1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
8 * Purpose: rf function code
15 * vnt_rf_write_embedded - Embedded write RF register via MAC
18 * RF_VT3226: RobertYu:20051111, VT3226C0 and before
19 * RF_VT3226D0: RobertYu:20051228
20 * RF_VT3342A0: RobertYu:20060609
24 #include <linux/errno.h>
30 #define CB_AL2230_INIT_SEQ 15
31 #define CB_AL7230_INIT_SEQ 16
32 #define CB_VT3226_INIT_SEQ 11
33 #define CB_VT3342_INIT_SEQ 13
35 static u8 al2230_init_table[CB_AL2230_INIT_SEQ][3] = {
53 static u8 al2230_channel_table0[CB_MAX_CHANNEL_24G][3] = {
70 static u8 al2230_channel_table1[CB_MAX_CHANNEL_24G][3] = {
87 static u8 al7230_init_table[CB_AL7230_INIT_SEQ][3] = {
106 static u8 al7230_init_table_amode[CB_AL7230_INIT_SEQ][3] = {
125 static u8 al7230_channel_table0[CB_MAX_CHANNEL][3] = {
140 {0x0f, 0xf5, 0x20}, /* channel 15 Tf = 4915MHz */
184 static u8 al7230_channel_table1[CB_MAX_CHANNEL][3] = {
199 {0x1d, 0x55, 0x51}, /* channel = 15, Tf = 4915MHz */
243 static u8 al7230_channel_table2[CB_MAX_CHANNEL][3] = {
258 {0x7f, 0xd7, 0x84}, /* channel = 15 Tf = 4915MHz */
302 static u8 vt3226_init_table[CB_VT3226_INIT_SEQ][3] = {
316 static u8 vt3226d0_init_table[CB_VT3226_INIT_SEQ][3] = {
330 static u8 vt3226_channel_table0[CB_MAX_CHANNEL_24G][3] = {
347 static u8 vt3226_channel_table1[CB_MAX_CHANNEL_24G][3] = {
364 static const u32 vt3226d0_lo_current_table[CB_MAX_CHANNEL_24G] = {
381 static u8 vt3342a0_init_table[CB_VT3342_INIT_SEQ][3] = { /* 11b/g mode */
397 static u8 vt3342_channel_table0[CB_MAX_CHANNEL][3] = {
412 {0x01, 0x15, 0x13}, /* channel = 15 Tf = 4915MHz */
456 static u8 vt3342_channel_table1[CB_MAX_CHANNEL][3] = {
471 {0x00, 0x44, 0x44}, /* channel = 15 Tf = 4915MHz */
517 VNT_TABLE_INIT_2 = 0,
523 struct vnt_table_info {
528 static const struct vnt_table_info vnt_table_seq[][3] = {
529 { /* RF_AL2230, RF_AL2230S init table, channel table 0 and 1 */
530 {&al2230_init_table[0][0], CB_AL2230_INIT_SEQ * 3},
531 {&al2230_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3},
532 {&al2230_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3}
533 }, { /* RF_AIROHA7230 init table, channel table 0 and 1 */
534 {&al7230_init_table[0][0], CB_AL7230_INIT_SEQ * 3},
535 {&al7230_channel_table0[0][0], CB_MAX_CHANNEL * 3},
536 {&al7230_channel_table1[0][0], CB_MAX_CHANNEL * 3}
537 }, { /* RF_VT3226 init table, channel table 0 and 1 */
538 {&vt3226_init_table[0][0], CB_VT3226_INIT_SEQ * 3},
539 {&vt3226_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3},
540 {&vt3226_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3}
541 }, { /* RF_VT3226D0 init table, channel table 0 and 1 */
542 {&vt3226d0_init_table[0][0], CB_VT3226_INIT_SEQ * 3},
543 {&vt3226_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3},
544 {&vt3226_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3}
545 }, { /* RF_VT3342A0 init table, channel table 0 and 1 */
546 {&vt3342a0_init_table[0][0], CB_VT3342_INIT_SEQ * 3},
547 {&vt3342_channel_table0[0][0], CB_MAX_CHANNEL * 3},
548 {&vt3342_channel_table1[0][0], CB_MAX_CHANNEL * 3}
549 }, { /* RF_AIROHA7230 init table 2 and channel table 2 */
550 {&al7230_init_table_amode[0][0], CB_AL7230_INIT_SEQ * 3},
551 {&al7230_channel_table2[0][0], CB_MAX_CHANNEL * 3},
557 * Description: Write to IF/RF, by embedded programming
559 int vnt_rf_write_embedded(struct vnt_private *priv, u32 data)
563 data |= (VNT_RF_REG_LEN << 3) | IFREGCTL_REGW;
565 reg_data[0] = (u8)data;
566 reg_data[1] = (u8)(data >> 8);
567 reg_data[2] = (u8)(data >> 16);
568 reg_data[3] = (u8)(data >> 24);
570 return vnt_control_out(priv, MESSAGE_TYPE_WRITE_IFRF, 0, 0,
571 ARRAY_SIZE(reg_data), reg_data);
574 static u8 vnt_rf_addpower(struct vnt_private *priv)
577 s32 rssi = -priv->current_rssi;
582 if (priv->rf_type == RF_VT3226D0)
588 return ((rssi - base + 1) / -5) * 2 + 5;
593 /* Set Tx power by power level and rate */
594 static int vnt_rf_set_txpower(struct vnt_private *priv, u8 power,
595 struct ieee80211_channel *ch)
597 u32 power_setting = 0;
600 power += vnt_rf_addpower(priv);
601 if (power > VNT_RF_MAX_POWER)
602 power = VNT_RF_MAX_POWER;
604 if (priv->power == power)
609 switch (priv->rf_type) {
611 power_setting = 0x0404090 | (power << 12);
613 ret = vnt_rf_write_embedded(priv, power_setting);
617 if (ch->flags & IEEE80211_CHAN_NO_OFDM)
618 ret = vnt_rf_write_embedded(priv, 0x0001b400);
620 ret = vnt_rf_write_embedded(priv, 0x0005a400);
624 power_setting = 0x0404090 | (power << 12);
626 ret = vnt_rf_write_embedded(priv, power_setting);
630 if (ch->flags & IEEE80211_CHAN_NO_OFDM) {
631 ret = vnt_rf_write_embedded(priv, 0x040c1400);
635 ret = vnt_rf_write_embedded(priv, 0x00299b00);
637 ret = vnt_rf_write_embedded(priv, 0x0005a400);
641 ret = vnt_rf_write_embedded(priv, 0x00099b00);
647 if (ch->flags & IEEE80211_CHAN_NO_OFDM)
648 ret = vnt_rf_write_embedded(priv, 0x111bb900);
650 ret = vnt_rf_write_embedded(priv, 0x221bb900);
656 * 0x080F1B00 for 3 wire control TxGain(D10)
657 * and 0x31 as TX Gain value
659 power_setting = 0x080c0b00 | (power << 12);
661 ret = vnt_rf_write_embedded(priv, power_setting);
665 power_setting = ((0x3f - power) << 20) | (0x17 << 8);
667 ret = vnt_rf_write_embedded(priv, power_setting);
670 if (ch->flags & IEEE80211_CHAN_NO_OFDM) {
671 u16 hw_value = ch->hw_value;
673 power_setting = ((0x3f - power) << 20) | (0xe07 << 8);
675 ret = vnt_rf_write_embedded(priv, power_setting);
679 ret = vnt_rf_write_embedded(priv, 0x03c6a200);
683 dev_dbg(&priv->usb->dev,
684 "%s 11b channel [%d]\n", __func__, hw_value);
688 if (hw_value < ARRAY_SIZE(vt3226d0_lo_current_table)) {
689 ret = vnt_rf_write_embedded(priv,
690 vt3226d0_lo_current_table[hw_value]);
695 ret = vnt_rf_write_embedded(priv, 0x015C0800);
697 dev_dbg(&priv->usb->dev,
698 "@@@@ %s> 11G mode\n", __func__);
700 power_setting = ((0x3f - power) << 20) | (0x7 << 8);
702 ret = vnt_rf_write_embedded(priv, power_setting);
706 ret = vnt_rf_write_embedded(priv, 0x00C6A200);
710 ret = vnt_rf_write_embedded(priv, 0x016BC600);
714 ret = vnt_rf_write_embedded(priv, 0x00900800);
720 power_setting = ((0x3f - power) << 20) | (0x27 << 8);
722 ret = vnt_rf_write_embedded(priv, power_setting);
730 /* Set Tx power by channel number type */
731 int vnt_rf_setpower(struct vnt_private *priv,
732 struct ieee80211_channel *ch)
735 u8 power = priv->cck_pwr;
740 /* set channel number to array number */
741 channel = ch->hw_value - 1;
743 if (ch->flags & IEEE80211_CHAN_NO_OFDM) {
744 if (channel < ARRAY_SIZE(priv->cck_pwr_tbl))
745 power = priv->cck_pwr_tbl[channel];
746 } else if (ch->band == NL80211_BAND_5GHZ) {
747 /* remove 14 channels to array size */
750 if (channel < ARRAY_SIZE(priv->ofdm_a_pwr_tbl))
751 power = priv->ofdm_a_pwr_tbl[channel];
753 if (channel < ARRAY_SIZE(priv->ofdm_pwr_tbl))
754 power = priv->ofdm_pwr_tbl[channel];
757 return vnt_rf_set_txpower(priv, power, ch);
760 /* Convert rssi to dbm */
761 void vnt_rf_rssi_to_dbm(struct vnt_private *priv, u8 rssi, long *dbm)
763 u8 idx = ((rssi & 0xc0) >> 6) & 0x03;
764 long b = rssi & 0x3f;
766 u8 airoharf[4] = {0, 18, 0, 40};
768 switch (priv->rf_type) {
781 *dbm = -1 * (a + b * 2);
784 int vnt_rf_table_download(struct vnt_private *priv)
788 const struct vnt_table_info *table_seq;
790 switch (priv->rf_type) {
812 table_seq = &vnt_table_seq[idx][0];
815 ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
816 MESSAGE_REQUEST_RF_INIT,
817 table_seq[VNT_TABLE_INIT].length,
818 table_seq[VNT_TABLE_INIT].addr);
822 /* Channel Table 0 */
823 ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE,
824 MESSAGE_REQUEST_RF_CH0,
825 table_seq[VNT_TABLE_0].length,
826 table_seq[VNT_TABLE_0].addr);
830 /* Channel Table 1 */
831 ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE,
832 MESSAGE_REQUEST_RF_CH1,
833 table_seq[VNT_TABLE_1].length,
834 table_seq[VNT_TABLE_1].addr);
836 if (priv->rf_type == RF_AIROHA7230) {
837 table_seq = &vnt_table_seq[5][0];
840 ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
841 MESSAGE_REQUEST_RF_INIT2,
842 table_seq[VNT_TABLE_INIT_2].length,
843 table_seq[VNT_TABLE_INIT_2].addr);
847 /* Channel Table 2 */
848 ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE,
849 MESSAGE_REQUEST_RF_CH2,
850 table_seq[VNT_TABLE_2].length,
851 table_seq[VNT_TABLE_2].addr);