Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e7d414ff authored by Hin-Tak Leung's avatar Hin-Tak Leung Committed by John W. Linville
Browse files

rtl8187: updating rtl8187_rtl8225.c to support RTL8187B

parent d1e11af5
Loading
Loading
Loading
Loading
+215 −14
Original line number Diff line number Diff line
@@ -305,9 +305,11 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
	/* anaparam2 on */
	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
	rtl818x_iowrite8(priv, &priv->map->CONFIG3,
			reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
	rtl818x_iowrite8(priv, &priv->map->CONFIG3,
			reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);

	rtl8225_write_phy_ofdm(dev, 2, 0x42);
@@ -471,12 +473,42 @@ static void rtl8225_rf_init(struct ieee80211_hw *dev)
	rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
}

static const u8 rtl8225z2_agc[] = {
	0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f,
	0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37,
	0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f,
	0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07,
	0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
	0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
	0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28,
	0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d,
	0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30,
	0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
	0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
};
static const u8 rtl8225z2_ofdm[] = {
	0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60,
	0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
	0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26,
	0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3,
	0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f,
	0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00,
	0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e,
	0x6d, 0x3c, 0xfb, 0x07
};

static const u8 rtl8225z2_tx_power_cck_ch14[] = {
	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00,
	0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
	0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
	0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00
};

static const u8 rtl8225z2_tx_power_cck[] = {
	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04,
	0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03,
	0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03,
	0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03
};

static const u8 rtl8225z2_tx_power_ofdm[] = {
@@ -526,9 +558,11 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
	/* anaparam2 on */
	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
	rtl818x_iowrite8(priv, &priv->map->CONFIG3,
			reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
	rtl818x_iowrite8(priv, &priv->map->CONFIG3,
			reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);

	rtl8225_write_phy_ofdm(dev, 2, 0x42);
@@ -542,6 +576,85 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
	msleep(1);
}

static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
{
	struct rtl8187_priv *priv = dev->priv;
	u8 cck_power, ofdm_power;
	const u8 *tmp;
	int i;

	cck_power = priv->channels[channel - 1].hw_value & 0xF;
	ofdm_power = priv->channels[channel - 1].hw_value >> 4;

	if (cck_power > 15)
		cck_power = (priv->hw_rev == RTL8187BvB) ? 15 : 22;
	else
		cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7;
	cck_power += priv->txpwr_base & 0xF;
	cck_power = min(cck_power, (u8)35);

	if (ofdm_power > 15)
		ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25;
	else
		ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10;
	ofdm_power += (priv->txpwr_base >> 4) & 0xF;
	ofdm_power = min(ofdm_power, (u8)35);

	if (channel == 14)
		tmp = rtl8225z2_tx_power_cck_ch14;
	else
		tmp = rtl8225z2_tx_power_cck;

	if (priv->hw_rev == RTL8187BvB) {
		if (cck_power <= 6)
			; /* do nothing */
		else if (cck_power <= 11)
			tmp += 8;
		else
			tmp += 16;
	} else {
		if (cck_power <= 5)
			; /* do nothing */
		else if (cck_power <= 11)
			tmp += 8;
		else if (cck_power <= 17)
			tmp += 16;
		else
			tmp += 24;
	}

	for (i = 0; i < 8; i++)
		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);

	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
			 rtl8225z2_tx_gain_cck_ofdm[cck_power]);
	msleep(1);

	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
			 rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1);
	if (priv->hw_rev == RTL8187BvB) {
		if (ofdm_power <= 11) {
			rtl8225_write_phy_ofdm(dev, 0x87, 0x60);
			rtl8225_write_phy_ofdm(dev, 0x89, 0x60);
		} else {
			rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
			rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
		}
	} else {
		if (ofdm_power <= 11) {
			rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
			rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
		} else if (ofdm_power <= 17) {
			rtl8225_write_phy_ofdm(dev, 0x87, 0x54);
			rtl8225_write_phy_ofdm(dev, 0x89, 0x54);
		} else {
			rtl8225_write_phy_ofdm(dev, 0x87, 0x50);
			rtl8225_write_phy_ofdm(dev, 0x89, 0x50);
		}
	}
	msleep(1);
}

static const u16 rtl8225z2_rxgain[] = {
	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
@@ -715,6 +828,81 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
	rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
}

static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
{
	struct rtl8187_priv *priv = dev->priv;
	int i;

	rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
	rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
	rtl8225_write(dev, 0x2, 0x44D); msleep(1);
	rtl8225_write(dev, 0x3, 0x441); msleep(1);
	rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
	rtl8225_write(dev, 0x5, 0xC72); msleep(1);
	rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
	rtl8225_write(dev, 0x7, 0x82A); msleep(1);
	rtl8225_write(dev, 0x8, 0x03F); msleep(1);
	rtl8225_write(dev, 0x9, 0x335); msleep(1);
	rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
	rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
	rtl8225_write(dev, 0xc, 0x850); msleep(1);
	rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
	rtl8225_write(dev, 0xe, 0x02B); msleep(1);
	rtl8225_write(dev, 0xf, 0x114); msleep(1);

	rtl8225_write(dev, 0x0, 0x1B7); msleep(1);

	for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
		rtl8225_write(dev, 0x1, i + 1); msleep(1);
		rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); msleep(1);
	}

	rtl8225_write(dev, 0x3, 0x080); msleep(1);
	rtl8225_write(dev, 0x5, 0x004); msleep(1);
	rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
	msleep(3000);

	rtl8225_write(dev, 0x2, 0xC4D); msleep(1);
	msleep(2000);

	rtl8225_write(dev, 0x2, 0x44D); msleep(1);
	rtl8225_write(dev, 0x0, 0x2BF); msleep(1);

	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03);
	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07);
	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);

	rtl8225_write_phy_ofdm(dev, 0x80, 0x12);
	for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) {
		rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]);
		rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i);
		rtl8225_write_phy_ofdm(dev, 0xE, 0);
	}
	rtl8225_write_phy_ofdm(dev, 0x80, 0x10);

	for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
		rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]);

	rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
	rtl818x_iowrite8(priv, &priv->map->SLOT, 9);
	rtl818x_iowrite8(priv, (u8 *)0xFFF0, 28);
	rtl818x_iowrite8(priv, (u8 *)0xFFF4, 28);
	rtl818x_iowrite8(priv, (u8 *)0xFFF8, 28);
	rtl818x_iowrite8(priv, (u8 *)0xFFFC, 28);
	rtl818x_iowrite8(priv, (u8 *)0xFF2D, 0x5B);
	rtl818x_iowrite8(priv, (u8 *)0xFF79, 0x5B);
	rtl818x_iowrite32(priv, (__le32 *)0xFFF0, (7 << 12) | (3 << 8) | 28);
	rtl818x_iowrite32(priv, (__le32 *)0xFFF4, (7 << 12) | (3 << 8) | 28);
	rtl818x_iowrite32(priv, (__le32 *)0xFFF8, (7 << 12) | (3 << 8) | 28);
	rtl818x_iowrite32(priv, (__le32 *)0xFFFC, (7 << 12) | (3 << 8) | 28);
	rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0);

	rtl8225_write_phy_ofdm(dev, 0x97, 0x46); msleep(1);
	rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6); msleep(1);
	rtl8225_write_phy_ofdm(dev, 0x85, 0xfc); msleep(1);
	rtl8225_write_phy_cck(dev, 0xc1, 0x88); msleep(1);
}

static void rtl8225_rf_stop(struct ieee80211_hw *dev)
{
	u8 reg;
@@ -739,8 +927,10 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,

	if (priv->rf->init == rtl8225_rf_init)
		rtl8225_rf_set_tx_power(dev, chan);
	else
	else if (priv->rf->init == rtl8225z2_rf_init)
		rtl8225z2_rf_set_tx_power(dev, chan);
	else
		rtl8225z2_b_rf_set_tx_power(dev, chan);

	rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
	msleep(10);
@@ -760,10 +950,19 @@ static const struct rtl818x_rf_ops rtl8225z2_ops = {
	.set_chan	= rtl8225_rf_set_channel
};

static const struct rtl818x_rf_ops rtl8225z2_b_ops = {
	.name		= "rtl8225z2",
	.init		= rtl8225z2_b_rf_init,
	.stop		= rtl8225_rf_stop,
	.set_chan	= rtl8225_rf_set_channel
};

const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
{
	u16 reg8, reg9;
	struct rtl8187_priv *priv = dev->priv;

	if (!priv->is_rtl8187b) {
		rtl8225_write(dev, 0, 0x1B7);

		reg8 = rtl8225_read(dev, 8);
@@ -775,4 +974,6 @@ const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
			return &rtl8225_ops;

		return &rtl8225z2_ops;
	} else
		return &rtl8225z2_b_ops;
}