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