root/drivers/leds/leds-aat1290.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fled_cdev_to_led
  2. led_cdev_to_fled_cdev
  3. aat1290_as2cwire_write
  4. aat1290_set_flash_safety_timer
  5. aat1290_led_brightness_set
  6. aat1290_led_flash_strobe_set
  7. aat1290_led_flash_timeout_set
  8. aat1290_led_parse_dt
  9. aat1290_led_validate_mm_current
  10. init_mm_current_scale
  11. aat1290_led_get_configuration
  12. aat1290_init_flash_timeout
  13. aat1290_intensity_to_brightness
  14. aat1290_brightness_to_intensity
  15. aat1290_led_external_strobe_set
  16. aat1290_init_v4l2_flash_config
  17. aat1290_init_v4l2_flash_config
  18. aat1290_led_probe
  19. aat1290_led_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *      LED Flash class driver for the AAT1290
   4  *      1.5A Step-Up Current Regulator for Flash LEDs
   5  *
   6  *      Copyright (C) 2015, Samsung Electronics Co., Ltd.
   7  *      Author: Jacek Anaszewski <j.anaszewski@samsung.com>
   8  */
   9 
  10 #include <linux/delay.h>
  11 #include <linux/gpio/consumer.h>
  12 #include <linux/led-class-flash.h>
  13 #include <linux/leds.h>
  14 #include <linux/module.h>
  15 #include <linux/mutex.h>
  16 #include <linux/of.h>
  17 #include <linux/pinctrl/consumer.h>
  18 #include <linux/platform_device.h>
  19 #include <linux/slab.h>
  20 #include <media/v4l2-flash-led-class.h>
  21 
  22 #define AAT1290_MOVIE_MODE_CURRENT_ADDR 17
  23 #define AAT1290_MAX_MM_CURR_PERCENT_0   16
  24 #define AAT1290_MAX_MM_CURR_PERCENT_100 1
  25 
  26 #define AAT1290_FLASH_SAFETY_TIMER_ADDR 18
  27 
  28 #define AAT1290_MOVIE_MODE_CONFIG_ADDR  19
  29 #define AAT1290_MOVIE_MODE_OFF          1
  30 #define AAT1290_MOVIE_MODE_ON           3
  31 
  32 #define AAT1290_MM_CURRENT_RATIO_ADDR   20
  33 #define AAT1290_MM_TO_FL_1_92           1
  34 
  35 #define AAT1290_MM_TO_FL_RATIO          1000 / 1920
  36 #define AAT1290_MAX_MM_CURRENT(fl_max)  (fl_max * AAT1290_MM_TO_FL_RATIO)
  37 
  38 #define AAT1290_LATCH_TIME_MIN_US       500
  39 #define AAT1290_LATCH_TIME_MAX_US       1000
  40 #define AAT1290_EN_SET_TICK_TIME_US     1
  41 #define AAT1290_FLEN_OFF_DELAY_TIME_US  10
  42 #define AAT1290_FLASH_TM_NUM_LEVELS     16
  43 #define AAT1290_MM_CURRENT_SCALE_SIZE   15
  44 
  45 #define AAT1290_NAME                    "aat1290"
  46 
  47 
  48 struct aat1290_led_config_data {
  49         /* maximum LED current in movie mode */
  50         u32 max_mm_current;
  51         /* maximum LED current in flash mode */
  52         u32 max_flash_current;
  53         /* maximum flash timeout */
  54         u32 max_flash_tm;
  55         /* external strobe capability */
  56         bool has_external_strobe;
  57         /* max LED brightness level */
  58         enum led_brightness max_brightness;
  59 };
  60 
  61 struct aat1290_led {
  62         /* platform device data */
  63         struct platform_device *pdev;
  64         /* secures access to the device */
  65         struct mutex lock;
  66 
  67         /* corresponding LED Flash class device */
  68         struct led_classdev_flash fled_cdev;
  69         /* V4L2 Flash device */
  70         struct v4l2_flash *v4l2_flash;
  71 
  72         /* FLEN pin */
  73         struct gpio_desc *gpio_fl_en;
  74         /* EN|SET pin  */
  75         struct gpio_desc *gpio_en_set;
  76         /* movie mode current scale */
  77         int *mm_current_scale;
  78         /* device mode */
  79         bool movie_mode;
  80         /* brightness cache */
  81         unsigned int torch_brightness;
  82 };
  83 
  84 static struct aat1290_led *fled_cdev_to_led(
  85                                 struct led_classdev_flash *fled_cdev)
  86 {
  87         return container_of(fled_cdev, struct aat1290_led, fled_cdev);
  88 }
  89 
  90 static struct led_classdev_flash *led_cdev_to_fled_cdev(
  91                                 struct led_classdev *led_cdev)
  92 {
  93         return container_of(led_cdev, struct led_classdev_flash, led_cdev);
  94 }
  95 
  96 static void aat1290_as2cwire_write(struct aat1290_led *led, int addr, int value)
  97 {
  98         int i;
  99 
 100         gpiod_direction_output(led->gpio_fl_en, 0);
 101         gpiod_direction_output(led->gpio_en_set, 0);
 102 
 103         udelay(AAT1290_FLEN_OFF_DELAY_TIME_US);
 104 
 105         /* write address */
 106         for (i = 0; i < addr; ++i) {
 107                 udelay(AAT1290_EN_SET_TICK_TIME_US);
 108                 gpiod_direction_output(led->gpio_en_set, 0);
 109                 udelay(AAT1290_EN_SET_TICK_TIME_US);
 110                 gpiod_direction_output(led->gpio_en_set, 1);
 111         }
 112 
 113         usleep_range(AAT1290_LATCH_TIME_MIN_US, AAT1290_LATCH_TIME_MAX_US);
 114 
 115         /* write data */
 116         for (i = 0; i < value; ++i) {
 117                 udelay(AAT1290_EN_SET_TICK_TIME_US);
 118                 gpiod_direction_output(led->gpio_en_set, 0);
 119                 udelay(AAT1290_EN_SET_TICK_TIME_US);
 120                 gpiod_direction_output(led->gpio_en_set, 1);
 121         }
 122 
 123         usleep_range(AAT1290_LATCH_TIME_MIN_US, AAT1290_LATCH_TIME_MAX_US);
 124 }
 125 
 126 static void aat1290_set_flash_safety_timer(struct aat1290_led *led,
 127                                         unsigned int micro_sec)
 128 {
 129         struct led_classdev_flash *fled_cdev = &led->fled_cdev;
 130         struct led_flash_setting *flash_tm = &fled_cdev->timeout;
 131         int flash_tm_reg = AAT1290_FLASH_TM_NUM_LEVELS -
 132                                 (micro_sec / flash_tm->step) + 1;
 133 
 134         aat1290_as2cwire_write(led, AAT1290_FLASH_SAFETY_TIMER_ADDR,
 135                                                         flash_tm_reg);
 136 }
 137 
 138 /* LED subsystem callbacks */
 139 
 140 static int aat1290_led_brightness_set(struct led_classdev *led_cdev,
 141                                         enum led_brightness brightness)
 142 {
 143         struct led_classdev_flash *fled_cdev = led_cdev_to_fled_cdev(led_cdev);
 144         struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
 145 
 146         mutex_lock(&led->lock);
 147 
 148         if (brightness == 0) {
 149                 gpiod_direction_output(led->gpio_fl_en, 0);
 150                 gpiod_direction_output(led->gpio_en_set, 0);
 151                 led->movie_mode = false;
 152         } else {
 153                 if (!led->movie_mode) {
 154                         aat1290_as2cwire_write(led,
 155                                 AAT1290_MM_CURRENT_RATIO_ADDR,
 156                                 AAT1290_MM_TO_FL_1_92);
 157                         led->movie_mode = true;
 158                 }
 159 
 160                 aat1290_as2cwire_write(led, AAT1290_MOVIE_MODE_CURRENT_ADDR,
 161                                 AAT1290_MAX_MM_CURR_PERCENT_0 - brightness);
 162                 aat1290_as2cwire_write(led, AAT1290_MOVIE_MODE_CONFIG_ADDR,
 163                                 AAT1290_MOVIE_MODE_ON);
 164         }
 165 
 166         mutex_unlock(&led->lock);
 167 
 168         return 0;
 169 }
 170 
 171 static int aat1290_led_flash_strobe_set(struct led_classdev_flash *fled_cdev,
 172                                          bool state)
 173 
 174 {
 175         struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
 176         struct led_classdev *led_cdev = &fled_cdev->led_cdev;
 177         struct led_flash_setting *timeout = &fled_cdev->timeout;
 178 
 179         mutex_lock(&led->lock);
 180 
 181         if (state) {
 182                 aat1290_set_flash_safety_timer(led, timeout->val);
 183                 gpiod_direction_output(led->gpio_fl_en, 1);
 184         } else {
 185                 gpiod_direction_output(led->gpio_fl_en, 0);
 186                 gpiod_direction_output(led->gpio_en_set, 0);
 187         }
 188 
 189         /*
 190          * To reenter movie mode after a flash event the part must be cycled
 191          * off and back on to reset the movie mode and reprogrammed via the
 192          * AS2Cwire. Therefore the brightness and movie_mode properties needs
 193          * to be updated here to reflect the actual state.
 194          */
 195         led_cdev->brightness = 0;
 196         led->movie_mode = false;
 197 
 198         mutex_unlock(&led->lock);
 199 
 200         return 0;
 201 }
 202 
 203 static int aat1290_led_flash_timeout_set(struct led_classdev_flash *fled_cdev,
 204                                                 u32 timeout)
 205 {
 206         /*
 207          * Don't do anything - flash timeout is cached in the led-class-flash
 208          * core and will be applied in the strobe_set op, as writing the
 209          * safety timer register spuriously turns the torch mode on.
 210          */
 211 
 212         return 0;
 213 }
 214 
 215 static int aat1290_led_parse_dt(struct aat1290_led *led,
 216                         struct aat1290_led_config_data *cfg,
 217                         struct device_node **sub_node)
 218 {
 219         struct device *dev = &led->pdev->dev;
 220         struct device_node *child_node;
 221 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
 222         struct pinctrl *pinctrl;
 223 #endif
 224         int ret = 0;
 225 
 226         led->gpio_fl_en = devm_gpiod_get(dev, "flen", GPIOD_ASIS);
 227         if (IS_ERR(led->gpio_fl_en)) {
 228                 ret = PTR_ERR(led->gpio_fl_en);
 229                 dev_err(dev, "Unable to claim gpio \"flen\".\n");
 230                 return ret;
 231         }
 232 
 233         led->gpio_en_set = devm_gpiod_get(dev, "enset", GPIOD_ASIS);
 234         if (IS_ERR(led->gpio_en_set)) {
 235                 ret = PTR_ERR(led->gpio_en_set);
 236                 dev_err(dev, "Unable to claim gpio \"enset\".\n");
 237                 return ret;
 238         }
 239 
 240 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
 241         pinctrl = devm_pinctrl_get_select_default(&led->pdev->dev);
 242         if (IS_ERR(pinctrl)) {
 243                 cfg->has_external_strobe = false;
 244                 dev_info(dev,
 245                          "No support for external strobe detected.\n");
 246         } else {
 247                 cfg->has_external_strobe = true;
 248         }
 249 #endif
 250 
 251         child_node = of_get_next_available_child(dev->of_node, NULL);
 252         if (!child_node) {
 253                 dev_err(dev, "No DT child node found for connected LED.\n");
 254                 return -EINVAL;
 255         }
 256 
 257         ret = of_property_read_u32(child_node, "led-max-microamp",
 258                                 &cfg->max_mm_current);
 259         /*
 260          * led-max-microamp will default to 1/20 of flash-max-microamp
 261          * in case it is missing.
 262          */
 263         if (ret < 0)
 264                 dev_warn(dev,
 265                         "led-max-microamp DT property missing\n");
 266 
 267         ret = of_property_read_u32(child_node, "flash-max-microamp",
 268                                 &cfg->max_flash_current);
 269         if (ret < 0) {
 270                 dev_err(dev,
 271                         "flash-max-microamp DT property missing\n");
 272                 goto err_parse_dt;
 273         }
 274 
 275         ret = of_property_read_u32(child_node, "flash-max-timeout-us",
 276                                 &cfg->max_flash_tm);
 277         if (ret < 0) {
 278                 dev_err(dev,
 279                         "flash-max-timeout-us DT property missing\n");
 280                 goto err_parse_dt;
 281         }
 282 
 283         *sub_node = child_node;
 284 
 285 err_parse_dt:
 286         of_node_put(child_node);
 287 
 288         return ret;
 289 }
 290 
 291 static void aat1290_led_validate_mm_current(struct aat1290_led *led,
 292                                         struct aat1290_led_config_data *cfg)
 293 {
 294         int i, b = 0, e = AAT1290_MM_CURRENT_SCALE_SIZE;
 295 
 296         while (e - b > 1) {
 297                 i = b + (e - b) / 2;
 298                 if (cfg->max_mm_current < led->mm_current_scale[i])
 299                         e = i;
 300                 else
 301                         b = i;
 302         }
 303 
 304         cfg->max_mm_current = led->mm_current_scale[b];
 305         cfg->max_brightness = b + 1;
 306 }
 307 
 308 static int init_mm_current_scale(struct aat1290_led *led,
 309                         struct aat1290_led_config_data *cfg)
 310 {
 311         static const int max_mm_current_percent[] = {
 312                 20, 22, 25, 28, 32, 36, 40, 45, 50, 56,
 313                 63, 71, 79, 89, 100
 314         };
 315         int i, max_mm_current =
 316                         AAT1290_MAX_MM_CURRENT(cfg->max_flash_current);
 317 
 318         led->mm_current_scale = devm_kzalloc(&led->pdev->dev,
 319                                         sizeof(max_mm_current_percent),
 320                                         GFP_KERNEL);
 321         if (!led->mm_current_scale)
 322                 return -ENOMEM;
 323 
 324         for (i = 0; i < AAT1290_MM_CURRENT_SCALE_SIZE; ++i)
 325                 led->mm_current_scale[i] = max_mm_current *
 326                                           max_mm_current_percent[i] / 100;
 327 
 328         return 0;
 329 }
 330 
 331 static int aat1290_led_get_configuration(struct aat1290_led *led,
 332                                         struct aat1290_led_config_data *cfg,
 333                                         struct device_node **sub_node)
 334 {
 335         int ret;
 336 
 337         ret = aat1290_led_parse_dt(led, cfg, sub_node);
 338         if (ret < 0)
 339                 return ret;
 340         /*
 341          * Init non-linear movie mode current scale basing
 342          * on the max flash current from led configuration.
 343          */
 344         ret = init_mm_current_scale(led, cfg);
 345         if (ret < 0)
 346                 return ret;
 347 
 348         aat1290_led_validate_mm_current(led, cfg);
 349 
 350 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
 351 #else
 352         devm_kfree(&led->pdev->dev, led->mm_current_scale);
 353 #endif
 354 
 355         return 0;
 356 }
 357 
 358 static void aat1290_init_flash_timeout(struct aat1290_led *led,
 359                                 struct aat1290_led_config_data *cfg)
 360 {
 361         struct led_classdev_flash *fled_cdev = &led->fled_cdev;
 362         struct led_flash_setting *setting;
 363 
 364         /* Init flash timeout setting */
 365         setting = &fled_cdev->timeout;
 366         setting->min = cfg->max_flash_tm / AAT1290_FLASH_TM_NUM_LEVELS;
 367         setting->max = cfg->max_flash_tm;
 368         setting->step = setting->min;
 369         setting->val = setting->max;
 370 }
 371 
 372 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
 373 static enum led_brightness aat1290_intensity_to_brightness(
 374                                         struct v4l2_flash *v4l2_flash,
 375                                         s32 intensity)
 376 {
 377         struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
 378         struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
 379         int i;
 380 
 381         for (i = AAT1290_MM_CURRENT_SCALE_SIZE - 1; i >= 0; --i)
 382                 if (intensity >= led->mm_current_scale[i])
 383                         return i + 1;
 384 
 385         return 1;
 386 }
 387 
 388 static s32 aat1290_brightness_to_intensity(struct v4l2_flash *v4l2_flash,
 389                                         enum led_brightness brightness)
 390 {
 391         struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
 392         struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
 393 
 394         return led->mm_current_scale[brightness - 1];
 395 }
 396 
 397 static int aat1290_led_external_strobe_set(struct v4l2_flash *v4l2_flash,
 398                                                 bool enable)
 399 {
 400         struct aat1290_led *led = fled_cdev_to_led(v4l2_flash->fled_cdev);
 401         struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
 402         struct led_classdev *led_cdev = &fled_cdev->led_cdev;
 403         struct pinctrl *pinctrl;
 404 
 405         gpiod_direction_output(led->gpio_fl_en, 0);
 406         gpiod_direction_output(led->gpio_en_set, 0);
 407 
 408         led->movie_mode = false;
 409         led_cdev->brightness = 0;
 410 
 411         pinctrl = devm_pinctrl_get_select(&led->pdev->dev,
 412                                                 enable ? "isp" : "host");
 413         if (IS_ERR(pinctrl)) {
 414                 dev_warn(&led->pdev->dev, "Unable to switch strobe source.\n");
 415                 return PTR_ERR(pinctrl);
 416         }
 417 
 418         return 0;
 419 }
 420 
 421 static void aat1290_init_v4l2_flash_config(struct aat1290_led *led,
 422                                         struct aat1290_led_config_data *led_cfg,
 423                                         struct v4l2_flash_config *v4l2_sd_cfg)
 424 {
 425         struct led_classdev *led_cdev = &led->fled_cdev.led_cdev;
 426         struct led_flash_setting *s;
 427 
 428         strlcpy(v4l2_sd_cfg->dev_name, led_cdev->dev->kobj.name,
 429                 sizeof(v4l2_sd_cfg->dev_name));
 430 
 431         s = &v4l2_sd_cfg->intensity;
 432         s->min = led->mm_current_scale[0];
 433         s->max = led_cfg->max_mm_current;
 434         s->step = 1;
 435         s->val = s->max;
 436 
 437         v4l2_sd_cfg->has_external_strobe = led_cfg->has_external_strobe;
 438 }
 439 
 440 static const struct v4l2_flash_ops v4l2_flash_ops = {
 441         .external_strobe_set = aat1290_led_external_strobe_set,
 442         .intensity_to_led_brightness = aat1290_intensity_to_brightness,
 443         .led_brightness_to_intensity = aat1290_brightness_to_intensity,
 444 };
 445 #else
 446 static inline void aat1290_init_v4l2_flash_config(struct aat1290_led *led,
 447                                 struct aat1290_led_config_data *led_cfg,
 448                                 struct v4l2_flash_config *v4l2_sd_cfg)
 449 {
 450 }
 451 static const struct v4l2_flash_ops v4l2_flash_ops;
 452 #endif
 453 
 454 static const struct led_flash_ops flash_ops = {
 455         .strobe_set = aat1290_led_flash_strobe_set,
 456         .timeout_set = aat1290_led_flash_timeout_set,
 457 };
 458 
 459 static int aat1290_led_probe(struct platform_device *pdev)
 460 {
 461         struct device *dev = &pdev->dev;
 462         struct device_node *sub_node = NULL;
 463         struct aat1290_led *led;
 464         struct led_classdev *led_cdev;
 465         struct led_classdev_flash *fled_cdev;
 466         struct led_init_data init_data = {};
 467         struct aat1290_led_config_data led_cfg = {};
 468         struct v4l2_flash_config v4l2_sd_cfg = {};
 469         int ret;
 470 
 471         led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
 472         if (!led)
 473                 return -ENOMEM;
 474 
 475         led->pdev = pdev;
 476         platform_set_drvdata(pdev, led);
 477 
 478         fled_cdev = &led->fled_cdev;
 479         fled_cdev->ops = &flash_ops;
 480         led_cdev = &fled_cdev->led_cdev;
 481 
 482         ret = aat1290_led_get_configuration(led, &led_cfg, &sub_node);
 483         if (ret < 0)
 484                 return ret;
 485 
 486         mutex_init(&led->lock);
 487 
 488         /* Initialize LED Flash class device */
 489         led_cdev->brightness_set_blocking = aat1290_led_brightness_set;
 490         led_cdev->max_brightness = led_cfg.max_brightness;
 491         led_cdev->flags |= LED_DEV_CAP_FLASH;
 492 
 493         aat1290_init_flash_timeout(led, &led_cfg);
 494 
 495         init_data.fwnode = of_fwnode_handle(sub_node);
 496         init_data.devicename = AAT1290_NAME;
 497 
 498         /* Register LED Flash class device */
 499         ret = led_classdev_flash_register_ext(&pdev->dev, fled_cdev,
 500                                               &init_data);
 501         if (ret < 0)
 502                 goto err_flash_register;
 503 
 504         aat1290_init_v4l2_flash_config(led, &led_cfg, &v4l2_sd_cfg);
 505 
 506         /* Create V4L2 Flash subdev. */
 507         led->v4l2_flash = v4l2_flash_init(dev, of_fwnode_handle(sub_node),
 508                                           fled_cdev, &v4l2_flash_ops,
 509                                           &v4l2_sd_cfg);
 510         if (IS_ERR(led->v4l2_flash)) {
 511                 ret = PTR_ERR(led->v4l2_flash);
 512                 goto error_v4l2_flash_init;
 513         }
 514 
 515         return 0;
 516 
 517 error_v4l2_flash_init:
 518         led_classdev_flash_unregister(fled_cdev);
 519 err_flash_register:
 520         mutex_destroy(&led->lock);
 521 
 522         return ret;
 523 }
 524 
 525 static int aat1290_led_remove(struct platform_device *pdev)
 526 {
 527         struct aat1290_led *led = platform_get_drvdata(pdev);
 528 
 529         v4l2_flash_release(led->v4l2_flash);
 530         led_classdev_flash_unregister(&led->fled_cdev);
 531 
 532         mutex_destroy(&led->lock);
 533 
 534         return 0;
 535 }
 536 
 537 static const struct of_device_id aat1290_led_dt_match[] = {
 538         { .compatible = "skyworks,aat1290" },
 539         {},
 540 };
 541 MODULE_DEVICE_TABLE(of, aat1290_led_dt_match);
 542 
 543 static struct platform_driver aat1290_led_driver = {
 544         .probe          = aat1290_led_probe,
 545         .remove         = aat1290_led_remove,
 546         .driver         = {
 547                 .name   = "aat1290",
 548                 .of_match_table = aat1290_led_dt_match,
 549         },
 550 };
 551 
 552 module_platform_driver(aat1290_led_driver);
 553 
 554 MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
 555 MODULE_DESCRIPTION("Skyworks Current Regulator for Flash LEDs");
 556 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */