aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/leds/Kconfig1
-rw-r--r--drivers/leds/leds-aat1290.c137
2 files changed, 132 insertions, 6 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 86de046d4281..b04f82c113f2 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -47,6 +47,7 @@ config LEDS_AAT1290
47 depends on LEDS_CLASS_FLASH 47 depends on LEDS_CLASS_FLASH
48 depends on GPIOLIB 48 depends on GPIOLIB
49 depends on OF 49 depends on OF
50 depends on PINCTRL
50 help 51 help
51 This option enables support for the LEDs on the AAT1290. 52 This option enables support for the LEDs on the AAT1290.
52 53
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