浏览代码

leds: allow led-drivers to use a variable range of brightness values

This patch allows drivers to override the default maximum brightness value
of 255.  We take care to preserve backwards-compatibility as much as
possible, so that user-space ABI doesn't change for existing drivers.
LED trigger code has also been updated to use the per-LED maximum.

Signed-off-by: Guennadi Liakhovetski <lg@denx.de>
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Guennadi Liakhovetski 16 年之前
父节点
当前提交
1bd465e6b0

+ 20 - 1
drivers/leds/led-class.c

@@ -64,7 +64,16 @@ static ssize_t led_brightness_store(struct device *dev,
 	return ret;
 	return ret;
 }
 }
 
 
+static ssize_t led_max_brightness_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", led_cdev->max_brightness);
+}
+
 static DEVICE_ATTR(brightness, 0644, led_brightness_show, led_brightness_store);
 static DEVICE_ATTR(brightness, 0644, led_brightness_show, led_brightness_store);
+static DEVICE_ATTR(max_brightness, 0444, led_max_brightness_show, NULL);
 #ifdef CONFIG_LEDS_TRIGGERS
 #ifdef CONFIG_LEDS_TRIGGERS
 static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
 static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
 #endif
 #endif
@@ -138,6 +147,13 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
 	list_add_tail(&led_cdev->node, &leds_list);
 	list_add_tail(&led_cdev->node, &leds_list);
 	up_write(&leds_list_lock);
 	up_write(&leds_list_lock);
 
 
+	if (!led_cdev->max_brightness)
+		led_cdev->max_brightness = LED_FULL;
+
+	rc = device_create_file(led_cdev->dev, &dev_attr_max_brightness);
+	if (rc)
+		goto err_out_attr_max;
+
 	led_update_brightness(led_cdev);
 	led_update_brightness(led_cdev);
 
 
 #ifdef CONFIG_LEDS_TRIGGERS
 #ifdef CONFIG_LEDS_TRIGGERS
@@ -155,9 +171,11 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
 
 
 #ifdef CONFIG_LEDS_TRIGGERS
 #ifdef CONFIG_LEDS_TRIGGERS
 err_out_led_list:
 err_out_led_list:
+	device_remove_file(led_cdev->dev, &dev_attr_max_brightness);
+#endif
+err_out_attr_max:
 	device_remove_file(led_cdev->dev, &dev_attr_brightness);
 	device_remove_file(led_cdev->dev, &dev_attr_brightness);
 	list_del(&led_cdev->node);
 	list_del(&led_cdev->node);
-#endif
 err_out:
 err_out:
 	device_unregister(led_cdev->dev);
 	device_unregister(led_cdev->dev);
 	return rc;
 	return rc;
@@ -172,6 +190,7 @@ EXPORT_SYMBOL_GPL(led_classdev_register);
  */
  */
 void led_classdev_unregister(struct led_classdev *led_cdev)
 void led_classdev_unregister(struct led_classdev *led_cdev)
 {
 {
+	device_remove_file(led_cdev->dev, &dev_attr_max_brightness);
 	device_remove_file(led_cdev->dev, &dev_attr_brightness);
 	device_remove_file(led_cdev->dev, &dev_attr_brightness);
 #ifdef CONFIG_LEDS_TRIGGERS
 #ifdef CONFIG_LEDS_TRIGGERS
 	device_remove_file(led_cdev->dev, &dev_attr_trigger);
 	device_remove_file(led_cdev->dev, &dev_attr_trigger);

+ 2 - 2
drivers/leds/leds.h

@@ -20,8 +20,8 @@
 static inline void led_set_brightness(struct led_classdev *led_cdev,
 static inline void led_set_brightness(struct led_classdev *led_cdev,
 					enum led_brightness value)
 					enum led_brightness value)
 {
 {
-	if (value > LED_FULL)
-		value = LED_FULL;
+	if (value > led_cdev->max_brightness)
+		value = led_cdev->max_brightness;
 	led_cdev->brightness = value;
 	led_cdev->brightness = value;
 	if (!(led_cdev->flags & LED_SUSPENDED))
 	if (!(led_cdev->flags & LED_SUSPENDED))
 		led_cdev->brightness_set(led_cdev, value);
 		led_cdev->brightness_set(led_cdev, value);

+ 1 - 1
drivers/leds/ledtrig-default-on.c

@@ -19,7 +19,7 @@
 
 
 static void defon_trig_activate(struct led_classdev *led_cdev)
 static void defon_trig_activate(struct led_classdev *led_cdev)
 {
 {
-	led_set_brightness(led_cdev, LED_FULL);
+	led_set_brightness(led_cdev, led_cdev->max_brightness);
 }
 }
 
 
 static struct led_trigger defon_led_trigger = {
 static struct led_trigger defon_led_trigger = {

+ 2 - 2
drivers/leds/ledtrig-heartbeat.c

@@ -47,7 +47,7 @@ static void led_heartbeat_function(unsigned long data)
 			msecs_to_jiffies(heartbeat_data->period);
 			msecs_to_jiffies(heartbeat_data->period);
 		delay = msecs_to_jiffies(70);
 		delay = msecs_to_jiffies(70);
 		heartbeat_data->phase++;
 		heartbeat_data->phase++;
-		brightness = LED_FULL;
+		brightness = led_cdev->max_brightness;
 		break;
 		break;
 	case 1:
 	case 1:
 		delay = heartbeat_data->period / 4 - msecs_to_jiffies(70);
 		delay = heartbeat_data->period / 4 - msecs_to_jiffies(70);
@@ -56,7 +56,7 @@ static void led_heartbeat_function(unsigned long data)
 	case 2:
 	case 2:
 		delay = msecs_to_jiffies(70);
 		delay = msecs_to_jiffies(70);
 		heartbeat_data->phase++;
 		heartbeat_data->phase++;
-		brightness = LED_FULL;
+		brightness = led_cdev->max_brightness;
 		break;
 		break;
 	default:
 	default:
 		delay = heartbeat_data->period - heartbeat_data->period / 4 -
 		delay = heartbeat_data->period - heartbeat_data->period / 4 -

+ 2 - 1
drivers/leds/ledtrig-ide-disk.c

@@ -37,7 +37,8 @@ static void ledtrig_ide_timerfunc(unsigned long data)
 {
 {
 	if (ide_lastactivity != ide_activity) {
 	if (ide_lastactivity != ide_activity) {
 		ide_lastactivity = ide_activity;
 		ide_lastactivity = ide_activity;
-		led_trigger_event(ledtrig_ide, LED_FULL);
+		/* INT_MAX will set each LED to its maximum brightness */
+		led_trigger_event(ledtrig_ide, INT_MAX);
 		mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
 		mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
 	} else {
 	} else {
 		led_trigger_event(ledtrig_ide, LED_OFF);
 		led_trigger_event(ledtrig_ide, LED_OFF);

+ 1 - 1
drivers/leds/ledtrig-timer.c

@@ -166,7 +166,7 @@ static void timer_trig_activate(struct led_classdev *led_cdev)
 
 
 	timer_data->brightness_on = led_get_brightness(led_cdev);
 	timer_data->brightness_on = led_get_brightness(led_cdev);
 	if (timer_data->brightness_on == LED_OFF)
 	if (timer_data->brightness_on == LED_OFF)
-		timer_data->brightness_on = LED_FULL;
+		timer_data->brightness_on = led_cdev->max_brightness;
 	led_cdev->trigger_data = timer_data;
 	led_cdev->trigger_data = timer_data;
 
 
 	init_timer(&timer_data->timer);
 	init_timer(&timer_data->timer);

+ 1 - 0
include/linux/leds.h

@@ -30,6 +30,7 @@ enum led_brightness {
 struct led_classdev {
 struct led_classdev {
 	const char		*name;
 	const char		*name;
 	int			 brightness;
 	int			 brightness;
+	int			 max_brightness;
 	int			 flags;
 	int			 flags;
 
 
 	/* Lower 16 bits reflect status */
 	/* Lower 16 bits reflect status */