From 17702c46e6d86d2318e76025e67dba8ec54306ea Mon Sep 17 00:00:00 2001 From: Matt Hsu Date: Fri, 6 Mar 2009 12:28:25 +0000 Subject: Re-write lp5521 LED driver. - provide clean sysfs to control RGB channel directly. They are looked like the following: channel_mode channel_pwm channel_cur - add platform data to export RGB channel accordingly. Signed-off-by: Matt Hsu --- drivers/leds/leds-lp5521.c | 637 +++++++++++++++------------------------------ 1 file changed, 204 insertions(+), 433 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 7bbf79a6f3a..0415b9e6d77 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c @@ -1,10 +1,7 @@ -/* - * drivers/leds/leds-lp5521.c - * - * Copyright (C) 2007 Nokia Corporation +/* NS LP5521 Programmable LED driver. * - * Written by Mathias Nyman - * Matt Hsu + * (C) 2009 by Openmoko, Inc. + * Author: Matt Hsu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,491 +17,247 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - #include #include #include #include +#include +#include +#include +#include #include -#define LP5521_DRIVER_NAME "lp5521" - -#ifdef LED_CONNECTED_WRONG -#define LP5521_REG_R_PWM 0x04 -#define LP5521_REG_B_PWM 0x02 -#else -#define LP5521_REG_R_PWM 0x02 -#define LP5521_REG_B_PWM 0x04 -#endif -#define LP5521_REG_ENABLE 0x00 -#define LP5521_REG_OP_MODE 0x01 -#define LP5521_REG_G_PWM 0x03 -#define LP5521_REG_R_CNTRL 0x05 -#define LP5521_REG_G_CNTRL 0x06 -#define LP5521_REG_B_CNTRL 0x07 -#define LP5521_REG_MISC 0x08 -#define LP5521_REG_R_CHANNEL_PC 0x09 -#define LP5521_REG_G_CHANNEL_PC 0x0a -#define LP5521_REG_B_CHANNEL_PC 0x0b -#define LP5521_REG_STATUS 0x0c -#define LP5521_REG_RESET 0x0d -#define LP5521_REG_GPO 0x0e -#define LP5521_REG_R_PROG_MEM 0x10 -#define LP5521_REG_G_PROG_MEM 0x30 -#define LP5521_REG_B_PROG_MEM 0x50 - -#define LP5521_MODE_LOAD "load" -#define LP5521_MODE_RUN "run" -#define LP5521_MODE_DIRECT_CONTROL "direct" - -#define LP5521_CURRENT_1m5 0x0f -#define LP5521_CURRENT_3m1 0x1f -#define LP5521_CURRENT_4m7 0x2f -#define LP5521_CURRENT_6m3 0x3f -#define LP5521_CURRENT_7m9 0x4f -#define LP5521_CURRENT_9m5 0x5f -#define LP5521_CURRENT_11m1 0x6f -#define LP5521_CURRENT_12m7 0x7f -#define LP5521_CURRENT_14m3 0x8f -#define LP5521_CURRENT_15m9 0x9f -#define LP5521_CURRENT_17m5 0xaf -#define LP5521_CURRENT_19m1 0xbf -#define LP5521_CURRENT_20m7 0xcf -#define LP5521_CURRENT_22m3 0xdf -#define LP5521_CURRENT_23m9 0xef -#define LP5521_CURRENT_25m5 0xff - -#define LP5521_PROGRAM_LENGTH 32 /* in bytes */ - -struct lp5521_chip { - struct mutex lock; - struct i2c_client *client; - char *mode; - int red; - int green; - int blue; -}; - -static int lp5521_set_mode(struct lp5521_chip *chip, char *mode); +#define LP5521_DRIVER_NAME "lp5521" -static int lp5521_write(struct i2c_client *client, u8 reg, u8 value) +static int __lp5521_reg_write(struct lp5521 *lp, u8 reg, u8 value) { - return i2c_smbus_write_byte_data(client, reg, value); + return i2c_smbus_write_byte_data(lp->client, reg, value); } -static int lp5521_read(struct i2c_client *client, u8 reg, u8 *buf) +static int reg_write(struct lp5521 *lp, u_int8_t reg, u_int8_t val) { - s32 ret = i2c_smbus_read_byte_data(client, reg); + int ret; - if (ret < 0) - return -EIO; + mutex_lock(&lp->lock); + ret = __lp5521_reg_write(lp, reg, val); + mutex_unlock(&lp->lock); - *buf = ret; - return 0; + return ret; } -static int lp5521_configure(struct i2c_client *client) +static int __lp5521_reg_read(struct lp5521 *lp, u8 reg) { - int ret = 0; - - /* Enable chip and set light to logarithmic mode*/ - ret |= lp5521_write(client, LP5521_REG_ENABLE, 0xc0); - - /* setting all color pwms to direct control mode */ - ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x3f); + int32_t ret; - /* setting current to 4.7 mA for all channels */ - ret |= lp5521_write(client, LP5521_REG_R_CNTRL, LP5521_CURRENT_4m7); - ret |= lp5521_write(client, LP5521_REG_G_CNTRL, LP5521_CURRENT_4m7); - ret |= lp5521_write(client, LP5521_REG_B_CNTRL, LP5521_CURRENT_4m7); + ret = i2c_smbus_read_byte_data(lp->client, reg); - /* Enable auto-powersave, set charge pump to auto, red to battery */ - ret |= lp5521_write(client, LP5521_REG_MISC, 0x3c); - - /* initialize all channels pwm to zero */ - ret |= lp5521_write(client, LP5521_REG_R_PWM, 0); - ret |= lp5521_write(client, LP5521_REG_G_PWM, 0); - ret |= lp5521_write(client, LP5521_REG_B_PWM, 0); - - /* Not much can be done about errors at this point */ return ret; } -static int lp5521_load_program(struct lp5521_chip *chip, u8 *pattern) +static u_int8_t reg_read(struct lp5521 *lp, u_int8_t reg) { - struct i2c_client *client = chip->client; - int ret = 0; + int32_t ret; - /* Enter load program mode for all led channels */ - ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x15); /* 0001 0101 */ - if (ret) - return ret; - - if (chip->red) - ret |= i2c_smbus_write_i2c_block_data(client, - LP5521_REG_R_PROG_MEM, - LP5521_PROGRAM_LENGTH, - pattern); - if (chip->green) - ret |= i2c_smbus_write_i2c_block_data(client, - LP5521_REG_G_PROG_MEM, - LP5521_PROGRAM_LENGTH, - pattern); - if (chip->blue) - ret |= i2c_smbus_write_i2c_block_data(client, - LP5521_REG_B_PROG_MEM, - LP5521_PROGRAM_LENGTH, - pattern); + mutex_lock(&lp->lock); + ret = __lp5521_reg_read(lp, reg); + mutex_unlock(&lp->lock); - return ret; + return ret & 0xff; } -static int lp5521_run_program(struct lp5521_chip *chip) +static int reg_set_bit_mask(struct lp5521 *lp, + u_int8_t reg, u_int8_t mask, u_int8_t val) { - struct i2c_client *client = chip->client; int ret; - u8 mask = 0xc0; - u8 exec_state = 0; - u8 enable_reg; - - ret = lp5521_read(client, LP5521_REG_ENABLE, &enable_reg); - if (ret) - goto fail; - - enable_reg &= mask; + u_int8_t tmp; - /* set all active channels exec state to countinous run*/ - exec_state |= (chip->red << 5); - exec_state |= (chip->green << 3); - exec_state |= (chip->blue << 1); + val &= mask; - enable_reg |= exec_state; + mutex_lock(&lp->lock); - ret |= lp5521_write(client, LP5521_REG_ENABLE, enable_reg); + tmp = __lp5521_reg_read(lp, reg); + tmp &= ~mask; + tmp |= val; + ret = __lp5521_reg_write(lp, reg, tmp); - /* set op-mode to run for active channels, disabled for others */ - ret |= lp5521_write(client, LP5521_REG_OP_MODE, exec_state); + mutex_unlock(&lp->lock); -fail: return ret; } -/*--------------------------------------------------------------*/ -/* Sysfs interface */ -/*--------------------------------------------------------------*/ +static const char *lp5521_ch_name[] = { + "blue", "green", "red", +}; -static ssize_t show_active_channels(struct device *dev, - struct device_attribute *attr, - char *buf) +static inline int channel_id_by_name(const char *name) { - struct lp5521_chip *chip = dev_get_drvdata(dev); - char channels[4]; - int pos = 0; - -#ifdef LED_CONNECTED_WRONG - if (chip->blue) - pos += sprintf(channels + pos, "r"); - if (chip->green) - pos += sprintf(channels + pos, "g"); - if (chip->red) - pos += sprintf(channels + pos, "b"); - -#else - if (chip->red) - pos += sprintf(channels + pos, "r"); - if (chip->green) - pos += sprintf(channels + pos, "g"); - if (chip->blue) - pos += sprintf(channels + pos, "b"); -#endif - - channels[pos] = '\0'; - - return sprintf(buf, "%s\n", channels); + int channel_id = -1; + + if (!strncmp(name, lp5521_ch_name[LP5521_BLUE], + strlen(lp5521_ch_name[LP5521_BLUE]))) + channel_id = LP5521_BLUE; + else if (!strncmp(name, lp5521_ch_name[LP5521_GREEN], + strlen(lp5521_ch_name[LP5521_GREEN]))) + channel_id = LP5521_GREEN; + else if (!strncmp(name, lp5521_ch_name[LP5521_RED], + strlen(lp5521_ch_name[LP5521_RED]))) + channel_id = LP5521_RED; + + return channel_id; } -static ssize_t store_active_channels(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct lp5521_chip *chip = dev_get_drvdata(dev); - - chip->red = 0; - chip->green = 0; - chip->blue = 0; - -#ifdef LED_CONNECTED_WRONG - if (strchr(buf, 'r') != NULL) - chip->blue = 1; - if (strchr(buf, 'b') != NULL) - chip->red = 1; -#else - if (strchr(buf, 'r') != NULL) - chip->red = 1; - if (strchr(buf, 'b') != NULL) - chip->blue = 1; -#endif - if (strchr(buf, 'g') != NULL) - chip->green = 1; - - return len; -} +static const char *lp5521_ch_mode[] = { + "disable", "load", "run", + "direct", +}; -static ssize_t show_color(struct device *dev, - struct device_attribute *attr, - char *buf) +/* + * Individual mode control + */ +static ssize_t show_mode(struct device *dev, struct device_attribute + *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); - int ret = 0; - u8 r, g, b; + struct lp5521 *lp = i2c_get_clientdata(client); + int id; + uint8_t val; - ret |= lp5521_read(client, LP5521_REG_R_PWM, &r); - ret |= lp5521_read(client, LP5521_REG_G_PWM, &g); - ret |= lp5521_read(client, LP5521_REG_B_PWM, &b); + id = channel_id_by_name(attr->attr.name); + val = reg_read(lp, LP5521_REG_OP_MODE); - if (ret) - return ret; + val = val >> (id * 2); + val &= 0x3; - return sprintf(buf, "%.2x:%.2x:%.2x\n", r, g, b); + return sprintf(buf, "%s\n", lp5521_ch_mode[val]); } -static ssize_t store_color(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t set_mode(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); - struct lp5521_chip *chip = i2c_get_clientdata(client); - int ret; - unsigned r, g, b; - + struct lp5521 *lp = i2c_get_clientdata(client); + int id; + uint8_t mask, i; - ret = sscanf(buf, "%2x:%2x:%2x", &r, &g, &b); - if (ret != 3) - return -EINVAL; + id = channel_id_by_name(attr->attr.name); - mutex_lock(&chip->lock); + mask = (0x3 << (id * 2)); - ret = lp5521_write(client, LP5521_REG_R_PWM, (u8)r); - ret = lp5521_write(client, LP5521_REG_G_PWM, (u8)g); - ret = lp5521_write(client, LP5521_REG_B_PWM, (u8)b); - - mutex_unlock(&chip->lock); - - return len; -} - -static ssize_t store_load(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct lp5521_chip *chip = dev_get_drvdata(dev); - int ret, nrchars, offset = 0, i = 0; - char c[3]; - unsigned cmd; - u8 pattern[LP5521_PROGRAM_LENGTH] = {0}; - - while ((offset < len - 1) && (i < LP5521_PROGRAM_LENGTH)) { - - /* separate sscanfs because length is working only for %s */ - ret = sscanf(buf + offset, "%2s%n ", c, &nrchars); - ret = sscanf(c, "%2x", &cmd); - if (ret != 1) - goto fail; - pattern[i] = (u8)cmd; - - offset += nrchars; - i++; + for (i = LP5521_REG_OP_MODE; i <= LP5521_MODE_DIRECT; i++) { + if (!strncmp(buf, lp5521_ch_mode[i], strlen(lp5521_ch_mode[i]))) { + reg_set_bit_mask(lp, + LP5521_REG_OP_MODE, mask, (i << (id * 2))); + } } - /* pattern commands are always two bytes long */ - if (i % 2) - goto fail; - - mutex_lock(&chip->lock); - - ret = lp5521_load_program(chip, pattern); - mutex_unlock(&chip->lock); - - if (ret) { - dev_err(dev, "lp5521 failed loading pattern\n"); - return ret; - } - - return len; -fail: - dev_err(dev, "lp5521 wrong pattern format\n"); - return -EINVAL; + return count; } -static ssize_t show_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct lp5521_chip *chip = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", chip->mode); -} - -static ssize_t store_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct lp5521_chip *chip = dev_get_drvdata(dev); - - mutex_lock(&chip->lock); - - if (!strncmp(buf, "run", 3)) - lp5521_set_mode(chip, LP5521_MODE_RUN); - else if (!strncmp(buf, "load", 4)) - lp5521_set_mode(chip, LP5521_MODE_LOAD); - else if (!strncmp(buf, "direct", 6)) - lp5521_set_mode(chip, LP5521_MODE_DIRECT_CONTROL); +static DEVICE_ATTR(red_mode, S_IRUGO | S_IWUSR, show_mode, set_mode); +static DEVICE_ATTR(green_mode, S_IRUGO | S_IWUSR, show_mode, set_mode); +static DEVICE_ATTR(blue_mode, S_IRUGO | S_IWUSR, show_mode, set_mode); - mutex_unlock(&chip->lock); - - return len; -} - -static ssize_t show_current(struct device *dev, - struct device_attribute *attr, - char *buf) +/* + * Individual pwm control + */ +static ssize_t show_pwm(struct device *dev, struct device_attribute + *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); - int ret = 0; - u8 r_curr, g_curr, b_curr; - - ret |= lp5521_read(client, LP5521_REG_R_CNTRL, &r_curr); - ret |= lp5521_read(client, LP5521_REG_G_CNTRL, &g_curr); - ret |= lp5521_read(client, LP5521_REG_B_CNTRL, &b_curr); + struct lp5521 *lp = i2c_get_clientdata(client); + int id; + uint8_t val; - if (ret) - return ret; + id = channel_id_by_name(attr->attr.name); + val = reg_read(lp, LP5521_REG_B_PWM-id); - r_curr = r_curr >> 4; - g_curr = g_curr >> 4; - b_curr = b_curr >> 4; - - if (r_curr == g_curr && g_curr == b_curr) - return sprintf(buf, "%x\n", r_curr); - else - return sprintf(buf, "%x %x %x\n", r_curr, g_curr, b_curr); + return sprintf(buf, "%d\n", val); } -static ssize_t store_current(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { - struct lp5521_chip *chip = dev_get_drvdata(dev); - struct i2c_client *client = chip->client; - int ret; - unsigned curr; - - ret = sscanf(buf, "%1x", &curr); - if (ret != 1) - return -EINVAL; - - /* current level is determined by the 4 upper bits, rest is ones */ - curr = (curr << 4) | 0x0f; - - mutex_lock(&chip->lock); - - ret |= lp5521_write(client, LP5521_REG_R_CNTRL, (u8)curr); - ret |= lp5521_write(client, LP5521_REG_G_CNTRL, (u8)curr); - ret |= lp5521_write(client, LP5521_REG_B_CNTRL, (u8)curr); + int id; + struct i2c_client *client = to_i2c_client(dev); + struct lp5521 *lp = i2c_get_clientdata(client); + unsigned int pwm = simple_strtoul(buf, NULL, 10); - mutex_unlock(&chip->lock); + id = channel_id_by_name(attr->attr.name); + reg_write(lp, LP5521_REG_B_PWM-id, pwm); - return len; + return count; } -static DEVICE_ATTR(color, S_IRUGO | S_IWUGO, show_color, store_color); -static DEVICE_ATTR(load, S_IWUGO, NULL, store_load); -static DEVICE_ATTR(mode, S_IRUGO | S_IWUGO, show_mode, store_mode); -static DEVICE_ATTR(active_channels, S_IRUGO | S_IWUGO, - show_active_channels, store_active_channels); -static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current); +static DEVICE_ATTR(red_pwm, S_IRUGO | S_IWUSR, show_pwm, set_pwm); +static DEVICE_ATTR(green_pwm, S_IRUGO | S_IWUSR, show_pwm, set_pwm); +static DEVICE_ATTR(blue_pwm, S_IRUGO | S_IWUSR, show_pwm, set_pwm); -static int lp5521_register_sysfs(struct i2c_client *client) +/* + * Individual current control + */ +static ssize_t show_cur(struct device *dev, struct device_attribute + *attr, char *buf) { - struct device *dev = &client->dev; - int ret; + struct i2c_client *client = to_i2c_client(dev); + struct lp5521 *lp = i2c_get_clientdata(client); + int id; + uint8_t val; - ret = device_create_file(dev, &dev_attr_color); - if (ret) - goto fail1; - ret = device_create_file(dev, &dev_attr_load); - if (ret) - goto fail2; - ret = device_create_file(dev, &dev_attr_active_channels); - if (ret) - goto fail3; - ret = device_create_file(dev, &dev_attr_mode); - if (ret) - goto fail4; - ret = device_create_file(dev, &dev_attr_led_current); - if (ret) - goto fail5; - return 0; + id = channel_id_by_name(attr->attr.name); + val = reg_read(lp, LP5521_REG_B_CUR-id); -fail5: - device_remove_file(dev, &dev_attr_mode); -fail4: - device_remove_file(dev, &dev_attr_active_channels); -fail3: - device_remove_file(dev, &dev_attr_load); -fail2: - device_remove_file(dev, &dev_attr_color); -fail1: - return ret; + return sprintf(buf, "%d (100uA)\n", val); } -#ifdef MODULE -static void lp5521_unregister_sysfs(struct i2c_client *client) +static ssize_t set_cur(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { - struct lp5521_chip *chip = i2c_get_clientdata(client); - struct device *dev = &client->dev; + int id; + struct i2c_client *client = to_i2c_client(dev); + struct lp5521 *lp = i2c_get_clientdata(client); + unsigned int cur = simple_strtoul(buf, NULL, 10); - device_remove_file(dev, &dev_attr_led_current); - device_remove_file(dev, &dev_attr_mode); - device_remove_file(dev, &dev_attr_active_channels); - device_remove_file(dev, &dev_attr_color); + id = channel_id_by_name(attr->attr.name); + reg_write(lp, LP5521_REG_B_CUR-id, cur); - if (!strcmp(chip->mode, LP5521_MODE_LOAD)) - device_remove_file(dev, &dev_attr_load); + return count; } -#endif -/*--------------------------------------------------------------*/ -/* Set chip operating mode */ -/*--------------------------------------------------------------*/ - -static int lp5521_set_mode(struct lp5521_chip *chip, char *mode) -{ - struct i2c_client *client = chip->client ; - int ret = 0; +static DEVICE_ATTR(red_cur, S_IRUGO | S_IWUSR, show_cur, set_cur); +static DEVICE_ATTR(green_cur, S_IRUGO | S_IWUSR, show_cur, set_cur); +static DEVICE_ATTR(blue_cur, S_IRUGO | S_IWUSR, show_cur, set_cur); - /* if in that mode already do nothing, except for run */ - if (!strcmp(mode, chip->mode) && strcmp(mode, LP5521_MODE_RUN)) - return 0; +static struct attribute *lp_sysfs_entries[16]; - if (!strcmp(mode, LP5521_MODE_RUN)) - ret = lp5521_run_program(chip); +static struct attribute_group lp_attr_group = { + .name = NULL, + .attrs = lp_sysfs_entries, +}; - if (!strcmp(mode, LP5521_MODE_LOAD)) - ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x15); +static void populate_sysfs_group(struct lp5521 *lp) +{ + int i = 0; - if (!strcmp(mode, LP5521_MODE_DIRECT_CONTROL)) - ret |= lp5521_write(client, LP5521_REG_OP_MODE, 0x3F); + if (lp->pdata->channels[LP5521_RED] & LP5521_CONNECTED) { + lp_sysfs_entries[i++] = &dev_attr_red_mode.attr; + lp_sysfs_entries[i++] = &dev_attr_red_pwm.attr; + lp_sysfs_entries[i++] = &dev_attr_red_cur.attr; + } - chip->mode = mode; + if (lp->pdata->channels[LP5521_GREEN] & LP5521_CONNECTED) { + lp_sysfs_entries[i++] = &dev_attr_green_mode.attr; + lp_sysfs_entries[i++] = &dev_attr_green_pwm.attr; + lp_sysfs_entries[i++] = &dev_attr_green_cur.attr; + } - return ret; + if (lp->pdata->channels[LP5521_BLUE] & LP5521_CONNECTED) { + lp_sysfs_entries[i++] = &dev_attr_blue_mode.attr; + lp_sysfs_entries[i++] = &dev_attr_blue_pwm.attr; + lp_sysfs_entries[i++] = &dev_attr_blue_cur.attr; + } } -/*--------------------------------------------------------------*/ -/* Probe, Attach, Remove */ -/*--------------------------------------------------------------*/ static struct i2c_driver lp5521_driver; #ifdef CONFIG_PM @@ -527,60 +280,78 @@ static int lp5521_resume(struct device *dev) #define lp5521_resume NULL #endif -static int lp5521_probe(struct i2c_client *client, const struct i2c_device_id *id) +static irqreturn_t lp5521_irq(int irq, void *_lp) { - struct lp5521_chip *chip; + struct lp5521 *lp = _lp; + dev_info(lp->dev, "lp5521 interrupt\n"); + + return IRQ_HANDLED; +} + +static int __devinit +lp5521_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct lp5521 *lp; int ret = 0; struct lp5521_platform_data *pdata = client->dev.platform_data; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) + lp = kzalloc(sizeof(*lp), GFP_KERNEL); + if (!lp) return -ENOMEM; - chip->client = client; - strncpy(client->name, LP5521_DRIVER_NAME, I2C_NAME_SIZE); - i2c_set_clientdata(client, chip); + lp->client = client; + lp->irq = client->irq; + lp->dev = &client->dev; + i2c_set_clientdata(client, lp); - mutex_init(&chip->lock); + lp->pdata = pdata; + mutex_init(&lp->lock); /* enter start-up mode */ if (pdata->ext_enable) (pdata->ext_enable)(1); - ret = lp5521_configure(client); - if (ret < 0) { - dev_err(&client->dev, "lp5521 error configuring chip \n"); - goto fail1; + reg_write(lp, LP5521_REG_ENABLE, 0x40); + + /* charge pump mode and clk src selection */ + reg_write(lp, LP5521_REG_CONFIG, 0x11); + + /* allocate IRQ resource */ + if (lp->irq) { + ret = request_irq(client->irq, lp5521_irq, + IRQF_TRIGGER_LOW, LP5521_DRIVER_NAME, lp); + if (ret) { + dev_err(lp->dev, "request IRQ failed\n"); + goto fail; + } + } else { + dev_err(lp->dev, "No IRQ allocated \n"); } - /* Set default values */ - chip->mode = LP5521_MODE_DIRECT_CONTROL; - chip->red = 1; - chip->green = 1; - chip->blue = 1; + populate_sysfs_group(lp); - ret = lp5521_register_sysfs(client); - if (ret) - dev_err(&client->dev, "lp5521 registering sysfs failed \n"); + ret = sysfs_create_group(&client->dev.kobj, &lp_attr_group); + + if (ret) { + dev_err(lp->dev, "error creating sysfs group\n"); + goto fail; + } return ret; -fail1: - kfree(chip); +fail: + kfree(lp); return ret; } -#ifdef MODULE -static int lp5521_remove(struct i2c_client *client) +static int __devexit lp5521_remove(struct i2c_client *client) { - struct lp5521_chip *chip = i2c_get_clientdata(client); + struct lp5521 *lp = i2c_get_clientdata(client); - lp5521_unregister_sysfs(client); - kfree(chip); + kfree(lp); return 0; } -#endif static struct i2c_device_id lp5521_id[] = { {LP5521_DRIVER_NAME, }, @@ -607,9 +378,9 @@ static void __exit lp5521_exit(void) i2c_del_driver(&lp5521_driver); } -MODULE_AUTHOR("Mathias Nyman "); -MODULE_DESCRIPTION("lp5521 LED driver"); -MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Matt Hsu "); +MODULE_DESCRIPTION("NS lp5521 LED driver"); +MODULE_LICENSE("GPLv2"); module_init(lp5521_init); module_exit(lp5521_exit); -- cgit v1.2.3