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