mirror of
https://github.com/torvalds/linux.git
synced 2024-11-28 07:01:32 +00:00
leds: lp55xx: Add multicolor framework support to lp55xx
Add multicolor framework support for the lp55xx family. Acked-by: Pavel Machek <pavel@ucw.cz> Acked-by: Jacek Anaszewski <jacek.anaszewski@gmail.com> Signed-off-by: Dan Murphy <dmurphy@ti.com> Signed-off-by: Pavel Machek <pavel@ucw.cz>
This commit is contained in:
parent
c732eaf01f
commit
92a81562e6
@ -386,7 +386,8 @@ config LEDS_LP3952
|
|||||||
|
|
||||||
config LEDS_LP55XX_COMMON
|
config LEDS_LP55XX_COMMON
|
||||||
tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501"
|
tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501"
|
||||||
depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501
|
depends on LEDS_CLASS_MULTICOLOR || !LEDS_CLASS_MULTICOLOR
|
||||||
|
depends on OF
|
||||||
select FW_LOADER
|
select FW_LOADER
|
||||||
select FW_LOADER_USER_HELPER
|
select FW_LOADER_USER_HELPER
|
||||||
help
|
help
|
||||||
@ -396,7 +397,7 @@ config LEDS_LP55XX_COMMON
|
|||||||
config LEDS_LP5521
|
config LEDS_LP5521
|
||||||
tristate "LED Support for N.S. LP5521 LED driver chip"
|
tristate "LED Support for N.S. LP5521 LED driver chip"
|
||||||
depends on LEDS_CLASS && I2C
|
depends on LEDS_CLASS && I2C
|
||||||
select LEDS_LP55XX_COMMON
|
depends on LEDS_LP55XX_COMMON
|
||||||
help
|
help
|
||||||
If you say yes here you get support for the National Semiconductor
|
If you say yes here you get support for the National Semiconductor
|
||||||
LP5521 LED driver. It is 3 channel chip with programmable engines.
|
LP5521 LED driver. It is 3 channel chip with programmable engines.
|
||||||
@ -406,7 +407,7 @@ config LEDS_LP5521
|
|||||||
config LEDS_LP5523
|
config LEDS_LP5523
|
||||||
tristate "LED Support for TI/National LP5523/55231 LED driver chip"
|
tristate "LED Support for TI/National LP5523/55231 LED driver chip"
|
||||||
depends on LEDS_CLASS && I2C
|
depends on LEDS_CLASS && I2C
|
||||||
select LEDS_LP55XX_COMMON
|
depends on LEDS_LP55XX_COMMON
|
||||||
help
|
help
|
||||||
If you say yes here you get support for TI/National Semiconductor
|
If you say yes here you get support for TI/National Semiconductor
|
||||||
LP5523/55231 LED driver.
|
LP5523/55231 LED driver.
|
||||||
@ -417,7 +418,7 @@ config LEDS_LP5523
|
|||||||
config LEDS_LP5562
|
config LEDS_LP5562
|
||||||
tristate "LED Support for TI LP5562 LED driver chip"
|
tristate "LED Support for TI LP5562 LED driver chip"
|
||||||
depends on LEDS_CLASS && I2C
|
depends on LEDS_CLASS && I2C
|
||||||
select LEDS_LP55XX_COMMON
|
depends on LEDS_LP55XX_COMMON
|
||||||
help
|
help
|
||||||
If you say yes here you get support for TI LP5562 LED driver.
|
If you say yes here you get support for TI LP5562 LED driver.
|
||||||
It is 4 channels chip with programmable engines.
|
It is 4 channels chip with programmable engines.
|
||||||
@ -427,7 +428,7 @@ config LEDS_LP5562
|
|||||||
config LEDS_LP8501
|
config LEDS_LP8501
|
||||||
tristate "LED Support for TI LP8501 LED driver chip"
|
tristate "LED Support for TI LP8501 LED driver chip"
|
||||||
depends on LEDS_CLASS && I2C
|
depends on LEDS_CLASS && I2C
|
||||||
select LEDS_LP55XX_COMMON
|
depends on LEDS_LP55XX_COMMON
|
||||||
help
|
help
|
||||||
If you say yes here you get support for TI LP8501 LED driver.
|
If you say yes here you get support for TI LP8501 LED driver.
|
||||||
It is 9 channel chip with programmable engines.
|
It is 9 channel chip with programmable engines.
|
||||||
|
@ -505,9 +505,16 @@ static int lp5521_probe(struct i2c_client *client,
|
|||||||
struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
|
struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||||
struct device_node *np = client->dev.of_node;
|
struct device_node *np = client->dev.of_node;
|
||||||
|
|
||||||
|
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
|
||||||
|
if (!chip)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
chip->cfg = &lp5521_cfg;
|
||||||
|
|
||||||
if (!pdata) {
|
if (!pdata) {
|
||||||
if (np) {
|
if (np) {
|
||||||
pdata = lp55xx_of_populate_pdata(&client->dev, np);
|
pdata = lp55xx_of_populate_pdata(&client->dev, np,
|
||||||
|
chip);
|
||||||
if (IS_ERR(pdata))
|
if (IS_ERR(pdata))
|
||||||
return PTR_ERR(pdata);
|
return PTR_ERR(pdata);
|
||||||
} else {
|
} else {
|
||||||
@ -516,10 +523,6 @@ static int lp5521_probe(struct i2c_client *client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
|
|
||||||
if (!chip)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
led = devm_kcalloc(&client->dev,
|
led = devm_kcalloc(&client->dev,
|
||||||
pdata->num_channels, sizeof(*led), GFP_KERNEL);
|
pdata->num_channels, sizeof(*led), GFP_KERNEL);
|
||||||
if (!led)
|
if (!led)
|
||||||
@ -527,7 +530,6 @@ static int lp5521_probe(struct i2c_client *client,
|
|||||||
|
|
||||||
chip->cl = client;
|
chip->cl = client;
|
||||||
chip->pdata = pdata;
|
chip->pdata = pdata;
|
||||||
chip->cfg = &lp5521_cfg;
|
|
||||||
|
|
||||||
mutex_init(&chip->lock);
|
mutex_init(&chip->lock);
|
||||||
|
|
||||||
|
@ -873,9 +873,16 @@ static int lp5523_probe(struct i2c_client *client,
|
|||||||
struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
|
struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||||
struct device_node *np = client->dev.of_node;
|
struct device_node *np = client->dev.of_node;
|
||||||
|
|
||||||
|
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
|
||||||
|
if (!chip)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
chip->cfg = &lp5523_cfg;
|
||||||
|
|
||||||
if (!pdata) {
|
if (!pdata) {
|
||||||
if (np) {
|
if (np) {
|
||||||
pdata = lp55xx_of_populate_pdata(&client->dev, np);
|
pdata = lp55xx_of_populate_pdata(&client->dev, np,
|
||||||
|
chip);
|
||||||
if (IS_ERR(pdata))
|
if (IS_ERR(pdata))
|
||||||
return PTR_ERR(pdata);
|
return PTR_ERR(pdata);
|
||||||
} else {
|
} else {
|
||||||
@ -884,10 +891,6 @@ static int lp5523_probe(struct i2c_client *client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
|
|
||||||
if (!chip)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
led = devm_kcalloc(&client->dev,
|
led = devm_kcalloc(&client->dev,
|
||||||
pdata->num_channels, sizeof(*led), GFP_KERNEL);
|
pdata->num_channels, sizeof(*led), GFP_KERNEL);
|
||||||
if (!led)
|
if (!led)
|
||||||
@ -895,7 +898,6 @@ static int lp5523_probe(struct i2c_client *client,
|
|||||||
|
|
||||||
chip->cl = client;
|
chip->cl = client;
|
||||||
chip->pdata = pdata;
|
chip->pdata = pdata;
|
||||||
chip->cfg = &lp5523_cfg;
|
|
||||||
|
|
||||||
mutex_init(&chip->lock);
|
mutex_init(&chip->lock);
|
||||||
|
|
||||||
|
@ -520,9 +520,16 @@ static int lp5562_probe(struct i2c_client *client,
|
|||||||
struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
|
struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||||
struct device_node *np = client->dev.of_node;
|
struct device_node *np = client->dev.of_node;
|
||||||
|
|
||||||
|
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
|
||||||
|
if (!chip)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
chip->cfg = &lp5562_cfg;
|
||||||
|
|
||||||
if (!pdata) {
|
if (!pdata) {
|
||||||
if (np) {
|
if (np) {
|
||||||
pdata = lp55xx_of_populate_pdata(&client->dev, np);
|
pdata = lp55xx_of_populate_pdata(&client->dev, np,
|
||||||
|
chip);
|
||||||
if (IS_ERR(pdata))
|
if (IS_ERR(pdata))
|
||||||
return PTR_ERR(pdata);
|
return PTR_ERR(pdata);
|
||||||
} else {
|
} else {
|
||||||
@ -531,9 +538,6 @@ static int lp5562_probe(struct i2c_client *client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
|
|
||||||
if (!chip)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
led = devm_kcalloc(&client->dev,
|
led = devm_kcalloc(&client->dev,
|
||||||
pdata->num_channels, sizeof(*led), GFP_KERNEL);
|
pdata->num_channels, sizeof(*led), GFP_KERNEL);
|
||||||
@ -542,7 +546,6 @@ static int lp5562_probe(struct i2c_client *client,
|
|||||||
|
|
||||||
chip->cl = client;
|
chip->cl = client;
|
||||||
chip->pdata = pdata;
|
chip->pdata = pdata;
|
||||||
chip->cfg = &lp5562_cfg;
|
|
||||||
|
|
||||||
mutex_init(&chip->lock);
|
mutex_init(&chip->lock);
|
||||||
|
|
||||||
|
@ -34,6 +34,11 @@ static struct lp55xx_led *dev_to_lp55xx_led(struct device *dev)
|
|||||||
return cdev_to_lp55xx_led(dev_get_drvdata(dev));
|
return cdev_to_lp55xx_led(dev_get_drvdata(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct lp55xx_led *mcled_cdev_to_led(struct led_classdev_mc *mc_cdev)
|
||||||
|
{
|
||||||
|
return container_of(mc_cdev, struct lp55xx_led, mc_cdev);
|
||||||
|
}
|
||||||
|
|
||||||
static void lp55xx_reset_device(struct lp55xx_chip *chip)
|
static void lp55xx_reset_device(struct lp55xx_chip *chip)
|
||||||
{
|
{
|
||||||
struct lp55xx_device_config *cfg = chip->cfg;
|
struct lp55xx_device_config *cfg = chip->cfg;
|
||||||
@ -129,6 +134,18 @@ static struct attribute *lp55xx_led_attrs[] = {
|
|||||||
};
|
};
|
||||||
ATTRIBUTE_GROUPS(lp55xx_led);
|
ATTRIBUTE_GROUPS(lp55xx_led);
|
||||||
|
|
||||||
|
static int lp55xx_set_mc_brightness(struct led_classdev *cdev,
|
||||||
|
enum led_brightness brightness)
|
||||||
|
{
|
||||||
|
struct led_classdev_mc *mc_dev = lcdev_to_mccdev(cdev);
|
||||||
|
struct lp55xx_led *led = mcled_cdev_to_led(mc_dev);
|
||||||
|
struct lp55xx_device_config *cfg = led->chip->cfg;
|
||||||
|
|
||||||
|
led_mc_calc_color_components(&led->mc_cdev, brightness);
|
||||||
|
return cfg->multicolor_brightness_fn(led);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static int lp55xx_set_brightness(struct led_classdev *cdev,
|
static int lp55xx_set_brightness(struct led_classdev *cdev,
|
||||||
enum led_brightness brightness)
|
enum led_brightness brightness)
|
||||||
{
|
{
|
||||||
@ -145,9 +162,12 @@ static int lp55xx_init_led(struct lp55xx_led *led,
|
|||||||
struct lp55xx_platform_data *pdata = chip->pdata;
|
struct lp55xx_platform_data *pdata = chip->pdata;
|
||||||
struct lp55xx_device_config *cfg = chip->cfg;
|
struct lp55xx_device_config *cfg = chip->cfg;
|
||||||
struct device *dev = &chip->cl->dev;
|
struct device *dev = &chip->cl->dev;
|
||||||
char name[32];
|
|
||||||
int ret;
|
|
||||||
int max_channel = cfg->max_channel;
|
int max_channel = cfg->max_channel;
|
||||||
|
struct mc_subled *mc_led_info;
|
||||||
|
struct led_classdev *led_cdev;
|
||||||
|
char name[32];
|
||||||
|
int i, j = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (chan >= max_channel) {
|
if (chan >= max_channel) {
|
||||||
dev_err(dev, "invalid channel: %d / %d\n", chan, max_channel);
|
dev_err(dev, "invalid channel: %d / %d\n", chan, max_channel);
|
||||||
@ -157,20 +177,6 @@ static int lp55xx_init_led(struct lp55xx_led *led,
|
|||||||
if (pdata->led_config[chan].led_current == 0)
|
if (pdata->led_config[chan].led_current == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
led->led_current = pdata->led_config[chan].led_current;
|
|
||||||
led->max_current = pdata->led_config[chan].max_current;
|
|
||||||
led->chan_nr = pdata->led_config[chan].chan_nr;
|
|
||||||
led->cdev.default_trigger = pdata->led_config[chan].default_trigger;
|
|
||||||
|
|
||||||
if (led->chan_nr >= max_channel) {
|
|
||||||
dev_err(dev, "Use channel numbers between 0 and %d\n",
|
|
||||||
max_channel - 1);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
led->cdev.brightness_set_blocking = lp55xx_set_brightness;
|
|
||||||
led->cdev.groups = lp55xx_led_groups;
|
|
||||||
|
|
||||||
if (pdata->led_config[chan].name) {
|
if (pdata->led_config[chan].name) {
|
||||||
led->cdev.name = pdata->led_config[chan].name;
|
led->cdev.name = pdata->led_config[chan].name;
|
||||||
} else {
|
} else {
|
||||||
@ -179,7 +185,47 @@ static int lp55xx_init_led(struct lp55xx_led *led,
|
|||||||
led->cdev.name = name;
|
led->cdev.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = devm_led_classdev_register(dev, &led->cdev);
|
if (pdata->led_config[chan].num_colors > 1) {
|
||||||
|
mc_led_info = devm_kcalloc(dev,
|
||||||
|
pdata->led_config[chan].num_colors,
|
||||||
|
sizeof(*mc_led_info), GFP_KERNEL);
|
||||||
|
if (!mc_led_info)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
led_cdev = &led->mc_cdev.led_cdev;
|
||||||
|
led_cdev->name = led->cdev.name;
|
||||||
|
led_cdev->brightness_set_blocking = lp55xx_set_mc_brightness;
|
||||||
|
led->mc_cdev.num_colors = pdata->led_config[chan].num_colors;
|
||||||
|
for (i = 0; i < led->mc_cdev.num_colors; i++) {
|
||||||
|
mc_led_info[i].color_index =
|
||||||
|
pdata->led_config[chan].color_id[i];
|
||||||
|
mc_led_info[i].channel =
|
||||||
|
pdata->led_config[chan].output_num[i];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
led->mc_cdev.subled_info = mc_led_info;
|
||||||
|
} else {
|
||||||
|
led->cdev.brightness_set_blocking = lp55xx_set_brightness;
|
||||||
|
}
|
||||||
|
|
||||||
|
led->cdev.groups = lp55xx_led_groups;
|
||||||
|
led->cdev.default_trigger = pdata->led_config[chan].default_trigger;
|
||||||
|
led->led_current = pdata->led_config[chan].led_current;
|
||||||
|
led->max_current = pdata->led_config[chan].max_current;
|
||||||
|
led->chan_nr = pdata->led_config[chan].chan_nr;
|
||||||
|
|
||||||
|
if (led->chan_nr >= max_channel) {
|
||||||
|
dev_err(dev, "Use channel numbers between 0 and %d\n",
|
||||||
|
max_channel - 1);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdata->led_config[chan].num_colors > 1)
|
||||||
|
ret = devm_led_classdev_multicolor_register(dev, &led->mc_cdev);
|
||||||
|
else
|
||||||
|
ret = devm_led_classdev_register(dev, &led->cdev);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "led register err: %d\n", ret);
|
dev_err(dev, "led register err: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
@ -515,14 +561,105 @@ void lp55xx_unregister_sysfs(struct lp55xx_chip *chip)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs);
|
EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs);
|
||||||
|
|
||||||
|
static int lp55xx_parse_common_child(struct device_node *np,
|
||||||
|
struct lp55xx_led_config *cfg,
|
||||||
|
int led_number, int *chan_nr)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
of_property_read_string(np, "chan-name",
|
||||||
|
&cfg[led_number].name);
|
||||||
|
of_property_read_u8(np, "led-cur",
|
||||||
|
&cfg[led_number].led_current);
|
||||||
|
of_property_read_u8(np, "max-cur",
|
||||||
|
&cfg[led_number].max_current);
|
||||||
|
|
||||||
|
ret = of_property_read_u32(np, "reg", chan_nr);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (*chan_nr < 0 || *chan_nr > cfg->max_channel)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lp55xx_parse_multi_led_child(struct device_node *child,
|
||||||
|
struct lp55xx_led_config *cfg,
|
||||||
|
int child_number, int color_number)
|
||||||
|
{
|
||||||
|
int chan_nr, color_id, ret;
|
||||||
|
|
||||||
|
ret = lp55xx_parse_common_child(child, cfg, child_number, &chan_nr);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = of_property_read_u32(child, "color", &color_id);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
cfg[child_number].color_id[color_number] = color_id;
|
||||||
|
cfg[child_number].output_num[color_number] = chan_nr;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lp55xx_parse_multi_led(struct device_node *np,
|
||||||
|
struct lp55xx_led_config *cfg,
|
||||||
|
int child_number)
|
||||||
|
{
|
||||||
|
struct device_node *child;
|
||||||
|
int num_colors = 0, ret;
|
||||||
|
|
||||||
|
for_each_child_of_node(np, child) {
|
||||||
|
ret = lp55xx_parse_multi_led_child(child, cfg, child_number,
|
||||||
|
num_colors);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
num_colors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg[child_number].num_colors = num_colors;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lp55xx_parse_logical_led(struct device_node *np,
|
||||||
|
struct lp55xx_led_config *cfg,
|
||||||
|
int child_number)
|
||||||
|
{
|
||||||
|
int led_color, ret;
|
||||||
|
int chan_nr = 0;
|
||||||
|
|
||||||
|
cfg[child_number].default_trigger =
|
||||||
|
of_get_property(np, "linux,default-trigger", NULL);
|
||||||
|
|
||||||
|
ret = of_property_read_u32(np, "color", &led_color);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (led_color == LED_COLOR_ID_MULTI)
|
||||||
|
return lp55xx_parse_multi_led(np, cfg, child_number);
|
||||||
|
|
||||||
|
ret = lp55xx_parse_common_child(np, cfg, child_number, &chan_nr);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
cfg[child_number].chan_nr = chan_nr;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,
|
struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,
|
||||||
struct device_node *np)
|
struct device_node *np,
|
||||||
|
struct lp55xx_chip *chip)
|
||||||
{
|
{
|
||||||
struct device_node *child;
|
struct device_node *child;
|
||||||
struct lp55xx_platform_data *pdata;
|
struct lp55xx_platform_data *pdata;
|
||||||
struct lp55xx_led_config *cfg;
|
struct lp55xx_led_config *cfg;
|
||||||
int num_channels;
|
int num_channels;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||||
if (!pdata)
|
if (!pdata)
|
||||||
@ -540,16 +677,12 @@ struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,
|
|||||||
|
|
||||||
pdata->led_config = &cfg[0];
|
pdata->led_config = &cfg[0];
|
||||||
pdata->num_channels = num_channels;
|
pdata->num_channels = num_channels;
|
||||||
|
cfg->max_channel = chip->cfg->max_channel;
|
||||||
|
|
||||||
for_each_child_of_node(np, child) {
|
for_each_child_of_node(np, child) {
|
||||||
cfg[i].chan_nr = i;
|
ret = lp55xx_parse_logical_led(child, cfg, i);
|
||||||
|
if (ret)
|
||||||
of_property_read_string(child, "chan-name", &cfg[i].name);
|
return ERR_PTR(-EINVAL);
|
||||||
of_property_read_u8(child, "led-cur", &cfg[i].led_current);
|
|
||||||
of_property_read_u8(child, "max-cur", &cfg[i].max_current);
|
|
||||||
cfg[i].default_trigger =
|
|
||||||
of_get_property(child, "linux,default-trigger", NULL);
|
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#ifndef _LEDS_LP55XX_COMMON_H
|
#ifndef _LEDS_LP55XX_COMMON_H
|
||||||
#define _LEDS_LP55XX_COMMON_H
|
#define _LEDS_LP55XX_COMMON_H
|
||||||
|
|
||||||
|
#include <linux/led-class-multicolor.h>
|
||||||
|
|
||||||
enum lp55xx_engine_index {
|
enum lp55xx_engine_index {
|
||||||
LP55XX_ENGINE_INVALID,
|
LP55XX_ENGINE_INVALID,
|
||||||
LP55XX_ENGINE_1,
|
LP55XX_ENGINE_1,
|
||||||
@ -93,6 +95,7 @@ struct lp55xx_reg {
|
|||||||
* @max_channel : Maximum number of channels
|
* @max_channel : Maximum number of channels
|
||||||
* @post_init_device : Chip specific initialization code
|
* @post_init_device : Chip specific initialization code
|
||||||
* @brightness_fn : Brightness function
|
* @brightness_fn : Brightness function
|
||||||
|
* @multicolor_brightness_fn : Multicolor brightness function
|
||||||
* @set_led_current : LED current set function
|
* @set_led_current : LED current set function
|
||||||
* @firmware_cb : Call function when the firmware is loaded
|
* @firmware_cb : Call function when the firmware is loaded
|
||||||
* @run_engine : Run internal engine for pattern
|
* @run_engine : Run internal engine for pattern
|
||||||
@ -106,9 +109,12 @@ struct lp55xx_device_config {
|
|||||||
/* define if the device has specific initialization process */
|
/* define if the device has specific initialization process */
|
||||||
int (*post_init_device) (struct lp55xx_chip *chip);
|
int (*post_init_device) (struct lp55xx_chip *chip);
|
||||||
|
|
||||||
/* access brightness register */
|
/* set LED brightness */
|
||||||
int (*brightness_fn)(struct lp55xx_led *led);
|
int (*brightness_fn)(struct lp55xx_led *led);
|
||||||
|
|
||||||
|
/* set multicolor LED brightness */
|
||||||
|
int (*multicolor_brightness_fn)(struct lp55xx_led *led);
|
||||||
|
|
||||||
/* current setting function */
|
/* current setting function */
|
||||||
void (*set_led_current) (struct lp55xx_led *led, u8 led_current);
|
void (*set_led_current) (struct lp55xx_led *led, u8 led_current);
|
||||||
|
|
||||||
@ -159,6 +165,8 @@ struct lp55xx_chip {
|
|||||||
* struct lp55xx_led
|
* struct lp55xx_led
|
||||||
* @chan_nr : Channel number
|
* @chan_nr : Channel number
|
||||||
* @cdev : LED class device
|
* @cdev : LED class device
|
||||||
|
* @mc_cdev : Multi color class device
|
||||||
|
* @color_components: Multi color LED map information
|
||||||
* @led_current : Current setting at each led channel
|
* @led_current : Current setting at each led channel
|
||||||
* @max_current : Maximun current at each led channel
|
* @max_current : Maximun current at each led channel
|
||||||
* @brightness : Brightness value
|
* @brightness : Brightness value
|
||||||
@ -167,6 +175,7 @@ struct lp55xx_chip {
|
|||||||
struct lp55xx_led {
|
struct lp55xx_led {
|
||||||
int chan_nr;
|
int chan_nr;
|
||||||
struct led_classdev cdev;
|
struct led_classdev cdev;
|
||||||
|
struct led_classdev_mc mc_cdev;
|
||||||
u8 led_current;
|
u8 led_current;
|
||||||
u8 max_current;
|
u8 max_current;
|
||||||
u8 brightness;
|
u8 brightness;
|
||||||
@ -196,6 +205,7 @@ extern void lp55xx_unregister_sysfs(struct lp55xx_chip *chip);
|
|||||||
|
|
||||||
/* common device tree population function */
|
/* common device tree population function */
|
||||||
extern struct lp55xx_platform_data
|
extern struct lp55xx_platform_data
|
||||||
*lp55xx_of_populate_pdata(struct device *dev, struct device_node *np);
|
*lp55xx_of_populate_pdata(struct device *dev, struct device_node *np,
|
||||||
|
struct lp55xx_chip *chip);
|
||||||
|
|
||||||
#endif /* _LEDS_LP55XX_COMMON_H */
|
#endif /* _LEDS_LP55XX_COMMON_H */
|
||||||
|
@ -308,9 +308,16 @@ static int lp8501_probe(struct i2c_client *client,
|
|||||||
struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
|
struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||||
struct device_node *np = client->dev.of_node;
|
struct device_node *np = client->dev.of_node;
|
||||||
|
|
||||||
|
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
|
||||||
|
if (!chip)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
chip->cfg = &lp8501_cfg;
|
||||||
|
|
||||||
if (!pdata) {
|
if (!pdata) {
|
||||||
if (np) {
|
if (np) {
|
||||||
pdata = lp55xx_of_populate_pdata(&client->dev, np);
|
pdata = lp55xx_of_populate_pdata(&client->dev, np,
|
||||||
|
chip);
|
||||||
if (IS_ERR(pdata))
|
if (IS_ERR(pdata))
|
||||||
return PTR_ERR(pdata);
|
return PTR_ERR(pdata);
|
||||||
} else {
|
} else {
|
||||||
@ -319,10 +326,6 @@ static int lp8501_probe(struct i2c_client *client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
|
|
||||||
if (!chip)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
led = devm_kcalloc(&client->dev,
|
led = devm_kcalloc(&client->dev,
|
||||||
pdata->num_channels, sizeof(*led), GFP_KERNEL);
|
pdata->num_channels, sizeof(*led), GFP_KERNEL);
|
||||||
if (!led)
|
if (!led)
|
||||||
@ -330,7 +333,6 @@ static int lp8501_probe(struct i2c_client *client,
|
|||||||
|
|
||||||
chip->cl = client;
|
chip->cl = client;
|
||||||
chip->pdata = pdata;
|
chip->pdata = pdata;
|
||||||
chip->cfg = &lp8501_cfg;
|
|
||||||
|
|
||||||
mutex_init(&chip->lock);
|
mutex_init(&chip->lock);
|
||||||
|
|
||||||
|
@ -13,18 +13,25 @@
|
|||||||
#define _LEDS_LP55XX_H
|
#define _LEDS_LP55XX_H
|
||||||
|
|
||||||
#include <linux/gpio/consumer.h>
|
#include <linux/gpio/consumer.h>
|
||||||
|
#include <linux/led-class-multicolor.h>
|
||||||
|
|
||||||
/* Clock configuration */
|
/* Clock configuration */
|
||||||
#define LP55XX_CLOCK_AUTO 0
|
#define LP55XX_CLOCK_AUTO 0
|
||||||
#define LP55XX_CLOCK_INT 1
|
#define LP55XX_CLOCK_INT 1
|
||||||
#define LP55XX_CLOCK_EXT 2
|
#define LP55XX_CLOCK_EXT 2
|
||||||
|
|
||||||
|
#define LP55XX_MAX_GROUPED_CHAN 4
|
||||||
|
|
||||||
struct lp55xx_led_config {
|
struct lp55xx_led_config {
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *default_trigger;
|
const char *default_trigger;
|
||||||
u8 chan_nr;
|
u8 chan_nr;
|
||||||
u8 led_current; /* mA x10, 0 if led is not connected */
|
u8 led_current; /* mA x10, 0 if led is not connected */
|
||||||
u8 max_current;
|
u8 max_current;
|
||||||
|
int num_colors;
|
||||||
|
unsigned int max_channel;
|
||||||
|
int color_id[LED_COLOR_ID_MAX];
|
||||||
|
int output_num[LED_COLOR_ID_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lp55xx_predef_pattern {
|
struct lp55xx_predef_pattern {
|
||||||
|
Loading…
Reference in New Issue
Block a user