diff options
| -rw-r--r-- | sound/soc/codecs/rt5677.c | 163 | ||||
| -rw-r--r-- | sound/soc/codecs/rt5677.h | 79 |
2 files changed, 242 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, |
diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index 07df96b43f59..9dceb41d18ea 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h | |||
| @@ -1406,6 +1406,46 @@ | |||
| 1406 | #define RT5677_DSP_CLK_SRC_PLL2 (0x0 << 7) | 1406 | #define RT5677_DSP_CLK_SRC_PLL2 (0x0 << 7) |
| 1407 | #define RT5677_DSP_CLK_SRC_BYPASS (0x1 << 7) | 1407 | #define RT5677_DSP_CLK_SRC_BYPASS (0x1 << 7) |
| 1408 | 1408 | ||
| 1409 | /* ASRC Control 3 (0x85) */ | ||
| 1410 | #define RT5677_DA_STO_CLK_SEL_MASK (0xf << 12) | ||
| 1411 | #define RT5677_DA_STO_CLK_SEL_SFT 12 | ||
| 1412 | #define RT5677_DA_MONO2L_CLK_SEL_MASK (0xf << 4) | ||
| 1413 | #define RT5677_DA_MONO2L_CLK_SEL_SFT 4 | ||
| 1414 | #define RT5677_DA_MONO2R_CLK_SEL_MASK (0xf << 0) | ||
| 1415 | #define RT5677_DA_MONO2R_CLK_SEL_SFT 0 | ||
| 1416 | |||
| 1417 | /* ASRC Control 4 (0x86) */ | ||
| 1418 | #define RT5677_DA_MONO3L_CLK_SEL_MASK (0xf << 12) | ||
| 1419 | #define RT5677_DA_MONO3L_CLK_SEL_SFT 12 | ||
| 1420 | #define RT5677_DA_MONO3R_CLK_SEL_MASK (0xf << 8) | ||
| 1421 | #define RT5677_DA_MONO3R_CLK_SEL_SFT 8 | ||
| 1422 | #define RT5677_DA_MONO4L_CLK_SEL_MASK (0xf << 4) | ||
| 1423 | #define RT5677_DA_MONO4L_CLK_SEL_SFT 4 | ||
| 1424 | #define RT5677_DA_MONO4R_CLK_SEL_MASK (0xf << 0) | ||
| 1425 | #define RT5677_DA_MONO4R_CLK_SEL_SFT 0 | ||
| 1426 | |||
| 1427 | /* ASRC Control 5 (0x87) */ | ||
| 1428 | #define RT5677_AD_STO1_CLK_SEL_MASK (0xf << 12) | ||
| 1429 | #define RT5677_AD_STO1_CLK_SEL_SFT 12 | ||
| 1430 | #define RT5677_AD_STO2_CLK_SEL_MASK (0xf << 8) | ||
| 1431 | #define RT5677_AD_STO2_CLK_SEL_SFT 8 | ||
| 1432 | #define RT5677_AD_STO3_CLK_SEL_MASK (0xf << 4) | ||
| 1433 | #define RT5677_AD_STO3_CLK_SEL_SFT 4 | ||
| 1434 | #define RT5677_AD_STO4_CLK_SEL_MASK (0xf << 0) | ||
| 1435 | #define RT5677_AD_STO4_CLK_SEL_SFT 0 | ||
| 1436 | |||
| 1437 | /* ASRC Control 6 (0x88) */ | ||
| 1438 | #define RT5677_AD_MONOL_CLK_SEL_MASK (0xf << 12) | ||
| 1439 | #define RT5677_AD_MONOL_CLK_SEL_SFT 12 | ||
| 1440 | #define RT5677_AD_MONOR_CLK_SEL_MASK (0xf << 8) | ||
| 1441 | #define RT5677_AD_MONOR_CLK_SEL_SFT 8 | ||
| 1442 | |||
| 1443 | /* ASRC Control 7 (0x89) */ | ||
| 1444 | #define RT5677_DSP_OB_0_3_CLK_SEL_MASK (0xf << 12) | ||
| 1445 | #define RT5677_DSP_OB_0_3_CLK_SEL_SFT 12 | ||
| 1446 | #define RT5677_DSP_OB_4_7_CLK_SEL_MASK (0xf << 8) | ||
| 1447 | #define RT5677_DSP_OB_4_7_CLK_SEL_SFT 8 | ||
| 1448 | |||
| 1409 | /* VAD Function Control 4 (0x9f) */ | 1449 | /* VAD Function Control 4 (0x9f) */ |
| 1410 | #define RT5677_VAD_SRC_MASK (0x7 << 8) | 1450 | #define RT5677_VAD_SRC_MASK (0x7 << 8) |
| 1411 | #define RT5677_VAD_SRC_SFT 8 | 1451 | #define RT5677_VAD_SRC_SFT 8 |
| @@ -1670,6 +1710,42 @@ enum rt5677_type { | |||
| 1670 | RT5676, | 1710 | RT5676, |
| 1671 | }; | 1711 | }; |
| 1672 | 1712 | ||
| 1713 | /* ASRC clock source selection */ | ||
| 1714 | enum { | ||
| 1715 | RT5677_CLK_SEL_SYS, | ||
| 1716 | RT5677_CLK_SEL_I2S1_ASRC, | ||
| 1717 | RT5677_CLK_SEL_I2S2_ASRC, | ||
| 1718 | RT5677_CLK_SEL_I2S3_ASRC, | ||
| 1719 | RT5677_CLK_SEL_I2S4_ASRC, | ||
| 1720 | RT5677_CLK_SEL_I2S5_ASRC, | ||
| 1721 | RT5677_CLK_SEL_I2S6_ASRC, | ||
| 1722 | RT5677_CLK_SEL_SYS2, | ||
| 1723 | RT5677_CLK_SEL_SYS3, | ||
| 1724 | RT5677_CLK_SEL_SYS4, | ||
| 1725 | RT5677_CLK_SEL_SYS5, | ||
| 1726 | RT5677_CLK_SEL_SYS6, | ||
| 1727 | RT5677_CLK_SEL_SYS7, | ||
| 1728 | }; | ||
| 1729 | |||
| 1730 | /* filter mask */ | ||
| 1731 | enum { | ||
| 1732 | RT5677_DA_STEREO_FILTER = 0x1, | ||
| 1733 | RT5677_DA_MONO2_L_FILTER = (0x1 << 1), | ||
| 1734 | RT5677_DA_MONO2_R_FILTER = (0x1 << 2), | ||
| 1735 | RT5677_DA_MONO3_L_FILTER = (0x1 << 3), | ||
| 1736 | RT5677_DA_MONO3_R_FILTER = (0x1 << 4), | ||
| 1737 | RT5677_DA_MONO4_L_FILTER = (0x1 << 5), | ||
| 1738 | RT5677_DA_MONO4_R_FILTER = (0x1 << 6), | ||
| 1739 | RT5677_AD_STEREO1_FILTER = (0x1 << 7), | ||
| 1740 | RT5677_AD_STEREO2_FILTER = (0x1 << 8), | ||
| 1741 | RT5677_AD_STEREO3_FILTER = (0x1 << 9), | ||
| 1742 | RT5677_AD_STEREO4_FILTER = (0x1 << 10), | ||
| 1743 | RT5677_AD_MONO_L_FILTER = (0x1 << 11), | ||
| 1744 | RT5677_AD_MONO_R_FILTER = (0x1 << 12), | ||
| 1745 | RT5677_DSP_OB_0_3_FILTER = (0x1 << 13), | ||
| 1746 | RT5677_DSP_OB_4_7_FILTER = (0x1 << 14), | ||
| 1747 | }; | ||
| 1748 | |||
| 1673 | struct rt5677_priv { | 1749 | struct rt5677_priv { |
| 1674 | struct snd_soc_codec *codec; | 1750 | struct snd_soc_codec *codec; |
| 1675 | struct rt5677_platform_data pdata; | 1751 | struct rt5677_platform_data pdata; |
| @@ -1696,4 +1772,7 @@ struct rt5677_priv { | |||
| 1696 | bool is_vref_slow; | 1772 | bool is_vref_slow; |
| 1697 | }; | 1773 | }; |
| 1698 | 1774 | ||
| 1775 | int rt5677_sel_asrc_clk_src(struct snd_soc_codec *codec, | ||
| 1776 | unsigned int filter_mask, unsigned int clk_src); | ||
| 1777 | |||
| 1699 | #endif /* __RT5677_H__ */ | 1778 | #endif /* __RT5677_H__ */ |
