Lines Matching +full:flash +full:- +full:led
1 // SPDX-License-Identifier: GPL-2.0
2 // Flash and torch driver for Texas Instruments LM3601X LED
3 // Flash driver chip family
4 // Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
9 #include <linux/led-class-flash.h>
73 * struct lm3601x_led - private lm3601x LED data
74 * @fled_cdev: flash LED class device pointer
78 * @flash_timeout: the timeout for the flash
81 * @flash_current_max: maximum current for the flash
82 * @max_flash_timeout: maximum timeout for the flash
134 static int lm3601x_read_faults(struct lm3601x_led *led) in lm3601x_read_faults() argument
139 ret = regmap_read(led->regmap, LM3601X_FLAGS_REG, &flags_val); in lm3601x_read_faults()
141 return -EIO; in lm3601x_read_faults()
143 led->last_flag = 0; in lm3601x_read_faults()
146 led->last_flag |= LED_FAULT_OVER_VOLTAGE; in lm3601x_read_faults()
149 led->last_flag |= LED_FAULT_OVER_TEMPERATURE; in lm3601x_read_faults()
152 led->last_flag |= LED_FAULT_SHORT_CIRCUIT; in lm3601x_read_faults()
155 led->last_flag |= LED_FAULT_OVER_CURRENT; in lm3601x_read_faults()
158 led->last_flag |= LED_FAULT_UNDER_VOLTAGE; in lm3601x_read_faults()
161 led->last_flag |= LED_FAULT_INPUT_VOLTAGE; in lm3601x_read_faults()
164 led->last_flag |= LED_FAULT_LED_OVER_TEMPERATURE; in lm3601x_read_faults()
166 return led->last_flag; in lm3601x_read_faults()
173 struct lm3601x_led *led = fled_cdev_to_led(fled_cdev); in lm3601x_brightness_set() local
176 mutex_lock(&led->lock); in lm3601x_brightness_set()
178 ret = lm3601x_read_faults(led); in lm3601x_brightness_set()
182 if (led->led_mode == LM3601X_LED_TORCH) in lm3601x_brightness_set()
188 ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG, in lm3601x_brightness_set()
193 ret = regmap_write(led->regmap, LM3601X_LED_TORCH_REG, brightness - 1); in lm3601x_brightness_set()
197 ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG, in lm3601x_brightness_set()
201 mutex_unlock(&led->lock); in lm3601x_brightness_set()
208 struct lm3601x_led *led = fled_cdev_to_led(fled_cdev); in lm3601x_strobe_set() local
213 mutex_lock(&led->lock); in lm3601x_strobe_set()
215 ret = regmap_read(led->regmap, LM3601X_CFG_REG, ¤t_timeout); in lm3601x_strobe_set()
219 if (led->flash_timeout >= LM3601X_TIMEOUT_XOVER_US) in lm3601x_strobe_set()
220 timeout_reg_val = led->flash_timeout / LM3601X_UPPER_STEP_US + 0x07; in lm3601x_strobe_set()
222 timeout_reg_val = led->flash_timeout / LM3601X_LOWER_STEP_US - 0x01; in lm3601x_strobe_set()
224 if (led->flash_timeout != current_timeout) in lm3601x_strobe_set()
225 ret = regmap_update_bits(led->regmap, LM3601X_CFG_REG, in lm3601x_strobe_set()
229 ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG, in lm3601x_strobe_set()
233 ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG, in lm3601x_strobe_set()
236 ret = lm3601x_read_faults(led); in lm3601x_strobe_set()
238 mutex_unlock(&led->lock); in lm3601x_strobe_set()
245 struct lm3601x_led *led = fled_cdev_to_led(fled_cdev); in lm3601x_flash_brightness_set() local
249 mutex_lock(&led->lock); in lm3601x_flash_brightness_set()
250 ret = lm3601x_read_faults(led); in lm3601x_flash_brightness_set()
255 ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG, in lm3601x_flash_brightness_set()
262 ret = regmap_write(led->regmap, LM3601X_LED_FLASH_REG, brightness_val); in lm3601x_flash_brightness_set()
264 mutex_unlock(&led->lock); in lm3601x_flash_brightness_set()
271 struct lm3601x_led *led = fled_cdev_to_led(fled_cdev); in lm3601x_flash_timeout_set() local
273 mutex_lock(&led->lock); in lm3601x_flash_timeout_set()
275 led->flash_timeout = timeout; in lm3601x_flash_timeout_set()
277 mutex_unlock(&led->lock); in lm3601x_flash_timeout_set()
284 struct lm3601x_led *led = fled_cdev_to_led(fled_cdev); in lm3601x_strobe_get() local
288 mutex_lock(&led->lock); in lm3601x_strobe_get()
290 ret = regmap_read(led->regmap, LM3601X_ENABLE_REG, &strobe_state); in lm3601x_strobe_get()
297 mutex_unlock(&led->lock); in lm3601x_strobe_get()
304 struct lm3601x_led *led = fled_cdev_to_led(fled_cdev); in lm3601x_flash_fault_get() local
306 lm3601x_read_faults(led); in lm3601x_flash_fault_get()
308 *fault = led->last_flag; in lm3601x_flash_fault_get()
321 static int lm3601x_register_leds(struct lm3601x_led *led, in lm3601x_register_leds() argument
328 led->fled_cdev.ops = &flash_ops; in lm3601x_register_leds()
330 setting = &led->fled_cdev.timeout; in lm3601x_register_leds()
331 setting->min = LM3601X_MIN_TIMEOUT_US; in lm3601x_register_leds()
332 setting->max = led->max_flash_timeout; in lm3601x_register_leds()
333 setting->step = LM3601X_LOWER_STEP_US; in lm3601x_register_leds()
334 setting->val = led->max_flash_timeout; in lm3601x_register_leds()
336 setting = &led->fled_cdev.brightness; in lm3601x_register_leds()
337 setting->min = LM3601X_MIN_STROBE_I_UA; in lm3601x_register_leds()
338 setting->max = led->flash_current_max; in lm3601x_register_leds()
339 setting->step = LM3601X_TORCH_REG_DIV; in lm3601x_register_leds()
340 setting->val = led->flash_current_max; in lm3601x_register_leds()
342 led_cdev = &led->fled_cdev.led_cdev; in lm3601x_register_leds()
343 led_cdev->brightness_set_blocking = lm3601x_brightness_set; in lm3601x_register_leds()
344 led_cdev->max_brightness = in lm3601x_register_leds()
345 DIV_ROUND_UP(led->torch_current_max - LM3601X_MIN_TORCH_I_UA + 1, in lm3601x_register_leds()
347 led_cdev->flags |= LED_DEV_CAP_FLASH; in lm3601x_register_leds()
350 init_data.devicename = led->client->name; in lm3601x_register_leds()
351 init_data.default_label = (led->led_mode == LM3601X_LED_TORCH) ? in lm3601x_register_leds()
353 return devm_led_classdev_flash_register_ext(&led->client->dev, in lm3601x_register_leds()
354 &led->fled_cdev, &init_data); in lm3601x_register_leds()
357 static int lm3601x_parse_node(struct lm3601x_led *led, in lm3601x_parse_node() argument
361 int ret = -ENODEV; in lm3601x_parse_node()
363 child = device_get_next_child_node(&led->client->dev, child); in lm3601x_parse_node()
365 dev_err(&led->client->dev, "No LED Child node\n"); in lm3601x_parse_node()
369 ret = fwnode_property_read_u32(child, "reg", &led->led_mode); in lm3601x_parse_node()
371 dev_err(&led->client->dev, "reg DT property missing\n"); in lm3601x_parse_node()
375 if (led->led_mode > LM3601X_LED_TORCH || in lm3601x_parse_node()
376 led->led_mode < LM3601X_LED_IR) { in lm3601x_parse_node()
377 dev_warn(&led->client->dev, "Invalid led mode requested\n"); in lm3601x_parse_node()
378 ret = -EINVAL; in lm3601x_parse_node()
382 ret = fwnode_property_read_u32(child, "led-max-microamp", in lm3601x_parse_node()
383 &led->torch_current_max); in lm3601x_parse_node()
385 dev_warn(&led->client->dev, in lm3601x_parse_node()
386 "led-max-microamp DT property missing\n"); in lm3601x_parse_node()
390 if (led->torch_current_max > LM3601X_MAX_TORCH_I_UA) { in lm3601x_parse_node()
391 dev_warn(&led->client->dev, in lm3601x_parse_node()
393 led->torch_current_max, in lm3601x_parse_node()
395 led->torch_current_max = LM3601X_MAX_TORCH_I_UA; in lm3601x_parse_node()
398 ret = fwnode_property_read_u32(child, "flash-max-microamp", in lm3601x_parse_node()
399 &led->flash_current_max); in lm3601x_parse_node()
401 dev_warn(&led->client->dev, in lm3601x_parse_node()
402 "flash-max-microamp DT property missing\n"); in lm3601x_parse_node()
406 ret = fwnode_property_read_u32(child, "flash-max-timeout-us", in lm3601x_parse_node()
407 &led->max_flash_timeout); in lm3601x_parse_node()
409 dev_warn(&led->client->dev, in lm3601x_parse_node()
410 "flash-max-timeout-us DT property missing\n"); in lm3601x_parse_node()
423 struct lm3601x_led *led; in lm3601x_probe() local
427 led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL); in lm3601x_probe()
428 if (!led) in lm3601x_probe()
429 return -ENOMEM; in lm3601x_probe()
431 led->client = client; in lm3601x_probe()
432 i2c_set_clientdata(client, led); in lm3601x_probe()
434 ret = lm3601x_parse_node(led, &fwnode); in lm3601x_probe()
436 return -ENODEV; in lm3601x_probe()
438 led->regmap = devm_regmap_init_i2c(client, &lm3601x_regmap); in lm3601x_probe()
439 if (IS_ERR(led->regmap)) { in lm3601x_probe()
440 ret = PTR_ERR(led->regmap); in lm3601x_probe()
441 dev_err(&client->dev, in lm3601x_probe()
446 ret = regmap_write(led->regmap, LM3601X_DEV_ID_REG, LM3601X_SW_RESET); in lm3601x_probe()
448 dev_warn(&client->dev, "Failed to reset the LED controller\n"); in lm3601x_probe()
450 mutex_init(&led->lock); in lm3601x_probe()
452 return lm3601x_register_leds(led, fwnode); in lm3601x_probe()
457 struct lm3601x_led *led = i2c_get_clientdata(client); in lm3601x_remove() local
460 ret = regmap_update_bits(led->regmap, LM3601X_ENABLE_REG, in lm3601x_remove()
463 dev_warn(&client->dev, in lm3601x_remove()
492 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3601X");