summaryrefslogtreecommitdiff
path: root/drivers/leds/rgb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/leds/rgb')
-rw-r--r--drivers/leds/rgb/Kconfig1
-rw-r--r--drivers/leds/rgb/leds-group-multicolor.c2
-rw-r--r--drivers/leds/rgb/leds-ktd202x.c82
-rw-r--r--drivers/leds/rgb/leds-mt6370-rgb.c42
-rw-r--r--drivers/leds/rgb/leds-ncp5623.c16
-rw-r--r--drivers/leds/rgb/leds-pwm-multicolor.c8
-rw-r--r--drivers/leds/rgb/leds-qcom-lpg.c30
7 files changed, 94 insertions, 87 deletions
diff --git a/drivers/leds/rgb/Kconfig b/drivers/leds/rgb/Kconfig
index 8fc12d6a2958..222d943d826a 100644
--- a/drivers/leds/rgb/Kconfig
+++ b/drivers/leds/rgb/Kconfig
@@ -17,7 +17,6 @@ config LEDS_GROUP_MULTICOLOR
config LEDS_KTD202X
tristate "LED support for KTD202x Chips"
depends on I2C
- depends on OF
select REGMAP_I2C
help
This option enables support for the Kinetic KTD2026/KTD2027
diff --git a/drivers/leds/rgb/leds-group-multicolor.c b/drivers/leds/rgb/leds-group-multicolor.c
index b6c7679015fd..548c7dd63ba1 100644
--- a/drivers/leds/rgb/leds-group-multicolor.c
+++ b/drivers/leds/rgb/leds-group-multicolor.c
@@ -55,7 +55,7 @@ static void restore_sysfs_write_access(void *data)
{
struct led_classdev *led_cdev = data;
- /* Restore the write acccess to the LED */
+ /* Restore the write access to the LED */
mutex_lock(&led_cdev->led_access);
led_sysfs_enable(led_cdev);
mutex_unlock(&led_cdev->led_access);
diff --git a/drivers/leds/rgb/leds-ktd202x.c b/drivers/leds/rgb/leds-ktd202x.c
index 514965795a10..04e62faa3a00 100644
--- a/drivers/leds/rgb/leds-ktd202x.c
+++ b/drivers/leds/rgb/leds-ktd202x.c
@@ -99,7 +99,7 @@ struct ktd202x {
struct device *dev;
struct regmap *regmap;
bool enabled;
- int num_leds;
+ unsigned long num_leds;
struct ktd202x_led leds[] __counted_by(num_leds);
};
@@ -381,16 +381,19 @@ static int ktd202x_blink_mc_set(struct led_classdev *cdev,
mc->num_colors);
}
-static int ktd202x_setup_led_rgb(struct ktd202x *chip, struct device_node *np,
+static int ktd202x_setup_led_rgb(struct ktd202x *chip, struct fwnode_handle *fwnode,
struct ktd202x_led *led, struct led_init_data *init_data)
{
+ struct fwnode_handle *child;
struct led_classdev *cdev;
- struct device_node *child;
struct mc_subled *info;
int num_channels;
int i = 0;
- num_channels = of_get_available_child_count(np);
+ num_channels = 0;
+ fwnode_for_each_available_child_node(fwnode, child)
+ num_channels++;
+
if (!num_channels || num_channels > chip->num_leds)
return -EINVAL;
@@ -398,22 +401,22 @@ static int ktd202x_setup_led_rgb(struct ktd202x *chip, struct device_node *np,
if (!info)
return -ENOMEM;
- for_each_available_child_of_node(np, child) {
+ fwnode_for_each_available_child_node(fwnode, child) {
u32 mono_color;
u32 reg;
int ret;
- ret = of_property_read_u32(child, "reg", &reg);
+ ret = fwnode_property_read_u32(child, "reg", &reg);
if (ret != 0 || reg >= chip->num_leds) {
- dev_err(chip->dev, "invalid 'reg' of %pOFn\n", child);
- of_node_put(child);
- return -EINVAL;
+ dev_err(chip->dev, "invalid 'reg' of %pfw\n", child);
+ fwnode_handle_put(child);
+ return ret;
}
- ret = of_property_read_u32(child, "color", &mono_color);
+ ret = fwnode_property_read_u32(child, "color", &mono_color);
if (ret < 0 && ret != -EINVAL) {
- dev_err(chip->dev, "failed to parse 'color' of %pOF\n", child);
- of_node_put(child);
+ dev_err(chip->dev, "failed to parse 'color' of %pfw\n", child);
+ fwnode_handle_put(child);
return ret;
}
@@ -433,16 +436,16 @@ static int ktd202x_setup_led_rgb(struct ktd202x *chip, struct device_node *np,
return devm_led_classdev_multicolor_register_ext(chip->dev, &led->mcdev, init_data);
}
-static int ktd202x_setup_led_single(struct ktd202x *chip, struct device_node *np,
+static int ktd202x_setup_led_single(struct ktd202x *chip, struct fwnode_handle *fwnode,
struct ktd202x_led *led, struct led_init_data *init_data)
{
struct led_classdev *cdev;
u32 reg;
int ret;
- ret = of_property_read_u32(np, "reg", &reg);
+ ret = fwnode_property_read_u32(fwnode, "reg", &reg);
if (ret != 0 || reg >= chip->num_leds) {
- dev_err(chip->dev, "invalid 'reg' of %pOFn\n", np);
+ dev_err(chip->dev, "invalid 'reg' of %pfw\n", fwnode);
return -EINVAL;
}
led->index = reg;
@@ -454,7 +457,7 @@ static int ktd202x_setup_led_single(struct ktd202x *chip, struct device_node *np
return devm_led_classdev_register_ext(chip->dev, &led->cdev, init_data);
}
-static int ktd202x_add_led(struct ktd202x *chip, struct device_node *np, unsigned int index)
+static int ktd202x_add_led(struct ktd202x *chip, struct fwnode_handle *fwnode, unsigned int index)
{
struct ktd202x_led *led = &chip->leds[index];
struct led_init_data init_data = {};
@@ -463,21 +466,21 @@ static int ktd202x_add_led(struct ktd202x *chip, struct device_node *np, unsigne
int ret;
/* Color property is optional in single color case */
- ret = of_property_read_u32(np, "color", &color);
+ ret = fwnode_property_read_u32(fwnode, "color", &color);
if (ret < 0 && ret != -EINVAL) {
- dev_err(chip->dev, "failed to parse 'color' of %pOF\n", np);
+ dev_err(chip->dev, "failed to parse 'color' of %pfw\n", fwnode);
return ret;
}
led->chip = chip;
- init_data.fwnode = of_fwnode_handle(np);
+ init_data.fwnode = fwnode;
if (color == LED_COLOR_ID_RGB) {
cdev = &led->mcdev.led_cdev;
- ret = ktd202x_setup_led_rgb(chip, np, led, &init_data);
+ ret = ktd202x_setup_led_rgb(chip, fwnode, led, &init_data);
} else {
cdev = &led->cdev;
- ret = ktd202x_setup_led_single(chip, np, led, &init_data);
+ ret = ktd202x_setup_led_single(chip, fwnode, led, &init_data);
}
if (ret) {
@@ -490,15 +493,13 @@ static int ktd202x_add_led(struct ktd202x *chip, struct device_node *np, unsigne
return 0;
}
-static int ktd202x_probe_dt(struct ktd202x *chip)
+static int ktd202x_probe_fw(struct ktd202x *chip)
{
- struct device_node *np = dev_of_node(chip->dev), *child;
+ struct device *dev = chip->dev;
int count;
int i = 0;
- chip->num_leds = (int)(unsigned long)of_device_get_match_data(chip->dev);
-
- count = of_get_available_child_count(np);
+ count = device_get_child_node_count(dev);
if (!count || count > chip->num_leds)
return -EINVAL;
@@ -507,13 +508,12 @@ static int ktd202x_probe_dt(struct ktd202x *chip)
/* Allow the device to execute the complete reset */
usleep_range(200, 300);
- for_each_available_child_of_node(np, child) {
+ device_for_each_child_node_scoped(dev, child) {
int ret = ktd202x_add_led(chip, child, i);
- if (ret) {
- of_node_put(child);
+ if (ret)
return ret;
- }
+
i++;
}
@@ -554,6 +554,12 @@ static int ktd202x_probe(struct i2c_client *client)
return ret;
}
+ ret = devm_mutex_init(dev, &chip->mutex);
+ if (ret)
+ return ret;
+
+ chip->num_leds = (unsigned long)i2c_get_match_data(client);
+
chip->regulators[0].supply = "vin";
chip->regulators[1].supply = "vio";
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(chip->regulators), chip->regulators);
@@ -568,7 +574,7 @@ static int ktd202x_probe(struct i2c_client *client)
return ret;
}
- ret = ktd202x_probe_dt(chip);
+ ret = ktd202x_probe_fw(chip);
if (ret < 0) {
regulator_bulk_disable(ARRAY_SIZE(chip->regulators), chip->regulators);
return ret;
@@ -580,8 +586,6 @@ static int ktd202x_probe(struct i2c_client *client)
return ret;
}
- mutex_init(&chip->mutex);
-
return 0;
}
@@ -590,8 +594,6 @@ static void ktd202x_remove(struct i2c_client *client)
struct ktd202x *chip = i2c_get_clientdata(client);
ktd202x_chip_disable(chip);
-
- mutex_destroy(&chip->mutex);
}
static void ktd202x_shutdown(struct i2c_client *client)
@@ -602,10 +604,17 @@ static void ktd202x_shutdown(struct i2c_client *client)
regmap_write(chip->regmap, KTD202X_REG_RESET_CONTROL, KTD202X_RSTR_RESET);
}
+static const struct i2c_device_id ktd202x_id[] = {
+ {"ktd2026", KTD2026_NUM_LEDS},
+ {"ktd2027", KTD2027_NUM_LEDS},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, ktd202x_id);
+
static const struct of_device_id ktd202x_match_table[] = {
{ .compatible = "kinetic,ktd2026", .data = (void *)KTD2026_NUM_LEDS },
{ .compatible = "kinetic,ktd2027", .data = (void *)KTD2027_NUM_LEDS },
- {},
+ {}
};
MODULE_DEVICE_TABLE(of, ktd202x_match_table);
@@ -617,6 +626,7 @@ static struct i2c_driver ktd202x_driver = {
.probe = ktd202x_probe,
.remove = ktd202x_remove,
.shutdown = ktd202x_shutdown,
+ .id_table = ktd202x_id,
};
module_i2c_driver(ktd202x_driver);
diff --git a/drivers/leds/rgb/leds-mt6370-rgb.c b/drivers/leds/rgb/leds-mt6370-rgb.c
index 448d0da11848..ebd3ba878dd5 100644
--- a/drivers/leds/rgb/leds-mt6370-rgb.c
+++ b/drivers/leds/rgb/leds-mt6370-rgb.c
@@ -21,7 +21,7 @@
#include <linux/regmap.h>
#include <linux/util_macros.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
enum {
MT6370_LED_ISNK1 = 0,
@@ -149,7 +149,6 @@ struct mt6370_priv {
struct regmap_field *fields[F_MAX_FIELDS];
const struct reg_field *reg_fields;
const struct linear_range *ranges;
- struct reg_cfg *reg_cfgs;
const struct mt6370_pdata *pdata;
unsigned int leds_count;
unsigned int leds_active;
@@ -588,7 +587,7 @@ static inline int mt6370_mc_pattern_clear(struct led_classdev *lcdev)
struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc);
struct mt6370_priv *priv = led->priv;
struct mc_subled *subled;
- int i, ret;
+ int i, ret = 0;
mutex_lock(&led->priv->lock);
@@ -906,7 +905,6 @@ static int mt6370_leds_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mt6370_priv *priv;
- struct fwnode_handle *child;
size_t count;
unsigned int i = 0;
int ret;
@@ -937,37 +935,27 @@ static int mt6370_leds_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "Failed to allocate regmap field\n");
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
struct mt6370_led *led = priv->leds + i++;
struct led_init_data init_data = { .fwnode = child };
u32 reg, color;
ret = fwnode_property_read_u32(child, "reg", &reg);
- if (ret) {
- dev_err(dev, "Failed to parse reg property\n");
- goto fwnode_release;
- }
+ if (ret)
+ dev_err_probe(dev, ret, "Failed to parse reg property\n");
- if (reg >= MT6370_MAX_LEDS) {
- ret = -EINVAL;
- dev_err(dev, "Error reg property number\n");
- goto fwnode_release;
- }
+ if (reg >= MT6370_MAX_LEDS)
+ return dev_err_probe(dev, -EINVAL, "Error reg property number\n");
ret = fwnode_property_read_u32(child, "color", &color);
- if (ret) {
- dev_err(dev, "Failed to parse color property\n");
- goto fwnode_release;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to parse color property\n");
if (color == LED_COLOR_ID_RGB || color == LED_COLOR_ID_MULTI)
reg = MT6370_VIRTUAL_MULTICOLOR;
- if (priv->leds_active & BIT(reg)) {
- ret = -EINVAL;
- dev_err(dev, "Duplicate reg property\n");
- goto fwnode_release;
- }
+ if (priv->leds_active & BIT(reg))
+ return dev_err_probe(dev, -EINVAL, "Duplicate reg property\n");
priv->leds_active |= BIT(reg);
@@ -976,18 +964,14 @@ static int mt6370_leds_probe(struct platform_device *pdev)
ret = mt6370_init_led_properties(dev, led, &init_data);
if (ret)
- goto fwnode_release;
+ return ret;
ret = mt6370_led_register(dev, led, &init_data);
if (ret)
- goto fwnode_release;
+ return ret;
}
return 0;
-
-fwnode_release:
- fwnode_handle_put(child);
- return ret;
}
static const struct of_device_id mt6370_rgbled_device_table[] = {
diff --git a/drivers/leds/rgb/leds-ncp5623.c b/drivers/leds/rgb/leds-ncp5623.c
index 2be4ff918516..f18156683375 100644
--- a/drivers/leds/rgb/leds-ncp5623.c
+++ b/drivers/leds/rgb/leds-ncp5623.c
@@ -183,16 +183,12 @@ static int ncp5623_probe(struct i2c_client *client)
fwnode_for_each_available_child_node(mc_node, led_node) {
ret = fwnode_property_read_u32(led_node, "color", &color_index);
- if (ret) {
- fwnode_handle_put(led_node);
- goto release_mc_node;
- }
+ if (ret)
+ goto release_led_node;
ret = fwnode_property_read_u32(led_node, "reg", &reg);
- if (ret) {
- fwnode_handle_put(led_node);
- goto release_mc_node;
- }
+ if (ret)
+ goto release_led_node;
subled_info[ncp->mc_dev.num_colors].channel = reg;
subled_info[ncp->mc_dev.num_colors++].color_index = color_index;
@@ -223,6 +219,10 @@ release_mc_node:
fwnode_handle_put(mc_node);
return ret;
+
+release_led_node:
+ fwnode_handle_put(led_node);
+ goto release_mc_node;
}
static void ncp5623_remove(struct i2c_client *client)
diff --git a/drivers/leds/rgb/leds-pwm-multicolor.c b/drivers/leds/rgb/leds-pwm-multicolor.c
index e1a81e0109e8..f80a06cc31f8 100644
--- a/drivers/leds/rgb/leds-pwm-multicolor.c
+++ b/drivers/leds/rgb/leds-pwm-multicolor.c
@@ -50,7 +50,13 @@ static int led_pwm_mc_set(struct led_classdev *cdev,
duty = priv->leds[i].state.period - duty;
priv->leds[i].state.duty_cycle = duty;
- priv->leds[i].state.enabled = duty > 0;
+ /*
+ * Disabling a PWM doesn't guarantee that it emits the inactive level.
+ * So keep it on. Only for suspending the PWM should be disabled because
+ * otherwise it refuses to suspend. The possible downside is that the
+ * LED might stay (or even go) on.
+ */
+ priv->leds[i].state.enabled = !(cdev->flags & LED_SUSPENDED);
ret = pwm_apply_might_sleep(priv->leds[i].pwm,
&priv->leds[i].state);
if (ret)
diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c
index 6bdc5b923f98..f3c9ef2bfa57 100644
--- a/drivers/leds/rgb/leds-qcom-lpg.c
+++ b/drivers/leds/rgb/leds-qcom-lpg.c
@@ -2,7 +2,7 @@
/*
* Copyright (c) 2017-2022 Linaro Ltd
* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
- * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/bits.h>
#include <linux/bitfield.h>
@@ -254,6 +254,9 @@ static int lpg_clear_pbs_trigger(struct lpg *lpg, unsigned int lut_mask)
u8 val = 0;
int rc;
+ if (!lpg->lpg_chan_sdam)
+ return 0;
+
lpg->pbs_en_bitmap &= (~lut_mask);
if (!lpg->pbs_en_bitmap) {
rc = nvmem_device_write(lpg->lpg_chan_sdam, SDAM_REG_PBS_SEQ_EN, 1, &val);
@@ -276,6 +279,9 @@ static int lpg_set_pbs_trigger(struct lpg *lpg, unsigned int lut_mask)
u8 val = PBS_SW_TRIG_BIT;
int rc;
+ if (!lpg->lpg_chan_sdam)
+ return 0;
+
if (!lpg->pbs_en_bitmap) {
rc = nvmem_device_write(lpg->lpg_chan_sdam, SDAM_REG_PBS_SEQ_EN, 1, &val);
if (rc < 0)
@@ -1362,7 +1368,6 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np)
{
struct led_init_data init_data = {};
struct led_classdev *cdev;
- struct device_node *child;
struct mc_subled *info;
struct lpg_led *led;
const char *state;
@@ -1393,12 +1398,10 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np)
if (!info)
return -ENOMEM;
i = 0;
- for_each_available_child_of_node(np, child) {
+ for_each_available_child_of_node_scoped(np, child) {
ret = lpg_parse_channel(lpg, child, &led->channels[i]);
- if (ret < 0) {
- of_node_put(child);
+ if (ret < 0)
return ret;
- }
info[i].color_index = led->channels[i]->color;
info[i].intensity = 0;
@@ -1594,7 +1597,6 @@ static int lpg_init_sdam(struct lpg *lpg)
static int lpg_probe(struct platform_device *pdev)
{
- struct device_node *np;
struct lpg *lpg;
int ret;
int i;
@@ -1634,12 +1636,10 @@ static int lpg_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
- for_each_available_child_of_node(pdev->dev.of_node, np) {
+ for_each_available_child_of_node_scoped(pdev->dev.of_node, np) {
ret = lpg_add_led(lpg, np);
- if (ret) {
- of_node_put(np);
+ if (ret)
return ret;
- }
}
for (i = 0; i < lpg->num_channels; i++)
@@ -1693,6 +1693,13 @@ static const struct lpg_data pm8941_lpg_data = {
},
};
+static const struct lpg_data pmi8950_pwm_data = {
+ .num_channels = 1,
+ .channels = (const struct lpg_channel_data[]) {
+ { .base = 0xb000 },
+ },
+};
+
static const struct lpg_data pm8994_lpg_data = {
.lut_base = 0xb000,
.lut_size = 64,
@@ -1819,6 +1826,7 @@ static const struct of_device_id lpg_of_table[] = {
{ .compatible = "qcom,pm8941-lpg", .data = &pm8941_lpg_data },
{ .compatible = "qcom,pm8994-lpg", .data = &pm8994_lpg_data },
{ .compatible = "qcom,pmi632-lpg", .data = &pmi632_lpg_data },
+ { .compatible = "qcom,pmi8950-pwm", .data = &pmi8950_pwm_data },
{ .compatible = "qcom,pmi8994-lpg", .data = &pmi8994_lpg_data },
{ .compatible = "qcom,pmi8998-lpg", .data = &pmi8998_lpg_data },
{ .compatible = "qcom,pmc8180c-lpg", .data = &pm8150l_lpg_data },