linux/drivers/staging/vt6656/rf.c
<<
>>
Prefs
   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
  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
  85
  86static 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
 100static 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
 114static 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
 131static 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
 148static 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
 165enum {
 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
 173struct vnt_table_info {
 174        u8 *addr;
 175        int length;
 176};
 177
 178static 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 */
 197int 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
 212static 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 */
 232static 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 */
 346int 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 */
 376void 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
 397int 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