]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/leds/leds-lp5521.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[karo-tx-linux.git] / drivers / leds / leds-lp5521.c
index 1392feb1bcf7849559ba29b38f163afa01a305bb..05188351711d2d80f5ac8cd0a006159b732b2c90 100644 (file)
@@ -220,17 +220,11 @@ static int lp5521_update_program_memory(struct lp55xx_chip *chip,
        };
        unsigned cmd;
        char c[3];
-       int program_size;
        int nrchars;
-       int offset = 0;
        int ret;
-       int i;
-
-       /* clear program memory before updating */
-       for (i = 0; i < LP5521_PROGRAM_LENGTH; i++)
-               lp55xx_write(chip, addr[idx] + i, 0);
+       int offset = 0;
+       int i = 0;
 
-       i = 0;
        while ((offset < size - 1) && (i < LP5521_PROGRAM_LENGTH)) {
                /* separate sscanfs because length is working only for %s */
                ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
@@ -250,11 +244,19 @@ static int lp5521_update_program_memory(struct lp55xx_chip *chip,
        if (i % 2)
                goto err;
 
-       program_size = i;
-       for (i = 0; i < program_size; i++)
-               lp55xx_write(chip, addr[idx] + i, pattern[i]);
+       mutex_lock(&chip->lock);
 
-       return 0;
+       for (i = 0; i < LP5521_PROGRAM_LENGTH; i++) {
+               ret = lp55xx_write(chip, addr[idx] + i, pattern[i]);
+               if (ret) {
+                       mutex_unlock(&chip->lock);
+                       return -EINVAL;
+               }
+       }
+
+       mutex_unlock(&chip->lock);
+
+       return size;
 
 err:
        dev_err(&chip->cl->dev, "wrong pattern format\n");
@@ -365,6 +367,80 @@ static void lp5521_led_brightness_work(struct work_struct *work)
        mutex_unlock(&chip->lock);
 }
 
+static ssize_t show_engine_mode(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf, int nr)
+{
+       struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
+       struct lp55xx_chip *chip = led->chip;
+       enum lp55xx_engine_mode mode = chip->engines[nr - 1].mode;
+
+       switch (mode) {
+       case LP55XX_ENGINE_RUN:
+               return sprintf(buf, "run\n");
+       case LP55XX_ENGINE_LOAD:
+               return sprintf(buf, "load\n");
+       case LP55XX_ENGINE_DISABLED:
+       default:
+               return sprintf(buf, "disabled\n");
+       }
+}
+show_mode(1)
+show_mode(2)
+show_mode(3)
+
+static ssize_t store_engine_mode(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t len, int nr)
+{
+       struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
+       struct lp55xx_chip *chip = led->chip;
+       struct lp55xx_engine *engine = &chip->engines[nr - 1];
+
+       mutex_lock(&chip->lock);
+
+       chip->engine_idx = nr;
+
+       if (!strncmp(buf, "run", 3)) {
+               lp5521_run_engine(chip, true);
+               engine->mode = LP55XX_ENGINE_RUN;
+       } else if (!strncmp(buf, "load", 4)) {
+               lp5521_stop_engine(chip);
+               lp5521_load_engine(chip);
+               engine->mode = LP55XX_ENGINE_LOAD;
+       } else if (!strncmp(buf, "disabled", 8)) {
+               lp5521_stop_engine(chip);
+               engine->mode = LP55XX_ENGINE_DISABLED;
+       }
+
+       mutex_unlock(&chip->lock);
+
+       return len;
+}
+store_mode(1)
+store_mode(2)
+store_mode(3)
+
+static ssize_t store_engine_load(struct device *dev,
+                            struct device_attribute *attr,
+                            const char *buf, size_t len, int nr)
+{
+       struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
+       struct lp55xx_chip *chip = led->chip;
+
+       mutex_lock(&chip->lock);
+
+       chip->engine_idx = nr;
+       lp5521_load_engine(chip);
+
+       mutex_unlock(&chip->lock);
+
+       return lp5521_update_program_memory(chip, buf, len);
+}
+store_load(1)
+store_load(2)
+store_load(3)
+
 static ssize_t lp5521_selftest(struct device *dev,
                               struct device_attribute *attr,
                               char *buf)
@@ -381,9 +457,21 @@ static ssize_t lp5521_selftest(struct device *dev,
 }
 
 /* device attributes */
-static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL);
+static LP55XX_DEV_ATTR_RW(engine1_mode, show_engine1_mode, store_engine1_mode);
+static LP55XX_DEV_ATTR_RW(engine2_mode, show_engine2_mode, store_engine2_mode);
+static LP55XX_DEV_ATTR_RW(engine3_mode, show_engine3_mode, store_engine3_mode);
+static LP55XX_DEV_ATTR_WO(engine1_load, store_engine1_load);
+static LP55XX_DEV_ATTR_WO(engine2_load, store_engine2_load);
+static LP55XX_DEV_ATTR_WO(engine3_load, store_engine3_load);
+static LP55XX_DEV_ATTR_RO(selftest, lp5521_selftest);
 
 static struct attribute *lp5521_attributes[] = {
+       &dev_attr_engine1_mode.attr,
+       &dev_attr_engine2_mode.attr,
+       &dev_attr_engine3_mode.attr,
+       &dev_attr_engine1_load.attr,
+       &dev_attr_engine2_load.attr,
+       &dev_attr_engine3_load.attr,
        &dev_attr_selftest.attr,
        NULL
 };
@@ -420,7 +508,7 @@ static int lp5521_probe(struct i2c_client *client,
        struct lp55xx_platform_data *pdata;
        struct device_node *np = client->dev.of_node;
 
-       if (!client->dev.platform_data) {
+       if (!dev_get_platdata(&client->dev)) {
                if (np) {
                        ret = lp55xx_of_populate_pdata(&client->dev, np);
                        if (ret < 0)
@@ -430,7 +518,7 @@ static int lp5521_probe(struct i2c_client *client,
                        return -EINVAL;
                }
        }
-       pdata = client->dev.platform_data;
+       pdata = dev_get_platdata(&client->dev);
 
        chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
        if (!chip)