All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chris Wilson <chris@chris-wilson.co.uk>
To: intel-gfx@lists.freedesktop.org
Subject: [PATCH 10/21] drm/i915: Implement manual override of LVDS single/dual channel mode
Date: Sat, 16 Apr 2011 10:17:34 +0100	[thread overview]
Message-ID: <1302945465-32115-11-git-send-email-chris@chris-wilson.co.uk> (raw)
In-Reply-To: <1302945465-32115-1-git-send-email-chris@chris-wilson.co.uk>

From: Mike Isely <isely@isely.net>

The logic for LVDS setup in the Intel driver needs to know whether the
LVDS port should be in single or dual channel mode when calculating
video timing.  It had been answering this question by probing the
current hardware configuration, under the assumption that the video
BIOS would have already set it up.  But the video BIOS would actually
have to know how to set up the LVDS port for the connected device,
which is a bad assumption if the display device is not integral to the
processor board - a situation that can exist for embedded situation.
This is yet one more case where the Intel driver had been implicitly
relying on the video BIOS for display configuration.

This changes creates a new kernel option, lvds_channels, which can be
used to override the probe.  Setting this allows the user to specify
the number of channels in use, avoiding the possibly erroneous probe
of the hardware.  Almost nobody should ever need to touch this option,
and its default value of zero is interpreted to preserve existing
probe-the-hardware behavior.  But if the video BIOS gets this "wrong",
then it can be overridden by setting lvds_channels to 1 or 2,
indicating single or dual channel LVDS mode, respectively.

Signed-off-by: Mike Isely <isely@isely.net>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_drv.c      |    4 ++++
 drivers/gpu/drm/i915/i915_drv.h      |    1 +
 drivers/gpu/drm/i915/intel_display.c |   32 +++++++++++++++++---------------
 3 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 49d38b0..0acc995 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -71,6 +71,10 @@ unsigned int i915_lvds_24bit = 0;
 module_param_named(lvds_24bit, i915_lvds_24bit, int, 0600);
 MODULE_PARM_DESC(lvds_24bit, "LVDS 24 bit pixel format: 0=leave untouched (default), 1=24 bit '2.0' format, 2=24 bit '2.1' format, 3=force older 18 bit format");
 
+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");
+
 static struct drm_driver driver;
 extern int intel_agp_enabled;
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7cd63bb..76e111c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -977,6 +977,7 @@ extern unsigned int i915_fbpercrtc;
 extern int i915_panel_ignore_lid;
 extern unsigned int i915_powersave;
 extern unsigned int i915_semaphores;
+extern unsigned int i915_lvds_channels;
 extern unsigned int i915_lvds_downclock;
 extern unsigned int i915_panel_use_ssc;
 extern int i915_vbt_sdvo_panel_type;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a21d3666..29b292c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -354,6 +354,17 @@ static const intel_limit_t intel_limits_ironlake_display_port = {
         .find_pll = intel_find_pll_ironlake_dp,
 };
 
+static bool intel_lvds_is_dual_channel_mode(struct drm_i915_private *dev_priv,
+					    int lvds_reg)
+{
+	/* Did the user specify the number of channels? */
+	if (i915_lvds_channels)
+		return i915_lvds_channels == 2;
+
+	/* No, let's probe the current status of the hardware instead. */
+	return (I915_READ(lvds_reg) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
+}
+
 static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
 						int refclk)
 {
@@ -362,8 +373,7 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
 	const intel_limit_t *limit;
 
 	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-		if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) ==
-		    LVDS_CLKB_POWER_UP) {
+		if (intel_lvds_is_dual_channel_mode(dev_priv, PCH_LVDS)) {
 			/* LVDS dual channel */
 			if (refclk == 100000)
 				limit = &intel_limits_ironlake_dual_lvds_100m;
@@ -391,8 +401,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 (intel_lvds_is_dual_channel_mode(dev_priv, LVDS))
 			/* LVDS with dual channel */
 			limit = &intel_limits_g4x_dual_channel_lvds;
 		else
@@ -523,14 +532,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 
 	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
 	    (I915_READ(LVDS)) != 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_lvds_is_dual_channel_mode(dev_priv, LVDS))
 			clock.p2 = limit->p2.p2_fast;
 		else
 			clock.p2 = limit->p2.p2_slow;
@@ -594,8 +596,8 @@ 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_lvds_is_dual_channel_mode(dev_priv, lvds_reg))
 			clock.p2 = limit->p2.p2_fast;
 		else
 			clock.p2 = limit->p2.p2_slow;
@@ -4913,7 +4915,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	if (is_lvds) {
 		if ((intel_panel_use_ssc(dev_priv) &&
 		     dev_priv->lvds_ssc_freq == 100) ||
-		    (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+		    intel_lvds_is_dual_channel_mode(dev_priv, PCH_LVDS))
 			factor = 25;
 	} else if (is_sdvo && is_tv)
 		factor = 20;
-- 
1.7.4.1

  parent reply	other threads:[~2011-04-16  9:18 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-16  9:17 i915 next, post-llc Chris Wilson
2011-04-16  9:17 ` [PATCH 01/21] drm/i915: Cache GT fifo count for SandyBridge Chris Wilson
2011-04-16  9:17 ` [PATCH 02/21] drm/i915: Refactor pwrite/pread to use single copy of get_user_pages Chris Wilson
2011-04-16  9:17 ` [PATCH 03/21] drm/i915: s/addr & ~PAGE_MASK/offset_in_page(addr)/ Chris Wilson
2011-04-16  9:17 ` [PATCH 04/21] drm/i915: Maintain fenced gpu access until we flush the fence Chris Wilson
2011-04-16  9:17 ` [PATCH 05/21] drm/i915: Invalidate fenced read domains upon flush Chris Wilson
2011-04-16  9:17 ` [PATCH 06/21] drm/i915: Pass the fence register number to be written Chris Wilson
2011-04-16  9:17 ` [PATCH 07/21] drm/i915: Track fence setup separately from fenced object lifetime Chris Wilson
2011-04-16 13:20   ` Daniel Vetter
2011-04-16  9:17 ` [PATCH 08/21] drm/i915: Only print out the actual number of fences for i915_error_state Chris Wilson
2011-04-16  9:17 ` [PATCH 09/21] drm/i915: Implement direct support for 24 bit LVDS pixel format Chris Wilson
2011-04-16  9:17 ` Chris Wilson [this message]
2011-04-16  9:17 ` [PATCH 11/21] drm/i915/tv: Use a direct pointer for tv_mode Chris Wilson
2011-04-16  9:17 ` [PATCH 12/21] drm/i915: Replace ironlake_compute_wm0 with g4x_compute_wm0 Chris Wilson
2011-04-16  9:17 ` [PATCH 13/21] drm/i915/crt: Explicitly return false if connected to a digital monitor Chris Wilson
2011-04-16  9:17 ` [PATCH 14/21] drm/i915/i2c: Convert from using GMBUS1 + reg_offset idiom to reg + 0 Chris Wilson
2011-04-16  9:17 ` [PATCH 15/21] drm/i915/gmbus: Reset the controller on initialisation Chris Wilson
2011-04-16  9:17 ` [PATCH 16/21] drm/i915: Retire requests before disabling pagefaults Chris Wilson
2011-04-16 13:44   ` Daniel Vetter
2011-04-16  9:17 ` [PATCH 17/21] drm/i915: Repeat retiring of requests until the seqno is stable Chris Wilson
2011-04-16 13:45   ` Daniel Vetter
2011-04-16  9:17 ` [PATCH 18/21] drm/i915: Split out i915_gem_object_move_to_ring() from execbuffer Chris Wilson
2011-04-16 13:54   ` Daniel Vetter
2011-04-16 14:18     ` Chris Wilson
2011-04-16 14:24       ` Daniel Vetter
2011-04-16  9:17 ` [PATCH 19/21] drm/i915: Enable the use of GPU semaphores whilst page-flipping Chris Wilson
2011-04-16 13:58   ` Daniel Vetter
2011-04-16 14:20     ` Chris Wilson
2011-04-16  9:17 ` [PATCH 20/21] drm/i915: Use a slab for object allocation Chris Wilson
2011-04-16 14:07   ` Daniel Vetter
2011-04-16  9:17 ` [PATCH 21/21] drm/i915: Introduce vmap (mapping of user pages into video memory) ioctl Chris Wilson
2011-04-18 14:58   ` Daniel Vetter
2011-04-19  6:20     ` Chris Wilson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1302945465-32115-11-git-send-email-chris@chris-wilson.co.uk \
    --to=chris@chris-wilson.co.uk \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.