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 @@ -1092,6 +1092,79 @@ i830_panel_fitter_pipe(I830Ptr pI830) return 1; } +/** + * 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. * @@ -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 b44db7ec..03861a91 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1952,59 +1952,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, @@ -3503,11 +3450,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); diff --git a/src/i830_quirks.c b/src/i830_quirks.c index 5eb01be5..3becf357 100644 --- a/src/i830_quirks.c +++ b/src/i830_quirks.c @@ -309,6 +309,9 @@ static i830_quirk i830_quirk_list[] = { /* Littlebit Sepia X35 (rebranded Asus Z37E) (See LP: #201257) */ { PCI_CHIP_I965_GM, 0x1043, 0x8265, quirk_ignore_tv }, + /* 855 & before need to leave pipe A & dpll A up */ + { PCI_CHIP_I855_GM, SUBSYS_ANY, SUBSYS_ANY, quirk_pipea_force }, + { 0, 0, 0, NULL }, }; @@ -325,9 +328,10 @@ void i830_fixup_devices(ScrnInfoPtr scrn) while (p && p->chipType != 0) { if (DEVICE_ID(pI830->PciInfo) == p->chipType && - SUBVENDOR_ID(pI830->PciInfo) == p->subsysVendor && - (SUBSYS_ID(pI830->PciInfo) == p->subsysCard || - p->subsysCard == SUBSYS_ANY)) + (SUBVENDOR_ID(pI830->PciInfo) == p->subsysVendor || + p->subsysVendor == SUBSYS_ANY) && + (SUBSYS_ID(pI830->PciInfo) == p->subsysCard || + p->subsysCard == SUBSYS_ANY)) p->hook(pI830); ++p; }