From patchwork Tue Sep 15 20:23:06 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joerg Albert X-Patchwork-Id: 47752 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n8FKNC4W029101 for ; Tue, 15 Sep 2009 20:23:12 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751164AbZIOUXH (ORCPT ); Tue, 15 Sep 2009 16:23:07 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751119AbZIOUXG (ORCPT ); Tue, 15 Sep 2009 16:23:06 -0400 Received: from mail.gmx.net ([213.165.64.20]:53190 "HELO mail.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1751090AbZIOUXF (ORCPT ); Tue, 15 Sep 2009 16:23:05 -0400 Received: (qmail invoked by alias); 15 Sep 2009 20:23:07 -0000 Received: from f055149020.adsl.alicedsl.de (EHLO [192.168.2.185]) [78.55.149.20] by mail.gmx.net (mp012) with SMTP; 15 Sep 2009 22:23:07 +0200 X-Authenticated: #3800222 X-Provags-ID: V01U2FsdGVkX1/O7UQ6xtfOHdMoY10q/qqNUvGlZ3iCCPvkIWm1SX I8/EiYyAPsPr5r Message-ID: <4AAFF7AA.4030509@gmx.de> Date: Tue, 15 Sep 2009 22:23:06 +0200 From: Joerg Albert User-Agent: Thunderbird 2.0.0.23 (X11/20090817) MIME-Version: 1.0 To: "John W. Linville" CC: Christian Lamparter , "linux-wireless@vger.kernel.org" Subject: [PATCH] ar9170: add heavy clip handling X-Y-GMX-Trusted: 0 X-FuHaFi: 0.4 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org add heavy clip handling for 2.4GHz only (similar to the vendor driver). Signed-off-by: Joerg Albert --- drivers/net/wireless/ath/ar9170/ar9170.h | 2 + drivers/net/wireless/ath/ar9170/phy.c | 71 ++++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index 914e471..e63a7d9 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -204,6 +204,8 @@ struct ar9170 { u8 power_2G_ht20[8]; u8 power_2G_ht40[8]; + u8 phy_heavy_clip; + #ifdef CONFIG_AR9170_LEDS struct delayed_work led_work; struct ar9170_led leds[AR9170_NUM_LEDS]; diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c index 941c699..c42dbd6 100644 --- a/drivers/net/wireless/ath/ar9170/phy.c +++ b/drivers/net/wireless/ath/ar9170/phy.c @@ -1280,8 +1280,38 @@ static u8 ar9170_get_max_edge_power(struct ar9170 *ar, return rc; } -/* calculate the conformance test limits and apply them to ar->power* - * (derived from otus hal/hpmain.c, line 3706 ff.) +static u8 ar9170_get_heavy_clip(struct ar9170 *ar, + struct ar9170_calctl_edges edges[], + u32 freq, enum ar9170_bw bw) +{ + u8 f; + int i; + u8 rc = 0; + + if (freq < 3000) + f = freq - 2300; + else + f = (freq - 4800) / 5; + + if (bw == AR9170_BW_40_BELOW || bw == AR9170_BW_40_ABOVE) + rc |= 0xf0; + + for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { + if (edges[i].channel == 0xff) + break; + if (f == edges[i].channel) { + if (!(edges[i].power_flags & AR9170_CALCTL_EDGE_FLAGS)) + rc |= 0x0f; + break; + } + } + + return rc; +} + +/* + * calculate the conformance test limits and the heavy clip parameter + * and apply them to ar->power* (derived from otus hal/hpmain.c, line 3706) */ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) { @@ -1314,6 +1344,8 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) #define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n]) + ar->phy_heavy_clip = 0; + /* * TODO: investigate the differences between OTUS' * hpreg.c::zfHpGetRegulatoryDomain() and @@ -1349,6 +1381,15 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) if (ctl_idx < AR5416_NUM_CTLS) { int f_off = 0; + /* determine heav clip parameter from + the 11G edges array */ + if (modes[i].ctl_mode == CTL_11G) { + ar->phy_heavy_clip = + ar9170_get_heavy_clip(ar, + EDGES(ctl_idx, 1), + freq, bw); + } + /* adjust freq for 40MHz */ if (modes[i].ctl_mode == CTL_2GHT40 || modes[i].ctl_mode == CTL_5GHT40) { @@ -1394,6 +1435,19 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) modes[i].max_power); } } + + if (ar->phy_heavy_clip & 0xf0) { + ar->power_2G_ht40[0]--; + ar->power_2G_ht40[1]--; + ar->power_2G_ht40[2]--; + } + if (ar->phy_heavy_clip & 0xf) { + ar->power_2G_ht20[0]++; + ar->power_2G_ht20[1]++; + ar->power_2G_ht20[2]++; + } + + #undef EDGES } @@ -1503,8 +1557,6 @@ static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) /* calc. conformance test limits and apply to ar->power*[] */ ar9170_calc_ctl(ar, freq, bw); - /* TODO: (heavy clip) regulatory domain power level fine-tuning. */ - /* set ACK/CTS TX power */ ar9170_regwrite_begin(ar); @@ -1647,6 +1699,17 @@ int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, if (err) return err; + if (ar->phy_heavy_clip) { + err = ar9170_write_reg(ar, 0x1c59e0, + 0x200 | ar->phy_heavy_clip); + if (err) { + if (ar9170_nag_limiter(ar)) + printk(KERN_ERR "%s: failed to set " + "heavy clip\n", + wiphy_name(ar->hw->wiphy)); + } + } + for (i = 0; i < 2; i++) { ar->noise[i] = ar9170_calc_noise_dbm( (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff);