Blame view
drivers/leds/leds-lm3532.c
18.6 KB
bc1b8492c leds: lm3532: Int... |
1 2 |
// SPDX-License-Identifier: GPL-2.0 // TI LM3532 LED driver |
c54373381 leds: Replace HTT... |
3 4 |
// Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com/ // https://www.ti.com/lit/ds/symlink/lm3532.pdf |
bc1b8492c leds: lm3532: Int... |
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include <linux/i2c.h> #include <linux/leds.h> #include <linux/slab.h> #include <linux/regmap.h> #include <linux/types.h> #include <linux/regulator/consumer.h> #include <linux/module.h> #include <uapi/linux/uleds.h> #include <linux/gpio/consumer.h> #define LM3532_NAME "lm3532-led" #define LM3532_BL_MODE_MANUAL 0x00 #define LM3532_BL_MODE_ALS 0x01 #define LM3532_REG_OUTPUT_CFG 0x10 #define LM3532_REG_STARTSHUT_RAMP 0x11 #define LM3532_REG_RT_RAMP 0x12 #define LM3532_REG_PWM_A_CFG 0x13 #define LM3532_REG_PWM_B_CFG 0x14 #define LM3532_REG_PWM_C_CFG 0x15 #define LM3532_REG_ZONE_CFG_A 0x16 |
4c9054506 leds: lm3532: Cha... |
27 |
#define LM3532_REG_CTRL_A_FS_CURR 0x17 |
bc1b8492c leds: lm3532: Int... |
28 |
#define LM3532_REG_ZONE_CFG_B 0x18 |
4c9054506 leds: lm3532: Cha... |
29 |
#define LM3532_REG_CTRL_B_FS_CURR 0x19 |
bc1b8492c leds: lm3532: Int... |
30 |
#define LM3532_REG_ZONE_CFG_C 0x1a |
4c9054506 leds: lm3532: Cha... |
31 |
#define LM3532_REG_CTRL_C_FS_CURR 0x1b |
bc1b8492c leds: lm3532: Int... |
32 33 34 35 36 37 38 39 40 41 |
#define LM3532_REG_ENABLE 0x1d #define LM3532_ALS_CONFIG 0x23 #define LM3532_REG_ZN_0_HI 0x60 #define LM3532_REG_ZN_0_LO 0x61 #define LM3532_REG_ZN_1_HI 0x62 #define LM3532_REG_ZN_1_LO 0x63 #define LM3532_REG_ZN_2_HI 0x64 #define LM3532_REG_ZN_2_LO 0x65 #define LM3532_REG_ZN_3_HI 0x66 #define LM3532_REG_ZN_3_LO 0x67 |
131239402 leds: lm3532: Fix... |
42 43 44 |
#define LM3532_REG_ZONE_TRGT_A 0x70 #define LM3532_REG_ZONE_TRGT_B 0x75 #define LM3532_REG_ZONE_TRGT_C 0x7a |
bc1b8492c leds: lm3532: Int... |
45 |
#define LM3532_REG_MAX 0x7e |
6559ac329 leds: lm3532: Fix... |
46 |
/* Control Enable */ |
bc1b8492c leds: lm3532: Int... |
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
#define LM3532_CTRL_A_ENABLE BIT(0) #define LM3532_CTRL_B_ENABLE BIT(1) #define LM3532_CTRL_C_ENABLE BIT(2) /* PWM Zone Control */ #define LM3532_PWM_ZONE_MASK 0x7c #define LM3532_PWM_ZONE_0_EN BIT(2) #define LM3532_PWM_ZONE_1_EN BIT(3) #define LM3532_PWM_ZONE_2_EN BIT(4) #define LM3532_PWM_ZONE_3_EN BIT(5) #define LM3532_PWM_ZONE_4_EN BIT(6) /* Brightness Configuration */ #define LM3532_I2C_CTRL BIT(0) #define LM3532_ALS_CTRL 0 #define LM3532_LINEAR_MAP BIT(1) #define LM3532_ZONE_MASK (BIT(2) | BIT(3) | BIT(4)) #define LM3532_ZONE_0 0 #define LM3532_ZONE_1 BIT(2) #define LM3532_ZONE_2 BIT(3) #define LM3532_ZONE_3 (BIT(2) | BIT(3)) #define LM3532_ZONE_4 BIT(4) #define LM3532_ENABLE_ALS BIT(3) #define LM3532_ALS_SEL_SHIFT 6 /* Zone Boundary Register */ #define LM3532_ALS_WINDOW_mV 2000 #define LM3532_ALS_ZB_MAX 4 #define LM3532_ALS_OFFSET_mV 2 #define LM3532_CONTROL_A 0 #define LM3532_CONTROL_B 1 #define LM3532_CONTROL_C 2 #define LM3532_MAX_CONTROL_BANKS 3 #define LM3532_MAX_LED_STRINGS 3 #define LM3532_OUTPUT_CFG_MASK 0x3 #define LM3532_BRT_VAL_ADJUST 8 #define LM3532_RAMP_DOWN_SHIFT 3 #define LM3532_NUM_RAMP_VALS 8 #define LM3532_NUM_AVG_VALS 8 #define LM3532_NUM_IMP_VALS 32 |
517ea49a7 leds: lm3532: Add... |
91 92 93 |
#define LM3532_FS_CURR_MIN 5000 #define LM3532_FS_CURR_MAX 29800 #define LM3532_FS_CURR_STEP 800 |
bc1b8492c leds: lm3532: Int... |
94 95 |
/* * struct lm3532_als_data |
9e955a421 leds: lm3532: Fix... |
96 97 98 99 100 101 102 103 104 |
* @config: value of ALS configuration register * @als1_imp_sel: value of ALS1 resistor select register * @als2_imp_sel: value of ALS2 resistor select register * @als_avrg_time: ALS averaging time * @als_input_mode: ALS input mode for brightness control * @als_vmin: Minimum ALS voltage * @als_vmax: Maximum ALS voltage * @zone_lo: values of ALS lo ZB(Zone Boundary) registers * @zone_hi: values of ALS hi ZB(Zone Boundary) registers |
bc1b8492c leds: lm3532: Int... |
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
*/ struct lm3532_als_data { u8 config; u8 als1_imp_sel; u8 als2_imp_sel; u8 als_avrg_time; u8 als_input_mode; u32 als_vmin; u32 als_vmax; u8 zones_lo[LM3532_ALS_ZB_MAX]; u8 zones_hi[LM3532_ALS_ZB_MAX]; }; /** * struct lm3532_led * @led_dev: led class device |
9e955a421 leds: lm3532: Fix... |
121 122 123 124 125 126 127 128 |
* @priv: Pointer the device data structure * @control_bank: Control bank the LED is associated to * @mode: Mode of the LED string * @ctrl_brt_pointer: Zone target register that controls the sink * @num_leds: Number of LED strings are supported in this array * @full_scale_current: The full-scale current setting for the current sink. * @led_strings: The LED strings supported in this array * @enabled: Enabled status |
bc1b8492c leds: lm3532: Int... |
129 130 131 132 133 134 135 |
*/ struct lm3532_led { struct led_classdev led_dev; struct lm3532_data *priv; int control_bank; int mode; |
131239402 leds: lm3532: Fix... |
136 |
int ctrl_brt_pointer; |
bc1b8492c leds: lm3532: Int... |
137 |
int num_leds; |
517ea49a7 leds: lm3532: Add... |
138 |
int full_scale_current; |
28799272a leds: lm3532: mak... |
139 |
unsigned int enabled:1; |
bc1b8492c leds: lm3532: Int... |
140 |
u32 led_strings[LM3532_MAX_CONTROL_BANKS]; |
bc1b8492c leds: lm3532: Int... |
141 142 143 144 |
}; /** * struct lm3532_data |
9e955a421 leds: lm3532: Fix... |
145 |
* @enable_gpio: Hardware enable gpio |
bc1b8492c leds: lm3532: Int... |
146 147 |
* @regulator: regulator * @client: i2c client |
9e955a421 leds: lm3532: Fix... |
148 149 150 151 152 153 154 |
* @regmap: Devices register map * @dev: Pointer to the devices device struct * @lock: Lock for reading/writing the device * @als_data: Pointer to the als data struct * @runtime_ramp_up: Runtime ramp up setting * @runtime_ramp_down: Runtime ramp down setting * @leds: Array of LED strings |
bc1b8492c leds: lm3532: Int... |
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
*/ struct lm3532_data { struct gpio_desc *enable_gpio; struct regulator *regulator; struct i2c_client *client; struct regmap *regmap; struct device *dev; struct mutex lock; struct lm3532_als_data *als_data; u32 runtime_ramp_up; u32 runtime_ramp_down; struct lm3532_led leds[]; }; static const struct reg_default lm3532_reg_defs[] = { {LM3532_REG_OUTPUT_CFG, 0xe4}, {LM3532_REG_STARTSHUT_RAMP, 0xc0}, {LM3532_REG_RT_RAMP, 0xc0}, {LM3532_REG_PWM_A_CFG, 0x82}, {LM3532_REG_PWM_B_CFG, 0x82}, {LM3532_REG_PWM_C_CFG, 0x82}, {LM3532_REG_ZONE_CFG_A, 0xf1}, |
4c9054506 leds: lm3532: Cha... |
180 |
{LM3532_REG_CTRL_A_FS_CURR, 0xf3}, |
bc1b8492c leds: lm3532: Int... |
181 |
{LM3532_REG_ZONE_CFG_B, 0xf1}, |
4c9054506 leds: lm3532: Cha... |
182 |
{LM3532_REG_CTRL_B_FS_CURR, 0xf3}, |
bc1b8492c leds: lm3532: Int... |
183 |
{LM3532_REG_ZONE_CFG_C, 0xf1}, |
4c9054506 leds: lm3532: Cha... |
184 |
{LM3532_REG_CTRL_C_FS_CURR, 0xf3}, |
bc1b8492c leds: lm3532: Int... |
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
{LM3532_REG_ENABLE, 0xf8}, {LM3532_ALS_CONFIG, 0x44}, {LM3532_REG_ZN_0_HI, 0x35}, {LM3532_REG_ZN_0_LO, 0x33}, {LM3532_REG_ZN_1_HI, 0x6a}, {LM3532_REG_ZN_1_LO, 0x66}, {LM3532_REG_ZN_2_HI, 0xa1}, {LM3532_REG_ZN_2_LO, 0x99}, {LM3532_REG_ZN_3_HI, 0xdc}, {LM3532_REG_ZN_3_LO, 0xcc}, }; static const struct regmap_config lm3532_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = LM3532_REG_MAX, .reg_defaults = lm3532_reg_defs, .num_reg_defaults = ARRAY_SIZE(lm3532_reg_defs), .cache_type = REGCACHE_FLAT, }; |
536129cc9 leds: lm3532: Mov... |
206 |
static const int als_imp_table[LM3532_NUM_IMP_VALS] = {37000, 18500, 12330, |
bc1b8492c leds: lm3532: Int... |
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
92500, 7400, 6170, 5290, 4630, 4110, 3700, 3360, 3080, 2850, 2640, 2440, 2310, 2180, 2060, 1950, 1850, 1760, 1680, 1610, 1540, 1480, 1420, 1370, 1320, 1280, 1230, 1190}; static int lm3532_get_als_imp_index(int als_imped) { int i; if (als_imped > als_imp_table[1]) return 0; if (als_imped < als_imp_table[LM3532_NUM_IMP_VALS - 1]) return LM3532_NUM_IMP_VALS - 1; for (i = 1; i < LM3532_NUM_IMP_VALS; i++) { if (als_imped == als_imp_table[i]) return i; /* Find an approximate index by looking up the table */ if (als_imped < als_imp_table[i - 1] && als_imped > als_imp_table[i]) { if (als_imped - als_imp_table[i - 1] < als_imp_table[i] - als_imped) return i + 1; else return i; } } return -EINVAL; } static int lm3532_get_index(const int table[], int size, int value) { int i; for (i = 1; i < size; i++) { if (value == table[i]) return i; /* Find an approximate index by looking up the table */ if (value > table[i - 1] && value < table[i]) { if (value - table[i - 1] < table[i] - value) return i - 1; else return i; } } return -EINVAL; } |
536129cc9 leds: lm3532: Mov... |
262 |
static const int als_avrg_table[LM3532_NUM_AVG_VALS] = {17920, 35840, 71680, |
bc1b8492c leds: lm3532: Int... |
263 264 265 266 267 268 269 270 271 272 273 274 275 |
1433360, 286720, 573440, 1146880, 2293760}; static int lm3532_get_als_avg_index(int avg_time) { if (avg_time <= als_avrg_table[0]) return 0; if (avg_time > als_avrg_table[LM3532_NUM_AVG_VALS - 1]) return LM3532_NUM_AVG_VALS - 1; return lm3532_get_index(&als_avrg_table[0], LM3532_NUM_AVG_VALS, avg_time); } |
536129cc9 leds: lm3532: Mov... |
276 |
static const int ramp_table[LM3532_NUM_RAMP_VALS] = { 8, 1024, 2048, 4096, 8192, |
bc1b8492c leds: lm3532: Int... |
277 278 279 280 281 282 283 284 285 286 287 288 |
16384, 32768, 65536}; static int lm3532_get_ramp_index(int ramp_time) { if (ramp_time <= ramp_table[0]) return 0; if (ramp_time > ramp_table[LM3532_NUM_RAMP_VALS - 1]) return LM3532_NUM_RAMP_VALS - 1; return lm3532_get_index(&ramp_table[0], LM3532_NUM_RAMP_VALS, ramp_time); } |
070a0eed7 leds: lm3532: Avo... |
289 |
/* Caller must take care of locking */ |
bc1b8492c leds: lm3532: Int... |
290 291 292 293 |
static int lm3532_led_enable(struct lm3532_led *led_data) { int ctrl_en_val = BIT(led_data->control_bank); int ret; |
070a0eed7 leds: lm3532: Avo... |
294 295 |
if (led_data->enabled) return 0; |
bc1b8492c leds: lm3532: Int... |
296 297 298 299 300 301 302 |
ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE, ctrl_en_val, ctrl_en_val); if (ret) { dev_err(led_data->priv->dev, "Failed to set ctrl:%d ", ret); return ret; } |
070a0eed7 leds: lm3532: Avo... |
303 304 305 306 307 308 309 |
ret = regulator_enable(led_data->priv->regulator); if (ret < 0) return ret; led_data->enabled = 1; return 0; |
bc1b8492c leds: lm3532: Int... |
310 |
} |
070a0eed7 leds: lm3532: Avo... |
311 |
/* Caller must take care of locking */ |
bc1b8492c leds: lm3532: Int... |
312 313 314 315 |
static int lm3532_led_disable(struct lm3532_led *led_data) { int ctrl_en_val = BIT(led_data->control_bank); int ret; |
070a0eed7 leds: lm3532: Avo... |
316 317 |
if (!led_data->enabled) return 0; |
bc1b8492c leds: lm3532: Int... |
318 |
ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE, |
6559ac329 leds: lm3532: Fix... |
319 |
ctrl_en_val, 0); |
bc1b8492c leds: lm3532: Int... |
320 321 322 323 324 |
if (ret) { dev_err(led_data->priv->dev, "Failed to set ctrl:%d ", ret); return ret; } |
070a0eed7 leds: lm3532: Avo... |
325 326 327 328 329 330 331 |
ret = regulator_disable(led_data->priv->regulator); if (ret < 0) return ret; led_data->enabled = 0; return 0; |
bc1b8492c leds: lm3532: Int... |
332 333 334 335 336 337 338 339 340 341 342 |
} static int lm3532_brightness_set(struct led_classdev *led_cdev, enum led_brightness brt_val) { struct lm3532_led *led = container_of(led_cdev, struct lm3532_led, led_dev); u8 brightness_reg; int ret; mutex_lock(&led->priv->lock); |
6559ac329 leds: lm3532: Fix... |
343 |
if (led->mode == LM3532_ALS_CTRL) { |
bc1b8492c leds: lm3532: Int... |
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
if (brt_val > LED_OFF) ret = lm3532_led_enable(led); else ret = lm3532_led_disable(led); goto unlock; } if (brt_val == LED_OFF) { ret = lm3532_led_disable(led); goto unlock; } ret = lm3532_led_enable(led); if (ret) goto unlock; |
131239402 leds: lm3532: Fix... |
360 361 |
brightness_reg = LM3532_REG_ZONE_TRGT_A + led->control_bank * 5 + (led->ctrl_brt_pointer >> 2); |
bc1b8492c leds: lm3532: Int... |
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 |
ret = regmap_write(led->priv->regmap, brightness_reg, brt_val); unlock: mutex_unlock(&led->priv->lock); return ret; } static int lm3532_init_registers(struct lm3532_led *led) { struct lm3532_data *drvdata = led->priv; unsigned int runtime_ramp_val; unsigned int output_cfg_val = 0; unsigned int output_cfg_shift = 0; unsigned int output_cfg_mask = 0; |
131239402 leds: lm3532: Fix... |
377 378 |
unsigned int brightness_config_reg; unsigned int brightness_config_val; |
517ea49a7 leds: lm3532: Add... |
379 380 |
int fs_current_reg; int fs_current_val; |
bc1b8492c leds: lm3532: Int... |
381 |
int ret, i; |
131239402 leds: lm3532: Fix... |
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 |
if (drvdata->enable_gpio) gpiod_direction_output(drvdata->enable_gpio, 1); brightness_config_reg = LM3532_REG_ZONE_CFG_A + led->control_bank * 2; /* * This could be hard coded to the default value but the control * brightness register may have changed during boot. */ ret = regmap_read(drvdata->regmap, brightness_config_reg, &led->ctrl_brt_pointer); if (ret) return ret; led->ctrl_brt_pointer &= LM3532_ZONE_MASK; brightness_config_val = led->ctrl_brt_pointer | led->mode; ret = regmap_write(drvdata->regmap, brightness_config_reg, brightness_config_val); if (ret) return ret; |
517ea49a7 leds: lm3532: Add... |
401 402 403 404 405 406 407 408 409 410 |
if (led->full_scale_current) { fs_current_reg = LM3532_REG_CTRL_A_FS_CURR + led->control_bank * 2; fs_current_val = (led->full_scale_current - LM3532_FS_CURR_MIN) / LM3532_FS_CURR_STEP; ret = regmap_write(drvdata->regmap, fs_current_reg, fs_current_val); if (ret) return ret; } |
bc1b8492c leds: lm3532: Int... |
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 |
for (i = 0; i < led->num_leds; i++) { output_cfg_shift = led->led_strings[i] * 2; output_cfg_val |= (led->control_bank << output_cfg_shift); output_cfg_mask |= LM3532_OUTPUT_CFG_MASK << output_cfg_shift; } ret = regmap_update_bits(drvdata->regmap, LM3532_REG_OUTPUT_CFG, output_cfg_mask, output_cfg_val); if (ret) return ret; runtime_ramp_val = drvdata->runtime_ramp_up | (drvdata->runtime_ramp_down << LM3532_RAMP_DOWN_SHIFT); return regmap_write(drvdata->regmap, LM3532_REG_RT_RAMP, runtime_ramp_val); } static int lm3532_als_configure(struct lm3532_data *priv, struct lm3532_led *led) { struct lm3532_als_data *als = priv->als_data; u32 als_vmin, als_vmax, als_vstep; int zone_reg = LM3532_REG_ZN_0_HI; |
bc1b8492c leds: lm3532: Int... |
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 |
int ret; int i; als_vmin = als->als_vmin; als_vmax = als->als_vmax; als_vstep = (als_vmax - als_vmin) / ((LM3532_ALS_ZB_MAX + 1) * 2); for (i = 0; i < LM3532_ALS_ZB_MAX; i++) { als->zones_lo[i] = ((als_vmin + als_vstep + (i * als_vstep)) * LED_FULL) / 1000; als->zones_hi[i] = ((als_vmin + LM3532_ALS_OFFSET_mV + als_vstep + (i * als_vstep)) * LED_FULL) / 1000; zone_reg = LM3532_REG_ZN_0_HI + i * 2; ret = regmap_write(priv->regmap, zone_reg, als->zones_lo[i]); if (ret) return ret; zone_reg += 1; ret = regmap_write(priv->regmap, zone_reg, als->zones_hi[i]); if (ret) return ret; } als->config = (als->als_avrg_time | (LM3532_ENABLE_ALS) | (als->als_input_mode << LM3532_ALS_SEL_SHIFT)); |
131239402 leds: lm3532: Fix... |
462 |
return regmap_write(priv->regmap, LM3532_ALS_CONFIG, als->config); |
bc1b8492c leds: lm3532: Int... |
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 |
} static int lm3532_parse_als(struct lm3532_data *priv) { struct lm3532_als_data *als; int als_avg_time; int als_impedance; int ret; als = devm_kzalloc(priv->dev, sizeof(*als), GFP_KERNEL); if (als == NULL) return -ENOMEM; ret = device_property_read_u32(&priv->client->dev, "ti,als-vmin", &als->als_vmin); if (ret) als->als_vmin = 0; ret = device_property_read_u32(&priv->client->dev, "ti,als-vmax", &als->als_vmax); if (ret) als->als_vmax = LM3532_ALS_WINDOW_mV; if (als->als_vmax > LM3532_ALS_WINDOW_mV) { ret = -EINVAL; return ret; } ret = device_property_read_u32(&priv->client->dev, "ti,als1-imp-sel", &als_impedance); if (ret) als->als1_imp_sel = 0; else als->als1_imp_sel = lm3532_get_als_imp_index(als_impedance); ret = device_property_read_u32(&priv->client->dev, "ti,als2-imp-sel", &als_impedance); if (ret) als->als2_imp_sel = 0; else als->als2_imp_sel = lm3532_get_als_imp_index(als_impedance); ret = device_property_read_u32(&priv->client->dev, "ti,als-avrg-time-us", &als_avg_time); if (ret) als->als_avrg_time = 0; else als->als_avrg_time = lm3532_get_als_avg_index(als_avg_time); ret = device_property_read_u8(&priv->client->dev, "ti,als-input-mode", &als->als_input_mode); if (ret) als->als_input_mode = 0; if (als->als_input_mode > LM3532_BL_MODE_ALS) { ret = -EINVAL; return ret; } priv->als_data = als; return ret; } static int lm3532_parse_node(struct lm3532_data *priv) { struct fwnode_handle *child = NULL; struct lm3532_led *led; |
bc1b8492c leds: lm3532: Int... |
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 |
int control_bank; u32 ramp_time; size_t i = 0; int ret; priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(priv->enable_gpio)) priv->enable_gpio = NULL; priv->regulator = devm_regulator_get(&priv->client->dev, "vin"); if (IS_ERR(priv->regulator)) priv->regulator = NULL; ret = device_property_read_u32(&priv->client->dev, "ramp-up-us", &ramp_time); if (ret) dev_info(&priv->client->dev, "ramp-up-ms property missing "); else priv->runtime_ramp_up = lm3532_get_ramp_index(ramp_time); ret = device_property_read_u32(&priv->client->dev, "ramp-down-us", &ramp_time); if (ret) dev_info(&priv->client->dev, "ramp-down-ms property missing "); else priv->runtime_ramp_down = lm3532_get_ramp_index(ramp_time); device_for_each_child_node(priv->dev, child) { |
cf6eb52fa leds: lm3532: use... |
562 563 564 565 566 |
struct led_init_data idata = { .fwnode = child, .default_label = ":", .devicename = priv->client->name, }; |
bc1b8492c leds: lm3532: Int... |
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 |
led = &priv->leds[i]; ret = fwnode_property_read_u32(child, "reg", &control_bank); if (ret) { dev_err(&priv->client->dev, "reg property missing "); fwnode_handle_put(child); goto child_out; } if (control_bank > LM3532_CONTROL_C) { dev_err(&priv->client->dev, "Control bank invalid "); continue; } led->control_bank = control_bank; ret = fwnode_property_read_u32(child, "ti,led-mode", &led->mode); if (ret) { dev_err(&priv->client->dev, "ti,led-mode property missing "); fwnode_handle_put(child); goto child_out; } |
6d4faf3b6 leds: lm3532: Fix... |
593 594 595 596 597 598 599 600 601 |
if (fwnode_property_present(child, "led-max-microamp") && fwnode_property_read_u32(child, "led-max-microamp", &led->full_scale_current)) dev_err(&priv->client->dev, "Failed getting led-max-microamp "); else led->full_scale_current = min(led->full_scale_current, LM3532_FS_CURR_MAX); |
517ea49a7 leds: lm3532: Add... |
602 |
|
bc1b8492c leds: lm3532: Int... |
603 |
if (led->mode == LM3532_BL_MODE_ALS) { |
6559ac329 leds: lm3532: Fix... |
604 |
led->mode = LM3532_ALS_CTRL; |
bc1b8492c leds: lm3532: Int... |
605 606 607 608 609 610 |
ret = lm3532_parse_als(priv); if (ret) dev_err(&priv->client->dev, "Failed to parse als "); else lm3532_als_configure(priv, led); |
6559ac329 leds: lm3532: Fix... |
611 612 |
} else { led->mode = LM3532_I2C_CTRL; |
bc1b8492c leds: lm3532: Int... |
613 |
} |
cc93c8637 leds: lm3532: Swi... |
614 |
led->num_leds = fwnode_property_count_u32(child, "led-sources"); |
bc1b8492c leds: lm3532: Int... |
615 |
if (led->num_leds > LM3532_MAX_LED_STRINGS) { |
31e065c4e leds: lm3532: add... |
616 617 |
dev_err(&priv->client->dev, "Too many LED string defined "); |
bc1b8492c leds: lm3532: Int... |
618 619 620 621 622 623 624 625 626 627 628 629 |
continue; } ret = fwnode_property_read_u32_array(child, "led-sources", led->led_strings, led->num_leds); if (ret) { dev_err(&priv->client->dev, "led-sources property missing "); fwnode_handle_put(child); goto child_out; } |
bc1b8492c leds: lm3532: Int... |
630 |
led->priv = priv; |
bc1b8492c leds: lm3532: Int... |
631 |
led->led_dev.brightness_set_blocking = lm3532_brightness_set; |
cf6eb52fa leds: lm3532: use... |
632 |
ret = devm_led_classdev_register_ext(priv->dev, &led->led_dev, &idata); |
bc1b8492c leds: lm3532: Int... |
633 634 635 636 637 638 639 |
if (ret) { dev_err(&priv->client->dev, "led register err: %d ", ret); fwnode_handle_put(child); goto child_out; } |
6559ac329 leds: lm3532: Fix... |
640 641 642 643 644 645 646 647 |
ret = lm3532_init_registers(led); if (ret) { dev_err(&priv->client->dev, "register init err: %d ", ret); fwnode_handle_put(child); goto child_out; } |
bc1b8492c leds: lm3532: Int... |
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 |
i++; } child_out: return ret; } static int lm3532_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct lm3532_data *drvdata; int ret = 0; int count; count = device_get_child_node_count(&client->dev); if (!count) { dev_err(&client->dev, "LEDs are not defined in device tree!"); return -ENODEV; } drvdata = devm_kzalloc(&client->dev, struct_size(drvdata, leds, count), GFP_KERNEL); if (drvdata == NULL) return -ENOMEM; drvdata->client = client; drvdata->dev = &client->dev; drvdata->regmap = devm_regmap_init_i2c(client, &lm3532_regmap_config); if (IS_ERR(drvdata->regmap)) { ret = PTR_ERR(drvdata->regmap); dev_err(&client->dev, "Failed to allocate register map: %d ", ret); return ret; } mutex_init(&drvdata->lock); i2c_set_clientdata(client, drvdata); ret = lm3532_parse_node(drvdata); if (ret) { dev_err(&client->dev, "Failed to parse node "); return ret; } |
bc1b8492c leds: lm3532: Int... |
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 |
return ret; } static int lm3532_remove(struct i2c_client *client) { struct lm3532_data *drvdata = i2c_get_clientdata(client); mutex_destroy(&drvdata->lock); if (drvdata->enable_gpio) gpiod_direction_output(drvdata->enable_gpio, 0); return 0; } static const struct of_device_id of_lm3532_leds_match[] = { { .compatible = "ti,lm3532", }, {}, }; MODULE_DEVICE_TABLE(of, of_lm3532_leds_match); static const struct i2c_device_id lm3532_id[] = { {LM3532_NAME, 0}, {} }; MODULE_DEVICE_TABLE(i2c, lm3532_id); static struct i2c_driver lm3532_i2c_driver = { .probe = lm3532_probe, .remove = lm3532_remove, .id_table = lm3532_id, .driver = { .name = LM3532_NAME, .of_match_table = of_lm3532_leds_match, }, }; module_i2c_driver(lm3532_i2c_driver); MODULE_DESCRIPTION("Back Light driver for LM3532"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>"); |