Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright  2007 Intel Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     21  * SOFTWARE.
     22  *
     23  * Authors:
     24  *    Zhenyu Wang <zhenyu.z.wang (at) intel.com>
     25  *
     26  */
     27 #ifdef HAVE_CONFIG_H
     28 #include "config.h"
     29 #endif
     30 
     31 #include "i830.h"
     32 
     33 #define SUBSYS_ANY (~0)
     34 
     35 #define DMIID_DIR "/sys/class/dmi/id/"
     36 #define DMIID_FILE(x) (DMIID_DIR # x)
     37 
     38 typedef struct {
     39     int chipType;
     40     int subsysVendor;
     41     int subsysCard;
     42     void (*hook)(I830Ptr);
     43 } i830_quirk, *i830_quirk_ptr;
     44 
     45 enum i830_dmi_data_t {
     46     bios_vendor,
     47     bios_version,
     48     bios_date,
     49     sys_vendor,
     50     product_name,
     51     product_version,
     52     product_serial,
     53     product_uuid,
     54     board_vendor,
     55     board_name,
     56     board_version,
     57     board_serial,
     58     board_asset_tag,
     59     chassis_vendor,
     60     chassis_type,
     61     chassis_version,
     62     chassis_serial,
     63     chassis_asset_tag,
     64     dmi_data_max,
     65 };
     66 
     67 static char *i830_dmi_data[dmi_data_max];
     68 
     69 #define I830_DMI_FIELD_FUNC(field) \
     70 static void i830_dmi_store_##field(void) \
     71 {\
     72     FILE *f = NULL;\
     73     int ret;\
     74     f = fopen(DMIID_FILE(field), "r");\
     75     if (f == NULL) {\
     76 	xfree(i830_dmi_data[field]); i830_dmi_data[field] = NULL;\
     77 	return;\
     78     }\
     79     ret = fread(i830_dmi_data[field], 64, 1, f);	\
     80     fclose(f);\
     81 }
     82 
     83 I830_DMI_FIELD_FUNC(bios_vendor);
     84 I830_DMI_FIELD_FUNC(bios_version);
     85 I830_DMI_FIELD_FUNC(bios_date);
     86 I830_DMI_FIELD_FUNC(sys_vendor);
     87 I830_DMI_FIELD_FUNC(product_name);
     88 I830_DMI_FIELD_FUNC(product_version);
     89 I830_DMI_FIELD_FUNC(product_serial);
     90 I830_DMI_FIELD_FUNC(product_uuid);
     91 I830_DMI_FIELD_FUNC(board_vendor);
     92 I830_DMI_FIELD_FUNC(board_name);
     93 I830_DMI_FIELD_FUNC(board_version);
     94 I830_DMI_FIELD_FUNC(board_serial);
     95 I830_DMI_FIELD_FUNC(board_asset_tag);
     96 I830_DMI_FIELD_FUNC(chassis_vendor);
     97 I830_DMI_FIELD_FUNC(chassis_type);
     98 I830_DMI_FIELD_FUNC(chassis_version);
     99 I830_DMI_FIELD_FUNC(chassis_serial);
    100 I830_DMI_FIELD_FUNC(chassis_asset_tag);
    101 
    102 static void i830_dmi_scan(void)
    103 {
    104     int i;
    105 
    106     for (i = 0; i < dmi_data_max; i++) {
    107 	i830_dmi_data[i] = xcalloc(64, sizeof(char));
    108 	if (!i830_dmi_data[i]) {
    109 	    int j;
    110 	    for (j = 0; j < i; j++) {
    111 		xfree(i830_dmi_data[j]);
    112 		i830_dmi_data[i] = NULL;
    113 	    }
    114 	    return;
    115 	}
    116     }
    117 
    118     i830_dmi_store_bios_vendor();
    119     i830_dmi_store_bios_version();
    120     i830_dmi_store_bios_date();
    121     i830_dmi_store_sys_vendor();
    122     i830_dmi_store_product_name();
    123     i830_dmi_store_product_version();
    124     i830_dmi_store_product_serial();
    125     i830_dmi_store_product_uuid();
    126     i830_dmi_store_board_vendor();
    127     i830_dmi_store_board_name();
    128     i830_dmi_store_board_version();
    129     i830_dmi_store_board_serial();
    130     i830_dmi_store_board_asset_tag();
    131     i830_dmi_store_chassis_vendor();
    132     i830_dmi_store_chassis_type();
    133     i830_dmi_store_chassis_version();
    134     i830_dmi_store_chassis_serial();
    135     i830_dmi_store_chassis_asset_tag();
    136 }
    137 
    138 #define DMIID_DUMP(field) \
    139     ErrorF("\t" # field ": %s", i830_dmi_data[field] ?\
    140 	    i830_dmi_data[field] : "unknown")
    141 
    142 static void i830_dmi_dump(void)
    143 {
    144     ErrorF("i830_dmi_dump:\n");
    145     DMIID_DUMP(bios_vendor);
    146     DMIID_DUMP(bios_version);
    147     DMIID_DUMP(bios_date);
    148     DMIID_DUMP(sys_vendor);
    149     DMIID_DUMP(product_name);
    150     DMIID_DUMP(product_version);
    151     DMIID_DUMP(product_serial);
    152     DMIID_DUMP(product_uuid);
    153     DMIID_DUMP(board_vendor);
    154     DMIID_DUMP(board_name);
    155     DMIID_DUMP(board_version);
    156     DMIID_DUMP(board_serial);
    157     DMIID_DUMP(board_asset_tag);
    158     DMIID_DUMP(chassis_vendor);
    159     DMIID_DUMP(chassis_type);
    160     DMIID_DUMP(chassis_version);
    161     DMIID_DUMP(chassis_serial);
    162     DMIID_DUMP(chassis_asset_tag);
    163 }
    164 
    165 /*
    166  * Old chips have undocumented panel fitting registers.  Some of them actually
    167  * work; this quirk indicates that.
    168  */
    169 static void quirk_pfit_safe (I830Ptr pI830)
    170 {
    171     pI830->quirk_flag |= QUIRK_PFIT_SAFE;
    172 }
    173 
    174 /*
    175  * Some machines hose the display regs regardless of the ACPI DOS
    176  * setting, so we need to reset modes at ACPI event time.
    177  */
    178 static void quirk_reset_modes (I830Ptr pI830)
    179 {
    180     pI830->quirk_flag |= QUIRK_RESET_MODES;
    181 }
    182 
    183 static void quirk_pipea_force (I830Ptr pI830)
    184 {
    185     pI830->quirk_flag |= QUIRK_PIPEA_FORCE;
    186 }
    187 
    188 static void quirk_ignore_tv (I830Ptr pI830)
    189 {
    190     pI830->quirk_flag |= QUIRK_IGNORE_TV;
    191 }
    192 
    193 static void quirk_ignore_lvds (I830Ptr pI830)
    194 {
    195     pI830->quirk_flag |= QUIRK_IGNORE_LVDS;
    196 }
    197 
    198 static void quirk_ignore_crt (I830Ptr pI830)
    199 {
    200     pI830->quirk_flag |= QUIRK_IGNORE_CRT;
    201 }
    202 
    203 static void quirk_mac_mini (I830Ptr pI830)
    204 {
    205     pI830->quirk_flag |= QUIRK_IGNORE_MACMINI_LVDS;
    206 }
    207 
    208 static void quirk_lenovo_tv_dmi (I830Ptr pI830)
    209 {
    210     /* X60, X60s has no TV output.
    211      * Z61 has S-video TV output.
    212      * And they have same subsys ids...
    213      *
    214      * http://www-307.ibm.com/pc/support/site.wss/MIGR-45120.html
    215      * http://www.thinkwiki.org/wiki/List_of_DMI_IDs
    216      */
    217     if (!i830_dmi_data[bios_version]) {
    218 	ErrorF("Failed to load DMI info, X60 TV quirk not applied.\n");
    219 	return;
    220     }
    221     if (!strncmp(i830_dmi_data[bios_version], "7B", 2) || /* X60, X60s */
    222 	    !strncmp(i830_dmi_data[bios_version], "7E", 2)) /* R60e */
    223 	pI830->quirk_flag |= QUIRK_IGNORE_TV;
    224 }
    225 
    226 static void quirk_msi_lvds_dmi (I830Ptr pI830)
    227 {
    228    /* MSI IM-945GSE-A has no TV output, nor a LVDS connection.
    229     */
    230    if (!i830_dmi_data[board_name]) {
    231        ErrorF("Failed to load DMI info, MSI LVDS quirk not applied.\n");
    232        return;
    233    }
    234    if (!strncmp(i830_dmi_data[board_name],"A9830IMS",8)) {
    235        pI830->quirk_flag |= QUIRK_IGNORE_LVDS;
    236        pI830->quirk_flag |= QUIRK_IGNORE_TV;
    237    }
    238 }
    239 
    240 static void quirk_ibase_lvds (I830Ptr pI830)
    241 {
    242    if (!i830_dmi_data[board_name]) {
    243        ErrorF("Failed to load DMI info, iBase LVDS quirk not applied.\n");
    244        return;
    245    }
    246    if (!strncmp(i830_dmi_data[board_name], "i855-W83627HF", 13)) {
    247        pI830->quirk_flag |= QUIRK_IGNORE_LVDS;
    248    }
    249 }
    250 
    251 static void quirk_ivch_dvob (I830Ptr pI830)
    252 {
    253 	pI830->quirk_flag |= QUIRK_IVCH_NEED_DVOB;
    254 }
    255 
    256 /* For broken hw/bios for incorrect acpi _LID state that
    257    can't be fixed with customed DSDT or other way */
    258 static void quirk_broken_acpi_lid (I830Ptr pI830)
    259 {
    260 	pI830->quirk_flag |= QUIRK_BROKEN_ACPI_LID;
    261 }
    262 
    263 /* keep this list sorted by OEM, then by chip ID */
    264 static i830_quirk i830_quirk_list[] = {
    265     /* Aopen mini pc */
    266     { PCI_CHIP_I915_GM, 0xa0a0, SUBSYS_ANY, quirk_ignore_lvds },
    267     { PCI_CHIP_I945_GM, 0xa0a0, SUBSYS_ANY, quirk_ignore_lvds },
    268     { PCI_CHIP_I965_GM, 0xa0a0, SUBSYS_ANY, quirk_ignore_lvds },
    269     { PCI_CHIP_GM45_GM, 0xa0a0, SUBSYS_ANY, quirk_ignore_lvds },
    270 
    271     { PCI_CHIP_I965_GM, 0x8086, 0x1999, quirk_ignore_lvds },
    272 
    273     /* Apple Mac mini has no lvds, but macbook pro does */
    274     { PCI_CHIP_I945_GM, 0x8086, 0x7270, quirk_mac_mini },
    275 
    276     /* Transtec Senyo 610 mini pc */
    277     { PCI_CHIP_I965_GM, 0x1509, 0x2f15, quirk_ignore_lvds },
    278 
    279     /* Clevo M720R has no tv output */
    280     { PCI_CHIP_I965_GM, 0x1558, 0x0721, quirk_ignore_tv },
    281 
    282     /* Dell Latitude X1 */
    283     { PCI_CHIP_I915_GM, 0x1028, 0x01a3, quirk_ignore_tv },
    284     /* Dell Latitude X1 / D630 (LP: #197740) */
    285     { PCI_CHIP_I915_GM, 0x1028, 0x01f9, quirk_ignore_tv },
    286     /* Dell XPS 1330 */
    287     { PCI_CHIP_I965_GM, 0x1028, 0x0209, quirk_ignore_tv },
    288     /* Dell Inspiron 1535 */
    289     { PCI_CHIP_I965_GM, 0x1028, 0x0254, quirk_ignore_tv },
    290     /* Dell Inspiron 1735 */
    291     { PCI_CHIP_I965_GM, 0x1028, 0x0256, quirk_ignore_tv },
    292     /* Dell Inspiron 1318 */
    293     { PCI_CHIP_I965_GM, 0x1028, 0x0286, quirk_ignore_tv },
    294     /* Dell Vostro A840 (LP: #235155) */
    295     { PCI_CHIP_I965_GM, 0x1028, 0x0298, quirk_ignore_tv },
    296     /* Dell Studio Hybrid */
    297     { PCI_CHIP_I965_GM, 0x1028, 0x0279, quirk_ignore_lvds },
    298 
    299     /* Lenovo Napa TV (use dmi)*/
    300     { PCI_CHIP_I945_GM, 0x17aa, SUBSYS_ANY, quirk_lenovo_tv_dmi },
    301     /* Lenovo 3000 v200 */
    302     { PCI_CHIP_I965_GM, 0x17aa, 0x3c18, quirk_ignore_tv },
    303 
    304     /* MSI IM-945GSE-A has no LVDS or TV (use dmi) */
    305     { PCI_CHIP_I945_GME, 0x8086, 0x27ae, quirk_msi_lvds_dmi },
    306 
    307     /* Panasonic Toughbook CF-Y4 has no TV output */
    308     { PCI_CHIP_I915_GM, 0x10f7, 0x8338, quirk_ignore_tv },
    309     /* Panasonic Toughbook CF-Y7 has no TV output */
    310     { PCI_CHIP_I965_GM, 0x10f7, 0x8338, quirk_ignore_tv },
    311 
    312     /* Toshiba Satellite U300 has no TV output */
    313     { PCI_CHIP_I965_GM, 0x1179, 0xff50, quirk_ignore_tv },
    314     /* Toshiba i830M laptop (fix bug 11148) */
    315     { PCI_CHIP_I830_M, 0x1179, 0xff00, quirk_ivch_dvob },
    316 
    317     /* Motion Computing M1200 reported on irc */
    318     { PCI_CHIP_I830_M, 0x14c0, 0x0012, quirk_ivch_dvob },
    319 
    320     /* Samsung Q35 has no TV output */
    321     { PCI_CHIP_I945_GM, 0x144d, 0xc504, quirk_ignore_tv },
    322     /* Samsung Q45 has no TV output */
    323     { PCI_CHIP_I965_GM, 0x144d, 0xc510, quirk_ignore_tv },
    324 
    325     /* HP Compaq nx6110 has no TV output */
    326     { PCI_CHIP_I915_GM, 0x103c, 0x099c, quirk_ignore_tv },
    327     /* HP Compaq nx6310 has no TV output */
    328     { PCI_CHIP_I945_GM, 0x103c, 0x30aa, quirk_ignore_tv },
    329     /* HP Compaq 6730s has no TV output */
    330     { PCI_CHIP_GM45_GM, 0x103c, 0x30e8, quirk_ignore_tv },
    331     /* HP Compaq 2730p needs pipe A force quirk (LP: #291555) */
    332     { PCI_CHIP_GM45_GM, 0x103c, 0x30eb, quirk_pipea_force },
    333     /* HP Mini needs pipe A force quirk (LP: #322104) */
    334     { PCI_CHIP_I945_GME,0x103c, 0x361a, quirk_pipea_force },
    335     /* HP Mini 5101 needs pipe A force quirk */
    336     { PCI_CHIP_I945_GME,0x103c, 0x3632, quirk_pipea_force },
    337 
    338     /* Thinkpad R31 needs pipe A force quirk */
    339     { PCI_CHIP_I830_M, 0x1014, 0x0505, quirk_pipea_force },
    340     /* Dell Latitude D400 needs pipe A force quirk (LP: #228519) */
    341     { PCI_CHIP_I855_GM, 0x1028, 0x0139, quirk_pipea_force },
    342     /* Dell Latitude D500 needs pipe A force quirk */
    343     { PCI_CHIP_I855_GM, 0x1028, 0x0152, quirk_pipea_force },
    344     /* Dell Latitude D505 needs pipe A force quirk (LP: #235643) */
    345     { PCI_CHIP_I855_GM, 0x1028, 0x0163, quirk_pipea_force },
    346     /* Dell Latitude X300 needs pipe A force quirk */
    347     { PCI_CHIP_I855_GM, 0x1028, 0x014f, quirk_pipea_force },
    348     /* Dell Inspiron 510m needs pipe A force quirk */
    349     { PCI_CHIP_I855_GM, 0x1028, 0x0164, quirk_pipea_force },
    350     /* Toshiba Satellite A30 needs pipe A force quirk */
    351     { PCI_CHIP_I855_GM, 0x1179, 0xff00 , quirk_pipea_force },
    352     /* Toshiba Protege R-205, S-209 needs pipe A force quirk */
    353     { PCI_CHIP_I915_GM, 0x1179, 0x0001, quirk_pipea_force },
    354     /* Intel 855GM hardware (See LP: #216490) */
    355     { PCI_CHIP_I855_GM, 0x1028, 0x00c8, quirk_pipea_force },
    356     /* Intel 855GM hardware (See Novell Bugzilla #406123) */
    357     { PCI_CHIP_I855_GM, 0x10cf, 0x1215, quirk_pipea_force },
    358     /* HP Pavilion ze4944ea needs pipe A force quirk (See LP: #242389) */
    359     { PCI_CHIP_I855_GM, 0x103c, 0x3084, quirk_pipea_force },
    360 
    361     { PCI_CHIP_I855_GM, 0x161f, 0x2030, quirk_pfit_safe },
    362 
    363     /* ThinkPad X30 needs pipe A force quirk (LP: #304614) */
    364     { PCI_CHIP_I830_M,  0x1014, 0x0513, quirk_pipea_force },
    365     /* ThinkPad X40 needs pipe A force quirk */
    366     { PCI_CHIP_I855_GM, 0x1014, 0x0557, quirk_pipea_force },
    367 
    368     /* ThinkPad T60 needs pipe A force quirk (bug #16494) */
    369     { PCI_CHIP_I945_GM, 0x17aa, 0x201a, quirk_pipea_force },
    370 
    371     /* Sony vaio PCG-r600HFP (fix bug 13722) */
    372     { PCI_CHIP_I830_M, 0x104d, 0x8100, quirk_ivch_dvob },
    373     /* Sony vaio VGN-SZ4MN (See LP: #212163) */
    374     { PCI_CHIP_I830_M, 0x104d, 0x81e6, quirk_pipea_force },
    375     /* Sony VGC-LT71DB has no VGA output (bug #17395) */
    376     { PCI_CHIP_I965_GM, 0x104d, 0x9018, quirk_ignore_crt },
    377 
    378     /* Quanta Gigabyte W251U (See LP: #244242) */
    379     { PCI_CHIP_I945_GM, 0x152d, 0x0755, quirk_pipea_force },
    380 
    381     /* Ordi Enduro UW31 (See LP: #152416) */
    382     { PCI_CHIP_I945_GM, 0x1584, 0x9900, quirk_ignore_tv },
    383 
    384     /* Dell Latitude D500 needs reset modes quirk */
    385     { PCI_CHIP_I855_GM, 0x1028, 0x0152, quirk_reset_modes },
    386 
    387     /* Littlebit Sepia X35 (rebranded Asus Z37E) (See LP: #201257) */
    388     { PCI_CHIP_I965_GM, 0x1043, 0x8265, quirk_ignore_tv },
    389 
    390     /* 855 & before need to leave pipe A & dpll A up */
    391     { PCI_CHIP_I855_GM, SUBSYS_ANY, SUBSYS_ANY, quirk_pipea_force },
    392     { PCI_CHIP_845_G, SUBSYS_ANY, SUBSYS_ANY, quirk_pipea_force },
    393 
    394     /* Asus Eee Box has no LVDS */
    395     { PCI_CHIP_I945_GME, 0x1043, 0x1252, quirk_ignore_lvds },
    396 
    397     /* #19239: Mirrus Centrino laptop */
    398     { PCI_CHIP_I915_GM, 0x1584, 0x9800, quirk_broken_acpi_lid },
    399 
    400     /* #19529: iBase MB890 board */
    401     { PCI_CHIP_I855_GM, 0x8086, 0x3582, quirk_ibase_lvds },
    402 
    403     { 0, 0, 0, NULL },
    404 };
    405 
    406 void i830_fixup_devices(ScrnInfoPtr scrn)
    407 {
    408     I830Ptr pI830 = I830PTR(scrn);
    409     i830_quirk_ptr p = i830_quirk_list;
    410     int i;
    411 
    412     i830_dmi_scan();
    413 
    414     if (0)
    415 	i830_dmi_dump();
    416 
    417     while (p && p->chipType != 0) {
    418 	if (DEVICE_ID(pI830->PciInfo) == p->chipType &&
    419 	    (SUBVENDOR_ID(pI830->PciInfo) == p->subsysVendor ||
    420 	     p->subsysVendor == SUBSYS_ANY) &&
    421 	    (SUBSYS_ID(pI830->PciInfo) == p->subsysCard ||
    422 	     p->subsysCard == SUBSYS_ANY))
    423 	    p->hook(pI830);
    424 	++p;
    425     }
    426 
    427     for (i = 0; i < dmi_data_max; i++)
    428 	if (i830_dmi_data[i])
    429 	    xfree(i830_dmi_data[i]);
    430 }
    431