diff options
author | John Hsu <KCHSU0@nuvoton.com> | 2016-03-15 00:09:36 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-05-30 11:17:44 -0400 |
commit | 407c71b69850aa789c70f7f7e54244739983d8d2 (patch) | |
tree | 89e366a4584052c8ac8e706d607f24a1f7c79869 | |
parent | 70543c300902b35b6f8cfafa8fff857bd84e351f (diff) |
ASoC: nau8825: improve FLL function for better performance
In FLL calculation, increase VCO/DCO frequency for better performance.
Besides, have different register configuration according to fraction or not
when apply FLL parameters.
Signed-off-by: John Hsu <KCHSU0@nuvoton.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/codecs/nau8825.c | 47 | ||||
-rw-r--r-- | sound/soc/codecs/nau8825.h | 13 |
2 files changed, 42 insertions, 18 deletions
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index b45ca8a32069..cb08a358b2a3 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include "nau8825.h" | 31 | #include "nau8825.h" |
32 | 32 | ||
33 | #define NAU_FREF_MAX 13500000 | 33 | #define NAU_FREF_MAX 13500000 |
34 | #define NAU_FVCO_MAX 100000000 | 34 | #define NAU_FVCO_MAX 124000000 |
35 | #define NAU_FVCO_MIN 90000000 | 35 | #define NAU_FVCO_MIN 90000000 |
36 | 36 | ||
37 | struct nau8825_fll { | 37 | struct nau8825_fll { |
@@ -973,8 +973,8 @@ static int nau8825_codec_probe(struct snd_soc_codec *codec) | |||
973 | static int nau8825_calc_fll_param(unsigned int fll_in, unsigned int fs, | 973 | static int nau8825_calc_fll_param(unsigned int fll_in, unsigned int fs, |
974 | struct nau8825_fll *fll_param) | 974 | struct nau8825_fll *fll_param) |
975 | { | 975 | { |
976 | u64 fvco; | 976 | u64 fvco, fvco_max; |
977 | unsigned int fref, i; | 977 | unsigned int fref, i, fvco_sel; |
978 | 978 | ||
979 | /* Ensure the reference clock frequency (FREF) is <= 13.5MHz by dividing | 979 | /* Ensure the reference clock frequency (FREF) is <= 13.5MHz by dividing |
980 | * freq_in by 1, 2, 4, or 8 using FLL pre-scalar. | 980 | * freq_in by 1, 2, 4, or 8 using FLL pre-scalar. |
@@ -999,18 +999,23 @@ static int nau8825_calc_fll_param(unsigned int fll_in, unsigned int fs, | |||
999 | fll_param->ratio = fll_ratio[i].val; | 999 | fll_param->ratio = fll_ratio[i].val; |
1000 | 1000 | ||
1001 | /* Calculate the frequency of DCO (FDCO) given freq_out = 256 * Fs. | 1001 | /* Calculate the frequency of DCO (FDCO) given freq_out = 256 * Fs. |
1002 | * FDCO must be within the 90MHz - 100MHz or the FFL cannot be | 1002 | * FDCO must be within the 90MHz - 124MHz or the FFL cannot be |
1003 | * guaranteed across the full range of operation. | 1003 | * guaranteed across the full range of operation. |
1004 | * FDCO = freq_out * 2 * mclk_src_scaling | 1004 | * FDCO = freq_out * 2 * mclk_src_scaling |
1005 | */ | 1005 | */ |
1006 | fvco_max = 0; | ||
1007 | fvco_sel = ARRAY_SIZE(mclk_src_scaling); | ||
1006 | for (i = 0; i < ARRAY_SIZE(mclk_src_scaling); i++) { | 1008 | for (i = 0; i < ARRAY_SIZE(mclk_src_scaling); i++) { |
1007 | fvco = 256 * fs * 2 * mclk_src_scaling[i].param; | 1009 | fvco = 256 * fs * 2 * mclk_src_scaling[i].param; |
1008 | if (NAU_FVCO_MIN < fvco && fvco < NAU_FVCO_MAX) | 1010 | if (fvco > NAU_FVCO_MIN && fvco < NAU_FVCO_MAX && |
1009 | break; | 1011 | fvco_max < fvco) { |
1012 | fvco_max = fvco; | ||
1013 | fvco_sel = i; | ||
1014 | } | ||
1010 | } | 1015 | } |
1011 | if (i == ARRAY_SIZE(mclk_src_scaling)) | 1016 | if (ARRAY_SIZE(mclk_src_scaling) == fvco_sel) |
1012 | return -EINVAL; | 1017 | return -EINVAL; |
1013 | fll_param->mclk_src = mclk_src_scaling[i].val; | 1018 | fll_param->mclk_src = mclk_src_scaling[fvco_sel].val; |
1014 | 1019 | ||
1015 | /* Calculate the FLL 10-bit integer input and the FLL 16-bit fractional | 1020 | /* Calculate the FLL 10-bit integer input and the FLL 16-bit fractional |
1016 | * input based on FDCO, FREF and FLL ratio. | 1021 | * input based on FDCO, FREF and FLL ratio. |
@@ -1025,7 +1030,8 @@ static void nau8825_fll_apply(struct nau8825 *nau8825, | |||
1025 | struct nau8825_fll *fll_param) | 1030 | struct nau8825_fll *fll_param) |
1026 | { | 1031 | { |
1027 | regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER, | 1032 | regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER, |
1028 | NAU8825_CLK_MCLK_SRC_MASK, fll_param->mclk_src); | 1033 | NAU8825_CLK_SRC_MASK | NAU8825_CLK_MCLK_SRC_MASK, |
1034 | NAU8825_CLK_SRC_MCLK | fll_param->mclk_src); | ||
1029 | regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL1, | 1035 | regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL1, |
1030 | NAU8825_FLL_RATIO_MASK, fll_param->ratio); | 1036 | NAU8825_FLL_RATIO_MASK, fll_param->ratio); |
1031 | /* FLL 16-bit fractional input */ | 1037 | /* FLL 16-bit fractional input */ |
@@ -1038,10 +1044,25 @@ static void nau8825_fll_apply(struct nau8825 *nau8825, | |||
1038 | NAU8825_FLL_REF_DIV_MASK, fll_param->clk_ref_div); | 1044 | NAU8825_FLL_REF_DIV_MASK, fll_param->clk_ref_div); |
1039 | /* select divided VCO input */ | 1045 | /* select divided VCO input */ |
1040 | regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5, | 1046 | regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5, |
1041 | NAU8825_FLL_FILTER_SW_MASK, 0x0000); | 1047 | NAU8825_FLL_CLK_SW_MASK, NAU8825_FLL_CLK_SW_REF); |
1042 | /* FLL sigma delta modulator enable */ | 1048 | /* Disable free-running mode */ |
1043 | regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL6, | 1049 | regmap_update_bits(nau8825->regmap, |
1044 | NAU8825_SDM_EN_MASK, NAU8825_SDM_EN); | 1050 | NAU8825_REG_FLL6, NAU8825_DCO_EN, 0); |
1051 | if (fll_param->fll_frac) { | ||
1052 | regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5, | ||
1053 | NAU8825_FLL_PDB_DAC_EN | NAU8825_FLL_LOOP_FTR_EN | | ||
1054 | NAU8825_FLL_FTR_SW_MASK, | ||
1055 | NAU8825_FLL_PDB_DAC_EN | NAU8825_FLL_LOOP_FTR_EN | | ||
1056 | NAU8825_FLL_FTR_SW_FILTER); | ||
1057 | regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL6, | ||
1058 | NAU8825_SDM_EN, NAU8825_SDM_EN); | ||
1059 | } else { | ||
1060 | regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5, | ||
1061 | NAU8825_FLL_PDB_DAC_EN | NAU8825_FLL_LOOP_FTR_EN | | ||
1062 | NAU8825_FLL_FTR_SW_MASK, NAU8825_FLL_FTR_SW_ACCU); | ||
1063 | regmap_update_bits(nau8825->regmap, | ||
1064 | NAU8825_REG_FLL6, NAU8825_SDM_EN, 0); | ||
1065 | } | ||
1045 | } | 1066 | } |
1046 | 1067 | ||
1047 | /* freq_out must be 256*Fs in order to achieve the best performance */ | 1068 | /* freq_out must be 256*Fs in order to achieve the best performance */ |
diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h index ed0d8f3df65f..5fe009dcfb3d 100644 --- a/sound/soc/codecs/nau8825.h +++ b/sound/soc/codecs/nau8825.h | |||
@@ -123,15 +123,18 @@ | |||
123 | #define NAU8825_FLL_REF_DIV_MASK (0x3 << 10) | 123 | #define NAU8825_FLL_REF_DIV_MASK (0x3 << 10) |
124 | 124 | ||
125 | /* FLL5 (0x08) */ | 125 | /* FLL5 (0x08) */ |
126 | #define NAU8825_FLL_FILTER_SW_MASK (0x1 << 14) | 126 | #define NAU8825_FLL_PDB_DAC_EN (0x1 << 15) |
127 | #define NAU8825_FLL_LOOP_FTR_EN (0x1 << 14) | ||
128 | #define NAU8825_FLL_CLK_SW_MASK (0x1 << 13) | ||
129 | #define NAU8825_FLL_CLK_SW_N2 (0x1 << 13) | ||
130 | #define NAU8825_FLL_CLK_SW_REF (0x0 << 13) | ||
131 | #define NAU8825_FLL_FTR_SW_MASK (0x1 << 12) | ||
132 | #define NAU8825_FLL_FTR_SW_ACCU (0x1 << 12) | ||
133 | #define NAU8825_FLL_FTR_SW_FILTER (0x0 << 12) | ||
127 | 134 | ||
128 | /* FLL6 (0x9) */ | 135 | /* FLL6 (0x9) */ |
129 | #define NAU8825_DCO_EN_MASK (0x1 << 15) | ||
130 | #define NAU8825_DCO_EN (0x1 << 15) | 136 | #define NAU8825_DCO_EN (0x1 << 15) |
131 | #define NAU8825_DCO_DIS (0x0 << 15) | ||
132 | #define NAU8825_SDM_EN_MASK (0x1 << 14) | ||
133 | #define NAU8825_SDM_EN (0x1 << 14) | 137 | #define NAU8825_SDM_EN (0x1 << 14) |
134 | #define NAU8825_SDM_DIS (0x0 << 14) | ||
135 | 138 | ||
136 | /* HSD_CTRL (0xc) */ | 139 | /* HSD_CTRL (0xc) */ |
137 | #define NAU8825_HSD_AUTO_MODE (1 << 6) | 140 | #define NAU8825_HSD_AUTO_MODE (1 << 6) |