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