1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // MediaTek ALSA SoC Audio DAI Hostless Control 4 // 5 // Copyright (c) 2022 MediaTek Inc. 6 // Author: Jiaxin Yu <jiaxin.yu@mediatek.com> 7 8 #include "mt8186-afe-common.h" 9 10 static const struct snd_pcm_hardware mt8186_hostless_hardware = { 11 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 12 SNDRV_PCM_INFO_MMAP_VALID), 13 .period_bytes_min = 256, 14 .period_bytes_max = 4 * 48 * 1024, 15 .periods_min = 2, 16 .periods_max = 256, 17 .buffer_bytes_max = 4 * 48 * 1024, 18 .fifo_size = 0, 19 }; 20 21 /* dai component */ 22 static const struct snd_soc_dapm_route mtk_dai_hostless_routes[] = { 23 /* Hostless ADDA Loopback */ 24 {"ADDA_DL_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, 25 {"ADDA_DL_CH1", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, 26 {"ADDA_DL_CH2", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, 27 {"ADDA_DL_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, 28 {"I2S1_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, 29 {"I2S1_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, 30 {"I2S3_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, 31 {"I2S3_CH1", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, 32 {"I2S3_CH2", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, 33 {"I2S3_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, 34 {"Hostless LPBK UL", NULL, "ADDA_UL_Mux"}, 35 36 /* Hostelss FM */ 37 /* connsys_i2s to hw gain 1*/ 38 {"Hostless FM UL", NULL, "Connsys I2S"}, 39 40 {"HW_GAIN1_IN_CH1", "CONNSYS_I2S_CH1 Switch", "Hostless FM DL"}, 41 {"HW_GAIN1_IN_CH2", "CONNSYS_I2S_CH2 Switch", "Hostless FM DL"}, 42 /* hw gain to adda dl */ 43 {"Hostless FM UL", NULL, "HW Gain 1 Out"}, 44 45 {"ADDA_DL_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"}, 46 {"ADDA_DL_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"}, 47 /* hw gain to i2s3 */ 48 {"I2S3_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"}, 49 {"I2S3_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"}, 50 /* hw gain to i2s1 */ 51 {"I2S1_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"}, 52 {"I2S1_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"}, 53 54 /* Hostless_SRC */ 55 {"ADDA_DL_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"}, 56 {"ADDA_DL_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"}, 57 {"I2S1_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"}, 58 {"I2S1_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"}, 59 {"I2S3_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"}, 60 {"I2S3_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"}, 61 {"Hostless_SRC_1_UL", NULL, "HW_SRC_1_Out"}, 62 63 /* Hostless_SRC_bargein */ 64 {"HW_SRC_1_IN_CH1", "I2S0_CH1 Switch", "Hostless_SRC_Bargein_DL"}, 65 {"HW_SRC_1_IN_CH2", "I2S0_CH2 Switch", "Hostless_SRC_Bargein_DL"}, 66 {"Hostless_SRC_Bargein_UL", NULL, "I2S0"}, 67 68 /* Hostless AAudio */ 69 {"Hostless HW Gain AAudio In", NULL, "HW Gain 2 In"}, 70 {"Hostless SRC AAudio UL", NULL, "HW Gain 2 Out"}, 71 {"HW_SRC_2_IN_CH1", "HW_GAIN2_OUT_CH1 Switch", "Hostless SRC AAudio DL"}, 72 {"HW_SRC_2_IN_CH2", "HW_GAIN2_OUT_CH2 Switch", "Hostless SRC AAudio DL"}, 73 }; 74 75 /* dai ops */ 76 static int mtk_dai_hostless_startup(struct snd_pcm_substream *substream, 77 struct snd_soc_dai *dai) 78 { 79 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 80 struct snd_pcm_runtime *runtime = substream->runtime; 81 int ret; 82 83 snd_soc_set_runtime_hwparams(substream, &mt8186_hostless_hardware); 84 85 ret = snd_pcm_hw_constraint_integer(runtime, 86 SNDRV_PCM_HW_PARAM_PERIODS); 87 if (ret < 0) { 88 dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n"); 89 return ret; 90 } 91 92 return 0; 93 } 94 95 static const struct snd_soc_dai_ops mtk_dai_hostless_ops = { 96 .startup = mtk_dai_hostless_startup, 97 }; 98 99 /* dai driver */ 100 #define MTK_HOSTLESS_RATES (SNDRV_PCM_RATE_8000_48000 |\ 101 SNDRV_PCM_RATE_88200 |\ 102 SNDRV_PCM_RATE_96000 |\ 103 SNDRV_PCM_RATE_176400 |\ 104 SNDRV_PCM_RATE_192000) 105 106 #define MTK_HOSTLESS_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ 107 SNDRV_PCM_FMTBIT_S24_LE |\ 108 SNDRV_PCM_FMTBIT_S32_LE) 109 110 static struct snd_soc_dai_driver mtk_dai_hostless_driver[] = { 111 { 112 .name = "Hostless LPBK DAI", 113 .id = MT8186_DAI_HOSTLESS_LPBK, 114 .playback = { 115 .stream_name = "Hostless LPBK DL", 116 .channels_min = 1, 117 .channels_max = 2, 118 .rates = MTK_HOSTLESS_RATES, 119 .formats = MTK_HOSTLESS_FORMATS, 120 }, 121 .capture = { 122 .stream_name = "Hostless LPBK UL", 123 .channels_min = 1, 124 .channels_max = 2, 125 .rates = MTK_HOSTLESS_RATES, 126 .formats = MTK_HOSTLESS_FORMATS, 127 }, 128 .ops = &mtk_dai_hostless_ops, 129 }, 130 { 131 .name = "Hostless FM DAI", 132 .id = MT8186_DAI_HOSTLESS_FM, 133 .playback = { 134 .stream_name = "Hostless FM DL", 135 .channels_min = 1, 136 .channels_max = 2, 137 .rates = MTK_HOSTLESS_RATES, 138 .formats = MTK_HOSTLESS_FORMATS, 139 }, 140 .capture = { 141 .stream_name = "Hostless FM UL", 142 .channels_min = 1, 143 .channels_max = 2, 144 .rates = MTK_HOSTLESS_RATES, 145 .formats = MTK_HOSTLESS_FORMATS, 146 }, 147 .ops = &mtk_dai_hostless_ops, 148 }, 149 { 150 .name = "Hostless_SRC_1_DAI", 151 .id = MT8186_DAI_HOSTLESS_SRC_1, 152 .playback = { 153 .stream_name = "Hostless_SRC_1_DL", 154 .channels_min = 1, 155 .channels_max = 2, 156 .rates = MTK_HOSTLESS_RATES, 157 .formats = MTK_HOSTLESS_FORMATS, 158 }, 159 .capture = { 160 .stream_name = "Hostless_SRC_1_UL", 161 .channels_min = 1, 162 .channels_max = 2, 163 .rates = MTK_HOSTLESS_RATES, 164 .formats = MTK_HOSTLESS_FORMATS, 165 }, 166 .ops = &mtk_dai_hostless_ops, 167 }, 168 { 169 .name = "Hostless_SRC_Bargein_DAI", 170 .id = MT8186_DAI_HOSTLESS_SRC_BARGEIN, 171 .playback = { 172 .stream_name = "Hostless_SRC_Bargein_DL", 173 .channels_min = 1, 174 .channels_max = 2, 175 .rates = MTK_HOSTLESS_RATES, 176 .formats = MTK_HOSTLESS_FORMATS, 177 }, 178 .capture = { 179 .stream_name = "Hostless_SRC_Bargein_UL", 180 .channels_min = 1, 181 .channels_max = 2, 182 .rates = MTK_HOSTLESS_RATES, 183 .formats = MTK_HOSTLESS_FORMATS, 184 }, 185 .ops = &mtk_dai_hostless_ops, 186 }, 187 /* BE dai */ 188 { 189 .name = "Hostless_UL1 DAI", 190 .id = MT8186_DAI_HOSTLESS_UL1, 191 .capture = { 192 .stream_name = "Hostless_UL1 UL", 193 .channels_min = 1, 194 .channels_max = 4, 195 .rates = MTK_HOSTLESS_RATES, 196 .formats = MTK_HOSTLESS_FORMATS, 197 }, 198 .ops = &mtk_dai_hostless_ops, 199 }, 200 { 201 .name = "Hostless_UL2 DAI", 202 .id = MT8186_DAI_HOSTLESS_UL2, 203 .capture = { 204 .stream_name = "Hostless_UL2 UL", 205 .channels_min = 1, 206 .channels_max = 4, 207 .rates = MTK_HOSTLESS_RATES, 208 .formats = MTK_HOSTLESS_FORMATS, 209 }, 210 .ops = &mtk_dai_hostless_ops, 211 }, 212 { 213 .name = "Hostless_UL3 DAI", 214 .id = MT8186_DAI_HOSTLESS_UL3, 215 .capture = { 216 .stream_name = "Hostless_UL3 UL", 217 .channels_min = 1, 218 .channels_max = 2, 219 .rates = MTK_HOSTLESS_RATES, 220 .formats = MTK_HOSTLESS_FORMATS, 221 }, 222 .ops = &mtk_dai_hostless_ops, 223 }, 224 { 225 .name = "Hostless_UL5 DAI", 226 .id = MT8186_DAI_HOSTLESS_UL5, 227 .capture = { 228 .stream_name = "Hostless_UL5 UL", 229 .channels_min = 1, 230 .channels_max = 12, 231 .rates = MTK_HOSTLESS_RATES, 232 .formats = MTK_HOSTLESS_FORMATS, 233 }, 234 .ops = &mtk_dai_hostless_ops, 235 }, 236 { 237 .name = "Hostless_UL6 DAI", 238 .id = MT8186_DAI_HOSTLESS_UL6, 239 .capture = { 240 .stream_name = "Hostless_UL6 UL", 241 .channels_min = 1, 242 .channels_max = 2, 243 .rates = MTK_HOSTLESS_RATES, 244 .formats = MTK_HOSTLESS_FORMATS, 245 }, 246 .ops = &mtk_dai_hostless_ops, 247 }, 248 { 249 .name = "Hostless HW Gain AAudio DAI", 250 .id = MT8186_DAI_HOSTLESS_HW_GAIN_AAUDIO, 251 .capture = { 252 .stream_name = "Hostless HW Gain AAudio In", 253 .channels_min = 1, 254 .channels_max = 2, 255 .rates = MTK_HOSTLESS_RATES, 256 .formats = MTK_HOSTLESS_FORMATS, 257 }, 258 .ops = &mtk_dai_hostless_ops, 259 }, 260 { 261 .name = "Hostless SRC AAudio DAI", 262 .id = MT8186_DAI_HOSTLESS_SRC_AAUDIO, 263 .playback = { 264 .stream_name = "Hostless SRC AAudio DL", 265 .channels_min = 1, 266 .channels_max = 2, 267 .rates = MTK_HOSTLESS_RATES, 268 .formats = MTK_HOSTLESS_FORMATS, 269 }, 270 .capture = { 271 .stream_name = "Hostless SRC AAudio UL", 272 .channels_min = 1, 273 .channels_max = 2, 274 .rates = MTK_HOSTLESS_RATES, 275 .formats = MTK_HOSTLESS_FORMATS, 276 }, 277 .ops = &mtk_dai_hostless_ops, 278 }, 279 }; 280 281 int mt8186_dai_hostless_register(struct mtk_base_afe *afe) 282 { 283 struct mtk_base_afe_dai *dai; 284 285 dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); 286 if (!dai) 287 return -ENOMEM; 288 289 list_add(&dai->list, &afe->sub_dais); 290 291 dai->dai_drivers = mtk_dai_hostless_driver; 292 dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_hostless_driver); 293 294 dai->dapm_routes = mtk_dai_hostless_routes; 295 dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_hostless_routes); 296 297 return 0; 298 } 299