Commit dffd28a1 authored by Dmitry Baryshkov's avatar Dmitry Baryshkov Committed by Anton Vorontsov

apm_power: support using VOLTAGE_* properties for apm calculations

It's pretty dummy, but useful for batteries for which we can only
get voltages.
Signed-off-by: default avatarDmitry Baryshkov <dbaryshkov@gmail.com>
Signed-off-by: default avatarAnton Vorontsov <cbou@mail.ru>
parent 8f8e9b38
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include <linux/power_supply.h> #include <linux/power_supply.h>
#include <linux/apm-emulation.h> #include <linux/apm-emulation.h>
static DEFINE_MUTEX(apm_mutex);
#define PSY_PROP(psy, prop, val) psy->get_property(psy, \ #define PSY_PROP(psy, prop, val) psy->get_property(psy, \
POWER_SUPPLY_PROP_##prop, val) POWER_SUPPLY_PROP_##prop, val)
...@@ -22,8 +22,15 @@ static DEFINE_MUTEX(apm_mutex); ...@@ -22,8 +22,15 @@ static DEFINE_MUTEX(apm_mutex);
#define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val) #define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val)
static DEFINE_MUTEX(apm_mutex);
static struct power_supply *main_battery; static struct power_supply *main_battery;
enum apm_source {
SOURCE_ENERGY,
SOURCE_CHARGE,
SOURCE_VOLTAGE,
};
struct find_bat_param { struct find_bat_param {
struct power_supply *main; struct power_supply *main;
struct power_supply *bat; struct power_supply *bat;
...@@ -107,7 +114,7 @@ static void find_main_battery(void) ...@@ -107,7 +114,7 @@ static void find_main_battery(void)
} }
} }
static int calculate_time(int status, int using_charge) static int do_calculate_time(int status, enum apm_source source)
{ {
union power_supply_propval full; union power_supply_propval full;
union power_supply_propval empty; union power_supply_propval empty;
...@@ -126,20 +133,34 @@ static int calculate_time(int status, int using_charge) ...@@ -126,20 +133,34 @@ static int calculate_time(int status, int using_charge)
return -1; return -1;
} }
if (using_charge) { switch (source) {
case SOURCE_CHARGE:
full_prop = POWER_SUPPLY_PROP_CHARGE_FULL; full_prop = POWER_SUPPLY_PROP_CHARGE_FULL;
full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN;
empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
cur_avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG; cur_avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG;
cur_now_prop = POWER_SUPPLY_PROP_CHARGE_NOW; cur_now_prop = POWER_SUPPLY_PROP_CHARGE_NOW;
} else { break;
case SOURCE_ENERGY:
full_prop = POWER_SUPPLY_PROP_ENERGY_FULL; full_prop = POWER_SUPPLY_PROP_ENERGY_FULL;
full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN;
empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY; empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY;
empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
cur_avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; cur_avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG;
cur_now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; cur_now_prop = POWER_SUPPLY_PROP_ENERGY_NOW;
break;
case SOURCE_VOLTAGE:
full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX;
full_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN;
empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN;
empty_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN;
cur_avg_prop = POWER_SUPPLY_PROP_VOLTAGE_AVG;
cur_now_prop = POWER_SUPPLY_PROP_VOLTAGE_NOW;
break;
default:
printk(KERN_ERR "Unsupported source: %d\n", source);
return -1;
} }
if (_MPSY_PROP(full_prop, &full)) { if (_MPSY_PROP(full_prop, &full)) {
...@@ -166,7 +187,26 @@ static int calculate_time(int status, int using_charge) ...@@ -166,7 +187,26 @@ static int calculate_time(int status, int using_charge)
return -((cur.intval - empty.intval) * 60L) / I.intval; return -((cur.intval - empty.intval) * 60L) / I.intval;
} }
static int calculate_capacity(int using_charge) static int calculate_time(int status)
{
int time;
time = do_calculate_time(status, SOURCE_ENERGY);
if (time != -1)
return time;
time = do_calculate_time(status, SOURCE_CHARGE);
if (time != -1)
return time;
time = do_calculate_time(status, SOURCE_VOLTAGE);
if (time != -1)
return time;
return -1;
}
static int calculate_capacity(enum apm_source source)
{ {
enum power_supply_property full_prop, empty_prop; enum power_supply_property full_prop, empty_prop;
enum power_supply_property full_design_prop, empty_design_prop; enum power_supply_property full_design_prop, empty_design_prop;
...@@ -174,20 +214,33 @@ static int calculate_capacity(int using_charge) ...@@ -174,20 +214,33 @@ static int calculate_capacity(int using_charge)
union power_supply_propval empty, full, cur; union power_supply_propval empty, full, cur;
int ret; int ret;
if (using_charge) { switch (source) {
case SOURCE_CHARGE:
full_prop = POWER_SUPPLY_PROP_CHARGE_FULL; full_prop = POWER_SUPPLY_PROP_CHARGE_FULL;
empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY; empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN; full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN;
empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN; empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN;
now_prop = POWER_SUPPLY_PROP_CHARGE_NOW; now_prop = POWER_SUPPLY_PROP_CHARGE_NOW;
avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG; avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG;
} else { break;
case SOURCE_ENERGY:
full_prop = POWER_SUPPLY_PROP_ENERGY_FULL; full_prop = POWER_SUPPLY_PROP_ENERGY_FULL;
empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY; empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY;
full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN; full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN;
empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN;
now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; now_prop = POWER_SUPPLY_PROP_ENERGY_NOW;
avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG;
case SOURCE_VOLTAGE:
full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX;
empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN;
full_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN;
empty_design_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN;
now_prop = POWER_SUPPLY_PROP_VOLTAGE_NOW;
avg_prop = POWER_SUPPLY_PROP_VOLTAGE_AVG;
break;
default:
printk(KERN_ERR "Unsupported source: %d\n", source);
return -1;
} }
if (_MPSY_PROP(full_prop, &full)) { if (_MPSY_PROP(full_prop, &full)) {
...@@ -254,10 +307,12 @@ static void apm_battery_apm_get_power_status(struct apm_power_info *info) ...@@ -254,10 +307,12 @@ static void apm_battery_apm_get_power_status(struct apm_power_info *info)
info->battery_life = capacity.intval; info->battery_life = capacity.intval;
} else { } else {
/* try calculate using energy */ /* try calculate using energy */
info->battery_life = calculate_capacity(0); info->battery_life = calculate_capacity(SOURCE_ENERGY);
/* if failed try calculate using charge instead */ /* if failed try calculate using charge instead */
if (info->battery_life == -1) if (info->battery_life == -1)
info->battery_life = calculate_capacity(1); info->battery_life = calculate_capacity(SOURCE_CHARGE);
if (info->battery_life == -1)
info->battery_life = calculate_capacity(SOURCE_VOLTAGE);
} }
/* charging status */ /* charging status */
...@@ -280,22 +335,16 @@ static void apm_battery_apm_get_power_status(struct apm_power_info *info) ...@@ -280,22 +335,16 @@ static void apm_battery_apm_get_power_status(struct apm_power_info *info)
if (status.intval == POWER_SUPPLY_STATUS_CHARGING) { if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
if (!MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full) || if (!MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full) ||
!MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full)) { !MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full))
info->time = time_to_full.intval / 60; info->time = time_to_full.intval / 60;
} else { else
info->time = calculate_time(status.intval, 0); info->time = calculate_time(status.intval);
if (info->time == -1)
info->time = calculate_time(status.intval, 1);
}
} else { } else {
if (!MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty) || if (!MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty) ||
!MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty)) { !MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty))
info->time = time_to_empty.intval / 60; info->time = time_to_empty.intval / 60;
} else { else
info->time = calculate_time(status.intval, 0); info->time = calculate_time(status.intval);
if (info->time == -1)
info->time = calculate_time(status.intval, 1);
}
} }
mutex_unlock(&apm_mutex); mutex_unlock(&apm_mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment