Add the rt linux 4.1.3-rt3 as base
[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, BIT7, 0);
32                 phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT31, 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|(BIT23|BIT25));
40         /* Pin Settings */
41         phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT9|BIT8, 0);
42         phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT10, 0);
43         phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT22, 1);
44         phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT31, 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, BIT7, 1);
50         phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT4, 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, BIT7, 0);
63                 phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
64                                BIT5|BIT4|BIT3, 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|(BIT23|BIT25));
72         /* Pin Settings */
73         phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT9|BIT8, 0);
74         phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT10, 0);
75         phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT22, 0);
76         phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT31, 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, BIT7, 1);
82         phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT4, 1);
83         /* Tx Settings */
84         phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N, BIT21, 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                                BIT10|BIT9|BIT8, 1);
91                 phy_set_bb_reg(adapter, ODM_REG_RX_DEFUALT_A_11N,
92                                BIT13|BIT12|BIT11, 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|(BIT23|BIT25));
122         value32 = phy_query_bb_reg(adapter,  0x7B4, bMaskDWord);
123         phy_set_bb_reg(adapter, 0x7b4, bMaskDWord, value32|(BIT16|BIT17));
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, BIT9|BIT8, 0);
130         phy_set_bb_reg(adapter, 0x864, BIT10, 0);
131         phy_set_bb_reg(adapter, 0xb2c, BIT22, 0);
132         phy_set_bb_reg(adapter, 0xb2c, BIT31, 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, BIT10|BIT9|BIT8, 1);
139                         phy_set_bb_reg(adapter, 0x858, BIT13|BIT12|BIT11, 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, BIT10|BIT9|BIT8, 0);
147                         phy_set_bb_reg(adapter, 0x858, BIT13|BIT12|BIT11, 1);
148                         phy_set_bb_reg(adapter, 0x878, BIT16, 0);
149                         phy_set_bb_reg(adapter, 0x858, BIT15|BIT14, 2);
150                         phy_set_bb_reg(adapter, 0x878, BIT19|BIT18|BIT17, 3);
151                         phy_set_bb_reg(adapter, 0x878, BIT22|BIT21|BIT20, 4);
152                         phy_set_bb_reg(adapter, 0x878, BIT25|BIT24|BIT23, 5);
153                         phy_set_bb_reg(adapter, 0x878, BIT28|BIT27|BIT26, 6);
154                         phy_set_bb_reg(adapter, 0x878, BIT31|BIT30|BIT29, 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, BIT21, 1);
169         phy_set_bb_reg(adapter, 0x864, BIT5|BIT4|BIT3, 0);
170         phy_set_bb_reg(adapter, 0x864, BIT8|BIT7|BIT6, 1);
171
172         /* Enter Traing state */
173         phy_set_bb_reg(adapter, 0x864, BIT2|BIT1|BIT0, (AntCombination-1));
174         phy_set_bb_reg(adapter, 0xc50, BIT7, 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                                        BIT5|BIT4|BIT3, default_ant);
209                         phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
210                                        BIT8|BIT7|BIT6, optional_ant);
211                         phy_set_bb_reg(adapter, ODM_REG_ANTSEL_CTRL_11N,
212                                        BIT14|BIT13|BIT12, default_ant);
213                         phy_set_bb_reg(adapter, ODM_REG_RESP_TX_11N,
214                                        BIT6|BIT7, 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                                        BIT5|BIT4|BIT3, default_ant);
218                         phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
219                                        BIT8|BIT7|BIT6, 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&BIT0;
235         dm_fat_tbl->antsel_b[mac_id] = (target_ant&BIT1)>>1;
236         dm_fat_tbl->antsel_c[mac_id] = (target_ant&BIT2)>>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 = (main_rssi > aux_rssi) ?
296                                           main_rssi : aux_rssi;
297                         if ((local_max_rssi > ant_div_max_rssi) &&
298                             (local_max_rssi < 40))
299                                 ant_div_max_rssi = local_max_rssi;
300                         if (local_max_rssi > max_rssi)
301                                 max_rssi = local_max_rssi;
302
303                         /* 2 Select RX Idle Antenna */
304                         if ((dm_fat_tbl->RxIdleAnt == MAIN_ANT) &&
305                             (main_rssi == 0))
306                                 main_rssi = aux_rssi;
307                         else if ((dm_fat_tbl->RxIdleAnt == AUX_ANT) &&
308                                  (aux_rssi == 0))
309                                 aux_rssi = main_rssi;
310
311                         local_min_rssi = (main_rssi > aux_rssi) ?
312                                           aux_rssi : main_rssi;
313                         if (local_min_rssi < min_rssi) {
314                                 min_rssi = local_min_rssi;
315                                 RxIdleAnt = target_ant;
316                         }
317                         /* 2 Select TRX Antenna */
318                         if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
319                                 update_tx_ant_88eu(dm_odm, target_ant, i);
320                 }
321                 dm_fat_tbl->MainAnt_Sum[i] = 0;
322                 dm_fat_tbl->AuxAnt_Sum[i] = 0;
323                 dm_fat_tbl->MainAnt_Cnt[i] = 0;
324                 dm_fat_tbl->AuxAnt_Cnt[i] = 0;
325         }
326
327         /* 2 Set RX Idle Antenna */
328         rtl88eu_dm_update_rx_idle_ant(dm_odm, RxIdleAnt);
329
330         dig_table->AntDiv_RSSI_max = ant_div_max_rssi;
331         dig_table->RSSI_max = max_rssi;
332 }
333
334 void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm)
335 {
336         struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
337         struct adapter *adapter = dm_odm->Adapter;
338
339         if (!(dm_odm->SupportAbility & ODM_BB_ANT_DIV))
340                 return;
341         if (!dm_odm->bLinked) {
342                 ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
343                              ("ODM_AntennaDiversity_88E(): No Link.\n"));
344                 if (dm_fat_tbl->bBecomeLinked) {
345                         ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
346                                      ("Need to Turn off HW AntDiv\n"));
347                         phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT7, 0);
348                         phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
349                                        BIT15, 0);
350                         if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
351                                 phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
352                                                BIT21, 0);
353                         dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
354                 }
355                 return;
356         } else {
357                 if (!dm_fat_tbl->bBecomeLinked) {
358                         ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
359                                      ("Need to Turn on HW AntDiv\n"));
360                         phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT7, 1);
361                         phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
362                                        BIT15, 1);
363                         if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
364                                 phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
365                                                BIT21, 1);
366                         dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
367                 }
368         }
369         if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ||
370             (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV))
371                 rtl88eu_dm_hw_ant_div(dm_odm);
372 }