]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/leds/led-class.c
Merge tag 'armsoc-fixes-nc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm...
[karo-tx-linux.git] / drivers / leds / led-class.c
index 326ee6e925a205531f97f0815451e4af87505ceb..f2b0a80a62b46712a17e642efebd148ea2c99537 100644 (file)
@@ -103,6 +103,68 @@ static const struct attribute_group *led_groups[] = {
        NULL,
 };
 
+#ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED
+static ssize_t brightness_hw_changed_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct led_classdev *led_cdev = dev_get_drvdata(dev);
+
+       if (led_cdev->brightness_hw_changed == -1)
+               return -ENODATA;
+
+       return sprintf(buf, "%u\n", led_cdev->brightness_hw_changed);
+}
+
+static DEVICE_ATTR_RO(brightness_hw_changed);
+
+static int led_add_brightness_hw_changed(struct led_classdev *led_cdev)
+{
+       struct device *dev = led_cdev->dev;
+       int ret;
+
+       ret = device_create_file(dev, &dev_attr_brightness_hw_changed);
+       if (ret) {
+               dev_err(dev, "Error creating brightness_hw_changed\n");
+               return ret;
+       }
+
+       led_cdev->brightness_hw_changed_kn =
+               sysfs_get_dirent(dev->kobj.sd, "brightness_hw_changed");
+       if (!led_cdev->brightness_hw_changed_kn) {
+               dev_err(dev, "Error getting brightness_hw_changed kn\n");
+               device_remove_file(dev, &dev_attr_brightness_hw_changed);
+               return -ENXIO;
+       }
+
+       return 0;
+}
+
+static void led_remove_brightness_hw_changed(struct led_classdev *led_cdev)
+{
+       sysfs_put(led_cdev->brightness_hw_changed_kn);
+       device_remove_file(led_cdev->dev, &dev_attr_brightness_hw_changed);
+}
+
+void led_classdev_notify_brightness_hw_changed(struct led_classdev *led_cdev,
+                                              enum led_brightness brightness)
+{
+       if (WARN_ON(!led_cdev->brightness_hw_changed_kn))
+               return;
+
+       led_cdev->brightness_hw_changed = brightness;
+       sysfs_notify_dirent(led_cdev->brightness_hw_changed_kn);
+}
+EXPORT_SYMBOL_GPL(led_classdev_notify_brightness_hw_changed);
+#else
+static int led_add_brightness_hw_changed(struct led_classdev *led_cdev)
+{
+       return 0;
+}
+static void led_remove_brightness_hw_changed(struct led_classdev *led_cdev)
+{
+}
+#endif
+
 /**
  * led_classdev_suspend - suspend an led_classdev.
  * @led_cdev: the led_classdev to suspend.
@@ -204,9 +266,20 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
                dev_warn(parent, "Led %s renamed to %s due to name collision",
                                led_cdev->name, dev_name(led_cdev->dev));
 
+       if (led_cdev->flags & LED_BRIGHT_HW_CHANGED) {
+               ret = led_add_brightness_hw_changed(led_cdev);
+               if (ret) {
+                       device_unregister(led_cdev->dev);
+                       return ret;
+               }
+       }
+
        led_cdev->work_flags = 0;
 #ifdef CONFIG_LEDS_TRIGGERS
        init_rwsem(&led_cdev->trigger_lock);
+#endif
+#ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED
+       led_cdev->brightness_hw_changed = -1;
 #endif
        mutex_init(&led_cdev->led_access);
        /* add to the list of leds */
@@ -256,6 +329,9 @@ void led_classdev_unregister(struct led_classdev *led_cdev)
 
        flush_work(&led_cdev->set_brightness_work);
 
+       if (led_cdev->flags & LED_BRIGHT_HW_CHANGED)
+               led_remove_brightness_hw_changed(led_cdev);
+
        device_unregister(led_cdev->dev);
 
        down_write(&leds_list_lock);