xf86-video-intel: 2 commits - src/i830_bios.c src/i830_bios.h src/i830_display.c src/i830.h src/i830_lvds.c src/i830_tv.c

Jesse Barnes jbarnes at kemper.freedesktop.org
Thu Jul 10 12:58:25 PDT 2008


 src/i830.h         |    4 ++
 src/i830_bios.c    |   90 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/i830_bios.h    |   93 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/i830_display.c |   18 +++++++---
 src/i830_lvds.c    |    3 +
 src/i830_tv.c      |    4 ++
 6 files changed, 207 insertions(+), 5 deletions(-)

New commits:
commit 3c0f2bcc9965155fecab606edae68874427d3423
Author: Jesse Barnes <jbarnes at jbarnes-t61.(none)>
Date:   Thu Jul 10 12:57:25 2008 -0700

    Add VBIOS based TV connector detection
    
    Now that the VBIOS code supports it, we can use the general features block to
    detect whether a TV connector is present on a given platform.
    
    Reviewed by Nanhai Zou.

diff --git a/src/i830_tv.c b/src/i830_tv.c
index cde929a..651f77b 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1715,6 +1715,10 @@ i830_tv_init(ScrnInfoPtr pScrn)
 	    (tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
 	return;
 
+    i830_bios_get_tv(pScrn);
+    if (!pI830->tv_present) /* VBIOS claims no TV connector */
+	return;
+
     output = xf86OutputCreate (pScrn, &i830_tv_output_funcs, "TV");
 
     if (!output)
commit e00d9435609bcff1afb71aa6638a6b42a64f5178
Author: Jesse Barnes <jbarnes at jbarnes-t61.(none)>
Date:   Thu Jul 10 12:55:12 2008 -0700

    Improve VBIOS feature detection, add SSC support
    
    Improve the VBIOS feature detection and use it to find whether the platform
    supports spread spectrum clocking.  Use the specified reference clock, but
    disable SSC if multiple heads are active, since it can cause problems in cloned
    configurations.
    
    Reviewed by Nanhai Zou.

diff --git a/src/i830.h b/src/i830.h
index 570db13..68690f7 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -554,6 +554,10 @@ typedef struct _I830Rec {
    OptionInfoPtr Options;
 
    Bool lvds_24_bit_mode;
+   Bool lvds_use_ssc;
+   int lvds_ssc_freq; /* in MHz */
+
+   Bool tv_present; /* TV connector present (from VBIOS) */
 
    Bool StolenOnly;
 
diff --git a/src/i830_bios.c b/src/i830_bios.c
index 57ee278..a8193fc 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -70,6 +70,32 @@ i830DumpBIOSToFile(ScrnInfoPtr pScrn, unsigned char *bios)
     fclose(f);
 }
 
+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;
+}
+
 /**
  * Loads the Video BIOS and checks that the VBT exists.
  *
@@ -127,6 +153,70 @@ i830_bios_get (ScrnInfoPtr pScrn)
     return bios;
 }
 
+void
+i830_bios_get_ssc(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    struct vbt_header *vbt;
+    struct bdb_header *bdb;
+    struct bdb_general_features *bdb_features;
+    int vbt_off, bdb_off;
+    unsigned char *bios;
+
+    bios = i830_bios_get(pScrn);
+
+    if (bios == NULL)
+	return;
+
+    vbt_off = INTEL_BIOS_16(0x1a);
+    vbt = (struct vbt_header *)(bios + vbt_off);
+    bdb_off = vbt_off + vbt->bdb_offset;
+    bdb = (struct bdb_header *)(bios + bdb_off);
+
+    bdb_features = find_section(bdb, BDB_GENERAL_FEATURES);
+    if (!bdb_features)
+	return;
+
+    pI830->lvds_use_ssc = bdb_features->enable_ssc;
+    if (pI830->lvds_use_ssc) {
+	if (IS_I855(pI830))
+	    pI830->lvds_ssc_freq = bdb_features->ssc_freq ? 66 : 48;
+	else
+	    pI830->lvds_ssc_freq = bdb_features->ssc_freq ? 100 : 96;
+    }
+
+    xfree(bios);
+}
+
+void
+i830_bios_get_tv(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    struct vbt_header *vbt;
+    struct bdb_header *bdb;
+    struct bdb_general_features *bdb_features;
+    int vbt_off, bdb_off;
+    unsigned char *bios;
+
+    bios = i830_bios_get(pScrn);
+
+    if (bios == NULL)
+	return;
+
+    vbt_off = INTEL_BIOS_16(0x1a);
+    vbt = (struct vbt_header *)(bios + vbt_off);
+    bdb_off = vbt_off + vbt->bdb_offset;
+    bdb = (struct bdb_header *)(bios + bdb_off);
+
+    bdb_features = find_section(bdb, BDB_GENERAL_FEATURES);
+    if (!bdb_features)
+	return;
+
+    pI830->tv_present = bdb_features->int_tv_support;
+
+    xfree(bios);
+}
+
 /**
  * Returns the BIOS's fixed panel mode.
  *
diff --git a/src/i830_bios.h b/src/i830_bios.h
index 95230f5..c1ba50d 100644
--- a/src/i830_bios.h
+++ b/src/i830_bios.h
@@ -49,6 +49,97 @@ struct bdb_header {
     uint16_t bdb_size;			/**< in bytes */
 } __attribute__((packed));
 
+/*
+ * There are several types of BIOS data blocks (BDBs), each block has
+ * an ID and size in the first 3 bytes (ID in first, size in next 2).
+ * Known types are listed below.
+ */
+#define BDB_GENERAL_FEATURES	  1
+#define BDB_GENERAL_DEFINITIONS	  2
+#define BDB_OLD_TOGGLE_LIST	  3
+#define BDB_MODE_SUPPORT_LIST	  4
+#define BDB_GENERIC_MODE_TABLE	  5
+#define BDB_EXT_MMIO_REGS	  6
+#define BDB_SWF_IO		  7
+#define BDB_SWF_MMIO		  8
+#define BDB_DOT_CLOCK_TABLE	  9
+#define BDB_MODE_REMOVAL_TABLE	 10
+#define BDB_CHILD_DEVICE_TABLE	 11
+#define BDB_DRIVER_FEATURES	 12
+#define BDB_DRIVER_PERSISTENCE	 13
+#define BDB_EXT_TABLE_PTRS	 14
+#define BDB_DOT_CLOCK_OVERRIDE	 15
+#define BDB_DISPLAY_SELECT	 16
+/* 17 rsvd */
+#define BDB_DRIVER_ROTATION	 18
+#define BDB_DISPLAY_REMOVE	 19
+#define BDB_OEM_CUSTOM		 20
+#define BDB_EFP_LIST		 21 /* workarounds for VGA hsync/vsync */
+#define BDB_SDVO_LVDS_OPTIONS	 22
+#define BDB_SDVO_PANEL_DTDS	 23
+#define BDB_SDVO_LVDS_PNP_IDS	 24
+#define BDB_SDVO_LVDS_POWER_SEQ	 25
+#define BDB_TV_OPTIONS		 26
+#define BDB_LVDS_OPTIONS	 40
+#define BDB_LVDS_LFP_DATA_PTRS	 41
+#define BDB_LVDS_LFP_DATA	 42
+#define BDB_LVDS_BACKLIGHT	 43
+#define BDB_LVDS_POWER		 44
+#define BDB_SKIP		254 /* VBIOS private block, ignore */
+
+struct bdb_general_features {
+        /* bits 1 */
+	unsigned char panel_fitting:2;
+	unsigned char flexaim:1;
+	unsigned char msg_enable:1;
+	unsigned char clear_screen:3;
+	unsigned char color_flip:1;
+
+        /* bits 2 */
+	unsigned char download_ext_vbt:1;
+	unsigned char enable_ssc:1;
+	unsigned char ssc_freq:1;
+	unsigned char enable_lfp_on_override:1;
+	unsigned char disable_ssc_ddt:1;
+	unsigned char rsvd8:3; /* finish byte */
+
+        /* bits 3 */
+	unsigned char disable_smooth_vision:1;
+	unsigned char single_dvi:1;
+	unsigned char rsvd9:6; /* finish byte */
+
+        /* bits 4 */
+	unsigned char legacy_monitor_detect;
+
+        /* bits 5 */
+	unsigned char int_crt_support:1;
+	unsigned char int_tv_support:1;
+	unsigned char rsvd11:6; /* finish byte */
+} __attribute__((packed));
+
+struct bdb_general_definitions {
+	/* DDC GPIO */
+	unsigned char crt_ddc_gmbus_pin;
+
+	/* DPMS bits */
+	unsigned char dpms_acpi:1;
+	unsigned char skip_boot_crt_detect:1;
+	unsigned char dpms_aim:1;
+	unsigned char rsvd1:5; /* finish byte */
+
+	/* boot device bits */
+	unsigned char boot_display[2];
+	unsigned char child_dev_size;
+
+	/* device info */
+	unsigned char tv_or_lvds_info[33];
+	unsigned char dev1[33];
+	unsigned char dev2[33];
+	unsigned char dev3[33];
+	unsigned char dev4[33];
+	/* may be another device block here on some platforms */
+};
+
 #define LVDS_CAP_EDID			(1 << 6)
 #define LVDS_CAP_DITHER			(1 << 5)
 #define LVDS_CAP_PFIT_AUTO_RATIO	(1 << 4)
@@ -150,6 +241,8 @@ struct vch_bdb_22 {
 unsigned char *
 i830_bios_get (ScrnInfoPtr pScrn);
 
+void i830_bios_get_ssc(ScrnInfoPtr pScrn);
+void i830_bios_get_tv(ScrnInfoPtr pScrn);
 DisplayModePtr i830_bios_get_panel_mode(ScrnInfoPtr pScrn, Bool *wants_dither);
 
 unsigned char *
diff --git a/src/i830_display.c b/src/i830_display.c
index 306fed4..3967b69 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1128,7 +1128,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
     int dsppos_reg = (plane == 0) ? DSPAPOS : DSPBPOS;
     int dspsize_reg = (plane == 0) ? DSPASIZE : DSPBSIZE;
     int pipestat_reg = (pipe == 0) ? PIPEASTAT : PIPEBSTAT;
-    int i;
+    int i, num_outputs = 0;
     int refclk;
     intel_clock_t clock;
     uint32_t dpll = 0, fp = 0, dspcntr, pipeconf, lvds_bits = 0;
@@ -1168,9 +1168,19 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	    is_crt = TRUE;
 	    break;
 	}
+
+	num_outputs++;
     }
 
-    if (IS_I9XX(pI830)) {
+    if (num_outputs > 1)
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "clone detected, disabling SSC\n");
+
+    /* Don't use SSC when cloned */
+    if (pI830->lvds_use_ssc && num_outputs < 2) {
+	refclk = pI830->lvds_ssc_freq * 1000;
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "using SSC reference clock of %d MHz\n", refclk / 1000);
+    } else if (IS_I9XX(pI830)) {
 	refclk = 96000;
     } else {
 	refclk = 48000;
@@ -1246,10 +1256,8 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 /*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
 	dpll |= 3;
     }
-#if 0
-    else if (is_lvds)
+    else if (is_lvds && pI830->lvds_use_ssc && num_outputs < 2)
 	dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
-#endif
     else
 	dpll |= PLL_REF_INPUT_DREFCLK;
 
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index d1bbb3a..c7f2434 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -1341,6 +1341,9 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 	goto disable_exit;
     }
 
+    /* Update pI830 w/SSC info, if any */
+    i830_bios_get_ssc(pScrn);
+
  skip_panel_fixed_mode_setup:
 
     /* Blacklist machines with BIOSes that list an LVDS panel without actually


More information about the xorg-commit mailing list