Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'leds-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/pavel/linux-leds

Pull LED updates from Pavel Machek:
"Nothing major is happening here"

* tag 'leds-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/pavel/linux-leds:
leds: lp55xx: initialise output direction from dts
ARM: dts: omap3-n900: Fix lp5523 for multi color
leds: ktd2692: Drop calling dev_of_node() in ktd2692_parse_dt
leds: lgm-sso: Get rid of duplicate of_node assignment
leds: tca6507: Get rid of duplicate of_node assignment
leds: leds-fsg: Drop FSG3 LED driver
leds: lp50xx: remove unused variable
dt-bindings: leds: Replace moonlight with indicator in mt6360 example
leds: led-core: Update fwnode with device_set_node
leds: tca6507: use swap() to make code cleaner
leds: Add mt6360 driver
dt-bindings: leds: Add bindings for MT6360 LED

+1130 -225
+159
Documentation/devicetree/bindings/leds/leds-mt6360.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/leds-mt6360.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: LED driver for MT6360 PMIC from MediaTek Integrated. 8 + 9 + maintainers: 10 + - Gene Chen <gene_chen@richtek.com> 11 + 12 + description: | 13 + This module is part of the MT6360 MFD device. 14 + see Documentation/devicetree/bindings/mfd/mt6360.yaml 15 + Add MT6360 LED driver include 2-channel Flash LED with torch/strobe mode, 16 + and 4-channel RGB LED support Register/Flash/Breath Mode 17 + 18 + properties: 19 + compatible: 20 + const: mediatek,mt6360-led 21 + 22 + "#address-cells": 23 + const: 1 24 + 25 + "#size-cells": 26 + const: 0 27 + 28 + patternProperties: 29 + "^(multi-)?led@[0-5]$": 30 + type: object 31 + $ref: common.yaml# 32 + description: 33 + Properties for a single LED. 34 + 35 + properties: 36 + reg: 37 + description: Index of the LED. 38 + enum: 39 + - 0 # LED output ISINK1 40 + - 1 # LED output ISINK2 41 + - 2 # LED output ISINK3 42 + - 3 # LED output ISINKML 43 + - 4 # LED output FLASH1 44 + - 5 # LED output FLASH2 45 + 46 + unevaluatedProperties: false 47 + 48 + required: 49 + - compatible 50 + - "#address-cells" 51 + - "#size-cells" 52 + 53 + additionalProperties: false 54 + 55 + examples: 56 + - | 57 + #include <dt-bindings/leds/common.h> 58 + led-controller { 59 + compatible = "mediatek,mt6360-led"; 60 + #address-cells = <1>; 61 + #size-cells = <0>; 62 + 63 + multi-led@0 { 64 + reg = <0>; 65 + function = LED_FUNCTION_INDICATOR; 66 + color = <LED_COLOR_ID_RGB>; 67 + led-max-microamp = <24000>; 68 + #address-cells = <1>; 69 + #size-cells = <0>; 70 + led@0 { 71 + reg = <0>; 72 + color = <LED_COLOR_ID_RED>; 73 + }; 74 + led@1 { 75 + reg = <1>; 76 + color = <LED_COLOR_ID_GREEN>; 77 + }; 78 + led@2 { 79 + reg = <2>; 80 + color = <LED_COLOR_ID_BLUE>; 81 + }; 82 + }; 83 + led@3 { 84 + reg = <3>; 85 + function = LED_FUNCTION_INDICATOR; 86 + color = <LED_COLOR_ID_WHITE>; 87 + led-max-microamp = <150000>; 88 + }; 89 + led@4 { 90 + reg = <4>; 91 + function = LED_FUNCTION_FLASH; 92 + color = <LED_COLOR_ID_WHITE>; 93 + function-enumerator = <1>; 94 + led-max-microamp = <200000>; 95 + flash-max-microamp = <500000>; 96 + flash-max-timeout-us = <1024000>; 97 + }; 98 + led@5 { 99 + reg = <5>; 100 + function = LED_FUNCTION_FLASH; 101 + color = <LED_COLOR_ID_WHITE>; 102 + function-enumerator = <2>; 103 + led-max-microamp = <200000>; 104 + flash-max-microamp = <500000>; 105 + flash-max-timeout-us = <1024000>; 106 + }; 107 + }; 108 + 109 + - | 110 + 111 + led-controller { 112 + compatible = "mediatek,mt6360-led"; 113 + #address-cells = <1>; 114 + #size-cells = <0>; 115 + 116 + led@0 { 117 + reg = <0>; 118 + function = LED_FUNCTION_INDICATOR; 119 + color = <LED_COLOR_ID_RED>; 120 + led-max-microamp = <24000>; 121 + }; 122 + led@1 { 123 + reg = <1>; 124 + function = LED_FUNCTION_INDICATOR; 125 + color = <LED_COLOR_ID_GREEN>; 126 + led-max-microamp = <24000>; 127 + }; 128 + led@2 { 129 + reg = <2>; 130 + function = LED_FUNCTION_INDICATOR; 131 + color = <LED_COLOR_ID_BLUE>; 132 + led-max-microamp = <24000>; 133 + }; 134 + led@3 { 135 + reg = <3>; 136 + function = LED_FUNCTION_INDICATOR; 137 + color = <LED_COLOR_ID_WHITE>; 138 + led-max-microamp = <150000>; 139 + }; 140 + led@4 { 141 + reg = <4>; 142 + function = LED_FUNCTION_FLASH; 143 + color = <LED_COLOR_ID_WHITE>; 144 + function-enumerator = <1>; 145 + led-max-microamp = <200000>; 146 + flash-max-microamp = <500000>; 147 + flash-max-timeout-us = <1024000>; 148 + }; 149 + led@5 { 150 + reg = <5>; 151 + function = LED_FUNCTION_FLASH; 152 + color = <LED_COLOR_ID_WHITE>; 153 + function-enumerator = <2>; 154 + led-max-microamp = <200000>; 155 + flash-max-microamp = <500000>; 156 + flash-max-timeout-us = <1024000>; 157 + }; 158 + }; 159 + ...
+40 -10
arch/arm/boot/dts/omap3-n900.dts
··· 8 8 9 9 #include "omap34xx.dtsi" 10 10 #include <dt-bindings/input/input.h> 11 + #include <dt-bindings/leds/common.h> 11 12 12 13 /* 13 14 * Default secure signed bootloader (Nokia X-Loader) does not enable L3 firewall ··· 631 630 }; 632 631 633 632 lp5523: lp5523@32 { 633 + #address-cells = <1>; 634 + #size-cells = <0>; 634 635 compatible = "national,lp5523"; 635 636 reg = <0x32>; 636 637 clock-mode = /bits/ 8 <0>; /* LP55XX_CLOCK_AUTO */ 637 - enable-gpio = <&gpio2 9 GPIO_ACTIVE_HIGH>; /* 41 */ 638 + enable-gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>; /* 41 */ 638 639 639 - chan0 { 640 + led@0 { 641 + reg = <0>; 640 642 chan-name = "lp5523:kb1"; 641 643 led-cur = /bits/ 8 <50>; 642 644 max-cur = /bits/ 8 <100>; 645 + color = <LED_COLOR_ID_WHITE>; 646 + function = LED_FUNCTION_KBD_BACKLIGHT; 643 647 }; 644 648 645 - chan1 { 649 + led@1 { 650 + reg = <1>; 646 651 chan-name = "lp5523:kb2"; 647 652 led-cur = /bits/ 8 <50>; 648 653 max-cur = /bits/ 8 <100>; 654 + color = <LED_COLOR_ID_WHITE>; 655 + function = LED_FUNCTION_KBD_BACKLIGHT; 649 656 }; 650 657 651 - chan2 { 658 + led@2 { 659 + reg = <2>; 652 660 chan-name = "lp5523:kb3"; 653 661 led-cur = /bits/ 8 <50>; 654 662 max-cur = /bits/ 8 <100>; 663 + color = <LED_COLOR_ID_WHITE>; 664 + function = LED_FUNCTION_KBD_BACKLIGHT; 655 665 }; 656 666 657 - chan3 { 667 + led@3 { 668 + reg = <3>; 658 669 chan-name = "lp5523:kb4"; 659 670 led-cur = /bits/ 8 <50>; 660 671 max-cur = /bits/ 8 <100>; 672 + color = <LED_COLOR_ID_WHITE>; 673 + function = LED_FUNCTION_KBD_BACKLIGHT; 661 674 }; 662 675 663 - chan4 { 676 + led@4 { 677 + reg = <4>; 664 678 chan-name = "lp5523:b"; 665 679 led-cur = /bits/ 8 <50>; 666 680 max-cur = /bits/ 8 <100>; 681 + color = <LED_COLOR_ID_BLUE>; 682 + function = LED_FUNCTION_STATUS; 667 683 }; 668 684 669 - chan5 { 685 + led@5 { 686 + reg = <5>; 670 687 chan-name = "lp5523:g"; 671 688 led-cur = /bits/ 8 <50>; 672 689 max-cur = /bits/ 8 <100>; 690 + color = <LED_COLOR_ID_GREEN>; 691 + function = LED_FUNCTION_STATUS; 673 692 }; 674 693 675 - chan6 { 694 + led@6 { 695 + reg = <6>; 676 696 chan-name = "lp5523:r"; 677 697 led-cur = /bits/ 8 <50>; 678 698 max-cur = /bits/ 8 <100>; 699 + color = <LED_COLOR_ID_RED>; 700 + function = LED_FUNCTION_STATUS; 679 701 }; 680 702 681 - chan7 { 703 + led@7 { 704 + reg = <7>; 682 705 chan-name = "lp5523:kb5"; 683 706 led-cur = /bits/ 8 <50>; 684 707 max-cur = /bits/ 8 <100>; 708 + color = <LED_COLOR_ID_WHITE>; 709 + function = LED_FUNCTION_KBD_BACKLIGHT; 685 710 }; 686 711 687 - chan8 { 712 + led@8 { 713 + reg = <8>; 688 714 chan-name = "lp5523:kb6"; 689 715 led-cur = /bits/ 8 <50>; 690 716 max-cur = /bits/ 8 <100>; 717 + color = <LED_COLOR_ID_WHITE>; 718 + function = LED_FUNCTION_KBD_BACKLIGHT; 691 719 }; 692 720 }; 693 721
-7
drivers/leds/Kconfig
··· 260 260 This option enables support for the Soekris net4801 and net4826 error 261 261 LED. 262 262 263 - config LEDS_FSG 264 - tristate "LED Support for the Freecom FSG-3" 265 - depends on LEDS_CLASS 266 - depends on MACH_FSG 267 - help 268 - This option enables support for the LEDs on the Freecom FSG-3. 269 - 270 263 config LEDS_WRAP 271 264 tristate "LED Support for the WRAP series LEDs" 272 265 depends on LEDS_CLASS
-1
drivers/leds/Makefile
··· 26 26 obj-$(CONFIG_LEDS_CPCAP) += leds-cpcap.o 27 27 obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o 28 28 obj-$(CONFIG_LEDS_DA9052) += leds-da9052.o 29 - obj-$(CONFIG_LEDS_FSG) += leds-fsg.o 30 29 obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o 31 30 obj-$(CONFIG_LEDS_GPIO_REGISTER) += leds-gpio-register.o 32 31 obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
-1
drivers/leds/blink/leds-lgm-sso.c
··· 477 477 gc->ngpio = priv->gpio.pins; 478 478 gc->parent = dev; 479 479 gc->owner = THIS_MODULE; 480 - gc->of_node = dev->of_node; 481 480 482 481 return devm_gpiochip_add_data(dev, gc, priv); 483 482 }
+13
drivers/leds/flash/Kconfig
··· 48 48 multifunction device. It has build in control for two leds in flash 49 49 and torch mode. 50 50 51 + config LEDS_MT6360 52 + tristate "LED Support for Mediatek MT6360 PMIC" 53 + depends on LEDS_CLASS && OF 54 + depends on LEDS_CLASS_FLASH || !LEDS_CLASS_FLASH 55 + depends on LEDS_CLASS_MULTICOLOR || !LEDS_CLASS_MULTICOLOR 56 + depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS 57 + depends on MFD_MT6360 58 + help 59 + This option enables support for dual Flash LED drivers found on 60 + Mediatek MT6360 PMIC. 61 + Independent current sources supply for each flash LED support torch 62 + and strobe mode. 63 + 51 64 config LEDS_RT4505 52 65 tristate "LED support for RT4505 flashlight controller" 53 66 depends on I2C && OF
+1
drivers/leds/flash/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 3 + obj-$(CONFIG_LEDS_MT6360) += leds-mt6360.o 3 4 obj-$(CONFIG_LEDS_AAT1290) += leds-aat1290.o 4 5 obj-$(CONFIG_LEDS_AS3645A) += leds-as3645a.o 5 6 obj-$(CONFIG_LEDS_KTD2692) += leds-ktd2692.o
+1 -1
drivers/leds/flash/leds-ktd2692.c
··· 274 274 struct device_node *child_node; 275 275 int ret; 276 276 277 - if (!dev_of_node(dev)) 277 + if (!np) 278 278 return -ENXIO; 279 279 280 280 led->ctrl_gpio = devm_gpiod_get(dev, "ctrl", GPIOD_ASIS);
+910
drivers/leds/flash/leds-mt6360.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <linux/bitops.h> 4 + #include <linux/delay.h> 5 + #include <linux/init.h> 6 + #include <linux/interrupt.h> 7 + #include <linux/kernel.h> 8 + #include <linux/led-class-flash.h> 9 + #include <linux/led-class-multicolor.h> 10 + #include <linux/module.h> 11 + #include <linux/mutex.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/property.h> 14 + #include <linux/regmap.h> 15 + #include <media/v4l2-flash-led-class.h> 16 + 17 + enum { 18 + MT6360_LED_ISNK1 = 0, 19 + MT6360_LED_ISNK2, 20 + MT6360_LED_ISNK3, 21 + MT6360_LED_ISNKML, 22 + MT6360_LED_FLASH1, 23 + MT6360_LED_FLASH2, 24 + MT6360_MAX_LEDS 25 + }; 26 + 27 + #define MT6360_REG_RGBEN 0x380 28 + #define MT6360_REG_ISNK(_led_no) (0x381 + (_led_no)) 29 + #define MT6360_ISNK_ENMASK(_led_no) BIT(7 - (_led_no)) 30 + #define MT6360_ISNK_MASK GENMASK(4, 0) 31 + #define MT6360_CHRINDSEL_MASK BIT(3) 32 + 33 + /* Virtual definition for multicolor */ 34 + #define MT6360_VIRTUAL_MULTICOLOR (MT6360_MAX_LEDS + 1) 35 + #define MULTICOLOR_NUM_CHANNELS 3 36 + 37 + #define MT6360_REG_FLEDEN 0x37E 38 + #define MT6360_REG_STRBTO 0x373 39 + #define MT6360_REG_FLEDBASE(_id) (0x372 + 4 * (_id - MT6360_LED_FLASH1)) 40 + #define MT6360_REG_FLEDISTRB(_id) (MT6360_REG_FLEDBASE(_id) + 2) 41 + #define MT6360_REG_FLEDITOR(_id) (MT6360_REG_FLEDBASE(_id) + 3) 42 + #define MT6360_REG_CHGSTAT2 0x3E1 43 + #define MT6360_REG_FLEDSTAT1 0x3E9 44 + #define MT6360_ITORCH_MASK GENMASK(4, 0) 45 + #define MT6360_ISTROBE_MASK GENMASK(6, 0) 46 + #define MT6360_STRBTO_MASK GENMASK(6, 0) 47 + #define MT6360_TORCHEN_MASK BIT(3) 48 + #define MT6360_STROBEN_MASK BIT(2) 49 + #define MT6360_FLCSEN_MASK(_id) BIT(MT6360_LED_FLASH2 - _id) 50 + #define MT6360_FLEDCHGVINOVP_MASK BIT(3) 51 + #define MT6360_FLED1STRBTO_MASK BIT(11) 52 + #define MT6360_FLED2STRBTO_MASK BIT(10) 53 + #define MT6360_FLED1STRB_MASK BIT(9) 54 + #define MT6360_FLED2STRB_MASK BIT(8) 55 + #define MT6360_FLED1SHORT_MASK BIT(7) 56 + #define MT6360_FLED2SHORT_MASK BIT(6) 57 + #define MT6360_FLEDLVF_MASK BIT(3) 58 + 59 + #define MT6360_ISNKRGB_STEPUA 2000 60 + #define MT6360_ISNKRGB_MAXUA 24000 61 + #define MT6360_ISNKML_STEPUA 5000 62 + #define MT6360_ISNKML_MAXUA 150000 63 + 64 + #define MT6360_ITORCH_MINUA 25000 65 + #define MT6360_ITORCH_STEPUA 12500 66 + #define MT6360_ITORCH_MAXUA 400000 67 + #define MT6360_ISTRB_MINUA 50000 68 + #define MT6360_ISTRB_STEPUA 12500 69 + #define MT6360_ISTRB_MAXUA 1500000 70 + #define MT6360_STRBTO_MINUS 64000 71 + #define MT6360_STRBTO_STEPUS 32000 72 + #define MT6360_STRBTO_MAXUS 2432000 73 + 74 + #define STATE_OFF 0 75 + #define STATE_KEEP 1 76 + #define STATE_ON 2 77 + 78 + struct mt6360_led { 79 + union { 80 + struct led_classdev isnk; 81 + struct led_classdev_mc mc; 82 + struct led_classdev_flash flash; 83 + }; 84 + struct v4l2_flash *v4l2_flash; 85 + struct mt6360_priv *priv; 86 + u32 led_no; 87 + u32 default_state; 88 + }; 89 + 90 + struct mt6360_priv { 91 + struct device *dev; 92 + struct regmap *regmap; 93 + struct mutex lock; 94 + unsigned int fled_strobe_used; 95 + unsigned int fled_torch_used; 96 + unsigned int leds_active; 97 + unsigned int leds_count; 98 + struct mt6360_led leds[]; 99 + }; 100 + 101 + static int mt6360_mc_brightness_set(struct led_classdev *lcdev, 102 + enum led_brightness level) 103 + { 104 + struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev); 105 + struct mt6360_led *led = container_of(mccdev, struct mt6360_led, mc); 106 + struct mt6360_priv *priv = led->priv; 107 + u32 real_bright, enable_mask = 0, enable = 0; 108 + int i, ret; 109 + 110 + mutex_lock(&priv->lock); 111 + 112 + led_mc_calc_color_components(mccdev, level); 113 + 114 + for (i = 0; i < mccdev->num_colors; i++) { 115 + struct mc_subled *subled = mccdev->subled_info + i; 116 + 117 + real_bright = min(lcdev->max_brightness, subled->brightness); 118 + ret = regmap_update_bits(priv->regmap, MT6360_REG_ISNK(i), 119 + MT6360_ISNK_MASK, real_bright); 120 + if (ret) 121 + goto out; 122 + 123 + enable_mask |= MT6360_ISNK_ENMASK(subled->channel); 124 + if (real_bright) 125 + enable |= MT6360_ISNK_ENMASK(subled->channel); 126 + } 127 + 128 + ret = regmap_update_bits(priv->regmap, MT6360_REG_RGBEN, enable_mask, 129 + enable); 130 + 131 + out: 132 + mutex_unlock(&priv->lock); 133 + return ret; 134 + } 135 + 136 + static int mt6360_isnk_brightness_set(struct led_classdev *lcdev, 137 + enum led_brightness level) 138 + { 139 + struct mt6360_led *led = container_of(lcdev, struct mt6360_led, isnk); 140 + struct mt6360_priv *priv = led->priv; 141 + u32 enable_mask = MT6360_ISNK_ENMASK(led->led_no); 142 + u32 val = level ? MT6360_ISNK_ENMASK(led->led_no) : 0; 143 + int ret; 144 + 145 + mutex_lock(&priv->lock); 146 + 147 + ret = regmap_update_bits(priv->regmap, MT6360_REG_ISNK(led->led_no), 148 + MT6360_ISNK_MASK, level); 149 + if (ret) 150 + goto out; 151 + 152 + ret = regmap_update_bits(priv->regmap, MT6360_REG_RGBEN, enable_mask, 153 + val); 154 + 155 + out: 156 + mutex_unlock(&priv->lock); 157 + return ret; 158 + } 159 + 160 + static int mt6360_torch_brightness_set(struct led_classdev *lcdev, 161 + enum led_brightness level) 162 + { 163 + struct mt6360_led *led = 164 + container_of(lcdev, struct mt6360_led, flash.led_cdev); 165 + struct mt6360_priv *priv = led->priv; 166 + u32 enable_mask = MT6360_TORCHEN_MASK | MT6360_FLCSEN_MASK(led->led_no); 167 + u32 val = level ? MT6360_FLCSEN_MASK(led->led_no) : 0; 168 + u32 prev = priv->fled_torch_used, curr; 169 + int ret; 170 + 171 + mutex_lock(&priv->lock); 172 + 173 + /* 174 + * Only one set of flash control logic, use the flag to avoid strobe is 175 + * currently used. 176 + */ 177 + if (priv->fled_strobe_used) { 178 + dev_warn(lcdev->dev, "Please disable strobe first [%d]\n", 179 + priv->fled_strobe_used); 180 + ret = -EBUSY; 181 + goto unlock; 182 + } 183 + 184 + if (level) 185 + curr = prev | BIT(led->led_no); 186 + else 187 + curr = prev & ~BIT(led->led_no); 188 + 189 + if (curr) 190 + val |= MT6360_TORCHEN_MASK; 191 + 192 + if (level) { 193 + ret = regmap_update_bits(priv->regmap, 194 + MT6360_REG_FLEDITOR(led->led_no), 195 + MT6360_ITORCH_MASK, level - 1); 196 + if (ret) 197 + goto unlock; 198 + } 199 + 200 + ret = regmap_update_bits(priv->regmap, MT6360_REG_FLEDEN, enable_mask, 201 + val); 202 + if (ret) 203 + goto unlock; 204 + 205 + priv->fled_torch_used = curr; 206 + 207 + unlock: 208 + mutex_unlock(&priv->lock); 209 + return ret; 210 + } 211 + 212 + static int mt6360_flash_brightness_set(struct led_classdev_flash *fl_cdev, 213 + u32 brightness) 214 + { 215 + /* 216 + * Due to the current spike when turning on flash, let brightness to be 217 + * kept by framework. 218 + * This empty function is used to prevent led_classdev_flash register 219 + * ops check failure. 220 + */ 221 + return 0; 222 + } 223 + 224 + static int _mt6360_flash_brightness_set(struct led_classdev_flash *fl_cdev, 225 + u32 brightness) 226 + { 227 + struct mt6360_led *led = 228 + container_of(fl_cdev, struct mt6360_led, flash); 229 + struct mt6360_priv *priv = led->priv; 230 + struct led_flash_setting *s = &fl_cdev->brightness; 231 + u32 val = (brightness - s->min) / s->step; 232 + 233 + return regmap_update_bits(priv->regmap, 234 + MT6360_REG_FLEDISTRB(led->led_no), 235 + MT6360_ISTROBE_MASK, val); 236 + } 237 + 238 + static int mt6360_strobe_set(struct led_classdev_flash *fl_cdev, bool state) 239 + { 240 + struct mt6360_led *led = 241 + container_of(fl_cdev, struct mt6360_led, flash); 242 + struct mt6360_priv *priv = led->priv; 243 + struct led_classdev *lcdev = &fl_cdev->led_cdev; 244 + struct led_flash_setting *s = &fl_cdev->brightness; 245 + u32 enable_mask = MT6360_STROBEN_MASK | MT6360_FLCSEN_MASK(led->led_no); 246 + u32 val = state ? MT6360_FLCSEN_MASK(led->led_no) : 0; 247 + u32 prev = priv->fled_strobe_used, curr; 248 + int ret; 249 + 250 + mutex_lock(&priv->lock); 251 + 252 + /* 253 + * Only one set of flash control logic, use the flag to avoid torch is 254 + * currently used 255 + */ 256 + if (priv->fled_torch_used) { 257 + dev_warn(lcdev->dev, "Please disable torch first [0x%x]\n", 258 + priv->fled_torch_used); 259 + ret = -EBUSY; 260 + goto unlock; 261 + } 262 + 263 + if (state) 264 + curr = prev | BIT(led->led_no); 265 + else 266 + curr = prev & ~BIT(led->led_no); 267 + 268 + if (curr) 269 + val |= MT6360_STROBEN_MASK; 270 + 271 + ret = regmap_update_bits(priv->regmap, MT6360_REG_FLEDEN, enable_mask, 272 + val); 273 + if (ret) { 274 + dev_err(lcdev->dev, "[%d] control current source %d fail\n", 275 + led->led_no, state); 276 + goto unlock; 277 + } 278 + 279 + /* 280 + * If the flash need to be on, config the flash current ramping up to 281 + * the setting value. 282 + * Else, always recover back to the minimum one 283 + */ 284 + ret = _mt6360_flash_brightness_set(fl_cdev, state ? s->val : s->min); 285 + if (ret) 286 + goto unlock; 287 + 288 + /* 289 + * For the flash turn on/off, HW rampping up/down time is 5ms/500us, 290 + * respectively. 291 + */ 292 + if (!prev && curr) 293 + usleep_range(5000, 6000); 294 + else if (prev && !curr) 295 + udelay(500); 296 + 297 + priv->fled_strobe_used = curr; 298 + 299 + unlock: 300 + mutex_unlock(&priv->lock); 301 + return ret; 302 + } 303 + 304 + static int mt6360_strobe_get(struct led_classdev_flash *fl_cdev, bool *state) 305 + { 306 + struct mt6360_led *led = 307 + container_of(fl_cdev, struct mt6360_led, flash); 308 + struct mt6360_priv *priv = led->priv; 309 + 310 + mutex_lock(&priv->lock); 311 + *state = !!(priv->fled_strobe_used & BIT(led->led_no)); 312 + mutex_unlock(&priv->lock); 313 + 314 + return 0; 315 + } 316 + 317 + static int mt6360_timeout_set(struct led_classdev_flash *fl_cdev, u32 timeout) 318 + { 319 + struct mt6360_led *led = 320 + container_of(fl_cdev, struct mt6360_led, flash); 321 + struct mt6360_priv *priv = led->priv; 322 + struct led_flash_setting *s = &fl_cdev->timeout; 323 + u32 val = (timeout - s->min) / s->step; 324 + int ret; 325 + 326 + mutex_lock(&priv->lock); 327 + ret = regmap_update_bits(priv->regmap, MT6360_REG_STRBTO, 328 + MT6360_STRBTO_MASK, val); 329 + mutex_unlock(&priv->lock); 330 + 331 + return ret; 332 + } 333 + 334 + static int mt6360_fault_get(struct led_classdev_flash *fl_cdev, u32 *fault) 335 + { 336 + struct mt6360_led *led = 337 + container_of(fl_cdev, struct mt6360_led, flash); 338 + struct mt6360_priv *priv = led->priv; 339 + u16 fled_stat; 340 + unsigned int chg_stat, strobe_timeout_mask, fled_short_mask; 341 + u32 rfault = 0; 342 + int ret; 343 + 344 + mutex_lock(&priv->lock); 345 + ret = regmap_read(priv->regmap, MT6360_REG_CHGSTAT2, &chg_stat); 346 + if (ret) 347 + goto unlock; 348 + 349 + ret = regmap_raw_read(priv->regmap, MT6360_REG_FLEDSTAT1, &fled_stat, 350 + sizeof(fled_stat)); 351 + if (ret) 352 + goto unlock; 353 + 354 + if (led->led_no == MT6360_LED_FLASH1) { 355 + strobe_timeout_mask = MT6360_FLED1STRBTO_MASK; 356 + fled_short_mask = MT6360_FLED1SHORT_MASK; 357 + } else { 358 + strobe_timeout_mask = MT6360_FLED2STRBTO_MASK; 359 + fled_short_mask = MT6360_FLED2SHORT_MASK; 360 + } 361 + 362 + if (chg_stat & MT6360_FLEDCHGVINOVP_MASK) 363 + rfault |= LED_FAULT_INPUT_VOLTAGE; 364 + 365 + if (fled_stat & strobe_timeout_mask) 366 + rfault |= LED_FAULT_TIMEOUT; 367 + 368 + if (fled_stat & fled_short_mask) 369 + rfault |= LED_FAULT_SHORT_CIRCUIT; 370 + 371 + if (fled_stat & MT6360_FLEDLVF_MASK) 372 + rfault |= LED_FAULT_UNDER_VOLTAGE; 373 + 374 + *fault = rfault; 375 + unlock: 376 + mutex_unlock(&priv->lock); 377 + return ret; 378 + } 379 + 380 + static const struct led_flash_ops mt6360_flash_ops = { 381 + .flash_brightness_set = mt6360_flash_brightness_set, 382 + .strobe_set = mt6360_strobe_set, 383 + .strobe_get = mt6360_strobe_get, 384 + .timeout_set = mt6360_timeout_set, 385 + .fault_get = mt6360_fault_get, 386 + }; 387 + 388 + static int mt6360_isnk_init_default_state(struct mt6360_led *led) 389 + { 390 + struct mt6360_priv *priv = led->priv; 391 + unsigned int regval; 392 + u32 level; 393 + int ret; 394 + 395 + ret = regmap_read(priv->regmap, MT6360_REG_ISNK(led->led_no), &regval); 396 + if (ret) 397 + return ret; 398 + level = regval & MT6360_ISNK_MASK; 399 + 400 + ret = regmap_read(priv->regmap, MT6360_REG_RGBEN, &regval); 401 + if (ret) 402 + return ret; 403 + 404 + if (!(regval & MT6360_ISNK_ENMASK(led->led_no))) 405 + level = LED_OFF; 406 + 407 + switch (led->default_state) { 408 + case STATE_ON: 409 + led->isnk.brightness = led->isnk.max_brightness; 410 + break; 411 + case STATE_KEEP: 412 + led->isnk.brightness = min(level, led->isnk.max_brightness); 413 + break; 414 + default: 415 + led->isnk.brightness = LED_OFF; 416 + } 417 + 418 + return mt6360_isnk_brightness_set(&led->isnk, led->isnk.brightness); 419 + } 420 + 421 + static int mt6360_flash_init_default_state(struct mt6360_led *led) 422 + { 423 + struct led_classdev_flash *flash = &led->flash; 424 + struct mt6360_priv *priv = led->priv; 425 + u32 enable_mask = MT6360_TORCHEN_MASK | MT6360_FLCSEN_MASK(led->led_no); 426 + u32 level; 427 + unsigned int regval; 428 + int ret; 429 + 430 + ret = regmap_read(priv->regmap, MT6360_REG_FLEDITOR(led->led_no), 431 + &regval); 432 + if (ret) 433 + return ret; 434 + level = regval & MT6360_ITORCH_MASK; 435 + 436 + ret = regmap_read(priv->regmap, MT6360_REG_FLEDEN, &regval); 437 + if (ret) 438 + return ret; 439 + 440 + if ((regval & enable_mask) == enable_mask) 441 + level += 1; 442 + else 443 + level = LED_OFF; 444 + 445 + switch (led->default_state) { 446 + case STATE_ON: 447 + flash->led_cdev.brightness = flash->led_cdev.max_brightness; 448 + break; 449 + case STATE_KEEP: 450 + flash->led_cdev.brightness = 451 + min(level, flash->led_cdev.max_brightness); 452 + break; 453 + default: 454 + flash->led_cdev.brightness = LED_OFF; 455 + } 456 + 457 + return mt6360_torch_brightness_set(&flash->led_cdev, 458 + flash->led_cdev.brightness); 459 + } 460 + 461 + #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS) 462 + static int mt6360_flash_external_strobe_set(struct v4l2_flash *v4l2_flash, 463 + bool enable) 464 + { 465 + struct led_classdev_flash *flash = v4l2_flash->fled_cdev; 466 + struct mt6360_led *led = container_of(flash, struct mt6360_led, flash); 467 + struct mt6360_priv *priv = led->priv; 468 + u32 mask = MT6360_FLCSEN_MASK(led->led_no); 469 + u32 val = enable ? mask : 0; 470 + int ret; 471 + 472 + mutex_lock(&priv->lock); 473 + 474 + ret = regmap_update_bits(priv->regmap, MT6360_REG_FLEDEN, mask, val); 475 + if (ret) 476 + goto unlock; 477 + 478 + if (enable) 479 + priv->fled_strobe_used |= BIT(led->led_no); 480 + else 481 + priv->fled_strobe_used &= ~BIT(led->led_no); 482 + 483 + unlock: 484 + mutex_unlock(&priv->lock); 485 + return ret; 486 + } 487 + 488 + static const struct v4l2_flash_ops v4l2_flash_ops = { 489 + .external_strobe_set = mt6360_flash_external_strobe_set, 490 + }; 491 + 492 + static void mt6360_init_v4l2_flash_config(struct mt6360_led *led, 493 + struct v4l2_flash_config *config) 494 + { 495 + struct led_classdev *lcdev; 496 + struct led_flash_setting *s = &config->intensity; 497 + 498 + lcdev = &led->flash.led_cdev; 499 + 500 + s->min = MT6360_ITORCH_MINUA; 501 + s->step = MT6360_ITORCH_STEPUA; 502 + s->val = s->max = s->min + (lcdev->max_brightness - 1) * s->step; 503 + 504 + config->has_external_strobe = 1; 505 + strscpy(config->dev_name, lcdev->dev->kobj.name, 506 + sizeof(config->dev_name)); 507 + 508 + config->flash_faults = LED_FAULT_SHORT_CIRCUIT | LED_FAULT_TIMEOUT | 509 + LED_FAULT_INPUT_VOLTAGE | 510 + LED_FAULT_UNDER_VOLTAGE; 511 + } 512 + #else 513 + static const struct v4l2_flash_ops v4l2_flash_ops; 514 + static void mt6360_init_v4l2_flash_config(struct mt6360_led *led, 515 + struct v4l2_flash_config *config) 516 + { 517 + } 518 + #endif 519 + 520 + static int mt6360_led_register(struct device *parent, struct mt6360_led *led, 521 + struct led_init_data *init_data) 522 + { 523 + struct mt6360_priv *priv = led->priv; 524 + struct v4l2_flash_config v4l2_config = {0}; 525 + int ret; 526 + 527 + if ((led->led_no == MT6360_LED_ISNK1 || 528 + led->led_no == MT6360_VIRTUAL_MULTICOLOR) && 529 + (priv->leds_active & BIT(MT6360_LED_ISNK1))) { 530 + /* 531 + * Change isink1 to SW control mode, disconnect it with 532 + * charger state 533 + */ 534 + ret = regmap_update_bits(priv->regmap, MT6360_REG_RGBEN, 535 + MT6360_CHRINDSEL_MASK, 536 + MT6360_CHRINDSEL_MASK); 537 + if (ret) { 538 + dev_err(parent, "Failed to config ISNK1 to SW mode\n"); 539 + return ret; 540 + } 541 + } 542 + 543 + switch (led->led_no) { 544 + case MT6360_VIRTUAL_MULTICOLOR: 545 + ret = mt6360_mc_brightness_set(&led->mc.led_cdev, LED_OFF); 546 + if (ret) { 547 + dev_err(parent, 548 + "Failed to init multicolor brightness\n"); 549 + return ret; 550 + } 551 + 552 + ret = devm_led_classdev_multicolor_register_ext(parent, 553 + &led->mc, init_data); 554 + if (ret) { 555 + dev_err(parent, "Couldn't register multicolor\n"); 556 + return ret; 557 + } 558 + break; 559 + case MT6360_LED_ISNK1 ... MT6360_LED_ISNKML: 560 + ret = mt6360_isnk_init_default_state(led); 561 + if (ret) { 562 + dev_err(parent, "Failed to init %d isnk state\n", 563 + led->led_no); 564 + return ret; 565 + } 566 + 567 + ret = devm_led_classdev_register_ext(parent, &led->isnk, 568 + init_data); 569 + if (ret) { 570 + dev_err(parent, "Couldn't register isink %d\n", 571 + led->led_no); 572 + return ret; 573 + } 574 + break; 575 + default: 576 + ret = mt6360_flash_init_default_state(led); 577 + if (ret) { 578 + dev_err(parent, "Failed to init %d flash state\n", 579 + led->led_no); 580 + return ret; 581 + } 582 + 583 + ret = devm_led_classdev_flash_register_ext(parent, &led->flash, 584 + init_data); 585 + if (ret) { 586 + dev_err(parent, "Couldn't register flash %d\n", 587 + led->led_no); 588 + return ret; 589 + } 590 + 591 + mt6360_init_v4l2_flash_config(led, &v4l2_config); 592 + led->v4l2_flash = v4l2_flash_init(parent, init_data->fwnode, 593 + &led->flash, 594 + &v4l2_flash_ops, 595 + &v4l2_config); 596 + if (IS_ERR(led->v4l2_flash)) { 597 + dev_err(parent, "Failed to register %d v4l2 sd\n", 598 + led->led_no); 599 + return PTR_ERR(led->v4l2_flash); 600 + } 601 + } 602 + 603 + return 0; 604 + } 605 + 606 + static u32 clamp_align(u32 val, u32 min, u32 max, u32 step) 607 + { 608 + u32 retval; 609 + 610 + retval = clamp_val(val, min, max); 611 + if (step > 1) 612 + retval = rounddown(retval - min, step) + min; 613 + 614 + return retval; 615 + } 616 + 617 + static int mt6360_init_isnk_properties(struct mt6360_led *led, 618 + struct led_init_data *init_data) 619 + { 620 + struct led_classdev *lcdev; 621 + struct mt6360_priv *priv = led->priv; 622 + struct fwnode_handle *child; 623 + u32 step_uA = MT6360_ISNKRGB_STEPUA, max_uA = MT6360_ISNKRGB_MAXUA; 624 + u32 val; 625 + int num_color = 0, ret; 626 + 627 + if (led->led_no == MT6360_VIRTUAL_MULTICOLOR) { 628 + struct mc_subled *sub_led; 629 + 630 + sub_led = devm_kzalloc(priv->dev, 631 + sizeof(*sub_led) * MULTICOLOR_NUM_CHANNELS, GFP_KERNEL); 632 + if (!sub_led) 633 + return -ENOMEM; 634 + 635 + fwnode_for_each_child_node(init_data->fwnode, child) { 636 + u32 reg, color; 637 + 638 + ret = fwnode_property_read_u32(child, "reg", &reg); 639 + if (ret || reg > MT6360_LED_ISNK3 || 640 + priv->leds_active & BIT(reg)) 641 + return -EINVAL; 642 + 643 + ret = fwnode_property_read_u32(child, "color", &color); 644 + if (ret) { 645 + dev_err(priv->dev, 646 + "led %d, no color specified\n", 647 + led->led_no); 648 + return ret; 649 + } 650 + 651 + priv->leds_active |= BIT(reg); 652 + sub_led[num_color].color_index = color; 653 + sub_led[num_color].channel = reg; 654 + num_color++; 655 + } 656 + 657 + if (num_color < 2) { 658 + dev_err(priv->dev, 659 + "Multicolor must include 2 or more led channel\n"); 660 + return -EINVAL; 661 + } 662 + 663 + led->mc.num_colors = num_color; 664 + led->mc.subled_info = sub_led; 665 + 666 + lcdev = &led->mc.led_cdev; 667 + lcdev->brightness_set_blocking = mt6360_mc_brightness_set; 668 + } else { 669 + if (led->led_no == MT6360_LED_ISNKML) { 670 + step_uA = MT6360_ISNKML_STEPUA; 671 + max_uA = MT6360_ISNKML_MAXUA; 672 + } 673 + 674 + lcdev = &led->isnk; 675 + lcdev->brightness_set_blocking = mt6360_isnk_brightness_set; 676 + } 677 + 678 + ret = fwnode_property_read_u32(init_data->fwnode, "led-max-microamp", 679 + &val); 680 + if (ret) { 681 + dev_warn(priv->dev, 682 + "Not specified led-max-microamp, config to the minimum\n"); 683 + val = step_uA; 684 + } else 685 + val = clamp_align(val, 0, max_uA, step_uA); 686 + 687 + lcdev->max_brightness = val / step_uA; 688 + 689 + fwnode_property_read_string(init_data->fwnode, "linux,default-trigger", 690 + &lcdev->default_trigger); 691 + 692 + return 0; 693 + } 694 + 695 + static int mt6360_init_flash_properties(struct mt6360_led *led, 696 + struct led_init_data *init_data) 697 + { 698 + struct led_classdev_flash *flash = &led->flash; 699 + struct led_classdev *lcdev = &flash->led_cdev; 700 + struct mt6360_priv *priv = led->priv; 701 + struct led_flash_setting *s; 702 + u32 val; 703 + int ret; 704 + 705 + ret = fwnode_property_read_u32(init_data->fwnode, "led-max-microamp", 706 + &val); 707 + if (ret) { 708 + dev_warn(priv->dev, 709 + "Not specified led-max-microamp, config to the minimum\n"); 710 + val = MT6360_ITORCH_MINUA; 711 + } else 712 + val = clamp_align(val, MT6360_ITORCH_MINUA, MT6360_ITORCH_MAXUA, 713 + MT6360_ITORCH_STEPUA); 714 + 715 + lcdev->max_brightness = 716 + (val - MT6360_ITORCH_MINUA) / MT6360_ITORCH_STEPUA + 1; 717 + lcdev->brightness_set_blocking = mt6360_torch_brightness_set; 718 + lcdev->flags |= LED_DEV_CAP_FLASH; 719 + 720 + ret = fwnode_property_read_u32(init_data->fwnode, "flash-max-microamp", 721 + &val); 722 + if (ret) { 723 + dev_warn(priv->dev, 724 + "Not specified flash-max-microamp, config to the minimum\n"); 725 + val = MT6360_ISTRB_MINUA; 726 + } else 727 + val = clamp_align(val, MT6360_ISTRB_MINUA, MT6360_ISTRB_MAXUA, 728 + MT6360_ISTRB_STEPUA); 729 + 730 + s = &flash->brightness; 731 + s->min = MT6360_ISTRB_MINUA; 732 + s->step = MT6360_ISTRB_STEPUA; 733 + s->val = s->max = val; 734 + 735 + /* 736 + * Always configure as min level when off to prevent flash current 737 + * spike. 738 + */ 739 + ret = _mt6360_flash_brightness_set(flash, s->min); 740 + if (ret) 741 + return ret; 742 + 743 + ret = fwnode_property_read_u32(init_data->fwnode, 744 + "flash-max-timeout-us", &val); 745 + if (ret) { 746 + dev_warn(priv->dev, 747 + "Not specified flash-max-timeout-us, config to the minimum\n"); 748 + val = MT6360_STRBTO_MINUS; 749 + } else 750 + val = clamp_align(val, MT6360_STRBTO_MINUS, MT6360_STRBTO_MAXUS, 751 + MT6360_STRBTO_STEPUS); 752 + 753 + s = &flash->timeout; 754 + s->min = MT6360_STRBTO_MINUS; 755 + s->step = MT6360_STRBTO_STEPUS; 756 + s->val = s->max = val; 757 + 758 + flash->ops = &mt6360_flash_ops; 759 + 760 + return 0; 761 + } 762 + 763 + static int mt6360_init_common_properties(struct mt6360_led *led, 764 + struct led_init_data *init_data) 765 + { 766 + const char *const states[] = { "off", "keep", "on" }; 767 + const char *str; 768 + int ret; 769 + 770 + if (!fwnode_property_read_string(init_data->fwnode, 771 + "default-state", &str)) { 772 + ret = match_string(states, ARRAY_SIZE(states), str); 773 + if (ret < 0) 774 + ret = STATE_OFF; 775 + 776 + led->default_state = ret; 777 + } 778 + 779 + return 0; 780 + } 781 + 782 + static void mt6360_v4l2_flash_release(struct mt6360_priv *priv) 783 + { 784 + int i; 785 + 786 + for (i = 0; i < priv->leds_count; i++) { 787 + struct mt6360_led *led = priv->leds + i; 788 + 789 + if (led->v4l2_flash) 790 + v4l2_flash_release(led->v4l2_flash); 791 + } 792 + } 793 + 794 + static int mt6360_led_probe(struct platform_device *pdev) 795 + { 796 + struct mt6360_priv *priv; 797 + struct fwnode_handle *child; 798 + size_t count; 799 + int i = 0, ret; 800 + 801 + count = device_get_child_node_count(&pdev->dev); 802 + if (!count || count > MT6360_MAX_LEDS) { 803 + dev_err(&pdev->dev, 804 + "No child node or node count over max led number %zu\n", 805 + count); 806 + return -EINVAL; 807 + } 808 + 809 + priv = devm_kzalloc(&pdev->dev, 810 + struct_size(priv, leds, count), GFP_KERNEL); 811 + if (!priv) 812 + return -ENOMEM; 813 + 814 + priv->leds_count = count; 815 + priv->dev = &pdev->dev; 816 + mutex_init(&priv->lock); 817 + 818 + priv->regmap = dev_get_regmap(pdev->dev.parent, NULL); 819 + if (!priv->regmap) { 820 + dev_err(&pdev->dev, "Failed to get parent regmap\n"); 821 + return -ENODEV; 822 + } 823 + 824 + device_for_each_child_node(&pdev->dev, child) { 825 + struct mt6360_led *led = priv->leds + i; 826 + struct led_init_data init_data = { .fwnode = child, }; 827 + u32 reg, led_color; 828 + 829 + ret = fwnode_property_read_u32(child, "color", &led_color); 830 + if (ret) 831 + goto out_flash_release; 832 + 833 + if (led_color == LED_COLOR_ID_RGB || 834 + led_color == LED_COLOR_ID_MULTI) 835 + reg = MT6360_VIRTUAL_MULTICOLOR; 836 + else { 837 + ret = fwnode_property_read_u32(child, "reg", &reg); 838 + if (ret) 839 + goto out_flash_release; 840 + 841 + if (reg >= MT6360_MAX_LEDS) { 842 + ret = -EINVAL; 843 + goto out_flash_release; 844 + } 845 + } 846 + 847 + if (priv->leds_active & BIT(reg)) { 848 + ret = -EINVAL; 849 + goto out_flash_release; 850 + } 851 + priv->leds_active |= BIT(reg); 852 + 853 + led->led_no = reg; 854 + led->priv = priv; 855 + 856 + ret = mt6360_init_common_properties(led, &init_data); 857 + if (ret) 858 + goto out_flash_release; 859 + 860 + if (reg == MT6360_VIRTUAL_MULTICOLOR || 861 + reg <= MT6360_LED_ISNKML) 862 + ret = mt6360_init_isnk_properties(led, &init_data); 863 + else 864 + ret = mt6360_init_flash_properties(led, &init_data); 865 + 866 + if (ret) 867 + goto out_flash_release; 868 + 869 + ret = mt6360_led_register(&pdev->dev, led, &init_data); 870 + if (ret) 871 + goto out_flash_release; 872 + 873 + i++; 874 + } 875 + 876 + platform_set_drvdata(pdev, priv); 877 + return 0; 878 + 879 + out_flash_release: 880 + mt6360_v4l2_flash_release(priv); 881 + return ret; 882 + } 883 + 884 + static int mt6360_led_remove(struct platform_device *pdev) 885 + { 886 + struct mt6360_priv *priv = platform_get_drvdata(pdev); 887 + 888 + mt6360_v4l2_flash_release(priv); 889 + return 0; 890 + } 891 + 892 + static const struct of_device_id __maybe_unused mt6360_led_of_id[] = { 893 + { .compatible = "mediatek,mt6360-led", }, 894 + {} 895 + }; 896 + MODULE_DEVICE_TABLE(of, mt6360_led_of_id); 897 + 898 + static struct platform_driver mt6360_led_driver = { 899 + .driver = { 900 + .name = "mt6360-led", 901 + .of_match_table = mt6360_led_of_id, 902 + }, 903 + .probe = mt6360_led_probe, 904 + .remove = mt6360_led_remove, 905 + }; 906 + module_platform_driver(mt6360_led_driver); 907 + 908 + MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>"); 909 + MODULE_DESCRIPTION("MT6360 LED Driver"); 910 + MODULE_LICENSE("GPL v2");
+2 -4
drivers/leds/led-class.c
··· 375 375 mutex_unlock(&led_cdev->led_access); 376 376 return PTR_ERR(led_cdev->dev); 377 377 } 378 - if (init_data && init_data->fwnode) { 379 - led_cdev->dev->fwnode = init_data->fwnode; 380 - led_cdev->dev->of_node = to_of_node(init_data->fwnode); 381 - } 378 + if (init_data && init_data->fwnode) 379 + device_set_node(led_cdev->dev, init_data->fwnode); 382 380 383 381 if (ret) 384 382 dev_warn(parent, "Led %s renamed to %s due to name collision",
-193
drivers/leds/leds-fsg.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * LED Driver for the Freecom FSG-3 4 - * 5 - * Copyright (c) 2008 Rod Whitby <rod@whitby.id.au> 6 - * 7 - * Author: Rod Whitby <rod@whitby.id.au> 8 - * 9 - * Based on leds-spitz.c 10 - * Copyright 2005-2006 Openedhand Ltd. 11 - * Author: Richard Purdie <rpurdie@openedhand.com> 12 - */ 13 - 14 - #include <linux/kernel.h> 15 - #include <linux/platform_device.h> 16 - #include <linux/leds.h> 17 - #include <linux/module.h> 18 - #include <linux/io.h> 19 - #include <mach/hardware.h> 20 - 21 - #define FSG_LED_WLAN_BIT 0 22 - #define FSG_LED_WAN_BIT 1 23 - #define FSG_LED_SATA_BIT 2 24 - #define FSG_LED_USB_BIT 4 25 - #define FSG_LED_RING_BIT 5 26 - #define FSG_LED_SYNC_BIT 7 27 - 28 - static short __iomem *latch_address; 29 - static unsigned short latch_value; 30 - 31 - 32 - static void fsg_led_wlan_set(struct led_classdev *led_cdev, 33 - enum led_brightness value) 34 - { 35 - if (value) { 36 - latch_value &= ~(1 << FSG_LED_WLAN_BIT); 37 - *latch_address = latch_value; 38 - } else { 39 - latch_value |= (1 << FSG_LED_WLAN_BIT); 40 - *latch_address = latch_value; 41 - } 42 - } 43 - 44 - static void fsg_led_wan_set(struct led_classdev *led_cdev, 45 - enum led_brightness value) 46 - { 47 - if (value) { 48 - latch_value &= ~(1 << FSG_LED_WAN_BIT); 49 - *latch_address = latch_value; 50 - } else { 51 - latch_value |= (1 << FSG_LED_WAN_BIT); 52 - *latch_address = latch_value; 53 - } 54 - } 55 - 56 - static void fsg_led_sata_set(struct led_classdev *led_cdev, 57 - enum led_brightness value) 58 - { 59 - if (value) { 60 - latch_value &= ~(1 << FSG_LED_SATA_BIT); 61 - *latch_address = latch_value; 62 - } else { 63 - latch_value |= (1 << FSG_LED_SATA_BIT); 64 - *latch_address = latch_value; 65 - } 66 - } 67 - 68 - static void fsg_led_usb_set(struct led_classdev *led_cdev, 69 - enum led_brightness value) 70 - { 71 - if (value) { 72 - latch_value &= ~(1 << FSG_LED_USB_BIT); 73 - *latch_address = latch_value; 74 - } else { 75 - latch_value |= (1 << FSG_LED_USB_BIT); 76 - *latch_address = latch_value; 77 - } 78 - } 79 - 80 - static void fsg_led_sync_set(struct led_classdev *led_cdev, 81 - enum led_brightness value) 82 - { 83 - if (value) { 84 - latch_value &= ~(1 << FSG_LED_SYNC_BIT); 85 - *latch_address = latch_value; 86 - } else { 87 - latch_value |= (1 << FSG_LED_SYNC_BIT); 88 - *latch_address = latch_value; 89 - } 90 - } 91 - 92 - static void fsg_led_ring_set(struct led_classdev *led_cdev, 93 - enum led_brightness value) 94 - { 95 - if (value) { 96 - latch_value &= ~(1 << FSG_LED_RING_BIT); 97 - *latch_address = latch_value; 98 - } else { 99 - latch_value |= (1 << FSG_LED_RING_BIT); 100 - *latch_address = latch_value; 101 - } 102 - } 103 - 104 - 105 - static struct led_classdev fsg_wlan_led = { 106 - .name = "fsg:blue:wlan", 107 - .brightness_set = fsg_led_wlan_set, 108 - .flags = LED_CORE_SUSPENDRESUME, 109 - }; 110 - 111 - static struct led_classdev fsg_wan_led = { 112 - .name = "fsg:blue:wan", 113 - .brightness_set = fsg_led_wan_set, 114 - .flags = LED_CORE_SUSPENDRESUME, 115 - }; 116 - 117 - static struct led_classdev fsg_sata_led = { 118 - .name = "fsg:blue:sata", 119 - .brightness_set = fsg_led_sata_set, 120 - .flags = LED_CORE_SUSPENDRESUME, 121 - }; 122 - 123 - static struct led_classdev fsg_usb_led = { 124 - .name = "fsg:blue:usb", 125 - .brightness_set = fsg_led_usb_set, 126 - .flags = LED_CORE_SUSPENDRESUME, 127 - }; 128 - 129 - static struct led_classdev fsg_sync_led = { 130 - .name = "fsg:blue:sync", 131 - .brightness_set = fsg_led_sync_set, 132 - .flags = LED_CORE_SUSPENDRESUME, 133 - }; 134 - 135 - static struct led_classdev fsg_ring_led = { 136 - .name = "fsg:blue:ring", 137 - .brightness_set = fsg_led_ring_set, 138 - .flags = LED_CORE_SUSPENDRESUME, 139 - }; 140 - 141 - 142 - static int fsg_led_probe(struct platform_device *pdev) 143 - { 144 - int ret; 145 - 146 - /* Map the LED chip select address space */ 147 - latch_address = (unsigned short *) devm_ioremap(&pdev->dev, 148 - IXP4XX_EXP_BUS_BASE(2), 512); 149 - if (!latch_address) 150 - return -ENOMEM; 151 - 152 - latch_value = 0xffff; 153 - *latch_address = latch_value; 154 - 155 - ret = devm_led_classdev_register(&pdev->dev, &fsg_wlan_led); 156 - if (ret < 0) 157 - return ret; 158 - 159 - ret = devm_led_classdev_register(&pdev->dev, &fsg_wan_led); 160 - if (ret < 0) 161 - return ret; 162 - 163 - ret = devm_led_classdev_register(&pdev->dev, &fsg_sata_led); 164 - if (ret < 0) 165 - return ret; 166 - 167 - ret = devm_led_classdev_register(&pdev->dev, &fsg_usb_led); 168 - if (ret < 0) 169 - return ret; 170 - 171 - ret = devm_led_classdev_register(&pdev->dev, &fsg_sync_led); 172 - if (ret < 0) 173 - return ret; 174 - 175 - ret = devm_led_classdev_register(&pdev->dev, &fsg_ring_led); 176 - if (ret < 0) 177 - return ret; 178 - 179 - return ret; 180 - } 181 - 182 - static struct platform_driver fsg_led_driver = { 183 - .probe = fsg_led_probe, 184 - .driver = { 185 - .name = "fsg-led", 186 - }, 187 - }; 188 - 189 - module_platform_driver(fsg_led_driver); 190 - 191 - MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>"); 192 - MODULE_DESCRIPTION("Freecom FSG-3 LED driver"); 193 - MODULE_LICENSE("GPL");
-1
drivers/leds/leds-lp50xx.c
··· 266 266 struct led_classdev_mc mc_cdev; 267 267 struct lp50xx *priv; 268 268 unsigned long bank_modules; 269 - int led_intensity[LP50XX_LEDS_PER_MODULE]; 270 269 u8 ctrl_bank_enabled; 271 270 int led_number; 272 271 };
+3 -1
drivers/leds/leds-lp55xx-common.c
··· 439 439 return -EINVAL; 440 440 441 441 if (pdata->enable_gpiod) { 442 + gpiod_direction_output(pdata->enable_gpiod, 0); 443 + 442 444 gpiod_set_consumer_name(pdata->enable_gpiod, "LP55xx enable"); 443 445 gpiod_set_value(pdata->enable_gpiod, 0); 444 446 usleep_range(1000, 2000); /* Keep enable down at least 1ms */ ··· 696 694 of_property_read_u8(np, "clock-mode", &pdata->clock_mode); 697 695 698 696 pdata->enable_gpiod = devm_gpiod_get_optional(dev, "enable", 699 - GPIOD_OUT_LOW); 697 + GPIOD_ASIS); 700 698 if (IS_ERR(pdata->enable_gpiod)) 701 699 return ERR_CAST(pdata->enable_gpiod); 702 700
+1 -6
drivers/leds/leds-tca6507.c
··· 242 242 if (diff < 65536) { 243 243 int actual; 244 244 if (msec & 1) { 245 - c1 = *c2p; 246 - *c2p = *c1p; 247 - *c1p = c1; 245 + swap(*c2p, *c1p); 248 246 } 249 247 actual = time_codes[*c1p] + time_codes[*c2p]; 250 248 if (*c1p < *c2p) ··· 641 643 tca->gpio.direction_output = tca6507_gpio_direction_output; 642 644 tca->gpio.set = tca6507_gpio_set_value; 643 645 tca->gpio.parent = dev; 644 - #ifdef CONFIG_OF_GPIO 645 - tca->gpio.of_node = of_node_get(dev_of_node(dev)); 646 - #endif 647 646 err = gpiochip_add_data(&tca->gpio, tca); 648 647 if (err) { 649 648 tca->gpio.ngpio = 0;