]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/acpi/video.c
parisc: sba_iommu: fix build bug when CONFIG_PARISC_AGP=y
[linux-2.6.git] / drivers / acpi / video.c
index a54ff6bce8fa3865cc2e78f7bc0ae2ffd0e6e0c3..bb5ed059114aa296e826b91f8b35083ccc773028 100644 (file)
 #include <linux/seq_file.h>
 #include <linux/input.h>
 #include <linux/backlight.h>
+#include <linux/thermal.h>
 #include <linux/video_output.h>
+#include <linux/sort.h>
 #include <asm/uaccess.h>
 
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
-#define ACPI_VIDEO_COMPONENT           0x08000000
 #define ACPI_VIDEO_CLASS               "video"
 #define ACPI_VIDEO_BUS_NAME            "Video Bus"
 #define ACPI_VIDEO_DEVICE_NAME         "Video Device"
@@ -56,8 +57,6 @@
 #define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS      0x88
 #define ACPI_VIDEO_NOTIFY_DISPLAY_OFF          0x89
 
-#define ACPI_VIDEO_HEAD_INVALID                (~0u - 1)
-#define ACPI_VIDEO_HEAD_END            (~0u)
 #define MAX_NAME_LEN   20
 
 #define ACPI_VIDEO_DISPLAY_CRT 1
@@ -72,8 +71,12 @@ MODULE_AUTHOR("Bruno Ducrot");
 MODULE_DESCRIPTION("ACPI Video Driver");
 MODULE_LICENSE("GPL");
 
+static int brightness_switch_enabled = 1;
+module_param(brightness_switch_enabled, bool, 0644);
+
 static int acpi_video_bus_add(struct acpi_device *device);
 static int acpi_video_bus_remove(struct acpi_device *device, int type);
+static int acpi_video_resume(struct acpi_device *device);
 
 static const struct acpi_device_id video_device_ids[] = {
        {ACPI_VIDEO_HID, 0},
@@ -88,6 +91,7 @@ static struct acpi_driver acpi_video_bus = {
        .ops = {
                .add = acpi_video_bus_add,
                .remove = acpi_video_bus_remove,
+               .resume = acpi_video_resume,
                },
 };
 
@@ -179,12 +183,14 @@ struct acpi_video_device {
        struct acpi_device *dev;
        struct acpi_video_device_brightness *brightness;
        struct backlight_device *backlight;
+       struct thermal_cooling_device *cdev;
        struct output_device *output_dev;
 };
 
 /* bus */
 static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
 static struct file_operations acpi_video_bus_info_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_bus_info_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -193,6 +199,7 @@ static struct file_operations acpi_video_bus_info_fops = {
 
 static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
 static struct file_operations acpi_video_bus_ROM_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_bus_ROM_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -202,6 +209,7 @@ static struct file_operations acpi_video_bus_ROM_fops = {
 static int acpi_video_bus_POST_info_open_fs(struct inode *inode,
                                            struct file *file);
 static struct file_operations acpi_video_bus_POST_info_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_bus_POST_info_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -210,6 +218,7 @@ static struct file_operations acpi_video_bus_POST_info_fops = {
 
 static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
 static struct file_operations acpi_video_bus_POST_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_bus_POST_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -218,6 +227,7 @@ static struct file_operations acpi_video_bus_POST_fops = {
 
 static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
 static struct file_operations acpi_video_bus_DOS_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_bus_DOS_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -228,6 +238,7 @@ static struct file_operations acpi_video_bus_DOS_fops = {
 static int acpi_video_device_info_open_fs(struct inode *inode,
                                          struct file *file);
 static struct file_operations acpi_video_device_info_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_device_info_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -237,6 +248,7 @@ static struct file_operations acpi_video_device_info_fops = {
 static int acpi_video_device_state_open_fs(struct inode *inode,
                                           struct file *file);
 static struct file_operations acpi_video_device_state_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_device_state_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -246,6 +258,7 @@ static struct file_operations acpi_video_device_state_fops = {
 static int acpi_video_device_brightness_open_fs(struct inode *inode,
                                                struct file *file);
 static struct file_operations acpi_video_device_brightness_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_device_brightness_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -255,6 +268,7 @@ static struct file_operations acpi_video_device_brightness_fops = {
 static int acpi_video_device_EDID_open_fs(struct inode *inode,
                                          struct file *file);
 static struct file_operations acpi_video_device_EDID_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_device_EDID_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -273,25 +287,24 @@ static void acpi_video_device_rebind(struct acpi_video_bus *video);
 static void acpi_video_device_bind(struct acpi_video_bus *video,
                                   struct acpi_video_device *device);
 static int acpi_video_device_enumerate(struct acpi_video_bus *video);
-static int acpi_video_switch_output(struct acpi_video_bus *video, int event);
 static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
                        int level);
 static int acpi_video_device_lcd_get_level_current(
                        struct acpi_video_device *device,
-                       unsigned long *level);
+                       unsigned long long *level);
 static int acpi_video_get_next_level(struct acpi_video_device *device,
                                     u32 level_current, u32 event);
 static void acpi_video_switch_brightness(struct acpi_video_device *device,
                                         int event);
 static int acpi_video_device_get_state(struct acpi_video_device *device,
-                           unsigned long *state);
+                           unsigned long long *state);
 static int acpi_video_output_get(struct output_device *od);
 static int acpi_video_device_set_state(struct acpi_video_device *device, int state);
 
 /*backlight device sysfs support*/
 static int acpi_video_get_brightness(struct backlight_device *bd)
 {
-       unsigned long cur_level;
+       unsigned long long cur_level;
        int i;
        struct acpi_video_device *vd =
                (struct acpi_video_device *)bl_get_data(bd);
@@ -323,7 +336,7 @@ static struct backlight_ops acpi_backlight_ops = {
 /*video output device sysfs support*/
 static int acpi_video_output_get(struct output_device *od)
 {
-       unsigned long state;
+       unsigned long long state;
        struct acpi_video_device *vd =
                (struct acpi_video_device *)dev_get_drvdata(&od->dev);
        acpi_video_device_get_state(vd, &state);
@@ -342,6 +355,54 @@ static struct output_properties acpi_output_properties = {
        .set_state = acpi_video_output_set,
        .get_status = acpi_video_output_get,
 };
+
+
+/* thermal cooling device callbacks */
+static int video_get_max_state(struct thermal_cooling_device *cdev, char *buf)
+{
+       struct acpi_device *device = cdev->devdata;
+       struct acpi_video_device *video = acpi_driver_data(device);
+
+       return sprintf(buf, "%d\n", video->brightness->count - 3);
+}
+
+static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
+{
+       struct acpi_device *device = cdev->devdata;
+       struct acpi_video_device *video = acpi_driver_data(device);
+       unsigned long long level;
+       int state;
+
+       acpi_video_device_lcd_get_level_current(video, &level);
+       for (state = 2; state < video->brightness->count; state++)
+               if (level == video->brightness->levels[state])
+                       return sprintf(buf, "%d\n",
+                                      video->brightness->count - state - 1);
+
+       return -EINVAL;
+}
+
+static int
+video_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state)
+{
+       struct acpi_device *device = cdev->devdata;
+       struct acpi_video_device *video = acpi_driver_data(device);
+       int level;
+
+       if ( state >= video->brightness->count - 2)
+               return -EINVAL;
+
+       state = video->brightness->count - state;
+       level = video->brightness->levels[state -1];
+       return acpi_video_device_lcd_set_level(video, level);
+}
+
+static struct thermal_cooling_device_ops video_cooling_ops = {
+       .get_max_state = video_get_max_state,
+       .get_cur_state = video_get_cur_state,
+       .set_cur_state = video_set_cur_state,
+};
+
 /* --------------------------------------------------------------------------
                                Video Management
    -------------------------------------------------------------------------- */
@@ -349,7 +410,7 @@ static struct output_properties acpi_output_properties = {
 /* device */
 
 static int
-acpi_video_device_query(struct acpi_video_device *device, unsigned long *state)
+acpi_video_device_query(struct acpi_video_device *device, unsigned long long *state)
 {
        int status;
 
@@ -360,7 +421,7 @@ acpi_video_device_query(struct acpi_video_device *device, unsigned long *state)
 
 static int
 acpi_video_device_get_state(struct acpi_video_device *device,
-                           unsigned long *state)
+                           unsigned long long *state)
 {
        int status;
 
@@ -375,7 +436,7 @@ acpi_video_device_set_state(struct acpi_video_device *device, int state)
        int status;
        union acpi_object arg0 = { ACPI_TYPE_INTEGER };
        struct acpi_object_list args = { 1, &arg0 };
-       unsigned long ret;
+       unsigned long long ret;
 
 
        arg0.integer.value = state;
@@ -421,6 +482,7 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
        int status = AE_OK;
        union acpi_object arg0 = { ACPI_TYPE_INTEGER };
        struct acpi_object_list args = { 1, &arg0 };
+       int state;
 
 
        arg0.integer.value = level;
@@ -429,12 +491,16 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
                status = acpi_evaluate_object(device->dev->handle, "_BCM",
                                              &args, NULL);
        device->brightness->curr = level;
+       for (state = 2; state < device->brightness->count; state++)
+               if (level == device->brightness->levels[state])
+                       device->backlight->props.brightness = state - 2;
+
        return status;
 }
 
 static int
 acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
-                                       unsigned long *level)
+                                       unsigned long long *level)
 {
        if (device->cap._BQC)
                return acpi_evaluate_integer(device->dev->handle, "_BQC", NULL,
@@ -488,7 +554,7 @@ static int
 acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
 {
        int status;
-       unsigned long tmp;
+       unsigned long long tmp;
        union acpi_object arg0 = { ACPI_TYPE_INTEGER };
        struct acpi_object_list args = { 1, &arg0 };
 
@@ -503,7 +569,7 @@ acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
 }
 
 static int
-acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id)
+acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id)
 {
        int status;
 
@@ -514,7 +580,7 @@ acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long *id)
 
 static int
 acpi_video_bus_POST_options(struct acpi_video_bus *video,
-                           unsigned long *options)
+                           unsigned long long *options)
 {
        int status;
 
@@ -565,11 +631,95 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
        return status;
 }
 
+/*
+ * Simple comparison function used to sort backlight levels.
+ */
+
+static int
+acpi_video_cmp_level(const void *a, const void *b)
+{
+       return *(int *)a - *(int *)b;
+}
+
 /*
  *  Arg:       
  *     device  : video output device (LCD, CRT, ..)
  *
  *  Return Value:
+ *     Maximum brightness level
+ *
+ *  Allocate and initialize device->brightness.
+ */
+
+static int
+acpi_video_init_brightness(struct acpi_video_device *device)
+{
+       union acpi_object *obj = NULL;
+       int i, max_level = 0, count = 0;
+       union acpi_object *o;
+       struct acpi_video_device_brightness *br = NULL;
+
+       if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available "
+                                               "LCD brightness level\n"));
+               goto out;
+       }
+
+       if (obj->package.count < 2)
+               goto out;
+
+       br = kzalloc(sizeof(*br), GFP_KERNEL);
+       if (!br) {
+               printk(KERN_ERR "can't allocate memory\n");
+               goto out;
+       }
+
+       br->levels = kmalloc(obj->package.count * sizeof *(br->levels),
+                               GFP_KERNEL);
+       if (!br->levels)
+               goto out_free;
+
+       for (i = 0; i < obj->package.count; i++) {
+               o = (union acpi_object *)&obj->package.elements[i];
+               if (o->type != ACPI_TYPE_INTEGER) {
+                       printk(KERN_ERR PREFIX "Invalid data\n");
+                       continue;
+               }
+               br->levels[count] = (u32) o->integer.value;
+
+               if (br->levels[count] > max_level)
+                       max_level = br->levels[count];
+               count++;
+       }
+
+       /* don't sort the first two brightness levels */
+       sort(&br->levels[2], count - 2, sizeof(br->levels[2]),
+               acpi_video_cmp_level, NULL);
+
+       if (count < 2)
+               goto out_free_levels;
+
+       br->count = count;
+       device->brightness = br;
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count));
+       kfree(obj);
+       return max_level;
+
+out_free_levels:
+       kfree(br->levels);
+out_free:
+       kfree(br);
+out:
+       device->brightness = NULL;
+       kfree(obj);
+       return 0;
+}
+
+/*
+ *  Arg:
+ *     device  : video output device (LCD, CRT, ..)
+ *
+ *  Return Value:
  *     None
  *
  *  Find out all required AML methods defined under the output
@@ -579,10 +729,7 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
 static void acpi_video_device_find_cap(struct acpi_video_device *device)
 {
        acpi_handle h_dummy1;
-       int i;
        u32 max_level = 0;
-       union acpi_object *obj = NULL;
-       struct acpi_video_device_brightness *br = NULL;
 
 
        memset(&device->cap, 0, sizeof(device->cap));
@@ -611,55 +758,11 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                device->cap._DSS = 1;
        }
 
-       if (ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
-
-               if (obj->package.count >= 2) {
-                       int count = 0;
-                       union acpi_object *o;
-
-                       br = kzalloc(sizeof(*br), GFP_KERNEL);
-                       if (!br) {
-                               printk(KERN_ERR "can't allocate memory\n");
-                       } else {
-                               br->levels = kmalloc(obj->package.count *
-                                                    sizeof *(br->levels), GFP_KERNEL);
-                               if (!br->levels)
-                                       goto out;
-
-                               for (i = 0; i < obj->package.count; i++) {
-                                       o = (union acpi_object *)&obj->package.
-                                           elements[i];
-                                       if (o->type != ACPI_TYPE_INTEGER) {
-                                               printk(KERN_ERR PREFIX "Invalid data\n");
-                                               continue;
-                                       }
-                                       br->levels[count] = (u32) o->integer.value;
-
-                                       if (br->levels[count] > max_level)
-                                               max_level = br->levels[count];
-                                       count++;
-                               }
-                             out:
-                               if (count < 2) {
-                                       kfree(br->levels);
-                                       kfree(br);
-                               } else {
-                                       br->count = count;
-                                       device->brightness = br;
-                                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                                         "found %d brightness levels\n",
-                                                         count));
-                               }
-                       }
-               }
+       if (acpi_video_backlight_support())
+               max_level = acpi_video_init_brightness(device);
 
-       } else {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available LCD brightness level\n"));
-       }
-
-       kfree(obj);
-
-       if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
+       if (device->cap._BCL && device->cap._BCM && max_level > 0) {
+               int result;
                static int count = 0;
                char *name;
                name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
@@ -670,23 +773,53 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                device->backlight = backlight_device_register(name,
                        NULL, device, &acpi_backlight_ops);
                device->backlight->props.max_brightness = device->brightness->count-3;
-               device->backlight->props.brightness = acpi_video_get_brightness(device->backlight);
+               /*
+                * If there exists the _BQC object, the _BQC object will be
+                * called to get the current backlight brightness. Otherwise
+                * the brightness will be set to the maximum.
+                */
+               if (device->cap._BQC)
+                       device->backlight->props.brightness =
+                               acpi_video_get_brightness(device->backlight);
+               else
+                       device->backlight->props.brightness =
+                               device->backlight->props.max_brightness;
                backlight_update_status(device->backlight);
-
                kfree(name);
-       }
-       if (device->cap._DCS && device->cap._DSS){
-               static int count = 0;
-               char *name;
-               name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
-               if (!name)
+
+               device->cdev = thermal_cooling_device_register("LCD",
+                                       device->dev, &video_cooling_ops);
+               if (IS_ERR(device->cdev))
                        return;
-               sprintf(name, "acpi_video%d", count++);
-               device->output_dev = video_output_register(name,
-                               NULL, device, &acpi_output_properties);
-               kfree(name);
+
+               dev_info(&device->dev->dev, "registered as cooling_device%d\n",
+                        device->cdev->id);
+               result = sysfs_create_link(&device->dev->dev.kobj,
+                               &device->cdev->device.kobj,
+                               "thermal_cooling");
+               if (result)
+                       printk(KERN_ERR PREFIX "Create sysfs link\n");
+               result = sysfs_create_link(&device->cdev->device.kobj,
+                               &device->dev->dev.kobj, "device");
+               if (result)
+                       printk(KERN_ERR PREFIX "Create sysfs link\n");
+
+       }
+
+       if (acpi_video_display_switch_support()) {
+
+               if (device->cap._DCS && device->cap._DSS) {
+                       static int count;
+                       char *name;
+                       name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
+                       if (!name)
+                               return;
+                       sprintf(name, "acpi_video%d", count++);
+                       device->output_dev = video_output_register(name,
+                                       NULL, device, &acpi_output_properties);
+                       kfree(name);
+               }
        }
-       return;
 }
 
 /*
@@ -732,11 +865,16 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
 static int acpi_video_bus_check(struct acpi_video_bus *video)
 {
        acpi_status status = -ENOENT;
-
+       struct device *dev;
 
        if (!video)
                return -EINVAL;
 
+       dev = acpi_get_physical_pci_device(video->device->handle);
+       if (!dev)
+               return -ENODEV;
+       put_device(dev);
+
        /* Since there is no HID, CID and so on for VGA driver, we have
         * to check well known required nodes.
         */
@@ -808,7 +946,7 @@ static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
 {
        int status;
        struct acpi_video_device *dev = seq->private;
-       unsigned long state;
+       unsigned long long state;
 
 
        if (!dev)
@@ -817,14 +955,14 @@ static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
        status = acpi_video_device_get_state(dev, &state);
        seq_printf(seq, "state:     ");
        if (ACPI_SUCCESS(status))
-               seq_printf(seq, "0x%02lx\n", state);
+               seq_printf(seq, "0x%02llx\n", state);
        else
                seq_printf(seq, "<not supported>\n");
 
        status = acpi_video_device_query(dev, &state);
        seq_printf(seq, "query:     ");
        if (ACPI_SUCCESS(status))
-               seq_printf(seq, "0x%02lx\n", state);
+               seq_printf(seq, "0x%02llx\n", state);
        else
                seq_printf(seq, "<not supported>\n");
 
@@ -882,7 +1020,7 @@ acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset)
        }
 
        seq_printf(seq, "levels: ");
-       for (i = 0; i < dev->brightness->count; i++)
+       for (i = 2; i < dev->brightness->count; i++)
                seq_printf(seq, " %d", dev->brightness->levels[i]);
        seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
 
@@ -921,7 +1059,7 @@ acpi_video_device_write_brightness(struct file *file,
                return -EFAULT;
 
        /* validate through the list of available levels */
-       for (i = 0; i < dev->brightness->count; i++)
+       for (i = 2; i < dev->brightness->count; i++)
                if (level == dev->brightness->levels[i]) {
                        if (ACPI_SUCCESS
                            (acpi_video_device_lcd_set_level(dev, level)))
@@ -975,87 +1113,82 @@ acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file)
 
 static int acpi_video_device_add_fs(struct acpi_device *device)
 {
-       struct proc_dir_entry *entry = NULL;
+       struct proc_dir_entry *entry, *device_dir;
        struct acpi_video_device *vid_dev;
 
-
-       if (!device)
-               return -ENODEV;
-
        vid_dev = acpi_driver_data(device);
        if (!vid_dev)
                return -ENODEV;
 
-       if (!acpi_device_dir(device)) {
-               acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
-                                                    vid_dev->video->dir);
-               if (!acpi_device_dir(device))
-                       return -ENODEV;
-               acpi_device_dir(device)->owner = THIS_MODULE;
-       }
+       device_dir = proc_mkdir(acpi_device_bid(device),
+                               vid_dev->video->dir);
+       if (!device_dir)
+               return -ENOMEM;
+
+       device_dir->owner = THIS_MODULE;
 
        /* 'info' [R] */
-       entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data("info", S_IRUGO, device_dir,
+                       &acpi_video_device_info_fops, acpi_driver_data(device));
        if (!entry)
-               return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_video_device_info_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
+               goto err_remove_dir;
 
        /* 'state' [R/W] */
-       entry =
-           create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR,
-                             acpi_device_dir(device));
+       acpi_video_device_state_fops.write = acpi_video_device_write_state;
+       entry = proc_create_data("state", S_IFREG | S_IRUGO | S_IWUSR,
+                                device_dir,
+                                &acpi_video_device_state_fops,
+                                acpi_driver_data(device));
        if (!entry)
-               return -ENODEV;
-       else {
-               acpi_video_device_state_fops.write = acpi_video_device_write_state;
-               entry->proc_fops = &acpi_video_device_state_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
+               goto err_remove_info;
 
        /* 'brightness' [R/W] */
-       entry =
-           create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR,
-                             acpi_device_dir(device));
+       acpi_video_device_brightness_fops.write =
+               acpi_video_device_write_brightness;
+       entry = proc_create_data("brightness", S_IFREG | S_IRUGO | S_IWUSR,
+                                device_dir,
+                                &acpi_video_device_brightness_fops,
+                                acpi_driver_data(device));
        if (!entry)
-               return -ENODEV;
-       else {
-               acpi_video_device_brightness_fops.write = acpi_video_device_write_brightness;
-               entry->proc_fops = &acpi_video_device_brightness_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
+               goto err_remove_state;
 
        /* 'EDID' [R] */
-       entry = create_proc_entry("EDID", S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data("EDID", S_IRUGO, device_dir,
+                                &acpi_video_device_EDID_fops,
+                                acpi_driver_data(device));
        if (!entry)
-               return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_video_device_EDID_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
+               goto err_remove_brightness;
+
+       acpi_device_dir(device) = device_dir;
 
        return 0;
+
+ err_remove_brightness:
+       remove_proc_entry("brightness", device_dir);
+ err_remove_state:
+       remove_proc_entry("state", device_dir);
+ err_remove_info:
+       remove_proc_entry("info", device_dir);
+ err_remove_dir:
+       remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
+       return -ENOMEM;
 }
 
 static int acpi_video_device_remove_fs(struct acpi_device *device)
 {
        struct acpi_video_device *vid_dev;
+       struct proc_dir_entry *device_dir;
 
        vid_dev = acpi_driver_data(device);
        if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
                return -ENODEV;
 
-       if (acpi_device_dir(device)) {
-               remove_proc_entry("info", acpi_device_dir(device));
-               remove_proc_entry("state", acpi_device_dir(device));
-               remove_proc_entry("brightness", acpi_device_dir(device));
-               remove_proc_entry("EDID", acpi_device_dir(device));
+       device_dir = acpi_device_dir(device);
+       if (device_dir) {
+               remove_proc_entry("info", device_dir);
+               remove_proc_entry("state", device_dir);
+               remove_proc_entry("brightness", device_dir);
+               remove_proc_entry("EDID", device_dir);
                remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
                acpi_device_dir(device) = NULL;
        }
@@ -1097,7 +1230,7 @@ static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset)
        if (!video)
                goto end;
 
-       printk(KERN_INFO PREFIX "Please implement %s\n", __FUNCTION__);
+       printk(KERN_INFO PREFIX "Please implement %s\n", __func__);
        seq_printf(seq, "<TODO>\n");
 
       end:
@@ -1112,7 +1245,7 @@ static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file)
 static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
 {
        struct acpi_video_bus *video = seq->private;
-       unsigned long options;
+       unsigned long long options;
        int status;
 
 
@@ -1127,7 +1260,7 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
                        printk(KERN_WARNING PREFIX
                               "This indicates a BIOS bug. Please contact the manufacturer.\n");
                }
-               printk("%lx\n", options);
+               printk(KERN_WARNING "%llx\n", options);
                seq_printf(seq, "can POST: <integrated video>");
                if (options & 2)
                        seq_printf(seq, " <PCI video>");
@@ -1151,7 +1284,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
 {
        struct acpi_video_bus *video = seq->private;
        int status;
-       unsigned long id;
+       unsigned long long id;
 
 
        if (!video)
@@ -1198,7 +1331,7 @@ acpi_video_bus_write_POST(struct file *file,
        struct seq_file *m = file->private_data;
        struct acpi_video_bus *video = m->private;
        char str[12] = { 0 };
-       unsigned long opt, options;
+       unsigned long long opt, options;
 
 
        if (!video || count + 1 > sizeof str)
@@ -1262,123 +1395,81 @@ acpi_video_bus_write_DOS(struct file *file,
 
 static int acpi_video_bus_add_fs(struct acpi_device *device)
 {
-       long device_id;
-       int status;
-       struct proc_dir_entry *entry = NULL;
-       struct acpi_video_bus *video;
-       struct device *dev;
+       struct acpi_video_bus *video = acpi_driver_data(device);
+       struct proc_dir_entry *device_dir;
+       struct proc_dir_entry *entry;
 
-       status =
-           acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id);
-
-       if (!ACPI_SUCCESS(status))
-               return -ENODEV;
-
-       /* We need to attempt to determine whether the _ADR refers to a
-          PCI device or not. There's no terribly good way to do this,
-          so the best we can hope for is to assume that there'll never
-          be a video device in the host bridge */
-       if (device_id >= 0x10000) {
-               /* It looks like a PCI device. Does it exist? */
-               dev = acpi_get_physical_device(device->handle);
-       } else {
-               /* It doesn't look like a PCI device. Does its parent
-                  exist? */
-               acpi_handle phandle;
-               if (acpi_get_parent(device->handle, &phandle))
-                       return -ENODEV;
-               dev = acpi_get_physical_device(phandle);
-       }
-       if (!dev)
-               return -ENODEV;
-       put_device(dev);
-
-
-
-       video = acpi_driver_data(device);
+       device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir);
+       if (!device_dir)
+               return -ENOMEM;
 
-       if (!acpi_device_dir(device)) {
-               acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
-                                                    acpi_video_dir);
-               if (!acpi_device_dir(device))
-                       return -ENODEV;
-               video->dir = acpi_device_dir(device);
-               acpi_device_dir(device)->owner = THIS_MODULE;
-       }
+       device_dir->owner = THIS_MODULE;
 
        /* 'info' [R] */
-       entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data("info", S_IRUGO, device_dir,
+                                &acpi_video_bus_info_fops,
+                                acpi_driver_data(device));
        if (!entry)
-               return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_video_bus_info_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
+               goto err_remove_dir;
 
        /* 'ROM' [R] */
-       entry = create_proc_entry("ROM", S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data("ROM", S_IRUGO, device_dir,
+                                &acpi_video_bus_ROM_fops,
+                                acpi_driver_data(device));
        if (!entry)
-               return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_video_bus_ROM_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
+               goto err_remove_info;
 
        /* 'POST_info' [R] */
-       entry =
-           create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data("POST_info", S_IRUGO, device_dir,
+                                &acpi_video_bus_POST_info_fops,
+                                acpi_driver_data(device));
        if (!entry)
-               return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_video_bus_POST_info_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
+               goto err_remove_rom;
 
        /* 'POST' [R/W] */
-       entry =
-           create_proc_entry("POST", S_IFREG | S_IRUGO | S_IRUSR,
-                             acpi_device_dir(device));
+       acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
+       entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR,
+                                device_dir,
+                                &acpi_video_bus_POST_fops,
+                                acpi_driver_data(device));
        if (!entry)
-               return -ENODEV;
-       else {
-               acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
-               entry->proc_fops = &acpi_video_bus_POST_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
+               goto err_remove_post_info;
 
        /* 'DOS' [R/W] */
-       entry =
-           create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IRUSR,
-                             acpi_device_dir(device));
+       acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
+       entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR,
+                                device_dir,
+                                &acpi_video_bus_DOS_fops,
+                                acpi_driver_data(device));
        if (!entry)
-               return -ENODEV;
-       else {
-               acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
-               entry->proc_fops = &acpi_video_bus_DOS_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
+               goto err_remove_post;
 
+       video->dir = acpi_device_dir(device) = device_dir;
        return 0;
+
+ err_remove_post:
+       remove_proc_entry("POST", device_dir);
+ err_remove_post_info:
+       remove_proc_entry("POST_info", device_dir);
+ err_remove_rom:
+       remove_proc_entry("ROM", device_dir);
+ err_remove_info:
+       remove_proc_entry("info", device_dir);
+ err_remove_dir:
+       remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
+       return -ENOMEM;
 }
 
 static int acpi_video_bus_remove_fs(struct acpi_device *device)
 {
-       struct acpi_video_bus *video;
-
-
-       video = acpi_driver_data(device);
-
-       if (acpi_device_dir(device)) {
-               remove_proc_entry("info", acpi_device_dir(device));
-               remove_proc_entry("ROM", acpi_device_dir(device));
-               remove_proc_entry("POST_info", acpi_device_dir(device));
-               remove_proc_entry("POST", acpi_device_dir(device));
-               remove_proc_entry("DOS", acpi_device_dir(device));
+       struct proc_dir_entry *device_dir = acpi_device_dir(device);
+
+       if (device_dir) {
+               remove_proc_entry("info", device_dir);
+               remove_proc_entry("ROM", device_dir);
+               remove_proc_entry("POST_info", device_dir);
+               remove_proc_entry("POST", device_dir);
+               remove_proc_entry("DOS", device_dir);
                remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
                acpi_device_dir(device) = NULL;
        }
@@ -1394,11 +1485,15 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device)
 static struct acpi_video_device_attrib*
 acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id)
 {
-       int count;
+       struct acpi_video_enumerated_device *ids;
+       int i;
+
+       for (i = 0; i < video->attached_count; i++) {
+               ids = &video->attached_array[i];
+               if ((ids->value.int_val & 0xffff) == device_id)
+                       return &ids->value.attrib;
+       }
 
-       for(count = 0; count < video->attached_count; count++)
-               if((video->attached_array[count].value.int_val & 0xffff) == device_id)
-                       return &(video->attached_array[count].value.attrib);
        return NULL;
 }
 
@@ -1406,7 +1501,7 @@ static int
 acpi_video_bus_get_one_device(struct acpi_device *device,
                              struct acpi_video_bus *video)
 {
-       unsigned long device_id;
+       unsigned long long device_id;
        int status;
        struct acpi_video_device *data;
        struct acpi_video_device_attrib* attribute;
@@ -1424,7 +1519,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
 
                strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME);
                strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
-               acpi_driver_data(device) = data;
+               device->driver_data = data;
 
                data->device_id = device_id;
                data->video = video;
@@ -1463,8 +1558,8 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
                                                     acpi_video_device_notify,
                                                     data);
                if (ACPI_FAILURE(status)) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "Error installing notify handler\n"));
+                       printk(KERN_ERR PREFIX
+                                         "Error installing notify handler\n");
                        if(data->brightness)
                                kfree(data->brightness->levels);
                        kfree(data->brightness);
@@ -1525,20 +1620,16 @@ static void
 acpi_video_device_bind(struct acpi_video_bus *video,
                       struct acpi_video_device *device)
 {
+       struct acpi_video_enumerated_device *ids;
        int i;
 
-#define IDS_VAL(i) video->attached_array[i].value.int_val
-#define IDS_BIND(i) video->attached_array[i].bind_info
-
-       for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID &&
-            i < video->attached_count; i++) {
-               if (device->device_id == (IDS_VAL(i) & 0xffff)) {
-                       IDS_BIND(i) = device;
+       for (i = 0; i < video->attached_count; i++) {
+               ids = &video->attached_array[i];
+               if (device->device_id == (ids->value.int_val & 0xffff)) {
+                       ids->bind_info = device;
                        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i));
                }
        }
-#undef IDS_VAL
-#undef IDS_BIND
 }
 
 /*
@@ -1557,7 +1648,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
        int status;
        int count;
        int i;
-       struct acpi_video_enumerated_device *active_device_list;
+       struct acpi_video_enumerated_device *active_list;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *dod = NULL;
        union acpi_object *obj;
@@ -1578,13 +1669,10 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n",
                          dod->package.count));
 
-       active_device_list = kmalloc((1 +
-                                     dod->package.count) *
-                                    sizeof(struct
-                                           acpi_video_enumerated_device),
-                                    GFP_KERNEL);
-
-       if (!active_device_list) {
+       active_list = kcalloc(1 + dod->package.count,
+                             sizeof(struct acpi_video_enumerated_device),
+                             GFP_KERNEL);
+       if (!active_list) {
                status = -ENOMEM;
                goto out;
        }
@@ -1594,82 +1682,25 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
                obj = &dod->package.elements[i];
 
                if (obj->type != ACPI_TYPE_INTEGER) {
-                       printk(KERN_ERR PREFIX "Invalid _DOD data\n");
-                       active_device_list[i].value.int_val =
-                           ACPI_VIDEO_HEAD_INVALID;
+                       printk(KERN_ERR PREFIX
+                               "Invalid _DOD data in element %d\n", i);
+                       continue;
                }
-               active_device_list[i].value.int_val = obj->integer.value;
-               active_device_list[i].bind_info = NULL;
+
+               active_list[count].value.int_val = obj->integer.value;
+               active_list[count].bind_info = NULL;
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i,
                                  (int)obj->integer.value));
                count++;
        }
-       active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END;
 
        kfree(video->attached_array);
 
-       video->attached_array = active_device_list;
+       video->attached_array = active_list;
        video->attached_count = count;
-      out:
-       kfree(buffer.pointer);
-       return status;
-}
-
-/*
- *  Arg:
- *     video   : video bus device 
- *     event   : notify event
- *
- *  Return:
- *     < 0     : error
- *  
- *     1. Find out the current active output device.
- *     2. Identify the next output device to switch to.
- *     3. call _DSS to do actual switch.
- */
-
-static int acpi_video_switch_output(struct acpi_video_bus *video, int event)
-{
-       struct list_head *node;
-       struct acpi_video_device *dev = NULL;
-       struct acpi_video_device *dev_next = NULL;
-       struct acpi_video_device *dev_prev = NULL;
-       unsigned long state;
-       int status = 0;
-
-       mutex_lock(&video->device_list_lock);
-
-       list_for_each(node, &video->video_device_list) {
-               dev = container_of(node, struct acpi_video_device, entry);
-               status = acpi_video_device_get_state(dev, &state);
-               if (state & 0x2) {
-                       dev_next = container_of(node->next,
-                                       struct acpi_video_device, entry);
-                       dev_prev = container_of(node->prev,
-                                       struct acpi_video_device, entry);
-                       goto out;
-               }
-       }
-
-       dev_next = container_of(node->next, struct acpi_video_device, entry);
-       dev_prev = container_of(node->prev, struct acpi_video_device, entry);
 
  out:
-       mutex_unlock(&video->device_list_lock);
-
-       switch (event) {
-       case ACPI_VIDEO_NOTIFY_CYCLE:
-       case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
-               acpi_video_device_set_state(dev, 0);
-               acpi_video_device_set_state(dev_next, 0x80000001);
-               break;
-       case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:
-               acpi_video_device_set_state(dev, 0);
-               acpi_video_device_set_state(dev_prev, 0x80000001);
-       default:
-               break;
-       }
-
+       kfree(buffer.pointer);
        return status;
 }
 
@@ -1681,7 +1712,7 @@ acpi_video_get_next_level(struct acpi_video_device *device,
        max = max_below = 0;
        min = min_above = 255;
        /* Find closest level to level_current */
-       for (i = 0; i < device->brightness->count; i++) {
+       for (i = 2; i < device->brightness->count; i++) {
                l = device->brightness->levels[i];
                if (abs(l - level_current) < abs(delta)) {
                        delta = l - level_current;
@@ -1691,7 +1722,7 @@ acpi_video_get_next_level(struct acpi_video_device *device,
        }
        /* Ajust level_current to closest available level */
        level_current += delta;
-       for (i = 0; i < device->brightness->count; i++) {
+       for (i = 2; i < device->brightness->count; i++) {
                l = device->brightness->levels[i];
                if (l < min)
                        min = l;
@@ -1721,7 +1752,9 @@ acpi_video_get_next_level(struct acpi_video_device *device,
 static void
 acpi_video_switch_brightness(struct acpi_video_device *device, int event)
 {
-       unsigned long level_current, level_next;
+       unsigned long long level_current, level_next;
+       if (!device->brightness)
+               return;
        acpi_video_device_lcd_get_level_current(device, &level_current);
        level_next = acpi_video_get_next_level(device, level_current, event);
        acpi_video_device_lcd_set_level(device, level_next);
@@ -1740,7 +1773,8 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video,
 
                status = acpi_video_bus_get_one_device(dev, video);
                if (ACPI_FAILURE(status)) {
-                       ACPI_EXCEPTION((AE_INFO, status, "Cant attach device"));
+                       printk(KERN_WARNING PREFIX
+                                       "Cant attach device");
                        continue;
                }
        }
@@ -1764,6 +1798,14 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
                                            ACPI_DEVICE_NOTIFY,
                                            acpi_video_device_notify);
        backlight_device_unregister(device->backlight);
+       if (device->cdev) {
+               sysfs_remove_link(&device->dev->dev.kobj,
+                                 "thermal_cooling");
+               sysfs_remove_link(&device->cdev->device.kobj,
+                                 "device");
+               thermal_cooling_device_unregister(device->cdev);
+               device->cdev = NULL;
+       }
        video_output_unregister(device->output_dev);
 
        return 0;
@@ -1832,23 +1874,19 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
                                         * connector. */
                acpi_video_device_enumerate(video);
                acpi_video_device_rebind(video);
-               acpi_video_switch_output(video, event);
                acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_SWITCHVIDEOMODE;
                break;
 
        case ACPI_VIDEO_NOTIFY_CYCLE:   /* Cycle Display output hotkey pressed. */
-               acpi_video_switch_output(video, event);
                acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_SWITCHVIDEOMODE;
                break;
        case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:     /* Next Display output hotkey pressed. */
-               acpi_video_switch_output(video, event);
                acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_VIDEO_NEXT;
                break;
        case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:     /* previous Display output hotkey pressed. */
-               acpi_video_switch_output(video, event);
                acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_VIDEO_PREV;
                break;
@@ -1860,6 +1898,7 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
                break;
        }
 
+       acpi_notifier_call_chain(device, event, 0);
        input_report_key(input, keycode, 1);
        input_sync(input);
        input_report_key(input, keycode, 0);
@@ -1885,27 +1924,32 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
 
        switch (event) {
        case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS:        /* Cycle brightness */
-               acpi_video_switch_brightness(video_device, event);
+               if (brightness_switch_enabled)
+                       acpi_video_switch_brightness(video_device, event);
                acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_BRIGHTNESS_CYCLE;
                break;
        case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS:  /* Increase brightness */
-               acpi_video_switch_brightness(video_device, event);
+               if (brightness_switch_enabled)
+                       acpi_video_switch_brightness(video_device, event);
                acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_BRIGHTNESSUP;
                break;
        case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS:  /* Decrease brightness */
-               acpi_video_switch_brightness(video_device, event);
+               if (brightness_switch_enabled)
+                       acpi_video_switch_brightness(video_device, event);
                acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_BRIGHTNESSDOWN;
                break;
        case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */
-               acpi_video_switch_brightness(video_device, event);
+               if (brightness_switch_enabled)
+                       acpi_video_switch_brightness(video_device, event);
                acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_BRIGHTNESS_ZERO;
                break;
        case ACPI_VIDEO_NOTIFY_DISPLAY_OFF:     /* display device off */
-               acpi_video_switch_brightness(video_device, event);
+               if (brightness_switch_enabled)
+                       acpi_video_switch_brightness(video_device, event);
                acpi_bus_generate_proc_event(device, event, 0);
                keycode = KEY_DISPLAY_OFF;
                break;
@@ -1916,6 +1960,7 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
                break;
        }
 
+       acpi_notifier_call_chain(device, event, 0);
        input_report_key(input, keycode, 1);
        input_sync(input);
        input_report_key(input, keycode, 0);
@@ -1925,6 +1970,25 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
 }
 
 static int instance;
+static int acpi_video_resume(struct acpi_device *device)
+{
+       struct acpi_video_bus *video;
+       struct acpi_video_device *video_device;
+       int i;
+
+       if (!device || !acpi_driver_data(device))
+               return -EINVAL;
+
+       video = acpi_driver_data(device);
+
+       for (i = 0; i < video->attached_count; i++) {
+               video_device = video->attached_array[i].bind_info;
+               if (video_device && video_device->backlight)
+                       acpi_video_set_brightness(video_device->backlight);
+       }
+       return AE_OK;
+}
+
 static int acpi_video_bus_add(struct acpi_device *device)
 {
        acpi_status status;
@@ -1942,11 +2006,17 @@ static int acpi_video_bus_add(struct acpi_device *device)
                        device->pnp.bus_id[3] = '0' + instance;
                instance ++;
        }
+       /* a hack to fix the duplicate name "VGA" problem on Pa 3553 */
+       if (!strcmp(device->pnp.bus_id, "VGA")) {
+               if (instance)
+                       device->pnp.bus_id[3] = '0' + instance;
+               instance++;
+       }
 
        video->device = device;
        strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
        strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS);
-       acpi_driver_data(device) = video;
+       device->driver_data = video;
 
        acpi_video_bus_find_cap(video);
        error = acpi_video_bus_check(video);
@@ -1967,8 +2037,8 @@ static int acpi_video_bus_add(struct acpi_device *device)
                                             ACPI_DEVICE_NOTIFY,
                                             acpi_video_bus_notify, video);
        if (ACPI_FAILURE(status)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "Error installing notify handler\n"));
+               printk(KERN_ERR PREFIX
+                                 "Error installing notify handler\n");
                error = -ENODEV;
                goto err_stop_video;
        }
@@ -2022,7 +2092,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
        acpi_video_bus_remove_fs(device);
  err_free_video:
        kfree(video);
-       acpi_driver_data(device) = NULL;
+       device->driver_data = NULL;
 
        return error;
 }
@@ -2058,12 +2128,6 @@ static int __init acpi_video_init(void)
 {
        int result = 0;
 
-
-       /*
-          acpi_dbg_level = 0xFFFFFFFF;
-          acpi_dbg_layer = 0x08000000;
-        */
-
        acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
        if (!acpi_video_dir)
                return -ENODEV;