1/* 2 * LED Flash class driver for the AAT1290 3 * 1.5A Step-Up Current Regulator for Flash LEDs 4 * 5 * Copyright (C) 2015, Samsung Electronics Co., Ltd. 6 * Author: Jacek Anaszewski <j.anaszewski@samsung.com> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * version 2 as published by the Free Software Foundation. 11 */ 12 13#include <linux/delay.h> 14#include <linux/gpio/consumer.h> 15#include <linux/led-class-flash.h> 16#include <linux/leds.h> 17#include <linux/module.h> 18#include <linux/mutex.h> 19#include <linux/of.h> 20#include <linux/pinctrl/consumer.h> 21#include <linux/platform_device.h> 22#include <linux/slab.h> 23#include <linux/workqueue.h> 24#include <media/v4l2-flash-led-class.h> 25 26#define AAT1290_MOVIE_MODE_CURRENT_ADDR 17 27#define AAT1290_MAX_MM_CURR_PERCENT_0 16 28#define AAT1290_MAX_MM_CURR_PERCENT_100 1 29 30#define AAT1290_FLASH_SAFETY_TIMER_ADDR 18 31 32#define AAT1290_MOVIE_MODE_CONFIG_ADDR 19 33#define AAT1290_MOVIE_MODE_OFF 1 34#define AAT1290_MOVIE_MODE_ON 3 35 36#define AAT1290_MM_CURRENT_RATIO_ADDR 20 37#define AAT1290_MM_TO_FL_1_92 1 38 39#define AAT1290_MM_TO_FL_RATIO 1000 / 1920 40#define AAT1290_MAX_MM_CURRENT(fl_max) (fl_max * AAT1290_MM_TO_FL_RATIO) 41 42#define AAT1290_LATCH_TIME_MIN_US 500 43#define AAT1290_LATCH_TIME_MAX_US 1000 44#define AAT1290_EN_SET_TICK_TIME_US 1 45#define AAT1290_FLEN_OFF_DELAY_TIME_US 10 46#define AAT1290_FLASH_TM_NUM_LEVELS 16 47#define AAT1290_MM_CURRENT_SCALE_SIZE 15 48 49 50struct aat1290_led_config_data { 51 /* maximum LED current in movie mode */ 52 u32 max_mm_current; 53 /* maximum LED current in flash mode */ 54 u32 max_flash_current; 55 /* maximum flash timeout */ 56 u32 max_flash_tm; 57 /* external strobe capability */ 58 bool has_external_strobe; 59 /* max LED brightness level */ 60 enum led_brightness max_brightness; 61}; 62 63struct aat1290_led { 64 /* platform device data */ 65 struct platform_device *pdev; 66 /* secures access to the device */ 67 struct mutex lock; 68 69 /* corresponding LED Flash class device */ 70 struct led_classdev_flash fled_cdev; 71 /* V4L2 Flash device */ 72 struct v4l2_flash *v4l2_flash; 73 74 /* FLEN pin */ 75 struct gpio_desc *gpio_fl_en; 76 /* EN|SET pin */ 77 struct gpio_desc *gpio_en_set; 78 /* movie mode current scale */ 79 int *mm_current_scale; 80 /* device mode */ 81 bool movie_mode; 82 83 /* brightness cache */ 84 unsigned int torch_brightness; 85 /* assures led-triggers compatibility */ 86 struct work_struct work_brightness_set; 87}; 88 89static struct aat1290_led *fled_cdev_to_led( 90 struct led_classdev_flash *fled_cdev) 91{ 92 return container_of(fled_cdev, struct aat1290_led, fled_cdev); 93} 94 95static void aat1290_as2cwire_write(struct aat1290_led *led, int addr, int value) 96{ 97 int i; 98 99 gpiod_direction_output(led->gpio_fl_en, 0); 100 gpiod_direction_output(led->gpio_en_set, 0); 101 102 udelay(AAT1290_FLEN_OFF_DELAY_TIME_US); 103 104 /* write address */ 105 for (i = 0; i < addr; ++i) { 106 udelay(AAT1290_EN_SET_TICK_TIME_US); 107 gpiod_direction_output(led->gpio_en_set, 0); 108 udelay(AAT1290_EN_SET_TICK_TIME_US); 109 gpiod_direction_output(led->gpio_en_set, 1); 110 } 111 112 usleep_range(AAT1290_LATCH_TIME_MIN_US, AAT1290_LATCH_TIME_MAX_US); 113 114 /* write data */ 115 for (i = 0; i < value; ++i) { 116 udelay(AAT1290_EN_SET_TICK_TIME_US); 117 gpiod_direction_output(led->gpio_en_set, 0); 118 udelay(AAT1290_EN_SET_TICK_TIME_US); 119 gpiod_direction_output(led->gpio_en_set, 1); 120 } 121 122 usleep_range(AAT1290_LATCH_TIME_MIN_US, AAT1290_LATCH_TIME_MAX_US); 123} 124 125static void aat1290_set_flash_safety_timer(struct aat1290_led *led, 126 unsigned int micro_sec) 127{ 128 struct led_classdev_flash *fled_cdev = &led->fled_cdev; 129 struct led_flash_setting *flash_tm = &fled_cdev->timeout; 130 int flash_tm_reg = AAT1290_FLASH_TM_NUM_LEVELS - 131 (micro_sec / flash_tm->step) + 1; 132 133 aat1290_as2cwire_write(led, AAT1290_FLASH_SAFETY_TIMER_ADDR, 134 flash_tm_reg); 135} 136 137static void aat1290_brightness_set(struct aat1290_led *led, 138 enum led_brightness brightness) 139{ 140 mutex_lock(&led->lock); 141 142 if (brightness == 0) { 143 gpiod_direction_output(led->gpio_fl_en, 0); 144 gpiod_direction_output(led->gpio_en_set, 0); 145 led->movie_mode = false; 146 } else { 147 if (!led->movie_mode) { 148 aat1290_as2cwire_write(led, 149 AAT1290_MM_CURRENT_RATIO_ADDR, 150 AAT1290_MM_TO_FL_1_92); 151 led->movie_mode = true; 152 } 153 154 aat1290_as2cwire_write(led, AAT1290_MOVIE_MODE_CURRENT_ADDR, 155 AAT1290_MAX_MM_CURR_PERCENT_0 - brightness); 156 aat1290_as2cwire_write(led, AAT1290_MOVIE_MODE_CONFIG_ADDR, 157 AAT1290_MOVIE_MODE_ON); 158 } 159 160 mutex_unlock(&led->lock); 161} 162 163/* LED subsystem callbacks */ 164 165static void aat1290_brightness_set_work(struct work_struct *work) 166{ 167 struct aat1290_led *led = 168 container_of(work, struct aat1290_led, work_brightness_set); 169 170 aat1290_brightness_set(led, led->torch_brightness); 171} 172 173static void aat1290_led_brightness_set(struct led_classdev *led_cdev, 174 enum led_brightness brightness) 175{ 176 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev); 177 struct aat1290_led *led = fled_cdev_to_led(fled_cdev); 178 179 led->torch_brightness = brightness; 180 schedule_work(&led->work_brightness_set); 181} 182 183static int aat1290_led_brightness_set_sync(struct led_classdev *led_cdev, 184 enum led_brightness brightness) 185{ 186 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev); 187 struct aat1290_led *led = fled_cdev_to_led(fled_cdev); 188 189 aat1290_brightness_set(led, brightness); 190 191 return 0; 192} 193 194static int aat1290_led_flash_strobe_set(struct led_classdev_flash *fled_cdev, 195 bool state) 196 197{ 198 struct aat1290_led *led = fled_cdev_to_led(fled_cdev); 199 struct led_classdev *led_cdev = &fled_cdev->led_cdev; 200 struct led_flash_setting *timeout = &fled_cdev->timeout; 201 202 mutex_lock(&led->lock); 203 204 if (state) { 205 aat1290_set_flash_safety_timer(led, timeout->val); 206 gpiod_direction_output(led->gpio_fl_en, 1); 207 } else { 208 gpiod_direction_output(led->gpio_fl_en, 0); 209 gpiod_direction_output(led->gpio_en_set, 0); 210 } 211 212 /* 213 * To reenter movie mode after a flash event the part must be cycled 214 * off and back on to reset the movie mode and reprogrammed via the 215 * AS2Cwire. Therefore the brightness and movie_mode properties needs 216 * to be updated here to reflect the actual state. 217 */ 218 led_cdev->brightness = 0; 219 led->movie_mode = false; 220 221 mutex_unlock(&led->lock); 222 223 return 0; 224} 225 226static int aat1290_led_flash_timeout_set(struct led_classdev_flash *fled_cdev, 227 u32 timeout) 228{ 229 /* 230 * Don't do anything - flash timeout is cached in the led-class-flash 231 * core and will be applied in the strobe_set op, as writing the 232 * safety timer register spuriously turns the torch mode on. 233 */ 234 235 return 0; 236} 237 238static int aat1290_led_parse_dt(struct aat1290_led *led, 239 struct aat1290_led_config_data *cfg, 240 struct device_node **sub_node) 241{ 242 struct led_classdev *led_cdev = &led->fled_cdev.led_cdev; 243 struct device *dev = &led->pdev->dev; 244 struct device_node *child_node; 245#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS) 246 struct pinctrl *pinctrl; 247#endif 248 int ret = 0; 249 250 led->gpio_fl_en = devm_gpiod_get(dev, "flen", GPIOD_ASIS); 251 if (IS_ERR(led->gpio_fl_en)) { 252 ret = PTR_ERR(led->gpio_fl_en); 253 dev_err(dev, "Unable to claim gpio \"flen\".\n"); 254 return ret; 255 } 256 257 led->gpio_en_set = devm_gpiod_get(dev, "enset", GPIOD_ASIS); 258 if (IS_ERR(led->gpio_en_set)) { 259 ret = PTR_ERR(led->gpio_en_set); 260 dev_err(dev, "Unable to claim gpio \"enset\".\n"); 261 return ret; 262 } 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 275 child_node = of_get_next_available_child(dev->of_node, NULL); 276 if (!child_node) { 277 dev_err(dev, "No DT child node found for connected LED.\n"); 278 return -EINVAL; 279 } 280 281 led_cdev->name = of_get_property(child_node, "label", NULL) ? : 282 child_node->name; 283 284 ret = of_property_read_u32(child_node, "led-max-microamp", 285 &cfg->max_mm_current); 286 /* 287 * led-max-microamp will default to 1/20 of flash-max-microamp 288 * in case it is missing. 289 */ 290 if (ret < 0) 291 dev_warn(dev, 292 "led-max-microamp DT property missing\n"); 293 294 ret = of_property_read_u32(child_node, "flash-max-microamp", 295 &cfg->max_flash_current); 296 if (ret < 0) { 297 dev_err(dev, 298 "flash-max-microamp DT property missing\n"); 299 return ret; 300 } 301 302 ret = of_property_read_u32(child_node, "flash-max-timeout-us", 303 &cfg->max_flash_tm); 304 if (ret < 0) { 305 dev_err(dev, 306 "flash-max-timeout-us DT property missing\n"); 307 return ret; 308 } 309 310 of_node_put(child_node); 311 312 *sub_node = child_node; 313 314 return ret; 315} 316 317static void aat1290_led_validate_mm_current(struct aat1290_led *led, 318 struct aat1290_led_config_data *cfg) 319{ 320 int i, b = 0, e = AAT1290_MM_CURRENT_SCALE_SIZE; 321 322 while (e - b > 1) { 323 i = b + (e - b) / 2; 324 if (cfg->max_mm_current < led->mm_current_scale[i]) 325 e = i; 326 else 327 b = i; 328 } 329 330 cfg->max_mm_current = led->mm_current_scale[b]; 331 cfg->max_brightness = b + 1; 332} 333 334static int init_mm_current_scale(struct aat1290_led *led, 335 struct aat1290_led_config_data *cfg) 336{ 337 int max_mm_current_percent[] = { 20, 22, 25, 28, 32, 36, 40, 45, 50, 56, 338 63, 71, 79, 89, 100 }; 339 int i, max_mm_current = 340 AAT1290_MAX_MM_CURRENT(cfg->max_flash_current); 341 342 led->mm_current_scale = devm_kzalloc(&led->pdev->dev, 343 sizeof(max_mm_current_percent), 344 GFP_KERNEL); 345 if (!led->mm_current_scale) 346 return -ENOMEM; 347 348 for (i = 0; i < AAT1290_MM_CURRENT_SCALE_SIZE; ++i) 349 led->mm_current_scale[i] = max_mm_current * 350 max_mm_current_percent[i] / 100; 351 352 return 0; 353} 354 355static int aat1290_led_get_configuration(struct aat1290_led *led, 356 struct aat1290_led_config_data *cfg, 357 struct device_node **sub_node) 358{ 359 int ret; 360 361 ret = aat1290_led_parse_dt(led, cfg, sub_node); 362 if (ret < 0) 363 return ret; 364 /* 365 * Init non-linear movie mode current scale basing 366 * on the max flash current from led configuration. 367 */ 368 ret = init_mm_current_scale(led, cfg); 369 if (ret < 0) 370 return ret; 371 372 aat1290_led_validate_mm_current(led, cfg); 373 374#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS) 375#else 376 devm_kfree(&led->pdev->dev, led->mm_current_scale); 377#endif 378 379 return 0; 380} 381 382static void aat1290_init_flash_timeout(struct aat1290_led *led, 383 struct aat1290_led_config_data *cfg) 384{ 385 struct led_classdev_flash *fled_cdev = &led->fled_cdev; 386 struct led_flash_setting *setting; 387 388 /* Init flash timeout setting */ 389 setting = &fled_cdev->timeout; 390 setting->min = cfg->max_flash_tm / AAT1290_FLASH_TM_NUM_LEVELS; 391 setting->max = cfg->max_flash_tm; 392 setting->step = setting->min; 393 setting->val = setting->max; 394} 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 478static const struct led_flash_ops flash_ops = { 479 .strobe_set = aat1290_led_flash_strobe_set, 480 .timeout_set = aat1290_led_flash_timeout_set, 481}; 482 483static int aat1290_led_probe(struct platform_device *pdev) 484{ 485 struct device *dev = &pdev->dev; 486 struct device_node *sub_node = NULL; 487 struct aat1290_led *led; 488 struct led_classdev *led_cdev; 489 struct led_classdev_flash *fled_cdev; 490 struct aat1290_led_config_data led_cfg = {}; 491 struct v4l2_flash_config v4l2_sd_cfg = {}; 492 int ret; 493 494 led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL); 495 if (!led) 496 return -ENOMEM; 497 498 led->pdev = pdev; 499 platform_set_drvdata(pdev, led); 500 501 fled_cdev = &led->fled_cdev; 502 fled_cdev->ops = &flash_ops; 503 led_cdev = &fled_cdev->led_cdev; 504 505 ret = aat1290_led_get_configuration(led, &led_cfg, &sub_node); 506 if (ret < 0) 507 return ret; 508 509 mutex_init(&led->lock); 510 511 /* Initialize LED Flash class device */ 512 led_cdev->brightness_set = aat1290_led_brightness_set; 513 led_cdev->brightness_set_sync = aat1290_led_brightness_set_sync; 514 led_cdev->max_brightness = led_cfg.max_brightness; 515 led_cdev->flags |= LED_DEV_CAP_FLASH; 516 INIT_WORK(&led->work_brightness_set, aat1290_brightness_set_work); 517 518 aat1290_init_flash_timeout(led, &led_cfg); 519 520 /* Register LED Flash class device */ 521 ret = led_classdev_flash_register(&pdev->dev, fled_cdev); 522 if (ret < 0) 523 goto err_flash_register; 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 535 return 0; 536 537error_v4l2_flash_init: 538 led_classdev_flash_unregister(fled_cdev); 539err_flash_register: 540 mutex_destroy(&led->lock); 541 542 return ret; 543} 544 545static int aat1290_led_remove(struct platform_device *pdev) 546{ 547 struct aat1290_led *led = platform_get_drvdata(pdev); 548 549 v4l2_flash_release(led->v4l2_flash); 550 led_classdev_flash_unregister(&led->fled_cdev); 551 cancel_work_sync(&led->work_brightness_set); 552 553 mutex_destroy(&led->lock); 554 555 return 0; 556} 557 558static const struct of_device_id aat1290_led_dt_match[] = { 559 { .compatible = "skyworks,aat1290" }, 560 {}, 561}; 562MODULE_DEVICE_TABLE(of, aat1290_led_dt_match); 563 564static struct platform_driver aat1290_led_driver = { 565 .probe = aat1290_led_probe, 566 .remove = aat1290_led_remove, 567 .driver = { 568 .name = "aat1290", 569 .of_match_table = aat1290_led_dt_match, 570 }, 571}; 572 573module_platform_driver(aat1290_led_driver); 574 575MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>"); 576MODULE_DESCRIPTION("Skyworks Current Regulator for Flash LEDs"); 577MODULE_LICENSE("GPL v2"); 578