msm: HTC: Update HTC battery drivers

* HTC kernel version: m7-kk-3.4.10-17db3b4

Change-Id: I69b7420a33199b5a48119d846c5fdb221abe2d65
diff --git a/arch/arm/mach-msm/htc/htc_battery_8960.c b/arch/arm/mach-msm/htc/htc_battery_8960.c
index dea5f04..bad85de 100644
--- a/arch/arm/mach-msm/htc/htc_battery_8960.c
+++ b/arch/arm/mach-msm/htc/htc_battery_8960.c
@@ -39,7 +39,7 @@
 #include <mach/htc_gauge.h>
 #include <mach/htc_charger.h>
 #include <mach/htc_battery_cell.h>
-
+#define MSPERIOD(end, start)	ktime_to_ms(ktime_sub(end, start))
 
 #define HTC_BATT_CHG_DIS_BIT_EOC	(1)
 #define HTC_BATT_CHG_DIS_BIT_ID		(1<<1)
@@ -48,15 +48,23 @@
 #define HTC_BATT_CHG_DIS_BIT_TMR	(1<<4)
 #define HTC_BATT_CHG_DIS_BIT_MFG	(1<<5)
 #define HTC_BATT_CHG_DIS_BIT_USR_TMR	(1<<6)
+#define HTC_BATT_CHG_DIS_BIT_STOP_SWOLLEN	(1<<7)
+
 static int chg_dis_reason;
 static int chg_dis_active_mask = HTC_BATT_CHG_DIS_BIT_ID
 								| HTC_BATT_CHG_DIS_BIT_MFG
+								| HTC_BATT_CHG_DIS_BIT_STOP_SWOLLEN
 								| HTC_BATT_CHG_DIS_BIT_TMP
 								| HTC_BATT_CHG_DIS_BIT_TMR
 								| HTC_BATT_CHG_DIS_BIT_USR_TMR;
 static int chg_dis_control_mask = HTC_BATT_CHG_DIS_BIT_ID
 								| HTC_BATT_CHG_DIS_BIT_MFG
+								| HTC_BATT_CHG_DIS_BIT_STOP_SWOLLEN
 								| HTC_BATT_CHG_DIS_BIT_USR_TMR;
+static int chg_dis_pj_mask = HTC_BATT_CHG_DIS_BIT_ID
+								| HTC_BATT_CHG_DIS_BIT_TMR;
+
+
 #define HTC_BATT_PWRSRC_DIS_BIT_MFG		(1)
 #define HTC_BATT_PWRSRC_DIS_BIT_API		(1<<1)
 static int pwrsrc_dis_reason;
@@ -83,6 +91,7 @@
 #define CONTEXT_STATE_BIT_TALK			(1)
 #define CONTEXT_STATE_BIT_SEARCH		(1<<1)
 #define CONTEXT_STATE_BIT_NAVIGATION	(1<<2)
+#define CONTEXT_STATE_BIT_DAYDREAM		(1<<3)
 static int context_state;
 
 #define STATE_WORKQUEUE_PENDING			(1)
@@ -121,9 +130,9 @@
 struct wake_lock batt_shutdown_wake_lock;
 
 static struct early_suspend early_suspend;
-#ifdef CONFIG_HTC_BATT_ALARM
 static int screen_state;
-
+static int pre_screen_state;
+#ifdef CONFIG_HTC_BATT_ALARM
 static int ac_suspend_flag;
 #endif
 static int htc_ext_5v_output_now;
@@ -131,23 +140,25 @@
 
 static int latest_chg_src = CHARGER_BATTERY;
 
+static int latest_pj_src = PJ_OUT;
+
 struct htc_battery_info {
 	int device_id;
 
-
+	
 	struct mutex info_lock;
 
 	spinlock_t batt_lock;
 	int is_open;
 
-
+	
 	int critical_low_voltage_mv;
-
+	
 	int *critical_alarm_vol_ptr;
 	int critical_alarm_vol_cols;
 	int overload_vol_thr_mv;
 	int overload_curr_thr_ma;
-
+	int smooth_chg_full_delay_min;
 	struct kobject batt_timer_kobj;
 	struct kobject batt_cable_kobj;
 
@@ -161,13 +172,14 @@
 
 	int guage_driver;
 	int charger;
-
+	
 	struct htc_gauge *igauge;
 	struct htc_charger *icharger;
 	struct htc_battery_cell *bcell;
 	int state;
-	unsigned int htc_extension;
+	unsigned int htc_extension;	
 	int (*get_thermal_sensor_temp)(int sensor_num, unsigned long *temp);
+	int shutdown_voltage;
 };
 static struct htc_battery_info htc_batt_info;
 
@@ -175,7 +187,7 @@
 	struct mutex schedule_lock;
 	unsigned long batt_system_jiffies;
 	unsigned long batt_suspend_ms;
-	unsigned long total_time_ms;
+	unsigned long total_time_ms;	
 	unsigned int batt_alarm_status;
 #ifdef CONFIG_HTC_BATT_ALARM
 	unsigned int batt_critical_alarm_counter;
@@ -185,15 +197,17 @@
 	unsigned int time_out;
 	struct work_struct batt_work;
 	struct delayed_work unknown_usb_detect_work;
+	struct delayed_work calculate_pj_level_work;
 	struct alarm batt_check_wakeup_alarm;
 	struct timer_list batt_timer;
 	struct workqueue_struct *batt_wq;
 	struct wake_lock battery_lock;
 	struct wake_lock unknown_usb_detect_lock;
+	struct wake_lock calculate_pj_level_lock;
 };
 static struct htc_battery_timer htc_batt_timer;
 
-struct mutex cable_notifier_lock;
+struct mutex cable_notifier_lock; 
 static void cable_status_notifier_func(int online);
 static struct t_cable_status_notifier cable_status_notifier = {
 	.name = "htc_battery_8960",
@@ -214,16 +228,6 @@
 	int threshold_ma;
 	int level_boundary;
 };
-static struct max_level_by_current_ma limit_level_curr_table[] = { {-800, 92},
-							{-700, 93},
-							{-600, 94},
-							{-500, 95},
-							{-400, 96},
-							{-300, 97},
-							{-200, 98},
-							{-100, 99},};
-
-static const int LIMIT_LEVEL_CURR_TABLE_SIZE = sizeof(limit_level_curr_table) / sizeof (limit_level_curr_table[0]);
 
 int htc_gauge_get_battery_voltage(int *result)
 {
@@ -259,7 +263,7 @@
 				__func__, htc_batt_info.state);
 	}
 
-
+	
 	wake_lock(&htc_batt_timer.battery_lock);
 	queue_work(htc_batt_timer.batt_wq, &htc_batt_timer.batt_work);
 	return 0;
@@ -318,7 +322,7 @@
 			htc_batt_schedule_batt_info_update();
 		}
 #endif
-
+		
 		if (htc_batt_info.igauge && htc_batt_info.critical_alarm_vol_cols) {
 			if (htc_batt_info.igauge->register_lower_voltage_alarm_notifier)
 				htc_batt_info.igauge->register_lower_voltage_alarm_notifier(
@@ -367,12 +371,12 @@
 
 int htc_charger_event_notify(enum htc_charger_event event)
 {
-
+	
 	pr_info("[BATT] %s charger event=%d\n", __func__, event);
 	switch (event) {
 	case HTC_CHARGER_EVENT_VBUS_IN:
-
-
+		
+		
 		break;
 	case HTC_CHARGER_EVENT_SRC_INTERNAL:
 		htc_ext_5v_output_now = 1;
@@ -386,23 +390,23 @@
 		htc_batt_schedule_batt_info_update();
 		break;
 	case HTC_CHARGER_EVENT_VBUS_OUT:
-	case HTC_CHARGER_EVENT_SRC_NONE:
+	case HTC_CHARGER_EVENT_SRC_NONE: 
 		latest_chg_src = CHARGER_BATTERY;
 		htc_batt_schedule_batt_info_update();
 		break;
-	case HTC_CHARGER_EVENT_SRC_USB:
+	case HTC_CHARGER_EVENT_SRC_USB: 
 		latest_chg_src = CHARGER_USB;
 		htc_batt_schedule_batt_info_update();
 		break;
-	case HTC_CHARGER_EVENT_SRC_AC:
+	case HTC_CHARGER_EVENT_SRC_AC: 
 		latest_chg_src = CHARGER_AC;
 		htc_batt_schedule_batt_info_update();
 		break;
-	case HTC_CHARGER_EVENT_SRC_WIRELESS:
+	case HTC_CHARGER_EVENT_SRC_WIRELESS: 
 		latest_chg_src = CHARGER_WIRELESS;
 		htc_batt_schedule_batt_info_update();
 		break;
-	case HTC_CHARGER_EVENT_SRC_DETECTING:
+	case HTC_CHARGER_EVENT_SRC_DETECTING: 
 		latest_chg_src = CHARGER_DETECTING;
 		htc_batt_schedule_batt_info_update();
 		wake_lock(&htc_batt_timer.unknown_usb_detect_lock);
@@ -411,8 +415,11 @@
 				round_jiffies_relative(msecs_to_jiffies(
 								UNKNOWN_USB_DETECT_DELAY_MS)));
 		break;
-	case HTC_CHARGER_EVENT_SRC_UNKNOWN_USB:
-		latest_chg_src = CHARGER_UNKNOWN_USB;
+	case HTC_CHARGER_EVENT_SRC_UNKNOWN_USB: 
+		if (get_kernel_flag() & KERNEL_FLAG_ENABLE_FAST_CHARGE)
+			latest_chg_src = CHARGER_AC;
+		else
+			latest_chg_src = CHARGER_UNKNOWN_USB;
 		htc_batt_schedule_batt_info_update();
 		break;
 	case HTC_CHARGER_EVENT_OVP:
@@ -428,7 +435,7 @@
 	case HTC_CHARGER_EVENT_READY:
 		if (!htc_batt_info.icharger) {
 			pr_err("[BATT]err: htc_charger is not hooked.\n");
-
+				
 			break;
 		}
 		mutex_lock(&htc_batt_info.info_lock);
@@ -443,6 +450,14 @@
 #endif
 		mutex_unlock(&htc_batt_info.info_lock);
 		break;
+	case HTC_CHARGER_EVENT_POWER_JACKET_IN:
+		latest_pj_src = PJ_IN;
+		htc_batt_schedule_batt_info_update();
+		break;
+	case HTC_CHARGER_EVENT_POWER_JACKET_OUT:
+		latest_pj_src = PJ_OUT;
+		htc_batt_schedule_batt_info_update();
+		break;
 	default:
 		pr_info("[BATT] unsupported charger event(%d)\n", event);
 		break;
@@ -550,7 +565,7 @@
 		if (++htc_batt_timer.batt_critical_alarm_counter >= 3) {
 			BATT_LOG("%s: 3V voltage alarm is triggered.", __func__);
 			htc_batt_info.rep.level = 1;
-
+			
 			htc_battery_core_update_changed();
 		}
 		batt_set_voltage_alarm_mode(BATT_ALARM_CRITICAL_MODE);
@@ -558,7 +573,7 @@
 		htc_batt_timer.batt_alarm_status++;
 		BATT_LOG("%s: NORMAL_MODE batt alarm status = %u", __func__,
 			htc_batt_timer.batt_alarm_status);
-	} else {
+	} else { 
 		BATT_ERR("%s:Warning: batt alarm triggerred in disable mode ", __func__);
 	}
 #else
@@ -576,7 +591,7 @@
 	if (status != CHARGER_BATTERY && !ac_suspend_flag)
 		wake_lock(&htc_batt_info.vbus_wake_lock);
 	else if (status == CHARGER_USB && ac_suspend_flag)
-
+		
 		wake_lock(&htc_batt_info.vbus_wake_lock);
 	else
 		   wake_lock_timeout(&htc_batt_info.vbus_wake_lock, HZ * 5);
@@ -593,11 +608,11 @@
 {
 	static int first_update = 1;
 	mutex_lock(&cable_notifier_lock);
-
+	
 	htc_batt_info.rep.batt_state = 1;
 
 	BATT_LOG("%s(%d)", __func__, online);
-
+	
 	if (online == latest_chg_src && !first_update) {
 		BATT_LOG("%s: charger type (%u) same return.",
 			__func__, online);
@@ -610,17 +625,17 @@
 	case CONNECT_TYPE_USB:
 		BATT_LOG("USB charger");
 		htc_charger_event_notify(HTC_CHARGER_EVENT_SRC_USB);
-
+		
 		break;
 	case CONNECT_TYPE_AC:
 		BATT_LOG("5V AC charger");
 		htc_charger_event_notify(HTC_CHARGER_EVENT_SRC_AC);
-
+		
 		break;
 	case CONNECT_TYPE_WIRELESS:
 		BATT_LOG("wireless charger");
 		htc_charger_event_notify(HTC_CHARGER_EVENT_SRC_WIRELESS);
-
+		
 		break;
 	case CONNECT_TYPE_UNKNOWN:
 		BATT_LOG("unknown type");
@@ -628,7 +643,7 @@
 		break;
 	case CONNECT_TYPE_INTERNAL:
 		BATT_LOG("delivers power to VBUS from battery (not supported)");
-
+		
 		htc_charger_event_notify(HTC_CHARGER_EVENT_SRC_INTERNAL);
 		break;
 	case CONNECT_TYPE_CLEAR:
@@ -639,7 +654,7 @@
 	case CONNECT_TYPE_NONE:
 		BATT_LOG("No cable exists");
 		htc_charger_event_notify(HTC_CHARGER_EVENT_SRC_NONE);
-
+		
 		break;
 	case CONNECT_TYPE_MHL_AC:
 		BATT_LOG("mhl_ac");
@@ -648,10 +663,10 @@
 	default:
 		BATT_LOG("unsupported connect_type=%d", online);
 		htc_charger_event_notify(HTC_CHARGER_EVENT_SRC_NONE);
-
+		
 		break;
 	}
-#if 0
+#if 0 
 	htc_batt_timer.alarm_timer_flag =
 			(unsigned int)htc_batt_info.rep.charging_source;
 
@@ -724,14 +739,14 @@
 	htc_batt_schedule_batt_info_update();
 }
 
-struct mutex context_event_handler_lock;
+struct mutex context_event_handler_lock; 
 static int htc_batt_context_event_handler(enum batt_context_event event)
 {
 	int prev_context_state;
 
 	mutex_lock(&context_event_handler_lock);
 	prev_context_state = context_state;
-
+	
 	switch (event) {
 	case EVENT_TALK_START:
 		if (context_state & CONTEXT_STATE_BIT_TALK)
@@ -763,13 +778,23 @@
 			goto exit;
 		context_state &= ~CONTEXT_STATE_BIT_NAVIGATION;
 		break;
+	case EVENT_DAYDREAM_START:
+		if (context_state & CONTEXT_STATE_BIT_DAYDREAM)
+			goto exit;
+		context_state |= CONTEXT_STATE_BIT_DAYDREAM;
+		break;
+	case EVENT_DAYDREAM_STOP:
+		if (!(context_state & CONTEXT_STATE_BIT_DAYDREAM))
+			goto exit;
+		context_state &= ~CONTEXT_STATE_BIT_DAYDREAM;
+		break;
 	default:
 		pr_warn("unsupported context event (%d)\n", event);
 		goto exit;
 	}
 	BATT_LOG("context_state: 0x%x -> 0x%x", prev_context_state, context_state);
 
-
+	
 	__context_event_handler(event);
 
 exit:
@@ -829,18 +854,43 @@
 	return;
 }
 
+static void htc_batt_set_full_level_dis_batt_chg(int percent)
+{
+	if (percent < 0)
+		htc_batt_info.rep.full_level_dis_batt_chg = 0;
+	else if (100 < percent)
+		htc_batt_info.rep.full_level_dis_batt_chg = 100;
+	else
+		htc_batt_info.rep.full_level_dis_batt_chg = percent;
+
+	BATT_LOG(" set full_level_dis_batt_chg constraint as %d.", percent);
+
+	return;
+}
+
 static int htc_battery_get_rt_attr(enum htc_batt_rt_attr attr, int *val)
 {
 	int ret = 0;
 	switch (attr) {
 	case HTC_BATT_RT_VOLTAGE:
-		ret = htc_batt_info.igauge->get_battery_voltage(val);
+		if (htc_batt_info.igauge->get_battery_voltage)
+			ret = htc_batt_info.igauge->get_battery_voltage(val);
 		break;
 	case HTC_BATT_RT_CURRENT:
-		ret = htc_batt_info.igauge->get_battery_current(val);
+		if (htc_batt_info.igauge->get_battery_current)
+			ret = htc_batt_info.igauge->get_battery_current(val);
 		break;
 	case HTC_BATT_RT_TEMPERATURE:
-		ret = htc_batt_info.igauge->get_battery_temperature(val);
+		if (htc_batt_info.igauge->get_battery_temperature)
+			ret = htc_batt_info.igauge->get_battery_temperature(val);
+		break;
+	case HTC_PJ_RT_EXISTS:
+		if (htc_batt_info.icharger->get_pj_exist)
+			htc_batt_info.icharger->get_pj_exist(val);
+		break;
+	case HTC_PJ_RT_VOLTAGE:
+		if (htc_batt_info.igauge->get_pj_voltage)
+			htc_batt_info.igauge->get_pj_voltage(val);
 		break;
 	default:
 		ret = -EINVAL;
@@ -854,7 +904,7 @@
 {
 	int len = 0;
 
-
+	
 	len += scnprintf(buf + len, PAGE_SIZE - len,
 			"charging_source: %d;\n"
 			"charging_enabled: %d;\n"
@@ -870,7 +920,21 @@
 			htc_batt_info.htc_extension
 			);
 
+	if(htc_batt_info.icharger->is_pj_enable
+			&& htc_batt_info.icharger->is_pj_enable() > 0) {
+		len += scnprintf(buf + len, PAGE_SIZE - len,
+				"pj_source: %d;\n"
+				"pj_chg_status: %d;\n"
+				"pj_vol: %d;\n"
+				"pj_level: %d;\n",
+				htc_batt_info.rep.pj_src,
+				htc_batt_info.rep.pj_chg_status,
+				htc_batt_info.rep.pj_vol,
+				htc_batt_info.rep.pj_level
+				);
+	}
 
+	
 	if (htc_batt_info.igauge) {
 #if 0
 		if (htc_batt_info.igauge->name)
@@ -882,7 +946,7 @@
 						PAGE_SIZE - len);
 	}
 
-
+	
 	if (htc_batt_info.icharger) {
 #if 0
 		if (htc_batt_info.icharger->name)
@@ -901,7 +965,7 @@
 {
 	int len = 0, cc_uah = 0;
 
-
+	
 	if (htc_batt_info.igauge) {
 		if (htc_batt_info.igauge->get_battery_cc) {
 			htc_batt_info.igauge->get_battery_cc(&cc_uah);
@@ -991,6 +1055,13 @@
 	htc_batt_update->temp_fault = htc_batt_info.rep.temp_fault;
 	htc_batt_update->batt_state = htc_batt_info.rep.batt_state;
 	htc_batt_update->overload = htc_batt_info.rep.overload;
+	htc_batt_update->full_level_dis_batt_chg = htc_batt_info.rep.full_level_dis_batt_chg;
+	htc_batt_update->pj_vol = htc_batt_info.rep.pj_vol;
+	htc_batt_update->pj_src = htc_batt_info.rep.pj_src;
+	htc_batt_update->pj_chg_status = htc_batt_info.rep.pj_chg_status;
+	htc_batt_update->pj_full = htc_batt_info.rep.pj_full;
+	htc_batt_update->pj_level= htc_batt_info.rep.pj_level;
+	htc_batt_update->pj_level_pre= htc_batt_info.rep.pj_level_pre;
 	return 0;
 }
 
@@ -1027,7 +1098,7 @@
 	u32 battid_adc = 0;
 	struct battery_adc_reply adc;
 
-
+	
 	ret = pm8058_htc_config_mpp_and_adc_read(
 			adc.adc_voltage,
 			ADC_REPLY_ARRAY_SIZE,
@@ -1036,7 +1107,7 @@
 			htc_batt_info.mpp_config->vol[PM_MPP_AIN_AMUX]);
 	if (ret)
 		goto get_adc_failed;
-
+	
 	ret = pm8058_htc_config_mpp_and_adc_read(
 			adc.adc_current,
 			ADC_REPLY_ARRAY_SIZE,
@@ -1045,7 +1116,7 @@
 			htc_batt_info.mpp_config->curr[PM_MPP_AIN_AMUX]);
 	if (ret)
 		goto get_adc_failed;
-
+	
 	ret = pm8058_htc_config_mpp_and_adc_read(
 			adc.adc_temperature,
 			ADC_REPLY_ARRAY_SIZE,
@@ -1054,7 +1125,7 @@
 			htc_batt_info.mpp_config->temp[PM_MPP_AIN_AMUX]);
 	if (ret)
 		goto get_adc_failed;
-
+	
 	ret = pm8058_htc_config_mpp_and_adc_read(
 			adc.adc_battid,
 			ADC_REPLY_ARRAY_SIZE,
@@ -1102,9 +1173,9 @@
 {
 	static int pingpong = 1;
 	int lowerbd;
-	int b_is_charge_off_by_bounding = 0;
+	int is_input_chg_off_by_bounding = 0;
 
-	lowerbd = upperbd - 5;
+	lowerbd = upperbd - 5; 
 
 	if (lowerbd < 0)
 		lowerbd = 0;
@@ -1112,12 +1183,12 @@
 	if (pingpong == 1 && upperbd <= current_level) {
 		pr_info("MFG: lowerbd=%d, upperbd=%d, current=%d,"
 				" pingpong:1->0 turn off\n", lowerbd, upperbd, current_level);
-		b_is_charge_off_by_bounding = 1;
+		is_input_chg_off_by_bounding = 1;
 		pingpong = 0;
 	} else if (pingpong == 0 && lowerbd < current_level) {
 		pr_info("MFG: lowerbd=%d, upperbd=%d, current=%d,"
 				" toward 0, turn off\n", lowerbd, upperbd, current_level);
-		b_is_charge_off_by_bounding = 1;
+		is_input_chg_off_by_bounding = 1;
 	} else if (pingpong == 0 && current_level <= lowerbd) {
 		pr_info("MFG: lowerbd=%d, upperbd=%d, current=%d,"
 				" pingpong:0->1 turn on\n", lowerbd, upperbd, current_level);
@@ -1126,7 +1197,38 @@
 		pr_info("MFG: lowerbd=%d, upperbd=%d, current=%d,"
 				" toward %d, turn on\n", lowerbd, upperbd, current_level, pingpong);
 	}
-	return b_is_charge_off_by_bounding;
+	return is_input_chg_off_by_bounding;
+}
+
+static int bounding_fullly_charged_level_dis_batt_chg(int upperbd, int current_level)
+{
+	static int pingpong = 1;
+	int lowerbd;
+	int is_batt_chg_off_by_bounding = 0;
+
+	lowerbd = upperbd - 5; 
+
+	if (lowerbd < 0)
+		lowerbd = 0;
+
+	if (pingpong == 1 && upperbd <= current_level) {
+		pr_info("[BATT] %s: lowerbd=%d, upperbd=%d, current=%d,"
+				" pingpong:1->0 turn off\n", __func__, lowerbd, upperbd, current_level);
+		is_batt_chg_off_by_bounding = 1;
+		pingpong = 0;
+	} else if (pingpong == 0 && lowerbd < current_level) {
+		pr_info("[BATT] %s: lowerbd=%d, upperbd=%d, current=%d,"
+				" toward 0, turn off\n", __func__, lowerbd, upperbd, current_level);
+		is_batt_chg_off_by_bounding = 1;
+	} else if (pingpong == 0 && current_level <= lowerbd) {
+		pr_info("[BATT] %s: lowerbd=%d, upperbd=%d, current=%d,"
+				" pingpong:0->1 turn on\n", __func__, lowerbd, upperbd, current_level);
+		pingpong = 1;
+	} else {
+		pr_info("[BATT] %s: lowerbd=%d, upperbd=%d, current=%d,"
+				" toward %d, turn on\n", __func__, lowerbd, upperbd, current_level, pingpong);
+	}
+	return is_batt_chg_off_by_bounding;
 }
 
 static inline int is_bounding_fully_charged_level(void)
@@ -1138,6 +1240,15 @@
 	return 0;
 }
 
+static inline int is_bounding_fully_charged_level_dis_batt_chg(void)
+{
+	if (0 < htc_batt_info.rep.full_level_dis_batt_chg &&
+			htc_batt_info.rep.full_level_dis_batt_chg < 100)
+		return bounding_fullly_charged_level_dis_batt_chg(
+				htc_batt_info.rep.full_level_dis_batt_chg, htc_batt_info.rep.level);
+	return 0;
+}
+
 static void batt_update_info_from_charger(void)
 {
 	if (!htc_batt_info.icharger) {
@@ -1169,36 +1280,36 @@
 		return;
 	}
 
-
-
+	
+	
 	if (htc_batt_info.igauge->get_battery_voltage)
 		htc_batt_info.igauge->get_battery_voltage(
 				&htc_batt_info.rep.batt_vol);
-
+	
 	if (htc_batt_info.igauge->get_battery_current)
 		htc_batt_info.igauge->get_battery_current(
 				&htc_batt_info.rep.batt_current);
-
+	
 	if (htc_batt_info.igauge->get_battery_temperature)
 		htc_batt_info.igauge->get_battery_temperature(
 				&htc_batt_info.rep.batt_temp);
-
+	
 	if (htc_batt_info.igauge->is_battery_temp_fault)
 		htc_batt_info.igauge->is_battery_temp_fault(
 				&htc_batt_info.rep.temp_fault);
-
+	
 	if (htc_batt_info.igauge->get_battery_id)
 		htc_batt_info.igauge->get_battery_id(
 				&htc_batt_info.rep.batt_id);
 
-
+	
 	if (htc_battery_cell_get_cur_cell())
 		htc_batt_info.rep.full_bat = htc_battery_cell_get_cur_cell()->capacity;
 
 	htc_batt_info.igauge->get_battery_soc(
 		&htc_batt_info.rep.level_raw);
 	htc_batt_info.rep.level = htc_batt_info.rep.level_raw;
-
+	
 	if (htc_batt_info.icharger->is_ovp)
 		htc_batt_info.icharger->is_ovp(&htc_batt_info.rep.over_vchg);
 }
@@ -1223,12 +1334,14 @@
 			htc_batt_info.rep.overload = 0;
 		} else
 			htc_batt_info.rep.overload = 1;
-	} else {
+	} else { 
 			overload_count = 0;
 			htc_batt_info.rep.overload = 0;
 	}
 }
 
+#define CHG_ONE_PERCENT_LIMIT_PERIOD_MS		(1000 * 60)
+#define DISCHG_UPDATE_PERIOD_MS			(1000 * 60)
 #define ONE_PERCENT_LIMIT_PERIOD_MS		(1000 * (60 + 10))
 #define FIVE_PERCENT_LIMIT_PERIOD_MS	(1000 * (300 + 10))
 static void batt_level_adjust(unsigned long time_since_last_update_ms)
@@ -1237,7 +1350,10 @@
 	static int critical_low_enter = 0;
 	int prev_level, drop_level;
 	int is_full = 0;
-	int i, prev_current, measured_current;
+	int prev_current;
+	unsigned long level_since_last_update_ms;
+	unsigned long cur_jiffies = 0;
+	static unsigned long pre_jiffies;
 	const struct battery_info_reply *prev_batt_info_rep =
 						htc_battery_core_get_batt_info_rep();
 
@@ -1247,15 +1363,38 @@
 	} else {
 		prev_level = htc_batt_info.rep.level;
 		prev_current = htc_batt_info.rep.batt_current;
+		pre_jiffies = 0;
+		level_since_last_update_ms = DISCHG_UPDATE_PERIOD_MS;
 	}
 	drop_level = prev_level - htc_batt_info.rep.level;
 
+	if ((prev_batt_info_rep->charging_source > 0) &&
+		htc_batt_info.rep.charging_source == 0 && prev_level == 100) {
+		BATT_LOG("%s: Cable plug out when level 100, reset timer.",__func__);
+		pre_jiffies = jiffies;
+		htc_batt_info.rep.level = prev_level;
+		return;
+	}
+
 	if (!prev_batt_info_rep->charging_enabled &&
 			!((prev_batt_info_rep->charging_source == 0) &&
 				htc_batt_info.rep.charging_source > 0)) {
+		if (drop_level > 0) {
+			cur_jiffies = jiffies;
+			level_since_last_update_ms =
+			(cur_jiffies - pre_jiffies) * MSEC_PER_SEC / HZ;
+			BATT_LOG("%s: total_time since last batt level update = %lu ms.",
+					__func__, level_since_last_update_ms);
+			if (time_since_last_update_ms < DISCHG_UPDATE_PERIOD_MS &&
+				level_since_last_update_ms < DISCHG_UPDATE_PERIOD_MS) {
+				htc_batt_info.rep.level = prev_level;
+				return;
+			}
+		}
+
 		if (is_voltage_critical_low(htc_batt_info.rep.batt_vol)) {
 			critical_low_enter = 1;
-
+			
 			pr_info("[BATT] battery level force decreses 6%% from %d%%"
 					" (soc=%d)on critical low (%d mV)\n", prev_level,
 						htc_batt_info.rep.level,
@@ -1269,13 +1408,20 @@
 								drop_level,time_since_last_update_ms);
 					htc_batt_info.rep.level = prev_level - 2;
 				} else if (drop_level < 0) {
-					if (critical_low_enter) {
-						pr_warn("[BATT] level increase because of"
-								" exit critical_low!\n");
+					if (htc_batt_info.rep.pj_src > 0
+							&& htc_batt_info.rep.pj_chg_status == PJ_CHG_STATUS_DCHG) {
+						
+						pr_info("[BATT] level increase due to PJ charge battery"
+								" in %lu ms.\n",time_since_last_update_ms);
+					} else {
+						if (critical_low_enter) {
+							pr_warn("[BATT] level increase because of"
+									" exit critical_low!\n");
+						}
+						htc_batt_info.rep.level = prev_level;
 					}
-					htc_batt_info.rep.level = prev_level;
 				} else {
-
+					
 				}
 			} else if ((chg_limit_reason & HTC_BATT_CHG_LIMIT_BIT_TALK) &&
 				(time_since_last_update_ms <= FIVE_PERCENT_LIMIT_PERIOD_MS)) {
@@ -1284,13 +1430,20 @@
 								drop_level,time_since_last_update_ms);
 					htc_batt_info.rep.level = prev_level - 5;
 				} else if (drop_level < 0) {
-					if (critical_low_enter) {
-						pr_warn("[BATT] level increase because of"
-								" exit critical_low!\n");
+					if (htc_batt_info.rep.pj_src > 0
+							&& htc_batt_info.rep.pj_chg_status == PJ_CHG_STATUS_DCHG) {
+						
+						pr_info("[BATT] level increase due to PJ charge battery"
+								" in phone call.");
+					} else {
+						if (critical_low_enter) {
+							pr_warn("[BATT] level increase because of"
+									" exit critical_low!\n");
+						}
+						htc_batt_info.rep.level = prev_level;
 					}
-					htc_batt_info.rep.level = prev_level;
 				} else {
-
+					
 				}
 			} else {
 				if (3 < drop_level) {
@@ -1298,13 +1451,19 @@
 								drop_level,time_since_last_update_ms);
 					htc_batt_info.rep.level = prev_level - 3;
 				} else if (drop_level < 0) {
-					if (critical_low_enter) {
-						pr_warn("[BATT] level increase because of"
-								" exit critical_low!\n");
+					if (htc_batt_info.rep.pj_src > 0
+							&& htc_batt_info.rep.pj_chg_status == PJ_CHG_STATUS_DCHG) {
+						
+						pr_info("[BATT] level increase due to PJ charge battery.");
+					} else {
+						if (critical_low_enter) {
+							pr_warn("[BATT] level increase because of"
+									" exit critical_low!\n");
+						}
+						htc_batt_info.rep.level = prev_level;
 					}
-					htc_batt_info.rep.level = prev_level;
 				} else {
-
+					
 				}
 			}
 
@@ -1313,65 +1472,61 @@
 				pr_warn("[BATT] exit critical_low without charge!\n");
 			}
 		}
-		if ((htc_batt_info.rep.level == 0) && (prev_level > 1)) {
-			htc_batt_info.rep.level = 1;
-			pr_info("[BATT] battery level forcely report %d%%"
-					" since prev_level=%d%%\n",
-					htc_batt_info.rep.level, prev_level);
+		if (htc_batt_info.rep.level == 0) {
+			if (prev_level > 1) {
+				htc_batt_info.rep.level = 1;
+				pr_info("[BATT] battery level forcely report %d%%"
+						" since prev_level=%d%%\n",
+						htc_batt_info.rep.level, prev_level);
+			} else if (htc_batt_info.shutdown_voltage > 0) {
+				if (htc_batt_info.rep.batt_vol > htc_batt_info.shutdown_voltage &&
+						htc_batt_info.rep.batt_temp > 0) {
+					BATT_LOG("Keep level 1 due to battery voltage over %dmV.",
+							htc_batt_info.shutdown_voltage);
+					htc_batt_info.rep.level = 1;
+				}
+			}
 		}
 	} else {
 		if (htc_batt_info.igauge->is_battery_full) {
 			htc_batt_info.igauge->is_battery_full(&is_full);
 			if (is_full != 0) {
-				htc_batt_info.rep.level = 100;
+				if (htc_batt_info.smooth_chg_full_delay_min
+					&& prev_level < 100) {
+					htc_batt_info.rep.level = prev_level + 1;
+				} else {
+					htc_batt_info.rep.level = 100; 
+				}
 			} else {
 				if (99 < htc_batt_info.rep.level)
-					htc_batt_info.rep.level = 99;
-
-				if (htc_batt_info.rep.level > limit_level_curr_table[0].level_boundary &&
-						prev_level < htc_batt_info.rep.level) {
-
-					measured_current = htc_batt_info.rep.batt_current;
-					if (measured_current <= 0) {
-						if (prev_current > 0 || prev_current < measured_current)
-							measured_current = prev_current;
-					}
-
-					if (measured_current <= 0) {
-						for (i = 0; i < LIMIT_LEVEL_CURR_TABLE_SIZE; i++) {
-							if (measured_current < limit_level_curr_table[i].threshold_ma * 1000) {
-								break;
-							}
-						}
-					} else {
-						i = 0;
-					}
-
-					if (i < LIMIT_LEVEL_CURR_TABLE_SIZE && htc_batt_info.rep.level >= limit_level_curr_table[i].level_boundary) {
-						if (prev_level >= limit_level_curr_table[i].level_boundary)
-							htc_batt_info.rep.level = prev_level;
+					htc_batt_info.rep.level = 99; 
+				else if (prev_level < htc_batt_info.rep.level) {
+						if(time_since_last_update_ms >
+								CHG_ONE_PERCENT_LIMIT_PERIOD_MS)
+							htc_batt_info.rep.level = prev_level + 1;
 						else
-							htc_batt_info.rep.level = limit_level_curr_table[i].level_boundary - 1;
-						pr_info("[BATT] limit battery level to %d(prev=%d) by (%d,%d) with measured current %d\n",
-							htc_batt_info.rep.level, prev_level, limit_level_curr_table[i].level_boundary,
-							limit_level_curr_table[i].threshold_ma,	measured_current);
-					}
+							htc_batt_info.rep.level = prev_level;
 				}
 			}
 		}
 		critical_low_enter = 0;
 	}
+
+	if (htc_batt_info.rep.level != prev_level)
+		pre_jiffies = cur_jiffies;
+
 	first = 0;
 }
 
 
 static void batt_update_limited_charge(void)
 {
-	if (htc_batt_info.state & STATE_EARLY_SUSPEND) {
-
+	if ((htc_batt_info.state & STATE_EARLY_SUSPEND)
+		|| (context_state & CONTEXT_STATE_BIT_DAYDREAM)) {
+		
 		set_limit_charge_with_reason(false, HTC_BATT_CHG_LIMIT_BIT_THRML);
 	} else {
-
+		
 		if ((!(chg_limit_reason & HTC_BATT_CHG_LIMIT_BIT_THRML)) &&
 				htc_batt_info.rep.batt_temp > 390) {
 			set_limit_charge_with_reason(true, HTC_BATT_CHG_LIMIT_BIT_THRML);
@@ -1379,7 +1534,7 @@
 				htc_batt_info.rep.batt_temp <= 370) {
 			set_limit_charge_with_reason(false, HTC_BATT_CHG_LIMIT_BIT_THRML);
 		} else {
-
+			
 		}
 	}
 }
@@ -1397,14 +1552,14 @@
 		return;
 	}
 
-
+	
 	if(!htc_batt_info.rep.charging_enabled)
 	{
 		sw_stimer_counter = 0;
 		return;
 	}
 
-
+	
 	if(htc_batt_info.icharger && htc_batt_info.icharger->is_batt_charge_enable)
 	{
 		batt_chg_enabled = htc_batt_info.icharger->is_batt_charge_enable();
@@ -1416,12 +1571,12 @@
 	}
 
 
-
+	
 	if((latest_chg_src == HTC_PWR_SOURCE_TYPE_AC) || (latest_chg_src == HTC_PWR_SOURCE_TYPE_9VAC))
 	{
 		pr_info("%s enter\n", __func__);
 
-
+		
 		if(sw_stimer_fault)
 		{
 			pr_info("%s safety timer expired\n", __func__);
@@ -1430,15 +1585,15 @@
 
 		sw_stimer_counter +=  time_since_last_update_ms;
 
-
+		
 		if(sw_stimer_counter >= HTC_SAFETY_TIME_16_HR_IN_MS)
 		{
 			pr_info("%s sw_stimer_counter expired, count:%lu ms", __func__, sw_stimer_counter);
 
-
+			
 			sw_stimer_fault = 1;
 
-
+			
 			sw_stimer_counter = 0;
 		}
 		else
@@ -1451,18 +1606,18 @@
 
 void update_htc_extension_state(void)
 {
-
+	
 	if (HTC_PWR_SOURCE_TYPE_UNKNOWN_USB == htc_batt_info.rep.charging_source)
 		htc_batt_info.htc_extension |= HTC_EXT_UNKNOWN_USB_CHARGER;
 	else
 		htc_batt_info.htc_extension &= ~HTC_EXT_UNKNOWN_USB_CHARGER;
-
+	
 	if (charger_under_rating &&
 		HTC_PWR_SOURCE_TYPE_AC == htc_batt_info.rep.charging_source)
 		htc_batt_info.htc_extension |= HTC_EXT_CHG_UNDER_RATING;
 	else
 		htc_batt_info.htc_extension &= ~HTC_EXT_CHG_UNDER_RATING;
-
+	
 	if (charger_safety_timeout || sw_stimer_fault)
 		htc_batt_info.htc_extension |= HTC_EXT_CHG_SAFTY_TIMEOUT;
 	else
@@ -1474,6 +1629,195 @@
 		htc_batt_info.htc_extension &= ~HTC_EXT_CHG_FULL_EOC_STOP;
 }
 
+void get_pj_status(int *full, int *status, int *exist)
+{
+	*full = htc_batt_info.rep.pj_full;
+	*status = htc_batt_info.rep.pj_chg_status;
+	*exist = htc_batt_info.rep.pj_src;
+}
+
+#define SAMPLE_TIME 5
+static int batt_get_avg(int value[SAMPLE_TIME])
+{
+	int i = 0, j = 0, n = 0, result = 0;
+
+    for (i = 0; i < SAMPLE_TIME - 1; i++)
+    {
+      for (j = i + 1; j < SAMPLE_TIME; j++)
+      {
+        if (value[i] > value[j])
+        {
+          n = value[i];
+          value[i] = value[j];
+          value[j] = n;
+        }
+      }
+    }
+
+	for (i = 1; i < SAMPLE_TIME - 1; i++)
+		result = result + value[i];
+
+    return (result/(SAMPLE_TIME-2));
+}
+
+#define PJ_LEVEL_UPDATE_PERIOD (10*60*1000)
+#define PJ_LEVEL_DETECT_PERIOD (30*1000)
+static void power_jacket_level_update(int first)
+{
+	int i, is_chg = 0;
+	int vol[SAMPLE_TIME] = {0};
+
+	for (i = 0; i < SAMPLE_TIME; i++)
+		htc_batt_info.igauge->get_pj_voltage(&vol[i]);
+
+	htc_batt_info.rep.pj_vol = batt_get_avg(vol);
+	htc_batt_info.rep.pj_level_pre = htc_batt_info.rep.pj_level;
+
+	
+	if (batt_full_eoc_stop|chg_dis_reason)
+		is_chg = 0;
+	else
+		is_chg = htc_batt_info.rep.charging_enabled;
+
+	htc_batt_info.rep.pj_level
+		= htc_batt_info.igauge->calculate_pj_level(htc_batt_info.rep.pj_vol,
+			is_chg, htc_batt_info.rep.batt_temp);
+
+	BATT_LOG("%s: pj_vol: %d, pj_level: %d, pj_level_pre: %d, is_chg:%d",
+		__func__, htc_batt_info.rep.pj_vol, htc_batt_info.rep.pj_level,
+		htc_batt_info.rep.pj_level_pre, is_chg);
+
+	
+	if (htc_batt_info.rep.charging_enabled == 0) {
+		if (htc_batt_info.rep.pj_level >= htc_batt_info.rep.pj_level_pre && !first)
+			htc_batt_info.rep.pj_level = htc_batt_info.rep.pj_level_pre;
+
+		if (htc_batt_info.rep.level < 15 &&
+			htc_batt_info.rep.pj_level > 19 &&
+			htc_batt_info.rep.pj_level <= 39)
+			htc_batt_info.rep.pj_level = 19;
+	} else {
+	
+		
+		if (htc_batt_info.rep.pj_level - htc_batt_info.rep.pj_level_pre > 19 && !first)
+			htc_batt_info.rep.pj_level = htc_batt_info.rep.pj_level_pre + 19;
+	}
+
+	
+	if (htc_batt_info.rep.pj_level > 100)
+		htc_batt_info.rep.pj_level = 100;
+	else if (htc_batt_info.rep.pj_level < 0)
+		htc_batt_info.rep.pj_level = 0;
+}
+
+void power_jacket_info_update(void)
+{
+	int pj_chg_status = htc_batt_info.rep.pj_chg_status;
+	int err = 0, prev_pj_src = 0;
+	static int first = 1;
+	static ktime_t start_ktime;
+	static ktime_t end_ktime;
+
+	
+	prev_pj_src = htc_batt_info.rep.pj_src;
+	htc_batt_info.rep.pj_src = latest_pj_src;
+
+	htc_batt_info.igauge->is_pj_full(&htc_batt_info.rep.pj_full);
+
+	if (htc_batt_info.rep.pj_src) {
+		end_ktime = ktime_get_real();
+
+		if (!prev_pj_src || first) {
+			
+			power_jacket_level_update(1);
+			start_ktime = end_ktime;
+		}
+
+		if (MSPERIOD(start_ktime, end_ktime) > 0 ||
+			MSPERIOD(end_ktime, start_ktime) >= PJ_LEVEL_UPDATE_PERIOD) {
+
+			BATT_LOG("%s:Set PJ_OFF 30s to read level (start:%lld, end:%lld)",__func__,
+				ktime_to_ms(start_ktime),ktime_to_ms(end_ktime));
+
+			start_ktime = end_ktime;
+
+			pj_chg_status = PJ_CHG_STATUS_OFF;
+			if (delayed_work_pending(&htc_batt_timer.calculate_pj_level_work)) {
+				wake_unlock(&htc_batt_timer.calculate_pj_level_lock);
+				cancel_delayed_work(&htc_batt_timer.calculate_pj_level_work);
+			}
+
+			wake_lock(&htc_batt_timer.calculate_pj_level_lock);
+			queue_delayed_work(htc_batt_timer.batt_wq,
+					&htc_batt_timer.calculate_pj_level_work,
+					msecs_to_jiffies(PJ_LEVEL_DETECT_PERIOD)); 
+		} else if (htc_batt_info.rep.charging_source > 0) {
+			if ((chg_dis_reason & chg_dis_pj_mask) || charger_dis_temp_fault) {
+				pj_chg_status = PJ_CHG_STATUS_OFF;
+			} else {
+				if (htc_batt_info.rep.pj_full == PJ_FULL)
+					pj_chg_status = PJ_CHG_STATUS_OFF;
+				else
+					pj_chg_status = PJ_CHG_STATUS_CHG;
+			}
+		} else {
+			if (charger_dis_temp_fault)
+				pj_chg_status = PJ_CHG_STATUS_OFF;
+			else
+				pj_chg_status = PJ_CHG_STATUS_DCHG;
+		}
+
+		pr_info("[BATT]%s: pj_vol:%d, pj_full_detect:%d, pj_level:%d\n",
+			__func__, htc_batt_info.rep.pj_vol,
+			htc_batt_info.rep.pj_full, htc_batt_info.rep.pj_level);
+	} else {
+		htc_batt_info.rep.pj_vol = 0;
+		htc_batt_info.rep.pj_level = 0;
+		pj_chg_status = PJ_CHG_STATUS_OFF;
+		if (delayed_work_pending(&htc_batt_timer.calculate_pj_level_work))
+			cancel_delayed_work(&htc_batt_timer.calculate_pj_level_work);
+	}
+
+	if (pj_chg_status != htc_batt_info.rep.pj_chg_status || first) {
+
+		pr_info("[BATT]%s: (%d -> %d) pj_src:%d, pre_pj_src:%d, charging_source: %d"
+			", chg_enable: %d, chg_dis_reason: %d, no_level_update_time:%lld\n",
+			__func__, htc_batt_info.rep.pj_chg_status, pj_chg_status, 
+			htc_batt_info.rep.pj_src, prev_pj_src, htc_batt_info.rep.charging_source,
+			htc_batt_info.rep.charging_enabled, chg_dis_reason, MSPERIOD(end_ktime, start_ktime));
+
+		if (pj_chg_status == PJ_CHG_STATUS_OFF)
+			err = htc_batt_info.icharger->set_pj_chg_control(0,0);
+		else if (pj_chg_status == PJ_CHG_STATUS_CHG)
+			err = htc_batt_info.icharger->set_pj_chg_control(0,1);
+		else if (pj_chg_status == PJ_CHG_STATUS_DCHG)
+			err = htc_batt_info.icharger->set_pj_chg_control(1,0);
+		else
+			BATT_ERR("%s: not avalible power jacket type (%d)\n", __func__, pj_chg_status);
+
+		if (err)
+			htc_batt_info.rep.pj_chg_status = htc_batt_info.icharger->get_pj_chg_control();
+		else
+			htc_batt_info.rep.pj_chg_status = pj_chg_status;
+	}
+
+	
+	if ((!prev_pj_src) && (!htc_batt_info.rep.pj_src) && (htc_batt_info.rep.charging_source > 0)) {
+			htc_batt_info.icharger->pj_exist_detect();
+	}
+
+	first = 0;
+}
+
+static void calculate_pj_level_worker(struct work_struct *work)
+{
+	if (htc_batt_info.rep.pj_chg_status == PJ_CHG_STATUS_OFF) {
+		power_jacket_level_update(0);
+		power_jacket_info_update();
+	}
+	wake_unlock(&htc_batt_timer.calculate_pj_level_lock);
+}
+
 static void batt_worker(struct work_struct *work)
 {
 	static int first = 1;
@@ -1484,18 +1828,19 @@
 	int prev_chg_src;
 	unsigned long time_since_last_update_ms;
 	unsigned long cur_jiffies;
+	int pmic_aicl_enabled = 0;
 
-
+	
 	cur_jiffies = jiffies;
 	time_since_last_update_ms = htc_batt_timer.total_time_ms +
 		((cur_jiffies - htc_batt_timer.batt_system_jiffies) * MSEC_PER_SEC / HZ);
 	BATT_LOG("%s: total_time since last batt update = %lu ms.",
 				__func__, time_since_last_update_ms);
-	htc_batt_timer.total_time_ms = 0;
+	htc_batt_timer.total_time_ms = 0; 
 	htc_batt_timer.batt_system_jiffies = cur_jiffies;
 
-
-
+	
+	
 	del_timer_sync(&htc_batt_timer.batt_timer);
 	batt_set_check_timer(htc_batt_timer.time_out);
 
@@ -1505,18 +1850,18 @@
 	htc_batt_timer.batt_critical_alarm_counter = 0;
 #endif
 
-
+	
 	prev_chg_src = htc_batt_info.rep.charging_source;
 	htc_batt_info.rep.charging_source = latest_chg_src;
 
-
+	
 	batt_update_info_from_gauge();
 	batt_update_info_from_charger();
 
-
+	
 	batt_level_adjust(time_since_last_update_ms);
 
-
+	
 	if (critical_shutdown) {
 		BATT_LOG("critical shutdown (set level=0 to force shutdown)");
 		htc_batt_info.rep.level = 0;
@@ -1525,7 +1870,7 @@
 		schedule_delayed_work(&shutdown_work,
 				msecs_to_jiffies(BATT_CRITICAL_VOL_SHUTDOWN_DELAY_MS));
 	}
-
+	
 	if (critical_alarm_level < 0 &&
 			htc_batt_info.rep.level >= VOL_ALARM_RESUME_AFTER_LEVEL) {
 		pr_info("[BATT] critical_alarm_level: %d -> %d\n",
@@ -1534,13 +1879,13 @@
 		critical_alarm_level_set = critical_alarm_level + 1;
 	}
 
-
+	
 	batt_update_limited_charge();
 
-
+	
 	batt_check_overload();
 
-
+	
 	if (need_sw_stimer)
 	{
 		sw_safety_timer_check(time_since_last_update_ms);
@@ -1549,7 +1894,7 @@
 	pr_debug("[BATT] context_state=0x%x, suspend_highfreq_check_reason=0x%x\n",
 			context_state, suspend_highfreq_check_reason);
 
-
+	
 	if (htc_batt_info.icharger &&
 			htc_batt_info.icharger->enable_5v_output)
 	{
@@ -1561,14 +1906,14 @@
 		pr_info("[BATT] enable_5v_output: %d\n", htc_ext_5v_output_now);
 	}
 
-
+	
 	update_htc_extension_state();
 
 
 	if (htc_batt_info.rep.charging_source > 0) {
-
+		
 		if (htc_batt_info.rep.batt_id == HTC_BATTERY_CELL_ID_UNKNOWN)
-			chg_dis_reason |= HTC_BATT_CHG_DIS_BIT_ID;
+			chg_dis_reason |= HTC_BATT_CHG_DIS_BIT_ID; 
 		else
 			chg_dis_reason &= ~HTC_BATT_CHG_DIS_BIT_ID;
 
@@ -1597,52 +1942,65 @@
 			pwrsrc_dis_reason &= ~HTC_BATT_PWRSRC_DIS_BIT_MFG;
 		}
 
+		if (is_bounding_fully_charged_level_dis_batt_chg())
+			chg_dis_reason |= HTC_BATT_CHG_DIS_BIT_STOP_SWOLLEN;
+		else
+			chg_dis_reason &= ~HTC_BATT_CHG_DIS_BIT_STOP_SWOLLEN;
+
 		if (htc_batt_info.rep.over_vchg)
 			chg_dis_reason |= HTC_BATT_CHG_DIS_BIT_OVP;
 		else
 			chg_dis_reason &= ~HTC_BATT_CHG_DIS_BIT_OVP;
 
-
+		
 		if (pwrsrc_dis_reason)
 			pwrsrc_enabled = 0;
 		else
 			pwrsrc_enabled = 1;
 
-
+		
 		if (chg_dis_reason & chg_dis_control_mask)
 			charging_enabled = HTC_PWR_SOURCE_TYPE_BATT;
 		else
 			charging_enabled = htc_batt_info.rep.charging_source;
 
-
+		
 		if (chg_dis_reason & chg_dis_active_mask)
 			htc_batt_info.rep.charging_enabled = HTC_PWR_SOURCE_TYPE_BATT;
 		else
 			htc_batt_info.rep.charging_enabled =
 										htc_batt_info.rep.charging_source;
 
-
+		
 		pr_info("[BATT] prev_chg_src=%d, prev_chg_en=%d,"
 				" chg_dis_reason/control/active=0x%x/0x%x/0x%x,"
-				" chg_limit_reason=0x%x,"
+				" chg_limit_reason/active=0x%x/0x%x,"
 				" pwrsrc_dis_reason=0x%x, prev_pwrsrc_enabled=%d,"
-				" context_state=0x%x,"
+				" context_state=0x%x, pre_screen/cur_screen=%d/%d, "
 				" htc_extension=0x%x, sw_stimer_counter=%ld\n",
 					prev_chg_src, prev_charging_enabled,
 					chg_dis_reason,
 					chg_dis_reason & chg_dis_control_mask,
 					chg_dis_reason & chg_dis_active_mask,
 					chg_limit_reason,
+					chg_limit_active_mask,
 					pwrsrc_dis_reason, prev_pwrsrc_enabled,
-					context_state,
+					context_state, pre_screen_state, screen_state,
 					htc_batt_info.htc_extension,
 					sw_stimer_counter);
+
+		
+		if(htc_batt_info.icharger->is_pmic_aicl_enable != NULL)
+			pmic_aicl_enabled = htc_batt_info.icharger->is_pmic_aicl_enable();
+
 		if (charging_enabled != prev_charging_enabled ||
 				prev_chg_src != htc_batt_info.rep.charging_source ||
 				first ||
-				pwrsrc_enabled != prev_pwrsrc_enabled) {
-
+				pwrsrc_enabled != prev_pwrsrc_enabled ||
+				((pre_screen_state != screen_state) && pmic_aicl_enabled)) {
+			
 			if (prev_chg_src != htc_batt_info.rep.charging_source ||
+					pre_screen_state != screen_state ||
 					first) {
 				BATT_LOG("set_pwrsrc_and_charger_enable(%d, %d, %d)",
 							htc_batt_info.rep.charging_source,
@@ -1672,11 +2030,11 @@
 			}
 		}
 	} else {
-
+		
 		if (prev_chg_src != htc_batt_info.rep.charging_source || first) {
-			chg_dis_reason = 0;
-			charging_enabled = 0;
-			pwrsrc_enabled = 0;
+			chg_dis_reason = 0; 
+			charging_enabled = 0; 
+			pwrsrc_enabled = 0; 
 			BATT_LOG("set_pwrsrc_and_charger_enable(%d, %d, %d)",
 						HTC_PWR_SOURCE_TYPE_BATT,
 						charging_enabled,
@@ -1686,22 +2044,36 @@
 				htc_batt_info.icharger->set_pwrsrc_and_charger_enable(
 								HTC_PWR_SOURCE_TYPE_BATT,
 								charging_enabled, pwrsrc_enabled);
-
+			
 			htc_batt_info.rep.charging_enabled =
 								htc_batt_info.rep.charging_source;
 		}
 	}
 
 
+	
+	if(htc_batt_info.icharger->is_pj_enable
+		&& htc_batt_info.icharger->is_pj_enable() > 0
+		&& htc_batt_info.icharger->set_pj_chg_control
+		&& htc_batt_info.icharger->get_pj_chg_control
+		&& htc_batt_info.icharger->pj_exist_detect
+		&& htc_batt_info.igauge->get_pj_voltage
+		&& htc_batt_info.icharger->get_pj_exist
+		&& htc_batt_info.igauge->is_pj_full
+		&& htc_batt_info.igauge->calculate_pj_level)
+		power_jacket_info_update();
+
+
+	
 	if (htc_batt_info.icharger) {
 		htc_batt_info.icharger->dump_all();
 	}
 
 
-
+	
 	htc_battery_core_update_changed();
 
-
+	
 	if (0 <= critical_alarm_level &&
 					critical_alarm_level < critical_alarm_level_set) {
 		critical_alarm_level_set = critical_alarm_level;
@@ -1714,6 +2086,7 @@
 	first = 0;
 	prev_charging_enabled = charging_enabled;
 	prev_pwrsrc_enabled = pwrsrc_enabled;
+	pre_screen_state = screen_state;
 
 	wake_unlock(&htc_batt_timer.battery_lock);
 	pr_info("[BATT] %s: done\n", __func__);
@@ -1789,7 +2162,7 @@
 			htc_batt_info.rep.level);
 
 #ifdef CONFIG_HTC_BATT_ALARM
-
+		
 		if (screen_state == 1) {
 			if (battery_vol_alarm_mode !=
 				BATT_ALARM_CRITICAL_MODE)
@@ -1830,7 +2203,7 @@
 		break;
 	}
 	case HTC_BATT_IOCTL_SET_ALARM_TIMER_FLAG: {
-
+		
 		unsigned int flag;
 		if (copy_from_user(&flag, (void *)arg, sizeof(unsigned int))) {
 			BATT_ERR("Set timer type into alarm failed!");
@@ -1861,7 +2234,7 @@
 static void mbat_in_func(struct work_struct *work)
 {
 #if defined(CONFIG_MACH_RUBY) || defined(CONFIG_MACH_HOLIDAY) || defined(CONFIG_MACH_VIGOR)
-
+	
 #define LTE_GPIO_MBAT_IN (61)
 	if (gpio_get_value(LTE_GPIO_MBAT_IN) == 0) {
 		pr_info("re-enable MBAT_IN irq!! due to false alarm\n");
@@ -1915,8 +2288,8 @@
 static void htc_battery_early_suspend(struct early_suspend *h)
 {
 	htc_batt_info.state |= STATE_EARLY_SUSPEND;
-#ifdef CONFIG_HTC_BATT_ALARM
 	screen_state = 0;
+#ifdef CONFIG_HTC_BATT_ALARM
 	batt_set_voltage_alarm_mode(BATT_ALARM_DISABLE_MODE);
 #endif
 	htc_batt_schedule_batt_info_update();
@@ -1926,13 +2299,13 @@
 static void htc_battery_late_resume(struct early_suspend *h)
 {
 	htc_batt_info.state &= ~STATE_EARLY_SUSPEND;
-#ifdef CONFIG_HTC_BATT_ALARM
 	screen_state = 1;
+#ifdef CONFIG_HTC_BATT_ALARM
 	batt_set_voltage_alarm_mode(BATT_ALARM_CRITICAL_MODE);
 #endif
 	htc_batt_schedule_batt_info_update();
 }
-#endif
+#endif 
 
 #define CHECH_TIME_TOLERANCE_MS	(1000)
 static int htc_battery_prepare(struct device *dev)
@@ -1966,7 +2339,7 @@
 
 	interval = ktime_set(check_time - htc_batt_timer.total_time_ms / 1000, 0);
 	next_alarm_sec = div_s64(interval.tv64, NSEC_PER_SEC);
-
+	
 	if (next_alarm_sec <= 1) {
 		BATT_LOG("%s: passing time:%lu ms, trigger batt_work immediately."
 			"(suspend_highfreq_check_reason=0x%x), "
@@ -2042,6 +2415,11 @@
 	.complete = htc_battery_complete,
 };
 
+int get_screen_state(void)
+{
+	return screen_state;
+}
+
 static int htc_battery_probe(struct platform_device *pdev)
 {
 	int i, rc = 0;
@@ -2083,6 +2461,8 @@
 	htc_battery_core_ptr->func_get_battery_info = htc_batt_get_battery_info;
 	htc_battery_core_ptr->func_charger_control = htc_batt_charger_control;
 	htc_battery_core_ptr->func_set_full_level = htc_batt_set_full_level;
+	htc_battery_core_ptr->func_set_full_level_dis_batt_chg =
+											htc_batt_set_full_level_dis_batt_chg;
 	htc_battery_core_ptr->func_set_max_input_current = htc_batt_set_max_input_current;
 	htc_battery_core_ptr->func_context_event_handler =
 											htc_batt_context_event_handler;
@@ -2102,7 +2482,7 @@
 	for (i = 0; i < ADC_REPLY_ARRAY_SIZE; i++)
 		htc_batt_info.adc_vref[i] = 66;
 
-
+	
 	htc_batt_info.critical_low_voltage_mv = pdata->critical_low_voltage_mv;
 	if (pdata->critical_alarm_vol_ptr) {
 		htc_batt_info.critical_alarm_vol_ptr = pdata->critical_alarm_vol_ptr;
@@ -2112,10 +2492,14 @@
 	}
 	htc_batt_info.overload_vol_thr_mv = pdata->overload_vol_thr_mv;
 	htc_batt_info.overload_curr_thr_ma = pdata->overload_curr_thr_ma;
+	htc_batt_info.smooth_chg_full_delay_min = pdata->smooth_chg_full_delay_min;
 	chg_limit_active_mask = pdata->chg_limit_active_mask;
 	htc_batt_info.igauge = &pdata->igauge;
 	htc_batt_info.icharger = &pdata->icharger;
 	htc_batt_info.get_thermal_sensor_temp = pdata->get_thermal_sensor_temp;
+	htc_batt_info.shutdown_voltage = 0;
+	if (pdata->shutdown_voltage_critiria_setting)
+		htc_batt_info.shutdown_voltage = pdata->shutdown_voltage_critiria_setting;
 
 #if 0
 	htc_batt_info.mpp_config = &pdata->mpp_data;
@@ -2124,6 +2508,9 @@
 	INIT_WORK(&htc_batt_timer.batt_work, batt_worker);
 	INIT_DELAYED_WORK(&htc_batt_timer.unknown_usb_detect_work,
 							unknown_usb_detect_worker);
+	INIT_DELAYED_WORK(&htc_batt_timer.calculate_pj_level_work,
+							calculate_pj_level_worker);
+
 	init_timer(&htc_batt_timer.batt_timer);
 	htc_batt_timer.batt_timer.function = batt_regular_timer_handler;
 	alarm_init(&htc_batt_timer.batt_check_wakeup_alarm,
@@ -2168,7 +2555,7 @@
 		htc_batt_info.icharger->charger_change_notifier_register(
 											&cable_status_notifier);
 
-
+	
 	if ((htc_batt_info.icharger->sw_safetytimer) &&
 			!(get_kernel_flag() & KERNEL_FLAG_KEEP_CHARG_ON) &&
 			!(get_kernel_flag() & KERNEL_FLAG_PA_RECHARG_TEST))
@@ -2179,7 +2566,7 @@
 
 		}
 
-
+	
 	if((get_kernel_flag() & KERNEL_FLAG_KEEP_CHARG_ON) || (get_kernel_flag() & KERNEL_FLAG_PA_RECHARG_TEST))
 	{
 		chg_limit_active_mask = 0;
@@ -2228,6 +2615,8 @@
 			"htc_voltage_alarm");
 	wake_lock_init(&batt_shutdown_wake_lock, WAKE_LOCK_SUSPEND,
 			"batt_shutdown");
+	wake_lock_init(&htc_batt_timer.calculate_pj_level_lock,
+			WAKE_LOCK_SUSPEND, "calculate_pj_level");
 	mutex_init(&htc_batt_info.info_lock);
 	mutex_init(&htc_batt_timer.schedule_lock);
 	mutex_init(&cable_notifier_lock);
@@ -2237,7 +2626,7 @@
 	mutex_init(&batt_set_alarm_lock);
 #endif
 
-
+	
 	htc_batt_info.rep.batt_vol = 3700;
 	htc_batt_info.rep.batt_id = 1;
 	htc_batt_info.rep.batt_temp = 250;
@@ -2248,19 +2637,25 @@
 	htc_batt_info.rep.batt_state = 0;
 	htc_batt_info.rep.temp_fault = -1;
 	htc_batt_info.rep.overload = 0;
+	htc_batt_info.rep.pj_src = 0;
+	htc_batt_info.rep.pj_chg_status = 0;
+	htc_batt_info.rep.pj_full = PJ_NOT_FULL;
+	htc_batt_info.rep.pj_vol = 0;
+	htc_batt_info.rep.full_level_dis_batt_chg = 100;
 	htc_batt_timer.total_time_ms = 0;
 	htc_batt_timer.batt_system_jiffies = jiffies;
 	htc_batt_timer.batt_alarm_status = 0;
 	htc_batt_timer.alarm_timer_flag = 0;
 
+	screen_state = 1;
+	pre_screen_state = 1;
 #ifdef CONFIG_HTC_BATT_ALARM
 	battery_vol_alarm_mode = BATT_ALARM_NORMAL_MODE;
-	screen_state = 1;
 	alarm_data.lower_threshold = 2800;
 	alarm_data.upper_threshold = 4400;
 #endif
 
-
+	
 
 	platform_driver_register(&htc_battery_driver);
 
diff --git a/arch/arm/mach-msm/htc/htc_battery_cell.c b/arch/arm/mach-msm/htc/htc_battery_cell.c
index 5ca53cd..d9266f1 100644
--- a/arch/arm/mach-msm/htc/htc_battery_cell.c
+++ b/arch/arm/mach-msm/htc/htc_battery_cell.c
@@ -17,9 +17,9 @@
 #include <linux/err.h>
 #include <mach/htc_battery_cell.h>
 
-static struct htc_battery_cell *cells;
-static int cell_num;
-static struct htc_battery_cell *cur_cell;
+static struct htc_battery_cell *cells;	
+static int cell_num;					
+static struct htc_battery_cell *cur_cell; 
 
 static unsigned int hv_authenticated;
 
@@ -34,6 +34,7 @@
 	.voltage_min = 3200,
 	.chg_param = NULL,
 	.gauge_param = NULL,
+	.pj_param = NULL,
 };
 
 int htc_battery_cell_init(struct htc_battery_cell *ary, int ary_size)
@@ -96,6 +97,13 @@
 	return NULL;
 }
 
+inline void *htc_battery_cell_get_cur_cell_pj_cdata(void)
+{
+	if (cur_cell)
+		return cur_cell->pj_param;
+	return NULL;
+}
+
 inline struct htc_battery_cell *htc_battery_cell_find(int id_raw)
 {
 	int i = 0;
@@ -112,7 +120,7 @@
 	}
 	pr_err("[BATT] %s: cell id can not be identified (id_raw=%d)\n",
 			__func__, id_raw);
-
+	
 	return pcell;
 }
 
@@ -127,19 +135,19 @@
 		pr_err("[BATT] cell pointer is NULL so unknown ID is return.\n");
 		return HTC_BATTERY_CELL_ID_UNKNOWN;
 	}
-
+	
 	if (cur_cell == pcell)
 		return pcell->id;
-
+	
 	if (cur_cell) {
 		if (pcell->id == HTC_BATTERY_CELL_ID_UNKNOWN) {
 			unknown_count++;
 			if (unknown_count < HTC_BATTERY_CELL_CHECK_UNKNOWN_COUNT)
-				return cur_cell->id;
+				return cur_cell->id; 
 		} else
 			unknown_count = 0;
 	} else {
-
+		
 		pr_warn("[BATT]warn: cur_cell is initiated by %s", __func__);
 		cur_cell = pcell;
 		return pcell->id;
@@ -164,7 +172,7 @@
 		hv_authenticated = 0;
 		pr_info("[BATT] HV authentication failed.\n");
 	}
-	return 0;
+	return 0; 
 }
 __setup("androidboot.dq=", check_dq_setup);
 
diff --git a/arch/arm/mach-msm/htc/htc_battery_core.c b/arch/arm/mach-msm/htc/htc_battery_core.c
index feb160f..76303b5 100644
--- a/arch/arm/mach-msm/htc/htc_battery_core.c
+++ b/arch/arm/mach-msm/htc/htc_battery_core.c
@@ -82,6 +82,7 @@
 static struct work_struct batt_charger_ctrl_work;
 struct workqueue_struct *batt_charger_ctrl_wq;
 static unsigned int charger_ctrl_stat;
+static unsigned int phone_call_stat;
 
 static int test_power_monitor;
 
@@ -283,6 +284,30 @@
 	return count;
 }
 
+static ssize_t htc_battery_set_full_level_dis_batt_chg(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int rc = 0;
+	unsigned long percent = 100;
+
+	rc = strict_strtoul(buf, 10, &percent);
+	if (rc)
+		return rc;
+
+	if (percent > 100 || percent == 0)
+		return -EINVAL;
+
+	if (!battery_core_info.func.func_set_full_level_dis_batt_chg) {
+		BATT_ERR("No set full level (disable battery charging only) function!");
+		return -ENOENT;
+	}
+
+	battery_core_info.func.func_set_full_level_dis_batt_chg(percent);
+
+	return count;
+}
+
 int htc_battery_charger_disable()
 {
 	int rc = 0;
@@ -372,6 +397,17 @@
 	return count;
 }
 
+static ssize_t htc_battery_phone_call_stat(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	int i = 0;
+
+	i += scnprintf(buf + i, PAGE_SIZE - i, "%u\n", phone_call_stat);
+
+	return i;
+}
+
 static ssize_t htc_battery_set_phone_call(struct device *dev,
 				struct device_attribute *attr,
 				const char *buf, size_t count)
@@ -395,6 +431,8 @@
 	else
 		battery_core_info.func.func_context_event_handler(EVENT_TALK_STOP);
 
+	 phone_call_stat = phone_call;
+
 	return count;
 }
 static ssize_t htc_battery_set_network_search(struct device *dev,
@@ -476,6 +514,35 @@
 	return count;
 }
 
+static ssize_t htc_battery_set_disable_limit_chg(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int rc = 0;
+	unsigned long disable_limit_chg = 0;
+
+	rc = strict_strtoul(buf, 10, &disable_limit_chg);
+	if (rc)
+		return rc;
+
+	BATT_LOG("Set context disable_limit_chg = %lu", disable_limit_chg);
+
+	if((disable_limit_chg != 0) && (disable_limit_chg != 1))
+		return -EINVAL;
+
+	if (!battery_core_info.func.func_context_event_handler) {
+		BATT_ERR("No context_event_notify function!");
+		return -ENOENT;
+	}
+
+	if (disable_limit_chg)
+		battery_core_info.func.func_context_event_handler(EVENT_DAYDREAM_START);
+	else
+		battery_core_info.func.func_context_event_handler(EVENT_DAYDREAM_STOP);
+
+	return count;
+}
+
 static struct device_attribute htc_battery_attrs[] = {
 	HTC_BATTERY_ATTR(batt_id),
 	HTC_BATTERY_ATTR(batt_vol),
@@ -486,6 +553,10 @@
 	HTC_BATTERY_ATTR(full_bat),
 	HTC_BATTERY_ATTR(over_vchg),
 	HTC_BATTERY_ATTR(batt_state),
+	HTC_BATTERY_ATTR(batt_overload),
+	HTC_BATTERY_ATTR(pj_exist),
+	HTC_BATTERY_ATTR(pj_status),
+	HTC_BATTERY_ATTR(pj_level),
 
 	__ATTR(batt_attr_text, S_IRUGO, htc_battery_show_batt_attr, NULL),
 	__ATTR(batt_power_meter, S_IRUGO, htc_battery_show_cc_attr, NULL),
@@ -496,13 +567,15 @@
 	__ATTR(delta, S_IWUSR | S_IWGRP, NULL, htc_battery_set_delta),
 	__ATTR(full_level, S_IWUSR | S_IWGRP, NULL,
 		htc_battery_set_full_level),
+	__ATTR(full_level_dis_batt_chg, S_IWUSR | S_IWGRP, NULL,
+		htc_battery_set_full_level_dis_batt_chg),
 	__ATTR(batt_debug_flag, S_IWUSR | S_IWGRP, NULL,
 		htc_battery_debug_flag),
 	__ATTR(charger_control, S_IWUSR | S_IWGRP, htc_battery_charger_stat,
 		htc_battery_charger_switch),
 	__ATTR(charger_timer, S_IWUSR | S_IWGRP, NULL,
 		htc_battery_charger_ctrl_timer),
-	__ATTR(phone_call, S_IWUSR | S_IWGRP, NULL,
+	__ATTR(phone_call, S_IWUSR | S_IWGRP, htc_battery_phone_call_stat,
 		htc_battery_set_phone_call),
 	__ATTR(network_search, S_IWUSR | S_IWGRP, NULL,
 		htc_battery_set_network_search),
@@ -510,12 +583,16 @@
 		htc_battery_set_navigation),
 	__ATTR(context_event, S_IWUSR | S_IWGRP, NULL,
 		htc_battery_set_context_event),
+	__ATTR(disable_limit_chg, S_IWUSR | S_IWGRP, NULL,
+		htc_battery_set_disable_limit_chg),
 };
 
 static struct device_attribute htc_battery_rt_attrs[] = {
 	__ATTR(batt_vol_now, S_IRUGO, htc_battery_rt_attr_show, NULL),
 	__ATTR(batt_current_now, S_IRUGO, htc_battery_rt_attr_show, NULL),
 	__ATTR(batt_temp_now, S_IRUGO, htc_battery_rt_attr_show, NULL),
+	__ATTR(pj_exist_now, S_IRUGO, htc_battery_rt_attr_show, NULL),
+	__ATTR(pj_vol_now, S_IRUGO, htc_battery_rt_attr_show, NULL),
 };
 
 
@@ -702,6 +779,29 @@
 		i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
 				battery_core_info.rep.overload);
 		break;
+	case PJ_EXIST:
+		i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
+				battery_core_info.rep.pj_src);
+		break;
+	case PJ_STATUS:
+		
+		if (battery_core_info.rep.pj_full == 3)	{
+			if ((battery_core_info.rep.pj_level - battery_core_info.rep.pj_level_pre) >= 19)
+				BATT_LOG("level diff over 19, level:%d, pre_level:%d\n",
+					battery_core_info.rep.pj_level, battery_core_info.rep.pj_level_pre);
+			else
+				i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", HTC_UI_PJ_FULL);
+		} else { 
+			if (battery_core_info.rep.pj_chg_status == 2 || battery_core_info.rep.charging_enabled)
+				i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", HTC_UI_PJ_CHG);
+			else
+				i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", HTC_UI_PJ_NOT_CHG);
+		}
+		break;
+	case PJ_LEVEL:
+		i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
+				battery_core_info.rep.pj_level);
+		break;
 	default:
 		i = -EINVAL;
 	}
@@ -831,9 +931,18 @@
 		if (CHARGER_USB == battery_core_info.rep.charging_source ||
 			CHARGER_USB == new_batt_info_rep.charging_source)
 			is_send_usb_uevent = 1;
+		if (CHARGER_DETECTING == battery_core_info.rep.charging_source ||
+			CHARGER_DETECTING == new_batt_info_rep.charging_source)
+			is_send_usb_uevent = 1;
+		if (CHARGER_UNKNOWN_USB == battery_core_info.rep.charging_source ||
+			CHARGER_UNKNOWN_USB == new_batt_info_rep.charging_source)
+			is_send_usb_uevent = 1;
 		if (CHARGER_AC == battery_core_info.rep.charging_source ||
 			CHARGER_AC == new_batt_info_rep.charging_source)
 			is_send_ac_uevent = 1;
+		if (CHARGER_9V_AC == battery_core_info.rep.charging_source ||
+			CHARGER_9V_AC == new_batt_info_rep.charging_source)
+			is_send_ac_uevent = 1;
 		if (CHARGER_MHL_AC == battery_core_info.rep.charging_source ||
 			CHARGER_MHL_AC == new_batt_info_rep.charging_source)
 			is_send_ac_uevent = 1;
@@ -846,7 +955,10 @@
 		((battery_core_info.rep.level != new_batt_info_rep.level) ||
 		(battery_core_info.rep.batt_vol != new_batt_info_rep.batt_vol) ||
 		(battery_core_info.rep.over_vchg != new_batt_info_rep.over_vchg) ||
-		(battery_core_info.rep.batt_temp != new_batt_info_rep.batt_temp))) {
+		(battery_core_info.rep.batt_temp != new_batt_info_rep.batt_temp) ||
+		(battery_core_info.rep.pj_full!= new_batt_info_rep.pj_full) ||
+		(battery_core_info.rep.pj_src!= new_batt_info_rep.pj_src) ||
+		(battery_core_info.rep.pj_chg_status!= new_batt_info_rep.pj_chg_status))) {
 		is_send_batt_uevent = 1;
 	}
 
@@ -858,7 +970,7 @@
 			battery_over_loading = 0;
 	}
 
-
+	
 	if (battery_core_info.func.func_notify_pnpmgr_charging_enabled) {
 		if (battery_core_info.rep.charging_enabled !=
 				new_batt_info_rep.charging_enabled)
@@ -876,11 +988,11 @@
 			battery_core_info.rep.batt_temp = 680;
 		}
 	} else {
-
+		
 		batt_temp_over_68c_count = 0;
 	}
 
-
+	
 	if (test_power_monitor) {
 		BATT_LOG("test_power_monitor is set: overwrite fake batt info.");
 		battery_core_info.rep.batt_id = 77;
@@ -929,7 +1041,7 @@
 				battery_core_info.htc_charge_full = 0;
 		}
 
-
+		
 		if (battery_over_loading >= 2) {
 			battery_core_info.htc_charge_full = 0;
 			battery_over_loading = 0;
@@ -940,8 +1052,8 @@
 	mutex_unlock(&battery_core_info.info_lock);
 
 	BATT_LOG("ID=%d,level=%d,level_raw=%d,vol=%d,temp=%d,current=%d,"
-		"chg_src=%d,chg_en=%d,full_bat=%d,over_vchg=%d,"
-		"batt_state=%d,overload=%d,ui_chg_full=%d",
+		"chg_src=%d,chg_en=%d,pj_src=%d,pj_level=%d,full_bat=%d,"
+		"over_vchg=%d,batt_state=%d,overload=%d,ui_chg_full=%d",
 			battery_core_info.rep.batt_id,
 			battery_core_info.rep.level,
 			battery_core_info.rep.level_raw,
@@ -950,6 +1062,8 @@
 			battery_core_info.rep.batt_current,
 			battery_core_info.rep.charging_source,
 			battery_core_info.rep.charging_enabled,
+			battery_core_info.rep.pj_src,
+			battery_core_info.rep.pj_level,
 			battery_core_info.rep.full_bat,
 			battery_core_info.rep.over_vchg,
 			battery_core_info.rep.batt_state,
@@ -957,7 +1071,7 @@
 			battery_core_info.htc_charge_full);
 
 
-
+	
 	if (is_send_batt_uevent) {
 		power_supply_changed(&htc_power_supplies[BATTERY_SUPPLY]);
 		BATT_LOG("power_supply_changed: battery");
@@ -1022,11 +1136,14 @@
 	if (htc_battery->func_set_full_level)
 		battery_core_info.func.func_set_full_level =
 					htc_battery->func_set_full_level;
+	if (htc_battery->func_set_full_level_dis_batt_chg)
+		battery_core_info.func.func_set_full_level_dis_batt_chg =
+					htc_battery->func_set_full_level_dis_batt_chg;
 	if (htc_battery->func_notify_pnpmgr_charging_enabled)
 		battery_core_info.func.func_notify_pnpmgr_charging_enabled =
 					htc_battery->func_notify_pnpmgr_charging_enabled;
 
-
+	
 	for (i = 0; i < ARRAY_SIZE(htc_power_supplies); i++) {
 		rc = power_supply_register(dev, &htc_power_supplies[i]);
 		if (rc)
@@ -1034,10 +1151,10 @@
 				" (%d)\n", rc);
 	}
 
-
+	
 	htc_battery_create_attrs(htc_power_supplies[CHARGER_BATTERY].dev);
 
-
+	
 	charger_ctrl_stat = ENABLE_CHARGER;
 	INIT_WORK(&batt_charger_ctrl_work, batt_charger_ctrl_func);
 	alarm_init(&batt_charger_ctrl_alarm,
@@ -1046,7 +1163,7 @@
 	batt_charger_ctrl_wq =
 			create_singlethread_workqueue("charger_ctrl_timer");
 
-
+	
 	battery_core_info.update_time = jiffies;
 	battery_core_info.present = 1;
 	battery_core_info.htc_charge_full = 0;
@@ -1059,9 +1176,10 @@
 	battery_core_info.rep.level_raw = 0;
 	battery_core_info.rep.full_bat = 1580000;
 	battery_core_info.rep.full_level = 100;
-
+	battery_core_info.rep.full_level_dis_batt_chg = 100;
+	
 	battery_core_info.rep.temp_fault = -1;
-
+	
 	battery_core_info.rep.batt_state = 0;
 	battery_core_info.rep.overload = 0;
 
diff --git a/arch/arm/mach-msm/include/mach/htc_battery_8960.h b/arch/arm/mach-msm/include/mach/htc_battery_8960.h
index d1b1bb1..6419af4 100644
--- a/arch/arm/mach-msm/include/mach/htc_battery_8960.h
+++ b/arch/arm/mach-msm/include/mach/htc_battery_8960.h
@@ -117,10 +117,12 @@
 	int critical_alarm_vol_cols;
 	int overload_vol_thr_mv;
 	int overload_curr_thr_ma;
+	int smooth_chg_full_delay_min;
 	struct htc_gauge igauge;
 	struct htc_charger icharger;
 	int (*get_thermal_sensor_temp)(int sensor_num, unsigned long *temp);
 	int (*notify_pnpmgr_charging_enabled)(int charging_enabled);
+	int shutdown_voltage_critiria_setting;
 };
 
 enum {
@@ -129,4 +131,6 @@
 	BATT_ALARM_CRITICAL_MODE,
 };
 
+void get_pj_status(int *is_full, int *status, int *exist);
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/htc_battery_cell.h b/arch/arm/mach-msm/include/mach/htc_battery_cell.h
index b8b55c2..b9bfed4 100644
--- a/arch/arm/mach-msm/include/mach/htc_battery_cell.h
+++ b/arch/arm/mach-msm/include/mach/htc_battery_cell.h
@@ -32,6 +32,7 @@
 	const int	voltage_min;
 	void *chg_param;	
 	void *gauge_param;	
+	void *pj_param; 
 };
 
 
@@ -52,6 +53,8 @@
 
 void *htc_battery_cell_get_cur_cell_gauge_cdata(void);
 
+void *htc_battery_cell_get_cur_cell_pj_cdata(void);
+
 int htc_battery_cell_hv_authenticated(void);
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/htc_battery_common.h b/arch/arm/mach-msm/include/mach/htc_battery_common.h
index 5119058..02250bb 100644
--- a/arch/arm/mach-msm/include/mach/htc_battery_common.h
+++ b/arch/arm/mach-msm/include/mach/htc_battery_common.h
@@ -55,7 +55,9 @@
 	EVENT_NETWORK_SEARCH_START,
 	EVENT_NETWORK_SEARCH_STOP,
 	EVENT_NAVIGATION_START,
-	EVENT_NAVIGATION_STOP
+	EVENT_NAVIGATION_STOP,
+	EVENT_DAYDREAM_START,
+	EVENT_DAYDREAM_STOP
 };
 
 
diff --git a/arch/arm/mach-msm/include/mach/htc_battery_core.h b/arch/arm/mach-msm/include/mach/htc_battery_core.h
index d21548e..cc6fc6f 100644
--- a/arch/arm/mach-msm/include/mach/htc_battery_core.h
+++ b/arch/arm/mach-msm/include/mach/htc_battery_core.h
@@ -51,16 +51,27 @@
 	OVER_VCHG,
 	BATT_STATE,
 	OVERLOAD,
+	PJ_EXIST,
+	PJ_STATUS,
+	PJ_LEVEL,
 };
 
 enum htc_batt_rt_attr {
 	HTC_BATT_RT_VOLTAGE = 0,
 	HTC_BATT_RT_CURRENT,
 	HTC_BATT_RT_TEMPERATURE,
+	HTC_PJ_RT_EXISTS,
+	HTC_PJ_RT_VOLTAGE,
 };
 
 struct battery_info_reply {
 	u32 batt_vol;
+	u32 pj_vol;
+	u32 pj_src;
+	u32 pj_chg_status;
+	u32 pj_full;
+	s32 pj_level;
+	s32 pj_level_pre;
 	u32 batt_id;
 	s32 batt_temp;
 	s32 batt_current;
@@ -71,6 +82,7 @@
 	u32 charging_enabled;
 	u32 full_bat;
 	u32 full_level;
+	u32 full_level_dis_batt_chg;
 	u32 over_vchg;
 	s32 temp_fault;
 	u32 batt_state;
@@ -86,6 +98,7 @@
 	int (*func_charger_control)(enum charger_control_flag);
 	int (*func_context_event_handler)(enum batt_context_event);
 	void (*func_set_full_level)(int full_level);
+	void (*func_set_full_level_dis_batt_chg)(int full_level_dis_batt_chg);
 	int (*func_set_max_input_current)(int target_ma);
 	int (*func_notify_pnpmgr_charging_enabled)(int charging_enabled);
 };
diff --git a/arch/arm/mach-msm/include/mach/htc_charger.h b/arch/arm/mach-msm/include/mach/htc_charger.h
index 19eb41b..011e381 100644
--- a/arch/arm/mach-msm/include/mach/htc_charger.h
+++ b/arch/arm/mach-msm/include/mach/htc_charger.h
@@ -32,17 +32,19 @@
 	HTC_CHARGER_EVENT_SRC_UNKNOWN_USB,
 	HTC_CHARGER_EVENT_SRC_UNDER_RATING,
 	HTC_CHARGER_EVENT_SAFETY_TIMEOUT,
+	HTC_CHARGER_EVENT_POWER_JACKET_IN,
+	HTC_CHARGER_EVENT_POWER_JACKET_OUT,
 };
 
 enum htc_charging_cfg {
-	HTC_CHARGER_CFG_LIMIT = 0,
+	HTC_CHARGER_CFG_LIMIT = 0,	
 	HTC_CHARGER_CFG_SLOW,
 	HTC_CHARGER_CFG_FAST,
 };
 
 enum htc_power_source_type {
-
-
+	
+	
 	HTC_PWR_SOURCE_TYPE_BATT = 0,
 	HTC_PWR_SOURCE_TYPE_USB,
 	HTC_PWR_SOURCE_TYPE_AC,
@@ -66,6 +68,24 @@
 	HTC_EXTCHG_EVENT_TYPE_MAX = 255,
 };
 
+enum htc_power_jacket_chg_status_type {
+	PJ_CHG_STATUS_OFF,
+	PJ_CHG_STATUS_DCHG,
+	PJ_CHG_STATUS_CHG,
+};
+
+enum htc_power_jacket_full_type {
+	PJ_NOT_FULL = 0,
+	PJ_FULL_DETECT,
+	PJ_FULL_DETECT_READ_VOL,
+	PJ_FULL,
+};
+
+enum power_jacket_exist {
+	PJ_OUT = 0,
+	PJ_IN,
+};
+
 struct htc_charger {
 	const char *name;
 	int ready;
@@ -93,6 +113,12 @@
 	int (*enable_5v_output)(bool enable);
 	int (*is_safty_timer_timeout)(int *result);
 	int (*is_battery_full_eoc_stop)(int *result);
+	int (*set_pj_chg_control)(int pj_to_batt,int batt_to_pj);
+	int (*get_pj_chg_control)(void);
+	int (*pj_exist_detect)(void);
+	int (*is_pj_enable)(void);
+	void (*get_pj_exist)(int *result);
+	int (*is_pmic_aicl_enable)(void);
 };
 
 int htc_charger_event_notify(enum htc_charger_event);
diff --git a/arch/arm/mach-msm/include/mach/htc_gauge.h b/arch/arm/mach-msm/include/mach/htc_gauge.h
index 0c39713..dc6e3ab 100644
--- a/arch/arm/mach-msm/include/mach/htc_gauge.h
+++ b/arch/arm/mach-msm/include/mach/htc_gauge.h
@@ -35,11 +35,14 @@
 	int (*get_battery_cc)(int *result);
 	int (*is_battery_temp_fault)(int *result);
 	int (*is_battery_full)(int *result);
+	int (*is_pj_full)(int *result);
+	void (*get_pj_voltage)(int *result);
+	int (*calculate_pj_level)(int vol, int is_charging, int batt_temp);
 #if 0
 	int (*dump_all)(void);
 #endif
 	int (*get_attr_text)(char *buf, int size);
-
+	
 	int (*register_lower_voltage_alarm_notifier)(void (*callback)(int));
 	int (*enable_lower_voltage_alarm)(int enable);
 	int (*set_lower_voltage_alarm_threshold)(int thres_mV);
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 662a517..7abd79c 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -47,6 +47,19 @@
 	POWER_SUPPLY_CHARGE_TYPE_FAST,
 };
 
+#ifdef CONFIG_HTC_BATT_8960
+enum {
+	POWER_SUPPLY_DISABLE_CHARGE = 0,
+	POWER_SUPPLY_ENABLE_SLOW_CHARGE,
+	POWER_SUPPLY_ENABLE_FAST_CHARGE,
+	POWER_SUPPLY_ENABLE_9VAC_CHARGE,
+	POWER_SUPPLY_ENABLE_WIRELESS_CHARGE,
+	POWER_SUPPLY_ENABLE_SLOW_HV_CHARGE,
+	POWER_SUPPLY_ENABLE_FAST_HV_CHARGE,
+	POWER_SUPPLY_ENABLE_INTERNAL,
+};
+#endif
+
 enum {
 	POWER_SUPPLY_HEALTH_UNKNOWN = 0,
 	POWER_SUPPLY_HEALTH_GOOD,
@@ -82,6 +95,15 @@
 	POWER_SUPPLY_SCOPE_DEVICE,
 };
 
+#ifdef CONFIG_HTC_BATT_8960
+enum {
+	HTC_UI_PJ_NOT_CHG = 0,
+	HTC_UI_PJ_CHG,
+	HTC_UI_PJ_FULL,
+	HTC_UI_PJ_EMPTY,
+};
+#endif
+
 enum power_supply_property {
 	/* Properties of type `int' */
 	POWER_SUPPLY_PROP_STATUS = 0,