mirror of https://github.com/torvalds/linux.git
LEDS for v6.19
* Add optional GPIO enable pin support to PWM LED driver.
* Allow LED module 0 to be added to module bank in lp50xx driver.
* Fix upboard LED driver module alias to ensure proper auto-loading.
* Update LP5009 to support 3 modules for a total of 9 LEDs.
* Skip LEDs without color components in cros_ec driver instead of failing probe.
* Fix GPIO descriptor leaks in netxbig error paths by releasing acquired GPIOs.
* Allow LED_COLOR_ID_MULTI in qcom-lpg driver for greater flexibility.
* Enable LP55XX common LED use without FW_LOADER_USER_HELPER.
* Ensure lp50xx chip is enabled before any I2C communication.
* Use fwnode_for_each_child_node() instead of fwnode_for_each_available_child_node()
in LED drivers.
* Use device_get_next_child_node() instead of fwnode_get_next_available_child_node()
in LED flash drivers.
* Replace sprintf() with sysfs_emit() in sysfs show functions for improved
bounds checking.
* Replace system_wq() with system_percpu_wq() in the input event trigger.
* Reorder include files to alphabetic order in the PWM LED driver.
* Do not enable TRILED in qcom-lpg when configuring PWM.
* Drop duplicate LEDS_EXPRESSWIRE config from Kconfig.
* Remove arcxcnn_bl.txt Device Tree binding documentation.
* Convert ArcticSand arc2c0608 LED driver binding to DT Schema.
* Add default-brightness property to common LED binding.
* Add enable-gpios property to PWM LED binding.
* Add PM7550 to qcom,spmi-flash-led compatible.
* Explain standalone PWM usage in qcom-lpg binding.
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEdrbJNaO+IJqU8IdIUa+KL4f8d2EFAmkxtx8ACgkQUa+KL4f8
d2EsAA/+KdtCs9WXrFcQOHZBlZvLeNMklninXPjMFOMcjd6A9l26XzkKW5qS59ax
1H+gUxjryN5EGtYE1ITKjpwwWJL+VEGsMXcuonMf0g/UwE5CFw3VR1nL3+xK9IM0
2xzTZwDkbqYUVsEWVparazdvVU/niwqdjyWqfYFM3XXZWk5TpFkzOnluRwSPAt70
IZRJzYPHlGiZKmFpLtmxFcsJM7MiqsHgP3tzMEAmUHFQg75MhWVUJld8hTaek6hf
gS+jqdoCV6+dnP76KlRZ2OMHwAG/Nmu91mFp5VnG8vIH6PhERokP6ewi07lJUPTp
bHyb/oWb+YJvAXnzZ5Yh5q7ygnAa2kFgYAmUBDQyvTwmOgloMl7qb1hzSOqfRkE0
xyQ8ah6gtTu6Tq0kBB3jV9UFfG1ecDjRVqIbJnEFZjOfb3peyjdNVjgMraBWGCHB
D93RAft/aByE3bnX20DF2icOGJDmlAVaHPETO8yMBVIKfynjY3y8eTdt126pT7a8
HOs8UtJZXmwHdgtvgUzAOiklxvuYMKIBqkym8BQ20lCnqw+BKxqQ962+rGJhrxOj
AKy4gx980HmBxaet4ssn5ba186+jlCR26WFPRAcHF17c8+aKPXH8htdPFZPWAd1Z
MoQP/VOHzsPE4x75xvVX9DkZiv9WyHxaCzxlXXZhAHiYxoLg4uE=
=/TDJ
-----END PGP SIGNATURE-----
Merge tag 'leds-next-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds
Pull LED updates from Lee Jones:
"Updates:
- Add optional GPIO enable pin support to PWM LED driver
Fixes:
- Allow LED module 0 to be added to module bank in lp50xx driver
- Fix upboard LED driver module alias to ensure proper auto-loading
- Update LP5009 to support 3 modules for a total of 9 LEDs
- Skip LEDs without color components in cros_ec driver instead of
failing probe
- Fix GPIO descriptor leaks in netxbig error paths by releasing
acquired GPIOs
- Allow LED_COLOR_ID_MULTI in qcom-lpg driver for greater flexibility
- Enable LP55XX common LED use without FW_LOADER_USER_HELPER
- Ensure lp50xx chip is enabled before any I2C communication
Cleanups:
- Use fwnode_for_each_child_node() instead of
fwnode_for_each_available_child_node() in LED drivers
- Use device_get_next_child_node() instead of
fwnode_get_next_available_child_node() in LED flash drivers
- Replace sprintf() with sysfs_emit() in sysfs show functions for
improved bounds checking
- Replace system_wq() with system_percpu_wq() in the input event
trigger
- Reorder include files to alphabetic order in the PWM LED driver
- Do not enable TRILED in qcom-lpg when configuring PWM
- Drop duplicate LEDS_EXPRESSWIRE config from Kconfig
Removals:
- Remove arcxcnn_bl.txt Device Tree binding documentation
Devicetree bindings:
- Convert ArcticSand arc2c0608 LED driver binding to DT Schema
- Add default-brightness property to common LED binding
- Add enable-gpios property to PWM LED binding
- Add PM7550 to qcom,spmi-flash-led compatible
- Explain standalone PWM usage in qcom-lpg binding"
* tag 'leds-next-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds: (21 commits)
leds: rgb: leds-qcom-lpg: Don't enable TRILED when configuring PWM
dt-bindings: leds: qcom-lpg: Explain standalone PWM usage
leds: rgb: leds-qcom-lpg: Allow LED_COLOR_ID_MULTI
leds: pwm: Reorder include files to alphabetic order
leds: pwm: Add optional GPIO enable pin support
dt-bindings: leds: pwm: Add enable-gpios property
leds: trigger: Replace use of system_wq() with system_percpu_wq()
leds: led-class: Replace sprintf() with sysfs_emit() in sysfs show functions
dt-bindings: leds: qcom,spmi-flash-led: Add PM7550
leds: netxbig: Fix GPIO descriptor leak in error paths
leds: leds-lp50xx: Enable chip before any communication
leds: Drop duplicate LEDS_EXPRESSWIRE config
leds: leds-cros_ec: Skip LEDs without color components
leds: leds-lp50xx: LP5009 supports 3 modules for a total of 9 LEDs
leds: upboard: Fix module alias
leds: leds-lp50xx: Allow LED 0 to be added to module bank
leds: lp55xx_common: Enable use without FW_LOADER_USER_HELPER
dt-bindings: leds: Add default-brightness property to common.yaml
leds: flash: Use fwnode_get_next_child_node() instead
leds: Use fwnode_for_each_child_node() instead
...
This commit is contained in:
commit
7b8653a579
|
|
@ -0,0 +1,108 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/leds/backlight/arc,arc2c0608.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ArcticSand arc2c0608 LED driver
|
||||
|
||||
description: |
|
||||
The ArcticSand arc2c0608 LED driver provides ultra
|
||||
efficient notebook backlighting. Optional properties not
|
||||
specified will default to values in IC EPROM.
|
||||
|
||||
Datasheet:
|
||||
https://www.murata.com/-/media/webrenewal/products/power/power-semiconductor/overview/lineup/led-boost/arc2/arc2c0608.ashx.
|
||||
|
||||
maintainers:
|
||||
- Brian Dodge <bdodge@arcticsand.com>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/leds/common.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: arc,arc2c0608
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
default-brightness:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 4095
|
||||
|
||||
led-sources:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description: List of enabled channels
|
||||
items:
|
||||
enum: [0, 1, 2, 3, 4, 5]
|
||||
minItems: 1
|
||||
uniqueItems: true
|
||||
|
||||
arc,led-config-0:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Fading speed (period between intensity
|
||||
steps)
|
||||
|
||||
arc,led-config-1:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: If set, sets ILED_CONFIG register. Used for
|
||||
fine tuning the maximum LED current.
|
||||
|
||||
arc,dim-freq:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: PWM mode frequency setting (bits [3:0] used)
|
||||
|
||||
arc,comp-config:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Setting for register CONFIG_COMP which
|
||||
controls internal resitances, feed forward freqs,
|
||||
and initial VOUT at startup. Consult the datasheet.
|
||||
|
||||
arc,filter-config:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: RC and PWM Filter settings.
|
||||
Bit Assignment
|
||||
7654 3 2 1 0
|
||||
xxxx RCF1 RCF0 PWM1 PWM0
|
||||
RCF statuses PWM Filter Statues
|
||||
00 = OFF (default) 00 = OFF (default)
|
||||
01 = LOW 01 = 2 STEPS
|
||||
10 - MEDIUM 10 = 4 STEPS
|
||||
11 = HIGH 11 = 8 STEPS
|
||||
|
||||
arc,trim-config:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Sets percentage increase of Maximum LED
|
||||
Current.
|
||||
0x00 = 0% increase.
|
||||
0x20 = 20.2%.
|
||||
0x3F = 41.5%
|
||||
|
||||
label: true
|
||||
|
||||
linux,default-trigger: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
led-controller@30 {
|
||||
compatible = "arc,arc2c0608";
|
||||
reg = <0x30>;
|
||||
default-brightness = <500>;
|
||||
label = "lcd-backlight";
|
||||
linux,default-trigger = "backlight";
|
||||
led-sources = <0 1 2 5>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
Binding for ArcticSand arc2c0608 LED driver
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "arc,arc2c0608"
|
||||
- reg: slave address
|
||||
|
||||
Optional properties:
|
||||
- default-brightness: brightness value on boot, value from: 0-4095
|
||||
- label: The name of the backlight device
|
||||
See Documentation/devicetree/bindings/leds/common.txt
|
||||
- led-sources: List of enabled channels from 0 to 5.
|
||||
See Documentation/devicetree/bindings/leds/common.txt
|
||||
|
||||
- arc,led-config-0: setting for register ILED_CONFIG_0
|
||||
- arc,led-config-1: setting for register ILED_CONFIG_1
|
||||
- arc,dim-freq: PWM mode frequence setting (bits [3:0] used)
|
||||
- arc,comp-config: setting for register CONFIG_COMP
|
||||
- arc,filter-config: setting for register FILTER_CONFIG
|
||||
- arc,trim-config: setting for register IMAXTUNE
|
||||
|
||||
Note: Optional properties not specified will default to values in IC EPROM
|
||||
|
||||
Example:
|
||||
|
||||
arc2c0608@30 {
|
||||
compatible = "arc,arc2c0608";
|
||||
reg = <0x30>;
|
||||
default-brightness = <500>;
|
||||
label = "lcd-backlight";
|
||||
linux,default-trigger = "backlight";
|
||||
led-sources = <0 1 2 5>;
|
||||
};
|
||||
|
||||
|
|
@ -173,6 +173,12 @@ properties:
|
|||
led-max-microamp.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
default-brightness:
|
||||
description:
|
||||
Brightness to be set if LED's default state is on. Used only during
|
||||
initialization. If the option is not set then max brightness is used.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
panic-indicator:
|
||||
description:
|
||||
This property specifies that the LED should be used, if at all possible,
|
||||
|
|
|
|||
|
|
@ -40,6 +40,13 @@ patternProperties:
|
|||
initialization. If the option is not set then max brightness is used.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
enable-gpios:
|
||||
description:
|
||||
GPIO for LED hardware enable control. Set active when brightness is
|
||||
non-zero and inactive when brightness is zero.
|
||||
The GPIO default state follows the "default-state" property.
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- pwms
|
||||
- max-brightness
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@ description: >
|
|||
The Qualcomm Light Pulse Generator consists of three different hardware blocks;
|
||||
a ramp generator with lookup table (LUT), the light pulse generator and a three
|
||||
channel current sink. These blocks are found in a wide range of Qualcomm PMICs.
|
||||
The light pulse generator (LPG) can also be used independently to output PWM
|
||||
signal for standard PWM applications. In this scenario, the LPG output should
|
||||
be routed to a specific PMIC GPIO by setting the GPIO pin mux to the special
|
||||
functions indicated in the datasheet, the TRILED driver for the channel will
|
||||
not be enabled in this configuration.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ properties:
|
|||
- enum:
|
||||
- qcom,pm6150l-flash-led
|
||||
- qcom,pm660l-flash-led
|
||||
- qcom,pm7550-flash-led
|
||||
- qcom,pm8150c-flash-led
|
||||
- qcom,pm8150l-flash-led
|
||||
- qcom,pm8350c-flash-led
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ More details of the instructions can be found from the public data sheet.
|
|||
LP5521 has the internal program memory for running various LED patterns.
|
||||
There are two ways to run LED patterns.
|
||||
|
||||
1) Legacy interface - enginex_mode and enginex_load
|
||||
1) sysfs interface - enginex_mode and enginex_load
|
||||
Control interface for the engines:
|
||||
|
||||
x is 1 .. 3
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ If both fields are NULL, 'lp5523' is used by default.
|
|||
LP5523 has the internal program memory for running various LED patterns.
|
||||
There are two ways to run LED patterns.
|
||||
|
||||
1) Legacy interface - enginex_mode, enginex_load and enginex_leds
|
||||
1) sysfs interface - enginex_mode, enginex_load and enginex_leds
|
||||
|
||||
Control interface for the engines:
|
||||
|
||||
|
|
|
|||
|
|
@ -214,10 +214,6 @@ config LEDS_EL15203000
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called leds-el15203000.
|
||||
|
||||
config LEDS_EXPRESSWIRE
|
||||
bool
|
||||
depends on GPIOLIB
|
||||
|
||||
config LEDS_TURRIS_OMNIA
|
||||
tristate "LED support for CZ.NIC's Turris Omnia"
|
||||
depends on LEDS_CLASS_MULTICOLOR
|
||||
|
|
@ -443,8 +439,8 @@ config LEDS_LP55XX_COMMON
|
|||
depends on LEDS_CLASS_MULTICOLOR
|
||||
depends on OF
|
||||
depends on I2C
|
||||
select FW_LOADER
|
||||
select FW_LOADER_USER_HELPER
|
||||
imply FW_LOADER
|
||||
imply FW_LOADER_USER_HELPER
|
||||
help
|
||||
This option supports common operations for LP5521/5523/55231/5562/5569/
|
||||
8501 devices.
|
||||
|
|
|
|||
|
|
@ -365,7 +365,7 @@ static int rt4505_probe(struct i2c_client *client)
|
|||
return ret;
|
||||
}
|
||||
|
||||
child = fwnode_get_next_available_child_node(client->dev.fwnode, NULL);
|
||||
child = device_get_next_child_node(&client->dev, NULL);
|
||||
if (!child) {
|
||||
dev_err(priv->dev, "Failed to get child node\n");
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ static int rt8515_probe(struct platform_device *pdev)
|
|||
return dev_err_probe(dev, PTR_ERR(rt->enable_torch),
|
||||
"cannot get ENT (enable torch) GPIO\n");
|
||||
|
||||
child = fwnode_get_next_available_child_node(dev->fwnode, NULL);
|
||||
child = device_get_next_child_node(dev, NULL);
|
||||
if (!child) {
|
||||
dev_err(dev,
|
||||
"No fwnode child node found for connected LED.\n");
|
||||
|
|
|
|||
|
|
@ -214,8 +214,7 @@ static int sgm3140_probe(struct platform_device *pdev)
|
|||
return dev_err_probe(&pdev->dev, ret,
|
||||
"Failed to request regulator\n");
|
||||
|
||||
child_node = fwnode_get_next_available_child_node(pdev->dev.fwnode,
|
||||
NULL);
|
||||
child_node = device_get_next_child_node(&pdev->dev, NULL);
|
||||
if (!child_node) {
|
||||
dev_err(&pdev->dev,
|
||||
"No fwnode child node found for connected LED.\n");
|
||||
|
|
|
|||
|
|
@ -544,7 +544,7 @@ static int tps6131x_parse_node(struct tps6131x *tps6131x)
|
|||
|
||||
tps6131x->valley_current_limit = device_property_read_bool(dev, "ti,valley-current-limit");
|
||||
|
||||
tps6131x->led_node = fwnode_get_next_available_child_node(dev->fwnode, NULL);
|
||||
tps6131x->led_node = device_get_next_child_node(dev, NULL);
|
||||
if (!tps6131x->led_node) {
|
||||
dev_err(dev, "Missing LED node\n");
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ static ssize_t brightness_show(struct device *dev,
|
|||
brightness = led_cdev->brightness;
|
||||
mutex_unlock(&led_cdev->led_access);
|
||||
|
||||
return sprintf(buf, "%u\n", brightness);
|
||||
return sysfs_emit(buf, "%u\n", brightness);
|
||||
}
|
||||
|
||||
static ssize_t brightness_store(struct device *dev,
|
||||
|
|
@ -80,7 +80,7 @@ static ssize_t max_brightness_show(struct device *dev,
|
|||
max_brightness = led_cdev->max_brightness;
|
||||
mutex_unlock(&led_cdev->led_access);
|
||||
|
||||
return sprintf(buf, "%u\n", max_brightness);
|
||||
return sysfs_emit(buf, "%u\n", max_brightness);
|
||||
}
|
||||
static DEVICE_ATTR_RO(max_brightness);
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ static ssize_t brightness_hw_changed_show(struct device *dev,
|
|||
if (led_cdev->brightness_hw_changed == -1)
|
||||
return -ENODATA;
|
||||
|
||||
return sprintf(buf, "%u\n", led_cdev->brightness_hw_changed);
|
||||
return sysfs_emit(buf, "%u\n", led_cdev->brightness_hw_changed);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(brightness_hw_changed);
|
||||
|
|
|
|||
|
|
@ -142,9 +142,6 @@ static int cros_ec_led_count_subleds(struct device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
if (!num_subleds)
|
||||
return -EINVAL;
|
||||
|
||||
*max_brightness = common_range;
|
||||
return num_subleds;
|
||||
}
|
||||
|
|
@ -189,6 +186,8 @@ static int cros_ec_led_probe_one(struct device *dev, struct cros_ec_device *cros
|
|||
&priv->led_mc_cdev.led_cdev.max_brightness);
|
||||
if (num_subleds < 0)
|
||||
return num_subleds;
|
||||
if (num_subleds == 0)
|
||||
return 0; /* LED without any colors, skip */
|
||||
|
||||
priv->cros_ec = cros_ec;
|
||||
priv->led_id = id;
|
||||
|
|
|
|||
|
|
@ -50,11 +50,17 @@
|
|||
|
||||
#define LP50XX_SW_RESET 0xff
|
||||
#define LP50XX_CHIP_EN BIT(6)
|
||||
#define LP50XX_CHIP_DISABLE 0x00
|
||||
#define LP50XX_START_TIME_US 500
|
||||
#define LP50XX_RESET_TIME_US 3
|
||||
|
||||
#define LP50XX_EN_GPIO_LOW 0
|
||||
#define LP50XX_EN_GPIO_HIGH 1
|
||||
|
||||
/* There are 3 LED outputs per bank */
|
||||
#define LP50XX_LEDS_PER_MODULE 3
|
||||
|
||||
#define LP5009_MAX_LED_MODULES 2
|
||||
#define LP5009_MAX_LED_MODULES 3
|
||||
#define LP5012_MAX_LED_MODULES 4
|
||||
#define LP5018_MAX_LED_MODULES 6
|
||||
#define LP5024_MAX_LED_MODULES 8
|
||||
|
|
@ -341,17 +347,15 @@ static int lp50xx_brightness_set(struct led_classdev *cdev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int lp50xx_set_banks(struct lp50xx *priv, u32 led_banks[])
|
||||
static int lp50xx_set_banks(struct lp50xx *priv, u32 led_banks[], int num_leds)
|
||||
{
|
||||
u8 led_config_lo, led_config_hi;
|
||||
u32 bank_enable_mask = 0;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->chip_info->max_modules; i++) {
|
||||
if (led_banks[i])
|
||||
bank_enable_mask |= (1 << led_banks[i]);
|
||||
}
|
||||
for (i = 0; i < num_leds; i++)
|
||||
bank_enable_mask |= (1 << led_banks[i]);
|
||||
|
||||
led_config_lo = bank_enable_mask;
|
||||
led_config_hi = bank_enable_mask >> 8;
|
||||
|
|
@ -371,19 +375,42 @@ static int lp50xx_reset(struct lp50xx *priv)
|
|||
return regmap_write(priv->regmap, priv->chip_info->reset_reg, LP50XX_SW_RESET);
|
||||
}
|
||||
|
||||
static int lp50xx_enable_disable(struct lp50xx *priv, int enable_disable)
|
||||
static int lp50xx_enable(struct lp50xx *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpiod_direction_output(priv->enable_gpio, enable_disable);
|
||||
if (priv->enable_gpio) {
|
||||
ret = gpiod_direction_output(priv->enable_gpio, LP50XX_EN_GPIO_HIGH);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
udelay(LP50XX_START_TIME_US);
|
||||
}
|
||||
|
||||
ret = lp50xx_reset(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (enable_disable)
|
||||
return regmap_write(priv->regmap, LP50XX_DEV_CFG0, LP50XX_CHIP_EN);
|
||||
else
|
||||
return regmap_write(priv->regmap, LP50XX_DEV_CFG0, 0);
|
||||
return regmap_write(priv->regmap, LP50XX_DEV_CFG0, LP50XX_CHIP_EN);
|
||||
}
|
||||
|
||||
static int lp50xx_disable(struct lp50xx *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(priv->regmap, LP50XX_DEV_CFG0, LP50XX_CHIP_DISABLE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (priv->enable_gpio) {
|
||||
ret = gpiod_direction_output(priv->enable_gpio, LP50XX_EN_GPIO_LOW);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
udelay(LP50XX_RESET_TIME_US);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lp50xx_probe_leds(struct fwnode_handle *child, struct lp50xx *priv,
|
||||
|
|
@ -405,7 +432,7 @@ static int lp50xx_probe_leds(struct fwnode_handle *child, struct lp50xx *priv,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = lp50xx_set_banks(priv, led_banks);
|
||||
ret = lp50xx_set_banks(priv, led_banks, num_leds);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "Cannot setup banked LEDs\n");
|
||||
return ret;
|
||||
|
|
@ -447,6 +474,10 @@ static int lp50xx_probe_dt(struct lp50xx *priv)
|
|||
return dev_err_probe(priv->dev, PTR_ERR(priv->enable_gpio),
|
||||
"Failed to get enable GPIO\n");
|
||||
|
||||
ret = lp50xx_enable(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->regulator = devm_regulator_get(priv->dev, "vled");
|
||||
if (IS_ERR(priv->regulator))
|
||||
priv->regulator = NULL;
|
||||
|
|
@ -547,14 +578,6 @@ static int lp50xx_probe(struct i2c_client *client)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = lp50xx_reset(led);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = lp50xx_enable_disable(led, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return lp50xx_probe_dt(led);
|
||||
}
|
||||
|
||||
|
|
@ -563,7 +586,7 @@ static void lp50xx_remove(struct i2c_client *client)
|
|||
struct lp50xx *led = i2c_get_clientdata(client);
|
||||
int ret;
|
||||
|
||||
ret = lp50xx_enable_disable(led, 0);
|
||||
ret = lp50xx_disable(led);
|
||||
if (ret)
|
||||
dev_err(led->dev, "Failed to disable chip\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ static int max5970_led_probe(struct platform_device *pdev)
|
|||
if (!led_node)
|
||||
return -ENODEV;
|
||||
|
||||
fwnode_for_each_available_child_node(led_node, child) {
|
||||
fwnode_for_each_child_node(led_node, child) {
|
||||
u32 reg;
|
||||
|
||||
if (fwnode_property_read_u32(child, "reg", ®))
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ static int max77705_add_led(struct device *dev, struct regmap *regmap, struct fw
|
|||
cdev->brightness_set_blocking = max77705_led_brightness_set_multi;
|
||||
cdev->blink_set = max77705_rgb_blink;
|
||||
|
||||
fwnode_for_each_available_child_node(np, child) {
|
||||
fwnode_for_each_child_node(np, child) {
|
||||
ret = max77705_parse_subled(dev, child, &info[i]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -364,6 +364,9 @@ static int netxbig_gpio_ext_get(struct device *dev,
|
|||
if (!addr)
|
||||
return -ENOMEM;
|
||||
|
||||
gpio_ext->addr = addr;
|
||||
gpio_ext->num_addr = 0;
|
||||
|
||||
/*
|
||||
* We cannot use devm_ managed resources with these GPIO descriptors
|
||||
* since they are associated with the "GPIO extension device" which
|
||||
|
|
@ -375,45 +378,58 @@ static int netxbig_gpio_ext_get(struct device *dev,
|
|||
gpiod = gpiod_get_index(gpio_ext_dev, "addr", i,
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(gpiod))
|
||||
return PTR_ERR(gpiod);
|
||||
goto err_set_code;
|
||||
gpiod_set_consumer_name(gpiod, "GPIO extension addr");
|
||||
addr[i] = gpiod;
|
||||
gpio_ext->num_addr++;
|
||||
}
|
||||
gpio_ext->addr = addr;
|
||||
gpio_ext->num_addr = num_addr;
|
||||
|
||||
ret = gpiod_count(gpio_ext_dev, "data");
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"Failed to count GPIOs in DT property data-gpios\n");
|
||||
return ret;
|
||||
goto err_free_addr;
|
||||
}
|
||||
num_data = ret;
|
||||
data = devm_kcalloc(dev, num_data, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
if (!data) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_addr;
|
||||
}
|
||||
|
||||
gpio_ext->data = data;
|
||||
gpio_ext->num_data = 0;
|
||||
|
||||
for (i = 0; i < num_data; i++) {
|
||||
gpiod = gpiod_get_index(gpio_ext_dev, "data", i,
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(gpiod))
|
||||
return PTR_ERR(gpiod);
|
||||
goto err_free_data;
|
||||
gpiod_set_consumer_name(gpiod, "GPIO extension data");
|
||||
data[i] = gpiod;
|
||||
gpio_ext->num_data++;
|
||||
}
|
||||
gpio_ext->data = data;
|
||||
gpio_ext->num_data = num_data;
|
||||
|
||||
gpiod = gpiod_get(gpio_ext_dev, "enable", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(gpiod)) {
|
||||
dev_err(dev,
|
||||
"Failed to get GPIO from DT property enable-gpio\n");
|
||||
return PTR_ERR(gpiod);
|
||||
goto err_free_data;
|
||||
}
|
||||
gpiod_set_consumer_name(gpiod, "GPIO extension enable");
|
||||
gpio_ext->enable = gpiod;
|
||||
|
||||
return devm_add_action_or_reset(dev, netxbig_gpio_ext_remove, gpio_ext);
|
||||
|
||||
err_free_data:
|
||||
for (i = 0; i < gpio_ext->num_data; i++)
|
||||
gpiod_put(gpio_ext->data[i]);
|
||||
err_set_code:
|
||||
ret = PTR_ERR(gpiod);
|
||||
err_free_addr:
|
||||
for (i = 0; i < gpio_ext->num_addr; i++)
|
||||
gpiod_put(gpio_ext->addr[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int netxbig_leds_get_of_pdata(struct device *dev,
|
||||
|
|
|
|||
|
|
@ -9,12 +9,13 @@
|
|||
* based on leds-gpio.c by Raphael Assenat <raph@8d.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
|
@ -26,6 +27,7 @@ struct led_pwm {
|
|||
};
|
||||
|
||||
struct led_pwm_data {
|
||||
struct gpio_desc *enable_gpio;
|
||||
struct led_classdev cdev;
|
||||
struct pwm_device *pwm;
|
||||
struct pwm_state pwmstate;
|
||||
|
|
@ -51,6 +53,8 @@ static int led_pwm_set(struct led_classdev *led_cdev,
|
|||
if (led_dat->active_low)
|
||||
duty = led_dat->pwmstate.period - duty;
|
||||
|
||||
gpiod_set_value_cansleep(led_dat->enable_gpio, !!brightness);
|
||||
|
||||
led_dat->pwmstate.duty_cycle = duty;
|
||||
/*
|
||||
* Disabling a PWM doesn't guarantee that it emits the inactive level.
|
||||
|
|
@ -132,6 +136,21 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
|
|||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Claim the GPIO as GPIOD_ASIS and set the value
|
||||
* later on to honor the different default states
|
||||
*/
|
||||
led_data->enable_gpio = devm_fwnode_gpiod_get(dev, fwnode, "enable", GPIOD_ASIS, NULL);
|
||||
if (IS_ERR(led_data->enable_gpio)) {
|
||||
if (PTR_ERR(led_data->enable_gpio) == -ENOENT)
|
||||
/* Enable GPIO is optional */
|
||||
led_data->enable_gpio = NULL;
|
||||
else
|
||||
return PTR_ERR(led_data->enable_gpio);
|
||||
}
|
||||
|
||||
gpiod_direction_output(led_data->enable_gpio, !!led_data->cdev.brightness);
|
||||
|
||||
ret = devm_led_classdev_register_ext(dev, &led_data->cdev, &init_data);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to register PWM led for %s: %d\n",
|
||||
|
|
|
|||
|
|
@ -123,4 +123,4 @@ MODULE_AUTHOR("Gary Wang <garywang@aaeon.com.tw>");
|
|||
MODULE_AUTHOR("Thomas Richard <thomas.richard@bootlin.com>");
|
||||
MODULE_DESCRIPTION("UP Board LED driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:upboard-led");
|
||||
MODULE_ALIAS("platform:upboard-leds");
|
||||
|
|
|
|||
|
|
@ -391,7 +391,7 @@ static int ktd202x_setup_led_rgb(struct ktd202x *chip, struct fwnode_handle *fwn
|
|||
int i = 0;
|
||||
|
||||
num_channels = 0;
|
||||
fwnode_for_each_available_child_node(fwnode, child)
|
||||
fwnode_for_each_child_node(fwnode, child)
|
||||
num_channels++;
|
||||
|
||||
if (!num_channels || num_channels > chip->num_leds)
|
||||
|
|
@ -401,7 +401,7 @@ static int ktd202x_setup_led_rgb(struct ktd202x *chip, struct fwnode_handle *fwn
|
|||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
fwnode_for_each_available_child_node(fwnode, child) {
|
||||
fwnode_for_each_child_node(fwnode, child) {
|
||||
u32 mono_color;
|
||||
u32 reg;
|
||||
int ret;
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ static int ncp5623_probe(struct i2c_client *client)
|
|||
goto release_mc_node;
|
||||
}
|
||||
|
||||
fwnode_for_each_available_child_node(mc_node, led_node) {
|
||||
fwnode_for_each_child_node(mc_node, led_node) {
|
||||
ret = fwnode_property_read_u32(led_node, "color", &color_index);
|
||||
if (ret)
|
||||
goto release_led_node;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2022 Linaro Ltd
|
||||
* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
||||
*/
|
||||
#include <linux/bits.h>
|
||||
#include <linux/bitfield.h>
|
||||
|
|
@ -1247,8 +1247,6 @@ static int lpg_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
|||
|
||||
lpg_apply(chan);
|
||||
|
||||
triled_set(lpg, chan->triled_mask, chan->enabled ? chan->triled_mask : 0);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&lpg->lock);
|
||||
|
||||
|
|
@ -1382,7 +1380,7 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np)
|
|||
return dev_err_probe(lpg->dev, ret,
|
||||
"failed to parse \"color\" of %pOF\n", np);
|
||||
|
||||
if (color == LED_COLOR_ID_RGB)
|
||||
if (color == LED_COLOR_ID_RGB || color == LED_COLOR_ID_MULTI)
|
||||
num_channels = of_get_available_child_count(np);
|
||||
else
|
||||
num_channels = 1;
|
||||
|
|
@ -1394,7 +1392,7 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np)
|
|||
led->lpg = lpg;
|
||||
led->num_channels = num_channels;
|
||||
|
||||
if (color == LED_COLOR_ID_RGB) {
|
||||
if (color == LED_COLOR_ID_RGB || color == LED_COLOR_ID_MULTI) {
|
||||
info = devm_kcalloc(lpg->dev, num_channels, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
|
@ -1454,7 +1452,7 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np)
|
|||
|
||||
init_data.fwnode = of_fwnode_handle(np);
|
||||
|
||||
if (color == LED_COLOR_ID_RGB)
|
||||
if (color == LED_COLOR_ID_RGB || color == LED_COLOR_ID_MULTI)
|
||||
ret = devm_led_classdev_multicolor_register_ext(lpg->dev, &led->mcdev, &init_data);
|
||||
else
|
||||
ret = devm_led_classdev_register_ext(lpg->dev, &led->cdev, &init_data);
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ static void input_events_event(struct input_handle *handle, unsigned int type,
|
|||
|
||||
spin_unlock_irqrestore(&data->lock, flags);
|
||||
|
||||
mod_delayed_work(system_wq, &data->work, led_off_delay);
|
||||
mod_delayed_work(system_percpu_wq, &data->work, led_off_delay);
|
||||
}
|
||||
|
||||
static int input_events_connect(struct input_handler *handler, struct input_dev *dev,
|
||||
|
|
|
|||
Loading…
Reference in New Issue