diff options
author | Evgeny Romanov <romanov@neurosoft.ru> | 2013-01-10 13:24:48 +0400 |
---|---|---|
committer | Anton Vorontsov <anton@enomsg.org> | 2013-02-03 07:07:34 +0400 |
commit | 7cee9aefda78019b6e7c42fcf3600b9fd8aeb8d5 (patch) | |
tree | 69bc89435734ea6dba548157c16a9acae6767377 /drivers/power | |
parent | 84d7b768748943db2bb658b43931fdab04c224cc (diff) | |
download | linux-7cee9aefda78019b6e7c42fcf3600b9fd8aeb8d5.tar.xz |
ds2782_battery: Add power_supply_changed() calls for proper uevent support
This patch affects on Android battery indicator. Battery driver should
send uevent message when battery status changes in order to get Android
battery level dynamically updated. Delayed work was added to periodically
check battery status and capacity.
Signed-off-by: Evgeny Romanov <romanov@neurosoft.ru>
Signed-off-by: Anton Vorontsov <anton@enomsg.org>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/ds2782_battery.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index 2fa9b6bf1f3f..e7301b3ed623 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c @@ -7,6 +7,8 @@ * * DS2786 added by Yulia Vilensky <vilensky@compulab.co.il> * + * UEvent sending added by Evgeny Romanov <romanov@neurosoft.ru> + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -19,6 +21,7 @@ #include <linux/errno.h> #include <linux/swab.h> #include <linux/i2c.h> +#include <linux/delay.h> #include <linux/idr.h> #include <linux/power_supply.h> #include <linux/slab.h> @@ -40,6 +43,8 @@ #define DS2786_CURRENT_UNITS 25 +#define DS278x_DELAY 1000 + struct ds278x_info; struct ds278x_battery_ops { @@ -54,8 +59,11 @@ struct ds278x_info { struct i2c_client *client; struct power_supply battery; struct ds278x_battery_ops *ops; + struct delayed_work bat_work; int id; int rsns; + int capacity; + int status; /* State Of Charge */ }; static DEFINE_IDR(battery_id); @@ -220,6 +228,8 @@ static int ds278x_get_status(struct ds278x_info *info, int *status) if (err) return err; + info->capacity = capacity; + if (capacity == 100) *status = POWER_SUPPLY_STATUS_FULL; else if (current_uA == 0) @@ -267,6 +277,27 @@ static int ds278x_battery_get_property(struct power_supply *psy, return ret; } +static void ds278x_bat_update(struct ds278x_info *info) +{ + int old_status = info->status; + int old_capacity = info->capacity; + + ds278x_get_status(info, &info->status); + + if ((old_status != info->status) || (old_capacity != info->capacity)) + power_supply_changed(&info->battery); +} + +static void ds278x_bat_work(struct work_struct *work) +{ + struct ds278x_info *info; + + info = container_of(work, struct ds278x_info, bat_work.work); + ds278x_bat_update(info); + + schedule_delayed_work(&info->bat_work, DS278x_DELAY); +} + static enum power_supply_property ds278x_battery_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_CAPACITY, @@ -295,10 +326,39 @@ static int ds278x_battery_remove(struct i2c_client *client) idr_remove(&battery_id, info->id); mutex_unlock(&battery_lock); + cancel_delayed_work(&info->bat_work); + kfree(info); return 0; } +#ifdef CONFIG_PM + +static int ds278x_suspend(struct i2c_client *client, + pm_message_t state) +{ + struct ds278x_info *info = i2c_get_clientdata(client); + + cancel_delayed_work(&info->bat_work); + return 0; +} + +static int ds278x_resume(struct i2c_client *client) +{ + struct ds278x_info *info = i2c_get_clientdata(client); + + schedule_delayed_work(&info->bat_work, DS278x_DELAY); + return 0; +} + +#else + +#define ds278x_suspend NULL +#define ds278x_resume NULL + +#endif /* CONFIG_PM */ + + enum ds278x_num_id { DS2782 = 0, DS2786, @@ -368,10 +428,17 @@ static int ds278x_battery_probe(struct i2c_client *client, info->ops = &ds278x_ops[id->driver_data]; ds278x_power_supply_init(&info->battery); + info->capacity = 100; + info->status = POWER_SUPPLY_STATUS_FULL; + + INIT_DELAYED_WORK(&info->bat_work, ds278x_bat_work); + ret = power_supply_register(&client->dev, &info->battery); if (ret) { dev_err(&client->dev, "failed to register battery\n"); goto fail_register; + } else { + schedule_delayed_work(&info->bat_work, DS278x_DELAY); } return 0; @@ -401,6 +468,8 @@ static struct i2c_driver ds278x_battery_driver = { }, .probe = ds278x_battery_probe, .remove = ds278x_battery_remove, + .suspend = ds278x_suspend, + .resume = ds278x_resume, .id_table = ds278x_id, }; module_i2c_driver(ds278x_battery_driver); |