diff options
author | Christian Lamparter <chunkeey@web.de> | 2009-01-10 19:14:18 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-01-29 16:00:24 -0500 |
commit | 6917f506a03b6bd7389683e8a8e08a1ad977b33e (patch) | |
tree | 1a5ed1755ae86666eea587a2c942984f9444932c /drivers/net/wireless/p54/p54common.c | |
parent | 83cf1b6edba6bde87c8cf852b182d44b12ae7f88 (diff) |
p54: longbow frontend support
This patch adds support for longbow RF chip.
Signed-off-by: Christian Lamparter <chunkeey@web.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/p54/p54common.c')
-rw-r--r-- | drivers/net/wireless/p54/p54common.c | 141 |
1 files changed, 104 insertions, 37 deletions
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index ec0d109c0095..9fc0c9efe701 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -651,7 +651,7 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
651 | } | 651 | } |
652 | 652 | ||
653 | priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; | 653 | priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; |
654 | if (priv->rxhw == 4) | 654 | if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW) |
655 | p54_init_xbow_synth(dev); | 655 | p54_init_xbow_synth(dev); |
656 | if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) | 656 | if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) |
657 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; | 657 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; |
@@ -704,7 +704,14 @@ static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi) | |||
704 | struct p54_common *priv = dev->priv; | 704 | struct p54_common *priv = dev->priv; |
705 | int band = dev->conf.channel->band; | 705 | int band = dev->conf.channel->band; |
706 | 706 | ||
707 | return ((rssi * priv->rssical_db[band].mul) / 64 + | 707 | if (priv->rxhw != PDR_SYNTH_FRONTEND_LONGBOW) |
708 | return ((rssi * priv->rssical_db[band].mul) / 64 + | ||
709 | priv->rssical_db[band].add) / 4; | ||
710 | else | ||
711 | /* | ||
712 | * TODO: find the correct formula | ||
713 | */ | ||
714 | return ((rssi * priv->rssical_db[band].mul) / 64 + | ||
708 | priv->rssical_db[band].add) / 4; | 715 | priv->rssical_db[band].add) / 4; |
709 | } | 716 | } |
710 | 717 | ||
@@ -1612,8 +1619,13 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
1612 | memset(txhdr->durations, 0, sizeof(txhdr->durations)); | 1619 | memset(txhdr->durations, 0, sizeof(txhdr->durations)); |
1613 | txhdr->tx_antenna = ((info->antenna_sel_tx == 0) ? | 1620 | txhdr->tx_antenna = ((info->antenna_sel_tx == 0) ? |
1614 | 2 : info->antenna_sel_tx - 1) & priv->tx_diversity_mask; | 1621 | 2 : info->antenna_sel_tx - 1) & priv->tx_diversity_mask; |
1615 | txhdr->output_power = priv->output_power; | 1622 | if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { |
1616 | txhdr->cts_rate = cts_rate; | 1623 | txhdr->longbow.cts_rate = cts_rate; |
1624 | txhdr->longbow.output_power = cpu_to_le16(priv->output_power); | ||
1625 | } else { | ||
1626 | txhdr->normal.output_power = priv->output_power; | ||
1627 | txhdr->normal.cts_rate = cts_rate; | ||
1628 | } | ||
1617 | if (padding) | 1629 | if (padding) |
1618 | txhdr->align[0] = padding; | 1630 | txhdr->align[0] = padding; |
1619 | 1631 | ||
@@ -1715,47 +1727,77 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell) | |||
1715 | { | 1727 | { |
1716 | struct p54_common *priv = dev->priv; | 1728 | struct p54_common *priv = dev->priv; |
1717 | struct sk_buff *skb; | 1729 | struct sk_buff *skb; |
1718 | struct p54_scan *chan; | 1730 | struct p54_hdr *hdr; |
1731 | struct p54_scan_head *head; | ||
1732 | struct p54_iq_autocal_entry *iq_autocal; | ||
1733 | union p54_scan_body_union *body; | ||
1734 | struct p54_scan_tail_rate *rate; | ||
1735 | struct pda_rssi_cal_entry *rssi; | ||
1719 | unsigned int i; | 1736 | unsigned int i; |
1720 | void *entry; | 1737 | void *entry; |
1721 | int band = dev->conf.channel->band; | 1738 | int band = dev->conf.channel->band; |
1722 | __le16 freq = cpu_to_le16(dev->conf.channel->center_freq); | 1739 | __le16 freq = cpu_to_le16(dev->conf.channel->center_freq); |
1723 | 1740 | ||
1724 | skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan), | 1741 | skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) + |
1742 | 2 + sizeof(*iq_autocal) + sizeof(*body) + | ||
1743 | sizeof(*rate) + 2 * sizeof(*rssi), | ||
1725 | P54_CONTROL_TYPE_SCAN, GFP_ATOMIC); | 1744 | P54_CONTROL_TYPE_SCAN, GFP_ATOMIC); |
1726 | if (!skb) | 1745 | if (!skb) |
1727 | return -ENOMEM; | 1746 | return -ENOMEM; |
1728 | 1747 | ||
1729 | chan = (struct p54_scan *) skb_put(skb, sizeof(*chan)); | 1748 | head = (struct p54_scan_head *) skb_put(skb, sizeof(*head)); |
1730 | memset(chan->scan_params, 0, sizeof(chan->scan_params)); | 1749 | memset(head->scan_params, 0, sizeof(head->scan_params)); |
1731 | chan->mode = cpu_to_le16(mode); | 1750 | head->mode = cpu_to_le16(mode); |
1732 | chan->dwell = cpu_to_le16(dwell); | 1751 | head->dwell = cpu_to_le16(dwell); |
1752 | head->freq = freq; | ||
1733 | 1753 | ||
1754 | if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { | ||
1755 | __le16 *pa_power_points = (__le16 *) skb_put(skb, 2); | ||
1756 | *pa_power_points = cpu_to_le16(0x0c); | ||
1757 | } | ||
1758 | |||
1759 | iq_autocal = (void *) skb_put(skb, sizeof(*iq_autocal)); | ||
1734 | for (i = 0; i < priv->iq_autocal_len; i++) { | 1760 | for (i = 0; i < priv->iq_autocal_len; i++) { |
1735 | if (priv->iq_autocal[i].freq != freq) | 1761 | if (priv->iq_autocal[i].freq != freq) |
1736 | continue; | 1762 | continue; |
1737 | 1763 | ||
1738 | memcpy(&chan->iq_autocal, &priv->iq_autocal[i], | 1764 | memcpy(iq_autocal, &priv->iq_autocal[i].params, |
1739 | sizeof(*priv->iq_autocal)); | 1765 | sizeof(struct p54_iq_autocal_entry)); |
1740 | break; | 1766 | break; |
1741 | } | 1767 | } |
1742 | if (i == priv->iq_autocal_len) | 1768 | if (i == priv->iq_autocal_len) |
1743 | goto err; | 1769 | goto err; |
1744 | 1770 | ||
1771 | if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) | ||
1772 | body = (void *) skb_put(skb, sizeof(body->longbow)); | ||
1773 | else | ||
1774 | body = (void *) skb_put(skb, sizeof(body->normal)); | ||
1775 | |||
1745 | for (i = 0; i < priv->output_limit->entries; i++) { | 1776 | for (i = 0; i < priv->output_limit->entries; i++) { |
1746 | struct pda_channel_output_limit *limits; | ||
1747 | __le16 *entry_freq = (void *) (priv->output_limit->data + | 1777 | __le16 *entry_freq = (void *) (priv->output_limit->data + |
1748 | priv->output_limit->entry_size * i); | 1778 | priv->output_limit->entry_size * i); |
1749 | 1779 | ||
1750 | if (*entry_freq != freq) | 1780 | if (*entry_freq != freq) |
1751 | continue; | 1781 | continue; |
1752 | 1782 | ||
1753 | limits = (void *) entry_freq; | 1783 | if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { |
1754 | chan->val_barker = 0x38; | 1784 | memcpy(&body->longbow.power_limits, |
1755 | chan->val_bpsk = chan->dup_bpsk = limits->val_bpsk; | 1785 | (void *) entry_freq + sizeof(__le16), |
1756 | chan->val_qpsk = chan->dup_qpsk = limits->val_qpsk; | 1786 | priv->output_limit->entry_size); |
1757 | chan->val_16qam = chan->dup_16qam = limits->val_16qam; | 1787 | } else { |
1758 | chan->val_64qam = chan->dup_64qam = limits->val_64qam; | 1788 | struct pda_channel_output_limit *limits = |
1789 | (void *) entry_freq; | ||
1790 | |||
1791 | body->normal.val_barker = 0x38; | ||
1792 | body->normal.val_bpsk = body->normal.dup_bpsk = | ||
1793 | limits->val_bpsk; | ||
1794 | body->normal.val_qpsk = body->normal.dup_qpsk = | ||
1795 | limits->val_qpsk; | ||
1796 | body->normal.val_16qam = body->normal.dup_16qam = | ||
1797 | limits->val_16qam; | ||
1798 | body->normal.val_64qam = body->normal.dup_64qam = | ||
1799 | limits->val_64qam; | ||
1800 | } | ||
1759 | break; | 1801 | break; |
1760 | } | 1802 | } |
1761 | if (i == priv->output_limit->entries) | 1803 | if (i == priv->output_limit->entries) |
@@ -1763,34 +1805,59 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell) | |||
1763 | 1805 | ||
1764 | entry = (void *)(priv->curve_data->data + priv->curve_data->offset); | 1806 | entry = (void *)(priv->curve_data->data + priv->curve_data->offset); |
1765 | for (i = 0; i < priv->curve_data->entries; i++) { | 1807 | for (i = 0; i < priv->curve_data->entries; i++) { |
1766 | struct pda_pa_curve_data *curve_data; | ||
1767 | if (*((__le16 *)entry) != freq) { | 1808 | if (*((__le16 *)entry) != freq) { |
1768 | entry += priv->curve_data->entry_size; | 1809 | entry += priv->curve_data->entry_size; |
1769 | continue; | 1810 | continue; |
1770 | } | 1811 | } |
1771 | 1812 | ||
1772 | entry += sizeof(__le16); | 1813 | if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { |
1773 | chan->pa_points_per_curve = 8; | 1814 | memcpy(&body->longbow.curve_data, |
1774 | memset(chan->curve_data, 0, sizeof(*chan->curve_data)); | 1815 | (void *) entry + sizeof(__le16), |
1775 | curve_data = (void *) priv->curve_data->data; | 1816 | priv->curve_data->entry_size); |
1776 | 1817 | } else { | |
1777 | memcpy(chan->curve_data, entry, | 1818 | struct p54_scan_body *chan = &body->normal; |
1778 | sizeof(struct p54_pa_curve_data_sample) * | 1819 | struct pda_pa_curve_data *curve_data = |
1779 | min_t(u8, 8, curve_data->points_per_channel)); | 1820 | (void *) priv->curve_data->data; |
1821 | |||
1822 | entry += sizeof(__le16); | ||
1823 | chan->pa_points_per_curve = 8; | ||
1824 | memset(chan->curve_data, 0, sizeof(*chan->curve_data)); | ||
1825 | memcpy(chan->curve_data, entry, | ||
1826 | sizeof(struct p54_pa_curve_data_sample) * | ||
1827 | min((u8)8, curve_data->points_per_channel)); | ||
1828 | } | ||
1780 | break; | 1829 | break; |
1781 | } | 1830 | } |
1782 | if (i == priv->curve_data->entries) | 1831 | if (i == priv->curve_data->entries) |
1783 | goto err; | 1832 | goto err; |
1784 | 1833 | ||
1785 | if (priv->fw_var < 0x500) { | 1834 | if ((priv->fw_var >= 0x500) && (priv->fw_var < 0x509)) { |
1786 | chan->v1_rssi.mul = cpu_to_le16(priv->rssical_db[band].mul); | 1835 | rate = (void *) skb_put(skb, sizeof(*rate)); |
1787 | chan->v1_rssi.add = cpu_to_le16(priv->rssical_db[band].add); | 1836 | rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); |
1788 | } else { | 1837 | for (i = 0; i < sizeof(rate->rts_rates); i++) |
1789 | chan->v2.rssi.mul = cpu_to_le16(priv->rssical_db[band].mul); | 1838 | rate->rts_rates[i] = i; |
1790 | chan->v2.rssi.add = cpu_to_le16(priv->rssical_db[band].add); | ||
1791 | chan->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); | ||
1792 | memset(chan->v2.rts_rates, 0, 8); | ||
1793 | } | 1839 | } |
1840 | |||
1841 | rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi)); | ||
1842 | rssi->mul = cpu_to_le16(priv->rssical_db[band].mul); | ||
1843 | rssi->add = cpu_to_le16(priv->rssical_db[band].add); | ||
1844 | if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { | ||
1845 | /* Longbow frontend needs ever more */ | ||
1846 | rssi = (void *) skb_put(skb, sizeof(*rssi)); | ||
1847 | rssi->mul = cpu_to_le16(priv->rssical_db[band].longbow_unkn); | ||
1848 | rssi->add = cpu_to_le16(priv->rssical_db[band].longbow_unk2); | ||
1849 | } | ||
1850 | |||
1851 | if (priv->fw_var >= 0x509) { | ||
1852 | rate = (void *) skb_put(skb, sizeof(*rate)); | ||
1853 | rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); | ||
1854 | for (i = 0; i < sizeof(rate->rts_rates); i++) | ||
1855 | rate->rts_rates[i] = i; | ||
1856 | } | ||
1857 | |||
1858 | hdr = (struct p54_hdr *) skb->data; | ||
1859 | hdr->len = cpu_to_le16(skb->len - sizeof(*hdr)); | ||
1860 | |||
1794 | priv->tx(dev, skb); | 1861 | priv->tx(dev, skb); |
1795 | return 0; | 1862 | return 0; |
1796 | 1863 | ||