1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2023 Richtek Technology Corp.
4 *
5 * Authors:
6 *   ChiYuan Huang <cy_huang@richtek.com>
7 *   Alice Chen <alice_chen@richtek.com>
8 */
9
10#include <linux/bitfield.h>
11#include <linux/bitops.h>
12#include <linux/kernel.h>
13#include <linux/leds.h>
14#include <linux/led-class-multicolor.h>
15#include <linux/linear_range.h>
16#include <linux/mod_devicetable.h>
17#include <linux/module.h>
18#include <linux/mutex.h>
19#include <linux/platform_device.h>
20#include <linux/property.h>
21#include <linux/regmap.h>
22#include <linux/util_macros.h>
23
24#include <asm/unaligned.h>
25
26enum {
27	MT6370_LED_ISNK1 = 0,
28	MT6370_LED_ISNK2,
29	MT6370_LED_ISNK3,
30	MT6370_LED_ISNK4,
31	MT6370_MAX_LEDS
32};
33
34enum mt6370_led_mode {
35	MT6370_LED_PWM_MODE = 0,
36	MT6370_LED_BREATH_MODE,
37	MT6370_LED_REG_MODE,
38	MT6370_LED_MAX_MODE
39};
40
41enum mt6370_led_field {
42	F_RGB_EN = 0,
43	F_CHGIND_EN,
44	F_LED1_CURR,
45	F_LED2_CURR,
46	F_LED3_CURR,
47	F_LED4_CURR,
48	F_LED1_MODE,
49	F_LED2_MODE,
50	F_LED3_MODE,
51	F_LED4_MODE,
52	F_LED1_DUTY,
53	F_LED2_DUTY,
54	F_LED3_DUTY,
55	F_LED4_DUTY,
56	F_LED1_FREQ,
57	F_LED2_FREQ,
58	F_LED3_FREQ,
59	F_LED4_FREQ,
60	F_MAX_FIELDS
61};
62
63enum mt6370_led_ranges {
64	R_LED123_CURR = 0,
65	R_LED4_CURR,
66	R_LED_TRFON,
67	R_LED_TOFF,
68	R_MAX_RANGES
69};
70
71enum mt6370_pattern {
72	P_LED_TR1 = 0,
73	P_LED_TR2,
74	P_LED_TF1,
75	P_LED_TF2,
76	P_LED_TON,
77	P_LED_TOFF,
78	P_MAX_PATTERNS
79};
80
81#define MT6370_REG_DEV_INFO			0x100
82#define MT6370_REG_RGB1_DIM			0x182
83#define MT6370_REG_RGB2_DIM			0x183
84#define MT6370_REG_RGB3_DIM			0x184
85#define MT6370_REG_RGB_EN			0x185
86#define MT6370_REG_RGB1_ISNK			0x186
87#define MT6370_REG_RGB2_ISNK			0x187
88#define MT6370_REG_RGB3_ISNK			0x188
89#define MT6370_REG_RGB1_TR			0x189
90#define MT6370_REG_RGB_CHRIND_DIM		0x192
91#define MT6370_REG_RGB_CHRIND_CTRL		0x193
92#define MT6370_REG_RGB_CHRIND_TR		0x194
93
94#define MT6372_REG_RGB_EN			0x182
95#define MT6372_REG_RGB1_ISNK			0x183
96#define MT6372_REG_RGB2_ISNK			0x184
97#define MT6372_REG_RGB3_ISNK			0x185
98#define MT6372_REG_RGB4_ISNK			0x186
99#define MT6372_REG_RGB1_DIM			0x187
100#define MT6372_REG_RGB2_DIM			0x188
101#define MT6372_REG_RGB3_DIM			0x189
102#define MT6372_REG_RGB4_DIM			0x18A
103#define MT6372_REG_RGB12_FREQ			0x18B
104#define MT6372_REG_RGB34_FREQ			0x18C
105#define MT6372_REG_RGB1_TR			0x18D
106
107#define MT6370_VENDOR_ID_MASK			GENMASK(7, 4)
108#define MT6372_VENDOR_ID			0x9
109#define MT6372C_VENDOR_ID			0xb
110#define MT6370_CHEN_BIT(id)			BIT(MT6370_LED_ISNK4 - id)
111#define MT6370_VIRTUAL_MULTICOLOR		5
112#define MC_CHANNEL_NUM				3
113#define MT6370_PWM_DUTY				(BIT(5) - 1)
114#define MT6372_PWM_DUTY				(BIT(8) - 1)
115
116struct mt6370_led {
117	/*
118	 * If the color of the LED in DT is set to
119	 *   - 'LED_COLOR_ID_RGB'
120	 *   - 'LED_COLOR_ID_MULTI'
121	 * The member 'index' of this struct will be set to
122	 * 'MT6370_VIRTUAL_MULTICOLOR'.
123	 * If so, this LED will choose 'struct led_classdev_mc mc' to use.
124	 * Instead, if the member 'index' of this struct is set to
125	 * 'MT6370_LED_ISNK1' ~ 'MT6370_LED_ISNK4', then this LED will choose
126	 * 'struct led_classdev isink' to use.
127	 */
128	union {
129		struct led_classdev isink;
130		struct led_classdev_mc mc;
131	};
132	struct mt6370_priv *priv;
133	enum led_default_state default_state;
134	u32 index;
135};
136
137struct mt6370_pdata {
138	const unsigned int *tfreq;
139	unsigned int tfreq_len;
140	u16 reg_rgb1_tr;
141	s16 reg_rgb_chrind_tr;
142	u8 pwm_duty;
143};
144
145struct mt6370_priv {
146	/* Per LED access lock */
147	struct mutex lock;
148	struct regmap *regmap;
149	struct regmap_field *fields[F_MAX_FIELDS];
150	const struct reg_field *reg_fields;
151	const struct linear_range *ranges;
152	struct reg_cfg *reg_cfgs;
153	const struct mt6370_pdata *pdata;
154	unsigned int leds_count;
155	unsigned int leds_active;
156	struct mt6370_led leds[] __counted_by(leds_count);
157};
158
159static const struct reg_field common_reg_fields[F_MAX_FIELDS] = {
160	[F_RGB_EN]	= REG_FIELD(MT6370_REG_RGB_EN, 4, 7),
161	[F_CHGIND_EN]	= REG_FIELD(MT6370_REG_RGB_CHRIND_DIM, 7, 7),
162	[F_LED1_CURR]	= REG_FIELD(MT6370_REG_RGB1_ISNK, 0, 2),
163	[F_LED2_CURR]	= REG_FIELD(MT6370_REG_RGB2_ISNK, 0, 2),
164	[F_LED3_CURR]	= REG_FIELD(MT6370_REG_RGB3_ISNK, 0, 2),
165	[F_LED4_CURR]	= REG_FIELD(MT6370_REG_RGB_CHRIND_CTRL, 0, 1),
166	[F_LED1_MODE]	= REG_FIELD(MT6370_REG_RGB1_DIM, 5, 6),
167	[F_LED2_MODE]	= REG_FIELD(MT6370_REG_RGB2_DIM, 5, 6),
168	[F_LED3_MODE]	= REG_FIELD(MT6370_REG_RGB3_DIM, 5, 6),
169	[F_LED4_MODE]	= REG_FIELD(MT6370_REG_RGB_CHRIND_DIM, 5, 6),
170	[F_LED1_DUTY]	= REG_FIELD(MT6370_REG_RGB1_DIM, 0, 4),
171	[F_LED2_DUTY]	= REG_FIELD(MT6370_REG_RGB2_DIM, 0, 4),
172	[F_LED3_DUTY]	= REG_FIELD(MT6370_REG_RGB3_DIM, 0, 4),
173	[F_LED4_DUTY]	= REG_FIELD(MT6370_REG_RGB_CHRIND_DIM, 0, 4),
174	[F_LED1_FREQ]	= REG_FIELD(MT6370_REG_RGB1_ISNK, 3, 5),
175	[F_LED2_FREQ]	= REG_FIELD(MT6370_REG_RGB2_ISNK, 3, 5),
176	[F_LED3_FREQ]	= REG_FIELD(MT6370_REG_RGB3_ISNK, 3, 5),
177	[F_LED4_FREQ]	= REG_FIELD(MT6370_REG_RGB_CHRIND_CTRL, 2, 4),
178};
179
180static const struct reg_field mt6372_reg_fields[F_MAX_FIELDS] = {
181	[F_RGB_EN]	= REG_FIELD(MT6372_REG_RGB_EN, 4, 7),
182	[F_CHGIND_EN]	= REG_FIELD(MT6372_REG_RGB_EN, 3, 3),
183	[F_LED1_CURR]	= REG_FIELD(MT6372_REG_RGB1_ISNK, 0, 3),
184	[F_LED2_CURR]	= REG_FIELD(MT6372_REG_RGB2_ISNK, 0, 3),
185	[F_LED3_CURR]	= REG_FIELD(MT6372_REG_RGB3_ISNK, 0, 3),
186	[F_LED4_CURR]	= REG_FIELD(MT6372_REG_RGB4_ISNK, 0, 3),
187	[F_LED1_MODE]	= REG_FIELD(MT6372_REG_RGB1_ISNK, 6, 7),
188	[F_LED2_MODE]	= REG_FIELD(MT6372_REG_RGB2_ISNK, 6, 7),
189	[F_LED3_MODE]	= REG_FIELD(MT6372_REG_RGB3_ISNK, 6, 7),
190	[F_LED4_MODE]	= REG_FIELD(MT6372_REG_RGB4_ISNK, 6, 7),
191	[F_LED1_DUTY]	= REG_FIELD(MT6372_REG_RGB1_DIM, 0, 7),
192	[F_LED2_DUTY]	= REG_FIELD(MT6372_REG_RGB2_DIM, 0, 7),
193	[F_LED3_DUTY]	= REG_FIELD(MT6372_REG_RGB3_DIM, 0, 7),
194	[F_LED4_DUTY]	= REG_FIELD(MT6372_REG_RGB4_DIM, 0, 7),
195	[F_LED1_FREQ]	= REG_FIELD(MT6372_REG_RGB12_FREQ, 5, 7),
196	[F_LED2_FREQ]	= REG_FIELD(MT6372_REG_RGB12_FREQ, 2, 4),
197	[F_LED3_FREQ]	= REG_FIELD(MT6372_REG_RGB34_FREQ, 5, 7),
198	[F_LED4_FREQ]	= REG_FIELD(MT6372_REG_RGB34_FREQ, 2, 4),
199};
200
201/* Current unit: microamp, time unit: millisecond */
202static const struct linear_range common_led_ranges[R_MAX_RANGES] = {
203	[R_LED123_CURR]	= { 4000, 1, 6, 4000 },
204	[R_LED4_CURR]	= { 2000, 1, 3, 2000 },
205	[R_LED_TRFON]	= { 125, 0, 15, 200 },
206	[R_LED_TOFF]	= { 250, 0, 15, 400 },
207};
208
209static const struct linear_range mt6372_led_ranges[R_MAX_RANGES] = {
210	[R_LED123_CURR]	= { 2000, 1, 14, 2000 },
211	[R_LED4_CURR]	= { 2000, 1, 14, 2000 },
212	[R_LED_TRFON]	= { 125, 0, 15, 250 },
213	[R_LED_TOFF]	= { 250, 0, 15, 500 },
214};
215
216static const unsigned int common_tfreqs[] = {
217	10000, 5000, 2000, 1000, 500, 200, 5, 1,
218};
219
220static const unsigned int mt6372_tfreqs[] = {
221	8000, 4000, 2000, 1000, 500, 250, 8, 4,
222};
223
224static const struct mt6370_pdata common_pdata = {
225	.tfreq = common_tfreqs,
226	.tfreq_len = ARRAY_SIZE(common_tfreqs),
227	.pwm_duty = MT6370_PWM_DUTY,
228	.reg_rgb1_tr = MT6370_REG_RGB1_TR,
229	.reg_rgb_chrind_tr = MT6370_REG_RGB_CHRIND_TR,
230};
231
232static const struct mt6370_pdata mt6372_pdata = {
233	.tfreq = mt6372_tfreqs,
234	.tfreq_len = ARRAY_SIZE(mt6372_tfreqs),
235	.pwm_duty = MT6372_PWM_DUTY,
236	.reg_rgb1_tr = MT6372_REG_RGB1_TR,
237	.reg_rgb_chrind_tr = -1,
238};
239
240static enum mt6370_led_field mt6370_get_led_current_field(unsigned int led_no)
241{
242	switch (led_no) {
243	case MT6370_LED_ISNK1:
244		return F_LED1_CURR;
245	case MT6370_LED_ISNK2:
246		return F_LED2_CURR;
247	case MT6370_LED_ISNK3:
248		return F_LED3_CURR;
249	default:
250		return F_LED4_CURR;
251	}
252}
253
254static int mt6370_set_led_brightness(struct mt6370_priv *priv, unsigned int led_no,
255				     unsigned int level)
256{
257	enum mt6370_led_field sel_field;
258
259	sel_field = mt6370_get_led_current_field(led_no);
260
261	return regmap_field_write(priv->fields[sel_field], level);
262}
263
264static int mt6370_get_led_brightness(struct mt6370_priv *priv, unsigned int led_no,
265				     unsigned int *level)
266{
267	enum mt6370_led_field sel_field;
268
269	sel_field = mt6370_get_led_current_field(led_no);
270
271	return regmap_field_read(priv->fields[sel_field], level);
272}
273
274static int mt6370_set_led_duty(struct mt6370_priv *priv, unsigned int led_no, unsigned int ton,
275			       unsigned int toff)
276{
277	const struct mt6370_pdata *pdata = priv->pdata;
278	enum mt6370_led_field sel_field;
279	unsigned int divisor, ratio;
280
281	divisor = pdata->pwm_duty;
282	ratio = ton * divisor / (ton + toff);
283
284	switch (led_no) {
285	case MT6370_LED_ISNK1:
286		sel_field = F_LED1_DUTY;
287		break;
288	case MT6370_LED_ISNK2:
289		sel_field = F_LED2_DUTY;
290		break;
291	case MT6370_LED_ISNK3:
292		sel_field = F_LED3_DUTY;
293		break;
294	default:
295		sel_field = F_LED4_DUTY;
296		break;
297	}
298
299	return regmap_field_write(priv->fields[sel_field], ratio);
300}
301
302static int mt6370_set_led_freq(struct mt6370_priv *priv, unsigned int led_no, unsigned int ton,
303			       unsigned int toff)
304{
305	const struct mt6370_pdata *pdata = priv->pdata;
306	enum mt6370_led_field sel_field;
307	unsigned int tfreq_len = pdata->tfreq_len;
308	unsigned int tsum, sel;
309
310	tsum = ton + toff;
311
312	if (tsum > pdata->tfreq[0] || tsum < pdata->tfreq[tfreq_len - 1])
313		return -EOPNOTSUPP;
314
315	sel = find_closest_descending(tsum, pdata->tfreq, tfreq_len);
316
317	switch (led_no) {
318	case MT6370_LED_ISNK1:
319		sel_field = F_LED1_FREQ;
320		break;
321	case MT6370_LED_ISNK2:
322		sel_field = F_LED2_FREQ;
323		break;
324	case MT6370_LED_ISNK3:
325		sel_field = F_LED3_FREQ;
326		break;
327	default:
328		sel_field = F_LED4_FREQ;
329		break;
330	}
331
332	return regmap_field_write(priv->fields[sel_field], sel);
333}
334
335static void mt6370_get_breath_reg_base(struct mt6370_priv *priv, unsigned int led_no,
336				       unsigned int *base)
337{
338	const struct mt6370_pdata *pdata = priv->pdata;
339
340	if (pdata->reg_rgb_chrind_tr < 0) {
341		*base = pdata->reg_rgb1_tr + led_no * 3;
342		return;
343	}
344
345	switch (led_no) {
346	case MT6370_LED_ISNK1:
347	case MT6370_LED_ISNK2:
348	case MT6370_LED_ISNK3:
349		*base = pdata->reg_rgb1_tr + led_no * 3;
350		break;
351	default:
352		*base = pdata->reg_rgb_chrind_tr;
353		break;
354	}
355}
356
357static int mt6370_gen_breath_pattern(struct mt6370_priv *priv, struct led_pattern *pattern, u32 len,
358				     u8 *pattern_val, u32 val_len)
359{
360	enum mt6370_led_ranges sel_range;
361	struct led_pattern *curr;
362	unsigned int sel;
363	u32 val = 0;
364	int i;
365
366	if (len < P_MAX_PATTERNS && val_len < P_MAX_PATTERNS / 2)
367		return -EINVAL;
368
369	/*
370	 * Pattern list
371	 * tr1:	 byte 0, b'[7:4]
372	 * tr2:	 byte 0, b'[3:0]
373	 * tf1:	 byte 1, b'[7:4]
374	 * tf2:	 byte 1, b'[3:0]
375	 * ton:	 byte 2, b'[7:4]
376	 * toff: byte 2, b'[3:0]
377	 */
378	for (i = 0; i < P_MAX_PATTERNS; i++) {
379		curr = pattern + i;
380
381		sel_range = i == P_LED_TOFF ? R_LED_TOFF : R_LED_TRFON;
382
383		linear_range_get_selector_within(priv->ranges + sel_range, curr->delta_t, &sel);
384
385		if (i % 2) {
386			val |= sel;
387		} else {
388			val <<= 8;
389			val |= sel << 4;
390		}
391	}
392
393	put_unaligned_be24(val, pattern_val);
394
395	return 0;
396}
397
398static int mt6370_set_led_mode(struct mt6370_priv *priv, unsigned int led_no,
399			       enum mt6370_led_mode mode)
400{
401	enum mt6370_led_field sel_field;
402
403	switch (led_no) {
404	case MT6370_LED_ISNK1:
405		sel_field = F_LED1_MODE;
406		break;
407	case MT6370_LED_ISNK2:
408		sel_field = F_LED2_MODE;
409		break;
410	case MT6370_LED_ISNK3:
411		sel_field = F_LED3_MODE;
412		break;
413	default:
414		sel_field = F_LED4_MODE;
415		break;
416	}
417
418	return regmap_field_write(priv->fields[sel_field], mode);
419}
420
421static int mt6370_mc_brightness_set(struct led_classdev *lcdev, enum led_brightness level)
422{
423	struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev);
424	struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc);
425	struct mt6370_priv *priv = led->priv;
426	struct mc_subled *subled;
427	unsigned int enable, disable;
428	int i, ret;
429
430	mutex_lock(&priv->lock);
431
432	led_mc_calc_color_components(mccdev, level);
433
434	ret = regmap_field_read(priv->fields[F_RGB_EN], &enable);
435	if (ret)
436		goto out_unlock;
437
438	disable = enable;
439
440	for (i = 0; i < mccdev->num_colors; i++) {
441		u32 brightness;
442
443		subled = mccdev->subled_info + i;
444		brightness = min(subled->brightness, lcdev->max_brightness);
445		disable &= ~MT6370_CHEN_BIT(subled->channel);
446
447		if (level == 0) {
448			enable &= ~MT6370_CHEN_BIT(subled->channel);
449
450			ret = mt6370_set_led_mode(priv, subled->channel, MT6370_LED_REG_MODE);
451			if (ret)
452				goto out_unlock;
453
454			continue;
455		}
456
457		if (brightness == 0) {
458			enable &= ~MT6370_CHEN_BIT(subled->channel);
459			continue;
460		}
461
462		enable |= MT6370_CHEN_BIT(subled->channel);
463
464		ret = mt6370_set_led_brightness(priv, subled->channel, brightness);
465		if (ret)
466			goto out_unlock;
467	}
468
469	ret = regmap_field_write(priv->fields[F_RGB_EN], disable);
470	if (ret)
471		goto out_unlock;
472
473	ret = regmap_field_write(priv->fields[F_RGB_EN], enable);
474
475out_unlock:
476	mutex_unlock(&priv->lock);
477
478	return ret;
479}
480
481static int mt6370_mc_blink_set(struct led_classdev *lcdev,
482			       unsigned long *delay_on,
483			       unsigned long *delay_off)
484{
485	struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev);
486	struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc);
487	struct mt6370_priv *priv = led->priv;
488	struct mc_subled *subled;
489	unsigned int enable, disable;
490	int i, ret;
491
492	mutex_lock(&priv->lock);
493
494	if (!*delay_on && !*delay_off)
495		*delay_on = *delay_off = 500;
496
497	ret = regmap_field_read(priv->fields[F_RGB_EN], &enable);
498	if (ret)
499		goto out_unlock;
500
501	disable = enable;
502
503	for (i = 0; i < mccdev->num_colors; i++) {
504		subled = mccdev->subled_info + i;
505
506		disable &= ~MT6370_CHEN_BIT(subled->channel);
507
508		ret = mt6370_set_led_duty(priv, subled->channel, *delay_on, *delay_off);
509		if (ret)
510			goto out_unlock;
511
512		ret = mt6370_set_led_freq(priv, subled->channel, *delay_on, *delay_off);
513		if (ret)
514			goto out_unlock;
515
516		ret = mt6370_set_led_mode(priv, subled->channel, MT6370_LED_PWM_MODE);
517		if (ret)
518			goto out_unlock;
519	}
520
521	/* Toggle to make pattern timing the same */
522	ret = regmap_field_write(priv->fields[F_RGB_EN], disable);
523	if (ret)
524		goto out_unlock;
525
526	ret = regmap_field_write(priv->fields[F_RGB_EN], enable);
527
528out_unlock:
529	mutex_unlock(&priv->lock);
530
531	return ret;
532}
533
534static int mt6370_mc_pattern_set(struct led_classdev *lcdev, struct led_pattern *pattern, u32 len,
535				 int repeat)
536{
537	struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev);
538	struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc);
539	struct mt6370_priv *priv = led->priv;
540	struct mc_subled *subled;
541	unsigned int reg_base, enable, disable;
542	u8 params[P_MAX_PATTERNS / 2];
543	int i, ret;
544
545	mutex_lock(&priv->lock);
546
547	ret = mt6370_gen_breath_pattern(priv, pattern, len, params, sizeof(params));
548	if (ret)
549		goto out_unlock;
550
551	ret = regmap_field_read(priv->fields[F_RGB_EN], &enable);
552	if (ret)
553		goto out_unlock;
554
555	disable = enable;
556
557	for (i = 0; i < mccdev->num_colors; i++) {
558		subled = mccdev->subled_info + i;
559
560		mt6370_get_breath_reg_base(priv, subled->channel, &reg_base);
561		disable &= ~MT6370_CHEN_BIT(subled->channel);
562
563		ret = regmap_raw_write(priv->regmap, reg_base, params, sizeof(params));
564		if (ret)
565			goto out_unlock;
566
567		ret = mt6370_set_led_mode(priv, subled->channel, MT6370_LED_BREATH_MODE);
568		if (ret)
569			goto out_unlock;
570	}
571
572	/* Toggle to make pattern timing be the same */
573	ret = regmap_field_write(priv->fields[F_RGB_EN], disable);
574	if (ret)
575		goto out_unlock;
576
577	ret = regmap_field_write(priv->fields[F_RGB_EN], enable);
578
579out_unlock:
580	mutex_unlock(&priv->lock);
581
582	return ret;
583}
584
585static inline int mt6370_mc_pattern_clear(struct led_classdev *lcdev)
586{
587	struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev);
588	struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc);
589	struct mt6370_priv *priv = led->priv;
590	struct mc_subled *subled;
591	int i, ret;
592
593	mutex_lock(&led->priv->lock);
594
595	for (i = 0; i < mccdev->num_colors; i++) {
596		subled = mccdev->subled_info + i;
597
598		ret = mt6370_set_led_mode(priv, subled->channel, MT6370_LED_REG_MODE);
599		if (ret)
600			break;
601	}
602
603	mutex_unlock(&led->priv->lock);
604
605	return ret;
606}
607
608static int mt6370_isnk_brightness_set(struct led_classdev *lcdev,
609				      enum led_brightness level)
610{
611	struct mt6370_led *led = container_of(lcdev, struct mt6370_led, isink);
612	struct mt6370_priv *priv = led->priv;
613	unsigned int enable;
614	int ret;
615
616	mutex_lock(&priv->lock);
617
618	ret = regmap_field_read(priv->fields[F_RGB_EN], &enable);
619	if (ret)
620		goto out_unlock;
621
622	if (level == 0) {
623		enable &= ~MT6370_CHEN_BIT(led->index);
624
625		ret = mt6370_set_led_mode(priv, led->index, MT6370_LED_REG_MODE);
626		if (ret)
627			goto out_unlock;
628	} else {
629		enable |= MT6370_CHEN_BIT(led->index);
630
631		ret = mt6370_set_led_brightness(priv, led->index, level);
632		if (ret)
633			goto out_unlock;
634	}
635
636	ret = regmap_field_write(priv->fields[F_RGB_EN], enable);
637
638out_unlock:
639	mutex_unlock(&priv->lock);
640
641	return ret;
642}
643
644static int mt6370_isnk_blink_set(struct led_classdev *lcdev, unsigned long *delay_on,
645				 unsigned long *delay_off)
646{
647	struct mt6370_led *led = container_of(lcdev, struct mt6370_led, isink);
648	struct mt6370_priv *priv = led->priv;
649	int ret;
650
651	mutex_lock(&priv->lock);
652
653	if (!*delay_on && !*delay_off)
654		*delay_on = *delay_off = 500;
655
656	ret = mt6370_set_led_duty(priv, led->index, *delay_on, *delay_off);
657	if (ret)
658		goto out_unlock;
659
660	ret = mt6370_set_led_freq(priv, led->index, *delay_on, *delay_off);
661	if (ret)
662		goto out_unlock;
663
664	ret = mt6370_set_led_mode(priv, led->index, MT6370_LED_PWM_MODE);
665
666out_unlock:
667	mutex_unlock(&priv->lock);
668
669	return ret;
670}
671
672static int mt6370_isnk_pattern_set(struct led_classdev *lcdev, struct led_pattern *pattern, u32 len,
673				   int repeat)
674{
675	struct mt6370_led *led = container_of(lcdev, struct mt6370_led, isink);
676	struct mt6370_priv *priv = led->priv;
677	unsigned int reg_base;
678	u8 params[P_MAX_PATTERNS / 2];
679	int ret;
680
681	mutex_lock(&priv->lock);
682
683	ret = mt6370_gen_breath_pattern(priv, pattern, len, params, sizeof(params));
684	if (ret)
685		goto out_unlock;
686
687	mt6370_get_breath_reg_base(priv, led->index, &reg_base);
688
689	ret = regmap_raw_write(priv->regmap, reg_base, params, sizeof(params));
690	if (ret)
691		goto out_unlock;
692
693	ret = mt6370_set_led_mode(priv, led->index, MT6370_LED_BREATH_MODE);
694
695out_unlock:
696	mutex_unlock(&priv->lock);
697
698	return ret;
699}
700
701static inline int mt6370_isnk_pattern_clear(struct led_classdev *lcdev)
702{
703	struct mt6370_led *led = container_of(lcdev, struct mt6370_led, isink);
704	struct mt6370_priv *priv = led->priv;
705	int ret;
706
707	mutex_lock(&led->priv->lock);
708	ret = mt6370_set_led_mode(priv, led->index, MT6370_LED_REG_MODE);
709	mutex_unlock(&led->priv->lock);
710
711	return ret;
712}
713
714static int mt6370_assign_multicolor_info(struct device *dev, struct mt6370_led *led,
715					 struct fwnode_handle *fwnode)
716{
717	struct mt6370_priv *priv = led->priv;
718	struct fwnode_handle *child;
719	struct mc_subled *sub_led;
720	u32 num_color = 0;
721	int ret;
722
723	sub_led = devm_kcalloc(dev, MC_CHANNEL_NUM, sizeof(*sub_led), GFP_KERNEL);
724	if (!sub_led)
725		return -ENOMEM;
726
727	fwnode_for_each_child_node(fwnode, child) {
728		u32 reg, color;
729
730		ret = fwnode_property_read_u32(child, "reg", &reg);
731		if (ret || reg > MT6370_LED_ISNK3 || priv->leds_active & BIT(reg)) {
732			fwnode_handle_put(child);
733			return -EINVAL;
734		}
735
736		ret = fwnode_property_read_u32(child, "color", &color);
737		if (ret) {
738			fwnode_handle_put(child);
739			return dev_err_probe(dev, ret, "LED %d, no color specified\n", led->index);
740		}
741
742		priv->leds_active |= BIT(reg);
743		sub_led[num_color].color_index = color;
744		sub_led[num_color].channel = reg;
745		sub_led[num_color].intensity = 0;
746		num_color++;
747	}
748
749	if (num_color < 2)
750		return dev_err_probe(dev, -EINVAL,
751				     "Multicolor must include 2 or more LED channels\n");
752
753	led->mc.num_colors = num_color;
754	led->mc.subled_info = sub_led;
755
756	return 0;
757}
758
759static int mt6370_init_led_properties(struct device *dev, struct mt6370_led *led,
760				      struct led_init_data *init_data)
761{
762	struct mt6370_priv *priv = led->priv;
763	struct led_classdev *lcdev;
764	enum mt6370_led_ranges sel_range;
765	u32 max_uA, max_level;
766	int ret;
767
768	if (led->index == MT6370_VIRTUAL_MULTICOLOR) {
769		ret = mt6370_assign_multicolor_info(dev, led, init_data->fwnode);
770		if (ret)
771			return ret;
772
773		lcdev = &led->mc.led_cdev;
774		lcdev->brightness_set_blocking = mt6370_mc_brightness_set;
775		lcdev->blink_set = mt6370_mc_blink_set;
776		lcdev->pattern_set = mt6370_mc_pattern_set;
777		lcdev->pattern_clear = mt6370_mc_pattern_clear;
778	} else {
779		lcdev = &led->isink;
780		lcdev->brightness_set_blocking = mt6370_isnk_brightness_set;
781		lcdev->blink_set = mt6370_isnk_blink_set;
782		lcdev->pattern_set = mt6370_isnk_pattern_set;
783		lcdev->pattern_clear = mt6370_isnk_pattern_clear;
784	}
785
786	ret = fwnode_property_read_u32(init_data->fwnode, "led-max-microamp", &max_uA);
787	if (ret) {
788		dev_warn(dev, "Not specified led-max-microamp, config to the minimum\n");
789		max_uA = 0;
790	}
791
792	if (led->index == MT6370_LED_ISNK4)
793		sel_range = R_LED4_CURR;
794	else
795		sel_range = R_LED123_CURR;
796
797	linear_range_get_selector_within(priv->ranges + sel_range, max_uA, &max_level);
798
799	lcdev->max_brightness = max_level;
800
801	led->default_state = led_init_default_state_get(init_data->fwnode);
802
803	return 0;
804}
805
806static int mt6370_isnk_init_default_state(struct mt6370_led *led)
807{
808	struct mt6370_priv *priv = led->priv;
809	unsigned int enable, level;
810	int ret;
811
812	ret = mt6370_get_led_brightness(priv, led->index, &level);
813	if (ret)
814		return ret;
815
816	ret = regmap_field_read(priv->fields[F_RGB_EN], &enable);
817	if (ret)
818		return ret;
819
820	if (!(enable & MT6370_CHEN_BIT(led->index)))
821		level = 0;
822
823	switch (led->default_state) {
824	case LEDS_DEFSTATE_ON:
825		led->isink.brightness = led->isink.max_brightness;
826		break;
827	case LEDS_DEFSTATE_KEEP:
828		led->isink.brightness = min(level, led->isink.max_brightness);
829		break;
830	default:
831		led->isink.brightness = 0;
832		break;
833	}
834
835	return mt6370_isnk_brightness_set(&led->isink, led->isink.brightness);
836}
837
838static int mt6370_multicolor_led_register(struct device *dev, struct mt6370_led *led,
839					  struct led_init_data *init_data)
840{
841	int ret;
842
843	ret = mt6370_mc_brightness_set(&led->mc.led_cdev, 0);
844	if (ret)
845		return dev_err_probe(dev, ret, "Couldn't set multicolor brightness\n");
846
847	ret = devm_led_classdev_multicolor_register_ext(dev, &led->mc, init_data);
848	if (ret)
849		return dev_err_probe(dev, ret, "Couldn't register multicolor\n");
850
851	return 0;
852}
853
854static int mt6370_led_register(struct device *dev, struct mt6370_led *led,
855			       struct led_init_data *init_data)
856{
857	struct mt6370_priv *priv = led->priv;
858	int ret;
859
860	if (led->index == MT6370_VIRTUAL_MULTICOLOR)
861		return mt6370_multicolor_led_register(dev, led, init_data);
862
863	/* If ISNK4 is declared, change its mode from HW auto to SW control */
864	if (led->index == MT6370_LED_ISNK4) {
865		ret = regmap_field_write(priv->fields[F_CHGIND_EN], 1);
866		if (ret)
867			return dev_err_probe(dev, ret, "Failed to set CHRIND to SW\n");
868	}
869
870	ret = mt6370_isnk_init_default_state(led);
871	if (ret)
872		return dev_err_probe(dev, ret, "Failed to init %d isnk state\n", led->index);
873
874	ret = devm_led_classdev_register_ext(dev, &led->isink, init_data);
875	if (ret)
876		return dev_err_probe(dev, ret, "Couldn't register isink %d\n", led->index);
877
878	return 0;
879}
880
881static int mt6370_check_vendor_info(struct mt6370_priv *priv)
882{
883	unsigned int devinfo, vid;
884	int ret;
885
886	ret = regmap_read(priv->regmap, MT6370_REG_DEV_INFO, &devinfo);
887	if (ret)
888		return ret;
889
890	vid = FIELD_GET(MT6370_VENDOR_ID_MASK, devinfo);
891	if (vid == MT6372_VENDOR_ID || vid == MT6372C_VENDOR_ID) {
892		priv->reg_fields = mt6372_reg_fields;
893		priv->ranges = mt6372_led_ranges;
894		priv->pdata = &mt6372_pdata;
895	} else {
896		/* Common for MT6370/71 */
897		priv->reg_fields = common_reg_fields;
898		priv->ranges = common_led_ranges;
899		priv->pdata = &common_pdata;
900	}
901
902	return 0;
903}
904
905static int mt6370_leds_probe(struct platform_device *pdev)
906{
907	struct device *dev = &pdev->dev;
908	struct mt6370_priv *priv;
909	struct fwnode_handle *child;
910	size_t count;
911	unsigned int i = 0;
912	int ret;
913
914	count = device_get_child_node_count(dev);
915	if (!count || count > MT6370_MAX_LEDS)
916		return dev_err_probe(dev, -EINVAL,
917				     "No child node or node count over max LED number %zu\n",
918				      count);
919
920	priv = devm_kzalloc(dev, struct_size(priv, leds, count), GFP_KERNEL);
921	if (!priv)
922		return -ENOMEM;
923
924	priv->leds_count = count;
925	mutex_init(&priv->lock);
926
927	priv->regmap = dev_get_regmap(dev->parent, NULL);
928	if (!priv->regmap)
929		return dev_err_probe(dev, -ENODEV, "Failed to get parent regmap\n");
930
931	ret = mt6370_check_vendor_info(priv);
932	if (ret)
933		return dev_err_probe(dev, ret, "Failed to check vendor info\n");
934
935	ret = devm_regmap_field_bulk_alloc(dev, priv->regmap, priv->fields, priv->reg_fields,
936					   F_MAX_FIELDS);
937	if (ret)
938		return dev_err_probe(dev, ret, "Failed to allocate regmap field\n");
939
940	device_for_each_child_node(dev, child) {
941		struct mt6370_led *led = priv->leds + i++;
942		struct led_init_data init_data = { .fwnode = child };
943		u32 reg, color;
944
945		ret = fwnode_property_read_u32(child, "reg", &reg);
946		if (ret) {
947			dev_err(dev, "Failed to parse reg property\n");
948			goto fwnode_release;
949		}
950
951		if (reg >= MT6370_MAX_LEDS) {
952			ret = -EINVAL;
953			dev_err(dev, "Error reg property number\n");
954			goto fwnode_release;
955		}
956
957		ret = fwnode_property_read_u32(child, "color", &color);
958		if (ret) {
959			dev_err(dev, "Failed to parse color property\n");
960			goto fwnode_release;
961		}
962
963		if (color == LED_COLOR_ID_RGB || color == LED_COLOR_ID_MULTI)
964			reg = MT6370_VIRTUAL_MULTICOLOR;
965
966		if (priv->leds_active & BIT(reg)) {
967			ret = -EINVAL;
968			dev_err(dev, "Duplicate reg property\n");
969			goto fwnode_release;
970		}
971
972		priv->leds_active |= BIT(reg);
973
974		led->index = reg;
975		led->priv = priv;
976
977		ret = mt6370_init_led_properties(dev, led, &init_data);
978		if (ret)
979			goto fwnode_release;
980
981		ret = mt6370_led_register(dev, led, &init_data);
982		if (ret)
983			goto fwnode_release;
984	}
985
986	return 0;
987
988fwnode_release:
989	fwnode_handle_put(child);
990	return ret;
991}
992
993static const struct of_device_id mt6370_rgbled_device_table[] = {
994	{ .compatible = "mediatek,mt6370-indicator" },
995	{}
996};
997MODULE_DEVICE_TABLE(of, mt6370_rgbled_device_table);
998
999static struct platform_driver mt6370_rgbled_driver = {
1000	.driver = {
1001		.name = "mt6370-indicator",
1002		.of_match_table = mt6370_rgbled_device_table,
1003	},
1004	.probe = mt6370_leds_probe,
1005};
1006module_platform_driver(mt6370_rgbled_driver);
1007
1008MODULE_AUTHOR("Alice Chen <alice_chen@richtek.com>");
1009MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
1010MODULE_DESCRIPTION("MediaTek MT6370 RGB LED Driver");
1011MODULE_LICENSE("GPL");
1012