~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/net/wireless/ath/ath9k/ar9003_calib.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (c) 2010 Atheros Communications Inc.
 
2
 * Copyright (c) 2010-2011 Atheros Communications Inc.
3
3
 *
4
4
 * Permission to use, copy, modify, and/or distribute this software for any
5
5
 * purpose with or without fee is hereby granted, provided that the above
18
18
#include "hw-ops.h"
19
19
#include "ar9003_phy.h"
20
20
 
21
 
#define MPASS   3
22
21
#define MAX_MEASUREMENT 8
23
 
#define MAX_DIFFERENCE  10
 
22
#define MAX_MAG_DELTA   11
 
23
#define MAX_PHS_DELTA   10
24
24
 
25
25
struct coeff {
26
 
        int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS];
27
 
        int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS];
 
26
        int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
 
27
        int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
28
28
        int iqc_coeff[2];
29
29
};
30
30
 
185
185
 
186
186
        /* Accumulate IQ cal measures for active chains */
187
187
        for (i = 0; i < AR5416_MAX_CHAINS; i++) {
188
 
                ah->totalPowerMeasI[i] +=
189
 
                        REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
190
 
                ah->totalPowerMeasQ[i] +=
191
 
                        REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
192
 
                ah->totalIqCorrMeas[i] +=
193
 
                        (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
194
 
                ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
195
 
                        "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
196
 
                        ah->cal_samples, i, ah->totalPowerMeasI[i],
197
 
                        ah->totalPowerMeasQ[i],
198
 
                        ah->totalIqCorrMeas[i]);
 
188
                if (ah->txchainmask & BIT(i)) {
 
189
                        ah->totalPowerMeasI[i] +=
 
190
                                REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
 
191
                        ah->totalPowerMeasQ[i] +=
 
192
                                REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
 
193
                        ah->totalIqCorrMeas[i] +=
 
194
                                (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
 
195
                        ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
 
196
                                "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
 
197
                                ah->cal_samples, i, ah->totalPowerMeasI[i],
 
198
                                ah->totalPowerMeasQ[i],
 
199
                                ah->totalIqCorrMeas[i]);
 
200
                }
199
201
        }
200
202
}
201
203
 
608
610
        return true;
609
611
}
610
612
 
611
 
static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg)
 
613
static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
 
614
                                     int max_delta)
612
615
{
613
 
        int diff[MPASS];
614
 
 
615
 
        diff[0] = abs(mp_coeff[0] - mp_coeff[1]);
616
 
        diff[1] = abs(mp_coeff[1] - mp_coeff[2]);
617
 
        diff[2] = abs(mp_coeff[2] - mp_coeff[0]);
618
 
 
619
 
        if (diff[0] > MAX_DIFFERENCE &&
620
 
            diff[1] > MAX_DIFFERENCE &&
621
 
            diff[2] > MAX_DIFFERENCE)
622
 
                return false;
623
 
 
624
 
        if (diff[0] <= diff[1] && diff[0] <= diff[2])
625
 
                *mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2;
626
 
        else if (diff[1] <= diff[2])
627
 
                *mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2;
628
 
        else
629
 
                *mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2;
630
 
 
631
 
        return true;
 
616
        int mp_max = -64, max_idx = 0;
 
617
        int mp_min = 63, min_idx = 0;
 
618
        int mp_avg = 0, i, outlier_idx = 0;
 
619
 
 
620
        /* find min/max mismatch across all calibrated gains */
 
621
        for (i = 0; i < nmeasurement; i++) {
 
622
                mp_avg += mp_coeff[i];
 
623
                if (mp_coeff[i] > mp_max) {
 
624
                        mp_max = mp_coeff[i];
 
625
                        max_idx = i;
 
626
                } else if (mp_coeff[i] < mp_min) {
 
627
                        mp_min = mp_coeff[i];
 
628
                        min_idx = i;
 
629
                }
 
630
        }
 
631
 
 
632
        /* find average (exclude max abs value) */
 
633
        for (i = 0; i < nmeasurement; i++) {
 
634
                if ((abs(mp_coeff[i]) < abs(mp_max)) ||
 
635
                    (abs(mp_coeff[i]) < abs(mp_min)))
 
636
                        mp_avg += mp_coeff[i];
 
637
        }
 
638
        mp_avg /= (nmeasurement - 1);
 
639
 
 
640
        /* detect outlier */
 
641
        if (abs(mp_max - mp_min) > max_delta) {
 
642
                if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg))
 
643
                        outlier_idx = max_idx;
 
644
                else
 
645
                        outlier_idx = min_idx;
 
646
        }
 
647
        mp_coeff[outlier_idx] = mp_avg;
632
648
}
633
649
 
634
650
static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
635
651
                                                 u8 num_chains,
636
652
                                                 struct coeff *coeff)
637
653
{
638
 
        struct ath_common *common = ath9k_hw_common(ah);
639
654
        int i, im, nmeasurement;
640
 
        int magnitude, phase;
641
655
        u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
642
656
 
643
657
        memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
657
671
 
658
672
        /* Load the average of 2 passes */
659
673
        for (i = 0; i < num_chains; i++) {
660
 
                if (AR_SREV_9485(ah))
661
 
                        nmeasurement = REG_READ_FIELD(ah,
662
 
                                        AR_PHY_TX_IQCAL_STATUS_B0_9485,
663
 
                                        AR_PHY_CALIBRATED_GAINS_0);
664
 
                else
665
 
                        nmeasurement = REG_READ_FIELD(ah,
666
 
                                        AR_PHY_TX_IQCAL_STATUS_B0,
667
 
                                        AR_PHY_CALIBRATED_GAINS_0);
 
674
                nmeasurement = REG_READ_FIELD(ah,
 
675
                                AR_PHY_TX_IQCAL_STATUS_B0,
 
676
                                AR_PHY_CALIBRATED_GAINS_0);
668
677
 
669
678
                if (nmeasurement > MAX_MEASUREMENT)
670
679
                        nmeasurement = MAX_MEASUREMENT;
671
680
 
 
681
                /* detect outlier only if nmeasurement > 1 */
 
682
                if (nmeasurement > 1) {
 
683
                        /* Detect magnitude outlier */
 
684
                        ar9003_hw_detect_outlier(coeff->mag_coeff[i],
 
685
                                        nmeasurement, MAX_MAG_DELTA);
 
686
 
 
687
                        /* Detect phase outlier */
 
688
                        ar9003_hw_detect_outlier(coeff->phs_coeff[i],
 
689
                                        nmeasurement, MAX_PHS_DELTA);
 
690
                }
 
691
 
672
692
                for (im = 0; im < nmeasurement; im++) {
673
 
                        /*
674
 
                         * Determine which 2 passes are closest and compute avg
675
 
                         * magnitude
676
 
                         */
677
 
                        if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im],
678
 
                                                                    &magnitude))
679
 
                                goto disable_txiqcal;
680
 
 
681
 
                        /*
682
 
                         * Determine which 2 passes are closest and compute avg
683
 
                         * phase
684
 
                         */
685
 
                        if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im],
686
 
                                                                    &phase))
687
 
                                goto disable_txiqcal;
688
 
 
689
 
                        coeff->iqc_coeff[0] = (magnitude & 0x7f) |
690
 
                                              ((phase & 0x7f) << 7);
 
693
 
 
694
                        coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
 
695
                                ((coeff->phs_coeff[i][im] & 0x7f) << 7);
691
696
 
692
697
                        if ((im % 2) == 0)
693
698
                                REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
707
712
 
708
713
        return;
709
714
 
710
 
disable_txiqcal:
711
 
        REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
712
 
                      AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0);
713
 
        REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
714
 
                      AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0);
715
 
 
716
 
        ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n");
717
715
}
718
716
 
719
 
static void ar9003_hw_tx_iq_cal(struct ath_hw *ah)
 
717
static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
720
718
{
721
719
        struct ath_common *common = ath9k_hw_common(ah);
722
 
        static const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
723
 
                AR_PHY_TX_IQCAL_STATUS_B0,
724
 
                AR_PHY_TX_IQCAL_STATUS_B1,
725
 
                AR_PHY_TX_IQCAL_STATUS_B2,
726
 
        };
727
 
        static const u32 chan_info_tab[] = {
728
 
                AR_PHY_CHAN_INFO_TAB_0,
729
 
                AR_PHY_CHAN_INFO_TAB_1,
730
 
                AR_PHY_CHAN_INFO_TAB_2,
731
 
        };
732
 
        struct coeff coeff;
733
 
        s32 iq_res[6];
734
 
        s32 i, j, ip, im, nmeasurement;
735
 
        u8 nchains = get_streams(common->tx_chainmask);
736
 
 
737
 
        for (ip = 0; ip < MPASS; ip++) {
738
 
                REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
739
 
                              AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
740
 
                              DELPT);
741
 
                REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
742
 
                              AR_PHY_TX_IQCAL_START_DO_CAL,
743
 
                              AR_PHY_TX_IQCAL_START_DO_CAL);
744
 
 
745
 
                if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
746
 
                                   AR_PHY_TX_IQCAL_START_DO_CAL,
747
 
                                   0, AH_WAIT_TIMEOUT)) {
748
 
                        ath_dbg(common, ATH_DBG_CALIBRATE,
749
 
                                "Tx IQ Cal not complete.\n");
750
 
                        goto TX_IQ_CAL_FAILED;
751
 
                }
752
 
 
753
 
                nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0,
754
 
                                              AR_PHY_CALIBRATED_GAINS_0);
755
 
                        if (nmeasurement > MAX_MEASUREMENT)
756
 
                                nmeasurement = MAX_MEASUREMENT;
757
 
 
758
 
                for (i = 0; i < nchains; i++) {
759
 
                        ath_dbg(common, ATH_DBG_CALIBRATE,
760
 
                                "Doing Tx IQ Cal for chain %d.\n", i);
761
 
                        for (im = 0; im < nmeasurement; im++) {
762
 
                                if (REG_READ(ah, txiqcal_status[i]) &
763
 
                                             AR_PHY_TX_IQCAL_STATUS_FAILED) {
764
 
                                        ath_dbg(common, ATH_DBG_CALIBRATE,
765
 
                                                "Tx IQ Cal failed for chain %d.\n", i);
766
 
                                        goto TX_IQ_CAL_FAILED;
767
 
                                }
768
 
 
769
 
                                for (j = 0; j < 3; j++) {
770
 
                                        u8 idx = 2 * j,
771
 
                                           offset = 4 * (3 * im + j);
772
 
 
773
 
                                        REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
774
 
                                                      AR_PHY_CHAN_INFO_TAB_S2_READ,
775
 
                                                      0);
776
 
 
777
 
                                        /* 32 bits */
778
 
                                        iq_res[idx] = REG_READ(ah,
779
 
                                                        chan_info_tab[i] +
780
 
                                                        offset);
781
 
 
782
 
                                        REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
783
 
                                                      AR_PHY_CHAN_INFO_TAB_S2_READ,
784
 
                                                      1);
785
 
 
786
 
                                        /* 16 bits */
787
 
                                        iq_res[idx+1] = 0xffff & REG_READ(ah,
788
 
                                                                chan_info_tab[i] +
789
 
                                                                offset);
790
 
 
791
 
                                        ath_dbg(common, ATH_DBG_CALIBRATE,
792
 
                                                "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
793
 
                                                idx, iq_res[idx], idx+1, iq_res[idx+1]);
794
 
                                }
795
 
 
796
 
                                if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
797
 
                                                            coeff.iqc_coeff)) {
798
 
                                        ath_dbg(common, ATH_DBG_CALIBRATE,
799
 
                                                "Failed in calculation of IQ correction.\n");
800
 
                                        goto TX_IQ_CAL_FAILED;
801
 
                                }
802
 
                                coeff.mag_coeff[i][im][ip] =
803
 
                                                coeff.iqc_coeff[0] & 0x7f;
804
 
                                coeff.phs_coeff[i][im][ip] =
805
 
                                                (coeff.iqc_coeff[0] >> 7) & 0x7f;
806
 
 
807
 
                                if (coeff.mag_coeff[i][im][ip] > 63)
808
 
                                        coeff.mag_coeff[i][im][ip] -= 128;
809
 
                                if (coeff.phs_coeff[i][im][ip] > 63)
810
 
                                        coeff.phs_coeff[i][im][ip] -= 128;
811
 
 
812
 
                        }
813
 
                }
814
 
        }
815
 
 
816
 
        ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff);
817
 
 
818
 
        return;
819
 
 
820
 
TX_IQ_CAL_FAILED:
821
 
        ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
822
 
}
823
 
 
824
 
static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
825
 
{
826
720
        u8 tx_gain_forced;
827
721
 
828
 
        REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485,
829
 
                      AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT);
830
722
        tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
831
723
                                        AR_PHY_TXGAIN_FORCE);
832
724
        if (tx_gain_forced)
833
725
                REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
834
726
                              AR_PHY_TXGAIN_FORCE, 0);
835
727
 
836
 
        REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485,
837
 
                      AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1);
 
728
        REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
 
729
                      AR_PHY_TX_IQCAL_START_DO_CAL, 1);
 
730
 
 
731
        if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
 
732
                        AR_PHY_TX_IQCAL_START_DO_CAL, 0,
 
733
                        AH_WAIT_TIMEOUT)) {
 
734
                ath_dbg(common, ATH_DBG_CALIBRATE,
 
735
                        "Tx IQ Cal is not completed.\n");
 
736
                return false;
 
737
        }
 
738
        return true;
838
739
}
839
740
 
840
741
static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
841
742
{
842
743
        struct ath_common *common = ath9k_hw_common(ah);
843
744
        const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
844
 
                AR_PHY_TX_IQCAL_STATUS_B0_9485,
 
745
                AR_PHY_TX_IQCAL_STATUS_B0,
845
746
                AR_PHY_TX_IQCAL_STATUS_B1,
846
747
                AR_PHY_TX_IQCAL_STATUS_B2,
847
748
        };
853
754
        struct coeff coeff;
854
755
        s32 iq_res[6];
855
756
        u8 num_chains = 0;
856
 
        int i, ip, im, j;
 
757
        int i, im, j;
857
758
        int nmeasurement;
858
759
 
859
760
        for (i = 0; i < AR9300_MAX_CHAINS; i++) {
861
762
                        num_chains++;
862
763
        }
863
764
 
864
 
        for (ip = 0; ip < MPASS; ip++) {
865
 
                for (i = 0; i < num_chains; i++) {
866
 
                        nmeasurement = REG_READ_FIELD(ah,
867
 
                                        AR_PHY_TX_IQCAL_STATUS_B0_9485,
868
 
                                        AR_PHY_CALIBRATED_GAINS_0);
869
 
                        if (nmeasurement > MAX_MEASUREMENT)
870
 
                                nmeasurement = MAX_MEASUREMENT;
871
 
 
872
 
                        for (im = 0; im < nmeasurement; im++) {
 
765
        for (i = 0; i < num_chains; i++) {
 
766
                nmeasurement = REG_READ_FIELD(ah,
 
767
                                AR_PHY_TX_IQCAL_STATUS_B0,
 
768
                                AR_PHY_CALIBRATED_GAINS_0);
 
769
                if (nmeasurement > MAX_MEASUREMENT)
 
770
                        nmeasurement = MAX_MEASUREMENT;
 
771
 
 
772
                for (im = 0; im < nmeasurement; im++) {
 
773
                        ath_dbg(common, ATH_DBG_CALIBRATE,
 
774
                                "Doing Tx IQ Cal for chain %d.\n", i);
 
775
 
 
776
                        if (REG_READ(ah, txiqcal_status[i]) &
 
777
                                        AR_PHY_TX_IQCAL_STATUS_FAILED) {
873
778
                                ath_dbg(common, ATH_DBG_CALIBRATE,
874
 
                                        "Doing Tx IQ Cal for chain %d.\n", i);
875
 
 
876
 
                                if (REG_READ(ah, txiqcal_status[i]) &
877
 
                                    AR_PHY_TX_IQCAL_STATUS_FAILED) {
878
 
                                        ath_dbg(common, ATH_DBG_CALIBRATE,
879
779
                                        "Tx IQ Cal failed for chain %d.\n", i);
880
 
                                        goto tx_iqcal_fail;
881
 
                                }
882
 
 
883
 
                                for (j = 0; j < 3; j++) {
884
 
                                        u32 idx = 2 * j, offset = 4 * (3 * im + j);
885
 
 
886
 
                                        REG_RMW_FIELD(ah,
 
780
                                goto tx_iqcal_fail;
 
781
                        }
 
782
 
 
783
                        for (j = 0; j < 3; j++) {
 
784
                                u32 idx = 2 * j, offset = 4 * (3 * im + j);
 
785
 
 
786
                                REG_RMW_FIELD(ah,
887
787
                                                AR_PHY_CHAN_INFO_MEMORY,
888
788
                                                AR_PHY_CHAN_INFO_TAB_S2_READ,
889
789
                                                0);
890
790
 
891
 
                                        /* 32 bits */
892
 
                                        iq_res[idx] = REG_READ(ah,
893
 
                                                        chan_info_tab[i] +
894
 
                                                        offset);
 
791
                                /* 32 bits */
 
792
                                iq_res[idx] = REG_READ(ah,
 
793
                                                chan_info_tab[i] +
 
794
                                                offset);
895
795
 
896
 
                                        REG_RMW_FIELD(ah,
 
796
                                REG_RMW_FIELD(ah,
897
797
                                                AR_PHY_CHAN_INFO_MEMORY,
898
798
                                                AR_PHY_CHAN_INFO_TAB_S2_READ,
899
799
                                                1);
900
800
 
901
 
                                        /* 16 bits */
902
 
                                        iq_res[idx + 1] = 0xffff & REG_READ(ah,
903
 
                                                          chan_info_tab[i] + offset);
904
 
 
905
 
                                        ath_dbg(common, ATH_DBG_CALIBRATE,
906
 
                                                "IQ RES[%d]=0x%x"
907
 
                                                "IQ_RES[%d]=0x%x\n",
908
 
                                                idx, iq_res[idx], idx + 1,
909
 
                                                iq_res[idx + 1]);
910
 
                                }
911
 
 
912
 
                                if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
913
 
                                                            coeff.iqc_coeff)) {
914
 
                                        ath_dbg(common, ATH_DBG_CALIBRATE,
915
 
                                         "Failed in calculation of IQ correction.\n");
916
 
                                        goto tx_iqcal_fail;
917
 
                                }
918
 
 
919
 
                                coeff.mag_coeff[i][im][ip] =
920
 
                                                coeff.iqc_coeff[0] & 0x7f;
921
 
                                coeff.phs_coeff[i][im][ip] =
922
 
                                                (coeff.iqc_coeff[0] >> 7) & 0x7f;
923
 
 
924
 
                                if (coeff.mag_coeff[i][im][ip] > 63)
925
 
                                        coeff.mag_coeff[i][im][ip] -= 128;
926
 
                                if (coeff.phs_coeff[i][im][ip] > 63)
927
 
                                        coeff.phs_coeff[i][im][ip] -= 128;
928
 
                        }
 
801
                                /* 16 bits */
 
802
                                iq_res[idx + 1] = 0xffff & REG_READ(ah,
 
803
                                                chan_info_tab[i] + offset);
 
804
 
 
805
                                ath_dbg(common, ATH_DBG_CALIBRATE,
 
806
                                        "IQ RES[%d]=0x%x"
 
807
                                        "IQ_RES[%d]=0x%x\n",
 
808
                                        idx, iq_res[idx], idx + 1,
 
809
                                        iq_res[idx + 1]);
 
810
                        }
 
811
 
 
812
                        if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
 
813
                                                coeff.iqc_coeff)) {
 
814
                                ath_dbg(common, ATH_DBG_CALIBRATE,
 
815
                                        "Failed in calculation of \
 
816
                                        IQ correction.\n");
 
817
                                goto tx_iqcal_fail;
 
818
                        }
 
819
 
 
820
                        coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
 
821
                        coeff.phs_coeff[i][im] =
 
822
                                (coeff.iqc_coeff[0] >> 7) & 0x7f;
 
823
 
 
824
                        if (coeff.mag_coeff[i][im] > 63)
 
825
                                coeff.mag_coeff[i][im] -= 128;
 
826
                        if (coeff.phs_coeff[i][im] > 63)
 
827
                                coeff.phs_coeff[i][im] -= 128;
929
828
                }
930
829
        }
931
830
        ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff);
940
839
                               struct ath9k_channel *chan)
941
840
{
942
841
        struct ath_common *common = ath9k_hw_common(ah);
 
842
        struct ath9k_hw_capabilities *pCap = &ah->caps;
943
843
        int val;
 
844
        bool txiqcal_done = false;
944
845
 
945
846
        val = REG_READ(ah, AR_ENT_OTP);
946
847
        ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val);
947
848
 
948
 
        if (AR_SREV_9485(ah))
949
 
                ar9003_hw_set_chain_masks(ah, 0x1, 0x1);
950
 
        else if (val & AR_ENT_OTP_CHAIN2_DISABLE)
 
849
        /* Configure rx/tx chains before running AGC/TxiQ cals */
 
850
        if (val & AR_ENT_OTP_CHAIN2_DISABLE)
951
851
                ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
952
852
        else
953
 
                /*
954
 
                 * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain
955
 
                 * mode before running AGC/TxIQ cals
956
 
                 */
957
 
                ar9003_hw_set_chain_masks(ah, 0x7, 0x7);
 
853
                ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask,
 
854
                                          pCap->tx_chainmask);
958
855
 
959
856
        /* Do Tx IQ Calibration */
960
 
        if (AR_SREV_9485(ah))
961
 
                ar9003_hw_tx_iq_cal_run(ah);
962
 
        else
963
 
                ar9003_hw_tx_iq_cal(ah);
 
857
        REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
 
858
                      AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
 
859
                      DELPT);
964
860
 
965
 
        REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
966
 
        udelay(5);
967
 
        REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
 
861
        /*
 
862
         * For AR9485 or later chips, TxIQ cal runs as part of
 
863
         * AGC calibration
 
864
         */
 
865
        if (AR_SREV_9485_OR_LATER(ah))
 
866
                txiqcal_done = true;
 
867
        else {
 
868
                txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
 
869
                REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
 
870
                udelay(5);
 
871
                REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
 
872
        }
968
873
 
969
874
        /* Calibrate the AGC */
970
875
        REG_WRITE(ah, AR_PHY_AGC_CONTROL,
979
884
                return false;
980
885
        }
981
886
 
982
 
        if (AR_SREV_9485(ah))
 
887
        if (txiqcal_done)
983
888
                ar9003_hw_tx_iq_cal_post_proc(ah);
984
889
 
985
890
        /* Revert chainmasks to their original values before NF cal */