Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // mt8186-mt6366-da7219-max98357.c
0004 //  --  MT8186-MT6366-DA7219-MAX98357 ALSA SoC machine driver
0005 //
0006 // Copyright (c) 2022 MediaTek Inc.
0007 // Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
0008 //
0009 
0010 #include <linux/input.h>
0011 #include <linux/module.h>
0012 #include <linux/of_device.h>
0013 #include <linux/pm_runtime.h>
0014 #include <sound/pcm_params.h>
0015 #include <sound/soc.h>
0016 
0017 #include "../../codecs/da7219-aad.h"
0018 #include "../../codecs/da7219.h"
0019 #include "../../codecs/mt6358.h"
0020 #include "../common/mtk-afe-platform-driver.h"
0021 #include "mt8186-afe-common.h"
0022 #include "mt8186-afe-clk.h"
0023 #include "mt8186-afe-gpio.h"
0024 #include "mt8186-mt6366-common.h"
0025 
0026 #define DA7219_CODEC_DAI "da7219-hifi"
0027 #define DA7219_DEV_NAME "da7219.5-001a"
0028 
0029 struct mt8186_mt6366_da7219_max98357_priv {
0030     struct snd_soc_jack headset_jack, hdmi_jack;
0031 };
0032 
0033 static struct snd_soc_codec_conf mt8186_mt6366_da7219_max98357_codec_conf[] = {
0034     {
0035         .dlc = COMP_CODEC_CONF("mt6358-sound"),
0036         .name_prefix = "Mt6366",
0037     },
0038     {
0039         .dlc = COMP_CODEC_CONF("bt-sco"),
0040         .name_prefix = "Mt8186 bt",
0041     },
0042     {
0043         .dlc = COMP_CODEC_CONF("hdmi-audio-codec"),
0044         .name_prefix = "Mt8186 hdmi",
0045     },
0046 };
0047 
0048 static int mt8186_da7219_init(struct snd_soc_pcm_runtime *rtd)
0049 {
0050     struct mt8186_mt6366_da7219_max98357_priv *priv =
0051         snd_soc_card_get_drvdata(rtd->card);
0052     struct snd_soc_jack *jack = &priv->headset_jack;
0053     struct snd_soc_component *cmpnt_codec =
0054         asoc_rtd_to_codec(rtd, 0)->component;
0055     int ret;
0056 
0057     /* Enable Headset and 4 Buttons Jack detection */
0058     ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
0059                     SND_JACK_HEADSET | SND_JACK_BTN_0 |
0060                     SND_JACK_BTN_1 | SND_JACK_BTN_2 |
0061                     SND_JACK_BTN_3 | SND_JACK_LINEOUT,
0062                     jack);
0063     if (ret) {
0064         dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
0065         return ret;
0066     }
0067 
0068     snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
0069     snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
0070     snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
0071     snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
0072 
0073     da7219_aad_jack_det(cmpnt_codec, &priv->headset_jack);
0074 
0075     return 0;
0076 }
0077 
0078 static int mt8186_da7219_i2s_hw_params(struct snd_pcm_substream *substream,
0079                        struct snd_pcm_hw_params *params)
0080 {
0081     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0082     struct snd_soc_dai *codec_dai;
0083     unsigned int rate = params_rate(params);
0084     unsigned int mclk_fs_ratio = 256;
0085     unsigned int mclk_fs = rate * mclk_fs_ratio;
0086     unsigned int freq;
0087     int ret, j;
0088 
0089     ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0,
0090                      mclk_fs, SND_SOC_CLOCK_OUT);
0091     if (ret < 0) {
0092         dev_err(rtd->dev, "failed to set cpu dai sysclk: %d\n", ret);
0093         return ret;
0094     }
0095 
0096     for_each_rtd_codec_dais(rtd, j, codec_dai) {
0097         if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) {
0098             ret = snd_soc_dai_set_sysclk(codec_dai,
0099                              DA7219_CLKSRC_MCLK,
0100                              mclk_fs,
0101                              SND_SOC_CLOCK_IN);
0102             if (ret < 0) {
0103                 dev_err(rtd->dev, "failed to set sysclk: %d\n",
0104                     ret);
0105                 return ret;
0106             }
0107 
0108             if ((rate % 8000) == 0)
0109                 freq = DA7219_PLL_FREQ_OUT_98304;
0110             else
0111                 freq = DA7219_PLL_FREQ_OUT_90316;
0112 
0113             ret = snd_soc_dai_set_pll(codec_dai, 0,
0114                           DA7219_SYSCLK_PLL_SRM,
0115                           0, freq);
0116             if (ret) {
0117                 dev_err(rtd->dev, "failed to start PLL: %d\n",
0118                     ret);
0119                 return ret;
0120             }
0121         }
0122     }
0123 
0124     return 0;
0125 }
0126 
0127 static int mt8186_da7219_i2s_hw_free(struct snd_pcm_substream *substream)
0128 {
0129     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0130     struct snd_soc_dai *codec_dai;
0131     int ret = 0, j;
0132 
0133     for_each_rtd_codec_dais(rtd, j, codec_dai) {
0134         if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) {
0135             ret = snd_soc_dai_set_pll(codec_dai,
0136                           0, DA7219_SYSCLK_MCLK, 0, 0);
0137             if (ret < 0) {
0138                 dev_err(rtd->dev, "failed to stop PLL: %d\n",
0139                     ret);
0140                 return ret;
0141             }
0142         }
0143     }
0144 
0145     return 0;
0146 }
0147 
0148 static const struct snd_soc_ops mt8186_da7219_i2s_ops = {
0149     .hw_params = mt8186_da7219_i2s_hw_params,
0150     .hw_free = mt8186_da7219_i2s_hw_free,
0151 };
0152 
0153 static int mt8186_mt6366_da7219_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd)
0154 {
0155     struct snd_soc_component *cmpnt_codec =
0156         asoc_rtd_to_codec(rtd, 0)->component;
0157     struct mt8186_mt6366_da7219_max98357_priv *priv =
0158         snd_soc_card_get_drvdata(rtd->card);
0159     int ret;
0160 
0161     ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, &priv->hdmi_jack);
0162     if (ret) {
0163         dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret);
0164         return ret;
0165     }
0166 
0167     return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL);
0168 }
0169 
0170 static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
0171                   struct snd_pcm_hw_params *params,
0172                   snd_pcm_format_t fmt)
0173 {
0174     struct snd_interval *channels = hw_param_interval(params,
0175         SNDRV_PCM_HW_PARAM_CHANNELS);
0176 
0177     dev_dbg(rtd->dev, "%s(), fix format to %d\n", __func__, fmt);
0178 
0179     /* fix BE i2s channel to 2 channel */
0180     channels->min = 2;
0181     channels->max = 2;
0182 
0183     /* clean param mask first */
0184     snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
0185                  0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
0186 
0187     params_set_format(params, fmt);
0188 
0189     return 0;
0190 }
0191 
0192 static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
0193                       struct snd_pcm_hw_params *params)
0194 {
0195     return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S32_LE);
0196 }
0197 
0198 static int mt8186_anx7625_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
0199                           struct snd_pcm_hw_params *params)
0200 {
0201     return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S24_LE);
0202 }
0203 
0204 static int mt8186_mt6366_da7219_max98357_playback_startup(struct snd_pcm_substream *substream)
0205 {
0206     static const unsigned int rates[] = {
0207         48000
0208     };
0209     static const unsigned int channels[] = {
0210         2
0211     };
0212     static const struct snd_pcm_hw_constraint_list constraints_rates = {
0213         .count = ARRAY_SIZE(rates),
0214         .list  = rates,
0215         .mask = 0,
0216     };
0217     static const struct snd_pcm_hw_constraint_list constraints_channels = {
0218         .count = ARRAY_SIZE(channels),
0219         .list  = channels,
0220         .mask = 0,
0221     };
0222 
0223     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0224     struct snd_pcm_runtime *runtime = substream->runtime;
0225     int ret;
0226 
0227     ret = snd_pcm_hw_constraint_list(runtime, 0,
0228                      SNDRV_PCM_HW_PARAM_RATE,
0229                      &constraints_rates);
0230     if (ret < 0) {
0231         dev_err(rtd->dev, "hw_constraint_list rate failed\n");
0232         return ret;
0233     }
0234 
0235     ret = snd_pcm_hw_constraint_list(runtime, 0,
0236                      SNDRV_PCM_HW_PARAM_CHANNELS,
0237                      &constraints_channels);
0238     if (ret < 0) {
0239         dev_err(rtd->dev, "hw_constraint_list channel failed\n");
0240         return ret;
0241     }
0242 
0243     return 0;
0244 }
0245 
0246 static const struct snd_soc_ops mt8186_mt6366_da7219_max98357_playback_ops = {
0247     .startup = mt8186_mt6366_da7219_max98357_playback_startup,
0248 };
0249 
0250 static int mt8186_mt6366_da7219_max98357_capture_startup(struct snd_pcm_substream *substream)
0251 {
0252     static const unsigned int rates[] = {
0253         48000
0254     };
0255     static const unsigned int channels[] = {
0256         1, 2
0257     };
0258     static const struct snd_pcm_hw_constraint_list constraints_rates = {
0259         .count = ARRAY_SIZE(rates),
0260         .list  = rates,
0261         .mask = 0,
0262     };
0263     static const struct snd_pcm_hw_constraint_list constraints_channels = {
0264         .count = ARRAY_SIZE(channels),
0265         .list  = channels,
0266         .mask = 0,
0267     };
0268 
0269     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0270     struct snd_pcm_runtime *runtime = substream->runtime;
0271     int ret;
0272 
0273     ret = snd_pcm_hw_constraint_list(runtime, 0,
0274                      SNDRV_PCM_HW_PARAM_RATE,
0275                      &constraints_rates);
0276     if (ret < 0) {
0277         dev_err(rtd->dev, "hw_constraint_list rate failed\n");
0278         return ret;
0279     }
0280 
0281     ret = snd_pcm_hw_constraint_list(runtime, 0,
0282                      SNDRV_PCM_HW_PARAM_CHANNELS,
0283                      &constraints_channels);
0284     if (ret < 0) {
0285         dev_err(rtd->dev, "hw_constraint_list channel failed\n");
0286         return ret;
0287     }
0288 
0289     return 0;
0290 }
0291 
0292 static const struct snd_soc_ops mt8186_mt6366_da7219_max98357_capture_ops = {
0293     .startup = mt8186_mt6366_da7219_max98357_capture_startup,
0294 };
0295 
0296 /* FE */
0297 SND_SOC_DAILINK_DEFS(playback1,
0298              DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
0299              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0300              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0301 
0302 SND_SOC_DAILINK_DEFS(playback12,
0303              DAILINK_COMP_ARRAY(COMP_CPU("DL12")),
0304              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0305              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0306 
0307 SND_SOC_DAILINK_DEFS(playback2,
0308              DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
0309              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0310              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0311 
0312 SND_SOC_DAILINK_DEFS(playback3,
0313              DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
0314              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0315              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0316 
0317 SND_SOC_DAILINK_DEFS(playback4,
0318              DAILINK_COMP_ARRAY(COMP_CPU("DL4")),
0319              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0320              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0321 
0322 SND_SOC_DAILINK_DEFS(playback5,
0323              DAILINK_COMP_ARRAY(COMP_CPU("DL5")),
0324              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0325              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0326 
0327 SND_SOC_DAILINK_DEFS(playback6,
0328              DAILINK_COMP_ARRAY(COMP_CPU("DL6")),
0329              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0330              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0331 
0332 SND_SOC_DAILINK_DEFS(playback7,
0333              DAILINK_COMP_ARRAY(COMP_CPU("DL7")),
0334              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0335              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0336 
0337 SND_SOC_DAILINK_DEFS(playback8,
0338              DAILINK_COMP_ARRAY(COMP_CPU("DL8")),
0339              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0340              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0341 
0342 SND_SOC_DAILINK_DEFS(capture1,
0343              DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
0344              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0345              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0346 
0347 SND_SOC_DAILINK_DEFS(capture2,
0348              DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
0349              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0350              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0351 
0352 SND_SOC_DAILINK_DEFS(capture3,
0353              DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
0354              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0355              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0356 
0357 SND_SOC_DAILINK_DEFS(capture4,
0358              DAILINK_COMP_ARRAY(COMP_CPU("UL4")),
0359              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0360              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0361 
0362 SND_SOC_DAILINK_DEFS(capture5,
0363              DAILINK_COMP_ARRAY(COMP_CPU("UL5")),
0364              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0365              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0366 
0367 SND_SOC_DAILINK_DEFS(capture6,
0368              DAILINK_COMP_ARRAY(COMP_CPU("UL6")),
0369              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0370              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0371 
0372 SND_SOC_DAILINK_DEFS(capture7,
0373              DAILINK_COMP_ARRAY(COMP_CPU("UL7")),
0374              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0375              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0376 
0377 /* hostless */
0378 SND_SOC_DAILINK_DEFS(hostless_lpbk,
0379              DAILINK_COMP_ARRAY(COMP_CPU("Hostless LPBK DAI")),
0380              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0381              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0382 SND_SOC_DAILINK_DEFS(hostless_fm,
0383              DAILINK_COMP_ARRAY(COMP_CPU("Hostless FM DAI")),
0384              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0385              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0386 SND_SOC_DAILINK_DEFS(hostless_src1,
0387              DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_1_DAI")),
0388              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0389              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0390 SND_SOC_DAILINK_DEFS(hostless_src_bargein,
0391              DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_Bargein_DAI")),
0392              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0393              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0394 
0395 /* BE */
0396 SND_SOC_DAILINK_DEFS(adda,
0397              DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
0398              DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound",
0399                            "mt6358-snd-codec-aif1"),
0400                     COMP_CODEC("dmic-codec",
0401                            "dmic-hifi")),
0402              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0403 SND_SOC_DAILINK_DEFS(i2s0,
0404              DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),
0405              DAILINK_COMP_ARRAY(COMP_EMPTY()),
0406              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0407 SND_SOC_DAILINK_DEFS(i2s1,
0408              DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
0409              DAILINK_COMP_ARRAY(COMP_EMPTY()),
0410              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0411 SND_SOC_DAILINK_DEFS(i2s2,
0412              DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),
0413              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0414              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0415 SND_SOC_DAILINK_DEFS(i2s3,
0416              DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
0417              DAILINK_COMP_ARRAY(COMP_EMPTY()),
0418              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0419 SND_SOC_DAILINK_DEFS(hw_gain1,
0420              DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 1")),
0421              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0422              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0423 SND_SOC_DAILINK_DEFS(hw_gain2,
0424              DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 2")),
0425              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0426              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0427 SND_SOC_DAILINK_DEFS(hw_src1,
0428              DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_1")),
0429              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0430              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0431 SND_SOC_DAILINK_DEFS(hw_src2,
0432              DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_2")),
0433              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0434              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0435 SND_SOC_DAILINK_DEFS(connsys_i2s,
0436              DAILINK_COMP_ARRAY(COMP_CPU("CONNSYS_I2S")),
0437              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0438              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0439 SND_SOC_DAILINK_DEFS(pcm1,
0440              DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")),
0441              DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm-wb")),
0442              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0443 SND_SOC_DAILINK_DEFS(tdm_in,
0444              DAILINK_COMP_ARRAY(COMP_CPU("TDM IN")),
0445              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0446              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0447 
0448 /* hostless */
0449 SND_SOC_DAILINK_DEFS(hostless_ul1,
0450              DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL1 DAI")),
0451              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0452              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0453 SND_SOC_DAILINK_DEFS(hostless_ul2,
0454              DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL2 DAI")),
0455              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0456              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0457 SND_SOC_DAILINK_DEFS(hostless_ul3,
0458              DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL3 DAI")),
0459              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0460              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0461 SND_SOC_DAILINK_DEFS(hostless_ul5,
0462              DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL5 DAI")),
0463              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0464              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0465 SND_SOC_DAILINK_DEFS(hostless_ul6,
0466              DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL6 DAI")),
0467              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0468              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0469 SND_SOC_DAILINK_DEFS(hostless_hw_gain_aaudio,
0470              DAILINK_COMP_ARRAY(COMP_CPU("Hostless HW Gain AAudio DAI")),
0471              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0472              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0473 SND_SOC_DAILINK_DEFS(hostless_src_aaudio,
0474              DAILINK_COMP_ARRAY(COMP_CPU("Hostless SRC AAudio DAI")),
0475              DAILINK_COMP_ARRAY(COMP_DUMMY()),
0476              DAILINK_COMP_ARRAY(COMP_EMPTY()));
0477 static struct snd_soc_dai_link mt8186_mt6366_da7219_max98357_dai_links[] = {
0478     /* Front End DAI links */
0479     {
0480         .name = "Playback_1",
0481         .stream_name = "Playback_1",
0482         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0483                 SND_SOC_DPCM_TRIGGER_PRE},
0484         .dynamic = 1,
0485         .dpcm_playback = 1,
0486         .dpcm_merged_format = 1,
0487         .dpcm_merged_chan = 1,
0488         .dpcm_merged_rate = 1,
0489         .ops = &mt8186_mt6366_da7219_max98357_playback_ops,
0490         SND_SOC_DAILINK_REG(playback1),
0491     },
0492     {
0493         .name = "Playback_12",
0494         .stream_name = "Playback_12",
0495         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0496                 SND_SOC_DPCM_TRIGGER_PRE},
0497         .dynamic = 1,
0498         .dpcm_playback = 1,
0499         SND_SOC_DAILINK_REG(playback12),
0500     },
0501     {
0502         .name = "Playback_2",
0503         .stream_name = "Playback_2",
0504         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0505                 SND_SOC_DPCM_TRIGGER_PRE},
0506         .dynamic = 1,
0507         .dpcm_playback = 1,
0508         .dpcm_merged_format = 1,
0509         .dpcm_merged_chan = 1,
0510         .dpcm_merged_rate = 1,
0511         SND_SOC_DAILINK_REG(playback2),
0512     },
0513     {
0514         .name = "Playback_3",
0515         .stream_name = "Playback_3",
0516         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0517                 SND_SOC_DPCM_TRIGGER_PRE},
0518         .dynamic = 1,
0519         .dpcm_playback = 1,
0520         .dpcm_merged_format = 1,
0521         .dpcm_merged_chan = 1,
0522         .dpcm_merged_rate = 1,
0523         .ops = &mt8186_mt6366_da7219_max98357_playback_ops,
0524         SND_SOC_DAILINK_REG(playback3),
0525     },
0526     {
0527         .name = "Playback_4",
0528         .stream_name = "Playback_4",
0529         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0530                 SND_SOC_DPCM_TRIGGER_PRE},
0531         .dynamic = 1,
0532         .dpcm_playback = 1,
0533         SND_SOC_DAILINK_REG(playback4),
0534     },
0535     {
0536         .name = "Playback_5",
0537         .stream_name = "Playback_5",
0538         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0539                 SND_SOC_DPCM_TRIGGER_PRE},
0540         .dynamic = 1,
0541         .dpcm_playback = 1,
0542         SND_SOC_DAILINK_REG(playback5),
0543     },
0544     {
0545         .name = "Playback_6",
0546         .stream_name = "Playback_6",
0547         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0548                 SND_SOC_DPCM_TRIGGER_PRE},
0549         .dynamic = 1,
0550         .dpcm_playback = 1,
0551         SND_SOC_DAILINK_REG(playback6),
0552     },
0553     {
0554         .name = "Playback_7",
0555         .stream_name = "Playback_7",
0556         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0557                 SND_SOC_DPCM_TRIGGER_PRE},
0558         .dynamic = 1,
0559         .dpcm_playback = 1,
0560         SND_SOC_DAILINK_REG(playback7),
0561     },
0562     {
0563         .name = "Playback_8",
0564         .stream_name = "Playback_8",
0565         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0566                 SND_SOC_DPCM_TRIGGER_PRE},
0567         .dynamic = 1,
0568         .dpcm_playback = 1,
0569         SND_SOC_DAILINK_REG(playback8),
0570     },
0571     {
0572         .name = "Capture_1",
0573         .stream_name = "Capture_1",
0574         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0575                 SND_SOC_DPCM_TRIGGER_PRE},
0576         .dynamic = 1,
0577         .dpcm_capture = 1,
0578         SND_SOC_DAILINK_REG(capture1),
0579     },
0580     {
0581         .name = "Capture_2",
0582         .stream_name = "Capture_2",
0583         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0584                 SND_SOC_DPCM_TRIGGER_PRE},
0585         .dynamic = 1,
0586         .dpcm_capture = 1,
0587         .dpcm_merged_format = 1,
0588         .dpcm_merged_chan = 1,
0589         .dpcm_merged_rate = 1,
0590         .ops = &mt8186_mt6366_da7219_max98357_capture_ops,
0591         SND_SOC_DAILINK_REG(capture2),
0592     },
0593     {
0594         .name = "Capture_3",
0595         .stream_name = "Capture_3",
0596         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0597                 SND_SOC_DPCM_TRIGGER_PRE},
0598         .dynamic = 1,
0599         .dpcm_capture = 1,
0600         SND_SOC_DAILINK_REG(capture3),
0601     },
0602     {
0603         .name = "Capture_4",
0604         .stream_name = "Capture_4",
0605         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0606                 SND_SOC_DPCM_TRIGGER_PRE},
0607         .dynamic = 1,
0608         .dpcm_capture = 1,
0609         .dpcm_merged_format = 1,
0610         .dpcm_merged_chan = 1,
0611         .dpcm_merged_rate = 1,
0612         .ops = &mt8186_mt6366_da7219_max98357_capture_ops,
0613         SND_SOC_DAILINK_REG(capture4),
0614     },
0615     {
0616         .name = "Capture_5",
0617         .stream_name = "Capture_5",
0618         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0619                 SND_SOC_DPCM_TRIGGER_PRE},
0620         .dynamic = 1,
0621         .dpcm_capture = 1,
0622         SND_SOC_DAILINK_REG(capture5),
0623     },
0624     {
0625         .name = "Capture_6",
0626         .stream_name = "Capture_6",
0627         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0628                 SND_SOC_DPCM_TRIGGER_PRE},
0629         .dynamic = 1,
0630         .dpcm_capture = 1,
0631         .dpcm_merged_format = 1,
0632         .dpcm_merged_chan = 1,
0633         .dpcm_merged_rate = 1,
0634         SND_SOC_DAILINK_REG(capture6),
0635     },
0636     {
0637         .name = "Capture_7",
0638         .stream_name = "Capture_7",
0639         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0640                 SND_SOC_DPCM_TRIGGER_PRE},
0641         .dynamic = 1,
0642         .dpcm_capture = 1,
0643         SND_SOC_DAILINK_REG(capture7),
0644     },
0645     {
0646         .name = "Hostless_LPBK",
0647         .stream_name = "Hostless_LPBK",
0648         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0649                 SND_SOC_DPCM_TRIGGER_PRE},
0650         .dynamic = 1,
0651         .dpcm_playback = 1,
0652         .dpcm_capture = 1,
0653         .ignore_suspend = 1,
0654         SND_SOC_DAILINK_REG(hostless_lpbk),
0655     },
0656     {
0657         .name = "Hostless_FM",
0658         .stream_name = "Hostless_FM",
0659         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0660                 SND_SOC_DPCM_TRIGGER_PRE},
0661         .dynamic = 1,
0662         .dpcm_playback = 1,
0663         .dpcm_capture = 1,
0664         .ignore_suspend = 1,
0665         SND_SOC_DAILINK_REG(hostless_fm),
0666     },
0667     {
0668         .name = "Hostless_SRC_1",
0669         .stream_name = "Hostless_SRC_1",
0670         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0671                 SND_SOC_DPCM_TRIGGER_PRE},
0672         .dynamic = 1,
0673         .dpcm_playback = 1,
0674         .dpcm_capture = 1,
0675         .ignore_suspend = 1,
0676         SND_SOC_DAILINK_REG(hostless_src1),
0677     },
0678     {
0679         .name = "Hostless_SRC_Bargein",
0680         .stream_name = "Hostless_SRC_Bargein",
0681         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0682                 SND_SOC_DPCM_TRIGGER_PRE},
0683         .dynamic = 1,
0684         .dpcm_playback = 1,
0685         .dpcm_capture = 1,
0686         .ignore_suspend = 1,
0687         SND_SOC_DAILINK_REG(hostless_src_bargein),
0688     },
0689     {
0690         .name = "Hostless_HW_Gain_AAudio",
0691         .stream_name = "Hostless_HW_Gain_AAudio",
0692         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0693                 SND_SOC_DPCM_TRIGGER_PRE},
0694         .dynamic = 1,
0695         .dpcm_capture = 1,
0696         .ignore_suspend = 1,
0697         SND_SOC_DAILINK_REG(hostless_hw_gain_aaudio),
0698     },
0699     {
0700         .name = "Hostless_SRC_AAudio",
0701         .stream_name = "Hostless_SRC_AAudio",
0702         .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
0703                 SND_SOC_DPCM_TRIGGER_PRE},
0704         .dynamic = 1,
0705         .dpcm_playback = 1,
0706         .dpcm_capture = 1,
0707         .ignore_suspend = 1,
0708         SND_SOC_DAILINK_REG(hostless_src_aaudio),
0709     },
0710     /* Back End DAI links */
0711     {
0712         .name = "Primary Codec",
0713         .no_pcm = 1,
0714         .dpcm_playback = 1,
0715         .dpcm_capture = 1,
0716         .ignore_suspend = 1,
0717         .init = mt8186_mt6366_init,
0718         SND_SOC_DAILINK_REG(adda),
0719     },
0720     {
0721         .name = "I2S3",
0722         .no_pcm = 1,
0723         .dai_fmt = SND_SOC_DAIFMT_I2S |
0724                SND_SOC_DAIFMT_IB_IF |
0725                SND_SOC_DAIFMT_CBM_CFM,
0726         .dpcm_playback = 1,
0727         .ignore_suspend = 1,
0728         .init = mt8186_mt6366_da7219_max98357_hdmi_init,
0729         .be_hw_params_fixup = mt8186_anx7625_i2s_hw_params_fixup,
0730         SND_SOC_DAILINK_REG(i2s3),
0731     },
0732     {
0733         .name = "I2S0",
0734         .no_pcm = 1,
0735         .dpcm_capture = 1,
0736         .ignore_suspend = 1,
0737         .be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
0738         .ops = &mt8186_da7219_i2s_ops,
0739         SND_SOC_DAILINK_REG(i2s0),
0740     },
0741     {
0742         .name = "I2S1",
0743         .no_pcm = 1,
0744         .dpcm_playback = 1,
0745         .ignore_suspend = 1,
0746         .be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
0747         .init = mt8186_da7219_init,
0748         .ops = &mt8186_da7219_i2s_ops,
0749         SND_SOC_DAILINK_REG(i2s1),
0750     },
0751     {
0752         .name = "I2S2",
0753         .no_pcm = 1,
0754         .dpcm_capture = 1,
0755         .ignore_suspend = 1,
0756         .be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
0757         SND_SOC_DAILINK_REG(i2s2),
0758     },
0759     {
0760         .name = "HW Gain 1",
0761         .no_pcm = 1,
0762         .dpcm_playback = 1,
0763         .dpcm_capture = 1,
0764         .ignore_suspend = 1,
0765         SND_SOC_DAILINK_REG(hw_gain1),
0766     },
0767     {
0768         .name = "HW Gain 2",
0769         .no_pcm = 1,
0770         .dpcm_playback = 1,
0771         .dpcm_capture = 1,
0772         .ignore_suspend = 1,
0773         SND_SOC_DAILINK_REG(hw_gain2),
0774     },
0775     {
0776         .name = "HW_SRC_1",
0777         .no_pcm = 1,
0778         .dpcm_playback = 1,
0779         .dpcm_capture = 1,
0780         .ignore_suspend = 1,
0781         SND_SOC_DAILINK_REG(hw_src1),
0782     },
0783     {
0784         .name = "HW_SRC_2",
0785         .no_pcm = 1,
0786         .dpcm_playback = 1,
0787         .dpcm_capture = 1,
0788         .ignore_suspend = 1,
0789         SND_SOC_DAILINK_REG(hw_src2),
0790     },
0791     {
0792         .name = "CONNSYS_I2S",
0793         .no_pcm = 1,
0794         .dpcm_capture = 1,
0795         .ignore_suspend = 1,
0796         SND_SOC_DAILINK_REG(connsys_i2s),
0797     },
0798     {
0799         .name = "PCM 1",
0800         .dai_fmt = SND_SOC_DAIFMT_I2S |
0801                SND_SOC_DAIFMT_NB_IF,
0802         .no_pcm = 1,
0803         .dpcm_playback = 1,
0804         .dpcm_capture = 1,
0805         .ignore_suspend = 1,
0806         SND_SOC_DAILINK_REG(pcm1),
0807     },
0808     {
0809         .name = "TDM IN",
0810         .no_pcm = 1,
0811         .dpcm_capture = 1,
0812         .ignore_suspend = 1,
0813         SND_SOC_DAILINK_REG(tdm_in),
0814     },
0815     /* dummy BE for ul memif to record from dl memif */
0816     {
0817         .name = "Hostless_UL1",
0818         .no_pcm = 1,
0819         .dpcm_capture = 1,
0820         .ignore_suspend = 1,
0821         SND_SOC_DAILINK_REG(hostless_ul1),
0822     },
0823     {
0824         .name = "Hostless_UL2",
0825         .no_pcm = 1,
0826         .dpcm_capture = 1,
0827         .ignore_suspend = 1,
0828         SND_SOC_DAILINK_REG(hostless_ul2),
0829     },
0830     {
0831         .name = "Hostless_UL3",
0832         .no_pcm = 1,
0833         .dpcm_capture = 1,
0834         .ignore_suspend = 1,
0835         SND_SOC_DAILINK_REG(hostless_ul3),
0836     },
0837     {
0838         .name = "Hostless_UL5",
0839         .no_pcm = 1,
0840         .dpcm_capture = 1,
0841         .ignore_suspend = 1,
0842         SND_SOC_DAILINK_REG(hostless_ul5),
0843     },
0844     {
0845         .name = "Hostless_UL6",
0846         .no_pcm = 1,
0847         .dpcm_capture = 1,
0848         .ignore_suspend = 1,
0849         SND_SOC_DAILINK_REG(hostless_ul6),
0850     },
0851 };
0852 
0853 static const struct snd_soc_dapm_widget
0854 mt8186_mt6366_da7219_max98357_widgets[] = {
0855     SND_SOC_DAPM_SPK("Speakers", NULL),
0856     SND_SOC_DAPM_OUTPUT("HDMI1"),
0857 };
0858 
0859 static const struct snd_soc_dapm_route
0860 mt8186_mt6366_da7219_max98357_routes[] = {
0861     /* SPK */
0862     { "Speakers", NULL, "Speaker"},
0863     /* HDMI */
0864     { "HDMI1", NULL, "TX"},
0865 };
0866 
0867 static const struct snd_kcontrol_new
0868 mt8186_mt6366_da7219_max98357_controls[] = {
0869     SOC_DAPM_PIN_SWITCH("Speakers"),
0870     SOC_DAPM_PIN_SWITCH("HDMI1"),
0871 };
0872 
0873 static struct snd_soc_card mt8186_mt6366_da7219_max98357_soc_card = {
0874     .name = "mt8186_mt6366_da7219_max98357",
0875     .owner = THIS_MODULE,
0876     .dai_link = mt8186_mt6366_da7219_max98357_dai_links,
0877     .num_links = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_dai_links),
0878     .controls = mt8186_mt6366_da7219_max98357_controls,
0879     .num_controls = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_controls),
0880     .dapm_widgets = mt8186_mt6366_da7219_max98357_widgets,
0881     .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_widgets),
0882     .dapm_routes = mt8186_mt6366_da7219_max98357_routes,
0883     .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_routes),
0884     .codec_conf = mt8186_mt6366_da7219_max98357_codec_conf,
0885     .num_configs = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_codec_conf),
0886 };
0887 
0888 static int mt8186_mt6366_da7219_max98357_dev_probe(struct platform_device *pdev)
0889 {
0890     struct snd_soc_card *card;
0891     struct snd_soc_dai_link *dai_link;
0892     struct mt8186_mt6366_da7219_max98357_priv *priv;
0893     struct device_node *platform_node, *headset_codec, *playback_codec;
0894     int ret, i;
0895 
0896     card = (struct snd_soc_card *)device_get_match_data(&pdev->dev);
0897     if (!card)
0898         return -EINVAL;
0899     card->dev = &pdev->dev;
0900 
0901     platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0);
0902     if (!platform_node) {
0903         ret = -EINVAL;
0904         dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n");
0905         return ret;
0906     }
0907 
0908     playback_codec = of_get_child_by_name(pdev->dev.of_node, "playback-codecs");
0909     if (!playback_codec) {
0910         ret = -EINVAL;
0911         dev_err_probe(&pdev->dev, ret, "Property 'speaker-codecs' missing or invalid\n");
0912         goto err_playback_codec;
0913     }
0914 
0915     headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec");
0916     if (!headset_codec) {
0917         ret = -EINVAL;
0918         dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n");
0919         goto err_headset_codec;
0920     }
0921 
0922     for_each_card_prelinks(card, i, dai_link) {
0923         ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3");
0924         if (ret) {
0925             dev_err_probe(&pdev->dev, ret, "%s set speaker_codec fail\n",
0926                       dai_link->name);
0927             goto err_probe;
0928         }
0929 
0930         ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0");
0931         if (ret) {
0932             dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
0933                       dai_link->name);
0934             goto err_probe;
0935         }
0936 
0937         ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1");
0938         if (ret) {
0939             dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
0940                       dai_link->name);
0941             goto err_probe;
0942         }
0943 
0944         if (!dai_link->platforms->name)
0945             dai_link->platforms->of_node = platform_node;
0946     }
0947 
0948     priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0949     if (!priv) {
0950         ret = -ENOMEM;
0951         goto err_probe;
0952     }
0953 
0954     snd_soc_card_set_drvdata(card, priv);
0955 
0956     ret = mt8186_afe_gpio_init(&pdev->dev);
0957     if (ret) {
0958         dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__);
0959         goto err_probe;
0960     }
0961 
0962     ret = devm_snd_soc_register_card(&pdev->dev, card);
0963     if (ret)
0964         dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__);
0965 
0966 err_probe:
0967     of_node_put(headset_codec);
0968 err_headset_codec:
0969     of_node_put(playback_codec);
0970 err_playback_codec:
0971     of_node_put(platform_node);
0972 
0973     return ret;
0974 }
0975 
0976 #if IS_ENABLED(CONFIG_OF)
0977 static const struct of_device_id mt8186_mt6366_da7219_max98357_dt_match[] = {
0978     {   .compatible = "mediatek,mt8186-mt6366-da7219-max98357-sound",
0979         .data = &mt8186_mt6366_da7219_max98357_soc_card,
0980     },
0981     {}
0982 };
0983 #endif
0984 
0985 static struct platform_driver mt8186_mt6366_da7219_max98357_driver = {
0986     .driver = {
0987         .name = "mt8186_mt6366_da7219_max98357",
0988 #if IS_ENABLED(CONFIG_OF)
0989         .of_match_table = mt8186_mt6366_da7219_max98357_dt_match,
0990 #endif
0991         .pm = &snd_soc_pm_ops,
0992     },
0993     .probe = mt8186_mt6366_da7219_max98357_dev_probe,
0994 };
0995 
0996 module_platform_driver(mt8186_mt6366_da7219_max98357_driver);
0997 
0998 /* Module information */
0999 MODULE_DESCRIPTION("MT8186-MT6366-DA7219-MAX98357 ALSA SoC machine driver");
1000 MODULE_AUTHOR("Jiaxin Yu <jiaxin.yu@mediatek.com>");
1001 MODULE_LICENSE("GPL v2");
1002 MODULE_ALIAS("mt8186_mt6366_da7219_max98357 soc card");