+ if (blank == FB_BLANK_UNBLANK)
+ di->early_resume = 1;
+
+ return 0;
+}
+
+static int rk81x_battery_register_fb_notify(struct rk81x_battery *di)
+{
+ memset(&di->fb_nb, 0, sizeof(di->fb_nb));
+ di->fb_nb.notifier_call = rk81x_battery_fb_notifier;
+
+ return fb_register_client(&di->fb_nb);
+}
+
+/*
+ * it is first time for battery to be weld, init by ocv table
+ */
+static void rk81x_bat_first_pwron(struct rk81x_battery *di)
+{
+ rk81x_bat_save_fcc(di, di->design_capacity);
+ di->fcc = rk81x_bat_get_fcc(di);
+
+ di->rsoc = rk81x_bat_vol_to_capacity(di, di->voltage_ocv);
+ di->dsoc = di->rsoc;
+ di->nac = di->temp_nac;
+
+ rk81x_bat_set_bit(di, MISC_MARK_REG, OCV_VALID_SHIFT);
+ rk81x_bat_set_bit(di, MISC_MARK_REG, FIRST_PWRON_SHIFT);/*save*/
+ DBG("<%s>.this is first poweron: OCV-SOC:%d, OCV-CAP:%d, FCC:%d\n",
+ __func__, di->dsoc, di->nac, di->fcc);
+}
+
+static int rk81x_bat_get_calib_vol(struct rk81x_battery *di)
+{
+ int calib_vol;
+ int init_cur, diff;
+ int est_vol;
+ int relax_vol = di->relax_voltage;
+ int ocv_vol = di->voltage_ocv;
+
+ init_cur = rk81x_bat_get_avg_current(di);
+ diff = (di->bat_res + di->pdata->chrg_diff_vol) * init_cur;
+ diff /= 1000;
+ est_vol = di->voltage - diff;
+
+ if (di->loader_charged) {
+ calib_vol = est_vol;
+ return calib_vol;
+ }
+
+ if (di->pwroff_min > 8) {
+ if (abs(relax_vol - ocv_vol) < 100) {
+ calib_vol = ocv_vol;
+ } else {
+ if (abs(relax_vol - est_vol) > abs(ocv_vol - est_vol))
+ calib_vol = ocv_vol;
+ else
+ calib_vol = relax_vol;
+ }
+ } else if (di->pwroff_min > 2) {
+ calib_vol = ocv_vol;
+ } else {
+ calib_vol = -1;
+ }
+
+ dev_info(di->dev, "c=%d, v=%d, relax:%d, ocv:=%d, est=%d, calib=%d\n",
+ init_cur, di->voltage, relax_vol, ocv_vol, est_vol, calib_vol);
+
+ return calib_vol;
+}
+
+/*
+ * it is not first time for battery to be weld, init by last record info
+ */
+static void rk81x_bat_not_first_pwron(struct rk81x_battery *di)
+{
+ u8 pwron_soc;
+ u8 init_soc;
+ int remain_capacity;
+ int ocv_soc;
+ int calib_vol, calib_soc, calib_capacity;
+
+ rk81x_bat_clr_bit(di, MISC_MARK_REG, FIRST_PWRON_SHIFT);
+ rk81x_bat_read(di, SOC_REG, &pwron_soc, 1);
+ init_soc = pwron_soc;
+ remain_capacity = rk81x_bat_get_remain_capacity(di);
+
+ /* check if support uboot charge,
+ * if support, uboot charge driver should have done init work,
+ * so here we should skip init work
+ */
+ if (rk81x_bat_support_loader_chrg(di))
+ goto out;
+
+ calib_vol = rk81x_bat_get_calib_vol(di);
+ if (calib_vol > 0) {
+ calib_soc = rk81x_bat_vol_to_capacity(di, calib_vol);
+ calib_capacity = di->temp_nac;
+
+ if (abs(calib_soc - init_soc) >= 70 || di->loader_charged) {
+ init_soc = calib_soc;
+ remain_capacity = calib_capacity;
+ }
+ dev_info(di->dev, "calib_vol %d, init soc %d, remain_cap %d\n",
+ calib_vol, init_soc, remain_capacity);
+ }
+
+ ocv_soc = rk81x_bat_vol_to_capacity(di, di->voltage_ocv);
+ DBG("<%s>, Not first pwron, real_remain_cap = %d, ocv-remain_cp=%d\n",
+ __func__, remain_capacity, di->temp_nac);
+
+ if (di->pwroff_min > 0) {
+ if (di->pwroff_min > 30) {
+ rk81x_bat_set_bit(di, MISC_MARK_REG, OCV_VALID_SHIFT);
+
+ remain_capacity = di->temp_nac;
+ DBG("<%s>pwroff > 30 minute, remain_cap = %d\n",
+ __func__, remain_capacity);
+
+ } else if ((di->pwroff_min > 5) &&
+ (abs(ocv_soc - init_soc) >= 10)) {
+ if (remain_capacity >= di->temp_nac * 120/100)
+ remain_capacity = di->temp_nac * 110/100;
+ else if (remain_capacity < di->temp_nac * 8/10)
+ remain_capacity = di->temp_nac * 9/10;
+ DBG("<%s> pwroff > 5 minute, remain_cap = %d\n",
+ __func__, remain_capacity);
+ }
+ } else {
+ rk81x_bat_clr_bit(di, MISC_MARK_REG, OCV_VALID_SHIFT);
+ }
+out:
+ di->dsoc = init_soc;
+ di->nac = remain_capacity;
+ if (di->nac <= 0)
+ di->nac = 0;
+ DBG("<%s> init_soc = %d, init_capacity=%d\n",
+ __func__, di->dsoc, di->nac);
+}
+
+static u8 rk81x_bat_get_pwroff_min(struct rk81x_battery *di)
+{
+ u8 curr_pwroff_min, last_pwroff_min;
+
+ rk81x_bat_read(di, NON_ACT_TIMER_CNT_REG,
+ &curr_pwroff_min, 1);
+ rk81x_bat_read(di, NON_ACT_TIMER_CNT_REG_SAVE,
+ &last_pwroff_min, 1);
+
+ rk81x_bat_write(di, NON_ACT_TIMER_CNT_REG_SAVE,
+ &curr_pwroff_min, 1);
+
+ return (curr_pwroff_min != last_pwroff_min) ? curr_pwroff_min : 0;
+}
+
+static int rk81x_bat_rsoc_init(struct rk81x_battery *di)
+{
+ u8 calib_en;/*debug*/
+
+ di->voltage = rk81x_bat_get_vol(di);
+ di->voltage_ocv = rk81x_bat_get_ocv_vol(di);
+ di->pwroff_min = rk81x_bat_get_pwroff_min(di);
+ di->relax_voltage = rk81x_bat_get_relax_vol(di);
+ di->current_avg = rk81x_bat_get_avg_current(di);
+
+ dev_info(di->dev, "v=%d, ov=%d, rv=%d, c=%d, pwroff_min=%d\n",
+ di->voltage, di->voltage_ocv, di->relax_voltage,
+ di->current_avg, di->pwroff_min);
+
+ calib_en = rk81x_bat_read_bit(di, MISC_MARK_REG, OCV_CALIB_SHIFT);
+ DBG("readbit: calib_en=%d\n", calib_en);
+ if (is_rk81x_bat_first_poweron(di) ||
+ ((di->pwroff_min >= 30) && (calib_en == 1))) {
+ rk81x_bat_first_pwron(di);
+ rk81x_bat_clr_bit(di, MISC_MARK_REG, OCV_CALIB_SHIFT);
+
+ } else {
+ rk81x_bat_not_first_pwron(di);
+ }
+
+ return 0;
+}
+
+static u8 rk81x_bat_get_chrg_status(struct rk81x_battery *di)
+{
+ u8 status;
+ u8 ret = 0;