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 } 962