diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-12 14:35:33 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-12 14:35:33 -0400 |
| commit | 5223161dc0f5e44fbf3d5e42d23697b6796cdf4e (patch) | |
| tree | 10837ec58d96e751469d78d347f76c0d49238d72 /drivers | |
| parent | e5d0c874391a500be7643d3eef9fb07171eee129 (diff) | |
| parent | 61abeba5222895d6900b13115f5d8eba7988d7d6 (diff) | |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds
Pull led updates from Bryan Wu:
"Sorry for the late pull request, since I'm just back from vacation.
LED subsystem updates for 3.12:
- pca9633 driver DT supporting and pca9634 chip supporting
- restore legacy device attributes for lp5521
- other fixing and updates"
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds: (28 commits)
leds: wm831x-status: Request a REG resource
leds: trigger: ledtrig-backlight: Fix invalid memory access in fb_event notification callback
leds-pca963x: Fix device tree parsing
leds-pca9633: Rename to leds-pca963x
leds-pca9633: Add mutex to the ledout register
leds-pca9633: Unique naming of the LEDs
leds-pca9633: Add support for PCA9634
leds: lp5562: use LP55xx common macros for device attributes
Documentation: leds-lp5521,lp5523: update device attribute information
leds: lp5523: remove unnecessary writing commands
leds: lp5523: restore legacy device attributes
leds: lp5523: LED MUX configuration on initializing
leds: lp5523: make separate API for loading engine
leds: lp5521: remove unnecessary writing commands
leds: lp5521: restore legacy device attributes
leds: lp55xx: add common macros for device attributes
leds: lp55xx: add common data structure for program
Documentation: leds: Fix a typo
leds: ss4200: Fix incorrect placement of __initdata
leds: clevo-mail: Fix incorrect placement of __initdata
...
Diffstat (limited to 'drivers')
37 files changed, 1435 insertions, 300 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 074bcb3892b5..875bbe4c962e 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
| @@ -194,11 +194,11 @@ config LEDS_LP3944 | |||
| 194 | module will be called leds-lp3944. | 194 | module will be called leds-lp3944. |
| 195 | 195 | ||
| 196 | config LEDS_LP55XX_COMMON | 196 | config LEDS_LP55XX_COMMON |
| 197 | tristate "Common Driver for TI/National LP5521, LP5523/55231 and LP5562" | 197 | tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501" |
| 198 | depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 | 198 | depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501 |
| 199 | select FW_LOADER | 199 | select FW_LOADER |
| 200 | help | 200 | help |
| 201 | This option supports common operations for LP5521 and LP5523/55231 | 201 | This option supports common operations for LP5521/5523/55231/5562/8501 |
| 202 | devices. | 202 | devices. |
| 203 | 203 | ||
| 204 | config LEDS_LP5521 | 204 | config LEDS_LP5521 |
| @@ -232,6 +232,18 @@ config LEDS_LP5562 | |||
| 232 | Driver provides direct control via LED class and interface for | 232 | Driver provides direct control via LED class and interface for |
| 233 | programming the engines. | 233 | programming the engines. |
| 234 | 234 | ||
| 235 | config LEDS_LP8501 | ||
| 236 | tristate "LED Support for TI LP8501 LED driver chip" | ||
| 237 | depends on LEDS_CLASS && I2C | ||
| 238 | select LEDS_LP55XX_COMMON | ||
| 239 | help | ||
| 240 | If you say yes here you get support for TI LP8501 LED driver. | ||
| 241 | It is 9 channel chip with programmable engines. | ||
| 242 | Driver provides direct control via LED class and interface for | ||
| 243 | programming the engines. | ||
| 244 | It is similar as LP5523, but output power selection is available. | ||
| 245 | And register layout and engine program schemes are different. | ||
| 246 | |||
| 235 | config LEDS_LP8788 | 247 | config LEDS_LP8788 |
| 236 | tristate "LED support for the TI LP8788 PMIC" | 248 | tristate "LED support for the TI LP8788 PMIC" |
| 237 | depends on LEDS_CLASS | 249 | depends on LEDS_CLASS |
| @@ -279,13 +291,14 @@ config LEDS_PCA955X | |||
| 279 | LED driver chips accessed via the I2C bus. Supported | 291 | LED driver chips accessed via the I2C bus. Supported |
| 280 | devices include PCA9550, PCA9551, PCA9552, and PCA9553. | 292 | devices include PCA9550, PCA9551, PCA9552, and PCA9553. |
| 281 | 293 | ||
| 282 | config LEDS_PCA9633 | 294 | config LEDS_PCA963X |
| 283 | tristate "LED support for PCA9633 I2C chip" | 295 | tristate "LED support for PCA963x I2C chip" |
| 284 | depends on LEDS_CLASS | 296 | depends on LEDS_CLASS |
| 285 | depends on I2C | 297 | depends on I2C |
| 286 | help | 298 | help |
| 287 | This option enables support for LEDs connected to the PCA9633 | 299 | This option enables support for LEDs connected to the PCA963x |
| 288 | LED driver chip accessed via the I2C bus. | 300 | LED driver chip accessed via the I2C bus. Supported |
| 301 | devices include PCA9633 and PCA9634 | ||
| 289 | 302 | ||
| 290 | config LEDS_WM831X_STATUS | 303 | config LEDS_WM831X_STATUS |
| 291 | tristate "LED support for status LEDs on WM831x PMICs" | 304 | tristate "LED support for status LEDs on WM831x PMICs" |
| @@ -398,10 +411,7 @@ config LEDS_MC13783 | |||
| 398 | config LEDS_NS2 | 411 | config LEDS_NS2 |
| 399 | tristate "LED support for Network Space v2 GPIO LEDs" | 412 | tristate "LED support for Network Space v2 GPIO LEDs" |
| 400 | depends on LEDS_CLASS | 413 | depends on LEDS_CLASS |
| 401 | depends on MACH_NETSPACE_V2 || MACH_INETSPACE_V2 || \ | 414 | depends on ARCH_KIRKWOOD |
| 402 | MACH_NETSPACE_MAX_V2 || MACH_D2NET_V2 || \ | ||
| 403 | MACH_NETSPACE_V2_DT || MACH_INETSPACE_V2_DT || \ | ||
| 404 | MACH_NETSPACE_MAX_V2_DT || MACH_NETSPACE_MINI_V2_DT | ||
| 405 | default y | 415 | default y |
| 406 | help | 416 | help |
| 407 | This option enable support for the dual-GPIO LED found on the | 417 | This option enable support for the dual-GPIO LED found on the |
| @@ -410,8 +420,8 @@ config LEDS_NS2 | |||
| 410 | 420 | ||
| 411 | config LEDS_NETXBIG | 421 | config LEDS_NETXBIG |
| 412 | tristate "LED support for Big Network series LEDs" | 422 | tristate "LED support for Big Network series LEDs" |
| 413 | depends on MACH_NET2BIG_V2 || MACH_NET5BIG_V2 | ||
| 414 | depends on LEDS_CLASS | 423 | depends on LEDS_CLASS |
| 424 | depends on ARCH_KIRKWOOD | ||
| 415 | default y | 425 | default y |
| 416 | help | 426 | help |
| 417 | This option enable support for LEDs found on the LaCie 2Big | 427 | This option enable support for LEDs found on the LaCie 2Big |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index ae4b6135f665..8979b0b2c85e 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
| @@ -27,6 +27,7 @@ obj-$(CONFIG_LEDS_LP55XX_COMMON) += leds-lp55xx-common.o | |||
| 27 | obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o | 27 | obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o |
| 28 | obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o | 28 | obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o |
| 29 | obj-$(CONFIG_LEDS_LP5562) += leds-lp5562.o | 29 | obj-$(CONFIG_LEDS_LP5562) += leds-lp5562.o |
| 30 | obj-$(CONFIG_LEDS_LP8501) += leds-lp8501.o | ||
| 30 | obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o | 31 | obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o |
| 31 | obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o | 32 | obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o |
| 32 | obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o | 33 | obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o |
| @@ -34,7 +35,7 @@ obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o | |||
| 34 | obj-$(CONFIG_LEDS_OT200) += leds-ot200.o | 35 | obj-$(CONFIG_LEDS_OT200) += leds-ot200.o |
| 35 | obj-$(CONFIG_LEDS_FSG) += leds-fsg.o | 36 | obj-$(CONFIG_LEDS_FSG) += leds-fsg.o |
| 36 | obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o | 37 | obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o |
| 37 | obj-$(CONFIG_LEDS_PCA9633) += leds-pca9633.o | 38 | obj-$(CONFIG_LEDS_PCA963X) += leds-pca963x.o |
| 38 | obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o | 39 | obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o |
| 39 | obj-$(CONFIG_LEDS_DA9052) += leds-da9052.o | 40 | obj-$(CONFIG_LEDS_DA9052) += leds-da9052.o |
| 40 | obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o | 41 | obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o |
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index 232b3ce902e5..5f588c0a376e 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c | |||
| @@ -157,7 +157,7 @@ static int pm860x_led_dt_init(struct platform_device *pdev, | |||
| 157 | static int pm860x_led_probe(struct platform_device *pdev) | 157 | static int pm860x_led_probe(struct platform_device *pdev) |
| 158 | { | 158 | { |
| 159 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | 159 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); |
| 160 | struct pm860x_led_pdata *pdata = pdev->dev.platform_data; | 160 | struct pm860x_led_pdata *pdata = dev_get_platdata(&pdev->dev); |
| 161 | struct pm860x_led *data; | 161 | struct pm860x_led *data; |
| 162 | struct resource *res; | 162 | struct resource *res; |
| 163 | int ret = 0; | 163 | int ret = 0; |
diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c index e8072abe76e5..7e311a120b11 100644 --- a/drivers/leds/leds-adp5520.c +++ b/drivers/leds/leds-adp5520.c | |||
| @@ -87,7 +87,7 @@ static int adp5520_led_setup(struct adp5520_led *led) | |||
| 87 | 87 | ||
| 88 | static int adp5520_led_prepare(struct platform_device *pdev) | 88 | static int adp5520_led_prepare(struct platform_device *pdev) |
| 89 | { | 89 | { |
| 90 | struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data; | 90 | struct adp5520_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 91 | struct device *dev = pdev->dev.parent; | 91 | struct device *dev = pdev->dev.parent; |
| 92 | int ret = 0; | 92 | int ret = 0; |
| 93 | 93 | ||
| @@ -103,7 +103,7 @@ static int adp5520_led_prepare(struct platform_device *pdev) | |||
| 103 | 103 | ||
| 104 | static int adp5520_led_probe(struct platform_device *pdev) | 104 | static int adp5520_led_probe(struct platform_device *pdev) |
| 105 | { | 105 | { |
| 106 | struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data; | 106 | struct adp5520_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 107 | struct adp5520_led *led, *led_dat; | 107 | struct adp5520_led *led, *led_dat; |
| 108 | struct led_info *cur_led; | 108 | struct led_info *cur_led; |
| 109 | int ret, i; | 109 | int ret, i; |
| @@ -185,7 +185,7 @@ err: | |||
| 185 | 185 | ||
| 186 | static int adp5520_led_remove(struct platform_device *pdev) | 186 | static int adp5520_led_remove(struct platform_device *pdev) |
| 187 | { | 187 | { |
| 188 | struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data; | 188 | struct adp5520_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 189 | struct adp5520_led *led; | 189 | struct adp5520_led *led; |
| 190 | int i; | 190 | int i; |
| 191 | 191 | ||
diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c index cf9efe421c2b..6de216a89a0c 100644 --- a/drivers/leds/leds-asic3.c +++ b/drivers/leds/leds-asic3.c | |||
| @@ -94,7 +94,7 @@ static int blink_set(struct led_classdev *cdev, | |||
| 94 | 94 | ||
| 95 | static int asic3_led_probe(struct platform_device *pdev) | 95 | static int asic3_led_probe(struct platform_device *pdev) |
| 96 | { | 96 | { |
| 97 | struct asic3_led *led = pdev->dev.platform_data; | 97 | struct asic3_led *led = dev_get_platdata(&pdev->dev); |
| 98 | int ret; | 98 | int ret; |
| 99 | 99 | ||
| 100 | ret = mfd_cell_enable(pdev); | 100 | ret = mfd_cell_enable(pdev); |
| @@ -127,7 +127,7 @@ out: | |||
| 127 | 127 | ||
| 128 | static int asic3_led_remove(struct platform_device *pdev) | 128 | static int asic3_led_remove(struct platform_device *pdev) |
| 129 | { | 129 | { |
| 130 | struct asic3_led *led = pdev->dev.platform_data; | 130 | struct asic3_led *led = dev_get_platdata(&pdev->dev); |
| 131 | 131 | ||
| 132 | led_classdev_unregister(led->cdev); | 132 | led_classdev_unregister(led->cdev); |
| 133 | 133 | ||
diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c index 90518f84b9c0..56cec8d6a2ac 100644 --- a/drivers/leds/leds-atmel-pwm.c +++ b/drivers/leds/leds-atmel-pwm.c | |||
| @@ -42,7 +42,7 @@ static int pwmled_probe(struct platform_device *pdev) | |||
| 42 | int i; | 42 | int i; |
| 43 | int status; | 43 | int status; |
| 44 | 44 | ||
| 45 | pdata = pdev->dev.platform_data; | 45 | pdata = dev_get_platdata(&pdev->dev); |
| 46 | if (!pdata || pdata->num_leds < 1) | 46 | if (!pdata || pdata->num_leds < 1) |
| 47 | return -ENODEV; | 47 | return -ENODEV; |
| 48 | 48 | ||
| @@ -119,7 +119,7 @@ static int pwmled_remove(struct platform_device *pdev) | |||
| 119 | struct pwmled *leds; | 119 | struct pwmled *leds; |
| 120 | unsigned i; | 120 | unsigned i; |
| 121 | 121 | ||
| 122 | pdata = pdev->dev.platform_data; | 122 | pdata = dev_get_platdata(&pdev->dev); |
| 123 | leds = platform_get_drvdata(pdev); | 123 | leds = platform_get_drvdata(pdev); |
| 124 | 124 | ||
| 125 | for (i = 0; i < pdata->num_leds; i++) { | 125 | for (i = 0; i < pdata->num_leds; i++) { |
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index 2db04231a792..fb5a3472d614 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c | |||
| @@ -684,7 +684,7 @@ static int bd2802_probe(struct i2c_client *client, | |||
| 684 | } | 684 | } |
| 685 | 685 | ||
| 686 | led->client = client; | 686 | led->client = client; |
| 687 | pdata = led->pdata = client->dev.platform_data; | 687 | pdata = led->pdata = dev_get_platdata(&client->dev); |
| 688 | i2c_set_clientdata(client, led); | 688 | i2c_set_clientdata(client, led); |
| 689 | 689 | ||
| 690 | /* Configure RESET GPIO (L: RESET, H: RESET cancel) */ | 690 | /* Configure RESET GPIO (L: RESET, H: RESET cancel) */ |
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c index 6a8405df76a3..d93e2455da5c 100644 --- a/drivers/leds/leds-clevo-mail.c +++ b/drivers/leds/leds-clevo-mail.c | |||
| @@ -40,7 +40,7 @@ static int __init clevo_mail_led_dmi_callback(const struct dmi_system_id *id) | |||
| 40 | * detected as working, but in reality it is not) as low as | 40 | * detected as working, but in reality it is not) as low as |
| 41 | * possible. | 41 | * possible. |
| 42 | */ | 42 | */ |
| 43 | static struct dmi_system_id __initdata clevo_mail_led_dmi_table[] = { | 43 | static struct dmi_system_id clevo_mail_led_dmi_table[] __initdata = { |
| 44 | { | 44 | { |
| 45 | .callback = clevo_mail_led_dmi_callback, | 45 | .callback = clevo_mail_led_dmi_callback, |
| 46 | .ident = "Clevo D410J", | 46 | .ident = "Clevo D410J", |
diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c index c263a21db829..2a4b87f8091a 100644 --- a/drivers/leds/leds-da903x.c +++ b/drivers/leds/leds-da903x.c | |||
| @@ -93,7 +93,7 @@ static void da903x_led_set(struct led_classdev *led_cdev, | |||
| 93 | 93 | ||
| 94 | static int da903x_led_probe(struct platform_device *pdev) | 94 | static int da903x_led_probe(struct platform_device *pdev) |
| 95 | { | 95 | { |
| 96 | struct led_info *pdata = pdev->dev.platform_data; | 96 | struct led_info *pdata = dev_get_platdata(&pdev->dev); |
| 97 | struct da903x_led *led; | 97 | struct da903x_led *led; |
| 98 | int id, ret; | 98 | int id, ret; |
| 99 | 99 | ||
diff --git a/drivers/leds/leds-da9052.c b/drivers/leds/leds-da9052.c index efec43344e9f..865d4faf874a 100644 --- a/drivers/leds/leds-da9052.c +++ b/drivers/leds/leds-da9052.c | |||
| @@ -112,7 +112,7 @@ static int da9052_led_probe(struct platform_device *pdev) | |||
| 112 | int i; | 112 | int i; |
| 113 | 113 | ||
| 114 | da9052 = dev_get_drvdata(pdev->dev.parent); | 114 | da9052 = dev_get_drvdata(pdev->dev.parent); |
| 115 | pdata = da9052->dev->platform_data; | 115 | pdata = dev_get_platdata(da9052->dev); |
| 116 | if (pdata == NULL) { | 116 | if (pdata == NULL) { |
| 117 | dev_err(&pdev->dev, "No platform data\n"); | 117 | dev_err(&pdev->dev, "No platform data\n"); |
| 118 | goto err; | 118 | goto err; |
| @@ -185,7 +185,7 @@ static int da9052_led_remove(struct platform_device *pdev) | |||
| 185 | int i; | 185 | int i; |
| 186 | 186 | ||
| 187 | da9052 = dev_get_drvdata(pdev->dev.parent); | 187 | da9052 = dev_get_drvdata(pdev->dev.parent); |
| 188 | pdata = da9052->dev->platform_data; | 188 | pdata = dev_get_platdata(da9052->dev); |
| 189 | pled = pdata->pled; | 189 | pled = pdata->pled; |
| 190 | 190 | ||
| 191 | for (i = 0; i < pled->num_leds; i++) { | 191 | for (i = 0; i < pled->num_leds; i++) { |
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 84d74c373cae..e8b01e57348d 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c | |||
| @@ -233,7 +233,7 @@ static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev) | |||
| 233 | 233 | ||
| 234 | static int gpio_led_probe(struct platform_device *pdev) | 234 | static int gpio_led_probe(struct platform_device *pdev) |
| 235 | { | 235 | { |
| 236 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; | 236 | struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 237 | struct gpio_leds_priv *priv; | 237 | struct gpio_leds_priv *priv; |
| 238 | int i, ret = 0; | 238 | int i, ret = 0; |
| 239 | 239 | ||
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c index a036a19040fe..652368c2ea9a 100644 --- a/drivers/leds/leds-lm3530.c +++ b/drivers/leds/leds-lm3530.c | |||
| @@ -403,7 +403,7 @@ static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set); | |||
| 403 | static int lm3530_probe(struct i2c_client *client, | 403 | static int lm3530_probe(struct i2c_client *client, |
| 404 | const struct i2c_device_id *id) | 404 | const struct i2c_device_id *id) |
| 405 | { | 405 | { |
| 406 | struct lm3530_platform_data *pdata = client->dev.platform_data; | 406 | struct lm3530_platform_data *pdata = dev_get_platdata(&client->dev); |
| 407 | struct lm3530_data *drvdata; | 407 | struct lm3530_data *drvdata; |
| 408 | int err = 0; | 408 | int err = 0; |
| 409 | 409 | ||
diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c index bbf24d038a7f..027ede73b80d 100644 --- a/drivers/leds/leds-lm3533.c +++ b/drivers/leds/leds-lm3533.c | |||
| @@ -671,7 +671,7 @@ static int lm3533_led_probe(struct platform_device *pdev) | |||
| 671 | if (!lm3533) | 671 | if (!lm3533) |
| 672 | return -EINVAL; | 672 | return -EINVAL; |
| 673 | 673 | ||
| 674 | pdata = pdev->dev.platform_data; | 674 | pdata = dev_get_platdata(&pdev->dev); |
| 675 | if (!pdata) { | 675 | if (!pdata) { |
| 676 | dev_err(&pdev->dev, "no platform data\n"); | 676 | dev_err(&pdev->dev, "no platform data\n"); |
| 677 | return -EINVAL; | 677 | return -EINVAL; |
diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c index d81a8e7afd6c..591eb5e58ae3 100644 --- a/drivers/leds/leds-lm355x.c +++ b/drivers/leds/leds-lm355x.c | |||
| @@ -423,7 +423,7 @@ static const struct regmap_config lm355x_regmap = { | |||
| 423 | static int lm355x_probe(struct i2c_client *client, | 423 | static int lm355x_probe(struct i2c_client *client, |
| 424 | const struct i2c_device_id *id) | 424 | const struct i2c_device_id *id) |
| 425 | { | 425 | { |
| 426 | struct lm355x_platform_data *pdata = client->dev.platform_data; | 426 | struct lm355x_platform_data *pdata = dev_get_platdata(&client->dev); |
| 427 | struct lm355x_chip_data *chip; | 427 | struct lm355x_chip_data *chip; |
| 428 | 428 | ||
| 429 | int err; | 429 | int err; |
diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c index f361bbef2dec..ceb6b3cde6fe 100644 --- a/drivers/leds/leds-lm3642.c +++ b/drivers/leds/leds-lm3642.c | |||
| @@ -316,7 +316,7 @@ static const struct regmap_config lm3642_regmap = { | |||
| 316 | static int lm3642_probe(struct i2c_client *client, | 316 | static int lm3642_probe(struct i2c_client *client, |
| 317 | const struct i2c_device_id *id) | 317 | const struct i2c_device_id *id) |
| 318 | { | 318 | { |
| 319 | struct lm3642_platform_data *pdata = client->dev.platform_data; | 319 | struct lm3642_platform_data *pdata = dev_get_platdata(&client->dev); |
| 320 | struct lm3642_chip_data *chip; | 320 | struct lm3642_chip_data *chip; |
| 321 | 321 | ||
| 322 | int err; | 322 | int err; |
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c index 0c4386e656c1..8e1abdcd4c9d 100644 --- a/drivers/leds/leds-lp3944.c +++ b/drivers/leds/leds-lp3944.c | |||
| @@ -289,7 +289,7 @@ static void lp3944_led_set_brightness(struct led_classdev *led_cdev, | |||
| 289 | dev_dbg(&led->client->dev, "%s: %s, %d\n", | 289 | dev_dbg(&led->client->dev, "%s: %s, %d\n", |
| 290 | __func__, led_cdev->name, brightness); | 290 | __func__, led_cdev->name, brightness); |
| 291 | 291 | ||
| 292 | led->status = brightness; | 292 | led->status = !!brightness; |
| 293 | schedule_work(&led->work); | 293 | schedule_work(&led->work); |
| 294 | } | 294 | } |
| 295 | 295 | ||
| @@ -377,7 +377,8 @@ exit: | |||
| 377 | static int lp3944_probe(struct i2c_client *client, | 377 | static int lp3944_probe(struct i2c_client *client, |
| 378 | const struct i2c_device_id *id) | 378 | const struct i2c_device_id *id) |
| 379 | { | 379 | { |
| 380 | struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data; | 380 | struct lp3944_platform_data *lp3944_pdata = |
| 381 | dev_get_platdata(&client->dev); | ||
| 381 | struct lp3944_data *data; | 382 | struct lp3944_data *data; |
| 382 | int err; | 383 | int err; |
| 383 | 384 | ||
| @@ -413,7 +414,7 @@ static int lp3944_probe(struct i2c_client *client, | |||
| 413 | 414 | ||
| 414 | static int lp3944_remove(struct i2c_client *client) | 415 | static int lp3944_remove(struct i2c_client *client) |
| 415 | { | 416 | { |
| 416 | struct lp3944_platform_data *pdata = client->dev.platform_data; | 417 | struct lp3944_platform_data *pdata = dev_get_platdata(&client->dev); |
| 417 | struct lp3944_data *data = i2c_get_clientdata(client); | 418 | struct lp3944_data *data = i2c_get_clientdata(client); |
| 418 | int i; | 419 | int i; |
| 419 | 420 | ||
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 1392feb1bcf7..05188351711d 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c | |||
| @@ -220,17 +220,11 @@ static int lp5521_update_program_memory(struct lp55xx_chip *chip, | |||
| 220 | }; | 220 | }; |
| 221 | unsigned cmd; | 221 | unsigned cmd; |
| 222 | char c[3]; | 222 | char c[3]; |
| 223 | int program_size; | ||
| 224 | int nrchars; | 223 | int nrchars; |
| 225 | int offset = 0; | ||
| 226 | int ret; | 224 | int ret; |
| 227 | int i; | 225 | int offset = 0; |
| 228 | 226 | int i = 0; | |
| 229 | /* clear program memory before updating */ | ||
| 230 | for (i = 0; i < LP5521_PROGRAM_LENGTH; i++) | ||
| 231 | lp55xx_write(chip, addr[idx] + i, 0); | ||
| 232 | 227 | ||
| 233 | i = 0; | ||
| 234 | while ((offset < size - 1) && (i < LP5521_PROGRAM_LENGTH)) { | 228 | while ((offset < size - 1) && (i < LP5521_PROGRAM_LENGTH)) { |
| 235 | /* separate sscanfs because length is working only for %s */ | 229 | /* separate sscanfs because length is working only for %s */ |
| 236 | ret = sscanf(data + offset, "%2s%n ", c, &nrchars); | 230 | ret = sscanf(data + offset, "%2s%n ", c, &nrchars); |
| @@ -250,11 +244,19 @@ static int lp5521_update_program_memory(struct lp55xx_chip *chip, | |||
| 250 | if (i % 2) | 244 | if (i % 2) |
| 251 | goto err; | 245 | goto err; |
| 252 | 246 | ||
| 253 | program_size = i; | 247 | mutex_lock(&chip->lock); |
| 254 | for (i = 0; i < program_size; i++) | ||
| 255 | lp55xx_write(chip, addr[idx] + i, pattern[i]); | ||
| 256 | 248 | ||
| 257 | return 0; | 249 | for (i = 0; i < LP5521_PROGRAM_LENGTH; i++) { |
| 250 | ret = lp55xx_write(chip, addr[idx] + i, pattern[i]); | ||
| 251 | if (ret) { | ||
| 252 | mutex_unlock(&chip->lock); | ||
| 253 | return -EINVAL; | ||
| 254 | } | ||
| 255 | } | ||
| 256 | |||
| 257 | mutex_unlock(&chip->lock); | ||
| 258 | |||
| 259 | return size; | ||
| 258 | 260 | ||
| 259 | err: | 261 | err: |
| 260 | dev_err(&chip->cl->dev, "wrong pattern format\n"); | 262 | dev_err(&chip->cl->dev, "wrong pattern format\n"); |
| @@ -365,6 +367,80 @@ static void lp5521_led_brightness_work(struct work_struct *work) | |||
| 365 | mutex_unlock(&chip->lock); | 367 | mutex_unlock(&chip->lock); |
| 366 | } | 368 | } |
| 367 | 369 | ||
| 370 | static ssize_t show_engine_mode(struct device *dev, | ||
| 371 | struct device_attribute *attr, | ||
| 372 | char *buf, int nr) | ||
| 373 | { | ||
| 374 | struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); | ||
| 375 | struct lp55xx_chip *chip = led->chip; | ||
| 376 | enum lp55xx_engine_mode mode = chip->engines[nr - 1].mode; | ||
| 377 | |||
| 378 | switch (mode) { | ||
| 379 | case LP55XX_ENGINE_RUN: | ||
| 380 | return sprintf(buf, "run\n"); | ||
| 381 | case LP55XX_ENGINE_LOAD: | ||
| 382 | return sprintf(buf, "load\n"); | ||
| 383 | case LP55XX_ENGINE_DISABLED: | ||
| 384 | default: | ||
| 385 | return sprintf(buf, "disabled\n"); | ||
| 386 | } | ||
| 387 | } | ||
| 388 | show_mode(1) | ||
| 389 | show_mode(2) | ||
| 390 | show_mode(3) | ||
| 391 | |||
| 392 | static ssize_t store_engine_mode(struct device *dev, | ||
| 393 | struct device_attribute *attr, | ||
| 394 | const char *buf, size_t len, int nr) | ||
| 395 | { | ||
| 396 | struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); | ||
| 397 | struct lp55xx_chip *chip = led->chip; | ||
| 398 | struct lp55xx_engine *engine = &chip->engines[nr - 1]; | ||
| 399 | |||
| 400 | mutex_lock(&chip->lock); | ||
| 401 | |||
| 402 | chip->engine_idx = nr; | ||
| 403 | |||
| 404 | if (!strncmp(buf, "run", 3)) { | ||
| 405 | lp5521_run_engine(chip, true); | ||
| 406 | engine->mode = LP55XX_ENGINE_RUN; | ||
| 407 | } else if (!strncmp(buf, "load", 4)) { | ||
| 408 | lp5521_stop_engine(chip); | ||
| 409 | lp5521_load_engine(chip); | ||
| 410 | engine->mode = LP55XX_ENGINE_LOAD; | ||
| 411 | } else if (!strncmp(buf, "disabled", 8)) { | ||
| 412 | lp5521_stop_engine(chip); | ||
| 413 | engine->mode = LP55XX_ENGINE_DISABLED; | ||
| 414 | } | ||
| 415 | |||
| 416 | mutex_unlock(&chip->lock); | ||
| 417 | |||
| 418 | return len; | ||
| 419 | } | ||
| 420 | store_mode(1) | ||
| 421 | store_mode(2) | ||
| 422 | store_mode(3) | ||
| 423 | |||
| 424 | static ssize_t store_engine_load(struct device *dev, | ||
| 425 | struct device_attribute *attr, | ||
| 426 | const char *buf, size_t len, int nr) | ||
| 427 | { | ||
| 428 | struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); | ||
| 429 | struct lp55xx_chip *chip = led->chip; | ||
| 430 | |||
| 431 | mutex_lock(&chip->lock); | ||
| 432 | |||
| 433 | chip->engine_idx = nr; | ||
| 434 | lp5521_load_engine(chip); | ||
| 435 | |||
| 436 | mutex_unlock(&chip->lock); | ||
| 437 | |||
| 438 | return lp5521_update_program_memory(chip, buf, len); | ||
| 439 | } | ||
| 440 | store_load(1) | ||
| 441 | store_load(2) | ||
| 442 | store_load(3) | ||
| 443 | |||
| 368 | static ssize_t lp5521_selftest(struct device *dev, | 444 | static ssize_t lp5521_selftest(struct device *dev, |
| 369 | struct device_attribute *attr, | 445 | struct device_attribute *attr, |
| 370 | char *buf) | 446 | char *buf) |
| @@ -381,9 +457,21 @@ static ssize_t lp5521_selftest(struct device *dev, | |||
| 381 | } | 457 | } |
| 382 | 458 | ||
| 383 | /* device attributes */ | 459 | /* device attributes */ |
| 384 | static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL); | 460 | static LP55XX_DEV_ATTR_RW(engine1_mode, show_engine1_mode, store_engine1_mode); |
| 461 | static LP55XX_DEV_ATTR_RW(engine2_mode, show_engine2_mode, store_engine2_mode); | ||
| 462 | static LP55XX_DEV_ATTR_RW(engine3_mode, show_engine3_mode, store_engine3_mode); | ||
| 463 | static LP55XX_DEV_ATTR_WO(engine1_load, store_engine1_load); | ||
| 464 | static LP55XX_DEV_ATTR_WO(engine2_load, store_engine2_load); | ||
| 465 | static LP55XX_DEV_ATTR_WO(engine3_load, store_engine3_load); | ||
| 466 | static LP55XX_DEV_ATTR_RO(selftest, lp5521_selftest); | ||
| 385 | 467 | ||
| 386 | static struct attribute *lp5521_attributes[] = { | 468 | static struct attribute *lp5521_attributes[] = { |
| 469 | &dev_attr_engine1_mode.attr, | ||
| 470 | &dev_attr_engine2_mode.attr, | ||
| 471 | &dev_attr_engine3_mode.attr, | ||
| 472 | &dev_attr_engine1_load.attr, | ||
| 473 | &dev_attr_engine2_load.attr, | ||
| 474 | &dev_attr_engine3_load.attr, | ||
| 387 | &dev_attr_selftest.attr, | 475 | &dev_attr_selftest.attr, |
| 388 | NULL | 476 | NULL |
| 389 | }; | 477 | }; |
| @@ -420,7 +508,7 @@ static int lp5521_probe(struct i2c_client *client, | |||
| 420 | struct lp55xx_platform_data *pdata; | 508 | struct lp55xx_platform_data *pdata; |
| 421 | struct device_node *np = client->dev.of_node; | 509 | struct device_node *np = client->dev.of_node; |
| 422 | 510 | ||
| 423 | if (!client->dev.platform_data) { | 511 | if (!dev_get_platdata(&client->dev)) { |
| 424 | if (np) { | 512 | if (np) { |
| 425 | ret = lp55xx_of_populate_pdata(&client->dev, np); | 513 | ret = lp55xx_of_populate_pdata(&client->dev, np); |
| 426 | if (ret < 0) | 514 | if (ret < 0) |
| @@ -430,7 +518,7 @@ static int lp5521_probe(struct i2c_client *client, | |||
| 430 | return -EINVAL; | 518 | return -EINVAL; |
| 431 | } | 519 | } |
| 432 | } | 520 | } |
| 433 | pdata = client->dev.platform_data; | 521 | pdata = dev_get_platdata(&client->dev); |
| 434 | 522 | ||
| 435 | chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); | 523 | chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); |
| 436 | if (!chip) | 524 | if (!chip) |
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index 3979428f3100..fe3bcbb5747f 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c | |||
| @@ -49,6 +49,9 @@ | |||
| 49 | #define LP5523_REG_RESET 0x3D | 49 | #define LP5523_REG_RESET 0x3D |
| 50 | #define LP5523_REG_LED_TEST_CTRL 0x41 | 50 | #define LP5523_REG_LED_TEST_CTRL 0x41 |
| 51 | #define LP5523_REG_LED_TEST_ADC 0x42 | 51 | #define LP5523_REG_LED_TEST_ADC 0x42 |
| 52 | #define LP5523_REG_CH1_PROG_START 0x4C | ||
| 53 | #define LP5523_REG_CH2_PROG_START 0x4D | ||
| 54 | #define LP5523_REG_CH3_PROG_START 0x4E | ||
| 52 | #define LP5523_REG_PROG_PAGE_SEL 0x4F | 55 | #define LP5523_REG_PROG_PAGE_SEL 0x4F |
| 53 | #define LP5523_REG_PROG_MEM 0x50 | 56 | #define LP5523_REG_PROG_MEM 0x50 |
| 54 | 57 | ||
| @@ -65,11 +68,15 @@ | |||
| 65 | #define LP5523_RESET 0xFF | 68 | #define LP5523_RESET 0xFF |
| 66 | #define LP5523_ADC_SHORTCIRC_LIM 80 | 69 | #define LP5523_ADC_SHORTCIRC_LIM 80 |
| 67 | #define LP5523_EXT_CLK_USED 0x08 | 70 | #define LP5523_EXT_CLK_USED 0x08 |
| 71 | #define LP5523_ENG_STATUS_MASK 0x07 | ||
| 68 | 72 | ||
| 69 | /* Memory Page Selection */ | 73 | /* Memory Page Selection */ |
| 70 | #define LP5523_PAGE_ENG1 0 | 74 | #define LP5523_PAGE_ENG1 0 |
| 71 | #define LP5523_PAGE_ENG2 1 | 75 | #define LP5523_PAGE_ENG2 1 |
| 72 | #define LP5523_PAGE_ENG3 2 | 76 | #define LP5523_PAGE_ENG3 2 |
| 77 | #define LP5523_PAGE_MUX1 3 | ||
| 78 | #define LP5523_PAGE_MUX2 4 | ||
| 79 | #define LP5523_PAGE_MUX3 5 | ||
| 73 | 80 | ||
| 74 | /* Program Memory Operations */ | 81 | /* Program Memory Operations */ |
| 75 | #define LP5523_MODE_ENG1_M 0x30 /* Operation Mode Register */ | 82 | #define LP5523_MODE_ENG1_M 0x30 /* Operation Mode Register */ |
| @@ -94,11 +101,15 @@ | |||
| 94 | #define LP5523_RUN_ENG2 0x08 | 101 | #define LP5523_RUN_ENG2 0x08 |
| 95 | #define LP5523_RUN_ENG3 0x02 | 102 | #define LP5523_RUN_ENG3 0x02 |
| 96 | 103 | ||
| 104 | #define LED_ACTIVE(mux, led) (!!(mux & (0x0001 << led))) | ||
| 105 | |||
| 97 | enum lp5523_chip_id { | 106 | enum lp5523_chip_id { |
| 98 | LP5523, | 107 | LP5523, |
| 99 | LP55231, | 108 | LP55231, |
| 100 | }; | 109 | }; |
| 101 | 110 | ||
| 111 | static int lp5523_init_program_engine(struct lp55xx_chip *chip); | ||
| 112 | |||
| 102 | static inline void lp5523_wait_opmode_done(void) | 113 | static inline void lp5523_wait_opmode_done(void) |
| 103 | { | 114 | { |
| 104 | usleep_range(1000, 2000); | 115 | usleep_range(1000, 2000); |
| @@ -134,7 +145,11 @@ static int lp5523_post_init_device(struct lp55xx_chip *chip) | |||
| 134 | if (ret) | 145 | if (ret) |
| 135 | return ret; | 146 | return ret; |
| 136 | 147 | ||
| 137 | return lp55xx_write(chip, LP5523_REG_ENABLE_LEDS_LSB, 0xff); | 148 | ret = lp55xx_write(chip, LP5523_REG_ENABLE_LEDS_LSB, 0xff); |
| 149 | if (ret) | ||
| 150 | return ret; | ||
| 151 | |||
| 152 | return lp5523_init_program_engine(chip); | ||
| 138 | } | 153 | } |
| 139 | 154 | ||
| 140 | static void lp5523_load_engine(struct lp55xx_chip *chip) | 155 | static void lp5523_load_engine(struct lp55xx_chip *chip) |
| @@ -152,15 +167,21 @@ static void lp5523_load_engine(struct lp55xx_chip *chip) | |||
| 152 | [LP55XX_ENGINE_3] = LP5523_LOAD_ENG3, | 167 | [LP55XX_ENGINE_3] = LP5523_LOAD_ENG3, |
| 153 | }; | 168 | }; |
| 154 | 169 | ||
| 170 | lp55xx_update_bits(chip, LP5523_REG_OP_MODE, mask[idx], val[idx]); | ||
| 171 | |||
| 172 | lp5523_wait_opmode_done(); | ||
| 173 | } | ||
| 174 | |||
| 175 | static void lp5523_load_engine_and_select_page(struct lp55xx_chip *chip) | ||
| 176 | { | ||
| 177 | enum lp55xx_engine_index idx = chip->engine_idx; | ||
| 155 | u8 page_sel[] = { | 178 | u8 page_sel[] = { |
| 156 | [LP55XX_ENGINE_1] = LP5523_PAGE_ENG1, | 179 | [LP55XX_ENGINE_1] = LP5523_PAGE_ENG1, |
| 157 | [LP55XX_ENGINE_2] = LP5523_PAGE_ENG2, | 180 | [LP55XX_ENGINE_2] = LP5523_PAGE_ENG2, |
| 158 | [LP55XX_ENGINE_3] = LP5523_PAGE_ENG3, | 181 | [LP55XX_ENGINE_3] = LP5523_PAGE_ENG3, |
| 159 | }; | 182 | }; |
| 160 | 183 | ||
| 161 | lp55xx_update_bits(chip, LP5523_REG_OP_MODE, mask[idx], val[idx]); | 184 | lp5523_load_engine(chip); |
| 162 | |||
| 163 | lp5523_wait_opmode_done(); | ||
| 164 | 185 | ||
| 165 | lp55xx_write(chip, LP5523_REG_PROG_PAGE_SEL, page_sel[idx]); | 186 | lp55xx_write(chip, LP5523_REG_PROG_PAGE_SEL, page_sel[idx]); |
| 166 | } | 187 | } |
| @@ -227,23 +248,75 @@ static void lp5523_run_engine(struct lp55xx_chip *chip, bool start) | |||
| 227 | lp55xx_update_bits(chip, LP5523_REG_ENABLE, LP5523_EXEC_M, exec); | 248 | lp55xx_update_bits(chip, LP5523_REG_ENABLE, LP5523_EXEC_M, exec); |
| 228 | } | 249 | } |
| 229 | 250 | ||
| 251 | static int lp5523_init_program_engine(struct lp55xx_chip *chip) | ||
| 252 | { | ||
| 253 | int i; | ||
| 254 | int j; | ||
| 255 | int ret; | ||
| 256 | u8 status; | ||
| 257 | /* one pattern per engine setting LED MUX start and stop addresses */ | ||
| 258 | static const u8 pattern[][LP5523_PROGRAM_LENGTH] = { | ||
| 259 | { 0x9c, 0x30, 0x9c, 0xb0, 0x9d, 0x80, 0xd8, 0x00, 0}, | ||
| 260 | { 0x9c, 0x40, 0x9c, 0xc0, 0x9d, 0x80, 0xd8, 0x00, 0}, | ||
| 261 | { 0x9c, 0x50, 0x9c, 0xd0, 0x9d, 0x80, 0xd8, 0x00, 0}, | ||
| 262 | }; | ||
| 263 | |||
| 264 | /* hardcode 32 bytes of memory for each engine from program memory */ | ||
| 265 | ret = lp55xx_write(chip, LP5523_REG_CH1_PROG_START, 0x00); | ||
| 266 | if (ret) | ||
| 267 | return ret; | ||
| 268 | |||
| 269 | ret = lp55xx_write(chip, LP5523_REG_CH2_PROG_START, 0x10); | ||
| 270 | if (ret) | ||
| 271 | return ret; | ||
| 272 | |||
| 273 | ret = lp55xx_write(chip, LP5523_REG_CH3_PROG_START, 0x20); | ||
| 274 | if (ret) | ||
| 275 | return ret; | ||
| 276 | |||
| 277 | /* write LED MUX address space for each engine */ | ||
| 278 | for (i = LP55XX_ENGINE_1; i <= LP55XX_ENGINE_3; i++) { | ||
| 279 | chip->engine_idx = i; | ||
| 280 | lp5523_load_engine_and_select_page(chip); | ||
| 281 | |||
| 282 | for (j = 0; j < LP5523_PROGRAM_LENGTH; j++) { | ||
| 283 | ret = lp55xx_write(chip, LP5523_REG_PROG_MEM + j, | ||
| 284 | pattern[i - 1][j]); | ||
| 285 | if (ret) | ||
| 286 | goto out; | ||
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | lp5523_run_engine(chip, true); | ||
| 291 | |||
| 292 | /* Let the programs run for couple of ms and check the engine status */ | ||
| 293 | usleep_range(3000, 6000); | ||
| 294 | lp55xx_read(chip, LP5523_REG_STATUS, &status); | ||
| 295 | status &= LP5523_ENG_STATUS_MASK; | ||
| 296 | |||
| 297 | if (status != LP5523_ENG_STATUS_MASK) { | ||
| 298 | dev_err(&chip->cl->dev, | ||
| 299 | "cound not configure LED engine, status = 0x%.2x\n", | ||
| 300 | status); | ||
| 301 | ret = -1; | ||
| 302 | } | ||
| 303 | |||
| 304 | out: | ||
| 305 | lp5523_stop_engine(chip); | ||
| 306 | return ret; | ||
| 307 | } | ||
| 308 | |||
| 230 | static int lp5523_update_program_memory(struct lp55xx_chip *chip, | 309 | static int lp5523_update_program_memory(struct lp55xx_chip *chip, |
| 231 | const u8 *data, size_t size) | 310 | const u8 *data, size_t size) |
| 232 | { | 311 | { |
| 233 | u8 pattern[LP5523_PROGRAM_LENGTH] = {0}; | 312 | u8 pattern[LP5523_PROGRAM_LENGTH] = {0}; |
| 234 | unsigned cmd; | 313 | unsigned cmd; |
| 235 | char c[3]; | 314 | char c[3]; |
| 236 | int update_size; | ||
| 237 | int nrchars; | 315 | int nrchars; |
| 238 | int offset = 0; | ||
| 239 | int ret; | 316 | int ret; |
| 240 | int i; | 317 | int offset = 0; |
| 241 | 318 | int i = 0; | |
| 242 | /* clear program memory before updating */ | ||
| 243 | for (i = 0; i < LP5523_PROGRAM_LENGTH; i++) | ||
| 244 | lp55xx_write(chip, LP5523_REG_PROG_MEM + i, 0); | ||
| 245 | 319 | ||
| 246 | i = 0; | ||
| 247 | while ((offset < size - 1) && (i < LP5523_PROGRAM_LENGTH)) { | 320 | while ((offset < size - 1) && (i < LP5523_PROGRAM_LENGTH)) { |
| 248 | /* separate sscanfs because length is working only for %s */ | 321 | /* separate sscanfs because length is working only for %s */ |
| 249 | ret = sscanf(data + offset, "%2s%n ", c, &nrchars); | 322 | ret = sscanf(data + offset, "%2s%n ", c, &nrchars); |
| @@ -263,11 +336,19 @@ static int lp5523_update_program_memory(struct lp55xx_chip *chip, | |||
| 263 | if (i % 2) | 336 | if (i % 2) |
| 264 | goto err; | 337 | goto err; |
| 265 | 338 | ||
| 266 | update_size = i; | 339 | mutex_lock(&chip->lock); |
| 267 | for (i = 0; i < update_size; i++) | ||
| 268 | lp55xx_write(chip, LP5523_REG_PROG_MEM + i, pattern[i]); | ||
| 269 | 340 | ||
| 270 | return 0; | 341 | for (i = 0; i < LP5523_PROGRAM_LENGTH; i++) { |
| 342 | ret = lp55xx_write(chip, LP5523_REG_PROG_MEM + i, pattern[i]); | ||
| 343 | if (ret) { | ||
| 344 | mutex_unlock(&chip->lock); | ||
| 345 | return -EINVAL; | ||
| 346 | } | ||
| 347 | } | ||
| 348 | |||
| 349 | mutex_unlock(&chip->lock); | ||
| 350 | |||
| 351 | return size; | ||
| 271 | 352 | ||
| 272 | err: | 353 | err: |
| 273 | dev_err(&chip->cl->dev, "wrong pattern format\n"); | 354 | dev_err(&chip->cl->dev, "wrong pattern format\n"); |
| @@ -290,10 +371,196 @@ static void lp5523_firmware_loaded(struct lp55xx_chip *chip) | |||
| 290 | * 2) write firmware data into program memory | 371 | * 2) write firmware data into program memory |
| 291 | */ | 372 | */ |
| 292 | 373 | ||
| 293 | lp5523_load_engine(chip); | 374 | lp5523_load_engine_and_select_page(chip); |
| 294 | lp5523_update_program_memory(chip, fw->data, fw->size); | 375 | lp5523_update_program_memory(chip, fw->data, fw->size); |
| 295 | } | 376 | } |
| 296 | 377 | ||
| 378 | static ssize_t show_engine_mode(struct device *dev, | ||
| 379 | struct device_attribute *attr, | ||
| 380 | char *buf, int nr) | ||
| 381 | { | ||
| 382 | struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); | ||
| 383 | struct lp55xx_chip *chip = led->chip; | ||
| 384 | enum lp55xx_engine_mode mode = chip->engines[nr - 1].mode; | ||
| 385 | |||
| 386 | switch (mode) { | ||
| 387 | case LP55XX_ENGINE_RUN: | ||
| 388 | return sprintf(buf, "run\n"); | ||
| 389 | case LP55XX_ENGINE_LOAD: | ||
| 390 | return sprintf(buf, "load\n"); | ||
| 391 | case LP55XX_ENGINE_DISABLED: | ||
| 392 | default: | ||
| 393 | return sprintf(buf, "disabled\n"); | ||
| 394 | } | ||
| 395 | } | ||
| 396 | show_mode(1) | ||
| 397 | show_mode(2) | ||
| 398 | show_mode(3) | ||
| 399 | |||
| 400 | static ssize_t store_engine_mode(struct device *dev, | ||
| 401 | struct device_attribute *attr, | ||
| 402 | const char *buf, size_t len, int nr) | ||
| 403 | { | ||
| 404 | struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); | ||
| 405 | struct lp55xx_chip *chip = led->chip; | ||
| 406 | struct lp55xx_engine *engine = &chip->engines[nr - 1]; | ||
| 407 | |||
| 408 | mutex_lock(&chip->lock); | ||
| 409 | |||
| 410 | chip->engine_idx = nr; | ||
| 411 | |||
| 412 | if (!strncmp(buf, "run", 3)) { | ||
| 413 | lp5523_run_engine(chip, true); | ||
| 414 | engine->mode = LP55XX_ENGINE_RUN; | ||
| 415 | } else if (!strncmp(buf, "load", 4)) { | ||
| 416 | lp5523_stop_engine(chip); | ||
| 417 | lp5523_load_engine(chip); | ||
| 418 | engine->mode = LP55XX_ENGINE_LOAD; | ||
| 419 | } else if (!strncmp(buf, "disabled", 8)) { | ||
| 420 | lp5523_stop_engine(chip); | ||
| 421 | engine->mode = LP55XX_ENGINE_DISABLED; | ||
| 422 | } | ||
| 423 | |||
| 424 | mutex_unlock(&chip->lock); | ||
| 425 | |||
| 426 | return len; | ||
| 427 | } | ||
| 428 | store_mode(1) | ||
| 429 | store_mode(2) | ||
| 430 | store_mode(3) | ||
| 431 | |||
| 432 | static int lp5523_mux_parse(const char *buf, u16 *mux, size_t len) | ||
| 433 | { | ||
| 434 | u16 tmp_mux = 0; | ||
| 435 | int i; | ||
| 436 | |||
| 437 | len = min_t(int, len, LP5523_MAX_LEDS); | ||
| 438 | |||
| 439 | for (i = 0; i < len; i++) { | ||
| 440 | switch (buf[i]) { | ||
| 441 | case '1': | ||
| 442 | tmp_mux |= (1 << i); | ||
| 443 | break; | ||
| 444 | case '0': | ||
| 445 | break; | ||
| 446 | case '\n': | ||
| 447 | i = len; | ||
| 448 | break; | ||
| 449 | default: | ||
| 450 | return -1; | ||
| 451 | } | ||
| 452 | } | ||
| 453 | *mux = tmp_mux; | ||
| 454 | |||
| 455 | return 0; | ||
| 456 | } | ||
| 457 | |||
| 458 | static void lp5523_mux_to_array(u16 led_mux, char *array) | ||
| 459 | { | ||
| 460 | int i, pos = 0; | ||
| 461 | for (i = 0; i < LP5523_MAX_LEDS; i++) | ||
| 462 | pos += sprintf(array + pos, "%x", LED_ACTIVE(led_mux, i)); | ||
| 463 | |||
| 464 | array[pos] = '\0'; | ||
| 465 | } | ||
| 466 | |||
| 467 | static ssize_t show_engine_leds(struct device *dev, | ||
| 468 | struct device_attribute *attr, | ||
| 469 | char *buf, int nr) | ||
| 470 | { | ||
| 471 | struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); | ||
| 472 | struct lp55xx_chip *chip = led->chip; | ||
| 473 | char mux[LP5523_MAX_LEDS + 1]; | ||
| 474 | |||
| 475 | lp5523_mux_to_array(chip->engines[nr - 1].led_mux, mux); | ||
| 476 | |||
| 477 | return sprintf(buf, "%s\n", mux); | ||
| 478 | } | ||
| 479 | show_leds(1) | ||
| 480 | show_leds(2) | ||
| 481 | show_leds(3) | ||
| 482 | |||
| 483 | static int lp5523_load_mux(struct lp55xx_chip *chip, u16 mux, int nr) | ||
| 484 | { | ||
| 485 | struct lp55xx_engine *engine = &chip->engines[nr - 1]; | ||
| 486 | int ret; | ||
| 487 | u8 mux_page[] = { | ||
| 488 | [LP55XX_ENGINE_1] = LP5523_PAGE_MUX1, | ||
| 489 | [LP55XX_ENGINE_2] = LP5523_PAGE_MUX2, | ||
| 490 | [LP55XX_ENGINE_3] = LP5523_PAGE_MUX3, | ||
| 491 | }; | ||
| 492 | |||
| 493 | lp5523_load_engine(chip); | ||
| 494 | |||
| 495 | ret = lp55xx_write(chip, LP5523_REG_PROG_PAGE_SEL, mux_page[nr]); | ||
| 496 | if (ret) | ||
| 497 | return ret; | ||
| 498 | |||
| 499 | ret = lp55xx_write(chip, LP5523_REG_PROG_MEM , (u8)(mux >> 8)); | ||
| 500 | if (ret) | ||
| 501 | return ret; | ||
| 502 | |||
| 503 | ret = lp55xx_write(chip, LP5523_REG_PROG_MEM + 1, (u8)(mux)); | ||
| 504 | if (ret) | ||
| 505 | return ret; | ||
| 506 | |||
| 507 | engine->led_mux = mux; | ||
| 508 | return 0; | ||
| 509 | } | ||
| 510 | |||
| 511 | static ssize_t store_engine_leds(struct device *dev, | ||
| 512 | struct device_attribute *attr, | ||
| 513 | const char *buf, size_t len, int nr) | ||
| 514 | { | ||
| 515 | struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); | ||
| 516 | struct lp55xx_chip *chip = led->chip; | ||
| 517 | struct lp55xx_engine *engine = &chip->engines[nr - 1]; | ||
| 518 | u16 mux = 0; | ||
| 519 | ssize_t ret; | ||
| 520 | |||
| 521 | if (lp5523_mux_parse(buf, &mux, len)) | ||
| 522 | return -EINVAL; | ||
| 523 | |||
| 524 | mutex_lock(&chip->lock); | ||
| 525 | |||
| 526 | chip->engine_idx = nr; | ||
| 527 | ret = -EINVAL; | ||
| 528 | |||
| 529 | if (engine->mode != LP55XX_ENGINE_LOAD) | ||
| 530 | goto leave; | ||
| 531 | |||
| 532 | if (lp5523_load_mux(chip, mux, nr)) | ||
| 533 | goto leave; | ||
| 534 | |||
| 535 | ret = len; | ||
| 536 | leave: | ||
| 537 | mutex_unlock(&chip->lock); | ||
| 538 | return ret; | ||
| 539 | } | ||
| 540 | store_leds(1) | ||
| 541 | store_leds(2) | ||
| 542 | store_leds(3) | ||
| 543 | |||
| 544 | static ssize_t store_engine_load(struct device *dev, | ||
| 545 | struct device_attribute *attr, | ||
| 546 | const char *buf, size_t len, int nr) | ||
| 547 | { | ||
| 548 | struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); | ||
| 549 | struct lp55xx_chip *chip = led->chip; | ||
| 550 | |||
| 551 | mutex_lock(&chip->lock); | ||
| 552 | |||
| 553 | chip->engine_idx = nr; | ||
| 554 | lp5523_load_engine_and_select_page(chip); | ||
| 555 | |||
| 556 | mutex_unlock(&chip->lock); | ||
| 557 | |||
| 558 | return lp5523_update_program_memory(chip, buf, len); | ||
| 559 | } | ||
| 560 | store_load(1) | ||
| 561 | store_load(2) | ||
| 562 | store_load(3) | ||
| 563 | |||
| 297 | static ssize_t lp5523_selftest(struct device *dev, | 564 | static ssize_t lp5523_selftest(struct device *dev, |
| 298 | struct device_attribute *attr, | 565 | struct device_attribute *attr, |
| 299 | char *buf) | 566 | char *buf) |
| @@ -393,9 +660,27 @@ static void lp5523_led_brightness_work(struct work_struct *work) | |||
| 393 | mutex_unlock(&chip->lock); | 660 | mutex_unlock(&chip->lock); |
| 394 | } | 661 | } |
| 395 | 662 | ||
| 396 | static DEVICE_ATTR(selftest, S_IRUGO, lp5523_selftest, NULL); | 663 | static LP55XX_DEV_ATTR_RW(engine1_mode, show_engine1_mode, store_engine1_mode); |
| 664 | static LP55XX_DEV_ATTR_RW(engine2_mode, show_engine2_mode, store_engine2_mode); | ||
| 665 | static LP55XX_DEV_ATTR_RW(engine3_mode, show_engine3_mode, store_engine3_mode); | ||
| 666 | static LP55XX_DEV_ATTR_RW(engine1_leds, show_engine1_leds, store_engine1_leds); | ||
| 667 | static LP55XX_DEV_ATTR_RW(engine2_leds, show_engine2_leds, store_engine2_leds); | ||
| 668 | static LP55XX_DEV_ATTR_RW(engine3_leds, show_engine3_leds, store_engine3_leds); | ||
| 669 | static LP55XX_DEV_ATTR_WO(engine1_load, store_engine1_load); | ||
| 670 | static LP55XX_DEV_ATTR_WO(engine2_load, store_engine2_load); | ||
| 671 | static LP55XX_DEV_ATTR_WO(engine3_load, store_engine3_load); | ||
| 672 | static LP55XX_DEV_ATTR_RO(selftest, lp5523_selftest); | ||
| 397 | 673 | ||
| 398 | static struct attribute *lp5523_attributes[] = { | 674 | static struct attribute *lp5523_attributes[] = { |
| 675 | &dev_attr_engine1_mode.attr, | ||
| 676 | &dev_attr_engine2_mode.attr, | ||
| 677 | &dev_attr_engine3_mode.attr, | ||
| 678 | &dev_attr_engine1_load.attr, | ||
| 679 | &dev_attr_engine2_load.attr, | ||
| 680 | &dev_attr_engine3_load.attr, | ||
| 681 | &dev_attr_engine1_leds.attr, | ||
| 682 | &dev_attr_engine2_leds.attr, | ||
| 683 | &dev_attr_engine3_leds.attr, | ||
| 399 | &dev_attr_selftest.attr, | 684 | &dev_attr_selftest.attr, |
| 400 | NULL, | 685 | NULL, |
| 401 | }; | 686 | }; |
| @@ -432,7 +717,7 @@ static int lp5523_probe(struct i2c_client *client, | |||
| 432 | struct lp55xx_platform_data *pdata; | 717 | struct lp55xx_platform_data *pdata; |
| 433 | struct device_node *np = client->dev.of_node; | 718 | struct device_node *np = client->dev.of_node; |
| 434 | 719 | ||
| 435 | if (!client->dev.platform_data) { | 720 | if (!dev_get_platdata(&client->dev)) { |
| 436 | if (np) { | 721 | if (np) { |
| 437 | ret = lp55xx_of_populate_pdata(&client->dev, np); | 722 | ret = lp55xx_of_populate_pdata(&client->dev, np); |
| 438 | if (ret < 0) | 723 | if (ret < 0) |
| @@ -442,7 +727,7 @@ static int lp5523_probe(struct i2c_client *client, | |||
| 442 | return -EINVAL; | 727 | return -EINVAL; |
| 443 | } | 728 | } |
| 444 | } | 729 | } |
| 445 | pdata = client->dev.platform_data; | 730 | pdata = dev_get_platdata(&client->dev); |
| 446 | 731 | ||
| 447 | chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); | 732 | chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); |
| 448 | if (!chip) | 733 | if (!chip) |
diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c index cbd856dac150..2585cfd57711 100644 --- a/drivers/leds/leds-lp5562.c +++ b/drivers/leds/leds-lp5562.c | |||
| @@ -477,8 +477,8 @@ static ssize_t lp5562_store_engine_mux(struct device *dev, | |||
| 477 | return len; | 477 | return len; |
| 478 | } | 478 | } |
| 479 | 479 | ||
| 480 | static DEVICE_ATTR(led_pattern, S_IWUSR, NULL, lp5562_store_pattern); | 480 | static LP55XX_DEV_ATTR_WO(led_pattern, lp5562_store_pattern); |
| 481 | static DEVICE_ATTR(engine_mux, S_IWUSR, NULL, lp5562_store_engine_mux); | 481 | static LP55XX_DEV_ATTR_WO(engine_mux, lp5562_store_engine_mux); |
| 482 | 482 | ||
| 483 | static struct attribute *lp5562_attributes[] = { | 483 | static struct attribute *lp5562_attributes[] = { |
| 484 | &dev_attr_led_pattern.attr, | 484 | &dev_attr_led_pattern.attr, |
| @@ -518,7 +518,7 @@ static int lp5562_probe(struct i2c_client *client, | |||
| 518 | struct lp55xx_platform_data *pdata; | 518 | struct lp55xx_platform_data *pdata; |
| 519 | struct device_node *np = client->dev.of_node; | 519 | struct device_node *np = client->dev.of_node; |
| 520 | 520 | ||
| 521 | if (!client->dev.platform_data) { | 521 | if (!dev_get_platdata(&client->dev)) { |
| 522 | if (np) { | 522 | if (np) { |
| 523 | ret = lp55xx_of_populate_pdata(&client->dev, np); | 523 | ret = lp55xx_of_populate_pdata(&client->dev, np); |
| 524 | if (ret < 0) | 524 | if (ret < 0) |
| @@ -528,7 +528,7 @@ static int lp5562_probe(struct i2c_client *client, | |||
| 528 | return -EINVAL; | 528 | return -EINVAL; |
| 529 | } | 529 | } |
| 530 | } | 530 | } |
| 531 | pdata = client->dev.platform_data; | 531 | pdata = dev_get_platdata(&client->dev); |
| 532 | 532 | ||
| 533 | chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); | 533 | chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); |
| 534 | if (!chip) | 534 | if (!chip) |
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c index c2fecd4d391c..351825b96f16 100644 --- a/drivers/leds/leds-lp55xx-common.c +++ b/drivers/leds/leds-lp55xx-common.c | |||
| @@ -593,6 +593,9 @@ int lp55xx_of_populate_pdata(struct device *dev, struct device_node *np) | |||
| 593 | of_property_read_string(np, "label", &pdata->label); | 593 | of_property_read_string(np, "label", &pdata->label); |
| 594 | of_property_read_u8(np, "clock-mode", &pdata->clock_mode); | 594 | of_property_read_u8(np, "clock-mode", &pdata->clock_mode); |
| 595 | 595 | ||
| 596 | /* LP8501 specific */ | ||
| 597 | of_property_read_u8(np, "pwr-sel", (u8 *)&pdata->pwr_sel); | ||
| 598 | |||
| 596 | dev->platform_data = pdata; | 599 | dev->platform_data = pdata; |
| 597 | 600 | ||
| 598 | return 0; | 601 | return 0; |
diff --git a/drivers/leds/leds-lp55xx-common.h b/drivers/leds/leds-lp55xx-common.h index dbbf86df0f1f..cceab483edd0 100644 --- a/drivers/leds/leds-lp55xx-common.h +++ b/drivers/leds/leds-lp55xx-common.h | |||
| @@ -20,8 +20,62 @@ enum lp55xx_engine_index { | |||
| 20 | LP55XX_ENGINE_1, | 20 | LP55XX_ENGINE_1, |
| 21 | LP55XX_ENGINE_2, | 21 | LP55XX_ENGINE_2, |
| 22 | LP55XX_ENGINE_3, | 22 | LP55XX_ENGINE_3, |
| 23 | LP55XX_ENGINE_MAX = LP55XX_ENGINE_3, | ||
| 23 | }; | 24 | }; |
| 24 | 25 | ||
| 26 | enum lp55xx_engine_mode { | ||
| 27 | LP55XX_ENGINE_DISABLED, | ||
| 28 | LP55XX_ENGINE_LOAD, | ||
| 29 | LP55XX_ENGINE_RUN, | ||
| 30 | }; | ||
| 31 | |||
| 32 | #define LP55XX_DEV_ATTR_RW(name, show, store) \ | ||
| 33 | DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show, store) | ||
| 34 | #define LP55XX_DEV_ATTR_RO(name, show) \ | ||
| 35 | DEVICE_ATTR(name, S_IRUGO, show, NULL) | ||
| 36 | #define LP55XX_DEV_ATTR_WO(name, store) \ | ||
| 37 | DEVICE_ATTR(name, S_IWUSR, NULL, store) | ||
| 38 | |||
| 39 | #define show_mode(nr) \ | ||
| 40 | static ssize_t show_engine##nr##_mode(struct device *dev, \ | ||
| 41 | struct device_attribute *attr, \ | ||
| 42 | char *buf) \ | ||
| 43 | { \ | ||
| 44 | return show_engine_mode(dev, attr, buf, nr); \ | ||
| 45 | } | ||
| 46 | |||
| 47 | #define store_mode(nr) \ | ||
| 48 | static ssize_t store_engine##nr##_mode(struct device *dev, \ | ||
| 49 | struct device_attribute *attr, \ | ||
| 50 | const char *buf, size_t len) \ | ||
| 51 | { \ | ||
| 52 | return store_engine_mode(dev, attr, buf, len, nr); \ | ||
| 53 | } | ||
| 54 | |||
| 55 | #define show_leds(nr) \ | ||
| 56 | static ssize_t show_engine##nr##_leds(struct device *dev, \ | ||
| 57 | struct device_attribute *attr, \ | ||
| 58 | char *buf) \ | ||
| 59 | { \ | ||
| 60 | return show_engine_leds(dev, attr, buf, nr); \ | ||
| 61 | } | ||
| 62 | |||
| 63 | #define store_leds(nr) \ | ||
| 64 | static ssize_t store_engine##nr##_leds(struct device *dev, \ | ||
| 65 | struct device_attribute *attr, \ | ||
| 66 | const char *buf, size_t len) \ | ||
| 67 | { \ | ||
| 68 | return store_engine_leds(dev, attr, buf, len, nr); \ | ||
| 69 | } | ||
| 70 | |||
| 71 | #define store_load(nr) \ | ||
| 72 | static ssize_t store_engine##nr##_load(struct device *dev, \ | ||
| 73 | struct device_attribute *attr, \ | ||
| 74 | const char *buf, size_t len) \ | ||
| 75 | { \ | ||
| 76 | return store_engine_load(dev, attr, buf, len, nr); \ | ||
| 77 | } | ||
| 78 | |||
| 25 | struct lp55xx_led; | 79 | struct lp55xx_led; |
| 26 | struct lp55xx_chip; | 80 | struct lp55xx_chip; |
| 27 | 81 | ||
| @@ -72,6 +126,16 @@ struct lp55xx_device_config { | |||
| 72 | }; | 126 | }; |
| 73 | 127 | ||
| 74 | /* | 128 | /* |
| 129 | * struct lp55xx_engine | ||
| 130 | * @mode : Engine mode | ||
| 131 | * @led_mux : Mux bits for LED selection. Only used in LP5523 | ||
| 132 | */ | ||
| 133 | struct lp55xx_engine { | ||
| 134 | enum lp55xx_engine_mode mode; | ||
| 135 | u16 led_mux; | ||
| 136 | }; | ||
| 137 | |||
| 138 | /* | ||
| 75 | * struct lp55xx_chip | 139 | * struct lp55xx_chip |
| 76 | * @cl : I2C communication for access registers | 140 | * @cl : I2C communication for access registers |
| 77 | * @pdata : Platform specific data | 141 | * @pdata : Platform specific data |
| @@ -79,6 +143,7 @@ struct lp55xx_device_config { | |||
| 79 | * @num_leds : Number of registered LEDs | 143 | * @num_leds : Number of registered LEDs |
| 80 | * @cfg : Device specific configuration data | 144 | * @cfg : Device specific configuration data |
| 81 | * @engine_idx : Selected engine number | 145 | * @engine_idx : Selected engine number |
| 146 | * @engines : Engine structure for the device attribute R/W interface | ||
| 82 | * @fw : Firmware data for running a LED pattern | 147 | * @fw : Firmware data for running a LED pattern |
| 83 | */ | 148 | */ |
| 84 | struct lp55xx_chip { | 149 | struct lp55xx_chip { |
| @@ -89,6 +154,7 @@ struct lp55xx_chip { | |||
| 89 | int num_leds; | 154 | int num_leds; |
| 90 | struct lp55xx_device_config *cfg; | 155 | struct lp55xx_device_config *cfg; |
| 91 | enum lp55xx_engine_index engine_idx; | 156 | enum lp55xx_engine_index engine_idx; |
| 157 | struct lp55xx_engine engines[LP55XX_ENGINE_MAX]; | ||
| 92 | const struct firmware *fw; | 158 | const struct firmware *fw; |
| 93 | }; | 159 | }; |
| 94 | 160 | ||
diff --git a/drivers/leds/leds-lp8501.c b/drivers/leds/leds-lp8501.c new file mode 100644 index 000000000000..8d55a780ca46 --- /dev/null +++ b/drivers/leds/leds-lp8501.c | |||
| @@ -0,0 +1,410 @@ | |||
| 1 | /* | ||
| 2 | * TI LP8501 9 channel 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 | ||
| 9 | * modify it under the terms of the GNU General Public License | ||
| 10 | * version 2 as published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/delay.h> | ||
| 15 | #include <linux/firmware.h> | ||
| 16 | #include <linux/i2c.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/leds.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/mutex.h> | ||
| 21 | #include <linux/platform_data/leds-lp55xx.h> | ||
| 22 | #include <linux/slab.h> | ||
| 23 | |||
| 24 | #include "leds-lp55xx-common.h" | ||
| 25 | |||
| 26 | #define LP8501_PROGRAM_LENGTH 32 | ||
| 27 | #define LP8501_MAX_LEDS 9 | ||
| 28 | |||
| 29 | /* Registers */ | ||
| 30 | #define LP8501_REG_ENABLE 0x00 | ||
| 31 | #define LP8501_ENABLE BIT(6) | ||
| 32 | #define LP8501_EXEC_M 0x3F | ||
| 33 | #define LP8501_EXEC_ENG1_M 0x30 | ||
| 34 | #define LP8501_EXEC_ENG2_M 0x0C | ||
| 35 | #define LP8501_EXEC_ENG3_M 0x03 | ||
| 36 | #define LP8501_RUN_ENG1 0x20 | ||
| 37 | #define LP8501_RUN_ENG2 0x08 | ||
| 38 | #define LP8501_RUN_ENG3 0x02 | ||
| 39 | |||
| 40 | #define LP8501_REG_OP_MODE 0x01 | ||
| 41 | #define LP8501_MODE_ENG1_M 0x30 | ||
| 42 | #define LP8501_MODE_ENG2_M 0x0C | ||
| 43 | #define LP8501_MODE_ENG3_M 0x03 | ||
| 44 | #define LP8501_LOAD_ENG1 0x10 | ||
| 45 | #define LP8501_LOAD_ENG2 0x04 | ||
| 46 | #define LP8501_LOAD_ENG3 0x01 | ||
| 47 | |||
| 48 | #define LP8501_REG_PWR_CONFIG 0x05 | ||
| 49 | #define LP8501_PWR_CONFIG_M 0x03 | ||
| 50 | |||
| 51 | #define LP8501_REG_LED_PWM_BASE 0x16 | ||
| 52 | |||
| 53 | #define LP8501_REG_LED_CURRENT_BASE 0x26 | ||
| 54 | |||
| 55 | #define LP8501_REG_CONFIG 0x36 | ||
| 56 | #define LP8501_PWM_PSAVE BIT(7) | ||
| 57 | #define LP8501_AUTO_INC BIT(6) | ||
| 58 | #define LP8501_PWR_SAVE BIT(5) | ||
| 59 | #define LP8501_CP_AUTO 0x18 | ||
| 60 | #define LP8501_INT_CLK BIT(0) | ||
| 61 | #define LP8501_DEFAULT_CFG \ | ||
| 62 | (LP8501_PWM_PSAVE | LP8501_AUTO_INC | LP8501_PWR_SAVE | LP8501_CP_AUTO) | ||
| 63 | |||
| 64 | #define LP8501_REG_RESET 0x3D | ||
| 65 | #define LP8501_RESET 0xFF | ||
| 66 | |||
| 67 | #define LP8501_REG_PROG_PAGE_SEL 0x4F | ||
| 68 | #define LP8501_PAGE_ENG1 0 | ||
| 69 | #define LP8501_PAGE_ENG2 1 | ||
| 70 | #define LP8501_PAGE_ENG3 2 | ||
| 71 | |||
| 72 | #define LP8501_REG_PROG_MEM 0x50 | ||
| 73 | |||
| 74 | #define LP8501_ENG1_IS_LOADING(mode) \ | ||
| 75 | ((mode & LP8501_MODE_ENG1_M) == LP8501_LOAD_ENG1) | ||
| 76 | #define LP8501_ENG2_IS_LOADING(mode) \ | ||
| 77 | ((mode & LP8501_MODE_ENG2_M) == LP8501_LOAD_ENG2) | ||
| 78 | #define LP8501_ENG3_IS_LOADING(mode) \ | ||
| 79 | ((mode & LP8501_MODE_ENG3_M) == LP8501_LOAD_ENG3) | ||
| 80 | |||
| 81 | static inline void lp8501_wait_opmode_done(void) | ||
| 82 | { | ||
| 83 | usleep_range(1000, 2000); | ||
| 84 | } | ||
| 85 | |||
| 86 | static void lp8501_set_led_current(struct lp55xx_led *led, u8 led_current) | ||
| 87 | { | ||
| 88 | led->led_current = led_current; | ||
| 89 | lp55xx_write(led->chip, LP8501_REG_LED_CURRENT_BASE + led->chan_nr, | ||
| 90 | led_current); | ||
| 91 | } | ||
| 92 | |||
| 93 | static int lp8501_post_init_device(struct lp55xx_chip *chip) | ||
| 94 | { | ||
| 95 | int ret; | ||
| 96 | u8 val = LP8501_DEFAULT_CFG; | ||
| 97 | |||
| 98 | ret = lp55xx_write(chip, LP8501_REG_ENABLE, LP8501_ENABLE); | ||
| 99 | if (ret) | ||
| 100 | return ret; | ||
| 101 | |||
| 102 | /* Chip startup time is 500 us, 1 - 2 ms gives some margin */ | ||
| 103 | usleep_range(1000, 2000); | ||
| 104 | |||
| 105 | if (chip->pdata->clock_mode != LP55XX_CLOCK_EXT) | ||
| 106 | val |= LP8501_INT_CLK; | ||
| 107 | |||
| 108 | ret = lp55xx_write(chip, LP8501_REG_CONFIG, val); | ||
| 109 | if (ret) | ||
| 110 | return ret; | ||
| 111 | |||
| 112 | /* Power selection for each output */ | ||
| 113 | return lp55xx_update_bits(chip, LP8501_REG_PWR_CONFIG, | ||
| 114 | LP8501_PWR_CONFIG_M, chip->pdata->pwr_sel); | ||
| 115 | } | ||
| 116 | |||
| 117 | static void lp8501_load_engine(struct lp55xx_chip *chip) | ||
| 118 | { | ||
| 119 | enum lp55xx_engine_index idx = chip->engine_idx; | ||
| 120 | u8 mask[] = { | ||
| 121 | [LP55XX_ENGINE_1] = LP8501_MODE_ENG1_M, | ||
| 122 | [LP55XX_ENGINE_2] = LP8501_MODE_ENG2_M, | ||
| 123 | [LP55XX_ENGINE_3] = LP8501_MODE_ENG3_M, | ||
| 124 | }; | ||
| 125 | |||
| 126 | u8 val[] = { | ||
| 127 | [LP55XX_ENGINE_1] = LP8501_LOAD_ENG1, | ||
| 128 | [LP55XX_ENGINE_2] = LP8501_LOAD_ENG2, | ||
| 129 | [LP55XX_ENGINE_3] = LP8501_LOAD_ENG3, | ||
| 130 | }; | ||
| 131 | |||
| 132 | u8 page_sel[] = { | ||
| 133 | [LP55XX_ENGINE_1] = LP8501_PAGE_ENG1, | ||
| 134 | [LP55XX_ENGINE_2] = LP8501_PAGE_ENG2, | ||
| 135 | [LP55XX_ENGINE_3] = LP8501_PAGE_ENG3, | ||
| 136 | }; | ||
| 137 | |||
| 138 | lp55xx_update_bits(chip, LP8501_REG_OP_MODE, mask[idx], val[idx]); | ||
| 139 | |||
| 140 | lp8501_wait_opmode_done(); | ||
| 141 | |||
| 142 | lp55xx_write(chip, LP8501_REG_PROG_PAGE_SEL, page_sel[idx]); | ||
| 143 | } | ||
| 144 | |||
| 145 | static void lp8501_stop_engine(struct lp55xx_chip *chip) | ||
| 146 | { | ||
| 147 | lp55xx_write(chip, LP8501_REG_OP_MODE, 0); | ||
| 148 | lp8501_wait_opmode_done(); | ||
| 149 | } | ||
| 150 | |||
| 151 | static void lp8501_turn_off_channels(struct lp55xx_chip *chip) | ||
| 152 | { | ||
| 153 | int i; | ||
| 154 | |||
| 155 | for (i = 0; i < LP8501_MAX_LEDS; i++) | ||
| 156 | lp55xx_write(chip, LP8501_REG_LED_PWM_BASE + i, 0); | ||
| 157 | } | ||
| 158 | |||
| 159 | static void lp8501_run_engine(struct lp55xx_chip *chip, bool start) | ||
| 160 | { | ||
| 161 | int ret; | ||
| 162 | u8 mode; | ||
| 163 | u8 exec; | ||
| 164 | |||
| 165 | /* stop engine */ | ||
| 166 | if (!start) { | ||
| 167 | lp8501_stop_engine(chip); | ||
| 168 | lp8501_turn_off_channels(chip); | ||
| 169 | return; | ||
| 170 | } | ||
| 171 | |||
| 172 | /* | ||
| 173 | * To run the engine, | ||
| 174 | * operation mode and enable register should updated at the same time | ||
| 175 | */ | ||
| 176 | |||
| 177 | ret = lp55xx_read(chip, LP8501_REG_OP_MODE, &mode); | ||
| 178 | if (ret) | ||
| 179 | return; | ||
| 180 | |||
| 181 | ret = lp55xx_read(chip, LP8501_REG_ENABLE, &exec); | ||
| 182 | if (ret) | ||
| 183 | return; | ||
| 184 | |||
| 185 | /* change operation mode to RUN only when each engine is loading */ | ||
| 186 | if (LP8501_ENG1_IS_LOADING(mode)) { | ||
| 187 | mode = (mode & ~LP8501_MODE_ENG1_M) | LP8501_RUN_ENG1; | ||
| 188 | exec = (exec & ~LP8501_EXEC_ENG1_M) | LP8501_RUN_ENG1; | ||
| 189 | } | ||
| 190 | |||
| 191 | if (LP8501_ENG2_IS_LOADING(mode)) { | ||
| 192 | mode = (mode & ~LP8501_MODE_ENG2_M) | LP8501_RUN_ENG2; | ||
| 193 | exec = (exec & ~LP8501_EXEC_ENG2_M) | LP8501_RUN_ENG2; | ||
| 194 | } | ||
| 195 | |||
| 196 | if (LP8501_ENG3_IS_LOADING(mode)) { | ||
| 197 | mode = (mode & ~LP8501_MODE_ENG3_M) | LP8501_RUN_ENG3; | ||
| 198 | exec = (exec & ~LP8501_EXEC_ENG3_M) | LP8501_RUN_ENG3; | ||
| 199 | } | ||
| 200 | |||
| 201 | lp55xx_write(chip, LP8501_REG_OP_MODE, mode); | ||
| 202 | lp8501_wait_opmode_done(); | ||
| 203 | |||
| 204 | lp55xx_update_bits(chip, LP8501_REG_ENABLE, LP8501_EXEC_M, exec); | ||
| 205 | } | ||
| 206 | |||
| 207 | static int lp8501_update_program_memory(struct lp55xx_chip *chip, | ||
| 208 | const u8 *data, size_t size) | ||
| 209 | { | ||
| 210 | u8 pattern[LP8501_PROGRAM_LENGTH] = {0}; | ||
| 211 | unsigned cmd; | ||
| 212 | char c[3]; | ||
| 213 | int update_size; | ||
| 214 | int nrchars; | ||
| 215 | int offset = 0; | ||
| 216 | int ret; | ||
| 217 | int i; | ||
| 218 | |||
| 219 | /* clear program memory before updating */ | ||
| 220 | for (i = 0; i < LP8501_PROGRAM_LENGTH; i++) | ||
| 221 | lp55xx_write(chip, LP8501_REG_PROG_MEM + i, 0); | ||
| 222 | |||
| 223 | i = 0; | ||
| 224 | while ((offset < size - 1) && (i < LP8501_PROGRAM_LENGTH)) { | ||
| 225 | /* separate sscanfs because length is working only for %s */ | ||
| 226 | ret = sscanf(data + offset, "%2s%n ", c, &nrchars); | ||
| 227 | if (ret != 1) | ||
| 228 | goto err; | ||
| 229 | |||
| 230 | ret = sscanf(c, "%2x", &cmd); | ||
| 231 | if (ret != 1) | ||
| 232 | goto err; | ||
| 233 | |||
| 234 | pattern[i] = (u8)cmd; | ||
| 235 | offset += nrchars; | ||
| 236 | i++; | ||
| 237 | } | ||
| 238 | |||
| 239 | /* Each instruction is 16bit long. Check that length is even */ | ||
| 240 | if (i % 2) | ||
| 241 | goto err; | ||
| 242 | |||
| 243 | update_size = i; | ||
| 244 | for (i = 0; i < update_size; i++) | ||
| 245 | lp55xx_write(chip, LP8501_REG_PROG_MEM + i, pattern[i]); | ||
| 246 | |||
| 247 | return 0; | ||
| 248 | |||
| 249 | err: | ||
| 250 | dev_err(&chip->cl->dev, "wrong pattern format\n"); | ||
| 251 | return -EINVAL; | ||
| 252 | } | ||
| 253 | |||
| 254 | static void lp8501_firmware_loaded(struct lp55xx_chip *chip) | ||
| 255 | { | ||
| 256 | const struct firmware *fw = chip->fw; | ||
| 257 | |||
| 258 | if (fw->size > LP8501_PROGRAM_LENGTH) { | ||
| 259 | dev_err(&chip->cl->dev, "firmware data size overflow: %zu\n", | ||
| 260 | fw->size); | ||
| 261 | return; | ||
| 262 | } | ||
| 263 | |||
| 264 | /* | ||
| 265 | * Program momery sequence | ||
| 266 | * 1) set engine mode to "LOAD" | ||
| 267 | * 2) write firmware data into program memory | ||
| 268 | */ | ||
| 269 | |||
| 270 | lp8501_load_engine(chip); | ||
| 271 | lp8501_update_program_memory(chip, fw->data, fw->size); | ||
| 272 | } | ||
| 273 | |||
| 274 | static void lp8501_led_brightness_work(struct work_struct *work) | ||
| 275 | { | ||
| 276 | struct lp55xx_led *led = container_of(work, struct lp55xx_led, | ||
| 277 | brightness_work); | ||
| 278 | struct lp55xx_chip *chip = led->chip; | ||
| 279 | |||
| 280 | mutex_lock(&chip->lock); | ||
| 281 | lp55xx_write(chip, LP8501_REG_LED_PWM_BASE + led->chan_nr, | ||
| 282 | led->brightness); | ||
| 283 | mutex_unlock(&chip->lock); | ||
| 284 | } | ||
| 285 | |||
| 286 | /* Chip specific configurations */ | ||
| 287 | static struct lp55xx_device_config lp8501_cfg = { | ||
| 288 | .reset = { | ||
| 289 | .addr = LP8501_REG_RESET, | ||
| 290 | .val = LP8501_RESET, | ||
| 291 | }, | ||
| 292 | .enable = { | ||
| 293 | .addr = LP8501_REG_ENABLE, | ||
| 294 | .val = LP8501_ENABLE, | ||
| 295 | }, | ||
| 296 | .max_channel = LP8501_MAX_LEDS, | ||
| 297 | .post_init_device = lp8501_post_init_device, | ||
| 298 | .brightness_work_fn = lp8501_led_brightness_work, | ||
| 299 | .set_led_current = lp8501_set_led_current, | ||
| 300 | .firmware_cb = lp8501_firmware_loaded, | ||
| 301 | .run_engine = lp8501_run_engine, | ||
| 302 | }; | ||
| 303 | |||
| 304 | static int lp8501_probe(struct i2c_client *client, | ||
| 305 | const struct i2c_device_id *id) | ||
| 306 | { | ||
| 307 | int ret; | ||
| 308 | struct lp55xx_chip *chip; | ||
| 309 | struct lp55xx_led *led; | ||
| 310 | struct lp55xx_platform_data *pdata; | ||
| 311 | struct device_node *np = client->dev.of_node; | ||
| 312 | |||
| 313 | if (!dev_get_platdata(&client->dev)) { | ||
| 314 | if (np) { | ||
| 315 | ret = lp55xx_of_populate_pdata(&client->dev, np); | ||
| 316 | if (ret < 0) | ||
| 317 | return ret; | ||
| 318 | } else { | ||
| 319 | dev_err(&client->dev, "no platform data\n"); | ||
| 320 | return -EINVAL; | ||
| 321 | } | ||
| 322 | } | ||
| 323 | pdata = dev_get_platdata(&client->dev); | ||
| 324 | |||
| 325 | chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); | ||
| 326 | if (!chip) | ||
| 327 | return -ENOMEM; | ||
| 328 | |||
| 329 | led = devm_kzalloc(&client->dev, | ||
| 330 | sizeof(*led) * pdata->num_channels, GFP_KERNEL); | ||
| 331 | if (!led) | ||
| 332 | return -ENOMEM; | ||
| 333 | |||
| 334 | chip->cl = client; | ||
| 335 | chip->pdata = pdata; | ||
| 336 | chip->cfg = &lp8501_cfg; | ||
| 337 | |||
| 338 | mutex_init(&chip->lock); | ||
| 339 | |||
| 340 | i2c_set_clientdata(client, led); | ||
| 341 | |||
| 342 | ret = lp55xx_init_device(chip); | ||
| 343 | if (ret) | ||
| 344 | goto err_init; | ||
| 345 | |||
| 346 | dev_info(&client->dev, "%s Programmable led chip found\n", id->name); | ||
| 347 | |||
| 348 | ret = lp55xx_register_leds(led, chip); | ||
| 349 | if (ret) | ||
| 350 | goto err_register_leds; | ||
| 351 | |||
| 352 | ret = lp55xx_register_sysfs(chip); | ||
| 353 | if (ret) { | ||
| 354 | dev_err(&client->dev, "registering sysfs failed\n"); | ||
| 355 | goto err_register_sysfs; | ||
| 356 | } | ||
| 357 | |||
| 358 | return 0; | ||
| 359 | |||
| 360 | err_register_sysfs: | ||
| 361 | lp55xx_unregister_leds(led, chip); | ||
| 362 | err_register_leds: | ||
| 363 | lp55xx_deinit_device(chip); | ||
| 364 | err_init: | ||
| 365 | return ret; | ||
| 366 | } | ||
| 367 | |||
| 368 | static int lp8501_remove(struct i2c_client *client) | ||
| 369 | { | ||
| 370 | struct lp55xx_led *led = i2c_get_clientdata(client); | ||
| 371 | struct lp55xx_chip *chip = led->chip; | ||
| 372 | |||
| 373 | lp8501_stop_engine(chip); | ||
| 374 | lp55xx_unregister_sysfs(chip); | ||
| 375 | lp55xx_unregister_leds(led, chip); | ||
| 376 | lp55xx_deinit_device(chip); | ||
| 377 | |||
| 378 | return 0; | ||
| 379 | } | ||
| 380 | |||
| 381 | static const struct i2c_device_id lp8501_id[] = { | ||
| 382 | { "lp8501", 0 }, | ||
| 383 | { } | ||
| 384 | }; | ||
| 385 | MODULE_DEVICE_TABLE(i2c, lp8501_id); | ||
| 386 | |||
| 387 | #ifdef CONFIG_OF | ||
| 388 | static const struct of_device_id of_lp8501_leds_match[] = { | ||
| 389 | { .compatible = "ti,lp8501", }, | ||
| 390 | {}, | ||
| 391 | }; | ||
| 392 | |||
| 393 | MODULE_DEVICE_TABLE(of, of_lp8501_leds_match); | ||
| 394 | #endif | ||
| 395 | |||
| 396 | static struct i2c_driver lp8501_driver = { | ||
| 397 | .driver = { | ||
| 398 | .name = "lp8501", | ||
| 399 | .of_match_table = of_match_ptr(of_lp8501_leds_match), | ||
| 400 | }, | ||
| 401 | .probe = lp8501_probe, | ||
| 402 | .remove = lp8501_remove, | ||
| 403 | .id_table = lp8501_id, | ||
| 404 | }; | ||
| 405 | |||
| 406 | module_i2c_driver(lp8501_driver); | ||
| 407 | |||
| 408 | MODULE_DESCRIPTION("Texas Instruments LP8501 LED drvier"); | ||
| 409 | MODULE_AUTHOR("Milo Kim"); | ||
| 410 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index ca48a7d5502d..3417e5be7b57 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c | |||
| @@ -135,7 +135,7 @@ static void delete_lt3593_led(struct lt3593_led_data *led) | |||
| 135 | 135 | ||
| 136 | static int lt3593_led_probe(struct platform_device *pdev) | 136 | static int lt3593_led_probe(struct platform_device *pdev) |
| 137 | { | 137 | { |
| 138 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; | 138 | struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 139 | struct lt3593_led_data *leds_data; | 139 | struct lt3593_led_data *leds_data; |
| 140 | int i, ret = 0; | 140 | int i, ret = 0; |
| 141 | 141 | ||
| @@ -169,7 +169,7 @@ err: | |||
| 169 | static int lt3593_led_remove(struct platform_device *pdev) | 169 | static int lt3593_led_remove(struct platform_device *pdev) |
| 170 | { | 170 | { |
| 171 | int i; | 171 | int i; |
| 172 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; | 172 | struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 173 | struct lt3593_led_data *leds_data; | 173 | struct lt3593_led_data *leds_data; |
| 174 | 174 | ||
| 175 | leds_data = platform_get_drvdata(pdev); | 175 | leds_data = platform_get_drvdata(pdev); |
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c index c61c5ebcc08e..2f9f141084ba 100644 --- a/drivers/leds/leds-netxbig.c +++ b/drivers/leds/leds-netxbig.c | |||
| @@ -306,7 +306,7 @@ create_netxbig_led(struct platform_device *pdev, | |||
| 306 | struct netxbig_led_data *led_dat, | 306 | struct netxbig_led_data *led_dat, |
| 307 | const struct netxbig_led *template) | 307 | const struct netxbig_led *template) |
| 308 | { | 308 | { |
| 309 | struct netxbig_led_platform_data *pdata = pdev->dev.platform_data; | 309 | struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 310 | int ret; | 310 | int ret; |
| 311 | 311 | ||
| 312 | spin_lock_init(&led_dat->lock); | 312 | spin_lock_init(&led_dat->lock); |
| @@ -354,7 +354,7 @@ create_netxbig_led(struct platform_device *pdev, | |||
| 354 | 354 | ||
| 355 | static int netxbig_led_probe(struct platform_device *pdev) | 355 | static int netxbig_led_probe(struct platform_device *pdev) |
| 356 | { | 356 | { |
| 357 | struct netxbig_led_platform_data *pdata = pdev->dev.platform_data; | 357 | struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 358 | struct netxbig_led_data *leds_data; | 358 | struct netxbig_led_data *leds_data; |
| 359 | int i; | 359 | int i; |
| 360 | int ret; | 360 | int ret; |
| @@ -391,7 +391,7 @@ err_free_leds: | |||
| 391 | 391 | ||
| 392 | static int netxbig_led_remove(struct platform_device *pdev) | 392 | static int netxbig_led_remove(struct platform_device *pdev) |
| 393 | { | 393 | { |
| 394 | struct netxbig_led_platform_data *pdata = pdev->dev.platform_data; | 394 | struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 395 | struct netxbig_led_data *leds_data; | 395 | struct netxbig_led_data *leds_data; |
| 396 | int i; | 396 | int i; |
| 397 | 397 | ||
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index e7df9875c400..141f13438e80 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c | |||
| @@ -321,7 +321,7 @@ static inline int sizeof_ns2_led_priv(int num_leds) | |||
| 321 | 321 | ||
| 322 | static int ns2_led_probe(struct platform_device *pdev) | 322 | static int ns2_led_probe(struct platform_device *pdev) |
| 323 | { | 323 | { |
| 324 | struct ns2_led_platform_data *pdata = pdev->dev.platform_data; | 324 | struct ns2_led_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 325 | struct ns2_led_priv *priv; | 325 | struct ns2_led_priv *priv; |
| 326 | int i; | 326 | int i; |
| 327 | int ret; | 327 | int ret; |
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index 0c597bdd23f9..4a0e786b7832 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c | |||
| @@ -446,7 +446,8 @@ static int pca9532_probe(struct i2c_client *client, | |||
| 446 | const struct i2c_device_id *id) | 446 | const struct i2c_device_id *id) |
| 447 | { | 447 | { |
| 448 | struct pca9532_data *data = i2c_get_clientdata(client); | 448 | struct pca9532_data *data = i2c_get_clientdata(client); |
| 449 | struct pca9532_platform_data *pca9532_pdata = client->dev.platform_data; | 449 | struct pca9532_platform_data *pca9532_pdata = |
| 450 | dev_get_platdata(&client->dev); | ||
| 450 | 451 | ||
| 451 | if (!pca9532_pdata) | 452 | if (!pca9532_pdata) |
| 452 | return -EIO; | 453 | return -EIO; |
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c index edf485b773c8..c3a08b60535b 100644 --- a/drivers/leds/leds-pca955x.c +++ b/drivers/leds/leds-pca955x.c | |||
| @@ -267,7 +267,7 @@ static int pca955x_probe(struct i2c_client *client, | |||
| 267 | 267 | ||
| 268 | chip = &pca955x_chipdefs[id->driver_data]; | 268 | chip = &pca955x_chipdefs[id->driver_data]; |
| 269 | adapter = to_i2c_adapter(client->dev.parent); | 269 | adapter = to_i2c_adapter(client->dev.parent); |
| 270 | pdata = client->dev.platform_data; | 270 | pdata = dev_get_platdata(&client->dev); |
| 271 | 271 | ||
| 272 | /* Make sure the slave address / chip type combo given is possible */ | 272 | /* Make sure the slave address / chip type combo given is possible */ |
| 273 | if ((client->addr & ~((1 << chip->slv_addr_shift) - 1)) != | 273 | if ((client->addr & ~((1 << chip->slv_addr_shift) - 1)) != |
diff --git a/drivers/leds/leds-pca9633.c b/drivers/leds/leds-pca9633.c deleted file mode 100644 index 9aae5679ffb2..000000000000 --- a/drivers/leds/leds-pca9633.c +++ /dev/null | |||
| @@ -1,194 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2011 bct electronic GmbH | ||
| 3 | * | ||
| 4 | * Author: Peter Meerwald <p.meerwald@bct-electronic.com> | ||
| 5 | * | ||
| 6 | * Based on leds-pca955x.c | ||
| 7 | * | ||
| 8 | * This file is subject to the terms and conditions of version 2 of | ||
| 9 | * the GNU General Public License. See the file COPYING in the main | ||
| 10 | * directory of this archive for more details. | ||
| 11 | * | ||
| 12 | * LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62) | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/delay.h> | ||
| 18 | #include <linux/string.h> | ||
| 19 | #include <linux/ctype.h> | ||
| 20 | #include <linux/leds.h> | ||
| 21 | #include <linux/err.h> | ||
| 22 | #include <linux/i2c.h> | ||
| 23 | #include <linux/workqueue.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/platform_data/leds-pca9633.h> | ||
| 26 | |||
| 27 | /* LED select registers determine the source that drives LED outputs */ | ||
| 28 | #define PCA9633_LED_OFF 0x0 /* LED driver off */ | ||
| 29 | #define PCA9633_LED_ON 0x1 /* LED driver on */ | ||
| 30 | #define PCA9633_LED_PWM 0x2 /* Controlled through PWM */ | ||
| 31 | #define PCA9633_LED_GRP_PWM 0x3 /* Controlled through PWM/GRPPWM */ | ||
| 32 | |||
| 33 | #define PCA9633_MODE1 0x00 | ||
| 34 | #define PCA9633_MODE2 0x01 | ||
| 35 | #define PCA9633_PWM_BASE 0x02 | ||
| 36 | #define PCA9633_LEDOUT 0x08 | ||
| 37 | |||
| 38 | static const struct i2c_device_id pca9633_id[] = { | ||
| 39 | { "pca9633", 0 }, | ||
| 40 | { } | ||
| 41 | }; | ||
| 42 | MODULE_DEVICE_TABLE(i2c, pca9633_id); | ||
| 43 | |||
| 44 | struct pca9633_led { | ||
| 45 | struct i2c_client *client; | ||
| 46 | struct work_struct work; | ||
| 47 | enum led_brightness brightness; | ||
| 48 | struct led_classdev led_cdev; | ||
| 49 | int led_num; /* 0 .. 3 potentially */ | ||
| 50 | char name[32]; | ||
| 51 | }; | ||
| 52 | |||
| 53 | static void pca9633_led_work(struct work_struct *work) | ||
| 54 | { | ||
| 55 | struct pca9633_led *pca9633 = container_of(work, | ||
| 56 | struct pca9633_led, work); | ||
| 57 | u8 ledout = i2c_smbus_read_byte_data(pca9633->client, PCA9633_LEDOUT); | ||
| 58 | int shift = 2 * pca9633->led_num; | ||
| 59 | u8 mask = 0x3 << shift; | ||
| 60 | |||
| 61 | switch (pca9633->brightness) { | ||
| 62 | case LED_FULL: | ||
| 63 | i2c_smbus_write_byte_data(pca9633->client, PCA9633_LEDOUT, | ||
| 64 | (ledout & ~mask) | (PCA9633_LED_ON << shift)); | ||
| 65 | break; | ||
| 66 | case LED_OFF: | ||
| 67 | i2c_smbus_write_byte_data(pca9633->client, PCA9633_LEDOUT, | ||
| 68 | ledout & ~mask); | ||
| 69 | break; | ||
| 70 | default: | ||
| 71 | i2c_smbus_write_byte_data(pca9633->client, | ||
| 72 | PCA9633_PWM_BASE + pca9633->led_num, | ||
| 73 | pca9633->brightness); | ||
| 74 | i2c_smbus_write_byte_data(pca9633->client, PCA9633_LEDOUT, | ||
| 75 | (ledout & ~mask) | (PCA9633_LED_PWM << shift)); | ||
| 76 | break; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | static void pca9633_led_set(struct led_classdev *led_cdev, | ||
| 81 | enum led_brightness value) | ||
| 82 | { | ||
| 83 | struct pca9633_led *pca9633; | ||
| 84 | |||
| 85 | pca9633 = container_of(led_cdev, struct pca9633_led, led_cdev); | ||
| 86 | |||
| 87 | pca9633->brightness = value; | ||
| 88 | |||
| 89 | /* | ||
| 90 | * Must use workqueue for the actual I/O since I2C operations | ||
| 91 | * can sleep. | ||
| 92 | */ | ||
| 93 | schedule_work(&pca9633->work); | ||
| 94 | } | ||
| 95 | |||
| 96 | static int pca9633_probe(struct i2c_client *client, | ||
| 97 | const struct i2c_device_id *id) | ||
| 98 | { | ||
| 99 | struct pca9633_led *pca9633; | ||
| 100 | struct pca9633_platform_data *pdata; | ||
| 101 | int i, err; | ||
| 102 | |||
| 103 | pdata = client->dev.platform_data; | ||
| 104 | |||
| 105 | if (pdata) { | ||
| 106 | if (pdata->leds.num_leds <= 0 || pdata->leds.num_leds > 4) { | ||
| 107 | dev_err(&client->dev, "board info must claim at most 4 LEDs"); | ||
| 108 | return -EINVAL; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 112 | pca9633 = devm_kzalloc(&client->dev, 4 * sizeof(*pca9633), GFP_KERNEL); | ||
| 113 | if (!pca9633) | ||
| 114 | return -ENOMEM; | ||
| 115 | |||
| 116 | i2c_set_clientdata(client, pca9633); | ||
| 117 | |||
| 118 | for (i = 0; i < 4; i++) { | ||
| 119 | pca9633[i].client = client; | ||
| 120 | pca9633[i].led_num = i; | ||
| 121 | |||
| 122 | /* Platform data can specify LED names and default triggers */ | ||
| 123 | if (pdata && i < pdata->leds.num_leds) { | ||
| 124 | if (pdata->leds.leds[i].name) | ||
| 125 | snprintf(pca9633[i].name, | ||
| 126 | sizeof(pca9633[i].name), "pca9633:%s", | ||
| 127 | pdata->leds.leds[i].name); | ||
| 128 | if (pdata->leds.leds[i].default_trigger) | ||
| 129 | pca9633[i].led_cdev.default_trigger = | ||
| 130 | pdata->leds.leds[i].default_trigger; | ||
| 131 | } else { | ||
| 132 | snprintf(pca9633[i].name, sizeof(pca9633[i].name), | ||
| 133 | "pca9633:%d", i); | ||
| 134 | } | ||
| 135 | |||
| 136 | pca9633[i].led_cdev.name = pca9633[i].name; | ||
| 137 | pca9633[i].led_cdev.brightness_set = pca9633_led_set; | ||
| 138 | |||
| 139 | INIT_WORK(&pca9633[i].work, pca9633_led_work); | ||
| 140 | |||
| 141 | err = led_classdev_register(&client->dev, &pca9633[i].led_cdev); | ||
| 142 | if (err < 0) | ||
| 143 | goto exit; | ||
| 144 | } | ||
| 145 | |||
| 146 | /* Disable LED all-call address and set normal mode */ | ||
| 147 | i2c_smbus_write_byte_data(client, PCA9633_MODE1, 0x00); | ||
| 148 | |||
| 149 | /* Configure output: open-drain or totem pole (push-pull) */ | ||
| 150 | if (pdata && pdata->outdrv == PCA9633_OPEN_DRAIN) | ||
| 151 | i2c_smbus_write_byte_data(client, PCA9633_MODE2, 0x01); | ||
| 152 | |||
| 153 | /* Turn off LEDs */ | ||
| 154 | i2c_smbus_write_byte_data(client, PCA9633_LEDOUT, 0x00); | ||
| 155 | |||
| 156 | return 0; | ||
| 157 | |||
| 158 | exit: | ||
| 159 | while (i--) { | ||
| 160 | led_classdev_unregister(&pca9633[i].led_cdev); | ||
| 161 | cancel_work_sync(&pca9633[i].work); | ||
| 162 | } | ||
| 163 | |||
| 164 | return err; | ||
| 165 | } | ||
| 166 | |||
| 167 | static int pca9633_remove(struct i2c_client *client) | ||
| 168 | { | ||
| 169 | struct pca9633_led *pca9633 = i2c_get_clientdata(client); | ||
| 170 | int i; | ||
| 171 | |||
| 172 | for (i = 0; i < 4; i++) { | ||
| 173 | led_classdev_unregister(&pca9633[i].led_cdev); | ||
| 174 | cancel_work_sync(&pca9633[i].work); | ||
| 175 | } | ||
| 176 | |||
| 177 | return 0; | ||
| 178 | } | ||
| 179 | |||
| 180 | static struct i2c_driver pca9633_driver = { | ||
| 181 | .driver = { | ||
| 182 | .name = "leds-pca9633", | ||
| 183 | .owner = THIS_MODULE, | ||
| 184 | }, | ||
| 185 | .probe = pca9633_probe, | ||
| 186 | .remove = pca9633_remove, | ||
| 187 | .id_table = pca9633_id, | ||
| 188 | }; | ||
| 189 | |||
| 190 | module_i2c_driver(pca9633_driver); | ||
| 191 | |||
| 192 | MODULE_AUTHOR("Peter Meerwald <p.meerwald@bct-electronic.com>"); | ||
| 193 | MODULE_DESCRIPTION("PCA9633 LED driver"); | ||
| 194 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/leds/leds-pca963x.c b/drivers/leds/leds-pca963x.c new file mode 100644 index 000000000000..82589c0a5689 --- /dev/null +++ b/drivers/leds/leds-pca963x.c | |||
| @@ -0,0 +1,461 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2011 bct electronic GmbH | ||
| 3 | * Copyright 2013 Qtechnology/AS | ||
| 4 | * | ||
| 5 | * Author: Peter Meerwald <p.meerwald@bct-electronic.com> | ||
| 6 | * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com> | ||
| 7 | * | ||
| 8 | * Based on leds-pca955x.c | ||
| 9 | * | ||
| 10 | * This file is subject to the terms and conditions of version 2 of | ||
| 11 | * the GNU General Public License. See the file COPYING in the main | ||
| 12 | * directory of this archive for more details. | ||
| 13 | * | ||
| 14 | * LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62) | ||
| 15 | * LED driver for the PCA9634 I2C LED driver (7-bit slave address set by hw.) | ||
| 16 | * | ||
| 17 | * Note that hardware blinking violates the leds infrastructure driver | ||
| 18 | * interface since the hardware only supports blinking all LEDs with the | ||
| 19 | * same delay_on/delay_off rates. That is, only the LEDs that are set to | ||
| 20 | * blink will actually blink but all LEDs that are set to blink will blink | ||
| 21 | * in identical fashion. The delay_on/delay_off values of the last LED | ||
| 22 | * that is set to blink will be used for all of the blinking LEDs. | ||
| 23 | * Hardware blinking is disabled by default but can be enabled by setting | ||
| 24 | * the 'blink_type' member in the platform_data struct to 'PCA963X_HW_BLINK' | ||
| 25 | * or by adding the 'nxp,hw-blink' property to the DTS. | ||
| 26 | */ | ||
| 27 | |||
| 28 | #include <linux/module.h> | ||
| 29 | #include <linux/delay.h> | ||
| 30 | #include <linux/string.h> | ||
| 31 | #include <linux/ctype.h> | ||
| 32 | #include <linux/leds.h> | ||
| 33 | #include <linux/err.h> | ||
| 34 | #include <linux/i2c.h> | ||
| 35 | #include <linux/workqueue.h> | ||
| 36 | #include <linux/slab.h> | ||
| 37 | #include <linux/of.h> | ||
| 38 | #include <linux/platform_data/leds-pca963x.h> | ||
| 39 | |||
| 40 | /* LED select registers determine the source that drives LED outputs */ | ||
| 41 | #define PCA963X_LED_OFF 0x0 /* LED driver off */ | ||
| 42 | #define PCA963X_LED_ON 0x1 /* LED driver on */ | ||
| 43 | #define PCA963X_LED_PWM 0x2 /* Controlled through PWM */ | ||
| 44 | #define PCA963X_LED_GRP_PWM 0x3 /* Controlled through PWM/GRPPWM */ | ||
| 45 | |||
| 46 | #define PCA963X_MODE2_DMBLNK 0x20 /* Enable blinking */ | ||
| 47 | |||
| 48 | #define PCA963X_MODE1 0x00 | ||
| 49 | #define PCA963X_MODE2 0x01 | ||
| 50 | #define PCA963X_PWM_BASE 0x02 | ||
| 51 | |||
| 52 | enum pca963x_type { | ||
| 53 | pca9633, | ||
| 54 | pca9634, | ||
| 55 | }; | ||
| 56 | |||
| 57 | struct pca963x_chipdef { | ||
| 58 | u8 grppwm; | ||
| 59 | u8 grpfreq; | ||
| 60 | u8 ledout_base; | ||
| 61 | int n_leds; | ||
| 62 | }; | ||
| 63 | |||
| 64 | static struct pca963x_chipdef pca963x_chipdefs[] = { | ||
| 65 | [pca9633] = { | ||
| 66 | .grppwm = 0x6, | ||
| 67 | .grpfreq = 0x7, | ||
| 68 | .ledout_base = 0x8, | ||
| 69 | .n_leds = 4, | ||
| 70 | }, | ||
| 71 | [pca9634] = { | ||
| 72 | .grppwm = 0xa, | ||
| 73 | .grpfreq = 0xb, | ||
| 74 | .ledout_base = 0xc, | ||
| 75 | .n_leds = 8, | ||
| 76 | }, | ||
| 77 | }; | ||
| 78 | |||
| 79 | /* Total blink period in milliseconds */ | ||
| 80 | #define PCA963X_BLINK_PERIOD_MIN 42 | ||
| 81 | #define PCA963X_BLINK_PERIOD_MAX 10667 | ||
| 82 | |||
| 83 | static const struct i2c_device_id pca963x_id[] = { | ||
| 84 | { "pca9632", pca9633 }, | ||
| 85 | { "pca9633", pca9633 }, | ||
| 86 | { "pca9634", pca9634 }, | ||
| 87 | { } | ||
| 88 | }; | ||
| 89 | MODULE_DEVICE_TABLE(i2c, pca963x_id); | ||
| 90 | |||
| 91 | enum pca963x_cmd { | ||
| 92 | BRIGHTNESS_SET, | ||
| 93 | BLINK_SET, | ||
| 94 | }; | ||
| 95 | |||
| 96 | struct pca963x_led; | ||
| 97 | |||
| 98 | struct pca963x { | ||
| 99 | struct pca963x_chipdef *chipdef; | ||
| 100 | struct mutex mutex; | ||
| 101 | struct i2c_client *client; | ||
| 102 | struct pca963x_led *leds; | ||
| 103 | }; | ||
| 104 | |||
| 105 | struct pca963x_led { | ||
| 106 | struct pca963x *chip; | ||
| 107 | struct work_struct work; | ||
| 108 | enum led_brightness brightness; | ||
| 109 | struct led_classdev led_cdev; | ||
| 110 | int led_num; /* 0 .. 7 potentially */ | ||
| 111 | enum pca963x_cmd cmd; | ||
| 112 | char name[32]; | ||
| 113 | u8 gdc; | ||
| 114 | u8 gfrq; | ||
| 115 | }; | ||
| 116 | |||
| 117 | static void pca963x_brightness_work(struct pca963x_led *pca963x) | ||
| 118 | { | ||
| 119 | u8 ledout_addr = pca963x->chip->chipdef->ledout_base | ||
| 120 | + (pca963x->led_num / 4); | ||
| 121 | u8 ledout; | ||
| 122 | int shift = 2 * (pca963x->led_num % 4); | ||
| 123 | u8 mask = 0x3 << shift; | ||
| 124 | |||
| 125 | mutex_lock(&pca963x->chip->mutex); | ||
| 126 | ledout = i2c_smbus_read_byte_data(pca963x->chip->client, ledout_addr); | ||
| 127 | switch (pca963x->brightness) { | ||
| 128 | case LED_FULL: | ||
| 129 | i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr, | ||
| 130 | (ledout & ~mask) | (PCA963X_LED_ON << shift)); | ||
| 131 | break; | ||
| 132 | case LED_OFF: | ||
| 133 | i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr, | ||
| 134 | ledout & ~mask); | ||
| 135 | break; | ||
| 136 | default: | ||
| 137 | i2c_smbus_write_byte_data(pca963x->chip->client, | ||
| 138 | PCA963X_PWM_BASE + pca963x->led_num, | ||
| 139 | pca963x->brightness); | ||
| 140 | i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr, | ||
| 141 | (ledout & ~mask) | (PCA963X_LED_PWM << shift)); | ||
| 142 | break; | ||
| 143 | } | ||
| 144 | mutex_unlock(&pca963x->chip->mutex); | ||
| 145 | } | ||
| 146 | |||
| 147 | static void pca963x_blink_work(struct pca963x_led *pca963x) | ||
| 148 | { | ||
| 149 | u8 ledout_addr = pca963x->chip->chipdef->ledout_base + | ||
| 150 | (pca963x->led_num / 4); | ||
| 151 | u8 ledout; | ||
| 152 | u8 mode2 = i2c_smbus_read_byte_data(pca963x->chip->client, | ||
| 153 | PCA963X_MODE2); | ||
| 154 | int shift = 2 * (pca963x->led_num % 4); | ||
| 155 | u8 mask = 0x3 << shift; | ||
| 156 | |||
| 157 | i2c_smbus_write_byte_data(pca963x->chip->client, | ||
| 158 | pca963x->chip->chipdef->grppwm, pca963x->gdc); | ||
| 159 | |||
| 160 | i2c_smbus_write_byte_data(pca963x->chip->client, | ||
| 161 | pca963x->chip->chipdef->grpfreq, pca963x->gfrq); | ||
| 162 | |||
| 163 | if (!(mode2 & PCA963X_MODE2_DMBLNK)) | ||
| 164 | i2c_smbus_write_byte_data(pca963x->chip->client, PCA963X_MODE2, | ||
| 165 | mode2 | PCA963X_MODE2_DMBLNK); | ||
| 166 | |||
| 167 | mutex_lock(&pca963x->chip->mutex); | ||
| 168 | ledout = i2c_smbus_read_byte_data(pca963x->chip->client, ledout_addr); | ||
| 169 | if ((ledout & mask) != (PCA963X_LED_GRP_PWM << shift)) | ||
| 170 | i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr, | ||
| 171 | (ledout & ~mask) | (PCA963X_LED_GRP_PWM << shift)); | ||
| 172 | mutex_unlock(&pca963x->chip->mutex); | ||
| 173 | } | ||
| 174 | |||
| 175 | static void pca963x_work(struct work_struct *work) | ||
| 176 | { | ||
| 177 | struct pca963x_led *pca963x = container_of(work, | ||
| 178 | struct pca963x_led, work); | ||
| 179 | |||
| 180 | switch (pca963x->cmd) { | ||
| 181 | case BRIGHTNESS_SET: | ||
| 182 | pca963x_brightness_work(pca963x); | ||
| 183 | break; | ||
| 184 | case BLINK_SET: | ||
| 185 | pca963x_blink_work(pca963x); | ||
| 186 | break; | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | static void pca963x_led_set(struct led_classdev *led_cdev, | ||
| 191 | enum led_brightness value) | ||
| 192 | { | ||
| 193 | struct pca963x_led *pca963x; | ||
| 194 | |||
| 195 | pca963x = container_of(led_cdev, struct pca963x_led, led_cdev); | ||
| 196 | |||
| 197 | pca963x->cmd = BRIGHTNESS_SET; | ||
| 198 | pca963x->brightness = value; | ||
| 199 | |||
| 200 | /* | ||
| 201 | * Must use workqueue for the actual I/O since I2C operations | ||
| 202 | * can sleep. | ||
| 203 | */ | ||
| 204 | schedule_work(&pca963x->work); | ||
| 205 | } | ||
| 206 | |||
| 207 | static int pca963x_blink_set(struct led_classdev *led_cdev, | ||
| 208 | unsigned long *delay_on, unsigned long *delay_off) | ||
| 209 | { | ||
| 210 | struct pca963x_led *pca963x; | ||
| 211 | unsigned long time_on, time_off, period; | ||
| 212 | u8 gdc, gfrq; | ||
| 213 | |||
| 214 | pca963x = container_of(led_cdev, struct pca963x_led, led_cdev); | ||
| 215 | |||
| 216 | time_on = *delay_on; | ||
| 217 | time_off = *delay_off; | ||
| 218 | |||
| 219 | /* If both zero, pick reasonable defaults of 500ms each */ | ||
| 220 | if (!time_on && !time_off) { | ||
| 221 | time_on = 500; | ||
| 222 | time_off = 500; | ||
| 223 | } | ||
| 224 | |||
| 225 | period = time_on + time_off; | ||
| 226 | |||
| 227 | /* If period not supported by hardware, default to someting sane. */ | ||
| 228 | if ((period < PCA963X_BLINK_PERIOD_MIN) || | ||
| 229 | (period > PCA963X_BLINK_PERIOD_MAX)) { | ||
| 230 | time_on = 500; | ||
| 231 | time_off = 500; | ||
| 232 | period = time_on + time_off; | ||
| 233 | } | ||
| 234 | |||
| 235 | /* | ||
| 236 | * From manual: duty cycle = (GDC / 256) -> | ||
| 237 | * (time_on / period) = (GDC / 256) -> | ||
| 238 | * GDC = ((time_on * 256) / period) | ||
| 239 | */ | ||
| 240 | gdc = (time_on * 256) / period; | ||
| 241 | |||
| 242 | /* | ||
| 243 | * From manual: period = ((GFRQ + 1) / 24) in seconds. | ||
| 244 | * So, period (in ms) = (((GFRQ + 1) / 24) * 1000) -> | ||
| 245 | * GFRQ = ((period * 24 / 1000) - 1) | ||
| 246 | */ | ||
| 247 | gfrq = (period * 24 / 1000) - 1; | ||
| 248 | |||
| 249 | pca963x->cmd = BLINK_SET; | ||
| 250 | pca963x->gdc = gdc; | ||
| 251 | pca963x->gfrq = gfrq; | ||
| 252 | |||
| 253 | /* | ||
| 254 | * Must use workqueue for the actual I/O since I2C operations | ||
| 255 | * can sleep. | ||
| 256 | */ | ||
| 257 | schedule_work(&pca963x->work); | ||
| 258 | |||
| 259 | *delay_on = time_on; | ||
| 260 | *delay_off = time_off; | ||
| 261 | |||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 265 | #if IS_ENABLED(CONFIG_OF) | ||
| 266 | static struct pca963x_platform_data * | ||
| 267 | pca963x_dt_init(struct i2c_client *client, struct pca963x_chipdef *chip) | ||
| 268 | { | ||
| 269 | struct device_node *np = client->dev.of_node, *child; | ||
| 270 | struct pca963x_platform_data *pdata; | ||
| 271 | struct led_info *pca963x_leds; | ||
| 272 | int count; | ||
| 273 | |||
| 274 | count = of_get_child_count(np); | ||
| 275 | if (!count || count > chip->n_leds) | ||
| 276 | return ERR_PTR(-ENODEV); | ||
| 277 | |||
| 278 | pca963x_leds = devm_kzalloc(&client->dev, | ||
| 279 | sizeof(struct led_info) * chip->n_leds, GFP_KERNEL); | ||
| 280 | if (!pca963x_leds) | ||
| 281 | return ERR_PTR(-ENOMEM); | ||
| 282 | |||
| 283 | for_each_child_of_node(np, child) { | ||
| 284 | struct led_info led; | ||
| 285 | u32 reg; | ||
| 286 | int res; | ||
| 287 | |||
| 288 | res = of_property_read_u32(child, "reg", ®); | ||
| 289 | if ((res != 0) || (reg >= chip->n_leds)) | ||
| 290 | continue; | ||
| 291 | led.name = | ||
| 292 | of_get_property(child, "label", NULL) ? : child->name; | ||
| 293 | led.default_trigger = | ||
| 294 | of_get_property(child, "linux,default-trigger", NULL); | ||
| 295 | pca963x_leds[reg] = led; | ||
| 296 | } | ||
| 297 | pdata = devm_kzalloc(&client->dev, | ||
| 298 | sizeof(struct pca963x_platform_data), GFP_KERNEL); | ||
| 299 | if (!pdata) | ||
| 300 | return ERR_PTR(-ENOMEM); | ||
| 301 | |||
| 302 | pdata->leds.leds = pca963x_leds; | ||
| 303 | pdata->leds.num_leds = chip->n_leds; | ||
| 304 | |||
| 305 | /* default to open-drain unless totem pole (push-pull) is specified */ | ||
| 306 | if (of_property_read_bool(np, "nxp,totem-pole")) | ||
| 307 | pdata->outdrv = PCA963X_TOTEM_POLE; | ||
| 308 | else | ||
| 309 | pdata->outdrv = PCA963X_OPEN_DRAIN; | ||
| 310 | |||
| 311 | /* default to software blinking unless hardware blinking is specified */ | ||
| 312 | if (of_property_read_bool(np, "nxp,hw-blink")) | ||
| 313 | pdata->blink_type = PCA963X_HW_BLINK; | ||
| 314 | else | ||
| 315 | pdata->blink_type = PCA963X_SW_BLINK; | ||
| 316 | |||
| 317 | return pdata; | ||
| 318 | } | ||
| 319 | |||
| 320 | static const struct of_device_id of_pca963x_match[] = { | ||
| 321 | { .compatible = "nxp,pca9632", }, | ||
| 322 | { .compatible = "nxp,pca9633", }, | ||
| 323 | { .compatible = "nxp,pca9634", }, | ||
| 324 | {}, | ||
| 325 | }; | ||
| 326 | #else | ||
| 327 | static struct pca963x_platform_data * | ||
| 328 | pca963x_dt_init(struct i2c_client *client, struct pca963x_chipdef *chip) | ||
| 329 | { | ||
| 330 | return ERR_PTR(-ENODEV); | ||
| 331 | } | ||
| 332 | #endif | ||
| 333 | |||
| 334 | static int pca963x_probe(struct i2c_client *client, | ||
| 335 | const struct i2c_device_id *id) | ||
| 336 | { | ||
| 337 | struct pca963x *pca963x_chip; | ||
| 338 | struct pca963x_led *pca963x; | ||
| 339 | struct pca963x_platform_data *pdata; | ||
| 340 | struct pca963x_chipdef *chip; | ||
| 341 | int i, err; | ||
| 342 | |||
| 343 | chip = &pca963x_chipdefs[id->driver_data]; | ||
| 344 | pdata = dev_get_platdata(&client->dev); | ||
| 345 | |||
| 346 | if (!pdata) { | ||
| 347 | pdata = pca963x_dt_init(client, chip); | ||
| 348 | if (IS_ERR(pdata)) { | ||
| 349 | dev_warn(&client->dev, "could not parse configuration\n"); | ||
| 350 | pdata = NULL; | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | if (pdata && (pdata->leds.num_leds < 1 || | ||
| 355 | pdata->leds.num_leds > chip->n_leds)) { | ||
| 356 | dev_err(&client->dev, "board info must claim 1-%d LEDs", | ||
| 357 | chip->n_leds); | ||
| 358 | return -EINVAL; | ||
| 359 | } | ||
| 360 | |||
| 361 | pca963x_chip = devm_kzalloc(&client->dev, sizeof(*pca963x_chip), | ||
| 362 | GFP_KERNEL); | ||
| 363 | if (!pca963x_chip) | ||
| 364 | return -ENOMEM; | ||
| 365 | pca963x = devm_kzalloc(&client->dev, chip->n_leds * sizeof(*pca963x), | ||
| 366 | GFP_KERNEL); | ||
| 367 | if (!pca963x) | ||
| 368 | return -ENOMEM; | ||
| 369 | |||
| 370 | i2c_set_clientdata(client, pca963x_chip); | ||
| 371 | |||
| 372 | mutex_init(&pca963x_chip->mutex); | ||
| 373 | pca963x_chip->chipdef = chip; | ||
| 374 | pca963x_chip->client = client; | ||
| 375 | pca963x_chip->leds = pca963x; | ||
| 376 | |||
| 377 | /* Turn off LEDs by default*/ | ||
| 378 | i2c_smbus_write_byte_data(client, chip->ledout_base, 0x00); | ||
| 379 | if (chip->n_leds > 4) | ||
| 380 | i2c_smbus_write_byte_data(client, chip->ledout_base + 1, 0x00); | ||
| 381 | |||
| 382 | for (i = 0; i < chip->n_leds; i++) { | ||
| 383 | pca963x[i].led_num = i; | ||
| 384 | pca963x[i].chip = pca963x_chip; | ||
| 385 | |||
| 386 | /* Platform data can specify LED names and default triggers */ | ||
| 387 | if (pdata && i < pdata->leds.num_leds) { | ||
| 388 | if (pdata->leds.leds[i].name) | ||
| 389 | snprintf(pca963x[i].name, | ||
| 390 | sizeof(pca963x[i].name), "pca963x:%s", | ||
| 391 | pdata->leds.leds[i].name); | ||
| 392 | if (pdata->leds.leds[i].default_trigger) | ||
| 393 | pca963x[i].led_cdev.default_trigger = | ||
| 394 | pdata->leds.leds[i].default_trigger; | ||
| 395 | } | ||
| 396 | if (!pdata || i >= pdata->leds.num_leds || | ||
| 397 | !pdata->leds.leds[i].name) | ||
| 398 | snprintf(pca963x[i].name, sizeof(pca963x[i].name), | ||
| 399 | "pca963x:%d:%.2x:%d", client->adapter->nr, | ||
| 400 | client->addr, i); | ||
| 401 | |||
| 402 | pca963x[i].led_cdev.name = pca963x[i].name; | ||
| 403 | pca963x[i].led_cdev.brightness_set = pca963x_led_set; | ||
| 404 | |||
| 405 | if (pdata && pdata->blink_type == PCA963X_HW_BLINK) | ||
| 406 | pca963x[i].led_cdev.blink_set = pca963x_blink_set; | ||
| 407 | |||
| 408 | INIT_WORK(&pca963x[i].work, pca963x_work); | ||
| 409 | |||
| 410 | err = led_classdev_register(&client->dev, &pca963x[i].led_cdev); | ||
| 411 | if (err < 0) | ||
| 412 | goto exit; | ||
| 413 | } | ||
| 414 | |||
| 415 | /* Disable LED all-call address and set normal mode */ | ||
| 416 | i2c_smbus_write_byte_data(client, PCA963X_MODE1, 0x00); | ||
| 417 | |||
| 418 | /* Configure output: open-drain or totem pole (push-pull) */ | ||
| 419 | if (pdata && pdata->outdrv == PCA963X_OPEN_DRAIN) | ||
| 420 | i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x01); | ||
| 421 | |||
| 422 | return 0; | ||
| 423 | |||
| 424 | exit: | ||
| 425 | while (i--) { | ||
| 426 | led_classdev_unregister(&pca963x[i].led_cdev); | ||
| 427 | cancel_work_sync(&pca963x[i].work); | ||
| 428 | } | ||
| 429 | |||
| 430 | return err; | ||
| 431 | } | ||
| 432 | |||
| 433 | static int pca963x_remove(struct i2c_client *client) | ||
| 434 | { | ||
| 435 | struct pca963x *pca963x = i2c_get_clientdata(client); | ||
| 436 | int i; | ||
| 437 | |||
| 438 | for (i = 0; i < pca963x->chipdef->n_leds; i++) { | ||
| 439 | led_classdev_unregister(&pca963x->leds[i].led_cdev); | ||
| 440 | cancel_work_sync(&pca963x->leds[i].work); | ||
| 441 | } | ||
| 442 | |||
| 443 | return 0; | ||
| 444 | } | ||
| 445 | |||
| 446 | static struct i2c_driver pca963x_driver = { | ||
| 447 | .driver = { | ||
| 448 | .name = "leds-pca963x", | ||
| 449 | .owner = THIS_MODULE, | ||
| 450 | .of_match_table = of_match_ptr(of_pca963x_match), | ||
| 451 | }, | ||
| 452 | .probe = pca963x_probe, | ||
| 453 | .remove = pca963x_remove, | ||
| 454 | .id_table = pca963x_id, | ||
| 455 | }; | ||
| 456 | |||
| 457 | module_i2c_driver(pca963x_driver); | ||
| 458 | |||
| 459 | MODULE_AUTHOR("Peter Meerwald <p.meerwald@bct-electronic.com>"); | ||
| 460 | MODULE_DESCRIPTION("PCA963X LED driver"); | ||
| 461 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index faf52c005e8c..bb6f94898541 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c | |||
| @@ -147,7 +147,7 @@ err: | |||
| 147 | 147 | ||
| 148 | static int led_pwm_probe(struct platform_device *pdev) | 148 | static int led_pwm_probe(struct platform_device *pdev) |
| 149 | { | 149 | { |
| 150 | struct led_pwm_platform_data *pdata = pdev->dev.platform_data; | 150 | struct led_pwm_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 151 | struct led_pwm_priv *priv; | 151 | struct led_pwm_priv *priv; |
| 152 | int i, ret = 0; | 152 | int i, ret = 0; |
| 153 | 153 | ||
diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c index 4253a9b03dbf..358430db6e66 100644 --- a/drivers/leds/leds-regulator.c +++ b/drivers/leds/leds-regulator.c | |||
| @@ -142,7 +142,8 @@ static void regulator_led_brightness_set(struct led_classdev *led_cdev, | |||
| 142 | 142 | ||
| 143 | static int regulator_led_probe(struct platform_device *pdev) | 143 | static int regulator_led_probe(struct platform_device *pdev) |
| 144 | { | 144 | { |
| 145 | struct led_regulator_platform_data *pdata = pdev->dev.platform_data; | 145 | struct led_regulator_platform_data *pdata = |
| 146 | dev_get_platdata(&pdev->dev); | ||
| 146 | struct regulator_led *led; | 147 | struct regulator_led *led; |
| 147 | struct regulator *vcc; | 148 | struct regulator *vcc; |
| 148 | int ret = 0; | 149 | int ret = 0; |
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c index e1a0df63a37f..76483fb5ee45 100644 --- a/drivers/leds/leds-s3c24xx.c +++ b/drivers/leds/leds-s3c24xx.c | |||
| @@ -71,7 +71,7 @@ static int s3c24xx_led_remove(struct platform_device *dev) | |||
| 71 | 71 | ||
| 72 | static int s3c24xx_led_probe(struct platform_device *dev) | 72 | static int s3c24xx_led_probe(struct platform_device *dev) |
| 73 | { | 73 | { |
| 74 | struct s3c24xx_led_platdata *pdata = dev->dev.platform_data; | 74 | struct s3c24xx_led_platdata *pdata = dev_get_platdata(&dev->dev); |
| 75 | struct s3c24xx_gpio_led *led; | 75 | struct s3c24xx_gpio_led *led; |
| 76 | int ret; | 76 | int ret; |
| 77 | 77 | ||
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c index 64e204e714f6..5b8f938a8d73 100644 --- a/drivers/leds/leds-ss4200.c +++ b/drivers/leds/leds-ss4200.c | |||
| @@ -91,7 +91,7 @@ MODULE_PARM_DESC(nodetect, "Skip DMI-based hardware detection"); | |||
| 91 | * detected as working, but in reality it is not) as low as | 91 | * detected as working, but in reality it is not) as low as |
| 92 | * possible. | 92 | * possible. |
| 93 | */ | 93 | */ |
| 94 | static struct dmi_system_id __initdata nas_led_whitelist[] = { | 94 | static struct dmi_system_id nas_led_whitelist[] __initdata = { |
| 95 | { | 95 | { |
| 96 | .callback = ss4200_led_dmi_callback, | 96 | .callback = ss4200_led_dmi_callback, |
| 97 | .ident = "Intel SS4200-E", | 97 | .ident = "Intel SS4200-E", |
| @@ -197,7 +197,7 @@ static void nasgpio_led_set_attr(struct led_classdev *led_cdev, | |||
| 197 | spin_unlock(&nasgpio_gpio_lock); | 197 | spin_unlock(&nasgpio_gpio_lock); |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | u32 nasgpio_led_get_attr(struct led_classdev *led_cdev, u32 port) | 200 | static u32 nasgpio_led_get_attr(struct led_classdev *led_cdev, u32 port) |
| 201 | { | 201 | { |
| 202 | struct nasgpio_led *led = led_classdev_to_nasgpio_led(led_cdev); | 202 | struct nasgpio_led *led = led_classdev_to_nasgpio_led(led_cdev); |
| 203 | u32 gpio_in; | 203 | u32 gpio_in; |
diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c index 98fe021ba276..8cc304f36728 100644 --- a/drivers/leds/leds-tca6507.c +++ b/drivers/leds/leds-tca6507.c | |||
| @@ -737,7 +737,7 @@ static int tca6507_probe(struct i2c_client *client, | |||
| 737 | int i = 0; | 737 | int i = 0; |
| 738 | 738 | ||
| 739 | adapter = to_i2c_adapter(client->dev.parent); | 739 | adapter = to_i2c_adapter(client->dev.parent); |
| 740 | pdata = client->dev.platform_data; | 740 | pdata = dev_get_platdata(&client->dev); |
| 741 | 741 | ||
| 742 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) | 742 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) |
| 743 | return -EIO; | 743 | return -EIO; |
diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c index 120815a42701..0a1a13f3a6a5 100644 --- a/drivers/leds/leds-wm831x-status.c +++ b/drivers/leds/leds-wm831x-status.c | |||
| @@ -230,9 +230,9 @@ static int wm831x_status_probe(struct platform_device *pdev) | |||
| 230 | int id = pdev->id % ARRAY_SIZE(chip_pdata->status); | 230 | int id = pdev->id % ARRAY_SIZE(chip_pdata->status); |
| 231 | int ret; | 231 | int ret; |
| 232 | 232 | ||
| 233 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 233 | res = platform_get_resource(pdev, IORESOURCE_REG, 0); |
| 234 | if (res == NULL) { | 234 | if (res == NULL) { |
| 235 | dev_err(&pdev->dev, "No I/O resource\n"); | 235 | dev_err(&pdev->dev, "No register resource\n"); |
| 236 | ret = -EINVAL; | 236 | ret = -EINVAL; |
| 237 | goto err; | 237 | goto err; |
| 238 | } | 238 | } |
| @@ -246,8 +246,8 @@ static int wm831x_status_probe(struct platform_device *pdev) | |||
| 246 | drvdata->wm831x = wm831x; | 246 | drvdata->wm831x = wm831x; |
| 247 | drvdata->reg = res->start; | 247 | drvdata->reg = res->start; |
| 248 | 248 | ||
| 249 | if (wm831x->dev->platform_data) | 249 | if (dev_get_platdata(wm831x->dev)) |
| 250 | chip_pdata = wm831x->dev->platform_data; | 250 | chip_pdata = dev_get_platdata(wm831x->dev); |
| 251 | else | 251 | else |
| 252 | chip_pdata = NULL; | 252 | chip_pdata = NULL; |
| 253 | 253 | ||
diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c index 8a181d56602d..3f75fd22fd49 100644 --- a/drivers/leds/leds-wm8350.c +++ b/drivers/leds/leds-wm8350.c | |||
| @@ -203,7 +203,7 @@ static int wm8350_led_probe(struct platform_device *pdev) | |||
| 203 | { | 203 | { |
| 204 | struct regulator *isink, *dcdc; | 204 | struct regulator *isink, *dcdc; |
| 205 | struct wm8350_led *led; | 205 | struct wm8350_led *led; |
| 206 | struct wm8350_led_platform_data *pdata = pdev->dev.platform_data; | 206 | struct wm8350_led_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 207 | int i; | 207 | int i; |
| 208 | 208 | ||
| 209 | if (pdata == NULL) { | 209 | if (pdata == NULL) { |
diff --git a/drivers/leds/trigger/ledtrig-backlight.c b/drivers/leds/trigger/ledtrig-backlight.c index 3c9c88a07eb8..47e55aa9eefa 100644 --- a/drivers/leds/trigger/ledtrig-backlight.c +++ b/drivers/leds/trigger/ledtrig-backlight.c | |||
| @@ -36,26 +36,28 @@ static int fb_notifier_callback(struct notifier_block *p, | |||
| 36 | struct bl_trig_notifier, notifier); | 36 | struct bl_trig_notifier, notifier); |
| 37 | struct led_classdev *led = n->led; | 37 | struct led_classdev *led = n->led; |
| 38 | struct fb_event *fb_event = data; | 38 | struct fb_event *fb_event = data; |
| 39 | int *blank = fb_event->data; | 39 | int *blank; |
| 40 | int new_status = *blank ? BLANK : UNBLANK; | 40 | int new_status; |
| 41 | 41 | ||
| 42 | switch (event) { | 42 | /* If we aren't interested in this event, skip it immediately ... */ |
| 43 | case FB_EVENT_BLANK: | 43 | if (event != FB_EVENT_BLANK) |
| 44 | if (new_status == n->old_status) | 44 | return 0; |
| 45 | break; | ||
| 46 | 45 | ||
| 47 | if ((n->old_status == UNBLANK) ^ n->invert) { | 46 | blank = fb_event->data; |
| 48 | n->brightness = led->brightness; | 47 | new_status = *blank ? BLANK : UNBLANK; |
| 49 | __led_set_brightness(led, LED_OFF); | ||
| 50 | } else { | ||
| 51 | __led_set_brightness(led, n->brightness); | ||
| 52 | } | ||
| 53 | 48 | ||
| 54 | n->old_status = new_status; | 49 | if (new_status == n->old_status) |
| 50 | return 0; | ||
| 55 | 51 | ||
| 56 | break; | 52 | if ((n->old_status == UNBLANK) ^ n->invert) { |
| 53 | n->brightness = led->brightness; | ||
| 54 | __led_set_brightness(led, LED_OFF); | ||
| 55 | } else { | ||
| 56 | __led_set_brightness(led, n->brightness); | ||
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | n->old_status = new_status; | ||
| 60 | |||
| 59 | return 0; | 61 | return 0; |
| 60 | } | 62 | } |
| 61 | 63 | ||
