1058 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * LED Flash class driver for the flash cell of max77693 mfd.4 *5 * Copyright (C) 2015, Samsung Electronics Co., Ltd.6 *7 * Authors: Jacek Anaszewski <j.anaszewski@samsung.com>8 * Andrzej Hajda <a.hajda@samsung.com>9 */10 11#include <linux/led-class-flash.h>12#include <linux/mfd/max77693.h>13#include <linux/mfd/max77693-common.h>14#include <linux/mfd/max77693-private.h>15#include <linux/module.h>16#include <linux/mutex.h>17#include <linux/platform_device.h>18#include <linux/regmap.h>19#include <linux/slab.h>20#include <media/v4l2-flash-led-class.h>21 22#define MODE_OFF 023#define MODE_FLASH(a) (1 << (a))24#define MODE_TORCH(a) (1 << (2 + (a)))25#define MODE_FLASH_EXTERNAL(a) (1 << (4 + (a)))26 27#define MODE_FLASH_MASK (MODE_FLASH(FLED1) | MODE_FLASH(FLED2) | \28 MODE_FLASH_EXTERNAL(FLED1) | \29 MODE_FLASH_EXTERNAL(FLED2))30#define MODE_TORCH_MASK (MODE_TORCH(FLED1) | MODE_TORCH(FLED2))31 32#define FLED1_IOUT (1 << 0)33#define FLED2_IOUT (1 << 1)34 35enum max77693_fled {36 FLED1,37 FLED2,38};39 40enum max77693_led_mode {41 FLASH,42 TORCH,43};44 45struct max77693_led_config_data {46 const char *label[2];47 u32 iout_torch_max[2];48 u32 iout_flash_max[2];49 u32 flash_timeout_max[2];50 u32 num_leds;51 u32 boost_mode;52 u32 boost_vout;53 u32 low_vsys;54};55 56struct max77693_sub_led {57 /* corresponding FLED output identifier */58 int fled_id;59 /* corresponding LED Flash class device */60 struct led_classdev_flash fled_cdev;61 /* V4L2 Flash device */62 struct v4l2_flash *v4l2_flash;63 64 /* brightness cache */65 unsigned int torch_brightness;66 /* flash timeout cache */67 unsigned int flash_timeout;68 /* flash faults that may have occurred */69 u32 flash_faults;70};71 72struct max77693_led_device {73 /* parent mfd regmap */74 struct regmap *regmap;75 /* platform device data */76 struct platform_device *pdev;77 /* secures access to the device */78 struct mutex lock;79 80 /* sub led data */81 struct max77693_sub_led sub_leds[2];82 83 /* maximum torch current values for FLED outputs */84 u32 iout_torch_max[2];85 /* maximum flash current values for FLED outputs */86 u32 iout_flash_max[2];87 88 /* current flash timeout cache */89 unsigned int current_flash_timeout;90 /* ITORCH register cache */91 u8 torch_iout_reg;92 /* mode of fled outputs */93 unsigned int mode_flags;94 /* recently strobed fled */95 int strobing_sub_led_id;96 /* bitmask of FLED outputs use state (bit 0. - FLED1, bit 1. - FLED2) */97 u8 fled_mask;98 /* FLED modes that can be set */99 u8 allowed_modes;100 101 /* arrangement of current outputs */102 bool iout_joint;103};104 105static u8 max77693_led_iout_to_reg(u32 ua)106{107 if (ua < FLASH_IOUT_MIN)108 ua = FLASH_IOUT_MIN;109 return (ua - FLASH_IOUT_MIN) / FLASH_IOUT_STEP;110}111 112static u8 max77693_flash_timeout_to_reg(u32 us)113{114 return (us - FLASH_TIMEOUT_MIN) / FLASH_TIMEOUT_STEP;115}116 117static inline struct max77693_sub_led *flcdev_to_sub_led(118 struct led_classdev_flash *fled_cdev)119{120 return container_of(fled_cdev, struct max77693_sub_led, fled_cdev);121}122 123static inline struct max77693_led_device *sub_led_to_led(124 struct max77693_sub_led *sub_led)125{126 return container_of(sub_led, struct max77693_led_device,127 sub_leds[sub_led->fled_id]);128}129 130static inline u8 max77693_led_vsys_to_reg(u32 mv)131{132 return ((mv - MAX_FLASH1_VSYS_MIN) / MAX_FLASH1_VSYS_STEP) << 2;133}134 135static inline u8 max77693_led_vout_to_reg(u32 mv)136{137 return (mv - FLASH_VOUT_MIN) / FLASH_VOUT_STEP + FLASH_VOUT_RMIN;138}139 140static inline bool max77693_fled_used(struct max77693_led_device *led,141 int fled_id)142{143 u8 fled_bit = (fled_id == FLED1) ? FLED1_IOUT : FLED2_IOUT;144 145 return led->fled_mask & fled_bit;146}147 148static int max77693_set_mode_reg(struct max77693_led_device *led, u8 mode)149{150 struct regmap *rmap = led->regmap;151 int ret, v = 0, i;152 153 for (i = FLED1; i <= FLED2; ++i) {154 if (mode & MODE_TORCH(i))155 v |= FLASH_EN_ON << TORCH_EN_SHIFT(i);156 157 if (mode & MODE_FLASH(i)) {158 v |= FLASH_EN_ON << FLASH_EN_SHIFT(i);159 } else if (mode & MODE_FLASH_EXTERNAL(i)) {160 v |= FLASH_EN_FLASH << FLASH_EN_SHIFT(i);161 /*162 * Enable hw triggering also for torch mode, as some163 * camera sensors use torch led to fathom ambient light164 * conditions before strobing the flash.165 */166 v |= FLASH_EN_TORCH << TORCH_EN_SHIFT(i);167 }168 }169 170 /* Reset the register only prior setting flash modes */171 if (mode & ~(MODE_TORCH(FLED1) | MODE_TORCH(FLED2))) {172 ret = regmap_write(rmap, MAX77693_LED_REG_FLASH_EN, 0);173 if (ret < 0)174 return ret;175 }176 177 return regmap_write(rmap, MAX77693_LED_REG_FLASH_EN, v);178}179 180static int max77693_add_mode(struct max77693_led_device *led, u8 mode)181{182 u8 new_mode_flags;183 int i, ret;184 185 if (led->iout_joint)186 /* Span the mode on FLED2 for joint iouts case */187 mode |= (mode << 1);188 189 /*190 * FLASH_EXTERNAL mode activates FLASHEN and TORCHEN pins in the device.191 * Corresponding register bit fields interfere with SW triggered modes,192 * thus clear them to ensure proper device configuration.193 */194 for (i = FLED1; i <= FLED2; ++i)195 if (mode & MODE_FLASH_EXTERNAL(i))196 led->mode_flags &= (~MODE_TORCH(i) & ~MODE_FLASH(i));197 198 new_mode_flags = mode | led->mode_flags;199 new_mode_flags &= led->allowed_modes;200 201 if (new_mode_flags ^ led->mode_flags)202 led->mode_flags = new_mode_flags;203 else204 return 0;205 206 ret = max77693_set_mode_reg(led, led->mode_flags);207 if (ret < 0)208 return ret;209 210 /*211 * Clear flash mode flag after setting the mode to avoid spurious flash212 * strobing on each subsequent torch mode setting.213 */214 if (mode & MODE_FLASH_MASK)215 led->mode_flags &= ~mode;216 217 return ret;218}219 220static int max77693_clear_mode(struct max77693_led_device *led,221 u8 mode)222{223 if (led->iout_joint)224 /* Clear mode also on FLED2 for joint iouts case */225 mode |= (mode << 1);226 227 led->mode_flags &= ~mode;228 229 return max77693_set_mode_reg(led, led->mode_flags);230}231 232static void max77693_add_allowed_modes(struct max77693_led_device *led,233 int fled_id, enum max77693_led_mode mode)234{235 if (mode == FLASH)236 led->allowed_modes |= (MODE_FLASH(fled_id) |237 MODE_FLASH_EXTERNAL(fled_id));238 else239 led->allowed_modes |= MODE_TORCH(fled_id);240}241 242static void max77693_distribute_currents(struct max77693_led_device *led,243 int fled_id, enum max77693_led_mode mode,244 u32 micro_amp, u32 iout_max[2], u32 iout[2])245{246 if (!led->iout_joint) {247 iout[fled_id] = micro_amp;248 max77693_add_allowed_modes(led, fled_id, mode);249 return;250 }251 252 iout[FLED1] = min(micro_amp, iout_max[FLED1]);253 iout[FLED2] = micro_amp - iout[FLED1];254 255 if (mode == FLASH)256 led->allowed_modes &= ~MODE_FLASH_MASK;257 else258 led->allowed_modes &= ~MODE_TORCH_MASK;259 260 max77693_add_allowed_modes(led, FLED1, mode);261 262 if (iout[FLED2])263 max77693_add_allowed_modes(led, FLED2, mode);264}265 266static int max77693_set_torch_current(struct max77693_led_device *led,267 int fled_id, u32 micro_amp)268{269 struct regmap *rmap = led->regmap;270 u8 iout1_reg = 0, iout2_reg = 0;271 u32 iout[2];272 273 max77693_distribute_currents(led, fled_id, TORCH, micro_amp,274 led->iout_torch_max, iout);275 276 if (fled_id == FLED1 || led->iout_joint) {277 iout1_reg = max77693_led_iout_to_reg(iout[FLED1]);278 led->torch_iout_reg &= TORCH_IOUT_MASK(TORCH_IOUT2_SHIFT);279 }280 if (fled_id == FLED2 || led->iout_joint) {281 iout2_reg = max77693_led_iout_to_reg(iout[FLED2]);282 led->torch_iout_reg &= TORCH_IOUT_MASK(TORCH_IOUT1_SHIFT);283 }284 285 led->torch_iout_reg |= ((iout1_reg << TORCH_IOUT1_SHIFT) |286 (iout2_reg << TORCH_IOUT2_SHIFT));287 288 return regmap_write(rmap, MAX77693_LED_REG_ITORCH,289 led->torch_iout_reg);290}291 292static int max77693_set_flash_current(struct max77693_led_device *led,293 int fled_id,294 u32 micro_amp)295{296 struct regmap *rmap = led->regmap;297 u8 iout1_reg, iout2_reg;298 u32 iout[2];299 int ret = -EINVAL;300 301 max77693_distribute_currents(led, fled_id, FLASH, micro_amp,302 led->iout_flash_max, iout);303 304 if (fled_id == FLED1 || led->iout_joint) {305 iout1_reg = max77693_led_iout_to_reg(iout[FLED1]);306 ret = regmap_write(rmap, MAX77693_LED_REG_IFLASH1,307 iout1_reg);308 if (ret < 0)309 return ret;310 }311 if (fled_id == FLED2 || led->iout_joint) {312 iout2_reg = max77693_led_iout_to_reg(iout[FLED2]);313 ret = regmap_write(rmap, MAX77693_LED_REG_IFLASH2,314 iout2_reg);315 }316 317 return ret;318}319 320static int max77693_set_timeout(struct max77693_led_device *led, u32 microsec)321{322 struct regmap *rmap = led->regmap;323 u8 v;324 int ret;325 326 v = max77693_flash_timeout_to_reg(microsec) | FLASH_TMR_LEVEL;327 328 ret = regmap_write(rmap, MAX77693_LED_REG_FLASH_TIMER, v);329 if (ret < 0)330 return ret;331 332 led->current_flash_timeout = microsec;333 334 return 0;335}336 337static int max77693_get_strobe_status(struct max77693_led_device *led,338 bool *state)339{340 struct regmap *rmap = led->regmap;341 unsigned int v;342 int ret;343 344 ret = regmap_read(rmap, MAX77693_LED_REG_FLASH_STATUS, &v);345 if (ret < 0)346 return ret;347 348 *state = v & FLASH_STATUS_FLASH_ON;349 350 return ret;351}352 353static int max77693_get_flash_faults(struct max77693_sub_led *sub_led)354{355 struct max77693_led_device *led = sub_led_to_led(sub_led);356 struct regmap *rmap = led->regmap;357 unsigned int v;358 u8 fault_open_mask, fault_short_mask;359 int ret;360 361 sub_led->flash_faults = 0;362 363 if (led->iout_joint) {364 fault_open_mask = FLASH_INT_FLED1_OPEN | FLASH_INT_FLED2_OPEN;365 fault_short_mask = FLASH_INT_FLED1_SHORT |366 FLASH_INT_FLED2_SHORT;367 } else {368 fault_open_mask = (sub_led->fled_id == FLED1) ?369 FLASH_INT_FLED1_OPEN :370 FLASH_INT_FLED2_OPEN;371 fault_short_mask = (sub_led->fled_id == FLED1) ?372 FLASH_INT_FLED1_SHORT :373 FLASH_INT_FLED2_SHORT;374 }375 376 ret = regmap_read(rmap, MAX77693_LED_REG_FLASH_INT, &v);377 if (ret < 0)378 return ret;379 380 if (v & fault_open_mask)381 sub_led->flash_faults |= LED_FAULT_OVER_VOLTAGE;382 if (v & fault_short_mask)383 sub_led->flash_faults |= LED_FAULT_SHORT_CIRCUIT;384 if (v & FLASH_INT_OVER_CURRENT)385 sub_led->flash_faults |= LED_FAULT_OVER_CURRENT;386 387 return 0;388}389 390static int max77693_setup(struct max77693_led_device *led,391 struct max77693_led_config_data *led_cfg)392{393 struct regmap *rmap = led->regmap;394 int i, first_led, last_led, ret;395 u32 max_flash_curr[2];396 u8 v;397 398 /*399 * Initialize only flash current. Torch current doesn't400 * require initialization as ITORCH register is written with401 * new value each time brightness_set op is called.402 */403 if (led->iout_joint) {404 first_led = FLED1;405 last_led = FLED1;406 max_flash_curr[FLED1] = led_cfg->iout_flash_max[FLED1] +407 led_cfg->iout_flash_max[FLED2];408 } else {409 first_led = max77693_fled_used(led, FLED1) ? FLED1 : FLED2;410 last_led = max77693_fled_used(led, FLED2) ? FLED2 : FLED1;411 max_flash_curr[FLED1] = led_cfg->iout_flash_max[FLED1];412 max_flash_curr[FLED2] = led_cfg->iout_flash_max[FLED2];413 }414 415 for (i = first_led; i <= last_led; ++i) {416 ret = max77693_set_flash_current(led, i,417 max_flash_curr[i]);418 if (ret < 0)419 return ret;420 }421 422 v = TORCH_TMR_NO_TIMER | MAX77693_LED_TRIG_TYPE_LEVEL;423 ret = regmap_write(rmap, MAX77693_LED_REG_ITORCHTIMER, v);424 if (ret < 0)425 return ret;426 427 if (led_cfg->low_vsys > 0)428 v = max77693_led_vsys_to_reg(led_cfg->low_vsys) |429 MAX_FLASH1_MAX_FL_EN;430 else431 v = 0;432 433 ret = regmap_write(rmap, MAX77693_LED_REG_MAX_FLASH1, v);434 if (ret < 0)435 return ret;436 ret = regmap_write(rmap, MAX77693_LED_REG_MAX_FLASH2, 0);437 if (ret < 0)438 return ret;439 440 if (led_cfg->boost_mode == MAX77693_LED_BOOST_FIXED)441 v = FLASH_BOOST_FIXED;442 else443 v = led_cfg->boost_mode | led_cfg->boost_mode << 1;444 445 if (max77693_fled_used(led, FLED1) && max77693_fled_used(led, FLED2))446 v |= FLASH_BOOST_LEDNUM_2;447 448 ret = regmap_write(rmap, MAX77693_LED_REG_VOUT_CNTL, v);449 if (ret < 0)450 return ret;451 452 v = max77693_led_vout_to_reg(led_cfg->boost_vout);453 ret = regmap_write(rmap, MAX77693_LED_REG_VOUT_FLASH1, v);454 if (ret < 0)455 return ret;456 457 return max77693_set_mode_reg(led, MODE_OFF);458}459 460/* LED subsystem callbacks */461static int max77693_led_brightness_set(struct led_classdev *led_cdev,462 enum led_brightness value)463{464 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);465 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);466 struct max77693_led_device *led = sub_led_to_led(sub_led);467 int fled_id = sub_led->fled_id, ret;468 469 mutex_lock(&led->lock);470 471 if (value == 0) {472 ret = max77693_clear_mode(led, MODE_TORCH(fled_id));473 if (ret < 0)474 dev_dbg(&led->pdev->dev,475 "Failed to clear torch mode (%d)\n",476 ret);477 goto unlock;478 }479 480 ret = max77693_set_torch_current(led, fled_id, value * TORCH_IOUT_STEP);481 if (ret < 0) {482 dev_dbg(&led->pdev->dev,483 "Failed to set torch current (%d)\n",484 ret);485 goto unlock;486 }487 488 ret = max77693_add_mode(led, MODE_TORCH(fled_id));489 if (ret < 0)490 dev_dbg(&led->pdev->dev,491 "Failed to set torch mode (%d)\n",492 ret);493unlock:494 mutex_unlock(&led->lock);495 496 return ret;497}498 499static int max77693_led_flash_brightness_set(500 struct led_classdev_flash *fled_cdev,501 u32 brightness)502{503 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);504 struct max77693_led_device *led = sub_led_to_led(sub_led);505 int ret;506 507 mutex_lock(&led->lock);508 ret = max77693_set_flash_current(led, sub_led->fled_id, brightness);509 mutex_unlock(&led->lock);510 511 return ret;512}513 514static int max77693_led_flash_strobe_set(515 struct led_classdev_flash *fled_cdev,516 bool state)517{518 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);519 struct max77693_led_device *led = sub_led_to_led(sub_led);520 int fled_id = sub_led->fled_id;521 int ret;522 523 mutex_lock(&led->lock);524 525 if (!state) {526 ret = max77693_clear_mode(led, MODE_FLASH(fled_id));527 goto unlock;528 }529 530 if (sub_led->flash_timeout != led->current_flash_timeout) {531 ret = max77693_set_timeout(led, sub_led->flash_timeout);532 if (ret < 0)533 goto unlock;534 }535 536 led->strobing_sub_led_id = fled_id;537 538 ret = max77693_add_mode(led, MODE_FLASH(fled_id));539 if (ret < 0)540 goto unlock;541 542 ret = max77693_get_flash_faults(sub_led);543 544unlock:545 mutex_unlock(&led->lock);546 return ret;547}548 549static int max77693_led_flash_fault_get(550 struct led_classdev_flash *fled_cdev,551 u32 *fault)552{553 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);554 555 *fault = sub_led->flash_faults;556 557 return 0;558}559 560static int max77693_led_flash_strobe_get(561 struct led_classdev_flash *fled_cdev,562 bool *state)563{564 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);565 struct max77693_led_device *led = sub_led_to_led(sub_led);566 int ret;567 568 if (!state)569 return -EINVAL;570 571 mutex_lock(&led->lock);572 573 ret = max77693_get_strobe_status(led, state);574 575 *state = !!(*state && (led->strobing_sub_led_id == sub_led->fled_id));576 577 mutex_unlock(&led->lock);578 579 return ret;580}581 582static int max77693_led_flash_timeout_set(583 struct led_classdev_flash *fled_cdev,584 u32 timeout)585{586 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);587 struct max77693_led_device *led = sub_led_to_led(sub_led);588 589 mutex_lock(&led->lock);590 sub_led->flash_timeout = timeout;591 mutex_unlock(&led->lock);592 593 return 0;594}595 596static int max77693_led_parse_dt(struct max77693_led_device *led,597 struct max77693_led_config_data *cfg,598 struct device_node **sub_nodes)599{600 struct device *dev = &led->pdev->dev;601 struct max77693_sub_led *sub_leds = led->sub_leds;602 struct device_node *node = dev_of_node(dev);603 struct property *prop;604 u32 led_sources[2];605 int i, ret, fled_id;606 607 of_property_read_u32(node, "maxim,boost-mode", &cfg->boost_mode);608 of_property_read_u32(node, "maxim,boost-mvout", &cfg->boost_vout);609 of_property_read_u32(node, "maxim,mvsys-min", &cfg->low_vsys);610 611 for_each_available_child_of_node_scoped(node, child_node) {612 prop = of_find_property(child_node, "led-sources", NULL);613 if (prop) {614 const __be32 *srcs = NULL;615 616 for (i = 0; i < ARRAY_SIZE(led_sources); ++i) {617 srcs = of_prop_next_u32(prop, srcs,618 &led_sources[i]);619 if (!srcs)620 break;621 }622 } else {623 dev_err(dev,624 "led-sources DT property missing\n");625 return -EINVAL;626 }627 628 if (i == 2) {629 fled_id = FLED1;630 led->fled_mask = FLED1_IOUT | FLED2_IOUT;631 } else if (led_sources[0] == FLED1) {632 fled_id = FLED1;633 led->fled_mask |= FLED1_IOUT;634 } else if (led_sources[0] == FLED2) {635 fled_id = FLED2;636 led->fled_mask |= FLED2_IOUT;637 } else {638 dev_err(dev,639 "Wrong led-sources DT property value.\n");640 return -EINVAL;641 }642 643 if (sub_nodes[fled_id]) {644 dev_err(dev,645 "Conflicting \"led-sources\" DT properties\n");646 return -EINVAL;647 }648 649 sub_nodes[fled_id] = of_node_get(child_node);650 sub_leds[fled_id].fled_id = fled_id;651 652 cfg->label[fled_id] =653 of_get_property(child_node, "label", NULL) ? :654 child_node->name;655 656 ret = of_property_read_u32(child_node, "led-max-microamp",657 &cfg->iout_torch_max[fled_id]);658 if (ret < 0) {659 cfg->iout_torch_max[fled_id] = TORCH_IOUT_MIN;660 dev_warn(dev, "led-max-microamp DT property missing\n");661 }662 663 ret = of_property_read_u32(child_node, "flash-max-microamp",664 &cfg->iout_flash_max[fled_id]);665 if (ret < 0) {666 cfg->iout_flash_max[fled_id] = FLASH_IOUT_MIN;667 dev_warn(dev,668 "flash-max-microamp DT property missing\n");669 }670 671 ret = of_property_read_u32(child_node, "flash-max-timeout-us",672 &cfg->flash_timeout_max[fled_id]);673 if (ret < 0) {674 cfg->flash_timeout_max[fled_id] = FLASH_TIMEOUT_MIN;675 dev_warn(dev,676 "flash-max-timeout-us DT property missing\n");677 }678 679 if (++cfg->num_leds == 2 ||680 (max77693_fled_used(led, FLED1) &&681 max77693_fled_used(led, FLED2)))682 break;683 }684 685 if (cfg->num_leds == 0) {686 dev_err(dev, "No DT child node found for connected LED(s).\n");687 return -EINVAL;688 }689 690 return 0;691}692 693static void clamp_align(u32 *v, u32 min, u32 max, u32 step)694{695 *v = clamp_val(*v, min, max);696 if (step > 1)697 *v = (*v - min) / step * step + min;698}699 700static void max77693_align_iout_current(struct max77693_led_device *led,701 u32 *iout, u32 min, u32 max, u32 step)702{703 int i;704 705 if (led->iout_joint) {706 if (iout[FLED1] > min) {707 iout[FLED1] /= 2;708 iout[FLED2] = iout[FLED1];709 } else {710 iout[FLED1] = min;711 iout[FLED2] = 0;712 return;713 }714 }715 716 for (i = FLED1; i <= FLED2; ++i)717 if (max77693_fled_used(led, i))718 clamp_align(&iout[i], min, max, step);719 else720 iout[i] = 0;721}722 723static void max77693_led_validate_configuration(struct max77693_led_device *led,724 struct max77693_led_config_data *cfg)725{726 u32 flash_iout_max = cfg->boost_mode ? FLASH_IOUT_MAX_2LEDS :727 FLASH_IOUT_MAX_1LED;728 int i;729 730 if (cfg->num_leds == 1 &&731 max77693_fled_used(led, FLED1) && max77693_fled_used(led, FLED2))732 led->iout_joint = true;733 734 cfg->boost_mode = clamp_val(cfg->boost_mode, MAX77693_LED_BOOST_NONE,735 MAX77693_LED_BOOST_FIXED);736 737 /* Boost must be enabled if both current outputs are used */738 if ((cfg->boost_mode == MAX77693_LED_BOOST_NONE) && led->iout_joint)739 cfg->boost_mode = MAX77693_LED_BOOST_FIXED;740 741 max77693_align_iout_current(led, cfg->iout_torch_max,742 TORCH_IOUT_MIN, TORCH_IOUT_MAX, TORCH_IOUT_STEP);743 744 max77693_align_iout_current(led, cfg->iout_flash_max,745 FLASH_IOUT_MIN, flash_iout_max, FLASH_IOUT_STEP);746 747 for (i = 0; i < ARRAY_SIZE(cfg->flash_timeout_max); ++i)748 clamp_align(&cfg->flash_timeout_max[i], FLASH_TIMEOUT_MIN,749 FLASH_TIMEOUT_MAX, FLASH_TIMEOUT_STEP);750 751 clamp_align(&cfg->boost_vout, FLASH_VOUT_MIN, FLASH_VOUT_MAX,752 FLASH_VOUT_STEP);753 754 if (cfg->low_vsys)755 clamp_align(&cfg->low_vsys, MAX_FLASH1_VSYS_MIN,756 MAX_FLASH1_VSYS_MAX, MAX_FLASH1_VSYS_STEP);757}758 759static int max77693_led_get_configuration(struct max77693_led_device *led,760 struct max77693_led_config_data *cfg,761 struct device_node **sub_nodes)762{763 int ret;764 765 ret = max77693_led_parse_dt(led, cfg, sub_nodes);766 if (ret < 0)767 return ret;768 769 max77693_led_validate_configuration(led, cfg);770 771 memcpy(led->iout_torch_max, cfg->iout_torch_max,772 sizeof(led->iout_torch_max));773 memcpy(led->iout_flash_max, cfg->iout_flash_max,774 sizeof(led->iout_flash_max));775 776 return 0;777}778 779static const struct led_flash_ops flash_ops = {780 .flash_brightness_set = max77693_led_flash_brightness_set,781 .strobe_set = max77693_led_flash_strobe_set,782 .strobe_get = max77693_led_flash_strobe_get,783 .timeout_set = max77693_led_flash_timeout_set,784 .fault_get = max77693_led_flash_fault_get,785};786 787static void max77693_init_flash_settings(struct max77693_sub_led *sub_led,788 struct max77693_led_config_data *led_cfg)789{790 struct led_classdev_flash *fled_cdev = &sub_led->fled_cdev;791 struct max77693_led_device *led = sub_led_to_led(sub_led);792 int fled_id = sub_led->fled_id;793 struct led_flash_setting *setting;794 795 /* Init flash intensity setting */796 setting = &fled_cdev->brightness;797 setting->min = FLASH_IOUT_MIN;798 setting->max = led->iout_joint ?799 led_cfg->iout_flash_max[FLED1] +800 led_cfg->iout_flash_max[FLED2] :801 led_cfg->iout_flash_max[fled_id];802 setting->step = FLASH_IOUT_STEP;803 setting->val = setting->max;804 805 /* Init flash timeout setting */806 setting = &fled_cdev->timeout;807 setting->min = FLASH_TIMEOUT_MIN;808 setting->max = led_cfg->flash_timeout_max[fled_id];809 setting->step = FLASH_TIMEOUT_STEP;810 setting->val = setting->max;811}812 813#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)814 815static int max77693_led_external_strobe_set(816 struct v4l2_flash *v4l2_flash,817 bool enable)818{819 struct max77693_sub_led *sub_led =820 flcdev_to_sub_led(v4l2_flash->fled_cdev);821 struct max77693_led_device *led = sub_led_to_led(sub_led);822 int fled_id = sub_led->fled_id;823 int ret;824 825 mutex_lock(&led->lock);826 827 if (enable)828 ret = max77693_add_mode(led, MODE_FLASH_EXTERNAL(fled_id));829 else830 ret = max77693_clear_mode(led, MODE_FLASH_EXTERNAL(fled_id));831 832 mutex_unlock(&led->lock);833 834 return ret;835}836 837static void max77693_init_v4l2_flash_config(struct max77693_sub_led *sub_led,838 struct max77693_led_config_data *led_cfg,839 struct v4l2_flash_config *v4l2_sd_cfg)840{841 struct max77693_led_device *led = sub_led_to_led(sub_led);842 struct device *dev = &led->pdev->dev;843 struct max77693_dev *iodev = dev_get_drvdata(dev->parent);844 struct i2c_client *i2c = iodev->i2c;845 struct led_flash_setting *s;846 847 snprintf(v4l2_sd_cfg->dev_name, sizeof(v4l2_sd_cfg->dev_name),848 "%s %d-%04x", sub_led->fled_cdev.led_cdev.name,849 i2c_adapter_id(i2c->adapter), i2c->addr);850 851 s = &v4l2_sd_cfg->intensity;852 s->min = TORCH_IOUT_MIN;853 s->max = sub_led->fled_cdev.led_cdev.max_brightness * TORCH_IOUT_STEP;854 s->step = TORCH_IOUT_STEP;855 s->val = s->max;856 857 /* Init flash faults config */858 v4l2_sd_cfg->flash_faults = LED_FAULT_OVER_VOLTAGE |859 LED_FAULT_SHORT_CIRCUIT |860 LED_FAULT_OVER_CURRENT;861 862 v4l2_sd_cfg->has_external_strobe = true;863}864 865static const struct v4l2_flash_ops v4l2_flash_ops = {866 .external_strobe_set = max77693_led_external_strobe_set,867};868#else869static inline void max77693_init_v4l2_flash_config(870 struct max77693_sub_led *sub_led,871 struct max77693_led_config_data *led_cfg,872 struct v4l2_flash_config *v4l2_sd_cfg)873{874}875static const struct v4l2_flash_ops v4l2_flash_ops;876#endif877 878static void max77693_init_fled_cdev(struct max77693_sub_led *sub_led,879 struct max77693_led_config_data *led_cfg)880{881 struct max77693_led_device *led = sub_led_to_led(sub_led);882 int fled_id = sub_led->fled_id;883 struct led_classdev_flash *fled_cdev;884 struct led_classdev *led_cdev;885 886 /* Initialize LED Flash class device */887 fled_cdev = &sub_led->fled_cdev;888 fled_cdev->ops = &flash_ops;889 led_cdev = &fled_cdev->led_cdev;890 891 led_cdev->name = led_cfg->label[fled_id];892 893 led_cdev->brightness_set_blocking = max77693_led_brightness_set;894 led_cdev->max_brightness = (led->iout_joint ?895 led_cfg->iout_torch_max[FLED1] +896 led_cfg->iout_torch_max[FLED2] :897 led_cfg->iout_torch_max[fled_id]) /898 TORCH_IOUT_STEP;899 led_cdev->flags |= LED_DEV_CAP_FLASH;900 901 max77693_init_flash_settings(sub_led, led_cfg);902 903 /* Init flash timeout cache */904 sub_led->flash_timeout = fled_cdev->timeout.val;905}906 907static int max77693_register_led(struct max77693_sub_led *sub_led,908 struct max77693_led_config_data *led_cfg,909 struct device_node *sub_node)910{911 struct max77693_led_device *led = sub_led_to_led(sub_led);912 struct led_classdev_flash *fled_cdev = &sub_led->fled_cdev;913 struct device *dev = &led->pdev->dev;914 struct v4l2_flash_config v4l2_sd_cfg = {};915 int ret;916 917 /* Register in the LED subsystem */918 ret = led_classdev_flash_register(dev, fled_cdev);919 if (ret < 0)920 return ret;921 922 max77693_init_v4l2_flash_config(sub_led, led_cfg, &v4l2_sd_cfg);923 924 /* Register in the V4L2 subsystem. */925 sub_led->v4l2_flash = v4l2_flash_init(dev, of_fwnode_handle(sub_node),926 fled_cdev, &v4l2_flash_ops,927 &v4l2_sd_cfg);928 if (IS_ERR(sub_led->v4l2_flash)) {929 ret = PTR_ERR(sub_led->v4l2_flash);930 goto err_v4l2_flash_init;931 }932 933 return 0;934 935err_v4l2_flash_init:936 led_classdev_flash_unregister(fled_cdev);937 return ret;938}939 940static int max77693_led_probe(struct platform_device *pdev)941{942 struct device *dev = &pdev->dev;943 struct max77693_dev *iodev = dev_get_drvdata(dev->parent);944 struct max77693_led_device *led;945 struct max77693_sub_led *sub_leds;946 struct device_node *sub_nodes[2] = {};947 struct max77693_led_config_data led_cfg = {};948 int init_fled_cdev[2], i, ret;949 950 led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);951 if (!led)952 return -ENOMEM;953 954 led->pdev = pdev;955 led->regmap = iodev->regmap;956 led->allowed_modes = MODE_FLASH_MASK;957 sub_leds = led->sub_leds;958 959 platform_set_drvdata(pdev, led);960 ret = max77693_led_get_configuration(led, &led_cfg, sub_nodes);961 if (ret < 0)962 return ret;963 964 ret = max77693_setup(led, &led_cfg);965 if (ret < 0)966 goto err_setup;967 968 mutex_init(&led->lock);969 970 init_fled_cdev[FLED1] =971 led->iout_joint || max77693_fled_used(led, FLED1);972 init_fled_cdev[FLED2] =973 !led->iout_joint && max77693_fled_used(led, FLED2);974 975 for (i = FLED1; i <= FLED2; ++i) {976 if (!init_fled_cdev[i])977 continue;978 979 /* Initialize LED Flash class device */980 max77693_init_fled_cdev(&sub_leds[i], &led_cfg);981 982 /*983 * Register LED Flash class device and corresponding984 * V4L2 Flash device.985 */986 ret = max77693_register_led(&sub_leds[i], &led_cfg,987 sub_nodes[i]);988 if (ret < 0) {989 /*990 * At this moment FLED1 might have been already991 * registered and it needs to be released.992 */993 if (i == FLED2)994 goto err_register_led2;995 else996 goto err_register_led1;997 }998 of_node_put(sub_nodes[i]);999 sub_nodes[i] = NULL;1000 }1001 1002 return 0;1003 1004err_register_led2:1005 /* It is possible than only FLED2 was to be registered */1006 if (!init_fled_cdev[FLED1])1007 goto err_register_led1;1008 v4l2_flash_release(sub_leds[FLED1].v4l2_flash);1009 led_classdev_flash_unregister(&sub_leds[FLED1].fled_cdev);1010err_register_led1:1011 mutex_destroy(&led->lock);1012 1013err_setup:1014 for (i = FLED1; i <= FLED2; i++)1015 of_node_put(sub_nodes[i]);1016 return ret;1017}1018 1019static void 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 1037static const struct of_device_id max77693_led_dt_match[] = {1038 { .compatible = "maxim,max77693-led" },1039 {},1040};1041MODULE_DEVICE_TABLE(of, max77693_led_dt_match);1042 1043static struct platform_driver max77693_led_driver = {1044 .probe = max77693_led_probe,1045 .remove_new = max77693_led_remove,1046 .driver = {1047 .name = "max77693-led",1048 .of_match_table = max77693_led_dt_match,1049 },1050};1051 1052module_platform_driver(max77693_led_driver);1053 1054MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");1055MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");1056MODULE_DESCRIPTION("Maxim MAX77693 led flash driver");1057MODULE_LICENSE("GPL v2");1058