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