diff options
Diffstat (limited to 'drivers/power/apm_power.c')
-rw-r--r-- | drivers/power/apm_power.c | 91 |
1 files changed, 70 insertions, 21 deletions
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c index 7e29b90a4f63..a832a9a05c66 100644 --- a/drivers/power/apm_power.c +++ b/drivers/power/apm_power.c | |||
@@ -13,7 +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 | ||
16 | static DEFINE_MUTEX(apm_mutex); | 16 | |
17 | #define PSY_PROP(psy, prop, val) psy->get_property(psy, \ | 17 | #define PSY_PROP(psy, prop, val) psy->get_property(psy, \ |
18 | POWER_SUPPLY_PROP_##prop, val) | 18 | POWER_SUPPLY_PROP_##prop, val) |
19 | 19 | ||
@@ -22,8 +22,15 @@ static DEFINE_MUTEX(apm_mutex); | |||
22 | 22 | ||
23 | #define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val) | 23 | #define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val) |
24 | 24 | ||
25 | static DEFINE_MUTEX(apm_mutex); | ||
25 | static struct power_supply *main_battery; | 26 | static struct power_supply *main_battery; |
26 | 27 | ||
28 | enum apm_source { | ||
29 | SOURCE_ENERGY, | ||
30 | SOURCE_CHARGE, | ||
31 | SOURCE_VOLTAGE, | ||
32 | }; | ||
33 | |||
27 | struct find_bat_param { | 34 | struct find_bat_param { |
28 | struct power_supply *main; | 35 | struct power_supply *main; |
29 | struct power_supply *bat; | 36 | struct power_supply *bat; |
@@ -107,7 +114,7 @@ static void find_main_battery(void) | |||
107 | } | 114 | } |
108 | } | 115 | } |
109 | 116 | ||
110 | static int calculate_time(int status, int using_charge) | 117 | static int do_calculate_time(int status, enum apm_source source) |
111 | { | 118 | { |
112 | union power_supply_propval full; | 119 | union power_supply_propval full; |
113 | union power_supply_propval empty; | 120 | union power_supply_propval empty; |
@@ -126,20 +133,34 @@ static int calculate_time(int status, int using_charge) | |||
126 | return -1; | 133 | return -1; |
127 | } | 134 | } |
128 | 135 | ||
129 | if (using_charge) { | 136 | switch (source) { |
137 | case SOURCE_CHARGE: | ||
130 | full_prop = POWER_SUPPLY_PROP_CHARGE_FULL; | 138 | full_prop = POWER_SUPPLY_PROP_CHARGE_FULL; |
131 | full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; | 139 | full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; |
132 | empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; | 140 | empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; |
133 | empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; | 141 | empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; |
134 | cur_avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG; | 142 | cur_avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG; |
135 | cur_now_prop = POWER_SUPPLY_PROP_CHARGE_NOW; | 143 | cur_now_prop = POWER_SUPPLY_PROP_CHARGE_NOW; |
136 | } else { | 144 | break; |
145 | case SOURCE_ENERGY: | ||
137 | full_prop = POWER_SUPPLY_PROP_ENERGY_FULL; | 146 | full_prop = POWER_SUPPLY_PROP_ENERGY_FULL; |
138 | full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; | 147 | full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; |
139 | empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY; | 148 | empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY; |
140 | empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; | 149 | empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; |
141 | cur_avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; | 150 | cur_avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; |
142 | cur_now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; | 151 | cur_now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; |
152 | break; | ||
153 | case SOURCE_VOLTAGE: | ||
154 | full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; | ||
155 | full_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN; | ||
156 | empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; | ||
157 | empty_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN; | ||
158 | cur_avg_prop = POWER_SUPPLY_PROP_VOLTAGE_AVG; | ||
159 | cur_now_prop = POWER_SUPPLY_PROP_VOLTAGE_NOW; | ||
160 | break; | ||
161 | default: | ||
162 | printk(KERN_ERR "Unsupported source: %d\n", source); | ||
163 | return -1; | ||
143 | } | 164 | } |
144 | 165 | ||
145 | if (_MPSY_PROP(full_prop, &full)) { | 166 | if (_MPSY_PROP(full_prop, &full)) { |
@@ -166,7 +187,26 @@ static int calculate_time(int status, int using_charge) | |||
166 | return -((cur.intval - empty.intval) * 60L) / I.intval; | 187 | return -((cur.intval - empty.intval) * 60L) / I.intval; |
167 | } | 188 | } |
168 | 189 | ||
169 | static int calculate_capacity(int using_charge) | 190 | static int calculate_time(int status) |
191 | { | ||
192 | int time; | ||
193 | |||
194 | time = do_calculate_time(status, SOURCE_ENERGY); | ||
195 | if (time != -1) | ||
196 | return time; | ||
197 | |||
198 | time = do_calculate_time(status, SOURCE_CHARGE); | ||
199 | if (time != -1) | ||
200 | return time; | ||
201 | |||
202 | time = do_calculate_time(status, SOURCE_VOLTAGE); | ||
203 | if (time != -1) | ||
204 | return time; | ||
205 | |||
206 | return -1; | ||
207 | } | ||
208 | |||
209 | static int calculate_capacity(enum apm_source source) | ||
170 | { | 210 | { |
171 | enum power_supply_property full_prop, empty_prop; | 211 | enum power_supply_property full_prop, empty_prop; |
172 | enum power_supply_property full_design_prop, empty_design_prop; | 212 | enum power_supply_property full_design_prop, empty_design_prop; |
@@ -174,20 +214,33 @@ static int calculate_capacity(int using_charge) | |||
174 | union power_supply_propval empty, full, cur; | 214 | union power_supply_propval empty, full, cur; |
175 | int ret; | 215 | int ret; |
176 | 216 | ||
177 | if (using_charge) { | 217 | switch (source) { |
218 | case SOURCE_CHARGE: | ||
178 | full_prop = POWER_SUPPLY_PROP_CHARGE_FULL; | 219 | full_prop = POWER_SUPPLY_PROP_CHARGE_FULL; |
179 | empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; | 220 | empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; |
180 | full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; | 221 | full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; |
181 | empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN; | 222 | empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN; |
182 | now_prop = POWER_SUPPLY_PROP_CHARGE_NOW; | 223 | now_prop = POWER_SUPPLY_PROP_CHARGE_NOW; |
183 | avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG; | 224 | avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG; |
184 | } else { | 225 | break; |
226 | case SOURCE_ENERGY: | ||
185 | full_prop = POWER_SUPPLY_PROP_ENERGY_FULL; | 227 | full_prop = POWER_SUPPLY_PROP_ENERGY_FULL; |
186 | empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY; | 228 | empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY; |
187 | full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; | 229 | full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; |
188 | empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; | 230 | empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; |
189 | now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; | 231 | now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; |
190 | avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; | 232 | avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; |
233 | case SOURCE_VOLTAGE: | ||
234 | full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; | ||
235 | empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; | ||
236 | full_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN; | ||
237 | empty_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN; | ||
238 | now_prop = POWER_SUPPLY_PROP_VOLTAGE_NOW; | ||
239 | avg_prop = POWER_SUPPLY_PROP_VOLTAGE_AVG; | ||
240 | break; | ||
241 | default: | ||
242 | printk(KERN_ERR "Unsupported source: %d\n", source); | ||
243 | return -1; | ||
191 | } | 244 | } |
192 | 245 | ||
193 | if (_MPSY_PROP(full_prop, &full)) { | 246 | if (_MPSY_PROP(full_prop, &full)) { |
@@ -254,10 +307,12 @@ static void apm_battery_apm_get_power_status(struct apm_power_info *info) | |||
254 | info->battery_life = capacity.intval; | 307 | info->battery_life = capacity.intval; |
255 | } else { | 308 | } else { |
256 | /* try calculate using energy */ | 309 | /* try calculate using energy */ |
257 | info->battery_life = calculate_capacity(0); | 310 | info->battery_life = calculate_capacity(SOURCE_ENERGY); |
258 | /* if failed try calculate using charge instead */ | 311 | /* if failed try calculate using charge instead */ |
259 | if (info->battery_life == -1) | 312 | if (info->battery_life == -1) |
260 | info->battery_life = calculate_capacity(1); | 313 | info->battery_life = calculate_capacity(SOURCE_CHARGE); |
314 | if (info->battery_life == -1) | ||
315 | info->battery_life = calculate_capacity(SOURCE_VOLTAGE); | ||
261 | } | 316 | } |
262 | 317 | ||
263 | /* charging status */ | 318 | /* charging status */ |
@@ -280,22 +335,16 @@ static void apm_battery_apm_get_power_status(struct apm_power_info *info) | |||
280 | 335 | ||
281 | if (status.intval == POWER_SUPPLY_STATUS_CHARGING) { | 336 | if (status.intval == POWER_SUPPLY_STATUS_CHARGING) { |
282 | if (!MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full) || | 337 | if (!MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full) || |
283 | !MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full)) { | 338 | !MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full)) |
284 | info->time = time_to_full.intval / 60; | 339 | info->time = time_to_full.intval / 60; |
285 | } else { | 340 | else |
286 | info->time = calculate_time(status.intval, 0); | 341 | info->time = calculate_time(status.intval); |
287 | if (info->time == -1) | ||
288 | info->time = calculate_time(status.intval, 1); | ||
289 | } | ||
290 | } else { | 342 | } else { |
291 | if (!MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty) || | 343 | if (!MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty) || |
292 | !MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty)) { | 344 | !MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty)) |
293 | info->time = time_to_empty.intval / 60; | 345 | info->time = time_to_empty.intval / 60; |
294 | } else { | 346 | else |
295 | info->time = calculate_time(status.intval, 0); | 347 | info->time = calculate_time(status.intval); |
296 | if (info->time == -1) | ||
297 | info->time = calculate_time(status.intval, 1); | ||
298 | } | ||
299 | } | 348 | } |
300 | 349 | ||
301 | mutex_unlock(&apm_mutex); | 350 | mutex_unlock(&apm_mutex); |