b43: N-PHY: add RX IQ calibrationi for rev < 3
authorRafał Miłecki <zajec5@gmail.com>
Fri, 15 Jan 2010 15:20:56 +0000 (16:20 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 15 Jan 2010 22:05:43 +0000 (17:05 -0500)
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/b43/phy_n.c

index 4111a46..f982f56 100644 (file)
@@ -1660,6 +1660,206 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
        return error;
 }
 
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */
+static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
+                       struct nphy_txgains target, u8 type, bool debug)
+{
+       struct b43_phy_n *nphy = dev->phy.n;
+       int i, j, index;
+       u8 rfctl[2];
+       u8 afectl_core;
+       u16 tmp[6];
+       u16 cur_hpf1, cur_hpf2, cur_lna;
+       u32 real, imag;
+       enum ieee80211_band band;
+
+       u8 use;
+       u16 cur_hpf;
+       u16 lna[3] = { 3, 3, 1 };
+       u16 hpf1[3] = { 7, 2, 0 };
+       u16 hpf2[3] = { 2, 0, 0 };
+       u32 power[3];
+       u16 gain_save[2];
+       u16 cal_gain[2];
+       struct nphy_iqcal_params cal_params[2];
+       struct nphy_iq_est est;
+       int ret = 0;
+       bool playtone = true;
+       int desired = 13;
+
+       b43_nphy_stay_in_carrier_search(dev, 1);
+
+       if (dev->phy.rev < 2)
+               ;/* TODO: Call N PHY Reapply TX Cal Coeffs */
+       /* TODO: Read an N PHY Table with ID 7, length 2, offset 0x110,
+               width 16, and data gain_save */
+       for (i = 0; i < 2; i++) {
+               b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]);
+               cal_gain[i] = cal_params[i].cal_gain;
+       }
+       /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110,
+               width 16, and data from cal_gain */
+
+       for (i = 0; i < 2; i++) {
+               if (i == 0) {
+                       rfctl[0] = B43_NPHY_RFCTL_INTC1;
+                       rfctl[1] = B43_NPHY_RFCTL_INTC2;
+                       afectl_core = B43_NPHY_AFECTL_C1;
+               } else {
+                       rfctl[0] = B43_NPHY_RFCTL_INTC2;
+                       rfctl[1] = B43_NPHY_RFCTL_INTC1;
+                       afectl_core = B43_NPHY_AFECTL_C2;
+               }
+
+               tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
+               tmp[2] = b43_phy_read(dev, afectl_core);
+               tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
+               tmp[4] = b43_phy_read(dev, rfctl[0]);
+               tmp[5] = b43_phy_read(dev, rfctl[1]);
+
+               b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
+                               (u16)~B43_NPHY_RFSEQCA_RXDIS,
+                               ((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
+               b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
+                               (1 - i));
+               b43_phy_set(dev, afectl_core, 0x0006);
+               b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006);
+
+               band = b43_current_band(dev->wl);
+
+               if (nphy->rxcalparams & 0xFF000000) {
+                       if (band == IEEE80211_BAND_5GHZ)
+                               b43_phy_write(dev, rfctl[0], 0x140);
+                       else
+                               b43_phy_write(dev, rfctl[0], 0x110);
+               } else {
+                       if (band == IEEE80211_BAND_5GHZ)
+                               b43_phy_write(dev, rfctl[0], 0x180);
+                       else
+                               b43_phy_write(dev, rfctl[0], 0x120);
+               }
+
+               if (band == IEEE80211_BAND_5GHZ)
+                       b43_phy_write(dev, rfctl[1], 0x148);
+               else
+                       b43_phy_write(dev, rfctl[1], 0x114);
+
+               if (nphy->rxcalparams & 0x10000) {
+                       b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC,
+                                       (i + 1));
+                       b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC,
+                                       (2 - i));
+               }
+
+               for (j = 0; i < 4; j++) {
+                       if (j < 3) {
+                               cur_lna = lna[j];
+                               cur_hpf1 = hpf1[j];
+                               cur_hpf2 = hpf2[j];
+                       } else {
+                               if (power[1] > 10000) {
+                                       use = 1;
+                                       cur_hpf = cur_hpf1;
+                                       index = 2;
+                               } else {
+                                       if (power[0] > 10000) {
+                                               use = 1;
+                                               cur_hpf = cur_hpf1;
+                                               index = 1;
+                                       } else {
+                                               index = 0;
+                                               use = 2;
+                                               cur_hpf = cur_hpf2;
+                                       }
+                               }
+                               cur_lna = lna[index];
+                               cur_hpf1 = hpf1[index];
+                               cur_hpf2 = hpf2[index];
+                               cur_hpf += desired - hweight32(power[index]);
+                               cur_hpf = clamp_val(cur_hpf, 0, 10);
+                               if (use == 1)
+                                       cur_hpf1 = cur_hpf;
+                               else
+                                       cur_hpf2 = cur_hpf;
+                       }
+
+                       tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
+                                       (cur_lna << 2));
+                       /* TODO:Call N PHY RF Ctrl Override with 0x400, tmp[0],
+                               3, 0 as arguments */
+                       /* TODO: Call N PHY Force RF Seq with 2 as argument */
+                       /* TODO: Call N PHT Stop Playback */
+
+                       if (playtone) {
+                               /* TODO: Call N PHY TX Tone with 4000,
+                                       (nphy_rxcalparams & 0xffff), 0, 0
+                                       as arguments and save result as ret */
+                               playtone = false;
+                       } else {
+                               /* TODO: Call N PHY Run Samples with 160,
+                                       0xFFFF, 0, 0, 0 as arguments */
+                       }
+
+                       if (ret == 0) {
+                               if (j < 3) {
+                                       b43_nphy_rx_iq_est(dev, &est, 1024, 32,
+                                                                       false);
+                                       if (i == 0) {
+                                               real = est.i0_pwr;
+                                               imag = est.q0_pwr;
+                                       } else {
+                                               real = est.i1_pwr;
+                                               imag = est.q1_pwr;
+                                       }
+                                       power[i] = ((real + imag) / 1024) + 1;
+                               } else {
+                                       b43_nphy_calc_rx_iq_comp(dev, 1 << i);
+                               }
+                               /* TODO: Call N PHY Stop Playback */
+                       }
+
+                       if (ret != 0)
+                               break;
+               }
+
+               b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC);
+               b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC);
+               b43_phy_write(dev, rfctl[1], tmp[5]);
+               b43_phy_write(dev, rfctl[0], tmp[4]);
+               b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]);
+               b43_phy_write(dev, afectl_core, tmp[2]);
+               b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]);
+
+               if (ret != 0)
+                       break;
+       }
+
+       /* TODO: Call N PHY RF Ctrl Override with 0x400, 0, 3, 1 as arguments*/
+       /* TODO: Call N PHY Force RF Seq with 2 as argument */
+       /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110,
+               width 16, and data from gain_save */
+
+       b43_nphy_stay_in_carrier_search(dev, 0);
+
+       return ret;
+}
+
+static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev,
+                       struct nphy_txgains target, u8 type, bool debug)
+{
+       return -1;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */
+static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
+                       struct nphy_txgains target, u8 type, bool debug)
+{
+       if (dev->phy.rev >= 3)
+               return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug);
+       else
+               return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug);
+}
+
 /*
  * Init N-PHY
  * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N
@@ -1831,16 +2031,14 @@ int b43_phy_initn(struct b43_wldev *dev)
                }
        }
 
-       /*
        if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) {
                if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
-                       Call N PHY Save Cal
+                       ;/* Call N PHY Save Cal */
                else if (nphy->mphase_cal_phase_id == 0)
-                       N PHY Periodic Calibration with argument 3
+                       ;/* N PHY Periodic Calibration with argument 3 */
        } else {
                b43_nphy_restore_cal(dev);
        }
-       */
 
        /* b43_nphy_tx_pwr_ctrl_coef_setup(dev); */
        /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */