2  *  video.c - ACPI Video Driver ($Revision:$)
 
   4  *  Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
 
   5  *  Copyright (C) 2004 Bruno Ducrot <ducrot@poupinou.org>
 
   7  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   9  *  This program is free software; you can redistribute it and/or modify
 
  10  *  it under the terms of the GNU General Public License as published by
 
  11  *  the Free Software Foundation; either version 2 of the License, or (at
 
  12  *  your option) any later version.
 
  14  *  This program is distributed in the hope that it will be useful, but
 
  15  *  WITHOUT ANY WARRANTY; without even the implied warranty of
 
  16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
  17  *  General Public License for more details.
 
  19  *  You should have received a copy of the GNU General Public License along
 
  20  *  with this program; if not, write to the Free Software Foundation, Inc.,
 
  21  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 
  23  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
  26 #include <linux/kernel.h>
 
  27 #include <linux/module.h>
 
  28 #include <linux/init.h>
 
  29 #include <linux/types.h>
 
  30 #include <linux/list.h>
 
  31 #include <linux/proc_fs.h>
 
  32 #include <linux/seq_file.h>
 
  34 #include <asm/uaccess.h>
 
  36 #include <acpi/acpi_bus.h>
 
  37 #include <acpi/acpi_drivers.h>
 
  39 #define ACPI_VIDEO_COMPONENT            0x08000000
 
  40 #define ACPI_VIDEO_CLASS                "video"
 
  41 #define ACPI_VIDEO_DRIVER_NAME          "ACPI Video Driver"
 
  42 #define ACPI_VIDEO_BUS_NAME             "Video Bus"
 
  43 #define ACPI_VIDEO_DEVICE_NAME          "Video Device"
 
  44 #define ACPI_VIDEO_NOTIFY_SWITCH        0x80
 
  45 #define ACPI_VIDEO_NOTIFY_PROBE         0x81
 
  46 #define ACPI_VIDEO_NOTIFY_CYCLE         0x82
 
  47 #define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT   0x83
 
  48 #define ACPI_VIDEO_NOTIFY_PREV_OUTPUT   0x84
 
  50 #define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS      0x82
 
  51 #define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS        0x83
 
  52 #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS        0x84
 
  53 #define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS       0x85
 
  54 #define ACPI_VIDEO_NOTIFY_DISPLAY_OFF           0x86
 
  56 #define ACPI_VIDEO_HEAD_INVALID         (~0u - 1)
 
  57 #define ACPI_VIDEO_HEAD_END             (~0u)
 
  59 #define _COMPONENT              ACPI_VIDEO_COMPONENT
 
  60 ACPI_MODULE_NAME("acpi_video")
 
  62     MODULE_AUTHOR("Bruno Ducrot");
 
  63 MODULE_DESCRIPTION(ACPI_VIDEO_DRIVER_NAME);
 
  64 MODULE_LICENSE("GPL");
 
  66 static int acpi_video_bus_add(struct acpi_device *device);
 
  67 static int acpi_video_bus_remove(struct acpi_device *device, int type);
 
  68 static int acpi_video_bus_match(struct acpi_device *device,
 
  69                                 struct acpi_driver *driver);
 
  71 static struct acpi_driver acpi_video_bus = {
 
  72         .name = ACPI_VIDEO_DRIVER_NAME,
 
  73         .class = ACPI_VIDEO_CLASS,
 
  75                 .add = acpi_video_bus_add,
 
  76                 .remove = acpi_video_bus_remove,
 
  77                 .match = acpi_video_bus_match,
 
  81 struct acpi_video_bus_flags {
 
  82         u8 multihead:1;         /* can switch video heads */
 
  83         u8 rom:1;               /* can retrieve a video rom */
 
  84         u8 post:1;              /* can configure the head to */
 
  88 struct acpi_video_bus_cap {
 
  89         u8 _DOS:1;              /*Enable/Disable output switching */
 
  90         u8 _DOD:1;              /*Enumerate all devices attached to display adapter */
 
  91         u8 _ROM:1;              /*Get ROM Data */
 
  92         u8 _GPD:1;              /*Get POST Device */
 
  93         u8 _SPD:1;              /*Set POST Device */
 
  94         u8 _VPO:1;              /*Video POST Options */
 
  98 struct acpi_video_device_attrib {
 
  99         u32 display_index:4;    /* A zero-based instance of the Display */
 
 100         u32 display_port_attachment:4;  /*This field differenates displays type */
 
 101         u32 display_type:4;     /*Describe the specific type in use */
 
 102         u32 vendor_specific:4;  /*Chipset Vendor Specifi */
 
 103         u32 bios_can_detect:1;  /*BIOS can detect the device */
 
 104         u32 depend_on_vga:1;    /*Non-VGA output device whose power is related to 
 
 106         u32 pipe_id:3;          /*For VGA multiple-head devices. */
 
 107         u32 reserved:10;        /*Must be 0 */
 
 108         u32 device_id_scheme:1; /*Device ID Scheme */
 
 111 struct acpi_video_enumerated_device {
 
 114                 struct acpi_video_device_attrib attrib;
 
 116         struct acpi_video_device *bind_info;
 
 119 struct acpi_video_bus {
 
 122         struct acpi_video_enumerated_device *attached_array;
 
 124         struct acpi_video_bus_cap cap;
 
 125         struct acpi_video_bus_flags flags;
 
 126         struct semaphore sem;
 
 127         struct list_head video_device_list;
 
 128         struct proc_dir_entry *dir;
 
 131 struct acpi_video_device_flags {
 
 140 struct acpi_video_device_cap {
 
 141         u8 _ADR:1;              /*Return the unique ID */
 
 142         u8 _BCL:1;              /*Query list of brightness control levels supported */
 
 143         u8 _BCM:1;              /*Set the brightness level */
 
 144         u8 _DDC:1;              /*Return the EDID for this device */
 
 145         u8 _DCS:1;              /*Return status of output device */
 
 146         u8 _DGS:1;              /*Query graphics state */
 
 147         u8 _DSS:1;              /*Device state set */
 
 151 struct acpi_video_device_brightness {
 
 157 struct acpi_video_device {
 
 159         unsigned long device_id;
 
 160         struct acpi_video_device_flags flags;
 
 161         struct acpi_video_device_cap cap;
 
 162         struct list_head entry;
 
 163         struct acpi_video_bus *video;
 
 164         struct acpi_device *dev;
 
 165         struct acpi_video_device_brightness *brightness;
 
 169 static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
 
 170 static struct file_operations acpi_video_bus_info_fops = {
 
 171         .open = acpi_video_bus_info_open_fs,
 
 174         .release = single_release,
 
 177 static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
 
 178 static struct file_operations acpi_video_bus_ROM_fops = {
 
 179         .open = acpi_video_bus_ROM_open_fs,
 
 182         .release = single_release,
 
 185 static int acpi_video_bus_POST_info_open_fs(struct inode *inode,
 
 187 static struct file_operations acpi_video_bus_POST_info_fops = {
 
 188         .open = acpi_video_bus_POST_info_open_fs,
 
 191         .release = single_release,
 
 194 static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
 
 195 static struct file_operations acpi_video_bus_POST_fops = {
 
 196         .open = acpi_video_bus_POST_open_fs,
 
 199         .release = single_release,
 
 202 static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
 
 203 static struct file_operations acpi_video_bus_DOS_fops = {
 
 204         .open = acpi_video_bus_DOS_open_fs,
 
 207         .release = single_release,
 
 211 static int acpi_video_device_info_open_fs(struct inode *inode,
 
 213 static struct file_operations acpi_video_device_info_fops = {
 
 214         .open = acpi_video_device_info_open_fs,
 
 217         .release = single_release,
 
 220 static int acpi_video_device_state_open_fs(struct inode *inode,
 
 222 static struct file_operations acpi_video_device_state_fops = {
 
 223         .open = acpi_video_device_state_open_fs,
 
 226         .release = single_release,
 
 229 static int acpi_video_device_brightness_open_fs(struct inode *inode,
 
 231 static struct file_operations acpi_video_device_brightness_fops = {
 
 232         .open = acpi_video_device_brightness_open_fs,
 
 235         .release = single_release,
 
 238 static int acpi_video_device_EDID_open_fs(struct inode *inode,
 
 240 static struct file_operations acpi_video_device_EDID_fops = {
 
 241         .open = acpi_video_device_EDID_open_fs,
 
 244         .release = single_release,
 
 247 static char device_decode[][30] = {
 
 248         "motherboard VGA device",
 
 254 static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data);
 
 255 static void acpi_video_device_rebind(struct acpi_video_bus *video);
 
 256 static void acpi_video_device_bind(struct acpi_video_bus *video,
 
 257                                    struct acpi_video_device *device);
 
 258 static int acpi_video_device_enumerate(struct acpi_video_bus *video);
 
 259 static int acpi_video_switch_output(struct acpi_video_bus *video, int event);
 
 260 static int acpi_video_get_next_level(struct acpi_video_device *device,
 
 261                                      u32 level_current, u32 event);
 
 262 static void acpi_video_switch_brightness(struct acpi_video_device *device,
 
 265 /* --------------------------------------------------------------------------
 
 267    -------------------------------------------------------------------------- */
 
 272 acpi_video_device_query(struct acpi_video_device *device, unsigned long *state)
 
 275         ACPI_FUNCTION_TRACE("acpi_video_device_query");
 
 276         status = acpi_evaluate_integer(device->handle, "_DGS", NULL, state);
 
 278         return_VALUE(status);
 
 282 acpi_video_device_get_state(struct acpi_video_device *device,
 
 283                             unsigned long *state)
 
 287         ACPI_FUNCTION_TRACE("acpi_video_device_get_state");
 
 289         status = acpi_evaluate_integer(device->handle, "_DCS", NULL, state);
 
 291         return_VALUE(status);
 
 295 acpi_video_device_set_state(struct acpi_video_device *device, int state)
 
 298         union acpi_object arg0 = { ACPI_TYPE_INTEGER };
 
 299         struct acpi_object_list args = { 1, &arg0 };
 
 302         ACPI_FUNCTION_TRACE("acpi_video_device_set_state");
 
 304         arg0.integer.value = state;
 
 305         status = acpi_evaluate_integer(device->handle, "_DSS", &args, &ret);
 
 307         return_VALUE(status);
 
 311 acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
 
 312                                    union acpi_object **levels)
 
 315         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 
 316         union acpi_object *obj;
 
 318         ACPI_FUNCTION_TRACE("acpi_video_device_lcd_query_levels");
 
 322         status = acpi_evaluate_object(device->handle, "_BCL", NULL, &buffer);
 
 323         if (!ACPI_SUCCESS(status))
 
 324                 return_VALUE(status);
 
 325         obj = (union acpi_object *)buffer.pointer;
 
 326         if (!obj && (obj->type != ACPI_TYPE_PACKAGE)) {
 
 327                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _BCL data\n"));
 
 337         kfree(buffer.pointer);
 
 339         return_VALUE(status);
 
 343 acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
 
 346         union acpi_object arg0 = { ACPI_TYPE_INTEGER };
 
 347         struct acpi_object_list args = { 1, &arg0 };
 
 349         ACPI_FUNCTION_TRACE("acpi_video_device_lcd_set_level");
 
 351         arg0.integer.value = level;
 
 352         status = acpi_evaluate_object(device->handle, "_BCM", &args, NULL);
 
 354         printk(KERN_DEBUG "set_level status: %x\n", status);
 
 355         return_VALUE(status);
 
 359 acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
 
 360                                         unsigned long *level)
 
 363         ACPI_FUNCTION_TRACE("acpi_video_device_lcd_get_level_current");
 
 365         status = acpi_evaluate_integer(device->handle, "_BQC", NULL, level);
 
 367         return_VALUE(status);
 
 371 acpi_video_device_EDID(struct acpi_video_device *device,
 
 372                        union acpi_object **edid, ssize_t length)
 
 375         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 
 376         union acpi_object *obj;
 
 377         union acpi_object arg0 = { ACPI_TYPE_INTEGER };
 
 378         struct acpi_object_list args = { 1, &arg0 };
 
 380         ACPI_FUNCTION_TRACE("acpi_video_device_get_EDID");
 
 385                 return_VALUE(-ENODEV);
 
 387                 arg0.integer.value = 1;
 
 388         else if (length == 256)
 
 389                 arg0.integer.value = 2;
 
 391                 return_VALUE(-EINVAL);
 
 393         status = acpi_evaluate_object(device->handle, "_DDC", &args, &buffer);
 
 394         if (ACPI_FAILURE(status))
 
 395                 return_VALUE(-ENODEV);
 
 397         obj = (union acpi_object *)buffer.pointer;
 
 399         if (obj && obj->type == ACPI_TYPE_BUFFER)
 
 402                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _DDC data\n"));
 
 407         return_VALUE(status);
 
 413 acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
 
 417         union acpi_object arg0 = { ACPI_TYPE_INTEGER };
 
 418         struct acpi_object_list args = { 1, &arg0 };
 
 420         ACPI_FUNCTION_TRACE("acpi_video_bus_set_POST");
 
 422         arg0.integer.value = option;
 
 424         status = acpi_evaluate_integer(video->handle, "_SPD", &args, &tmp);
 
 425         if (ACPI_SUCCESS(status))
 
 426                 status = tmp ? (-EINVAL) : (AE_OK);
 
 428         return_VALUE(status);
 
 432 acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id)
 
 436         ACPI_FUNCTION_TRACE("acpi_video_bus_get_POST");
 
 438         status = acpi_evaluate_integer(video->handle, "_GPD", NULL, id);
 
 440         return_VALUE(status);
 
 444 acpi_video_bus_POST_options(struct acpi_video_bus *video,
 
 445                             unsigned long *options)
 
 448         ACPI_FUNCTION_TRACE("acpi_video_bus_POST_options");
 
 450         status = acpi_evaluate_integer(video->handle, "_VPO", NULL, options);
 
 453         return_VALUE(status);
 
 458  *      video           : video bus device pointer
 
 460  *              0.      The system BIOS should NOT automatically switch(toggle)
 
 461  *                      the active display output.
 
 462  *              1.      The system BIOS should automatically switch (toggle) the
 
 463  *                      active display output. No swich event.
 
 464  *              2.      The _DGS value should be locked.
 
 465  *              3.      The system BIOS should not automatically switch (toggle) the
 
 466  *                      active display output, but instead generate the display switch
 
 469  *              0.      The system BIOS should automatically control the brightness level
 
 470  *                      of the LCD, when the power changes from AC to DC
 
 471  *              1.      The system BIOS should NOT automatically control the brightness 
 
 472  *                      level of the LCD, when the power changes from AC to DC.
 
 478 acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
 
 480         acpi_integer status = 0;
 
 481         union acpi_object arg0 = { ACPI_TYPE_INTEGER };
 
 482         struct acpi_object_list args = { 1, &arg0 };
 
 484         ACPI_FUNCTION_TRACE("acpi_video_bus_DOS");
 
 486         if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) {
 
 490         arg0.integer.value = (lcd_flag << 2) | bios_flag;
 
 491         video->dos_setting = arg0.integer.value;
 
 492         acpi_evaluate_object(video->handle, "_DOS", &args, NULL);
 
 495         return_VALUE(status);
 
 500  *      device  : video output device (LCD, CRT, ..)
 
 505  *  Find out all required AML method defined under the output
 
 509 static void acpi_video_device_find_cap(struct acpi_video_device *device)
 
 512         acpi_handle h_dummy1;
 
 514         union acpi_object *obj = NULL;
 
 515         struct acpi_video_device_brightness *br = NULL;
 
 517         ACPI_FUNCTION_TRACE("acpi_video_device_find_cap");
 
 519         memset(&device->cap, 0, 4);
 
 521         if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ADR", &h_dummy1))) {
 
 522                 device->cap._ADR = 1;
 
 524         if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCL", &h_dummy1))) {
 
 525                 device->cap._BCL = 1;
 
 527         if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_BCM", &h_dummy1))) {
 
 528                 device->cap._BCM = 1;
 
 530         if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DDC", &h_dummy1))) {
 
 531                 device->cap._DDC = 1;
 
 533         if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DCS", &h_dummy1))) {
 
 534                 device->cap._DCS = 1;
 
 536         if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DGS", &h_dummy1))) {
 
 537                 device->cap._DGS = 1;
 
 539         if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DSS", &h_dummy1))) {
 
 540                 device->cap._DSS = 1;
 
 543         status = acpi_video_device_lcd_query_levels(device, &obj);
 
 545         if (obj && obj->type == ACPI_TYPE_PACKAGE && obj->package.count >= 2) {
 
 547                 union acpi_object *o;
 
 549                 br = kmalloc(sizeof(*br), GFP_KERNEL);
 
 551                         printk(KERN_ERR "can't allocate memory\n");
 
 553                         memset(br, 0, sizeof(*br));
 
 554                         br->levels = kmalloc(obj->package.count *
 
 555                                              sizeof *(br->levels), GFP_KERNEL);
 
 559                         for (i = 0; i < obj->package.count; i++) {
 
 560                                 o = (union acpi_object *)&obj->package.
 
 562                                 if (o->type != ACPI_TYPE_INTEGER) {
 
 563                                         ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
 567                                 br->levels[count] = (u32) o->integer.value;
 
 576                                 device->brightness = br;
 
 577                                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 
 578                                                   "found %d brightness levels\n",
 
 591  *      device  : video output device (VGA)
 
 596  *  Find out all required AML method defined under the video bus device.
 
 599 static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
 
 601         acpi_handle h_dummy1;
 
 603         memset(&video->cap, 0, 4);
 
 604         if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOS", &h_dummy1))) {
 
 607         if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_DOD", &h_dummy1))) {
 
 610         if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_ROM", &h_dummy1))) {
 
 613         if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_GPD", &h_dummy1))) {
 
 616         if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_SPD", &h_dummy1))) {
 
 619         if (ACPI_SUCCESS(acpi_get_handle(video->handle, "_VPO", &h_dummy1))) {
 
 625  * Check whether the video bus device has required AML method to
 
 626  * support the desired features
 
 629 static int acpi_video_bus_check(struct acpi_video_bus *video)
 
 631         acpi_status status = -ENOENT;
 
 633         ACPI_FUNCTION_TRACE("acpi_video_bus_check");
 
 636                 return_VALUE(-EINVAL);
 
 638         /* Since there is no HID, CID and so on for VGA driver, we have
 
 639          * to check well known required nodes.
 
 642         /* Does this device able to support video switching ? */
 
 643         if (video->cap._DOS) {
 
 644                 video->flags.multihead = 1;
 
 648         /* Does this device able to retrieve a retrieve a video ROM ? */
 
 649         if (video->cap._ROM) {
 
 650                 video->flags.rom = 1;
 
 654         /* Does this device able to configure which video device to POST ? */
 
 655         if (video->cap._GPD && video->cap._SPD && video->cap._VPO) {
 
 656                 video->flags.post = 1;
 
 660         return_VALUE(status);
 
 663 /* --------------------------------------------------------------------------
 
 665    -------------------------------------------------------------------------- */
 
 667 static struct proc_dir_entry *acpi_video_dir;
 
 671 static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset)
 
 673         struct acpi_video_device *dev =
 
 674             (struct acpi_video_device *)seq->private;
 
 676         ACPI_FUNCTION_TRACE("acpi_video_device_info_seq_show");
 
 681         seq_printf(seq, "device_id:    0x%04x\n", (u32) dev->device_id);
 
 682         seq_printf(seq, "type:         ");
 
 684                 seq_printf(seq, "CRT\n");
 
 685         else if (dev->flags.lcd)
 
 686                 seq_printf(seq, "LCD\n");
 
 687         else if (dev->flags.tvout)
 
 688                 seq_printf(seq, "TVOUT\n");
 
 690                 seq_printf(seq, "UNKNOWN\n");
 
 692         seq_printf(seq, "known by bios: %s\n", dev->flags.bios ? "yes" : "no");
 
 699 acpi_video_device_info_open_fs(struct inode *inode, struct file *file)
 
 701         return single_open(file, acpi_video_device_info_seq_show,
 
 705 static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
 
 708         struct acpi_video_device *dev =
 
 709             (struct acpi_video_device *)seq->private;
 
 712         ACPI_FUNCTION_TRACE("acpi_video_device_state_seq_show");
 
 717         status = acpi_video_device_get_state(dev, &state);
 
 718         seq_printf(seq, "state:     ");
 
 719         if (ACPI_SUCCESS(status))
 
 720                 seq_printf(seq, "0x%02lx\n", state);
 
 722                 seq_printf(seq, "<not supported>\n");
 
 724         status = acpi_video_device_query(dev, &state);
 
 725         seq_printf(seq, "query:     ");
 
 726         if (ACPI_SUCCESS(status))
 
 727                 seq_printf(seq, "0x%02lx\n", state);
 
 729                 seq_printf(seq, "<not supported>\n");
 
 736 acpi_video_device_state_open_fs(struct inode *inode, struct file *file)
 
 738         return single_open(file, acpi_video_device_state_seq_show,
 
 743 acpi_video_device_write_state(struct file *file,
 
 744                               const char __user * buffer,
 
 745                               size_t count, loff_t * data)
 
 748         struct seq_file *m = (struct seq_file *)file->private_data;
 
 749         struct acpi_video_device *dev = (struct acpi_video_device *)m->private;
 
 750         char str[12] = { 0 };
 
 753         ACPI_FUNCTION_TRACE("acpi_video_device_write_state");
 
 755         if (!dev || count + 1 > sizeof str)
 
 756                 return_VALUE(-EINVAL);
 
 758         if (copy_from_user(str, buffer, count))
 
 759                 return_VALUE(-EFAULT);
 
 762         state = simple_strtoul(str, NULL, 0);
 
 763         state &= ((1ul << 31) | (1ul << 30) | (1ul << 0));
 
 765         status = acpi_video_device_set_state(dev, state);
 
 768                 return_VALUE(-EFAULT);
 
 774 acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset)
 
 776         struct acpi_video_device *dev =
 
 777             (struct acpi_video_device *)seq->private;
 
 780         ACPI_FUNCTION_TRACE("acpi_video_device_brightness_seq_show");
 
 782         if (!dev || !dev->brightness) {
 
 783                 seq_printf(seq, "<not supported>\n");
 
 787         seq_printf(seq, "levels: ");
 
 788         for (i = 0; i < dev->brightness->count; i++)
 
 789                 seq_printf(seq, " %d", dev->brightness->levels[i]);
 
 790         seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
 
 796 acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file)
 
 798         return single_open(file, acpi_video_device_brightness_seq_show,
 
 803 acpi_video_device_write_brightness(struct file *file,
 
 804                                    const char __user * buffer,
 
 805                                    size_t count, loff_t * data)
 
 807         struct seq_file *m = (struct seq_file *)file->private_data;
 
 808         struct acpi_video_device *dev = (struct acpi_video_device *)m->private;
 
 810         unsigned int level = 0;
 
 813         ACPI_FUNCTION_TRACE("acpi_video_device_write_brightness");
 
 815         if (!dev || !dev->brightness || count + 1 > sizeof str)
 
 816                 return_VALUE(-EINVAL);
 
 818         if (copy_from_user(str, buffer, count))
 
 819                 return_VALUE(-EFAULT);
 
 822         level = simple_strtoul(str, NULL, 0);
 
 825                 return_VALUE(-EFAULT);
 
 827         /* validate though the list of available levels */
 
 828         for (i = 0; i < dev->brightness->count; i++)
 
 829                 if (level == dev->brightness->levels[i]) {
 
 831                             (acpi_video_device_lcd_set_level(dev, level)))
 
 832                                 dev->brightness->curr = level;
 
 839 static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset)
 
 841         struct acpi_video_device *dev =
 
 842             (struct acpi_video_device *)seq->private;
 
 845         union acpi_object *edid = NULL;
 
 847         ACPI_FUNCTION_TRACE("acpi_video_device_EDID_seq_show");
 
 852         status = acpi_video_device_EDID(dev, &edid, 128);
 
 853         if (ACPI_FAILURE(status)) {
 
 854                 status = acpi_video_device_EDID(dev, &edid, 256);
 
 857         if (ACPI_FAILURE(status)) {
 
 861         if (edid && edid->type == ACPI_TYPE_BUFFER) {
 
 862                 for (i = 0; i < edid->buffer.length; i++)
 
 863                         seq_putc(seq, edid->buffer.pointer[i]);
 
 868                 seq_printf(seq, "<not supported>\n");
 
 876 acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file)
 
 878         return single_open(file, acpi_video_device_EDID_seq_show,
 
 882 static int acpi_video_device_add_fs(struct acpi_device *device)
 
 884         struct proc_dir_entry *entry = NULL;
 
 885         struct acpi_video_device *vid_dev;
 
 887         ACPI_FUNCTION_TRACE("acpi_video_device_add_fs");
 
 890                 return_VALUE(-ENODEV);
 
 892         vid_dev = (struct acpi_video_device *)acpi_driver_data(device);
 
 894                 return_VALUE(-ENODEV);
 
 896         if (!acpi_device_dir(device)) {
 
 897                 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
 
 898                                                      vid_dev->video->dir);
 
 899                 if (!acpi_device_dir(device))
 
 900                         return_VALUE(-ENODEV);
 
 901                 acpi_device_dir(device)->owner = THIS_MODULE;
 
 905         entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
 
 907                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
 908                                   "Unable to create 'info' fs entry\n"));
 
 910                 entry->proc_fops = &acpi_video_device_info_fops;
 
 911                 entry->data = acpi_driver_data(device);
 
 912                 entry->owner = THIS_MODULE;
 
 917             create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR,
 
 918                               acpi_device_dir(device));
 
 920                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
 921                                   "Unable to create 'state' fs entry\n"));
 
 923                 acpi_video_device_state_fops.write = acpi_video_device_write_state;
 
 924                 entry->proc_fops = &acpi_video_device_state_fops;
 
 925                 entry->data = acpi_driver_data(device);
 
 926                 entry->owner = THIS_MODULE;
 
 929         /* 'brightness' [R/W] */
 
 931             create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR,
 
 932                               acpi_device_dir(device));
 
 934                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
 935                                   "Unable to create 'brightness' fs entry\n"));
 
 937                 acpi_video_device_brightness_fops.write = acpi_video_device_write_brightness;
 
 938                 entry->proc_fops = &acpi_video_device_brightness_fops;
 
 939                 entry->data = acpi_driver_data(device);
 
 940                 entry->owner = THIS_MODULE;
 
 944         entry = create_proc_entry("EDID", S_IRUGO, acpi_device_dir(device));
 
 946                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
 947                                   "Unable to create 'brightness' fs entry\n"));
 
 949                 entry->proc_fops = &acpi_video_device_EDID_fops;
 
 950                 entry->data = acpi_driver_data(device);
 
 951                 entry->owner = THIS_MODULE;
 
 957 static int acpi_video_device_remove_fs(struct acpi_device *device)
 
 959         struct acpi_video_device *vid_dev;
 
 960         ACPI_FUNCTION_TRACE("acpi_video_device_remove_fs");
 
 962         vid_dev = (struct acpi_video_device *)acpi_driver_data(device);
 
 963         if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
 
 964                 return_VALUE(-ENODEV);
 
 966         if (acpi_device_dir(device)) {
 
 967                 remove_proc_entry("info", acpi_device_dir(device));
 
 968                 remove_proc_entry("state", acpi_device_dir(device));
 
 969                 remove_proc_entry("brightness", acpi_device_dir(device));
 
 970                 remove_proc_entry("EDID", acpi_device_dir(device));
 
 971                 remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
 
 972                 acpi_device_dir(device) = NULL;
 
 979 static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset)
 
 981         struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
 
 983         ACPI_FUNCTION_TRACE("acpi_video_bus_info_seq_show");
 
 988         seq_printf(seq, "Switching heads:              %s\n",
 
 989                    video->flags.multihead ? "yes" : "no");
 
 990         seq_printf(seq, "Video ROM:                    %s\n",
 
 991                    video->flags.rom ? "yes" : "no");
 
 992         seq_printf(seq, "Device to be POSTed on boot:  %s\n",
 
 993                    video->flags.post ? "yes" : "no");
 
 999 static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file)
 
1001         return single_open(file, acpi_video_bus_info_seq_show,
 
1005 static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset)
 
1007         struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
 
1009         ACPI_FUNCTION_TRACE("acpi_video_bus_ROM_seq_show");
 
1014         printk(KERN_INFO PREFIX "Please implement %s\n", __FUNCTION__);
 
1015         seq_printf(seq, "<TODO>\n");
 
1021 static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file)
 
1023         return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data);
 
1026 static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
 
1028         struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
 
1029         unsigned long options;
 
1032         ACPI_FUNCTION_TRACE("acpi_video_bus_POST_info_seq_show");
 
1037         status = acpi_video_bus_POST_options(video, &options);
 
1038         if (ACPI_SUCCESS(status)) {
 
1039                 if (!(options & 1)) {
 
1040                         printk(KERN_WARNING PREFIX
 
1041                                "The motherboard VGA device is not listed as a possible POST device.\n");
 
1042                         printk(KERN_WARNING PREFIX
 
1043                                "This indicate a BIOS bug.  Please contact the manufacturer.\n");
 
1045                 printk("%lx\n", options);
 
1046                 seq_printf(seq, "can POST: <intgrated video>");
 
1048                         seq_printf(seq, " <PCI video>");
 
1050                         seq_printf(seq, " <AGP video>");
 
1051                 seq_putc(seq, '\n');
 
1053                 seq_printf(seq, "<not supported>\n");
 
1059 acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file)
 
1061         return single_open(file, acpi_video_bus_POST_info_seq_show,
 
1065 static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
 
1067         struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
 
1071         ACPI_FUNCTION_TRACE("acpi_video_bus_POST_seq_show");
 
1076         status = acpi_video_bus_get_POST(video, &id);
 
1077         if (!ACPI_SUCCESS(status)) {
 
1078                 seq_printf(seq, "<not supported>\n");
 
1081         seq_printf(seq, "device posted is <%s>\n", device_decode[id & 3]);
 
1087 static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset)
 
1089         struct acpi_video_bus *video = (struct acpi_video_bus *)seq->private;
 
1091         ACPI_FUNCTION_TRACE("acpi_video_bus_DOS_seq_show");
 
1093         seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting);
 
1098 static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file)
 
1100         return single_open(file, acpi_video_bus_POST_seq_show,
 
1104 static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file)
 
1106         return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data);
 
1110 acpi_video_bus_write_POST(struct file *file,
 
1111                           const char __user * buffer,
 
1112                           size_t count, loff_t * data)
 
1115         struct seq_file *m = (struct seq_file *)file->private_data;
 
1116         struct acpi_video_bus *video = (struct acpi_video_bus *)m->private;
 
1117         char str[12] = { 0 };
 
1118         unsigned long opt, options;
 
1120         ACPI_FUNCTION_TRACE("acpi_video_bus_write_POST");
 
1122         if (!video || count + 1 > sizeof str)
 
1123                 return_VALUE(-EINVAL);
 
1125         status = acpi_video_bus_POST_options(video, &options);
 
1126         if (!ACPI_SUCCESS(status))
 
1127                 return_VALUE(-EINVAL);
 
1129         if (copy_from_user(str, buffer, count))
 
1130                 return_VALUE(-EFAULT);
 
1133         opt = strtoul(str, NULL, 0);
 
1135                 return_VALUE(-EFAULT);
 
1137         /* just in case an OEM 'forget' the motherboard... */
 
1140         if (options & (1ul << opt)) {
 
1141                 status = acpi_video_bus_set_POST(video, opt);
 
1142                 if (!ACPI_SUCCESS(status))
 
1143                         return_VALUE(-EFAULT);
 
1147         return_VALUE(count);
 
1151 acpi_video_bus_write_DOS(struct file *file,
 
1152                          const char __user * buffer,
 
1153                          size_t count, loff_t * data)
 
1156         struct seq_file *m = (struct seq_file *)file->private_data;
 
1157         struct acpi_video_bus *video = (struct acpi_video_bus *)m->private;
 
1158         char str[12] = { 0 };
 
1161         ACPI_FUNCTION_TRACE("acpi_video_bus_write_DOS");
 
1163         if (!video || count + 1 > sizeof str)
 
1164                 return_VALUE(-EINVAL);
 
1166         if (copy_from_user(str, buffer, count))
 
1167                 return_VALUE(-EFAULT);
 
1170         opt = strtoul(str, NULL, 0);
 
1172                 return_VALUE(-EFAULT);
 
1174         status = acpi_video_bus_DOS(video, opt & 0x3, (opt & 0x4) >> 2);
 
1176         if (!ACPI_SUCCESS(status))
 
1177                 return_VALUE(-EFAULT);
 
1179         return_VALUE(count);
 
1182 static int acpi_video_bus_add_fs(struct acpi_device *device)
 
1184         struct proc_dir_entry *entry = NULL;
 
1185         struct acpi_video_bus *video;
 
1187         ACPI_FUNCTION_TRACE("acpi_video_bus_add_fs");
 
1189         video = (struct acpi_video_bus *)acpi_driver_data(device);
 
1191         if (!acpi_device_dir(device)) {
 
1192                 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
 
1194                 if (!acpi_device_dir(device))
 
1195                         return_VALUE(-ENODEV);
 
1196                 video->dir = acpi_device_dir(device);
 
1197                 acpi_device_dir(device)->owner = THIS_MODULE;
 
1201         entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
 
1203                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
1204                                   "Unable to create 'info' fs entry\n"));
 
1206                 entry->proc_fops = &acpi_video_bus_info_fops;
 
1207                 entry->data = acpi_driver_data(device);
 
1208                 entry->owner = THIS_MODULE;
 
1212         entry = create_proc_entry("ROM", S_IRUGO, acpi_device_dir(device));
 
1214                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
1215                                   "Unable to create 'ROM' fs entry\n"));
 
1217                 entry->proc_fops = &acpi_video_bus_ROM_fops;
 
1218                 entry->data = acpi_driver_data(device);
 
1219                 entry->owner = THIS_MODULE;
 
1222         /* 'POST_info' [R] */
 
1224             create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device));
 
1226                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
1227                                   "Unable to create 'POST_info' fs entry\n"));
 
1229                 entry->proc_fops = &acpi_video_bus_POST_info_fops;
 
1230                 entry->data = acpi_driver_data(device);
 
1231                 entry->owner = THIS_MODULE;
 
1236             create_proc_entry("POST", S_IFREG | S_IRUGO | S_IRUSR,
 
1237                               acpi_device_dir(device));
 
1239                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
1240                                   "Unable to create 'POST' fs entry\n"));
 
1242                 acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
 
1243                 entry->proc_fops = &acpi_video_bus_POST_fops;
 
1244                 entry->data = acpi_driver_data(device);
 
1245                 entry->owner = THIS_MODULE;
 
1250             create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IRUSR,
 
1251                               acpi_device_dir(device));
 
1253                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
1254                                   "Unable to create 'DOS' fs entry\n"));
 
1256                 acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
 
1257                 entry->proc_fops = &acpi_video_bus_DOS_fops;
 
1258                 entry->data = acpi_driver_data(device);
 
1259                 entry->owner = THIS_MODULE;
 
1265 static int acpi_video_bus_remove_fs(struct acpi_device *device)
 
1267         struct acpi_video_bus *video;
 
1269         ACPI_FUNCTION_TRACE("acpi_video_bus_remove_fs");
 
1271         video = (struct acpi_video_bus *)acpi_driver_data(device);
 
1273         if (acpi_device_dir(device)) {
 
1274                 remove_proc_entry("info", acpi_device_dir(device));
 
1275                 remove_proc_entry("ROM", acpi_device_dir(device));
 
1276                 remove_proc_entry("POST_info", acpi_device_dir(device));
 
1277                 remove_proc_entry("POST", acpi_device_dir(device));
 
1278                 remove_proc_entry("DOS", acpi_device_dir(device));
 
1279                 remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
 
1280                 acpi_device_dir(device) = NULL;
 
1286 /* --------------------------------------------------------------------------
 
1288    -------------------------------------------------------------------------- */
 
1290 /* device interface */
 
1293 acpi_video_bus_get_one_device(struct acpi_device *device,
 
1294                               struct acpi_video_bus *video)
 
1296         unsigned long device_id;
 
1298         struct acpi_video_device *data;
 
1300         ACPI_FUNCTION_TRACE("acpi_video_bus_get_one_device");
 
1302         if (!device || !video)
 
1303                 return_VALUE(-EINVAL);
 
1306             acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
 
1307         if (ACPI_SUCCESS(status)) {
 
1309                 data = kmalloc(sizeof(struct acpi_video_device), GFP_KERNEL);
 
1311                         return_VALUE(-ENOMEM);
 
1313                 memset(data, 0, sizeof(struct acpi_video_device));
 
1315                 data->handle = device->handle;
 
1316                 strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
 
1317                 strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
 
1318                 acpi_driver_data(device) = data;
 
1320                 data->device_id = device_id;
 
1321                 data->video = video;
 
1324                 switch (device_id & 0xffff) {
 
1326                         data->flags.crt = 1;
 
1329                         data->flags.lcd = 1;
 
1332                         data->flags.tvout = 1;
 
1335                         data->flags.unknown = 1;
 
1339                 acpi_video_device_bind(video, data);
 
1340                 acpi_video_device_find_cap(data);
 
1342                 status = acpi_install_notify_handler(data->handle,
 
1344                                                      acpi_video_device_notify,
 
1346                 if (ACPI_FAILURE(status)) {
 
1347                         ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
1348                                           "Error installing notify handler\n"));
 
1354                 list_add_tail(&data->entry, &video->video_device_list);
 
1357                 acpi_video_device_add_fs(device);
 
1363         return_VALUE(-ENOENT);
 
1368  *      video   : video bus device 
 
1373  *  Enumerate the video device list of the video bus, 
 
1374  *  bind the ids with the corresponding video devices
 
1375  *  under the video bus.
 
1378 static void acpi_video_device_rebind(struct acpi_video_bus *video)
 
1380         struct list_head *node, *next;
 
1381         list_for_each_safe(node, next, &video->video_device_list) {
 
1382                 struct acpi_video_device *dev =
 
1383                     container_of(node, struct acpi_video_device, entry);
 
1384                 acpi_video_device_bind(video, dev);
 
1390  *      video   : video bus device 
 
1391  *      device  : video output device under the video 
 
1397  *  Bind the ids with the corresponding video devices
 
1398  *  under the video bus.
 
1402 acpi_video_device_bind(struct acpi_video_bus *video,
 
1403                        struct acpi_video_device *device)
 
1406         ACPI_FUNCTION_TRACE("acpi_video_device_bind");
 
1408 #define IDS_VAL(i) video->attached_array[i].value.int_val
 
1409 #define IDS_BIND(i) video->attached_array[i].bind_info
 
1411         for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID &&
 
1412              i < video->attached_count; i++) {
 
1413                 if (device->device_id == (IDS_VAL(i) & 0xffff)) {
 
1414                         IDS_BIND(i) = device;
 
1415                         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i));
 
1424  *      video   : video bus device 
 
1429  *  Call _DOD to enumerate all devices attached to display adapter
 
1433 static int acpi_video_device_enumerate(struct acpi_video_bus *video)
 
1438         struct acpi_video_enumerated_device *active_device_list;
 
1439         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 
1440         union acpi_object *dod = NULL;
 
1441         union acpi_object *obj;
 
1443         ACPI_FUNCTION_TRACE("acpi_video_device_enumerate");
 
1445         status = acpi_evaluate_object(video->handle, "_DOD", NULL, &buffer);
 
1446         if (!ACPI_SUCCESS(status)) {
 
1447                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _DOD\n"));
 
1448                 return_VALUE(status);
 
1451         dod = (union acpi_object *)buffer.pointer;
 
1452         if (!dod || (dod->type != ACPI_TYPE_PACKAGE)) {
 
1453                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _DOD data\n"));
 
1458         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n",
 
1459                           dod->package.count));
 
1461         active_device_list = kmalloc((1 +
 
1462                                       dod->package.count) *
 
1464                                             acpi_video_enumerated_device),
 
1467         if (!active_device_list) {
 
1473         for (i = 0; i < dod->package.count; i++) {
 
1474                 obj = (union acpi_object *)&dod->package.elements[i];
 
1476                 if (obj->type != ACPI_TYPE_INTEGER) {
 
1477                         ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
1478                                           "Invalid _DOD data\n"));
 
1479                         active_device_list[i].value.int_val =
 
1480                             ACPI_VIDEO_HEAD_INVALID;
 
1482                 active_device_list[i].value.int_val = obj->integer.value;
 
1483                 active_device_list[i].bind_info = NULL;
 
1484                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i,
 
1485                                   (int)obj->integer.value));
 
1488         active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END;
 
1490         kfree(video->attached_array);
 
1492         video->attached_array = active_device_list;
 
1493         video->attached_count = count;
 
1495         acpi_os_free(buffer.pointer);
 
1496         return_VALUE(status);
 
1501  *      video   : video bus device 
 
1502  *      event   : Nontify Event
 
1507  *      1. Find out the current active output device.
 
1508  *      2. Identify the next output device to switch
 
1509  *      3. call _DSS to do actual switch.
 
1512 static int acpi_video_switch_output(struct acpi_video_bus *video, int event)
 
1514         struct list_head *node, *next;
 
1515         struct acpi_video_device *dev = NULL;
 
1516         struct acpi_video_device *dev_next = NULL;
 
1517         struct acpi_video_device *dev_prev = NULL;
 
1518         unsigned long state;
 
1521         ACPI_FUNCTION_TRACE("acpi_video_switch_output");
 
1523         list_for_each_safe(node, next, &video->video_device_list) {
 
1524                 dev = container_of(node, struct acpi_video_device, entry);
 
1525                 status = acpi_video_device_get_state(dev, &state);
 
1528                             container_of(node->next, struct acpi_video_device,
 
1531                             container_of(node->prev, struct acpi_video_device,
 
1536         dev_next = container_of(node->next, struct acpi_video_device, entry);
 
1537         dev_prev = container_of(node->prev, struct acpi_video_device, entry);
 
1540         case ACPI_VIDEO_NOTIFY_CYCLE:
 
1541         case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
 
1542                 acpi_video_device_set_state(dev, 0);
 
1543                 acpi_video_device_set_state(dev_next, 0x80000001);
 
1545         case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:
 
1546                 acpi_video_device_set_state(dev, 0);
 
1547                 acpi_video_device_set_state(dev_prev, 0x80000001);
 
1552         return_VALUE(status);
 
1556 acpi_video_get_next_level(struct acpi_video_device *device,
 
1557                           u32 level_current, u32 event)
 
1560         return level_current;
 
1564 acpi_video_switch_brightness(struct acpi_video_device *device, int event)
 
1566         unsigned long level_current, level_next;
 
1567         acpi_video_device_lcd_get_level_current(device, &level_current);
 
1568         level_next = acpi_video_get_next_level(device, level_current, event);
 
1569         acpi_video_device_lcd_set_level(device, level_next);
 
1573 acpi_video_bus_get_devices(struct acpi_video_bus *video,
 
1574                            struct acpi_device *device)
 
1577         struct list_head *node, *next;
 
1579         ACPI_FUNCTION_TRACE("acpi_video_get_devices");
 
1581         acpi_video_device_enumerate(video);
 
1583         list_for_each_safe(node, next, &device->children) {
 
1584                 struct acpi_device *dev =
 
1585                     list_entry(node, struct acpi_device, node);
 
1590                 status = acpi_video_bus_get_one_device(dev, video);
 
1591                 if (ACPI_FAILURE(status)) {
 
1592                         ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
1593                                           "Cant attach device\n"));
 
1598         return_VALUE(status);
 
1601 static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
 
1604         struct acpi_video_bus *video;
 
1606         ACPI_FUNCTION_TRACE("acpi_video_bus_put_one_device");
 
1608         if (!device || !device->video)
 
1609                 return_VALUE(-ENOENT);
 
1611         video = device->video;
 
1614         list_del(&device->entry);
 
1616         acpi_video_device_remove_fs(device->dev);
 
1618         status = acpi_remove_notify_handler(device->handle,
 
1620                                             acpi_video_device_notify);
 
1621         if (ACPI_FAILURE(status))
 
1622                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
1623                                   "Error removing notify handler\n"));
 
1628 static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
 
1631         struct list_head *node, *next;
 
1633         ACPI_FUNCTION_TRACE("acpi_video_bus_put_devices");
 
1635         list_for_each_safe(node, next, &video->video_device_list) {
 
1636                 struct acpi_video_device *data =
 
1637                     list_entry(node, struct acpi_video_device, entry);
 
1641                 status = acpi_video_bus_put_one_device(data);
 
1642                 if (ACPI_FAILURE(status))
 
1643                         printk(KERN_WARNING PREFIX
 
1644                                "hhuuhhuu bug in acpi video driver.\n");
 
1646                 kfree(data->brightness);
 
1654 /* acpi_video interface */
 
1656 static int acpi_video_bus_start_devices(struct acpi_video_bus *video)
 
1658         return acpi_video_bus_DOS(video, 1, 0);
 
1661 static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
 
1663         return acpi_video_bus_DOS(video, 0, 1);
 
1666 static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
 
1668         struct acpi_video_bus *video = (struct acpi_video_bus *)data;
 
1669         struct acpi_device *device = NULL;
 
1671         ACPI_FUNCTION_TRACE("acpi_video_bus_notify");
 
1672         printk("video bus notify\n");
 
1677         if (acpi_bus_get_device(handle, &device))
 
1681         case ACPI_VIDEO_NOTIFY_SWITCH:  /* User request that a switch occur,
 
1682                                          * most likely via hotkey. */
 
1683                 acpi_bus_generate_event(device, event, 0);
 
1686         case ACPI_VIDEO_NOTIFY_PROBE:   /* User plug or remove a video
 
1688                 acpi_video_device_enumerate(video);
 
1689                 acpi_video_device_rebind(video);
 
1690                 acpi_video_switch_output(video, event);
 
1691                 acpi_bus_generate_event(device, event, 0);
 
1694         case ACPI_VIDEO_NOTIFY_CYCLE:   /* Cycle Display output hotkey pressed. */
 
1695         case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:     /* Next Display output hotkey pressed. */
 
1696         case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:     /* previous Display output hotkey pressed. */
 
1697                 acpi_video_switch_output(video, event);
 
1698                 acpi_bus_generate_event(device, event, 0);
 
1702                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 
1703                                   "Unsupported event [0x%x]\n", event));
 
1710 static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
 
1712         struct acpi_video_device *video_device =
 
1713             (struct acpi_video_device *)data;
 
1714         struct acpi_device *device = NULL;
 
1716         ACPI_FUNCTION_TRACE("acpi_video_device_notify");
 
1718         printk("video device notify\n");
 
1722         if (acpi_bus_get_device(handle, &device))
 
1726         case ACPI_VIDEO_NOTIFY_SWITCH:  /* change in status (cycle output device) */
 
1727         case ACPI_VIDEO_NOTIFY_PROBE:   /* change in status (output device status) */
 
1728                 acpi_bus_generate_event(device, event, 0);
 
1730         case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS:        /* Cycle brightness */
 
1731         case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS:  /* Increase brightness */
 
1732         case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS:  /* Decrease brightness */
 
1733         case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */
 
1734         case ACPI_VIDEO_NOTIFY_DISPLAY_OFF:     /* display device off */
 
1735                 acpi_video_switch_brightness(video_device, event);
 
1736                 acpi_bus_generate_event(device, event, 0);
 
1739                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 
1740                                   "Unsupported event [0x%x]\n", event));
 
1746 static int acpi_video_bus_add(struct acpi_device *device)
 
1749         acpi_status status = 0;
 
1750         struct acpi_video_bus *video = NULL;
 
1752         ACPI_FUNCTION_TRACE("acpi_video_bus_add");
 
1755                 return_VALUE(-EINVAL);
 
1757         video = kmalloc(sizeof(struct acpi_video_bus), GFP_KERNEL);
 
1759                 return_VALUE(-ENOMEM);
 
1760         memset(video, 0, sizeof(struct acpi_video_bus));
 
1762         video->handle = device->handle;
 
1763         strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
 
1764         strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
 
1765         acpi_driver_data(device) = video;
 
1767         acpi_video_bus_find_cap(video);
 
1768         result = acpi_video_bus_check(video);
 
1772         result = acpi_video_bus_add_fs(device);
 
1776         init_MUTEX(&video->sem);
 
1777         INIT_LIST_HEAD(&video->video_device_list);
 
1779         acpi_video_bus_get_devices(video, device);
 
1780         acpi_video_bus_start_devices(video);
 
1782         status = acpi_install_notify_handler(video->handle,
 
1784                                              acpi_video_bus_notify, video);
 
1785         if (ACPI_FAILURE(status)) {
 
1786                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
1787                                   "Error installing notify handler\n"));
 
1792         printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s  rom: %s  post: %s)\n",
 
1793                ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
 
1794                video->flags.multihead ? "yes" : "no",
 
1795                video->flags.rom ? "yes" : "no",
 
1796                video->flags.post ? "yes" : "no");
 
1800                 acpi_video_bus_remove_fs(device);
 
1804         return_VALUE(result);
 
1807 static int acpi_video_bus_remove(struct acpi_device *device, int type)
 
1809         acpi_status status = 0;
 
1810         struct acpi_video_bus *video = NULL;
 
1812         ACPI_FUNCTION_TRACE("acpi_video_bus_remove");
 
1814         if (!device || !acpi_driver_data(device))
 
1815                 return_VALUE(-EINVAL);
 
1817         video = (struct acpi_video_bus *)acpi_driver_data(device);
 
1819         acpi_video_bus_stop_devices(video);
 
1821         status = acpi_remove_notify_handler(video->handle,
 
1823                                             acpi_video_bus_notify);
 
1824         if (ACPI_FAILURE(status))
 
1825                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 
1826                                   "Error removing notify handler\n"));
 
1828         acpi_video_bus_put_devices(video);
 
1829         acpi_video_bus_remove_fs(device);
 
1831         kfree(video->attached_array);
 
1838 acpi_video_bus_match(struct acpi_device *device, struct acpi_driver *driver)
 
1840         acpi_handle h_dummy1;
 
1841         acpi_handle h_dummy2;
 
1842         acpi_handle h_dummy3;
 
1844         ACPI_FUNCTION_TRACE("acpi_video_bus_match");
 
1846         if (!device || !driver)
 
1847                 return_VALUE(-EINVAL);
 
1849         /* Since there is no HID, CID for ACPI Video drivers, we have
 
1850          * to check well known required nodes for each feature we support.
 
1853         /* Does this device able to support video switching ? */
 
1854         if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) &&
 
1855             ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2)))
 
1858         /* Does this device able to retrieve a video ROM ? */
 
1859         if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1)))
 
1862         /* Does this device able to configure which video head to be POSTed ? */
 
1863         if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) &&
 
1864             ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) &&
 
1865             ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3)))
 
1868         return_VALUE(-ENODEV);
 
1871 static int __init acpi_video_init(void)
 
1875         ACPI_FUNCTION_TRACE("acpi_video_init");
 
1878            acpi_dbg_level = 0xFFFFFFFF;
 
1879            acpi_dbg_layer = 0x08000000;
 
1882         acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
 
1883         if (!acpi_video_dir)
 
1884                 return_VALUE(-ENODEV);
 
1885         acpi_video_dir->owner = THIS_MODULE;
 
1887         result = acpi_bus_register_driver(&acpi_video_bus);
 
1889                 remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
 
1890                 return_VALUE(-ENODEV);
 
1896 static void __exit acpi_video_exit(void)
 
1898         ACPI_FUNCTION_TRACE("acpi_video_exit");
 
1900         acpi_bus_unregister_driver(&acpi_video_bus);
 
1902         remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
 
1907 module_init(acpi_video_init);
 
1908 module_exit(acpi_video_exit);