aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath5k/eeprom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath5k/eeprom.c')
-rw-r--r--drivers/net/wireless/ath5k/eeprom.c774
1 files changed, 542 insertions, 232 deletions
diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c
index ac45ca47ca87..c0fb3b09ba45 100644
--- a/drivers/net/wireless/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath5k/eeprom.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> 2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> 3 * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
4 * Copyright (c) 2008 Felix Fietkau <nbd@openwrt.org> 4 * Copyright (c) 2008-2009 Felix Fietkau <nbd@openwrt.org>
5 * 5 *
6 * Permission to use, copy, modify, and distribute this software for any 6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above 7 * purpose with or without fee is hereby granted, provided that the above
@@ -98,11 +98,6 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
98 int ret; 98 int ret;
99 u16 val; 99 u16 val;
100 100
101 /* Initial TX thermal adjustment values */
102 ee->ee_tx_clip = 4;
103 ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
104 ee->ee_gain_select = 1;
105
106 /* 101 /*
107 * Read values from EEPROM and store them in the capability structure 102 * Read values from EEPROM and store them in the capability structure
108 */ 103 */
@@ -241,22 +236,22 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
241 ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); 236 ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
242 switch(mode) { 237 switch(mode) {
243 case AR5K_EEPROM_MODE_11A: 238 case AR5K_EEPROM_MODE_11A:
244 ee->ee_ob[mode][3] = (val >> 5) & 0x7; 239 ee->ee_ob[mode][3] = (val >> 5) & 0x7;
245 ee->ee_db[mode][3] = (val >> 2) & 0x7; 240 ee->ee_db[mode][3] = (val >> 2) & 0x7;
246 ee->ee_ob[mode][2] = (val << 1) & 0x7; 241 ee->ee_ob[mode][2] = (val << 1) & 0x7;
247 242
248 AR5K_EEPROM_READ(o++, val); 243 AR5K_EEPROM_READ(o++, val);
249 ee->ee_ob[mode][2] |= (val >> 15) & 0x1; 244 ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
250 ee->ee_db[mode][2] = (val >> 12) & 0x7; 245 ee->ee_db[mode][2] = (val >> 12) & 0x7;
251 ee->ee_ob[mode][1] = (val >> 9) & 0x7; 246 ee->ee_ob[mode][1] = (val >> 9) & 0x7;
252 ee->ee_db[mode][1] = (val >> 6) & 0x7; 247 ee->ee_db[mode][1] = (val >> 6) & 0x7;
253 ee->ee_ob[mode][0] = (val >> 3) & 0x7; 248 ee->ee_ob[mode][0] = (val >> 3) & 0x7;
254 ee->ee_db[mode][0] = val & 0x7; 249 ee->ee_db[mode][0] = val & 0x7;
255 break; 250 break;
256 case AR5K_EEPROM_MODE_11G: 251 case AR5K_EEPROM_MODE_11G:
257 case AR5K_EEPROM_MODE_11B: 252 case AR5K_EEPROM_MODE_11B:
258 ee->ee_ob[mode][1] = (val >> 4) & 0x7; 253 ee->ee_ob[mode][1] = (val >> 4) & 0x7;
259 ee->ee_db[mode][1] = val & 0x7; 254 ee->ee_db[mode][1] = val & 0x7;
260 break; 255 break;
261 } 256 }
262 257
@@ -504,35 +499,6 @@ ath5k_eeprom_init_modes(struct ath5k_hw *ah)
504 return 0; 499 return 0;
505} 500}
506 501
507/* Used to match PCDAC steps with power values on RF5111 chips
508 * (eeprom versions < 4). For RF5111 we have 10 pre-defined PCDAC
509 * steps that match with the power values we read from eeprom. On
510 * older eeprom versions (< 3.2) these steps are equaly spaced at
511 * 10% of the pcdac curve -until the curve reaches it's maximum-
512 * (10 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
513 * these 10 steps are spaced in a different way. This function returns
514 * the pcdac steps based on eeprom version and curve min/max so that we
515 * can have pcdac/pwr points.
516 */
517static inline void
518ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
519{
520 static const u16 intercepts3[] =
521 { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
522 static const u16 intercepts3_2[] =
523 { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
524 const u16 *ip;
525 int i;
526
527 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2)
528 ip = intercepts3_2;
529 else
530 ip = intercepts3;
531
532 for (i = 0; i < ARRAY_SIZE(intercepts3); i++)
533 *vp++ = (ip[i] * max + (100 - ip[i]) * min) / 100;
534}
535
536/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff 502/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff
537 * frequency mask) */ 503 * frequency mask) */
538static inline int 504static inline int
@@ -546,26 +512,25 @@ ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
546 int ret; 512 int ret;
547 u16 val; 513 u16 val;
548 514
515 ee->ee_n_piers[mode] = 0;
549 while(i < max) { 516 while(i < max) {
550 AR5K_EEPROM_READ(o++, val); 517 AR5K_EEPROM_READ(o++, val);
551 518
552 freq1 = (val >> 8) & 0xff; 519 freq1 = val & 0xff;
553 freq2 = val & 0xff; 520 if (!freq1)
554 521 break;
555 if (freq1) {
556 pc[i++].freq = ath5k_eeprom_bin2freq(ee,
557 freq1, mode);
558 ee->ee_n_piers[mode]++;
559 }
560 522
561 if (freq2) { 523 pc[i++].freq = ath5k_eeprom_bin2freq(ee,
562 pc[i++].freq = ath5k_eeprom_bin2freq(ee, 524 freq1, mode);
563 freq2, mode); 525 ee->ee_n_piers[mode]++;
564 ee->ee_n_piers[mode]++;
565 }
566 526
567 if (!freq1 || !freq2) 527 freq2 = (val >> 8) & 0xff;
528 if (!freq2)
568 break; 529 break;
530
531 pc[i++].freq = ath5k_eeprom_bin2freq(ee,
532 freq2, mode);
533 ee->ee_n_piers[mode]++;
569 } 534 }
570 535
571 /* return new offset */ 536 /* return new offset */
@@ -652,13 +617,122 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
652 return 0; 617 return 0;
653} 618}
654 619
655/* Read power calibration for RF5111 chips 620/*
621 * Read power calibration for RF5111 chips
622 *
656 * For RF5111 we have an XPD -eXternal Power Detector- curve 623 * For RF5111 we have an XPD -eXternal Power Detector- curve
657 * for each calibrated channel. Each curve has PCDAC steps on 624 * for each calibrated channel. Each curve has 0,5dB Power steps
658 * x axis and power on y axis and looks like a logarithmic 625 * on x axis and PCDAC steps (offsets) on y axis and looks like an
659 * function. To recreate the curve and pass the power values 626 * exponential function. To recreate the curve we read 11 points
660 * on the pcdac table, we read 10 points here and interpolate later. 627 * here and interpolate later.
661 */ 628 */
629
630/* Used to match PCDAC steps with power values on RF5111 chips
631 * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC
632 * steps that match with the power values we read from eeprom. On
633 * older eeprom versions (< 3.2) these steps are equaly spaced at
634 * 10% of the pcdac curve -until the curve reaches it's maximum-
635 * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
636 * these 11 steps are spaced in a different way. This function returns
637 * the pcdac steps based on eeprom version and curve min/max so that we
638 * can have pcdac/pwr points.
639 */
640static inline void
641ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
642{
643 const static u16 intercepts3[] =
644 { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
645 const static u16 intercepts3_2[] =
646 { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
647 const u16 *ip;
648 int i;
649
650 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2)
651 ip = intercepts3_2;
652 else
653 ip = intercepts3;
654
655 for (i = 0; i < ARRAY_SIZE(intercepts3); i++)
656 vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100;
657}
658
659/* Convert RF5111 specific data to generic raw data
660 * used by interpolation code */
661static int
662ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
663 struct ath5k_chan_pcal_info *chinfo)
664{
665 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
666 struct ath5k_chan_pcal_info_rf5111 *pcinfo;
667 struct ath5k_pdgain_info *pd;
668 u8 pier, point, idx;
669 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
670
671 /* Fill raw data for each calibration pier */
672 for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
673
674 pcinfo = &chinfo[pier].rf5111_info;
675
676 /* Allocate pd_curves for this cal pier */
677 chinfo[pier].pd_curves =
678 kcalloc(AR5K_EEPROM_N_PD_CURVES,
679 sizeof(struct ath5k_pdgain_info),
680 GFP_KERNEL);
681
682 if (!chinfo[pier].pd_curves)
683 return -ENOMEM;
684
685 /* Only one curve for RF5111
686 * find out which one and place
687 * in in pd_curves.
688 * Note: ee_x_gain is reversed here */
689 for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) {
690
691 if (!((ee->ee_x_gain[mode] >> idx) & 0x1)) {
692 pdgain_idx[0] = idx;
693 break;
694 }
695 }
696
697 ee->ee_pd_gains[mode] = 1;
698
699 pd = &chinfo[pier].pd_curves[idx];
700
701 pd->pd_points = AR5K_EEPROM_N_PWR_POINTS_5111;
702
703 /* Allocate pd points for this curve */
704 pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
705 sizeof(u8), GFP_KERNEL);
706 if (!pd->pd_step)
707 return -ENOMEM;
708
709 pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
710 sizeof(s16), GFP_KERNEL);
711 if (!pd->pd_pwr)
712 return -ENOMEM;
713
714 /* Fill raw dataset
715 * (convert power to 0.25dB units
716 * for RF5112 combatibility) */
717 for (point = 0; point < pd->pd_points; point++) {
718
719 /* Absolute values */
720 pd->pd_pwr[point] = 2 * pcinfo->pwr[point];
721
722 /* Already sorted */
723 pd->pd_step[point] = pcinfo->pcdac[point];
724 }
725
726 /* Set min/max pwr */
727 chinfo[pier].min_pwr = pd->pd_pwr[0];
728 chinfo[pier].max_pwr = pd->pd_pwr[10];
729
730 }
731
732 return 0;
733}
734
735/* Parse EEPROM data */
662static int 736static int
663ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) 737ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
664{ 738{
@@ -747,30 +821,165 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
747 cdata->pcdac_max, cdata->pcdac); 821 cdata->pcdac_max, cdata->pcdac);
748 } 822 }
749 823
750 return 0; 824 return ath5k_eeprom_convert_pcal_info_5111(ah, mode, pcal);
751} 825}
752 826
753/* Read power calibration for RF5112 chips 827
828/*
829 * Read power calibration for RF5112 chips
830 *
754 * For RF5112 we have 4 XPD -eXternal Power Detector- curves 831 * For RF5112 we have 4 XPD -eXternal Power Detector- curves
755 * for each calibrated channel on 0, -6, -12 and -18dbm but we only 832 * for each calibrated channel on 0, -6, -12 and -18dbm but we only
756 * use the higher (3) and the lower (0) curves. Each curve has PCDAC 833 * use the higher (3) and the lower (0) curves. Each curve has 0.5dB
757 * steps on x axis and power on y axis and looks like a linear 834 * power steps on x axis and PCDAC steps on y axis and looks like a
758 * function. To recreate the curve and pass the power values 835 * linear function. To recreate the curve and pass the power values
759 * on the pcdac table, we read 4 points for xpd 0 and 3 points 836 * on hw, we read 4 points for xpd 0 (lower gain -> max power)
760 * for xpd 3 here and interpolate later. 837 * and 3 points for xpd 3 (higher gain -> lower power) here and
838 * interpolate later.
761 * 839 *
762 * Note: Many vendors just use xpd 0 so xpd 3 is zeroed. 840 * Note: Many vendors just use xpd 0 so xpd 3 is zeroed.
763 */ 841 */
842
843/* Convert RF5112 specific data to generic raw data
844 * used by interpolation code */
845static int
846ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
847 struct ath5k_chan_pcal_info *chinfo)
848{
849 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
850 struct ath5k_chan_pcal_info_rf5112 *pcinfo;
851 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
852 unsigned int pier, pdg, point;
853
854 /* Fill raw data for each calibration pier */
855 for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
856
857 pcinfo = &chinfo[pier].rf5112_info;
858
859 /* Allocate pd_curves for this cal pier */
860 chinfo[pier].pd_curves =
861 kcalloc(AR5K_EEPROM_N_PD_CURVES,
862 sizeof(struct ath5k_pdgain_info),
863 GFP_KERNEL);
864
865 if (!chinfo[pier].pd_curves)
866 return -ENOMEM;
867
868 /* Fill pd_curves */
869 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
870
871 u8 idx = pdgain_idx[pdg];
872 struct ath5k_pdgain_info *pd =
873 &chinfo[pier].pd_curves[idx];
874
875 /* Lowest gain curve (max power) */
876 if (pdg == 0) {
877 /* One more point for better accuracy */
878 pd->pd_points = AR5K_EEPROM_N_XPD0_POINTS;
879
880 /* Allocate pd points for this curve */
881 pd->pd_step = kcalloc(pd->pd_points,
882 sizeof(u8), GFP_KERNEL);
883
884 if (!pd->pd_step)
885 return -ENOMEM;
886
887 pd->pd_pwr = kcalloc(pd->pd_points,
888 sizeof(s16), GFP_KERNEL);
889
890 if (!pd->pd_pwr)
891 return -ENOMEM;
892
893
894 /* Fill raw dataset
895 * (all power levels are in 0.25dB units) */
896 pd->pd_step[0] = pcinfo->pcdac_x0[0];
897 pd->pd_pwr[0] = pcinfo->pwr_x0[0];
898
899 for (point = 1; point < pd->pd_points;
900 point++) {
901 /* Absolute values */
902 pd->pd_pwr[point] =
903 pcinfo->pwr_x0[point];
904
905 /* Deltas */
906 pd->pd_step[point] =
907 pd->pd_step[point - 1] +
908 pcinfo->pcdac_x0[point];
909 }
910
911 /* Set min power for this frequency */
912 chinfo[pier].min_pwr = pd->pd_pwr[0];
913
914 /* Highest gain curve (min power) */
915 } else if (pdg == 1) {
916
917 pd->pd_points = AR5K_EEPROM_N_XPD3_POINTS;
918
919 /* Allocate pd points for this curve */
920 pd->pd_step = kcalloc(pd->pd_points,
921 sizeof(u8), GFP_KERNEL);
922
923 if (!pd->pd_step)
924 return -ENOMEM;
925
926 pd->pd_pwr = kcalloc(pd->pd_points,
927 sizeof(s16), GFP_KERNEL);
928
929 if (!pd->pd_pwr)
930 return -ENOMEM;
931
932 /* Fill raw dataset
933 * (all power levels are in 0.25dB units) */
934 for (point = 0; point < pd->pd_points;
935 point++) {
936 /* Absolute values */
937 pd->pd_pwr[point] =
938 pcinfo->pwr_x3[point];
939
940 /* Fixed points */
941 pd->pd_step[point] =
942 pcinfo->pcdac_x3[point];
943 }
944
945 /* Since we have a higher gain curve
946 * override min power */
947 chinfo[pier].min_pwr = pd->pd_pwr[0];
948 }
949 }
950 }
951
952 return 0;
953}
954
955/* Parse EEPROM data */
764static int 956static int
765ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) 957ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
766{ 958{
767 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 959 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
768 struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info; 960 struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info;
769 struct ath5k_chan_pcal_info *gen_chan_info; 961 struct ath5k_chan_pcal_info *gen_chan_info;
962 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
770 u32 offset; 963 u32 offset;
771 unsigned int i, c; 964 u8 i, c;
772 u16 val; 965 u16 val;
773 int ret; 966 int ret;
967 u8 pd_gains = 0;
968
969 /* Count how many curves we have and
970 * identify them (which one of the 4
971 * available curves we have on each count).
972 * Curves are stored from lower (x0) to
973 * higher (x3) gain */
974 for (i = 0; i < AR5K_EEPROM_N_PD_CURVES; i++) {
975 /* ee_x_gain[mode] is x gain mask */
976 if ((ee->ee_x_gain[mode] >> i) & 0x1)
977 pdgain_idx[pd_gains++] = i;
978 }
979 ee->ee_pd_gains[mode] = pd_gains;
980
981 if (pd_gains == 0 || pd_gains > 2)
982 return -EINVAL;
774 983
775 switch (mode) { 984 switch (mode) {
776 case AR5K_EEPROM_MODE_11A: 985 case AR5K_EEPROM_MODE_11A:
@@ -808,13 +1017,13 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
808 for (i = 0; i < ee->ee_n_piers[mode]; i++) { 1017 for (i = 0; i < ee->ee_n_piers[mode]; i++) {
809 chan_pcal_info = &gen_chan_info[i].rf5112_info; 1018 chan_pcal_info = &gen_chan_info[i].rf5112_info;
810 1019
811 /* Power values in dBm * 4 1020 /* Power values in quarter dB
812 * for the lower xpd gain curve 1021 * for the lower xpd gain curve
813 * (0 dBm -> higher output power) */ 1022 * (0 dBm -> higher output power) */
814 for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) { 1023 for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
815 AR5K_EEPROM_READ(offset++, val); 1024 AR5K_EEPROM_READ(offset++, val);
816 chan_pcal_info->pwr_x0[c] = (val & 0xff); 1025 chan_pcal_info->pwr_x0[c] = (s8) (val & 0xff);
817 chan_pcal_info->pwr_x0[++c] = ((val >> 8) & 0xff); 1026 chan_pcal_info->pwr_x0[++c] = (s8) ((val >> 8) & 0xff);
818 } 1027 }
819 1028
820 /* PCDAC steps 1029 /* PCDAC steps
@@ -825,12 +1034,12 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
825 chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f); 1034 chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f);
826 chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f); 1035 chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f);
827 1036
828 /* Power values in dBm * 4 1037 /* Power values in quarter dB
829 * for the higher xpd gain curve 1038 * for the higher xpd gain curve
830 * (18 dBm -> lower output power) */ 1039 * (18 dBm -> lower output power) */
831 AR5K_EEPROM_READ(offset++, val); 1040 AR5K_EEPROM_READ(offset++, val);
832 chan_pcal_info->pwr_x3[0] = (val & 0xff); 1041 chan_pcal_info->pwr_x3[0] = (s8) (val & 0xff);
833 chan_pcal_info->pwr_x3[1] = ((val >> 8) & 0xff); 1042 chan_pcal_info->pwr_x3[1] = (s8) ((val >> 8) & 0xff);
834 1043
835 AR5K_EEPROM_READ(offset++, val); 1044 AR5K_EEPROM_READ(offset++, val);
836 chan_pcal_info->pwr_x3[2] = (val & 0xff); 1045 chan_pcal_info->pwr_x3[2] = (val & 0xff);
@@ -843,24 +1052,36 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
843 chan_pcal_info->pcdac_x3[2] = 63; 1052 chan_pcal_info->pcdac_x3[2] = 63;
844 1053
845 if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) { 1054 if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) {
846 chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0xff); 1055 chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0x3f);
847 1056
848 /* Last xpd0 power level is also channel maximum */ 1057 /* Last xpd0 power level is also channel maximum */
849 gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3]; 1058 gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3];
850 } else { 1059 } else {
851 chan_pcal_info->pcdac_x0[0] = 1; 1060 chan_pcal_info->pcdac_x0[0] = 1;
852 gen_chan_info[i].max_pwr = ((val >> 8) & 0xff); 1061 gen_chan_info[i].max_pwr = (s8) ((val >> 8) & 0xff);
853 } 1062 }
854 1063
855 /* Recreate pcdac_x0 table for this channel using pcdac steps */
856 chan_pcal_info->pcdac_x0[1] += chan_pcal_info->pcdac_x0[0];
857 chan_pcal_info->pcdac_x0[2] += chan_pcal_info->pcdac_x0[1];
858 chan_pcal_info->pcdac_x0[3] += chan_pcal_info->pcdac_x0[2];
859 } 1064 }
860 1065
861 return 0; 1066 return ath5k_eeprom_convert_pcal_info_5112(ah, mode, gen_chan_info);
862} 1067}
863 1068
1069
1070/*
1071 * Read power calibration for RF2413 chips
1072 *
1073 * For RF2413 we have a Power to PDDAC table (Power Detector)
1074 * instead of a PCDAC and 4 pd gain curves for each calibrated channel.
1075 * Each curve has power on x axis in 0.5 db steps and PDDADC steps on y
1076 * axis and looks like an exponential function like the RF5111 curve.
1077 *
1078 * To recreate the curves we read here the points and interpolate
1079 * later. Note that in most cases only 2 (higher and lower) curves are
1080 * used (like RF5112) but vendors have the oportunity to include all
1081 * 4 curves on eeprom. The final curve (higher power) has an extra
1082 * point for better accuracy like RF5112.
1083 */
1084
864/* For RF2413 power calibration data doesn't start on a fixed location and 1085/* For RF2413 power calibration data doesn't start on a fixed location and
865 * if a mode is not supported, it's section is missing -not zeroed-. 1086 * if a mode is not supported, it's section is missing -not zeroed-.
866 * So we need to calculate the starting offset for each section by using 1087 * So we need to calculate the starting offset for each section by using
@@ -890,13 +1111,15 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
890 switch(mode) { 1111 switch(mode) {
891 case AR5K_EEPROM_MODE_11G: 1112 case AR5K_EEPROM_MODE_11G:
892 if (AR5K_EEPROM_HDR_11B(ee->ee_header)) 1113 if (AR5K_EEPROM_HDR_11B(ee->ee_header))
893 offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11B) + 1114 offset += ath5k_pdgains_size_2413(ee,
894 AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; 1115 AR5K_EEPROM_MODE_11B) +
1116 AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
895 /* fall through */ 1117 /* fall through */
896 case AR5K_EEPROM_MODE_11B: 1118 case AR5K_EEPROM_MODE_11B:
897 if (AR5K_EEPROM_HDR_11A(ee->ee_header)) 1119 if (AR5K_EEPROM_HDR_11A(ee->ee_header))
898 offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11A) + 1120 offset += ath5k_pdgains_size_2413(ee,
899 AR5K_EEPROM_N_5GHZ_CHAN / 2; 1121 AR5K_EEPROM_MODE_11A) +
1122 AR5K_EEPROM_N_5GHZ_CHAN / 2;
900 /* fall through */ 1123 /* fall through */
901 case AR5K_EEPROM_MODE_11A: 1124 case AR5K_EEPROM_MODE_11A:
902 break; 1125 break;
@@ -907,37 +1130,118 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
907 return offset; 1130 return offset;
908} 1131}
909 1132
910/* Read power calibration for RF2413 chips 1133/* Convert RF2413 specific data to generic raw data
911 * For RF2413 we have a PDDAC table (Power Detector) instead 1134 * used by interpolation code */
912 * of a PCDAC and 4 pd gain curves for each calibrated channel. 1135static int
913 * Each curve has PDDAC steps on x axis and power on y axis and 1136ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
914 * looks like an exponential function. To recreate the curves 1137 struct ath5k_chan_pcal_info *chinfo)
915 * we read here the points and interpolate later. Note that 1138{
916 * in most cases only higher and lower curves are used (like 1139 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
917 * RF5112) but vendors have the oportunity to include all 4 1140 struct ath5k_chan_pcal_info_rf2413 *pcinfo;
918 * curves on eeprom. The final curve (higher power) has an extra 1141 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
919 * point for better accuracy like RF5112. 1142 unsigned int pier, pdg, point;
920 */ 1143
1144 /* Fill raw data for each calibration pier */
1145 for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
1146
1147 pcinfo = &chinfo[pier].rf2413_info;
1148
1149 /* Allocate pd_curves for this cal pier */
1150 chinfo[pier].pd_curves =
1151 kcalloc(AR5K_EEPROM_N_PD_CURVES,
1152 sizeof(struct ath5k_pdgain_info),
1153 GFP_KERNEL);
1154
1155 if (!chinfo[pier].pd_curves)
1156 return -ENOMEM;
1157
1158 /* Fill pd_curves */
1159 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
1160
1161 u8 idx = pdgain_idx[pdg];
1162 struct ath5k_pdgain_info *pd =
1163 &chinfo[pier].pd_curves[idx];
1164
1165 /* One more point for the highest power
1166 * curve (lowest gain) */
1167 if (pdg == ee->ee_pd_gains[mode] - 1)
1168 pd->pd_points = AR5K_EEPROM_N_PD_POINTS;
1169 else
1170 pd->pd_points = AR5K_EEPROM_N_PD_POINTS - 1;
1171
1172 /* Allocate pd points for this curve */
1173 pd->pd_step = kcalloc(pd->pd_points,
1174 sizeof(u8), GFP_KERNEL);
1175
1176 if (!pd->pd_step)
1177 return -ENOMEM;
1178
1179 pd->pd_pwr = kcalloc(pd->pd_points,
1180 sizeof(s16), GFP_KERNEL);
1181
1182 if (!pd->pd_pwr)
1183 return -ENOMEM;
1184
1185 /* Fill raw dataset
1186 * convert all pwr levels to
1187 * quarter dB for RF5112 combatibility */
1188 pd->pd_step[0] = pcinfo->pddac_i[pdg];
1189 pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg];
1190
1191 for (point = 1; point < pd->pd_points; point++) {
1192
1193 pd->pd_pwr[point] = pd->pd_pwr[point - 1] +
1194 2 * pcinfo->pwr[pdg][point - 1];
1195
1196 pd->pd_step[point] = pd->pd_step[point - 1] +
1197 pcinfo->pddac[pdg][point - 1];
1198
1199 }
1200
1201 /* Highest gain curve -> min power */
1202 if (pdg == 0)
1203 chinfo[pier].min_pwr = pd->pd_pwr[0];
1204
1205 /* Lowest gain curve -> max power */
1206 if (pdg == ee->ee_pd_gains[mode] - 1)
1207 chinfo[pier].max_pwr =
1208 pd->pd_pwr[pd->pd_points - 1];
1209 }
1210 }
1211
1212 return 0;
1213}
1214
1215/* Parse EEPROM data */
921static int 1216static int
922ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) 1217ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
923{ 1218{
924 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 1219 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
925 struct ath5k_chan_pcal_info_rf2413 *chan_pcal_info; 1220 struct ath5k_chan_pcal_info_rf2413 *pcinfo;
926 struct ath5k_chan_pcal_info *gen_chan_info; 1221 struct ath5k_chan_pcal_info *chinfo;
927 unsigned int i, c; 1222 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
928 u32 offset; 1223 u32 offset;
929 int ret; 1224 int idx, i, ret;
930 u16 val; 1225 u16 val;
931 u8 pd_gains = 0; 1226 u8 pd_gains = 0;
932 1227
933 if (ee->ee_x_gain[mode] & 0x1) pd_gains++; 1228 /* Count how many curves we have and
934 if ((ee->ee_x_gain[mode] >> 1) & 0x1) pd_gains++; 1229 * identify them (which one of the 4
935 if ((ee->ee_x_gain[mode] >> 2) & 0x1) pd_gains++; 1230 * available curves we have on each count).
936 if ((ee->ee_x_gain[mode] >> 3) & 0x1) pd_gains++; 1231 * Curves are stored from higher to
1232 * lower gain so we go backwards */
1233 for (idx = AR5K_EEPROM_N_PD_CURVES - 1; idx >= 0; idx--) {
1234 /* ee_x_gain[mode] is x gain mask */
1235 if ((ee->ee_x_gain[mode] >> idx) & 0x1)
1236 pdgain_idx[pd_gains++] = idx;
1237
1238 }
937 ee->ee_pd_gains[mode] = pd_gains; 1239 ee->ee_pd_gains[mode] = pd_gains;
938 1240
1241 if (pd_gains == 0)
1242 return -EINVAL;
1243
939 offset = ath5k_cal_data_offset_2413(ee, mode); 1244 offset = ath5k_cal_data_offset_2413(ee, mode);
940 ee->ee_n_piers[mode] = 0;
941 switch (mode) { 1245 switch (mode) {
942 case AR5K_EEPROM_MODE_11A: 1246 case AR5K_EEPROM_MODE_11A:
943 if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) 1247 if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
@@ -945,7 +1249,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
945 1249
946 ath5k_eeprom_init_11a_pcal_freq(ah, offset); 1250 ath5k_eeprom_init_11a_pcal_freq(ah, offset);
947 offset += AR5K_EEPROM_N_5GHZ_CHAN / 2; 1251 offset += AR5K_EEPROM_N_5GHZ_CHAN / 2;
948 gen_chan_info = ee->ee_pwr_cal_a; 1252 chinfo = ee->ee_pwr_cal_a;
949 break; 1253 break;
950 case AR5K_EEPROM_MODE_11B: 1254 case AR5K_EEPROM_MODE_11B:
951 if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) 1255 if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
@@ -953,7 +1257,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
953 1257
954 ath5k_eeprom_init_11bg_2413(ah, mode, offset); 1258 ath5k_eeprom_init_11bg_2413(ah, mode, offset);
955 offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; 1259 offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
956 gen_chan_info = ee->ee_pwr_cal_b; 1260 chinfo = ee->ee_pwr_cal_b;
957 break; 1261 break;
958 case AR5K_EEPROM_MODE_11G: 1262 case AR5K_EEPROM_MODE_11G:
959 if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) 1263 if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
@@ -961,41 +1265,35 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
961 1265
962 ath5k_eeprom_init_11bg_2413(ah, mode, offset); 1266 ath5k_eeprom_init_11bg_2413(ah, mode, offset);
963 offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; 1267 offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
964 gen_chan_info = ee->ee_pwr_cal_g; 1268 chinfo = ee->ee_pwr_cal_g;
965 break; 1269 break;
966 default: 1270 default:
967 return -EINVAL; 1271 return -EINVAL;
968 } 1272 }
969 1273
970 if (pd_gains == 0)
971 return 0;
972
973 for (i = 0; i < ee->ee_n_piers[mode]; i++) { 1274 for (i = 0; i < ee->ee_n_piers[mode]; i++) {
974 chan_pcal_info = &gen_chan_info[i].rf2413_info; 1275 pcinfo = &chinfo[i].rf2413_info;
975 1276
976 /* 1277 /*
977 * Read pwr_i, pddac_i and the first 1278 * Read pwr_i, pddac_i and the first
978 * 2 pd points (pwr, pddac) 1279 * 2 pd points (pwr, pddac)
979 */ 1280 */
980 AR5K_EEPROM_READ(offset++, val); 1281 AR5K_EEPROM_READ(offset++, val);
981 chan_pcal_info->pwr_i[0] = val & 0x1f; 1282 pcinfo->pwr_i[0] = val & 0x1f;
982 chan_pcal_info->pddac_i[0] = (val >> 5) & 0x7f; 1283 pcinfo->pddac_i[0] = (val >> 5) & 0x7f;
983 chan_pcal_info->pwr[0][0] = 1284 pcinfo->pwr[0][0] = (val >> 12) & 0xf;
984 (val >> 12) & 0xf;
985 1285
986 AR5K_EEPROM_READ(offset++, val); 1286 AR5K_EEPROM_READ(offset++, val);
987 chan_pcal_info->pddac[0][0] = val & 0x3f; 1287 pcinfo->pddac[0][0] = val & 0x3f;
988 chan_pcal_info->pwr[0][1] = (val >> 6) & 0xf; 1288 pcinfo->pwr[0][1] = (val >> 6) & 0xf;
989 chan_pcal_info->pddac[0][1] = 1289 pcinfo->pddac[0][1] = (val >> 10) & 0x3f;
990 (val >> 10) & 0x3f;
991 1290
992 AR5K_EEPROM_READ(offset++, val); 1291 AR5K_EEPROM_READ(offset++, val);
993 chan_pcal_info->pwr[0][2] = val & 0xf; 1292 pcinfo->pwr[0][2] = val & 0xf;
994 chan_pcal_info->pddac[0][2] = 1293 pcinfo->pddac[0][2] = (val >> 4) & 0x3f;
995 (val >> 4) & 0x3f;
996 1294
997 chan_pcal_info->pwr[0][3] = 0; 1295 pcinfo->pwr[0][3] = 0;
998 chan_pcal_info->pddac[0][3] = 0; 1296 pcinfo->pddac[0][3] = 0;
999 1297
1000 if (pd_gains > 1) { 1298 if (pd_gains > 1) {
1001 /* 1299 /*
@@ -1003,44 +1301,36 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
1003 * so it only has 2 pd points. 1301 * so it only has 2 pd points.
1004 * Continue wih pd gain 1. 1302 * Continue wih pd gain 1.
1005 */ 1303 */
1006 chan_pcal_info->pwr_i[1] = (val >> 10) & 0x1f; 1304 pcinfo->pwr_i[1] = (val >> 10) & 0x1f;
1007 1305
1008 chan_pcal_info->pddac_i[1] = (val >> 15) & 0x1; 1306 pcinfo->pddac_i[1] = (val >> 15) & 0x1;
1009 AR5K_EEPROM_READ(offset++, val); 1307 AR5K_EEPROM_READ(offset++, val);
1010 chan_pcal_info->pddac_i[1] |= (val & 0x3F) << 1; 1308 pcinfo->pddac_i[1] |= (val & 0x3F) << 1;
1011 1309
1012 chan_pcal_info->pwr[1][0] = (val >> 6) & 0xf; 1310 pcinfo->pwr[1][0] = (val >> 6) & 0xf;
1013 chan_pcal_info->pddac[1][0] = 1311 pcinfo->pddac[1][0] = (val >> 10) & 0x3f;
1014 (val >> 10) & 0x3f;
1015 1312
1016 AR5K_EEPROM_READ(offset++, val); 1313 AR5K_EEPROM_READ(offset++, val);
1017 chan_pcal_info->pwr[1][1] = val & 0xf; 1314 pcinfo->pwr[1][1] = val & 0xf;
1018 chan_pcal_info->pddac[1][1] = 1315 pcinfo->pddac[1][1] = (val >> 4) & 0x3f;
1019 (val >> 4) & 0x3f; 1316 pcinfo->pwr[1][2] = (val >> 10) & 0xf;
1020 chan_pcal_info->pwr[1][2] = 1317
1021 (val >> 10) & 0xf; 1318 pcinfo->pddac[1][2] = (val >> 14) & 0x3;
1022
1023 chan_pcal_info->pddac[1][2] =
1024 (val >> 14) & 0x3;
1025 AR5K_EEPROM_READ(offset++, val); 1319 AR5K_EEPROM_READ(offset++, val);
1026 chan_pcal_info->pddac[1][2] |= 1320 pcinfo->pddac[1][2] |= (val & 0xF) << 2;
1027 (val & 0xF) << 2;
1028 1321
1029 chan_pcal_info->pwr[1][3] = 0; 1322 pcinfo->pwr[1][3] = 0;
1030 chan_pcal_info->pddac[1][3] = 0; 1323 pcinfo->pddac[1][3] = 0;
1031 } else if (pd_gains == 1) { 1324 } else if (pd_gains == 1) {
1032 /* 1325 /*
1033 * Pd gain 0 is the last one so 1326 * Pd gain 0 is the last one so
1034 * read the extra point. 1327 * read the extra point.
1035 */ 1328 */
1036 chan_pcal_info->pwr[0][3] = 1329 pcinfo->pwr[0][3] = (val >> 10) & 0xf;
1037 (val >> 10) & 0xf;
1038 1330
1039 chan_pcal_info->pddac[0][3] = 1331 pcinfo->pddac[0][3] = (val >> 14) & 0x3;
1040 (val >> 14) & 0x3;
1041 AR5K_EEPROM_READ(offset++, val); 1332 AR5K_EEPROM_READ(offset++, val);
1042 chan_pcal_info->pddac[0][3] |= 1333 pcinfo->pddac[0][3] |= (val & 0xF) << 2;
1043 (val & 0xF) << 2;
1044 } 1334 }
1045 1335
1046 /* 1336 /*
@@ -1048,105 +1338,65 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
1048 * as above. 1338 * as above.
1049 */ 1339 */
1050 if (pd_gains > 2) { 1340 if (pd_gains > 2) {
1051 chan_pcal_info->pwr_i[2] = (val >> 4) & 0x1f; 1341 pcinfo->pwr_i[2] = (val >> 4) & 0x1f;
1052 chan_pcal_info->pddac_i[2] = (val >> 9) & 0x7f; 1342 pcinfo->pddac_i[2] = (val >> 9) & 0x7f;
1053 1343
1054 AR5K_EEPROM_READ(offset++, val); 1344 AR5K_EEPROM_READ(offset++, val);
1055 chan_pcal_info->pwr[2][0] = 1345 pcinfo->pwr[2][0] = (val >> 0) & 0xf;
1056 (val >> 0) & 0xf; 1346 pcinfo->pddac[2][0] = (val >> 4) & 0x3f;
1057 chan_pcal_info->pddac[2][0] = 1347 pcinfo->pwr[2][1] = (val >> 10) & 0xf;
1058 (val >> 4) & 0x3f; 1348
1059 chan_pcal_info->pwr[2][1] = 1349 pcinfo->pddac[2][1] = (val >> 14) & 0x3;
1060 (val >> 10) & 0xf;
1061
1062 chan_pcal_info->pddac[2][1] =
1063 (val >> 14) & 0x3;
1064 AR5K_EEPROM_READ(offset++, val); 1350 AR5K_EEPROM_READ(offset++, val);
1065 chan_pcal_info->pddac[2][1] |= 1351 pcinfo->pddac[2][1] |= (val & 0xF) << 2;
1066 (val & 0xF) << 2;
1067 1352
1068 chan_pcal_info->pwr[2][2] = 1353 pcinfo->pwr[2][2] = (val >> 4) & 0xf;
1069 (val >> 4) & 0xf; 1354 pcinfo->pddac[2][2] = (val >> 8) & 0x3f;
1070 chan_pcal_info->pddac[2][2] =
1071 (val >> 8) & 0x3f;
1072 1355
1073 chan_pcal_info->pwr[2][3] = 0; 1356 pcinfo->pwr[2][3] = 0;
1074 chan_pcal_info->pddac[2][3] = 0; 1357 pcinfo->pddac[2][3] = 0;
1075 } else if (pd_gains == 2) { 1358 } else if (pd_gains == 2) {
1076 chan_pcal_info->pwr[1][3] = 1359 pcinfo->pwr[1][3] = (val >> 4) & 0xf;
1077 (val >> 4) & 0xf; 1360 pcinfo->pddac[1][3] = (val >> 8) & 0x3f;
1078 chan_pcal_info->pddac[1][3] =
1079 (val >> 8) & 0x3f;
1080 } 1361 }
1081 1362
1082 if (pd_gains > 3) { 1363 if (pd_gains > 3) {
1083 chan_pcal_info->pwr_i[3] = (val >> 14) & 0x3; 1364 pcinfo->pwr_i[3] = (val >> 14) & 0x3;
1084 AR5K_EEPROM_READ(offset++, val); 1365 AR5K_EEPROM_READ(offset++, val);
1085 chan_pcal_info->pwr_i[3] |= ((val >> 0) & 0x7) << 2; 1366 pcinfo->pwr_i[3] |= ((val >> 0) & 0x7) << 2;
1086 1367
1087 chan_pcal_info->pddac_i[3] = (val >> 3) & 0x7f; 1368 pcinfo->pddac_i[3] = (val >> 3) & 0x7f;
1088 chan_pcal_info->pwr[3][0] = 1369 pcinfo->pwr[3][0] = (val >> 10) & 0xf;
1089 (val >> 10) & 0xf; 1370 pcinfo->pddac[3][0] = (val >> 14) & 0x3;
1090 chan_pcal_info->pddac[3][0] =
1091 (val >> 14) & 0x3;
1092 1371
1093 AR5K_EEPROM_READ(offset++, val); 1372 AR5K_EEPROM_READ(offset++, val);
1094 chan_pcal_info->pddac[3][0] |= 1373 pcinfo->pddac[3][0] |= (val & 0xF) << 2;
1095 (val & 0xF) << 2; 1374 pcinfo->pwr[3][1] = (val >> 4) & 0xf;
1096 chan_pcal_info->pwr[3][1] = 1375 pcinfo->pddac[3][1] = (val >> 8) & 0x3f;
1097 (val >> 4) & 0xf; 1376
1098 chan_pcal_info->pddac[3][1] = 1377 pcinfo->pwr[3][2] = (val >> 14) & 0x3;
1099 (val >> 8) & 0x3f;
1100
1101 chan_pcal_info->pwr[3][2] =
1102 (val >> 14) & 0x3;
1103 AR5K_EEPROM_READ(offset++, val); 1378 AR5K_EEPROM_READ(offset++, val);
1104 chan_pcal_info->pwr[3][2] |= 1379 pcinfo->pwr[3][2] |= ((val >> 0) & 0x3) << 2;
1105 ((val >> 0) & 0x3) << 2;
1106 1380
1107 chan_pcal_info->pddac[3][2] = 1381 pcinfo->pddac[3][2] = (val >> 2) & 0x3f;
1108 (val >> 2) & 0x3f; 1382 pcinfo->pwr[3][3] = (val >> 8) & 0xf;
1109 chan_pcal_info->pwr[3][3] =
1110 (val >> 8) & 0xf;
1111 1383
1112 chan_pcal_info->pddac[3][3] = 1384 pcinfo->pddac[3][3] = (val >> 12) & 0xF;
1113 (val >> 12) & 0xF;
1114 AR5K_EEPROM_READ(offset++, val); 1385 AR5K_EEPROM_READ(offset++, val);
1115 chan_pcal_info->pddac[3][3] |= 1386 pcinfo->pddac[3][3] |= ((val >> 0) & 0x3) << 4;
1116 ((val >> 0) & 0x3) << 4;
1117 } else if (pd_gains == 3) { 1387 } else if (pd_gains == 3) {
1118 chan_pcal_info->pwr[2][3] = 1388 pcinfo->pwr[2][3] = (val >> 14) & 0x3;
1119 (val >> 14) & 0x3;
1120 AR5K_EEPROM_READ(offset++, val); 1389 AR5K_EEPROM_READ(offset++, val);
1121 chan_pcal_info->pwr[2][3] |= 1390 pcinfo->pwr[2][3] |= ((val >> 0) & 0x3) << 2;
1122 ((val >> 0) & 0x3) << 2;
1123
1124 chan_pcal_info->pddac[2][3] =
1125 (val >> 2) & 0x3f;
1126 }
1127 1391
1128 for (c = 0; c < pd_gains; c++) { 1392 pcinfo->pddac[2][3] = (val >> 2) & 0x3f;
1129 /* Recreate pwr table for this channel using pwr steps */
1130 chan_pcal_info->pwr[c][0] += chan_pcal_info->pwr_i[c] * 2;
1131 chan_pcal_info->pwr[c][1] += chan_pcal_info->pwr[c][0];
1132 chan_pcal_info->pwr[c][2] += chan_pcal_info->pwr[c][1];
1133 chan_pcal_info->pwr[c][3] += chan_pcal_info->pwr[c][2];
1134 if (chan_pcal_info->pwr[c][3] == chan_pcal_info->pwr[c][2])
1135 chan_pcal_info->pwr[c][3] = 0;
1136
1137 /* Recreate pddac table for this channel using pddac steps */
1138 chan_pcal_info->pddac[c][0] += chan_pcal_info->pddac_i[c];
1139 chan_pcal_info->pddac[c][1] += chan_pcal_info->pddac[c][0];
1140 chan_pcal_info->pddac[c][2] += chan_pcal_info->pddac[c][1];
1141 chan_pcal_info->pddac[c][3] += chan_pcal_info->pddac[c][2];
1142 if (chan_pcal_info->pddac[c][3] == chan_pcal_info->pddac[c][2])
1143 chan_pcal_info->pddac[c][3] = 0;
1144 } 1393 }
1145 } 1394 }
1146 1395
1147 return 0; 1396 return ath5k_eeprom_convert_pcal_info_2413(ah, mode, chinfo);
1148} 1397}
1149 1398
1399
1150/* 1400/*
1151 * Read per rate target power (this is the maximum tx power 1401 * Read per rate target power (this is the maximum tx power
1152 * supported by the card). This info is used when setting 1402 * supported by the card). This info is used when setting
@@ -1154,11 +1404,12 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
1154 * 1404 *
1155 * This also works for v5 EEPROMs. 1405 * This also works for v5 EEPROMs.
1156 */ 1406 */
1157static int ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) 1407static int
1408ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode)
1158{ 1409{
1159 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 1410 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1160 struct ath5k_rate_pcal_info *rate_pcal_info; 1411 struct ath5k_rate_pcal_info *rate_pcal_info;
1161 u16 *rate_target_pwr_num; 1412 u8 *rate_target_pwr_num;
1162 u32 offset; 1413 u32 offset;
1163 u16 val; 1414 u16 val;
1164 int ret, i; 1415 int ret, i;
@@ -1264,7 +1515,9 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
1264 else 1515 else
1265 read_pcal = ath5k_eeprom_read_pcal_info_5111; 1516 read_pcal = ath5k_eeprom_read_pcal_info_5111;
1266 1517
1267 for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) { 1518
1519 for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G;
1520 mode++) {
1268 err = read_pcal(ah, mode); 1521 err = read_pcal(ah, mode);
1269 if (err) 1522 if (err)
1270 return err; 1523 return err;
@@ -1277,6 +1530,62 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
1277 return 0; 1530 return 0;
1278} 1531}
1279 1532
1533static int
1534ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
1535{
1536 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1537 struct ath5k_chan_pcal_info *chinfo;
1538 u8 pier, pdg;
1539
1540 switch (mode) {
1541 case AR5K_EEPROM_MODE_11A:
1542 if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
1543 return 0;
1544 chinfo = ee->ee_pwr_cal_a;
1545 break;
1546 case AR5K_EEPROM_MODE_11B:
1547 if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
1548 return 0;
1549 chinfo = ee->ee_pwr_cal_b;
1550 break;
1551 case AR5K_EEPROM_MODE_11G:
1552 if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
1553 return 0;
1554 chinfo = ee->ee_pwr_cal_g;
1555 break;
1556 default:
1557 return -EINVAL;
1558 }
1559
1560 for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
1561 if (!chinfo[pier].pd_curves)
1562 continue;
1563
1564 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
1565 struct ath5k_pdgain_info *pd =
1566 &chinfo[pier].pd_curves[pdg];
1567
1568 if (pd != NULL) {
1569 kfree(pd->pd_step);
1570 kfree(pd->pd_pwr);
1571 }
1572 }
1573
1574 kfree(chinfo[pier].pd_curves);
1575 }
1576
1577 return 0;
1578}
1579
1580void
1581ath5k_eeprom_detach(struct ath5k_hw *ah)
1582{
1583 u8 mode;
1584
1585 for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++)
1586 ath5k_eeprom_free_pcal_info(ah, mode);
1587}
1588
1280/* Read conformance test limits used for regulatory control */ 1589/* Read conformance test limits used for regulatory control */
1281static int 1590static int
1282ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) 1591ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
@@ -1457,3 +1766,4 @@ bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah)
1457 else 1766 else
1458 return false; 1767 return false;
1459} 1768}
1769