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