]> Git Repo - linux.git/blob - drivers/staging/vt6656/rf.c
arm64: avoid prototype warnings for syscalls
[linux.git] / drivers / staging / vt6656 / rf.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
4  * All rights reserved.
5  *
6  * Purpose: rf function code
7  *
8  * Author: Jerry Chen
9  *
10  * Date: Feb. 19, 2004
11  *
12  * Functions:
13  *      vnt_rf_write_embedded   - Embedded write RF register via MAC
14  *
15  * Revision History:
16  *      RF_VT3226: RobertYu:20051111, VT3226C0 and before
17  *      RF_VT3226D0: RobertYu:20051228
18  *      RF_VT3342A0: RobertYu:20060609
19  *
20  */
21
22 #include <linux/errno.h>
23 #include "mac.h"
24 #include "rf.h"
25 #include "baseband.h"
26 #include "usbpipe.h"
27
28 #define CB_AL2230_INIT_SEQ    15
29 #define CB_AL7230_INIT_SEQ    16
30 #define CB_VT3226_INIT_SEQ    11
31 #define CB_VT3342_INIT_SEQ    13
32
33 static u8 al2230_init_table[CB_AL2230_INIT_SEQ][3] = {
34         {0x03, 0xf7, 0x90},
35         {0x03, 0x33, 0x31},
36         {0x01, 0xb8, 0x02},
37         {0x00, 0xff, 0xf3},
38         {0x00, 0x05, 0xa4},
39         {0x0f, 0x4d, 0xc5},
40         {0x08, 0x05, 0xb6},
41         {0x01, 0x47, 0xc7},
42         {0x00, 0x06, 0x88},
43         {0x04, 0x03, 0xb9},
44         {0x00, 0xdb, 0xba},
45         {0x00, 0x09, 0x9b},
46         {0x0b, 0xdf, 0xfc},
47         {0x00, 0x00, 0x0d},
48         {0x00, 0x58, 0x0f}
49 };
50
51 static u8 al2230_channel_table0[CB_MAX_CHANNEL_24G][3] = {
52         {0x03, 0xf7, 0x90},
53         {0x03, 0xf7, 0x90},
54         {0x03, 0xe7, 0x90},
55         {0x03, 0xe7, 0x90},
56         {0x03, 0xf7, 0xa0},
57         {0x03, 0xf7, 0xa0},
58         {0x03, 0xe7, 0xa0},
59         {0x03, 0xe7, 0xa0},
60         {0x03, 0xf7, 0xb0},
61         {0x03, 0xf7, 0xb0},
62         {0x03, 0xe7, 0xb0},
63         {0x03, 0xe7, 0xb0},
64         {0x03, 0xf7, 0xc0},
65         {0x03, 0xe7, 0xc0}
66 };
67
68 static u8 al2230_channel_table1[CB_MAX_CHANNEL_24G][3] = {
69         {0x03, 0x33, 0x31},
70         {0x0b, 0x33, 0x31},
71         {0x03, 0x33, 0x31},
72         {0x0b, 0x33, 0x31},
73         {0x03, 0x33, 0x31},
74         {0x0b, 0x33, 0x31},
75         {0x03, 0x33, 0x31},
76         {0x0b, 0x33, 0x31},
77         {0x03, 0x33, 0x31},
78         {0x0b, 0x33, 0x31},
79         {0x03, 0x33, 0x31},
80         {0x0b, 0x33, 0x31},
81         {0x03, 0x33, 0x31},
82         {0x06, 0x66, 0x61}
83 };
84
85 static u8 vt3226_init_table[CB_VT3226_INIT_SEQ][3] = {
86         {0x03, 0xff, 0x80},
87         {0x02, 0x82, 0xa1},
88         {0x03, 0xc6, 0xa2},
89         {0x01, 0x97, 0x93},
90         {0x03, 0x66, 0x64},
91         {0x00, 0x61, 0xa5},
92         {0x01, 0x7b, 0xd6},
93         {0x00, 0x80, 0x17},
94         {0x03, 0xf8, 0x08},
95         {0x00, 0x02, 0x39},
96         {0x02, 0x00, 0x2a}
97 };
98
99 static u8 vt3226d0_init_table[CB_VT3226_INIT_SEQ][3] = {
100         {0x03, 0xff, 0x80},
101         {0x03, 0x02, 0x21},
102         {0x03, 0xc6, 0xa2},
103         {0x01, 0x97, 0x93},
104         {0x03, 0x66, 0x64},
105         {0x00, 0x71, 0xa5},
106         {0x01, 0x15, 0xc6},
107         {0x01, 0x2e, 0x07},
108         {0x00, 0x58, 0x08},
109         {0x00, 0x02, 0x79},
110         {0x02, 0x01, 0xaa}
111 };
112
113 static u8 vt3226_channel_table0[CB_MAX_CHANNEL_24G][3] = {
114         {0x01, 0x97, 0x83},
115         {0x01, 0x97, 0x83},
116         {0x01, 0x97, 0x93},
117         {0x01, 0x97, 0x93},
118         {0x01, 0x97, 0x93},
119         {0x01, 0x97, 0x93},
120         {0x01, 0x97, 0xa3},
121         {0x01, 0x97, 0xa3},
122         {0x01, 0x97, 0xa3},
123         {0x01, 0x97, 0xa3},
124         {0x01, 0x97, 0xb3},
125         {0x01, 0x97, 0xb3},
126         {0x01, 0x97, 0xb3},
127         {0x03, 0x37, 0xc3}
128 };
129
130 static u8 vt3226_channel_table1[CB_MAX_CHANNEL_24G][3] = {
131         {0x02, 0x66, 0x64},
132         {0x03, 0x66, 0x64},
133         {0x00, 0x66, 0x64},
134         {0x01, 0x66, 0x64},
135         {0x02, 0x66, 0x64},
136         {0x03, 0x66, 0x64},
137         {0x00, 0x66, 0x64},
138         {0x01, 0x66, 0x64},
139         {0x02, 0x66, 0x64},
140         {0x03, 0x66, 0x64},
141         {0x00, 0x66, 0x64},
142         {0x01, 0x66, 0x64},
143         {0x02, 0x66, 0x64},
144         {0x00, 0xcc, 0xc4}
145 };
146
147 static const u32 vt3226d0_lo_current_table[CB_MAX_CHANNEL_24G] = {
148         0x0135c600,
149         0x0135c600,
150         0x0235c600,
151         0x0235c600,
152         0x0235c600,
153         0x0335c600,
154         0x0335c600,
155         0x0335c600,
156         0x0335c600,
157         0x0335c600,
158         0x0335c600,
159         0x0335c600,
160         0x0335c600,
161         0x0135c600
162 };
163
164 enum {
165         VNT_TABLE_INIT = 0,
166         VNT_TABLE_INIT_2 = 0,
167         VNT_TABLE_0 = 1,
168         VNT_TABLE_1 = 2,
169         VNT_TABLE_2 = 1
170 };
171
172 struct vnt_table_info {
173         u8 *addr;
174         int length;
175 };
176
177 static const struct vnt_table_info vnt_table_seq[][3] = {
178         {       /* RF_AL2230, RF_AL2230S init table, channel table 0 and 1 */
179                 {&al2230_init_table[0][0], CB_AL2230_INIT_SEQ * 3},
180                 {&al2230_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3},
181                 {&al2230_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3}
182         }, {    /* RF_VT3226 init table, channel table 0 and 1 */
183                 {&vt3226_init_table[0][0], CB_VT3226_INIT_SEQ * 3},
184                 {&vt3226_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3},
185                 {&vt3226_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3}
186         }, {    /* RF_VT3226D0 init table, channel table 0 and 1 */
187                 {&vt3226d0_init_table[0][0], CB_VT3226_INIT_SEQ * 3},
188                 {&vt3226_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3},
189                 {&vt3226_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3}
190         }
191 };
192
193 /*
194  * Description: Write to IF/RF, by embedded programming
195  */
196 int vnt_rf_write_embedded(struct vnt_private *priv, u32 data)
197 {
198         u8 reg_data[4];
199
200         data |= (VNT_RF_REG_LEN << 3) | IFREGCTL_REGW;
201
202         reg_data[0] = (u8)data;
203         reg_data[1] = (u8)(data >> 8);
204         reg_data[2] = (u8)(data >> 16);
205         reg_data[3] = (u8)(data >> 24);
206
207         return vnt_control_out(priv, MESSAGE_TYPE_WRITE_IFRF, 0, 0,
208                                ARRAY_SIZE(reg_data), reg_data);
209 }
210
211 static u8 vnt_rf_addpower(struct vnt_private *priv)
212 {
213         int base;
214         s32 rssi = -priv->current_rssi;
215
216         if (!rssi)
217                 return 7;
218
219         if (priv->rf_type == RF_VT3226D0)
220                 base = -60;
221         else
222                 base = -70;
223
224         if (rssi < base)
225                 return ((rssi - base + 1) / -5) * 2 + 5;
226
227         return 0;
228 }
229
230 /* Set Tx power by power level and rate */
231 static int vnt_rf_set_txpower(struct vnt_private *priv, u8 power,
232                               struct ieee80211_channel *ch)
233 {
234         u32 power_setting = 0;
235         int ret = 0;
236
237         power += vnt_rf_addpower(priv);
238         if (power > VNT_RF_MAX_POWER)
239                 power = VNT_RF_MAX_POWER;
240
241         if (priv->power == power)
242                 return 0;
243
244         priv->power = power;
245
246         switch (priv->rf_type) {
247         case RF_AL2230:
248                 power_setting = 0x0404090 | (power << 12);
249
250                 ret = vnt_rf_write_embedded(priv, power_setting);
251                 if (ret)
252                         return ret;
253
254                 if (ch->flags & IEEE80211_CHAN_NO_OFDM)
255                         ret = vnt_rf_write_embedded(priv, 0x0001b400);
256                 else
257                         ret = vnt_rf_write_embedded(priv, 0x0005a400);
258
259                 break;
260         case RF_AL2230S:
261                 power_setting = 0x0404090 | (power << 12);
262
263                 ret = vnt_rf_write_embedded(priv, power_setting);
264                 if (ret)
265                         return ret;
266
267                 if (ch->flags & IEEE80211_CHAN_NO_OFDM) {
268                         ret = vnt_rf_write_embedded(priv, 0x040c1400);
269                         if (ret)
270                                 return ret;
271
272                         ret = vnt_rf_write_embedded(priv, 0x00299b00);
273                 } else {
274                         ret = vnt_rf_write_embedded(priv, 0x0005a400);
275                         if (ret)
276                                 return ret;
277
278                         ret = vnt_rf_write_embedded(priv, 0x00099b00);
279                 }
280
281                 break;
282
283         case RF_VT3226:
284                 power_setting = ((0x3f - power) << 20) | (0x17 << 8);
285
286                 ret = vnt_rf_write_embedded(priv, power_setting);
287                 break;
288         case RF_VT3226D0:
289                 if (ch->flags & IEEE80211_CHAN_NO_OFDM) {
290                         u16 hw_value = ch->hw_value;
291
292                         power_setting = ((0x3f - power) << 20) | (0xe07 << 8);
293
294                         ret = vnt_rf_write_embedded(priv, power_setting);
295                         if (ret)
296                                 return ret;
297
298                         ret = vnt_rf_write_embedded(priv, 0x03c6a200);
299                         if (ret)
300                                 return ret;
301
302                         dev_dbg(&priv->usb->dev,
303                                 "%s 11b channel [%d]\n", __func__, hw_value);
304
305                         hw_value--;
306
307                         if (hw_value < ARRAY_SIZE(vt3226d0_lo_current_table)) {
308                                 ret = vnt_rf_write_embedded(priv,
309                                                             vt3226d0_lo_current_table[hw_value]);
310                                 if (ret)
311                                         return ret;
312                         }
313
314                         ret = vnt_rf_write_embedded(priv, 0x015C0800);
315                 } else {
316                         dev_dbg(&priv->usb->dev,
317                                 "@@@@ %s> 11G mode\n", __func__);
318
319                         power_setting = ((0x3f - power) << 20) | (0x7 << 8);
320
321                         ret = vnt_rf_write_embedded(priv, power_setting);
322                         if (ret)
323                                 return ret;
324
325                         ret = vnt_rf_write_embedded(priv, 0x00C6A200);
326                         if (ret)
327                                 return ret;
328
329                         ret = vnt_rf_write_embedded(priv, 0x016BC600);
330                         if (ret)
331                                 return ret;
332
333                         ret = vnt_rf_write_embedded(priv, 0x00900800);
334                 }
335
336                 break;
337
338         default:
339                 break;
340         }
341         return ret;
342 }
343
344 /* Set Tx power by channel number type */
345 int vnt_rf_setpower(struct vnt_private *priv,
346                     struct ieee80211_channel *ch)
347 {
348         u16 channel;
349         u8 power = priv->cck_pwr;
350
351         if (!ch)
352                 return -EINVAL;
353
354         /* set channel number to array number */
355         channel = ch->hw_value - 1;
356
357         if (ch->flags & IEEE80211_CHAN_NO_OFDM) {
358                 if (channel < ARRAY_SIZE(priv->cck_pwr_tbl))
359                         power = priv->cck_pwr_tbl[channel];
360         } else if (ch->band == NL80211_BAND_5GHZ) {
361                 /* remove 14 channels to array size */
362                 channel -= 14;
363
364                 if (channel < ARRAY_SIZE(priv->ofdm_a_pwr_tbl))
365                         power = priv->ofdm_a_pwr_tbl[channel];
366         } else {
367                 if (channel < ARRAY_SIZE(priv->ofdm_pwr_tbl))
368                         power = priv->ofdm_pwr_tbl[channel];
369         }
370
371         return vnt_rf_set_txpower(priv, power, ch);
372 }
373
374 /* Convert rssi to dbm */
375 void vnt_rf_rssi_to_dbm(struct vnt_private *priv, u8 rssi, long *dbm)
376 {
377         u8 idx = ((rssi & 0xc0) >> 6) & 0x03;
378         long b = rssi & 0x3f;
379         long a = 0;
380         u8 airoharf[4] = {0, 18, 0, 40};
381
382         switch (priv->rf_type) {
383         case RF_AL2230:
384         case RF_AL2230S:
385         case RF_VT3226:
386         case RF_VT3226D0:
387                 a = airoharf[idx];
388                 break;
389         default:
390                 break;
391         }
392
393         *dbm = -1 * (a + b * 2);
394 }
395
396 int vnt_rf_table_download(struct vnt_private *priv)
397 {
398         int ret;
399         int idx = -1;
400         const struct vnt_table_info *table_seq;
401
402         switch (priv->rf_type) {
403         case RF_AL2230:
404         case RF_AL2230S:
405                 idx = 0;
406                 break;
407         case RF_VT3226:
408                 idx = 1;
409                 break;
410         case RF_VT3226D0:
411                 idx = 2;
412                 break;
413         }
414
415         if (idx < 0)
416                 return 0;
417
418         table_seq = &vnt_table_seq[idx][0];
419
420         /* Init Table */
421         ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
422                               MESSAGE_REQUEST_RF_INIT,
423                               table_seq[VNT_TABLE_INIT].length,
424                               table_seq[VNT_TABLE_INIT].addr);
425         if (ret)
426                 return ret;
427
428         /* Channel Table 0 */
429         ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE,
430                                      MESSAGE_REQUEST_RF_CH0,
431                                      table_seq[VNT_TABLE_0].length,
432                                      table_seq[VNT_TABLE_0].addr);
433         if (ret)
434                 return ret;
435
436         /* Channel Table 1 */
437         ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE,
438                                      MESSAGE_REQUEST_RF_CH1,
439                                      table_seq[VNT_TABLE_1].length,
440                                      table_seq[VNT_TABLE_1].addr);
441
442         return ret;
443 }
This page took 0.055264 seconds and 4 git commands to generate.