diff options
author | Jesse Barnes <jbarnes@jbarnes-t61.(none)> | 2008-07-10 12:55:12 -0700 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2008-07-10 12:55:12 -0700 |
commit | e00d9435609bcff1afb71aa6638a6b42a64f5178 (patch) | |
tree | 4e64382957eb97f9321fd7bbf4a10da7743c088f /src/i830_bios.c | |
parent | 7332132a79e5b5c208d43e93dfe0c8b12eb1728d (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.c | 90 |
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. * |