diff options
Diffstat (limited to 'sound/soc/codecs/rt5677.c')
-rw-r--r-- | sound/soc/codecs/rt5677.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index c2a6e4091357..af182586712d 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c | |||
@@ -1034,6 +1034,169 @@ static int can_use_asrc(struct snd_soc_dapm_widget *source, | |||
1034 | return 0; | 1034 | return 0; |
1035 | } | 1035 | } |
1036 | 1036 | ||
1037 | /** | ||
1038 | * rt5677_sel_asrc_clk_src - select ASRC clock source for a set of filters | ||
1039 | * @codec: SoC audio codec device. | ||
1040 | * @filter_mask: mask of filters. | ||
1041 | * @clk_src: clock source | ||
1042 | * | ||
1043 | * The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5677 can | ||
1044 | * only support standard 32fs or 64fs i2s format, ASRC should be enabled to | ||
1045 | * support special i2s clock format such as Intel's 100fs(100 * sampling rate). | ||
1046 | * ASRC function will track i2s clock and generate a corresponding system clock | ||
1047 | * for codec. This function provides an API to select the clock source for a | ||
1048 | * set of filters specified by the mask. And the codec driver will turn on ASRC | ||
1049 | * for these filters if ASRC is selected as their clock source. | ||
1050 | */ | ||
1051 | int rt5677_sel_asrc_clk_src(struct snd_soc_codec *codec, | ||
1052 | unsigned int filter_mask, unsigned int clk_src) | ||
1053 | { | ||
1054 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | ||
1055 | unsigned int asrc3_mask = 0, asrc3_value = 0; | ||
1056 | unsigned int asrc4_mask = 0, asrc4_value = 0; | ||
1057 | unsigned int asrc5_mask = 0, asrc5_value = 0; | ||
1058 | unsigned int asrc6_mask = 0, asrc6_value = 0; | ||
1059 | unsigned int asrc7_mask = 0, asrc7_value = 0; | ||
1060 | |||
1061 | switch (clk_src) { | ||
1062 | case RT5677_CLK_SEL_SYS: | ||
1063 | case RT5677_CLK_SEL_I2S1_ASRC: | ||
1064 | case RT5677_CLK_SEL_I2S2_ASRC: | ||
1065 | case RT5677_CLK_SEL_I2S3_ASRC: | ||
1066 | case RT5677_CLK_SEL_I2S4_ASRC: | ||
1067 | case RT5677_CLK_SEL_I2S5_ASRC: | ||
1068 | case RT5677_CLK_SEL_I2S6_ASRC: | ||
1069 | case RT5677_CLK_SEL_SYS2: | ||
1070 | case RT5677_CLK_SEL_SYS3: | ||
1071 | case RT5677_CLK_SEL_SYS4: | ||
1072 | case RT5677_CLK_SEL_SYS5: | ||
1073 | case RT5677_CLK_SEL_SYS6: | ||
1074 | case RT5677_CLK_SEL_SYS7: | ||
1075 | break; | ||
1076 | |||
1077 | default: | ||
1078 | return -EINVAL; | ||
1079 | } | ||
1080 | |||
1081 | /* ASRC 3 */ | ||
1082 | if (filter_mask & RT5677_DA_STEREO_FILTER) { | ||
1083 | asrc3_mask |= RT5677_DA_STO_CLK_SEL_MASK; | ||
1084 | asrc3_value = (asrc3_value & ~RT5677_DA_STO_CLK_SEL_MASK) | ||
1085 | | (clk_src << RT5677_DA_STO_CLK_SEL_SFT); | ||
1086 | } | ||
1087 | |||
1088 | if (filter_mask & RT5677_DA_MONO2_L_FILTER) { | ||
1089 | asrc3_mask |= RT5677_DA_MONO2L_CLK_SEL_MASK; | ||
1090 | asrc3_value = (asrc3_value & ~RT5677_DA_MONO2L_CLK_SEL_MASK) | ||
1091 | | (clk_src << RT5677_DA_MONO2L_CLK_SEL_SFT); | ||
1092 | } | ||
1093 | |||
1094 | if (filter_mask & RT5677_DA_MONO2_R_FILTER) { | ||
1095 | asrc3_mask |= RT5677_DA_MONO2R_CLK_SEL_MASK; | ||
1096 | asrc3_value = (asrc3_value & ~RT5677_DA_MONO2R_CLK_SEL_MASK) | ||
1097 | | (clk_src << RT5677_DA_MONO2R_CLK_SEL_SFT); | ||
1098 | } | ||
1099 | |||
1100 | if (asrc3_mask) | ||
1101 | regmap_update_bits(rt5677->regmap, RT5677_ASRC_3, asrc3_mask, | ||
1102 | asrc3_value); | ||
1103 | |||
1104 | /* ASRC 4 */ | ||
1105 | if (filter_mask & RT5677_DA_MONO3_L_FILTER) { | ||
1106 | asrc4_mask |= RT5677_DA_MONO3L_CLK_SEL_MASK; | ||
1107 | asrc4_value = (asrc4_value & ~RT5677_DA_MONO3L_CLK_SEL_MASK) | ||
1108 | | (clk_src << RT5677_DA_MONO3L_CLK_SEL_SFT); | ||
1109 | } | ||
1110 | |||
1111 | if (filter_mask & RT5677_DA_MONO3_R_FILTER) { | ||
1112 | asrc4_mask |= RT5677_DA_MONO3R_CLK_SEL_MASK; | ||
1113 | asrc4_value = (asrc4_value & ~RT5677_DA_MONO3R_CLK_SEL_MASK) | ||
1114 | | (clk_src << RT5677_DA_MONO3R_CLK_SEL_SFT); | ||
1115 | } | ||
1116 | |||
1117 | if (filter_mask & RT5677_DA_MONO4_L_FILTER) { | ||
1118 | asrc4_mask |= RT5677_DA_MONO4L_CLK_SEL_MASK; | ||
1119 | asrc4_value = (asrc4_value & ~RT5677_DA_MONO4L_CLK_SEL_MASK) | ||
1120 | | (clk_src << RT5677_DA_MONO4L_CLK_SEL_SFT); | ||
1121 | } | ||
1122 | |||
1123 | if (filter_mask & RT5677_DA_MONO4_R_FILTER) { | ||
1124 | asrc4_mask |= RT5677_DA_MONO4R_CLK_SEL_MASK; | ||
1125 | asrc4_value = (asrc4_value & ~RT5677_DA_MONO4R_CLK_SEL_MASK) | ||
1126 | | (clk_src << RT5677_DA_MONO4R_CLK_SEL_SFT); | ||
1127 | } | ||
1128 | |||
1129 | if (asrc4_mask) | ||
1130 | regmap_update_bits(rt5677->regmap, RT5677_ASRC_4, asrc4_mask, | ||
1131 | asrc4_value); | ||
1132 | |||
1133 | /* ASRC 5 */ | ||
1134 | if (filter_mask & RT5677_AD_STEREO1_FILTER) { | ||
1135 | asrc5_mask |= RT5677_AD_STO1_CLK_SEL_MASK; | ||
1136 | asrc5_value = (asrc5_value & ~RT5677_AD_STO1_CLK_SEL_MASK) | ||
1137 | | (clk_src << RT5677_AD_STO1_CLK_SEL_SFT); | ||
1138 | } | ||
1139 | |||
1140 | if (filter_mask & RT5677_AD_STEREO2_FILTER) { | ||
1141 | asrc5_mask |= RT5677_AD_STO2_CLK_SEL_MASK; | ||
1142 | asrc5_value = (asrc5_value & ~RT5677_AD_STO2_CLK_SEL_MASK) | ||
1143 | | (clk_src << RT5677_AD_STO2_CLK_SEL_SFT); | ||
1144 | } | ||
1145 | |||
1146 | if (filter_mask & RT5677_AD_STEREO3_FILTER) { | ||
1147 | asrc5_mask |= RT5677_AD_STO3_CLK_SEL_MASK; | ||
1148 | asrc5_value = (asrc5_value & ~RT5677_AD_STO3_CLK_SEL_MASK) | ||
1149 | | (clk_src << RT5677_AD_STO3_CLK_SEL_SFT); | ||
1150 | } | ||
1151 | |||
1152 | if (filter_mask & RT5677_AD_STEREO4_FILTER) { | ||
1153 | asrc5_mask |= RT5677_AD_STO4_CLK_SEL_MASK; | ||
1154 | asrc5_value = (asrc5_value & ~RT5677_AD_STO4_CLK_SEL_MASK) | ||
1155 | | (clk_src << RT5677_AD_STO4_CLK_SEL_SFT); | ||
1156 | } | ||
1157 | |||
1158 | if (asrc5_mask) | ||
1159 | regmap_update_bits(rt5677->regmap, RT5677_ASRC_5, asrc5_mask, | ||
1160 | asrc5_value); | ||
1161 | |||
1162 | /* ASRC 6 */ | ||
1163 | if (filter_mask & RT5677_AD_MONO_L_FILTER) { | ||
1164 | asrc6_mask |= RT5677_AD_MONOL_CLK_SEL_MASK; | ||
1165 | asrc6_value = (asrc6_value & ~RT5677_AD_MONOL_CLK_SEL_MASK) | ||
1166 | | (clk_src << RT5677_AD_MONOL_CLK_SEL_SFT); | ||
1167 | } | ||
1168 | |||
1169 | if (filter_mask & RT5677_AD_MONO_R_FILTER) { | ||
1170 | asrc6_mask |= RT5677_AD_MONOR_CLK_SEL_MASK; | ||
1171 | asrc6_value = (asrc6_value & ~RT5677_AD_MONOR_CLK_SEL_MASK) | ||
1172 | | (clk_src << RT5677_AD_MONOR_CLK_SEL_SFT); | ||
1173 | } | ||
1174 | |||
1175 | if (asrc6_mask) | ||
1176 | regmap_update_bits(rt5677->regmap, RT5677_ASRC_6, asrc6_mask, | ||
1177 | asrc6_value); | ||
1178 | |||
1179 | /* ASRC 7 */ | ||
1180 | if (filter_mask & RT5677_DSP_OB_0_3_FILTER) { | ||
1181 | asrc7_mask |= RT5677_DSP_OB_0_3_CLK_SEL_MASK; | ||
1182 | asrc7_value = (asrc7_value & ~RT5677_DSP_OB_0_3_CLK_SEL_MASK) | ||
1183 | | (clk_src << RT5677_DSP_OB_0_3_CLK_SEL_SFT); | ||
1184 | } | ||
1185 | |||
1186 | if (filter_mask & RT5677_DSP_OB_4_7_FILTER) { | ||
1187 | asrc7_mask |= RT5677_DSP_OB_4_7_CLK_SEL_MASK; | ||
1188 | asrc7_value = (asrc7_value & ~RT5677_DSP_OB_4_7_CLK_SEL_MASK) | ||
1189 | | (clk_src << RT5677_DSP_OB_4_7_CLK_SEL_SFT); | ||
1190 | } | ||
1191 | |||
1192 | if (asrc7_mask) | ||
1193 | regmap_update_bits(rt5677->regmap, RT5677_ASRC_7, asrc7_mask, | ||
1194 | asrc7_value); | ||
1195 | |||
1196 | return 0; | ||
1197 | } | ||
1198 | EXPORT_SYMBOL_GPL(rt5677_sel_asrc_clk_src); | ||
1199 | |||
1037 | /* Digital Mixer */ | 1200 | /* Digital Mixer */ |
1038 | static const struct snd_kcontrol_new rt5677_sto1_adc_l_mix[] = { | 1201 | static const struct snd_kcontrol_new rt5677_sto1_adc_l_mix[] = { |
1039 | SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO1_ADC_MIXER, | 1202 | SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO1_ADC_MIXER, |