]> Git Repo - linux.git/blame - sound/soc/sof/intel/mtl.c
ASoC: SOF: Intel: Enable d0i3 work for ipc4
[linux.git] / sound / soc / sof / intel / mtl.c
CommitLineData
064520e8
BL
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2//
3// Copyright(c) 2022 Intel Corporation. All rights reserved.
4//
5// Authors: Ranjani Sridharan <[email protected]>
6//
7
8/*
9 * Hardware interface for audio DSP on Meteorlake.
10 */
11
12#include <linux/firmware.h>
13#include <sound/sof/ipc4/header.h>
d272b657 14#include <trace/events/sof_intel.h>
064520e8
BL
15#include "../ipc4-priv.h"
16#include "../ops.h"
17#include "hda.h"
18#include "hda-ipc.h"
19#include "../sof-audio.h"
20#include "mtl.h"
21
22static const struct snd_sof_debugfs_map mtl_dsp_debugfs[] = {
23 {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
24 {"pp", HDA_DSP_PP_BAR, 0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS},
25 {"dsp", HDA_DSP_BAR, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS},
26};
27
28static void mtl_ipc_host_done(struct snd_sof_dev *sdev)
29{
30 /*
31 * clear busy interrupt to tell dsp controller this interrupt has been accepted,
32 * not trigger it again
33 */
34 snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR,
35 MTL_DSP_REG_HFIPCXTDR_BUSY, MTL_DSP_REG_HFIPCXTDR_BUSY);
36 /*
37 * clear busy bit to ack dsp the msg has been processed and send reply msg to dsp
38 */
39 snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDA,
40 MTL_DSP_REG_HFIPCXTDA_BUSY, 0);
41}
42
43static void mtl_ipc_dsp_done(struct snd_sof_dev *sdev)
44{
45 /*
46 * set DONE bit - tell DSP we have received the reply msg from DSP, and processed it,
47 * don't send more reply to host
48 */
49 snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA,
50 MTL_DSP_REG_HFIPCXIDA_DONE, MTL_DSP_REG_HFIPCXIDA_DONE);
51
52 /* unmask Done interrupt */
53 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL,
54 MTL_DSP_REG_HFIPCXCTL_DONE, MTL_DSP_REG_HFIPCXCTL_DONE);
55}
56
57/* Check if an IPC IRQ occurred */
58static bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev)
59{
60 u32 irq_status;
61 u32 hfintipptr;
62
63 /* read Interrupt IP Pointer */
64 hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK;
65 irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, hfintipptr + MTL_DSP_IRQSTS);
66
d272b657 67 trace_sof_intel_hda_irq_ipc_check(sdev, irq_status);
064520e8
BL
68
69 if (irq_status != U32_MAX && (irq_status & MTL_DSP_IRQSTS_IPC))
70 return true;
71
72 return false;
73}
74
75/* Check if an SDW IRQ occurred */
76static bool mtl_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
77{
78 u32 irq_status;
79 u32 hfintipptr;
80
81 /* read Interrupt IP Pointer */
82 hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK;
83 irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, hfintipptr + MTL_DSP_IRQSTS);
84
85 if (irq_status != U32_MAX && (irq_status & MTL_DSP_IRQSTS_SDW))
86 return true;
87
88 return false;
89}
90
91static int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
92{
483e4cdf 93 struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
064520e8
BL
94 struct sof_ipc4_msg *msg_data = msg->msg_data;
95
483e4cdf
PU
96 if (hda_ipc4_tx_is_busy(sdev)) {
97 hdev->delayed_ipc_tx_msg = msg;
98 return 0;
99 }
100
101 hdev->delayed_ipc_tx_msg = NULL;
102
064520e8
BL
103 /* send the message via mailbox */
104 if (msg_data->data_size)
105 sof_mailbox_write(sdev, sdev->host_box.offset, msg_data->data_ptr,
106 msg_data->data_size);
107
108 snd_sof_dsp_write(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDDY,
109 msg_data->extension);
110 snd_sof_dsp_write(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDR,
111 msg_data->primary | MTL_DSP_REG_HFIPCXIDR_BUSY);
112
3e6b6ed3
RW
113 hda_dsp_ipc4_schedule_d0i3_work(hdev, msg);
114
064520e8
BL
115 return 0;
116}
117
118static void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev)
119{
120 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
121 const struct sof_intel_dsp_desc *chip = hda->desc;
122
123 /* enable IPC DONE and BUSY interrupts */
124 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
125 MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE,
126 MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE);
127}
128
129static void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev)
130{
131 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
132 const struct sof_intel_dsp_desc *chip = hda->desc;
133
134 /* disable IPC DONE and BUSY interrupts */
135 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
136 MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE, 0);
137}
138
aa70a580
PLB
139static void mtl_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable)
140{
141 u32 hipcie;
142 u32 mask;
143 u32 val;
144 int ret;
145
146 /* Enable/Disable SoundWire interrupt */
147 mask = MTL_DSP_REG_HfSNDWIE_IE_MASK;
148 if (enable)
149 val = mask;
150 else
151 val = 0;
152
153 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE, mask, val);
154
155 /* check if operation was successful */
156 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE, hipcie,
157 (hipcie & mask) == val,
158 HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US);
159 if (ret < 0)
160 dev_err(sdev->dev, "failed to set SoundWire IPC interrupt %s\n",
161 enable ? "enable" : "disable");
162}
163
00f4f338 164static int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable)
064520e8
BL
165{
166 u32 hfintipptr;
167 u32 irqinten;
064520e8 168 u32 hipcie;
00f4f338
PLB
169 u32 mask;
170 u32 val;
064520e8
BL
171 int ret;
172
173 /* read Interrupt IP Pointer */
174 hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK;
175
00f4f338
PLB
176 /* Enable/Disable Host IPC and SOUNDWIRE */
177 mask = MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK;
178 if (enable)
179 val = mask;
180 else
181 val = 0;
182
183 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, hfintipptr, mask, val);
064520e8
BL
184
185 /* check if operation was successful */
064520e8 186 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, hfintipptr, irqinten,
00f4f338 187 (irqinten & mask) == val,
064520e8
BL
188 HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US);
189 if (ret < 0) {
00f4f338
PLB
190 dev_err(sdev->dev, "failed to %s Host IPC and/or SOUNDWIRE\n",
191 enable ? "enable" : "disable");
064520e8
BL
192 return ret;
193 }
194
00f4f338
PLB
195 /* Enable/Disable Host IPC interrupt*/
196 mask = MTL_DSP_REG_HfHIPCIE_IE_MASK;
197 if (enable)
198 val = mask;
199 else
200 val = 0;
201
202 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE, mask, val);
064520e8
BL
203
204 /* check if operation was successful */
064520e8 205 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE, hipcie,
00f4f338 206 (hipcie & mask) == val,
064520e8
BL
207 HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US);
208 if (ret < 0) {
00f4f338
PLB
209 dev_err(sdev->dev, "failed to set Host IPC interrupt %s\n",
210 enable ? "enable" : "disable");
064520e8
BL
211 return ret;
212 }
213
064520e8
BL
214 return ret;
215}
216
217/* pre fw run operations */
218static int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev)
219{
220 u32 dsphfpwrsts;
221 u32 dsphfdsscs;
222 u32 cpa;
223 u32 pgs;
224 int ret;
225
226 /* Set the DSP subsystem power on */
227 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFDSSCS,
228 MTL_HFDSSCS_SPA_MASK, MTL_HFDSSCS_SPA_MASK);
229
230 /* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */
231 usleep_range(1000, 1010);
232
233 /* poll with timeout to check if operation successful */
234 cpa = MTL_HFDSSCS_CPA_MASK;
064520e8
BL
235 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFDSSCS, dsphfdsscs,
236 (dsphfdsscs & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US,
237 HDA_DSP_RESET_TIMEOUT_US);
238 if (ret < 0) {
239 dev_err(sdev->dev, "failed to enable DSP subsystem\n");
240 return ret;
241 }
242
243 /* Power up gated-DSP-0 domain in order to access the DSP shim register block. */
244 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFPWRCTL,
245 MTL_HFPWRCTL_WPDSPHPXPG, MTL_HFPWRCTL_WPDSPHPXPG);
246
247 usleep_range(1000, 1010);
248
249 /* poll with timeout to check if operation successful */
250 pgs = MTL_HFPWRSTS_DSPHPXPGS_MASK;
064520e8
BL
251 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFPWRSTS, dsphfpwrsts,
252 (dsphfpwrsts & pgs) == pgs,
253 HDA_DSP_REG_POLL_INTERVAL_US,
254 HDA_DSP_RESET_TIMEOUT_US);
255 if (ret < 0)
256 dev_err(sdev->dev, "failed to power up gated DSP domain\n");
257
258 /* make sure SoundWire is not power-gated */
259 snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, MTL_HFPWRCTL,
260 MTL_HfPWRCTL_WPIOXPG(1), MTL_HfPWRCTL_WPIOXPG(1));
261 return ret;
262}
263
264static int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev)
265{
266 int ret;
267
268 if (sdev->first_boot) {
269 struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
270
271 ret = hda_sdw_startup(sdev);
272 if (ret < 0) {
273 dev_err(sdev->dev, "could not startup SoundWire links\n");
274 return ret;
275 }
276
277 /* Check if IMR boot is usable */
278 if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT))
279 hdev->imrboot_supported = true;
280 }
281
282 hda_sdw_int_enable(sdev, true);
283 return 0;
284}
285
286static void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
287{
288 char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR;
289 u32 romdbgsts;
290 u32 romdbgerr;
291 u32 fwsts;
292 u32 fwlec;
293
294 fwsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_STS);
295 fwlec = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_ERROR);
296 romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY);
297 romdbgerr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY_ERROR);
298
299 dev_err(sdev->dev, "ROM status: %#x, ROM error: %#x\n", fwsts, fwlec);
300 dev_err(sdev->dev, "ROM debug status: %#x, ROM debug error: %#x\n", romdbgsts,
301 romdbgerr);
302 romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY + 0x8 * 3);
303 dev_printk(level, sdev->dev, "ROM feature bit%s enabled\n",
304 romdbgsts & BIT(24) ? "" : " not");
305}
306
307static bool mtl_dsp_primary_core_is_enabled(struct snd_sof_dev *sdev)
308{
309 int val;
310
311 val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE);
312 if (val != U32_MAX && val & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK)
313 return true;
314
315 return false;
316}
317
318static int mtl_dsp_core_power_up(struct snd_sof_dev *sdev, int core)
319{
320 unsigned int cpa;
321 u32 dspcxctl;
322 int ret;
323
324 /* Only the primary core can be powered up by the host */
325 if (core != SOF_DSP_PRIMARY_CORE || mtl_dsp_primary_core_is_enabled(sdev))
326 return 0;
327
328 /* Program the owner of the IP & shim registers (10: Host CPU) */
329 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE,
330 MTL_DSP2CXCTL_PRIMARY_CORE_OSEL,
331 0x2 << MTL_DSP2CXCTL_PRIMARY_CORE_OSEL_SHIFT);
332
333 /* enable SPA bit */
334 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE,
335 MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK,
336 MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK);
337
338 /* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */
339 usleep_range(1000, 1010);
340
341 /* poll with timeout to check if operation successful */
342 cpa = MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK;
343 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl,
344 (dspcxctl & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US,
345 HDA_DSP_RESET_TIMEOUT_US);
740e5d87 346 if (ret < 0)
064520e8
BL
347 dev_err(sdev->dev, "%s: timeout on MTL_DSP2CXCTL_PRIMARY_CORE read\n",
348 __func__);
064520e8
BL
349
350 return ret;
351}
352
353static int mtl_dsp_core_power_down(struct snd_sof_dev *sdev, int core)
354{
355 u32 dspcxctl;
356 int ret;
357
358 /* Only the primary core can be powered down by the host */
359 if (core != SOF_DSP_PRIMARY_CORE || !mtl_dsp_primary_core_is_enabled(sdev))
360 return 0;
361
362 /* disable SPA bit */
363 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE,
364 MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK, 0);
365
514bc59b 366 /* Wait for unstable CPA read (0 then 1 then 0) just after setting SPA bit */
064520e8
BL
367 usleep_range(1000, 1010);
368
369 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl,
370 !(dspcxctl & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK),
371 HDA_DSP_REG_POLL_INTERVAL_US,
372 HDA_DSP_PD_TIMEOUT * USEC_PER_MSEC);
373 if (ret < 0)
374 dev_err(sdev->dev, "failed to power down primary core\n");
375
376 return ret;
377}
378
2090cb9b
FO
379static int mtl_power_down_dsp(struct snd_sof_dev *sdev)
380{
381 u32 dsphfdsscs, cpa;
382 int ret;
383
384 /* first power down core */
385 ret = mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE);
386 if (ret) {
387 dev_err(sdev->dev, "mtl dsp power down error, %d\n", ret);
388 return ret;
389 }
390
391 /* Set the DSP subsystem power down */
392 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFDSSCS,
393 MTL_HFDSSCS_SPA_MASK, 0);
394
514bc59b 395 /* Wait for unstable CPA read (0 then 1 then 0) just after setting SPA bit */
2090cb9b
FO
396 usleep_range(1000, 1010);
397
398 /* poll with timeout to check if operation successful */
399 cpa = MTL_HFDSSCS_CPA_MASK;
400 dsphfdsscs = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFDSSCS);
401 return snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFDSSCS, dsphfdsscs,
402 (dsphfdsscs & cpa) == 0, HDA_DSP_REG_POLL_INTERVAL_US,
403 HDA_DSP_RESET_TIMEOUT_US);
404}
405
064520e8
BL
406static int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
407{
408 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
409 const struct sof_intel_dsp_desc *chip = hda->desc;
410 unsigned int status;
411 u32 ipc_hdr;
412 int ret;
413
414 /* step 1: purge FW request */
415 ipc_hdr = chip->ipc_req_mask | HDA_DSP_ROM_IPC_CONTROL;
416 if (!imr_boot)
417 ipc_hdr |= HDA_DSP_ROM_IPC_PURGE_FW | ((stream_tag - 1) << 9);
418
419 snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req, ipc_hdr);
420
421 /* step 2: power up primary core */
422 ret = mtl_dsp_core_power_up(sdev, SOF_DSP_PRIMARY_CORE);
423 if (ret < 0) {
424 if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
425 dev_err(sdev->dev, "dsp core 0/1 power up failed\n");
426 goto err;
427 }
428
429 dev_dbg(sdev->dev, "Primary core power up successful\n");
430
431 /* step 3: wait for IPC DONE bit from ROM */
432 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, chip->ipc_ack, status,
433 ((status & chip->ipc_ack_mask) == chip->ipc_ack_mask),
434 HDA_DSP_REG_POLL_INTERVAL_US, MTL_DSP_PURGE_TIMEOUT_US);
435 if (ret < 0) {
436 if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
437 dev_err(sdev->dev, "timeout waiting for purge IPC done\n");
438 goto err;
439 }
440
441 /* set DONE bit to clear the reply IPC message */
442 snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, chip->ipc_ack, chip->ipc_ack_mask,
443 chip->ipc_ack_mask);
444
445 /* step 4: enable interrupts */
00f4f338 446 ret = mtl_enable_interrupts(sdev, true);
064520e8
BL
447 if (ret < 0) {
448 if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
449 dev_err(sdev->dev, "%s: failed to enable interrupts\n", __func__);
450 goto err;
451 }
452
453 mtl_enable_ipc_interrupts(sdev);
454
455 /*
456 * ACE workaround: don't wait for ROM INIT.
457 * The platform cannot catch ROM_INIT_DONE because of a very short
458 * timing window. Follow the recommendations and skip this part.
459 */
460
461 return 0;
462
463err:
464 snd_sof_dsp_dbg_dump(sdev, "MTL DSP init fail", 0);
465 mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE);
466 return ret;
467}
468
469static irqreturn_t mtl_ipc_irq_thread(int irq, void *context)
470{
471 struct sof_ipc4_msg notification_data = {{ 0 }};
472 struct snd_sof_dev *sdev = context;
483e4cdf 473 bool ack_received = false;
064520e8
BL
474 bool ipc_irq = false;
475 u32 hipcida;
476 u32 hipctdr;
477
478 hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA);
c8ed7ce2 479 hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR);
064520e8
BL
480
481 /* reply message from DSP */
482 if (hipcida & MTL_DSP_REG_HFIPCXIDA_DONE) {
483 /* DSP received the message */
484 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL,
485 MTL_DSP_REG_HFIPCXCTL_DONE, 0);
486
487 mtl_ipc_dsp_done(sdev);
488
489 ipc_irq = true;
483e4cdf 490 ack_received = true;
064520e8
BL
491 }
492
064520e8
BL
493 if (hipctdr & MTL_DSP_REG_HFIPCXTDR_BUSY) {
494 /* Message from DSP (reply or notification) */
495 u32 extension = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDDY);
496 u32 primary = hipctdr & MTL_DSP_REG_HFIPCXTDR_MSG_MASK;
497
498 /*
499 * ACE fw sends a new fw ipc message to host to
500 * notify the status of the last host ipc message
501 */
502 if (primary & SOF_IPC4_MSG_DIR_MASK) {
503 /* Reply received */
1549a69b
PU
504 if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
505 struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
064520e8 506
1549a69b
PU
507 data->primary = primary;
508 data->extension = extension;
064520e8 509
1549a69b 510 spin_lock_irq(&sdev->ipc_lock);
064520e8 511
1549a69b 512 snd_sof_ipc_get_reply(sdev);
010c050f 513 mtl_ipc_host_done(sdev);
1549a69b 514 snd_sof_ipc_reply(sdev, data->primary);
064520e8 515
1549a69b
PU
516 spin_unlock_irq(&sdev->ipc_lock);
517 } else {
518 dev_dbg_ratelimited(sdev->dev,
519 "IPC reply before FW_READY: %#x|%#x\n",
520 primary, extension);
521 }
064520e8
BL
522 } else {
523 /* Notification received */
524 notification_data.primary = primary;
525 notification_data.extension = extension;
526
527 sdev->ipc->msg.rx_data = &notification_data;
528 snd_sof_ipc_msgs_rx(sdev);
529 sdev->ipc->msg.rx_data = NULL;
064520e8 530
010c050f
PU
531 mtl_ipc_host_done(sdev);
532 }
064520e8
BL
533
534 ipc_irq = true;
535 }
536
537 if (!ipc_irq) {
538 /* This interrupt is not shared so no need to return IRQ_NONE. */
b837870f 539 dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n");
064520e8
BL
540 }
541
483e4cdf
PU
542 if (ack_received) {
543 struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
544
545 if (hdev->delayed_ipc_tx_msg)
546 mtl_ipc_send_msg(sdev, hdev->delayed_ipc_tx_msg);
547 }
548
064520e8
BL
549 return IRQ_HANDLED;
550}
551
552static int mtl_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev)
553{
554 return MTL_DSP_MBOX_UPLINK_OFFSET;
555}
556
557static int mtl_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id)
558{
559 return MTL_SRAM_WINDOW_OFFSET(id);
560}
561
064520e8
BL
562static void mtl_ipc_dump(struct snd_sof_dev *sdev)
563{
d01784ee 564 u32 hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl;
064520e8 565
d01784ee
PU
566 hipcidr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDR);
567 hipcidd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDDY);
064520e8 568 hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA);
064520e8 569 hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR);
d01784ee
PU
570 hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDDY);
571 hipctda = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDA);
572 hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL);
064520e8 573
064520e8 574 dev_err(sdev->dev,
d01784ee
PU
575 "Host IPC initiator: %#x|%#x|%#x, target: %#x|%#x|%#x, ctl: %#x\n",
576 hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl);
064520e8
BL
577}
578
39df087f
RS
579static int mtl_dsp_disable_interrupts(struct snd_sof_dev *sdev)
580{
aa70a580 581 mtl_enable_sdw_irq(sdev, false);
39df087f 582 mtl_disable_ipc_interrupts(sdev);
00f4f338 583 return mtl_enable_interrupts(sdev, false);
39df087f
RS
584}
585
faceb344
RW
586static u64 mtl_dsp_get_stream_hda_link_position(struct snd_sof_dev *sdev,
587 struct snd_soc_component *component,
588 struct snd_pcm_substream *substream)
589{
590 struct hdac_stream *hstream = substream->runtime->private_data;
591 u32 llp_l, llp_u;
592
593 llp_l = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, MTL_PPLCLLPL(hstream->index));
594 llp_u = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, MTL_PPLCLLPU(hstream->index));
595 return ((u64)llp_u << 32) | llp_l;
596}
597
064520e8
BL
598/* Meteorlake ops */
599struct snd_sof_dsp_ops sof_mtl_ops;
600EXPORT_SYMBOL_NS(sof_mtl_ops, SND_SOC_SOF_INTEL_HDA_COMMON);
601
602int sof_mtl_ops_init(struct snd_sof_dev *sdev)
603{
604 struct sof_ipc4_fw_data *ipc4_data;
605
606 /* common defaults */
607 memcpy(&sof_mtl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops));
608
609 /* shutdown */
610 sof_mtl_ops.shutdown = hda_dsp_shutdown;
611
612 /* doorbell */
613 sof_mtl_ops.irq_thread = mtl_ipc_irq_thread;
614
615 /* ipc */
616 sof_mtl_ops.send_msg = mtl_ipc_send_msg;
617 sof_mtl_ops.get_mailbox_offset = mtl_dsp_ipc_get_mailbox_offset;
618 sof_mtl_ops.get_window_offset = mtl_dsp_ipc_get_window_offset;
619
620 /* debug */
621 sof_mtl_ops.debug_map = mtl_dsp_debugfs;
622 sof_mtl_ops.debug_map_count = ARRAY_SIZE(mtl_dsp_debugfs);
623 sof_mtl_ops.dbg_dump = mtl_dsp_dump;
624 sof_mtl_ops.ipc_dump = mtl_ipc_dump;
625
626 /* pre/post fw run */
627 sof_mtl_ops.pre_fw_run = mtl_dsp_pre_fw_run;
628 sof_mtl_ops.post_fw_run = mtl_dsp_post_fw_run;
629
630 /* parse platform specific extended manifest */
631 sof_mtl_ops.parse_platform_ext_manifest = NULL;
632
633 /* dsp core get/put */
634 /* TODO: add core_get and core_put */
635
faceb344
RW
636 sof_mtl_ops.get_stream_position = mtl_dsp_get_stream_hda_link_position;
637
064520e8
BL
638 sdev->private = devm_kzalloc(sdev->dev, sizeof(struct sof_ipc4_fw_data), GFP_KERNEL);
639 if (!sdev->private)
640 return -ENOMEM;
641
642 ipc4_data = sdev->private;
643 ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET;
644
cc4a3a19
PU
645 ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_2;
646
3ab2c21e
PU
647 /* External library loading support */
648 ipc4_data->load_library = hda_dsp_ipc4_load_library;
649
064520e8
BL
650 /* set DAI ops */
651 hda_set_dai_drv_ops(sdev, &sof_mtl_ops);
652
653 return 0;
654};
655EXPORT_SYMBOL_NS(sof_mtl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON);
656
657const struct sof_intel_dsp_desc mtl_chip_info = {
658 .cores_num = 3,
659 .init_core_mask = BIT(0),
660 .host_managed_cores_mask = BIT(0),
661 .ipc_req = MTL_DSP_REG_HFIPCXIDR,
662 .ipc_req_mask = MTL_DSP_REG_HFIPCXIDR_BUSY,
663 .ipc_ack = MTL_DSP_REG_HFIPCXIDA,
664 .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE,
665 .ipc_ctl = MTL_DSP_REG_HFIPCXCTL,
666 .rom_status_reg = MTL_DSP_ROM_STS,
667 .rom_init_timeout = 300,
9ccbc2e1 668 .ssp_count = MTL_SSP_COUNT,
064520e8
BL
669 .ssp_base_offset = CNL_SSP_BASE_OFFSET,
670 .sdw_shim_base = SDW_SHIM_BASE_ACE,
671 .sdw_alh_base = SDW_ALH_BASE_ACE,
f8632adc 672 .d0i3_offset = MTL_HDA_VS_D0I3C,
625339ca 673 .read_sdw_lcount = hda_sdw_check_lcount_common,
aa70a580 674 .enable_sdw_irq = mtl_enable_sdw_irq,
064520e8
BL
675 .check_sdw_irq = mtl_dsp_check_sdw_irq,
676 .check_ipc_irq = mtl_dsp_check_ipc_irq,
677 .cl_init = mtl_dsp_cl_init,
2090cb9b 678 .power_down_dsp = mtl_power_down_dsp,
39df087f 679 .disable_interrupts = mtl_dsp_disable_interrupts,
064520e8
BL
680 .hw_ip_version = SOF_INTEL_ACE_1_0,
681};
682EXPORT_SYMBOL_NS(mtl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
This page took 0.266637 seconds and 4 git commands to generate.