1 // SPDX-License-Identifier: GPL-2.0-only
3 * LED driver : leds-ktd2692.c
5 * Copyright (C) 2015 Samsung Electronics
6 * Ingi Kim <ingi2.kim@samsung.com>
9 #include <linux/cleanup.h>
10 #include <linux/err.h>
11 #include <linux/gpio/consumer.h>
12 #include <linux/leds-expresswire.h>
13 #include <linux/led-class-flash.h>
14 #include <linux/module.h>
15 #include <linux/mutex.h>
17 #include <linux/platform_device.h>
18 #include <linux/regulator/consumer.h>
20 /* Value related the movie mode */
21 #define KTD2692_MOVIE_MODE_CURRENT_LEVELS 16
22 #define KTD2692_MM_TO_FL_RATIO(x) ((x) / 3)
23 #define KTD2692_MM_MIN_CURR_THRESHOLD_SCALE 8
25 /* Value related the flash mode */
26 #define KTD2692_FLASH_MODE_TIMEOUT_LEVELS 8
27 #define KTD2692_FLASH_MODE_TIMEOUT_DISABLE 0
28 #define KTD2692_FLASH_MODE_CURR_PERCENT(x) (((x) * 16) / 100)
30 /* Macro for getting offset of flash timeout */
31 #define GET_TIMEOUT_OFFSET(timeout, step) ((timeout) / (step))
33 /* Base register address */
34 #define KTD2692_REG_LVP_BASE 0x00
35 #define KTD2692_REG_FLASH_TIMEOUT_BASE 0x20
36 #define KTD2692_REG_MM_MIN_CURR_THRESHOLD_BASE 0x40
37 #define KTD2692_REG_MOVIE_CURRENT_BASE 0x60
38 #define KTD2692_REG_FLASH_CURRENT_BASE 0x80
39 #define KTD2692_REG_MODE_BASE 0xA0
41 /* KTD2692 default length of name */
42 #define KTD2692_NAME_LENGTH 20
44 /* Movie / Flash Mode Control */
45 enum ktd2692_led_mode
{
46 KTD2692_MODE_DISABLE
= 0, /* default */
51 struct ktd2692_led_config_data
{
52 /* maximum LED current in movie mode */
53 u32 movie_max_microamp
;
54 /* maximum LED current in flash mode */
55 u32 flash_max_microamp
;
56 /* maximum flash timeout */
57 u32 flash_max_timeout
;
58 /* max LED brightness level */
59 enum led_brightness max_brightness
;
62 const struct expresswire_timing ktd2692_timing
= {
65 .end_of_data_low_us
= 10,
66 .end_of_data_high_us
= 350,
71 struct ktd2692_context
{
72 /* Common ExpressWire properties (ctrl GPIO and timing) */
73 struct expresswire_common_props props
;
75 /* Related LED Flash class device */
76 struct led_classdev_flash fled_cdev
;
78 /* secures access to the device */
80 struct regulator
*regulator
;
82 struct gpio_desc
*aux_gpio
;
84 enum ktd2692_led_mode mode
;
85 enum led_brightness torch_brightness
;
88 static struct ktd2692_context
*fled_cdev_to_led(
89 struct led_classdev_flash
*fled_cdev
)
91 return container_of(fled_cdev
, struct ktd2692_context
, fled_cdev
);
94 static int ktd2692_led_brightness_set(struct led_classdev
*led_cdev
,
95 enum led_brightness brightness
)
97 struct led_classdev_flash
*fled_cdev
= lcdev_to_flcdev(led_cdev
);
98 struct ktd2692_context
*led
= fled_cdev_to_led(fled_cdev
);
100 mutex_lock(&led
->lock
);
102 if (brightness
== LED_OFF
) {
103 led
->mode
= KTD2692_MODE_DISABLE
;
104 gpiod_direction_output(led
->aux_gpio
, 0);
106 expresswire_write_u8(&led
->props
, brightness
|
107 KTD2692_REG_MOVIE_CURRENT_BASE
);
108 led
->mode
= KTD2692_MODE_MOVIE
;
111 expresswire_write_u8(&led
->props
, led
->mode
| KTD2692_REG_MODE_BASE
);
112 mutex_unlock(&led
->lock
);
117 static int ktd2692_led_flash_strobe_set(struct led_classdev_flash
*fled_cdev
,
120 struct ktd2692_context
*led
= fled_cdev_to_led(fled_cdev
);
121 struct led_flash_setting
*timeout
= &fled_cdev
->timeout
;
124 mutex_lock(&led
->lock
);
127 flash_tm_reg
= GET_TIMEOUT_OFFSET(timeout
->val
, timeout
->step
);
128 expresswire_write_u8(&led
->props
, flash_tm_reg
129 | KTD2692_REG_FLASH_TIMEOUT_BASE
);
131 led
->mode
= KTD2692_MODE_FLASH
;
132 gpiod_direction_output(led
->aux_gpio
, 1);
134 led
->mode
= KTD2692_MODE_DISABLE
;
135 gpiod_direction_output(led
->aux_gpio
, 0);
138 expresswire_write_u8(&led
->props
, led
->mode
| KTD2692_REG_MODE_BASE
);
140 fled_cdev
->led_cdev
.brightness
= LED_OFF
;
141 led
->mode
= KTD2692_MODE_DISABLE
;
143 mutex_unlock(&led
->lock
);
148 static int ktd2692_led_flash_timeout_set(struct led_classdev_flash
*fled_cdev
,
154 static void ktd2692_init_movie_current_max(struct ktd2692_led_config_data
*cfg
)
157 u32 movie_current_microamp
;
159 offset
= KTD2692_MOVIE_MODE_CURRENT_LEVELS
;
160 step
= KTD2692_MM_TO_FL_RATIO(cfg
->flash_max_microamp
)
161 / KTD2692_MOVIE_MODE_CURRENT_LEVELS
;
164 movie_current_microamp
= step
* offset
;
166 } while ((movie_current_microamp
> cfg
->movie_max_microamp
) &&
169 cfg
->max_brightness
= offset
;
172 static void ktd2692_init_flash_timeout(struct led_classdev_flash
*fled_cdev
,
173 struct ktd2692_led_config_data
*cfg
)
175 struct led_flash_setting
*setting
;
177 setting
= &fled_cdev
->timeout
;
178 setting
->min
= KTD2692_FLASH_MODE_TIMEOUT_DISABLE
;
179 setting
->max
= cfg
->flash_max_timeout
;
180 setting
->step
= cfg
->flash_max_timeout
181 / (KTD2692_FLASH_MODE_TIMEOUT_LEVELS
- 1);
182 setting
->val
= cfg
->flash_max_timeout
;
185 static void ktd2692_setup(struct ktd2692_context
*led
)
187 led
->mode
= KTD2692_MODE_DISABLE
;
188 expresswire_power_off(&led
->props
);
189 gpiod_direction_output(led
->aux_gpio
, 0);
191 expresswire_write_u8(&led
->props
, (KTD2692_MM_MIN_CURR_THRESHOLD_SCALE
- 1)
192 | KTD2692_REG_MM_MIN_CURR_THRESHOLD_BASE
);
193 expresswire_write_u8(&led
->props
, KTD2692_FLASH_MODE_CURR_PERCENT(45)
194 | KTD2692_REG_FLASH_CURRENT_BASE
);
197 static void regulator_disable_action(void *_data
)
199 struct device
*dev
= _data
;
200 struct ktd2692_context
*led
= dev_get_drvdata(dev
);
203 ret
= regulator_disable(led
->regulator
);
205 dev_err(dev
, "Failed to disable supply: %d\n", ret
);
208 static int ktd2692_parse_dt(struct ktd2692_context
*led
, struct device
*dev
,
209 struct ktd2692_led_config_data
*cfg
)
211 struct device_node
*np
= dev_of_node(dev
);
217 led
->props
.ctrl_gpio
= devm_gpiod_get(dev
, "ctrl", GPIOD_ASIS
);
218 ret
= PTR_ERR_OR_ZERO(led
->props
.ctrl_gpio
);
220 return dev_err_probe(dev
, ret
, "cannot get ctrl-gpios\n");
222 led
->aux_gpio
= devm_gpiod_get_optional(dev
, "aux", GPIOD_ASIS
);
223 if (IS_ERR(led
->aux_gpio
))
224 return dev_err_probe(dev
, PTR_ERR(led
->aux_gpio
), "cannot get aux-gpios\n");
226 led
->regulator
= devm_regulator_get(dev
, "vin");
227 if (IS_ERR(led
->regulator
))
228 led
->regulator
= NULL
;
230 if (led
->regulator
) {
231 ret
= regulator_enable(led
->regulator
);
233 dev_err(dev
, "Failed to enable supply: %d\n", ret
);
235 ret
= devm_add_action_or_reset(dev
,
236 regulator_disable_action
, dev
);
242 struct device_node
*child_node
__free(device_node
) =
243 of_get_next_available_child(np
, NULL
);
245 dev_err(dev
, "No DT child node found for connected LED.\n");
249 led
->fled_cdev
.led_cdev
.name
=
250 of_get_property(child_node
, "label", NULL
) ? : child_node
->name
;
252 ret
= of_property_read_u32(child_node
, "led-max-microamp",
253 &cfg
->movie_max_microamp
);
255 dev_err(dev
, "failed to parse led-max-microamp\n");
259 ret
= of_property_read_u32(child_node
, "flash-max-microamp",
260 &cfg
->flash_max_microamp
);
262 dev_err(dev
, "failed to parse flash-max-microamp\n");
266 ret
= of_property_read_u32(child_node
, "flash-max-timeout-us",
267 &cfg
->flash_max_timeout
);
269 dev_err(dev
, "failed to parse flash-max-timeout-us\n");
276 static const struct led_flash_ops flash_ops
= {
277 .strobe_set
= ktd2692_led_flash_strobe_set
,
278 .timeout_set
= ktd2692_led_flash_timeout_set
,
281 static int ktd2692_probe(struct platform_device
*pdev
)
283 struct ktd2692_context
*led
;
284 struct led_classdev
*led_cdev
;
285 struct led_classdev_flash
*fled_cdev
;
286 struct ktd2692_led_config_data led_cfg
;
289 led
= devm_kzalloc(&pdev
->dev
, sizeof(*led
), GFP_KERNEL
);
293 fled_cdev
= &led
->fled_cdev
;
294 led_cdev
= &fled_cdev
->led_cdev
;
295 led
->props
.timing
= ktd2692_timing
;
297 ret
= ktd2692_parse_dt(led
, &pdev
->dev
, &led_cfg
);
301 ktd2692_init_flash_timeout(fled_cdev
, &led_cfg
);
302 ktd2692_init_movie_current_max(&led_cfg
);
304 fled_cdev
->ops
= &flash_ops
;
306 led_cdev
->max_brightness
= led_cfg
.max_brightness
;
307 led_cdev
->brightness_set_blocking
= ktd2692_led_brightness_set
;
308 led_cdev
->flags
|= LED_CORE_SUSPENDRESUME
| LED_DEV_CAP_FLASH
;
310 mutex_init(&led
->lock
);
312 platform_set_drvdata(pdev
, led
);
314 ret
= led_classdev_flash_register(&pdev
->dev
, fled_cdev
);
316 dev_err(&pdev
->dev
, "can't register LED %s\n", led_cdev
->name
);
317 mutex_destroy(&led
->lock
);
326 static void ktd2692_remove(struct platform_device
*pdev
)
328 struct ktd2692_context
*led
= platform_get_drvdata(pdev
);
330 led_classdev_flash_unregister(&led
->fled_cdev
);
332 mutex_destroy(&led
->lock
);
335 static const struct of_device_id ktd2692_match
[] = {
336 { .compatible
= "kinetic,ktd2692", },
339 MODULE_DEVICE_TABLE(of
, ktd2692_match
);
341 static struct platform_driver ktd2692_driver
= {
344 .of_match_table
= ktd2692_match
,
346 .probe
= ktd2692_probe
,
347 .remove
= ktd2692_remove
,
350 module_platform_driver(ktd2692_driver
);
352 MODULE_IMPORT_NS("EXPRESSWIRE");
353 MODULE_AUTHOR("Ingi Kim <ingi2.kim@samsung.com>");
354 MODULE_DESCRIPTION("Kinetic KTD2692 LED driver");
355 MODULE_LICENSE("GPL v2");