diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d087528..ee9da12 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -209,6 +209,7 @@ typedef struct drm_i915_private { /* LVDS info */ int backlight_duty_cycle; /* restore backlight to this value */ bool panel_wants_dither; + bool lvds_is_dual_channel; struct drm_display_mode *panel_fixed_mode; struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 508838e..49785c8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -88,7 +88,7 @@ struct intel_limit { #define I8XX_P2_SLOW 4 #define I8XX_P2_FAST 2 #define I8XX_P2_LVDS_SLOW 14 -#define I8XX_P2_LVDS_FAST 14 /* No fast option */ +#define I8XX_P2_LVDS_FAST 7 #define I8XX_P2_SLOW_LIMIT 165000 #define I9XX_DOT_MIN 20000 @@ -509,8 +509,7 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) const intel_limit_t *limit; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { - if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) + if (dev_priv->lvds_is_dual_channel) /* LVDS with dual channel */ limit = &intel_limits_g4x_dual_channel_lvds; else @@ -644,16 +643,9 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, intel_clock_t clock; int err = target; - if (IS_I9XX(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && - (I915_READ(LVDS) & LVDS_PORT_EN) != 0) { - /* - * For LVDS, if the panel is on, just rely on its current - * settings for dual-channel. We haven't figured out how to - * reliably set up different single/dual channel state, if we - * even can. - */ - if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { + + if (dev_priv->lvds_is_dual_channel) clock.p2 = limit->p2.p2_fast; else clock.p2 = limit->p2.p2_slow; @@ -709,8 +701,8 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, found = false; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { - if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) + + if (dev_priv->lvds_is_dual_channel) clock.p2 = limit->p2.p2_fast; else clock.p2 = limit->p2.p2_slow; @@ -764,8 +756,8 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, found = false; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { - if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) + + if (dev_priv->lvds_is_dual_channel) clock.p2 = limit->p2.p2_fast; else clock.p2 = limit->p2.p2_slow; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 9ab38ef..9077d0e 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -848,6 +848,31 @@ static int intel_lid_present(void) } #endif +/* + * We determin lvds channel type based on panel fixed mode. + * The algorithm is from vbios code. + */ +static void intel_lvds_detect_channel_type(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int hdisplay, vdisplay; + + /* Default to Single Channel */ + dev_priv->lvds_is_dual_channel = false; + + hdisplay = 1280; + if (IS_GM45(dev)) + vdisplay = 801; /*vdisplay <= 800 is for single channel*/ + else + vdisplay = 1024; + + + if (dev_priv->panel_fixed_mode->hdisplay >= hdisplay && + dev_priv->panel_fixed_mode->vdisplay >= vdisplay) + dev_priv->lvds_is_dual_channel = true; + +} + /** * intel_lvds_init - setup LVDS connectors on this device * @dev: drm device @@ -1010,6 +1035,9 @@ out: I915_WRITE(BLC_PWM_PCH_CTL1, pwm); } drm_sysfs_connector_add(connector); + + intel_lvds_detect_channel_type(dev); + return; failed: