162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * MediaTek ALSA SoC Audio DAI PCM I/F Control 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2022 MediaTek Inc. 662306a36Sopenharmony_ci * Author: Bicycle Tsai <bicycle.tsai@mediatek.com> 762306a36Sopenharmony_ci * Trevor Wu <trevor.wu@mediatek.com> 862306a36Sopenharmony_ci * Chun-Chia Chiu <chun-chia.chiu@mediatek.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/bitfield.h> 1262306a36Sopenharmony_ci#include <linux/regmap.h> 1362306a36Sopenharmony_ci#include <sound/pcm_params.h> 1462306a36Sopenharmony_ci#include "mt8188-afe-clk.h" 1562306a36Sopenharmony_ci#include "mt8188-afe-common.h" 1662306a36Sopenharmony_ci#include "mt8188-reg.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cienum { 1962306a36Sopenharmony_ci MTK_DAI_PCM_FMT_I2S, 2062306a36Sopenharmony_ci MTK_DAI_PCM_FMT_EIAJ, 2162306a36Sopenharmony_ci MTK_DAI_PCM_FMT_MODEA, 2262306a36Sopenharmony_ci MTK_DAI_PCM_FMT_MODEB, 2362306a36Sopenharmony_ci}; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cienum { 2662306a36Sopenharmony_ci MTK_DAI_PCM_CLK_A1SYS, 2762306a36Sopenharmony_ci MTK_DAI_PCM_CLK_A2SYS, 2862306a36Sopenharmony_ci MTK_DAI_PCM_CLK_26M_48K, 2962306a36Sopenharmony_ci MTK_DAI_PCM_CLK_26M_441K, 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistruct mtk_dai_pcm_rate { 3362306a36Sopenharmony_ci unsigned int rate; 3462306a36Sopenharmony_ci unsigned int reg_value; 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistruct mtk_dai_pcmif_priv { 3862306a36Sopenharmony_ci unsigned int slave_mode; 3962306a36Sopenharmony_ci unsigned int lrck_inv; 4062306a36Sopenharmony_ci unsigned int bck_inv; 4162306a36Sopenharmony_ci unsigned int format; 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic const struct mtk_dai_pcm_rate mtk_dai_pcm_rates[] = { 4562306a36Sopenharmony_ci { .rate = 8000, .reg_value = 0, }, 4662306a36Sopenharmony_ci { .rate = 16000, .reg_value = 1, }, 4762306a36Sopenharmony_ci { .rate = 32000, .reg_value = 2, }, 4862306a36Sopenharmony_ci { .rate = 48000, .reg_value = 3, }, 4962306a36Sopenharmony_ci { .rate = 11025, .reg_value = 1, }, 5062306a36Sopenharmony_ci { .rate = 22050, .reg_value = 2, }, 5162306a36Sopenharmony_ci { .rate = 44100, .reg_value = 3, }, 5262306a36Sopenharmony_ci}; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic int mtk_dai_pcm_mode(unsigned int rate) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci int i; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mtk_dai_pcm_rates); i++) 5962306a36Sopenharmony_ci if (mtk_dai_pcm_rates[i].rate == rate) 6062306a36Sopenharmony_ci return mtk_dai_pcm_rates[i].reg_value; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci return -EINVAL; 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic const struct snd_kcontrol_new mtk_dai_pcm_o000_mix[] = { 6662306a36Sopenharmony_ci SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN0, 0, 1, 0), 6762306a36Sopenharmony_ci SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN0_2, 6, 1, 0), 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic const struct snd_kcontrol_new mtk_dai_pcm_o001_mix[] = { 7162306a36Sopenharmony_ci SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN1, 1, 1, 0), 7262306a36Sopenharmony_ci SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN1_2, 7, 1, 0), 7362306a36Sopenharmony_ci}; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = { 7662306a36Sopenharmony_ci SND_SOC_DAPM_MIXER("I002", SND_SOC_NOPM, 0, 0, NULL, 0), 7762306a36Sopenharmony_ci SND_SOC_DAPM_MIXER("I003", SND_SOC_NOPM, 0, 0, NULL, 0), 7862306a36Sopenharmony_ci SND_SOC_DAPM_MIXER("O000", SND_SOC_NOPM, 0, 0, 7962306a36Sopenharmony_ci mtk_dai_pcm_o000_mix, 8062306a36Sopenharmony_ci ARRAY_SIZE(mtk_dai_pcm_o000_mix)), 8162306a36Sopenharmony_ci SND_SOC_DAPM_MIXER("O001", SND_SOC_NOPM, 0, 0, 8262306a36Sopenharmony_ci mtk_dai_pcm_o001_mix, 8362306a36Sopenharmony_ci ARRAY_SIZE(mtk_dai_pcm_o001_mix)), 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PCM_1_EN", PCM_INTF_CON1, 0, 0, NULL, 0), 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("PCM1_INPUT"), 8862306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("PCM1_OUTPUT"), 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci SND_SOC_DAPM_CLOCK_SUPPLY("aud_asrc11"), 9162306a36Sopenharmony_ci SND_SOC_DAPM_CLOCK_SUPPLY("aud_asrc12"), 9262306a36Sopenharmony_ci SND_SOC_DAPM_CLOCK_SUPPLY("aud_pcmif"), 9362306a36Sopenharmony_ci}; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = { 9662306a36Sopenharmony_ci {"I002", NULL, "PCM1 Capture"}, 9762306a36Sopenharmony_ci {"I003", NULL, "PCM1 Capture"}, 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci {"O000", "I000 Switch", "I000"}, 10062306a36Sopenharmony_ci {"O001", "I001 Switch", "I001"}, 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci {"O000", "I070 Switch", "I070"}, 10362306a36Sopenharmony_ci {"O001", "I071 Switch", "I071"}, 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci {"PCM1 Playback", NULL, "O000"}, 10662306a36Sopenharmony_ci {"PCM1 Playback", NULL, "O001"}, 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci {"PCM1 Playback", NULL, "PCM_1_EN"}, 10962306a36Sopenharmony_ci {"PCM1 Playback", NULL, "aud_asrc12"}, 11062306a36Sopenharmony_ci {"PCM1 Playback", NULL, "aud_pcmif"}, 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci {"PCM1 Capture", NULL, "PCM_1_EN"}, 11362306a36Sopenharmony_ci {"PCM1 Capture", NULL, "aud_asrc11"}, 11462306a36Sopenharmony_ci {"PCM1 Capture", NULL, "aud_pcmif"}, 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci {"PCM1_OUTPUT", NULL, "PCM1 Playback"}, 11762306a36Sopenharmony_ci {"PCM1 Capture", NULL, "PCM1_INPUT"}, 11862306a36Sopenharmony_ci}; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic int mtk_dai_pcm_configure(struct snd_pcm_substream *substream, 12162306a36Sopenharmony_ci struct snd_soc_dai *dai) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci struct snd_pcm_runtime * const runtime = substream->runtime; 12462306a36Sopenharmony_ci struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 12562306a36Sopenharmony_ci struct mt8188_afe_private *afe_priv = afe->platform_priv; 12662306a36Sopenharmony_ci struct mtk_dai_pcmif_priv *pcmif_priv = NULL; 12762306a36Sopenharmony_ci unsigned int slave_mode; 12862306a36Sopenharmony_ci unsigned int lrck_inv; 12962306a36Sopenharmony_ci unsigned int bck_inv; 13062306a36Sopenharmony_ci unsigned int fmt; 13162306a36Sopenharmony_ci unsigned int bit_width = dai->sample_bits; 13262306a36Sopenharmony_ci unsigned int val = 0; 13362306a36Sopenharmony_ci unsigned int mask = 0; 13462306a36Sopenharmony_ci int fs = 0; 13562306a36Sopenharmony_ci int mode = 0; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci if (dai->id < 0) 13862306a36Sopenharmony_ci return -EINVAL; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci pcmif_priv = afe_priv->dai_priv[dai->id]; 14162306a36Sopenharmony_ci slave_mode = pcmif_priv->slave_mode; 14262306a36Sopenharmony_ci lrck_inv = pcmif_priv->lrck_inv; 14362306a36Sopenharmony_ci bck_inv = pcmif_priv->bck_inv; 14462306a36Sopenharmony_ci fmt = pcmif_priv->format; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* sync freq mode */ 14762306a36Sopenharmony_ci fs = mt8188_afe_fs_timing(runtime->rate); 14862306a36Sopenharmony_ci if (fs < 0) 14962306a36Sopenharmony_ci return -EINVAL; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci val |= FIELD_PREP(PCM_INTF_CON2_SYNC_FREQ_MODE_MASK, fs); 15262306a36Sopenharmony_ci mask |= PCM_INTF_CON2_SYNC_FREQ_MODE_MASK; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci /* clk domain sel */ 15562306a36Sopenharmony_ci if (runtime->rate % 8000) 15662306a36Sopenharmony_ci val |= FIELD_PREP(PCM_INTF_CON2_CLK_DOMAIN_SEL_MASK, 15762306a36Sopenharmony_ci MTK_DAI_PCM_CLK_26M_441K); 15862306a36Sopenharmony_ci else 15962306a36Sopenharmony_ci val |= FIELD_PREP(PCM_INTF_CON2_CLK_DOMAIN_SEL_MASK, 16062306a36Sopenharmony_ci MTK_DAI_PCM_CLK_26M_48K); 16162306a36Sopenharmony_ci mask |= PCM_INTF_CON2_CLK_DOMAIN_SEL_MASK; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci regmap_update_bits(afe->regmap, PCM_INTF_CON2, mask, val); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci val = 0; 16662306a36Sopenharmony_ci mask = 0; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* pcm mode */ 16962306a36Sopenharmony_ci mode = mtk_dai_pcm_mode(runtime->rate); 17062306a36Sopenharmony_ci if (mode < 0) 17162306a36Sopenharmony_ci return -EINVAL; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci val |= FIELD_PREP(PCM_INTF_CON1_PCM_MODE_MASK, mode); 17462306a36Sopenharmony_ci mask |= PCM_INTF_CON1_PCM_MODE_MASK; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci /* pcm format */ 17762306a36Sopenharmony_ci val |= FIELD_PREP(PCM_INTF_CON1_PCM_FMT_MASK, fmt); 17862306a36Sopenharmony_ci mask |= PCM_INTF_CON1_PCM_FMT_MASK; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci /* pcm sync length */ 18162306a36Sopenharmony_ci if (fmt == MTK_DAI_PCM_FMT_MODEA || 18262306a36Sopenharmony_ci fmt == MTK_DAI_PCM_FMT_MODEB) 18362306a36Sopenharmony_ci val |= FIELD_PREP(PCM_INTF_CON1_SYNC_LENGTH_MASK, 1); 18462306a36Sopenharmony_ci else 18562306a36Sopenharmony_ci val |= FIELD_PREP(PCM_INTF_CON1_SYNC_LENGTH_MASK, bit_width); 18662306a36Sopenharmony_ci mask |= PCM_INTF_CON1_SYNC_LENGTH_MASK; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci /* pcm bits, word length */ 18962306a36Sopenharmony_ci if (bit_width > 16) { 19062306a36Sopenharmony_ci val |= PCM_INTF_CON1_PCM_24BIT; 19162306a36Sopenharmony_ci val |= PCM_INTF_CON1_PCM_WLEN_64BCK; 19262306a36Sopenharmony_ci } else { 19362306a36Sopenharmony_ci val |= PCM_INTF_CON1_PCM_16BIT; 19462306a36Sopenharmony_ci val |= PCM_INTF_CON1_PCM_WLEN_32BCK; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci mask |= PCM_INTF_CON1_PCM_BIT_MASK; 19762306a36Sopenharmony_ci mask |= PCM_INTF_CON1_PCM_WLEN_MASK; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci /* master/slave */ 20062306a36Sopenharmony_ci if (!slave_mode) { 20162306a36Sopenharmony_ci val |= PCM_INTF_CON1_PCM_MASTER; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (lrck_inv) 20462306a36Sopenharmony_ci val |= PCM_INTF_CON1_SYNC_OUT_INV; 20562306a36Sopenharmony_ci if (bck_inv) 20662306a36Sopenharmony_ci val |= PCM_INTF_CON1_BCLK_OUT_INV; 20762306a36Sopenharmony_ci mask |= PCM_INTF_CON1_CLK_OUT_INV_MASK; 20862306a36Sopenharmony_ci } else { 20962306a36Sopenharmony_ci val |= PCM_INTF_CON1_PCM_SLAVE; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci if (lrck_inv) 21262306a36Sopenharmony_ci val |= PCM_INTF_CON1_SYNC_IN_INV; 21362306a36Sopenharmony_ci if (bck_inv) 21462306a36Sopenharmony_ci val |= PCM_INTF_CON1_BCLK_IN_INV; 21562306a36Sopenharmony_ci mask |= PCM_INTF_CON1_CLK_IN_INV_MASK; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci // TODO: add asrc setting for slave mode 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci mask |= PCM_INTF_CON1_PCM_M_S_MASK; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci regmap_update_bits(afe->regmap, PCM_INTF_CON1, mask, val); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci return 0; 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci/* dai ops */ 22762306a36Sopenharmony_cistatic int mtk_dai_pcm_prepare(struct snd_pcm_substream *substream, 22862306a36Sopenharmony_ci struct snd_soc_dai *dai) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci if (snd_soc_dai_get_widget_playback(dai)->active || 23162306a36Sopenharmony_ci snd_soc_dai_get_widget_capture(dai)->active) 23262306a36Sopenharmony_ci return 0; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci return mtk_dai_pcm_configure(substream, dai); 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 24062306a36Sopenharmony_ci struct mt8188_afe_private *afe_priv = afe->platform_priv; 24162306a36Sopenharmony_ci struct mtk_dai_pcmif_priv *pcmif_priv = NULL; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci dev_dbg(dai->dev, "%s fmt 0x%x\n", __func__, fmt); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci if (dai->id < 0) 24662306a36Sopenharmony_ci return -EINVAL; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci pcmif_priv = afe_priv->dai_priv[dai->id]; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 25162306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 25262306a36Sopenharmony_ci pcmif_priv->format = MTK_DAI_PCM_FMT_I2S; 25362306a36Sopenharmony_ci break; 25462306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 25562306a36Sopenharmony_ci pcmif_priv->format = MTK_DAI_PCM_FMT_MODEA; 25662306a36Sopenharmony_ci break; 25762306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 25862306a36Sopenharmony_ci pcmif_priv->format = MTK_DAI_PCM_FMT_MODEB; 25962306a36Sopenharmony_ci break; 26062306a36Sopenharmony_ci default: 26162306a36Sopenharmony_ci return -EINVAL; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 26562306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 26662306a36Sopenharmony_ci pcmif_priv->bck_inv = 0; 26762306a36Sopenharmony_ci pcmif_priv->lrck_inv = 0; 26862306a36Sopenharmony_ci break; 26962306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_IF: 27062306a36Sopenharmony_ci pcmif_priv->bck_inv = 0; 27162306a36Sopenharmony_ci pcmif_priv->lrck_inv = 1; 27262306a36Sopenharmony_ci break; 27362306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 27462306a36Sopenharmony_ci pcmif_priv->bck_inv = 1; 27562306a36Sopenharmony_ci pcmif_priv->lrck_inv = 0; 27662306a36Sopenharmony_ci break; 27762306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_IF: 27862306a36Sopenharmony_ci pcmif_priv->bck_inv = 1; 27962306a36Sopenharmony_ci pcmif_priv->lrck_inv = 1; 28062306a36Sopenharmony_ci break; 28162306a36Sopenharmony_ci default: 28262306a36Sopenharmony_ci return -EINVAL; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 28662306a36Sopenharmony_ci case SND_SOC_DAIFMT_BC_FC: 28762306a36Sopenharmony_ci pcmif_priv->slave_mode = 1; 28862306a36Sopenharmony_ci break; 28962306a36Sopenharmony_ci case SND_SOC_DAIFMT_BP_FP: 29062306a36Sopenharmony_ci pcmif_priv->slave_mode = 0; 29162306a36Sopenharmony_ci break; 29262306a36Sopenharmony_ci default: 29362306a36Sopenharmony_ci return -EINVAL; 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci return 0; 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistatic const struct snd_soc_dai_ops mtk_dai_pcm_ops = { 30062306a36Sopenharmony_ci .prepare = mtk_dai_pcm_prepare, 30162306a36Sopenharmony_ci .set_fmt = mtk_dai_pcm_set_fmt, 30262306a36Sopenharmony_ci}; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci/* dai driver */ 30562306a36Sopenharmony_ci#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000) 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ 30862306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE |\ 30962306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S32_LE) 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cistatic struct snd_soc_dai_driver mtk_dai_pcm_driver[] = { 31262306a36Sopenharmony_ci { 31362306a36Sopenharmony_ci .name = "PCM1", 31462306a36Sopenharmony_ci .id = MT8188_AFE_IO_PCM, 31562306a36Sopenharmony_ci .playback = { 31662306a36Sopenharmony_ci .stream_name = "PCM1 Playback", 31762306a36Sopenharmony_ci .channels_min = 1, 31862306a36Sopenharmony_ci .channels_max = 2, 31962306a36Sopenharmony_ci .rates = MTK_PCM_RATES, 32062306a36Sopenharmony_ci .formats = MTK_PCM_FORMATS, 32162306a36Sopenharmony_ci }, 32262306a36Sopenharmony_ci .capture = { 32362306a36Sopenharmony_ci .stream_name = "PCM1 Capture", 32462306a36Sopenharmony_ci .channels_min = 1, 32562306a36Sopenharmony_ci .channels_max = 2, 32662306a36Sopenharmony_ci .rates = MTK_PCM_RATES, 32762306a36Sopenharmony_ci .formats = MTK_PCM_FORMATS, 32862306a36Sopenharmony_ci }, 32962306a36Sopenharmony_ci .ops = &mtk_dai_pcm_ops, 33062306a36Sopenharmony_ci .symmetric_rate = 1, 33162306a36Sopenharmony_ci .symmetric_sample_bits = 1, 33262306a36Sopenharmony_ci }, 33362306a36Sopenharmony_ci}; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cistatic int init_pcmif_priv_data(struct mtk_base_afe *afe) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci struct mt8188_afe_private *afe_priv = afe->platform_priv; 33862306a36Sopenharmony_ci struct mtk_dai_pcmif_priv *pcmif_priv; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci pcmif_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_dai_pcmif_priv), 34162306a36Sopenharmony_ci GFP_KERNEL); 34262306a36Sopenharmony_ci if (!pcmif_priv) 34362306a36Sopenharmony_ci return -ENOMEM; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci afe_priv->dai_priv[MT8188_AFE_IO_PCM] = pcmif_priv; 34662306a36Sopenharmony_ci return 0; 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ciint mt8188_dai_pcm_register(struct mtk_base_afe *afe) 35062306a36Sopenharmony_ci{ 35162306a36Sopenharmony_ci struct mtk_base_afe_dai *dai; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); 35462306a36Sopenharmony_ci if (!dai) 35562306a36Sopenharmony_ci return -ENOMEM; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci list_add(&dai->list, &afe->sub_dais); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci dai->dai_drivers = mtk_dai_pcm_driver; 36062306a36Sopenharmony_ci dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci dai->dapm_widgets = mtk_dai_pcm_widgets; 36362306a36Sopenharmony_ci dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets); 36462306a36Sopenharmony_ci dai->dapm_routes = mtk_dai_pcm_routes; 36562306a36Sopenharmony_ci dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci return init_pcmif_priv_data(afe); 36862306a36Sopenharmony_ci} 369