Merge branch 'fix/pcm-jiffies-check' into fix/asoc
[pandora-kernel.git] / 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         if (ofdm_power > (u8)15)
289                 ofdm_power = 25;
290         else
291                 ofdm_power += 10;
292
293         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
294                          rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
295
296         if (channel == 14)
297                 tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
298         else
299                 tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
300
301         for (i = 0; i < 8; i++)
302                 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
303
304         msleep(1); // FIXME: optional?
305
306         /* anaparam2 on */
307         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
308         reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
309         rtl818x_iowrite8(priv, &priv->map->CONFIG3,
310                         reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
311         rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
312                           RTL8187_RTL8225_ANAPARAM2_ON);
313         rtl818x_iowrite8(priv, &priv->map->CONFIG3,
314                         reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
315         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
316
317         rtl8225_write_phy_ofdm(dev, 2, 0x42);
318         rtl8225_write_phy_ofdm(dev, 6, 0x00);
319         rtl8225_write_phy_ofdm(dev, 8, 0x00);
320
321         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
322                          rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
323
324         tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
325
326         rtl8225_write_phy_ofdm(dev, 5, *tmp);
327         rtl8225_write_phy_ofdm(dev, 7, *tmp);
328
329         msleep(1);
330 }
331
332 static void rtl8225_rf_init(struct ieee80211_hw *dev)
333 {
334         struct rtl8187_priv *priv = dev->priv;
335         int i;
336
337         rtl8225_write(dev, 0x0, 0x067);
338         rtl8225_write(dev, 0x1, 0xFE0);
339         rtl8225_write(dev, 0x2, 0x44D);
340         rtl8225_write(dev, 0x3, 0x441);
341         rtl8225_write(dev, 0x4, 0x486);
342         rtl8225_write(dev, 0x5, 0xBC0);
343         rtl8225_write(dev, 0x6, 0xAE6);
344         rtl8225_write(dev, 0x7, 0x82A);
345         rtl8225_write(dev, 0x8, 0x01F);
346         rtl8225_write(dev, 0x9, 0x334);
347         rtl8225_write(dev, 0xA, 0xFD4);
348         rtl8225_write(dev, 0xB, 0x391);
349         rtl8225_write(dev, 0xC, 0x050);
350         rtl8225_write(dev, 0xD, 0x6DB);
351         rtl8225_write(dev, 0xE, 0x029);
352         rtl8225_write(dev, 0xF, 0x914); msleep(100);
353
354         rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
355         rtl8225_write(dev, 0x2, 0x44D); msleep(200);
356
357         if (!(rtl8225_read(dev, 6) & (1 << 7))) {
358                 rtl8225_write(dev, 0x02, 0x0c4d);
359                 msleep(200);
360                 rtl8225_write(dev, 0x02, 0x044d);
361                 msleep(100);
362                 if (!(rtl8225_read(dev, 6) & (1 << 7)))
363                         printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
364                                wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
365         }
366
367         rtl8225_write(dev, 0x0, 0x127);
368
369         for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
370                 rtl8225_write(dev, 0x1, i + 1);
371                 rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
372         }
373
374         rtl8225_write(dev, 0x0, 0x027);
375         rtl8225_write(dev, 0x0, 0x22F);
376
377         for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
378                 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
379                 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
380         }
381
382         msleep(1);
383
384         rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
385         rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
386         rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
387         rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
388         rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
389         rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
390         rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
391         rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
392         rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
393         rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
394         rtl8225_write_phy_ofdm(dev, 0x0a, 0x09);
395         rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
396         rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
397         rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
398         rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
399         rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
400         rtl8225_write_phy_ofdm(dev, 0x11, 0x06);
401         rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
402         rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
403         rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
404         rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
405         rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
406         rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
407         rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
408         rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
409         rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
410         rtl8225_write_phy_ofdm(dev, 0x1b, 0x76);
411         rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
412         rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
413         rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
414         rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
415         rtl8225_write_phy_ofdm(dev, 0x21, 0x27);
416         rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
417         rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
418         rtl8225_write_phy_ofdm(dev, 0x25, 0x20);
419         rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
420         rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
421
422         rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
423         rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
424         rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
425         rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
426
427         rtl8225_write_phy_cck(dev, 0x00, 0x98);
428         rtl8225_write_phy_cck(dev, 0x03, 0x20);
429         rtl8225_write_phy_cck(dev, 0x04, 0x7e);
430         rtl8225_write_phy_cck(dev, 0x05, 0x12);
431         rtl8225_write_phy_cck(dev, 0x06, 0xfc);
432         rtl8225_write_phy_cck(dev, 0x07, 0x78);
433         rtl8225_write_phy_cck(dev, 0x08, 0x2e);
434         rtl8225_write_phy_cck(dev, 0x10, 0x9b);
435         rtl8225_write_phy_cck(dev, 0x11, 0x88);
436         rtl8225_write_phy_cck(dev, 0x12, 0x47);
437         rtl8225_write_phy_cck(dev, 0x13, 0xd0);
438         rtl8225_write_phy_cck(dev, 0x19, 0x00);
439         rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
440         rtl8225_write_phy_cck(dev, 0x1b, 0x08);
441         rtl8225_write_phy_cck(dev, 0x40, 0x86);
442         rtl8225_write_phy_cck(dev, 0x41, 0x8d);
443         rtl8225_write_phy_cck(dev, 0x42, 0x15);
444         rtl8225_write_phy_cck(dev, 0x43, 0x18);
445         rtl8225_write_phy_cck(dev, 0x44, 0x1f);
446         rtl8225_write_phy_cck(dev, 0x45, 0x1e);
447         rtl8225_write_phy_cck(dev, 0x46, 0x1a);
448         rtl8225_write_phy_cck(dev, 0x47, 0x15);
449         rtl8225_write_phy_cck(dev, 0x48, 0x10);
450         rtl8225_write_phy_cck(dev, 0x49, 0x0a);
451         rtl8225_write_phy_cck(dev, 0x4a, 0x05);
452         rtl8225_write_phy_cck(dev, 0x4b, 0x02);
453         rtl8225_write_phy_cck(dev, 0x4c, 0x05);
454
455         rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
456
457         rtl8225_rf_set_tx_power(dev, 1);
458
459         /* RX antenna default to A */
460         rtl8225_write_phy_cck(dev, 0x10, 0x9b);                 /* B: 0xDB */
461         rtl8225_write_phy_ofdm(dev, 0x26, 0x90);                /* B: 0x10 */
462
463         rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
464         msleep(1);
465         rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
466
467         /* set sensitivity */
468         rtl8225_write(dev, 0x0c, 0x50);
469         rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
470         rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
471         rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
472         rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
473         rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
474 }
475
476 static const u8 rtl8225z2_agc[] = {
477         0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f,
478         0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37,
479         0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f,
480         0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07,
481         0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
482         0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
483         0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28,
484         0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d,
485         0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30,
486         0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
487         0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
488 };
489 static const u8 rtl8225z2_ofdm[] = {
490         0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60,
491         0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
492         0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26,
493         0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3,
494         0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f,
495         0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00,
496         0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e,
497         0x6d, 0x3c, 0xfb, 0x07
498 };
499
500 static const u8 rtl8225z2_tx_power_cck_ch14[] = {
501         0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00,
502         0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
503         0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
504         0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00
505 };
506
507 static const u8 rtl8225z2_tx_power_cck[] = {
508         0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04,
509         0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03,
510         0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03,
511         0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03
512 };
513
514 static const u8 rtl8225z2_tx_power_ofdm[] = {
515         0x42, 0x00, 0x40, 0x00, 0x40
516 };
517
518 static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
519         0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
520         0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
521         0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
522         0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
523         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
524         0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
525 };
526
527 static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
528 {
529         struct rtl8187_priv *priv = dev->priv;
530         u8 cck_power, ofdm_power;
531         const u8 *tmp;
532         u32 reg;
533         int i;
534
535         cck_power = priv->channels[channel - 1].hw_value & 0xF;
536         ofdm_power = priv->channels[channel - 1].hw_value >> 4;
537
538         cck_power = min(cck_power, (u8)15);
539         cck_power += priv->txpwr_base & 0xF;
540         cck_power = min(cck_power, (u8)35);
541
542         if (ofdm_power > (u8)15)
543                 ofdm_power = 25;
544         else
545                 ofdm_power += 10;
546         ofdm_power += priv->txpwr_base >> 4;
547         ofdm_power = min(ofdm_power, (u8)35);
548
549         if (channel == 14)
550                 tmp = rtl8225z2_tx_power_cck_ch14;
551         else
552                 tmp = rtl8225z2_tx_power_cck;
553
554         for (i = 0; i < 8; i++)
555                 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
556
557         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
558                          rtl8225z2_tx_gain_cck_ofdm[cck_power]);
559         msleep(1);
560
561         /* anaparam2 on */
562         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
563         reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
564         rtl818x_iowrite8(priv, &priv->map->CONFIG3,
565                         reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
566         rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
567                           RTL8187_RTL8225_ANAPARAM2_ON);
568         rtl818x_iowrite8(priv, &priv->map->CONFIG3,
569                         reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
570         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
571
572         rtl8225_write_phy_ofdm(dev, 2, 0x42);
573         rtl8225_write_phy_ofdm(dev, 5, 0x00);
574         rtl8225_write_phy_ofdm(dev, 6, 0x40);
575         rtl8225_write_phy_ofdm(dev, 7, 0x00);
576         rtl8225_write_phy_ofdm(dev, 8, 0x40);
577
578         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
579                          rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
580         msleep(1);
581 }
582
583 static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
584 {
585         struct rtl8187_priv *priv = dev->priv;
586         u8 cck_power, ofdm_power;
587         const u8 *tmp;
588         int i;
589
590         cck_power = priv->channels[channel - 1].hw_value & 0xF;
591         ofdm_power = priv->channels[channel - 1].hw_value >> 4;
592
593         if (cck_power > 15)
594                 cck_power = (priv->hw_rev == RTL8187BvB) ? 15 : 22;
595         else
596                 cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7;
597         cck_power += priv->txpwr_base & 0xF;
598         cck_power = min(cck_power, (u8)35);
599
600         if (ofdm_power > 15)
601                 ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25;
602         else
603                 ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10;
604         ofdm_power += (priv->txpwr_base >> 4) & 0xF;
605         ofdm_power = min(ofdm_power, (u8)35);
606
607         if (channel == 14)
608                 tmp = rtl8225z2_tx_power_cck_ch14;
609         else
610                 tmp = rtl8225z2_tx_power_cck;
611
612         if (priv->hw_rev == RTL8187BvB) {
613                 if (cck_power <= 6)
614                         ; /* do nothing */
615                 else if (cck_power <= 11)
616                         tmp += 8;
617                 else
618                         tmp += 16;
619         } else {
620                 if (cck_power <= 5)
621                         ; /* do nothing */
622                 else if (cck_power <= 11)
623                         tmp += 8;
624                 else if (cck_power <= 17)
625                         tmp += 16;
626                 else
627                         tmp += 24;
628         }
629
630         for (i = 0; i < 8; i++)
631                 rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
632
633         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
634                          rtl8225z2_tx_gain_cck_ofdm[cck_power] << 1);
635         msleep(1);
636
637         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
638                          rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1);
639         if (priv->hw_rev == RTL8187BvB) {
640                 if (ofdm_power <= 11) {
641                         rtl8225_write_phy_ofdm(dev, 0x87, 0x60);
642                         rtl8225_write_phy_ofdm(dev, 0x89, 0x60);
643                 } else {
644                         rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
645                         rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
646                 }
647         } else {
648                 if (ofdm_power <= 11) {
649                         rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
650                         rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
651                 } else if (ofdm_power <= 17) {
652                         rtl8225_write_phy_ofdm(dev, 0x87, 0x54);
653                         rtl8225_write_phy_ofdm(dev, 0x89, 0x54);
654                 } else {
655                         rtl8225_write_phy_ofdm(dev, 0x87, 0x50);
656                         rtl8225_write_phy_ofdm(dev, 0x89, 0x50);
657                 }
658         }
659         msleep(1);
660 }
661
662 static const u16 rtl8225z2_rxgain[] = {
663         0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
664         0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
665         0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
666         0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
667         0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
668         0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
669         0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
670         0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
671         0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
672         0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
673         0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
674         0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
675 };
676
677 static const u8 rtl8225z2_gain_bg[] = {
678         0x23, 0x15, 0xa5, /* -82-1dBm */
679         0x23, 0x15, 0xb5, /* -82-2dBm */
680         0x23, 0x15, 0xc5, /* -82-3dBm */
681         0x33, 0x15, 0xc5, /* -78dBm */
682         0x43, 0x15, 0xc5, /* -74dBm */
683         0x53, 0x15, 0xc5, /* -70dBm */
684         0x63, 0x15, 0xc5  /* -66dBm */
685 };
686
687 static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
688 {
689         struct rtl8187_priv *priv = dev->priv;
690         int i;
691
692         rtl8225_write(dev, 0x0, 0x2BF);
693         rtl8225_write(dev, 0x1, 0xEE0);
694         rtl8225_write(dev, 0x2, 0x44D);
695         rtl8225_write(dev, 0x3, 0x441);
696         rtl8225_write(dev, 0x4, 0x8C3);
697         rtl8225_write(dev, 0x5, 0xC72);
698         rtl8225_write(dev, 0x6, 0x0E6);
699         rtl8225_write(dev, 0x7, 0x82A);
700         rtl8225_write(dev, 0x8, 0x03F);
701         rtl8225_write(dev, 0x9, 0x335);
702         rtl8225_write(dev, 0xa, 0x9D4);
703         rtl8225_write(dev, 0xb, 0x7BB);
704         rtl8225_write(dev, 0xc, 0x850);
705         rtl8225_write(dev, 0xd, 0xCDF);
706         rtl8225_write(dev, 0xe, 0x02B);
707         rtl8225_write(dev, 0xf, 0x114);
708         msleep(100);
709
710         rtl8225_write(dev, 0x0, 0x1B7);
711
712         for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
713                 rtl8225_write(dev, 0x1, i + 1);
714                 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
715         }
716
717         rtl8225_write(dev, 0x3, 0x080);
718         rtl8225_write(dev, 0x5, 0x004);
719         rtl8225_write(dev, 0x0, 0x0B7);
720         rtl8225_write(dev, 0x2, 0xc4D);
721
722         msleep(200);
723         rtl8225_write(dev, 0x2, 0x44D);
724         msleep(100);
725
726         if (!(rtl8225_read(dev, 6) & (1 << 7))) {
727                 rtl8225_write(dev, 0x02, 0x0C4D);
728                 msleep(200);
729                 rtl8225_write(dev, 0x02, 0x044D);
730                 msleep(100);
731                 if (!(rtl8225_read(dev, 6) & (1 << 7)))
732                         printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
733                                wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
734         }
735
736         msleep(200);
737
738         rtl8225_write(dev, 0x0, 0x2BF);
739
740         for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
741                 rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
742                 rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
743         }
744
745         msleep(1);
746
747         rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
748         rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
749         rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
750         rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
751         rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
752         rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
753         rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
754         rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
755         rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
756         rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
757         rtl8225_write_phy_ofdm(dev, 0x0a, 0x08);
758         rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
759         rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
760         rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
761         rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
762         rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
763         rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
764         rtl8225_write_phy_ofdm(dev, 0x11, 0x07);
765         rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
766         rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
767         rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
768         rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
769         rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
770         rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
771         rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
772         rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
773         rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
774         rtl8225_write_phy_ofdm(dev, 0x1b, 0x15);
775         rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
776         rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5);
777         rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
778         rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
779         rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
780         rtl8225_write_phy_ofdm(dev, 0x21, 0x17);
781         rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
782         rtl8225_write_phy_ofdm(dev, 0x23, 0x80);
783         rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
784         rtl8225_write_phy_ofdm(dev, 0x25, 0x00);
785         rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
786         rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
787
788         rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
789         rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
790         rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
791         rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
792
793         rtl8225_write_phy_cck(dev, 0x00, 0x98);
794         rtl8225_write_phy_cck(dev, 0x03, 0x20);
795         rtl8225_write_phy_cck(dev, 0x04, 0x7e);
796         rtl8225_write_phy_cck(dev, 0x05, 0x12);
797         rtl8225_write_phy_cck(dev, 0x06, 0xfc);
798         rtl8225_write_phy_cck(dev, 0x07, 0x78);
799         rtl8225_write_phy_cck(dev, 0x08, 0x2e);
800         rtl8225_write_phy_cck(dev, 0x10, 0x9b);
801         rtl8225_write_phy_cck(dev, 0x11, 0x88);
802         rtl8225_write_phy_cck(dev, 0x12, 0x47);
803         rtl8225_write_phy_cck(dev, 0x13, 0xd0);
804         rtl8225_write_phy_cck(dev, 0x19, 0x00);
805         rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
806         rtl8225_write_phy_cck(dev, 0x1b, 0x08);
807         rtl8225_write_phy_cck(dev, 0x40, 0x86);
808         rtl8225_write_phy_cck(dev, 0x41, 0x8d);
809         rtl8225_write_phy_cck(dev, 0x42, 0x15);
810         rtl8225_write_phy_cck(dev, 0x43, 0x18);
811         rtl8225_write_phy_cck(dev, 0x44, 0x36);
812         rtl8225_write_phy_cck(dev, 0x45, 0x35);
813         rtl8225_write_phy_cck(dev, 0x46, 0x2e);
814         rtl8225_write_phy_cck(dev, 0x47, 0x25);
815         rtl8225_write_phy_cck(dev, 0x48, 0x1c);
816         rtl8225_write_phy_cck(dev, 0x49, 0x12);
817         rtl8225_write_phy_cck(dev, 0x4a, 0x09);
818         rtl8225_write_phy_cck(dev, 0x4b, 0x04);
819         rtl8225_write_phy_cck(dev, 0x4c, 0x05);
820
821         rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
822
823         rtl8225z2_rf_set_tx_power(dev, 1);
824
825         /* RX antenna default to A */
826         rtl8225_write_phy_cck(dev, 0x10, 0x9b);                 /* B: 0xDB */
827         rtl8225_write_phy_ofdm(dev, 0x26, 0x90);                /* B: 0x10 */
828
829         rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
830         msleep(1);
831         rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
832 }
833
834 static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
835 {
836         struct rtl8187_priv *priv = dev->priv;
837         int i;
838
839         rtl8225_write(dev, 0x0, 0x0B7);
840         rtl8225_write(dev, 0x1, 0xEE0);
841         rtl8225_write(dev, 0x2, 0x44D);
842         rtl8225_write(dev, 0x3, 0x441);
843         rtl8225_write(dev, 0x4, 0x8C3);
844         rtl8225_write(dev, 0x5, 0xC72);
845         rtl8225_write(dev, 0x6, 0x0E6);
846         rtl8225_write(dev, 0x7, 0x82A);
847         rtl8225_write(dev, 0x8, 0x03F);
848         rtl8225_write(dev, 0x9, 0x335);
849         rtl8225_write(dev, 0xa, 0x9D4);
850         rtl8225_write(dev, 0xb, 0x7BB);
851         rtl8225_write(dev, 0xc, 0x850);
852         rtl8225_write(dev, 0xd, 0xCDF);
853         rtl8225_write(dev, 0xe, 0x02B);
854         rtl8225_write(dev, 0xf, 0x114);
855
856         rtl8225_write(dev, 0x0, 0x1B7);
857
858         for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
859                 rtl8225_write(dev, 0x1, i + 1);
860                 rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
861         }
862
863         rtl8225_write(dev, 0x3, 0x080);
864         rtl8225_write(dev, 0x5, 0x004);
865         rtl8225_write(dev, 0x0, 0x0B7);
866
867         rtl8225_write(dev, 0x2, 0xC4D);
868
869         rtl8225_write(dev, 0x2, 0x44D);
870         rtl8225_write(dev, 0x0, 0x2BF);
871
872         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03);
873         rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07);
874         rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);
875
876         rtl8225_write_phy_ofdm(dev, 0x80, 0x12);
877         for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) {
878                 rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]);
879                 rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i);
880                 rtl8225_write_phy_ofdm(dev, 0xE, 0);
881         }
882         rtl8225_write_phy_ofdm(dev, 0x80, 0x10);
883
884         for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
885                 rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]);
886
887         rtl8225_write_phy_ofdm(dev, 0x97, 0x46);
888         rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6);
889         rtl8225_write_phy_ofdm(dev, 0x85, 0xfc);
890         rtl8225_write_phy_cck(dev, 0xc1, 0x88);
891 }
892
893 static void rtl8225_rf_stop(struct ieee80211_hw *dev)
894 {
895         u8 reg;
896         struct rtl8187_priv *priv = dev->priv;
897
898         rtl8225_write(dev, 0x4, 0x1f);
899
900         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
901         reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
902         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
903         if (!priv->is_rtl8187b) {
904                 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
905                                   RTL8187_RTL8225_ANAPARAM2_OFF);
906                 rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
907                                   RTL8187_RTL8225_ANAPARAM_OFF);
908         } else {
909                 rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
910                                   RTL8187B_RTL8225_ANAPARAM2_OFF);
911                 rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
912                                   RTL8187B_RTL8225_ANAPARAM_OFF);
913                 rtl818x_iowrite8(priv, &priv->map->ANAPARAM3,
914                                   RTL8187B_RTL8225_ANAPARAM3_OFF);
915         }
916         rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
917         rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
918 }
919
920 static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
921                                    struct ieee80211_conf *conf)
922 {
923         struct rtl8187_priv *priv = dev->priv;
924         int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
925
926         if (priv->rf->init == rtl8225_rf_init)
927                 rtl8225_rf_set_tx_power(dev, chan);
928         else if (priv->rf->init == rtl8225z2_rf_init)
929                 rtl8225z2_rf_set_tx_power(dev, chan);
930         else
931                 rtl8225z2_b_rf_set_tx_power(dev, chan);
932
933         rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
934         msleep(10);
935 }
936
937 static const struct rtl818x_rf_ops rtl8225_ops = {
938         .name           = "rtl8225",
939         .init           = rtl8225_rf_init,
940         .stop           = rtl8225_rf_stop,
941         .set_chan       = rtl8225_rf_set_channel
942 };
943
944 static const struct rtl818x_rf_ops rtl8225z2_ops = {
945         .name           = "rtl8225z2",
946         .init           = rtl8225z2_rf_init,
947         .stop           = rtl8225_rf_stop,
948         .set_chan       = rtl8225_rf_set_channel
949 };
950
951 static const struct rtl818x_rf_ops rtl8225z2_b_ops = {
952         .name           = "rtl8225z2",
953         .init           = rtl8225z2_b_rf_init,
954         .stop           = rtl8225_rf_stop,
955         .set_chan       = rtl8225_rf_set_channel
956 };
957
958 const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
959 {
960         u16 reg8, reg9;
961         struct rtl8187_priv *priv = dev->priv;
962
963         if (!priv->is_rtl8187b) {
964                 rtl8225_write(dev, 0, 0x1B7);
965
966                 reg8 = rtl8225_read(dev, 8);
967                 reg9 = rtl8225_read(dev, 9);
968
969                 rtl8225_write(dev, 0, 0x0B7);
970
971                 if (reg8 != 0x588 || reg9 != 0x700)
972                         return &rtl8225_ops;
973
974                 return &rtl8225z2_ops;
975         } else
976                 return &rtl8225z2_b_ops;
977 }