1/* 2 * LP5562 LED driver 3 * 4 * Copyright (C) 2013 Texas Instruments 5 * 6 * Author: Milo(Woogyom) Kim <milo.kim@ti.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13#include <linux/delay.h> 14#include <linux/firmware.h> 15#include <linux/i2c.h> 16#include <linux/leds.h> 17#include <linux/module.h> 18#include <linux/mutex.h> 19#include <linux/of.h> 20#include <linux/platform_data/leds-lp55xx.h> 21#include <linux/slab.h> 22 23#include "leds-lp55xx-common.h" 24 25#define LP5562_PROGRAM_LENGTH 32 26#define LP5562_MAX_LEDS 4 27 28/* ENABLE Register 00h */ 29#define LP5562_REG_ENABLE 0x00 30#define LP5562_EXEC_ENG1_M 0x30 31#define LP5562_EXEC_ENG2_M 0x0C 32#define LP5562_EXEC_ENG3_M 0x03 33#define LP5562_EXEC_M 0x3F 34#define LP5562_MASTER_ENABLE 0x40 /* Chip master enable */ 35#define LP5562_LOGARITHMIC_PWM 0x80 /* Logarithmic PWM adjustment */ 36#define LP5562_EXEC_RUN 0x2A 37#define LP5562_ENABLE_DEFAULT \ 38 (LP5562_MASTER_ENABLE | LP5562_LOGARITHMIC_PWM) 39#define LP5562_ENABLE_RUN_PROGRAM \ 40 (LP5562_ENABLE_DEFAULT | LP5562_EXEC_RUN) 41 42/* OPMODE Register 01h */ 43#define LP5562_REG_OP_MODE 0x01 44#define LP5562_MODE_ENG1_M 0x30 45#define LP5562_MODE_ENG2_M 0x0C 46#define LP5562_MODE_ENG3_M 0x03 47#define LP5562_LOAD_ENG1 0x10 48#define LP5562_LOAD_ENG2 0x04 49#define LP5562_LOAD_ENG3 0x01 50#define LP5562_RUN_ENG1 0x20 51#define LP5562_RUN_ENG2 0x08 52#define LP5562_RUN_ENG3 0x02 53#define LP5562_ENG1_IS_LOADING(mode) \ 54 ((mode & LP5562_MODE_ENG1_M) == LP5562_LOAD_ENG1) 55#define LP5562_ENG2_IS_LOADING(mode) \ 56 ((mode & LP5562_MODE_ENG2_M) == LP5562_LOAD_ENG2) 57#define LP5562_ENG3_IS_LOADING(mode) \ 58 ((mode & LP5562_MODE_ENG3_M) == LP5562_LOAD_ENG3) 59 60/* BRIGHTNESS Registers */ 61#define LP5562_REG_R_PWM 0x04 62#define LP5562_REG_G_PWM 0x03 63#define LP5562_REG_B_PWM 0x02 64#define LP5562_REG_W_PWM 0x0E 65 66/* CURRENT Registers */ 67#define LP5562_REG_R_CURRENT 0x07 68#define LP5562_REG_G_CURRENT 0x06 69#define LP5562_REG_B_CURRENT 0x05 70#define LP5562_REG_W_CURRENT 0x0F 71 72/* CONFIG Register 08h */ 73#define LP5562_REG_CONFIG 0x08 74#define LP5562_PWM_HF 0x40 75#define LP5562_PWRSAVE_EN 0x20 76#define LP5562_CLK_INT 0x01 /* Internal clock */ 77#define LP5562_DEFAULT_CFG (LP5562_PWM_HF | LP5562_PWRSAVE_EN) 78 79/* RESET Register 0Dh */ 80#define LP5562_REG_RESET 0x0D 81#define LP5562_RESET 0xFF 82 83/* PROGRAM ENGINE Registers */ 84#define LP5562_REG_PROG_MEM_ENG1 0x10 85#define LP5562_REG_PROG_MEM_ENG2 0x30 86#define LP5562_REG_PROG_MEM_ENG3 0x50 87 88/* LEDMAP Register 70h */ 89#define LP5562_REG_ENG_SEL 0x70 90#define LP5562_ENG_SEL_PWM 0 91#define LP5562_ENG_FOR_RGB_M 0x3F 92#define LP5562_ENG_SEL_RGB 0x1B /* R:ENG1, G:ENG2, B:ENG3 */ 93#define LP5562_ENG_FOR_W_M 0xC0 94#define LP5562_ENG1_FOR_W 0x40 /* W:ENG1 */ 95#define LP5562_ENG2_FOR_W 0x80 /* W:ENG2 */ 96#define LP5562_ENG3_FOR_W 0xC0 /* W:ENG3 */ 97 98/* Program Commands */ 99#define LP5562_CMD_DISABLE 0x00 100#define LP5562_CMD_LOAD 0x15 101#define LP5562_CMD_RUN 0x2A 102#define LP5562_CMD_DIRECT 0x3F 103#define LP5562_PATTERN_OFF 0 104 105static inline void lp5562_wait_opmode_done(void) 106{ 107 /* operation mode change needs to be longer than 153 us */ 108 usleep_range(200, 300); 109} 110 111static inline void lp5562_wait_enable_done(void) 112{ 113 /* it takes more 488 us to update ENABLE register */ 114 usleep_range(500, 600); 115} 116 117static void lp5562_set_led_current(struct lp55xx_led *led, u8 led_current) 118{ 119 u8 addr[] = { 120 LP5562_REG_R_CURRENT, 121 LP5562_REG_G_CURRENT, 122 LP5562_REG_B_CURRENT, 123 LP5562_REG_W_CURRENT, 124 }; 125 126 led->led_current = led_current; 127 lp55xx_write(led->chip, addr[led->chan_nr], led_current); 128} 129 130static void lp5562_load_engine(struct lp55xx_chip *chip) 131{ 132 enum lp55xx_engine_index idx = chip->engine_idx; 133 u8 mask[] = { 134 [LP55XX_ENGINE_1] = LP5562_MODE_ENG1_M, 135 [LP55XX_ENGINE_2] = LP5562_MODE_ENG2_M, 136 [LP55XX_ENGINE_3] = LP5562_MODE_ENG3_M, 137 }; 138 139 u8 val[] = { 140 [LP55XX_ENGINE_1] = LP5562_LOAD_ENG1, 141 [LP55XX_ENGINE_2] = LP5562_LOAD_ENG2, 142 [LP55XX_ENGINE_3] = LP5562_LOAD_ENG3, 143 }; 144 145 lp55xx_update_bits(chip, LP5562_REG_OP_MODE, mask[idx], val[idx]); 146 147 lp5562_wait_opmode_done(); 148} 149 150static void lp5562_stop_engine(struct lp55xx_chip *chip) 151{ 152 lp55xx_write(chip, LP5562_REG_OP_MODE, LP5562_CMD_DISABLE); 153 lp5562_wait_opmode_done(); 154} 155 156static void lp5562_run_engine(struct lp55xx_chip *chip, bool start) 157{ 158 int ret; 159 u8 mode; 160 u8 exec; 161 162 /* stop engine */ 163 if (!start) { 164 lp55xx_write(chip, LP5562_REG_ENABLE, LP5562_ENABLE_DEFAULT); 165 lp5562_wait_enable_done(); 166 lp5562_stop_engine(chip); 167 lp55xx_write(chip, LP5562_REG_ENG_SEL, LP5562_ENG_SEL_PWM); 168 lp55xx_write(chip, LP5562_REG_OP_MODE, LP5562_CMD_DIRECT); 169 lp5562_wait_opmode_done(); 170 return; 171 } 172 173 /* 174 * To run the engine, 175 * operation mode and enable register should updated at the same time 176 */ 177 178 ret = lp55xx_read(chip, LP5562_REG_OP_MODE, &mode); 179 if (ret) 180 return; 181 182 ret = lp55xx_read(chip, LP5562_REG_ENABLE, &exec); 183 if (ret) 184 return; 185 186 /* change operation mode to RUN only when each engine is loading */ 187 if (LP5562_ENG1_IS_LOADING(mode)) { 188 mode = (mode & ~LP5562_MODE_ENG1_M) | LP5562_RUN_ENG1; 189 exec = (exec & ~LP5562_EXEC_ENG1_M) | LP5562_RUN_ENG1; 190 } 191 192 if (LP5562_ENG2_IS_LOADING(mode)) { 193 mode = (mode & ~LP5562_MODE_ENG2_M) | LP5562_RUN_ENG2; 194 exec = (exec & ~LP5562_EXEC_ENG2_M) | LP5562_RUN_ENG2; 195 } 196 197 if (LP5562_ENG3_IS_LOADING(mode)) { 198 mode = (mode & ~LP5562_MODE_ENG3_M) | LP5562_RUN_ENG3; 199 exec = (exec & ~LP5562_EXEC_ENG3_M) | LP5562_RUN_ENG3; 200 } 201 202 lp55xx_write(chip, LP5562_REG_OP_MODE, mode); 203 lp5562_wait_opmode_done(); 204 205 lp55xx_update_bits(chip, LP5562_REG_ENABLE, LP5562_EXEC_M, exec); 206 lp5562_wait_enable_done(); 207} 208 209static int lp5562_update_firmware(struct lp55xx_chip *chip, 210 const u8 *data, size_t size) 211{ 212 enum lp55xx_engine_index idx = chip->engine_idx; 213 u8 pattern[LP5562_PROGRAM_LENGTH] = {0}; 214 u8 addr[] = { 215 [LP55XX_ENGINE_1] = LP5562_REG_PROG_MEM_ENG1, 216 [LP55XX_ENGINE_2] = LP5562_REG_PROG_MEM_ENG2, 217 [LP55XX_ENGINE_3] = LP5562_REG_PROG_MEM_ENG3, 218 }; 219 unsigned cmd; 220 char c[3]; 221 int program_size; 222 int nrchars; 223 int offset = 0; 224 int ret; 225 int i; 226 227 /* clear program memory before updating */ 228 for (i = 0; i < LP5562_PROGRAM_LENGTH; i++) 229 lp55xx_write(chip, addr[idx] + i, 0); 230 231 i = 0; 232 while ((offset < size - 1) && (i < LP5562_PROGRAM_LENGTH)) { 233 /* separate sscanfs because length is working only for %s */ 234 ret = sscanf(data + offset, "%2s%n ", c, &nrchars); 235 if (ret != 1) 236 goto err; 237 238 ret = sscanf(c, "%2x", &cmd); 239 if (ret != 1) 240 goto err; 241 242 pattern[i] = (u8)cmd; 243 offset += nrchars; 244 i++; 245 } 246 247 /* Each instruction is 16bit long. Check that length is even */ 248 if (i % 2) 249 goto err; 250 251 program_size = i; 252 for (i = 0; i < program_size; i++) 253 lp55xx_write(chip, addr[idx] + i, pattern[i]); 254 255 return 0; 256 257err: 258 dev_err(&chip->cl->dev, "wrong pattern format\n"); 259 return -EINVAL; 260} 261 262static void lp5562_firmware_loaded(struct lp55xx_chip *chip) 263{ 264 const struct firmware *fw = chip->fw; 265 266 if (fw->size > LP5562_PROGRAM_LENGTH) { 267 dev_err(&chip->cl->dev, "firmware data size overflow: %zu\n", 268 fw->size); 269 return; 270 } 271 272 /* 273 * Program momery sequence 274 * 1) set engine mode to "LOAD" 275 * 2) write firmware data into program memory 276 */ 277 278 lp5562_load_engine(chip); 279 lp5562_update_firmware(chip, fw->data, fw->size); 280} 281 282static int lp5562_post_init_device(struct lp55xx_chip *chip) 283{ 284 int ret; 285 u8 cfg = LP5562_DEFAULT_CFG; 286 287 /* Set all PWMs to direct control mode */ 288 ret = lp55xx_write(chip, LP5562_REG_OP_MODE, LP5562_CMD_DIRECT); 289 if (ret) 290 return ret; 291 292 lp5562_wait_opmode_done(); 293 294 /* Update configuration for the clock setting */ 295 if (!lp55xx_is_extclk_used(chip)) 296 cfg |= LP5562_CLK_INT; 297 298 ret = lp55xx_write(chip, LP5562_REG_CONFIG, cfg); 299 if (ret) 300 return ret; 301 302 /* Initialize all channels PWM to zero -> leds off */ 303 lp55xx_write(chip, LP5562_REG_R_PWM, 0); 304 lp55xx_write(chip, LP5562_REG_G_PWM, 0); 305 lp55xx_write(chip, LP5562_REG_B_PWM, 0); 306 lp55xx_write(chip, LP5562_REG_W_PWM, 0); 307 308 /* Set LED map as register PWM by default */ 309 lp55xx_write(chip, LP5562_REG_ENG_SEL, LP5562_ENG_SEL_PWM); 310 311 return 0; 312} 313 314static void lp5562_led_brightness_work(struct work_struct *work) 315{ 316 struct lp55xx_led *led = container_of(work, struct lp55xx_led, 317 brightness_work); 318 struct lp55xx_chip *chip = led->chip; 319 u8 addr[] = { 320 LP5562_REG_R_PWM, 321 LP5562_REG_G_PWM, 322 LP5562_REG_B_PWM, 323 LP5562_REG_W_PWM, 324 }; 325 326 mutex_lock(&chip->lock); 327 lp55xx_write(chip, addr[led->chan_nr], led->brightness); 328 mutex_unlock(&chip->lock); 329} 330 331static void lp5562_write_program_memory(struct lp55xx_chip *chip, 332 u8 base, const u8 *rgb, int size) 333{ 334 int i; 335 336 if (!rgb || size <= 0) 337 return; 338 339 for (i = 0; i < size; i++) 340 lp55xx_write(chip, base + i, *(rgb + i)); 341 342 lp55xx_write(chip, base + i, 0); 343 lp55xx_write(chip, base + i + 1, 0); 344} 345 346/* check the size of program count */ 347static inline bool _is_pc_overflow(struct lp55xx_predef_pattern *ptn) 348{ 349 return ptn->size_r >= LP5562_PROGRAM_LENGTH || 350 ptn->size_g >= LP5562_PROGRAM_LENGTH || 351 ptn->size_b >= LP5562_PROGRAM_LENGTH; 352} 353 354static int lp5562_run_predef_led_pattern(struct lp55xx_chip *chip, int mode) 355{ 356 struct lp55xx_predef_pattern *ptn; 357 int i; 358 359 if (mode == LP5562_PATTERN_OFF) { 360 lp5562_run_engine(chip, false); 361 return 0; 362 } 363 364 ptn = chip->pdata->patterns + (mode - 1); 365 if (!ptn || _is_pc_overflow(ptn)) { 366 dev_err(&chip->cl->dev, "invalid pattern data\n"); 367 return -EINVAL; 368 } 369 370 lp5562_stop_engine(chip); 371 372 /* Set LED map as RGB */ 373 lp55xx_write(chip, LP5562_REG_ENG_SEL, LP5562_ENG_SEL_RGB); 374 375 /* Load engines */ 376 for (i = LP55XX_ENGINE_1; i <= LP55XX_ENGINE_3; i++) { 377 chip->engine_idx = i; 378 lp5562_load_engine(chip); 379 } 380 381 /* Clear program registers */ 382 lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG1, 0); 383 lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG1 + 1, 0); 384 lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG2, 0); 385 lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG2 + 1, 0); 386 lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG3, 0); 387 lp55xx_write(chip, LP5562_REG_PROG_MEM_ENG3 + 1, 0); 388 389 /* Program engines */ 390 lp5562_write_program_memory(chip, LP5562_REG_PROG_MEM_ENG1, 391 ptn->r, ptn->size_r); 392 lp5562_write_program_memory(chip, LP5562_REG_PROG_MEM_ENG2, 393 ptn->g, ptn->size_g); 394 lp5562_write_program_memory(chip, LP5562_REG_PROG_MEM_ENG3, 395 ptn->b, ptn->size_b); 396 397 /* Run engines */ 398 lp5562_run_engine(chip, true); 399 400 return 0; 401} 402 403static ssize_t lp5562_store_pattern(struct device *dev, 404 struct device_attribute *attr, 405 const char *buf, size_t len) 406{ 407 struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); 408 struct lp55xx_chip *chip = led->chip; 409 struct lp55xx_predef_pattern *ptn = chip->pdata->patterns; 410 int num_patterns = chip->pdata->num_patterns; 411 unsigned long mode; 412 int ret; 413 414 ret = kstrtoul(buf, 0, &mode); 415 if (ret) 416 return ret; 417 418 if (mode > num_patterns || !ptn) 419 return -EINVAL; 420 421 mutex_lock(&chip->lock); 422 ret = lp5562_run_predef_led_pattern(chip, mode); 423 mutex_unlock(&chip->lock); 424 425 if (ret) 426 return ret; 427 428 return len; 429} 430 431static ssize_t lp5562_store_engine_mux(struct device *dev, 432 struct device_attribute *attr, 433 const char *buf, size_t len) 434{ 435 struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); 436 struct lp55xx_chip *chip = led->chip; 437 u8 mask; 438 u8 val; 439 440 /* LED map 441 * R ... Engine 1 (fixed) 442 * G ... Engine 2 (fixed) 443 * B ... Engine 3 (fixed) 444 * W ... Engine 1 or 2 or 3 445 */ 446 447 if (sysfs_streq(buf, "RGB")) { 448 mask = LP5562_ENG_FOR_RGB_M; 449 val = LP5562_ENG_SEL_RGB; 450 } else if (sysfs_streq(buf, "W")) { 451 enum lp55xx_engine_index idx = chip->engine_idx; 452 453 mask = LP5562_ENG_FOR_W_M; 454 switch (idx) { 455 case LP55XX_ENGINE_1: 456 val = LP5562_ENG1_FOR_W; 457 break; 458 case LP55XX_ENGINE_2: 459 val = LP5562_ENG2_FOR_W; 460 break; 461 case LP55XX_ENGINE_3: 462 val = LP5562_ENG3_FOR_W; 463 break; 464 default: 465 return -EINVAL; 466 } 467 468 } else { 469 dev_err(dev, "choose RGB or W\n"); 470 return -EINVAL; 471 } 472 473 mutex_lock(&chip->lock); 474 lp55xx_update_bits(chip, LP5562_REG_ENG_SEL, mask, val); 475 mutex_unlock(&chip->lock); 476 477 return len; 478} 479 480static LP55XX_DEV_ATTR_WO(led_pattern, lp5562_store_pattern); 481static LP55XX_DEV_ATTR_WO(engine_mux, lp5562_store_engine_mux); 482 483static struct attribute *lp5562_attributes[] = { 484 &dev_attr_led_pattern.attr, 485 &dev_attr_engine_mux.attr, 486 NULL, 487}; 488 489static const struct attribute_group lp5562_group = { 490 .attrs = lp5562_attributes, 491}; 492 493/* Chip specific configurations */ 494static struct lp55xx_device_config lp5562_cfg = { 495 .max_channel = LP5562_MAX_LEDS, 496 .reset = { 497 .addr = LP5562_REG_RESET, 498 .val = LP5562_RESET, 499 }, 500 .enable = { 501 .addr = LP5562_REG_ENABLE, 502 .val = LP5562_ENABLE_DEFAULT, 503 }, 504 .post_init_device = lp5562_post_init_device, 505 .set_led_current = lp5562_set_led_current, 506 .brightness_work_fn = lp5562_led_brightness_work, 507 .run_engine = lp5562_run_engine, 508 .firmware_cb = lp5562_firmware_loaded, 509 .dev_attr_group = &lp5562_group, 510}; 511 512static int lp5562_probe(struct i2c_client *client, 513 const struct i2c_device_id *id) 514{ 515 int ret; 516 struct lp55xx_chip *chip; 517 struct lp55xx_led *led; 518 struct lp55xx_platform_data *pdata; 519 struct device_node *np = client->dev.of_node; 520 521 if (!dev_get_platdata(&client->dev)) { 522 if (np) { 523 ret = lp55xx_of_populate_pdata(&client->dev, np); 524 if (ret < 0) 525 return ret; 526 } else { 527 dev_err(&client->dev, "no platform data\n"); 528 return -EINVAL; 529 } 530 } 531 pdata = dev_get_platdata(&client->dev); 532 533 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 534 if (!chip) 535 return -ENOMEM; 536 537 led = devm_kzalloc(&client->dev, 538 sizeof(*led) * pdata->num_channels, GFP_KERNEL); 539 if (!led) 540 return -ENOMEM; 541 542 chip->cl = client; 543 chip->pdata = pdata; 544 chip->cfg = &lp5562_cfg; 545 546 mutex_init(&chip->lock); 547 548 i2c_set_clientdata(client, led); 549 550 ret = lp55xx_init_device(chip); 551 if (ret) 552 goto err_init; 553 554 ret = lp55xx_register_leds(led, chip); 555 if (ret) 556 goto err_register_leds; 557 558 ret = lp55xx_register_sysfs(chip); 559 if (ret) { 560 dev_err(&client->dev, "registering sysfs failed\n"); 561 goto err_register_sysfs; 562 } 563 564 return 0; 565 566err_register_sysfs: 567 lp55xx_unregister_leds(led, chip); 568err_register_leds: 569 lp55xx_deinit_device(chip); 570err_init: 571 return ret; 572} 573 574static int lp5562_remove(struct i2c_client *client) 575{ 576 struct lp55xx_led *led = i2c_get_clientdata(client); 577 struct lp55xx_chip *chip = led->chip; 578 579 lp5562_stop_engine(chip); 580 581 lp55xx_unregister_sysfs(chip); 582 lp55xx_unregister_leds(led, chip); 583 lp55xx_deinit_device(chip); 584 585 return 0; 586} 587 588static const struct i2c_device_id lp5562_id[] = { 589 { "lp5562", 0 }, 590 { } 591}; 592MODULE_DEVICE_TABLE(i2c, lp5562_id); 593 594#ifdef CONFIG_OF 595static const struct of_device_id of_lp5562_leds_match[] = { 596 { .compatible = "ti,lp5562", }, 597 {}, 598}; 599 600MODULE_DEVICE_TABLE(of, of_lp5562_leds_match); 601#endif 602 603static struct i2c_driver lp5562_driver = { 604 .driver = { 605 .name = "lp5562", 606 .of_match_table = of_match_ptr(of_lp5562_leds_match), 607 }, 608 .probe = lp5562_probe, 609 .remove = lp5562_remove, 610 .id_table = lp5562_id, 611}; 612 613module_i2c_driver(lp5562_driver); 614 615MODULE_DESCRIPTION("Texas Instruments LP5562 LED Driver"); 616MODULE_AUTHOR("Milo Kim"); 617MODULE_LICENSE("GPL"); 618