diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-07-17 17:48:40 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-07-17 17:48:40 -0700 |
| commit | e0d97b04eceb637a476a2d0233bc7721611a9cb2 (patch) | |
| tree | 8ba1e373e0cae434e9a95c32bc89a65fb35348aa | |
| parent | 1200af3ac16489d9f0b86000362a044ed7521cf6 (diff) | |
| parent | 1df5aa3754cac2045998ca505edb84d994786c67 (diff) | |
Merge tag 'backlight-next-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight
Pull backlight updates from Lee Jones:
"New Drivers:
- Texas Instruments LM3509 Backlight Driver
Fix-ups:
- Device Tree binding adaptions/conversions/creation
- Drop i2c_device_id::driver_data where the value is unused
- Make use of the new *_scoped() guard APIs
- Decouple from fbdev by providing Backlight with its own
BACKLIGHT_POWER_* constrains
Bug Fixes:
- Correctly assess return values (NULL vs IS_ERR())
- Supply a bunch of MODULE_DESCRIPTIONs to silence modpost warnings"
* tag 'backlight-next-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight: (23 commits)
backlight: sky81452-backlight: Use backlight power constants
backlight: rave-sp-backlight: Use backlight power constants
backlight: pwm-backlight: Use backlight power constants
backlight: pcf50633-backlight: Use backlight power constants
backlight: pandora-backlight: Use backlight power constants
backlight: mp3309c: Use backlight power constants
backlight: lm3533-backlight: Use backlight power constants
backlight: led-backlight: Use backlight power constants
backlight: ktd253-backlight: Use backlight power constants
backlight: kb3886-bl: Use backlight power constants
backlight: journada_bl: Use backlight power constants
backlight: ipaq-micro-backlight: Use backlight power constants
backlight: gpio-backlight: Use backlight power constants
backlight: corgi-lcd: Use backlight power constants
backlight: ams369fb06: Use backlight power constants
backlight: aat2870-backlight: Use blacklight power constants
backlight: Add BACKLIGHT_POWER_ constants for power states
backlight: lm3509_bl: Fix early returns in for_each_child_of_node()
backlight: Drop explicit initialization of struct i2c_device_id::driver_data to 0
backlight: Add missing MODULE_DESCRIPTION() macros
...
30 files changed, 550 insertions, 64 deletions
diff --git a/Documentation/ABI/stable/sysfs-class-backlight b/Documentation/ABI/stable/sysfs-class-backlight index 023fb52645f8..6102d6bebdf9 100644 --- a/Documentation/ABI/stable/sysfs-class-backlight +++ b/Documentation/ABI/stable/sysfs-class-backlight @@ -3,10 +3,11 @@ Date: April 2005 KernelVersion: 2.6.12 Contact: Richard Purdie <rpurdie@rpsys.net> Description: - Control BACKLIGHT power, values are FB_BLANK_* from fb.h + Control BACKLIGHT power, values are compatible with + FB_BLANK_* from fb.h - - FB_BLANK_UNBLANK (0) : power on. - - FB_BLANK_POWERDOWN (4) : power off + - 0 (FB_BLANK_UNBLANK) : power on. + - 4 (FB_BLANK_POWERDOWN) : power off Users: HAL What: /sys/class/backlight/<backlight>/brightness diff --git a/Documentation/devicetree/bindings/leds/backlight/ti,lm3509.yaml b/Documentation/devicetree/bindings/leds/backlight/ti,lm3509.yaml new file mode 100644 index 000000000000..482fae71dd53 --- /dev/null +++ b/Documentation/devicetree/bindings/leds/backlight/ti,lm3509.yaml @@ -0,0 +1,136 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/backlight/ti,lm3509.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI LM3509 High Efficiency Boost for White LED's and/or OLED Displays + +maintainers: + - Patrick Gansterer <paroga@paroga.com> + +description: + The LM3509 current mode boost converter offers two separate outputs. + https://www.ti.com/product/LM3509 + +properties: + compatible: + const: ti,lm3509 + + reg: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + reset-gpios: + maxItems: 1 + + ti,brightness-rate-of-change-us: + description: Brightness Rate of Change in microseconds. + enum: [51, 13000, 26000, 52000] + + ti,oled-mode: + description: Enable OLED mode. + type: boolean + +patternProperties: + "^led@[01]$": + type: object + description: Properties for a string of connected LEDs. + $ref: common.yaml# + + properties: + reg: + description: + The control register that is used to program the two current sinks. + The LM3509 has two registers (BMAIN and BSUB) and are represented + as 0 or 1 in this property. The two current sinks can be controlled + independently with both registers, or register BMAIN can be + configured to control both sinks with the led-sources property. + minimum: 0 + maximum: 1 + + label: true + + led-sources: + minItems: 1 + maxItems: 2 + items: + minimum: 0 + maximum: 1 + + default-brightness: + minimum: 0 + maximum: 31 + default: 18 + + max-brightness: + minimum: 0 + maximum: 31 + default: 31 + + required: + - reg + + additionalProperties: false + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + i2c { + #address-cells = <1>; + #size-cells = <0>; + + backlight@36 { + compatible = "ti,lm3509"; + reg = <0x36>; + reset-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; + + ti,oled-mode; + ti,brightness-rate-of-change-us = <52000>; + + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + led-sources = <0 1>; + label = "lcd-backlight"; + default-brightness = <12>; + max-brightness = <31>; + }; + }; + }; + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + backlight@36 { + compatible = "ti,lm3509"; + reg = <0x36>; + + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + default-brightness = <12>; + }; + + led@1 { + reg = <1>; + default-brightness = <15>; + }; + }; + }; diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 230bca07b09d..3614a5d29c71 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -373,6 +373,13 @@ config BACKLIGHT_AAT2870 If you have a AnalogicTech AAT2870 say Y to enable the backlight driver. +config BACKLIGHT_LM3509 + tristate "Backlight Driver for LM3509" + depends on I2C + select REGMAP_I2C + help + This supports TI LM3509 Backlight Driver + config BACKLIGHT_LM3630A tristate "Backlight Driver for LM3630A" depends on I2C && PWM diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 8d2cb252042d..8fc98f760a8a 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_BACKLIGHT_IPAQ_MICRO) += ipaq_micro_bl.o obj-$(CONFIG_BACKLIGHT_KTD253) += ktd253-backlight.o obj-$(CONFIG_BACKLIGHT_KTD2801) += ktd2801-backlight.o obj-$(CONFIG_BACKLIGHT_KTZ8866) += ktz8866.o +obj-$(CONFIG_BACKLIGHT_LM3509) += lm3509_bl.o obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o obj-$(CONFIG_BACKLIGHT_LM3630A) += lm3630a_bl.o obj-$(CONFIG_BACKLIGHT_LM3639) += lm3639_bl.o diff --git a/drivers/video/backlight/aat2870_bl.c b/drivers/video/backlight/aat2870_bl.c index b4c3354a1a8a..68d327ee4b2e 100644 --- a/drivers/video/backlight/aat2870_bl.c +++ b/drivers/video/backlight/aat2870_bl.c @@ -156,7 +156,7 @@ static int aat2870_bl_probe(struct platform_device *pdev) bd->props.max_brightness = 255; aat2870_bl->brightness = 0; - bd->props.power = FB_BLANK_UNBLANK; + bd->props.power = BACKLIGHT_POWER_ON; bd->props.brightness = bd->props.max_brightness; ret = aat2870_bl_update_status(bd); @@ -176,7 +176,7 @@ static void aat2870_bl_remove(struct platform_device *pdev) struct aat2870_bl_driver_data *aat2870_bl = platform_get_drvdata(pdev); struct backlight_device *bd = aat2870_bl->bd; - bd->props.power = FB_BLANK_POWERDOWN; + bd->props.power = BACKLIGHT_POWER_OFF; bd->props.brightness = 0; backlight_update_status(bd); } diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index 6bb18dc970e9..ad4bd4c8f441 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c @@ -963,7 +963,7 @@ static SIMPLE_DEV_PM_OPS(adp8870_i2c_pm_ops, adp8870_i2c_suspend, adp8870_i2c_resume); static const struct i2c_device_id adp8870_id[] = { - { "adp8870", 0 }, + { "adp8870" }, { } }; MODULE_DEVICE_TABLE(i2c, adp8870_id); diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c index 57ec205d2bd2..f8442689ac43 100644 --- a/drivers/video/backlight/ams369fg06.c +++ b/drivers/video/backlight/ams369fg06.c @@ -10,7 +10,6 @@ #include <linux/backlight.h> #include <linux/delay.h> -#include <linux/fb.h> #include <linux/lcd.h> #include <linux/module.h> #include <linux/spi/spi.h> @@ -300,7 +299,7 @@ static int ams369fg06_ldi_disable(struct ams369fg06 *lcd) static int ams369fg06_power_is_on(int power) { - return power <= FB_BLANK_NORMAL; + return power <= BACKLIGHT_POWER_REDUCED; } static int ams369fg06_power_on(struct ams369fg06 *lcd) @@ -396,8 +395,8 @@ static int ams369fg06_set_power(struct lcd_device *ld, int power) { struct ams369fg06 *lcd = lcd_get_data(ld); - if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && - power != FB_BLANK_NORMAL) { + if (power != BACKLIGHT_POWER_ON && power != BACKLIGHT_POWER_OFF && + power != BACKLIGHT_POWER_REDUCED) { dev_err(lcd->dev, "power value should be 0, 1 or 4.\n"); return -EINVAL; } @@ -492,11 +491,11 @@ static int ams369fg06_probe(struct spi_device *spi) * current lcd status is powerdown and then * it enables lcd panel. */ - lcd->power = FB_BLANK_POWERDOWN; + lcd->power = BACKLIGHT_POWER_OFF; - ams369fg06_power(lcd, FB_BLANK_UNBLANK); + ams369fg06_power(lcd, BACKLIGHT_POWER_ON); } else { - lcd->power = FB_BLANK_UNBLANK; + lcd->power = BACKLIGHT_POWER_ON; } spi_set_drvdata(spi, lcd); @@ -510,7 +509,7 @@ static void ams369fg06_remove(struct spi_device *spi) { struct ams369fg06 *lcd = spi_get_drvdata(spi); - ams369fg06_power(lcd, FB_BLANK_POWERDOWN); + ams369fg06_power(lcd, BACKLIGHT_POWER_OFF); } #ifdef CONFIG_PM_SLEEP @@ -524,16 +523,16 @@ static int ams369fg06_suspend(struct device *dev) * when lcd panel is suspend, lcd panel becomes off * regardless of status. */ - return ams369fg06_power(lcd, FB_BLANK_POWERDOWN); + return ams369fg06_power(lcd, BACKLIGHT_POWER_OFF); } static int ams369fg06_resume(struct device *dev) { struct ams369fg06 *lcd = dev_get_drvdata(dev); - lcd->power = FB_BLANK_POWERDOWN; + lcd->power = BACKLIGHT_POWER_OFF; - return ams369fg06_power(lcd, FB_BLANK_UNBLANK); + return ams369fg06_power(lcd, BACKLIGHT_POWER_ON); } #endif @@ -544,7 +543,7 @@ static void ams369fg06_shutdown(struct spi_device *spi) { struct ams369fg06 *lcd = spi_get_drvdata(spi); - ams369fg06_power(lcd, FB_BLANK_POWERDOWN); + ams369fg06_power(lcd, BACKLIGHT_POWER_OFF); } static struct spi_driver ams369fg06_driver = { diff --git a/drivers/video/backlight/bd6107.c b/drivers/video/backlight/bd6107.c index 6be2c67ba85c..90764f83d2f1 100644 --- a/drivers/video/backlight/bd6107.c +++ b/drivers/video/backlight/bd6107.c @@ -180,7 +180,7 @@ static void bd6107_remove(struct i2c_client *client) } static const struct i2c_device_id bd6107_ids[] = { - { "bd6107", 0 }, + { "bd6107" }, { } }; MODULE_DEVICE_TABLE(i2c, bd6107_ids); diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index aad1680c9075..e4fcfbe38dc6 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c @@ -526,7 +526,7 @@ static int corgi_lcd_probe(struct spi_device *spi) return PTR_ERR(lcd->bl_dev); lcd->bl_dev->props.brightness = pdata->default_intensity; - lcd->bl_dev->props.power = FB_BLANK_UNBLANK; + lcd->bl_dev->props.power = BACKLIGHT_POWER_ON; ret = setup_gpio_backlight(lcd, pdata); if (ret) @@ -547,7 +547,7 @@ static void corgi_lcd_remove(struct spi_device *spi) { struct corgi_lcd *lcd = spi_get_drvdata(spi); - lcd->bl_dev->props.power = FB_BLANK_UNBLANK; + lcd->bl_dev->props.power = BACKLIGHT_POWER_ON; lcd->bl_dev->props.brightness = 0; backlight_update_status(lcd->bl_dev); corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN); diff --git a/drivers/video/backlight/gpio_backlight.c b/drivers/video/backlight/gpio_backlight.c index 4476c317ce29..728a546904b0 100644 --- a/drivers/video/backlight/gpio_backlight.c +++ b/drivers/video/backlight/gpio_backlight.c @@ -5,7 +5,6 @@ #include <linux/backlight.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/gpio/consumer.h> #include <linux/init.h> #include <linux/kernel.h> @@ -81,12 +80,12 @@ static int gpio_backlight_probe(struct platform_device *pdev) /* Set the initial power state */ if (!of_node || !of_node->phandle) /* Not booted with device tree or no phandle link to the node */ - bl->props.power = def_value ? FB_BLANK_UNBLANK - : FB_BLANK_POWERDOWN; + bl->props.power = def_value ? BACKLIGHT_POWER_ON + : BACKLIGHT_POWER_OFF; else if (gpiod_get_value_cansleep(gbl->gpiod) == 0) - bl->props.power = FB_BLANK_POWERDOWN; + bl->props.power = BACKLIGHT_POWER_OFF; else - bl->props.power = FB_BLANK_UNBLANK; + bl->props.power = BACKLIGHT_POWER_ON; bl->props.brightness = 1; diff --git a/drivers/video/backlight/ipaq_micro_bl.c b/drivers/video/backlight/ipaq_micro_bl.c index f595b8c8cbb2..19ff66e444bc 100644 --- a/drivers/video/backlight/ipaq_micro_bl.c +++ b/drivers/video/backlight/ipaq_micro_bl.c @@ -7,7 +7,6 @@ #include <linux/backlight.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/init.h> #include <linux/mfd/ipaq-micro.h> #include <linux/module.h> @@ -42,7 +41,7 @@ static const struct backlight_ops micro_bl_ops = { static const struct backlight_properties micro_bl_props = { .type = BACKLIGHT_RAW, .max_brightness = 255, - .power = FB_BLANK_UNBLANK, + .power = BACKLIGHT_POWER_ON, .brightness = 64, }; diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c index 066d0dc98f60..e28d2c071798 100644 --- a/drivers/video/backlight/jornada720_bl.c +++ b/drivers/video/backlight/jornada720_bl.c @@ -7,7 +7,6 @@ #include <linux/backlight.h> #include <linux/device.h> -#include <linux/fb.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -121,7 +120,7 @@ static int jornada_bl_probe(struct platform_device *pdev) return ret; } - bd->props.power = FB_BLANK_UNBLANK; + bd->props.power = BACKLIGHT_POWER_ON; bd->props.brightness = BL_DEF_BRIGHT; /* * note. make sure max brightness is set otherwise diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c index 55794b239cff..050b5c21f4a8 100644 --- a/drivers/video/backlight/kb3886_bl.c +++ b/drivers/video/backlight/kb3886_bl.c @@ -10,9 +10,9 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> +#include <linux/io.h> #include <linux/platform_device.h> #include <linux/mutex.h> -#include <linux/fb.h> #include <linux/backlight.h> #include <linux/delay.h> #include <linux/dmi.h> @@ -151,7 +151,7 @@ static int kb3886bl_probe(struct platform_device *pdev) platform_set_drvdata(pdev, kb3886_backlight_device); - kb3886_backlight_device->props.power = FB_BLANK_UNBLANK; + kb3886_backlight_device->props.power = BACKLIGHT_POWER_ON; kb3886_backlight_device->props.brightness = machinfo->default_intensity; backlight_update_status(kb3886_backlight_device); diff --git a/drivers/video/backlight/ktd253-backlight.c b/drivers/video/backlight/ktd253-backlight.c index d7d43454f64a..327b4ee75254 100644 --- a/drivers/video/backlight/ktd253-backlight.c +++ b/drivers/video/backlight/ktd253-backlight.c @@ -7,7 +7,6 @@ #include <linux/backlight.h> #include <linux/delay.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/gpio/consumer.h> #include <linux/init.h> #include <linux/kernel.h> @@ -190,10 +189,10 @@ static int ktd253_backlight_probe(struct platform_device *pdev) /* When we just enable the GPIO line we set max brightness */ if (brightness) { bl->props.brightness = brightness; - bl->props.power = FB_BLANK_UNBLANK; + bl->props.power = BACKLIGHT_POWER_ON; } else { bl->props.brightness = 0; - bl->props.power = FB_BLANK_POWERDOWN; + bl->props.power = BACKLIGHT_POWER_OFF; } ktd253->bl = bl; diff --git a/drivers/video/backlight/ktz8866.c b/drivers/video/backlight/ktz8866.c index 014877b5a984..2e508741c0af 100644 --- a/drivers/video/backlight/ktz8866.c +++ b/drivers/video/backlight/ktz8866.c @@ -179,8 +179,8 @@ static void ktz8866_remove(struct i2c_client *client) } static const struct i2c_device_id ktz8866_ids[] = { - { "ktz8866", 0 }, - {}, + { "ktz8866" }, + {} }; MODULE_DEVICE_TABLE(i2c, ktz8866_ids); diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c index 032f8bddf872..c7aefcd6e4e3 100644 --- a/drivers/video/backlight/led_bl.c +++ b/drivers/video/backlight/led_bl.c @@ -200,8 +200,8 @@ static int led_bl_probe(struct platform_device *pdev) props.type = BACKLIGHT_RAW; props.max_brightness = priv->max_brightness; props.brightness = priv->default_brightness; - props.power = (priv->default_brightness > 0) ? FB_BLANK_POWERDOWN : - FB_BLANK_UNBLANK; + props.power = (priv->default_brightness > 0) ? BACKLIGHT_POWER_OFF : + BACKLIGHT_POWER_ON; priv->bl_dev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, priv, &led_bl_ops, &props); if (IS_ERR(priv->bl_dev)) { diff --git a/drivers/video/backlight/lm3509_bl.c b/drivers/video/backlight/lm3509_bl.c new file mode 100644 index 000000000000..24e1a19ff72d --- /dev/null +++ b/drivers/video/backlight/lm3509_bl.c @@ -0,0 +1,343 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/regmap.h> + +#define LM3509_NAME "lm3509_bl" + +#define LM3509_SINK_MAIN 0 +#define LM3509_SINK_SUB 1 +#define LM3509_NUM_SINKS 2 + +#define LM3509_DEF_BRIGHTNESS 0x12 +#define LM3509_MAX_BRIGHTNESS 0x1F + +#define REG_GP 0x10 +#define REG_BMAIN 0xA0 +#define REG_BSUB 0xB0 +#define REG_MAX 0xFF + +enum { + REG_GP_ENM_BIT = 0, + REG_GP_ENS_BIT, + REG_GP_UNI_BIT, + REG_GP_RMP0_BIT, + REG_GP_RMP1_BIT, + REG_GP_OLED_BIT, +}; + +struct lm3509_bl { + struct regmap *regmap; + struct backlight_device *bl_main; + struct backlight_device *bl_sub; + struct gpio_desc *reset_gpio; +}; + +struct lm3509_bl_led_data { + const char *label; + int led_sources; + u32 brightness; + u32 max_brightness; +}; + +static void lm3509_reset(struct lm3509_bl *data) +{ + if (data->reset_gpio) { + gpiod_set_value(data->reset_gpio, 1); + udelay(1); + gpiod_set_value(data->reset_gpio, 0); + udelay(10); + } +} + +static int lm3509_update_status(struct backlight_device *bl, + unsigned int en_mask, unsigned int br_reg) +{ + struct lm3509_bl *data = bl_get_data(bl); + int ret; + bool en; + + ret = regmap_write(data->regmap, br_reg, backlight_get_brightness(bl)); + if (ret < 0) + return ret; + + en = !backlight_is_blank(bl); + return regmap_update_bits(data->regmap, REG_GP, en_mask, + en ? en_mask : 0); +} + +static int lm3509_main_update_status(struct backlight_device *bl) +{ + return lm3509_update_status(bl, BIT(REG_GP_ENM_BIT), REG_BMAIN); +} + +static const struct backlight_ops lm3509_main_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = lm3509_main_update_status, +}; + +static int lm3509_sub_update_status(struct backlight_device *bl) +{ + return lm3509_update_status(bl, BIT(REG_GP_ENS_BIT), REG_BSUB); +} + +static const struct backlight_ops lm3509_sub_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = lm3509_sub_update_status, +}; + +static struct backlight_device * +lm3509_backlight_register(struct device *dev, const char *name_suffix, + struct lm3509_bl *data, + const struct backlight_ops *ops, + const struct lm3509_bl_led_data *led_data) + +{ + struct backlight_device *bd; + struct backlight_properties props; + const char *label = led_data->label; + char name[64]; + + memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; + props.brightness = led_data->brightness; + props.max_brightness = led_data->max_brightness; + props.scale = BACKLIGHT_SCALE_NON_LINEAR; + + if (!label) { + snprintf(name, sizeof(name), "lm3509-%s-%s", dev_name(dev), + name_suffix); + label = name; + } + + bd = devm_backlight_device_register(dev, label, dev, data, ops, &props); + if (IS_ERR(bd)) + return bd; + + backlight_update_status(bd); + return bd; +} + +static const struct regmap_config lm3509_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = REG_MAX, +}; + +static int lm3509_parse_led_sources(struct device_node *node, + int default_led_sources) +{ + u32 sources[LM3509_NUM_SINKS]; + int ret, num_sources, i; + + num_sources = of_property_count_u32_elems(node, "led-sources"); + if (num_sources < 0) + return default_led_sources; + else if (num_sources > ARRAY_SIZE(sources)) + return -EINVAL; + + ret = of_property_read_u32_array(node, "led-sources", sources, + num_sources); + if (ret) + return ret; + + for (i = 0; i < num_sources; i++) { + if (sources[i] >= LM3509_NUM_SINKS) + return -EINVAL; + + ret |= BIT(sources[i]); + } + + return ret; +} + +static int lm3509_parse_dt_node(struct device *dev, + struct lm3509_bl_led_data *led_data) +{ + int seen_led_sources = 0; + + for_each_child_of_node_scoped(dev->of_node, child) { + struct lm3509_bl_led_data *ld; + int ret; + u32 reg; + int valid_led_sources; + + ret = of_property_read_u32(child, "reg", ®); + if (ret < 0) + return ret; + if (reg >= LM3509_NUM_SINKS) + return -EINVAL; + ld = &led_data[reg]; + + ld->le |
