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