1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Machine driver for AMD Yellow Carp platform using DMIC |
4 | * |
5 | * Copyright 2021 Advanced Micro Devices, Inc. |
6 | */ |
7 | |
8 | #include <sound/soc.h> |
9 | #include <sound/soc-dapm.h> |
10 | #include <linux/module.h> |
11 | #include <sound/pcm.h> |
12 | #include <sound/pcm_params.h> |
13 | #include <linux/io.h> |
14 | #include <linux/dmi.h> |
15 | #include <linux/acpi.h> |
16 | |
17 | #include "acp6x.h" |
18 | |
19 | #define DRV_NAME "acp_yc_mach" |
20 | |
21 | SND_SOC_DAILINK_DEF(acp6x_pdm, |
22 | DAILINK_COMP_ARRAY(COMP_CPU("acp_yc_pdm_dma.0" ))); |
23 | |
24 | SND_SOC_DAILINK_DEF(dmic_codec, |
25 | DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec.0" , |
26 | "dmic-hifi" ))); |
27 | |
28 | SND_SOC_DAILINK_DEF(pdm_platform, |
29 | DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_yc_pdm_dma.0" ))); |
30 | |
31 | static struct snd_soc_dai_link acp6x_dai_pdm[] = { |
32 | { |
33 | .name = "acp6x-dmic-capture" , |
34 | .stream_name = "DMIC capture" , |
35 | .capture_only = 1, |
36 | SND_SOC_DAILINK_REG(acp6x_pdm, dmic_codec, pdm_platform), |
37 | }, |
38 | }; |
39 | |
40 | static struct snd_soc_card acp6x_card = { |
41 | .name = "acp6x" , |
42 | .owner = THIS_MODULE, |
43 | .dai_link = acp6x_dai_pdm, |
44 | .num_links = 1, |
45 | }; |
46 | |
47 | static const struct dmi_system_id yc_acp_quirk_table[] = { |
48 | { |
49 | .driver_data = &acp6x_card, |
50 | .matches = { |
51 | DMI_MATCH(DMI_BOARD_VENDOR, "Dell Inc." ), |
52 | DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5525" ), |
53 | } |
54 | }, |
55 | { |
56 | .driver_data = &acp6x_card, |
57 | .matches = { |
58 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
59 | DMI_MATCH(DMI_PRODUCT_NAME, "21D0" ), |
60 | } |
61 | }, |
62 | { |
63 | .driver_data = &acp6x_card, |
64 | .matches = { |
65 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
66 | DMI_MATCH(DMI_PRODUCT_NAME, "21D0" ), |
67 | } |
68 | }, |
69 | { |
70 | .driver_data = &acp6x_card, |
71 | .matches = { |
72 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
73 | DMI_MATCH(DMI_PRODUCT_NAME, "21D1" ), |
74 | } |
75 | }, |
76 | { |
77 | .driver_data = &acp6x_card, |
78 | .matches = { |
79 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
80 | DMI_MATCH(DMI_PRODUCT_NAME, "21D2" ), |
81 | } |
82 | }, |
83 | { |
84 | .driver_data = &acp6x_card, |
85 | .matches = { |
86 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
87 | DMI_MATCH(DMI_PRODUCT_NAME, "21D3" ), |
88 | } |
89 | }, |
90 | { |
91 | .driver_data = &acp6x_card, |
92 | .matches = { |
93 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
94 | DMI_MATCH(DMI_PRODUCT_NAME, "21D4" ), |
95 | } |
96 | }, |
97 | { |
98 | .driver_data = &acp6x_card, |
99 | .matches = { |
100 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
101 | DMI_MATCH(DMI_PRODUCT_NAME, "21D5" ), |
102 | } |
103 | }, |
104 | { |
105 | .driver_data = &acp6x_card, |
106 | .matches = { |
107 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
108 | DMI_MATCH(DMI_PRODUCT_NAME, "21CF" ), |
109 | } |
110 | }, |
111 | { |
112 | .driver_data = &acp6x_card, |
113 | .matches = { |
114 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
115 | DMI_MATCH(DMI_PRODUCT_NAME, "21CG" ), |
116 | } |
117 | }, |
118 | { |
119 | .driver_data = &acp6x_card, |
120 | .matches = { |
121 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
122 | DMI_MATCH(DMI_PRODUCT_NAME, "21CQ" ), |
123 | } |
124 | }, |
125 | { |
126 | .driver_data = &acp6x_card, |
127 | .matches = { |
128 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
129 | DMI_MATCH(DMI_PRODUCT_NAME, "21CR" ), |
130 | } |
131 | }, |
132 | { |
133 | .driver_data = &acp6x_card, |
134 | .matches = { |
135 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
136 | DMI_MATCH(DMI_PRODUCT_NAME, "21CM" ), |
137 | } |
138 | }, |
139 | { |
140 | .driver_data = &acp6x_card, |
141 | .matches = { |
142 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
143 | DMI_MATCH(DMI_PRODUCT_NAME, "21CN" ), |
144 | } |
145 | }, |
146 | { |
147 | .driver_data = &acp6x_card, |
148 | .matches = { |
149 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
150 | DMI_MATCH(DMI_PRODUCT_NAME, "21CH" ), |
151 | } |
152 | }, |
153 | { |
154 | .driver_data = &acp6x_card, |
155 | .matches = { |
156 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
157 | DMI_MATCH(DMI_PRODUCT_NAME, "21CJ" ), |
158 | } |
159 | }, |
160 | { |
161 | .driver_data = &acp6x_card, |
162 | .matches = { |
163 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
164 | DMI_MATCH(DMI_PRODUCT_NAME, "21CK" ), |
165 | } |
166 | }, |
167 | { |
168 | .driver_data = &acp6x_card, |
169 | .matches = { |
170 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
171 | DMI_MATCH(DMI_PRODUCT_NAME, "21CL" ), |
172 | } |
173 | }, |
174 | { |
175 | .driver_data = &acp6x_card, |
176 | .matches = { |
177 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
178 | DMI_MATCH(DMI_PRODUCT_NAME, "21EF" ), |
179 | } |
180 | }, |
181 | { |
182 | .driver_data = &acp6x_card, |
183 | .matches = { |
184 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
185 | DMI_MATCH(DMI_PRODUCT_NAME, "21EM" ), |
186 | } |
187 | }, |
188 | { |
189 | .driver_data = &acp6x_card, |
190 | .matches = { |
191 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
192 | DMI_MATCH(DMI_PRODUCT_NAME, "21EN" ), |
193 | } |
194 | }, |
195 | { |
196 | .driver_data = &acp6x_card, |
197 | .matches = { |
198 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
199 | DMI_MATCH(DMI_PRODUCT_NAME, "21HY" ), |
200 | } |
201 | }, |
202 | { |
203 | .driver_data = &acp6x_card, |
204 | .matches = { |
205 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
206 | DMI_MATCH(DMI_PRODUCT_NAME, "21J0" ), |
207 | } |
208 | }, |
209 | { |
210 | .driver_data = &acp6x_card, |
211 | .matches = { |
212 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
213 | DMI_MATCH(DMI_PRODUCT_NAME, "21J5" ), |
214 | } |
215 | }, |
216 | { |
217 | .driver_data = &acp6x_card, |
218 | .matches = { |
219 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
220 | DMI_MATCH(DMI_PRODUCT_NAME, "21J6" ), |
221 | } |
222 | }, |
223 | { |
224 | .driver_data = &acp6x_card, |
225 | .matches = { |
226 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
227 | DMI_MATCH(DMI_PRODUCT_NAME, "82QF" ), |
228 | } |
229 | }, |
230 | { |
231 | .driver_data = &acp6x_card, |
232 | .matches = { |
233 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
234 | DMI_MATCH(DMI_PRODUCT_NAME, "82TL" ), |
235 | } |
236 | }, |
237 | { |
238 | .driver_data = &acp6x_card, |
239 | .matches = { |
240 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
241 | DMI_MATCH(DMI_PRODUCT_NAME, "82UG" ), |
242 | } |
243 | }, |
244 | { |
245 | .driver_data = &acp6x_card, |
246 | .matches = { |
247 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
248 | DMI_MATCH(DMI_PRODUCT_NAME, "82UU" ), |
249 | } |
250 | }, |
251 | { |
252 | .driver_data = &acp6x_card, |
253 | .matches = { |
254 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
255 | DMI_MATCH(DMI_PRODUCT_NAME, "82V2" ), |
256 | } |
257 | }, |
258 | { |
259 | .driver_data = &acp6x_card, |
260 | .matches = { |
261 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
262 | DMI_MATCH(DMI_PRODUCT_NAME, "82YM" ), |
263 | } |
264 | }, |
265 | { |
266 | .driver_data = &acp6x_card, |
267 | .matches = { |
268 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO" ), |
269 | DMI_MATCH(DMI_PRODUCT_NAME, "83AS" ), |
270 | } |
271 | }, |
272 | { |
273 | .driver_data = &acp6x_card, |
274 | .matches = { |
275 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC." ), |
276 | DMI_MATCH(DMI_PRODUCT_NAME, "UM5302TA" ), |
277 | } |
278 | }, |
279 | { |
280 | .driver_data = &acp6x_card, |
281 | .matches = { |
282 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC." ), |
283 | DMI_MATCH(DMI_PRODUCT_NAME, "M5402RA" ), |
284 | } |
285 | }, |
286 | { |
287 | .driver_data = &acp6x_card, |
288 | .matches = { |
289 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC." ), |
290 | DMI_MATCH(DMI_PRODUCT_NAME, "M6400RC" ), |
291 | } |
292 | }, |
293 | { |
294 | .driver_data = &acp6x_card, |
295 | .matches = { |
296 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC." ), |
297 | DMI_MATCH(DMI_PRODUCT_NAME, "M3402RA" ), |
298 | } |
299 | }, |
300 | { |
301 | .driver_data = &acp6x_card, |
302 | .matches = { |
303 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC." ), |
304 | DMI_MATCH(DMI_PRODUCT_NAME, "M6500RC" ), |
305 | } |
306 | }, |
307 | { |
308 | .driver_data = &acp6x_card, |
309 | .matches = { |
310 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC." ), |
311 | DMI_MATCH(DMI_PRODUCT_NAME, "E1504FA" ), |
312 | } |
313 | }, |
314 | { |
315 | .driver_data = &acp6x_card, |
316 | .matches = { |
317 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC." ), |
318 | DMI_MATCH(DMI_PRODUCT_NAME, "M7600RE" ), |
319 | } |
320 | }, |
321 | { |
322 | .driver_data = &acp6x_card, |
323 | .matches = { |
324 | DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd." ), |
325 | DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 B7ED" ), |
326 | } |
327 | }, |
328 | { |
329 | .driver_data = &acp6x_card, |
330 | .matches = { |
331 | DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd." ), |
332 | DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 C7VF" ), |
333 | } |
334 | }, |
335 | { |
336 | .driver_data = &acp6x_card, |
337 | .matches = { |
338 | DMI_MATCH(DMI_BOARD_VENDOR, "Alienware" ), |
339 | DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD" ), |
340 | } |
341 | }, |
342 | { |
343 | .driver_data = &acp6x_card, |
344 | .matches = { |
345 | DMI_MATCH(DMI_BOARD_VENDOR, "TIMI" ), |
346 | DMI_MATCH(DMI_PRODUCT_NAME, "Redmi Book Pro 14 2022" ), |
347 | } |
348 | }, |
349 | { |
350 | .driver_data = &acp6x_card, |
351 | .matches = { |
352 | DMI_MATCH(DMI_BOARD_VENDOR, "TIMI" ), |
353 | DMI_MATCH(DMI_PRODUCT_NAME, "Redmi Book Pro 15 2022" ), |
354 | } |
355 | }, |
356 | { |
357 | .driver_data = &acp6x_card, |
358 | .matches = { |
359 | DMI_MATCH(DMI_BOARD_VENDOR, "Razer" ), |
360 | DMI_MATCH(DMI_PRODUCT_NAME, "Blade 14 (2022) - RZ09-0427" ), |
361 | } |
362 | }, |
363 | { |
364 | .driver_data = &acp6x_card, |
365 | .matches = { |
366 | DMI_MATCH(DMI_BOARD_VENDOR, "RB" ), |
367 | DMI_MATCH(DMI_PRODUCT_NAME, "Swift SFA16-41" ), |
368 | } |
369 | }, |
370 | { |
371 | .driver_data = &acp6x_card, |
372 | .matches = { |
373 | DMI_MATCH(DMI_BOARD_VENDOR, "IRBIS" ), |
374 | DMI_MATCH(DMI_PRODUCT_NAME, "15NBC1011" ), |
375 | } |
376 | }, |
377 | { |
378 | .driver_data = &acp6x_card, |
379 | .matches = { |
380 | DMI_MATCH(DMI_BOARD_VENDOR, "HP" ), |
381 | DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16z-n000" ), |
382 | } |
383 | }, |
384 | { |
385 | .driver_data = &acp6x_card, |
386 | .matches = { |
387 | DMI_MATCH(DMI_BOARD_VENDOR, "HP" ), |
388 | DMI_MATCH(DMI_BOARD_NAME, "8A42" ), |
389 | } |
390 | }, |
391 | { |
392 | .driver_data = &acp6x_card, |
393 | .matches = { |
394 | DMI_MATCH(DMI_BOARD_VENDOR, "HP" ), |
395 | DMI_MATCH(DMI_BOARD_NAME, "8A43" ), |
396 | } |
397 | }, |
398 | { |
399 | .driver_data = &acp6x_card, |
400 | .matches = { |
401 | DMI_MATCH(DMI_BOARD_VENDOR, "HP" ), |
402 | DMI_MATCH(DMI_BOARD_NAME, "8A22" ), |
403 | } |
404 | }, |
405 | { |
406 | .driver_data = &acp6x_card, |
407 | .matches = { |
408 | DMI_MATCH(DMI_BOARD_VENDOR, "HP" ), |
409 | DMI_MATCH(DMI_BOARD_NAME, "8A3E" ), |
410 | } |
411 | }, |
412 | { |
413 | .driver_data = &acp6x_card, |
414 | .matches = { |
415 | DMI_MATCH(DMI_BOARD_VENDOR, "HP" ), |
416 | DMI_MATCH(DMI_BOARD_NAME, "8B2F" ), |
417 | } |
418 | }, |
419 | { |
420 | .driver_data = &acp6x_card, |
421 | .matches = { |
422 | DMI_MATCH(DMI_BOARD_VENDOR, "HP" ), |
423 | DMI_MATCH(DMI_BOARD_NAME, "8BD6" ), |
424 | } |
425 | }, |
426 | { |
427 | .driver_data = &acp6x_card, |
428 | .matches = { |
429 | DMI_MATCH(DMI_BOARD_VENDOR, "MECHREVO" ), |
430 | DMI_MATCH(DMI_BOARD_NAME, "MRID6" ), |
431 | } |
432 | }, |
433 | { |
434 | .driver_data = &acp6x_card, |
435 | .matches = { |
436 | DMI_MATCH(DMI_BOARD_VENDOR, "System76" ), |
437 | DMI_MATCH(DMI_PRODUCT_VERSION, "pang12" ), |
438 | } |
439 | }, |
440 | { |
441 | .driver_data = &acp6x_card, |
442 | .matches = { |
443 | DMI_MATCH(DMI_BOARD_VENDOR, "System76" ), |
444 | DMI_MATCH(DMI_PRODUCT_VERSION, "pang13" ), |
445 | } |
446 | }, |
447 | {} |
448 | }; |
449 | |
450 | static int acp6x_probe(struct platform_device *pdev) |
451 | { |
452 | const struct dmi_system_id *dmi_id; |
453 | struct acp6x_pdm *machine = NULL; |
454 | struct snd_soc_card *card; |
455 | struct acpi_device *adev; |
456 | int ret; |
457 | |
458 | /* check the parent device's firmware node has _DSD or not */ |
459 | adev = ACPI_COMPANION(pdev->dev.parent); |
460 | if (adev) { |
461 | const union acpi_object *obj; |
462 | |
463 | if (!acpi_dev_get_property(adev, name: "AcpDmicConnected" , ACPI_TYPE_INTEGER, obj: &obj) && |
464 | obj->integer.value == 1) |
465 | platform_set_drvdata(pdev, data: &acp6x_card); |
466 | } |
467 | |
468 | /* check for any DMI overrides */ |
469 | dmi_id = dmi_first_match(list: yc_acp_quirk_table); |
470 | if (dmi_id) |
471 | platform_set_drvdata(pdev, data: dmi_id->driver_data); |
472 | |
473 | card = platform_get_drvdata(pdev); |
474 | if (!card) |
475 | return -ENODEV; |
476 | dev_info(&pdev->dev, "Enabling ACP DMIC support via %s" , dmi_id ? "DMI" : "ACPI" ); |
477 | acp6x_card.dev = &pdev->dev; |
478 | |
479 | snd_soc_card_set_drvdata(card, data: machine); |
480 | ret = devm_snd_soc_register_card(dev: &pdev->dev, card); |
481 | if (ret) { |
482 | return dev_err_probe(dev: &pdev->dev, err: ret, |
483 | fmt: "snd_soc_register_card(%s) failed\n" , |
484 | card->name); |
485 | } |
486 | return 0; |
487 | } |
488 | |
489 | static struct platform_driver acp6x_mach_driver = { |
490 | .driver = { |
491 | .name = "acp_yc_mach" , |
492 | .pm = &snd_soc_pm_ops, |
493 | }, |
494 | .probe = acp6x_probe, |
495 | }; |
496 | |
497 | module_platform_driver(acp6x_mach_driver); |
498 | |
499 | MODULE_AUTHOR("Vijendar.Mukunda@amd.com" ); |
500 | MODULE_LICENSE("GPL v2" ); |
501 | MODULE_ALIAS("platform:" DRV_NAME); |
502 | |