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