From 61d0b1cffdf685bd83f5b98c6af870b4c57e61c0 Mon Sep 17 00:00:00 2001 From: LeTama Date: Mon, 18 Oct 2010 21:04:05 +0200 Subject: [PATCH 1/4] Revert "htcleo: add yaffs driver in kernel" Options YAFFS_DISABLE_TAGS_ECC and DISABLE_BLOCK_REFRESHING must be set to 'y'. YAFFS_FS as 'y' is still dangerous for non-magldr users This reverts commit 107e05ec286b81ddd971ff908d556b25c082aa44. --- arch/arm/configs/htcleo_defconfig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/htcleo_defconfig b/arch/arm/configs/htcleo_defconfig index ff9e0087..c6697304 100644 --- a/arch/arm/configs/htcleo_defconfig +++ b/arch/arm/configs/htcleo_defconfig @@ -1642,16 +1642,20 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -CONFIG_YAFFS_FS=y +CONFIG_YAFFS_FS=m CONFIG_YAFFS_YAFFS1=y # CONFIG_YAFFS_9BYTE_TAGS is not set # CONFIG_YAFFS_DOES_ECC is not set CONFIG_YAFFS_YAFFS2=y CONFIG_YAFFS_AUTO_YAFFS2=y -# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set +CONFIG_YAFFS_DISABLE_TAGS_ECC=y # CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set # CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y +# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set +CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING=y +# CONFIG_YAFFS_DISABLE_BACKGROUND is not set +CONFIG_YAFFS_XATTR=y # CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set CONFIG_SQUASHFS=y From dc353d939b21a0b679d6aaac699d0e793b99902d Mon Sep 17 00:00:00 2001 From: LeTama Date: Thu, 21 Oct 2010 19:12:21 +0200 Subject: [PATCH 2/4] htcleo: add support for specific acdb file --- arch/arm/mach-msm/qdsp6_1550/q6audio.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-msm/qdsp6_1550/q6audio.c b/arch/arm/mach-msm/qdsp6_1550/q6audio.c index 7dbea42d..df8a64fb 100644 --- a/arch/arm/mach-msm/qdsp6_1550/q6audio.c +++ b/arch/arm/mach-msm/qdsp6_1550/q6audio.c @@ -173,6 +173,7 @@ static char acdb_file[64] = "default.acdb"; static uint32_t tx_acdb = 0; static uint32_t rx_acdb = 0; static int acdb_use_rpc = 0; +static int acdb_use_map = 0; ///////////////////////////////////////////////////////////////////////////////// // helper functions for device parameters @@ -1152,11 +1153,27 @@ static int acdb_init(char *filename) // return -ENODEV; +#ifdef CONFIG_MACH_HTCLEO + pr_info("acdb: trying htcleo.acdb\n"); + if(request_firmware(&fw, "htcleo.acdb", q6_control_device.this_device) < 0) { + pr_info("acdb: load 'htcleo.acdb' failed, trying 'default.acdb'\n"); + acdb_use_map = 0; + if (request_firmware(&fw, filename, q6_control_device.this_device) < 0) { + pr_err("acdb: load 'default.acdb' failed...\n"); + return -ENODEV; + } + } else { + pr_info("acdb: 'htcleo.acdb' found, using translation\n"); + acdb_use_map = 1; + } +#else pr_info("acdb: load '%s'\n", filename); + acd_use_map = 0; if (request_firmware(&fw, filename, q6_control_device.this_device) < 0) { pr_err("acdb: load 'default.acdb' failed...\n"); return -ENODEV; } +#endif db = (void*) fw->data; if (fw->size < sizeof(struct audio_config_database)) { @@ -1364,9 +1381,12 @@ static int acdb_get_config_table(uint32_t device_id, uint32_t sample_rate) int n; printk("table\n"); + // htcleo use custom table with wince values, it must be mapped + if(acdb_use_map) + device_id = map_cad_dev_to_virtual(device_id); db = acdb_data; for (n = 0; n < db->entry_count; n++) - { + { if (db->entry[n].device_id != device_id) continue; if (db->entry[n].sample_rate != sample_rate) From 26386dbf814503474f18f2bc41252a82e622b9f4 Mon Sep 17 00:00:00 2001 From: Markinus Date: Mon, 25 Oct 2010 01:16:35 +0200 Subject: [PATCH 3/4] htcleo: cleanups and fixes for battery and power - Correct cable detection on boot with cable in - Removed battery disabling code, this isn't working with our device - Add Full Battery Calibration, if Battery > 95% and charging <5mA we set it to 100% (fix for nand 100% problems) - Removed some not used code Importand: It's in this step for standard battery only, support in next step. --- arch/arm/mach-msm/board-htcleo-battery.c | 1090 +++++++---------- arch/arm/mach-msm/board-htcleo-power.c | 171 +-- .../include/mach/board-htcleo-battery.h | 102 ++ 3 files changed, 642 insertions(+), 721 deletions(-) create mode 100644 arch/arm/mach-msm/include/mach/board-htcleo-battery.h diff --git a/arch/arm/mach-msm/board-htcleo-battery.c b/arch/arm/mach-msm/board-htcleo-battery.c index 10cb6ec6..20488aa9 100644 --- a/arch/arm/mach-msm/board-htcleo-battery.c +++ b/arch/arm/mach-msm/board-htcleo-battery.c @@ -1,6 +1,6 @@ -/* arch/arm/mach-msm/board-htcleo-battery.c +/* arch/arm/mach-msm/board-htcleo-battery.h * -* Copyright (C) 2010 Cotulla +* Copyright (C) 2010 Markinus * Copyright (C) 2009 HTC Corporation * Copyright (C) 2009 Google, Inc. * @@ -41,7 +41,6 @@ my primary target was to make high quality battery support in Android for HTC LE #include #include -#include #include #include #include @@ -52,121 +51,32 @@ my primary target was to make high quality battery support in Android for HTC LE #include #include #include +#include #include "gpio_chip.h" #include "board-htcleo.h" - -//////////////////////////////////////////////////////////////////////////////////////// - - -#define LEO_BATTERY_CAPACITY 1230 -#define LEO_BATTERY_EMPTY 500 - - -/* Known commands to the DS2784 chip */ -#define W1_DS2784_SWAP 0xAA -#define W1_DS2784_READ_DATA 0x69 -#define W1_DS2784_WRITE_DATA 0x6C -#define W1_DS2784_COPY_DATA 0x48 -#define W1_DS2784_RECALL_DATA 0xB8 -#define W1_DS2784_LOCK 0x6A - -/* Number of valid register addresses */ -#define DS2784_DATA_SIZE 0x80 - -#define DS2784_EEPROM_BLOCK0 0x20 -#define DS2784_ACTIVE_FULL 0x20 -#define DS2784_EEPROM_BLOCK1 0x30 -#define DS2784_RATED_CAPACITY 0x32 -#define DS2784_CURRENT_OFFSET_BIAS 0x33 -#define DS2784_ACTIVE_EMPTY 0x3b - -/** -* The DS2482 registers - there are 3 registers that are addressed by a read -* pointer. The read pointer is set by the last command executed. -* -* To read the data, issue a register read for any address -*/ -#define DS2482_CMD_RESET 0xF0 /* No param */ -#define DS2482_CMD_SET_READ_PTR 0xE1 /* Param: DS2482_PTR_CODE_xxx */ -#define DS2482_CMD_CHANNEL_SELECT 0xC3 -#define DS2482_CMD_WRITE_CONFIG 0xD2 /* Param: Config byte */ -#define DS2482_CMD_1WIRE_RESET 0xB4 /* Param: None */ -#define DS2482_CMD_1WIRE_SINGLE_BIT 0x87 /* Param: Bit byte (bit7) */ -#define DS2482_CMD_1WIRE_WRITE_BYTE 0xA5 /* Param: Data byte */ -#define DS2482_CMD_1WIRE_READ_BYTE 0x96 /* Param: None */ -/* Note to read the byte, Set the ReadPtr to Data then read (any addr) */ -#define DS2482_CMD_1WIRE_TRIPLET 0x78 /* Param: Dir byte (bit7) */ - -/* Values for DS2482_CMD_SET_READ_PTR */ -#define DS2482_PTR_CODE_STATUS 0xF0 -#define DS2482_PTR_CODE_DATA 0xE1 -#define DS2482_PTR_CODE_CHANNEL 0xD2 /* DS2482-800 only */ -#define DS2482_PTR_CODE_CONFIG 0xC3 - - -#define RAW_DATA_SIZE 10 - - -//////////////////////////////////////////////////////////////////////////////////////// - - -// from board-htcleo-power.c -extern int is_ac_power_supplied(void); - -// from board-htcleo-log.c -extern double log(double x); - - -struct battery_status +static enum power_supply_property battery_properties[] = { - int timestamp; + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CURRENT_AVG, + POWER_SUPPLY_PROP_CHARGE_COUNTER, +}; - int voltage_uV; /* units of uV */ - int current_uA; /* units of uA */ - int current_avg_uA; - int charge_uAh; - - s16 temp_C; /* units of 0.1 C */ - - u8 percentage; /* battery percentage */ - u8 charge_source; - u8 status_reg; - u8 battery_full; /* battery full (don't charge) */ - - u8 cooldown; /* was overtemp */ - u8 charge_mode; -} __attribute__((packed)); - - -#define SOURCE_NONE 0 -#define SOURCE_USB 1 -#define SOURCE_AC 2 - -#define CHARGE_OFF 0 -#define CHARGE_SLOW 1 -#define CHARGE_FAST 2 -#define CHARGE_BATT_DISABLE 3 /* disable charging at battery */ - -#define TEMP_CRITICAL 600 /* no charging at all */ -#define TEMP_HOT 500 /* no fast charge, no charge > 4.1v */ -#define TEMP_WARM 450 /* no fast charge above this */ - -#define TEMP_HOT_MAX_MV 4100 /* stop charging here when hot */ -#define TEMP_HOT_MIN_MV 3800 /* resume charging here when hot */ -#define CE_DISABLE_MIN_MV 4100 +static int battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val); +static void htcleo_program_alarm(struct htcleo_device_info *di, int seconds); +static void battery_ext_power_changed(struct power_supply *psy); #define BATTERY_LOG_MAX 1024 #define BATTERY_LOG_MASK (BATTERY_LOG_MAX - 1) -/* When we're awake or running on wall power, sample the battery -* gauge every FAST_POLL seconds. If we're asleep and on battery -* power, sample every SLOW_POLL seconds -*/ -#define FAST_POLL (1 * 60) -#define SLOW_POLL (10 * 60) - static DEFINE_MUTEX(battery_log_lock); static struct battery_status battery_log[BATTERY_LOG_MAX]; static unsigned battery_log_head; @@ -174,15 +84,15 @@ static unsigned battery_log_tail; void battery_log_status(struct battery_status *s) { - unsigned n; - mutex_lock(&battery_log_lock); - n = battery_log_head; - memcpy(battery_log + n, s, sizeof(struct battery_status)); - n = (n + 1) & BATTERY_LOG_MASK; - if (n == battery_log_tail) - battery_log_tail = (battery_log_tail + 1) & BATTERY_LOG_MASK; - battery_log_head = n; - mutex_unlock(&battery_log_lock); + unsigned n; + mutex_lock(&battery_log_lock); + n = battery_log_head; + memcpy(battery_log + n, s, sizeof(struct battery_status)); + n = (n + 1) & BATTERY_LOG_MASK; + if (n == battery_log_tail) + battery_log_tail = (battery_log_tail + 1) & BATTERY_LOG_MASK; + battery_log_head = n; + mutex_unlock(&battery_log_lock); } static const char *battery_source[3] = { "none", " usb", " ac" }; @@ -190,202 +100,145 @@ static const char *battery_mode[4] = { " off", "slow", "fast", "full" }; static int battery_log_print(struct seq_file *sf, void *private) { - unsigned n; - mutex_lock(&battery_log_lock); - seq_printf(sf, "timestamp mV mA avg mA uAh dC %% src mode reg full\n"); - for (n = battery_log_tail; n != battery_log_head; n = (n + 1) & BATTERY_LOG_MASK) - { - struct battery_status *s = battery_log + n; - seq_printf(sf, "%9d %5d %6d %6d %8d %4d %3d %s %s 0x%02x %d\n", - s->timestamp, s->voltage_uV / 1000, - s->current_uA / 1000, s->current_avg_uA / 1000, - s->charge_uAh, s->temp_C, - s->percentage, - battery_source[s->charge_source], - battery_mode[s->charge_mode], - s->status_reg, s->battery_full); - } - mutex_unlock(&battery_log_lock); - return 0; + unsigned n; + mutex_lock(&battery_log_lock); + seq_printf(sf, "timestamp mV mA avg mA uAh dC %% src mode reg full\n"); + for (n = battery_log_tail; n != battery_log_head; n = (n + 1) & BATTERY_LOG_MASK) + { + struct battery_status *s = battery_log + n; + seq_printf(sf, "%9d %5d %6d %6d %8d %4d %3d %s %s 0x%02x %d\n", + s->timestamp, s->voltage_uV / 1000, + s->current_uA / 1000, s->current_avg_uA / 1000, + s->charge_uAh, s->temp_C, + s->percentage, + battery_source[s->charge_source], + battery_mode[s->charge_mode], + s->status_reg, s->battery_full); + } + mutex_unlock(&battery_log_lock); + return 0; } - -struct htcleo_device_info -{ - struct device *dev; - - /* DS2784 data, valid after calling htcleo_battery_read_status() */ - char raw[RAW_DATA_SIZE]; /* raw HTCLEO data */ - uint32_t raw_status; - - struct battery_status status; - - struct power_supply bat; - struct workqueue_struct *monitor_wqueue; - struct work_struct monitor_work; - struct alarm alarm; - struct wake_lock work_wake_lock; - - // int (*charge)(int on, int fast); - // struct w1_slave *w1_slave; - struct i2c_client *client; - - u8 dummy; /* dummy battery flag */ - u8 last_charge_mode; /* previous charger state */ - u8 slow_poll; - - ktime_t last_poll; - ktime_t last_charge_seen; -}; - -#define psy_to_dev_info(x) container_of((x), struct htcleo_device_info, bat) - -static struct wake_lock vbus_wake_lock; - -#define BATT_RSNSP (67) /*Passion battery source 1*/ - -static enum power_supply_property battery_properties[] = -{ - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_HEALTH, - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_TECHNOLOGY, - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_TEMP, - POWER_SUPPLY_PROP_CURRENT_NOW, - POWER_SUPPLY_PROP_CURRENT_AVG, - POWER_SUPPLY_PROP_CHARGE_COUNTER, -}; - -static int battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val); -static void htcleo_program_alarm(struct htcleo_device_info *di, int seconds); -static void battery_ext_power_changed(struct power_supply *psy); - -#define to_htcleo_device_info(x) container_of((x), struct htcleo_device_info, bat); - - -////////////////////////////////////////////////////////////////////////// - static int I2C_Read_Status(struct htcleo_device_info *di) { - uint8_t i2c_msg[1]; - uint8_t i2c_data[2]; + uint8_t i2c_msg[1]; + uint8_t i2c_data[2]; - i2c_msg[0] = 0x01; //status reg + i2c_msg[0] = 0x01; //status reg - i2c_master_send(di->client, i2c_msg, 1); - i2c_master_recv(di->client, i2c_data, 2); + i2c_master_send(di->client, i2c_msg, 1); + i2c_master_recv(di->client, i2c_data, 2); - dev_dbg(&di->client->dev, "I2C_Read_Status() = %08X!\n", i2c_data[0]); - di->raw_status = i2c_data[0]; - return 0; + dev_dbg(&di->client->dev, "I2C_Read_Status() = %08X!\n", i2c_data[0]); + di->raw_status = i2c_data[0]; + return 0; } static int I2C_Read_Data(struct htcleo_device_info *di) { - uint8_t i2c_msg[1]; - uint8_t i2c_data[10]; + uint8_t i2c_msg[1]; + uint8_t i2c_data[10]; - i2c_msg[0] = 0x08; // AUX0 AUX1 VOLTAGE CURRENT ACR + i2c_msg[0] = 0x08; // AUX0 AUX1 VOLTAGE CURRENT ACR - i2c_master_send(di->client, i2c_msg, 1); - i2c_master_recv(di->client, i2c_data, 10); + i2c_master_send(di->client, i2c_msg, 1); + i2c_master_recv(di->client, i2c_data, 10); - dev_dbg(&di->client->dev, "I2C_Read_Data() %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X!\n", - i2c_data[0], i2c_data[1], i2c_data[2], i2c_data[3], i2c_data[4], - i2c_data[5], i2c_data[6], i2c_data[7], i2c_data[8], i2c_data[9]); - memcpy(di->raw, i2c_data, 10); - return 0; + dev_dbg(&di->client->dev, "I2C_Read_Data() %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X!\n", + i2c_data[0], i2c_data[1], i2c_data[2], i2c_data[3], i2c_data[4], + i2c_data[5], i2c_data[6], i2c_data[7], i2c_data[8], i2c_data[9]); + memcpy(di->raw, i2c_data, 10); + return 0; } static int I2C_Write_ACR(struct htcleo_device_info *di, uint16_t val) { - uint8_t i2c_msg[3]; + uint8_t i2c_msg[3]; - i2c_msg[0] = 0x10; - i2c_msg[1] = (val >> 8) & 0xFF; - i2c_msg[2] = (val >> 0) & 0xFF; + i2c_msg[0] = 0x10; + i2c_msg[1] = (val >> 8) & 0xFF; + i2c_msg[2] = (val >> 0) & 0xFF; - // dev_dbg(&di->client->dev, "I2C_Write_ACR() = %04X!\n", val); - i2c_master_send(di->client, i2c_msg, 3); - return 0; +// dev_dbg(&di->client->dev, "I2C_Write_ACR() = %04X!\n", val); + i2c_master_send(di->client, i2c_msg, 3); + return 0; } ////////////////////////////////////////////////////////////////////////// static int htcleo_charge(int on, int fast) { - gpio_direction_output(HTCLEO_GPIO_BATTERY_CHARGER_CURRENT, !!fast); - gpio_direction_output(HTCLEO_GPIO_BATTERY_CHARGER_ENABLE, !on); - return 0; + gpio_direction_output(HTCLEO_GPIO_BATTERY_CHARGER_CURRENT, !!fast); + gpio_direction_output(HTCLEO_GPIO_BATTERY_CHARGER_ENABLE, !on); + return 0; } static void htcleo_parse_data(uint32_t raw_status, u8 *raw, struct battery_status *s) { - short n; - uint32_t n32; - uint32_t FL, ACR, ACR_EMPTY; + short n; + uint32_t n32; + uint32_t FL, ACR, ACR_EMPTY; - /* Get status reg */ - s->status_reg = raw_status; + /* Get status reg */ + s->status_reg = raw_status; - /* Get Level */ - // TODO: FL too wrong (?) - ACR = ((raw[8] << 8) | raw[9]); - FL = (LEO_BATTERY_CAPACITY * 1570) / 625; - ACR_EMPTY = (LEO_BATTERY_EMPTY * 1570) / 625; - s->percentage = (100 * (ACR - ACR_EMPTY)) / FL; + /* Get Level */ + // TODO: FL too wrong (?) + ACR = ((raw[8] << 8) | raw[9]); + FL = (LEO_BATTERY_CAPACITY * 1570) / 625; + ACR_EMPTY = (LEO_BATTERY_EMPTY * 1570) / 625; + s->percentage = (100 * (ACR - ACR_EMPTY)) / FL; - s->charge_uAh = 1000 * (((ACR - ACR_EMPTY) * 625) / 1570); - printk("ACR=%d FL=%d RAAC=%d\n", ACR, ACR_EMPTY, s->percentage); - - if (s->percentage < 0 ) s->percentage = 0; - if (s->percentage > 100 ) s->percentage = 100; + s->charge_uAh = 1000 * (((ACR - ACR_EMPTY) * 625) / 1570); + + if (s->percentage < 0 ) s->percentage = 0; + if (s->percentage > 100 ) s->percentage = 100; - /* Get Voltage */ - n32 = (((raw[4] << 8) | raw[5]) / 16); - //s->voltage_uV = (n32 * 244) / 100; - s->voltage_uV = 1000 * ((n32 * 312) >> 7); // div to 128 + /* Get Voltage */ + n32 = (((raw[4] << 8) | raw[5]) / 16); + //s->voltage_uV = (n32 * 244) / 100; + s->voltage_uV = 1000 * ((n32 * 312) >> 7); // div to 128 - /* Get Current */ - n = ((raw[6]) << 8) | raw[7]; - s->current_uA = 1000 * (((n / 4) * 625) / 1570); + /* Get Current */ + n = ((raw[6]) << 8) | raw[7]; + s->current_uA = 1000 * (((n/4) * 625) / 1570); - // average current not supported by DS2746 - s->current_avg_uA = s->current_uA; + printk("ACR=%d CURR=%d VOL=%d RAAC=%d\n", ACR, s->current_uA, s->voltage_uV, s->percentage); - /* Get Temperature */ - n = ((raw[0] << 8) | (raw[1])); - n /= 16; + // average current not supported by DS2746 + s->current_avg_uA = s->current_uA; -// printk("temp = %x\n", n); - if (n > 2047 || n == 0) - { - s->temp_C = 250; - } - else - { - double v = 0.021277 * (300.0 / (2047.0 / n - 1.0)); - s->temp_C = 10 * (1.0 / ((log(v) * 0.000290698) + 0.003354016) - 273.15); - } - if (s->temp_C < -250) - { - s->temp_C = -250; - } + /* Get Temperature */ + n = ((raw[0] << 8) | (raw[1])); + n /= 16; + + // printk("temp = %x\n", n); + if (n > 2047 || n == 0) + { + s->temp_C = 250; + } + else + { + double v = 0.021277 * (300.0 / (2047.0 / n - 1.0)); + s->temp_C = 10 * (1.0 / ((log(v) * 0.000290698) + 0.003354016) - 273.15); + } + if (s->temp_C < -250) + { + s->temp_C = -250; + } } static int htcleo_battery_read_status(struct htcleo_device_info *di) { // read status - I2C_Read_Status(di); - I2C_Read_Data(di); + I2C_Read_Status(di); + I2C_Read_Data(di); // printk("status = %04X\n", di->raw_status); - htcleo_parse_data(di->raw_status, di->raw, &di->status); + htcleo_parse_data(di->raw_status, di->raw, &di->status); - dev_dbg(&di->client->dev, "batt: %3d%%, %d mV, %d mA (%d avg), %d.%d C, %d mAh\n", + dev_dbg(&di->client->dev, "batt: %3d%%, %d mV, %d mA (%d avg), %d.%d C, %d mAh\n", di->status.percentage, di->status.voltage_uV / 1000, di->status.current_uA / 1000, di->status.current_avg_uA / 1000, @@ -400,509 +253,470 @@ static int htcleo_battery_read_status(struct htcleo_device_info *di) static int htcleo_set_cc(struct htcleo_device_info *di, bool enable) { // not supported for DS2745, there no CE bit - return 0; + return 0; } static int battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { - struct htcleo_device_info *di = psy_to_dev_info(psy); + struct htcleo_device_info *di = psy_to_dev_info(psy); - switch (psp) - { - case POWER_SUPPLY_PROP_STATUS: - switch (di->status.charge_source) - { - case CHARGE_OFF: - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; - break; - case CHARGE_FAST: - case CHARGE_SLOW: - if (di->status.battery_full) - val->intval = POWER_SUPPLY_STATUS_FULL; - else if (di->status.charge_mode == CHARGE_OFF || - di->status.charge_mode == CHARGE_BATT_DISABLE) - val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; - else - val->intval = POWER_SUPPLY_STATUS_CHARGING; - break; - default: - val->intval = POWER_SUPPLY_STATUS_UNKNOWN; - break; - } - break; - case POWER_SUPPLY_PROP_HEALTH: - if (di->status.temp_C >= TEMP_HOT) - val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; - else - val->intval = POWER_SUPPLY_HEALTH_GOOD; - break; - case POWER_SUPPLY_PROP_PRESENT: - /* XXX todo */ - val->intval = 1; - break; - case POWER_SUPPLY_PROP_TECHNOLOGY: - if (di->dummy) - val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; - else - val->intval = POWER_SUPPLY_TECHNOLOGY_LION; - break; - case POWER_SUPPLY_PROP_CAPACITY: - if (di->dummy) - val->intval = 75; - else - val->intval = di->status.percentage; - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = di->status.voltage_uV; - break; - case POWER_SUPPLY_PROP_TEMP: - val->intval = di->status.temp_C; - break; - case POWER_SUPPLY_PROP_CURRENT_NOW: - val->intval = di->status.current_uA; - break; - case POWER_SUPPLY_PROP_CURRENT_AVG: - val->intval = di->status.current_avg_uA; - break; - case POWER_SUPPLY_PROP_CHARGE_COUNTER: - val->intval = di->status.charge_uAh; - break; - default: - return -EINVAL; - } + switch (psp) + { + case POWER_SUPPLY_PROP_STATUS: + switch (di->status.charge_source) + { + case CHARGE_OFF: + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; + break; + case CHARGE_FAST: + case CHARGE_SLOW: + if (di->status.battery_full) + val->intval = POWER_SUPPLY_STATUS_FULL; + else if (di->status.charge_mode == CHARGE_OFF) + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; + else + val->intval = POWER_SUPPLY_STATUS_CHARGING; + break; + default: + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; + break; + } + break; + case POWER_SUPPLY_PROP_HEALTH: + if (di->status.temp_C >= TEMP_HOT) + val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; + else + val->intval = POWER_SUPPLY_HEALTH_GOOD; + break; + case POWER_SUPPLY_PROP_PRESENT: + /* XXX todo */ + val->intval = 1; + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + if (di->dummy) + val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; + else + val->intval = POWER_SUPPLY_TECHNOLOGY_LION; + break; + case POWER_SUPPLY_PROP_CAPACITY: + if (di->dummy) + val->intval = 75; + else + val->intval = di->status.percentage; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = di->status.voltage_uV; + break; + case POWER_SUPPLY_PROP_TEMP: + val->intval = di->status.temp_C; + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval = di->status.current_uA; + break; + case POWER_SUPPLY_PROP_CURRENT_AVG: + val->intval = di->status.current_avg_uA; + break; + case POWER_SUPPLY_PROP_CHARGE_COUNTER: + val->intval = di->status.charge_uAh; + break; + default: + return -EINVAL; + } - return 0; + return 0; } static void htcleo_battery_update_status(struct htcleo_device_info *di) { - u8 last_level; - last_level = di->status.percentage; + u8 last_level; + last_level = di->status.percentage; - htcleo_battery_read_status(di); + htcleo_battery_read_status(di); -// CotullaTODO: add ACR = FL at top point here + // CotullaTODO: add ACR = FL at top point here - if ((last_level != di->status.percentage) || (di->status.temp_C > 450)) - { - power_supply_changed(&di->bat); - } + if ((last_level != di->status.percentage) || (di->status.temp_C > 450)) + { + power_supply_changed(&di->bat); + } } static DEFINE_MUTEX(charge_state_lock); static bool check_timeout(ktime_t now, ktime_t last, int seconds) { - ktime_t timeout = ktime_add(last, ktime_set(seconds, 0)); - return ktime_sub(timeout, now).tv64 < 0; + ktime_t timeout = ktime_add(last, ktime_set(seconds, 0)); + return ktime_sub(timeout, now).tv64 < 0; } static int battery_adjust_charge_state(struct htcleo_device_info *di) { - unsigned source; - int rc = 0; - int temp, volt; + unsigned source; + int rc = 0; + int temp, volt, curr, perc; int ovp; - u8 charge_mode; - bool charge_timeout = false; + u8 charge_mode; + bool charge_timeout = false; + static int lastval=0xffff; + const int min_curr=5000; - mutex_lock(&charge_state_lock); + mutex_lock(&charge_state_lock); - temp = di->status.temp_C; - volt = di->status.voltage_uV / 1000; + curr = di->status.current_uA; + perc = di->status.percentage; + temp = di->status.temp_C; + volt = di->status.voltage_uV / 1000; - source = di->status.charge_source; + source = di->status.charge_source; - /* initially our charge mode matches our source: - * NONE:OFF, USB:SLOW, AC:FAST - */ - charge_mode = source; - - /* shut off charger when full: - * - CHGTF flag is set - */ -#if 1 - /*if (di->status.status_reg & 0x80) - { - di->status.battery_full = 1; - charge_mode = CHARGE_BATT_DISABLE; - } - else - { - di->status.battery_full = 0; - }*/ - if(di->status.percentage >= 99) - { - di->status.battery_full = 1; - charge_mode = CHARGE_BATT_DISABLE; - } - else - { - di->status.battery_full = 0; - } -#else - // CotullaTODO: add DS274X check code here - di->status.battery_full = 0; -#endif + /* initially our charge mode matches our source: + * NONE:OFF, USB:SLOW, AC:FAST + */ + charge_mode = source; + + // Check whether the bat is full and change the ACR to right 100% value + if(curr >=0 && curr < min_curr && lastval < min_curr && perc > 95 && source) { + uint32_t FL = (LEO_BATTERY_CAPACITY * 1570) / 625; + uint32_t ACR_EMPTY = (LEO_BATTERY_EMPTY * 1570) / 625; + I2C_Write_ACR(di, FL+ACR_EMPTY); + di->status.battery_full = 1; + di->status.percentage = 100; + charge_mode = CHARGE_OFF; + } + else { + di->status.battery_full = 0; + } + if(curr >=0) lastval=curr; + else lastval=0xffff; ovp = gpio_get_value(HTCLEO_GPIO_BATTERY_OVER_CHG); if (ovp) { - // printk("OVERPOWER!!!! FACK!\n"); + printk("Battery overpowered!\n"); } - if (temp >= TEMP_HOT || ovp) - { - if (temp >= TEMP_CRITICAL) - { - charge_mode = CHARGE_BATT_DISABLE; - } + if (temp >= TEMP_HOT || ovp) + { + if (temp >= TEMP_CRITICAL) + { + charge_mode = CHARGE_OFF; + } - /* once we charge to max voltage when hot, disable - * charging until the temp drops or the voltage drops - */ - if (volt >= TEMP_HOT_MAX_MV) - { - di->status.cooldown = 1; - } - } + /* once we charge to max voltage when hot, disable + * charging until the temp drops or the voltage drops + */ + if (volt >= TEMP_HOT_MAX_MV) + { + di->status.cooldown = 1; + } + } - /* when the battery is warm, only charge in slow charge mode */ - if ((temp >= TEMP_WARM) && (charge_mode == CHARGE_FAST)) - charge_mode = CHARGE_SLOW; + /* when the battery is warm, only charge in slow charge mode */ + if ((temp >= TEMP_WARM) && (charge_mode == CHARGE_FAST)) + charge_mode = CHARGE_SLOW; - if (di->status.cooldown) - { - if ((temp < TEMP_WARM) || (volt <= TEMP_HOT_MIN_MV)) - di->status.cooldown = 0; - else - charge_mode = CHARGE_BATT_DISABLE; - } + if (di->status.cooldown) + { + if ((temp < TEMP_WARM) || (volt <= TEMP_HOT_MIN_MV)) + di->status.cooldown = 0; + else + charge_mode = CHARGE_OFF; + } - if (di->status.current_uA > 1024) - { - di->last_charge_seen = di->last_poll; - } - else if (di->last_charge_mode != CHARGE_OFF && check_timeout(di->last_poll, di->last_charge_seen, 60 * 60)) - { - if (di->last_charge_mode == CHARGE_BATT_DISABLE) - { - /* The charger is only powering the phone. Toggle the - * enable line periodically to prevent auto shutdown. - */ - di->last_charge_seen = di->last_poll; - pr_info("batt: charging POKE CHARGER\n"); - htcleo_charge(0, 0); - udelay(10); - htcleo_charge(1, source == CHARGE_FAST); - } - else - { - /* The charger has probably stopped charging. Turn it - * off until the next sample period. - */ - charge_timeout = true; - charge_mode = CHARGE_OFF; - } - } + if (di->status.current_uA > 1024) + { + di->last_charge_seen = di->last_poll; + } + else if (di->last_charge_mode != CHARGE_OFF && check_timeout(di->last_poll, di->last_charge_seen, 60 * 60)) + { + /* The charger has probably stopped charging. Turn it + * off until the next sample period. + */ + charge_timeout = true; + charge_mode = CHARGE_OFF; + } - if (source == CHARGE_OFF) - charge_mode = CHARGE_OFF; + if (source == CHARGE_OFF) + charge_mode = CHARGE_OFF; - /* Don't use CHARGE_BATT_DISABLE unless the voltage is high since the - * voltage drop over the discharge-path diode can cause a shutdown. - */ - if (charge_mode == CHARGE_BATT_DISABLE && volt < CE_DISABLE_MIN_MV) - charge_mode = CHARGE_OFF; - if (di->last_charge_mode == charge_mode) - goto done; + if (di->last_charge_mode == charge_mode) + goto done; - di->last_charge_mode = charge_mode; - di->status.charge_mode = charge_mode; + di->last_charge_mode = charge_mode; + di->status.charge_mode = charge_mode; - switch (charge_mode) - { - case CHARGE_OFF: - htcleo_charge(0, 0); - htcleo_set_cc(di, true); - if (temp >= TEMP_CRITICAL) - pr_info("batt: charging OFF [OVERTEMP]\n"); - else if (di->status.cooldown) - pr_info("batt: charging OFF [COOLDOWN]\n"); - else if (di->status.battery_full) - pr_info("batt: charging OFF [FULL]\n"); - else if (charge_timeout) - pr_info("batt: charging OFF [TIMEOUT]\n"); - else - pr_info("batt: charging OFF\n"); - break; - case CHARGE_BATT_DISABLE: - di->last_charge_seen = di->last_poll; - htcleo_set_cc(di, false); - htcleo_charge(1, source == CHARGE_FAST); - if (temp >= TEMP_CRITICAL) - pr_info("batt: charging BATTOFF [OVERTEMP]\n"); - else if (di->status.cooldown) - pr_info("batt: charging BATTOFF [COOLDOWN]\n"); - else if (di->status.battery_full) - pr_info("batt: charging BATTOFF [FULL]\n"); - else - pr_info("batt: charging BATTOFF [UNKNOWN]\n"); - break; - case CHARGE_SLOW: - di->last_charge_seen = di->last_poll; - htcleo_set_cc(di, true); - htcleo_charge(1, 0); - pr_info("batt: charging SLOW\n"); - break; - case CHARGE_FAST: - di->last_charge_seen = di->last_poll; - htcleo_set_cc(di, true); - htcleo_charge(1, 1); - pr_info("batt: charging FAST\n"); - break; - } - rc = 1; -done: - mutex_unlock(&charge_state_lock); - return rc; + switch (charge_mode) + { + case CHARGE_OFF: + htcleo_charge(0, 0); + htcleo_set_cc(di, true); + if (temp >= TEMP_CRITICAL) + pr_info("batt: charging OFF [OVERTEMP]\n"); + else if (di->status.cooldown) + pr_info("batt: charging OFF [COOLDOWN]\n"); + else if (di->status.battery_full) + pr_info("batt: charging OFF [FULL]\n"); + else if (charge_timeout) + pr_info("batt: charging OFF [TIMEOUT]\n"); + else + pr_info("batt: charging OFF\n"); + break; + case CHARGE_SLOW: + di->last_charge_seen = di->last_poll; + htcleo_set_cc(di, true); + htcleo_charge(1, 0); + pr_info("batt: charging SLOW\n"); + break; + case CHARGE_FAST: + di->last_charge_seen = di->last_poll; + htcleo_set_cc(di, true); + htcleo_charge(1, 1); + pr_info("batt: charging FAST\n"); + break; + } + rc = 1; + done: + mutex_unlock(&charge_state_lock); + return rc; } static void htcleo_battery_work(struct work_struct *work) { - struct htcleo_device_info *di = container_of(work, struct htcleo_device_info, monitor_work); - struct timespec ts; - unsigned long flags; + struct htcleo_device_info *di = container_of(work, struct htcleo_device_info, monitor_work); + struct timespec ts; + unsigned long flags; - htcleo_battery_update_status(di); + htcleo_battery_update_status(di); - di->last_poll = alarm_get_elapsed_realtime(); + di->last_poll = alarm_get_elapsed_realtime(); - if (battery_adjust_charge_state(di)) - { - power_supply_changed(&di->bat); - } + if (battery_adjust_charge_state(di)) + { + power_supply_changed(&di->bat); + } - ts = ktime_to_timespec(di->last_poll); - di->status.timestamp = ts.tv_sec; - battery_log_status(&di->status); + ts = ktime_to_timespec(di->last_poll); + di->status.timestamp = ts.tv_sec; + battery_log_status(&di->status); - /* prevent suspend before starting the alarm */ - local_irq_save(flags); - wake_unlock(&di->work_wake_lock); - htcleo_program_alarm(di, FAST_POLL); - local_irq_restore(flags); + /* prevent suspend before starting the alarm */ + local_irq_save(flags); + wake_unlock(&di->work_wake_lock); + htcleo_program_alarm(di, FAST_POLL); + local_irq_restore(flags); } ////////////////////////////////////////////////////////////////////////// static void htcleo_program_alarm(struct htcleo_device_info *di, int seconds) { - ktime_t low_interval = ktime_set(seconds - 10, 0); - ktime_t slack = ktime_set(20, 0); - ktime_t next; + ktime_t low_interval = ktime_set(seconds - 10, 0); + ktime_t slack = ktime_set(20, 0); + ktime_t next; - next = ktime_add(di->last_poll, low_interval); + next = ktime_add(di->last_poll, low_interval); - alarm_start_range(&di->alarm, next, ktime_add(next, slack)); + alarm_start_range(&di->alarm, next, ktime_add(next, slack)); } static void htcleo_battery_alarm(struct alarm *alarm) { - struct htcleo_device_info *di = container_of(alarm, struct htcleo_device_info, alarm); - wake_lock(&di->work_wake_lock); - queue_work(di->monitor_wqueue, &di->monitor_work); + struct htcleo_device_info *di = container_of(alarm, struct htcleo_device_info, alarm); + wake_lock(&di->work_wake_lock); + queue_work(di->monitor_wqueue, &di->monitor_work); } static void battery_ext_power_changed(struct power_supply *psy) { - struct htcleo_device_info *di; - int got_power; + struct htcleo_device_info *di; + int got_power; - di = psy_to_dev_info(psy); - got_power = power_supply_am_i_supplied(psy); + di = psy_to_dev_info(psy); + got_power = power_supply_am_i_supplied(psy); - if (got_power) - { - if (is_ac_power_supplied()) - di->status.charge_source = SOURCE_AC; - else - di->status.charge_source = SOURCE_USB; - wake_lock(&vbus_wake_lock); - } - else - { - di->status.charge_source = SOURCE_NONE; - /* give userspace some time to see the uevent and update - * LED state or whatnot... - */ - wake_lock_timeout(&vbus_wake_lock, HZ / 2); - } - battery_adjust_charge_state(di); - power_supply_changed(psy); + if (got_power) + { + if (is_ac_power_supplied()) + di->status.charge_source = SOURCE_AC; + else + di->status.charge_source = SOURCE_USB; + wake_lock(&vbus_wake_lock); + } + else + { + di->status.charge_source = SOURCE_NONE; + /* give userspace some time to see the uevent and update + * LED state or whatnot... + */ + wake_lock_timeout(&vbus_wake_lock, HZ / 2); + } + battery_adjust_charge_state(di); + power_supply_changed(psy); } static int htcleo_battery_probe(struct i2c_client *client, const struct i2c_device_id *id) { - int rc; - struct htcleo_device_info *di; + int rc; + struct htcleo_device_info *di; - printk("$$$ htcleo_battery_probe $$$\n"); - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) - { - return -EIO; - } + printk("%s\n", __func__); + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) + { + return -EIO; + } - di = kzalloc(sizeof(*di), GFP_KERNEL); - if (!di) - { - return -ENOMEM; - } + di = kzalloc(sizeof(*di), GFP_KERNEL); + if (!di) + { + return -ENOMEM; + } + + mydi=di; - di->client = client; + di->client = client; - i2c_set_clientdata(client, di); + i2c_set_clientdata(client, di); - gpio_request(HTCLEO_GPIO_BATTERY_CHARGER_CURRENT, "charger_current"); - gpio_request(HTCLEO_GPIO_BATTERY_CHARGER_ENABLE, "charger_enable"); - gpio_request(HTCLEO_GPIO_BATTERY_OVER_CHG, "charger_over_chg"); + gpio_request(HTCLEO_GPIO_BATTERY_CHARGER_CURRENT, "charger_current"); + gpio_request(HTCLEO_GPIO_BATTERY_CHARGER_ENABLE, "charger_enable"); + gpio_request(HTCLEO_GPIO_BATTERY_OVER_CHG, "charger_over_chg"); - gpio_direction_output(HTCLEO_GPIO_BATTERY_CHARGER_CURRENT, 1); - gpio_direction_output(HTCLEO_GPIO_BATTERY_CHARGER_ENABLE, 1); - gpio_direction_input(HTCLEO_GPIO_BATTERY_OVER_CHG); + gpio_direction_output(HTCLEO_GPIO_BATTERY_CHARGER_CURRENT, 1); + gpio_direction_output(HTCLEO_GPIO_BATTERY_CHARGER_ENABLE, 1); + gpio_direction_input(HTCLEO_GPIO_BATTERY_OVER_CHG); - di->bat.name = "battery"; - di->bat.type = POWER_SUPPLY_TYPE_BATTERY; - di->bat.properties = battery_properties; - di->bat.num_properties = ARRAY_SIZE(battery_properties); - di->bat.external_power_changed = battery_ext_power_changed; - di->bat.get_property = battery_get_property; - di->last_charge_mode = 0xff; + di->bat.name = "battery"; + di->bat.type = POWER_SUPPLY_TYPE_BATTERY; + di->bat.properties = battery_properties; + di->bat.num_properties = ARRAY_SIZE(battery_properties); + di->bat.external_power_changed = battery_ext_power_changed; + di->bat.get_property = battery_get_property; + di->last_charge_mode = 0xff; - rc = power_supply_register(&client->dev, &di->bat); - if (rc) - { - goto fail_register; - } + rc = power_supply_register(&client->dev, &di->bat); + if (rc) + { + goto fail_register; + } - INIT_WORK(&di->monitor_work, htcleo_battery_work); - di->monitor_wqueue = create_freezeable_workqueue(dev_name(&client->dev)); + INIT_WORK(&di->monitor_work, htcleo_battery_work); + di->monitor_wqueue = create_freezeable_workqueue(dev_name(&client->dev)); - /* init to something sane */ - di->last_poll = alarm_get_elapsed_realtime(); + /* init to something sane */ + di->last_poll = alarm_get_elapsed_realtime(); - if (!di->monitor_wqueue) - { - rc = -ESRCH; - goto fail_workqueue; - } - wake_lock_init(&di->work_wake_lock, WAKE_LOCK_SUSPEND, "htcleo-battery"); - printk("alarm init\n"); - alarm_init(&di->alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, htcleo_battery_alarm); - wake_lock(&di->work_wake_lock); - queue_work(di->monitor_wqueue, &di->monitor_work); - printk("probe exit!\n"); - return 0; + if (!di->monitor_wqueue) + { + rc = -ESRCH; + goto fail_workqueue; + } + wake_lock_init(&di->work_wake_lock, WAKE_LOCK_SUSPEND, "htcleo-battery"); + printk("alarm init\n"); + alarm_init(&di->alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, htcleo_battery_alarm); + wake_lock(&di->work_wake_lock); + queue_work(di->monitor_wqueue, &di->monitor_work); + printk("%s: done!\n", __func__); + return 0; -fail_workqueue: - power_supply_unregister(&di->bat); -fail_register: + fail_workqueue: + power_supply_unregister(&di->bat); + fail_register: - gpio_free(HTCLEO_GPIO_BATTERY_CHARGER_CURRENT); - gpio_free(HTCLEO_GPIO_BATTERY_CHARGER_ENABLE); - gpio_free(HTCLEO_GPIO_BATTERY_OVER_CHG); + gpio_free(HTCLEO_GPIO_BATTERY_CHARGER_CURRENT); + gpio_free(HTCLEO_GPIO_BATTERY_CHARGER_ENABLE); + gpio_free(HTCLEO_GPIO_BATTERY_OVER_CHG); - kfree(di); - return rc; + kfree(di); + return rc; } static int htcleo_suspend(struct device *dev) { - struct htcleo_device_info *di = dev_get_drvdata(dev); + struct htcleo_device_info *di = dev_get_drvdata(dev); - /* If we are on battery, reduce our update rate until - * we next resume. - */ - if (di->status.charge_source == SOURCE_NONE) - { - htcleo_program_alarm(di, SLOW_POLL); - di->slow_poll = 1; - } - return 0; + /* If we are on battery, reduce our update rate until + * we next resume. + */ + if (di->status.charge_source == SOURCE_NONE) + { + htcleo_program_alarm(di, SLOW_POLL); + di->slow_poll = 1; + } + return 0; } static int htcleo_resume(struct device *dev) { - struct htcleo_device_info *di = dev_get_drvdata(dev); + struct htcleo_device_info *di = dev_get_drvdata(dev); - /* We might be on a slow sample cycle. If we're - * resuming we should resample the battery state - * if it's been over a minute since we last did - * so, and move back to sampling every minute until - * we suspend again. - */ - if (di->slow_poll) - { - htcleo_program_alarm(di, FAST_POLL); - di->slow_poll = 0; - } - return 0; + /* We might be on a slow sample cycle. If we're + * resuming we should resample the battery state + * if it's been over a minute since we last did + * so, and move back to sampling every minute until + * we suspend again. + */ + if (di->slow_poll) + { + htcleo_program_alarm(di, FAST_POLL); + di->slow_poll = 0; + } + return 0; } static struct dev_pm_ops htcleo_pm_ops = { - .suspend = htcleo_suspend, - .resume = htcleo_resume, + .suspend = htcleo_suspend, + .resume = htcleo_resume, }; static const struct i2c_device_id htcleo_battery_id[] = { - { "htcleo-battery", 0 }, - { } + { "htcleo-battery", 0 }, + { } }; static struct i2c_driver htcleo_battery_driver = { - .driver = - { - .name = "htcleo-battery", - .owner = THIS_MODULE, - .pm = &htcleo_pm_ops, - }, - .id_table = htcleo_battery_id, - .probe = htcleo_battery_probe, + .driver = + { + .name = "htcleo-battery", + .owner = THIS_MODULE, + .pm = &htcleo_pm_ops, + }, + .id_table = htcleo_battery_id, + .probe = htcleo_battery_probe, #ifndef CONFIG_HAS_EARLYSUSPEND - /* .suspend = htcleo_suspend, - .resume = htcleo_resume,*/ + /* .suspend = htcleo_suspend, + .resume = htcleo_resume,*/ #endif }; static int battery_log_open(struct inode *inode, struct file *file) { - return single_open(file, battery_log_print, NULL); + return single_open(file, battery_log_print, NULL); } static struct file_operations battery_log_fops = { - .open = battery_log_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, + .open = battery_log_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; static int __init htcleo_battery_init(void) { - debugfs_create_file("battery_log", 0444, NULL, NULL, &battery_log_fops); - wake_lock_init(&vbus_wake_lock, WAKE_LOCK_SUSPEND, "vbus_present"); - return i2c_add_driver(&htcleo_battery_driver); + debugfs_create_file("battery_log", 0444, NULL, NULL, &battery_log_fops); + wake_lock_init(&vbus_wake_lock, WAKE_LOCK_SUSPEND, "vbus_present"); + return i2c_add_driver(&htcleo_battery_driver); } //module_init(htcleo_battery_init); diff --git a/arch/arm/mach-msm/board-htcleo-power.c b/arch/arm/mach-msm/board-htcleo-power.c index 1fab8214..fcb9d8da 100644 --- a/arch/arm/mach-msm/board-htcleo-power.c +++ b/arch/arm/mach-msm/board-htcleo-power.c @@ -37,12 +37,13 @@ #include #include #include +#include #include "board-htcleo.h" static char *supply_list[] = { - "battery", + "battery", }; static int inited; @@ -51,7 +52,7 @@ static int usb_status; static struct work_struct vbus_work; #ifdef CONFIG_USB_ANDROID -extern void notify_usb_connected(int status); +void notify_usb_connected(int status); static struct t_usb_status_notifier usb_status_notifier = { .name = "htc_battery", .func = notify_usb_connected, @@ -62,122 +63,126 @@ static int power_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { - if (psp != POWER_SUPPLY_PROP_ONLINE) - return -EINVAL; + if (psp != POWER_SUPPLY_PROP_ONLINE) + return -EINVAL; - if (psy->type == POWER_SUPPLY_TYPE_MAINS) - { - val->intval = (usb_status == 2); - } - else - { - val->intval = vbus_present; - } - return 0; + if (psy->type == POWER_SUPPLY_TYPE_MAINS) + { + val->intval = (usb_status == 2); + } + else + { + val->intval = vbus_present; + } + return 0; } static enum power_supply_property power_properties[] = { - POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_ONLINE, }; static struct power_supply ac_supply = { - .name = "ac", - .type = POWER_SUPPLY_TYPE_MAINS, - .supplied_to = supply_list, - .num_supplicants = ARRAY_SIZE(supply_list), - .properties = power_properties, - .num_properties = ARRAY_SIZE(power_properties), - .get_property = power_get_property, + .name = "ac", + .type = POWER_SUPPLY_TYPE_MAINS, + .supplied_to = supply_list, + .num_supplicants = ARRAY_SIZE(supply_list), + .properties = power_properties, + .num_properties = ARRAY_SIZE(power_properties), + .get_property = power_get_property, }; static struct power_supply usb_supply = { - .name = "usb", - .type = POWER_SUPPLY_TYPE_USB, - .supplied_to = supply_list, - .num_supplicants = ARRAY_SIZE(supply_list), - .properties = power_properties, - .num_properties = ARRAY_SIZE(power_properties), - .get_property = power_get_property, + .name = "usb", + .type = POWER_SUPPLY_TYPE_USB, + .supplied_to = supply_list, + .num_supplicants = ARRAY_SIZE(supply_list), + .properties = power_properties, + .num_properties = ARRAY_SIZE(power_properties), + .get_property = power_get_property, }; static int get_vbus_state(void) { - if (readl(MSM_SHARED_RAM_BASE + 0xEF20C)) - return 1; - else - return 0; + if (readl(MSM_SHARED_RAM_BASE + 0xEF20C)) + return 1; + else + return 0; } void notify_cable_status(int status) { - pr_info("### notify_cable_status(%d) ###\n", status); - vbus_present = status; - msm_hsusb_set_vbus_state(vbus_present); - power_supply_changed(&ac_supply); - power_supply_changed(&usb_supply); + pr_info("### notify_cable_status(%d) ###\n", status); + vbus_present = status; + msm_hsusb_set_vbus_state(vbus_present); + power_supply_changed(&ac_supply); + power_supply_changed(&usb_supply); + if(mydi) + power_supply_changed(&mydi->bat); } // called from USB driver void notify_usb_connected(int status) { - if (!inited) return; - pr_info("### notify_usb_connected(%d) ###\n", status); - usb_status = status; - power_supply_changed(&ac_supply); - power_supply_changed(&usb_supply); + if (!inited) return; + pr_info("### notify_usb_connected(%d) ###\n", status); + usb_status = status; + power_supply_changed(&ac_supply); + power_supply_changed(&usb_supply); + if(mydi) + power_supply_changed(&mydi->bat); } // called from DEX intrrupt void notify_vbus_change_intr(void) { - if (!inited) return; - schedule_work(&vbus_work); + if (!inited) return; + schedule_work(&vbus_work); } // used by battery driver int is_ac_power_supplied(void) { - return (usb_status == 2); + return (usb_status == 2); } static void vbus_work_func(struct work_struct *work) { - int vbus = get_vbus_state(); - printk(" new vbus = %d\n", vbus); -#ifdef CONFIG_USB_EHCI_HCD - if (vbus) - return 0; - else - return 0; -#else - if (vbus) - gpio_set_value(HTCLEO_GPIO_POWER_USB, 0); - else - gpio_set_value(HTCLEO_GPIO_POWER_USB, 1); -#endif - notify_cable_status(vbus); + int vbus = get_vbus_state(); + printk(" new vbus = %d\n", vbus); + #ifdef CONFIG_USB_EHCI_HCD + if (vbus) + return 0; + else + return 0; + #else + if (vbus) + gpio_set_value(HTCLEO_GPIO_POWER_USB, 0); + else + gpio_set_value(HTCLEO_GPIO_POWER_USB, 1); + #endif + notify_cable_status(vbus); } static int htcleo_power_probe(struct platform_device *pdev) { - printk("$$$ htcleo_power_probe $$$\n"); + printk("$$$ htcleo_power_probe $$$\n"); - INIT_WORK(&vbus_work, vbus_work_func); + INIT_WORK(&vbus_work, vbus_work_func); - gpio_request(HTCLEO_GPIO_POWER_USB, "power_usb"); - gpio_direction_output(HTCLEO_GPIO_POWER_USB, 0); + gpio_request(HTCLEO_GPIO_POWER_USB, "power_usb"); + gpio_direction_output(HTCLEO_GPIO_POWER_USB, 0); - power_supply_register(&pdev->dev, &ac_supply); - power_supply_register(&pdev->dev, &usb_supply); + power_supply_register(&pdev->dev, &ac_supply); + power_supply_register(&pdev->dev, &usb_supply); - inited = 1; - // init VBUS state - notify_vbus_change_intr(); - return 0; + inited = 1; + // init VBUS state + notify_vbus_change_intr(); + return 0; } //#define APP_BATT_PDEV_NAME "rs30100001:00000000" @@ -185,25 +190,25 @@ static int htcleo_power_probe(struct platform_device *pdev) static struct platform_driver htcleo_power_driver = { - .probe = htcleo_power_probe, - .driver = - { - .name = APP_BATT_PDEV_NAME, - .owner = THIS_MODULE, - }, + .probe = htcleo_power_probe, + .driver = + { + .name = APP_BATT_PDEV_NAME, + .owner = THIS_MODULE, + }, }; static int __init htcleo_power_init(void) { - printk("htcleo_power_init\n"); - platform_driver_register(&htcleo_power_driver); -#ifdef CONFIG_USB_ANDROID - usb_register_notifier(&usb_status_notifier); -#endif - return 0; + printk("htcleo_power_init\n"); + platform_driver_register(&htcleo_power_driver); + #ifdef CONFIG_USB_ANDROID + usb_register_notifier(&usb_status_notifier); + #endif + return 0; } -module_init(htcleo_power_init); -//later_init(htcleo_power_init); +//module_init(htcleo_power_init); +late_initcall(htcleo_power_init); MODULE_DESCRIPTION("HTCLEO Power Driver"); MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-msm/include/mach/board-htcleo-battery.h b/arch/arm/mach-msm/include/mach/board-htcleo-battery.h new file mode 100644 index 00000000..bc7c9ec2 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/board-htcleo-battery.h @@ -0,0 +1,102 @@ +#ifndef __LEO_BATTERY__ +#define __LEO_BATTERY__ + +#include + +#define LEO_BATTERY_CAPACITY 1230 +#define LEO_BATTERY_EMPTY 500 + +// from board-htcleo-power.c +extern int is_ac_power_supplied(void); + +// from board-htcleo-log.c +extern double log(double x); + +#define RAW_DATA_SIZE 10 + + +struct battery_status +{ + int timestamp; + + int voltage_uV; /* units of uV */ + int current_uA; /* units of uA */ + int current_avg_uA; + int charge_uAh; + + s16 temp_C; /* units of 0.1 C */ + + u8 percentage; /* battery percentage */ + u8 charge_source; + u8 status_reg; + u8 battery_full; /* battery full (don't charge) */ + + u8 cooldown; /* was overtemp */ + u8 charge_mode; +} __attribute__((packed)); + + +#define SOURCE_NONE 0 +#define SOURCE_USB 1 +#define SOURCE_AC 2 + +#define CHARGE_OFF 0 +#define CHARGE_SLOW 1 +#define CHARGE_FAST 2 + +#define TEMP_CRITICAL 600 /* no charging at all */ +#define TEMP_HOT 500 /* no fast charge, no charge > 4.1v */ +#define TEMP_WARM 450 /* no fast charge above this */ + +#define TEMP_HOT_MAX_MV 4100 /* stop charging here when hot */ +#define TEMP_HOT_MIN_MV 3800 /* resume charging here when hot */ +#define CE_DISABLE_MIN_MV 4100 + + +/* When we're awake or running on wall power, sample the battery +* gauge every FAST_POLL seconds. If we're asleep and on battery +* power, sample every SLOW_POLL seconds +*/ +#define FAST_POLL (1 * 60) +#define SLOW_POLL (10 * 60) + + +struct htcleo_device_info +{ + struct device *dev; + + /* DS2784 data, valid after calling htcleo_battery_read_status() */ + char raw[RAW_DATA_SIZE]; /* raw HTCLEO data */ + uint32_t raw_status; + + struct battery_status status; + + struct power_supply bat; + struct workqueue_struct *monitor_wqueue; + struct work_struct monitor_work; + struct alarm alarm; + struct wake_lock work_wake_lock; + + // int (*charge)(int on, int fast); + // struct w1_slave *w1_slave; + struct i2c_client *client; + + u8 dummy; /* dummy battery flag */ + u8 last_charge_mode; /* previous charger state */ + u8 slow_poll; + + ktime_t last_poll; + ktime_t last_charge_seen; +}; + +static struct htcleo_device_info * mydi = NULL; + +#define psy_to_dev_info(x) container_of((x), struct htcleo_device_info, bat) + +static struct wake_lock vbus_wake_lock; + + +#define to_htcleo_device_info(x) container_of((x), struct htcleo_device_info, bat); + +#endif + From dbd408efab87c018ab9c2e35fee672a97446852c Mon Sep 17 00:00:00 2001 From: LeTama Date: Mon, 25 Oct 2010 21:23:23 +0200 Subject: [PATCH 4/4] Audio stuttering fix, credits to Darkstone --- include/linux/mm.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 9e2fa999..397a3774 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1170,8 +1170,8 @@ int write_one_page(struct page *page, int wait); void task_dirty_inc(struct task_struct *tsk); /* readahead.c */ -#define VM_MAX_READAHEAD 4 /* kbytes */ -#define VM_MIN_READAHEAD 4 /* kbytes (includes current page) */ +#define VM_MAX_READAHEAD 128 /* kbytes */ +#define VM_MIN_READAHEAD 16 /* kbytes (includes current page) */ int force_page_cache_readahead(struct address_space *mapping, struct file *filp, pgoff_t offset, unsigned long nr_to_read);