aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/ds2782_battery.c
diff options
context:
space:
mode:
authorEvgeny Romanov <romanov@neurosoft.ru>2013-01-10 04:24:48 -0500
committerAnton Vorontsov <anton@enomsg.org>2013-02-02 22:07:34 -0500
commit7cee9aefda78019b6e7c42fcf3600b9fd8aeb8d5 (patch)
tree69bc89435734ea6dba548157c16a9acae6767377 /drivers/power/ds2782_battery.c
parent84d7b768748943db2bb658b43931fdab04c224cc (diff)
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/ds2782_battery.c')
-rw-r--r--drivers/power/ds2782_battery.c69
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 @@
7 * 7 *
8 * DS2786 added by Yulia Vilensky <vilensky@compulab.co.il> 8 * DS2786 added by Yulia Vilensky <vilensky@compulab.co.il>
9 * 9 *
10 * UEvent sending added by Evgeny Romanov <romanov@neurosoft.ru>
11 *
10 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 13 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. 14 * published by the Free Software Foundation.
@@ -19,6 +21,7 @@
19#include <linux/errno.h> 21#include <linux/errno.h>
20#include <linux/swab.h> 22#include <linux/swab.h>
21#include <linux/i2c.h> 23#include <linux/i2c.h>
24#include <linux/delay.h>
22#include <linux/idr.h> 25#include <linux/idr.h>
23#include <linux/power_supply.h> 26#include <linux/power_supply.h>
24#include <linux/slab.h> 27#include <linux/slab.h>
@@ -40,6 +43,8 @@
40 43
41#define DS2786_CURRENT_UNITS 25 44#define DS2786_CURRENT_UNITS 25
42 45
46#define DS278x_DELAY 1000
47
43struct ds278x_info; 48struct ds278x_info;
44 49
45struct ds278x_battery_ops { 50struct ds278x_battery_ops {
@@ -54,8 +59,11 @@ struct ds278x_info {
54 struct i2c_client *client; 59 struct i2c_client *client;
55 struct power_supply battery; 60 struct power_supply battery;
56 struct ds278x_battery_ops *ops; 61 struct ds278x_battery_ops *ops;
62 struct delayed_work bat_work;
57 int id; 63 int id;
58 int rsns; 64 int rsns;
65 int capacity;
66 int status; /* State Of Charge */
59}; 67};
60 68
61static DEFINE_IDR(battery_id); 69static DEFINE_IDR(battery_id);
@@ -220,6 +228,8 @@ static int ds278x_get_status(struct ds278x_info *info, int *status)
220 if (err) 228 if (err)
221 return err; 229 return err;
222 230
231 info->capacity = capacity;
232
223 if (capacity == 100) 233 if (capacity == 100)
224 *status = POWER_SUPPLY_STATUS_FULL; 234 *status = POWER_SUPPLY_STATUS_FULL;
225 else if (current_uA == 0) 235 else if (current_uA == 0)
@@ -267,6 +277,27 @@ static int ds278x_battery_get_property(struct power_supply *psy,
267 return ret; 277 return ret;
268} 278}
269 279
280static void ds278x_bat_update(struct ds278x_info *info)
281{
282 int old_status = info->status;
283 int old_capacity = info->capacity;
284
285 ds278x_get_status(info, &info->status);
286
287 if ((old_status != info->status) || (old_capacity != info->capacity))
288 power_supply_changed(&info->battery);
289}
290
291static void ds278x_bat_work(struct work_struct *work)
292{
293 struct ds278x_info *info;
294
295 info = container_of(work, struct ds278x_info, bat_work.work);
296 ds278x_bat_update(info);
297
298 schedule_delayed_work(&info->bat_work, DS278x_DELAY);
299}
300
270static enum power_supply_property ds278x_battery_props[] = { 301static enum power_supply_property ds278x_battery_props[] = {
271 POWER_SUPPLY_PROP_STATUS, 302 POWER_SUPPLY_PROP_STATUS,
272 POWER_SUPPLY_PROP_CAPACITY, 303 POWER_SUPPLY_PROP_CAPACITY,
@@ -295,10 +326,39 @@ static int ds278x_battery_remove(struct i2c_client *client)
295 idr_remove(&battery_id, info->id); 326 idr_remove(&battery_id, info->id);
296 mutex_unlock(&battery_lock); 327 mutex_unlock(&battery_lock);
297 328
329 cancel_delayed_work(&info->bat_work);
330
298 kfree(info); 331 kfree(info);
299 return 0; 332 return 0;
300} 333}
301 334
335#ifdef CONFIG_PM
336
337static int ds278x_suspend(struct i2c_client *client,
338 pm_message_t state)
339{
340 struct ds278x_info *info = i2c_get_clientdata(client);
341
342 cancel_delayed_work(&info->bat_work);
343 return 0;
344}
345
346static int ds278x_resume(struct i2c_client *client)
347{
348 struct ds278x_info *info = i2c_get_clientdata(client);
349
350 schedule_delayed_work(&info->bat_work, DS278x_DELAY);
351 return 0;
352}
353
354#else
355
356#define ds278x_suspend NULL
357#define ds278x_resume NULL
358
359#endif /* CONFIG_PM */
360
361
302enum ds278x_num_id { 362enum ds278x_num_id {
303 DS2782 = 0, 363 DS2782 = 0,
304 DS2786, 364 DS2786,
@@ -368,10 +428,17 @@ static int ds278x_battery_probe(struct i2c_client *client,
368 info->ops = &ds278x_ops[id->driver_data]; 428 info->ops = &ds278x_ops[id->driver_data];
369 ds278x_power_supply_init(&info->battery); 429 ds278x_power_supply_init(&info->battery);
370 430
431 info->capacity = 100;
432 info->status = POWER_SUPPLY_STATUS_FULL;
433
434 INIT_DELAYED_WORK(&info->bat_work, ds278x_bat_work);
435
371 ret = power_supply_register(&client->dev, &info->battery); 436 ret = power_supply_register(&client->dev, &info->battery);
372 if (ret) { 437 if (ret) {
373 dev_err(&client->dev, "failed to register battery\n"); 438 dev_err(&client->dev, "failed to register battery\n");
374 goto fail_register; 439 goto fail_register;
440 } else {
441 schedule_delayed_work(&info->bat_work, DS278x_DELAY);
375 } 442 }
376 443
377 return 0; 444 return 0;
@@ -401,6 +468,8 @@ static struct i2c_driver ds278x_battery_driver = {
401 }, 468 },
402 .probe = ds278x_battery_probe, 469 .probe = ds278x_battery_probe,
403 .remove = ds278x_battery_remove, 470 .remove = ds278x_battery_remove,
471 .suspend = ds278x_suspend,
472 .resume = ds278x_resume,
404 .id_table = ds278x_id, 473 .id_table = ds278x_id,
405}; 474};
406module_i2c_driver(ds278x_battery_driver); 475module_i2c_driver(ds278x_battery_driver);