summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@nietzche.virtuousgeek.org>2008-07-17 14:41:51 -0700
committerZhenyu Wang <zhenyu.z.wang@intel.com>2008-07-21 11:14:35 +0800
commit37848925c4557385f154443ffbb917a8203506f8 (patch)
treec20db2a6c6f5710bca8c2342b84aaa795404198e
parent91cbb5b8ad1fbc22dd77c0329fc3962b1ca99b9e (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. (cherry picked from commit b8ca1c747a679c931267363639fc0bc690cae2d6)
-rw-r--r--src/i830_display.c75
-rw-r--r--src/i830_driver.c58
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);