blob: 6cbe2edc868c365ab48687ea7dd6e43bc1dece77 [file] [log] [blame]
Liam Girdwooddd96dac2019-04-12 11:08:47 -05001// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2//
3// This file is provided under a dual BSD/GPLv2 license. When using or
4// redistributing this file, you may do so under either license.
5//
6// Copyright(c) 2018 Intel Corporation. All rights reserved.
7//
8// Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9// Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
10// Rander Wang <rander.wang@intel.com>
11// Keyon Jie <yang.jie@linux.intel.com>
12//
13
14/*
15 * Hardware interface for generic Intel audio DSP HDA IP
16 */
17
Liam Girdwooddd96dac2019-04-12 11:08:47 -050018#include <sound/hdaudio_ext.h>
Kai Vehmanenf1fd9d02019-06-12 11:57:03 -050019#include <sound/hda_register.h>
20
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -050021#include <linux/acpi.h>
Liam Girdwooddd96dac2019-04-12 11:08:47 -050022#include <linux/module.h>
Pierre-Louis Bossartb9ddd812020-03-25 16:50:21 -050023#include <linux/soundwire/sdw.h>
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -050024#include <linux/soundwire/sdw_intel.h>
Pierre-Louis Bossart68b953a2019-08-12 11:06:23 -050025#include <sound/intel-nhlt.h>
Liam Girdwooddd96dac2019-04-12 11:08:47 -050026#include <sound/sof.h>
27#include <sound/sof/xtensa.h>
Pierre-Louis Bossartd2c383a2020-03-25 16:50:20 -050028#include "../sof-audio.h"
Liam Girdwooddd96dac2019-04-12 11:08:47 -050029#include "../ops.h"
30#include "hda.h"
Liam Girdwooddd96dac2019-04-12 11:08:47 -050031
32#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
33#include <sound/soc-acpi-intel-match.h>
34#endif
35
36/* platform specific devices */
37#include "shim.h"
38
Liam Girdwoodff2be862019-09-27 15:05:36 -050039#define EXCEPT_MAX_HDR_SIZE 0x400
40
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -050041#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
42
Pierre-Louis Bossart02df8f42020-03-25 16:50:24 -050043/*
44 * The default for SoundWire clock stop quirks is to power gate the IP
45 * and do a Bus Reset, this will need to be modified when the DSP
46 * needs to remain in D0i3 so that the Master does not lose context
47 * and enumeration is not required on clock restart
48 */
49static int sdw_clock_stop_quirks = SDW_INTEL_CLK_STOP_BUS_RESET;
50module_param(sdw_clock_stop_quirks, int, 0444);
51MODULE_PARM_DESC(sdw_clock_stop_quirks, "SOF SoundWire clock stop quirks");
52
Pierre-Louis Bossartd2c383a2020-03-25 16:50:20 -050053static int sdw_params_stream(struct device *dev,
54 struct sdw_intel_stream_params_data *params_data)
55{
56 struct snd_sof_dev *sdev = dev_get_drvdata(dev);
57 struct snd_soc_dai *d = params_data->dai;
58 struct sof_ipc_dai_config config;
59 struct sof_ipc_reply reply;
60 int link_id = params_data->link_id;
61 int alh_stream_id = params_data->alh_stream_id;
62 int ret;
63 u32 size = sizeof(config);
64
65 memset(&config, 0, size);
66 config.hdr.size = size;
67 config.hdr.cmd = SOF_IPC_GLB_DAI_MSG | SOF_IPC_DAI_CONFIG;
68 config.type = SOF_DAI_INTEL_ALH;
69 config.dai_index = (link_id << 8) | (d->id);
70 config.alh.stream_id = alh_stream_id;
71
72 /* send message to DSP */
73 ret = sof_ipc_tx_message(sdev->ipc,
74 config.hdr.cmd, &config, size, &reply,
75 sizeof(reply));
76 if (ret < 0) {
77 dev_err(sdev->dev,
78 "error: failed to set DAI hw_params for link %d dai->id %d ALH %d\n",
79 link_id, d->id, alh_stream_id);
80 }
81
82 return ret;
83}
84
85static int sdw_free_stream(struct device *dev,
86 struct sdw_intel_stream_free_data *free_data)
87{
88 struct snd_sof_dev *sdev = dev_get_drvdata(dev);
89 struct snd_soc_dai *d = free_data->dai;
90 struct sof_ipc_dai_config config;
91 struct sof_ipc_reply reply;
92 int link_id = free_data->link_id;
93 int ret;
94 u32 size = sizeof(config);
95
96 memset(&config, 0, size);
97 config.hdr.size = size;
98 config.hdr.cmd = SOF_IPC_GLB_DAI_MSG | SOF_IPC_DAI_CONFIG;
99 config.type = SOF_DAI_INTEL_ALH;
100 config.dai_index = (link_id << 8) | d->id;
101 config.alh.stream_id = 0xFFFF; /* invalid value on purpose */
102
103 /* send message to DSP */
104 ret = sof_ipc_tx_message(sdev->ipc,
105 config.hdr.cmd, &config, size, &reply,
106 sizeof(reply));
107 if (ret < 0) {
108 dev_err(sdev->dev,
109 "error: failed to free stream for link %d dai->id %d\n",
110 link_id, d->id);
111 }
112
113 return ret;
114}
115
116static const struct sdw_intel_ops sdw_callback = {
117 .params_stream = sdw_params_stream,
118 .free_stream = sdw_free_stream,
119};
120
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -0500121void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable)
122{
123 sdw_intel_enable_irq(sdev->bar[HDA_DSP_BAR], enable);
124}
125
126static int hda_sdw_acpi_scan(struct snd_sof_dev *sdev)
127{
128 struct sof_intel_hda_dev *hdev;
129 acpi_handle handle;
130 int ret;
131
132 handle = ACPI_HANDLE(sdev->dev);
133
134 /* save ACPI info for the probe step */
135 hdev = sdev->pdata->hw_pdata;
136
137 ret = sdw_intel_acpi_scan(handle, &hdev->info);
Pierre-Louis Bossart0d4453e2020-04-09 13:44:14 -0500138 if (ret < 0)
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -0500139 return -EINVAL;
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -0500140
141 return 0;
142}
143
144static int hda_sdw_probe(struct snd_sof_dev *sdev)
145{
146 struct sof_intel_hda_dev *hdev;
147 struct sdw_intel_res res;
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -0500148 void *sdw;
149
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -0500150 hdev = sdev->pdata->hw_pdata;
151
152 memset(&res, 0, sizeof(res));
153
154 res.mmio_base = sdev->bar[HDA_DSP_BAR];
155 res.irq = sdev->ipc_irq;
156 res.handle = hdev->info.handle;
157 res.parent = sdev->dev;
Pierre-Louis Bossartd2c383a2020-03-25 16:50:20 -0500158 res.ops = &sdw_callback;
159 res.dev = sdev->dev;
Pierre-Louis Bossart02df8f42020-03-25 16:50:24 -0500160 res.clock_stop_quirks = sdw_clock_stop_quirks;
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -0500161
162 /*
163 * ops and arg fields are not populated for now,
164 * they will be needed when the DAI callbacks are
165 * provided
166 */
167
168 /* we could filter links here if needed, e.g for quirks */
169 res.count = hdev->info.count;
170 res.link_mask = hdev->info.link_mask;
171
172 sdw = sdw_intel_probe(&res);
173 if (!sdw) {
174 dev_err(sdev->dev, "error: SoundWire probe failed\n");
175 return -EINVAL;
176 }
177
178 /* save context */
179 hdev->sdw = sdw;
180
181 return 0;
182}
183
184int hda_sdw_startup(struct snd_sof_dev *sdev)
185{
186 struct sof_intel_hda_dev *hdev;
187
188 hdev = sdev->pdata->hw_pdata;
189
Pierre-Louis Bossartb9ddd812020-03-25 16:50:21 -0500190 if (!hdev->sdw)
191 return 0;
192
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -0500193 return sdw_intel_startup(hdev->sdw);
194}
195
196static int hda_sdw_exit(struct snd_sof_dev *sdev)
197{
198 struct sof_intel_hda_dev *hdev;
199
200 hdev = sdev->pdata->hw_pdata;
201
202 hda_sdw_int_enable(sdev, false);
203
204 if (hdev->sdw)
205 sdw_intel_exit(hdev->sdw);
206 hdev->sdw = NULL;
207
208 return 0;
209}
Bard Liao722ba5f2020-03-25 16:50:23 -0500210
211static bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
212{
213 struct sof_intel_hda_dev *hdev;
214 bool ret = false;
215 u32 irq_status;
216
217 hdev = sdev->pdata->hw_pdata;
218
219 if (!hdev->sdw)
220 return ret;
221
222 /* store status */
223 irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIS2);
224
225 /* invalid message ? */
226 if (irq_status == 0xffffffff)
227 goto out;
228
229 /* SDW message ? */
230 if (irq_status & HDA_DSP_REG_ADSPIS2_SNDW)
231 ret = true;
232
233out:
234 return ret;
235}
236
237static irqreturn_t hda_dsp_sdw_thread(int irq, void *context)
238{
239 return sdw_intel_thread(irq, context);
240}
241
Rander Wang90de3282020-03-25 16:50:26 -0500242static bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev)
243{
244 struct sof_intel_hda_dev *hdev;
245
246 hdev = sdev->pdata->hw_pdata;
247 if (hdev->sdw &&
248 snd_sof_dsp_read(sdev, HDA_DSP_BAR,
249 HDA_DSP_REG_SNDW_WAKE_STS))
250 return true;
251
252 return false;
253}
254
Rander Wangbbd19cd2020-03-25 16:50:25 -0500255void hda_sdw_process_wakeen(struct snd_sof_dev *sdev)
256{
257 struct sof_intel_hda_dev *hdev;
258
259 hdev = sdev->pdata->hw_pdata;
260 if (!hdev->sdw)
261 return;
262
263 sdw_intel_process_wakeen_event(hdev->sdw);
264}
265
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -0500266#endif
267
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500268/*
269 * Debug
270 */
271
272struct hda_dsp_msg_code {
273 u32 code;
274 const char *msg;
275};
276
Guennadi Liakhovetski672ff5e2019-07-22 09:13:57 -0500277static bool hda_use_msi = IS_ENABLED(CONFIG_PCI);
278#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG)
279module_param_named(use_msi, hda_use_msi, bool, 0444);
280MODULE_PARM_DESC(use_msi, "SOF HDA use PCI MSI mode");
281#endif
282
Pierre-Louis Bossart68b953a2019-08-12 11:06:23 -0500283#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
284static int hda_dmic_num = -1;
285module_param_named(dmic_num, hda_dmic_num, int, 0444);
286MODULE_PARM_DESC(dmic_num, "SOF HDA DMIC number");
Kai Vehmanen139c7fe2019-10-29 15:40:13 +0200287
Kai Vehmanen42c67752020-03-12 14:48:53 -0500288static bool hda_codec_use_common_hdmi = IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI);
Kai Vehmanen139c7fe2019-10-29 15:40:13 +0200289module_param_named(use_common_hdmi, hda_codec_use_common_hdmi, bool, 0444);
290MODULE_PARM_DESC(use_common_hdmi, "SOF HDA use common HDMI codec driver");
Pierre-Louis Bossart68b953a2019-08-12 11:06:23 -0500291#endif
292
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500293static const struct hda_dsp_msg_code hda_dsp_rom_msg[] = {
294 {HDA_DSP_ROM_FW_MANIFEST_LOADED, "status: manifest loaded"},
295 {HDA_DSP_ROM_FW_FW_LOADED, "status: fw loaded"},
296 {HDA_DSP_ROM_FW_ENTERED, "status: fw entered"},
297 {HDA_DSP_ROM_CSE_ERROR, "error: cse error"},
298 {HDA_DSP_ROM_CSE_WRONG_RESPONSE, "error: cse wrong response"},
299 {HDA_DSP_ROM_IMR_TO_SMALL, "error: IMR too small"},
300 {HDA_DSP_ROM_BASE_FW_NOT_FOUND, "error: base fw not found"},
301 {HDA_DSP_ROM_CSE_VALIDATION_FAILED, "error: signature verification failed"},
302 {HDA_DSP_ROM_IPC_FATAL_ERROR, "error: ipc fatal error"},
303 {HDA_DSP_ROM_L2_CACHE_ERROR, "error: L2 cache error"},
304 {HDA_DSP_ROM_LOAD_OFFSET_TO_SMALL, "error: load offset too small"},
305 {HDA_DSP_ROM_API_PTR_INVALID, "error: API ptr invalid"},
Colin Ian King07f80452019-05-01 11:23:08 +0100306 {HDA_DSP_ROM_BASEFW_INCOMPAT, "error: base fw incompatible"},
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500307 {HDA_DSP_ROM_UNHANDLED_INTERRUPT, "error: unhandled interrupt"},
308 {HDA_DSP_ROM_MEMORY_HOLE_ECC, "error: ECC memory hole"},
309 {HDA_DSP_ROM_KERNEL_EXCEPTION, "error: kernel exception"},
310 {HDA_DSP_ROM_USER_EXCEPTION, "error: user exception"},
311 {HDA_DSP_ROM_UNEXPECTED_RESET, "error: unexpected reset"},
312 {HDA_DSP_ROM_NULL_FW_ENTRY, "error: null FW entry point"},
313};
314
315static void hda_dsp_get_status_skl(struct snd_sof_dev *sdev)
316{
317 u32 status;
318 int i;
319
320 status = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
321 HDA_ADSP_FW_STATUS_SKL);
322
323 for (i = 0; i < ARRAY_SIZE(hda_dsp_rom_msg); i++) {
324 if (status == hda_dsp_rom_msg[i].code) {
325 dev_err(sdev->dev, "%s - code %8.8x\n",
326 hda_dsp_rom_msg[i].msg, status);
327 return;
328 }
329 }
330
331 /* not for us, must be generic sof message */
332 dev_dbg(sdev->dev, "unknown ROM status value %8.8x\n", status);
333}
334
335static void hda_dsp_get_status(struct snd_sof_dev *sdev)
336{
337 u32 status;
338 int i;
339
340 status = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
341 HDA_DSP_SRAM_REG_ROM_STATUS);
342
343 for (i = 0; i < ARRAY_SIZE(hda_dsp_rom_msg); i++) {
344 if (status == hda_dsp_rom_msg[i].code) {
345 dev_err(sdev->dev, "%s - code %8.8x\n",
346 hda_dsp_rom_msg[i].msg, status);
347 return;
348 }
349 }
350
351 /* not for us, must be generic sof message */
352 dev_dbg(sdev->dev, "unknown ROM status value %8.8x\n", status);
353}
354
355static void hda_dsp_get_registers(struct snd_sof_dev *sdev,
356 struct sof_ipc_dsp_oops_xtensa *xoops,
357 struct sof_ipc_panic_info *panic_info,
358 u32 *stack, size_t stack_words)
359{
Kai Vehmanen14104eb2019-06-03 11:18:15 -0500360 u32 offset = sdev->dsp_oops_offset;
361
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500362 /* first read registers */
Kai Vehmanen14104eb2019-06-03 11:18:15 -0500363 sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
364
365 /* note: variable AR register array is not read */
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500366
367 /* then get panic info */
Liam Girdwoodff2be862019-09-27 15:05:36 -0500368 if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
369 dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
370 xoops->arch_hdr.totalsize);
371 return;
372 }
Kai Vehmanen14104eb2019-06-03 11:18:15 -0500373 offset += xoops->arch_hdr.totalsize;
374 sof_block_read(sdev, sdev->mmio_bar, offset,
375 panic_info, sizeof(*panic_info));
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500376
377 /* then get the stack */
Kai Vehmanen14104eb2019-06-03 11:18:15 -0500378 offset += sizeof(*panic_info);
379 sof_block_read(sdev, sdev->mmio_bar, offset, stack,
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500380 stack_words * sizeof(u32));
381}
382
383void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags)
384{
385 struct sof_ipc_dsp_oops_xtensa xoops;
386 struct sof_ipc_panic_info panic_info;
387 u32 stack[HDA_DSP_STACK_DUMP_SIZE];
388 u32 status, panic;
389
390 /* try APL specific status message types first */
391 hda_dsp_get_status_skl(sdev);
392
393 /* now try generic SOF status messages */
394 status = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
395 HDA_ADSP_ERROR_CODE_SKL);
396
397 /*TODO: Check: there is no define in spec, but it is used in the code*/
398 panic = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
399 HDA_ADSP_ERROR_CODE_SKL + 0x4);
400
Ranjani Sridharan6ca5cec2019-12-17 18:26:09 -0600401 if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) {
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500402 hda_dsp_get_registers(sdev, &xoops, &panic_info, stack,
403 HDA_DSP_STACK_DUMP_SIZE);
404 snd_sof_get_status(sdev, status, panic, &xoops, &panic_info,
405 stack, HDA_DSP_STACK_DUMP_SIZE);
406 } else {
407 dev_err(sdev->dev, "error: status = 0x%8.8x panic = 0x%8.8x\n",
408 status, panic);
409 hda_dsp_get_status_skl(sdev);
410 }
411}
412
413void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
414{
415 struct sof_ipc_dsp_oops_xtensa xoops;
416 struct sof_ipc_panic_info panic_info;
417 u32 stack[HDA_DSP_STACK_DUMP_SIZE];
418 u32 status, panic;
419
420 /* try APL specific status message types first */
421 hda_dsp_get_status(sdev);
422
423 /* now try generic SOF status messages */
424 status = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
425 HDA_DSP_SRAM_REG_FW_STATUS);
426 panic = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_FW_TRACEP);
427
Ranjani Sridharan6ca5cec2019-12-17 18:26:09 -0600428 if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) {
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500429 hda_dsp_get_registers(sdev, &xoops, &panic_info, stack,
430 HDA_DSP_STACK_DUMP_SIZE);
431 snd_sof_get_status(sdev, status, panic, &xoops, &panic_info,
432 stack, HDA_DSP_STACK_DUMP_SIZE);
433 } else {
434 dev_err(sdev->dev, "error: status = 0x%8.8x panic = 0x%8.8x\n",
435 status, panic);
436 hda_dsp_get_status(sdev);
437 }
438}
439
Kai Vehmanenf1fd9d02019-06-12 11:57:03 -0500440void hda_ipc_irq_dump(struct snd_sof_dev *sdev)
441{
442 struct hdac_bus *bus = sof_to_bus(sdev);
443 u32 adspis;
444 u32 intsts;
445 u32 intctl;
446 u32 ppsts;
447 u8 rirbsts;
448
449 /* read key IRQ stats and config registers */
450 adspis = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIS);
451 intsts = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS);
452 intctl = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL);
453 ppsts = snd_sof_dsp_read(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPSTS);
454 rirbsts = snd_hdac_chip_readb(bus, RIRBSTS);
455
456 dev_err(sdev->dev,
457 "error: hda irq intsts 0x%8.8x intlctl 0x%8.8x rirb %2.2x\n",
458 intsts, intctl, rirbsts);
459 dev_err(sdev->dev,
460 "error: dsp irq ppsts 0x%8.8x adspis 0x%8.8x\n",
461 ppsts, adspis);
462}
463
Pan Xiulif3da49f2019-04-30 18:09:33 -0500464void hda_ipc_dump(struct snd_sof_dev *sdev)
465{
466 u32 hipcie;
467 u32 hipct;
468 u32 hipcctl;
469
Kai Vehmanenf1fd9d02019-06-12 11:57:03 -0500470 hda_ipc_irq_dump(sdev);
471
Pan Xiulif3da49f2019-04-30 18:09:33 -0500472 /* read IPC status */
473 hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCIE);
474 hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT);
475 hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCCTL);
476
477 /* dump the IPC regs */
478 /* TODO: parse the raw msg */
479 dev_err(sdev->dev,
480 "error: host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n",
481 hipcie, hipct, hipcctl);
482}
483
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500484static int hda_init(struct snd_sof_dev *sdev)
485{
486 struct hda_bus *hbus;
487 struct hdac_bus *bus;
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500488 struct pci_dev *pci = to_pci_dev(sdev->dev);
489 int ret;
490
491 hbus = sof_to_hbus(sdev);
492 bus = sof_to_bus(sdev);
493
494 /* HDA bus init */
Takashi Iwaid4ff1b32019-08-07 20:50:50 +0200495 sof_hda_bus_init(bus, &pci->dev);
Bard Liao64ca9d92019-05-27 00:58:36 +0800496
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500497 bus->use_posbuf = 1;
498 bus->bdl_pos_adj = 0;
Kai Vehmanenf3416e72019-10-08 11:44:35 -0500499 bus->sync_write = 1;
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500500
501 mutex_init(&hbus->prepare_mutex);
502 hbus->pci = pci;
503 hbus->mixer_assigned = -1;
504 hbus->modelname = "sofbus";
505
506 /* initialise hdac bus */
507 bus->addr = pci_resource_start(pci, 0);
YueHaibingad169f92019-05-31 22:25:26 +0800508#if IS_ENABLED(CONFIG_PCI)
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500509 bus->remap_addr = pci_ioremap_bar(pci, 0);
YueHaibingad169f92019-05-31 22:25:26 +0800510#endif
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500511 if (!bus->remap_addr) {
512 dev_err(bus->dev, "error: ioremap error\n");
513 return -ENXIO;
514 }
515
516 /* HDA base */
517 sdev->bar[HDA_DSP_HDA_BAR] = bus->remap_addr;
518
Kai Vehmanenaf7aae12020-02-06 22:02:23 +0200519 /* init i915 and HDMI codecs */
520 ret = hda_codec_i915_init(sdev);
Kai Vehmanen71cc8ab2020-02-20 19:10:28 +0200521 if (ret < 0)
522 dev_warn(sdev->dev, "init of i915 and HDMI codec failed\n");
Kai Vehmanenaf7aae12020-02-06 22:02:23 +0200523
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500524 /* get controller capabilities */
525 ret = hda_dsp_ctrl_get_caps(sdev);
526 if (ret < 0)
527 dev_err(sdev->dev, "error: get caps error\n");
528
529 return ret;
530}
531
532#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
533
Pierre-Louis Bossart68b953a2019-08-12 11:06:23 -0500534static int check_nhlt_dmic(struct snd_sof_dev *sdev)
535{
536 struct nhlt_acpi_table *nhlt;
537 int dmic_num;
538
539 nhlt = intel_nhlt_init(sdev->dev);
540 if (nhlt) {
541 dmic_num = intel_nhlt_get_dmic_geo(sdev->dev, nhlt);
542 intel_nhlt_free(nhlt);
543 if (dmic_num == 2 || dmic_num == 4)
544 return dmic_num;
545 }
546
547 return 0;
548}
549
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500550static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
Pierre-Louis Bossart68b953a2019-08-12 11:06:23 -0500551 const char *sof_tplg_filename,
552 const char *idisp_str,
553 const char *dmic_str)
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500554{
555 const char *tplg_filename = NULL;
556 char *filename;
557 char *split_ext;
558
559 filename = devm_kstrdup(sdev->dev, sof_tplg_filename, GFP_KERNEL);
560 if (!filename)
561 return NULL;
562
563 /* this assumes a .tplg extension */
564 split_ext = strsep(&filename, ".");
565 if (split_ext) {
566 tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
Pierre-Louis Bossart68b953a2019-08-12 11:06:23 -0500567 "%s%s%s.tplg",
568 split_ext, idisp_str, dmic_str);
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500569 if (!tplg_filename)
570 return NULL;
571 }
572 return tplg_filename;
573}
574
Zhu Yingjiangbe1b5772019-05-24 14:09:24 -0500575#endif
576
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500577static int hda_init_caps(struct snd_sof_dev *sdev)
578{
579 struct hdac_bus *bus = sof_to_bus(sdev);
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -0500580 struct snd_sof_pdata *pdata = sdev->pdata;
Zhu Yingjiangbe1b5772019-05-24 14:09:24 -0500581#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500582 struct hdac_ext_link *hlink;
Zhu Yingjiangbe1b5772019-05-24 14:09:24 -0500583#endif
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -0500584 struct sof_intel_hda_dev *hdev = pdata->hw_pdata;
585 u32 link_mask;
Zhu Yingjiangbe1b5772019-05-24 14:09:24 -0500586 int ret = 0;
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500587
588 device_disable_async_suspend(bus->dev);
589
590 /* check if dsp is there */
591 if (bus->ppcap)
592 dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n");
593
Ranjani Sridharancc352732019-08-06 15:19:58 -0700594 /* Init HDA controller after i915 init */
Zhu Yingjiangbe1b5772019-05-24 14:09:24 -0500595 ret = hda_dsp_ctrl_init_chip(sdev, true);
596 if (ret < 0) {
597 dev_err(bus->dev, "error: init chip failed with ret: %d\n",
598 ret);
599 return ret;
600 }
601
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -0500602 /* scan SoundWire capabilities exposed by DSDT */
603 ret = hda_sdw_acpi_scan(sdev);
604 if (ret < 0) {
Pierre-Louis Bossart0d4453e2020-04-09 13:44:14 -0500605 dev_dbg(sdev->dev, "skipping SoundWire, not detected with ACPI scan\n");
Pierre-Louis Bossartb9ddd812020-03-25 16:50:21 -0500606 goto skip_soundwire;
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -0500607 }
608
609 link_mask = hdev->info.link_mask;
610 if (!link_mask) {
Pierre-Louis Bossartb9ddd812020-03-25 16:50:21 -0500611 dev_dbg(sdev->dev, "skipping SoundWire, no links enabled\n");
612 goto skip_soundwire;
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -0500613 }
614
Pierre-Louis Bossartb9ddd812020-03-25 16:50:21 -0500615 /*
616 * probe/allocate SoundWire resources.
617 * The hardware configuration takes place in hda_sdw_startup
618 * after power rails are enabled.
619 * It's entirely possible to have a mix of I2S/DMIC/SoundWire
620 * devices, so we allocate the resources in all cases.
621 */
622 ret = hda_sdw_probe(sdev);
623 if (ret < 0) {
624 dev_err(sdev->dev, "error: SoundWire probe error\n");
625 return ret;
626 }
627
628skip_soundwire:
629
Zhu Yingjiangbe1b5772019-05-24 14:09:24 -0500630#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500631 if (bus->mlcap)
632 snd_hdac_ext_bus_get_ml_capabilities(bus);
633
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500634 /* create codec instances */
Ranjani Sridharan80acdd42019-12-04 15:15:52 -0600635 hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi);
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500636
Kai Vehmanen0c754192020-01-20 18:01:16 +0200637 if (!HDA_IDISP_CODEC(bus->codec_mask))
Kai Vehmanen71cc8ab2020-02-20 19:10:28 +0200638 hda_codec_i915_display_power(sdev, false);
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500639
640 /*
641 * we are done probing so decrement link counts
642 */
643 list_for_each_entry(hlink, &bus->hlink_list, list)
644 snd_hdac_ext_bus_link_put(bus, hlink);
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500645#endif
Zhu Yingjiangbe1b5772019-05-24 14:09:24 -0500646 return 0;
647}
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500648
649static const struct sof_intel_dsp_desc
650 *get_chip_info(struct snd_sof_pdata *pdata)
651{
652 const struct sof_dev_desc *desc = pdata->desc;
653 const struct sof_intel_dsp_desc *chip_info;
654
655 chip_info = desc->chip_info;
656
657 return chip_info;
658}
659
Bard Liao7c11af92019-12-04 15:28:59 -0600660static irqreturn_t hda_dsp_interrupt_handler(int irq, void *context)
661{
662 struct snd_sof_dev *sdev = context;
663
664 /*
665 * Get global interrupt status. It includes all hardware interrupt
666 * sources in the Intel HD Audio controller.
667 */
668 if (snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS) &
669 SOF_HDA_INTSTS_GIS) {
670
671 /* disable GIE interrupt */
672 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
673 SOF_HDA_INTCTL,
674 SOF_HDA_INT_GLOBAL_EN,
675 0);
676
677 return IRQ_WAKE_THREAD;
678 }
679
680 return IRQ_NONE;
681}
682
683static irqreturn_t hda_dsp_interrupt_thread(int irq, void *context)
684{
685 struct snd_sof_dev *sdev = context;
Bard Liao722ba5f2020-03-25 16:50:23 -0500686 struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
Bard Liao7c11af92019-12-04 15:28:59 -0600687
688 /* deal with streams and controller first */
689 if (hda_dsp_check_stream_irq(sdev))
690 hda_dsp_stream_threaded_handler(irq, sdev);
691
692 if (hda_dsp_check_ipc_irq(sdev))
693 sof_ops(sdev)->irq_thread(irq, sdev);
694
Bard Liao722ba5f2020-03-25 16:50:23 -0500695 if (hda_dsp_check_sdw_irq(sdev))
696 hda_dsp_sdw_thread(irq, hdev->sdw);
697
Rander Wang90de3282020-03-25 16:50:26 -0500698 if (hda_sdw_check_wakeen_irq(sdev))
699 hda_sdw_process_wakeen(sdev);
700
Bard Liao7c11af92019-12-04 15:28:59 -0600701 /* enable GIE interrupt */
702 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
703 SOF_HDA_INTCTL,
704 SOF_HDA_INT_GLOBAL_EN,
705 SOF_HDA_INT_GLOBAL_EN);
706
707 return IRQ_HANDLED;
708}
709
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500710int hda_dsp_probe(struct snd_sof_dev *sdev)
711{
712 struct pci_dev *pci = to_pci_dev(sdev->dev);
713 struct sof_intel_hda_dev *hdev;
714 struct hdac_bus *bus;
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500715 const struct sof_intel_dsp_desc *chip;
Zhu Yingjiangbe1b5772019-05-24 14:09:24 -0500716 int ret = 0;
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500717
718 /*
719 * detect DSP by checking class/subclass/prog-id information
720 * class=04 subclass 03 prog-if 00: no DSP, legacy driver is required
721 * class=04 subclass 01 prog-if 00: DSP is present
722 * (and may be required e.g. for DMIC or SSP support)
723 * class=04 subclass 03 prog-if 80: either of DSP or legacy mode works
724 */
725 if (pci->class == 0x040300) {
726 dev_err(sdev->dev, "error: the DSP is not enabled on this platform, aborting probe\n");
727 return -ENODEV;
728 } else if (pci->class != 0x040100 && pci->class != 0x040380) {
729 dev_err(sdev->dev, "error: unknown PCI class/subclass/prog-if 0x%06x found, aborting probe\n", pci->class);
730 return -ENODEV;
731 }
732 dev_info(sdev->dev, "DSP detected with PCI class/subclass/prog-if 0x%06x\n", pci->class);
733
734 chip = get_chip_info(sdev->pdata);
735 if (!chip) {
736 dev_err(sdev->dev, "error: no such device supported, chip id:%x\n",
737 pci->device);
738 ret = -EIO;
739 goto err;
740 }
741
742 hdev = devm_kzalloc(sdev->dev, sizeof(*hdev), GFP_KERNEL);
743 if (!hdev)
744 return -ENOMEM;
745 sdev->pdata->hw_pdata = hdev;
746 hdev->desc = chip;
747
748 hdev->dmic_dev = platform_device_register_data(sdev->dev, "dmic-codec",
749 PLATFORM_DEVID_NONE,
750 NULL, 0);
751 if (IS_ERR(hdev->dmic_dev)) {
752 dev_err(sdev->dev, "error: failed to create DMIC device\n");
753 return PTR_ERR(hdev->dmic_dev);
754 }
755
756 /*
757 * use position update IPC if either it is forced
758 * or we don't have other choice
759 */
760#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_FORCE_IPC_POSITION)
761 hdev->no_ipc_position = 0;
762#else
763 hdev->no_ipc_position = sof_ops(sdev)->pcm_pointer ? 1 : 0;
764#endif
765
766 /* set up HDA base */
767 bus = sof_to_bus(sdev);
768 ret = hda_init(sdev);
769 if (ret < 0)
770 goto hdac_bus_unmap;
771
772 /* DSP base */
YueHaibingad169f92019-05-31 22:25:26 +0800773#if IS_ENABLED(CONFIG_PCI)
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500774 sdev->bar[HDA_DSP_BAR] = pci_ioremap_bar(pci, HDA_DSP_BAR);
YueHaibingad169f92019-05-31 22:25:26 +0800775#endif
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500776 if (!sdev->bar[HDA_DSP_BAR]) {
777 dev_err(sdev->dev, "error: ioremap error\n");
778 ret = -ENXIO;
779 goto hdac_bus_unmap;
780 }
781
782 sdev->mmio_bar = HDA_DSP_BAR;
783 sdev->mailbox_bar = HDA_DSP_BAR;
784
785 /* allow 64bit DMA address if supported by H/W */
786 if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(64))) {
787 dev_dbg(sdev->dev, "DMA mask is 64 bit\n");
788 dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(64));
789 } else {
790 dev_dbg(sdev->dev, "DMA mask is 32 bit\n");
791 dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
792 dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32));
793 }
794
795 /* init streams */
796 ret = hda_dsp_stream_init(sdev);
797 if (ret < 0) {
798 dev_err(sdev->dev, "error: failed to init streams\n");
799 /*
800 * not all errors are due to memory issues, but trying
801 * to free everything does not harm
802 */
803 goto free_streams;
804 }
805
806 /*
807 * register our IRQ
808 * let's try to enable msi firstly
809 * if it fails, use legacy interrupt mode
Guennadi Liakhovetski672ff5e2019-07-22 09:13:57 -0500810 * TODO: support msi multiple vectors
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500811 */
Pierre-Louis Bossartbb67dd12019-08-06 12:06:03 -0500812 if (hda_use_msi && pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI) > 0) {
Guennadi Liakhovetski672ff5e2019-07-22 09:13:57 -0500813 dev_info(sdev->dev, "use msi interrupt mode\n");
Bard Liao7c11af92019-12-04 15:28:59 -0600814 sdev->ipc_irq = pci_irq_vector(pci, 0);
Guennadi Liakhovetski672ff5e2019-07-22 09:13:57 -0500815 /* initialised to "false" by kzalloc() */
816 sdev->msi_enabled = true;
817 }
818
819 if (!sdev->msi_enabled) {
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500820 dev_info(sdev->dev, "use legacy interrupt mode\n");
821 /*
822 * in IO-APIC mode, hda->irq and ipc_irq are using the same
823 * irq number of pci->irq
824 */
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500825 sdev->ipc_irq = pci->irq;
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500826 }
827
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500828 dev_dbg(sdev->dev, "using IPC IRQ %d\n", sdev->ipc_irq);
Bard Liao7c11af92019-12-04 15:28:59 -0600829 ret = request_threaded_irq(sdev->ipc_irq, hda_dsp_interrupt_handler,
830 hda_dsp_interrupt_thread,
831 IRQF_SHARED, "AudioDSP", sdev);
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500832 if (ret < 0) {
833 dev_err(sdev->dev, "error: failed to register IPC IRQ %d\n",
834 sdev->ipc_irq);
Bard Liao7c11af92019-12-04 15:28:59 -0600835 goto free_irq_vector;
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500836 }
837
838 pci_set_master(pci);
839 synchronize_irq(pci->irq);
840
841 /*
842 * clear TCSEL to clear playback on some HD Audio
843 * codecs. PCI TCSEL is defined in the Intel manuals.
844 */
845 snd_sof_pci_update_bits(sdev, PCI_TCSEL, 0x07, 0);
846
847 /* init HDA capabilities */
848 ret = hda_init_caps(sdev);
849 if (ret < 0)
850 goto free_ipc_irq;
851
Zhu Yingjiang1f5253b2019-05-22 11:21:40 -0500852 /* enable ppcap interrupt */
853 hda_dsp_ctrl_ppcap_enable(sdev, true);
854 hda_dsp_ctrl_ppcap_int_enable(sdev, true);
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500855
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500856 /* set default mailbox offset for FW ready message */
857 sdev->dsp_box.offset = HDA_DSP_MBOX_UPLINK_OFFSET;
858
Ranjani Sridharan63e51fd32020-01-29 16:07:25 -0600859 INIT_DELAYED_WORK(&hdev->d0i3_work, hda_dsp_d0i3_work);
860
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500861 return 0;
862
863free_ipc_irq:
864 free_irq(sdev->ipc_irq, sdev);
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500865free_irq_vector:
866 if (sdev->msi_enabled)
867 pci_free_irq_vectors(pci);
868free_streams:
869 hda_dsp_stream_free(sdev);
870/* dsp_unmap: not currently used */
871 iounmap(sdev->bar[HDA_DSP_BAR]);
872hdac_bus_unmap:
873 iounmap(bus->remap_addr);
Kai Vehmanenaf7aae12020-02-06 22:02:23 +0200874 hda_codec_i915_exit(sdev);
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500875err:
876 return ret;
877}
878
879int hda_dsp_remove(struct snd_sof_dev *sdev)
880{
881 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
882 struct hdac_bus *bus = sof_to_bus(sdev);
883 struct pci_dev *pci = to_pci_dev(sdev->dev);
884 const struct sof_intel_dsp_desc *chip = hda->desc;
885
Ranjani Sridharan63e51fd32020-01-29 16:07:25 -0600886 /* cancel any attempt for DSP D0I3 */
887 cancel_delayed_work_sync(&hda->d0i3_work);
888
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500889#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
890 /* codec removal, invoke bus_device_remove */
891 snd_hdac_ext_bus_device_remove(bus);
892#endif
893
Pierre-Louis Bossart51dfed12020-03-25 16:50:18 -0500894 hda_sdw_exit(sdev);
895
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500896 if (!IS_ERR_OR_NULL(hda->dmic_dev))
897 platform_device_unregister(hda->dmic_dev);
898
899 /* disable DSP IRQ */
900 snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
901 SOF_HDA_PPCTL_PIE, 0);
902
903 /* disable CIE and GIE interrupts */
904 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
905 SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN, 0);
906
907 /* disable cores */
908 if (chip)
909 hda_dsp_core_reset_power_down(sdev, chip->cores_mask);
910
911 /* disable DSP */
912 snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
913 SOF_HDA_PPCTL_GPROCEN, 0);
914
915 free_irq(sdev->ipc_irq, sdev);
Liam Girdwooddd96dac2019-04-12 11:08:47 -0500916 if (sdev->msi_enabled)
917 pci_free_irq_vectors(pci);
918
919 hda_dsp_stream_free(sdev);
920#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
921 snd_hdac_link_free_all(bus);
922#endif
923
924 iounmap(sdev->bar[HDA_DSP_BAR]);
925 iounmap(bus->remap_addr);
926
927#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
928 snd_hdac_ext_bus_exit(bus);
929#endif
930 hda_codec_i915_exit(sdev);
931
932 return 0;
933}
934
Daniel Baluta285880a2019-12-04 15:15:53 -0600935#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
936static int hda_generic_machine_select(struct snd_sof_dev *sdev)
937{
938 struct hdac_bus *bus = sof_to_bus(sdev);
939 struct snd_soc_acpi_mach_params *mach_params;
940 struct snd_soc_acpi_mach *hda_mach;
941 struct snd_sof_pdata *pdata = sdev->pdata;
942 const char *tplg_filename;
943 const char *idisp_str;
944 const char *dmic_str;
945 int dmic_num = 0;
946 int codec_num = 0;
947 int i;
948
949 /* codec detection */
950 if (!bus->codec_mask) {
951 dev_info(bus->dev, "no hda codecs found!\n");
952 } else {
953 dev_info(bus->dev, "hda codecs found, mask %lx\n",
954 bus->codec_mask);
955
956 for (i = 0; i < HDA_MAX_CODECS; i++) {
957 if (bus->codec_mask & (1 << i))
958 codec_num++;
959 }
960
961 /*
962 * If no machine driver is found, then:
963 *
Kai Vehmanen71cc8ab2020-02-20 19:10:28 +0200964 * generic hda machine driver can handle:
965 * - one HDMI codec, and/or
966 * - one external HDAudio codec
Daniel Baluta285880a2019-12-04 15:15:53 -0600967 */
Kai Vehmanen71cc8ab2020-02-20 19:10:28 +0200968 if (!pdata->machine && codec_num <= 2) {
Daniel Baluta285880a2019-12-04 15:15:53 -0600969 hda_mach = snd_soc_acpi_intel_hda_machines;
970
971 /* topology: use the info from hda_machines */
972 pdata->tplg_filename =
973 hda_mach->sof_tplg_filename;
974
975 dev_info(bus->dev, "using HDA machine driver %s now\n",
976 hda_mach->drv_name);
977
Kai Vehmanen71cc8ab2020-02-20 19:10:28 +0200978 if (codec_num == 1 && HDA_IDISP_CODEC(bus->codec_mask))
Daniel Baluta285880a2019-12-04 15:15:53 -0600979 idisp_str = "-idisp";
980 else
981 idisp_str = "";
982
983 /* first check NHLT for DMICs */
984 dmic_num = check_nhlt_dmic(sdev);
985
986 /* allow for module parameter override */
987 if (hda_dmic_num != -1)
988 dmic_num = hda_dmic_num;
989
990 switch (dmic_num) {
991 case 2:
992 dmic_str = "-2ch";
993 break;
994 case 4:
995 dmic_str = "-4ch";
996 break;
997 default:
998 dmic_num = 0;
999 dmic_str = "";
1000 break;
1001 }
1002
1003 tplg_filename = pdata->tplg_filename;
1004 tplg_filename = fixup_tplg_name(sdev, tplg_filename,
1005 idisp_str, dmic_str);
1006 if (!tplg_filename)
1007 return -EINVAL;
1008
1009 pdata->machine = hda_mach;
1010 pdata->tplg_filename = tplg_filename;
1011 }
1012 }
1013
1014 /* used by hda machine driver to create dai links */
1015 if (pdata->machine) {
1016 mach_params = (struct snd_soc_acpi_mach_params *)
1017 &pdata->machine->mach_params;
1018 mach_params->codec_mask = bus->codec_mask;
1019 mach_params->common_hdmi_codec_drv = hda_codec_use_common_hdmi;
1020 mach_params->dmic_num = dmic_num;
1021 }
1022
1023 return 0;
1024}
1025#else
1026static int hda_generic_machine_select(struct snd_sof_dev *sdev)
1027{
1028 return 0;
1029}
1030#endif
1031
Pierre-Louis Bossartb9ddd812020-03-25 16:50:21 -05001032#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
1033/* Check if all Slaves defined on the link can be found */
1034static bool link_slaves_found(struct snd_sof_dev *sdev,
1035 const struct snd_soc_acpi_link_adr *link,
1036 struct sdw_intel_ctx *sdw)
1037{
1038 struct hdac_bus *bus = sof_to_bus(sdev);
1039 struct sdw_intel_slave_id *ids = sdw->ids;
1040 int num_slaves = sdw->num_slaves;
1041 unsigned int part_id, link_id, unique_id, mfg_id;
1042 int i, j;
1043
1044 for (i = 0; i < link->num_adr; i++) {
1045 u64 adr = link->adr_d[i].adr;
1046
1047 mfg_id = SDW_MFG_ID(adr);
1048 part_id = SDW_PART_ID(adr);
1049 link_id = SDW_DISCO_LINK_ID(adr);
1050 for (j = 0; j < num_slaves; j++) {
1051 if (ids[j].link_id != link_id ||
1052 ids[j].id.part_id != part_id ||
1053 ids[j].id.mfg_id != mfg_id)
1054 continue;
1055 /*
1056 * we have to check unique id
1057 * if there is more than one
1058 * Slave on the link
1059 */
1060 unique_id = SDW_UNIQUE_ID(adr);
1061 if (link->num_adr == 1 ||
1062 ids[j].id.unique_id == SDW_IGNORED_UNIQUE_ID ||
1063 ids[j].id.unique_id == unique_id) {
1064 dev_dbg(bus->dev,
1065 "found %x at link %d\n",
1066 part_id, link_id);
1067 break;
1068 }
1069 }
1070 if (j == num_slaves) {
1071 dev_dbg(bus->dev,
1072 "Slave %x not found\n",
1073 part_id);
1074 return false;
1075 }
1076 }
1077 return true;
1078}
1079
1080static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
1081{
1082 struct snd_sof_pdata *pdata = sdev->pdata;
1083 const struct snd_soc_acpi_link_adr *link;
1084 struct hdac_bus *bus = sof_to_bus(sdev);
1085 struct snd_soc_acpi_mach *mach;
1086 struct sof_intel_hda_dev *hdev;
1087 u32 link_mask;
1088 int i;
1089
1090 hdev = pdata->hw_pdata;
1091 link_mask = hdev->info.link_mask;
1092
1093 /*
1094 * Select SoundWire machine driver if needed using the
1095 * alternate tables. This case deals with SoundWire-only
1096 * machines, for mixed cases with I2C/I2S the detection relies
1097 * on the HID list.
1098 */
1099 if (link_mask && !pdata->machine) {
1100 for (mach = pdata->desc->alt_machines;
1101 mach && mach->link_mask; mach++) {
1102 if (mach->link_mask != link_mask)
1103 continue;
1104
1105 /* No need to match adr if there is no links defined */
1106 if (!mach->links)
1107 break;
1108
1109 link = mach->links;
1110 for (i = 0; i < hdev->info.count && link->num_adr;
1111 i++, link++) {
1112 /*
1113 * Try next machine if any expected Slaves
1114 * are not found on this link.
1115 */
1116 if (!link_slaves_found(sdev, link, hdev->sdw))
1117 break;
1118 }
1119 /* Found if all Slaves are checked */
1120 if (i == hdev->info.count || !link->num_adr)
1121 break;
1122 }
1123 if (mach && mach->link_mask) {
1124 dev_dbg(bus->dev,
1125 "SoundWire machine driver %s topology %s\n",
1126 mach->drv_name,
1127 mach->sof_tplg_filename);
1128 pdata->machine = mach;
1129 mach->mach_params.links = mach->links;
1130 mach->mach_params.link_mask = mach->link_mask;
1131 mach->mach_params.platform = dev_name(sdev->dev);
1132 pdata->fw_filename = mach->sof_fw_filename;
1133 pdata->tplg_filename = mach->sof_tplg_filename;
1134 } else {
1135 dev_info(sdev->dev,
1136 "No SoundWire machine driver found\n");
1137 }
1138 }
1139
1140 return 0;
1141}
1142#else
1143static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
1144{
1145 return 0;
1146}
1147#endif
1148
Daniel Baluta285880a2019-12-04 15:15:53 -06001149void hda_set_mach_params(const struct snd_soc_acpi_mach *mach,
1150 struct device *dev)
1151{
1152 struct snd_soc_acpi_mach_params *mach_params;
1153
1154 mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params;
1155 mach_params->platform = dev_name(dev);
1156}
1157
1158void hda_machine_select(struct snd_sof_dev *sdev)
1159{
1160 struct snd_sof_pdata *sof_pdata = sdev->pdata;
1161 const struct sof_dev_desc *desc = sof_pdata->desc;
1162 struct snd_soc_acpi_mach *mach;
1163
1164 mach = snd_soc_acpi_find_machine(desc->machines);
1165 if (mach) {
1166 sof_pdata->tplg_filename = mach->sof_tplg_filename;
1167 sof_pdata->machine = mach;
Pierre-Louis Bossartb9ddd812020-03-25 16:50:21 -05001168
1169 if (mach->link_mask) {
1170 mach->mach_params.links = mach->links;
1171 mach->mach_params.link_mask = mach->link_mask;
1172 }
Daniel Baluta285880a2019-12-04 15:15:53 -06001173 }
1174
1175 /*
Pierre-Louis Bossartb9ddd812020-03-25 16:50:21 -05001176 * If I2S fails, try SoundWire
1177 */
1178 hda_sdw_machine_select(sdev);
1179
1180 /*
Daniel Baluta285880a2019-12-04 15:15:53 -06001181 * Choose HDA generic machine driver if mach is NULL.
1182 * Otherwise, set certain mach params.
1183 */
1184 hda_generic_machine_select(sdev);
1185
1186 if (!sof_pdata->machine)
1187 dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
1188}
1189
Liam Girdwooddd96dac2019-04-12 11:08:47 -05001190MODULE_LICENSE("Dual BSD/GPL");
Pierre-Louis Bossart5bd216c2019-12-17 14:22:29 -06001191MODULE_IMPORT_NS(SND_SOC_SOF_HDA_AUDIO_CODEC);
1192MODULE_IMPORT_NS(SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
Pierre-Louis Bossart068ac0d2019-12-17 14:22:31 -06001193MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);