xref: /linux/sound/soc/intel/avs/board_selection.c (revision af477f4d5a6c183e2dd44f49dd9a7950bfa7bd50)
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Copyright(c) 2021-2022 Intel Corporation
4 //
5 // Authors: Cezary Rojewski <cezary.rojewski@intel.com>
6 //          Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
7 //
8 
9 #include <linux/acpi.h>
10 #include <linux/module.h>
11 #include <linux/dmi.h>
12 #include <linux/pci.h>
13 #include <acpi/nhlt.h>
14 #include <linux/platform_device.h>
15 #include <sound/hda_codec.h>
16 #include <sound/hda_register.h>
17 #include <sound/soc-acpi.h>
18 #include <sound/soc-component.h>
19 #include "avs.h"
20 #include "utils.h"
21 
22 static char *i2s_test;
23 module_param(i2s_test, charp, 0444);
24 MODULE_PARM_DESC(i2s_test, "Use I2S test-board instead of ACPI, i2s_test=ssp0tdm,ssp1tdm,... 0 to ignore port");
25 
26 bool obsolete_card_names = IS_ENABLED(CONFIG_SND_SOC_INTEL_AVS_CARDNAME_OBSOLETE);
27 module_param_named(obsolete_card_names, obsolete_card_names, bool, 0444);
28 MODULE_PARM_DESC(obsolete_card_names, "Use obsolete card names 0=no, 1=yes");
29 
30 static const struct dmi_system_id kbl_dmi_table[] = {
31 	{
32 		.matches = {
33 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
34 			DMI_MATCH(DMI_BOARD_NAME, "Skylake Y LPDDR3 RVP3"),
35 		},
36 	},
37 	{
38 		.matches = {
39 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
40 			DMI_MATCH(DMI_BOARD_NAME, "AmberLake Y"),
41 		},
42 	},
43 	{}
44 };
45 
46 static const struct dmi_system_id kblr_dmi_table[] = {
47 	{
48 		.matches = {
49 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
50 			DMI_MATCH(DMI_BOARD_NAME, "Kabylake R DDR4 RVP"),
51 		},
52 	},
53 	{}
54 };
55 
dmi_match_quirk(void * arg)56 static struct snd_soc_acpi_mach *dmi_match_quirk(void *arg)
57 {
58 	struct snd_soc_acpi_mach *mach = arg;
59 	const struct dmi_system_id *dmi_id;
60 	struct dmi_system_id *dmi_table;
61 
62 	if (mach->quirk_data == NULL)
63 		return mach;
64 
65 	dmi_table = (struct dmi_system_id *)mach->quirk_data;
66 
67 	dmi_id = dmi_first_match(dmi_table);
68 	if (!dmi_id)
69 		return NULL;
70 
71 	return mach;
72 }
73 
74 #define AVS_SSP(x)		(BIT(x))
75 #define AVS_SSP_RANGE(a, b)	(GENMASK(b, a))
76 
77 /* supported I2S board codec configurations */
78 static struct snd_soc_acpi_mach avs_skl_i2s_machines[] = {
79 	{
80 		.id = "INT343A",
81 		.drv_name = "avs_rt286",
82 		.mach_params = {
83 			.i2s_link_mask = AVS_SSP(0),
84 		},
85 		.tplg_filename = "rt286-tplg.bin",
86 	},
87 	{
88 		.id = "10508825",
89 		.drv_name = "avs_nau8825",
90 		.mach_params = {
91 			.i2s_link_mask = AVS_SSP(1),
92 		},
93 		.tplg_filename = "nau8825-tplg.bin",
94 	},
95 	{
96 		.id = "INT343B",
97 		.drv_name = "avs_ssm4567",
98 		.mach_params = {
99 			.i2s_link_mask = AVS_SSP(0),
100 		},
101 		.tplg_filename = "ssm4567-tplg.bin",
102 	},
103 	{
104 		.id = "MX98357A",
105 		.drv_name = "avs_max98357a",
106 		.mach_params = {
107 			.i2s_link_mask = AVS_SSP(0),
108 		},
109 		.tplg_filename = "max98357a-tplg.bin",
110 	},
111 	{},
112 };
113 
114 static struct snd_soc_acpi_mach avs_kbl_i2s_machines[] = {
115 	{
116 		.id = "INT343A",
117 		.drv_name = "avs_rt286",
118 		.mach_params = {
119 			.i2s_link_mask = AVS_SSP(0),
120 		},
121 		.quirk_data = &kbl_dmi_table,
122 		.machine_quirk = dmi_match_quirk,
123 		.tplg_filename = "rt286-tplg.bin",
124 	},
125 	{
126 		.id = "INT343A",
127 		.drv_name = "avs_rt298",
128 		.mach_params = {
129 			.i2s_link_mask = AVS_SSP(0),
130 		},
131 		.quirk_data = &kblr_dmi_table,
132 		.machine_quirk = dmi_match_quirk,
133 		.tplg_filename = "rt298-tplg.bin",
134 	},
135 	{
136 		.id = "MX98927",
137 		.drv_name = "avs_max98927",
138 		.mach_params = {
139 			.i2s_link_mask = AVS_SSP(0),
140 		},
141 		.tplg_filename = "max98927-tplg.bin",
142 	},
143 	{
144 		.id = "10EC5514",
145 		.drv_name = "avs_rt5514",
146 		.mach_params = {
147 			.i2s_link_mask = AVS_SSP(0),
148 		},
149 		.pdata = (struct avs_mach_pdata[]){ { .tdms = (unsigned long[]){ 0x2 } } },
150 		.tplg_filename = "rt5514-tplg.bin",
151 	},
152 	{
153 		.id = "10EC5663",
154 		.drv_name = "avs_rt5663",
155 		.mach_params = {
156 			.i2s_link_mask = AVS_SSP(1),
157 		},
158 		.tplg_filename = "rt5663-tplg.bin",
159 	},
160 	{
161 		.id = "MX98373",
162 		.drv_name = "avs_max98373",
163 		.mach_params = {
164 			.i2s_link_mask = AVS_SSP(0),
165 		},
166 		.tplg_filename = "max98373-tplg.bin",
167 	},
168 	{
169 		.id = "MX98357A",
170 		.drv_name = "avs_max98357a",
171 		.mach_params = {
172 			.i2s_link_mask = AVS_SSP(0),
173 		},
174 		.tplg_filename = "max98357a-tplg.bin",
175 	},
176 	{
177 		.id = "DLGS7219",
178 		.drv_name = "avs_da7219",
179 		.mach_params = {
180 			.i2s_link_mask = AVS_SSP(1),
181 		},
182 		.tplg_filename = "da7219-tplg.bin",
183 	},
184 	{
185 		.id = "ESSX8336",
186 		.drv_name = "avs_es8336",
187 		.mach_params = {
188 			.i2s_link_mask = AVS_SSP(0),
189 		},
190 		.tplg_filename = "es8336-tplg.bin",
191 	},
192 	{},
193 };
194 
195 static struct snd_soc_acpi_mach avs_apl_i2s_machines[] = {
196 	{
197 		.id = "INT343A",
198 		.drv_name = "avs_rt298",
199 		.mach_params = {
200 			.i2s_link_mask = AVS_SSP(5),
201 		},
202 		.tplg_filename = "rt298-tplg.bin",
203 	},
204 	{
205 		.id = "INT34C3",
206 		.drv_name = "avs_tdf8532",
207 		.mach_params = {
208 			.i2s_link_mask = AVS_SSP_RANGE(0, 5),
209 		},
210 		.pdata = (struct avs_mach_pdata[]){ {
211 			.tdms = (unsigned long[]){ 0x1, 0x1, 0x14, 0x1, 0x1, 0x1 }
212 		} },
213 		.tplg_filename = "tdf8532-tplg.bin",
214 	},
215 	{
216 		.id = "MX98357A",
217 		.drv_name = "avs_max98357a",
218 		.mach_params = {
219 			.i2s_link_mask = AVS_SSP(5),
220 		},
221 		.tplg_filename = "max98357a-tplg.bin",
222 	},
223 	{
224 		.id = "DLGS7219",
225 		.drv_name = "avs_da7219",
226 		.mach_params = {
227 			.i2s_link_mask = AVS_SSP(1),
228 		},
229 		.tplg_filename = "da7219-tplg.bin",
230 	},
231 	{},
232 };
233 
234 static struct snd_soc_acpi_mach avs_gml_i2s_machines[] = {
235 	{
236 		.id = "INT343A",
237 		.drv_name = "avs_rt298",
238 		.mach_params = {
239 			.i2s_link_mask = AVS_SSP(2),
240 		},
241 		.tplg_filename = "rt298-tplg.bin",
242 	},
243 	{},
244 };
245 
246 static struct snd_soc_acpi_mach avs_cnl_i2s_machines[] = {
247 	{
248 		.id = "INT34C2",
249 		.drv_name = "avs_rt274",
250 		.mach_params = {
251 			.i2s_link_mask = AVS_SSP(0),
252 		},
253 		.tplg_filename = "rt274-tplg.bin",
254 	},
255 	{
256 		.id = "10EC5682",
257 		.drv_name = "avs_rt5682",
258 		.mach_params = {
259 			.i2s_link_mask = AVS_SSP(1),
260 		},
261 		.tplg_filename = "rt5682-tplg.bin",
262 	},
263 	{},
264 };
265 
266 static struct snd_soc_acpi_mach avs_icl_i2s_machines[] = {
267 	{
268 		.id = "INT343A",
269 		.drv_name = "avs_rt298",
270 		.mach_params = {
271 			.i2s_link_mask = AVS_SSP(0),
272 		},
273 		.tplg_filename = "rt298-tplg.bin",
274 	},
275 	{
276 		.id = "INT34C2",
277 		.drv_name = "avs_rt274",
278 		.mach_params = {
279 			.i2s_link_mask = AVS_SSP(0),
280 		},
281 		.tplg_filename = "rt274-tplg.bin",
282 	},
283 	{},
284 };
285 
286 static struct snd_soc_acpi_mach avs_tgl_i2s_machines[] = {
287 	{
288 		.id = "INT34C2",
289 		.drv_name = "avs_rt274",
290 		.mach_params = {
291 			.i2s_link_mask = AVS_SSP(0),
292 		},
293 		.tplg_filename = "rt274-tplg.bin",
294 	},
295 	{
296 		.id = "10EC0298",
297 		.drv_name = "avs_rt298",
298 		.mach_params = {
299 			.i2s_link_mask = AVS_SSP(0),
300 		},
301 		.tplg_filename = "rt298-tplg.bin",
302 	},
303 	{
304 		.id = "10EC1308",
305 		.drv_name = "avs_rt1308",
306 		.mach_params = {
307 			.i2s_link_mask = AVS_SSP(1),
308 		},
309 		.tplg_filename = "rt1308-tplg.bin",
310 	},
311 	{
312 		.id = "ESSX8336",
313 		.drv_name = "avs_es8336",
314 		.mach_params = {
315 			.i2s_link_mask = AVS_SSP(0),
316 		},
317 		.tplg_filename = "es8336-tplg.bin",
318 	},
319 	{},
320 };
321 
322 static struct snd_soc_acpi_mach avs_mbl_i2s_machines[] = {
323 	{
324 		.id = "PCM3168A",
325 		.drv_name = "avs_pcm3168a",
326 		.mach_params = {
327 			.i2s_link_mask = AVS_SSP(0) | AVS_SSP(2),
328 		},
329 		.tplg_filename = "pcm3168a-tplg.bin",
330 	},
331 	{}
332 };
333 
334 struct avs_acpi_boards {
335 	int id;
336 	struct snd_soc_acpi_mach *machs;
337 };
338 
339 #define AVS_MACH_ENTRY(_id, _mach) \
340 	{ .id = PCI_DEVICE_ID_INTEL_##_id, .machs = (_mach), }
341 
342 /* supported I2S boards per platform */
343 static const struct avs_acpi_boards i2s_boards[] = {
344 	AVS_MACH_ENTRY(HDA_SKL_LP, avs_skl_i2s_machines),
345 	AVS_MACH_ENTRY(HDA_KBL_LP, avs_kbl_i2s_machines),
346 	AVS_MACH_ENTRY(HDA_APL, avs_apl_i2s_machines),
347 	AVS_MACH_ENTRY(HDA_GML, avs_gml_i2s_machines),
348 	AVS_MACH_ENTRY(HDA_CNL_LP,	avs_cnl_i2s_machines),
349 	AVS_MACH_ENTRY(HDA_CNL_H,	avs_cnl_i2s_machines),
350 	AVS_MACH_ENTRY(HDA_CML_LP,	avs_cnl_i2s_machines),
351 	AVS_MACH_ENTRY(HDA_ICL_LP,	avs_icl_i2s_machines),
352 	AVS_MACH_ENTRY(HDA_TGL_LP,	avs_tgl_i2s_machines),
353 	AVS_MACH_ENTRY(HDA_EHL_0,	avs_tgl_i2s_machines),
354 	AVS_MACH_ENTRY(HDA_ADL_N,	avs_mbl_i2s_machines),
355 	AVS_MACH_ENTRY(HDA_ADL_P,	avs_tgl_i2s_machines),
356 	AVS_MACH_ENTRY(HDA_RPL_P_0,	avs_tgl_i2s_machines),
357 	AVS_MACH_ENTRY(HDA_RPL_M,	avs_mbl_i2s_machines),
358 	AVS_MACH_ENTRY(HDA_FCL,		avs_tgl_i2s_machines),
359 	{ },
360 };
361 
avs_get_i2s_boards(struct avs_dev * adev)362 static const struct avs_acpi_boards *avs_get_i2s_boards(struct avs_dev *adev)
363 {
364 	int id, i;
365 
366 	id = adev->base.pci->device;
367 	for (i = 0; i < ARRAY_SIZE(i2s_boards); i++)
368 		if (i2s_boards[i].id == id)
369 			return &i2s_boards[i];
370 	return NULL;
371 }
372 
373 /* platform devices owned by AVS audio are removed with this hook */
board_pdev_unregister(void * data)374 static void board_pdev_unregister(void *data)
375 {
376 	platform_device_unregister(data);
377 }
378 
avs_register_probe_board(struct avs_dev * adev)379 static int __maybe_unused avs_register_probe_board(struct avs_dev *adev)
380 {
381 	struct platform_device *board;
382 	struct snd_soc_acpi_mach mach = {{0}};
383 	int ret;
384 
385 	ret = avs_probe_platform_register(adev, "probe-platform");
386 	if (ret < 0)
387 		return ret;
388 
389 	mach.mach_params.platform = "probe-platform";
390 
391 	board = platform_device_register_data(NULL, "avs_probe_mb", PLATFORM_DEVID_NONE,
392 					      (const void *)&mach, sizeof(mach));
393 	if (IS_ERR(board)) {
394 		dev_err(adev->dev, "probe board register failed\n");
395 		return PTR_ERR(board);
396 	}
397 
398 	ret = devm_add_action(adev->dev, board_pdev_unregister, board);
399 	if (ret < 0) {
400 		platform_device_unregister(board);
401 		return ret;
402 	}
403 	return 0;
404 }
405 
avs_register_dmic_board(struct avs_dev * adev)406 static int avs_register_dmic_board(struct avs_dev *adev)
407 {
408 	struct platform_device *codec, *board;
409 	struct snd_soc_acpi_mach mach = {{0}};
410 	struct avs_mach_pdata *pdata;
411 	int ret;
412 
413 	if (!acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, -1, -1)) {
414 		dev_dbg(adev->dev, "no DMIC endpoints present\n");
415 		return 0;
416 	}
417 
418 	codec = platform_device_register_simple("dmic-codec", PLATFORM_DEVID_NONE, NULL, 0);
419 	if (IS_ERR(codec)) {
420 		dev_err(adev->dev, "dmic codec register failed\n");
421 		return PTR_ERR(codec);
422 	}
423 
424 	ret = devm_add_action(adev->dev, board_pdev_unregister, codec);
425 	if (ret < 0) {
426 		platform_device_unregister(codec);
427 		return ret;
428 	}
429 
430 	ret = avs_dmic_platform_register(adev, "dmic-platform");
431 	if (ret < 0)
432 		return ret;
433 
434 	pdata = devm_kzalloc(adev->dev, sizeof(*pdata), GFP_KERNEL);
435 	if (!pdata)
436 		return -ENOMEM;
437 	pdata->obsolete_card_names = obsolete_card_names;
438 	mach.pdata = pdata;
439 	mach.tplg_filename = "dmic-tplg.bin";
440 	mach.mach_params.platform = "dmic-platform";
441 
442 	board = platform_device_register_data(NULL, "avs_dmic", PLATFORM_DEVID_NONE,
443 					(const void *)&mach, sizeof(mach));
444 	if (IS_ERR(board)) {
445 		dev_err(adev->dev, "dmic board register failed\n");
446 		return PTR_ERR(board);
447 	}
448 
449 	ret = devm_add_action(adev->dev, board_pdev_unregister, board);
450 	if (ret < 0) {
451 		platform_device_unregister(board);
452 		return ret;
453 	}
454 
455 	return 0;
456 }
457 
avs_register_i2s_board(struct avs_dev * adev,struct snd_soc_acpi_mach * mach)458 static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach *mach)
459 {
460 	struct platform_device *board;
461 	struct avs_mach_pdata *pdata;
462 	int num_ssps;
463 	char *name;
464 	int ret;
465 	int uid;
466 
467 	num_ssps = adev->hw_cfg.i2s_caps.ctrl_count;
468 	if (fls(mach->mach_params.i2s_link_mask) > num_ssps) {
469 		dev_err(adev->dev, "Platform supports %d SSPs but board %s requires SSP%ld\n",
470 			num_ssps, mach->drv_name,
471 			(unsigned long)__fls(mach->mach_params.i2s_link_mask));
472 		return -ENODEV;
473 	}
474 
475 	pdata = mach->pdata;
476 	if (!pdata)
477 		pdata = devm_kzalloc(adev->dev, sizeof(*pdata), GFP_KERNEL);
478 	if (!pdata)
479 		return -ENOMEM;
480 	pdata->obsolete_card_names = obsolete_card_names;
481 	mach->pdata = pdata;
482 
483 	uid = mach->mach_params.i2s_link_mask;
484 	if (avs_mach_singular_ssp(mach))
485 		uid = (uid << AVS_CHANNELS_MAX) + avs_mach_ssp_tdm(mach, avs_mach_ssp_port(mach));
486 
487 	name = devm_kasprintf(adev->dev, GFP_KERNEL, "%s.%d-platform", mach->drv_name, uid);
488 	if (!name)
489 		return -ENOMEM;
490 
491 	ret = avs_i2s_platform_register(adev, name, mach->mach_params.i2s_link_mask, pdata->tdms);
492 	if (ret < 0)
493 		return ret;
494 
495 	mach->mach_params.platform = name;
496 
497 	board = platform_device_register_data(NULL, mach->drv_name, uid,
498 					      (const void *)mach, sizeof(*mach));
499 	if (IS_ERR(board)) {
500 		dev_err(adev->dev, "ssp board register failed\n");
501 		return PTR_ERR(board);
502 	}
503 
504 	ret = devm_add_action(adev->dev, board_pdev_unregister, board);
505 	if (ret < 0) {
506 		platform_device_unregister(board);
507 		return ret;
508 	}
509 
510 	return 0;
511 }
512 
avs_register_i2s_test_board(struct avs_dev * adev,int ssp_port,int tdm_slot)513 static int avs_register_i2s_test_board(struct avs_dev *adev, int ssp_port, int tdm_slot)
514 {
515 	struct snd_soc_acpi_mach *mach;
516 	int tdm_mask = BIT(tdm_slot);
517 	unsigned long *tdm_cfg;
518 	char *tplg_name;
519 	int ret;
520 
521 	mach = devm_kzalloc(adev->dev, sizeof(*mach), GFP_KERNEL);
522 	tdm_cfg = devm_kcalloc(adev->dev, ssp_port + 1, sizeof(unsigned long), GFP_KERNEL);
523 	tplg_name = devm_kasprintf(adev->dev, GFP_KERNEL, AVS_STRING_FMT("i2s", "-test-tplg.bin",
524 				   ssp_port, tdm_slot));
525 	if (!mach || !tdm_cfg || !tplg_name)
526 		return -ENOMEM;
527 
528 	mach->drv_name = "avs_i2s_test";
529 	mach->mach_params.i2s_link_mask = AVS_SSP(ssp_port);
530 	tdm_cfg[ssp_port] = tdm_mask;
531 	mach->pdata = tdm_cfg;
532 	mach->tplg_filename = tplg_name;
533 
534 	ret = avs_register_i2s_board(adev, mach);
535 	if (ret < 0) {
536 		dev_warn(adev->dev, "register i2s %s failed: %d\n", mach->drv_name, ret);
537 		return ret;
538 	}
539 
540 	return 0;
541 }
542 
avs_register_i2s_test_boards(struct avs_dev * adev)543 static int avs_register_i2s_test_boards(struct avs_dev *adev)
544 {
545 	int max_ssps = adev->hw_cfg.i2s_caps.ctrl_count;
546 	int ssp_port, tdm_slot, ret;
547 	unsigned long tdm_slots;
548 	u32 *array, num_elems;
549 
550 	ret = parse_int_array(i2s_test, strlen(i2s_test), (int **)&array);
551 	if (ret) {
552 		dev_err(adev->dev, "failed to parse i2s_test parameter\n");
553 		return ret;
554 	}
555 
556 	num_elems = *array;
557 	if (num_elems > max_ssps) {
558 		dev_err(adev->dev, "board supports only %d SSP, %d specified\n",
559 			max_ssps, num_elems);
560 		return -EINVAL;
561 	}
562 
563 	for (ssp_port = 0; ssp_port < num_elems; ssp_port++) {
564 		tdm_slots = array[1 + ssp_port];
565 		for_each_set_bit(tdm_slot, &tdm_slots, 16) {
566 			ret = avs_register_i2s_test_board(adev, ssp_port, tdm_slot);
567 			if (ret)
568 				return ret;
569 		}
570 	}
571 
572 	return 0;
573 }
574 
avs_register_i2s_boards(struct avs_dev * adev)575 static int avs_register_i2s_boards(struct avs_dev *adev)
576 {
577 	const struct avs_acpi_boards *boards;
578 	struct snd_soc_acpi_mach *mach;
579 	int ret;
580 
581 	if (!acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_SSP, -1, -1, -1)) {
582 		dev_dbg(adev->dev, "no I2S endpoints present\n");
583 		return 0;
584 	}
585 
586 	if (i2s_test)
587 		return avs_register_i2s_test_boards(adev);
588 
589 	boards = avs_get_i2s_boards(adev);
590 	if (!boards) {
591 		dev_dbg(adev->dev, "no I2S endpoints supported\n");
592 		return 0;
593 	}
594 
595 	for (mach = boards->machs; mach->id[0]; mach++) {
596 		if (!acpi_dev_present(mach->id, mach->uid, -1))
597 			continue;
598 
599 		if (mach->machine_quirk)
600 			if (!mach->machine_quirk(mach))
601 				continue;
602 
603 		ret = avs_register_i2s_board(adev, mach);
604 		if (ret < 0)
605 			dev_warn(adev->dev, "register i2s %s failed: %d\n", mach->drv_name, ret);
606 	}
607 
608 	return 0;
609 }
610 
avs_register_hda_board(struct avs_dev * adev,struct hda_codec * codec)611 static int avs_register_hda_board(struct avs_dev *adev, struct hda_codec *codec)
612 {
613 	struct snd_soc_acpi_mach mach = {{0}};
614 	struct platform_device *board;
615 	struct avs_mach_pdata *pdata;
616 	struct hdac_device *hdev = &codec->core;
617 	char *pname;
618 	int ret, id;
619 
620 	pname = devm_kasprintf(adev->dev, GFP_KERNEL, "%s-platform", dev_name(&hdev->dev));
621 	if (!pname)
622 		return -ENOMEM;
623 
624 	pdata = devm_kzalloc(adev->dev, sizeof(*pdata), GFP_KERNEL);
625 	if (!pdata)
626 		return -ENOMEM;
627 	pdata->obsolete_card_names = obsolete_card_names;
628 	pdata->codec = codec;
629 
630 	ret = avs_hda_platform_register(adev, pname);
631 	if (ret < 0)
632 		return ret;
633 
634 	mach.pdata = pdata;
635 	mach.mach_params.platform = pname;
636 	mach.tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL, "hda-%08x-tplg.bin",
637 					    hdev->vendor_id);
638 	if (!mach.tplg_filename)
639 		return -ENOMEM;
640 
641 	id = adev->base.core.idx * HDA_MAX_CODECS + hdev->addr;
642 	board = platform_device_register_data(NULL, "avs_hdaudio", id, (const void *)&mach,
643 					      sizeof(mach));
644 	if (IS_ERR(board)) {
645 		dev_err(adev->dev, "hda board register failed\n");
646 		return PTR_ERR(board);
647 	}
648 
649 	ret = devm_add_action(adev->dev, board_pdev_unregister, board);
650 	if (ret < 0) {
651 		platform_device_unregister(board);
652 		return ret;
653 	}
654 
655 	return 0;
656 }
657 
avs_register_hda_boards(struct avs_dev * adev)658 static int avs_register_hda_boards(struct avs_dev *adev)
659 {
660 	struct hdac_bus *bus = &adev->base.core;
661 	struct hdac_device *hdev;
662 	int ret;
663 
664 	if (!bus->num_codecs) {
665 		dev_dbg(adev->dev, "no HDA endpoints present\n");
666 		return 0;
667 	}
668 
669 	list_for_each_entry(hdev, &bus->codec_list, list) {
670 		struct hda_codec *codec;
671 
672 		codec = dev_to_hda_codec(&hdev->dev);
673 
674 		ret = avs_register_hda_board(adev, codec);
675 		if (ret < 0)
676 			dev_warn(adev->dev, "register hda-%08x failed: %d\n",
677 				 codec->core.vendor_id, ret);
678 	}
679 
680 	return 0;
681 }
682 
avs_register_all_boards(struct avs_dev * adev)683 int avs_register_all_boards(struct avs_dev *adev)
684 {
685 	int ret;
686 
687 #ifdef CONFIG_DEBUG_FS
688 	ret = avs_register_probe_board(adev);
689 	if (ret < 0)
690 		dev_warn(adev->dev, "enumerate PROBE endpoints failed: %d\n", ret);
691 #endif
692 
693 	ret = avs_register_dmic_board(adev);
694 	if (ret < 0)
695 		dev_warn(adev->dev, "enumerate DMIC endpoints failed: %d\n",
696 			 ret);
697 
698 	ret = avs_register_i2s_boards(adev);
699 	if (ret < 0)
700 		dev_warn(adev->dev, "enumerate I2S endpoints failed: %d\n",
701 			 ret);
702 
703 	ret = avs_register_hda_boards(adev);
704 	if (ret < 0)
705 		dev_warn(adev->dev, "enumerate HDA endpoints failed: %d\n",
706 			 ret);
707 
708 	return 0;
709 }
710 
avs_unregister_all_boards(struct avs_dev * adev)711 void avs_unregister_all_boards(struct avs_dev *adev)
712 {
713 	snd_soc_unregister_component(adev->dev);
714 }
715