diff options
| -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); |
