X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fleds%2Fleds-gpio.c;h=b13bd2950e956347b98bac9ed76e18efcabed612;hb=04489eeb02a40bc15029886cef7285ada3ab0de6;hp=99bc50059d3531499fa78ca369129a5f7d8c0e39;hpb=06e5fda18491b5ab3419bddc36f3de5b4f7142a9;p=linux-2.6 diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 99bc50059d..b13bd2950e 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -24,6 +24,8 @@ struct gpio_led_data { u8 new_level; u8 can_sleep; u8 active_low; + int (*platform_gpio_blink_set)(unsigned gpio, + unsigned long *delay_on, unsigned long *delay_off); }; static void gpio_led_work(struct work_struct *work) @@ -49,17 +51,26 @@ static void gpio_led_set(struct led_classdev *led_cdev, if (led_dat->active_low) level = !level; - /* setting GPIOs with I2C/etc requires a preemptible task context */ + /* Setting GPIOs with I2C/etc requires a task context, and we don't + * seem to have a reliable way to know if we're already in one; so + * let's just assume the worst. + */ if (led_dat->can_sleep) { - if (preempt_count()) { - led_dat->new_level = level; - schedule_work(&led_dat->work); - } else - gpio_set_value_cansleep(led_dat->gpio, level); + led_dat->new_level = level; + schedule_work(&led_dat->work); } else gpio_set_value(led_dat->gpio, level); } +static int gpio_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, unsigned long *delay_off) +{ + struct gpio_led_data *led_dat = + container_of(led_cdev, struct gpio_led_data, cdev); + + return led_dat->platform_gpio_blink_set(led_dat->gpio, delay_on, delay_off); +} + static int gpio_led_probe(struct platform_device *pdev) { struct gpio_led_platform_data *pdata = pdev->dev.platform_data; @@ -79,17 +90,21 @@ static int gpio_led_probe(struct platform_device *pdev) cur_led = &pdata->leds[i]; led_dat = &leds_data[i]; + ret = gpio_request(cur_led->gpio, cur_led->name); + if (ret < 0) + goto err; + led_dat->cdev.name = cur_led->name; led_dat->cdev.default_trigger = cur_led->default_trigger; led_dat->gpio = cur_led->gpio; led_dat->can_sleep = gpio_cansleep(cur_led->gpio); led_dat->active_low = cur_led->active_low; + if (pdata->gpio_blink_set) { + led_dat->platform_gpio_blink_set = pdata->gpio_blink_set; + led_dat->cdev.blink_set = gpio_blink_set; + } led_dat->cdev.brightness_set = gpio_led_set; - led_dat->cdev.brightness = cur_led->active_low ? LED_FULL : LED_OFF; - - ret = gpio_request(led_dat->gpio, led_dat->cdev.name); - if (ret < 0) - goto err; + led_dat->cdev.brightness = LED_OFF; gpio_direction_output(led_dat->gpio, led_dat->active_low); @@ -199,3 +214,4 @@ module_exit(gpio_led_exit); MODULE_AUTHOR("Raphael Assenat "); MODULE_DESCRIPTION("GPIO LED driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:leds-gpio");