xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8189fs/hal/phydm/txbf/haltxbf8822b.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /******************************************************************************
2*4882a593Smuzhiyun  *
3*4882a593Smuzhiyun  * Copyright(c) 2016 - 2017 Realtek Corporation.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or modify it
6*4882a593Smuzhiyun  * under the terms of version 2 of the GNU General Public License as
7*4882a593Smuzhiyun  * published by the Free Software Foundation.
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * This program is distributed in the hope that it will be useful, but WITHOUT
10*4882a593Smuzhiyun  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12*4882a593Smuzhiyun  * more details.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  *****************************************************************************/
15*4882a593Smuzhiyun /*@============================================================*/
16*4882a593Smuzhiyun /* @Description:                                              */
17*4882a593Smuzhiyun /*                                                           @*/
18*4882a593Smuzhiyun /* This file is for 8814A TXBF mechanism                     */
19*4882a593Smuzhiyun /*                                                           @*/
20*4882a593Smuzhiyun /*@============================================================*/
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #include "mp_precomp.h"
23*4882a593Smuzhiyun #include "phydm_precomp.h"
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #if (RTL8822B_SUPPORT == 1)
26*4882a593Smuzhiyun #ifdef PHYDM_BEAMFORMING_SUPPORT
27*4882a593Smuzhiyun 
hal_txbf_8822b_get_ntx(void * dm_void)28*4882a593Smuzhiyun u8 hal_txbf_8822b_get_ntx(
29*4882a593Smuzhiyun 	void *dm_void)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun 	struct dm_struct *dm = (struct dm_struct *)dm_void;
32*4882a593Smuzhiyun 	u8 ntx = 0;
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #if DEV_BUS_TYPE == RT_USB_INTERFACE
35*4882a593Smuzhiyun 	if (dm->support_interface == ODM_ITRF_USB) {
36*4882a593Smuzhiyun 		if (*dm->hub_usb_mode == 2) { /*USB3.0*/
37*4882a593Smuzhiyun 			if (dm->rf_type == RF_4T4R)
38*4882a593Smuzhiyun 				ntx = 3;
39*4882a593Smuzhiyun 			else if (dm->rf_type == RF_3T3R)
40*4882a593Smuzhiyun 				ntx = 2;
41*4882a593Smuzhiyun 			else
42*4882a593Smuzhiyun 				ntx = 1;
43*4882a593Smuzhiyun 		} else if (*dm->hub_usb_mode == 1) /*USB 2.0 always 2Tx*/
44*4882a593Smuzhiyun 			ntx = 1;
45*4882a593Smuzhiyun 		else
46*4882a593Smuzhiyun 			ntx = 1;
47*4882a593Smuzhiyun 	} else
48*4882a593Smuzhiyun #endif
49*4882a593Smuzhiyun 	{
50*4882a593Smuzhiyun 		if (dm->rf_type == RF_4T4R)
51*4882a593Smuzhiyun 			ntx = 3;
52*4882a593Smuzhiyun 		else if (dm->rf_type == RF_3T3R)
53*4882a593Smuzhiyun 			ntx = 2;
54*4882a593Smuzhiyun 		else
55*4882a593Smuzhiyun 			ntx = 1;
56*4882a593Smuzhiyun 	}
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	return ntx;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
hal_txbf_8822b_get_nrx(void * dm_void)61*4882a593Smuzhiyun u8 hal_txbf_8822b_get_nrx(
62*4882a593Smuzhiyun 	void *dm_void)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun 	struct dm_struct *dm = (struct dm_struct *)dm_void;
65*4882a593Smuzhiyun 	u8 nrx = 0;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	if (dm->rf_type == RF_4T4R)
68*4882a593Smuzhiyun 		nrx = 3;
69*4882a593Smuzhiyun 	else if (dm->rf_type == RF_3T3R)
70*4882a593Smuzhiyun 		nrx = 2;
71*4882a593Smuzhiyun 	else if (dm->rf_type == RF_2T2R)
72*4882a593Smuzhiyun 		nrx = 1;
73*4882a593Smuzhiyun 	else if (dm->rf_type == RF_2T3R)
74*4882a593Smuzhiyun 		nrx = 2;
75*4882a593Smuzhiyun 	else if (dm->rf_type == RF_2T4R)
76*4882a593Smuzhiyun 		nrx = 3;
77*4882a593Smuzhiyun 	else if (dm->rf_type == RF_1T1R)
78*4882a593Smuzhiyun 		nrx = 0;
79*4882a593Smuzhiyun 	else if (dm->rf_type == RF_1T2R)
80*4882a593Smuzhiyun 		nrx = 1;
81*4882a593Smuzhiyun 	else
82*4882a593Smuzhiyun 		nrx = 0;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	return nrx;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun /***************SU & MU BFee Entry********************/
hal_txbf_8822b_rf_mode(void * dm_void,struct _RT_BEAMFORMING_INFO * beamforming_info,u8 idx)88*4882a593Smuzhiyun void hal_txbf_8822b_rf_mode(
89*4882a593Smuzhiyun 	void *dm_void,
90*4882a593Smuzhiyun 	struct _RT_BEAMFORMING_INFO *beamforming_info,
91*4882a593Smuzhiyun 	u8 idx)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun #if 0
94*4882a593Smuzhiyun 	struct dm_struct	*dm = (struct dm_struct *)dm_void;
95*4882a593Smuzhiyun 	u8				i, nr_index = 0;
96*4882a593Smuzhiyun 	boolean				is_self_beamformer = false;
97*4882a593Smuzhiyun 	boolean				is_self_beamformee = false;
98*4882a593Smuzhiyun 	struct _RT_BEAMFORMEE_ENTRY	beamformee_entry;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	if (idx < BEAMFORMEE_ENTRY_NUM)
101*4882a593Smuzhiyun 		beamformee_entry = beamforming_info->beamformee_entry[idx];
102*4882a593Smuzhiyun 	else
103*4882a593Smuzhiyun 		return;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	if (dm->rf_type == RF_1T1R)
106*4882a593Smuzhiyun 		return;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	for (i = RF_PATH_A; i < RF_PATH_B; i++) {
109*4882a593Smuzhiyun 		odm_set_rf_reg(dm, (enum rf_path)i, rf_welut_jaguar, 0x80000, 0x1);
110*4882a593Smuzhiyun 		/*RF mode table write enable*/
111*4882a593Smuzhiyun 	}
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	if (beamforming_info->beamformee_su_cnt > 0 || beamforming_info->beamformee_mu_cnt > 0) {
114*4882a593Smuzhiyun 		for (i = RF_PATH_A; i < RF_PATH_B; i++) {
115*4882a593Smuzhiyun 			odm_set_rf_reg(dm, (enum rf_path)i, rf_mode_table_addr, 0xfffff, 0x18000);
116*4882a593Smuzhiyun 			/*Select RX mode*/
117*4882a593Smuzhiyun 			odm_set_rf_reg(dm, (enum rf_path)i, rf_mode_table_data0, 0xfffff, 0xBE77F);
118*4882a593Smuzhiyun 			/*Set Table data*/
119*4882a593Smuzhiyun 			odm_set_rf_reg(dm, (enum rf_path)i, rf_mode_table_data1, 0xfffff, 0x226BF);
120*4882a593Smuzhiyun 			/*@Enable TXIQGEN in RX mode*/
121*4882a593Smuzhiyun 		}
122*4882a593Smuzhiyun 		odm_set_rf_reg(dm, RF_PATH_A, rf_mode_table_data1, 0xfffff, 0xE26BF);
123*4882a593Smuzhiyun 		/*@Enable TXIQGEN in RX mode*/
124*4882a593Smuzhiyun 	}
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	for (i = RF_PATH_A; i < RF_PATH_B; i++) {
127*4882a593Smuzhiyun 		odm_set_rf_reg(dm, (enum rf_path)i, rf_welut_jaguar, 0x80000, 0x0);
128*4882a593Smuzhiyun 		/*RF mode table write disable*/
129*4882a593Smuzhiyun 	}
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	if (beamforming_info->beamformee_su_cnt > 0) {
132*4882a593Smuzhiyun 		/*@for 8814 19ac(idx 1), 19b4(idx 0), different Tx ant setting*/
133*4882a593Smuzhiyun 		odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(28) | BIT29, 0x2);			/*@enable BB TxBF ant mapping register*/
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 		if (idx == 0) {
136*4882a593Smuzhiyun 			/*Nsts = 2	AB*/
137*4882a593Smuzhiyun 			odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF0_8822B, 0xffff, 0x0433);
138*4882a593Smuzhiyun 			odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x043);
139*4882a593Smuzhiyun 			/*odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_2, MASKLWORD, 0x430);*/
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 		} else {/*@IDX =1*/
142*4882a593Smuzhiyun 			odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, 0xffff, 0x0433);
143*4882a593Smuzhiyun 			odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x043);
144*4882a593Smuzhiyun 			/*odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_2, MASKLWORD, 0x430;*/
145*4882a593Smuzhiyun 		}
146*4882a593Smuzhiyun 	} else {
147*4882a593Smuzhiyun 		odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x1); /*@1SS by path-A*/
148*4882a593Smuzhiyun 		odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_2_8822B, MASKLWORD, 0x430); /*@2SS by path-A,B*/
149*4882a593Smuzhiyun 	}
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	if (beamforming_info->beamformee_mu_cnt > 0) {
152*4882a593Smuzhiyun 		/*@MU STAs share the common setting*/
153*4882a593Smuzhiyun 		odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(31), 1);
154*4882a593Smuzhiyun 		odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, 0xffff, 0x0433);
155*4882a593Smuzhiyun 		odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x043);
156*4882a593Smuzhiyun 	}
157*4882a593Smuzhiyun #endif
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun #if 0
160*4882a593Smuzhiyun void
161*4882a593Smuzhiyun hal_txbf_8822b_download_ndpa(
162*4882a593Smuzhiyun 	void			*adapter,
163*4882a593Smuzhiyun 	u8				idx
164*4882a593Smuzhiyun )
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	u8			u1b_tmp = 0, tmp_reg422 = 0;
167*4882a593Smuzhiyun 	u8			bcn_valid_reg = 0, count = 0, dl_bcn_count = 0;
168*4882a593Smuzhiyun 	u16			head_page = 0x7FE;
169*4882a593Smuzhiyun 	boolean			is_send_beacon = false;
170*4882a593Smuzhiyun 	HAL_DATA_TYPE	*hal_data = GET_HAL_DATA(adapter);
171*4882a593Smuzhiyun 	u16			tx_page_bndy = LAST_ENTRY_OF_TX_PKT_BUFFER_8814A; /*@default reseved 1 page for the IC type which is undefined.*/
172*4882a593Smuzhiyun 	struct _RT_BEAMFORMING_INFO	*beam_info = GET_BEAMFORM_INFO(adapter);
173*4882a593Smuzhiyun 	struct _RT_BEAMFORMEE_ENTRY	*p_beam_entry = beam_info->beamformee_entry + idx;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	hal_data->is_fw_dw_rsvd_page_in_progress = true;
176*4882a593Smuzhiyun 	phydm_get_hal_def_var_handler_interface(dm, HAL_DEF_TX_PAGE_BOUNDARY, (u16 *)&tx_page_bndy);
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	/*Set REG_CR bit 8. DMA beacon by SW.*/
179*4882a593Smuzhiyun 	u1b_tmp = platform_efio_read_1byte(adapter, REG_CR_8814A + 1);
180*4882a593Smuzhiyun 	platform_efio_write_1byte(adapter,  REG_CR_8814A + 1, (u1b_tmp | BIT(0)));
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	/*Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.*/
184*4882a593Smuzhiyun 	tmp_reg422 = platform_efio_read_1byte(adapter, REG_FWHW_TXQ_CTRL_8814A + 2);
185*4882a593Smuzhiyun 	platform_efio_write_1byte(adapter, REG_FWHW_TXQ_CTRL_8814A + 2,  tmp_reg422 & (~BIT(6)));
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	if (tmp_reg422 & BIT(6)) {
188*4882a593Smuzhiyun 		RT_TRACE(COMP_INIT, DBG_LOUD, ("SetBeamformDownloadNDPA_8814A(): There is an adapter is sending beacon.\n"));
189*4882a593Smuzhiyun 		is_send_beacon = true;
190*4882a593Smuzhiyun 	}
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	/*@0x204[11:0]	Beacon Head for TXDMA*/
193*4882a593Smuzhiyun 	platform_efio_write_2byte(adapter, REG_FIFOPAGE_CTRL_2_8814A, head_page);
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	do {
196*4882a593Smuzhiyun 		/*@Clear beacon valid check bit.*/
197*4882a593Smuzhiyun 		bcn_valid_reg = platform_efio_read_1byte(adapter, REG_FIFOPAGE_CTRL_2_8814A + 1);
198*4882a593Smuzhiyun 		platform_efio_write_1byte(adapter, REG_FIFOPAGE_CTRL_2_8814A + 1, (bcn_valid_reg | BIT(7)));
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 		/*@download NDPA rsvd page.*/
201*4882a593Smuzhiyun 		if (p_beam_entry->beamform_entry_cap & BEAMFORMER_CAP_VHT_SU)
202*4882a593Smuzhiyun 			beamforming_send_vht_ndpa_packet(dm, p_beam_entry->mac_addr, p_beam_entry->AID, p_beam_entry->sound_bw, BEACON_QUEUE);
203*4882a593Smuzhiyun 		else
204*4882a593Smuzhiyun 			beamforming_send_ht_ndpa_packet(dm, p_beam_entry->mac_addr, p_beam_entry->sound_bw, BEACON_QUEUE);
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 		/*@check rsvd page download OK.*/
207*4882a593Smuzhiyun 		bcn_valid_reg = platform_efio_read_1byte(adapter, REG_FIFOPAGE_CTRL_2_8814A + 1);
208*4882a593Smuzhiyun 		count = 0;
209*4882a593Smuzhiyun 		while (!(bcn_valid_reg & BIT(7)) && count < 20) {
210*4882a593Smuzhiyun 			count++;
211*4882a593Smuzhiyun 			delay_us(10);
212*4882a593Smuzhiyun 			bcn_valid_reg = platform_efio_read_1byte(adapter, REG_FIFOPAGE_CTRL_2_8814A + 2);
213*4882a593Smuzhiyun 		}
214*4882a593Smuzhiyun 		dl_bcn_count++;
215*4882a593Smuzhiyun 	} while (!(bcn_valid_reg & BIT(7)) && dl_bcn_count < 5);
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	if (!(bcn_valid_reg & BIT(0)))
218*4882a593Smuzhiyun 		RT_DISP(FBEAM, FBEAM_ERROR, ("%s Download RSVD page failed!\n", __func__));
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	/*@0x204[11:0]	Beacon Head for TXDMA*/
221*4882a593Smuzhiyun 	platform_efio_write_2byte(adapter, REG_FIFOPAGE_CTRL_2_8814A, tx_page_bndy);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	/*To make sure that if there exists an adapter which would like to send beacon.*/
224*4882a593Smuzhiyun 	/*@If exists, the origianl value of 0x422[6] will be 1, we should check this to*/
225*4882a593Smuzhiyun 	/*prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
226*4882a593Smuzhiyun 	/*the beacon cannot be sent by HW.*/
227*4882a593Smuzhiyun 	/*@2010.06.23. Added by tynli.*/
228*4882a593Smuzhiyun 	if (is_send_beacon)
229*4882a593Smuzhiyun 		platform_efio_write_1byte(adapter, REG_FWHW_TXQ_CTRL_8814A + 2, tmp_reg422);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	/*@Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli.*/
232*4882a593Smuzhiyun 	/*@Clear CR[8] or beacon packet will not be send to TxBuf anymore.*/
233*4882a593Smuzhiyun 	u1b_tmp = platform_efio_read_1byte(adapter, REG_CR_8814A + 1);
234*4882a593Smuzhiyun 	platform_efio_write_1byte(adapter, REG_CR_8814A + 1, (u1b_tmp & (~BIT(0))));
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	p_beam_entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_PROGRESSED;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	hal_data->is_fw_dw_rsvd_page_in_progress = false;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun void
242*4882a593Smuzhiyun hal_txbf_8822b_fw_txbf_cmd(
243*4882a593Smuzhiyun 	void	*adapter
244*4882a593Smuzhiyun )
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun 	u8	idx, period = 0;
247*4882a593Smuzhiyun 	u8	PageNum0 = 0xFF, PageNum1 = 0xFF;
248*4882a593Smuzhiyun 	u8	u1_tx_bf_parm[3] = {0};
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	PMGNT_INFO				mgnt_info = &(adapter->MgntInfo);
251*4882a593Smuzhiyun 	struct _RT_BEAMFORMING_INFO	*beam_info = GET_BEAMFORM_INFO(adapter);
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) {
254*4882a593Smuzhiyun 		if (beam_info->beamformee_entry[idx].is_used && beam_info->beamformee_entry[idx].beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) {
255*4882a593Smuzhiyun 			if (beam_info->beamformee_entry[idx].is_sound) {
256*4882a593Smuzhiyun 				PageNum0 = 0xFE;
257*4882a593Smuzhiyun 				PageNum1 = 0x07;
258*4882a593Smuzhiyun 				period = (u8)(beam_info->beamformee_entry[idx].sound_period);
259*4882a593Smuzhiyun 			} else if (PageNum0 == 0xFF) {
260*4882a593Smuzhiyun 				PageNum0 = 0xFF; /*stop sounding*/
261*4882a593Smuzhiyun 				PageNum1 = 0x0F;
262*4882a593Smuzhiyun 			}
263*4882a593Smuzhiyun 		}
264*4882a593Smuzhiyun 	}
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	u1_tx_bf_parm[0] = PageNum0;
267*4882a593Smuzhiyun 	u1_tx_bf_parm[1] = PageNum1;
268*4882a593Smuzhiyun 	u1_tx_bf_parm[2] = period;
269*4882a593Smuzhiyun 	fill_h2c_cmd(adapter, PHYDM_H2C_TXBF, 3, u1_tx_bf_parm);
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	RT_DISP(FBEAM, FBEAM_FUN, ("@%s End, PageNum0 = 0x%x, PageNum1 = 0x%x period = %d", __func__, PageNum0, PageNum1, period));
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun #endif
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun #if 0
276*4882a593Smuzhiyun void
277*4882a593Smuzhiyun hal_txbf_8822b_init(
278*4882a593Smuzhiyun 	void			*dm_void
279*4882a593Smuzhiyun )
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun 	struct dm_struct	*dm = (struct dm_struct *)dm_void;
282*4882a593Smuzhiyun 	u8		u1b_tmp;
283*4882a593Smuzhiyun 	struct _RT_BEAMFORMING_INFO		*beamforming_info = &dm->beamforming_info;
284*4882a593Smuzhiyun 	void				*adapter = dm->adapter;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	odm_set_bb_reg(dm, R_0x14c0, BIT(16), 1); /*@Enable P1 aggr new packet according to P0 transfer time*/
287*4882a593Smuzhiyun 	odm_set_bb_reg(dm, R_0x14c0, BIT(15) | BIT14 | BIT13 | BIT12, 10); /*@MU Retry Limit*/
288*4882a593Smuzhiyun 	odm_set_bb_reg(dm, R_0x14c0, BIT(7), 0); /*@Disable Tx MU-MIMO until sounding done*/
289*4882a593Smuzhiyun 	odm_set_bb_reg(dm, R_0x14c0, 0x3F, 0); /* @Clear validity of MU STAs */
290*4882a593Smuzhiyun 	odm_write_1byte(dm, 0x167c, 0x70); /*@MU-MIMO Option as default value*/
291*4882a593Smuzhiyun 	odm_write_2byte(dm, 0x1680, 0); /*@MU-MIMO Control as default value*/
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	/* Set MU NDPA rate & BW source */
294*4882a593Smuzhiyun 	/* @0x42C[30] = 1 (0: from Tx desc, 1: from 0x45F) */
295*4882a593Smuzhiyun 	u1b_tmp = odm_read_1byte(dm, 0x42C);
296*4882a593Smuzhiyun 	odm_write_1byte(dm, REG_TXBF_CTRL_8822B, (u1b_tmp | BIT(6)));
297*4882a593Smuzhiyun 	/* @0x45F[7:0] = 0x10 (rate=OFDM_6M, BW20) */
298*4882a593Smuzhiyun 	odm_write_1byte(dm, REG_NDPA_OPT_CTRL_8822B, 0x10);
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	/*Temp Settings*/
301*4882a593Smuzhiyun 	odm_set_bb_reg(dm, R_0x6dc, 0x3F000000, 4); /*STA2's CSI rate is fixed at 6M*/
302*4882a593Smuzhiyun 	odm_set_bb_reg(dm, R_0x1c94, MASKDWORD, 0xAFFFAFFF); /*@Grouping bitmap parameters*/
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	/* @Init HW variable */
305*4882a593Smuzhiyun 	beamforming_info->reg_mu_tx_ctrl = odm_read_4byte(dm, 0x14c0);
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	if (dm->rf_type == RF_2T2R) { /*@2T2R*/
308*4882a593Smuzhiyun 		PHYDM_DBG(dm, DBG_TXBF, "%s: rf_type is 2T2R\n", __func__);
309*4882a593Smuzhiyun 		config_phydm_trx_mode_8822b(dm, (enum bb_path)3,
310*4882a593Smuzhiyun 					    (enum bb_path)3, BB_PATH_AB;
311*4882a593Smuzhiyun 	}
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun #if (OMNIPEEK_SNIFFER_ENABLED == 1)
314*4882a593Smuzhiyun 	/* @Config HW to receive packet on the user position from registry for sniffer mode. */
315*4882a593Smuzhiyun 	/* odm_set_bb_reg(dm, R_0xb00, BIT(9), 1);*/ /* For A-cut only. RegB00[9] = 1 (enable PMAC Rx) */
316*4882a593Smuzhiyun 	odm_set_bb_reg(dm, R_0xb54, BIT(30), 1); /* RegB54[30] = 1 (force user position) */
317*4882a593Smuzhiyun 	odm_set_bb_reg(dm, R_0xb54, (BIT(29) | BIT28), adapter->MgntInfo.sniff_user_position); /* RegB54[29:28] = user position (0~3) */
318*4882a593Smuzhiyun 	PHYDM_DBG(dm, DBG_TXBF,
319*4882a593Smuzhiyun 		  "Set adapter->MgntInfo.sniff_user_position=%#X\n",
320*4882a593Smuzhiyun 		  adapter->MgntInfo.sniff_user_position);
321*4882a593Smuzhiyun #endif
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun #endif
324*4882a593Smuzhiyun 
hal_txbf_8822b_enter(void * dm_void,u8 bfer_bfee_idx)325*4882a593Smuzhiyun void hal_txbf_8822b_enter(
326*4882a593Smuzhiyun 	void *dm_void,
327*4882a593Smuzhiyun 	u8 bfer_bfee_idx)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun 	struct dm_struct *dm = (struct dm_struct *)dm_void;
330*4882a593Smuzhiyun 	u8 i = 0;
331*4882a593Smuzhiyun 	u8 bfer_idx = (bfer_bfee_idx & 0xF0) >> 4;
332*4882a593Smuzhiyun 	u8 bfee_idx = (bfer_bfee_idx & 0xF);
333*4882a593Smuzhiyun 	u16 csi_param = 0;
334*4882a593Smuzhiyun 	struct _RT_BEAMFORMING_INFO *beamforming_info = &dm->beamforming_info;
335*4882a593Smuzhiyun 	struct _RT_BEAMFORMEE_ENTRY *p_beamformee_entry;
336*4882a593Smuzhiyun 	struct _RT_BEAMFORMER_ENTRY *beamformer_entry;
337*4882a593Smuzhiyun 	u16 value16, sta_id = 0;
338*4882a593Smuzhiyun 	u8 nc_index = 0, nr_index = 0, grouping = 0, codebookinfo = 0, coefficientsize = 0;
339*4882a593Smuzhiyun 	u32 gid_valid, user_position_l, user_position_h;
340*4882a593Smuzhiyun 	u32 mu_reg[6] = {0x1684, 0x1686, 0x1688, 0x168a, 0x168c, 0x168e};
341*4882a593Smuzhiyun 	u8 u1b_tmp;
342*4882a593Smuzhiyun 	u32 u4b_tmp;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	RT_DISP(FBEAM, FBEAM_FUN, ("%s: bfer_bfee_idx=%d, bfer_idx=%d, bfee_idx=%d\n", __func__, bfer_bfee_idx, bfer_idx, bfee_idx));
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	/*************SU BFer Entry Init*************/
347*4882a593Smuzhiyun 	if (beamforming_info->beamformer_su_cnt > 0 && bfer_idx < BEAMFORMER_ENTRY_NUM) {
348*4882a593Smuzhiyun 		beamformer_entry = &beamforming_info->beamformer_entry[bfer_idx];
349*4882a593Smuzhiyun 		beamformer_entry->is_mu_ap = false;
350*4882a593Smuzhiyun 		/*Sounding protocol control*/
351*4882a593Smuzhiyun 		odm_write_1byte(dm, REG_SND_PTCL_CTRL_8822B, 0xDB);
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 		for (i = 0; i < MAX_BEAMFORMER_SU; i++) {
354*4882a593Smuzhiyun 			if ((beamforming_info->beamformer_su_reg_maping & BIT(i)) == 0) {
355*4882a593Smuzhiyun 				beamforming_info->beamformer_su_reg_maping |= BIT(i);
356*4882a593Smuzhiyun 				beamformer_entry->su_reg_index = i;
357*4882a593Smuzhiyun 				break;
358*4882a593Smuzhiyun 			}
359*4882a593Smuzhiyun 		}
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 		/*@MAC address/Partial AID of Beamformer*/
362*4882a593Smuzhiyun 		if (beamformer_entry->su_reg_index == 0) {
363*4882a593Smuzhiyun 			for (i = 0; i < 6; i++)
364*4882a593Smuzhiyun 				odm_write_1byte(dm, (REG_ASSOCIATED_BFMER0_INFO_8822B + i), beamformer_entry->mac_addr[i]);
365*4882a593Smuzhiyun 		} else {
366*4882a593Smuzhiyun 			for (i = 0; i < 6; i++)
367*4882a593Smuzhiyun 				odm_write_1byte(dm, (REG_ASSOCIATED_BFMER1_INFO_8822B + i), beamformer_entry->mac_addr[i]);
368*4882a593Smuzhiyun 		}
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 		/*@CSI report parameters of Beamformer*/
371*4882a593Smuzhiyun 		nc_index = hal_txbf_8822b_get_nrx(dm); /*@for 8814A nrx = 3(4 ant), min=0(1 ant)*/
372*4882a593Smuzhiyun 		nr_index = beamformer_entry->num_of_sounding_dim; /*@0x718[7] = 1 use Nsts, 0x718[7] = 0 use reg setting. as Bfee, we use Nsts, so nr_index don't care*/
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 		grouping = 0;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 		/*@for ac = 1, for n = 3*/
377*4882a593Smuzhiyun 		if (beamformer_entry->beamform_entry_cap & BEAMFORMEE_CAP_VHT_SU)
378*4882a593Smuzhiyun 			codebookinfo = 1;
379*4882a593Smuzhiyun 		else if (beamformer_entry->beamform_entry_cap & BEAMFORMEE_CAP_HT_EXPLICIT)
380*4882a593Smuzhiyun 			codebookinfo = 3;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 		coefficientsize = 3;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 		csi_param = (u16)((coefficientsize << 10) | (codebookinfo << 8) | (grouping << 6) | (nr_index << 3) | (nc_index));
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 		if (bfer_idx == 0)
387*4882a593Smuzhiyun 			odm_write_2byte(dm, REG_TX_CSI_RPT_PARAM_BW20_8822B, csi_param);
388*4882a593Smuzhiyun 		else
389*4882a593Smuzhiyun 			odm_write_2byte(dm, REG_TX_CSI_RPT_PARAM_BW20_8822B + 2, csi_param);
390*4882a593Smuzhiyun 		/*ndp_rx_standby_timer, 8814 need > 0x56, suggest from Dvaid*/
391*4882a593Smuzhiyun 		odm_write_1byte(dm, REG_SND_PTCL_CTRL_8822B + 3, 0x70);
392*4882a593Smuzhiyun 	}
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	/*************SU BFee Entry Init*************/
395*4882a593Smuzhiyun 	if (beamforming_info->beamformee_su_cnt > 0 && bfee_idx < BEAMFORMEE_ENTRY_NUM) {
396*4882a593Smuzhiyun 		p_beamformee_entry = &beamforming_info->beamformee_entry[bfee_idx];
397*4882a593Smuzhiyun 		p_beamformee_entry->is_mu_sta = false;
398*4882a593Smuzhiyun 		hal_txbf_8822b_rf_mode(dm, beamforming_info, bfee_idx);
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 		if (phydm_acting_determine(dm, phydm_acting_as_ibss))
401*4882a593Smuzhiyun 			sta_id = p_beamformee_entry->mac_id;
402*4882a593Smuzhiyun 		else
403*4882a593Smuzhiyun 			sta_id = p_beamformee_entry->p_aid;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 		for (i = 0; i < MAX_BEAMFORMEE_SU; i++) {
406*4882a593Smuzhiyun 			if ((beamforming_info->beamformee_su_reg_maping & BIT(i)) == 0) {
407*4882a593Smuzhiyun 				beamforming_info->beamformee_su_reg_maping |= BIT(i);
408*4882a593Smuzhiyun 				p_beamformee_entry->su_reg_index = i;
409*4882a593Smuzhiyun 				break;
410*4882a593Smuzhiyun 			}
411*4882a593Smuzhiyun 		}
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 		/*P_AID of Beamformee & enable NDPA transmission & enable NDPA interrupt*/
414*4882a593Smuzhiyun 		if (p_beamformee_entry->su_reg_index == 0) {
415*4882a593Smuzhiyun 			odm_write_2byte(dm, REG_TXBF_CTRL_8822B, sta_id);
416*4882a593Smuzhiyun 			odm_write_1byte(dm, REG_TXBF_CTRL_8822B + 3, odm_read_1byte(dm, REG_TXBF_CTRL_8822B + 3) | BIT(4) | BIT(6) | BIT(7));
417*4882a593Smuzhiyun 		} else
418*4882a593Smuzhiyun 			odm_write_2byte(dm, REG_TXBF_CTRL_8822B + 2, sta_id | BIT(14) | BIT(15) | BIT(12));
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 		/*@CSI report parameters of Beamformee*/
421*4882a593Smuzhiyun 		if (p_beamformee_entry->su_reg_index == 0) {
422*4882a593Smuzhiyun 			/*@Get BIT24 & BIT25*/
423*4882a593Smuzhiyun 			u8 tmp = odm_read_1byte(dm, REG_ASSOCIATED_BFMEE_SEL_8822B + 3) & 0x3;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 			odm_write_1byte(dm, REG_ASSOCIATED_BFMEE_SEL_8822B + 3, tmp | 0x60);
426*4882a593Smuzhiyun 			odm_write_2byte(dm, REG_ASSOCIATED_BFMEE_SEL_8822B, sta_id | BIT(9));
427*4882a593Smuzhiyun 		} else
428*4882a593Smuzhiyun 			odm_write_2byte(dm, REG_ASSOCIATED_BFMEE_SEL_8822B + 2, sta_id | 0xE200); /*Set BIT25*/
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 		phydm_beamforming_notify(dm);
431*4882a593Smuzhiyun 	}
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	/*************MU BFer Entry Init*************/
434*4882a593Smuzhiyun 	if (beamforming_info->beamformer_mu_cnt > 0 && bfer_idx < BEAMFORMER_ENTRY_NUM) {
435*4882a593Smuzhiyun 		beamformer_entry = &beamforming_info->beamformer_entry[bfer_idx];
436*4882a593Smuzhiyun 		beamforming_info->mu_ap_index = bfer_idx;
437*4882a593Smuzhiyun 		beamformer_entry->is_mu_ap = true;
438*4882a593Smuzhiyun 		for (i = 0; i < 8; i++)
439*4882a593Smuzhiyun 			beamformer_entry->gid_valid[i] = 0;
440*4882a593Smuzhiyun 		for (i = 0; i < 16; i++)
441*4882a593Smuzhiyun 			beamformer_entry->user_position[i] = 0;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 		/*Sounding protocol control*/
444*4882a593Smuzhiyun 		odm_write_1byte(dm, REG_SND_PTCL_CTRL_8822B, 0xDB);
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 		/* @MAC address */
447*4882a593Smuzhiyun 		for (i = 0; i < 6; i++)
448*4882a593Smuzhiyun 			odm_write_1byte(dm, (REG_ASSOCIATED_BFMER0_INFO_8822B + i), beamformer_entry->mac_addr[i]);
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 		/* Set partial AID */
451*4882a593Smuzhiyun 		odm_write_2byte(dm, (REG_ASSOCIATED_BFMER0_INFO_8822B + 6), beamformer_entry->p_aid);
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 		/* @Fill our AID to 0x1680[11:0] and [13:12] = 2b'00, BF report segment select to 3895 bytes*/
454*4882a593Smuzhiyun 		u1b_tmp = odm_read_1byte(dm, 0x1680);
455*4882a593Smuzhiyun 		u1b_tmp = (beamformer_entry->p_aid) & 0xFFF;
456*4882a593Smuzhiyun 		odm_write_1byte(dm, 0x1680, u1b_tmp);
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 		/* Set 80us for leaving ndp_rx_standby_state */
459*4882a593Smuzhiyun 		odm_write_1byte(dm, 0x71B, 0x50);
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 		/* Set 0x6A0[14] = 1 to accept action_no_ack */
462*4882a593Smuzhiyun 		u1b_tmp = odm_read_1byte(dm, REG_RXFLTMAP0_8822B + 1);
463*4882a593Smuzhiyun 		u1b_tmp |= 0x40;
464*4882a593Smuzhiyun 		odm_write_1byte(dm, REG_RXFLTMAP0_8822B + 1, u1b_tmp);
465*4882a593Smuzhiyun 		/* Set 0x6A2[5:4] = 1 to NDPA and BF report poll */
466*4882a593Smuzhiyun 		u1b_tmp = odm_read_1byte(dm, REG_RXFLTMAP1_8822B);
467*4882a593Smuzhiyun 		u1b_tmp |= 0x30;
468*4882a593Smuzhiyun 		odm_write_1byte(dm, REG_RXFLTMAP1_8822B, u1b_tmp);
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 		/*@CSI report parameters of Beamformer*/
471*4882a593Smuzhiyun 		nc_index = hal_txbf_8822b_get_nrx(dm); /* @Depend on RF type */
472*4882a593Smuzhiyun 		nr_index = 1; /*@0x718[7] = 1 use Nsts, 0x718[7] = 0 use reg setting. as Bfee, we use Nsts, so nr_index don't care*/
473*4882a593Smuzhiyun 		grouping = 0; /*no grouping*/
474*4882a593Smuzhiyun 		codebookinfo = 1; /*@7 bit for psi, 9 bit for phi*/
475*4882a593Smuzhiyun 		coefficientsize = 0; /*This is nothing really matter*/
476*4882a593Smuzhiyun 		csi_param = (u16)((coefficientsize << 10) | (codebookinfo << 8) | (grouping << 6) | (nr_index << 3) | (nc_index));
477*4882a593Smuzhiyun 		odm_write_2byte(dm, 0x6F4, csi_param);
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 		/*@for B-cut*/
480*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0x6a0, BIT(20), 0);
481*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0x688, BIT(20), 0);
482*4882a593Smuzhiyun 	}
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	/*************MU BFee Entry Init*************/
485*4882a593Smuzhiyun 	if (beamforming_info->beamformee_mu_cnt > 0 && bfee_idx < BEAMFORMEE_ENTRY_NUM) {
486*4882a593Smuzhiyun 		p_beamformee_entry = &beamforming_info->beamformee_entry[bfee_idx];
487*4882a593Smuzhiyun 		p_beamformee_entry->is_mu_sta = true;
488*4882a593Smuzhiyun 		for (i = 0; i < MAX_BEAMFORMEE_MU; i++) {
489*4882a593Smuzhiyun 			if ((beamforming_info->beamformee_mu_reg_maping & BIT(i)) == 0) {
490*4882a593Smuzhiyun 				beamforming_info->beamformee_mu_reg_maping |= BIT(i);
491*4882a593Smuzhiyun 				p_beamformee_entry->mu_reg_index = i;
492*4882a593Smuzhiyun 				break;
493*4882a593Smuzhiyun 			}
494*4882a593Smuzhiyun 		}
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 		if (p_beamformee_entry->mu_reg_index == 0xFF) {
497*4882a593Smuzhiyun 			/* There is no valid bit in beamformee_mu_reg_maping */
498*4882a593Smuzhiyun 			RT_DISP(FBEAM, FBEAM_FUN, ("%s: ERROR! There is no valid bit in beamformee_mu_reg_maping!\n", __func__));
499*4882a593Smuzhiyun 			return;
500*4882a593Smuzhiyun 		}
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 		/*User position table*/
503*4882a593Smuzhiyun 		switch (p_beamformee_entry->mu_reg_index) {
504*4882a593Smuzhiyun 		case 0:
505*4882a593Smuzhiyun 			gid_valid = 0x7fe;
506*4882a593Smuzhiyun 			user_position_l = 0x111110;
507*4882a593Smuzhiyun 			user_position_h = 0x0;
508*4882a593Smuzhiyun 			break;
509*4882a593Smuzhiyun 		case 1:
510*4882a593Smuzhiyun 			gid_valid = 0x7f806;
511*4882a593Smuzhiyun 			user_position_l = 0x11000004;
512*4882a593Smuzhiyun 			user_position_h = 0x11;
513*4882a593Smuzhiyun 			break;
514*4882a593Smuzhiyun 		case 2:
515*4882a593Smuzhiyun 			gid_valid = 0x1f81818;
516*4882a593Smuzhiyun 			user_position_l = 0x400040;
517*4882a593Smuzhiyun 			user_position_h = 0x11100;
518*4882a593Smuzhiyun 			break;
519*4882a593Smuzhiyun 		case 3:
520*4882a593Smuzhiyun 			gid_valid = 0x1e186060;
521*4882a593Smuzhiyun 			user_position_l = 0x4000400;
522*4882a593Smuzhiyun 			user_position_h = 0x1100040;
523*4882a593Smuzhiyun 			break;
524*4882a593Smuzhiyun 		case 4:
525*4882a593Smuzhiyun 			gid_valid = 0x66618180;
526*4882a593Smuzhiyun 			user_position_l = 0x40004000;
527*4882a593Smuzhiyun 			user_position_h = 0x10040400;
528*4882a593Smuzhiyun 			break;
529*4882a593Smuzhiyun 		case 5:
530*4882a593Smuzhiyun 			gid_valid = 0x79860600;
531*4882a593Smuzhiyun 			user_position_l = 0x40000;
532*4882a593Smuzhiyun 			user_position_h = 0x4404004;
533*4882a593Smuzhiyun 			break;
534*4882a593Smuzhiyun 		}
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 		for (i = 0; i < 8; i++) {
537*4882a593Smuzhiyun 			if (i < 4) {
538*4882a593Smuzhiyun 				p_beamformee_entry->gid_valid[i] = (u8)(gid_valid & 0xFF);
539*4882a593Smuzhiyun 				gid_valid = (gid_valid >> 8);
540*4882a593Smuzhiyun 			} else
541*4882a593Smuzhiyun 				p_beamformee_entry->gid_valid[i] = 0;
542*4882a593Smuzhiyun 		}
543*4882a593Smuzhiyun 		for (i = 0; i < 16; i++) {
544*4882a593Smuzhiyun 			if (i < 4)
545*4882a593Smuzhiyun 				p_beamformee_entry->user_position[i] = (u8)((user_position_l >> (i * 8)) & 0xFF);
546*4882a593Smuzhiyun 			else if (i < 8)
547*4882a593Smuzhiyun 				p_beamformee_entry->user_position[i] = (u8)((user_position_h >> ((i - 4) * 8)) & 0xFF);
548*4882a593Smuzhiyun 			else
549*4882a593Smuzhiyun 				p_beamformee_entry->user_position[i] = 0;
550*4882a593Smuzhiyun 		}
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 		/*Sounding protocol control*/
553*4882a593Smuzhiyun 		odm_write_1byte(dm, REG_SND_PTCL_CTRL_8822B, 0xDB);
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 		/*select MU STA table*/
556*4882a593Smuzhiyun 		beamforming_info->reg_mu_tx_ctrl &= ~(BIT(8) | BIT(9) | BIT(10));
557*4882a593Smuzhiyun 		beamforming_info->reg_mu_tx_ctrl |= (p_beamformee_entry->mu_reg_index << 8) & (BIT(8) | BIT(9) | BIT(10));
558*4882a593Smuzhiyun 		odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0x14c4, MASKDWORD, 0); /*Reset gid_valid table*/
561*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0x14c8, MASKDWORD, user_position_l);
562*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0x14cc, MASKDWORD, user_position_h);
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 		/*set validity of MU STAs*/
565*4882a593Smuzhiyun 		beamforming_info->reg_mu_tx_ctrl &= 0xFFFFFFC0;
566*4882a593Smuzhiyun 		beamforming_info->reg_mu_tx_ctrl |= beamforming_info->beamformee_mu_reg_maping & 0x3F;
567*4882a593Smuzhiyun 		odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 		PHYDM_DBG(dm, DBG_TXBF,
570*4882a593Smuzhiyun 			  "@%s, reg_mu_tx_ctrl = 0x%x, user_position_l = 0x%x, user_position_h = 0x%x\n",
571*4882a593Smuzhiyun 			  __func__, beamforming_info->reg_mu_tx_ctrl,
572*4882a593Smuzhiyun 			  user_position_l, user_position_h);
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 		value16 = odm_read_2byte(dm, mu_reg[p_beamformee_entry->mu_reg_index]);
575*4882a593Smuzhiyun 		value16 &= 0xFE00; /*@Clear PAID*/
576*4882a593Smuzhiyun 		value16 |= BIT(9); /*@Enable MU BFee*/
577*4882a593Smuzhiyun 		value16 |= p_beamformee_entry->p_aid;
578*4882a593Smuzhiyun 		odm_write_2byte(dm, mu_reg[p_beamformee_entry->mu_reg_index], value16);
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun 		/* @0x42C[30] = 1 (0: from Tx desc, 1: from 0x45F) */
581*4882a593Smuzhiyun 		u1b_tmp = odm_read_1byte(dm, REG_TXBF_CTRL_8822B + 3);
582*4882a593Smuzhiyun 		u1b_tmp |= 0xD0; /* Set bit 28, 30, 31 to 3b'111*/
583*4882a593Smuzhiyun 		odm_write_1byte(dm, REG_TXBF_CTRL_8822B + 3, u1b_tmp);
584*4882a593Smuzhiyun 		/* Set NDPA to 6M*/
585*4882a593Smuzhiyun 		odm_write_1byte(dm, REG_NDPA_RATE_8822B, 0x4);
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 		u1b_tmp = odm_read_1byte(dm, REG_NDPA_OPT_CTRL_8822B);
588*4882a593Smuzhiyun 		u1b_tmp &= 0xFC; /* @Clear bit 0, 1*/
589*4882a593Smuzhiyun 		odm_write_1byte(dm, REG_NDPA_OPT_CTRL_8822B, u1b_tmp);
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun 		u4b_tmp = odm_read_4byte(dm, REG_SND_PTCL_CTRL_8822B);
592*4882a593Smuzhiyun 		u4b_tmp = ((u4b_tmp & 0xFF0000FF) | 0x020200); /* Set [23:8] to 0x0202*/
593*4882a593Smuzhiyun 		odm_write_4byte(dm, REG_SND_PTCL_CTRL_8822B, u4b_tmp);
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 		/* Set 0x6A0[14] = 1 to accept action_no_ack */
596*4882a593Smuzhiyun 		u1b_tmp = odm_read_1byte(dm, REG_RXFLTMAP0_8822B + 1);
597*4882a593Smuzhiyun 		u1b_tmp |= 0x40;
598*4882a593Smuzhiyun 		odm_write_1byte(dm, REG_RXFLTMAP0_8822B + 1, u1b_tmp);
599*4882a593Smuzhiyun 		/* @End of MAC registers setting */
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 		hal_txbf_8822b_rf_mode(dm, beamforming_info, bfee_idx);
602*4882a593Smuzhiyun #if (SUPPORT_MU_BF == 1)
603*4882a593Smuzhiyun 		/*Special for plugfest*/
604*4882a593Smuzhiyun 		delay_ms(50); /* wait for 4-way handshake ending*/
605*4882a593Smuzhiyun 		send_sw_vht_gid_mgnt_frame(dm, p_beamformee_entry->mac_addr, bfee_idx);
606*4882a593Smuzhiyun #endif
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 		phydm_beamforming_notify(dm);
609*4882a593Smuzhiyun #if 1
610*4882a593Smuzhiyun 		{
611*4882a593Smuzhiyun 			u32 ctrl_info_offset, index;
612*4882a593Smuzhiyun 			/*Set Ctrl Info*/
613*4882a593Smuzhiyun 			odm_write_2byte(dm, 0x140, 0x660);
614*4882a593Smuzhiyun 			ctrl_info_offset = 0x8000 + 32 * p_beamformee_entry->mac_id;
615*4882a593Smuzhiyun 			/*Reset Ctrl Info*/
616*4882a593Smuzhiyun 			for (index = 0; index < 8; index++)
617*4882a593Smuzhiyun 				odm_write_4byte(dm, ctrl_info_offset + index * 4, 0);
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 			odm_write_4byte(dm, ctrl_info_offset, (p_beamformee_entry->mu_reg_index + 1) << 16);
620*4882a593Smuzhiyun 			odm_write_1byte(dm, 0x81, 0x80); /*RPTBUF ready*/
621*4882a593Smuzhiyun 
622*4882a593Smuzhiyun 			PHYDM_DBG(dm, DBG_TXBF,
623*4882a593Smuzhiyun 				  "@%s, mac_id = %d, ctrl_info_offset = 0x%x, mu_reg_index = %x\n",
624*4882a593Smuzhiyun 				  __func__, p_beamformee_entry->mac_id,
625*4882a593Smuzhiyun 				  ctrl_info_offset,
626*4882a593Smuzhiyun 				  p_beamformee_entry->mu_reg_index);
627*4882a593Smuzhiyun 		}
628*4882a593Smuzhiyun #endif
629*4882a593Smuzhiyun 	}
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun 
hal_txbf_8822b_leave(void * dm_void,u8 idx)632*4882a593Smuzhiyun void hal_txbf_8822b_leave(
633*4882a593Smuzhiyun 	void *dm_void,
634*4882a593Smuzhiyun 	u8 idx)
635*4882a593Smuzhiyun {
636*4882a593Smuzhiyun 	struct dm_struct *dm = (struct dm_struct *)dm_void;
637*4882a593Smuzhiyun 	struct _RT_BEAMFORMING_INFO *beamforming_info = &dm->beamforming_info;
638*4882a593Smuzhiyun 	struct _RT_BEAMFORMER_ENTRY *beamformer_entry;
639*4882a593Smuzhiyun 	struct _RT_BEAMFORMEE_ENTRY *p_beamformee_entry;
640*4882a593Smuzhiyun 	u32 mu_reg[6] = {0x1684, 0x1686, 0x1688, 0x168a, 0x168c, 0x168e};
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 	if (idx < BEAMFORMER_ENTRY_NUM) {
643*4882a593Smuzhiyun 		beamformer_entry = &beamforming_info->beamformer_entry[idx];
644*4882a593Smuzhiyun 		p_beamformee_entry = &beamforming_info->beamformee_entry[idx];
645*4882a593Smuzhiyun 	} else
646*4882a593Smuzhiyun 		return;
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	/*@Clear P_AID of Beamformee*/
649*4882a593Smuzhiyun 	/*@Clear MAC address of Beamformer*/
650*4882a593Smuzhiyun 	/*@Clear Associated Bfmee Sel*/
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 	if (beamformer_entry->beamform_entry_cap == BEAMFORMING_CAP_NONE) {
653*4882a593Smuzhiyun 		odm_write_1byte(dm, REG_SND_PTCL_CTRL_8822B, 0xD8);
654*4882a593Smuzhiyun 		if (beamformer_entry->is_mu_ap == 0) { /*SU BFer */
655*4882a593Smuzhiyun 			if (beamformer_entry->su_reg_index == 0) {
656*4882a593Smuzhiyun 				odm_write_4byte(dm, REG_ASSOCIATED_BFMER0_INFO_8822B, 0);
657*4882a593Smuzhiyun 				odm_write_2byte(dm, REG_ASSOCIATED_BFMER0_INFO_8822B + 4, 0);
658*4882a593Smuzhiyun 				odm_write_2byte(dm, REG_TX_CSI_RPT_PARAM_BW20_8822B, 0);
659*4882a593Smuzhiyun 			} else {
660*4882a593Smuzhiyun 				odm_write_4byte(dm, REG_ASSOCIATED_BFMER1_INFO_8822B, 0);
661*4882a593Smuzhiyun 				odm_write_2byte(dm, REG_ASSOCIATED_BFMER1_INFO_8822B + 4, 0);
662*4882a593Smuzhiyun 				odm_write_2byte(dm, REG_TX_CSI_RPT_PARAM_BW20_8822B + 2, 0);
663*4882a593Smuzhiyun 			}
664*4882a593Smuzhiyun 			beamforming_info->beamformer_su_reg_maping &= ~(BIT(beamformer_entry->su_reg_index));
665*4882a593Smuzhiyun 			beamformer_entry->su_reg_index = 0xFF;
666*4882a593Smuzhiyun 		} else { /*@MU BFer */
667*4882a593Smuzhiyun 			/*set validity of MU STA0 and MU STA1*/
668*4882a593Smuzhiyun 			beamforming_info->reg_mu_tx_ctrl &= 0xFFFFFFC0;
669*4882a593Smuzhiyun 			odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun 			odm_memory_set(dm, beamformer_entry->gid_valid, 0, 8);
672*4882a593Smuzhiyun 			odm_memory_set(dm, beamformer_entry->user_position, 0, 16);
673*4882a593Smuzhiyun 			beamformer_entry->is_mu_ap = false;
674*4882a593Smuzhiyun 		}
675*4882a593Smuzhiyun 	}
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	if (p_beamformee_entry->beamform_entry_cap == BEAMFORMING_CAP_NONE) {
678*4882a593Smuzhiyun 		hal_txbf_8822b_rf_mode(dm, beamforming_info, idx);
679*4882a593Smuzhiyun 		if (p_beamformee_entry->is_mu_sta == 0) { /*SU BFee*/
680*4882a593Smuzhiyun 			if (p_beamformee_entry->su_reg_index == 0) {
681*4882a593Smuzhiyun 				odm_write_2byte(dm, REG_TXBF_CTRL_8822B, 0x0);
682*4882a593Smuzhiyun 				odm_write_1byte(dm, REG_TXBF_CTRL_8822B + 3, odm_read_1byte(dm, REG_TXBF_CTRL_8822B + 3) | BIT(4) | BIT(6) | BIT(7));
683*4882a593Smuzhiyun 				odm_write_2byte(dm, REG_ASSOCIATED_BFMEE_SEL_8822B, 0);
684*4882a593Smuzhiyun 			} else {
685*4882a593Smuzhiyun 				odm_write_2byte(dm, REG_TXBF_CTRL_8822B + 2, 0x0 | BIT(14) | BIT(15) | BIT(12));
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun 				odm_write_2byte(dm, REG_ASSOCIATED_BFMEE_SEL_8822B + 2,
688*4882a593Smuzhiyun 						odm_read_2byte(dm, REG_ASSOCIATED_BFMEE_SEL_8822B + 2) & 0x60);
689*4882a593Smuzhiyun 			}
690*4882a593Smuzhiyun 			beamforming_info->beamformee_su_reg_maping &= ~(BIT(p_beamformee_entry->su_reg_index));
691*4882a593Smuzhiyun 			p_beamformee_entry->su_reg_index = 0xFF;
692*4882a593Smuzhiyun 		} else { /*@MU BFee */
693*4882a593Smuzhiyun 			/*@Disable sending NDPA & BF-rpt-poll to this BFee*/
694*4882a593Smuzhiyun 			odm_write_2byte(dm, mu_reg[p_beamformee_entry->mu_reg_index], 0);
695*4882a593Smuzhiyun 			/*set validity of MU STA*/
696*4882a593Smuzhiyun 			beamforming_info->reg_mu_tx_ctrl &= ~(BIT(p_beamformee_entry->mu_reg_index));
697*4882a593Smuzhiyun 			odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 			p_beamformee_entry->is_mu_sta = false;
700*4882a593Smuzhiyun 			beamforming_info->beamformee_mu_reg_maping &= ~(BIT(p_beamformee_entry->mu_reg_index));
701*4882a593Smuzhiyun 			p_beamformee_entry->mu_reg_index = 0xFF;
702*4882a593Smuzhiyun 		}
703*4882a593Smuzhiyun 	}
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun /***********SU & MU BFee Entry Only when souding done****************/
hal_txbf_8822b_status(void * dm_void,u8 beamform_idx)707*4882a593Smuzhiyun void hal_txbf_8822b_status(
708*4882a593Smuzhiyun 	void *dm_void,
709*4882a593Smuzhiyun 	u8 beamform_idx)
710*4882a593Smuzhiyun {
711*4882a593Smuzhiyun 	struct dm_struct *dm = (struct dm_struct *)dm_void;
712*4882a593Smuzhiyun 	u16 beam_ctrl_val, tmp_val;
713*4882a593Smuzhiyun 	u32 beam_ctrl_reg;
714*4882a593Smuzhiyun 	struct _RT_BEAMFORMING_INFO *beamforming_info = &dm->beamforming_info;
715*4882a593Smuzhiyun 	struct _RT_BEAMFORMEE_ENTRY *beamform_entry;
716*4882a593Smuzhiyun 	boolean is_mu_sounding = beamforming_info->is_mu_sounding, is_bitmap_ready = false;
717*4882a593Smuzhiyun 	u16 bitmap;
718*4882a593Smuzhiyun 	u8 idx, gid, i;
719*4882a593Smuzhiyun 	u8 id1, id0;
720*4882a593Smuzhiyun 	u32 gid_valid[6] = {0};
721*4882a593Smuzhiyun 	u32 value32;
722*4882a593Smuzhiyun 	boolean is_sounding_success[6] = {false};
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun 	if (beamform_idx < BEAMFORMEE_ENTRY_NUM)
725*4882a593Smuzhiyun 		beamform_entry = &beamforming_info->beamformee_entry[beamform_idx];
726*4882a593Smuzhiyun 	else
727*4882a593Smuzhiyun 		return;
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	/*SU sounding done */
730*4882a593Smuzhiyun 	if (is_mu_sounding == false) {
731*4882a593Smuzhiyun 		if (phydm_acting_determine(dm, phydm_acting_as_ibss))
732*4882a593Smuzhiyun 			beam_ctrl_val = beamform_entry->mac_id;
733*4882a593Smuzhiyun 		else
734*4882a593Smuzhiyun 			beam_ctrl_val = beamform_entry->p_aid;
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 		PHYDM_DBG(dm, DBG_TXBF,
737*4882a593Smuzhiyun 			  "@%s, beamform_entry.beamform_entry_state = %d",
738*4882a593Smuzhiyun 			  __func__, beamform_entry->beamform_entry_state);
739*4882a593Smuzhiyun 
740*4882a593Smuzhiyun 		if (beamform_entry->su_reg_index == 0)
741*4882a593Smuzhiyun 			beam_ctrl_reg = REG_TXBF_CTRL_8822B;
742*4882a593Smuzhiyun 		else {
743*4882a593Smuzhiyun 			beam_ctrl_reg = REG_TXBF_CTRL_8822B + 2;
744*4882a593Smuzhiyun 			beam_ctrl_val |= BIT(12) | BIT(14) | BIT(15);
745*4882a593Smuzhiyun 		}
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 		if (beamform_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) {
748*4882a593Smuzhiyun 			if (beamform_entry->sound_bw == CHANNEL_WIDTH_20)
749*4882a593Smuzhiyun 				beam_ctrl_val |= BIT(9);
750*4882a593Smuzhiyun 			else if (beamform_entry->sound_bw == CHANNEL_WIDTH_40)
751*4882a593Smuzhiyun 				beam_ctrl_val |= (BIT(9) | BIT(10));
752*4882a593Smuzhiyun 			else if (beamform_entry->sound_bw == CHANNEL_WIDTH_80)
753*4882a593Smuzhiyun 				beam_ctrl_val |= (BIT(9) | BIT(10) | BIT(11));
754*4882a593Smuzhiyun 		} else {
755*4882a593Smuzhiyun 			PHYDM_DBG(dm, DBG_TXBF, "@%s, Don't apply Vmatrix",
756*4882a593Smuzhiyun 				  __func__);
757*4882a593Smuzhiyun 			beam_ctrl_val &= ~(BIT(9) | BIT(10) | BIT(11));
758*4882a593Smuzhiyun 		}
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun 		odm_write_2byte(dm, beam_ctrl_reg, beam_ctrl_val);
761*4882a593Smuzhiyun 		/*@disable NDP packet use beamforming */
762*4882a593Smuzhiyun 		tmp_val = odm_read_2byte(dm, REG_TXBF_CTRL_8822B);
763*4882a593Smuzhiyun 		odm_write_2byte(dm, REG_TXBF_CTRL_8822B, tmp_val | BIT(15));
764*4882a593Smuzhiyun 	} else {
765*4882a593Smuzhiyun 		PHYDM_DBG(dm, DBG_TXBF, "@%s, MU Sounding Done\n", __func__);
766*4882a593Smuzhiyun 		/*@MU sounding done */
767*4882a593Smuzhiyun 		if (1) { /* @(beamform_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) { */
768*4882a593Smuzhiyun 			PHYDM_DBG(dm, DBG_TXBF,
769*4882a593Smuzhiyun 				  "@%s, BEAMFORMING_ENTRY_STATE_PROGRESSED\n",
770*4882a593Smuzhiyun 				  __func__);
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 			value32 = odm_get_bb_reg(dm, R_0x1684, MASKDWORD);
773*4882a593Smuzhiyun 			is_sounding_success[0] = (value32 & BIT(10)) ? 1 : 0;
774*4882a593Smuzhiyun 			is_sounding_success[1] = (value32 & BIT(26)) ? 1 : 0;
775*4882a593Smuzhiyun 			value32 = odm_get_bb_reg(dm, R_0x1688, MASKDWORD);
776*4882a593Smuzhiyun 			is_sounding_success[2] = (value32 & BIT(10)) ? 1 : 0;
777*4882a593Smuzhiyun 			is_sounding_success[3] = (value32 & BIT(26)) ? 1 : 0;
778*4882a593Smuzhiyun 			value32 = odm_get_bb_reg(dm, R_0x168c, MASKDWORD);
779*4882a593Smuzhiyun 			is_sounding_success[4] = (value32 & BIT(10)) ? 1 : 0;
780*4882a593Smuzhiyun 			is_sounding_success[5] = (value32 & BIT(26)) ? 1 : 0;
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun 			PHYDM_DBG(dm, DBG_TXBF,
783*4882a593Smuzhiyun 				  "@%s, is_sounding_success STA1:%d,  STA2:%d, STA3:%d, STA4:%d, STA5:%d, STA6:%d\n",
784*4882a593Smuzhiyun 				  __func__, is_sounding_success[0],
785*4882a593Smuzhiyun 				  is_sounding_success[1],
786*4882a593Smuzhiyun 				  is_sounding_success[2],
787*4882a593Smuzhiyun 				  is_sounding_success[3],
788*4882a593Smuzhiyun 				  is_sounding_success[4],
789*4882a593Smuzhiyun 				  is_sounding_success[5]);
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 			value32 = odm_get_bb_reg(dm, R_0xf4c, 0xFFFF0000);
792*4882a593Smuzhiyun 			/* odm_set_bb_reg(dm, R_0x19e0, MASKHWORD, 0xFFFF);Let MAC ignore bitmap */
793*4882a593Smuzhiyun 
794*4882a593Smuzhiyun 			is_bitmap_ready = (boolean)((value32 & BIT(15)) >> 15);
795*4882a593Smuzhiyun 			bitmap = (u16)(value32 & 0x3FFF);
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun 			for (idx = 0; idx < 15; idx++) {
798*4882a593Smuzhiyun 				if (idx < 5) { /*@bit0~4*/
799*4882a593Smuzhiyun 					id0 = 0;
800*4882a593Smuzhiyun 					id1 = (u8)(idx + 1);
801*4882a593Smuzhiyun 				} else if (idx < 9) { /*@bit5~8*/
802*4882a593Smuzhiyun 					id0 = 1;
803*4882a593Smuzhiyun 					id1 = (u8)(idx - 3);
804*4882a593Smuzhiyun 				} else if (idx < 12) { /*@bit9~11*/
805*4882a593Smuzhiyun 					id0 = 2;
806*4882a593Smuzhiyun 					id1 = (u8)(idx - 6);
807*4882a593Smuzhiyun 				} else if (idx < 14) { /*@bit12~13*/
808*4882a593Smuzhiyun 					id0 = 3;
809*4882a593Smuzhiyun 					id1 = (u8)(idx - 8);
810*4882a593Smuzhiyun 				} else { /*@bit14*/
811*4882a593Smuzhiyun 					id0 = 4;
812*4882a593Smuzhiyun 					id1 = (u8)(idx - 9);
813*4882a593Smuzhiyun 				}
814*4882a593Smuzhiyun 				if (bitmap & BIT(idx)) {
815*4882a593Smuzhiyun 					/*Pair 1*/
816*4882a593Smuzhiyun 					gid = (idx << 1) + 1;
817*4882a593Smuzhiyun 					gid_valid[id0] |= (BIT(gid));
818*4882a593Smuzhiyun 					gid_valid[id1] |= (BIT(gid));
819*4882a593Smuzhiyun 					/*Pair 2*/
820*4882a593Smuzhiyun 					gid += 1;
821*4882a593Smuzhiyun 					gid_valid[id0] |= (BIT(gid));
822*4882a593Smuzhiyun 					gid_valid[id1] |= (BIT(gid));
823*4882a593Smuzhiyun 				} else {
824*4882a593Smuzhiyun 					/*Pair 1*/
825*4882a593Smuzhiyun 					gid = (idx << 1) + 1;
826*4882a593Smuzhiyun 					gid_valid[id0] &= ~(BIT(gid));
827*4882a593Smuzhiyun 					gid_valid[id1] &= ~(BIT(gid));
828*4882a593Smuzhiyun 					/*Pair 2*/
829*4882a593Smuzhiyun 					gid += 1;
830*4882a593Smuzhiyun 					gid_valid[id0] &= ~(BIT(gid));
831*4882a593Smuzhiyun 					gid_valid[id1] &= ~(BIT(gid));
832*4882a593Smuzhiyun 				}
833*4882a593Smuzhiyun 			}
834*4882a593Smuzhiyun 
835*4882a593Smuzhiyun 			for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {
836*4882a593Smuzhiyun 				beamform_entry = &beamforming_info->beamformee_entry[i];
837*4882a593Smuzhiyun 				if (beamform_entry->is_mu_sta && beamform_entry->mu_reg_index < 6) {
838*4882a593Smuzhiyun 					value32 = gid_valid[beamform_entry->mu_reg_index];
839*4882a593Smuzhiyun 					for (idx = 0; idx < 4; idx++) {
840*4882a593Smuzhiyun 						beamform_entry->gid_valid[idx] = (u8)(value32 & 0xFF);
841*4882a593Smuzhiyun 						value32 = (value32 >> 8);
842*4882a593Smuzhiyun 					}
843*4882a593Smuzhiyun 				}
844*4882a593Smuzhiyun 			}
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun 			for (idx = 0; idx < 6; idx++) {
847*4882a593Smuzhiyun 				beamforming_info->reg_mu_tx_ctrl &= ~(BIT(8) | BIT(9) | BIT(10));
848*4882a593Smuzhiyun 				beamforming_info->reg_mu_tx_ctrl |= ((idx << 8) & (BIT(8) | BIT(9) | BIT(10)));
849*4882a593Smuzhiyun 				odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
850*4882a593Smuzhiyun 				odm_set_mac_reg(dm, R_0x14c4, MASKDWORD, gid_valid[idx]); /*set MU STA gid valid table*/
851*4882a593Smuzhiyun 			}
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 			/*@Enable TxMU PPDU*/
854*4882a593Smuzhiyun 			if (beamforming_info->dbg_disable_mu_tx == false)
855*4882a593Smuzhiyun 				beamforming_info->reg_mu_tx_ctrl |= BIT(7);
856*4882a593Smuzhiyun 			else
857*4882a593Smuzhiyun 				beamforming_info->reg_mu_tx_ctrl &= ~BIT(7);
858*4882a593Smuzhiyun 			odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
859*4882a593Smuzhiyun 		}
860*4882a593Smuzhiyun 	}
861*4882a593Smuzhiyun }
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun /*Only used for MU BFer Entry when get GID management frame (self is as MU STA)*/
hal_txbf_8822b_config_gtab(void * dm_void)864*4882a593Smuzhiyun void hal_txbf_8822b_config_gtab(
865*4882a593Smuzhiyun 	void *dm_void)
866*4882a593Smuzhiyun {
867*4882a593Smuzhiyun 	struct dm_struct *dm = (struct dm_struct *)dm_void;
868*4882a593Smuzhiyun 	struct _RT_BEAMFORMING_INFO *beamforming_info = &dm->beamforming_info;
869*4882a593Smuzhiyun 	struct _RT_BEAMFORMER_ENTRY *beamformer_entry = NULL;
870*4882a593Smuzhiyun 	u32 gid_valid = 0, user_position_l = 0, user_position_h = 0, i;
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun 	if (beamforming_info->mu_ap_index < BEAMFORMER_ENTRY_NUM)
873*4882a593Smuzhiyun 		beamformer_entry = &beamforming_info->beamformer_entry[beamforming_info->mu_ap_index];
874*4882a593Smuzhiyun 	else
875*4882a593Smuzhiyun 		return;
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun 	PHYDM_DBG(dm, DBG_TXBF, "%s==>\n", __func__);
878*4882a593Smuzhiyun 
879*4882a593Smuzhiyun 	/*@For GID 0~31*/
880*4882a593Smuzhiyun 	for (i = 0; i < 4; i++)
881*4882a593Smuzhiyun 		gid_valid |= (beamformer_entry->gid_valid[i] << (i << 3));
882*4882a593Smuzhiyun 	for (i = 0; i < 8; i++) {
883*4882a593Smuzhiyun 		if (i < 4)
884*4882a593Smuzhiyun 			user_position_l |= (beamformer_entry->user_position[i] << (i << 3));
885*4882a593Smuzhiyun 		else
886*4882a593Smuzhiyun 			user_position_h |= (beamformer_entry->user_position[i] << ((i - 4) << 3));
887*4882a593Smuzhiyun 	}
888*4882a593Smuzhiyun 	/*select MU STA0 table*/
889*4882a593Smuzhiyun 	beamforming_info->reg_mu_tx_ctrl &= ~(BIT(8) | BIT(9) | BIT(10));
890*4882a593Smuzhiyun 	odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
891*4882a593Smuzhiyun 	odm_set_bb_reg(dm, R_0x14c4, MASKDWORD, gid_valid);
892*4882a593Smuzhiyun 	odm_set_bb_reg(dm, R_0x14c8, MASKDWORD, user_position_l);
893*4882a593Smuzhiyun 	odm_set_bb_reg(dm, R_0x14cc, MASKDWORD, user_position_h);
894*4882a593Smuzhiyun 
895*4882a593Smuzhiyun 	PHYDM_DBG(dm, DBG_TXBF,
896*4882a593Smuzhiyun 		  "%s: STA0: gid_valid = 0x%x, user_position_l = 0x%x, user_position_h = 0x%x\n",
897*4882a593Smuzhiyun 		  __func__, gid_valid, user_position_l, user_position_h);
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun 	gid_valid = 0;
900*4882a593Smuzhiyun 	user_position_l = 0;
901*4882a593Smuzhiyun 	user_position_h = 0;
902*4882a593Smuzhiyun 
903*4882a593Smuzhiyun 	/*@For GID 32~64*/
904*4882a593Smuzhiyun 	for (i = 4; i < 8; i++)
905*4882a593Smuzhiyun 		gid_valid |= (beamformer_entry->gid_valid[i] << ((i - 4) << 3));
906*4882a593Smuzhiyun 	for (i = 8; i < 16; i++) {
907*4882a593Smuzhiyun 		if (i < 4)
908*4882a593Smuzhiyun 			user_position_l |= (beamformer_entry->user_position[i] << ((i - 8) << 3));
909*4882a593Smuzhiyun 		else
910*4882a593Smuzhiyun 			user_position_h |= (beamformer_entry->user_position[i] << ((i - 12) << 3));
911*4882a593Smuzhiyun 	}
912*4882a593Smuzhiyun 	/*select MU STA1 table*/
913*4882a593Smuzhiyun 	beamforming_info->reg_mu_tx_ctrl &= ~(BIT(8) | BIT(9) | BIT(10));
914*4882a593Smuzhiyun 	beamforming_info->reg_mu_tx_ctrl |= BIT(8);
915*4882a593Smuzhiyun 	odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
916*4882a593Smuzhiyun 	odm_set_bb_reg(dm, R_0x14c4, MASKDWORD, gid_valid);
917*4882a593Smuzhiyun 	odm_set_bb_reg(dm, R_0x14c8, MASKDWORD, user_position_l);
918*4882a593Smuzhiyun 	odm_set_bb_reg(dm, R_0x14cc, MASKDWORD, user_position_h);
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun 	PHYDM_DBG(dm, DBG_TXBF,
921*4882a593Smuzhiyun 		  "%s: STA1: gid_valid = 0x%x, user_position_l = 0x%x, user_position_h = 0x%x\n",
922*4882a593Smuzhiyun 		  __func__, gid_valid, user_position_l, user_position_h);
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun 	/* Set validity of MU STA0 and MU STA1*/
925*4882a593Smuzhiyun 	beamforming_info->reg_mu_tx_ctrl &= 0xFFFFFFC0;
926*4882a593Smuzhiyun 	beamforming_info->reg_mu_tx_ctrl |= 0x3; /* STA0, STA1*/
927*4882a593Smuzhiyun 	odm_write_4byte(dm, 0x14c0, beamforming_info->reg_mu_tx_ctrl);
928*4882a593Smuzhiyun }
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun #if 0
931*4882a593Smuzhiyun /*This function translate the bitmap to GTAB*/
932*4882a593Smuzhiyun void
933*4882a593Smuzhiyun haltxbf8822b_gtab_translation(
934*4882a593Smuzhiyun 	struct dm_struct			*dm
935*4882a593Smuzhiyun )
936*4882a593Smuzhiyun {
937*4882a593Smuzhiyun 	u8 idx, gid;
938*4882a593Smuzhiyun 	u8 id1, id0;
939*4882a593Smuzhiyun 	u32 gid_valid[6] = {0};
940*4882a593Smuzhiyun 	u32 user_position_lsb[6] = {0};
941*4882a593Smuzhiyun 	u32 user_position_msb[6] = {0};
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun 	for (idx = 0; idx < 15; idx++) {
944*4882a593Smuzhiyun 		if (idx < 5) {/*@bit0~4*/
945*4882a593Smuzhiyun 			id0 = 0;
946*4882a593Smuzhiyun 			id1 = (u8)(idx + 1);
947*4882a593Smuzhiyun 		} else if (idx < 9) { /*@bit5~8*/
948*4882a593Smuzhiyun 			id0 = 1;
949*4882a593Smuzhiyun 			id1 = (u8)(idx - 3);
950*4882a593Smuzhiyun 		} else if (idx < 12) { /*@bit9~11*/
951*4882a593Smuzhiyun 			id0 = 2;
952*4882a593Smuzhiyun 			id1 = (u8)(idx - 6);
953*4882a593Smuzhiyun 		} else if (idx < 14) { /*@bit12~13*/
954*4882a593Smuzhiyun 			id0 = 3;
955*4882a593Smuzhiyun 			id1 = (u8)(idx - 8);
956*4882a593Smuzhiyun 		} else { /*@bit14*/
957*4882a593Smuzhiyun 			id0 = 4;
958*4882a593Smuzhiyun 			id1 = (u8)(idx - 9);
959*4882a593Smuzhiyun 		}
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 		/*Pair 1*/
962*4882a593Smuzhiyun 		gid = (idx << 1) + 1;
963*4882a593Smuzhiyun 		gid_valid[id0] |= (1 << gid);
964*4882a593Smuzhiyun 		gid_valid[id1] |= (1 << gid);
965*4882a593Smuzhiyun 		if (gid < 16) {
966*4882a593Smuzhiyun 			/*user_position_lsb[id0] |= (0 << (gid << 1));*/
967*4882a593Smuzhiyun 			user_position_lsb[id1] |= (1 << (gid << 1));
968*4882a593Smuzhiyun 		} else {
969*4882a593Smuzhiyun 			/*user_position_msb[id0] |= (0 << ((gid - 16) << 1));*/
970*4882a593Smuzhiyun 			user_position_msb[id1] |= (1 << ((gid - 16) << 1));
971*4882a593Smuzhiyun 		}
972*4882a593Smuzhiyun 
973*4882a593Smuzhiyun 		/*Pair 2*/
974*4882a593Smuzhiyun 		gid += 1;
975*4882a593Smuzhiyun 		gid_valid[id0] |= (1 << gid);
976*4882a593Smuzhiyun 		gid_valid[id1] |= (1 << gid);
977*4882a593Smuzhiyun 		if (gid < 16) {
978*4882a593Smuzhiyun 			user_position_lsb[id0] |= (1 << (gid << 1));
979*4882a593Smuzhiyun 			/*user_position_lsb[id1] |= (0 << (gid << 1));*/
980*4882a593Smuzhiyun 		} else {
981*4882a593Smuzhiyun 			user_position_msb[id0] |= (1 << ((gid - 16) << 1));
982*4882a593Smuzhiyun 			/*user_position_msb[id1] |= (0 << ((gid - 16) << 1));*/
983*4882a593Smuzhiyun 		}
984*4882a593Smuzhiyun 	}
985*4882a593Smuzhiyun 
986*4882a593Smuzhiyun 
987*4882a593Smuzhiyun 	for (idx = 0; idx < 6; idx++) {
988*4882a593Smuzhiyun 		/*@dbg_print("gid_valid[%d] = 0x%x\n", idx, gid_valid[idx]);
989*4882a593Smuzhiyun 		dbg_print("user_position[%d] = 0x%x   %x\n", idx, user_position_msb[idx], user_position_lsb[idx]);*/
990*4882a593Smuzhiyun 	}
991*4882a593Smuzhiyun }
992*4882a593Smuzhiyun #endif
993*4882a593Smuzhiyun 
hal_txbf_8822b_fw_txbf(void * dm_void,u8 idx)994*4882a593Smuzhiyun void hal_txbf_8822b_fw_txbf(
995*4882a593Smuzhiyun 	void *dm_void,
996*4882a593Smuzhiyun 	u8 idx)
997*4882a593Smuzhiyun {
998*4882a593Smuzhiyun #if 0
999*4882a593Smuzhiyun 	struct _RT_BEAMFORMING_INFO	*beam_info = GET_BEAMFORM_INFO(adapter);
1000*4882a593Smuzhiyun 	struct _RT_BEAMFORMEE_ENTRY	*p_beam_entry = beam_info->beamformee_entry + idx;
1001*4882a593Smuzhiyun 
1002*4882a593Smuzhiyun 	if (p_beam_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSING)
1003*4882a593Smuzhiyun 		hal_txbf_8822b_download_ndpa(adapter, idx);
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun 	hal_txbf_8822b_fw_txbf_cmd(adapter);
1006*4882a593Smuzhiyun #endif
1007*4882a593Smuzhiyun }
1008*4882a593Smuzhiyun 
1009*4882a593Smuzhiyun #endif
1010*4882a593Smuzhiyun 
1011*4882a593Smuzhiyun #if (defined(CONFIG_BB_TXBF_API))
1012*4882a593Smuzhiyun /*this function is only used for BFer*/
phydm_8822btxbf_rfmode(void * dm_void,u8 su_bfee_cnt,u8 mu_bfee_cnt)1013*4882a593Smuzhiyun void phydm_8822btxbf_rfmode(void *dm_void, u8 su_bfee_cnt, u8 mu_bfee_cnt)
1014*4882a593Smuzhiyun {
1015*4882a593Smuzhiyun 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1016*4882a593Smuzhiyun 	u8 i;
1017*4882a593Smuzhiyun 
1018*4882a593Smuzhiyun 	if (dm->rf_type == RF_1T1R)
1019*4882a593Smuzhiyun 		return;
1020*4882a593Smuzhiyun 
1021*4882a593Smuzhiyun 	if (su_bfee_cnt > 0 || mu_bfee_cnt > 0) {
1022*4882a593Smuzhiyun 		for (i = RF_PATH_A; i <= RF_PATH_B; i++) {
1023*4882a593Smuzhiyun 			odm_set_rf_reg(dm, (enum rf_path)i, RF_0xef, BIT(19), 0x1); /*RF mode table write enable*/
1024*4882a593Smuzhiyun 			odm_set_rf_reg(dm, (enum rf_path)i, RF_0x33, 0xF, 3); /*Select RX mode*/
1025*4882a593Smuzhiyun 			odm_set_rf_reg(dm, (enum rf_path)i, RF_0x3e, 0xfffff, 0x00036); /*Set Table data*/
1026*4882a593Smuzhiyun 			odm_set_rf_reg(dm, (enum rf_path)i, RF_0x3f, 0xfffff, 0x5AFCE); /*Set Table data*/
1027*4882a593Smuzhiyun 			odm_set_rf_reg(dm, (enum rf_path)i, RF_0xef, BIT(19), 0x0); /*RF mode table write disable*/
1028*4882a593Smuzhiyun 		}
1029*4882a593Smuzhiyun 	}
1030*4882a593Smuzhiyun 
1031*4882a593Smuzhiyun 	odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(30), 1); /*@if Nsts > Nc, don't apply V matrix*/
1032*4882a593Smuzhiyun 
1033*4882a593Smuzhiyun 	if (su_bfee_cnt > 0 || mu_bfee_cnt > 0) {
1034*4882a593Smuzhiyun 		/*@for 8814 19ac(idx 1), 19b4(idx 0), different Tx ant setting*/
1035*4882a593Smuzhiyun 		odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(28) | BIT29, 0x2); /*@enable BB TxBF ant mapping register*/
1036*4882a593Smuzhiyun 		odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(31), 1); /*@ignore user since 8822B only 2Tx*/
1037*4882a593Smuzhiyun 
1038*4882a593Smuzhiyun 		/*Nsts = 2	AB*/
1039*4882a593Smuzhiyun 		odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, 0xffff, 0x0433);
1040*4882a593Smuzhiyun 		odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x043);
1041*4882a593Smuzhiyun 
1042*4882a593Smuzhiyun 	} else {
1043*4882a593Smuzhiyun 		odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(28) | BIT29, 0x0); /*@enable BB TxBF ant mapping register*/
1044*4882a593Smuzhiyun 		odm_set_bb_reg(dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(31), 0); /*@ignore user since 8822B only 2Tx*/
1045*4882a593Smuzhiyun 
1046*4882a593Smuzhiyun 		odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x1); /*@1SS by path-A*/
1047*4882a593Smuzhiyun 		odm_set_bb_reg(dm, REG_BB_TX_PATH_SEL_2_8822B, MASKLWORD, 0x430); /*@2SS by path-A,B*/
1048*4882a593Smuzhiyun 	}
1049*4882a593Smuzhiyun }
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun /*this function is for BFer bug workaround*/
phydm_8822b_sutxbfer_workaroud(void * dm_void,boolean enable_su_bfer,u8 nc,u8 nr,u8 ng,u8 CB,u8 BW,boolean is_vht)1052*4882a593Smuzhiyun void phydm_8822b_sutxbfer_workaroud(void *dm_void, boolean enable_su_bfer,
1053*4882a593Smuzhiyun 				    u8 nc, u8 nr, u8 ng, u8 CB, u8 BW,
1054*4882a593Smuzhiyun 				    boolean is_vht)
1055*4882a593Smuzhiyun {
1056*4882a593Smuzhiyun 	struct dm_struct *dm = (struct dm_struct *)dm_void;
1057*4882a593Smuzhiyun 
1058*4882a593Smuzhiyun 	if (enable_su_bfer) {
1059*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0x19f8, BIT(22) | BIT(21) | BIT(20), 0x1);
1060*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0x19f8, BIT(25) | BIT(24) | BIT(23), 0x0);
1061*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0x19f8, BIT(16), 0x1);
1062*4882a593Smuzhiyun 
1063*4882a593Smuzhiyun 		if (is_vht)
1064*4882a593Smuzhiyun 			odm_set_bb_reg(dm, R_0x19f0, BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0), 0x1f);
1065*4882a593Smuzhiyun 		else
1066*4882a593Smuzhiyun 			odm_set_bb_reg(dm, R_0x19f0, BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0), 0x22);
1067*4882a593Smuzhiyun 
1068*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0x19f0, BIT(7) | BIT(6), nc);
1069*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0x19f0, BIT(9) | BIT(8), nr);
1070*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0x19f0, BIT(11) | BIT(10), ng);
1071*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0x19f0, BIT(13) | BIT(12), CB);
1072*4882a593Smuzhiyun 
1073*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0xb58, BIT(3) | BIT(2), BW);
1074*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0xb58, BIT(7) | BIT(6) | BIT(5) | BIT(4), 0x0);
1075*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0xb58, BIT(9) | BIT(8), BW);
1076*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0xb58, BIT(13) | BIT(12) | BIT(11) | BIT(10), 0x0);
1077*4882a593Smuzhiyun 	} else {
1078*4882a593Smuzhiyun 		odm_set_bb_reg(dm, R_0x19f8, BIT(16), 0x0);
1079*4882a593Smuzhiyun 	}
1080*4882a593Smuzhiyun 
1081*4882a593Smuzhiyun 	PHYDM_DBG(dm, DBG_TXBF, "[%s] enable_su_bfer = %d, is_vht = %d\n",
1082*4882a593Smuzhiyun 		  __func__, enable_su_bfer, is_vht);
1083*4882a593Smuzhiyun 	PHYDM_DBG(dm, DBG_TXBF,
1084*4882a593Smuzhiyun 		  "[%s] nc = %d, nr = %d, ng = %d, CB = %d, BW = %d\n",
1085*4882a593Smuzhiyun 		  __func__, nc, nr, ng, CB, BW);
1086*4882a593Smuzhiyun }
1087*4882a593Smuzhiyun #endif
1088*4882a593Smuzhiyun #endif /* @(RTL8822B_SUPPORT == 1)*/
1089