xref: /linux/sound/soc/intel/boards/sof_realtek_common.c (revision e7bb43898bcf54da7ffb4819a04c8428f7db24db)
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Copyright(c) 2020 Intel Corporation. All rights reserved.
4 
5 #include <linux/device.h>
6 #include <linux/kernel.h>
7 #include <sound/pcm.h>
8 #include <sound/pcm_params.h>
9 #include <sound/soc.h>
10 #include <sound/soc-acpi.h>
11 #include <sound/soc-dai.h>
12 #include <sound/soc-dapm.h>
13 #include <sound/sof.h>
14 #include <uapi/sound/asound.h>
15 #include "../../codecs/rt1011.h"
16 #include "../../codecs/rt1015.h"
17 #include "../../codecs/rt1308.h"
18 #include "../common/soc-intel-quirks.h"
19 #include "sof_realtek_common.h"
20 
21 /*
22  * Common structures and functions
23  */
24 static const struct snd_kcontrol_new realtek_4spk_kcontrols[] = {
25 	SOC_DAPM_PIN_SWITCH("WL Ext Spk"),
26 	SOC_DAPM_PIN_SWITCH("WR Ext Spk"),
27 	SOC_DAPM_PIN_SWITCH("TL Ext Spk"),
28 	SOC_DAPM_PIN_SWITCH("TR Ext Spk"),
29 };
30 
31 static const struct snd_soc_dapm_widget realtek_4spk_widgets[] = {
32 	SND_SOC_DAPM_SPK("WL Ext Spk", NULL),
33 	SND_SOC_DAPM_SPK("WR Ext Spk", NULL),
34 	SND_SOC_DAPM_SPK("TL Ext Spk", NULL),
35 	SND_SOC_DAPM_SPK("TR Ext Spk", NULL),
36 };
37 
38 /* helper function to get the number of specific codec */
39 static unsigned int get_num_codecs(const char *hid)
40 {
41 	struct acpi_device *adev;
42 	unsigned int dev_num = 0;
43 
44 	for_each_acpi_dev_match(adev, hid, NULL, -1)
45 		dev_num++;
46 
47 	return dev_num;
48 }
49 
50 /*
51  * Realtek ALC1011
52  */
53 static const struct snd_soc_dapm_route speaker_map_lr[] = {
54 	/* speaker */
55 	{ "Left Spk", NULL, "Left SPO" },
56 	{ "Right Spk", NULL, "Right SPO" },
57 };
58 
59 static const struct snd_soc_dapm_route rt1011_4spk_routes[] = {
60 	{"WL Ext Spk", NULL, "WL SPO" },
61 	{"WR Ext Spk", NULL, "WR SPO" },
62 	{"TL Ext Spk", NULL, "TL SPO" },
63 	{"TR Ext Spk", NULL, "TR SPO" },
64 };
65 
66 static struct snd_soc_codec_conf rt1011_2spk_codec_confs[] = {
67 	{
68 		.dlc = COMP_CODEC_CONF(RT1011_DEV0_NAME),
69 		.name_prefix = "Left",
70 	},
71 	{
72 		.dlc = COMP_CODEC_CONF(RT1011_DEV1_NAME),
73 		.name_prefix = "Right",
74 	},
75 };
76 
77 static struct snd_soc_codec_conf rt1011_4spk_codec_confs[] = {
78 	{
79 		.dlc = COMP_CODEC_CONF(RT1011_DEV0_NAME),
80 		.name_prefix = "WL",
81 	},
82 	{
83 		.dlc = COMP_CODEC_CONF(RT1011_DEV1_NAME),
84 		.name_prefix = "WR",
85 	},
86 	{
87 		.dlc = COMP_CODEC_CONF(RT1011_DEV2_NAME),
88 		.name_prefix = "TL",
89 	},
90 	{
91 		.dlc = COMP_CODEC_CONF(RT1011_DEV3_NAME),
92 		.name_prefix = "TR",
93 	},
94 };
95 
96 static struct snd_soc_dai_link_component rt1011_dai_link_components[] = {
97 	{
98 		.name = RT1011_DEV0_NAME,
99 		.dai_name = RT1011_CODEC_DAI,
100 	},
101 	{
102 		.name = RT1011_DEV1_NAME,
103 		.dai_name = RT1011_CODEC_DAI,
104 	},
105 	{
106 		.name = RT1011_DEV2_NAME,
107 		.dai_name = RT1011_CODEC_DAI,
108 	},
109 	{
110 		.name = RT1011_DEV3_NAME,
111 		.dai_name = RT1011_CODEC_DAI,
112 	},
113 };
114 
115 static const struct {
116 	unsigned int tx;
117 	unsigned int rx;
118 } rt1011_tdm_mask[] = {
119 	{.tx = 0x4, .rx = 0x1},
120 	{.tx = 0x8, .rx = 0x2},
121 	{.tx = 0x1, .rx = 0x1},
122 	{.tx = 0x2, .rx = 0x2},
123 };
124 
125 static int rt1011_hw_params(struct snd_pcm_substream *substream,
126 			    struct snd_pcm_hw_params *params)
127 {
128 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
129 	struct snd_soc_dai *codec_dai;
130 	int srate, i, ret = 0;
131 
132 	srate = params_rate(params);
133 
134 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
135 		/* 100 Fs to drive 24 bit data */
136 		ret = snd_soc_dai_set_pll(codec_dai, 0, RT1011_PLL1_S_BCLK,
137 					  100 * srate, 256 * srate);
138 		if (ret < 0) {
139 			dev_err(codec_dai->dev, "fail to set pll, ret %d\n",
140 				ret);
141 			return ret;
142 		}
143 
144 		ret = snd_soc_dai_set_sysclk(codec_dai, RT1011_FS_SYS_PRE_S_PLL1,
145 					     256 * srate, SND_SOC_CLOCK_IN);
146 		if (ret < 0) {
147 			dev_err(codec_dai->dev, "fail to set sysclk, ret %d\n",
148 				ret);
149 			return ret;
150 		}
151 
152 		if (i >= ARRAY_SIZE(rt1011_tdm_mask)) {
153 			dev_err(codec_dai->dev, "invalid codec index %d\n",
154 				i);
155 			return -ENODEV;
156 		}
157 
158 		ret = snd_soc_dai_set_tdm_slot(codec_dai, rt1011_tdm_mask[i].tx,
159 					       rt1011_tdm_mask[i].rx, 4,
160 					       params_width(params));
161 		if (ret < 0) {
162 			dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n",
163 				ret);
164 			return ret;
165 		}
166 	}
167 
168 	return 0;
169 }
170 
171 static const struct snd_soc_ops rt1011_ops = {
172 	.hw_params = rt1011_hw_params,
173 };
174 
175 static int rt1011_init(struct snd_soc_pcm_runtime *rtd)
176 {
177 	struct snd_soc_card *card = rtd->card;
178 	unsigned int num_codecs = get_num_codecs(RT1011_ACPI_HID);
179 	int ret;
180 
181 	switch (num_codecs) {
182 	case 2:
183 		if (!soc_intel_is_cml()) {
184 			ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map_lr,
185 						      ARRAY_SIZE(speaker_map_lr));
186 			if (ret) {
187 				dev_err(rtd->dev, "fail to add rt1011 routes, ret %d\n",
188 					ret);
189 				return ret;
190 			}
191 
192 			break;
193 		}
194 
195 		/*
196 		 * register speaker widgets "WL Ext Spk" and "WR Ext Spk" to
197 		 * keep backward compatible with cml devices
198 		 */
199 		fallthrough;
200 	case 4:
201 		ret = snd_soc_dapm_new_controls(&card->dapm, realtek_4spk_widgets,
202 						num_codecs);
203 		if (ret) {
204 			dev_err(rtd->dev, "fail to add rt1011 widgets, ret %d\n",
205 				ret);
206 			return ret;
207 		}
208 
209 		ret = snd_soc_add_card_controls(card, realtek_4spk_kcontrols,
210 						num_codecs);
211 		if (ret) {
212 			dev_err(rtd->dev, "fail to add rt1011 controls, ret %d\n",
213 				ret);
214 			return ret;
215 		}
216 
217 		ret = snd_soc_dapm_add_routes(&card->dapm, rt1011_4spk_routes,
218 					      num_codecs);
219 		if (ret) {
220 			dev_err(rtd->dev, "fail to add rt1011 routes, ret %d\n",
221 				ret);
222 			return ret;
223 		}
224 		break;
225 	default:
226 		dev_err(rtd->dev, "rt1011: invalid num_codecs %d\n", num_codecs);
227 		return -EINVAL;
228 	}
229 
230 	return ret;
231 }
232 
233 void sof_rt1011_dai_link(struct device *dev, struct snd_soc_dai_link *link)
234 {
235 	unsigned int num_codecs = get_num_codecs(RT1011_ACPI_HID);
236 
237 	link->codecs = rt1011_dai_link_components;
238 
239 	switch (num_codecs) {
240 	case 2:
241 	case 4:
242 		link->num_codecs = num_codecs;
243 		break;
244 	default:
245 		dev_err(dev, "rt1011: invalid num_codecs %d\n", num_codecs);
246 		break;
247 	}
248 
249 	link->init = rt1011_init;
250 	link->ops = &rt1011_ops;
251 }
252 EXPORT_SYMBOL_NS(sof_rt1011_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
253 
254 void sof_rt1011_codec_conf(struct device *dev, struct snd_soc_card *card)
255 {
256 	unsigned int num_codecs = get_num_codecs(RT1011_ACPI_HID);
257 
258 	switch (num_codecs) {
259 	case 2:
260 		if (soc_intel_is_cml()) {
261 			/*
262 			 * use name prefix 'WL' and 'WR' for speaker widgets to
263 			 * keep backward compatible with cml devices
264 			 */
265 			card->codec_conf = rt1011_4spk_codec_confs;
266 		} else {
267 			card->codec_conf = rt1011_2spk_codec_confs;
268 		}
269 
270 		card->num_configs = num_codecs;
271 		break;
272 	case 4:
273 		card->codec_conf = rt1011_4spk_codec_confs;
274 		card->num_configs = ARRAY_SIZE(rt1011_4spk_codec_confs);
275 		break;
276 	default:
277 		dev_err(dev, "rt1011: invalid num_codecs %d\n", num_codecs);
278 		break;
279 	}
280 
281 }
282 EXPORT_SYMBOL_NS(sof_rt1011_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON);
283 
284 /*
285  * rt1015:  i2c mode driver for ALC1015 and ALC1015Q
286  * rt1015p: auto-mode driver for ALC1015, ALC1015Q, and ALC1015Q-VB
287  *
288  * For stereo output, there are always two amplifiers on the board.
289  * However, the ACPI implements only one device instance (UID=0) if they
290  * are sharing the same enable pin. The code will detect the number of
291  * device instance and use corresponding DAPM structures for
292  * initialization.
293  */
294 static const struct snd_soc_dapm_route rt1015p_1dev_dapm_routes[] = {
295 	/* speaker */
296 	{ "Left Spk", NULL, "Speaker" },
297 	{ "Right Spk", NULL, "Speaker" },
298 };
299 
300 static const struct snd_soc_dapm_route rt1015p_2dev_dapm_routes[] = {
301 	/* speaker */
302 	{ "Left Spk", NULL, "Left Speaker" },
303 	{ "Right Spk", NULL, "Right Speaker" },
304 };
305 
306 static struct snd_soc_codec_conf rt1015p_codec_confs[] = {
307 	{
308 		.dlc = COMP_CODEC_CONF(RT1015P_DEV0_NAME),
309 		.name_prefix = "Left",
310 	},
311 	{
312 		.dlc = COMP_CODEC_CONF(RT1015P_DEV1_NAME),
313 		.name_prefix = "Right",
314 	},
315 };
316 
317 static struct snd_soc_dai_link_component rt1015p_dai_link_components[] = {
318 	{
319 		.name = RT1015P_DEV0_NAME,
320 		.dai_name = RT1015P_CODEC_DAI,
321 	},
322 	{
323 		.name = RT1015P_DEV1_NAME,
324 		.dai_name = RT1015P_CODEC_DAI,
325 	},
326 };
327 
328 static int rt1015p_get_num_codecs(void)
329 {
330 	static int dev_num;
331 
332 	if (dev_num)
333 		return dev_num;
334 
335 	if (!acpi_dev_present("RTL1015", "1", -1))
336 		dev_num = 1;
337 	else
338 		dev_num = 2;
339 
340 	return dev_num;
341 }
342 
343 static int rt1015p_hw_params(struct snd_pcm_substream *substream,
344 			     struct snd_pcm_hw_params *params)
345 {
346 	/* reserved for debugging purpose */
347 
348 	return 0;
349 }
350 
351 static const struct snd_soc_ops rt1015p_ops = {
352 	.hw_params = rt1015p_hw_params,
353 };
354 
355 static int rt1015p_init(struct snd_soc_pcm_runtime *rtd)
356 {
357 	struct snd_soc_card *card = rtd->card;
358 	int ret;
359 
360 	if (rt1015p_get_num_codecs() == 1)
361 		ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_1dev_dapm_routes,
362 					      ARRAY_SIZE(rt1015p_1dev_dapm_routes));
363 	else
364 		ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_2dev_dapm_routes,
365 					      ARRAY_SIZE(rt1015p_2dev_dapm_routes));
366 	if (ret)
367 		dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
368 	return ret;
369 }
370 
371 void sof_rt1015p_dai_link(struct snd_soc_dai_link *link)
372 {
373 	link->codecs = rt1015p_dai_link_components;
374 	link->num_codecs = rt1015p_get_num_codecs();
375 	link->init = rt1015p_init;
376 	link->ops = &rt1015p_ops;
377 }
378 EXPORT_SYMBOL_NS(sof_rt1015p_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
379 
380 void sof_rt1015p_codec_conf(struct snd_soc_card *card)
381 {
382 	if (rt1015p_get_num_codecs() == 1)
383 		return;
384 
385 	card->codec_conf = rt1015p_codec_confs;
386 	card->num_configs = ARRAY_SIZE(rt1015p_codec_confs);
387 }
388 EXPORT_SYMBOL_NS(sof_rt1015p_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON);
389 
390 /*
391  * RT1015 audio amplifier
392  */
393 
394 static const struct {
395 	unsigned int tx;
396 	unsigned int rx;
397 } rt1015_tdm_mask[] = {
398 	{.tx = 0x0, .rx = 0x1},
399 	{.tx = 0x0, .rx = 0x2},
400 };
401 
402 static int rt1015_hw_params(struct snd_pcm_substream *substream,
403 			    struct snd_pcm_hw_params *params)
404 {
405 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
406 	struct snd_soc_dai_link *dai_link = rtd->dai_link;
407 	struct snd_soc_dai *codec_dai;
408 	int i, clk_freq;
409 	int ret = 0;
410 
411 	clk_freq = sof_dai_get_bclk(rtd);
412 
413 	if (clk_freq <= 0) {
414 		dev_err(rtd->dev, "fail to get bclk freq, ret %d\n", clk_freq);
415 		return -EINVAL;
416 	}
417 
418 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
419 		ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
420 					  clk_freq,
421 					  params_rate(params) * 256);
422 		if (ret) {
423 			dev_err(codec_dai->dev, "fail to set pll, ret %d\n",
424 				ret);
425 			return ret;
426 		}
427 
428 		ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL,
429 					     params_rate(params) * 256,
430 					     SND_SOC_CLOCK_IN);
431 		if (ret) {
432 			dev_err(codec_dai->dev, "fail to set sysclk, ret %d\n",
433 				ret);
434 			return ret;
435 		}
436 
437 		switch (dai_link->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
438 		case SND_SOC_DAIFMT_DSP_A:
439 		case SND_SOC_DAIFMT_DSP_B:
440 			/* 4-slot TDM */
441 			ret = snd_soc_dai_set_tdm_slot(codec_dai,
442 						       rt1015_tdm_mask[i].tx,
443 						       rt1015_tdm_mask[i].rx,
444 						       4,
445 						       params_width(params));
446 			if (ret < 0) {
447 				dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n",
448 					ret);
449 				return ret;
450 			}
451 			break;
452 		default:
453 			dev_dbg(codec_dai->dev, "codec is in I2S mode\n");
454 			break;
455 		}
456 	}
457 
458 	return ret;
459 }
460 
461 static struct snd_soc_ops rt1015_ops = {
462 	.hw_params = rt1015_hw_params,
463 };
464 
465 static struct snd_soc_codec_conf rt1015_amp_conf[] = {
466 	{
467 		.dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME),
468 		.name_prefix = "Left",
469 	},
470 	{
471 		.dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME),
472 		.name_prefix = "Right",
473 	},
474 };
475 
476 static struct snd_soc_dai_link_component rt1015_components[] = {
477 	{
478 		.name = RT1015_DEV0_NAME,
479 		.dai_name = RT1015_CODEC_DAI,
480 	},
481 	{
482 		.name = RT1015_DEV1_NAME,
483 		.dai_name = RT1015_CODEC_DAI,
484 	},
485 };
486 
487 static int speaker_codec_init_lr(struct snd_soc_pcm_runtime *rtd)
488 {
489 	return snd_soc_dapm_add_routes(&rtd->card->dapm, speaker_map_lr,
490 					ARRAY_SIZE(speaker_map_lr));
491 }
492 
493 void sof_rt1015_codec_conf(struct snd_soc_card *card)
494 {
495 	card->codec_conf = rt1015_amp_conf;
496 	card->num_configs = ARRAY_SIZE(rt1015_amp_conf);
497 }
498 EXPORT_SYMBOL_NS(sof_rt1015_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON);
499 
500 void sof_rt1015_dai_link(struct snd_soc_dai_link *link)
501 {
502 	link->codecs = rt1015_components;
503 	link->num_codecs = ARRAY_SIZE(rt1015_components);
504 	link->init = speaker_codec_init_lr;
505 	link->ops = &rt1015_ops;
506 }
507 EXPORT_SYMBOL_NS(sof_rt1015_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
508 
509 /*
510  * RT1308 audio amplifier
511  */
512 static const struct snd_kcontrol_new rt1308_kcontrols[] = {
513 	SOC_DAPM_PIN_SWITCH("Speakers"),
514 };
515 
516 static const struct snd_soc_dapm_widget rt1308_dapm_widgets[] = {
517 	SND_SOC_DAPM_SPK("Speakers", NULL),
518 };
519 
520 static const struct snd_soc_dapm_route rt1308_dapm_routes[] = {
521 	/* speaker */
522 	{"Speakers", NULL, "SPOL"},
523 	{"Speakers", NULL, "SPOR"},
524 };
525 
526 static struct snd_soc_dai_link_component rt1308_components[] = {
527 	{
528 		.name = RT1308_DEV0_NAME,
529 		.dai_name = RT1308_CODEC_DAI,
530 	}
531 };
532 
533 static int rt1308_init(struct snd_soc_pcm_runtime *rtd)
534 {
535 	struct snd_soc_card *card = rtd->card;
536 	int ret;
537 
538 	ret = snd_soc_dapm_new_controls(&card->dapm, rt1308_dapm_widgets,
539 					ARRAY_SIZE(rt1308_dapm_widgets));
540 	if (ret) {
541 		dev_err(rtd->dev, "fail to add dapm controls, ret %d\n", ret);
542 		return ret;
543 	}
544 
545 	ret = snd_soc_add_card_controls(card, rt1308_kcontrols,
546 					ARRAY_SIZE(rt1308_kcontrols));
547 	if (ret) {
548 		dev_err(rtd->dev, "fail to add card controls, ret %d\n", ret);
549 		return ret;
550 	}
551 
552 	ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_dapm_routes,
553 				      ARRAY_SIZE(rt1308_dapm_routes));
554 
555 	if (ret)
556 		dev_err(rtd->dev, "fail to add dapm routes, ret %d\n", ret);
557 
558 	return ret;
559 }
560 
561 static int rt1308_hw_params(struct snd_pcm_substream *substream,
562 			    struct snd_pcm_hw_params *params)
563 {
564 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
565 	struct snd_soc_card *card = rtd->card;
566 	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
567 	int clk_id, clk_freq, pll_out;
568 	int ret;
569 
570 	clk_id = RT1308_PLL_S_MCLK;
571 	/* get the tplg configured mclk. */
572 	clk_freq = sof_dai_get_mclk(rtd);
573 
574 	pll_out = params_rate(params) * 512;
575 
576 	/* Set rt1308 pll */
577 	ret = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out);
578 	if (ret < 0) {
579 		dev_err(card->dev, "Failed to set RT1308 PLL: %d\n", ret);
580 		return ret;
581 	}
582 
583 	/* Set rt1308 sysclk */
584 	ret = snd_soc_dai_set_sysclk(codec_dai, RT1308_FS_SYS_S_PLL, pll_out,
585 				     SND_SOC_CLOCK_IN);
586 	if (ret < 0)
587 		dev_err(card->dev, "Failed to set RT1308 SYSCLK: %d\n", ret);
588 
589 	return ret;
590 }
591 
592 static const struct snd_soc_ops rt1308_ops = {
593 	.hw_params = rt1308_hw_params,
594 };
595 
596 void sof_rt1308_dai_link(struct snd_soc_dai_link *link)
597 {
598 	link->codecs = rt1308_components;
599 	link->num_codecs = ARRAY_SIZE(rt1308_components);
600 	link->init = rt1308_init;
601 	link->ops = &rt1308_ops;
602 }
603 EXPORT_SYMBOL_NS(sof_rt1308_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
604 
605 /*
606  * 2-amp Configuration for RT1019
607  */
608 
609 static const struct snd_soc_dapm_route rt1019p_dapm_routes[] = {
610 	/* speaker */
611 	{ "Left Spk", NULL, "Speaker" },
612 	{ "Right Spk", NULL, "Speaker" },
613 };
614 
615 static struct snd_soc_dai_link_component rt1019p_components[] = {
616 	{
617 		.name = RT1019P_DEV0_NAME,
618 		.dai_name = RT1019P_CODEC_DAI,
619 	},
620 };
621 
622 static int rt1019p_init(struct snd_soc_pcm_runtime *rtd)
623 {
624 	struct snd_soc_card *card = rtd->card;
625 	int ret;
626 
627 	ret = snd_soc_dapm_add_routes(&card->dapm, rt1019p_dapm_routes,
628 				      ARRAY_SIZE(rt1019p_dapm_routes));
629 	if (ret) {
630 		dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
631 		return ret;
632 	}
633 	return ret;
634 }
635 
636 void sof_rt1019p_dai_link(struct snd_soc_dai_link *link)
637 {
638 	link->codecs = rt1019p_components;
639 	link->num_codecs = ARRAY_SIZE(rt1019p_components);
640 	link->init = rt1019p_init;
641 }
642 EXPORT_SYMBOL_NS(sof_rt1019p_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
643 
644 MODULE_DESCRIPTION("ASoC Intel SOF Realtek helpers");
645 MODULE_LICENSE("GPL");
646