From 4c0e0e4711a30923603b3bcd8cdf297c04aecef9 Mon Sep 17 00:00:00 2001 From: David Phillips Date: Sun, 16 May 2021 21:18:01 +1200 Subject: led: add blink support The blink support is a bit of an odd case that has to be shoehorned into the Linux LED API. CDS9K's LED blink logic doesn't allow for anything other than 50% duty, so we ignore delay_off all the time, and just set it to whatever we derive delay_on to rounded to. --- cds9k-led.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/cds9k-led.c b/cds9k-led.c index 3f976cc..adcb18b 100644 --- a/cds9k-led.c +++ b/cds9k-led.c @@ -4,8 +4,13 @@ #include #include -#define LED_REG_VALUE 0x0 -#define LED_REG_RATE 0x1 +#define LED_REG_VALUE 0x0 +#define LED_REG_PERIOD 0x1 + +#define LED_BLINK_MIN_MS 20 +#define LED_BLINK_MAX_MS 5100 +#define MS_TO_CDS9K(x) ((x) / 10) +#define CDS9K_TO_MS(x) ((x) * 10) struct cds9k_led { struct led_classdev cdev; @@ -13,11 +18,30 @@ struct cds9k_led { u32 base; }; -void cds9k_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) +int cds9k_led_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) { struct cds9k_led *led = container_of(led_cdev, struct cds9k_led, cdev); + unsigned long blink_value; + /* Only 50% duty is supported by controller, so we ignore delay_off */ + blink_value = MS_TO_CDS9K(*delay_on); + if (blink_value >= 255) { + blink_value = 255; + } + *delay_off = *delay_on = CDS9K_TO_MS(blink_value); + + return regmap_write(led->regmap, led->base + LED_REG_PERIOD, blink_value); +} +void cds9k_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + unsigned long blink_off = 0; + struct cds9k_led *led = container_of(led_cdev, struct cds9k_led, cdev); regmap_write(led->regmap, led->base + LED_REG_VALUE, brightness); + if (brightness == LED_OFF) + cds9k_led_blink_set(led_cdev, &blink_off, &blink_off); } enum led_brightness cds9k_led_brightness_get(struct led_classdev *led_cdev) @@ -64,6 +88,7 @@ static int cds9k_led_probe(struct platform_device *pdev) led->cdev.brightness_set = cds9k_led_brightness_set; led->cdev.brightness_get = cds9k_led_brightness_get; led->cdev.max_brightness = 0xFF; + led->cdev.blink_set = cds9k_led_blink_set; /* FIXME default state keep/on etc */ init_data.fwnode = of_fwnode_handle(np); -- cgit v1.1