diff --git a/src/i830.h b/src/i830.h index 3381c3c..4d344e8 100644 --- a/src/i830.h +++ b/src/i830.h @@ -290,6 +290,7 @@ typedef struct _I830OutputPrivateRec { Bool load_detect_temp; Bool needs_tv_clock; uint32_t lvds_bits; + Bool need_panel_off; int pipe_mask; int clone_mask; /** Output-private structure. Should replace i2c_drv */ diff --git a/src/i830_driver.c b/src/i830_driver.c index 16ddc41..4e2259f 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1060,6 +1060,8 @@ PreInitCleanup(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); + RestoreHWState(pScrn); + if (I830IsPrimary(pScrn)) { if (pI830->entityPrivate) pI830->entityPrivate->pScrn_1 = NULL; @@ -1602,7 +1604,6 @@ I830AccelMethodInit(ScrnInfoPtr pScrn) PreInitCleanup(pScrn); return FALSE; } - RestoreHWState(pScrn); /* XXX This should go away, replaced by xf86Crtc.c support for it */ pI830->rotation = RR_Rotate_0; diff --git a/src/i830_lvds.c b/src/i830_lvds.c index df92dea..f23ed90 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -622,7 +622,7 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, float horiz_ratio, vert_ratio; int left_border = 0, right_border = 0, top_border = 0, bottom_border = 0; int i; - Bool border = 0; + Bool border = 0, had_border = 0, had_pfit = 0; for (i = 0; i < xf86_config->num_output; i++) { xf86OutputPtr other_output = xf86_config->output[i]; @@ -837,6 +837,26 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, } out: + /* + * Need to power cycle the panel on pre-965 or if the border/panel fitting + * status changed or either are enabled. + */ + had_border = !!(intel_output->lvds_bits & LVDS_BORDER_ENABLE); + + if (!IS_I965G(pI830)) { + intel_output->need_panel_off = 1; + } else if (border || had_border) { + intel_output->need_panel_off = 1; + } else if ((pfit_control & PFIT_ENABLE) || + (dev_priv->pfit_control & PFIT_ENABLE)) { + intel_output->need_panel_off = 1; + } else { + intel_output->need_panel_off = 0; + } + + ErrorF("*** fixed up mode, need_panel_off %d, pfit_control 0x%08lx (old 0x%08lx), " + "border %d\n", intel_output->need_panel_off, pfit_control, dev_priv->pfit_control, border); + dev_priv->pfit_control = pfit_control; dev_priv->pfit_pgm_ratios = pfit_pgm_ratios; @@ -855,7 +875,24 @@ out: static void i830_lvds_prepare(xf86OutputPtr output) { - i830_lvds_dpms(output, DPMSModeOff); + I830OutputPrivatePtr intel_output = output->driver_private; + + /* + * 965+ chips can handle mode changes w/o turning off the panel in most + * cases. However, when timings change the panel *does* need to go off, + * and this only happens with centered modes. + */ + if (intel_output->need_panel_off) + i830_lvds_dpms(output, DPMSModeOff); +} + +static void +i830_lvds_commit(xf86OutputPtr output) +{ + I830OutputPrivatePtr intel_output = output->driver_private; + + if (intel_output->need_panel_off) + i830_lvds_dpms(output, DPMSModeOn); } static void @@ -1312,7 +1349,7 @@ static const xf86OutputFuncsRec i830_lvds_output_funcs = { .mode_fixup = i830_lvds_mode_fixup, .prepare = i830_lvds_prepare, .mode_set = i830_lvds_mode_set, - .commit = i830_output_commit, + .commit = i830_lvds_commit, .detect = i830_lvds_detect, .get_modes = i830_lvds_get_modes, #ifdef RANDR_12_INTERFACE