toshiba_acpi: Only register backlight device when interface is read/write
authorSeth Forshee <seth.forshee@canonical.com>
Thu, 19 Apr 2012 16:23:50 +0000 (11:23 -0500)
committerMatthew Garrett <mjg@redhat.com>
Thu, 31 May 2012 18:26:04 +0000 (14:26 -0400)
Currently the backlight device is registered unconditionally, but many
(probably most) Toshibas either don't support HCI_LCD_BRIGHTNESS or only
support reading from it. This patch adds a test of HCI_LCD_BRIGHTNESS
during initialization and only registers the backlight device if this
interface supports both reads and writes.

Cc: Akio Idehara <zbe64533@gmail.com>
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
drivers/platform/x86/toshiba_acpi.c

index 57787d87d9a4780df7e6d3a5d757aa7179545445..1bb128bbcfc98c26e595af0dbc98178668cd0959 100644 (file)
@@ -480,9 +480,8 @@ static const struct rfkill_ops toshiba_rfk_ops = {
 
 static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
 
-static int get_lcd(struct backlight_device *bd)
+static int __get_lcd_brightness(struct toshiba_acpi_dev *dev)
 {
-       struct toshiba_acpi_dev *dev = bl_get_data(bd);
        u32 hci_result;
        u32 value;
 
@@ -493,6 +492,12 @@ static int get_lcd(struct backlight_device *bd)
        return -EIO;
 }
 
+static int get_lcd_brightness(struct backlight_device *bd)
+{
+       struct toshiba_acpi_dev *dev = bl_get_data(bd);
+       return __get_lcd_brightness(dev);
+}
+
 static int lcd_proc_show(struct seq_file *m, void *v)
 {
        struct toshiba_acpi_dev *dev = m->private;
@@ -501,7 +506,7 @@ static int lcd_proc_show(struct seq_file *m, void *v)
        if (!dev->backlight_dev)
                return -ENODEV;
 
-       value = get_lcd(dev->backlight_dev);
+       value = get_lcd_brightness(dev->backlight_dev);
        if (value >= 0) {
                seq_printf(m, "brightness:              %d\n", value);
                seq_printf(m, "brightness_levels:       %d\n",
@@ -518,7 +523,7 @@ static int lcd_proc_open(struct inode *inode, struct file *file)
        return single_open(file, lcd_proc_show, PDE(inode)->data);
 }
 
-static int set_lcd(struct toshiba_acpi_dev *dev, int value)
+static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value)
 {
        u32 hci_result;
 
@@ -530,7 +535,7 @@ static int set_lcd(struct toshiba_acpi_dev *dev, int value)
 static int set_lcd_status(struct backlight_device *bd)
 {
        struct toshiba_acpi_dev *dev = bl_get_data(bd);
-       return set_lcd(dev, bd->props.brightness);
+       return set_lcd_brightness(dev, bd->props.brightness);
 }
 
 static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
@@ -549,7 +554,7 @@ static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
 
        if (sscanf(cmd, " brightness : %i", &value) == 1 &&
            value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
-               ret = set_lcd(dev, value);
+               ret = set_lcd_brightness(dev, value);
                if (ret == 0)
                        ret = count;
        } else {
@@ -860,8 +865,8 @@ static void remove_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
 }
 
 static const struct backlight_ops toshiba_backlight_data = {
-        .get_brightness = get_lcd,
-        .update_status  = set_lcd_status,
+       .get_brightness = get_lcd_brightness,
+       .update_status  = set_lcd_status,
 };
 
 static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str,
@@ -1020,6 +1025,47 @@ static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
        return error;
 }
 
+static int __devinit toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev)
+{
+       struct backlight_properties props;
+       int brightness;
+       int ret;
+
+       /*
+        * Some machines don't support the backlight methods at all, and
+        * others support it read-only. Either of these is pretty useless,
+        * so only register the backlight device if the backlight method
+        * supports both reads and writes.
+        */
+       brightness = __get_lcd_brightness(dev);
+       if (brightness < 0)
+               return 0;
+       ret = set_lcd_brightness(dev, brightness);
+       if (ret) {
+               pr_debug("Backlight method is read-only, disabling backlight support\n");
+               return 0;
+       }
+
+       props.type = BACKLIGHT_PLATFORM;
+       props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
+       memset(&props, 0, sizeof(props));
+
+       dev->backlight_dev = backlight_device_register("toshiba",
+                                                      &dev->acpi_dev->dev,
+                                                      dev,
+                                                      &toshiba_backlight_data,
+                                                      &props);
+       if (IS_ERR(dev->backlight_dev)) {
+               ret = PTR_ERR(dev->backlight_dev);
+               pr_err("Could not register toshiba backlight device\n");
+               dev->backlight_dev = NULL;
+               return ret;
+       }
+
+       dev->backlight_dev->props.brightness = brightness;
+       return 0;
+}
+
 static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type)
 {
        struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
@@ -1078,7 +1124,6 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
        u32 dummy;
        bool bt_present;
        int ret = 0;
-       struct backlight_properties props;
 
        if (toshiba_acpi)
                return -EBUSY;
@@ -1104,22 +1149,9 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
 
        mutex_init(&dev->mutex);
 
-       memset(&props, 0, sizeof(props));
-       props.type = BACKLIGHT_PLATFORM;
-       props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
-       dev->backlight_dev = backlight_device_register("toshiba",
-                                                      &acpi_dev->dev,
-                                                      dev,
-                                                      &toshiba_backlight_data,
-                                                      &props);
-       if (IS_ERR(dev->backlight_dev)) {
-               ret = PTR_ERR(dev->backlight_dev);
-
-               pr_err("Could not register toshiba backlight device\n");
-               dev->backlight_dev = NULL;
+       ret = toshiba_acpi_setup_backlight(dev);
+       if (ret)
                goto error;
-       }
-       dev->backlight_dev->props.brightness = get_lcd(dev->backlight_dev);
 
        /* Register rfkill switch for Bluetooth */
        if (hci_get_bt_present(dev, &bt_present) == HCI_SUCCESS && bt_present) {