[Intel-gfx] [PATCH 2/3] [drm/i915] - Implement ability to disabled LVDS fixed mode

Mike Isely isely at isely.net
Thu Mar 17 14:58:09 CET 2011


An LVDS connected display device typically has a "fixed" mode to
which its video timings are locked, and that mode is not controllable
by the user - user-specified timings are always ignored.  If the fixed
mode's expected resolution does not match the user-specified frame
buffer's resolution, then the port is programmed to scale the image
(this is how multiple resolutions are handled on an LCD panel and it's
why you get fuzzy LCD resolutions when the chosen resolution doesn't
match the native resolution).

Unfortunately this setup makes it impossible for the user to control
the display's video timings.  This new option implements a new kernel
option, lvds_fixed, which defaults to true.  But when it is set to
false (zero), fixed mode is disabled; all scaling is gone and the
driver will then use the user-specified video timings.  Obviously the
user has to get the timings correct, but this is really not much
different than the bad old days of CRT video modes.

And while we normally don't want to disable fixed mode, the fact of
the matter is that sometimes there's no choice if the driver otherwise
gets the fixed mode "wrong".  This can happen in some embedded systems
where the video BIOS really has no knowledge of the display device.

Warning: With fixed mode disabled, and if there is no other mode data
supplied anywhere (e.g. KMS trying to run a framebuffer for fbcon on
an LVDS console), then the LVDS port will likely simply be disabled.
However that's easily remedied by supplying video mode information on
the kernel command line, for example "video=LVDS-1:800x600-24MR at 100"
for a 100Hz 800x600 24bpp resolution.

Signed-off-by: Mike Isely <isely at pobox.com>
---
 drivers/gpu/drm/i915/i915_drv.c   |    3 +++
 drivers/gpu/drm/i915/i915_drv.h   |    1 +
 drivers/gpu/drm/i915/intel_lvds.c |   31 ++++++++++++++++++++++---------
 3 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index c89f71c251acf230db613229eca90d24584b9729..004880aa3a948669b8b4e23d9ad73d132cff81d0 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -46,6 +46,9 @@ module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
 unsigned int i915_powersave = 1;
 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_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 526cef2972ab9afce1c17f57ef39ce9cc4dc736f..3fa8681459aa596e12e885568e5b48f0c9a60719 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -885,6 +885,7 @@ extern struct drm_ioctl_desc i915_ioctls[];
 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_downclock;
 extern unsigned int i915_lvds_24bit;
 
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index fe779b33899af536eb2e76429c9b05c363ce7721..303d60f71ca6dcf4ce7b59fe625ed5377af24bc4 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -157,10 +157,12 @@ static int intel_lvds_mode_valid(struct drm_connector *connector,
 	struct intel_lvds *intel_lvds = intel_attached_lvds(connector);
 	struct drm_display_mode *fixed_mode = intel_lvds->fixed_mode;
 
-	if (mode->hdisplay > fixed_mode->hdisplay)
-		return MODE_PANEL;
-	if (mode->vdisplay > fixed_mode->vdisplay)
-		return MODE_PANEL;
+	if (fixed_mode) {
+		if (mode->hdisplay > fixed_mode->hdisplay)
+			return MODE_PANEL;
+		if (mode->vdisplay > fixed_mode->vdisplay)
+			return MODE_PANEL;
+	}
 
 	return MODE_OK;
 }
@@ -253,7 +255,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 	 * with the panel scaling set up to source from the H/VDisplay
 	 * of the original mode.
 	 */
-	intel_fixed_panel_mode(intel_lvds->fixed_mode, adjusted_mode);
+	if (intel_lvds->fixed_mode)
+		intel_fixed_panel_mode(intel_lvds->fixed_mode, adjusted_mode);
 
 	if (HAS_PCH_SPLIT(dev)) {
 		intel_pch_panel_fitting(dev, intel_lvds->fitting_mode,
@@ -488,11 +491,13 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
 	if (intel_lvds->edid)
 		return drm_add_edid_modes(connector, intel_lvds->edid);
 
-	mode = drm_mode_duplicate(dev, intel_lvds->fixed_mode);
-	if (mode == 0)
-		return 0;
+	if (intel_lvds->fixed_mode) {
+		mode = drm_mode_duplicate(dev, intel_lvds->fixed_mode);
+		if (mode == 0)
+			return 0;
 
-	drm_mode_probed_add(connector, mode);
+		drm_mode_probed_add(connector, mode);
+	}
 	return 1;
 }
 
@@ -942,6 +947,14 @@ bool intel_lvds_init(struct drm_device *dev)
 	 *    if closed, act like it's not there for now
 	 */
 
+	if (!i915_lvds_fixed) {
+		DRM_DEBUG_KMS("Skipping any attempt to determine"
+			      " panel fixed mode.\n");
+		goto out;
+	}
+	DRM_DEBUG_KMS("Attempting to determine panel fixed mode.\n");
+
+
 	/*
 	 * Attempt to get the fixed panel mode from DDC.  Assume that the
 	 * preferred mode is the right one.
-- 
1.5.6.5


-- 

Mike Isely
isely @ isely (dot) net
PGP: 03 54 43 4D 75 E5 CC 92 71 16 01 E2 B5 F5 C1 E8



More information about the Intel-gfx mailing list