CHROMIUM: [media] rockchip-vpu: reconstructs hw codes for futher chips
[firefly-linux-kernel-4.4.55.git] / drivers / power / rk30_factory_adc_battery.c
old mode 100644 (file)
new mode 100755 (executable)
index cb441fb..9d4b7df
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <asm/io.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <mach/gpio.h>
 #include <linux/adc.h>
-#include <mach/iomux.h>
-#include <mach/board.h>
 #include <linux/delay.h>
 #include <linux/ktime.h>
 #include <linux/slab.h>
 #include <linux/syscalls.h>
 #include <linux/fs.h>
 #include <linux/wakelock.h>
-
-#if 0
-#define DBG(x...)   printk(x)
-#else
-#define DBG(x...)
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/power/rockchip-adc-battery.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+#include <linux/iio/consumer.h>
+
+#ifdef CONFIG_EARLYSUSPEND
+/* kernel/power/earlysuspend.c */
+extern suspend_state_t get_suspend_state(void);
 #endif
 
-static int rk30_battery_dbg_level = 0;
+static int rk30_battery_dbg_level;
 module_param_named(dbg_level, rk30_battery_dbg_level, int, 0644);
-#define pr_bat( args...) \
-       do { \
-               if (rk30_battery_dbg_level) { \
-                       pr_info(args); \
-               } \
-       } while (0)
-
-
-/*******************ÒÔϲÎÊý¿ÉÒÔÐÞ¸Ä******************************/
-#define        TIMER_MS_COUNTS          1000   //¶¨Ê±Æ÷µÄ³¤¶Èms
-//ÒÔϲÎÊýÐèÒª¸ù¾Ýʵ¼Ê²âÊÔµ÷Õû
-#define        SLOPE_SECOND_COUNTS                    15       //ͳ¼ÆµçѹбÂʵÄʱ¼ä¼ä¸ôs
-#define        DISCHARGE_MIN_SECOND                   45       //×î¿ì·Åµçµç1%ʱ¼ä
-#define        CHARGE_MIN_SECOND                      45       //×î¿ì³äµçµç1%ʱ¼ä
-#define        CHARGE_MID_SECOND                      90       //ÆÕͨ³äµçµç1%ʱ¼ä
-#define        CHARGE_MAX_SECOND                      250      //×³äµçµç1%ʱ¼ä
-#define   CHARGE_FULL_DELAY_TIMES          10          //³äµçÂú¼ì²â·À¶¶Ê±¼ä
-#define   USBCHARGE_IDENTIFY_TIMES        5           //²åÈëUSB»ìÁ÷£¬pcʶ±ð¼ì²âʱ¼ä
+#define DBG( args...) \
+do {\
+       if (rk30_battery_dbg_level) {\
+               pr_info(args);\
+       } \
+} while (0)
+
+#define        TIMER_MS_COUNTS          1000   
+#define        SLOPE_SECOND_COUNTS                    15       
+#define        DISCHARGE_MIN_SECOND                   30
+#define        CHARGE_MIN_SECOND                      45       
+#define        CHARGE_MID_SECOND                      90       
+#define        CHARGE_MAX_SECOND                      250
+#define   CHARGE_FULL_DELAY_TIMES          10     
+#define   USBCHARGE_IDENTIFY_TIMES        2        
 
 #define        NUM_VOLTAGE_SAMPLE                             ((SLOPE_SECOND_COUNTS * 1000) / TIMER_MS_COUNTS)  
 #define        NUM_DISCHARGE_MIN_SAMPLE                 ((DISCHARGE_MIN_SECOND * 1000) / TIMER_MS_COUNTS)       
 #define        NUM_CHARGE_MIN_SAMPLE            ((CHARGE_MIN_SECOND * 1000) / TIMER_MS_COUNTS)     
 #define        NUM_CHARGE_MID_SAMPLE            ((CHARGE_MID_SECOND * 1000) / TIMER_MS_COUNTS)      
 #define        NUM_CHARGE_MAX_SAMPLE            ((CHARGE_MAX_SECOND * 1000) / TIMER_MS_COUNTS)   
-#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   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   CHARGE_IS_OK                    1
+#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
+#define  BAT_DEFINE_VALUE                                        3300  /*2500*/
 #endif
 
+#define RK30_GPIO_LOW 0
+#define RK30_GPIO_HIGH 1
 
-#define BATT_FILENAME "/data/bat_last_capacity.dat"
-
-static struct wake_lock batt_wake_lock;
-
-
-struct batt_vol_cal{
-       u32 disp_cal;
-       u32 dis_charge_vol;
-       u32 charge_vol;
-};
-#if 0
-
-#ifdef CONFIG_BATTERY_RK30_VOL3V8
-
-#define BATT_MAX_VOL_VALUE                             4120                    //ÂúµçʱµÄµç³Øµçѹ       
-#define BATT_ZERO_VOL_VALUE                            3400                    //¹Ø»úʱµÄµç³Øµçѹ
-#define BATT_NOMAL_VOL_VALUE                         3800               
-//divider resistance 
-#define BAT_PULL_UP_R                                         200
-#define BAT_PULL_DOWN_R                                    200
-
-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},
-       {29,3680,3810},{31,3687,3814},{33,3693,3818},{35,3699,3822},{37,3705,3825},
-       {39,3710,3830},{41,3714,3832},{43,3718,3834},{45,3722,3836},{47,3726,3837},
-       {49,3730,3839},{51,3734,3841},{53,3738,3842},{55,3742,3844},{57,3746,3844},
-       {59,3750,3855},{61,3756,3860},{63,3764,3864},{65,3774,3871},{67,3786,3890},
-       {69,3800,3910},{71,3808,3930},{73,3817,3977},{75,3827,3977},{77,3845,3997},
-       {79,3950,4030},{81,3964,4047},{83,3982,4064},{85,4002,4080},{87,4026,4096},
-       {89,4030,4132},{91,4034,4144},{93,4055,4150},{95,4085,4195},{97,4085,4195},{100,4120,4200},
-};
-#else
-#define BATT_MAX_VOL_VALUE                              8284                   //Full charge voltage
-#define BATT_ZERO_VOL_VALUE                             6800                   // power down voltage 
-#define BATT_NOMAL_VOL_VALUE                          7600                
-
-//¶¨ÒåADC²ÉÑù·Öѹµç×裬ÒÔʵ¼ÊֵΪ׼£¬µ¥Î»K
-
-#define BAT_PULL_UP_R                                         300 
-#define BAT_PULL_DOWN_R                                    100
-
-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
-       {39,7420,7920},  {41,7424,7928},   {43,7436,7947},   {45,7444,7944},      {47,7450,7958}, //508
-       {49,7460,7965},  {51,7468,7975},   {53, 7476,7990},  {55,7482,8000},      {57,7492,8005}, // 5 14
-       {59,7500,8011},  {61,7510,8033},   {63,7528,8044},   {65,7548,8055},      {67,7560,8066},//506
-       {69,7600,8070},  {71,7618,8075},   {73,7634,8080},   {75,7654,8085},      {77,7690,8100}, //400
-       {79,7900,8180},  {81,7920,8210},   {83,7964,8211},   {85,8000,8214},      {87,8002,8218},//290
-       {89,8012, 8220}, {91,8022,8235},   {93,8110,8260},   {95,8140,8290},       {97,8170,8300},  {100,8200 ,8310},//110
-
-};
-#endif
 
 
+//#define BATT_FILENAME "/data/bat_last_capacity.dat"
 
-#define BATT_NUM  ARRAY_SIZE(batt_table)
-#endif
 
 #define BATTERY_APK 
-
 #ifdef  BATTERY_APK
-
 #define BATT_NUM  11
-#include <linux/fs.h>
 int    battery_dbg_level = 0;
 int    battery_test_flag = 0;
-int gVoltageCnt = 3400;
-int gDoubleVoltageCnt = 6800;
-#ifdef CONFIG_BATTERY_RK30_VOL3V8
-#define BATT_MAX_VOL_VALUE                             4120                    //ÂúµçʱµÄµç³Øµçѹ       
-#define BATT_ZERO_VOL_VALUE                            3400                    //¹Ø»úʱµÄµç³Øµçѹ
-#define BATT_NOMAL_VOL_VALUE                         3800     
-         
-//int    pull_up_res  =100;
-//int    pull_down_res = 100;
+int    gVoltageCnt = 3400;
+int    gDoubleVoltageCnt = 6800;
+unsigned long gSecondsCnt = 0;
+char gDischargeFlag[4] = {"on "};
+static int    g_old_cap = -1;
+static int g_uboot_incre = 0;
 
+#if 1
+#define BATT_MAX_VOL_VALUE     4250/*Full  charge volatge*/
+#define BATT_ZERO_VOL_VALUE    3500/*power down voltage*/
+#define BATT_NOMAL_VOL_VALUE                         3800            
 
 static int batt_table[2*BATT_NUM+6] =
 {
@@ -173,35 +117,45 @@ static int batt_table[2*BATT_NUM+6] =
 #define adc_to_voltage(adc_val) ((adc_val * BAT_DEFINE_VALUE * (batt_table[4] +batt_table[5])) / (1024 *batt_table[5]))
 #else
 #define BATT_MAX_VOL_VALUE                              8284                   //Full charge voltage
-#define BATT_ZERO_VOL_VALUE                             6800                   // power down voltage 
+#define BATT_ZERO_VOL_VALUE                             6900                   // power down voltage 
 #define BATT_NOMAL_VOL_VALUE                          7600                
-//int    pull_up_res  =300;
-//int    pull_down_res = 100;
-//¶¨ÒåADC²ÉÑù·Öѹµç×裬ÒÔʵ¼ÊֵΪ׼£¬µ¥Î»K
+
 
 static int batt_table[2*BATT_NUM+6] =
 {
        0x4B434F52,0x7461625F,0x79726574,1,300,100,
-       6800,7242,7332,7404,7470,7520,7610,7744,7848,8016,8284,
-       7630, 7754, 7852, 7908, 7956, 8024, 8112, 8220, 8306, 8318, 8328
+       6800, 7242, 7332, 7404, 7470, 7520, 7610, 7744, 7848, 8016, 8284,//discharge
+       7630, 7754, 7852, 7908, 7956, 8024, 8112, 8220, 8306, 8318, 8328//charge
 };
 #define adc_to_voltage(adc_val) ((adc_val * BAT_DEFINE_VALUE * (batt_table[4] +batt_table[5])) / (1024 *batt_table[5]))
-
-
 #endif
-#else
-//#define adc_to_voltage(adc_val)                           ((adc_val * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R))
+
 #endif
-int Cnt=0;
-unsigned long gSecondsCnt = 0;
 
-char gDischargeFlag[3] = {"on "};
 
 
 /********************************************************************************/
 
-extern int dwc_vbus_status(void);
-extern int get_msc_connect_flag(void);
+
+enum {
+       BATTERY_STATUS                  = 0,
+       BATTERY_HEALTH                  = 1,
+       BATTERY_PRESENT                 = 2,
+       BATTERY_CAPACITY                        = 3,
+       BATTERY_AC_ONLINE                       = 4,
+       BATTERY_STATUS_CHANGED  = 5,
+       AC_STATUS_CHANGED               = 6,
+       BATTERY_INT_STATUS              = 7,
+       BATTERY_INT_ENABLE              = 8,
+};
+
+typedef enum {
+       CHARGER_BATTERY = 0,
+       CHARGER_USB,
+       CHARGER_AC
+} charger_type_t;
+
+
 
 struct rk30_adc_battery_data {
        int irq;
@@ -209,13 +163,12 @@ struct rk30_adc_battery_data {
        //struct timer_list       timer;
        struct workqueue_struct *wq;
        struct delayed_work         delay_work;
+       struct delayed_work     check_work;
        struct work_struct          dcwakeup_work;
        struct work_struct                   lowerpower_work;
        bool                    resume;
        
        struct rk30_adc_battery_platform_data *pdata;
-
-       int                     full_times;
        
        struct adc_client       *client; 
        int                     adc_val;
@@ -233,46 +186,85 @@ struct rk30_adc_battery_data {
        int                    *pSamples;
        int                     gBatCapacityDisChargeCnt;
        int                     gBatCapacityChargeCnt;
-       int               capacitytmp;
-       int                     poweron_check;
+       int                     gBatCapacityacChargeCnt;
+       int                     gBatCapacityusbChargeCnt ;
+       int                       gBatCapacityusbdisChargeCnt;
+       int                       capacitytmp;
        int                     suspend_capacity;
        int                     gBatUsbChargeCnt;
        int                     status_lock;
 
-       int                    usb_charging;
-       int                    ac_charging;
+       struct power_supply     bat;
+       struct power_supply     usb;
+       struct power_supply     ac;
+       struct power_supply     bk_bat;
+       
+       int                     poweron_check;
+       int                     usb_charging;
+       int                     ac_charging;
+       int                      charge_check;
+       int                        charge_level;
+       
+       int                     charge_source_now;
+       int                     charge_soure_old;
+       int                     charge_start_capacity;
+       int                     charge_start_voltage;
+       int                     start_voltage_status;
+       int                     charge_up_proprotion;
+       int                     charge_down_proportion;
+       int                     voltage_to_local;
+       unsigned long          suspend_time;
+       unsigned long           resume_time;
+       int                      adc_value;
+       
+       int                     full_times;
+       int                         charge_full_flag;
+       int                     stop_check;
+       struct notifier_block battery_nb;
 
+       int                         lower_power_flag;
+       int                         time_to_full;
 
 };
 static struct rk30_adc_battery_data *gBatteryData;
-
-
+static struct wake_lock batt_wake_lock;
+static struct wake_lock batt_wake_lock_detect_lowpower;
+static struct wake_lock charge_display_lock;
+int system_lowerpower = 0;
+extern void kernel_power_off(void);
+extern int dwc_vbus_status(void);
+extern int get_gadget_connect_flag(void);
+extern int dwc_otg_check_dpdm(void);
+static int  is_charge_ok(struct rk30_adc_battery_data *bat);
+static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat);
+extern void rk_send_wakeup_key(void);
+static  bool batt_gpio_is_valid(int number)
+{
+       return number > 0 && number < 256;
+}
 #ifdef  BATTERY_APK
-#define BAT_ADC_TABLE_LEN               11
+//#define BAT_ADC_TABLE_LEN               11
 static ssize_t bat_param_read(struct device *dev,struct device_attribute *attr, char *buf)
 {
-#if 1
        int i;
        for(i=0;i<BATT_NUM;i++)
                printk("i=%d batt_table=%d\n",i+6,batt_table[i+6]);
 
        for(i=0;i<BATT_NUM;i++)
                printk("i=%d batt_table=%d\n",i+17,batt_table[i+17]);
-#endif
        return 0;
 }
-DEVICE_ATTR(batparam, 0664, bat_param_read,NULL);
+DEVICE_ATTR(batparam, 0444, bat_param_read, NULL);
 
 
 static ssize_t rkbatt_show_debug_attrs(struct device *dev,
-                                             struct device_attribute *attr, char *buf) 
+                                                                             struct device_attribute *attr, char *buf) 
 {                               
        return sprintf(buf, "%d\n", battery_dbg_level);
 }
 
 static ssize_t rkbatt_restore_debug_attrs(struct device *dev, 
-                                               struct device_attribute *attr,
-                                               const char *buf, size_t size)
+                                                                                 struct device_attribute *attr, const char *buf, size_t size)
 {
        int liTmp;
        
@@ -288,11 +280,9 @@ static ssize_t rkbatt_restore_debug_attrs(struct device *dev,
        }
        return size;
 }
-static int  is_charge_ok(struct rk30_adc_battery_data *bat);
 
 static ssize_t rkbatt_show_state_attrs(struct device *dev,
-                                             struct device_attribute *attr,
-                                             char *buf) 
+                                                                               struct device_attribute *attr, char *buf) 
 {
 //     struct rk30_adc_battery_platform_data *pdata = gBatteryData->pdata;
        int charge_ok_value =0 ;
@@ -305,21 +295,19 @@ static ssize_t rkbatt_show_state_attrs(struct device *dev,
 }
 
 static ssize_t rkbatt_restore_state_attrs(struct device *dev, 
-                                               struct device_attribute *attr,
-                                               const char *buf, size_t size)
+                                                                               struct device_attribute *attr, const char *buf, size_t size)
 {
        return size;
 }
 
 static ssize_t rkbatt_show_value_attrs(struct device *dev,
-                                             struct device_attribute *attr, char *buf) 
+                                                                           struct device_attribute *attr, char *buf) 
 {                               
        return sprintf(buf, "pull_up_res =%d,\npull_down_res=%d\n", batt_table[4],batt_table[5]);
 }
 
 static ssize_t rkbatt_restore_value_attrs(struct device *dev, 
-                                               struct device_attribute *attr,
-                                               const char *buf, size_t size)
+                                                                               struct device_attribute *attr, const char *buf, size_t size)
 {
        int liUp        = 0;
        int liDown      = 0;
@@ -331,21 +319,16 @@ static ssize_t rkbatt_restore_value_attrs(struct device *dev,
                batt_table[4] = liUp;
                batt_table[5] = liDown;
        }
-       else
-       {
-               //nothing
-       }
        return size;
 }
 
 static ssize_t rkbatt_show_flag_attrs(struct device *dev,
-                                             struct device_attribute *attr, char *buf) 
+                                                                        struct device_attribute *attr, char *buf) 
 {                               
        return sprintf(buf, "rk29_battery_test_flag=%d\n", battery_test_flag);
 }
 static ssize_t rkbatt_restore_flag_attrs(struct device *dev, 
-                                               struct device_attribute *attr,
-                                               const char *buf, size_t size)
+                                                                           struct device_attribute *attr, const char *buf, size_t size)
 {
        int liFlag;
        
@@ -357,20 +340,69 @@ static ssize_t rkbatt_restore_flag_attrs(struct device *dev,
        }
        return size;
 }
+
+static int __init adc_bootloader_setup(char *str)
+{
+
+       if(str) {
+               printk("adc.incre is %s\n", str);
+               sscanf(str, "%d", &g_uboot_incre);
+       }
+       return 0;
+}
+early_param("adc.incre", adc_bootloader_setup);
+
+static ssize_t rkbatt_show_oldcap_attrs(struct device *dev, struct device_attribute *attr, char *buf) 
+{                               
+       return sprintf(buf, "%d\n", g_old_cap);
+}
+
+static ssize_t rkbatt_restore_oldcap_attrs(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+       int old_cap;
+       
+       sscanf(buf, "%d", &old_cap);
+       
+       if(old_cap >= 0 && old_cap <= 100)
+       {
+               g_old_cap = old_cap;
+       }
+       else
+       {
+               dev_err(dev, "rk29adc_restore_oldcap_attrs err\n");
+       }
+       return size;
+}
+
+
 static struct device_attribute rkbatt_attrs[] = {
        __ATTR(state, 0664, rkbatt_show_state_attrs, rkbatt_restore_state_attrs),
        __ATTR(debug, 0664, rkbatt_show_debug_attrs, rkbatt_restore_debug_attrs),
-       __ATTR(value, 0666, rkbatt_show_value_attrs, rkbatt_restore_value_attrs),
-       __ATTR(flag,  0666, rkbatt_show_flag_attrs,  rkbatt_restore_flag_attrs),
+       __ATTR(value, 0555, rkbatt_show_value_attrs, rkbatt_restore_value_attrs),
+       __ATTR(flag,  0555, rkbatt_show_flag_attrs,  rkbatt_restore_flag_attrs),
+       __ATTR(oldcap, 0664, rkbatt_show_oldcap_attrs, rkbatt_restore_oldcap_attrs),
 };
 
+static int rk_adc_battery_iio_read(struct rk30_adc_battery_platform_data *data)
+{
+       struct iio_channel *channel = data->chan;
+       int val, ret;
+
+       ret = iio_read_channel_raw(channel, &val);
+       if (ret < 0) {
+               pr_err("read channel() error: %d\n", ret);
+               return ret;
+       }
+       return val;
+}
+
+
 static int create_sysfs_interfaces(struct device *dev)
 {
        int liTmep;
-       for (liTmep = 0; liTmep < ARRAY_SIZE(rkbatt_attrs); liTmep++)
-       {
-               if (device_create_file(dev, rkbatt_attrs + liTmep))
-               {
+       for (liTmep = 0; liTmep < ARRAY_SIZE(rkbatt_attrs); liTmep++)   {
+               
+               if (device_create_file(dev, rkbatt_attrs + liTmep)){
                        goto error;
                }
        }
@@ -378,8 +410,7 @@ static int create_sysfs_interfaces(struct device *dev)
        return 0;
 
 error:
-       for ( ; liTmep >= 0; liTmep--)
-       {
+       for ( ; liTmep >= 0; liTmep--){
                device_remove_file(dev, rkbatt_attrs + liTmep);
        }
        
@@ -389,30 +420,7 @@ error:
 
 #endif
 
-
-
-enum {
-       BATTERY_STATUS          = 0,
-       BATTERY_HEALTH          = 1,
-       BATTERY_PRESENT         = 2,
-       BATTERY_CAPACITY        = 3,
-       BATTERY_AC_ONLINE       = 4,
-       BATTERY_STATUS_CHANGED  = 5,
-       AC_STATUS_CHANGED       = 6,
-       BATTERY_INT_STATUS          = 7,
-       BATTERY_INT_ENABLE          = 8,
-};
-
-typedef enum {
-       CHARGER_BATTERY = 0,
-       CHARGER_USB,
-       CHARGER_AC
-} charger_type_t;
-
-
-
-
-
+#if 0
 static int rk30_adc_battery_load_capacity(void)
 {
        char value[4];
@@ -420,7 +428,7 @@ static int rk30_adc_battery_load_capacity(void)
        long fd = sys_open(BATT_FILENAME,O_RDONLY,0);
 
        if(fd < 0){
-               pr_bat("rk30_adc_battery_load_capacity: open file /data/bat_last_capacity.dat failed\n");
+               DBG("rk30_adc_battery_load_capacity: open file /data/bat_last_capacity.dat failed\n");
                return -1;
        }
 
@@ -437,169 +445,331 @@ static void rk30_adc_battery_put_capacity(int loadcapacity)
        long fd = sys_open(BATT_FILENAME,O_CREAT | O_RDWR,0);
 
        if(fd < 0){
-               pr_bat("rk30_adc_battery_put_capacity: open file /data/bat_last_capacity.dat failed\n");
+               DBG("rk30_adc_battery_put_capacity: open file /data/bat_last_capacity.dat failed\n");
                return;
        }
        
        *p = loadcapacity;
        sys_write(fd, (const char __user *)value, 4);
-
        sys_close(fd);
 }
+#endif
+static BLOCKING_NOTIFIER_HEAD(adc_battery_chain_head);
 
-static void rk30_adc_battery_charge_enable(struct rk30_adc_battery_data *bat)
+int register_adc_battery_notifier(struct notifier_block *nb)
 {
-       struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+       return blocking_notifier_chain_register(&adc_battery_chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(register_adc_battery_notifier);
+
+int unregister_adc_battery_notifier(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_unregister(&adc_battery_chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_adc_battery_notifier);
+
+int adc_battery_notifier_call_chain(unsigned long val)
+{
+       return (blocking_notifier_call_chain(&adc_battery_chain_head, val, NULL)
+                       == NOTIFY_BAD) ? -EINVAL : 0;
+}
+EXPORT_SYMBOL_GPL(adc_battery_notifier_call_chain);
 
-       if (pdata->charge_set_pin != INVALID_GPIO){
+static void rk_start_charge(struct rk30_adc_battery_data *bat)
+{
+       struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+       if (batt_gpio_is_valid(pdata->charge_set_pin))
                gpio_direction_output(pdata->charge_set_pin, pdata->charge_set_level);
-       }
 }
 
-static void rk30_adc_battery_charge_disable(struct rk30_adc_battery_data *bat)
+static void rk_stop_charge(struct rk30_adc_battery_data *bat)
 {
        struct rk30_adc_battery_platform_data *pdata = bat->pdata;
 
-       if (pdata->charge_set_pin != INVALID_GPIO){
+
+       if (batt_gpio_is_valid(pdata->charge_set_pin))
                gpio_direction_output(pdata->charge_set_pin, 1 - pdata->charge_set_level);
-       }
 }
 
-//extern int suspend_flag;
-static int rk30_adc_battery_get_charge_level(struct rk30_adc_battery_data *bat)
-{
-       int charge_on = 0;
+static int  get_ac_status(struct rk30_adc_battery_data *bat){
+       
        struct rk30_adc_battery_platform_data *pdata = bat->pdata;
-
-#if defined (CONFIG_BATTERY_RK30_AC_CHARGE)
-       if (pdata->dc_det_pin != INVALID_GPIO){
+       int status = 0;
+       if (batt_gpio_is_valid(pdata->dc_det_pin)) {
                if (gpio_get_value (pdata->dc_det_pin) == pdata->dc_det_level){
-                       //charge_on = 1;
-                       bat -> ac_charging = 1;
+                               status = 1;
+                       }else{
+                               status = 0;
+                       }
+       }else{
+               if(pdata->is_dc_charging){
+                       status = pdata->is_dc_charging();
                }
-               else{
-                       bat -> ac_charging = 0;
+       }
+
+       return status;
+}
+#if  defined CONFIG_BATTERY_RK30_USB_CHARGE
+
+//state of charge ----running
+static int  get_usb_status2(struct rk30_adc_battery_data *bat){
+
+//     struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+       int usb_status = 0; // 0--dischage ,1 ---usb charge, 2 ---ac charge
+       int vbus_status =  dwc_vbus_status();
+       
+       if (1 == vbus_status) {
+               if (0 == get_gadget_connect_flag()){ 
+                       if (++bat->gBatUsbChargeCnt >= NUM_USBCHARGE_IDENTIFY_TIMES){
+                               bat->gBatUsbChargeCnt = NUM_USBCHARGE_IDENTIFY_TIMES + 1;
+                               usb_status = 2; // non-standard AC charger
+                               if(bat ->pdata ->control_usb_charging)
+                                       bat ->pdata ->control_usb_charging(1);
+                       }else{
+                               usb_status = 1; // connect to pc        
+                               if(bat ->pdata ->control_usb_charging)
+                                       bat ->pdata ->control_usb_charging(0);
+                       }
+               }else{
+                               
+                               usb_status = 1; // connect to pc        
+                               if(bat ->pdata ->control_usb_charging)
+                                       bat ->pdata ->control_usb_charging(0);
 
                }
-       }
-       else{
-               if(pdata->is_dc_charging){
-                       //charge_on =pdata->is_dc_charging();
-                       bat ->ac_charging = pdata->is_dc_charging();;
+               
+       }else{
+               bat->gBatUsbChargeCnt = 0;
+               if (2 == vbus_status) {
+                       usb_status = 2; //standard AC charger
+                       
+                       if(bat ->pdata ->control_usb_charging)
+                                       bat ->pdata ->control_usb_charging(1);
+               }else{
+                       usb_status = 0; 
                }
+
+
        }
+       return usb_status;
+
+}
 #endif
-       if(1 == pdata->spport_usb_charging){
-               if (charge_on == 0){
-                       if (1 == dwc_vbus_status()) {
-                               if (0 == get_msc_connect_flag()){ 
-                                       if (++bat->gBatUsbChargeCnt >= NUM_USBCHARGE_IDENTIFY_TIMES){
-                                               bat->gBatUsbChargeCnt = NUM_USBCHARGE_IDENTIFY_TIMES + 1;
-                                               //charge_on = 1;
-                                               bat->usb_charging =1;
-                                               if(bat -> pdata ->control_usb_charging)
-                                                       bat -> pdata ->control_usb_charging(0);
-
-                                               //printk("1 == dwc_vbus_status\n");
-                                       }
-                               }                            
+static int rk_battery_get_status(struct rk30_adc_battery_data *bat)
+{
+       int charge_on = 0;
+/*     struct rk30_adc_battery_platform_data *pdata = bat->pdata;*/
+       int ac_ac_charging = 0, usb_ac_charging = 0;
+       int i=0;
+
+       ac_ac_charging = get_ac_status(bat);
+       if(1 == ac_ac_charging)
+               charge_on = 1;
+
+#if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)  
+               if (strstr(saved_command_line,"charger")){
+                       wake_lock(&charge_display_lock);  //lock
+                       if (batt_gpio_is_valid(bat->pdata->usb_det_pin)) {
+                               if( gpio_get_value(bat->pdata->usb_det_pin)== bat->pdata->usb_det_level){
+                                       if(( 1 == usb_ac_charging )||( 1 == ac_ac_charging ))
+                                               bat -> ac_charging = 1;
+                                       if(( 1 == bat->usb_charging)||(1 == bat ->ac_charging))
+                                               charge_on =1;
+                                       return charge_on;
+                               }else{
+                                       if(( 0 == usb_ac_charging )&&( 0 == ac_ac_charging ))
+                                               bat -> ac_charging = 0;
+                                       else
+                                               bat->ac_charging = 1;
+                                       
+                                       bat->usb_charging = 0;
+                                       if(1 == bat->ac_charging)
+                                               charge_on=1;
+                                       else
+                                               charge_on = 0;
+                                       return charge_on;
+                               }
                        }else{
-                               bat->gBatUsbChargeCnt = 0;
-                               if (2 == dwc_vbus_status()) {
-                                       //charge_on = 1;
-                                       bat->usb_charging =1;
+
+                               if(dwc_otg_check_dpdm() == 0){
+                                       bat->usb_charging = 0;
+                                       usb_ac_charging = 0;
+                               }else if(dwc_otg_check_dpdm() == 1){
+                                       bat->usb_charging = 1;
                                        if(bat -> pdata ->control_usb_charging)
-                                                       bat -> pdata ->control_usb_charging(1);
-                                       //printk("2 == dwc_vbus_status\n");
-                               }else{
-                                       bat->usb_charging =0;
+                                               bat -> pdata ->control_usb_charging(0);
+                               }else if(dwc_otg_check_dpdm() == 2){
+                                       bat->usb_charging = 0;
+                                       usb_ac_charging = 1;
+                                       if(bat -> pdata ->control_usb_charging)
+                                               bat -> pdata ->control_usb_charging(1); 
                                }
+                               if((1 == usb_ac_charging)||(1 == ac_ac_charging))
+                                       bat ->ac_charging = 1;
+                               else
+                                       bat ->ac_charging = 0;
+
+                               if(( 0 == bat ->ac_charging )&&(0 == bat->usb_charging  )){
+                                       charge_on = 0;
+                                       bat->bat_change = 1;
+                               }
+
+                               return charge_on;
+
+                       }
                }
-               }
-       }
-#if 0
-       if (pdata->spport_usb_charging)  //is usb charging 
-               if(pdata->is_usb_charging)
-                       charge_on = pdata->is_usb_charging();
 
+               if (charge_on == 0){
+                       usb_ac_charging = get_usb_status2(bat); //0 --discharge, 1---usb charging,2----AC charging;
+                       if(1 == usb_ac_charging)
+                               bat->usb_charging = 1;
+                       else
+                               bat->usb_charging = 0;                                          
+               }
 #endif
+       if((usb_ac_charging == 2)||(ac_ac_charging == 1))
+               bat -> ac_charging = 1;
+       else
+               bat -> ac_charging = 0;
+
        if((bat->usb_charging == 1)||(bat ->ac_charging ==1))
                charge_on =1;
+       
+       if(1 == bat->ac_charging )
+                       bat->charge_source_now = 1; //ac charge
+       else if( 1 == bat->usb_charging){
+                       bat->charge_source_now = 2; //ac charge
+       }else{
+               bat->charge_soure_old =0;
+               bat->charge_source_now=0;
+       }
+       if(bat->charge_source_now != bat->charge_soure_old){
+
+               for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++){                //0.3 s
+                       msleep(1); //mdelay --- > msleep
+                       rk30_adc_battery_voltage_samples(bat);              //get new voltage
+               }
+
+                       bat->charge_soure_old = bat->charge_source_now;
+                       bat->bat_change = 1;
+       }
+       DBG("ac_status=%d,usb_status=%d bat->bat_change = %d\n",bat -> ac_charging, bat->usb_charging ,bat->bat_change );
+       
        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))
+       if( 1 != bat->charge_level)
                return -1;
        
-       if (pdata->charge_ok_pin != INVALID_GPIO){              
-               if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level)
-               {
+       if ((!(batt_gpio_is_valid(pdata->charge_ok_pin))) && (
+               pdata->charging_ok == NULL))
+               return -1;
+       
+       if (batt_gpio_is_valid(pdata->charge_ok_pin)) {
+               if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level){
                        charge_is_ok =1;
                }
-       }else if( pdata->charging_ok)
-               {       
+       }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;
 
-       charge_level = rk30_adc_battery_get_charge_level(bat);
+       charge_level = bat ->charge_level;//rk_battery_get_status(bat);
 
-       //¼ì²â³äµç״̬±ä»¯Çé¿ö
        if (charge_level != bat->old_charge_level){
                bat->old_charge_level = charge_level;
                bat->bat_change  = 1;
-               
+#if 0
                if(charge_level) {            
-                       rk30_adc_battery_charge_enable(bat);
+                       rk_start_charge(bat);
                }
                else{
-                       rk30_adc_battery_charge_disable(bat);
+                       rk_stop_charge(bat);
                }
-               bat->bat_status_cnt = 0;        //״̬±ä»¯¿ªÊ¼¼ÆÊý
+#endif
+               bat->bat_status_cnt = 0;        
        }
+       if(( 1 == charge_level )&&(1 == bat->charge_full_flag) && (bat->bat_capacity < 90)){
+               rk_start_charge(bat);  //recharge
+               if(bat->pdata->ctrl_charge_led != NULL)
+                       bat->pdata->ctrl_charge_led(0);
+
+       }else if (charge_level) {
+               rk_start_charge(bat);
+               }else{
+                       rk_stop_charge(bat);
+
+               }
+       
 
        if(charge_level == 0){   
        //discharge
+               bat->charge_full_flag = 0;
                bat->full_times = 0;
+               bat->time_to_full = 0;
                bat->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
-       }
-       else{
-       //CHARGE            
+       }else{
+       //charging          
                if( is_charge_ok(bat)  ==  INVALID_CHARGE_CHECK){
-
                        if (bat->bat_capacity == 100){
                                if (bat->bat_status != POWER_SUPPLY_STATUS_FULL){
                                        bat->bat_status = POWER_SUPPLY_STATUS_FULL;
                                        bat->bat_change  = 1;
+                                       bat->charge_full_flag = 1;
+                                       if(bat->pdata->ctrl_charge_led != NULL)
+                                               bat->pdata->ctrl_charge_led(1);
+                                       rk_stop_charge(bat);
+                                               
                                }
-                       }
-                       else{
+                       }else{
                                bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+                               if((bat->bat_capacity == 99)&&(bat->time_to_full == 0)){
+                                       bat->time_to_full = get_seconds();
+                               }else if(bat->bat_capacity == 99)
+                               {
+                                       if(get_seconds() - bat->time_to_full > 1800){
+                                               bat->bat_capacity = 100;
+                                               bat->time_to_full = 0;
+                                       }
+
+                               }
+
+                               if(bat->pdata->ctrl_charge_led != NULL)
+                                               bat->pdata->ctrl_charge_led(0);
                        }
-               }
-               else{  // pin of charge_ok_pin
+               }else{  // pin of charge_ok_pin
                        if (is_charge_ok(bat) != CHARGE_IS_OK ){
 
                                bat->full_times = 0;
                                bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
-                       }
-                       else{
-       //¼ì²âµ½³äµçÂúµçƽ±êÖ¾
+
+                               if((bat->bat_capacity == 99)&&(bat->time_to_full == 0)){
+                               bat->time_to_full = get_seconds();
+                               }else if(bat->bat_capacity == 99)
+                               {
+                                       if(get_seconds() - bat->time_to_full > 1800){
+                                               bat->bat_capacity = 100;
+                                               bat->time_to_full = 0;
+                                       }
+
+                               }
+
+
+                       }else{
                                bat->full_times++;
 
                                if (bat->full_times >= NUM_CHARGE_FULL_DELAY_TIMES) {
@@ -609,6 +779,7 @@ static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat)
                                if ((bat->full_times >= NUM_CHARGE_FULL_DELAY_TIMES) && (bat->bat_capacity >= 99)){
                                        if (bat->bat_status != POWER_SUPPLY_STATUS_FULL){
                                                bat->bat_status = POWER_SUPPLY_STATUS_FULL;
+                                               rk_stop_charge(bat);
                                                bat->bat_capacity = 100;
                                                bat->bat_change  = 1;
                                        }
@@ -622,48 +793,56 @@ static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat)
 
        return charge_level;
 }
-static int rk_adc_voltage(int value)
+
+static int rk_adc_battery_iio_read_refvol(struct rk30_adc_battery_platform_data *data)
 {
-       int voltage;
+       struct iio_channel *channel = data->ref_voltage_chan;
+       int val, ret;
 
-       int ref_voltage; //reference_voltage
-       int pullup_res;
-       int pulldown_res;
+       ret = iio_read_channel_raw(channel, &val);
+       if (ret < 0) {
+               pr_err("read channel() error: %d\n", ret);
+               return ret;
+       }
+       return val;
+}
 
-       ref_voltage = gBatteryData ->pdata->reference_voltage;
-       pullup_res = gBatteryData ->pdata->pull_up_res;
-       pulldown_res = gBatteryData ->pdata->pull_down_res;
+static int get_ref_voltage(struct rk30_adc_battery_data *bat)
+{
+       int data_value;
+       struct regulator *logic;
+       int voltage, ref_voltage;
 
-       if(ref_voltage && pullup_res && pulldown_res){
-               
-               voltage =  ((value * ref_voltage * (pullup_res + pulldown_res)) / (1024 * pulldown_res));
+       logic = regulator_get(NULL, "vdd_arm");
+       voltage = regulator_get_voltage(logic);
+       data_value = rk_adc_battery_iio_read_refvol(bat->pdata);
+       ref_voltage = voltage*1024/data_value/1000;
+
+       return ref_voltage;
+}
+static int rk_adc_voltage(struct rk30_adc_battery_data *bat, int value)
+{
+       int voltage;
+       int ref_voltage;
+
+       ref_voltage = bat ->pdata->reference_voltage;
+
+       if (ref_voltage) {
+               if (bat->pdata->auto_calibration == 1)
+                       ref_voltage = get_ref_voltage(bat);
+               voltage = (value * ref_voltage * (batt_table[4] + batt_table[5])) / (1024 * batt_table[5]);
+               DBG("ref_voltage =%d, voltage=%d\n", ref_voltage, voltage);
                
        }else{
-               voltage = adc_to_voltage(value);        
+               voltage = adc_to_voltage(value);
        }
-               
-               
+       DBG("ref_voltage =%d, voltage=%d\n", ref_voltage, voltage);
        return voltage;
 
 }
 static void rk_handle_ripple(struct rk30_adc_battery_data *bat, int status)
 {
        
-#if  0
-                if(1 == status){
-                        if(bat->bat_voltage >=  bat->pdata->charge_table[bat->pdata->table_size-1]+ 10)
-                                bat->bat_voltage = bat->pdata->charge_table[bat->pdata->table_size-1]  + 10;
-                        else if(bat->bat_voltage <= bat->pdata->charge_table[0] - 10)
-                                bat->bat_voltage =   bat->pdata->charge_table[0] - 10;
-                }
-                else{
-                        if(bat->bat_voltage >=  bat->pdata->discharge_table[bat->pdata->table_size-1]+ 10)
-                                bat->bat_voltage =  bat->pdata->discharge_table[ bat->pdata->table_size-1] + 10;
-                        else if(bat->bat_voltage <=   bat->pdata->discharge_table[ 0]  - 10)
-                                bat->bat_voltage =   bat->pdata->discharge_table[ 0] - 10;
-
-                }
-#endif 
        int *p_table;
 
        if (bat->pdata->use_board_table){
@@ -685,26 +864,26 @@ static void rk_handle_ripple(struct rk30_adc_battery_data *bat, int status)
 
 }
 
-static int *pSamples;
+//static int *pSamples;
 static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat)
 {
        int value;
        int i,*pStart = bat->adc_samples, num = 0;
-       int level = rk30_adc_battery_get_charge_level(bat);
+       int level = bat->charge_level;
 
 
        value = bat->adc_val;
-       adc_async_read(bat->client);
+       bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
 
-       *pSamples++ = rk_adc_voltage(value);
+       *(bat->pSamples++) = rk_adc_voltage(bat,value);
 
        bat->bat_status_cnt++;
        if (bat->bat_status_cnt > NUM_VOLTAGE_SAMPLE)  bat->bat_status_cnt = NUM_VOLTAGE_SAMPLE + 1;
 
-       num = pSamples - pStart;
+       num = bat->pSamples - pStart;
        
        if (num >= NUM_VOLTAGE_SAMPLE){
-               pSamples = pStart;
+               bat ->pSamples = pStart;
                num = NUM_VOLTAGE_SAMPLE;
                
        }
@@ -715,7 +894,7 @@ static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat)
        }
        bat->bat_voltage = value / num;
 
-       /*Ïû³ýë´Ìµçѹ*/
+       /*handle  ripple */
        if(battery_test_flag == 0)
        {
                if(0 == bat->pdata->use_board_table){
@@ -739,14 +918,10 @@ static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat)
        
                if(batt_table[3] == 0){
                        if(bat->bat_voltage < 3400){
-                               //printk("gSecondsCnt=%ld,get_seconds()=%ld,(get_seconds() - gSecondsCnt)=%ld-------------------1\n",gSecondsCnt,get_seconds(),(get_seconds() - gSecondsCnt));
                                if((get_seconds() - gSecondsCnt) > 30){
                                        gSecondsCnt = get_seconds();
-                                       //printk("gSecondsCnt=%ld,gVoltageCnt=%d,(gVoltageCnt - bat->bat_voltage)=%d,bat->bat_voltage=%d-------------------2\n",gSecondsCnt,gVoltageCnt,(gVoltageCnt - bat->bat_voltage),bat->bat_voltage);
                                        if((gVoltageCnt - bat->bat_voltage) > 15){
-                                               //gVoltageCnt = bat->bat_voltage;
-                                               //printk("gVoltageCnt=%d-------------------3\n",gVoltageCnt);
-                                               strncpy(gDischargeFlag, "off" ,3);      
+                                               strncpy(gDischargeFlag, "off" ,4);      
                                        }
                                        gVoltageCnt = bat->bat_voltage;
 
@@ -759,14 +934,10 @@ static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat)
                }
                else{
                        if(bat->bat_voltage < 6800){
-                               //printk("gSecondsCnt=%ld,get_seconds()=%ld,(get_seconds() - gSecondsCnt)=%ld-------------------1\n",gSecondsCnt,get_seconds(),(get_seconds() - gSecondsCnt));
                                if((get_seconds() - gSecondsCnt) > 30){
                                        gSecondsCnt = get_seconds();
-                                       //printk("gSecondsCnt=%ld,gVoltageCnt=%d,(gVoltageCnt - bat->bat_voltage)=%d,bat->bat_voltage=%d-------------------2\n",gSecondsCnt,gVoltageCnt,(gVoltageCnt - bat->bat_voltage),bat->bat_voltage);
                                        if((gDoubleVoltageCnt - bat->bat_voltage) > 30){
-                                               //gVoltageCnt = bat->bat_voltage;
-                                               //printk("gVoltageCnt=%d-------------------3\n",gVoltageCnt);
-                                               strncpy(gDischargeFlag, "off" ,3);      
+                                               strncpy(gDischargeFlag, "off" ,4);      
                                        }
                                        gDoubleVoltageCnt =bat->bat_voltage;
                                }
@@ -776,81 +947,25 @@ static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat)
                        }       
                }
        }
-/****************************************************/
 }
-#if 0
-static int rk_voltage_capacity(struct rk30_adc_battery_data *bat, int BatVoltage)
-{
 
-       int i = 0;
-       int capacity = 0;
-       int size =bat->pdata->table_size;
-       int *p;
-       int *p_capacity = bat->pdata->property_tabel;
-       
-       if (rk30_adc_battery_get_charge_level(bat)){  //charge
-               p =  bat->pdata->charge_table;
-               if(BatVoltage >= (p[size - 1])){
-                       capacity = 99;
-               }       
-               else{
-                       if(BatVoltage <= (p[0])){
-                               capacity = 0;
-                       }
-                       else{
-                               for(i = 0; i < size - 1; i++){
-
-                                       if(((p[i]) <= BatVoltage) && (BatVoltage < (p[i+1]))){
-                                               capacity = p_capacity[i] + ((BatVoltage - p[i]) *  (p_capacity[i+1] -p_capacity[i]))/ (p[i+1]- p[i]);
-                                               break;
-                                       }
-                               }
-                       }  
-               }
-
-       }
-       else{  //discharge
-               p =  bat->pdata->discharge_table;
-               if(BatVoltage >= (p[size - 1])){
-                       capacity = 100;
-               }       
-               else{
-                       if(BatVoltage <= p[0]){
-                               capacity = 0;
-                       }
-                       else{
-                               for(i = 0; i < size - 1; i++){
-                                       if((p[i] <= BatVoltage) &&( BatVoltage < p[i+1])){
-                                               capacity =  p_capacity[i]+ ((BatVoltage - p[i]) * (p_capacity[i+1] -p_capacity[i] ) )/ (p[i+1]- p[i]) ;
-                                               break;
-                                       }
-                               }
-                       }  
-
-               }
-
-
-       }
-           return capacity;
-
-
-}
-
-#endif
-static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *bat, int BatVoltage)
-{
+static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *bat, int BatVoltage)
+{
        int i = 0;
        int capacity = 0;
 
        int  *p;
+
        if (bat->pdata->use_board_table)
-               p = bat->pdata->board_batt_table;       
+               p = bat->pdata->board_batt_table;
+       else if (bat->pdata->dts_batt_table)
+               p = bat->pdata->dts_batt_table;
        else 
                p = batt_table;
 
-//     rk30_battery_table_info_dump(p);
 
-       if (rk30_adc_battery_get_charge_level(bat)){  //charge
+       if (1 == bat->charge_level){  //charge
+               if(0 == bat->start_voltage_status ){
                        if(BatVoltage >= (p[2*BATT_NUM +5])){
                                capacity = 100;
                        }       
@@ -859,17 +974,77 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba
                                        capacity = 0;
                                }
                                else{
-                                       for(i = BATT_NUM +6; i <2*BATT_NUM +6; i++){
+                                       for(i = BATT_NUM +6; i <2*BATT_NUM +5; i++){
 
-                                               if(((p[i]) <= BatVoltage) && (BatVoltage < (p[i+1]))){
-                                                       capacity = (i-(BATT_NUM +6))*10 + ((BatVoltage - p[i]) *  10)/ (p[i+1]- p[i]);
+                                               if(((p[i]) <= BatVoltage) && (BatVoltage <  (p[i+1]))){
+
+                                                               capacity = (i-(BATT_NUM +6))*10 + ((BatVoltage - p[i]) *  10)/ (p[i+1]- p[i]);
                                                        break;
                                                }
                                        }
                                }  
                        }
+               }
+               else{
 
-               }else{  //discharge
+                       DBG("start_voltage=%d,start_capacity =%d\n", bat->charge_start_voltage, bat->charge_start_capacity);
+                       DBG("charge_down_proportion =%d,charge_up_proprotion=%d\n",bat ->charge_down_proportion,bat ->charge_up_proprotion);
+                       for(i = BATT_NUM +6; i <2*BATT_NUM +5; i++)
+                               if(((p[i]) <= bat->charge_start_voltage) && (bat->charge_start_voltage <  (p[i+1])))    
+                                       bat->voltage_to_local = i;
+                               if(BatVoltage >= (p[2*BATT_NUM +5])){
+                                       capacity = 100;
+                               }else{  
+                               
+                                       if(BatVoltage <= (p[BATT_NUM +6])){
+                                               capacity = 0;
+                                               }else{
+
+                                                       if(BatVoltage <bat->charge_start_voltage){
+                                                               for(i = BATT_NUM +6; i <2*BATT_NUM +5; i++)
+                                                                       if(((p[i]) <= BatVoltage) && (BatVoltage <  (p[i+1]))){
+                                                                               if( p[i+1] < bat->charge_start_voltage ){
+                                                                                       capacity =bat->charge_start_capacity - ((p[i+1] -BatVoltage) * bat->charge_start_capacity/(bat->voltage_to_local -17+1))/ (p[i+1]- p[i]) - (bat->voltage_to_local- (i ))*bat->charge_start_capacity/(bat->voltage_to_local -17+1);
+                                                                                        DBG("1<<<<<<< %d  bat->voltage_to_local =%d capacity = %d BatVoltage =%d  p[i] = %d,p[i+1] = %d  \n", i, bat->voltage_to_local,capacity,BatVoltage,p[i], p[i+1]);
+                                                               
+                                                                               }
+                                                                               else {
+                                                                                       capacity =bat->charge_start_capacity - ((bat->charge_start_voltage -BatVoltage) * bat->charge_start_capacity/(bat->voltage_to_local -17+1) )/ (bat->charge_start_voltage - p[i]);
+                                                                                       DBG("2<<<<<< %d   capacity = %d BatVoltage =%d  p[i] = %d,p[i+1] = %d  \n", i,capacity,BatVoltage,p[i], p[i+1]);
+                                                                               }
+                                                                               break;
+                                                                       }
+
+
+                                                       }else{
+
+                                                                       if(BatVoltage > bat->charge_start_voltage){
+                                                                               for(i = BATT_NUM +6; i <2*BATT_NUM +5; i++)
+                                                                                       if(((p[i]) <= BatVoltage) && (BatVoltage <  (p[i+1]))){
+                                                                                               if( p[i] > bat->charge_start_voltage ){
+                                                                                                       capacity = bat->charge_start_capacity + (i +1- (bat->voltage_to_local))*(100- bat->charge_start_capacity )/( 10 -  (bat->voltage_to_local  - 17)) + (BatVoltage - p[i]) * (100- bat->charge_start_capacity )/( 10 -  (bat->voltage_to_local -17))/ (p[i+1]- p[i]);
+                                                                                                       DBG("3<<<<<<<< %d bat->voltage_to_local =%d  capacity = %d BatVoltage =%d  p[i] = %d,p[i+1] = %d  \n", i, bat->voltage_to_local,capacity,BatVoltage,p[i], p[i+1]);
+                                                                                               }
+                                                                                               else {
+                                                                                                      capacity = bat->charge_start_capacity + (BatVoltage - bat->charge_start_voltage) * (100- bat->charge_start_capacity )/( 10 -  (bat->voltage_to_local-17 )) /(p[i+1] - bat->charge_start_voltage );
+                                                                                                       DBG(" 4<<<<<<<<<%d bat->voltage_to_local =%d  capacity = %d BatVoltage =%d  p[i] = %d,p[i+1] = %d  \n", i,bat->voltage_to_local,capacity,BatVoltage,p[i], p[i+1]);
+                                                                                               }
+                                                                                               break;
+                                                                                       }
+
+                                                                       }else{
+
+                                                                               if(BatVoltage  ==  bat->charge_start_voltage)
+                                                                                       capacity = bat ->charge_start_capacity;
+                                                                               }
+                                                               }
+                                                       }
+                                       }
+
+                       }
+
+               }
+               else{  //discharge
                        if(BatVoltage >= (p[BATT_NUM +5])){
                                capacity = 100;
                        }       
@@ -878,7 +1053,7 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba
                                        capacity = 0;
                                }
                                else{
-                                       for(i = 6; i < BATT_NUM +6; i++){
+                                       for(i = 6; i < BATT_NUM +5; i++){
                                                if(((p[i]) <= BatVoltage) && (BatVoltage < (p[i+1]))){
                                                        capacity = (i-6)*10+ ((BatVoltage - p[i]) *10 )/ (p[i+1]- p[i]) ;
                                                        break;
@@ -891,27 +1066,35 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba
 
                }
 
-//     }
+       DBG("real_voltage_to_capacity =%d\n" ,capacity);
+
     return capacity;
 }
+#if  defined CONFIG_BATTERY_RK30_USB_CHARGE
 
-static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat)
+static void rk_usb_charger(struct rk30_adc_battery_data *bat)
 {
        int capacity = 0;
-//     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)  {
-               bat->gBatCapacityDisChargeCnt = 0;
-               bat->gBatCapacityChargeCnt    = 0;
-               return;
+       if((1 == bat ->charge_level)&&( 0 == bat ->start_voltage_status)){
+                       bat ->charge_start_voltage = bat ->bat_voltage;
+                       bat ->start_voltage_status = 1;
+                       bat ->charge_start_capacity = bat ->bat_capacity;
+                       if(bat ->charge_start_capacity%10 != 0){
+                               bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10+1;
+                               bat ->charge_down_proportion = bat ->charge_start_capacity/10+1;
+                       }else{
+                               bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10;
+                               bat ->charge_down_proportion = bat ->charge_start_capacity/10;
+
+
+                       }
        }
-       
+
        capacity = rk30_adc_battery_voltage_to_capacity(bat, bat->bat_voltage);
-           
-       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
@@ -919,77 +1102,175 @@ static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat)
                                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) >= timer_of_charge_sample){
-                               bat->gBatCapacityDisChargeCnt  = 0;
+                       if (++(bat->gBatCapacityusbChargeCnt) >= timer_of_charge_sample){
+                               bat->gBatCapacityusbChargeCnt  = 0;
                                if (bat->bat_capacity < 99){
                                        bat->bat_capacity++;
                                        bat->bat_change  = 1;
                                }
                        }
                        bat->gBatCapacityChargeCnt = 0;
-               }
-               else{  //   Êµ¼ÊµÄÈÝÁ¿±È²ÉÑù±È ÏÔʾµÄÈÝÁ¿Ð¡
-                           bat->gBatCapacityDisChargeCnt = 0;
-                           (bat->gBatCapacityChargeCnt)++;
-                               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 >= timer_of_charge_sample){
-                                               bat->gBatCapacityChargeCnt = 0;
-                                               if (bat->bat_capacity < 99){
-                                                       bat->bat_capacity++;
-                                                       bat->bat_change  = 1;
-                                               }
+                       bat ->gBatCapacityusbdisChargeCnt = 0;//get_suspend_state(void)
+               }else //if(( get_suspend_state() != PM_SUSPEND_MEM)&&(capacity < bat->bat_capacity)){
+               // if((gpio_get_value (bat->pdata->back_light_pin) == 1)&&(capacity < bat->bat_capacity)){
+               if((capacity < bat->bat_capacity)){
+                               DBG("USB CHARGE DOWN\n");
+
+               //      if (capacity < bat->bat_capacity){
+                               if(capacity <10){
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 40; // 13
+                               }else if(capacity < 20){
+                                       if(capacity + 3 > bat->bat_capacity  )
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -5;  //5s
+                                       else if(capacity  + 7 > bat->bat_capacity )
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -10; //10s
+                                       else if(capacity  + 10> bat->bat_capacity )
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -25; // 13
+                                       else
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 35; // 13
+                               }else{
+                                       if(capacity + 3 > bat->bat_capacity  )
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -5;  //5s
+                                       else if(capacity  + 7 > bat->bat_capacity )
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -10; //10s
+                                       else if(capacity  + 10> bat->bat_capacity )
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 15; // 13
+                                       else
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 20; // 13
+                       }
+                               
+                               if (++(bat->gBatCapacityusbdisChargeCnt) >= timer_of_discharge_sample){
+                                       bat->gBatCapacityusbdisChargeCnt = 0;
+                                       if (bat->bat_capacity > 0){
+                                               bat->bat_capacity-- ;
+                                               bat->bat_change  = 1;
                                        }
                                }
-                               else{
-#if 0                                  
-                                       if (capacity > capacitytmp){
-                                       //¹ý³ÌÖÐÈç¹ûµçѹÓÐÔö³¤£¬¶¨Ê±Æ÷¸´Î»£¬·ÀÖ¹¶¨Ê±Æ÷Ä£Äâ³äµç±Èʵ¼Ê³äµç¿ì
-                                               gBatCapacityChargeCnt = 0;
+                               
+                       //}
+                       bat->gBatCapacityusbChargeCnt  = 0;
+
+               }
+               else //if(get_suspend_state() == PM_SUSPEND_MEM){
+                       //if(gpio_get_value (bat->pdata->back_light_pin) == 0){
+                       {
+
+
+                       bat->gBatCapacityusbdisChargeCnt = 0;
+                       // (bat->gBatCapacityusbChargeCnt)++;
+                       if( is_charge_ok(bat) != INVALID_CHARGE_CHECK){
+                               if( is_charge_ok(bat) == CHARGE_IS_OK){
+
+                                       if (++bat->gBatCapacityusbChargeCnt >= timer_of_charge_sample-30){
+                                               bat->gBatCapacityusbChargeCnt = 0;
+                                                       if (bat->bat_capacity <= 99){
+                                                               bat->bat_capacity++;
+                                                               bat->bat_change  = 1;
+                                                       }
                                        }
-                                       else if (/*bat->bat_capacity >= 85) &&*/ (gBatCapacityChargeCnt > NUM_CHARGE_MAX_SAMPLE)){
-                                               gBatCapacityChargeCnt = (NUM_CHARGE_MAX_SAMPLE - NUM_CHARGE_MID_SAMPLE);
+                               }else{
+                                               if (capacity > bat->capacitytmp){
+                                                       bat->gBatCapacityChargeCnt = 0;
+                                               }else{
 
-                                               if (bat->bat_capacity < 99){
-                                               bat->bat_capacity++;
-                                               bat->bat_change  = 1;
+                                                       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){
+                                                                       bat->bat_capacity++;
+                                                                       bat->bat_change  = 1;
+                                                               }
+                                                       }
                                                }
                                        }
+
                                }
-#else                  //  ·ÀÖ¹µç³ØÀÏ»¯ºó³öÏֳ岻ÂúµÄÇé¿ö£¬
+                               else{
                                        if (capacity > bat->capacitytmp){
-                                       //¹ý³ÌÖÐÈç¹ûµçѹÓÐÔö³¤£¬¶¨Ê±Æ÷¸´Î»£¬·ÀÖ¹¶¨Ê±Æ÷Ä£Äâ³äµç±Èʵ¼Ê³äµç¿ì
-                                               bat->gBatCapacityChargeCnt = 0;
+                                                       bat->gBatCapacityChargeCnt = 0;
+                                       }else{
+                                               if ((bat->bat_capacity >= 85) &&(bat->gBatCapacityusbChargeCnt > NUM_CHARGE_MAX_SAMPLE)){
+                                                       bat->gBatCapacityusbChargeCnt = (NUM_CHARGE_MAX_SAMPLE - NUM_CHARGE_MID_SAMPLE);
+                                                               if (bat->bat_capacity <= 99){
+                                                                       bat->bat_capacity++;
+                                                                       bat->bat_change  = 1;
+                                                       }
+                                               }
                                        }
-                                       else{
+                       }
 
-                                               if ((bat->bat_capacity >= 85) &&((bat->gBatCapacityChargeCnt) > NUM_CHARGE_MAX_SAMPLE)){
-                                                       bat->gBatCapacityChargeCnt = (NUM_CHARGE_MAX_SAMPLE - NUM_CHARGE_MID_SAMPLE);
+               }
+               bat->capacitytmp = capacity;
 
+}
+#endif
+static void rk_ac_charger(struct rk30_adc_battery_data *bat)
+{
+       int capacity = 0;
+       int timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE;
+
+       if((1 == bat->charge_level)&&( 0 == bat->start_voltage_status)){
+               bat->charge_start_voltage = bat->bat_voltage;
+               bat->start_voltage_status = 1;
+               bat->charge_start_capacity = bat->bat_capacity;
+                       if(bat ->charge_start_capacity%10 != 0){
+                               bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10+1;
+                               bat ->charge_down_proportion = bat ->charge_start_capacity/10+1;
+                       }else{
+                               bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10;
+                               bat ->charge_down_proportion = bat ->charge_start_capacity/10;
+
+
+                       }
+       }
+       capacity = rk30_adc_battery_voltage_to_capacity(bat, bat->bat_voltage);
+               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->gBatCapacityacChargeCnt) >= timer_of_charge_sample){
+                               bat->gBatCapacityacChargeCnt  = 0;
+                               if (bat->bat_capacity < 99){
+                                       bat->bat_capacity++;
+                                       bat->bat_change  = 1;
+                               }
+                       }
+                       bat->gBatCapacityChargeCnt = 0;
+               }
+               else{  
+                           bat->gBatCapacityacChargeCnt = 0;
+                           (bat->gBatCapacityChargeCnt)++;
+                               if( is_charge_ok(bat) != INVALID_CHARGE_CHECK){
+                                       if( is_charge_ok(bat) == CHARGE_IS_OK){
+                                               if (bat->gBatCapacityChargeCnt >= timer_of_charge_sample){
+                                                       bat->gBatCapacityChargeCnt = 0;
                                                        if (bat->bat_capacity < 99){
                                                                bat->bat_capacity++;
                                                                bat->bat_change  = 1;
                                                        }
                                                }
+                                       }else{
+                                               if (capacity > bat->capacitytmp){
+                                                       bat->gBatCapacityChargeCnt = 0;
+                                               }
+                                               else{
+
+                                                       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){
+                                                                       bat->bat_capacity++;
+                                                                       bat->bat_change  = 1;
+                                                               }
+                                                       }
+                                               }
                                        }
-                               }
-#endif
 
-                       }
-                       else{
-                       //ûÓгäµçÂú¼ì²â½Å£¬³¤Ê±¼äÄÚµçѹÎޱ仯£¬¶¨Ê±Æ÷Ä£Äâ³äµç
+                       }else{
                                if (capacity > bat->capacitytmp){
-                               //¹ý³ÌÖÐÈç¹ûµçѹÓÐÔö³¤£¬¶¨Ê±Æ÷¸´Î»£¬·ÀÖ¹¶¨Ê±Æ÷Ä£Äâ³äµç±Èʵ¼Ê³äµç¿ì
                                        bat->gBatCapacityChargeCnt = 0;
                                }
                                else{
@@ -997,7 +1278,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;
                                                }
@@ -1007,17 +1288,42 @@ static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat)
 
                        }            
                }
-       }    
-       else{   
-       //·Åµçʱ,Ö»ÔÊÐíµçѹϽµ
+               bat->capacitytmp = capacity;
+}
+static void rk_battery_charger(struct rk30_adc_battery_data *bat)
+{
+
+       int capacity = 0;
+       int timer_of_discharge_sample = DISCHARGE_MIN_SECOND;
+       
+       capacity = rk30_adc_battery_voltage_to_capacity(bat, bat->bat_voltage);
+
                if (capacity < bat->bat_capacity){
-                       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 0
+                               if(capacity <10){
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 40; // 13
+                               }else 
+                               #endif
+                               if(capacity < 20){
+                                       if(capacity + 3 > bat->bat_capacity  )
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND -5;  //5s
+                                       else if(capacity  + 7 > bat->bat_capacity )
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND -10; //10s
+                                       else if(capacity  + 10> bat->bat_capacity )
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND -25; // 13
+                                       else
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND - 35; // 13
+                               }else{
+                                       if(capacity + 3 > bat->bat_capacity  )
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND -5;  //5s
+                                       else if(capacity  + 7 > bat->bat_capacity )
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND -10; //10s
+                                       else if(capacity  + 10> bat->bat_capacity )
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND - 15; // 13
+                                       else
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND - 20; // 13
 
+                       }
                        if (++(bat->gBatCapacityDisChargeCnt) >= timer_of_discharge_sample){
                                bat->gBatCapacityDisChargeCnt = 0;
                                if (bat->bat_capacity > 0){
@@ -1030,75 +1336,114 @@ static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat)
                        bat->gBatCapacityDisChargeCnt = 0;
                }
                bat->gBatCapacityChargeCnt = 0;
-       }
+               bat->gBatCapacityusbdisChargeCnt=0 ;
+               bat->gBatCapacityusbChargeCnt =0;
+               bat->gBatCapacityacChargeCnt = 0;
+               bat->start_voltage_status = 0;
+               
                bat->capacitytmp = capacity;
+
+
+
+}
+
+static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat)
+{
+//     int capacity = 0;
+//     int timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE;
+//     int timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE;
+
+       if (bat->bat_status_cnt < NUM_VOLTAGE_SAMPLE)  {
+               bat->gBatCapacityDisChargeCnt = 0;
+               bat->gBatCapacityChargeCnt    = 0;
+               bat->gBatCapacityacChargeCnt = 0;
+               return;
+       }
+       
+       if(1 == bat->charge_level){
+#if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)  
+               if(1 == bat->usb_charging)
+                       rk_usb_charger(bat);
+               else
+                       rk_ac_charger(bat);
+#else
+               rk_ac_charger(bat);
+#endif
+       }else{
+               rk_battery_charger(bat);
+
+       }
+       
 }
 
 //static int poweron_check = 0;
-static void rk30_adc_battery_poweron_capacity_check(void)
+static void rk30_adc_battery_poweron_capacity_check(struct rk30_adc_battery_data *bat)
 {
 
        int new_capacity, old_capacity;
         int cnt = 50 ;
 
-       new_capacity = gBatteryData->bat_capacity;
-
+       new_capacity = bat ->bat_capacity;
+               
        while( cnt -- ){
-           old_capacity = rk30_adc_battery_load_capacity();
-          // printk("------------------->> : %d \n",old_capacity);
-           if( old_capacity >= 0 ){
+               g_old_cap = g_old_cap + g_uboot_incre;
+               if(g_old_cap > 100)
+                       g_old_cap = 100;
+           old_capacity = g_old_cap;   // rk30_adc_battery_load_capacity();
+           if( old_capacity != -1 ){
                break ;
            }
            msleep(100);
        }
-//     printk("---------------------------------------------------------->> : %d \n",old_capacity);
+        printk("func:%s; line:%d; old_capacity = %d; new_capacity = %d; g_uboot_incre = %d\n", __func__, __LINE__, old_capacity, new_capacity,g_uboot_incre);
+
        if ((old_capacity < 0) || (old_capacity > 100)){
                old_capacity = new_capacity;
        }    
 
-       if (gBatteryData->bat_status == POWER_SUPPLY_STATUS_FULL){
+       if (bat ->bat_status == POWER_SUPPLY_STATUS_FULL){
                if (new_capacity > 80){
-                       gBatteryData->bat_capacity = 100;
+                       bat ->bat_capacity = 100;
                }
        }
-       else if (gBatteryData->bat_status != POWER_SUPPLY_STATUS_NOT_CHARGING){
+       else if (bat ->bat_status != POWER_SUPPLY_STATUS_NOT_CHARGING){
        //chargeing state
-       //ÎÊÌ⣺
-//     //1£©³¤Ê±¼ä¹Ø»ú·ÅÖú󣬿ª»úºó¶ÁÈ¡µÄÈÝÁ¿Ô¶Ô¶´óÓÚʵ¼ÊÈÝÁ¿Ôõô°ì£¿
-//     //2£©Èç¹û²»ÕâÑù×ö£¬¶Ìʱ¼ä¹Ø»úÔÙ¿ª»ú£¬Ç°ºóÈÝÁ¿²»Ò»ÖÂÓÖ¸ÃÔõô°ì£¿
-//     //3£©Ò»ÏÂÄÇÖÖ·½Ê½ºÏÊÊ£¿
-       //gBatteryData->bat_capacity = new_capacity;
-               gBatteryData->bat_capacity = (new_capacity > old_capacity) ? new_capacity : old_capacity;
+               bat->bat_capacity = (old_capacity < 10) ? (old_capacity + 2) : old_capacity;
        }else{
-
-               if(new_capacity > old_capacity + 50 )
-                       gBatteryData->bat_capacity = new_capacity;
-               else
-                       gBatteryData->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity;  //avoid the value of capacity increase 
+                       bat ->bat_capacity = old_capacity;
+               if(bat->bat_capacity == 100)
+                       bat->bat_capacity = 99;
+               if(bat->bat_capacity == 0)
+                       bat->bat_capacity =1;
        }
+       DBG("oldcapacity %d,newcapacity %d,capacity %d\n", old_capacity
+               , new_capacity, bat->bat_capacity);
 
-
-       printk("capacity = %d, new_capacity = %d, old_capacity = %d\n",gBatteryData->bat_capacity, new_capacity, old_capacity);
-
-       gBatteryData->bat_change = 1;
+       bat ->bat_change = 1;
 }
+#if  defined CONFIG_BATTERY_RK30_USB_CHARGE
+#define to_battery_usb_device_info(x) container_of((x), \
+               struct rk30_adc_battery_data, usb);
 
 static int rk30_adc_battery_get_usb_property(struct power_supply *psy, 
                                    enum power_supply_property psp,
                                    union power_supply_propval *val)
 {
-       charger_type_t charger;
-       charger =  CHARGER_USB;
+       struct rk30_adc_battery_data *bat=  to_battery_usb_device_info(psy);
 
        switch (psp) {
-       case POWER_SUPPLY_PROP_ONLINE:
-               if (psy->type == POWER_SUPPLY_TYPE_USB)
-                       val->intval = gBatteryData ->usb_charging;
-               //printk("%s:%d\n",__FUNCTION__,val->intval);
-               break;
+               case POWER_SUPPLY_PROP_ONLINE:
+                       if (psy->type == POWER_SUPPLY_TYPE_USB){
+                               val->intval = bat ->usb_charging;
+                               if (strstr(saved_command_line,"charger") == NULL){                                      
+                                       if( 1 == bat->charge_full_flag)
+                                               val->intval = 0;
+                               }
+                       }
+                       break;
 
-       default:
-               return -EINVAL;
+               default:
+                       return -EINVAL;
        }
        
        return 0;
@@ -1120,30 +1465,34 @@ static struct power_supply rk30_usb_supply =
        .properties     = rk30_adc_battery_usb_props,
        .num_properties = ARRAY_SIZE(rk30_adc_battery_usb_props),
 };
-
-#if defined(CONFIG_BATTERY_RK30_AC_CHARGE)
+#endif
 static irqreturn_t rk30_adc_battery_dc_wakeup(int irq, void *dev_id)
 {   
+       disable_irq_nosync(irq);
        queue_work(gBatteryData->wq, &gBatteryData->dcwakeup_work);
        return IRQ_HANDLED;
 }
 
+#define to_battery_ac_device_info(x) container_of((x), \
+               struct rk30_adc_battery_data, ac);
 
 static int rk30_adc_battery_get_ac_property(struct power_supply *psy,
                        enum power_supply_property psp,
                        union power_supply_propval *val)
 {
-       int ret = 0;
-       charger_type_t charger;
-       charger =  CHARGER_USB;
+       int ret;
+
+       struct rk30_adc_battery_data *bat = to_battery_ac_device_info(psy);
+
        switch (psp) {
        case POWER_SUPPLY_PROP_ONLINE:
-               if (psy->type == POWER_SUPPLY_TYPE_MAINS)
-               {
-                       //if (rk30_adc_battery_get_charge_level(gBatteryData))
-                       val->intval = gBatteryData ->ac_charging;
+               if (psy->type == POWER_SUPPLY_TYPE_MAINS){
+                       val->intval = bat ->ac_charging;
+                       if (strstr(saved_command_line,"charger")  == NULL ){
+                               if( 1 == bat->charge_full_flag)
+                                       val->intval = 0;
+                       }
                }
-               DBG("%s:%d\n",__FUNCTION__,val->intval);
                break;
                
        default:
@@ -1151,7 +1500,7 @@ static int rk30_adc_battery_get_ac_property(struct power_supply *psy,
                break;
        }
 
-       return ret;
+       return 0;
 }
 
 static enum power_supply_property rk30_adc_battery_ac_props[] = 
@@ -1169,35 +1518,34 @@ static struct power_supply rk30_ac_supply =
        .properties     = rk30_adc_battery_ac_props,
        .num_properties = ARRAY_SIZE(rk30_adc_battery_ac_props),
 };
-
 static void rk30_adc_battery_dcdet_delaywork(struct work_struct *work)
 {
+
        int ret;
        struct rk30_adc_battery_platform_data *pdata;
        int irq;
        int irq_flag;
-       
-       pdata    = gBatteryData->pdata;
-       irq        = gpio_to_irq(pdata->dc_det_pin);
-       irq_flag = gpio_get_value (pdata->dc_det_pin) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
-
-       rk28_send_wakeup_key(); // wake up the system
+       struct rk30_adc_battery_data  *bat = container_of((work), \
+               struct rk30_adc_battery_data, dcwakeup_work);
 
+       pdata    = bat->pdata;
+       irq        = gpio_to_irq(pdata->dc_det_pin);
        free_irq(irq, NULL);
+       msleep(10);
+       irq_flag = gpio_get_value (pdata->dc_det_pin) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
        ret = request_irq(irq, rk30_adc_battery_dc_wakeup, irq_flag, "ac_charge_irq", NULL);// reinitialize the DC irq 
        if (ret) {
                free_irq(irq, NULL);
        }
 
-       power_supply_changed(&rk30_ac_supply);
+       power_supply_changed(&bat ->ac);
+       rk_send_wakeup_key();
 
-       gBatteryData->bat_status_cnt = 0;        //the state of battery is change
+       bat ->bat_status_cnt = 0;        //the state of battery is change
 
 }
 
 
-#endif
-
 static int rk30_adc_battery_get_status(struct rk30_adc_battery_data *bat)
 {
        return (bat->bat_status);
@@ -1228,32 +1576,33 @@ static int rk30_adc_battery_get_property(struct power_supply *psy,
                                 union power_supply_propval *val)
 {              
        int ret = 0;
-
+       int voltage;
+       struct rk30_adc_battery_data  *bat = container_of((psy), \
+                       struct rk30_adc_battery_data, bat);
        switch (psp) {
                case POWER_SUPPLY_PROP_STATUS:
-                       val->intval = rk30_adc_battery_get_status(gBatteryData);
+                       val->intval = rk30_adc_battery_get_status(bat);
                        DBG("gBatStatus=%d\n",val->intval);
                        break;
                case POWER_SUPPLY_PROP_HEALTH:
-                       val->intval = rk30_adc_battery_get_health(gBatteryData);
+                       val->intval = rk30_adc_battery_get_health(bat);
                        DBG("gBatHealth=%d\n",val->intval);
                        break;
                case POWER_SUPPLY_PROP_PRESENT:
-                       val->intval = rk30_adc_battery_get_present(gBatteryData);
+                       val->intval = rk30_adc_battery_get_present(bat);
                        DBG("gBatPresent=%d\n",val->intval);
                        break;
                case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-                       val ->intval = rk30_adc_battery_get_voltage(gBatteryData);
+               //      val ->intval = rk30_adc_battery_get_voltage(bat);
+                       voltage = rk30_adc_battery_get_voltage(bat);
+                       val->intval = voltage*1000;
                        DBG("gBatVoltage=%d\n",val->intval);
                        break;
-               //      case POWER_SUPPLY_PROP_CURRENT_NOW:
-               //              val->intval = 1100;
-               //              break;
                case POWER_SUPPLY_PROP_CAPACITY:
                        if(battery_test_flag == 2)
                                val->intval = 50;
                        else
-                               val->intval = rk30_adc_battery_get_capacity(gBatteryData);
+                               val->intval = rk30_adc_battery_get_capacity(bat);
                        DBG("gBatCapacity=%d%%\n",val->intval);
                        break;
                case POWER_SUPPLY_PROP_TECHNOLOGY:
@@ -1279,7 +1628,6 @@ static enum power_supply_property rk30_adc_battery_props[] = {
        POWER_SUPPLY_PROP_HEALTH,
        POWER_SUPPLY_PROP_PRESENT,
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
-//     POWER_SUPPLY_PROP_CURRENT_NOW,
        POWER_SUPPLY_PROP_TECHNOLOGY,
        POWER_SUPPLY_PROP_CAPACITY,
        POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
@@ -1298,51 +1646,62 @@ static struct power_supply rk30_battery_supply =
 };
 
 #ifdef CONFIG_PM
-static void rk30_adc_battery_resume_check(void)
+static void rk30_adc_battery_resume_check(struct rk30_adc_battery_data *bat)
 {
        int i;
        int level,oldlevel;
        int new_capacity, old_capacity;
-       struct rk30_adc_battery_data *bat = gBatteryData;
+//     struct rk30_adc_battery_data *bat = gBatteryData;
+
+       bat ->old_charge_level = -1;
+       bat ->pSamples = bat->adc_samples;
 
-       bat->old_charge_level = -1;
-       pSamples = bat->adc_samples;
+       bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
 
-       adc_sync_read(bat->client);                             //start adc sample
-       level = oldlevel = rk30_adc_battery_status_samples(bat);//init charge status
+       level = oldlevel =  rk_battery_get_status(bat);//rk30_adc_battery_status_samples(bat);//init charge status
 
        for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++) {               //0.3 s   
        
                mdelay(1);
                rk30_adc_battery_voltage_samples(bat);              //get voltage
-               level = rk30_adc_battery_status_samples(bat);       //check charge status
+               level =          rk_battery_get_status(bat);// rk30_adc_battery_status_samples(bat);       //check charge status
                if (oldlevel != level){         
                    oldlevel = level;                               //if charge status changed, reset sample
                    i = 0;
                }        
        }
        new_capacity = rk30_adc_battery_voltage_to_capacity(bat, bat->bat_voltage);
-       old_capacity =gBatteryData-> suspend_capacity;
+       old_capacity =bat-> suspend_capacity;
 
-       if (bat->bat_status != POWER_SUPPLY_STATUS_NOT_CHARGING){
+       //if (bat->bat_status != POWER_SUPPLY_STATUS_NOT_CHARGING){
+       if( 1 == level ){
        //chargeing state
-               bat->bat_capacity = (new_capacity > old_capacity) ? new_capacity : old_capacity;
+               bat->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity;
        }
        else{
                bat->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity;  // aviod the value of capacity increase    dicharge
        }
 
+               if (batt_gpio_is_valid(bat->pdata->batt_low_pin)) {
+                       if (gpio_get_value(bat ->pdata->batt_low_pin) == bat ->pdata->batt_low_level)
+                               bat->bat_capacity = 0;
+
+               }
+       return;
 }
 
 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);
+       struct rk30_adc_battery_data *data = platform_get_drvdata(dev);
+
+       data ->suspend_capacity = data->bat_capacity;
+       data ->suspend_time = get_seconds();
+       cancel_delayed_work(&data ->delay_work);
        
-       if( gBatteryData->pdata->batt_low_pin != INVALID_GPIO){
+       if (batt_gpio_is_valid(data->pdata->batt_low_pin)) {
                
-               irq = gpio_to_irq(gBatteryData->pdata->batt_low_pin);
+               irq = gpio_to_irq(data ->pdata->batt_low_pin);
                enable_irq(irq);
                enable_irq_wake(irq);
        }
@@ -1353,11 +1712,17 @@ static int rk30_adc_battery_suspend(struct platform_device *dev, pm_message_t st
 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(100));
-       if( gBatteryData->pdata->batt_low_pin != INVALID_GPIO){
+       struct rk30_adc_battery_data *data = platform_get_drvdata(dev);
+        if( data->bat_capacity < 10 ){
+               wake_lock_timeout(&batt_wake_lock_detect_lowpower,15*HZ);
+               data->bat_change  = 1;
+       }
+       data ->resume_time = get_seconds();
+       data ->resume = true;
+       queue_delayed_work(data->wq, &data ->delay_work, msecs_to_jiffies(100));
+       if (batt_gpio_is_valid(data->pdata->batt_low_pin)) {
                
-               irq = gpio_to_irq(gBatteryData->pdata->batt_low_pin);
+               irq = gpio_to_irq(data ->pdata ->batt_low_pin);
                disable_irq_wake(irq);
                disable_irq(irq);
        }
@@ -1372,71 +1737,83 @@ static int rk30_adc_battery_resume(struct platform_device *dev)
 unsigned long AdcTestCnt = 0;
 static void rk30_adc_battery_timer_work(struct work_struct *work)
 {
+       struct rk30_adc_battery_data  *bat = container_of((work), struct
+               rk30_adc_battery_data, delay_work.work);
+
 #ifdef CONFIG_PM
-       if (gBatteryData->resume) {
-               rk30_adc_battery_resume_check();
-               gBatteryData->resume = false;
+       if (bat ->resume) {
+       //      if( (bat->resume_time - bat->suspend_time) >= 1800 )
+                       rk30_adc_battery_resume_check(bat);
+               //else
+                       //bat->bat_capacity = bat->suspend_capacity;
+               bat ->resume = false;
+               bat ->bat_change =1;
        }
 #endif
-
-
-       rk30_adc_battery_status_samples(gBatteryData);
-
-       if (gBatteryData->poweron_check){   
-               gBatteryData->poweron_check = 0;
-               rk30_adc_battery_poweron_capacity_check();
+       bat->stop_check = 1;
+       if( 1 == bat ->lower_power_flag ){
+                       bat ->bat_capacity = 0;
+                       bat ->bat_change =1;
+       }
+       if (bat ->poweron_check){   
+               bat ->poweron_check = 0;
+               rk30_adc_battery_poweron_capacity_check(bat);
        }
 
-       rk30_adc_battery_voltage_samples(gBatteryData);
-       rk30_adc_battery_capacity_samples(gBatteryData);
+       bat ->charge_level = rk_battery_get_status(bat);
+       DBG("bat ->charge_level =%d\n", bat ->charge_level);
+       rk30_adc_battery_status_samples(bat);
+       rk30_adc_battery_voltage_samples(bat);
+       rk30_adc_battery_capacity_samples(bat);
 
-       if( 0 == gBatteryData ->pdata ->charging_sleep){
-               if( 1 == rk30_adc_battery_get_charge_level(gBatteryData)){  // charge
-                       if(0 == gBatteryData->status_lock ){                    
+       if( 0 == bat ->pdata ->charging_sleep){
+               if( 1 == bat->charge_level){  // charge
+                       if(0 == bat->status_lock ){                     
                                wake_lock(&batt_wake_lock);  //lock
-                               gBatteryData->status_lock = 1; 
+                               bat ->status_lock = 1; 
                        }
                }
                else{
-                       if(1 == gBatteryData->status_lock ){                    
+                       if(1 == bat ->status_lock ){                    
                                wake_unlock(&batt_wake_lock);  //unlock
-                               gBatteryData->status_lock = 0; 
+                               bat ->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);
-               }
+       if(bat ->bat_change){
+               bat ->bat_change= 0;
+               if (strstr(saved_command_line,"charger") == NULL){       //when low charging-current,not in charging-displays   
+                       if(0 == bat ->bat_capacity){
+                               bat ->ac_charging = 0;
+                               bat ->usb_charging = 0;
 
+                       }
+               }
+               // rk30_adc_battery_put_capacity(bat ->bat_capacity);
+               power_supply_changed(&bat ->bat);
+               power_supply_changed(&bat ->ac);
+#if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
+               power_supply_changed(&bat ->usb);
 #endif
-                if(1 == gBatteryData->pdata->spport_usb_charging){
-                       power_supply_changed(&rk30_usb_supply);
-                }
-
 
        }
 
-       if (rk30_battery_dbg_level){
+       //if (rk30_battery_dbg_level){
                if (++AdcTestCnt >= 2)
                        {
                        AdcTestCnt = 0;
 
-                       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);
+                       DBG("Status = %d, RealAdcVal = %d, RealVol = %d,gBatVol = %d, gBatCap = %d, RealCapacity = %d, batt_dischargecnt = %d\n,  chargecnt = %d,ac_count = %d, usb_count =%d ,usb_dischargecount =%d\n", 
+                       bat ->bat_status, bat ->adc_val, rk_adc_voltage(bat, bat ->adc_val), 
+                       bat ->bat_voltage, bat ->bat_capacity, bat ->capacitytmp, bat ->gBatCapacityDisChargeCnt, bat ->gBatCapacityChargeCnt,
+                       bat ->gBatCapacityacChargeCnt, bat ->gBatCapacityusbChargeCnt, bat ->gBatCapacityusbdisChargeCnt);
 
                }
-       }
-       queue_delayed_work(gBatteryData->wq, &gBatteryData->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS));
+       //}
+       queue_delayed_work(bat ->wq, &bat ->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS));
 
 }
 
@@ -1444,65 +1821,46 @@ static void rk30_adc_battery_timer_work(struct work_struct *work)
 static int rk30_adc_battery_io_init(struct rk30_adc_battery_platform_data *pdata)
 {
        int ret = 0;
-       
-       if (pdata->io_init) {
-               pdata->io_init();
-               return 0;
-       }
-       
-       //charge control pin
-       if (pdata->charge_set_pin != INVALID_GPIO){
-               ret = gpio_request(pdata->charge_set_pin, NULL);
-               if (ret) {
-                       printk("failed to request dc_det gpio\n");
-                       goto error;
-                       }
-               gpio_direction_output(pdata->charge_set_pin, 1 - pdata->charge_set_level);
-       }
-       
-       //dc charge detect pin
-       if (pdata->dc_det_pin != INVALID_GPIO){
+
+       if (batt_gpio_is_valid(pdata->dc_det_pin)) {
                ret = gpio_request(pdata->dc_det_pin, NULL);
                if (ret) {
-                       printk("failed to request dc_det gpio\n");
+                       pr_info("failed to request dc_det gpio\n");
                        goto error;
                }
        
-               gpio_pull_updown(pdata->dc_det_pin, GPIOPullUp);//important
                ret = gpio_direction_input(pdata->dc_det_pin);
                if (ret) {
-                       printk("failed to set gpio dc_det input\n");
+                       pr_info("failed to set gpio dc_det input\n");
                        goto error;
                }
        }
        
        //charge ok detect
-       if (pdata->charge_ok_pin != INVALID_GPIO){
+       if (batt_gpio_is_valid(pdata->charge_ok_pin)) {
                ret = gpio_request(pdata->charge_ok_pin, NULL);
                if (ret) {
-                       printk("failed to request charge_ok gpio\n");
+                       pr_err("failed to request charge_ok gpio\n");
                        goto error;
                }
        
-               gpio_pull_updown(pdata->charge_ok_pin, GPIOPullUp);//important
                ret = gpio_direction_input(pdata->charge_ok_pin);
                if (ret) {
-                       printk("failed to set gpio charge_ok input\n");
+                       pr_err("failed to set gpio charge_ok input\n");
                        goto error;
                }
        }
        //batt low pin
-       if( pdata->batt_low_pin != INVALID_GPIO){
+       if (batt_gpio_is_valid(pdata->batt_low_pin)) {
                ret = gpio_request(pdata->batt_low_pin, NULL);
                if (ret) {
-                       printk("failed to request batt_low_pin gpio\n");
+                       pr_err("failed to request batt_low_pin gpio\n");
                        goto error;
                }
        
-               gpio_pull_updown(pdata->batt_low_pin, GPIOPullUp); 
                ret = gpio_direction_input(pdata->batt_low_pin);
                if (ret) {
-                       printk("failed to set gpio batt_low_pin input\n");
+                       pr_err("failed to set gpio batt_low_pin input\n");
                        goto error;
                }
        }
@@ -1513,116 +1871,199 @@ error:
 }
 
 extern void kernel_power_off(void);
+int get_battery_status(void)
+{
+       return system_lowerpower;
+}
+static int rk_adc_battery_poweron_status(struct rk30_adc_battery_data *bat)
+{
+       int status; 
+#if  defined CONFIG_BATTERY_RK30_USB_CHARGE
+       int otg_status = 0;
+#endif
+
+//     struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+
+       if (get_ac_status(bat) ){               
+                       bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+                       bat -> ac_charging = 1;         
+                       if (is_charge_ok(bat)  == 1){
+                               bat->bat_status = POWER_SUPPLY_STATUS_FULL;
+                               bat->bat_capacity = 100;
+                       }
+                       power_supply_changed(&bat ->ac);
+
+       }
+#if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
+       otg_status = dwc_otg_check_dpdm();
+       if( 0 != otg_status ){
+               bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+               if (is_charge_ok(bat)  == 1){
+                       bat->bat_status = POWER_SUPPLY_STATUS_FULL;
+                       bat->bat_capacity = 100;
+               }
+       }
+       
+       if(otg_status == 1){
+               bat->usb_charging = 1;
+               if(bat -> pdata ->control_usb_charging)
+                       bat -> pdata ->control_usb_charging(0);
+       }else if(otg_status == 2){
+               bat->usb_charging = 0;
+               bat -> ac_charging = 1;
+               if(bat -> pdata ->control_usb_charging)
+                       bat -> pdata ->control_usb_charging(1); 
+       }else{
+               bat->usb_charging = 0;
+       }
+       printk("charge_status = %d\n",otg_status);
+#endif
+       power_supply_changed(&bat ->ac);
+#if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
+       power_supply_changed(&bat ->usb);
+#endif
+       if((bat -> ac_charging == 1)||(bat->usb_charging == 1)){
+               bat ->old_charge_level =1;
+               bat->charge_level = 1;
+               status =1;
+       }else{
+               bat ->old_charge_level =0;
+               bat->charge_level = 0;
+               status =0;
+       }
+       return status;  
+
+
+}
 static void rk30_adc_battery_check(struct rk30_adc_battery_data *bat)
 {
        int i;
        int level,oldlevel;
-       struct rk30_adc_battery_platform_data *pdata = bat->pdata;
-       //printk("%s--%d:\n",__FUNCTION__,__LINE__);
+//     struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+       int check_data[NUM_VOLTAGE_SAMPLE];
+       //bat ->old_charge_level
+//     pSamples = bat->adc_samples;
 
-       bat->old_charge_level = -1;
-       bat->capacitytmp = 0;
-       bat->suspend_capacity = 0;
-       
-       pSamples = bat->adc_samples;
 
-       adc_sync_read(bat->client);                             //start adc sample
-       level = oldlevel = rk30_adc_battery_status_samples(bat);//init charge status
+       bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
+
+       DBG("first_adc_value is  %d\n", bat->adc_val);
+       level = oldlevel =       rk_adc_battery_poweron_status(bat);// rk30_adc_battery_status_samples(bat);//init charge status
 
-       bat->full_times = 0;
        for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++){                //0.3 s
                mdelay(1);
                rk30_adc_battery_voltage_samples(bat);              //get voltage
                //level = rk30_adc_battery_status_samples(bat);       //check charge status
-               level = rk30_adc_battery_get_charge_level(bat);
+#if 0
+               level = rk_adc_battery_poweron_status(bat);
 
                if (oldlevel != level){
                        oldlevel = level;                               //if charge status changed, reset sample
                        i = 0;
-               }        
+               }  
+#endif
        }
-
-       bat->bat_capacity = rk30_adc_battery_voltage_to_capacity(bat, bat->bat_voltage);  //init bat_capacity
-
+       for(i=0; i< NUM_VOLTAGE_SAMPLE; i++){
+               mdelay(10);
+               check_data[i] = bat->adc_val;
+               
+               bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
+               bat->adc_value += check_data[i];
+       }
+       bat->adc_value  /=  NUM_VOLTAGE_SAMPLE;
        
-       bat->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
-       if (rk30_adc_battery_get_charge_level(bat)){
-               bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
-
-               if (pdata->charge_ok_pin != INVALID_GPIO){
-                       if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level){
+       bat->bat_capacity = rk30_adc_battery_voltage_to_capacity(bat, bat->bat_voltage);  //init bat_capacity
+       bat->capacitytmp = bat->bat_capacity;
+       level = rk_adc_battery_poweron_status(bat);
+       if((1 == level)&&(0 == bat->start_voltage_status )){
+                       bat->charge_start_voltage = bat->bat_voltage;
+                       bat->start_voltage_status = 1;
+                       bat->charge_start_capacity = bat->bat_capacity;
+                       bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10+1;
+                       bat ->charge_down_proportion = bat ->charge_start_capacity/10+1;
+       }
+#if 0  
+       if (get_ac_status(bat) ){               
+                       bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+                       bat -> ac_charging = 1;         
+                       if (is_charge_ok(bat)  == 1){
                                bat->bat_status = POWER_SUPPLY_STATUS_FULL;
                                bat->bat_capacity = 100;
                        }
+       }
+#if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
+       if( 0 != dwc_otg_check_dpdm() ){
+               bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+               if (is_charge_ok(bat)  == 1){
+                       bat->bat_status = POWER_SUPPLY_STATUS_FULL;
+                       bat->bat_capacity = 100;
                }
        }
-
-
-
-#if 0
-#if 1
-       rk30_adc_battery_poweron_capacity_check();
-#else
-       gBatteryData->poweron_check = 1;
+       
+       if(dwc_otg_check_dpdm() == 1){
+               bat->usb_charging = 1;
+               if(bat -> pdata ->control_usb_charging)
+                       bat -> pdata ->control_usb_charging(0);
+       }else if(dwc_otg_check_dpdm() == 2){
+               bat->usb_charging = 0;
+               bat -> ac_charging = 1;
+               if(bat -> pdata ->control_usb_charging)
+                       bat -> pdata ->control_usb_charging(1); 
+       }else{
+               bat->usb_charging = 0;
+       }
 #endif
-       gBatteryData->poweron_check = 0;
+       power_supply_changed(&bat ->ac);
+#if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
+       power_supply_changed(&bat ->usb);
 #endif
-/*******************************************
-//¿ª»ú²ÉÑùµ½µÄµçѹºÍÉϴιػú±£´æµçѹÏà²î½Ï´ó£¬Ôõô´¦Àí£¿
-if (bat->bat_capacity > old_capacity)
-{
-if ((bat->bat_capacity - old_capacity) > 20)
-{
-
-}
-}
-else if (bat->bat_capacity < old_capacity)
-{
-if ((old_capacity > bat->bat_capacity) > 20)
-{
+       if((bat -> ac_charging == 1)||(bat->usb_charging == 1)){
+               bat ->old_charge_level =1;
+               bat->charge_level = 1;
+       }
 
-}
-}
-*********************************************/
-       if (bat->bat_capacity == 0) bat->bat_capacity = 1;
+#endif
+#if 0
+       if (bat->bat_capacity == 0) {
+               bat->bat_capacity = 1;
+               system_lowerpower = 1;
+       }
+#endif
 
+       if(0 !=bat ->pdata->low_voltage_protection ){
+               if (bat->bat_voltage <= bat->pdata->low_voltage_protection) {
+                       system_lowerpower = 1;
+                       printk("protection lower power .....\n");
+                       }
+       }else{
+               if (bat->bat_voltage <= BATT_ZERO_VOL_VALUE) {
+                       system_lowerpower = 1;
+                       pr_info("lower power bat->bat_voltage = %d\n"
+                               , bat->bat_voltage);
+                       }
+       }       
 
-       if(1==gBatteryData -> pdata->low_voltage_protection)
+#if 0
                if ((bat->bat_voltage <= BATT_ZERO_VOL_VALUE)&&(bat->bat_status != POWER_SUPPLY_STATUS_CHARGING)){
                        kernel_power_off();
                }
-
-}
-
-static void rk30_adc_battery_callback(struct adc_client *client, void *param, int result)
-{
-#if 0
-       struct rk30_adc_battery_data  *info = container_of(client, struct rk30_adc_battery_data,
-               client);
-       info->adc_val = result;
 #endif
-       if (result < 0){
-               pr_bat("adc_battery_callback    resule < 0 , the value ");
-               return;
-       }
-       else{
-               gBatteryData->adc_val = result;
-               pr_bat("result = %d, gBatteryData->adc_val = %d\n", result, gBatteryData->adc_val );
-       }
-       return;
+
 }
 
-#if 1
 static void rk30_adc_battery_lowerpower_delaywork(struct work_struct *work)
 {
        int irq;
-       if( gBatteryData->pdata->batt_low_pin != INVALID_GPIO){
-               irq = gpio_to_irq(gBatteryData->pdata->batt_low_pin);
+
+       struct rk30_adc_battery_data  *bat = container_of((work), \
+                       struct rk30_adc_battery_data, lowerpower_work);
+
+       if (batt_gpio_is_valid(bat->pdata->batt_low_pin)) {
+               irq = gpio_to_irq(bat ->pdata ->batt_low_pin);
                disable_irq(irq);
        }
 
        printk("lowerpower\n");
-       rk28_send_wakeup_key(); // wake up the system   
        return;
 }
 
@@ -1632,159 +2073,400 @@ static irqreturn_t rk30_adc_battery_low_wakeup(int irq,void *dev_id)
        queue_work(gBatteryData->wq, &gBatteryData->lowerpower_work);
        return IRQ_HANDLED;
 }
+static void rk_lowerpower_check(struct rk30_adc_battery_data *bat)
+{
+       int adc_val;
+       int i;
+       int check_data[NUM_VOLTAGE_SAMPLE];
+       
+       for(i=0; i< NUM_VOLTAGE_SAMPLE; i++){
+               mdelay(10);
+               bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
+               check_data[i] = bat->adc_val;   
+
+               adc_val += check_data[i];
+       }
+       adc_val /=NUM_VOLTAGE_SAMPLE;
+
+       DBG(">>>>>>>>>>>one>>>%d, two<<<<<%d<<<<\n",bat->adc_value,adc_val);
+       DBG(">>>>>>>>>>>firset-value>>>%d, second-value<<<<<%d<<<<\n",rk_adc_voltage(bat, bat->adc_value),rk_adc_voltage(bat, adc_val));
+
+       if((adc_val >= bat->adc_value+5) &&(bat->bat_status == POWER_SUPPLY_STATUS_NOT_CHARGING ) )//
+       {
+               printk("%d,%d\n",adc_val,bat->adc_value);
+               printk("lower-power shutdown");
+               kernel_power_off();
+       }
 
+}
+static void rk_adc_battery_check_work(struct work_struct *work)
+{
+       struct rk30_adc_battery_data  *bat =
+               container_of((work), struct
+               rk30_adc_battery_data, check_work.work);
+       
+               if(1 == get_ac_status(bat)){
+                       bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+                       bat -> ac_charging = 1;
+               }
+               
+               power_supply_changed(&bat ->ac);
+       if(bat->stop_check != 1)
+               queue_delayed_work(bat ->wq, &bat ->check_work, msecs_to_jiffies(TIMER_MS_COUNTS));
+
+}
+static void poweron_lowerpoer_handle(struct rk30_adc_battery_data *bat)
+{
+#ifdef CONFIG_LOGO_LOWERPOWER_WARNING
+       if((1 ==  get_battery_status())&&(bat->bat_status == POWER_SUPPLY_STATUS_NOT_CHARGING )){
+               mdelay (1500);
+               kernel_power_off();
+       }
 #endif
 
+}
+static int battery_notifier_call(struct notifier_block *nb,
+               unsigned long event, void *data)
+{
+       struct rk30_adc_battery_data *bat=
+               container_of(nb, struct rk30_adc_battery_data, battery_nb);
+
+       switch (event) {
+       case 1:
+               rk_lowerpower_check(bat);
+               break;
+
+       case 2:
+               poweron_lowerpoer_handle(bat);
+               break;
+       default:
+               return NOTIFY_OK;
+       }
+       return NOTIFY_OK;
+}
+
+#ifdef CONFIG_OF
+static int rk31_adcbat_parse_dt(struct platform_device *pdev, struct
+rk30_adc_battery_platform_data *data)
+{
+       struct device_node *node = pdev->dev.of_node;
+       enum of_gpio_flags flags;
+       struct property *prop;
+       int length;
+       u32 value;
+       int ret;
+       int i;
+       size_t size;
+
+       struct iio_channel *channels;
+       int num = 0;
+
+       channels = iio_channel_get_all(&pdev->dev);
+       if (IS_ERR(channels))
+               pr_err("get adc channels fails\n");
+       while (channels[num].indio_dev)
+               num++;
+       data->chan = &channels[0];
+       if (num > 1)
+               data->ref_voltage_chan = &channels[1];
+       ret = of_property_read_u32(node, "auto_calibration", &value);
+       if (ret < 0) {
+               pr_info("%s:unsupport auto_calibration\n", __func__);
+               value = 0;
+       }
+       data->auto_calibration = value;
+
+       ret = of_property_read_u32(node, "ref_voltage", &value);
+       if (ret < 0) {
+               pr_info("%s:unsupport ref_voltage\n", __func__);
+               value = 0;
+       }
+       data->reference_voltage = value;
+
+       /* determine the number of config info */
+       prop = of_find_property(node, "bat_table", &length);
+       if (!prop)
+               return -EINVAL;
+
+       length /= sizeof(u32);
+
+       if (length > 0) {
+               size = (sizeof(*data->dts_batt_table)) * length;
+               data->dts_batt_table =
+                       devm_kzalloc(&(pdev->dev), size, GFP_KERNEL);
+               if (!data->dts_batt_table)
+                       return -ENOMEM;
+
+               ret = of_property_read_u32_array(node
+                       , "bat_table", data->dts_batt_table, length);
+               if (ret < 0)
+                       return ret;
+       }
+
+       for (i = 4; i < length; i++) {
+               batt_table[i] = data->dts_batt_table[i];
+
+               pr_info("data->dts_batt_table[ %d ] %d %d\n", i
+                       , data->dts_batt_table[i], batt_table[i]);
+       }
+       data->dc_det_pin = of_get_named_gpio_flags(node
+               , "dc_det_gpio", 0, &flags);
+       if (data->dc_det_pin == -EPROBE_DEFER)
+               pr_info("%s  dc_det_gpio error\n", __func__);
+
+       if (batt_gpio_is_valid(data->dc_det_pin))
+               data->dc_det_level = (flags & OF_GPIO_ACTIVE_LOW)
+               ?  RK30_GPIO_LOW : RK30_GPIO_HIGH;
+
+       data->batt_low_pin = of_get_named_gpio_flags(node
+               , "bat_low_gpio", 0, &flags);
+       if (data->batt_low_pin == -EPROBE_DEFER)
+               pr_info("%s  bat_low_gpio error\n", __func__);
+
+       if (batt_gpio_is_valid(data->batt_low_pin))
+               data->batt_low_level = (flags & OF_GPIO_ACTIVE_LOW)
+               ?  RK30_GPIO_LOW : RK30_GPIO_HIGH;
+
+       data->charge_ok_pin = of_get_named_gpio_flags(node
+               , "chg_ok_gpio", 0, &flags);
+       if (data->charge_ok_pin == -EPROBE_DEFER)
+               pr_info("%s  chg_ok_gpio error\n", __func__);
+
+       if (batt_gpio_is_valid(data->charge_ok_pin))
+               data->charge_ok_level = (flags & OF_GPIO_ACTIVE_LOW)
+               ? RK30_GPIO_LOW : RK30_GPIO_HIGH;
+
+       ret = of_property_read_u32(node, "is_dc_charge", &value);
+       if (ret < 0) {
+               pr_info("%s:hardware unsupport dc charge\n", __func__);
+               value = 0;
+       }
+       data->is_dc_charge = value;
+
+       ret = of_property_read_u32(node, "is_usb_charge"
+               , &value);
+       if (ret < 0) {
+               pr_err("%s:hardware unsupport usb charge\n", __func__);
+               value = 0;
+       }
+       data->is_usb_charge = value;
+
+       pr_info("rk30 battery:support %s %s charger\n",
+               data->is_dc_charge ? "DC" : ""
+               , data->is_usb_charge ? "USB" : "");
+
+       return 0;
+}
+#else
+static int rk31_adcbat_parse_dt(struct platform_device
+*dev, struct rk30_adc_battery_platform_data *data)
+{
+       return -ENODEV;
+}
+#endif
+
+
 static int rk30_adc_battery_probe(struct platform_device *pdev)
 {
+
        int    ret;
        int    irq;
        int    irq_flag;
-       struct adc_client                   *client;
        struct rk30_adc_battery_data          *data;
-       struct rk30_adc_battery_platform_data *pdata = pdev->dev.platform_data;
+       struct rk30_adc_battery_platform_data *pdata;
+#ifdef CONFIG_MACH_RK_FAC
+       int i;
+       for(i=0;i<BATT_NUM;i++)
+       {
+               batt_table[6+i]=pdata->chargeArray[i];
+               batt_table[BATT_NUM+6+i]=pdata->chargeArray[i];
+       }
+#endif         
        gSecondsCnt = get_seconds();
-       data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (data == NULL) {
+       /*data = kzalloc(sizeof(*data), GFP_KERNEL);*/
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (data == NULL)
                ret = -ENOMEM;
-               goto err_data_alloc_failed;
-       }
+
+       /*pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);*/
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (pdata == NULL)
+               ret = -ENOMEM;
+
        memset(data, 0, sizeof(struct rk30_adc_battery_data));
        gBatteryData = data;
-
        platform_set_drvdata(pdev, data);
 
        data->pdata = pdata;
        data->status_lock = 0;  
-       ret = rk30_adc_battery_io_init(pdata);
+       data->old_charge_level = -1;
+       data->capacitytmp = 0;
+       data->suspend_capacity = 0;
+       data->ac_charging = 0;
+       data->usb_charging = 0;
+       data->full_times = 0;
+       data->gBatCapacityDisChargeCnt =0;
+       data->gBatCapacityChargeCnt=0;
+       data->gBatCapacityusbdisChargeCnt=0 ;
+       data->gBatCapacityusbChargeCnt =0;
+       data->gBatCapacityacChargeCnt = 0;
+       data->charge_source_now = 0;
+       data->charge_soure_old = 0;
+       data->start_voltage_status = 0;
+       data->charge_full_flag =0;
+       data->pSamples = data->adc_samples;
+       data->lower_power_flag = 0;
+       data->capacitytmp = 0;
+       data->time_to_full = 0;
+       data->stop_check = 0;
+       data->voltage_to_local = 0;
+
+       data->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+       wake_lock_init(&batt_wake_lock, WAKE_LOCK_SUSPEND, "batt_lock");        
+       wake_lock_init(&charge_display_lock, WAKE_LOCK_SUSPEND, "charge_display_lock"); //charge_display_lock
+       wake_lock_init(&batt_wake_lock_detect_lowpower
+               , WAKE_LOCK_SUSPEND, "lowpower_lock");
+
+       ret = rk31_adcbat_parse_dt(pdev, data->pdata);
+       /*ret = rk31_adcbat_parse_dt(pdev, pdata);*/
+       if (ret < 0) {
+               pr_err("failed to find rk30 adc battery platform data\n");
+               goto err_io_init;
+       }
+
+       ret = rk30_adc_battery_io_init(data->pdata);
         if (ret) {
+               ret = -EINVAL;
                goto err_io_init;
        }
     
        memset(data->adc_samples, 0, sizeof(int)*(NUM_VOLTAGE_SAMPLE + 2));
 
         //register adc for battery sample
-        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;
-           
+       data->wq = create_singlethread_workqueue("adc_battd");
         //variable init
-       data->client  = client;
-       data->adc_val = adc_sync_read(client);
+       /*data->client  = client;*/
+       data->adc_val = rk_adc_battery_iio_read(data->pdata);
 
-       ret = power_supply_register(&pdev->dev, &rk30_battery_supply);
+       data ->bat = rk30_battery_supply;
+       ret = power_supply_register(&pdev->dev,&data ->bat);
        if (ret){
+               ret = -EINVAL;
                printk(KERN_INFO "fail to battery power_supply_register\n");
                goto err_battery_failed;
        }
-#ifdef BATTERY_APK
-       ret = device_create_file(&pdev->dev,&dev_attr_batparam);
-       if(ret)
-       {
-               printk(KERN_ERR "failed to create bat param file\n");
-               goto err_battery_failed;
-       }
-               
-#endif 
-        if(1 == pdata->spport_usb_charging){
-       ret = power_supply_register(&pdev->dev, &rk30_usb_supply);
+#if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)  
+       data ->usb = rk30_usb_supply;
+       ret = power_supply_register(&pdev->dev, &data ->usb);
        if (ret){
+               ret = -EINVAL;
                printk(KERN_INFO "fail to usb power_supply_register\n");
                goto err_usb_failed;
        }
-        }
-       wake_lock_init(&batt_wake_lock, WAKE_LOCK_SUSPEND, "batt_lock");        
-
-       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);
-       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);
+#endif
+       data ->ac = rk30_ac_supply;
+       ret = power_supply_register(&pdev->dev, &data ->ac);
        if (ret) {
+               ret = -EINVAL;
                printk(KERN_INFO "fail to ac power_supply_register\n");
                goto err_ac_failed;
        }
+
        //init dc dectet irq & delay work
-       if (pdata->dc_det_pin != INVALID_GPIO){
+       if (batt_gpio_is_valid(data->pdata->dc_det_pin)) {
                INIT_WORK(&data->dcwakeup_work, rk30_adc_battery_dcdet_delaywork);
                
-               irq = gpio_to_irq(pdata->dc_det_pin);           
-               irq_flag = gpio_get_value (pdata->dc_det_pin) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
+               irq = gpio_to_irq(data->pdata->dc_det_pin);
+               irq_flag = gpio_get_value(data->pdata->dc_det_pin)
+                       ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
                ret = request_irq(irq, rk30_adc_battery_dc_wakeup, irq_flag, "ac_charge_irq", NULL);
                if (ret) {
+                       ret = -EINVAL;
                        printk("failed to request dc det irq\n");
                        goto err_dcirq_failed;
                }
                enable_irq_wake(irq);  
        
        }
-#endif
 
-#if 1
-       // batt low irq lowerpower_work
-       if( pdata->batt_low_pin != INVALID_GPIO){
-               INIT_WORK(&data->lowerpower_work, rk30_adc_battery_lowerpower_delaywork);
+#ifdef BATTERY_APK
+       ret = device_create_file(&pdev->dev,&dev_attr_batparam);
+       if(ret){
+               ret = -EINVAL;
+               printk(KERN_ERR "failed to create bat param file\n");
+               goto err_battery_failed;
+       }
                
-               irq = gpio_to_irq(pdata->batt_low_pin);
-               ret = request_irq(irq, rk30_adc_battery_low_wakeup, IRQF_TRIGGER_LOW, "batt_low_irq", NULL);
-
-               if (ret) {
-                       printk("failed to request batt_low_irq irq\n");
-                       goto err_lowpowerirq_failed;
-               }
-               disable_irq(irq);
-       
-       }
-#endif
-
-#ifdef  BATTERY_APK
        ret = create_sysfs_interfaces(&pdev->dev);
        if (ret < 0)
        {
+               ret = -EINVAL;
                dev_err(&pdev->dev,               
                        "device rk30_adc_batterry sysfs register failed\n");
                goto err_sysfs;
        }
-
 #endif 
+       //Power on Battery detect
+       rk30_adc_battery_check(data);
+
+//     data->wq = create_singlethread_workqueue("adc_battd");
+       INIT_DELAYED_WORK(&data->delay_work, rk30_adc_battery_timer_work);
+
+       //if (1 == data->pdata->save_capacity) {
+       if (1) {
+               queue_delayed_work(data->wq, &data->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS*10));
+               data ->poweron_check = 1;
+       }else{
+               queue_delayed_work(data->wq, &data->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS));
+               data ->poweron_check = 0;
+       }
+       INIT_DELAYED_WORK(&data->check_work, rk_adc_battery_check_work);
+       queue_delayed_work(data ->wq, &data ->check_work, msecs_to_jiffies(TIMER_MS_COUNTS));
+       if (batt_gpio_is_valid(data->pdata->batt_low_pin)) {
+               if (0 == gpio_get_value(data->pdata->batt_low_pin)) {
+                      mdelay(20);
+                       if (gpio_get_value(data->pdata->batt_low_pin) == 0) {
+                        printk("lower power\n");
+                              kernel_power_off(); 
+                      }
+               }
+               
+               INIT_WORK(&data->lowerpower_work, rk30_adc_battery_lowerpower_delaywork);               
+               irq = gpio_to_irq(data->pdata->batt_low_pin);
+               ret = request_irq(irq, rk30_adc_battery_low_wakeup, IRQF_TRIGGER_LOW, "batt_low_irq", NULL);
+               if (ret) {
+                       ret = -EINVAL;
+                       printk("failed to request batt_low_irq irq\n");
+                       goto err_lowpowerirq_failed;
+               }
+               disable_irq(irq);
+
+       }
+       data->battery_nb.notifier_call = battery_notifier_call;
+       register_adc_battery_notifier(&data->battery_nb);
+
        printk(KERN_INFO "rk30_adc_battery: driver initialized\n");
        
        return 0;
 err_sysfs:     
-err_usb_failed:
-       power_supply_unregister(&rk30_usb_supply);
-
+       power_supply_unregister(&data ->usb);
 err_ac_failed:
-#if defined (CONFIG_BATTERY_RK30_AC_CHARGE)
-       power_supply_unregister(&rk30_ac_supply);
-#endif
+       power_supply_unregister(&data ->ac);
 
+err_usb_failed:
 err_battery_failed:
-       power_supply_unregister(&rk30_battery_supply);
+       power_supply_unregister(&data ->bat);
     
 err_dcirq_failed:
-       free_irq(gpio_to_irq(pdata->dc_det_pin), data);
+       if (batt_gpio_is_valid(data->pdata->dc_det_pin))
+               free_irq(gpio_to_irq(data->pdata->dc_det_pin), data);
 #if 1
  err_lowpowerirq_failed:
-       free_irq(gpio_to_irq(pdata->batt_low_pin), data);
-#endif
-err_adc_register_failed:
-err_io_init:    
-err_data_alloc_failed:
-       kfree(data);
+       if (batt_gpio_is_valid(data->pdata->batt_low_pin))
+               free_irq(gpio_to_irq(data->pdata->batt_low_pin), data);
 
+#endif
+err_io_init:
        printk("rk30_adc_battery: error!\n");
     
        return ret;
@@ -1793,32 +2475,44 @@ err_data_alloc_failed:
 static int rk30_adc_battery_remove(struct platform_device *pdev)
 {
        struct rk30_adc_battery_data *data = platform_get_drvdata(pdev);
-       struct rk30_adc_battery_platform_data *pdata = pdev->dev.platform_data;
-
-       cancel_delayed_work(&gBatteryData->delay_work); 
-        if(1 == pdata->spport_usb_charging){   
-       power_supply_unregister(&rk30_usb_supply);
-        }
-#if defined(CONFIG_BATTERY_RK30_AC_CHARGE)
-       power_supply_unregister(&rk30_ac_supply);
-#endif
-       power_supply_unregister(&rk30_battery_supply);
+       struct rk30_adc_battery_platform_data *pdata = data->pdata;
 
-       free_irq(gpio_to_irq(pdata->dc_det_pin), data);
+       cancel_delayed_work_sync(&data->delay_work);    
+       if (batt_gpio_is_valid(pdata->dc_det_pin))
+               cancel_work_sync(&data->dcwakeup_work);
+        cancel_delayed_work_sync(&data->check_work);
 
-       kfree(data);
+       if (batt_gpio_is_valid(pdata->batt_low_pin))
+               cancel_work_sync(&data->lowerpower_work);
+#if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
+               power_supply_unregister(&data ->usb);
+#endif
+       power_supply_unregister(&data ->ac);
+       power_supply_unregister(&data ->bat);
+       if (batt_gpio_is_valid(pdata->dc_det_pin))
+               free_irq(gpio_to_irq(pdata->dc_det_pin), data);
        
        return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id rk30_adc_battery_dt_match[] = {
+       { .compatible = "rk30-adc-battery",},
+       {},
+};
+MODULE_DEVICE_TABLE(of, rk30_adc_battery_dt_match);
+#endif
+
+
 static struct platform_driver rk30_adc_battery_driver = {
        .probe          = rk30_adc_battery_probe,
        .remove         = rk30_adc_battery_remove,
        .suspend                = rk30_adc_battery_suspend,
        .resume         = rk30_adc_battery_resume,
        .driver = {
-               .name = "rk30-battery",
+               .name = "rk30-adc-battery",
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(rk30_adc_battery_dt_match),
        }
 };
 
@@ -1831,10 +2525,13 @@ static void __exit rk30_adc_battery_exit(void)
 {
        platform_driver_unregister(&rk30_adc_battery_driver);
 }
-
-module_init(rk30_adc_battery_init);//module_init(rk30_adc_battery_init);//subsys_initcall(rk30_adc_battery_init);
+//module_init(rk30_adc_battery_init);//module_init(rk30_adc_battery_init);//
+subsys_initcall(rk30_adc_battery_init);
+//fs_initcall(rk30_adc_battery_init);
 module_exit(rk30_adc_battery_exit);
 
+
+
 MODULE_DESCRIPTION("Battery detect driver for the rk30");
 MODULE_AUTHOR("luowei lw@rock-chips.com");
 MODULE_LICENSE("GPL");