1*5097c0c8SAlexandre Mergnat // SPDX-License-Identifier: GPL-2.0 2*5097c0c8SAlexandre Mergnat /* 3*5097c0c8SAlexandre Mergnat * MediaTek 8365 ALSA SoC Audio DAI PCM Control 4*5097c0c8SAlexandre Mergnat * 5*5097c0c8SAlexandre Mergnat * Copyright (c) 2024 MediaTek Inc. 6*5097c0c8SAlexandre Mergnat * Authors: Jia Zeng <jia.zeng@mediatek.com> 7*5097c0c8SAlexandre Mergnat * Alexandre Mergnat <amergnat@baylibre.com> 8*5097c0c8SAlexandre Mergnat */ 9*5097c0c8SAlexandre Mergnat 10*5097c0c8SAlexandre Mergnat #include <linux/bitops.h> 11*5097c0c8SAlexandre Mergnat #include <linux/regmap.h> 12*5097c0c8SAlexandre Mergnat #include <sound/pcm_params.h> 13*5097c0c8SAlexandre Mergnat #include "mt8365-afe-clk.h" 14*5097c0c8SAlexandre Mergnat #include "mt8365-afe-common.h" 15*5097c0c8SAlexandre Mergnat 16*5097c0c8SAlexandre Mergnat struct mt8365_pcm_intf_data { 17*5097c0c8SAlexandre Mergnat bool slave_mode; 18*5097c0c8SAlexandre Mergnat bool lrck_inv; 19*5097c0c8SAlexandre Mergnat bool bck_inv; 20*5097c0c8SAlexandre Mergnat unsigned int format; 21*5097c0c8SAlexandre Mergnat }; 22*5097c0c8SAlexandre Mergnat 23*5097c0c8SAlexandre Mergnat /* DAI Drivers */ 24*5097c0c8SAlexandre Mergnat 25*5097c0c8SAlexandre Mergnat static void mt8365_dai_enable_pcm1(struct mtk_base_afe *afe) 26*5097c0c8SAlexandre Mergnat { 27*5097c0c8SAlexandre Mergnat regmap_update_bits(afe->regmap, PCM_INTF_CON1, 28*5097c0c8SAlexandre Mergnat PCM_INTF_CON1_EN, PCM_INTF_CON1_EN); 29*5097c0c8SAlexandre Mergnat } 30*5097c0c8SAlexandre Mergnat 31*5097c0c8SAlexandre Mergnat static void mt8365_dai_disable_pcm1(struct mtk_base_afe *afe) 32*5097c0c8SAlexandre Mergnat { 33*5097c0c8SAlexandre Mergnat regmap_update_bits(afe->regmap, PCM_INTF_CON1, 34*5097c0c8SAlexandre Mergnat PCM_INTF_CON1_EN, 0x0); 35*5097c0c8SAlexandre Mergnat } 36*5097c0c8SAlexandre Mergnat 37*5097c0c8SAlexandre Mergnat static int mt8365_dai_configure_pcm1(struct snd_pcm_substream *substream, 38*5097c0c8SAlexandre Mergnat struct snd_soc_dai *dai) 39*5097c0c8SAlexandre Mergnat { 40*5097c0c8SAlexandre Mergnat struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 41*5097c0c8SAlexandre Mergnat struct mt8365_afe_private *afe_priv = afe->platform_priv; 42*5097c0c8SAlexandre Mergnat struct mt8365_pcm_intf_data *pcm_priv = afe_priv->dai_priv[MT8365_AFE_IO_PCM1]; 43*5097c0c8SAlexandre Mergnat bool slave_mode = pcm_priv->slave_mode; 44*5097c0c8SAlexandre Mergnat bool lrck_inv = pcm_priv->lrck_inv; 45*5097c0c8SAlexandre Mergnat bool bck_inv = pcm_priv->bck_inv; 46*5097c0c8SAlexandre Mergnat unsigned int fmt = pcm_priv->format; 47*5097c0c8SAlexandre Mergnat unsigned int bit_width = dai->sample_bits; 48*5097c0c8SAlexandre Mergnat unsigned int val = 0; 49*5097c0c8SAlexandre Mergnat 50*5097c0c8SAlexandre Mergnat if (!slave_mode) { 51*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_MASTER_MODE | 52*5097c0c8SAlexandre Mergnat PCM_INTF_CON1_BYPASS_ASRC; 53*5097c0c8SAlexandre Mergnat 54*5097c0c8SAlexandre Mergnat if (lrck_inv) 55*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_SYNC_OUT_INV; 56*5097c0c8SAlexandre Mergnat if (bck_inv) 57*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_BCLK_OUT_INV; 58*5097c0c8SAlexandre Mergnat } else { 59*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_SLAVE_MODE; 60*5097c0c8SAlexandre Mergnat 61*5097c0c8SAlexandre Mergnat if (lrck_inv) 62*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_SYNC_IN_INV; 63*5097c0c8SAlexandre Mergnat if (bck_inv) 64*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_BCLK_IN_INV; 65*5097c0c8SAlexandre Mergnat 66*5097c0c8SAlexandre Mergnat /* TODO: add asrc setting */ 67*5097c0c8SAlexandre Mergnat } 68*5097c0c8SAlexandre Mergnat 69*5097c0c8SAlexandre Mergnat val |= FIELD_PREP(PCM_INTF_CON1_FORMAT_MASK, fmt); 70*5097c0c8SAlexandre Mergnat 71*5097c0c8SAlexandre Mergnat if (fmt == MT8365_PCM_FORMAT_PCMA || 72*5097c0c8SAlexandre Mergnat fmt == MT8365_PCM_FORMAT_PCMB) 73*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_SYNC_LEN(1); 74*5097c0c8SAlexandre Mergnat else 75*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_SYNC_LEN(bit_width); 76*5097c0c8SAlexandre Mergnat 77*5097c0c8SAlexandre Mergnat switch (substream->runtime->rate) { 78*5097c0c8SAlexandre Mergnat case 48000: 79*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_FS_48K; 80*5097c0c8SAlexandre Mergnat break; 81*5097c0c8SAlexandre Mergnat case 32000: 82*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_FS_32K; 83*5097c0c8SAlexandre Mergnat break; 84*5097c0c8SAlexandre Mergnat case 16000: 85*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_FS_16K; 86*5097c0c8SAlexandre Mergnat break; 87*5097c0c8SAlexandre Mergnat case 8000: 88*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_FS_8K; 89*5097c0c8SAlexandre Mergnat break; 90*5097c0c8SAlexandre Mergnat default: 91*5097c0c8SAlexandre Mergnat return -EINVAL; 92*5097c0c8SAlexandre Mergnat } 93*5097c0c8SAlexandre Mergnat 94*5097c0c8SAlexandre Mergnat if (bit_width > 16) 95*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_24BIT | PCM_INTF_CON1_64BCK; 96*5097c0c8SAlexandre Mergnat else 97*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_16BIT | PCM_INTF_CON1_32BCK; 98*5097c0c8SAlexandre Mergnat 99*5097c0c8SAlexandre Mergnat val |= PCM_INTF_CON1_EXT_MODEM; 100*5097c0c8SAlexandre Mergnat 101*5097c0c8SAlexandre Mergnat regmap_update_bits(afe->regmap, PCM_INTF_CON1, 102*5097c0c8SAlexandre Mergnat PCM_INTF_CON1_CONFIG_MASK, val); 103*5097c0c8SAlexandre Mergnat 104*5097c0c8SAlexandre Mergnat return 0; 105*5097c0c8SAlexandre Mergnat } 106*5097c0c8SAlexandre Mergnat 107*5097c0c8SAlexandre Mergnat static int mt8365_dai_pcm1_startup(struct snd_pcm_substream *substream, 108*5097c0c8SAlexandre Mergnat struct snd_soc_dai *dai) 109*5097c0c8SAlexandre Mergnat { 110*5097c0c8SAlexandre Mergnat struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 111*5097c0c8SAlexandre Mergnat 112*5097c0c8SAlexandre Mergnat if (snd_soc_dai_active(dai)) 113*5097c0c8SAlexandre Mergnat return 0; 114*5097c0c8SAlexandre Mergnat 115*5097c0c8SAlexandre Mergnat mt8365_afe_enable_main_clk(afe); 116*5097c0c8SAlexandre Mergnat 117*5097c0c8SAlexandre Mergnat return 0; 118*5097c0c8SAlexandre Mergnat } 119*5097c0c8SAlexandre Mergnat 120*5097c0c8SAlexandre Mergnat static void mt8365_dai_pcm1_shutdown(struct snd_pcm_substream *substream, 121*5097c0c8SAlexandre Mergnat struct snd_soc_dai *dai) 122*5097c0c8SAlexandre Mergnat { 123*5097c0c8SAlexandre Mergnat struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 124*5097c0c8SAlexandre Mergnat 125*5097c0c8SAlexandre Mergnat if (snd_soc_dai_active(dai)) 126*5097c0c8SAlexandre Mergnat return; 127*5097c0c8SAlexandre Mergnat 128*5097c0c8SAlexandre Mergnat mt8365_dai_disable_pcm1(afe); 129*5097c0c8SAlexandre Mergnat mt8365_afe_disable_main_clk(afe); 130*5097c0c8SAlexandre Mergnat } 131*5097c0c8SAlexandre Mergnat 132*5097c0c8SAlexandre Mergnat static int mt8365_dai_pcm1_prepare(struct snd_pcm_substream *substream, 133*5097c0c8SAlexandre Mergnat struct snd_soc_dai *dai) 134*5097c0c8SAlexandre Mergnat { 135*5097c0c8SAlexandre Mergnat struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 136*5097c0c8SAlexandre Mergnat int ret; 137*5097c0c8SAlexandre Mergnat 138*5097c0c8SAlexandre Mergnat if ((snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_PLAYBACK) + 139*5097c0c8SAlexandre Mergnat snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_CAPTURE)) > 1) { 140*5097c0c8SAlexandre Mergnat dev_info(afe->dev, "%s '%s' active(%u-%u) already\n", 141*5097c0c8SAlexandre Mergnat __func__, snd_pcm_stream_str(substream), 142*5097c0c8SAlexandre Mergnat snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_PLAYBACK), 143*5097c0c8SAlexandre Mergnat snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_CAPTURE)); 144*5097c0c8SAlexandre Mergnat return 0; 145*5097c0c8SAlexandre Mergnat } 146*5097c0c8SAlexandre Mergnat 147*5097c0c8SAlexandre Mergnat ret = mt8365_dai_configure_pcm1(substream, dai); 148*5097c0c8SAlexandre Mergnat if (ret) 149*5097c0c8SAlexandre Mergnat return ret; 150*5097c0c8SAlexandre Mergnat 151*5097c0c8SAlexandre Mergnat mt8365_dai_enable_pcm1(afe); 152*5097c0c8SAlexandre Mergnat 153*5097c0c8SAlexandre Mergnat return 0; 154*5097c0c8SAlexandre Mergnat } 155*5097c0c8SAlexandre Mergnat 156*5097c0c8SAlexandre Mergnat static int mt8365_dai_pcm1_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 157*5097c0c8SAlexandre Mergnat { 158*5097c0c8SAlexandre Mergnat struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 159*5097c0c8SAlexandre Mergnat struct mt8365_afe_private *afe_priv = afe->platform_priv; 160*5097c0c8SAlexandre Mergnat struct mt8365_pcm_intf_data *pcm_priv = afe_priv->dai_priv[MT8365_AFE_IO_PCM1]; 161*5097c0c8SAlexandre Mergnat 162*5097c0c8SAlexandre Mergnat switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 163*5097c0c8SAlexandre Mergnat case SND_SOC_DAIFMT_I2S: 164*5097c0c8SAlexandre Mergnat pcm_priv->format = MT8365_PCM_FORMAT_I2S; 165*5097c0c8SAlexandre Mergnat break; 166*5097c0c8SAlexandre Mergnat default: 167*5097c0c8SAlexandre Mergnat return -EINVAL; 168*5097c0c8SAlexandre Mergnat } 169*5097c0c8SAlexandre Mergnat 170*5097c0c8SAlexandre Mergnat switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 171*5097c0c8SAlexandre Mergnat case SND_SOC_DAIFMT_NB_NF: 172*5097c0c8SAlexandre Mergnat pcm_priv->bck_inv = false; 173*5097c0c8SAlexandre Mergnat pcm_priv->lrck_inv = false; 174*5097c0c8SAlexandre Mergnat break; 175*5097c0c8SAlexandre Mergnat case SND_SOC_DAIFMT_NB_IF: 176*5097c0c8SAlexandre Mergnat pcm_priv->bck_inv = false; 177*5097c0c8SAlexandre Mergnat pcm_priv->lrck_inv = true; 178*5097c0c8SAlexandre Mergnat break; 179*5097c0c8SAlexandre Mergnat case SND_SOC_DAIFMT_IB_NF: 180*5097c0c8SAlexandre Mergnat pcm_priv->bck_inv = true; 181*5097c0c8SAlexandre Mergnat pcm_priv->lrck_inv = false; 182*5097c0c8SAlexandre Mergnat break; 183*5097c0c8SAlexandre Mergnat case SND_SOC_DAIFMT_IB_IF: 184*5097c0c8SAlexandre Mergnat pcm_priv->bck_inv = true; 185*5097c0c8SAlexandre Mergnat pcm_priv->lrck_inv = true; 186*5097c0c8SAlexandre Mergnat break; 187*5097c0c8SAlexandre Mergnat default: 188*5097c0c8SAlexandre Mergnat return -EINVAL; 189*5097c0c8SAlexandre Mergnat } 190*5097c0c8SAlexandre Mergnat 191*5097c0c8SAlexandre Mergnat switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 192*5097c0c8SAlexandre Mergnat case SND_SOC_DAIFMT_CBM_CFM: 193*5097c0c8SAlexandre Mergnat pcm_priv->slave_mode = true; 194*5097c0c8SAlexandre Mergnat break; 195*5097c0c8SAlexandre Mergnat case SND_SOC_DAIFMT_CBS_CFS: 196*5097c0c8SAlexandre Mergnat pcm_priv->slave_mode = false; 197*5097c0c8SAlexandre Mergnat break; 198*5097c0c8SAlexandre Mergnat default: 199*5097c0c8SAlexandre Mergnat return -EINVAL; 200*5097c0c8SAlexandre Mergnat } 201*5097c0c8SAlexandre Mergnat 202*5097c0c8SAlexandre Mergnat return 0; 203*5097c0c8SAlexandre Mergnat } 204*5097c0c8SAlexandre Mergnat 205*5097c0c8SAlexandre Mergnat static const struct snd_soc_dai_ops mt8365_dai_pcm1_ops = { 206*5097c0c8SAlexandre Mergnat .startup = mt8365_dai_pcm1_startup, 207*5097c0c8SAlexandre Mergnat .shutdown = mt8365_dai_pcm1_shutdown, 208*5097c0c8SAlexandre Mergnat .prepare = mt8365_dai_pcm1_prepare, 209*5097c0c8SAlexandre Mergnat .set_fmt = mt8365_dai_pcm1_set_fmt, 210*5097c0c8SAlexandre Mergnat }; 211*5097c0c8SAlexandre Mergnat 212*5097c0c8SAlexandre Mergnat static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = { 213*5097c0c8SAlexandre Mergnat { 214*5097c0c8SAlexandre Mergnat .name = "PCM1", 215*5097c0c8SAlexandre Mergnat .id = MT8365_AFE_IO_PCM1, 216*5097c0c8SAlexandre Mergnat .playback = { 217*5097c0c8SAlexandre Mergnat .stream_name = "PCM1 Playback", 218*5097c0c8SAlexandre Mergnat .channels_min = 1, 219*5097c0c8SAlexandre Mergnat .channels_max = 2, 220*5097c0c8SAlexandre Mergnat .rates = SNDRV_PCM_RATE_8000 | 221*5097c0c8SAlexandre Mergnat SNDRV_PCM_RATE_16000 | 222*5097c0c8SAlexandre Mergnat SNDRV_PCM_RATE_32000 | 223*5097c0c8SAlexandre Mergnat SNDRV_PCM_RATE_48000, 224*5097c0c8SAlexandre Mergnat .formats = SNDRV_PCM_FMTBIT_S16_LE | 225*5097c0c8SAlexandre Mergnat SNDRV_PCM_FMTBIT_S32_LE, 226*5097c0c8SAlexandre Mergnat }, 227*5097c0c8SAlexandre Mergnat .capture = { 228*5097c0c8SAlexandre Mergnat .stream_name = "PCM1 Capture", 229*5097c0c8SAlexandre Mergnat .channels_min = 1, 230*5097c0c8SAlexandre Mergnat .channels_max = 2, 231*5097c0c8SAlexandre Mergnat .rates = SNDRV_PCM_RATE_8000 | 232*5097c0c8SAlexandre Mergnat SNDRV_PCM_RATE_16000 | 233*5097c0c8SAlexandre Mergnat SNDRV_PCM_RATE_32000 | 234*5097c0c8SAlexandre Mergnat SNDRV_PCM_RATE_48000, 235*5097c0c8SAlexandre Mergnat .formats = SNDRV_PCM_FMTBIT_S16_LE | 236*5097c0c8SAlexandre Mergnat SNDRV_PCM_FMTBIT_S32_LE, 237*5097c0c8SAlexandre Mergnat }, 238*5097c0c8SAlexandre Mergnat .ops = &mt8365_dai_pcm1_ops, 239*5097c0c8SAlexandre Mergnat .symmetric_rate = 1, 240*5097c0c8SAlexandre Mergnat .symmetric_sample_bits = 1, 241*5097c0c8SAlexandre Mergnat } 242*5097c0c8SAlexandre Mergnat }; 243*5097c0c8SAlexandre Mergnat 244*5097c0c8SAlexandre Mergnat /* DAI widget */ 245*5097c0c8SAlexandre Mergnat 246*5097c0c8SAlexandre Mergnat static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = { 247*5097c0c8SAlexandre Mergnat SND_SOC_DAPM_OUTPUT("PCM1 Out"), 248*5097c0c8SAlexandre Mergnat SND_SOC_DAPM_INPUT("PCM1 In"), 249*5097c0c8SAlexandre Mergnat }; 250*5097c0c8SAlexandre Mergnat 251*5097c0c8SAlexandre Mergnat /* DAI route */ 252*5097c0c8SAlexandre Mergnat 253*5097c0c8SAlexandre Mergnat static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = { 254*5097c0c8SAlexandre Mergnat {"PCM1 Playback", NULL, "O07"}, 255*5097c0c8SAlexandre Mergnat {"PCM1 Playback", NULL, "O08"}, 256*5097c0c8SAlexandre Mergnat {"PCM1 Out", NULL, "PCM1 Playback"}, 257*5097c0c8SAlexandre Mergnat 258*5097c0c8SAlexandre Mergnat {"I09", NULL, "PCM1 Capture"}, 259*5097c0c8SAlexandre Mergnat {"I22", NULL, "PCM1 Capture"}, 260*5097c0c8SAlexandre Mergnat {"PCM1 Capture", NULL, "PCM1 In"}, 261*5097c0c8SAlexandre Mergnat }; 262*5097c0c8SAlexandre Mergnat 263*5097c0c8SAlexandre Mergnat static int init_pcmif_priv_data(struct mtk_base_afe *afe) 264*5097c0c8SAlexandre Mergnat { 265*5097c0c8SAlexandre Mergnat struct mt8365_afe_private *afe_priv = afe->platform_priv; 266*5097c0c8SAlexandre Mergnat struct mt8365_pcm_intf_data *pcmif_priv; 267*5097c0c8SAlexandre Mergnat 268*5097c0c8SAlexandre Mergnat pcmif_priv = devm_kzalloc(afe->dev, sizeof(struct mt8365_pcm_intf_data), 269*5097c0c8SAlexandre Mergnat GFP_KERNEL); 270*5097c0c8SAlexandre Mergnat if (!pcmif_priv) 271*5097c0c8SAlexandre Mergnat return -ENOMEM; 272*5097c0c8SAlexandre Mergnat 273*5097c0c8SAlexandre Mergnat afe_priv->dai_priv[MT8365_AFE_IO_PCM1] = pcmif_priv; 274*5097c0c8SAlexandre Mergnat return 0; 275*5097c0c8SAlexandre Mergnat } 276*5097c0c8SAlexandre Mergnat 277*5097c0c8SAlexandre Mergnat int mt8365_dai_pcm_register(struct mtk_base_afe *afe) 278*5097c0c8SAlexandre Mergnat { 279*5097c0c8SAlexandre Mergnat struct mtk_base_afe_dai *dai; 280*5097c0c8SAlexandre Mergnat 281*5097c0c8SAlexandre Mergnat dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); 282*5097c0c8SAlexandre Mergnat if (!dai) 283*5097c0c8SAlexandre Mergnat return -ENOMEM; 284*5097c0c8SAlexandre Mergnat 285*5097c0c8SAlexandre Mergnat list_add(&dai->list, &afe->sub_dais); 286*5097c0c8SAlexandre Mergnat dai->dai_drivers = mtk_dai_pcm_driver; 287*5097c0c8SAlexandre Mergnat dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver); 288*5097c0c8SAlexandre Mergnat dai->dapm_widgets = mtk_dai_pcm_widgets; 289*5097c0c8SAlexandre Mergnat dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets); 290*5097c0c8SAlexandre Mergnat dai->dapm_routes = mtk_dai_pcm_routes; 291*5097c0c8SAlexandre Mergnat dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes); 292*5097c0c8SAlexandre Mergnat return init_pcmif_priv_data(afe); 293*5097c0c8SAlexandre Mergnat } 294