Commit 69ba3e5d authored by Christian Lamparter's avatar Christian Lamparter Committed by John W. Linville

p54: more accurate rssi to dBm conversion

This patch replaces the static rssi auto calibration data
with more precise values out of the device's eeprom.
Signed-off-by: default avatarChristian Lamparter <chunkeey@web.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent da9f57ea
...@@ -61,6 +61,13 @@ struct p54_edcf_queue_param { ...@@ -61,6 +61,13 @@ struct p54_edcf_queue_param {
__le16 txop; __le16 txop;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct p54_rssi_linear_approximation {
s16 mul;
s16 add;
s16 longbow_unkn;
s16 longbow_unk2;
};
#define EEPROM_READBACK_LEN 0x3fc #define EEPROM_READBACK_LEN 0x3fc
#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000 #define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
...@@ -91,6 +98,7 @@ struct p54_common { ...@@ -91,6 +98,7 @@ struct p54_common {
struct pda_channel_output_limit *output_limit; struct pda_channel_output_limit *output_limit;
unsigned int output_limit_len; unsigned int output_limit_len;
struct pda_pa_curve_data *curve_data; struct pda_pa_curve_data *curve_data;
struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS];
unsigned int filter_flags; unsigned int filter_flags;
bool use_short_slot; bool use_short_slot;
u16 rxhw; u16 rxhw;
......
...@@ -335,6 +335,36 @@ static const char *p54_rf_chips[] = { "NULL", "Duette3", "Duette2", ...@@ -335,6 +335,36 @@ static const char *p54_rf_chips[] = { "NULL", "Duette3", "Duette2",
"Frisbee", "Xbow", "Longbow", "NULL", "NULL" }; "Frisbee", "Xbow", "Longbow", "NULL", "NULL" };
static int p54_init_xbow_synth(struct ieee80211_hw *dev); static int p54_init_xbow_synth(struct ieee80211_hw *dev);
static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len,
u16 type)
{
struct p54_common *priv = dev->priv;
int offset = (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) ? 2 : 0;
int entry_size = sizeof(struct pda_rssi_cal_entry) + offset;
int num_entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2;
int i;
if (len != (entry_size * num_entries)) {
printk(KERN_ERR "%s: unknown rssi calibration data packing "
" type:(%x) len:%d.\n",
wiphy_name(dev->wiphy), type, len);
print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE,
data, len);
printk(KERN_ERR "%s: please report this issue.\n",
wiphy_name(dev->wiphy));
return;
}
for (i = 0; i < num_entries; i++) {
struct pda_rssi_cal_entry *cal = data +
(offset + i * entry_size);
priv->rssical_db[i].mul = (s16) le16_to_cpu(cal->mul);
priv->rssical_db[i].add = (s16) le16_to_cpu(cal->add);
}
}
static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
{ {
struct p54_common *priv = dev->priv; struct p54_common *priv = dev->priv;
...@@ -434,6 +464,12 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) ...@@ -434,6 +464,12 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
case PDR_HARDWARE_PLATFORM_COMPONENT_ID: case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
priv->version = *(u8 *)(entry->data + 1); priv->version = *(u8 *)(entry->data + 1);
break; break;
case PDR_RSSI_LINEAR_APPROXIMATION:
case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND:
case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED:
p54_parse_rssical(dev, entry->data, data_len,
le16_to_cpu(entry->code));
break;
case PDR_END: case PDR_END:
/* make it overrun */ /* make it overrun */
entry_len = len; entry_len = len;
...@@ -453,10 +489,7 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) ...@@ -453,10 +489,7 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
case PDR_DEFAULT_COUNTRY: case PDR_DEFAULT_COUNTRY:
case PDR_ANTENNA_GAIN: case PDR_ANTENNA_GAIN:
case PDR_PRISM_INDIGO_PA_CALIBRATION_DATA: case PDR_PRISM_INDIGO_PA_CALIBRATION_DATA:
case PDR_RSSI_LINEAR_APPROXIMATION:
case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND:
case PDR_REGULATORY_POWER_LIMITS: case PDR_REGULATORY_POWER_LIMITS:
case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED:
case PDR_RADIATED_TRANSMISSION_CORRECTION: case PDR_RADIATED_TRANSMISSION_CORRECTION:
case PDR_PRISM_TX_IQ_CALIBRATION: case PDR_PRISM_TX_IQ_CALIBRATION:
case PDR_BASEBAND_REGISTERS: case PDR_BASEBAND_REGISTERS:
...@@ -527,8 +560,11 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) ...@@ -527,8 +560,11 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi) static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi)
{ {
/* TODO: get the rssi_add & rssi_mul data from the eeprom */ struct p54_common *priv = dev->priv;
return ((rssi * 0x83) / 64 - 400) / 4; int band = dev->conf.channel->band;
return ((rssi * priv->rssical_db[band].mul) / 64 +
priv->rssical_db[band].add) / 4;
} }
static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
...@@ -1466,15 +1502,15 @@ static int p54_setup_mac(struct ieee80211_hw *dev) ...@@ -1466,15 +1502,15 @@ static int p54_setup_mac(struct ieee80211_hw *dev)
return 0; return 0;
} }
static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell, static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell)
u16 frequency)
{ {
struct p54_common *priv = dev->priv; struct p54_common *priv = dev->priv;
struct sk_buff *skb; struct sk_buff *skb;
struct p54_scan *chan; struct p54_scan *chan;
unsigned int i; unsigned int i;
void *entry; void *entry;
__le16 freq = cpu_to_le16(frequency); __le16 freq = cpu_to_le16(dev->conf.channel->center_freq);
int band = dev->conf.channel->band;
skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan) + skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan) +
sizeof(struct p54_hdr), P54_CONTROL_TYPE_SCAN, sizeof(struct p54_hdr), P54_CONTROL_TYPE_SCAN,
...@@ -1535,11 +1571,11 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell, ...@@ -1535,11 +1571,11 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell,
} }
if (priv->fw_var < 0x500) { if (priv->fw_var < 0x500) {
chan->v1.rssical_mul = cpu_to_le16(130); chan->v1_rssi.mul = cpu_to_le16(priv->rssical_db[band].mul);
chan->v1.rssical_add = cpu_to_le16(0xfe70); chan->v1_rssi.add = cpu_to_le16(priv->rssical_db[band].add);
} else { } else {
chan->v2.rssical_mul = cpu_to_le16(130); chan->v2.rssi.mul = cpu_to_le16(priv->rssical_db[band].mul);
chan->v2.rssical_add = cpu_to_le16(0xfe70); chan->v2.rssi.add = cpu_to_le16(priv->rssical_db[band].add);
chan->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); chan->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
memset(chan->v2.rts_rates, 0, 8); memset(chan->v2.rts_rates, 0, 8);
} }
...@@ -1801,8 +1837,7 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed) ...@@ -1801,8 +1837,7 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed)
goto out; goto out;
} }
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
ret = p54_scan(dev, P54_SCAN_EXIT, 0, ret = p54_scan(dev, P54_SCAN_EXIT, 0);
conf->channel->center_freq);
if (ret) if (ret)
goto out; goto out;
} }
...@@ -1828,8 +1863,7 @@ static int p54_config_interface(struct ieee80211_hw *dev, ...@@ -1828,8 +1863,7 @@ static int p54_config_interface(struct ieee80211_hw *dev,
} }
if (conf->changed & IEEE80211_IFCC_BEACON) { if (conf->changed & IEEE80211_IFCC_BEACON) {
ret = p54_scan(dev, P54_SCAN_EXIT, 0, ret = p54_scan(dev, P54_SCAN_EXIT, 0);
dev->conf.channel->center_freq);
if (ret) if (ret)
goto out; goto out;
ret = p54_setup_mac(dev); ret = p54_setup_mac(dev);
...@@ -1968,8 +2002,7 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev, ...@@ -1968,8 +2002,7 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev,
priv->basic_rate_mask = info->basic_rates; priv->basic_rate_mask = info->basic_rates;
p54_setup_mac(dev); p54_setup_mac(dev);
if (priv->fw_var >= 0x500) if (priv->fw_var >= 0x500)
p54_scan(dev, P54_SCAN_EXIT, 0, p54_scan(dev, P54_SCAN_EXIT, 0);
dev->conf.channel->center_freq);
} }
if (changed & BSS_CHANGED_ASSOC) { if (changed & BSS_CHANGED_ASSOC) {
if (info->assoc) { if (info->assoc) {
......
...@@ -178,6 +178,11 @@ struct pda_pa_curve_data { ...@@ -178,6 +178,11 @@ struct pda_pa_curve_data {
u8 data[0]; u8 data[0];
} __attribute__ ((packed)); } __attribute__ ((packed));
struct pda_rssi_cal_entry {
__le16 mul;
__le16 add;
} __attribute__ ((packed));
/* /*
* this defines the PDR codes used to build PDAs as defined in document * this defines the PDR codes used to build PDAs as defined in document
* number 553155. The current implementation mirrors version 1.1 of the * number 553155. The current implementation mirrors version 1.1 of the
...@@ -429,22 +434,18 @@ struct p54_scan { ...@@ -429,22 +434,18 @@ struct p54_scan {
u8 dup_16qam; u8 dup_16qam;
u8 dup_64qam; u8 dup_64qam;
union { union {
struct { struct pda_rssi_cal_entry v1_rssi;
__le16 rssical_mul;
__le16 rssical_add;
} v1 __attribute__ ((packed));
struct { struct {
__le32 basic_rate_mask; __le32 basic_rate_mask;
u8 rts_rates[8]; u8 rts_rates[8];
__le16 rssical_mul; struct pda_rssi_cal_entry rssi;
__le16 rssical_add;
} v2 __attribute__ ((packed)); } v2 __attribute__ ((packed));
} __attribute__ ((packed)); } __attribute__ ((packed));
} __attribute__ ((packed)); } __attribute__ ((packed));
#define P54_SCAN_V1_LEN (sizeof(struct p54_scan)-12) #define P54_SCAN_V1_LEN 0x70
#define P54_SCAN_V2_LEN (sizeof(struct p54_scan)) #define P54_SCAN_V2_LEN 0x7c
struct p54_led { struct p54_led {
__le16 mode; __le16 mode;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment