Lines Matching +full:led +full:- +full:8

1 // SPDX-License-Identifier: GPL-2.0
2 // TI LM3532 LED driver
3 // Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com/
16 #define LM3532_NAME "lm3532-led"
86 #define LM3532_BRT_VAL_ADJUST 8
89 #define LM3532_NUM_RAMP_VALS 8
90 #define LM3532_NUM_AVG_VALS 8
123 * @led_dev: led class device
125 * @control_bank: Control bank the LED is associated to
126 * @mode: Mode of the LED string
128 * @num_leds: Number of LED strings are supported in this array
129 * @full_scale_current: The full-scale current setting for the current sink.
130 * @led_strings: The LED strings supported in this array
157 * @leds: Array of LED strings
201 .reg_bits = 8,
202 .val_bits = 8,
225 if (als_imped < als_imp_table[LM3532_NUM_IMP_VALS - 1]) in lm3532_get_als_imp_index()
226 return LM3532_NUM_IMP_VALS - 1; in lm3532_get_als_imp_index()
233 if (als_imped < als_imp_table[i - 1] && in lm3532_get_als_imp_index()
235 if (als_imped - als_imp_table[i - 1] < in lm3532_get_als_imp_index()
236 als_imp_table[i] - als_imped) in lm3532_get_als_imp_index()
243 return -EINVAL; in lm3532_get_als_imp_index()
255 if (value > table[i - 1] && in lm3532_get_index()
257 if (value - table[i - 1] < table[i] - value) in lm3532_get_index()
258 return i - 1; in lm3532_get_index()
264 return -EINVAL; in lm3532_get_index()
275 if (avg_time > als_avrg_table[LM3532_NUM_AVG_VALS - 1]) in lm3532_get_als_avg_index()
276 return LM3532_NUM_AVG_VALS - 1; in lm3532_get_als_avg_index()
282 static const int ramp_table[LM3532_NUM_RAMP_VALS] = { 8, 1024, 2048, 4096, 8192,
289 if (ramp_time > ramp_table[LM3532_NUM_RAMP_VALS - 1]) in lm3532_get_ramp_index()
290 return LM3532_NUM_RAMP_VALS - 1; in lm3532_get_ramp_index()
299 int ctrl_en_val = BIT(led_data->control_bank); in lm3532_led_enable()
302 if (led_data->enabled) in lm3532_led_enable()
305 ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE, in lm3532_led_enable()
308 dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret); in lm3532_led_enable()
312 ret = regulator_enable(led_data->priv->regulator); in lm3532_led_enable()
316 led_data->enabled = 1; in lm3532_led_enable()
324 int ctrl_en_val = BIT(led_data->control_bank); in lm3532_led_disable()
327 if (!led_data->enabled) in lm3532_led_disable()
330 ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE, in lm3532_led_disable()
333 dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret); in lm3532_led_disable()
337 ret = regulator_disable(led_data->priv->regulator); in lm3532_led_disable()
341 led_data->enabled = 0; in lm3532_led_disable()
349 struct lm3532_led *led = in lm3532_brightness_set() local
354 mutex_lock(&led->priv->lock); in lm3532_brightness_set()
356 if (led->mode == LM3532_ALS_CTRL) { in lm3532_brightness_set()
358 ret = lm3532_led_enable(led); in lm3532_brightness_set()
360 ret = lm3532_led_disable(led); in lm3532_brightness_set()
366 ret = lm3532_led_disable(led); in lm3532_brightness_set()
370 ret = lm3532_led_enable(led); in lm3532_brightness_set()
374 brightness_reg = LM3532_REG_ZONE_TRGT_A + led->control_bank * 5 + in lm3532_brightness_set()
375 (led->ctrl_brt_pointer >> 2); in lm3532_brightness_set()
377 ret = regmap_write(led->priv->regmap, brightness_reg, brt_val); in lm3532_brightness_set()
380 mutex_unlock(&led->priv->lock); in lm3532_brightness_set()
384 static int lm3532_init_registers(struct lm3532_led *led) in lm3532_init_registers() argument
386 struct lm3532_data *drvdata = led->priv; in lm3532_init_registers()
397 if (drvdata->enable_gpio) in lm3532_init_registers()
398 gpiod_direction_output(drvdata->enable_gpio, 1); in lm3532_init_registers()
400 brightness_config_reg = LM3532_REG_ZONE_CFG_A + led->control_bank * 2; in lm3532_init_registers()
405 ret = regmap_read(drvdata->regmap, brightness_config_reg, in lm3532_init_registers()
406 &led->ctrl_brt_pointer); in lm3532_init_registers()
410 led->ctrl_brt_pointer &= LM3532_ZONE_MASK; in lm3532_init_registers()
411 brightness_config_val = led->ctrl_brt_pointer | led->mode; in lm3532_init_registers()
412 ret = regmap_write(drvdata->regmap, brightness_config_reg, in lm3532_init_registers()
417 if (led->full_scale_current) { in lm3532_init_registers()
418 fs_current_reg = LM3532_REG_CTRL_A_FS_CURR + led->control_bank * 2; in lm3532_init_registers()
419 fs_current_val = (led->full_scale_current - LM3532_FS_CURR_MIN) / in lm3532_init_registers()
422 ret = regmap_write(drvdata->regmap, fs_current_reg, in lm3532_init_registers()
428 for (i = 0; i < led->num_leds; i++) { in lm3532_init_registers()
429 output_cfg_shift = led->led_strings[i] * 2; in lm3532_init_registers()
430 output_cfg_val |= (led->control_bank << output_cfg_shift); in lm3532_init_registers()
434 ret = regmap_update_bits(drvdata->regmap, LM3532_REG_OUTPUT_CFG, in lm3532_init_registers()
439 runtime_ramp_val = drvdata->runtime_ramp_up | in lm3532_init_registers()
440 (drvdata->runtime_ramp_down << LM3532_RAMP_DOWN_SHIFT); in lm3532_init_registers()
442 return regmap_write(drvdata->regmap, LM3532_REG_RT_RAMP, in lm3532_init_registers()
447 struct lm3532_led *led) in lm3532_als_configure() argument
449 struct lm3532_als_data *als = priv->als_data; in lm3532_als_configure()
455 als_vmin = als->als_vmin; in lm3532_als_configure()
456 als_vmax = als->als_vmax; in lm3532_als_configure()
458 als_vstep = (als_vmax - als_vmin) / ((LM3532_ALS_ZB_MAX + 1) * 2); in lm3532_als_configure()
461 als->zones_lo[i] = ((als_vmin + als_vstep + (i * als_vstep)) * in lm3532_als_configure()
463 als->zones_hi[i] = ((als_vmin + LM3532_ALS_OFFSET_mV + in lm3532_als_configure()
467 ret = regmap_write(priv->regmap, zone_reg, als->zones_lo[i]); in lm3532_als_configure()
472 ret = regmap_write(priv->regmap, zone_reg, als->zones_hi[i]); in lm3532_als_configure()
477 als->config = (als->als_avrg_time | (LM3532_ENABLE_ALS) | in lm3532_als_configure()
478 (als->als_input_mode << LM3532_ALS_SEL_SHIFT)); in lm3532_als_configure()
480 return regmap_write(priv->regmap, LM3532_ALS_CONFIG, als->config); in lm3532_als_configure()
490 als = devm_kzalloc(priv->dev, sizeof(*als), GFP_KERNEL); in lm3532_parse_als()
492 return -ENOMEM; in lm3532_parse_als()
494 ret = device_property_read_u32(&priv->client->dev, "ti,als-vmin", in lm3532_parse_als()
495 &als->als_vmin); in lm3532_parse_als()
497 als->als_vmin = 0; in lm3532_parse_als()
499 ret = device_property_read_u32(&priv->client->dev, "ti,als-vmax", in lm3532_parse_als()
500 &als->als_vmax); in lm3532_parse_als()
502 als->als_vmax = LM3532_ALS_WINDOW_mV; in lm3532_parse_als()
504 if (als->als_vmax > LM3532_ALS_WINDOW_mV) { in lm3532_parse_als()
505 ret = -EINVAL; in lm3532_parse_als()
509 ret = device_property_read_u32(&priv->client->dev, "ti,als1-imp-sel", in lm3532_parse_als()
512 als->als1_imp_sel = 0; in lm3532_parse_als()
514 als->als1_imp_sel = lm3532_get_als_imp_index(als_impedance); in lm3532_parse_als()
516 ret = device_property_read_u32(&priv->client->dev, "ti,als2-imp-sel", in lm3532_parse_als()
519 als->als2_imp_sel = 0; in lm3532_parse_als()
521 als->als2_imp_sel = lm3532_get_als_imp_index(als_impedance); in lm3532_parse_als()
523 ret = device_property_read_u32(&priv->client->dev, "ti,als-avrg-time-us", in lm3532_parse_als()
526 als->als_avrg_time = 0; in lm3532_parse_als()
528 als->als_avrg_time = lm3532_get_als_avg_index(als_avg_time); in lm3532_parse_als()
530 ret = device_property_read_u8(&priv->client->dev, "ti,als-input-mode", in lm3532_parse_als()
531 &als->als_input_mode); in lm3532_parse_als()
533 als->als_input_mode = 0; in lm3532_parse_als()
535 if (als->als_input_mode > LM3532_BL_MODE_ALS) { in lm3532_parse_als()
536 ret = -EINVAL; in lm3532_parse_als()
540 priv->als_data = als; in lm3532_parse_als()
548 struct lm3532_led *led; in lm3532_parse_node() local
554 priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev, in lm3532_parse_node()
556 if (IS_ERR(priv->enable_gpio)) in lm3532_parse_node()
557 priv->enable_gpio = NULL; in lm3532_parse_node()
559 priv->regulator = devm_regulator_get(&priv->client->dev, "vin"); in lm3532_parse_node()
560 if (IS_ERR(priv->regulator)) in lm3532_parse_node()
561 priv->regulator = NULL; in lm3532_parse_node()
563 ret = device_property_read_u32(&priv->client->dev, "ramp-up-us", in lm3532_parse_node()
566 dev_info(&priv->client->dev, "ramp-up-ms property missing\n"); in lm3532_parse_node()
568 priv->runtime_ramp_up = lm3532_get_ramp_index(ramp_time); in lm3532_parse_node()
570 ret = device_property_read_u32(&priv->client->dev, "ramp-down-us", in lm3532_parse_node()
573 dev_info(&priv->client->dev, "ramp-down-ms property missing\n"); in lm3532_parse_node()
575 priv->runtime_ramp_down = lm3532_get_ramp_index(ramp_time); in lm3532_parse_node()
577 device_for_each_child_node(priv->dev, child) { in lm3532_parse_node()
581 .devicename = priv->client->name, in lm3532_parse_node()
584 led = &priv->leds[i]; in lm3532_parse_node()
588 dev_err(&priv->client->dev, "reg property missing\n"); in lm3532_parse_node()
594 dev_err(&priv->client->dev, "Control bank invalid\n"); in lm3532_parse_node()
598 led->control_bank = control_bank; in lm3532_parse_node()
600 ret = fwnode_property_read_u32(child, "ti,led-mode", in lm3532_parse_node()
601 &led->mode); in lm3532_parse_node()
603 dev_err(&priv->client->dev, "ti,led-mode property missing\n"); in lm3532_parse_node()
608 if (fwnode_property_present(child, "led-max-microamp") && in lm3532_parse_node()
609 fwnode_property_read_u32(child, "led-max-microamp", in lm3532_parse_node()
610 &led->full_scale_current)) in lm3532_parse_node()
611 dev_err(&priv->client->dev, in lm3532_parse_node()
612 "Failed getting led-max-microamp\n"); in lm3532_parse_node()
614 led->full_scale_current = min(led->full_scale_current, in lm3532_parse_node()
617 if (led->mode == LM3532_BL_MODE_ALS) { in lm3532_parse_node()
618 led->mode = LM3532_ALS_CTRL; in lm3532_parse_node()
621 dev_err(&priv->client->dev, "Failed to parse als\n"); in lm3532_parse_node()
623 lm3532_als_configure(priv, led); in lm3532_parse_node()
625 led->mode = LM3532_I2C_CTRL; in lm3532_parse_node()
628 led->num_leds = fwnode_property_count_u32(child, "led-sources"); in lm3532_parse_node()
629 if (led->num_leds > LM3532_MAX_LED_STRINGS) { in lm3532_parse_node()
630 dev_err(&priv->client->dev, "Too many LED string defined\n"); in lm3532_parse_node()
634 ret = fwnode_property_read_u32_array(child, "led-sources", in lm3532_parse_node()
635 led->led_strings, in lm3532_parse_node()
636 led->num_leds); in lm3532_parse_node()
638 dev_err(&priv->client->dev, "led-sources property missing\n"); in lm3532_parse_node()
643 led->priv = priv; in lm3532_parse_node()
644 led->led_dev.brightness_set_blocking = lm3532_brightness_set; in lm3532_parse_node()
646 ret = devm_led_classdev_register_ext(priv->dev, &led->led_dev, &idata); in lm3532_parse_node()
648 dev_err(&priv->client->dev, "led register err: %d\n", in lm3532_parse_node()
654 ret = lm3532_init_registers(led); in lm3532_parse_node()
656 dev_err(&priv->client->dev, "register init err: %d\n", in lm3532_parse_node()
676 count = device_get_child_node_count(&client->dev); in lm3532_probe()
678 dev_err(&client->dev, "LEDs are not defined in device tree!"); in lm3532_probe()
679 return -ENODEV; in lm3532_probe()
682 drvdata = devm_kzalloc(&client->dev, struct_size(drvdata, leds, count), in lm3532_probe()
685 return -ENOMEM; in lm3532_probe()
687 drvdata->client = client; in lm3532_probe()
688 drvdata->dev = &client->dev; in lm3532_probe()
690 drvdata->regmap = devm_regmap_init_i2c(client, &lm3532_regmap_config); in lm3532_probe()
691 if (IS_ERR(drvdata->regmap)) { in lm3532_probe()
692 ret = PTR_ERR(drvdata->regmap); in lm3532_probe()
693 dev_err(&client->dev, "Failed to allocate register map: %d\n", in lm3532_probe()
698 mutex_init(&drvdata->lock); in lm3532_probe()
703 dev_err(&client->dev, "Failed to parse node\n"); in lm3532_probe()
714 mutex_destroy(&drvdata->lock); in lm3532_remove()
716 if (drvdata->enable_gpio) in lm3532_remove()
717 gpiod_direction_output(drvdata->enable_gpio, 0); in lm3532_remove()