1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. 4 * All rights reserved. 5 * 6 * Purpose: rf function code 7 * 8 * Author: Jerry Chen 9 * 10 * Date: Feb. 19, 2004 11 * 12 * Functions: 13 * vnt_rf_write_embedded - Embedded write RF register via MAC 14 * 15 * Revision History: 16 * RF_VT3226: RobertYu:20051111, VT3226C0 and before 17 * RF_VT3226D0: RobertYu:20051228 18 * RF_VT3342A0: RobertYu:20060609 19 * 20 */ 21 22 #include <linux/errno.h> 23 #include "mac.h" 24 #include "rf.h" 25 #include "baseband.h" 26 #include "usbpipe.h" 27 28 #define CB_AL2230_INIT_SEQ 15 29 #define CB_AL7230_INIT_SEQ 16 30 #define CB_VT3226_INIT_SEQ 11 31 #define CB_VT3342_INIT_SEQ 13 32 33 static u8 al2230_init_table[CB_AL2230_INIT_SEQ][3] = { 34 {0x03, 0xf7, 0x90}, 35 {0x03, 0x33, 0x31}, 36 {0x01, 0xb8, 0x02}, 37 {0x00, 0xff, 0xf3}, 38 {0x00, 0x05, 0xa4}, 39 {0x0f, 0x4d, 0xc5}, 40 {0x08, 0x05, 0xb6}, 41 {0x01, 0x47, 0xc7}, 42 {0x00, 0x06, 0x88}, 43 {0x04, 0x03, 0xb9}, 44 {0x00, 0xdb, 0xba}, 45 {0x00, 0x09, 0x9b}, 46 {0x0b, 0xdf, 0xfc}, 47 {0x00, 0x00, 0x0d}, 48 {0x00, 0x58, 0x0f} 49 }; 50 51 static u8 al2230_channel_table0[CB_MAX_CHANNEL_24G][3] = { 52 {0x03, 0xf7, 0x90}, 53 {0x03, 0xf7, 0x90}, 54 {0x03, 0xe7, 0x90}, 55 {0x03, 0xe7, 0x90}, 56 {0x03, 0xf7, 0xa0}, 57 {0x03, 0xf7, 0xa0}, 58 {0x03, 0xe7, 0xa0}, 59 {0x03, 0xe7, 0xa0}, 60 {0x03, 0xf7, 0xb0}, 61 {0x03, 0xf7, 0xb0}, 62 {0x03, 0xe7, 0xb0}, 63 {0x03, 0xe7, 0xb0}, 64 {0x03, 0xf7, 0xc0}, 65 {0x03, 0xe7, 0xc0} 66 }; 67 68 static u8 al2230_channel_table1[CB_MAX_CHANNEL_24G][3] = { 69 {0x03, 0x33, 0x31}, 70 {0x0b, 0x33, 0x31}, 71 {0x03, 0x33, 0x31}, 72 {0x0b, 0x33, 0x31}, 73 {0x03, 0x33, 0x31}, 74 {0x0b, 0x33, 0x31}, 75 {0x03, 0x33, 0x31}, 76 {0x0b, 0x33, 0x31}, 77 {0x03, 0x33, 0x31}, 78 {0x0b, 0x33, 0x31}, 79 {0x03, 0x33, 0x31}, 80 {0x0b, 0x33, 0x31}, 81 {0x03, 0x33, 0x31}, 82 {0x06, 0x66, 0x61} 83 }; 84 85 86 static u8 vt3226_init_table[CB_VT3226_INIT_SEQ][3] = { 87 {0x03, 0xff, 0x80}, 88 {0x02, 0x82, 0xa1}, 89 {0x03, 0xc6, 0xa2}, 90 {0x01, 0x97, 0x93}, 91 {0x03, 0x66, 0x64}, 92 {0x00, 0x61, 0xa5}, 93 {0x01, 0x7b, 0xd6}, 94 {0x00, 0x80, 0x17}, 95 {0x03, 0xf8, 0x08}, 96 {0x00, 0x02, 0x39}, 97 {0x02, 0x00, 0x2a} 98 }; 99 100 static u8 vt3226d0_init_table[CB_VT3226_INIT_SEQ][3] = { 101 {0x03, 0xff, 0x80}, 102 {0x03, 0x02, 0x21}, 103 {0x03, 0xc6, 0xa2}, 104 {0x01, 0x97, 0x93}, 105 {0x03, 0x66, 0x64}, 106 {0x00, 0x71, 0xa5}, 107 {0x01, 0x15, 0xc6}, 108 {0x01, 0x2e, 0x07}, 109 {0x00, 0x58, 0x08}, 110 {0x00, 0x02, 0x79}, 111 {0x02, 0x01, 0xaa} 112 }; 113 114 static u8 vt3226_channel_table0[CB_MAX_CHANNEL_24G][3] = { 115 {0x01, 0x97, 0x83}, 116 {0x01, 0x97, 0x83}, 117 {0x01, 0x97, 0x93}, 118 {0x01, 0x97, 0x93}, 119 {0x01, 0x97, 0x93}, 120 {0x01, 0x97, 0x93}, 121 {0x01, 0x97, 0xa3}, 122 {0x01, 0x97, 0xa3}, 123 {0x01, 0x97, 0xa3}, 124 {0x01, 0x97, 0xa3}, 125 {0x01, 0x97, 0xb3}, 126 {0x01, 0x97, 0xb3}, 127 {0x01, 0x97, 0xb3}, 128 {0x03, 0x37, 0xc3} 129 }; 130 131 static u8 vt3226_channel_table1[CB_MAX_CHANNEL_24G][3] = { 132 {0x02, 0x66, 0x64}, 133 {0x03, 0x66, 0x64}, 134 {0x00, 0x66, 0x64}, 135 {0x01, 0x66, 0x64}, 136 {0x02, 0x66, 0x64}, 137 {0x03, 0x66, 0x64}, 138 {0x00, 0x66, 0x64}, 139 {0x01, 0x66, 0x64}, 140 {0x02, 0x66, 0x64}, 141 {0x03, 0x66, 0x64}, 142 {0x00, 0x66, 0x64}, 143 {0x01, 0x66, 0x64}, 144 {0x02, 0x66, 0x64}, 145 {0x00, 0xcc, 0xc4} 146 }; 147 148 static const u32 vt3226d0_lo_current_table[CB_MAX_CHANNEL_24G] = { 149 0x0135c600, 150 0x0135c600, 151 0x0235c600, 152 0x0235c600, 153 0x0235c600, 154 0x0335c600, 155 0x0335c600, 156 0x0335c600, 157 0x0335c600, 158 0x0335c600, 159 0x0335c600, 160 0x0335c600, 161 0x0335c600, 162 0x0135c600 163 }; 164 165 enum { 166 VNT_TABLE_INIT = 0, 167 VNT_TABLE_INIT_2 = 0, 168 VNT_TABLE_0 = 1, 169 VNT_TABLE_1 = 2, 170 VNT_TABLE_2 = 1 171 }; 172 173 struct vnt_table_info { 174 u8 *addr; 175 int length; 176 }; 177 178 static const struct vnt_table_info vnt_table_seq[][3] = { 179 { /* RF_AL2230, RF_AL2230S init table, channel table 0 and 1 */ 180 {&al2230_init_table[0][0], CB_AL2230_INIT_SEQ * 3}, 181 {&al2230_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3}, 182 {&al2230_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3} 183 }, { /* RF_VT3226 init table, channel table 0 and 1 */ 184 {&vt3226_init_table[0][0], CB_VT3226_INIT_SEQ * 3}, 185 {&vt3226_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3}, 186 {&vt3226_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3} 187 }, { /* RF_VT3226D0 init table, channel table 0 and 1 */ 188 {&vt3226d0_init_table[0][0], CB_VT3226_INIT_SEQ * 3}, 189 {&vt3226_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3}, 190 {&vt3226_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3} 191 } 192 }; 193 194 /* 195 * Description: Write to IF/RF, by embedded programming 196 */ 197 int vnt_rf_write_embedded(struct vnt_private *priv, u32 data) 198 { 199 u8 reg_data[4]; 200 201 data |= (VNT_RF_REG_LEN << 3) | IFREGCTL_REGW; 202 203 reg_data[0] = (u8)data; 204 reg_data[1] = (u8)(data >> 8); 205 reg_data[2] = (u8)(data >> 16); 206 reg_data[3] = (u8)(data >> 24); 207 208 return vnt_control_out(priv, MESSAGE_TYPE_WRITE_IFRF, 0, 0, 209 ARRAY_SIZE(reg_data), reg_data); 210 } 211 212 static u8 vnt_rf_addpower(struct vnt_private *priv) 213 { 214 int base; 215 s32 rssi = -priv->current_rssi; 216 217 if (!rssi) 218 return 7; 219 220 if (priv->rf_type == RF_VT3226D0) 221 base = -60; 222 else 223 base = -70; 224 225 if (rssi < base) 226 return ((rssi - base + 1) / -5) * 2 + 5; 227 228 return 0; 229 } 230 231 /* Set Tx power by power level and rate */ 232 static int vnt_rf_set_txpower(struct vnt_private *priv, u8 power, 233 struct ieee80211_channel *ch) 234 { 235 u32 power_setting = 0; 236 int ret = 0; 237 238 power += vnt_rf_addpower(priv); 239 if (power > VNT_RF_MAX_POWER) 240 power = VNT_RF_MAX_POWER; 241 242 if (priv->power == power) 243 return 0; 244 245 priv->power = power; 246 247 switch (priv->rf_type) { 248 case RF_AL2230: 249 power_setting = 0x0404090 | (power << 12); 250 251 ret = vnt_rf_write_embedded(priv, power_setting); 252 if (ret) 253 return ret; 254 255 if (ch->flags & IEEE80211_CHAN_NO_OFDM) 256 ret = vnt_rf_write_embedded(priv, 0x0001b400); 257 else 258 ret = vnt_rf_write_embedded(priv, 0x0005a400); 259 260 break; 261 case RF_AL2230S: 262 power_setting = 0x0404090 | (power << 12); 263 264 ret = vnt_rf_write_embedded(priv, power_setting); 265 if (ret) 266 return ret; 267 268 if (ch->flags & IEEE80211_CHAN_NO_OFDM) { 269 ret = vnt_rf_write_embedded(priv, 0x040c1400); 270 if (ret) 271 return ret; 272 273 ret = vnt_rf_write_embedded(priv, 0x00299b00); 274 } else { 275 ret = vnt_rf_write_embedded(priv, 0x0005a400); 276 if (ret) 277 return ret; 278 279 ret = vnt_rf_write_embedded(priv, 0x00099b00); 280 } 281 282 break; 283 284 case RF_VT3226: 285 power_setting = ((0x3f - power) << 20) | (0x17 << 8); 286 287 ret = vnt_rf_write_embedded(priv, power_setting); 288 break; 289 case RF_VT3226D0: 290 if (ch->flags & IEEE80211_CHAN_NO_OFDM) { 291 u16 hw_value = ch->hw_value; 292 293 power_setting = ((0x3f - power) << 20) | (0xe07 << 8); 294 295 ret = vnt_rf_write_embedded(priv, power_setting); 296 if (ret) 297 return ret; 298 299 ret = vnt_rf_write_embedded(priv, 0x03c6a200); 300 if (ret) 301 return ret; 302 303 dev_dbg(&priv->usb->dev, 304 "%s 11b channel [%d]\n", __func__, hw_value); 305 306 hw_value--; 307 308 if (hw_value < ARRAY_SIZE(vt3226d0_lo_current_table)) { 309 ret = vnt_rf_write_embedded(priv, 310 vt3226d0_lo_current_table[hw_value]); 311 if (ret) 312 return ret; 313 } 314 315 ret = vnt_rf_write_embedded(priv, 0x015C0800); 316 } else { 317 dev_dbg(&priv->usb->dev, 318 "@@@@ %s> 11G mode\n", __func__); 319 320 power_setting = ((0x3f - power) << 20) | (0x7 << 8); 321 322 ret = vnt_rf_write_embedded(priv, power_setting); 323 if (ret) 324 return ret; 325 326 ret = vnt_rf_write_embedded(priv, 0x00C6A200); 327 if (ret) 328 return ret; 329 330 ret = vnt_rf_write_embedded(priv, 0x016BC600); 331 if (ret) 332 return ret; 333 334 ret = vnt_rf_write_embedded(priv, 0x00900800); 335 } 336 337 break; 338 339 default: 340 break; 341 } 342 return ret; 343 } 344 345 /* Set Tx power by channel number type */ 346 int vnt_rf_setpower(struct vnt_private *priv, 347 struct ieee80211_channel *ch) 348 { 349 u16 channel; 350 u8 power = priv->cck_pwr; 351 352 if (!ch) 353 return -EINVAL; 354 355 /* set channel number to array number */ 356 channel = ch->hw_value - 1; 357 358 if (ch->flags & IEEE80211_CHAN_NO_OFDM) { 359 if (channel < ARRAY_SIZE(priv->cck_pwr_tbl)) 360 power = priv->cck_pwr_tbl[channel]; 361 } else if (ch->band == NL80211_BAND_5GHZ) { 362 /* remove 14 channels to array size */ 363 channel -= 14; 364 365 if (channel < ARRAY_SIZE(priv->ofdm_a_pwr_tbl)) 366 power = priv->ofdm_a_pwr_tbl[channel]; 367 } else { 368 if (channel < ARRAY_SIZE(priv->ofdm_pwr_tbl)) 369 power = priv->ofdm_pwr_tbl[channel]; 370 } 371 372 return vnt_rf_set_txpower(priv, power, ch); 373 } 374 375 /* Convert rssi to dbm */ 376 void vnt_rf_rssi_to_dbm(struct vnt_private *priv, u8 rssi, long *dbm) 377 { 378 u8 idx = ((rssi & 0xc0) >> 6) & 0x03; 379 long b = rssi & 0x3f; 380 long a = 0; 381 u8 airoharf[4] = {0, 18, 0, 40}; 382 383 switch (priv->rf_type) { 384 case RF_AL2230: 385 case RF_AL2230S: 386 case RF_VT3226: 387 case RF_VT3226D0: 388 a = airoharf[idx]; 389 break; 390 default: 391 break; 392 } 393 394 *dbm = -1 * (a + b * 2); 395 } 396 397 int vnt_rf_table_download(struct vnt_private *priv) 398 { 399 int ret; 400 int idx = -1; 401 const struct vnt_table_info *table_seq; 402 403 switch (priv->rf_type) { 404 case RF_AL2230: 405 case RF_AL2230S: 406 idx = 0; 407 break; 408 case RF_VT3226: 409 idx = 1; 410 break; 411 case RF_VT3226D0: 412 idx = 2; 413 break; 414 } 415 416 if (idx < 0) 417 return 0; 418 419 table_seq = &vnt_table_seq[idx][0]; 420 421 /* Init Table */ 422 ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0, 423 MESSAGE_REQUEST_RF_INIT, 424 table_seq[VNT_TABLE_INIT].length, 425 table_seq[VNT_TABLE_INIT].addr); 426 if (ret) 427 return ret; 428 429 /* Channel Table 0 */ 430 ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE, 431 MESSAGE_REQUEST_RF_CH0, 432 table_seq[VNT_TABLE_0].length, 433 table_seq[VNT_TABLE_0].addr); 434 if (ret) 435 return ret; 436 437 /* Channel Table 1 */ 438 ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE, 439 MESSAGE_REQUEST_RF_CH1, 440 table_seq[VNT_TABLE_1].length, 441 table_seq[VNT_TABLE_1].addr); 442 443 return ret; 444 } 445