diff options
author | Dave Airlie <airlied@linux.ie> | 2006-05-09 20:44:14 +1000 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2006-06-02 10:03:10 +1000 |
commit | 1db93f295adf8ed80bc571ab24033235bf914a0c (patch) | |
tree | 7c67444d24f37e34d87257b1991236a941753aa7 | |
parent | 79957ca7c8b84711aa113bc727a9112fe718c8f7 (diff) |
add intel sdvo save/restore registers
-rw-r--r-- | src/i830_driver.c | 5 | ||||
-rw-r--r-- | src/i830_raw.c | 52 | ||||
-rw-r--r-- | src/i830_sdvo.c | 157 |
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) |