X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fleds%2Fledtrig-timer.c;h=82c55d6e49023ff9fe2866a819a1c5ec7bad7949;hb=4c79141d28bc290ae307e3f81f5bc909c26faf6e;hp=29a8818a32ec23e71fda137f1e634e46de538559;hpb=12fda16814bba05a84a49a1da25a069d6c249758;p=linux-2.6-omap-h63xx.git diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c index 29a8818a32e..82c55d6e490 100644 --- a/drivers/leds/ledtrig-timer.c +++ b/drivers/leds/ledtrig-timer.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include @@ -51,9 +52,10 @@ static void led_timer_function(unsigned long data) mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay)); } -static ssize_t led_delay_on_show(struct class_device *dev, char *buf) +static ssize_t led_delay_on_show(struct device *dev, + struct device_attribute *attr, char *buf) { - struct led_classdev *led_cdev = class_get_devdata(dev); + struct led_classdev *led_cdev = dev_get_drvdata(dev); struct timer_trig_data *timer_data = led_cdev->trigger_data; sprintf(buf, "%lu\n", timer_data->delay_on); @@ -61,10 +63,10 @@ static ssize_t led_delay_on_show(struct class_device *dev, char *buf) return strlen(buf) + 1; } -static ssize_t led_delay_on_store(struct class_device *dev, const char *buf, - size_t size) +static ssize_t led_delay_on_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = class_get_devdata(dev); + struct led_classdev *led_cdev = dev_get_drvdata(dev); struct timer_trig_data *timer_data = led_cdev->trigger_data; int ret = -EINVAL; char *after; @@ -75,17 +77,31 @@ static ssize_t led_delay_on_store(struct class_device *dev, const char *buf, count++; if (count == size) { - timer_data->delay_on = state; - mod_timer(&timer_data->timer, jiffies + 1); + if (timer_data->delay_on != state) { + /* the new value differs from the previous */ + timer_data->delay_on = state; + + /* deactivate previous settings */ + del_timer_sync(&timer_data->timer); + + /* try to activate hardware acceleration, if any */ + if (!led_cdev->blink_set || + led_cdev->blink_set(led_cdev, + &timer_data->delay_on, &timer_data->delay_off)) { + /* no hardware acceleration, blink via timer */ + mod_timer(&timer_data->timer, jiffies + 1); + } + } ret = count; } return ret; } -static ssize_t led_delay_off_show(struct class_device *dev, char *buf) +static ssize_t led_delay_off_show(struct device *dev, + struct device_attribute *attr, char *buf) { - struct led_classdev *led_cdev = class_get_devdata(dev); + struct led_classdev *led_cdev = dev_get_drvdata(dev); struct timer_trig_data *timer_data = led_cdev->trigger_data; sprintf(buf, "%lu\n", timer_data->delay_off); @@ -93,10 +109,10 @@ static ssize_t led_delay_off_show(struct class_device *dev, char *buf) return strlen(buf) + 1; } -static ssize_t led_delay_off_store(struct class_device *dev, const char *buf, - size_t size) +static ssize_t led_delay_off_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) { - struct led_classdev *led_cdev = class_get_devdata(dev); + struct led_classdev *led_cdev = dev_get_drvdata(dev); struct timer_trig_data *timer_data = led_cdev->trigger_data; int ret = -EINVAL; char *after; @@ -107,18 +123,29 @@ static ssize_t led_delay_off_store(struct class_device *dev, const char *buf, count++; if (count == size) { - timer_data->delay_off = state; - mod_timer(&timer_data->timer, jiffies + 1); + if (timer_data->delay_off != state) { + /* the new value differs from the previous */ + timer_data->delay_off = state; + + /* deactivate previous settings */ + del_timer_sync(&timer_data->timer); + + /* try to activate hardware acceleration, if any */ + if (!led_cdev->blink_set || + led_cdev->blink_set(led_cdev, + &timer_data->delay_on, &timer_data->delay_off)) { + /* no hardware acceleration, blink via timer */ + mod_timer(&timer_data->timer, jiffies + 1); + } + } ret = count; } return ret; } -static CLASS_DEVICE_ATTR(delay_on, 0644, led_delay_on_show, - led_delay_on_store); -static CLASS_DEVICE_ATTR(delay_off, 0644, led_delay_off_show, - led_delay_off_store); +static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store); +static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); static void timer_trig_activate(struct led_classdev *led_cdev) { @@ -135,18 +162,24 @@ static void timer_trig_activate(struct led_classdev *led_cdev) timer_data->timer.function = led_timer_function; timer_data->timer.data = (unsigned long) led_cdev; - rc = class_device_create_file(led_cdev->class_dev, - &class_device_attr_delay_on); - if (rc) goto err_out; - rc = class_device_create_file(led_cdev->class_dev, - &class_device_attr_delay_off); - if (rc) goto err_out_delayon; + rc = device_create_file(led_cdev->dev, &dev_attr_delay_on); + if (rc) + goto err_out; + rc = device_create_file(led_cdev->dev, &dev_attr_delay_off); + if (rc) + goto err_out_delayon; + + /* If there is hardware support for blinking, start one + * user friendly blink rate chosen by the driver. + */ + if (led_cdev->blink_set) + led_cdev->blink_set(led_cdev, + &timer_data->delay_on, &timer_data->delay_off); return; err_out_delayon: - class_device_remove_file(led_cdev->class_dev, - &class_device_attr_delay_on); + device_remove_file(led_cdev->dev, &dev_attr_delay_on); err_out: led_cdev->trigger_data = NULL; kfree(timer_data); @@ -157,10 +190,8 @@ static void timer_trig_deactivate(struct led_classdev *led_cdev) struct timer_trig_data *timer_data = led_cdev->trigger_data; if (timer_data) { - class_device_remove_file(led_cdev->class_dev, - &class_device_attr_delay_on); - class_device_remove_file(led_cdev->class_dev, - &class_device_attr_delay_off); + device_remove_file(led_cdev->dev, &dev_attr_delay_on); + device_remove_file(led_cdev->dev, &dev_attr_delay_off); del_timer_sync(&timer_data->timer); kfree(timer_data); }