diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-28 21:53:01 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-28 21:53:01 -0500 |
commit | 268943fb7529a15254a5247372119ba4bd735e94 (patch) | |
tree | 790d42cfade2a35b0eec5e1b7e0ac3795d399bcc /drivers | |
parent | 2ad48ee810335bdd99de96e1a0796ba34c0e8301 (diff) | |
parent | 3cb6f44aedf519dce4a9106dec675b94d675c539 (diff) |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds
Pull LED subsystem update from Bryan Wu:
"Basically this cycle is mostly cleanup for LED subsystem"
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds:
leds: s3c24xx: Remove hardware.h inclusion
leds: replace list_for_each with list_for_each_entry
leds: kirkwood: Cleanup in header files
leds: pwm: Remove a warning on non-DT platforms
leds: leds-pwm: fix duty time overflow.
leds: leds-mc13783: Remove unneeded mc13xxx_{un}lock
leds: leds-mc13783: Remove duplicate field in platform data
drivers: leds: leds-tca6507: check CONFIG_GPIOLIB whether defined for 'gpio_base'
leds: lp5523: Support LED MUX configuration on running a pattern
leds: lp5521/5523: Fix multiple engine usage bug
LEDS: tca6507 - fix up some comments.
LEDS: tca6507: add device-tree support for GPIO configuration.
LEDS: tca6507 - fix bugs in parsing of device-tree configuration.
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/leds/led-triggers.c | 15 | ||||
-rw-r--r-- | drivers/leds/leds-lp5521.c | 18 | ||||
-rw-r--r-- | drivers/leds/leds-lp5523.c | 20 | ||||
-rw-r--r-- | drivers/leds/leds-lp55xx-common.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-mc13783.c | 89 | ||||
-rw-r--r-- | drivers/leds/leds-pwm.c | 9 | ||||
-rw-r--r-- | drivers/leds/leds-s3c24xx.c | 3 | ||||
-rw-r--r-- | drivers/leds/leds-tca6507.c | 207 |
8 files changed, 160 insertions, 203 deletions
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 3c972b2f9893..e387f41a9cb7 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c | |||
@@ -242,18 +242,14 @@ EXPORT_SYMBOL_GPL(led_trigger_unregister); | |||
242 | void led_trigger_event(struct led_trigger *trig, | 242 | void led_trigger_event(struct led_trigger *trig, |
243 | enum led_brightness brightness) | 243 | enum led_brightness brightness) |
244 | { | 244 | { |
245 | struct list_head *entry; | 245 | struct led_classdev *led_cdev; |
246 | 246 | ||
247 | if (!trig) | 247 | if (!trig) |
248 | return; | 248 | return; |
249 | 249 | ||
250 | read_lock(&trig->leddev_list_lock); | 250 | read_lock(&trig->leddev_list_lock); |
251 | list_for_each(entry, &trig->led_cdevs) { | 251 | list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) |
252 | struct led_classdev *led_cdev; | ||
253 | |||
254 | led_cdev = list_entry(entry, struct led_classdev, trig_list); | ||
255 | led_set_brightness(led_cdev, brightness); | 252 | led_set_brightness(led_cdev, brightness); |
256 | } | ||
257 | read_unlock(&trig->leddev_list_lock); | 253 | read_unlock(&trig->leddev_list_lock); |
258 | } | 254 | } |
259 | EXPORT_SYMBOL_GPL(led_trigger_event); | 255 | EXPORT_SYMBOL_GPL(led_trigger_event); |
@@ -264,16 +260,13 @@ static void led_trigger_blink_setup(struct led_trigger *trig, | |||
264 | int oneshot, | 260 | int oneshot, |
265 | int invert) | 261 | int invert) |
266 | { | 262 | { |
267 | struct list_head *entry; | 263 | struct led_classdev *led_cdev; |
268 | 264 | ||
269 | if (!trig) | 265 | if (!trig) |
270 | return; | 266 | return; |
271 | 267 | ||
272 | read_lock(&trig->leddev_list_lock); | 268 | read_lock(&trig->leddev_list_lock); |
273 | list_for_each(entry, &trig->led_cdevs) { | 269 | list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) { |
274 | struct led_classdev *led_cdev; | ||
275 | |||
276 | led_cdev = list_entry(entry, struct led_classdev, trig_list); | ||
277 | if (oneshot) | 270 | if (oneshot) |
278 | led_blink_set_oneshot(led_cdev, delay_on, delay_off, | 271 | led_blink_set_oneshot(led_cdev, delay_on, delay_off, |
279 | invert); | 272 | invert); |
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index a97263e902ff..2ec34cfcedce 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c | |||
@@ -152,12 +152,26 @@ static void lp5521_load_engine(struct lp55xx_chip *chip) | |||
152 | lp5521_wait_opmode_done(); | 152 | lp5521_wait_opmode_done(); |
153 | } | 153 | } |
154 | 154 | ||
155 | static void lp5521_stop_engine(struct lp55xx_chip *chip) | 155 | static void lp5521_stop_all_engines(struct lp55xx_chip *chip) |
156 | { | 156 | { |
157 | lp55xx_write(chip, LP5521_REG_OP_MODE, 0); | 157 | lp55xx_write(chip, LP5521_REG_OP_MODE, 0); |
158 | lp5521_wait_opmode_done(); | 158 | lp5521_wait_opmode_done(); |
159 | } | 159 | } |
160 | 160 | ||
161 | static void lp5521_stop_engine(struct lp55xx_chip *chip) | ||
162 | { | ||
163 | enum lp55xx_engine_index idx = chip->engine_idx; | ||
164 | u8 mask[] = { | ||
165 | [LP55XX_ENGINE_1] = LP5521_MODE_R_M, | ||
166 | [LP55XX_ENGINE_2] = LP5521_MODE_G_M, | ||
167 | [LP55XX_ENGINE_3] = LP5521_MODE_B_M, | ||
168 | }; | ||
169 | |||
170 | lp55xx_update_bits(chip, LP5521_REG_OP_MODE, mask[idx], 0); | ||
171 | |||
172 | lp5521_wait_opmode_done(); | ||
173 | } | ||
174 | |||
161 | static void lp5521_run_engine(struct lp55xx_chip *chip, bool start) | 175 | static void lp5521_run_engine(struct lp55xx_chip *chip, bool start) |
162 | { | 176 | { |
163 | int ret; | 177 | int ret; |
@@ -564,7 +578,7 @@ static int lp5521_remove(struct i2c_client *client) | |||
564 | struct lp55xx_led *led = i2c_get_clientdata(client); | 578 | struct lp55xx_led *led = i2c_get_clientdata(client); |
565 | struct lp55xx_chip *chip = led->chip; | 579 | struct lp55xx_chip *chip = led->chip; |
566 | 580 | ||
567 | lp5521_stop_engine(chip); | 581 | lp5521_stop_all_engines(chip); |
568 | lp55xx_unregister_sysfs(chip); | 582 | lp55xx_unregister_sysfs(chip); |
569 | lp55xx_unregister_leds(led, chip); | 583 | lp55xx_unregister_leds(led, chip); |
570 | lp55xx_deinit_device(chip); | 584 | lp55xx_deinit_device(chip); |
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index 3a0bc886a87a..4ade66a2d9d4 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c | |||
@@ -195,12 +195,26 @@ static void lp5523_load_engine_and_select_page(struct lp55xx_chip *chip) | |||
195 | lp55xx_write(chip, LP5523_REG_PROG_PAGE_SEL, page_sel[idx]); | 195 | lp55xx_write(chip, LP5523_REG_PROG_PAGE_SEL, page_sel[idx]); |
196 | } | 196 | } |
197 | 197 | ||
198 | static void lp5523_stop_engine(struct lp55xx_chip *chip) | 198 | static void lp5523_stop_all_engines(struct lp55xx_chip *chip) |
199 | { | 199 | { |
200 | lp55xx_write(chip, LP5523_REG_OP_MODE, 0); | 200 | lp55xx_write(chip, LP5523_REG_OP_MODE, 0); |
201 | lp5523_wait_opmode_done(); | 201 | lp5523_wait_opmode_done(); |
202 | } | 202 | } |
203 | 203 | ||
204 | static void lp5523_stop_engine(struct lp55xx_chip *chip) | ||
205 | { | ||
206 | enum lp55xx_engine_index idx = chip->engine_idx; | ||
207 | u8 mask[] = { | ||
208 | [LP55XX_ENGINE_1] = LP5523_MODE_ENG1_M, | ||
209 | [LP55XX_ENGINE_2] = LP5523_MODE_ENG2_M, | ||
210 | [LP55XX_ENGINE_3] = LP5523_MODE_ENG3_M, | ||
211 | }; | ||
212 | |||
213 | lp55xx_update_bits(chip, LP5523_REG_OP_MODE, mask[idx], 0); | ||
214 | |||
215 | lp5523_wait_opmode_done(); | ||
216 | } | ||
217 | |||
204 | static void lp5523_turn_off_channels(struct lp55xx_chip *chip) | 218 | static void lp5523_turn_off_channels(struct lp55xx_chip *chip) |
205 | { | 219 | { |
206 | int i; | 220 | int i; |
@@ -311,7 +325,7 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip) | |||
311 | } | 325 | } |
312 | 326 | ||
313 | out: | 327 | out: |
314 | lp5523_stop_engine(chip); | 328 | lp5523_stop_all_engines(chip); |
315 | return ret; | 329 | return ret; |
316 | } | 330 | } |
317 | 331 | ||
@@ -782,7 +796,7 @@ static int lp5523_remove(struct i2c_client *client) | |||
782 | struct lp55xx_led *led = i2c_get_clientdata(client); | 796 | struct lp55xx_led *led = i2c_get_clientdata(client); |
783 | struct lp55xx_chip *chip = led->chip; | 797 | struct lp55xx_chip *chip = led->chip; |
784 | 798 | ||
785 | lp5523_stop_engine(chip); | 799 | lp5523_stop_all_engines(chip); |
786 | lp55xx_unregister_sysfs(chip); | 800 | lp55xx_unregister_sysfs(chip); |
787 | lp55xx_unregister_leds(led, chip); | 801 | lp55xx_unregister_leds(led, chip); |
788 | lp55xx_deinit_device(chip); | 802 | lp55xx_deinit_device(chip); |
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c index 9acc6bb7deef..88317b4f7bf3 100644 --- a/drivers/leds/leds-lp55xx-common.c +++ b/drivers/leds/leds-lp55xx-common.c | |||
@@ -210,6 +210,7 @@ static void lp55xx_firmware_loaded(const struct firmware *fw, void *context) | |||
210 | { | 210 | { |
211 | struct lp55xx_chip *chip = context; | 211 | struct lp55xx_chip *chip = context; |
212 | struct device *dev = &chip->cl->dev; | 212 | struct device *dev = &chip->cl->dev; |
213 | enum lp55xx_engine_index idx = chip->engine_idx; | ||
213 | 214 | ||
214 | if (!fw) { | 215 | if (!fw) { |
215 | dev_err(dev, "firmware request failed\n"); | 216 | dev_err(dev, "firmware request failed\n"); |
@@ -219,6 +220,7 @@ static void lp55xx_firmware_loaded(const struct firmware *fw, void *context) | |||
219 | /* handling firmware data is chip dependent */ | 220 | /* handling firmware data is chip dependent */ |
220 | mutex_lock(&chip->lock); | 221 | mutex_lock(&chip->lock); |
221 | 222 | ||
223 | chip->engines[idx - 1].mode = LP55XX_ENGINE_LOAD; | ||
222 | chip->fw = fw; | 224 | chip->fw = fw; |
223 | if (chip->cfg->firmware_cb) | 225 | if (chip->cfg->firmware_cb) |
224 | chip->cfg->firmware_cb(chip); | 226 | chip->cfg->firmware_cb(chip); |
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c index fa9b439323bd..ca87a1b4a0db 100644 --- a/drivers/leds/leds-mc13783.c +++ b/drivers/leds/leds-mc13783.c | |||
@@ -117,9 +117,7 @@ static void mc13xxx_led_work(struct work_struct *work) | |||
117 | BUG(); | 117 | BUG(); |
118 | } | 118 | } |
119 | 119 | ||
120 | mc13xxx_lock(led->master); | ||
121 | mc13xxx_reg_rmw(led->master, reg, mask << shift, value << shift); | 120 | mc13xxx_reg_rmw(led->master, reg, mask << shift, value << shift); |
122 | mc13xxx_unlock(led->master); | ||
123 | } | 121 | } |
124 | 122 | ||
125 | static void mc13xxx_led_set(struct led_classdev *led_cdev, | 123 | static void mc13xxx_led_set(struct led_classdev *led_cdev, |
@@ -132,75 +130,6 @@ static void mc13xxx_led_set(struct led_classdev *led_cdev, | |||
132 | schedule_work(&led->work); | 130 | schedule_work(&led->work); |
133 | } | 131 | } |
134 | 132 | ||
135 | static int __init mc13xxx_led_setup(struct mc13xxx_led *led, int max_current) | ||
136 | { | ||
137 | int shift, mask, reg, ret, bank; | ||
138 | |||
139 | switch (led->id) { | ||
140 | case MC13783_LED_MD: | ||
141 | reg = MC13XXX_REG_LED_CONTROL(2); | ||
142 | shift = 0; | ||
143 | mask = 0x07; | ||
144 | break; | ||
145 | case MC13783_LED_AD: | ||
146 | reg = MC13XXX_REG_LED_CONTROL(2); | ||
147 | shift = 3; | ||
148 | mask = 0x07; | ||
149 | break; | ||
150 | case MC13783_LED_KP: | ||
151 | reg = MC13XXX_REG_LED_CONTROL(2); | ||
152 | shift = 6; | ||
153 | mask = 0x07; | ||
154 | break; | ||
155 | case MC13783_LED_R1: | ||
156 | case MC13783_LED_G1: | ||
157 | case MC13783_LED_B1: | ||
158 | case MC13783_LED_R2: | ||
159 | case MC13783_LED_G2: | ||
160 | case MC13783_LED_B2: | ||
161 | case MC13783_LED_R3: | ||
162 | case MC13783_LED_G3: | ||
163 | case MC13783_LED_B3: | ||
164 | bank = (led->id - MC13783_LED_R1) / 3; | ||
165 | reg = MC13XXX_REG_LED_CONTROL(3) + bank; | ||
166 | shift = ((led->id - MC13783_LED_R1) - bank * 3) * 2; | ||
167 | mask = 0x03; | ||
168 | break; | ||
169 | case MC13892_LED_MD: | ||
170 | reg = MC13XXX_REG_LED_CONTROL(0); | ||
171 | shift = 9; | ||
172 | mask = 0x07; | ||
173 | break; | ||
174 | case MC13892_LED_AD: | ||
175 | reg = MC13XXX_REG_LED_CONTROL(0); | ||
176 | shift = 21; | ||
177 | mask = 0x07; | ||
178 | break; | ||
179 | case MC13892_LED_KP: | ||
180 | reg = MC13XXX_REG_LED_CONTROL(1); | ||
181 | shift = 9; | ||
182 | mask = 0x07; | ||
183 | break; | ||
184 | case MC13892_LED_R: | ||
185 | case MC13892_LED_G: | ||
186 | case MC13892_LED_B: | ||
187 | bank = (led->id - MC13892_LED_R) / 2; | ||
188 | reg = MC13XXX_REG_LED_CONTROL(2) + bank; | ||
189 | shift = ((led->id - MC13892_LED_R) - bank * 2) * 12 + 9; | ||
190 | mask = 0x07; | ||
191 | break; | ||
192 | default: | ||
193 | BUG(); | ||
194 | } | ||
195 | |||
196 | mc13xxx_lock(led->master); | ||
197 | ret = mc13xxx_reg_rmw(led->master, reg, mask << shift, | ||
198 | max_current << shift); | ||
199 | mc13xxx_unlock(led->master); | ||
200 | |||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | static int __init mc13xxx_led_probe(struct platform_device *pdev) | 133 | static int __init mc13xxx_led_probe(struct platform_device *pdev) |
205 | { | 134 | { |
206 | struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); | 135 | struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); |
@@ -233,31 +162,22 @@ static int __init mc13xxx_led_probe(struct platform_device *pdev) | |||
233 | leds->num_leds = num_leds; | 162 | leds->num_leds = num_leds; |
234 | platform_set_drvdata(pdev, leds); | 163 | platform_set_drvdata(pdev, leds); |
235 | 164 | ||
236 | mc13xxx_lock(mcdev); | ||
237 | for (i = 0; i < devtype->num_regs; i++) { | 165 | for (i = 0; i < devtype->num_regs; i++) { |
238 | reg = pdata->led_control[i]; | 166 | reg = pdata->led_control[i]; |
239 | WARN_ON(reg >= (1 << 24)); | 167 | WARN_ON(reg >= (1 << 24)); |
240 | ret = mc13xxx_reg_write(mcdev, MC13XXX_REG_LED_CONTROL(i), reg); | 168 | ret = mc13xxx_reg_write(mcdev, MC13XXX_REG_LED_CONTROL(i), reg); |
241 | if (ret) | 169 | if (ret) |
242 | break; | 170 | return ret; |
243 | } | ||
244 | mc13xxx_unlock(mcdev); | ||
245 | |||
246 | if (ret) { | ||
247 | dev_err(&pdev->dev, "Unable to init LED driver\n"); | ||
248 | return ret; | ||
249 | } | 171 | } |
250 | 172 | ||
251 | for (i = 0; i < num_leds; i++) { | 173 | for (i = 0; i < num_leds; i++) { |
252 | const char *name, *trig; | 174 | const char *name, *trig; |
253 | char max_current; | ||
254 | 175 | ||
255 | ret = -EINVAL; | 176 | ret = -EINVAL; |
256 | 177 | ||
257 | id = pdata->led[i].id; | 178 | id = pdata->led[i].id; |
258 | name = pdata->led[i].name; | 179 | name = pdata->led[i].name; |
259 | trig = pdata->led[i].default_trigger; | 180 | trig = pdata->led[i].default_trigger; |
260 | max_current = pdata->led[i].max_current; | ||
261 | 181 | ||
262 | if ((id > devtype->led_max) || (id < devtype->led_min)) { | 182 | if ((id > devtype->led_max) || (id < devtype->led_min)) { |
263 | dev_err(&pdev->dev, "Invalid ID %i\n", id); | 183 | dev_err(&pdev->dev, "Invalid ID %i\n", id); |
@@ -280,11 +200,6 @@ static int __init mc13xxx_led_probe(struct platform_device *pdev) | |||
280 | 200 | ||
281 | INIT_WORK(&leds->led[i].work, mc13xxx_led_work); | 201 | INIT_WORK(&leds->led[i].work, mc13xxx_led_work); |
282 | 202 | ||
283 | ret = mc13xxx_led_setup(&leds->led[i], max_current); | ||
284 | if (ret) { | ||
285 | dev_err(&pdev->dev, "Unable to setup LED %i\n", id); | ||
286 | break; | ||
287 | } | ||
288 | ret = led_classdev_register(pdev->dev.parent, | 203 | ret = led_classdev_register(pdev->dev.parent, |
289 | &leds->led[i].cdev); | 204 | &leds->led[i].cdev); |
290 | if (ret) { | 205 | if (ret) { |
@@ -313,10 +228,8 @@ static int mc13xxx_led_remove(struct platform_device *pdev) | |||
313 | cancel_work_sync(&leds->led[i].work); | 228 | cancel_work_sync(&leds->led[i].work); |
314 | } | 229 | } |
315 | 230 | ||
316 | mc13xxx_lock(mcdev); | ||
317 | for (i = 0; i < leds->devtype->num_regs; i++) | 231 | for (i = 0; i < leds->devtype->num_regs; i++) |
318 | mc13xxx_reg_write(mcdev, MC13XXX_REG_LED_CONTROL(i), 0); | 232 | mc13xxx_reg_write(mcdev, MC13XXX_REG_LED_CONTROL(i), 0); |
319 | mc13xxx_unlock(mcdev); | ||
320 | 233 | ||
321 | return 0; | 234 | return 0; |
322 | } | 235 | } |
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index b31d8e99c419..605047428b5a 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c | |||
@@ -66,9 +66,11 @@ static void led_pwm_set(struct led_classdev *led_cdev, | |||
66 | struct led_pwm_data *led_dat = | 66 | struct led_pwm_data *led_dat = |
67 | container_of(led_cdev, struct led_pwm_data, cdev); | 67 | container_of(led_cdev, struct led_pwm_data, cdev); |
68 | unsigned int max = led_dat->cdev.max_brightness; | 68 | unsigned int max = led_dat->cdev.max_brightness; |
69 | unsigned int period = led_dat->period; | 69 | unsigned long long duty = led_dat->period; |
70 | 70 | ||
71 | led_dat->duty = brightness * period / max; | 71 | duty *= brightness; |
72 | do_div(duty, max); | ||
73 | led_dat->duty = duty; | ||
72 | 74 | ||
73 | if (led_dat->can_sleep) | 75 | if (led_dat->can_sleep) |
74 | schedule_work(&led_dat->work); | 76 | schedule_work(&led_dat->work); |
@@ -85,11 +87,10 @@ static inline size_t sizeof_pwm_leds_priv(int num_leds) | |||
85 | static int led_pwm_create_of(struct platform_device *pdev, | 87 | static int led_pwm_create_of(struct platform_device *pdev, |
86 | struct led_pwm_priv *priv) | 88 | struct led_pwm_priv *priv) |
87 | { | 89 | { |
88 | struct device_node *node = pdev->dev.of_node; | ||
89 | struct device_node *child; | 90 | struct device_node *child; |
90 | int ret; | 91 | int ret; |
91 | 92 | ||
92 | for_each_child_of_node(node, child) { | 93 | for_each_child_of_node(pdev->dev.of_node, child) { |
93 | struct led_pwm_data *led_dat = &priv->leds[priv->num_leds]; | 94 | struct led_pwm_data *led_dat = &priv->leds[priv->num_leds]; |
94 | 95 | ||
95 | led_dat->cdev.name = of_get_property(child, "label", | 96 | led_dat->cdev.name = of_get_property(child, "label", |
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c index 87cf215af798..98174e7240ee 100644 --- a/drivers/leds/leds-s3c24xx.c +++ b/drivers/leds/leds-s3c24xx.c | |||
@@ -18,11 +18,10 @@ | |||
18 | #include <linux/gpio.h> | 18 | #include <linux/gpio.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/platform_data/leds-s3c24xx.h> | ||
21 | 22 | ||
22 | #include <mach/hardware.h> | ||
23 | #include <mach/regs-gpio.h> | 23 | #include <mach/regs-gpio.h> |
24 | #include <plat/gpio-cfg.h> | 24 | #include <plat/gpio-cfg.h> |
25 | #include <linux/platform_data/leds-s3c24xx.h> | ||
26 | 25 | ||
27 | /* our context */ | 26 | /* our context */ |
28 | 27 | ||
diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c index 8cc304f36728..3d9e267a56c4 100644 --- a/drivers/leds/leds-tca6507.c +++ b/drivers/leds/leds-tca6507.c | |||
@@ -4,77 +4,87 @@ | |||
4 | * The TCA6507 is a programmable LED controller that can drive 7 | 4 | * The TCA6507 is a programmable LED controller that can drive 7 |
5 | * separate lines either by holding them low, or by pulsing them | 5 | * separate lines either by holding them low, or by pulsing them |
6 | * with modulated width. | 6 | * with modulated width. |
7 | * The modulation can be varied in a simple pattern to produce a blink or | 7 | * The modulation can be varied in a simple pattern to produce a |
8 | * double-blink. | 8 | * blink or double-blink. |
9 | * | 9 | * |
10 | * This driver can configure each line either as a 'GPIO' which is out-only | 10 | * This driver can configure each line either as a 'GPIO' which is |
11 | * (no pull-up) or as an LED with variable brightness and hardware-assisted | 11 | * out-only (pull-up resistor required) or as an LED with variable |
12 | * blinking. | 12 | * brightness and hardware-assisted blinking. |
13 | * | 13 | * |
14 | * Apart from OFF and ON there are three programmable brightness levels which | 14 | * Apart from OFF and ON there are three programmable brightness |
15 | * can be programmed from 0 to 15 and indicate how many 500usec intervals in | 15 | * levels which can be programmed from 0 to 15 and indicate how many |
16 | * each 8msec that the led is 'on'. The levels are named MASTER, BANK0 and | 16 | * 500usec intervals in each 8msec that the led is 'on'. The levels |
17 | * BANK1. | 17 | * are named MASTER, BANK0 and BANK1. |
18 | * | 18 | * |
19 | * There are two different blink rates that can be programmed, each with | 19 | * There are two different blink rates that can be programmed, each |
20 | * separate time for rise, on, fall, off and second-off. Thus if 3 or more | 20 | * with separate time for rise, on, fall, off and second-off. Thus if |
21 | * different non-trivial rates are required, software must be used for the extra | 21 | * 3 or more different non-trivial rates are required, software must |
22 | * rates. The two different blink rates must align with the two levels BANK0 and | 22 | * be used for the extra rates. The two different blink rates must |
23 | * BANK1. | 23 | * align with the two levels BANK0 and BANK1. This driver does not |
24 | * This driver does not support double-blink so 'second-off' always matches | 24 | * support double-blink so 'second-off' always matches 'off'. |
25 | * 'off'. | ||
26 | * | 25 | * |
27 | * Only 16 different times can be programmed in a roughly logarithmic scale from | 26 | * Only 16 different times can be programmed in a roughly logarithmic |
28 | * 64ms to 16320ms. To be precise the possible times are: | 27 | * scale from 64ms to 16320ms. To be precise the possible times are: |
29 | * 0, 64, 128, 192, 256, 384, 512, 768, | 28 | * 0, 64, 128, 192, 256, 384, 512, 768, |
30 | * 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320 | 29 | * 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320 |
31 | * | 30 | * |
32 | * Times that cannot be closely matched with these must be | 31 | * Times that cannot be closely matched with these must be handled in |
33 | * handled in software. This driver allows 12.5% error in matching. | 32 | * software. This driver allows 12.5% error in matching. |
34 | * | 33 | * |
35 | * This driver does not allow rise/fall rates to be set explicitly. When trying | 34 | * This driver does not allow rise/fall rates to be set explicitly. |
36 | * to match a given 'on' or 'off' period, an appropriate pair of 'change' and | 35 | * When trying to match a given 'on' or 'off' period, an appropriate |
37 | * 'hold' times are chosen to get a close match. If the target delay is even, | 36 | * pair of 'change' and 'hold' times are chosen to get a close match. |
38 | * the 'change' number will be the smaller; if odd, the 'hold' number will be | 37 | * If the target delay is even, the 'change' number will be the |
39 | * the smaller. | 38 | * smaller; if odd, the 'hold' number will be the smaller. |
40 | 39 | ||
41 | * Choosing pairs of delays with 12.5% errors allows us to match delays in the | 40 | * Choosing pairs of delays with 12.5% errors allows us to match |
42 | * ranges: 56-72, 112-144, 168-216, 224-27504, 28560-36720. | 41 | * delays in the ranges: 56-72, 112-144, 168-216, 224-27504, |
43 | * 26% of the achievable sums can be matched by multiple pairings. For example | 42 | * 28560-36720. |
44 | * 1536 == 1536+0, 1024+512, or 768+768. This driver will always choose the | 43 | * 26% of the achievable sums can be matched by multiple pairings. |
45 | * pairing with the least maximum - 768+768 in this case. Other pairings are | 44 | * For example 1536 == 1536+0, 1024+512, or 768+768. |
46 | * not available. | 45 | * This driver will always choose the pairing with the least |
46 | * maximum - 768+768 in this case. Other pairings are not available. | ||
47 | * | 47 | * |
48 | * Access to the 3 levels and 2 blinks are on a first-come, first-served basis. | 48 | * Access to the 3 levels and 2 blinks are on a first-come, |
49 | * Access can be shared by multiple leds if they have the same level and | 49 | * first-served basis. Access can be shared by multiple leds if they |
50 | * either same blink rates, or some don't blink. | 50 | * have the same level and either same blink rates, or some don't |
51 | * When a led changes, it relinquishes access and tries again, so it might | 51 | * blink. When a led changes, it relinquishes access and tries again, |
52 | * lose access to hardware blink. | 52 | * so it might lose access to hardware blink. |
53 | * If a blink engine cannot be allocated, software blink is used. | ||
54 | * If the desired brightness cannot be allocated, the closest available non-zero | ||
55 | * brightness is used. As 'full' is always available, the worst case would be | ||
56 | * to have two different blink rates at '1', with Max at '2', then other leds | ||
57 | * will have to choose between '2' and '16'. Hopefully this is not likely. | ||
58 | * | 53 | * |
59 | * Each bank (BANK0 and BANK1) has two usage counts - LEDs using the brightness | 54 | * If a blink engine cannot be allocated, software blink is used. If |
60 | * and LEDs using the blink. It can only be reprogrammed when the appropriate | 55 | * the desired brightness cannot be allocated, the closest available |
61 | * counter is zero. The MASTER level has a single usage count. | 56 | * non-zero brightness is used. As 'full' is always available, the |
57 | * worst case would be to have two different blink rates at '1', with | ||
58 | * Max at '2', then other leds will have to choose between '2' and | ||
59 | * '16'. Hopefully this is not likely. | ||
62 | * | 60 | * |
63 | * Each Led has programmable 'on' and 'off' time as milliseconds. With each | 61 | * Each bank (BANK0 and BANK1) has two usage counts - LEDs using the |
64 | * there is a flag saying if it was explicitly requested or defaulted. | 62 | * brightness and LEDs using the blink. It can only be reprogrammed |
65 | * Similarly the banks know if each time was explicit or a default. Defaults | 63 | * when the appropriate counter is zero. The MASTER level has a |
66 | * are permitted to be changed freely - they are not recognised when matching. | 64 | * single usage count. |
67 | * | 65 | * |
66 | * Each LED has programmable 'on' and 'off' time as milliseconds. | ||
67 | * With each there is a flag saying if it was explicitly requested or | ||
68 | * defaulted. Similarly the banks know if each time was explicit or a | ||
69 | * default. Defaults are permitted to be changed freely - they are | ||
70 | * not recognised when matching. | ||
68 | * | 71 | * |
69 | * An led-tca6507 device must be provided with platform data. This data | ||
70 | * lists for each output: the name, default trigger, and whether the signal | ||
71 | * is being used as a GPiO rather than an led. 'struct led_plaform_data' | ||
72 | * is used for this. If 'name' is NULL, the output isn't used. If 'flags' | ||
73 | * is TCA6507_MAKE_CPIO, the output is a GPO. | ||
74 | * The "struct led_platform_data" can be embedded in a | ||
75 | * "struct tca6507_platform_data" which adds a 'gpio_base' for the GPiOs, | ||
76 | * and a 'setup' callback which is called once the GPiOs are available. | ||
77 | * | 72 | * |
73 | * An led-tca6507 device must be provided with platform data or | ||
74 | * configured via devicetree. | ||
75 | * | ||
76 | * The platform-data lists for each output: the name, default trigger, | ||
77 | * and whether the signal is being used as a GPIO rather than an LED. | ||
78 | * 'struct led_plaform_data' is used for this. If 'name' is NULL, the | ||
79 | * output isn't used. If 'flags' is TCA6507_MAKE_GPIO, the output is | ||
80 | * a GPO. The "struct led_platform_data" can be embedded in a "struct | ||
81 | * tca6507_platform_data" which adds a 'gpio_base' for the GPIOs, and | ||
82 | * a 'setup' callback which is called once the GPIOs are available. | ||
83 | * | ||
84 | * When configured via devicetree there is one child for each output. | ||
85 | * The "reg" determines the output number and "compatible" determines | ||
86 | * whether it is an LED or a GPIO. "linux,default-trigger" can set a | ||
87 | * default trigger. | ||
78 | */ | 88 | */ |
79 | 89 | ||
80 | #include <linux/module.h> | 90 | #include <linux/module.h> |
@@ -192,17 +202,18 @@ MODULE_DEVICE_TABLE(i2c, tca6507_id); | |||
192 | static int choose_times(int msec, int *c1p, int *c2p) | 202 | static int choose_times(int msec, int *c1p, int *c2p) |
193 | { | 203 | { |
194 | /* | 204 | /* |
195 | * Choose two timecodes which add to 'msec' as near as possible. | 205 | * Choose two timecodes which add to 'msec' as near as |
196 | * The first returned is the 'on' or 'off' time. The second is to be | 206 | * possible. The first returned is the 'on' or 'off' time. |
197 | * used as a 'fade-on' or 'fade-off' time. If 'msec' is even, | 207 | * The second is to be used as a 'fade-on' or 'fade-off' time. |
198 | * the first will not be smaller than the second. If 'msec' is odd, | 208 | * If 'msec' is even, the first will not be smaller than the |
199 | * the first will not be larger than the second. | 209 | * second. If 'msec' is odd, the first will not be larger |
200 | * If we cannot get a sum within 1/8 of 'msec' fail with -EINVAL, | 210 | * than the second. |
201 | * otherwise return the sum that was achieved, plus 1 if the first is | 211 | * If we cannot get a sum within 1/8 of 'msec' fail with |
202 | * smaller. | 212 | * -EINVAL, otherwise return the sum that was achieved, plus 1 |
203 | * If two possibilities are equally good (e.g. 512+0, 256+256), choose | 213 | * if the first is smaller. |
204 | * the first pair so there is more change-time visible (i.e. it is | 214 | * If two possibilities are equally good (e.g. 512+0, |
205 | * softer). | 215 | * 256+256), choose the first pair so there is more |
216 | * change-time visible (i.e. it is softer). | ||
206 | */ | 217 | */ |
207 | int c1, c2; | 218 | int c1, c2; |
208 | int tmax = msec * 9 / 8; | 219 | int tmax = msec * 9 / 8; |
@@ -255,8 +266,8 @@ static int choose_times(int msec, int *c1p, int *c2p) | |||
255 | } | 266 | } |
256 | 267 | ||
257 | /* | 268 | /* |
258 | * Update the register file with the appropriate 3-bit state for | 269 | * Update the register file with the appropriate 3-bit state for the |
259 | * the given led. | 270 | * given led. |
260 | */ | 271 | */ |
261 | static void set_select(struct tca6507_chip *tca, int led, int val) | 272 | static void set_select(struct tca6507_chip *tca, int led, int val) |
262 | { | 273 | { |
@@ -274,9 +285,9 @@ static void set_select(struct tca6507_chip *tca, int led, int val) | |||
274 | } | 285 | } |
275 | } | 286 | } |
276 | 287 | ||
277 | /* Update the register file with the appropriate 4-bit code for | 288 | /* Update the register file with the appropriate 4-bit code for one |
278 | * one bank or other. This can be used for timers, for levels, or | 289 | * bank or other. This can be used for timers, for levels, or for |
279 | * for initialisation. | 290 | * initialization. |
280 | */ | 291 | */ |
281 | static void set_code(struct tca6507_chip *tca, int reg, int bank, int new) | 292 | static void set_code(struct tca6507_chip *tca, int reg, int bank, int new) |
282 | { | 293 | { |
@@ -309,7 +320,7 @@ static void set_level(struct tca6507_chip *tca, int bank, int level) | |||
309 | tca->bank[bank].level = level; | 320 | tca->bank[bank].level = level; |
310 | } | 321 | } |
311 | 322 | ||
312 | /* Record all relevant time code for a given bank */ | 323 | /* Record all relevant time codes for a given bank */ |
313 | static void set_times(struct tca6507_chip *tca, int bank) | 324 | static void set_times(struct tca6507_chip *tca, int bank) |
314 | { | 325 | { |
315 | int c1, c2; | 326 | int c1, c2; |
@@ -317,7 +328,8 @@ static void set_times(struct tca6507_chip *tca, int bank) | |||
317 | 328 | ||
318 | result = choose_times(tca->bank[bank].ontime, &c1, &c2); | 329 | result = choose_times(tca->bank[bank].ontime, &c1, &c2); |
319 | dev_dbg(&tca->client->dev, | 330 | dev_dbg(&tca->client->dev, |
320 | "Chose on times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1], | 331 | "Chose on times %d(%d) %d(%d) for %dms\n", |
332 | c1, time_codes[c1], | ||
321 | c2, time_codes[c2], tca->bank[bank].ontime); | 333 | c2, time_codes[c2], tca->bank[bank].ontime); |
322 | set_code(tca, TCA6507_FADE_ON, bank, c2); | 334 | set_code(tca, TCA6507_FADE_ON, bank, c2); |
323 | set_code(tca, TCA6507_FULL_ON, bank, c1); | 335 | set_code(tca, TCA6507_FULL_ON, bank, c1); |
@@ -325,7 +337,8 @@ static void set_times(struct tca6507_chip *tca, int bank) | |||
325 | 337 | ||
326 | result = choose_times(tca->bank[bank].offtime, &c1, &c2); | 338 | result = choose_times(tca->bank[bank].offtime, &c1, &c2); |
327 | dev_dbg(&tca->client->dev, | 339 | dev_dbg(&tca->client->dev, |
328 | "Chose off times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1], | 340 | "Chose off times %d(%d) %d(%d) for %dms\n", |
341 | c1, time_codes[c1], | ||
329 | c2, time_codes[c2], tca->bank[bank].offtime); | 342 | c2, time_codes[c2], tca->bank[bank].offtime); |
330 | set_code(tca, TCA6507_FADE_OFF, bank, c2); | 343 | set_code(tca, TCA6507_FADE_OFF, bank, c2); |
331 | set_code(tca, TCA6507_FIRST_OFF, bank, c1); | 344 | set_code(tca, TCA6507_FIRST_OFF, bank, c1); |
@@ -373,7 +386,8 @@ static void led_release(struct tca6507_led *led) | |||
373 | 386 | ||
374 | static int led_prepare(struct tca6507_led *led) | 387 | static int led_prepare(struct tca6507_led *led) |
375 | { | 388 | { |
376 | /* Assign this led to a bank, configuring that bank if necessary. */ | 389 | /* Assign this led to a bank, configuring that bank if |
390 | * necessary. */ | ||
377 | int level = TO_LEVEL(led->led_cdev.brightness); | 391 | int level = TO_LEVEL(led->led_cdev.brightness); |
378 | struct tca6507_chip *tca = led->chip; | 392 | struct tca6507_chip *tca = led->chip; |
379 | int c1, c2; | 393 | int c1, c2; |
@@ -389,10 +403,10 @@ static int led_prepare(struct tca6507_led *led) | |||
389 | 403 | ||
390 | if (led->ontime == 0 || led->offtime == 0) { | 404 | if (led->ontime == 0 || led->offtime == 0) { |
391 | /* | 405 | /* |
392 | * Just set the brightness, choosing first usable bank. | 406 | * Just set the brightness, choosing first usable |
393 | * If none perfect, choose best. | 407 | * bank. If none perfect, choose best. Count |
394 | * Count backwards so we check MASTER bank first | 408 | * backwards so we check MASTER bank first to avoid |
395 | * to avoid wasting a timer. | 409 | * wasting a timer. |
396 | */ | 410 | */ |
397 | int best = -1;/* full-on */ | 411 | int best = -1;/* full-on */ |
398 | int diff = 15-level; | 412 | int diff = 15-level; |
@@ -433,9 +447,9 @@ static int led_prepare(struct tca6507_led *led) | |||
433 | } | 447 | } |
434 | 448 | ||
435 | /* | 449 | /* |
436 | * We have on/off time so we need to try to allocate a timing bank. | 450 | * We have on/off time so we need to try to allocate a timing |
437 | * First check if times are compatible with hardware and give up if | 451 | * bank. First check if times are compatible with hardware |
438 | * not. | 452 | * and give up if not. |
439 | */ | 453 | */ |
440 | if (choose_times(led->ontime, &c1, &c2) < 0) | 454 | if (choose_times(led->ontime, &c1, &c2) < 0) |
441 | return -EINVAL; | 455 | return -EINVAL; |
@@ -523,8 +537,8 @@ static int led_assign(struct tca6507_led *led) | |||
523 | err = led_prepare(led); | 537 | err = led_prepare(led); |
524 | if (err) { | 538 | if (err) { |
525 | /* | 539 | /* |
526 | * Can only fail on timer setup. In that case we need to | 540 | * Can only fail on timer setup. In that case we need |
527 | * re-establish as steady level. | 541 | * to re-establish as steady level. |
528 | */ | 542 | */ |
529 | led->ontime = 0; | 543 | led->ontime = 0; |
530 | led->offtime = 0; | 544 | led->offtime = 0; |
@@ -594,8 +608,8 @@ static void tca6507_gpio_set_value(struct gpio_chip *gc, | |||
594 | 608 | ||
595 | spin_lock_irqsave(&tca->lock, flags); | 609 | spin_lock_irqsave(&tca->lock, flags); |
596 | /* | 610 | /* |
597 | * 'OFF' is floating high, and 'ON' is pulled down, so it has the | 611 | * 'OFF' is floating high, and 'ON' is pulled down, so it has |
598 | * inverse sense of 'val'. | 612 | * the inverse sense of 'val'. |
599 | */ | 613 | */ |
600 | set_select(tca, tca->gpio_map[offset], | 614 | set_select(tca, tca->gpio_map[offset], |
601 | val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON); | 615 | val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON); |
@@ -638,6 +652,9 @@ static int tca6507_probe_gpios(struct i2c_client *client, | |||
638 | tca->gpio.direction_output = tca6507_gpio_direction_output; | 652 | tca->gpio.direction_output = tca6507_gpio_direction_output; |
639 | tca->gpio.set = tca6507_gpio_set_value; | 653 | tca->gpio.set = tca6507_gpio_set_value; |
640 | tca->gpio.dev = &client->dev; | 654 | tca->gpio.dev = &client->dev; |
655 | #ifdef CONFIG_OF_GPIO | ||
656 | tca->gpio.of_node = of_node_get(client->dev.of_node); | ||
657 | #endif | ||
641 | err = gpiochip_add(&tca->gpio); | 658 | err = gpiochip_add(&tca->gpio); |
642 | if (err) { | 659 | if (err) { |
643 | tca->gpio.ngpio = 0; | 660 | tca->gpio.ngpio = 0; |
@@ -682,7 +699,7 @@ tca6507_led_dt_init(struct i2c_client *client) | |||
682 | return ERR_PTR(-ENODEV); | 699 | return ERR_PTR(-ENODEV); |
683 | 700 | ||
684 | tca_leds = devm_kzalloc(&client->dev, | 701 | tca_leds = devm_kzalloc(&client->dev, |
685 | sizeof(struct led_info) * count, GFP_KERNEL); | 702 | sizeof(struct led_info) * NUM_LEDS, GFP_KERNEL); |
686 | if (!tca_leds) | 703 | if (!tca_leds) |
687 | return ERR_PTR(-ENOMEM); | 704 | return ERR_PTR(-ENOMEM); |
688 | 705 | ||
@@ -695,9 +712,11 @@ tca6507_led_dt_init(struct i2c_client *client) | |||
695 | of_get_property(child, "label", NULL) ? : child->name; | 712 | of_get_property(child, "label", NULL) ? : child->name; |
696 | led.default_trigger = | 713 | led.default_trigger = |
697 | of_get_property(child, "linux,default-trigger", NULL); | 714 | of_get_property(child, "linux,default-trigger", NULL); |
698 | 715 | led.flags = 0; | |
716 | if (of_property_match_string(child, "compatible", "gpio") >= 0) | ||
717 | led.flags |= TCA6507_MAKE_GPIO; | ||
699 | ret = of_property_read_u32(child, "reg", ®); | 718 | ret = of_property_read_u32(child, "reg", ®); |
700 | if (ret != 0) | 719 | if (ret != 0 || reg < 0 || reg >= NUM_LEDS) |
701 | continue; | 720 | continue; |
702 | 721 | ||
703 | tca_leds[reg] = led; | 722 | tca_leds[reg] = led; |
@@ -708,8 +727,10 @@ tca6507_led_dt_init(struct i2c_client *client) | |||
708 | return ERR_PTR(-ENOMEM); | 727 | return ERR_PTR(-ENOMEM); |
709 | 728 | ||
710 | pdata->leds.leds = tca_leds; | 729 | pdata->leds.leds = tca_leds; |
711 | pdata->leds.num_leds = count; | 730 | pdata->leds.num_leds = NUM_LEDS; |
712 | 731 | #ifdef CONFIG_GPIOLIB | |
732 | pdata->gpio_base = -1; | ||
733 | #endif | ||
713 | return pdata; | 734 | return pdata; |
714 | } | 735 | } |
715 | 736 | ||