diff options
Diffstat (limited to 'drivers/power/apm_power.c')
-rw-r--r-- | drivers/power/apm_power.c | 94 |
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 | ||
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,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 | ||
169 | static int calculate_capacity(int using_charge) | 193 | static 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 | |||
212 | static 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); |