1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2023 Richtek Technology Corp.
6 * Alice Chen <alice_chen@richtek.com>
7 * ChiYuan Huang <cy_huang@richtek.com>
10 #include <linux/bitops.h>
11 #include <linux/delay.h>
12 #include <linux/init.h>
13 #include <linux/interrupt.h>
14 #include <linux/kernel.h>
15 #include <linux/led-class-flash.h>
16 #include <linux/module.h>
17 #include <linux/mutex.h>
18 #include <linux/platform_device.h>
19 #include <linux/property.h>
20 #include <linux/regmap.h>
22 #include <media/v4l2-flash-led-class.h>
25 MT6370_LED_FLASH1
= 0,
30 /* Virtual definition for multicolor */
32 #define MT6370_REG_FLEDEN 0x17E
33 #define MT6370_REG_STRBTO 0x173
34 #define MT6370_REG_CHGSTAT2 0x1D1
35 #define MT6370_REG_FLEDSTAT1 0x1D9
36 #define MT6370_REG_FLEDISTRB(_id) (0x174 + 4 * (_id))
37 #define MT6370_REG_FLEDITOR(_id) (0x175 + 4 * (_id))
38 #define MT6370_ITORCH_MASK GENMASK(4, 0)
39 #define MT6370_ISTROBE_MASK GENMASK(6, 0)
40 #define MT6370_STRBTO_MASK GENMASK(6, 0)
41 #define MT6370_TORCHEN_MASK BIT(3)
42 #define MT6370_STROBEN_MASK BIT(2)
43 #define MT6370_FLCSEN_MASK(_id) BIT(MT6370_LED_FLASH2 - (_id))
44 #define MT6370_FLCSEN_MASK_ALL GENMASK(1, 0)
45 #define MT6370_FLEDCHGVINOVP_MASK BIT(3)
46 #define MT6370_FLED1STRBTO_MASK BIT(11)
47 #define MT6370_FLED2STRBTO_MASK BIT(10)
48 #define MT6370_FLED1STRB_MASK BIT(9)
49 #define MT6370_FLED2STRB_MASK BIT(8)
50 #define MT6370_FLED1SHORT_MASK BIT(7)
51 #define MT6370_FLED2SHORT_MASK BIT(6)
52 #define MT6370_FLEDLVF_MASK BIT(3)
54 #define MT6370_LED_JOINT 2
55 #define MT6370_RANGE_FLED_REG 4
56 #define MT6370_ITORCH_MIN_uA 25000
57 #define MT6370_ITORCH_STEP_uA 12500
58 #define MT6370_ITORCH_MAX_uA 400000
59 #define MT6370_ITORCH_DOUBLE_MAX_uA 800000
60 #define MT6370_ISTRB_MIN_uA 50000
61 #define MT6370_ISTRB_STEP_uA 12500
62 #define MT6370_ISTRB_MAX_uA 1500000
63 #define MT6370_ISTRB_DOUBLE_MAX_uA 3000000
64 #define MT6370_STRBTO_MIN_US 64000
65 #define MT6370_STRBTO_STEP_US 32000
66 #define MT6370_STRBTO_MAX_US 2432000
68 #define to_mt6370_led(ptr, member) container_of(ptr, struct mt6370_led, member)
71 struct led_classdev_flash flash
;
72 struct v4l2_flash
*v4l2_flash
;
73 struct mt6370_priv
*priv
;
78 struct regmap
*regmap
;
80 unsigned int fled_strobe_used
;
81 unsigned int fled_torch_used
;
82 unsigned int leds_active
;
83 unsigned int leds_count
;
84 struct mt6370_led leds
[] __counted_by(leds_count
);
87 static int mt6370_torch_brightness_set(struct led_classdev
*lcdev
, enum led_brightness level
)
89 struct mt6370_led
*led
= to_mt6370_led(lcdev
, flash
.led_cdev
);
90 struct mt6370_priv
*priv
= led
->priv
;
91 u32 led_enable_mask
= led
->led_no
== MT6370_LED_JOINT
? MT6370_FLCSEN_MASK_ALL
:
92 MT6370_FLCSEN_MASK(led
->led_no
);
93 u32 enable_mask
= MT6370_TORCHEN_MASK
| led_enable_mask
;
94 u32 val
= level
? led_enable_mask
: 0;
98 mutex_lock(&priv
->lock
);
101 * There is only one set of flash control logic, and this flag is used to check if 'strobe'
102 * is currently being used.
104 if (priv
->fled_strobe_used
) {
105 dev_warn(lcdev
->dev
, "Please disable strobe first [%d]\n", priv
->fled_strobe_used
);
111 curr
= priv
->fled_torch_used
| BIT(led
->led_no
);
113 curr
= priv
->fled_torch_used
& ~BIT(led
->led_no
);
116 val
|= MT6370_TORCHEN_MASK
;
120 if (led
->led_no
== MT6370_LED_JOINT
) {
121 u32 flevel
[MT6370_MAX_LEDS
];
124 * There're two flash channels in MT6370. If joint flash output is used,
125 * torch current will be averaged output from both channels.
127 flevel
[0] = level
/ 2;
128 flevel
[1] = level
- flevel
[0];
129 for (i
= 0; i
< MT6370_MAX_LEDS
; i
++) {
130 ret
= regmap_update_bits(priv
->regmap
, MT6370_REG_FLEDITOR(i
),
131 MT6370_ITORCH_MASK
, flevel
[i
]);
136 ret
= regmap_update_bits(priv
->regmap
, MT6370_REG_FLEDITOR(led
->led_no
),
137 MT6370_ITORCH_MASK
, level
);
143 ret
= regmap_update_bits(priv
->regmap
, MT6370_REG_FLEDEN
, enable_mask
, val
);
147 priv
->fled_torch_used
= curr
;
150 mutex_unlock(&priv
->lock
);
154 static int mt6370_flash_brightness_set(struct led_classdev_flash
*fl_cdev
, u32 brightness
)
157 * Because of the current spikes when turning on the flash, the brightness should be kept
158 * by the LED framework. This empty function is used to prevent checking failure when
159 * led_classdev_flash registers ops.
164 static int _mt6370_flash_brightness_set(struct led_classdev_flash
*fl_cdev
, u32 brightness
)
166 struct mt6370_led
*led
= to_mt6370_led(fl_cdev
, flash
);
167 struct mt6370_priv
*priv
= led
->priv
;
168 struct led_flash_setting
*setting
= &fl_cdev
->brightness
;
169 u32 val
= (brightness
- setting
->min
) / setting
->step
;
172 if (led
->led_no
== MT6370_LED_JOINT
) {
173 u32 flevel
[MT6370_MAX_LEDS
];
176 * There're two flash channels in MT6370. If joint flash output is used, storbe
177 * current will be averaged output from both channels.
180 flevel
[1] = val
- flevel
[0];
181 for (i
= 0; i
< MT6370_MAX_LEDS
; i
++) {
182 ret
= regmap_update_bits(priv
->regmap
, MT6370_REG_FLEDISTRB(i
),
183 MT6370_ISTROBE_MASK
, flevel
[i
]);
188 ret
= regmap_update_bits(priv
->regmap
, MT6370_REG_FLEDISTRB(led
->led_no
),
189 MT6370_ISTROBE_MASK
, val
);
195 static int mt6370_strobe_set(struct led_classdev_flash
*fl_cdev
, bool state
)
197 struct mt6370_led
*led
= to_mt6370_led(fl_cdev
, flash
);
198 struct mt6370_priv
*priv
= led
->priv
;
199 struct led_classdev
*lcdev
= &fl_cdev
->led_cdev
;
200 struct led_flash_setting
*s
= &fl_cdev
->brightness
;
201 u32 led_enable_mask
= led
->led_no
== MT6370_LED_JOINT
? MT6370_FLCSEN_MASK_ALL
:
202 MT6370_FLCSEN_MASK(led
->led_no
);
203 u32 enable_mask
= MT6370_STROBEN_MASK
| led_enable_mask
;
204 u32 val
= state
? led_enable_mask
: 0;
208 mutex_lock(&priv
->lock
);
211 * There is only one set of flash control logic, and this flag is used to check if 'torch'
212 * is currently being used.
214 if (priv
->fled_torch_used
) {
215 dev_warn(lcdev
->dev
, "Please disable torch first [0x%x]\n", priv
->fled_torch_used
);
221 curr
= priv
->fled_strobe_used
| BIT(led
->led_no
);
223 curr
= priv
->fled_strobe_used
& ~BIT(led
->led_no
);
226 val
|= MT6370_STROBEN_MASK
;
228 ret
= regmap_update_bits(priv
->regmap
, MT6370_REG_FLEDEN
, enable_mask
, val
);
230 dev_err(lcdev
->dev
, "[%d] control current source %d fail\n", led
->led_no
, state
);
235 * If the flash needs to turn on, configure the flash current to ramp up to the setting
236 * value. Otherwise, always revert to the minimum one.
238 ret
= _mt6370_flash_brightness_set(fl_cdev
, state
? s
->val
: s
->min
);
240 dev_err(lcdev
->dev
, "[%d] Failed to set brightness\n", led
->led_no
);
245 * For the flash to turn on/off, we must wait for HW ramping up/down time 5ms/500us to
246 * prevent the unexpected problem.
248 if (!priv
->fled_strobe_used
&& curr
)
249 usleep_range(5000, 6000);
250 else if (priv
->fled_strobe_used
&& !curr
)
251 usleep_range(500, 600);
253 priv
->fled_strobe_used
= curr
;
256 mutex_unlock(&priv
->lock
);
260 static int mt6370_strobe_get(struct led_classdev_flash
*fl_cdev
, bool *state
)
262 struct mt6370_led
*led
= to_mt6370_led(fl_cdev
, flash
);
263 struct mt6370_priv
*priv
= led
->priv
;
265 mutex_lock(&priv
->lock
);
266 *state
= !!(priv
->fled_strobe_used
& BIT(led
->led_no
));
267 mutex_unlock(&priv
->lock
);
272 static int mt6370_timeout_set(struct led_classdev_flash
*fl_cdev
, u32 timeout
)
274 struct mt6370_led
*led
= to_mt6370_led(fl_cdev
, flash
);
275 struct mt6370_priv
*priv
= led
->priv
;
276 struct led_flash_setting
*s
= &fl_cdev
->timeout
;
277 u32 val
= (timeout
- s
->min
) / s
->step
;
279 return regmap_update_bits(priv
->regmap
, MT6370_REG_STRBTO
, MT6370_STRBTO_MASK
, val
);
282 static int mt6370_fault_get(struct led_classdev_flash
*fl_cdev
, u32
*fault
)
284 struct mt6370_led
*led
= to_mt6370_led(fl_cdev
, flash
);
285 struct mt6370_priv
*priv
= led
->priv
;
287 unsigned int chg_stat
, strobe_timeout_mask
, fled_short_mask
;
291 ret
= regmap_read(priv
->regmap
, MT6370_REG_CHGSTAT2
, &chg_stat
);
295 ret
= regmap_raw_read(priv
->regmap
, MT6370_REG_FLEDSTAT1
, &fled_stat
, sizeof(fled_stat
));
299 switch (led
->led_no
) {
300 case MT6370_LED_FLASH1
:
301 strobe_timeout_mask
= MT6370_FLED1STRBTO_MASK
;
302 fled_short_mask
= MT6370_FLED1SHORT_MASK
;
305 case MT6370_LED_FLASH2
:
306 strobe_timeout_mask
= MT6370_FLED2STRBTO_MASK
;
307 fled_short_mask
= MT6370_FLED2SHORT_MASK
;
310 case MT6370_LED_JOINT
:
311 strobe_timeout_mask
= MT6370_FLED1STRBTO_MASK
| MT6370_FLED2STRBTO_MASK
;
312 fled_short_mask
= MT6370_FLED1SHORT_MASK
| MT6370_FLED2SHORT_MASK
;
318 if (chg_stat
& MT6370_FLEDCHGVINOVP_MASK
)
319 rfault
|= LED_FAULT_INPUT_VOLTAGE
;
321 if (fled_stat
& strobe_timeout_mask
)
322 rfault
|= LED_FAULT_TIMEOUT
;
324 if (fled_stat
& fled_short_mask
)
325 rfault
|= LED_FAULT_SHORT_CIRCUIT
;
327 if (fled_stat
& MT6370_FLEDLVF_MASK
)
328 rfault
|= LED_FAULT_UNDER_VOLTAGE
;
334 static const struct led_flash_ops mt6370_flash_ops
= {
335 .flash_brightness_set
= mt6370_flash_brightness_set
,
336 .strobe_set
= mt6370_strobe_set
,
337 .strobe_get
= mt6370_strobe_get
,
338 .timeout_set
= mt6370_timeout_set
,
339 .fault_get
= mt6370_fault_get
,
342 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
343 static int mt6370_flash_external_strobe_set(struct v4l2_flash
*v4l2_flash
,
346 struct led_classdev_flash
*flash
= v4l2_flash
->fled_cdev
;
347 struct mt6370_led
*led
= to_mt6370_led(flash
, flash
);
348 struct mt6370_priv
*priv
= led
->priv
;
349 u32 mask
= led
->led_no
== MT6370_LED_JOINT
? MT6370_FLCSEN_MASK_ALL
:
350 MT6370_FLCSEN_MASK(led
->led_no
);
351 u32 val
= enable
? mask
: 0;
354 mutex_lock(&priv
->lock
);
356 ret
= regmap_update_bits(priv
->regmap
, MT6370_REG_FLEDEN
, mask
, val
);
361 priv
->fled_strobe_used
|= BIT(led
->led_no
);
363 priv
->fled_strobe_used
&= ~BIT(led
->led_no
);
366 mutex_unlock(&priv
->lock
);
370 static const struct v4l2_flash_ops v4l2_flash_ops
= {
371 .external_strobe_set
= mt6370_flash_external_strobe_set
,
374 static void mt6370_init_v4l2_flash_config(struct mt6370_led
*led
, struct v4l2_flash_config
*cfg
)
376 struct led_classdev
*lcdev
;
377 struct led_flash_setting
*s
= &cfg
->intensity
;
379 lcdev
= &led
->flash
.led_cdev
;
381 s
->min
= MT6370_ITORCH_MIN_uA
;
382 s
->step
= MT6370_ITORCH_STEP_uA
;
383 s
->val
= s
->max
= s
->min
+ (lcdev
->max_brightness
- 1) * s
->step
;
385 cfg
->has_external_strobe
= 1;
386 strscpy(cfg
->dev_name
, dev_name(lcdev
->dev
), sizeof(cfg
->dev_name
));
388 cfg
->flash_faults
= LED_FAULT_SHORT_CIRCUIT
| LED_FAULT_TIMEOUT
|
389 LED_FAULT_INPUT_VOLTAGE
| LED_FAULT_UNDER_VOLTAGE
;
392 static const struct v4l2_flash_ops v4l2_flash_ops
;
393 static void mt6370_init_v4l2_flash_config(struct mt6370_led
*led
, struct v4l2_flash_config
*cfg
)
398 static void mt6370_v4l2_flash_release(void *v4l2_flash
)
400 v4l2_flash_release(v4l2_flash
);
403 static int mt6370_led_register(struct device
*parent
, struct mt6370_led
*led
,
404 struct fwnode_handle
*fwnode
)
406 struct led_init_data init_data
= { .fwnode
= fwnode
};
407 struct v4l2_flash_config v4l2_config
= {};
410 ret
= devm_led_classdev_flash_register_ext(parent
, &led
->flash
, &init_data
);
412 return dev_err_probe(parent
, ret
, "Couldn't register flash %d\n", led
->led_no
);
414 mt6370_init_v4l2_flash_config(led
, &v4l2_config
);
415 led
->v4l2_flash
= v4l2_flash_init(parent
, fwnode
, &led
->flash
, &v4l2_flash_ops
,
417 if (IS_ERR(led
->v4l2_flash
))
418 return dev_err_probe(parent
, PTR_ERR(led
->v4l2_flash
),
419 "Failed to register %d v4l2 sd\n", led
->led_no
);
421 return devm_add_action_or_reset(parent
, mt6370_v4l2_flash_release
, led
->v4l2_flash
);
424 static u32
mt6370_clamp(u32 val
, u32 min
, u32 max
, u32 step
)
428 retval
= clamp_val(val
, min
, max
);
430 retval
= rounddown(retval
- min
, step
) + min
;
435 static int mt6370_init_flash_properties(struct device
*dev
, struct mt6370_led
*led
,
436 struct fwnode_handle
*fwnode
)
438 struct led_classdev_flash
*flash
= &led
->flash
;
439 struct led_classdev
*lcdev
= &flash
->led_cdev
;
440 struct mt6370_priv
*priv
= led
->priv
;
441 struct led_flash_setting
*s
;
442 u32 sources
[MT6370_MAX_LEDS
];
446 num
= fwnode_property_count_u32(fwnode
, "led-sources");
448 return dev_err_probe(dev
, -EINVAL
,
449 "Not specified or wrong number of led-sources\n");
451 ret
= fwnode_property_read_u32_array(fwnode
, "led-sources", sources
, num
);
455 for (i
= 0; i
< num
; i
++) {
456 if (sources
[i
] >= MT6370_MAX_LEDS
)
458 if (priv
->leds_active
& BIT(sources
[i
]))
460 priv
->leds_active
|= BIT(sources
[i
]);
463 /* If both channels are specified in 'led-sources', joint flash output mode is used */
464 led
->led_no
= num
== 2 ? MT6370_LED_JOINT
: sources
[0];
466 max_ua
= num
== 2 ? MT6370_ITORCH_DOUBLE_MAX_uA
: MT6370_ITORCH_MAX_uA
;
467 val
= MT6370_ITORCH_MIN_uA
;
468 ret
= fwnode_property_read_u32(fwnode
, "led-max-microamp", &val
);
470 val
= mt6370_clamp(val
, MT6370_ITORCH_MIN_uA
, max_ua
, MT6370_ITORCH_STEP_uA
);
472 lcdev
->max_brightness
= (val
- MT6370_ITORCH_MIN_uA
) / MT6370_ITORCH_STEP_uA
+ 1;
473 lcdev
->brightness_set_blocking
= mt6370_torch_brightness_set
;
474 lcdev
->flags
|= LED_DEV_CAP_FLASH
;
476 max_ua
= num
== 2 ? MT6370_ISTRB_DOUBLE_MAX_uA
: MT6370_ISTRB_MAX_uA
;
477 val
= MT6370_ISTRB_MIN_uA
;
478 ret
= fwnode_property_read_u32(fwnode
, "flash-max-microamp", &val
);
480 val
= mt6370_clamp(val
, MT6370_ISTRB_MIN_uA
, max_ua
, MT6370_ISTRB_STEP_uA
);
482 s
= &flash
->brightness
;
483 s
->min
= MT6370_ISTRB_MIN_uA
;
484 s
->step
= MT6370_ISTRB_STEP_uA
;
485 s
->val
= s
->max
= val
;
487 /* Always configure to the minimum level when off to prevent flash current spikes. */
488 ret
= _mt6370_flash_brightness_set(flash
, s
->min
);
492 val
= MT6370_STRBTO_MIN_US
;
493 ret
= fwnode_property_read_u32(fwnode
, "flash-max-timeout-us", &val
);
495 val
= mt6370_clamp(val
, MT6370_STRBTO_MIN_US
, MT6370_STRBTO_MAX_US
,
496 MT6370_STRBTO_STEP_US
);
499 s
->min
= MT6370_STRBTO_MIN_US
;
500 s
->step
= MT6370_STRBTO_STEP_US
;
501 s
->val
= s
->max
= val
;
503 flash
->ops
= &mt6370_flash_ops
;
508 static int mt6370_led_probe(struct platform_device
*pdev
)
510 struct device
*dev
= &pdev
->dev
;
511 struct mt6370_priv
*priv
;
512 struct fwnode_handle
*child
;
516 count
= device_get_child_node_count(dev
);
517 if (!count
|| count
> MT6370_MAX_LEDS
)
518 return dev_err_probe(dev
, -EINVAL
,
519 "No child node or node count over max led number %zu\n", count
);
521 priv
= devm_kzalloc(dev
, struct_size(priv
, leds
, count
), GFP_KERNEL
);
525 priv
->leds_count
= count
;
526 mutex_init(&priv
->lock
);
528 priv
->regmap
= dev_get_regmap(dev
->parent
, NULL
);
530 return dev_err_probe(dev
, -ENODEV
, "Failed to get parent regmap\n");
532 device_for_each_child_node(dev
, child
) {
533 struct mt6370_led
*led
= priv
->leds
+ i
;
537 ret
= mt6370_init_flash_properties(dev
, led
, child
);
539 fwnode_handle_put(child
);
543 ret
= mt6370_led_register(dev
, led
, child
);
545 fwnode_handle_put(child
);
555 static const struct of_device_id mt6370_led_of_id
[] = {
556 { .compatible
= "mediatek,mt6370-flashlight" },
559 MODULE_DEVICE_TABLE(of
, mt6370_led_of_id
);
561 static struct platform_driver mt6370_led_driver
= {
563 .name
= "mt6370-flashlight",
564 .of_match_table
= mt6370_led_of_id
,
566 .probe
= mt6370_led_probe
,
568 module_platform_driver(mt6370_led_driver
);
570 MODULE_AUTHOR("Alice Chen <alice_chen@richtek.com>");
571 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
572 MODULE_DESCRIPTION("MT6370 FLASH LED Driver");
573 MODULE_LICENSE("GPL");