/****************************************************************************** * * Copyright(c) 2007 - 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. * * The full GNU General Public License is included in this distribution in the * file called LICENSE. * * Contact Information: * wlanfae * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, * Hsinchu 300, Taiwan. * * Larry Finger * *****************************************************************************/ #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 (RTL8822C_SUPPORT == 1) /*---------------------------Define Local Constant---------------------------*/ /*8822C DPK ver:0x20 20200106*/ static u32 _btc_wait_indirect_reg_ready_8822c( struct dm_struct *dm) { u32 delay_count = 0; u16 i; /* wait for ready bit before access 0x1700 */ while (1) { if ((odm_read_1byte(dm, 0x1703) & BIT(5)) == 0) { for (i = 0; i < 500; i++) /*delay 10ms*/ ODM_delay_us(20); if (++delay_count >= 10) break; } else { break; } } return delay_count; } static u32 _btc_read_indirect_reg_8822c( struct dm_struct *dm, u16 reg_addr) { u32 delay_count = 0; /* wait for ready bit before access 0x1700 */ _btc_wait_indirect_reg_ready_8822c(dm); odm_write_4byte(dm, 0x1700, 0x800F0000 | reg_addr); return odm_read_4byte(dm, 0x1708); /* get read data */ } static void _btc_write_indirect_reg_8822c( struct dm_struct *dm, u16 reg_addr, u32 bit_mask, u32 reg_value) { u32 val, i = 0, bitpos = 0, delay_count = 0; if (bit_mask == 0x0) return; if (bit_mask == 0xffffffff) { /* wait for ready bit before access 0x1700 */ _btc_wait_indirect_reg_ready_8822c(dm); /* put write data */ odm_write_4byte(dm, 0x1704, reg_value); 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 = _btc_read_indirect_reg_8822c(dm, reg_addr); val = (val & (~bit_mask)) | (reg_value << bitpos); /* wait for ready bit before access 0x1700 */ _btc_wait_indirect_reg_ready_8822c(dm); odm_write_4byte(dm, 0x1704, val); /* put write data */ odm_write_4byte(dm, 0x1700, 0xc00F0000 | reg_addr); } } void btc_set_gnt_wl_bt_8822c( void *dm_void, boolean is_before_k) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; if (is_before_k) { dpk_info->gnt_control = odm_get_mac_reg(dm, R_0x70, MASKDWORD); dpk_info->gnt_value = _btc_read_indirect_reg_8822c(dm, 0x38); /*force GNT control to WL*/ odm_set_mac_reg(dm, R_0x70, BIT(26), 0x1); /*force GNT_WL=1, GNT_BT=0*/ _btc_write_indirect_reg_8822c(dm, 0x38, 0xFF00, 0x77); #if 0 RF_DBG(dm, DBG_RF_DPK, "[DPK] ori 0x70 / 0x38 = 0x%x / 0x%x\n", dpk_info->gnt_control, dpk_info->gnt_value); RF_DBG(dm, DBG_RF_DPK, "[DPK] set 0x70/0x38 = 0x%x/0x%x\n", odm_get_mac_reg(dm, R_0x70, MASKDWORD), _btc_read_indirect_reg_8822c(dm, 0x38)); #endif } else { _btc_write_indirect_reg_8822c(dm, 0x38, MASKDWORD, dpk_info->gnt_value); odm_set_mac_reg(dm, R_0x70, MASKDWORD, dpk_info->gnt_control); #if 0 RF_DBG(dm, DBG_RF_DPK, "[DPK] load 0x70 / 0x38 = 0x%x / 0x%x\n", odm_get_mac_reg(dm, R_0x70, MASKDWORD), _btc_read_indirect_reg_8822c(dm, 0x38)); #endif } } void _backup_mac_bb_registers_8822c( struct dm_struct *dm, u32 *reg, u32 *reg_backup, u32 reg_num) { u32 i; for (i = 0; i < reg_num; i++) { reg_backup[i] = odm_read_4byte(dm, reg[i]); #if 0 RF_DBG(dm, DBG_RF_DPK, "[DPK] Backup MAC/BB 0x%x = 0x%x\n", reg[i], reg_backup[i]); #endif } } void _backup_rf_registers_8822c( struct dm_struct *dm, u32 *rf_reg, u32 rf_reg_backup[][2]) { u32 i; for (i = 0; i < DPK_RF_REG_NUM_8822C; i++) { rf_reg_backup[i][RF_PATH_A] = odm_get_rf_reg(dm, RF_PATH_A, rf_reg[i], RFREG_MASK); rf_reg_backup[i][RF_PATH_B] = odm_get_rf_reg(dm, RF_PATH_B, rf_reg[i], RFREG_MASK); #if 0 RF_DBG(dm, DBG_RF_DPK, "[DPK] Backup RF_A 0x%x = 0x%x\n", rf_reg[i], rf_reg_backup[i][RF_PATH_A]); RF_DBG(dm, DBG_RF_DPK, "[DPK] Backup RF_B 0x%x = 0x%x\n", rf_reg[i], rf_reg_backup[i][RF_PATH_B]); #endif } } void _reload_mac_bb_registers_8822c( struct dm_struct *dm, u32 *reg, u32 *reg_backup, u32 reg_num) { struct dm_dpk_info *dpk_info = &dm->dpk_info; u32 i; /*toggle IGI*/ odm_write_4byte(dm, 0x1d70, 0x50505050); for (i = 0; i < reg_num; i++) { odm_write_4byte(dm, reg[i], reg_backup[i]); #if 0 RF_DBG(dm, DBG_RF_DPK, "[DPK] Reload MAC/BB 0x%x = 0x%x\n", reg[i], reg_backup[i]); #endif } odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0xc); /*subpage 2*/ odm_set_bb_reg(dm, R_0x1bd4, 0x000000f0, 0x4); /*force CLK off for power saving*/ } void _reload_rf_registers_8822c( struct dm_struct *dm, u32 *rf_reg, u32 rf_reg_backup[][2]) { u32 i, rf_reg_8f[DPK_RF_PATH_NUM_8822C] = {0x0}; for (i = 0; i < DPK_RF_REG_NUM_8822C; i++) { odm_set_rf_reg(dm, RF_PATH_A, rf_reg[i], RFREG_MASK, rf_reg_backup[i][RF_PATH_A]); odm_set_rf_reg(dm, RF_PATH_B, rf_reg[i], RFREG_MASK, rf_reg_backup[i][RF_PATH_B]); #if 0 RF_DBG(dm, DBG_RF_DPK, "[DPK] Reload RF_A 0x%x = 0x%x\n", rf_reg[i], rf_reg_backup[i][RF_PATH_A]); RF_DBG(dm, DBG_RF_DPK, "[DPK] Reload RF_B 0x%x = 0x%x\n", rf_reg[i], rf_reg_backup[i][RF_PATH_B]); #endif } #if 0 /*reload RF 0x8f for non-saving power mode*/ for (i = 0; i < DPK_RF_PATH_NUM_8822C; i++) { rf_reg_8f[i] = odm_get_rf_reg(dm, (enum rf_path)i, RF_0x8f, 0x00fff); odm_set_rf_reg(dm, (enum rf_path)i, RF_0x8f, RFREG_MASK, 0xa8000 | rf_reg_8f[i]); } #endif } void _dpk_information_8822c( struct dm_struct *dm) { struct dm_dpk_info *dpk_info = &dm->dpk_info; u32 reg_rf18; if (odm_get_bb_reg(dm, R_0x1e7c, BIT(30))) dpk_info->is_tssi_mode = true; else dpk_info->is_tssi_mode = false; reg_rf18 = odm_get_rf_reg(dm, RF_PATH_A, RF_0x18, RFREG_MASK); dpk_info->dpk_band = (u8)((reg_rf18 & BIT(16)) >> 16); /*0/1:G/A*/ dpk_info->dpk_ch = (u8)reg_rf18 & 0xff; dpk_info->dpk_bw = (u8)((reg_rf18 & 0x3000) >> 12); /*3/2/1:20/40/80*/ RF_DBG(dm, DBG_RF_DPK, "[DPK] TSSI/ Band/ CH/ BW = %d / %s / %d / %s\n", dpk_info->is_tssi_mode, dpk_info->dpk_band == 0 ? "2G" : "5G", dpk_info->dpk_ch, dpk_info->dpk_bw == 3 ? "20M" : (dpk_info->dpk_bw == 2 ? "40M" : "80M")); } void _dpk_rxbb_dc_cal_8822c( struct dm_struct *dm, u8 path) { u8 i; odm_set_rf_reg(dm, (enum rf_path)path, 0x92, RFREG_MASK, 0x84800); ODM_delay_us(5); odm_set_rf_reg(dm, (enum rf_path)path, 0x92, RFREG_MASK, 0x84801); for (i = 0; i < 30; i++) /*delay 600us*/ ODM_delay_us(20); odm_set_rf_reg(dm, (enum rf_path)path, 0x92, RFREG_MASK, 0x84800); } u8 _dpk_dc_corr_check_8822c( struct dm_struct *dm, u8 path) { struct dm_dpk_info *dpk_info = &dm->dpk_info; u16 dc_i, dc_q; u8 corr_val, corr_idx; odm_write_4byte(dm, 0x1bd4, 0x000900F0); dc_i = (u16)odm_get_bb_reg(dm, 0x1bfc, 0x0fff0000); dc_q = (u16)odm_get_bb_reg(dm, 0x1bfc, 0x00000fff); if (dc_i >> 11 == 1) dc_i = 0x1000 - dc_i; if (dc_q >> 11 == 1) dc_q = 0x1000 - dc_q; RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d DC I/Q, = %d / %d\n", path, dc_i, dc_q); dpk_info->dc_i[path] = dc_i; dpk_info->dc_q[path] = dc_q; odm_write_4byte(dm, 0x1bd4, 0x000000F0); corr_idx = (u8)odm_get_bb_reg(dm, 0x1bfc, 0x000000ff); corr_val = (u8)odm_get_bb_reg(dm, 0x1bfc, 0x0000ff00); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d Corr_idx / Corr_val = %d / %d\n", path, corr_idx, corr_val); dpk_info->corr_idx[path] = corr_idx; dpk_info->corr_val[path] = corr_val; if ((dc_i > 200) || (dc_q > 200) || (corr_idx < 40) || (corr_idx > 65)) return 1; else return 0; } void _dpk_tx_pause_8822c( struct dm_struct *dm) { u8 reg_rf0_a, reg_rf0_b; u16 count = 0; odm_write_1byte(dm, R_0x522, 0xff); odm_set_bb_reg(dm, R_0x1e70, 0x0000000f, 0x2); /*hw tx stop*/ reg_rf0_a = (u8)odm_get_rf_reg(dm, RF_PATH_A, RF_0x00, 0xF0000); reg_rf0_b = (u8)odm_get_rf_reg(dm, RF_PATH_B, RF_0x00, 0xF0000); while (((reg_rf0_a == 2) || (reg_rf0_b == 2)) && count < 2500) { reg_rf0_a = (u8)odm_get_rf_reg(dm, RF_PATH_A, RF_0x00, 0xF0000); reg_rf0_b = (u8)odm_get_rf_reg(dm, RF_PATH_B, RF_0x00, 0xF0000); ODM_delay_us(2); count++; } RF_DBG(dm, DBG_RF_DPK, "[DPK] Tx pause!!\n"); } void _dpk_mac_bb_setting_8822c( struct dm_struct *dm) { struct dm_dpk_info *dpk_info = &dm->dpk_info; _dpk_tx_pause_8822c(dm); if (dpk_info->is_tssi_mode) { odm_set_bb_reg(dm, R_0x1e7c, BIT(30), 0x0); odm_set_bb_reg(dm, R_0x18a4, BIT(28), 0x0); odm_set_bb_reg(dm, R_0x41a4, BIT(28), 0x0); } odm_set_bb_reg(dm, R_0x1e24, BIT(17), 0x1); /*r_gothrough_iqkdpk*/ odm_set_bb_reg(dm, R_0x1d58, 0xff8, 0x1ff); /*BB CCA off*/ /*r_rftxen_gck_force*/ odm_set_bb_reg(dm, R_0x1864, BIT(31), 0x1); odm_set_bb_reg(dm, R_0x4164, BIT(31), 0x1); /*r_dis_sharerx_txgat*/ odm_set_bb_reg(dm, R_0x180c, BIT(27), 0x1); odm_set_bb_reg(dm, R_0x410c, BIT(27), 0x1); odm_set_bb_reg(dm, R_0x186c, BIT(7), 0x1); odm_set_bb_reg(dm, R_0x416c, BIT(7), 0x1); odm_set_bb_reg(dm, R_0x180c, BIT(1) | BIT(0), 0x0); odm_set_bb_reg(dm, R_0x410c, BIT(1) | BIT(0), 0x0); odm_set_bb_reg(dm, R_0x1a14, 0x300, 0x3); /*CCK RXIQ weighting=0*/ odm_set_bb_reg(dm, R_0x80c, 0x0000000f, 0x8); /*freq shap filter*/ /*odm_write_1byte(dm, R_0x820, 0x33);*/ odm_set_bb_reg(dm, R_0x824, 0x000f0000, 0x3); odm_set_bb_reg(dm, R_0x824, 0x0f000000, 0x3); RF_DBG(dm, DBG_RF_DPK, "[DPK] MAC/BB setting for DPK mode\n"); } void _dpk_manual_txagc_8822c( struct dm_struct *dm, boolean is_manual) { odm_set_bb_reg(dm, R_0x18a4, BIT(7), is_manual); odm_set_bb_reg(dm, R_0x41a4, BIT(7), is_manual); } void _dpk_set_txagc_8822c( struct dm_struct *dm) { odm_set_bb_reg(dm, R_0x18a0, 0x007C0000, 0x1f); odm_set_bb_reg(dm, R_0x41a0, 0x007C0000, 0x1f); odm_set_bb_reg(dm, 0x18e8, 0x0001F000, 0x1f); odm_set_bb_reg(dm, 0x41e8, 0x0001F000, 0x1f); } void _dpk_afe_setting_8822c( struct dm_struct *dm, boolean is_do_dpk) { struct dm_dpk_info *dpk_info = &dm->dpk_info; if (is_do_dpk) { odm_set_bb_reg(dm, R_0x1c38, MASKDWORD, 0xFFFFFFFF); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x700f0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x700f0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x701f0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x702f0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x703f0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x704f0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x705f0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x706f0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x707f0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x708f0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x709f0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70af0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70bf0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70cf0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70df0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70ef0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70ff0001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70ff0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x700f0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x700f0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x701f0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x702f0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x703f0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x704f0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x705f0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x706f0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x707f0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x708f0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x709f0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70af0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70bf0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70cf0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70df0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70ef0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70ff0001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70ff0001); RF_DBG(dm, DBG_RF_DPK, "[DPK] AFE for DPK mode\n"); } else { if (dpk_info->is_tssi_mode) { odm_set_bb_reg(dm, R_0x1c38, MASKDWORD, 0xf7d5005e); odm_set_bb_reg(dm, R_0x1860, 0x00007000, 0x4 >> dpk_info->dpk_band); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x700b8041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x701f0040 | (0x4 >> dpk_info->dpk_band)); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x702f0040 | (0x4 >> dpk_info->dpk_band)); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x703f0040 | (0x4 >> dpk_info->dpk_band)); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x704f0040 | (0x4 >> dpk_info->dpk_band)); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x705b8041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x706f0040 | (0x4 >> dpk_info->dpk_band)); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x700b8041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x701f0040 | (0x4 >> dpk_info->dpk_band)); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x702f0040 | (0x4 >> dpk_info->dpk_band)); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x703f0040 | (0x4 >> dpk_info->dpk_band)); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x704f0040 | (0x4 >> dpk_info->dpk_band)); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x705b8041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x706f0040 | (0x4 >> dpk_info->dpk_band)); RF_DBG(dm, DBG_RF_DPK, "[DPK] AFE for TSSI mode\n"); } else { odm_set_bb_reg(dm, R_0x1c38, MASKDWORD, 0xFFA1005E); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x700b8041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70144041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70244041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70344041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70444041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x705b8041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70644041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x700b8041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70144041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70244041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70344041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70444041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x705b8041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70644041); RF_DBG(dm, DBG_RF_DPK, "[DPK] AFE for non-TSSI mode\n"); } odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x707b8041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x708b8041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x709b8041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70ab8041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70bb8041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70cb8041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70db8041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70eb8041); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70fb8041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x707b8041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x708b8041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x709b8041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70ab8041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70bb8041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70cb8041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70db8041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70eb8041); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70fb8041); } } void _dpk_pre_setting_8822c( struct dm_struct *dm) { struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 path; for (path = 0; path < DPK_RF_PATH_NUM_8822C; path++) { odm_set_rf_reg(dm, (enum rf_path)path, RF_0x19, RFREG_MASK, 0x0); odm_set_bb_reg(dm, R_0x1b00, MASKDWORD, 0x8 | (path << 1)); if (dpk_info->dpk_band == 0x0) /*txagc bnd*/ odm_set_bb_reg(dm, R_0x1b60, MASKDWORD, 0x1f100000); else odm_set_bb_reg(dm, R_0x1b60, MASKDWORD, 0x1f0d0000); odm_set_bb_reg(dm, R_0x1b44, 0x00007000, 0x4); /*GL = val*0.5+1*/ odm_set_bb_reg(dm, R_0x1b20, 0xc0000000, 0x3); /*CFIR to TX*/ } odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0xc); /*one-shot 6ms*/ odm_set_bb_reg(dm, R_0x1be4, MASKDWORD, 0x3b23170b); odm_set_bb_reg(dm, R_0x1be8, MASKDWORD, 0x775f5347); } u32 _dpk_rf_setting_8822c( struct dm_struct *dm, u8 path) { struct dm_dpk_info *dpk_info = &dm->dpk_info; s8 txidx_offset = 0x0; u32 value32 = 0, ori_txbb = 0; u8 i; #if 0 if (phydm_set_bb_dbg_port(dm, DBGPORT_PRI_1, 0x944 | (path << 9))) { value32 = phydm_get_bb_dbg_port_val(dm); phydm_release_bb_dbg_port(dm); } txidx_offset = (value32 >> 8) & 0x7f; if ((txidx_offset >> 6) == 1) txidx_offset = (txidx_offset - 0x80) / 4; else txidx_offset = txidx_offset / 4; RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d txidx_offset = 0x%x\n", path, txidx_offset); #endif if (dpk_info->dpk_band == 0x0) { /*2G*/ /*TXAGC for gainloss*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x00, RFREG_MASK, 0x50017 + txidx_offset); ori_txbb = odm_get_rf_reg(dm, (enum rf_path)path, RF_0x56, RFREG_MASK); /*debug TX Gain*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0xde, BIT(16), 0x1); /*debug power trim*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0xde, BIT(19), 0x1); /*set offset to zero*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x55, 0x7C000, 0x0); odm_set_rf_reg(dm, (enum rf_path)path, RF_0x56, RFREG_MASK, ori_txbb); /*ATT Gain*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x55, BIT(4) | BIT(3) | BIT(2), 0x1); /*mixer*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x87, BIT(18), 0x0); /*PGA2*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x00, 0x003e0, 0xf); } else { /*5G*/ /*TXAGC for gainloss*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x00, RFREG_MASK, 0x50017 + txidx_offset); ori_txbb = odm_get_rf_reg(dm, (enum rf_path)path, RF_0x56, RFREG_MASK); /*debug TX Gain*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0xde, BIT(16), 0x1); /*debug power trim*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0xde, BIT(19), 0x1); /*set offset to zero*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x55, 0x7C000, 0x0); odm_set_rf_reg(dm, (enum rf_path)path, RF_0x56, RFREG_MASK, ori_txbb); /*ATT Gain*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x63, BIT(15) | BIT(14), 0x0); odm_set_rf_reg(dm, (enum rf_path)path, RF_0x63, BIT(4) | BIT(3) | BIT(2), 0x6); /*switch*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x63, BIT(13) | BIT(12), 0x1); /*mixer*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x8a, BIT(4) | BIT(3), 0x0); /*PGA2*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x00, 0x003e0, 0xf); } /*Bypass RXBB filter*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0xde, BIT(2), 0x1); /*BW of RXBB*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x1a, BIT(11) | BIT(10), 0x0); /*BW of TXBB*/ if (dpk_info->dpk_bw == 0x1) /*80M*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x1a, BIT(14) | BIT(13) | BIT(12), 0x2); else odm_set_rf_reg(dm, (enum rf_path)path, RF_0x1a, BIT(14) | BIT(13) | BIT(12), 0x1); odm_set_rf_reg(dm, (enum rf_path)path, RF_0x8f, BIT(1), 0x1); RF_DBG(dm, DBG_RF_DPK, "[DPK] ori TXAGC/TXBB/offset = 0x%x / 0x%x / %+d\n", odm_get_rf_reg(dm, (enum rf_path)path, RF_0x00, 0x0001f), odm_get_rf_reg(dm, (enum rf_path)path, RF_0x56, 0x0001f), (ori_txbb & 0x1f) - 0xf); /*txagc 0x17 = txbb 0xf*/ for (i = 0; i < 5; i++) /*delay 100us for TIA SV loop*/ ODM_delay_us(20); return ori_txbb & 0x1f; } u8 _dpk_one_shot_8822c( struct dm_struct *dm, u8 path, u8 action) { struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 temp = 0x0, bw = 0x0, reg_2d9c = 0x0, sync_done = 0x0, result = 0; u16 dpk_cmd = 0x0, count = 0; if (dpk_info->dpk_bw == 0x1) /*80M*/ bw = 2; else bw = 0; if (action == GAIN_LOSS) temp = 0x14 + path; else if (action == DO_DPK) temp = 0x16 + path + bw; else if (action == DPK_ON) temp = 0x1a + path; else if (action == DAGC) temp = 0x1c + path + bw; btc_set_gnt_wl_bt_8822c(dm, true); if (action ==0) { odm_set_bb_reg(dm, R_0x1bb4, BIT(12), 0x1); odm_set_bb_reg(dm, R_0x1bb4, BIT(12), 0x0); odm_set_bb_reg(dm, R_0x1bd4, 0x001f0000, 0x0); ODM_delay_us(20); sync_done = (u8)odm_get_bb_reg(dm, R_0x1bfc, BIT(31)); while (sync_done != 0x1 && count < 1000) { ODM_delay_us(20); sync_done = (u8)odm_get_bb_reg(dm, R_0x1bfc, BIT(31)); count++; } } else { odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0x8 | (path << 1)); odm_set_bb_reg(dm, R_0x1bcc, 0x0000003f, 0x9); /*ItQt -6dB*/ dpk_cmd = (temp << 8) | 0x48; odm_set_bb_reg(dm, R_0x1b00, MASKDWORD, dpk_cmd); odm_set_bb_reg(dm, R_0x1b00, MASKDWORD, dpk_cmd + 1); reg_2d9c = odm_read_1byte(dm, R_0x2d9c); while (reg_2d9c != 0x55 && count < 1000) { ODM_delay_us(20); reg_2d9c = odm_read_1byte(dm, R_0x2d9c); count++; } odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0x8 | (path << 1)); odm_set_bb_reg(dm, R_0x1bcc, 0x0000003f, 0x0); /*ItQt 0dB*/ } RF_DBG(dm, DBG_RF_DPK, "[DPK] one-shot for S%d %s = 0x%x (count=%d)\n", path, action == 1 ? "GL" : (action == 2 ? "DO_DPK" : (action == 3 ? "DPK_ON" : (action == 0 ? "Cal_PWR" : "DAGC"))), dpk_cmd, count); if (count == 1000) { RF_DBG(dm, DBG_RF_DPK, "[DPK] one-shot over 20ms!!!!\n"); result = 1; } btc_set_gnt_wl_bt_8822c(dm, false); odm_write_1byte(dm, 0x1b10, 0x0); return result; } u16 _dpk_dgain_read_8822c( struct dm_struct *dm, u8 path) { u16 dgain = 0x0; odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0xc); /*subpage 2*/ odm_set_bb_reg(dm, R_0x1bd4, 0x00ff0000, 0x0); dgain = (u16)odm_get_bb_reg(dm, R_0x1bfc, 0x0FFF0000); /*[27:16]*/ RF_DBG(dm, DBG_RF_DPK, "[DPK] DGain = 0x%x (%d)\n", dgain, dgain); return dgain; } u8 _dpk_thermal_read_8822c( void *dm_void, u8 path) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; odm_set_rf_reg(dm, (enum rf_path)path, RF_0x42, BIT(19), 0x1); odm_set_rf_reg(dm, (enum rf_path)path, RF_0x42, BIT(19), 0x0); odm_set_rf_reg(dm, (enum rf_path)path, RF_0x42, BIT(19), 0x1); ODM_delay_us(15); return (u8)odm_get_rf_reg(dm, (enum rf_path)path, RF_0x42, 0x0007e); } u32 _dpk_pas_read_8822c( struct dm_struct *dm, u8 path, u8 action) { u8 k; u32 reg_1bfc, i_val = 0, q_val = 0; odm_set_bb_reg(dm, R_0x1b00, MASKDWORD, 0x8 | (path << 1)); odm_set_bb_reg(dm, R_0x1b48, BIT(14), 0x0); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x00060001); odm_set_bb_reg(dm, R_0x1b4c, MASKDWORD, 0x00000000); switch (action) { case LOSS_CHK: odm_set_bb_reg(dm, R_0x1b4c, MASKDWORD, 0x00080000); q_val = odm_get_bb_reg(dm, R_0x1bfc, MASKHWORD); i_val = odm_get_bb_reg(dm, R_0x1bfc, MASKLWORD); if (i_val >> 15 != 0) i_val = 0x10000 - i_val; if (q_val >> 15 != 0) q_val = 0x10000 - q_val; #if (DPK_PAS_CHK_DBG_8822C) RF_DBG(dm, DBG_RF_DPK, "[DPK][%s] i=0x%x,q=0x%x,i^2+q^2=0x%x\n", "LOSS", i_val, q_val, i_val*i_val + q_val*q_val); #endif break; case PAS_READ: for (k = 0; k < 64; k++) { odm_set_bb_reg(dm, R_0x1b4c, MASKDWORD, (0x00080000 | (k << 24))); #if 0 RF_DBG(dm, DBG_RF_DPK, "[DPK] 0x1b4c[%d] = 0x%x\n", k, odm_get_bb_reg(dm, R_0x1b4c, MASKDWORD)); #endif reg_1bfc = odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD); RF_DBG(dm, DBG_RF_DPK, "[DPK] PA scan_S%d = 0x%08x\n", path, reg_1bfc); } break; default: break; } odm_set_bb_reg(dm, R_0x1b4c, MASKDWORD, 0x00000000); return i_val*i_val + q_val*q_val; } u8 _dpk_gainloss_result_8822c( struct dm_struct *dm, u8 path) { u8 result; odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0x8 | (path << 1)); odm_set_bb_reg(dm, R_0x1b48, BIT(14), 0x1); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x00060000); result = (u8)odm_get_bb_reg(dm, R_0x1bfc, 0x000000f0); odm_set_bb_reg(dm, R_0x1b48, BIT(14), 0x0); RF_DBG(dm, DBG_RF_DPK, "[DPK] tmp GL = %d\n", result); return result; } u8 _dpk_agc_chk_8822c( struct dm_struct *dm, u8 path, u8 limited_pga, u8 check) { u8 result = 0; u16 dgain =0; u32 loss = 0; u32 loss_db = 0; if (check == GAIN_CHK) { _dpk_one_shot_8822c(dm, path, DAGC); dgain = _dpk_dgain_read_8822c(dm, path); if ((dgain > 1535) && !limited_pga) { /*DGain > 1535 happen*/ RF_DBG(dm, DBG_RF_DPK, "[DPK] Small DGain!!\n"); result = 2; return result; } else if ((dgain < 768) && !limited_pga) { /*DGain < 768 happen*/ RF_DBG(dm, DBG_RF_DPK, "[DPK] Large DGain!!\n"); result = 1; return result; } else return result; } else if (check == LOSS_CHK) { loss = _dpk_pas_read_8822c(dm, path, LOSS_CHK); if (loss < 0x4000000) { RF_DBG(dm, DBG_RF_DPK, "[DPK] GLoss < 0dB happen!!\n"); result = 4; return result; } loss_db = 3 * halrf_psd_log2base(loss >> 13); #if (DPK_PAS_CHK_DBG_8822C) RF_DBG(dm, DBG_RF_DPK, "[DPK] GLoss = %d.%02ddB\n", (loss_db - 3870) / 100, (loss_db -3870) % 100); #endif if ((loss_db - 3870) > 1000) { /*GL > 10dB*/ RF_DBG(dm, DBG_RF_DPK, "[DPK] GLoss > 10dB happen!!\n"); result = 3; return result; } else if ((loss_db - 3870) < 250) { /*GL < 2.5dB*/ RF_DBG(dm, DBG_RF_DPK, "[DPK] GLoss < 2.5dB happen!!\n"); result = 4; return result; } else return result; } else return result; } u8 _dpk_pas_agc_8822c( struct dm_struct *dm, u8 path, u8 gain_only, u8 loss_only) { u8 tmp_txbb = 0, tmp_pga = 0, i = 0; u8 goout = 0, limited_pga = 0, agc_cnt = 0; do { switch (i) { case 0: /*Gain check first*/ tmp_txbb = (u8)odm_get_rf_reg(dm, (enum rf_path)path, RF_0x56, 0x0001f); tmp_pga = (u8)odm_get_rf_reg(dm, (enum rf_path)path, RF_0x00, 0x003e0); RF_DBG(dm, DBG_RF_DPK, "[DPK][AGC] Start TXBB=0x%x, PGA=0x%x\n", tmp_txbb, tmp_pga); if (loss_only) i = 5; else { i = _dpk_agc_chk_8822c(dm, path, limited_pga, GAIN_CHK); if ((i == 0) && gain_only) goout = 1; else if (i == 0) i =5; } agc_cnt++; break; case 1: /*Gain > criterion*/ if (tmp_pga > 0xe) { odm_set_rf_reg(dm, (enum rf_path)path, RF_0x00, 0x003e0, 0xc); RF_DBG(dm, DBG_RF_DPK, "[DPK][AGC] PGA(-1) = 0xc\n"); } else if ((0xb < tmp_pga) && (tmp_pga < 0xf)) { odm_set_rf_reg(dm, (enum rf_path)path, RF_0x00, 0x003e0, 0x0); RF_DBG(dm, DBG_RF_DPK, "[DPK][AGC] PGA(-1) = 0x0\n"); } else if (tmp_pga < 0xc) { RF_DBG(dm, DBG_RF_DPK, "[DPK][AGC] PGA@ lower bound!!\n"); limited_pga = 1; } i = 0; break; case 2: /*Gain < criterion*/ if (tmp_pga < 0xc) { odm_set_rf_reg(dm, (enum rf_path)path, RF_0x00, 0x003e0, 0xc); RF_DBG(dm, DBG_RF_DPK, "[DPK][AGC] PGA(+1) = 0xc\n"); } else if ((0xb < tmp_pga) && (tmp_pga < 0xf)) { odm_set_rf_reg(dm, (enum rf_path)path, RF_0x00, 0x003e0, 0xf); RF_DBG(dm, DBG_RF_DPK, "[DPK][AGC] PGA(+1) = 0xf\n"); } else if (tmp_pga > 0xe) { RF_DBG(dm, DBG_RF_DPK, "[DPK][AGC] PGA@ upper bound!!\n"); limited_pga = 1; } i = 0; break; case 3: /*GL > criterion*/ if (tmp_txbb == 0x0) { goout = 1; RF_DBG(dm, DBG_RF_DPK, "[DPK][AGC] TXBB@ lower bound!!\n"); break; } tmp_txbb = tmp_txbb - 2; odm_set_rf_reg(dm, (enum rf_path)path, RF_0x56, 0x0001f, tmp_txbb); RF_DBG(dm, DBG_RF_DPK, "[DPK][AGC] TXBB(-2) = 0x%x\n", tmp_txbb); limited_pga = 0; i = 0; break; case 4: /*GL < criterion*/ if (tmp_txbb == 0x1f) { goout = 1; RF_DBG(dm, DBG_RF_DPK, "[DPK][AGC] TXBB@ upper bound!!\n"); break; } tmp_txbb = tmp_txbb + 3; odm_set_rf_reg(dm, (enum rf_path)path, RF_0x56, 0x0001f, tmp_txbb); RF_DBG(dm, DBG_RF_DPK, "[DPK][AGC] TXBB(+3) = 0x%x\n", tmp_txbb); limited_pga = 0; i = 0; break; case 5: /*Loss check*/ _dpk_one_shot_8822c(dm, path, GAIN_LOSS); i = _dpk_agc_chk_8822c(dm, path, limited_pga, LOSS_CHK); #if (DPK_PAS_DBG_8822C) _dpk_pas_read_8822c(dm, path, PAS_READ); #endif if (i == 0) goout = 1; break; default: goout = 1; break; } } while (!goout && (agc_cnt < 6)); return tmp_txbb; } boolean _dpk_coef_iq_check_8822c( struct dm_struct *dm, u16 coef_i, u16 coef_q) { if ((coef_i == 0x1000) || (coef_i == 0x0fff) || (coef_q == 0x1000) || (coef_q == 0x0fff)) return 1; else return 0; } u32 _dpk_coef_transfer_8822c( void *dm_void) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; u32 reg_1bfc = 0; u16 coef_i = 0, coef_q = 0; reg_1bfc = odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD); #if (DPK_COEF_DBG_8822C) RF_DBG(dm, DBG_RF_DPK, "[DPK][coef_r] 0x1bfc = 0x%08x\n", reg_1bfc); #endif #if 1 coef_i = (u16)odm_get_bb_reg(dm, R_0x1bfc, MASKHWORD) & 0x1fff; coef_q = (u16)odm_get_bb_reg(dm, R_0x1bfc, MASKLWORD) & 0x1fff; coef_q = ((0x2000 - coef_q) & 0x1fff) - 1; reg_1bfc = (coef_i << 16) | coef_q; #endif return reg_1bfc; } void _dpk_get_coef_8822c( void *dm_void, u8 path) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; odm_set_bb_reg(dm, R_0x1b00, MASKDWORD, 0x0000000c); if (path == RF_PATH_A) { odm_set_bb_reg(dm, R_0x1bb4, BIT(24), 0x0); odm_set_bb_reg(dm, R_0x1b04, MASKDWORD, 0x30000080); } else if (path == RF_PATH_B) { odm_set_bb_reg(dm, R_0x1bb4, BIT(24), 0x1); odm_set_bb_reg(dm, R_0x1b5c, MASKDWORD, 0x30000080); } odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x000400F0); dpk_info->coef[path][0] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x040400F0); dpk_info->coef[path][1] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x080400F0); dpk_info->coef[path][2] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x010400F0); dpk_info->coef[path][3] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x050400F0); dpk_info->coef[path][4] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x090400F0); dpk_info->coef[path][5] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x020400F0); dpk_info->coef[path][6] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x060400F0); dpk_info->coef[path][7] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x0A0400F0); dpk_info->coef[path][8] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x030400F0); dpk_info->coef[path][9] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x070400F0); dpk_info->coef[path][10] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x0B0400F0); dpk_info->coef[path][11] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x0C0400F0); dpk_info->coef[path][12] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x100400F0); dpk_info->coef[path][13] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x0D0400F0); dpk_info->coef[path][14] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x110400F0); dpk_info->coef[path][15] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x0E0400F0); dpk_info->coef[path][16] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x120400F0); dpk_info->coef[path][17] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x0F0400F0); dpk_info->coef[path][18] = _dpk_coef_transfer_8822c(dm); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x130400F0); dpk_info->coef[path][19] = _dpk_coef_transfer_8822c(dm); } u8 _dpk_coef_read_8822c( void *dm_void, u8 path) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 addr, result = 1; u16 coef_i, coef_q; for (addr = 0; addr < 20; addr++) { coef_i = (u16)((dpk_info->coef[path][addr] & 0x1fff0000) >> 16); coef_q = (u16)(dpk_info->coef[path][addr] & 0x1fff); if (_dpk_coef_iq_check_8822c(dm, coef_i, coef_q)) { result = 0; break; } } return result; } void _dpk_coef_write_8822c( void *dm_void, u8 path, u8 result) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 addr; u16 tmp_reg; u32 coef; odm_set_bb_reg(dm, R_0x1b00, MASKDWORD, 0x0000000c); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x000000F0); for (addr = 0; addr < 20; addr++) { if (path == RF_PATH_A) tmp_reg = 0x1b0c + addr * 4; else tmp_reg = 0x1b64 + addr * 4; if (!result) { if (addr == 3) coef = 0x04001fff; else coef = 0x00001fff; } else coef = dpk_info->coef[path][addr]; odm_set_bb_reg(dm, tmp_reg, MASKDWORD, coef); #if (DPK_COEF_DBG_8822C) RF_DBG(dm, DBG_RF_DPK, "[DPK][coef_w] S%d 0x%x = 0x%08x\n", path, tmp_reg, coef); #endif } } void _dpk_coef1_read_8822c( void *dm_void, u8 path) { struct dm_struct *dm = (struct dm_struct *)dm_void; odm_set_bb_reg(dm, R_0x1bb4, BIT(24), path); odm_set_bb_reg(dm, 0x1b04 + path * 0x58, BIT(29) | BIT(28), 0x1); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x000400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x040400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x080400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x010400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x050400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x090400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x020400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x060400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x0A0400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x030400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x070400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x0B0400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x0C0400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x100400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x0D0400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x110400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x0E0400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x120400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x0F0400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x130400F0); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d coef1 = 0x%08x\n", path, odm_get_bb_reg(dm, R_0x1bfc, MASKDWORD)); odm_set_bb_reg(dm, 0x1b04 + path * 0x58, 0xf0000000, 0x0); /*disable manual coef*/ } void _dpk_coef_default_8822c( void *dm_void, u8 path) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 addr; u16 tmp_reg; u32 coef; odm_set_bb_reg(dm, R_0x1b00, MASKDWORD, 0x0000000c); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x000000F0); for (addr = 0; addr < 20; addr++) { if (path == RF_PATH_A) tmp_reg = 0x1b0c + addr * 4; else tmp_reg = 0x1b64 + addr * 4; if (addr == 3) coef = 0x04001fff; else coef = 0x00001fff; odm_set_bb_reg(dm, tmp_reg, MASKDWORD, coef); RF_DBG(dm, DBG_RF_DPK, "[DPK][Coef write] 0x%x = 0x%x\n", tmp_reg, coef); } } void _dpk_fill_result_8822c( void *dm_void, u32 dpk_txagc, u8 path, u8 result) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0x8 | (path << 1)); if (result) /*check PASS*/ odm_write_1byte(dm, R_0x1b67, (u8)(dpk_txagc - 6)); /*ItQt -6dB*/ else odm_write_1byte(dm, R_0x1b67, 0x00); dpk_info->result[path] = result; dpk_info->dpk_txagc[path] = odm_read_1byte(dm, R_0x1b67); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d 0x1b67 = 0x%x\n", path, odm_read_1byte(dm, R_0x1b67)); _dpk_coef_write_8822c(dm, path, result); } u32 _dpk_gainloss_8822c( struct dm_struct *dm, u8 path) { struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 k = 0, tx_agc_search = 0x0, t1 = 0, t2 = 0; u8 tx_agc, tx_bb, ori_txbb, ori_txagc; s8 txidx_offset = 0x0; ori_txbb = (u8)_dpk_rf_setting_8822c(dm, path); ori_txagc = (u8)odm_get_rf_reg(dm, (enum rf_path)path, RF_0x00, 0x0001f); _dpk_rxbb_dc_cal_8822c(dm, path); /*DCK for DPK*/ _dpk_one_shot_8822c(dm, path, DAGC); _dpk_dgain_read_8822c(dm, path); if (_dpk_dc_corr_check_8822c(dm, path)) { _dpk_rxbb_dc_cal_8822c(dm, path); /*re-do DCK for DPK*/ _dpk_one_shot_8822c(dm, path, DAGC); _dpk_dc_corr_check_8822c(dm, path); } t1 = _dpk_thermal_read_8822c(dm, path); #if 1 tx_bb = _dpk_pas_agc_8822c(dm, path, false, true); #else _dpk_one_shot_8822c(dm, path, GAIN_LOSS); #endif #if 0 RF_DBG(dm, DBG_RF_DPK, "[DPK][GL] S%d RF_0x0=0x%x, 0x63=0x%x, 0x8a=0x%x, 0x1a=0x%x, 0x8f=0x%x\n", path, odm_get_rf_reg(dm, (enum rf_path)path, RF_0x00, RFREG_MASK), odm_get_rf_reg(dm, (enum rf_path)path, RF_0x63, RFREG_MASK), odm_get_rf_reg(dm, (enum rf_path)path, RF_0x8a, RFREG_MASK), odm_get_rf_reg(dm, (enum rf_path)path, RF_0x1a, RFREG_MASK), odm_get_rf_reg(dm, (enum rf_path)path, RF_0x8f, RFREG_MASK)); #endif tx_agc_search = _dpk_gainloss_result_8822c(dm, path); if (tx_bb < tx_agc_search) /*aviod txbb < 0*/ tx_bb = 0; else tx_bb = tx_bb - tx_agc_search; odm_set_rf_reg(dm, (enum rf_path)path, RF_0x56, 0x0001f, tx_bb); tx_agc = ori_txagc - (ori_txbb - tx_bb); RF_DBG(dm, DBG_RF_DPK, "[DPK][GL] S%d TXAGC=0x%x, TXBB=0x%x\n", path, tx_agc, tx_bb); t2 = _dpk_thermal_read_8822c(dm, path); dpk_info->thermal_dpk_delta[path] = HALRF_ABS(t2, t1); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d thermal delta of GL = %d (%d - %d)\n", path, dpk_info->thermal_dpk_delta[path], t2, t1); return tx_agc; } u8 _dpk_by_path_8822c( struct dm_struct *dm, u32 tx_agc, u8 path) { struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 result = 1; u16 dc_i, dc_q; #if 0 tx_agc = (odm_get_rf_reg(dm, (enum rf_path)path, RF_0x00, RFREG_MASK) & ~0x1f) | tx_agc; RF_DBG(dm, DBG_RF_DPK, "[DPK][DO_DPK] RF0x0 = 0x%x\n", tx_agc); /*TXAGC for DPK*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x00, RFREG_MASK, tx_agc); RF_DBG(dm, DBG_RF_DPK, "[DPK][GL] S%d RF 0x63=0x%x, 0x8a=0x%x, 0x1a=0x%x, 0x8f=0x%x\n", path, odm_get_rf_reg(dm, (enum rf_path)path, RF_0x63, RFREG_MASK), odm_get_rf_reg(dm, (enum rf_path)path, RF_0x8a, RFREG_MASK), odm_get_rf_reg(dm, (enum rf_path)path, RF_0x1a, RFREG_MASK), odm_get_rf_reg(dm, (enum rf_path)path, RF_0x8f, RFREG_MASK)); #endif result = _dpk_one_shot_8822c(dm, path, DO_DPK); odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0x8 | (path << 1)); result = result | (u8)odm_get_bb_reg(dm, R_0x1b08, BIT(26)); RF_DBG(dm, DBG_RF_DPK, "[DPK][DO_DPK] DPK Fail = %x\n", result); /*set RX high gain for RXBB DCK*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x00, RFREG_MASK, 0x33e14); _dpk_get_coef_8822c(dm, path); #if 0 odm_write_4byte(dm, 0x1bd4, 0x000900F0); dc_i = (u16)odm_get_bb_reg(dm, 0x1bfc, 0x0fff0000); dc_q = (u16)odm_get_bb_reg(dm, 0x1bfc, 0x00000fff); if (dc_i >> 11 == 1) dc_i = 0x1000 - dc_i; if (dc_q >> 11 == 1) dc_q = 0x1000 - dc_q; RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d DC i/q = %d / %d\n", path, dc_i, dc_q); #endif #if (DPK_PAS_DBG_8822C) _dpk_pas_read_8822c(dm, path, PAS_READ); #endif return result; } void _dpk_cal_gs_8822c( struct dm_struct *dm, u8 path) { struct dm_dpk_info *dpk_info = &dm->dpk_info; u16 tmp_gs = 0; odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0x8 | (path << 1)); odm_set_bb_reg(dm, R_0x1b20, BIT(25), 0x0); /*BypassDPD=0*/ odm_set_bb_reg(dm, R_0x1b20, 0xc0000000, 0x0); /* disable CFIR to TX*/ odm_set_bb_reg(dm, R_0x1bcc, 0x0000003f, 0x9); /* ItQt shift 1 bit*/ odm_set_bb_reg(dm, R_0x1bcc, BIT(21), 0x1); /* inner loopback*/ odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0xc); odm_set_bb_reg(dm, R_0x1bd4, 0x000000f0, 0xf); if (path == RF_PATH_A) { /*manual pwsf+gs*/ odm_set_bb_reg(dm, R_0x1b04, 0x0fffffff, 0x1066680); /*enable MDPD*/ odm_set_bb_reg(dm, R_0x1b08, BIT(31), 0x1); } else { odm_set_bb_reg(dm, R_0x1b5c, 0x0fffffff, 0x1066680); odm_set_bb_reg(dm, R_0x1b60, BIT(31), 0x1); } if (dpk_info->dpk_bw == 0x1) { /*80M*/ /*TPG DC*/ odm_write_4byte(dm, R_0x1bf8, 0x80001310); odm_write_4byte(dm, R_0x1bf8, 0x00001310); odm_write_4byte(dm, R_0x1bf8, 0x810000DB); odm_write_4byte(dm, R_0x1bf8, 0x010000DB); odm_write_4byte(dm, R_0x1bf8, 0x0000B428); /*set TPG*/ odm_write_4byte(dm, R_0x1bf4, 0x05020000 | (BIT(path) << 28)); } else { odm_write_4byte(dm, R_0x1bf8, 0x8200190C); odm_write_4byte(dm, R_0x1bf8, 0x0200190C); odm_write_4byte(dm, R_0x1bf8, 0x8301EE14); odm_write_4byte(dm, R_0x1bf8, 0x0301EE14); odm_write_4byte(dm, R_0x1bf8, 0x0000B428); odm_write_4byte(dm, R_0x1bf4, 0x05020008 | (BIT(path) << 28)); } odm_set_bb_reg(dm, R_0x1bb4, 0xff000000, 0x8 | path); _dpk_one_shot_8822c(dm, path, 0); /*restore*/ odm_set_bb_reg(dm, R_0x1bf4, 0xff000000, 0x0); /*TPG off*/ odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0x8 | (path << 1)); odm_set_bb_reg(dm, R_0x1bcc, 0xc000003f, 0x0); /* ItQt*/ odm_set_bb_reg(dm, R_0x1bcc, BIT(21), 0x0); /* inner loopback off*/ odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0xc); if (path == RF_PATH_A) odm_set_bb_reg(dm, R_0x1b04, 0x0fffffff, 0x5b); else odm_set_bb_reg(dm, R_0x1b5c, 0x0fffffff, 0x5b); odm_set_bb_reg(dm, R_0x1bd4, 0x001f0000, 0x0); tmp_gs = (u16)odm_get_bb_reg(dm, R_0x1bfc, 0x0FFF0000); #if 0 RF_DBG(dm, DBG_RF_DPK, "[DPK] tmp_gs = 0x%x\n", tmp_gs); #endif tmp_gs = (tmp_gs * 910) >> 10; /*910 = 0x5b * 10*/ if ((tmp_gs % 10) >= 5) tmp_gs = tmp_gs / 10 + 1; else tmp_gs = tmp_gs / 10; if (path == RF_PATH_A) odm_set_bb_reg(dm, R_0x1b04, 0x0fffffff, tmp_gs); else odm_set_bb_reg(dm, R_0x1b5c, 0x0fffffff, tmp_gs); dpk_info->dpk_gs[path] = tmp_gs; } void _dpk_cal_coef1_8822c( struct dm_struct *dm) { struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 reg_2d9c, path; u16 count = 0; u32 i_scaling; odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0x0000000c); odm_set_bb_reg(dm, R_0x1bd4, MASKDWORD, 0x000000F0); /*force comp clk on*/ odm_set_bb_reg(dm, R_0x1b00, MASKDWORD, 0x00001148); odm_set_bb_reg(dm, R_0x1b00, MASKDWORD, 0x00001149); reg_2d9c = odm_read_1byte(dm, R_0x2d9c); while (reg_2d9c != 0x55 && count < 1000) { ODM_delay_us(20); reg_2d9c = odm_read_1byte(dm, R_0x2d9c); count++; } RF_DBG(dm, DBG_RF_DPK, "[DPK] one-shot for Cal_coef1 (count=%d)\n", count); odm_write_1byte(dm, 0x1b10, 0x0); odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0x0000000c); for (path = 0; path < DPK_RF_PATH_NUM_8822C; path++) { i_scaling = 0x16c00 / dpk_info->dpk_gs[path]; /*0x16c00 = 0x400 * 0x5b*/ RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d i_scaling = 0x%x\n", path, i_scaling); /*write 4th I value*/ odm_set_bb_reg(dm, 0x1b18 + path * 0x58, MASKHWORD, i_scaling); /*load coef to coef1*/ odm_set_bb_reg(dm, 0x1b04 + path * 0x58, 0xf0000000, 0x9); odm_set_bb_reg(dm, 0x1b04 + path * 0x58, 0xf0000000, 0x1); odm_set_bb_reg(dm, 0x1b04 + path * 0x58, 0xf0000000, 0x0); /*enable 2nd coef*/ odm_set_bb_reg(dm, 0x1b08 + path * 0x58, BIT(14), 0x0); /*0:enable; 1:bypass*/ #if DPK_COEF_DBG_8822C _dpk_coef1_read_8822c(dm, path); #endif } } void _dpk_on_8822c( struct dm_struct *dm, u8 path) { struct dm_dpk_info *dpk_info = &dm->dpk_info; _dpk_one_shot_8822c(dm, path, DPK_ON); odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0x8 | (path << 1)); odm_set_bb_reg(dm, R_0x1b20, 0xc0000000, 0x0); /* disable CFIR to TX*/ if ((dpk_info->dpk_path_ok & BIT(path)) >> path) _dpk_cal_gs_8822c(dm, path); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d DPD on!!!\n\n", path); } void dpk_coef_read_8822c( void *dm_void) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 path, addr; RF_DBG(dm, DBG_RF_DPK, "[DPK] ========= Coef Read Start =========\n"); for (path = 0; path < DPK_RF_PATH_NUM_8822C; path++) { for (addr = 0; addr < 20; addr++) RF_DBG(dm, DBG_RF_DPK, "[DPK] Read S%d coef[%02d]= 0x%08x\n", path, addr, dpk_info->coef[path][addr]); } RF_DBG(dm, DBG_RF_DPK, "[DPK] ========= Coef Read Finish =========\n"); } u8 _dpk_check_fail_8822c( struct dm_struct *dm, boolean is_fail, u32 dpk_txagc, u8 path) { struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 result; if (!is_fail) if (_dpk_coef_read_8822c(dm, path)) result = 1; /*check PASS*/ else result = 0; /*check FAIL*/ else result = 0; /*check FAIL*/ _dpk_fill_result_8822c(dm, dpk_txagc, path, result); return result; } void _dpk_result_reset_8822c( struct dm_struct *dm) { struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 path; dpk_info->dpk_path_ok = 0; for (path = 0; path < DPK_RF_PATH_NUM_8822C; path++) { odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0x8 | (path << 1)); odm_set_bb_reg(dm, R_0x1b58, 0x0000007f, 0x0); dpk_info->dpk_txagc[path] = 0; dpk_info->result[path] = 0; dpk_info->dpk_gs[path] = 0x5b; dpk_info->pre_pwsf[path] = 0; dpk_info->thermal_dpk[path] = _dpk_thermal_read_8822c(dm, path); RF_DBG(dm, DBG_RF_DPK, "[DPK] init thermal S%d = %d\n", path, dpk_info->thermal_dpk[path]); #if 0 RF_DBG(dm, DBG_RF_DPK, "[DPK][reset] S%d pwsf=0x%x, dpk_result=%d\n", path, dpk_info->pwsf[path], dpk_info->result[path], #endif } } void _dpk_calibrate_8822c( struct dm_struct *dm, u8 path) { struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 dpk_fail = 1, retry_cnt; u32 dpk_txagc = 0; RF_DBG(dm, DBG_RF_DPK, "[DPK] =========== S%d DPK Start ===========\n", path); for (retry_cnt = 0; retry_cnt < 1; retry_cnt++) { RF_DBG(dm, DBG_RF_DPK, "[DPK] retry = %d\n", retry_cnt); dpk_txagc = _dpk_gainloss_8822c(dm, path); dpk_fail = _dpk_by_path_8822c(dm, dpk_txagc, path); if (_dpk_check_fail_8822c(dm, dpk_fail, dpk_txagc, path)) break; } RF_DBG(dm, DBG_RF_DPK, "[DPK] =========== S%d DPK Finish ==========\n", path); if (dpk_info->result[path]) dpk_info->dpk_path_ok = dpk_info->dpk_path_ok | BIT(path); } void _dpk_path_select_8822c( struct dm_struct *dm) { struct dm_dpk_info *dpk_info = &dm->dpk_info; #if (DPK_PATH_A_8822C) _dpk_calibrate_8822c(dm, RF_PATH_A); #endif #if (DPK_PATH_B_8822C) _dpk_calibrate_8822c(dm, RF_PATH_B); #endif _dpk_on_8822c(dm, RF_PATH_A); _dpk_on_8822c(dm, RF_PATH_B); _dpk_cal_coef1_8822c(dm); } void _dpk_result_summary_8822c( struct dm_struct *dm) { struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 path; RF_DBG(dm, DBG_RF_DPK, "[DPK] ======== DPK Result Summary =======\n"); for (path = 0; path < DPK_RF_PATH_NUM_8822C; path++) { RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d dpk_txagc = 0x%x, dpk_result = %d\n", path, dpk_info->dpk_txagc[path], dpk_info->result[path]); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d gain scaling = 0x%x\n", path, dpk_info->dpk_gs[path]); RF_DBG(dm, DBG_RF_DPK, "[DPK] S%d DPK is %s\n", path, ((dpk_info->dpk_path_ok & BIT(path)) >> path) ? "Success" : "Fail"); } RF_DBG(dm, DBG_RF_DPK, "[DPK] dpk_path_ok = 0x%x\n", dpk_info->dpk_path_ok); RF_DBG(dm, DBG_RF_DPK, "[DPK] ======== DPK Result Summary =======\n"); } void _dpk_reload_data_8822c( void *dm_void) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 path; if ((dpk_info->dpk_path_ok == 0) && (dpk_info->dpk_ch == 0)) return; /*never do DPK before*/ for (path = 0; path < DPK_RF_PATH_NUM_8822C; path++) { odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0x8 | (path << 1)); if (dpk_info->dpk_band == 0x0) /*txagc bnd*/ odm_set_bb_reg(dm, R_0x1b60, MASKDWORD, 0x1f100000); else odm_set_bb_reg(dm, R_0x1b60, MASKDWORD, 0x1f0d0000); odm_write_1byte(dm, R_0x1b67, dpk_info->dpk_txagc[path]); _dpk_coef_write_8822c(dm, path, (dpk_info->dpk_path_ok & BIT(path)) >> path); _dpk_one_shot_8822c(dm, path, DPK_ON); odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0xc); if (path == RF_PATH_A) odm_set_bb_reg(dm, R_0x1b04, 0x0fffffff, dpk_info->dpk_gs[0]); else odm_set_bb_reg(dm, R_0x1b5c, 0x0fffffff, dpk_info->dpk_gs[1]); } _dpk_cal_coef1_8822c(dm); } u8 dpk_reload_8822c( void *dm_void) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; u8 channel; dpk_info->is_reload = false; channel = (u8)(odm_get_rf_reg(dm, RF_PATH_A, RF_0x18, RFREG_MASK) & 0xff); if (channel == dpk_info->dpk_ch) { RF_DBG(dm, DBG_RF_DPK, "[DPK] DPK reload for CH%d!!\n", dpk_info->dpk_ch); _dpk_reload_data_8822c(dm); dpk_info->is_reload = true; } return dpk_info->is_reload; } void _dpk_by_fw_8822c( struct dm_struct *dm) { enum hal_status status = HAL_STATUS_FAILURE; RF_DBG(dm, DBG_RF_DPK, "[DPK] DPK by FW !!\n"); status = odm_dpk_by_fw(dm); if (status == HAL_STATUS_SUCCESS) RF_DBG(dm, DBG_RF_DPK, "[DPK] FW DPK Trigger OK!!!\n"); else RF_DBG(dm, DBG_RF_DPK, "[DPK] FW DPK Trigger Fail!!!\n"); } void _dpk_force_bypass_8822c( void *dm_void) { struct dm_struct *dm = (struct dm_struct *)dm_void; odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0xc); /*subpage 2*/ odm_set_bb_reg(dm, R_0x1b08, BIT(15) | BIT(14), 0x3); odm_set_bb_reg(dm, R_0x1b04, 0x000000ff, 0x5b); RF_DBG(dm, DBG_RF_DPK, "[DPK] S0 DPK bypass !!!\n"); odm_set_bb_reg(dm, R_0x1b60, BIT(15) | BIT(14), 0x3); odm_set_bb_reg(dm, R_0x1b5c, 0x000000ff, 0x5b); RF_DBG(dm, DBG_RF_DPK, "[DPK] S1 DPK bypass !!!\n"); } void _rx_dc_cal_8822c( struct dm_struct *dm) { u32 bb_reg_backup[7]; u32 bb_reg[7] = { R_0x520, R_0x1d58, R_0x180c, R_0x410c, R_0x1a14, R_0x1e70, R_0x1d70}; u8 path; _backup_mac_bb_registers_8822c(dm, bb_reg, bb_reg_backup, 7); _dpk_tx_pause_8822c(dm); odm_set_bb_reg(dm, R_0x1d58, 0xff8, 0x1ff); /*BB CCA off*/ odm_set_bb_reg(dm, R_0x180c, BIT(1) | BIT(0), 0x0); odm_set_bb_reg(dm, R_0x410c, BIT(1) | BIT(0), 0x0); odm_set_bb_reg(dm, R_0x1a14, 0x300, 0x3); /*CCK RXIQ weighting=0*/ for (path = 0; path < 2; path++) { /*set RX high gain for RXBB DCK*/ odm_set_rf_reg(dm, (enum rf_path)path, RF_0x00, RFREG_MASK, 0x33e14); _dpk_rxbb_dc_cal_8822c(dm, path); /*DCK for DPK*/ } _reload_mac_bb_registers_8822c(dm, bb_reg, bb_reg_backup, 7); } void do_dpk_8822c( void *dm_void) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; struct _hal_rf_ *rf = &dm->rf_table; u32 bb_reg_backup[DPK_BB_REG_NUM_8822C]; u32 rf_reg_backup[DPK_RF_REG_NUM_8822C][DPK_RF_PATH_NUM_8822C]; u32 bb_reg[DPK_BB_REG_NUM_8822C] = { R_0x520, R_0x820, R_0x824, R_0x1c3c, R_0x1d58, R_0x1864, R_0x4164, R_0x180c, R_0x410c, R_0x186c, R_0x416c, R_0x1a14, R_0x1e70, R_0x80c, R_0x1d70, R_0x1e7c, R_0x18a4, R_0x41a4}; u32 rf_reg[DPK_RF_REG_NUM_8822C] = { RF_0x19, RF_0x1a, RF_0x55, RF_0x63, RF_0x87, RF_0x8f, RF_0xde}; if (rf->ext_pa && (*dm->band_type == ODM_BAND_2_4G)) { RF_DBG(dm, DBG_RF_DPK, "[DPK] Skip DPK due to ext_PA exist!!\n"); _dpk_force_bypass_8822c(dm); _rx_dc_cal_8822c(dm); return; } else if (rf->ext_pa_5g && (*dm->band_type == ODM_BAND_5G)) { RF_DBG(dm, DBG_RF_DPK, "[DPK] Skip DPK due to 5G_ext_PA exist!!\n"); _dpk_force_bypass_8822c(dm); _rx_dc_cal_8822c(dm); return; } else if (!dpk_info->is_dpk_pwr_on) { RF_DBG(dm, DBG_RF_DPK, "[DPK] Skip DPK due to DPD PWR off !!\n"); return; } else if (!(*dm->mp_mode) && (dm->fw_offload_ability & PHYDM_RF_DPK_OFFLOAD)) { _dpk_by_fw_8822c(dm); return; } else if (!(*dm->mp_mode) && dpk_reload_8822c(dm)) return; RF_DBG(dm, DBG_RF_DPK, "[DPK] ****** DPK Start (Ver: %s), Cut: %d ******\n", DPK_VER_8822C, dm->cut_version); _dpk_information_8822c(dm); _backup_mac_bb_registers_8822c(dm, bb_reg, bb_reg_backup, DPK_BB_REG_NUM_8822C); _backup_rf_registers_8822c(dm, rf_reg, rf_reg_backup); _dpk_mac_bb_setting_8822c(dm); _dpk_afe_setting_8822c(dm, true); _dpk_manual_txagc_8822c(dm, true); _dpk_pre_setting_8822c(dm); _dpk_result_reset_8822c(dm); _dpk_path_select_8822c(dm); _dpk_result_summary_8822c(dm); _dpk_manual_txagc_8822c(dm, false); _dpk_afe_setting_8822c(dm, false); dpk_enable_disable_8822c(dm); _reload_rf_registers_8822c(dm, rf_reg, rf_reg_backup); halrf_rxbb_dc_cal_8822c(dm); /*DCK for Rx*/ _reload_mac_bb_registers_8822c(dm, bb_reg, bb_reg_backup, DPK_BB_REG_NUM_8822C); } void dpk_enable_disable_8822c( void *dm_void) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0xc); /*subpage 2*/ odm_set_bb_reg(dm, R_0x1b08, BIT(31), dpk_info->is_dpk_pwr_on); odm_set_bb_reg(dm, R_0x1b60, BIT(31), dpk_info->is_dpk_pwr_on); if (dpk_info->is_dpk_enable) { if (dpk_info->dpk_path_ok & BIT(0)) { odm_set_bb_reg(dm, R_0x1b08, BIT(15) | BIT(14), 0x0); odm_set_bb_reg(dm, R_0x1b04, 0x000000ff, dpk_info->dpk_gs[RF_PATH_A]); RF_DBG(dm, DBG_RF_DPK, "[DPK] S0 DPK enable !!!\n"); } if ((dpk_info->dpk_path_ok & BIT(1)) >> 1) { odm_set_bb_reg(dm, R_0x1b60, BIT(15) | BIT(14), 0x0); odm_set_bb_reg(dm, R_0x1b5c, 0x000000ff, dpk_info->dpk_gs[RF_PATH_B]); RF_DBG(dm, DBG_RF_DPK, "[DPK] S1 DPK enable !!!\n"); } } else { if (dpk_info->dpk_path_ok & BIT(0)) { odm_set_bb_reg(dm, R_0x1b08, BIT(15) | BIT(14), 0x3); odm_set_bb_reg(dm, R_0x1b04, 0x000000ff,0x5b); RF_DBG(dm, DBG_RF_DPK, "[DPK] S0 DPK bypass !!!\n"); } if ((dpk_info->dpk_path_ok & BIT(1)) >> 1) { odm_set_bb_reg(dm, R_0x1b60, BIT(15) | BIT(14), 0x3); odm_set_bb_reg(dm, R_0x1b5c, 0x000000ff,0x5b); RF_DBG(dm, DBG_RF_DPK, "[DPK] S1 DPK bypass !!!\n"); } } } void dpk_track_8822c( void *dm_void) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; struct _hal_rf_ *rf = &dm->rf_table; u8 is_increase, i = 0, k = 0, path; u8 thermal_dpk_avg_count = 0, thermal_value[2] = {0}; u32 thermal_dpk_avg[2] = {0}; s8 offset[2], delta_dpk[2]; if ((dpk_info->thermal_dpk[0] == 0) && (dpk_info->thermal_dpk[1] == 0)) { RF_DBG(dm, DBG_RF_DPK, "[DPK_track] Bypass DPK tracking!!!!\n"); return; } else RF_DBG(dm, DBG_RF_DPK | DBG_RF_TX_PWR_TRACK, "[DPK_track] =======================================\n"); /*get thermal meter*/ for (path = 0; path < DPK_RF_PATH_NUM_8822C; path++) { thermal_value[path] = _dpk_thermal_read_8822c(dm, path); RF_DBG(dm, DBG_RF_DPK | DBG_RF_TX_PWR_TRACK, "[DPK_track] S%d thermal now = %d\n", path, thermal_value[path]); } dpk_info->thermal_dpk_avg[0][dpk_info->thermal_dpk_avg_index] = thermal_value[0]; dpk_info->thermal_dpk_avg[1][dpk_info->thermal_dpk_avg_index] = thermal_value[1]; dpk_info->thermal_dpk_avg_index++; /*Average times */ if (dpk_info->thermal_dpk_avg_index == THERMAL_DPK_AVG_NUM) dpk_info->thermal_dpk_avg_index = 0; for (i = 0; i < THERMAL_DPK_AVG_NUM; i++) { if (dpk_info->thermal_dpk_avg[0][i] || dpk_info->thermal_dpk_avg[1][i]) { thermal_dpk_avg[0] += dpk_info->thermal_dpk_avg[0][i]; thermal_dpk_avg[1] += dpk_info->thermal_dpk_avg[1][i]; thermal_dpk_avg_count++; } } /*Calculate Average ThermalValue after average enough times*/ if (thermal_dpk_avg_count) { #if 0 RF_DBG(dm, DBG_RF_DPK, "[DPK_track] S0 ThermalValue_DPK_AVG (count) = %d (%d))\n", thermal_dpk_avg[0], thermal_dpk_avg_count); RF_DBG(dm, DBG_RF_DPK, "[DPK_track] S1 ThermalValue_DPK_AVG (count) = %d (%d))\n", thermal_dpk_avg[1], thermal_dpk_avg_count); #endif thermal_value[0] = (u8)(thermal_dpk_avg[0] / thermal_dpk_avg_count); thermal_value[1] = (u8)(thermal_dpk_avg[1] / thermal_dpk_avg_count); RF_DBG(dm, DBG_RF_DPK | DBG_RF_TX_PWR_TRACK, "[DPK_track] S0 thermal avg = %d (DPK @ %d)\n", thermal_value[0], dpk_info->thermal_dpk[0]); RF_DBG(dm, DBG_RF_DPK | DBG_RF_TX_PWR_TRACK, "[DPK_track] S1 thermal avg = %d (DPK @ %d)\n", thermal_value[1], dpk_info->thermal_dpk[1]); } for (path = 0; path < DPK_RF_PATH_NUM_8822C; path++) { delta_dpk[path] = dpk_info->thermal_dpk[path] - thermal_value[path]; offset[path] = (delta_dpk[path] - dpk_info->thermal_dpk_delta[path]) & 0x7f; RF_DBG(dm, DBG_RF_DPK | DBG_RF_TX_PWR_TRACK, "[DPK_track] S%d thermal_diff= %d, cal_diff= %d, offset= %d\n", path, delta_dpk[path], dpk_info->thermal_dpk_delta[path], offset[path] > 64 ? offset[path] - 128 : offset[path]); } if (rf->is_dpk_in_progress || dm->rf_calibrate_info.is_iqk_in_progress || rf->is_tssi_in_progress) return; for (path = 0; path < DPK_RF_PATH_NUM_8822C; path++) { if (offset[path] != dpk_info->pre_pwsf[path]) { odm_set_bb_reg(dm, R_0x1b00, 0x0000000f, 0x8 | (path << 1)); odm_set_bb_reg(dm, R_0x1b58, 0x0000007f, offset[path]); dpk_info->pre_pwsf[path] = offset[path]; RF_DBG(dm, DBG_RF_DPK | DBG_RF_TX_PWR_TRACK, "[DPK_track] S%d new pwsf is 0x%x, 0x1b58=0x%x\n", path, dpk_info->pre_pwsf[path], odm_get_bb_reg(dm, R_0x1b58, MASKDWORD)); } else RF_DBG(dm, DBG_RF_DPK | DBG_RF_TX_PWR_TRACK, "[DPK_track] S%d pwsf unchanged (0x%x)\n", path, dpk_info->pre_pwsf[path]); } } void dpk_info_by_8822c( void *dm_void, u32 *_used, char *output, u32 *_out_len) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; u32 used = *_used; u32 out_len = *_out_len; u8 path, addr; PDM_SNPF(out_len, used, output + used, out_len - used, " %-25s = %d / %d\n", "S0 DC (I/Q)", dpk_info->dc_i[0], dpk_info->dc_q[0]); PDM_SNPF(out_len, used, output + used, out_len - used, " %-25s = %d / %d\n", "S0 Corr (idx/val)", dpk_info->corr_idx[0], dpk_info->corr_val[0]); PDM_SNPF(out_len, used, output + used, out_len - used, " %-25s = %d / %d\n", "S1 DC (I/Q)", dpk_info->dc_i[1], dpk_info->dc_q[1]); PDM_SNPF(out_len, used, output + used, out_len - used, " %-25s = %d / %d\n", "S1 Corr (idx/val)", dpk_info->corr_idx[1], dpk_info->corr_val[1]); PDM_SNPF(out_len, used, output + used, out_len - used, " %-25s = 0x%x / 0x%x\n", "DPK TxAGC (path)", dpk_info->dpk_txagc[0], dpk_info->dpk_txagc[1]); PDM_SNPF(out_len, used, output + used, out_len - used, " %-25s = 0x%x / 0x%x\n", "DPK Gain Scaling (path)", dpk_info->dpk_gs[0], dpk_info->dpk_gs[1]); PDM_SNPF(out_len, used, output + used, out_len - used, "\n==============[ Coef Read Start ]==============\n"); for (path = 0; path < DPK_RF_PATH_NUM_8822C; path++) { for (addr = 0; addr < 20; addr++) PDM_SNPF(out_len, used, output + used, out_len - used, " Read S%d coef[%02d] = 0x%08x\n", path, addr, dpk_info->coef[path][addr]); } PDM_SNPF(out_len, used, output + used, out_len - used, "==============[ Coef Read Finish ]==============\n"); } void dpk_info_rsvd_page_8822c( void *dm_void, u8 *buf, u32 *buf_size) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; if (buf) { odm_move_memory(dm, buf, &(dpk_info->dpk_path_ok), 2); odm_move_memory(dm, buf + 2, dpk_info->dpk_txagc, 2); odm_move_memory(dm, buf + 4, dpk_info->dpk_gs, 4); odm_move_memory(dm, buf + 8, dpk_info->coef, 160); odm_move_memory(dm, buf + 168, &(dpk_info->dpk_ch), 1); } if (buf_size) *buf_size = DPK_INFO_RSVD_LEN_8822C; } void dpk_c2h_report_transfer_8822c( void *dm_void, boolean is_ok, u8 *buf, u8 buf_size) { struct dm_struct *dm = (struct dm_struct *)dm_void; struct dm_dpk_info *dpk_info = &dm->dpk_info; struct dm_dpk_c2h_report dpk_c2h_report; u8 i, j; u8 path_status = 0; if (!is_ok) { RF_DBG(dm, DBG_RF_DPK, "[DPK]FW DPK C2H data fail!!!\n"); return; } else if (buf_size < DPK_C2H_REPORT_LEN_8822C) { RF_DBG(dm, DBG_RF_DPK, "[DPK]FW DPK: error buf size(%d)!!!\n", buf_size); return; } for (i = 0; i < 2; i++) { odm_move_memory(dm, &(dpk_c2h_report.path_ok[i]), buf + i, 1); for (j = 0; j < DPK_RF_PATH_NUM_8822C; j++) { odm_move_memory(dm, &(dpk_c2h_report.therm[i][j]), buf + 2 + i + j, 1); odm_move_memory(dm, &(dpk_c2h_report.therm_delta[i][j]), buf + 6 + i + j, 1); } } for (i = 0; i < DPK_RF_PATH_NUM_8822C; i++) { dpk_info->thermal_dpk[i]= dpk_c2h_report.therm[0][i]; dpk_info->thermal_dpk_delta[i]= dpk_c2h_report.therm_delta[0][i]; } dpk_info->dpk_path_ok = dpk_c2h_report.path_ok[0]; #if 0 for (i = 0; i < 9; i++) RF_DBG(dm, DBG_RF_DPK, "[DPK] buf[%d] = 0x%x\n", i, *(buf + i)); RF_DBG(dm, DBG_RF_DPK, "[DPK] dpk_path_ok = 0x%x\n", dpk_c2h_report.path_ok[0]); RF_DBG(dm, DBG_RF_DPK, "[DPK] thermal_dpk[0] = 0x%x\n", dpk_c2h_report.therm[0][0]); RF_DBG(dm, DBG_RF_DPK, "[DPK] thermal_dpk[1] = 0x%x\n", dpk_c2h_report.therm[0][1]); RF_DBG(dm, DBG_RF_DPK, "[DPK] thermal_dpk_delta[0] = 0x%x\n", dpk_c2h_report.therm_delta[0][0]); RF_DBG(dm, DBG_RF_DPK, "[DPK] thermal_dpk_delta[1] = 0x%x\n", dpk_c2h_report.therm_delta[0][1]); #endif } #endif