diff -Naur xserver-xorg-video-intel.orig/src/bios_reader/bios_reader.c xserver-xorg-video-intel.vbios/src/bios_reader/bios_reader.c --- xserver-xorg-video-intel.orig/src/bios_reader/bios_reader.c 2008-03-25 18:15:45.000000000 -0700 +++ xserver-xorg-video-intel.vbios/src/bios_reader/bios_reader.c 2008-07-18 15:54:45.000000000 -0700 @@ -25,11 +25,17 @@ * */ +#include +#include #include #include #include +#include +#include +#include #include + #include "../i830_bios.h" #define _PARSE_EDID_ @@ -51,108 +57,223 @@ (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) { + printf("usage: %s \n", argv[0]); + return 1; + } + + filename = argv[1]; + + fd = open(filename, O_RDONLY); + if (fd == -1) { + printf("Couldn't open \"%s\": %s\n", filename, strerror(errno)); + return 1; + } - if (argc == 2) - filename = argv[1]; + if (stat(filename, &finfo)) { + printf("failed to stat \"%s\": %s\n", filename, strerror(errno)); + return 1; + } - f = fopen(filename, "r"); - if (!f) { - printf("Couldn't open %s\n", filename); + 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; } - pI830->VBIOS = calloc(1, bios_size); - if (fread(pI830->VBIOS, 1, bios_size, f) != bios_size) + /* 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 -Naur xserver-xorg-video-intel.orig/src/i830_bios.c xserver-xorg-video-intel.vbios/src/i830_bios.c --- xserver-xorg-video-intel.orig/src/i830_bios.c 2008-04-21 00:06:29.000000000 -0700 +++ xserver-xorg-video-intel.vbios/src/i830_bios.c 2008-07-18 16:12:51.000000000 -0700 @@ -39,58 +39,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; + + /* Defaults if we can't find VBT info */ + pI830->lvds_dither = 0; - f = fopen(filename, "w"); - if (f == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Couldn't open %s\n", filename); + 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; - } - 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); + lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); + if (!lvds_lfp_data) + return; + + 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 +parse_general_features(I830Ptr pI830, struct bdb_header *bdb) +{ + 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; + } } /** - * Loads the Video BIOS and checks that the VBT exists. + * i830_bios_init - map VBIOS, find VBT * * VBT existence is a sanity check that is relied on by other i830_bios.c code. * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may * feed an updated VBT back through that, compared to what we'll fetch using * this method of groping around in the BIOS data. + * + * Returns 0 on success, nonzero on failure. */ -unsigned char * -i830_bios_get (ScrnInfoPtr pScrn) +int +i830_bios_init(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); struct vbt_header *vbt; - int vbt_off; + struct bdb_header *bdb; + int vbt_off, bdb_off; unsigned char *bios; vbeInfoPtr pVbe; bios = xalloc(INTEL_VBIOS_SIZE); if (bios == NULL) - return NULL; + return -1; - pVbe = VBEInit (NULL, pI830->pEnt->index); + pVbe = VBEInit(NULL, pI830->pEnt->index); if (pVbe != NULL) { memcpy(bios, xf86int10Addr(pVbe->pInt10, pVbe->pInt10->BIOSseg << 4), @@ -104,15 +198,12 @@ #endif } - if (0) - i830DumpBIOSToFile(pScrn, bios); - vbt_off = INTEL_BIOS_16(0x1a); if (vbt_off >= INTEL_VBIOS_SIZE) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT offset: 0x%x\n", vbt_off); xfree(bios); - return NULL; + return -1; } vbt = (struct vbt_header *)(bios + vbt_off); @@ -120,179 +211,17 @@ if (memcmp(vbt->signature, "$VBT", 4) != 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad VBT signature\n"); xfree(bios); - return NULL; + return -1; } - return bios; -} - -/** - * 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. - */ -DisplayModePtr -i830_bios_get_panel_mode(ScrnInfoPtr pScrn, Bool *wants_dither) -{ - I830Ptr pI830 = I830PTR(pScrn); - struct vbt_header *vbt; - struct bdb_header *bdb; - int vbt_off, bdb_off, bdb_block_off, block_size; - int panel_type = -1; - unsigned char *bios; - - bios = i830_bios_get (pScrn); - - if (bios == NULL) - return NULL; - - vbt_off = INTEL_BIOS_16(0x1a); - vbt = (struct vbt_header *)(bios + vbt_off); + /* Now that we've found the VBIOS, go scour the VBTs */ bdb_off = vbt_off + vbt->bdb_offset; bdb = (struct bdb_header *)(bios + bdb_off); - if (memcmp(bdb->signature, "BIOS_DATA_BLOCK ", 16) != 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad BDB signature\n"); - xfree(bios); - return NULL; - } - - *wants_dither = FALSE; - 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; - DisplayModePtr fixed_mode; - uint8_t *timing_ptr; - - id = INTEL_BIOS_8(start); - block_size = INTEL_BIOS_16(start + 1) + 3; - switch (id) { - case 40: - lvds1 = (struct lvds_bdb_1 *)(bios + start); - panel_type = lvds1->panel_type; - if (lvds1->caps & LVDS_CAP_DITHER) - *wants_dither = TRUE; - break; - case 41: - if (panel_type == -1) - break; - - lvds2 = (struct lvds_bdb_2 *)(bios + start); - fpparam = (struct lvds_bdb_2_fp_params *)(bios + - bdb_off + lvds2->panels[panel_type].fp_params_offset); - fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(bios + - bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset); - timing_ptr = bios + bdb_off + - lvds2->panels[panel_type].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 *)(bios + - bdb_off + lvds2->panels[panel_type].fp_params_offset + 8); - fptiming = (struct lvds_bdb_2_fp_edid_dtd *)(bios + - bdb_off + lvds2->panels[panel_type].fp_edid_dtd_offset + 8); - timing_ptr = bios + bdb_off + - lvds2->panels[panel_type].fp_edid_dtd_offset + 8; - - if (fpparam->terminator != 0xffff) - continue; - } - - 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); - - if (pI830->debug_modes) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Found panel mode in BIOS VBT tables:\n"); - xf86PrintModeline(pScrn->scrnIndex, fixed_mode); - } - - xfree(bios); - return fixed_mode; - } - } + parse_general_features(pI830, bdb); + parse_panel_data(pI830, bdb); xfree(bios); - return NULL; -} - -unsigned char * -i830_bios_get_aim_data_block (ScrnInfoPtr pScrn, int aim, int data_block) -{ - unsigned char *bios; - int bdb_off; - int vbt_off; - int aim_off; - struct vbt_header *vbt; - struct aimdb_header *aimdb; - struct aimdb_block *aimdb_block; - - bios = i830_bios_get (pScrn); - if (!bios) - return NULL; - vbt_off = INTEL_BIOS_16(0x1a); - vbt = (struct vbt_header *)(bios + vbt_off); - - aim_off = vbt->aim_offset[aim]; - if (!aim_off) - { - xfree (bios); - return NULL; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "aim_off %d\n", aim_off); - aimdb = (struct aimdb_header *) (bios + vbt_off + aim_off); - bdb_off = aimdb->aimdb_header_size; - while (bdb_off < aimdb->aimdb_size) - { - aimdb_block = (struct aimdb_block *) (bios + vbt_off + aim_off + bdb_off); - if (aimdb_block->aimdb_id == data_block) - { - unsigned char *aim = malloc (aimdb_block->aimdb_size + sizeof (struct aimdb_block)); - if (!aim) - { - xfree (bios); - return NULL; - } - memcpy (aim, aimdb_block, aimdb_block->aimdb_size + sizeof (struct aimdb_block)); - xfree (bios); - return aim; - } - bdb_off += aimdb_block->aimdb_size + sizeof (struct aimdb_block); - } - xfree (bios); - return NULL; + return 0; } diff -Naur xserver-xorg-video-intel.orig/src/i830_bios.h xserver-xorg-video-intel.vbios/src/i830_bios.h --- xserver-xorg-video-intel.orig/src/i830_bios.h 2008-03-25 18:15:45.000000000 -0700 +++ xserver-xorg-video-intel.vbios/src/i830_bios.h 2008-07-18 16:09:41.000000000 -0700 @@ -49,6 +49,97 @@ 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) @@ -56,15 +147,22 @@ #define LVDS_CAP_PFIT_TEXT_MODE (1 << 2) #define LVDS_CAP_PFIT_GRAPHICS (1 << 1) #define LVDS_CAP_PFIT_TEXT (1 << 0) -struct lvds_bdb_1 { - uint8_t id; /**< 40 */ - uint16_t size; + +struct bdb_lvds_options { uint8_t panel_type; - uint8_t reserved0; - uint16_t caps; + 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 rsvd4; } __attribute__((packed)); -struct lvds_bdb_2_fp_params { +struct lvds_fp_timing { uint16_t x_res; uint16_t y_res; uint32_t lvds_reg; @@ -80,7 +178,7 @@ uint16_t terminator; } __attribute__((packed)); -struct lvds_bdb_2_fp_edid_dtd { +struct lvds_dvo_timing { uint16_t dclk; /**< In 10khz */ uint8_t hactive; uint8_t hblank; @@ -102,20 +200,37 @@ #define FP_EDID_FLAG_HSYNC_POSITIVE (1 << 1) } __attribute__((packed)); -struct lvds_bdb_2_entry { - uint16_t fp_params_offset; /**< From beginning of BDB */ - uint8_t fp_params_size; - uint16_t fp_edid_dtd_offset; - uint8_t fp_edid_dtd_size; - uint16_t fp_edid_pid_offset; - uint8_t fp_edid_pid_size; +struct lvds_pnp_id { + uint16_t mfg_name; + uint16_t product_code; + uint32_t serial; + uint8_t mfg_week; + uint8_t mfg_year; +} __attribute__((packed));; + +/* LFP pointer table contains entries to the struct below */ +struct bdb_lvds_lfp_data_ptr { + uint16_t fp_timing_offset; /* offsets are from start of bdb */ + uint8_t fp_table_size; + uint16_t dvo_timing_offset; + uint8_t dvo_table_size; + uint16_t panel_pnp_id_offset; + uint8_t pnp_table_size; +} __attribute__((packed)); + +struct bdb_lvds_lfp_data_ptrs { + uint8_t lvds_entries; + struct bdb_lvds_lfp_data_ptr ptr[16]; +} __attribute__((packed)); + +struct bdb_lvds_lfp_data_entry { + struct lvds_fp_timing fp_timing; + struct lvds_dvo_timing dvo_timing; + struct lvds_pnp_id pnp_id; } __attribute__((packed)); -struct lvds_bdb_2 { - uint8_t id; /**< 41 */ - uint16_t size; - uint8_t table_size; /* not sure on this one */ - struct lvds_bdb_2_entry panels[16]; +struct bdb_lvds_lfp_data { + struct bdb_lvds_lfp_data_entry data[16]; } __attribute__((packed)); struct aimdb_header { @@ -147,12 +262,6 @@ struct vch_panel_data panels[16]; } __attribute__((packed)); -unsigned char * -i830_bios_get (ScrnInfoPtr pScrn); - -DisplayModePtr i830_bios_get_panel_mode(ScrnInfoPtr pScrn, Bool *wants_dither); - -unsigned char * -i830_bios_get_aim_data_block (ScrnInfoPtr pScrn, int aim, int data_block); +int i830_bios_init(ScrnInfoPtr pScrn); #endif /* _I830_BIOS_H_ */ diff -Naur xserver-xorg-video-intel.orig/src/i830_display.c xserver-xorg-video-intel.vbios/src/i830_display.c --- xserver-xorg-video-intel.orig/src/i830_display.c 2008-04-21 00:06:29.000000000 -0700 +++ xserver-xorg-video-intel.vbios/src/i830_display.c 2008-07-18 15:50:35.000000000 -0700 @@ -1116,7 +1116,11 @@ } } - if (IS_I9XX(pI830)) { + if (pI830->lvds_use_ssc) { + 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; @@ -1189,10 +1193,8 @@ /* dpll |= PLL_REF_INPUT_TVCLKINBC; */ dpll |= 3; } -#if 0 - else if (is_lvds) + else if (is_lvds && pI830->lvds_use_ssc) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; -#endif else dpll |= PLL_REF_INPUT_DREFCLK; diff -Naur xserver-xorg-video-intel.orig/src/i830_driver.c xserver-xorg-video-intel.vbios/src/i830_driver.c --- xserver-xorg-video-intel.orig/src/i830_driver.c 2008-04-21 00:06:47.000000000 -0700 +++ xserver-xorg-video-intel.vbios/src/i830_driver.c 2008-07-18 15:54:45.000000000 -0700 @@ -1556,6 +1556,10 @@ #endif + if (i830_bios_init(pScrn)) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "VBIOS initialization failed.\n"); + I830PreInitDDC(pScrn); for (i = 0; i < num_pipe; i++) { i830_crtc_init(pScrn, i); diff -Naur xserver-xorg-video-intel.orig/src/i830_dvo.c xserver-xorg-video-intel.vbios/src/i830_dvo.c --- xserver-xorg-video-intel.orig/src/i830_dvo.c 2008-03-25 19:15:53.000000000 -0700 +++ xserver-xorg-video-intel.vbios/src/i830_dvo.c 2008-07-18 15:54:45.000000000 -0700 @@ -165,8 +165,9 @@ static int i830_dvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) { + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; - struct _I830DVODriver *drv = intel_output->i2c_drv; void *dev_priv = intel_output->i2c_drv->dev_priv; if (pMode->Flags & V_DBLSCAN) @@ -174,10 +175,10 @@ /* XXX: Validate clock range */ - if (drv->panel_fixed_mode) { - if (pMode->HDisplay > drv->panel_fixed_mode->HDisplay) + if (pI830->lvds_fixed_mode) { + if (pMode->HDisplay > pI830->lvds_fixed_mode->HDisplay) return MODE_PANEL; - if (pMode->VDisplay > drv->panel_fixed_mode->VDisplay) + if (pMode->VDisplay > pI830->lvds_fixed_mode->VDisplay) return MODE_PANEL; } @@ -188,24 +189,25 @@ i830_dvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) { + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; - struct _I830DVODriver *drv = intel_output->i2c_drv; /* If we have timings from the BIOS for the panel, put them in * to the adjusted mode. The CRTC will be set up for this mode, * with the panel scaling set up to source from the H/VDisplay * of the original mode. */ - if (drv->panel_fixed_mode != NULL) { - adjusted_mode->HDisplay = drv->panel_fixed_mode->HDisplay; - adjusted_mode->HSyncStart = drv->panel_fixed_mode->HSyncStart; - adjusted_mode->HSyncEnd = drv->panel_fixed_mode->HSyncEnd; - adjusted_mode->HTotal = drv->panel_fixed_mode->HTotal; - adjusted_mode->VDisplay = drv->panel_fixed_mode->VDisplay; - adjusted_mode->VSyncStart = drv->panel_fixed_mode->VSyncStart; - adjusted_mode->VSyncEnd = drv->panel_fixed_mode->VSyncEnd; - adjusted_mode->VTotal = drv->panel_fixed_mode->VTotal; - adjusted_mode->Clock = drv->panel_fixed_mode->Clock; + if (pI830->lvds_fixed_mode != NULL) { + adjusted_mode->HDisplay = pI830->lvds_fixed_mode->HDisplay; + adjusted_mode->HSyncStart = pI830->lvds_fixed_mode->HSyncStart; + adjusted_mode->HSyncEnd = pI830->lvds_fixed_mode->HSyncEnd; + adjusted_mode->HTotal = pI830->lvds_fixed_mode->HTotal; + adjusted_mode->VDisplay = pI830->lvds_fixed_mode->VDisplay; + adjusted_mode->VSyncStart = pI830->lvds_fixed_mode->VSyncStart; + adjusted_mode->VSyncEnd = pI830->lvds_fixed_mode->VSyncEnd; + adjusted_mode->VTotal = pI830->lvds_fixed_mode->VTotal; + adjusted_mode->Clock = pI830->lvds_fixed_mode->Clock; xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V); } @@ -287,8 +289,9 @@ static DisplayModePtr i830_dvo_get_modes(xf86OutputPtr output) { + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; - struct _I830DVODriver *drv = intel_output->i2c_drv; DisplayModePtr modes; /* We should probably have an i2c driver get_modes function for those @@ -307,8 +310,8 @@ return modes; } - if (drv->panel_fixed_mode != NULL) - return xf86DuplicateMode(drv->panel_fixed_mode); + if (pI830->lvds_fixed_mode != NULL) + return xf86DuplicateMode(pI830->lvds_fixed_mode); return NULL; } @@ -530,8 +533,8 @@ * so for now, just get the current mode being output through * DVO. */ - drv->panel_fixed_mode = i830_dvo_get_current_mode(output); - drv->panel_wants_dither = TRUE; + pI830->lvds_fixed_mode = i830_dvo_get_current_mode(output); + pI830->lvds_dither = TRUE; } return; diff -Naur xserver-xorg-video-intel.orig/src/i830.h xserver-xorg-video-intel.vbios/src/i830.h --- xserver-xorg-video-intel.orig/src/i830.h 2008-04-21 00:06:29.000000000 -0700 +++ xserver-xorg-video-intel.vbios/src/i830.h 2008-07-18 16:11:10.000000000 -0700 @@ -251,8 +251,6 @@ I830I2CVidOutputRec *vid_rec; void *dev_priv; pointer modhandle; - DisplayModePtr panel_fixed_mode; - Bool panel_wants_dither; }; extern const char *i830_output_type_names[]; @@ -549,6 +547,14 @@ OptionInfoPtr Options; Bool lvds_24_bit_mode; + Bool lvds_use_ssc; + int lvds_ssc_freq; /* in MHz */ + Bool lvds_dither; + DisplayModePtr lvds_fixed_mode; + DisplayModePtr lvds_ddc_mode; + Bool skip_panel_detect; + + Bool tv_present; /* TV connector present (from VBIOS) */ Bool StolenOnly; diff -Naur xserver-xorg-video-intel.orig/src/i830_lvds.c xserver-xorg-video-intel.vbios/src/i830_lvds.c --- xserver-xorg-video-intel.orig/src/i830_lvds.c 2008-04-14 01:55:53.000000000 -0700 +++ xserver-xorg-video-intel.vbios/src/i830_lvds.c 2008-07-18 16:09:05.000000000 -0700 @@ -57,12 +57,6 @@ }; struct i830_lvds_priv { - /* The BIOS's fixed timings for the LVDS */ - DisplayModePtr panel_fixed_mode; - - /* The panel needs dithering enabled */ - Bool panel_wants_dither; - /* restore backlight to this value */ int backlight_duty_cycle; @@ -472,9 +466,9 @@ static int i830_lvds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) { - I830OutputPrivatePtr intel_output = output->driver_private; - struct i830_lvds_priv *dev_priv = intel_output->dev_priv; - DisplayModePtr pFixedMode = dev_priv->panel_fixed_mode; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr pFixedMode = pI830->lvds_fixed_mode; if (pFixedMode) { @@ -522,7 +516,7 @@ } /* If we don't have a panel mode there's not much we can do */ - if (dev_priv->panel_fixed_mode == NULL) + if (pI830->lvds_fixed_mode == NULL) return TRUE; /* If we have timings from the BIOS for the panel, put them in @@ -530,19 +524,19 @@ * with the panel scaling set up to source from the H/VDisplay * of the original mode. */ - adjusted_mode->HDisplay = dev_priv->panel_fixed_mode->HDisplay; - adjusted_mode->HSyncStart = dev_priv->panel_fixed_mode->HSyncStart; - adjusted_mode->HSyncEnd = dev_priv->panel_fixed_mode->HSyncEnd; - adjusted_mode->HTotal = dev_priv->panel_fixed_mode->HTotal; - adjusted_mode->VDisplay = dev_priv->panel_fixed_mode->VDisplay; - adjusted_mode->VSyncStart = dev_priv->panel_fixed_mode->VSyncStart; - adjusted_mode->VSyncEnd = dev_priv->panel_fixed_mode->VSyncEnd; - adjusted_mode->VTotal = dev_priv->panel_fixed_mode->VTotal; - adjusted_mode->Clock = dev_priv->panel_fixed_mode->Clock; + adjusted_mode->HDisplay = pI830->lvds_fixed_mode->HDisplay; + adjusted_mode->HSyncStart = pI830->lvds_fixed_mode->HSyncStart; + adjusted_mode->HSyncEnd = pI830->lvds_fixed_mode->HSyncEnd; + adjusted_mode->HTotal = pI830->lvds_fixed_mode->HTotal; + adjusted_mode->VDisplay = pI830->lvds_fixed_mode->VDisplay; + adjusted_mode->VSyncStart = pI830->lvds_fixed_mode->VSyncStart; + adjusted_mode->VSyncEnd = pI830->lvds_fixed_mode->VSyncEnd; + adjusted_mode->VTotal = pI830->lvds_fixed_mode->VTotal; + adjusted_mode->Clock = pI830->lvds_fixed_mode->Clock; xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V); /* Make sure pre-965s set dither correctly */ - if (!IS_I965G(pI830) && dev_priv->panel_wants_dither) + if (!IS_I965G(pI830) && pI830->lvds_dither) pfit_control |= PANEL_8TO6_DITHER_ENABLE; /* Native modes don't need fitting */ @@ -583,12 +577,12 @@ * LVDS borders are enabled (see i830_display.c). */ left_border = - (dev_priv->panel_fixed_mode->HDisplay - mode->HDisplay) / 2; + (pI830->lvds_fixed_mode->HDisplay - mode->HDisplay) / 2; right_border = left_border; if (mode->HDisplay & 1) right_border++; top_border = - (dev_priv->panel_fixed_mode->VDisplay - mode->VDisplay) / 2; + (pI830->lvds_fixed_mode->VDisplay - mode->VDisplay) / 2; bottom_border = top_border; if (mode->VDisplay & 1) bottom_border++; @@ -647,7 +641,7 @@ HORIZ_INTERP_BILINEAR; /* Pillar will have left/right borders */ - left_border = (dev_priv->panel_fixed_mode->HDisplay - + left_border = (pI830->lvds_fixed_mode->HDisplay - scaled_width) / 2; right_border = left_border; if (mode->HDisplay & 1) /* odd resolutions */ @@ -670,7 +664,7 @@ HORIZ_INTERP_BILINEAR; /* Letterbox will have top/bottom borders */ - top_border = (dev_priv->panel_fixed_mode->VDisplay - + top_border = (pI830->lvds_fixed_mode->VDisplay - mode->VDisplay) / 2; bottom_border = top_border; if (mode->VDisplay & 1) @@ -772,8 +766,9 @@ static DisplayModePtr i830_lvds_get_modes(xf86OutputPtr output) { + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; - struct i830_lvds_priv *dev_priv = intel_output->dev_priv; xf86MonPtr edid_mon; DisplayModePtr modes; @@ -802,8 +797,8 @@ } } - if (dev_priv->panel_fixed_mode != NULL) - return xf86DuplicateMode(dev_priv->panel_fixed_mode); + if (pI830->lvds_fixed_mode != NULL) + return xf86DuplicateMode(pI830->lvds_fixed_mode); return NULL; } @@ -811,13 +806,13 @@ static void i830_lvds_destroy (xf86OutputPtr output) { + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; - if (intel_output) + if (pI830->lvds_fixed_mode) { - struct i830_lvds_priv *dev_priv = intel_output->dev_priv; - - xf86DeleteMode (&dev_priv->panel_fixed_mode, dev_priv->panel_fixed_mode); + xf86DeleteMode (&pI830->lvds_fixed_mode, pI830->lvds_fixed_mode); xfree (intel_output); } } @@ -1195,7 +1190,7 @@ I830Ptr pI830 = I830PTR(pScrn); xf86OutputPtr output; I830OutputPrivatePtr intel_output; - DisplayModePtr modes, scan, bios_mode; + DisplayModePtr modes, scan; struct i830_lvds_priv *dev_priv; if (pI830->quirk_flag & QUIRK_IGNORE_LVDS) @@ -1223,6 +1218,15 @@ dev_priv = (struct i830_lvds_priv *) (intel_output + 1); intel_output->dev_priv = dev_priv; + /* + * Mode detection algorithms for LFP: + * 1) if EDID present, use it, done + * 2) if VBT present, use it, done + * 3) if current mode is programmed, use it, done + * 4) check for Mac mini & other quirks + * 4) fail, assume no LFP + */ + /* Set up the LVDS DDC channel. Most panels won't support it, but it can * be useful if available. */ @@ -1244,73 +1248,45 @@ scan->prev = scan->next; if (scan->next != NULL) scan->next = scan->prev; - dev_priv->panel_fixed_mode = scan; + pI830->lvds_ddc_mode = scan; } /* Delete the mode list */ while (modes != NULL) xf86DeleteMode(&modes, modes); - /* If we didn't get EDID, try checking if the panel is already turned on. - * If so, assume that whatever is currently programmed is the correct mode. + if (pI830->lvds_ddc_mode) { + pI830->lvds_fixed_mode = pI830->lvds_ddc_mode; + goto found_mode; + } + + /* Get the LVDS fixed mode out of the BIOS. We should support LVDS with + * the BIOS being unavailable or broken, but lack the configuration options + * for now. + */ + if (pI830->lvds_fixed_mode) + goto found_mode; + + /* If we *still* don't have a mode, try checking if the panel is already + * turned on. If so, assume that whatever is currently programmed is the + * correct mode. */ - if (dev_priv->panel_fixed_mode == NULL) { + if (pI830->lvds_fixed_mode == NULL) { uint32_t lvds = INREG(LVDS); int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); xf86CrtcPtr crtc = xf86_config->crtc[pipe]; if (lvds & LVDS_PORT_EN) { - dev_priv->panel_fixed_mode = i830_crtc_mode_get(pScrn, crtc); - if (dev_priv->panel_fixed_mode != NULL) - dev_priv->panel_fixed_mode->type |= M_T_PREFERRED; + pI830->lvds_fixed_mode = i830_crtc_mode_get(pScrn, crtc); + if (pI830->lvds_fixed_mode != NULL) + pI830->lvds_fixed_mode->type |= M_T_PREFERRED; } } - /* Get the LVDS fixed mode out of the BIOS. We should support LVDS with - * the BIOS being unavailable or broken, but lack the configuration options - * for now. - */ - bios_mode = i830_bios_get_panel_mode(pScrn, &dev_priv->panel_wants_dither); - if (bios_mode != NULL) { - if (dev_priv->panel_fixed_mode != NULL) { - /* Fixup for a 1280x768 panel with the horizontal trimmed - * down to 1024 for text mode. - */ - if (!xf86ModesEqual(dev_priv->panel_fixed_mode, bios_mode) && - dev_priv->panel_fixed_mode->HDisplay == 1024 && - dev_priv->panel_fixed_mode->HSyncStart == 1200 && - dev_priv->panel_fixed_mode->HSyncEnd == 1312 && - dev_priv->panel_fixed_mode->HTotal == 1688 && - dev_priv->panel_fixed_mode->VDisplay == 768) - { - dev_priv->panel_fixed_mode->HDisplay = 1280; - dev_priv->panel_fixed_mode->HSyncStart = 1328; - dev_priv->panel_fixed_mode->HSyncEnd = 1440; - dev_priv->panel_fixed_mode->HTotal = 1688; - } - - if (pI830->debug_modes && - !xf86ModesEqual(dev_priv->panel_fixed_mode, bios_mode)) - { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "BIOS panel mode data doesn't match probed data, " - "continuing with probed.\n"); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS mode:\n"); - xf86PrintModeline(pScrn->scrnIndex, bios_mode); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "probed mode:\n"); - xf86PrintModeline(pScrn->scrnIndex, dev_priv->panel_fixed_mode); - xfree(bios_mode->name); - xfree(bios_mode); - } - } else { - dev_priv->panel_fixed_mode = bios_mode; - } - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Couldn't detect panel mode. Disabling panel\n"); + if (!pI830->lvds_fixed_mode) goto disable_exit; - } +found_mode: /* Blacklist machines with BIOSes that list an LVDS panel without actually * having one. */ @@ -1324,9 +1300,9 @@ * display. */ - if (dev_priv->panel_fixed_mode != NULL && - dev_priv->panel_fixed_mode->HDisplay == 800 && - dev_priv->panel_fixed_mode->VDisplay == 600) + if (pI830->lvds_fixed_mode != NULL && + pI830->lvds_fixed_mode->HDisplay == 800 && + pI830->lvds_fixed_mode->VDisplay == 600) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Suspected Mac Mini, ignoring the LVDS\n"); diff -Naur xserver-xorg-video-intel.orig/src/i830_tv.c xserver-xorg-video-intel.vbios/src/i830_tv.c --- xserver-xorg-video-intel.orig/src/i830_tv.c 2008-03-25 19:15:53.000000000 -0700 +++ xserver-xorg-video-intel.vbios/src/i830_tv.c 2008-07-18 16:11:34.000000000 -0700 @@ -1711,6 +1711,9 @@ (tv_dac_off & TVDAC_STATE_CHG_EN) != 0) return; + if (!pI830->tv_present) /* VBIOS claims no TV connector */ + return; + output = xf86OutputCreate (pScrn, &i830_tv_output_funcs, "TV"); if (!output)