1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 *
19 ******************************************************************************/
20#define _RTL8188E_PHYCFG_C_
21
22#include <osdep_service.h>
23#include <drv_types.h>
24#include <rtw_iol.h>
25#include <rtl8188e_hal.h>
26#include <rf.h>
27#include <phy.h>
28
29#define MAX_PRECMD_CNT 16
30#define MAX_RFDEPENDCMD_CNT 16
31#define MAX_POSTCMD_CNT 16
32
33#define MAX_DOZE_WAITING_TIMES_9x 64
34
35static u32 cal_bit_shift(u32 bitmask)
36{
37	u32 i;
38
39	for (i = 0; i <= 31; i++) {
40		if (((bitmask >> i) & 0x1) == 1)
41			break;
42	}
43	return i;
44}
45
46u32 phy_query_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask)
47{
48	u32 return_value = 0, original_value, bit_shift;
49
50	original_value = usb_read32(adapt, regaddr);
51	bit_shift = cal_bit_shift(bitmask);
52	return_value = (original_value & bitmask) >> bit_shift;
53	return return_value;
54}
55
56void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data)
57{
58	u32 original_value, bit_shift;
59
60	if (bitmask != bMaskDWord) { /* if not "double word" write */
61		original_value = usb_read32(adapt, regaddr);
62		bit_shift = cal_bit_shift(bitmask);
63		data = (original_value & (~bitmask)) | (data << bit_shift);
64	}
65
66	usb_write32(adapt, regaddr, data);
67}
68
69static u32 rf_serial_read(struct adapter *adapt,
70			enum rf_radio_path rfpath, u32 offset)
71{
72	u32 ret = 0;
73	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
74	struct bb_reg_def *phyreg = &hal_data->PHYRegDef[rfpath];
75	u32 tmplong, tmplong2;
76	u8 rfpi_enable = 0;
77
78	offset &= 0xff;
79
80	tmplong = phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord);
81	if (rfpath == RF_PATH_A)
82		tmplong2 = tmplong;
83	else
84		tmplong2 = phy_query_bb_reg(adapt, phyreg->rfHSSIPara2,
85					    bMaskDWord);
86
87	tmplong2 = (tmplong2 & (~bLSSIReadAddress)) |
88		   (offset<<23) | bLSSIReadEdge;
89
90	phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord,
91		       tmplong&(~bLSSIReadEdge));
92	udelay(10);
93
94	phy_set_bb_reg(adapt, phyreg->rfHSSIPara2, bMaskDWord, tmplong2);
95	udelay(100);
96
97	udelay(10);
98
99	if (rfpath == RF_PATH_A)
100		rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, BIT8);
101	else if (rfpath == RF_PATH_B)
102		rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, BIT8);
103
104	if (rfpi_enable)
105		ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBackPi,
106				       bLSSIReadBackData);
107	else
108		ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBack,
109				       bLSSIReadBackData);
110	return ret;
111}
112
113static void rf_serial_write(struct adapter *adapt,
114			    enum rf_radio_path rfpath, u32 offset,
115			    u32 data)
116{
117	u32 data_and_addr = 0;
118	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
119	struct bb_reg_def *phyreg = &hal_data->PHYRegDef[rfpath];
120
121	offset &= 0xff;
122	data_and_addr = ((offset<<20) | (data&0x000fffff)) & 0x0fffffff;
123	phy_set_bb_reg(adapt, phyreg->rf3wireOffset, bMaskDWord, data_and_addr);
124}
125
126u32 phy_query_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path,
127		     u32 reg_addr, u32 bit_mask)
128{
129	u32 original_value, readback_value, bit_shift;
130
131	original_value = rf_serial_read(adapt, rf_path, reg_addr);
132	bit_shift =  cal_bit_shift(bit_mask);
133	readback_value = (original_value & bit_mask) >> bit_shift;
134	return readback_value;
135}
136
137void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path,
138		     u32 reg_addr, u32 bit_mask, u32 data)
139{
140	u32 original_value, bit_shift;
141
142	/*  RF data is 12 bits only */
143	if (bit_mask != bRFRegOffsetMask) {
144		original_value = rf_serial_read(adapt, rf_path, reg_addr);
145		bit_shift =  cal_bit_shift(bit_mask);
146		data = (original_value & (~bit_mask)) | (data << bit_shift);
147	}
148
149	rf_serial_write(adapt, rf_path, reg_addr, data);
150}
151
152static void get_tx_power_index(struct adapter *adapt, u8 channel, u8 *cck_pwr,
153			       u8 *ofdm_pwr, u8 *bw20_pwr, u8 *bw40_pwr)
154{
155	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
156	u8 index = (channel - 1);
157	u8 TxCount = 0, path_nums;
158
159	if ((RF_1T2R == hal_data->rf_type) || (RF_1T1R == hal_data->rf_type))
160		path_nums = 1;
161	else
162		path_nums = 2;
163
164	for (TxCount = 0; TxCount < path_nums; TxCount++) {
165		if (TxCount == RF_PATH_A) {
166			cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
167			ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
168					    hal_data->OFDM_24G_Diff[TxCount][RF_PATH_A];
169
170			bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
171					    hal_data->BW20_24G_Diff[TxCount][RF_PATH_A];
172			bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
173		} else if (TxCount == RF_PATH_B) {
174			cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
175			ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
176			hal_data->BW20_24G_Diff[RF_PATH_A][index]+
177			hal_data->BW20_24G_Diff[TxCount][index];
178
179			bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
180			hal_data->BW20_24G_Diff[TxCount][RF_PATH_A]+
181			hal_data->BW20_24G_Diff[TxCount][index];
182			bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
183		} else if (TxCount == RF_PATH_C) {
184			cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
185			ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
186			hal_data->BW20_24G_Diff[RF_PATH_A][index]+
187			hal_data->BW20_24G_Diff[RF_PATH_B][index]+
188			hal_data->BW20_24G_Diff[TxCount][index];
189
190			bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
191			hal_data->BW20_24G_Diff[RF_PATH_A][index]+
192			hal_data->BW20_24G_Diff[RF_PATH_B][index]+
193			hal_data->BW20_24G_Diff[TxCount][index];
194			bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
195		} else if (TxCount == RF_PATH_D) {
196			cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
197			ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
198			hal_data->BW20_24G_Diff[RF_PATH_A][index]+
199			hal_data->BW20_24G_Diff[RF_PATH_B][index]+
200			hal_data->BW20_24G_Diff[RF_PATH_C][index]+
201			hal_data->BW20_24G_Diff[TxCount][index];
202
203			bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
204			hal_data->BW20_24G_Diff[RF_PATH_A][index]+
205			hal_data->BW20_24G_Diff[RF_PATH_B][index]+
206			hal_data->BW20_24G_Diff[RF_PATH_C][index]+
207			hal_data->BW20_24G_Diff[TxCount][index];
208			bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
209		}
210	}
211}
212
213static void phy_power_index_check(struct adapter *adapt, u8 channel,
214				  u8 *cck_pwr, u8 *ofdm_pwr, u8 *bw20_pwr,
215				  u8 *bw40_pwr)
216{
217	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
218
219	hal_data->CurrentCckTxPwrIdx = cck_pwr[0];
220	hal_data->CurrentOfdm24GTxPwrIdx = ofdm_pwr[0];
221	hal_data->CurrentBW2024GTxPwrIdx = bw20_pwr[0];
222	hal_data->CurrentBW4024GTxPwrIdx = bw40_pwr[0];
223}
224
225void phy_set_tx_power_level(struct adapter *adapt, u8 channel)
226{
227	u8 cck_pwr[MAX_TX_COUNT] = {0};
228	u8 ofdm_pwr[MAX_TX_COUNT] = {0};/*  [0]:RF-A, [1]:RF-B */
229	u8 bw20_pwr[MAX_TX_COUNT] = {0};
230	u8 bw40_pwr[MAX_TX_COUNT] = {0};
231
232	get_tx_power_index(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
233			   &bw20_pwr[0], &bw40_pwr[0]);
234
235	phy_power_index_check(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
236			      &bw20_pwr[0], &bw40_pwr[0]);
237
238	rtl88eu_phy_rf6052_set_cck_txpower(adapt, &cck_pwr[0]);
239	rtl88eu_phy_rf6052_set_ofdm_txpower(adapt, &ofdm_pwr[0], &bw20_pwr[0],
240					  &bw40_pwr[0], channel);
241}
242
243static void phy_set_bw_mode_callback(struct adapter *adapt)
244{
245	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
246	u8 reg_bw_opmode;
247	u8 reg_prsr_rsc;
248
249	if (hal_data->rf_chip == RF_PSEUDO_11N)
250		return;
251
252	/*  There is no 40MHz mode in RF_8225. */
253	if (hal_data->rf_chip == RF_8225)
254		return;
255
256	if (adapt->bDriverStopped)
257		return;
258
259	/* Set MAC register */
260
261	reg_bw_opmode = usb_read8(adapt, REG_BWOPMODE);
262	reg_prsr_rsc = usb_read8(adapt, REG_RRSR+2);
263
264	switch (hal_data->CurrentChannelBW) {
265	case HT_CHANNEL_WIDTH_20:
266		reg_bw_opmode |= BW_OPMODE_20MHZ;
267		usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
268		break;
269	case HT_CHANNEL_WIDTH_40:
270		reg_bw_opmode &= ~BW_OPMODE_20MHZ;
271		usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
272		reg_prsr_rsc = (reg_prsr_rsc&0x90) |
273			       (hal_data->nCur40MhzPrimeSC<<5);
274		usb_write8(adapt, REG_RRSR+2, reg_prsr_rsc);
275		break;
276	default:
277		break;
278	}
279
280	/* Set PHY related register */
281	switch (hal_data->CurrentChannelBW) {
282	case HT_CHANNEL_WIDTH_20:
283		phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x0);
284		phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x0);
285		break;
286	case HT_CHANNEL_WIDTH_40:
287		phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x1);
288		phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x1);
289		/* Set Control channel to upper or lower.
290		 * These settings are required only for 40MHz
291		 */
292		phy_set_bb_reg(adapt, rCCK0_System, bCCKSideBand,
293		    (hal_data->nCur40MhzPrimeSC>>1));
294		phy_set_bb_reg(adapt, rOFDM1_LSTF, 0xC00,
295			       hal_data->nCur40MhzPrimeSC);
296		phy_set_bb_reg(adapt, 0x818, (BIT26 | BIT27),
297		   (hal_data->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
298		break;
299	default:
300		break;
301	}
302
303	/* Set RF related register */
304	if (hal_data->rf_chip == RF_6052)
305		rtl88eu_phy_rf6052_set_bandwidth(adapt, hal_data->CurrentChannelBW);
306}
307
308void phy_set_bw_mode(struct adapter *adapt, enum ht_channel_width bandwidth,
309		     unsigned char offset)
310{
311	struct hal_data_8188e	*hal_data = GET_HAL_DATA(adapt);
312	enum ht_channel_width tmp_bw = hal_data->CurrentChannelBW;
313
314	hal_data->CurrentChannelBW = bandwidth;
315	hal_data->nCur40MhzPrimeSC = offset;
316
317	if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
318		phy_set_bw_mode_callback(adapt);
319	else
320		hal_data->CurrentChannelBW = tmp_bw;
321}
322
323static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel)
324{
325	u8 rf_path;
326	u32 param1, param2;
327	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
328
329	if (adapt->bNotifyChannelChange)
330		DBG_88E("[%s] ch = %d\n", __func__, channel);
331
332	phy_set_tx_power_level(adapt, channel);
333
334	param1 = RF_CHNLBW;
335	param2 = channel;
336	for (rf_path = 0; rf_path < hal_data->NumTotalRFPath; rf_path++) {
337		hal_data->RfRegChnlVal[rf_path] = (hal_data->RfRegChnlVal[rf_path] &
338						  0xfffffc00) | param2;
339		phy_set_rf_reg(adapt, (enum rf_radio_path)rf_path, param1,
340			       bRFRegOffsetMask, hal_data->RfRegChnlVal[rf_path]);
341	}
342}
343
344void phy_sw_chnl(struct adapter *adapt, u8 channel)
345{
346	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
347	u8 tmpchannel = hal_data->CurrentChannel;
348
349	if (hal_data->rf_chip == RF_PSEUDO_11N)
350		return;
351
352	if (channel == 0)
353		channel = 1;
354
355	hal_data->CurrentChannel = channel;
356
357	if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
358		phy_sw_chnl_callback(adapt, channel);
359	else
360		hal_data->CurrentChannel = tmpchannel;
361}
362
363#define ODM_TXPWRTRACK_MAX_IDX_88E  6
364
365static u8 get_right_chnl_for_iqk(u8 chnl)
366{
367	u8 place;
368	u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
369		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64,
370		100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
371		124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153,
372		155, 157, 159, 161, 163, 165
373	};
374
375	if (chnl > 14) {
376		for (place = 0; place < sizeof(channel_all); place++) {
377			if (channel_all[place] == chnl)
378				return ++place;
379		}
380	}
381	return 0;
382}
383
384void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type,
385				     u8 *direction, u32 *out_write_val)
386{
387	u8 pwr_value = 0;
388	/*  Tx power tracking BB swing table. */
389	if (type == 0) { /* For OFDM adjust */
390		ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
391			     ("BbSwingIdxOfdm = %d BbSwingFlagOfdm=%d\n",
392			     dm_odm->BbSwingIdxOfdm, dm_odm->BbSwingFlagOfdm));
393
394		if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) {
395			*direction = 1;
396			pwr_value = dm_odm->BbSwingIdxOfdmBase -
397				     dm_odm->BbSwingIdxOfdm;
398		} else {
399			*direction = 2;
400			pwr_value = dm_odm->BbSwingIdxOfdm -
401				     dm_odm->BbSwingIdxOfdmBase;
402		}
403
404	} else if (type == 1) { /* For CCK adjust. */
405		ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
406			     ("dm_odm->BbSwingIdxCck = %d dm_odm->BbSwingIdxCckBase = %d\n",
407			     dm_odm->BbSwingIdxCck, dm_odm->BbSwingIdxCckBase));
408
409		if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) {
410			*direction = 1;
411			pwr_value = dm_odm->BbSwingIdxCckBase -
412				     dm_odm->BbSwingIdxCck;
413		} else {
414			*direction = 2;
415			pwr_value = dm_odm->BbSwingIdxCck -
416				     dm_odm->BbSwingIdxCckBase;
417		}
418
419	}
420
421	if (pwr_value >= ODM_TXPWRTRACK_MAX_IDX_88E && *direction == 1)
422		pwr_value = ODM_TXPWRTRACK_MAX_IDX_88E;
423
424	*out_write_val = pwr_value | (pwr_value<<8) | (pwr_value<<16) |
425			 (pwr_value<<24);
426}
427
428static void dm_txpwr_track_setpwr(struct odm_dm_struct *dm_odm)
429{
430	if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) {
431		ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
432			     ("dm_txpwr_track_setpwr CH=%d\n", *(dm_odm->pChannel)));
433		phy_set_tx_power_level(dm_odm->Adapter, *(dm_odm->pChannel));
434		dm_odm->BbSwingFlagOfdm = false;
435		dm_odm->BbSwingFlagCck = false;
436	}
437}
438
439void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
440{
441	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
442	u8 thermal_val = 0, delta, delta_lck, delta_iqk, offset;
443	u8 thermal_avg_count = 0;
444	u32 thermal_avg = 0;
445	s32 ele_d, temp_cck;
446	s8 ofdm_index[2], cck_index = 0;
447	s8 ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
448	u32 i = 0, j = 0;
449	bool is2t = false;
450
451	u8 ofdm_min_index = 6, rf; /* OFDM BB Swing should be less than +3.0dB */
452	s8 ofdm_index_mapping[2][index_mapping_NUM_88E] = {
453		/* 2.4G, decrease power */
454		{0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11},
455		/* 2.4G, increase power */
456		{0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10},
457	};
458	u8 thermal_mapping[2][index_mapping_NUM_88E] = {
459		/* 2.4G, decrease power */
460		{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27},
461		/* 2.4G, increase power */
462		{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25},
463	};
464	struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
465
466	dm_txpwr_track_setpwr(dm_odm);
467
468	dm_odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++;
469	dm_odm->RFCalibrateInfo.bTXPowerTrackingInit = true;
470
471	dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317;
472
473	thermal_val = (u8)phy_query_rf_reg(adapt, RF_PATH_A,
474					   RF_T_METER_88E, 0xfc00);
475
476	if (is2t)
477		rf = 2;
478	else
479		rf = 1;
480
481	if (thermal_val) {
482		/* Query OFDM path A default setting */
483		ele_d = phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D;
484		for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
485			if (ele_d == (OFDMSwingTable[i]&bMaskOFDM_D)) {
486				ofdm_index_old[0] = (u8)i;
487				dm_odm->BbSwingIdxOfdmBase = (u8)i;
488				break;
489			}
490		}
491
492		/* Query OFDM path B default setting */
493		if (is2t) {
494			ele_d = phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord)&bMaskOFDM_D;
495			for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
496				if (ele_d == (OFDMSwingTable[i]&bMaskOFDM_D)) {
497					ofdm_index_old[1] = (u8)i;
498					break;
499				}
500			}
501		}
502
503		/* Query CCK default setting From 0xa24 */
504		temp_cck = dm_odm->RFCalibrateInfo.RegA24;
505
506		for (i = 0; i < CCK_TABLE_SIZE; i++) {
507			if ((dm_odm->RFCalibrateInfo.bCCKinCH14 &&
508				memcmp(&temp_cck, &CCKSwingTable_Ch14[i][2], 4)) ||
509				memcmp(&temp_cck, &CCKSwingTable_Ch1_Ch13[i][2], 4)) {
510					cck_index_old = (u8)i;
511					dm_odm->BbSwingIdxCckBase = (u8)i;
512					break;
513			}
514		}
515
516		if (!dm_odm->RFCalibrateInfo.ThermalValue) {
517			dm_odm->RFCalibrateInfo.ThermalValue = hal_data->EEPROMThermalMeter;
518			dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
519			dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
520
521			for (i = 0; i < rf; i++)
522				dm_odm->RFCalibrateInfo.OFDM_index[i] = ofdm_index_old[i];
523			dm_odm->RFCalibrateInfo.CCK_index = cck_index_old;
524		}
525
526		/* calculate average thermal meter */
527		dm_odm->RFCalibrateInfo.ThermalValue_AVG[dm_odm->RFCalibrateInfo.ThermalValue_AVG_index] = thermal_val;
528		dm_odm->RFCalibrateInfo.ThermalValue_AVG_index++;
529		if (dm_odm->RFCalibrateInfo.ThermalValue_AVG_index == AVG_THERMAL_NUM_88E)
530			dm_odm->RFCalibrateInfo.ThermalValue_AVG_index = 0;
531
532		for (i = 0; i < AVG_THERMAL_NUM_88E; i++) {
533			if (dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]) {
534				thermal_avg += dm_odm->RFCalibrateInfo.ThermalValue_AVG[i];
535				thermal_avg_count++;
536			}
537		}
538
539		if (thermal_avg_count)
540			thermal_val = (u8)(thermal_avg / thermal_avg_count);
541
542		if (dm_odm->RFCalibrateInfo.bDoneTxpower &&
543			!dm_odm->RFCalibrateInfo.bReloadtxpowerindex)
544			delta = abs(thermal_val - dm_odm->RFCalibrateInfo.ThermalValue);
545		else {
546			delta = abs(thermal_val - hal_data->EEPROMThermalMeter);
547			if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
548				dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false;
549				dm_odm->RFCalibrateInfo.bDoneTxpower = false;
550			}
551		}
552
553		delta_lck = abs(dm_odm->RFCalibrateInfo.ThermalValue_LCK - thermal_val);
554		delta_iqk = abs(dm_odm->RFCalibrateInfo.ThermalValue_IQK - thermal_val);
555
556		/* Delta temperature is equal to or larger than 20 centigrade.*/
557		if ((delta_lck >= 8)) {
558			dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
559			rtl88eu_phy_lc_calibrate(adapt);
560		}
561
562		if (delta > 0 && dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
563			delta = abs(hal_data->EEPROMThermalMeter - thermal_val);
564
565			/* calculate new OFDM / CCK offset */
566			if (thermal_val > hal_data->EEPROMThermalMeter)
567				j = 1;
568			else
569				j = 0;
570			for (offset = 0; offset < index_mapping_NUM_88E; offset++) {
571				if (delta < thermal_mapping[j][offset]) {
572					if (offset != 0)
573						offset--;
574					break;
575				}
576			}
577			if (offset >= index_mapping_NUM_88E)
578				offset = index_mapping_NUM_88E-1;
579
580			/* Updating ofdm_index values with new OFDM / CCK offset */
581			for (i = 0; i < rf; i++) {
582				ofdm_index[i] = dm_odm->RFCalibrateInfo.OFDM_index[i] + ofdm_index_mapping[j][offset];
583				if (ofdm_index[i] > OFDM_TABLE_SIZE_92D-1)
584					ofdm_index[i] = OFDM_TABLE_SIZE_92D-1;
585				else if (ofdm_index[i] < ofdm_min_index)
586					ofdm_index[i] = ofdm_min_index;
587			}
588
589			cck_index = dm_odm->RFCalibrateInfo.CCK_index + ofdm_index_mapping[j][offset];
590			if (cck_index > CCK_TABLE_SIZE-1)
591				cck_index = CCK_TABLE_SIZE-1;
592			else if (cck_index < 0)
593				cck_index = 0;
594
595			/* 2 temporarily remove bNOPG */
596			/* Config by SwingTable */
597			if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
598				dm_odm->RFCalibrateInfo.bDoneTxpower = true;
599
600				/*  Revse TX power table. */
601				dm_odm->BbSwingIdxOfdm = (u8)ofdm_index[0];
602				dm_odm->BbSwingIdxCck = (u8)cck_index;
603
604				if (dm_odm->BbSwingIdxOfdmCurrent != dm_odm->BbSwingIdxOfdm) {
605					dm_odm->BbSwingIdxOfdmCurrent = dm_odm->BbSwingIdxOfdm;
606					dm_odm->BbSwingFlagOfdm = true;
607				}
608
609				if (dm_odm->BbSwingIdxCckCurrent != dm_odm->BbSwingIdxCck) {
610					dm_odm->BbSwingIdxCckCurrent = dm_odm->BbSwingIdxCck;
611					dm_odm->BbSwingFlagCck = true;
612				}
613			}
614		}
615
616		/* Delta temperature is equal to or larger than 20 centigrade.*/
617		if (delta_iqk >= 8) {
618			dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
619			rtl88eu_phy_iq_calibrate(adapt, false);
620		}
621		/* update thermal meter value */
622		if (dm_odm->RFCalibrateInfo.TxPowerTrackControl)
623			dm_odm->RFCalibrateInfo.ThermalValue = thermal_val;
624	}
625	dm_odm->RFCalibrateInfo.TXPowercount = 0;
626}
627
628#define MAX_TOLERANCE 5
629
630static u8 phy_path_a_iqk(struct adapter *adapt, bool config_pathb)
631{
632	u32 reg_eac, reg_e94, reg_e9c, reg_ea4;
633	u8 result = 0x00;
634
635	/* 1 Tx IQK */
636	/* path-A IQK setting */
637	phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
638	phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
639	phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x8214032a);
640	phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
641
642	/* LO calibration setting */
643	phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
644
645	/* One shot, path A LOK & IQK */
646	phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
647	phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
648
649	mdelay(IQK_DELAY_TIME_88E);
650
651	reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
652	reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
653	reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
654	reg_ea4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord);
655
656	if (!(reg_eac & BIT28) &&
657	    (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
658	    (((reg_e9c & 0x03FF0000)>>16) != 0x42))
659		result |= 0x01;
660	return result;
661}
662
663static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB)
664{
665	u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u4tmp;
666	u8 result = 0x00;
667	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
668	struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
669
670	/* 1 Get TXIMR setting */
671	/* modify RXIQK mode table */
672	phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
673	phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
674	phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
675	phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
676	phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B);
677
678	/* PA,PAD off */
679	phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x980);
680	phy_set_rf_reg(adapt, RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000);
681
682	phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
683
684	/* IQK setting */
685	phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
686	phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
687
688	/* path-A IQK setting */
689	phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
690	phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
691	phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f);
692	phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
693
694	/* LO calibration setting */
695	phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
696
697	/* One shot, path A LOK & IQK */
698	phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
699	phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
700
701	/* delay x ms */
702	mdelay(IQK_DELAY_TIME_88E);
703
704	/* Check failed */
705	reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
706	reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
707	reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
708
709	if (!(reg_eac & BIT28) &&
710	    (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
711	    (((reg_e9c & 0x03FF0000)>>16) != 0x42))
712		result |= 0x01;
713	else					/* if Tx not OK, ignore Rx */
714		return result;
715
716	u4tmp = 0x80007C00 | (reg_e94&0x3FF0000)  | ((reg_e9c&0x3FF0000) >> 16);
717	phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, u4tmp);
718
719	/* 1 RX IQK */
720	/* modify RXIQK mode table */
721	ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
722		     ("Path-A Rx IQK modify RXIQK mode table 2!\n"));
723	phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
724	phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
725	phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
726	phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
727	phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa);
728	phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
729
730	/* IQK setting */
731	phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x01004800);
732
733	/* path-A IQK setting */
734	phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
735	phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
736	phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c05);
737	phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160c1f);
738
739	/* LO calibration setting */
740	phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
741
742	phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
743	phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
744
745	mdelay(IQK_DELAY_TIME_88E);
746
747	/*  Check failed */
748	reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
749	reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
750	reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
751	reg_ea4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord);
752
753	/* reload RF 0xdf */
754	phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
755	phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x180);
756
757	if (!(reg_eac & BIT27) && /* if Tx is OK, check whether Rx is OK */
758	    (((reg_ea4 & 0x03FF0000)>>16) != 0x132) &&
759	    (((reg_eac & 0x03FF0000)>>16) != 0x36))
760		result |= 0x02;
761	else
762		ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
763			     ("Path A Rx IQK fail!!\n"));
764
765	return result;
766}
767
768static u8 phy_path_b_iqk(struct adapter *adapt)
769{
770	u32 regeac, regeb4, regebc, regec4, regecc;
771	u8 result = 0x00;
772	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
773	struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
774
775	/* One shot, path B LOK & IQK */
776	phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000002);
777	phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000000);
778
779	mdelay(IQK_DELAY_TIME_88E);
780
781	regeac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
782	regeb4 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B, bMaskDWord);
783	regebc = phy_query_bb_reg(adapt, rTx_Power_After_IQK_B, bMaskDWord);
784	regec4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2, bMaskDWord);
785	regecc = phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2, bMaskDWord);
786
787	if (!(regeac & BIT31) &&
788	    (((regeb4 & 0x03FF0000)>>16) != 0x142) &&
789	    (((regebc & 0x03FF0000)>>16) != 0x42))
790		result |= 0x01;
791	else
792		return result;
793
794	if (!(regeac & BIT30) &&
795	    (((regec4 & 0x03FF0000)>>16) != 0x132) &&
796	    (((regecc & 0x03FF0000)>>16) != 0x36))
797		result |= 0x02;
798	else
799		ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION,
800			     ODM_DBG_LOUD,  ("Path B Rx IQK fail!!\n"));
801	return result;
802}
803
804static void patha_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
805			   u8 final_candidate, bool txonly)
806{
807	u32 oldval_0, x, tx0_a, reg;
808	s32 y, tx0_c;
809
810	if (final_candidate == 0xFF) {
811		return;
812	} else if (iqkok) {
813		oldval_0 = (phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
814
815		x = result[final_candidate][0];
816		if ((x & 0x00000200) != 0)
817			x = x | 0xFFFFFC00;
818
819		tx0_a = (x * oldval_0) >> 8;
820		phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x3FF, tx0_a);
821		phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(31),
822			       ((x * oldval_0>>7) & 0x1));
823
824		y = result[final_candidate][1];
825		if ((y & 0x00000200) != 0)
826			y = y | 0xFFFFFC00;
827
828		tx0_c = (y * oldval_0) >> 8;
829		phy_set_bb_reg(adapt, rOFDM0_XCTxAFE, 0xF0000000,
830			       ((tx0_c&0x3C0)>>6));
831		phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x003F0000,
832			       (tx0_c&0x3F));
833		phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(29),
834			       ((y * oldval_0>>7) & 0x1));
835
836		if (txonly)
837			return;
838
839		reg = result[final_candidate][2];
840		phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0x3FF, reg);
841
842		reg = result[final_candidate][3] & 0x3F;
843		phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0xFC00, reg);
844
845		reg = (result[final_candidate][3] >> 6) & 0xF;
846		phy_set_bb_reg(adapt, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
847	}
848}
849
850static void pathb_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
851			   u8 final_candidate, bool txonly)
852{
853	u32 oldval_1, x, tx1_a, reg;
854	s32 y, tx1_c;
855
856	if (final_candidate == 0xFF) {
857		return;
858	} else if (iqkok) {
859		oldval_1 = (phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
860
861		x = result[final_candidate][4];
862		if ((x & 0x00000200) != 0)
863			x = x | 0xFFFFFC00;
864		tx1_a = (x * oldval_1) >> 8;
865		phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x3FF, tx1_a);
866
867		phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(27),
868			       ((x * oldval_1>>7) & 0x1));
869
870		y = result[final_candidate][5];
871		if ((y & 0x00000200) != 0)
872			y = y | 0xFFFFFC00;
873
874		tx1_c = (y * oldval_1) >> 8;
875
876		phy_set_bb_reg(adapt, rOFDM0_XDTxAFE, 0xF0000000,
877			       ((tx1_c&0x3C0)>>6));
878		phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x003F0000,
879			       (tx1_c&0x3F));
880		phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(25),
881			       ((y * oldval_1>>7) & 0x1));
882
883		if (txonly)
884			return;
885
886		reg = result[final_candidate][6];
887		phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
888
889		reg = result[final_candidate][7] & 0x3F;
890		phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
891
892		reg = (result[final_candidate][7] >> 6) & 0xF;
893		phy_set_bb_reg(adapt, rOFDM0_AGCRSSITable, 0x0000F000, reg);
894	}
895}
896
897static void save_adda_registers(struct adapter *adapt, u32 *addareg,
898				u32 *backup, u32 register_num)
899{
900	u32 i;
901
902	for (i = 0; i < register_num; i++) {
903		backup[i] = phy_query_bb_reg(adapt, addareg[i], bMaskDWord);
904	}
905}
906
907static void save_mac_registers(struct adapter *adapt, u32 *mac_reg,
908			       u32 *backup)
909{
910	u32 i;
911
912	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
913		backup[i] = usb_read8(adapt, mac_reg[i]);
914	}
915	backup[i] = usb_read32(adapt, mac_reg[i]);
916}
917
918static void reload_adda_reg(struct adapter *adapt, u32 *adda_reg,
919			    u32 *backup, u32 regiester_num)
920{
921	u32 i;
922
923	for (i = 0; i < regiester_num; i++)
924		phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, backup[i]);
925}
926
927static void reload_mac_registers(struct adapter *adapt,
928				 u32 *mac_reg, u32 *backup)
929{
930	u32 i;
931
932	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
933		usb_write8(adapt, mac_reg[i], (u8)backup[i]);
934	}
935	usb_write32(adapt, mac_reg[i], backup[i]);
936}
937
938static void path_adda_on(struct adapter *adapt, u32 *adda_reg,
939			 bool is_path_a_on, bool is2t)
940{
941	u32 path_on;
942	u32 i;
943
944	if (!is2t) {
945		path_on = 0x0bdb25a0;
946		phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, 0x0b1b25a0);
947	} else {
948		path_on = is_path_a_on ? 0x04db25a4 : 0x0b1b25a4;
949		phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, path_on);
950	}
951
952	for (i = 1; i < IQK_ADDA_REG_NUM; i++)
953		phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, path_on);
954}
955
956static void mac_setting_calibration(struct adapter *adapt, u32 *mac_reg, u32 *backup)
957{
958	u32 i = 0;
959
960	usb_write8(adapt, mac_reg[i], 0x3F);
961
962	for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) {
963		usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT3)));
964	}
965	usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT5)));
966}
967
968static void path_a_standby(struct adapter *adapt)
969{
970
971	phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x0);
972	phy_set_bb_reg(adapt, 0x840, bMaskDWord, 0x00010000);
973	phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
974}
975
976static void pi_mode_switch(struct adapter *adapt, bool pi_mode)
977{
978	u32 mode;
979
980	mode = pi_mode ? 0x01000100 : 0x01000000;
981	phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode);
982	phy_set_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode);
983}
984
985static bool simularity_compare(struct adapter *adapt, s32 resulta[][8],
986			       u8 c1, u8 c2)
987{
988	u32 i, j, diff, sim_bitmap = 0, bound;
989	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
990	struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
991	u8 final_candidate[2] = {0xFF, 0xFF};	/* for path A and path B */
992	bool result = true;
993	s32 tmp1 = 0, tmp2 = 0;
994
995	if ((dm_odm->RFType == ODM_2T2R) || (dm_odm->RFType == ODM_2T3R) ||
996	    (dm_odm->RFType == ODM_2T4R))
997		bound = 8;
998	else
999		bound = 4;
1000
1001	for (i = 0; i < bound; i++) {
1002		if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) {
1003			if ((resulta[c1][i] & 0x00000200) != 0)
1004				tmp1 = resulta[c1][i] | 0xFFFFFC00;
1005			else
1006				tmp1 = resulta[c1][i];
1007
1008			if ((resulta[c2][i] & 0x00000200) != 0)
1009				tmp2 = resulta[c2][i] | 0xFFFFFC00;
1010			else
1011				tmp2 = resulta[c2][i];
1012		} else {
1013			tmp1 = resulta[c1][i];
1014			tmp2 = resulta[c2][i];
1015		}
1016
1017		diff = (tmp1 > tmp2) ? (tmp1 - tmp2) : (tmp2 - tmp1);
1018
1019		if (diff > MAX_TOLERANCE) {
1020			if ((i == 2 || i == 6) && !sim_bitmap) {
1021				if (resulta[c1][i] + resulta[c1][i+1] == 0)
1022					final_candidate[(i/4)] = c2;
1023				else if (resulta[c2][i] + resulta[c2][i+1] == 0)
1024					final_candidate[(i/4)] = c1;
1025				else
1026					sim_bitmap = sim_bitmap | (1<<i);
1027			} else {
1028				sim_bitmap = sim_bitmap | (1<<i);
1029			}
1030		}
1031	}
1032
1033	if (sim_bitmap == 0) {
1034		for (i = 0; i < (bound/4); i++) {
1035			if (final_candidate[i] != 0xFF) {
1036				for (j = i*4; j < (i+1)*4-2; j++)
1037					resulta[3][j] = resulta[final_candidate[i]][j];
1038				result = false;
1039			}
1040		}
1041		return result;
1042	} else {
1043		if (!(sim_bitmap & 0x03)) {		   /* path A TX OK */
1044			for (i = 0; i < 2; i++)
1045				resulta[3][i] = resulta[c1][i];
1046		}
1047		if (!(sim_bitmap & 0x0c)) {		   /* path A RX OK */
1048			for (i = 2; i < 4; i++)
1049				resulta[3][i] = resulta[c1][i];
1050		}
1051
1052		if (!(sim_bitmap & 0x30)) { /* path B TX OK */
1053			for (i = 4; i < 6; i++)
1054				resulta[3][i] = resulta[c1][i];
1055		}
1056
1057		if (!(sim_bitmap & 0xc0)) { /* path B RX OK */
1058			for (i = 6; i < 8; i++)
1059				resulta[3][i] = resulta[c1][i];
1060		}
1061		return false;
1062	}
1063}
1064
1065static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8],
1066			     u8 t, bool is2t)
1067{
1068	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
1069	struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
1070	u32 i;
1071	u8 path_a_ok, path_b_ok;
1072	u32 adda_reg[IQK_ADDA_REG_NUM] = {
1073					  rFPGA0_XCD_SwitchControl, rBlue_Tooth,
1074					  rRx_Wait_CCA, rTx_CCK_RFON,
1075					  rTx_CCK_BBON, rTx_OFDM_RFON,
1076					  rTx_OFDM_BBON, rTx_To_Rx,
1077					  rTx_To_Tx, rRx_CCK,
1078					  rRx_OFDM, rRx_Wait_RIFS,
1079					  rRx_TO_Rx, rStandby,
1080					  rSleep, rPMPD_ANAEN};
1081
1082	u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
1083					    REG_TXPAUSE, REG_BCN_CTRL,
1084					    REG_BCN_CTRL_1, REG_GPIO_MUXCFG};
1085
1086	/* since 92C & 92D have the different define in IQK_BB_REG */
1087	u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
1088					      rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar,
1089					      rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB,
1090					      rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE,
1091					      rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD};
1092
1093	u32 retry_count = 9;
1094	if (*(dm_odm->mp_mode) == 1)
1095		retry_count = 9;
1096	else
1097		retry_count = 2;
1098
1099	if (t == 0) {
1100
1101		/*  Save ADDA parameters, turn Path A ADDA on */
1102		save_adda_registers(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
1103				    IQK_ADDA_REG_NUM);
1104		save_mac_registers(adapt, iqk_mac_reg,
1105				   dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1106		save_adda_registers(adapt, iqk_bb_reg_92c,
1107				    dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
1108	}
1109
1110	path_adda_on(adapt, adda_reg, true, is2t);
1111	if (t == 0)
1112		dm_odm->RFCalibrateInfo.bRfPiEnable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1,
1113									   BIT(8));
1114
1115	if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
1116		/*  Switch BB to PI mode to do IQ Calibration. */
1117		pi_mode_switch(adapt, true);
1118	}
1119
1120	/* BB setting */
1121	phy_set_bb_reg(adapt, rFPGA0_RFMOD, BIT24, 0x00);
1122	phy_set_bb_reg(adapt, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
1123	phy_set_bb_reg(adapt, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
1124	phy_set_bb_reg(adapt, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
1125
1126	phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT10, 0x01);
1127	phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT26, 0x01);
1128	phy_set_bb_reg(adapt, rFPGA0_XA_RFInterfaceOE, BIT10, 0x00);
1129	phy_set_bb_reg(adapt, rFPGA0_XB_RFInterfaceOE, BIT10, 0x00);
1130
1131	if (is2t) {
1132		phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter, bMaskDWord,
1133			       0x00010000);
1134		phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter, bMaskDWord,
1135			       0x00010000);
1136	}
1137
1138	/* MAC settings */
1139	mac_setting_calibration(adapt, iqk_mac_reg,
1140				dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1141
1142	/* Page B init */
1143	/* AP or IQK */
1144	phy_set_bb_reg(adapt, rConfig_AntA, bMaskDWord, 0x0f600000);
1145
1146	if (is2t)
1147		phy_set_bb_reg(adapt, rConfig_AntB, bMaskDWord, 0x0f600000);
1148
1149	/*  IQ calibration setting */
1150	phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
1151	phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
1152	phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
1153
1154	for (i = 0; i < retry_count; i++) {
1155		path_a_ok = phy_path_a_iqk(adapt, is2t);
1156		if (path_a_ok == 0x01) {
1157				result[t][0] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A,
1158								 bMaskDWord)&0x3FF0000)>>16;
1159				result[t][1] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_A,
1160								 bMaskDWord)&0x3FF0000)>>16;
1161			break;
1162		}
1163	}
1164
1165	for (i = 0; i < retry_count; i++) {
1166		path_a_ok = phy_path_a_rx_iqk(adapt, is2t);
1167		if (path_a_ok == 0x03) {
1168				result[t][2] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2,
1169								 bMaskDWord)&0x3FF0000)>>16;
1170				result[t][3] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2,
1171								 bMaskDWord)&0x3FF0000)>>16;
1172			break;
1173		} else {
1174			ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1175				     ("Path A Rx IQK Fail!!\n"));
1176		}
1177	}
1178
1179	if (0x00 == path_a_ok) {
1180		ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1181			     ("Path A IQK failed!!\n"));
1182	}
1183
1184	if (is2t) {
1185		path_a_standby(adapt);
1186
1187		/*  Turn Path B ADDA on */
1188		path_adda_on(adapt, adda_reg, false, is2t);
1189
1190		for (i = 0; i < retry_count; i++) {
1191			path_b_ok = phy_path_b_iqk(adapt);
1192			if (path_b_ok == 0x03) {
1193				result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
1194								 bMaskDWord)&0x3FF0000)>>16;
1195				result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
1196								 bMaskDWord)&0x3FF0000)>>16;
1197				result[t][6] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2,
1198								 bMaskDWord)&0x3FF0000)>>16;
1199				result[t][7] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2,
1200								 bMaskDWord)&0x3FF0000)>>16;
1201				break;
1202			} else if (i == (retry_count - 1) && path_b_ok == 0x01) {	/* Tx IQK OK */
1203				result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
1204								 bMaskDWord)&0x3FF0000)>>16;
1205				result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
1206								 bMaskDWord)&0x3FF0000)>>16;
1207			}
1208		}
1209
1210		if (0x00 == path_b_ok) {
1211			ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1212				     ("Path B IQK failed!!\n"));
1213		}
1214	}
1215
1216	/* Back to BB mode, load original value */
1217	phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0);
1218
1219	if (t != 0) {
1220		if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
1221			/* Switch back BB to SI mode after
1222			 * finish IQ Calibration.
1223			 */
1224			pi_mode_switch(adapt, false);
1225		}
1226
1227		/*  Reload ADDA power saving parameters */
1228		reload_adda_reg(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
1229				IQK_ADDA_REG_NUM);
1230
1231		/*  Reload MAC parameters */
1232		reload_mac_registers(adapt, iqk_mac_reg,
1233				     dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1234
1235		reload_adda_reg(adapt, iqk_bb_reg_92c, dm_odm->RFCalibrateInfo.IQK_BB_backup,
1236				IQK_BB_REG_NUM);
1237
1238		/*  Restore RX initial gain */
1239		phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter,
1240			       bMaskDWord, 0x00032ed3);
1241		if (is2t)
1242			phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter,
1243				       bMaskDWord, 0x00032ed3);
1244
1245		/* load 0xe30 IQC default value */
1246		phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
1247		phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
1248	}
1249}
1250
1251static void phy_lc_calibrate(struct adapter *adapt, bool is2t)
1252{
1253	u8 tmpreg;
1254	u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
1255
1256	/* Check continuous TX and Packet TX */
1257	tmpreg = usb_read8(adapt, 0xd03);
1258
1259	if ((tmpreg&0x70) != 0)
1260		usb_write8(adapt, 0xd03, tmpreg&0x8F);
1261	else
1262		usb_write8(adapt, REG_TXPAUSE, 0xFF);
1263
1264	if ((tmpreg&0x70) != 0) {
1265		/* 1. Read original RF mode */
1266		/* Path-A */
1267		rf_a_mode = phy_query_rf_reg(adapt, RF_PATH_A, RF_AC,
1268					     bMask12Bits);
1269
1270		/* Path-B */
1271		if (is2t)
1272			rf_b_mode = phy_query_rf_reg(adapt, RF_PATH_B, RF_AC,
1273						     bMask12Bits);
1274
1275		/* 2. Set RF mode = standby mode */
1276		/* Path-A */
1277		phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits,
1278			       (rf_a_mode&0x8FFFF)|0x10000);
1279
1280		/* Path-B */
1281		if (is2t)
1282			phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
1283				       (rf_b_mode&0x8FFFF)|0x10000);
1284	}
1285
1286	/* 3. Read RF reg18 */
1287	lc_cal = phy_query_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits);
1288
1289	/* 4. Set LC calibration begin bit15 */
1290	phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits,
1291		       lc_cal|0x08000);
1292
1293	msleep(100);
1294
1295	/* Restore original situation */
1296	if ((tmpreg&0x70) != 0) {
1297		/* Deal with continuous TX case */
1298		/* Path-A */
1299		usb_write8(adapt, 0xd03, tmpreg);
1300		phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits, rf_a_mode);
1301
1302		/* Path-B */
1303		if (is2t)
1304			phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
1305				       rf_b_mode);
1306	} else {
1307		/* Deal with Packet TX case */
1308		usb_write8(adapt, REG_TXPAUSE, 0x00);
1309	}
1310}
1311
1312void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery)
1313{
1314	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
1315	struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
1316	s32 result[4][8];
1317	u8 i, final, chn_index;
1318	bool pathaok, pathbok;
1319	s32 reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4,
1320	    reg_ecc;
1321	bool is12simular, is13simular, is23simular;
1322	bool singletone = false, carrier_sup = false;
1323	u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
1324		rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance,
1325		rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable,
1326		rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance,
1327		rOFDM0_XCTxAFE, rOFDM0_XDTxAFE,
1328		rOFDM0_RxIQExtAnta};
1329	bool is2t;
1330
1331	is2t = (dm_odm->RFType == ODM_2T2R) ? true : false;
1332
1333	if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
1334		return;
1335
1336	if (singletone || carrier_sup)
1337		return;
1338
1339	if (recovery) {
1340		ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD,
1341			     ("phy_iq_calibrate: Return due to recovery!\n"));
1342		reload_adda_reg(adapt, iqk_bb_reg_92c,
1343				dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
1344		return;
1345	}
1346
1347	for (i = 0; i < 8; i++) {
1348		result[0][i] = 0;
1349		result[1][i] = 0;
1350		result[2][i] = 0;
1351		if ((i == 0) || (i == 2) || (i == 4)  || (i == 6))
1352			result[3][i] = 0x100;
1353		else
1354			result[3][i] = 0;
1355	}
1356	final = 0xff;
1357	pathaok = false;
1358	pathbok = false;
1359	is12simular = false;
1360	is23simular = false;
1361	is13simular = false;
1362
1363	for (i = 0; i < 3; i++) {
1364		phy_iq_calibrate(adapt, result, i, is2t);
1365
1366		if (i == 1) {
1367			is12simular = simularity_compare(adapt, result, 0, 1);
1368			if (is12simular) {
1369				final = 0;
1370				break;
1371			}
1372		}
1373
1374		if (i == 2) {
1375			is13simular = simularity_compare(adapt, result, 0, 2);
1376			if (is13simular) {
1377				final = 0;
1378				break;
1379			}
1380			is23simular = simularity_compare(adapt, result, 1, 2);
1381			if (is23simular)
1382				final = 1;
1383			else
1384				final = 3;
1385		}
1386	}
1387
1388	for (i = 0; i < 4; i++) {
1389		reg_e94 = result[i][0];
1390		reg_e9c = result[i][1];
1391		reg_ea4 = result[i][2];
1392		reg_eac = result[i][3];
1393		reg_eb4 = result[i][4];
1394		reg_ebc = result[i][5];
1395		reg_ec4 = result[i][6];
1396		reg_ecc = result[i][7];
1397	}
1398
1399	if (final != 0xff) {
1400		reg_e94 = result[final][0];
1401		reg_e9c = result[final][1];
1402		reg_ea4 = result[final][2];
1403		reg_eac = result[final][3];
1404		reg_eb4 = result[final][4];
1405		reg_ebc = result[final][5];
1406		dm_odm->RFCalibrateInfo.RegE94 = reg_e94;
1407		dm_odm->RFCalibrateInfo.RegE9C = reg_e9c;
1408		dm_odm->RFCalibrateInfo.RegEB4 = reg_eb4;
1409		dm_odm->RFCalibrateInfo.RegEBC = reg_ebc;
1410		reg_ec4 = result[final][6];
1411		reg_ecc = result[final][7];
1412		pathaok = true;
1413		pathbok = true;
1414	} else {
1415		ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1416			     ("IQK: FAIL use default value\n"));
1417		dm_odm->RFCalibrateInfo.RegE94 = 0x100;
1418		dm_odm->RFCalibrateInfo.RegEB4 = 0x100;
1419		dm_odm->RFCalibrateInfo.RegE9C = 0x0;
1420		dm_odm->RFCalibrateInfo.RegEBC = 0x0;
1421	}
1422	if (reg_e94 != 0)
1423		patha_fill_iqk(adapt, pathaok, result, final,
1424			       (reg_ea4 == 0));
1425	if (is2t) {
1426		if (reg_eb4 != 0)
1427			pathb_fill_iqk(adapt, pathbok, result, final,
1428				       (reg_ec4 == 0));
1429	}
1430
1431	chn_index = get_right_chnl_for_iqk(hal_data->CurrentChannel);
1432
1433	if (final < 4) {
1434		for (i = 0; i < IQK_Matrix_REG_NUM; i++)
1435			dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[chn_index].Value[0][i] = result[final][i];
1436		dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[chn_index].bIQKDone = true;
1437	}
1438
1439	save_adda_registers(adapt, iqk_bb_reg_92c,
1440			    dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
1441}
1442
1443void rtl88eu_phy_lc_calibrate(struct adapter *adapt)
1444{
1445	bool singletone = false, carrier_sup = false;
1446	u32 timeout = 2000, timecount = 0;
1447	struct hal_data_8188e *hal_data = GET_HAL_DATA(adapt);
1448	struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
1449
1450	if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
1451		return;
1452	if (singletone || carrier_sup)
1453		return;
1454
1455	while (*(dm_odm->pbScanInProcess) && timecount < timeout) {
1456		mdelay(50);
1457		timecount += 50;
1458	}
1459
1460	dm_odm->RFCalibrateInfo.bLCKInProgress = true;
1461
1462	if (dm_odm->RFType == ODM_2T2R) {
1463		phy_lc_calibrate(adapt, true);
1464	} else {
1465		/* For 88C 1T1R */
1466		phy_lc_calibrate(adapt, false);
1467	}
1468
1469	dm_odm->RFCalibrateInfo.bLCKInProgress = false;
1470}
1471