Source
x
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2009,2018 Daniel Mack <daniel@zonque.org>
struct lt3593_led_data {
char name[LED_MAX_NAME_SIZE];
struct led_classdev cdev;
struct gpio_desc *gpiod;
};
static int lt3593_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct lt3593_led_data *led_dat =
container_of(led_cdev, struct lt3593_led_data, cdev);
int pulses;
/*
* The LT3593 resets its internal current level register to the maximum
* level on the first falling edge on the control pin. Each following
* falling edge decreases the current level by 625uA. Up to 32 pulses
* can be sent, so the maximum power reduction is 20mA.
* After a timeout of 128us, the value is taken from the register and
* applied is to the output driver.
*/
if (value == 0) {
gpiod_set_value_cansleep(led_dat->gpiod, 0);
return 0;
}
pulses = 32 - (value * 32) / 255;
if (pulses == 0) {
gpiod_set_value_cansleep(led_dat->gpiod, 0);
mdelay(1);
gpiod_set_value_cansleep(led_dat->gpiod, 1);
return 0;
}
gpiod_set_value_cansleep(led_dat->gpiod, 1);
while (pulses--) {
gpiod_set_value_cansleep(led_dat->gpiod, 0);
udelay(1);
gpiod_set_value_cansleep(led_dat->gpiod, 1);
udelay(1);
}
return 0;
}
static struct lt3593_led_data *lt3593_led_probe_pdata(struct device *dev)
{
struct gpio_led_platform_data *pdata = dev_get_platdata(dev);
const struct gpio_led *template = &pdata->leds[0];
struct lt3593_led_data *led_data;
int ret, state;
if (pdata->num_leds != 1)
return ERR_PTR(-EINVAL);
led_data = devm_kzalloc(dev, sizeof(*led_data), GFP_KERNEL);
if (!led_data)
return ERR_PTR(-ENOMEM);
led_data->cdev.name = template->name;
led_data->cdev.default_trigger = template->default_trigger;
led_data->cdev.brightness_set_blocking = lt3593_led_set;
state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
led_data->cdev.brightness = state ? LED_FULL : LED_OFF;
if (!template->retain_state_suspended)
led_data->cdev.flags |= LED_CORE_SUSPENDRESUME;
ret = devm_gpio_request_one(dev, template->gpio, state ?
GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
template->name);
if (ret < 0)
return ERR_PTR(ret);