~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/mediatek/mt8365/mt8365-mt6357.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * MediaTek MT8365 Sound Card driver
  4  *
  5  * Copyright (c) 2024 MediaTek Inc.
  6  * Authors: Nicolas Belin <nbelin@baylibre.com>
  7  */
  8 
  9 #include <linux/module.h>
 10 #include <linux/of_gpio.h>
 11 #include <sound/soc.h>
 12 #include <sound/pcm_params.h>
 13 #include "mt8365-afe-common.h"
 14 #include <linux/pinctrl/consumer.h>
 15 #include "../common/mtk-soc-card.h"
 16 #include "../common/mtk-soundcard-driver.h"
 17 
 18 enum pinctrl_pin_state {
 19         PIN_STATE_DEFAULT,
 20         PIN_STATE_DMIC,
 21         PIN_STATE_MISO_OFF,
 22         PIN_STATE_MISO_ON,
 23         PIN_STATE_MOSI_OFF,
 24         PIN_STATE_MOSI_ON,
 25         PIN_STATE_MAX
 26 };
 27 
 28 static const char * const mt8365_mt6357_pin_str[PIN_STATE_MAX] = {
 29         "default",
 30         "dmic",
 31         "miso_off",
 32         "miso_on",
 33         "mosi_off",
 34         "mosi_on",
 35 };
 36 
 37 struct mt8365_mt6357_priv {
 38         struct pinctrl *pinctrl;
 39         struct pinctrl_state *pin_states[PIN_STATE_MAX];
 40 };
 41 
 42 enum {
 43         /* FE */
 44         DAI_LINK_DL1_PLAYBACK = 0,
 45         DAI_LINK_DL2_PLAYBACK,
 46         DAI_LINK_AWB_CAPTURE,
 47         DAI_LINK_VUL_CAPTURE,
 48         /* BE */
 49         DAI_LINK_2ND_I2S_INTF,
 50         DAI_LINK_DMIC,
 51         DAI_LINK_INT_ADDA,
 52         DAI_LINK_NUM
 53 };
 54 
 55 static const struct snd_soc_dapm_widget mt8365_mt6357_widgets[] = {
 56         SND_SOC_DAPM_OUTPUT("HDMI Out"),
 57 };
 58 
 59 static const struct snd_soc_dapm_route mt8365_mt6357_routes[] = {
 60         {"HDMI Out", NULL, "2ND I2S Playback"},
 61         {"DMIC In", NULL, "MICBIAS0"},
 62 };
 63 
 64 static int mt8365_mt6357_int_adda_startup(struct snd_pcm_substream *substream)
 65 {
 66         struct snd_soc_pcm_runtime *rtd = substream->private_data;
 67         struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(rtd->card);
 68         int ret = 0;
 69 
 70         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 71                 if (IS_ERR(priv->pin_states[PIN_STATE_MOSI_ON]))
 72                         return ret;
 73 
 74                 ret = pinctrl_select_state(priv->pinctrl,
 75                                            priv->pin_states[PIN_STATE_MOSI_ON]);
 76                 if (ret)
 77                         dev_err(rtd->card->dev, "%s failed to select state %d\n",
 78                                 __func__, ret);
 79         }
 80 
 81         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 82                 if (IS_ERR(priv->pin_states[PIN_STATE_MISO_ON]))
 83                         return ret;
 84 
 85                 ret = pinctrl_select_state(priv->pinctrl,
 86                                            priv->pin_states[PIN_STATE_MISO_ON]);
 87                 if (ret)
 88                         dev_err(rtd->card->dev, "%s failed to select state %d\n",
 89                                 __func__, ret);
 90         }
 91 
 92         return 0;
 93 }
 94 
 95 static void mt8365_mt6357_int_adda_shutdown(struct snd_pcm_substream *substream)
 96 {
 97         struct snd_soc_pcm_runtime *rtd = substream->private_data;
 98         struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(rtd->card);
 99         int ret = 0;
100 
101         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
102                 if (IS_ERR(priv->pin_states[PIN_STATE_MOSI_OFF]))
103                         return;
104 
105                 ret = pinctrl_select_state(priv->pinctrl,
106                                            priv->pin_states[PIN_STATE_MOSI_OFF]);
107                 if (ret)
108                         dev_err(rtd->card->dev, "%s failed to select state %d\n",
109                                 __func__, ret);
110         }
111 
112         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
113                 if (IS_ERR(priv->pin_states[PIN_STATE_MISO_OFF]))
114                         return;
115 
116                 ret = pinctrl_select_state(priv->pinctrl,
117                                            priv->pin_states[PIN_STATE_MISO_OFF]);
118                 if (ret)
119                         dev_err(rtd->card->dev, "%s failed to select state %d\n",
120                                 __func__, ret);
121         }
122 }
123 
124 static const struct snd_soc_ops mt8365_mt6357_int_adda_ops = {
125         .startup = mt8365_mt6357_int_adda_startup,
126         .shutdown = mt8365_mt6357_int_adda_shutdown,
127 };
128 
129 SND_SOC_DAILINK_DEFS(playback1,
130                      DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
131                      DAILINK_COMP_ARRAY(COMP_DUMMY()),
132                      DAILINK_COMP_ARRAY(COMP_EMPTY()));
133 SND_SOC_DAILINK_DEFS(playback2,
134                      DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
135                      DAILINK_COMP_ARRAY(COMP_DUMMY()),
136                      DAILINK_COMP_ARRAY(COMP_EMPTY()));
137 SND_SOC_DAILINK_DEFS(awb_capture,
138                      DAILINK_COMP_ARRAY(COMP_CPU("AWB")),
139                      DAILINK_COMP_ARRAY(COMP_DUMMY()),
140                      DAILINK_COMP_ARRAY(COMP_EMPTY()));
141 SND_SOC_DAILINK_DEFS(vul,
142                      DAILINK_COMP_ARRAY(COMP_CPU("VUL")),
143                      DAILINK_COMP_ARRAY(COMP_DUMMY()),
144                      DAILINK_COMP_ARRAY(COMP_EMPTY()));
145 
146 SND_SOC_DAILINK_DEFS(i2s3,
147                      DAILINK_COMP_ARRAY(COMP_CPU("2ND I2S")),
148                      DAILINK_COMP_ARRAY(COMP_DUMMY()),
149                      DAILINK_COMP_ARRAY(COMP_EMPTY()));
150 SND_SOC_DAILINK_DEFS(dmic,
151                      DAILINK_COMP_ARRAY(COMP_CPU("DMIC")),
152                      DAILINK_COMP_ARRAY(COMP_DUMMY()),
153                      DAILINK_COMP_ARRAY(COMP_EMPTY()));
154 SND_SOC_DAILINK_DEFS(primary_codec,
155                      DAILINK_COMP_ARRAY(COMP_CPU("INT ADDA")),
156                      DAILINK_COMP_ARRAY(COMP_CODEC("mt6357-sound", "mt6357-snd-codec-aif1")),
157                      DAILINK_COMP_ARRAY(COMP_EMPTY()));
158 
159 /* Digital audio interface glue - connects codec <---> CPU */
160 static struct snd_soc_dai_link mt8365_mt6357_dais[] = {
161         /* Front End DAI links */
162         [DAI_LINK_DL1_PLAYBACK] = {
163                 .name = "DL1_FE",
164                 .stream_name = "MultiMedia1_PLayback",
165                 .id = DAI_LINK_DL1_PLAYBACK,
166                 .trigger = {
167                         SND_SOC_DPCM_TRIGGER_POST,
168                         SND_SOC_DPCM_TRIGGER_POST
169                 },
170                 .dynamic = 1,
171                 .dpcm_playback = 1,
172                 .dpcm_merged_rate = 1,
173                 SND_SOC_DAILINK_REG(playback1),
174         },
175         [DAI_LINK_DL2_PLAYBACK] = {
176                 .name = "DL2_FE",
177                 .stream_name = "MultiMedia2_PLayback",
178                 .id = DAI_LINK_DL2_PLAYBACK,
179                 .trigger = {
180                         SND_SOC_DPCM_TRIGGER_POST,
181                         SND_SOC_DPCM_TRIGGER_POST
182                 },
183                 .dynamic = 1,
184                 .dpcm_playback = 1,
185                 .dpcm_merged_rate = 1,
186                 SND_SOC_DAILINK_REG(playback2),
187         },
188         [DAI_LINK_AWB_CAPTURE] = {
189                 .name = "AWB_FE",
190                 .stream_name = "DL1_AWB_Record",
191                 .id = DAI_LINK_AWB_CAPTURE,
192                 .trigger = {
193                         SND_SOC_DPCM_TRIGGER_POST,
194                         SND_SOC_DPCM_TRIGGER_POST
195                 },
196                 .dynamic = 1,
197                 .dpcm_capture = 1,
198                 .dpcm_merged_rate = 1,
199                 SND_SOC_DAILINK_REG(awb_capture),
200         },
201         [DAI_LINK_VUL_CAPTURE] = {
202                 .name = "VUL_FE",
203                 .stream_name = "MultiMedia1_Capture",
204                 .id = DAI_LINK_VUL_CAPTURE,
205                 .trigger = {
206                         SND_SOC_DPCM_TRIGGER_POST,
207                         SND_SOC_DPCM_TRIGGER_POST
208                 },
209                 .dynamic = 1,
210                 .dpcm_capture = 1,
211                 .dpcm_merged_rate = 1,
212                 SND_SOC_DAILINK_REG(vul),
213         },
214         /* Back End DAI links */
215         [DAI_LINK_2ND_I2S_INTF] = {
216                 .name = "I2S_OUT_BE",
217                 .no_pcm = 1,
218                 .id = DAI_LINK_2ND_I2S_INTF,
219                 .dai_fmt = SND_SOC_DAIFMT_I2S |
220                                 SND_SOC_DAIFMT_NB_NF |
221                                 SND_SOC_DAIFMT_CBS_CFS,
222                 .dpcm_playback = 1,
223                 .dpcm_capture = 1,
224                 SND_SOC_DAILINK_REG(i2s3),
225         },
226         [DAI_LINK_DMIC] = {
227                 .name = "DMIC_BE",
228                 .no_pcm = 1,
229                 .id = DAI_LINK_DMIC,
230                 .dpcm_capture = 1,
231                 SND_SOC_DAILINK_REG(dmic),
232         },
233         [DAI_LINK_INT_ADDA] = {
234                 .name = "MTK_Codec",
235                 .no_pcm = 1,
236                 .id = DAI_LINK_INT_ADDA,
237                 .dpcm_playback = 1,
238                 .dpcm_capture = 1,
239                 .ops = &mt8365_mt6357_int_adda_ops,
240                 SND_SOC_DAILINK_REG(primary_codec),
241         },
242 };
243 
244 static int mt8365_mt6357_gpio_probe(struct snd_soc_card *card)
245 {
246         struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(card);
247         int ret, i;
248 
249         priv->pinctrl = devm_pinctrl_get(card->dev);
250         if (IS_ERR(priv->pinctrl)) {
251                 ret = PTR_ERR(priv->pinctrl);
252                 return dev_err_probe(card->dev, ret,
253                                      "Failed to get pinctrl\n");
254         }
255 
256         for (i = PIN_STATE_DEFAULT ; i < PIN_STATE_MAX ; i++) {
257                 priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl,
258                                                            mt8365_mt6357_pin_str[i]);
259                 if (IS_ERR(priv->pin_states[i])) {
260                         dev_info(card->dev, "No pin state for %s\n",
261                                  mt8365_mt6357_pin_str[i]);
262                 } else {
263                         ret = pinctrl_select_state(priv->pinctrl,
264                                                    priv->pin_states[i]);
265                         if (ret) {
266                                 dev_err_probe(card->dev, ret,
267                                               "Failed to select pin state %s\n",
268                                               mt8365_mt6357_pin_str[i]);
269                                 return ret;
270                         }
271                 }
272         }
273         return 0;
274 }
275 
276 static struct snd_soc_card mt8365_mt6357_soc_card = {
277         .name = "mt8365-evk",
278         .owner = THIS_MODULE,
279         .dai_link = mt8365_mt6357_dais,
280         .num_links = ARRAY_SIZE(mt8365_mt6357_dais),
281         .dapm_widgets = mt8365_mt6357_widgets,
282         .num_dapm_widgets = ARRAY_SIZE(mt8365_mt6357_widgets),
283         .dapm_routes = mt8365_mt6357_routes,
284         .num_dapm_routes = ARRAY_SIZE(mt8365_mt6357_routes),
285 };
286 
287 static int mt8365_mt6357_dev_probe(struct mtk_soc_card_data *soc_card_data, bool legacy)
288 {
289         struct mtk_platform_card_data *card_data = soc_card_data->card_data;
290         struct snd_soc_card *card = card_data->card;
291         struct device *dev = card->dev;
292         struct mt8365_mt6357_priv *mach_priv;
293         int ret;
294 
295         card->dev = dev;
296         ret = parse_dai_link_info(card);
297         if (ret)
298                 goto err;
299 
300         mach_priv = devm_kzalloc(dev, sizeof(*mach_priv),
301                                  GFP_KERNEL);
302         if (!mach_priv)
303                 return -ENOMEM;
304         soc_card_data->mach_priv = mach_priv;
305         snd_soc_card_set_drvdata(card, soc_card_data);
306         mt8365_mt6357_gpio_probe(card);
307         return 0;
308 
309 err:
310         clean_card_reference(card);
311         return ret;
312 }
313 
314 static const struct mtk_soundcard_pdata mt8365_mt6357_card = {
315         .card_name = "mt8365-mt6357",
316         .card_data = &(struct mtk_platform_card_data) {
317                 .card = &mt8365_mt6357_soc_card,
318         },
319         .soc_probe = mt8365_mt6357_dev_probe
320 };
321 
322 static const struct of_device_id mt8365_mt6357_dt_match[] = {
323         { .compatible = "mediatek,mt8365-mt6357", .data = &mt8365_mt6357_card },
324         { /* sentinel */ }
325 };
326 MODULE_DEVICE_TABLE(of, mt8365_mt6357_dt_match);
327 
328 static struct platform_driver mt8365_mt6357_driver = {
329         .driver = {
330                    .name = "mt8365_mt6357",
331                    .of_match_table = mt8365_mt6357_dt_match,
332                    .pm = &snd_soc_pm_ops,
333         },
334         .probe = mtk_soundcard_common_probe,
335 };
336 
337 module_platform_driver(mt8365_mt6357_driver);
338 
339 /* Module information */
340 MODULE_DESCRIPTION("MT8365 EVK SoC machine driver");
341 MODULE_AUTHOR("Nicolas Belin <nbelin@baylibre.com>");
342 MODULE_LICENSE("GPL");
343 MODULE_ALIAS("platform: mt8365_mt6357");
344 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php