]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/acpi/video.c
Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-backlight
[karo-tx-linux.git] / drivers / acpi / video.c
index bf525cca3b637160a3c1b28f95269ea108c1dfd3..04ea697f72bff00b94cc2d1151df53d8b5d93e1e 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/seq_file.h>
 
 #include <linux/backlight.h>
+#include <linux/video_output.h>
 #include <asm/uaccess.h>
 
 #include <acpi/acpi_bus.h>
@@ -102,9 +103,9 @@ struct acpi_video_bus_cap {
 
 struct acpi_video_device_attrib {
        u32 display_index:4;    /* A zero-based instance of the Display */
-       u32 display_port_attachment:4;  /*This field differenates displays type */
+       u32 display_port_attachment:4;  /*This field differentiates the display type */
        u32 display_type:4;     /*Describe the specific type in use */
-       u32 vendor_specific:4;  /*Chipset Vendor Specifi */
+       u32 vendor_specific:4;  /*Chipset Vendor Specific */
        u32 bios_can_detect:1;  /*BIOS can detect the device */
        u32 depend_on_vga:1;    /*Non-VGA output device whose power is related to 
                                   the VGA device. */
@@ -169,7 +170,7 @@ struct acpi_video_device {
        struct acpi_device *dev;
        struct acpi_video_device_brightness *brightness;
        struct backlight_device *backlight;
-       struct backlight_properties *data;
+       struct output_device *output_dev;
 };
 
 /* bus */
@@ -273,26 +274,57 @@ 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);
+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;
        struct acpi_video_device *vd =
-               (struct acpi_video_device *)class_get_devdata(&bd->class_dev);
+               (struct acpi_video_device *)bl_get_data(bd);
        acpi_video_device_lcd_get_level_current(vd, &cur_level);
        return (int) cur_level;
 }
 
 static int acpi_video_set_brightness(struct backlight_device *bd)
 {
-       int request_level = bd->props->brightness;
+       int request_level = bd->props.brightness;
        struct acpi_video_device *vd =
-               (struct acpi_video_device *)class_get_devdata(&bd->class_dev);
+               (struct acpi_video_device *)bl_get_data(bd);
        acpi_video_device_lcd_set_level(vd, request_level);
        return 0;
 }
 
+static struct backlight_ops acpi_backlight_ops = {
+       .get_brightness = acpi_video_get_brightness,
+       .update_status  = acpi_video_set_brightness,
+};
+
+/*video output device sysfs support*/
+static int acpi_video_output_get(struct output_device *od)
+{
+       unsigned long state;
+       struct acpi_video_device *vd =
+               (struct acpi_video_device *)class_get_devdata(&od->class_dev);
+       acpi_video_device_get_state(vd, &state);
+       return (int)state;
+}
+
+static int acpi_video_output_set(struct output_device *od)
+{
+       unsigned long state = od->request_state;
+       struct acpi_video_device *vd=
+               (struct acpi_video_device *)class_get_devdata(&od->class_dev);
+       return acpi_video_device_set_state(vd, state);
+}
+
+static struct output_properties acpi_output_properties = {
+       .set_state = acpi_video_output_set,
+       .get_status = acpi_video_output_get,
+};
 /* --------------------------------------------------------------------------
                                Video Management
    -------------------------------------------------------------------------- */
@@ -480,16 +512,16 @@ acpi_video_bus_POST_options(struct acpi_video_bus *video,
  *             0.      The system BIOS should NOT automatically switch(toggle)
  *                     the active display output.
  *             1.      The system BIOS should automatically switch (toggle) the
- *                     active display output. No swich event.
+ *                     active display output. No switch event.
  *             2.      The _DGS value should be locked.
  *             3.      The system BIOS should not automatically switch (toggle) the
  *                     active display output, but instead generate the display switch
  *                     event notify code.
  *     lcd_flag        :
  *             0.      The system BIOS should automatically control the brightness level
- *                     of the LCD, when the power changes from AC to DC
+ *                     of the LCD when the power changes from AC to DC
  *             1.      The system BIOS should NOT automatically control the brightness 
- *                     level of the LCD, when the power changes from AC to DC.
+ *                     level of the LCD when the power changes from AC to DC.
  * Return Value:
  *             -1      wrong arg.
  */
@@ -521,13 +553,12 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
  *  Return Value:
  *     None
  *
- *  Find out all required AML method defined under the output
+ *  Find out all required AML methods defined under the output
  *  device.
  */
 
 static void acpi_video_device_find_cap(struct acpi_video_device *device)
 {
-       acpi_integer status;
        acpi_handle h_dummy1;
        int i;
        u32 max_level = 0;
@@ -561,78 +592,81 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
                device->cap._DSS = 1;
        }
 
-       status = acpi_video_device_lcd_query_levels(device, &obj);
-
-       if (obj && obj->type == ACPI_TYPE_PACKAGE && 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);
+       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->count = count;
-                               device->brightness = br;
-                               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                                 "found %d brightness levels\n",
-                                                 count));
+                               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));
+                               }
                        }
                }
+
+       } 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){
+       if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
                unsigned long tmp;
                static int count = 0;
                char *name;
-               struct backlight_properties *acpi_video_data;
-
                name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
                if (!name)
                        return;
 
-               acpi_video_data = kzalloc(
-                       sizeof(struct backlight_properties),
-                       GFP_KERNEL);
-               if (!acpi_video_data){
-                       kfree(name);
-                       return;
-               }
-               acpi_video_data->owner = THIS_MODULE;
-               acpi_video_data->get_brightness =
-                       acpi_video_get_brightness;
-               acpi_video_data->update_status =
-                       acpi_video_set_brightness;
                sprintf(name, "acpi_video%d", count++);
-               device->data = acpi_video_data;
-               acpi_video_data->max_brightness = max_level;
                acpi_video_device_lcd_get_level_current(device, &tmp);
-               acpi_video_data->brightness = (int)tmp;
                device->backlight = backlight_device_register(name,
-                       NULL, device, acpi_video_data);
+                       NULL, device, &acpi_backlight_ops);
+               device->backlight->props.max_brightness = max_level;
+               device->backlight->props.brightness = (int)tmp;
+               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)
+                       return;
+               sprintf(name, "acpi_video%d", count++);
+               device->output_dev = video_output_register(name,
+                               NULL, device, &acpi_output_properties);
                kfree(name);
        }
        return;
@@ -645,7 +679,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
  *  Return Value:
  *     None
  *
- *  Find out all required AML method defined under the video bus device.
+ *  Find out all required AML methods defined under the video bus device.
  */
 
 static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
@@ -690,19 +724,19 @@ static int acpi_video_bus_check(struct acpi_video_bus *video)
         * to check well known required nodes.
         */
 
-       /* Does this device able to support video switching ? */
+       /* Does this device support video switching? */
        if (video->cap._DOS) {
                video->flags.multihead = 1;
                status = 0;
        }
 
-       /* Does this device able to retrieve a retrieve a video ROM ? */
+       /* Does this device support retrieving a video ROM? */
        if (video->cap._ROM) {
                video->flags.rom = 1;
                status = 0;
        }
 
-       /* Does this device able to configure which video device to POST ? */
+       /* Does this device support configuring which video device to POST? */
        if (video->cap._GPD && video->cap._SPD && video->cap._VPO) {
                video->flags.post = 1;
                status = 0;
@@ -869,7 +903,7 @@ acpi_video_device_write_brightness(struct file *file,
        if (level > 100)
                return -EFAULT;
 
-       /* validate though the list of available levels */
+       /* validate through the list of available levels */
        for (i = 0; i < dev->brightness->count; i++)
                if (level == dev->brightness->levels[i]) {
                        if (ACPI_SUCCESS
@@ -1074,10 +1108,10 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
                        printk(KERN_WARNING PREFIX
                               "The motherboard VGA device is not listed as a possible POST device.\n");
                        printk(KERN_WARNING PREFIX
-                              "This indicate a BIOS bug.  Please contact the manufacturer.\n");
+                              "This indicates a BIOS bug. Please contact the manufacturer.\n");
                }
                printk("%lx\n", options);
-               seq_printf(seq, "can POST: <intgrated video>");
+               seq_printf(seq, "can POST: <integrated video>");
                if (options & 2)
                        seq_printf(seq, " <PCI video>");
                if (options & 4)
@@ -1111,7 +1145,7 @@ static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
                seq_printf(seq, "<not supported>\n");
                goto end;
        }
-       seq_printf(seq, "device posted is <%s>\n", device_decode[id & 3]);
+       seq_printf(seq, "device POSTed is <%s>\n", device_decode[id & 3]);
 
       end:
        return 0;
@@ -1165,7 +1199,7 @@ acpi_video_bus_write_POST(struct file *file,
        if (opt > 3)
                return -EFAULT;
 
-       /* just in case an OEM 'forget' the motherboard... */
+       /* just in case an OEM 'forgot' the motherboard... */
        options |= 1;
 
        if (options & (1ul << opt)) {
@@ -1536,13 +1570,13 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
 /*
  *  Arg:
  *     video   : video bus device 
- *     event   : Nontify Event
+ *     event   : notify event
  *
  *  Return:
  *     < 0     : error
  *  
  *     1. Find out the current active output device.
- *     2. Identify the next output device to switch
+ *     2. Identify the next output device to switch to.
  *     3. call _DSS to do actual switch.
  */
 
@@ -1677,10 +1711,8 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
        status = acpi_remove_notify_handler(device->dev->handle,
                                            ACPI_DEVICE_NOTIFY,
                                            acpi_video_device_notify);
-       if (device->backlight){
-               backlight_device_unregister(device->backlight);
-               kfree(device->data);
-       }
+       backlight_device_unregister(device->backlight);
+       video_output_unregister(device->output_dev);
        return 0;
 }
 
@@ -1735,12 +1767,12 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
        device = video->device;
 
        switch (event) {
-       case ACPI_VIDEO_NOTIFY_SWITCH:  /* User request that a switch occur,
+       case ACPI_VIDEO_NOTIFY_SWITCH:  /* User requested a switch,
                                         * most likely via hotkey. */
                acpi_bus_generate_event(device, event, 0);
                break;
 
-       case ACPI_VIDEO_NOTIFY_PROBE:   /* User plug or remove a video
+       case ACPI_VIDEO_NOTIFY_PROBE:   /* User plugged in or removed a video
                                         * connector. */
                acpi_video_device_enumerate(video);
                acpi_video_device_rebind(video);