acpi: video: enhance the quirk detect logic of _BQC
[deliverable/linux.git] / drivers / acpi / video.c
CommitLineData
1da177e4
LT
1/*
2 * video.c - ACPI Video Driver ($Revision:$)
3 *
4 * Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
5 * Copyright (C) 2004 Bruno Ducrot <ducrot@poupinou.org>
f4715189 6 * Copyright (C) 2006 Thomas Tuttle <linux-kernel@ttuttle.net>
1da177e4
LT
7 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 */
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/init.h>
30#include <linux/types.h>
31#include <linux/list.h>
bbac81f5 32#include <linux/mutex.h>
e9dab196 33#include <linux/input.h>
2f3d000a 34#include <linux/backlight.h>
702ed512 35#include <linux/thermal.h>
935e5f29 36#include <linux/sort.h>
74a365b3
MG
37#include <linux/pci.h>
38#include <linux/pci_ids.h>
5a0e3ad6 39#include <linux/slab.h>
1da177e4 40#include <asm/uaccess.h>
eb27cae8 41#include <linux/dmi.h>
1da177e4
LT
42#include <acpi/acpi_bus.h>
43#include <acpi/acpi_drivers.h>
ac7729da 44#include <linux/suspend.h>
e92a7162 45#include <acpi/video.h>
1da177e4 46
a192a958
LB
47#define PREFIX "ACPI: "
48
1da177e4
LT
49#define ACPI_VIDEO_BUS_NAME "Video Bus"
50#define ACPI_VIDEO_DEVICE_NAME "Video Device"
51#define ACPI_VIDEO_NOTIFY_SWITCH 0x80
52#define ACPI_VIDEO_NOTIFY_PROBE 0x81
53#define ACPI_VIDEO_NOTIFY_CYCLE 0x82
54#define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83
55#define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84
56
f4715189
TT
57#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x85
58#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86
59#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87
60#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88
61#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89
1da177e4 62
2f3d000a 63#define MAX_NAME_LEN 20
1da177e4 64
1da177e4 65#define _COMPONENT ACPI_VIDEO_COMPONENT
f52fd66d 66ACPI_MODULE_NAME("video");
1da177e4 67
f52fd66d 68MODULE_AUTHOR("Bruno Ducrot");
7cda93e0 69MODULE_DESCRIPTION("ACPI Video Driver");
1da177e4
LT
70MODULE_LICENSE("GPL");
71
90ab5ee9 72static bool brightness_switch_enabled = 1;
8a681a4d
ZR
73module_param(brightness_switch_enabled, bool, 0644);
74
c504f8cb
ZR
75/*
76 * By default, we don't allow duplicate ACPI video bus devices
77 * under the same VGA controller
78 */
90ab5ee9 79static bool allow_duplicates;
c504f8cb
ZR
80module_param(allow_duplicates, bool, 0644);
81
99fd1895
ZR
82/*
83 * Some BIOSes claim they use minimum backlight at boot,
84 * and this may bring dimming screen after boot
85 */
90ab5ee9 86static bool use_bios_initial_backlight = 1;
99fd1895
ZR
87module_param(use_bios_initial_backlight, bool, 0644);
88
86e437f0 89static int register_count = 0;
4be44fcd 90static int acpi_video_bus_add(struct acpi_device *device);
51fac838 91static int acpi_video_bus_remove(struct acpi_device *device);
7015558f 92static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
1da177e4 93
1ba90e3a
TR
94static const struct acpi_device_id video_device_ids[] = {
95 {ACPI_VIDEO_HID, 0},
96 {"", 0},
97};
98MODULE_DEVICE_TABLE(acpi, video_device_ids);
99
1da177e4 100static struct acpi_driver acpi_video_bus = {
c2b6705b 101 .name = "video",
1da177e4 102 .class = ACPI_VIDEO_CLASS,
1ba90e3a 103 .ids = video_device_ids,
1da177e4
LT
104 .ops = {
105 .add = acpi_video_bus_add,
106 .remove = acpi_video_bus_remove,
7015558f 107 .notify = acpi_video_bus_notify,
4be44fcd 108 },
1da177e4
LT
109};
110
111struct acpi_video_bus_flags {
4be44fcd
LB
112 u8 multihead:1; /* can switch video heads */
113 u8 rom:1; /* can retrieve a video rom */
114 u8 post:1; /* can configure the head to */
115 u8 reserved:5;
1da177e4
LT
116};
117
118struct acpi_video_bus_cap {
4be44fcd
LB
119 u8 _DOS:1; /*Enable/Disable output switching */
120 u8 _DOD:1; /*Enumerate all devices attached to display adapter */
121 u8 _ROM:1; /*Get ROM Data */
122 u8 _GPD:1; /*Get POST Device */
123 u8 _SPD:1; /*Set POST Device */
124 u8 _VPO:1; /*Video POST Options */
125 u8 reserved:2;
1da177e4
LT
126};
127
4be44fcd
LB
128struct acpi_video_device_attrib {
129 u32 display_index:4; /* A zero-based instance of the Display */
98fb8fe1 130 u32 display_port_attachment:4; /*This field differentiates the display type */
4be44fcd 131 u32 display_type:4; /*Describe the specific type in use */
98fb8fe1 132 u32 vendor_specific:4; /*Chipset Vendor Specific */
4be44fcd
LB
133 u32 bios_can_detect:1; /*BIOS can detect the device */
134 u32 depend_on_vga:1; /*Non-VGA output device whose power is related to
135 the VGA device. */
136 u32 pipe_id:3; /*For VGA multiple-head devices. */
137 u32 reserved:10; /*Must be 0 */
138 u32 device_id_scheme:1; /*Device ID Scheme */
1da177e4
LT
139};
140
141struct acpi_video_enumerated_device {
142 union {
143 u32 int_val;
4be44fcd 144 struct acpi_video_device_attrib attrib;
1da177e4
LT
145 } value;
146 struct acpi_video_device *bind_info;
147};
148
149struct acpi_video_bus {
e6afa0de 150 struct acpi_device *device;
4be44fcd 151 u8 dos_setting;
1da177e4 152 struct acpi_video_enumerated_device *attached_array;
4be44fcd
LB
153 u8 attached_count;
154 struct acpi_video_bus_cap cap;
1da177e4 155 struct acpi_video_bus_flags flags;
4be44fcd 156 struct list_head video_device_list;
bbac81f5 157 struct mutex device_list_lock; /* protects video_device_list */
e9dab196
LY
158 struct input_dev *input;
159 char phys[32]; /* for input device */
ac7729da 160 struct notifier_block pm_nb;
1da177e4
LT
161};
162
163struct acpi_video_device_flags {
4be44fcd
LB
164 u8 crt:1;
165 u8 lcd:1;
166 u8 tvout:1;
82cae999 167 u8 dvi:1;
4be44fcd
LB
168 u8 bios:1;
169 u8 unknown:1;
82cae999 170 u8 reserved:2;
1da177e4
LT
171};
172
173struct acpi_video_device_cap {
4be44fcd
LB
174 u8 _ADR:1; /*Return the unique ID */
175 u8 _BCL:1; /*Query list of brightness control levels supported */
176 u8 _BCM:1; /*Set the brightness level */
2f3d000a 177 u8 _BQC:1; /* Get current brightness level */
c60d638e 178 u8 _BCQ:1; /* Some buggy BIOS uses _BCQ instead of _BQC */
4be44fcd 179 u8 _DDC:1; /*Return the EDID for this device */
1da177e4
LT
180};
181
d32f6947
ZR
182struct acpi_video_brightness_flags {
183 u8 _BCL_no_ac_battery_levels:1; /* no AC/Battery levels in _BCL */
d80fb99f 184 u8 _BCL_reversed:1; /* _BCL package is in a reversed order*/
1a7c618a
ZR
185 u8 _BCL_use_index:1; /* levels in _BCL are index values */
186 u8 _BCM_use_index:1; /* input of _BCM is an index value */
187 u8 _BQC_use_index:1; /* _BQC returns an index value */
d32f6947
ZR
188};
189
1da177e4 190struct acpi_video_device_brightness {
4be44fcd
LB
191 int curr;
192 int count;
193 int *levels;
d32f6947 194 struct acpi_video_brightness_flags flags;
1da177e4
LT
195};
196
197struct acpi_video_device {
4be44fcd
LB
198 unsigned long device_id;
199 struct acpi_video_device_flags flags;
200 struct acpi_video_device_cap cap;
201 struct list_head entry;
202 struct acpi_video_bus *video;
203 struct acpi_device *dev;
1da177e4 204 struct acpi_video_device_brightness *brightness;
2f3d000a 205 struct backlight_device *backlight;
4a703a8f 206 struct thermal_cooling_device *cooling_dev;
1da177e4
LT
207};
208
b7171ae7 209static const char device_decode[][30] = {
1da177e4
LT
210 "motherboard VGA device",
211 "PCI VGA device",
212 "AGP VGA device",
213 "UNKNOWN",
214};
215
4be44fcd
LB
216static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data);
217static void acpi_video_device_rebind(struct acpi_video_bus *video);
218static void acpi_video_device_bind(struct acpi_video_bus *video,
219 struct acpi_video_device *device);
1da177e4 220static int acpi_video_device_enumerate(struct acpi_video_bus *video);
2f3d000a
YL
221static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
222 int level);
223static int acpi_video_device_lcd_get_level_current(
224 struct acpi_video_device *device,
a89803df 225 unsigned long long *level, bool raw);
4be44fcd
LB
226static int acpi_video_get_next_level(struct acpi_video_device *device,
227 u32 level_current, u32 event);
c8890f90 228static int acpi_video_switch_brightness(struct acpi_video_device *device,
4be44fcd 229 int event);
1da177e4 230
2f3d000a
YL
231/*backlight device sysfs support*/
232static int acpi_video_get_brightness(struct backlight_device *bd)
233{
27663c58 234 unsigned long long cur_level;
38531e6f 235 int i;
2f3d000a 236 struct acpi_video_device *vd =
655bfd7a 237 (struct acpi_video_device *)bl_get_data(bd);
c8890f90 238
a89803df 239 if (acpi_video_device_lcd_get_level_current(vd, &cur_level, false))
c8890f90 240 return -EINVAL;
38531e6f
MG
241 for (i = 2; i < vd->brightness->count; i++) {
242 if (vd->brightness->levels[i] == cur_level)
243 /* The first two entries are special - see page 575
244 of the ACPI spec 3.0 */
245 return i-2;
246 }
247 return 0;
2f3d000a
YL
248}
249
250static int acpi_video_set_brightness(struct backlight_device *bd)
251{
24450c7a 252 int request_level = bd->props.brightness + 2;
2f3d000a 253 struct acpi_video_device *vd =
655bfd7a 254 (struct acpi_video_device *)bl_get_data(bd);
24450c7a
ZR
255
256 return acpi_video_device_lcd_set_level(vd,
257 vd->brightness->levels[request_level]);
2f3d000a
YL
258}
259
acc2472e 260static const struct backlight_ops acpi_backlight_ops = {
599a52d1
RP
261 .get_brightness = acpi_video_get_brightness,
262 .update_status = acpi_video_set_brightness,
263};
264
702ed512 265/* thermal cooling device callbacks */
4a703a8f 266static int video_get_max_state(struct thermal_cooling_device *cooling_dev, unsigned
6503e5df 267 long *state)
702ed512 268{
4a703a8f 269 struct acpi_device *device = cooling_dev->devdata;
702ed512
ZR
270 struct acpi_video_device *video = acpi_driver_data(device);
271
6503e5df
MG
272 *state = video->brightness->count - 3;
273 return 0;
702ed512
ZR
274}
275
4a703a8f 276static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsigned
6503e5df 277 long *state)
702ed512 278{
4a703a8f 279 struct acpi_device *device = cooling_dev->devdata;
702ed512 280 struct acpi_video_device *video = acpi_driver_data(device);
27663c58 281 unsigned long long level;
6503e5df 282 int offset;
702ed512 283
a89803df 284 if (acpi_video_device_lcd_get_level_current(video, &level, false))
c8890f90 285 return -EINVAL;
6503e5df
MG
286 for (offset = 2; offset < video->brightness->count; offset++)
287 if (level == video->brightness->levels[offset]) {
288 *state = video->brightness->count - offset - 1;
289 return 0;
290 }
702ed512
ZR
291
292 return -EINVAL;
293}
294
295static int
4a703a8f 296video_set_cur_state(struct thermal_cooling_device *cooling_dev, unsigned long state)
702ed512 297{
4a703a8f 298 struct acpi_device *device = cooling_dev->devdata;
702ed512
ZR
299 struct acpi_video_device *video = acpi_driver_data(device);
300 int level;
301
302 if ( state >= video->brightness->count - 2)
303 return -EINVAL;
304
305 state = video->brightness->count - state;
306 level = video->brightness->levels[state -1];
307 return acpi_video_device_lcd_set_level(video, level);
308}
309
9c8b04be 310static const struct thermal_cooling_device_ops video_cooling_ops = {
702ed512
ZR
311 .get_max_state = video_get_max_state,
312 .get_cur_state = video_get_cur_state,
313 .set_cur_state = video_set_cur_state,
314};
315
1da177e4
LT
316/* --------------------------------------------------------------------------
317 Video Management
318 -------------------------------------------------------------------------- */
319
1da177e4 320static int
4be44fcd
LB
321acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
322 union acpi_object **levels)
1da177e4 323{
4be44fcd
LB
324 int status;
325 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
326 union acpi_object *obj;
1da177e4 327
1da177e4
LT
328
329 *levels = NULL;
330
90130268 331 status = acpi_evaluate_object(device->dev->handle, "_BCL", NULL, &buffer);
1da177e4 332 if (!ACPI_SUCCESS(status))
d550d98d 333 return status;
4be44fcd 334 obj = (union acpi_object *)buffer.pointer;
6665bda7 335 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
6468463a 336 printk(KERN_ERR PREFIX "Invalid _BCL data\n");
1da177e4
LT
337 status = -EFAULT;
338 goto err;
339 }
340
341 *levels = obj;
342
d550d98d 343 return 0;
1da177e4 344
4be44fcd 345 err:
6044ec88 346 kfree(buffer.pointer);
1da177e4 347
d550d98d 348 return status;
1da177e4
LT
349}
350
351static int
4be44fcd 352acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
1da177e4 353{
24450c7a 354 int status;
4be44fcd
LB
355 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
356 struct acpi_object_list args = { 1, &arg0 };
9e6dada9 357 int state;
1da177e4 358
1da177e4 359 arg0.integer.value = level;
1da177e4 360
24450c7a
ZR
361 status = acpi_evaluate_object(device->dev->handle, "_BCM",
362 &args, NULL);
363 if (ACPI_FAILURE(status)) {
364 ACPI_ERROR((AE_INFO, "Evaluating _BCM failed"));
365 return -EIO;
366 }
367
4500ca8e 368 device->brightness->curr = level;
9e6dada9 369 for (state = 2; state < device->brightness->count; state++)
24450c7a 370 if (level == device->brightness->levels[state]) {
1a7c618a
ZR
371 if (device->backlight)
372 device->backlight->props.brightness = state - 2;
24450c7a
ZR
373 return 0;
374 }
9e6dada9 375
24450c7a
ZR
376 ACPI_ERROR((AE_INFO, "Current brightness invalid"));
377 return -EINVAL;
1da177e4
LT
378}
379
45cb50e6
ZR
380/*
381 * For some buggy _BQC methods, we need to add a constant value to
382 * the _BQC return value to get the actual current brightness level
383 */
384
385static int bqc_offset_aml_bug_workaround;
386static int __init video_set_bqc_offset(const struct dmi_system_id *d)
387{
388 bqc_offset_aml_bug_workaround = 9;
389 return 0;
390}
391
129ff8f8
ZR
392static int video_ignore_initial_backlight(const struct dmi_system_id *d)
393{
394 use_bios_initial_backlight = 0;
395 return 0;
396}
397
45cb50e6
ZR
398static struct dmi_system_id video_dmi_table[] __initdata = {
399 /*
400 * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121
401 */
402 {
403 .callback = video_set_bqc_offset,
404 .ident = "Acer Aspire 5720",
405 .matches = {
406 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
407 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"),
408 },
409 },
5afc4abe
LB
410 {
411 .callback = video_set_bqc_offset,
412 .ident = "Acer Aspire 5710Z",
413 .matches = {
414 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
415 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5710Z"),
416 },
417 },
34ac272b
ZR
418 {
419 .callback = video_set_bqc_offset,
420 .ident = "eMachines E510",
421 .matches = {
422 DMI_MATCH(DMI_BOARD_VENDOR, "EMACHINES"),
423 DMI_MATCH(DMI_PRODUCT_NAME, "eMachines E510"),
424 },
425 },
93bcece2
ZR
426 {
427 .callback = video_set_bqc_offset,
428 .ident = "Acer Aspire 5315",
429 .matches = {
430 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
431 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"),
432 },
433 },
152a4e63
ZR
434 {
435 .callback = video_set_bqc_offset,
436 .ident = "Acer Aspire 7720",
437 .matches = {
438 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
439 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"),
440 },
441 },
129ff8f8
ZR
442 {
443 .callback = video_ignore_initial_backlight,
444 .ident = "HP Folio 13-2000",
445 .matches = {
446 DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
447 DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"),
448 },
449 },
771d09b3
GMDV
450 {
451 .callback = video_ignore_initial_backlight,
452 .ident = "HP Pavilion dm4",
453 .matches = {
454 DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
455 DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dm4 Notebook PC"),
456 },
457 },
45cb50e6
ZR
458 {}
459};
460
994fa63c
DB
461static unsigned long long
462acpi_video_bqc_value_to_level(struct acpi_video_device *device,
463 unsigned long long bqc_value)
464{
465 unsigned long long level;
466
467 if (device->brightness->flags._BQC_use_index) {
468 /*
469 * _BQC returns an index that doesn't account for
470 * the first 2 items with special meaning, so we need
471 * to compensate for that by offsetting ourselves
472 */
473 if (device->brightness->flags._BCL_reversed)
474 bqc_value = device->brightness->count - 3 - bqc_value;
475
476 level = device->brightness->levels[bqc_value + 2];
477 } else {
478 level = bqc_value;
479 }
480
481 level += bqc_offset_aml_bug_workaround;
482
483 return level;
484}
485
1da177e4 486static int
4be44fcd 487acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
a89803df 488 unsigned long long *level, bool raw)
1da177e4 489{
c8890f90 490 acpi_status status = AE_OK;
4e231fa4 491 int i;
c8890f90 492
c60d638e
ZR
493 if (device->cap._BQC || device->cap._BCQ) {
494 char *buf = device->cap._BQC ? "_BQC" : "_BCQ";
495
496 status = acpi_evaluate_integer(device->dev->handle, buf,
c8890f90
ZR
497 NULL, level);
498 if (ACPI_SUCCESS(status)) {
a89803df
DB
499 if (raw) {
500 /*
501 * Caller has indicated he wants the raw
502 * value returned by _BQC, so don't furtherly
503 * mess with the value.
504 */
505 return 0;
506 }
507
994fa63c 508 *level = acpi_video_bqc_value_to_level(device, *level);
1a7c618a 509
4e231fa4
VS
510 for (i = 2; i < device->brightness->count; i++)
511 if (device->brightness->levels[i] == *level) {
512 device->brightness->curr = *level;
513 return 0;
514 }
a89803df
DB
515 /*
516 * BQC returned an invalid level.
517 * Stop using it.
518 */
519 ACPI_WARNING((AE_INFO,
520 "%s returned an invalid level",
521 buf));
522 device->cap._BQC = device->cap._BCQ = 0;
c8890f90
ZR
523 } else {
524 /* Fixme:
525 * should we return an error or ignore this failure?
526 * dev->brightness->curr is a cached value which stores
527 * the correct current backlight level in most cases.
528 * ACPI video backlight still works w/ buggy _BQC.
529 * http://bugzilla.kernel.org/show_bug.cgi?id=12233
530 */
c60d638e
ZR
531 ACPI_WARNING((AE_INFO, "Evaluating %s failed", buf));
532 device->cap._BQC = device->cap._BCQ = 0;
c8890f90
ZR
533 }
534 }
535
4500ca8e 536 *level = device->brightness->curr;
c8890f90 537 return 0;
1da177e4
LT
538}
539
540static int
4be44fcd
LB
541acpi_video_device_EDID(struct acpi_video_device *device,
542 union acpi_object **edid, ssize_t length)
1da177e4 543{
4be44fcd
LB
544 int status;
545 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
546 union acpi_object *obj;
547 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
548 struct acpi_object_list args = { 1, &arg0 };
1da177e4 549
1da177e4
LT
550
551 *edid = NULL;
552
553 if (!device)
d550d98d 554 return -ENODEV;
1da177e4
LT
555 if (length == 128)
556 arg0.integer.value = 1;
557 else if (length == 256)
558 arg0.integer.value = 2;
559 else
d550d98d 560 return -EINVAL;
1da177e4 561
90130268 562 status = acpi_evaluate_object(device->dev->handle, "_DDC", &args, &buffer);
1da177e4 563 if (ACPI_FAILURE(status))
d550d98d 564 return -ENODEV;
1da177e4 565
50dd0969 566 obj = buffer.pointer;
1da177e4
LT
567
568 if (obj && obj->type == ACPI_TYPE_BUFFER)
569 *edid = obj;
570 else {
6468463a 571 printk(KERN_ERR PREFIX "Invalid _DDC data\n");
1da177e4
LT
572 status = -EFAULT;
573 kfree(obj);
574 }
575
d550d98d 576 return status;
1da177e4
LT
577}
578
1da177e4
LT
579/* bus */
580
1da177e4
LT
581/*
582 * Arg:
583 * video : video bus device pointer
584 * bios_flag :
585 * 0. The system BIOS should NOT automatically switch(toggle)
586 * the active display output.
587 * 1. The system BIOS should automatically switch (toggle) the
98fb8fe1 588 * active display output. No switch event.
1da177e4
LT
589 * 2. The _DGS value should be locked.
590 * 3. The system BIOS should not automatically switch (toggle) the
591 * active display output, but instead generate the display switch
592 * event notify code.
593 * lcd_flag :
594 * 0. The system BIOS should automatically control the brightness level
98fb8fe1 595 * of the LCD when the power changes from AC to DC
1da177e4 596 * 1. The system BIOS should NOT automatically control the brightness
98fb8fe1 597 * level of the LCD when the power changes from AC to DC.
1da177e4 598 * Return Value:
ea9f8856 599 * -EINVAL wrong arg.
1da177e4
LT
600 */
601
602static int
4be44fcd 603acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
1da177e4 604{
ea9f8856 605 acpi_status status;
4be44fcd
LB
606 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
607 struct acpi_object_list args = { 1, &arg0 };
1da177e4 608
b0373843
ZR
609 if (!video->cap._DOS)
610 return 0;
1da177e4 611
ea9f8856
IM
612 if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1)
613 return -EINVAL;
1da177e4
LT
614 arg0.integer.value = (lcd_flag << 2) | bios_flag;
615 video->dos_setting = arg0.integer.value;
ea9f8856
IM
616 status = acpi_evaluate_object(video->device->handle, "_DOS",
617 &args, NULL);
618 if (ACPI_FAILURE(status))
619 return -EIO;
1da177e4 620
ea9f8856 621 return 0;
1da177e4
LT
622}
623
935e5f29
ZR
624/*
625 * Simple comparison function used to sort backlight levels.
626 */
627
628static int
629acpi_video_cmp_level(const void *a, const void *b)
630{
631 return *(int *)a - *(int *)b;
632}
633
a50188da
AL
634/*
635 * Decides if _BQC/_BCQ for this system is usable
636 *
637 * We do this by changing the level first and then read out the current
638 * brightness level, if the value does not match, find out if it is using
639 * index. If not, clear the _BQC/_BCQ capability.
640 */
641static int acpi_video_bqc_quirk(struct acpi_video_device *device,
642 int max_level, int current_level)
643{
644 struct acpi_video_device_brightness *br = device->brightness;
645 int result;
646 unsigned long long level;
647 int test_level;
648
649 /* don't mess with existing known broken systems */
650 if (bqc_offset_aml_bug_workaround)
651 return 0;
652
653 /*
654 * Some systems always report current brightness level as maximum
655 * through _BQC, we need to test another value for them.
656 */
657 test_level = current_level == max_level ? br->levels[2] : max_level;
658
659 result = acpi_video_device_lcd_set_level(device, test_level);
660 if (result)
661 return result;
662
663 result = acpi_video_device_lcd_get_level_current(device, &level, true);
664 if (result)
665 return result;
666
667 if (level != test_level) {
668 /* buggy _BQC found, need to find out if it uses index */
669 if (level < br->count) {
670 if (br->flags._BCL_reversed)
671 level = br->count - 3 - level;
672 if (br->levels[level + 2] == test_level)
673 br->flags._BQC_use_index = 1;
674 }
675
676 if (!br->flags._BQC_use_index)
677 device->cap._BQC = device->cap._BCQ = 0;
678 }
679
680 return 0;
681}
682
683
1da177e4
LT
684/*
685 * Arg:
686 * device : video output device (LCD, CRT, ..)
687 *
688 * Return Value:
469778c1
JJ
689 * Maximum brightness level
690 *
691 * Allocate and initialize device->brightness.
692 */
693
694static int
695acpi_video_init_brightness(struct acpi_video_device *device)
696{
697 union acpi_object *obj = NULL;
d32f6947 698 int i, max_level = 0, count = 0, level_ac_battery = 0;
1a7c618a 699 unsigned long long level, level_old;
469778c1
JJ
700 union acpi_object *o;
701 struct acpi_video_device_brightness *br = NULL;
1a7c618a 702 int result = -EINVAL;
469778c1
JJ
703
704 if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
705 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available "
706 "LCD brightness level\n"));
707 goto out;
708 }
709
710 if (obj->package.count < 2)
711 goto out;
712
713 br = kzalloc(sizeof(*br), GFP_KERNEL);
714 if (!br) {
715 printk(KERN_ERR "can't allocate memory\n");
1a7c618a 716 result = -ENOMEM;
469778c1
JJ
717 goto out;
718 }
719
d32f6947 720 br->levels = kmalloc((obj->package.count + 2) * sizeof *(br->levels),
469778c1 721 GFP_KERNEL);
1a7c618a
ZR
722 if (!br->levels) {
723 result = -ENOMEM;
469778c1 724 goto out_free;
1a7c618a 725 }
469778c1
JJ
726
727 for (i = 0; i < obj->package.count; i++) {
728 o = (union acpi_object *)&obj->package.elements[i];
729 if (o->type != ACPI_TYPE_INTEGER) {
730 printk(KERN_ERR PREFIX "Invalid data\n");
731 continue;
732 }
733 br->levels[count] = (u32) o->integer.value;
734
735 if (br->levels[count] > max_level)
736 max_level = br->levels[count];
737 count++;
738 }
739
d32f6947
ZR
740 /*
741 * some buggy BIOS don't export the levels
742 * when machine is on AC/Battery in _BCL package.
743 * In this case, the first two elements in _BCL packages
744 * are also supported brightness levels that OS should take care of.
745 */
90af2cf6
ZR
746 for (i = 2; i < count; i++) {
747 if (br->levels[i] == br->levels[0])
d32f6947 748 level_ac_battery++;
90af2cf6
ZR
749 if (br->levels[i] == br->levels[1])
750 level_ac_battery++;
751 }
d32f6947
ZR
752
753 if (level_ac_battery < 2) {
754 level_ac_battery = 2 - level_ac_battery;
755 br->flags._BCL_no_ac_battery_levels = 1;
756 for (i = (count - 1 + level_ac_battery); i >= 2; i--)
757 br->levels[i] = br->levels[i - level_ac_battery];
758 count += level_ac_battery;
759 } else if (level_ac_battery > 2)
bf6787eb 760 ACPI_ERROR((AE_INFO, "Too many duplicates in _BCL package"));
d32f6947 761
d80fb99f
ZR
762 /* Check if the _BCL package is in a reversed order */
763 if (max_level == br->levels[2]) {
764 br->flags._BCL_reversed = 1;
765 sort(&br->levels[2], count - 2, sizeof(br->levels[2]),
766 acpi_video_cmp_level, NULL);
767 } else if (max_level != br->levels[count - 1])
768 ACPI_ERROR((AE_INFO,
bf6787eb 769 "Found unordered _BCL package"));
469778c1
JJ
770
771 br->count = count;
772 device->brightness = br;
1a7c618a
ZR
773
774 /* Check the input/output of _BQC/_BCL/_BCM */
775 if ((max_level < 100) && (max_level <= (count - 2)))
776 br->flags._BCL_use_index = 1;
777
778 /*
779 * _BCM is always consistent with _BCL,
780 * at least for all the laptops we have ever seen.
781 */
782 br->flags._BCM_use_index = br->flags._BCL_use_index;
783
784 /* _BQC uses INDEX while _BCL uses VALUE in some laptops */
90c53ca4 785 br->curr = level = max_level;
e047cca6
ZR
786
787 if (!device->cap._BQC)
788 goto set_level;
789
a89803df
DB
790 result = acpi_video_device_lcd_get_level_current(device,
791 &level_old, true);
1a7c618a
ZR
792 if (result)
793 goto out_free_levels;
794
a50188da 795 result = acpi_video_bqc_quirk(device, max_level, level_old);
1a7c618a
ZR
796 if (result)
797 goto out_free_levels;
a50188da
AL
798 /*
799 * cap._BQC may get cleared due to _BQC is found to be broken
800 * in acpi_video_bqc_quirk, so check again here.
801 */
802 if (!device->cap._BQC)
803 goto set_level;
e047cca6 804
994fa63c
DB
805 if (use_bios_initial_backlight) {
806 level = acpi_video_bqc_value_to_level(device, level_old);
90c53ca4 807 /*
994fa63c
DB
808 * On some buggy laptops, _BQC returns an uninitialized
809 * value when invoked for the first time, i.e.
810 * level_old is invalid (no matter whether it's a level
811 * or an index). Set the backlight to max_level in this case.
90c53ca4 812 */
994fa63c
DB
813 for (i = 2; i < br->count; i++)
814 if (level_old == br->levels[i])
815 break;
816 if (i == br->count)
817 level = max_level;
90c53ca4 818 }
e047cca6 819
e047cca6 820set_level:
90c53ca4 821 result = acpi_video_device_lcd_set_level(device, level);
e047cca6
ZR
822 if (result)
823 goto out_free_levels;
1a7c618a 824
d32f6947
ZR
825 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
826 "found %d brightness levels\n", count - 2));
469778c1 827 kfree(obj);
1a7c618a 828 return result;
469778c1
JJ
829
830out_free_levels:
831 kfree(br->levels);
832out_free:
833 kfree(br);
834out:
835 device->brightness = NULL;
836 kfree(obj);
1a7c618a 837 return result;
469778c1
JJ
838}
839
840/*
841 * Arg:
842 * device : video output device (LCD, CRT, ..)
843 *
844 * Return Value:
1da177e4
LT
845 * None
846 *
98fb8fe1 847 * Find out all required AML methods defined under the output
1da177e4
LT
848 * device.
849 */
850
4be44fcd 851static void acpi_video_device_find_cap(struct acpi_video_device *device)
1da177e4 852{
1da177e4 853 acpi_handle h_dummy1;
1da177e4 854
90130268 855 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) {
1da177e4
LT
856 device->cap._ADR = 1;
857 }
90130268 858 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCL", &h_dummy1))) {
4be44fcd 859 device->cap._BCL = 1;
1da177e4 860 }
90130268 861 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) {
4be44fcd 862 device->cap._BCM = 1;
1da177e4 863 }
2f3d000a
YL
864 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1)))
865 device->cap._BQC = 1;
c60d638e
ZR
866 else if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCQ",
867 &h_dummy1))) {
868 printk(KERN_WARNING FW_BUG "_BCQ is used instead of _BQC\n");
869 device->cap._BCQ = 1;
870 }
871
90130268 872 if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) {
4be44fcd 873 device->cap._DDC = 1;
1da177e4 874 }
1da177e4 875
1a7c618a 876 if (acpi_video_backlight_support()) {
a19a6ee6 877 struct backlight_properties props;
9661e92c
MG
878 struct pci_dev *pdev;
879 acpi_handle acpi_parent;
880 struct device *parent = NULL;
702ed512 881 int result;
2f3d000a
YL
882 static int count = 0;
883 char *name;
1a7c618a
ZR
884
885 result = acpi_video_init_brightness(device);
886 if (result)
887 return;
aeb834d9 888 name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
2f3d000a
YL
889 if (!name)
890 return;
aeb834d9 891 count++;
2f3d000a 892
9661e92c
MG
893 acpi_get_parent(device->dev->handle, &acpi_parent);
894
895 pdev = acpi_get_pci_dev(acpi_parent);
896 if (pdev) {
897 parent = &pdev->dev;
898 pci_dev_put(pdev);
899 }
900
a19a6ee6 901 memset(&props, 0, sizeof(struct backlight_properties));
bb7ca747 902 props.type = BACKLIGHT_FIRMWARE;
a19a6ee6 903 props.max_brightness = device->brightness->count - 3;
9661e92c
MG
904 device->backlight = backlight_device_register(name,
905 parent,
906 device,
a19a6ee6
MG
907 &acpi_backlight_ops,
908 &props);
2f3d000a 909 kfree(name);
e01ce79b
ZR
910 if (IS_ERR(device->backlight))
911 return;
702ed512 912
ac7729da
RW
913 /*
914 * Save current brightness level in case we have to restore it
915 * before acpi_video_device_lcd_set_level() is called next time.
916 */
917 device->backlight->props.brightness =
918 acpi_video_get_brightness(device->backlight);
702ed512 919
4a703a8f 920 device->cooling_dev = thermal_cooling_device_register("LCD",
702ed512 921 device->dev, &video_cooling_ops);
4a703a8f 922 if (IS_ERR(device->cooling_dev)) {
4b4fe3b6 923 /*
4a703a8f 924 * Set cooling_dev to NULL so we don't crash trying to
4b4fe3b6
DT
925 * free it.
926 * Also, why the hell we are returning early and
927 * not attempt to register video output if cooling
928 * device registration failed?
929 * -- dtor
930 */
4a703a8f 931 device->cooling_dev = NULL;
43ff39f2 932 return;
4b4fe3b6 933 }
43ff39f2 934
fc3a8828 935 dev_info(&device->dev->dev, "registered as cooling_device%d\n",
4a703a8f 936 device->cooling_dev->id);
9030062f 937 result = sysfs_create_link(&device->dev->dev.kobj,
4a703a8f 938 &device->cooling_dev->device.kobj,
9030062f
JL
939 "thermal_cooling");
940 if (result)
941 printk(KERN_ERR PREFIX "Create sysfs link\n");
4a703a8f 942 result = sysfs_create_link(&device->cooling_dev->device.kobj,
9030062f
JL
943 &device->dev->dev.kobj, "device");
944 if (result)
945 printk(KERN_ERR PREFIX "Create sysfs link\n");
946
2f3d000a 947 }
1da177e4
LT
948}
949
950/*
951 * Arg:
952 * device : video output device (VGA)
953 *
954 * Return Value:
955 * None
956 *
98fb8fe1 957 * Find out all required AML methods defined under the video bus device.
1da177e4
LT
958 */
959
4be44fcd 960static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
1da177e4 961{
4be44fcd 962 acpi_handle h_dummy1;
1da177e4 963
90130268 964 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) {
1da177e4
LT
965 video->cap._DOS = 1;
966 }
90130268 967 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOD", &h_dummy1))) {
1da177e4
LT
968 video->cap._DOD = 1;
969 }
90130268 970 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_ROM", &h_dummy1))) {
1da177e4
LT
971 video->cap._ROM = 1;
972 }
90130268 973 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_GPD", &h_dummy1))) {
1da177e4
LT
974 video->cap._GPD = 1;
975 }
90130268 976 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_SPD", &h_dummy1))) {
1da177e4
LT
977 video->cap._SPD = 1;
978 }
90130268 979 if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_VPO", &h_dummy1))) {
1da177e4
LT
980 video->cap._VPO = 1;
981 }
982}
983
984/*
985 * Check whether the video bus device has required AML method to
986 * support the desired features
987 */
988
4be44fcd 989static int acpi_video_bus_check(struct acpi_video_bus *video)
1da177e4 990{
4be44fcd 991 acpi_status status = -ENOENT;
1e4cffe7 992 struct pci_dev *dev;
1da177e4
LT
993
994 if (!video)
d550d98d 995 return -EINVAL;
1da177e4 996
1e4cffe7 997 dev = acpi_get_pci_dev(video->device->handle);
22c13f9d
TR
998 if (!dev)
999 return -ENODEV;
1e4cffe7 1000 pci_dev_put(dev);
22c13f9d 1001
1da177e4
LT
1002 /* Since there is no HID, CID and so on for VGA driver, we have
1003 * to check well known required nodes.
1004 */
1005
98fb8fe1 1006 /* Does this device support video switching? */
3a1151e3
SB
1007 if (video->cap._DOS || video->cap._DOD) {
1008 if (!video->cap._DOS) {
1009 printk(KERN_WARNING FW_BUG
1010 "ACPI(%s) defines _DOD but not _DOS\n",
1011 acpi_device_bid(video->device));
1012 }
1da177e4
LT
1013 video->flags.multihead = 1;
1014 status = 0;
1015 }
1016
98fb8fe1 1017 /* Does this device support retrieving a video ROM? */
4be44fcd 1018 if (video->cap._ROM) {
1da177e4
LT
1019 video->flags.rom = 1;
1020 status = 0;
1021 }
1022
98fb8fe1 1023 /* Does this device support configuring which video device to POST? */
4be44fcd 1024 if (video->cap._GPD && video->cap._SPD && video->cap._VPO) {
1da177e4
LT
1025 video->flags.post = 1;
1026 status = 0;
1027 }
1028
d550d98d 1029 return status;
1da177e4
LT
1030}
1031
1da177e4
LT
1032/* --------------------------------------------------------------------------
1033 Driver Interface
1034 -------------------------------------------------------------------------- */
1035
1036/* device interface */
82cae999
RZ
1037static struct acpi_video_device_attrib*
1038acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id)
1039{
78eed028
DT
1040 struct acpi_video_enumerated_device *ids;
1041 int i;
1042
1043 for (i = 0; i < video->attached_count; i++) {
1044 ids = &video->attached_array[i];
1045 if ((ids->value.int_val & 0xffff) == device_id)
1046 return &ids->value.attrib;
1047 }
82cae999 1048
82cae999
RZ
1049 return NULL;
1050}
1da177e4 1051
e92a7162
MG
1052static int
1053acpi_video_get_device_type(struct acpi_video_bus *video,
1054 unsigned long device_id)
1055{
1056 struct acpi_video_enumerated_device *ids;
1057 int i;
1058
1059 for (i = 0; i < video->attached_count; i++) {
1060 ids = &video->attached_array[i];
1061 if ((ids->value.int_val & 0xffff) == device_id)
1062 return ids->value.int_val;
1063 }
1064
1065 return 0;
1066}
1067
1da177e4 1068static int
4be44fcd
LB
1069acpi_video_bus_get_one_device(struct acpi_device *device,
1070 struct acpi_video_bus *video)
1da177e4 1071{
27663c58 1072 unsigned long long device_id;
e92a7162 1073 int status, device_type;
4be44fcd 1074 struct acpi_video_device *data;
82cae999 1075 struct acpi_video_device_attrib* attribute;
1da177e4
LT
1076
1077 if (!device || !video)
d550d98d 1078 return -EINVAL;
1da177e4 1079
4be44fcd
LB
1080 status =
1081 acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
1da177e4
LT
1082 if (ACPI_SUCCESS(status)) {
1083
36bcbec7 1084 data = kzalloc(sizeof(struct acpi_video_device), GFP_KERNEL);
1da177e4 1085 if (!data)
d550d98d 1086 return -ENOMEM;
1da177e4 1087
1da177e4
LT
1088 strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
1089 strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
db89b4f0 1090 device->driver_data = data;
1da177e4
LT
1091
1092 data->device_id = device_id;
1093 data->video = video;
1094 data->dev = device;
1095
82cae999
RZ
1096 attribute = acpi_video_get_device_attr(video, device_id);
1097
1098 if((attribute != NULL) && attribute->device_id_scheme) {
1099 switch (attribute->display_type) {
1100 case ACPI_VIDEO_DISPLAY_CRT:
1101 data->flags.crt = 1;
1102 break;
1103 case ACPI_VIDEO_DISPLAY_TV:
1104 data->flags.tvout = 1;
1105 break;
1106 case ACPI_VIDEO_DISPLAY_DVI:
1107 data->flags.dvi = 1;
1108 break;
1109 case ACPI_VIDEO_DISPLAY_LCD:
1110 data->flags.lcd = 1;
1111 break;
1112 default:
1113 data->flags.unknown = 1;
1114 break;
1115 }
1116 if(attribute->bios_can_detect)
1117 data->flags.bios = 1;
e92a7162
MG
1118 } else {
1119 /* Check for legacy IDs */
1120 device_type = acpi_video_get_device_type(video,
1121 device_id);
1122 /* Ignore bits 16 and 18-20 */
1123 switch (device_type & 0xffe2ffff) {
1124 case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR:
1125 data->flags.crt = 1;
1126 break;
1127 case ACPI_VIDEO_DISPLAY_LEGACY_PANEL:
1128 data->flags.lcd = 1;
1129 break;
1130 case ACPI_VIDEO_DISPLAY_LEGACY_TV:
1131 data->flags.tvout = 1;
1132 break;
1133 default:
1134 data->flags.unknown = 1;
1135 }
1136 }
4be44fcd 1137
1da177e4
LT
1138 acpi_video_device_bind(video, data);
1139 acpi_video_device_find_cap(data);
1140
90130268 1141 status = acpi_install_notify_handler(device->handle,
4be44fcd
LB
1142 ACPI_DEVICE_NOTIFY,
1143 acpi_video_device_notify,
1144 data);
1da177e4 1145 if (ACPI_FAILURE(status)) {
55ac9a01
LM
1146 printk(KERN_ERR PREFIX
1147 "Error installing notify handler\n");
973bf491
YL
1148 if(data->brightness)
1149 kfree(data->brightness->levels);
1150 kfree(data->brightness);
1151 kfree(data);
1152 return -ENODEV;
1da177e4
LT
1153 }
1154
bbac81f5 1155 mutex_lock(&video->device_list_lock);
1da177e4 1156 list_add_tail(&data->entry, &video->video_device_list);
bbac81f5 1157 mutex_unlock(&video->device_list_lock);
1da177e4 1158
d550d98d 1159 return 0;
1da177e4
LT
1160 }
1161
d550d98d 1162 return -ENOENT;
1da177e4
LT
1163}
1164
1165/*
1166 * Arg:
1167 * video : video bus device
1168 *
1169 * Return:
1170 * none
1171 *
1172 * Enumerate the video device list of the video bus,
1173 * bind the ids with the corresponding video devices
1174 * under the video bus.
4be44fcd 1175 */
1da177e4 1176
4be44fcd 1177static void acpi_video_device_rebind(struct acpi_video_bus *video)
1da177e4 1178{
ff102ea9
DT
1179 struct acpi_video_device *dev;
1180
bbac81f5 1181 mutex_lock(&video->device_list_lock);
ff102ea9
DT
1182
1183 list_for_each_entry(dev, &video->video_device_list, entry)
4be44fcd 1184 acpi_video_device_bind(video, dev);
ff102ea9 1185
bbac81f5 1186 mutex_unlock(&video->device_list_lock);
1da177e4
LT
1187}
1188
1189/*
1190 * Arg:
1191 * video : video bus device
1192 * device : video output device under the video
1193 * bus
1194 *
1195 * Return:
1196 * none
1197 *
1198 * Bind the ids with the corresponding video devices
1199 * under the video bus.
4be44fcd 1200 */
1da177e4
LT
1201
1202static void
4be44fcd
LB
1203acpi_video_device_bind(struct acpi_video_bus *video,
1204 struct acpi_video_device *device)
1da177e4 1205{
78eed028 1206 struct acpi_video_enumerated_device *ids;
4be44fcd 1207 int i;
1da177e4 1208
78eed028
DT
1209 for (i = 0; i < video->attached_count; i++) {
1210 ids = &video->attached_array[i];
1211 if (device->device_id == (ids->value.int_val & 0xffff)) {
1212 ids->bind_info = device;
1da177e4
LT
1213 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i));
1214 }
1215 }
1da177e4
LT
1216}
1217
1218/*
1219 * Arg:
1220 * video : video bus device
1221 *
1222 * Return:
1223 * < 0 : error
1224 *
1225 * Call _DOD to enumerate all devices attached to display adapter
1226 *
4be44fcd 1227 */
1da177e4
LT
1228
1229static int acpi_video_device_enumerate(struct acpi_video_bus *video)
1230{
4be44fcd
LB
1231 int status;
1232 int count;
1233 int i;
78eed028 1234 struct acpi_video_enumerated_device *active_list;
4be44fcd
LB
1235 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1236 union acpi_object *dod = NULL;
1237 union acpi_object *obj;
1da177e4 1238
90130268 1239 status = acpi_evaluate_object(video->device->handle, "_DOD", NULL, &buffer);
1da177e4 1240 if (!ACPI_SUCCESS(status)) {
a6fc6720 1241 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _DOD"));
d550d98d 1242 return status;
1da177e4
LT
1243 }
1244
50dd0969 1245 dod = buffer.pointer;
1da177e4 1246 if (!dod || (dod->type != ACPI_TYPE_PACKAGE)) {
a6fc6720 1247 ACPI_EXCEPTION((AE_INFO, status, "Invalid _DOD data"));
1da177e4
LT
1248 status = -EFAULT;
1249 goto out;
1250 }
1251
1252 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n",
4be44fcd 1253 dod->package.count));
1da177e4 1254
78eed028
DT
1255 active_list = kcalloc(1 + dod->package.count,
1256 sizeof(struct acpi_video_enumerated_device),
1257 GFP_KERNEL);
1258 if (!active_list) {
1da177e4
LT
1259 status = -ENOMEM;
1260 goto out;
1261 }
1262
1263 count = 0;
1264 for (i = 0; i < dod->package.count; i++) {
50dd0969 1265 obj = &dod->package.elements[i];
1da177e4
LT
1266
1267 if (obj->type != ACPI_TYPE_INTEGER) {
78eed028
DT
1268 printk(KERN_ERR PREFIX
1269 "Invalid _DOD data in element %d\n", i);
1270 continue;
1da177e4 1271 }
78eed028
DT
1272
1273 active_list[count].value.int_val = obj->integer.value;
1274 active_list[count].bind_info = NULL;
4be44fcd
LB
1275 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i,
1276 (int)obj->integer.value));
1da177e4
LT
1277 count++;
1278 }
1da177e4 1279
6044ec88 1280 kfree(video->attached_array);
4be44fcd 1281
78eed028 1282 video->attached_array = active_list;
1da177e4 1283 video->attached_count = count;
78eed028
DT
1284
1285 out:
02438d87 1286 kfree(buffer.pointer);
d550d98d 1287 return status;
1da177e4
LT
1288}
1289
4be44fcd
LB
1290static int
1291acpi_video_get_next_level(struct acpi_video_device *device,
1292 u32 level_current, u32 event)
1da177e4 1293{
63f0edfc 1294 int min, max, min_above, max_below, i, l, delta = 255;
f4715189
TT
1295 max = max_below = 0;
1296 min = min_above = 255;
63f0edfc 1297 /* Find closest level to level_current */
0a3db1ce 1298 for (i = 2; i < device->brightness->count; i++) {
63f0edfc
AS
1299 l = device->brightness->levels[i];
1300 if (abs(l - level_current) < abs(delta)) {
1301 delta = l - level_current;
1302 if (!delta)
1303 break;
1304 }
1305 }
1306 /* Ajust level_current to closest available level */
1307 level_current += delta;
0a3db1ce 1308 for (i = 2; i < device->brightness->count; i++) {
f4715189
TT
1309 l = device->brightness->levels[i];
1310 if (l < min)
1311 min = l;
1312 if (l > max)
1313 max = l;
1314 if (l < min_above && l > level_current)
1315 min_above = l;
1316 if (l > max_below && l < level_current)
1317 max_below = l;
1318 }
1319
1320 switch (event) {
1321 case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS:
1322 return (level_current < max) ? min_above : min;
1323 case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS:
1324 return (level_current < max) ? min_above : max;
1325 case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS:
1326 return (level_current > min) ? max_below : min;
1327 case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS:
1328 case ACPI_VIDEO_NOTIFY_DISPLAY_OFF:
1329 return 0;
1330 default:
1331 return level_current;
1332 }
1da177e4
LT
1333}
1334
c8890f90 1335static int
4be44fcd 1336acpi_video_switch_brightness(struct acpi_video_device *device, int event)
1da177e4 1337{
27663c58 1338 unsigned long long level_current, level_next;
c8890f90
ZR
1339 int result = -EINVAL;
1340
28c32e99
ZR
1341 /* no warning message if acpi_backlight=vendor is used */
1342 if (!acpi_video_backlight_support())
1343 return 0;
1344
469778c1 1345 if (!device->brightness)
c8890f90
ZR
1346 goto out;
1347
1348 result = acpi_video_device_lcd_get_level_current(device,
a89803df
DB
1349 &level_current,
1350 false);
c8890f90
ZR
1351 if (result)
1352 goto out;
1353
1da177e4 1354 level_next = acpi_video_get_next_level(device, level_current, event);
c8890f90 1355
24450c7a 1356 result = acpi_video_device_lcd_set_level(device, level_next);
c8890f90 1357
36342742
MG
1358 if (!result)
1359 backlight_force_update(device->backlight,
1360 BACKLIGHT_UPDATE_HOTKEY);
1361
c8890f90
ZR
1362out:
1363 if (result)
1364 printk(KERN_ERR PREFIX "Failed to switch the brightness\n");
1365
1366 return result;
1da177e4
LT
1367}
1368
e92a7162
MG
1369int acpi_video_get_edid(struct acpi_device *device, int type, int device_id,
1370 void **edid)
1371{
1372 struct acpi_video_bus *video;
1373 struct acpi_video_device *video_device;
1374 union acpi_object *buffer = NULL;
1375 acpi_status status;
1376 int i, length;
1377
1378 if (!device || !acpi_driver_data(device))
1379 return -EINVAL;
1380
1381 video = acpi_driver_data(device);
1382
1383 for (i = 0; i < video->attached_count; i++) {
1384 video_device = video->attached_array[i].bind_info;
1385 length = 256;
1386
1387 if (!video_device)
1388 continue;
1389
82069552
ZR
1390 if (!video_device->cap._DDC)
1391 continue;
1392
e92a7162
MG
1393 if (type) {
1394 switch (type) {
1395 case ACPI_VIDEO_DISPLAY_CRT:
1396 if (!video_device->flags.crt)
1397 continue;
1398 break;
1399 case ACPI_VIDEO_DISPLAY_TV:
1400 if (!video_device->flags.tvout)
1401 continue;
1402 break;
1403 case ACPI_VIDEO_DISPLAY_DVI:
1404 if (!video_device->flags.dvi)
1405 continue;
1406 break;
1407 case ACPI_VIDEO_DISPLAY_LCD:
1408 if (!video_device->flags.lcd)
1409 continue;
1410 break;
1411 }
1412 } else if (video_device->device_id != device_id) {
1413 continue;
1414 }
1415
1416 status = acpi_video_device_EDID(video_device, &buffer, length);
1417
1418 if (ACPI_FAILURE(status) || !buffer ||
1419 buffer->type != ACPI_TYPE_BUFFER) {
1420 length = 128;
1421 status = acpi_video_device_EDID(video_device, &buffer,
1422 length);
1423 if (ACPI_FAILURE(status) || !buffer ||
1424 buffer->type != ACPI_TYPE_BUFFER) {
1425 continue;
1426 }
1427 }
1428
1429 *edid = buffer->buffer.pointer;
1430 return length;
1431 }
1432
1433 return -ENODEV;
1434}
1435EXPORT_SYMBOL(acpi_video_get_edid);
1436
1da177e4 1437static int
4be44fcd
LB
1438acpi_video_bus_get_devices(struct acpi_video_bus *video,
1439 struct acpi_device *device)
1da177e4 1440{
fba4e087 1441 int status = 0;
ff102ea9 1442 struct acpi_device *dev;
1da177e4 1443
fba4e087
IM
1444 /*
1445 * There are systems where video module known to work fine regardless
1446 * of broken _DOD and ignoring returned value here doesn't cause
1447 * any issues later.
1448 */
1449 acpi_video_device_enumerate(video);
1da177e4 1450
ff102ea9 1451 list_for_each_entry(dev, &device->children, node) {
1da177e4
LT
1452
1453 status = acpi_video_bus_get_one_device(dev, video);
ea9f8856 1454 if (status) {
55ac9a01 1455 printk(KERN_WARNING PREFIX
25985edc 1456 "Can't attach device\n");
1da177e4
LT
1457 continue;
1458 }
1da177e4 1459 }
d550d98d 1460 return status;
1da177e4
LT
1461}
1462
4be44fcd 1463static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
1da177e4 1464{
031ec77b 1465 acpi_status status;
1da177e4
LT
1466
1467 if (!device || !device->video)
d550d98d 1468 return -ENOENT;
1da177e4 1469
90130268 1470 status = acpi_remove_notify_handler(device->dev->handle,
4be44fcd
LB
1471 ACPI_DEVICE_NOTIFY,
1472 acpi_video_device_notify);
cfa806f0
AK
1473 if (ACPI_FAILURE(status)) {
1474 printk(KERN_WARNING PREFIX
25985edc 1475 "Can't remove video notify handler\n");
cfa806f0 1476 }
e29b3ee3 1477 if (device->backlight) {
e29b3ee3
KP
1478 backlight_device_unregister(device->backlight);
1479 device->backlight = NULL;
1480 }
4a703a8f 1481 if (device->cooling_dev) {
702ed512
ZR
1482 sysfs_remove_link(&device->dev->dev.kobj,
1483 "thermal_cooling");
4a703a8f 1484 sysfs_remove_link(&device->cooling_dev->device.kobj,
702ed512 1485 "device");
4a703a8f
DT
1486 thermal_cooling_device_unregister(device->cooling_dev);
1487 device->cooling_dev = NULL;
702ed512 1488 }
ff102ea9 1489
d550d98d 1490 return 0;
1da177e4
LT
1491}
1492
4be44fcd 1493static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
1da177e4 1494{
4be44fcd 1495 int status;
ff102ea9 1496 struct acpi_video_device *dev, *next;
1da177e4 1497
bbac81f5 1498 mutex_lock(&video->device_list_lock);
1da177e4 1499
ff102ea9 1500 list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
1da177e4 1501
ff102ea9 1502 status = acpi_video_bus_put_one_device(dev);
4be44fcd
LB
1503 if (ACPI_FAILURE(status))
1504 printk(KERN_WARNING PREFIX
1505 "hhuuhhuu bug in acpi video driver.\n");
1da177e4 1506
ff102ea9
DT
1507 if (dev->brightness) {
1508 kfree(dev->brightness->levels);
1509 kfree(dev->brightness);
1510 }
1511 list_del(&dev->entry);
1512 kfree(dev);
1da177e4
LT
1513 }
1514
bbac81f5 1515 mutex_unlock(&video->device_list_lock);
ff102ea9 1516
d550d98d 1517 return 0;
1da177e4
LT
1518}
1519
1520/* acpi_video interface */
1521
4be44fcd 1522static int acpi_video_bus_start_devices(struct acpi_video_bus *video)
1da177e4 1523{
a21101c4 1524 return acpi_video_bus_DOS(video, 0, 0);
1da177e4
LT
1525}
1526
4be44fcd 1527static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
1da177e4
LT
1528{
1529 return acpi_video_bus_DOS(video, 0, 1);
1530}
1531
7015558f 1532static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
1da177e4 1533{
7015558f 1534 struct acpi_video_bus *video = acpi_driver_data(device);
e9dab196 1535 struct input_dev *input;
17c452f9 1536 int keycode = 0;
e9dab196 1537
1da177e4 1538 if (!video)
d550d98d 1539 return;
1da177e4 1540
e9dab196 1541 input = video->input;
1da177e4
LT
1542
1543 switch (event) {
98fb8fe1 1544 case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch,
1da177e4 1545 * most likely via hotkey. */
14e04fb3 1546 acpi_bus_generate_proc_event(device, event, 0);
8a37c65d 1547 keycode = KEY_SWITCHVIDEOMODE;
1da177e4
LT
1548 break;
1549
98fb8fe1 1550 case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video
1da177e4
LT
1551 * connector. */
1552 acpi_video_device_enumerate(video);
1553 acpi_video_device_rebind(video);
14e04fb3 1554 acpi_bus_generate_proc_event(device, event, 0);
e9dab196 1555 keycode = KEY_SWITCHVIDEOMODE;
1da177e4
LT
1556 break;
1557
4be44fcd 1558 case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */
25c87f7f 1559 acpi_bus_generate_proc_event(device, event, 0);
e9dab196
LY
1560 keycode = KEY_SWITCHVIDEOMODE;
1561 break;
4be44fcd 1562 case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */
25c87f7f 1563 acpi_bus_generate_proc_event(device, event, 0);
e9dab196
LY
1564 keycode = KEY_VIDEO_NEXT;
1565 break;
4be44fcd 1566 case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */
14e04fb3 1567 acpi_bus_generate_proc_event(device, event, 0);
e9dab196 1568 keycode = KEY_VIDEO_PREV;
1da177e4
LT
1569 break;
1570
1571 default:
1572 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd 1573 "Unsupported event [0x%x]\n", event));
1da177e4
LT
1574 break;
1575 }
1576
8a37c65d
LT
1577 if (acpi_notifier_call_chain(device, event, 0))
1578 /* Something vetoed the keypress. */
1579 keycode = 0;
17c452f9
MG
1580
1581 if (keycode) {
1582 input_report_key(input, keycode, 1);
1583 input_sync(input);
1584 input_report_key(input, keycode, 0);
1585 input_sync(input);
1586 }
e9dab196 1587
d550d98d 1588 return;
1da177e4
LT
1589}
1590
4be44fcd 1591static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
1da177e4 1592{
50dd0969 1593 struct acpi_video_device *video_device = data;
4be44fcd 1594 struct acpi_device *device = NULL;
e9dab196
LY
1595 struct acpi_video_bus *bus;
1596 struct input_dev *input;
17c452f9 1597 int keycode = 0;
1da177e4 1598
1da177e4 1599 if (!video_device)
d550d98d 1600 return;
1da177e4 1601
e6afa0de 1602 device = video_device->dev;
e9dab196
LY
1603 bus = video_device->video;
1604 input = bus->input;
1da177e4
LT
1605
1606 switch (event) {
4be44fcd 1607 case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */
8a681a4d
ZR
1608 if (brightness_switch_enabled)
1609 acpi_video_switch_brightness(video_device, event);
14e04fb3 1610 acpi_bus_generate_proc_event(device, event, 0);
e9dab196
LY
1611 keycode = KEY_BRIGHTNESS_CYCLE;
1612 break;
4be44fcd 1613 case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */
8a681a4d
ZR
1614 if (brightness_switch_enabled)
1615 acpi_video_switch_brightness(video_device, event);
25c87f7f 1616 acpi_bus_generate_proc_event(device, event, 0);
e9dab196
LY
1617 keycode = KEY_BRIGHTNESSUP;
1618 break;
4be44fcd 1619 case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */
8a681a4d
ZR
1620 if (brightness_switch_enabled)
1621 acpi_video_switch_brightness(video_device, event);
25c87f7f 1622 acpi_bus_generate_proc_event(device, event, 0);
e9dab196
LY
1623 keycode = KEY_BRIGHTNESSDOWN;
1624 break;
70f23fd6 1625 case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightness */
8a681a4d
ZR
1626 if (brightness_switch_enabled)
1627 acpi_video_switch_brightness(video_device, event);
25c87f7f 1628 acpi_bus_generate_proc_event(device, event, 0);
e9dab196
LY
1629 keycode = KEY_BRIGHTNESS_ZERO;
1630 break;
4be44fcd 1631 case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */
8a681a4d
ZR
1632 if (brightness_switch_enabled)
1633 acpi_video_switch_brightness(video_device, event);
14e04fb3 1634 acpi_bus_generate_proc_event(device, event, 0);
e9dab196 1635 keycode = KEY_DISPLAY_OFF;
1da177e4
LT
1636 break;
1637 default:
1638 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd 1639 "Unsupported event [0x%x]\n", event));
1da177e4
LT
1640 break;
1641 }
e9dab196 1642
7761f638 1643 acpi_notifier_call_chain(device, event, 0);
17c452f9
MG
1644
1645 if (keycode) {
1646 input_report_key(input, keycode, 1);
1647 input_sync(input);
1648 input_report_key(input, keycode, 0);
1649 input_sync(input);
1650 }
e9dab196 1651
d550d98d 1652 return;
1da177e4
LT
1653}
1654
ac7729da
RW
1655static int acpi_video_resume(struct notifier_block *nb,
1656 unsigned long val, void *ign)
863c1490
MG
1657{
1658 struct acpi_video_bus *video;
1659 struct acpi_video_device *video_device;
1660 int i;
1661
ac7729da
RW
1662 switch (val) {
1663 case PM_HIBERNATION_PREPARE:
1664 case PM_SUSPEND_PREPARE:
1665 case PM_RESTORE_PREPARE:
1666 return NOTIFY_DONE;
1667 }
863c1490 1668
ac7729da
RW
1669 video = container_of(nb, struct acpi_video_bus, pm_nb);
1670
1671 dev_info(&video->device->dev, "Restoring backlight state\n");
863c1490
MG
1672
1673 for (i = 0; i < video->attached_count; i++) {
1674 video_device = video->attached_array[i].bind_info;
1675 if (video_device && video_device->backlight)
1676 acpi_video_set_brightness(video_device->backlight);
1677 }
ac7729da
RW
1678
1679 return NOTIFY_OK;
863c1490
MG
1680}
1681
c504f8cb
ZR
1682static acpi_status
1683acpi_video_bus_match(acpi_handle handle, u32 level, void *context,
1684 void **return_value)
1685{
1686 struct acpi_device *device = context;
1687 struct acpi_device *sibling;
1688 int result;
1689
1690 if (handle == device->handle)
1691 return AE_CTRL_TERMINATE;
1692
1693 result = acpi_bus_get_device(handle, &sibling);
1694 if (result)
1695 return AE_OK;
1696
1697 if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME))
1698 return AE_ALREADY_EXISTS;
1699
1700 return AE_OK;
1701}
1702
ac7729da
RW
1703static int instance;
1704
4be44fcd 1705static int acpi_video_bus_add(struct acpi_device *device)
1da177e4 1706{
f51e8391 1707 struct acpi_video_bus *video;
e9dab196 1708 struct input_dev *input;
f51e8391 1709 int error;
c504f8cb
ZR
1710 acpi_status status;
1711
1712 status = acpi_walk_namespace(ACPI_TYPE_DEVICE,
1713 device->parent->handle, 1,
1714 acpi_video_bus_match, NULL,
1715 device, NULL);
1716 if (status == AE_ALREADY_EXISTS) {
1717 printk(KERN_WARNING FW_BUG
1718 "Duplicate ACPI video bus devices for the"
1719 " same VGA controller, please try module "
1720 "parameter \"video.allow_duplicates=1\""
1721 "if the current driver doesn't work.\n");
1722 if (!allow_duplicates)
1723 return -ENODEV;
1724 }
1da177e4 1725
36bcbec7 1726 video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL);
1da177e4 1727 if (!video)
d550d98d 1728 return -ENOMEM;
1da177e4 1729
e6d9da1d
ZR
1730 /* a hack to fix the duplicate name "VID" problem on T61 */
1731 if (!strcmp(device->pnp.bus_id, "VID")) {
1732 if (instance)
1733 device->pnp.bus_id[3] = '0' + instance;
1734 instance ++;
1735 }
f3b39f13
ZY
1736 /* a hack to fix the duplicate name "VGA" problem on Pa 3553 */
1737 if (!strcmp(device->pnp.bus_id, "VGA")) {
1738 if (instance)
1739 device->pnp.bus_id[3] = '0' + instance;
1740 instance++;
1741 }
e6d9da1d 1742
e6afa0de 1743 video->device = device;
1da177e4
LT
1744 strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
1745 strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
db89b4f0 1746 device->driver_data = video;
1da177e4
LT
1747
1748 acpi_video_bus_find_cap(video);
f51e8391
DT
1749 error = acpi_video_bus_check(video);
1750 if (error)
1751 goto err_free_video;
1da177e4 1752
bbac81f5 1753 mutex_init(&video->device_list_lock);
1da177e4
LT
1754 INIT_LIST_HEAD(&video->video_device_list);
1755
ea9f8856
IM
1756 error = acpi_video_bus_get_devices(video, device);
1757 if (error)
1758 goto err_free_video;
1da177e4 1759
e9dab196 1760 video->input = input = input_allocate_device();
f51e8391
DT
1761 if (!input) {
1762 error = -ENOMEM;
b60e7f61 1763 goto err_put_video;
f51e8391 1764 }
e9dab196 1765
b60e7f61
IM
1766 error = acpi_video_bus_start_devices(video);
1767 if (error)
1768 goto err_free_input_dev;
1769
e9dab196
LY
1770 snprintf(video->phys, sizeof(video->phys),
1771 "%s/video/input0", acpi_device_hid(video->device));
1772
1773 input->name = acpi_device_name(video->device);
1774 input->phys = video->phys;
1775 input->id.bustype = BUS_HOST;
1776 input->id.product = 0x06;
91c05c66 1777 input->dev.parent = &device->dev;
e9dab196
LY
1778 input->evbit[0] = BIT(EV_KEY);
1779 set_bit(KEY_SWITCHVIDEOMODE, input->keybit);
1780 set_bit(KEY_VIDEO_NEXT, input->keybit);
1781 set_bit(KEY_VIDEO_PREV, input->keybit);
1782 set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit);
1783 set_bit(KEY_BRIGHTNESSUP, input->keybit);
1784 set_bit(KEY_BRIGHTNESSDOWN, input->keybit);
1785 set_bit(KEY_BRIGHTNESS_ZERO, input->keybit);
1786 set_bit(KEY_DISPLAY_OFF, input->keybit);
e9dab196 1787
1da177e4 1788 printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n",
4be44fcd
LB
1789 ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
1790 video->flags.multihead ? "yes" : "no",
1791 video->flags.rom ? "yes" : "no",
1792 video->flags.post ? "yes" : "no");
1da177e4 1793
ac7729da
RW
1794 video->pm_nb.notifier_call = acpi_video_resume;
1795 video->pm_nb.priority = 0;
ea9f8856
IM
1796 error = register_pm_notifier(&video->pm_nb);
1797 if (error)
301f33fb
DC
1798 goto err_stop_video;
1799
1800 error = input_register_device(input);
1801 if (error)
1802 goto err_unregister_pm_notifier;
ac7729da 1803
f51e8391
DT
1804 return 0;
1805
301f33fb
DC
1806 err_unregister_pm_notifier:
1807 unregister_pm_notifier(&video->pm_nb);
f51e8391
DT
1808 err_stop_video:
1809 acpi_video_bus_stop_devices(video);
b60e7f61
IM
1810 err_free_input_dev:
1811 input_free_device(input);
ea9f8856 1812 err_put_video:
f51e8391
DT
1813 acpi_video_bus_put_devices(video);
1814 kfree(video->attached_array);
f51e8391
DT
1815 err_free_video:
1816 kfree(video);
db89b4f0 1817 device->driver_data = NULL;
1da177e4 1818
f51e8391 1819 return error;
1da177e4
LT
1820}
1821
51fac838 1822static int acpi_video_bus_remove(struct acpi_device *device)
1da177e4 1823{
4be44fcd 1824 struct acpi_video_bus *video = NULL;
1da177e4 1825
1da177e4
LT
1826
1827 if (!device || !acpi_driver_data(device))
d550d98d 1828 return -EINVAL;
1da177e4 1829
50dd0969 1830 video = acpi_driver_data(device);
1da177e4 1831
ac7729da
RW
1832 unregister_pm_notifier(&video->pm_nb);
1833
1da177e4 1834 acpi_video_bus_stop_devices(video);
1da177e4 1835 acpi_video_bus_put_devices(video);
1da177e4 1836
e9dab196 1837 input_unregister_device(video->input);
6044ec88 1838 kfree(video->attached_array);
1da177e4
LT
1839 kfree(video);
1840
d550d98d 1841 return 0;
1da177e4
LT
1842}
1843
c6996bdd
AC
1844static int __init is_i740(struct pci_dev *dev)
1845{
1846 if (dev->device == 0x00D1)
1847 return 1;
1848 if (dev->device == 0x7000)
1849 return 1;
1850 return 0;
1851}
1852
74a365b3
MG
1853static int __init intel_opregion_present(void)
1854{
c6996bdd 1855 int opregion = 0;
74a365b3
MG
1856 struct pci_dev *dev = NULL;
1857 u32 address;
1858
1859 for_each_pci_dev(dev) {
1860 if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
1861 continue;
1862 if (dev->vendor != PCI_VENDOR_ID_INTEL)
1863 continue;
c6996bdd
AC
1864 /* We don't want to poke around undefined i740 registers */
1865 if (is_i740(dev))
1866 continue;
74a365b3
MG
1867 pci_read_config_dword(dev, 0xfc, &address);
1868 if (!address)
1869 continue;
c6996bdd 1870 opregion = 1;
74a365b3 1871 }
c6996bdd 1872 return opregion;
74a365b3
MG
1873}
1874
1875int acpi_video_register(void)
1da177e4 1876{
4be44fcd 1877 int result = 0;
86e437f0
ZY
1878 if (register_count) {
1879 /*
1880 * if the function of acpi_video_register is already called,
1881 * don't register the acpi_vide_bus again and return no error.
1882 */
1883 return 0;
1884 }
1da177e4 1885
1da177e4 1886 result = acpi_bus_register_driver(&acpi_video_bus);
39fe394d 1887 if (result < 0)
d550d98d 1888 return -ENODEV;
1da177e4 1889
86e437f0
ZY
1890 /*
1891 * When the acpi_video_bus is loaded successfully, increase
1892 * the counter reference.
1893 */
1894 register_count = 1;
1895
d550d98d 1896 return 0;
1da177e4 1897}
74a365b3
MG
1898EXPORT_SYMBOL(acpi_video_register);
1899
86e437f0
ZY
1900void acpi_video_unregister(void)
1901{
1902 if (!register_count) {
1903 /*
1904 * If the acpi video bus is already unloaded, don't
1905 * unload it again and return directly.
1906 */
1907 return;
1908 }
1909 acpi_bus_unregister_driver(&acpi_video_bus);
1910
86e437f0
ZY
1911 register_count = 0;
1912
1913 return;
1914}
1915EXPORT_SYMBOL(acpi_video_unregister);
1916
74a365b3
MG
1917/*
1918 * This is kind of nasty. Hardware using Intel chipsets may require
1919 * the video opregion code to be run first in order to initialise
1920 * state before any ACPI video calls are made. To handle this we defer
1921 * registration of the video class until the opregion code has run.
1922 */
1923
1924static int __init acpi_video_init(void)
1925{
45cb50e6
ZR
1926 dmi_check_system(video_dmi_table);
1927
74a365b3
MG
1928 if (intel_opregion_present())
1929 return 0;
1930
1931 return acpi_video_register();
1932}
1da177e4 1933
86e437f0 1934static void __exit acpi_video_exit(void)
1da177e4 1935{
86e437f0 1936 acpi_video_unregister();
1da177e4 1937
d550d98d 1938 return;
1da177e4
LT
1939}
1940
1941module_init(acpi_video_init);
1942module_exit(acpi_video_exit);
This page took 0.944944 seconds and 5 git commands to generate.