mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'leds-next-6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds
Pull LED updates from Lee Jones:
"LED Triggers:
- Allow writing "default" to the sysfs 'trigger' attribute to set an
LED to its default trigger
- If the default trigger is "none", writing "default" will remove the
current trigger
- Updated sysfs ABI documentation for the new "default" trigger
functionality
LED KUnit Testing:
- Provide a skeleton KUnit test suite for the LEDs framework
- Expand the LED class device registration KUnit test to cover more
scenarios, including 'brightness_get' behavior
- Add KUnit tests for the LED lookup and get API ('led_add_lookup',
'devm_led_get')
LED Flash Class:
- Add support for setting flash/strobe duration through a new
'duration_set' op and 'led_set_flash_duration()' function, aligning
with 'V4L2_CID_FLASH_DURATION'
Texas Instruments TPS6131x:
- Add a new driver for the TPS61310/TPS61311 flash LED controllers
- The driver supports the device's three constant-current sinks for
flash and torch modes
LED Core:
- Prevent potential 'snprintf()' truncations in LED names by checking
for buffer overflows
ChromeOS EC LEDs:
- Avoid a -Wflex-array-member-not-at-end GCC warning by replacing an
on-stack flexible structure definition with a utility function call
Multicolor LEDs:
- Fix issue where setting multi_intensity while software blinking is
active could stop blinking
PCA955x LEDs:
- Avoid potential buffer overflow when creating default labels by
changing a field's type to 'u8' and updating format specifiers
PCA995x LEDs:
- Fix a typo (stray space) in an 'of_device_id' entry in the
'pca995x_of_match' table
Kconfig:
- Prevent LED drivers from being enabled by default when
'COMPILE_TEST' is set
Device Property API:
- Split 'device_get_child_node_count()' into a new helper
'fwnode_get_child_node_count()' that doesn't require a device
struct, making the API more symmetrical
Driver Modernization (using 'fwnode_get_child_node_count()'):
- Update 'leds-pwm-multicolor', 'leds-ncp5623' and 'leds-ncp5623' to
use the new 'fwnode_get_child_node_count()' helper, removing their
custom implementation
- As above in the USB Type-C TCPM driver
Driver Modernization (using new GPIO setter callbacks):
- Convert 'leds-lgm-sso' to use new GPIO line value setter callbacks
which return an integer for error handling
- Convert 'leds-pca955x', 'leds-pca9532' and 'leds-tca6507' to use
new GPIO setter callbacks
Documentation:
- Remove the '.rst' extension for 'leds-st1202' in the documentation
index for consistency
LP8860 LEDs:
- Use 'regmap_multi_reg_write()' for EEPROM writes instead of manual
looping
- Use scoped mutex guards and 'devm_mutex_init()' to simplify
function exits and ensure automatic cleanup
- Remove default register definitions that are unused when regmap
caching is not active
- Use 'devm_regulator_get_enable_optional()' to handle the optional
regulator, simplifying enabling and removing manual disabling
- Refactor 'lp8860_unlock_eeprom()' to only perform the unlock
operation, removing the lock part and an unnecessary parameter
- Use a 'devm' action to disable the enable-GPIO, simplifying cleanup
and error paths, and remove the now-empty '.remove()' function
Turris Omnia LEDs:
- Drop unnecessary commas in terminator entries of 'struct attribute'
and 'struct of_device_id' arrays
MT6370 RGB LEDs:
- Use the 'LINEAR_RANGE()' for defining 'struct linear_range' entries
to improve robustness
Texas Instruments TPS6131x:
- Add new devicetree bindings for the TI TPS61310/TPS61311 flash LED
driver"
* tag 'leds-next-6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds: (31 commits)
leds: tps6131x: Add support for Texas Instruments TPS6131X flash LED driver
dt-bindings: leds: Add Texas Instruments TPS6131x flash LED driver
leds: flash: Add support for flash/strobe duration
leds: rgb: leds-mt6370-rgb: Improve definition of some struct linear_range
leds: led-test: Provide tests for the lookup and get infrastructure
leds: led-test: Fill out the registration test to cover more test cases
leds: led-test: Remove standard error checking after KUNIT_ASSERT_*()
leds: pca995x: Fix typo in pca995x_of_match's of_device_id entry
leds: Provide skeleton KUnit testing for the LEDs framework
leds: tca6507: Use new GPIO line value setter callbacks
leds: pca9532: Use new GPIO line value setter callbacks
leds: pca955x: Use new GPIO line value setter callbacks
leds: lgm-sso: Use new GPIO line value setter callbacks
leds: Do not enable by default during compile testing
leds: turris-omnia: Drop commas in the terminator entries
leds: lp8860: Disable GPIO with devm action
leds: lp8860: Only unlock in lp8860_unlock_eeprom()
leds: lp8860: Enable regulator using enable_optional helper
leds: lp8860: Remove default regs when not caching
leds: lp8860: Use new mutex guards to cleanup function exits
...
This commit is contained in:
commit
b546608ea2
30 files changed
+1288
-258
No files matched your search
@@ -72,6 +72,12 @@ Description:
|
||||
/sys/class/leds/<led> once a given trigger is selected. For
|
||||
their documentation see `sysfs-class-led-trigger-*`.
|
||||
|
||||
Writing "none" removes the trigger for this LED.
|
||||
|
||||
Writing "default" sets the trigger to the LED's default trigger
|
||||
(which would often be configured in the device tree for the
|
||||
hardware).
|
||||
|
||||
What: /sys/class/leds/<led>/inverted
|
||||
Date: January 2011
|
||||
KernelVersion: 2.6.38
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/leds/ti,tps61310.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Texas Instruments TPS6131X flash LED driver
|
||||
|
||||
maintainers:
|
||||
- Matthias Fend <matthias.fend@emfend.at>
|
||||
|
||||
description: |
|
||||
The TPS61310/TPS61311 is a flash LED driver with I2C interface.
|
||||
Its power stage is capable of supplying a maximum total current of roughly 1500mA.
|
||||
The TPS6131x provides three constant-current sinks, capable of sinking
|
||||
up to 2 x 400mA (LED1 and LED3) and 800mA (LED2) in flash mode.
|
||||
In torch mode, each sink (LED1, LED2, LED3) supports currents up to 175mA.
|
||||
Since the three current sinks share most of the control components such as
|
||||
flash timer, control logic, safety timer and the operating mode, they cannot
|
||||
be used completely independently of each other. Therefore, only one LED is
|
||||
supported, but the current sinks can be combined accordingly.
|
||||
|
||||
The data sheet can be found at:
|
||||
https://www.ti.com/lit/ds/symlink/tps61310.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- ti,tps61311
|
||||
- const: ti,tps61310
|
||||
- items:
|
||||
- const: ti,tps61310
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
description: GPIO connected to NRESET pin
|
||||
|
||||
ti,valley-current-limit:
|
||||
type: boolean
|
||||
description:
|
||||
Reduce the valley peak current limit from 1750mA to 1250mA (TPS61310) or
|
||||
from 2480mA to 1800mA (TPS61311).
|
||||
|
||||
led:
|
||||
type: object
|
||||
$ref: common.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
led-sources:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
items:
|
||||
enum: [1, 2, 3]
|
||||
|
||||
led-max-microamp:
|
||||
oneOf:
|
||||
- minimum: 50000
|
||||
maximum: 350000
|
||||
multipleOf: 50000
|
||||
- minimum: 25000
|
||||
maximum: 525000
|
||||
multipleOf: 25000
|
||||
|
||||
flash-max-microamp:
|
||||
oneOf:
|
||||
- minimum: 50000
|
||||
maximum: 800000
|
||||
multipleOf: 50000
|
||||
- minimum: 25000
|
||||
maximum: 1500000
|
||||
multipleOf: 25000
|
||||
|
||||
flash-max-timeout-us:
|
||||
enum: [ 5300, 10700, 16000, 21300, 26600, 32000, 37300, 68200, 71500,
|
||||
102200, 136300, 170400, 204500, 340800, 579300, 852000 ]
|
||||
|
||||
required:
|
||||
- led-sources
|
||||
- led-max-microamp
|
||||
- flash-max-microamp
|
||||
- flash-max-timeout-us
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- led
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
led-controller@33 {
|
||||
compatible = "ti,tps61311", "ti,tps61310";
|
||||
reg = <0x33>;
|
||||
|
||||
reset-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
|
||||
|
||||
led {
|
||||
function = LED_FUNCTION_FLASH;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
led-sources = <1>, <2>, <3>;
|
||||
led-max-microamp = <525000>;
|
||||
flash-max-microamp = <1500000>;
|
||||
flash-max-timeout-us = <852000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -28,5 +28,5 @@ LEDs
|
||||
leds-mlxcpld
|
||||
leds-mt6370-rgb
|
||||
leds-sc27xx
|
||||
leds-st1202.rst
|
||||
leds-st1202
|
||||
leds-qcom-lpg
|
||||
@@ -24447,6 +24447,13 @@ F: Documentation/devicetree/bindings/hwmon/ti,tps23861.yaml
|
||||
F: Documentation/hwmon/tps23861.rst
|
||||
F: drivers/hwmon/tps23861.c
|
||||
|
||||
TEXAS INSTRUMENTS TPS6131X FLASH LED DRIVER
|
||||
M: Matthias Fend <matthias.fend@emfend.at>
|
||||
L: linux-leds@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/leds/ti,tps6131x.yaml
|
||||
F: drivers/leds/flash/leds-tps6131x.c
|
||||
|
||||
TEXAS INSTRUMENTS' DAC7612 DAC DRIVER
|
||||
M: Ricardo Ribalda <ribalda@kernel.org>
|
||||
L: linux-iio@vger.kernel.org
|
||||
|
||||
@@ -928,22 +928,22 @@ bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
|
||||
EXPORT_SYMBOL_GPL(fwnode_device_is_available);
|
||||
|
||||
/**
|
||||
* device_get_child_node_count - return the number of child nodes for device
|
||||
* @dev: Device to count the child nodes for
|
||||
* fwnode_get_child_node_count - return the number of child nodes for a given firmware node
|
||||
* @fwnode: Pointer to the parent firmware node
|
||||
*
|
||||
* Return: the number of child nodes for a given device.
|
||||
* Return: the number of child nodes for a given firmware node.
|
||||
*/
|
||||
unsigned int device_get_child_node_count(const struct device *dev)
|
||||
unsigned int fwnode_get_child_node_count(const struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct fwnode_handle *child;
|
||||
unsigned int count = 0;
|
||||
|
||||
device_for_each_child_node(dev, child)
|
||||
fwnode_for_each_child_node(fwnode, child)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_get_child_node_count);
|
||||
EXPORT_SYMBOL_GPL(fwnode_get_child_node_count);
|
||||
|
||||
bool device_dma_supported(const struct device *dev)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
CONFIG_KUNIT=y
|
||||
CONFIG_NEW_LEDS=y
|
||||
CONFIG_LEDS_CLASS=y
|
||||
CONFIG_LEDS_KUNIT_TEST=y
|
||||
@@ -55,6 +55,13 @@ config LEDS_BRIGHTNESS_HW_CHANGED
|
||||
|
||||
See Documentation/ABI/testing/sysfs-class-led for details.
|
||||
|
||||
config LEDS_KUNIT_TEST
|
||||
tristate "KUnit tests for LEDs"
|
||||
depends on KUNIT && LEDS_CLASS
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
Say Y here to enable KUnit testing for the LEDs framework.
|
||||
|
||||
comment "LED drivers"
|
||||
|
||||
config LEDS_88PM860X
|
||||
@@ -735,7 +742,7 @@ config LEDS_NS2
|
||||
tristate "LED support for Network Space v2 GPIO LEDs"
|
||||
depends on LEDS_CLASS
|
||||
depends on MACH_KIRKWOOD || MACH_ARMADA_370 || COMPILE_TEST
|
||||
default y
|
||||
default y if MACH_KIRKWOOD || MACH_ARMADA_370
|
||||
help
|
||||
This option enables support for the dual-GPIO LEDs found on the
|
||||
following LaCie/Seagate boards:
|
||||
@@ -750,7 +757,7 @@ config LEDS_NETXBIG
|
||||
depends on LEDS_CLASS
|
||||
depends on MACH_KIRKWOOD || COMPILE_TEST
|
||||
depends on OF_GPIO
|
||||
default y
|
||||
default MACH_KIRKWOOD
|
||||
help
|
||||
This option enables support for LEDs found on the LaCie 2Big
|
||||
and 5Big Network v2 boards. The LEDs are wired to a CPLD and are
|
||||
|
||||
@@ -6,6 +6,7 @@ obj-$(CONFIG_LEDS_CLASS) += led-class.o
|
||||
obj-$(CONFIG_LEDS_CLASS_FLASH) += led-class-flash.o
|
||||
obj-$(CONFIG_LEDS_CLASS_MULTICOLOR) += led-class-multicolor.o
|
||||
obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
|
||||
obj-$(CONFIG_LEDS_KUNIT_TEST) += led-test.o
|
||||
|
||||
# LED Platform Drivers (keep this sorted, M-| sort)
|
||||
obj-$(CONFIG_LEDS_88PM860X) += leds-88pm860x.o
|
||||
|
||||
@@ -450,7 +450,7 @@ static int sso_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
return !!(reg_val & BIT(offset));
|
||||
}
|
||||
|
||||
static void sso_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
|
||||
static int sso_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
|
||||
{
|
||||
struct sso_led_priv *priv = gpiochip_get_data(chip);
|
||||
|
||||
@@ -458,6 +458,8 @@ static void sso_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
|
||||
if (!priv->gpio.freq)
|
||||
regmap_update_bits(priv->mmap, SSO_CON0, SSO_CON0_SWU,
|
||||
SSO_CON0_SWU);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sso_gpio_gc_init(struct device *dev, struct sso_led_priv *priv)
|
||||
@@ -469,7 +471,7 @@ static int sso_gpio_gc_init(struct device *dev, struct sso_led_priv *priv)
|
||||
gc->get_direction = sso_gpio_get_dir;
|
||||
gc->direction_output = sso_gpio_dir_out;
|
||||
gc->get = sso_gpio_get;
|
||||
gc->set = sso_gpio_set;
|
||||
gc->set_rv = sso_gpio_set;
|
||||
|
||||
gc->label = "lgm-sso";
|
||||
gc->base = -1;
|
||||
|
||||
@@ -132,4 +132,15 @@ config LEDS_SY7802
|
||||
|
||||
This driver can be built as a module, it will be called "leds-sy7802".
|
||||
|
||||
config LEDS_TPS6131X
|
||||
tristate "LED support for TI TPS6131x flash LED driver"
|
||||
depends on I2C && OF
|
||||
depends on GPIOLIB
|
||||
select REGMAP_I2C
|
||||
help
|
||||
This option enables support for Texas Instruments TPS61310/TPS61311
|
||||
flash LED driver.
|
||||
|
||||
This driver can be built as a module, it will be called "leds-tps6131x".
|
||||
|
||||
endif # LEDS_CLASS_FLASH
|
||||
@@ -12,3 +12,4 @@ obj-$(CONFIG_LEDS_RT4505) += leds-rt4505.o
|
||||
obj-$(CONFIG_LEDS_RT8515) += leds-rt8515.o
|
||||
obj-$(CONFIG_LEDS_SGM3140) += leds-sgm3140.o
|
||||
obj-$(CONFIG_LEDS_SY7802) += leds-sy7802.o
|
||||
obj-$(CONFIG_LEDS_TPS6131X) += leds-tps6131x.o
|
||||
File diff suppressed because it is too large.
Load diff
@@ -440,6 +440,21 @@ int led_update_flash_brightness(struct led_classdev_flash *fled_cdev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(led_update_flash_brightness);
|
||||
|
||||
int led_set_flash_duration(struct led_classdev_flash *fled_cdev, u32 duration)
|
||||
{
|
||||
struct led_classdev *led_cdev = &fled_cdev->led_cdev;
|
||||
struct led_flash_setting *s = &fled_cdev->duration;
|
||||
|
||||
s->val = duration;
|
||||
led_clamp_align(s);
|
||||
|
||||
if (!(led_cdev->flags & LED_SUSPENDED))
|
||||
return call_flash_op(fled_cdev, duration_set, s->val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(led_set_flash_duration);
|
||||
|
||||
MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
|
||||
MODULE_DESCRIPTION("LED Flash class interface");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
@@ -59,7 +59,8 @@ static ssize_t multi_intensity_store(struct device *dev,
|
||||
for (i = 0; i < mcled_cdev->num_colors; i++)
|
||||
mcled_cdev->subled_info[i].intensity = intensity_value[i];
|
||||
|
||||
led_set_brightness(led_cdev, led_cdev->brightness);
|
||||
if (!test_bit(LED_BLINK_SW, &led_cdev->work_flags))
|
||||
led_set_brightness(led_cdev, led_cdev->brightness);
|
||||
ret = size;
|
||||
err_out:
|
||||
mutex_unlock(&led_cdev->led_access);
|
||||
|
||||
+25
-20
@@ -529,6 +529,7 @@ int led_compose_name(struct device *dev, struct led_init_data *init_data,
|
||||
struct led_properties props = {};
|
||||
struct fwnode_handle *fwnode = init_data->fwnode;
|
||||
const char *devicename = init_data->devicename;
|
||||
int n;
|
||||
|
||||
if (!led_classdev_name)
|
||||
return -EINVAL;
|
||||
@@ -542,45 +543,49 @@ int led_compose_name(struct device *dev, struct led_init_data *init_data,
|
||||
* Otherwise the label is prepended with devicename to compose
|
||||
* the final LED class device name.
|
||||
*/
|
||||
if (!devicename) {
|
||||
strscpy(led_classdev_name, props.label,
|
||||
LED_MAX_NAME_SIZE);
|
||||
if (devicename) {
|
||||
n = snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
|
||||
devicename, props.label);
|
||||
} else {
|
||||
snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
|
||||
devicename, props.label);
|
||||
n = snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s", props.label);
|
||||
}
|
||||
} else if (props.function || props.color_present) {
|
||||
char tmp_buf[LED_MAX_NAME_SIZE];
|
||||
|
||||
if (props.func_enum_present) {
|
||||
snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s-%d",
|
||||
props.color_present ? led_colors[props.color] : "",
|
||||
props.function ?: "", props.func_enum);
|
||||
n = snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s-%d",
|
||||
props.color_present ? led_colors[props.color] : "",
|
||||
props.function ?: "", props.func_enum);
|
||||
} else {
|
||||
snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s",
|
||||
props.color_present ? led_colors[props.color] : "",
|
||||
props.function ?: "");
|
||||
n = snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s",
|
||||
props.color_present ? led_colors[props.color] : "",
|
||||
props.function ?: "");
|
||||
}
|
||||
if (init_data->devname_mandatory) {
|
||||
snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
|
||||
devicename, tmp_buf);
|
||||
} else {
|
||||
strscpy(led_classdev_name, tmp_buf, LED_MAX_NAME_SIZE);
|
||||
if (n >= LED_MAX_NAME_SIZE)
|
||||
return -E2BIG;
|
||||
|
||||
if (init_data->devname_mandatory) {
|
||||
n = snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
|
||||
devicename, tmp_buf);
|
||||
} else {
|
||||
n = snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s", tmp_buf);
|
||||
}
|
||||
} else if (init_data->default_label) {
|
||||
if (!devicename) {
|
||||
dev_err(dev, "Legacy LED naming requires devicename segment");
|
||||
return -EINVAL;
|
||||
}
|
||||
snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
|
||||
devicename, init_data->default_label);
|
||||
n = snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
|
||||
devicename, init_data->default_label);
|
||||
} else if (is_of_node(fwnode)) {
|
||||
strscpy(led_classdev_name, to_of_node(fwnode)->name,
|
||||
LED_MAX_NAME_SIZE);
|
||||
n = snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s",
|
||||
to_of_node(fwnode)->name);
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
if (n >= LED_MAX_NAME_SIZE)
|
||||
return -E2BIG;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(led_compose_name);
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2025 Google LLC
|
||||
*
|
||||
* Author: Lee Jones <lee@kernel.org>
|
||||
*/
|
||||
|
||||
#include <kunit/device.h>
|
||||
#include <kunit/test.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/leds.h>
|
||||
|
||||
#define LED_TEST_POST_REG_BRIGHTNESS 10
|
||||
|
||||
struct led_test_ddata {
|
||||
struct led_classdev cdev;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
static enum led_brightness led_test_brightness_get(struct led_classdev *cdev)
|
||||
{
|
||||
return LED_TEST_POST_REG_BRIGHTNESS;
|
||||
}
|
||||
|
||||
static void led_test_class_register(struct kunit *test)
|
||||
{
|
||||
struct led_test_ddata *ddata = test->priv;
|
||||
struct led_classdev *cdev_clash, *cdev = &ddata->cdev;
|
||||
struct device *dev = ddata->dev;
|
||||
int ret;
|
||||
|
||||
/* Register a LED class device */
|
||||
cdev->name = "led-test";
|
||||
cdev->brightness_get = led_test_brightness_get;
|
||||
cdev->brightness = 0;
|
||||
|
||||
ret = devm_led_classdev_register(dev, cdev);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, cdev->max_brightness, LED_FULL);
|
||||
KUNIT_EXPECT_EQ(test, cdev->brightness, LED_TEST_POST_REG_BRIGHTNESS);
|
||||
KUNIT_EXPECT_STREQ(test, cdev->dev->kobj.name, "led-test");
|
||||
|
||||
/* Register again with the same name - expect it to pass with the LED renamed */
|
||||
cdev_clash = devm_kmemdup(dev, cdev, sizeof(*cdev), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cdev_clash);
|
||||
|
||||
ret = devm_led_classdev_register(dev, cdev_clash);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
KUNIT_EXPECT_STREQ(test, cdev_clash->dev->kobj.name, "led-test_1");
|
||||
KUNIT_EXPECT_STREQ(test, cdev_clash->name, "led-test");
|
||||
|
||||
/* Enable name conflict rejection and register with the same name again - expect failure */
|
||||
cdev_clash->flags |= LED_REJECT_NAME_CONFLICT;
|
||||
ret = devm_led_classdev_register(dev, cdev_clash);
|
||||
KUNIT_EXPECT_EQ(test, ret, -EEXIST);
|
||||
}
|
||||
|
||||
static void led_test_class_add_lookup_and_get(struct kunit *test)
|
||||
{
|
||||
struct led_test_ddata *ddata = test->priv;
|
||||
struct led_classdev *cdev = &ddata->cdev, *cdev_get;
|
||||
struct device *dev = ddata->dev;
|
||||
struct led_lookup_data lookup;
|
||||
int ret;
|
||||
|
||||
/* First, register a LED class device */
|
||||
cdev->name = "led-test";
|
||||
ret = devm_led_classdev_register(dev, cdev);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
/* Then make the LED available for lookup */
|
||||
lookup.provider = cdev->name;
|
||||
lookup.dev_id = dev_name(dev);
|
||||
lookup.con_id = "led-test-1";
|
||||
led_add_lookup(&lookup);
|
||||
|
||||
/* Finally, attempt to look it up via the API - imagine this was an orthogonal driver */
|
||||
cdev_get = devm_led_get(dev, "led-test-1");
|
||||
KUNIT_ASSERT_FALSE(test, IS_ERR(cdev_get));
|
||||
|
||||
KUNIT_EXPECT_STREQ(test, cdev_get->name, cdev->name);
|
||||
|
||||
led_remove_lookup(&lookup);
|
||||
}
|
||||
|
||||
static struct kunit_case led_test_cases[] = {
|
||||
KUNIT_CASE(led_test_class_register),
|
||||
KUNIT_CASE(led_test_class_add_lookup_and_get),
|
||||
{ }
|
||||
};
|
||||
|
||||
static int led_test_init(struct kunit *test)
|
||||
{
|
||||
struct led_test_ddata *ddata;
|
||||
struct device *dev;
|
||||
|
||||
ddata = kunit_kzalloc(test, sizeof(*ddata), GFP_KERNEL);
|
||||
if (!ddata)
|
||||
return -ENOMEM;
|
||||
|
||||
test->priv = ddata;
|
||||
|
||||
dev = kunit_device_register(test, "led_test");
|
||||
if (IS_ERR(dev))
|
||||
return PTR_ERR(dev);
|
||||
|
||||
ddata->dev = get_device(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void led_test_exit(struct kunit *test)
|
||||
{
|
||||
struct led_test_ddata *ddata = test->priv;
|
||||
|
||||
if (ddata && ddata->dev)
|
||||
put_device(ddata->dev);
|
||||
}
|
||||
|
||||
static struct kunit_suite led_test_suite = {
|
||||
.name = "led",
|
||||
.init = led_test_init,
|
||||
.exit = led_test_exit,
|
||||
.test_cases = led_test_cases,
|
||||
};
|
||||
kunit_test_suite(led_test_suite);
|
||||
|
||||
MODULE_AUTHOR("Lee Jones <lee@kernel.org>");
|
||||
MODULE_DESCRIPTION("KUnit tests for the LED framework");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -54,6 +54,11 @@ ssize_t led_trigger_write(struct file *filp, struct kobject *kobj,
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (sysfs_streq(buf, "default")) {
|
||||
led_trigger_set_default(led_cdev);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
down_read(&triggers_list_lock);
|
||||
list_for_each_entry(trig, &trigger_list, next_trig) {
|
||||
if (sysfs_streq(buf, trig->name) && trigger_relevant(led_cdev, trig)) {
|
||||
@@ -98,6 +103,9 @@ static int led_trigger_format(char *buf, size_t size,
|
||||
int len = led_trigger_snprintf(buf, size, "%s",
|
||||
led_cdev->trigger ? "none" : "[none]");
|
||||
|
||||
if (led_cdev->default_trigger)
|
||||
len += led_trigger_snprintf(buf + len, size - len, " default");
|
||||
|
||||
list_for_each_entry(trig, &trigger_list, next_trig) {
|
||||
bool hit;
|
||||
|
||||
@@ -281,6 +289,11 @@ void led_trigger_set_default(struct led_classdev *led_cdev)
|
||||
if (!led_cdev->default_trigger)
|
||||
return;
|
||||
|
||||
if (!strcmp(led_cdev->default_trigger, "none")) {
|
||||
led_trigger_remove(led_cdev);
|
||||
return;
|
||||
}
|
||||
|
||||
down_read(&triggers_list_lock);
|
||||
down_write(&led_cdev->trigger_lock);
|
||||
list_for_each_entry(trig, &trigger_list, next_trig) {
|
||||
|
||||
@@ -60,31 +60,18 @@ static inline struct cros_ec_led_priv *cros_ec_led_cdev_to_priv(struct led_class
|
||||
union cros_ec_led_cmd_data {
|
||||
struct ec_params_led_control req;
|
||||
struct ec_response_led_control resp;
|
||||
} __packed;
|
||||
};
|
||||
|
||||
static int cros_ec_led_send_cmd(struct cros_ec_device *cros_ec,
|
||||
union cros_ec_led_cmd_data *arg)
|
||||
{
|
||||
int ret;
|
||||
struct {
|
||||
struct cros_ec_command msg;
|
||||
union cros_ec_led_cmd_data data;
|
||||
} __packed buf = {
|
||||
.msg = {
|
||||
.version = 1,
|
||||
.command = EC_CMD_LED_CONTROL,
|
||||
.insize = sizeof(arg->resp),
|
||||
.outsize = sizeof(arg->req),
|
||||
},
|
||||
.data.req = arg->req
|
||||
};
|
||||
|
||||
ret = cros_ec_cmd_xfer_status(cros_ec, &buf.msg);
|
||||
ret = cros_ec_cmd(cros_ec, 1, EC_CMD_LED_CONTROL, &arg->req,
|
||||
sizeof(arg->req), &arg->resp, sizeof(arg->resp));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
arg->resp = buf.data.resp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+48
-162
@@ -90,8 +90,6 @@
|
||||
* @led_dev: led class device pointer
|
||||
* @regmap: Devices register map
|
||||
* @eeprom_regmap: EEPROM register map
|
||||
* @enable_gpio: VDDIO/EN gpio to enable communication interface
|
||||
* @regulator: LED supply regulator pointer
|
||||
*/
|
||||
struct lp8860_led {
|
||||
struct mutex lock;
|
||||
@@ -99,16 +97,9 @@ struct lp8860_led {
|
||||
struct led_classdev led_dev;
|
||||
struct regmap *regmap;
|
||||
struct regmap *eeprom_regmap;
|
||||
struct gpio_desc *enable_gpio;
|
||||
struct regulator *regulator;
|
||||
};
|
||||
|
||||
struct lp8860_eeprom_reg {
|
||||
uint8_t reg;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
static struct lp8860_eeprom_reg lp8860_eeprom_disp_regs[] = {
|
||||
static const struct reg_sequence lp8860_eeprom_disp_regs[] = {
|
||||
{ LP8860_EEPROM_REG_0, 0xed },
|
||||
{ LP8860_EEPROM_REG_1, 0xdf },
|
||||
{ LP8860_EEPROM_REG_2, 0xdc },
|
||||
@@ -136,43 +127,29 @@ static struct lp8860_eeprom_reg lp8860_eeprom_disp_regs[] = {
|
||||
{ LP8860_EEPROM_REG_24, 0x3E },
|
||||
};
|
||||
|
||||
static int lp8860_unlock_eeprom(struct lp8860_led *led, int lock)
|
||||
static int lp8860_unlock_eeprom(struct lp8860_led *led)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&led->lock);
|
||||
guard(mutex)(&led->lock);
|
||||
|
||||
if (lock == LP8860_UNLOCK_EEPROM) {
|
||||
ret = regmap_write(led->regmap,
|
||||
LP8860_EEPROM_UNLOCK,
|
||||
LP8860_EEPROM_CODE_1);
|
||||
if (ret) {
|
||||
dev_err(&led->client->dev, "EEPROM Unlock failed\n");
|
||||
goto out;
|
||||
}
|
||||
ret = regmap_write(led->regmap, LP8860_EEPROM_UNLOCK, LP8860_EEPROM_CODE_1);
|
||||
if (ret) {
|
||||
dev_err(&led->client->dev, "EEPROM Unlock failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(led->regmap,
|
||||
LP8860_EEPROM_UNLOCK,
|
||||
LP8860_EEPROM_CODE_2);
|
||||
if (ret) {
|
||||
dev_err(&led->client->dev, "EEPROM Unlock failed\n");
|
||||
goto out;
|
||||
}
|
||||
ret = regmap_write(led->regmap,
|
||||
LP8860_EEPROM_UNLOCK,
|
||||
LP8860_EEPROM_CODE_3);
|
||||
if (ret) {
|
||||
dev_err(&led->client->dev, "EEPROM Unlock failed\n");
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
ret = regmap_write(led->regmap,
|
||||
LP8860_EEPROM_UNLOCK,
|
||||
LP8860_LOCK_EEPROM);
|
||||
ret = regmap_write(led->regmap, LP8860_EEPROM_UNLOCK, LP8860_EEPROM_CODE_2);
|
||||
if (ret) {
|
||||
dev_err(&led->client->dev, "EEPROM Unlock failed\n");
|
||||
return ret;
|
||||
}
|
||||
ret = regmap_write(led->regmap, LP8860_EEPROM_UNLOCK, LP8860_EEPROM_CODE_3);
|
||||
if (ret) {
|
||||
dev_err(&led->client->dev, "EEPROM Unlock failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&led->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -209,47 +186,35 @@ static int lp8860_brightness_set(struct led_classdev *led_cdev,
|
||||
int disp_brightness = brt_val * 255;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&led->lock);
|
||||
guard(mutex)(&led->lock);
|
||||
|
||||
ret = lp8860_fault_check(led);
|
||||
if (ret) {
|
||||
dev_err(&led->client->dev, "Cannot read/clear faults\n");
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(led->regmap, LP8860_DISP_CL1_BRT_MSB,
|
||||
(disp_brightness & 0xff00) >> 8);
|
||||
if (ret) {
|
||||
dev_err(&led->client->dev, "Cannot write CL1 MSB\n");
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(led->regmap, LP8860_DISP_CL1_BRT_LSB,
|
||||
disp_brightness & 0xff);
|
||||
if (ret) {
|
||||
dev_err(&led->client->dev, "Cannot write CL1 LSB\n");
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&led->lock);
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lp8860_init(struct lp8860_led *led)
|
||||
{
|
||||
unsigned int read_buf;
|
||||
int ret, i, reg_count;
|
||||
|
||||
if (led->regulator) {
|
||||
ret = regulator_enable(led->regulator);
|
||||
if (ret) {
|
||||
dev_err(&led->client->dev,
|
||||
"Failed to enable regulator\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
gpiod_direction_output(led->enable_gpio, 1);
|
||||
int ret, reg_count;
|
||||
|
||||
ret = lp8860_fault_check(led);
|
||||
if (ret)
|
||||
@@ -259,24 +224,20 @@ static int lp8860_init(struct lp8860_led *led)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = lp8860_unlock_eeprom(led, LP8860_UNLOCK_EEPROM);
|
||||
ret = lp8860_unlock_eeprom(led);
|
||||
if (ret) {
|
||||
dev_err(&led->client->dev, "Failed unlocking EEPROM\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
reg_count = ARRAY_SIZE(lp8860_eeprom_disp_regs);
|
||||
for (i = 0; i < reg_count; i++) {
|
||||
ret = regmap_write(led->eeprom_regmap,
|
||||
lp8860_eeprom_disp_regs[i].reg,
|
||||
lp8860_eeprom_disp_regs[i].value);
|
||||
if (ret) {
|
||||
dev_err(&led->client->dev, "Failed writing EEPROM\n");
|
||||
goto out;
|
||||
}
|
||||
ret = regmap_multi_reg_write(led->eeprom_regmap, lp8860_eeprom_disp_regs, reg_count);
|
||||
if (ret) {
|
||||
dev_err(&led->client->dev, "Failed writing EEPROM\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = lp8860_unlock_eeprom(led, LP8860_LOCK_EEPROM);
|
||||
ret = regmap_write(led->regmap, LP8860_EEPROM_UNLOCK, LP8860_LOCK_EEPROM);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -291,74 +252,14 @@ static int lp8860_init(struct lp8860_led *led)
|
||||
return ret;
|
||||
|
||||
out:
|
||||
if (ret)
|
||||
gpiod_direction_output(led->enable_gpio, 0);
|
||||
|
||||
if (led->regulator) {
|
||||
ret = regulator_disable(led->regulator);
|
||||
if (ret)
|
||||
dev_err(&led->client->dev,
|
||||
"Failed to disable regulator\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct reg_default lp8860_reg_defs[] = {
|
||||
{ LP8860_DISP_CL1_BRT_MSB, 0x00},
|
||||
{ LP8860_DISP_CL1_BRT_LSB, 0x00},
|
||||
{ LP8860_DISP_CL1_CURR_MSB, 0x00},
|
||||
{ LP8860_DISP_CL1_CURR_LSB, 0x00},
|
||||
{ LP8860_CL2_BRT_MSB, 0x00},
|
||||
{ LP8860_CL2_BRT_LSB, 0x00},
|
||||
{ LP8860_CL2_CURRENT, 0x00},
|
||||
{ LP8860_CL3_BRT_MSB, 0x00},
|
||||
{ LP8860_CL3_BRT_LSB, 0x00},
|
||||
{ LP8860_CL3_CURRENT, 0x00},
|
||||
{ LP8860_CL4_BRT_MSB, 0x00},
|
||||
{ LP8860_CL4_BRT_LSB, 0x00},
|
||||
{ LP8860_CL4_CURRENT, 0x00},
|
||||
{ LP8860_CONFIG, 0x00},
|
||||
{ LP8860_FAULT_CLEAR, 0x00},
|
||||
{ LP8860_EEPROM_CNTRL, 0x80},
|
||||
{ LP8860_EEPROM_UNLOCK, 0x00},
|
||||
};
|
||||
|
||||
static const struct regmap_config lp8860_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
.max_register = LP8860_EEPROM_UNLOCK,
|
||||
.reg_defaults = lp8860_reg_defs,
|
||||
.num_reg_defaults = ARRAY_SIZE(lp8860_reg_defs),
|
||||
};
|
||||
|
||||
static const struct reg_default lp8860_eeprom_defs[] = {
|
||||
{ LP8860_EEPROM_REG_0, 0x00 },
|
||||
{ LP8860_EEPROM_REG_1, 0x00 },
|
||||
{ LP8860_EEPROM_REG_2, 0x00 },
|
||||
{ LP8860_EEPROM_REG_3, 0x00 },
|
||||
{ LP8860_EEPROM_REG_4, 0x00 },
|
||||
{ LP8860_EEPROM_REG_5, 0x00 },
|
||||
{ LP8860_EEPROM_REG_6, 0x00 },
|
||||
{ LP8860_EEPROM_REG_7, 0x00 },
|
||||
{ LP8860_EEPROM_REG_8, 0x00 },
|
||||
{ LP8860_EEPROM_REG_9, 0x00 },
|
||||
{ LP8860_EEPROM_REG_10, 0x00 },
|
||||
{ LP8860_EEPROM_REG_11, 0x00 },
|
||||
{ LP8860_EEPROM_REG_12, 0x00 },
|
||||
{ LP8860_EEPROM_REG_13, 0x00 },
|
||||
{ LP8860_EEPROM_REG_14, 0x00 },
|
||||
{ LP8860_EEPROM_REG_15, 0x00 },
|
||||
{ LP8860_EEPROM_REG_16, 0x00 },
|
||||
{ LP8860_EEPROM_REG_17, 0x00 },
|
||||
{ LP8860_EEPROM_REG_18, 0x00 },
|
||||
{ LP8860_EEPROM_REG_19, 0x00 },
|
||||
{ LP8860_EEPROM_REG_20, 0x00 },
|
||||
{ LP8860_EEPROM_REG_21, 0x00 },
|
||||
{ LP8860_EEPROM_REG_22, 0x00 },
|
||||
{ LP8860_EEPROM_REG_23, 0x00 },
|
||||
{ LP8860_EEPROM_REG_24, 0x00 },
|
||||
};
|
||||
|
||||
static const struct regmap_config lp8860_eeprom_regmap_config = {
|
||||
@@ -366,10 +267,15 @@ static const struct regmap_config lp8860_eeprom_regmap_config = {
|
||||
.val_bits = 8,
|
||||
|
||||
.max_register = LP8860_EEPROM_REG_24,
|
||||
.reg_defaults = lp8860_eeprom_defs,
|
||||
.num_reg_defaults = ARRAY_SIZE(lp8860_eeprom_defs),
|
||||
};
|
||||
|
||||
static void lp8860_disable_gpio(void *data)
|
||||
{
|
||||
struct gpio_desc *gpio = data;
|
||||
|
||||
gpiod_set_value(gpio, 0);
|
||||
}
|
||||
|
||||
static int lp8860_probe(struct i2c_client *client)
|
||||
{
|
||||
int ret;
|
||||
@@ -377,6 +283,7 @@ static int lp8860_probe(struct i2c_client *client)
|
||||
struct device_node *np = dev_of_node(&client->dev);
|
||||
struct device_node *child_node;
|
||||
struct led_init_data init_data = {};
|
||||
struct gpio_desc *enable_gpio;
|
||||
|
||||
led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL);
|
||||
if (!led)
|
||||
@@ -386,24 +293,21 @@ static int lp8860_probe(struct i2c_client *client)
|
||||
if (!child_node)
|
||||
return -EINVAL;
|
||||
|
||||
led->enable_gpio = devm_gpiod_get_optional(&client->dev,
|
||||
"enable", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(led->enable_gpio)) {
|
||||
ret = PTR_ERR(led->enable_gpio);
|
||||
dev_err(&client->dev, "Failed to get enable gpio: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(enable_gpio))
|
||||
return dev_err_probe(&client->dev, PTR_ERR(enable_gpio),
|
||||
"Failed to get enable GPIO\n");
|
||||
devm_add_action_or_reset(&client->dev, lp8860_disable_gpio, enable_gpio);
|
||||
|
||||
led->regulator = devm_regulator_get(&client->dev, "vled");
|
||||
if (IS_ERR(led->regulator))
|
||||
led->regulator = NULL;
|
||||
ret = devm_regulator_get_enable_optional(&client->dev, "vled");
|
||||
if (ret && ret != -ENODEV)
|
||||
return dev_err_probe(&client->dev, ret,
|
||||
"Failed to enable vled regulator\n");
|
||||
|
||||
led->client = client;
|
||||
led->led_dev.brightness_set_blocking = lp8860_brightness_set;
|
||||
|
||||
mutex_init(&led->lock);
|
||||
|
||||
i2c_set_clientdata(client, led);
|
||||
devm_mutex_init(&client->dev, &led->lock);
|
||||
|
||||
led->regmap = devm_regmap_init_i2c(client, &lp8860_regmap_config);
|
||||
if (IS_ERR(led->regmap)) {
|
||||
@@ -439,23 +343,6 @@ static int lp8860_probe(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lp8860_remove(struct i2c_client *client)
|
||||
{
|
||||
struct lp8860_led *led = i2c_get_clientdata(client);
|
||||
int ret;
|
||||
|
||||
gpiod_direction_output(led->enable_gpio, 0);
|
||||
|
||||
if (led->regulator) {
|
||||
ret = regulator_disable(led->regulator);
|
||||
if (ret)
|
||||
dev_err(&led->client->dev,
|
||||
"Failed to disable regulator\n");
|
||||
}
|
||||
|
||||
mutex_destroy(&led->lock);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id lp8860_id[] = {
|
||||
{ "lp8860" },
|
||||
{ }
|
||||
@@ -474,7 +361,6 @@ static struct i2c_driver lp8860_driver = {
|
||||
.of_match_table = of_lp8860_leds_match,
|
||||
},
|
||||
.probe = lp8860_probe,
|
||||
.remove = lp8860_remove,
|
||||
.id_table = lp8860_id,
|
||||
};
|
||||
module_i2c_driver(lp8860_driver);
|
||||
|
||||
@@ -318,7 +318,8 @@ static int pca9532_gpio_request_pin(struct gpio_chip *gc, unsigned offset)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
static void pca9532_gpio_set_value(struct gpio_chip *gc, unsigned offset, int val)
|
||||
static int pca9532_gpio_set_value(struct gpio_chip *gc, unsigned int offset,
|
||||
int val)
|
||||
{
|
||||
struct pca9532_data *data = gpiochip_get_data(gc);
|
||||
struct pca9532_led *led = &data->leds[offset];
|
||||
@@ -329,6 +330,8 @@ static void pca9532_gpio_set_value(struct gpio_chip *gc, unsigned offset, int va
|
||||
led->state = PCA9532_OFF;
|
||||
|
||||
pca9532_setled(led);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pca9532_gpio_get_value(struct gpio_chip *gc, unsigned offset)
|
||||
@@ -351,9 +354,7 @@ static int pca9532_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
|
||||
|
||||
static int pca9532_gpio_direction_output(struct gpio_chip *gc, unsigned offset, int val)
|
||||
{
|
||||
pca9532_gpio_set_value(gc, offset, val);
|
||||
|
||||
return 0;
|
||||
return pca9532_gpio_set_value(gc, offset, val);
|
||||
}
|
||||
#endif /* CONFIG_LEDS_PCA9532_GPIO */
|
||||
|
||||
@@ -472,7 +473,7 @@ static int pca9532_configure(struct i2c_client *client,
|
||||
data->gpio.label = "gpio-pca9532";
|
||||
data->gpio.direction_input = pca9532_gpio_direction_input;
|
||||
data->gpio.direction_output = pca9532_gpio_direction_output;
|
||||
data->gpio.set = pca9532_gpio_set_value;
|
||||
data->gpio.set_rv = pca9532_gpio_set_value;
|
||||
data->gpio.get = pca9532_gpio_get_value;
|
||||
data->gpio.request = pca9532_gpio_request_pin;
|
||||
data->gpio.can_sleep = 1;
|
||||
|
||||
Loaded 20 of 30 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user