• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2020 Intel Corporation
3 
4 /*
5  *  sof_sdw - ASOC Machine driver for Intel SoundWire platforms
6  */
7 
8 #include <linux/device.h>
9 #include <linux/dmi.h>
10 #include <linux/module.h>
11 #include <linux/soundwire/sdw.h>
12 #include <linux/soundwire/sdw_type.h>
13 #include <sound/soc.h>
14 #include <sound/soc-acpi.h>
15 #include "sof_sdw_common.h"
16 
17 unsigned long sof_sdw_quirk = SOF_RT711_JD_SRC_JD1;
18 static int quirk_override = -1;
19 module_param_named(quirk, quirk_override, int, 0444);
20 MODULE_PARM_DESC(quirk, "Board-specific quirk override");
21 
22 #define INC_ID(BE, CPU, LINK)	do { (BE)++; (CPU)++; (LINK)++; } while (0)
23 
log_quirks(struct device * dev)24 static void log_quirks(struct device *dev)
25 {
26 	if (SOF_RT711_JDSRC(sof_sdw_quirk))
27 		dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
28 			SOF_RT711_JDSRC(sof_sdw_quirk));
29 	if (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
30 		dev_dbg(dev, "quirk SOF_SDW_FOUR_SPK enabled\n");
31 	if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
32 		dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n");
33 	if (sof_sdw_quirk & SOF_SDW_PCH_DMIC)
34 		dev_dbg(dev, "quirk SOF_SDW_PCH_DMIC enabled\n");
35 	if (SOF_SSP_GET_PORT(sof_sdw_quirk))
36 		dev_dbg(dev, "SSP port %ld\n",
37 			SOF_SSP_GET_PORT(sof_sdw_quirk));
38 	if (sof_sdw_quirk & SOF_RT715_DAI_ID_FIX)
39 		dev_dbg(dev, "quirk SOF_RT715_DAI_ID_FIX enabled\n");
40 	if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION)
41 		dev_dbg(dev, "quirk SOF_SDW_NO_AGGREGATION enabled\n");
42 }
43 
sof_sdw_quirk_cb(const struct dmi_system_id * id)44 static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
45 {
46 	sof_sdw_quirk = (unsigned long)id->driver_data;
47 	return 1;
48 }
49 
50 static const struct dmi_system_id sof_sdw_quirk_table[] = {
51 	/* CometLake devices */
52 	{
53 		.callback = sof_sdw_quirk_cb,
54 		.matches = {
55 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
56 			DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
57 		},
58 		.driver_data = (void *)SOF_SDW_PCH_DMIC,
59 	},
60 	{
61 		.callback = sof_sdw_quirk_cb,
62 		.matches = {
63 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
64 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
65 		},
66 		.driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
67 					SOF_RT715_DAI_ID_FIX),
68 	},
69 	{
70 		/* early version of SKU 09C6 */
71 		.callback = sof_sdw_quirk_cb,
72 		.matches = {
73 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
74 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
75 		},
76 		.driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
77 					SOF_RT715_DAI_ID_FIX),
78 	},
79 	{
80 		.callback = sof_sdw_quirk_cb,
81 		.matches = {
82 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
83 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
84 		},
85 		.driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
86 					SOF_RT715_DAI_ID_FIX |
87 					SOF_SDW_FOUR_SPK),
88 	},
89 	{
90 		.callback = sof_sdw_quirk_cb,
91 		.matches = {
92 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
93 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
94 		},
95 		.driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
96 					SOF_RT715_DAI_ID_FIX |
97 					SOF_SDW_FOUR_SPK),
98 	},
99 	/* IceLake devices */
100 	{
101 		.callback = sof_sdw_quirk_cb,
102 		.matches = {
103 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
104 			DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
105 		},
106 		.driver_data = (void *)SOF_SDW_PCH_DMIC,
107 	},
108 	/* TigerLake devices */
109 	{
110 		.callback = sof_sdw_quirk_cb,
111 		.matches = {
112 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
113 			DMI_MATCH(DMI_PRODUCT_NAME,
114 				  "Tiger Lake Client Platform"),
115 		},
116 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
117 					SOF_RT711_JD_SRC_JD1 |
118 					SOF_SDW_PCH_DMIC |
119 					SOF_SSP_PORT(SOF_I2S_SSP2)),
120 	},
121 	{
122 		.callback = sof_sdw_quirk_cb,
123 		.matches = {
124 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
125 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
126 		},
127 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
128 					SOF_RT711_JD_SRC_JD2 |
129 					SOF_RT715_DAI_ID_FIX),
130 	},
131 	{
132 		.callback = sof_sdw_quirk_cb,
133 		.matches = {
134 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
135 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
136 		},
137 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
138 					SOF_RT711_JD_SRC_JD2 |
139 					SOF_RT715_DAI_ID_FIX |
140 					SOF_SDW_FOUR_SPK),
141 	},
142 	{
143 		.callback = sof_sdw_quirk_cb,
144 		.matches = {
145 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
146 			DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"),
147 		},
148 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
149 					SOF_SDW_PCH_DMIC |
150 					SOF_SDW_FOUR_SPK),
151 	},
152 	{
153 		.callback = sof_sdw_quirk_cb,
154 		.matches = {
155 			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
156 			DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"),
157 		},
158 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
159 					SOF_SDW_PCH_DMIC |
160 					SOF_SDW_FOUR_SPK),
161 	},
162 	{
163 		/*
164 		 * this entry covers multiple HP SKUs. The family name
165 		 * does not seem robust enough, so we use a partial
166 		 * match that ignores the product name suffix
167 		 * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx)
168 		 */
169 		.callback = sof_sdw_quirk_cb,
170 		.matches = {
171 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
172 			DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible"),
173 		},
174 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
175 					SOF_SDW_PCH_DMIC |
176 					SOF_RT711_JD_SRC_JD2),
177 	},
178 	/* TigerLake-SDCA devices */
179 	{
180 		.callback = sof_sdw_quirk_cb,
181 		.matches = {
182 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
183 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
184 		},
185 		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
186 					SOF_RT711_JD_SRC_JD2 |
187 					SOF_RT715_DAI_ID_FIX |
188 					SOF_SDW_FOUR_SPK),
189 	},
190 	/* AlderLake devices */
191 	{
192 		.callback = sof_sdw_quirk_cb,
193 		.matches = {
194 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
195 			DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
196 		},
197 		.driver_data = (void *)(SOF_RT711_JD_SRC_JD1 |
198 					SOF_SDW_TGL_HDMI |
199 					SOF_RT715_DAI_ID_FIX |
200 					SOF_SDW_PCH_DMIC),
201 	},
202 	{}
203 };
204 
205 static struct snd_soc_dai_link_component dmic_component[] = {
206 	{
207 		.name = "dmic-codec",
208 		.dai_name = "dmic-hifi",
209 	}
210 };
211 
212 static struct snd_soc_dai_link_component platform_component[] = {
213 	{
214 		/* name might be overridden during probe */
215 		.name = "0000:00:1f.3"
216 	}
217 };
218 
219 /* these wrappers are only needed to avoid typecast compilation errors */
sdw_startup(struct snd_pcm_substream * substream)220 int sdw_startup(struct snd_pcm_substream *substream)
221 {
222 	return sdw_startup_stream(substream);
223 }
224 
sdw_prepare(struct snd_pcm_substream * substream)225 int sdw_prepare(struct snd_pcm_substream *substream)
226 {
227 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
228 	struct sdw_stream_runtime *sdw_stream;
229 	struct snd_soc_dai *dai;
230 
231 	/* Find stream from first CPU DAI */
232 	dai = asoc_rtd_to_cpu(rtd, 0);
233 
234 	sdw_stream = snd_soc_dai_get_sdw_stream(dai, substream->stream);
235 
236 	if (IS_ERR(sdw_stream)) {
237 		dev_err(rtd->dev, "no stream found for DAI %s", dai->name);
238 		return PTR_ERR(sdw_stream);
239 	}
240 
241 	return sdw_prepare_stream(sdw_stream);
242 }
243 
sdw_trigger(struct snd_pcm_substream * substream,int cmd)244 int sdw_trigger(struct snd_pcm_substream *substream, int cmd)
245 {
246 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
247 	struct sdw_stream_runtime *sdw_stream;
248 	struct snd_soc_dai *dai;
249 	int ret;
250 
251 	/* Find stream from first CPU DAI */
252 	dai = asoc_rtd_to_cpu(rtd, 0);
253 
254 	sdw_stream = snd_soc_dai_get_sdw_stream(dai, substream->stream);
255 
256 	if (IS_ERR(sdw_stream)) {
257 		dev_err(rtd->dev, "no stream found for DAI %s", dai->name);
258 		return PTR_ERR(sdw_stream);
259 	}
260 
261 	switch (cmd) {
262 	case SNDRV_PCM_TRIGGER_START:
263 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
264 	case SNDRV_PCM_TRIGGER_RESUME:
265 		ret = sdw_enable_stream(sdw_stream);
266 		break;
267 
268 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
269 	case SNDRV_PCM_TRIGGER_SUSPEND:
270 	case SNDRV_PCM_TRIGGER_STOP:
271 		ret = sdw_disable_stream(sdw_stream);
272 		break;
273 	default:
274 		ret = -EINVAL;
275 		break;
276 	}
277 
278 	if (ret)
279 		dev_err(rtd->dev, "%s trigger %d failed: %d", __func__, cmd, ret);
280 
281 	return ret;
282 }
283 
sdw_hw_free(struct snd_pcm_substream * substream)284 int sdw_hw_free(struct snd_pcm_substream *substream)
285 {
286 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
287 	struct sdw_stream_runtime *sdw_stream;
288 	struct snd_soc_dai *dai;
289 
290 	/* Find stream from first CPU DAI */
291 	dai = asoc_rtd_to_cpu(rtd, 0);
292 
293 	sdw_stream = snd_soc_dai_get_sdw_stream(dai, substream->stream);
294 
295 	if (IS_ERR(sdw_stream)) {
296 		dev_err(rtd->dev, "no stream found for DAI %s", dai->name);
297 		return PTR_ERR(sdw_stream);
298 	}
299 
300 	return sdw_deprepare_stream(sdw_stream);
301 }
302 
sdw_shutdown(struct snd_pcm_substream * substream)303 void sdw_shutdown(struct snd_pcm_substream *substream)
304 {
305 	sdw_shutdown_stream(substream);
306 }
307 
308 static const struct snd_soc_ops sdw_ops = {
309 	.startup = sdw_startup,
310 	.prepare = sdw_prepare,
311 	.trigger = sdw_trigger,
312 	.hw_free = sdw_hw_free,
313 	.shutdown = sdw_shutdown,
314 };
315 
316 static struct sof_sdw_codec_info codec_info_list[] = {
317 	{
318 		.part_id = 0x700,
319 		.direction = {true, true},
320 		.dai_name = "rt700-aif1",
321 		.init = sof_sdw_rt700_init,
322 	},
323 	{
324 		.part_id = 0x711,
325 		.version_id = 3,
326 		.direction = {true, true},
327 		.dai_name = "rt711-sdca-aif1",
328 		.init = sof_sdw_rt711_sdca_init,
329 		.exit = sof_sdw_rt711_sdca_exit,
330 	},
331 	{
332 		.part_id = 0x711,
333 		.version_id = 2,
334 		.direction = {true, true},
335 		.dai_name = "rt711-aif1",
336 		.init = sof_sdw_rt711_init,
337 		.exit = sof_sdw_rt711_exit,
338 	},
339 	{
340 		.part_id = 0x1308,
341 		.acpi_id = "10EC1308",
342 		.direction = {true, false},
343 		.dai_name = "rt1308-aif",
344 		.ops = &sof_sdw_rt1308_i2s_ops,
345 		.init = sof_sdw_rt1308_init,
346 	},
347 	{
348 		.part_id = 0x1316,
349 		.direction = {true, true},
350 		.dai_name = "rt1316-aif",
351 		.init = sof_sdw_rt1316_init,
352 	},
353 	{
354 		.part_id = 0x714,
355 		.version_id = 3,
356 		.direction = {false, true},
357 		.ignore_pch_dmic = true,
358 		.dai_name = "rt715-aif2",
359 		.init = sof_sdw_rt715_sdca_init,
360 	},
361 	{
362 		.part_id = 0x715,
363 		.version_id = 3,
364 		.direction = {false, true},
365 		.ignore_pch_dmic = true,
366 		.dai_name = "rt715-aif2",
367 		.init = sof_sdw_rt715_sdca_init,
368 	},
369 	{
370 		.part_id = 0x714,
371 		.version_id = 2,
372 		.direction = {false, true},
373 		.ignore_pch_dmic = true,
374 		.dai_name = "rt715-aif2",
375 		.init = sof_sdw_rt715_init,
376 	},
377 	{
378 		.part_id = 0x715,
379 		.version_id = 2,
380 		.direction = {false, true},
381 		.ignore_pch_dmic = true,
382 		.dai_name = "rt715-aif2",
383 		.init = sof_sdw_rt715_init,
384 	},
385 	{
386 		.part_id = 0x8373,
387 		.direction = {true, true},
388 		.dai_name = "max98373-aif1",
389 		.init = sof_sdw_mx8373_init,
390 		.codec_card_late_probe = sof_sdw_mx8373_late_probe,
391 	},
392 	{
393 		.part_id = 0x5682,
394 		.direction = {true, true},
395 		.dai_name = "rt5682-sdw",
396 		.init = sof_sdw_rt5682_init,
397 	},
398 };
399 
find_codec_info_part(u64 adr)400 static inline int find_codec_info_part(u64 adr)
401 {
402 	unsigned int part_id, sdw_version;
403 	int i;
404 
405 	part_id = SDW_PART_ID(adr);
406 	sdw_version = SDW_VERSION(adr);
407 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
408 		/*
409 		 * A codec info is for all sdw version with the part id if
410 		 * version_id is not specified in the codec info.
411 		 */
412 		if (part_id == codec_info_list[i].part_id &&
413 		    (!codec_info_list[i].version_id ||
414 		     sdw_version == codec_info_list[i].version_id))
415 			return i;
416 
417 	return -EINVAL;
418 
419 }
420 
find_codec_info_acpi(const u8 * acpi_id)421 static inline int find_codec_info_acpi(const u8 *acpi_id)
422 {
423 	int i;
424 
425 	if (!acpi_id[0])
426 		return -EINVAL;
427 
428 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
429 		if (!memcmp(codec_info_list[i].acpi_id, acpi_id,
430 			    ACPI_ID_LEN))
431 			break;
432 
433 	if (i == ARRAY_SIZE(codec_info_list))
434 		return -EINVAL;
435 
436 	return i;
437 }
438 
439 /*
440  * get BE dailink number and CPU DAI number based on sdw link adr.
441  * Since some sdw slaves may be aggregated, the CPU DAI number
442  * may be larger than the number of BE dailinks.
443  */
get_sdw_dailink_info(const struct snd_soc_acpi_link_adr * links,int * sdw_be_num,int * sdw_cpu_dai_num)444 static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links,
445 				int *sdw_be_num, int *sdw_cpu_dai_num)
446 {
447 	const struct snd_soc_acpi_link_adr *link;
448 	bool group_visited[SDW_MAX_GROUPS];
449 	bool no_aggregation;
450 	int i;
451 
452 	no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
453 	*sdw_cpu_dai_num = 0;
454 	*sdw_be_num  = 0;
455 
456 	if (!links)
457 		return -EINVAL;
458 
459 	for (i = 0; i < SDW_MAX_GROUPS; i++)
460 		group_visited[i] = false;
461 
462 	for (link = links; link->num_adr; link++) {
463 		const struct snd_soc_acpi_endpoint *endpoint;
464 		int codec_index;
465 		int stream;
466 		u64 adr;
467 
468 		adr = link->adr_d->adr;
469 		codec_index = find_codec_info_part(adr);
470 		if (codec_index < 0)
471 			return codec_index;
472 
473 		endpoint = link->adr_d->endpoints;
474 
475 		/* count DAI number for playback and capture */
476 		for_each_pcm_streams(stream) {
477 			if (!codec_info_list[codec_index].direction[stream])
478 				continue;
479 
480 			(*sdw_cpu_dai_num)++;
481 
482 			/* count BE for each non-aggregated slave or group */
483 			if (!endpoint->aggregated || no_aggregation ||
484 			    !group_visited[endpoint->group_id])
485 				(*sdw_be_num)++;
486 		}
487 
488 		if (endpoint->aggregated)
489 			group_visited[endpoint->group_id] = true;
490 	}
491 
492 	return 0;
493 }
494 
init_dai_link(struct snd_soc_dai_link * dai_links,int be_id,char * name,int playback,int capture,struct snd_soc_dai_link_component * cpus,int cpus_num,struct snd_soc_dai_link_component * codecs,int codecs_num,int (* init)(struct snd_soc_pcm_runtime * rtd),const struct snd_soc_ops * ops)495 static void init_dai_link(struct snd_soc_dai_link *dai_links, int be_id,
496 			  char *name, int playback, int capture,
497 			  struct snd_soc_dai_link_component *cpus,
498 			  int cpus_num,
499 			  struct snd_soc_dai_link_component *codecs,
500 			  int codecs_num,
501 			  int (*init)(struct snd_soc_pcm_runtime *rtd),
502 			  const struct snd_soc_ops *ops)
503 {
504 	dai_links->id = be_id;
505 	dai_links->name = name;
506 	dai_links->platforms = platform_component;
507 	dai_links->num_platforms = ARRAY_SIZE(platform_component);
508 	dai_links->nonatomic = true;
509 	dai_links->no_pcm = 1;
510 	dai_links->cpus = cpus;
511 	dai_links->num_cpus = cpus_num;
512 	dai_links->codecs = codecs;
513 	dai_links->num_codecs = codecs_num;
514 	dai_links->dpcm_playback = playback;
515 	dai_links->dpcm_capture = capture;
516 	dai_links->init = init;
517 	dai_links->ops = ops;
518 }
519 
is_unique_device(const struct snd_soc_acpi_link_adr * link,unsigned int sdw_version,unsigned int mfg_id,unsigned int part_id,unsigned int class_id,int index_in_link)520 static bool is_unique_device(const struct snd_soc_acpi_link_adr *link,
521 			     unsigned int sdw_version,
522 			     unsigned int mfg_id,
523 			     unsigned int part_id,
524 			     unsigned int class_id,
525 			     int index_in_link
526 			    )
527 {
528 	int i;
529 
530 	for (i = 0; i < link->num_adr; i++) {
531 		unsigned int sdw1_version, mfg1_id, part1_id, class1_id;
532 		u64 adr;
533 
534 		/* skip itself */
535 		if (i == index_in_link)
536 			continue;
537 
538 		adr = link->adr_d[i].adr;
539 
540 		sdw1_version = SDW_VERSION(adr);
541 		mfg1_id = SDW_MFG_ID(adr);
542 		part1_id = SDW_PART_ID(adr);
543 		class1_id = SDW_CLASS_ID(adr);
544 
545 		if (sdw_version == sdw1_version &&
546 		    mfg_id == mfg1_id &&
547 		    part_id == part1_id &&
548 		    class_id == class1_id)
549 			return false;
550 	}
551 
552 	return true;
553 }
554 
create_codec_dai_name(struct device * dev,const struct snd_soc_acpi_link_adr * link,struct snd_soc_dai_link_component * codec,int offset,struct snd_soc_codec_conf * codec_conf,int codec_count,int * codec_conf_index)555 static int create_codec_dai_name(struct device *dev,
556 				 const struct snd_soc_acpi_link_adr *link,
557 				 struct snd_soc_dai_link_component *codec,
558 				 int offset,
559 				 struct snd_soc_codec_conf *codec_conf,
560 				 int codec_count,
561 				 int *codec_conf_index)
562 {
563 	int i;
564 
565 	/* sanity check */
566 	if (*codec_conf_index + link->num_adr > codec_count) {
567 		dev_err(dev, "codec_conf: out-of-bounds access requested\n");
568 		return -EINVAL;
569 	}
570 
571 	for (i = 0; i < link->num_adr; i++) {
572 		unsigned int sdw_version, unique_id, mfg_id;
573 		unsigned int link_id, part_id, class_id;
574 		int codec_index, comp_index;
575 		char *codec_str;
576 		u64 adr;
577 
578 		adr = link->adr_d[i].adr;
579 
580 		sdw_version = SDW_VERSION(adr);
581 		link_id = SDW_DISCO_LINK_ID(adr);
582 		unique_id = SDW_UNIQUE_ID(adr);
583 		mfg_id = SDW_MFG_ID(adr);
584 		part_id = SDW_PART_ID(adr);
585 		class_id = SDW_CLASS_ID(adr);
586 
587 		comp_index = i + offset;
588 		if (is_unique_device(link, sdw_version, mfg_id, part_id,
589 				     class_id, i)) {
590 			codec_str = "sdw:%x:%x:%x:%x";
591 			codec[comp_index].name =
592 				devm_kasprintf(dev, GFP_KERNEL, codec_str,
593 					       link_id, mfg_id, part_id,
594 					       class_id);
595 		} else {
596 			codec_str = "sdw:%x:%x:%x:%x:%x";
597 			codec[comp_index].name =
598 				devm_kasprintf(dev, GFP_KERNEL, codec_str,
599 					       link_id, mfg_id, part_id,
600 					       class_id, unique_id);
601 		}
602 
603 		if (!codec[comp_index].name)
604 			return -ENOMEM;
605 
606 		codec_index = find_codec_info_part(adr);
607 		if (codec_index < 0)
608 			return codec_index;
609 
610 		codec[comp_index].dai_name =
611 			codec_info_list[codec_index].dai_name;
612 
613 		codec_conf[*codec_conf_index].dlc = codec[comp_index];
614 		codec_conf[*codec_conf_index].name_prefix = link->adr_d[i].name_prefix;
615 
616 		++*codec_conf_index;
617 	}
618 
619 	return 0;
620 }
621 
set_codec_init_func(const struct snd_soc_acpi_link_adr * link,struct snd_soc_dai_link * dai_links,bool playback,int group_id)622 static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link,
623 			       struct snd_soc_dai_link *dai_links,
624 			       bool playback, int group_id)
625 {
626 	int i;
627 
628 	do {
629 		/*
630 		 * Initialize the codec. If codec is part of an aggregated
631 		 * group (group_id>0), initialize all codecs belonging to
632 		 * same group.
633 		 */
634 		for (i = 0; i < link->num_adr; i++) {
635 			int codec_index;
636 
637 			codec_index = find_codec_info_part(link->adr_d[i].adr);
638 
639 			if (codec_index < 0)
640 				return codec_index;
641 			/* The group_id is > 0 iff the codec is aggregated */
642 			if (link->adr_d[i].endpoints->group_id != group_id)
643 				continue;
644 			if (codec_info_list[codec_index].init)
645 				codec_info_list[codec_index].init(link,
646 						dai_links,
647 						&codec_info_list[codec_index],
648 						playback);
649 		}
650 		link++;
651 	} while (link->mask && group_id);
652 
653 	return 0;
654 }
655 
656 /*
657  * check endpoint status in slaves and gather link ID for all slaves in
658  * the same group to generate different CPU DAI. Now only support
659  * one sdw link with all slaves set with only single group id.
660  *
661  * one slave on one sdw link with aggregated = 0
662  * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI
663  *
664  * two or more slaves on one sdw link with aggregated = 0
665  * one sdw BE DAI  <---> one-cpu DAI <---> multi-codec DAIs
666  *
667  * multiple links with multiple slaves with aggregated = 1
668  * one sdw BE DAI  <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs
669  */
get_slave_info(const struct snd_soc_acpi_link_adr * adr_link,struct device * dev,int * cpu_dai_id,int * cpu_dai_num,int * codec_num,int * group_id,bool * group_generated)670 static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
671 			  struct device *dev, int *cpu_dai_id, int *cpu_dai_num,
672 			  int *codec_num, int *group_id,
673 			  bool *group_generated)
674 {
675 	const struct snd_soc_acpi_adr_device *adr_d;
676 	const struct snd_soc_acpi_link_adr *adr_next;
677 	bool no_aggregation;
678 	int index = 0;
679 
680 	no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
681 	*codec_num = adr_link->num_adr;
682 	adr_d = adr_link->adr_d;
683 
684 	/* make sure the link mask has a single bit set */
685 	if (!is_power_of_2(adr_link->mask))
686 		return -EINVAL;
687 
688 	cpu_dai_id[index++] = ffs(adr_link->mask) - 1;
689 	if (!adr_d->endpoints->aggregated || no_aggregation) {
690 		*cpu_dai_num = 1;
691 		*group_id = 0;
692 		return 0;
693 	}
694 
695 	*group_id = adr_d->endpoints->group_id;
696 
697 	/* gather other link ID of slaves in the same group */
698 	for (adr_next = adr_link + 1; adr_next && adr_next->num_adr;
699 		adr_next++) {
700 		const struct snd_soc_acpi_endpoint *endpoint;
701 
702 		endpoint = adr_next->adr_d->endpoints;
703 		if (!endpoint->aggregated ||
704 		    endpoint->group_id != *group_id)
705 			continue;
706 
707 		/* make sure the link mask has a single bit set */
708 		if (!is_power_of_2(adr_next->mask))
709 			return -EINVAL;
710 
711 		if (index >= SDW_MAX_CPU_DAIS) {
712 			dev_err(dev, " cpu_dai_id array overflows");
713 			return -EINVAL;
714 		}
715 
716 		cpu_dai_id[index++] = ffs(adr_next->mask) - 1;
717 		*codec_num += adr_next->num_adr;
718 	}
719 
720 	/*
721 	 * indicate CPU DAIs for this group have been generated
722 	 * to avoid generating CPU DAIs for this group again.
723 	 */
724 	group_generated[*group_id] = true;
725 	*cpu_dai_num = index;
726 
727 	return 0;
728 }
729 
create_sdw_dailink(struct device * dev,int * be_index,struct snd_soc_dai_link * dai_links,int sdw_be_num,int sdw_cpu_dai_num,struct snd_soc_dai_link_component * cpus,const struct snd_soc_acpi_link_adr * link,int * cpu_id,bool * group_generated,struct snd_soc_codec_conf * codec_conf,int codec_count,int * codec_conf_index,bool * ignore_pch_dmic)730 static int create_sdw_dailink(struct device *dev, int *be_index,
731 			      struct snd_soc_dai_link *dai_links,
732 			      int sdw_be_num, int sdw_cpu_dai_num,
733 			      struct snd_soc_dai_link_component *cpus,
734 			      const struct snd_soc_acpi_link_adr *link,
735 			      int *cpu_id, bool *group_generated,
736 			      struct snd_soc_codec_conf *codec_conf,
737 			      int codec_count,
738 			      int *codec_conf_index,
739 			      bool *ignore_pch_dmic)
740 {
741 	const struct snd_soc_acpi_link_adr *link_next;
742 	struct snd_soc_dai_link_component *codecs;
743 	int cpu_dai_id[SDW_MAX_CPU_DAIS];
744 	int cpu_dai_num, cpu_dai_index;
745 	unsigned int group_id;
746 	int codec_idx = 0;
747 	int i = 0, j = 0;
748 	int codec_index;
749 	int codec_num;
750 	int stream;
751 	int ret;
752 	int k;
753 
754 	ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num,
755 			     &group_id, group_generated);
756 	if (ret)
757 		return ret;
758 
759 	codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL);
760 	if (!codecs)
761 		return -ENOMEM;
762 
763 	/* generate codec name on different links in the same group */
764 	for (link_next = link; link_next && link_next->num_adr &&
765 	     i < cpu_dai_num; link_next++) {
766 		const struct snd_soc_acpi_endpoint *endpoints;
767 
768 		endpoints = link_next->adr_d->endpoints;
769 		if (group_id && (!endpoints->aggregated ||
770 				 endpoints->group_id != group_id))
771 			continue;
772 
773 		/* skip the link excluded by this processed group */
774 		if (cpu_dai_id[i] != ffs(link_next->mask) - 1)
775 			continue;
776 
777 		ret = create_codec_dai_name(dev, link_next, codecs, codec_idx,
778 					    codec_conf, codec_count, codec_conf_index);
779 		if (ret < 0)
780 			return ret;
781 
782 		/* check next link to create codec dai in the processed group */
783 		i++;
784 		codec_idx += link_next->num_adr;
785 	}
786 
787 	/* find codec info to create BE DAI */
788 	codec_index = find_codec_info_part(link->adr_d[0].adr);
789 	if (codec_index < 0)
790 		return codec_index;
791 
792 	if (codec_info_list[codec_index].ignore_pch_dmic)
793 		*ignore_pch_dmic = true;
794 
795 	cpu_dai_index = *cpu_id;
796 	for_each_pcm_streams(stream) {
797 		char *name, *cpu_name;
798 		int playback, capture;
799 		static const char * const sdw_stream_name[] = {
800 			"SDW%d-Playback",
801 			"SDW%d-Capture",
802 		};
803 
804 		if (!codec_info_list[codec_index].direction[stream])
805 			continue;
806 
807 		/* create stream name according to first link id */
808 		name = devm_kasprintf(dev, GFP_KERNEL,
809 				      sdw_stream_name[stream], cpu_dai_id[0]);
810 		if (!name)
811 			return -ENOMEM;
812 
813 		/*
814 		 * generate CPU DAI name base on the sdw link ID and
815 		 * PIN ID with offset of 2 according to sdw dai driver.
816 		 */
817 		for (k = 0; k < cpu_dai_num; k++) {
818 			cpu_name = devm_kasprintf(dev, GFP_KERNEL,
819 						  "SDW%d Pin%d", cpu_dai_id[k],
820 						  j + SDW_INTEL_BIDIR_PDI_BASE);
821 			if (!cpu_name)
822 				return -ENOMEM;
823 
824 			if (cpu_dai_index >= sdw_cpu_dai_num) {
825 				dev_err(dev, "invalid cpu dai index %d",
826 					cpu_dai_index);
827 				return -EINVAL;
828 			}
829 
830 			cpus[cpu_dai_index++].dai_name = cpu_name;
831 		}
832 
833 		if (*be_index >= sdw_be_num) {
834 			dev_err(dev, " invalid be dai index %d", *be_index);
835 			return -EINVAL;
836 		}
837 
838 		if (*cpu_id >= sdw_cpu_dai_num) {
839 			dev_err(dev, " invalid cpu dai index %d", *cpu_id);
840 			return -EINVAL;
841 		}
842 
843 		playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
844 		capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
845 		init_dai_link(dai_links + *be_index, *be_index, name,
846 			      playback, capture,
847 			      cpus + *cpu_id, cpu_dai_num,
848 			      codecs, codec_num,
849 			      NULL, &sdw_ops);
850 		/*
851 		 * SoundWire DAILINKs use 'stream' functions and Bank Switch operations
852 		 * based on wait_for_completion(), tag them as 'nonatomic'.
853 		 */
854 		dai_links[*be_index].nonatomic = true;
855 
856 		ret = set_codec_init_func(link, dai_links + (*be_index)++,
857 					  playback, group_id);
858 		if (ret < 0) {
859 			dev_err(dev, "failed to init codec %d", codec_index);
860 			return ret;
861 		}
862 
863 		*cpu_id += cpu_dai_num;
864 		j++;
865 	}
866 
867 	return 0;
868 }
869 
870 /*
871  * DAI link ID of SSP & DMIC & HDMI are based on last
872  * link ID used by sdw link. Since be_id may be changed
873  * in init func of sdw codec, it is not equal to be_id
874  */
get_next_be_id(struct snd_soc_dai_link * links,int be_id)875 static inline int get_next_be_id(struct snd_soc_dai_link *links,
876 				 int be_id)
877 {
878 	return links[be_id - 1].id + 1;
879 }
880 
881 #define IDISP_CODEC_MASK	0x4
882 
sof_card_codec_conf_alloc(struct device * dev,struct snd_soc_acpi_mach_params * mach_params,struct snd_soc_codec_conf ** codec_conf,int * codec_conf_count)883 static int sof_card_codec_conf_alloc(struct device *dev,
884 				     struct snd_soc_acpi_mach_params *mach_params,
885 				     struct snd_soc_codec_conf **codec_conf,
886 				     int *codec_conf_count)
887 {
888 	const struct snd_soc_acpi_link_adr *adr_link;
889 	struct snd_soc_codec_conf *c_conf;
890 	int num_codecs = 0;
891 	int i;
892 
893 	adr_link = mach_params->links;
894 	if (!adr_link)
895 		return -EINVAL;
896 
897 	/* generate DAI links by each sdw link */
898 	for (; adr_link->num_adr; adr_link++) {
899 		for (i = 0; i < adr_link->num_adr; i++) {
900 			if (!adr_link->adr_d[i].name_prefix) {
901 				dev_err(dev, "codec 0x%llx does not have a name prefix\n",
902 					adr_link->adr_d[i].adr);
903 				return -EINVAL;
904 			}
905 		}
906 		num_codecs += adr_link->num_adr;
907 	}
908 
909 	c_conf = devm_kzalloc(dev, num_codecs * sizeof(*c_conf), GFP_KERNEL);
910 	if (!c_conf)
911 		return -ENOMEM;
912 
913 	*codec_conf = c_conf;
914 	*codec_conf_count = num_codecs;
915 
916 	return 0;
917 }
918 
sof_card_dai_links_create(struct device * dev,struct snd_soc_acpi_mach * mach,struct snd_soc_card * card)919 static int sof_card_dai_links_create(struct device *dev,
920 				     struct snd_soc_acpi_mach *mach,
921 				     struct snd_soc_card *card)
922 {
923 	int ssp_num, sdw_be_num = 0, hdmi_num = 0, dmic_num;
924 	struct mc_private *ctx = snd_soc_card_get_drvdata(card);
925 	struct snd_soc_dai_link_component *idisp_components;
926 	struct snd_soc_dai_link_component *ssp_components;
927 	struct snd_soc_acpi_mach_params *mach_params;
928 	const struct snd_soc_acpi_link_adr *adr_link;
929 	struct snd_soc_dai_link_component *cpus;
930 	struct snd_soc_codec_conf *codec_conf;
931 	bool ignore_pch_dmic = false;
932 	int codec_conf_count;
933 	int codec_conf_index = 0;
934 	bool group_generated[SDW_MAX_GROUPS];
935 	int ssp_codec_index, ssp_mask;
936 	struct snd_soc_dai_link *links;
937 	int num_links, link_id = 0;
938 	char *name, *cpu_name;
939 	int total_cpu_dai_num;
940 	int sdw_cpu_dai_num;
941 	int i, j, be_id = 0;
942 	int cpu_id = 0;
943 	int comp_num;
944 	int ret;
945 
946 	mach_params = &mach->mach_params;
947 
948 	/* allocate codec conf, will be populated when dailinks are created */
949 	ret = sof_card_codec_conf_alloc(dev, mach_params, &codec_conf, &codec_conf_count);
950 	if (ret < 0)
951 		return ret;
952 
953 	/* reset amp_num to ensure amp_num++ starts from 0 in each probe */
954 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
955 		codec_info_list[i].amp_num = 0;
956 
957 	if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
958 		hdmi_num = SOF_TGL_HDMI_COUNT;
959 	else
960 		hdmi_num = SOF_PRE_TGL_HDMI_COUNT;
961 
962 	ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk);
963 	/*
964 	 * on generic tgl platform, I2S or sdw mode is supported
965 	 * based on board rework. A ACPI device is registered in
966 	 * system only when I2S mode is supported, not sdw mode.
967 	 * Here check ACPI ID to confirm I2S is supported.
968 	 */
969 	ssp_codec_index = find_codec_info_acpi(mach->id);
970 	ssp_num = ssp_codec_index >= 0 ? hweight_long(ssp_mask) : 0;
971 	comp_num = hdmi_num + ssp_num;
972 
973 	ret = get_sdw_dailink_info(mach_params->links,
974 				   &sdw_be_num, &sdw_cpu_dai_num);
975 	if (ret < 0) {
976 		dev_err(dev, "failed to get sdw link info %d", ret);
977 		return ret;
978 	}
979 
980 	if (mach_params->codec_mask & IDISP_CODEC_MASK)
981 		ctx->idisp_codec = true;
982 
983 	/* enable dmic01 & dmic16k */
984 	dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) ? 2 : 0;
985 	comp_num += dmic_num;
986 
987 	dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num,
988 		dmic_num, ctx->idisp_codec ? hdmi_num : 0);
989 
990 	/* allocate BE dailinks */
991 	num_links = comp_num + sdw_be_num;
992 	links = devm_kcalloc(dev, num_links, sizeof(*links), GFP_KERNEL);
993 
994 	/* allocated CPU DAIs */
995 	total_cpu_dai_num = comp_num + sdw_cpu_dai_num;
996 	cpus = devm_kcalloc(dev, total_cpu_dai_num, sizeof(*cpus),
997 			    GFP_KERNEL);
998 
999 	if (!links || !cpus)
1000 		return -ENOMEM;
1001 
1002 	/* SDW */
1003 	if (!sdw_be_num)
1004 		goto SSP;
1005 
1006 	adr_link = mach_params->links;
1007 	if (!adr_link)
1008 		return -EINVAL;
1009 
1010 	/*
1011 	 * SoundWire Slaves aggregated in the same group may be
1012 	 * located on different hardware links. Clear array to indicate
1013 	 * CPU DAIs for this group have not been generated.
1014 	 */
1015 	for (i = 0; i < SDW_MAX_GROUPS; i++)
1016 		group_generated[i] = false;
1017 
1018 	/* generate DAI links by each sdw link */
1019 	for (; adr_link->num_adr; adr_link++) {
1020 		const struct snd_soc_acpi_endpoint *endpoint;
1021 
1022 		endpoint = adr_link->adr_d->endpoints;
1023 		if (endpoint->aggregated && !endpoint->group_id) {
1024 			dev_err(dev, "invalid group id on link %x",
1025 				adr_link->mask);
1026 			continue;
1027 		}
1028 
1029 		/* this group has been generated */
1030 		if (endpoint->aggregated &&
1031 		    group_generated[endpoint->group_id])
1032 			continue;
1033 
1034 		ret = create_sdw_dailink(dev, &be_id, links, sdw_be_num,
1035 					 sdw_cpu_dai_num, cpus, adr_link,
1036 					 &cpu_id, group_generated,
1037 					 codec_conf, codec_conf_count,
1038 					 &codec_conf_index,
1039 					 &ignore_pch_dmic);
1040 		if (ret < 0) {
1041 			dev_err(dev, "failed to create dai link %d", be_id);
1042 			return -ENOMEM;
1043 		}
1044 	}
1045 
1046 	/* non-sdw DAI follows sdw DAI */
1047 	link_id = be_id;
1048 
1049 	/* get BE ID for non-sdw DAI */
1050 	be_id = get_next_be_id(links, be_id);
1051 
1052 SSP:
1053 	/* SSP */
1054 	if (!ssp_num)
1055 		goto DMIC;
1056 
1057 	for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) {
1058 		struct sof_sdw_codec_info *info;
1059 		int playback, capture;
1060 		char *codec_name;
1061 
1062 		if (!(ssp_mask & 0x1))
1063 			continue;
1064 
1065 		name = devm_kasprintf(dev, GFP_KERNEL,
1066 				      "SSP%d-Codec", i);
1067 		if (!name)
1068 			return -ENOMEM;
1069 
1070 		cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i);
1071 		if (!cpu_name)
1072 			return -ENOMEM;
1073 
1074 		ssp_components = devm_kzalloc(dev, sizeof(*ssp_components),
1075 					      GFP_KERNEL);
1076 		if (!ssp_components)
1077 			return -ENOMEM;
1078 
1079 		info = &codec_info_list[ssp_codec_index];
1080 		codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d",
1081 					    info->acpi_id, j++);
1082 		if (!codec_name)
1083 			return -ENOMEM;
1084 
1085 		ssp_components->name = codec_name;
1086 		ssp_components->dai_name = info->dai_name;
1087 		cpus[cpu_id].dai_name = cpu_name;
1088 
1089 		playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK];
1090 		capture = info->direction[SNDRV_PCM_STREAM_CAPTURE];
1091 		init_dai_link(links + link_id, be_id, name,
1092 			      playback, capture,
1093 			      cpus + cpu_id, 1,
1094 			      ssp_components, 1,
1095 			      NULL, info->ops);
1096 
1097 		ret = info->init(NULL, links + link_id, info, 0);
1098 		if (ret < 0)
1099 			return ret;
1100 
1101 		INC_ID(be_id, cpu_id, link_id);
1102 	}
1103 
1104 DMIC:
1105 	/* dmic */
1106 	if (dmic_num > 0) {
1107 		if (ignore_pch_dmic) {
1108 			dev_warn(dev, "Ignoring PCH DMIC\n");
1109 			goto HDMI;
1110 		}
1111 		cpus[cpu_id].dai_name = "DMIC01 Pin";
1112 		init_dai_link(links + link_id, be_id, "dmic01",
1113 			      0, 1, // DMIC only supports capture
1114 			      cpus + cpu_id, 1,
1115 			      dmic_component, 1,
1116 			      sof_sdw_dmic_init, NULL);
1117 		INC_ID(be_id, cpu_id, link_id);
1118 
1119 		cpus[cpu_id].dai_name = "DMIC16k Pin";
1120 		init_dai_link(links + link_id, be_id, "dmic16k",
1121 			      0, 1, // DMIC only supports capture
1122 			      cpus + cpu_id, 1,
1123 			      dmic_component, 1,
1124 			      /* don't call sof_sdw_dmic_init() twice */
1125 			      NULL, NULL);
1126 		INC_ID(be_id, cpu_id, link_id);
1127 	}
1128 
1129 HDMI:
1130 	/* HDMI */
1131 	if (hdmi_num > 0) {
1132 		idisp_components = devm_kcalloc(dev, hdmi_num,
1133 						sizeof(*idisp_components),
1134 						GFP_KERNEL);
1135 		if (!idisp_components)
1136 			return -ENOMEM;
1137 	}
1138 
1139 	for (i = 0; i < hdmi_num; i++) {
1140 		name = devm_kasprintf(dev, GFP_KERNEL,
1141 				      "iDisp%d", i + 1);
1142 		if (!name)
1143 			return -ENOMEM;
1144 
1145 		if (ctx->idisp_codec) {
1146 			idisp_components[i].name = "ehdaudio0D2";
1147 			idisp_components[i].dai_name = devm_kasprintf(dev,
1148 								      GFP_KERNEL,
1149 								      "intel-hdmi-hifi%d",
1150 								      i + 1);
1151 			if (!idisp_components[i].dai_name)
1152 				return -ENOMEM;
1153 		} else {
1154 			idisp_components[i].name = "snd-soc-dummy";
1155 			idisp_components[i].dai_name = "snd-soc-dummy-dai";
1156 		}
1157 
1158 		cpu_name = devm_kasprintf(dev, GFP_KERNEL,
1159 					  "iDisp%d Pin", i + 1);
1160 		if (!cpu_name)
1161 			return -ENOMEM;
1162 
1163 		cpus[cpu_id].dai_name = cpu_name;
1164 		init_dai_link(links + link_id, be_id, name,
1165 			      1, 0, // HDMI only supports playback
1166 			      cpus + cpu_id, 1,
1167 			      idisp_components + i, 1,
1168 			      sof_sdw_hdmi_init, NULL);
1169 		INC_ID(be_id, cpu_id, link_id);
1170 	}
1171 
1172 	card->dai_link = links;
1173 	card->num_links = num_links;
1174 
1175 	card->codec_conf = codec_conf;
1176 	card->num_configs = codec_conf_count;
1177 
1178 	return 0;
1179 }
1180 
sof_sdw_card_late_probe(struct snd_soc_card * card)1181 static int sof_sdw_card_late_probe(struct snd_soc_card *card)
1182 {
1183 	int i, ret;
1184 
1185 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
1186 		if (!codec_info_list[i].late_probe)
1187 			continue;
1188 
1189 		ret = codec_info_list[i].codec_card_late_probe(card);
1190 		if (ret < 0)
1191 			return ret;
1192 	}
1193 
1194 	return sof_sdw_hdmi_card_late_probe(card);
1195 }
1196 
1197 /* SoC card */
1198 static const char sdw_card_long_name[] = "Intel Soundwire SOF";
1199 
1200 static struct snd_soc_card card_sof_sdw = {
1201 	.name = "soundwire",
1202 	.owner = THIS_MODULE,
1203 	.late_probe = sof_sdw_card_late_probe,
1204 };
1205 
mc_probe(struct platform_device * pdev)1206 static int mc_probe(struct platform_device *pdev)
1207 {
1208 	struct snd_soc_card *card = &card_sof_sdw;
1209 	struct snd_soc_acpi_mach *mach;
1210 	struct mc_private *ctx;
1211 	int amp_num = 0, i;
1212 	int ret;
1213 
1214 	dev_dbg(&pdev->dev, "Entry %s\n", __func__);
1215 
1216 	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1217 	if (!ctx)
1218 		return -ENOMEM;
1219 
1220 	dmi_check_system(sof_sdw_quirk_table);
1221 
1222 	if (quirk_override != -1) {
1223 		dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n",
1224 			 sof_sdw_quirk, quirk_override);
1225 		sof_sdw_quirk = quirk_override;
1226 	}
1227 	log_quirks(&pdev->dev);
1228 
1229 	INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
1230 
1231 	card->dev = &pdev->dev;
1232 	snd_soc_card_set_drvdata(card, ctx);
1233 
1234 	mach = pdev->dev.platform_data;
1235 	ret = sof_card_dai_links_create(&pdev->dev, mach,
1236 					card);
1237 	if (ret < 0)
1238 		return ret;
1239 
1240 	ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
1241 
1242 	/*
1243 	 * the default amp_num is zero for each codec and
1244 	 * amp_num will only be increased for active amp
1245 	 * codecs on used platform
1246 	 */
1247 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
1248 		amp_num += codec_info_list[i].amp_num;
1249 
1250 	card->components = devm_kasprintf(card->dev, GFP_KERNEL,
1251 					  "cfg-spk:%d cfg-amp:%d",
1252 					  (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
1253 					  ? 4 : 2, amp_num);
1254 	if (!card->components)
1255 		return -ENOMEM;
1256 
1257 	card->long_name = sdw_card_long_name;
1258 
1259 	/* Register the card */
1260 	ret = devm_snd_soc_register_card(&pdev->dev, card);
1261 	if (ret) {
1262 		dev_err(card->dev, "snd_soc_register_card failed %d\n", ret);
1263 		return ret;
1264 	}
1265 
1266 	platform_set_drvdata(pdev, card);
1267 
1268 	return ret;
1269 }
1270 
mc_remove(struct platform_device * pdev)1271 static int mc_remove(struct platform_device *pdev)
1272 {
1273 	struct snd_soc_card *card = platform_get_drvdata(pdev);
1274 	struct snd_soc_dai_link *link;
1275 	int ret;
1276 	int i, j;
1277 
1278 	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
1279 		if (!codec_info_list[i].exit)
1280 			continue;
1281 		/*
1282 		 * We don't need to call .exit function if there is no matched
1283 		 * dai link found.
1284 		 */
1285 		for_each_card_prelinks(card, j, link) {
1286 			if (!strcmp(link->codecs[0].dai_name,
1287 				    codec_info_list[i].dai_name)) {
1288 				ret = codec_info_list[i].exit(&pdev->dev, link);
1289 				if (ret)
1290 					dev_warn(&pdev->dev,
1291 						 "codec exit failed %d\n",
1292 						 ret);
1293 				break;
1294 			}
1295 		}
1296 	}
1297 
1298 	return 0;
1299 }
1300 
1301 static struct platform_driver sof_sdw_driver = {
1302 	.driver = {
1303 		.name = "sof_sdw",
1304 		.pm = &snd_soc_pm_ops,
1305 	},
1306 	.probe = mc_probe,
1307 	.remove = mc_remove,
1308 };
1309 
1310 module_platform_driver(sof_sdw_driver);
1311 
1312 MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver");
1313 MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>");
1314 MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>");
1315 MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
1316 MODULE_LICENSE("GPL v2");
1317 MODULE_ALIAS("platform:sof_sdw");
1318