|
@@ -1034,6 +1034,169 @@ static int can_use_asrc(struct snd_soc_dapm_widget *source,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * rt5677_sel_asrc_clk_src - select ASRC clock source for a set of filters
|
|
|
+ * @codec: SoC audio codec device.
|
|
|
+ * @filter_mask: mask of filters.
|
|
|
+ * @clk_src: clock source
|
|
|
+ *
|
|
|
+ * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5677 can
|
|
|
+ * only support standard 32fs or 64fs i2s format, ASRC should be enabled to
|
|
|
+ * support special i2s clock format such as Intel's 100fs(100 * sampling rate).
|
|
|
+ * ASRC function will track i2s clock and generate a corresponding system clock
|
|
|
+ * for codec. This function provides an API to select the clock source for a
|
|
|
+ * set of filters specified by the mask. And the codec driver will turn on ASRC
|
|
|
+ * for these filters if ASRC is selected as their clock source.
|
|
|
+ */
|
|
|
+int rt5677_sel_asrc_clk_src(struct snd_soc_codec *codec,
|
|
|
+ unsigned int filter_mask, unsigned int clk_src)
|
|
|
+{
|
|
|
+ struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
|
|
|
+ unsigned int asrc3_mask = 0, asrc3_value = 0;
|
|
|
+ unsigned int asrc4_mask = 0, asrc4_value = 0;
|
|
|
+ unsigned int asrc5_mask = 0, asrc5_value = 0;
|
|
|
+ unsigned int asrc6_mask = 0, asrc6_value = 0;
|
|
|
+ unsigned int asrc7_mask = 0, asrc7_value = 0;
|
|
|
+
|
|
|
+ switch (clk_src) {
|
|
|
+ case RT5677_CLK_SEL_SYS:
|
|
|
+ case RT5677_CLK_SEL_I2S1_ASRC:
|
|
|
+ case RT5677_CLK_SEL_I2S2_ASRC:
|
|
|
+ case RT5677_CLK_SEL_I2S3_ASRC:
|
|
|
+ case RT5677_CLK_SEL_I2S4_ASRC:
|
|
|
+ case RT5677_CLK_SEL_I2S5_ASRC:
|
|
|
+ case RT5677_CLK_SEL_I2S6_ASRC:
|
|
|
+ case RT5677_CLK_SEL_SYS2:
|
|
|
+ case RT5677_CLK_SEL_SYS3:
|
|
|
+ case RT5677_CLK_SEL_SYS4:
|
|
|
+ case RT5677_CLK_SEL_SYS5:
|
|
|
+ case RT5677_CLK_SEL_SYS6:
|
|
|
+ case RT5677_CLK_SEL_SYS7:
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* ASRC 3 */
|
|
|
+ if (filter_mask & RT5677_DA_STEREO_FILTER) {
|
|
|
+ asrc3_mask |= RT5677_DA_STO_CLK_SEL_MASK;
|
|
|
+ asrc3_value = (asrc3_value & ~RT5677_DA_STO_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_DA_STO_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filter_mask & RT5677_DA_MONO2_L_FILTER) {
|
|
|
+ asrc3_mask |= RT5677_DA_MONO2L_CLK_SEL_MASK;
|
|
|
+ asrc3_value = (asrc3_value & ~RT5677_DA_MONO2L_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_DA_MONO2L_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filter_mask & RT5677_DA_MONO2_R_FILTER) {
|
|
|
+ asrc3_mask |= RT5677_DA_MONO2R_CLK_SEL_MASK;
|
|
|
+ asrc3_value = (asrc3_value & ~RT5677_DA_MONO2R_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_DA_MONO2R_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (asrc3_mask)
|
|
|
+ regmap_update_bits(rt5677->regmap, RT5677_ASRC_3, asrc3_mask,
|
|
|
+ asrc3_value);
|
|
|
+
|
|
|
+ /* ASRC 4 */
|
|
|
+ if (filter_mask & RT5677_DA_MONO3_L_FILTER) {
|
|
|
+ asrc4_mask |= RT5677_DA_MONO3L_CLK_SEL_MASK;
|
|
|
+ asrc4_value = (asrc4_value & ~RT5677_DA_MONO3L_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_DA_MONO3L_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filter_mask & RT5677_DA_MONO3_R_FILTER) {
|
|
|
+ asrc4_mask |= RT5677_DA_MONO3R_CLK_SEL_MASK;
|
|
|
+ asrc4_value = (asrc4_value & ~RT5677_DA_MONO3R_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_DA_MONO3R_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filter_mask & RT5677_DA_MONO4_L_FILTER) {
|
|
|
+ asrc4_mask |= RT5677_DA_MONO4L_CLK_SEL_MASK;
|
|
|
+ asrc4_value = (asrc4_value & ~RT5677_DA_MONO4L_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_DA_MONO4L_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filter_mask & RT5677_DA_MONO4_R_FILTER) {
|
|
|
+ asrc4_mask |= RT5677_DA_MONO4R_CLK_SEL_MASK;
|
|
|
+ asrc4_value = (asrc4_value & ~RT5677_DA_MONO4R_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_DA_MONO4R_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (asrc4_mask)
|
|
|
+ regmap_update_bits(rt5677->regmap, RT5677_ASRC_4, asrc4_mask,
|
|
|
+ asrc4_value);
|
|
|
+
|
|
|
+ /* ASRC 5 */
|
|
|
+ if (filter_mask & RT5677_AD_STEREO1_FILTER) {
|
|
|
+ asrc5_mask |= RT5677_AD_STO1_CLK_SEL_MASK;
|
|
|
+ asrc5_value = (asrc5_value & ~RT5677_AD_STO1_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_AD_STO1_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filter_mask & RT5677_AD_STEREO2_FILTER) {
|
|
|
+ asrc5_mask |= RT5677_AD_STO2_CLK_SEL_MASK;
|
|
|
+ asrc5_value = (asrc5_value & ~RT5677_AD_STO2_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_AD_STO2_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filter_mask & RT5677_AD_STEREO3_FILTER) {
|
|
|
+ asrc5_mask |= RT5677_AD_STO3_CLK_SEL_MASK;
|
|
|
+ asrc5_value = (asrc5_value & ~RT5677_AD_STO3_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_AD_STO3_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filter_mask & RT5677_AD_STEREO4_FILTER) {
|
|
|
+ asrc5_mask |= RT5677_AD_STO4_CLK_SEL_MASK;
|
|
|
+ asrc5_value = (asrc5_value & ~RT5677_AD_STO4_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_AD_STO4_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (asrc5_mask)
|
|
|
+ regmap_update_bits(rt5677->regmap, RT5677_ASRC_5, asrc5_mask,
|
|
|
+ asrc5_value);
|
|
|
+
|
|
|
+ /* ASRC 6 */
|
|
|
+ if (filter_mask & RT5677_AD_MONO_L_FILTER) {
|
|
|
+ asrc6_mask |= RT5677_AD_MONOL_CLK_SEL_MASK;
|
|
|
+ asrc6_value = (asrc6_value & ~RT5677_AD_MONOL_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_AD_MONOL_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filter_mask & RT5677_AD_MONO_R_FILTER) {
|
|
|
+ asrc6_mask |= RT5677_AD_MONOR_CLK_SEL_MASK;
|
|
|
+ asrc6_value = (asrc6_value & ~RT5677_AD_MONOR_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_AD_MONOR_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (asrc6_mask)
|
|
|
+ regmap_update_bits(rt5677->regmap, RT5677_ASRC_6, asrc6_mask,
|
|
|
+ asrc6_value);
|
|
|
+
|
|
|
+ /* ASRC 7 */
|
|
|
+ if (filter_mask & RT5677_DSP_OB_0_3_FILTER) {
|
|
|
+ asrc7_mask |= RT5677_DSP_OB_0_3_CLK_SEL_MASK;
|
|
|
+ asrc7_value = (asrc7_value & ~RT5677_DSP_OB_0_3_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_DSP_OB_0_3_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filter_mask & RT5677_DSP_OB_4_7_FILTER) {
|
|
|
+ asrc7_mask |= RT5677_DSP_OB_4_7_CLK_SEL_MASK;
|
|
|
+ asrc7_value = (asrc7_value & ~RT5677_DSP_OB_4_7_CLK_SEL_MASK)
|
|
|
+ | (clk_src << RT5677_DSP_OB_4_7_CLK_SEL_SFT);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (asrc7_mask)
|
|
|
+ regmap_update_bits(rt5677->regmap, RT5677_ASRC_7, asrc7_mask,
|
|
|
+ asrc7_value);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(rt5677_sel_asrc_clk_src);
|
|
|
+
|
|
|
/* Digital Mixer */
|
|
|
static const struct snd_kcontrol_new rt5677_sto1_adc_l_mix[] = {
|
|
|
SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO1_ADC_MIXER,
|