Merge tag 'leds-next-6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds

Pull LED updates from Lee Jones:
"Core Frameworks:
- Ensure seldom updated triggers have a brightness value before first
update

New Device Support:
- Add support for Simatic IPC Device BX_59A to IPC LEDs Core
- Add support for Qualcomm PMI8950 PWM to LPG Core

New Functionality:
- Add a bunch of new LED function identifiers
- Add support for High Resolution Timers in LED Trigger Patten

Fix-ups:
- Shift out Audio Trigger to the Sound subsystem
- Convert suitable calls to devm_* managed resources
- Device Tree binding adaptions/conversions/creation
- Remove superfluous code/variables/attributes and simplify overall
- Use/convert to new/better APIs/helpers/MACROs instead of
hand-rolling implementations

Bug Fixes:
- Repair enabling Torch Mode from V4L2 on the second LED
- Ensure PWM is disabled when suspending"

* tag 'leds-next-6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds: (28 commits)
leds: mt6370: Remove unused field 'reg_cfgs' from 'struct mt6370_priv'
leds: lp50xx: Remove unused field 'num_of_banked_leds' from 'struct lp50xx'
leds: lp50xx: Remove unused field 'bank_modules' from 'struct lp50xx_led'
leds: aat1290: Remove unused field 'torch_brightness' from 'struct aat1290_led'
leds: sun50i-a100: Use match_string() helper to simplify the code
leds: pwm: Disable PWM when going to suspend
leds: trigger: pattern: Add support for hrtimer
leds: mt6360: Fix the second LED can not enable torch mode by V4L2
dt-bindings: leds: leds-qcom-lpg: Add support for PMI8950 PWM
leds: qcom-lpg: Add support for PMI8950 PWM
leds: apu: Remove duplicate DMI lookup data
leds: trigger: netdev: Remove not needed call to led_set_brightness in deactivate
dt-bindings: leds: Add LED_FUNCTION_SPEED_* for link speed on LAN/WAN
dt-bindings: leds: Add LED_FUNCTION_MOBILE for mobile network
leds: simatic-ipc-leds-gpio: Add support for module BX-59A
dt-bindings: leds: qcom-lpg: Document PM6150L compatible
dt-bindings: leds: pca963x: Convert text bindings to YAML
leds: an30259a: Use devm_mutex_init() for mutex initialization
leds: mlxreg: Use devm_mutex_init() for mutex initialization
leds: nic78bx: Use devm API to cleanup module's resources
...

+501 -275
+10
Documentation/ABI/testing/sysfs-class-led-trigger-pattern
··· 12 12 The exact format is described in: 13 13 Documentation/devicetree/bindings/leds/leds-trigger-pattern.txt 14 14 15 + What: /sys/class/leds/<led>/hr_pattern 16 + Date: April 2024 17 + Description: 18 + Specify a software pattern for the LED, that supports altering 19 + the brightness for the specified duration with one software 20 + timer. It can do gradual dimming and step change of brightness. 21 + 22 + Unlike the /sys/class/leds/<led>/pattern, this attribute runs 23 + a pattern on high-resolution timer (hrtimer). 24 + 15 25 What: /sys/class/leds/<led>/hw_pattern 16 26 Date: September 2018 17 27 KernelVersion: 4.20
+6 -2
Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
··· 27 27 - qcom,pm8994-lpg 28 28 - qcom,pmc8180c-lpg 29 29 - qcom,pmi632-lpg 30 + - qcom,pmi8950-pwm 30 31 - qcom,pmi8994-lpg 31 32 - qcom,pmi8998-lpg 32 33 - qcom,pmk8550-pwm 34 + - items: 35 + - enum: 36 + - qcom,pm6150l-lpg 37 + - const: qcom,pm8150l-lpg 33 38 - items: 34 39 - enum: 35 40 - qcom,pm8550-pwm ··· 147 142 - qcom,pm8941-lpg 148 143 - qcom,pm8994-lpg 149 144 - qcom,pmc8180c-lpg 145 + - qcom,pmi8950-pwm 150 146 - qcom,pmi8994-lpg 151 147 - qcom,pmi8998-lpg 152 148 - qcom,pmk8550-pwm ··· 296 290 label = "blue"; 297 291 }; 298 292 }; 299 - 300 - ...
+140
Documentation/devicetree/bindings/leds/nxp,pca963x.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/leds/nxp,pca963x.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: NXP PCA963x LED controllers 8 + 9 + maintainers: 10 + - Laurent Pinchart <laurent.pinchart@ideasonboard.com> 11 + 12 + description: | 13 + The NXP PCA963x are I2C-controlled LED drivers optimized for 14 + Red/Green/Blue/Amber (RGBA) color mixing applications. Each LED is 15 + individually controllable and has its own PWM controller. 16 + 17 + Datasheets are available at 18 + 19 + - https://www.nxp.com/docs/en/data-sheet/PCA9632.pdf 20 + - https://www.nxp.com/docs/en/data-sheet/PCA9633.pdf 21 + - https://www.nxp.com/docs/en/data-sheet/PCA9634.pdf 22 + - https://www.nxp.com/docs/en/data-sheet/PCA9635.pdf 23 + 24 + properties: 25 + compatible: 26 + enum: 27 + - nxp,pca9632 28 + - nxp,pca9633 29 + - nxp,pca9634 30 + - nxp,pca9635 31 + 32 + reg: 33 + maxItems: 1 34 + 35 + "#address-cells": 36 + const: 1 37 + 38 + "#size-cells": 39 + const: 0 40 + 41 + nxp,hw-blink: 42 + type: boolean 43 + description: 44 + Use hardware blinking instead of software blinking 45 + 46 + nxp,inverted-out: 47 + type: boolean 48 + description: 49 + Invert the polarity of the generated PWM. 50 + 51 + nxp,period-scale: 52 + $ref: /schemas/types.yaml#/definitions/uint32 53 + description: 54 + In some configurations, the chip blinks faster than expected. This 55 + parameter provides a scaling ratio (fixed point, decimal divided by 1000) 56 + to compensate, e.g. 1300=1.3x and 750=0.75x. 57 + 58 + nxp,totem-pole: 59 + type: boolean 60 + description: 61 + Use totem pole (push-pull) instead of open-drain (pca9632 defaults to 62 + open-drain, newer chips to totem pole). 63 + 64 + patternProperties: 65 + "^led@[0-9a-f]+$": 66 + type: object 67 + $ref: common.yaml# 68 + unevaluatedProperties: false 69 + 70 + properties: 71 + reg: 72 + minimum: 0 73 + 74 + required: 75 + - reg 76 + 77 + allOf: 78 + - if: 79 + properties: 80 + compatible: 81 + contains: 82 + enum: 83 + - nxp,pca9632 84 + - nxp,pca9633 85 + then: 86 + patternProperties: 87 + "^led@[0-9a-f]+$": 88 + properties: 89 + reg: 90 + maximum: 3 91 + else: 92 + patternProperties: 93 + "^led@[0-9a-f]+$": 94 + properties: 95 + reg: 96 + maximum: 7 97 + 98 + additionalProperties: false 99 + 100 + examples: 101 + - | 102 + #include <dt-bindings/leds/common.h> 103 + 104 + i2c { 105 + #address-cells = <1>; 106 + #size-cells = <0>; 107 + 108 + led-controller@62 { 109 + compatible = "nxp,pca9632"; 110 + reg = <0x62>; 111 + #address-cells = <1>; 112 + #size-cells = <0>; 113 + 114 + led@0 { 115 + reg = <0>; 116 + color = <LED_COLOR_ID_RED>; 117 + function = LED_FUNCTION_STATUS; 118 + }; 119 + 120 + led@1 { 121 + reg = <1>; 122 + color = <LED_COLOR_ID_GREEN>; 123 + function = LED_FUNCTION_STATUS; 124 + }; 125 + 126 + led@2 { 127 + reg = <2>; 128 + color = <LED_COLOR_ID_BLUE>; 129 + function = LED_FUNCTION_STATUS; 130 + }; 131 + 132 + led@3 { 133 + reg = <3>; 134 + color = <LED_COLOR_ID_WHITE>; 135 + function = LED_FUNCTION_STATUS; 136 + }; 137 + }; 138 + }; 139 + 140 + ...
-52
Documentation/devicetree/bindings/leds/pca963x.txt
··· 1 - LEDs connected to pca9632, pca9633 or pca9634 2 - 3 - Required properties: 4 - - compatible : should be : "nxp,pca9632", "nxp,pca9633", "nxp,pca9634" or "nxp,pca9635" 5 - 6 - Optional properties: 7 - - nxp,totem-pole : use totem pole (push-pull) instead of open-drain (pca9632 defaults 8 - to open-drain, newer chips to totem pole) 9 - - nxp,hw-blink : use hardware blinking instead of software blinking 10 - - nxp,period-scale : In some configurations, the chip blinks faster than expected. 11 - This parameter provides a scaling ratio (fixed point, decimal divided 12 - by 1000) to compensate, e.g. 1300=1.3x and 750=0.75x. 13 - - nxp,inverted-out: invert the polarity of the generated PWM 14 - 15 - Each led is represented as a sub-node of the nxp,pca963x device. 16 - 17 - LED sub-node properties: 18 - - label : (optional) see Documentation/devicetree/bindings/leds/common.txt 19 - - reg : number of LED line (could be from 0 to 3 in pca9632 or pca9633, 20 - 0 to 7 in pca9634, or 0 to 15 in pca9635) 21 - - linux,default-trigger : (optional) 22 - see Documentation/devicetree/bindings/leds/common.txt 23 - 24 - Examples: 25 - 26 - pca9632: pca9632 { 27 - compatible = "nxp,pca9632"; 28 - #address-cells = <1>; 29 - #size-cells = <0>; 30 - reg = <0x62>; 31 - 32 - red@0 { 33 - label = "red"; 34 - reg = <0>; 35 - linux,default-trigger = "none"; 36 - }; 37 - green@1 { 38 - label = "green"; 39 - reg = <1>; 40 - linux,default-trigger = "none"; 41 - }; 42 - blue@2 { 43 - label = "blue"; 44 - reg = <2>; 45 - linux,default-trigger = "none"; 46 - }; 47 - unused@3 { 48 - label = "unused"; 49 - reg = <3>; 50 - linux,default-trigger = "none"; 51 - }; 52 - };
-1
arch/mips/configs/ci20_defconfig
··· 152 152 CONFIG_LEDS_TRIGGER_PANIC=y 153 153 CONFIG_LEDS_TRIGGER_NETDEV=y 154 154 CONFIG_LEDS_TRIGGER_PATTERN=y 155 - CONFIG_LEDS_TRIGGER_AUDIO=y 156 155 CONFIG_RTC_CLASS=y 157 156 CONFIG_RTC_DRV_JZ4740=y 158 157 CONFIG_DMADEVICES=y
-2
drivers/leds/flash/leds-aat1290.c
··· 77 77 int *mm_current_scale; 78 78 /* device mode */ 79 79 bool movie_mode; 80 - /* brightness cache */ 81 - unsigned int torch_brightness; 82 80 }; 83 81 84 82 static struct aat1290_led *fled_cdev_to_led(
+11 -1
drivers/leds/flash/leds-mt6360.c
··· 241 241 u32 enable_mask = MT6360_STROBEN_MASK | MT6360_FLCSEN_MASK(led->led_no); 242 242 u32 val = state ? MT6360_FLCSEN_MASK(led->led_no) : 0; 243 243 u32 prev = priv->fled_strobe_used, curr; 244 - int ret; 244 + int ret = 0; 245 245 246 246 mutex_lock(&priv->lock); 247 + 248 + /* 249 + * If the state of the upcoming change is the same as the current LED 250 + * device state, then skip the subsequent code to avoid conflict 251 + * with the flow of turning on LED torch mode in V4L2. 252 + */ 253 + if (state == !!(BIT(led->led_no) & prev)) { 254 + dev_info(lcdev->dev, "No change in strobe state [0x%x]\n", prev); 255 + goto unlock; 256 + } 247 257 248 258 /* 249 259 * Only one set of flash control logic, use the flag to avoid torch is
+4 -2
drivers/leds/led-triggers.c
··· 194 194 spin_unlock(&trig->leddev_list_lock); 195 195 led_cdev->trigger = trig; 196 196 197 + ret = 0; 197 198 if (trig->activate) 198 199 ret = trig->activate(led_cdev); 199 200 else 200 - ret = 0; 201 - 201 + led_set_brightness(led_cdev, trig->brightness); 202 202 if (ret) 203 203 goto err_activate; 204 204 ··· 386 386 387 387 if (!trig) 388 388 return; 389 + 390 + trig->brightness = brightness; 389 391 390 392 rcu_read_lock(); 391 393 list_for_each_entry_rcu(led_cdev, &trig->led_cdevs, trig_list)
+4 -10
drivers/leds/leds-an30259a.c
··· 283 283 if (err < 0) 284 284 return err; 285 285 286 - mutex_init(&chip->mutex); 286 + err = devm_mutex_init(&client->dev, &chip->mutex); 287 + if (err) 288 + return err; 289 + 287 290 chip->client = client; 288 291 i2c_set_clientdata(client, chip); 289 292 ··· 320 317 return 0; 321 318 322 319 exit: 323 - mutex_destroy(&chip->mutex); 324 320 return err; 325 - } 326 - 327 - static void an30259a_remove(struct i2c_client *client) 328 - { 329 - struct an30259a *chip = i2c_get_clientdata(client); 330 - 331 - mutex_destroy(&chip->mutex); 332 321 } 333 322 334 323 static const struct of_device_id an30259a_match_table[] = { ··· 342 347 .of_match_table = an30259a_match_table, 343 348 }, 344 349 .probe = an30259a_probe, 345 - .remove = an30259a_remove, 346 350 .id_table = an30259a_id, 347 351 }; 348 352
+1 -2
drivers/leds/leds-apu.c
··· 181 181 struct platform_device *pdev; 182 182 int err; 183 183 184 - if (!(dmi_match(DMI_SYS_VENDOR, "PC Engines") && 185 - (dmi_match(DMI_PRODUCT_NAME, "APU") || dmi_match(DMI_PRODUCT_NAME, "apu1")))) { 184 + if (!dmi_check_system(apu_led_dmi_table)) { 186 185 pr_err("No PC Engines APUv1 board detected. For APUv2,3 support, enable CONFIG_PCENGINES_APU2\n"); 187 186 return -ENODEV; 188 187 }
+21 -11
drivers/leds/leds-aw200xx.c
··· 530 530 .disable_locking = true, 531 531 }; 532 532 533 + static void aw200xx_chip_reset_action(void *data) 534 + { 535 + aw200xx_chip_reset(data); 536 + } 537 + 538 + static void aw200xx_disable_action(void *data) 539 + { 540 + aw200xx_disable(data); 541 + } 542 + 533 543 static int aw200xx_probe(struct i2c_client *client) 534 544 { 535 545 const struct aw200xx_chipdef *cdef; ··· 578 568 579 569 aw200xx_enable(chip); 580 570 571 + ret = devm_add_action(&client->dev, aw200xx_disable_action, chip); 572 + if (ret) 573 + return ret; 574 + 581 575 ret = aw200xx_chip_check(chip); 582 576 if (ret) 583 577 return ret; 584 578 585 - mutex_init(&chip->mutex); 579 + ret = devm_mutex_init(&client->dev, &chip->mutex); 580 + if (ret) 581 + return ret; 586 582 587 583 /* Need a lock now since after call aw200xx_probe_fw, sysfs nodes created */ 588 584 mutex_lock(&chip->mutex); 589 585 590 586 ret = aw200xx_chip_reset(chip); 587 + if (ret) 588 + goto out_unlock; 589 + 590 + ret = devm_add_action(&client->dev, aw200xx_chip_reset_action, chip); 591 591 if (ret) 592 592 goto out_unlock; 593 593 ··· 613 593 614 594 mutex_unlock(&chip->mutex); 615 595 return ret; 616 - } 617 - 618 - static void aw200xx_remove(struct i2c_client *client) 619 - { 620 - struct aw200xx *chip = i2c_get_clientdata(client); 621 - 622 - aw200xx_chip_reset(chip); 623 - aw200xx_disable(chip); 624 - mutex_destroy(&chip->mutex); 625 596 } 626 597 627 598 static const struct aw200xx_chipdef aw20036_cdef = { ··· 663 652 .of_match_table = aw200xx_match_table, 664 653 }, 665 654 .probe = aw200xx_probe, 666 - .remove = aw200xx_remove, 667 655 .id_table = aw200xx_id, 668 656 }; 669 657 module_i2c_driver(aw200xx_driver);
+13 -12
drivers/leds/leds-aw2013.c
··· 320 320 return 0; 321 321 } 322 322 323 + static void aw2013_chip_disable_action(void *data) 324 + { 325 + aw2013_chip_disable(data); 326 + } 327 + 323 328 static const struct regmap_config aw2013_regmap_config = { 324 329 .reg_bits = 8, 325 330 .val_bits = 8, ··· 341 336 if (!chip) 342 337 return -ENOMEM; 343 338 344 - mutex_init(&chip->mutex); 339 + ret = devm_mutex_init(&client->dev, &chip->mutex); 340 + if (ret) 341 + return ret; 342 + 345 343 mutex_lock(&chip->mutex); 346 344 347 345 chip->client = client; ··· 392 384 goto error_reg; 393 385 } 394 386 387 + ret = devm_add_action(&client->dev, aw2013_chip_disable_action, chip); 388 + if (ret) 389 + goto error_reg; 390 + 395 391 ret = aw2013_probe_dt(chip); 396 392 if (ret < 0) 397 393 goto error_reg; ··· 418 406 419 407 error: 420 408 mutex_unlock(&chip->mutex); 421 - mutex_destroy(&chip->mutex); 422 409 return ret; 423 - } 424 - 425 - static void aw2013_remove(struct i2c_client *client) 426 - { 427 - struct aw2013 *chip = i2c_get_clientdata(client); 428 - 429 - aw2013_chip_disable(chip); 430 - 431 - mutex_destroy(&chip->mutex); 432 410 } 433 411 434 412 static const struct of_device_id aw2013_match_table[] = { ··· 434 432 .of_match_table = aw2013_match_table, 435 433 }, 436 434 .probe = aw2013_probe, 437 - .remove = aw2013_remove, 438 435 }; 439 436 440 437 module_i2c_driver(aw2013_driver);
+17 -12
drivers/leds/leds-lm3532.c
··· 542 542 return ret; 543 543 } 544 544 545 + static void gpio_set_low_action(void *data) 546 + { 547 + struct lm3532_data *priv = data; 548 + 549 + gpiod_direction_output(priv->enable_gpio, 0); 550 + } 551 + 545 552 static int lm3532_parse_node(struct lm3532_data *priv) 546 553 { 547 554 struct fwnode_handle *child = NULL; ··· 562 555 "enable", GPIOD_OUT_LOW); 563 556 if (IS_ERR(priv->enable_gpio)) 564 557 priv->enable_gpio = NULL; 558 + 559 + if (priv->enable_gpio) { 560 + ret = devm_add_action(&priv->client->dev, gpio_set_low_action, priv); 561 + if (ret) 562 + return ret; 563 + } 565 564 566 565 priv->regulator = devm_regulator_get(&priv->client->dev, "vin"); 567 566 if (IS_ERR(priv->regulator)) ··· 704 691 return ret; 705 692 } 706 693 707 - mutex_init(&drvdata->lock); 694 + ret = devm_mutex_init(&client->dev, &drvdata->lock); 695 + if (ret) 696 + return ret; 697 + 708 698 i2c_set_clientdata(client, drvdata); 709 699 710 700 ret = lm3532_parse_node(drvdata); ··· 717 701 } 718 702 719 703 return ret; 720 - } 721 - 722 - static void lm3532_remove(struct i2c_client *client) 723 - { 724 - struct lm3532_data *drvdata = i2c_get_clientdata(client); 725 - 726 - mutex_destroy(&drvdata->lock); 727 - 728 - if (drvdata->enable_gpio) 729 - gpiod_direction_output(drvdata->enable_gpio, 0); 730 704 } 731 705 732 706 static const struct of_device_id of_lm3532_leds_match[] = { ··· 733 727 734 728 static struct i2c_driver lm3532_i2c_driver = { 735 729 .probe = lm3532_probe, 736 - .remove = lm3532_remove, 737 730 .id_table = lm3532_id, 738 731 .driver = { 739 732 .name = LM3532_NAME,
+11 -10
drivers/leds/leds-lp3952.c
··· 207 207 .cache_type = REGCACHE_MAPLE, 208 208 }; 209 209 210 + static void gpio_set_low_action(void *data) 211 + { 212 + struct lp3952_led_array *priv = data; 213 + 214 + gpiod_set_value(priv->enable_gpio, 0); 215 + } 216 + 210 217 static int lp3952_probe(struct i2c_client *client) 211 218 { 212 219 int status; ··· 232 225 dev_err(&client->dev, "Failed to enable gpio: %d\n", status); 233 226 return status; 234 227 } 228 + 229 + status = devm_add_action(&client->dev, gpio_set_low_action, priv); 230 + if (status) 231 + return status; 235 232 236 233 priv->regmap = devm_regmap_init_i2c(client, &lp3952_regmap); 237 234 if (IS_ERR(priv->regmap)) { ··· 265 254 return 0; 266 255 } 267 256 268 - static void lp3952_remove(struct i2c_client *client) 269 - { 270 - struct lp3952_led_array *priv; 271 - 272 - priv = i2c_get_clientdata(client); 273 - lp3952_on_off(priv, LP3952_LED_ALL, false); 274 - gpiod_set_value(priv->enable_gpio, 0); 275 - } 276 - 277 257 static const struct i2c_device_id lp3952_id[] = { 278 258 {LP3952_NAME, 0}, 279 259 {} ··· 276 274 .name = LP3952_NAME, 277 275 }, 278 276 .probe = lp3952_probe, 279 - .remove = lp3952_remove, 280 277 .id_table = lp3952_id, 281 278 }; 282 279
-5
drivers/leds/leds-lp50xx.c
··· 265 265 struct lp50xx_led { 266 266 struct led_classdev_mc mc_cdev; 267 267 struct lp50xx *priv; 268 - unsigned long bank_modules; 269 268 u8 ctrl_bank_enabled; 270 269 int led_number; 271 270 }; ··· 278 279 * @dev: pointer to the devices device struct 279 280 * @lock: lock for reading/writing the device 280 281 * @chip_info: chip specific information (ie num_leds) 281 - * @num_of_banked_leds: holds the number of banked LEDs 282 282 * @leds: array of LED strings 283 283 */ 284 284 struct lp50xx { ··· 288 290 struct device *dev; 289 291 struct mutex lock; 290 292 const struct lp50xx_chip_info *chip_info; 291 - int num_of_banked_leds; 292 293 293 294 /* This needs to be at the end of the struct */ 294 295 struct lp50xx_led leds[]; ··· 400 403 dev_err(priv->dev, "reg property is invalid\n"); 401 404 return -EINVAL; 402 405 } 403 - 404 - priv->num_of_banked_leds = num_leds; 405 406 406 407 ret = fwnode_property_read_u32_array(child, "reg", led_banks, num_leds); 407 408 if (ret) {
+5 -9
drivers/leds/leds-mlxreg.c
··· 256 256 { 257 257 struct mlxreg_core_platform_data *led_pdata; 258 258 struct mlxreg_led_priv_data *priv; 259 + int err; 259 260 260 261 led_pdata = dev_get_platdata(&pdev->dev); 261 262 if (!led_pdata) { ··· 268 267 if (!priv) 269 268 return -ENOMEM; 270 269 271 - mutex_init(&priv->access_lock); 270 + err = devm_mutex_init(&pdev->dev, &priv->access_lock); 271 + if (err) 272 + return err; 273 + 272 274 priv->pdev = pdev; 273 275 priv->pdata = led_pdata; 274 276 275 277 return mlxreg_led_config(priv); 276 - } 277 - 278 - static void mlxreg_led_remove(struct platform_device *pdev) 279 - { 280 - struct mlxreg_led_priv_data *priv = dev_get_drvdata(&pdev->dev); 281 - 282 - mutex_destroy(&priv->access_lock); 283 278 } 284 279 285 280 static struct platform_driver mlxreg_led_driver = { ··· 283 286 .name = "leds-mlxreg", 284 287 }, 285 288 .probe = mlxreg_led_probe, 286 - .remove_new = mlxreg_led_remove, 287 289 }; 288 290 289 291 module_platform_driver(mlxreg_led_driver);
+13 -10
drivers/leds/leds-nic78bx.c
··· 118 118 } 119 119 }; 120 120 121 + static void lock_led_reg_action(void *data) 122 + { 123 + struct nic78bx_led_data *led_data = data; 124 + 125 + /* Lock LED register */ 126 + outb(NIC78BX_LOCK_VALUE, 127 + led_data->io_base + NIC78BX_LOCK_REG_OFFSET); 128 + } 129 + 121 130 static int nic78bx_probe(struct platform_device *pdev) 122 131 { 123 132 struct device *dev = &pdev->dev; ··· 161 152 led_data->io_base = io_rc->start; 162 153 spin_lock_init(&led_data->lock); 163 154 155 + ret = devm_add_action(dev, lock_led_reg_action, led_data); 156 + if (ret) 157 + return ret; 158 + 164 159 for (i = 0; i < ARRAY_SIZE(nic78bx_leds); i++) { 165 160 nic78bx_leds[i].data = led_data; 166 161 ··· 180 167 return ret; 181 168 } 182 169 183 - static void nic78bx_remove(struct platform_device *pdev) 184 - { 185 - struct nic78bx_led_data *led_data = platform_get_drvdata(pdev); 186 - 187 - /* Lock LED register */ 188 - outb(NIC78BX_LOCK_VALUE, 189 - led_data->io_base + NIC78BX_LOCK_REG_OFFSET); 190 - } 191 - 192 170 static const struct acpi_device_id led_device_ids[] = { 193 171 {"NIC78B3", 0}, 194 172 {"", 0}, ··· 188 184 189 185 static struct platform_driver led_driver = { 190 186 .probe = nic78bx_probe, 191 - .remove_new = nic78bx_remove, 192 187 .driver = { 193 188 .name = KBUILD_MODNAME, 194 189 .acpi_match_table = ACPI_PTR(led_device_ids),
+7 -1
drivers/leds/leds-pwm.c
··· 53 53 duty = led_dat->pwmstate.period - duty; 54 54 55 55 led_dat->pwmstate.duty_cycle = duty; 56 - led_dat->pwmstate.enabled = true; 56 + /* 57 + * Disabling a PWM doesn't guarantee that it emits the inactive level. 58 + * So keep it on. Only for suspending the PWM should be disabled because 59 + * otherwise it refuses to suspend. The possible downside is that the 60 + * LED might stay (or even go) on. 61 + */ 62 + led_dat->pwmstate.enabled = !(led_cdev->flags & LED_SUSPENDED); 57 63 return pwm_apply_might_sleep(led_dat->pwm, &led_dat->pwmstate); 58 64 } 59 65
+6 -8
drivers/leds/leds-sun50i-a100.c
··· 252 252 struct sun50i_a100_ledc *priv) 253 253 { 254 254 const char *format = "grb"; 255 - u32 i; 255 + int i; 256 256 257 257 device_property_read_string(dev, "allwinner,pixel-format", &format); 258 258 259 - for (i = 0; i < ARRAY_SIZE(sun50i_a100_ledc_formats); i++) { 260 - if (!strcmp(format, sun50i_a100_ledc_formats[i])) { 261 - priv->format = i; 262 - return 0; 263 - } 264 - } 259 + i = match_string(sun50i_a100_ledc_formats, ARRAY_SIZE(sun50i_a100_ledc_formats), format); 260 + if (i < 0) 261 + return dev_err_probe(dev, i, "Bad pixel format '%s'\n", format); 265 262 266 - return dev_err_probe(dev, -EINVAL, "Bad pixel format '%s'\n", format); 263 + priv->format = i; 264 + return 0; 267 265 } 268 266 269 267 static void sun50i_a100_ledc_set_format(struct sun50i_a100_ledc *priv)
-1
drivers/leds/rgb/leds-mt6370-rgb.c
··· 149 149 struct regmap_field *fields[F_MAX_FIELDS]; 150 150 const struct reg_field *reg_fields; 151 151 const struct linear_range *ranges; 152 - struct reg_cfg *reg_cfgs; 153 152 const struct mt6370_pdata *pdata; 154 153 unsigned int leds_count; 155 154 unsigned int leds_active;
+8
drivers/leds/rgb/leds-qcom-lpg.c
··· 1693 1693 }, 1694 1694 }; 1695 1695 1696 + static const struct lpg_data pmi8950_pwm_data = { 1697 + .num_channels = 1, 1698 + .channels = (const struct lpg_channel_data[]) { 1699 + { .base = 0xb000 }, 1700 + }, 1701 + }; 1702 + 1696 1703 static const struct lpg_data pm8994_lpg_data = { 1697 1704 .lut_base = 0xb000, 1698 1705 .lut_size = 64, ··· 1826 1819 { .compatible = "qcom,pm8941-lpg", .data = &pm8941_lpg_data }, 1827 1820 { .compatible = "qcom,pm8994-lpg", .data = &pm8994_lpg_data }, 1828 1821 { .compatible = "qcom,pmi632-lpg", .data = &pmi632_lpg_data }, 1822 + { .compatible = "qcom,pmi8950-pwm", .data = &pmi8950_pwm_data }, 1829 1823 { .compatible = "qcom,pmi8994-lpg", .data = &pmi8994_lpg_data }, 1830 1824 { .compatible = "qcom,pmi8998-lpg", .data = &pmi8998_lpg_data }, 1831 1825 { .compatible = "qcom,pmc8180c-lpg", .data = &pm8150l_lpg_data },
+1
drivers/leds/simple/simatic-ipc-leds-gpio-core.c
··· 56 56 case SIMATIC_IPC_DEVICE_127E: 57 57 case SIMATIC_IPC_DEVICE_227G: 58 58 case SIMATIC_IPC_DEVICE_BX_21A: 59 + case SIMATIC_IPC_DEVICE_BX_59A: 59 60 break; 60 61 default: 61 62 return -ENODEV;
+46 -6
drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c
··· 17 17 18 18 #include "simatic-ipc-leds-gpio.h" 19 19 20 - static struct gpiod_lookup_table simatic_ipc_led_gpio_table = { 20 + struct simatic_ipc_led_tables { 21 + struct gpiod_lookup_table *led_lookup_table; 22 + struct gpiod_lookup_table *led_lookup_table_extra; 23 + }; 24 + 25 + static struct gpiod_lookup_table simatic_ipc_led_gpio_table_227g = { 21 26 .dev_id = "leds-gpio", 22 27 .table = { 23 28 GPIO_LOOKUP_IDX("gpio-f7188x-2", 0, NULL, 0, GPIO_ACTIVE_LOW), ··· 35 30 }, 36 31 }; 37 32 38 - static struct gpiod_lookup_table simatic_ipc_led_gpio_table_extra = { 33 + static struct gpiod_lookup_table simatic_ipc_led_gpio_table_extra_227g = { 39 34 .dev_id = NULL, /* Filled during initialization */ 40 35 .table = { 41 36 GPIO_LOOKUP_IDX("gpio-f7188x-3", 6, NULL, 6, GPIO_ACTIVE_HIGH), ··· 44 39 }, 45 40 }; 46 41 42 + static struct gpiod_lookup_table simatic_ipc_led_gpio_table_bx_59a = { 43 + .dev_id = "leds-gpio", 44 + .table = { 45 + GPIO_LOOKUP_IDX("gpio-f7188x-2", 0, NULL, 0, GPIO_ACTIVE_LOW), 46 + GPIO_LOOKUP_IDX("gpio-f7188x-2", 3, NULL, 1, GPIO_ACTIVE_LOW), 47 + GPIO_LOOKUP_IDX("gpio-f7188x-5", 3, NULL, 2, GPIO_ACTIVE_LOW), 48 + GPIO_LOOKUP_IDX("gpio-f7188x-5", 2, NULL, 3, GPIO_ACTIVE_LOW), 49 + GPIO_LOOKUP_IDX("gpio-f7188x-7", 7, NULL, 4, GPIO_ACTIVE_LOW), 50 + GPIO_LOOKUP_IDX("gpio-f7188x-7", 4, NULL, 5, GPIO_ACTIVE_LOW), 51 + {} /* Terminating entry */ 52 + } 53 + }; 54 + 47 55 static int simatic_ipc_leds_gpio_f7188x_probe(struct platform_device *pdev) 48 56 { 49 - return simatic_ipc_leds_gpio_probe(pdev, &simatic_ipc_led_gpio_table, 50 - &simatic_ipc_led_gpio_table_extra); 57 + const struct simatic_ipc_platform *plat = dev_get_platdata(&pdev->dev); 58 + struct simatic_ipc_led_tables *led_tables; 59 + 60 + led_tables = devm_kzalloc(&pdev->dev, sizeof(*led_tables), GFP_KERNEL); 61 + if (!led_tables) 62 + return -ENOMEM; 63 + 64 + switch (plat->devmode) { 65 + case SIMATIC_IPC_DEVICE_227G: 66 + led_tables->led_lookup_table = &simatic_ipc_led_gpio_table_227g; 67 + led_tables->led_lookup_table_extra = &simatic_ipc_led_gpio_table_extra_227g; 68 + break; 69 + case SIMATIC_IPC_DEVICE_BX_59A: 70 + led_tables->led_lookup_table = &simatic_ipc_led_gpio_table_bx_59a; 71 + break; 72 + default: 73 + return -ENODEV; 74 + } 75 + 76 + platform_set_drvdata(pdev, led_tables); 77 + return simatic_ipc_leds_gpio_probe(pdev, led_tables->led_lookup_table, 78 + led_tables->led_lookup_table_extra); 51 79 } 52 80 53 81 static void simatic_ipc_leds_gpio_f7188x_remove(struct platform_device *pdev) 54 82 { 55 - simatic_ipc_leds_gpio_remove(pdev, &simatic_ipc_led_gpio_table, 56 - &simatic_ipc_led_gpio_table_extra); 83 + struct simatic_ipc_led_tables *led_tables = platform_get_drvdata(pdev); 84 + 85 + simatic_ipc_leds_gpio_remove(pdev, led_tables->led_lookup_table, 86 + led_tables->led_lookup_table_extra); 57 87 } 58 88 59 89 static struct platform_driver simatic_ipc_led_gpio_driver = {
-7
drivers/leds/trigger/Kconfig
··· 136 136 which is a series of tuples, of brightness and duration (ms). 137 137 If unsure, say N 138 138 139 - config LEDS_TRIGGER_AUDIO 140 - tristate "Audio Mute LED Trigger" 141 - help 142 - This allows LEDs to be controlled by audio drivers for following 143 - the audio mute and mic-mute changes. 144 - If unsure, say N 145 - 146 139 config LEDS_TRIGGER_TTY 147 140 tristate "LED Trigger for TTY devices" 148 141 depends on TTY
-1
drivers/leds/trigger/Makefile
··· 14 14 obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o 15 15 obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o 16 16 obj-$(CONFIG_LEDS_TRIGGER_PATTERN) += ledtrig-pattern.o 17 - obj-$(CONFIG_LEDS_TRIGGER_AUDIO) += ledtrig-audio.o 18 17 obj-$(CONFIG_LEDS_TRIGGER_TTY) += ledtrig-tty.o
-67
drivers/leds/trigger/ledtrig-audio.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - // 3 - // Audio Mute LED trigger 4 - // 5 - 6 - #include <linux/kernel.h> 7 - #include <linux/leds.h> 8 - #include <linux/module.h> 9 - #include "../leds.h" 10 - 11 - static enum led_brightness audio_state[NUM_AUDIO_LEDS]; 12 - 13 - static int ledtrig_audio_mute_activate(struct led_classdev *led_cdev) 14 - { 15 - led_set_brightness_nosleep(led_cdev, audio_state[LED_AUDIO_MUTE]); 16 - return 0; 17 - } 18 - 19 - static int ledtrig_audio_micmute_activate(struct led_classdev *led_cdev) 20 - { 21 - led_set_brightness_nosleep(led_cdev, audio_state[LED_AUDIO_MICMUTE]); 22 - return 0; 23 - } 24 - 25 - static struct led_trigger ledtrig_audio[NUM_AUDIO_LEDS] = { 26 - [LED_AUDIO_MUTE] = { 27 - .name = "audio-mute", 28 - .activate = ledtrig_audio_mute_activate, 29 - }, 30 - [LED_AUDIO_MICMUTE] = { 31 - .name = "audio-micmute", 32 - .activate = ledtrig_audio_micmute_activate, 33 - }, 34 - }; 35 - 36 - enum led_brightness ledtrig_audio_get(enum led_audio type) 37 - { 38 - return audio_state[type]; 39 - } 40 - EXPORT_SYMBOL_GPL(ledtrig_audio_get); 41 - 42 - void ledtrig_audio_set(enum led_audio type, enum led_brightness state) 43 - { 44 - audio_state[type] = state; 45 - led_trigger_event(&ledtrig_audio[type], state); 46 - } 47 - EXPORT_SYMBOL_GPL(ledtrig_audio_set); 48 - 49 - static int __init ledtrig_audio_init(void) 50 - { 51 - led_trigger_register(&ledtrig_audio[LED_AUDIO_MUTE]); 52 - led_trigger_register(&ledtrig_audio[LED_AUDIO_MICMUTE]); 53 - return 0; 54 - } 55 - module_init(ledtrig_audio_init); 56 - 57 - static void __exit ledtrig_audio_exit(void) 58 - { 59 - led_trigger_unregister(&ledtrig_audio[LED_AUDIO_MUTE]); 60 - led_trigger_unregister(&ledtrig_audio[LED_AUDIO_MICMUTE]); 61 - } 62 - module_exit(ledtrig_audio_exit); 63 - 64 - MODULE_DESCRIPTION("LED trigger for audio mute control"); 65 - MODULE_LICENSE("GPL v2"); 66 - MODULE_ALIAS("ledtrig:audio-mute"); 67 - MODULE_ALIAS("ledtrig:audio-micmute");
-2
drivers/leds/trigger/ledtrig-netdev.c
··· 724 724 725 725 cancel_delayed_work_sync(&trigger_data->work); 726 726 727 - led_set_brightness(led_cdev, LED_OFF); 728 - 729 727 dev_put(trigger_data->net_dev); 730 728 731 729 kfree(trigger_data);
+103 -23
drivers/leds/trigger/ledtrig-pattern.c
··· 13 13 #include <linux/mutex.h> 14 14 #include <linux/slab.h> 15 15 #include <linux/timer.h> 16 + #include <linux/hrtimer.h> 16 17 17 18 #define MAX_PATTERNS 1024 18 19 /* ··· 21 20 * every 50 milliseconds. 22 21 */ 23 22 #define UPDATE_INTERVAL 50 23 + 24 + enum pattern_type { 25 + PATTERN_TYPE_SW, /* Use standard timer for software pattern */ 26 + PATTERN_TYPE_HR, /* Use hrtimer for software pattern */ 27 + PATTERN_TYPE_HW, /* Hardware pattern */ 28 + }; 24 29 25 30 struct pattern_trig_data { 26 31 struct led_classdev *led_cdev; ··· 39 32 int last_repeat; 40 33 int delta_t; 41 34 bool is_indefinite; 42 - bool is_hw_pattern; 35 + enum pattern_type type; 43 36 struct timer_list timer; 37 + struct hrtimer hrtimer; 44 38 }; 45 39 46 40 static void pattern_trig_update_patterns(struct pattern_trig_data *data) ··· 79 71 return data->curr->brightness - step_brightness; 80 72 } 81 73 82 - static void pattern_trig_timer_function(struct timer_list *t) 74 + static void pattern_trig_timer_start(struct pattern_trig_data *data) 83 75 { 84 - struct pattern_trig_data *data = from_timer(data, t, timer); 76 + if (data->type == PATTERN_TYPE_HR) { 77 + hrtimer_start(&data->hrtimer, ns_to_ktime(0), HRTIMER_MODE_REL); 78 + } else { 79 + data->timer.expires = jiffies; 80 + add_timer(&data->timer); 81 + } 82 + } 85 83 84 + static void pattern_trig_timer_cancel(struct pattern_trig_data *data) 85 + { 86 + if (data->type == PATTERN_TYPE_HR) 87 + hrtimer_cancel(&data->hrtimer); 88 + else 89 + del_timer_sync(&data->timer); 90 + } 91 + 92 + static void pattern_trig_timer_restart(struct pattern_trig_data *data, 93 + unsigned long interval) 94 + { 95 + if (data->type == PATTERN_TYPE_HR) 96 + hrtimer_forward_now(&data->hrtimer, ms_to_ktime(interval)); 97 + else 98 + mod_timer(&data->timer, jiffies + msecs_to_jiffies(interval)); 99 + } 100 + 101 + static void pattern_trig_timer_common_function(struct pattern_trig_data *data) 102 + { 86 103 for (;;) { 87 104 if (!data->is_indefinite && !data->repeat) 88 105 break; ··· 116 83 /* Step change of brightness */ 117 84 led_set_brightness(data->led_cdev, 118 85 data->curr->brightness); 119 - mod_timer(&data->timer, 120 - jiffies + msecs_to_jiffies(data->curr->delta_t)); 86 + pattern_trig_timer_restart(data, data->curr->delta_t); 121 87 if (!data->next->delta_t) { 122 88 /* Skip the tuple with zero duration */ 123 89 pattern_trig_update_patterns(data); ··· 138 106 139 107 led_set_brightness(data->led_cdev, 140 108 pattern_trig_compute_brightness(data)); 141 - mod_timer(&data->timer, 142 - jiffies + msecs_to_jiffies(UPDATE_INTERVAL)); 109 + pattern_trig_timer_restart(data, UPDATE_INTERVAL); 143 110 144 111 /* Accumulate the gradual dimming time */ 145 112 data->delta_t += UPDATE_INTERVAL; ··· 148 117 } 149 118 } 150 119 120 + static void pattern_trig_timer_function(struct timer_list *t) 121 + { 122 + struct pattern_trig_data *data = from_timer(data, t, timer); 123 + 124 + return pattern_trig_timer_common_function(data); 125 + } 126 + 127 + static enum hrtimer_restart pattern_trig_hrtimer_function(struct hrtimer *t) 128 + { 129 + struct pattern_trig_data *data = 130 + container_of(t, struct pattern_trig_data, hrtimer); 131 + 132 + pattern_trig_timer_common_function(data); 133 + if (!data->is_indefinite && !data->repeat) 134 + return HRTIMER_NORESTART; 135 + 136 + return HRTIMER_RESTART; 137 + } 138 + 151 139 static int pattern_trig_start_pattern(struct led_classdev *led_cdev) 152 140 { 153 141 struct pattern_trig_data *data = led_cdev->trigger_data; ··· 174 124 if (!data->npatterns) 175 125 return 0; 176 126 177 - if (data->is_hw_pattern) { 127 + if (data->type == PATTERN_TYPE_HW) { 178 128 return led_cdev->pattern_set(led_cdev, data->patterns, 179 129 data->npatterns, data->repeat); 180 130 } ··· 186 136 data->delta_t = 0; 187 137 data->curr = data->patterns; 188 138 data->next = data->patterns + 1; 189 - data->timer.expires = jiffies; 190 - add_timer(&data->timer); 139 + pattern_trig_timer_start(data); 191 140 192 141 return 0; 193 142 } ··· 224 175 225 176 mutex_lock(&data->lock); 226 177 227 - del_timer_sync(&data->timer); 178 + pattern_trig_timer_cancel(data); 228 179 229 - if (data->is_hw_pattern) 180 + if (data->type == PATTERN_TYPE_HW) 230 181 led_cdev->pattern_clear(led_cdev); 231 182 232 183 data->last_repeat = data->repeat = res; ··· 245 196 static DEVICE_ATTR_RW(repeat); 246 197 247 198 static ssize_t pattern_trig_show_patterns(struct pattern_trig_data *data, 248 - char *buf, bool hw_pattern) 199 + char *buf, enum pattern_type type) 249 200 { 250 201 ssize_t count = 0; 251 202 int i; 252 203 253 204 mutex_lock(&data->lock); 254 205 255 - if (!data->npatterns || (data->is_hw_pattern ^ hw_pattern)) 206 + if (!data->npatterns || data->type != type) 256 207 goto out; 257 208 258 209 for (i = 0; i < data->npatterns; i++) { ··· 309 260 310 261 static ssize_t pattern_trig_store_patterns(struct led_classdev *led_cdev, 311 262 const char *buf, const u32 *buf_int, 312 - size_t count, bool hw_pattern) 263 + size_t count, enum pattern_type type) 313 264 { 314 265 struct pattern_trig_data *data = led_cdev->trigger_data; 315 266 int err = 0; 316 267 317 268 mutex_lock(&data->lock); 318 269 319 - del_timer_sync(&data->timer); 270 + pattern_trig_timer_cancel(data); 320 271 321 - if (data->is_hw_pattern) 272 + if (data->type == PATTERN_TYPE_HW) 322 273 led_cdev->pattern_clear(led_cdev); 323 274 324 - data->is_hw_pattern = hw_pattern; 275 + data->type = type; 325 276 data->npatterns = 0; 326 277 327 278 if (buf) ··· 346 297 struct led_classdev *led_cdev = dev_get_drvdata(dev); 347 298 struct pattern_trig_data *data = led_cdev->trigger_data; 348 299 349 - return pattern_trig_show_patterns(data, buf, false); 300 + return pattern_trig_show_patterns(data, buf, PATTERN_TYPE_SW); 350 301 } 351 302 352 303 static ssize_t pattern_store(struct device *dev, struct device_attribute *attr, ··· 354 305 { 355 306 struct led_classdev *led_cdev = dev_get_drvdata(dev); 356 307 357 - return pattern_trig_store_patterns(led_cdev, buf, NULL, count, false); 308 + return pattern_trig_store_patterns(led_cdev, buf, NULL, count, 309 + PATTERN_TYPE_SW); 358 310 } 359 311 360 312 static DEVICE_ATTR_RW(pattern); ··· 366 316 struct led_classdev *led_cdev = dev_get_drvdata(dev); 367 317 struct pattern_trig_data *data = led_cdev->trigger_data; 368 318 369 - return pattern_trig_show_patterns(data, buf, true); 319 + return pattern_trig_show_patterns(data, buf, PATTERN_TYPE_HW); 370 320 } 371 321 372 322 static ssize_t hw_pattern_store(struct device *dev, ··· 375 325 { 376 326 struct led_classdev *led_cdev = dev_get_drvdata(dev); 377 327 378 - return pattern_trig_store_patterns(led_cdev, buf, NULL, count, true); 328 + return pattern_trig_store_patterns(led_cdev, buf, NULL, count, 329 + PATTERN_TYPE_HW); 379 330 } 380 331 381 332 static DEVICE_ATTR_RW(hw_pattern); 333 + 334 + static ssize_t hr_pattern_show(struct device *dev, 335 + struct device_attribute *attr, char *buf) 336 + { 337 + struct led_classdev *led_cdev = dev_get_drvdata(dev); 338 + struct pattern_trig_data *data = led_cdev->trigger_data; 339 + 340 + return pattern_trig_show_patterns(data, buf, PATTERN_TYPE_HR); 341 + } 342 + 343 + static ssize_t hr_pattern_store(struct device *dev, 344 + struct device_attribute *attr, 345 + const char *buf, size_t count) 346 + { 347 + struct led_classdev *led_cdev = dev_get_drvdata(dev); 348 + 349 + return pattern_trig_store_patterns(led_cdev, buf, NULL, count, 350 + PATTERN_TYPE_HR); 351 + } 352 + 353 + static DEVICE_ATTR_RW(hr_pattern); 382 354 383 355 static umode_t pattern_trig_attrs_mode(struct kobject *kobj, 384 356 struct attribute *attr, int index) ··· 409 337 struct led_classdev *led_cdev = dev_get_drvdata(dev); 410 338 411 339 if (attr == &dev_attr_repeat.attr || attr == &dev_attr_pattern.attr) 340 + return attr->mode; 341 + else if (attr == &dev_attr_hr_pattern.attr) 412 342 return attr->mode; 413 343 else if (attr == &dev_attr_hw_pattern.attr && led_cdev->pattern_set) 414 344 return attr->mode; ··· 421 347 static struct attribute *pattern_trig_attrs[] = { 422 348 &dev_attr_pattern.attr, 423 349 &dev_attr_hw_pattern.attr, 350 + &dev_attr_hr_pattern.attr, 424 351 &dev_attr_repeat.attr, 425 352 NULL 426 353 }; ··· 451 376 goto out; 452 377 } 453 378 454 - err = pattern_trig_store_patterns(led_cdev, NULL, pattern, size, false); 379 + err = pattern_trig_store_patterns(led_cdev, NULL, pattern, size, 380 + PATTERN_TYPE_SW); 455 381 if (err < 0) 456 382 dev_warn(led_cdev->dev, 457 383 "Pattern initialization failed with error %d\n", err); ··· 476 400 led_cdev->pattern_clear = NULL; 477 401 } 478 402 403 + data->type = PATTERN_TYPE_SW; 479 404 data->is_indefinite = true; 480 405 data->last_repeat = -1; 481 406 mutex_init(&data->lock); 482 407 data->led_cdev = led_cdev; 483 408 led_set_trigger_data(led_cdev, data); 484 409 timer_setup(&data->timer, pattern_trig_timer_function, 0); 410 + hrtimer_init(&data->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 411 + data->hrtimer.function = pattern_trig_hrtimer_function; 485 412 led_cdev->activated = true; 486 413 487 414 if (led_cdev->flags & LED_INIT_DEFAULT_TRIGGER) { ··· 510 431 led_cdev->pattern_clear(led_cdev); 511 432 512 433 timer_shutdown_sync(&data->timer); 434 + hrtimer_cancel(&data->hrtimer); 513 435 514 436 led_set_brightness(led_cdev, LED_OFF); 515 437 kfree(data);
+3
include/dt-bindings/leds/common.h
··· 91 91 #define LED_FUNCTION_INDICATOR "indicator" 92 92 #define LED_FUNCTION_LAN "lan" 93 93 #define LED_FUNCTION_MAIL "mail" 94 + #define LED_FUNCTION_MOBILE "mobile" 94 95 #define LED_FUNCTION_MTD "mtd" 95 96 #define LED_FUNCTION_PANIC "panic" 96 97 #define LED_FUNCTION_PROGRAMMING "programming" 97 98 #define LED_FUNCTION_RX "rx" 98 99 #define LED_FUNCTION_SD "sd" 100 + #define LED_FUNCTION_SPEED_LAN "speed-lan" 101 + #define LED_FUNCTION_SPEED_WAN "speed-wan" 99 102 #define LED_FUNCTION_STANDBY "standby" 100 103 #define LED_FUNCTION_TORCH "torch" 101 104 #define LED_FUNCTION_TX "tx"
+15 -14
include/linux/leds.h
··· 455 455 int (*activate)(struct led_classdev *led_cdev); 456 456 void (*deactivate)(struct led_classdev *led_cdev); 457 457 458 + /* Brightness set by led_trigger_event */ 459 + enum led_brightness brightness; 460 + 458 461 /* LED-private triggers have this set */ 459 462 struct led_hw_trigger_type *trigger_type; 460 463 ··· 511 508 return led_cdev->trigger_data; 512 509 } 513 510 511 + static inline enum led_brightness 512 + led_trigger_get_brightness(const struct led_trigger *trigger) 513 + { 514 + return trigger ? trigger->brightness : LED_OFF; 515 + } 516 + 514 517 #define module_led_trigger(__led_trigger) \ 515 518 module_driver(__led_trigger, led_trigger_register, \ 516 519 led_trigger_unregister) ··· 551 542 static inline void *led_get_trigger_data(struct led_classdev *led_cdev) 552 543 { 553 544 return NULL; 545 + } 546 + 547 + static inline enum led_brightness 548 + led_trigger_get_brightness(const struct led_trigger *trigger) 549 + { 550 + return LED_OFF; 554 551 } 555 552 556 553 #endif /* CONFIG_LEDS_TRIGGERS */ ··· 704 689 LED_AUDIO_MICMUTE, /* mic mute LED */ 705 690 NUM_AUDIO_LEDS 706 691 }; 707 - 708 - #if IS_ENABLED(CONFIG_LEDS_TRIGGER_AUDIO) 709 - enum led_brightness ledtrig_audio_get(enum led_audio type); 710 - void ledtrig_audio_set(enum led_audio type, enum led_brightness state); 711 - #else 712 - static inline enum led_brightness ledtrig_audio_get(enum led_audio type) 713 - { 714 - return LED_OFF; 715 - } 716 - static inline void ledtrig_audio_set(enum led_audio type, 717 - enum led_brightness state) 718 - { 719 - } 720 - #endif 721 692 722 693 #endif /* __LINUX_LEDS_H_INCLUDED */
+27
include/linux/mutex.h
··· 22 22 #include <linux/cleanup.h> 23 23 #include <linux/mutex_types.h> 24 24 25 + struct device; 26 + 25 27 #ifdef CONFIG_DEBUG_LOCK_ALLOC 26 28 # define __DEP_MAP_MUTEX_INITIALIZER(lockname) \ 27 29 , .dep_map = { \ ··· 118 116 __mutex_init((mutex), #mutex, &__key); \ 119 117 } while (0) 120 118 #endif /* CONFIG_PREEMPT_RT */ 119 + 120 + #ifdef CONFIG_DEBUG_MUTEXES 121 + 122 + int __devm_mutex_init(struct device *dev, struct mutex *lock); 123 + 124 + #else 125 + 126 + static inline int __devm_mutex_init(struct device *dev, struct mutex *lock) 127 + { 128 + /* 129 + * When CONFIG_DEBUG_MUTEXES is off mutex_destroy() is just a nop so 130 + * no really need to register it in the devm subsystem. 131 + */ 132 + return 0; 133 + } 134 + 135 + #endif 136 + 137 + #define devm_mutex_init(dev, mutex) \ 138 + ({ \ 139 + typeof(mutex) mutex_ = (mutex); \ 140 + \ 141 + mutex_init(mutex_); \ 142 + __devm_mutex_init(dev, mutex_); \ 143 + }) 121 144 122 145 /* 123 146 * See kernel/locking/mutex.c for detailed documentation of these APIs.
+12
kernel/locking/mutex-debug.c
··· 12 12 */ 13 13 #include <linux/mutex.h> 14 14 #include <linux/delay.h> 15 + #include <linux/device.h> 15 16 #include <linux/export.h> 16 17 #include <linux/poison.h> 17 18 #include <linux/sched.h> ··· 89 88 #endif 90 89 lock->magic = lock; 91 90 } 91 + 92 + static void devm_mutex_release(void *res) 93 + { 94 + mutex_destroy(res); 95 + } 96 + 97 + int __devm_mutex_init(struct device *dev, struct mutex *lock) 98 + { 99 + return devm_add_action_or_reset(dev, devm_mutex_release, lock); 100 + } 101 + EXPORT_SYMBOL_GPL(__devm_mutex_init); 92 102 93 103 /*** 94 104 * mutex_destroy - mark a mutex unusable
-1
sound/core/Kconfig
··· 262 262 tristate 263 263 select NEW_LEDS if SND_CTL_LED 264 264 select LEDS_TRIGGERS if SND_CTL_LED 265 - select LEDS_TRIGGER_AUDIO if SND_CTL_LED 266 265 267 266 source "sound/core/seq/Kconfig"
+17 -3
sound/core/control_led.c
··· 53 53 54 54 static DEFINE_MUTEX(snd_ctl_led_mutex); 55 55 static bool snd_ctl_led_card_valid[SNDRV_CARDS]; 56 + static struct led_trigger *snd_ctl_ledtrig_audio[NUM_AUDIO_LEDS]; 56 57 static struct snd_ctl_led snd_ctl_leds[MAX_LED] = { 57 58 { 58 59 .name = "speaker", ··· 175 174 case MODE_FOLLOW_ROUTE: if (route >= 0) route ^= 1; break; 176 175 case MODE_FOLLOW_MUTE: /* noop */ break; 177 176 } 178 - if (route >= 0) 179 - ledtrig_audio_set(led->trigger_type, route ? LED_OFF : LED_ON); 177 + if (route >= 0) { 178 + struct led_trigger *trig = snd_ctl_ledtrig_audio[led->trigger_type]; 179 + 180 + led_trigger_event(trig, route ? LED_OFF : LED_ON); 181 + } 180 182 } 181 183 182 184 static struct snd_ctl_led_ctl *snd_ctl_led_find(struct snd_kcontrol *kctl, unsigned int ioff) ··· 424 420 struct device_attribute *attr, char *buf) 425 421 { 426 422 struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev); 423 + struct led_trigger *trig = snd_ctl_ledtrig_audio[led->trigger_type]; 427 424 428 - return sysfs_emit(buf, "%u\n", ledtrig_audio_get(led->trigger_type)); 425 + return sysfs_emit(buf, "%u\n", led_trigger_get_brightness(trig)); 429 426 } 430 427 431 428 static DEVICE_ATTR_RW(mode); ··· 716 711 struct snd_ctl_led *led; 717 712 unsigned int group; 718 713 714 + led_trigger_register_simple("audio-mute", &snd_ctl_ledtrig_audio[LED_AUDIO_MUTE]); 715 + led_trigger_register_simple("audio-micmute", &snd_ctl_ledtrig_audio[LED_AUDIO_MICMUTE]); 716 + 719 717 device_initialize(&snd_ctl_led_dev); 720 718 snd_ctl_led_dev.class = &sound_class; 721 719 snd_ctl_led_dev.release = snd_ctl_led_dev_release; ··· 771 763 } 772 764 device_unregister(&snd_ctl_led_dev); 773 765 snd_ctl_led_clean(NULL); 766 + 767 + led_trigger_unregister_simple(snd_ctl_ledtrig_audio[LED_AUDIO_MUTE]); 768 + led_trigger_unregister_simple(snd_ctl_ledtrig_audio[LED_AUDIO_MICMUTE]); 774 769 } 775 770 776 771 module_init(snd_ctl_led_init) 777 772 module_exit(snd_ctl_led_exit) 773 + 774 + MODULE_ALIAS("ledtrig:audio-mute"); 775 + MODULE_ALIAS("ledtrig:audio-micmute");