Adapted from Realtek-provided driver... Signed-off-by: John W. Linville <linville@xxxxxxxxxxxxx> --- drivers/net/wireless/rtl818x/rtl8180_dev.c | 18 +++++++++------ drivers/net/wireless/rtl818x/rtl8180_grf5101.c | 12 +++++++++- drivers/net/wireless/rtl818x/rtl8180_max2820.c | 19 +++++++++++++++- drivers/net/wireless/rtl818x/rtl8180_sa2400.c | 28 +++++++++++++++++++++++- drivers/net/wireless/rtl818x/rtl818x.h | 1 + 5 files changed, 68 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 31808f9..d8b186a 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -103,7 +103,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) { struct rtl8180_priv *priv = dev->priv; unsigned int count = 32; - u8 signal; + u8 signal, agc, sq; while (count--) { struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; @@ -132,12 +132,16 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) rx_status.antenna = (flags2 >> 15) & 1; rx_status.rate_idx = (flags >> 20) & 0xF; - /* TODO: improve signal/rssi reporting for !rtl8185 */ - signal = (flags2 >> 17) & 0x7F; - if (rx_status.rate_idx > 3) - signal = 90 - clamp_t(u8, signal, 25, 90); - else - signal = 95 - clamp_t(u8, signal, 30, 95); + agc = (flags2 >> 17) & 0x7F; + if (priv->r8185) { + if (rx_status.rate_idx > 3) + signal = 90 - clamp_t(u8, agc, 25, 90); + else + signal = 95 - clamp_t(u8, agc, 30, 95); + } else { + sq = flags2 & 0xff; + signal = priv->rf->calc_rssi(agc, sq); + } rx_status.signal = signal; rx_status.freq = dev->conf.channel->center_freq; rx_status.band = dev->conf.channel->band; diff --git a/drivers/net/wireless/rtl818x/rtl8180_grf5101.c b/drivers/net/wireless/rtl818x/rtl8180_grf5101.c index 947ee55..5cab9df 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_grf5101.c +++ b/drivers/net/wireless/rtl818x/rtl8180_grf5101.c @@ -69,6 +69,15 @@ static void grf5101_write_phy_antenna(struct ieee80211_hw *dev, short chan) rtl8180_write_phy(dev, 0x10, ant); } +static u8 grf5101_rf_calc_rssi(u8 agc, u8 sq) +{ + if (agc > 60) + return 65; + + /* TODO(?): just return agc (or agc + 5) to avoid mult / div */ + return 65 * agc / 60; +} + static void grf5101_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { @@ -176,5 +185,6 @@ const struct rtl818x_rf_ops grf5101_rf_ops = { .name = "GCT", .init = grf5101_rf_init, .stop = grf5101_rf_stop, - .set_chan = grf5101_rf_set_channel + .set_chan = grf5101_rf_set_channel, + .calc_rssi = grf5101_rf_calc_rssi, }; diff --git a/drivers/net/wireless/rtl818x/rtl8180_max2820.c b/drivers/net/wireless/rtl818x/rtl8180_max2820.c index 6c825fd..16c4655 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_max2820.c +++ b/drivers/net/wireless/rtl818x/rtl8180_max2820.c @@ -74,6 +74,22 @@ static void max2820_write_phy_antenna(struct ieee80211_hw *dev, short chan) rtl8180_write_phy(dev, 0x10, ant); } +static u8 max2820_rf_calc_rssi(u8 agc, u8 sq) +{ + bool odd; + + odd = !!(agc & 1); + + agc >>= 1; + if (odd) + agc += 76; + else + agc += 66; + + /* TODO: change addends above to avoid mult / div below */ + return 65 * agc / 100; +} + static void max2820_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { @@ -148,5 +164,6 @@ const struct rtl818x_rf_ops max2820_rf_ops = { .name = "Maxim", .init = max2820_rf_init, .stop = max2820_rf_stop, - .set_chan = max2820_rf_set_channel + .set_chan = max2820_rf_set_channel, + .calc_rssi = max2820_rf_calc_rssi, }; diff --git a/drivers/net/wireless/rtl818x/rtl8180_sa2400.c b/drivers/net/wireless/rtl818x/rtl8180_sa2400.c index cea4e0c..d064fcc 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_sa2400.c +++ b/drivers/net/wireless/rtl818x/rtl8180_sa2400.c @@ -76,6 +76,31 @@ static void sa2400_write_phy_antenna(struct ieee80211_hw *dev, short chan) } +static u8 sa2400_rf_rssi_map[] = { + 0x64, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, + 0x5d, 0x5c, 0x5b, 0x5a, 0x57, 0x54, 0x52, 0x50, + 0x4e, 0x4c, 0x4a, 0x48, 0x46, 0x44, 0x41, 0x3f, + 0x3c, 0x3a, 0x37, 0x36, 0x36, 0x1c, 0x1c, 0x1b, + 0x1b, 0x1a, 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, + 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, + 0x13, 0x12, 0x12, 0x11, 0x11, 0x10, 0x10, 0x0f, + 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b, + 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07, + 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x02, +}; + +static u8 sa2400_rf_calc_rssi(u8 agc, u8 sq) +{ + if (sq == 0x80) + return 1; + + if (sq > 78) + return 32; + + /* TODO: recalc sa2400_rf_rssi_map to avoid mult / div */ + return 65 * sa2400_rf_rssi_map[sq] / 100; +} + static void sa2400_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { @@ -198,5 +223,6 @@ const struct rtl818x_rf_ops sa2400_rf_ops = { .name = "Philips", .init = sa2400_rf_init, .stop = sa2400_rf_stop, - .set_chan = sa2400_rf_set_channel + .set_chan = sa2400_rf_set_channel, + .calc_rssi = sa2400_rf_calc_rssi, }; diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h index 8522490..22d9384 100644 --- a/drivers/net/wireless/rtl818x/rtl818x.h +++ b/drivers/net/wireless/rtl818x/rtl818x.h @@ -193,6 +193,7 @@ struct rtl818x_rf_ops { void (*stop)(struct ieee80211_hw *); void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *); void (*conf_erp)(struct ieee80211_hw *, struct ieee80211_bss_conf *); + u8 (*calc_rssi)(u8 agc, u8 sq); }; /** -- 1.7.1.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html