aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/apm_power.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/apm_power.c')
-rw-r--r--drivers/power/apm_power.c116
1 files changed, 68 insertions, 48 deletions
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c
index bbf3ee10da04..7e29b90a4f63 100644
--- a/drivers/power/apm_power.c
+++ b/drivers/power/apm_power.c
@@ -13,6 +13,7 @@
13#include <linux/power_supply.h> 13#include <linux/power_supply.h>
14#include <linux/apm-emulation.h> 14#include <linux/apm-emulation.h>
15 15
16static DEFINE_MUTEX(apm_mutex);
16#define PSY_PROP(psy, prop, val) psy->get_property(psy, \ 17#define PSY_PROP(psy, prop, val) psy->get_property(psy, \
17 POWER_SUPPLY_PROP_##prop, val) 18 POWER_SUPPLY_PROP_##prop, val)
18 19
@@ -23,67 +24,86 @@
23 24
24static struct power_supply *main_battery; 25static struct power_supply *main_battery;
25 26
26static void find_main_battery(void) 27struct find_bat_param {
27{ 28 struct power_supply *main;
28 struct device *dev; 29 struct power_supply *bat;
29 struct power_supply *bat = NULL; 30 struct power_supply *max_charge_bat;
30 struct power_supply *max_charge_bat = NULL; 31 struct power_supply *max_energy_bat;
31 struct power_supply *max_energy_bat = NULL;
32 union power_supply_propval full; 32 union power_supply_propval full;
33 int max_charge = 0; 33 int max_charge;
34 int max_energy = 0; 34 int max_energy;
35};
35 36
36 main_battery = NULL; 37static int __find_main_battery(struct device *dev, void *data)
38{
39 struct find_bat_param *bp = (struct find_bat_param *)data;
37 40
38 list_for_each_entry(dev, &power_supply_class->devices, node) { 41 bp->bat = dev_get_drvdata(dev);
39 bat = dev_get_drvdata(dev);
40 42
41 if (bat->use_for_apm) { 43 if (bp->bat->use_for_apm) {
42 /* nice, we explicitly asked to report this battery. */ 44 /* nice, we explicitly asked to report this battery. */
43 main_battery = bat; 45 bp->main = bp->bat;
44 return; 46 return 1;
45 } 47 }
46 48
47 if (!PSY_PROP(bat, CHARGE_FULL_DESIGN, &full) || 49 if (!PSY_PROP(bp->bat, CHARGE_FULL_DESIGN, &bp->full) ||
48 !PSY_PROP(bat, CHARGE_FULL, &full)) { 50 !PSY_PROP(bp->bat, CHARGE_FULL, &bp->full)) {
49 if (full.intval > max_charge) { 51 if (bp->full.intval > bp->max_charge) {
50 max_charge_bat = bat; 52 bp->max_charge_bat = bp->bat;
51 max_charge = full.intval; 53 bp->max_charge = bp->full.intval;
52 } 54 }
53 } else if (!PSY_PROP(bat, ENERGY_FULL_DESIGN, &full) || 55 } else if (!PSY_PROP(bp->bat, ENERGY_FULL_DESIGN, &bp->full) ||
54 !PSY_PROP(bat, ENERGY_FULL, &full)) { 56 !PSY_PROP(bp->bat, ENERGY_FULL, &bp->full)) {
55 if (full.intval > max_energy) { 57 if (bp->full.intval > bp->max_energy) {
56 max_energy_bat = bat; 58 bp->max_energy_bat = bp->bat;
57 max_energy = full.intval; 59 bp->max_energy = bp->full.intval;
58 }
59 } 60 }
60 } 61 }
62 return 0;
63}
64
65static void find_main_battery(void)
66{
67 struct find_bat_param bp;
68 int error;
69
70 memset(&bp, 0, sizeof(struct find_bat_param));
71 main_battery = NULL;
72 bp.main = main_battery;
73
74 error = class_for_each_device(power_supply_class, &bp,
75 __find_main_battery);
76 if (error) {
77 main_battery = bp.main;
78 return;
79 }
61 80
62 if ((max_energy_bat && max_charge_bat) && 81 if ((bp.max_energy_bat && bp.max_charge_bat) &&
63 (max_energy_bat != max_charge_bat)) { 82 (bp.max_energy_bat != bp.max_charge_bat)) {
64 /* try guess battery with more capacity */ 83 /* try guess battery with more capacity */
65 if (!PSY_PROP(max_charge_bat, VOLTAGE_MAX_DESIGN, &full)) { 84 if (!PSY_PROP(bp.max_charge_bat, VOLTAGE_MAX_DESIGN,
66 if (max_energy > max_charge * full.intval) 85 &bp.full)) {
67 main_battery = max_energy_bat; 86 if (bp.max_energy > bp.max_charge * bp.full.intval)
87 main_battery = bp.max_energy_bat;
68 else 88 else
69 main_battery = max_charge_bat; 89 main_battery = bp.max_charge_bat;
70 } else if (!PSY_PROP(max_energy_bat, VOLTAGE_MAX_DESIGN, 90 } else if (!PSY_PROP(bp.max_energy_bat, VOLTAGE_MAX_DESIGN,
71 &full)) { 91 &bp.full)) {
72 if (max_charge > max_energy / full.intval) 92 if (bp.max_charge > bp.max_energy / bp.full.intval)
73 main_battery = max_charge_bat; 93 main_battery = bp.max_charge_bat;
74 else 94 else
75 main_battery = max_energy_bat; 95 main_battery = bp.max_energy_bat;
76 } else { 96 } else {
77 /* give up, choice any */ 97 /* give up, choice any */
78 main_battery = max_energy_bat; 98 main_battery = bp.max_energy_bat;
79 } 99 }
80 } else if (max_charge_bat) { 100 } else if (bp.max_charge_bat) {
81 main_battery = max_charge_bat; 101 main_battery = bp.max_charge_bat;
82 } else if (max_energy_bat) { 102 } else if (bp.max_energy_bat) {
83 main_battery = max_energy_bat; 103 main_battery = bp.max_energy_bat;
84 } else { 104 } else {
85 /* give up, try the last if any */ 105 /* give up, try the last if any */
86 main_battery = bat; 106 main_battery = bp.bat;
87 } 107 }
88} 108}
89 109
@@ -207,10 +227,10 @@ static void apm_battery_apm_get_power_status(struct apm_power_info *info)
207 union power_supply_propval status; 227 union power_supply_propval status;
208 union power_supply_propval capacity, time_to_full, time_to_empty; 228 union power_supply_propval capacity, time_to_full, time_to_empty;
209 229
210 down(&power_supply_class->sem); 230 mutex_lock(&apm_mutex);
211 find_main_battery(); 231 find_main_battery();
212 if (!main_battery) { 232 if (!main_battery) {
213 up(&power_supply_class->sem); 233 mutex_unlock(&apm_mutex);
214 return; 234 return;
215 } 235 }
216 236
@@ -278,7 +298,7 @@ static void apm_battery_apm_get_power_status(struct apm_power_info *info)
278 } 298 }
279 } 299 }
280 300
281 up(&power_supply_class->sem); 301 mutex_unlock(&apm_mutex);
282} 302}
283 303
284static int __init apm_battery_init(void) 304static int __init apm_battery_init(void)