From ec22388dfefaf8eda07d12284b8f946d3c6eb148 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 26 Jul 2009 18:00:29 +0400 Subject: gta01_battery: generalise the driver, add capacity estimation Check if machine-specific hooks exist before calling, this allows to use this driver with gta02 or any other device that is able to provide battery voltage readings. Report an estimate of capacity percentage left, based on discharge curves. Strictly speaking, this is a violation of power_supply class specs but since this is the only driver for dumb batteries and userspace lacks any library to do the estimation itself, we have to stuff it here. Please keep in mind that this estimation is by no means accurate, usually cell phones have only 5 bars to represent charge status. Credit goes to Joerg Reisenweber and SpeedEvil for helping with gathering and analysing the data. Signed-off-by: Paul Fertser --- drivers/power/gta01_battery.c | 54 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/drivers/power/gta01_battery.c b/drivers/power/gta01_battery.c index 5b1a6c9b966..3c7c49777b0 100644 --- a/drivers/power/gta01_battery.c +++ b/drivers/power/gta01_battery.c @@ -23,8 +23,35 @@ static enum power_supply_property gta01_bat_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CAPACITY, }; +static int gta01_bat_voltscale(int volt) +{ + /* This table is suggested by SpeedEvil based on analysis of + * experimental data */ + static const int lut[][2] = { + { 4120, 100 }, + { 3900, 60 }, + { 3740, 25 }, + { 3600, 5 }, + { 3000, 0 } }; + int i, res = 0; + + if (volt > lut[0][0]) + res = lut[0][1]; + else + for (i = 0; lut[i][1]; i++) { + if (volt <= lut[i][0] && volt >= lut[i+1][0]) { + res = lut[i][1] - (lut[i][0]-volt)* + (lut[i][1]-lut[i+1][1])/ + (lut[i][0]-lut[i+1][0]); + break; + } + } + return res; +} + static int gta01_bat_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -33,20 +60,37 @@ static int gta01_bat_get_property(struct power_supply *psy, switch(psp) { case POWER_SUPPLY_PROP_STATUS: - if (bat->pdata->get_charging_status()) - val->intval = POWER_SUPPLY_STATUS_CHARGING; + if (bat->pdata->get_charging_status) + if (bat->pdata->get_charging_status()) + val->intval = POWER_SUPPLY_STATUS_CHARGING; + else + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; else - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = bat->pdata->get_voltage(); + if (bat->pdata->get_voltage) + val->intval = bat->pdata->get_voltage(); + else + val->intval = 0; break; case POWER_SUPPLY_PROP_CURRENT_NOW: - val->intval = bat->pdata->get_current(); + if (bat->pdata->get_current) + val->intval = bat->pdata->get_current(); + else + val->intval = 0; break; case POWER_SUPPLY_PROP_PRESENT: val->intval = 1; /* You must never run GTA01 without battery. */ break; + case POWER_SUPPLY_PROP_CAPACITY: + if (bat->pdata->get_voltage) + val->intval = gta01_bat_voltscale( + bat->pdata->get_voltage()/1000); + else + val->intval = 0; + break; + default: return -EINVAL; } -- cgit v1.2.3