1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2023 Richtek Technology Corp.
4 *
5 * Authors:
6 *   Alice Chen <alice_chen@richtek.com>
7 *   ChiYuan Huang <cy_huang@richtek.com>
8 */
9
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>
21
22#include <media/v4l2-flash-led-class.h>
23
24enum {
25	MT6370_LED_FLASH1 = 0,
26	MT6370_LED_FLASH2,
27	MT6370_MAX_LEDS
28};
29
30/* Virtual definition for multicolor */
31
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)
53
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
67
68#define to_mt6370_led(ptr, member) container_of(ptr, struct mt6370_led, member)
69
70struct mt6370_led {
71	struct led_classdev_flash flash;
72	struct v4l2_flash *v4l2_flash;
73	struct mt6370_priv *priv;
74	u8 led_no;
75};
76
77struct mt6370_priv {
78	struct regmap *regmap;
79	struct mutex lock;
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);
85};
86
87static int mt6370_torch_brightness_set(struct led_classdev *lcdev, enum led_brightness level)
88{
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;
95	u32 curr;
96	int ret, i;
97
98	mutex_lock(&priv->lock);
99
100	/*
101	 * There is only one set of flash control logic, and this flag is used to check if 'strobe'
102	 * is currently being used.
103	 */
104	if (priv->fled_strobe_used) {
105		dev_warn(lcdev->dev, "Please disable strobe first [%d]\n", priv->fled_strobe_used);
106		ret = -EBUSY;
107		goto unlock;
108	}
109
110	if (level)
111		curr = priv->fled_torch_used | BIT(led->led_no);
112	else
113		curr = priv->fled_torch_used & ~BIT(led->led_no);
114
115	if (curr)
116		val |= MT6370_TORCHEN_MASK;
117
118	if (level) {
119		level -= 1;
120		if (led->led_no == MT6370_LED_JOINT) {
121			u32 flevel[MT6370_MAX_LEDS];
122
123			/*
124			 * There're two flash channels in MT6370. If joint flash output is used,
125			 * torch current will be averaged output from both channels.
126			 */
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]);
132				if (ret)
133					goto unlock;
134			}
135		} else {
136			ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDITOR(led->led_no),
137						 MT6370_ITORCH_MASK, level);
138			if (ret)
139				goto unlock;
140		}
141	}
142
143	ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, enable_mask, val);
144	if (ret)
145		goto unlock;
146
147	priv->fled_torch_used = curr;
148
149unlock:
150	mutex_unlock(&priv->lock);
151	return ret;
152}
153
154static int mt6370_flash_brightness_set(struct led_classdev_flash *fl_cdev, u32 brightness)
155{
156	/*
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.
160	 */
161	return 0;
162}
163
164static int _mt6370_flash_brightness_set(struct led_classdev_flash *fl_cdev, u32 brightness)
165{
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;
170	int ret, i;
171
172	if (led->led_no == MT6370_LED_JOINT) {
173		u32 flevel[MT6370_MAX_LEDS];
174
175		/*
176		 * There're two flash channels in MT6370. If joint flash output is used, storbe
177		 * current will be averaged output from both channels.
178		 */
179		flevel[0] = val / 2;
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]);
184			if (ret)
185				break;
186		}
187	} else {
188		ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDISTRB(led->led_no),
189					 MT6370_ISTROBE_MASK, val);
190	}
191
192	return ret;
193}
194
195static int mt6370_strobe_set(struct led_classdev_flash *fl_cdev, bool state)
196{
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;
205	u32 curr;
206	int ret;
207
208	mutex_lock(&priv->lock);
209
210	/*
211	 * There is only one set of flash control logic, and this flag is used to check if 'torch'
212	 * is currently being used.
213	 */
214	if (priv->fled_torch_used) {
215		dev_warn(lcdev->dev, "Please disable torch first [0x%x]\n", priv->fled_torch_used);
216		ret = -EBUSY;
217		goto unlock;
218	}
219
220	if (state)
221		curr = priv->fled_strobe_used | BIT(led->led_no);
222	else
223		curr = priv->fled_strobe_used & ~BIT(led->led_no);
224
225	if (curr)
226		val |= MT6370_STROBEN_MASK;
227
228	ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, enable_mask, val);
229	if (ret) {
230		dev_err(lcdev->dev, "[%d] control current source %d fail\n", led->led_no, state);
231		goto unlock;
232	}
233
234	/*
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.
237	 */
238	ret = _mt6370_flash_brightness_set(fl_cdev, state ? s->val : s->min);
239	if (ret) {
240		dev_err(lcdev->dev, "[%d] Failed to set brightness\n", led->led_no);
241		goto unlock;
242	}
243
244	/*
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.
247	 */
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);
252
253	priv->fled_strobe_used = curr;
254
255unlock:
256	mutex_unlock(&priv->lock);
257	return ret;
258}
259
260static int mt6370_strobe_get(struct led_classdev_flash *fl_cdev, bool *state)
261{
262	struct mt6370_led *led = to_mt6370_led(fl_cdev, flash);
263	struct mt6370_priv *priv = led->priv;
264
265	mutex_lock(&priv->lock);
266	*state = !!(priv->fled_strobe_used & BIT(led->led_no));
267	mutex_unlock(&priv->lock);
268
269	return 0;
270}
271
272static int mt6370_timeout_set(struct led_classdev_flash *fl_cdev, u32 timeout)
273{
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;
278
279	return regmap_update_bits(priv->regmap, MT6370_REG_STRBTO, MT6370_STRBTO_MASK, val);
280}
281
282static int mt6370_fault_get(struct led_classdev_flash *fl_cdev, u32 *fault)
283{
284	struct mt6370_led *led = to_mt6370_led(fl_cdev, flash);
285	struct mt6370_priv *priv = led->priv;
286	u16 fled_stat;
287	unsigned int chg_stat, strobe_timeout_mask, fled_short_mask;
288	u32 rfault = 0;
289	int ret;
290
291	ret = regmap_read(priv->regmap, MT6370_REG_CHGSTAT2, &chg_stat);
292	if (ret)
293		return ret;
294
295	ret = regmap_raw_read(priv->regmap, MT6370_REG_FLEDSTAT1, &fled_stat, sizeof(fled_stat));
296	if (ret)
297		return ret;
298
299	switch (led->led_no) {
300	case MT6370_LED_FLASH1:
301		strobe_timeout_mask = MT6370_FLED1STRBTO_MASK;
302		fled_short_mask = MT6370_FLED1SHORT_MASK;
303		break;
304
305	case MT6370_LED_FLASH2:
306		strobe_timeout_mask = MT6370_FLED2STRBTO_MASK;
307		fled_short_mask = MT6370_FLED2SHORT_MASK;
308		break;
309
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;
313		break;
314	default:
315		return -EINVAL;
316	}
317
318	if (chg_stat & MT6370_FLEDCHGVINOVP_MASK)
319		rfault |= LED_FAULT_INPUT_VOLTAGE;
320
321	if (fled_stat & strobe_timeout_mask)
322		rfault |= LED_FAULT_TIMEOUT;
323
324	if (fled_stat & fled_short_mask)
325		rfault |= LED_FAULT_SHORT_CIRCUIT;
326
327	if (fled_stat & MT6370_FLEDLVF_MASK)
328		rfault |= LED_FAULT_UNDER_VOLTAGE;
329
330	*fault = rfault;
331	return ret;
332}
333
334static 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,
340};
341
342#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
343static int mt6370_flash_external_strobe_set(struct v4l2_flash *v4l2_flash,
344					    bool enable)
345{
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;
352	int ret;
353
354	mutex_lock(&priv->lock);
355
356	ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, mask, val);
357	if (ret)
358		goto unlock;
359
360	if (enable)
361		priv->fled_strobe_used |= BIT(led->led_no);
362	else
363		priv->fled_strobe_used &= ~BIT(led->led_no);
364
365unlock:
366	mutex_unlock(&priv->lock);
367	return ret;
368}
369
370static const struct v4l2_flash_ops v4l2_flash_ops = {
371	.external_strobe_set = mt6370_flash_external_strobe_set,
372};
373
374static void mt6370_init_v4l2_flash_config(struct mt6370_led *led, struct v4l2_flash_config *cfg)
375{
376	struct led_classdev *lcdev;
377	struct led_flash_setting *s = &cfg->intensity;
378
379	lcdev = &led->flash.led_cdev;
380
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;
384
385	cfg->has_external_strobe = 1;
386	strscpy(cfg->dev_name, dev_name(lcdev->dev), sizeof(cfg->dev_name));
387
388	cfg->flash_faults = LED_FAULT_SHORT_CIRCUIT | LED_FAULT_TIMEOUT |
389			    LED_FAULT_INPUT_VOLTAGE | LED_FAULT_UNDER_VOLTAGE;
390}
391#else
392static const struct v4l2_flash_ops v4l2_flash_ops;
393static void mt6370_init_v4l2_flash_config(struct mt6370_led *led, struct v4l2_flash_config *cfg)
394{
395}
396#endif
397
398static void mt6370_v4l2_flash_release(void *v4l2_flash)
399{
400	v4l2_flash_release(v4l2_flash);
401}
402
403static int mt6370_led_register(struct device *parent, struct mt6370_led *led,
404			       struct fwnode_handle *fwnode)
405{
406	struct led_init_data init_data = { .fwnode = fwnode };
407	struct v4l2_flash_config v4l2_config = {};
408	int ret;
409
410	ret = devm_led_classdev_flash_register_ext(parent, &led->flash, &init_data);
411	if (ret)
412		return dev_err_probe(parent, ret, "Couldn't register flash %d\n", led->led_no);
413
414	mt6370_init_v4l2_flash_config(led, &v4l2_config);
415	led->v4l2_flash = v4l2_flash_init(parent, fwnode, &led->flash, &v4l2_flash_ops,
416					  &v4l2_config);
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);
420
421	return devm_add_action_or_reset(parent, mt6370_v4l2_flash_release, led->v4l2_flash);
422}
423
424static u32 mt6370_clamp(u32 val, u32 min, u32 max, u32 step)
425{
426	u32 retval;
427
428	retval = clamp_val(val, min, max);
429	if (step > 1)
430		retval = rounddown(retval - min, step) + min;
431
432	return retval;
433}
434
435static int mt6370_init_flash_properties(struct device *dev, struct mt6370_led *led,
436					struct fwnode_handle *fwnode)
437{
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];
443	u32 max_ua, val;
444	int i, ret, num;
445
446	num = fwnode_property_count_u32(fwnode, "led-sources");
447	if (num < 1)
448		return dev_err_probe(dev, -EINVAL,
449				     "Not specified or wrong number of led-sources\n");
450
451	ret = fwnode_property_read_u32_array(fwnode, "led-sources", sources, num);
452	if (ret)
453		return ret;
454
455	for (i = 0; i < num; i++) {
456		if (sources[i] >= MT6370_MAX_LEDS)
457			return -EINVAL;
458		if (priv->leds_active & BIT(sources[i]))
459			return -EINVAL;
460		priv->leds_active |= BIT(sources[i]);
461	}
462
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];
465
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);
469	if (!ret)
470		val = mt6370_clamp(val, MT6370_ITORCH_MIN_uA, max_ua, MT6370_ITORCH_STEP_uA);
471
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;
475
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);
479	if (!ret)
480		val = mt6370_clamp(val, MT6370_ISTRB_MIN_uA, max_ua, MT6370_ISTRB_STEP_uA);
481
482	s = &flash->brightness;
483	s->min = MT6370_ISTRB_MIN_uA;
484	s->step = MT6370_ISTRB_STEP_uA;
485	s->val = s->max = val;
486
487	/* Always configure to the minimum level when off to prevent flash current spikes. */
488	ret = _mt6370_flash_brightness_set(flash, s->min);
489	if (ret)
490		return ret;
491
492	val = MT6370_STRBTO_MIN_US;
493	ret = fwnode_property_read_u32(fwnode, "flash-max-timeout-us", &val);
494	if (!ret)
495		val = mt6370_clamp(val, MT6370_STRBTO_MIN_US, MT6370_STRBTO_MAX_US,
496				   MT6370_STRBTO_STEP_US);
497
498	s = &flash->timeout;
499	s->min = MT6370_STRBTO_MIN_US;
500	s->step = MT6370_STRBTO_STEP_US;
501	s->val = s->max = val;
502
503	flash->ops = &mt6370_flash_ops;
504
505	return 0;
506}
507
508static int mt6370_led_probe(struct platform_device *pdev)
509{
510	struct device *dev = &pdev->dev;
511	struct mt6370_priv *priv;
512	struct fwnode_handle *child;
513	size_t count;
514	int i = 0, ret;
515
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);
520
521	priv = devm_kzalloc(dev, struct_size(priv, leds, count), GFP_KERNEL);
522	if (!priv)
523		return -ENOMEM;
524
525	priv->leds_count = count;
526	mutex_init(&priv->lock);
527
528	priv->regmap = dev_get_regmap(dev->parent, NULL);
529	if (!priv->regmap)
530		return dev_err_probe(dev, -ENODEV, "Failed to get parent regmap\n");
531
532	device_for_each_child_node(dev, child) {
533		struct mt6370_led *led = priv->leds + i;
534
535		led->priv = priv;
536
537		ret = mt6370_init_flash_properties(dev, led, child);
538		if (ret) {
539			fwnode_handle_put(child);
540			return ret;
541		}
542
543		ret = mt6370_led_register(dev, led, child);
544		if (ret) {
545			fwnode_handle_put(child);
546			return ret;
547		}
548
549		i++;
550	}
551
552	return 0;
553}
554
555static const struct of_device_id mt6370_led_of_id[] = {
556	{ .compatible = "mediatek,mt6370-flashlight" },
557	{}
558};
559MODULE_DEVICE_TABLE(of, mt6370_led_of_id);
560
561static struct platform_driver mt6370_led_driver = {
562	.driver = {
563		.name = "mt6370-flashlight",
564		.of_match_table = mt6370_led_of_id,
565	},
566	.probe = mt6370_led_probe,
567};
568module_platform_driver(mt6370_led_driver);
569
570MODULE_AUTHOR("Alice Chen <alice_chen@richtek.com>");
571MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
572MODULE_DESCRIPTION("MT6370 FLASH LED Driver");
573MODULE_LICENSE("GPL");
574