diff options
Diffstat (limited to 'src/i830_lvds.c')
-rw-r--r-- | src/i830_lvds.c | 158 |
1 files changed, 67 insertions, 91 deletions
diff --git a/src/i830_lvds.c b/src/i830_lvds.c index c7f24342..9f20579a 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -57,12 +57,6 @@ enum pfit_mode { }; struct i830_lvds_priv { - /* The BIOS's fixed timings for the LVDS */ - DisplayModePtr panel_fixed_mode; - - /* The panel needs dithering enabled */ - Bool panel_wants_dither; - /* The panel is in DPMS off */ Bool dpmsoff; @@ -486,9 +480,9 @@ i830_lvds_restore(xf86OutputPtr output) static int i830_lvds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) { - I830OutputPrivatePtr intel_output = output->driver_private; - struct i830_lvds_priv *dev_priv = intel_output->dev_priv; - DisplayModePtr pFixedMode = dev_priv->panel_fixed_mode; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr pFixedMode = pI830->lvds_fixed_mode; if (pFixedMode) { @@ -536,7 +530,7 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, } /* If we don't have a panel mode there's not much we can do */ - if (dev_priv->panel_fixed_mode == NULL) + if (pI830->lvds_fixed_mode == NULL) return TRUE; /* If we have timings from the BIOS for the panel, put them in @@ -544,19 +538,19 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, * with the panel scaling set up to source from the H/VDisplay * of the original mode. */ - adjusted_mode->HDisplay = dev_priv->panel_fixed_mode->HDisplay; - adjusted_mode->HSyncStart = dev_priv->panel_fixed_mode->HSyncStart; - adjusted_mode->HSyncEnd = dev_priv->panel_fixed_mode->HSyncEnd; - adjusted_mode->HTotal = dev_priv->panel_fixed_mode->HTotal; - adjusted_mode->VDisplay = dev_priv->panel_fixed_mode->VDisplay; - adjusted_mode->VSyncStart = dev_priv->panel_fixed_mode->VSyncStart; - adjusted_mode->VSyncEnd = dev_priv->panel_fixed_mode->VSyncEnd; - adjusted_mode->VTotal = dev_priv->panel_fixed_mode->VTotal; - adjusted_mode->Clock = dev_priv->panel_fixed_mode->Clock; + adjusted_mode->HDisplay = pI830->lvds_fixed_mode->HDisplay; + adjusted_mode->HSyncStart = pI830->lvds_fixed_mode->HSyncStart; + adjusted_mode->HSyncEnd = pI830->lvds_fixed_mode->HSyncEnd; + adjusted_mode->HTotal = pI830->lvds_fixed_mode->HTotal; + adjusted_mode->VDisplay = pI830->lvds_fixed_mode->VDisplay; + adjusted_mode->VSyncStart = pI830->lvds_fixed_mode->VSyncStart; + adjusted_mode->VSyncEnd = pI830->lvds_fixed_mode->VSyncEnd; + adjusted_mode->VTotal = pI830->lvds_fixed_mode->VTotal; + adjusted_mode->Clock = pI830->lvds_fixed_mode->Clock; xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V); /* Make sure pre-965s set dither correctly */ - if (!IS_I965G(pI830) && dev_priv->panel_wants_dither) + if (!IS_I965G(pI830) && pI830->lvds_dither) pfit_control |= PANEL_8TO6_DITHER_ENABLE; /* Native modes don't need fitting */ @@ -597,12 +591,12 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, * LVDS borders are enabled (see i830_display.c). */ left_border = - (dev_priv->panel_fixed_mode->HDisplay - mode->HDisplay) / 2; + (pI830->lvds_fixed_mode->HDisplay - mode->HDisplay) / 2; right_border = left_border; if (mode->HDisplay & 1) right_border++; top_border = - (dev_priv->panel_fixed_mode->VDisplay - mode->VDisplay) / 2; + (pI830->lvds_fixed_mode->VDisplay - mode->VDisplay) / 2; bottom_border = top_border; if (mode->VDisplay & 1) bottom_border++; @@ -661,7 +655,7 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, HORIZ_INTERP_BILINEAR; /* Pillar will have left/right borders */ - left_border = (dev_priv->panel_fixed_mode->HDisplay - + left_border = (pI830->lvds_fixed_mode->HDisplay - scaled_width) / 2; right_border = left_border; if (mode->HDisplay & 1) /* odd resolutions */ @@ -684,7 +678,7 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, HORIZ_INTERP_BILINEAR; /* Letterbox will have top/bottom borders */ - top_border = (dev_priv->panel_fixed_mode->VDisplay - + top_border = (pI830->lvds_fixed_mode->VDisplay - scaled_height) / 2; bottom_border = top_border; if (mode->VDisplay & 1) @@ -786,8 +780,9 @@ i830_lvds_detect(xf86OutputPtr output) static DisplayModePtr i830_lvds_get_modes(xf86OutputPtr output) { + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; - struct i830_lvds_priv *dev_priv = intel_output->dev_priv; xf86MonPtr edid_mon; DisplayModePtr modes; @@ -816,8 +811,8 @@ i830_lvds_get_modes(xf86OutputPtr output) } } - if (dev_priv->panel_fixed_mode != NULL) - return xf86DuplicateMode(dev_priv->panel_fixed_mode); + if (pI830->lvds_fixed_mode != NULL) + return xf86DuplicateMode(pI830->lvds_fixed_mode); return NULL; } @@ -825,13 +820,13 @@ i830_lvds_get_modes(xf86OutputPtr output) static void i830_lvds_destroy (xf86OutputPtr output) { + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; - if (intel_output) + if (pI830->lvds_fixed_mode) { - struct i830_lvds_priv *dev_priv = intel_output->dev_priv; - - xf86DeleteMode (&dev_priv->panel_fixed_mode, dev_priv->panel_fixed_mode); + xf86DeleteMode (&pI830->lvds_fixed_mode, pI830->lvds_fixed_mode); xfree (intel_output); } } @@ -1217,7 +1212,8 @@ i830_lvds_init(ScrnInfoPtr pScrn) I830Ptr pI830 = I830PTR(pScrn); xf86OutputPtr output; I830OutputPrivatePtr intel_output; - DisplayModePtr modes, scan, bios_mode; + DisplayModePtr modes, scan; + DisplayModePtr lvds_ddc_mode; struct i830_lvds_priv *dev_priv; if (pI830->quirk_flag & QUIRK_IGNORE_LVDS) @@ -1244,17 +1240,27 @@ i830_lvds_init(ScrnInfoPtr pScrn) dev_priv = (struct i830_lvds_priv *) (intel_output + 1); intel_output->dev_priv = dev_priv; + + /* + * Mode detection algorithms for LFP: + * 1) if EDID present, use it, done + * 2) if VBT present, use it, done + * 3) if current mode is programmed, use it, done + * 4) check for Mac mini & other quirks + * 4) fail, assume no LFP + */ /* Set up the LVDS DDC channel. Most panels won't support it, but it can * be useful if available. */ I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOC, "LVDSDDC_C"); - if (!pI830->lvds_fixed_mode) { + if (!pI830->skip_panel_detect) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Skipping any attempt to determine panel fixed mode.\n"); - goto skip_panel_fixed_mode_setup; + goto found_mode; } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Attempting to determine panel fixed mode.\n"); @@ -1274,77 +1280,47 @@ i830_lvds_init(ScrnInfoPtr pScrn) scan->prev = scan->next; if (scan->next != NULL) scan->next = scan->prev; - dev_priv->panel_fixed_mode = scan; + lvds_ddc_mode = scan; } /* Delete the mode list */ while (modes != NULL) xf86DeleteMode(&modes, modes); - /* If we didn't get EDID, try checking if the panel is already turned on. - * If so, assume that whatever is currently programmed is the correct mode. - */ - if (dev_priv->panel_fixed_mode == NULL) { - uint32_t lvds = INREG(LVDS); - int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86CrtcPtr crtc = xf86_config->crtc[pipe]; - - if (lvds & LVDS_PORT_EN) { - dev_priv->panel_fixed_mode = i830_crtc_mode_get(pScrn, crtc); - if (dev_priv->panel_fixed_mode != NULL) - dev_priv->panel_fixed_mode->type |= M_T_PREFERRED; - } + if (lvds_ddc_mode) { + pI830->lvds_fixed_mode = lvds_ddc_mode; + goto found_mode; } /* Get the LVDS fixed mode out of the BIOS. We should support LVDS with * the BIOS being unavailable or broken, but lack the configuration options * for now. */ - bios_mode = i830_bios_get_panel_mode(pScrn, &dev_priv->panel_wants_dither); - if (bios_mode != NULL) { - if (dev_priv->panel_fixed_mode != NULL) { - /* Fixup for a 1280x768 panel with the horizontal trimmed - * down to 1024 for text mode. - */ - if (!xf86ModesEqual(dev_priv->panel_fixed_mode, bios_mode) && - dev_priv->panel_fixed_mode->HDisplay == 1024 && - dev_priv->panel_fixed_mode->HSyncStart == 1200 && - dev_priv->panel_fixed_mode->HSyncEnd == 1312 && - dev_priv->panel_fixed_mode->HTotal == 1688 && - dev_priv->panel_fixed_mode->VDisplay == 768) - { - dev_priv->panel_fixed_mode->HDisplay = 1280; - dev_priv->panel_fixed_mode->HSyncStart = 1328; - dev_priv->panel_fixed_mode->HSyncEnd = 1440; - dev_priv->panel_fixed_mode->HTotal = 1688; - } + if (pI830->lvds_fixed_mode) + goto found_mode; + + /* If we *still* don't have a mode, try checking if the panel is already + * turned on. If so, assume that whatever is currently programmed is the + * correct mode. + */ + if (!pI830->lvds_fixed_mode) { + uint32_t lvds = INREG(LVDS); + int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc = xf86_config->crtc[pipe]; - if (pI830->debug_modes && - !xf86ModesEqual(dev_priv->panel_fixed_mode, bios_mode)) - { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "BIOS panel mode data doesn't match probed data, " - "continuing with probed.\n"); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS mode:\n"); - xf86PrintModeline(pScrn->scrnIndex, bios_mode); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "probed mode:\n"); - xf86PrintModeline(pScrn->scrnIndex, dev_priv->panel_fixed_mode); - xfree(bios_mode->name); - xfree(bios_mode); + if (lvds & LVDS_PORT_EN) { + pI830->lvds_fixed_mode = i830_crtc_mode_get(pScrn, crtc); + if (pI830->lvds_fixed_mode != NULL) { + pI830->lvds_fixed_mode->type |= M_T_PREFERRED; + goto found_mode; } - } else { - dev_priv->panel_fixed_mode = bios_mode; } - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Couldn't detect panel mode. Disabling panel\n"); - goto disable_exit; } - /* Update pI830 w/SSC info, if any */ - i830_bios_get_ssc(pScrn); + if (!pI830->lvds_fixed_mode) + goto disable_exit; - skip_panel_fixed_mode_setup: +found_mode: /* Blacklist machines with BIOSes that list an LVDS panel without actually * having one. @@ -1359,9 +1335,9 @@ i830_lvds_init(ScrnInfoPtr pScrn) * display. */ - if (dev_priv->panel_fixed_mode != NULL && - dev_priv->panel_fixed_mode->HDisplay == 800 && - dev_priv->panel_fixed_mode->VDisplay == 600) + if (pI830->lvds_fixed_mode != NULL && + pI830->lvds_fixed_mode->HDisplay == 800 && + pI830->lvds_fixed_mode->VDisplay == 600) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Suspected Mac Mini, ignoring the LVDS\n"); |