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

TOMOYO Linux Cross Reference
Linux/sound/soc/intel/boards/sof_rt5682.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ 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.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 // Copyright(c) 2019-2020 Intel Corporation.
  3 
  4 /*
  5  * Intel SOF Machine Driver with Realtek rt5682 Codec
  6  * and speaker codec MAX98357A or RT1015.
  7  */
  8 #include <linux/i2c.h>
  9 #include <linux/input.h>
 10 #include <linux/module.h>
 11 #include <linux/platform_device.h>
 12 #include <linux/clk.h>
 13 #include <linux/dmi.h>
 14 #include <sound/core.h>
 15 #include <sound/jack.h>
 16 #include <sound/pcm.h>
 17 #include <sound/pcm_params.h>
 18 #include <sound/soc.h>
 19 #include <sound/sof.h>
 20 #include <sound/rt5682.h>
 21 #include <sound/rt5682s.h>
 22 #include <sound/soc-acpi.h>
 23 #include "../../codecs/rt5682.h"
 24 #include "../../codecs/rt5682s.h"
 25 #include "../../codecs/rt5645.h"
 26 #include "../common/soc-intel-quirks.h"
 27 #include "sof_board_helpers.h"
 28 #include "sof_maxim_common.h"
 29 #include "sof_realtek_common.h"
 30 
 31 /* Driver-specific board quirks: from bit 0 to 7 */
 32 #define SOF_RT5682_MCLK_EN                      BIT(0)
 33 
 34 /* Default: MCLK on, MCLK 19.2M, SSP0  */
 35 static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
 36                                         SOF_SSP_PORT_CODEC(0);
 37 
 38 static int sof_rt5682_quirk_cb(const struct dmi_system_id *id)
 39 {
 40         sof_rt5682_quirk = (unsigned long)id->driver_data;
 41         return 1;
 42 }
 43 
 44 static const struct dmi_system_id sof_rt5682_quirk_table[] = {
 45         {
 46                 .callback = sof_rt5682_quirk_cb,
 47                 .matches = {
 48                         DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
 49                         DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max"),
 50                 },
 51                 .driver_data = (void *)(SOF_SSP_PORT_CODEC(2)),
 52         },
 53         {
 54                 .callback = sof_rt5682_quirk_cb,
 55                 .matches = {
 56                         DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
 57                         DMI_MATCH(DMI_PRODUCT_NAME, "UP-CHT01"),
 58                 },
 59                 .driver_data = (void *)(SOF_SSP_PORT_CODEC(2)),
 60         },
 61         {
 62                 .callback = sof_rt5682_quirk_cb,
 63                 .matches = {
 64                         DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
 65                         DMI_MATCH(DMI_PRODUCT_NAME, "WhiskeyLake Client"),
 66                 },
 67                 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
 68                                         SOF_SSP_PORT_CODEC(1)),
 69         },
 70         {
 71                 .callback = sof_rt5682_quirk_cb,
 72                 .matches = {
 73                         DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Volteer"),
 74                         DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98373_ALC5682I_I2S_UP4"),
 75                 },
 76                 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
 77                                         SOF_SSP_PORT_CODEC(0) |
 78                                         SOF_SSP_PORT_AMP(2) |
 79                                         SOF_NUM_IDISP_HDMI(4)),
 80         },
 81         {
 82                 .callback = sof_rt5682_quirk_cb,
 83                 .matches = {
 84                         DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
 85                         DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
 86                         DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"),
 87                 },
 88                 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
 89                                         SOF_SSP_PORT_CODEC(0) |
 90                                         SOF_SSP_PORT_AMP(2) |
 91                                         SOF_NUM_IDISP_HDMI(4)),
 92         },
 93         {
 94                 .callback = sof_rt5682_quirk_cb,
 95                 .matches = {
 96                         DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
 97                         DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98390_ALC5682I_I2S"),
 98                 },
 99                 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
100                                         SOF_SSP_PORT_CODEC(0) |
101                                         SOF_SSP_PORT_AMP(2) |
102                                         SOF_NUM_IDISP_HDMI(4)),
103         },
104         {
105                 .callback = sof_rt5682_quirk_cb,
106                 .matches = {
107                         DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
108                         DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_I2S_AMP_SSP2"),
109                 },
110                 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
111                                         SOF_SSP_PORT_CODEC(0) |
112                                         SOF_SSP_PORT_AMP(2) |
113                                         SOF_NUM_IDISP_HDMI(4)),
114         },
115         {
116                 .callback = sof_rt5682_quirk_cb,
117                 .matches = {
118                         DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
119                 },
120                 .driver_data = (void *)(SOF_RT5682_MCLK_EN |
121                                         SOF_SSP_PORT_CODEC(2) |
122                                         SOF_SSP_PORT_AMP(0) |
123                                         SOF_SSP_PORT_BT_OFFLOAD(1) |
124                                         SOF_BT_OFFLOAD_PRESENT
125                                         ),
126         },
127         {}
128 };
129 
130 static struct snd_soc_jack_pin jack_pins[] = {
131         {
132                 .pin    = "Headphone Jack",
133                 .mask   = SND_JACK_HEADPHONE,
134         },
135         {
136                 .pin    = "Headset Mic",
137                 .mask   = SND_JACK_MICROPHONE,
138         },
139 };
140 
141 static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
142 {
143         struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
144         struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
145         struct snd_soc_jack *jack = &ctx->headset_jack;
146         int extra_jack_data;
147         int ret, mclk_freq;
148 
149         if (ctx->rt5682.mclk_en) {
150                 mclk_freq = sof_dai_get_mclk(rtd);
151                 if (mclk_freq <= 0) {
152                         dev_err(rtd->dev, "invalid mclk freq %d\n", mclk_freq);
153                         return -EINVAL;
154                 }
155 
156                 /* need to enable ASRC function for 24MHz mclk rate */
157                 if (mclk_freq == 24000000) {
158                         dev_info(rtd->dev, "enable ASRC\n");
159 
160                         switch (ctx->codec_type) {
161                         case CODEC_RT5650:
162                                 rt5645_sel_asrc_clk_src(component,
163                                                         RT5645_DA_STEREO_FILTER |
164                                                         RT5645_AD_STEREO_FILTER,
165                                                         RT5645_CLK_SEL_I2S1_ASRC);
166                                 rt5645_sel_asrc_clk_src(component,
167                                                         RT5645_DA_MONO_L_FILTER |
168                                                         RT5645_DA_MONO_R_FILTER,
169                                                         RT5645_CLK_SEL_I2S2_ASRC);
170                                 break;
171                         case CODEC_RT5682:
172                                 rt5682_sel_asrc_clk_src(component,
173                                                         RT5682_DA_STEREO1_FILTER |
174                                                         RT5682_AD_STEREO1_FILTER,
175                                                         RT5682_CLK_SEL_I2S1_ASRC);
176                                 break;
177                         case CODEC_RT5682S:
178                                 rt5682s_sel_asrc_clk_src(component,
179                                                          RT5682S_DA_STEREO1_FILTER |
180                                                          RT5682S_AD_STEREO1_FILTER,
181                                                          RT5682S_CLK_SEL_I2S1_ASRC);
182                                 break;
183                         default:
184                                 dev_err(rtd->dev, "invalid codec type %d\n",
185                                         ctx->codec_type);
186                                 return -EINVAL;
187                         }
188                 }
189 
190                 if (ctx->rt5682.is_legacy_cpu) {
191                         /*
192                          * The firmware might enable the clock at
193                          * boot (this information may or may not
194                          * be reflected in the enable clock register).
195                          * To change the rate we must disable the clock
196                          * first to cover these cases. Due to common
197                          * clock framework restrictions that do not allow
198                          * to disable a clock that has not been enabled,
199                          * we need to enable the clock first.
200                          */
201                         ret = clk_prepare_enable(ctx->rt5682.mclk);
202                         if (!ret)
203                                 clk_disable_unprepare(ctx->rt5682.mclk);
204 
205                         ret = clk_set_rate(ctx->rt5682.mclk, 19200000);
206 
207                         if (ret)
208                                 dev_err(rtd->dev, "unable to set MCLK rate\n");
209                 }
210         }
211 
212         /*
213          * Headset buttons map to the google Reference headset.
214          * These can be configured by userspace.
215          */
216         ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
217                                          SND_JACK_HEADSET | SND_JACK_BTN_0 |
218                                          SND_JACK_BTN_1 | SND_JACK_BTN_2 |
219                                          SND_JACK_BTN_3,
220                                          jack,
221                                          jack_pins,
222                                          ARRAY_SIZE(jack_pins));
223         if (ret) {
224                 dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
225                 return ret;
226         }
227 
228         snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
229         snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
230         snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
231         snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
232 
233         if (ctx->codec_type == CODEC_RT5650) {
234                 extra_jack_data = SND_JACK_MICROPHONE | SND_JACK_BTN_0;
235                 ret = snd_soc_component_set_jack(component, jack, &extra_jack_data);
236         } else
237                 ret = snd_soc_component_set_jack(component, jack, NULL);
238 
239         if (ret) {
240                 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
241                 return ret;
242         }
243 
244         return ret;
245 };
246 
247 static void sof_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd)
248 {
249         struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
250 
251         snd_soc_component_set_jack(component, NULL, NULL);
252 }
253 
254 static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,
255                                 struct snd_pcm_hw_params *params)
256 {
257         struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
258         struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
259         struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
260         int pll_id, pll_source, pll_in, pll_out, clk_id, ret;
261 
262         if (ctx->rt5682.mclk_en) {
263                 if (ctx->rt5682.is_legacy_cpu) {
264                         ret = clk_prepare_enable(ctx->rt5682.mclk);
265                         if (ret < 0) {
266                                 dev_err(rtd->dev,
267                                         "could not configure MCLK state");
268                                 return ret;
269                         }
270                 }
271 
272                 switch (ctx->codec_type) {
273                 case CODEC_RT5650:
274                         pll_source = RT5645_PLL1_S_MCLK;
275                         break;
276                 case CODEC_RT5682:
277                         pll_source = RT5682_PLL1_S_MCLK;
278                         break;
279                 case CODEC_RT5682S:
280                         pll_source = RT5682S_PLL_S_MCLK;
281                         break;
282                 default:
283                         dev_err(rtd->dev, "invalid codec type %d\n",
284                                 ctx->codec_type);
285                         return -EINVAL;
286                 }
287 
288                 /* get the tplg configured mclk. */
289                 pll_in = sof_dai_get_mclk(rtd);
290                 if (pll_in <= 0) {
291                         dev_err(rtd->dev, "invalid mclk freq %d\n", pll_in);
292                         return -EINVAL;
293                 }
294         } else {
295                 switch (ctx->codec_type) {
296                 case CODEC_RT5650:
297                         pll_source = RT5645_PLL1_S_BCLK1;
298                         break;
299                 case CODEC_RT5682:
300                         pll_source = RT5682_PLL1_S_BCLK1;
301                         break;
302                 case CODEC_RT5682S:
303                         pll_source = RT5682S_PLL_S_BCLK1;
304                         break;
305                 default:
306                         dev_err(rtd->dev, "invalid codec type %d\n",
307                                 ctx->codec_type);
308                         return -EINVAL;
309                 }
310 
311                 /* get the tplg configured bclk. */
312                 pll_in = sof_dai_get_bclk(rtd);
313                 if (pll_in <= 0) {
314                         dev_err(rtd->dev, "invalid bclk freq %d\n", pll_in);
315                         return -EINVAL;
316                 }
317         }
318 
319         pll_out = params_rate(params) * 512;
320 
321         /* when MCLK is 512FS, no need to set PLL configuration additionally. */
322         if (pll_in == pll_out) {
323                 switch (ctx->codec_type) {
324                 case CODEC_RT5650:
325                         clk_id = RT5645_SCLK_S_MCLK;
326                         break;
327                 case CODEC_RT5682:
328                         clk_id = RT5682_SCLK_S_MCLK;
329                         break;
330                 case CODEC_RT5682S:
331                         clk_id = RT5682S_SCLK_S_MCLK;
332                         break;
333                 default:
334                         dev_err(rtd->dev, "invalid codec type %d\n",
335                                 ctx->codec_type);
336                         return -EINVAL;
337                 }
338         } else {
339                 switch (ctx->codec_type) {
340                 case CODEC_RT5650:
341                         pll_id = 0; /* not used in codec driver */
342                         clk_id = RT5645_SCLK_S_PLL1;
343                         break;
344                 case CODEC_RT5682:
345                         pll_id = RT5682_PLL1;
346                         clk_id = RT5682_SCLK_S_PLL1;
347                         break;
348                 case CODEC_RT5682S:
349                         /* check plla_table and pllb_table in rt5682s.c */
350                         switch (pll_in) {
351                         case 3072000:
352                         case 24576000:
353                                 /*
354                                  * For MCLK = 24.576MHz and sample rate = 96KHz case, use PLL1  We don't test
355                                  * pll_out or params_rate() here since rt5682s PLL2 doesn't support 24.576MHz
356                                  * input, so we have no choice but to use PLL1. Besides, we will not use PLL at
357                                  * all if pll_in == pll_out. ex, MCLK = 24.576Mhz and sample rate = 48KHz
358                                  */
359                                 pll_id = RT5682S_PLL1;
360                                 clk_id = RT5682S_SCLK_S_PLL1;
361                                 break;
362                         default:
363                                 pll_id = RT5682S_PLL2;
364                                 clk_id = RT5682S_SCLK_S_PLL2;
365                                 break;
366                         }
367                         break;
368                 default:
369                         dev_err(rtd->dev, "invalid codec type %d\n", ctx->codec_type);
370                         return -EINVAL;
371                 }
372 
373                 /* Configure pll for codec */
374                 ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source, pll_in,
375                                           pll_out);
376                 if (ret < 0)
377                         dev_err(rtd->dev, "snd_soc_dai_set_pll err = %d\n", ret);
378         }
379 
380         /* Configure sysclk for codec */
381         ret = snd_soc_dai_set_sysclk(codec_dai, clk_id,
382                                      pll_out, SND_SOC_CLOCK_IN);
383         if (ret < 0)
384                 dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
385 
386         /*
387          * slot_width should equal or large than data length, set them
388          * be the same
389          */
390         ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2,
391                                        params_width(params));
392         if (ret < 0) {
393                 dev_err(rtd->dev, "set TDM slot err:%d\n", ret);
394                 return ret;
395         }
396 
397         return ret;
398 }
399 
400 static const struct snd_soc_ops sof_rt5682_ops = {
401         .hw_params = sof_rt5682_hw_params,
402 };
403 
404 static int sof_card_late_probe(struct snd_soc_card *card)
405 {
406         struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
407         struct snd_soc_dapm_context *dapm = &card->dapm;
408         int err;
409 
410         if (ctx->amp_type == CODEC_MAX98373) {
411                 /* Disable Left and Right Spk pin after boot */
412                 snd_soc_dapm_disable_pin(dapm, "Left Spk");
413                 snd_soc_dapm_disable_pin(dapm, "Right Spk");
414                 err = snd_soc_dapm_sync(dapm);
415                 if (err < 0)
416                         return err;
417         }
418 
419         return sof_intel_board_card_late_probe(card);
420 }
421 
422 static const struct snd_kcontrol_new sof_controls[] = {
423         SOC_DAPM_PIN_SWITCH("Headphone Jack"),
424         SOC_DAPM_PIN_SWITCH("Headset Mic"),
425 };
426 
427 static const struct snd_soc_dapm_widget sof_widgets[] = {
428         SND_SOC_DAPM_HP("Headphone Jack", NULL),
429         SND_SOC_DAPM_MIC("Headset Mic", NULL),
430 };
431 
432 static const struct snd_soc_dapm_route sof_map[] = {
433         /* HP jack connectors - unknown if we have jack detection */
434         { "Headphone Jack", NULL, "HPOL" },
435         { "Headphone Jack", NULL, "HPOR" },
436 
437         /* other jacks */
438         { "IN1P", NULL, "Headset Mic" },
439 };
440 
441 static const struct snd_kcontrol_new rt5650_spk_kcontrols[] = {
442         SOC_DAPM_PIN_SWITCH("Left Spk"),
443         SOC_DAPM_PIN_SWITCH("Right Spk"),
444 
445 };
446 
447 static const struct snd_soc_dapm_widget rt5650_spk_widgets[] = {
448         SND_SOC_DAPM_SPK("Left Spk", NULL),
449         SND_SOC_DAPM_SPK("Right Spk", NULL),
450 };
451 
452 static const struct snd_soc_dapm_route rt5650_spk_dapm_routes[] = {
453         /* speaker */
454         { "Left Spk", NULL, "SPOL" },
455         { "Right Spk", NULL, "SPOR" },
456 };
457 
458 static int rt5650_spk_init(struct snd_soc_pcm_runtime *rtd)
459 {
460         struct snd_soc_card *card = rtd->card;
461         int ret;
462 
463         ret = snd_soc_dapm_new_controls(&card->dapm, rt5650_spk_widgets,
464                                         ARRAY_SIZE(rt5650_spk_widgets));
465         if (ret) {
466                 dev_err(rtd->dev, "fail to add rt5650 spk widgets, ret %d\n",
467                         ret);
468                 return ret;
469         }
470 
471         ret = snd_soc_add_card_controls(card, rt5650_spk_kcontrols,
472                                         ARRAY_SIZE(rt5650_spk_kcontrols));
473         if (ret) {
474                 dev_err(rtd->dev, "fail to add rt5650 spk kcontrols, ret %d\n",
475                         ret);
476                 return ret;
477         }
478 
479         ret = snd_soc_dapm_add_routes(&card->dapm, rt5650_spk_dapm_routes,
480                                       ARRAY_SIZE(rt5650_spk_dapm_routes));
481         if (ret)
482                 dev_err(rtd->dev, "fail to add dapm routes, ret=%d\n", ret);
483 
484         return ret;
485 }
486 
487 /* sof audio machine driver for rt5682 codec */
488 static struct snd_soc_card sof_audio_card_rt5682 = {
489         .name = "rt5682", /* the sof- prefix is added by the core */
490         .owner = THIS_MODULE,
491         .controls = sof_controls,
492         .num_controls = ARRAY_SIZE(sof_controls),
493         .dapm_widgets = sof_widgets,
494         .num_dapm_widgets = ARRAY_SIZE(sof_widgets),
495         .dapm_routes = sof_map,
496         .num_dapm_routes = ARRAY_SIZE(sof_map),
497         .fully_routed = true,
498         .late_probe = sof_card_late_probe,
499 };
500 
501 static struct snd_soc_dai_link_component rt5682_component[] = {
502         {
503                 .name = "i2c-10EC5682:00",
504                 .dai_name = "rt5682-aif1",
505         }
506 };
507 
508 static struct snd_soc_dai_link_component rt5682s_component[] = {
509         {
510                 .name = "i2c-RTL5682:00",
511                 .dai_name = "rt5682s-aif1",
512         }
513 };
514 
515 static struct snd_soc_dai_link_component rt5650_components[] = {
516         {
517                 .name = "i2c-10EC5650:00",
518                 .dai_name = "rt5645-aif1",
519         },
520         {
521                 .name = "i2c-10EC5650:00",
522                 .dai_name = "rt5645-aif2",
523         }
524 };
525 
526 static int
527 sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card,
528                           struct sof_card_private *ctx)
529 {
530         int ret;
531 
532         ret = sof_intel_board_set_dai_link(dev, card, ctx);
533         if (ret)
534                 return ret;
535 
536         if (!ctx->codec_link) {
537                 dev_err(dev, "codec link not available");
538                 return -EINVAL;
539         }
540 
541         /* codec-specific fields for headphone codec */
542         switch (ctx->codec_type) {
543         case CODEC_RT5650:
544                 ctx->codec_link->codecs = &rt5650_components[0];
545                 ctx->codec_link->num_codecs = 1;
546                 break;
547         case CODEC_RT5682:
548                 ctx->codec_link->codecs = rt5682_component;
549                 ctx->codec_link->num_codecs = ARRAY_SIZE(rt5682_component);
550                 break;
551         case CODEC_RT5682S:
552                 ctx->codec_link->codecs = rt5682s_component;
553                 ctx->codec_link->num_codecs = ARRAY_SIZE(rt5682s_component);
554                 break;
555         default:
556                 dev_err(dev, "invalid codec type %d\n", ctx->codec_type);
557                 return -EINVAL;
558         }
559 
560         ctx->codec_link->init = sof_rt5682_codec_init;
561         ctx->codec_link->exit = sof_rt5682_codec_exit;
562         ctx->codec_link->ops = &sof_rt5682_ops;
563 
564         if (!ctx->rt5682.is_legacy_cpu) {
565                 /*
566                  * Currently, On SKL+ platforms MCLK will be turned off in sof
567                  * runtime suspended, and it will go into runtime suspended
568                  * right after playback is stop. However, rt5682 will output
569                  * static noise if sysclk turns off during playback. Set
570                  * ignore_pmdown_time to power down rt5682 immediately and
571                  * avoid the noise.
572                  * It can be removed once we can control MCLK by driver.
573                  */
574                 ctx->codec_link->ignore_pmdown_time = 1;
575         }
576 
577         if (ctx->amp_type == CODEC_NONE)
578                 return 0;
579 
580         if (!ctx->amp_link) {
581                 dev_err(dev, "amp link not available");
582                 return -EINVAL;
583         }
584 
585         /* codec-specific fields for speaker amplifier */
586         switch (ctx->amp_type) {
587         case CODEC_MAX98357A:
588                 max_98357a_dai_link(ctx->amp_link);
589                 break;
590         case CODEC_MAX98360A:
591                 max_98360a_dai_link(ctx->amp_link);
592                 break;
593         case CODEC_MAX98373:
594                 max_98373_dai_link(dev, ctx->amp_link);
595                 break;
596         case CODEC_MAX98390:
597                 max_98390_dai_link(dev, ctx->amp_link);
598                 break;
599         case CODEC_RT1011:
600                 sof_rt1011_dai_link(dev, ctx->amp_link);
601                 break;
602         case CODEC_RT1015:
603                 sof_rt1015_dai_link(ctx->amp_link);
604                 break;
605         case CODEC_RT1015P:
606                 sof_rt1015p_dai_link(ctx->amp_link);
607                 break;
608         case CODEC_RT1019P:
609                 sof_rt1019p_dai_link(ctx->amp_link);
610                 break;
611         case CODEC_RT5650:
612                 /* use AIF2 to support speaker pipeline */
613                 ctx->amp_link->codecs = &rt5650_components[1];
614                 ctx->amp_link->num_codecs = 1;
615                 ctx->amp_link->init = rt5650_spk_init;
616                 ctx->amp_link->ops = &sof_rt5682_ops;
617                 break;
618         default:
619                 dev_err(dev, "invalid amp type %d\n", ctx->amp_type);
620                 return -EINVAL;
621         }
622 
623         return 0;
624 }
625 
626 #define GLK_LINK_ORDER  SOF_LINK_ORDER(SOF_LINK_AMP,         \
627                                         SOF_LINK_CODEC,      \
628                                         SOF_LINK_DMIC01,     \
629                                         SOF_LINK_IDISP_HDMI, \
630                                         SOF_LINK_NONE,       \
631                                         SOF_LINK_NONE,       \
632                                         SOF_LINK_NONE)
633 
634 static int sof_audio_probe(struct platform_device *pdev)
635 {
636         struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
637         struct sof_card_private *ctx;
638         char *card_name;
639         int ret;
640 
641         if (pdev->id_entry && pdev->id_entry->driver_data)
642                 sof_rt5682_quirk = (unsigned long)pdev->id_entry->driver_data;
643 
644         dmi_check_system(sof_rt5682_quirk_table);
645 
646         dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk);
647 
648         /* initialize ctx with board quirk */
649         ctx = sof_intel_board_get_ctx(&pdev->dev, sof_rt5682_quirk);
650         if (!ctx)
651                 return -ENOMEM;
652 
653         if (ctx->codec_type == CODEC_RT5650) {
654                 card_name = devm_kstrdup(&pdev->dev, "rt5650", GFP_KERNEL);
655                 if (!card_name)
656                         return -ENOMEM;
657 
658                 sof_audio_card_rt5682.name = card_name;
659 
660                 /* create speaker dai link also */
661                 if (ctx->amp_type == CODEC_NONE)
662                         ctx->amp_type = CODEC_RT5650;
663         }
664 
665         if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)
666                 ctx->hdmi.idisp_codec = true;
667 
668         if (soc_intel_is_byt() || soc_intel_is_cht()) {
669                 ctx->rt5682.is_legacy_cpu = true;
670                 ctx->dmic_be_num = 0;
671                 /* HDMI is not supported by SOF on Baytrail/CherryTrail */
672                 ctx->hdmi_num = 0;
673         } else if (soc_intel_is_glk()) {
674                 /* dmic16k not support */
675                 ctx->dmic_be_num = 1;
676 
677                 /* overwrite the DAI link order for GLK boards */
678                 ctx->link_order_overwrite = GLK_LINK_ORDER;
679 
680                 /* backward-compatible with existing devices */
681                 switch (ctx->amp_type) {
682                 case CODEC_MAX98357A:
683                         card_name = devm_kstrdup(&pdev->dev, "glkrt5682max",
684                                                  GFP_KERNEL);
685                         if (!card_name)
686                                 return -ENOMEM;
687 
688                         sof_audio_card_rt5682.name = card_name;
689                         break;
690                 default:
691                         break;
692                 }
693         } else if (soc_intel_is_cml()) {
694                 /* backward-compatible with existing devices */
695                 switch (ctx->amp_type) {
696                 case CODEC_RT1011:
697                         card_name = devm_kstrdup(&pdev->dev, "cml_rt1011_rt5682",
698                                                  GFP_KERNEL);
699                         if (!card_name)
700                                 return -ENOMEM;
701 
702                         sof_audio_card_rt5682.name = card_name;
703                         break;
704                 default:
705                         break;
706                 }
707         }
708 
709         if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) {
710                 ctx->rt5682.mclk_en = true;
711 
712                 /* need to get main clock from pmc */
713                 if (ctx->rt5682.is_legacy_cpu) {
714                         ctx->rt5682.mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
715                         if (IS_ERR(ctx->rt5682.mclk)) {
716                                 ret = PTR_ERR(ctx->rt5682.mclk);
717 
718                                 dev_err(&pdev->dev,
719                                         "Failed to get MCLK from pmc_plt_clk_3: %d\n",
720                                         ret);
721                                 return ret;
722                         }
723 
724                         ret = clk_prepare_enable(ctx->rt5682.mclk);
725                         if (ret < 0) {
726                                 dev_err(&pdev->dev,
727                                         "could not configure MCLK state");
728                                 return ret;
729                         }
730                 }
731         }
732 
733         /* update dai_link */
734         ret = sof_card_dai_links_create(&pdev->dev, &sof_audio_card_rt5682, ctx);
735         if (ret)
736                 return ret;
737 
738         /* update codec_conf */
739         switch (ctx->amp_type) {
740         case CODEC_MAX98373:
741                 max_98373_set_codec_conf(&sof_audio_card_rt5682);
742                 break;
743         case CODEC_MAX98390:
744                 max_98390_set_codec_conf(&pdev->dev, &sof_audio_card_rt5682);
745                 break;
746         case CODEC_RT1011:
747                 sof_rt1011_codec_conf(&pdev->dev, &sof_audio_card_rt5682);
748                 break;
749         case CODEC_RT1015:
750                 sof_rt1015_codec_conf(&sof_audio_card_rt5682);
751                 break;
752         case CODEC_RT1015P:
753                 sof_rt1015p_codec_conf(&sof_audio_card_rt5682);
754                 break;
755         case CODEC_MAX98357A:
756         case CODEC_MAX98360A:
757         case CODEC_RT1019P:
758         case CODEC_RT5650:
759         case CODEC_NONE:
760                 /* no codec conf required */
761                 break;
762         default:
763                 dev_err(&pdev->dev, "invalid amp type %d\n", ctx->amp_type);
764                 return -EINVAL;
765         }
766 
767         sof_audio_card_rt5682.dev = &pdev->dev;
768 
769         /* set platform name for each dailink */
770         ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_rt5682,
771                                                     mach->mach_params.platform);
772         if (ret)
773                 return ret;
774 
775         snd_soc_card_set_drvdata(&sof_audio_card_rt5682, ctx);
776 
777         return devm_snd_soc_register_card(&pdev->dev,
778                                           &sof_audio_card_rt5682);
779 }
780 
781 static const struct platform_device_id board_ids[] = {
782         {
783                 .name = "sof_rt5682",
784                 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
785                                         SOF_SSP_PORT_CODEC(2)),
786         },
787         {
788                 .name = "glk_rt5682_def",
789                 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
790                                         SOF_SSP_PORT_CODEC(2) |
791                                         SOF_SSP_PORT_AMP(1)),
792         },
793         {
794                 .name = "icl_rt5682_def",
795                 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
796                                         SOF_SSP_PORT_CODEC(0)),
797         },
798         {
799                 .name = "cml_rt5682_def",
800                 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
801                                         SOF_SSP_PORT_CODEC(0) |
802                                         SOF_SSP_PORT_AMP(1)),
803         },
804         {
805                 .name = "jsl_rt5682_def",
806                 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
807                                         SOF_SSP_PORT_CODEC(0) |
808                                         SOF_SSP_PORT_AMP(1)),
809         },
810         {
811                 .name = "tgl_rt5682_def",
812                 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
813                                         SOF_SSP_PORT_CODEC(0) |
814                                         SOF_SSP_PORT_AMP(1) |
815                                         SOF_NUM_IDISP_HDMI(4) |
816                                         SOF_SSP_PORT_BT_OFFLOAD(2) |
817                                         SOF_BT_OFFLOAD_PRESENT),
818         },
819         {
820                 .name = "adl_rt5682_def",
821                 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
822                                         SOF_SSP_PORT_CODEC(0) |
823                                         SOF_SSP_PORT_AMP(1) |
824                                         SOF_NUM_IDISP_HDMI(4) |
825                                         SOF_SSP_PORT_BT_OFFLOAD(2) |
826                                         SOF_BT_OFFLOAD_PRESENT),
827         },
828         {
829                 .name = "adl_mx98357_rt5682",
830                 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
831                                         SOF_SSP_PORT_CODEC(0) |
832                                         SOF_SSP_PORT_AMP(2) |
833                                         SOF_NUM_IDISP_HDMI(4)),
834         },
835         {
836                 .name = "adl_rt5682_c1_h02",
837                 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
838                                         SOF_SSP_PORT_CODEC(1) |
839                                         /* SSP 0 and SSP 2 are used for HDMI IN */
840                                         SOF_SSP_MASK_HDMI_CAPTURE(0x5)),
841         },
842         {
843                 .name = "rpl_mx98357_rt5682",
844                 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
845                                         SOF_SSP_PORT_CODEC(0) |
846                                         SOF_SSP_PORT_AMP(2) |
847                                         SOF_NUM_IDISP_HDMI(4)),
848         },
849         {
850                 .name = "rpl_rt5682_def",
851                 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
852                                         SOF_SSP_PORT_CODEC(0) |
853                                         SOF_SSP_PORT_AMP(1) |
854                                         SOF_NUM_IDISP_HDMI(4) |
855                                         SOF_SSP_PORT_BT_OFFLOAD(2) |
856                                         SOF_BT_OFFLOAD_PRESENT),
857         },
858         {
859                 .name = "rpl_rt5682_c1_h02",
860                 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
861                                         SOF_SSP_PORT_CODEC(1) |
862                                         /* SSP 0 and SSP 2 are used for HDMI IN */
863                                         SOF_SSP_MASK_HDMI_CAPTURE(0x5)),
864         },
865         {
866                 .name = "mtl_rt5682_def",
867                 .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
868                                         SOF_SSP_PORT_CODEC(0) |
869                                         SOF_SSP_PORT_AMP(1) |
870                                         SOF_SSP_PORT_BT_OFFLOAD(2) |
871                                         SOF_BT_OFFLOAD_PRESENT),
872         },
873         { }
874 };
875 MODULE_DEVICE_TABLE(platform, board_ids);
876 
877 static struct platform_driver sof_audio = {
878         .probe = sof_audio_probe,
879         .driver = {
880                 .name = "sof_rt5682",
881                 .pm = &snd_soc_pm_ops,
882         },
883         .id_table = board_ids,
884 };
885 module_platform_driver(sof_audio)
886 
887 /* Module information */
888 MODULE_DESCRIPTION("SOF Audio Machine driver");
889 MODULE_AUTHOR("Bard Liao <bard.liao@intel.com>");
890 MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
891 MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
892 MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
893 MODULE_LICENSE("GPL v2");
894 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
895 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
896 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
897 

~ [ 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