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