Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  LED Flash class driver for the AAT1290
0004  *  1.5A Step-Up Current Regulator for Flash LEDs
0005  *
0006  *  Copyright (C) 2015, Samsung Electronics Co., Ltd.
0007  *  Author: Jacek Anaszewski <j.anaszewski@samsung.com>
0008  */
0009 
0010 #include <linux/delay.h>
0011 #include <linux/gpio/consumer.h>
0012 #include <linux/led-class-flash.h>
0013 #include <linux/leds.h>
0014 #include <linux/module.h>
0015 #include <linux/mutex.h>
0016 #include <linux/of.h>
0017 #include <linux/pinctrl/consumer.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/slab.h>
0020 #include <media/v4l2-flash-led-class.h>
0021 
0022 #define AAT1290_MOVIE_MODE_CURRENT_ADDR 17
0023 #define AAT1290_MAX_MM_CURR_PERCENT_0   16
0024 #define AAT1290_MAX_MM_CURR_PERCENT_100 1
0025 
0026 #define AAT1290_FLASH_SAFETY_TIMER_ADDR 18
0027 
0028 #define AAT1290_MOVIE_MODE_CONFIG_ADDR  19
0029 #define AAT1290_MOVIE_MODE_OFF      1
0030 #define AAT1290_MOVIE_MODE_ON       3
0031 
0032 #define AAT1290_MM_CURRENT_RATIO_ADDR   20
0033 #define AAT1290_MM_TO_FL_1_92       1
0034 
0035 #define AAT1290_MM_TO_FL_RATIO      1000 / 1920
0036 #define AAT1290_MAX_MM_CURRENT(fl_max)  (fl_max * AAT1290_MM_TO_FL_RATIO)
0037 
0038 #define AAT1290_LATCH_TIME_MIN_US   500
0039 #define AAT1290_LATCH_TIME_MAX_US   1000
0040 #define AAT1290_EN_SET_TICK_TIME_US 1
0041 #define AAT1290_FLEN_OFF_DELAY_TIME_US  10
0042 #define AAT1290_FLASH_TM_NUM_LEVELS 16
0043 #define AAT1290_MM_CURRENT_SCALE_SIZE   15
0044 
0045 #define AAT1290_NAME            "aat1290"
0046 
0047 
0048 struct aat1290_led_config_data {
0049     /* maximum LED current in movie mode */
0050     u32 max_mm_current;
0051     /* maximum LED current in flash mode */
0052     u32 max_flash_current;
0053     /* maximum flash timeout */
0054     u32 max_flash_tm;
0055     /* external strobe capability */
0056     bool has_external_strobe;
0057     /* max LED brightness level */
0058     enum led_brightness max_brightness;
0059 };
0060 
0061 struct aat1290_led {
0062     /* platform device data */
0063     struct platform_device *pdev;
0064     /* secures access to the device */
0065     struct mutex lock;
0066 
0067     /* corresponding LED Flash class device */
0068     struct led_classdev_flash fled_cdev;
0069     /* V4L2 Flash device */
0070     struct v4l2_flash *v4l2_flash;
0071 
0072     /* FLEN pin */
0073     struct gpio_desc *gpio_fl_en;
0074     /* EN|SET pin  */
0075     struct gpio_desc *gpio_en_set;
0076     /* movie mode current scale */
0077     int *mm_current_scale;
0078     /* device mode */
0079     bool movie_mode;
0080     /* brightness cache */
0081     unsigned int torch_brightness;
0082 };
0083 
0084 static struct aat1290_led *fled_cdev_to_led(
0085                 struct led_classdev_flash *fled_cdev)
0086 {
0087     return container_of(fled_cdev, struct aat1290_led, fled_cdev);
0088 }
0089 
0090 static struct led_classdev_flash *led_cdev_to_fled_cdev(
0091                 struct led_classdev *led_cdev)
0092 {
0093     return container_of(led_cdev, struct led_classdev_flash, led_cdev);
0094 }
0095 
0096 static void aat1290_as2cwire_write(struct aat1290_led *led, int addr, int value)
0097 {
0098     int i;
0099 
0100     gpiod_direction_output(led->gpio_fl_en, 0);
0101     gpiod_direction_output(led->gpio_en_set, 0);
0102 
0103     udelay(AAT1290_FLEN_OFF_DELAY_TIME_US);
0104 
0105     /* write address */
0106     for (i = 0; i < addr; ++i) {
0107         udelay(AAT1290_EN_SET_TICK_TIME_US);
0108         gpiod_direction_output(led->gpio_en_set, 0);
0109         udelay(AAT1290_EN_SET_TICK_TIME_US);
0110         gpiod_direction_output(led->gpio_en_set, 1);
0111     }
0112 
0113     usleep_range(AAT1290_LATCH_TIME_MIN_US, AAT1290_LATCH_TIME_MAX_US);
0114 
0115     /* write data */
0116     for (i = 0; i < value; ++i) {
0117         udelay(AAT1290_EN_SET_TICK_TIME_US);
0118         gpiod_direction_output(led->gpio_en_set, 0);
0119         udelay(AAT1290_EN_SET_TICK_TIME_US);
0120         gpiod_direction_output(led->gpio_en_set, 1);
0121     }
0122 
0123     usleep_range(AAT1290_LATCH_TIME_MIN_US, AAT1290_LATCH_TIME_MAX_US);
0124 }
0125 
0126 static void aat1290_set_flash_safety_timer(struct aat1290_led *led,
0127                     unsigned int micro_sec)
0128 {
0129     struct led_classdev_flash *fled_cdev = &led->fled_cdev;
0130     struct led_flash_setting *flash_tm = &fled_cdev->timeout;
0131     int flash_tm_reg = AAT1290_FLASH_TM_NUM_LEVELS -
0132                 (micro_sec / flash_tm->step) + 1;
0133 
0134     aat1290_as2cwire_write(led, AAT1290_FLASH_SAFETY_TIMER_ADDR,
0135                             flash_tm_reg);
0136 }
0137 
0138 /* LED subsystem callbacks */
0139 
0140 static int aat1290_led_brightness_set(struct led_classdev *led_cdev,
0141                     enum led_brightness brightness)
0142 {
0143     struct led_classdev_flash *fled_cdev = led_cdev_to_fled_cdev(led_cdev);
0144     struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
0145 
0146     mutex_lock(&led->lock);
0147 
0148     if (brightness == 0) {
0149         gpiod_direction_output(led->gpio_fl_en, 0);
0150         gpiod_direction_output(led->gpio_en_set, 0);
0151         led->movie_mode = false;
0152     } else {
0153         if (!led->movie_mode) {
0154             aat1290_as2cwire_write(led,
0155                 AAT1290_MM_CURRENT_RATIO_ADDR,
0156                 AAT1290_MM_TO_FL_1_92);
0157             led->movie_mode = true;
0158         }
0159 
0160         aat1290_as2cwire_write(led, AAT1290_MOVIE_MODE_CURRENT_ADDR,
0161                 AAT1290_MAX_MM_CURR_PERCENT_0 - brightness);
0162         aat1290_as2cwire_write(led, AAT1290_MOVIE_MODE_CONFIG_ADDR,
0163                 AAT1290_MOVIE_MODE_ON);
0164     }
0165 
0166     mutex_unlock(&led->lock);
0167 
0168     return 0;
0169 }
0170 
0171 static int aat1290_led_flash_strobe_set(struct led_classdev_flash *fled_cdev,
0172                      bool state)
0173 
0174 {
0175     struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
0176     struct led_classdev *led_cdev = &fled_cdev->led_cdev;
0177     struct led_flash_setting *timeout = &fled_cdev->timeout;
0178 
0179     mutex_lock(&led->lock);
0180 
0181     if (state) {
0182         aat1290_set_flash_safety_timer(led, timeout->val);
0183         gpiod_direction_output(led->gpio_fl_en, 1);
0184     } else {
0185         gpiod_direction_output(led->gpio_fl_en, 0);
0186         gpiod_direction_output(led->gpio_en_set, 0);
0187     }
0188 
0189     /*
0190      * To reenter movie mode after a flash event the part must be cycled
0191      * off and back on to reset the movie mode and reprogrammed via the
0192      * AS2Cwire. Therefore the brightness and movie_mode properties needs
0193      * to be updated here to reflect the actual state.
0194      */
0195     led_cdev->brightness = 0;
0196     led->movie_mode = false;
0197 
0198     mutex_unlock(&led->lock);
0199 
0200     return 0;
0201 }
0202 
0203 static int aat1290_led_flash_timeout_set(struct led_classdev_flash *fled_cdev,
0204                         u32 timeout)
0205 {
0206     /*
0207      * Don't do anything - flash timeout is cached in the led-class-flash
0208      * core and will be applied in the strobe_set op, as writing the
0209      * safety timer register spuriously turns the torch mode on.
0210      */
0211 
0212     return 0;
0213 }
0214 
0215 static int aat1290_led_parse_dt(struct aat1290_led *led,
0216             struct aat1290_led_config_data *cfg,
0217             struct device_node **sub_node)
0218 {
0219     struct device *dev = &led->pdev->dev;
0220     struct device_node *child_node;
0221 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
0222     struct pinctrl *pinctrl;
0223 #endif
0224     int ret = 0;
0225 
0226     led->gpio_fl_en = devm_gpiod_get(dev, "flen", GPIOD_ASIS);
0227     if (IS_ERR(led->gpio_fl_en)) {
0228         ret = PTR_ERR(led->gpio_fl_en);
0229         dev_err(dev, "Unable to claim gpio \"flen\".\n");
0230         return ret;
0231     }
0232 
0233     led->gpio_en_set = devm_gpiod_get(dev, "enset", GPIOD_ASIS);
0234     if (IS_ERR(led->gpio_en_set)) {
0235         ret = PTR_ERR(led->gpio_en_set);
0236         dev_err(dev, "Unable to claim gpio \"enset\".\n");
0237         return ret;
0238     }
0239 
0240 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
0241     pinctrl = devm_pinctrl_get_select_default(&led->pdev->dev);
0242     if (IS_ERR(pinctrl)) {
0243         cfg->has_external_strobe = false;
0244         dev_info(dev,
0245              "No support for external strobe detected.\n");
0246     } else {
0247         cfg->has_external_strobe = true;
0248     }
0249 #endif
0250 
0251     child_node = of_get_next_available_child(dev_of_node(dev), NULL);
0252     if (!child_node) {
0253         dev_err(dev, "No DT child node found for connected LED.\n");
0254         return -EINVAL;
0255     }
0256 
0257     ret = of_property_read_u32(child_node, "led-max-microamp",
0258                 &cfg->max_mm_current);
0259     /*
0260      * led-max-microamp will default to 1/20 of flash-max-microamp
0261      * in case it is missing.
0262      */
0263     if (ret < 0)
0264         dev_warn(dev,
0265             "led-max-microamp DT property missing\n");
0266 
0267     ret = of_property_read_u32(child_node, "flash-max-microamp",
0268                 &cfg->max_flash_current);
0269     if (ret < 0) {
0270         dev_err(dev,
0271             "flash-max-microamp DT property missing\n");
0272         goto err_parse_dt;
0273     }
0274 
0275     ret = of_property_read_u32(child_node, "flash-max-timeout-us",
0276                 &cfg->max_flash_tm);
0277     if (ret < 0) {
0278         dev_err(dev,
0279             "flash-max-timeout-us DT property missing\n");
0280         goto err_parse_dt;
0281     }
0282 
0283     *sub_node = child_node;
0284 
0285 err_parse_dt:
0286     of_node_put(child_node);
0287 
0288     return ret;
0289 }
0290 
0291 static void aat1290_led_validate_mm_current(struct aat1290_led *led,
0292                     struct aat1290_led_config_data *cfg)
0293 {
0294     int i, b = 0, e = AAT1290_MM_CURRENT_SCALE_SIZE;
0295 
0296     while (e - b > 1) {
0297         i = b + (e - b) / 2;
0298         if (cfg->max_mm_current < led->mm_current_scale[i])
0299             e = i;
0300         else
0301             b = i;
0302     }
0303 
0304     cfg->max_mm_current = led->mm_current_scale[b];
0305     cfg->max_brightness = b + 1;
0306 }
0307 
0308 static int init_mm_current_scale(struct aat1290_led *led,
0309             struct aat1290_led_config_data *cfg)
0310 {
0311     static const int max_mm_current_percent[] = {
0312         20, 22, 25, 28, 32, 36, 40, 45, 50, 56,
0313         63, 71, 79, 89, 100
0314     };
0315     int i, max_mm_current =
0316             AAT1290_MAX_MM_CURRENT(cfg->max_flash_current);
0317 
0318     led->mm_current_scale = devm_kzalloc(&led->pdev->dev,
0319                     sizeof(max_mm_current_percent),
0320                     GFP_KERNEL);
0321     if (!led->mm_current_scale)
0322         return -ENOMEM;
0323 
0324     for (i = 0; i < AAT1290_MM_CURRENT_SCALE_SIZE; ++i)
0325         led->mm_current_scale[i] = max_mm_current *
0326                       max_mm_current_percent[i] / 100;
0327 
0328     return 0;
0329 }
0330 
0331 static int aat1290_led_get_configuration(struct aat1290_led *led,
0332                     struct aat1290_led_config_data *cfg,
0333                     struct device_node **sub_node)
0334 {
0335     int ret;
0336 
0337     ret = aat1290_led_parse_dt(led, cfg, sub_node);
0338     if (ret < 0)
0339         return ret;
0340     /*
0341      * Init non-linear movie mode current scale basing
0342      * on the max flash current from led configuration.
0343      */
0344     ret = init_mm_current_scale(led, cfg);
0345     if (ret < 0)
0346         return ret;
0347 
0348     aat1290_led_validate_mm_current(led, cfg);
0349 
0350 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
0351 #else
0352     devm_kfree(&led->pdev->dev, led->mm_current_scale);
0353 #endif
0354 
0355     return 0;
0356 }
0357 
0358 static void aat1290_init_flash_timeout(struct aat1290_led *led,
0359                 struct aat1290_led_config_data *cfg)
0360 {
0361     struct led_classdev_flash *fled_cdev = &led->fled_cdev;
0362     struct led_flash_setting *setting;
0363 
0364     /* Init flash timeout setting */
0365     setting = &fled_cdev->timeout;
0366     setting->min = cfg->max_flash_tm / AAT1290_FLASH_TM_NUM_LEVELS;
0367     setting->max = cfg->max_flash_tm;
0368     setting->step = setting->min;
0369     setting->val = setting->max;
0370 }
0371 
0372 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
0373 static enum led_brightness aat1290_intensity_to_brightness(
0374                     struct v4l2_flash *v4l2_flash,
0375                     s32 intensity)
0376 {
0377     struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
0378     struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
0379     int i;
0380 
0381     for (i = AAT1290_MM_CURRENT_SCALE_SIZE - 1; i >= 0; --i)
0382         if (intensity >= led->mm_current_scale[i])
0383             return i + 1;
0384 
0385     return 1;
0386 }
0387 
0388 static s32 aat1290_brightness_to_intensity(struct v4l2_flash *v4l2_flash,
0389                     enum led_brightness brightness)
0390 {
0391     struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
0392     struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
0393 
0394     return led->mm_current_scale[brightness - 1];
0395 }
0396 
0397 static int aat1290_led_external_strobe_set(struct v4l2_flash *v4l2_flash,
0398                         bool enable)
0399 {
0400     struct aat1290_led *led = fled_cdev_to_led(v4l2_flash->fled_cdev);
0401     struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
0402     struct led_classdev *led_cdev = &fled_cdev->led_cdev;
0403     struct pinctrl *pinctrl;
0404 
0405     gpiod_direction_output(led->gpio_fl_en, 0);
0406     gpiod_direction_output(led->gpio_en_set, 0);
0407 
0408     led->movie_mode = false;
0409     led_cdev->brightness = 0;
0410 
0411     pinctrl = devm_pinctrl_get_select(&led->pdev->dev,
0412                         enable ? "isp" : "host");
0413     if (IS_ERR(pinctrl)) {
0414         dev_warn(&led->pdev->dev, "Unable to switch strobe source.\n");
0415         return PTR_ERR(pinctrl);
0416     }
0417 
0418     return 0;
0419 }
0420 
0421 static void aat1290_init_v4l2_flash_config(struct aat1290_led *led,
0422                     struct aat1290_led_config_data *led_cfg,
0423                     struct v4l2_flash_config *v4l2_sd_cfg)
0424 {
0425     struct led_classdev *led_cdev = &led->fled_cdev.led_cdev;
0426     struct led_flash_setting *s;
0427 
0428     strlcpy(v4l2_sd_cfg->dev_name, led_cdev->dev->kobj.name,
0429         sizeof(v4l2_sd_cfg->dev_name));
0430 
0431     s = &v4l2_sd_cfg->intensity;
0432     s->min = led->mm_current_scale[0];
0433     s->max = led_cfg->max_mm_current;
0434     s->step = 1;
0435     s->val = s->max;
0436 
0437     v4l2_sd_cfg->has_external_strobe = led_cfg->has_external_strobe;
0438 }
0439 
0440 static const struct v4l2_flash_ops v4l2_flash_ops = {
0441     .external_strobe_set = aat1290_led_external_strobe_set,
0442     .intensity_to_led_brightness = aat1290_intensity_to_brightness,
0443     .led_brightness_to_intensity = aat1290_brightness_to_intensity,
0444 };
0445 #else
0446 static inline void aat1290_init_v4l2_flash_config(struct aat1290_led *led,
0447                 struct aat1290_led_config_data *led_cfg,
0448                 struct v4l2_flash_config *v4l2_sd_cfg)
0449 {
0450 }
0451 static const struct v4l2_flash_ops v4l2_flash_ops;
0452 #endif
0453 
0454 static const struct led_flash_ops flash_ops = {
0455     .strobe_set = aat1290_led_flash_strobe_set,
0456     .timeout_set = aat1290_led_flash_timeout_set,
0457 };
0458 
0459 static int aat1290_led_probe(struct platform_device *pdev)
0460 {
0461     struct device *dev = &pdev->dev;
0462     struct device_node *sub_node = NULL;
0463     struct aat1290_led *led;
0464     struct led_classdev *led_cdev;
0465     struct led_classdev_flash *fled_cdev;
0466     struct led_init_data init_data = {};
0467     struct aat1290_led_config_data led_cfg = {};
0468     struct v4l2_flash_config v4l2_sd_cfg = {};
0469     int ret;
0470 
0471     led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
0472     if (!led)
0473         return -ENOMEM;
0474 
0475     led->pdev = pdev;
0476     platform_set_drvdata(pdev, led);
0477 
0478     fled_cdev = &led->fled_cdev;
0479     fled_cdev->ops = &flash_ops;
0480     led_cdev = &fled_cdev->led_cdev;
0481 
0482     ret = aat1290_led_get_configuration(led, &led_cfg, &sub_node);
0483     if (ret < 0)
0484         return ret;
0485 
0486     mutex_init(&led->lock);
0487 
0488     /* Initialize LED Flash class device */
0489     led_cdev->brightness_set_blocking = aat1290_led_brightness_set;
0490     led_cdev->max_brightness = led_cfg.max_brightness;
0491     led_cdev->flags |= LED_DEV_CAP_FLASH;
0492 
0493     aat1290_init_flash_timeout(led, &led_cfg);
0494 
0495     init_data.fwnode = of_fwnode_handle(sub_node);
0496     init_data.devicename = AAT1290_NAME;
0497 
0498     /* Register LED Flash class device */
0499     ret = led_classdev_flash_register_ext(&pdev->dev, fled_cdev,
0500                           &init_data);
0501     if (ret < 0)
0502         goto err_flash_register;
0503 
0504     aat1290_init_v4l2_flash_config(led, &led_cfg, &v4l2_sd_cfg);
0505 
0506     /* Create V4L2 Flash subdev. */
0507     led->v4l2_flash = v4l2_flash_init(dev, of_fwnode_handle(sub_node),
0508                       fled_cdev, &v4l2_flash_ops,
0509                       &v4l2_sd_cfg);
0510     if (IS_ERR(led->v4l2_flash)) {
0511         ret = PTR_ERR(led->v4l2_flash);
0512         goto error_v4l2_flash_init;
0513     }
0514 
0515     return 0;
0516 
0517 error_v4l2_flash_init:
0518     led_classdev_flash_unregister(fled_cdev);
0519 err_flash_register:
0520     mutex_destroy(&led->lock);
0521 
0522     return ret;
0523 }
0524 
0525 static int aat1290_led_remove(struct platform_device *pdev)
0526 {
0527     struct aat1290_led *led = platform_get_drvdata(pdev);
0528 
0529     v4l2_flash_release(led->v4l2_flash);
0530     led_classdev_flash_unregister(&led->fled_cdev);
0531 
0532     mutex_destroy(&led->lock);
0533 
0534     return 0;
0535 }
0536 
0537 static const struct of_device_id aat1290_led_dt_match[] = {
0538     { .compatible = "skyworks,aat1290" },
0539     {},
0540 };
0541 MODULE_DEVICE_TABLE(of, aat1290_led_dt_match);
0542 
0543 static struct platform_driver aat1290_led_driver = {
0544     .probe      = aat1290_led_probe,
0545     .remove     = aat1290_led_remove,
0546     .driver     = {
0547         .name   = "aat1290",
0548         .of_match_table = aat1290_led_dt_match,
0549     },
0550 };
0551 
0552 module_platform_driver(aat1290_led_driver);
0553 
0554 MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
0555 MODULE_DESCRIPTION("Skyworks Current Regulator for Flash LEDs");
0556 MODULE_LICENSE("GPL v2");