/****************************************************************************** * * 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" #include "../phydm_precomp.h" #if (RTL8822C_SUPPORT) #if (PHYDM_FW_API_ENABLE_8822C) /* ======================================================================== */ /* These following functions can be used for PHY DM only*/ #ifdef CONFIG_TXAGC_DEBUG_8822C __odm_func__ boolean phydm_set_pw_by_rate_8822c(struct dm_struct *dm, s8 *pw_idx, u8 rate_idx) { u32 pw_all = 0; u8 j = 0; if (rate_idx % 4 != 0) { pr_debug("[Warning] %s\n", __func__); return false; } PHYDM_DBG(dm, ODM_PHY_CONFIG, "pow = {%d, %d, %d, %d}\n", *pw_idx, *(pw_idx - 1), *(pw_idx - 2), *(pw_idx - 3)); /* @bbrstb TX AGC report - default disable */ /* @Enable for writing the TX AGC table when bb_reset=0 */ odm_set_bb_reg(dm, R_0x1c90, BIT(15), 0x0); /* @According the rate to write in the ofdm or the cck */ /* @driver need to construct a 4-byte power index */ odm_set_bb_reg(dm, R_0x3a00 + rate_idx, MASKDWORD, pw_all); PHYDM_DBG(dm, ODM_PHY_CONFIG, "rate_idx=0x%x (REG0x%x) = 0x%x\n", rate_idx, R_0x3a00 + rate_idx, pw_all); for (j = 0; j < 4; j++) config_phydm_read_txagc_diff_8822c(dm, rate_idx + j); return true; } __odm_func__ void phydm_txagc_tab_buff_init_8822c(struct dm_struct *dm) { u8 i; for (i = 0; i < NUM_RATE_AC_2SS; i++) { dm->txagc_buff[RF_PATH_A][i] = i >> 2; dm->txagc_buff[RF_PATH_B][i] = i >> 2; } } __odm_func__ void phydm_txagc_tab_buff_show_8822c(struct dm_struct *dm) { u8 i; pr_debug("path A\n"); for (i = 0; i < NUM_RATE_AC_2SS; i++) pr_debug("[A][rate:%d] = %d\n", i, dm->txagc_buff[RF_PATH_A][i]); pr_debug("path B\n"); for (i = 0; i < NUM_RATE_AC_2SS; i++) pr_debug("[B][rate:%d] = %d\n", i, dm->txagc_buff[RF_PATH_B][i]); } #endif __odm_func__ void phydm_bb_reset_8822c(struct dm_struct *dm) { if (*dm->mp_mode) return; odm_set_mac_reg(dm, R_0x0, BIT(16), 1); odm_set_mac_reg(dm, R_0x0, BIT(16), 0); odm_set_mac_reg(dm, R_0x0, BIT(16), 1); } __odm_func__ void phydm_bb_reset_no_3wires_8822c(struct dm_struct *dm) { /* Disable bbrstb 3-wires */ odm_set_bb_reg(dm, R_0x1c90, BIT(8), 0x0); odm_set_mac_reg(dm, R_0x0, BIT(16), 1); odm_set_mac_reg(dm, R_0x0, BIT(16), 0); odm_set_mac_reg(dm, R_0x0, BIT(16), 1); /* Enable bbrstb 3-wires */ odm_set_bb_reg(dm, R_0x1c90, BIT(8), 0x1); } __odm_func__ boolean phydm_chk_pkg_set_valid_8822c(struct dm_struct *dm, u8 ver_bb, u8 ver_rf) { boolean valid = true; if (ver_bb >= 41 && ver_rf >= 23) valid = true; else if (ver_bb < 41 && ver_rf < 23) valid = true; else valid = false; if (!valid) { odm_set_bb_reg(dm, R_0x1c3c, (BIT(0) | BIT(1)), 0x0); pr_debug("[Warning][%s] Pkg_ver{bb, rf}={%d, %d} disable all BB block\n", __func__, ver_bb, ver_rf); } return valid; } __odm_func__ void phydm_igi_toggle_8822c(struct dm_struct *dm) { /* * @Toggle IGI to force BB HW send 3-wire-cmd and will let RF HW enter RX mode. * @Because BB HW does not send 3-wire command automacically when BB setting * @is changed including the configuration of path/channel/BW */ u32 igi = 0x20; /* @Do not use PHYDM API to read/write because FW can not access */ igi = odm_get_bb_reg(dm, R_0x1d70, 0x7f); odm_set_bb_reg(dm, R_0x1d70, 0x7f, igi - 2); odm_set_bb_reg(dm, R_0x1d70, 0x7f00, igi - 2); odm_set_bb_reg(dm, R_0x1d70, 0x7f, igi); odm_set_bb_reg(dm, R_0x1d70, 0x7f00, igi); } __odm_func__ u32 phydm_check_bit_mask_8822c(u32 bit_mask, u32 data_original, u32 data) { u8 bit_shift = 0; if (bit_mask != 0xfffff) { for (bit_shift = 0; bit_shift <= 19; bit_shift++) { if ((bit_mask >> bit_shift) & 0x1) break; } return (data_original & (~bit_mask)) | (data << bit_shift); } return data; } __odm_func__ u32 config_phydm_read_rf_reg_8822c(struct dm_struct *dm, enum rf_path path, u32 reg_addr, u32 bit_mask) { u32 readback_value = 0, direct_addr = 0; u32 offset_read_rf[2] = {R_0x3c00, R_0x4c00}; PHYDM_DBG(dm, ODM_PHY_CONFIG, "%s ======>\n", __func__); /* @Error handling.*/ if (path > RF_PATH_B) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Unsupported path (%d)\n", path); return INVALID_RF_DATA; } /* @Calculate offset */ reg_addr &= 0xff; direct_addr = offset_read_rf[path] + (reg_addr << 2); /* @RF register only has 20bits */ bit_mask &= RFREG_MASK; /* @Read RF register directly */ readback_value = odm_get_bb_reg(dm, direct_addr, bit_mask); PHYDM_DBG(dm, ODM_PHY_CONFIG, "RF-%d 0x%x = 0x%x, bit mask = 0x%x\n", path, reg_addr, readback_value, bit_mask); return readback_value; } __odm_func__ boolean config_phydm_direct_write_rf_reg_8822c(struct dm_struct *dm, enum rf_path path, u32 reg_addr, u32 bit_mask, u32 data) { u32 direct_addr = 0; u32 offset_write_rf[2] = {R_0x3c00, R_0x4c00}; PHYDM_DBG(dm, ODM_PHY_CONFIG, "%s ======>\n", __func__); /* @Calculate offset */ reg_addr &= 0xff; direct_addr = offset_write_rf[path] + (reg_addr << 2); /* @RF register only has 20bits */ bit_mask &= RFREG_MASK; /* @write RF register directly*/ odm_set_bb_reg(dm, direct_addr, bit_mask, data); ODM_delay_us(1); PHYDM_DBG(dm, ODM_PHY_CONFIG, "RF-%d 0x%x = 0x%x , bit mask = 0x%x\n", path, reg_addr, data, bit_mask); return true; } __odm_func__ boolean config_phydm_write_rf_reg_8822c(struct dm_struct *dm, enum rf_path path, u32 reg_addr, u32 bit_mask, u32 data) { u32 data_and_addr = 0, data_original = 0; u32 offset_write_rf[2] = {R_0x1808, R_0x4108}; boolean result = false; PHYDM_DBG(dm, ODM_PHY_CONFIG, "%s ======>\n", __func__); /* @Error handling.*/ if (path > RF_PATH_B) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Invalid path=%d\n", path); return false; } if (!(reg_addr == RF_0x0)) { result = config_phydm_direct_write_rf_reg_8822c(dm, path, reg_addr, bit_mask, data); return result; } /* @Read RF register content first */ reg_addr &= 0xff; bit_mask &= RFREG_MASK; if (bit_mask != RFREG_MASK) { data_original = config_phydm_read_rf_reg_8822c(dm, path, reg_addr, RFREG_MASK); /* @Error handling. RF is disabled */ if (!(data_original != INVALID_RF_DATA)) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Write fail, RF is disable\n"); return false; } /* @check bit mask */ data = phydm_check_bit_mask_8822c(bit_mask, data_original, data); } /* @Put write addr in [27:20] and write data in [19:00] */ data_and_addr = ((reg_addr << 20) | (data & 0x000fffff)) & 0x0fffffff; /* @Write operation */ odm_set_bb_reg(dm, offset_write_rf[path], MASKDWORD, data_and_addr); PHYDM_DBG(dm, ODM_PHY_CONFIG, "RF-%d 0x%x = 0x%x (original: 0x%x), bit mask = 0x%x\n", path, reg_addr, data, data_original, bit_mask); #if (defined(CONFIG_RUN_IN_DRV)) if (dm->support_interface == ODM_ITRF_PCIE) ODM_delay_us(13); #elif (defined(CONFIG_RUN_IN_FW)) ODM_delay_us(13); #endif return true; } __odm_func__ boolean phydm_write_txagc_1byte_8822c(struct dm_struct *dm, u32 pw_idx, u8 hw_rate) { #if (PHYDM_FW_API_FUNC_ENABLE_8822C) u32 offset_txagc = R_0x3a00; u8 rate_idx = (hw_rate & 0xfc), i = 0; u8 rate_offset = (hw_rate & 0x3); u8 ret = 0; u32 txagc_idx = 0x0; PHYDM_DBG(dm, ODM_PHY_CONFIG, "%s ======>\n", __func__); /* @For debug command only!!!! */ /* @bbrstb TX AGC report - default disable */ /* @Enable for writing the TX AGC table when bb_reset=0 */ odm_set_bb_reg(dm, R_0x1c90, BIT(15), 0x0); /* @Error handling */ if (hw_rate > 0x53) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Unsupported rate\n"); return false; } /* @For HW limitation, We can't write TXAGC once a byte. */ for (i = 0; i < 4; i++) { if (i != rate_offset) { ret = config_phydm_read_txagc_diff_8822c(dm, rate_idx + i); txagc_idx |= ret << (i << 3); } else { txagc_idx |= (pw_idx & 0x7f) << (i << 3); } } odm_set_bb_reg(dm, (offset_txagc + rate_idx), MASKDWORD, txagc_idx); PHYDM_DBG(dm, ODM_PHY_CONFIG, "rate_idx 0x%x (0x%x) = 0x%x\n", hw_rate, (offset_txagc + hw_rate), txagc_idx); return true; #else return false; #endif } __odm_func__ boolean config_phydm_write_txagc_ref_8822c(struct dm_struct *dm, u8 power_index, enum rf_path path, enum PDM_RATE_TYPE rate_type) { /* @2-path power reference */ u32 txagc_ofdm_ref[2] = {R_0x18e8, R_0x41e8}; u32 txagc_cck_ref[2] = {R_0x18a0, R_0x41a0}; PHYDM_DBG(dm, ODM_PHY_CONFIG, "%s ======>\n", __func__); /* @Input need to be HW rate index, not driver rate index!!!! */ if (dm->is_disable_phy_api) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Disable PHY API for debug\n"); return true; } /* @Error handling */ if (path > RF_PATH_B) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Unsupported path (%d)\n", path); return false; } /* @bbrstb TX AGC report - default disable */ /* @Enable for writing the TX AGC table when bb_reset=0 */ odm_set_bb_reg(dm, R_0x1c90, BIT(15), 0x0); /* @According the rate to write in the ofdm or the cck */ /* @CCK reference setting */ if (rate_type == PDM_CCK) { odm_set_bb_reg(dm, txagc_cck_ref[path], 0x007f0000, power_index); PHYDM_DBG(dm, ODM_PHY_CONFIG, "path-%d rate type %d (0x%x) = 0x%x\n", path, rate_type, txagc_cck_ref[path], power_index); /* @OFDM reference setting */ } else { odm_set_bb_reg(dm, txagc_ofdm_ref[path], 0x0001fc00, power_index); PHYDM_DBG(dm, ODM_PHY_CONFIG, "path-%d rate type %d (0x%x) = 0x%x\n", path, rate_type, txagc_ofdm_ref[path], power_index); } return true; } __odm_func__ boolean config_phydm_write_txagc_diff_8822c(struct dm_struct *dm, s8 power_index1, s8 power_index2, s8 power_index3, s8 power_index4, u8 hw_rate) { u32 offset_txagc = R_0x3a00; u8 rate_idx = hw_rate & 0xfc; /* @Extract the 0xfc */ u8 power_idx1 = 0; u8 power_idx2 = 0; u8 power_idx3 = 0; u8 power_idx4 = 0; u32 pw_all = 0; power_idx1 = power_index1 & 0x7f; power_idx2 = power_index2 & 0x7f; power_idx3 = power_index3 & 0x7f; power_idx4 = power_index4 & 0x7f; pw_all = (power_idx4 << 24) | (power_idx3 << 16) | (power_idx2 << 8) | power_idx1; PHYDM_DBG(dm, ODM_PHY_CONFIG, "%s ======>\n", __func__); /* @Input need to be HW rate index, not driver rate index!!!! */ if (dm->is_disable_phy_api) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Disable PHY API for debug\n"); return true; } /* @Error handling */ if (hw_rate > ODM_RATEVHTSS2MCS9) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Unsupported rate\n"); return false; } /* @bbrstb TX AGC report - default disable */ /* @Enable for writing the TX AGC table when bb_reset=0 */ odm_set_bb_reg(dm, R_0x1c90, BIT(15), 0x0); /* @According the rate to write in the ofdm or the cck */ /* @driver need to construct a 4-byte power index */ odm_set_bb_reg(dm, (offset_txagc + rate_idx), MASKDWORD, pw_all); PHYDM_DBG(dm, ODM_PHY_CONFIG, "rate index 0x%x (0x%x) = 0x%x\n", hw_rate, (offset_txagc + hw_rate), pw_all); return true; } #if 1 /*Will remove when FW fill TXAGC funciton well verified*/ __odm_func__ void config_phydm_set_txagc_to_hw_8822c(struct dm_struct *dm) { #if (defined(CONFIG_RUN_IN_DRV)) s8 diff_tab[2][NUM_RATE_AC_2SS]; /*power diff table of 2 paths*/ s8 diff_tab_min[NUM_RATE_AC_2SS]; u8 ref_pow_cck[2] = {dm->txagc_buff[RF_PATH_A][ODM_RATE11M], dm->txagc_buff[RF_PATH_B][ODM_RATE11M]}; u8 ref_pow_ofdm[2] = {dm->txagc_buff[RF_PATH_A][ODM_RATEMCS7], dm->txagc_buff[RF_PATH_B][ODM_RATEMCS7]}; u8 ref_pow_tmp = 0; enum rf_path path = 0; u8 i, j = 0; if (*dm->is_fcs_mode_enable) return; /* === [Reference base] =============================================*/ #ifdef CONFIG_TXAGC_DEBUG_8822C pr_debug("ref_pow_cck={%d, %d}, ref_pow_ofdm={%d, %d}\n", ref_pow_cck[0], ref_pow_cck[1], ref_pow_ofdm[0], ref_pow_ofdm[1]); #endif /*Set OFDM/CCK Ref. power index*/ config_phydm_write_txagc_ref_8822c(dm, ref_pow_cck[0], RF_PATH_A, PDM_CCK); config_phydm_write_txagc_ref_8822c(dm, ref_pow_cck[1], RF_PATH_B, PDM_CCK); config_phydm_write_txagc_ref_8822c(dm, ref_pow_ofdm[0], RF_PATH_A, PDM_OFDM); config_phydm_write_txagc_ref_8822c(dm, ref_pow_ofdm[1], RF_PATH_B, PDM_OFDM); /* === [Power By Rate] ==============================================*/ for (path = RF_PATH_A; path <= RF_PATH_B; path++) odm_move_memory(dm, diff_tab[path], dm->txagc_buff[path], NUM_RATE_AC_2SS); #ifdef CONFIG_TXAGC_DEBUG_8822C pr_debug("1. diff_tab path A\n"); for (i = 0; i <= ODM_RATEVHTSS2MCS9; i++) pr_debug("[A][rate:%d] = %d\n", i, diff_tab[RF_PATH_A][i]); pr_debug("2. diff_tab path B\n"); for (i = 0; i <= ODM_RATEVHTSS2MCS9; i++) pr_debug("[B][rate:%d] = %d\n", i, diff_tab[RF_PATH_B][i]); #endif for (path = RF_PATH_A; path <= RF_PATH_B; path++) { /*CCK*/ ref_pow_tmp = ref_pow_cck[path]; for (j = ODM_RATE1M; j <= ODM_RATE11M; j++) { diff_tab[path][j] -= (s8)ref_pow_tmp; /**/ } /*OFDM*/ ref_pow_tmp = ref_pow_ofdm[path]; for (j = ODM_RATE6M; j <= ODM_RATEMCS15; j++) { diff_tab[path][j] -= (s8)ref_pow_tmp; /**/ } for (j = ODM_RATEVHTSS1MCS0; j <= ODM_RATEVHTSS2MCS9; j++) { diff_tab[path][j] -= (s8)ref_pow_tmp; /**/ } } #ifdef CONFIG_TXAGC_DEBUG_8822C pr_debug("3. diff_tab path A\n"); for (i = 0; i <= ODM_RATEVHTSS2MCS9; i++) pr_debug("[A][rate:%d] = %d\n", i, diff_tab[RF_PATH_A][i]); pr_debug("4. diff_tab path B\n"); for (i = 0; i <= ODM_RATEVHTSS2MCS9; i++) pr_debug("[B][rate:%d] = %d\n", i, diff_tab[RF_PATH_B][i]); #endif for (i = ODM_RATE1M; i <= ODM_RATEMCS15; i++) { diff_tab_min[i] = MIN_2(diff_tab[RF_PATH_A][i], diff_tab[RF_PATH_B][i]); #ifdef CONFIG_TXAGC_DEBUG_8822C pr_debug("diff_tab_min[rate:%d]= %d\n", i, diff_tab_min[i]); #endif if (i % 4 == 3) { config_phydm_write_txagc_diff_8822c(dm, diff_tab_min[i - 3], diff_tab_min[i - 2], diff_tab_min[i - 1], diff_tab_min[i], i - 3); } } for (i = ODM_RATEVHTSS1MCS0; i <= ODM_RATEVHTSS2MCS9; i++) { diff_tab_min[i] = MIN_2(diff_tab[RF_PATH_A][i], diff_tab[RF_PATH_B][i]); #ifdef CONFIG_TXAGC_DEBUG_8822C pr_debug("diff_tab_min[rate:%d]= %d\n", i, diff_tab_min[i]); #endif if (i % 4 == 3) { config_phydm_write_txagc_diff_8822c(dm, diff_tab_min[i - 3], diff_tab_min[i - 2], diff_tab_min[i - 1], diff_tab_min[i], i - 3); } } #endif } __odm_func__ boolean config_phydm_write_txagc_8822c(struct dm_struct *dm, u32 pw_idx, enum rf_path path, u8 hw_rate) { #if (defined(CONFIG_RUN_IN_DRV)) u8 ref_rate = ODM_RATEMCS15; u8 rate; u8 fill_valid_cnt = 0; u8 i = 0; if (*dm->is_fcs_mode_enable) return false; if (dm->is_disable_phy_api) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Disable PHY API for debug\n"); return true; } if (path > RF_PATH_B) { pr_debug("[Warning 1] %s\n", __func__); return false; } if ((hw_rate > ODM_RATEMCS15 && hw_rate <= ODM_RATEMCS31) || hw_rate > ODM_RATEVHTSS2MCS9) { pr_debug("[Warning 2] %s\n", __func__); return false; } if (hw_rate <= ODM_RATEMCS15) ref_rate = ODM_RATEMCS15; else ref_rate = ODM_RATEVHTSS2MCS9; fill_valid_cnt = ref_rate - hw_rate + 1; if (fill_valid_cnt > 4) fill_valid_cnt = 4; for (i = 0; i < fill_valid_cnt; i++) { rate = hw_rate + i; if (rate > (PHY_NUM_RATE_IDX - 1)) /*Just for protection*/ break; dm->txagc_buff[path][rate] = (u8)((pw_idx >> (8 * i)) & 0xff); } #endif return true; } #endif #if 1 /*API for FW fill txagc*/ __odm_func__ void phydm_set_txagc_by_table_8822c(struct dm_struct *dm, struct txagc_table_8822c *tab) { #if (defined(CONFIG_RUN_IN_FW)) u8 i = 0; /* === [Reference base] =============================================*/ /*Set OFDM/CCK Ref. power index*/ config_phydm_write_txagc_ref_8822c(dm, tab->ref_pow_cck[0], RF_PATH_A, PDM_CCK); config_phydm_write_txagc_ref_8822c(dm, tab->ref_pow_cck[1], RF_PATH_B, PDM_CCK); config_phydm_write_txagc_ref_8822c(dm, tab->ref_pow_ofdm[0], RF_PATH_A, PDM_OFDM); config_phydm_write_txagc_ref_8822c(dm, tab->ref_pow_ofdm[1], RF_PATH_B, PDM_OFDM); for (i = ODM_RATE1M; i <= ODM_RATEMCS15; i++) { if (i % 4 == 3) { config_phydm_write_txagc_diff_8822c(dm, tab->diff_t[i - 3], tab->diff_t[i - 2], tab->diff_t[i - 1], tab->diff_t[i], i - 3); } } for (i = ODM_RATEVHTSS1MCS0; i <= ODM_RATEVHTSS2MCS9; i++) { if (i % 4 == 3) { config_phydm_write_txagc_diff_8822c(dm, tab->diff_t[i - 3], tab->diff_t[i - 2], tab->diff_t[i - 1], tab->diff_t[i], i - 3); } } #endif } __odm_func__ void phydm_get_txagc_ref_and_diff_8822c(struct dm_struct *dm, u8 txagc_buff[2][NUM_RATE_AC_2SS], u16 length, struct txagc_table_8822c *tab) { #if (defined(CONFIG_RUN_IN_DRV)) s8 diff_tab[2][NUM_RATE_AC_2SS]; /*power diff table of 2 paths*/ s8 diff_tab_min[NUM_RATE_AC_2SS]; u8 ref_pow_cck[2]; u8 ref_pow_ofdm[2]; u8 ref_pow_tmp = 0; enum rf_path path = 0; u8 i, j = 0; if (*dm->mp_mode || !dm->is_download_fw) return; if (length != NUM_RATE_AC_2SS) { pr_debug("[warning] %s\n", __func__); return; } /* === [Reference base] =============================================*/ #ifdef CONFIG_TXAGC_DEBUG_8822C pr_debug("ref_pow_cck={%d, %d}, ref_pow_ofdm={%d, %d}\n", ref_pow_cck[0], ref_pow_cck[1], ref_pow_ofdm[0], ref_pow_ofdm[1]); #endif /* === [Power By Rate] ==============================================*/ for (path = RF_PATH_A; path <= RF_PATH_B; path++) odm_move_memory(dm, diff_tab[path], txagc_buff[path], NUM_RATE_AC_2SS); ref_pow_cck[0] = diff_tab[RF_PATH_A][ODM_RATE11M]; ref_pow_cck[1] = diff_tab[RF_PATH_B][ODM_RATE11M]; ref_pow_ofdm[0] = diff_tab[RF_PATH_A][ODM_RATEMCS7]; ref_pow_ofdm[1] = diff_tab[RF_PATH_B][ODM_RATEMCS7]; #ifdef CONFIG_TXAGC_DEBUG_8822C pr_debug("1. diff_tab path A\n"); for (i = 0; i <= ODM_RATEVHTSS2MCS9; i++) pr_debug("[A][rate:%d] = %d\n", i, diff_tab[RF_PATH_A][i]); pr_debug("2. diff_tab path B\n"); for (i = 0; i <= ODM_RATEVHTSS2MCS9; i++) pr_debug("[B][rate:%d] = %d\n", i, diff_tab[RF_PATH_B][i]); #endif for (path = RF_PATH_A; path <= RF_PATH_B; path++) { /*CCK*/ ref_pow_tmp = ref_pow_cck[path]; for (j = ODM_RATE1M; j <= ODM_RATE11M; j++) { diff_tab[path][j] -= (s8)ref_pow_tmp; /**/ } /*OFDM*/ ref_pow_tmp = ref_pow_ofdm[path]; for (j = ODM_RATE6M; j <= ODM_RATEMCS15; j++) { diff_tab[path][j] -= (s8)ref_pow_tmp; /**/ } for (j = ODM_RATEVHTSS1MCS0; j <= ODM_RATEVHTSS2MCS9; j++) { diff_tab[path][j] -= (s8)ref_pow_tmp; /**/ } } #ifdef CONFIG_TXAGC_DEBUG_8822C pr_debug("3. diff_tab path A\n"); for (i = 0; i <= ODM_RATEVHTSS2MCS9; i++) pr_debug("[A][rate:%d] = %d\n", i, diff_tab[RF_PATH_A][i]); pr_debug("4. diff_tab path B\n"); for (i = 0; i <= ODM_RATEVHTSS2MCS9; i++) pr_debug("[B][rate:%d] = %d\n", i, diff_tab[RF_PATH_B][i]); #endif for (i = ODM_RATE1M; i <= ODM_RATEMCS15; i++) { diff_tab_min[i] = MIN_2(diff_tab[RF_PATH_A][i], diff_tab[RF_PATH_B][i]); #ifdef CONFIG_TXAGC_DEBUG_8822C pr_debug("diff_tab_min[rate:%d]= %d\n", i, diff_tab_min[i]); #endif } for (i = ODM_RATEVHTSS1MCS0; i <= ODM_RATEVHTSS2MCS9; i++) { diff_tab_min[i] = MIN_2(diff_tab[RF_PATH_A][i], diff_tab[RF_PATH_B][i]); #ifdef CONFIG_TXAGC_DEBUG_8822C pr_debug("diff_tab_min[rate:%d]= %d\n", i, diff_tab_min[i]); #endif } odm_move_memory(dm, tab->ref_pow_cck, ref_pow_cck, 2); odm_move_memory(dm, tab->ref_pow_ofdm, ref_pow_ofdm, 2); odm_move_memory(dm, tab->diff_t, diff_tab_min, NUM_RATE_AC_2SS); #endif } #endif __odm_func__ s8 config_phydm_read_txagc_diff_8822c(struct dm_struct *dm, u8 hw_rate) { #if (PHYDM_FW_API_FUNC_ENABLE_8822C) s8 read_back_data = 0; PHYDM_DBG(dm, ODM_PHY_CONFIG, "%s ======>\n", __func__); /* @Input need to be HW rate index, not driver rate index!!!! */ /* @Error handling */ if (hw_rate > 0x53) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Unsupported rate\n"); return INVALID_TXAGC_DATA; } /* @Disable TX AGC report */ odm_set_bb_reg(dm, R_0x1c7c, BIT(23), 0x0); /* need to check */ /* @Set data rate index (bit30~24) */ odm_set_bb_reg(dm, R_0x1c7c, 0x7F000000, hw_rate); /* @Enable TXAGC report */ odm_set_bb_reg(dm, R_0x1c7c, BIT(23), 0x1); /* @Read TX AGC report */ read_back_data = (s8)odm_get_bb_reg(dm, R_0x2de8, 0xff); if (read_back_data & BIT(6)) read_back_data |= BIT(7); /* @Driver have to disable TXAGC report after reading TXAGC */ odm_set_bb_reg(dm, R_0x1c7c, BIT(23), 0x0); PHYDM_DBG(dm, ODM_PHY_CONFIG, "rate index 0x%x = 0x%x\n", hw_rate, read_back_data); return read_back_data; #else return 0; #endif } __odm_func__ u8 config_phydm_read_txagc_8822c(struct dm_struct *dm, enum rf_path path, u8 hw_rate, enum PDM_RATE_TYPE rate_type) { s8 read_back_data = 0; u8 ref_data = 0; u8 result_data = 0; /* @2-path power reference */ u32 r_txagc_ofdm[2] = {R_0x18e8, R_0x41e8}; u32 r_txagc_cck[2] = {R_0x18a0, R_0x41a0}; PHYDM_DBG(dm, ODM_PHY_CONFIG, "%s ======>\n", __func__); /* @Input need to be HW rate index, not driver rate index!!!! */ /* @Error handling */ if (path > RF_PATH_B || hw_rate > 0x53) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Unsupported path (%d)\n", path); return INVALID_TXAGC_DATA; } /* @Disable TX AGC report */ odm_set_bb_reg(dm, R_0x1c7c, BIT(23), 0x0); /* need to check */ /* @Set data rate index (bit30~24) */ odm_set_bb_reg(dm, R_0x1c7c, 0x7F000000, hw_rate); /* @Enable TXAGC report */ odm_set_bb_reg(dm, R_0x1c7c, BIT(23), 0x1); /* @Read power difference report */ read_back_data = (s8)odm_get_bb_reg(dm, R_0x2de8, 0xff); if (read_back_data & BIT(6)) read_back_data |= BIT(7); /* @Read power reference value report */ if (rate_type == PDM_CCK) /* @Bit=22:16 */ ref_data = (u8)odm_get_bb_reg(dm, r_txagc_cck[path], 0x7F0000); else if (rate_type == PDM_OFDM) /* @Bit=16:10 */ ref_data = (u8)odm_get_bb_reg(dm, r_txagc_ofdm[path], 0x1FC00); PHYDM_DBG(dm, ODM_PHY_CONFIG, "diff=%d ref=%d\n", read_back_data, ref_data); if (read_back_data + ref_data < 0) result_data = 0; else result_data = read_back_data + ref_data; /* @Driver have to disable TXAGC report after reading TXAGC */ odm_set_bb_reg(dm, R_0x1c7c, BIT(23), 0x0); PHYDM_DBG(dm, ODM_PHY_CONFIG, "path-%d rate index 0x%x = 0x%x\n", path, hw_rate, result_data); return result_data; } __odm_func__ void phydm_get_tx_path_en_setting_8822c(struct dm_struct *dm, struct tx_path_en_8822c *path) { u32 val = 0; #ifdef CONFIG_PATH_DIVERSITY struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div; #endif /*OFDM*/ val = odm_get_bb_reg(dm, R_0x820, MASKDWORD); path->tx_path_en_ofdm_2sts = (u8)((val & 0xf0) >> 4); path->tx_path_en_ofdm_1sts = (u8)(val & 0xf); /*CCK*/ val = odm_get_bb_reg(dm, R_0x1a04, 0xf0000000); if (val == 0xc) path->tx_path_en_cck = 3; /*AB*/ else if (val == 0x8) path->tx_path_en_cck = 1; /*A*/ else if (val == 0x4) path->tx_path_en_cck = 2; /*B*/ else if (val == 0x0) path->tx_path_en_cck = 0; /*disable cck tx in 5G*/ /*Path CTRL source*/ val = odm_get_bb_reg(dm, R_0x1e24, BIT(16)); path->is_path_ctrl_by_bb_reg = (boolean)(~val); /*stop path div*/ #ifdef CONFIG_PATH_DIVERSITY path->stop_path_div = p_div->stop_path_div; #else path->stop_path_div = true; #endif } __odm_func__ void phydm_get_rx_path_en_setting_8822c(struct dm_struct *dm, struct rx_path_en_8822c *path) { u32 val = 0; /*OFDM*/ path->rx_path_en_ofdm = (u8)odm_get_bb_reg(dm, R_0x824, 0xf0000); /*CCK*/ val = odm_get_bb_reg(dm, R_0x1a04, 0x0f000000); if (val == 0x1) path->rx_path_en_cck = 3; /*AB*/ else if (val == 0x0) path->rx_path_en_cck = 1; /*A*/ else if (val == 0x5) path->rx_path_en_cck = 2; /*B*/ } __odm_func__ void phydm_config_cck_tx_path_8822c(struct dm_struct *dm, enum bb_path tx_path) { if (tx_path == BB_PATH_A) odm_set_bb_reg(dm, R_0x1a04, 0xf0000000, 0x8); else if (tx_path == BB_PATH_B) odm_set_bb_reg(dm, R_0x1a04, 0xf0000000, 0x4); else /* if (tx_path == BB_PATH_AB)*/ odm_set_bb_reg(dm, R_0x1a04, 0xf0000000, 0xc); phydm_bb_reset_8822c(dm); } __odm_func__ boolean phydm_config_cck_rx_path_8822c(struct dm_struct *dm, enum bb_path rx_path) { boolean set_result = PHYDM_SET_FAIL; if (rx_path == BB_PATH_A) { /* Select ant_A to receive CCK_1 and CCK_2*/ odm_set_bb_reg(dm, R_0x1a04, 0x0f000000, 0x0); /* Enable Rx clk gated */ odm_set_bb_reg(dm, R_0x1a2c, BIT(5), 0x0); /* Disable MRC for CCK barker */ odm_set_bb_reg(dm, R_0x1a2c, 0x00060000, 0x0); /* Disable MRC for CCK CCA */ odm_set_bb_reg(dm, R_0x1a2c, 0x00600000, 0x0); /* 2R CS ratio setting*/ odm_set_bb_reg(dm, R_0x1ad0, 0x3e0, 0xd); } else if (rx_path == BB_PATH_B) { /* Select ant_B to receive CCK_1 and CCK_2*/ odm_set_bb_reg(dm, R_0x1a04, 0x0f000000, 0x5); /* Disable Rx clk gated */ odm_set_bb_reg(dm, R_0x1a2c, BIT(5), 0x1); /* replace path-B with path-AB: [PHYDM-336]*/ /* Disable MRC for CCK barker */ odm_set_bb_reg(dm, R_0x1a2c, 0x00060000, 0x0); /* Eable MRC for CCK CCA */ odm_set_bb_reg(dm, R_0x1a2c, 0x00600000, 0x1); /* 2R CS ratio setting*/ odm_set_bb_reg(dm, R_0x1ad0, 0x3e0, 0xf); } else if (rx_path == BB_PATH_AB) { /* Select ant_A to receive CCK_1 and ant_B to receive CCK_2*/ odm_set_bb_reg(dm, R_0x1a04, 0x0f000000, 0x1); /* Enable Rx clk gated */ odm_set_bb_reg(dm, R_0x1a2c, BIT(5), 0x0); /* Enable MRC for CCK barker */ odm_set_bb_reg(dm, R_0x1a2c, 0x00060000, 0x1); /* Eable MRC for CCK CCA */ odm_set_bb_reg(dm, R_0x1a2c, 0x00600000, 0x1); /* 2R CS ratio setting*/ odm_set_bb_reg(dm, R_0x1ad0, 0x3e0, 0xd); } set_result = PHYDM_SET_SUCCESS; phydm_bb_reset_8822c(dm); return set_result; } __odm_func__ void phydm_config_ofdm_tx_path_8822c(struct dm_struct *dm, enum bb_path tx_path_2ss, enum bb_path tx_path_sel_1ss) { u8 tx_path_2ss_en = false; if (tx_path_2ss == BB_PATH_AB) tx_path_2ss_en = true; if (!tx_path_2ss_en) {/* 1ss1T, do not config this with STBC*/ if (tx_path_sel_1ss == BB_PATH_A) { odm_set_bb_reg(dm, R_0x820, 0xff, 0x1); odm_set_bb_reg(dm, R_0x1e2c, 0xffff, 0x0); } else { /*if (tx_path_sel_1ss == BB_PATH_B)*/ odm_set_bb_reg(dm, R_0x820, 0xff, 0x2); odm_set_bb_reg(dm, R_0x1e2c, 0xffff, 0x0); } } else { if (tx_path_sel_1ss == BB_PATH_A) { odm_set_bb_reg(dm, R_0x820, 0xff, 0x31); odm_set_bb_reg(dm, R_0x1e2c, 0xffff, 0x0400); } else if (tx_path_sel_1ss == BB_PATH_B) { odm_set_bb_reg(dm, R_0x820, 0xff, 0x32); odm_set_bb_reg(dm, R_0x1e2c, 0xffff, 0x0400); } else { /*BB_PATH_AB*/ odm_set_bb_reg(dm, R_0x820, 0xff, 0x33); odm_set_bb_reg(dm, R_0x1e2c, 0xffff, 0x0404); } } phydm_bb_reset_8822c(dm); } __odm_func__ void phydm_config_ofdm_rx_path_8822c(struct dm_struct *dm, enum bb_path rx_path) { u32 ofdm_rx = 0x0; ofdm_rx = (u32)rx_path; if (!(*dm->mp_mode)) { if (ofdm_rx == BB_PATH_B) { ofdm_rx = BB_PATH_AB; odm_set_bb_reg(dm, R_0xcc0, 0x7ff, 0x0); odm_set_bb_reg(dm, R_0xcc0, BIT(22), 0x1); odm_set_bb_reg(dm, R_0xcc8, 0x7ff, 0x0); odm_set_bb_reg(dm, R_0xcc8, BIT(22), 0x1); } else { /* ofdm_rx == BB_PATH_A || ofdm_rx == BB_PATH_AB*/ odm_set_bb_reg(dm, R_0xcc0, 0x7ff, 0x400); odm_set_bb_reg(dm, R_0xcc0, BIT(22), 0x0); odm_set_bb_reg(dm, R_0xcc8, 0x7ff, 0x400); odm_set_bb_reg(dm, R_0xcc8, BIT(22), 0x0); } } if (ofdm_rx == BB_PATH_A || ofdm_rx == BB_PATH_B) { /*@ ht_mcs_limit*/ odm_set_bb_reg(dm, R_0x1d30, 0x300, 0x0); /*@ vht_nss_limit*/ odm_set_bb_reg(dm, R_0x1d30, 0x600000, 0x0); /* @Disable Antenna weighting */ odm_set_bb_reg(dm, R_0xc44, BIT(17), 0x0); /* @htstf ant-wgt enable = 0*/ odm_set_bb_reg(dm, R_0xc54, BIT(20), 0x0); /* @MRC_mode = 'original ZF eqz'*/ odm_set_bb_reg(dm, R_0xc38, BIT(24), 0x0); /* @Rx_ant */ odm_set_bb_reg(dm, R_0x824, 0x000f0000, rx_path); /* @Rx_CCA*/ odm_set_bb_reg(dm, R_0x824, 0x0f000000, rx_path); } else if (ofdm_rx == BB_PATH_AB) { /*@ ht_mcs_limit*/ odm_set_bb_reg(dm, R_0x1d30, 0x300, 0x1); /*@ vht_nss_limit*/ odm_set_bb_reg(dm, R_0x1d30, 0x600000, 0x1); /* @Enable Antenna weighting */ odm_set_bb_reg(dm, R_0xc44, BIT(17), 0x1); /* @htstf ant-wgt enable = 1*/ odm_set_bb_reg(dm, R_0xc54, BIT(20), 0x1); /* @MRC_mode = 'modified ZF eqz'*/ odm_set_bb_reg(dm, R_0xc38, BIT(24), 0x1); /* @Rx_ant */ odm_set_bb_reg(dm, R_0x824, 0x000f0000, BB_PATH_AB); /* @Rx_CCA*/ odm_set_bb_reg(dm, R_0x824, 0x0f000000, BB_PATH_AB); } phydm_bb_reset_8822c(dm); } __odm_func__ void phydm_config_tx_path_8822c(struct dm_struct *dm, enum bb_path tx_path_2ss, enum bb_path tx_path_sel_1ss, enum bb_path tx_path_sel_cck) { dm->tx_2ss_status = tx_path_2ss; dm->tx_1ss_status = tx_path_sel_1ss; dm->tx_ant_status = dm->tx_2ss_status | dm->tx_1ss_status; /* @CCK TX antenna mapping */ phydm_config_cck_tx_path_8822c(dm, tx_path_sel_cck); /* @OFDM TX antenna mapping*/ phydm_config_ofdm_tx_path_8822c(dm, tx_path_2ss, tx_path_sel_1ss); PHYDM_DBG(dm, ODM_PHY_CONFIG, "path_sel_2ss/1ss/cck={%d, %d, %d}\n", tx_path_2ss, tx_path_sel_1ss, tx_path_sel_cck); phydm_bb_reset_8822c(dm); } __odm_func__ void phydm_config_rx_path_8822c(struct dm_struct *dm, enum bb_path rx_path) { /* @CCK RX antenna mapping */ phydm_config_cck_rx_path_8822c(dm, rx_path); /* @OFDM RX antenna mapping*/ phydm_config_ofdm_rx_path_8822c(dm, rx_path); dm->rx_ant_status = rx_path; phydm_bb_reset_8822c(dm); } __odm_func__ void phydm_set_rf_mode_table_8822c(struct dm_struct *dm, enum bb_path tx_path_mode_table, enum bb_path rx_path) { /* @Cannot shut down path-A, beacause synthesizer will shut down * @when path-A is in shut down mode */ /* @[3-wire setting] 0: shutdown, 1: standby, 2: TX, 3: RX*/ if (tx_path_mode_table == BB_PATH_A) { if (rx_path == BB_PATH_A) { odm_set_bb_reg(dm, R_0x1800, 0xfffff, 0x33312); odm_set_bb_reg(dm, R_0x4100, 0xfffff, 0x0); } else { /* @BB_PATH_AB*/ odm_set_bb_reg(dm, R_0x1800, 0xfffff, 0x33312); odm_set_bb_reg(dm, R_0x4100, 0xfffff, 0x33311); } } else if (tx_path_mode_table == BB_PATH_B) { if (rx_path == BB_PATH_A) { odm_set_bb_reg(dm, R_0x1800, 0xfffff, 0x33311); odm_set_bb_reg(dm, R_0x4100, 0xfffff, 0x11112); } else { odm_set_bb_reg(dm, R_0x1800, 0xfffff, 0x33311); odm_set_bb_reg(dm, R_0x4100, 0xfffff, 0x33312); } } else if (tx_path_mode_table == BB_PATH_AB) { if (rx_path == BB_PATH_A) { odm_set_bb_reg(dm, R_0x1800, 0xfffff, 0x33312); odm_set_bb_reg(dm, R_0x4100, 0xfffff, 0x11112); } else { odm_set_bb_reg(dm, R_0x1800, 0xfffff, 0x33312); odm_set_bb_reg(dm, R_0x4100, 0xfffff, 0x33312); } } } __odm_func__ void phydm_rfe_8822c(struct dm_struct *dm, enum bb_path path) { u8 rfe_type = dm->rfe_type; u32 rf_reg18 = 0; u8 central_ch = 0; boolean is_2g_ch = false; rf_reg18 = config_phydm_read_rf_reg_8822c(dm, RF_PATH_A, RF_0x18, RFREG_MASK); central_ch = (u8)(rf_reg18 & 0xff); is_2g_ch = (central_ch <= 14) ? true : false; PHYDM_DBG(dm, ODM_PHY_CONFIG, "[8822C] Update RFE PINs: T/RX_path:{0x%x, 0x%x}, rfe_type:%d\n", dm->tx_ant_status, dm->rx_ant_status, rfe_type); /*HW Setting for each RFE type */ if (rfe_type == 21 || rfe_type == 22) { /*rfe sel*/ /*0 : PAPE_2G_rfm*/ /*2 : LNAON_2G*/ /*3 : rfm_lnaon*/ /*7 : 1'b0*/ if (is_2g_ch) path = BB_PATH_NON; switch (path) { case BB_PATH_NON: odm_set_bb_reg(dm, R_0x1840, 0xffff, 0x7770); odm_set_bb_reg(dm, R_0x4144, 0xffff, 0x7077); break; case BB_PATH_A: odm_set_bb_reg(dm, R_0x1840, 0xffff, 0x2300); odm_set_bb_reg(dm, R_0x4144, 0xffff, 0x7077); break; case BB_PATH_B: odm_set_bb_reg(dm, R_0x1840, 0xffff, 0x7770); odm_set_bb_reg(dm, R_0x4144, 0xffff, 0x2030); break; case BB_PATH_AB: odm_set_bb_reg(dm, R_0x1840, 0xffff, 0x2300); odm_set_bb_reg(dm, R_0x4144, 0xffff, 0x2030); break; default: break; } } } __odm_func__ boolean config_phydm_trx_mode_8822c(struct dm_struct *dm, enum bb_path tx_path_en, enum bb_path rx_path, enum bb_path tx_path_sel_1ss) { #ifdef CONFIG_PATH_DIVERSITY struct _ODM_PATH_DIVERSITY_ *p_div = &dm->dm_path_div; #endif boolean disable_2sts_div_mode = false; enum bb_path tx_path_mode_table = tx_path_en; enum bb_path tx_path_2ss = BB_PATH_AB; u8 rfe_type = dm->rfe_type; PHYDM_DBG(dm, ODM_PHY_CONFIG, "%s ======>\n", __func__); if (dm->is_disable_phy_api) { pr_debug("[%s] Disable PHY API\n", __func__); return true; } /*RX Check*/ if (rx_path & ~BB_PATH_AB) { pr_debug("[Warning][%s] RX:0x%x\n", __func__, rx_path); return false; } /*TX Check*/ if (tx_path_en == BB_PATH_AUTO && tx_path_sel_1ss == BB_PATH_AUTO) { /*@ Shutting down 2sts rate, but 1sts PathDiv is enabled*/ disable_2sts_div_mode = true; tx_path_mode_table = BB_PATH_AB; } else if (tx_path_en & ~BB_PATH_AB) { pr_debug("[Warning][%s] TX:0x%x\n", __func__, tx_path_en); return false; } /* @==== [RF Mode Table] ========================================*/ phydm_set_rf_mode_table_8822c(dm, tx_path_mode_table, rx_path); /* @==== [RX Path] ==============================================*/ phydm_config_rx_path_8822c(dm, rx_path); /* @==== [TX Path] ==============================================*/ #ifdef CONFIG_PATH_DIVERSITY /*@ [PHYDM-312]*/ if (p_div->default_tx_path != BB_PATH_A && p_div->default_tx_path != BB_PATH_B) p_div->default_tx_path = BB_PATH_A; if (tx_path_en == BB_PATH_A || tx_path_en == BB_PATH_B) { p_div->stop_path_div = true; tx_path_sel_1ss = tx_path_en; tx_path_2ss = BB_PATH_NON; } else if (tx_path_en == BB_PATH_AB) { if (tx_path_sel_1ss == BB_PATH_AUTO) { p_div->stop_path_div = false; tx_path_sel_1ss = p_div->default_tx_path; } else { /* @BB_PATH_AB, BB_PATH_A, BB_PATH_B*/ p_div->stop_path_div = true; } tx_path_2ss = BB_PATH_AB; } else if (disable_2sts_div_mode) { p_div->stop_path_div = false; tx_path_sel_1ss = p_div->default_tx_path; tx_path_2ss = BB_PATH_NON; } #else if (dm->tx_1ss_status == BB_PATH_NON) dm->tx_1ss_status = BB_PATH_A; if (tx_path_en == BB_PATH_A || tx_path_en == BB_PATH_B) { tx_path_2ss = BB_PATH_NON; tx_path_sel_1ss = tx_path_en; } else if (tx_path_en == BB_PATH_AB) { tx_path_2ss = BB_PATH_AB; if (tx_path_sel_1ss == BB_PATH_AUTO) tx_path_sel_1ss = dm->tx_1ss_status; } else if (disable_2sts_div_mode) { tx_path_2ss = BB_PATH_NON; tx_path_sel_1ss = dm->tx_1ss_status; } #endif phydm_config_tx_path_8822c(dm, tx_path_2ss, tx_path_sel_1ss, tx_path_sel_1ss); /*====== [RFE ctrl] =============================================*/ if (rfe_type == 21 || rfe_type == 22) { if (dm->tx_ant_status == BB_PATH_A && rx_path == BB_PATH_A) phydm_rfe_8822c(dm, BB_PATH_A); else if (dm->tx_ant_status == BB_PATH_B && rx_path == BB_PATH_B) phydm_rfe_8822c(dm, BB_PATH_B); else phydm_rfe_8822c(dm, BB_PATH_AB); } phydm_igi_toggle_8822c(dm); PHYDM_DBG(dm, ODM_PHY_CONFIG, "RX_en=%x, tx_en/2ss/1ss={%x,%x,%x}\n", rx_path, tx_path_en, tx_path_2ss, tx_path_sel_1ss); phydm_bb_reset_8822c(dm); return true; } void phydm_cck_rxiq_8822c(struct dm_struct *dm, u8 set_type) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "%s ======>\n", __func__); if (set_type == PHYDM_SET) { /* @ CCK source 5*/ odm_set_bb_reg(dm, R_0x1a9c, BIT(20), 0x1); /* @ CCK RxIQ weighting = [1,1] */ odm_set_bb_reg(dm, R_0x1a14, 0x300, 0x0); } else if (set_type == PHYDM_REVERT) { /* @ CCK source 1*/ odm_set_bb_reg(dm, R_0x1a9c, BIT(20), 0x0); /* @ CCK RxIQ weighting = [0,0] */ odm_set_bb_reg(dm, R_0x1a14, 0x300, 0x3); } } __odm_func__ boolean config_phydm_switch_band_8822c(struct dm_struct *dm, u8 central_ch) { return true; } __odm_func__ void phydm_cck_tx_shaping_filter_8822c(struct dm_struct *dm, u8 central_ch) { /* @CCK TX filter parameters */ if (central_ch == 14) { /* @TX Shaping Filter C0~1 */ odm_set_bb_reg(dm, R_0x1a20, MASKHWORD, 0x3da0); /* @TX Shaping Filter C2~5 */ odm_set_bb_reg(dm, R_0x1a24, MASKDWORD, 0x4962c931); /* @TX Shaping Filter C6~7 */ odm_set_bb_reg(dm, R_0x1a28, MASKLWORD, 0x6aa3); /* @TX Shaping Filter C8~9 */ odm_set_bb_reg(dm, R_0x1a98, MASKHWORD, 0xaa7b); /* @TX Shaping Filter C10~11 */ odm_set_bb_reg(dm, R_0x1a9c, MASKLWORD, 0xf3d7); /* @TX Shaping Filter C12~15 */ odm_set_bb_reg(dm, R_0x1aa0, MASKDWORD, 0x00000000); /* @TX Shaping Filter_MSB C0~7 */ odm_set_bb_reg(dm, R_0x1aac, MASKDWORD, 0xff012455); /* @TX Shaping Filter_MSB C8~15 */ odm_set_bb_reg(dm, R_0x1ab0, MASKDWORD, 0x0000ffff); } else { /* @TX Shaping Filter C0~1 */ odm_set_bb_reg(dm, R_0x1a20, MASKHWORD, 0x5284); /* @TX Shaping Filter C2~5 */ odm_set_bb_reg(dm, R_0x1a24, MASKDWORD, 0x3e18fec8); /* @TX Shaping Filter C6~7 */ odm_set_bb_reg(dm, R_0x1a28, MASKLWORD, 0x0a88); /* @TX Shaping Filter C8~9 */ odm_set_bb_reg(dm, R_0x1a98, MASKHWORD, 0xacc4); /* @TX Shaping Filter C10~11 */ odm_set_bb_reg(dm, R_0x1a9c, MASKLWORD, 0xc8b2); /* @TX Shaping Filter C12~15 */ odm_set_bb_reg(dm, R_0x1aa0, MASKDWORD, 0x00faf0de); /* @TX Shaping Filter_MSB C0~7 */ odm_set_bb_reg(dm, R_0x1aac, MASKDWORD, 0x00122344); /* @TX Shaping Filter_MSB C8~15 */ odm_set_bb_reg(dm, R_0x1ab0, MASKDWORD, 0x0fffffff); } } __odm_func__ void phydm_cck_agc_tab_sel_8822c(struct dm_struct *dm, u8 table) { odm_set_bb_reg(dm, R_0x18ac, 0xf000, table); odm_set_bb_reg(dm, R_0x41ac, 0xf000, table); } __odm_func__ void phydm_ofdm_agc_tab_sel_8822c(struct dm_struct *dm, u8 table) { struct phydm_dig_struct *dig_tab = &dm->dm_dig_table; u8 lower_bound = dm->ofdm_rxagc_l_bnd[table]; odm_set_bb_reg(dm, R_0x18ac, 0x1f0, table); odm_set_bb_reg(dm, R_0x41ac, 0x1f0, table); dig_tab->agc_table_idx = table; if (!dm->l_bnd_detect[table]) lower_bound = L_BND_DEFAULT_8822C; /*AGC lower bound, need to be updated with AGC table*/ odm_set_bb_reg(dm, R_0x828, 0xf8, lower_bound); } __odm_func__ void phydm_sco_trk_fc_setting_8822c(struct dm_struct *dm, u8 central_ch) { if (central_ch == 13 || central_ch == 14) { /* @n:41, s:37 */ odm_set_bb_reg(dm, R_0xc30, 0xfff, 0x969); } else if (central_ch == 11 || central_ch == 12) { /* @n:42, s:37 */ odm_set_bb_reg(dm, R_0xc30, 0xfff, 0x96a); } else if (central_ch >= 1 && central_ch <= 10) { /* @n:42, s:38 */ odm_set_bb_reg(dm, R_0xc30, 0xfff, 0x9aa); } else if (central_ch >= 36 && central_ch <= 51) { /* @n:20, s:18 */ odm_set_bb_reg(dm, R_0xc30, 0xfff, 0x494); } else if (central_ch >= 52 && central_ch <= 55) { /* @n:19, s:18 */ odm_set_bb_reg(dm, R_0xc30, 0xfff, 0x493); } else if ((central_ch >= 56) && (central_ch <= 111)) { /* @n:19, s:17 */ odm_set_bb_reg(dm, R_0xc30, 0xfff, 0x453); } else if ((central_ch >= 112) && (central_ch <= 119)) { /* @n:18, s:17 */ odm_set_bb_reg(dm, R_0xc30, 0xfff, 0x452); } else if ((central_ch >= 120) && (central_ch <= 172)) { /* @n:18, s:16 */ odm_set_bb_reg(dm, R_0xc30, 0xfff, 0x412); } else { /* if ((central_ch >= 173) && (central_ch <= 177)) */ /* n:17, s:16 */ odm_set_bb_reg(dm, R_0xc30, 0xfff, 0x411); } } __odm_func__ void phydm_tx_dfir_setting_8822c(struct dm_struct *dm, u8 central_ch) { if (central_ch <= 14) { if (central_ch == 13) odm_set_bb_reg(dm, R_0x808, 0x70, 0x3); else odm_set_bb_reg(dm, R_0x808, 0x70, 0x1); } else { odm_set_bb_reg(dm, R_0x808, 0x70, 0x3); } } __odm_func__ void phydm_set_dis_dpd_by_rate_8822c(struct dm_struct *dm, u16 bitmask) { /* bit(0) : ofdm 6m*/ /* bit(1) : ofdm 9m*/ /* bit(2) : ht mcs0*/ /* bit(3) : ht mcs1*/ /* bit(4) : ht mcs8*/ /* bit(5) : ht mcs9*/ /* bit(6) : vht 1ss mcs0*/ /* bit(7) : vht 1ss mcs1*/ /* bit(8) : vht 2ss mcs0*/ /* bit(9) : vht 2ss mcs1*/ odm_set_bb_reg(dm, R_0xa70, 0x3ff, bitmask); dm->dis_dpd_rate = bitmask; } __odm_func__ boolean config_phydm_switch_channel_8822c(struct dm_struct *dm, u8 central_ch) { u32 rf_reg18 = 0; boolean is_2g_ch = true; enum bb_path tx_1sts = BB_PATH_NON; enum bb_path tx_2sts = BB_PATH_NON; enum bb_path tx = BB_PATH_NON; enum bb_path rx = BB_PATH_NON; u8 rfe_type = dm->rfe_type; struct phydm_iot_center *iot_table = &dm->iot_table; PHYDM_DBG(dm, ODM_PHY_CONFIG, "%s ======>\n", __func__); if (dm->is_disable_phy_api) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Disable PHY API\n"); return true; } if ((central_ch > 14 && central_ch < 36) || (central_ch > 64 && central_ch < 100) || (central_ch > 144 && central_ch < 149) || central_ch > 177) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Error CH:%d\n", central_ch); return false; } rf_reg18 = config_phydm_read_rf_reg_8822c(dm, RF_PATH_A, RF_0x18, RFREG_MASK); if (rf_reg18 == INVALID_RF_DATA) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Invalid RF_0x18\n"); return false; } is_2g_ch = (central_ch <= 14) ? true : false; /* [get trx info for cck tx and rfe ctrl] */ tx_1sts = dm->tx_1ss_status; if (tx_1sts == BB_PATH_NON) { tx_1sts = (u8)odm_get_bb_reg(dm, R_0x820, 0xf); dm->tx_1ss_status = (u8)tx_1sts; pr_debug("[%s]tx_1ss is non!, update tx_1sts:%d\n", __func__, tx_1sts); } tx = dm->tx_ant_status; if (tx == BB_PATH_NON) { tx_2sts = (u8)odm_get_bb_reg(dm, R_0x820, 0xf0); tx = (u8)(tx_1sts | tx_2sts); dm->tx_2ss_status = (u8)tx_2sts; dm->tx_ant_status = tx; pr_debug("[%s]tx_ant_status is non!, update tx_2sts/tx_path:%d/%d\n", __func__, tx_2sts, tx); } rx = dm->rx_ant_status; if (rx == BB_PATH_NON) { rx = (u8)odm_get_bb_reg(dm, R_0x824, 0xf0000); dm->rx_ant_status = (u8)rx; pr_debug("[%s]rx_ant_status is non!, update rx_path:%d\n", __func__, rx); } /* ==== [Set RF Reg 0x18] ===========================================*/ rf_reg18 &= ~0x703ff; /*[18:17],[16],[9:8],[7:0]*/ rf_reg18 |= central_ch; /* Channel*/ if (!is_2g_ch) { /*5G*/ rf_reg18 |= (BIT(16) | BIT(8)); /* 5G Sub-Band, 01: 54005720*/ if (central_ch > 144) rf_reg18 |= BIT(18); else if (central_ch >= 80) rf_reg18 |= BIT(17); } /*reset HSSI*/ odm_set_bb_reg(dm, R_0x1c90, BIT(8), 0x0); /*RxA enhance-Q setting*/ odm_set_rf_reg(dm, RF_PATH_A, RF_0xdf, BIT(18), is_2g_ch); /*write RF-0x18*/ odm_set_rf_reg(dm, RF_PATH_A, RF_0x18, RFREG_MASK, rf_reg18); odm_set_rf_reg(dm, RF_PATH_B, RF_0x18, RFREG_MASK, rf_reg18); /*reset HSSI*/ odm_set_bb_reg(dm, R_0x1c90, BIT(8), 0x1); /*force update anapar*/ odm_set_bb_reg(dm, R_0x1830, BIT(29), 0x1); odm_set_bb_reg(dm, R_0x4130, BIT(29), 0x1); /* ==== [Set BB Reg] =================================================*/ /* 1. AGC table selection */ if (central_ch <= 14) { if (*dm->band_width == CHANNEL_WIDTH_20) { phydm_cck_agc_tab_sel_8822c(dm, CCK_BW20_8822C); phydm_ofdm_agc_tab_sel_8822c(dm, OFDM_2G_BW20_8822C); } else { phydm_cck_agc_tab_sel_8822c(dm, CCK_BW40_8822C); phydm_ofdm_agc_tab_sel_8822c(dm, OFDM_2G_BW40_8822C); } } else if (central_ch >= 36 && central_ch <= 64) { phydm_ofdm_agc_tab_sel_8822c(dm, OFDM_5G_LOW_BAND_8822C); } else if ((central_ch >= 100) && (central_ch <= 144)) { phydm_ofdm_agc_tab_sel_8822c(dm, OFDM_5G_MID_BAND_8822C); } else { /*if (central_ch >= 149)*/ phydm_ofdm_agc_tab_sel_8822c(dm, OFDM_5G_HIGH_BAND_8822C); } /* 2. Set fc for clock offset tracking */ phydm_sco_trk_fc_setting_8822c(dm, central_ch); /* 3. TX DFIR*/ phydm_tx_dfir_setting_8822c(dm, central_ch); /* 4. Other BB Settings*/ if (is_2g_ch) { phydm_cck_tx_shaping_filter_8822c(dm, central_ch); /* Enable CCK Rx IQ */ phydm_cck_rxiq_8822c(dm, PHYDM_SET); /* Disable MAC CCK check */ odm_set_mac_reg(dm, R_0x454, BIT(7), 0x0); /* Disable BB CCK check */ odm_set_bb_reg(dm, R_0x1a80, BIT(18), 0x0); /* CCA Mask, default = 0xf */ odm_set_bb_reg(dm, R_0x1c80, 0x3F000000, 0xF); /*RFE ctrl*/ if (rfe_type == 21 || rfe_type == 22) phydm_rfe_8822c(dm, BB_PATH_NON); } else { /* 5G*/ /* Enable BB CCK check */ odm_set_bb_reg(dm, R_0x1a80, BIT(18), 0x1); /* Enable CCK check */ odm_set_mac_reg(dm, R_0x454, BIT(7), 0x1); /* Disable CCK Rx IQ */ phydm_cck_rxiq_8822c(dm, PHYDM_REVERT); /* CCA Mask */ odm_set_bb_reg(dm, R_0x1c80, 0x3F000000, 0x22); /*RFE ctrl*/ if (rfe_type == 21 || rfe_type == 22) { if (tx == BB_PATH_A && rx == BB_PATH_A) phydm_rfe_8822c(dm, BB_PATH_A); else if (tx == BB_PATH_B && rx == BB_PATH_B) phydm_rfe_8822c(dm, BB_PATH_B); else phydm_rfe_8822c(dm, BB_PATH_AB); } } if (iot_table->patch_id_011f0500) { if (central_ch != 1 && dm->en_dis_dpd) phydm_set_dis_dpd_by_rate_8822c(dm, 0x3ff); else phydm_set_dis_dpd_by_rate_8822c(dm, 0x0); } /*====================================================================*/ phydm_igi_toggle_8822c(dm); phydm_bb_reset_8822c(dm); PHYDM_DBG(dm, ODM_PHY_CONFIG, "Switch CH:%d success\n", central_ch); return true; } __odm_func__ boolean config_phydm_switch_bandwidth_8822c(struct dm_struct *dm, u8 pri_ch, enum channel_width bw) { u32 rf_reg18 = 0; u32 rf_reg3f = 0; boolean rf_reg_status = true; PHYDM_DBG(dm, ODM_PHY_CONFIG, "%s ======>\n", __func__); if (dm->is_disable_phy_api) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Disable PHY API for debug!!\n"); return true; } /*Error handling */ if (bw >= CHANNEL_WIDTH_MAX || (bw == CHANNEL_WIDTH_40 && pri_ch > 2) || (bw == CHANNEL_WIDTH_80 && pri_ch > 4)) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Fail to switch bw(bw:%d, pri ch:%d)\n", bw, pri_ch); return false; } rf_reg18 = config_phydm_read_rf_reg_8822c(dm, RF_PATH_A, RF_0x18, RFREG_MASK); if (rf_reg18 != INVALID_RF_DATA) rf_reg_status = true; else rf_reg_status = false; rf_reg18 &= ~(BIT(13) | BIT(12)); /*Switch bandwidth */ switch (bw) { case CHANNEL_WIDTH_5: case CHANNEL_WIDTH_10: case CHANNEL_WIDTH_20: if (bw == CHANNEL_WIDTH_5) { /*RX DFIR*/ odm_set_bb_reg(dm, R_0x810, 0x3ff0, 0x2ab); /*small BW:[7:6]=0x1 */ /*TX pri ch:[11:8]=0x0, RX pri ch:[15:12]=0x0 */ odm_set_bb_reg(dm, R_0x9b0, 0xffc0, 0x1); /*DAC clock = 120M clock for BW5 */ odm_set_bb_reg(dm, R_0x9b4, 0x00000700, 0x4); /*ADC clock = 40M clock for BW5 */ odm_set_bb_reg(dm, R_0x9b4, 0x00700000, 0x4); } else if (bw == CHANNEL_WIDTH_10) { /*RX DFIR*/ odm_set_bb_reg(dm, R_0x810, 0x3ff0, 0x2ab); /*small BW:[7:6]=0x2 */ /*TX pri ch:[11:8]=0x0, RX pri ch:[15:12]=0x0 */ odm_set_bb_reg(dm, R_0x9b0, 0xffc0, 0x2); /*DAC clock = 240M clock for BW10 */ odm_set_bb_reg(dm, R_0x9b4, 0x00000700, 0x6); /*ADC clock = 80M clock for BW10 */ odm_set_bb_reg(dm, R_0x9b4, 0x00700000, 0x5); } else if (bw == CHANNEL_WIDTH_20) { /*RX DFIR*/ odm_set_bb_reg(dm, R_0x810, 0x3ff0, 0x19b); /*small BW:[7:6]=0x0 */ /*TX pri ch:[11:8]=0x0, RX pri ch:[15:12]=0x0 */ odm_set_bb_reg(dm, R_0x9b0, 0xffc0, 0x0); /*DAC clock = 480M clock for BW20 */ odm_set_bb_reg(dm, R_0x9b4, 0x00000700, 0x7); /*ADC clock = 160M clock for BW20 */ odm_set_bb_reg(dm, R_0x9b4, 0x00700000, 0x6); } /*TX_RF_BW:[1:0]=0x0, RX_RF_BW:[3:2]=0x0 */ odm_set_bb_reg(dm, R_0x9b0, 0xf, 0x0); /*RF bandwidth */ rf_reg18 |= (BIT(13) | BIT(12)); /*RF RXBB setting*/ rf_reg3f = (BIT(4) | BIT(3)); /*pilot smoothing on */ odm_set_bb_reg(dm, R_0xcbc, BIT(21), 0x0); /*CCK source 4 */ odm_set_bb_reg(dm, R_0x1abc, BIT(30), 0x0); /*dynamic CCK PD th*/ odm_set_bb_reg(dm, R_0x1ae8, BIT(31), 0x1); odm_set_bb_reg(dm, R_0x1aec, 0xf, 0x6); /*subtune*/ odm_set_bb_reg(dm, R_0x88c, 0xf000, 0x1); if (*dm->band_type == ODM_BAND_2_4G) { phydm_cck_agc_tab_sel_8822c(dm, CCK_BW20_8822C); phydm_ofdm_agc_tab_sel_8822c(dm, OFDM_2G_BW20_8822C); } break; case CHANNEL_WIDTH_40: /*CCK primary channel */ if (pri_ch == 1) odm_set_bb_reg(dm, R_0x1a00, BIT(4), pri_ch); else odm_set_bb_reg(dm, R_0x1a00, BIT(4), 0); /*TX_RF_BW:[1:0]=0x1, RX_RF_BW:[3:2]=0x1 */ odm_set_bb_reg(dm, R_0x9b0, 0xf, 0x5); /*small BW */ odm_set_bb_reg(dm, R_0x9b0, 0xc0, 0x0); /*TX pri ch:[11:8], RX pri ch:[15:12] */ odm_set_bb_reg(dm, R_0x9b0, 0xff00, (pri_ch | (pri_ch << 4))); /*RF bandwidth */ rf_reg18 |= BIT(13); /*RF RXBB setting*/ rf_reg3f = BIT(4); /*pilot smoothing off */ odm_set_bb_reg(dm, R_0xcbc, BIT(21), 0x1); /*CCK source 5 */ odm_set_bb_reg(dm, R_0x1abc, BIT(30), 0x1); /*dynamic CCK PD th*/ odm_set_bb_reg(dm, R_0x1ae8, BIT(31), 0x0); odm_set_bb_reg(dm, R_0x1aec, 0xf, 0x8); /*subtune*/ odm_set_bb_reg(dm, R_0x88c, 0xf000, 0x1); if (*dm->band_type == ODM_BAND_2_4G) { /*CCK*/ phydm_cck_agc_tab_sel_8822c(dm, CCK_BW40_8822C); phydm_ofdm_agc_tab_sel_8822c(dm, OFDM_2G_BW40_8822C); } break; case CHANNEL_WIDTH_80: /*TX_RF_BW:[1:0]=0x2, RX_RF_BW:[3:2]=0x2 */ odm_set_bb_reg(dm, R_0x9b0, 0xf, 0xa); /*small BW */ odm_set_bb_reg(dm, R_0x9b0, 0xc0, 0x0); /*TX pri ch:[11:8], RX pri ch:[15:12] */ odm_set_bb_reg(dm, R_0x9b0, 0xff00, (pri_ch | (pri_ch << 4))); /*RF bandwidth */ rf_reg18 |= BIT(12); /*RF RXBB setting*/ rf_reg3f = BIT(3); /*pilot smoothing off */ odm_set_bb_reg(dm, R_0xcbc, BIT(21), 0x1); /*subtune*/ odm_set_bb_reg(dm, R_0x88c, 0xf000, 0x6); break; default: PHYDM_DBG(dm, ODM_PHY_CONFIG, "Fail to switch bw (bw:%d, pri ch:%d)\n", bw, pri_ch); } /*Write RF register */ /*reset HSSI*/ odm_set_bb_reg(dm, R_0x1c90, BIT(8), 0x0); /*RF RXBB setting, WLANBB-1081*/ odm_set_rf_reg(dm, RF_PATH_A, RF_0xee, 0x4, 0x1); odm_set_rf_reg(dm, RF_PATH_A, RF_0x33, 0x1F, 0x12); odm_set_rf_reg(dm, RF_PATH_A, RF_0x3f, RFREG_MASK, rf_reg3f); odm_set_rf_reg(dm, RF_PATH_A, RF_0xee, 0x4, 0x0); odm_set_rf_reg(dm, RF_PATH_B, RF_0xee, 0x4, 0x1); odm_set_rf_reg(dm, RF_PATH_B, RF_0x33, 0x1F, 0x12); odm_set_rf_reg(dm, RF_PATH_B, RF_0x3f, RFREG_MASK, rf_reg3f); odm_set_rf_reg(dm, RF_PATH_B, RF_0xee, 0x4, 0x0); /*write RF-0x18*/ odm_set_rf_reg(dm, RF_PATH_A, RF_0x18, RFREG_MASK, rf_reg18); odm_set_rf_reg(dm, RF_PATH_B, RF_0x18, RFREG_MASK, rf_reg18); /*reset HSSI*/ odm_set_bb_reg(dm, R_0x1c90, BIT(8), 0x1); /*force update anapar*/ odm_set_bb_reg(dm, R_0x1830, BIT(29), 0x1); odm_set_bb_reg(dm, R_0x4130, BIT(29), 0x1); if (!rf_reg_status) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Fail to switch bw (bw:%d, primary ch:%d), because writing RF register is fail\n", bw, pri_ch); return false; } /*fix bw setting*/ #ifdef CONFIG_BW_INDICATION if (!(*dm->mp_mode)) phydm_bw_fixed_setting(dm); #endif /*Toggle IGI to let RF enter RX mode */ phydm_igi_toggle_8822c(dm); PHYDM_DBG(dm, ODM_PHY_CONFIG, "Success to switch bw (bw:%d, pri ch:%d)\n", bw, pri_ch); phydm_bb_reset_8822c(dm); return true; } __odm_func__ boolean config_phydm_switch_channel_bw_8822c(struct dm_struct *dm, u8 central_ch, u8 primary_ch_idx, enum channel_width bandwidth) { /* @Switch channel */ if (!config_phydm_switch_channel_8822c(dm, central_ch)) return false; /* @Switch bandwidth */ if (!config_phydm_switch_bandwidth_8822c(dm, primary_ch_idx, bandwidth)) return false; return true; } __odm_func__ void phydm_i_only_setting_8822c(struct dm_struct *dm, boolean en_i_only, boolean en_before_cca) { if (en_i_only) { /*@ Set path-a*/ if (en_before_cca) { odm_set_bb_reg(dm, R_0x1800, 0xfff00, 0x833); odm_set_bb_reg(dm, R_0x1c68, 0xc000, 0x2); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70038001); } else { if (!(*dm->band_width == CHANNEL_WIDTH_40)) return; dm->bp_0x9b0 = odm_get_bb_reg(dm, R_0x9b0, MASKDWORD); odm_set_bb_reg(dm, R_0x1800, 0xfff00, 0x888); odm_set_bb_reg(dm, R_0x898, BIT(30), 0x1); odm_set_bb_reg(dm, R_0x1c68, 0xc000, 0x1); odm_set_bb_reg(dm, R_0x9b0, MASKDWORD, 0x2200); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70038001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70038001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70538001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70738001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70838001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70938001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70a38001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70b38001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70c38001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70d38001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70e38001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70f38001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70f38001); } } else { if (en_before_cca) { odm_set_bb_reg(dm, R_0x1800, 0xfff00, 0x333); odm_set_bb_reg(dm, R_0x1c68, 0xc000, 0x0); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x700b8001); } else { if (!(*dm->band_width == CHANNEL_WIDTH_40)) return; odm_set_bb_reg(dm, R_0x1800, 0xfff00, 0x333); odm_set_bb_reg(dm, R_0x898, BIT(30), 0x0); odm_set_bb_reg(dm, R_0x1c68, 0xc000, 0x0); odm_set_bb_reg(dm, R_0x9b0, MASKDWORD, dm->bp_0x9b0); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x700b8001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x700b8001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x705b8001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x707b8001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x708b8001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x709b8001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70ab8001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70bb8001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70cb8001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70db8001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70eb8001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70fb8001); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70fb8001); } } } __odm_func__ void phydm_1rcca_setting_8822c(struct dm_struct *dm, boolean en_1rcca) { if (en_1rcca) { /*@ Set path-a*/ odm_set_bb_reg(dm, R_0x83c, 0x4, 0x1); odm_set_bb_reg(dm, R_0x824, 0x0f000000, 0x1); odm_set_bb_reg(dm, R_0x4100, 0xf0000, 0x1); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70008001); phydm_config_cck_rx_path_8822c(dm, BB_PATH_A); } else { odm_set_bb_reg(dm, R_0x83c, 0x4, 0x0); odm_set_bb_reg(dm, R_0x824, 0x0f000000, 0x3); odm_set_bb_reg(dm, R_0x4100, 0xf0000, 0x3); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x700b8001); phydm_config_cck_rx_path_8822c(dm, BB_PATH_AB); } phydm_bb_reset_8822c(dm); } __odm_func__ void phydm_invld_pkt_setting_8822c(struct dm_struct *dm, boolean en_invld_pkt) { if (en_invld_pkt) { odm_set_bb_reg(dm, R_0x1c64, BIT(30), 0x1); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70e0c001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70e0c001); } else { odm_set_bb_reg(dm, R_0x1c64, BIT(30), 0x0); odm_set_bb_reg(dm, R_0x1830, MASKDWORD, 0x70eb8001); odm_set_bb_reg(dm, R_0x4130, MASKDWORD, 0x70eb8001); } } __odm_func__ void phydm_cck_gi_bound_8822c(struct dm_struct *dm) { struct phydm_physts *physts_table = &dm->dm_physts_table; u8 cck_gi_u_bnd_msb = 0; u8 cck_gi_u_bnd_lsb = 0; u8 cck_gi_l_bnd_msb = 0; u8 cck_gi_l_bnd_lsb = 0; cck_gi_u_bnd_msb = (u8)odm_get_bb_reg(dm, R_0x1a98, 0xc000); cck_gi_u_bnd_lsb = (u8)odm_get_bb_reg(dm, R_0x1aa8, 0xf0000); cck_gi_l_bnd_msb = (u8)odm_get_bb_reg(dm, R_0x1a98, 0xc0); cck_gi_l_bnd_lsb = (u8)odm_get_bb_reg(dm, R_0x1a70, 0x0f000000); physts_table->cck_gi_u_bnd = (u8)((cck_gi_u_bnd_msb << 4) | (cck_gi_u_bnd_lsb)); physts_table->cck_gi_l_bnd = (u8)((cck_gi_l_bnd_msb << 4) | (cck_gi_l_bnd_lsb)); } __odm_func__ void phydm_ch_smooth_setting_8822c(struct dm_struct *dm, boolean en_ch_smooth) { if (en_ch_smooth) /* @enable force channel smoothing*/ odm_set_bb_reg(dm, R_0xc54, BIT(7), 0x1); else odm_set_bb_reg(dm, R_0xc54, BIT(7), 0x0); } __odm_func__ u16 phydm_get_dis_dpd_by_rate_8822c(struct dm_struct *dm) { u16 dis_dpd_rate = 0; dis_dpd_rate = dm->dis_dpd_rate; return dis_dpd_rate; } __odm_func__ void phydm_cck_pd_init_8822c(struct dm_struct *dm) { struct phydm_iot_center *iot_table = &dm->iot_table; if (*dm->mp_mode && iot_table->patch_id_021f0800) /*CS ratio:BW20/1R*/ odm_set_bb_reg(dm, R_0x1ad0, 0x1f, 0x12); } __odm_func__ boolean config_phydm_parameter_init_8822c(struct dm_struct *dm, enum odm_parameter_init type) { PHYDM_DBG(dm, ODM_PHY_CONFIG, "%s ======>\n", __func__); phydm_cck_gi_bound_8822c(dm); phydm_cck_pd_init_8822c(dm); if (*dm->mp_mode) phydm_ch_smooth_setting_8822c(dm, true); /* Disable low rate DPD*/ if (dm->en_dis_dpd) phydm_set_dis_dpd_by_rate_8822c(dm, 0x3ff); else phydm_set_dis_dpd_by_rate_8822c(dm, 0x0); /* @Do not use PHYDM API to read/write because FW can not access */ /* @Turn on 3-wire*/ odm_set_bb_reg(dm, R_0x180c, 0x3, 0x3); odm_set_bb_reg(dm, R_0x180c, BIT(28), 0x1); odm_set_bb_reg(dm, R_0x410c, 0x3, 0x3); odm_set_bb_reg(dm, R_0x410c, BIT(28), 0x1); if (type == ODM_PRE_SETTING) { odm_set_bb_reg(dm, R_0x1c3c, (BIT(0) | BIT(1)), 0x0); PHYDM_DBG(dm, ODM_PHY_CONFIG, "Pre setting: disable OFDM and CCK block\n"); } else if (type == ODM_POST_SETTING) { odm_set_bb_reg(dm, R_0x1c3c, (BIT(0) | BIT(1)), 0x3); PHYDM_DBG(dm, ODM_PHY_CONFIG, "Post setting: enable OFDM and CCK block\n"); } else { PHYDM_DBG(dm, ODM_PHY_CONFIG, "Wrong type!!\n"); return false; } phydm_bb_reset_8822c(dm); #ifdef CONFIG_TXAGC_DEBUG_8822C /*phydm_txagc_tab_buff_init_8822c(dm);*/ #endif return true; } __odm_func__ boolean phydm_chk_bb_state_idle_8822c(struct dm_struct *dm) { u32 dbgport = 0; /* Do not check GNT_WL for LPS */ odm_set_bb_reg(dm, R_0x1c3c, 0x00f00000, 0x0); dbgport = odm_get_bb_reg(dm, R_0x2db4, MASKDWORD); if ((dbgport & 0x1ffeff3f) == 0 && (dbgport & 0xc0000000) == 0xc0000000) return true; else return false; } #if CONFIG_POWERSAVING __odm_func_aon__ boolean phydm_8822c_lps(struct dm_struct *dm, boolean enable_lps) { u16 poll_cnt = 0; u32 bbtemp = 0; if (enable_lps == _TRUE) { /* backup RF reg0x0 */ SysMib.Wlan.PS.PSParm.RxGainPathA = config_phydm_read_rf_reg_8822c(dm, RF_PATH_A, RF_0x0, RFREG_MASK); SysMib.Wlan.PS.PSParm.RxGainPathB = config_phydm_read_rf_reg_8822c(dm, RF_PATH_B, RF_0x0, RFREG_MASK); /* turn off TRx HSSI*/ odm_set_bb_reg(dm, R_0x180c, 0x3, 0x0); odm_set_bb_reg(dm, R_0x410c, 0x3, 0x0); /* Set RF enter shutdown mode*/ bbtemp = odm_get_bb_reg(dm, R_0x824, MASKDWORD); odm_set_bb_reg(dm, R_0x824, 0xf0000, 0x3); config_phydm_write_rf_reg_8822c(dm, RF_PATH_A, RF_0x0, RFREG_MASK, 0x0); config_phydm_write_rf_reg_8822c(dm, RF_PATH_B, RF_0x0, RFREG_MASK, 0x0); odm_set_bb_reg(dm, R_0x824, MASKDWORD, bbtemp); /*bb reset w/o 3-wires */ phydm_bb_reset_no_3wires_8822c(dm); while (1) { if (phydm_chk_bb_state_idle_8822c(dm)) break; if (poll_cnt > WAIT_TXSM_STABLE_CNT) { WriteMACRegDWord(REG_DBG_DW_FW_ERR, ReadMACRegDWord(REG_DBG_DW_FW_ERR) | FES_BBSTATE_IDLE); /* SysMib.Wlan.DbgPort.DbgInfoParm.u4ErrFlag[0] |= FES_BBSTATE_IDLE; */ return _FALSE; } DelayUS(WAIT_TXSM_STABLE_ONCE_TIME); poll_cnt++; } /* disable CCK and OFDM module */ WriteMACRegByte(REG_SYS_FUNC_EN, ReadMACRegByte(REG_SYS_FUNC_EN) & ~BIT_FEN_BBRSTB); if (poll_cnt < WAIT_TXSM_STABLE_CNT) { /* Gated BBclk*/ odm_set_bb_reg(dm, R_0x1c24, BIT(0), 0x1); } return _TRUE; } else { /* release BB clk*/ odm_set_bb_reg(dm, R_0x1c24, BIT(0), 0x0); PwrGatedRestoreBB(); /* Enable CCK and OFDM module, */ /* should be a delay large than 200ns before RF access */ WriteMACRegByte(REG_SYS_FUNC_EN, ReadMACRegByte(REG_SYS_FUNC_EN) | BIT_FEN_BBRSTB); DelayUS(1); /* Set RF enter active mode */ bbtemp = odm_get_bb_reg(dm, R_0x824, MASKDWORD); odm_set_bb_reg(dm, R_0x824, 0xf0000, 0x3); config_phydm_write_rf_reg_8822c(dm, RF_PATH_A, RF_0x0, RFREG_MASK, SysMib.Wlan.PS.PSParm.RxGainPathA); config_phydm_write_rf_reg_8822c(dm, RF_PATH_B, RF_0x0, RFREG_MASK, SysMib.Wlan.PS.PSParm.RxGainPathB); odm_set_bb_reg(dm, R_0x824, MASKDWORD, bbtemp); /*bb reset w/o 3-wires */ phydm_bb_reset_no_3wires_8822c(dm); /* turn on TRx HSSI*/ odm_set_bb_reg(dm, R_0x180c, 0x3, 0x3); odm_set_bb_reg(dm, R_0x410c, 0x3, 0x3); return _TRUE; } } #endif /* #if CONFIG_POWERSAVING */ /* ======================================================================== */ #endif /* PHYDM_FW_API_ENABLE_8822C */ #endif /* RTL8822C_SUPPORT */