]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
drivers/net/wireless: Use wiphy_<level>
[net-next-2.6.git] / drivers / net / wireless / rtl818x / rtl8187_rtl8225.c
CommitLineData
605bebe2
MW
1/*
2 * Radio tuning for RTL8225 on RTL8187
3 *
4 * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
5 * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
6 *
7 * Based on the r8187 driver, which is:
8 * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
9 *
0aec00ae
JL
10 * Magic delays, register offsets, and phy value tables below are
11 * taken from the original r8187 driver sources. Thanks to Realtek
12 * for their support!
605bebe2
MW
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18
19#include <linux/init.h>
20#include <linux/usb.h>
21#include <net/mac80211.h>
22
23#include "rtl8187.h"
24#include "rtl8187_rtl8225.h"
25
26static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
27{
28 struct rtl8187_priv *priv = dev->priv;
29 u16 reg80, reg84, reg82;
30 u32 bangdata;
31 int i;
32
33 bangdata = (data << 4) | (addr & 0xf);
34
35 reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
36 reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
37
38 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
39
40 reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
41 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
42 udelay(10);
43
44 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
45 udelay(2);
46 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
47 udelay(10);
48
49 for (i = 15; i >= 0; i--) {
50 u16 reg = reg80 | (bangdata & (1 << i)) >> i;
51
52 if (i & 1)
53 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
54
55 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
56 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
57
58 if (!(i & 1))
59 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
60 }
61
62 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
63 udelay(10);
64
65 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
66 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
605bebe2
MW
67}
68
899413de 69static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
605bebe2
MW
70{
71 struct rtl8187_priv *priv = dev->priv;
72 u16 reg80, reg82, reg84;
73
74 reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
75 reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
76 reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
77
78 reg80 &= ~(0x3 << 2);
79 reg84 &= ~0xF;
80
81 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
82 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
83 udelay(10);
84
85 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
86 udelay(2);
87
88 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
89 udelay(10);
90
9be6f0d4
JL
91 mutex_lock(&priv->io_mutex);
92
93 priv->io_dmabuf->bits16 = data;
605bebe2
MW
94 usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
95 RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
9be6f0d4
JL
96 addr, 0x8225, &priv->io_dmabuf->bits16, sizeof(data),
97 HZ / 2);
98
99 mutex_unlock(&priv->io_mutex);
605bebe2
MW
100
101 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
102 udelay(10);
103
104 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
105 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
605bebe2
MW
106}
107
f6532111 108static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
605bebe2
MW
109{
110 struct rtl8187_priv *priv = dev->priv;
111
112 if (priv->asic_rev)
899413de 113 rtl8225_write_8051(dev, addr, cpu_to_le16(data));
605bebe2
MW
114 else
115 rtl8225_write_bitbang(dev, addr, data);
116}
117
f6532111 118static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
605bebe2
MW
119{
120 struct rtl8187_priv *priv = dev->priv;
121 u16 reg80, reg82, reg84, out;
122 int i;
123
124 reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
125 reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
126 reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
127
128 reg80 &= ~0xF;
129
130 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
131 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
132
133 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
134 udelay(4);
135 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
136 udelay(5);
137
138 for (i = 4; i >= 0; i--) {
139 u16 reg = reg80 | ((addr >> i) & 1);
140
141 if (!(i & 1)) {
142 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
143 udelay(1);
144 }
145
146 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
147 reg | (1 << 1));
148 udelay(2);
149 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
150 reg | (1 << 1));
151 udelay(2);
152
153 if (i & 1) {
154 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
155 udelay(1);
156 }
157 }
158
159 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
160 reg80 | (1 << 3) | (1 << 1));
161 udelay(2);
162 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
163 reg80 | (1 << 3));
164 udelay(2);
165 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
166 reg80 | (1 << 3));
167 udelay(2);
168
169 out = 0;
170 for (i = 11; i >= 0; i--) {
171 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
172 reg80 | (1 << 3));
173 udelay(1);
174 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
175 reg80 | (1 << 3) | (1 << 1));
176 udelay(2);
177 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
178 reg80 | (1 << 3) | (1 << 1));
179 udelay(2);
180 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
181 reg80 | (1 << 3) | (1 << 1));
182 udelay(2);
183
184 if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
185 out |= 1 << i;
186
187 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
188 reg80 | (1 << 3));
189 udelay(2);
190 }
191
192 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
193 reg80 | (1 << 3) | (1 << 2));
194 udelay(2);
195
196 rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
197 rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
198 rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
199
200 return out;
201}
202
203static const u16 rtl8225bcd_rxgain[] = {
204 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
205 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
206 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
207 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
208 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
209 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
210 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
211 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
212 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
213 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
214 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
215 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
216};
217
218static const u8 rtl8225_agc[] = {
219 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
220 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
221 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
222 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
223 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
224 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
225 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
226 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
227 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
228 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
229 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
230 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
231 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
232 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
233 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
234 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
235};
236
237static const u8 rtl8225_gain[] = {
238 0x23, 0x88, 0x7c, 0xa5, /* -82dBm */
239 0x23, 0x88, 0x7c, 0xb5, /* -82dBm */
240 0x23, 0x88, 0x7c, 0xc5, /* -82dBm */
241 0x33, 0x80, 0x79, 0xc5, /* -78dBm */
242 0x43, 0x78, 0x76, 0xc5, /* -74dBm */
243 0x53, 0x60, 0x73, 0xc5, /* -70dBm */
244 0x63, 0x58, 0x70, 0xc5, /* -66dBm */
245};
246
247static const u8 rtl8225_threshold[] = {
248 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
249};
250
251static const u8 rtl8225_tx_gain_cck_ofdm[] = {
252 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
253};
254
255static const u8 rtl8225_tx_power_cck[] = {
256 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
257 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
258 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
259 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
260 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
261 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
262};
263
264static const u8 rtl8225_tx_power_cck_ch14[] = {
265 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
266 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
267 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
268 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
269 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
270 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
271};
272
273static const u8 rtl8225_tx_power_ofdm[] = {
274 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
275};
276
277static const u32 rtl8225_chan[] = {
278 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
279 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
280};
281
282static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
283{
284 struct rtl8187_priv *priv = dev->priv;
285 u8 cck_power, ofdm_power;
286 const u8 *tmp;
287 u32 reg;
288 int i;
289
8318d78a
JB
290 cck_power = priv->channels[channel - 1].hw_value & 0xF;
291 ofdm_power = priv->channels[channel - 1].hw_value >> 4;
605bebe2
MW
292
293 cck_power = min(cck_power, (u8)11);
eb83bbf5
LF
294 if (ofdm_power > (u8)15)
295 ofdm_power = 25;
296 else
297 ofdm_power += 10;
605bebe2
MW
298
299 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
300 rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
301
302 if (channel == 14)
303 tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
304 else
305 tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
306
307 for (i = 0; i < 8; i++)
308 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
309
310 msleep(1); // FIXME: optional?
311
312 /* anaparam2 on */
313 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
314 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
e7d414ff
HTL
315 rtl818x_iowrite8(priv, &priv->map->CONFIG3,
316 reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
4ece16a1
HRK
317 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
318 RTL8187_RTL8225_ANAPARAM2_ON);
e7d414ff
HTL
319 rtl818x_iowrite8(priv, &priv->map->CONFIG3,
320 reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
605bebe2
MW
321 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
322
323 rtl8225_write_phy_ofdm(dev, 2, 0x42);
324 rtl8225_write_phy_ofdm(dev, 6, 0x00);
325 rtl8225_write_phy_ofdm(dev, 8, 0x00);
326
327 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
328 rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
329
330 tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
331
332 rtl8225_write_phy_ofdm(dev, 5, *tmp);
333 rtl8225_write_phy_ofdm(dev, 7, *tmp);
334
335 msleep(1);
336}
337
f6532111 338static void rtl8225_rf_init(struct ieee80211_hw *dev)
605bebe2
MW
339{
340 struct rtl8187_priv *priv = dev->priv;
341 int i;
342
946d1c22
LF
343 rtl8225_write(dev, 0x0, 0x067);
344 rtl8225_write(dev, 0x1, 0xFE0);
345 rtl8225_write(dev, 0x2, 0x44D);
346 rtl8225_write(dev, 0x3, 0x441);
347 rtl8225_write(dev, 0x4, 0x486);
348 rtl8225_write(dev, 0x5, 0xBC0);
349 rtl8225_write(dev, 0x6, 0xAE6);
350 rtl8225_write(dev, 0x7, 0x82A);
351 rtl8225_write(dev, 0x8, 0x01F);
352 rtl8225_write(dev, 0x9, 0x334);
353 rtl8225_write(dev, 0xA, 0xFD4);
354 rtl8225_write(dev, 0xB, 0x391);
355 rtl8225_write(dev, 0xC, 0x050);
356 rtl8225_write(dev, 0xD, 0x6DB);
357 rtl8225_write(dev, 0xE, 0x029);
605bebe2
MW
358 rtl8225_write(dev, 0xF, 0x914); msleep(100);
359
360 rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
361 rtl8225_write(dev, 0x2, 0x44D); msleep(200);
362
363 if (!(rtl8225_read(dev, 6) & (1 << 7))) {
364 rtl8225_write(dev, 0x02, 0x0c4d);
365 msleep(200);
366 rtl8225_write(dev, 0x02, 0x044d);
367 msleep(100);
368 if (!(rtl8225_read(dev, 6) & (1 << 7)))
c96c31e4
JP
369 wiphy_warn(dev->wiphy, "rf calibration failed! %x\n",
370 rtl8225_read(dev, 6));
605bebe2
MW
371 }
372
373 rtl8225_write(dev, 0x0, 0x127);
374
375 for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
376 rtl8225_write(dev, 0x1, i + 1);
377 rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
378 }
379
380 rtl8225_write(dev, 0x0, 0x027);
381 rtl8225_write(dev, 0x0, 0x22F);
382
383 for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
384 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
605bebe2 385 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
605bebe2
MW
386 }
387
388 msleep(1);
389
35cc988a
LF
390 rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
391 rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
392 rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
393 rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
394 rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
395 rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
396 rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
397 rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
398 rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
399 rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
400 rtl8225_write_phy_ofdm(dev, 0x0a, 0x09);
401 rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
402 rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
403 rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
404 rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
405 rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
406 rtl8225_write_phy_ofdm(dev, 0x11, 0x06);
407 rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
408 rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
409 rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
410 rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
411 rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
412 rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
413 rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
414 rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
415 rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
416 rtl8225_write_phy_ofdm(dev, 0x1b, 0x76);
417 rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
418 rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
419 rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
420 rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
421 rtl8225_write_phy_ofdm(dev, 0x21, 0x27);
422 rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
423 rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
424 rtl8225_write_phy_ofdm(dev, 0x25, 0x20);
425 rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
426 rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
605bebe2
MW
427
428 rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
429 rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
430 rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
431 rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
432
a3d67bc2
LF
433 rtl8225_write_phy_cck(dev, 0x00, 0x98);
434 rtl8225_write_phy_cck(dev, 0x03, 0x20);
435 rtl8225_write_phy_cck(dev, 0x04, 0x7e);
436 rtl8225_write_phy_cck(dev, 0x05, 0x12);
437 rtl8225_write_phy_cck(dev, 0x06, 0xfc);
438 rtl8225_write_phy_cck(dev, 0x07, 0x78);
439 rtl8225_write_phy_cck(dev, 0x08, 0x2e);
440 rtl8225_write_phy_cck(dev, 0x10, 0x9b);
441 rtl8225_write_phy_cck(dev, 0x11, 0x88);
442 rtl8225_write_phy_cck(dev, 0x12, 0x47);
605bebe2
MW
443 rtl8225_write_phy_cck(dev, 0x13, 0xd0);
444 rtl8225_write_phy_cck(dev, 0x19, 0x00);
445 rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
446 rtl8225_write_phy_cck(dev, 0x1b, 0x08);
447 rtl8225_write_phy_cck(dev, 0x40, 0x86);
a3d67bc2
LF
448 rtl8225_write_phy_cck(dev, 0x41, 0x8d);
449 rtl8225_write_phy_cck(dev, 0x42, 0x15);
450 rtl8225_write_phy_cck(dev, 0x43, 0x18);
451 rtl8225_write_phy_cck(dev, 0x44, 0x1f);
452 rtl8225_write_phy_cck(dev, 0x45, 0x1e);
453 rtl8225_write_phy_cck(dev, 0x46, 0x1a);
454 rtl8225_write_phy_cck(dev, 0x47, 0x15);
455 rtl8225_write_phy_cck(dev, 0x48, 0x10);
456 rtl8225_write_phy_cck(dev, 0x49, 0x0a);
457 rtl8225_write_phy_cck(dev, 0x4a, 0x05);
458 rtl8225_write_phy_cck(dev, 0x4b, 0x02);
459 rtl8225_write_phy_cck(dev, 0x4c, 0x05);
605bebe2
MW
460
461 rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
462
463 rtl8225_rf_set_tx_power(dev, 1);
464
465 /* RX antenna default to A */
a3d67bc2 466 rtl8225_write_phy_cck(dev, 0x10, 0x9b); /* B: 0xDB */
35cc988a 467 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); /* B: 0x10 */
605bebe2
MW
468
469 rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
470 msleep(1);
471 rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
472
473 /* set sensitivity */
474 rtl8225_write(dev, 0x0c, 0x50);
475 rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
476 rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
477 rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
478 rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
479 rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
480}
481
e7d414ff
HTL
482static const u8 rtl8225z2_agc[] = {
483 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f,
484 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37,
485 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f,
486 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07,
487 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
488 0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
489 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28,
490 0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d,
491 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30,
492 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
493 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
494};
495static const u8 rtl8225z2_ofdm[] = {
496 0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60,
497 0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
498 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26,
499 0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3,
500 0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f,
501 0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00,
502 0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e,
503 0x6d, 0x3c, 0xfb, 0x07
504};
505
605bebe2 506static const u8 rtl8225z2_tx_power_cck_ch14[] = {
e7d414ff
HTL
507 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00,
508 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
509 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
510 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00
605bebe2
MW
511};
512
513static const u8 rtl8225z2_tx_power_cck[] = {
e7d414ff
HTL
514 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04,
515 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03,
516 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03,
517 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03
605bebe2
MW
518};
519
520static const u8 rtl8225z2_tx_power_ofdm[] = {
521 0x42, 0x00, 0x40, 0x00, 0x40
522};
523
524static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
525 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
526 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
527 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
528 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
529 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
530 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
531};
532
533static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
534{
535 struct rtl8187_priv *priv = dev->priv;
536 u8 cck_power, ofdm_power;
537 const u8 *tmp;
538 u32 reg;
539 int i;
540
8318d78a
JB
541 cck_power = priv->channels[channel - 1].hw_value & 0xF;
542 ofdm_power = priv->channels[channel - 1].hw_value >> 4;
605bebe2
MW
543
544 cck_power = min(cck_power, (u8)15);
545 cck_power += priv->txpwr_base & 0xF;
546 cck_power = min(cck_power, (u8)35);
547
eb83bbf5
LF
548 if (ofdm_power > (u8)15)
549 ofdm_power = 25;
550 else
551 ofdm_power += 10;
605bebe2
MW
552 ofdm_power += priv->txpwr_base >> 4;
553 ofdm_power = min(ofdm_power, (u8)35);
554
555 if (channel == 14)
556 tmp = rtl8225z2_tx_power_cck_ch14;
557 else
558 tmp = rtl8225z2_tx_power_cck;
559
560 for (i = 0; i < 8; i++)
561 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
562
563 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
564 rtl8225z2_tx_gain_cck_ofdm[cck_power]);
565 msleep(1);
566
567 /* anaparam2 on */
568 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
569 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
e7d414ff
HTL
570 rtl818x_iowrite8(priv, &priv->map->CONFIG3,
571 reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
4ece16a1
HRK
572 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
573 RTL8187_RTL8225_ANAPARAM2_ON);
e7d414ff
HTL
574 rtl818x_iowrite8(priv, &priv->map->CONFIG3,
575 reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
605bebe2
MW
576 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
577
578 rtl8225_write_phy_ofdm(dev, 2, 0x42);
579 rtl8225_write_phy_ofdm(dev, 5, 0x00);
580 rtl8225_write_phy_ofdm(dev, 6, 0x40);
581 rtl8225_write_phy_ofdm(dev, 7, 0x00);
582 rtl8225_write_phy_ofdm(dev, 8, 0x40);
583
584 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
585 rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
586 msleep(1);
587}
588
e7d414ff
HTL
589static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
590{
591 struct rtl8187_priv *priv = dev->priv;
592 u8 cck_power, ofdm_power;
593 const u8 *tmp;
594 int i;
595
596 cck_power = priv->channels[channel - 1].hw_value & 0xF;
597 ofdm_power = priv->channels[channel - 1].hw_value >> 4;
598
599 if (cck_power > 15)
600 cck_power = (priv->hw_rev == RTL8187BvB) ? 15 : 22;
601 else
602 cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7;
603 cck_power += priv->txpwr_base & 0xF;
604 cck_power = min(cck_power, (u8)35);
605
606 if (ofdm_power > 15)
607 ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25;
608 else
609 ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10;
610 ofdm_power += (priv->txpwr_base >> 4) & 0xF;
611 ofdm_power = min(ofdm_power, (u8)35);
612
613 if (channel == 14)
614 tmp = rtl8225z2_tx_power_cck_ch14;
615 else
616 tmp = rtl8225z2_tx_power_cck;
617
618 if (priv->hw_rev == RTL8187BvB) {
619 if (cck_power <= 6)
620 ; /* do nothing */
621 else if (cck_power <= 11)
622 tmp += 8;
623 else
624 tmp += 16;
625 } else {
626 if (cck_power <= 5)
627 ; /* do nothing */
628 else if (cck_power <= 11)
629 tmp += 8;
630 else if (cck_power <= 17)
631 tmp += 16;
632 else
633 tmp += 24;
634 }
635
636 for (i = 0; i < 8; i++)
637 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
638
639 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
c4832467 640 rtl8225z2_tx_gain_cck_ofdm[cck_power] << 1);
e7d414ff
HTL
641 msleep(1);
642
643 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
644 rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1);
645 if (priv->hw_rev == RTL8187BvB) {
646 if (ofdm_power <= 11) {
647 rtl8225_write_phy_ofdm(dev, 0x87, 0x60);
648 rtl8225_write_phy_ofdm(dev, 0x89, 0x60);
649 } else {
650 rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
651 rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
652 }
653 } else {
654 if (ofdm_power <= 11) {
655 rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
656 rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
657 } else if (ofdm_power <= 17) {
658 rtl8225_write_phy_ofdm(dev, 0x87, 0x54);
659 rtl8225_write_phy_ofdm(dev, 0x89, 0x54);
660 } else {
661 rtl8225_write_phy_ofdm(dev, 0x87, 0x50);
662 rtl8225_write_phy_ofdm(dev, 0x89, 0x50);
663 }
664 }
665 msleep(1);
666}
667
605bebe2
MW
668static const u16 rtl8225z2_rxgain[] = {
669 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
670 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
671 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
672 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
673 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
674 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
675 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
676 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
677 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
678 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
679 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
680 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
681};
682
683static const u8 rtl8225z2_gain_bg[] = {
684 0x23, 0x15, 0xa5, /* -82-1dBm */
685 0x23, 0x15, 0xb5, /* -82-2dBm */
686 0x23, 0x15, 0xc5, /* -82-3dBm */
687 0x33, 0x15, 0xc5, /* -78dBm */
688 0x43, 0x15, 0xc5, /* -74dBm */
689 0x53, 0x15, 0xc5, /* -70dBm */
690 0x63, 0x15, 0xc5 /* -66dBm */
691};
692
f6532111 693static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
605bebe2
MW
694{
695 struct rtl8187_priv *priv = dev->priv;
696 int i;
697
946d1c22
LF
698 rtl8225_write(dev, 0x0, 0x2BF);
699 rtl8225_write(dev, 0x1, 0xEE0);
700 rtl8225_write(dev, 0x2, 0x44D);
701 rtl8225_write(dev, 0x3, 0x441);
702 rtl8225_write(dev, 0x4, 0x8C3);
703 rtl8225_write(dev, 0x5, 0xC72);
704 rtl8225_write(dev, 0x6, 0x0E6);
705 rtl8225_write(dev, 0x7, 0x82A);
706 rtl8225_write(dev, 0x8, 0x03F);
707 rtl8225_write(dev, 0x9, 0x335);
708 rtl8225_write(dev, 0xa, 0x9D4);
709 rtl8225_write(dev, 0xb, 0x7BB);
710 rtl8225_write(dev, 0xc, 0x850);
711 rtl8225_write(dev, 0xd, 0xCDF);
712 rtl8225_write(dev, 0xe, 0x02B);
713 rtl8225_write(dev, 0xf, 0x114);
714 msleep(100);
605bebe2
MW
715
716 rtl8225_write(dev, 0x0, 0x1B7);
717
718 for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
719 rtl8225_write(dev, 0x1, i + 1);
720 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
721 }
722
723 rtl8225_write(dev, 0x3, 0x080);
724 rtl8225_write(dev, 0x5, 0x004);
725 rtl8225_write(dev, 0x0, 0x0B7);
726 rtl8225_write(dev, 0x2, 0xc4D);
727
728 msleep(200);
729 rtl8225_write(dev, 0x2, 0x44D);
730 msleep(100);
731
732 if (!(rtl8225_read(dev, 6) & (1 << 7))) {
733 rtl8225_write(dev, 0x02, 0x0C4D);
734 msleep(200);
735 rtl8225_write(dev, 0x02, 0x044D);
736 msleep(100);
737 if (!(rtl8225_read(dev, 6) & (1 << 7)))
c96c31e4
JP
738 wiphy_warn(dev->wiphy, "rf calibration failed! %x\n",
739 rtl8225_read(dev, 6));
605bebe2
MW
740 }
741
742 msleep(200);
743
744 rtl8225_write(dev, 0x0, 0x2BF);
745
746 for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
747 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
605bebe2 748 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
605bebe2
MW
749 }
750
751 msleep(1);
752
35cc988a
LF
753 rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
754 rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
755 rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
756 rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
757 rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
758 rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
759 rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
760 rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
761 rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
762 rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
763 rtl8225_write_phy_ofdm(dev, 0x0a, 0x08);
764 rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
765 rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
605bebe2 766 rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
35cc988a
LF
767 rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
768 rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
769 rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
770 rtl8225_write_phy_ofdm(dev, 0x11, 0x07);
771 rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
772 rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
773 rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
774 rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
775 rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
776 rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
777 rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
778 rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
779 rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
780 rtl8225_write_phy_ofdm(dev, 0x1b, 0x15);
781 rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
782 rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5);
783 rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
784 rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
785 rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
786 rtl8225_write_phy_ofdm(dev, 0x21, 0x17);
787 rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
788 rtl8225_write_phy_ofdm(dev, 0x23, 0x80);
789 rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
790 rtl8225_write_phy_ofdm(dev, 0x25, 0x00);
791 rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
792 rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
605bebe2
MW
793
794 rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
795 rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
796 rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
797 rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
798
a3d67bc2
LF
799 rtl8225_write_phy_cck(dev, 0x00, 0x98);
800 rtl8225_write_phy_cck(dev, 0x03, 0x20);
801 rtl8225_write_phy_cck(dev, 0x04, 0x7e);
802 rtl8225_write_phy_cck(dev, 0x05, 0x12);
803 rtl8225_write_phy_cck(dev, 0x06, 0xfc);
804 rtl8225_write_phy_cck(dev, 0x07, 0x78);
805 rtl8225_write_phy_cck(dev, 0x08, 0x2e);
806 rtl8225_write_phy_cck(dev, 0x10, 0x9b);
807 rtl8225_write_phy_cck(dev, 0x11, 0x88);
808 rtl8225_write_phy_cck(dev, 0x12, 0x47);
605bebe2
MW
809 rtl8225_write_phy_cck(dev, 0x13, 0xd0);
810 rtl8225_write_phy_cck(dev, 0x19, 0x00);
811 rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
812 rtl8225_write_phy_cck(dev, 0x1b, 0x08);
813 rtl8225_write_phy_cck(dev, 0x40, 0x86);
a3d67bc2
LF
814 rtl8225_write_phy_cck(dev, 0x41, 0x8d);
815 rtl8225_write_phy_cck(dev, 0x42, 0x15);
816 rtl8225_write_phy_cck(dev, 0x43, 0x18);
817 rtl8225_write_phy_cck(dev, 0x44, 0x36);
818 rtl8225_write_phy_cck(dev, 0x45, 0x35);
819 rtl8225_write_phy_cck(dev, 0x46, 0x2e);
820 rtl8225_write_phy_cck(dev, 0x47, 0x25);
821 rtl8225_write_phy_cck(dev, 0x48, 0x1c);
822 rtl8225_write_phy_cck(dev, 0x49, 0x12);
823 rtl8225_write_phy_cck(dev, 0x4a, 0x09);
824 rtl8225_write_phy_cck(dev, 0x4b, 0x04);
825 rtl8225_write_phy_cck(dev, 0x4c, 0x05);
605bebe2
MW
826
827 rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
828
829 rtl8225z2_rf_set_tx_power(dev, 1);
830
831 /* RX antenna default to A */
a3d67bc2 832 rtl8225_write_phy_cck(dev, 0x10, 0x9b); /* B: 0xDB */
35cc988a 833 rtl8225_write_phy_ofdm(dev, 0x26, 0x90); /* B: 0x10 */
605bebe2
MW
834
835 rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
836 msleep(1);
837 rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
838}
839
e7d414ff
HTL
840static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
841{
842 struct rtl8187_priv *priv = dev->priv;
843 int i;
844
946d1c22
LF
845 rtl8225_write(dev, 0x0, 0x0B7);
846 rtl8225_write(dev, 0x1, 0xEE0);
847 rtl8225_write(dev, 0x2, 0x44D);
848 rtl8225_write(dev, 0x3, 0x441);
849 rtl8225_write(dev, 0x4, 0x8C3);
850 rtl8225_write(dev, 0x5, 0xC72);
851 rtl8225_write(dev, 0x6, 0x0E6);
852 rtl8225_write(dev, 0x7, 0x82A);
853 rtl8225_write(dev, 0x8, 0x03F);
854 rtl8225_write(dev, 0x9, 0x335);
855 rtl8225_write(dev, 0xa, 0x9D4);
856 rtl8225_write(dev, 0xb, 0x7BB);
857 rtl8225_write(dev, 0xc, 0x850);
858 rtl8225_write(dev, 0xd, 0xCDF);
859 rtl8225_write(dev, 0xe, 0x02B);
860 rtl8225_write(dev, 0xf, 0x114);
861
862 rtl8225_write(dev, 0x0, 0x1B7);
e7d414ff
HTL
863
864 for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
946d1c22
LF
865 rtl8225_write(dev, 0x1, i + 1);
866 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
e7d414ff
HTL
867 }
868
946d1c22
LF
869 rtl8225_write(dev, 0x3, 0x080);
870 rtl8225_write(dev, 0x5, 0x004);
871 rtl8225_write(dev, 0x0, 0x0B7);
e7d414ff 872
946d1c22 873 rtl8225_write(dev, 0x2, 0xC4D);
e7d414ff 874
946d1c22
LF
875 rtl8225_write(dev, 0x2, 0x44D);
876 rtl8225_write(dev, 0x0, 0x2BF);
e7d414ff
HTL
877
878 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03);
879 rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07);
880 rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);
881
882 rtl8225_write_phy_ofdm(dev, 0x80, 0x12);
883 for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) {
884 rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]);
885 rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i);
886 rtl8225_write_phy_ofdm(dev, 0xE, 0);
887 }
888 rtl8225_write_phy_ofdm(dev, 0x80, 0x10);
889
890 for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
891 rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]);
892
35cc988a
LF
893 rtl8225_write_phy_ofdm(dev, 0x97, 0x46);
894 rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6);
895 rtl8225_write_phy_ofdm(dev, 0x85, 0xfc);
896 rtl8225_write_phy_cck(dev, 0xc1, 0x88);
e7d414ff
HTL
897}
898
f6532111 899static void rtl8225_rf_stop(struct ieee80211_hw *dev)
605bebe2
MW
900{
901 u8 reg;
902 struct rtl8187_priv *priv = dev->priv;
903
946d1c22 904 rtl8225_write(dev, 0x4, 0x1f);
605bebe2
MW
905
906 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
907 reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
908 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
4ece16a1
HRK
909 if (!priv->is_rtl8187b) {
910 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
911 RTL8187_RTL8225_ANAPARAM2_OFF);
912 rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
913 RTL8187_RTL8225_ANAPARAM_OFF);
914 } else {
915 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
916 RTL8187B_RTL8225_ANAPARAM2_OFF);
917 rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
918 RTL8187B_RTL8225_ANAPARAM_OFF);
919 rtl818x_iowrite8(priv, &priv->map->ANAPARAM3,
920 RTL8187B_RTL8225_ANAPARAM3_OFF);
921 }
605bebe2
MW
922 rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
923 rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
924}
925
f6532111
MW
926static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
927 struct ieee80211_conf *conf)
605bebe2
MW
928{
929 struct rtl8187_priv *priv = dev->priv;
8318d78a 930 int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
605bebe2 931
f6532111 932 if (priv->rf->init == rtl8225_rf_init)
8318d78a 933 rtl8225_rf_set_tx_power(dev, chan);
e7d414ff 934 else if (priv->rf->init == rtl8225z2_rf_init)
8318d78a 935 rtl8225z2_rf_set_tx_power(dev, chan);
e7d414ff
HTL
936 else
937 rtl8225z2_b_rf_set_tx_power(dev, chan);
605bebe2 938
8318d78a 939 rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
605bebe2
MW
940 msleep(10);
941}
f6532111
MW
942
943static const struct rtl818x_rf_ops rtl8225_ops = {
944 .name = "rtl8225",
945 .init = rtl8225_rf_init,
946 .stop = rtl8225_rf_stop,
947 .set_chan = rtl8225_rf_set_channel
948};
949
950static const struct rtl818x_rf_ops rtl8225z2_ops = {
951 .name = "rtl8225z2",
952 .init = rtl8225z2_rf_init,
953 .stop = rtl8225_rf_stop,
954 .set_chan = rtl8225_rf_set_channel
955};
956
e7d414ff
HTL
957static const struct rtl818x_rf_ops rtl8225z2_b_ops = {
958 .name = "rtl8225z2",
959 .init = rtl8225z2_b_rf_init,
960 .stop = rtl8225_rf_stop,
961 .set_chan = rtl8225_rf_set_channel
962};
963
f6532111
MW
964const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
965{
966 u16 reg8, reg9;
e7d414ff 967 struct rtl8187_priv *priv = dev->priv;
f6532111 968
e7d414ff
HTL
969 if (!priv->is_rtl8187b) {
970 rtl8225_write(dev, 0, 0x1B7);
f6532111 971
e7d414ff
HTL
972 reg8 = rtl8225_read(dev, 8);
973 reg9 = rtl8225_read(dev, 9);
f6532111 974
e7d414ff 975 rtl8225_write(dev, 0, 0x0B7);
f6532111 976
e7d414ff
HTL
977 if (reg8 != 0x588 || reg9 != 0x700)
978 return &rtl8225_ops;
f6532111 979
e7d414ff
HTL
980 return &rtl8225z2_ops;
981 } else
982 return &rtl8225z2_b_ops;
f6532111 983}