summaryrefslogtreecommitdiffstats
path: root/drivers/leds/leds-aat1290.c
diff options
context:
space:
mode:
authorJacek Anaszewski <j.anaszewski@samsung.com>2015-06-19 03:33:22 -0400
committerBryan Wu <cooloney@gmail.com>2015-06-22 16:56:46 -0400
commitac69b9038f8214e2a8ee0eb3a113af473a7518e4 (patch)
treefa3eab2ff21e1146e998dc5d976088cbb01c39bf /drivers/leds/leds-aat1290.c
parent8bdc89390ed645c7d7c1e23470d24fbd523e7168 (diff)
leds: aat1290: add support for V4L2 Flash sub-device
Add support for V4L2 Flash sub-device to the aat1290 LED Flash class driver. The support allows for V4L2 Flash sub-device to take the control of the LED Flash class device. Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com> Acked-by: Kyungmin Park <kyungmin.park@samsung.com> Cc: Bryan Wu <cooloney@gmail.com> Cc: Richard Purdie <rpurdie@rpsys.net> Cc: Sakari Ailus <sakari.ailus@iki.fi> Signed-off-by: Bryan Wu <cooloney@gmail.com>
Diffstat (limited to 'drivers/leds/leds-aat1290.c')
-rw-r--r--drivers/leds/leds-aat1290.c137
1 files changed, 131 insertions, 6 deletions
diff --git a/drivers/leds/leds-aat1290.c b/drivers/leds/leds-aat1290.c
index 6ea1d5465309..5de2f19d3c0d 100644
--- a/drivers/leds/leds-aat1290.c
+++ b/drivers/leds/leds-aat1290.c
@@ -17,9 +17,11 @@
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/mutex.h> 18#include <linux/mutex.h>
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/pinctrl/consumer.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
21#include <linux/slab.h> 22#include <linux/slab.h>
22#include <linux/workqueue.h> 23#include <linux/workqueue.h>
24#include <media/v4l2-flash-led-class.h>
23 25
24#define AAT1290_MOVIE_MODE_CURRENT_ADDR 17 26#define AAT1290_MOVIE_MODE_CURRENT_ADDR 17
25#define AAT1290_MAX_MM_CURR_PERCENT_0 16 27#define AAT1290_MAX_MM_CURR_PERCENT_0 16
@@ -52,6 +54,8 @@ struct aat1290_led_config_data {
52 u32 max_flash_current; 54 u32 max_flash_current;
53 /* maximum flash timeout */ 55 /* maximum flash timeout */
54 u32 max_flash_tm; 56 u32 max_flash_tm;
57 /* external strobe capability */
58 bool has_external_strobe;
55 /* max LED brightness level */ 59 /* max LED brightness level */
56 enum led_brightness max_brightness; 60 enum led_brightness max_brightness;
57}; 61};
@@ -64,6 +68,8 @@ struct aat1290_led {
64 68
65 /* corresponding LED Flash class device */ 69 /* corresponding LED Flash class device */
66 struct led_classdev_flash fled_cdev; 70 struct led_classdev_flash fled_cdev;
71 /* V4L2 Flash device */
72 struct v4l2_flash *v4l2_flash;
67 73
68 /* FLEN pin */ 74 /* FLEN pin */
69 struct gpio_desc *gpio_fl_en; 75 struct gpio_desc *gpio_fl_en;
@@ -230,11 +236,15 @@ static int aat1290_led_flash_timeout_set(struct led_classdev_flash *fled_cdev,
230} 236}
231 237
232static int aat1290_led_parse_dt(struct aat1290_led *led, 238static int aat1290_led_parse_dt(struct aat1290_led *led,
233 struct aat1290_led_config_data *cfg) 239 struct aat1290_led_config_data *cfg,
240 struct device_node **sub_node)
234{ 241{
235 struct led_classdev *led_cdev = &led->fled_cdev.led_cdev; 242 struct led_classdev *led_cdev = &led->fled_cdev.led_cdev;
236 struct device *dev = &led->pdev->dev; 243 struct device *dev = &led->pdev->dev;
237 struct device_node *child_node; 244 struct device_node *child_node;
245#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
246 struct pinctrl *pinctrl;
247#endif
238 int ret = 0; 248 int ret = 0;
239 249
240 led->gpio_fl_en = devm_gpiod_get(dev, "flen"); 250 led->gpio_fl_en = devm_gpiod_get(dev, "flen");
@@ -251,6 +261,17 @@ static int aat1290_led_parse_dt(struct aat1290_led *led,
251 return ret; 261 return ret;
252 } 262 }
253 263
264#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
265 pinctrl = devm_pinctrl_get_select_default(&led->pdev->dev);
266 if (IS_ERR(pinctrl)) {
267 cfg->has_external_strobe = false;
268 dev_info(dev,
269 "No support for external strobe detected.\n");
270 } else {
271 cfg->has_external_strobe = true;
272 }
273#endif
274
254 child_node = of_get_next_available_child(dev->of_node, NULL); 275 child_node = of_get_next_available_child(dev->of_node, NULL);
255 if (!child_node) { 276 if (!child_node) {
256 dev_err(dev, "No DT child node found for connected LED.\n"); 277 dev_err(dev, "No DT child node found for connected LED.\n");
@@ -288,6 +309,8 @@ static int aat1290_led_parse_dt(struct aat1290_led *led,
288 309
289 of_node_put(child_node); 310 of_node_put(child_node);
290 311
312 *sub_node = child_node;
313
291 return ret; 314 return ret;
292} 315}
293 316
@@ -316,7 +339,8 @@ int init_mm_current_scale(struct aat1290_led *led,
316 int i, max_mm_current = 339 int i, max_mm_current =
317 AAT1290_MAX_MM_CURRENT(cfg->max_flash_current); 340 AAT1290_MAX_MM_CURRENT(cfg->max_flash_current);
318 341
319 led->mm_current_scale = kzalloc(sizeof(max_mm_current_percent), 342 led->mm_current_scale = devm_kzalloc(&led->pdev->dev,
343 sizeof(max_mm_current_percent),
320 GFP_KERNEL); 344 GFP_KERNEL);
321 if (!led->mm_current_scale) 345 if (!led->mm_current_scale)
322 return -ENOMEM; 346 return -ENOMEM;
@@ -329,11 +353,12 @@ int init_mm_current_scale(struct aat1290_led *led,
329} 353}
330 354
331static int aat1290_led_get_configuration(struct aat1290_led *led, 355static int aat1290_led_get_configuration(struct aat1290_led *led,
332 struct aat1290_led_config_data *cfg) 356 struct aat1290_led_config_data *cfg,
357 struct device_node **sub_node)
333{ 358{
334 int ret; 359 int ret;
335 360
336 ret = aat1290_led_parse_dt(led, cfg); 361 ret = aat1290_led_parse_dt(led, cfg, sub_node);
337 if (ret < 0) 362 if (ret < 0)
338 return ret; 363 return ret;
339 /* 364 /*
@@ -346,7 +371,10 @@ static int aat1290_led_get_configuration(struct aat1290_led *led,
346 371
347 aat1290_led_validate_mm_current(led, cfg); 372 aat1290_led_validate_mm_current(led, cfg);
348 373
349 kfree(led->mm_current_scale); 374#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
375#else
376 devm_kfree(&led->pdev->dev, led->mm_current_scale);
377#endif
350 378
351 return 0; 379 return 0;
352} 380}
@@ -365,6 +393,88 @@ static void aat1290_init_flash_timeout(struct aat1290_led *led,
365 setting->val = setting->max; 393 setting->val = setting->max;
366} 394}
367 395
396#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
397static enum led_brightness aat1290_intensity_to_brightness(
398 struct v4l2_flash *v4l2_flash,
399 s32 intensity)
400{
401 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
402 struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
403 int i;
404
405 for (i = AAT1290_MM_CURRENT_SCALE_SIZE - 1; i >= 0; --i)
406 if (intensity >= led->mm_current_scale[i])
407 return i + 1;
408
409 return 1;
410}
411
412static s32 aat1290_brightness_to_intensity(struct v4l2_flash *v4l2_flash,
413 enum led_brightness brightness)
414{
415 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
416 struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
417
418 return led->mm_current_scale[brightness - 1];
419}
420
421static int aat1290_led_external_strobe_set(struct v4l2_flash *v4l2_flash,
422 bool enable)
423{
424 struct aat1290_led *led = fled_cdev_to_led(v4l2_flash->fled_cdev);
425 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
426 struct led_classdev *led_cdev = &fled_cdev->led_cdev;
427 struct pinctrl *pinctrl;
428
429 gpiod_direction_output(led->gpio_fl_en, 0);
430 gpiod_direction_output(led->gpio_en_set, 0);
431
432 led->movie_mode = false;
433 led_cdev->brightness = 0;
434
435 pinctrl = devm_pinctrl_get_select(&led->pdev->dev,
436 enable ? "isp" : "host");
437 if (IS_ERR(pinctrl)) {
438 dev_warn(&led->pdev->dev, "Unable to switch strobe source.\n");
439 return PTR_ERR(pinctrl);
440 }
441
442 return 0;
443}
444
445static void aat1290_init_v4l2_flash_config(struct aat1290_led *led,
446 struct aat1290_led_config_data *led_cfg,
447 struct v4l2_flash_config *v4l2_sd_cfg)
448{
449 struct led_classdev *led_cdev = &led->fled_cdev.led_cdev;
450 struct led_flash_setting *s;
451
452 strlcpy(v4l2_sd_cfg->dev_name, led_cdev->name,
453 sizeof(v4l2_sd_cfg->dev_name));
454
455 s = &v4l2_sd_cfg->torch_intensity;
456 s->min = led->mm_current_scale[0];
457 s->max = led_cfg->max_mm_current;
458 s->step = 1;
459 s->val = s->max;
460
461 v4l2_sd_cfg->has_external_strobe = led_cfg->has_external_strobe;
462}
463
464static const struct v4l2_flash_ops v4l2_flash_ops = {
465 .external_strobe_set = aat1290_led_external_strobe_set,
466 .intensity_to_led_brightness = aat1290_intensity_to_brightness,
467 .led_brightness_to_intensity = aat1290_brightness_to_intensity,
468};
469#else
470static inline void aat1290_init_v4l2_flash_config(struct aat1290_led *led,
471 struct aat1290_led_config_data *led_cfg,
472 struct v4l2_flash_config *v4l2_sd_cfg)
473{
474}
475static const struct v4l2_flash_ops v4l2_flash_ops;
476#endif
477
368static const struct led_flash_ops flash_ops = { 478static const struct led_flash_ops flash_ops = {
369 .strobe_set = aat1290_led_flash_strobe_set, 479 .strobe_set = aat1290_led_flash_strobe_set,
370 .timeout_set = aat1290_led_flash_timeout_set, 480 .timeout_set = aat1290_led_flash_timeout_set,
@@ -373,10 +483,12 @@ static const struct led_flash_ops flash_ops = {
373static int aat1290_led_probe(struct platform_device *pdev) 483static int aat1290_led_probe(struct platform_device *pdev)
374{ 484{
375 struct device *dev = &pdev->dev; 485 struct device *dev = &pdev->dev;
486 struct device_node *sub_node = NULL;
376 struct aat1290_led *led; 487 struct aat1290_led *led;
377 struct led_classdev *led_cdev; 488 struct led_classdev *led_cdev;
378 struct led_classdev_flash *fled_cdev; 489 struct led_classdev_flash *fled_cdev;
379 struct aat1290_led_config_data led_cfg = {}; 490 struct aat1290_led_config_data led_cfg = {};
491 struct v4l2_flash_config v4l2_sd_cfg = {};
380 int ret; 492 int ret;
381 493
382 led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL); 494 led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
@@ -390,7 +502,7 @@ static int aat1290_led_probe(struct platform_device *pdev)
390 fled_cdev->ops = &flash_ops; 502 fled_cdev->ops = &flash_ops;
391 led_cdev = &fled_cdev->led_cdev; 503 led_cdev = &fled_cdev->led_cdev;
392 504
393 ret = aat1290_led_get_configuration(led, &led_cfg); 505 ret = aat1290_led_get_configuration(led, &led_cfg, &sub_node);
394 if (ret < 0) 506 if (ret < 0)
395 return ret; 507 return ret;
396 508
@@ -410,8 +522,20 @@ static int aat1290_led_probe(struct platform_device *pdev)
410 if (ret < 0) 522 if (ret < 0)
411 goto err_flash_register; 523 goto err_flash_register;
412 524
525 aat1290_init_v4l2_flash_config(led, &led_cfg, &v4l2_sd_cfg);
526
527 /* Create V4L2 Flash subdev. */
528 led->v4l2_flash = v4l2_flash_init(dev, sub_node, fled_cdev, NULL,
529 &v4l2_flash_ops, &v4l2_sd_cfg);
530 if (IS_ERR(led->v4l2_flash)) {
531 ret = PTR_ERR(led->v4l2_flash);
532 goto error_v4l2_flash_init;
533 }
534
413 return 0; 535 return 0;
414 536
537error_v4l2_flash_init:
538 led_classdev_flash_unregister(fled_cdev);
415err_flash_register: 539err_flash_register:
416 mutex_destroy(&led->lock); 540 mutex_destroy(&led->lock);
417 541
@@ -422,6 +546,7 @@ static int aat1290_led_remove(struct platform_device *pdev)
422{ 546{
423 struct aat1290_led *led = platform_get_drvdata(pdev); 547 struct aat1290_led *led = platform_get_drvdata(pdev);
424 548
549 v4l2_flash_release(led->v4l2_flash);
425 led_classdev_flash_unregister(&led->fled_cdev); 550 led_classdev_flash_unregister(&led->fled_cdev);
426 cancel_work_sync(&led->work_brightness_set); 551 cancel_work_sync(&led->work_brightness_set);
427 552