Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * LED Flash class driver for the flash cell of max77693 mfd.
0004  *
0005  *  Copyright (C) 2015, Samsung Electronics Co., Ltd.
0006  *
0007  *  Authors: Jacek Anaszewski <j.anaszewski@samsung.com>
0008  *       Andrzej Hajda <a.hajda@samsung.com>
0009  */
0010 
0011 #include <linux/led-class-flash.h>
0012 #include <linux/mfd/max77693.h>
0013 #include <linux/mfd/max77693-common.h>
0014 #include <linux/mfd/max77693-private.h>
0015 #include <linux/module.h>
0016 #include <linux/mutex.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/regmap.h>
0019 #include <linux/slab.h>
0020 #include <media/v4l2-flash-led-class.h>
0021 
0022 #define MODE_OFF        0
0023 #define MODE_FLASH(a)       (1 << (a))
0024 #define MODE_TORCH(a)       (1 << (2 + (a)))
0025 #define MODE_FLASH_EXTERNAL(a)  (1 << (4 + (a)))
0026 
0027 #define MODE_FLASH_MASK     (MODE_FLASH(FLED1) | MODE_FLASH(FLED2) | \
0028                  MODE_FLASH_EXTERNAL(FLED1) | \
0029                  MODE_FLASH_EXTERNAL(FLED2))
0030 #define MODE_TORCH_MASK     (MODE_TORCH(FLED1) | MODE_TORCH(FLED2))
0031 
0032 #define FLED1_IOUT      (1 << 0)
0033 #define FLED2_IOUT      (1 << 1)
0034 
0035 enum max77693_fled {
0036     FLED1,
0037     FLED2,
0038 };
0039 
0040 enum max77693_led_mode {
0041     FLASH,
0042     TORCH,
0043 };
0044 
0045 struct max77693_led_config_data {
0046     const char *label[2];
0047     u32 iout_torch_max[2];
0048     u32 iout_flash_max[2];
0049     u32 flash_timeout_max[2];
0050     u32 num_leds;
0051     u32 boost_mode;
0052     u32 boost_vout;
0053     u32 low_vsys;
0054 };
0055 
0056 struct max77693_sub_led {
0057     /* corresponding FLED output identifier */
0058     int fled_id;
0059     /* corresponding LED Flash class device */
0060     struct led_classdev_flash fled_cdev;
0061     /* V4L2 Flash device */
0062     struct v4l2_flash *v4l2_flash;
0063 
0064     /* brightness cache */
0065     unsigned int torch_brightness;
0066     /* flash timeout cache */
0067     unsigned int flash_timeout;
0068     /* flash faults that may have occurred */
0069     u32 flash_faults;
0070 };
0071 
0072 struct max77693_led_device {
0073     /* parent mfd regmap */
0074     struct regmap *regmap;
0075     /* platform device data */
0076     struct platform_device *pdev;
0077     /* secures access to the device */
0078     struct mutex lock;
0079 
0080     /* sub led data */
0081     struct max77693_sub_led sub_leds[2];
0082 
0083     /* maximum torch current values for FLED outputs */
0084     u32 iout_torch_max[2];
0085     /* maximum flash current values for FLED outputs */
0086     u32 iout_flash_max[2];
0087 
0088     /* current flash timeout cache */
0089     unsigned int current_flash_timeout;
0090     /* ITORCH register cache */
0091     u8 torch_iout_reg;
0092     /* mode of fled outputs */
0093     unsigned int mode_flags;
0094     /* recently strobed fled */
0095     int strobing_sub_led_id;
0096     /* bitmask of FLED outputs use state (bit 0. - FLED1, bit 1. - FLED2) */
0097     u8 fled_mask;
0098     /* FLED modes that can be set */
0099     u8 allowed_modes;
0100 
0101     /* arrangement of current outputs */
0102     bool iout_joint;
0103 };
0104 
0105 static u8 max77693_led_iout_to_reg(u32 ua)
0106 {
0107     if (ua < FLASH_IOUT_MIN)
0108         ua = FLASH_IOUT_MIN;
0109     return (ua - FLASH_IOUT_MIN) / FLASH_IOUT_STEP;
0110 }
0111 
0112 static u8 max77693_flash_timeout_to_reg(u32 us)
0113 {
0114     return (us - FLASH_TIMEOUT_MIN) / FLASH_TIMEOUT_STEP;
0115 }
0116 
0117 static inline struct max77693_sub_led *flcdev_to_sub_led(
0118                     struct led_classdev_flash *fled_cdev)
0119 {
0120     return container_of(fled_cdev, struct max77693_sub_led, fled_cdev);
0121 }
0122 
0123 static inline struct max77693_led_device *sub_led_to_led(
0124                     struct max77693_sub_led *sub_led)
0125 {
0126     return container_of(sub_led, struct max77693_led_device,
0127                 sub_leds[sub_led->fled_id]);
0128 }
0129 
0130 static inline u8 max77693_led_vsys_to_reg(u32 mv)
0131 {
0132     return ((mv - MAX_FLASH1_VSYS_MIN) / MAX_FLASH1_VSYS_STEP) << 2;
0133 }
0134 
0135 static inline u8 max77693_led_vout_to_reg(u32 mv)
0136 {
0137     return (mv - FLASH_VOUT_MIN) / FLASH_VOUT_STEP + FLASH_VOUT_RMIN;
0138 }
0139 
0140 static inline bool max77693_fled_used(struct max77693_led_device *led,
0141                      int fled_id)
0142 {
0143     u8 fled_bit = (fled_id == FLED1) ? FLED1_IOUT : FLED2_IOUT;
0144 
0145     return led->fled_mask & fled_bit;
0146 }
0147 
0148 static int max77693_set_mode_reg(struct max77693_led_device *led, u8 mode)
0149 {
0150     struct regmap *rmap = led->regmap;
0151     int ret, v = 0, i;
0152 
0153     for (i = FLED1; i <= FLED2; ++i) {
0154         if (mode & MODE_TORCH(i))
0155             v |= FLASH_EN_ON << TORCH_EN_SHIFT(i);
0156 
0157         if (mode & MODE_FLASH(i)) {
0158             v |= FLASH_EN_ON << FLASH_EN_SHIFT(i);
0159         } else if (mode & MODE_FLASH_EXTERNAL(i)) {
0160             v |= FLASH_EN_FLASH << FLASH_EN_SHIFT(i);
0161             /*
0162              * Enable hw triggering also for torch mode, as some
0163              * camera sensors use torch led to fathom ambient light
0164              * conditions before strobing the flash.
0165              */
0166             v |= FLASH_EN_TORCH << TORCH_EN_SHIFT(i);
0167         }
0168     }
0169 
0170     /* Reset the register only prior setting flash modes */
0171     if (mode & ~(MODE_TORCH(FLED1) | MODE_TORCH(FLED2))) {
0172         ret = regmap_write(rmap, MAX77693_LED_REG_FLASH_EN, 0);
0173         if (ret < 0)
0174             return ret;
0175     }
0176 
0177     return regmap_write(rmap, MAX77693_LED_REG_FLASH_EN, v);
0178 }
0179 
0180 static int max77693_add_mode(struct max77693_led_device *led, u8 mode)
0181 {
0182     u8 new_mode_flags;
0183     int i, ret;
0184 
0185     if (led->iout_joint)
0186         /* Span the mode on FLED2 for joint iouts case */
0187         mode |= (mode << 1);
0188 
0189     /*
0190      * FLASH_EXTERNAL mode activates FLASHEN and TORCHEN pins in the device.
0191      * Corresponding register bit fields interfere with SW triggered modes,
0192      * thus clear them to ensure proper device configuration.
0193      */
0194     for (i = FLED1; i <= FLED2; ++i)
0195         if (mode & MODE_FLASH_EXTERNAL(i))
0196             led->mode_flags &= (~MODE_TORCH(i) & ~MODE_FLASH(i));
0197 
0198     new_mode_flags = mode | led->mode_flags;
0199     new_mode_flags &= led->allowed_modes;
0200 
0201     if (new_mode_flags ^ led->mode_flags)
0202         led->mode_flags = new_mode_flags;
0203     else
0204         return 0;
0205 
0206     ret = max77693_set_mode_reg(led, led->mode_flags);
0207     if (ret < 0)
0208         return ret;
0209 
0210     /*
0211      * Clear flash mode flag after setting the mode to avoid spurious flash
0212      * strobing on each subsequent torch mode setting.
0213      */
0214     if (mode & MODE_FLASH_MASK)
0215         led->mode_flags &= ~mode;
0216 
0217     return ret;
0218 }
0219 
0220 static int max77693_clear_mode(struct max77693_led_device *led,
0221                 u8 mode)
0222 {
0223     if (led->iout_joint)
0224         /* Clear mode also on FLED2 for joint iouts case */
0225         mode |= (mode << 1);
0226 
0227     led->mode_flags &= ~mode;
0228 
0229     return max77693_set_mode_reg(led, led->mode_flags);
0230 }
0231 
0232 static void max77693_add_allowed_modes(struct max77693_led_device *led,
0233                 int fled_id, enum max77693_led_mode mode)
0234 {
0235     if (mode == FLASH)
0236         led->allowed_modes |= (MODE_FLASH(fled_id) |
0237                        MODE_FLASH_EXTERNAL(fled_id));
0238     else
0239         led->allowed_modes |= MODE_TORCH(fled_id);
0240 }
0241 
0242 static void max77693_distribute_currents(struct max77693_led_device *led,
0243                 int fled_id, enum max77693_led_mode mode,
0244                 u32 micro_amp, u32 iout_max[2], u32 iout[2])
0245 {
0246     if (!led->iout_joint) {
0247         iout[fled_id] = micro_amp;
0248         max77693_add_allowed_modes(led, fled_id, mode);
0249         return;
0250     }
0251 
0252     iout[FLED1] = min(micro_amp, iout_max[FLED1]);
0253     iout[FLED2] = micro_amp - iout[FLED1];
0254 
0255     if (mode == FLASH)
0256         led->allowed_modes &= ~MODE_FLASH_MASK;
0257     else
0258         led->allowed_modes &= ~MODE_TORCH_MASK;
0259 
0260     max77693_add_allowed_modes(led, FLED1, mode);
0261 
0262     if (iout[FLED2])
0263         max77693_add_allowed_modes(led, FLED2, mode);
0264 }
0265 
0266 static int max77693_set_torch_current(struct max77693_led_device *led,
0267                 int fled_id, u32 micro_amp)
0268 {
0269     struct regmap *rmap = led->regmap;
0270     u8 iout1_reg = 0, iout2_reg = 0;
0271     u32 iout[2];
0272 
0273     max77693_distribute_currents(led, fled_id, TORCH, micro_amp,
0274                     led->iout_torch_max, iout);
0275 
0276     if (fled_id == FLED1 || led->iout_joint) {
0277         iout1_reg = max77693_led_iout_to_reg(iout[FLED1]);
0278         led->torch_iout_reg &= TORCH_IOUT_MASK(TORCH_IOUT2_SHIFT);
0279     }
0280     if (fled_id == FLED2 || led->iout_joint) {
0281         iout2_reg = max77693_led_iout_to_reg(iout[FLED2]);
0282         led->torch_iout_reg &= TORCH_IOUT_MASK(TORCH_IOUT1_SHIFT);
0283     }
0284 
0285     led->torch_iout_reg |= ((iout1_reg << TORCH_IOUT1_SHIFT) |
0286                 (iout2_reg << TORCH_IOUT2_SHIFT));
0287 
0288     return regmap_write(rmap, MAX77693_LED_REG_ITORCH,
0289                         led->torch_iout_reg);
0290 }
0291 
0292 static int max77693_set_flash_current(struct max77693_led_device *led,
0293                     int fled_id,
0294                     u32 micro_amp)
0295 {
0296     struct regmap *rmap = led->regmap;
0297     u8 iout1_reg, iout2_reg;
0298     u32 iout[2];
0299     int ret = -EINVAL;
0300 
0301     max77693_distribute_currents(led, fled_id, FLASH, micro_amp,
0302                     led->iout_flash_max, iout);
0303 
0304     if (fled_id == FLED1 || led->iout_joint) {
0305         iout1_reg = max77693_led_iout_to_reg(iout[FLED1]);
0306         ret = regmap_write(rmap, MAX77693_LED_REG_IFLASH1,
0307                             iout1_reg);
0308         if (ret < 0)
0309             return ret;
0310     }
0311     if (fled_id == FLED2 || led->iout_joint) {
0312         iout2_reg = max77693_led_iout_to_reg(iout[FLED2]);
0313         ret = regmap_write(rmap, MAX77693_LED_REG_IFLASH2,
0314                             iout2_reg);
0315     }
0316 
0317     return ret;
0318 }
0319 
0320 static int max77693_set_timeout(struct max77693_led_device *led, u32 microsec)
0321 {
0322     struct regmap *rmap = led->regmap;
0323     u8 v;
0324     int ret;
0325 
0326     v = max77693_flash_timeout_to_reg(microsec) | FLASH_TMR_LEVEL;
0327 
0328     ret = regmap_write(rmap, MAX77693_LED_REG_FLASH_TIMER, v);
0329     if (ret < 0)
0330         return ret;
0331 
0332     led->current_flash_timeout = microsec;
0333 
0334     return 0;
0335 }
0336 
0337 static int max77693_get_strobe_status(struct max77693_led_device *led,
0338                     bool *state)
0339 {
0340     struct regmap *rmap = led->regmap;
0341     unsigned int v;
0342     int ret;
0343 
0344     ret = regmap_read(rmap, MAX77693_LED_REG_FLASH_STATUS, &v);
0345     if (ret < 0)
0346         return ret;
0347 
0348     *state = v & FLASH_STATUS_FLASH_ON;
0349 
0350     return ret;
0351 }
0352 
0353 static int max77693_get_flash_faults(struct max77693_sub_led *sub_led)
0354 {
0355     struct max77693_led_device *led = sub_led_to_led(sub_led);
0356     struct regmap *rmap = led->regmap;
0357     unsigned int v;
0358     u8 fault_open_mask, fault_short_mask;
0359     int ret;
0360 
0361     sub_led->flash_faults = 0;
0362 
0363     if (led->iout_joint) {
0364         fault_open_mask = FLASH_INT_FLED1_OPEN | FLASH_INT_FLED2_OPEN;
0365         fault_short_mask = FLASH_INT_FLED1_SHORT |
0366                             FLASH_INT_FLED2_SHORT;
0367     } else {
0368         fault_open_mask = (sub_led->fled_id == FLED1) ?
0369                         FLASH_INT_FLED1_OPEN :
0370                         FLASH_INT_FLED2_OPEN;
0371         fault_short_mask = (sub_led->fled_id == FLED1) ?
0372                         FLASH_INT_FLED1_SHORT :
0373                         FLASH_INT_FLED2_SHORT;
0374     }
0375 
0376     ret = regmap_read(rmap, MAX77693_LED_REG_FLASH_INT, &v);
0377     if (ret < 0)
0378         return ret;
0379 
0380     if (v & fault_open_mask)
0381         sub_led->flash_faults |= LED_FAULT_OVER_VOLTAGE;
0382     if (v & fault_short_mask)
0383         sub_led->flash_faults |= LED_FAULT_SHORT_CIRCUIT;
0384     if (v & FLASH_INT_OVER_CURRENT)
0385         sub_led->flash_faults |= LED_FAULT_OVER_CURRENT;
0386 
0387     return 0;
0388 }
0389 
0390 static int max77693_setup(struct max77693_led_device *led,
0391              struct max77693_led_config_data *led_cfg)
0392 {
0393     struct regmap *rmap = led->regmap;
0394     int i, first_led, last_led, ret;
0395     u32 max_flash_curr[2];
0396     u8 v;
0397 
0398     /*
0399      * Initialize only flash current. Torch current doesn't
0400      * require initialization as ITORCH register is written with
0401      * new value each time brightness_set op is called.
0402      */
0403     if (led->iout_joint) {
0404         first_led = FLED1;
0405         last_led = FLED1;
0406         max_flash_curr[FLED1] = led_cfg->iout_flash_max[FLED1] +
0407                     led_cfg->iout_flash_max[FLED2];
0408     } else {
0409         first_led = max77693_fled_used(led, FLED1) ? FLED1 : FLED2;
0410         last_led = max77693_fled_used(led, FLED2) ? FLED2 : FLED1;
0411         max_flash_curr[FLED1] = led_cfg->iout_flash_max[FLED1];
0412         max_flash_curr[FLED2] = led_cfg->iout_flash_max[FLED2];
0413     }
0414 
0415     for (i = first_led; i <= last_led; ++i) {
0416         ret = max77693_set_flash_current(led, i,
0417                     max_flash_curr[i]);
0418         if (ret < 0)
0419             return ret;
0420     }
0421 
0422     v = TORCH_TMR_NO_TIMER | MAX77693_LED_TRIG_TYPE_LEVEL;
0423     ret = regmap_write(rmap, MAX77693_LED_REG_ITORCHTIMER, v);
0424     if (ret < 0)
0425         return ret;
0426 
0427     if (led_cfg->low_vsys > 0)
0428         v = max77693_led_vsys_to_reg(led_cfg->low_vsys) |
0429                         MAX_FLASH1_MAX_FL_EN;
0430     else
0431         v = 0;
0432 
0433     ret = regmap_write(rmap, MAX77693_LED_REG_MAX_FLASH1, v);
0434     if (ret < 0)
0435         return ret;
0436     ret = regmap_write(rmap, MAX77693_LED_REG_MAX_FLASH2, 0);
0437     if (ret < 0)
0438         return ret;
0439 
0440     if (led_cfg->boost_mode == MAX77693_LED_BOOST_FIXED)
0441         v = FLASH_BOOST_FIXED;
0442     else
0443         v = led_cfg->boost_mode | led_cfg->boost_mode << 1;
0444 
0445     if (max77693_fled_used(led, FLED1) && max77693_fled_used(led, FLED2))
0446         v |= FLASH_BOOST_LEDNUM_2;
0447 
0448     ret = regmap_write(rmap, MAX77693_LED_REG_VOUT_CNTL, v);
0449     if (ret < 0)
0450         return ret;
0451 
0452     v = max77693_led_vout_to_reg(led_cfg->boost_vout);
0453     ret = regmap_write(rmap, MAX77693_LED_REG_VOUT_FLASH1, v);
0454     if (ret < 0)
0455         return ret;
0456 
0457     return max77693_set_mode_reg(led, MODE_OFF);
0458 }
0459 
0460 /* LED subsystem callbacks */
0461 static int max77693_led_brightness_set(struct led_classdev *led_cdev,
0462                     enum led_brightness value)
0463 {
0464     struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
0465     struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
0466     struct max77693_led_device *led = sub_led_to_led(sub_led);
0467     int fled_id = sub_led->fled_id, ret;
0468 
0469     mutex_lock(&led->lock);
0470 
0471     if (value == 0) {
0472         ret = max77693_clear_mode(led, MODE_TORCH(fled_id));
0473         if (ret < 0)
0474             dev_dbg(&led->pdev->dev,
0475                 "Failed to clear torch mode (%d)\n",
0476                 ret);
0477         goto unlock;
0478     }
0479 
0480     ret = max77693_set_torch_current(led, fled_id, value * TORCH_IOUT_STEP);
0481     if (ret < 0) {
0482         dev_dbg(&led->pdev->dev,
0483             "Failed to set torch current (%d)\n",
0484             ret);
0485         goto unlock;
0486     }
0487 
0488     ret = max77693_add_mode(led, MODE_TORCH(fled_id));
0489     if (ret < 0)
0490         dev_dbg(&led->pdev->dev,
0491             "Failed to set torch mode (%d)\n",
0492             ret);
0493 unlock:
0494     mutex_unlock(&led->lock);
0495 
0496     return ret;
0497 }
0498 
0499 static int max77693_led_flash_brightness_set(
0500                 struct led_classdev_flash *fled_cdev,
0501                 u32 brightness)
0502 {
0503     struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
0504     struct max77693_led_device *led = sub_led_to_led(sub_led);
0505     int ret;
0506 
0507     mutex_lock(&led->lock);
0508     ret = max77693_set_flash_current(led, sub_led->fled_id, brightness);
0509     mutex_unlock(&led->lock);
0510 
0511     return ret;
0512 }
0513 
0514 static int max77693_led_flash_strobe_set(
0515                 struct led_classdev_flash *fled_cdev,
0516                 bool state)
0517 {
0518     struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
0519     struct max77693_led_device *led = sub_led_to_led(sub_led);
0520     int fled_id = sub_led->fled_id;
0521     int ret;
0522 
0523     mutex_lock(&led->lock);
0524 
0525     if (!state) {
0526         ret = max77693_clear_mode(led, MODE_FLASH(fled_id));
0527         goto unlock;
0528     }
0529 
0530     if (sub_led->flash_timeout != led->current_flash_timeout) {
0531         ret = max77693_set_timeout(led, sub_led->flash_timeout);
0532         if (ret < 0)
0533             goto unlock;
0534     }
0535 
0536     led->strobing_sub_led_id = fled_id;
0537 
0538     ret = max77693_add_mode(led, MODE_FLASH(fled_id));
0539     if (ret < 0)
0540         goto unlock;
0541 
0542     ret = max77693_get_flash_faults(sub_led);
0543 
0544 unlock:
0545     mutex_unlock(&led->lock);
0546     return ret;
0547 }
0548 
0549 static int max77693_led_flash_fault_get(
0550                 struct led_classdev_flash *fled_cdev,
0551                 u32 *fault)
0552 {
0553     struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
0554 
0555     *fault = sub_led->flash_faults;
0556 
0557     return 0;
0558 }
0559 
0560 static int max77693_led_flash_strobe_get(
0561                 struct led_classdev_flash *fled_cdev,
0562                 bool *state)
0563 {
0564     struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
0565     struct max77693_led_device *led = sub_led_to_led(sub_led);
0566     int ret;
0567 
0568     if (!state)
0569         return -EINVAL;
0570 
0571     mutex_lock(&led->lock);
0572 
0573     ret = max77693_get_strobe_status(led, state);
0574 
0575     *state = !!(*state && (led->strobing_sub_led_id == sub_led->fled_id));
0576 
0577     mutex_unlock(&led->lock);
0578 
0579     return ret;
0580 }
0581 
0582 static int max77693_led_flash_timeout_set(
0583                 struct led_classdev_flash *fled_cdev,
0584                 u32 timeout)
0585 {
0586     struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
0587     struct max77693_led_device *led = sub_led_to_led(sub_led);
0588 
0589     mutex_lock(&led->lock);
0590     sub_led->flash_timeout = timeout;
0591     mutex_unlock(&led->lock);
0592 
0593     return 0;
0594 }
0595 
0596 static int max77693_led_parse_dt(struct max77693_led_device *led,
0597                 struct max77693_led_config_data *cfg,
0598                 struct device_node **sub_nodes)
0599 {
0600     struct device *dev = &led->pdev->dev;
0601     struct max77693_sub_led *sub_leds = led->sub_leds;
0602     struct device_node *node = dev_of_node(dev), *child_node;
0603     struct property *prop;
0604     u32 led_sources[2];
0605     int i, ret, fled_id;
0606 
0607     of_property_read_u32(node, "maxim,boost-mode", &cfg->boost_mode);
0608     of_property_read_u32(node, "maxim,boost-mvout", &cfg->boost_vout);
0609     of_property_read_u32(node, "maxim,mvsys-min", &cfg->low_vsys);
0610 
0611     for_each_available_child_of_node(node, child_node) {
0612         prop = of_find_property(child_node, "led-sources", NULL);
0613         if (prop) {
0614             const __be32 *srcs = NULL;
0615 
0616             for (i = 0; i < ARRAY_SIZE(led_sources); ++i) {
0617                 srcs = of_prop_next_u32(prop, srcs,
0618                             &led_sources[i]);
0619                 if (!srcs)
0620                     break;
0621             }
0622         } else {
0623             dev_err(dev,
0624                 "led-sources DT property missing\n");
0625             of_node_put(child_node);
0626             return -EINVAL;
0627         }
0628 
0629         if (i == 2) {
0630             fled_id = FLED1;
0631             led->fled_mask = FLED1_IOUT | FLED2_IOUT;
0632         } else if (led_sources[0] == FLED1) {
0633             fled_id = FLED1;
0634             led->fled_mask |= FLED1_IOUT;
0635         } else if (led_sources[0] == FLED2) {
0636             fled_id = FLED2;
0637             led->fled_mask |= FLED2_IOUT;
0638         } else {
0639             dev_err(dev,
0640                 "Wrong led-sources DT property value.\n");
0641             of_node_put(child_node);
0642             return -EINVAL;
0643         }
0644 
0645         if (sub_nodes[fled_id]) {
0646             dev_err(dev,
0647                 "Conflicting \"led-sources\" DT properties\n");
0648             of_node_put(child_node);
0649             return -EINVAL;
0650         }
0651 
0652         sub_nodes[fled_id] = child_node;
0653         sub_leds[fled_id].fled_id = fled_id;
0654 
0655         cfg->label[fled_id] =
0656             of_get_property(child_node, "label", NULL) ? :
0657                         child_node->name;
0658 
0659         ret = of_property_read_u32(child_node, "led-max-microamp",
0660                     &cfg->iout_torch_max[fled_id]);
0661         if (ret < 0) {
0662             cfg->iout_torch_max[fled_id] = TORCH_IOUT_MIN;
0663             dev_warn(dev, "led-max-microamp DT property missing\n");
0664         }
0665 
0666         ret = of_property_read_u32(child_node, "flash-max-microamp",
0667                     &cfg->iout_flash_max[fled_id]);
0668         if (ret < 0) {
0669             cfg->iout_flash_max[fled_id] = FLASH_IOUT_MIN;
0670             dev_warn(dev,
0671                  "flash-max-microamp DT property missing\n");
0672         }
0673 
0674         ret = of_property_read_u32(child_node, "flash-max-timeout-us",
0675                     &cfg->flash_timeout_max[fled_id]);
0676         if (ret < 0) {
0677             cfg->flash_timeout_max[fled_id] = FLASH_TIMEOUT_MIN;
0678             dev_warn(dev,
0679                  "flash-max-timeout-us DT property missing\n");
0680         }
0681 
0682         if (++cfg->num_leds == 2 ||
0683             (max77693_fled_used(led, FLED1) &&
0684              max77693_fled_used(led, FLED2))) {
0685             of_node_put(child_node);
0686             break;
0687         }
0688     }
0689 
0690     if (cfg->num_leds == 0) {
0691         dev_err(dev, "No DT child node found for connected LED(s).\n");
0692         return -EINVAL;
0693     }
0694 
0695     return 0;
0696 }
0697 
0698 static void clamp_align(u32 *v, u32 min, u32 max, u32 step)
0699 {
0700     *v = clamp_val(*v, min, max);
0701     if (step > 1)
0702         *v = (*v - min) / step * step + min;
0703 }
0704 
0705 static void max77693_align_iout_current(struct max77693_led_device *led,
0706                     u32 *iout, u32 min, u32 max, u32 step)
0707 {
0708     int i;
0709 
0710     if (led->iout_joint) {
0711         if (iout[FLED1] > min) {
0712             iout[FLED1] /= 2;
0713             iout[FLED2] = iout[FLED1];
0714         } else {
0715             iout[FLED1] = min;
0716             iout[FLED2] = 0;
0717             return;
0718         }
0719     }
0720 
0721     for (i = FLED1; i <= FLED2; ++i)
0722         if (max77693_fled_used(led, i))
0723             clamp_align(&iout[i], min, max, step);
0724         else
0725             iout[i] = 0;
0726 }
0727 
0728 static void max77693_led_validate_configuration(struct max77693_led_device *led,
0729                     struct max77693_led_config_data *cfg)
0730 {
0731     u32 flash_iout_max = cfg->boost_mode ? FLASH_IOUT_MAX_2LEDS :
0732                            FLASH_IOUT_MAX_1LED;
0733     int i;
0734 
0735     if (cfg->num_leds == 1 &&
0736         max77693_fled_used(led, FLED1) && max77693_fled_used(led, FLED2))
0737         led->iout_joint = true;
0738 
0739     cfg->boost_mode = clamp_val(cfg->boost_mode, MAX77693_LED_BOOST_NONE,
0740                 MAX77693_LED_BOOST_FIXED);
0741 
0742     /* Boost must be enabled if both current outputs are used */
0743     if ((cfg->boost_mode == MAX77693_LED_BOOST_NONE) && led->iout_joint)
0744         cfg->boost_mode = MAX77693_LED_BOOST_FIXED;
0745 
0746     max77693_align_iout_current(led, cfg->iout_torch_max,
0747             TORCH_IOUT_MIN, TORCH_IOUT_MAX, TORCH_IOUT_STEP);
0748 
0749     max77693_align_iout_current(led, cfg->iout_flash_max,
0750             FLASH_IOUT_MIN, flash_iout_max, FLASH_IOUT_STEP);
0751 
0752     for (i = 0; i < ARRAY_SIZE(cfg->flash_timeout_max); ++i)
0753         clamp_align(&cfg->flash_timeout_max[i], FLASH_TIMEOUT_MIN,
0754                 FLASH_TIMEOUT_MAX, FLASH_TIMEOUT_STEP);
0755 
0756     clamp_align(&cfg->boost_vout, FLASH_VOUT_MIN, FLASH_VOUT_MAX,
0757                             FLASH_VOUT_STEP);
0758 
0759     if (cfg->low_vsys)
0760         clamp_align(&cfg->low_vsys, MAX_FLASH1_VSYS_MIN,
0761                 MAX_FLASH1_VSYS_MAX, MAX_FLASH1_VSYS_STEP);
0762 }
0763 
0764 static int max77693_led_get_configuration(struct max77693_led_device *led,
0765                 struct max77693_led_config_data *cfg,
0766                 struct device_node **sub_nodes)
0767 {
0768     int ret;
0769 
0770     ret = max77693_led_parse_dt(led, cfg, sub_nodes);
0771     if (ret < 0)
0772         return ret;
0773 
0774     max77693_led_validate_configuration(led, cfg);
0775 
0776     memcpy(led->iout_torch_max, cfg->iout_torch_max,
0777                 sizeof(led->iout_torch_max));
0778     memcpy(led->iout_flash_max, cfg->iout_flash_max,
0779                 sizeof(led->iout_flash_max));
0780 
0781     return 0;
0782 }
0783 
0784 static const struct led_flash_ops flash_ops = {
0785     .flash_brightness_set   = max77693_led_flash_brightness_set,
0786     .strobe_set     = max77693_led_flash_strobe_set,
0787     .strobe_get     = max77693_led_flash_strobe_get,
0788     .timeout_set        = max77693_led_flash_timeout_set,
0789     .fault_get      = max77693_led_flash_fault_get,
0790 };
0791 
0792 static void max77693_init_flash_settings(struct max77693_sub_led *sub_led,
0793                  struct max77693_led_config_data *led_cfg)
0794 {
0795     struct led_classdev_flash *fled_cdev = &sub_led->fled_cdev;
0796     struct max77693_led_device *led = sub_led_to_led(sub_led);
0797     int fled_id = sub_led->fled_id;
0798     struct led_flash_setting *setting;
0799 
0800     /* Init flash intensity setting */
0801     setting = &fled_cdev->brightness;
0802     setting->min = FLASH_IOUT_MIN;
0803     setting->max = led->iout_joint ?
0804         led_cfg->iout_flash_max[FLED1] +
0805         led_cfg->iout_flash_max[FLED2] :
0806         led_cfg->iout_flash_max[fled_id];
0807     setting->step = FLASH_IOUT_STEP;
0808     setting->val = setting->max;
0809 
0810     /* Init flash timeout setting */
0811     setting = &fled_cdev->timeout;
0812     setting->min = FLASH_TIMEOUT_MIN;
0813     setting->max = led_cfg->flash_timeout_max[fled_id];
0814     setting->step = FLASH_TIMEOUT_STEP;
0815     setting->val = setting->max;
0816 }
0817 
0818 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
0819 
0820 static int max77693_led_external_strobe_set(
0821                 struct v4l2_flash *v4l2_flash,
0822                 bool enable)
0823 {
0824     struct max77693_sub_led *sub_led =
0825                 flcdev_to_sub_led(v4l2_flash->fled_cdev);
0826     struct max77693_led_device *led = sub_led_to_led(sub_led);
0827     int fled_id = sub_led->fled_id;
0828     int ret;
0829 
0830     mutex_lock(&led->lock);
0831 
0832     if (enable)
0833         ret = max77693_add_mode(led, MODE_FLASH_EXTERNAL(fled_id));
0834     else
0835         ret = max77693_clear_mode(led, MODE_FLASH_EXTERNAL(fled_id));
0836 
0837     mutex_unlock(&led->lock);
0838 
0839     return ret;
0840 }
0841 
0842 static void max77693_init_v4l2_flash_config(struct max77693_sub_led *sub_led,
0843                 struct max77693_led_config_data *led_cfg,
0844                 struct v4l2_flash_config *v4l2_sd_cfg)
0845 {
0846     struct max77693_led_device *led = sub_led_to_led(sub_led);
0847     struct device *dev = &led->pdev->dev;
0848     struct max77693_dev *iodev = dev_get_drvdata(dev->parent);
0849     struct i2c_client *i2c = iodev->i2c;
0850     struct led_flash_setting *s;
0851 
0852     snprintf(v4l2_sd_cfg->dev_name, sizeof(v4l2_sd_cfg->dev_name),
0853          "%s %d-%04x", sub_led->fled_cdev.led_cdev.name,
0854          i2c_adapter_id(i2c->adapter), i2c->addr);
0855 
0856     s = &v4l2_sd_cfg->intensity;
0857     s->min = TORCH_IOUT_MIN;
0858     s->max = sub_led->fled_cdev.led_cdev.max_brightness * TORCH_IOUT_STEP;
0859     s->step = TORCH_IOUT_STEP;
0860     s->val = s->max;
0861 
0862     /* Init flash faults config */
0863     v4l2_sd_cfg->flash_faults = LED_FAULT_OVER_VOLTAGE |
0864                 LED_FAULT_SHORT_CIRCUIT |
0865                 LED_FAULT_OVER_CURRENT;
0866 
0867     v4l2_sd_cfg->has_external_strobe = true;
0868 }
0869 
0870 static const struct v4l2_flash_ops v4l2_flash_ops = {
0871     .external_strobe_set = max77693_led_external_strobe_set,
0872 };
0873 #else
0874 static inline void max77693_init_v4l2_flash_config(
0875                 struct max77693_sub_led *sub_led,
0876                 struct max77693_led_config_data *led_cfg,
0877                 struct v4l2_flash_config *v4l2_sd_cfg)
0878 {
0879 }
0880 static const struct v4l2_flash_ops v4l2_flash_ops;
0881 #endif
0882 
0883 static void max77693_init_fled_cdev(struct max77693_sub_led *sub_led,
0884                 struct max77693_led_config_data *led_cfg)
0885 {
0886     struct max77693_led_device *led = sub_led_to_led(sub_led);
0887     int fled_id = sub_led->fled_id;
0888     struct led_classdev_flash *fled_cdev;
0889     struct led_classdev *led_cdev;
0890 
0891     /* Initialize LED Flash class device */
0892     fled_cdev = &sub_led->fled_cdev;
0893     fled_cdev->ops = &flash_ops;
0894     led_cdev = &fled_cdev->led_cdev;
0895 
0896     led_cdev->name = led_cfg->label[fled_id];
0897 
0898     led_cdev->brightness_set_blocking = max77693_led_brightness_set;
0899     led_cdev->max_brightness = (led->iout_joint ?
0900                     led_cfg->iout_torch_max[FLED1] +
0901                     led_cfg->iout_torch_max[FLED2] :
0902                     led_cfg->iout_torch_max[fled_id]) /
0903                    TORCH_IOUT_STEP;
0904     led_cdev->flags |= LED_DEV_CAP_FLASH;
0905 
0906     max77693_init_flash_settings(sub_led, led_cfg);
0907 
0908     /* Init flash timeout cache */
0909     sub_led->flash_timeout = fled_cdev->timeout.val;
0910 }
0911 
0912 static int max77693_register_led(struct max77693_sub_led *sub_led,
0913                  struct max77693_led_config_data *led_cfg,
0914                  struct device_node *sub_node)
0915 {
0916     struct max77693_led_device *led = sub_led_to_led(sub_led);
0917     struct led_classdev_flash *fled_cdev = &sub_led->fled_cdev;
0918     struct device *dev = &led->pdev->dev;
0919     struct v4l2_flash_config v4l2_sd_cfg = {};
0920     int ret;
0921 
0922     /* Register in the LED subsystem */
0923     ret = led_classdev_flash_register(dev, fled_cdev);
0924     if (ret < 0)
0925         return ret;
0926 
0927     max77693_init_v4l2_flash_config(sub_led, led_cfg, &v4l2_sd_cfg);
0928 
0929     /* Register in the V4L2 subsystem. */
0930     sub_led->v4l2_flash = v4l2_flash_init(dev, of_fwnode_handle(sub_node),
0931                           fled_cdev, &v4l2_flash_ops,
0932                           &v4l2_sd_cfg);
0933     if (IS_ERR(sub_led->v4l2_flash)) {
0934         ret = PTR_ERR(sub_led->v4l2_flash);
0935         goto err_v4l2_flash_init;
0936     }
0937 
0938     return 0;
0939 
0940 err_v4l2_flash_init:
0941     led_classdev_flash_unregister(fled_cdev);
0942     return ret;
0943 }
0944 
0945 static int max77693_led_probe(struct platform_device *pdev)
0946 {
0947     struct device *dev = &pdev->dev;
0948     struct max77693_dev *iodev = dev_get_drvdata(dev->parent);
0949     struct max77693_led_device *led;
0950     struct max77693_sub_led *sub_leds;
0951     struct device_node *sub_nodes[2] = {};
0952     struct max77693_led_config_data led_cfg = {};
0953     int init_fled_cdev[2], i, ret;
0954 
0955     led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
0956     if (!led)
0957         return -ENOMEM;
0958 
0959     led->pdev = pdev;
0960     led->regmap = iodev->regmap;
0961     led->allowed_modes = MODE_FLASH_MASK;
0962     sub_leds = led->sub_leds;
0963 
0964     platform_set_drvdata(pdev, led);
0965     ret = max77693_led_get_configuration(led, &led_cfg, sub_nodes);
0966     if (ret < 0)
0967         return ret;
0968 
0969     ret = max77693_setup(led, &led_cfg);
0970     if (ret < 0)
0971         return ret;
0972 
0973     mutex_init(&led->lock);
0974 
0975     init_fled_cdev[FLED1] =
0976             led->iout_joint || max77693_fled_used(led, FLED1);
0977     init_fled_cdev[FLED2] =
0978             !led->iout_joint && max77693_fled_used(led, FLED2);
0979 
0980     for (i = FLED1; i <= FLED2; ++i) {
0981         if (!init_fled_cdev[i])
0982             continue;
0983 
0984         /* Initialize LED Flash class device */
0985         max77693_init_fled_cdev(&sub_leds[i], &led_cfg);
0986 
0987         /*
0988          * Register LED Flash class device and corresponding
0989          * V4L2 Flash device.
0990          */
0991         ret = max77693_register_led(&sub_leds[i], &led_cfg,
0992                         sub_nodes[i]);
0993         if (ret < 0) {
0994             /*
0995              * At this moment FLED1 might have been already
0996              * registered and it needs to be released.
0997              */
0998             if (i == FLED2)
0999                 goto err_register_led2;
1000             else
1001                 goto err_register_led1;
1002         }
1003     }
1004 
1005     return 0;
1006 
1007 err_register_led2:
1008     /* It is possible than only FLED2 was to be registered */
1009     if (!init_fled_cdev[FLED1])
1010         goto err_register_led1;
1011     v4l2_flash_release(sub_leds[FLED1].v4l2_flash);
1012     led_classdev_flash_unregister(&sub_leds[FLED1].fled_cdev);
1013 err_register_led1:
1014     mutex_destroy(&led->lock);
1015 
1016     return ret;
1017 }
1018 
1019 static int max77693_led_remove(struct platform_device *pdev)
1020 {
1021     struct max77693_led_device *led = platform_get_drvdata(pdev);
1022     struct max77693_sub_led *sub_leds = led->sub_leds;
1023 
1024     if (led->iout_joint || max77693_fled_used(led, FLED1)) {
1025         v4l2_flash_release(sub_leds[FLED1].v4l2_flash);
1026         led_classdev_flash_unregister(&sub_leds[FLED1].fled_cdev);
1027     }
1028 
1029     if (!led->iout_joint && max77693_fled_used(led, FLED2)) {
1030         v4l2_flash_release(sub_leds[FLED2].v4l2_flash);
1031         led_classdev_flash_unregister(&sub_leds[FLED2].fled_cdev);
1032     }
1033 
1034     mutex_destroy(&led->lock);
1035 
1036     return 0;
1037 }
1038 
1039 static const struct of_device_id max77693_led_dt_match[] = {
1040     { .compatible = "maxim,max77693-led" },
1041     {},
1042 };
1043 MODULE_DEVICE_TABLE(of, max77693_led_dt_match);
1044 
1045 static struct platform_driver max77693_led_driver = {
1046     .probe      = max77693_led_probe,
1047     .remove     = max77693_led_remove,
1048     .driver     = {
1049         .name   = "max77693-led",
1050         .of_match_table = max77693_led_dt_match,
1051     },
1052 };
1053 
1054 module_platform_driver(max77693_led_driver);
1055 
1056 MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
1057 MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1058 MODULE_DESCRIPTION("Maxim MAX77693 led flash driver");
1059 MODULE_LICENSE("GPL v2");