diff options
author | Fang, Yang A <yang.a.fang@intel.com> | 2015-02-04 21:19:31 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-02-05 13:09:27 -0500 |
commit | 79080a8b42a08fb68a1ea2e036e54a4749edbd43 (patch) | |
tree | f5f7026285d94958bf3442f548e89c403ad9be85 /sound | |
parent | 5c4ca99df718f6569849ab5fabdf18c14755b144 (diff) |
ASoC: rt5645: add API to select ASRC clock source
This patch defines an API to select the clock source for specified filters.
Signed-off-by: Fang, Yang A <yang.a.fang@intel.com>
Acked-by: Kevin Strasser <kevin.strasser@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/rt5645.c | 81 | ||||
-rw-r--r-- | sound/soc/codecs/rt5645.h | 72 |
2 files changed, 112 insertions, 41 deletions
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 21b2d72b4ea8..debf16c5b549 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -613,6 +613,87 @@ static int is_using_asrc(struct snd_soc_dapm_widget *source, | |||
613 | 613 | ||
614 | } | 614 | } |
615 | 615 | ||
616 | /** | ||
617 | * rt5645_sel_asrc_clk_src - select ASRC clock source for a set of filters | ||
618 | * @codec: SoC audio codec device. | ||
619 | * @filter_mask: mask of filters. | ||
620 | * @clk_src: clock source | ||
621 | * | ||
622 | * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5645 can | ||
623 | * only support standard 32fs or 64fs i2s format, ASRC should be enabled to | ||
624 | * support special i2s clock format such as Intel's 100fs(100 * sampling rate). | ||
625 | * ASRC function will track i2s clock and generate a corresponding system clock | ||
626 | * for codec. This function provides an API to select the clock source for a | ||
627 | * set of filters specified by the mask. And the codec driver will turn on ASRC | ||
628 | * for these filters if ASRC is selected as their clock source. | ||
629 | */ | ||
630 | int rt5645_sel_asrc_clk_src(struct snd_soc_codec *codec, | ||
631 | unsigned int filter_mask, unsigned int clk_src) | ||
632 | { | ||
633 | unsigned int asrc2_mask = 0; | ||
634 | unsigned int asrc2_value = 0; | ||
635 | unsigned int asrc3_mask = 0; | ||
636 | unsigned int asrc3_value = 0; | ||
637 | |||
638 | switch (clk_src) { | ||
639 | case RT5645_CLK_SEL_SYS: | ||
640 | case RT5645_CLK_SEL_I2S1_ASRC: | ||
641 | case RT5645_CLK_SEL_I2S2_ASRC: | ||
642 | case RT5645_CLK_SEL_SYS2: | ||
643 | break; | ||
644 | |||
645 | default: | ||
646 | return -EINVAL; | ||
647 | } | ||
648 | |||
649 | if (filter_mask & RT5645_DA_STEREO_FILTER) { | ||
650 | asrc2_mask |= RT5645_DA_STO_CLK_SEL_MASK; | ||
651 | asrc2_value = (asrc2_value & ~RT5645_DA_STO_CLK_SEL_MASK) | ||
652 | | (clk_src << RT5645_DA_STO_CLK_SEL_SFT); | ||
653 | } | ||
654 | |||
655 | if (filter_mask & RT5645_DA_MONO_L_FILTER) { | ||
656 | asrc2_mask |= RT5645_DA_MONOL_CLK_SEL_MASK; | ||
657 | asrc2_value = (asrc2_value & ~RT5645_DA_MONOL_CLK_SEL_MASK) | ||
658 | | (clk_src << RT5645_DA_MONOL_CLK_SEL_SFT); | ||
659 | } | ||
660 | |||
661 | if (filter_mask & RT5645_DA_MONO_R_FILTER) { | ||
662 | asrc2_mask |= RT5645_DA_MONOR_CLK_SEL_MASK; | ||
663 | asrc2_value = (asrc2_value & ~RT5645_DA_MONOR_CLK_SEL_MASK) | ||
664 | | (clk_src << RT5645_DA_MONOR_CLK_SEL_SFT); | ||
665 | } | ||
666 | |||
667 | if (filter_mask & RT5645_AD_STEREO_FILTER) { | ||
668 | asrc2_mask |= RT5645_AD_STO1_CLK_SEL_MASK; | ||
669 | asrc2_value = (asrc2_value & ~RT5645_AD_STO1_CLK_SEL_MASK) | ||
670 | | (clk_src << RT5645_AD_STO1_CLK_SEL_SFT); | ||
671 | } | ||
672 | |||
673 | if (filter_mask & RT5645_AD_MONO_L_FILTER) { | ||
674 | asrc3_mask |= RT5645_AD_MONOL_CLK_SEL_MASK; | ||
675 | asrc3_value = (asrc3_value & ~RT5645_AD_MONOL_CLK_SEL_MASK) | ||
676 | | (clk_src << RT5645_AD_MONOL_CLK_SEL_SFT); | ||
677 | } | ||
678 | |||
679 | if (filter_mask & RT5645_AD_MONO_R_FILTER) { | ||
680 | asrc3_mask |= RT5645_AD_MONOR_CLK_SEL_MASK; | ||
681 | asrc3_value = (asrc3_value & ~RT5645_AD_MONOR_CLK_SEL_MASK) | ||
682 | | (clk_src << RT5645_AD_MONOR_CLK_SEL_SFT); | ||
683 | } | ||
684 | |||
685 | if (asrc2_mask) | ||
686 | snd_soc_update_bits(codec, RT5645_ASRC_2, | ||
687 | asrc2_mask, asrc2_value); | ||
688 | |||
689 | if (asrc3_mask) | ||
690 | snd_soc_update_bits(codec, RT5645_ASRC_3, | ||
691 | asrc3_mask, asrc3_value); | ||
692 | |||
693 | return 0; | ||
694 | } | ||
695 | EXPORT_SYMBOL_GPL(rt5645_sel_asrc_clk_src); | ||
696 | |||
616 | /* Digital Mixer */ | 697 | /* Digital Mixer */ |
617 | static const struct snd_kcontrol_new rt5645_sto1_adc_l_mix[] = { | 698 | static const struct snd_kcontrol_new rt5645_sto1_adc_l_mix[] = { |
618 | SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER, | 699 | SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER, |
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h index 74542310d3f0..dbfd98c22f4d 100644 --- a/sound/soc/codecs/rt5645.h +++ b/sound/soc/codecs/rt5645.h | |||
@@ -1120,50 +1120,27 @@ | |||
1120 | #define RT5645_DMIC_2_M_NOR (0x0 << 8) | 1120 | #define RT5645_DMIC_2_M_NOR (0x0 << 8) |
1121 | #define RT5645_DMIC_2_M_ASYN (0x1 << 8) | 1121 | #define RT5645_DMIC_2_M_ASYN (0x1 << 8) |
1122 | 1122 | ||
1123 | /* ASRC clock source selection (0x84, 0x85) */ | ||
1124 | #define RT5645_CLK_SEL_SYS (0x0) | ||
1125 | #define RT5645_CLK_SEL_I2S1_ASRC (0x1) | ||
1126 | #define RT5645_CLK_SEL_I2S2_ASRC (0x2) | ||
1127 | #define RT5645_CLK_SEL_SYS2 (0x5) | ||
1128 | |||
1123 | /* ASRC Control 2 (0x84) */ | 1129 | /* ASRC Control 2 (0x84) */ |
1124 | #define RT5645_MDA_L_M_MASK (0x1 << 15) | 1130 | #define RT5645_DA_STO_CLK_SEL_MASK (0xf << 12) |
1125 | #define RT5645_MDA_L_M_SFT 15 | 1131 | #define RT5645_DA_STO_CLK_SEL_SFT 12 |
1126 | #define RT5645_MDA_L_M_NOR (0x0 << 15) | 1132 | #define RT5645_DA_MONOL_CLK_SEL_MASK (0xf << 8) |
1127 | #define RT5645_MDA_L_M_ASYN (0x1 << 15) | 1133 | #define RT5645_DA_MONOL_CLK_SEL_SFT 8 |
1128 | #define RT5645_MDA_R_M_MASK (0x1 << 14) | 1134 | #define RT5645_DA_MONOR_CLK_SEL_MASK (0xf << 4) |
1129 | #define RT5645_MDA_R_M_SFT 14 | 1135 | #define RT5645_DA_MONOR_CLK_SEL_SFT 4 |
1130 | #define RT5645_MDA_R_M_NOR (0x0 << 14) | 1136 | #define RT5645_AD_STO1_CLK_SEL_MASK (0xf << 0) |
1131 | #define RT5645_MDA_R_M_ASYN (0x1 << 14) | 1137 | #define RT5645_AD_STO1_CLK_SEL_SFT 0 |
1132 | #define RT5645_MAD_L_M_MASK (0x1 << 13) | ||
1133 | #define RT5645_MAD_L_M_SFT 13 | ||
1134 | #define RT5645_MAD_L_M_NOR (0x0 << 13) | ||
1135 | #define RT5645_MAD_L_M_ASYN (0x1 << 13) | ||
1136 | #define RT5645_MAD_R_M_MASK (0x1 << 12) | ||
1137 | #define RT5645_MAD_R_M_SFT 12 | ||
1138 | #define RT5645_MAD_R_M_NOR (0x0 << 12) | ||
1139 | #define RT5645_MAD_R_M_ASYN (0x1 << 12) | ||
1140 | #define RT5645_ADC_M_MASK (0x1 << 11) | ||
1141 | #define RT5645_ADC_M_SFT 11 | ||
1142 | #define RT5645_ADC_M_NOR (0x0 << 11) | ||
1143 | #define RT5645_ADC_M_ASYN (0x1 << 11) | ||
1144 | #define RT5645_STO_DAC_M_MASK (0x1 << 5) | ||
1145 | #define RT5645_STO_DAC_M_SFT 5 | ||
1146 | #define RT5645_STO_DAC_M_NOR (0x0 << 5) | ||
1147 | #define RT5645_STO_DAC_M_ASYN (0x1 << 5) | ||
1148 | #define RT5645_I2S1_R_D_MASK (0x1 << 4) | ||
1149 | #define RT5645_I2S1_R_D_SFT 4 | ||
1150 | #define RT5645_I2S1_R_D_DIS (0x0 << 4) | ||
1151 | #define RT5645_I2S1_R_D_EN (0x1 << 4) | ||
1152 | #define RT5645_I2S2_R_D_MASK (0x1 << 3) | ||
1153 | #define RT5645_I2S2_R_D_SFT 3 | ||
1154 | #define RT5645_I2S2_R_D_DIS (0x0 << 3) | ||
1155 | #define RT5645_I2S2_R_D_EN (0x1 << 3) | ||
1156 | #define RT5645_PRE_SCLK_MASK (0x3) | ||
1157 | #define RT5645_PRE_SCLK_SFT 0 | ||
1158 | #define RT5645_PRE_SCLK_512 (0x0) | ||
1159 | #define RT5645_PRE_SCLK_1024 (0x1) | ||
1160 | #define RT5645_PRE_SCLK_2048 (0x2) | ||
1161 | 1138 | ||
1162 | /* ASRC Control 3 (0x85) */ | 1139 | /* ASRC Control 3 (0x85) */ |
1163 | #define RT5645_I2S1_RATE_MASK (0xf << 12) | 1140 | #define RT5645_AD_MONOL_CLK_SEL_MASK (0xf << 4) |
1164 | #define RT5645_I2S1_RATE_SFT 12 | 1141 | #define RT5645_AD_MONOL_CLK_SEL_SFT 4 |
1165 | #define RT5645_I2S2_RATE_MASK (0xf << 8) | 1142 | #define RT5645_AD_MONOR_CLK_SEL_MASK (0xf << 0) |
1166 | #define RT5645_I2S2_RATE_SFT 8 | 1143 | #define RT5645_AD_MONOR_CLK_SEL_SFT 0 |
1167 | 1144 | ||
1168 | /* ASRC Control 4 (0x89) */ | 1145 | /* ASRC Control 4 (0x89) */ |
1169 | #define RT5645_I2S1_PD_MASK (0x7 << 12) | 1146 | #define RT5645_I2S1_PD_MASK (0x7 << 12) |
@@ -2189,6 +2166,19 @@ enum { | |||
2189 | CODEC_TYPE_RT5650, | 2166 | CODEC_TYPE_RT5650, |
2190 | }; | 2167 | }; |
2191 | 2168 | ||
2169 | /* filter mask */ | ||
2170 | enum { | ||
2171 | RT5645_DA_STEREO_FILTER = 0x1, | ||
2172 | RT5645_DA_MONO_L_FILTER = (0x1 << 1), | ||
2173 | RT5645_DA_MONO_R_FILTER = (0x1 << 2), | ||
2174 | RT5645_AD_STEREO_FILTER = (0x1 << 3), | ||
2175 | RT5645_AD_MONO_L_FILTER = (0x1 << 4), | ||
2176 | RT5645_AD_MONO_R_FILTER = (0x1 << 5), | ||
2177 | }; | ||
2178 | |||
2179 | int rt5645_sel_asrc_clk_src(struct snd_soc_codec *codec, | ||
2180 | unsigned int filter_mask, unsigned int clk_src); | ||
2181 | |||
2192 | struct rt5645_priv { | 2182 | struct rt5645_priv { |
2193 | struct snd_soc_codec *codec; | 2183 | struct snd_soc_codec *codec; |
2194 | struct rt5645_platform_data pdata; | 2184 | struct rt5645_platform_data pdata; |