OSDN Git Service

Add rtl8821ce driver version 5.5.2
[android-x86/external-kernel-drivers.git] / rtl8821ce / hal / phydm / halrf / halrf_psd.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2017 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  *****************************************************************************/
15
16 /*============================================================
17  * include files
18  *============================================================
19  */
20 #include "mp_precomp.h"
21 #include "phydm_precomp.h"
22
23 #if (DM_ODM_SUPPORT_TYPE & ODM_WIN)
24
25 #if 0
26 u32 _sqrt(u64 n)
27 {
28         u64     ans = 0, q = 0;
29         s64     i;
30
31         /*for (i = sizeof(n) * 8 - 2; i > -1; i = i - 2) {*/
32         for (i = 8 * 8 - 2; i > -1; i = i - 2) {
33                 q = (q << 2) | ((n & (3 << i)) >> i);
34                 if (q >= ((ans << 2) | 1))
35                 {
36                         q = q - ((ans << 2) | 1);
37                         ans = (ans << 1) | 1;
38                 }
39                 else
40                         ans = ans << 1;
41         }
42         DbgPrint("ans=0x%x\n", ans);
43
44         return (u32)ans;
45 }
46 #endif
47
48 u64 _sqrt(u64 x)
49 {
50         u64 i = 0;
51         u64 j = x / 2 + 1;
52
53         while (i <= j) {
54                 u64 mid = (i + j) / 2;
55
56                 u64 sq = mid * mid;
57
58                 if (sq == x)
59                         return mid;
60                 else if (sq < x)
61                         i = mid + 1;
62                 else
63                         j = mid - 1;
64         }
65
66         return j;
67 }
68
69 u32 halrf_get_psd_data(
70         struct dm_struct *dm,
71         u32 point)
72 {
73         struct _hal_rf_ *rf = &(dm->rf_table);
74         struct _halrf_psd_data *psd = &(rf->halrf_psd_data);
75         u32 psd_val = 0, psd_reg, psd_report, psd_point, psd_start, i, delay_time;
76
77 #if (DEV_BUS_TYPE == RT_USB_INTERFACE) || (DEV_BUS_TYPE == RT_SDIO_INTERFACE)
78         if (psd->average == 0)
79                 delay_time = 100;
80         else
81                 delay_time = 0;
82 #else
83         if (psd->average == 0)
84                 delay_time = 1000;
85         else
86                 delay_time = 100;
87 #endif
88
89         if (dm->support_ic_type & (ODM_RTL8812 | ODM_RTL8821 | ODM_RTL8814A | ODM_RTL8822B | ODM_RTL8821C)) {
90                 psd_reg = R_0x910;
91                 psd_report = R_0xf44;
92         } else {
93                 psd_reg = R_0x808;
94                 psd_report = R_0x8b4;
95         }
96
97         if (dm->support_ic_type & ODM_RTL8710B) {
98                 psd_point = 0xeffffc00;
99                 psd_start = 0x10000000;
100         } else {
101                 psd_point = 0xffbffc00;
102                 psd_start = 0x00400000;
103         }
104
105         psd_val = odm_get_bb_reg(dm, psd_reg, MASKDWORD);
106
107         psd_val &= psd_point;
108         psd_val |= point;
109
110         odm_set_bb_reg(dm, psd_reg, MASKDWORD, psd_val);
111
112         psd_val |= psd_start;
113
114         odm_set_bb_reg(dm, psd_reg, MASKDWORD, psd_val);
115
116         for (i = 0; i < delay_time; i++)
117                 ODM_delay_us(1);
118
119         psd_val = odm_get_bb_reg(dm, psd_report, MASKDWORD);
120
121         if (dm->support_ic_type & (ODM_RTL8821C | ODM_RTL8710B)) {
122                 psd_val &= MASKL3BYTES;
123                 psd_val = psd_val / 32;
124         } else {
125                 psd_val &= MASKLWORD;
126         }
127
128         return psd_val;
129 }
130
131 void halrf_psd(
132         struct dm_struct *dm,
133         u32 point,
134         u32 start_point,
135         u32 stop_point,
136         u32 average)
137 {
138         struct _hal_rf_ *rf = &(dm->rf_table);
139         struct _halrf_psd_data *psd = &(rf->halrf_psd_data);
140
141         u32 i = 0, j = 0, k = 0;
142         u32 psd_reg, avg_org, point_temp, average_tmp;
143         u64 data_tatal = 0, data_temp[64] = {0};
144
145         psd->buf_size = 256;
146
147         if (average == 0)
148                 average_tmp = 1;
149         else
150                 average_tmp = average;
151
152         if (dm->support_ic_type & (ODM_RTL8812 | ODM_RTL8821 | ODM_RTL8814A | ODM_RTL8822B | ODM_RTL8821C))
153                 psd_reg = R_0x910;
154         else
155                 psd_reg = R_0x808;
156
157 #if 0
158         dbg_print("[PSD]point=%d, start_point=%d, stop_point=%d, average=%d, average_tmp=%d, buf_size=%d\n",
159                 point, start_point, stop_point, average, average_tmp, psd->buf_size);
160 #endif
161
162         for (i = 0; i < psd->buf_size; i++)
163                 psd->psd_data[i] = 0;
164
165         if (dm->support_ic_type & ODM_RTL8710B)
166                 avg_org = odm_get_bb_reg(dm, psd_reg, 0x30000);
167         else
168                 avg_org = odm_get_bb_reg(dm, psd_reg, 0x3000);
169
170         if (average != 0) {
171                 if (dm->support_ic_type & ODM_RTL8710B)
172                         odm_set_bb_reg(dm, psd_reg, 0x30000, 0x1);
173                 else
174                         odm_set_bb_reg(dm, psd_reg, 0x3000, 0x1);
175         }
176
177 #if 0
178         if (avg_temp == 0)
179                 avg = 1;
180         else if (avg_temp == 1)
181                 avg = 8;
182         else if (avg_temp == 2)
183                 avg = 16;
184         else if (avg_temp == 3)
185                 avg = 32;
186 #endif
187
188         i = start_point;
189         while (i < stop_point) {
190                 data_tatal = 0;
191
192                 if (i >= point)
193                         point_temp = i - point;
194                 else
195                         point_temp = i;
196
197                 for (k = 0; k < average_tmp; k++) {
198                         data_temp[k] = halrf_get_psd_data(dm, point_temp);
199                         data_tatal = data_tatal + (data_temp[k] * data_temp[k]);
200
201 #if 0
202                         if ((k % 20) == 0)
203                                 dbg_print("\n ");
204
205                         dbg_print("0x%x ", data_temp[k]);
206 #endif
207                 }
208                 /*dbg_print("\n");*/
209
210                 data_tatal = ((data_tatal * 100) / average_tmp);
211                 psd->psd_data[j] = (u32)_sqrt(data_tatal);
212
213                 i++;
214                 j++;
215         }
216
217 #if 0
218         for (i = 0; i < psd->buf_size; i++) {
219                 if ((i % 20) == 0)
220                         dbg_print("\n ");
221
222                 dbg_print("0x%x ", psd->psd_data[i]);
223         }
224         dbg_print("\n\n");
225 #endif
226
227         if (dm->support_ic_type & ODM_RTL8710B)
228                 odm_set_bb_reg(dm, psd_reg, 0x30000, avg_org);
229         else
230                 odm_set_bb_reg(dm, psd_reg, 0x3000, avg_org);
231 }
232
233 enum rt_status
234 halrf_psd_init(
235         struct dm_struct *dm)
236 {
237         enum rt_status ret_status = RT_STATUS_SUCCESS;
238         struct _hal_rf_ *rf = &(dm->rf_table);
239         struct _halrf_psd_data *psd = &(rf->halrf_psd_data);
240
241         if (psd->psd_progress) {
242                 ret_status = RT_STATUS_PENDING;
243         } else {
244                 psd->psd_progress = 1;
245                 halrf_psd(dm, psd->point, psd->start_point, psd->stop_point, psd->average);
246                 psd->psd_progress = 0;
247         }
248
249         return ret_status;
250 }
251
252 enum rt_status
253 halrf_psd_query(
254         struct dm_struct *dm,
255         u32 *outbuf,
256         u32 buf_size)
257 {
258         enum rt_status ret_status = RT_STATUS_SUCCESS;
259         struct _hal_rf_ *rf = &(dm->rf_table);
260         struct _halrf_psd_data *psd = &(rf->halrf_psd_data);
261
262         if (psd->psd_progress)
263                 ret_status = RT_STATUS_PENDING;
264         else
265                 PlatformMoveMemory(outbuf, psd->psd_data, 0x400);
266
267         return ret_status;
268 }
269
270 enum rt_status
271 halrf_psd_init_query(
272         struct dm_struct *dm,
273         u32 *outbuf,
274         u32 point,
275         u32 start_point,
276         u32 stop_point,
277         u32 average,
278         u32 buf_size)
279 {
280         enum rt_status ret_status = RT_STATUS_SUCCESS;
281         struct _hal_rf_ *rf = &(dm->rf_table);
282         struct _halrf_psd_data *psd = &(rf->halrf_psd_data);
283
284         psd->point = point;
285         psd->start_point = start_point;
286         psd->stop_point = stop_point;
287         psd->average = average;
288
289         if (psd->psd_progress) {
290                 ret_status = RT_STATUS_PENDING;
291         } else {
292                 psd->psd_progress = 1;
293                 halrf_psd(dm, psd->point, psd->start_point, psd->stop_point, psd->average);
294                 PlatformMoveMemory(outbuf, psd->psd_data, 0x400);
295                 psd->psd_progress = 0;
296         }
297
298         return ret_status;
299 }
300
301 #endif /*#if (DM_ODM_SUPPORT_TYPE & ODM_WIN)*/