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

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

Pull backlight updates from Lee Jones:
"Additions:
- Add support for Awinic AW99706 backlight driver

Fixes:
- Add GPIOLIB dependency to backlight ktd2801 driver
- Add devlink to LED Backlight's supplier LEDs to enforce correct
removal order and prevent NULL pointer dereferences
- Fix kernel-doc warnings in lp855x.h

Removals:
- Do not include <linux/fb.h> in backlight.h
- Fix unused function warnings from suspend/resume ops in aw99706.c
by switching to DEFINE_SIMPLE_DEV_PM_OPS and using pm_ptr()

Bindings:
- Add Awinic AW99706 backlight binding to MAINTAINERS
- Add Awinic AW99706 backlight binding documentation"

* tag 'backlight-next-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight:
backlight: aw99706: Fix unused function warnings from suspend/resume ops
backlight: lp855x: Fix lp855x.h kernel-doc warnings
dt-bindings: leds: backlight: Add Awinic AW99706 backlight
backlight: aw99706: Add support for Awinic AW99706 backlight
backlight: led-bl: Add devlink to supplier LEDs
backlight: ktd2801: Depend on GPIOLIB
backlight: Do not include <linux/fb.h> in header file

+603 -3
+101
Documentation/devicetree/bindings/leds/backlight/awinic,aw99706.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/leds/backlight/awinic,aw99706.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Awinic AW99706 6-channel WLED Backlight Driver 8 + 9 + maintainers: 10 + - Junjie Cao <caojunjie650@gmail.com> 11 + 12 + allOf: 13 + - $ref: common.yaml# 14 + 15 + properties: 16 + compatible: 17 + const: awinic,aw99706 18 + 19 + reg: 20 + maxItems: 1 21 + 22 + enable-gpios: 23 + description: GPIO to use to enable/disable the backlight (HWEN pin). 24 + maxItems: 1 25 + 26 + awinic,dim-mode: 27 + $ref: /schemas/types.yaml#/definitions/uint32 28 + description: > 29 + Select dimming mode of the device. 30 + 0 = Bypass mode. 31 + 1 = DC mode. 32 + 2 = MIX mode(PWM at low brightness and DC at high brightness). 33 + 3 = MIX-26k mode(MIX mode with different PWM frequency). 34 + enum: [ 0, 1, 2, 3 ] 35 + default: 1 36 + 37 + awinic,sw-freq-hz: 38 + description: Boost switching frequency in Hz. 39 + enum: [ 300000, 400000, 500000, 600000, 660000, 750000, 850000, 1000000, 40 + 1200000, 1330000, 1500000, 1700000 ] 41 + default: 750000 42 + 43 + awinic,sw-ilmt-microamp: 44 + description: Switching current limitation in uA. 45 + enum: [ 1500000, 2000000, 2500000, 3000000 ] 46 + default: 3000000 47 + 48 + awinic,iled-max-microamp: 49 + description: Maximum LED current setting in uA. 50 + minimum: 5000 51 + maximum: 50000 52 + multipleOf: 500 53 + default: 20000 54 + 55 + awinic,uvlo-thres-microvolt: 56 + description: UVLO(Under Voltage Lock Out) in uV. 57 + enum: [ 2200000, 5000000 ] 58 + default: 2200000 59 + 60 + awinic,ramp-ctl: 61 + $ref: /schemas/types.yaml#/definitions/uint32 62 + description: > 63 + Select ramp control and filter of the device. 64 + 0 = Fade in/fade out. 65 + 1 = Light filter. 66 + 2 = Medium filter. 67 + 3 = Heavy filter. 68 + enum: [ 0, 1, 2, 3 ] 69 + default: 2 70 + 71 + required: 72 + - compatible 73 + - reg 74 + - enable-gpios 75 + 76 + unevaluatedProperties: false 77 + 78 + examples: 79 + - | 80 + #include <dt-bindings/gpio/gpio.h> 81 + 82 + i2c { 83 + #address-cells = <1>; 84 + #size-cells = <0>; 85 + 86 + backlight@76 { 87 + compatible = "awinic,aw99706"; 88 + reg = <0x76>; 89 + enable-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>; 90 + default-brightness = <2047>; 91 + max-brightness = <4095>; 92 + awinic,dim-mode = <1>; 93 + awinic,sw-freq-hz = <750000>; 94 + awinic,sw-ilmt-microamp = <3000000>; 95 + awinic,uvlo-thres-microvolt = <2200000>; 96 + awinic,iled-max-microamp = <20000>; 97 + awinic,ramp-ctl = <2>; 98 + }; 99 + }; 100 + 101 + ...
+6
MAINTAINERS
··· 4156 4156 F: Documentation/devicetree/bindings/iio/adc/avia-hx711.yaml 4157 4157 F: drivers/iio/adc/hx711.c 4158 4158 4159 + AWINIC AW99706 WLED BACKLIGHT DRIVER 4160 + M: Junjie Cao <caojunjie650@gmail.com> 4161 + S: Maintained 4162 + F: Documentation/devicetree/bindings/leds/backlight/awinic,aw99706.yaml 4163 + F: drivers/video/backlight/aw99706.c 4164 + 4159 4165 AX.25 NETWORK LAYER 4160 4166 L: linux-hams@vger.kernel.org 4161 4167 S: Orphan
+9
drivers/video/backlight/Kconfig
··· 156 156 If in doubt, it's safe to enable this option; it doesn't kick 157 157 in unless the board's description says it's wired that way. 158 158 159 + config BACKLIGHT_AW99706 160 + tristate "Backlight Driver for Awinic AW99706" 161 + depends on I2C 162 + select REGMAP_I2C 163 + help 164 + If you have a LCD backlight connected to the WLED output of AW99706 165 + WLED output, say Y here to enable this driver. 166 + 159 167 config BACKLIGHT_EP93XX 160 168 tristate "Cirrus EP93xx Backlight Driver" 161 169 depends on FB_EP93XX ··· 193 185 194 186 config BACKLIGHT_KTD2801 195 187 tristate "Backlight Driver for Kinetic KTD2801" 188 + depends on GPIOLIB || COMPILE_TEST 196 189 select LEDS_EXPRESSWIRE 197 190 help 198 191 Say Y to enable the backlight driver for the Kinetic KTD2801 1-wire
+1
drivers/video/backlight/Makefile
··· 25 25 obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o 26 26 obj-$(CONFIG_BACKLIGHT_APPLE_DWI) += apple_dwi_bl.o 27 27 obj-$(CONFIG_BACKLIGHT_AS3711) += as3711_bl.o 28 + obj-$(CONFIG_BACKLIGHT_AW99706) += aw99706.o 28 29 obj-$(CONFIG_BACKLIGHT_BD6107) += bd6107.o 29 30 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o 30 31 obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
+471
drivers/video/backlight/aw99706.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * aw99706 - Backlight driver for the AWINIC AW99706 4 + * 5 + * Copyright (C) 2025 Junjie Cao <caojunjie650@gmail.com> 6 + * Copyright (C) 2025 Pengyu Luo <mitltlatltl@gmail.com> 7 + * 8 + * Based on vendor driver: 9 + * Copyright (c) 2023 AWINIC Technology CO., LTD 10 + */ 11 + 12 + #include <linux/backlight.h> 13 + #include <linux/bitfield.h> 14 + #include <linux/delay.h> 15 + #include <linux/gpio.h> 16 + #include <linux/i2c.h> 17 + #include <linux/kernel.h> 18 + #include <linux/module.h> 19 + #include <linux/regmap.h> 20 + 21 + #define AW99706_MAX_BRT_LVL 4095 22 + #define AW99706_REG_MAX 0x1F 23 + #define AW99706_ID 0x07 24 + 25 + /* registers list */ 26 + #define AW99706_CFG0_REG 0x00 27 + #define AW99706_DIM_MODE_MASK GENMASK(1, 0) 28 + 29 + #define AW99706_CFG1_REG 0x01 30 + #define AW99706_SW_FREQ_MASK GENMASK(3, 0) 31 + #define AW99706_SW_ILMT_MASK GENMASK(5, 4) 32 + 33 + #define AW99706_CFG2_REG 0x02 34 + #define AW99706_ILED_MAX_MASK GENMASK(6, 0) 35 + #define AW99706_UVLOSEL_MASK BIT(7) 36 + 37 + #define AW99706_CFG3_REG 0x03 38 + #define AW99706_CFG4_REG 0x04 39 + #define AW99706_BRT_MSB_MASK GENMASK(3, 0) 40 + 41 + #define AW99706_CFG5_REG 0x05 42 + #define AW99706_BRT_LSB_MASK GENMASK(7, 0) 43 + 44 + #define AW99706_CFG6_REG 0x06 45 + #define AW99706_RAMP_CTL_MASK GENMASK(7, 6) 46 + 47 + #define AW99706_CFG7_REG 0x07 48 + #define AW99706_CFG8_REG 0x08 49 + #define AW99706_CFG9_REG 0x09 50 + #define AW99706_CFGA_REG 0x0A 51 + #define AW99706_CFGB_REG 0x0B 52 + #define AW99706_CFGC_REG 0x0C 53 + #define AW99706_CFGD_REG 0x0D 54 + #define AW99706_FLAG_REG 0x10 55 + #define AW99706_BACKLIGHT_EN_MASK BIT(7) 56 + 57 + #define AW99706_CHIPID_REG 0x11 58 + #define AW99706_LED_OPEN_FLAG_REG 0x12 59 + #define AW99706_LED_SHORT_FLAG_REG 0x13 60 + #define AW99706_MTPLDOSEL_REG 0x1E 61 + #define AW99706_MTPRUN_REG 0x1F 62 + 63 + #define RESV 0 64 + 65 + /* Boost switching frequency table, in Hz */ 66 + static const u32 aw99706_sw_freq_tbl[] = { 67 + RESV, RESV, RESV, RESV, 300000, 400000, 500000, 600000, 68 + 660000, 750000, 850000, 1000000, 1200000, 1330000, 1500000, 1700000 69 + }; 70 + 71 + /* Switching current limitation table, in uA */ 72 + static const u32 aw99706_sw_ilmt_tbl[] = { 73 + 1500000, 2000000, 2500000, 3000000 74 + }; 75 + 76 + /* ULVO threshold table, in uV */ 77 + static const u32 aw99706_ulvo_thres_tbl[] = { 78 + 2200000, 5000000 79 + }; 80 + 81 + struct aw99706_dt_prop { 82 + const char * const name; 83 + int (*lookup)(const struct aw99706_dt_prop *prop, u32 dt_val, u8 *val); 84 + const u32 * const lookup_tbl; 85 + u8 tbl_size; 86 + u8 reg; 87 + u8 mask; 88 + u32 def_val; 89 + }; 90 + 91 + static int aw99706_dt_property_lookup(const struct aw99706_dt_prop *prop, 92 + u32 dt_val, u8 *val) 93 + { 94 + int i; 95 + 96 + if (!prop->lookup_tbl) { 97 + *val = dt_val; 98 + return 0; 99 + } 100 + 101 + for (i = 0; i < prop->tbl_size; i++) 102 + if (prop->lookup_tbl[i] == dt_val) 103 + break; 104 + 105 + *val = i; 106 + 107 + return i == prop->tbl_size ? -1 : 0; 108 + } 109 + 110 + #define MIN_ILED_MAX 5000 111 + #define MAX_ILED_MAX 50000 112 + #define STEP_ILED_MAX 500 113 + 114 + static int 115 + aw99706_dt_property_iled_max_convert(const struct aw99706_dt_prop *prop, 116 + u32 dt_val, u8 *val) 117 + { 118 + if (dt_val > MAX_ILED_MAX || dt_val < MIN_ILED_MAX) 119 + return -1; 120 + 121 + *val = (dt_val - MIN_ILED_MAX) / STEP_ILED_MAX; 122 + 123 + return (dt_val - MIN_ILED_MAX) % STEP_ILED_MAX; 124 + } 125 + 126 + static const struct aw99706_dt_prop aw99706_dt_props[] = { 127 + { 128 + "awinic,dim-mode", aw99706_dt_property_lookup, 129 + NULL, 0, 130 + AW99706_CFG0_REG, AW99706_DIM_MODE_MASK, 1, 131 + }, 132 + { 133 + "awinic,sw-freq", aw99706_dt_property_lookup, 134 + aw99706_sw_freq_tbl, ARRAY_SIZE(aw99706_sw_freq_tbl), 135 + AW99706_CFG1_REG, AW99706_SW_FREQ_MASK, 750000, 136 + }, 137 + { 138 + "awinic,sw-ilmt", aw99706_dt_property_lookup, 139 + aw99706_sw_ilmt_tbl, ARRAY_SIZE(aw99706_sw_ilmt_tbl), 140 + AW99706_CFG1_REG, AW99706_SW_ILMT_MASK, 3000000, 141 + }, 142 + { 143 + "awinic,iled-max", aw99706_dt_property_iled_max_convert, 144 + NULL, 0, 145 + AW99706_CFG2_REG, AW99706_ILED_MAX_MASK, 20000, 146 + 147 + }, 148 + { 149 + "awinic,uvlo-thres", aw99706_dt_property_lookup, 150 + aw99706_ulvo_thres_tbl, ARRAY_SIZE(aw99706_ulvo_thres_tbl), 151 + AW99706_CFG2_REG, AW99706_UVLOSEL_MASK, 2200000, 152 + }, 153 + { 154 + "awinic,ramp-ctl", aw99706_dt_property_lookup, 155 + NULL, 0, 156 + AW99706_CFG6_REG, AW99706_RAMP_CTL_MASK, 2, 157 + } 158 + }; 159 + 160 + struct reg_init_data { 161 + u8 reg; 162 + u8 mask; 163 + u8 val; 164 + }; 165 + 166 + struct aw99706_device { 167 + struct i2c_client *client; 168 + struct device *dev; 169 + struct regmap *regmap; 170 + struct backlight_device *bl_dev; 171 + struct gpio_desc *hwen_gpio; 172 + struct reg_init_data init_tbl[ARRAY_SIZE(aw99706_dt_props)]; 173 + bool bl_enable; 174 + }; 175 + 176 + enum reg_access { 177 + REG_NONE_ACCESS = 0, 178 + REG_RD_ACCESS = 1, 179 + REG_WR_ACCESS = 2, 180 + }; 181 + 182 + static const u8 aw99706_regs[AW99706_REG_MAX + 1] = { 183 + [AW99706_CFG0_REG] = REG_RD_ACCESS | REG_WR_ACCESS, 184 + [AW99706_CFG1_REG] = REG_RD_ACCESS | REG_WR_ACCESS, 185 + [AW99706_CFG2_REG] = REG_RD_ACCESS | REG_WR_ACCESS, 186 + [AW99706_CFG3_REG] = REG_RD_ACCESS | REG_WR_ACCESS, 187 + [AW99706_CFG4_REG] = REG_RD_ACCESS | REG_WR_ACCESS, 188 + [AW99706_CFG5_REG] = REG_RD_ACCESS | REG_WR_ACCESS, 189 + [AW99706_CFG6_REG] = REG_RD_ACCESS | REG_WR_ACCESS, 190 + [AW99706_CFG7_REG] = REG_RD_ACCESS | REG_WR_ACCESS, 191 + [AW99706_CFG8_REG] = REG_RD_ACCESS | REG_WR_ACCESS, 192 + [AW99706_CFG9_REG] = REG_RD_ACCESS | REG_WR_ACCESS, 193 + [AW99706_CFGA_REG] = REG_RD_ACCESS | REG_WR_ACCESS, 194 + [AW99706_CFGB_REG] = REG_RD_ACCESS | REG_WR_ACCESS, 195 + [AW99706_CFGC_REG] = REG_RD_ACCESS | REG_WR_ACCESS, 196 + [AW99706_CFGD_REG] = REG_RD_ACCESS | REG_WR_ACCESS, 197 + [AW99706_FLAG_REG] = REG_RD_ACCESS, 198 + [AW99706_CHIPID_REG] = REG_RD_ACCESS, 199 + [AW99706_LED_OPEN_FLAG_REG] = REG_RD_ACCESS, 200 + [AW99706_LED_SHORT_FLAG_REG] = REG_RD_ACCESS, 201 + 202 + /* 203 + * Write bit is dropped here, writing BIT(0) to MTPLDOSEL will unlock 204 + * Multi-time Programmable (MTP). 205 + */ 206 + [AW99706_MTPLDOSEL_REG] = REG_RD_ACCESS, 207 + [AW99706_MTPRUN_REG] = REG_NONE_ACCESS, 208 + }; 209 + 210 + static bool aw99706_readable_reg(struct device *dev, unsigned int reg) 211 + { 212 + return aw99706_regs[reg] & REG_RD_ACCESS; 213 + } 214 + 215 + static bool aw99706_writeable_reg(struct device *dev, unsigned int reg) 216 + { 217 + return aw99706_regs[reg] & REG_WR_ACCESS; 218 + } 219 + 220 + static inline int aw99706_i2c_read(struct aw99706_device *aw, u8 reg, 221 + unsigned int *val) 222 + { 223 + return regmap_read(aw->regmap, reg, val); 224 + } 225 + 226 + static inline int aw99706_i2c_write(struct aw99706_device *aw, u8 reg, u8 val) 227 + { 228 + return regmap_write(aw->regmap, reg, val); 229 + } 230 + 231 + static inline int aw99706_i2c_update_bits(struct aw99706_device *aw, u8 reg, 232 + u8 mask, u8 val) 233 + { 234 + return regmap_update_bits(aw->regmap, reg, mask, val); 235 + } 236 + 237 + static void aw99706_dt_parse(struct aw99706_device *aw, 238 + struct backlight_properties *bl_props) 239 + { 240 + const struct aw99706_dt_prop *prop; 241 + u32 dt_val; 242 + int ret, i; 243 + u8 val; 244 + 245 + for (i = 0; i < ARRAY_SIZE(aw99706_dt_props); i++) { 246 + prop = &aw99706_dt_props[i]; 247 + ret = device_property_read_u32(aw->dev, prop->name, &dt_val); 248 + if (ret < 0) 249 + dt_val = prop->def_val; 250 + 251 + if (prop->lookup(prop, dt_val, &val)) { 252 + dev_warn(aw->dev, "invalid value %d for property %s, using default value %d\n", 253 + dt_val, prop->name, prop->def_val); 254 + 255 + prop->lookup(prop, prop->def_val, &val); 256 + } 257 + 258 + aw->init_tbl[i].reg = prop->reg; 259 + aw->init_tbl[i].mask = prop->mask; 260 + aw->init_tbl[i].val = val << __ffs(prop->mask); 261 + } 262 + 263 + bl_props->brightness = AW99706_MAX_BRT_LVL >> 1; 264 + bl_props->max_brightness = AW99706_MAX_BRT_LVL; 265 + device_property_read_u32(aw->dev, "default-brightness", 266 + &bl_props->brightness); 267 + device_property_read_u32(aw->dev, "max-brightness", 268 + &bl_props->max_brightness); 269 + 270 + if (bl_props->max_brightness > AW99706_MAX_BRT_LVL) 271 + bl_props->max_brightness = AW99706_MAX_BRT_LVL; 272 + 273 + if (bl_props->brightness > bl_props->max_brightness) 274 + bl_props->brightness = bl_props->max_brightness; 275 + } 276 + 277 + static int aw99706_hw_init(struct aw99706_device *aw) 278 + { 279 + int ret, i; 280 + 281 + gpiod_set_value_cansleep(aw->hwen_gpio, 1); 282 + 283 + for (i = 0; i < ARRAY_SIZE(aw->init_tbl); i++) { 284 + ret = aw99706_i2c_update_bits(aw, aw->init_tbl[i].reg, 285 + aw->init_tbl[i].mask, 286 + aw->init_tbl[i].val); 287 + if (ret < 0) { 288 + dev_err(aw->dev, "Failed to write init data %d\n", ret); 289 + return ret; 290 + } 291 + } 292 + 293 + return 0; 294 + } 295 + 296 + static int aw99706_bl_enable(struct aw99706_device *aw, bool en) 297 + { 298 + int ret; 299 + u8 val; 300 + 301 + val = FIELD_PREP(AW99706_BACKLIGHT_EN_MASK, en); 302 + ret = aw99706_i2c_update_bits(aw, AW99706_CFGD_REG, 303 + AW99706_BACKLIGHT_EN_MASK, val); 304 + if (ret) 305 + dev_err(aw->dev, "Failed to enable backlight!\n"); 306 + 307 + return ret; 308 + } 309 + 310 + static int aw99706_update_brightness(struct aw99706_device *aw, u32 brt_lvl) 311 + { 312 + bool bl_enable_now = !!brt_lvl; 313 + int ret; 314 + 315 + ret = aw99706_i2c_write(aw, AW99706_CFG4_REG, 316 + (brt_lvl >> 8) & AW99706_BRT_MSB_MASK); 317 + if (ret < 0) 318 + return ret; 319 + 320 + ret = aw99706_i2c_write(aw, AW99706_CFG5_REG, 321 + brt_lvl & AW99706_BRT_LSB_MASK); 322 + if (ret < 0) 323 + return ret; 324 + 325 + if (aw->bl_enable != bl_enable_now) { 326 + ret = aw99706_bl_enable(aw, bl_enable_now); 327 + if (!ret) 328 + aw->bl_enable = bl_enable_now; 329 + } 330 + 331 + return ret; 332 + } 333 + 334 + static int aw99706_bl_update_status(struct backlight_device *bl) 335 + { 336 + struct aw99706_device *aw = bl_get_data(bl); 337 + 338 + return aw99706_update_brightness(aw, bl->props.brightness); 339 + } 340 + 341 + static const struct backlight_ops aw99706_bl_ops = { 342 + .options = BL_CORE_SUSPENDRESUME, 343 + .update_status = aw99706_bl_update_status, 344 + }; 345 + 346 + static const struct regmap_config aw99706_regmap_config = { 347 + .reg_bits = 8, 348 + .val_bits = 8, 349 + .max_register = AW99706_REG_MAX, 350 + .writeable_reg = aw99706_writeable_reg, 351 + .readable_reg = aw99706_readable_reg, 352 + }; 353 + 354 + static int aw99706_chip_id_read(struct aw99706_device *aw) 355 + { 356 + int ret; 357 + unsigned int val; 358 + 359 + ret = aw99706_i2c_read(aw, AW99706_CHIPID_REG, &val); 360 + if (ret < 0) 361 + return ret; 362 + 363 + return val; 364 + } 365 + 366 + static int aw99706_probe(struct i2c_client *client) 367 + { 368 + struct device *dev = &client->dev; 369 + struct aw99706_device *aw; 370 + struct backlight_device *bl_dev; 371 + struct backlight_properties props = {}; 372 + int ret = 0; 373 + 374 + aw = devm_kzalloc(dev, sizeof(*aw), GFP_KERNEL); 375 + if (!aw) 376 + return -ENOMEM; 377 + 378 + aw->client = client; 379 + aw->dev = dev; 380 + i2c_set_clientdata(client, aw); 381 + 382 + aw->regmap = devm_regmap_init_i2c(client, &aw99706_regmap_config); 383 + if (IS_ERR(aw->regmap)) 384 + return dev_err_probe(dev, PTR_ERR(aw->regmap), 385 + "Failed to init regmap\n"); 386 + 387 + ret = aw99706_chip_id_read(aw); 388 + if (ret != AW99706_ID) 389 + return dev_err_probe(dev, -ENODEV, 390 + "Unknown chip id 0x%02x\n", ret); 391 + 392 + aw99706_dt_parse(aw, &props); 393 + 394 + aw->hwen_gpio = devm_gpiod_get(aw->dev, "enable", GPIOD_OUT_LOW); 395 + if (IS_ERR(aw->hwen_gpio)) 396 + return dev_err_probe(dev, PTR_ERR(aw->hwen_gpio), 397 + "Failed to get enable gpio\n"); 398 + 399 + ret = aw99706_hw_init(aw); 400 + if (ret < 0) 401 + return dev_err_probe(dev, ret, 402 + "Failed to initialize the chip\n"); 403 + 404 + props.type = BACKLIGHT_RAW; 405 + props.scale = BACKLIGHT_SCALE_LINEAR; 406 + 407 + bl_dev = devm_backlight_device_register(dev, "aw99706-backlight", dev, 408 + aw, &aw99706_bl_ops, &props); 409 + if (IS_ERR(bl_dev)) 410 + return dev_err_probe(dev, PTR_ERR(bl_dev), 411 + "Failed to register backlight!\n"); 412 + 413 + aw->bl_dev = bl_dev; 414 + 415 + return 0; 416 + } 417 + 418 + static void aw99706_remove(struct i2c_client *client) 419 + { 420 + struct aw99706_device *aw = i2c_get_clientdata(client); 421 + 422 + aw99706_update_brightness(aw, 0); 423 + 424 + msleep(50); 425 + 426 + gpiod_set_value_cansleep(aw->hwen_gpio, 0); 427 + } 428 + 429 + static int aw99706_suspend(struct device *dev) 430 + { 431 + struct aw99706_device *aw = dev_get_drvdata(dev); 432 + 433 + return aw99706_update_brightness(aw, 0); 434 + } 435 + 436 + static int aw99706_resume(struct device *dev) 437 + { 438 + struct aw99706_device *aw = dev_get_drvdata(dev); 439 + 440 + return aw99706_hw_init(aw); 441 + } 442 + 443 + static DEFINE_SIMPLE_DEV_PM_OPS(aw99706_pm_ops, aw99706_suspend, aw99706_resume); 444 + 445 + static const struct i2c_device_id aw99706_ids[] = { 446 + { "aw99706" }, 447 + { } 448 + }; 449 + MODULE_DEVICE_TABLE(i2c, aw99706_ids); 450 + 451 + static const struct of_device_id aw99706_match_table[] = { 452 + { .compatible = "awinic,aw99706", }, 453 + { } 454 + }; 455 + MODULE_DEVICE_TABLE(of, aw99706_match_table); 456 + 457 + static struct i2c_driver aw99706_i2c_driver = { 458 + .probe = aw99706_probe, 459 + .remove = aw99706_remove, 460 + .id_table = aw99706_ids, 461 + .driver = { 462 + .name = "aw99706", 463 + .of_match_table = aw99706_match_table, 464 + .pm = pm_ptr(&aw99706_pm_ops), 465 + }, 466 + }; 467 + 468 + module_i2c_driver(aw99706_i2c_driver); 469 + 470 + MODULE_LICENSE("GPL v2"); 471 + MODULE_DESCRIPTION("BackLight driver for aw99706");
+13
drivers/video/backlight/led_bl.c
··· 211 211 } 212 212 213 213 for (i = 0; i < priv->nb_leds; i++) { 214 + struct device_link *link; 215 + 216 + link = device_link_add(&pdev->dev, priv->leds[i]->dev->parent, 217 + DL_FLAG_AUTOREMOVE_CONSUMER); 218 + if (!link) { 219 + dev_err(&pdev->dev, "Failed to add devlink (consumer %s, supplier %s)\n", 220 + dev_name(&pdev->dev), dev_name(priv->leds[i]->dev->parent)); 221 + backlight_device_unregister(priv->bl_dev); 222 + return -EINVAL; 223 + } 224 + } 225 + 226 + for (i = 0; i < priv->nb_leds; i++) { 214 227 mutex_lock(&priv->leds[i]->led_access); 215 228 led_sysfs_disable(priv->leds[i]); 216 229 mutex_unlock(&priv->leds[i]->led_access);
-1
include/linux/backlight.h
··· 10 10 #define _LINUX_BACKLIGHT_H 11 11 12 12 #include <linux/device.h> 13 - #include <linux/fb.h> 14 13 #include <linux/mutex.h> 15 14 #include <linux/types.h> 16 15
+2 -2
include/linux/platform_data/lp855x.h
··· 124 124 }; 125 125 126 126 /** 127 - * struct lp855x_platform_data 127 + * struct lp855x_platform_data - lp855 platform-specific data 128 128 * @name : Backlight driver name. If it is not defined, default name is set. 129 129 * @device_control : value of DEVICE CONTROL register 130 130 * @initial_brightness : initial value of backlight brightness 131 131 * @period_ns : platform specific pwm period value. unit is nano. 132 - Only valid when mode is PWM_BASED. 132 + * Only valid when mode is PWM_BASED. 133 133 * @size_program : total size of lp855x_rom_data 134 134 * @rom_data : list of new eeprom/eprom registers 135 135 */