Skip to content

Commit

Permalink
leds: add the sysfs interface into the leds-bd2802 driver for changin…
Browse files Browse the repository at this point in the history
…g wave pattern and led current.

Allow the user application to change the wave pattern and led current by
'wave_pattern' and 'rgb_current' sysfs files.

Signed-off-by: Kim Kyuwon <q1.kim@samsung.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
  • Loading branch information
Kim Kyuwon authored and Richard Purdie committed Jun 23, 2009
1 parent 1b18cf4 commit 8792f7c
Showing 1 changed file with 73 additions and 13 deletions.
86 changes: 73 additions & 13 deletions drivers/leds/leds-bd2802.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ struct bd2802_led {
enum led_ids led_id;
enum led_colors color;
enum led_bits state;

/* General attributes of RGB LEDs */
int wave_pattern;
int rgb_current;
};


Expand Down Expand Up @@ -254,7 +258,7 @@ static void bd2802_set_on(struct bd2802_led *led, enum led_ids id,
bd2802_reset_cancel(led);

reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP);
bd2802_write_byte(led->client, reg, BD2802_CURRENT_032);
bd2802_write_byte(led->client, reg, led->rgb_current);
reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP);
bd2802_write_byte(led->client, reg, BD2802_CURRENT_000);
reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN);
Expand All @@ -275,9 +279,9 @@ static void bd2802_set_blink(struct bd2802_led *led, enum led_ids id,
reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP);
bd2802_write_byte(led->client, reg, BD2802_CURRENT_000);
reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP);
bd2802_write_byte(led->client, reg, BD2802_CURRENT_032);
bd2802_write_byte(led->client, reg, led->rgb_current);
reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN);
bd2802_write_byte(led->client, reg, BD2802_PATTERN_HALF);
bd2802_write_byte(led->client, reg, led->wave_pattern);

bd2802_enable(led, id);
bd2802_update_state(led, id, color, BD2802_BLINK);
Expand Down Expand Up @@ -406,7 +410,7 @@ static void bd2802_enable_adv_conf(struct bd2802_led *led)
ret = device_create_file(&led->client->dev,
bd2802_addr_attributes[i]);
if (ret) {
dev_err(&led->client->dev, "failed to sysfs file %s\n",
dev_err(&led->client->dev, "failed: sysfs file %s\n",
bd2802_addr_attributes[i]->attr.name);
goto failed_remove_files;
}
Expand Down Expand Up @@ -483,6 +487,52 @@ static struct device_attribute bd2802_adv_conf_attr = {
.store = bd2802_store_adv_conf,
};

#define BD2802_CONTROL_ATTR(attr_name, name_str) \
static ssize_t bd2802_show_##attr_name(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\
ssize_t ret; \
down_read(&led->rwsem); \
ret = sprintf(buf, "0x%02x\n", led->attr_name); \
up_read(&led->rwsem); \
return ret; \
} \
static ssize_t bd2802_store_##attr_name(struct device *dev, \
struct device_attribute *attr, const char *buf, size_t count) \
{ \
struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\
unsigned long val; \
int ret; \
if (!count) \
return -EINVAL; \
ret = strict_strtoul(buf, 16, &val); \
if (ret) \
return ret; \
down_write(&led->rwsem); \
led->attr_name = val; \
up_write(&led->rwsem); \
return count; \
} \
static struct device_attribute bd2802_##attr_name##_attr = { \
.attr = { \
.name = name_str, \
.mode = 0644, \
.owner = THIS_MODULE \
}, \
.show = bd2802_show_##attr_name, \
.store = bd2802_store_##attr_name, \
};

BD2802_CONTROL_ATTR(wave_pattern, "wave_pattern");
BD2802_CONTROL_ATTR(rgb_current, "rgb_current");

static struct device_attribute *bd2802_attributes[] = {
&bd2802_adv_conf_attr,
&bd2802_wave_pattern_attr,
&bd2802_rgb_current_attr,
};

static void bd2802_led_work(struct work_struct *work)
{
struct bd2802_led *led = container_of(work, struct bd2802_led, work);
Expand Down Expand Up @@ -635,7 +685,7 @@ static int __devinit bd2802_probe(struct i2c_client *client,
{
struct bd2802_led *led;
struct bd2802_led_platform_data *pdata;
int ret;
int ret, i;

led = kzalloc(sizeof(struct bd2802_led), GFP_KERNEL);
if (!led) {
Expand Down Expand Up @@ -665,13 +715,20 @@ static int __devinit bd2802_probe(struct i2c_client *client,
/* To save the power, reset BD2802 after detecting */
gpio_set_value(led->pdata->reset_gpio, 0);

/* Default attributes */
led->wave_pattern = BD2802_PATTERN_HALF;
led->rgb_current = BD2802_CURRENT_032;

init_rwsem(&led->rwsem);

ret = device_create_file(&client->dev, &bd2802_adv_conf_attr);
if (ret) {
dev_err(&client->dev, "failed to create sysfs file %s\n",
bd2802_adv_conf_attr.attr.name);
goto failed_free;
for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) {
ret = device_create_file(&led->client->dev,
bd2802_attributes[i]);
if (ret) {
dev_err(&led->client->dev, "failed: sysfs file %s\n",
bd2802_attributes[i]->attr.name);
goto failed_unregister_dev_file;
}
}

ret = bd2802_register_led_classdev(led);
Expand All @@ -681,7 +738,8 @@ static int __devinit bd2802_probe(struct i2c_client *client,
return 0;

failed_unregister_dev_file:
device_remove_file(&client->dev, &bd2802_adv_conf_attr);
for (i--; i >= 0; i--)
device_remove_file(&led->client->dev, bd2802_attributes[i]);
failed_free:
i2c_set_clientdata(client, NULL);
kfree(led);
Expand All @@ -692,12 +750,14 @@ static int __devinit bd2802_probe(struct i2c_client *client,
static int __exit bd2802_remove(struct i2c_client *client)
{
struct bd2802_led *led = i2c_get_clientdata(client);
int i;

bd2802_unregister_led_classdev(led);
gpio_set_value(led->pdata->reset_gpio, 0);
bd2802_unregister_led_classdev(led);
if (led->adf_on)
bd2802_disable_adv_conf(led);
device_remove_file(&client->dev, &bd2802_adv_conf_attr);
for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++)
device_remove_file(&led->client->dev, bd2802_attributes[i]);
i2c_set_clientdata(client, NULL);
kfree(led);

Expand Down

0 comments on commit 8792f7c

Please sign in to comment.