From d385376f0d75fdbeed8041ed6baf5cb4a1578ffb Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Fri, 5 Oct 2007 01:05:00 +0400 Subject: [PATCH] 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 --- drivers/power/apm_power.c | 57 ++++++++++++++++++++++++++++++++------- 1 file 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) -- 2.39.2