summaryrefslogtreecommitdiff
path: root/src/i830_bios.c
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@jbarnes-t61.(none)>2008-07-10 12:55:12 -0700
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-07-10 12:55:12 -0700
commite00d9435609bcff1afb71aa6638a6b42a64f5178 (patch)
tree4e64382957eb97f9321fd7bbf4a10da7743c088f /src/i830_bios.c
parent7332132a79e5b5c208d43e93dfe0c8b12eb1728d (diff)
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.
Diffstat (limited to 'src/i830_bios.c')
-rw-r--r--src/i830_bios.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/i830_bios.c b/src/i830_bios.c
index 57ee2782..a8193fc5 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.
*