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