GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / staging / rtlwifi / phydm / phydm_kfree.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2016  Realtek Corporation.
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  * The full GNU General Public License is included in this distribution in the
15  * file called LICENSE.
16  *
17  * Contact Information:
18  * wlanfae <wlanfae@realtek.com>
19  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20  * Hsinchu 300, Taiwan.
21  *
22  * Larry Finger <Larry.Finger@lwfinger.net>
23  *
24  *****************************************************************************/
25
26 /*============================================================*/
27 /*include files*/
28 /*============================================================*/
29 #include "mp_precomp.h"
30 #include "phydm_precomp.h"
31
32 /*<YuChen, 150720> Add for KFree Feature Requested by RF David.*/
33 /*This is a phydm API*/
34
35 static void phydm_set_kfree_to_rf_8814a(void *dm_void, u8 e_rf_path, u8 data)
36 {
37         struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
38         struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
39         bool is_odd;
40
41         if ((data % 2) != 0) { /*odd->positive*/
42                 data = data - 1;
43                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(19),
44                                1);
45                 is_odd = true;
46         } else { /*even->negative*/
47                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(19),
48                                0);
49                 is_odd = false;
50         }
51         ODM_RT_TRACE(dm, ODM_COMP_MP, "%s(): RF_0x55[19]= %d\n", __func__,
52                      is_odd);
53         switch (data) {
54         case 0:
55                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14),
56                                0);
57                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET,
58                                BIT(17) | BIT(16) | BIT(15), 0);
59                 cali_info->kfree_offset[e_rf_path] = 0;
60                 break;
61         case 2:
62                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14),
63                                1);
64                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET,
65                                BIT(17) | BIT(16) | BIT(15), 0);
66                 cali_info->kfree_offset[e_rf_path] = 0;
67                 break;
68         case 4:
69                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14),
70                                0);
71                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET,
72                                BIT(17) | BIT(16) | BIT(15), 1);
73                 cali_info->kfree_offset[e_rf_path] = 1;
74                 break;
75         case 6:
76                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14),
77                                1);
78                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET,
79                                BIT(17) | BIT(16) | BIT(15), 1);
80                 cali_info->kfree_offset[e_rf_path] = 1;
81                 break;
82         case 8:
83                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14),
84                                0);
85                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET,
86                                BIT(17) | BIT(16) | BIT(15), 2);
87                 cali_info->kfree_offset[e_rf_path] = 2;
88                 break;
89         case 10:
90                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14),
91                                1);
92                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET,
93                                BIT(17) | BIT(16) | BIT(15), 2);
94                 cali_info->kfree_offset[e_rf_path] = 2;
95                 break;
96         case 12:
97                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14),
98                                0);
99                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET,
100                                BIT(17) | BIT(16) | BIT(15), 3);
101                 cali_info->kfree_offset[e_rf_path] = 3;
102                 break;
103         case 14:
104                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14),
105                                1);
106                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET,
107                                BIT(17) | BIT(16) | BIT(15), 3);
108                 cali_info->kfree_offset[e_rf_path] = 3;
109                 break;
110         case 16:
111                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14),
112                                0);
113                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET,
114                                BIT(17) | BIT(16) | BIT(15), 4);
115                 cali_info->kfree_offset[e_rf_path] = 4;
116                 break;
117         case 18:
118                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14),
119                                1);
120                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET,
121                                BIT(17) | BIT(16) | BIT(15), 4);
122                 cali_info->kfree_offset[e_rf_path] = 4;
123                 break;
124         case 20:
125                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET, BIT(14),
126                                0);
127                 odm_set_rf_reg(dm, e_rf_path, REG_RF_TX_GAIN_OFFSET,
128                                BIT(17) | BIT(16) | BIT(15), 5);
129                 cali_info->kfree_offset[e_rf_path] = 5;
130                 break;
131
132         default:
133                 break;
134         }
135
136         if (!is_odd) {
137                 /*that means Kfree offset is negative, we need to record it.*/
138                 cali_info->kfree_offset[e_rf_path] =
139                         (-1) * cali_info->kfree_offset[e_rf_path];
140                 ODM_RT_TRACE(dm, ODM_COMP_MP, "%s(): kfree_offset = %d\n",
141                              __func__, cali_info->kfree_offset[e_rf_path]);
142         } else {
143                 ODM_RT_TRACE(dm, ODM_COMP_MP, "%s(): kfree_offset = %d\n",
144                              __func__, cali_info->kfree_offset[e_rf_path]);
145         }
146 }
147
148 static void phydm_set_kfree_to_rf(void *dm_void, u8 e_rf_path, u8 data)
149 {
150         struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
151
152         if (dm->support_ic_type & ODM_RTL8814A)
153                 phydm_set_kfree_to_rf_8814a(dm, e_rf_path, data);
154 }
155
156 void phydm_config_kfree(void *dm_void, u8 channel_to_sw, u8 *kfree_table)
157 {
158         struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void;
159         struct dm_rf_calibration_struct *cali_info = &dm->rf_calibrate_info;
160         u8 rfpath = 0, max_rf_path = 0;
161         u8 channel_idx = 0;
162
163         if (dm->support_ic_type & ODM_RTL8814A)
164                 max_rf_path = 4; /*0~3*/
165         else if (dm->support_ic_type &
166                  (ODM_RTL8812 | ODM_RTL8192E | ODM_RTL8822B))
167                 max_rf_path = 2; /*0~1*/
168         else
169                 max_rf_path = 1;
170
171         ODM_RT_TRACE(dm, ODM_COMP_MP, "===>%s()\n", __func__);
172
173         if (cali_info->reg_rf_kfree_enable == 2) {
174                 ODM_RT_TRACE(dm, ODM_COMP_MP,
175                              "%s(): reg_rf_kfree_enable == 2, Disable\n",
176                              __func__);
177                 return;
178         }
179
180         if (cali_info->reg_rf_kfree_enable != 1 &&
181             cali_info->reg_rf_kfree_enable != 0) {
182                 ODM_RT_TRACE(dm, ODM_COMP_MP, "<===%s()\n", __func__);
183                 return;
184         }
185
186         ODM_RT_TRACE(dm, ODM_COMP_MP, "%s(): reg_rf_kfree_enable == true\n",
187                      __func__);
188         /*Make sure the targetval is defined*/
189         if (((cali_info->reg_rf_kfree_enable == 1) &&
190              (kfree_table[0] != 0xFF)) ||
191             cali_info->rf_kfree_enable) {
192                 /*if kfree_table[0] == 0xff, means no Kfree*/
193                 if (*dm->band_type == ODM_BAND_2_4G) {
194                         if (channel_to_sw <= 14 && channel_to_sw >= 1)
195                                 channel_idx = PHYDM_2G;
196                 } else if (*dm->band_type == ODM_BAND_5G) {
197                         if (channel_to_sw >= 36 && channel_to_sw <= 48)
198                                 channel_idx = PHYDM_5GLB1;
199                         if (channel_to_sw >= 52 && channel_to_sw <= 64)
200                                 channel_idx = PHYDM_5GLB2;
201                         if (channel_to_sw >= 100 && channel_to_sw <= 120)
202                                 channel_idx = PHYDM_5GMB1;
203                         if (channel_to_sw >= 124 && channel_to_sw <= 144)
204                                 channel_idx = PHYDM_5GMB2;
205                         if (channel_to_sw >= 149 && channel_to_sw <= 177)
206                                 channel_idx = PHYDM_5GHB;
207                 }
208
209                 for (rfpath = ODM_RF_PATH_A; rfpath < max_rf_path; rfpath++) {
210                         ODM_RT_TRACE(dm, ODM_COMP_MP, "%s(): PATH_%d: %#x\n",
211                                      __func__, rfpath,
212                                      kfree_table[channel_idx * max_rf_path +
213                                                  rfpath]);
214                         phydm_set_kfree_to_rf(
215                                 dm, rfpath,
216                                 kfree_table[channel_idx * max_rf_path +
217                                             rfpath]);
218                 }
219         } else {
220                 ODM_RT_TRACE(
221                         dm, ODM_COMP_MP,
222                         "%s(): targetval not defined, Don't execute KFree Process.\n",
223                         __func__);
224                 return;
225         }
226
227         ODM_RT_TRACE(dm, ODM_COMP_MP, "<===%s()\n", __func__);
228 }