]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 29 Jan 2014 02:53:01 +0000 (18:53 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 29 Jan 2014 02:53:01 +0000 (18:53 -0800)
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.

14 files changed:
Documentation/devicetree/bindings/leds/tca6507.txt
Documentation/leds/leds-lp55xx.txt
arch/arm/mach-imx/mach-mx31moboard.c
drivers/leds/led-triggers.c
drivers/leds/leds-lp5521.c
drivers/leds/leds-lp5523.c
drivers/leds/leds-lp55xx-common.c
drivers/leds/leds-mc13783.c
drivers/leds/leds-pwm.c
drivers/leds/leds-s3c24xx.c
drivers/leds/leds-tca6507.c
include/linux/mfd/mc13xxx.h
include/linux/platform_data/leds-kirkwood-netxbig.h
include/linux/platform_data/leds-kirkwood-ns2.h

index 80ff3dfb1f325e89993184324e8ed053fd15e867..d7221b84987cd684169bee2765a050cba3511c75 100644 (file)
@@ -2,6 +2,13 @@ LEDs connected to tca6507
 
 Required properties:
 - compatible : should be : "ti,tca6507".
+- #address-cells: must be 1
+- #size-cells: must be 0
+- reg: typically 0x45.
+
+Optional properties:
+- gpio-controller: allows lines to be used as output-only GPIOs.
+- #gpio-cells: if present, must be 0.
 
 Each led is represented as a sub-node of the ti,tca6507 device.
 
@@ -10,6 +17,7 @@ LED sub-node properties:
 - reg : number of LED line (could be from 0 to 6)
 - linux,default-trigger : (optional)
    see Documentation/devicetree/bindings/leds/common.txt
+- compatible: either "led" (the default) or "gpio".
 
 Examples:
 
@@ -19,6 +27,9 @@ tca6507@45 {
        #size-cells = <0>;
        reg = <0x45>;
 
+       gpio-controller;
+       #gpio-cells = <2>;
+
        led0: red-aux@0 {
                label = "red:aux";
                reg = <0x0>;
@@ -29,5 +40,10 @@ tca6507@45 {
                reg = <0x5>;
                linux,default-trigger = "default-on";
        };
+
+       wifi-reset@6 {
+               reg = <0x6>;
+               compatible = "gpio";
+       };
 };
 
index 82713ff92eb3e5c72a82ff6f1dc9d637e7f04376..bcea12a0c5847e12211a14d43f356d0f1a1e77f0 100644 (file)
@@ -73,6 +73,10 @@ select_engine : Select which engine is used for running program
 run_engine    : Start program which is loaded via the firmware interface
 firmware      : Load program data
 
+In case of LP5523, one more command is required, 'enginex_leds'.
+It is used for selecting LED output(s) at each engine number.
+In more details, please refer to 'leds-lp5523.txt'.
+
 For example, run blinking pattern in engine #1 of LP5521
 echo 1 > /sys/bus/i2c/devices/xxxx/select_engine
 echo 1 > /sys/class/firmware/lp5521/loading
@@ -81,10 +85,12 @@ echo 0 > /sys/class/firmware/lp5521/loading
 echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
 
 For example, run blinking pattern in engine #3 of LP55231
+Two LEDs are configured as pattern output channels.
 echo 3 > /sys/bus/i2c/devices/xxxx/select_engine
 echo 1 > /sys/class/firmware/lp55231/loading
 echo "9d0740ff7e0040007e00a0010000" > /sys/class/firmware/lp55231/data
 echo 0 > /sys/class/firmware/lp55231/loading
+echo "000001100" > /sys/bus/i2c/devices/xxxx/engine3_leds
 echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
 
 To start blinking patterns in engine #2 and #3 simultaneously,
@@ -99,17 +105,19 @@ done
 echo 1 > /sys/class/leds/red/device/run_engine
 
 Here is another example for LP5523.
+Full LED strings are selected by 'engine2_leds'.
 echo 2 > /sys/bus/i2c/devices/xxxx/select_engine
 echo 1 > /sys/class/firmware/lp5523/loading
 echo "9d80400004ff05ff437f0000" > /sys/class/firmware/lp5523/data
 echo 0 > /sys/class/firmware/lp5523/loading
+echo "111111111" > /sys/bus/i2c/devices/xxxx/engine2_leds
 echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
 
 As soon as 'loading' is set to 0, registered callback is called.
 Inside the callback, the selected engine is loaded and memory is updated.
 To run programmed pattern, 'run_engine' attribute should be enabled.
 
-The pattern sqeuence of LP8501 is same as LP5523.
+The pattern sqeuence of LP8501 is similar to LP5523.
 However pattern data is specific.
 Ex 1) Engine 1 is used
 echo 1 > /sys/bus/i2c/devices/xxxx/select_engine
index 6f424eced1816914bf59e39e48608b50bb338fe5..b3738e616f197bef538f2610bd519ad066f8cddd 100644 (file)
@@ -236,32 +236,26 @@ static struct mc13xxx_led_platform_data moboard_led[] = {
        {
                .id = MC13783_LED_R1,
                .name = "coreboard-led-4:red",
-               .max_current = 2,
        },
        {
                .id = MC13783_LED_G1,
                .name = "coreboard-led-4:green",
-               .max_current = 2,
        },
        {
                .id = MC13783_LED_B1,
                .name = "coreboard-led-4:blue",
-               .max_current = 2,
        },
        {
                .id = MC13783_LED_R2,
                .name = "coreboard-led-5:red",
-               .max_current = 3,
        },
        {
                .id = MC13783_LED_G2,
                .name = "coreboard-led-5:green",
-               .max_current = 3,
        },
        {
                .id = MC13783_LED_B2,
                .name = "coreboard-led-5:blue",
-               .max_current = 3,
        },
 };
 
@@ -271,8 +265,14 @@ static struct mc13xxx_leds_platform_data moboard_leds = {
        .led_control[0] = MC13783_LED_C0_ENABLE | MC13783_LED_C0_ABMODE(0),
        .led_control[1] = MC13783_LED_C1_SLEWLIM,
        .led_control[2] = MC13783_LED_C2_SLEWLIM,
-       .led_control[3] = MC13783_LED_C3_PERIOD(0),
-       .led_control[4] = MC13783_LED_C3_PERIOD(0),
+       .led_control[3] = MC13783_LED_C3_PERIOD(0) |
+                         MC13783_LED_C3_CURRENT_R1(2) |
+                         MC13783_LED_C3_CURRENT_G1(2) |
+                         MC13783_LED_C3_CURRENT_B1(2),
+       .led_control[4] = MC13783_LED_C4_PERIOD(0) |
+                         MC13783_LED_C4_CURRENT_R2(3) |
+                         MC13783_LED_C4_CURRENT_G2(3) |
+                         MC13783_LED_C4_CURRENT_B2(3),
 };
 
 static struct mc13xxx_buttons_platform_data moboard_buttons = {
index 3c972b2f989335e4df54aa8436cbd99a7f19ba09..e387f41a9cb7667f3542f510b4a954d299e1d316 100644 (file)
@@ -242,18 +242,14 @@ EXPORT_SYMBOL_GPL(led_trigger_unregister);
 void led_trigger_event(struct led_trigger *trig,
                        enum led_brightness brightness)
 {
-       struct list_head *entry;
+       struct led_classdev *led_cdev;
 
        if (!trig)
                return;
 
        read_lock(&trig->leddev_list_lock);
-       list_for_each(entry, &trig->led_cdevs) {
-               struct led_classdev *led_cdev;
-
-               led_cdev = list_entry(entry, struct led_classdev, trig_list);
+       list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list)
                led_set_brightness(led_cdev, brightness);
-       }
        read_unlock(&trig->leddev_list_lock);
 }
 EXPORT_SYMBOL_GPL(led_trigger_event);
@@ -264,16 +260,13 @@ static void led_trigger_blink_setup(struct led_trigger *trig,
                             int oneshot,
                             int invert)
 {
-       struct list_head *entry;
+       struct led_classdev *led_cdev;
 
        if (!trig)
                return;
 
        read_lock(&trig->leddev_list_lock);
-       list_for_each(entry, &trig->led_cdevs) {
-               struct led_classdev *led_cdev;
-
-               led_cdev = list_entry(entry, struct led_classdev, trig_list);
+       list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) {
                if (oneshot)
                        led_blink_set_oneshot(led_cdev, delay_on, delay_off,
                                              invert);
index a97263e902ffc6b927db6b935cb290902909f21e..2ec34cfcedcee613aebd97bae8c06966b826f404 100644 (file)
@@ -152,12 +152,26 @@ static void lp5521_load_engine(struct lp55xx_chip *chip)
        lp5521_wait_opmode_done();
 }
 
-static void lp5521_stop_engine(struct lp55xx_chip *chip)
+static void lp5521_stop_all_engines(struct lp55xx_chip *chip)
 {
        lp55xx_write(chip, LP5521_REG_OP_MODE, 0);
        lp5521_wait_opmode_done();
 }
 
+static void lp5521_stop_engine(struct lp55xx_chip *chip)
+{
+       enum lp55xx_engine_index idx = chip->engine_idx;
+       u8 mask[] = {
+               [LP55XX_ENGINE_1] = LP5521_MODE_R_M,
+               [LP55XX_ENGINE_2] = LP5521_MODE_G_M,
+               [LP55XX_ENGINE_3] = LP5521_MODE_B_M,
+       };
+
+       lp55xx_update_bits(chip, LP5521_REG_OP_MODE, mask[idx], 0);
+
+       lp5521_wait_opmode_done();
+}
+
 static void lp5521_run_engine(struct lp55xx_chip *chip, bool start)
 {
        int ret;
@@ -564,7 +578,7 @@ static int lp5521_remove(struct i2c_client *client)
        struct lp55xx_led *led = i2c_get_clientdata(client);
        struct lp55xx_chip *chip = led->chip;
 
-       lp5521_stop_engine(chip);
+       lp5521_stop_all_engines(chip);
        lp55xx_unregister_sysfs(chip);
        lp55xx_unregister_leds(led, chip);
        lp55xx_deinit_device(chip);
index 3a0bc886a87a2c88782c9b075f0eba935271ebc2..4ade66a2d9d4758b314c45ed52a222ff0cb0aeca 100644 (file)
@@ -195,12 +195,26 @@ static void lp5523_load_engine_and_select_page(struct lp55xx_chip *chip)
        lp55xx_write(chip, LP5523_REG_PROG_PAGE_SEL, page_sel[idx]);
 }
 
-static void lp5523_stop_engine(struct lp55xx_chip *chip)
+static void lp5523_stop_all_engines(struct lp55xx_chip *chip)
 {
        lp55xx_write(chip, LP5523_REG_OP_MODE, 0);
        lp5523_wait_opmode_done();
 }
 
+static void lp5523_stop_engine(struct lp55xx_chip *chip)
+{
+       enum lp55xx_engine_index idx = chip->engine_idx;
+       u8 mask[] = {
+               [LP55XX_ENGINE_1] = LP5523_MODE_ENG1_M,
+               [LP55XX_ENGINE_2] = LP5523_MODE_ENG2_M,
+               [LP55XX_ENGINE_3] = LP5523_MODE_ENG3_M,
+       };
+
+       lp55xx_update_bits(chip, LP5523_REG_OP_MODE, mask[idx], 0);
+
+       lp5523_wait_opmode_done();
+}
+
 static void lp5523_turn_off_channels(struct lp55xx_chip *chip)
 {
        int i;
@@ -311,7 +325,7 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip)
        }
 
 out:
-       lp5523_stop_engine(chip);
+       lp5523_stop_all_engines(chip);
        return ret;
 }
 
@@ -782,7 +796,7 @@ static int lp5523_remove(struct i2c_client *client)
        struct lp55xx_led *led = i2c_get_clientdata(client);
        struct lp55xx_chip *chip = led->chip;
 
-       lp5523_stop_engine(chip);
+       lp5523_stop_all_engines(chip);
        lp55xx_unregister_sysfs(chip);
        lp55xx_unregister_leds(led, chip);
        lp55xx_deinit_device(chip);
index 9acc6bb7deef01f153e5c71044ac93be7e983ba9..88317b4f7bf3abf70e4337a12aa682646e8a2e56 100644 (file)
@@ -210,6 +210,7 @@ static void lp55xx_firmware_loaded(const struct firmware *fw, void *context)
 {
        struct lp55xx_chip *chip = context;
        struct device *dev = &chip->cl->dev;
+       enum lp55xx_engine_index idx = chip->engine_idx;
 
        if (!fw) {
                dev_err(dev, "firmware request failed\n");
@@ -219,6 +220,7 @@ static void lp55xx_firmware_loaded(const struct firmware *fw, void *context)
        /* handling firmware data is chip dependent */
        mutex_lock(&chip->lock);
 
+       chip->engines[idx - 1].mode = LP55XX_ENGINE_LOAD;
        chip->fw = fw;
        if (chip->cfg->firmware_cb)
                chip->cfg->firmware_cb(chip);
index fa9b439323bd06d0d126a48a7828e4b47665c6b5..ca87a1b4a0db228896ca19dc410885eaa53eb7f3 100644 (file)
@@ -117,9 +117,7 @@ static void mc13xxx_led_work(struct work_struct *work)
                BUG();
        }
 
-       mc13xxx_lock(led->master);
        mc13xxx_reg_rmw(led->master, reg, mask << shift, value << shift);
-       mc13xxx_unlock(led->master);
 }
 
 static void mc13xxx_led_set(struct led_classdev *led_cdev,
@@ -132,75 +130,6 @@ static void mc13xxx_led_set(struct led_classdev *led_cdev,
        schedule_work(&led->work);
 }
 
-static int __init mc13xxx_led_setup(struct mc13xxx_led *led, int max_current)
-{
-       int shift, mask, reg, ret, bank;
-
-       switch (led->id) {
-       case MC13783_LED_MD:
-               reg = MC13XXX_REG_LED_CONTROL(2);
-               shift = 0;
-               mask = 0x07;
-               break;
-       case MC13783_LED_AD:
-               reg = MC13XXX_REG_LED_CONTROL(2);
-               shift = 3;
-               mask = 0x07;
-               break;
-       case MC13783_LED_KP:
-               reg = MC13XXX_REG_LED_CONTROL(2);
-               shift = 6;
-               mask = 0x07;
-               break;
-       case MC13783_LED_R1:
-       case MC13783_LED_G1:
-       case MC13783_LED_B1:
-       case MC13783_LED_R2:
-       case MC13783_LED_G2:
-       case MC13783_LED_B2:
-       case MC13783_LED_R3:
-       case MC13783_LED_G3:
-       case MC13783_LED_B3:
-               bank = (led->id - MC13783_LED_R1) / 3;
-               reg = MC13XXX_REG_LED_CONTROL(3) + bank;
-               shift = ((led->id - MC13783_LED_R1) - bank * 3) * 2;
-               mask = 0x03;
-               break;
-       case MC13892_LED_MD:
-               reg = MC13XXX_REG_LED_CONTROL(0);
-               shift = 9;
-               mask = 0x07;
-               break;
-       case MC13892_LED_AD:
-               reg = MC13XXX_REG_LED_CONTROL(0);
-               shift = 21;
-               mask = 0x07;
-               break;
-       case MC13892_LED_KP:
-               reg = MC13XXX_REG_LED_CONTROL(1);
-               shift = 9;
-               mask = 0x07;
-               break;
-       case MC13892_LED_R:
-       case MC13892_LED_G:
-       case MC13892_LED_B:
-               bank = (led->id - MC13892_LED_R) / 2;
-               reg = MC13XXX_REG_LED_CONTROL(2) + bank;
-               shift = ((led->id - MC13892_LED_R) - bank * 2) * 12 + 9;
-               mask = 0x07;
-               break;
-       default:
-               BUG();
-       }
-
-       mc13xxx_lock(led->master);
-       ret = mc13xxx_reg_rmw(led->master, reg, mask << shift,
-                             max_current << shift);
-       mc13xxx_unlock(led->master);
-
-       return ret;
-}
-
 static int __init mc13xxx_led_probe(struct platform_device *pdev)
 {
        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)
        leds->num_leds = num_leds;
        platform_set_drvdata(pdev, leds);
 
-       mc13xxx_lock(mcdev);
        for (i = 0; i < devtype->num_regs; i++) {
                reg = pdata->led_control[i];
                WARN_ON(reg >= (1 << 24));
                ret = mc13xxx_reg_write(mcdev, MC13XXX_REG_LED_CONTROL(i), reg);
                if (ret)
-                       break;
-       }
-       mc13xxx_unlock(mcdev);
-
-       if (ret) {
-               dev_err(&pdev->dev, "Unable to init LED driver\n");
-               return ret;
+                       return ret;
        }
 
        for (i = 0; i < num_leds; i++) {
                const char *name, *trig;
-               char max_current;
 
                ret = -EINVAL;
 
                id = pdata->led[i].id;
                name = pdata->led[i].name;
                trig = pdata->led[i].default_trigger;
-               max_current = pdata->led[i].max_current;
 
                if ((id > devtype->led_max) || (id < devtype->led_min)) {
                        dev_err(&pdev->dev, "Invalid ID %i\n", id);
@@ -280,11 +200,6 @@ static int __init mc13xxx_led_probe(struct platform_device *pdev)
 
                INIT_WORK(&leds->led[i].work, mc13xxx_led_work);
 
-               ret = mc13xxx_led_setup(&leds->led[i], max_current);
-               if (ret) {
-                       dev_err(&pdev->dev, "Unable to setup LED %i\n", id);
-                       break;
-               }
                ret = led_classdev_register(pdev->dev.parent,
                                            &leds->led[i].cdev);
                if (ret) {
@@ -313,10 +228,8 @@ static int mc13xxx_led_remove(struct platform_device *pdev)
                cancel_work_sync(&leds->led[i].work);
        }
 
-       mc13xxx_lock(mcdev);
        for (i = 0; i < leds->devtype->num_regs; i++)
                mc13xxx_reg_write(mcdev, MC13XXX_REG_LED_CONTROL(i), 0);
-       mc13xxx_unlock(mcdev);
 
        return 0;
 }
index b31d8e99c41992c77610fe5ca1694211035ea592..605047428b5ad75e2d67add0edaecb912d35581a 100644 (file)
@@ -66,9 +66,11 @@ static void led_pwm_set(struct led_classdev *led_cdev,
        struct led_pwm_data *led_dat =
                container_of(led_cdev, struct led_pwm_data, cdev);
        unsigned int max = led_dat->cdev.max_brightness;
-       unsigned int period =  led_dat->period;
+       unsigned long long duty =  led_dat->period;
 
-       led_dat->duty = brightness * period / max;
+       duty *= brightness;
+       do_div(duty, max);
+       led_dat->duty = duty;
 
        if (led_dat->can_sleep)
                schedule_work(&led_dat->work);
@@ -85,11 +87,10 @@ static inline size_t sizeof_pwm_leds_priv(int num_leds)
 static int led_pwm_create_of(struct platform_device *pdev,
                             struct led_pwm_priv *priv)
 {
-       struct device_node *node = pdev->dev.of_node;
        struct device_node *child;
        int ret;
 
-       for_each_child_of_node(node, child) {
+       for_each_child_of_node(pdev->dev.of_node, child) {
                struct led_pwm_data *led_dat = &priv->leds[priv->num_leds];
 
                led_dat->cdev.name = of_get_property(child, "label",
index 87cf215af798c97076df857b0609292c1f752cfe..98174e7240ee9f41b8a4d0cddae494ebff99da65 100644 (file)
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/platform_data/leds-s3c24xx.h>
 
-#include <mach/hardware.h>
 #include <mach/regs-gpio.h>
 #include <plat/gpio-cfg.h>
-#include <linux/platform_data/leds-s3c24xx.h>
 
 /* our context */
 
index 8cc304f36728a4e217cbf6716f893a3e6f5aed0c..3d9e267a56c428580bfaa074ce08053bd86ae34a 100644 (file)
@@ -4,77 +4,87 @@
  * The TCA6507 is a programmable LED controller that can drive 7
  * separate lines either by holding them low, or by pulsing them
  * with modulated width.
- * The modulation can be varied in a simple pattern to produce a blink or
- * double-blink.
+ * The modulation can be varied in a simple pattern to produce a
+ * blink or double-blink.
  *
- * This driver can configure each line either as a 'GPIO' which is out-only
- * (no pull-up) or as an LED with variable brightness and hardware-assisted
- * blinking.
+ * This driver can configure each line either as a 'GPIO' which is
+ * out-only (pull-up resistor required) or as an LED with variable
+ * brightness and hardware-assisted blinking.
  *
- * Apart from OFF and ON there are three programmable brightness levels which
- * can be programmed from 0 to 15 and indicate how many 500usec intervals in
- * each 8msec that the led is 'on'.  The levels are named MASTER, BANK0 and
- * BANK1.
+ * Apart from OFF and ON there are three programmable brightness
+ * levels which can be programmed from 0 to 15 and indicate how many
+ * 500usec intervals in each 8msec that the led is 'on'.  The levels
+ * are named MASTER, BANK0 and BANK1.
  *
- * There are two different blink rates that can be programmed, each with
- * separate time for rise, on, fall, off and second-off.  Thus if 3 or more
- * different non-trivial rates are required, software must be used for the extra
- * rates. The two different blink rates must align with the two levels BANK0 and
- * BANK1.
- * This driver does not support double-blink so 'second-off' always matches
- * 'off'.
+ * There are two different blink rates that can be programmed, each
+ * with separate time for rise, on, fall, off and second-off.  Thus if
+ * 3 or more different non-trivial rates are required, software must
+ * be used for the extra rates. The two different blink rates must
+ * align with the two levels BANK0 and BANK1.  This driver does not
+ * support double-blink so 'second-off' always matches 'off'.
  *
- * Only 16 different times can be programmed in a roughly logarithmic scale from
- * 64ms to 16320ms.  To be precise the possible times are:
+ * Only 16 different times can be programmed in a roughly logarithmic
+ * scale from 64ms to 16320ms.  To be precise the possible times are:
  *    0, 64, 128, 192, 256, 384, 512, 768,
  *    1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320
  *
- * Times that cannot be closely matched with these must be
- * handled in software.  This driver allows 12.5% error in matching.
+ * Times that cannot be closely matched with these must be handled in
+ * software.  This driver allows 12.5% error in matching.
  *
- * This driver does not allow rise/fall rates to be set explicitly.  When trying
- * to match a given 'on' or 'off' period, an appropriate pair of 'change' and
- * 'hold' times are chosen to get a close match.  If the target delay is even,
- * the 'change' number will be the smaller; if odd, the 'hold' number will be
- * the smaller.
-
- * Choosing pairs of delays with 12.5% errors allows us to match delays in the
- * ranges: 56-72, 112-144, 168-216, 224-27504, 28560-36720.
- * 26% of the achievable sums can be matched by multiple pairings. For example
- * 1536 == 1536+0, 1024+512, or 768+768.  This driver will always choose the
- * pairing with the least maximum - 768+768 in this case.  Other pairings are
- * not available.
+ * This driver does not allow rise/fall rates to be set explicitly.
+ * When trying to match a given 'on' or 'off' period, an appropriate
+ * pair of 'change' and 'hold' times are chosen to get a close match.
+ * If the target delay is even, the 'change' number will be the
+ * smaller; if odd, the 'hold' number will be the smaller.
+
+ * Choosing pairs of delays with 12.5% errors allows us to match
+ * delays in the ranges: 56-72, 112-144, 168-216, 224-27504,
+ * 28560-36720.
+ * 26% of the achievable sums can be matched by multiple pairings.
+ * For example 1536 == 1536+0, 1024+512, or 768+768.
+ * This driver will always choose the pairing with the least
+ * maximum - 768+768 in this case.  Other pairings are not available.
  *
- * Access to the 3 levels and 2 blinks are on a first-come, first-served basis.
- * Access can be shared by multiple leds if they have the same level and
- * either same blink rates, or some don't blink.
- * When a led changes, it relinquishes access and tries again, so it might
- * lose access to hardware blink.
- * If a blink engine cannot be allocated, software blink is used.
- * If the desired brightness cannot be allocated, the closest available non-zero
- * brightness is used.  As 'full' is always available, the worst case would be
- * to have two different blink rates at '1', with Max at '2', then other leds
- * will have to choose between '2' and '16'.  Hopefully this is not likely.
+ * Access to the 3 levels and 2 blinks are on a first-come,
+ * first-served basis.  Access can be shared by multiple leds if they
+ * have the same level and either same blink rates, or some don't
+ * blink.  When a led changes, it relinquishes access and tries again,
+ * so it might lose access to hardware blink.
  *
- * Each bank (BANK0 and BANK1) has two usage counts - LEDs using the brightness
- * and LEDs using the blink.  It can only be reprogrammed when the appropriate
- * counter is zero.  The MASTER level has a single usage count.
+ * If a blink engine cannot be allocated, software blink is used.  If
+ * the desired brightness cannot be allocated, the closest available
+ * non-zero brightness is used.  As 'full' is always available, the
+ * worst case would be to have two different blink rates at '1', with
+ * Max at '2', then other leds will have to choose between '2' and
+ * '16'.  Hopefully this is not likely.
  *
- * Each Led has programmable 'on' and 'off' time as milliseconds.  With each
- * there is a flag saying if it was explicitly requested or defaulted.
- * Similarly the banks know if each time was explicit or a default.  Defaults
- * are permitted to be changed freely - they are not recognised when matching.
+ * Each bank (BANK0 and BANK1) has two usage counts - LEDs using the
+ * brightness and LEDs using the blink.  It can only be reprogrammed
+ * when the appropriate counter is zero.  The MASTER level has a
+ * single usage count.
  *
+ * Each LED has programmable 'on' and 'off' time as milliseconds.
+ * With each there is a flag saying if it was explicitly requested or
+ * defaulted.  Similarly the banks know if each time was explicit or a
+ * default.  Defaults are permitted to be changed freely - they are
+ * not recognised when matching.
  *
- * An led-tca6507 device must be provided with platform data.  This data
- * lists for each output: the name, default trigger, and whether the signal
- * is being used as a GPiO rather than an led.  'struct led_plaform_data'
- * is used for this.  If 'name' is NULL, the output isn't used.  If 'flags'
- * is TCA6507_MAKE_CPIO, the output is a GPO.
- * The "struct led_platform_data" can be embedded in a
- * "struct tca6507_platform_data" which adds a 'gpio_base' for the GPiOs,
- * and a 'setup' callback which is called once the GPiOs are available.
  *
+ * An led-tca6507 device must be provided with platform data or
+ * configured via devicetree.
+ *
+ * The platform-data lists for each output: the name, default trigger,
+ * and whether the signal is being used as a GPIO rather than an LED.
+ * 'struct led_plaform_data' is used for this.  If 'name' is NULL, the
+ * output isn't used.  If 'flags' is TCA6507_MAKE_GPIO, the output is
+ * a GPO.  The "struct led_platform_data" can be embedded in a "struct
+ * tca6507_platform_data" which adds a 'gpio_base' for the GPIOs, and
+ * a 'setup' callback which is called once the GPIOs are available.
+ *
+ * When configured via devicetree there is one child for each output.
+ * The "reg" determines the output number and "compatible" determines
+ * whether it is an LED or a GPIO.  "linux,default-trigger" can set a
+ * default trigger.
  */
 
 #include <linux/module.h>
@@ -192,17 +202,18 @@ MODULE_DEVICE_TABLE(i2c, tca6507_id);
 static int choose_times(int msec, int *c1p, int *c2p)
 {
        /*
-        * Choose two timecodes which add to 'msec' as near as possible.
-        * The first returned is the 'on' or 'off' time.  The second is to be
-        * used as a 'fade-on' or 'fade-off' time.  If 'msec' is even,
-        * the first will not be smaller than the second.  If 'msec' is odd,
-        * the first will not be larger than the second.
-        * If we cannot get a sum within 1/8 of 'msec' fail with -EINVAL,
-        * otherwise return the sum that was achieved, plus 1 if the first is
-        * smaller.
-        * If two possibilities are equally good (e.g. 512+0, 256+256), choose
-        * the first pair so there is more change-time visible (i.e. it is
-        * softer).
+        * Choose two timecodes which add to 'msec' as near as
+        * possible.  The first returned is the 'on' or 'off' time.
+        * The second is to be used as a 'fade-on' or 'fade-off' time.
+        * If 'msec' is even, the first will not be smaller than the
+        * second.  If 'msec' is odd, the first will not be larger
+        * than the second.
+        * If we cannot get a sum within 1/8 of 'msec' fail with
+        * -EINVAL, otherwise return the sum that was achieved, plus 1
+        * if the first is smaller.
+        * If two possibilities are equally good (e.g. 512+0,
+        * 256+256), choose the first pair so there is more
+        * change-time visible (i.e. it is softer).
         */
        int c1, c2;
        int tmax = msec * 9 / 8;
@@ -255,8 +266,8 @@ static int choose_times(int msec, int *c1p, int *c2p)
 }
 
 /*
- * Update the register file with the appropriate 3-bit state for
- * the given led.
+ * Update the register file with the appropriate 3-bit state for the
+ * given led.
  */
 static void set_select(struct tca6507_chip *tca, int led, int val)
 {
@@ -274,9 +285,9 @@ static void set_select(struct tca6507_chip *tca, int led, int val)
        }
 }
 
-/* Update the register file with the appropriate 4-bit code for
- * one bank or other.  This can be used for timers, for levels, or
- * for initialisation.
+/* Update the register file with the appropriate 4-bit code for one
+ * bank or other.  This can be used for timers, for levels, or for
+ * initialization.
  */
 static void set_code(struct tca6507_chip *tca, int reg, int bank, int new)
 {
@@ -309,7 +320,7 @@ static void set_level(struct tca6507_chip *tca, int bank, int level)
        tca->bank[bank].level = level;
 }
 
-/* Record all relevant time code for a given bank */
+/* Record all relevant time codes for a given bank */
 static void set_times(struct tca6507_chip *tca, int bank)
 {
        int c1, c2;
@@ -317,7 +328,8 @@ static void set_times(struct tca6507_chip *tca, int bank)
 
        result = choose_times(tca->bank[bank].ontime, &c1, &c2);
        dev_dbg(&tca->client->dev,
-               "Chose on  times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1],
+               "Chose on  times %d(%d) %d(%d) for %dms\n",
+               c1, time_codes[c1],
                c2, time_codes[c2], tca->bank[bank].ontime);
        set_code(tca, TCA6507_FADE_ON, bank, c2);
        set_code(tca, TCA6507_FULL_ON, bank, c1);
@@ -325,7 +337,8 @@ static void set_times(struct tca6507_chip *tca, int bank)
 
        result = choose_times(tca->bank[bank].offtime, &c1, &c2);
        dev_dbg(&tca->client->dev,
-               "Chose off times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1],
+               "Chose off times %d(%d) %d(%d) for %dms\n",
+               c1, time_codes[c1],
                c2, time_codes[c2], tca->bank[bank].offtime);
        set_code(tca, TCA6507_FADE_OFF, bank, c2);
        set_code(tca, TCA6507_FIRST_OFF, bank, c1);
@@ -373,7 +386,8 @@ static void led_release(struct tca6507_led *led)
 
 static int led_prepare(struct tca6507_led *led)
 {
-       /* Assign this led to a bank, configuring that bank if necessary. */
+       /* Assign this led to a bank, configuring that bank if
+        * necessary. */
        int level = TO_LEVEL(led->led_cdev.brightness);
        struct tca6507_chip *tca = led->chip;
        int c1, c2;
@@ -389,10 +403,10 @@ static int led_prepare(struct tca6507_led *led)
 
        if (led->ontime == 0 || led->offtime == 0) {
                /*
-                * Just set the brightness, choosing first usable bank.
-                * If none perfect, choose best.
-                * Count backwards so we check MASTER bank first
-                * to avoid wasting a timer.
+                * Just set the brightness, choosing first usable
+                * bank.  If none perfect, choose best.  Count
+                * backwards so we check MASTER bank first to avoid
+                * wasting a timer.
                 */
                int best = -1;/* full-on */
                int diff = 15-level;
@@ -433,9 +447,9 @@ static int led_prepare(struct tca6507_led *led)
        }
 
        /*
-        * We have on/off time so we need to try to allocate a timing bank.
-        * First check if times are compatible with hardware and give up if
-        * not.
+        * We have on/off time so we need to try to allocate a timing
+        * bank.  First check if times are compatible with hardware
+        * and give up if not.
         */
        if (choose_times(led->ontime, &c1, &c2) < 0)
                return -EINVAL;
@@ -523,8 +537,8 @@ static int led_assign(struct tca6507_led *led)
        err = led_prepare(led);
        if (err) {
                /*
-                * Can only fail on timer setup.  In that case we need to
-                * re-establish as steady level.
+                * Can only fail on timer setup.  In that case we need
+                * to re-establish as steady level.
                 */
                led->ontime = 0;
                led->offtime = 0;
@@ -594,8 +608,8 @@ static void tca6507_gpio_set_value(struct gpio_chip *gc,
 
        spin_lock_irqsave(&tca->lock, flags);
        /*
-        * 'OFF' is floating high, and 'ON' is pulled down, so it has the
-        * inverse sense of 'val'.
+        * 'OFF' is floating high, and 'ON' is pulled down, so it has
+        * the inverse sense of 'val'.
         */
        set_select(tca, tca->gpio_map[offset],
                   val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON);
@@ -638,6 +652,9 @@ static int tca6507_probe_gpios(struct i2c_client *client,
        tca->gpio.direction_output = tca6507_gpio_direction_output;
        tca->gpio.set = tca6507_gpio_set_value;
        tca->gpio.dev = &client->dev;
+#ifdef CONFIG_OF_GPIO
+       tca->gpio.of_node = of_node_get(client->dev.of_node);
+#endif
        err = gpiochip_add(&tca->gpio);
        if (err) {
                tca->gpio.ngpio = 0;
@@ -682,7 +699,7 @@ tca6507_led_dt_init(struct i2c_client *client)
                return ERR_PTR(-ENODEV);
 
        tca_leds = devm_kzalloc(&client->dev,
-                       sizeof(struct led_info) * count, GFP_KERNEL);
+                       sizeof(struct led_info) * NUM_LEDS, GFP_KERNEL);
        if (!tca_leds)
                return ERR_PTR(-ENOMEM);
 
@@ -695,9 +712,11 @@ tca6507_led_dt_init(struct i2c_client *client)
                        of_get_property(child, "label", NULL) ? : child->name;
                led.default_trigger =
                        of_get_property(child, "linux,default-trigger", NULL);
-
+               led.flags = 0;
+               if (of_property_match_string(child, "compatible", "gpio") >= 0)
+                       led.flags |= TCA6507_MAKE_GPIO;
                ret = of_property_read_u32(child, "reg", &reg);
-               if (ret != 0)
+               if (ret != 0 || reg < 0 || reg >= NUM_LEDS)
                        continue;
 
                tca_leds[reg] = led;
@@ -708,8 +727,10 @@ tca6507_led_dt_init(struct i2c_client *client)
                return ERR_PTR(-ENOMEM);
 
        pdata->leds.leds = tca_leds;
-       pdata->leds.num_leds = count;
-
+       pdata->leds.num_leds = NUM_LEDS;
+#ifdef CONFIG_GPIOLIB
+       pdata->gpio_base = -1;
+#endif
        return pdata;
 }
 
index 6156686bf108f38b91fcfb09766f73012dac20ea..ac39d910e70bda7c209d783dc6f01464a836e08a 100644 (file)
@@ -110,9 +110,6 @@ struct mc13xxx_led_platform_data {
        int id;
        const char *name;
        const char *default_trigger;
-
-/* Three or two bits current selection depending on the led */
-       char max_current;
 };
 
 #define MAX_LED_CONTROL_REGS   6
@@ -121,7 +118,7 @@ struct mc13xxx_leds_platform_data {
        struct mc13xxx_led_platform_data *led;
        int num_leds;
 
-/* LED Control 0 */
+/* MC13783 LED Control 0 */
 #define MC13783_LED_C0_ENABLE          (1 << 0)
 #define MC13783_LED_C0_TRIODE_MD       (1 << 7)
 #define MC13783_LED_C0_TRIODE_AD       (1 << 8)
@@ -129,21 +126,43 @@ struct mc13xxx_leds_platform_data {
 #define MC13783_LED_C0_BOOST           (1 << 10)
 #define MC13783_LED_C0_ABMODE(x)       (((x) & 0x7) << 11)
 #define MC13783_LED_C0_ABREF(x)                (((x) & 0x3) << 14)
-/* LED Control 1 */
+/* MC13783 LED Control 1 */
 #define MC13783_LED_C1_TC1HALF         (1 << 18)
 #define MC13783_LED_C1_SLEWLIM         (1 << 23)
-/* LED Control 2 */
+/* MC13783 LED Control 2 */
+#define MC13783_LED_C2_CURRENT_MD(x)   (((x) & 0x7) << 0)
+#define MC13783_LED_C2_CURRENT_AD(x)   (((x) & 0x7) << 3)
+#define MC13783_LED_C2_CURRENT_KP(x)   (((x) & 0x7) << 6)
 #define MC13783_LED_C2_PERIOD(x)       (((x) & 0x3) << 21)
 #define MC13783_LED_C2_SLEWLIM         (1 << 23)
-/* LED Control 3 */
+/* MC13783 LED Control 3 */
+#define MC13783_LED_C3_CURRENT_R1(x)   (((x) & 0x3) << 0)
+#define MC13783_LED_C3_CURRENT_G1(x)   (((x) & 0x3) << 2)
+#define MC13783_LED_C3_CURRENT_B1(x)   (((x) & 0x3) << 4)
 #define MC13783_LED_C3_PERIOD(x)       (((x) & 0x3) << 21)
 #define MC13783_LED_C3_TRIODE_TC1      (1 << 23)
-/* LED Control 4 */
+/* MC13783 LED Control 4 */
+#define MC13783_LED_C4_CURRENT_R2(x)   (((x) & 0x3) << 0)
+#define MC13783_LED_C4_CURRENT_G2(x)   (((x) & 0x3) << 2)
+#define MC13783_LED_C4_CURRENT_B2(x)   (((x) & 0x3) << 4)
 #define MC13783_LED_C4_PERIOD(x)       (((x) & 0x3) << 21)
 #define MC13783_LED_C4_TRIODE_TC2      (1 << 23)
-/* LED Control 5 */
+/* MC13783 LED Control 5 */
+#define MC13783_LED_C5_CURRENT_R3(x)   (((x) & 0x3) << 0)
+#define MC13783_LED_C5_CURRENT_G3(x)   (((x) & 0x3) << 2)
+#define MC13783_LED_C5_CURRENT_B3(x)   (((x) & 0x3) << 4)
 #define MC13783_LED_C5_PERIOD(x)       (((x) & 0x3) << 21)
 #define MC13783_LED_C5_TRIODE_TC3      (1 << 23)
+/* MC13892 LED Control 0 */
+#define MC13892_LED_C0_CURRENT_MD(x)   (((x) & 0x7) << 9)
+#define MC13892_LED_C0_CURRENT_AD(x)   (((x) & 0x7) << 21)
+/* MC13892 LED Control 1 */
+#define MC13892_LED_C1_CURRENT_KP(x)   (((x) & 0x7) << 9)
+/* MC13892 LED Control 2 */
+#define MC13892_LED_C2_CURRENT_R(x)    (((x) & 0x7) << 9)
+#define MC13892_LED_C2_CURRENT_G(x)    (((x) & 0x7) << 21)
+/* MC13892 LED Control 3 */
+#define MC13892_LED_C3_CURRENT_B(x)    (((x) & 0x7) << 9)
        u32 led_control[MAX_LED_CONTROL_REGS];
 };
 
index 24b536ebdf13de364c5c5bf0f0106d654eb94d31..d2be19a51acde32102710cdf0db536fe4d364f01 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/arm/mach-kirkwood/include/mach/leds-netxbig.h
- *
  * Platform data structure for netxbig LED driver
  *
  * This file is licensed under the terms of the GNU General Public
@@ -8,8 +6,8 @@
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef __MACH_LEDS_NETXBIG_H
-#define __MACH_LEDS_NETXBIG_H
+#ifndef __LEDS_KIRKWOOD_NETXBIG_H
+#define __LEDS_KIRKWOOD_NETXBIG_H
 
 struct netxbig_gpio_ext {
        unsigned        *addr;
@@ -52,4 +50,4 @@ struct netxbig_led_platform_data {
        int                     num_leds;
 };
 
-#endif /* __MACH_LEDS_NETXBIG_H */
+#endif /* __LEDS_KIRKWOOD_NETXBIG_H */
index e21272e5f66847112a7805ed90730e0eca612b42..6a9fed57f34620c20a931f317150e5a381058e8f 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/arm/mach-kirkwood/include/mach/leds-ns2.h
- *
  * Platform data structure for Network Space v2 LED driver
  *
  * This file is licensed under the terms of the GNU General Public
@@ -8,8 +6,8 @@
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef __MACH_LEDS_NS2_H
-#define __MACH_LEDS_NS2_H
+#ifndef __LEDS_KIRKWOOD_NS2_H
+#define __LEDS_KIRKWOOD_NS2_H
 
 struct ns2_led {
        const char      *name;
@@ -23,4 +21,4 @@ struct ns2_led_platform_data {
        struct ns2_led  *leds;
 };
 
-#endif /* __MACH_LEDS_NS2_H */
+#endif /* __LEDS_KIRKWOOD_NS2_H */