18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright(c) 2009-2012  Realtek Corporation.*/
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include "../wifi.h"
58c2ecf20Sopenharmony_ci#include "reg.h"
68c2ecf20Sopenharmony_ci#include "def.h"
78c2ecf20Sopenharmony_ci#include "phy.h"
88c2ecf20Sopenharmony_ci#include "rf.h"
98c2ecf20Sopenharmony_ci#include "dm.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_cistatic void _rtl92s_get_powerbase(struct ieee80211_hw *hw, u8 *p_pwrlevel,
138c2ecf20Sopenharmony_ci				  u8 chnl, u32 *ofdmbase, u32 *mcsbase,
148c2ecf20Sopenharmony_ci				  u8 *p_final_pwridx)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
178c2ecf20Sopenharmony_ci	struct rtl_phy *rtlphy = &(rtlpriv->phy);
188c2ecf20Sopenharmony_ci	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
198c2ecf20Sopenharmony_ci	u32 pwrbase0, pwrbase1;
208c2ecf20Sopenharmony_ci	u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0;
218c2ecf20Sopenharmony_ci	u8 i, pwrlevel[4];
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	for (i = 0; i < 2; i++)
248c2ecf20Sopenharmony_ci		pwrlevel[i] = p_pwrlevel[i];
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	/* We only care about the path A for legacy. */
278c2ecf20Sopenharmony_ci	if (rtlefuse->eeprom_version < 2) {
288c2ecf20Sopenharmony_ci		pwrbase0 = pwrlevel[0] + (rtlefuse->legacy_ht_txpowerdiff & 0xf);
298c2ecf20Sopenharmony_ci	} else {
308c2ecf20Sopenharmony_ci		legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff
318c2ecf20Sopenharmony_ci						[RF90_PATH_A][chnl - 1];
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci		/* For legacy OFDM, tx pwr always > HT OFDM pwr.
348c2ecf20Sopenharmony_ci		 * We do not care Path B
358c2ecf20Sopenharmony_ci		 * legacy OFDM pwr diff. NO BB register
368c2ecf20Sopenharmony_ci		 * to notify HW. */
378c2ecf20Sopenharmony_ci		pwrbase0 = pwrlevel[0] + legacy_pwrdiff;
388c2ecf20Sopenharmony_ci	}
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	pwrbase0 = (pwrbase0 << 24) | (pwrbase0 << 16) | (pwrbase0 << 8) |
418c2ecf20Sopenharmony_ci		    pwrbase0;
428c2ecf20Sopenharmony_ci	*ofdmbase = pwrbase0;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	/* MCS rates */
458c2ecf20Sopenharmony_ci	if (rtlefuse->eeprom_version >= 2) {
468c2ecf20Sopenharmony_ci		/* Check HT20 to HT40 diff	*/
478c2ecf20Sopenharmony_ci		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
488c2ecf20Sopenharmony_ci			for (i = 0; i < 2; i++) {
498c2ecf20Sopenharmony_ci				/* rf-A, rf-B */
508c2ecf20Sopenharmony_ci				/* HT 20<->40 pwr diff */
518c2ecf20Sopenharmony_ci				ht20_pwrdiff = rtlefuse->txpwr_ht20diff
528c2ecf20Sopenharmony_ci							[i][chnl - 1];
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci				if (ht20_pwrdiff < 8) /* 0~+7 */
558c2ecf20Sopenharmony_ci					pwrlevel[i] += ht20_pwrdiff;
568c2ecf20Sopenharmony_ci				else /* index8-15=-8~-1 */
578c2ecf20Sopenharmony_ci					pwrlevel[i] -= (16 - ht20_pwrdiff);
588c2ecf20Sopenharmony_ci			}
598c2ecf20Sopenharmony_ci		}
608c2ecf20Sopenharmony_ci	}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	/* use index of rf-A */
638c2ecf20Sopenharmony_ci	pwrbase1 = pwrlevel[0];
648c2ecf20Sopenharmony_ci	pwrbase1 = (pwrbase1 << 24) | (pwrbase1 << 16) | (pwrbase1 << 8) |
658c2ecf20Sopenharmony_ci				pwrbase1;
668c2ecf20Sopenharmony_ci	*mcsbase = pwrbase1;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	/* The following is for Antenna
698c2ecf20Sopenharmony_ci	 * diff from Ant-B to Ant-A */
708c2ecf20Sopenharmony_ci	p_final_pwridx[0] = pwrlevel[0];
718c2ecf20Sopenharmony_ci	p_final_pwridx[1] = pwrlevel[1];
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	switch (rtlefuse->eeprom_regulatory) {
748c2ecf20Sopenharmony_ci	case 3:
758c2ecf20Sopenharmony_ci		/* The following is for calculation
768c2ecf20Sopenharmony_ci		 * of the power diff for Ant-B to Ant-A. */
778c2ecf20Sopenharmony_ci		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
788c2ecf20Sopenharmony_ci			p_final_pwridx[0] += rtlefuse->pwrgroup_ht40
798c2ecf20Sopenharmony_ci						[RF90_PATH_A][
808c2ecf20Sopenharmony_ci						chnl - 1];
818c2ecf20Sopenharmony_ci			p_final_pwridx[1] += rtlefuse->pwrgroup_ht40
828c2ecf20Sopenharmony_ci						[RF90_PATH_B][
838c2ecf20Sopenharmony_ci						chnl - 1];
848c2ecf20Sopenharmony_ci		} else {
858c2ecf20Sopenharmony_ci			p_final_pwridx[0] += rtlefuse->pwrgroup_ht20
868c2ecf20Sopenharmony_ci						[RF90_PATH_A][
878c2ecf20Sopenharmony_ci						chnl - 1];
888c2ecf20Sopenharmony_ci			p_final_pwridx[1] += rtlefuse->pwrgroup_ht20
898c2ecf20Sopenharmony_ci						[RF90_PATH_B][
908c2ecf20Sopenharmony_ci						chnl - 1];
918c2ecf20Sopenharmony_ci		}
928c2ecf20Sopenharmony_ci		break;
938c2ecf20Sopenharmony_ci	default:
948c2ecf20Sopenharmony_ci		break;
958c2ecf20Sopenharmony_ci	}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
988c2ecf20Sopenharmony_ci		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
998c2ecf20Sopenharmony_ci			"40MHz finalpwr_idx (A / B) = 0x%x / 0x%x\n",
1008c2ecf20Sopenharmony_ci			p_final_pwridx[0], p_final_pwridx[1]);
1018c2ecf20Sopenharmony_ci	} else {
1028c2ecf20Sopenharmony_ci		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
1038c2ecf20Sopenharmony_ci			"20MHz finalpwr_idx (A / B) = 0x%x / 0x%x\n",
1048c2ecf20Sopenharmony_ci			p_final_pwridx[0], p_final_pwridx[1]);
1058c2ecf20Sopenharmony_ci	}
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cistatic void _rtl92s_set_antennadiff(struct ieee80211_hw *hw,
1098c2ecf20Sopenharmony_ci				    u8 *p_final_pwridx)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
1128c2ecf20Sopenharmony_ci	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1138c2ecf20Sopenharmony_ci	struct rtl_phy *rtlphy = &(rtlpriv->phy);
1148c2ecf20Sopenharmony_ci	s8 ant_pwr_diff = 0;
1158c2ecf20Sopenharmony_ci	u32	u4reg_val = 0;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	if (rtlphy->rf_type == RF_2T2R) {
1188c2ecf20Sopenharmony_ci		ant_pwr_diff = p_final_pwridx[1] - p_final_pwridx[0];
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci		/* range is from 7~-8,
1218c2ecf20Sopenharmony_ci		 * index = 0x0~0xf */
1228c2ecf20Sopenharmony_ci		if (ant_pwr_diff > 7)
1238c2ecf20Sopenharmony_ci			ant_pwr_diff = 7;
1248c2ecf20Sopenharmony_ci		if (ant_pwr_diff < -8)
1258c2ecf20Sopenharmony_ci			ant_pwr_diff = -8;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
1288c2ecf20Sopenharmony_ci			"Antenna Diff from RF-B to RF-A = %d (0x%x)\n",
1298c2ecf20Sopenharmony_ci			ant_pwr_diff, ant_pwr_diff & 0xf);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci		ant_pwr_diff &= 0xf;
1328c2ecf20Sopenharmony_ci	}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	/* Antenna TX power difference */
1358c2ecf20Sopenharmony_ci	rtlefuse->antenna_txpwdiff[2] = 0;/* RF-D, don't care */
1368c2ecf20Sopenharmony_ci	rtlefuse->antenna_txpwdiff[1] = 0;/* RF-C, don't care */
1378c2ecf20Sopenharmony_ci	rtlefuse->antenna_txpwdiff[0] = (u8)(ant_pwr_diff);	/* RF-B */
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	u4reg_val = rtlefuse->antenna_txpwdiff[2] << 8 |
1408c2ecf20Sopenharmony_ci				rtlefuse->antenna_txpwdiff[1] << 4 |
1418c2ecf20Sopenharmony_ci				rtlefuse->antenna_txpwdiff[0];
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	rtl_set_bbreg(hw, RFPGA0_TXGAINSTAGE, (BXBTXAGC | BXCTXAGC | BXDTXAGC),
1448c2ecf20Sopenharmony_ci		      u4reg_val);
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, "Write BCD-Diff(0x%x) = 0x%x\n",
1478c2ecf20Sopenharmony_ci		RFPGA0_TXGAINSTAGE, u4reg_val);
1488c2ecf20Sopenharmony_ci}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_cistatic void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw,
1518c2ecf20Sopenharmony_ci						      u8 chnl, u8 index,
1528c2ecf20Sopenharmony_ci						      u32 pwrbase0,
1538c2ecf20Sopenharmony_ci						      u32 pwrbase1,
1548c2ecf20Sopenharmony_ci						      u32 *p_outwrite_val)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
1578c2ecf20Sopenharmony_ci	struct rtl_phy *rtlphy = &(rtlpriv->phy);
1588c2ecf20Sopenharmony_ci	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1598c2ecf20Sopenharmony_ci	u8 i, chnlgroup, pwrdiff_limit[4];
1608c2ecf20Sopenharmony_ci	u32 writeval, customer_limit;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	/* Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */
1638c2ecf20Sopenharmony_ci	switch (rtlefuse->eeprom_regulatory) {
1648c2ecf20Sopenharmony_ci	case 0:
1658c2ecf20Sopenharmony_ci		/* Realtek better performance increase power diff
1668c2ecf20Sopenharmony_ci		 * defined by Realtek for large power */
1678c2ecf20Sopenharmony_ci		chnlgroup = 0;
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci		writeval = rtlphy->mcs_offset[chnlgroup][index] +
1708c2ecf20Sopenharmony_ci				((index < 2) ? pwrbase0 : pwrbase1);
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
1738c2ecf20Sopenharmony_ci			"RTK better performance, writeval = 0x%x\n", writeval);
1748c2ecf20Sopenharmony_ci		break;
1758c2ecf20Sopenharmony_ci	case 1:
1768c2ecf20Sopenharmony_ci		/* Realtek regulatory increase power diff defined
1778c2ecf20Sopenharmony_ci		 * by Realtek for regulatory */
1788c2ecf20Sopenharmony_ci		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
1798c2ecf20Sopenharmony_ci			writeval = ((index < 2) ? pwrbase0 : pwrbase1);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
1828c2ecf20Sopenharmony_ci				"Realtek regulatory, 40MHz, writeval = 0x%x\n",
1838c2ecf20Sopenharmony_ci				writeval);
1848c2ecf20Sopenharmony_ci		} else {
1858c2ecf20Sopenharmony_ci			chnlgroup = 0;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci			if (rtlphy->pwrgroup_cnt >= 3) {
1888c2ecf20Sopenharmony_ci				if (chnl <= 3)
1898c2ecf20Sopenharmony_ci					chnlgroup = 0;
1908c2ecf20Sopenharmony_ci				else if (chnl >= 4 && chnl <= 8)
1918c2ecf20Sopenharmony_ci					chnlgroup = 1;
1928c2ecf20Sopenharmony_ci				else if (chnl > 8)
1938c2ecf20Sopenharmony_ci					chnlgroup = 2;
1948c2ecf20Sopenharmony_ci				if (rtlphy->pwrgroup_cnt == 4)
1958c2ecf20Sopenharmony_ci					chnlgroup++;
1968c2ecf20Sopenharmony_ci			}
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci			writeval = rtlphy->mcs_offset[chnlgroup][index]
1998c2ecf20Sopenharmony_ci					+ ((index < 2) ?
2008c2ecf20Sopenharmony_ci					pwrbase0 : pwrbase1);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
2038c2ecf20Sopenharmony_ci				"Realtek regulatory, 20MHz, writeval = 0x%x\n",
2048c2ecf20Sopenharmony_ci				writeval);
2058c2ecf20Sopenharmony_ci		}
2068c2ecf20Sopenharmony_ci		break;
2078c2ecf20Sopenharmony_ci	case 2:
2088c2ecf20Sopenharmony_ci		/* Better regulatory don't increase any power diff */
2098c2ecf20Sopenharmony_ci		writeval = ((index < 2) ? pwrbase0 : pwrbase1);
2108c2ecf20Sopenharmony_ci		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
2118c2ecf20Sopenharmony_ci			"Better regulatory, writeval = 0x%x\n", writeval);
2128c2ecf20Sopenharmony_ci		break;
2138c2ecf20Sopenharmony_ci	case 3:
2148c2ecf20Sopenharmony_ci		/* Customer defined power diff. increase power diff
2158c2ecf20Sopenharmony_ci		  defined by customer. */
2168c2ecf20Sopenharmony_ci		chnlgroup = 0;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
2198c2ecf20Sopenharmony_ci			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
2208c2ecf20Sopenharmony_ci				"customer's limit, 40MHz = 0x%x\n",
2218c2ecf20Sopenharmony_ci				rtlefuse->pwrgroup_ht40
2228c2ecf20Sopenharmony_ci				[RF90_PATH_A][chnl - 1]);
2238c2ecf20Sopenharmony_ci		} else {
2248c2ecf20Sopenharmony_ci			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
2258c2ecf20Sopenharmony_ci				"customer's limit, 20MHz = 0x%x\n",
2268c2ecf20Sopenharmony_ci				rtlefuse->pwrgroup_ht20
2278c2ecf20Sopenharmony_ci				[RF90_PATH_A][chnl - 1]);
2288c2ecf20Sopenharmony_ci		}
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci		for (i = 0; i < 4; i++) {
2318c2ecf20Sopenharmony_ci			pwrdiff_limit[i] = (u8)((rtlphy->mcs_offset
2328c2ecf20Sopenharmony_ci				[chnlgroup][index] & (0x7f << (i * 8)))
2338c2ecf20Sopenharmony_ci				>> (i * 8));
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci			if (rtlphy->current_chan_bw ==
2368c2ecf20Sopenharmony_ci			    HT_CHANNEL_WIDTH_20_40) {
2378c2ecf20Sopenharmony_ci				if (pwrdiff_limit[i] >
2388c2ecf20Sopenharmony_ci				    rtlefuse->pwrgroup_ht40
2398c2ecf20Sopenharmony_ci				    [RF90_PATH_A][chnl - 1]) {
2408c2ecf20Sopenharmony_ci					pwrdiff_limit[i] =
2418c2ecf20Sopenharmony_ci					  rtlefuse->pwrgroup_ht40
2428c2ecf20Sopenharmony_ci					  [RF90_PATH_A][chnl - 1];
2438c2ecf20Sopenharmony_ci				}
2448c2ecf20Sopenharmony_ci			} else {
2458c2ecf20Sopenharmony_ci				if (pwrdiff_limit[i] >
2468c2ecf20Sopenharmony_ci				    rtlefuse->pwrgroup_ht20
2478c2ecf20Sopenharmony_ci				    [RF90_PATH_A][chnl - 1]) {
2488c2ecf20Sopenharmony_ci					pwrdiff_limit[i] =
2498c2ecf20Sopenharmony_ci					    rtlefuse->pwrgroup_ht20
2508c2ecf20Sopenharmony_ci					    [RF90_PATH_A][chnl - 1];
2518c2ecf20Sopenharmony_ci				}
2528c2ecf20Sopenharmony_ci			}
2538c2ecf20Sopenharmony_ci		}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci		customer_limit = (pwrdiff_limit[3] << 24) |
2568c2ecf20Sopenharmony_ci				(pwrdiff_limit[2] << 16) |
2578c2ecf20Sopenharmony_ci				(pwrdiff_limit[1] << 8) |
2588c2ecf20Sopenharmony_ci				(pwrdiff_limit[0]);
2598c2ecf20Sopenharmony_ci		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
2608c2ecf20Sopenharmony_ci			"Customer's limit = 0x%x\n", customer_limit);
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci		writeval = customer_limit + ((index < 2) ?
2638c2ecf20Sopenharmony_ci					     pwrbase0 : pwrbase1);
2648c2ecf20Sopenharmony_ci		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
2658c2ecf20Sopenharmony_ci			"Customer, writeval = 0x%x\n", writeval);
2668c2ecf20Sopenharmony_ci		break;
2678c2ecf20Sopenharmony_ci	default:
2688c2ecf20Sopenharmony_ci		chnlgroup = 0;
2698c2ecf20Sopenharmony_ci		writeval = rtlphy->mcs_offset[chnlgroup][index] +
2708c2ecf20Sopenharmony_ci				((index < 2) ? pwrbase0 : pwrbase1);
2718c2ecf20Sopenharmony_ci		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
2728c2ecf20Sopenharmony_ci			"RTK better performance, writeval = 0x%x\n", writeval);
2738c2ecf20Sopenharmony_ci		break;
2748c2ecf20Sopenharmony_ci	}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	if (rtlpriv->dm.dynamic_txhighpower_lvl == TX_HIGH_PWR_LEVEL_LEVEL1)
2778c2ecf20Sopenharmony_ci		writeval = 0x10101010;
2788c2ecf20Sopenharmony_ci	else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
2798c2ecf20Sopenharmony_ci		 TX_HIGH_PWR_LEVEL_LEVEL2)
2808c2ecf20Sopenharmony_ci		writeval = 0x0;
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	*p_outwrite_val = writeval;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_cistatic void _rtl92s_write_ofdm_powerreg(struct ieee80211_hw *hw,
2878c2ecf20Sopenharmony_ci					u8 index, u32 val)
2888c2ecf20Sopenharmony_ci{
2898c2ecf20Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
2908c2ecf20Sopenharmony_ci	struct rtl_phy *rtlphy = &(rtlpriv->phy);
2918c2ecf20Sopenharmony_ci	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2928c2ecf20Sopenharmony_ci	u16 regoffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c};
2938c2ecf20Sopenharmony_ci	u8 i, rfa_pwr[4];
2948c2ecf20Sopenharmony_ci	u8 rfa_lower_bound = 0, rfa_upper_bound = 0, rf_pwr_diff = 0;
2958c2ecf20Sopenharmony_ci	u32 writeval = val;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	/* If path A and Path B coexist, we must limit Path A tx power.
2988c2ecf20Sopenharmony_ci	 * Protect Path B pwr over or under flow. We need to calculate
2998c2ecf20Sopenharmony_ci	 * upper and lower bound of path A tx power. */
3008c2ecf20Sopenharmony_ci	if (rtlphy->rf_type == RF_2T2R) {
3018c2ecf20Sopenharmony_ci		rf_pwr_diff = rtlefuse->antenna_txpwdiff[0];
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci		/* Diff=-8~-1 */
3048c2ecf20Sopenharmony_ci		if (rf_pwr_diff >= 8) {
3058c2ecf20Sopenharmony_ci			/* Prevent underflow!! */
3068c2ecf20Sopenharmony_ci			rfa_lower_bound = 0x10 - rf_pwr_diff;
3078c2ecf20Sopenharmony_ci		/* if (rf_pwr_diff >= 0) Diff = 0-7 */
3088c2ecf20Sopenharmony_ci		} else {
3098c2ecf20Sopenharmony_ci			rfa_upper_bound = RF6052_MAX_TX_PWR - rf_pwr_diff;
3108c2ecf20Sopenharmony_ci		}
3118c2ecf20Sopenharmony_ci	}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++) {
3148c2ecf20Sopenharmony_ci		rfa_pwr[i] = (u8)((writeval & (0x7f << (i * 8))) >> (i * 8));
3158c2ecf20Sopenharmony_ci		if (rfa_pwr[i]  > RF6052_MAX_TX_PWR)
3168c2ecf20Sopenharmony_ci			rfa_pwr[i]  = RF6052_MAX_TX_PWR;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci		/* If path A and Path B coexist, we must limit Path A tx power.
3198c2ecf20Sopenharmony_ci		 * Protect Path B pwr over or under flow. We need to calculate
3208c2ecf20Sopenharmony_ci		 * upper and lower bound of path A tx power. */
3218c2ecf20Sopenharmony_ci		if (rtlphy->rf_type == RF_2T2R) {
3228c2ecf20Sopenharmony_ci			/* Diff=-8~-1 */
3238c2ecf20Sopenharmony_ci			if (rf_pwr_diff >= 8) {
3248c2ecf20Sopenharmony_ci				/* Prevent underflow!! */
3258c2ecf20Sopenharmony_ci				if (rfa_pwr[i] < rfa_lower_bound)
3268c2ecf20Sopenharmony_ci					rfa_pwr[i] = rfa_lower_bound;
3278c2ecf20Sopenharmony_ci			/* Diff = 0-7 */
3288c2ecf20Sopenharmony_ci			} else if (rf_pwr_diff >= 1) {
3298c2ecf20Sopenharmony_ci				/* Prevent overflow */
3308c2ecf20Sopenharmony_ci				if (rfa_pwr[i] > rfa_upper_bound)
3318c2ecf20Sopenharmony_ci					rfa_pwr[i] = rfa_upper_bound;
3328c2ecf20Sopenharmony_ci			}
3338c2ecf20Sopenharmony_ci		}
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	writeval = (rfa_pwr[3] << 24) | (rfa_pwr[2] << 16) | (rfa_pwr[1] << 8) |
3388c2ecf20Sopenharmony_ci				rfa_pwr[0];
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	rtl_set_bbreg(hw, regoffset[index], 0x7f7f7f7f, writeval);
3418c2ecf20Sopenharmony_ci}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_civoid rtl92s_phy_rf6052_set_ofdmtxpower(struct ieee80211_hw *hw,
3448c2ecf20Sopenharmony_ci				       u8 *p_pwrlevel, u8 chnl)
3458c2ecf20Sopenharmony_ci{
3468c2ecf20Sopenharmony_ci	u32 writeval, pwrbase0, pwrbase1;
3478c2ecf20Sopenharmony_ci	u8 index = 0;
3488c2ecf20Sopenharmony_ci	u8 finalpwr_idx[4];
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	_rtl92s_get_powerbase(hw, p_pwrlevel, chnl, &pwrbase0, &pwrbase1,
3518c2ecf20Sopenharmony_ci			&finalpwr_idx[0]);
3528c2ecf20Sopenharmony_ci	_rtl92s_set_antennadiff(hw, &finalpwr_idx[0]);
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	for (index = 0; index < 6; index++) {
3558c2ecf20Sopenharmony_ci		_rtl92s_get_txpower_writeval_byregulatory(hw, chnl, index,
3568c2ecf20Sopenharmony_ci				pwrbase0, pwrbase1, &writeval);
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci		_rtl92s_write_ofdm_powerreg(hw, index, writeval);
3598c2ecf20Sopenharmony_ci	}
3608c2ecf20Sopenharmony_ci}
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_civoid rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, u8 pwrlevel)
3638c2ecf20Sopenharmony_ci{
3648c2ecf20Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
3658c2ecf20Sopenharmony_ci	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
3668c2ecf20Sopenharmony_ci	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
3678c2ecf20Sopenharmony_ci	u32 txagc = 0;
3688c2ecf20Sopenharmony_ci	bool dont_inc_cck_or_turboscanoff = false;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	if (((rtlefuse->eeprom_version >= 2) &&
3718c2ecf20Sopenharmony_ci	      (rtlefuse->txpwr_safetyflag == 1)) ||
3728c2ecf20Sopenharmony_ci	      ((rtlefuse->eeprom_version >= 2) &&
3738c2ecf20Sopenharmony_ci	      (rtlefuse->eeprom_regulatory != 0)))
3748c2ecf20Sopenharmony_ci		dont_inc_cck_or_turboscanoff = true;
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	if (mac->act_scanning) {
3778c2ecf20Sopenharmony_ci		txagc = 0x3f;
3788c2ecf20Sopenharmony_ci		if (dont_inc_cck_or_turboscanoff)
3798c2ecf20Sopenharmony_ci			txagc = pwrlevel;
3808c2ecf20Sopenharmony_ci	} else {
3818c2ecf20Sopenharmony_ci		txagc = pwrlevel;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci		if (rtlpriv->dm.dynamic_txhighpower_lvl ==
3848c2ecf20Sopenharmony_ci		    TX_HIGH_PWR_LEVEL_LEVEL1)
3858c2ecf20Sopenharmony_ci			txagc = 0x10;
3868c2ecf20Sopenharmony_ci		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
3878c2ecf20Sopenharmony_ci			TX_HIGH_PWR_LEVEL_LEVEL2)
3888c2ecf20Sopenharmony_ci			txagc = 0x0;
3898c2ecf20Sopenharmony_ci	}
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	if (txagc > RF6052_MAX_TX_PWR)
3928c2ecf20Sopenharmony_ci		txagc = RF6052_MAX_TX_PWR;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	rtl_set_bbreg(hw, RTXAGC_CCK_MCS32, BTX_AGCRATECCK, txagc);
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_cibool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw)
3998c2ecf20Sopenharmony_ci{
4008c2ecf20Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
4018c2ecf20Sopenharmony_ci	struct rtl_phy *rtlphy = &(rtlpriv->phy);
4028c2ecf20Sopenharmony_ci	u32 u4reg_val = 0;
4038c2ecf20Sopenharmony_ci	u8 rfpath;
4048c2ecf20Sopenharmony_ci	bool rtstatus = true;
4058c2ecf20Sopenharmony_ci	struct bb_reg_def *pphyreg;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	/* Initialize RF */
4088c2ecf20Sopenharmony_ci	for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci		pphyreg = &rtlphy->phyreg_def[rfpath];
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci		/* Store original RFENV control type */
4138c2ecf20Sopenharmony_ci		switch (rfpath) {
4148c2ecf20Sopenharmony_ci		case RF90_PATH_A:
4158c2ecf20Sopenharmony_ci		case RF90_PATH_C:
4168c2ecf20Sopenharmony_ci			u4reg_val = rtl92s_phy_query_bb_reg(hw,
4178c2ecf20Sopenharmony_ci							    pphyreg->rfintfs,
4188c2ecf20Sopenharmony_ci							    BRFSI_RFENV);
4198c2ecf20Sopenharmony_ci			break;
4208c2ecf20Sopenharmony_ci		case RF90_PATH_B:
4218c2ecf20Sopenharmony_ci		case RF90_PATH_D:
4228c2ecf20Sopenharmony_ci			u4reg_val = rtl92s_phy_query_bb_reg(hw,
4238c2ecf20Sopenharmony_ci							    pphyreg->rfintfs,
4248c2ecf20Sopenharmony_ci							    BRFSI_RFENV << 16);
4258c2ecf20Sopenharmony_ci			break;
4268c2ecf20Sopenharmony_ci		}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci		/* Set RF_ENV enable */
4298c2ecf20Sopenharmony_ci		rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfe,
4308c2ecf20Sopenharmony_ci				      BRFSI_RFENV << 16, 0x1);
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci		/* Set RF_ENV output high */
4338c2ecf20Sopenharmony_ci		rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci		/* Set bit number of Address and Data for RF register */
4368c2ecf20Sopenharmony_ci		rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2,
4378c2ecf20Sopenharmony_ci				B3WIRE_ADDRESSLENGTH, 0x0);
4388c2ecf20Sopenharmony_ci		rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2,
4398c2ecf20Sopenharmony_ci				B3WIRE_DATALENGTH, 0x0);
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci		/* Initialize RF fom connfiguration file */
4428c2ecf20Sopenharmony_ci		switch (rfpath) {
4438c2ecf20Sopenharmony_ci		case RF90_PATH_A:
4448c2ecf20Sopenharmony_ci			rtstatus = rtl92s_phy_config_rf(hw,
4458c2ecf20Sopenharmony_ci						(enum radio_path)rfpath);
4468c2ecf20Sopenharmony_ci			break;
4478c2ecf20Sopenharmony_ci		case RF90_PATH_B:
4488c2ecf20Sopenharmony_ci			rtstatus = rtl92s_phy_config_rf(hw,
4498c2ecf20Sopenharmony_ci						(enum radio_path)rfpath);
4508c2ecf20Sopenharmony_ci			break;
4518c2ecf20Sopenharmony_ci		case RF90_PATH_C:
4528c2ecf20Sopenharmony_ci			break;
4538c2ecf20Sopenharmony_ci		case RF90_PATH_D:
4548c2ecf20Sopenharmony_ci			break;
4558c2ecf20Sopenharmony_ci		}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci		/* Restore RFENV control type */
4588c2ecf20Sopenharmony_ci		switch (rfpath) {
4598c2ecf20Sopenharmony_ci		case RF90_PATH_A:
4608c2ecf20Sopenharmony_ci		case RF90_PATH_C:
4618c2ecf20Sopenharmony_ci			rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs, BRFSI_RFENV,
4628c2ecf20Sopenharmony_ci					      u4reg_val);
4638c2ecf20Sopenharmony_ci			break;
4648c2ecf20Sopenharmony_ci		case RF90_PATH_B:
4658c2ecf20Sopenharmony_ci		case RF90_PATH_D:
4668c2ecf20Sopenharmony_ci			rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs,
4678c2ecf20Sopenharmony_ci					      BRFSI_RFENV << 16,
4688c2ecf20Sopenharmony_ci					      u4reg_val);
4698c2ecf20Sopenharmony_ci			break;
4708c2ecf20Sopenharmony_ci		}
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci		if (!rtstatus) {
4738c2ecf20Sopenharmony_ci			pr_err("Radio[%d] Fail!!\n", rfpath);
4748c2ecf20Sopenharmony_ci			goto fail;
4758c2ecf20Sopenharmony_ci		}
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	}
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	return rtstatus;
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_cifail:
4828c2ecf20Sopenharmony_ci	return rtstatus;
4838c2ecf20Sopenharmony_ci}
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_civoid rtl92s_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
4868c2ecf20Sopenharmony_ci{
4878c2ecf20Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
4888c2ecf20Sopenharmony_ci	struct rtl_phy *rtlphy = &(rtlpriv->phy);
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	switch (bandwidth) {
4918c2ecf20Sopenharmony_ci	case HT_CHANNEL_WIDTH_20:
4928c2ecf20Sopenharmony_ci		rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
4938c2ecf20Sopenharmony_ci					   0xfffff3ff) | 0x0400);
4948c2ecf20Sopenharmony_ci		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
4958c2ecf20Sopenharmony_ci					rtlphy->rfreg_chnlval[0]);
4968c2ecf20Sopenharmony_ci		break;
4978c2ecf20Sopenharmony_ci	case HT_CHANNEL_WIDTH_20_40:
4988c2ecf20Sopenharmony_ci		rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
4998c2ecf20Sopenharmony_ci					    0xfffff3ff));
5008c2ecf20Sopenharmony_ci		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
5018c2ecf20Sopenharmony_ci					rtlphy->rfreg_chnlval[0]);
5028c2ecf20Sopenharmony_ci		break;
5038c2ecf20Sopenharmony_ci	default:
5048c2ecf20Sopenharmony_ci		pr_err("unknown bandwidth: %#X\n", bandwidth);
5058c2ecf20Sopenharmony_ci		break;
5068c2ecf20Sopenharmony_ci	}
5078c2ecf20Sopenharmony_ci}
508