drm/tests: hdmi: Fix memory leaks in drm_display_mode_from_cea_vic()
[drm/drm-misc.git] / drivers / leds / leds-lp5569.c
blob786f2aa35319e3de3232a94ea4857ab0bd15e77a
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2024 Christian Marangi <ansuelsmth@gmail.com>
4 */
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>
20 #include "leds-lp55xx-common.h"
22 #define LP5569_MAX_LEDS 9
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)
32 #define LP5569_PAGES_PER_ENGINE 4
34 #define LP5569_REG_ENABLE 0x00
35 #define LP5569_ENABLE BIT(6)
37 #define LP5569_REG_EXEC_CTRL 0x01
38 #define LP5569_MODE_ENG_SHIFT 2
40 #define LP5569_REG_OP_MODE 0x02
41 #define LP5569_EXEC_ENG_SHIFT 2
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)
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
96 #define LP5569_STARTUP_SLEEP 500
98 #define LEDn_STATUS_FAULT(n, status) ((status) >> (n) & BIT(0))
100 #define LP5569_DEFAULT_CONFIG \
101 (LP5569_AUTO_INC | LP5569_PWR_SAVE | LP5569_PWM_PWR_SAVE)
103 static void lp5569_run_engine(struct lp55xx_chip *chip, bool start)
105 if (!start) {
106 lp55xx_stop_engine(chip);
107 lp55xx_turn_off_channels(chip);
108 return;
111 lp55xx_run_engine_common(chip);
114 static int lp5569_init_program_engine(struct lp55xx_chip *chip)
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},
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;
132 ret = lp55xx_write(chip, LP5569_REG_CH2_PROG_START, LP5569_ENG2_PROG_ADDR);
133 if (ret)
134 return ret;
136 ret = lp55xx_write(chip, LP5569_REG_CH3_PROG_START, LP5569_ENG3_PROG_ADDR);
137 if (ret)
138 return ret;
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);
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;
153 lp5569_run_engine(chip, true);
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);
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;
167 out:
168 lp55xx_stop_all_engine(chip);
169 return ret;
172 static int lp5569_post_init_device(struct lp55xx_chip *chip)
174 int ret;
175 u8 val;
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;
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;
191 ret = lp55xx_update_bits(chip, LP5569_REG_IO_CONTROL,
192 LP5569_CLK_OUTPUT,
193 LP5569_CLK_OUTPUT);
194 if (ret)
195 return ret;
198 ret = lp55xx_write(chip, LP5569_REG_ENABLE, LP5569_ENABLE);
199 if (ret)
200 return ret;
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);
206 return lp5569_init_program_engine(chip);
209 static ssize_t lp5569_led_open_test(struct lp55xx_led *led, char *buf)
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;
218 /* Set in STANDBY state */
219 ret = lp55xx_write(chip, LP5569_REG_ENABLE, 0);
220 if (ret)
221 goto exit;
223 /* Wait 1ms for device to enter STANDBY state */
224 usleep_range(1000, 2000);
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;
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;
239 /* Put Device in NORMAL state */
240 ret = lp55xx_write(chip, LP5569_REG_ENABLE, LP5569_ENABLE);
241 if (ret)
242 goto exit;
244 /* Wait 500 us for device to enter NORMAL state */
245 usleep_range(500, 750);
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;
254 led_tmp++;
257 /* Wait 500 us for device to fill status regs */
258 usleep_range(500, 750);
260 /* Parse status led fault 1 regs */
261 ret = lp55xx_read(chip, LP5569_REG_LED_FAULT1, &status);
262 if (ret < 0)
263 goto exit;
265 for (i = 0; i < 8; i++)
266 leds_fault[i] = !!((status >> i) & 0x1);
268 /* Parse status led fault 2 regs */
269 ret = lp55xx_read(chip, LP5569_REG_LED_FAULT2, &status);
270 if (ret < 0)
271 goto exit;
273 for (i = 0; i < 1; i++)
274 leds_fault[i + 8] = !!((status >> i) & 0x1);
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);
283 led_tmp++;
286 ret = pos;
288 exit:
289 /* Disable LED Open Test */
290 lp55xx_update_bits(chip, LP5569_REG_MISC2, LP5569_LED_OPEN_TEST, 0);
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);
296 led_tmp++;
299 return ret;
302 static ssize_t lp5569_led_short_test(struct lp55xx_led *led, char *buf)
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;
311 /* Set in STANDBY state */
312 ret = lp55xx_write(chip, LP5569_REG_ENABLE, 0);
313 if (ret)
314 goto exit;
316 /* Wait 1ms for device to enter STANDBY state */
317 usleep_range(1000, 2000);
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;
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;
333 ret = lp55xx_write(chip, LP5569_REG_LED_CURRENT_BASE + led_tmp->chan_nr,
334 LED_FULL);
335 if (ret)
336 goto exit;
338 led_tmp++;
341 /* Put Device in NORMAL state */
342 ret = lp55xx_write(chip, LP5569_REG_ENABLE, LP5569_ENABLE);
343 if (ret)
344 goto exit;
346 /* Wait 500 us for device to enter NORMAL state */
347 usleep_range(500, 750);
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;
355 /* Wait 500 us for device to fill status regs */
356 usleep_range(500, 750);
358 /* Parse status led fault 1 regs */
359 ret = lp55xx_read(chip, LP5569_REG_LED_FAULT1, &status);
360 if (ret < 0)
361 goto exit;
363 for (i = 0; i < 8; i++)
364 leds_fault[i] = !!LEDn_STATUS_FAULT(i, status);
366 /* Parse status led fault 2 regs */
367 ret = lp55xx_read(chip, LP5569_REG_LED_FAULT2, &status);
368 if (ret < 0)
369 goto exit;
371 for (i = 0; i < 1; i++)
372 leds_fault[i + 8] = !!LEDn_STATUS_FAULT(i, status);
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);
381 led_tmp++;
384 ret = pos;
386 exit:
387 /* Disable LED Shorted Test */
388 lp55xx_update_bits(chip, LP5569_REG_MISC2, LP5569_LED_SHORT_TEST, 0);
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);
394 led_tmp++;
397 return ret;
400 static ssize_t lp5569_selftest(struct device *dev,
401 struct device_attribute *attr,
402 char *buf)
404 struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
405 struct lp55xx_chip *chip = led->chip;
406 int i, pos = 0;
408 guard(mutex)(&chip->lock);
410 /* Test LED Open */
411 pos = lp5569_led_open_test(led, buf);
412 if (pos < 0)
413 return sprintf(buf, "FAIL\n");
415 /* Test LED Shorted */
416 pos += lp5569_led_short_test(led, buf);
417 if (pos < 0)
418 return sprintf(buf, "FAIL\n");
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);
425 /* Restore brightness */
426 lp55xx_write(chip, LP5569_REG_LED_PWM_BASE + led->chan_nr,
427 led->brightness);
428 led++;
431 return pos == 0 ? sysfs_emit(buf, "OK\n") : pos;
434 LP55XX_DEV_ATTR_ENGINE_MODE(1);
435 LP55XX_DEV_ATTR_ENGINE_MODE(2);
436 LP55XX_DEV_ATTR_ENGINE_MODE(3);
437 LP55XX_DEV_ATTR_ENGINE_LEDS(1);
438 LP55XX_DEV_ATTR_ENGINE_LEDS(2);
439 LP55XX_DEV_ATTR_ENGINE_LEDS(3);
440 LP55XX_DEV_ATTR_ENGINE_LOAD(1);
441 LP55XX_DEV_ATTR_ENGINE_LOAD(2);
442 LP55XX_DEV_ATTR_ENGINE_LOAD(3);
443 static LP55XX_DEV_ATTR_RO(selftest, lp5569_selftest);
444 LP55XX_DEV_ATTR_MASTER_FADER(1);
445 LP55XX_DEV_ATTR_MASTER_FADER(2);
446 LP55XX_DEV_ATTR_MASTER_FADER(3);
447 static LP55XX_DEV_ATTR_RW(master_fader_leds, lp55xx_show_master_fader_leds,
448 lp55xx_store_master_fader_leds);
450 static 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,
468 static const struct attribute_group lp5569_group = {
469 .attrs = lp5569_attributes,
472 /* Chip specific configurations */
473 static struct lp55xx_device_config lp5569_cfg = {
474 .reg_op_mode = {
475 .addr = LP5569_REG_OP_MODE,
476 .shift = LP5569_MODE_ENG_SHIFT,
478 .reg_exec = {
479 .addr = LP5569_REG_EXEC_CTRL,
480 .shift = LP5569_EXEC_ENG_SHIFT,
482 .reset = {
483 .addr = LP5569_REG_RESET,
484 .val = LP5569_RESET,
486 .enable = {
487 .addr = LP5569_REG_ENABLE,
488 .val = LP5569_ENABLE,
490 .prog_mem_base = {
491 .addr = LP5569_REG_PROG_MEM,
493 .reg_led_pwm_base = {
494 .addr = LP5569_REG_LED_PWM_BASE,
496 .reg_led_current_base = {
497 .addr = LP5569_REG_LED_CURRENT_BASE,
499 .reg_master_fader_base = {
500 .addr = LP5569_REG_MASTER_FADER_BASE,
502 .reg_led_ctrl_base = {
503 .addr = LP5569_REG_LED_CTRL_BASE,
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,
516 static const struct i2c_device_id lp5569_id[] = {
517 { "lp5569", .driver_data = (kernel_ulong_t)&lp5569_cfg, },
521 MODULE_DEVICE_TABLE(i2c, lp5569_id);
523 static const struct of_device_id of_lp5569_leds_match[] = {
524 { .compatible = "ti,lp5569", .data = &lp5569_cfg, },
528 MODULE_DEVICE_TABLE(of, of_lp5569_leds_match);
530 static struct i2c_driver lp5569_driver = {
531 .driver = {
532 .name = "lp5569",
533 .of_match_table = of_lp5569_leds_match,
535 .probe = lp55xx_probe,
536 .remove = lp55xx_remove,
537 .id_table = lp5569_id,
540 module_i2c_driver(lp5569_driver);
542 MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
543 MODULE_DESCRIPTION("LP5569 LED engine");
544 MODULE_LICENSE("GPL");