RK3368 DDR: fix HDMI display abnormal when ddr change freq
[firefly-linux-kernel-4.4.55.git] / drivers / power / rk30_adc_battery.c
index 47d536cfe4d9b36119f31878f0c99a282a16111c..9cc477577a44e6a5141b08ca63f705f6ba797ee2 100644 (file)
@@ -71,9 +71,20 @@ module_param_named(dbg_level, rk30_battery_dbg_level, int, 0644);
 #define   NUM_CHARGE_FULL_DELAY_TIMES         ((CHARGE_FULL_DELAY_TIMES * 1000) / TIMER_MS_COUNTS)     //³äµçÂú״̬³ÖÐøʱ¼ä³¤¶È
 #define   NUM_USBCHARGE_IDENTIFY_TIMES      ((USBCHARGE_IDENTIFY_TIMES * 1000) / TIMER_MS_COUNTS)      //³äµçÂú״̬³ÖÐøʱ¼ä³¤¶È
 
-#define BAT_2V5_VALUE                                       2500
+#define   CHARGE_IS_OK                    1
+#define   INVALID_CHARGE_CHECK               -1
+
+#if defined(CONFIG_ARCH_RK3066B)
+
+#define  BAT_DEFINE_VALUE                                           1800
+#elif defined(CONFIG_ARCH_RK2928)
+#define  BAT_DEFINE_VALUE                                                3300
+#else
+#define  BAT_DEFINE_VALUE                                           2500
+
+
+#endif
 
-#define BATT_NUM                                                   52
 #define BATT_FILENAME "/data/bat_last_capacity.dat"
 
 static struct wake_lock batt_wake_lock;
@@ -92,9 +103,12 @@ struct batt_vol_cal{
 #define BATT_NOMAL_VOL_VALUE                         3800               
 //divider resistance 
 #define BAT_PULL_UP_R                                         200
+#if defined(CONFIG_ARCH_RK3066B)
+#define BAT_PULL_DOWN_R                                    100
+#else
 #define BAT_PULL_DOWN_R                                    200
-
-static struct batt_vol_cal  batt_table[BATT_NUM] = {
+#endif
+static struct batt_vol_cal  batt_table[] = {
        {0,3400,3520},{1,3420,3525},{2,3420,3575},{3,3475,3600},{5,3505,3620},{7,3525,3644},
        {9,3540,3662},{11,3557,3670},{13,3570,3684},{15,3580,3700},{17,3610,3715},
        {19,3630,3720},{21,3640,3748},{23,3652,3756},{25,3662,3775},{27,3672,3790},
@@ -116,8 +130,8 @@ static struct batt_vol_cal  batt_table[BATT_NUM] = {
 #define BAT_PULL_UP_R                                         300 
 #define BAT_PULL_DOWN_R                                    100
 
-static struct batt_vol_cal  batt_table[BATT_NUM] = {
-       {0,6800,7400},    {1,6840,7440},     {2,6880,7480},     {3,6950,7450},       {5,7010,7510},    {7,7050,7550},
+static struct batt_vol_cal  batt_table[] = {
+       {0,6800,7400},    {1,6840,7440},    {2,6880,7480},     {3,6950,7450},       {5,7010,7510},    {7,7050,7550},
        {9,7080,7580},    {11,7104,7604},   {13,7140,7640},   {15,7160,7660},      {17,7220,7720},
        {19,7260,7760},  {21,7280,7780},   {23,7304,7802},   {25,7324,7824},      {27,7344,7844},
        {29,7360,7860},  {31,7374,7874},   {33,7386,7886},   {35,7398,7898},      {37,7410,7910},//500
@@ -131,7 +145,10 @@ static struct batt_vol_cal  batt_table[BATT_NUM] = {
 };
 #endif
 
-#define adc_to_voltage(adc_val)                           ((adc_val * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R))
+
+#define BATT_NUM  ARRAY_SIZE(batt_table)
+
+#define adc_to_voltage(adc_val)                           ((adc_val * BAT_DEFINE_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R))
 
 /********************************************************************************/
 
@@ -263,39 +280,48 @@ static int rk30_adc_battery_get_charge_level(struct rk30_adc_battery_data *bat)
                        charge_on = 1;
                }
        }
+       else{
+               if(pdata->is_dc_charging)
+                       charge_on =pdata->is_dc_charging();
+       }
+       
+               
 #endif
+#if 1
+       if (pdata->spport_usb_charging)  //is usb charging 
+               if(pdata->is_usb_charging)
+                       charge_on = pdata->is_usb_charging();
 
-#if defined  (CONFIG_BATTERY_RK30_USB_CHARGE)
-       if (charge_on == 0){
-               if (suspend_flag)
-                       return;
-               if (1 == dwc_vbus_status()) {          //¼ì²âµ½USB²åÈ룬µ«ÊÇÎÞ·¨Ê¶±ðÊÇ·ñÊdzäµçÆ÷
-                                                //ͨ¹ýÑÓʱ¼ì²âPCʶ±ð±êÖ¾£¬Èç¹û³¬Ê±¼ì²â²»µ½£¬ËµÃ÷Êdzäµç
-                       if (0 == get_msc_connect_flag()){                               //²åÈë³äµçÆ÷ʱ¼ä´óÓÚÒ»¶¨Ê±¼äÖ®ºó£¬¿ªÊ¼½øÈë³äµç״̬
-                               if (++gBatUsbChargeCnt >= NUM_USBCHARGE_IDENTIFY_TIMES){
-                                       gBatUsbChargeCnt = NUM_USBCHARGE_IDENTIFY_TIMES + 1;
-                                       charge_on = 1;
-                               }
-                       }                               //·ñÔò£¬²»½øÈë³äµçģʽ
-               }                   
-               else{
-                       gBatUsbChargeCnt = 0;
-                       if (2 == dwc_vbus_status()) {
-                               charge_on = 1;
-                       }
-               }
-       }
 #endif
        return charge_on;
 }
+static int  is_charge_ok(struct rk30_adc_battery_data *bat)
+{
+       int charge_is_ok = 0;
+       struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+
+       if((pdata->charge_ok_pin == INVALID_GPIO)&& ( pdata->charging_ok == NULL))
+               return -1;
+       
+       if (pdata->charge_ok_pin != INVALID_GPIO){              
+               if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level)
+               {
+                       charge_is_ok =1;
+               }
+       }else if( pdata->charging_ok)
+               {       
+               charge_is_ok = pdata->charging_ok();
+               }
+       return charge_is_ok;
+
+
+}
 
 //int old_charge_level;
 static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat)
 {
        int charge_level;
-       
-       struct rk30_adc_battery_platform_data *pdata = bat->pdata;
-
+//     struct rk30_adc_battery_platform_data *pdata = bat->pdata;
        charge_level = rk30_adc_battery_get_charge_level(bat);
 
        //¼ì²â³äµç״̬±ä»¯Çé¿ö
@@ -318,8 +344,9 @@ static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat)
                bat->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
        }
        else{
-       //CHARGE            
-               if (pdata->charge_ok_pin == INVALID_GPIO){  //no charge_ok_pin
+       //CHARGE        
+               if( is_charge_ok(bat)  ==  INVALID_CHARGE_CHECK){
+               //if (pdata->charge_ok_pin == INVALID_GPIO){  //no charge_ok_pin
 
                        if (bat->bat_capacity == 100){
                                if (bat->bat_status != POWER_SUPPLY_STATUS_FULL){
@@ -332,7 +359,7 @@ static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat)
                        }
                }
                else{  // pin of charge_ok_pin
-                       if (gpio_get_value(pdata->charge_ok_pin) != pdata->charge_ok_level){
+                       if (is_charge_ok(bat) != CHARGE_IS_OK ){
 
                                bat->full_times = 0;
                                bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
@@ -345,7 +372,7 @@ static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat)
                                        bat->full_times = NUM_CHARGE_FULL_DELAY_TIMES + 1;
                                }
 
-                               if ((bat->full_times >= NUM_CHARGE_FULL_DELAY_TIMES) && (bat->bat_capacity >= 99)){
+                               if ((bat->full_times >= NUM_CHARGE_FULL_DELAY_TIMES) && (bat->bat_capacity >= 95)){
                                        if (bat->bat_status != POWER_SUPPLY_STATUS_FULL){
                                                bat->bat_status = POWER_SUPPLY_STATUS_FULL;
                                                bat->bat_capacity = 100;
@@ -361,6 +388,32 @@ static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat)
 
        return charge_level;
 }
+//#define adc_to_voltage(adc_val)                           ((adc_val * BAT_DEFINE_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R))
+
+static int rk_adc_voltage(int value)
+{
+       int voltage;
+
+       int ref_voltage; //reference_voltage
+       int pullup_res;
+       int pulldown_res;
+
+       ref_voltage = gBatteryData ->pdata->reference_voltage;
+       pullup_res = gBatteryData ->pdata->pull_up_res;
+       pulldown_res = gBatteryData ->pdata->pull_down_res;
+
+       if(ref_voltage && pullup_res && pulldown_res){
+               
+               voltage =  ((value * ref_voltage * (pullup_res + pulldown_res)) / (1024 * pulldown_res));
+               
+       }else{
+               voltage = adc_to_voltage(value);        
+       }
+               
+               
+       return voltage;
+
+}
 
 static int *pSamples;
 static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat)
@@ -373,7 +426,7 @@ static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat)
        value = bat->adc_val;
        adc_async_read(bat->client);
 
-       *pSamples++ = adc_to_voltage(value);
+       *pSamples++ = rk_adc_voltage(value);
 
        bat->bat_status_cnt++;
        if (bat->bat_status_cnt > NUM_VOLTAGE_SAMPLE)  bat->bat_status_cnt = NUM_VOLTAGE_SAMPLE + 1;
@@ -418,7 +471,7 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba
 
        if (rk30_adc_battery_get_charge_level(bat)){  //charge
                if(BatVoltage >= (p[BATT_NUM - 1].charge_vol)){
-                       capacity = 100;
+                       capacity = 99;
                }       
                else{
                        if(BatVoltage <= (p[0].charge_vol)){
@@ -428,7 +481,7 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba
                                for(i = 0; i < BATT_NUM - 1; i++){
 
                                        if(((p[i].charge_vol) <= BatVoltage) && (BatVoltage < (p[i+1].charge_vol))){
-                                               capacity = p[i].disp_cal ;
+                                               capacity = p[i].disp_cal + ((BatVoltage - p[i].charge_vol) *  (p[i+1].disp_cal -p[i].disp_cal ))/ (p[i+1].charge_vol- p[i].charge_vol);
                                                break;
                                        }
                                }
@@ -447,7 +500,7 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba
                        else{
                                for(i = 0; i < BATT_NUM - 1; i++){
                                        if(((p[i].dis_charge_vol) <= BatVoltage) && (BatVoltage < (p[i+1].dis_charge_vol))){
-                                               capacity = p[i].disp_cal ;
+                                               capacity =  p[i].disp_cal+ ((BatVoltage - p[i].dis_charge_vol) * (p[i+1].disp_cal -p[i].disp_cal ) )/ (p[i+1].dis_charge_vol- p[i].dis_charge_vol) ;
                                                break;
                                        }
                                }
@@ -458,12 +511,15 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba
 
        }
     return capacity;
-}
+    }
+
 
 static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat)
 {
        int capacity = 0;
-       struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+//     struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+       int timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE;
+       int timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE;
 
        //³ä·Åµç״̬±ä»¯ºó£¬BufferÌîÂú֮ǰ£¬²»¸üÐÂ
        if (bat->bat_status_cnt < NUM_VOLTAGE_SAMPLE)  {
@@ -476,8 +532,14 @@ static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat)
            
        if (rk30_adc_battery_get_charge_level(bat)){
                if (capacity > bat->bat_capacity){
+                       if(capacity > bat->bat_capacity + 10 )
+                               timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE -10;  //5s
+                       else if(capacity > bat->bat_capacity + 7 )
+                               timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE -5; //10s
+                               else if(capacity > bat->bat_capacity + 3 )
+                                       timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE - 2; // 13
                        //ʵ¼Ê²ÉÑùµ½µÄÈÝÁ¿±ÈÏÔʾµÄÈÝÁ¿´ó£¬Öð¼¶ÉÏÉý
-                       if (++(bat->gBatCapacityDisChargeCnt) >= NUM_CHARGE_MIN_SAMPLE){
+                       if (++(bat->gBatCapacityDisChargeCnt) >= timer_of_charge_sample){
                                bat->gBatCapacityDisChargeCnt  = 0;
                                if (bat->bat_capacity < 99){
                                        bat->bat_capacity++;
@@ -489,11 +551,19 @@ static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat)
                else{  //   Êµ¼ÊµÄÈÝÁ¿±È²ÉÑù±È ÏÔʾµÄÈÝÁ¿Ð¡
                            bat->gBatCapacityDisChargeCnt = 0;
                            (bat->gBatCapacityChargeCnt)++;
-            
-                       if (pdata->charge_ok_pin != INVALID_GPIO){
-                               if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level){
+                       pr_bat("------------- is_charge_ok(bat)=%d\n", is_charge_ok(bat));
+                               if( is_charge_ok(bat) != INVALID_CHARGE_CHECK){
+                       //if (pdata->charge_ok_pin != INVALID_GPIO){
+                               //if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level){
+                               if( is_charge_ok(bat) == CHARGE_IS_OK){
+                                       if(capacity > bat->bat_capacity + 10 )
+                                               timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE -13;  //  2s
+                                       else if(capacity > bat->bat_capacity + 7 )
+                                               timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE -10; //10s
+                                       else if(capacity > bat->bat_capacity + 2 )
+                                               timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE -8; //7s                                 
                                //¼ì²âµ½µç³Ø³äÂú±êÖ¾£¬Í¬Ê±³¤Ê±¼äÄÚ³äµçµçѹÎޱ仯£¬¿ªÊ¼Æô¶¯¼Æʱ³äµç£¬¿ìËÙÉÏÉýÈÝÁ¿
-                                       if (bat->gBatCapacityChargeCnt >= NUM_CHARGE_MIN_SAMPLE){
+                                       if (bat->gBatCapacityChargeCnt >= timer_of_charge_sample){
                                                bat->gBatCapacityChargeCnt = 0;
                                                if (bat->bat_capacity < 99){
                                                        bat->bat_capacity++;
@@ -547,7 +617,7 @@ static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat)
                                        if ((bat->bat_capacity >= 85) &&(bat->gBatCapacityChargeCnt > NUM_CHARGE_MAX_SAMPLE)){
                                                bat->gBatCapacityChargeCnt = (NUM_CHARGE_MAX_SAMPLE - NUM_CHARGE_MID_SAMPLE);
 
-                                               if (bat->bat_capacity < 99){
+                                               if (bat->bat_capacity <= 99){
                                                        bat->bat_capacity++;
                                                        bat->bat_change  = 1;
                                                }
@@ -561,7 +631,14 @@ static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat)
        else{   
        //·Åµçʱ,Ö»ÔÊÐíµçѹϽµ
                if (capacity < bat->bat_capacity){
-                       if (++(bat->gBatCapacityDisChargeCnt) >= NUM_DISCHARGE_MIN_SAMPLE){
+                       if(capacity + 10 > bat->bat_capacity  )
+                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -10;  //5s
+                       else if(capacity  + 7 > bat->bat_capacity )
+                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -5; //10s
+                               else if(capacity  + 3> bat->bat_capacity )
+                                       timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 2; // 13
+
+                       if (++(bat->gBatCapacityDisChargeCnt) >= timer_of_discharge_sample){
                                bat->gBatCapacityDisChargeCnt = 0;
                                if (bat->bat_capacity > 0){
                                        bat->bat_capacity-- ;
@@ -585,6 +662,8 @@ static void rk30_adc_battery_poweron_capacity_check(void)
 
        new_capacity = gBatteryData->bat_capacity;
        old_capacity = rk30_adc_battery_load_capacity();
+
+       pr_bat("------------old_capacity---%d\n",old_capacity);
        if ((old_capacity <= 0) || (old_capacity >= 100)){
                old_capacity = new_capacity;
        }    
@@ -611,7 +690,7 @@ static void rk30_adc_battery_poweron_capacity_check(void)
        }
 
 
-       //printk("capacity = %d, new_capacity = %d, old_capacity = %d\n",gBatteryData->bat_capacity, new_capacity, old_capacity);
+       pr_bat("capacity = %d, new_capacity = %d, old_capacity = %d\n",gBatteryData->bat_capacity, new_capacity, old_capacity);
 
        gBatteryData->bat_change = 1;
 }
@@ -627,7 +706,11 @@ static int rk30_adc_battery_get_usb_property(struct power_supply *psy,
        switch (psp) {
        case POWER_SUPPLY_PROP_ONLINE:
                if (psy->type == POWER_SUPPLY_TYPE_USB)
-                       val->intval = get_msc_connect_flag();
+               //      val->intval = get_msc_connect_flag();
+               if (gBatteryData->pdata->spport_usb_charging)  //is usb charging 
+                       if(gBatteryData->pdata->is_usb_charging)
+                               val->intval = gBatteryData ->pdata->is_usb_charging();
+
                printk("%s:%d\n",__FUNCTION__,val->intval);
                break;
 
@@ -874,15 +957,31 @@ static void rk30_adc_battery_resume_check(void)
 
 static int rk30_adc_battery_suspend(struct platform_device *dev, pm_message_t state)
 {
+       int irq;
        gBatteryData->suspend_capacity = gBatteryData->bat_capacity;
        cancel_delayed_work(&gBatteryData->delay_work);
+       
+       if( gBatteryData->pdata->batt_low_pin != INVALID_GPIO){
+               
+               irq = gpio_to_irq(gBatteryData->pdata->batt_low_pin);
+               enable_irq(irq);
+               enable_irq_wake(irq);
+       }
+
        return 0;
 }
 
 static int rk30_adc_battery_resume(struct platform_device *dev)
 {
+       int irq;
        gBatteryData->resume = true;
-       queue_delayed_work(gBatteryData->wq, &gBatteryData->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS));
+       queue_delayed_work(gBatteryData->wq, &gBatteryData->delay_work, msecs_to_jiffies(100));
+       if( gBatteryData->pdata->batt_low_pin != INVALID_GPIO){
+               
+               irq = gpio_to_irq(gBatteryData->pdata->batt_low_pin);
+               disable_irq_wake(irq);
+               disable_irq(irq);
+       }
        return 0;
 }
 #else
@@ -900,8 +999,7 @@ static void rk30_adc_battery_timer_work(struct work_struct *work)
                gBatteryData->resume = false;
        }
 #endif
-
-
+               
        rk30_adc_battery_status_samples(gBatteryData);
 
        if (gBatteryData->poweron_check){   
@@ -912,27 +1010,33 @@ static void rk30_adc_battery_timer_work(struct work_struct *work)
        rk30_adc_battery_voltage_samples(gBatteryData);
        rk30_adc_battery_capacity_samples(gBatteryData);
 
-       if( 1 == rk30_adc_battery_get_charge_level(gBatteryData)){  // charge
-               if(0 == gBatteryData->status_lock ){                    
-                       wake_lock(&batt_wake_lock);  //lock
-                       gBatteryData->status_lock = 1; 
-               }
-       }
-       else{
-               if(1 == gBatteryData->status_lock ){                    
-                       wake_unlock(&batt_wake_lock);  //unlock
-                       gBatteryData->status_lock = 0; 
+       if( 0 == gBatteryData ->pdata ->charging_sleep){
+               if( 1 == rk30_adc_battery_get_charge_level(gBatteryData)){  // charge
+                       if(0 == gBatteryData->status_lock ){                    
+                               wake_lock(&batt_wake_lock);  //lock
+                               gBatteryData->status_lock = 1; 
+                       }
                }
+               else{
+                       if(1 == gBatteryData->status_lock ){                    
+                               wake_unlock(&batt_wake_lock);  //unlock
+                               gBatteryData->status_lock = 0; 
+                       }
 
+               }
        }
        
        
-
        /*update battery parameter after adc and capacity has been changed*/
        if(gBatteryData->bat_change){
                gBatteryData->bat_change = 0;
                rk30_adc_battery_put_capacity(gBatteryData->bat_capacity);
                power_supply_changed(&rk30_battery_supply);
+#if  defined (CONFIG_BATTERY_RK30_AC_CHARGE)
+               if (gBatteryData->pdata->dc_det_pin == INVALID_GPIO){
+                       power_supply_changed(&rk30_ac_supply);
+               }
+#endif
        }
 
        if (rk30_battery_dbg_level){
@@ -940,8 +1044,8 @@ static void rk30_adc_battery_timer_work(struct work_struct *work)
                        {
                        AdcTestCnt = 0;
 
-                       printk("Status = %d, RealAdcVal = %d, RealVol = %d,gBatVol = %d, gBatCap = %d, RealCapacity = %d, dischargecnt = %d, chargecnt = %d\n", 
-                       gBatteryData->bat_status, gBatteryData->adc_val, adc_to_voltage(gBatteryData->adc_val), 
+                       pr_bat("Status = %d, RealAdcVal = %d, RealVol = %d,gBatVol = %d, gBatCap = %d, RealCapacity = %d, dischargecnt = %d, chargecnt = %d\n", 
+                       gBatteryData->bat_status, gBatteryData->adc_val, rk_adc_voltage(gBatteryData->adc_val), 
                        gBatteryData->bat_voltage, gBatteryData->bat_capacity, gBatteryData->capacitytmp, gBatteryData->gBatCapacityDisChargeCnt,gBatteryData-> gBatCapacityChargeCnt);
 
                }
@@ -957,6 +1061,7 @@ static int rk30_adc_battery_io_init(struct rk30_adc_battery_platform_data *pdata
        
        if (pdata->io_init) {
                pdata->io_init();
+               return 0;
        }
        
        //charge control pin
@@ -1021,7 +1126,7 @@ error:
        return -1;
 }
 
-//extern void kernel_power_off(void);
+extern void kernel_power_off(void);
 static void rk30_adc_battery_check(struct rk30_adc_battery_data *bat)
 {
        int i;
@@ -1067,14 +1172,14 @@ static void rk30_adc_battery_check(struct rk30_adc_battery_data *bat)
        }
 
 
-
+#if 0
 #if 1
        rk30_adc_battery_poweron_capacity_check();
 #else
        gBatteryData->poweron_check = 1;
 #endif
        gBatteryData->poweron_check = 0;
-
+#endif
 /*******************************************
 //¿ª»ú²ÉÑùµ½µÄµçѹºÍÉϴιػú±£´æµçѹÏà²î½Ï´ó£¬Ôõô´¦Àí£¿
 if (bat->bat_capacity > old_capacity)
@@ -1095,11 +1200,12 @@ if ((old_capacity > bat->bat_capacity) > 20)
        if (bat->bat_capacity == 0) bat->bat_capacity = 1;
 
 
-#if 0
-       if ((bat->bat_voltage <= batt_table[0].dis_charge_vol+ 50)&&(bat->bat_status != POWER_SUPPLY_STATUS_CHARGING)){
-               kernel_power_off();
-       }
-#endif
+       if(1==gBatteryData -> pdata->low_voltage_protection)
+
+               if ((bat->bat_voltage <= batt_table[0].dis_charge_vol+ 50)&&(bat->bat_status != POWER_SUPPLY_STATUS_CHARGING)){
+                       kernel_power_off();
+               }
+
 }
 
 static void rk30_adc_battery_callback(struct adc_client *client, void *param, int result)
@@ -1120,11 +1226,15 @@ static void rk30_adc_battery_callback(struct adc_client *client, void *param, in
        return;
 }
 
-#if 0
+#if 1
 static void rk30_adc_battery_lowerpower_delaywork(struct work_struct *work)
 {
-       struct rk30_adc_battery_platform_data *pdata;
        int irq;
+       if( gBatteryData->pdata->batt_low_pin != INVALID_GPIO){
+               irq = gpio_to_irq(gBatteryData->pdata->batt_low_pin);
+               disable_irq(irq);
+       }
+
        printk("lowerpower\n");
        rk28_send_wakeup_key(); // wake up the system   
        return;
@@ -1133,8 +1243,7 @@ static void rk30_adc_battery_lowerpower_delaywork(struct work_struct *work)
 
 static irqreturn_t rk30_adc_battery_low_wakeup(int irq,void *dev_id)
 {
-
-       schedule_work(&gBatteryData->lowerpower_work);  
+       queue_work(gBatteryData->wq, &gBatteryData->lowerpower_work);
        return IRQ_HANDLED;
 }
 
@@ -1148,14 +1257,15 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
        struct adc_client                   *client;
        struct rk30_adc_battery_data          *data;
        struct rk30_adc_battery_platform_data *pdata = pdev->dev.platform_data;
-       
+
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (data == NULL) {
                ret = -ENOMEM;
                goto err_data_alloc_failed;
        }
+       
+       memset(data, 0, sizeof(struct rk30_adc_battery_data));
        gBatteryData = data;
-
        platform_set_drvdata(pdev, data);
 
        data->pdata = pdata;
@@ -1168,7 +1278,10 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
        memset(data->adc_samples, 0, sizeof(int)*(NUM_VOLTAGE_SAMPLE + 2));
 
         //register adc for battery sample
-       client = adc_register(0, rk30_adc_battery_callback, NULL);  //pdata->adc_channel = ani0
+        if(0 == pdata->adc_channel)
+               client = adc_register(0, rk30_adc_battery_callback, NULL);  //pdata->adc_channel = ani0
+       else
+               client = adc_register(pdata->adc_channel, rk30_adc_battery_callback, NULL);  
        if(!client)
                goto err_adc_register_failed;
            
@@ -1194,9 +1307,16 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
 
        data->wq = create_singlethread_workqueue("adc_battd");
        INIT_DELAYED_WORK(&data->delay_work, rk30_adc_battery_timer_work);
+       
        //Power on Battery detect
        rk30_adc_battery_check(data);
-       queue_delayed_work(data->wq, &data->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS));
+       if(1 == pdata->save_capacity ){
+               queue_delayed_work(data->wq, &data->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS*10));
+               gBatteryData->poweron_check = 1;
+       }else{
+               queue_delayed_work(data->wq, &data->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS));
+               gBatteryData->poweron_check = 0;
+       }
 
 #if  defined (CONFIG_BATTERY_RK30_AC_CHARGE)
        ret = power_supply_register(&pdev->dev, &rk30_ac_supply);
@@ -1220,7 +1340,7 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
        }
 #endif
 
-#if 0
+#if 1
        // batt low irq lowerpower_work
        if( pdata->batt_low_pin != INVALID_GPIO){
                INIT_WORK(&data->lowerpower_work, rk30_adc_battery_lowerpower_delaywork);
@@ -1232,7 +1352,8 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
                        printk("failed to request batt_low_irq irq\n");
                        goto err_lowpowerirq_failed;
                }
-               enable_irq_wake(irq);
+               disable_irq(irq);
+       
        }
 #endif
 
@@ -1255,7 +1376,7 @@ err_battery_failed:
     
 err_dcirq_failed:
        free_irq(gpio_to_irq(pdata->dc_det_pin), data);
-#if 0
+#if 1
  err_lowpowerirq_failed:
        free_irq(gpio_to_irq(pdata->batt_low_pin), data);
 #endif
@@ -1311,7 +1432,9 @@ static void __exit rk30_adc_battery_exit(void)
        platform_driver_unregister(&rk30_adc_battery_driver);
 }
 
-subsys_initcall(rk30_adc_battery_init);//subsys_initcall(rk30_adc_battery_init);
+//subsys_initcall(rk30_adc_battery_init);//subsys_initcall(rk30_adc_battery_init);
+module_init(rk30_adc_battery_init);//subsys_initcall(rk30_adc_battery_init);
+
 module_exit(rk30_adc_battery_exit);
 
 MODULE_DESCRIPTION("Battery detect driver for the rk30");