diff options
author | Milo Kim <milo.kim@ti.com> | 2013-08-08 00:41:40 -0400 |
---|---|---|
committer | Bryan Wu <cooloney@gmail.com> | 2013-08-26 20:22:12 -0400 |
commit | c0e5e9b542d134eb43ea4ebc83446e6f2f63089a (patch) | |
tree | d9192fb09ea0e92af6b7d6eca69498efdec034b7 | |
parent | 36030978f51b596c30188187ffcc8a436cce16f0 (diff) |
leds: lp5521: restore legacy device attributes
git commit 9ce7cb170f97f83a78dc948bf7d25690f15e1328
may cause an application confict, engineN_mode and engineN_load.
This interface should be maintained for compatibility.
Restored device attributes are 'engineN_mode' and 'engineN_load'.
A 'selftest' attribute macro is replaced with LP55xx common macro.
Use a mutex in lp5521_update_program_memory()
: This function is called when an user-application writes a 'engineN_load' file
or pattern data is loaded from generic firmware interface.
So, writing program memory should be protected.
If an error occurs on accessing this area, just it returns as -EINVAL quickly.
This error code is exact same as old driver function, lp5521_do_store_load()
because it should be kept for an user-application compatibility.
Even the driver is changed, we can use the application without re-compiling
sources.
'led_pattern' attribute is not included
: engineN_mode and _load were created for custom user-application.
'led_pattern' is an exception. I added this attribute not for custom application
but for simple test. Now it is used only in LP5562 driver, not LP5521.
Signed-off-by: Milo Kim <milo.kim@ti.com>
Signed-off-by: Bryan Wu <cooloney@gmail.com>
-rw-r--r-- | drivers/leds/leds-lp5521.c | 104 |
1 files changed, 100 insertions, 4 deletions
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 9e28dd073e26..c00f922163b3 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c | |||
@@ -251,10 +251,20 @@ static int lp5521_update_program_memory(struct lp55xx_chip *chip, | |||
251 | goto err; | 251 | goto err; |
252 | 252 | ||
253 | program_size = i; | 253 | program_size = i; |
254 | for (i = 0; i < program_size; i++) | ||
255 | lp55xx_write(chip, addr[idx] + i, pattern[i]); | ||
256 | 254 | ||
257 | return 0; | 255 | mutex_lock(&chip->lock); |
256 | |||
257 | for (i = 0; i < program_size; i++) { | ||
258 | ret = lp55xx_write(chip, addr[idx] + i, pattern[i]); | ||
259 | if (ret) { | ||
260 | mutex_unlock(&chip->lock); | ||
261 | return -EINVAL; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | mutex_unlock(&chip->lock); | ||
266 | |||
267 | return size; | ||
258 | 268 | ||
259 | err: | 269 | err: |
260 | dev_err(&chip->cl->dev, "wrong pattern format\n"); | 270 | dev_err(&chip->cl->dev, "wrong pattern format\n"); |
@@ -365,6 +375,80 @@ static void lp5521_led_brightness_work(struct work_struct *work) | |||
365 | mutex_unlock(&chip->lock); | 375 | mutex_unlock(&chip->lock); |
366 | } | 376 | } |
367 | 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 | lp5521_run_engine(chip, true); | ||
414 | engine->mode = LP55XX_ENGINE_RUN; | ||
415 | } else if (!strncmp(buf, "load", 4)) { | ||
416 | lp5521_stop_engine(chip); | ||
417 | lp5521_load_engine(chip); | ||
418 | engine->mode = LP55XX_ENGINE_LOAD; | ||
419 | } else if (!strncmp(buf, "disabled", 8)) { | ||
420 | lp5521_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 ssize_t store_engine_load(struct device *dev, | ||
433 | struct device_attribute *attr, | ||
434 | const char *buf, size_t len, int nr) | ||
435 | { | ||
436 | struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); | ||
437 | struct lp55xx_chip *chip = led->chip; | ||
438 | |||
439 | mutex_lock(&chip->lock); | ||
440 | |||
441 | chip->engine_idx = nr; | ||
442 | lp5521_load_engine(chip); | ||
443 | |||
444 | mutex_unlock(&chip->lock); | ||
445 | |||
446 | return lp5521_update_program_memory(chip, buf, len); | ||
447 | } | ||
448 | store_load(1) | ||
449 | store_load(2) | ||
450 | store_load(3) | ||
451 | |||
368 | static ssize_t lp5521_selftest(struct device *dev, | 452 | static ssize_t lp5521_selftest(struct device *dev, |
369 | struct device_attribute *attr, | 453 | struct device_attribute *attr, |
370 | char *buf) | 454 | char *buf) |
@@ -381,9 +465,21 @@ static ssize_t lp5521_selftest(struct device *dev, | |||
381 | } | 465 | } |
382 | 466 | ||
383 | /* device attributes */ | 467 | /* device attributes */ |
384 | static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL); | 468 | static LP55XX_DEV_ATTR_RW(engine1_mode, show_engine1_mode, store_engine1_mode); |
469 | static LP55XX_DEV_ATTR_RW(engine2_mode, show_engine2_mode, store_engine2_mode); | ||
470 | static LP55XX_DEV_ATTR_RW(engine3_mode, show_engine3_mode, store_engine3_mode); | ||
471 | static LP55XX_DEV_ATTR_WO(engine1_load, store_engine1_load); | ||
472 | static LP55XX_DEV_ATTR_WO(engine2_load, store_engine2_load); | ||
473 | static LP55XX_DEV_ATTR_WO(engine3_load, store_engine3_load); | ||
474 | static LP55XX_DEV_ATTR_RO(selftest, lp5521_selftest); | ||
385 | 475 | ||
386 | static struct attribute *lp5521_attributes[] = { | 476 | static struct attribute *lp5521_attributes[] = { |
477 | &dev_attr_engine1_mode.attr, | ||
478 | &dev_attr_engine2_mode.attr, | ||
479 | &dev_attr_engine3_mode.attr, | ||
480 | &dev_attr_engine1_load.attr, | ||
481 | &dev_attr_engine2_load.attr, | ||
482 | &dev_attr_engine3_load.attr, | ||
387 | &dev_attr_selftest.attr, | 483 | &dev_attr_selftest.attr, |
388 | NULL | 484 | NULL |
389 | }; | 485 | }; |