diff options
| -rw-r--r-- | sound/soc/codecs/rt5670.c | 83 | ||||
| -rw-r--r-- | sound/soc/codecs/rt5670.h | 15 |
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 | */ | ||
| 608 | int 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 | } | ||
| 674 | EXPORT_SYMBOL_GPL(rt5670_sel_asrc_clk_src); | ||
| 675 | |||
| 593 | /* Digital Mixer */ | 676 | /* Digital Mixer */ |
| 594 | static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = { | 677 | static 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 */ | ||
| 1973 | enum { | ||
| 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 | |||
| 1984 | int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec, | ||
| 1985 | unsigned int filter_mask, unsigned int clk_src); | ||
| 1986 | |||
| 1972 | struct rt5670_priv { | 1987 | struct 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; |
