2 * LED driver : leds-ktd2692.c
4 * Copyright (C) 2015 Samsung Electronics
5 * Ingi Kim <ingi2.kim@samsung.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/delay.h>
13 #include <linux/err.h>
14 #include <linux/gpio/consumer.h>
15 #include <linux/led-class-flash.h>
16 #include <linux/module.h>
17 #include <linux/mutex.h>
19 #include <linux/platform_device.h>
20 #include <linux/regulator/consumer.h>
21 #include <linux/workqueue.h>
23 /* Value related the movie mode */
24 #define KTD2692_MOVIE_MODE_CURRENT_LEVELS 16
25 #define KTD2692_MM_TO_FL_RATIO(x) ((x) / 3)
26 #define KTD2962_MM_MIN_CURR_THRESHOLD_SCALE 8
28 /* Value related the flash mode */
29 #define KTD2692_FLASH_MODE_TIMEOUT_LEVELS 8
30 #define KTD2692_FLASH_MODE_TIMEOUT_DISABLE 0
31 #define KTD2692_FLASH_MODE_CURR_PERCENT(x) (((x) * 16) / 100)
33 /* Macro for getting offset of flash timeout */
34 #define GET_TIMEOUT_OFFSET(timeout, step) ((timeout) / (step))
36 /* Base register address */
37 #define KTD2692_REG_LVP_BASE 0x00
38 #define KTD2692_REG_FLASH_TIMEOUT_BASE 0x20
39 #define KTD2692_REG_MM_MIN_CURR_THRESHOLD_BASE 0x40
40 #define KTD2692_REG_MOVIE_CURRENT_BASE 0x60
41 #define KTD2692_REG_FLASH_CURRENT_BASE 0x80
42 #define KTD2692_REG_MODE_BASE 0xA0
44 /* Set bit coding time for expresswire interface */
45 #define KTD2692_TIME_RESET_US 700
46 #define KTD2692_TIME_DATA_START_TIME_US 10
47 #define KTD2692_TIME_HIGH_END_OF_DATA_US 350
48 #define KTD2692_TIME_LOW_END_OF_DATA_US 10
49 #define KTD2692_TIME_SHORT_BITSET_US 4
50 #define KTD2692_TIME_LONG_BITSET_US 12
52 /* KTD2692 default length of name */
53 #define KTD2692_NAME_LENGTH 20
60 /* Movie / Flash Mode Control */
61 enum ktd2692_led_mode
{
62 KTD2692_MODE_DISABLE
= 0, /* default */
67 struct ktd2692_led_config_data
{
68 /* maximum LED current in movie mode */
69 u32 movie_max_microamp
;
70 /* maximum LED current in flash mode */
71 u32 flash_max_microamp
;
72 /* maximum flash timeout */
73 u32 flash_max_timeout
;
74 /* max LED brightness level */
75 enum led_brightness max_brightness
;
78 struct ktd2692_context
{
79 /* Related LED Flash class device */
80 struct led_classdev_flash fled_cdev
;
82 /* secures access to the device */
84 struct regulator
*regulator
;
85 struct work_struct work_brightness_set
;
87 struct gpio_desc
*aux_gpio
;
88 struct gpio_desc
*ctrl_gpio
;
90 enum ktd2692_led_mode mode
;
91 enum led_brightness torch_brightness
;
94 static struct ktd2692_context
*fled_cdev_to_led(
95 struct led_classdev_flash
*fled_cdev
)
97 return container_of(fled_cdev
, struct ktd2692_context
, fled_cdev
);
100 static void ktd2692_expresswire_start(struct ktd2692_context
*led
)
102 gpiod_direction_output(led
->ctrl_gpio
, KTD2692_HIGH
);
103 udelay(KTD2692_TIME_DATA_START_TIME_US
);
106 static void ktd2692_expresswire_reset(struct ktd2692_context
*led
)
108 gpiod_direction_output(led
->ctrl_gpio
, KTD2692_LOW
);
109 udelay(KTD2692_TIME_RESET_US
);
112 static void ktd2692_expresswire_end(struct ktd2692_context
*led
)
114 gpiod_direction_output(led
->ctrl_gpio
, KTD2692_LOW
);
115 udelay(KTD2692_TIME_LOW_END_OF_DATA_US
);
116 gpiod_direction_output(led
->ctrl_gpio
, KTD2692_HIGH
);
117 udelay(KTD2692_TIME_HIGH_END_OF_DATA_US
);
120 static void ktd2692_expresswire_set_bit(struct ktd2692_context
*led
, bool bit
)
123 * The Low Bit(0) and High Bit(1) is based on a time detection
124 * algorithm between time low and time high
125 * Time_(L_LB) : Low time of the Low Bit(0)
126 * Time_(H_LB) : High time of the LOW Bit(0)
127 * Time_(L_HB) : Low time of the High Bit(1)
128 * Time_(H_HB) : High time of the High Bit(1)
130 * It can be simplified to:
131 * Low Bit(0) : 2 * Time_(H_LB) < Time_(L_LB)
132 * High Bit(1) : 2 * Time_(L_HB) < Time_(H_HB)
133 * HIGH ___ ____ _.. _________ ___
134 * |_________| |_.. |____| |__|
135 * LOW <L_LB> <H_LB> <L_HB> <H_HB>
136 * [ Low Bit (0) ] [ High Bit(1) ]
139 gpiod_direction_output(led
->ctrl_gpio
, KTD2692_LOW
);
140 udelay(KTD2692_TIME_SHORT_BITSET_US
);
141 gpiod_direction_output(led
->ctrl_gpio
, KTD2692_HIGH
);
142 udelay(KTD2692_TIME_LONG_BITSET_US
);
144 gpiod_direction_output(led
->ctrl_gpio
, KTD2692_LOW
);
145 udelay(KTD2692_TIME_LONG_BITSET_US
);
146 gpiod_direction_output(led
->ctrl_gpio
, KTD2692_HIGH
);
147 udelay(KTD2692_TIME_SHORT_BITSET_US
);
151 static void ktd2692_expresswire_write(struct ktd2692_context
*led
, u8 value
)
155 ktd2692_expresswire_start(led
);
156 for (i
= 7; i
>= 0; i
--)
157 ktd2692_expresswire_set_bit(led
, value
& BIT(i
));
158 ktd2692_expresswire_end(led
);
161 static void ktd2692_brightness_set(struct ktd2692_context
*led
,
162 enum led_brightness brightness
)
164 mutex_lock(&led
->lock
);
166 if (brightness
== LED_OFF
) {
167 led
->mode
= KTD2692_MODE_DISABLE
;
168 gpiod_direction_output(led
->aux_gpio
, KTD2692_LOW
);
170 ktd2692_expresswire_write(led
, brightness
|
171 KTD2692_REG_MOVIE_CURRENT_BASE
);
172 led
->mode
= KTD2692_MODE_MOVIE
;
175 ktd2692_expresswire_write(led
, led
->mode
| KTD2692_REG_MODE_BASE
);
176 mutex_unlock(&led
->lock
);
179 static void ktd2692_brightness_set_work(struct work_struct
*work
)
181 struct ktd2692_context
*led
=
182 container_of(work
, struct ktd2692_context
, work_brightness_set
);
184 ktd2692_brightness_set(led
, led
->torch_brightness
);
187 static void ktd2692_led_brightness_set(struct led_classdev
*led_cdev
,
188 enum led_brightness brightness
)
190 struct led_classdev_flash
*fled_cdev
= lcdev_to_flcdev(led_cdev
);
191 struct ktd2692_context
*led
= fled_cdev_to_led(fled_cdev
);
193 led
->torch_brightness
= brightness
;
194 schedule_work(&led
->work_brightness_set
);
197 static int ktd2692_led_brightness_set_sync(struct led_classdev
*led_cdev
,
198 enum led_brightness brightness
)
200 struct led_classdev_flash
*fled_cdev
= lcdev_to_flcdev(led_cdev
);
201 struct ktd2692_context
*led
= fled_cdev_to_led(fled_cdev
);
203 ktd2692_brightness_set(led
, brightness
);
208 static int ktd2692_led_flash_strobe_set(struct led_classdev_flash
*fled_cdev
,
211 struct ktd2692_context
*led
= fled_cdev_to_led(fled_cdev
);
212 struct led_flash_setting
*timeout
= &fled_cdev
->timeout
;
215 mutex_lock(&led
->lock
);
218 flash_tm_reg
= GET_TIMEOUT_OFFSET(timeout
->val
, timeout
->step
);
219 ktd2692_expresswire_write(led
, flash_tm_reg
220 | KTD2692_REG_FLASH_TIMEOUT_BASE
);
222 led
->mode
= KTD2692_MODE_FLASH
;
223 gpiod_direction_output(led
->aux_gpio
, KTD2692_HIGH
);
225 led
->mode
= KTD2692_MODE_DISABLE
;
226 gpiod_direction_output(led
->aux_gpio
, KTD2692_LOW
);
229 ktd2692_expresswire_write(led
, led
->mode
| KTD2692_REG_MODE_BASE
);
231 fled_cdev
->led_cdev
.brightness
= LED_OFF
;
232 led
->mode
= KTD2692_MODE_DISABLE
;
234 mutex_unlock(&led
->lock
);
239 static int ktd2692_led_flash_timeout_set(struct led_classdev_flash
*fled_cdev
,
245 static void ktd2692_init_movie_current_max(struct ktd2692_led_config_data
*cfg
)
248 u32 movie_current_microamp
;
250 offset
= KTD2692_MOVIE_MODE_CURRENT_LEVELS
;
251 step
= KTD2692_MM_TO_FL_RATIO(cfg
->flash_max_microamp
)
252 / KTD2692_MOVIE_MODE_CURRENT_LEVELS
;
255 movie_current_microamp
= step
* offset
;
257 } while ((movie_current_microamp
> cfg
->movie_max_microamp
) &&
260 cfg
->max_brightness
= offset
;
263 static void ktd2692_init_flash_timeout(struct led_classdev_flash
*fled_cdev
,
264 struct ktd2692_led_config_data
*cfg
)
266 struct led_flash_setting
*setting
;
268 setting
= &fled_cdev
->timeout
;
269 setting
->min
= KTD2692_FLASH_MODE_TIMEOUT_DISABLE
;
270 setting
->max
= cfg
->flash_max_timeout
;
271 setting
->step
= cfg
->flash_max_timeout
272 / (KTD2692_FLASH_MODE_TIMEOUT_LEVELS
- 1);
273 setting
->val
= cfg
->flash_max_timeout
;
276 static void ktd2692_setup(struct ktd2692_context
*led
)
278 led
->mode
= KTD2692_MODE_DISABLE
;
279 ktd2692_expresswire_reset(led
);
280 gpiod_direction_output(led
->aux_gpio
, KTD2692_LOW
);
282 ktd2692_expresswire_write(led
, (KTD2962_MM_MIN_CURR_THRESHOLD_SCALE
- 1)
283 | KTD2692_REG_MM_MIN_CURR_THRESHOLD_BASE
);
284 ktd2692_expresswire_write(led
, KTD2692_FLASH_MODE_CURR_PERCENT(45)
285 | KTD2692_REG_FLASH_CURRENT_BASE
);
288 static int ktd2692_parse_dt(struct ktd2692_context
*led
, struct device
*dev
,
289 struct ktd2692_led_config_data
*cfg
)
291 struct device_node
*np
= dev
->of_node
;
292 struct device_node
*child_node
;
298 led
->ctrl_gpio
= devm_gpiod_get(dev
, "ctrl", GPIOD_ASIS
);
299 if (IS_ERR(led
->ctrl_gpio
)) {
300 ret
= PTR_ERR(led
->ctrl_gpio
);
301 dev_err(dev
, "cannot get ctrl-gpios %d\n", ret
);
305 led
->aux_gpio
= devm_gpiod_get(dev
, "aux", GPIOD_ASIS
);
306 if (IS_ERR(led
->aux_gpio
)) {
307 ret
= PTR_ERR(led
->aux_gpio
);
308 dev_err(dev
, "cannot get aux-gpios %d\n", ret
);
312 led
->regulator
= devm_regulator_get(dev
, "vin");
313 if (IS_ERR(led
->regulator
))
314 led
->regulator
= NULL
;
316 if (led
->regulator
) {
317 ret
= regulator_enable(led
->regulator
);
319 dev_err(dev
, "Failed to enable supply: %d\n", ret
);
322 child_node
= of_get_next_available_child(np
, NULL
);
324 dev_err(dev
, "No DT child node found for connected LED.\n");
328 led
->fled_cdev
.led_cdev
.name
=
329 of_get_property(child_node
, "label", NULL
) ? : child_node
->name
;
331 ret
= of_property_read_u32(child_node
, "led-max-microamp",
332 &cfg
->movie_max_microamp
);
334 dev_err(dev
, "failed to parse led-max-microamp\n");
338 ret
= of_property_read_u32(child_node
, "flash-max-microamp",
339 &cfg
->flash_max_microamp
);
341 dev_err(dev
, "failed to parse flash-max-microamp\n");
345 ret
= of_property_read_u32(child_node
, "flash-max-timeout-us",
346 &cfg
->flash_max_timeout
);
348 dev_err(dev
, "failed to parse flash-max-timeout-us\n");
350 of_node_put(child_node
);
354 static const struct led_flash_ops flash_ops
= {
355 .strobe_set
= ktd2692_led_flash_strobe_set
,
356 .timeout_set
= ktd2692_led_flash_timeout_set
,
359 static int ktd2692_probe(struct platform_device
*pdev
)
361 struct ktd2692_context
*led
;
362 struct led_classdev
*led_cdev
;
363 struct led_classdev_flash
*fled_cdev
;
364 struct ktd2692_led_config_data led_cfg
;
367 led
= devm_kzalloc(&pdev
->dev
, sizeof(*led
), GFP_KERNEL
);
371 fled_cdev
= &led
->fled_cdev
;
372 led_cdev
= &fled_cdev
->led_cdev
;
374 ret
= ktd2692_parse_dt(led
, &pdev
->dev
, &led_cfg
);
378 ktd2692_init_flash_timeout(fled_cdev
, &led_cfg
);
379 ktd2692_init_movie_current_max(&led_cfg
);
381 fled_cdev
->ops
= &flash_ops
;
383 led_cdev
->max_brightness
= led_cfg
.max_brightness
;
384 led_cdev
->brightness_set
= ktd2692_led_brightness_set
;
385 led_cdev
->brightness_set_sync
= ktd2692_led_brightness_set_sync
;
386 led_cdev
->flags
|= LED_CORE_SUSPENDRESUME
| LED_DEV_CAP_FLASH
;
388 mutex_init(&led
->lock
);
389 INIT_WORK(&led
->work_brightness_set
, ktd2692_brightness_set_work
);
391 platform_set_drvdata(pdev
, led
);
393 ret
= led_classdev_flash_register(&pdev
->dev
, fled_cdev
);
395 dev_err(&pdev
->dev
, "can't register LED %s\n", led_cdev
->name
);
396 mutex_destroy(&led
->lock
);
405 static int ktd2692_remove(struct platform_device
*pdev
)
407 struct ktd2692_context
*led
= platform_get_drvdata(pdev
);
410 led_classdev_flash_unregister(&led
->fled_cdev
);
411 cancel_work_sync(&led
->work_brightness_set
);
413 if (led
->regulator
) {
414 ret
= regulator_disable(led
->regulator
);
417 "Failed to disable supply: %d\n", ret
);
420 mutex_destroy(&led
->lock
);
425 static const struct of_device_id ktd2692_match
[] = {
426 { .compatible
= "kinetic,ktd2692", },
429 MODULE_DEVICE_TABLE(of
, ktd2692_match
);
431 static struct platform_driver ktd2692_driver
= {
434 .of_match_table
= ktd2692_match
,
436 .probe
= ktd2692_probe
,
437 .remove
= ktd2692_remove
,
440 module_platform_driver(ktd2692_driver
);
442 MODULE_AUTHOR("Ingi Kim <ingi2.kim@samsung.com>");
443 MODULE_DESCRIPTION("Kinetic KTD2692 LED driver");
444 MODULE_LICENSE("GPL v2");