From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mike Isely Subject: [PATCH 2/3] [drm/i915] - Implement ability to disabled LVDS fixed mode Date: Thu, 17 Mar 2011 08:58:09 -0500 (CDT) Message-ID: Reply-To: Mike Isely at pobox Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from cnc.isely.net (cnc.isely.net [75.149.91.89]) by gabe.freedesktop.org (Postfix) with ESMTP id 631B89E7D0 for ; Thu, 17 Mar 2011 07:03:32 -0700 (PDT) List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces+gcfxdi-intel-gfx=m.gmane.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+gcfxdi-intel-gfx=m.gmane.org@lists.freedesktop.org To: intel-gfx@lists.freedesktop.org Cc: Mike Isely at pobox List-Id: intel-gfx@lists.freedesktop.org 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@100" for a 100Hz 800x600 24bpp resolution. Signed-off-by: Mike Isely --- 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