OSDN Git Service

Add rtl8821ce driver version 5.5.2
[android-x86/external-kernel-drivers.git] / rtl8821ce / hal / phydm / halrf / rtl8821c / halrf_iqk_8821c.c
diff --git a/rtl8821ce/hal/phydm/halrf/rtl8821c/halrf_iqk_8821c.c b/rtl8821ce/hal/phydm/halrf/rtl8821c/halrf_iqk_8821c.c
new file mode 100644 (file)
index 0000000..259f868
--- /dev/null
@@ -0,0 +1,3777 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2016 - 2017 Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ *****************************************************************************/
+
+#include "mp_precomp.h"
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
+#if RT_PLATFORM == PLATFORM_MACOSX
+#include "phydm_precomp.h"
+#else
+#include "../phydm_precomp.h"
+#endif
+#else
+#include "../../phydm_precomp.h"
+#endif
+
+#if (RTL8821C_SUPPORT == 1)
+/*---------------------------Define Local Constant---------------------------*/
+
+static u32 dpk_result[DPK_BACKUP_REG_NUM_8821C];
+static boolean txgap_done[3] = {false, false, false};
+static boolean overflowflag;
+#define dpk_forcein_sram4 1
+#define txgap_ref_index 0x0
+#define txgap_k_number 0x7
+
+/*---------------------------Define Local Constant---------------------------*/
+#if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
+void do_iqk_8821c(void *dm_void, u8 delta_thermal_index, u8 thermal_value,
+                 u8 threshold)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+
+       dm->rf_calibrate_info.thermal_value_iqk = thermal_value;
+       halrf_segment_iqk_trigger(dm, true, iqk_info->segment_iqk);
+}
+#else
+/*Originally config->do_iqk is hooked phy_iq_calibrate_8821c, but do_iqk_8821c and phy_iq_calibrate_8821c have different arguments*/
+void do_iqk_8821c(void *dm_void, u8 delta_thermal_index, u8 thermal_value,
+                 u8 threshold)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+       /*boolean               is_recovery = (boolean) delta_thermal_index;*/
+       halrf_segment_iqk_trigger(dm, true, iqk_info->segment_iqk);
+}
+#endif
+void do_dpk_8821c(void *dm_void, u8 delta_thermal_index, u8 thermal_value,
+                 u8 threshold)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       /*boolean               is_recovery = (boolean) delta_thermal_index;*/
+       phy_dp_calibrate_8821c(dm, true);
+}
+
+boolean
+_iqk_check_nctl_done_8821c(struct dm_struct *dm, u8 path, u32 IQK_CMD)
+{
+       /*this function is only used after the version of nctl8.0*/
+       boolean notready = true;
+       boolean fail = true;
+       u32 delay_count = 0x0;
+
+       while (notready) {
+               if ((IQK_CMD & 0x00000f00) >> 8 == 0xc) {
+                       if (odm_get_rf_reg(dm, path, RF_0x08, RFREGOFFSETMASK) == 0x1a3b5)
+                               notready = false;
+                       else
+                               notready = true;
+               } else {
+                       if (odm_get_rf_reg(dm, path, RF_0x08, RFREGOFFSETMASK) == 0x12345)
+                               notready = false;
+                       else
+                               notready = true;
+               }
+               if (notready) {
+                       /*ODM_sleep_ms(1);*/
+                       ODM_delay_ms(1);
+                       delay_count++;
+               } else {
+                       fail = (boolean)odm_get_bb_reg(dm, R_0x1b08, BIT(26));
+                       if (fail) {
+                               RF_DBG(dm, DBG_RF_IQK,
+                                      "[IQK](1)IQK_CMD =0x%x, Fail, 0x1b08=0x%x, RF08=0x%x, 1b00=0x%x,fail=0x%x, notready=0x%x!!!\n",
+                                      IQK_CMD, odm_read_4byte(dm, 0x1b08),
+                                      odm_get_rf_reg(dm, path, RF_0x08,
+                                                     RFREGOFFSETMASK),
+                                      odm_read_4byte(dm, 0x1b00), fail,
+                                                     notready);
+                       }
+                       break;
+               }
+               if (delay_count >= 50) {
+                       RF_DBG(dm, DBG_RF_IQK, "[IQK]S%d IQK timeout!!!\n",
+                              path);
+                       break;
+               }
+       }
+       odm_set_rf_reg(dm, path, RF_0x8, RFREGOFFSETMASK, 0x0);
+
+       if (!fail) {
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[IQK]IQK_CMD =0x%x, delay_count =0x%x RF0x08=0x%x, 0x1b08=0x%x,RF0xef=0x%x,RF0xdf=0x%x, !!!\n",
+                      IQK_CMD, delay_count,
+                      odm_get_rf_reg(dm, path, RF_0x8, RFREGOFFSETMASK),
+                      odm_read_4byte(dm, 0x1b08),
+                      odm_get_rf_reg(dm, path, RF_0xef, RFREGOFFSETMASK),
+                      odm_get_rf_reg(dm, path, RF_0xdf, RFREGOFFSETMASK));
+       } else {
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[IQK](2)IQK_CMD =0x%x, Fail, 0x1b08=0x%x, RF08=0x%x!!!\n",
+                      IQK_CMD, odm_read_4byte(dm, 0x1b08),
+                      odm_get_rf_reg(dm, path, RF_0x08, RFREGOFFSETMASK));
+       }
+       return fail;
+}
+
+void phydm_get_read_counter_8821c(struct dm_struct *dm)
+{
+       u32 counter = 0x0;
+
+       while (1) {
+               if ((odm_get_rf_reg(dm, RF_PATH_A, RF_0x8, RFREGOFFSETMASK) == 0xabcde) || counter > 300)
+                       break;
+               counter++;
+               /*ODM_sleep_ms(1);*/
+               ODM_delay_ms(1);
+       };
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0x8, RFREGOFFSETMASK, 0x0);
+       RF_DBG(dm, DBG_RF_IQK, "[IQK]counter = %d\n", counter);
+}
+
+void _iqk_check_coex_status(struct dm_struct *dm, boolean beforeK)
+{
+       u8 u1b_tmp;
+       u16 count = 0;
+       u8 h2c_parameter;
+
+       h2c_parameter = 1;
+
+       if (beforeK) {
+               u1b_tmp = odm_read_1byte(dm, 0x49c);
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[IQK]check 0x49c[0] = 0x%x before h2c 0x6d\n", u1b_tmp);
+
+               /*check if BT IQK */
+               u1b_tmp = odm_read_1byte(dm, 0x49c);
+               while ((u1b_tmp & BIT(1)) && (count < 100)) {
+                       /*ODM_sleep_ms(10);*/
+                       ODM_delay_ms(10);
+                       u1b_tmp = odm_read_1byte(dm, 0x49c);
+                       count++;
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[IQK]check 0x49c[1]=0x%x, count = %d\n",
+                              u1b_tmp, count);
+               }
+#if 1
+               odm_fill_h2c_cmd(dm, ODM_H2C_WIFI_CALIBRATION, 1, &h2c_parameter);
+
+               u1b_tmp = odm_read_1byte(dm, 0x49c);
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[IQK]check 0x49c[0] = 0x%x after h2c 0x6d\n", u1b_tmp);
+
+               u1b_tmp = odm_read_1byte(dm, 0x49c);
+               /*check if WL IQK available form WL FW */
+               while ((!(u1b_tmp & BIT(0))) && (count < 100)) {
+#if 0
+                       /*ODM_sleep_ms(10);*/
+#endif
+                       ODM_delay_ms(10);
+                       u1b_tmp = odm_read_1byte(dm, 0x49c);
+                       count++;
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[IQK]check 0x49c[1]=0x%x, count = %d\n",
+                              u1b_tmp, count);
+               }
+
+               if (count >= 100)
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[IQK]Polling 0x49c to 1 for WiFi calibration H2C cmd FAIL! count(%d)\n",
+                              count);
+#endif
+
+       } else {
+               odm_set_bb_reg(dm, R_0x49c, BIT(0), 0x0);
+       }
+}
+
+u32 _iqk_indirect_read_reg(struct dm_struct *dm, u16 reg_addr)
+{
+       u32 j = 0;
+
+       /*wait for ready bit before access 0x1700*/
+       odm_write_4byte(dm, 0x1700, 0x800f0000 | reg_addr);
+
+       do {
+               j++;
+       } while (((odm_read_1byte(dm, 0x1703) & BIT(5)) == 0) && (j < 30000));
+
+       return odm_read_4byte(dm, 0x1708); /*get read data*/
+}
+
+void _iqk_indirect_write_reg(struct dm_struct *dm, u16 reg_addr, u32 bit_mask,
+                            u32 reg_value)
+{
+       u32 val, i = 0, j = 0, bitpos = 0;
+
+       if (bit_mask == 0x0)
+               return;
+       if (bit_mask == 0xffffffff) {
+               odm_write_4byte(dm, 0x1704, reg_value); /*put write data*/
+
+               /*wait for ready bit before access 0x1700*/
+               do {
+                       j++;
+               } while (((odm_read_1byte(dm, 0x1703) & BIT(5)) == 0) && (j < 30000));
+
+               odm_write_4byte(dm, 0x1700, 0xc00f0000 | reg_addr);
+       } else {
+               for (i = 0; i <= 31; i++) {
+                       if (((bit_mask >> i) & 0x1) == 0x1) {
+                               bitpos = i;
+                               break;
+                       }
+               }
+
+               /*read back register value before write*/
+               val = _iqk_indirect_read_reg(dm, reg_addr);
+               val = (val & (~bit_mask)) | (reg_value << bitpos);
+
+               odm_write_4byte(dm, 0x1704, val); /*put write data*/
+
+               /*wait for ready bit before access 0x1700*/
+               do {
+                       j++;
+               } while (((odm_read_1byte(dm, 0x1703) & BIT(5)) == 0) && (j < 30000));
+
+               odm_write_4byte(dm, 0x1700, 0xc00f0000 | reg_addr);
+       }
+}
+
+void _iqk_set_gnt_wl_high(struct dm_struct *dm)
+{
+       u32 val = 0;
+       u8 state = 0x1, sw_control = 0x1;
+
+       /*GNT_WL = 1*/
+       val = (sw_control) ? ((state << 1) | 0x1) : 0;
+       _iqk_indirect_write_reg(dm, 0x38, 0x3000, val); /*0x38[13:12]*/
+       _iqk_indirect_write_reg(dm, 0x38, 0x0300, val); /*0x38[9:8]*/
+}
+
+void _iqk_set_gnt_bt_low(struct dm_struct *dm)
+{
+       u32 val = 0;
+       u8 state = 0x0, sw_control = 0x1;
+
+       /*GNT_BT = 0*/
+       val = (sw_control) ? ((state << 1) | 0x1) : 0;
+       _iqk_indirect_write_reg(dm, 0x38, 0xc000, val); /*0x38[15:14]*/
+       _iqk_indirect_write_reg(dm, 0x38, 0x0c00, val); /*0x38[11:10]*/
+}
+
+void _iqk_set_gnt_wl_gnt_bt(struct dm_struct *dm, boolean beforeK)
+{
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+
+       if (beforeK) {
+               _iqk_set_gnt_wl_high(dm);
+               _iqk_set_gnt_bt_low(dm);
+       } else {
+               _iqk_indirect_write_reg(dm, 0x38, MASKDWORD, iqk_info->tmp_gntwl);
+       }
+}
+
+void _iqk_fail_count_8821c(void *dm_void)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+       u8 i;
+
+       dm->n_iqk_cnt++;
+       if (odm_get_rf_reg(dm, RF_PATH_A, RF_0x1bf0, BIT(16)) == 1)
+               iqk_info->is_reload = true;
+       else
+               iqk_info->is_reload = false;
+
+       if (!iqk_info->is_reload) {
+               for (i = 0; i < 8; i++) {
+                       if (odm_get_bb_reg(dm, R_0x1bf0, BIT(i)) == 1)
+                               dm->n_iqk_fail_cnt++;
+               }
+       }
+       RF_DBG(dm, DBG_RF_IQK, "[IQK]All/Fail = %d %d\n", dm->n_iqk_cnt,
+              dm->n_iqk_fail_cnt);
+}
+
+void _iqk_fill_iqk_report_8821c(void *dm_void, u8 channel)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+       u32 tmp1 = 0x0, tmp2 = 0x0, tmp3 = 0x0;
+       u8 i;
+
+       for (i = 0; i < SS_8821C; i++) {
+               tmp1 = tmp1 + ((iqk_info->iqk_fail_report[channel][i][TX_IQK] & 0x1) << i);
+               tmp2 = tmp2 + ((iqk_info->iqk_fail_report[channel][i][RX_IQK] & 0x1) << (i + 4));
+               tmp3 = tmp3 + ((iqk_info->rxiqk_fail_code[channel][i] & 0x3) << (i * 2 + 8));
+       }
+       odm_write_4byte(dm, 0x1b00, 0xf8000008);
+       odm_set_bb_reg(dm, R_0x1bf0, 0x00ffffff, tmp1 | tmp2 | tmp3);
+
+       for (i = 0; i < SS_8821C; i++)
+               odm_write_4byte(dm, 0x1be8 + (i * 4), (iqk_info->rxiqk_agc[channel][(i * 2) + 1] << 16) | iqk_info->rxiqk_agc[channel][i * 2]);
+       RF_DBG(dm, DBG_RF_IQK, "[IQK] 0x1be8 = %x\n",
+              odm_read_4byte(dm, 0x1be8));
+}
+
+void _iqk_iqk_fail_report_8821c(struct dm_struct *dm)
+{
+       u32 tmp1bf0 = 0x0;
+       u8 i;
+
+       tmp1bf0 = odm_read_4byte(dm, 0x1bf0);
+
+       for (i = 0; i < 4; i++) {
+               if (tmp1bf0 & (0x1 << i))
+#if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
+                       RF_DBG(dm, DBG_RF_IQK, "[IQK] please check S%d TXIQK\n",
+                              i);
+#else
+                       panic_printk("[IQK] please check S%d TXIQK\n", i);
+#endif
+               if (tmp1bf0 & (0x1 << (i + 12)))
+#if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
+                       RF_DBG(dm, DBG_RF_IQK, "[IQK] please check S%d RXIQK\n",
+                              i);
+#else
+                       panic_printk("[IQK] please check S%d RXIQK\n", i);
+#endif
+       }
+}
+
+void _iqk_backup_mac_bb_8821c(struct dm_struct *dm, u32 *MAC_backup,
+                             u32 *BB_backup, u32 *backup_mac_reg,
+                             u32 *backup_bb_reg, u8 num_backup_bb_reg)
+{
+       u32 i;
+
+       for (i = 0; i < MAC_REG_NUM_8821C; i++)
+               MAC_backup[i] = odm_read_4byte(dm, backup_mac_reg[i]);
+
+       for (i = 0; i < num_backup_bb_reg; i++)
+               BB_backup[i] = odm_read_4byte(dm, backup_bb_reg[i]);
+#if 0
+       /*      RF_DBG(dm, DBG_RF_IQK, "[IQK]BackupMacBB Success!!!!\n"); */
+#endif
+}
+
+void _iqk_backup_rf_8821c(struct dm_struct *dm, u32 RF_backup[][SS_8821C],
+                         u32 *backup_rf_reg)
+{
+       u32 i, j;
+
+       for (i = 0; i < RF_REG_NUM_8821C; i++)
+               for (j = 0; j < SS_8821C; j++)
+                       RF_backup[i][j] = odm_get_rf_reg(dm, (u8)j, backup_rf_reg[i], RFREGOFFSETMASK);
+#if 0
+       /*      RF_DBG(dm, DBG_RF_IQK, "[IQK]BackupRF Success!!!!\n"); */
+#endif
+}
+
+void _iqk_agc_bnd_int_8821c(struct dm_struct *dm)
+{
+       /*initialize RX AGC bnd, it must do after bbreset*/
+       odm_write_4byte(dm, 0x1b00, 0xf8000008);
+       odm_write_4byte(dm, 0x1b00, 0xf80a7008);
+       odm_write_4byte(dm, 0x1b00, 0xf8015008);
+       odm_write_4byte(dm, 0x1b00, 0xf8000008);
+#if 0
+       /*RF_DBG(dm, DBG_RF_IQK, "[IQK]init. rx agc bnd\n");*/
+#endif
+}
+
+void _iqk_bb_reset_8821c(struct dm_struct *dm)
+{
+       boolean cca_ing = false;
+       u32 count = 0;
+
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0x0, RFREGOFFSETMASK, 0x10000);
+       odm_set_bb_reg(dm, R_0x8f8,
+                      BIT(27) | BIT26 | BIT25 | BIT24 | BIT23 | BIT22 | BIT21 | BIT20, 0x0);
+
+       while (1) {
+               odm_write_4byte(dm, 0x8fc, 0x0);
+               odm_set_bb_reg(dm, R_0x198c, 0x7, 0x7);
+               cca_ing = (boolean)odm_get_bb_reg(dm, R_0xfa0, BIT(3));
+
+               if (count > 30)
+                       cca_ing = false;
+
+               if (cca_ing) {
+                       ODM_sleep_ms(1);
+                       count++;
+               } else {
+                       odm_write_1byte(dm, 0x808, 0x0); /*RX ant off*/
+                       odm_set_bb_reg(dm, R_0xa04, BIT(27) | BIT26 | BIT25 | BIT24, 0x0); /*CCK RX path off*/
+
+                       /*BBreset*/
+                       odm_set_bb_reg(dm, R_0x0, BIT(16), 0x0);
+                       odm_set_bb_reg(dm, R_0x0, BIT(16), 0x1);
+
+                       if (odm_get_bb_reg(dm, R_0x660, BIT(16)))
+                               odm_write_4byte(dm, 0x6b4, 0x89000006);
+                       RF_DBG(dm, DBG_RF_IQK, "[IQK]BBreset!!!!\n");
+                       break;
+               }
+       }
+}
+
+void _iqk_afe_setting_8821c(struct dm_struct *dm, boolean do_iqk)
+{
+       if (do_iqk) {
+               /*IQK AFE setting RX_WAIT_CCA mode */
+               odm_write_4byte(dm, 0xc60, 0x50000000);
+               odm_write_4byte(dm, 0xc60, 0x700F0040);
+
+               /*AFE setting*/
+               odm_write_4byte(dm, 0xc58, 0xd8000402);
+               odm_write_4byte(dm, 0xc5c, 0xd1000120);
+               odm_write_4byte(dm, 0xc6c, 0x00000a15);
+               _iqk_bb_reset_8821c(dm);
+#if 0
+               /*              RF_DBG(dm, DBG_RF_IQK, "[IQK]AFE setting for IQK mode!!!!\n"); */
+#endif
+       } else {
+               /*IQK AFE setting RX_WAIT_CCA mode */
+               odm_write_4byte(dm, 0xc60, 0x50000000);
+               odm_write_4byte(dm, 0xc60, 0x700B8040);
+
+               /*AFE setting*/
+               odm_write_4byte(dm, 0xc58, 0xd8020402);
+               odm_write_4byte(dm, 0xc5c, 0xde000120);
+               odm_write_4byte(dm, 0xc6c, 0x0000122a);
+#if 0
+               /*              RF_DBG(dm, DBG_RF_IQK, "[IQK]AFE setting for Normal mode!!!!\n"); */
+#endif
+       }
+       /*0x9a4[31]=0: Select da clock*/
+       odm_set_bb_reg(dm, R_0x9a4, BIT(31), 0x0);
+}
+
+void _iqk_restore_mac_bb_8821c(struct dm_struct *dm, u32 *MAC_backup,
+                              u32 *BB_backup, u32 *backup_mac_reg,
+                              u32 *backup_bb_reg, u8 num_backup_bb_reg)
+{
+       u32 i;
+
+       for (i = 0; i < MAC_REG_NUM_8821C; i++)
+               odm_write_4byte(dm, backup_mac_reg[i], MAC_backup[i]);
+       for (i = 0; i < num_backup_bb_reg; i++)
+               odm_write_4byte(dm, backup_bb_reg[i], BB_backup[i]);
+#if 0
+       /*      RF_DBG(dm, DBG_RF_IQK, "[IQK]RestoreMacBB Success!!!!\n"); */
+#endif
+}
+
+void _iqk_restore_rf_8821c(struct dm_struct *dm, u32 *backup_rf_reg,
+                          u32 RF_backup[][SS_8821C])
+{
+       u32 i;
+
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0xef, RFREGOFFSETMASK, 0x0);
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0xee, RFREGOFFSETMASK, 0x0);
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0xdf, RFREGOFFSETMASK, RF_backup[0][RF_PATH_A] & (~BIT(4)));
+#if 0
+       /*odm_set_rf_reg(dm, RF_PATH_A, RF_0xde, RFREGOFFSETMASK, RF_backup[1][RF_PATH_A]|BIT(4));*/
+#endif
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0xde, RFREGOFFSETMASK, RF_backup[1][RF_PATH_A] & (~BIT(4)));
+
+       for (i = 2; i < (RF_REG_NUM_8821C - 1); i++)
+               odm_set_rf_reg(dm, RF_PATH_A, backup_rf_reg[i], RFREGOFFSETMASK, RF_backup[i][RF_PATH_A]);
+
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0x1, RFREGOFFSETMASK, (RF_backup[4][RF_PATH_A] & (~BIT(0))));
+#if 0
+       /*RF_DBG(dm, DBG_RF_IQK, "[IQK]RestoreRF Success!!!!\n"); */
+#endif
+}
+
+void _iqk_backup_iqk_8821c(struct dm_struct *dm, u8 step, u8 path)
+{
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+       u8 i, j, k;
+#if 0
+       /*u16           iqk_apply[2] = {0xc94, 0xe94};*/
+#endif
+
+       switch (step) {
+       case 0:
+               iqk_info->iqk_channel[1] = iqk_info->iqk_channel[0];
+               for (i = 0; i < SS_8821C; i++) {
+                       iqk_info->lok_idac[1][i] = iqk_info->lok_idac[0][i];
+                       iqk_info->rxiqk_agc[1][i] = iqk_info->rxiqk_agc[0][i];
+                       iqk_info->bypass_iqk[1][i] = iqk_info->bypass_iqk[0][i];
+                       iqk_info->rxiqk_fail_code[1][i] = iqk_info->rxiqk_fail_code[0][i];
+                       for (j = 0; j < 2; j++) {
+                               iqk_info->iqk_fail_report[1][i][j] = iqk_info->iqk_fail_report[0][i][j];
+                               for (k = 0; k < 8; k++) {
+                                       iqk_info->iqk_cfir_real[1][i][j][k] = iqk_info->iqk_cfir_real[0][i][j][k];
+                                       iqk_info->iqk_cfir_imag[1][i][j][k] = iqk_info->iqk_cfir_imag[0][i][j][k];
+                               }
+                       }
+               }
+               for (i = 0; i < 4; i++) {
+                       iqk_info->rxiqk_fail_code[0][i] = 0x0;
+                       iqk_info->rxiqk_agc[0][i] = 0x0;
+                       for (j = 0; j < 2; j++) {
+                               iqk_info->iqk_fail_report[0][i][j] = true;
+                               iqk_info->gs_retry_count[0][i][j] = 0x0;
+                       }
+                       for (j = 0; j < 3; j++)
+                               iqk_info->retry_count[0][i][j] = 0x0;
+               }
+               /*backup channel*/
+               iqk_info->iqk_channel[0] = iqk_info->rf_reg18;
+               break;
+       case 1: /*LOK backup*/
+               iqk_info->lok_idac[0][path] = odm_get_rf_reg(dm, (enum rf_path)path, RF_0x58, RFREGOFFSETMASK);
+               break;
+       case 2: /*TXIQK backup*/
+       case 3: /*RXIQK backup*/
+               phydm_get_iqk_cfir(dm, (step - 2), path, false);
+               break;
+       }
+}
+
+void _iqk_reload_iqk_setting_8821c(struct dm_struct *dm, u8 channel,
+                                  u8 reload_idx
+                                  /*1: reload TX, 2: reload TX, RX*/)
+{
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+       u8 i, path, idx;
+       u16 iqk_apply[2] = {0xc94, 0xe94};
+
+       for (path = 0; path < SS_8821C; path++) {
+#if 0
+               if (reload_idx == 2) {
+                       odm_set_rf_reg(dm, (enum rf_path)path, RF_0xdf, BIT(4), 0x1);
+                       odm_set_rf_reg(dm, (enum rf_path)path, RF_0x58, RFREGOFFSETMASK, iqk_info->lok_idac[channel][path]);
+               }
+#endif
+               for (idx = 0; idx < reload_idx; idx++) {
+                       odm_set_bb_reg(dm, R_0x1b00, MASKDWORD, 0xf8000008 | path << 1);
+                       odm_set_bb_reg(dm, R_0x1b2c, MASKDWORD, 0x7);
+                       odm_set_bb_reg(dm, R_0x1b38, MASKDWORD, 0x20000000);
+                       odm_set_bb_reg(dm, R_0x1b3c, MASKDWORD, 0x20000000);
+                       odm_set_bb_reg(dm, R_0x1bcc, MASKDWORD, 0x00000000);
+                       if (idx == 0)
+                               odm_set_bb_reg(dm, R_0x1b0c, BIT(13) | BIT(12), 0x3);
+                       else
+                               odm_set_bb_reg(dm, R_0x1b0c, BIT(13) | BIT(12), 0x1);
+                       odm_set_bb_reg(dm, R_0x1bd4, BIT(20) | BIT(19) | BIT(18) | BIT(17) | BIT(16), 0x10);
+                       for (i = 0; i < 8; i++) {
+                               odm_write_4byte(dm, 0x1bd8, ((0xc0000000 >> idx) + 0x3) + (i * 4) + (iqk_info->iqk_cfir_real[channel][path][idx][i] << 9));
+                               odm_write_4byte(dm, 0x1bd8, ((0xc0000000 >> idx) + 0x1) + (i * 4) + (iqk_info->iqk_cfir_imag[channel][path][idx][i] << 9));
+                       }
+                       if (idx == 0)
+                               odm_set_bb_reg(dm, iqk_apply[path], BIT(0), ~(u32)(iqk_info->iqk_fail_report[channel][path][idx]));
+                       else
+                               odm_set_bb_reg(dm, iqk_apply[path], BIT(10), ~(u32)(iqk_info->iqk_fail_report[channel][path][idx]));
+               }
+               odm_set_bb_reg(dm, R_0x1bd8, MASKDWORD, 0x0);
+               odm_set_bb_reg(dm, R_0x1b0c, BIT(13) | BIT(12), 0x0);
+       }
+}
+
+boolean
+_iqk_reload_iqk_8821c(struct dm_struct *dm, boolean reset)
+{
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+       u8 i;
+       iqk_info->is_reload = false;
+       odm_set_bb_reg(dm, R_0x1bf0, BIT(16), 0x0); /*clear the reload flag*/
+
+       if (reset) {
+               for (i = 0; i < SS_8821C; i++)
+                       iqk_info->iqk_channel[i] = 0x0;
+       } else {
+               iqk_info->rf_reg18 = odm_get_rf_reg(dm, RF_PATH_A, RF_0x18, RFREGOFFSETMASK);
+
+               for (i = 0; i < SS_8821C; i++) {
+                       if (iqk_info->rf_reg18 == iqk_info->iqk_channel[i]) {
+                               _iqk_reload_iqk_setting_8821c(dm, i, 2);
+                               _iqk_fill_iqk_report_8821c(dm, i);
+                               RF_DBG(dm, DBG_RF_IQK,
+                                      "[IQK]reload IQK result before!!!!\n");
+                               odm_set_bb_reg(dm, R_0x1bf0, BIT(16), 0x1);
+                               iqk_info->is_reload = true;
+                       }
+               }
+       }
+
+       return iqk_info->is_reload;
+}
+
+void _iqk_rfe_setting_8821c(struct dm_struct *dm, boolean ext_pa_on)
+{
+       if (ext_pa_on) {
+               /*RFE setting*/
+               odm_write_4byte(dm, 0xcb0, 0x77777777);
+               odm_write_4byte(dm, 0xcb4, 0x00007777);
+               odm_write_4byte(dm, 0xcbc, 0x0000083B);
+#if 0
+               /*odm_write_4byte(dm, 0x1990, 0x00000c30);*/
+#endif
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]external PA on!!!!\n");
+       } else {
+               /*RFE setting*/
+               odm_write_4byte(dm, 0xcb0, 0x77171117);
+               odm_write_4byte(dm, 0xcb4, 0x00001177);
+               odm_write_4byte(dm, 0xcbc, 0x00000404);
+#if 0
+               /*odm_write_4byte(dm, 0x1990, 0x00000c30);*/
+#endif
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]external PA off!!!!\n");
+       }
+}
+
+void _iqk_rfsetting_8821c(struct dm_struct *dm)
+{
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+
+       u8 path;
+       u32 tmp;
+
+       odm_write_4byte(dm, 0x1b00, 0xf8000008);
+       odm_write_4byte(dm, 0x1bb8, 0x00000000);
+
+       for (path = 0; path < SS_8821C; path++) {
+               /*0xdf:B11 = 1,B4 = 0, B1 = 1*/
+               tmp = odm_get_rf_reg(dm, (enum rf_path)path, RF_0xdf, RFREGOFFSETMASK);
+               tmp = (tmp & (~BIT(4))) | BIT(1) | BIT(11);
+               odm_set_rf_reg(dm, (enum rf_path)path, RF_0xdf, RFREGOFFSETMASK, tmp);
+
+               if (iqk_info->is_btg) {
+                       tmp = odm_get_rf_reg(dm, RF_PATH_A, RF_0xde, RFREGOFFSETMASK);
+                       tmp = (tmp & (~BIT(4))) | BIT(15);
+#if 0
+                       /*tmp = tmp|BIT(4)|BIT(15); //manual LOK value  for A-cut*/
+#endif
+                       odm_set_rf_reg(dm, RF_PATH_A, RF_0xde, RFREGOFFSETMASK, tmp);
+               }
+
+               if (!iqk_info->is_btg) {
+                       /*WLAN_AG*/
+                       /*TX IQK         mode init*/
+                       odm_set_rf_reg(dm, (enum rf_path)path, RF_0xef, RFREGOFFSETMASK, 0x80000);
+                       odm_set_rf_reg(dm, (enum rf_path)path, RF_0x33, RFREGOFFSETMASK, 0x00024);
+                       odm_set_rf_reg(dm, (enum rf_path)path, RF_0x3e, RFREGOFFSETMASK, 0x0003f);
+#if 0
+                       /*odm_set_rf_reg(dm, (enum rf_path)path, RF_0x3f, RFREGOFFSETMASK, 0x60fde);*/
+#endif
+                       odm_set_rf_reg(dm, (enum rf_path)path, RF_0x3f, RFREGOFFSETMASK, 0xe0fde);
+                       odm_set_rf_reg(dm, (enum rf_path)path, RF_0xef, RFREGOFFSETMASK, 0x00000);
+                       if (*dm->band_type == ODM_BAND_5G) {
+                               odm_set_rf_reg(dm, (enum rf_path)path, RF_0xef, BIT(19), 0x1);
+                               odm_set_rf_reg(dm, (enum rf_path)path, RF_0x33, RFREGOFFSETMASK, 0x00026);
+                               odm_set_rf_reg(dm, (enum rf_path)path, RF_0x3e, RFREGOFFSETMASK, 0x00037);
+                               odm_set_rf_reg(dm, (enum rf_path)path, RF_0x3f, RFREGOFFSETMASK, 0xdefce);
+                               odm_set_rf_reg(dm, (enum rf_path)path, RF_0xef, BIT(19), 0x0);
+                       } else {
+                               odm_set_rf_reg(dm, (enum rf_path)path, RF_0xef, BIT(19), 0x1);
+                               odm_set_rf_reg(dm, (enum rf_path)path, RF_0x33, RFREGOFFSETMASK, 0x00026);
+                               odm_set_rf_reg(dm, (enum rf_path)path, RF_0x3e, RFREGOFFSETMASK, 0x00037);
+                               odm_set_rf_reg(dm, (enum rf_path)path, RF_0x3f, RFREGOFFSETMASK, 0x5efce);
+                               odm_set_rf_reg(dm, (enum rf_path)path, RF_0xef, BIT(19), 0x0);
+                       }
+               } else {
+                       /*WLAN_BTG*/
+                       /*TX IQK         mode init*/
+                       odm_set_rf_reg(dm, (enum rf_path)path, RF_0xee, RFREGOFFSETMASK, 0x01000);
+                       odm_set_rf_reg(dm, (enum rf_path)path, RF_0x33, RFREGOFFSETMASK, 0x00004);
+                       odm_set_rf_reg(dm, (enum rf_path)path, RF_0x3f, RFREGOFFSETMASK, 0x01ec1);
+                       odm_set_rf_reg(dm, (enum rf_path)path, RF_0xee, RFREGOFFSETMASK, 0x00000);
+               }
+       }
+}
+
+void _iqk_configure_macbb_8821c(struct dm_struct *dm)
+{
+       /*MACBB register setting*/
+       odm_write_1byte(dm, 0x522, 0x7f);
+       odm_set_bb_reg(dm, R_0x1518, BIT(16), 0x1);
+       odm_set_bb_reg(dm, R_0x550, BIT(11) | BIT(3), 0x0);
+       odm_set_bb_reg(dm, R_0x90c, BIT(15), 0x1); /*0x90c[15]=1: dac_buf reset selection*/
+
+       /*0xc94[0]=1, 0xe94[0]=1: Let tx from IQK*/
+       odm_set_bb_reg(dm, R_0xc94, BIT(0), 0x1);
+       odm_set_bb_reg(dm, R_0xc94, (BIT(11) | BIT(10)), 0x1);
+       /* 3-wire off*/
+       odm_write_4byte(dm, 0xc00, 0x00000004);
+       /*disable PMAC*/
+       odm_set_bb_reg(dm, R_0xb00, BIT(8), 0x0);
+#if 0
+       /*      RF_DBG(dm, DBG_RF_IQK, "[IQK]Set MACBB setting for IQK!!!!\n");*/
+#endif
+       /*disable CCK block*/
+       odm_set_bb_reg(dm, R_0x808, BIT(28), 0x0);
+       /*disable OFDM CCA*/
+       odm_set_bb_reg(dm, R_0x838, BIT(3) | BIT(2) | BIT(1), 0x7);
+
+}
+
+void _iqk_lok_setting_8821c(struct dm_struct *dm, u8 path, u8 pad_index)
+{
+       u32 LOK0x56_2G = 0x50ef3;
+       u32 LOK0x56_5G = 0x50ee8;
+       u32 LOK0x33 = 0;
+       u32 LOK0x78 = 0xbcbba;
+       u32 tmp = 0;
+
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+
+       LOK0x33 = pad_index;
+       /*add delay of MAC send packet*/
+
+       if (*dm->mp_mode)
+               odm_set_bb_reg(dm, R_0x810, BIT(7) | BIT(6) | BIT(5) | BIT(4), 0x8);
+
+       if (iqk_info->is_btg) {
+               tmp = (LOK0x78 & 0x1c000) >> 14;
+               odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+               odm_write_4byte(dm, 0x1bcc, 0x1b);
+               odm_write_1byte(dm, 0x1b23, 0x00);
+               odm_write_1byte(dm, 0x1b2b, 0x80);
+               /*0x78[11:0] = IDAC value*/
+               LOK0x78 = LOK0x78 & (0xe3fff | ((u32)pad_index << 14));
+               odm_set_rf_reg(dm, path, RF_0x78, RFREGOFFSETMASK, LOK0x78);
+               odm_set_rf_reg(dm, path, RF_0x5c, RFREGOFFSETMASK, 0x05320);
+               odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xac018);
+               odm_set_rf_reg(dm, RF_PATH_A, RF_0xee, BIT(4), 0x1);
+               odm_set_rf_reg(dm, RF_PATH_A, RF_0x33, BIT(3), 0x0);
+               RF_DBG(dm, DBG_RF_IQK, "[IQK] In the BTG\n");
+       } else {
+               /*tmp = (LOK0x56 & 0xe0) >> 5;*/
+               odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+               odm_write_4byte(dm, 0x1bcc, 0x9);
+               odm_write_1byte(dm, 0x1b23, 0x00);
+
+               switch (*dm->band_type) {
+               case ODM_BAND_2_4G:
+                       odm_write_1byte(dm, 0x1b2b, 0x00);
+                       LOK0x56_2G = LOK0x56_2G & (0xfff1f | ((u32)pad_index << 5));
+                       odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, LOK0x56_2G);
+                       odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xadc18);
+                       odm_set_rf_reg(dm, RF_PATH_A, RF_0xef, BIT(4), 0x1);
+                       odm_set_rf_reg(dm, RF_PATH_A, RF_0x33, BIT(3), 0x0);
+                       break;
+               case ODM_BAND_5G:
+                       odm_write_1byte(dm, 0x1b2b, 0x00);
+                       LOK0x56_5G = LOK0x56_5G & (0xfff1f | ((u32)pad_index << 5));
+                       odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, LOK0x56_5G);
+                       odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xadc18);
+                       odm_set_rf_reg(dm, RF_PATH_A, RF_0xef, BIT(4), 0x1);
+                       odm_set_rf_reg(dm, RF_PATH_A, RF_0x33, BIT(3), 0x1);
+                       break;
+               }
+       }
+       /*for IDAC LUT by PAD idx*/
+       odm_set_rf_reg(dm, path, RF_0x33, BIT(2) | BIT(1) | BIT(0), LOK0x33);
+#if 0
+       /*      RF_DBG(dm, DBG_RF_IQK, "[IQK]Set LOK setting!!!!\n");*/
+#endif
+}
+
+void _iqk_txk_setting_8821c(struct dm_struct *dm, u8 path)
+{
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+
+       if (iqk_info->is_btg) {
+               odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+               odm_write_4byte(dm, 0x1bcc, 0x1b);
+               odm_write_4byte(dm, 0x1b20, 0x00840008);
+
+               /*0x78[11:0] = IDAC value*/
+               odm_set_rf_reg(dm, path, RF_0x78, RFREGOFFSETMASK, 0xbcbba);
+               odm_set_rf_reg(dm, path, RF_0x5c, RFREGOFFSETMASK, 0x04320);
+               odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xac018);
+               odm_write_1byte(dm, 0x1b2b, 0x80);
+       } else {
+               odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+               odm_write_4byte(dm, 0x1bcc, 0x9);
+               odm_write_4byte(dm, 0x1b20, 0x01440008);
+
+               switch (*dm->band_type) {
+               case ODM_BAND_2_4G:
+                       odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, 0x50EF3);
+                       odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xadc18);
+                       odm_write_1byte(dm, 0x1b2b, 0x00);
+                       break;
+               case ODM_BAND_5G:
+#if 0
+                       /*odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, 0x50EF0);*/
+                       /*odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, 0x50Ec8);*/
+#endif
+                       odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, 0x5004e);
+                       odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xa9c18);
+                       odm_write_1byte(dm, 0x1b2b, 0x00);
+                       break;
+               }
+       }
+#if 0
+       /*      RF_DBG(dm, DBG_RF_IQK, "[IQK]Set TXK setting!!!!\n");*/
+#endif
+}
+
+void _iqk_rxk1setting_8821c(struct dm_struct *dm, u8 path)
+{
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+
+       if (iqk_info->is_btg) {
+               odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+               odm_write_1byte(dm, 0x1b2b, 0x80);
+               odm_write_4byte(dm, 0x1bcc, 0x09);
+               odm_write_4byte(dm, 0x1b20, 0x01450008);
+               odm_write_4byte(dm, 0x1b24, 0x01460c88);
+
+               /*0x78[11:0] = IDAC value*/
+               odm_set_rf_reg(dm, path, RF_0x78, RFREGOFFSETMASK, 0x8cbba);
+               odm_set_rf_reg(dm, path, RF_0x5c, RFREGOFFSETMASK, 0x00320);
+               odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xa8018);
+       } else {
+               odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+               switch (*dm->band_type) {
+               case ODM_BAND_2_4G:
+                       odm_write_1byte(dm, 0x1bcc, 0x12);
+                       odm_write_1byte(dm, 0x1b2b, 0x00);
+                       odm_write_4byte(dm, 0x1b20, 0x01450008);
+                       odm_write_4byte(dm, 0x1b24, 0x01461068);
+
+                       odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, 0x510f3);
+                       odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xa9c00);
+                       break;
+               case ODM_BAND_5G:
+                       odm_write_1byte(dm, 0x1bcc, 0x9);
+                       odm_write_1byte(dm, 0x1b2b, 0x00);
+                       odm_write_4byte(dm, 0x1b20, 0x00450008);
+                       odm_write_4byte(dm, 0x1b24, 0x00461468);
+
+                       odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, 0x510f3);
+                       odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xa9c00);
+                       break;
+               }
+       }
+#if 0
+       /*RF_DBG(dm, DBG_RF_IQK, "[IQK]Set RXK setting!!!!\n");*/
+#endif
+}
+
+static u8 btg_lna[5] = {0x0, 0x4, 0x8, 0xc, 0xf};
+static u8 wlg_lna[5] = {0x0, 0x1, 0x2, 0x3, 0x5};
+static u8 wla_lna[5] = {0x0, 0x1, 0x3, 0x4, 0x5};
+
+void _iqk_rxk2setting_8821c(struct dm_struct *dm, u8 path, boolean is_gs)
+{
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+
+       if (iqk_info->is_btg) {
+               if (is_gs) {
+                       iqk_info->tmp1bcc = 0x1b;
+                       iqk_info->lna_idx = 2;
+               }
+               odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+               odm_write_1byte(dm, 0x1b2b, 0x80);
+               odm_write_4byte(dm, 0x1bcc, iqk_info->tmp1bcc);
+               odm_write_4byte(dm, 0x1b20, 0x01450008);
+               odm_write_4byte(dm, 0x1b24, (0x01460048 | (btg_lna[iqk_info->lna_idx] << 10)));
+               /*0x78[11:0] = IDAC value*/
+               odm_set_rf_reg(dm, path, RF_0x78, RFREGOFFSETMASK, 0x8cbba);
+               odm_set_rf_reg(dm, path, RF_0x5c, RFREGOFFSETMASK, 0x00320);
+               odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xa8018);
+       } else {
+               odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+               switch (*dm->band_type) {
+               case ODM_BAND_2_4G:
+                       if (is_gs) {
+                               iqk_info->tmp1bcc = 0x12;
+                               iqk_info->lna_idx = 2;
+                       }
+                       odm_write_1byte(dm, 0x1bcc, iqk_info->tmp1bcc);
+                       odm_write_1byte(dm, 0x1b2b, 0x00);
+                       odm_write_4byte(dm, 0x1b20, 0x01450008);
+                       odm_write_4byte(dm, 0x1b24, (0x01460048 | (wlg_lna[iqk_info->lna_idx] << 10)));
+                       odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, 0x510f3);
+                       odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xa9c00);
+                       break;
+               case ODM_BAND_5G:
+                       if (is_gs) {
+                               /*iqk_info->tmp1bcc = 0x12;*/
+                               iqk_info->tmp1bcc = 0x09;
+                               iqk_info->lna_idx = 2;
+                       }
+                       odm_write_1byte(dm, 0x1bcc, iqk_info->tmp1bcc);
+                       odm_write_1byte(dm, 0x1b2b, 0x00);
+                       odm_write_4byte(dm, 0x1b20, 0x00450008);
+                       odm_write_4byte(dm, 0x1b24, (0x01460048 | (wla_lna[iqk_info->lna_idx] << 10)));
+#if 0
+                       /*odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, 0x51000);*/
+#endif
+                       odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, 0x51060);
+                       odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xa9c00);
+                       break;
+               }
+       }
+#if 0
+       /*      RF_DBG(dm, DBG_RF_IQK, "[IQK]Set RXK setting!!!!\n");*/
+#endif
+}
+
+boolean
+_iqk_check_cal_8821c(struct dm_struct *dm, u32 IQK_CMD)
+{
+       boolean notready = true, fail = true;
+       u32 delay_count = 0x0;
+
+       while (notready) {
+               if (odm_read_4byte(dm, 0x1b00) == (IQK_CMD & 0xffffff0f)) {
+                       fail = (boolean)odm_get_bb_reg(dm, R_0x1b08, BIT(26));
+                       notready = false;
+               } else {
+#if 0
+                       /*ODM_sleep_ms(1);*/
+#endif
+                       ODM_delay_ms(1);
+                       delay_count++;
+               }
+
+               if (delay_count >= 50) {
+                       fail = true;
+                       RF_DBG(dm, DBG_RF_IQK, "[IQK]IQK timeout!!!\n");
+                       break;
+               }
+       }
+#if 0
+       /*
+       RF_DBG(dm, DBG_RF_IQK,
+                    "[IQK]delay count = 0x%x!!!\n", delay_count);
+*/
+#endif
+       return fail;
+}
+
+boolean
+_iqk_rx_iqk_gain_search_fail_8821c(struct dm_struct *dm, u8 path, u8 step)
+{
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+       boolean fail = true;
+       u32 IQK_CMD = 0x0, rf_reg0, tmp, rxbb;
+       u8 IQMUX[4] = {0x9, 0x12, 0x1b, 0x24}, *plna;
+       u8 idx;
+       /*u8    lna_setting[5];*/
+
+       if (iqk_info->is_btg)
+               plna = btg_lna;
+       else if (*dm->band_type == ODM_BAND_2_4G)
+               plna = wlg_lna;
+       else
+               plna = wla_lna;
+
+       for (idx = 0; idx < 4; idx++)
+               if (iqk_info->tmp1bcc == IQMUX[idx])
+                       break;
+
+       odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+       odm_write_4byte(dm, 0x1bcc, iqk_info->tmp1bcc);
+
+       if (step == RXIQK1)
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[IQK]============ S%d RXIQK GainSearch ============\n",
+                      iqk_info->is_btg);
+
+       if (step == RXIQK1)
+               IQK_CMD = 0xf8000208 | (1 << (path + 4));
+       else
+               IQK_CMD = 0xf8000308 | (1 << (path + 4));
+
+       RF_DBG(dm, DBG_RF_IQK, "[IQK]S%d GS%d_Trigger = 0x%x\n", path, step,
+              IQK_CMD);
+
+       _iqk_set_gnt_wl_gnt_bt(dm, true);
+       odm_write_4byte(dm, 0x1b00, IQK_CMD);
+       odm_write_4byte(dm, 0x1b00, IQK_CMD + 0x1);
+#if 0
+       /*ODM_sleep_ms(GS_delay_8821C);*/
+#endif
+       ODM_delay_ms(GS_delay_8821C);
+       fail = _iqk_check_cal_8821c(dm, IQK_CMD);
+       RF_DBG(dm, DBG_RF_IQK, "[IQK]check 0x49c = %x\n",
+              odm_read_1byte(dm, 0x49c));
+       _iqk_set_gnt_wl_gnt_bt(dm, false);
+
+       if (step == RXIQK2) {
+               rf_reg0 = odm_get_rf_reg(dm, (enum rf_path)path, RF_0x0, RFREGOFFSETMASK);
+               odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[IQK]S%d ==> RF0x0 = 0x%x, tmp1bcc = 0x%x, idx = %d, 0x1b3c = 0x%x\n",
+                      path, rf_reg0, iqk_info->tmp1bcc, idx,
+                      odm_read_4byte(dm, 0x1b3c));
+               tmp = (rf_reg0 & 0x1fe0) >> 5;
+               rxbb = tmp & 0x1f;
+#if 1
+
+               if (rxbb == 0x1) {
+                       if (idx != 3)
+                               idx++;
+                       else if (iqk_info->lna_idx != 0x0)
+                               iqk_info->lna_idx--;
+                       else
+                               iqk_info->isbnd = true;
+                       fail = true;
+               } else if (rxbb == 0xa) {
+                       if (idx != 0)
+                               idx--;
+                       else if (iqk_info->lna_idx != 0x4)
+                               iqk_info->lna_idx++;
+                       else
+                               iqk_info->isbnd = true;
+                       fail = true;
+               } else {
+                       fail = false;
+               }
+
+               if (iqk_info->isbnd)
+                       fail = false;
+#endif
+
+#if 0
+               if (rxbb == 0x1) {
+                       if (iqk_info->lna_idx != 0x0)
+                               iqk_info->lna_idx--;
+                       else if (idx != 3)
+                               idx++;
+                       else
+                               iqk_info->isbnd = true;
+                       fail = true;
+               } else if (rxbb == 0xa) {
+                       if (idx != 0)
+                               idx--;
+                       else if (iqk_info->lna_idx != 0x7)
+                               iqk_info->lna_idx++;
+                       else
+                               iqk_info->isbnd = true;
+                       fail = true;
+               } else
+                       fail = false;
+
+               if (iqk_info->isbnd == true)
+                       fail = false;
+#endif
+               iqk_info->tmp1bcc = IQMUX[idx];
+
+               if (fail) {
+                       odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+                       odm_write_4byte(dm, 0x1b24, (odm_read_4byte(dm, 0x1b24) & 0xffffc3ff) | (*(plna + iqk_info->lna_idx) << 10));
+               }
+       }
+       return fail;
+}
+void _iqk_rxk2setting_by_toneindex_8821c(struct dm_struct *dm, u8 path,
+                                        boolean is_gs, u8 toneindex)
+{
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+
+       if (iqk_info->is_btg) {
+               iqk_info->tmp1bcc = 0x1b;
+               iqk_info->lna_idx = 2;
+               odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+               odm_write_1byte(dm, 0x1b2b, 0x80);
+               odm_write_4byte(dm, 0x1bcc, iqk_info->tmp1bcc);
+               odm_write_4byte(dm, 0x1b20, 0x01450008);
+               odm_write_4byte(dm, 0x1b24, (0x01460048 | (btg_lna[iqk_info->lna_idx] << 10)));
+               /*0x78[11:0] = IDAC value*/
+               odm_set_rf_reg(dm, path, RF_0x78, RFREGOFFSETMASK, 0x8cbba);
+               odm_set_rf_reg(dm, path, RF_0x5c, RFREGOFFSETMASK, 0x00320);
+               odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xa8018);
+       } else {
+               odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+               switch (*dm->band_type) {
+               case ODM_BAND_2_4G:
+                       iqk_info->tmp1bcc = 0x12;
+                       iqk_info->lna_idx = 2;
+                       odm_write_1byte(dm, 0x1bcc, iqk_info->tmp1bcc);
+                       odm_write_1byte(dm, 0x1b2b, 0x00);
+                       odm_write_4byte(dm, 0x1b20, 0x01450008);
+                       odm_write_4byte(dm, 0x1b24, (0x01460048 | (wlg_lna[iqk_info->lna_idx] << 10)));
+                       odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, 0x510f3);
+                       odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xa9c00);
+                       break;
+               case ODM_BAND_5G:
+                       iqk_info->tmp1bcc = 0x09;
+                       iqk_info->lna_idx = 2;
+                       odm_write_1byte(dm, 0x1bcc, iqk_info->tmp1bcc);
+                       odm_write_1byte(dm, 0x1b2b, 0x00);
+                       odm_write_4byte(dm, 0x1b20, 0x00450008);
+                       odm_write_4byte(dm, 0x1b24, (0x01460048 | (wla_lna[iqk_info->lna_idx] << 10)));
+#if 0
+                       /*odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, 0x51000);*/
+#endif
+                       odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, 0x51060);
+                       odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xa9c00);
+                       break;
+               }
+       }
+       odm_write_4byte(dm, 0x1b20, (odm_read_4byte(dm, 0x1b20) & 0x000fffff) | toneindex << 20);
+       odm_write_4byte(dm, 0x1b24, (odm_read_4byte(dm, 0x1b24) & 0x000fffff) | toneindex << 20);
+}
+
+boolean
+_iqk_rx_iqk_gain_search_fail_by_toneindex_8821c(struct dm_struct *dm, u8 path,
+                                               u8 step, u8 tone_index)
+{
+       boolean fail = true;
+       u32 IQK_CMD;
+#if 0
+       /*u8    lna_setting[5];*/
+#endif
+
+       _iqk_rxk2setting_by_toneindex_8821c(dm, path, RXIQK1, tone_index);
+       odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+
+       IQK_CMD = 0xf8000208 | (1 << (path + 4));
+
+       _iqk_set_gnt_wl_gnt_bt(dm, true);
+       odm_write_4byte(dm, 0x1b00, IQK_CMD);
+       odm_write_4byte(dm, 0x1b00, IQK_CMD + 0x1);
+#if 0
+       /*ODM_sleep_ms(GS_delay_8821C);*/
+#endif
+       ODM_delay_ms(GS_delay_8821C);
+       fail = _iqk_check_cal_8821c(dm, IQK_CMD);
+       _iqk_set_gnt_wl_gnt_bt(dm, false);
+
+       return fail;
+}
+
+boolean
+_lok_one_shot_8821c(void *dm_void, u8 path, u8 pad_index)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+       u8 delay_count = 0;
+       boolean LOK_notready = false;
+       u32 LOK_temp2 = 0, LOK_temp3 = 0;
+       u32 IQK_CMD = 0x0;
+#if 0
+       /*u8            LOKreg[] = {0x58, 0x78};*/
+#endif
+       RF_DBG(dm, DBG_RF_IQK, "[IQK]==========S%d LOK ==========\n",
+              iqk_info->is_btg);
+
+       IQK_CMD = 0xf8000008 | (1 << (4 + path));
+
+       RF_DBG(dm, DBG_RF_IQK, "[IQK]LOK_Trigger = 0x%x\n", IQK_CMD);
+
+       _iqk_set_gnt_wl_gnt_bt(dm, true);
+       odm_write_4byte(dm, 0x1b00, IQK_CMD);
+       odm_write_4byte(dm, 0x1b00, IQK_CMD + 1);
+       /*LOK: CMD ID = 0       {0xf8000018, 0xf8000028}*/
+       /*LOK: CMD ID = 0       {0xf8000019, 0xf8000029}*/
+#if 0
+       /*ODM_sleep_ms(LOK_delay_8821C);*/
+#endif
+       ODM_delay_ms(LOK_delay_8821C);
+
+       delay_count = 0;
+       LOK_notready = true;
+
+       while (LOK_notready) {
+               if (odm_get_rf_reg(dm, path, RF_0x8, RFREGOFFSETMASK) == 0x12345)
+                       LOK_notready = false;
+               else
+                       LOK_notready = true;
+
+               if (LOK_notready) {
+#if 0
+                       /*ODM_sleep_ms(1);*/
+#endif
+                       ODM_delay_ms(1);
+                       delay_count++;
+               }
+
+               if (delay_count >= 50) {
+                       RF_DBG(dm, DBG_RF_IQK, "[IQK]S%d LOK timeout!!!\n",
+                              path);
+                       break;
+               }
+       }
+       odm_set_rf_reg(dm, path, RF_0x8, RFREGOFFSETMASK, 0x0);
+
+       _iqk_set_gnt_wl_gnt_bt(dm, false);
+       RF_DBG(dm, DBG_RF_IQK, "[IQK]S%d ==> delay_count = 0x%x\n", path,
+              delay_count);
+
+       if (!LOK_notready) {
+               LOK_temp2 = odm_get_rf_reg(dm, (enum rf_path)path, RF_0x8, RFREGOFFSETMASK);
+               LOK_temp3 = odm_get_rf_reg(dm, (enum rf_path)path, RF_0x58, RFREGOFFSETMASK);
+
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]0x8 = 0x%x, 0x58 = 0x%x\n",
+                      LOK_temp2, LOK_temp3);
+       } else {
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]==>S%d LOK Fail!!!\n", path);
+       }
+
+       iqk_info->lok_fail[path] = LOK_notready;
+
+       /*fill IDAC LUT table*/
+#if 0
+       /*
+       for (i = 0; i < 8; i++) {
+               odm_set_rf_reg(dm, path, RF_0x33, BIT(2)|BIT(1)|BIT(0), i);
+               odm_set_rf_reg(dm, path, RF_0x8, RFREGOFFSETMASK, LOK_temp2);
+       }
+       */
+#endif
+       return LOK_notready;
+}
+
+boolean
+_iqk_one_shot_8821c(void *dm_void, u8 path, u8 idx)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+       u8 delay_count = 0;
+       boolean fail = true;
+       u32 IQK_CMD = 0x0;
+       u16 iqk_apply[2] = {0xc94, 0xe94};
+
+       if (idx == TX_IQK)
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[IQK]============ S%d WBTXIQK ============\n",
+                      iqk_info->is_btg);
+       else if (idx == RXIQK1)
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[IQK]============ S%d WBRXIQK STEP1============\n",
+                      iqk_info->is_btg);
+       else
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[IQK]============ S%d WBRXIQK STEP2============\n",
+                      iqk_info->is_btg);
+
+       if (idx == TXIQK) {
+               IQK_CMD = 0xf8000008 | ((*dm->band_width + 4) << 8) | (1 << (path + 4));
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]TXK_Trigger = 0x%x\n", IQK_CMD);
+#if 0
+               /*{0xf8000418, 0xf800042a} ==> 20 WBTXK (CMD = 4)*/
+               /*{0xf8000518, 0xf800052a} ==> 40 WBTXK (CMD = 5)*/
+               /*{0xf8000618, 0xf800062a} ==> 80 WBTXK (CMD = 6)*/
+#endif
+       } else if (idx == RXIQK1) {
+               if (*dm->band_width == 2)
+                       IQK_CMD = 0xf8000808 | (1 << (path + 4));
+               else
+                       IQK_CMD = 0xf8000708 | (1 << (path + 4));
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]RXK1_Trigger = 0x%x\n", IQK_CMD);
+#if 0
+               /*{0xf8000718, 0xf800072a} ==> 20 WBTXK (CMD = 7)*/
+               /*{0xf8000718, 0xf800072a} ==> 40 WBTXK (CMD = 7)*/
+               /*{0xf8000818, 0xf800082a} ==> 80 WBTXK (CMD = 8)*/
+#endif
+       } else if (idx == RXIQK2) {
+               IQK_CMD = 0xf8000008 | ((*dm->band_width + 9) << 8) | (1 << (path + 4));
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]RXK2_Trigger = 0x%x\n", IQK_CMD);
+#if 0
+               /*{0xf8000918, 0xf800092a} ==> 20 WBRXK (CMD = 9)*/
+               /*{0xf8000a18, 0xf8000a2a} ==> 40 WBRXK (CMD = 10)*/
+               /*{0xf8000b18, 0xf8000b2a} ==> 80 WBRXK (CMD = 11)*/
+#endif
+       }
+
+       _iqk_set_gnt_wl_gnt_bt(dm, true);
+
+       odm_write_4byte(dm, 0x1bc8, 0x80000000);
+       odm_write_4byte(dm, 0x8f8, 0x41400080);
+
+       if (odm_get_rf_reg(dm, path, RF_0x08, RFREGOFFSETMASK) != 0x0)
+               odm_set_rf_reg(dm, path, RF_0x8, RFREGOFFSETMASK, 0x0);
+
+       odm_write_4byte(dm, 0x1b00, IQK_CMD);
+       odm_write_4byte(dm, 0x1b00, IQK_CMD + 0x1);
+
+#if 0
+       /*ODM_sleep_ms(WBIQK_delay_8821C);*/
+#endif
+       ODM_delay_ms(WBIQK_delay_8821C);
+
+       fail = _iqk_check_nctl_done_8821c(dm, path, IQK_CMD);
+
+       RF_DBG(dm, DBG_RF_IQK, "[IQK]check 0x49c = %x\n",
+              odm_read_1byte(dm, 0x49c));
+
+       _iqk_set_gnt_wl_gnt_bt(dm, false);
+
+       if (dm->debug_components & DBG_RF_IQK) {
+               odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[IQK]S%d ==> 0x1b00 = 0x%x, 0x1b08 = 0x%x\n", path,
+                      odm_read_4byte(dm, 0x1b00), odm_read_4byte(dm, 0x1b08));
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]S%d ==> delay_count = 0x%x\n",
+                      path, delay_count);
+               if (idx != TXIQK)
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[IQK]S%d ==> RF0x0 = 0x%x, RF0x%x = 0x%x\n",
+                              path,
+                              odm_get_rf_reg(dm, path, RF_0x0,
+                                             RFREGOFFSETMASK),
+                              (iqk_info->is_btg) ? 0x78 : 0x56,
+                              (iqk_info->is_btg) ?
+                              odm_get_rf_reg(dm, path, RF_0x78,
+                                             RFREGOFFSETMASK) :
+                              odm_get_rf_reg(dm, path, RF_0x56,
+                                             RFREGOFFSETMASK));
+       }
+
+       odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+       if (idx == TXIQK) {
+               if (fail)
+                       odm_set_bb_reg(dm, iqk_apply[path], BIT(0), 0x0);
+               else
+                       _iqk_backup_iqk_8821c(dm, 0x2, path);
+       }
+       if (idx == RXIQK2) {
+               iqk_info->rxiqk_agc[0][path] =
+                       (u16)(((odm_get_rf_reg(dm, (enum rf_path)path, RF_0x0, RFREGOFFSETMASK) >> 5) & 0xff) |
+                             (iqk_info->tmp1bcc << 8));
+
+               odm_write_4byte(dm, 0x1b38, 0x20000000);
+
+               if (fail)
+                       odm_set_bb_reg(dm, iqk_apply[path], (BIT(11) | BIT(10)), 0x0);
+               else
+                       _iqk_backup_iqk_8821c(dm, 0x3, path);
+       }
+
+       if (idx == TXIQK)
+               iqk_info->iqk_fail_report[0][path][TXIQK] = fail;
+       else
+               iqk_info->iqk_fail_report[0][path][RXIQK] = fail;
+
+       return fail;
+}
+
+boolean
+_iqk_rxiqkbystep_8821c(void *dm_void, u8 path)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+       boolean KFAIL = true, gonext;
+
+#if 1
+       switch (iqk_info->rxiqk_step) {
+       case 1: /*gain search_RXK1*/
+               _iqk_rxk1setting_8821c(dm, path);
+               gonext = false;
+               while (1) {
+                       KFAIL = _iqk_rx_iqk_gain_search_fail_8821c(dm, path, RXIQK1);
+                       if (KFAIL && iqk_info->gs_retry_count[0][path][0] < 2) {
+                               iqk_info->gs_retry_count[0][path][0]++;
+                       } else if (KFAIL) {
+                               iqk_info->rxiqk_fail_code[0][path] = 0;
+                               iqk_info->rxiqk_step = 5;
+                               gonext = true;
+                       } else {
+                               iqk_info->rxiqk_step++;
+                               gonext = true;
+                       }
+                       if (gonext)
+                               break;
+               }
+               halrf_iqk_xym_read(dm, 0x0, 0x2);
+               break;
+       case 2: /*gain search_RXK2*/
+               _iqk_rxk2setting_8821c(dm, path, true);
+               iqk_info->isbnd = false;
+               while (1) {
+                       KFAIL = _iqk_rx_iqk_gain_search_fail_8821c(dm, path, RXIQK2);
+                       if (KFAIL && iqk_info->gs_retry_count[0][path][1] < rxiqk_gs_limit) {
+                               iqk_info->gs_retry_count[0][path][1]++;
+                       } else {
+                               iqk_info->rxiqk_step++;
+                               break;
+                       }
+               }
+               halrf_iqk_xym_read(dm, 0x0, 0x3);
+               break;
+       case 3: /*RXK1*/
+               _iqk_rxk1setting_8821c(dm, path);
+               gonext = false;
+               while (1) {
+                       KFAIL = _iqk_one_shot_8821c(dm, path, RXIQK1);
+                       if (KFAIL && iqk_info->retry_count[0][path][RXIQK1] < 2) {
+                               iqk_info->retry_count[0][path][RXIQK1]++;
+                       } else if (KFAIL) {
+                               iqk_info->rxiqk_fail_code[0][path] = 1;
+                               iqk_info->rxiqk_step = 5;
+                               gonext = true;
+                       } else {
+                               iqk_info->rxiqk_step++;
+                               gonext = true;
+                       }
+                       if (gonext)
+                               break;
+               }
+               halrf_iqk_xym_read(dm, 0x0, 0x4);
+               break;
+       case 4: /*RXK2*/
+               _iqk_rxk2setting_8821c(dm, path, false);
+               gonext = false;
+               while (1) {
+                       KFAIL = _iqk_one_shot_8821c(dm, path, RXIQK2);
+                       if (KFAIL && iqk_info->retry_count[0][path][RXIQK2] < 2) {
+                               iqk_info->retry_count[0][path][RXIQK2]++;
+                       } else if (KFAIL) {
+                               iqk_info->rxiqk_fail_code[0][path] = 2;
+                               iqk_info->rxiqk_step = 5;
+                               gonext = true;
+                       } else {
+                               iqk_info->rxiqk_step++;
+                               gonext = true;
+                       }
+                       if (gonext)
+                               break;
+               }
+               halrf_iqk_xym_read(dm, 0x0, 0x0);
+               break;
+       }
+       return KFAIL;
+#endif
+}
+void _iqk_iqk_by_path_8821c(void *dm_void, boolean segment_iqk)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+       boolean KFAIL = true;
+       u8 i, kcount_limit;
+
+#if 0
+       /*      RF_DBG(dm, DBG_RF_IQK, "[IQK]iqk_step = 0x%x\n", dm->rf_calibrate_info.iqk_step); */
+#endif
+       if (*dm->band_width == 2)
+               kcount_limit = kcount_limit_80m;
+       else
+               kcount_limit = kcount_limit_others;
+
+       while (1) {
+               switch (dm->rf_calibrate_info.iqk_step) {
+               case 1: /*S0 LOK*/
+                       for (i = 0; i < 8; i++) { /* the LOK Cal in the each PAD stage*/
+                               _iqk_lok_setting_8821c(dm, RF_PATH_A, i);
+                               _lok_one_shot_8821c(dm, RF_PATH_A, i);
+                       }
+                       dm->rf_calibrate_info.iqk_step++;
+                       break;
+               case 2: /*S0 TXIQK*/
+                       _iqk_txk_setting_8821c(dm, RF_PATH_A);
+                       KFAIL = _iqk_one_shot_8821c(dm, RF_PATH_A, TXIQK);
+                       iqk_info->kcount++;
+                       RF_DBG(dm, DBG_RF_IQK, "[IQK]KFail = 0x%x\n", KFAIL);
+                       if (KFAIL && iqk_info->retry_count[0][RF_PATH_A][TXIQK] < 3)
+                               iqk_info->retry_count[0][RF_PATH_A][TXIQK]++;
+                       else
+                               dm->rf_calibrate_info.iqk_step++;
+                       halrf_iqk_xym_read(dm, 0x0, 0x1);
+                       break;
+               case 3: /*S0 RXIQK*/
+                       while (1) {
+                               KFAIL = _iqk_rxiqkbystep_8821c(dm, RF_PATH_A);
+                               RF_DBG(dm, DBG_RF_IQK,
+                                      "[IQK]S0RXK KFail = 0x%x\n", KFAIL);
+                               if (iqk_info->rxiqk_step == 5) {
+                                       dm->rf_calibrate_info.iqk_step++;
+                                       iqk_info->rxiqk_step = 1;
+                                       if (KFAIL)
+                                               RF_DBG(dm, DBG_RF_IQK, "[IQK]S0RXK fail code: %d!!!\n", iqk_info->rxiqk_fail_code[0][RF_PATH_A]);
+                                       break;
+                               }
+                       }
+                       iqk_info->kcount++;
+                       break;
+               }
+
+               if (dm->rf_calibrate_info.iqk_step == 4) {
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[IQK]==========LOK summary ==========\n");
+                       RF_DBG(dm, DBG_RF_IQK, "[IQK]PathA_LOK_notready = %d\n",
+                              iqk_info->lok_fail[RF_PATH_A]);
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[IQK]==========IQK summary ==========\n");
+                       RF_DBG(dm, DBG_RF_IQK, "[IQK]PathA_TXIQK_fail = %d\n",
+                              iqk_info->iqk_fail_report[0][RF_PATH_A][TXIQK]);
+                       RF_DBG(dm, DBG_RF_IQK, "[IQK]PathA_RXIQK_fail = %d\n",
+                              iqk_info->iqk_fail_report[0][RF_PATH_A][RXIQK]);
+                       RF_DBG(dm, DBG_RF_IQK, "[IQK]PathA_TXIQK_retry = %d\n",
+                              iqk_info->retry_count[0][RF_PATH_A][TXIQK]);
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[IQK]PathA_RXK1_retry = %d, PathA_RXK2_retry = %d\n",
+                              iqk_info->retry_count[0][RF_PATH_A][RXIQK1],
+                              iqk_info->retry_count[0][RF_PATH_A][RXIQK2]);
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[IQK]PathA_GS1_retry = %d, PathA_GS2_retry = %d\n",
+                              iqk_info->gs_retry_count[0][RF_PATH_A][0],
+                              iqk_info->gs_retry_count[0][RF_PATH_A][1]);
+
+                       for (i = 0; i < SS_8821C; i++) {
+                               odm_write_4byte(dm, 0x1b00, 0xf8000008 | i << 1);
+                               odm_write_4byte(dm, 0x1b2c, 0x7);
+                               odm_write_4byte(dm, 0x1bcc, 0x0);
+                               odm_write_4byte(dm, 0x1b38, 0x20000000);
+                       }
+                       break;
+               }
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]segmentIQK = %d, Kcount = %d\n",
+                      segment_iqk, iqk_info->kcount);
+               if (segment_iqk && iqk_info->kcount == kcount_limit)
+                       break;
+       }
+}
+
+void _iqk_start_iqk_8821c(struct dm_struct *dm, boolean segment_iqk)
+{
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+       u32 tmp;
+
+       odm_write_4byte(dm, 0x1b00, 0xf8000008);
+       odm_write_4byte(dm, 0x1bb8, 0x00000000);
+       /*GNT_WL = 1*/
+       if (iqk_info->is_btg) {
+               tmp = odm_get_rf_reg(dm, RF_PATH_A, RF_0x1, RFREGOFFSETMASK);
+               tmp = (tmp & (~BIT(3))) | BIT(0) | BIT(2) | BIT(5);
+               odm_set_rf_reg(dm, RF_PATH_A, RF_0x1, RFREGOFFSETMASK, tmp);
+       } else {
+               tmp = odm_get_rf_reg(dm, RF_PATH_A, RF_0x1, RFREGOFFSETMASK);
+               tmp = ((tmp & (~BIT(3))) & (~BIT(5))) | BIT(0) | BIT(2);
+               odm_set_rf_reg(dm, RF_PATH_A, RF_0x1, RFREGOFFSETMASK, tmp);
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]==> RF0x1 = 0x%x\n",
+                      odm_get_rf_reg(dm, RF_PATH_A, RF_0x1, RFREGOFFSETMASK));
+       }
+       _iqk_iqk_by_path_8821c(dm, segment_iqk);
+}
+
+void _iq_calibrate_8821c_init(struct dm_struct *dm)
+{
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+       u8 i, j, k, m;
+       static boolean firstrun = true;
+
+       if (firstrun) {
+               firstrun = false;
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[IQK]=====>PHY_IQCalibrate_8821C_Init\n");
+
+               for (i = 0; i < SS_8821C; i++) {
+                       for (j = 0; j < 2; j++) {
+                               iqk_info->lok_fail[i] = true;
+                               iqk_info->iqk_fail[j][i] = true;
+                               iqk_info->iqc_matrix[j][i] = 0x20000000;
+                       }
+               }
+
+               for (i = 0; i < 2; i++) {
+                       iqk_info->iqk_channel[i] = 0x0;
+
+                       for (j = 0; j < SS_8821C; j++) {
+                               iqk_info->lok_idac[i][j] = 0x0;
+                               iqk_info->rxiqk_agc[i][j] = 0x0;
+                               iqk_info->bypass_iqk[i][j] = 0x0;
+
+                               for (k = 0; k < 2; k++) {
+                                       iqk_info->iqk_fail_report[i][j][k] = true;
+                                       for (m = 0; m < 8; m++) {
+                                               iqk_info->iqk_cfir_real[i][j][k][m] = 0x0;
+                                               iqk_info->iqk_cfir_imag[i][j][k][m] = 0x0;
+                                       }
+                               }
+
+                               for (k = 0; k < 3; k++)
+                                       iqk_info->retry_count[i][j][k] = 0x0;
+                       }
+               }
+       }
+}
+
+u8 _txgapk_txpower_compare_8821c(struct dm_struct *dm, u8 path, u32 pw1,
+                                u32 pw2, u32 *pwr_table)
+{
+       u8 pwr_delta;
+       u32 temp = 0x0;
+       temp = (u32)(pw1 / (pw2 / 1000));
+
+       if (temp < pwr_table[0]) /*<-3.5 dB*/
+               pwr_delta = 0x0;
+       else if (temp < pwr_table[1])
+               pwr_delta = 0x1;
+       else if (temp < pwr_table[2])
+               pwr_delta = 0x2;
+       else if (temp < pwr_table[3])
+               pwr_delta = 0x3;
+       else if (temp < pwr_table[4])
+               pwr_delta = 0x4;
+       else if (temp < pwr_table[5])
+               pwr_delta = 0x5;
+       else if (temp < pwr_table[6])
+               pwr_delta = 0x6;
+       else if (temp < pwr_table[7])
+               pwr_delta = 0x7;
+       else if (temp < pwr_table[8])
+               pwr_delta = 0x8;
+       else if (temp < pwr_table[9])
+               pwr_delta = 0x9;
+       else if (temp < pwr_table[0xa])
+               pwr_delta = 0xa;
+       else if (temp < pwr_table[0xb])
+               pwr_delta = 0xb;
+       else if (temp < pwr_table[0xc])
+               pwr_delta = 0xc;
+       else if (temp < pwr_table[0xd])
+               pwr_delta = 0xd;
+       else if (temp < pwr_table[0xe])
+               pwr_delta = 0xe;
+       else if (temp < pwr_table[0xf])
+               pwr_delta = 0xf;
+       else if (temp < pwr_table[0x10])
+               pwr_delta = 0x10;
+       else if (temp < pwr_table[0x11])
+               pwr_delta = 0x11;
+       else if (temp < pwr_table[0x12])
+               pwr_delta = 0x12;
+       else if (temp < pwr_table[0x13])
+               pwr_delta = 0x13;
+       else if (temp < pwr_table[0x14])
+               pwr_delta = 0x14;
+       else if (temp < pwr_table[0x15])
+               pwr_delta = 0x15;
+       else if (temp < pwr_table[0x16])
+               pwr_delta = 0x16;
+       else if (temp < pwr_table[0x17])
+               pwr_delta = 0x17;
+       else if (temp < pwr_table[0x18])
+               pwr_delta = 0x18;
+       else if (temp < pwr_table[0x19])
+               pwr_delta = 0x19;
+       else
+               pwr_delta = 0x1a;
+
+       RF_DBG(dm, DBG_RF_IQK, "[TXGAPK] temp =%d, pwr_delta =%x\n", temp,
+              pwr_delta);
+
+       return pwr_delta;
+}
+
+u32 _txgapk_txgap_compenstion_8821c(struct dm_struct *dm, u8 path,
+                                   u32 txgain_0x56, u8 pwr_delta)
+{
+       u32 new_txgain_0x56;
+
+       /*      0       1       2       3       4       5       6       7       8       9       10      11      12      13      14 */
+       /*      -3.5    -3 -2.5  -2  -1.5  -1  -0.5    0   0.5    1     1.5   2   2.5     3    3.5 (dB)*/
+#if 0
+       /*      pwr_table[0xf]={89,100,112,125,141,158,177,199,223,251,281,316,354,398,446}*/
+#endif
+
+       switch (pwr_delta) {
+       case 0x1a:
+       case 0x19:
+       case 0x18:
+       case 0x17:
+       case 0x16:
+       case 0x15:
+       case 0x14:
+#if 0
+       /*
+                                               if ((txgain_0x56 & 0x1f)<=0x1d)
+                                                       new_txgain_0x56 = txgain_0x56 + 0x2; //< -1.5 ~ -2.5dB
+                                               else if ((txgain_0x56 & 0x1f)<=  0x1e)
+                                                       new_txgain_0x56 = txgain_0x56 + 0x1;
+                                               else
+                                                       new_txgain_0x56 = txgain_0x56;
+                                               break;
+*/
+#endif
+       case 0x13:
+       case 0x12:
+               if ((txgain_0x56 & 0x1f) <= 0x1e)
+                       new_txgain_0x56 = txgain_0x56 + 0x1;/*< -0.5 ~ -1.5dB*/
+               else
+                       new_txgain_0x56 = txgain_0x56;
+               break;
+       case 0x11:
+       case 0x10:
+       case 0xf:
+       case 0xe:
+       case 0xd:
+       case 0xc:
+               new_txgain_0x56 = txgain_0x56; /*<  -0.5~0.5dB*/
+               break;
+       case 0xb:
+       case 0xa:
+       case 0x9:
+       case 0x8:
+       case 0x7:
+               if ((txgain_0x56 & 0x1f) >= 0x01)
+                       new_txgain_0x56 = txgain_0x56 - 0x1; /* >0.5~1.5dB */
+               else
+                       new_txgain_0x56 = txgain_0x56;
+               break;
+       case 0x6:
+       case 0x5:
+       case 0x4:
+       case 0x3:
+#if 0
+       /*
+                                               if ((txgain_0x56 & 0x1f)>= 0x02)
+                                                       new_txgain_0x56 = txgain_0x56 - 0x2; //>1.5~2.5dB
+                                               else if ((txgain_0x56 & 0x1f)>= 0x01)
+                                                       new_txgain_0x56 = txgain_0x56 - 0x1;
+                                               else
+                                                       new_txgain_0x56 = txgain_0x56;
+                                               break;
+*/
+#endif
+       case 0x2:
+       case 0x1:
+       case 0x0:
+#if 0
+       /*
+                                               if ((txgain_0x56 & 0x1f)>= 0x03)
+                                                       new_txgain_0x56 = txgain_0x56 - 0x3; //>2.5~3.5dB
+                                               else if ((txgain_0x56 & 0x1f)>= 0x02)
+                                                       new_txgain_0x56 = txgain_0x56 - 0x2;
+                                               else if ((txgain_0x56 & 0x1f)>= 0x01)
+                                                       new_txgain_0x56 = txgain_0x56 - 0x1;
+                                               else
+                                                       new_txgain_0x56 = txgain_0x56;
+                                               break;
+*/
+#endif
+       default:
+               new_txgain_0x56 = txgain_0x56;
+               break;
+       }
+       if ((new_txgain_0x56 & 0x1f) < 0x02)
+               new_txgain_0x56 = (new_txgain_0x56 & 0xffffc) + 0x2;
+       if ((new_txgain_0x56 & 0x1f) > 0x1d)
+               new_txgain_0x56 = (new_txgain_0x56 | 0x3) - 0x2;
+
+       return new_txgain_0x56;
+}
+
+void _txgapk_backup_8821c(struct dm_struct *dm, u32 *backup_txgap,
+                         u32 *backup_txgap_reg, u8 txgapk_reg_num)
+{
+       u32 i;
+
+       for (i = 0; i < txgapk_reg_num; i++)
+               backup_txgap[i] = odm_read_4byte(dm, backup_txgap_reg[i]);
+}
+u32 _txgapk_get_rf_tx_index_8821c(struct dm_struct *dm, u8 path,
+                                 u32 txgain_index)
+{
+       u32 rf_backup_reg00, rf_backup_regdf, rf_reg56;
+
+       rf_backup_reg00 = odm_get_rf_reg(dm, RF_PATH_A, RF_0x00, RFREGOFFSETMASK);
+       rf_backup_regdf = odm_get_rf_reg(dm, RF_PATH_A, RF_0xdf, RFREGOFFSETMASK);
+
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0xdf, RFREGOFFSETMASK, 0x08009);
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0x00, RFREGOFFSETMASK, 0x20000 + txgain_index);
+       /*ODM_sleep_us(10);*/
+
+       ODM_delay_us(10);
+       rf_reg56 = odm_get_rf_reg(dm, RF_PATH_A, RF_0x56, RFREGOFFSETMASK);
+
+       RF_DBG(dm, DBG_RF_IQK,
+              "[TXGAPK](2) txgain_index =0x%x, rf_reg56=0x%x\n", txgain_index,
+              rf_reg56);
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0x00, RFREGOFFSETMASK, rf_backup_reg00);
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0xdf, RFREGOFFSETMASK, rf_backup_regdf);
+       return rf_reg56;
+}
+
+void _txgapk_restore_8821c(struct dm_struct *dm, u32 *backup_txgap,
+                          u32 *backup_txgap_reg, u8 txgapk_reg_num)
+{
+       u32 i;
+
+       for (i = 0; i < txgapk_reg_num; i++)
+               odm_write_4byte(dm, backup_txgap_reg[i], backup_txgap[i]);
+}
+
+void _txgapk_setting_8821c(struct dm_struct *dm, u8 path)
+{
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+
+       /*RF*/
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0xef, RFREGOFFSETMASK, 0x80000);
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0x33, RFREGOFFSETMASK, 0x00024);
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0x3e, RFREGOFFSETMASK, 0x0003F);
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0x3f, RFREGOFFSETMASK, 0xCBFCE);
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0xef, RFREGOFFSETMASK, 0x00000);
+       if (iqk_info->is_btg) {
+       } else {
+               switch (*dm->band_type) {
+               case ODM_BAND_2_4G:
+                       break;
+               case ODM_BAND_5G:
+                       odm_set_rf_reg(dm, RF_PATH_A, RF_0x8f, RFREGOFFSETMASK, 0xA9C00);
+                       odm_set_rf_reg(dm, RF_PATH_A, RF_0xdf, RFREGOFFSETMASK, 0x00809);
+                       odm_set_rf_reg(dm, RF_PATH_A, RF_0x00, RFREGOFFSETMASK, 0x4001c);
+
+                       odm_write_4byte(dm, 0x1bcc, 0x00000009); /*try the iqk swing*/
+                       odm_write_4byte(dm, 0x1b20, 0x01040008);
+                       odm_write_4byte(dm, 0x1b24, 0x01040848);
+
+                       odm_write_4byte(dm, 0x1b14, 0x00001000);
+                       odm_write_4byte(dm, 0x1b1c, 0x82193d31);
+
+                       odm_write_1byte(dm, 0x1b22, 0x04); /*sync with RF0x33[3:0]*/
+                       odm_write_1byte(dm, 0x1b26, 0x04); /*sync with RF0x33[3:0]*/
+                       odm_write_1byte(dm, 0x1b2c, 0x03);
+                       odm_write_4byte(dm, 0x1b38, 0x20000000);
+                       odm_write_4byte(dm, 0x1b3c, 0x20000000);
+                       odm_write_4byte(dm, 0xc00, 0x4);
+
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[IQK](1) txgap calibration setting!!!\n");
+
+                       break;
+               }
+       }
+}
+
+u32 _txgapk_one_shot_8821c(struct dm_struct *dm_void, u8 path, u32 reg0x56)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       boolean txgap_k_notready = true;
+       u8 delay_count = 0x0;
+       u32 txgap_k_tmp1 = 0x1, txgap_k_tmp2 = 0x2;
+       u8 offset;
+       u32 reg_1bb8;
+       u32 rx_dsp_power;
+
+       reg_1bb8 = odm_read_4byte(dm, 0x1bb8);
+       /*clear the flag*/
+       odm_write_1byte(dm, 0x1bd6, 0x0b);
+       odm_set_bb_reg(dm, R_0x1bfc, BIT(1), 0x0);
+       txgap_k_notready = true;
+       delay_count = 0x0;
+       /* get tx gain*/
+       odm_write_1byte(dm, 0x1b2b, 0x00);
+       odm_write_1byte(dm, 0x1bb8, 0x00);
+       odm_set_rf_reg(dm, path, RF_0xdf, RFREGOFFSETMASK, 0x00802);
+       odm_set_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK, 0xa9c00);
+       odm_set_rf_reg(dm, path, RF_0x56, RFREGOFFSETMASK, reg0x56);
+       odm_write_4byte(dm, 0x1bb8, 0x00100000);
+#if 0
+       /*ODM_sleep_us(10);*/
+#endif
+
+       ODM_delay_us(10);
+       /* one-shot-1*/
+       odm_write_4byte(dm, 0x1b34, 0x1);
+       odm_write_4byte(dm, 0x1b34, 0x0);
+
+#if 1
+       while (txgap_k_notready) {
+               odm_write_1byte(dm, 0x1bd6, 0x0b);
+               if ((boolean)odm_get_bb_reg(dm, R_0x1bfc, BIT(1)))
+                       txgap_k_notready = false;
+               else
+                       txgap_k_notready = true;
+
+               if (txgap_k_notready) {
+#if 0
+                       /*ODM_sleep_us(100);*/
+#endif
+                       ODM_delay_us(100);
+                       delay_count++;
+               }
+
+               if (delay_count >= 20) {
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[TXGAPK] (3)txgapktimeout,delay_count=0x%x !!!\n",
+                              delay_count);
+                       txgap_k_notready = false;
+                       break;
+               }
+       }
+#else
+       ODM_sleep_ms(1);
+       if ((boolean)odm_get_bb_reg(dm, R_0x1bfc, BIT(1)))
+               txgap_k_notready = false;
+       else
+               txgap_k_notready = true;
+
+#endif
+
+       if (!txgap_k_notready) {
+               odm_write_1byte(dm, 0x1bd6, 0x5);
+               txgap_k_tmp1 = odm_read_4byte(dm, 0x1bfc) >> 27;
+               odm_write_1byte(dm, 0x1bd6, 0xe);
+               txgap_k_tmp2 = odm_read_4byte(dm, 0x1bfc);
+
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[TXGAPK] reg0x56 =0x%x, txgapK_tmp1 =0x%x, txgapK_tmp2 =0x%x!!!\n",
+                      reg0x56, txgap_k_tmp1, txgap_k_tmp2);
+
+               if (txgap_k_tmp1 == 0)
+                       offset = 0x0;
+               else if (txgap_k_tmp1 < 2)
+                       offset = 0x1;
+               else if (txgap_k_tmp1 < 4)
+                       offset = 0x2;
+               else
+                       offset = 0x3;
+
+               if (txgap_k_tmp1 == 0x0) {
+                       rx_dsp_power = txgap_k_tmp2;
+               } else {
+                       txgap_k_tmp1 = txgap_k_tmp1 << (32 - offset);
+                       txgap_k_tmp2 = txgap_k_tmp2 >> offset;
+                       rx_dsp_power = txgap_k_tmp1 + txgap_k_tmp2;
+                       overflowflag = true;
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[TXGAPK](3) (1)overflowflag = true, txgapK_tmp1 =0x%x, txgapK_tmp2 =0x%x!!!\n",
+                              txgap_k_tmp1, txgap_k_tmp2);
+               }
+       } else {
+               RF_DBG(dm, DBG_RF_IQK, "[TXGAPK](3) txgapK Fail!!!\n");
+       }
+
+       odm_write_4byte(dm, 0x1bb8, reg_1bb8);
+
+       return rx_dsp_power;
+}
+
+void _phy_txgapk_calibrate_8821c(void *dm_void, u8 path)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       u32 txgain[txgap_k_number] = {0, 0, 0, 0, 0, 0, 0};
+       u32 txgain_rf56[txgap_k_number] = {0, 0, 0, 0, 0, 0, 0};
+       u8 add_base, txgapk_num = 0x0, psd_delta = 0x0;
+       u8 i, bandselect = 0x0;
+       u32 backup_txgap_reg[11] = {0x1b14, 0x1b1c, 0x1b20, 0x1b24, 0x1b28, 0x1b2c, 0x1b38, 0x1b3c, 0x1bd6, 0x1bb8, 0x1bcc};
+       u32 backup_txgap[11];
+       u8 gain_gap_index[txgap_k_number] = {0x13, 0x10, 0xd, 0xa, 0x7, 0x4, 0x1};
+       u32 txgainindex[txgap_k_number] = {0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20};
+       u32 tmp1, tmp2, tmp3, tmp4, tmp5;
+       u8 skip_low_power_index = 0x3;
+
+       s8 psd_single_tone_offset_1db[3][3] = {{-1, 0, 0}, {-2, -1, -1}, {-1, -1, -1} }; /*5G, L,M,H, index 32,26,20*/
+       static u32 pwr_table_1db[27] = {590, 630, 668, 707, 749, 794, 841, 891, 944, 1000, 1040, 1096, 1148, 1202, 1258, 1318,
+                                       1380, 1412, 1513, 1584, 1678, 1778, 1888, 1995, 2113, 2387, 2391};
+       static u32 pwr_table_3db[27] = {944, 1000, 1059, 1122, 1185, 1258, 1333, 1412, 1496, 1584, 1659, 1737, 1819, 1905, 1995, 2089,
+                                       2187, 2290, 2398, 2511, 2660, 2818, 2985, 3162, 3349, 3548, 3758};
+       boolean txgapkdone = false;
+       u8 txgap_changed = 0x0;
+       u8 ref_val = 0x0;
+
+       overflowflag = 0;
+       RF_DBG(dm, DBG_RF_IQK,
+              "[TXGAPK] (1) *dm->band_width = %x, *dm->channel =%d, *dm->band_type=%x\n",
+              *dm->band_width, *dm->channel, *dm->band_type);
+
+       if (!(*dm->mp_mode))
+               return;
+
+       if (!(*dm->band_type == ODM_BAND_5G))
+               return;
+
+       if (*dm->band_width == 0) {
+#if 0
+               /*              return;*/
+#endif
+               if (*dm->channel < 64) {
+                       bandselect = 0x0;
+                       add_base = 0x0;
+               } else if (*dm->channel < 153) {
+                       bandselect = 0x1;
+                       add_base = 0x40;
+#if 0
+               /*else if (*dm->channel ==153){*/
+#endif
+               } else {
+                       bandselect = 0x2;
+                       add_base = 0x80;
+               }
+       } else if (*dm->band_width == 1) {
+               if (*dm->channel < 102) {
+                       bandselect = 0x0;
+                       add_base = 0x0;
+               } else if (*dm->channel < 151) {
+                       bandselect = 0x1;
+                       add_base = 0x40;
+#if 0
+               /*else if (*dm->channel ==151){*/
+#endif
+               } else {
+                       bandselect = 0x2;
+                       add_base = 0x80;
+               }
+       } else if (*dm->band_width == 2) {
+               /*              return;*/
+               if (*dm->channel < 106) {
+                       bandselect = 0x0;
+                       add_base = 0x0;
+               } else if (*dm->channel < 155) {
+                       bandselect = 0x1;
+                       add_base = 0x40;
+#if 0
+               /*else if (*dm->channel ==155){*/
+#endif
+               } else {
+                       bandselect = 0x2;
+                       add_base = 0x80;
+               }
+       } else {
+               return;
+       }
+
+       if (txgap_done[bandselect])
+               return;
+
+       /*Step 1*/
+       _txgapk_backup_8821c(dm, backup_txgap, backup_txgap_reg, 0xb);
+       /*step 2*/
+       phydm_clear_kfree_to_rf(dm, RF_PATH_A, 1);
+
+       for (i = 0; i < txgap_k_number; i++) {
+               txgain_rf56[i] = _txgapk_get_rf_tx_index_8821c(dm, RF_PATH_A, gain_gap_index[i]);
+               txgain[i] = txgain_rf56[i];
+       }
+
+       for (i = 0; i < txgap_k_number; i++) {
+               RF_DBG(dm, DBG_RF_IQK, "[TXGAPK] start txgain1[%x]=0x%x\n", i,
+                      txgain_rf56[i]);
+       }
+
+       _txgapk_setting_8821c(dm, RF_PATH_A);
+
+       /*step 3*/
+
+       /*1st*/
+       while (!txgapkdone) {
+               txgapk_num++;
+               if (txgapk_num > 2)
+                       break;
+
+               for (i = 0; i < txgap_k_number - 1 - skip_low_power_index; i++) {
+                       tmp1 = (txgain[i] & 0x000000e0) >> 5;
+                       tmp2 = (txgain[i + 1] & 0x000000e0) >> 5;
+                       tmp5 = txgain[i + 1];
+#if 0
+                       //if (tmp1 != tmp2){
+#endif
+                       if (true) {
+                               tmp3 = _txgapk_one_shot_8821c(dm, RF_PATH_A, txgain[i] - 2);
+                               tmp4 = _txgapk_one_shot_8821c(dm, RF_PATH_A, txgain[i + 1]);
+                               if (overflowflag)
+                                       overflowflag = false;
+#if 0
+                                       //tmp4 = tmp4>>1;
+#endif
+
+                               psd_delta =
+                                       _txgapk_txpower_compare_8821c(dm, RF_PATH_A, tmp3, tmp4, pwr_table_1db);
+
+                               psd_delta = psd_delta + psd_single_tone_offset_1db[bandselect][i];
+                               RF_DBG(dm, DBG_RF_IQK,
+                                      "[TXGAPK] new psd_detla = %x\n",
+                                      psd_delta);
+
+                               if (psd_delta <= 0xb)
+                                       txgap_changed++;
+                               else if (psd_delta <= 0x11)
+                                       ;
+                               else
+                                       txgap_changed++;
+
+                               txgain[i + 1] =
+                                       _txgapk_txgap_compenstion_8821c(dm, RF_PATH_A, txgain[i + 1], psd_delta);
+                       } else {
+                               RF_DBG(dm, DBG_RF_IQK,
+                                      "[TXGAPK]skip i=%d, txgain[%x]=0x%x\n",
+                                      i, i + 1, txgain[i + 1]);
+                       }
+               }
+
+               /*2nd*/
+
+               if (txgap_changed > 0x0) {
+                       RF_DBG(dm, DBG_RF_IQK, "[TXGAPK] do 3dB check\n");
+
+                       for (i = 0; i < txgap_k_number - 1 - skip_low_power_index; i++) {
+                               tmp1 = (txgain[i] & 0x000000e0) >> 5;
+                               tmp2 = (txgain[i + 1] & 0x000000e0) >> 5;
+
+                               if (tmp1 != tmp2) {
+                                       if (i == 0)
+                                               tmp3 = _txgapk_one_shot_8821c(dm, RF_PATH_A, txgain[i] - 2);
+                                       else
+                                               tmp3 = _txgapk_one_shot_8821c(dm, RF_PATH_A, txgain[i]);
+
+                                       tmp4 = _txgapk_one_shot_8821c(dm, RF_PATH_A, txgain[i + 1]);
+
+                                       if (overflowflag) {
+                                               overflowflag = false;
+                                               RF_DBG(dm, DBG_RF_IQK, "[IQK] tmp3= %x, tmp4= %x\n", tmp3, tmp4);
+                                       }
+                                       if (i == 0)
+                                               psd_delta =
+                                                       _txgapk_txpower_compare_8821c(dm, RF_PATH_A, tmp3, tmp4, pwr_table_1db);
+
+                                       else
+                                               psd_delta =
+                                                       _txgapk_txpower_compare_8821c(dm, RF_PATH_A, tmp3, tmp4, pwr_table_3db);
+
+                                       if (psd_delta <= 0xa)
+                                               ref_val++;
+                                       else if (psd_delta <= 0x12)
+                                               ;
+                                       else
+                                               ref_val++;
+                               } else {
+                                       RF_DBG(dm, DBG_RF_IQK, "[TXGAPK]skip i=%d, txgain[%x]=0x%x\n", i, i + 1, txgain[i + 1]);
+                               }
+                       }
+
+                       if (ref_val == 0x0) {
+                               txgapkdone = true;
+                               txgap_changed = 0x0;
+                       } else {
+                               /* restore default rf 0x56 */
+                               for (i = 0; i < txgap_k_number; i++)
+                                       txgain[i] = txgain_rf56[i];
+                       }
+
+               } else {
+                       txgapkdone = true;
+               }
+       }
+
+       /*step 7*/
+       _txgapk_restore_8821c(dm, backup_txgap, backup_txgap_reg, 0xb);
+
+       /*step 8*/
+       RF_DBG(dm, DBG_RF_IQK,
+              "[TXGAPK]txgapkdone =%x, txgap_changed=0x%x, ref_val =0x%x\n",
+              txgapkdone, txgap_changed, ref_val);
+
+       if (txgapkdone) {
+               odm_set_rf_reg(dm, RF_PATH_A, RF_0xef, RFREGOFFSETMASK, 0x00800);
+
+               for (i = 0; i < txgap_k_number; i++) {
+                       odm_set_rf_reg(dm, RF_PATH_A, RF_0x33, RFREGOFFSETMASK, txgainindex[i] + add_base);
+                       odm_set_rf_reg(dm, RF_PATH_A, RF_0x3f, RFREGOFFSETMASK, txgain[i]);
+               }
+               odm_set_rf_reg(dm, RF_PATH_A, RF_0xef, RFREGOFFSETMASK, 0x00000);
+               txgap_done[bandselect] = true;
+               txgapkdone = false;
+       }
+}
+
+#if 0
+/*
+void
+_DPK_BackupReg_8821C(
+       struct dm_struct*       dm,
+       static u32*     DPK_backup,
+       u32*            backup_dpk_reg
+       )
+{
+
+       u32 i;
+
+       for (i = 0; i < DPK_BACKUP_REG_NUM_8821C; i++)
+               DPK_backup[i] = odm_read_4byte(dm, backup_dpk_reg[i]);
+
+}
+void
+_DPK_Restore_8821C(
+       struct dm_struct*               dm,
+       static  u32*            DPK_backup,
+       u32*            backup_dpk_reg
+       )
+{
+       u32 i;
+       for (i = 0; i < DPK_BACKUP_REG_NUM_8821C; i++)
+               odm_write_4byte(dm, backup_dpk_reg[i], DPK_backup[i]);
+}
+
+*/
+#endif
+void _dpk_toggle_rxagc(struct dm_struct *dm, boolean reset)
+{
+       /*toggle RXAGC  workaround method*/
+       u32 tmp1;
+       tmp1 = odm_read_4byte(dm, 0xc50);
+       odm_set_bb_reg(dm, R_0xc50, BIT(3) | BIT(2) | BIT(1) | BIT(0), 0x0);
+#if 0
+       /*       ODM_sleep_ms(2);*/
+#endif
+       ODM_delay_ms(2);
+       odm_set_bb_reg(dm, R_0xc50, BIT(3) | BIT(2) | BIT(1) | BIT(0), 0x2);
+#if 0
+       /*       ODM_sleep_ms(2);*/
+#endif
+       ODM_delay_ms(2);
+       odm_set_bb_reg(dm, R_0xc50, BIT(3) | BIT(2) | BIT(1) | BIT(0), 0x0);
+       odm_write_4byte(dm, 0xc50, tmp1);
+}
+
+void _dpk_set_gain_scaling(struct dm_struct *dm, u8 path)
+{
+       u32 tmp1, tmp2, tmp3, tmp4, reg_1bfc;
+       u32 lut_i = 0x0, lut_q = 0x0, lut_pw = 0x0, lut_pw_avg = 0x0;
+       u16 gain_scaling = 0x0;
+
+       tmp1 = odm_read_4byte(dm, 0x1b00);
+       tmp2 = odm_read_4byte(dm, 0x1b08);
+       tmp3 = odm_read_4byte(dm, 0x1bd4);
+       tmp4 = odm_read_4byte(dm, 0x1bdc);
+
+       odm_write_4byte(dm, 0x1b00, 0xf8000008);
+       odm_write_4byte(dm, 0x1b08, 0x00000080);
+       odm_write_4byte(dm, 0x1bd4, 0x00040001);
+       odm_write_4byte(dm, 0x1bdc, 0xc0000081);
+
+       reg_1bfc = odm_read_4byte(dm, 0x1bfc);
+       lut_i = (reg_1bfc & 0x003ff800) >> 11;
+       lut_q = (reg_1bfc & 0x00007ff);
+
+       if ((lut_i & 0x400) == 0x400)
+               lut_i = 0x800 - lut_i;
+       if ((lut_q & 0x400) == 0x400)
+               lut_q = 0x800 - lut_q;
+
+       lut_pw = lut_i * lut_i + lut_q * lut_q;
+       lut_pw_avg = (u32)(lut_i + lut_q) >> 1;
+       gain_scaling = (u16)(0x800000 / lut_pw_avg);
+
+       odm_set_bb_reg(dm, R_0x1b98, 0x0000ffff, gain_scaling);
+       odm_set_bb_reg(dm, R_0x1b98, 0xffff0000, gain_scaling);
+
+       odm_write_4byte(dm, 0x1b00, tmp1);
+       odm_write_4byte(dm, 0x1b08, tmp2);
+       odm_write_4byte(dm, 0x1bd4, tmp3);
+       odm_write_4byte(dm, 0x1bdc, tmp4);
+
+       RF_DBG(dm, DBG_RF_IQK,
+              "[IQK] reg_1bfc =0x%x, lut_pw =0x%x, lut_i = 0x%x, lut_q = 0x%x, lut_pw_avg = 0x%x, gain_scaling = 0x%x, 0x1b98 =0x%x!!!\n",
+              reg_1bfc, lut_pw, lut_i, lut_q, lut_pw_avg, gain_scaling,
+              odm_read_4byte(dm, 0x1b98));
+}
+
+void _dpk_set_dpk_pa_scan(struct dm_struct *dm, u8 path)
+{
+       u32 tmp1, tmp2, reg_1bfc;
+       u32 pa_scan_i = 0x0, pa_scan_q = 0x0, pa_scan_pw = 0x0;
+       u32 gainloss_back = 0x0;
+#if 0
+       /*      boolean pa_scan_search_fail = false;*/
+#endif
+       tmp1 = odm_read_4byte(dm, 0x1bcf);
+       tmp2 = odm_read_4byte(dm, 0x1bd4);
+
+       odm_write_4byte(dm, 0x1bcf, 0x11);
+       odm_write_4byte(dm, 0x1bd4, 0x00060000);
+
+       reg_1bfc = odm_read_4byte(dm, 0x1bfc);
+       odm_write_4byte(dm, 0x1bcf, 0x15);
+       pa_scan_i = (reg_1bfc & 0xffff0000) >> 16;
+       pa_scan_q = (reg_1bfc & 0x0000ffff);
+
+       if ((pa_scan_i & 0x8000) == 0x8000)
+               pa_scan_i = 0x10000 - pa_scan_i;
+       if ((pa_scan_q & 0x8000) == 0x8000)
+               pa_scan_q = 0x10000 - pa_scan_q;
+
+       pa_scan_pw = pa_scan_i * pa_scan_i + pa_scan_q * pa_scan_q;
+
+       /*estimated pa_scan_pw*/
+#if 0
+       /*0dB => (512^2) * 10^(0/10) = 262144*/
+       /*1dB => (512^2) * 10^(1/10) = 330019*/
+       /*2dB => (512^2) * 10^(2/10) = 415470*/
+       /*3dB => (512^2) * 10^(3/10) = 523046*/
+       /*4dB => (512^2) * 10^(4/10) = 658475*/
+       /*5dB => (512^2) * 10^(5/10) = 828972*/
+       /*6dB => (512^2) * 10^(6/10) = 1043614*/
+       /*7dB => (512^2) * 10^(7/10) = 1313832*/
+       /*8dB => (512^2) * 10^(0/10) = 1654016*/
+       /*9dB => (512^2) * 10^(1/10) = 2082283*/
+       /*10dB => (512^2) * 10^(2/10) = 2621440*/
+       /*11dB => (512^2) * 10^(3/10) = 3300197*/
+       /*12dB => (512^2) * 10^(4/10) = 4154702*/
+       /*13dB => (512^2) * 10^(5/10) = 5230460*/
+       /*14dB => (512^2) * 10^(6/10) = 6584759*/
+       /*15dB => (512^2) * 10^(7/10) = 8289721*/
+#endif
+       if (pa_scan_pw >= 0x7e7db9)
+               pa_scan_pw = 0x0f;
+       else if (pa_scan_pw >= 0x6479b7)
+               pa_scan_pw = 0x0e;
+       else if (pa_scan_pw >= 0x4fcf7c)
+               pa_scan_pw = 0x0d;
+       else if (pa_scan_pw >= 0x3f654e)
+               pa_scan_pw = 0x0c;
+       else if (pa_scan_pw >= 0x325b65)
+               pa_scan_pw = 0x0b;
+       else if (pa_scan_pw >= 0x280000)
+               pa_scan_pw = 0x0a;
+       else if (pa_scan_pw >= 0x1fc5eb)
+               pa_scan_pw = 0x09;
+       else if (pa_scan_pw >= 0x193d00)
+               pa_scan_pw = 0x8;
+       else if (pa_scan_pw >= 0x140c28)
+               pa_scan_pw = 0x7;
+       else if (pa_scan_pw >= 0xefc9e)
+               pa_scan_pw = 0x6;
+       else if (pa_scan_pw >= 0xca62c)
+               pa_scan_pw = 0x5;
+       else if (pa_scan_pw > 0xa0c2b)
+               pa_scan_pw = 0x4;
+       else if (pa_scan_pw > 0x7fb26)
+               pa_scan_pw = 0x3;
+       else if (pa_scan_pw > 0x656ee)
+               pa_scan_pw = 0x2;
+       else if (pa_scan_pw > 0x50923)
+               pa_scan_pw = 0x1;
+       else /*262144 >= pa_scan_pw*/
+               pa_scan_pw = 0x0;
+
+       odm_write_4byte(dm, 0x1bd4, 0x00060001);
+       gainloss_back = (odm_read_4byte(dm, 0x1bfc) & 0x0000000f);
+
+       if (gainloss_back <= 0xa)
+               gainloss_back = 0xa - gainloss_back;
+
+       if (gainloss_back > pa_scan_pw + 0x8)
+               odm_set_rf_reg(dm, path, RF_0x8f, BIT(14) | BIT(13), 0x11);
+       else if ((pa_scan_pw + 0x8 - gainloss_back) >= 0x6)
+               odm_set_rf_reg(dm, path, RF_0x8f, BIT(14) | BIT(13), 0x00);
+       else
+#if 0
+               /*if (0x6 >= (pa_scan_pw + 0x8 - gainloss_back)> 0x0 )*/
+#endif
+               odm_set_rf_reg(dm, path, RF_0x8f, BIT(14) | BIT(13), 0x01);
+
+       RF_DBG(dm, DBG_RF_IQK,
+              "[IQK] reg_1bfc =0x%x, pa_scan_pw =0x%x, gainloss_back = 0x%x, pa_scan_i = 0x%x, pa_scan_q = 0x%x, RF0x8f = 0x%x, !!!\n",
+              reg_1bfc, pa_scan_pw, gainloss_back, pa_scan_i, pa_scan_q,
+              odm_get_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK));
+
+       odm_write_4byte(dm, 0x1bcf, tmp1);
+       odm_write_4byte(dm, 0x1bd4, tmp2);
+}
+
+void _dpk_disable_bb_dynamic_pwr_threshold(struct dm_struct *dm, boolean flag)
+{
+       if (flag) /*disable BB dynamic pwr threshold hold*/
+               odm_set_bb_reg(dm, R_0x1c74, BIT(31) | BIT(30) | BIT(29) | BIT(28), 0x0);
+       else
+               odm_set_bb_reg(dm, R_0x1c74, BIT(31) | BIT(30) | BIT(29) | BIT(28), 0x2);
+       RF_DBG(dm, DBG_RF_IQK, "[DPK]\nset 0x1c74 = 0x%x\n",
+              odm_read_4byte(dm, 0x1c74));
+}
+
+void _dpk_set_dpk_sram_to_10_8821c(struct dm_struct *dm, u8 path)
+{
+       u32 tmp1, tmp2;
+       u8 i;
+       tmp1 = odm_read_4byte(dm, 0x1b00);
+       tmp2 = odm_read_4byte(dm, 0x1b08);
+
+       for (i = 0; i < 64; i++)
+               odm_write_4byte(dm, 0x1bdc, 0xd0000001 + (i * 2) + 1);
+
+       for (i = 0; i < 64; i++)
+               odm_write_4byte(dm, 0x1bdc, 0x90000080 + (i * 2) + 1);
+
+#if 0
+       /*
+       RF_DBG(dm, DBG_RF_IQK,
+               "[DPK]return  txagc = 0x%x , 1bfc = 0x%x,rf00=0x%x\n",
+               tmp4, odm_read_4byte(dm, 0x1bfc),
+               odm_get_rf_reg(dm, path, RF_0x00, RFREGOFFSETMASK));
+*/
+#endif
+       odm_write_4byte(dm, 0x1bdc, 0x0);
+       odm_write_4byte(dm, 0x1b00, tmp1);
+       odm_write_4byte(dm, 0x1b08, tmp2);
+}
+
+void _dpk_set_bbtxagc_8821c(struct dm_struct *dm, u8 path)
+{
+       u8 hw_rate, tmp;
+
+       for (hw_rate = 0; hw_rate < 0x53; hw_rate++) {
+               phydm_write_txagc_1byte_8821c(dm, 0x30, (enum rf_path)0x0, hw_rate);
+
+               tmp = config_phydm_read_txagc_8821c(dm, (enum rf_path)0x0, hw_rate);
+#if 0
+               /*
+         RF_DBG(dm, DBG_RF_IQK,
+                 "hw_rate =0x%x, tmp =0x%x \n", hw_rate, tmp);
+*/
+#endif
+       }
+}
+
+u8 _dpk_get_txagcindpk_8821c(struct dm_struct *dm, u8 path)
+{
+       u32 tmp1, tmp2, tmp3;
+       u8 tmp4;
+       tmp1 = odm_read_4byte(dm, 0x1bcc);
+       odm_set_bb_reg(dm, R_0x1bcc, BIT(26), 0x01);
+       tmp2 = odm_read_4byte(dm, 0x1bd4);
+       odm_set_bb_reg(dm, R_0x1bd4, BIT(20) | BIT(19) | BIT(18) | BIT(17) | BIT(16), 0x0a);
+       tmp3 = odm_read_4byte(dm, 0x1bfc);
+       tmp4 = ((u8)odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)) >> 2;
+#if 0
+       /*
+       RF_DBG(dm, DBG_RF_IQK,
+               "[DPK]return  txagc = 0x%x , 1bfc = 0x%x,rf00=0x%x\n",
+               tmp4, odm_read_4byte(dm, 0x1bfc),
+               odm_get_rf_reg(dm, path, RF_0x00, RFREGOFFSETMASK));
+*/
+#endif
+       odm_write_4byte(dm, 0x1bcc, tmp1);
+       odm_write_4byte(dm, 0x1bd4, tmp2);
+
+       return tmp4;
+}
+
+void _dpk_ampmcurce_8821c(struct dm_struct *dm, u8 path)
+{
+       u8 i;
+       RF_DBG(dm, DBG_RF_IQK, "[DPK] 0x1bcc = 0x%x, 0x1bb8 =0x%x\n",
+              odm_read_4byte(dm, 0x1bcc), odm_read_4byte(dm, 0x1bb8));
+
+       odm_write_4byte(dm, 0x1bcc, 0x118f8800);
+       for (i = 0; i < 8; i++) {
+               odm_write_4byte(dm, 0x1b90, 0x0101e018 + i);
+               odm_write_4byte(dm, 0x1bd4, 0x00060000);
+               RF_DBG(dm, DBG_RF_IQK, "0x%x\n", odm_read_4byte(dm, 0x1bfc));
+               odm_write_4byte(dm, 0x1bd4, 0x00070000);
+               RF_DBG(dm, DBG_RF_IQK, "0x%x\n", odm_read_4byte(dm, 0x1bfc));
+               odm_write_4byte(dm, 0x1bd4, 0x00080000);
+               RF_DBG(dm, DBG_RF_IQK, "0x%x\n", odm_read_4byte(dm, 0x1bfc));
+               odm_write_4byte(dm, 0x1bd4, 0x00090000);
+               RF_DBG(dm, DBG_RF_IQK, "0x%x\n", odm_read_4byte(dm, 0x1bfc));
+       }
+
+       odm_write_4byte(dm, 0x1b90, 0x0001e018);
+}
+void _dpk_readsram_8821c(struct dm_struct *dm, u8 path)
+{
+       /* dbg message*/
+       u8 i;
+       odm_write_4byte(dm, 0x1b00, 0xf8000008);
+       odm_write_4byte(dm, 0x1b08, 0x00000080);
+       odm_write_4byte(dm, 0x1bd4, 0x00040001);
+
+       RF_DBG(dm, DBG_RF_IQK, "[DPK] SRAM value!!!\n");
+
+       for (i = 0; i < 64; i++) {
+#if 0
+               /*odm_write_4byte(dm, 0x1b90, 0x0101e018+i);*/
+#endif
+               odm_write_4byte(dm, 0x1bdc, 0xc0000081 + i * 2);
+
+               RF_DBG(dm, DBG_RF_IQK, "0x%x\n", odm_read_4byte(dm, 0x1bfc));
+       }
+       odm_write_4byte(dm, 0x1bd4, 0x00050001);
+       for (i = 0; i < 64; i++) {
+#if 0
+               /*odm_write_4byte(dm, 0x1b90, 0x0101e018+i);*/
+#endif
+               odm_write_4byte(dm, 0x1bdc, 0xc0000081 + i * 2);
+
+               RF_DBG(dm, DBG_RF_IQK, "0x%x\n", odm_read_4byte(dm, 0x1bfc));
+       }
+#if 0
+       /*ODM_sleep_ms(200);*/
+#endif
+       ODM_delay_ms(200);
+#if 0
+       /*odm_write_4byte(dm, 0x1b08, 0x00000080);*/
+#endif
+       odm_write_4byte(dm, 0x1bd4, 0xA0001);
+       odm_write_4byte(dm, 0x1bdc, 0x00000000);
+}
+
+void _dpk_restore_8821c(struct dm_struct *dm, u8 path)
+{
+       odm_write_4byte(dm, 0xc60, 0x700B8040);
+       odm_write_4byte(dm, 0xc60, 0x700B8040);
+       odm_write_4byte(dm, 0xc60, 0x70146040);
+       odm_write_4byte(dm, 0xc60, 0x70246040);
+       odm_write_4byte(dm, 0xc60, 0x70346040);
+       odm_write_4byte(dm, 0xc60, 0x70446040);
+       odm_write_4byte(dm, 0xc60, 0x705B2040);
+       odm_write_4byte(dm, 0xc60, 0x70646040);
+       odm_write_4byte(dm, 0xc60, 0x707B8040);
+       odm_write_4byte(dm, 0xc60, 0x708B8040);
+       odm_write_4byte(dm, 0xc60, 0x709B8040);
+       odm_write_4byte(dm, 0xc60, 0x70aB8040);
+       odm_write_4byte(dm, 0xc60, 0x70bB6040);
+       odm_write_4byte(dm, 0xc60, 0x70c06040);
+       odm_write_4byte(dm, 0xc60, 0x70d06040);
+       odm_write_4byte(dm, 0xc60, 0x70eF6040);
+       odm_write_4byte(dm, 0xc60, 0x70f06040);
+
+       odm_write_4byte(dm, 0xc58, 0xd8020402);
+       odm_write_4byte(dm, 0xc5c, 0xde000120);
+       odm_write_4byte(dm, 0xc6c, 0x0000122a);
+
+       odm_write_4byte(dm, 0x808, 0x24028211);
+#if 0
+       /*odm_write_4byte(dm, 0x810, 0x211042A5);*/
+#endif
+       odm_write_4byte(dm, 0x90c, 0x13000000);
+       odm_write_4byte(dm, 0x9a4, 0x80000088);
+       odm_write_4byte(dm, 0xc94, 0x01000101);
+       odm_write_4byte(dm, 0x1904, 0x00238000);
+       odm_write_4byte(dm, 0x1904, 0x00228000);
+       odm_write_4byte(dm, 0xC00, 0x00000007);
+}
+
+void _dpk_clear_sram_8821c(struct dm_struct *dm, u8 path)
+{
+       u8 i;
+
+       /* write pwsf*/
+       /*S3*/
+       odm_write_4byte(dm, 0x1bdc, 0x40caffe1);
+       odm_write_4byte(dm, 0x1bdc, 0x4080a1e3);
+       odm_write_4byte(dm, 0x1bdc, 0x405165e5);
+       odm_write_4byte(dm, 0x1bdc, 0x403340e7);
+       odm_write_4byte(dm, 0x1bdc, 0x402028e9);
+       odm_write_4byte(dm, 0x1bdc, 0x401419eb);
+       odm_write_4byte(dm, 0x1bdc, 0x400d10ed);
+       odm_write_4byte(dm, 0x1bdc, 0x40080aef);
+
+       odm_write_4byte(dm, 0x1bdc, 0x400506f1);
+       odm_write_4byte(dm, 0x1bdc, 0x400304f3);
+       odm_write_4byte(dm, 0x1bdc, 0x400203f5);
+       odm_write_4byte(dm, 0x1bdc, 0x400102f7);
+       odm_write_4byte(dm, 0x1bdc, 0x400101f9);
+       odm_write_4byte(dm, 0x1bdc, 0x400101fb);
+       odm_write_4byte(dm, 0x1bdc, 0x400101fd);
+       odm_write_4byte(dm, 0x1bdc, 0x400101ff);
+       /*S0*/
+       odm_write_4byte(dm, 0x1bdc, 0x40caff81);
+       odm_write_4byte(dm, 0x1bdc, 0x4080a183);
+       odm_write_4byte(dm, 0x1bdc, 0x40516585);
+       odm_write_4byte(dm, 0x1bdc, 0x40334087);
+       odm_write_4byte(dm, 0x1bdc, 0x40202889);
+       odm_write_4byte(dm, 0x1bdc, 0x4014198b);
+       odm_write_4byte(dm, 0x1bdc, 0x400d108d);
+       odm_write_4byte(dm, 0x1bdc, 0x40080a8f);
+       odm_write_4byte(dm, 0x1bdc, 0x40050691);
+       odm_write_4byte(dm, 0x1bdc, 0x40030493);
+       odm_write_4byte(dm, 0x1bdc, 0x40020395);
+       odm_write_4byte(dm, 0x1bdc, 0x40010297);
+       odm_write_4byte(dm, 0x1bdc, 0x40010199);
+       odm_write_4byte(dm, 0x1bdc, 0x4001019b);
+       odm_write_4byte(dm, 0x1bdc, 0x4001019d);
+       odm_write_4byte(dm, 0x1bdc, 0x4001019f);
+
+       odm_write_4byte(dm, 0x1bdc, 0x00000000);
+
+       /*clear sram even*/
+       for (i = 0; i < 0x40; i++)
+               odm_write_4byte(dm, 0x1bdc, 0xd0000000 + ((i * 2) + 1));
+       /*clear sram odd*/
+       for (i = 0; i < 0x40; i++)
+               odm_write_4byte(dm, 0x1bdc, 0x90000080 + ((i * 2) + 1));
+
+       odm_write_4byte(dm, 0x1bdc, 0x0);
+       RF_DBG(dm, DBG_RF_IQK, "[DPK]==========write pwsf and clear sram/n");
+}
+
+void _dpk_setting_8821c(struct dm_struct *dm, u8 path)
+{
+       RF_DBG(dm, DBG_RF_IQK,
+              "[DPK]==========Start the DPD setting Initilaize/n");
+       /*AFE setting*/
+       odm_write_4byte(dm, 0xc60, 0x50000000);
+       odm_write_4byte(dm, 0xc60, 0x700F0040);
+       odm_write_4byte(dm, 0xc5c, 0xd1000120);
+       odm_write_4byte(dm, 0xc58, 0xd8000402);
+       odm_write_4byte(dm, 0xc6c, 0x00000a15);
+       odm_write_4byte(dm, 0xc00, 0x00000004);
+#if 0
+       /*_iqk_bb_reset_8821c(dm);*/
+#endif
+       odm_write_4byte(dm, 0xe5c, 0xD1000120);
+       odm_write_4byte(dm, 0xc6c, 0x00000A15);
+       odm_write_4byte(dm, 0xe6c, 0x00000A15);
+       odm_write_4byte(dm, 0x808, 0x2D028200);
+#if 0
+       /*odm_write_4byte(dm, 0x810, 0x211042A5);*/
+#endif
+       odm_write_4byte(dm, 0x8f4, 0x00d80fb1);
+       odm_write_4byte(dm, 0x90c, 0x0B00C000);
+       odm_write_4byte(dm, 0x9a4, 0x00000080);
+       odm_write_4byte(dm, 0xc94, 0x01000101);
+       odm_write_4byte(dm, 0xe94, 0x01000101);
+       odm_write_4byte(dm, 0xe5c, 0xD1000120);
+       odm_write_4byte(dm, 0xc6c, 0x00000A15);
+       odm_write_4byte(dm, 0xe6c, 0x00000A15);
+       odm_write_4byte(dm, 0x1904, 0x00020000);
+       /*path A*/
+       /*RF*/
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0xef, RFREGOFFSETMASK, 0x80000);
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0x33, RFREGOFFSETMASK, 0x00024);
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0x3e, RFREGOFFSETMASK, 0x0003F);
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0x3f, RFREGOFFSETMASK, 0xCBFCE);
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0xef, RFREGOFFSETMASK, 0x00000);
+       /*AGC boundary selection*/
+       odm_write_4byte(dm, 0x1bbc, 0x0001abf6);
+       odm_write_4byte(dm, 0x1b90, 0x0001e018);
+       odm_write_4byte(dm, 0x1bb8, 0x000fffff);
+       odm_write_4byte(dm, 0x1bc8, 0x000c55aa);
+#if 0
+       /*odm_write_4byte(dm, 0x1bcc, 0x11978200);*/
+#endif
+       odm_write_4byte(dm, 0x1bcc, 0x11978800);
+#if 0
+       /*odm_write_4byte(dm, 0xcb0, 0x77775747);*/
+       /*odm_write_4byte(dm, 0xcb4, 0x100000f7);*/
+       /*odm_write_4byte(dm, 0xcb4, 0x10000007);*/
+       /*odm_write_4byte(dm, 0xcbc, 0x0);*/
+#endif
+}
+
+void _dpk_dynamic_bias_8821c(struct dm_struct *dm, u8 path, u8 dynamicbias)
+{
+       u32 tmp;
+       tmp = odm_get_rf_reg(dm, RF_PATH_A, RF_0xdf, RFREGOFFSETMASK);
+       tmp = tmp | BIT(8);
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0xdf, RFREGOFFSETMASK, tmp);
+       if ((*dm->band_type == ODM_BAND_5G) && (*dm->band_width == 1))
+               odm_set_rf_reg(dm, path, RF_0x61, BIT(7) | BIT(6) | BIT(5) | BIT(4), dynamicbias);
+       if ((*dm->band_type == ODM_BAND_5G) && (*dm->band_width == 2))
+               odm_set_rf_reg(dm, path, RF_0x61, BIT(7) | BIT(6) | BIT(5) | BIT(4), dynamicbias);
+       tmp = tmp & (~BIT(8));
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0xdf, RFREGOFFSETMASK, tmp);
+       RF_DBG(dm, DBG_RF_IQK, "[DPK]Set DynamicBias 0xdf=0x%x, 0x61=0x%x\n",
+              odm_get_rf_reg(dm, RF_PATH_A, RF_0xdf, RFREGOFFSETMASK),
+              odm_get_rf_reg(dm, RF_PATH_A, RF_0x61, RFREGOFFSETMASK));
+}
+
+void _dpk_boundary_selection_8821c(struct dm_struct *dm, u8 path)
+{
+       u8 tmp_pad, compared_pad, compared_txbb;
+       u32 rf_backup_reg00;
+       u8 i = 0;
+       u8 j = 1;
+       u32 boundaryselect = 0;
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+
+       RF_DBG(dm, DBG_RF_IQK, "[DPK]Start the DPD boundary selection\n");
+       rf_backup_reg00 = odm_get_rf_reg(dm, (enum rf_path)path, RF_0x00, RFREGOFFSETMASK);
+       tmp_pad = 0;
+       compared_pad = 0;
+       boundaryselect = 0;
+#if dpk_forcein_sram4
+       for (i = 0x1f; i > 0x0; i--) { /*i=tx index*/
+               odm_set_rf_reg(dm, RF_PATH_A, RF_0x00, RFREGOFFSETMASK, 0x20000 + i);
+
+               if (iqk_info->is_btg) {
+                       compared_pad = (u8)((0x1c000 & odm_get_rf_reg(dm, (enum rf_path)path, RF_0x78, RFREGOFFSETMASK)) >> 14);
+                       compared_txbb = (u8)((0x07C00 & odm_get_rf_reg(dm, (enum rf_path)path, RF_0x5c, RFREGOFFSETMASK)) >> 10);
+               } else {
+                       compared_pad = (u8)((0xe0 & odm_get_rf_reg(dm, (enum rf_path)path, RF_0x56, RFREGOFFSETMASK)) >> 5);
+                       compared_txbb = (u8)((0x1f & odm_get_rf_reg(dm, (enum rf_path)path, RF_0x56, RFREGOFFSETMASK)));
+               }
+               if (i == 0x1f) {
+                       /*boundaryselect = compared_txbb;*/
+                       boundaryselect = 0x1f;
+                       tmp_pad = compared_pad;
+               }
+               if (compared_pad < tmp_pad) {
+                       boundaryselect = boundaryselect + (i << (j * 5));
+                       tmp_pad = compared_pad;
+                       j++;
+               }
+
+               if (j >= 4)
+                       break;
+       }
+
+#else
+       boundaryselect = 0x0;
+#endif
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0x00, RFREGOFFSETMASK, rf_backup_reg00);
+       odm_write_4byte(dm, 0x1bbc, boundaryselect);
+}
+
+u8 _dpk_get_dpk_tx_agc_8821c(struct dm_struct *dm, u8 path)
+{
+       u8 tx_agc_init_value = 0x1f; /* DPK TXAGC value*/
+       u32 rf_reg00 = 0x0;
+       u8 gainloss = 0x1;
+       u8 best_tx_agc, txagcindpk = 0x0;
+       u8 tmp;
+       boolean fail = true;
+       u32 IQK_CMD = 0xf8000d18;
+
+       /* rf_reg00 = 0x40000 + tx_agc_init_value;  set TXAGC value */
+       if (*dm->band_type == ODM_BAND_5G) {
+               tx_agc_init_value = 0x1c;
+               rf_reg00 = 0x40000 + tx_agc_init_value; /* set TXAGC value*/
+#if 0
+               /*rf_reg00 = 0x54000 + tx_agc_init_value;*/ /* set TXAGC value*/
+#endif
+               odm_write_4byte(dm, 0x1bc8, 0x000c55aa);
+               odm_set_rf_reg(dm, RF_PATH_A, RF_0x8f, RFREGOFFSETMASK, 0xa9c00);
+       } else {
+               tx_agc_init_value = 0x17;
+               rf_reg00 = 0x44000 + tx_agc_init_value; /* set TXAGC value*/
+#if 0
+               /*rf_reg00 = 0x54000 + tx_agc_init_value; */ /* set TXAGC value*/
+#endif
+               odm_write_4byte(dm, 0x1bc8, 0x000c44aa);
+               odm_set_rf_reg(dm, RF_PATH_A, RF_0x8f, RFREGOFFSETMASK, 0xaec00);
+       }
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0x00, RFREGOFFSETMASK, rf_reg00);
+       odm_set_bb_reg(dm, R_0x1b8c, BIT(15) | BIT(14) | BIT(13), gainloss);
+       odm_set_bb_reg(dm, R_0x1bc8, BIT(31), 0x1);
+       odm_set_bb_reg(dm, R_0x8f8, BIT(25) | BIT(24) | BIT(23) | BIT(22), 0x5);
+
+       _dpk_set_bbtxagc_8821c(dm, RF_PATH_A);
+       txagcindpk = _dpk_get_txagcindpk_8821c(dm, RF_PATH_A);
+
+       if (odm_get_rf_reg(dm, path, RF_0x08, RFREGOFFSETMASK) != 0x0)
+               odm_set_rf_reg(dm, path, RF_0x8, RFREGOFFSETMASK, 0x0);
+       ;
+#if 0
+       /*ODM_sleep_ms(1);*/
+#endif
+       ODM_delay_ms(1);
+       odm_write_4byte(dm, 0x1b00, IQK_CMD);
+       odm_write_4byte(dm, 0x1b00, IQK_CMD + 1);
+
+       fail = _iqk_check_nctl_done_8821c(dm, path, IQK_CMD);
+
+       odm_write_4byte(dm, 0x1b90, 0x0001e018);
+#if 0
+       /*
+       RF_DBG(dm, DBG_RF_IQK,
+               "[DPK]rf_reg00 =0x%x, 0x8F =0x%x, txagcindpk =0x%x\n",
+               odm_get_rf_reg(dm, path, RF_0x00, RFREGOFFSETMASK),
+               odm_get_rf_reg(dm, path, RF_0x8f, RFREGOFFSETMASK),txagcindpk);
+*/
+#endif
+
+       odm_write_4byte(dm, 0x1bd4, 0x60001);
+       tmp = (u8)odm_read_4byte(dm, 0x1bfc);
+       best_tx_agc = tx_agc_init_value - (0xa - tmp);
+#if 0
+/*
+       RF_DBG(dm, DBG_RF_IQK,
+               "[DPK](2), 0x1b8c =0x%x, rf_reg00 = 0x%x, 0x1b00 = 0x%x, 0x1bfc = 0x%x, 0x1bd4 = 0x%x,best_tx_agc =0x%x, 0x1bfc[7:0] =0x%x\n",
+               odm_read_4byte(dm, 0x1b8c),
+               odm_get_rf_reg(dm, path, RF_0x00, RFREGOFFSETMASK),
+               odm_read_4byte(dm, 0x1b00),
+               odm_read_4byte(dm, 0x1bfc), odm_read_4byte(dm, 0x1bd4),
+               best_tx_agc, tmp);
+*/
+#endif
+/* dbg message*/
+#if 0
+
+       RF_DBG(dm, DBG_RF_IQK, "[DPK] 0x1bcc = 0x%x, 0x1bb8 =0x%x\n",
+              odm_read_4byte(dm, 0x1bcc), odm_read_4byte(dm, 0x1bb8));
+
+       odm_write_4byte(dm, 0x1bcc, 0x118f8800);
+       for (i = 0 ; i < 8; i++) {
+               odm_write_4byte(dm, 0x1b90, 0x0101e018 + i);
+               odm_write_4byte(dm, 0x1bd4, 0x00060000);
+               RF_DBG(dm, DBG_RF_IQK, "0x%x\n", odm_read_4byte(dm, 0x1bfc));
+               odm_write_4byte(dm, 0x1bd4, 0x00070000);
+               RF_DBG(dm, DBG_RF_IQK, "0x%x\n", odm_read_4byte(dm, 0x1bfc));
+               odm_write_4byte(dm, 0x1bd4, 0x00080000);
+               RF_DBG(dm, DBG_RF_IQK, "0x%x\n", odm_read_4byte(dm, 0x1bfc));
+               odm_write_4byte(dm, 0x1bd4, 0x00090000);
+               RF_DBG(dm, DBG_RF_IQK, "0x%x\n", odm_read_4byte(dm, 0x1bfc));
+       }
+
+       odm_write_4byte(dm, 0x1b90, 0x0001e018);
+
+#endif
+       return best_tx_agc;
+}
+
+boolean
+_dpk_enable_dpk_8821c(struct dm_struct *dm, u8 path, u8 best_tx_agc)
+{
+       u32 rf_reg00 = 0x0;
+       boolean fail = true;
+       u32 IQK_CMD = 0xf8000e18;
+
+       if (*dm->band_type == ODM_BAND_5G)
+               rf_reg00 = 0x40000 + best_tx_agc; /* set TXAGC value*/
+       else
+               rf_reg00 = 0x44000 + best_tx_agc; /* set TXAGC value*/
+       odm_set_rf_reg(dm, RF_PATH_A, RF_0x00, RFREGOFFSETMASK, rf_reg00);
+       _dpk_set_dpk_pa_scan(dm, RF_PATH_A);
+
+       /*ODM_sleep_ms(1);*/
+       ODM_delay_ms(1);
+       odm_set_bb_reg(dm, R_0x1bc8, BIT(31), 0x1);
+       odm_write_4byte(dm, 0x8f8, 0x41400080);
+
+       if (odm_get_rf_reg(dm, path, RF_0x08, RFREGOFFSETMASK) != 0x0)
+               odm_set_rf_reg(dm, path, RF_0x8, RFREGOFFSETMASK, 0x0);
+
+       /*ODM_sleep_ms(1);*/
+       ODM_delay_ms(1);
+       odm_write_4byte(dm, 0x1b00, IQK_CMD);
+       odm_write_4byte(dm, 0x1b00, IQK_CMD + 1);
+
+       odm_write_4byte(dm, 0x1b90, 0x0001e018);
+       odm_write_4byte(dm, 0x1bd4, 0xA0001);
+       fail = _iqk_check_nctl_done_8821c(dm, path, IQK_CMD);
+#if 0
+/*
+       RF_DBG(dm, DBG_RF_IQK,
+               "[DPK] (3) 0x1b0b = 0x%x, 0x1bc8 = 0x%x, rf_reg00 = 0x%x, ,0x1bfc = 0x%x, 0x1b90=0x%x, 0x1b94=0x%x\n",
+               odm_read_1byte(dm, 0x1b0b), odm_read_4byte(dm, 0x1bc8), odm_get_rf_reg(dm, path, RF_0x00, RFREGOFFSETMASK),
+               odm_read_4byte(dm, 0x1bfc), odm_read_4byte(dm, 0x1b90), odm_read_4byte(dm, 0x1b94));
+*/
+#endif
+#if 0 /* dbg message*/
+       u8 delay_count = 0x0;
+    u8 i;
+       u32 tmp;
+       odm_write_4byte(dm, 0x1b00, 0xf8000008);
+       odm_write_4byte(dm, 0x1b08, 0x00000080);
+       odm_write_4byte(dm, 0x1bd4, 0x00040001);
+
+       RF_DBG(dm, DBG_RF_IQK, "[DPK] SRAM value!!!\n");
+
+       for (i = 0 ; i < 64; i++) {
+               /*odm_write_4byte(dm, 0x1b90, 0x0101e018+i);*/
+               odm_write_4byte(dm, 0x1bdc, 0xc0000081 + i * 2);
+
+               RF_DBG(dm, DBG_RF_IQK, "0x%x\n", odm_read_4byte(dm, 0x1bfc));
+       }
+       odm_write_4byte(dm, 0x1bd4, 0x00050001);
+       for (i = 0 ; i < 64; i++) {
+               /*odm_write_4byte(dm, 0x1b90, 0x0101e018+i);*/
+               odm_write_4byte(dm, 0x1bdc, 0xc0000081 + i * 2);
+
+               RF_DBG(dm, DBG_RF_IQK, "0x%x\n", odm_read_4byte(dm, 0x1bfc));
+       }
+
+       /*odm_write_4byte(dm, 0x1b08, 0x00000080);*/
+       odm_write_4byte(dm, 0x1bd4, 0xA0001);
+       odm_write_4byte(dm, 0x1bdc, 0x00000000);
+#endif
+       return fail;
+}
+
+boolean
+_dpk_enable_dpd_8821c(struct dm_struct *dm, u8 path, u8 best_tx_agc)
+{
+       boolean fail = true;
+       u8 offset = 0x0;
+       u32 IQK_CMD = 0xf8000f18;
+       u8 external_pswf_gain;
+       boolean gain_scaling_enable = false;
+
+       odm_set_bb_reg(dm, R_0x1bc8, BIT(31), 0x1);
+       odm_write_4byte(dm, 0x8f8, 0x41400080);
+       if (odm_get_rf_reg(dm, path, RF_0x08, RFREGOFFSETMASK) != 0x0)
+               odm_set_rf_reg(dm, path, RF_0x8, RFREGOFFSETMASK, 0x0);
+       /*ODM_sleep_ms(1);*/
+       ODM_delay_ms(1);
+       odm_write_4byte(dm, 0x1b00, IQK_CMD);
+       odm_write_4byte(dm, 0x1b00, IQK_CMD + 1);
+       fail = _iqk_check_nctl_done_8821c(dm, path, IQK_CMD);
+
+       odm_write_4byte(dm, 0x1b90, 0x0001e018);
+       odm_write_4byte(dm, 0x1bd4, 0xA0001);
+
+       if (!fail) {
+               odm_write_4byte(dm, 0x1bcf, 0x19);
+               odm_write_4byte(dm, 0x1bdc, 0x0);
+               /*add 2db extrnal for compensate performnace, the reason is unknown*/
+               external_pswf_gain = 0x2;
+               best_tx_agc = best_tx_agc + external_pswf_gain;
+
+               if (best_tx_agc >= 0x19)
+                       offset = best_tx_agc - 0x19;
+               else
+                       offset = 0x20 - (0x19 - best_tx_agc);
+               odm_set_bb_reg(dm, R_0x1bd0, BIT(12) | BIT(11) | BIT(10) | BIT(9) | BIT(8), offset);
+               if (gain_scaling_enable)
+                       _dpk_set_gain_scaling(dm, RF_PATH_A);
+               else
+                       odm_write_4byte(dm, 0x1b98, 0x4c004c00);
+
+       } else {
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[DPK](4)0x1b08 =%x, 0x1bc8 = 0x%x,0x1bfc = 0x%x, ,0x1bd0 = 0x%x, offset =%x, 1bcc =%x\n",
+                      odm_read_4byte(dm, 0x1b08), odm_read_4byte(dm, 0x1bc8),
+                      odm_read_1byte(dm, 0x1bfc), odm_read_4byte(dm, 0x1bd0),
+                      offset, odm_read_4byte(dm, 0x1bcc));
+       }
+
+       return fail;
+}
+
+void _phy_dpd_calibrate_8821c(struct dm_struct *dm, boolean reset)
+{
+       u32 backup_dpdbb[3];
+       u8 best_tx_agc = 0x1c;
+       u32 MAC_backup[MAC_REG_NUM_8821C], RF_backup[RF_REG_NUM_8821C][1];
+       u32 backup_mac_reg[MAC_REG_NUM_8821C] = {0x520, 0x550, 0x1518};
+       u32 BB_backup[DPK_BB_REG_NUM_8821C];
+       u32 backup_bb_reg[DPK_BB_REG_NUM_8821C] = {0x808, 0x90c, 0xc00, 0xcb0, 0xcb4, 0xcbc, 0x1990, 0x9a4, 0xa04, 0xc58, 0xc5c, 0xe58, 0xe5c, 0xc6c, 0xe6c, 0x90c, 0xc94, 0xe94, 0x1904, 0xcb0, 0xcb4, 0xcbc, 0xc00};
+       u32 backup_rf_reg[RF_REG_NUM_8821C] = {0xdf, 0xde, 0x8f, 0x0, 0x1};
+       u8 i;
+       u32 backup_dpk_reg[3] = {0x1bd0, 0x1b98, 0x1bbc};
+
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+       iqk_info->is_btg = (boolean)odm_get_bb_reg(dm, R_0xcb8, BIT(16));
+       if (!(*dm->mp_mode))
+               if (_iqk_reload_iqk_8821c(dm, reset))
+                       return;
+       if (!(*dm->band_type == ODM_BAND_5G))
+               return;
+
+       RF_DBG(dm, DBG_RF_IQK, "[DPK]==========DPK strat!!!!!==========\n");
+       RF_DBG(dm, DBG_RF_IQK,
+              "[DPK]band_type = %s, band_width = %d, ExtPA2G = %d, ext_pa_5g = %d\n",
+              (*dm->band_type == ODM_BAND_5G) ? "5G" : "2G", *dm->band_width,
+              dm->ext_pa, dm->ext_pa_5g);
+       _iqk_backup_mac_bb_8821c(dm, MAC_backup, BB_backup, backup_mac_reg, backup_bb_reg, DPK_BB_REG_NUM_8821C);
+       _iqk_afe_setting_8821c(dm, true);
+       _iqk_backup_rf_8821c(dm, RF_backup, backup_rf_reg);
+
+       if (iqk_info->is_btg) {
+       } else {
+               if (*dm->band_type == ODM_BAND_2_4G)
+                       odm_set_bb_reg(dm, R_0xcb8, BIT(8), 0x1);
+               else
+                       odm_set_bb_reg(dm, R_0xcb8, BIT(8), 0x0);
+       }
+
+       /*backup 0x1b2c, 1b38,0x1b3c*/
+       backup_dpdbb[0] = odm_read_4byte(dm, 0x1b2c);
+       backup_dpdbb[1] = odm_read_4byte(dm, 0x1b38);
+       backup_dpdbb[2] = odm_read_4byte(dm, 0x1b3c);
+       RF_DBG(dm, DBG_RF_IQK, "[DPK]In DPD Process(1), Backup\n");
+
+       /*PDK Init Register setting*/
+       _dpk_clear_sram_8821c(dm, RF_PATH_A);
+       _dpk_setting_8821c(dm, RF_PATH_A);
+       _dpk_boundary_selection_8821c(dm, RF_PATH_A);
+       odm_set_bb_reg(dm, R_0x1bc8, BIT(31), 0x1);
+       odm_set_bb_reg(dm, R_0x8f8, BIT(25) | BIT(24) | BIT(23) | BIT(22), 0x5);
+       /* Get the best TXAGC*/
+
+       best_tx_agc = _dpk_get_dpk_tx_agc_8821c(dm, RF_PATH_A);
+#if 0
+       /*ODM_sleep_ms(2);*/
+#endif
+
+       ODM_delay_ms(2);
+       RF_DBG(dm, DBG_RF_IQK, "[DPK]In DPD Process(2), Best TXAGC = 0x%x\n",
+              best_tx_agc);
+
+       if (_dpk_enable_dpk_8821c(dm, RF_PATH_A, best_tx_agc)) {
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[DPK]In DPD Process(3), DPK process is Fail\n");
+       }
+#if 0
+       /*ODM_sleep_ms(2);*/
+#endif
+       ODM_delay_ms(2);
+       if (_dpk_enable_dpd_8821c(dm, RF_PATH_A, best_tx_agc)) {
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[DPK]In DPD Process(4), DPD process is Fail\n");
+       }
+       /* restore IQK */
+       iqk_info->rf_reg18 = odm_get_rf_reg(dm, RF_PATH_A, RF_0x18, RFREGOFFSETMASK);
+       _iqk_reload_iqk_setting_8821c(dm, 0, 2);
+       _iqk_fill_iqk_report_8821c(dm, 0);
+#if 0
+       /*
+       RF_DBG(dm, DBG_RF_IQK,
+               "[DPK]reload IQK result before, iqk_info->rf_reg18=0x%x, iqk_info->iqk_channel[0]=0x%x, iqk_info->iqk_channel[1]=0x%x!!!!\n",
+               iqk_info->rf_reg18, iqk_info->iqk_channel[0], iqk_info->iqk_channel[1]);
+      */
+#endif
+
+       /* Restore setup */
+#if 0
+       /*_dpk_readsram_8821c(dm, RF_PATH_A);*/
+#endif
+       _dpk_restore_8821c(dm, RF_PATH_A);
+       odm_set_bb_reg(dm, R_0x8f8, BIT(25) | BIT(24) | BIT(23) | BIT(22), 0x5);
+       odm_set_bb_reg(dm, R_0x1bd4, BIT(20) | BIT(19) | BIT(18) | BIT(17) | BIT(16), 0x0);
+       odm_set_bb_reg(dm, R_0x1b00, BIT(2) | BIT(1), 0x0);
+       odm_set_bb_reg(dm, R_0x1b08, BIT(6) | BIT(5), 0x2);
+
+       odm_write_4byte(dm, 0x1b2c, backup_dpdbb[0]);
+       odm_write_4byte(dm, 0x1b38, backup_dpdbb[1]);
+       odm_write_4byte(dm, 0x1b3c, backup_dpdbb[2]);
+       /*enable DPK*/
+       odm_set_bb_reg(dm, R_0x1b2c, BIT(7) | BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0), 0x5);
+/*enable boundary condition*/
+#if dpk_forcein_sram4 /* disable : froce in sram4*/
+       odm_set_bb_reg(dm, R_0x1bcc, BIT(27), 0x1);
+#endif
+       odm_write_4byte(dm, 0x1bcc, 0x11868800);
+       RF_DBG(dm, DBG_RF_IQK, "[DPK]In DPD Process(5), Restore\n");
+       _iqk_restore_mac_bb_8821c(dm, MAC_backup, BB_backup, backup_mac_reg, backup_bb_reg, DPK_BB_REG_NUM_8821C);
+       _iqk_afe_setting_8821c(dm, false);
+       _iqk_restore_rf_8821c(dm, backup_rf_reg, RF_backup);
+       /*toggle dynamic_pwr_threshold*/
+
+       /* backup the DPK current result*/
+       for (i = 0; i < DPK_BACKUP_REG_NUM_8821C; i++)
+               dpk_result[i] = odm_read_4byte(dm, backup_dpk_reg[i]);
+
+       RF_DBG(dm, DBG_RF_IQK,
+              "[DPK]the DPD calibration Process Finish (6), 0x1bd0 = 0x%x, 0x1b98 = 0x%x, 0x1bbc0= 0x%x\n",
+              dpk_result[0], dpk_result[1], dpk_result[2]);
+}
+
+u32 _iqk_tximr_selfcheck_8821c(void *dm_void, u8 tone_index, u8 path)
+{
+       u32 tx_ini_power_H[2], tx_ini_power_L[2];
+       u32 tmp1, tmp2, tmp3, tmp4, tmp5;
+       u32 IQK_CMD;
+       u32 tximr = 0x0;
+       u8 i;
+
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       /*backup*/
+       odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+       odm_write_4byte(dm, 0x1bc8, 0x80000000);
+       odm_write_4byte(dm, 0x8f8, 0x41400080);
+       tmp1 = odm_read_4byte(dm, 0x1b0c);
+       tmp2 = odm_read_4byte(dm, 0x1b14);
+       tmp3 = odm_read_4byte(dm, 0x1b1c);
+       tmp4 = odm_read_4byte(dm, 0x1b20);
+       tmp5 = odm_read_4byte(dm, 0x1b24);
+       /*setup*/
+       odm_write_4byte(dm, 0x1b0c, 0x00003000);
+       odm_write_4byte(dm, 0x1b1c, 0xA2193C32);
+       odm_write_1byte(dm, 0x1b15, 0x00);
+       odm_write_4byte(dm, 0x1b20, (u32)(tone_index << 20 | 0x00040008));
+       odm_write_4byte(dm, 0x1b24, (u32)(tone_index << 20 | 0x00060008));
+       odm_write_4byte(dm, 0x1b2c, 0x07);
+       odm_write_4byte(dm, 0x1b38, 0x20000000);
+       odm_write_4byte(dm, 0x1b3c, 0x20000000);
+       /* ======derive pwr1========*/
+       for (i = 0; i < 2; i++) {
+               if (i == 0)
+                       odm_write_4byte(dm, 0x1bcc, 0x0f);
+               else
+                       odm_write_4byte(dm, 0x1bcc, 0x09);
+               /* One Shot*/
+               IQK_CMD = 0x00000800;
+               odm_write_4byte(dm, 0x1b34, IQK_CMD + 1);
+               odm_write_4byte(dm, 0x1b34, IQK_CMD);
+               ODM_delay_ms(1);
+               odm_write_4byte(dm, 0x1bd4, 0x00040001);
+               tx_ini_power_H[i] = odm_read_4byte(dm, 0x1bfc);
+               odm_write_4byte(dm, 0x1bd4, 0x000C0001);
+               tx_ini_power_L[i] = odm_read_4byte(dm, 0x1bfc);
+       }
+       /*restore*/
+       odm_write_4byte(dm, 0x1b0c, tmp1);
+       odm_write_4byte(dm, 0x1b14, tmp2);
+       odm_write_4byte(dm, 0x1b1c, tmp3);
+       odm_write_4byte(dm, 0x1b20, tmp4);
+       odm_write_4byte(dm, 0x1b24, tmp5);
+
+       if (tx_ini_power_H[1] == tx_ini_power_H[0])
+               tximr = (3 * (halrf_psd_log2base(tx_ini_power_L[0] << 2) - halrf_psd_log2base(tx_ini_power_L[1]))) / 100;
+       else
+               tximr = 0;
+       return tximr;
+}
+
+u32 _iqk_rximr_selfcheck_8821c(void *dm_void, u8 tone_index, u8 path,
+                              u32 tmp1b38)
+{
+       u32 rx_ini_power_H[2], rx_ini_power_L[2]; /*[0]: psd tone; [1]: image tone*/
+       u32 tmp1, tmp2, tmp3, tmp4, tmp5;
+       u32 IQK_CMD, tmp1bcc;
+       u8 i;
+       u32 rximr = 0x0;
+
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+
+       /*backup*/
+       odm_write_4byte(dm, 0x1b00, 0xf8000008 | path << 1);
+       tmp1 = odm_read_4byte(dm, 0x1b0c);
+       tmp2 = odm_read_4byte(dm, 0x1b14);
+       tmp3 = odm_read_4byte(dm, 0x1b1c);
+       tmp4 = odm_read_4byte(dm, 0x1b20);
+       tmp5 = odm_read_4byte(dm, 0x1b24);
+
+       tmp1bcc = (odm_read_4byte(dm, 0x1be8) & 0x0000ff00) >> 8;
+       odm_write_4byte(dm, 0x1b0c, 0x00001000);
+       odm_write_1byte(dm, 0x1b15, 0x00);
+       odm_write_4byte(dm, 0x1b1c, 0x82193d31);
+       odm_write_4byte(dm, 0x1b20, (u32)(tone_index << 20 | 0x00040008));
+       odm_write_4byte(dm, 0x1b24, (u32)(tone_index << 20 | 0x00060048));
+       odm_write_4byte(dm, 0x1b2c, 0x07);
+#if 0
+       //odm_write_4byte(dm, 0x1b38, iqk_info->rxk1_tmp1b38[path][(tone_index&0xff0)>>4]);
+#endif
+       odm_write_4byte(dm, 0x1b38, tmp1b38);
+
+       odm_write_4byte(dm, 0x1b3c, 0x20000000);
+       odm_write_4byte(dm, 0x1bcc, tmp1bcc);
+       for (i = 0; i < 2; i++) {
+               if (i == 0)
+                       odm_write_4byte(dm, 0x1b1c, 0x82193d31);
+               else
+                       odm_write_4byte(dm, 0x1b1c, 0xA2193d31);
+               IQK_CMD = 0x00000800;
+               odm_write_4byte(dm, 0x1b34, IQK_CMD + 1);
+               odm_write_4byte(dm, 0x1b34, IQK_CMD);
+               ODM_delay_us(2000);
+               odm_write_1byte(dm, 0x1bd6, 0xb);
+#if 0
+               /*if ((boolean)odm_get_bb_reg(dm, R_0x1bfc, BIT(1))){*/
+#endif
+               if (1) {
+                       odm_write_1byte(dm, 0x1bd6, 0x5);
+                       rx_ini_power_H[i] = odm_read_4byte(dm, 0x1bfc);
+                       odm_write_1byte(dm, 0x1bd6, 0xe);
+                       rx_ini_power_L[i] = odm_read_4byte(dm, 0x1bfc);
+               } else {
+                       rx_ini_power_H[i] = 0x0;
+                       rx_ini_power_L[i] = 0x0;
+               }
+       }
+       /*restore*/
+       odm_write_4byte(dm, 0x1b0c, tmp1);
+       odm_write_4byte(dm, 0x1b14, tmp2);
+       odm_write_4byte(dm, 0x1b1c, tmp3);
+       odm_write_4byte(dm, 0x1b20, tmp4);
+       odm_write_4byte(dm, 0x1b24, tmp5);
+
+       for (i = 0; i < 2; i++)
+               rx_ini_power_H[i] = (rx_ini_power_H[i] & 0xf8000000) >> 27;
+
+       if (rx_ini_power_H[0] != rx_ini_power_H[1])
+               switch (rx_ini_power_H[0]) {
+               case 1:
+                       rx_ini_power_L[0] = (u32)((rx_ini_power_L[0] >> 1) | 0x80000000);
+                       rx_ini_power_L[1] = (u32)rx_ini_power_L[1] >> 1;
+                       break;
+               case 2:
+                       rx_ini_power_L[0] = (u32)((rx_ini_power_L[0] >> 2) | 0x80000000);
+                       rx_ini_power_L[1] = (u32)rx_ini_power_L[1] >> 2;
+                       break;
+               case 3:
+                       rx_ini_power_L[0] = (u32)((rx_ini_power_L[0] >> 2) | 0xc0000000);
+                       rx_ini_power_L[1] = (u32)rx_ini_power_L[1] >> 2;
+                       break;
+               case 4:
+                       rx_ini_power_L[0] = (u32)((rx_ini_power_L[0] >> 3) | 0x80000000);
+                       rx_ini_power_L[1] = (u32)rx_ini_power_L[1] >> 3;
+                       break;
+               case 5:
+                       rx_ini_power_L[0] = (u32)((rx_ini_power_L[0] >> 3) | 0xa0000000);
+                       rx_ini_power_L[1] = (u32)rx_ini_power_L[1] >> 3;
+                       break;
+               case 6:
+                       rx_ini_power_L[0] = (u32)((rx_ini_power_L[0] >> 3) | 0xc0000000);
+                       rx_ini_power_L[1] = (u32)rx_ini_power_L[1] >> 3;
+                       break;
+               case 7:
+                       rx_ini_power_L[0] = (u32)((rx_ini_power_L[0] >> 3) | 0xe0000000);
+                       rx_ini_power_L[1] = (u32)rx_ini_power_L[1] >> 3;
+                       break;
+               default:
+                       break;
+               }
+       rximr = (u32)(3 * ((halrf_psd_log2base(rx_ini_power_L[0] / 100) - halrf_psd_log2base(rx_ini_power_L[1] / 100))) / 100);
+#if 0
+       /*
+               RF_DBG(dm, DBG_RF_IQK, "%-20s: 0x%x, 0x%x, 0x%x, 0x%x,0x%x, tone_index=%x, rximr= %d\n",
+               (path == 0) ? "PATH A RXIMR ": "PATH B RXIMR",
+               rx_ini_power_H[0], rx_ini_power_L[0], rx_ini_power_H[1], rx_ini_power_L[1], tmp1bcc, tone_index, rximr);
+*/
+#endif
+       return rximr;
+}
+
+void _iqk_start_imr_test_8821c(void *dm_void, u8 path)
+{
+       u8 imr_limit, i, tone_index;
+       u32 tmp;
+       boolean KFAIL;
+       u32 rxk1_tmp1b38[2][15];
+       u32 imr_result[2];
+
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+
+       /*TX IMR*/
+       if (*dm->band_width == 2)
+               imr_limit = 0xe;
+       else if (*dm->band_width == 1)
+               imr_limit = 0x7;
+       else
+               imr_limit = 0x3;
+
+       _iqk_txk_setting_8821c(dm, RF_PATH_A);
+       KFAIL = _iqk_one_shot_8821c(dm, RF_PATH_A, TXIQK);
+       for (i = 0x0; i <= imr_limit; i++) {
+               tone_index = (u8)(0x08 | i << 4);
+               imr_result[RF_PATH_A] = _iqk_tximr_selfcheck_8821c(dm, tone_index, RF_PATH_A);
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]toneindex = %x, TXIMR = %d\n",
+                      tone_index, imr_result[RF_PATH_A]);
+       }
+       RF_DBG(dm, DBG_RF_IQK, "\n");
+       /*RX IMR*/
+       /*get the rxk1 tone index 0x1b38 setting*/
+       _iqk_rxk1setting_8821c(dm, path);
+       tmp = odm_read_4byte(dm, 0x1b1c);
+       for (path = 0; path < SS_8821C; path++) {
+               for (i = 0; i <= imr_limit; i++) {
+                       tone_index = (u8)(0x08 | i << 4);
+                       KFAIL = _iqk_rx_iqk_gain_search_fail_by_toneindex_8821c(dm, path, RXIQK1, tone_index);
+                       if (!KFAIL) {
+                               odm_write_4byte(dm, 0x1b1c, 0xa2193c32);
+                               odm_write_4byte(dm, 0x1b14, 0xe5);
+                               odm_write_4byte(dm, 0x1b14, 0x0);
+                               rxk1_tmp1b38[path][i] = odm_read_4byte(dm, 0x1b38);
+                       } else {
+                               rxk1_tmp1b38[path][i] = 0x0;
+                       }
+               }
+       }
+       _iqk_rxk2setting_8821c(dm, path, true);
+       for (path = 0; path < SS_8821C; path++) {
+               for (i = 0x0; i <= imr_limit; i++) {
+                       tone_index = (u8)(0x08 | i << 4);
+                       imr_result[RF_PATH_A] = _iqk_rximr_selfcheck_8821c(dm, tone_index, RF_PATH_A, rxk1_tmp1b38[path][i]);
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[IQK]toneindex = %x, RXIMR = %d\n", tone_index,
+                              imr_result[RF_PATH_A]);
+               }
+       }
+       odm_write_4byte(dm, 0x1b1c, tmp);
+       odm_write_4byte(dm, 0x1b38, 0x20000000);
+}
+
+void _phy_iq_calibrate_8821c(struct dm_struct *dm, boolean reset,
+                            boolean segment_iqk, boolean do_imr_test)
+{
+       u32 MAC_backup[MAC_REG_NUM_8821C], BB_backup[BB_REG_NUM_8821C];
+       u32 RF_backup[RF_REG_NUM_8821C][1];
+       u32 backup_mac_reg[MAC_REG_NUM_8821C] = {0x520, 0x550, 0x1518};
+       u32 backup_bb_reg[BB_REG_NUM_8821C] = {0x808, 0x90c, 0xc00, 0xcb0,
+                                               0xcb4, 0xcbc, 0x1990,
+                                               0x9a4, 0xa04, 0x838};
+       u32 backup_rf_reg[RF_REG_NUM_8821C] = {0xdf, 0xde, 0x8f, 0x0, 0x1};
+       boolean is_mp = false;
+
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+
+       if (*dm->mp_mode)
+               is_mp = true;
+       else if (dm->is_linked)
+               segment_iqk = false;
+       iqk_info->is_btg = (boolean)odm_get_bb_reg(dm, R_0xcb8, BIT(16));
+
+       if (!is_mp)
+               if (_iqk_reload_iqk_8821c(dm, reset))
+                       return;
+       if (!do_imr_test)
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[IQK]==========IQK strat!!!!!==========\n");
+       RF_DBG(dm, DBG_RF_IQK,
+              "[IQK]band_type = %s, band_width = %d, ExtPA2G = %d, ext_pa_5g = %d\n",
+              (*dm->band_type == ODM_BAND_5G) ? "5G" : "2G", *dm->band_width,
+              dm->ext_pa, dm->ext_pa_5g);
+       RF_DBG(dm, DBG_RF_IQK, "[IQK]Interface = %d, cut_version = %x\n",
+              dm->support_interface, dm->cut_version);
+
+       iqk_info->tmp_gntwl = _iqk_indirect_read_reg(dm, 0x38);
+       iqk_info->iqk_times++;
+       iqk_info->kcount = 0;
+       dm->rf_calibrate_info.iqk_total_progressing_time = 0;
+       dm->rf_calibrate_info.iqk_step = 1;
+       iqk_info->rxiqk_step = 1;
+       iqk_info->is_reload = false;
+
+       _iqk_backup_iqk_8821c(dm, 0x0, 0x0);
+       _iqk_backup_mac_bb_8821c(dm, MAC_backup, BB_backup, backup_mac_reg, backup_bb_reg, BB_REG_NUM_8821C);
+       _iqk_backup_rf_8821c(dm, RF_backup, backup_rf_reg);
+
+       while (1) {
+               if (!is_mp)
+                       dm->rf_calibrate_info.iqk_start_time = odm_get_current_time(dm);
+
+               _iqk_configure_macbb_8821c(dm);
+               _iqk_afe_setting_8821c(dm, true);
+               _iqk_rfe_setting_8821c(dm, false);
+               _iqk_agc_bnd_int_8821c(dm);
+               _iqk_rfsetting_8821c(dm);
+               if (do_imr_test) {
+                       _iqk_start_imr_test_8821c(dm, 0x0);
+                       dm->rf_calibrate_info.iqk_step = 4;
+               } else {
+                       _iqk_start_iqk_8821c(dm, segment_iqk);
+               }
+               _iqk_afe_setting_8821c(dm, false);
+               _iqk_restore_mac_bb_8821c(dm, MAC_backup, BB_backup, backup_mac_reg, backup_bb_reg, BB_REG_NUM_8821C);
+               _iqk_restore_rf_8821c(dm, backup_rf_reg, RF_backup);
+
+               if (!is_mp) {
+                       dm->rf_calibrate_info.iqk_progressing_time = odm_get_progressing_time(dm, dm->rf_calibrate_info.iqk_start_time);
+                       dm->rf_calibrate_info.iqk_total_progressing_time += odm_get_progressing_time(dm, dm->rf_calibrate_info.iqk_start_time);
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[IQK]IQK progressing_time = %lld ms\n",
+                              dm->rf_calibrate_info.iqk_progressing_time);
+               }
+
+               if (dm->rf_calibrate_info.iqk_step == 4)
+                       break;
+
+               iqk_info->kcount = 0;
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]delay 50ms!!!\n");
+#if 0
+               /*ODM_sleep_ms(50);*/
+#endif
+               ODM_delay_ms(50);
+       }
+
+       if (!do_imr_test) {
+               if (segment_iqk)
+                       _iqk_reload_iqk_setting_8821c(dm, 0x0, 0x1);
+               _iqk_fill_iqk_report_8821c(dm, 0);
+               if (!is_mp)
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[IQK]Total IQK progressing_time = %lld ms\n",
+                              dm->rf_calibrate_info.iqk_total_progressing_time)
+                              ;
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[IQK]==========IQK end!!!!!==========\n");
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]check 0x49c = %x\n",
+                      odm_read_1byte(dm, 0x49c));
+       }
+}
+
+void _phy_iq_calibrate_by_fw_8821c(void *dm_void, u8 clear, u8 segment_iqk)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       enum hal_status status = HAL_STATUS_FAILURE;
+
+       if (*dm->mp_mode)
+               clear = 0x1;
+       else if (dm->is_linked)
+               segment_iqk = 0x1;
+
+       status = odm_iq_calibrate_by_fw(dm, clear, segment_iqk);
+
+       if (status == HAL_STATUS_SUCCESS)
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]FWIQK  OK!!!\n");
+       else
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]FWIQK fail!!!\n");
+}
+
+/*********debug message start**************/
+
+void _phy_iqk_XYM_Read_Using_0x1b38_8821c(struct dm_struct *dm, u8 path)
+{
+       u32 tmp = 0x0;
+       u32 tmp2;
+       u8 i;
+
+       tmp = odm_read_4byte(dm, 0x1b1c);
+       odm_write_4byte(dm, 0x1b1c, 0xA2193C32);
+       RF_DBG(dm, DBG_RF_IQK, "\n");
+       for (i = 0; i < 0xa; i++) {
+               odm_write_4byte(dm, 0x1b14, 0xe6 + i);
+               odm_write_4byte(dm, 0x1b14, 0x0);
+               tmp2 = odm_read_4byte(dm, 0x1b38);
+               RF_DBG(dm, DBG_RF_IQK, "%x\n", tmp2);
+       }
+       odm_write_4byte(dm, 0x1b1c, tmp);
+       RF_DBG(dm, DBG_RF_IQK, "\n");
+       odm_write_4byte(dm, 0x1b38, 0x20000000);
+}
+
+void _phy_iqk_debug_inner_lpbk_psd_8821c(struct dm_struct *dm, u8 path)
+{
+       s16 tx_x;
+       s16 tx_y;
+       u32 temp = 0x0;
+       u32 psd_pwr = 0x0;
+       u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10;
+
+       tmp1 = odm_read_4byte(dm, 0x1b20);
+       tmp2 = odm_read_4byte(dm, 0x1b24);
+       tmp3 = odm_read_4byte(dm, 0x1b15);
+       tmp4 = odm_read_4byte(dm, 0x1b18);
+       tmp5 = odm_read_4byte(dm, 0x1b1c);
+       tmp6 = odm_read_4byte(dm, 0x1b28);
+       tmp7 = odm_read_4byte(dm, 0x1b90);
+       tmp8 = odm_read_4byte(dm, 0x1bcc);
+       tmp9 = odm_read_4byte(dm, 0x1b2c);
+       tmp10 = odm_read_4byte(dm, 0x1b30);
+       odm_write_4byte(dm, 0x1b20, 0x03840008);
+       odm_write_4byte(dm, 0x1b24, 0x03860008);
+       odm_write_1byte(dm, 0x1b15, 0x00);
+       odm_write_4byte(dm, 0x1b18, 0x00010101);
+       odm_write_4byte(dm, 0x1b1c, 0x02effcb2);
+       odm_write_4byte(dm, 0x1b28, 0x00060c00);
+       odm_write_4byte(dm, 0x1b90, 0x00080003);
+       odm_write_4byte(dm, 0x1bcc, 0x00000009);
+       odm_write_4byte(dm, 0x1b2c, 0x20000003);
+       odm_write_4byte(dm, 0x1b30, 0x20000000);
+       RF_DBG(dm, DBG_RF_IQK, "\n");
+       for (tx_x = 507; tx_x <= 532; tx_x++) {
+               for (tx_y = 0; tx_y <= 10 + 20; tx_y++) {
+                       if (tx_y < 0)
+                               temp = (tx_x << 20) | (tx_y + 2048) << 8;
+                       else
+                               temp = (tx_x << 20) | (tx_y << 8);
+                       odm_write_4byte(dm, 0x1b38, temp);
+                       odm_write_4byte(dm, 0x1b3c, 0x20000000);
+                       odm_write_4byte(dm, 0x1b34, 0x00000801);
+                       odm_write_4byte(dm, 0x1b34, 0x00000800);
+                       ODM_delay_ms(2);
+                       /*PSD_bef_K*/
+                       odm_write_4byte(dm, 0x1bd4, 0x000c0001);
+                       psd_pwr = odm_read_4byte(dm, 0x1bfc);
+                       RF_DBG(dm, DBG_RF_IQK, "%d ", psd_pwr);
+               }
+       }
+       RF_DBG(dm, DBG_RF_IQK, "\n");
+       odm_write_4byte(dm, 0x1b20, tmp1);
+       odm_write_4byte(dm, 0x1b24, tmp2);
+       odm_write_4byte(dm, 0x1b15, tmp3);
+       odm_write_4byte(dm, 0x1b18, tmp4);
+       odm_write_4byte(dm, 0x1b1c, tmp5);
+       odm_write_4byte(dm, 0x1b28, tmp6);
+       odm_write_4byte(dm, 0x1b90, tmp7);
+       odm_write_4byte(dm, 0x1bcc, tmp8);
+       odm_write_4byte(dm, 0x1b2c, tmp9);
+       odm_write_4byte(dm, 0x1b30, tmp10);
+       odm_write_4byte(dm, 0x1b38, 0x20000000);
+}
+
+void _iqk_readsram_8821c(struct dm_struct *dm, u8 path)
+{
+       u32 tmp1bd4, tmp1bd8, tmp;
+       u8 i;
+
+       tmp1bd4 = odm_read_4byte(dm, 0x1bd4);
+       tmp1bd8 = odm_read_4byte(dm, 0x1bd8);
+       odm_write_4byte(dm, 0x1bd4, 0x00010001);
+       for (i = 0; i < 0x80; i++) {
+               odm_write_4byte(dm, 0x1bd8, 0xa0000101 + (u32)(i << 1));
+               tmp = (u32)odm_read_4byte(dm, 0x1bfc) & 0x3ff;
+               if (i < 0x40)
+                       RF_DBG(dm, DBG_RF_IQK, "adc_i[%d] = %x\n", i, tmp);
+               else
+                       RF_DBG(dm, DBG_RF_IQK, "adc_q[%d] = %x\n", i, tmp);
+       }
+}
+
+void do_imr_test_8821c(void *dm_void)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+
+       RF_DBG(dm, DBG_RF_IQK,
+              "[IQK]  ************IMR Test *****************\n");
+       _phy_iq_calibrate_8821c(dm, false, false, true);
+       RF_DBG(dm, DBG_RF_IQK,
+              "[IQK]  **********End IMR Test *******************\n");
+}
+
+/*********debug message end***************/
+
+/*IQK version:0x23, NCTL:0x8*/
+/*1. modify the iqk counters for coex.*/
+
+void phy_iq_calibrate_8821c(void *dm_void, boolean clear, boolean segment_iqk)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       struct _hal_rf_ *rf = &dm->rf_table;
+
+       if (!(*dm->mp_mode))
+               _iqk_check_coex_status(dm, true);
+
+       RF_DBG(dm, DBG_RF_IQK, "[IQK]fw_ver= 0x%x\n", rf->fw_ver);
+       if (*dm->mp_mode)
+               halrf_iqk_hwtx_check(dm, true);
+       /*FW IQK*/
+       if (dm->fw_offload_ability & PHYDM_RF_IQK_OFFLOAD) {
+               _phy_iq_calibrate_by_fw_8821c(dm, clear, segment_iqk);
+               phydm_get_read_counter_8821c(dm);
+               RF_DBG(dm, DBG_RF_IQK, "[IQK]0x38= 0x%x\n",
+                      _iqk_indirect_read_reg(dm, 0x38));
+       } else {
+               _iq_calibrate_8821c_init(dm);
+               _phy_iq_calibrate_8821c(dm, clear, segment_iqk, false);
+       }
+       _iqk_fail_count_8821c(dm);
+
+       if (*dm->mp_mode)
+               halrf_iqk_hwtx_check(dm, false);
+#if (DM_ODM_SUPPORT_TYPE & ODM_AP)
+       _iqk_iqk_fail_report_8821c(dm);
+#endif
+       halrf_iqk_dbg(dm);
+
+       if (!(*dm->mp_mode))
+               _iqk_check_coex_status(dm, false);
+       RF_DBG(dm, DBG_RF_IQK, "[IQK]final 0x49c = %x\n",
+              odm_read_1byte(dm, 0x49c));
+}
+
+void phy_dp_calibrate_8821c(void *dm_void, boolean clear)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       struct _hal_rf_ *rf = &dm->rf_table;
+
+#if (DM_ODM_SUPPORT_TYPE & (ODM_WIN))
+       if (odm_check_power_status(dm) == false)
+               return;
+#endif
+
+#if (MP_DRIVER)
+       if ((dm->mp_mode != NULL) && (rf->is_con_tx != NULL) && (rf->is_single_tone != NULL) && (rf->is_carrier_suppresion != NULL))
+               if (*(dm->mp_mode) && ((*(rf->is_con_tx) || *(rf->is_single_tone) || *(rf->is_carrier_suppresion))))
+                       return;
+#endif
+
+#if (DM_ODM_SUPPORT_TYPE == ODM_CE)
+       if (!(rf->rf_supportability & HAL_RF_DPK))
+               return;
+#endif
+
+#if DISABLE_BB_RF
+       return;
+#endif
+
+       RF_DBG(dm, DBG_RF_IQK, "[DPK] In PHY, dm->dpk_en == %x\n", rf->dpk_en);
+
+       /*if dpk is not enable*/
+       if (rf->dpk_en == 0x0)
+               return;
+
+       /*start*/
+       if (!dm->rf_calibrate_info.is_iqk_in_progress) {
+               odm_acquire_spin_lock(dm, RT_IQK_SPINLOCK);
+               dm->rf_calibrate_info.is_iqk_in_progress = true;
+               odm_release_spin_lock(dm, RT_IQK_SPINLOCK);
+               if (*dm->mp_mode)
+                       dm->rf_calibrate_info.iqk_start_time = odm_get_current_time(dm);
+
+               if (*dm->mp_mode) {
+                       /*do DPK*/
+                       _phy_dpd_calibrate_8821c(dm, clear);
+                       _dpk_toggle_rxagc(dm, clear);
+               }
+
+               if (*dm->mp_mode) {
+                       dm->rf_calibrate_info.iqk_progressing_time = odm_get_progressing_time(dm, dm->rf_calibrate_info.iqk_start_time);
+                       RF_DBG(dm, DBG_RF_IQK,
+                              "[DPK]DPK progressing_time = %lld ms\n",
+                              dm->rf_calibrate_info.iqk_progressing_time);
+               }
+               odm_acquire_spin_lock(dm, RT_IQK_SPINLOCK);
+               dm->rf_calibrate_info.is_iqk_in_progress = false;
+               odm_release_spin_lock(dm, RT_IQK_SPINLOCK);
+       } else {
+               RF_DBG(dm, DBG_RF_IQK,
+                      "[DPK]== Return the DPK CMD, because the DPK in Progress ==\n");
+       }
+}
+void phy_txtap_calibrate_8821c(void *dm_void, boolean clear)
+{
+       u32 MAC_backup[MAC_REG_NUM_8821C], BB_backup[BB_REG_NUM_8821C], RF_backup[RF_REG_NUM_8821C][1];
+       u32 backup_mac_reg[MAC_REG_NUM_8821C] = {0x520, 0x550, 0x1518};
+       u32 backup_bb_reg[BB_REG_NUM_8821C] = {0x808, 0x90c, 0xc00, 0xcb0, 0xcb4, 0xcbc, 0x1990, 0x9a4, 0xa04};
+       u32 backup_rf_reg[RF_REG_NUM_8821C] = {0xdf, 0xde, 0x8f, 0x0, 0x1};
+
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       struct dm_iqk_info *iqk_info = &dm->IQK_info;
+
+#if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
+       struct _ADAPTER *adapter = dm->adapter;
+
+#if (MP_DRIVER == 1)
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
+       PMPT_CONTEXT p_mpt_ctx = &(adapter->MptCtx);
+#else
+#ifdef CONFIG_MP_INCLUDED
+       PMPT_CONTEXT p_mpt_ctx = &(adapter->mppriv.mpt_ctx);
+#endif
+#endif
+#endif
+
+       struct _hal_rf_ *rf = &dm->rf_table;
+
+#if (DM_ODM_SUPPORT_TYPE == ODM_CE)
+       if (!(rf->rf_supportability & HAL_RF_IQK))
+               return;
+#endif
+
+#if (DM_ODM_SUPPORT_TYPE & (ODM_WIN))
+       if (odm_check_power_status(adapter) == false)
+               return;
+#endif
+
+#if MP_DRIVER == 1
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
+       if (p_mpt_ctx->bSingleTone || p_mpt_ctx->bCarrierSuppression)
+               return;
+#else
+#ifdef CONFIG_MP_INCLUDED
+       if (p_mpt_ctx->is_single_tone || p_mpt_ctx->is_carrier_suppression)
+               return;
+#endif
+#endif
+#endif
+#endif
+
+       if (!(*dm->mp_mode))
+               _iqk_check_coex_status(dm, true);
+
+       if ((dm->rf_table.rf_supportability & HAL_RF_TXGAPK))
+               if (iqk_info->lok_fail[RF_PATH_A] == 0 &&
+                   iqk_info->iqk_fail_report[0][RF_PATH_A][TXIQK] == 0 &&
+                   iqk_info->iqk_fail_report[0][RF_PATH_A][RXIQK] == 0) {
+                       _iqk_backup_iqk_8821c(dm, 0x0, 0x0);
+                       _iqk_backup_mac_bb_8821c(dm, MAC_backup, BB_backup, backup_mac_reg, backup_bb_reg, BB_REG_NUM_8821C);
+                       _iqk_backup_rf_8821c(dm, RF_backup, backup_rf_reg);
+
+                       _iqk_configure_macbb_8821c(dm);
+                       _iqk_afe_setting_8821c(dm, true);
+                       _iqk_rfe_setting_8821c(dm, false);
+                       _iqk_agc_bnd_int_8821c(dm);
+                       _iqk_rfsetting_8821c(dm);
+
+                       _phy_txgapk_calibrate_8821c(dm, RF_PATH_A);
+
+                       _iqk_afe_setting_8821c(dm, false);
+                       _iqk_restore_mac_bb_8821c(dm, MAC_backup, BB_backup, backup_mac_reg, backup_bb_reg, BB_REG_NUM_8821C);
+                       _iqk_restore_rf_8821c(dm, backup_rf_reg, RF_backup);
+               }
+}
+void dpk_temperature_compensate_8821c(void *dm_void)
+{
+       struct dm_struct *dm = (struct dm_struct *)dm_void;
+       struct _hal_rf_ *rf = &dm->rf_table;
+#if !(DM_ODM_SUPPORT_TYPE & ODM_AP)
+       void *adapter = dm->adapter;
+       HAL_DATA_TYPE *hal_data = GET_HAL_DATA(((PADAPTER)adapter));
+       u8 pgthermal = hal_data->eeprom_thermal_meter;
+#else
+       struct rtl8192cd_priv *priv = dm->priv;
+       u8 pgthermal = (u8)priv->pmib->dot11RFEntry.ther;
+
+#endif
+       static u8 dpk_tm_trigger;
+       u8 thermal_value = 0, delta_dpk, i = 0;
+       u8 thermal_value_avg_count = 0;
+       u8 thermal_value_avg_times = 2;
+       u32 thermal_value_avg = 0;
+       u8 tmp, abs_temperature;
+
+       /*if dpk is not enable*/
+       if (rf->dpk_en == 0x0)
+               return;
+       /*if ap mode, disable dpk*/
+       if (DM_ODM_SUPPORT_TYPE & ODM_AP)
+               return;
+       if (!dpk_tm_trigger) {
+               odm_set_rf_reg(dm, RF_PATH_A, RF_0x42, BIT(17) | BIT(16), 0x03);
+#if 0
+               /*RF_DBG(dm, DBG_RF_IQK, "[DPK] (1) Trigger Thermal Meter!!\n");*/
+#endif
+               dpk_tm_trigger = 1;
+               return;
+       }
+
+       /* Initialize */
+       dpk_tm_trigger = 0;
+#if 0
+       /*RF_DBG(dm, DBG_RF_IQK, "[DPK] (2) calculate the thermal !!\n");
+       */
+#endif
+
+       /* calculate average thermal meter */
+       thermal_value = (u8)odm_get_rf_reg(dm, RF_PATH_A, RF_0x42, 0xfc00); /*0x42: RF Reg[15:10] 88E*/
+       RF_DBG(dm, DBG_RF_IQK, "[DPK] (3) current Thermal Meter = %d\n",
+              thermal_value);
+
+       dm->rf_calibrate_info.thermal_value_dpk = thermal_value;
+       dm->rf_calibrate_info.thermal_value_avg[dm->rf_calibrate_info.thermal_value_avg_index] = thermal_value;
+       dm->rf_calibrate_info.thermal_value_avg_index++;
+       if (dm->rf_calibrate_info.thermal_value_avg_index == thermal_value_avg_times)
+               dm->rf_calibrate_info.thermal_value_avg_index = 0;
+       for (i = 0; i < thermal_value_avg_times; i++) {
+               if (dm->rf_calibrate_info.thermal_value_avg[i]) {
+                       thermal_value_avg += dm->rf_calibrate_info.thermal_value_avg[i];
+                       thermal_value_avg_count++;
+               }
+       }
+       if (thermal_value_avg_count) /*Calculate Average thermal_value after average enough times*/
+               thermal_value = (u8)(thermal_value_avg / thermal_value_avg_count);
+       /* compensate the DPK */
+       delta_dpk = (thermal_value > pgthermal) ? (thermal_value - pgthermal) : (pgthermal - thermal_value);
+       tmp = (u8)((dpk_result[0] & 0x00001f00) >> 8);
+       RF_DBG(dm, DBG_RF_IQK,
+              "[DPK] (5)delta_dpk = %d, eeprom_thermal_meter = %d, tmp=%d\n",
+              delta_dpk, pgthermal, tmp);
+
+       if (thermal_value > pgthermal) {
+               abs_temperature = thermal_value - pgthermal;
+               if (abs_temperature >= 20)
+                       tmp = tmp + 4;
+               else if (abs_temperature >= 15)
+                       tmp = tmp + 3;
+               else if (abs_temperature >= 10)
+                       tmp = tmp + 2;
+               else if (abs_temperature >= 5)
+                       tmp = tmp + 1;
+       } else { /*low temperature*/
+               abs_temperature = pgthermal - thermal_value;
+               if (abs_temperature >= 20)
+                       tmp = tmp - 4;
+               else if (abs_temperature >= 15)
+                       tmp = tmp - 3;
+               else if (abs_temperature >= 10)
+                       tmp = tmp - 2;
+               else if (abs_temperature >= 5)
+                       tmp = tmp - 1;
+       }
+
+       odm_set_bb_reg(dm, R_0x1bd0, BIT(12) | BIT(11) | BIT(10) | BIT(9) | BIT(8), tmp);
+       RF_DBG(dm, DBG_RF_IQK,
+              "[DPK] (6)delta_dpk = %d, eeprom_thermal_meter = %d, new tmp=%d, 0x1bd0=0x%x\n",
+              delta_dpk, pgthermal, tmp, odm_read_4byte(dm, 0x1bd0));
+}
+
+#endif