summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2006-05-09 20:44:14 +1000
committerDave Airlie <airlied@linux.ie>2006-06-02 10:03:10 +1000
commit1db93f295adf8ed80bc571ab24033235bf914a0c (patch)
tree7c67444d24f37e34d87257b1991236a941753aa7
parent79957ca7c8b84711aa113bc727a9112fe718c8f7 (diff)
add intel sdvo save/restore registers
-rw-r--r--src/i830_driver.c5
-rw-r--r--src/i830_raw.c52
-rw-r--r--src/i830_sdvo.c157
3 files changed, 208 insertions, 6 deletions
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 758e765d..11e92494 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -4148,9 +4148,6 @@ SaveHWState(ScrnInfoPtr pScrn)
if (pI830->rawmode)
{
- vgaHWUnlock(hwp);
- vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS);
-
I830RawSaveState(pScrn, &pI830->SavedReg);
for (i=0; i<8; i++)
pI830->SavedReg.Fence[i] = pI830->ModeReg.Fence[i];
@@ -4236,8 +4233,6 @@ RestoreHWState(ScrnInfoPtr pScrn)
if (pI830->rawmode)
{
I830RawRestoreState(pScrn, &pI830->SavedReg);
- vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
- vgaHWLock(hwp);
return TRUE;
}
diff --git a/src/i830_raw.c b/src/i830_raw.c
index b20a0674..4f53c73a 100644
--- a/src/i830_raw.c
+++ b/src/i830_raw.c
@@ -706,7 +706,10 @@ Bool
I830RawSaveState(ScrnInfoPtr pScrn, I830RegPtr hw)
{
I830Ptr pI830 = I830PTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ vgaRegPtr vgaReg = &hwp->SavedReg;
int i, count;
+
hw->vga0_divisor = INREG(VCLK_DIVISOR_VGA0);
hw->vga1_divisor = INREG(VCLK_DIVISOR_VGA1);
hw->vga_pd = INREG(VCLK_POST_DIV);
@@ -765,6 +768,17 @@ I830RawSaveState(ScrnInfoPtr pScrn, I830RegPtr hw)
for (count = 0, i = SWF10; i<SWF16; i+=4)
hw->swf1x[count++] = INREG(i);
+
+ for (i = 0; i < pI830->num_outputs; i++) {
+ if (pI830->output[i].type == I830_OUTPUT_SDVO &&
+ pI830->output[i].sdvo_drv != NULL)
+ {
+ i830SDVOSave(pScrn, i);
+ }
+ }
+
+ vgaHWUnlock(hwp);
+ vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
return TRUE;
}
@@ -773,6 +787,36 @@ Bool
I830RawRestoreState(ScrnInfoPtr pScrn, I830RegPtr hw)
{
I830Ptr pI830 = I830PTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ vgaRegPtr vgaReg = &hwp->SavedReg;
+ CARD32 temp;
+ int i;
+
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
+ vgaHWLock(hwp);
+
+ /* First, disable display planes */
+ temp = INREG(DSPACNTR);
+ OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE);
+ temp = INREG(DSPBCNTR);
+ OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
+
+ /* Next, disable display pipes */
+ temp = INREG(PIPEACONF);
+ OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE);
+ temp = INREG(PIPEBCONF);
+ OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
+
+ /* XXX: Wait for a vblank */
+ sleep(1);
+
+ for (i = 0; i < pI830->num_outputs; i++) {
+ if (pI830->output[i].type == I830_OUTPUT_SDVO &&
+ pI830->output[i].sdvo_drv != NULL)
+ {
+ i830SDVOPreRestore(pScrn, i);
+ }
+ }
OUTREG(VCLK_DIVISOR_VGA0, hw->vga0_divisor);
OUTREG(VCLK_DIVISOR_VGA1, hw->vga1_divisor);
@@ -807,6 +851,14 @@ I830RawRestoreState(ScrnInfoPtr pScrn, I830RegPtr hw)
OUTREG(DSPBSTRIDE, hw->disp_b_stride);
OUTREG(VGACNTRL, hw->vgacntrl);
+
+ for (i = 0; i < pI830->num_outputs; i++) {
+ if (pI830->output[i].type == I830_OUTPUT_SDVO &&
+ pI830->output[i].sdvo_drv != NULL)
+ {
+ i830SDVOPostRestore(pScrn, i);
+ }
+ }
return TRUE;
}
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index b5f6bda1..34b14b80 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -278,7 +278,7 @@ I830SDVOSetTimingsPart1(I830SDVOPtr s, char cmd, unsigned short clock, CARD16 ma
s->sdvo_regs[SDVO_I2C_ARG_7] = (magic1 >> 8) & 0xff;
- I830SDVOWriteOutputs(s, 7);
+ I830SDVOWriteOutputs(s, 8);
I830SDVOReadInputRegs(s);
return TRUE;
@@ -389,6 +389,29 @@ I830SDVOGetPreferredInputTimingPart2(I830SDVOPtr s)
return TRUE;
}
+static int
+I830SDVOGetClockRateMult(I830SDVOPtr s)
+{
+ memset(s->sdvo_regs, 0, 9);
+
+ s->sdvo_regs[SDVO_I2C_OPCODE] = SDVO_CMD_GET_CLOCK_RATE_MULT;
+
+ I830SDVOWriteOutputs(s, 0);
+ I830SDVOReadInputRegs(s);
+
+ if (s->sdvo_regs[SDVO_I2C_CMD_STATUS] != SDVO_CMD_STATUS_SUCCESS) {
+ xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_ERROR,
+ "Couldn't get SDVO clock rate multiplier\n");
+ return SDVO_CLOCK_RATE_MULT_1X;
+ } else {
+ xf86DrvMsg(s->d.pI2CBus->scrnIndex, X_INFO,
+ "Current clock rate multiplier: %d\n",
+ s->sdvo_regs[SDVO_I2C_RETURN_0]);
+ }
+
+ return s->sdvo_regs[SDVO_I2C_RETURN_0];
+}
+
static Bool
I830SDVOSetClockRateMult(I830SDVOPtr s, unsigned char val)
{
@@ -403,6 +426,75 @@ I830SDVOSetClockRateMult(I830SDVOPtr s, unsigned char val)
return TRUE;
}
+
+/* Fetches either input or output timings to *dtd, depending on cmd. */
+Bool
+I830SDVOGetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd)
+{
+ memset(s->sdvo_regs, 0, 9);
+ s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+ I830SDVOWriteOutputs(s, 0);
+ I830SDVOReadInputRegs(s);
+
+ dtd->clock = s->sdvo_regs[SDVO_I2C_RETURN_0] |
+ (s->sdvo_regs[SDVO_I2C_RETURN_1] << 8);
+ dtd->h_active = s->sdvo_regs[SDVO_I2C_RETURN_2];
+ dtd->h_blank = s->sdvo_regs[SDVO_I2C_RETURN_3];
+ dtd->h_high = s->sdvo_regs[SDVO_I2C_RETURN_4];
+ dtd->v_active = s->sdvo_regs[SDVO_I2C_RETURN_5];
+ dtd->v_blank = s->sdvo_regs[SDVO_I2C_RETURN_6];
+ dtd->v_high = s->sdvo_regs[SDVO_I2C_RETURN_7];
+
+ memset(s->sdvo_regs, 0, 9);
+ s->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1;
+ I830SDVOWriteOutputs(s, 0);
+ I830SDVOReadInputRegs(s);
+
+ dtd->h_sync_off = s->sdvo_regs[SDVO_I2C_RETURN_0];
+ dtd->h_sync_width = s->sdvo_regs[SDVO_I2C_RETURN_1];
+ dtd->v_sync_off_width = s->sdvo_regs[SDVO_I2C_RETURN_2];
+ dtd->sync_off_width_high = s->sdvo_regs[SDVO_I2C_RETURN_3];
+ dtd->dtd_flags = s->sdvo_regs[SDVO_I2C_RETURN_4];
+ dtd->sdvo_flags = s->sdvo_regs[SDVO_I2C_RETURN_5];
+ dtd->v_sync_off_high = s->sdvo_regs[SDVO_I2C_RETURN_6];
+ dtd->reserved = s->sdvo_regs[SDVO_I2C_RETURN_7];
+
+ return TRUE;
+}
+
+/* Fetches either input or output timings to *dtd, depending on cmd. */
+Bool
+I830SDVOSetTimings(I830SDVOPtr s, i830_sdvo_dtd *dtd, CARD8 cmd)
+{
+ memset(s->sdvo_regs, 0, 9);
+ s->sdvo_regs[SDVO_I2C_OPCODE] = cmd;
+ s->sdvo_regs[SDVO_I2C_ARG_0] = dtd->clock & 0xff;
+ s->sdvo_regs[SDVO_I2C_ARG_1] = dtd->clock >> 8;
+ s->sdvo_regs[SDVO_I2C_ARG_2] = dtd->h_active;
+ s->sdvo_regs[SDVO_I2C_ARG_3] = dtd->h_blank;
+ s->sdvo_regs[SDVO_I2C_ARG_4] = dtd->h_high;
+ s->sdvo_regs[SDVO_I2C_ARG_5] = dtd->v_active;
+ s->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_blank;
+ s->sdvo_regs[SDVO_I2C_ARG_7] = dtd->v_high;
+ I830SDVOWriteOutputs(s, 8);
+ I830SDVOReadInputRegs(s);
+
+ memset(s->sdvo_regs, 0, 9);
+ s->sdvo_regs[SDVO_I2C_OPCODE] = cmd + 1;
+ s->sdvo_regs[SDVO_I2C_ARG_0] = dtd->h_sync_off;
+ s->sdvo_regs[SDVO_I2C_ARG_1] = dtd->h_sync_width;
+ s->sdvo_regs[SDVO_I2C_ARG_2] = dtd->v_sync_off_width;
+ s->sdvo_regs[SDVO_I2C_ARG_3] = dtd->sync_off_width_high;
+ s->sdvo_regs[SDVO_I2C_ARG_4] = dtd->dtd_flags;
+ s->sdvo_regs[SDVO_I2C_ARG_5] = dtd->sdvo_flags;
+ s->sdvo_regs[SDVO_I2C_ARG_6] = dtd->v_sync_off_high;
+ s->sdvo_regs[SDVO_I2C_ARG_7] = dtd->reserved;
+ I830SDVOWriteOutputs(s, 8);
+ I830SDVOReadInputRegs(s);
+
+ return TRUE;
+}
+
Bool
I830SDVOPreSetMode(I830SDVOPtr s, DisplayModePtr mode)
{
@@ -502,6 +594,69 @@ I830SDVOPostSetMode(I830SDVOPtr s, DisplayModePtr mode)
return ret;
}
+void
+i830SDVOSave(ScrnInfoPtr pScrn, int output_index)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
+
+ sdvo->save_sdvo_mult = I830SDVOGetClockRateMult(sdvo);
+ I830SDVOGetActiveOutputs(sdvo, &sdvo->save_sdvo_active_1,
+ &sdvo->save_sdvo_active_2);
+
+ I830SDVOSetTargetInput(sdvo, TRUE, FALSE);
+ I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_1,
+ SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+ I830SDVOSetTargetInput(sdvo, FALSE, TRUE);
+ I830SDVOGetTimings(sdvo, &sdvo->save_input_dtd_2,
+ SDVO_CMD_GET_INPUT_TIMINGS_PART1);
+
+ I830SDVOSetTargetOutput(sdvo, TRUE, FALSE);
+ I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_1,
+ SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+ I830SDVOSetTargetOutput(sdvo, FALSE, TRUE);
+ I830SDVOGetTimings(sdvo, &sdvo->save_output_dtd_2,
+ SDVO_CMD_GET_OUTPUT_TIMINGS_PART1);
+
+ sdvo->save_SDVOX = INREG(sdvo->output_device);
+}
+
+void
+i830SDVOPreRestore(ScrnInfoPtr pScrn, int output_index)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
+
+ I830SDVOSetActiveOutputs(sdvo, FALSE, FALSE);
+}
+
+void
+i830SDVOPostRestore(ScrnInfoPtr pScrn, int output_index)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ I830SDVOPtr sdvo = pI830->output[output_index].sdvo_drv;
+
+ I830SDVOSetTargetInput(sdvo, TRUE, FALSE);
+ I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_1,
+ SDVO_CMD_SET_INPUT_TIMINGS_PART1);
+ I830SDVOSetTargetInput(sdvo, FALSE, TRUE);
+ I830SDVOSetTimings(sdvo, &sdvo->save_input_dtd_2,
+ SDVO_CMD_SET_INPUT_TIMINGS_PART1);
+
+ I830SDVOSetTargetOutput(sdvo, TRUE, FALSE);
+ I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_1,
+ SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
+ I830SDVOSetTargetOutput(sdvo, FALSE, TRUE);
+ I830SDVOSetTimings(sdvo, &sdvo->save_output_dtd_2,
+ SDVO_CMD_SET_OUTPUT_TIMINGS_PART1);
+
+ I830SDVOSetClockRateMult(sdvo, sdvo->save_sdvo_mult);
+
+ OUTREG(sdvo->output_device, sdvo->save_SDVOX);
+
+ I830SDVOSetActiveOutputs(sdvo, sdvo->save_sdvo_active_1,
+ sdvo->save_sdvo_active_2);
+}
static Bool
I830SDVODDCI2CGetByte(I2CDevPtr d, I2CByte *data, Bool last)