From patchwork Thu Mar 17 13:58:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Isely X-Patchwork-Id: 641481 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p2HE59Ko017823 for ; Thu, 17 Mar 2011 14:05:29 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id F2AA49EB23 for ; Thu, 17 Mar 2011 07:05:08 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from cnc.isely.net (cnc.isely.net [75.149.91.89]) by gabe.freedesktop.org (Postfix) with ESMTP id 96F959EB44 for ; Thu, 17 Mar 2011 07:03:32 -0700 (PDT) Received: from cnc.isely.net (cnc.isely.net [::ffff:192.168.23.2]) (IDENT: isely, TLS: TLSv1/SSLv3,256bits,AES256-SHA) by cnc.isely.net with esmtp; Thu, 17 Mar 2011 08:58:14 -0500 id 0000000000132355.000000004D821376.0000628B Date: Thu, 17 Mar 2011 08:58:13 -0500 (CDT) From: Mike Isely To: intel-gfx@lists.freedesktop.org Message-ID: User-Agent: Alpine 1.10 (DEB 962 2008-03-14) Mime-Version: 1.0 Cc: Mike Isely at pobox Subject: [Intel-gfx] [PATCH 3/3] [drm/i915] - Implement manual override of LVDS single/dual channel mode X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list Reply-To: Mike Isely at pobox List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Thu, 17 Mar 2011 14:05:29 +0000 (UTC) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 004880aa3a948669b8b4e23d9ad73d132cff81d0..1d88f059a27321ecb681e2b7927bb69029fcb49a 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -49,6 +49,10 @@ module_param_named(powersave, i915_powersave, int, 0600); unsigned int i915_lvds_fixed = 1; module_param_named(lvds_fixed, i915_lvds_fixed, int, 0600); +unsigned int i915_lvds_channels = 0; +module_param_named(lvds_channels, i915_lvds_channels, int, 0600); +MODULE_PARM_DESC(lvds_channels, "LVDS channels in use: 0=(default) probe hardware 1=single 2=dual"); + unsigned int i915_lvds_downclock = 0; module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3fa8681459aa596e12e885568e5b48f0c9a60719..a6aab43e5f39f2d5b92a69a284bf8f72a254ea7c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -886,6 +886,7 @@ extern int i915_max_ioctl; extern unsigned int i915_fbpercrtc; extern unsigned int i915_powersave; extern unsigned int i915_lvds_fixed; +extern unsigned int i915_lvds_channels; extern unsigned int i915_lvds_downclock; extern unsigned int i915_lvds_24bit; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 09f57f29c30c371c213944be473090a780a287db..4dc91400edd8935be45a229cf91292339bca0ce8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -642,6 +642,20 @@ static const intel_limit_t intel_limits_ironlake_display_port = { .find_pll = intel_find_pll_ironlake_dp, }; +static int intel_is_dual_channel_mode(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + if (i915_lvds_channels) { + /* User has specified desired channel mode */ + return (i915_lvds_channels == 2); + } + + /* User has not specified mode so let's see + what the hardware is doing. */ + return ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP); +} + static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -653,8 +667,7 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc) if (dev_priv->lvds_use_ssc && dev_priv->lvds_ssc_freq == 100) refclk = 100; - if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) { + if (intel_is_dual_channel_mode(crtc)) { /* LVDS dual channel */ if (refclk == 100) limit = &intel_limits_ironlake_dual_lvds_100m; @@ -677,18 +690,16 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc) static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; 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 (intel_is_dual_channel_mode(crtc)) { /* LVDS with dual channel */ limit = &intel_limits_g4x_dual_channel_lvds; - else - /* LVDS with dual channel */ + } else { + /* LVDS with single channel */ limit = &intel_limits_g4x_single_channel_lvds; + } } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { limit = &intel_limits_g4x_hdmi; @@ -821,8 +832,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, * 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_is_dual_channel_mode(crtc)) clock.p2 = limit->p2.p2_fast; else clock.p2 = limit->p2.p2_slow; @@ -871,7 +881,6 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock) { struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; intel_clock_t clock; int max_n; bool found; @@ -886,8 +895,7 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, lvds_reg = PCH_LVDS; else lvds_reg = LVDS; - if ((I915_READ(lvds_reg) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) + if (intel_is_dual_channel_mode(crtc)) clock.p2 = limit->p2.p2_fast; else clock.p2 = limit->p2.p2_slow;