xf86-video-intel: man/intel.man src/i830_driver.c src/i830.h src/i830_lvds.c

Zhenyu Wang zhen at kemper.freedesktop.org
Wed May 7 19:16:32 PDT 2008


 man/intel.man     |   87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/i830.h        |    1 
 src/i830_driver.c |    8 ++++
 src/i830_lvds.c   |   10 ++++++
 4 files changed, 106 insertions(+)

New commits:
commit 9f324860431ff8199a78d19bbaa74046e1476b89
Author: Mike Isely <isely at pobox.com>
Date:   Thu May 8 10:00:17 2008 +0800

    Implement option to ignore external fixed mode settings
    
    The Intel xorg driver tries mightily to determine the native fixed
    panel mode settings for the LVDS output.  It does this through various
    means, including scanning video BIOS tables, and noticing if the pipe
    in question has already been set up by somebody else (and adopting
    those timings).  This strategy works well for say a laptop where the
    LCD panel is an integral part of the machine.  But for other
    applications where the display is unrelated to the system's BIOS or
    other software, then the BIOS will likely have no clue how to
    configure the LVDS output.  Worse still, the BIOS can simply "get it
    wrong", leaving the pipe misconfigured.  Unfortunately the Intel
    driver can potentially notice this, adopt the same settings, leaving a
    messed up display.
    
    All of this complexity normally happens independently, behind the
    scenes, from the mode timings that might otherwise be specified by the
    user.  This driver has a concept of fixed, i.e. "native" mode, and
    then user-specified mode.  If the corresponding resolutions between
    those concepts don't match, then the driver in theory will arrange for
    scaling to take place while adhering to the actual native mode of the
    panel.  Said another way, if the user says 800x600 but the driver
    mistakenly (see above) thinks the native mode is 640x480, then 640x480
    is the mode set with scaling to an 800x600 frame buffer.  If the
    driver gets the wrong native mode, then the result is a miserable mess
    with no way for the user to override what the driver thinks is right.
    
    This patch provides a means to override the driver.  This implements a
    new driver option, "LVDSFixedMode" which defaults to true (the normal,
    probe-what-I-need behavior).  However when set to false, then all the
    guessing is skipped and the driver will assume no fixed, i.e. "native"
    mode for the display device.  Instead with this option set to false,
    the driver will directly set the timings specified by the user,
    providing an escape hatch for situations where the driver can't
    correctly figure out the right mode.
    
    Under most scenarios of course, this option should not be needed.  But
    in situations where the Intel video BIOS is hopelessly fouled up
    related to the LVDS output, this option provides the escape hatch for
    the user to get a working display in spite of the BIOS situation.
    
    Signed-off-by: Mike Isely <isely at pobox.com>

diff --git a/man/intel.man b/man/intel.man
index 8a8b7a0..aac0efa 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -200,6 +200,15 @@ LVDS-connected display on the other hand is extremely washed out
 (e.g. white on a lighter white), trying this option might clear the
 problem.
 .TP
+.BI "Option \*qLVDSFixedMode\*q \*q" boolean \*q
+Use a fixed set of timings for the LVDS output, independent of normal
+xorg specified timings.  The default value if left unspecified is
+true, which is what you want for a normal LVDS-connected LCD type of
+panel.  If you are not sure about this, leave it at its default, which
+allows the driver to automatically figure out the correct fixed panel
+timings.  See further in the section about LVDS fixed timing for more
+information.
+.TP
 .BI "Option \*qXvMC\*q \*q" boolean \*q
 Enable XvMC driver. Current support MPEG2 MC on 915/945 and G33 series.
 User should provide absolute path to libIntelXvMC.so in XvMCConfig file.
@@ -295,6 +304,84 @@ sections with these outputs for configuration.  Associating Monitor sections
 with each output can be helpful if you need to ignore a specific output, for
 example, or statically configure an extended desktop monitor layout.
 
+.SH HARDWARE LVDS FIXED TIMINGS AND SCALING
+
+Following here is a discussion that should shed some light on the
+nature and reasoning behind the LVDSFixedMode option.
+
+Unlike a CRT display, an LCD has a "native" resolution corresponding
+to the actual pixel geometry.  A graphics controller under all normal
+circumstances should always output that resolution (and timings) to
+the display.  Anything else and the image might not fill the display,
+it might not be centered, or it might have information missing - any
+manner of strange effects can happen if an LCD panel is not fed with
+the expected resolution and timings.
+
+However there are cases where one might want to run an LCD panel at an
+effective resolution other than the native one.  And for this reason,
+GPUs which drive LCD panels typically include a hardware scaler to
+match the user-configured frame buffer size to the actual size of the
+panel.  Thus when one "sets" his/her 1280x1024 panel to only 1024x768,
+the GPU happily configures a 1024x768 frame buffer, but it scans the
+buffer out in such a way that the image is scaled to 1280x1024 and in
+fact sends 1280x1024 to the panel.  This is normally invisible to the
+user; when a "fuzzy" LCD image is seen, scaling like this is why this
+happens.
+
+In order to make this magic work, this driver logically has to be
+configured with two sets of monitor timings - the set specified (or
+otherwise determined) as the normal xorg "mode", and the "fixed"
+timings that are actually sent to the monitor.  But with xorg, it's
+only possible to specify the first user-driven set, and not the second
+fixed set.  So how does the driver figure out the correct fixed panel
+timings?  Normally it will attempt to detect the fixed timings, and it
+uses a number of strategies to figure this out.  First it attempts to
+read EDID data from whatever is connected to the LVDS port.  Failing
+that, it will check if the LVDS output is already configured (perhaps
+previously by the video BIOS) and will adopt those settings if found.
+Failing that, it will scan the video BIOS ROM, looking for an embedded
+mode table from which it can infer the proper timings.  If even that
+fails, then the driver gives up, prints the message "Couldn't detect
+panel mode.  Disabling panel" to the X server log, and shuts down the
+LVDS output.
+
+Under most circumstances, the detection scheme works.  However there
+are cases when it can go awry.  For example, if you have a panel
+without EDID support and it isn't integral to the motherboard
+(i.e. not a laptop), then odds are the driver is either not going to
+find something suitable to use or it is going to find something
+flat-out wrong, leaving a messed up display.  Remember that this is
+about the fixed timings being discussed here and not the
+user-specified timings which can always be set in xorg.conf in the
+worst case.  So when this process goes awry there seems to be little
+recourse.  This sort of scenario can happen in some embedded
+applications.
+
+The LVDSFixedMode option is present to deal with this.  This option
+normally enables the above-described detection strategy.  And since it
+defaults to true, this is in fact what normally happens.  However if
+the detection fails to do the right thing, the LVDSFixedMode option
+can instead be set to false, which disables all the magic.  With
+LVDSFixedMode set to false, the detection steps are skipped and the
+driver proceeds without a specified fixed mode timing.  This then
+causes the hardware scaler to be disabled, and the actual timings then
+used fall back to those normally configured via the usual xorg
+mechanisms.
+
+Having LVDSFixedMode set to false means that whatever is used for the
+monitor's mode (e.g. a modeline setting) is precisely what is sent to
+the device connected to the LVDS port.  This also means that the user
+now has to determine the correct mode to use - but it's really no
+different than the work for correctly configuring an old-school CRT
+anyway, and the alternative if detection fails will be a useless
+display.
+
+In short, leave LVDSFixedMode alone (thus set to true) and normal
+fixed mode detection will take place, which in most cases is exactly
+what is needed.  Set LVDSFixedMode to false and then the user has full
+control over the resolution and timings sent to the LVDS-connected
+device, through the usual means in xorg.
+
 .SH "SEE ALSO"
 __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
 .SH AUTHORS
diff --git a/src/i830.h b/src/i830.h
index b090ec4..9d0f727 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -655,6 +655,7 @@ typedef struct _I830Rec {
 
    /** Enables logging of debug output related to mode switching. */
    Bool debug_modes;
+   Bool lvds_fixed_mode;
    unsigned int quirk_flag;
 } I830Rec;
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 44c510c..662b3e4 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -305,6 +305,7 @@ typedef enum {
 #ifdef XF86DRI_MM
    OPTION_INTELTEXPOOL,
 #endif
+   OPTION_LVDSFIXEDMODE,
    OPTION_TRIPLEBUFFER,
    OPTION_FORCEENABLEPIPEA,
 #ifdef INTEL_XVMC
@@ -332,6 +333,7 @@ static OptionInfoRec I830Options[] = {
 #ifdef XF86DRI_MM
    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
 #endif
+   {OPTION_LVDSFIXEDMODE, "LVDSFixedMode", OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_TRIPLEBUFFER, "TripleBuffer", OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_FORCEENABLEPIPEA, "ForceEnablePipeA", OPTV_BOOLEAN,	{0},	FALSE},
 #ifdef INTEL_XVMC
@@ -1416,6 +1418,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
       pI830->lvds_24_bit_mode = FALSE;
    }
 
+   if (xf86ReturnOptValBool(pI830->Options, OPTION_LVDSFIXEDMODE, TRUE)) {
+      pI830->lvds_fixed_mode = TRUE;
+   } else {
+      pI830->lvds_fixed_mode = FALSE;
+   }
+
    if (xf86ReturnOptValBool(pI830->Options, OPTION_FORCEENABLEPIPEA, FALSE))
        pI830->quirk_flag |= QUIRK_PIPEA_FORCE;
 
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 1562c21..48402df 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -1228,6 +1228,14 @@ i830_lvds_init(ScrnInfoPtr pScrn)
      */
     I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOC, "LVDSDDC_C");
 
+    if (!pI830->lvds_fixed_mode) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Skipping any attempt to determine panel fixed mode.\n");
+	goto skip_panel_fixed_mode_setup;
+    }
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "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.
      */
@@ -1311,6 +1319,8 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 	goto disable_exit;
     }
 
+ skip_panel_fixed_mode_setup:
+
     /* Blacklist machines with BIOSes that list an LVDS panel without actually
      * having one.
      */


More information about the xorg-commit mailing list