Pull battery into release branch
[linux-3.10.git] / drivers / acpi / video.c
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>
6  *  Copyright (C) 2006 Thomas Tuttle <linux-kernel@ttuttle.net>
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>
32 #include <linux/proc_fs.h>
33 #include <linux/seq_file.h>
34
35 #include <linux/backlight.h>
36 #include <linux/video_output.h>
37 #include <asm/uaccess.h>
38
39 #include <acpi/acpi_bus.h>
40 #include <acpi/acpi_drivers.h>
41
42 #define ACPI_VIDEO_COMPONENT            0x08000000
43 #define ACPI_VIDEO_CLASS                "video"
44 #define ACPI_VIDEO_BUS_NAME             "Video Bus"
45 #define ACPI_VIDEO_DEVICE_NAME          "Video Device"
46 #define ACPI_VIDEO_NOTIFY_SWITCH        0x80
47 #define ACPI_VIDEO_NOTIFY_PROBE         0x81
48 #define ACPI_VIDEO_NOTIFY_CYCLE         0x82
49 #define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT   0x83
50 #define ACPI_VIDEO_NOTIFY_PREV_OUTPUT   0x84
51
52 #define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS      0x85
53 #define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS        0x86
54 #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS        0x87
55 #define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS       0x88
56 #define ACPI_VIDEO_NOTIFY_DISPLAY_OFF           0x89
57
58 #define ACPI_VIDEO_HEAD_INVALID         (~0u - 1)
59 #define ACPI_VIDEO_HEAD_END             (~0u)
60 #define MAX_NAME_LEN    20
61
62 #define ACPI_VIDEO_DISPLAY_CRT  1
63 #define ACPI_VIDEO_DISPLAY_TV   2
64 #define ACPI_VIDEO_DISPLAY_DVI  3
65 #define ACPI_VIDEO_DISPLAY_LCD  4
66
67 #define _COMPONENT              ACPI_VIDEO_COMPONENT
68 ACPI_MODULE_NAME("video");
69
70 MODULE_AUTHOR("Bruno Ducrot");
71 MODULE_DESCRIPTION("ACPI Video Driver");
72 MODULE_LICENSE("GPL");
73
74 static int acpi_video_bus_add(struct acpi_device *device);
75 static int acpi_video_bus_remove(struct acpi_device *device, int type);
76
77 static const struct acpi_device_id video_device_ids[] = {
78         {ACPI_VIDEO_HID, 0},
79         {"", 0},
80 };
81 MODULE_DEVICE_TABLE(acpi, video_device_ids);
82
83 static struct acpi_driver acpi_video_bus = {
84         .name = "video",
85         .class = ACPI_VIDEO_CLASS,
86         .ids = video_device_ids,
87         .ops = {
88                 .add = acpi_video_bus_add,
89                 .remove = acpi_video_bus_remove,
90                 },
91 };
92
93 struct acpi_video_bus_flags {
94         u8 multihead:1;         /* can switch video heads */
95         u8 rom:1;               /* can retrieve a video rom */
96         u8 post:1;              /* can configure the head to */
97         u8 reserved:5;
98 };
99
100 struct acpi_video_bus_cap {
101         u8 _DOS:1;              /*Enable/Disable output switching */
102         u8 _DOD:1;              /*Enumerate all devices attached to display adapter */
103         u8 _ROM:1;              /*Get ROM Data */
104         u8 _GPD:1;              /*Get POST Device */
105         u8 _SPD:1;              /*Set POST Device */
106         u8 _VPO:1;              /*Video POST Options */
107         u8 reserved:2;
108 };
109
110 struct acpi_video_device_attrib {
111         u32 display_index:4;    /* A zero-based instance of the Display */
112         u32 display_port_attachment:4;  /*This field differentiates the display type */
113         u32 display_type:4;     /*Describe the specific type in use */
114         u32 vendor_specific:4;  /*Chipset Vendor Specific */
115         u32 bios_can_detect:1;  /*BIOS can detect the device */
116         u32 depend_on_vga:1;    /*Non-VGA output device whose power is related to 
117                                    the VGA device. */
118         u32 pipe_id:3;          /*For VGA multiple-head devices. */
119         u32 reserved:10;        /*Must be 0 */
120         u32 device_id_scheme:1; /*Device ID Scheme */
121 };
122
123 struct acpi_video_enumerated_device {
124         union {
125                 u32 int_val;
126                 struct acpi_video_device_attrib attrib;
127         } value;
128         struct acpi_video_device *bind_info;
129 };
130
131 struct acpi_video_bus {
132         struct acpi_device *device;
133         u8 dos_setting;
134         struct acpi_video_enumerated_device *attached_array;
135         u8 attached_count;
136         struct acpi_video_bus_cap cap;
137         struct acpi_video_bus_flags flags;
138         struct semaphore sem;
139         struct list_head video_device_list;
140         struct proc_dir_entry *dir;
141 };
142
143 struct acpi_video_device_flags {
144         u8 crt:1;
145         u8 lcd:1;
146         u8 tvout:1;
147         u8 dvi:1;
148         u8 bios:1;
149         u8 unknown:1;
150         u8 reserved:2;
151 };
152
153 struct acpi_video_device_cap {
154         u8 _ADR:1;              /*Return the unique ID */
155         u8 _BCL:1;              /*Query list of brightness control levels supported */
156         u8 _BCM:1;              /*Set the brightness level */
157         u8 _BQC:1;              /* Get current brightness level */
158         u8 _DDC:1;              /*Return the EDID for this device */
159         u8 _DCS:1;              /*Return status of output device */
160         u8 _DGS:1;              /*Query graphics state */
161         u8 _DSS:1;              /*Device state set */
162 };
163
164 struct acpi_video_device_brightness {
165         int curr;
166         int count;
167         int *levels;
168 };
169
170 struct acpi_video_device {
171         unsigned long device_id;
172         struct acpi_video_device_flags flags;
173         struct acpi_video_device_cap cap;
174         struct list_head entry;
175         struct acpi_video_bus *video;
176         struct acpi_device *dev;
177         struct acpi_video_device_brightness *brightness;
178         struct backlight_device *backlight;
179         struct output_device *output_dev;
180 };
181
182 /* bus */
183 static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
184 static struct file_operations acpi_video_bus_info_fops = {
185         .open = acpi_video_bus_info_open_fs,
186         .read = seq_read,
187         .llseek = seq_lseek,
188         .release = single_release,
189 };
190
191 static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
192 static struct file_operations acpi_video_bus_ROM_fops = {
193         .open = acpi_video_bus_ROM_open_fs,
194         .read = seq_read,
195         .llseek = seq_lseek,
196         .release = single_release,
197 };
198
199 static int acpi_video_bus_POST_info_open_fs(struct inode *inode,
200                                             struct file *file);
201 static struct file_operations acpi_video_bus_POST_info_fops = {
202         .open = acpi_video_bus_POST_info_open_fs,
203         .read = seq_read,
204         .llseek = seq_lseek,
205         .release = single_release,
206 };
207
208 static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
209 static struct file_operations acpi_video_bus_POST_fops = {
210         .open = acpi_video_bus_POST_open_fs,
211         .read = seq_read,
212         .llseek = seq_lseek,
213         .release = single_release,
214 };
215
216 static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
217 static struct file_operations acpi_video_bus_DOS_fops = {
218         .open = acpi_video_bus_DOS_open_fs,
219         .read = seq_read,
220         .llseek = seq_lseek,
221         .release = single_release,
222 };
223
224 /* device */
225 static int acpi_video_device_info_open_fs(struct inode *inode,
226                                           struct file *file);
227 static struct file_operations acpi_video_device_info_fops = {
228         .open = acpi_video_device_info_open_fs,
229         .read = seq_read,
230         .llseek = seq_lseek,
231         .release = single_release,
232 };
233
234 static int acpi_video_device_state_open_fs(struct inode *inode,
235                                            struct file *file);
236 static struct file_operations acpi_video_device_state_fops = {
237         .open = acpi_video_device_state_open_fs,
238         .read = seq_read,
239         .llseek = seq_lseek,
240         .release = single_release,
241 };
242
243 static int acpi_video_device_brightness_open_fs(struct inode *inode,
244                                                 struct file *file);
245 static struct file_operations acpi_video_device_brightness_fops = {
246         .open = acpi_video_device_brightness_open_fs,
247         .read = seq_read,
248         .llseek = seq_lseek,
249         .release = single_release,
250 };
251
252 static int acpi_video_device_EDID_open_fs(struct inode *inode,
253                                           struct file *file);
254 static struct file_operations acpi_video_device_EDID_fops = {
255         .open = acpi_video_device_EDID_open_fs,
256         .read = seq_read,
257         .llseek = seq_lseek,
258         .release = single_release,
259 };
260
261 static char device_decode[][30] = {
262         "motherboard VGA device",
263         "PCI VGA device",
264         "AGP VGA device",
265         "UNKNOWN",
266 };
267
268 static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data);
269 static void acpi_video_device_rebind(struct acpi_video_bus *video);
270 static void acpi_video_device_bind(struct acpi_video_bus *video,
271                                    struct acpi_video_device *device);
272 static int acpi_video_device_enumerate(struct acpi_video_bus *video);
273 static int acpi_video_switch_output(struct acpi_video_bus *video, int event);
274 static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
275                         int level);
276 static int acpi_video_device_lcd_get_level_current(
277                         struct acpi_video_device *device,
278                         unsigned long *level);
279 static int acpi_video_get_next_level(struct acpi_video_device *device,
280                                      u32 level_current, u32 event);
281 static void acpi_video_switch_brightness(struct acpi_video_device *device,
282                                          int event);
283 static int acpi_video_device_get_state(struct acpi_video_device *device,
284                             unsigned long *state);
285 static int acpi_video_output_get(struct output_device *od);
286 static int acpi_video_device_set_state(struct acpi_video_device *device, int state);
287
288 /*backlight device sysfs support*/
289 static int acpi_video_get_brightness(struct backlight_device *bd)
290 {
291         unsigned long cur_level;
292         struct acpi_video_device *vd =
293                 (struct acpi_video_device *)bl_get_data(bd);
294         acpi_video_device_lcd_get_level_current(vd, &cur_level);
295         return (int) cur_level;
296 }
297
298 static int acpi_video_set_brightness(struct backlight_device *bd)
299 {
300         int request_level = bd->props.brightness;
301         struct acpi_video_device *vd =
302                 (struct acpi_video_device *)bl_get_data(bd);
303         acpi_video_device_lcd_set_level(vd, request_level);
304         return 0;
305 }
306
307 static struct backlight_ops acpi_backlight_ops = {
308         .get_brightness = acpi_video_get_brightness,
309         .update_status  = acpi_video_set_brightness,
310 };
311
312 /*video output device sysfs support*/
313 static int acpi_video_output_get(struct output_device *od)
314 {
315         unsigned long state;
316         struct acpi_video_device *vd =
317                 (struct acpi_video_device *)class_get_devdata(&od->class_dev);
318         acpi_video_device_get_state(vd, &state);
319         return (int)state;
320 }
321
322 static int acpi_video_output_set(struct output_device *od)
323 {
324         unsigned long state = od->request_state;
325         struct acpi_video_device *vd=
326                 (struct acpi_video_device *)class_get_devdata(&od->class_dev);
327         return acpi_video_device_set_state(vd, state);
328 }
329
330 static struct output_properties acpi_output_properties = {
331         .set_state = acpi_video_output_set,
332         .get_status = acpi_video_output_get,
333 };
334 /* --------------------------------------------------------------------------
335                                Video Management
336    -------------------------------------------------------------------------- */
337
338 /* device */
339
340 static int
341 acpi_video_device_query(struct acpi_video_device *device, unsigned long *state)
342 {
343         int status;
344
345         status = acpi_evaluate_integer(device->dev->handle, "_DGS", NULL, state);
346
347         return status;
348 }
349
350 static int
351 acpi_video_device_get_state(struct acpi_video_device *device,
352                             unsigned long *state)
353 {
354         int status;
355
356         status = acpi_evaluate_integer(device->dev->handle, "_DCS", NULL, state);
357
358         return status;
359 }
360
361 static int
362 acpi_video_device_set_state(struct acpi_video_device *device, int state)
363 {
364         int status;
365         union acpi_object arg0 = { ACPI_TYPE_INTEGER };
366         struct acpi_object_list args = { 1, &arg0 };
367         unsigned long ret;
368
369
370         arg0.integer.value = state;
371         status = acpi_evaluate_integer(device->dev->handle, "_DSS", &args, &ret);
372
373         return status;
374 }
375
376 static int
377 acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
378                                    union acpi_object **levels)
379 {
380         int status;
381         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
382         union acpi_object *obj;
383
384
385         *levels = NULL;
386
387         status = acpi_evaluate_object(device->dev->handle, "_BCL", NULL, &buffer);
388         if (!ACPI_SUCCESS(status))
389                 return status;
390         obj = (union acpi_object *)buffer.pointer;
391         if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
392                 printk(KERN_ERR PREFIX "Invalid _BCL data\n");
393                 status = -EFAULT;
394                 goto err;
395         }
396
397         *levels = obj;
398
399         return 0;
400
401       err:
402         kfree(buffer.pointer);
403
404         return status;
405 }
406
407 static int
408 acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
409 {
410         int status;
411         union acpi_object arg0 = { ACPI_TYPE_INTEGER };
412         struct acpi_object_list args = { 1, &arg0 };
413
414
415         arg0.integer.value = level;
416         status = acpi_evaluate_object(device->dev->handle, "_BCM", &args, NULL);
417
418         printk(KERN_DEBUG "set_level status: %x\n", status);
419         return status;
420 }
421
422 static int
423 acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
424                                         unsigned long *level)
425 {
426         int status;
427
428         status = acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, level);
429
430         return status;
431 }
432
433 static int
434 acpi_video_device_EDID(struct acpi_video_device *device,
435                        union acpi_object **edid, ssize_t length)
436 {
437         int status;
438         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
439         union acpi_object *obj;
440         union acpi_object arg0 = { ACPI_TYPE_INTEGER };
441         struct acpi_object_list args = { 1, &arg0 };
442
443
444         *edid = NULL;
445
446         if (!device)
447                 return -ENODEV;
448         if (length == 128)
449                 arg0.integer.value = 1;
450         else if (length == 256)
451                 arg0.integer.value = 2;
452         else
453                 return -EINVAL;
454
455         status = acpi_evaluate_object(device->dev->handle, "_DDC", &args, &buffer);
456         if (ACPI_FAILURE(status))
457                 return -ENODEV;
458
459         obj = buffer.pointer;
460
461         if (obj && obj->type == ACPI_TYPE_BUFFER)
462                 *edid = obj;
463         else {
464                 printk(KERN_ERR PREFIX "Invalid _DDC data\n");
465                 status = -EFAULT;
466                 kfree(obj);
467         }
468
469         return status;
470 }
471
472 /* bus */
473
474 static int
475 acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
476 {
477         int status;
478         unsigned long tmp;
479         union acpi_object arg0 = { ACPI_TYPE_INTEGER };
480         struct acpi_object_list args = { 1, &arg0 };
481
482
483         arg0.integer.value = option;
484
485         status = acpi_evaluate_integer(video->device->handle, "_SPD", &args, &tmp);
486         if (ACPI_SUCCESS(status))
487                 status = tmp ? (-EINVAL) : (AE_OK);
488
489         return status;
490 }
491
492 static int
493 acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id)
494 {
495         int status;
496
497         status = acpi_evaluate_integer(video->device->handle, "_GPD", NULL, id);
498
499         return status;
500 }
501
502 static int
503 acpi_video_bus_POST_options(struct acpi_video_bus *video,
504                             unsigned long *options)
505 {
506         int status;
507
508         status = acpi_evaluate_integer(video->device->handle, "_VPO", NULL, options);
509         *options &= 3;
510
511         return status;
512 }
513
514 /*
515  *  Arg:
516  *      video           : video bus device pointer
517  *      bios_flag       : 
518  *              0.      The system BIOS should NOT automatically switch(toggle)
519  *                      the active display output.
520  *              1.      The system BIOS should automatically switch (toggle) the
521  *                      active display output. No switch event.
522  *              2.      The _DGS value should be locked.
523  *              3.      The system BIOS should not automatically switch (toggle) the
524  *                      active display output, but instead generate the display switch
525  *                      event notify code.
526  *      lcd_flag        :
527  *              0.      The system BIOS should automatically control the brightness level
528  *                      of the LCD when the power changes from AC to DC
529  *              1.      The system BIOS should NOT automatically control the brightness 
530  *                      level of the LCD when the power changes from AC to DC.
531  * Return Value:
532  *              -1      wrong arg.
533  */
534
535 static int
536 acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
537 {
538         acpi_integer status = 0;
539         union acpi_object arg0 = { ACPI_TYPE_INTEGER };
540         struct acpi_object_list args = { 1, &arg0 };
541
542
543         if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) {
544                 status = -1;
545                 goto Failed;
546         }
547         arg0.integer.value = (lcd_flag << 2) | bios_flag;
548         video->dos_setting = arg0.integer.value;
549         acpi_evaluate_object(video->device->handle, "_DOS", &args, NULL);
550
551       Failed:
552         return status;
553 }
554
555 /*
556  *  Arg:        
557  *      device  : video output device (LCD, CRT, ..)
558  *
559  *  Return Value:
560  *      None
561  *
562  *  Find out all required AML methods defined under the output
563  *  device.
564  */
565
566 static void acpi_video_device_find_cap(struct acpi_video_device *device)
567 {
568         acpi_handle h_dummy1;
569         int i;
570         u32 max_level = 0;
571         union acpi_object *obj = NULL;
572         struct acpi_video_device_brightness *br = NULL;
573
574
575         memset(&device->cap, 0, 4);
576
577         if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) {
578                 device->cap._ADR = 1;
579         }
580         if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCL", &h_dummy1))) {
581                 device->cap._BCL = 1;
582         }
583         if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) {
584                 device->cap._BCM = 1;
585         }
586         if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1)))
587                 device->cap._BQC = 1;
588         if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) {
589                 device->cap._DDC = 1;
590         }
591         if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DCS", &h_dummy1))) {
592                 device->cap._DCS = 1;
593         }
594         if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DGS", &h_dummy1))) {
595                 device->cap._DGS = 1;
596         }
597         if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DSS", &h_dummy1))) {
598                 device->cap._DSS = 1;
599         }
600
601         if (ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
602
603                 if (obj->package.count >= 2) {
604                         int count = 0;
605                         union acpi_object *o;
606
607                         br = kzalloc(sizeof(*br), GFP_KERNEL);
608                         if (!br) {
609                                 printk(KERN_ERR "can't allocate memory\n");
610                         } else {
611                                 br->levels = kmalloc(obj->package.count *
612                                                      sizeof *(br->levels), GFP_KERNEL);
613                                 if (!br->levels)
614                                         goto out;
615
616                                 for (i = 0; i < obj->package.count; i++) {
617                                         o = (union acpi_object *)&obj->package.
618                                             elements[i];
619                                         if (o->type != ACPI_TYPE_INTEGER) {
620                                                 printk(KERN_ERR PREFIX "Invalid data\n");
621                                                 continue;
622                                         }
623                                         br->levels[count] = (u32) o->integer.value;
624
625                                         if (br->levels[count] > max_level)
626                                                 max_level = br->levels[count];
627                                         count++;
628                                 }
629                               out:
630                                 if (count < 2) {
631                                         kfree(br->levels);
632                                         kfree(br);
633                                 } else {
634                                         br->count = count;
635                                         device->brightness = br;
636                                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
637                                                           "found %d brightness levels\n",
638                                                           count));
639                                 }
640                         }
641                 }
642
643         } else {
644                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available LCD brightness level\n"));
645         }
646
647         kfree(obj);
648
649         if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
650                 unsigned long tmp;
651                 static int count = 0;
652                 char *name;
653                 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
654                 if (!name)
655                         return;
656
657                 sprintf(name, "acpi_video%d", count++);
658                 acpi_video_device_lcd_get_level_current(device, &tmp);
659                 device->backlight = backlight_device_register(name,
660                         NULL, device, &acpi_backlight_ops);
661                 device->backlight->props.max_brightness = max_level;
662                 device->backlight->props.brightness = (int)tmp;
663                 backlight_update_status(device->backlight);
664
665                 kfree(name);
666         }
667         if (device->cap._DCS && device->cap._DSS){
668                 static int count = 0;
669                 char *name;
670                 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
671                 if (!name)
672                         return;
673                 sprintf(name, "acpi_video%d", count++);
674                 device->output_dev = video_output_register(name,
675                                 NULL, device, &acpi_output_properties);
676                 kfree(name);
677         }
678         return;
679 }
680
681 /*
682  *  Arg:        
683  *      device  : video output device (VGA)
684  *
685  *  Return Value:
686  *      None
687  *
688  *  Find out all required AML methods defined under the video bus device.
689  */
690
691 static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
692 {
693         acpi_handle h_dummy1;
694
695         memset(&video->cap, 0, 4);
696         if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) {
697                 video->cap._DOS = 1;
698         }
699         if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOD", &h_dummy1))) {
700                 video->cap._DOD = 1;
701         }
702         if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_ROM", &h_dummy1))) {
703                 video->cap._ROM = 1;
704         }
705         if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_GPD", &h_dummy1))) {
706                 video->cap._GPD = 1;
707         }
708         if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_SPD", &h_dummy1))) {
709                 video->cap._SPD = 1;
710         }
711         if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_VPO", &h_dummy1))) {
712                 video->cap._VPO = 1;
713         }
714 }
715
716 /*
717  * Check whether the video bus device has required AML method to
718  * support the desired features
719  */
720
721 static int acpi_video_bus_check(struct acpi_video_bus *video)
722 {
723         acpi_status status = -ENOENT;
724
725
726         if (!video)
727                 return -EINVAL;
728
729         /* Since there is no HID, CID and so on for VGA driver, we have
730          * to check well known required nodes.
731          */
732
733         /* Does this device support video switching? */
734         if (video->cap._DOS) {
735                 video->flags.multihead = 1;
736                 status = 0;
737         }
738
739         /* Does this device support retrieving a video ROM? */
740         if (video->cap._ROM) {
741                 video->flags.rom = 1;
742                 status = 0;
743         }
744
745         /* Does this device support configuring which video device to POST? */
746         if (video->cap._GPD && video->cap._SPD && video->cap._VPO) {
747                 video->flags.post = 1;
748                 status = 0;
749         }
750
751         return status;
752 }
753
754 /* --------------------------------------------------------------------------
755                               FS Interface (/proc)
756    -------------------------------------------------------------------------- */
757
758 static struct proc_dir_entry *acpi_video_dir;
759
760 /* video devices */
761
762 static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset)
763 {
764         struct acpi_video_device *dev = seq->private;
765
766
767         if (!dev)
768                 goto end;
769
770         seq_printf(seq, "device_id:    0x%04x\n", (u32) dev->device_id);
771         seq_printf(seq, "type:         ");
772         if (dev->flags.crt)
773                 seq_printf(seq, "CRT\n");
774         else if (dev->flags.lcd)
775                 seq_printf(seq, "LCD\n");
776         else if (dev->flags.tvout)
777                 seq_printf(seq, "TVOUT\n");
778         else if (dev->flags.dvi)
779                 seq_printf(seq, "DVI\n");
780         else
781                 seq_printf(seq, "UNKNOWN\n");
782
783         seq_printf(seq, "known by bios: %s\n", dev->flags.bios ? "yes" : "no");
784
785       end:
786         return 0;
787 }
788
789 static int
790 acpi_video_device_info_open_fs(struct inode *inode, struct file *file)
791 {
792         return single_open(file, acpi_video_device_info_seq_show,
793                            PDE(inode)->data);
794 }
795
796 static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
797 {
798         int status;
799         struct acpi_video_device *dev = seq->private;
800         unsigned long state;
801
802
803         if (!dev)
804                 goto end;
805
806         status = acpi_video_device_get_state(dev, &state);
807         seq_printf(seq, "state:     ");
808         if (ACPI_SUCCESS(status))
809                 seq_printf(seq, "0x%02lx\n", state);
810         else
811                 seq_printf(seq, "<not supported>\n");
812
813         status = acpi_video_device_query(dev, &state);
814         seq_printf(seq, "query:     ");
815         if (ACPI_SUCCESS(status))
816                 seq_printf(seq, "0x%02lx\n", state);
817         else
818                 seq_printf(seq, "<not supported>\n");
819
820       end:
821         return 0;
822 }
823
824 static int
825 acpi_video_device_state_open_fs(struct inode *inode, struct file *file)
826 {
827         return single_open(file, acpi_video_device_state_seq_show,
828                            PDE(inode)->data);
829 }
830
831 static ssize_t
832 acpi_video_device_write_state(struct file *file,
833                               const char __user * buffer,
834                               size_t count, loff_t * data)
835 {
836         int status;
837         struct seq_file *m = file->private_data;
838         struct acpi_video_device *dev = m->private;
839         char str[12] = { 0 };
840         u32 state = 0;
841
842
843         if (!dev || count + 1 > sizeof str)
844                 return -EINVAL;
845
846         if (copy_from_user(str, buffer, count))
847                 return -EFAULT;
848
849         str[count] = 0;
850         state = simple_strtoul(str, NULL, 0);
851         state &= ((1ul << 31) | (1ul << 30) | (1ul << 0));
852
853         status = acpi_video_device_set_state(dev, state);
854
855         if (status)
856                 return -EFAULT;
857
858         return count;
859 }
860
861 static int
862 acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset)
863 {
864         struct acpi_video_device *dev = seq->private;
865         int i;
866
867
868         if (!dev || !dev->brightness) {
869                 seq_printf(seq, "<not supported>\n");
870                 return 0;
871         }
872
873         seq_printf(seq, "levels: ");
874         for (i = 0; i < dev->brightness->count; i++)
875                 seq_printf(seq, " %d", dev->brightness->levels[i]);
876         seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
877
878         return 0;
879 }
880
881 static int
882 acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file)
883 {
884         return single_open(file, acpi_video_device_brightness_seq_show,
885                            PDE(inode)->data);
886 }
887
888 static ssize_t
889 acpi_video_device_write_brightness(struct file *file,
890                                    const char __user * buffer,
891                                    size_t count, loff_t * data)
892 {
893         struct seq_file *m = file->private_data;
894         struct acpi_video_device *dev = m->private;
895         char str[4] = { 0 };
896         unsigned int level = 0;
897         int i;
898
899
900         if (!dev || !dev->brightness || count + 1 > sizeof str)
901                 return -EINVAL;
902
903         if (copy_from_user(str, buffer, count))
904                 return -EFAULT;
905
906         str[count] = 0;
907         level = simple_strtoul(str, NULL, 0);
908
909         if (level > 100)
910                 return -EFAULT;
911
912         /* validate through the list of available levels */
913         for (i = 0; i < dev->brightness->count; i++)
914                 if (level == dev->brightness->levels[i]) {
915                         if (ACPI_SUCCESS
916                             (acpi_video_device_lcd_set_level(dev, level)))
917                                 dev->brightness->curr = level;
918                         break;
919                 }
920
921         return count;
922 }
923
924 static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset)
925 {
926         struct acpi_video_device *dev = seq->private;
927         int status;
928         int i;
929         union acpi_object *edid = NULL;
930
931
932         if (!dev)
933                 goto out;
934
935         status = acpi_video_device_EDID(dev, &edid, 128);
936         if (ACPI_FAILURE(status)) {
937                 status = acpi_video_device_EDID(dev, &edid, 256);
938         }
939
940         if (ACPI_FAILURE(status)) {
941                 goto out;
942         }
943
944         if (edid && edid->type == ACPI_TYPE_BUFFER) {
945                 for (i = 0; i < edid->buffer.length; i++)
946                         seq_putc(seq, edid->buffer.pointer[i]);
947         }
948
949       out:
950         if (!edid)
951                 seq_printf(seq, "<not supported>\n");
952         else
953                 kfree(edid);
954
955         return 0;
956 }
957
958 static int
959 acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file)
960 {
961         return single_open(file, acpi_video_device_EDID_seq_show,
962                            PDE(inode)->data);
963 }
964
965 static int acpi_video_device_add_fs(struct acpi_device *device)
966 {
967         struct proc_dir_entry *entry = NULL;
968         struct acpi_video_device *vid_dev;
969
970
971         if (!device)
972                 return -ENODEV;
973
974         vid_dev = acpi_driver_data(device);
975         if (!vid_dev)
976                 return -ENODEV;
977
978         if (!acpi_device_dir(device)) {
979                 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
980                                                      vid_dev->video->dir);
981                 if (!acpi_device_dir(device))
982                         return -ENODEV;
983                 acpi_device_dir(device)->owner = THIS_MODULE;
984         }
985
986         /* 'info' [R] */
987         entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
988         if (!entry)
989                 return -ENODEV;
990         else {
991                 entry->proc_fops = &acpi_video_device_info_fops;
992                 entry->data = acpi_driver_data(device);
993                 entry->owner = THIS_MODULE;
994         }
995
996         /* 'state' [R/W] */
997         entry =
998             create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR,
999                               acpi_device_dir(device));
1000         if (!entry)
1001                 return -ENODEV;
1002         else {
1003                 acpi_video_device_state_fops.write = acpi_video_device_write_state;
1004                 entry->proc_fops = &acpi_video_device_state_fops;
1005                 entry->data = acpi_driver_data(device);
1006                 entry->owner = THIS_MODULE;
1007         }
1008
1009         /* 'brightness' [R/W] */
1010         entry =
1011             create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR,
1012                               acpi_device_dir(device));
1013         if (!entry)
1014                 return -ENODEV;
1015         else {
1016                 acpi_video_device_brightness_fops.write = acpi_video_device_write_brightness;
1017                 entry->proc_fops = &acpi_video_device_brightness_fops;
1018                 entry->data = acpi_driver_data(device);
1019                 entry->owner = THIS_MODULE;
1020         }
1021
1022         /* 'EDID' [R] */
1023         entry = create_proc_entry("EDID", S_IRUGO, acpi_device_dir(device));
1024         if (!entry)
1025                 return -ENODEV;
1026         else {
1027                 entry->proc_fops = &acpi_video_device_EDID_fops;
1028                 entry->data = acpi_driver_data(device);
1029                 entry->owner = THIS_MODULE;
1030         }
1031
1032         return 0;
1033 }
1034
1035 static int acpi_video_device_remove_fs(struct acpi_device *device)
1036 {
1037         struct acpi_video_device *vid_dev;
1038
1039         vid_dev = acpi_driver_data(device);
1040         if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
1041                 return -ENODEV;
1042
1043         if (acpi_device_dir(device)) {
1044                 remove_proc_entry("info", acpi_device_dir(device));
1045                 remove_proc_entry("state", acpi_device_dir(device));
1046                 remove_proc_entry("brightness", acpi_device_dir(device));
1047                 remove_proc_entry("EDID", acpi_device_dir(device));
1048                 remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
1049                 acpi_device_dir(device) = NULL;
1050         }
1051
1052         return 0;
1053 }
1054
1055 /* video bus */
1056 static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset)
1057 {
1058         struct acpi_video_bus *video = seq->private;
1059
1060
1061         if (!video)
1062                 goto end;
1063
1064         seq_printf(seq, "Switching heads:              %s\n",
1065                    video->flags.multihead ? "yes" : "no");
1066         seq_printf(seq, "Video ROM:                    %s\n",
1067                    video->flags.rom ? "yes" : "no");
1068         seq_printf(seq, "Device to be POSTed on boot:  %s\n",
1069                    video->flags.post ? "yes" : "no");
1070
1071       end:
1072         return 0;
1073 }
1074
1075 static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file)
1076 {
1077         return single_open(file, acpi_video_bus_info_seq_show,
1078                            PDE(inode)->data);
1079 }
1080
1081 static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset)
1082 {
1083         struct acpi_video_bus *video = seq->private;
1084
1085
1086         if (!video)
1087                 goto end;
1088
1089         printk(KERN_INFO PREFIX "Please implement %s\n", __FUNCTION__);
1090         seq_printf(seq, "<TODO>\n");
1091
1092       end:
1093         return 0;
1094 }
1095
1096 static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file)
1097 {
1098         return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data);
1099 }
1100
1101 static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
1102 {
1103         struct acpi_video_bus *video = seq->private;
1104         unsigned long options;
1105         int status;
1106
1107
1108         if (!video)
1109                 goto end;
1110
1111         status = acpi_video_bus_POST_options(video, &options);
1112         if (ACPI_SUCCESS(status)) {
1113                 if (!(options & 1)) {
1114                         printk(KERN_WARNING PREFIX
1115                                "The motherboard VGA device is not listed as a possible POST device.\n");
1116                         printk(KERN_WARNING PREFIX
1117                                "This indicates a BIOS bug. Please contact the manufacturer.\n");
1118                 }
1119                 printk("%lx\n", options);
1120                 seq_printf(seq, "can POST: <integrated video>");
1121                 if (options & 2)
1122                         seq_printf(seq, " <PCI video>");
1123                 if (options & 4)
1124                         seq_printf(seq, " <AGP video>");
1125                 seq_putc(seq, '\n');
1126         } else
1127                 seq_printf(seq, "<not supported>\n");
1128       end:
1129         return 0;
1130 }
1131
1132 static int
1133 acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file)
1134 {
1135         return single_open(file, acpi_video_bus_POST_info_seq_show,
1136                            PDE(inode)->data);
1137 }
1138
1139 static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
1140 {
1141         struct acpi_video_bus *video = seq->private;
1142         int status;
1143         unsigned long id;
1144
1145
1146         if (!video)
1147                 goto end;
1148
1149         status = acpi_video_bus_get_POST(video, &id);
1150         if (!ACPI_SUCCESS(status)) {
1151                 seq_printf(seq, "<not supported>\n");
1152                 goto end;
1153         }
1154         seq_printf(seq, "device POSTed is <%s>\n", device_decode[id & 3]);
1155
1156       end:
1157         return 0;
1158 }
1159
1160 static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset)
1161 {
1162         struct acpi_video_bus *video = seq->private;
1163
1164
1165         seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting);
1166
1167         return 0;
1168 }
1169
1170 static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file)
1171 {
1172         return single_open(file, acpi_video_bus_POST_seq_show,
1173                            PDE(inode)->data);
1174 }
1175
1176 static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file)
1177 {
1178         return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data);
1179 }
1180
1181 static ssize_t
1182 acpi_video_bus_write_POST(struct file *file,
1183                           const char __user * buffer,
1184                           size_t count, loff_t * data)
1185 {
1186         int status;
1187         struct seq_file *m = file->private_data;
1188         struct acpi_video_bus *video = m->private;
1189         char str[12] = { 0 };
1190         unsigned long opt, options;
1191
1192
1193         if (!video || count + 1 > sizeof str)
1194                 return -EINVAL;
1195
1196         status = acpi_video_bus_POST_options(video, &options);
1197         if (!ACPI_SUCCESS(status))
1198                 return -EINVAL;
1199
1200         if (copy_from_user(str, buffer, count))
1201                 return -EFAULT;
1202
1203         str[count] = 0;
1204         opt = strtoul(str, NULL, 0);
1205         if (opt > 3)
1206                 return -EFAULT;
1207
1208         /* just in case an OEM 'forgot' the motherboard... */
1209         options |= 1;
1210
1211         if (options & (1ul << opt)) {
1212                 status = acpi_video_bus_set_POST(video, opt);
1213                 if (!ACPI_SUCCESS(status))
1214                         return -EFAULT;
1215
1216         }
1217
1218         return count;
1219 }
1220
1221 static ssize_t
1222 acpi_video_bus_write_DOS(struct file *file,
1223                          const char __user * buffer,
1224                          size_t count, loff_t * data)
1225 {
1226         int status;
1227         struct seq_file *m = file->private_data;
1228         struct acpi_video_bus *video = m->private;
1229         char str[12] = { 0 };
1230         unsigned long opt;
1231
1232
1233         if (!video || count + 1 > sizeof str)
1234                 return -EINVAL;
1235
1236         if (copy_from_user(str, buffer, count))
1237                 return -EFAULT;
1238
1239         str[count] = 0;
1240         opt = strtoul(str, NULL, 0);
1241         if (opt > 7)
1242                 return -EFAULT;
1243
1244         status = acpi_video_bus_DOS(video, opt & 0x3, (opt & 0x4) >> 2);
1245
1246         if (!ACPI_SUCCESS(status))
1247                 return -EFAULT;
1248
1249         return count;
1250 }
1251
1252 static int acpi_video_bus_add_fs(struct acpi_device *device)
1253 {
1254         struct proc_dir_entry *entry = NULL;
1255         struct acpi_video_bus *video;
1256
1257
1258         video = acpi_driver_data(device);
1259
1260         if (!acpi_device_dir(device)) {
1261                 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1262                                                      acpi_video_dir);
1263                 if (!acpi_device_dir(device))
1264                         return -ENODEV;
1265                 video->dir = acpi_device_dir(device);
1266                 acpi_device_dir(device)->owner = THIS_MODULE;
1267         }
1268
1269         /* 'info' [R] */
1270         entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
1271         if (!entry)
1272                 return -ENODEV;
1273         else {
1274                 entry->proc_fops = &acpi_video_bus_info_fops;
1275                 entry->data = acpi_driver_data(device);
1276                 entry->owner = THIS_MODULE;
1277         }
1278
1279         /* 'ROM' [R] */
1280         entry = create_proc_entry("ROM", S_IRUGO, acpi_device_dir(device));
1281         if (!entry)
1282                 return -ENODEV;
1283         else {
1284                 entry->proc_fops = &acpi_video_bus_ROM_fops;
1285                 entry->data = acpi_driver_data(device);
1286                 entry->owner = THIS_MODULE;
1287         }
1288
1289         /* 'POST_info' [R] */
1290         entry =
1291             create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device));
1292         if (!entry)
1293                 return -ENODEV;
1294         else {
1295                 entry->proc_fops = &acpi_video_bus_POST_info_fops;
1296                 entry->data = acpi_driver_data(device);
1297                 entry->owner = THIS_MODULE;
1298         }
1299
1300         /* 'POST' [R/W] */
1301         entry =
1302             create_proc_entry("POST", S_IFREG | S_IRUGO | S_IRUSR,
1303                               acpi_device_dir(device));
1304         if (!entry)
1305                 return -ENODEV;
1306         else {
1307                 acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
1308                 entry->proc_fops = &acpi_video_bus_POST_fops;
1309                 entry->data = acpi_driver_data(device);
1310                 entry->owner = THIS_MODULE;
1311         }
1312
1313         /* 'DOS' [R/W] */
1314         entry =
1315             create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IRUSR,
1316                               acpi_device_dir(device));
1317         if (!entry)
1318                 return -ENODEV;
1319         else {
1320                 acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
1321                 entry->proc_fops = &acpi_video_bus_DOS_fops;
1322                 entry->data = acpi_driver_data(device);
1323                 entry->owner = THIS_MODULE;
1324         }
1325
1326         return 0;
1327 }
1328
1329 static int acpi_video_bus_remove_fs(struct acpi_device *device)
1330 {
1331         struct acpi_video_bus *video;
1332
1333
1334         video = acpi_driver_data(device);
1335
1336         if (acpi_device_dir(device)) {
1337                 remove_proc_entry("info", acpi_device_dir(device));
1338                 remove_proc_entry("ROM", acpi_device_dir(device));
1339                 remove_proc_entry("POST_info", acpi_device_dir(device));
1340                 remove_proc_entry("POST", acpi_device_dir(device));
1341                 remove_proc_entry("DOS", acpi_device_dir(device));
1342                 remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
1343                 acpi_device_dir(device) = NULL;
1344         }
1345
1346         return 0;
1347 }
1348
1349 /* --------------------------------------------------------------------------
1350                                  Driver Interface
1351    -------------------------------------------------------------------------- */
1352
1353 /* device interface */
1354 static struct acpi_video_device_attrib*
1355 acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id)
1356 {
1357         int count;
1358
1359         for(count = 0; count < video->attached_count; count++)
1360                 if((video->attached_array[count].value.int_val & 0xffff) == device_id)
1361                         return &(video->attached_array[count].value.attrib);
1362         return NULL;
1363 }
1364
1365 static int
1366 acpi_video_bus_get_one_device(struct acpi_device *device,
1367                               struct acpi_video_bus *video)
1368 {
1369         unsigned long device_id;
1370         int status;
1371         struct acpi_video_device *data;
1372         struct acpi_video_device_attrib* attribute;
1373
1374         if (!device || !video)
1375                 return -EINVAL;
1376
1377         status =
1378             acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
1379         if (ACPI_SUCCESS(status)) {
1380
1381                 data = kzalloc(sizeof(struct acpi_video_device), GFP_KERNEL);
1382                 if (!data)
1383                         return -ENOMEM;
1384
1385                 strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
1386                 strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
1387                 acpi_driver_data(device) = data;
1388
1389                 data->device_id = device_id;
1390                 data->video = video;
1391                 data->dev = device;
1392
1393                 attribute = acpi_video_get_device_attr(video, device_id);
1394
1395                 if((attribute != NULL) && attribute->device_id_scheme) {
1396                         switch (attribute->display_type) {
1397                         case ACPI_VIDEO_DISPLAY_CRT:
1398                                 data->flags.crt = 1;
1399                                 break;
1400                         case ACPI_VIDEO_DISPLAY_TV:
1401                                 data->flags.tvout = 1;
1402                                 break;
1403                         case ACPI_VIDEO_DISPLAY_DVI:
1404                                 data->flags.dvi = 1;
1405                                 break;
1406                         case ACPI_VIDEO_DISPLAY_LCD:
1407                                 data->flags.lcd = 1;
1408                                 break;
1409                         default:
1410                                 data->flags.unknown = 1;
1411                                 break;
1412                         }
1413                         if(attribute->bios_can_detect)
1414                                 data->flags.bios = 1;
1415                 } else
1416                         data->flags.unknown = 1;
1417
1418                 acpi_video_device_bind(video, data);
1419                 acpi_video_device_find_cap(data);
1420
1421                 status = acpi_install_notify_handler(device->handle,
1422                                                      ACPI_DEVICE_NOTIFY,
1423                                                      acpi_video_device_notify,
1424                                                      data);
1425                 if (ACPI_FAILURE(status)) {
1426                         ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1427                                           "Error installing notify handler\n"));
1428                         if(data->brightness)
1429                                 kfree(data->brightness->levels);
1430                         kfree(data->brightness);
1431                         kfree(data);
1432                         return -ENODEV;
1433                 }
1434
1435                 down(&video->sem);
1436                 list_add_tail(&data->entry, &video->video_device_list);
1437                 up(&video->sem);
1438
1439                 acpi_video_device_add_fs(device);
1440
1441                 return 0;
1442         }
1443
1444         return -ENOENT;
1445 }
1446
1447 /*
1448  *  Arg:
1449  *      video   : video bus device 
1450  *
1451  *  Return:
1452  *      none
1453  *  
1454  *  Enumerate the video device list of the video bus, 
1455  *  bind the ids with the corresponding video devices
1456  *  under the video bus.
1457  */
1458
1459 static void acpi_video_device_rebind(struct acpi_video_bus *video)
1460 {
1461         struct list_head *node, *next;
1462         list_for_each_safe(node, next, &video->video_device_list) {
1463                 struct acpi_video_device *dev =
1464                     container_of(node, struct acpi_video_device, entry);
1465                 acpi_video_device_bind(video, dev);
1466         }
1467 }
1468
1469 /*
1470  *  Arg:
1471  *      video   : video bus device 
1472  *      device  : video output device under the video 
1473  *              bus
1474  *
1475  *  Return:
1476  *      none
1477  *  
1478  *  Bind the ids with the corresponding video devices
1479  *  under the video bus.
1480  */
1481
1482 static void
1483 acpi_video_device_bind(struct acpi_video_bus *video,
1484                        struct acpi_video_device *device)
1485 {
1486         int i;
1487
1488 #define IDS_VAL(i) video->attached_array[i].value.int_val
1489 #define IDS_BIND(i) video->attached_array[i].bind_info
1490
1491         for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID &&
1492              i < video->attached_count; i++) {
1493                 if (device->device_id == (IDS_VAL(i) & 0xffff)) {
1494                         IDS_BIND(i) = device;
1495                         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i));
1496                 }
1497         }
1498 #undef IDS_VAL
1499 #undef IDS_BIND
1500 }
1501
1502 /*
1503  *  Arg:
1504  *      video   : video bus device 
1505  *
1506  *  Return:
1507  *      < 0     : error
1508  *  
1509  *  Call _DOD to enumerate all devices attached to display adapter
1510  *
1511  */
1512
1513 static int acpi_video_device_enumerate(struct acpi_video_bus *video)
1514 {
1515         int status;
1516         int count;
1517         int i;
1518         struct acpi_video_enumerated_device *active_device_list;
1519         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1520         union acpi_object *dod = NULL;
1521         union acpi_object *obj;
1522
1523         status = acpi_evaluate_object(video->device->handle, "_DOD", NULL, &buffer);
1524         if (!ACPI_SUCCESS(status)) {
1525                 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _DOD"));
1526                 return status;
1527         }
1528
1529         dod = buffer.pointer;
1530         if (!dod || (dod->type != ACPI_TYPE_PACKAGE)) {
1531                 ACPI_EXCEPTION((AE_INFO, status, "Invalid _DOD data"));
1532                 status = -EFAULT;
1533                 goto out;
1534         }
1535
1536         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n",
1537                           dod->package.count));
1538
1539         active_device_list = kmalloc((1 +
1540                                       dod->package.count) *
1541                                      sizeof(struct
1542                                             acpi_video_enumerated_device),
1543                                      GFP_KERNEL);
1544
1545         if (!active_device_list) {
1546                 status = -ENOMEM;
1547                 goto out;
1548         }
1549
1550         count = 0;
1551         for (i = 0; i < dod->package.count; i++) {
1552                 obj = &dod->package.elements[i];
1553
1554                 if (obj->type != ACPI_TYPE_INTEGER) {
1555                         printk(KERN_ERR PREFIX "Invalid _DOD data\n");
1556                         active_device_list[i].value.int_val =
1557                             ACPI_VIDEO_HEAD_INVALID;
1558                 }
1559                 active_device_list[i].value.int_val = obj->integer.value;
1560                 active_device_list[i].bind_info = NULL;
1561                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i,
1562                                   (int)obj->integer.value));
1563                 count++;
1564         }
1565         active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END;
1566
1567         kfree(video->attached_array);
1568
1569         video->attached_array = active_device_list;
1570         video->attached_count = count;
1571       out:
1572         kfree(buffer.pointer);
1573         return status;
1574 }
1575
1576 /*
1577  *  Arg:
1578  *      video   : video bus device 
1579  *      event   : notify event
1580  *
1581  *  Return:
1582  *      < 0     : error
1583  *  
1584  *      1. Find out the current active output device.
1585  *      2. Identify the next output device to switch to.
1586  *      3. call _DSS to do actual switch.
1587  */
1588
1589 static int acpi_video_switch_output(struct acpi_video_bus *video, int event)
1590 {
1591         struct list_head *node, *next;
1592         struct acpi_video_device *dev = NULL;
1593         struct acpi_video_device *dev_next = NULL;
1594         struct acpi_video_device *dev_prev = NULL;
1595         unsigned long state;
1596         int status = 0;
1597
1598
1599         list_for_each_safe(node, next, &video->video_device_list) {
1600                 dev = container_of(node, struct acpi_video_device, entry);
1601                 status = acpi_video_device_get_state(dev, &state);
1602                 if (state & 0x2) {
1603                         dev_next =
1604                             container_of(node->next, struct acpi_video_device,
1605                                          entry);
1606                         dev_prev =
1607                             container_of(node->prev, struct acpi_video_device,
1608                                          entry);
1609                         goto out;
1610                 }
1611         }
1612         dev_next = container_of(node->next, struct acpi_video_device, entry);
1613         dev_prev = container_of(node->prev, struct acpi_video_device, entry);
1614       out:
1615         switch (event) {
1616         case ACPI_VIDEO_NOTIFY_CYCLE:
1617         case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
1618                 acpi_video_device_set_state(dev, 0);
1619                 acpi_video_device_set_state(dev_next, 0x80000001);
1620                 break;
1621         case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:
1622                 acpi_video_device_set_state(dev, 0);
1623                 acpi_video_device_set_state(dev_prev, 0x80000001);
1624         default:
1625                 break;
1626         }
1627
1628         return status;
1629 }
1630
1631 static int
1632 acpi_video_get_next_level(struct acpi_video_device *device,
1633                           u32 level_current, u32 event)
1634 {
1635         int min, max, min_above, max_below, i, l;
1636         max = max_below = 0;
1637         min = min_above = 255;
1638         for (i = 0; i < device->brightness->count; i++) {
1639                 l = device->brightness->levels[i];
1640                 if (l < min)
1641                         min = l;
1642                 if (l > max)
1643                         max = l;
1644                 if (l < min_above && l > level_current)
1645                         min_above = l;
1646                 if (l > max_below && l < level_current)
1647                         max_below = l;
1648         }
1649
1650         switch (event) {
1651         case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS:
1652                 return (level_current < max) ? min_above : min;
1653         case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS:
1654                 return (level_current < max) ? min_above : max;
1655         case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS:
1656                 return (level_current > min) ? max_below : min;
1657         case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS:
1658         case ACPI_VIDEO_NOTIFY_DISPLAY_OFF:
1659                 return 0;
1660         default:
1661                 return level_current;
1662         }
1663 }
1664
1665 static void
1666 acpi_video_switch_brightness(struct acpi_video_device *device, int event)
1667 {
1668         unsigned long level_current, level_next;
1669         acpi_video_device_lcd_get_level_current(device, &level_current);
1670         level_next = acpi_video_get_next_level(device, level_current, event);
1671         acpi_video_device_lcd_set_level(device, level_next);
1672 }
1673
1674 static int
1675 acpi_video_bus_get_devices(struct acpi_video_bus *video,
1676                            struct acpi_device *device)
1677 {
1678         int status = 0;
1679         struct list_head *node, *next;
1680
1681
1682         acpi_video_device_enumerate(video);
1683
1684         list_for_each_safe(node, next, &device->children) {
1685                 struct acpi_device *dev =
1686                     list_entry(node, struct acpi_device, node);
1687
1688                 if (!dev)
1689                         continue;
1690
1691                 status = acpi_video_bus_get_one_device(dev, video);
1692                 if (ACPI_FAILURE(status)) {
1693                         ACPI_EXCEPTION((AE_INFO, status, "Cant attach device"));
1694                         continue;
1695                 }
1696
1697         }
1698         return status;
1699 }
1700
1701 static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
1702 {
1703         acpi_status status;
1704         struct acpi_video_bus *video;
1705
1706
1707         if (!device || !device->video)
1708                 return -ENOENT;
1709
1710         video = device->video;
1711
1712         down(&video->sem);
1713         list_del(&device->entry);
1714         up(&video->sem);
1715         acpi_video_device_remove_fs(device->dev);
1716
1717         status = acpi_remove_notify_handler(device->dev->handle,
1718                                             ACPI_DEVICE_NOTIFY,
1719                                             acpi_video_device_notify);
1720         backlight_device_unregister(device->backlight);
1721         video_output_unregister(device->output_dev);
1722         return 0;
1723 }
1724
1725 static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
1726 {
1727         int status;
1728         struct list_head *node, *next;
1729
1730
1731         list_for_each_safe(node, next, &video->video_device_list) {
1732                 struct acpi_video_device *data =
1733                     list_entry(node, struct acpi_video_device, entry);
1734                 if (!data)
1735                         continue;
1736
1737                 status = acpi_video_bus_put_one_device(data);
1738                 if (ACPI_FAILURE(status))
1739                         printk(KERN_WARNING PREFIX
1740                                "hhuuhhuu bug in acpi video driver.\n");
1741
1742                 if (data->brightness)
1743                         kfree(data->brightness->levels);
1744                 kfree(data->brightness);
1745                 kfree(data);
1746         }
1747
1748         return 0;
1749 }
1750
1751 /* acpi_video interface */
1752
1753 static int acpi_video_bus_start_devices(struct acpi_video_bus *video)
1754 {
1755         return acpi_video_bus_DOS(video, 1, 0);
1756 }
1757
1758 static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
1759 {
1760         return acpi_video_bus_DOS(video, 0, 1);
1761 }
1762
1763 static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
1764 {
1765         struct acpi_video_bus *video = data;
1766         struct acpi_device *device = NULL;
1767
1768         printk("video bus notify\n");
1769
1770         if (!video)
1771                 return;
1772
1773         device = video->device;
1774
1775         switch (event) {
1776         case ACPI_VIDEO_NOTIFY_SWITCH:  /* User requested a switch,
1777                                          * most likely via hotkey. */
1778                 acpi_bus_generate_event(device, event, 0);
1779                 break;
1780
1781         case ACPI_VIDEO_NOTIFY_PROBE:   /* User plugged in or removed a video
1782                                          * connector. */
1783                 acpi_video_device_enumerate(video);
1784                 acpi_video_device_rebind(video);
1785                 acpi_video_switch_output(video, event);
1786                 acpi_bus_generate_event(device, event, 0);
1787                 break;
1788
1789         case ACPI_VIDEO_NOTIFY_CYCLE:   /* Cycle Display output hotkey pressed. */
1790         case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:     /* Next Display output hotkey pressed. */
1791         case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:     /* previous Display output hotkey pressed. */
1792                 acpi_video_switch_output(video, event);
1793                 acpi_bus_generate_event(device, event, 0);
1794                 break;
1795
1796         default:
1797                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1798                                   "Unsupported event [0x%x]\n", event));
1799                 break;
1800         }
1801
1802         return;
1803 }
1804
1805 static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
1806 {
1807         struct acpi_video_device *video_device = data;
1808         struct acpi_device *device = NULL;
1809
1810         if (!video_device)
1811                 return;
1812
1813         device = video_device->dev;
1814
1815         switch (event) {
1816         case ACPI_VIDEO_NOTIFY_SWITCH:  /* change in status (cycle output device) */
1817         case ACPI_VIDEO_NOTIFY_PROBE:   /* change in status (output device status) */
1818                 acpi_bus_generate_event(device, event, 0);
1819                 break;
1820         case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS:        /* Cycle brightness */
1821         case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS:  /* Increase brightness */
1822         case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS:  /* Decrease brightness */
1823         case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */
1824         case ACPI_VIDEO_NOTIFY_DISPLAY_OFF:     /* display device off */
1825                 acpi_video_switch_brightness(video_device, event);
1826                 acpi_bus_generate_event(device, event, 0);
1827                 break;
1828         default:
1829                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1830                                   "Unsupported event [0x%x]\n", event));
1831                 break;
1832         }
1833         return;
1834 }
1835
1836 static int acpi_video_bus_add(struct acpi_device *device)
1837 {
1838         int result = 0;
1839         acpi_status status = 0;
1840         struct acpi_video_bus *video = NULL;
1841
1842
1843         if (!device)
1844                 return -EINVAL;
1845
1846         video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL);
1847         if (!video)
1848                 return -ENOMEM;
1849
1850         video->device = device;
1851         strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
1852         strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
1853         acpi_driver_data(device) = video;
1854
1855         acpi_video_bus_find_cap(video);
1856         result = acpi_video_bus_check(video);
1857         if (result)
1858                 goto end;
1859
1860         result = acpi_video_bus_add_fs(device);
1861         if (result)
1862                 goto end;
1863
1864         init_MUTEX(&video->sem);
1865         INIT_LIST_HEAD(&video->video_device_list);
1866
1867         acpi_video_bus_get_devices(video, device);
1868         acpi_video_bus_start_devices(video);
1869
1870         status = acpi_install_notify_handler(device->handle,
1871                                              ACPI_DEVICE_NOTIFY,
1872                                              acpi_video_bus_notify, video);
1873         if (ACPI_FAILURE(status)) {
1874                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1875                                   "Error installing notify handler\n"));
1876                 acpi_video_bus_stop_devices(video);
1877                 acpi_video_bus_put_devices(video);
1878                 kfree(video->attached_array);
1879                 acpi_video_bus_remove_fs(device);
1880                 result = -ENODEV;
1881                 goto end;
1882         }
1883
1884         printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s  rom: %s  post: %s)\n",
1885                ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
1886                video->flags.multihead ? "yes" : "no",
1887                video->flags.rom ? "yes" : "no",
1888                video->flags.post ? "yes" : "no");
1889
1890       end:
1891         if (result)
1892                 kfree(video);
1893
1894         return result;
1895 }
1896
1897 static int acpi_video_bus_remove(struct acpi_device *device, int type)
1898 {
1899         acpi_status status = 0;
1900         struct acpi_video_bus *video = NULL;
1901
1902
1903         if (!device || !acpi_driver_data(device))
1904                 return -EINVAL;
1905
1906         video = acpi_driver_data(device);
1907
1908         acpi_video_bus_stop_devices(video);
1909
1910         status = acpi_remove_notify_handler(video->device->handle,
1911                                             ACPI_DEVICE_NOTIFY,
1912                                             acpi_video_bus_notify);
1913
1914         acpi_video_bus_put_devices(video);
1915         acpi_video_bus_remove_fs(device);
1916
1917         kfree(video->attached_array);
1918         kfree(video);
1919
1920         return 0;
1921 }
1922
1923 static int __init acpi_video_init(void)
1924 {
1925         int result = 0;
1926
1927
1928         /*
1929            acpi_dbg_level = 0xFFFFFFFF;
1930            acpi_dbg_layer = 0x08000000;
1931          */
1932
1933         acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
1934         if (!acpi_video_dir)
1935                 return -ENODEV;
1936         acpi_video_dir->owner = THIS_MODULE;
1937
1938         result = acpi_bus_register_driver(&acpi_video_bus);
1939         if (result < 0) {
1940                 remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
1941                 return -ENODEV;
1942         }
1943
1944         return 0;
1945 }
1946
1947 static void __exit acpi_video_exit(void)
1948 {
1949
1950         acpi_bus_unregister_driver(&acpi_video_bus);
1951
1952         remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
1953
1954         return;
1955 }
1956
1957 module_init(acpi_video_init);
1958 module_exit(acpi_video_exit);