Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.14.15.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2024 Christian Marangi <ansuelsmth@gmail.com>
  4 */
  5
  6#include <linux/bitfield.h>
  7#include <linux/cleanup.h>
  8#include <linux/delay.h>
  9#include <linux/firmware.h>
 10#include <linux/i2c.h>
 11#include <linux/iopoll.h>
 12#include <linux/leds.h>
 13#include <linux/module.h>
 14#include <linux/mutex.h>
 15#include <linux/of.h>
 16#include <linux/platform_data/leds-lp55xx.h>
 17#include <linux/slab.h>
 18#include <dt-bindings/leds/leds-lp55xx.h>
 19
 20#include "leds-lp55xx-common.h"
 21
 22#define LP5569_MAX_LEDS			9
 23
 24/* Memory is used like this:
 25 * 0x00 engine 1 program (4 pages)
 26 * 0x40 engine 2 program (4 pages)
 27 * 0x80 engine 3 program (4 pages)
 28 * 0xc0 engine 1 muxing info (1 page)
 29 * 0xd0 engine 2 muxing info (1 page)
 30 * 0xe0 engine 3 muxing info (1 page)
 31 */
 32#define LP5569_PAGES_PER_ENGINE		4
 33
 34#define LP5569_REG_ENABLE		0x00
 35#define   LP5569_ENABLE			BIT(6)
 36
 37#define LP5569_REG_EXEC_CTRL		0x01
 38#define   LP5569_MODE_ENG_SHIFT		2
 39
 40#define LP5569_REG_OP_MODE		0x02
 41#define   LP5569_EXEC_ENG_SHIFT		2
 42
 43#define LP5569_REG_ENABLE_LEDS_MSB	0x04
 44#define LP5569_REG_ENABLE_LEDS_LSB	0x05
 45#define LP5569_REG_LED_CTRL_BASE	0x07
 46#define   LP5569_FADER_MAPPING_MASK	GENMASK(7, 5)
 47#define LP5569_REG_LED_PWM_BASE		0x16
 48#define LP5569_REG_LED_CURRENT_BASE	0x22
 49#define LP5569_REG_MISC			0x2F
 50#define   LP5569_AUTO_INC		BIT(6)
 51#define   LP5569_PWR_SAVE		BIT(5)
 52#define   LP5569_CP_MODE_MASK		GENMASK(4, 3)
 53#define   LP5569_PWM_PWR_SAVE		BIT(2)
 54#define   LP5569_INTERNAL_CLK		BIT(0)
 55#define LP5569_REG_MISC2		0x33
 56#define   LP5569_LED_SHORT_TEST		BIT(4)
 57#define   LP5569_LED_OPEN_TEST		BIT(3)
 58#define LP5569_REG_STATUS		0x3C
 59#define   LP5569_MASK_BUSY		BIT(7)
 60#define   LP5569_STARTUP_BUSY		BIT(6)
 61#define   LP5569_ENGINE_BUSY		BIT(5)
 62#define   LP5569_ENGINE1_INT		BIT(2)
 63#define   LP5569_ENGINE2_INT		BIT(1)
 64#define   LP5569_ENGINE3_INT		BIT(0)
 65#define   LP5569_ENG_STATUS_MASK	(LP5569_ENGINE1_INT | LP5569_ENGINE2_INT | \
 66					 LP5569_ENGINE3_INT)
 67#define LP5569_REG_IO_CONTROL		0x3D
 68#define   LP5569_CLK_OUTPUT		BIT(3)
 69#define LP5569_REG_RESET		0x3F
 70#define   LP5569_RESET			0xFF
 71#define LP5569_REG_MASTER_FADER_BASE	0x46
 72#define LP5569_REG_CH1_PROG_START	0x4B
 73#define LP5569_REG_CH2_PROG_START	0x4C
 74#define LP5569_REG_CH3_PROG_START	0x4D
 75#define LP5569_REG_PROG_PAGE_SEL	0x4F
 76#define LP5569_REG_PROG_MEM		0x50
 77#define LP5569_REG_LED_FAULT1		0x81
 78#define   LP5569_LED_FAULT8		BIT(0)
 79#define LP5569_REG_LED_FAULT2		0x82
 80#define   LP5569_LED_FAULT7		BIT(7)
 81#define   LP5569_LED_FAULT6		BIT(6)
 82#define   LP5569_LED_FAULT5		BIT(5)
 83#define   LP5569_LED_FAULT4		BIT(4)
 84#define   LP5569_LED_FAULT3		BIT(3)
 85#define   LP5569_LED_FAULT2		BIT(2)
 86#define   LP5569_LED_FAULT1		BIT(1)
 87#define   LP5569_LED_FAULT0		BIT(0)
 88
 89#define LP5569_ENG1_PROG_ADDR		0x0
 90#define LP5569_ENG2_PROG_ADDR		0x40
 91#define LP5569_ENG3_PROG_ADDR		0x80
 92#define LP5569_ENG1_MUX_ADDR		0xc0
 93#define LP5569_ENG2_MUX_ADDR		0xd0
 94#define LP5569_ENG3_MUX_ADDR		0xe0
 95
 96#define LP5569_STARTUP_SLEEP		500
 97
 98#define LEDn_STATUS_FAULT(n, status)	((status) >> (n) & BIT(0))
 99
100#define LP5569_DEFAULT_CONFIG \
101	(LP5569_AUTO_INC | LP5569_PWR_SAVE | LP5569_PWM_PWR_SAVE)
102
103static void lp5569_run_engine(struct lp55xx_chip *chip, bool start)
104{
105	if (!start) {
106		lp55xx_stop_engine(chip);
107		lp55xx_turn_off_channels(chip);
108		return;
109	}
110
111	lp55xx_run_engine_common(chip);
112}
113
114static int lp5569_init_program_engine(struct lp55xx_chip *chip)
115{
116	int i;
117	int j;
118	int ret;
119	u8 status;
120	/* Precompiled pattern per ENGINE setting LED MUX start and stop addresses */
121	static const u8 pattern[][LP55xx_BYTES_PER_PAGE] =  {
122		{ 0x9c, LP5569_ENG1_MUX_ADDR, 0x9c, 0xb0, 0x9d, 0x80, 0xd8, 0x00, 0},
123		{ 0x9c, LP5569_ENG2_MUX_ADDR, 0x9c, 0xc0, 0x9d, 0x80, 0xd8, 0x00, 0},
124		{ 0x9c, LP5569_ENG3_MUX_ADDR, 0x9c, 0xd0, 0x9d, 0x80, 0xd8, 0x00, 0},
125	};
126
127	/* Setup each ENGINE program start address */
128	ret = lp55xx_write(chip, LP5569_REG_CH1_PROG_START, LP5569_ENG1_PROG_ADDR);
129	if (ret)
130		return ret;
131
132	ret = lp55xx_write(chip, LP5569_REG_CH2_PROG_START, LP5569_ENG2_PROG_ADDR);
133	if (ret)
134		return ret;
135
136	ret = lp55xx_write(chip, LP5569_REG_CH3_PROG_START, LP5569_ENG3_PROG_ADDR);
137	if (ret)
138		return ret;
139
140	/* Write precompiled pattern for LED MUX address space for each ENGINE */
141	for (i = LP55XX_ENGINE_1; i <= LP55XX_ENGINE_3; i++) {
142		chip->engine_idx = i;
143		lp55xx_load_engine(chip);
144
145		for (j = 0; j < LP55xx_BYTES_PER_PAGE; j++) {
146			ret = lp55xx_write(chip, LP5569_REG_PROG_MEM + j,
147					   pattern[i - 1][j]);
148			if (ret)
149				goto out;
150		}
151	}
152
153	lp5569_run_engine(chip, true);
154
155	/* Let the programs run for couple of ms and check the engine status */
156	usleep_range(3000, 6000);
157	lp55xx_read(chip, LP5569_REG_STATUS, &status);
158	status = FIELD_GET(LP5569_ENG_STATUS_MASK, status);
159
160	if (status != LP5569_ENG_STATUS_MASK) {
161		dev_err(&chip->cl->dev,
162			"could not configure LED engine, status = 0x%.2x\n",
163			status);
164		ret = -EINVAL;
165	}
166
167out:
168	lp55xx_stop_all_engine(chip);
169	return ret;
170}
171
172static int lp5569_post_init_device(struct lp55xx_chip *chip)
173{
174	int ret;
175	u8 val;
176
177	val = LP5569_DEFAULT_CONFIG;
178	val |= FIELD_PREP(LP5569_CP_MODE_MASK, chip->pdata->charge_pump_mode);
179	ret = lp55xx_write(chip, LP5569_REG_MISC, val);
180	if (ret)
181		return ret;
182
183	if (chip->pdata->clock_mode == LP55XX_CLOCK_INT) {
184		/* Internal clock MUST be configured before CLK output */
185		ret = lp55xx_update_bits(chip, LP5569_REG_MISC,
186					 LP5569_INTERNAL_CLK,
187					 LP5569_INTERNAL_CLK);
188		if (ret)
189			return ret;
190
191		ret = lp55xx_update_bits(chip, LP5569_REG_IO_CONTROL,
192					 LP5569_CLK_OUTPUT,
193					 LP5569_CLK_OUTPUT);
194		if (ret)
195			return ret;
196	}
197
198	ret = lp55xx_write(chip, LP5569_REG_ENABLE, LP5569_ENABLE);
199	if (ret)
200		return ret;
201
202	read_poll_timeout(lp55xx_read, ret, !(val & LP5569_STARTUP_BUSY),
203			  LP5569_STARTUP_SLEEP, LP5569_STARTUP_SLEEP * 10, false,
204			  chip, LP5569_REG_STATUS, &val);
205
206	return lp5569_init_program_engine(chip);
207}
208
209static ssize_t lp5569_led_open_test(struct lp55xx_led *led, char *buf)
210{
211	struct lp55xx_chip *chip = led->chip;
212	struct lp55xx_platform_data *pdata = chip->pdata;
213	bool leds_fault[LP5569_MAX_LEDS];
214	struct lp55xx_led *led_tmp = led;
215	int i, ret, pos = 0;
216	u8 status;
217
218	/* Set in STANDBY state */
219	ret = lp55xx_write(chip, LP5569_REG_ENABLE, 0);
220	if (ret)
221		goto exit;
222
223	/* Wait 1ms for device to enter STANDBY state */
224	usleep_range(1000, 2000);
225
226	/* Set Charge Pump to 1.5x */
227	ret = lp55xx_update_bits(chip, LP5569_REG_MISC,
228				 FIELD_PREP(LP5569_CP_MODE_MASK, LP55XX_CP_BOOST),
229				 LP5569_CP_MODE_MASK);
230	if (ret)
231		goto exit;
232
233	/* Enable LED Open Test */
234	ret = lp55xx_update_bits(chip, LP5569_REG_MISC2, LP5569_LED_OPEN_TEST,
235				 LP5569_LED_OPEN_TEST);
236	if (ret)
237		goto exit;
238
239	/* Put Device in NORMAL state */
240	ret = lp55xx_write(chip, LP5569_REG_ENABLE, LP5569_ENABLE);
241	if (ret)
242		goto exit;
243
244	/* Wait 500 us for device to enter NORMAL state */
245	usleep_range(500, 750);
246
247	/* Enable LED and set to 100% brightness */
248	for (i = 0; i < pdata->num_channels; i++) {
249		ret = lp55xx_write(chip, LP5569_REG_LED_PWM_BASE + led_tmp->chan_nr,
250				   LED_FULL);
251		if (ret)
252			goto exit;
253
254		led_tmp++;
255	}
256
257	/* Wait 500 us for device to fill status regs */
258	usleep_range(500, 750);
259
260	/* Parse status led fault 1 regs */
261	ret = lp55xx_read(chip, LP5569_REG_LED_FAULT1, &status);
262	if (ret < 0)
263		goto exit;
264
265	for (i = 0; i < 8; i++)
266		leds_fault[i] = !!((status >> i) & 0x1);
267
268	/* Parse status led fault 2 regs */
269	ret = lp55xx_read(chip, LP5569_REG_LED_FAULT2, &status);
270	if (ret < 0)
271		goto exit;
272
273	for (i = 0; i < 1; i++)
274		leds_fault[i + 8] = !!((status >> i) & 0x1);
275
276	/* Report LED fault */
277	led_tmp = led;
278	for (i = 0; i < pdata->num_channels; i++) {
279		if (leds_fault[led_tmp->chan_nr])
280			pos += sysfs_emit_at(buf, pos, "LED %d OPEN FAIL\n",
281					     led_tmp->chan_nr);
282
283		led_tmp++;
284	}
285
286	ret = pos;
287
288exit:
289	/* Disable LED Open Test */
290	lp55xx_update_bits(chip, LP5569_REG_MISC2, LP5569_LED_OPEN_TEST, 0);
291
292	led_tmp = led;
293	for (i = 0; i < pdata->num_channels; i++) {
294		lp55xx_write(chip, LP5569_REG_LED_PWM_BASE + led_tmp->chan_nr, 0);
295
296		led_tmp++;
297	}
298
299	return ret;
300}
301
302static ssize_t lp5569_led_short_test(struct lp55xx_led *led, char *buf)
303{
304	struct lp55xx_chip *chip = led->chip;
305	struct lp55xx_platform_data *pdata = chip->pdata;
306	bool leds_fault[LP5569_MAX_LEDS];
307	struct lp55xx_led *led_tmp = led;
308	int i, ret, pos = 0;
309	u8 status;
310
311	/* Set in STANDBY state */
312	ret = lp55xx_write(chip, LP5569_REG_ENABLE, 0);
313	if (ret)
314		goto exit;
315
316	/* Wait 1ms for device to enter STANDBY state */
317	usleep_range(1000, 2000);
318
319	/* Set Charge Pump to 1x */
320	ret = lp55xx_update_bits(chip, LP5569_REG_MISC,
321				 FIELD_PREP(LP5569_CP_MODE_MASK, LP55XX_CP_BYPASS),
322				 LP5569_CP_MODE_MASK);
323	if (ret)
324		goto exit;
325
326	/* Enable LED and set to 100% brightness and current to 100% (25.5mA) */
327	for (i = 0; i < pdata->num_channels; i++) {
328		ret = lp55xx_write(chip, LP5569_REG_LED_PWM_BASE + led_tmp->chan_nr,
329				   LED_FULL);
330		if (ret)
331			goto exit;
332
333		ret = lp55xx_write(chip, LP5569_REG_LED_CURRENT_BASE + led_tmp->chan_nr,
334				   LED_FULL);
335		if (ret)
336			goto exit;
337
338		led_tmp++;
339	}
340
341	/* Put Device in NORMAL state */
342	ret = lp55xx_write(chip, LP5569_REG_ENABLE, LP5569_ENABLE);
343	if (ret)
344		goto exit;
345
346	/* Wait 500 us for device to enter NORMAL state */
347	usleep_range(500, 750);
348
349	/* Enable LED Shorted Test */
350	ret = lp55xx_update_bits(chip, LP5569_REG_MISC2, LP5569_LED_OPEN_TEST,
351				 LP5569_LED_SHORT_TEST);
352	if (ret)
353		goto exit;
354
355	/* Wait 500 us for device to fill status regs */
356	usleep_range(500, 750);
357
358	/* Parse status led fault 1 regs */
359	ret = lp55xx_read(chip, LP5569_REG_LED_FAULT1, &status);
360	if (ret < 0)
361		goto exit;
362
363	for (i = 0; i < 8; i++)
364		leds_fault[i] = !!LEDn_STATUS_FAULT(i, status);
365
366	/* Parse status led fault 2 regs */
367	ret = lp55xx_read(chip, LP5569_REG_LED_FAULT2, &status);
368	if (ret < 0)
369		goto exit;
370
371	for (i = 0; i < 1; i++)
372		leds_fault[i + 8] = !!LEDn_STATUS_FAULT(i, status);
373
374	/* Report LED fault */
375	led_tmp = led;
376	for (i = 0; i < pdata->num_channels; i++) {
377		if (leds_fault[led_tmp->chan_nr])
378			pos += sysfs_emit_at(buf, pos, "LED %d SHORTED FAIL\n",
379					     led_tmp->chan_nr);
380
381		led_tmp++;
382	}
383
384	ret = pos;
385
386exit:
387	/* Disable LED Shorted Test */
388	lp55xx_update_bits(chip, LP5569_REG_MISC2, LP5569_LED_SHORT_TEST, 0);
389
390	led_tmp = led;
391	for (i = 0; i < pdata->num_channels; i++) {
392		lp55xx_write(chip, LP5569_REG_LED_PWM_BASE + led_tmp->chan_nr, 0);
393
394		led_tmp++;
395	}
396
397	return ret;
398}
399
400static ssize_t lp5569_selftest(struct device *dev,
401			       struct device_attribute *attr,
402			       char *buf)
403{
404	struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
405	struct lp55xx_chip *chip = led->chip;
406	int i, pos = 0;
407
408	guard(mutex)(&chip->lock);
409
410	/* Test LED Open */
411	pos = lp5569_led_open_test(led, buf);
412	if (pos < 0)
413		return sprintf(buf, "FAIL\n");
414
415	/* Test LED Shorted */
416	pos += lp5569_led_short_test(led, buf);
417	if (pos < 0)
418		return sprintf(buf, "FAIL\n");
419
420	for (i = 0; i < chip->pdata->num_channels; i++) {
421		/* Restore current */
422		lp55xx_write(chip, LP5569_REG_LED_CURRENT_BASE + led->chan_nr,
423			     led->led_current);
424
425		/* Restore brightness */
426		lp55xx_write(chip, LP5569_REG_LED_PWM_BASE + led->chan_nr,
427			     led->brightness);
428		led++;
429	}
430
431	return pos == 0 ? sysfs_emit(buf, "OK\n") : pos;
432}
433
434LP55XX_DEV_ATTR_ENGINE_MODE(1);
435LP55XX_DEV_ATTR_ENGINE_MODE(2);
436LP55XX_DEV_ATTR_ENGINE_MODE(3);
437LP55XX_DEV_ATTR_ENGINE_LEDS(1);
438LP55XX_DEV_ATTR_ENGINE_LEDS(2);
439LP55XX_DEV_ATTR_ENGINE_LEDS(3);
440LP55XX_DEV_ATTR_ENGINE_LOAD(1);
441LP55XX_DEV_ATTR_ENGINE_LOAD(2);
442LP55XX_DEV_ATTR_ENGINE_LOAD(3);
443static LP55XX_DEV_ATTR_RO(selftest, lp5569_selftest);
444LP55XX_DEV_ATTR_MASTER_FADER(1);
445LP55XX_DEV_ATTR_MASTER_FADER(2);
446LP55XX_DEV_ATTR_MASTER_FADER(3);
447static LP55XX_DEV_ATTR_RW(master_fader_leds, lp55xx_show_master_fader_leds,
448			  lp55xx_store_master_fader_leds);
449
450static struct attribute *lp5569_attributes[] = {
451	&dev_attr_engine1_mode.attr,
452	&dev_attr_engine2_mode.attr,
453	&dev_attr_engine3_mode.attr,
454	&dev_attr_engine1_load.attr,
455	&dev_attr_engine2_load.attr,
456	&dev_attr_engine3_load.attr,
457	&dev_attr_engine1_leds.attr,
458	&dev_attr_engine2_leds.attr,
459	&dev_attr_engine3_leds.attr,
460	&dev_attr_selftest.attr,
461	&dev_attr_master_fader1.attr,
462	&dev_attr_master_fader2.attr,
463	&dev_attr_master_fader3.attr,
464	&dev_attr_master_fader_leds.attr,
465	NULL,
466};
467
468static const struct attribute_group lp5569_group = {
469	.attrs = lp5569_attributes,
470};
471
472/* Chip specific configurations */
473static struct lp55xx_device_config lp5569_cfg = {
474	.reg_op_mode = {
475		.addr = LP5569_REG_OP_MODE,
476		.shift = LP5569_MODE_ENG_SHIFT,
477	},
478	.reg_exec = {
479		.addr = LP5569_REG_EXEC_CTRL,
480		.shift = LP5569_EXEC_ENG_SHIFT,
481	},
482	.reset = {
483		.addr = LP5569_REG_RESET,
484		.val  = LP5569_RESET,
485	},
486	.enable = {
487		.addr = LP5569_REG_ENABLE,
488		.val  = LP5569_ENABLE,
489	},
490	.prog_mem_base = {
491		.addr = LP5569_REG_PROG_MEM,
492	},
493	.reg_led_pwm_base = {
494		.addr = LP5569_REG_LED_PWM_BASE,
495	},
496	.reg_led_current_base = {
497		.addr = LP5569_REG_LED_CURRENT_BASE,
498	},
499	.reg_master_fader_base = {
500		.addr = LP5569_REG_MASTER_FADER_BASE,
501	},
502	.reg_led_ctrl_base = {
503		.addr = LP5569_REG_LED_CTRL_BASE,
504	},
505	.pages_per_engine   = LP5569_PAGES_PER_ENGINE,
506	.max_channel  = LP5569_MAX_LEDS,
507	.post_init_device   = lp5569_post_init_device,
508	.brightness_fn      = lp55xx_led_brightness,
509	.multicolor_brightness_fn = lp55xx_multicolor_brightness,
510	.set_led_current    = lp55xx_set_led_current,
511	.firmware_cb        = lp55xx_firmware_loaded_cb,
512	.run_engine         = lp5569_run_engine,
513	.dev_attr_group     = &lp5569_group,
514};
515
516static const struct i2c_device_id lp5569_id[] = {
517	{ "lp5569",  .driver_data = (kernel_ulong_t)&lp5569_cfg, },
518	{ }
519};
520
521MODULE_DEVICE_TABLE(i2c, lp5569_id);
522
523static const struct of_device_id of_lp5569_leds_match[] = {
524	{ .compatible = "ti,lp5569", .data = &lp5569_cfg, },
525	{},
526};
527
528MODULE_DEVICE_TABLE(of, of_lp5569_leds_match);
529
530static struct i2c_driver lp5569_driver = {
531	.driver = {
532		.name	= "lp5569",
533		.of_match_table = of_lp5569_leds_match,
534	},
535	.probe		= lp55xx_probe,
536	.remove		= lp55xx_remove,
537	.id_table	= lp5569_id,
538};
539
540module_i2c_driver(lp5569_driver);
541
542MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
543MODULE_DESCRIPTION("LP5569 LED engine");
544MODULE_LICENSE("GPL");