diff --git a/src/i830_display.c b/src/i830_display.c index 3967b69..5a5418a 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -1093,6 +1093,81 @@ i830_panel_fitter_pipe(I830Ptr pI830) } /** + * Sets up the DSPARB register to split the display fifo appropriately between + * the display planes. + * + * Adjusting this register requires that the planes be off. + */ +static void +i830_update_dsparb(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + I830Ptr pI830 = I830PTR(pScrn); + uint32_t dspacntr, dspbcntr; + int total_hdisplay = 0, planea_hdisplay = 0, planeb_hdisplay = 0; + int fifo_entries = 0, planea_entries = 0, planeb_entries = 0, i; + + dspacntr = INREG(DSPACNTR); + dspbcntr = INREG(DSPBCNTR); + + /* Disable planes since DSPARB can only be updated when they're + * off. + */ + OUTREG(DSPACNTR, dspacntr & ~DISPLAY_PLANE_ENABLE); + OUTREG(DSPBCNTR, dspbcntr & ~DISPLAY_PLANE_ENABLE); + i830WaitForVblank(pScrn); + + /* + * FIFO entries will be split based on programmed modes + */ + if (IS_I965GM(pI830) || IS_GM45(pI830)) + fifo_entries = 127; + else if (IS_I9XX(pI830)) + fifo_entries = 95; + else if (IS_MOBILE(pI830)) { + fifo_entries = 255; + } else { + /* The 845/865 only have a AEND field. Though the field size would + * allow 128 entries, the 865 rendered the cursor wrong then. + * The BIOS set it up for 96. + */ + fifo_entries = 95; + } + + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + if (crtc->enabled) { + total_hdisplay += crtc->mode.HDisplay; + if (intel_crtc->plane == 0) + planea_hdisplay = crtc->mode.HDisplay; + else + planeb_hdisplay = crtc->mode.HDisplay; + } + } + + planea_entries = fifo_entries * planea_hdisplay / total_hdisplay; + planeb_entries = fifo_entries * planeb_hdisplay / total_hdisplay; + + if (IS_I965GM(pI830) || IS_GM45(pI830)) + OUTREG(DSPARB, + ((planea_entries + planeb_entries) << DSPARB_CSTART_SHIFT) | + (planea_entries << DSPARB_BSTART_SHIFT)); + else if (IS_I9XX(pI830)) + OUTREG(DSPARB, + ((planea_entries + planeb_entries) << DSPARB_CSTART_SHIFT) | + (planea_entries << DSPARB_BSTART_SHIFT)); + else + OUTREG(DSPARB, + ((planea_entries + planeb_entries) << DSPARB_BEND_SHIFT) | + (planea_entries << DSPARB_AEND_SHIFT)); + + OUTREG(DSPACNTR, dspacntr); + OUTREG(DSPBCNTR, dspbcntr); + i830WaitForVblank(pScrn); +} + +/** * Sets up registers for the given mode/adjusted_mode pair. * * The clocks, CRTCs and outputs attached to this CRTC must be off. @@ -1437,6 +1512,8 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, i830WaitForVblank(pScrn); + i830_update_dsparb(pScrn); + /* Clear any FIFO underrun status that may have occurred normally */ OUTREG(pipestat_reg, INREG(pipestat_reg) | FIFO_UNDERRUN); } diff --git a/src/i830_driver.c b/src/i830_driver.c index e29dd10..84aedba 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1954,59 +1954,6 @@ i830_refresh_ring(ScrnInfoPtr pScrn) i830MarkSync(pScrn); } -/** - * Sets up the DSPARB register to split the display fifo appropriately between - * the display planes. - * - * Adjusting this register requires that the planes be off, thus as a side - * effect they are disabled by this function. - */ -static void -i830_set_dsparb(ScrnInfoPtr pScrn) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - I830Ptr pI830 = I830PTR(pScrn); - int i; - - /* Disable outputs & pipes since DSPARB can only be updated when they're - * off. - */ - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - output->funcs->dpms(output, DPMSModeOff); - } - i830WaitForVblank(pScrn); - for (i = 0; i < xf86_config->num_crtc; i++) { - xf86CrtcPtr crtc = xf86_config->crtc[i]; - crtc->funcs->dpms(crtc, DPMSModeOff); - } - i830WaitForVblank(pScrn); - - /* Fixup FIFO defaults: - * we don't use plane C at all so we can allocate all but one of the 96 - * FIFO RAM entries equally between planes A and B. - */ - if (IS_I9XX(pI830)) { - if (IS_I965GM(pI830) || IS_GM45(pI830)) - OUTREG(DSPARB, (127 << DSPARB_CSTART_SHIFT) | - (64 << DSPARB_BSTART_SHIFT)); - else - OUTREG(DSPARB, (95 << DSPARB_CSTART_SHIFT) | - (48 << DSPARB_BSTART_SHIFT)); - } else { - if (IS_MOBILE(pI830)) { - /* The 830 has 288 entries, and the 855 has 256. */ - OUTREG(DSPARB, 254 << DSPARB_BEND_SHIFT | 128 << DSPARB_AEND_SHIFT); - } else { - /* The 845/865 only have a AEND field. Though the field size would - * allow 128 entries, the 865 rendered the cursor wrong then. - * The BIOS set it up for 96. - */ - OUTREG(DSPARB, 95 << DSPARB_AEND_SHIFT); - } - } -} - enum pipe { PIPE_A = 0, PIPE_B, @@ -3416,11 +3363,6 @@ I830EnterVT(int scrnIndex, int flags) if (!pI830->SWCursor) I830InitHWCursor(pScrn); - /* Set the DSPARB register. This disables the outputs, which is about to - * happen (likely) in xf86SetDesiredModes anyway. - */ - i830_set_dsparb(pScrn); - /* Tell the BIOS that we're in control of mode setting now. */ i830_init_bios_control(pScrn);