These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / staging / rtl8188eu / hal / odm_RTL8188E.c
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
21 #include "odm_precomp.h"
22 #include "phy.h"
23
24 static void dm_rx_hw_antena_div_init(struct odm_dm_struct *dm_odm)
25 {
26         struct adapter *adapter = dm_odm->Adapter;
27         u32 value32;
28
29         if (*(dm_odm->mp_mode) == 1) {
30                 dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
31                 phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
32                 phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
33                 return;
34         }
35
36         /* MAC Setting */
37         value32 = phy_query_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
38         phy_set_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord,
39                        value32|(BIT(23) | BIT(25)));
40         /* Pin Settings */
41         phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
42         phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
43         phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 1);
44         phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
45         /* OFDM Settings */
46         phy_set_bb_reg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord,
47                        0x000000a0);
48         /* CCK Settings */
49         phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
50         phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
51         rtl88eu_dm_update_rx_idle_ant(dm_odm, MAIN_ANT);
52         phy_set_bb_reg(adapter, ODM_REG_ANT_MAPPING1_11N, 0xFFFF, 0x0201);
53 }
54
55 static void dm_trx_hw_antenna_div_init(struct odm_dm_struct *dm_odm)
56 {
57         struct adapter *adapter = dm_odm->Adapter;
58         u32     value32;
59
60         if (*(dm_odm->mp_mode) == 1) {
61                 dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
62                 phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
63                 phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
64                                BIT(5) | BIT(4) | BIT(3), 0);
65                 return;
66         }
67
68         /* MAC Setting */
69         value32 = phy_query_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
70         phy_set_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord,
71                        value32|(BIT(23) | BIT(25)));
72         /* Pin Settings */
73         phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
74         phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
75         phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 0);
76         phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
77         /* OFDM Settings */
78         phy_set_bb_reg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord,
79                        0x000000a0);
80         /* CCK Settings */
81         phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
82         phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
83         /* Tx Settings */
84         phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N, BIT(21), 0);
85         rtl88eu_dm_update_rx_idle_ant(dm_odm, MAIN_ANT);
86
87         /* antenna mapping table */
88         if (!dm_odm->bIsMPChip) { /* testchip */
89                 phy_set_bb_reg(adapter, ODM_REG_RX_DEFUALT_A_11N,
90                                BIT(10) | BIT(9) | BIT(8), 1);
91                 phy_set_bb_reg(adapter, ODM_REG_RX_DEFUALT_A_11N,
92                                BIT(13) | BIT(12) | BIT(11), 2);
93         } else { /* MPchip */
94                 phy_set_bb_reg(adapter, ODM_REG_ANT_MAPPING1_11N, bMaskDWord,
95                                0x0201);
96         }
97 }
98
99 static void dm_fast_training_init(struct odm_dm_struct *dm_odm)
100 {
101         struct adapter *adapter = dm_odm->Adapter;
102         u32 value32, i;
103         struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
104         u32 AntCombination = 2;
105
106         if (*(dm_odm->mp_mode) == 1) {
107                 return;
108         }
109
110         for (i = 0; i < 6; i++) {
111                 dm_fat_tbl->Bssid[i] = 0;
112                 dm_fat_tbl->antSumRSSI[i] = 0;
113                 dm_fat_tbl->antRSSIcnt[i] = 0;
114                 dm_fat_tbl->antAveRSSI[i] = 0;
115         }
116         dm_fat_tbl->TrainIdx = 0;
117         dm_fat_tbl->FAT_State = FAT_NORMAL_STATE;
118
119         /* MAC Setting */
120         value32 = phy_query_bb_reg(adapter, 0x4c, bMaskDWord);
121         phy_set_bb_reg(adapter, 0x4c, bMaskDWord, value32|(BIT(23) | BIT(25)));
122         value32 = phy_query_bb_reg(adapter,  0x7B4, bMaskDWord);
123         phy_set_bb_reg(adapter, 0x7b4, bMaskDWord, value32|(BIT(16) | BIT(17)));
124
125         /* Match MAC ADDR */
126         phy_set_bb_reg(adapter, 0x7b4, 0xFFFF, 0);
127         phy_set_bb_reg(adapter, 0x7b0, bMaskDWord, 0);
128
129         phy_set_bb_reg(adapter, 0x870, BIT(9) | BIT(8), 0);
130         phy_set_bb_reg(adapter, 0x864, BIT(10), 0);
131         phy_set_bb_reg(adapter, 0xb2c, BIT(22), 0);
132         phy_set_bb_reg(adapter, 0xb2c, BIT(31), 1);
133         phy_set_bb_reg(adapter, 0xca4, bMaskDWord, 0x000000a0);
134
135         /* antenna mapping table */
136         if (AntCombination == 2) {
137                 if (!dm_odm->bIsMPChip) { /* testchip */
138                         phy_set_bb_reg(adapter, 0x858, BIT(10) | BIT(9) | BIT(8), 1);
139                         phy_set_bb_reg(adapter, 0x858, BIT(13) | BIT(12) | BIT(11), 2);
140                 } else { /* MPchip */
141                         phy_set_bb_reg(adapter, 0x914, bMaskByte0, 1);
142                         phy_set_bb_reg(adapter, 0x914, bMaskByte1, 2);
143                 }
144         } else if (AntCombination == 7) {
145                 if (!dm_odm->bIsMPChip) { /* testchip */
146                         phy_set_bb_reg(adapter, 0x858, BIT(10) | BIT(9) | BIT(8), 0);
147                         phy_set_bb_reg(adapter, 0x858, BIT(13) | BIT(12) | BIT(11), 1);
148                         phy_set_bb_reg(adapter, 0x878, BIT(16), 0);
149                         phy_set_bb_reg(adapter, 0x858, BIT(15) | BIT(14), 2);
150                         phy_set_bb_reg(adapter, 0x878, BIT(19) | BIT(18) | BIT(17), 3);
151                         phy_set_bb_reg(adapter, 0x878, BIT(22) | BIT(21) | BIT(20), 4);
152                         phy_set_bb_reg(adapter, 0x878, BIT(25) | BIT(24) | BIT(23), 5);
153                         phy_set_bb_reg(adapter, 0x878, BIT(28) | BIT(27) | BIT(26), 6);
154                         phy_set_bb_reg(adapter, 0x878, BIT(31) | BIT(30) | BIT(29), 7);
155                 } else { /* MPchip */
156                         phy_set_bb_reg(adapter, 0x914, bMaskByte0, 0);
157                         phy_set_bb_reg(adapter, 0x914, bMaskByte1, 1);
158                         phy_set_bb_reg(adapter, 0x914, bMaskByte2, 2);
159                         phy_set_bb_reg(adapter, 0x914, bMaskByte3, 3);
160                         phy_set_bb_reg(adapter, 0x918, bMaskByte0, 4);
161                         phy_set_bb_reg(adapter, 0x918, bMaskByte1, 5);
162                         phy_set_bb_reg(adapter, 0x918, bMaskByte2, 6);
163                         phy_set_bb_reg(adapter, 0x918, bMaskByte3, 7);
164                 }
165         }
166
167         /* Default Ant Setting when no fast training */
168         phy_set_bb_reg(adapter, 0x80c, BIT(21), 1);
169         phy_set_bb_reg(adapter, 0x864, BIT(5) | BIT(4) | BIT(3), 0);
170         phy_set_bb_reg(adapter, 0x864, BIT(8) | BIT(7) | BIT(6), 1);
171
172         /* Enter Traing state */
173         phy_set_bb_reg(adapter, 0x864, BIT(2) | BIT(1) | BIT(0), (AntCombination-1));
174         phy_set_bb_reg(adapter, 0xc50, BIT(7), 1);
175 }
176
177 void rtl88eu_dm_antenna_div_init(struct odm_dm_struct *dm_odm)
178 {
179         if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)
180                 dm_rx_hw_antena_div_init(dm_odm);
181         else if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
182                 dm_trx_hw_antenna_div_init(dm_odm);
183         else if (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)
184                 dm_fast_training_init(dm_odm);
185 }
186
187 void rtl88eu_dm_update_rx_idle_ant(struct odm_dm_struct *dm_odm, u8 ant)
188 {
189         struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
190         struct adapter *adapter = dm_odm->Adapter;
191         u32 default_ant, optional_ant;
192
193         if (dm_fat_tbl->RxIdleAnt != ant) {
194                 if (ant == MAIN_ANT) {
195                         default_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
196                                        MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
197                         optional_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
198                                         AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
199                 } else {
200                         default_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
201                                        AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
202                         optional_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
203                                         MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
204                 }
205
206                 if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
207                         phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
208                                        BIT(5) | BIT(4) | BIT(3), default_ant);
209                         phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
210                                        BIT(8) | BIT(7) | BIT(6), optional_ant);
211                         phy_set_bb_reg(adapter, ODM_REG_ANTSEL_CTRL_11N,
212                                        BIT(14) | BIT(13) | BIT(12), default_ant);
213                         phy_set_bb_reg(adapter, ODM_REG_RESP_TX_11N,
214                                        BIT(6) | BIT(7), default_ant);
215                 } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
216                         phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
217                                        BIT(5) | BIT(4) | BIT(3), default_ant);
218                         phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
219                                        BIT(8) | BIT(7) | BIT(6), optional_ant);
220                 }
221         }
222         dm_fat_tbl->RxIdleAnt = ant;
223 }
224
225 static void update_tx_ant_88eu(struct odm_dm_struct *dm_odm, u8 ant, u32 mac_id)
226 {
227         struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
228         u8 target_ant;
229
230         if (ant == MAIN_ANT)
231                 target_ant = MAIN_ANT_CG_TRX;
232         else
233                 target_ant = AUX_ANT_CG_TRX;
234         dm_fat_tbl->antsel_a[mac_id] = target_ant & BIT(0);
235         dm_fat_tbl->antsel_b[mac_id] = (target_ant & BIT(1))>>1;
236         dm_fat_tbl->antsel_c[mac_id] = (target_ant & BIT(2))>>2;
237 }
238
239 void rtl88eu_dm_set_tx_ant_by_tx_info(struct odm_dm_struct *dm_odm,
240                                       u8 *desc, u8 mac_id)
241 {
242         struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
243
244         if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ||
245             (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)) {
246                 SET_TX_DESC_ANTSEL_A_88E(desc, dm_fat_tbl->antsel_a[mac_id]);
247                 SET_TX_DESC_ANTSEL_B_88E(desc, dm_fat_tbl->antsel_b[mac_id]);
248                 SET_TX_DESC_ANTSEL_C_88E(desc, dm_fat_tbl->antsel_c[mac_id]);
249         }
250 }
251
252 void rtl88eu_dm_ant_sel_statistics(struct odm_dm_struct *dm_odm,
253                                    u8 antsel_tr_mux, u32 mac_id, u8 rx_pwdb_all)
254 {
255         struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
256         if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
257                 if (antsel_tr_mux == MAIN_ANT_CG_TRX) {
258                         dm_fat_tbl->MainAnt_Sum[mac_id] += rx_pwdb_all;
259                         dm_fat_tbl->MainAnt_Cnt[mac_id]++;
260                 } else {
261                         dm_fat_tbl->AuxAnt_Sum[mac_id] += rx_pwdb_all;
262                         dm_fat_tbl->AuxAnt_Cnt[mac_id]++;
263                 }
264         } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
265                 if (antsel_tr_mux == MAIN_ANT_CGCS_RX) {
266                         dm_fat_tbl->MainAnt_Sum[mac_id] += rx_pwdb_all;
267                         dm_fat_tbl->MainAnt_Cnt[mac_id]++;
268                 } else {
269                         dm_fat_tbl->AuxAnt_Sum[mac_id] += rx_pwdb_all;
270                         dm_fat_tbl->AuxAnt_Cnt[mac_id]++;
271                 }
272         }
273 }
274
275 static void rtl88eu_dm_hw_ant_div(struct odm_dm_struct *dm_odm)
276 {
277         struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
278         struct rtw_dig *dig_table = &dm_odm->DM_DigTable;
279         struct sta_info *entry;
280         u32 i, min_rssi = 0xFF, ant_div_max_rssi = 0, max_rssi = 0;
281         u32 local_min_rssi, local_max_rssi;
282         u32 main_rssi, aux_rssi;
283         u8 RxIdleAnt = 0, target_ant = 7;
284
285         for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
286                 entry = dm_odm->pODM_StaInfo[i];
287                 if (IS_STA_VALID(entry)) {
288                         /* 2 Caculate RSSI per Antenna */
289                         main_rssi = (dm_fat_tbl->MainAnt_Cnt[i] != 0) ?
290                                      (dm_fat_tbl->MainAnt_Sum[i]/dm_fat_tbl->MainAnt_Cnt[i]) : 0;
291                         aux_rssi = (dm_fat_tbl->AuxAnt_Cnt[i] != 0) ?
292                                     (dm_fat_tbl->AuxAnt_Sum[i]/dm_fat_tbl->AuxAnt_Cnt[i]) : 0;
293                         target_ant = (main_rssi >= aux_rssi) ? MAIN_ANT : AUX_ANT;
294                         /* 2 Select max_rssi for DIG */
295                         local_max_rssi = max(main_rssi, aux_rssi);
296                         if ((local_max_rssi > ant_div_max_rssi) &&
297                             (local_max_rssi < 40))
298                                 ant_div_max_rssi = local_max_rssi;
299                         if (local_max_rssi > max_rssi)
300                                 max_rssi = local_max_rssi;
301
302                         /* 2 Select RX Idle Antenna */
303                         if ((dm_fat_tbl->RxIdleAnt == MAIN_ANT) &&
304                             (main_rssi == 0))
305                                 main_rssi = aux_rssi;
306                         else if ((dm_fat_tbl->RxIdleAnt == AUX_ANT) &&
307                                  (aux_rssi == 0))
308                                 aux_rssi = main_rssi;
309
310                         local_min_rssi = min(main_rssi, aux_rssi);
311                         if (local_min_rssi < min_rssi) {
312                                 min_rssi = local_min_rssi;
313                                 RxIdleAnt = target_ant;
314                         }
315                         /* 2 Select TRX Antenna */
316                         if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
317                                 update_tx_ant_88eu(dm_odm, target_ant, i);
318                 }
319                 dm_fat_tbl->MainAnt_Sum[i] = 0;
320                 dm_fat_tbl->AuxAnt_Sum[i] = 0;
321                 dm_fat_tbl->MainAnt_Cnt[i] = 0;
322                 dm_fat_tbl->AuxAnt_Cnt[i] = 0;
323         }
324
325         /* 2 Set RX Idle Antenna */
326         rtl88eu_dm_update_rx_idle_ant(dm_odm, RxIdleAnt);
327
328         dig_table->AntDiv_RSSI_max = ant_div_max_rssi;
329         dig_table->RSSI_max = max_rssi;
330 }
331
332 void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm)
333 {
334         struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
335         struct adapter *adapter = dm_odm->Adapter;
336
337         if (!(dm_odm->SupportAbility & ODM_BB_ANT_DIV))
338                 return;
339         if (!dm_odm->bLinked) {
340                 ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
341                              ("ODM_AntennaDiversity_88E(): No Link.\n"));
342                 if (dm_fat_tbl->bBecomeLinked) {
343                         ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
344                                      ("Need to Turn off HW AntDiv\n"));
345                         phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
346                         phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
347                                        BIT(15), 0);
348                         if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
349                                 phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
350                                                BIT(21), 0);
351                         dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
352                 }
353                 return;
354         } else {
355                 if (!dm_fat_tbl->bBecomeLinked) {
356                         ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
357                                      ("Need to Turn on HW AntDiv\n"));
358                         phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 1);
359                         phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
360                                        BIT(15), 1);
361                         if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
362                                 phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
363                                                BIT(21), 1);
364                         dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
365                 }
366         }
367         if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ||
368             (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV))
369                 rtl88eu_dm_hw_ant_div(dm_odm);
370 }