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.c91
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
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,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
169static int calculate_capacity(int using_charge) 190static 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
209static 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);