aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2024-05-02 14:31:22 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2024-05-02 14:31:22 +1000
commit7c2f00675b64dfa2e23af401213d86e0cdcf294f (patch)
tree8a74561b50e151a716be040e622bdb98a3348237
parent4fe39f7245d667467d50a6b4e346c2435eb0221d (diff)
parentfd05e3698649f253db5476929675a8cd954cb2b8 (diff)
downloadlinux-next-history-7c2f00675b64dfa2e23af401213d86e0cdcf294f.tar.gz
Merge branch 'for-leds-next' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds.git
Notice: this object is not reachable from any branch.
Notice: this object is not reachable from any branch.
-rw-r--r--Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml8
-rw-r--r--Documentation/devicetree/bindings/leds/nxp,pca963x.yaml140
-rw-r--r--Documentation/devicetree/bindings/leds/pca963x.txt52
-rw-r--r--arch/mips/configs/ci20_defconfig1
-rw-r--r--drivers/leds/flash/leds-mt6360.c12
-rw-r--r--drivers/leds/led-triggers.c6
-rw-r--r--drivers/leds/leds-an30259a.c14
-rw-r--r--drivers/leds/leds-apu.c3
-rw-r--r--drivers/leds/leds-aw200xx.c32
-rw-r--r--drivers/leds/leds-aw2013.c25
-rw-r--r--drivers/leds/leds-lm3532.c29
-rw-r--r--drivers/leds/leds-lp3952.c21
-rw-r--r--drivers/leds/leds-mlxreg.c14
-rw-r--r--drivers/leds/leds-nic78bx.c23
-rw-r--r--drivers/leds/rgb/leds-qcom-lpg.c8
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio-core.c1
-rw-r--r--drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c52
-rw-r--r--drivers/leds/trigger/Kconfig7
-rw-r--r--drivers/leds/trigger/Makefile1
-rw-r--r--drivers/leds/trigger/ledtrig-audio.c67
-rw-r--r--drivers/leds/trigger/ledtrig-netdev.c2
-rw-r--r--include/dt-bindings/leds/common.h3
-rw-r--r--include/linux/leds.h29
-rw-r--r--include/linux/mutex.h27
-rw-r--r--kernel/locking/mutex-debug.c12
-rw-r--r--sound/core/Kconfig1
-rw-r--r--sound/core/control_led.c20
27 files changed, 375 insertions, 235 deletions
diff --git a/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml b/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
index 54a428d3d46ffe..8b82c45d1a48be 100644
--- a/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
+++ b/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
@@ -27,11 +27,16 @@ properties:
- qcom,pm8994-lpg
- qcom,pmc8180c-lpg
- qcom,pmi632-lpg
+ - qcom,pmi8950-pwm
- qcom,pmi8994-lpg
- qcom,pmi8998-lpg
- qcom,pmk8550-pwm
- items:
- enum:
+ - qcom,pm6150l-lpg
+ - const: qcom,pm8150l-lpg
+ - items:
+ - enum:
- qcom,pm8550-pwm
- const: qcom,pm8350c-pwm
@@ -142,6 +147,7 @@ allOf:
- qcom,pm8941-lpg
- qcom,pm8994-lpg
- qcom,pmc8180c-lpg
+ - qcom,pmi8950-pwm
- qcom,pmi8994-lpg
- qcom,pmi8998-lpg
- qcom,pmk8550-pwm
@@ -290,5 +296,3 @@ examples:
label = "blue";
};
};
-
-...
diff --git a/Documentation/devicetree/bindings/leds/nxp,pca963x.yaml b/Documentation/devicetree/bindings/leds/nxp,pca963x.yaml
new file mode 100644
index 00000000000000..938d0e48fe51bc
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/nxp,pca963x.yaml
@@ -0,0 +1,140 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/nxp,pca963x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP PCA963x LED controllers
+
+maintainers:
+ - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+description: |
+ The NXP PCA963x are I2C-controlled LED drivers optimized for
+ Red/Green/Blue/Amber (RGBA) color mixing applications. Each LED is
+ individually controllable and has its own PWM controller.
+
+ Datasheets are available at
+
+ - https://www.nxp.com/docs/en/data-sheet/PCA9632.pdf
+ - https://www.nxp.com/docs/en/data-sheet/PCA9633.pdf
+ - https://www.nxp.com/docs/en/data-sheet/PCA9634.pdf
+ - https://www.nxp.com/docs/en/data-sheet/PCA9635.pdf
+
+properties:
+ compatible:
+ enum:
+ - nxp,pca9632
+ - nxp,pca9633
+ - nxp,pca9634
+ - nxp,pca9635
+
+ reg:
+ maxItems: 1
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ nxp,hw-blink:
+ type: boolean
+ description:
+ Use hardware blinking instead of software blinking
+
+ nxp,inverted-out:
+ type: boolean
+ description:
+ Invert the polarity of the generated PWM.
+
+ nxp,period-scale:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ In some configurations, the chip blinks faster than expected. This
+ parameter provides a scaling ratio (fixed point, decimal divided by 1000)
+ to compensate, e.g. 1300=1.3x and 750=0.75x.
+
+ nxp,totem-pole:
+ type: boolean
+ description:
+ Use totem pole (push-pull) instead of open-drain (pca9632 defaults to
+ open-drain, newer chips to totem pole).
+
+patternProperties:
+ "^led@[0-9a-f]+$":
+ type: object
+ $ref: common.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ minimum: 0
+
+ required:
+ - reg
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nxp,pca9632
+ - nxp,pca9633
+ then:
+ patternProperties:
+ "^led@[0-9a-f]+$":
+ properties:
+ reg:
+ maximum: 3
+ else:
+ patternProperties:
+ "^led@[0-9a-f]+$":
+ properties:
+ reg:
+ maximum: 7
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/leds/common.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led-controller@62 {
+ compatible = "nxp,pca9632";
+ reg = <0x62>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_STATUS;
+ };
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_STATUS;
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_STATUS;
+ };
+
+ led@3 {
+ reg = <3>;
+ color = <LED_COLOR_ID_WHITE>;
+ function = LED_FUNCTION_STATUS;
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/leds/pca963x.txt b/Documentation/devicetree/bindings/leds/pca963x.txt
deleted file mode 100644
index 4eee41482041f5..00000000000000
--- a/Documentation/devicetree/bindings/leds/pca963x.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-LEDs connected to pca9632, pca9633 or pca9634
-
-Required properties:
-- compatible : should be : "nxp,pca9632", "nxp,pca9633", "nxp,pca9634" or "nxp,pca9635"
-
-Optional properties:
-- nxp,totem-pole : use totem pole (push-pull) instead of open-drain (pca9632 defaults
- to open-drain, newer chips to totem pole)
-- nxp,hw-blink : use hardware blinking instead of software blinking
-- nxp,period-scale : In some configurations, the chip blinks faster than expected.
- This parameter provides a scaling ratio (fixed point, decimal divided
- by 1000) to compensate, e.g. 1300=1.3x and 750=0.75x.
-- nxp,inverted-out: invert the polarity of the generated PWM
-
-Each led is represented as a sub-node of the nxp,pca963x device.
-
-LED sub-node properties:
-- label : (optional) see Documentation/devicetree/bindings/leds/common.txt
-- reg : number of LED line (could be from 0 to 3 in pca9632 or pca9633,
- 0 to 7 in pca9634, or 0 to 15 in pca9635)
-- linux,default-trigger : (optional)
- see Documentation/devicetree/bindings/leds/common.txt
-
-Examples:
-
-pca9632: pca9632 {
- compatible = "nxp,pca9632";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x62>;
-
- red@0 {
- label = "red";
- reg = <0>;
- linux,default-trigger = "none";
- };
- green@1 {
- label = "green";
- reg = <1>;
- linux,default-trigger = "none";
- };
- blue@2 {
- label = "blue";
- reg = <2>;
- linux,default-trigger = "none";
- };
- unused@3 {
- label = "unused";
- reg = <3>;
- linux,default-trigger = "none";
- };
-};
diff --git a/arch/mips/configs/ci20_defconfig b/arch/mips/configs/ci20_defconfig
index cdf2a782dee130..7827b2b392f670 100644
--- a/arch/mips/configs/ci20_defconfig
+++ b/arch/mips/configs/ci20_defconfig
@@ -152,7 +152,6 @@ CONFIG_LEDS_TRIGGER_CAMERA=m
CONFIG_LEDS_TRIGGER_PANIC=y
CONFIG_LEDS_TRIGGER_NETDEV=y
CONFIG_LEDS_TRIGGER_PATTERN=y
-CONFIG_LEDS_TRIGGER_AUDIO=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_JZ4740=y
CONFIG_DMADEVICES=y
diff --git a/drivers/leds/flash/leds-mt6360.c b/drivers/leds/flash/leds-mt6360.c
index a90de82f456837..1b75b4d3683486 100644
--- a/drivers/leds/flash/leds-mt6360.c
+++ b/drivers/leds/flash/leds-mt6360.c
@@ -241,11 +241,21 @@ static int mt6360_strobe_set(struct led_classdev_flash *fl_cdev, bool state)
u32 enable_mask = MT6360_STROBEN_MASK | MT6360_FLCSEN_MASK(led->led_no);
u32 val = state ? MT6360_FLCSEN_MASK(led->led_no) : 0;
u32 prev = priv->fled_strobe_used, curr;
- int ret;
+ int ret = 0;
mutex_lock(&priv->lock);
/*
+ * If the state of the upcoming change is the same as the current LED
+ * device state, then skip the subsequent code to avoid conflict
+ * with the flow of turning on LED torch mode in V4L2.
+ */
+ if (state == !!(BIT(led->led_no) & prev)) {
+ dev_info(lcdev->dev, "No change in strobe state [0x%x]\n", prev);
+ goto unlock;
+ }
+
+ /*
* Only one set of flash control logic, use the flag to avoid torch is
* currently used
*/
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index 0f5ac30053ad26..b1b323b19301d2 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -194,11 +194,11 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
spin_unlock(&trig->leddev_list_lock);
led_cdev->trigger = trig;
+ ret = 0;
if (trig->activate)
ret = trig->activate(led_cdev);
else
- ret = 0;
-
+ led_set_brightness(led_cdev, trig->brightness);
if (ret)
goto err_activate;
@@ -387,6 +387,8 @@ void led_trigger_event(struct led_trigger *trig,
if (!trig)
return;
+ trig->brightness = brightness;
+
rcu_read_lock();
list_for_each_entry_rcu(led_cdev, &trig->led_cdevs, trig_list)
led_set_brightness(led_cdev, brightness);
diff --git a/drivers/leds/leds-an30259a.c b/drivers/leds/leds-an30259a.c
index 0216afed3b6e72..decfca447d8a7a 100644
--- a/drivers/leds/leds-an30259a.c
+++ b/drivers/leds/leds-an30259a.c
@@ -283,7 +283,10 @@ static int an30259a_probe(struct i2c_client *client)
if (err < 0)
return err;
- mutex_init(&chip->mutex);
+ err = devm_mutex_init(&client->dev, &chip->mutex);
+ if (err)
+ return err;
+
chip->client = client;
i2c_set_clientdata(client, chip);
@@ -317,17 +320,9 @@ static int an30259a_probe(struct i2c_client *client)
return 0;
exit:
- mutex_destroy(&chip->mutex);
return err;
}
-static void an30259a_remove(struct i2c_client *client)
-{
- struct an30259a *chip = i2c_get_clientdata(client);
-
- mutex_destroy(&chip->mutex);
-}
-
static const struct of_device_id an30259a_match_table[] = {
{ .compatible = "panasonic,an30259a", },
{ /* sentinel */ },
@@ -347,7 +342,6 @@ static struct i2c_driver an30259a_driver = {
.of_match_table = an30259a_match_table,
},
.probe = an30259a_probe,
- .remove = an30259a_remove,
.id_table = an30259a_id,
};
diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c
index c409b80c236d71..1c116aaa9b6e39 100644
--- a/drivers/leds/leds-apu.c
+++ b/drivers/leds/leds-apu.c
@@ -181,8 +181,7 @@ static int __init apu_led_init(void)
struct platform_device *pdev;
int err;
- if (!(dmi_match(DMI_SYS_VENDOR, "PC Engines") &&
- (dmi_match(DMI_PRODUCT_NAME, "APU") || dmi_match(DMI_PRODUCT_NAME, "apu1")))) {
+ if (!dmi_check_system(apu_led_dmi_table)) {
pr_err("No PC Engines APUv1 board detected. For APUv2,3 support, enable CONFIG_PCENGINES_APU2\n");
return -ENODEV;
}
diff --git a/drivers/leds/leds-aw200xx.c b/drivers/leds/leds-aw200xx.c
index 6c8c9f2c19e339..f9d9844e027380 100644
--- a/drivers/leds/leds-aw200xx.c
+++ b/drivers/leds/leds-aw200xx.c
@@ -530,6 +530,16 @@ static const struct regmap_config aw200xx_regmap_config = {
.disable_locking = true,
};
+static void aw200xx_chip_reset_action(void *data)
+{
+ aw200xx_chip_reset(data);
+}
+
+static void aw200xx_disable_action(void *data)
+{
+ aw200xx_disable(data);
+}
+
static int aw200xx_probe(struct i2c_client *client)
{
const struct aw200xx_chipdef *cdef;
@@ -568,11 +578,17 @@ static int aw200xx_probe(struct i2c_client *client)
aw200xx_enable(chip);
+ ret = devm_add_action(&client->dev, aw200xx_disable_action, chip);
+ if (ret)
+ return ret;
+
ret = aw200xx_chip_check(chip);
if (ret)
return ret;
- mutex_init(&chip->mutex);
+ ret = devm_mutex_init(&client->dev, &chip->mutex);
+ if (ret)
+ return ret;
/* Need a lock now since after call aw200xx_probe_fw, sysfs nodes created */
mutex_lock(&chip->mutex);
@@ -581,6 +597,10 @@ static int aw200xx_probe(struct i2c_client *client)
if (ret)
goto out_unlock;
+ ret = devm_add_action(&client->dev, aw200xx_chip_reset_action, chip);
+ if (ret)
+ goto out_unlock;
+
ret = aw200xx_probe_fw(&client->dev, chip);
if (ret)
goto out_unlock;
@@ -595,15 +615,6 @@ out_unlock:
return ret;
}
-static void aw200xx_remove(struct i2c_client *client)
-{
- struct aw200xx *chip = i2c_get_clientdata(client);
-
- aw200xx_chip_reset(chip);
- aw200xx_disable(chip);
- mutex_destroy(&chip->mutex);
-}
-
static const struct aw200xx_chipdef aw20036_cdef = {
.channels = 36,
.display_size_rows_max = 3,
@@ -652,7 +663,6 @@ static struct i2c_driver aw200xx_driver = {
.of_match_table = aw200xx_match_table,
},
.probe = aw200xx_probe,
- .remove = aw200xx_remove,
.id_table = aw200xx_id,
};
module_i2c_driver(aw200xx_driver);
diff --git a/drivers/leds/leds-aw2013.c b/drivers/leds/leds-aw2013.c
index 17235a5e576aef..6475eadcb0df94 100644
--- a/drivers/leds/leds-aw2013.c
+++ b/drivers/leds/leds-aw2013.c
@@ -320,6 +320,11 @@ static int aw2013_probe_dt(struct aw2013 *chip)
return 0;
}
+static void aw2013_chip_disable_action(void *data)
+{
+ aw2013_chip_disable(data);
+}
+
static const struct regmap_config aw2013_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -336,7 +341,10 @@ static int aw2013_probe(struct i2c_client *client)
if (!chip)
return -ENOMEM;
- mutex_init(&chip->mutex);
+ ret = devm_mutex_init(&client->dev, &chip->mutex);
+ if (ret)
+ return ret;
+
mutex_lock(&chip->mutex);
chip->client = client;
@@ -384,6 +392,10 @@ static int aw2013_probe(struct i2c_client *client)
goto error_reg;
}
+ ret = devm_add_action(&client->dev, aw2013_chip_disable_action, chip);
+ if (ret)
+ goto error_reg;
+
ret = aw2013_probe_dt(chip);
if (ret < 0)
goto error_reg;
@@ -406,19 +418,9 @@ error_reg:
error:
mutex_unlock(&chip->mutex);
- mutex_destroy(&chip->mutex);
return ret;
}
-static void aw2013_remove(struct i2c_client *client)
-{
- struct aw2013 *chip = i2c_get_clientdata(client);
-
- aw2013_chip_disable(chip);
-
- mutex_destroy(&chip->mutex);
-}
-
static const struct of_device_id aw2013_match_table[] = {
{ .compatible = "awinic,aw2013", },
{ /* sentinel */ },
@@ -432,7 +434,6 @@ static struct i2c_driver aw2013_driver = {
.of_match_table = aw2013_match_table,
},
.probe = aw2013_probe,
- .remove = aw2013_remove,
};
module_i2c_driver(aw2013_driver);
diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c
index 13662a4aa1f265..8c90701dc50de5 100644
--- a/drivers/leds/leds-lm3532.c
+++ b/drivers/leds/leds-lm3532.c
@@ -542,6 +542,13 @@ static int lm3532_parse_als(struct lm3532_data *priv)
return ret;
}
+static void gpio_set_low_action(void *data)
+{
+ struct lm3532_data *priv = data;
+
+ gpiod_direction_output(priv->enable_gpio, 0);
+}
+
static int lm3532_parse_node(struct lm3532_data *priv)
{
struct fwnode_handle *child = NULL;
@@ -556,6 +563,12 @@ static int lm3532_parse_node(struct lm3532_data *priv)
if (IS_ERR(priv->enable_gpio))
priv->enable_gpio = NULL;
+ if (priv->enable_gpio) {
+ ret = devm_add_action(&priv->client->dev, gpio_set_low_action, priv);
+ if (ret)
+ return ret;
+ }
+
priv->regulator = devm_regulator_get(&priv->client->dev, "vin");
if (IS_ERR(priv->regulator))
priv->regulator = NULL;
@@ -691,7 +704,10 @@ static int lm3532_probe(struct i2c_client *client)
return ret;
}
- mutex_init(&drvdata->lock);
+ ret = devm_mutex_init(&client->dev, &drvdata->lock);
+ if (ret)
+ return ret;
+
i2c_set_clientdata(client, drvdata);
ret = lm3532_parse_node(drvdata);
@@ -703,16 +719,6 @@ static int lm3532_probe(struct i2c_client *client)
return ret;
}
-static void lm3532_remove(struct i2c_client *client)
-{
- struct lm3532_data *drvdata = i2c_get_clientdata(client);
-
- mutex_destroy(&drvdata->lock);
-
- if (drvdata->enable_gpio)
- gpiod_direction_output(drvdata->enable_gpio, 0);
-}
-
static const struct of_device_id of_lm3532_leds_match[] = {
{ .compatible = "ti,lm3532", },
{},
@@ -727,7 +733,6 @@ MODULE_DEVICE_TABLE(i2c, lm3532_id);
static struct i2c_driver lm3532_i2c_driver = {
.probe = lm3532_probe,
- .remove = lm3532_remove,
.id_table = lm3532_id,
.driver = {
.name = LM3532_NAME,
diff --git a/drivers/leds/leds-lp3952.c b/drivers/leds/leds-lp3952.c
index 5d18bbfd1f2318..ff7bae2447dd1b 100644
--- a/drivers/leds/leds-lp3952.c
+++ b/drivers/leds/leds-lp3952.c
@@ -207,6 +207,13 @@ static const struct regmap_config lp3952_regmap = {
.cache_type = REGCACHE_MAPLE,
};
+static void gpio_set_low_action(void *data)
+{
+ struct lp3952_led_array *priv = data;
+
+ gpiod_set_value(priv->enable_gpio, 0);
+}
+
static int lp3952_probe(struct i2c_client *client)
{
int status;
@@ -226,6 +233,10 @@ static int lp3952_probe(struct i2c_client *client)
return status;
}
+ status = devm_add_action(&client->dev, gpio_set_low_action, priv);
+ if (status)
+ return status;
+
priv->regmap = devm_regmap_init_i2c(client, &lp3952_regmap);
if (IS_ERR(priv->regmap)) {
int err = PTR_ERR(priv->regmap);
@@ -254,15 +265,6 @@ static int lp3952_probe(struct i2c_client *client)
return 0;
}
-static void lp3952_remove(struct i2c_client *client)
-{
- struct lp3952_led_array *priv;
-
- priv = i2c_get_clientdata(client);
- lp3952_on_off(priv, LP3952_LED_ALL, false);
- gpiod_set_value(priv->enable_gpio, 0);
-}
-
static const struct i2c_device_id lp3952_id[] = {
{LP3952_NAME, 0},
{}
@@ -274,7 +276,6 @@ static struct i2c_driver lp3952_i2c_driver = {
.name = LP3952_NAME,
},
.probe = lp3952_probe,
- .remove = lp3952_remove,
.id_table = lp3952_id,
};
diff --git a/drivers/leds/leds-mlxreg.c b/drivers/leds/leds-mlxreg.c
index 5595788d98d202..1b70de72376ccd 100644
--- a/drivers/leds/leds-mlxreg.c
+++ b/drivers/leds/leds-mlxreg.c
@@ -256,6 +256,7 @@ static int mlxreg_led_probe(struct platform_device *pdev)
{
struct mlxreg_core_platform_data *led_pdata;
struct mlxreg_led_priv_data *priv;
+ int err;
led_pdata = dev_get_platdata(&pdev->dev);
if (!led_pdata) {
@@ -267,26 +268,21 @@ static int mlxreg_led_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- mutex_init(&priv->access_lock);
+ err = devm_mutex_init(&pdev->dev, &priv->access_lock);
+ if (err)
+ return err;
+
priv->pdev = pdev;
priv->pdata = led_pdata;
return mlxreg_led_config(priv);
}
-static void mlxreg_led_remove(struct platform_device *pdev)
-{
- struct mlxreg_led_priv_data *priv = dev_get_drvdata(&pdev->dev);
-
- mutex_destroy(&priv->access_lock);
-}
-
static struct platform_driver mlxreg_led_driver = {
.driver = {
.name = "leds-mlxreg",
},
.probe = mlxreg_led_probe,
- .remove_new = mlxreg_led_remove,
};
module_platform_driver(mlxreg_led_driver);
diff --git a/drivers/leds/leds-nic78bx.c b/drivers/leds/leds-nic78bx.c
index a86b43dd995ee4..282d9e4cf116f8 100644
--- a/drivers/leds/leds-nic78bx.c
+++ b/drivers/leds/leds-nic78bx.c
@@ -118,6 +118,15 @@ static struct nic78bx_led nic78bx_leds[] = {
}
};
+static void lock_led_reg_action(void *data)
+{
+ struct nic78bx_led_data *led_data = data;
+
+ /* Lock LED register */
+ outb(NIC78BX_LOCK_VALUE,
+ led_data->io_base + NIC78BX_LOCK_REG_OFFSET);
+}
+
static int nic78bx_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -152,6 +161,10 @@ static int nic78bx_probe(struct platform_device *pdev)
led_data->io_base = io_rc->start;
spin_lock_init(&led_data->lock);
+ ret = devm_add_action(dev, lock_led_reg_action, led_data);
+ if (ret)
+ return ret;
+
for (i = 0; i < ARRAY_SIZE(nic78bx_leds); i++) {
nic78bx_leds[i].data = led_data;
@@ -167,15 +180,6 @@ static int nic78bx_probe(struct platform_device *pdev)
return ret;
}
-static void nic78bx_remove(struct platform_device *pdev)
-{
- struct nic78bx_led_data *led_data = platform_get_drvdata(pdev);
-
- /* Lock LED register */
- outb(NIC78BX_LOCK_VALUE,
- led_data->io_base + NIC78BX_LOCK_REG_OFFSET);
-}
-
static const struct acpi_device_id led_device_ids[] = {
{"NIC78B3", 0},
{"", 0},
@@ -184,7 +188,6 @@ MODULE_DEVICE_TABLE(acpi, led_device_ids);
static struct platform_driver led_driver = {
.probe = nic78bx_probe,
- .remove_new = nic78bx_remove,
.driver = {
.name = KBUILD_MODNAME,
.acpi_match_table = ACPI_PTR(led_device_ids),
diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c
index 6bdc5b923f9818..9467c796bd041f 100644
--- a/drivers/leds/rgb/leds-qcom-lpg.c
+++ b/drivers/leds/rgb/leds-qcom-lpg.c
@@ -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 },
diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-core.c b/drivers/leds/simple/simatic-ipc-leds-gpio-core.c
index 667ba1bc3a30fe..85003fd7f1aabe 100644
--- a/drivers/leds/simple/simatic-ipc-leds-gpio-core.c
+++ b/drivers/leds/simple/simatic-ipc-leds-gpio-core.c
@@ -56,6 +56,7 @@ int simatic_ipc_leds_gpio_probe(struct platform_device *pdev,
case SIMATIC_IPC_DEVICE_127E:
case SIMATIC_IPC_DEVICE_227G:
case SIMATIC_IPC_DEVICE_BX_21A:
+ case SIMATIC_IPC_DEVICE_BX_59A:
break;
default:
return -ENODEV;
diff --git a/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c b/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c
index c7c3a1f986e61d..7a5018639aafe3 100644
--- a/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c
+++ b/drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c
@@ -17,7 +17,12 @@
#include "simatic-ipc-leds-gpio.h"
-static struct gpiod_lookup_table simatic_ipc_led_gpio_table = {
+struct simatic_ipc_led_tables {
+ struct gpiod_lookup_table *led_lookup_table;
+ struct gpiod_lookup_table *led_lookup_table_extra;
+};
+
+static struct gpiod_lookup_table simatic_ipc_led_gpio_table_227g = {
.dev_id = "leds-gpio",
.table = {
GPIO_LOOKUP_IDX("gpio-f7188x-2", 0, NULL, 0, GPIO_ACTIVE_LOW),
@@ -30,7 +35,7 @@ static struct gpiod_lookup_table simatic_ipc_led_gpio_table = {
},
};
-static struct gpiod_lookup_table simatic_ipc_led_gpio_table_extra = {
+static struct gpiod_lookup_table simatic_ipc_led_gpio_table_extra_227g = {
.dev_id = NULL, /* Filled during initialization */
.table = {
GPIO_LOOKUP_IDX("gpio-f7188x-3", 6, NULL, 6, GPIO_ACTIVE_HIGH),
@@ -39,16 +44,51 @@ static struct gpiod_lookup_table simatic_ipc_led_gpio_table_extra = {
},
};
+static struct gpiod_lookup_table simatic_ipc_led_gpio_table_bx_59a = {
+ .dev_id = "leds-gpio",
+ .table = {
+ GPIO_LOOKUP_IDX("gpio-f7188x-2", 0, NULL, 0, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("gpio-f7188x-2", 3, NULL, 1, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("gpio-f7188x-5", 3, NULL, 2, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("gpio-f7188x-5", 2, NULL, 3, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("gpio-f7188x-7", 7, NULL, 4, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP_IDX("gpio-f7188x-7", 4, NULL, 5, GPIO_ACTIVE_LOW),
+ {} /* Terminating entry */
+ }
+};
+
static int simatic_ipc_leds_gpio_f7188x_probe(struct platform_device *pdev)
{
- return simatic_ipc_leds_gpio_probe(pdev, &simatic_ipc_led_gpio_table,
- &simatic_ipc_led_gpio_table_extra);
+ const struct simatic_ipc_platform *plat = dev_get_platdata(&pdev->dev);
+ struct simatic_ipc_led_tables *led_tables;
+
+ led_tables = devm_kzalloc(&pdev->dev, sizeof(*led_tables), GFP_KERNEL);
+ if (!led_tables)
+ return -ENOMEM;
+
+ switch (plat->devmode) {
+ case SIMATIC_IPC_DEVICE_227G:
+ led_tables->led_lookup_table = &simatic_ipc_led_gpio_table_227g;
+ led_tables->led_lookup_table_extra = &simatic_ipc_led_gpio_table_extra_227g;
+ break;
+ case SIMATIC_IPC_DEVICE_BX_59A:
+ led_tables->led_lookup_table = &simatic_ipc_led_gpio_table_bx_59a;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ platform_set_drvdata(pdev, led_tables);
+ return simatic_ipc_leds_gpio_probe(pdev, led_tables->led_lookup_table,
+ led_tables->led_lookup_table_extra);
}
static void simatic_ipc_leds_gpio_f7188x_remove(struct platform_device *pdev)
{
- simatic_ipc_leds_gpio_remove(pdev, &simatic_ipc_led_gpio_table,
- &simatic_ipc_led_gpio_table_extra);
+ struct simatic_ipc_led_tables *led_tables = platform_get_drvdata(pdev);
+
+ simatic_ipc_leds_gpio_remove(pdev, led_tables->led_lookup_table,
+ led_tables->led_lookup_table_extra);
}
static struct platform_driver simatic_ipc_led_gpio_driver = {
diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig
index d11d80176fc0fd..31576952e18172 100644
--- a/drivers/leds/trigger/Kconfig
+++ b/drivers/leds/trigger/Kconfig
@@ -136,13 +136,6 @@ config LEDS_TRIGGER_PATTERN
which is a series of tuples, of brightness and duration (ms).
If unsure, say N
-config LEDS_TRIGGER_AUDIO
- tristate "Audio Mute LED Trigger"
- help
- This allows LEDs to be controlled by audio drivers for following
- the audio mute and mic-mute changes.
- If unsure, say N
-
config LEDS_TRIGGER_TTY
tristate "LED Trigger for TTY devices"
depends on TTY
diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile
index 25c4db97cdd4ca..242f6c4e3453e3 100644
--- a/drivers/leds/trigger/Makefile
+++ b/drivers/leds/trigger/Makefile
@@ -14,5 +14,4 @@ obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o
obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o
obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o
obj-$(CONFIG_LEDS_TRIGGER_PATTERN) += ledtrig-pattern.o
-obj-$(CONFIG_LEDS_TRIGGER_AUDIO) += ledtrig-audio.o
obj-$(CONFIG_LEDS_TRIGGER_TTY) += ledtrig-tty.o
diff --git a/drivers/leds/trigger/ledtrig-audio.c b/drivers/leds/trigger/ledtrig-audio.c
deleted file mode 100644
index 2ecd4b760fc36a..00000000000000
--- a/drivers/leds/trigger/ledtrig-audio.c
+++ /dev/null
@@ -1,67 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Audio Mute LED trigger
-//
-
-#include <linux/kernel.h>
-#include <linux/leds.h>
-#include <linux/module.h>
-#include "../leds.h"
-
-static enum led_brightness audio_state[NUM_AUDIO_LEDS];
-
-static int ledtrig_audio_mute_activate(struct led_classdev *led_cdev)
-{
- led_set_brightness_nosleep(led_cdev, audio_state[LED_AUDIO_MUTE]);
- return 0;
-}
-
-static int ledtrig_audio_micmute_activate(struct led_classdev *led_cdev)
-{
- led_set_brightness_nosleep(led_cdev, audio_state[LED_AUDIO_MICMUTE]);
- return 0;
-}
-
-static struct led_trigger ledtrig_audio[NUM_AUDIO_LEDS] = {
- [LED_AUDIO_MUTE] = {
- .name = "audio-mute",
- .activate = ledtrig_audio_mute_activate,
- },
- [LED_AUDIO_MICMUTE] = {
- .name = "audio-micmute",
- .activate = ledtrig_audio_micmute_activate,
- },
-};
-
-enum led_brightness ledtrig_audio_get(enum led_audio type)
-{
- return audio_state[type];
-}
-EXPORT_SYMBOL_GPL(ledtrig_audio_get);
-
-void ledtrig_audio_set(enum led_audio type, enum led_brightness state)
-{
- audio_state[type] = state;
- led_trigger_event(&ledtrig_audio[type], state);
-}
-EXPORT_SYMBOL_GPL(ledtrig_audio_set);
-
-static int __init ledtrig_audio_init(void)
-{
- led_trigger_register(&ledtrig_audio[LED_AUDIO_MUTE]);
- led_trigger_register(&ledtrig_audio[LED_AUDIO_MICMUTE]);
- return 0;
-}
-module_init(ledtrig_audio_init);
-
-static void __exit ledtrig_audio_exit(void)
-{
- led_trigger_unregister(&ledtrig_audio[LED_AUDIO_MUTE]);
- led_trigger_unregister(&ledtrig_audio[LED_AUDIO_MICMUTE]);
-}
-module_exit(ledtrig_audio_exit);
-
-MODULE_DESCRIPTION("LED trigger for audio mute control");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("ledtrig:audio-mute");
-MODULE_ALIAS("ledtrig:audio-micmute");
diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
index ea00f6c708826b..22bba8e97642a4 100644
--- a/drivers/leds/trigger/ledtrig-netdev.c
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -724,8 +724,6 @@ static void netdev_trig_deactivate(struct led_classdev *led_cdev)
cancel_delayed_work_sync(&trigger_data->work);
- led_set_brightness(led_cdev, LED_OFF);
-
dev_put(trigger_data->net_dev);
kfree(trigger_data);
diff --git a/include/dt-bindings/leds/common.h b/include/dt-bindings/leds/common.h
index d7c980bdf3834b..4f017bea01233f 100644
--- a/include/dt-bindings/leds/common.h
+++ b/include/dt-bindings/leds/common.h
@@ -91,11 +91,14 @@
#define LED_FUNCTION_INDICATOR "indicator"
#define LED_FUNCTION_LAN "lan"
#define LED_FUNCTION_MAIL "mail"
+#define LED_FUNCTION_MOBILE "mobile"
#define LED_FUNCTION_MTD "mtd"
#define LED_FUNCTION_PANIC "panic"
#define LED_FUNCTION_PROGRAMMING "programming"
#define LED_FUNCTION_RX "rx"
#define LED_FUNCTION_SD "sd"
+#define LED_FUNCTION_SPEED_LAN "speed-lan"
+#define LED_FUNCTION_SPEED_WAN "speed-wan"
#define LED_FUNCTION_STANDBY "standby"
#define LED_FUNCTION_TORCH "torch"
#define LED_FUNCTION_TX "tx"
diff --git a/include/linux/leds.h b/include/linux/leds.h
index db6b114bb3d914..6300313c46b799 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -455,6 +455,9 @@ struct led_trigger {
int (*activate)(struct led_classdev *led_cdev);
void (*deactivate)(struct led_classdev *led_cdev);
+ /* Brightness set by led_trigger_event */
+ enum led_brightness brightness;
+
/* LED-private triggers have this set */
struct led_hw_trigger_type *trigger_type;
@@ -508,6 +511,12 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev)
return led_cdev->trigger_data;
}
+static inline enum led_brightness
+led_trigger_get_brightness(const struct led_trigger *trigger)
+{
+ return trigger ? trigger->brightness : LED_OFF;
+}
+
#define module_led_trigger(__led_trigger) \
module_driver(__led_trigger, led_trigger_register, \
led_trigger_unregister)
@@ -544,6 +553,12 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev)
return NULL;
}
+static inline enum led_brightness
+led_trigger_get_brightness(const struct led_trigger *trigger)
+{
+ return LED_OFF;
+}
+
#endif /* CONFIG_LEDS_TRIGGERS */
/* Trigger specific enum */
@@ -690,18 +705,4 @@ enum led_audio {
NUM_AUDIO_LEDS
};
-#if IS_ENABLED(CONFIG_LEDS_TRIGGER_AUDIO)
-enum led_brightness ledtrig_audio_get(enum led_audio type);
-void ledtrig_audio_set(enum led_audio type, enum led_brightness state);
-#else
-static inline enum led_brightness ledtrig_audio_get(enum led_audio type)
-{
- return LED_OFF;
-}
-static inline void ledtrig_audio_set(enum led_audio type,
- enum led_brightness state)
-{
-}
-#endif
-
#endif /* __LINUX_LEDS_H_INCLUDED */
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index 67edc4ca2beeb7..a561c629d89f0f 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -22,6 +22,8 @@
#include <linux/cleanup.h>
#include <linux/mutex_types.h>
+struct device;
+
#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define __DEP_MAP_MUTEX_INITIALIZER(lockname) \
, .dep_map = { \
@@ -117,6 +119,31 @@ do { \
} while (0)
#endif /* CONFIG_PREEMPT_RT */
+#ifdef CONFIG_DEBUG_MUTEXES
+
+int __devm_mutex_init(struct device *dev, struct mutex *lock);
+
+#else
+
+static inline int __devm_mutex_init(struct device *dev, struct mutex *lock)
+{
+ /*
+ * When CONFIG_DEBUG_MUTEXES is off mutex_destroy() is just a nop so
+ * no really need to register it in the devm subsystem.
+ */
+ return 0;
+}
+
+#endif
+
+#define devm_mutex_init(dev, mutex) \
+({ \
+ typeof(mutex) mutex_ = (mutex); \
+ \
+ mutex_init(mutex_); \
+ __devm_mutex_init(dev, mutex_); \
+})
+
/*
* See kernel/locking/mutex.c for detailed documentation of these APIs.
* Also see Documentation/locking/mutex-design.rst.
diff --git a/kernel/locking/mutex-debug.c b/kernel/locking/mutex-debug.c
index bc8abb8549d20d..6e6f6071cfa279 100644
--- a/kernel/locking/mutex-debug.c
+++ b/kernel/locking/mutex-debug.c
@@ -12,6 +12,7 @@
*/
#include <linux/mutex.h>
#include <linux/delay.h>
+#include <linux/device.h>
#include <linux/export.h>
#include <linux/poison.h>
#include <linux/sched.h>
@@ -89,6 +90,17 @@ void debug_mutex_init(struct mutex *lock, const char *name,
lock->magic = lock;
}
+static void devm_mutex_release(void *res)
+{
+ mutex_destroy(res);
+}
+
+int __devm_mutex_init(struct device *dev, struct mutex *lock)
+{
+ return devm_add_action_or_reset(dev, devm_mutex_release, lock);
+}
+EXPORT_SYMBOL_GPL(__devm_mutex_init);
+
/***
* mutex_destroy - mark a mutex unusable
* @lock: the mutex to be destroyed
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 8077f481d84fd6..b970a173464708 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -262,6 +262,5 @@ config SND_CTL_LED
tristate
select NEW_LEDS if SND_CTL_LED
select LEDS_TRIGGERS if SND_CTL_LED
- select LEDS_TRIGGER_AUDIO if SND_CTL_LED
source "sound/core/seq/Kconfig"
diff --git a/sound/core/control_led.c b/sound/core/control_led.c
index ac19d14bd57456..804805a95e2f04 100644
--- a/sound/core/control_led.c
+++ b/sound/core/control_led.c
@@ -53,6 +53,7 @@ struct snd_ctl_led_ctl {
static DEFINE_MUTEX(snd_ctl_led_mutex);
static bool snd_ctl_led_card_valid[SNDRV_CARDS];
+static struct led_trigger *snd_ctl_ledtrig_audio[NUM_AUDIO_LEDS];
static struct snd_ctl_led snd_ctl_leds[MAX_LED] = {
{
.name = "speaker",
@@ -174,8 +175,11 @@ static void snd_ctl_led_set_state(struct snd_card *card, unsigned int access,
case MODE_FOLLOW_ROUTE: if (route >= 0) route ^= 1; break;
case MODE_FOLLOW_MUTE: /* noop */ break;
}
- if (route >= 0)
- ledtrig_audio_set(led->trigger_type, route ? LED_OFF : LED_ON);
+ if (route >= 0) {
+ struct led_trigger *trig = snd_ctl_ledtrig_audio[led->trigger_type];
+
+ led_trigger_event(trig, route ? LED_OFF : LED_ON);
+ }
}
static struct snd_ctl_led_ctl *snd_ctl_led_find(struct snd_kcontrol *kctl, unsigned int ioff)
@@ -420,8 +424,9 @@ static ssize_t brightness_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev);
+ struct led_trigger *trig = snd_ctl_ledtrig_audio[led->trigger_type];
- return sysfs_emit(buf, "%u\n", ledtrig_audio_get(led->trigger_type));
+ return sysfs_emit(buf, "%u\n", led_trigger_get_brightness(trig));
}
static DEVICE_ATTR_RW(mode);
@@ -711,6 +716,9 @@ static int __init snd_ctl_led_init(void)
struct snd_ctl_led *led;
unsigned int group;
+ led_trigger_register_simple("audio-mute", &snd_ctl_ledtrig_audio[LED_AUDIO_MUTE]);
+ led_trigger_register_simple("audio-micmute", &snd_ctl_ledtrig_audio[LED_AUDIO_MICMUTE]);
+
device_initialize(&snd_ctl_led_dev);
snd_ctl_led_dev.class = &sound_class;
snd_ctl_led_dev.release = snd_ctl_led_dev_release;
@@ -763,7 +771,13 @@ static void __exit snd_ctl_led_exit(void)
}
device_unregister(&snd_ctl_led_dev);
snd_ctl_led_clean(NULL);
+
+ led_trigger_unregister_simple(snd_ctl_ledtrig_audio[LED_AUDIO_MUTE]);
+ led_trigger_unregister_simple(snd_ctl_ledtrig_audio[LED_AUDIO_MICMUTE]);
}
module_init(snd_ctl_led_init)
module_exit(snd_ctl_led_exit)
+
+MODULE_ALIAS("ledtrig:audio-mute");
+MODULE_ALIAS("ledtrig:audio-micmute");