| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * lp5523.c - LP5523, LP55231 LED Driver |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 6 | 7 | * |
|---|
| 7 | 8 | * Contact: Samu Onkalo <samu.p.onkalo@nokia.com> |
|---|
| 8 | 9 | * Milo(Woogyom) Kim <milo.kim@ti.com> |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is free software; you can redistribute it and/or |
|---|
| 11 | | - * modify it under the terms of the GNU General Public License |
|---|
| 12 | | - * version 2 as published by the Free Software Foundation. |
|---|
| 13 | | - * |
|---|
| 14 | | - * This program is distributed in the hope that it will be useful, but |
|---|
| 15 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 16 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|---|
| 17 | | - * General Public License for more details. |
|---|
| 18 | | - * |
|---|
| 19 | | - * You should have received a copy of the GNU General Public License |
|---|
| 20 | | - * along with this program; if not, write to the Free Software |
|---|
| 21 | | - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA |
|---|
| 22 | | - * 02110-1301 USA |
|---|
| 23 | 10 | */ |
|---|
| 24 | 11 | |
|---|
| 25 | 12 | #include <linux/delay.h> |
|---|
| .. | .. |
|---|
| 36 | 23 | |
|---|
| 37 | 24 | #define LP5523_PROGRAM_LENGTH 32 /* bytes */ |
|---|
| 38 | 25 | /* Memory is used like this: |
|---|
| 39 | | - 0x00 engine 1 program |
|---|
| 40 | | - 0x10 engine 2 program |
|---|
| 41 | | - 0x20 engine 3 program |
|---|
| 42 | | - 0x30 engine 1 muxing info |
|---|
| 43 | | - 0x40 engine 2 muxing info |
|---|
| 44 | | - 0x50 engine 3 muxing info |
|---|
| 45 | | -*/ |
|---|
| 26 | + * 0x00 engine 1 program |
|---|
| 27 | + * 0x10 engine 2 program |
|---|
| 28 | + * 0x20 engine 3 program |
|---|
| 29 | + * 0x30 engine 1 muxing info |
|---|
| 30 | + * 0x40 engine 2 muxing info |
|---|
| 31 | + * 0x50 engine 3 muxing info |
|---|
| 32 | + */ |
|---|
| 46 | 33 | #define LP5523_MAX_LEDS 9 |
|---|
| 47 | 34 | |
|---|
| 48 | 35 | /* Registers */ |
|---|
| .. | .. |
|---|
| 339 | 326 | const u8 *data, size_t size) |
|---|
| 340 | 327 | { |
|---|
| 341 | 328 | u8 pattern[LP5523_PROGRAM_LENGTH] = {0}; |
|---|
| 342 | | - unsigned cmd; |
|---|
| 329 | + unsigned int cmd; |
|---|
| 343 | 330 | char c[3]; |
|---|
| 344 | 331 | int nrchars; |
|---|
| 345 | 332 | int ret; |
|---|
| .. | .. |
|---|
| 481 | 468 | static void lp5523_mux_to_array(u16 led_mux, char *array) |
|---|
| 482 | 469 | { |
|---|
| 483 | 470 | int i, pos = 0; |
|---|
| 471 | + |
|---|
| 484 | 472 | for (i = 0; i < LP5523_MAX_LEDS; i++) |
|---|
| 485 | 473 | pos += sprintf(array + pos, "%x", LED_ACTIVE(led_mux, i)); |
|---|
| 486 | 474 | |
|---|
| .. | .. |
|---|
| 519 | 507 | if (ret) |
|---|
| 520 | 508 | return ret; |
|---|
| 521 | 509 | |
|---|
| 522 | | - ret = lp55xx_write(chip, LP5523_REG_PROG_MEM , (u8)(mux >> 8)); |
|---|
| 510 | + ret = lp55xx_write(chip, LP5523_REG_PROG_MEM, (u8)(mux >> 8)); |
|---|
| 523 | 511 | if (ret) |
|---|
| 524 | 512 | return ret; |
|---|
| 525 | 513 | |
|---|
| .. | .. |
|---|
| 804 | 792 | return ret; |
|---|
| 805 | 793 | } |
|---|
| 806 | 794 | |
|---|
| 795 | +static int lp5523_multicolor_brightness(struct lp55xx_led *led) |
|---|
| 796 | +{ |
|---|
| 797 | + struct lp55xx_chip *chip = led->chip; |
|---|
| 798 | + int ret; |
|---|
| 799 | + int i; |
|---|
| 800 | + |
|---|
| 801 | + mutex_lock(&chip->lock); |
|---|
| 802 | + for (i = 0; i < led->mc_cdev.num_colors; i++) { |
|---|
| 803 | + ret = lp55xx_write(chip, |
|---|
| 804 | + LP5523_REG_LED_PWM_BASE + |
|---|
| 805 | + led->mc_cdev.subled_info[i].channel, |
|---|
| 806 | + led->mc_cdev.subled_info[i].brightness); |
|---|
| 807 | + if (ret) |
|---|
| 808 | + break; |
|---|
| 809 | + } |
|---|
| 810 | + mutex_unlock(&chip->lock); |
|---|
| 811 | + return ret; |
|---|
| 812 | +} |
|---|
| 813 | + |
|---|
| 807 | 814 | static int lp5523_led_brightness(struct lp55xx_led *led) |
|---|
| 808 | 815 | { |
|---|
| 809 | 816 | struct lp55xx_chip *chip = led->chip; |
|---|
| .. | .. |
|---|
| 870 | 877 | .max_channel = LP5523_MAX_LEDS, |
|---|
| 871 | 878 | .post_init_device = lp5523_post_init_device, |
|---|
| 872 | 879 | .brightness_fn = lp5523_led_brightness, |
|---|
| 880 | + .multicolor_brightness_fn = lp5523_multicolor_brightness, |
|---|
| 873 | 881 | .set_led_current = lp5523_set_led_current, |
|---|
| 874 | 882 | .firmware_cb = lp5523_firmware_loaded, |
|---|
| 875 | 883 | .run_engine = lp5523_run_engine, |
|---|
| .. | .. |
|---|
| 883 | 891 | struct lp55xx_chip *chip; |
|---|
| 884 | 892 | struct lp55xx_led *led; |
|---|
| 885 | 893 | struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev); |
|---|
| 886 | | - struct device_node *np = client->dev.of_node; |
|---|
| 894 | + struct device_node *np = dev_of_node(&client->dev); |
|---|
| 895 | + |
|---|
| 896 | + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); |
|---|
| 897 | + if (!chip) |
|---|
| 898 | + return -ENOMEM; |
|---|
| 899 | + |
|---|
| 900 | + chip->cfg = &lp5523_cfg; |
|---|
| 887 | 901 | |
|---|
| 888 | 902 | if (!pdata) { |
|---|
| 889 | 903 | if (np) { |
|---|
| 890 | | - pdata = lp55xx_of_populate_pdata(&client->dev, np); |
|---|
| 904 | + pdata = lp55xx_of_populate_pdata(&client->dev, np, |
|---|
| 905 | + chip); |
|---|
| 891 | 906 | if (IS_ERR(pdata)) |
|---|
| 892 | 907 | return PTR_ERR(pdata); |
|---|
| 893 | 908 | } else { |
|---|
| .. | .. |
|---|
| 896 | 911 | } |
|---|
| 897 | 912 | } |
|---|
| 898 | 913 | |
|---|
| 899 | | - chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); |
|---|
| 900 | | - if (!chip) |
|---|
| 901 | | - return -ENOMEM; |
|---|
| 902 | | - |
|---|
| 903 | 914 | led = devm_kcalloc(&client->dev, |
|---|
| 904 | 915 | pdata->num_channels, sizeof(*led), GFP_KERNEL); |
|---|
| 905 | 916 | if (!led) |
|---|
| .. | .. |
|---|
| 907 | 918 | |
|---|
| 908 | 919 | chip->cl = client; |
|---|
| 909 | 920 | chip->pdata = pdata; |
|---|
| 910 | | - chip->cfg = &lp5523_cfg; |
|---|
| 911 | 921 | |
|---|
| 912 | 922 | mutex_init(&chip->lock); |
|---|
| 913 | 923 | |
|---|
| .. | .. |
|---|
| 921 | 931 | |
|---|
| 922 | 932 | ret = lp55xx_register_leds(led, chip); |
|---|
| 923 | 933 | if (ret) |
|---|
| 924 | | - goto err_register_leds; |
|---|
| 934 | + goto err_out; |
|---|
| 925 | 935 | |
|---|
| 926 | 936 | ret = lp55xx_register_sysfs(chip); |
|---|
| 927 | 937 | if (ret) { |
|---|
| 928 | 938 | dev_err(&client->dev, "registering sysfs failed\n"); |
|---|
| 929 | | - goto err_register_sysfs; |
|---|
| 939 | + goto err_out; |
|---|
| 930 | 940 | } |
|---|
| 931 | 941 | |
|---|
| 932 | 942 | return 0; |
|---|
| 933 | 943 | |
|---|
| 934 | | -err_register_sysfs: |
|---|
| 935 | | - lp55xx_unregister_leds(led, chip); |
|---|
| 936 | | -err_register_leds: |
|---|
| 944 | +err_out: |
|---|
| 937 | 945 | lp55xx_deinit_device(chip); |
|---|
| 938 | 946 | err_init: |
|---|
| 939 | 947 | return ret; |
|---|
| .. | .. |
|---|
| 946 | 954 | |
|---|
| 947 | 955 | lp5523_stop_all_engines(chip); |
|---|
| 948 | 956 | lp55xx_unregister_sysfs(chip); |
|---|
| 949 | | - lp55xx_unregister_leds(led, chip); |
|---|
| 950 | 957 | lp55xx_deinit_device(chip); |
|---|
| 951 | 958 | |
|---|
| 952 | 959 | return 0; |
|---|