aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMengdong Lin <mengdong.lin@intel.com>2015-01-06 21:19:12 -0500
committerMark Brown <broonie@kernel.org>2015-01-07 12:40:01 -0500
commite8c47ba3cadcc3649f18e4710804bb6c3791eac2 (patch)
tree0d9259b7d69443746d1d28236bff758b0c824adc
parentb7ed9f1d26f04272127a98248338177e5bac233e (diff)
ASoC: rt5670: add API to select ASRC clock source
When codec is in slave mode, ASRC can suppress noise for asynchronous MCLK and LRCLK or special I2S format. This patch defines an API to select the clock source for specified filters. And the codec driver will turn on ASRC for these filters if ASRC is selected as their clock source. Signed-off-by: Bard Liao <bardliao@realtek.com> Signed-off-by: Mengdong Lin <mengdong.lin@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/rt5670.c83
-rw-r--r--sound/soc/codecs/rt5670.h15
2 files changed, 98 insertions, 0 deletions
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c
index 0a027bc94399..0632b7458a53 100644
--- a/sound/soc/codecs/rt5670.c
+++ b/sound/soc/codecs/rt5670.c
@@ -590,6 +590,89 @@ static int can_use_asrc(struct snd_soc_dapm_widget *source,
590 return 0; 590 return 0;
591} 591}
592 592
593
594/**
595 * rt5670_sel_asrc_clk_src - select ASRC clock source for a set of filters
596 * @codec: SoC audio codec device.
597 * @filter_mask: mask of filters.
598 * @clk_src: clock source
599 *
600 * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5670 can
601 * only support standard 32fs or 64fs i2s format, ASRC should be enabled to
602 * support special i2s clock format such as Intel's 100fs(100 * sampling rate).
603 * ASRC function will track i2s clock and generate a corresponding system clock
604 * for codec. This function provides an API to select the clock source for a
605 * set of filters specified by the mask. And the codec driver will turn on ASRC
606 * for these filters if ASRC is selected as their clock source.
607 */
608int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec,
609 unsigned int filter_mask, unsigned int clk_src)
610{
611 unsigned int asrc2_mask = 0, asrc2_value = 0;
612 unsigned int asrc3_mask = 0, asrc3_value = 0;
613
614 if (clk_src > RT5670_CLK_SEL_SYS3)
615 return -EINVAL;
616
617 if (filter_mask & RT5670_DA_STEREO_FILTER) {
618 asrc2_mask |= RT5670_DA_STO_CLK_SEL_MASK;
619 asrc2_value = (asrc2_value & ~RT5670_DA_STO_CLK_SEL_MASK)
620 | (clk_src << RT5670_DA_STO_CLK_SEL_SFT);
621 }
622
623 if (filter_mask & RT5670_DA_MONO_L_FILTER) {
624 asrc2_mask |= RT5670_DA_MONOL_CLK_SEL_MASK;
625 asrc2_value = (asrc2_value & ~RT5670_DA_MONOL_CLK_SEL_MASK)
626 | (clk_src << RT5670_DA_MONOL_CLK_SEL_SFT);
627 }
628
629 if (filter_mask & RT5670_DA_MONO_R_FILTER) {
630 asrc2_mask |= RT5670_DA_MONOR_CLK_SEL_MASK;
631 asrc2_value = (asrc2_value & ~RT5670_DA_MONOR_CLK_SEL_MASK)
632 | (clk_src << RT5670_DA_MONOR_CLK_SEL_SFT);
633 }
634
635 if (filter_mask & RT5670_AD_STEREO_FILTER) {
636 asrc2_mask |= RT5670_AD_STO1_CLK_SEL_MASK;
637 asrc2_value = (asrc2_value & ~RT5670_AD_STO1_CLK_SEL_MASK)
638 | (clk_src << RT5670_AD_STO1_CLK_SEL_SFT);
639 }
640
641 if (filter_mask & RT5670_AD_MONO_L_FILTER) {
642 asrc3_mask |= RT5670_AD_MONOL_CLK_SEL_MASK;
643 asrc3_value = (asrc3_value & ~RT5670_AD_MONOL_CLK_SEL_MASK)
644 | (clk_src << RT5670_AD_MONOL_CLK_SEL_SFT);
645 }
646
647 if (filter_mask & RT5670_AD_MONO_R_FILTER) {
648 asrc3_mask |= RT5670_AD_MONOR_CLK_SEL_MASK;
649 asrc3_value = (asrc3_value & ~RT5670_AD_MONOR_CLK_SEL_MASK)
650 | (clk_src << RT5670_AD_MONOR_CLK_SEL_SFT);
651 }
652
653 if (filter_mask & RT5670_UP_RATE_FILTER) {
654 asrc3_mask |= RT5670_UP_CLK_SEL_MASK;
655 asrc3_value = (asrc3_value & ~RT5670_UP_CLK_SEL_MASK)
656 | (clk_src << RT5670_UP_CLK_SEL_SFT);
657 }
658
659 if (filter_mask & RT5670_DOWN_RATE_FILTER) {
660 asrc3_mask |= RT5670_DOWN_CLK_SEL_MASK;
661 asrc3_value = (asrc3_value & ~RT5670_DOWN_CLK_SEL_MASK)
662 | (clk_src << RT5670_DOWN_CLK_SEL_SFT);
663 }
664
665 if (asrc2_mask)
666 snd_soc_update_bits(codec, RT5670_ASRC_2,
667 asrc2_mask, asrc2_value);
668
669 if (asrc3_mask)
670 snd_soc_update_bits(codec, RT5670_ASRC_3,
671 asrc3_mask, asrc3_value);
672 return 0;
673}
674EXPORT_SYMBOL_GPL(rt5670_sel_asrc_clk_src);
675
593/* Digital Mixer */ 676/* Digital Mixer */
594static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = { 677static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = {
595 SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER, 678 SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER,
diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h
index ec38d8f173e7..21f8e18c13c4 100644
--- a/sound/soc/codecs/rt5670.h
+++ b/sound/soc/codecs/rt5670.h
@@ -1966,6 +1966,21 @@ enum {
1966 RT5670_DMIC_DATA_GPIO5, 1966 RT5670_DMIC_DATA_GPIO5,
1967}; 1967};
1968 1968
1969/* filter mask */
1970enum {
1971 RT5670_DA_STEREO_FILTER = 0x1,
1972 RT5670_DA_MONO_L_FILTER = (0x1 << 1),
1973 RT5670_DA_MONO_R_FILTER = (0x1 << 2),
1974 RT5670_AD_STEREO_FILTER = (0x1 << 3),
1975 RT5670_AD_MONO_L_FILTER = (0x1 << 4),
1976 RT5670_AD_MONO_R_FILTER = (0x1 << 5),
1977 RT5670_UP_RATE_FILTER = (0x1 << 6),
1978 RT5670_DOWN_RATE_FILTER = (0x1 << 7),
1979};
1980
1981int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec,
1982 unsigned int filter_mask, unsigned int clk_src);
1983
1969struct rt5670_priv { 1984struct rt5670_priv {
1970 struct snd_soc_codec *codec; 1985 struct snd_soc_codec *codec;
1971 struct rt5670_platform_data pdata; 1986 struct rt5670_platform_data pdata;