Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

leds: lp55xx: Add multicolor framework support to lp55xx

Add multicolor framework support for the lp55xx family.

Acked-by: Pavel Machek <pavel@ucw.cz>
Acked-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
Signed-off-by: Dan Murphy <dmurphy@ti.com>
Signed-off-by: Pavel Machek <pavel@ucw.cz>

authored by

Dan Murphy and committed by
Pavel Machek
92a81562 c732eaf0

+216 -56
+6 -5
drivers/leds/Kconfig
··· 386 386 387 387 config LEDS_LP55XX_COMMON 388 388 tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501" 389 - depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501 389 + depends on LEDS_CLASS_MULTICOLOR || !LEDS_CLASS_MULTICOLOR 390 + depends on OF 390 391 select FW_LOADER 391 392 select FW_LOADER_USER_HELPER 392 393 help ··· 397 396 config LEDS_LP5521 398 397 tristate "LED Support for N.S. LP5521 LED driver chip" 399 398 depends on LEDS_CLASS && I2C 400 - select LEDS_LP55XX_COMMON 399 + depends on LEDS_LP55XX_COMMON 401 400 help 402 401 If you say yes here you get support for the National Semiconductor 403 402 LP5521 LED driver. It is 3 channel chip with programmable engines. ··· 407 406 config LEDS_LP5523 408 407 tristate "LED Support for TI/National LP5523/55231 LED driver chip" 409 408 depends on LEDS_CLASS && I2C 410 - select LEDS_LP55XX_COMMON 409 + depends on LEDS_LP55XX_COMMON 411 410 help 412 411 If you say yes here you get support for TI/National Semiconductor 413 412 LP5523/55231 LED driver. ··· 418 417 config LEDS_LP5562 419 418 tristate "LED Support for TI LP5562 LED driver chip" 420 419 depends on LEDS_CLASS && I2C 421 - select LEDS_LP55XX_COMMON 420 + depends on LEDS_LP55XX_COMMON 422 421 help 423 422 If you say yes here you get support for TI LP5562 LED driver. 424 423 It is 4 channels chip with programmable engines. ··· 428 427 config LEDS_LP8501 429 428 tristate "LED Support for TI LP8501 LED driver chip" 430 429 depends on LEDS_CLASS && I2C 431 - select LEDS_LP55XX_COMMON 430 + depends on LEDS_LP55XX_COMMON 432 431 help 433 432 If you say yes here you get support for TI LP8501 LED driver. 434 433 It is 9 channel chip with programmable engines.
+8 -6
drivers/leds/leds-lp5521.c
··· 505 505 struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev); 506 506 struct device_node *np = client->dev.of_node; 507 507 508 + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 509 + if (!chip) 510 + return -ENOMEM; 511 + 512 + chip->cfg = &lp5521_cfg; 513 + 508 514 if (!pdata) { 509 515 if (np) { 510 - pdata = lp55xx_of_populate_pdata(&client->dev, np); 516 + pdata = lp55xx_of_populate_pdata(&client->dev, np, 517 + chip); 511 518 if (IS_ERR(pdata)) 512 519 return PTR_ERR(pdata); 513 520 } else { ··· 523 516 } 524 517 } 525 518 526 - chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 527 - if (!chip) 528 - return -ENOMEM; 529 - 530 519 led = devm_kcalloc(&client->dev, 531 520 pdata->num_channels, sizeof(*led), GFP_KERNEL); 532 521 if (!led) ··· 530 527 531 528 chip->cl = client; 532 529 chip->pdata = pdata; 533 - chip->cfg = &lp5521_cfg; 534 530 535 531 mutex_init(&chip->lock); 536 532
+8 -6
drivers/leds/leds-lp5523.c
··· 873 873 struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev); 874 874 struct device_node *np = client->dev.of_node; 875 875 876 + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 877 + if (!chip) 878 + return -ENOMEM; 879 + 880 + chip->cfg = &lp5523_cfg; 881 + 876 882 if (!pdata) { 877 883 if (np) { 878 - pdata = lp55xx_of_populate_pdata(&client->dev, np); 884 + pdata = lp55xx_of_populate_pdata(&client->dev, np, 885 + chip); 879 886 if (IS_ERR(pdata)) 880 887 return PTR_ERR(pdata); 881 888 } else { ··· 891 884 } 892 885 } 893 886 894 - chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 895 - if (!chip) 896 - return -ENOMEM; 897 - 898 887 led = devm_kcalloc(&client->dev, 899 888 pdata->num_channels, sizeof(*led), GFP_KERNEL); 900 889 if (!led) ··· 898 895 899 896 chip->cl = client; 900 897 chip->pdata = pdata; 901 - chip->cfg = &lp5523_cfg; 902 898 903 899 mutex_init(&chip->lock); 904 900
+8 -5
drivers/leds/leds-lp5562.c
··· 520 520 struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev); 521 521 struct device_node *np = client->dev.of_node; 522 522 523 + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 524 + if (!chip) 525 + return -ENOMEM; 526 + 527 + chip->cfg = &lp5562_cfg; 528 + 523 529 if (!pdata) { 524 530 if (np) { 525 - pdata = lp55xx_of_populate_pdata(&client->dev, np); 531 + pdata = lp55xx_of_populate_pdata(&client->dev, np, 532 + chip); 526 533 if (IS_ERR(pdata)) 527 534 return PTR_ERR(pdata); 528 535 } else { ··· 538 531 } 539 532 } 540 533 541 - chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 542 - if (!chip) 543 - return -ENOMEM; 544 534 545 535 led = devm_kcalloc(&client->dev, 546 536 pdata->num_channels, sizeof(*led), GFP_KERNEL); ··· 546 542 547 543 chip->cl = client; 548 544 chip->pdata = pdata; 549 - chip->cfg = &lp5562_cfg; 550 545 551 546 mutex_init(&chip->lock); 552 547
+159 -26
drivers/leds/leds-lp55xx-common.c
··· 34 34 return cdev_to_lp55xx_led(dev_get_drvdata(dev)); 35 35 } 36 36 37 + static struct lp55xx_led *mcled_cdev_to_led(struct led_classdev_mc *mc_cdev) 38 + { 39 + return container_of(mc_cdev, struct lp55xx_led, mc_cdev); 40 + } 41 + 37 42 static void lp55xx_reset_device(struct lp55xx_chip *chip) 38 43 { 39 44 struct lp55xx_device_config *cfg = chip->cfg; ··· 134 129 }; 135 130 ATTRIBUTE_GROUPS(lp55xx_led); 136 131 132 + static int lp55xx_set_mc_brightness(struct led_classdev *cdev, 133 + enum led_brightness brightness) 134 + { 135 + struct led_classdev_mc *mc_dev = lcdev_to_mccdev(cdev); 136 + struct lp55xx_led *led = mcled_cdev_to_led(mc_dev); 137 + struct lp55xx_device_config *cfg = led->chip->cfg; 138 + 139 + led_mc_calc_color_components(&led->mc_cdev, brightness); 140 + return cfg->multicolor_brightness_fn(led); 141 + 142 + } 143 + 137 144 static int lp55xx_set_brightness(struct led_classdev *cdev, 138 145 enum led_brightness brightness) 139 146 { ··· 162 145 struct lp55xx_platform_data *pdata = chip->pdata; 163 146 struct lp55xx_device_config *cfg = chip->cfg; 164 147 struct device *dev = &chip->cl->dev; 165 - char name[32]; 166 - int ret; 167 148 int max_channel = cfg->max_channel; 149 + struct mc_subled *mc_led_info; 150 + struct led_classdev *led_cdev; 151 + char name[32]; 152 + int i, j = 0; 153 + int ret; 168 154 169 155 if (chan >= max_channel) { 170 156 dev_err(dev, "invalid channel: %d / %d\n", chan, max_channel); ··· 177 157 if (pdata->led_config[chan].led_current == 0) 178 158 return 0; 179 159 180 - led->led_current = pdata->led_config[chan].led_current; 181 - led->max_current = pdata->led_config[chan].max_current; 182 - led->chan_nr = pdata->led_config[chan].chan_nr; 183 - led->cdev.default_trigger = pdata->led_config[chan].default_trigger; 184 - 185 - if (led->chan_nr >= max_channel) { 186 - dev_err(dev, "Use channel numbers between 0 and %d\n", 187 - max_channel - 1); 188 - return -EINVAL; 189 - } 190 - 191 - led->cdev.brightness_set_blocking = lp55xx_set_brightness; 192 - led->cdev.groups = lp55xx_led_groups; 193 - 194 160 if (pdata->led_config[chan].name) { 195 161 led->cdev.name = pdata->led_config[chan].name; 196 162 } else { ··· 185 179 led->cdev.name = name; 186 180 } 187 181 188 - ret = devm_led_classdev_register(dev, &led->cdev); 182 + if (pdata->led_config[chan].num_colors > 1) { 183 + mc_led_info = devm_kcalloc(dev, 184 + pdata->led_config[chan].num_colors, 185 + sizeof(*mc_led_info), GFP_KERNEL); 186 + if (!mc_led_info) 187 + return -ENOMEM; 188 + 189 + led_cdev = &led->mc_cdev.led_cdev; 190 + led_cdev->name = led->cdev.name; 191 + led_cdev->brightness_set_blocking = lp55xx_set_mc_brightness; 192 + led->mc_cdev.num_colors = pdata->led_config[chan].num_colors; 193 + for (i = 0; i < led->mc_cdev.num_colors; i++) { 194 + mc_led_info[i].color_index = 195 + pdata->led_config[chan].color_id[i]; 196 + mc_led_info[i].channel = 197 + pdata->led_config[chan].output_num[i]; 198 + j++; 199 + } 200 + 201 + led->mc_cdev.subled_info = mc_led_info; 202 + } else { 203 + led->cdev.brightness_set_blocking = lp55xx_set_brightness; 204 + } 205 + 206 + led->cdev.groups = lp55xx_led_groups; 207 + led->cdev.default_trigger = pdata->led_config[chan].default_trigger; 208 + led->led_current = pdata->led_config[chan].led_current; 209 + led->max_current = pdata->led_config[chan].max_current; 210 + led->chan_nr = pdata->led_config[chan].chan_nr; 211 + 212 + if (led->chan_nr >= max_channel) { 213 + dev_err(dev, "Use channel numbers between 0 and %d\n", 214 + max_channel - 1); 215 + return -EINVAL; 216 + } 217 + 218 + if (pdata->led_config[chan].num_colors > 1) 219 + ret = devm_led_classdev_multicolor_register(dev, &led->mc_cdev); 220 + else 221 + ret = devm_led_classdev_register(dev, &led->cdev); 222 + 189 223 if (ret) { 190 224 dev_err(dev, "led register err: %d\n", ret); 191 225 return ret; ··· 561 515 } 562 516 EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs); 563 517 518 + static int lp55xx_parse_common_child(struct device_node *np, 519 + struct lp55xx_led_config *cfg, 520 + int led_number, int *chan_nr) 521 + { 522 + int ret; 523 + 524 + of_property_read_string(np, "chan-name", 525 + &cfg[led_number].name); 526 + of_property_read_u8(np, "led-cur", 527 + &cfg[led_number].led_current); 528 + of_property_read_u8(np, "max-cur", 529 + &cfg[led_number].max_current); 530 + 531 + ret = of_property_read_u32(np, "reg", chan_nr); 532 + if (ret) 533 + return ret; 534 + 535 + if (*chan_nr < 0 || *chan_nr > cfg->max_channel) 536 + return -EINVAL; 537 + 538 + return 0; 539 + } 540 + 541 + static int lp55xx_parse_multi_led_child(struct device_node *child, 542 + struct lp55xx_led_config *cfg, 543 + int child_number, int color_number) 544 + { 545 + int chan_nr, color_id, ret; 546 + 547 + ret = lp55xx_parse_common_child(child, cfg, child_number, &chan_nr); 548 + if (ret) 549 + return ret; 550 + 551 + ret = of_property_read_u32(child, "color", &color_id); 552 + if (ret) 553 + return ret; 554 + 555 + cfg[child_number].color_id[color_number] = color_id; 556 + cfg[child_number].output_num[color_number] = chan_nr; 557 + 558 + return 0; 559 + } 560 + 561 + static int lp55xx_parse_multi_led(struct device_node *np, 562 + struct lp55xx_led_config *cfg, 563 + int child_number) 564 + { 565 + struct device_node *child; 566 + int num_colors = 0, ret; 567 + 568 + for_each_child_of_node(np, child) { 569 + ret = lp55xx_parse_multi_led_child(child, cfg, child_number, 570 + num_colors); 571 + if (ret) 572 + return ret; 573 + num_colors++; 574 + } 575 + 576 + cfg[child_number].num_colors = num_colors; 577 + 578 + return 0; 579 + } 580 + 581 + static int lp55xx_parse_logical_led(struct device_node *np, 582 + struct lp55xx_led_config *cfg, 583 + int child_number) 584 + { 585 + int led_color, ret; 586 + int chan_nr = 0; 587 + 588 + cfg[child_number].default_trigger = 589 + of_get_property(np, "linux,default-trigger", NULL); 590 + 591 + ret = of_property_read_u32(np, "color", &led_color); 592 + if (ret) 593 + return ret; 594 + 595 + if (led_color == LED_COLOR_ID_MULTI) 596 + return lp55xx_parse_multi_led(np, cfg, child_number); 597 + 598 + ret = lp55xx_parse_common_child(np, cfg, child_number, &chan_nr); 599 + if (ret < 0) 600 + return ret; 601 + 602 + cfg[child_number].chan_nr = chan_nr; 603 + 604 + return ret; 605 + } 606 + 564 607 struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev, 565 - struct device_node *np) 608 + struct device_node *np, 609 + struct lp55xx_chip *chip) 566 610 { 567 611 struct device_node *child; 568 612 struct lp55xx_platform_data *pdata; 569 613 struct lp55xx_led_config *cfg; 570 614 int num_channels; 571 615 int i = 0; 616 + int ret; 572 617 573 618 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 574 619 if (!pdata) ··· 677 540 678 541 pdata->led_config = &cfg[0]; 679 542 pdata->num_channels = num_channels; 543 + cfg->max_channel = chip->cfg->max_channel; 680 544 681 545 for_each_child_of_node(np, child) { 682 - cfg[i].chan_nr = i; 683 - 684 - of_property_read_string(child, "chan-name", &cfg[i].name); 685 - of_property_read_u8(child, "led-cur", &cfg[i].led_current); 686 - of_property_read_u8(child, "max-cur", &cfg[i].max_current); 687 - cfg[i].default_trigger = 688 - of_get_property(child, "linux,default-trigger", NULL); 689 - 546 + ret = lp55xx_parse_logical_led(child, cfg, i); 547 + if (ret) 548 + return ERR_PTR(-EINVAL); 690 549 i++; 691 550 } 692 551
+12 -2
drivers/leds/leds-lp55xx-common.h
··· 12 12 #ifndef _LEDS_LP55XX_COMMON_H 13 13 #define _LEDS_LP55XX_COMMON_H 14 14 15 + #include <linux/led-class-multicolor.h> 16 + 15 17 enum lp55xx_engine_index { 16 18 LP55XX_ENGINE_INVALID, 17 19 LP55XX_ENGINE_1, ··· 95 93 * @max_channel : Maximum number of channels 96 94 * @post_init_device : Chip specific initialization code 97 95 * @brightness_fn : Brightness function 96 + * @multicolor_brightness_fn : Multicolor brightness function 98 97 * @set_led_current : LED current set function 99 98 * @firmware_cb : Call function when the firmware is loaded 100 99 * @run_engine : Run internal engine for pattern ··· 109 106 /* define if the device has specific initialization process */ 110 107 int (*post_init_device) (struct lp55xx_chip *chip); 111 108 112 - /* access brightness register */ 109 + /* set LED brightness */ 113 110 int (*brightness_fn)(struct lp55xx_led *led); 111 + 112 + /* set multicolor LED brightness */ 113 + int (*multicolor_brightness_fn)(struct lp55xx_led *led); 114 114 115 115 /* current setting function */ 116 116 void (*set_led_current) (struct lp55xx_led *led, u8 led_current); ··· 165 159 * struct lp55xx_led 166 160 * @chan_nr : Channel number 167 161 * @cdev : LED class device 162 + * @mc_cdev : Multi color class device 163 + * @color_components: Multi color LED map information 168 164 * @led_current : Current setting at each led channel 169 165 * @max_current : Maximun current at each led channel 170 166 * @brightness : Brightness value ··· 175 167 struct lp55xx_led { 176 168 int chan_nr; 177 169 struct led_classdev cdev; 170 + struct led_classdev_mc mc_cdev; 178 171 u8 led_current; 179 172 u8 max_current; 180 173 u8 brightness; ··· 205 196 206 197 /* common device tree population function */ 207 198 extern struct lp55xx_platform_data 208 - *lp55xx_of_populate_pdata(struct device *dev, struct device_node *np); 199 + *lp55xx_of_populate_pdata(struct device *dev, struct device_node *np, 200 + struct lp55xx_chip *chip); 209 201 210 202 #endif /* _LEDS_LP55XX_COMMON_H */
+8 -6
drivers/leds/leds-lp8501.c
··· 308 308 struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev); 309 309 struct device_node *np = client->dev.of_node; 310 310 311 + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 312 + if (!chip) 313 + return -ENOMEM; 314 + 315 + chip->cfg = &lp8501_cfg; 316 + 311 317 if (!pdata) { 312 318 if (np) { 313 - pdata = lp55xx_of_populate_pdata(&client->dev, np); 319 + pdata = lp55xx_of_populate_pdata(&client->dev, np, 320 + chip); 314 321 if (IS_ERR(pdata)) 315 322 return PTR_ERR(pdata); 316 323 } else { ··· 326 319 } 327 320 } 328 321 329 - chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 330 - if (!chip) 331 - return -ENOMEM; 332 - 333 322 led = devm_kcalloc(&client->dev, 334 323 pdata->num_channels, sizeof(*led), GFP_KERNEL); 335 324 if (!led) ··· 333 330 334 331 chip->cl = client; 335 332 chip->pdata = pdata; 336 - chip->cfg = &lp8501_cfg; 337 333 338 334 mutex_init(&chip->lock); 339 335
+7
include/linux/platform_data/leds-lp55xx.h
··· 13 13 #define _LEDS_LP55XX_H 14 14 15 15 #include <linux/gpio/consumer.h> 16 + #include <linux/led-class-multicolor.h> 16 17 17 18 /* Clock configuration */ 18 19 #define LP55XX_CLOCK_AUTO 0 19 20 #define LP55XX_CLOCK_INT 1 20 21 #define LP55XX_CLOCK_EXT 2 22 + 23 + #define LP55XX_MAX_GROUPED_CHAN 4 21 24 22 25 struct lp55xx_led_config { 23 26 const char *name; ··· 28 25 u8 chan_nr; 29 26 u8 led_current; /* mA x10, 0 if led is not connected */ 30 27 u8 max_current; 28 + int num_colors; 29 + unsigned int max_channel; 30 + int color_id[LED_COLOR_ID_MAX]; 31 + int output_num[LED_COLOR_ID_MAX]; 31 32 }; 32 33 33 34 struct lp55xx_predef_pattern {