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-03-02 11:19:46 -0500
commitea232b3f7233f9242e5a1287377fedb6972dfea4 (patch)
tree419e013da85452004f200ef4bcc0113a833a43e0
parent3aebec3a701e70d6fe2816891e5abea066492779 (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 82553b1726cd..0a67adbcfbc3 100644
--- a/sound/soc/codecs/rt5670.h
+++ b/sound/soc/codecs/rt5670.h
@@ -1969,6 +1969,21 @@ enum {
1969 RT5670_DMIC_DATA_GPIO5, 1969 RT5670_DMIC_DATA_GPIO5,
1970}; 1970};
1971 1971
1972/* filter mask */
1973enum {
1974 RT5670_DA_STEREO_FILTER = 0x1,
1975 RT5670_DA_MONO_L_FILTER = (0x1 << 1),
1976 RT5670_DA_MONO_R_FILTER = (0x1 << 2),
1977 RT5670_AD_STEREO_FILTER = (0x1 << 3),
1978 RT5670_AD_MONO_L_FILTER = (0x1 << 4),
1979 RT5670_AD_MONO_R_FILTER = (0x1 << 5),
1980 RT5670_UP_RATE_FILTER = (0x1 << 6),
1981 RT5670_DOWN_RATE_FILTER = (0x1 << 7),
1982};
1983
1984int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec,
1985 unsigned int filter_mask, unsigned int clk_src);
1986
1972struct rt5670_priv { 1987struct rt5670_priv {
1973 struct snd_soc_codec *codec; 1988 struct snd_soc_codec *codec;
1974 struct rt5670_platform_data pdata; 1989 struct rt5670_platform_data pdata;