[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xserver-xorg-video-intel: Changes to 'debian-experimental'



 configure.ac                  |    2 
 debian/changelog              |    8 
 man/intel.man                 |   65 +++++-
 src/bios_reader/bios_reader.c |  291 +++++++++++++++++++++---------
 src/common.h                  |    2 
 src/i810_reg.h                |    2 
 src/i830.h                    |    6 
 src/i830_bios.c               |  401 ++++++++++++------------------------------
 src/i830_bios.h               |   72 ++++---
 src/i830_display.c            |   62 +++---
 src/i830_dri.c                |    2 
 src/i830_driver.c             |   18 +
 src/i830_dvo.c                |   43 ++--
 src/i830_hdmi.c               |    9 
 src/i830_lvds.c               |  158 ++++++----------
 src/i830_quirks.c             |    5 
 src/i830_sdvo.c               |   39 +++-
 src/i830_sdvo_regs.h          |    2 
 src/i830_tv.c                 |    1 
 19 files changed, 621 insertions(+), 567 deletions(-)

New commits:
commit cfdf9391594f7bb34a0924d0225541728ac5c4c8
Author: Timo Aaltonen <tjaalton@cc.hut.fi>
Date:   Wed Aug 20 13:05:00 2008 +0300

    Update changelog

diff --git a/debian/changelog b/debian/changelog
index d6b4f26..967e734 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+xserver-xorg-video-intel (2:2.4.1-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+  * Cherry-picked d5fd845aab407 from 2.4-branch:
+    "Fix reverted LVDS bios capability dword definition"
+
+ -- Timo Aaltonen <tepsipakki@ubuntu.com>  Wed, 20 Aug 2008 13:03:29 +0300
+
 xserver-xorg-video-intel (2:2.4.0-1) experimental; urgency=low
 
   * New upstream release.

commit 461e2c7da2fc7de906419eed70ec37a464888f82
Author: Zhenyu Wang <zhenyu.z.wang@intel.com>
Date:   Tue Aug 19 07:30:01 2008 +0800

    Fix reverted LVDS bios capability dword definition
    
    Issue found by Peter Clifton.
    (cherry picked from commit 0e6759bb6ad7293b6447bd20e3d7d8fdee46aba7)

diff --git a/src/i830_bios.h b/src/i830_bios.h
index a8d9add..2b073f3 100644
--- a/src/i830_bios.h
+++ b/src/i830_bios.h
@@ -152,13 +152,13 @@ struct bdb_lvds_options {
     uint8_t panel_type;
     uint8_t rsvd1;
     /* LVDS capabilities, stored in a dword */
-    uint8_t rsvd2:1;
-    uint8_t lvds_edid:1;
-    uint8_t pixel_dither:1;
-    uint8_t pfit_ratio_auto:1;
-    uint8_t pfit_gfx_mode_enhanced:1;
-    uint8_t pfit_text_mode_enhanced:1;
     uint8_t pfit_mode:2;
+    uint8_t pfit_text_mode_enhanced:1;
+    uint8_t pfit_gfx_mode_enhanced:1;
+    uint8_t pfit_ratio_auto:1;
+    uint8_t pixel_dither:1;
+    uint8_t lvds_edid:1;
+    uint8_t rsvd2:1;
     uint8_t rsvd4;
 } __attribute__((packed));
 

commit 4281b0116b8aa7201f523c21abf91f63e12cbccf
Author: Zhenyu Wang <zhenyu.z.wang@intel.com>
Date:   Fri Aug 15 13:05:06 2008 +0800

    Bump version 2.4.1

diff --git a/configure.ac b/configure.ac
index 6694773..0e155ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-video-intel],
-        2.4.0,
+        2.4.1,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-intel)
 

commit 01bbdbc6d83a526654abf501bd6cd203f8373774
Author: Alan Coopersmith <alan.coopersmith@sun.com>
Date:   Thu Jul 31 20:02:21 2008 -0700

    Man page typo fixes
    (cherry picked from commit 27e9506fda86e90fd67de1715fa32d23aaa8a683)

diff --git a/man/intel.man b/man/intel.man
index f363ab1..e9ae240 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -382,9 +382,9 @@ 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 MUTLIHEAD CONFIGURATIONS
+.SH MULTIHEAD CONFIGURATIONS
 
-The number of independent outputs is dicated by the number of CRTCs
+The number of independent outputs is dictated by the number of CRTCs
 (in X parlance) a given chip supports.  Most recent Intel chips have
 two CRTCs, meaning that two separate framebuffers can be displayed
 simultaneously, in an extended desktop configuration.  If a chip

commit 4ac91c2eb6b539fa23d218ca714cadf998ae8eb6
Author: Jesse Barnes <jbarnes@eee.(none)>
Date:   Thu Jul 31 19:21:36 2008 -0700

    Update man page
    
    Add example dual head config, add info on bug reporting.
    (cherry picked from commit da2eb83fb9a52291ea98f3285aee7bee2d55e0ca)

diff --git a/man/intel.man b/man/intel.man
index aac0efa..f363ab1 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -33,10 +33,10 @@ details.  This section only covers configuration details specific to this
 driver.
 .PP
 The Intel 8xx and 9xx families of integrated graphics chipsets have a unified
-memory architecture and uses system memory for video ram.  For the i810 and
-i815 family of chipset, operating system support for allocating system
-memory for video use is required in order to use this driver.  For the 830M
-and later, this is required in order for the driver to use more video ram
+memory architecture meaning that system memory is used as video RAM.  For the
+i810 and i815 family of chipsets, operating system support for allocating system
+memory is required in order to use this driver.  For the 830M
+and later, this is required in order for the driver to use more video RAM
 than has been pre-allocated at boot time by the BIOS.  This is usually
 achieved with an "agpgart" or "agp" kernel driver.  Linux, FreeBSD, OpenBSD,
 NetBSD, and Solaris have such kernel drivers available.
@@ -44,7 +44,7 @@ NetBSD, and Solaris have such kernel drivers available.
 By default, the i810 will use 8 megabytes
 of system memory for graphics.  For the 830M and later, the driver will
 automatically size its memory allocation according to the features it will
-support.  The
+support.  Therefore, the
 .B VideoRam
 option, which in the past had been necessary to allow more than some small
 amount of memory to be allocated, is now ignored.
@@ -84,7 +84,8 @@ Default: enabled on supported configurations.
 .TP
 .BI "Option \*qTiling\*q \*q" boolean \*q
 This option controls whether memory buffers are allocated in tiled mode.  In
-many cases (especially for complex rendering), tiling can improve performance.
+most cases (especially for complex rendering), tiling dramatically improves
+performance.
 Default: enabled.
 .TP
 .BI "Option \*qDRI\*q \*q" boolean \*q
@@ -180,8 +181,7 @@ the server log.
 Force the driver to leave pipe A enabled.  May be necessary in configurations
 where the BIOS accesses pipe registers during display hotswitch or lid close,
 causing a crash.  If you find that your platform needs this option, please file
-a bug against xf86-video-intel at http://bugs.freedesktop.org which includes
-the output of 'lspci -v' and 'lspci -vn'.
+a bug (see REPORTING BUGS below) including the output of 'lspci -v' and 'lspci -vn'.
 .TP
 .BI "Option \*qLVDS24Bit\*q \*q" boolean \*q
 Specify 24 bit pixel format (i.e. 8 bits per color) to be used for the
@@ -220,7 +220,7 @@ detected outputs.  You can use the
 .B xrandr
 tool to control outputs on the command line.  Each output listed below may have
 one or more properties associated with it (like a binary EDID block if one is
-found).  Some outputs have unique properties which are described below.
+found).  Some outputs have unique properties which are described below.  See the "MULTIHEAD CONFIGURATIONS" section below for additional information.
 
 .SS "VGA"
 VGA output port (typically exposed via an HD15 connector).
@@ -382,6 +382,53 @@ 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 MUTLIHEAD CONFIGURATIONS
+
+The number of independent outputs is dicated by the number of CRTCs
+(in X parlance) a given chip supports.  Most recent Intel chips have
+two CRTCs, meaning that two separate framebuffers can be displayed
+simultaneously, in an extended desktop configuration.  If a chip
+supports more outputs than it has CRTCs (say local flat panel, VGA and
+TV in the case of many outputs), two of the outputs will have to be
+"cloned", meaning that they display the same framebuffer contents (or
+one displays a subset of another's framebuffer if the modes aren't
+equal).
+
+You can use the "xrandr" tool, or various desktop utilities, to change
+your output configuration at runtime.  To statically configure your
+outputs, you can use the "Monitor-<type>" options along with
+additional monitor sections in your xorg.conf to create your screen
+topology.  The example below puts the VGA output to the right of the
+builtin laptop screen, both running at 1024x768.
+
+.nf
+.B "Section \*qMonitor\*q"
+.BI "  Identifier \*qLaptop FooBar Internal Display\*q"
+.BI "  Option \*qPosition\*q \*q0 0\*q"
+.B "EndSection"
+
+.B "Section \*qMonitor\*q"
+.BI "  Identifier \*qSome Random CRT\*q"
+.BI "  Option \*qPosition\*q \*q1024 0\*q"
+.BI "  Option \*qRightOf\*q \*qLaptop FoodBar Internal Display\*q"
+.B "EndSection"
+
+.B "Section \*qDevice\*q"
+.BI "  Driver \*qintel\*q"
+.BI "  Option \*qmonitor-LVDS\*q \*qLaptop FooBar Internal Display\*q"
+.BI "  Option \*qmonitor-VGA\*q \*qSome Random CRT\*q"
+.B "EndSection"
+
+.SH REPORTING BUGS
+
+The xf86-video-intel driver is part of the X.Org and Freedesktop.org
+umbrella projects.  Details on bug reporting can be found at
+http://www.intellinuxgraphics.org/how_to_report_bug.html.  Mailing
+lists are also commonly used to report experiences and ask questions
+about configuration and other topics.  See lists.freedesktop.org for
+more information (the xorg@lists.freedesktop.org mailing list is the
+most appropriate place to ask X.Org and driver related questions).
+
 .SH "SEE ALSO"
 __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
 .SH AUTHORS

commit 280be2a193063c9e2f062cbab9fa967a408dc290
Author: Zhenyu Wang <zhenyu.z.wang@intel.com>
Date:   Fri Aug 15 10:10:43 2008 +0800

    Always check and free driver private in LVDS destroy
    (cherry picked from commit ed7269e0a377b3135b06cacecc59119f06958feb)

diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 78fd2d8..96e9f00 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -824,11 +824,9 @@ i830_lvds_destroy (xf86OutputPtr output)
     I830Ptr	pI830 = I830PTR(pScrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
 
-    if (pI830->lvds_fixed_mode)
-    {
-        xf86DeleteMode (&pI830->lvds_fixed_mode, pI830->lvds_fixed_mode);
+    xf86DeleteMode (&pI830->lvds_fixed_mode, pI830->lvds_fixed_mode);
+    if (intel_output)
 	xfree (intel_output);
-    }
 }
 
 #ifdef RANDR_12_INTERFACE

commit 1f558fab4eef3b54de4853bc5247fbd0d24b68bf
Author: Zhenyu Wang <zhenyu.z.wang@intel.com>
Date:   Fri Aug 15 10:02:44 2008 +0800

    Make skip_panel_detect clear for its meaning
    (cherry picked from commit f4cb9a135dca9279af8186a9b18bf62ef7351019)

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 64d0db1..6f87c51 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1503,9 +1503,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags)
    }
 
    if (xf86ReturnOptValBool(pI830->Options, OPTION_LVDSFIXEDMODE, TRUE)) {
-      pI830->skip_panel_detect = TRUE;
-   } else {
       pI830->skip_panel_detect = FALSE;
+   } else {
+      pI830->skip_panel_detect = TRUE;
    }
 
    if (xf86ReturnOptValBool(pI830->Options, OPTION_FORCEENABLEPIPEA, FALSE))
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index a885627..78fd2d8 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -1255,7 +1255,7 @@ i830_lvds_init(ScrnInfoPtr pScrn)
      */
     I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOC, "LVDSDDC_C");
 
-    if (!pI830->skip_panel_detect) {
+    if (pI830->skip_panel_detect) {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		   "Skipping any attempt to determine panel fixed mode.\n");
 	goto found_mode;

commit 532e47a4a169e829ad34fdc8bb85e4eb81721af3
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date:   Thu Aug 14 16:02:37 2008 -0700

    Fix pipe A force quirk
    
    Last commit introduced a logic buglet, we went from (foo & BLAH) -> (!foo &
    BLAH) rather than !(foo & BLAH), so fix it up to make my laptop work again.
    (cherry picked from commit 22918f62c89a4314fb5d01c58f22fee5b9a15a27)

diff --git a/src/i830_display.c b/src/i830_display.c
index 622209b..2f1e7ab 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -858,7 +858,7 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
 	OUTREG(VGACNTRL, VGA_DISP_DISABLE);
 
 	/* May need to leave pipe A on */
-	if ((pipe != 0) || (!pI830->quirk_flag & QUIRK_PIPEA_FORCE))
+	if ((pipe != 0) || !(pI830->quirk_flag & QUIRK_PIPEA_FORCE))
 	{
 		/* Disable display plane */
 		temp = INREG(dspcntr_reg);

commit ac740398569dfa02d3d26a2abeb5c848717e6c03
Author: Olivier Fourdan <ofourdan@redhat.com>
Date:   Mon Aug 11 12:07:32 2008 -0400

    Fix DPMS off in the presence of the pipe A quirk.
    
    Still turn off the VGA plane, and also handle the DRI path at the end.
    (cherry picked from commit 9ec36e0c8bd8a4bd7c40569412fc1a21219b5af9)

diff --git a/src/i830_display.c b/src/i830_display.c
index e1dad03..622209b 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -854,44 +854,43 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
 	/* Give the overlay scaler a chance to disable if it's on this pipe */
 	i830_crtc_dpms_video(crtc, FALSE);
 
-	/* May need to leave pipe A on */
-	if ((pipe == 0) && (pI830->quirk_flag & QUIRK_PIPEA_FORCE))
-	    return;
-
 	/* Disable the VGA plane that we never use */
 	OUTREG(VGACNTRL, VGA_DISP_DISABLE);
 
-	/* Disable display plane */
-	temp = INREG(dspcntr_reg);
-	if ((temp & DISPLAY_PLANE_ENABLE) != 0)
+	/* May need to leave pipe A on */
+	if ((pipe != 0) || (!pI830->quirk_flag & QUIRK_PIPEA_FORCE))
 	{
-	    OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
-	    /* Flush the plane changes */
-	    OUTREG(dspbase_reg, INREG(dspbase_reg));
-	    POSTING_READ(dspbase_reg);
-	}
+		/* Disable display plane */
+		temp = INREG(dspcntr_reg);
+		if ((temp & DISPLAY_PLANE_ENABLE) != 0)
+		{
+		    OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+		    /* Flush the plane changes */
+		    OUTREG(dspbase_reg, INREG(dspbase_reg));
+		    POSTING_READ(dspbase_reg);
+		}
 
-	if (!IS_I9XX(pI830)) {
-	    /* Wait for vblank for the disable to take effect */
-	    i830WaitForVblank(pScrn);
-	}
+		if (!IS_I9XX(pI830)) {
+		    /* Wait for vblank for the disable to take effect */
+		    i830WaitForVblank(pScrn);
+		}
 
-	/* Next, disable display pipes */
-	temp = INREG(pipeconf_reg);
-	if ((temp & PIPEACONF_ENABLE) != 0) {
-	    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
-	    POSTING_READ(pipeconf_reg);
-	}
+		/* Next, disable display pipes */
+		temp = INREG(pipeconf_reg);
+		if ((temp & PIPEACONF_ENABLE) != 0) {
+		    OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
+		    POSTING_READ(pipeconf_reg);
+		}
 
-	/* Wait for vblank for the disable to take effect. */
-	i830WaitForVblank(pScrn);
+		/* Wait for vblank for the disable to take effect. */
+		i830WaitForVblank(pScrn);
 
-	temp = INREG(dpll_reg);
-	if ((temp & DPLL_VCO_ENABLE) != 0) {
-	    OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
-	    POSTING_READ(dpll_reg);
+		temp = INREG(dpll_reg);
+		if ((temp & DPLL_VCO_ENABLE) != 0) {
+		    OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
+		    POSTING_READ(dpll_reg);
+		}
 	}
-
 	/* Wait for the clocks to turn off. */
 	usleep(150);
 	break;

commit 9b03fd49b0f27c9add19dece55d00a58ed73c978
Author: Olivier Fourdan <ofourdan@redhat.com>
Date:   Mon Aug 11 11:30:51 2008 -0400

    Apply pipe A quirk to 845 as well.
    (cherry picked from commit 445c2e9ef8fc1d49bbb03e07bf36e0339be16a80)

diff --git a/src/i830_quirks.c b/src/i830_quirks.c
index 6fc8e53..a3ed044 100644
--- a/src/i830_quirks.c
+++ b/src/i830_quirks.c
@@ -315,6 +315,7 @@ static i830_quirk i830_quirk_list[] = {
 
     /* 855 & before need to leave pipe A & dpll A up */
     { PCI_CHIP_I855_GM, SUBSYS_ANY, SUBSYS_ANY, quirk_pipea_force },
+    { PCI_CHIP_845_G, SUBSYS_ANY, SUBSYS_ANY, quirk_pipea_force },
 
     { 0, 0, 0, NULL },
 };

commit d1b47cf0cb66fb1b7c991fbd4f4518c6ccdbc643
Author: Eric Anholt <eric@anholt.net>
Date:   Fri Aug 8 16:35:25 2008 -0700

    Set lvds_ddc_mode before use to avoid a segfault on mac mini.
    (cherry picked from commit fe90c0522f65f60c4c431787c889b7fb639ab61b)

diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 9f20579..a885627 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -1213,7 +1213,7 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     xf86OutputPtr	    output;
     I830OutputPrivatePtr    intel_output;
     DisplayModePtr	    modes, scan;
-    DisplayModePtr	    lvds_ddc_mode;
+    DisplayModePtr	    lvds_ddc_mode = NULL;
     struct i830_lvds_priv   *dev_priv;
 
     if (pI830->quirk_flag & QUIRK_IGNORE_LVDS)

commit 86b10601e8798974240ae17539b413c1798d34e1
Author: Jesse Barnes <jbarnes@jbarnes-t61.(none)>
Date:   Tue Aug 5 13:37:38 2008 -0700

    Reorganize VBIOS code
    
    Make VBT parsing happen at driver init time rather than in each output init
    function, to save time and better separate VBIOS code into i830_bios.[ch].  The
    changes end up touching the output files due to field name changes, and allow
    us to reorder & simplify our LFP mode detection code.
    (cherry picked from commit a21d4794b6812ce05d08f06dc47b26c4fb1c1fef)

diff --git a/src/bios_reader/bios_reader.c b/src/bios_reader/bios_reader.c
index ffa27f0..dbcd150 100644
--- a/src/bios_reader/bios_reader.c
+++ b/src/bios_reader/bios_reader.c
@@ -25,11 +25,17 @@
  *
  */
 
+#include <errno.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 
+
 #include "../i830_bios.h"
 
 #define _PARSE_EDID_
@@ -51,108 +57,223 @@ struct _fake_i830 *pI830 = &I830;
 				 (pI830->VBIOS[_addr + 2] << 16) \
 				 (pI830->VBIOS[_addr + 3] << 24))
 
+#define YESNO(val) ((val) ? "yes" : "no")
+
+static int tv_present;
+static int lvds_present;
+static int panel_type;
+
+static void *find_section(struct bdb_header *bdb, int section_id)
+{
+	unsigned char *base = (unsigned char *)bdb;
+	int index = 0;
+	uint16_t total, current_size;
+	unsigned char current_id;
+
+	/* skip to first section */
+	index += bdb->header_size;
+	total = bdb->bdb_size;
+
+	/* walk the sections looking for section_id */
+	while (index < total) {
+		current_id = *(base + index);
+		index++;
+		current_size = *((uint16_t *)(base + index));
+		index += 2;
+		if (current_id == section_id)
+			return base + index;
+		index += current_size;
+	}
+
+	return NULL;
+}
+
+static void dump_general_features(void *data)
+{
+    struct bdb_general_features *features = data;
+
+    if (!data)
+	return;
+
+    printf("General features block:\n");
+
+    printf("\tPanel fitting: ");
+    switch (features->panel_fitting) {
+    case 0:
+	printf("disabled\n");
+	break;
+    case 1:
+	printf("text only\n");
+	break;
+    case 2:
+	printf("graphics only\n");
+	break;
+    case 3:
+	printf("text & graphics\n");
+	break;
+    }
+    printf("\tFlexaim: %s\n", YESNO(features->flexaim));
+    printf("\tMessage: %s\n", YESNO(features->msg_enable));
+    printf("\tClear screen: %d\n", features->clear_screen);
+    printf("\tDVO color flip required: %s\n", YESNO(features->color_flip));
+    printf("\tExternal VBT: %s\n", YESNO(features->download_ext_vbt));
+    printf("\tEnable SSC: %s\n", YESNO(features->enable_ssc));
+    if (features->enable_ssc)
+	printf("\tSSC frequency: %s\n", features->ssc_freq ?
+	       "100 MHz (66 MHz on 855)" : "96 MHz (48 MHz on 855)");
+    printf("\tLFP on override: %s\n", YESNO(features->enable_lfp_on_override));
+    printf("\tDisable SSC on clone: %s\n", YESNO(features->disable_ssc_ddt));
+    printf("\tDisable smooth vision: %s\n",
+	   YESNO(features->disable_smooth_vision));
+    printf("\tSingle DVI for CRT/DVI: %s\n", YESNO(features->single_dvi));
+    printf("\tLegacy monitor detect: %s\n",
+	   YESNO(features->legacy_monitor_detect));
+    printf("\tIntegrated CRT: %s\n", YESNO(features->int_crt_support));
+    printf("\tIntegrated TV: %s\n", YESNO(features->int_tv_support));
+
+    tv_present = 1; /* should be based on whether TV DAC exists */
+    lvds_present = 1; /* should be based on IS_MOBILE() */
+}
+
+static void dump_general_definitions(void *data)
+{
+    struct bdb_general_definitions *defs = data;
+    unsigned char *lvds_data = defs->tv_or_lvds_info;
+
+    if (!data)
+	return;
+
+    printf("General definitions block:\n");
+
+    printf("\tCRT DDC GMBUS addr: 0x%02x\n", defs->crt_ddc_gmbus_pin);
+    printf("\tUse ACPI DPMS CRT power states: %s\n", YESNO(defs->dpms_acpi));
+    printf("\tSkip CRT detect at boot: %s\n",
+	   YESNO(defs->skip_boot_crt_detect));
+    printf("\tUse DPMS on AIM devices: %s\n", YESNO(defs->dpms_aim));
+    printf("\tBoot display type: 0x%02x%02x\n", defs->boot_display[1],
+	   defs->boot_display[0]);
+    printf("\tTV data block present: %s\n", YESNO(tv_present));
+    if (tv_present)
+	lvds_data += 33;
+    if (lvds_present)
+	printf("\tLFP DDC GMBUS addr: 0x%02x\n", lvds_data[19]);
+}
+
+static void dump_lvds_options(void *data)
+{
+    struct bdb_lvds_options *options = data;
+
+    if (!data)
+	return;
+
+    printf("LVDS options block:\n");
+
+    panel_type = options->panel_type;
+    printf("\tPanel type: %d\n", panel_type);
+    printf("\tLVDS EDID available: %s\n", YESNO(options->lvds_edid));
+    printf("\tPixel dither: %s\n", YESNO(options->pixel_dither));
+    printf("\tPFIT auto ratio: %s\n", YESNO(options->pfit_ratio_auto));
+    printf("\tPFIT enhanced graphics mode: %s\n",
+	   YESNO(options->pfit_gfx_mode_enhanced));
+    printf("\tPFIT enhanced text mode: %s\n",
+	   YESNO(options->pfit_text_mode_enhanced));
+    printf("\tPFIT mode: %d\n", options->pfit_mode);
+}
+
+static void dump_lvds_data(void *data, unsigned char *base)
+{
+    struct bdb_lvds_lfp_data *lvds_data = data;
+    int i;
+
+    if (!data)
+	return;
+
+    printf("LVDS panel data block (preferred block marked with '*'):\n");
+
+    for (i = 0; i < 16; i++) {
+	struct bdb_lvds_lfp_data_entry *lfp_data = &lvds_data->data[i];
+	uint8_t *timing_data = (uint8_t *)&lfp_data->dvo_timing;
+	char marker;
+
+	if (i == panel_type)
+	    marker = '*';
+	else
+	    marker = ' ';
+
+	printf("%c\tpanel type %02i: %dx%d clock %d\n", marker,
+	       i, lfp_data->fp_timing.x_res, lfp_data->fp_timing.y_res,
+	       _PIXEL_CLOCK(timing_data));
+	printf("\t\ttimings: %d %d %d %d %d %d %d %d\n",
+	       _H_ACTIVE(timing_data),
+	       _H_BLANK(timing_data),
+	       _H_SYNC_OFF(timing_data),
+	       _H_SYNC_WIDTH(timing_data),
+	       _V_ACTIVE(timing_data),
+	       _V_BLANK(timing_data),
+	       _V_SYNC_OFF(timing_data),
+	       _V_SYNC_WIDTH(timing_data));
+    }
+
+}
+
 int main(int argc, char **argv)
 {
-    FILE *f;
-    int bios_size = 65536;
-    struct vbt_header *vbt;
+    int fd;
+    struct vbt_header *vbt = NULL;
     struct bdb_header *bdb;
-    int vbt_off, bdb_off, bdb_block_off, block_size;
-    int panel_type = -1, i;
+    int vbt_off, bdb_off, i;
     char *filename = "bios";
+    struct stat finfo;
 
-    if (argc == 2)
-	filename = argv[1];
+    if (argc != 2) {
+	printf("usage: %s <rom file>\n", argv[0]);
+	return 1;
+    }
+	
+    filename = argv[1];
 
-    f = fopen(filename, "r");
-    if (!f) {
-	printf("Couldn't open %s\n", filename);
+    fd = open(filename, O_RDONLY);
+    if (fd == -1) {
+	printf("Couldn't open \"%s\": %s\n", filename, strerror(errno));
 	return 1;
     }
 
-    pI830->VBIOS = calloc(1, bios_size);
-    if (fread(pI830->VBIOS, 1, bios_size, f) != bios_size)
+    if (stat(filename, &finfo)) {
+	printf("failed to stat \"%s\": %s\n", filename, strerror(errno));
 	return 1;
+    }
+
+    pI830->VBIOS = mmap(NULL, finfo.st_size, PROT_READ, MAP_SHARED, fd, 0);
+    if (pI830->VBIOS == MAP_FAILED) {
+	printf("failed to map \"%s\": %s\n", filename, strerror(errno));
+	return 1;
+    }
+
+    /* Scour memory looking for the VBT signature */
+    for (i = 0; i + 4 < finfo.st_size; i++) {
+	if (!memcmp(pI830->VBIOS + i, "$VBT", 4)) {
+	    vbt_off = i;
+	    vbt = (struct vbt_header *)(pI830->VBIOS + i);
+	    break;
+	}
+    }
+
+    if (!vbt) {
+	printf("VBT signature missing\n");
+	return 1;
+    }
 
-    vbt_off = INTEL_BIOS_16(0x1a);
-    printf("VBT offset: %08x\n", vbt_off);
-    vbt = (struct vbt_header *)(pI830->VBIOS + vbt_off);
-    printf("VBT sig: %20s\n", vbt->signature);
     printf("VBT vers: %d.%d\n", vbt->version / 100, vbt->version % 100);
 
     bdb_off = vbt_off + vbt->bdb_offset;
     bdb = (struct bdb_header *)(pI830->VBIOS + bdb_off);
     printf("BDB sig: %16s\n", bdb->signature);
     printf("BDB vers: %d.%d\n", bdb->version / 100, bdb->version % 100);
-    for (bdb_block_off = bdb->header_size; bdb_block_off < bdb->bdb_size;
-	 bdb_block_off += block_size)
-    {
-	int start = bdb_off + bdb_block_off;
-	int id;
-	struct lvds_bdb_1 *lvds1;
-	struct lvds_bdb_2 *lvds2;
-	struct lvds_bdb_2_fp_params *fpparam;
-	struct lvds_bdb_2_fp_edid_dtd *fptiming;
-	uint8_t *timing_ptr;
-
-	id = INTEL_BIOS_8(start);
-	block_size = INTEL_BIOS_16(start + 1) + 3;
-	printf("BDB block type %03d size %d\n", id, block_size);
-	switch (id) {
-	case 40:
-	    lvds1 = (struct lvds_bdb_1 *)(pI830->VBIOS + start);
-	    panel_type = lvds1->panel_type;
-	    printf("Panel type: %d, caps %04x\n", panel_type, lvds1->caps);
-	    break;
-	case 41:
-	    if (panel_type == -1) {
-		printf("Found panel block with no panel type\n");
-		break;
-	    }
-
-	    lvds2 = (struct lvds_bdb_2 *)(pI830->VBIOS + start);
-
-	    printf("Entries per table: %d\n", lvds2->table_size);
-	    for (i = 0; i < 16; i++) {
-		char marker;
-		fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
-		    bdb_off + lvds2->panels[i].fp_params_offset);
-		fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS +
-		    bdb_off + lvds2->panels[i].fp_edid_dtd_offset);
-		timing_ptr = pI830->VBIOS + bdb_off +
-		    lvds2->panels[i].fp_edid_dtd_offset;
-		if (fpparam->terminator != 0xffff) {
-		    /* Apparently the offsets are wrong for some BIOSes, so we
-		     * try the other offsets if we find a bad terminator.
-		     */
-		    fpparam = (struct lvds_bdb_2_fp_params *)(pI830->VBIOS +
-			bdb_off + lvds2->panels[i].fp_params_offset + 8);
-		    fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(pI830->VBIOS +
-			bdb_off + lvds2->panels[i].fp_edid_dtd_offset + 8);
-		    timing_ptr = pI830->VBIOS + bdb_off +
-			lvds2->panels[i].fp_edid_dtd_offset + 8;
-
-		    if (fpparam->terminator != 0xffff)
-			continue;
-		}
-		if (i == panel_type)
-		    marker = '*';
-		else
-		    marker = ' ';
-		printf("%c Panel index %02i xres %d yres %d clock %d\n", marker,
-		       i, fpparam->x_res, fpparam->y_res,
-		       _PIXEL_CLOCK(timing_ptr));
-		printf("        %d %d %d %d %d %d %d %d\n",
-		       _H_ACTIVE(timing_ptr), _H_BLANK(timing_ptr),
-		       _H_SYNC_OFF(timing_ptr), _H_SYNC_WIDTH(timing_ptr),
-		       _V_ACTIVE(timing_ptr), _V_BLANK(timing_ptr),
-		       _V_SYNC_OFF(timing_ptr), _V_SYNC_WIDTH(timing_ptr));
-	    }
-
-	    printf("Panel of size %dx%d\n", fpparam->x_res, fpparam->y_res);
-	    break;
-	}
-    }
+
+    dump_general_features(find_section(bdb, BDB_GENERAL_FEATURES));
+    dump_general_definitions(find_section(bdb, BDB_GENERAL_DEFINITIONS));
+    dump_lvds_options(find_section(bdb, BDB_LVDS_OPTIONS));
+    dump_lvds_data(find_section(bdb, BDB_LVDS_LFP_DATA), bdb);
 
     return 0;
 }
diff --git a/src/i830.h b/src/i830.h
index 68690f7..6a5de6b 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -251,8 +251,6 @@ struct _I830DVODriver {
    I830I2CVidOutputRec *vid_rec;
    void *dev_priv;
    pointer modhandle;
-   DisplayModePtr panel_fixed_mode;
-   Bool panel_wants_dither;
 };
 
 extern const char *i830_output_type_names[];
@@ -556,6 +554,9 @@ typedef struct _I830Rec {
    Bool lvds_24_bit_mode;
    Bool lvds_use_ssc;
    int lvds_ssc_freq; /* in MHz */
+   Bool lvds_dither;
+   DisplayModePtr lvds_fixed_mode;
+   Bool skip_panel_detect;
 
    Bool tv_present; /* TV connector present (from VBIOS) */
 
@@ -663,7 +664,6 @@ 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_bios.c b/src/i830_bios.c
index a8193fc..fe55d23 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -40,84 +40,152 @@
 #include "edid.h"
 
 #define INTEL_BIOS_8(_addr)	(bios[_addr])
-#define INTEL_BIOS_16(_addr)	(bios[_addr] | \
+#define INTEL_BIOS_16(_addr)	(bios[_addr] |			\
 				 (bios[_addr + 1] << 8))
-#define INTEL_BIOS_32(_addr)	(bios[_addr] | \
-				 (bios[_addr + 1] << 8) \
-				 (bios[_addr + 2] << 16) \
+#define INTEL_BIOS_32(_addr)	(bios[_addr] |			\
+				 (bios[_addr + 1] << 8)		\
+				 (bios[_addr + 2] << 16)	\
 				 (bios[_addr + 3] << 24))
 
 /* XXX */
 #define INTEL_VBIOS_SIZE (64 * 1024)
 
+static void *
+find_section(struct bdb_header *bdb, int section_id)
+{
+    unsigned char *base = (unsigned char *)bdb;
+    int index = 0;
+    uint16_t total, current_size;
+    unsigned char current_id;
+
+    /* skip to first section */
+    index += bdb->header_size;
+    total = bdb->bdb_size;
+
+    /* walk the sections looking for section_id */
+    while (index < total) {
+	current_id = *(base + index);
+	index++;
+	current_size = *((uint16_t *)(base + index));
+	index += 2;
+	if (current_id == section_id)
+	    return base + index;
+	index += current_size;
+    }
+
+    return NULL;
+}
+
+/**
+ * Returns the BIOS's fixed panel mode.
+ *
+ * Note that many BIOSes will have the appropriate tables for a panel even when
+ * a panel is not attached.  Additionally, many BIOSes adjust table sizes or
+ * offsets, such that this parsing fails.  Thus, almost any other method for
+ * detecting the panel mode is preferable.
+ */
 static void
-i830DumpBIOSToFile(ScrnInfoPtr pScrn, unsigned char *bios)
+parse_panel_data(I830Ptr pI830, struct bdb_header *bdb)
 {
-    const char *filename = "/tmp/xf86-video-intel-VBIOS";
-    FILE *f;
+    struct bdb_lvds_options *lvds_options;
+    struct bdb_lvds_lfp_data *lvds_lfp_data;
+    struct bdb_lvds_lfp_data_entry *entry;
+    DisplayModePtr fixed_mode;
+    unsigned char *timing_ptr;
 
-    f = fopen(filename, "w");
-    if (f == NULL) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't open %s\n", filename);
+    /* Defaults if we can't find VBT info */
+    pI830->lvds_dither = 0;
+
+    lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
+    if (!lvds_options)
+	return;
+
+    pI830->lvds_dither = lvds_options->pixel_dither;
+    if (lvds_options->panel_type == 0xff)
+	return;
+
+    lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
+    if (!lvds_lfp_data)
 	return;
-    }
-    if (fwrite(bios, INTEL_VBIOS_SIZE, 1, f) != 1) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't write BIOS data\n");
-    }
 
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Wrote BIOS contents to %s\n",
-	       filename);
-    fclose(f);
+    entry = &lvds_lfp_data->data[lvds_options->panel_type];
+    timing_ptr = (unsigned char *)&entry->dvo_timing;
+
+    fixed_mode = xnfalloc(sizeof(DisplayModeRec));
+    memset(fixed_mode, 0, sizeof(*fixed_mode));
+
+    /* Since lvds_bdb_2_fp_edid_dtd is just an EDID detailed timing
+     * block, pull the contents out using EDID macros.
+     */
+    fixed_mode->HDisplay   = _H_ACTIVE(timing_ptr);
+    fixed_mode->VDisplay   = _V_ACTIVE(timing_ptr);
+    fixed_mode->HSyncStart = fixed_mode->HDisplay +
+	_H_SYNC_OFF(timing_ptr);
+    fixed_mode->HSyncEnd   = fixed_mode->HSyncStart +
+	_H_SYNC_WIDTH(timing_ptr);
+    fixed_mode->HTotal     = fixed_mode->HDisplay +
+	_H_BLANK(timing_ptr);
+    fixed_mode->VSyncStart = fixed_mode->VDisplay +
+	_V_SYNC_OFF(timing_ptr);
+    fixed_mode->VSyncEnd   = fixed_mode->VSyncStart +
+	_V_SYNC_WIDTH(timing_ptr);
+    fixed_mode->VTotal     = fixed_mode->VDisplay +
+	_V_BLANK(timing_ptr);
+    fixed_mode->Clock      = _PIXEL_CLOCK(timing_ptr) / 1000;
+    fixed_mode->type       = M_T_PREFERRED;
+
+    xf86SetModeDefaultName(fixed_mode);
+
+    pI830->lvds_fixed_mode = fixed_mode;
 }
 
-static void *
-find_section(struct bdb_header *bdb, int section_id)
+static void
+parse_general_features(I830Ptr pI830, struct bdb_header *bdb)
 {
-	unsigned char *base = (unsigned char *)bdb;
-	int index = 0;
-	uint16_t total, current_size;
-	unsigned char current_id;
-
-	/* skip to first section */
-	index += bdb->header_size;
-	total = bdb->bdb_size;
-
-	/* walk the sections looking for section_id */
-	while (index < total) {
-		current_id = *(base + index);
-		index++;
-		current_size = *((uint16_t *)(base + index));
-		index += 2;
-		if (current_id == section_id)
-			return base + index;
-		index += current_size;
-	}
-
-	return NULL;
+    struct bdb_general_features *general;
+
+    /* Set sensible defaults in case we can't find the general block */
+    pI830->tv_present = 1;
+
+    general = find_section(bdb, BDB_GENERAL_FEATURES);
+    if (!general)
+	return;
+
+    pI830->tv_present = general->int_tv_support;
+    pI830->lvds_use_ssc = general->enable_ssc;
+    if (pI830->lvds_use_ssc) {
+	if (IS_I855(pI830))
+	    pI830->lvds_ssc_freq = general->ssc_freq ? 66 : 48;
+	else
+	    pI830->lvds_ssc_freq = general->ssc_freq ? 100 : 96;
+    }


Reply to: