diff options
author | Anton Vorontsov <cbou@mail.ru> | 2007-10-05 01:05:00 +0400 |
---|---|---|
committer | Anton Vorontsov <cbou@mail.ru> | 2007-10-05 01:05:00 +0400 |
commit | d385376f0d75fdbeed8041ed6baf5cb4a1578ffb (patch) | |
tree | 123182e8e7c8468565d3f1718c7ac1fe4dd65b80 /drivers/power/apm_power.c | |
parent | cd1ebcc0ef620e8e7c5e399bf9e123135e4f24a4 (diff) |
apm_power: improve battery finding algorithm
Prior to this patch, if use_for_apm unspecified, apm_power able
to choice batteries according to their charge only.
This patch adds ability to choice batteries according to their charge,
energy, use_for_apm flag, and fallback to any battery if it failed to
decide.
Patch is mandatory to report Apple PMU batteries through legacy
/proc/apm interface using power supply class.
Signed-off-by: Anton Vorontsov <cbou@mail.ru>
Diffstat (limited to 'drivers/power/apm_power.c')
-rw-r--r-- | drivers/power/apm_power.c | 57 |
1 files changed, 47 insertions, 10 deletions
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c index 32ebfd76722a..3928e7cdddc1 100644 --- a/drivers/power/apm_power.c +++ b/drivers/power/apm_power.c @@ -26,28 +26,65 @@ static struct power_supply *main_battery; static void find_main_battery(void) { struct device *dev; - struct power_supply *bat, *batm; + struct power_supply *bat = NULL; + struct power_supply *max_charge_bat = NULL; + struct power_supply *max_energy_bat = NULL; union power_supply_propval full; int max_charge = 0; + int max_energy = 0; main_battery = NULL; - batm = NULL; + list_for_each_entry(dev, &power_supply_class->devices, node) { bat = dev_get_drvdata(dev); - /* If none of battery devices cantains 'use_for_apm' flag, - choice one with maximum design charge */ - if (!PSY_PROP(bat, CHARGE_FULL_DESIGN, &full)) { + + if (bat->use_for_apm) { + /* nice, we explicitly asked to report this battery. */ + main_battery = bat; + return; + } + + if (!PSY_PROP(bat, CHARGE_FULL_DESIGN, &full) || + !PSY_PROP(bat, CHARGE_FULL, &full)) { if (full.intval > max_charge) { - batm = bat; + max_charge_bat = bat; max_charge = full.intval; } + } else if (!PSY_PROP(bat, ENERGY_FULL_DESIGN, &full) || + !PSY_PROP(bat, ENERGY_FULL, &full)) { + if (full.intval > max_energy) { + max_energy_bat = bat; + max_energy = full.intval; + } } + } - if (bat->use_for_apm) - main_battery = bat; + if ((max_energy_bat && max_charge_bat) && + (max_energy_bat != max_charge_bat)) { + /* try guess battery with more capacity */ + if (!PSY_PROP(max_charge_bat, VOLTAGE_MAX_DESIGN, &full)) { + if (max_energy > max_charge * full.intval) + main_battery = max_energy_bat; + else + main_battery = max_charge_bat; + } else if (!PSY_PROP(max_energy_bat, VOLTAGE_MAX_DESIGN, + &full)) { + if (max_charge > max_energy / full.intval) + main_battery = max_charge_bat; + else + main_battery = max_energy_bat; + } else { + /* give up, choice any */ + main_battery = max_energy_bat; + } + } else if (max_charge_bat) { + main_battery = max_charge_bat; + } else if (max_energy_bat) { + main_battery = max_energy_bat; + } else { + /* give up, try the last if any */ + main_battery = bat; } - if (!main_battery) - main_battery = batm; } static int calculate_time(int status) |