diff options
author | Jesse Barnes <jbarnes@nietzche.virtuousgeek.org> | 2008-07-17 14:41:51 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2008-07-18 08:30:26 -0700 |
commit | b8ca1c747a679c931267363639fc0bc690cae2d6 (patch) | |
tree | 455ef45b377f966e3a8b74d12be175482bba63f2 | |
parent | b37a2a8ca82279468e3806dcf77d5fa7bdd0e874 (diff) |
Choose a split for DSPARB based on the configured modes for both planes.
Previously, we were attempting to give both planes equal space in the FIFO
to be fair. However, larger modes require more fifo space, so split it based
on the relative HDisplay of the modes. This should resolve some fifo underrun
issues with differently-sized displays, or single large ones.
Bug #16169.
-rw-r--r-- | src/i830_display.c | 75 | ||||
-rw-r--r-- | src/i830_driver.c | 58 |
2 files changed, 75 insertions, 58 deletions
diff --git a/src/i830_display.c b/src/i830_display.c index 3967b69b..69bf7f77 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -1093,6 +1093,79 @@ 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_I9XX(pI830)) + OUTREG(DSPARB, + ((planea_entries + planeb_entries) << DSPARB_CSTART_SHIFT) | + (planea_entries << DSPARB_BSTART_SHIFT)); + else if (IS_MOBILE(pI830)) + OUTREG(DSPARB, + ((planea_entries + planeb_entries) << DSPARB_BEND_SHIFT) | + (planea_entries << DSPARB_AEND_SHIFT)); + else + OUTREG(DSPARB, 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 +1510,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 e29dd102..84aedba8 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); |