1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2016  Realtek Corporation.
5  *
6  * Contact Information:
7  * wlanfae <wlanfae@realtek.com>
8  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
9  * Hsinchu 300, Taiwan.
10  *
11  * Larry Finger <Larry.Finger@lwfinger.net>
12  *
13  *****************************************************************************/
14 
15 #include "../mp_precomp.h"
16 #include "../phydm_precomp.h"
17 
phydm_dynamic_switch_htstf_mumimo_8822b(struct phy_dm_struct * dm)18 static void phydm_dynamic_switch_htstf_mumimo_8822b(struct phy_dm_struct *dm)
19 {
20 	/*if rssi > 40dBm, enable HT-STF gain controller,
21 	 *otherwise, if rssi < 40dBm, disable the controller
22 	 */
23 	/*add by Chun-Hung Ho 20160711 */
24 	if (dm->rssi_min >= 40)
25 		odm_set_bb_reg(dm, 0x8d8, BIT(17), 0x1);
26 	else if (dm->rssi_min < 35)
27 		odm_set_bb_reg(dm, 0x8d8, BIT(17), 0x0);
28 
29 	ODM_RT_TRACE(dm, ODM_COMP_COMMON, "%s, rssi_min = %d\n", __func__,
30 		     dm->rssi_min);
31 }
32 
_set_tx_a_cali_value(struct phy_dm_struct * dm,u8 rf_path,u8 offset,u8 tx_a_bias_offset)33 static void _set_tx_a_cali_value(struct phy_dm_struct *dm, u8 rf_path,
34 				 u8 offset, u8 tx_a_bias_offset)
35 {
36 	u32 modi_tx_a_value = 0;
37 	u8 tmp1_byte = 0;
38 	bool is_minus = false;
39 	u8 comp_value = 0;
40 
41 	switch (offset) {
42 	case 0x0:
43 		odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X10124);
44 		break;
45 	case 0x1:
46 		odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X10524);
47 		break;
48 	case 0x2:
49 		odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X10924);
50 		break;
51 	case 0x3:
52 		odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X10D24);
53 		break;
54 	case 0x4:
55 		odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X30164);
56 		break;
57 	case 0x5:
58 		odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X30564);
59 		break;
60 	case 0x6:
61 		odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X30964);
62 		break;
63 	case 0x7:
64 		odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X30D64);
65 		break;
66 	case 0x8:
67 		odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X50195);
68 		break;
69 	case 0x9:
70 		odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X50595);
71 		break;
72 	case 0xa:
73 		odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X50995);
74 		break;
75 	case 0xb:
76 		odm_set_rf_reg(dm, rf_path, 0x18, 0xFFFFF, 0X50D95);
77 		break;
78 	default:
79 		ODM_RT_TRACE(dm, ODM_COMP_COMMON,
80 			     "Invalid TxA band offset...\n");
81 		return;
82 	}
83 
84 	/* Get TxA value */
85 	modi_tx_a_value = odm_get_rf_reg(dm, rf_path, 0x61, 0xFFFFF);
86 	tmp1_byte = (u8)modi_tx_a_value & (BIT(3) | BIT(2) | BIT(1) | BIT(0));
87 
88 	/* check how much need to calibration */
89 	switch (tx_a_bias_offset) {
90 	case 0xF6:
91 		is_minus = true;
92 		comp_value = 3;
93 		break;
94 
95 	case 0xF4:
96 		is_minus = true;
97 		comp_value = 2;
98 		break;
99 
100 	case 0xF2:
101 		is_minus = true;
102 		comp_value = 1;
103 		break;
104 
105 	case 0xF3:
106 		is_minus = false;
107 		comp_value = 1;
108 		break;
109 
110 	case 0xF5:
111 		is_minus = false;
112 		comp_value = 2;
113 		break;
114 
115 	case 0xF7:
116 		is_minus = false;
117 		comp_value = 3;
118 		break;
119 
120 	case 0xF9:
121 		is_minus = false;
122 		comp_value = 4;
123 		break;
124 
125 	/* do nothing case */
126 	case 0xF0:
127 	default:
128 		ODM_RT_TRACE(dm, ODM_COMP_COMMON,
129 			     "No need to do TxA bias current calibration\n");
130 		return;
131 	}
132 
133 	/* calc correct value to calibrate */
134 	if (is_minus) {
135 		if (tmp1_byte >= comp_value) {
136 			tmp1_byte -= comp_value;
137 			/*modi_tx_a_value += tmp1_byte;*/
138 		} else {
139 			tmp1_byte = 0;
140 		}
141 	} else {
142 		tmp1_byte += comp_value;
143 		if (tmp1_byte >= 7)
144 			tmp1_byte = 7;
145 	}
146 
147 	/* Write back to RF reg */
148 	odm_set_rf_reg(dm, rf_path, 0x30, 0xFFFF,
149 		       (offset << 12 | (modi_tx_a_value & 0xFF0) | tmp1_byte));
150 }
151 
_txa_bias_cali_4_each_path(struct phy_dm_struct * dm,u8 rf_path,u8 efuse_value)152 static void _txa_bias_cali_4_each_path(struct phy_dm_struct *dm, u8 rf_path,
153 				       u8 efuse_value)
154 {
155 	/* switch on set TxA bias */
156 	odm_set_rf_reg(dm, rf_path, 0xEF, 0xFFFFF, 0x200);
157 
158 	/* Set 12 sets of TxA value */
159 	_set_tx_a_cali_value(dm, rf_path, 0x0, efuse_value);
160 	_set_tx_a_cali_value(dm, rf_path, 0x1, efuse_value);
161 	_set_tx_a_cali_value(dm, rf_path, 0x2, efuse_value);
162 	_set_tx_a_cali_value(dm, rf_path, 0x3, efuse_value);
163 	_set_tx_a_cali_value(dm, rf_path, 0x4, efuse_value);
164 	_set_tx_a_cali_value(dm, rf_path, 0x5, efuse_value);
165 	_set_tx_a_cali_value(dm, rf_path, 0x6, efuse_value);
166 	_set_tx_a_cali_value(dm, rf_path, 0x7, efuse_value);
167 	_set_tx_a_cali_value(dm, rf_path, 0x8, efuse_value);
168 	_set_tx_a_cali_value(dm, rf_path, 0x9, efuse_value);
169 	_set_tx_a_cali_value(dm, rf_path, 0xa, efuse_value);
170 	_set_tx_a_cali_value(dm, rf_path, 0xb, efuse_value);
171 
172 	/* switch off set TxA bias */
173 	odm_set_rf_reg(dm, rf_path, 0xEF, 0xFFFFF, 0x0);
174 }
175 
176 /*
177  * for 8822B PCIE D-cut patch only
178  * Normal driver and MP driver need this patch
179  */
180 
phydm_txcurrentcalibration(struct phy_dm_struct * dm)181 void phydm_txcurrentcalibration(struct phy_dm_struct *dm)
182 {
183 	u8 efuse0x3D8, efuse0x3D7;
184 	u32 orig_rf0x18_path_a = 0, orig_rf0x18_path_b = 0;
185 
186 	/* save original 0x18 value */
187 	orig_rf0x18_path_a = odm_get_rf_reg(dm, ODM_RF_PATH_A, 0x18, 0xFFFFF);
188 	orig_rf0x18_path_b = odm_get_rf_reg(dm, ODM_RF_PATH_B, 0x18, 0xFFFFF);
189 
190 	/* define efuse content */
191 	efuse0x3D8 = dm->efuse0x3d8;
192 	efuse0x3D7 = dm->efuse0x3d7;
193 
194 	/* check efuse content to judge whether need to calibration or not */
195 	if (efuse0x3D7 == 0xFF) {
196 		ODM_RT_TRACE(
197 			dm, ODM_COMP_COMMON,
198 			"efuse content 0x3D7 == 0xFF, No need to do TxA cali\n");
199 		return;
200 	}
201 
202 	/* write RF register for calibration */
203 	_txa_bias_cali_4_each_path(dm, ODM_RF_PATH_A, efuse0x3D7);
204 	_txa_bias_cali_4_each_path(dm, ODM_RF_PATH_B, efuse0x3D8);
205 
206 	/* restore original 0x18 value */
207 	odm_set_rf_reg(dm, ODM_RF_PATH_A, 0x18, 0xFFFFF, orig_rf0x18_path_a);
208 	odm_set_rf_reg(dm, ODM_RF_PATH_B, 0x18, 0xFFFFF, orig_rf0x18_path_b);
209 }
210 
phydm_hwsetting_8822b(struct phy_dm_struct * dm)211 void phydm_hwsetting_8822b(struct phy_dm_struct *dm)
212 {
213 	phydm_dynamic_switch_htstf_mumimo_8822b(dm);
214 }
215