0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/apm-emulation.h>
0011 #include <linux/adb.h>
0012 #include <linux/pmu.h>
0013
0014 #define APM_CRITICAL 10
0015 #define APM_LOW 30
0016
0017 static void pmu_apm_get_power_status(struct apm_power_info *info)
0018 {
0019 int percentage = -1;
0020 int batteries = 0;
0021 int time_units = -1;
0022 int real_count = 0;
0023 int i;
0024 char charging = 0;
0025 long charge = -1;
0026 long amperage = 0;
0027 unsigned long btype = 0;
0028
0029 info->battery_status = APM_BATTERY_STATUS_UNKNOWN;
0030 info->battery_flag = APM_BATTERY_FLAG_UNKNOWN;
0031 info->units = APM_UNITS_MINS;
0032
0033 if (pmu_power_flags & PMU_PWR_AC_PRESENT)
0034 info->ac_line_status = APM_AC_ONLINE;
0035 else
0036 info->ac_line_status = APM_AC_OFFLINE;
0037
0038 for (i=0; i<pmu_battery_count; i++) {
0039 if (pmu_batteries[i].flags & PMU_BATT_PRESENT) {
0040 batteries++;
0041 if (percentage < 0)
0042 percentage = 0;
0043 if (charge < 0)
0044 charge = 0;
0045 percentage += (pmu_batteries[i].charge * 100) /
0046 pmu_batteries[i].max_charge;
0047 charge += pmu_batteries[i].charge;
0048 amperage += pmu_batteries[i].amperage;
0049 if (btype == 0)
0050 btype = (pmu_batteries[i].flags & PMU_BATT_TYPE_MASK);
0051 real_count++;
0052 if ((pmu_batteries[i].flags & PMU_BATT_CHARGING))
0053 charging++;
0054 }
0055 }
0056 if (batteries == 0)
0057 info->ac_line_status = APM_AC_ONLINE;
0058
0059 if (real_count) {
0060 if (amperage < 0) {
0061 if (btype == PMU_BATT_TYPE_SMART)
0062 time_units = (charge * 59) / (amperage * -1);
0063 else
0064 time_units = (charge * 16440) / (amperage * -60);
0065 }
0066 percentage /= real_count;
0067 if (charging > 0) {
0068 info->battery_status = APM_BATTERY_STATUS_CHARGING;
0069 info->battery_flag = APM_BATTERY_FLAG_CHARGING;
0070 } else if (percentage <= APM_CRITICAL) {
0071 info->battery_status = APM_BATTERY_STATUS_CRITICAL;
0072 info->battery_flag = APM_BATTERY_FLAG_CRITICAL;
0073 } else if (percentage <= APM_LOW) {
0074 info->battery_status = APM_BATTERY_STATUS_LOW;
0075 info->battery_flag = APM_BATTERY_FLAG_LOW;
0076 } else {
0077 info->battery_status = APM_BATTERY_STATUS_HIGH;
0078 info->battery_flag = APM_BATTERY_FLAG_HIGH;
0079 }
0080 }
0081
0082 info->battery_life = percentage;
0083 info->time = time_units;
0084 }
0085
0086 static int __init apm_emu_init(void)
0087 {
0088 apm_get_power_status = pmu_apm_get_power_status;
0089
0090 printk(KERN_INFO "apm_emu: PMU APM Emulation initialized.\n");
0091
0092 return 0;
0093 }
0094
0095 static void __exit apm_emu_exit(void)
0096 {
0097 if (apm_get_power_status == pmu_apm_get_power_status)
0098 apm_get_power_status = NULL;
0099
0100 printk(KERN_INFO "apm_emu: PMU APM Emulation removed.\n");
0101 }
0102
0103 module_init(apm_emu_init);
0104 module_exit(apm_emu_exit);
0105
0106 MODULE_AUTHOR("Benjamin Herrenschmidt");
0107 MODULE_DESCRIPTION("APM emulation for PowerMac");
0108 MODULE_LICENSE("GPL");