xref: /openbmc/linux/sound/soc/sof/intel/mtl.c (revision 3ab2c21e65188cac151de1fbe6adf841f2ecb082)
1064520e8SBard Liao // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2064520e8SBard Liao //
3064520e8SBard Liao // Copyright(c) 2022 Intel Corporation. All rights reserved.
4064520e8SBard Liao //
5064520e8SBard Liao // Authors: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
6064520e8SBard Liao //
7064520e8SBard Liao 
8064520e8SBard Liao /*
9064520e8SBard Liao  * Hardware interface for audio DSP on Meteorlake.
10064520e8SBard Liao  */
11064520e8SBard Liao 
12064520e8SBard Liao #include <linux/firmware.h>
13064520e8SBard Liao #include <sound/sof/ipc4/header.h>
14d272b657SBard Liao #include <trace/events/sof_intel.h>
15064520e8SBard Liao #include "../ipc4-priv.h"
16064520e8SBard Liao #include "../ops.h"
17064520e8SBard Liao #include "hda.h"
18064520e8SBard Liao #include "hda-ipc.h"
19064520e8SBard Liao #include "../sof-audio.h"
20064520e8SBard Liao #include "mtl.h"
21064520e8SBard Liao 
22064520e8SBard Liao static const struct snd_sof_debugfs_map mtl_dsp_debugfs[] = {
23064520e8SBard Liao 	{"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
24064520e8SBard Liao 	{"pp", HDA_DSP_PP_BAR,  0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS},
25064520e8SBard Liao 	{"dsp", HDA_DSP_BAR,  0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS},
26064520e8SBard Liao };
27064520e8SBard Liao 
28064520e8SBard Liao static void mtl_ipc_host_done(struct snd_sof_dev *sdev)
29064520e8SBard Liao {
30064520e8SBard Liao 	/*
31064520e8SBard Liao 	 * clear busy interrupt to tell dsp controller this interrupt has been accepted,
32064520e8SBard Liao 	 * not trigger it again
33064520e8SBard Liao 	 */
34064520e8SBard Liao 	snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR,
35064520e8SBard Liao 				       MTL_DSP_REG_HFIPCXTDR_BUSY, MTL_DSP_REG_HFIPCXTDR_BUSY);
36064520e8SBard Liao 	/*
37064520e8SBard Liao 	 * clear busy bit to ack dsp the msg has been processed and send reply msg to dsp
38064520e8SBard Liao 	 */
39064520e8SBard Liao 	snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDA,
40064520e8SBard Liao 				       MTL_DSP_REG_HFIPCXTDA_BUSY, 0);
41064520e8SBard Liao }
42064520e8SBard Liao 
43064520e8SBard Liao static void mtl_ipc_dsp_done(struct snd_sof_dev *sdev)
44064520e8SBard Liao {
45064520e8SBard Liao 	/*
46064520e8SBard Liao 	 * set DONE bit - tell DSP we have received the reply msg from DSP, and processed it,
47064520e8SBard Liao 	 * don't send more reply to host
48064520e8SBard Liao 	 */
49064520e8SBard Liao 	snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA,
50064520e8SBard Liao 				       MTL_DSP_REG_HFIPCXIDA_DONE, MTL_DSP_REG_HFIPCXIDA_DONE);
51064520e8SBard Liao 
52064520e8SBard Liao 	/* unmask Done interrupt */
53064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL,
54064520e8SBard Liao 				MTL_DSP_REG_HFIPCXCTL_DONE, MTL_DSP_REG_HFIPCXCTL_DONE);
55064520e8SBard Liao }
56064520e8SBard Liao 
57064520e8SBard Liao /* Check if an IPC IRQ occurred */
58064520e8SBard Liao static bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev)
59064520e8SBard Liao {
60064520e8SBard Liao 	u32 irq_status;
61064520e8SBard Liao 	u32 hfintipptr;
62064520e8SBard Liao 
63064520e8SBard Liao 	/* read Interrupt IP Pointer */
64064520e8SBard Liao 	hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK;
65064520e8SBard Liao 	irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, hfintipptr + MTL_DSP_IRQSTS);
66064520e8SBard Liao 
67d272b657SBard Liao 	trace_sof_intel_hda_irq_ipc_check(sdev, irq_status);
68064520e8SBard Liao 
69064520e8SBard Liao 	if (irq_status != U32_MAX && (irq_status & MTL_DSP_IRQSTS_IPC))
70064520e8SBard Liao 		return true;
71064520e8SBard Liao 
72064520e8SBard Liao 	return false;
73064520e8SBard Liao }
74064520e8SBard Liao 
75064520e8SBard Liao /* Check if an SDW IRQ occurred */
76064520e8SBard Liao static bool mtl_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
77064520e8SBard Liao {
78064520e8SBard Liao 	u32 irq_status;
79064520e8SBard Liao 	u32 hfintipptr;
80064520e8SBard Liao 
81064520e8SBard Liao 	/* read Interrupt IP Pointer */
82064520e8SBard Liao 	hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK;
83064520e8SBard Liao 	irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, hfintipptr + MTL_DSP_IRQSTS);
84064520e8SBard Liao 
85064520e8SBard Liao 	if (irq_status != U32_MAX && (irq_status & MTL_DSP_IRQSTS_SDW))
86064520e8SBard Liao 		return true;
87064520e8SBard Liao 
88064520e8SBard Liao 	return false;
89064520e8SBard Liao }
90064520e8SBard Liao 
91064520e8SBard Liao static int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
92064520e8SBard Liao {
93064520e8SBard Liao 	struct sof_ipc4_msg *msg_data = msg->msg_data;
94064520e8SBard Liao 
95064520e8SBard Liao 	/* send the message via mailbox */
96064520e8SBard Liao 	if (msg_data->data_size)
97064520e8SBard Liao 		sof_mailbox_write(sdev, sdev->host_box.offset, msg_data->data_ptr,
98064520e8SBard Liao 				  msg_data->data_size);
99064520e8SBard Liao 
100064520e8SBard Liao 	snd_sof_dsp_write(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDDY,
101064520e8SBard Liao 			  msg_data->extension);
102064520e8SBard Liao 	snd_sof_dsp_write(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDR,
103064520e8SBard Liao 			  msg_data->primary | MTL_DSP_REG_HFIPCXIDR_BUSY);
104064520e8SBard Liao 
105064520e8SBard Liao 	return 0;
106064520e8SBard Liao }
107064520e8SBard Liao 
108064520e8SBard Liao static void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev)
109064520e8SBard Liao {
110064520e8SBard Liao 	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
111064520e8SBard Liao 	const struct sof_intel_dsp_desc *chip = hda->desc;
112064520e8SBard Liao 
113064520e8SBard Liao 	/* enable IPC DONE and BUSY interrupts */
114064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
115064520e8SBard Liao 				MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE,
116064520e8SBard Liao 				MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE);
117064520e8SBard Liao }
118064520e8SBard Liao 
119064520e8SBard Liao static void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev)
120064520e8SBard Liao {
121064520e8SBard Liao 	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
122064520e8SBard Liao 	const struct sof_intel_dsp_desc *chip = hda->desc;
123064520e8SBard Liao 
124064520e8SBard Liao 	/* disable IPC DONE and BUSY interrupts */
125064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
126064520e8SBard Liao 				MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE, 0);
127064520e8SBard Liao }
128064520e8SBard Liao 
129064520e8SBard Liao static int mtl_enable_interrupts(struct snd_sof_dev *sdev)
130064520e8SBard Liao {
131064520e8SBard Liao 	u32 hfintipptr;
132064520e8SBard Liao 	u32 irqinten;
133064520e8SBard Liao 	u32 host_ipc;
134064520e8SBard Liao 	u32 hipcie;
135064520e8SBard Liao 	int ret;
136064520e8SBard Liao 
137064520e8SBard Liao 	/* read Interrupt IP Pointer */
138064520e8SBard Liao 	hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK;
139064520e8SBard Liao 
140064520e8SBard Liao 	/* Enable Host IPC and SOUNDWIRE */
141064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, hfintipptr,
142064520e8SBard Liao 				MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK,
143064520e8SBard Liao 				MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK);
144064520e8SBard Liao 
145064520e8SBard Liao 	/* check if operation was successful */
146064520e8SBard Liao 	host_ipc = MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK;
147064520e8SBard Liao 	ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, hfintipptr, irqinten,
148064520e8SBard Liao 					    (irqinten & host_ipc) == host_ipc,
149064520e8SBard Liao 					    HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US);
150064520e8SBard Liao 	if (ret < 0) {
151064520e8SBard Liao 		dev_err(sdev->dev, "failed to enable Host IPC and/or SOUNDWIRE\n");
152064520e8SBard Liao 		return ret;
153064520e8SBard Liao 	}
154064520e8SBard Liao 
155064520e8SBard Liao 	/* Set Host IPC interrupt enable */
156064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE,
157064520e8SBard Liao 				MTL_DSP_REG_HfHIPCIE_IE_MASK, MTL_DSP_REG_HfHIPCIE_IE_MASK);
158064520e8SBard Liao 
159064520e8SBard Liao 	/* check if operation was successful */
160064520e8SBard Liao 	host_ipc = MTL_DSP_REG_HfHIPCIE_IE_MASK;
161064520e8SBard Liao 	ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE, hipcie,
162064520e8SBard Liao 					    (hipcie & host_ipc) == host_ipc,
163064520e8SBard Liao 					    HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US);
164064520e8SBard Liao 	if (ret < 0) {
165064520e8SBard Liao 		dev_err(sdev->dev, "failed to set Host IPC interrupt enable\n");
166064520e8SBard Liao 		return ret;
167064520e8SBard Liao 	}
168064520e8SBard Liao 
169064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE,
170064520e8SBard Liao 				MTL_DSP_REG_HfSNDWIE_IE_MASK, MTL_DSP_REG_HfSNDWIE_IE_MASK);
171064520e8SBard Liao 	host_ipc = MTL_DSP_REG_HfSNDWIE_IE_MASK;
172064520e8SBard Liao 	ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE, hipcie,
173064520e8SBard Liao 					    (hipcie & host_ipc) == host_ipc,
174064520e8SBard Liao 					    HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US);
175064520e8SBard Liao 	if (ret < 0)
176064520e8SBard Liao 		dev_err(sdev->dev, "failed to set SoundWire IPC interrupt enable\n");
177064520e8SBard Liao 
178064520e8SBard Liao 	return ret;
179064520e8SBard Liao }
180064520e8SBard Liao 
181064520e8SBard Liao static int mtl_disable_interrupts(struct snd_sof_dev *sdev)
182064520e8SBard Liao {
183064520e8SBard Liao 	u32 hfintipptr;
184064520e8SBard Liao 	u32 irqinten;
185064520e8SBard Liao 	u32 host_ipc;
186064520e8SBard Liao 	u32 hipcie;
187064520e8SBard Liao 	int ret1;
188064520e8SBard Liao 	int ret;
189064520e8SBard Liao 
190064520e8SBard Liao 	/* read Interrupt IP Pointer */
191064520e8SBard Liao 	hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK;
192064520e8SBard Liao 
193064520e8SBard Liao 	/* Disable Host IPC and SOUNDWIRE */
194064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, hfintipptr,
195064520e8SBard Liao 				MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK, 0);
196064520e8SBard Liao 
197064520e8SBard Liao 	/* check if operation was successful */
198064520e8SBard Liao 	host_ipc = MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK;
199064520e8SBard Liao 	ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, hfintipptr, irqinten,
200064520e8SBard Liao 					    (irqinten & host_ipc) == 0,
201064520e8SBard Liao 					    HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US);
202064520e8SBard Liao 	/* Continue to disable other interrupts when error happens */
203064520e8SBard Liao 	if (ret < 0)
204064520e8SBard Liao 		dev_err(sdev->dev, "failed to disable Host IPC and SoundWire\n");
205064520e8SBard Liao 
206064520e8SBard Liao 	/* Set Host IPC interrupt disable */
207064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE,
208064520e8SBard Liao 				MTL_DSP_REG_HfHIPCIE_IE_MASK, 0);
209064520e8SBard Liao 
210064520e8SBard Liao 	/* check if operation was successful */
211064520e8SBard Liao 	host_ipc = MTL_DSP_REG_HfHIPCIE_IE_MASK;
212064520e8SBard Liao 	ret1 = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE, hipcie,
213064520e8SBard Liao 					     (hipcie & host_ipc) == 0,
214064520e8SBard Liao 					     HDA_DSP_REG_POLL_INTERVAL_US,
215064520e8SBard Liao 					     HDA_DSP_RESET_TIMEOUT_US);
216064520e8SBard Liao 	if (ret1 < 0) {
217064520e8SBard Liao 		dev_err(sdev->dev, "failed to set Host IPC interrupt disable\n");
218064520e8SBard Liao 		if (!ret)
219064520e8SBard Liao 			ret = ret1;
220064520e8SBard Liao 	}
221064520e8SBard Liao 
222064520e8SBard Liao 	/* Set SoundWire IPC interrupt disable */
223064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE,
224064520e8SBard Liao 				MTL_DSP_REG_HfSNDWIE_IE_MASK, 0);
225064520e8SBard Liao 	host_ipc = MTL_DSP_REG_HfSNDWIE_IE_MASK;
226064520e8SBard Liao 	ret1 = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE, hipcie,
227064520e8SBard Liao 					     (hipcie & host_ipc) == 0,
228064520e8SBard Liao 					     HDA_DSP_REG_POLL_INTERVAL_US,
229064520e8SBard Liao 					     HDA_DSP_RESET_TIMEOUT_US);
230064520e8SBard Liao 	if (ret1 < 0) {
231064520e8SBard Liao 		dev_err(sdev->dev, "failed to set SoundWire IPC interrupt disable\n");
232064520e8SBard Liao 		if (!ret)
233064520e8SBard Liao 			ret = ret1;
234064520e8SBard Liao 	}
235064520e8SBard Liao 
236064520e8SBard Liao 	return ret;
237064520e8SBard Liao }
238064520e8SBard Liao 
239064520e8SBard Liao /* pre fw run operations */
240064520e8SBard Liao static int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev)
241064520e8SBard Liao {
242064520e8SBard Liao 	u32 dsphfpwrsts;
243064520e8SBard Liao 	u32 dsphfdsscs;
244064520e8SBard Liao 	u32 cpa;
245064520e8SBard Liao 	u32 pgs;
246064520e8SBard Liao 	int ret;
247064520e8SBard Liao 
248064520e8SBard Liao 	/* Set the DSP subsystem power on */
249064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFDSSCS,
250064520e8SBard Liao 				MTL_HFDSSCS_SPA_MASK, MTL_HFDSSCS_SPA_MASK);
251064520e8SBard Liao 
252064520e8SBard Liao 	/* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */
253064520e8SBard Liao 	usleep_range(1000, 1010);
254064520e8SBard Liao 
255064520e8SBard Liao 	/* poll with timeout to check if operation successful */
256064520e8SBard Liao 	cpa = MTL_HFDSSCS_CPA_MASK;
257064520e8SBard Liao 	ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFDSSCS, dsphfdsscs,
258064520e8SBard Liao 					    (dsphfdsscs & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US,
259064520e8SBard Liao 					    HDA_DSP_RESET_TIMEOUT_US);
260064520e8SBard Liao 	if (ret < 0) {
261064520e8SBard Liao 		dev_err(sdev->dev, "failed to enable DSP subsystem\n");
262064520e8SBard Liao 		return ret;
263064520e8SBard Liao 	}
264064520e8SBard Liao 
265064520e8SBard Liao 	/* Power up gated-DSP-0 domain in order to access the DSP shim register block. */
266064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFPWRCTL,
267064520e8SBard Liao 				MTL_HFPWRCTL_WPDSPHPXPG, MTL_HFPWRCTL_WPDSPHPXPG);
268064520e8SBard Liao 
269064520e8SBard Liao 	usleep_range(1000, 1010);
270064520e8SBard Liao 
271064520e8SBard Liao 	/* poll with timeout to check if operation successful */
272064520e8SBard Liao 	pgs = MTL_HFPWRSTS_DSPHPXPGS_MASK;
273064520e8SBard Liao 	ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFPWRSTS, dsphfpwrsts,
274064520e8SBard Liao 					    (dsphfpwrsts & pgs) == pgs,
275064520e8SBard Liao 					    HDA_DSP_REG_POLL_INTERVAL_US,
276064520e8SBard Liao 					    HDA_DSP_RESET_TIMEOUT_US);
277064520e8SBard Liao 	if (ret < 0)
278064520e8SBard Liao 		dev_err(sdev->dev, "failed to power up gated DSP domain\n");
279064520e8SBard Liao 
280064520e8SBard Liao 	/* make sure SoundWire is not power-gated */
281064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, MTL_HFPWRCTL,
282064520e8SBard Liao 				MTL_HfPWRCTL_WPIOXPG(1), MTL_HfPWRCTL_WPIOXPG(1));
283064520e8SBard Liao 	return ret;
284064520e8SBard Liao }
285064520e8SBard Liao 
286064520e8SBard Liao static int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev)
287064520e8SBard Liao {
288064520e8SBard Liao 	int ret;
289064520e8SBard Liao 
290064520e8SBard Liao 	if (sdev->first_boot) {
291064520e8SBard Liao 		struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
292064520e8SBard Liao 
293064520e8SBard Liao 		ret = hda_sdw_startup(sdev);
294064520e8SBard Liao 		if (ret < 0) {
295064520e8SBard Liao 			dev_err(sdev->dev, "could not startup SoundWire links\n");
296064520e8SBard Liao 			return ret;
297064520e8SBard Liao 		}
298064520e8SBard Liao 
299064520e8SBard Liao 		/* Check if IMR boot is usable */
300064520e8SBard Liao 		if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT))
301064520e8SBard Liao 			hdev->imrboot_supported = true;
302064520e8SBard Liao 	}
303064520e8SBard Liao 
304064520e8SBard Liao 	hda_sdw_int_enable(sdev, true);
305064520e8SBard Liao 	return 0;
306064520e8SBard Liao }
307064520e8SBard Liao 
308064520e8SBard Liao static void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
309064520e8SBard Liao {
310064520e8SBard Liao 	char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR;
311064520e8SBard Liao 	u32 romdbgsts;
312064520e8SBard Liao 	u32 romdbgerr;
313064520e8SBard Liao 	u32 fwsts;
314064520e8SBard Liao 	u32 fwlec;
315064520e8SBard Liao 
316064520e8SBard Liao 	fwsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_STS);
317064520e8SBard Liao 	fwlec = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_ERROR);
318064520e8SBard Liao 	romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY);
319064520e8SBard Liao 	romdbgerr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY_ERROR);
320064520e8SBard Liao 
321064520e8SBard Liao 	dev_err(sdev->dev, "ROM status: %#x, ROM error: %#x\n", fwsts, fwlec);
322064520e8SBard Liao 	dev_err(sdev->dev, "ROM debug status: %#x, ROM debug error: %#x\n", romdbgsts,
323064520e8SBard Liao 		romdbgerr);
324064520e8SBard Liao 	romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY + 0x8 * 3);
325064520e8SBard Liao 	dev_printk(level, sdev->dev, "ROM feature bit%s enabled\n",
326064520e8SBard Liao 		   romdbgsts & BIT(24) ? "" : " not");
327064520e8SBard Liao }
328064520e8SBard Liao 
329064520e8SBard Liao static bool mtl_dsp_primary_core_is_enabled(struct snd_sof_dev *sdev)
330064520e8SBard Liao {
331064520e8SBard Liao 	int val;
332064520e8SBard Liao 
333064520e8SBard Liao 	val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE);
334064520e8SBard Liao 	if (val != U32_MAX && val & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK)
335064520e8SBard Liao 		return true;
336064520e8SBard Liao 
337064520e8SBard Liao 	return false;
338064520e8SBard Liao }
339064520e8SBard Liao 
340064520e8SBard Liao static int mtl_dsp_core_power_up(struct snd_sof_dev *sdev, int core)
341064520e8SBard Liao {
342064520e8SBard Liao 	unsigned int cpa;
343064520e8SBard Liao 	u32 dspcxctl;
344064520e8SBard Liao 	int ret;
345064520e8SBard Liao 
346064520e8SBard Liao 	/* Only the primary core can be powered up by the host */
347064520e8SBard Liao 	if (core != SOF_DSP_PRIMARY_CORE || mtl_dsp_primary_core_is_enabled(sdev))
348064520e8SBard Liao 		return 0;
349064520e8SBard Liao 
350064520e8SBard Liao 	/* Program the owner of the IP & shim registers (10: Host CPU) */
351064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE,
352064520e8SBard Liao 				MTL_DSP2CXCTL_PRIMARY_CORE_OSEL,
353064520e8SBard Liao 				0x2 << MTL_DSP2CXCTL_PRIMARY_CORE_OSEL_SHIFT);
354064520e8SBard Liao 
355064520e8SBard Liao 	/* enable SPA bit */
356064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE,
357064520e8SBard Liao 				MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK,
358064520e8SBard Liao 				MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK);
359064520e8SBard Liao 
360064520e8SBard Liao 	/* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */
361064520e8SBard Liao 	usleep_range(1000, 1010);
362064520e8SBard Liao 
363064520e8SBard Liao 	/* poll with timeout to check if operation successful */
364064520e8SBard Liao 	cpa = MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK;
365064520e8SBard Liao 	ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl,
366064520e8SBard Liao 					    (dspcxctl & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US,
367064520e8SBard Liao 					    HDA_DSP_RESET_TIMEOUT_US);
368740e5d87SYong Zhi 	if (ret < 0)
369064520e8SBard Liao 		dev_err(sdev->dev, "%s: timeout on MTL_DSP2CXCTL_PRIMARY_CORE read\n",
370064520e8SBard Liao 			__func__);
371064520e8SBard Liao 
372064520e8SBard Liao 	return ret;
373064520e8SBard Liao }
374064520e8SBard Liao 
375064520e8SBard Liao static int mtl_dsp_core_power_down(struct snd_sof_dev *sdev, int core)
376064520e8SBard Liao {
377064520e8SBard Liao 	u32 dspcxctl;
378064520e8SBard Liao 	int ret;
379064520e8SBard Liao 
380064520e8SBard Liao 	/* Only the primary core can be powered down by the host */
381064520e8SBard Liao 	if (core != SOF_DSP_PRIMARY_CORE || !mtl_dsp_primary_core_is_enabled(sdev))
382064520e8SBard Liao 		return 0;
383064520e8SBard Liao 
384064520e8SBard Liao 	/* disable SPA bit */
385064520e8SBard Liao 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE,
386064520e8SBard Liao 				MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK, 0);
387064520e8SBard Liao 
388064520e8SBard Liao 	/* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */
389064520e8SBard Liao 	usleep_range(1000, 1010);
390064520e8SBard Liao 
391064520e8SBard Liao 	ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl,
392064520e8SBard Liao 					    !(dspcxctl & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK),
393064520e8SBard Liao 					    HDA_DSP_REG_POLL_INTERVAL_US,
394064520e8SBard Liao 					    HDA_DSP_PD_TIMEOUT * USEC_PER_MSEC);
395064520e8SBard Liao 	if (ret < 0)
396064520e8SBard Liao 		dev_err(sdev->dev, "failed to power down primary core\n");
397064520e8SBard Liao 
398064520e8SBard Liao 	return ret;
399064520e8SBard Liao }
400064520e8SBard Liao 
4012090cb9bSFred Oh static int mtl_power_down_dsp(struct snd_sof_dev *sdev)
4022090cb9bSFred Oh {
4032090cb9bSFred Oh 	u32 dsphfdsscs, cpa;
4042090cb9bSFred Oh 	int ret;
4052090cb9bSFred Oh 
4062090cb9bSFred Oh 	/* first power down core */
4072090cb9bSFred Oh 	ret = mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE);
4082090cb9bSFred Oh 	if (ret) {
4092090cb9bSFred Oh 		dev_err(sdev->dev, "mtl dsp power down error, %d\n", ret);
4102090cb9bSFred Oh 		return ret;
4112090cb9bSFred Oh 	}
4122090cb9bSFred Oh 
4132090cb9bSFred Oh 	/* Set the DSP subsystem power down */
4142090cb9bSFred Oh 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFDSSCS,
4152090cb9bSFred Oh 				MTL_HFDSSCS_SPA_MASK, 0);
4162090cb9bSFred Oh 
4172090cb9bSFred Oh 	/* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */
4182090cb9bSFred Oh 	usleep_range(1000, 1010);
4192090cb9bSFred Oh 
4202090cb9bSFred Oh 	/* poll with timeout to check if operation successful */
4212090cb9bSFred Oh 	cpa = MTL_HFDSSCS_CPA_MASK;
4222090cb9bSFred Oh 	dsphfdsscs = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFDSSCS);
4232090cb9bSFred Oh 	return snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFDSSCS, dsphfdsscs,
4242090cb9bSFred Oh 					     (dsphfdsscs & cpa) == 0, HDA_DSP_REG_POLL_INTERVAL_US,
4252090cb9bSFred Oh 					     HDA_DSP_RESET_TIMEOUT_US);
4262090cb9bSFred Oh }
4272090cb9bSFred Oh 
428064520e8SBard Liao static int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
429064520e8SBard Liao {
430064520e8SBard Liao 	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
431064520e8SBard Liao 	const struct sof_intel_dsp_desc *chip = hda->desc;
432064520e8SBard Liao 	unsigned int status;
433064520e8SBard Liao 	u32 ipc_hdr;
434064520e8SBard Liao 	int ret;
435064520e8SBard Liao 
436064520e8SBard Liao 	/* step 1: purge FW request */
437064520e8SBard Liao 	ipc_hdr = chip->ipc_req_mask | HDA_DSP_ROM_IPC_CONTROL;
438064520e8SBard Liao 	if (!imr_boot)
439064520e8SBard Liao 		ipc_hdr |= HDA_DSP_ROM_IPC_PURGE_FW | ((stream_tag - 1) << 9);
440064520e8SBard Liao 
441064520e8SBard Liao 	snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req, ipc_hdr);
442064520e8SBard Liao 
443064520e8SBard Liao 	/* step 2: power up primary core */
444064520e8SBard Liao 	ret = mtl_dsp_core_power_up(sdev, SOF_DSP_PRIMARY_CORE);
445064520e8SBard Liao 	if (ret < 0) {
446064520e8SBard Liao 		if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
447064520e8SBard Liao 			dev_err(sdev->dev, "dsp core 0/1 power up failed\n");
448064520e8SBard Liao 		goto err;
449064520e8SBard Liao 	}
450064520e8SBard Liao 
451064520e8SBard Liao 	dev_dbg(sdev->dev, "Primary core power up successful\n");
452064520e8SBard Liao 
453064520e8SBard Liao 	/* step 3: wait for IPC DONE bit from ROM */
454064520e8SBard Liao 	ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, chip->ipc_ack, status,
455064520e8SBard Liao 					    ((status & chip->ipc_ack_mask) == chip->ipc_ack_mask),
456064520e8SBard Liao 					    HDA_DSP_REG_POLL_INTERVAL_US, MTL_DSP_PURGE_TIMEOUT_US);
457064520e8SBard Liao 	if (ret < 0) {
458064520e8SBard Liao 		if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
459064520e8SBard Liao 			dev_err(sdev->dev, "timeout waiting for purge IPC done\n");
460064520e8SBard Liao 		goto err;
461064520e8SBard Liao 	}
462064520e8SBard Liao 
463064520e8SBard Liao 	/* set DONE bit to clear the reply IPC message */
464064520e8SBard Liao 	snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, chip->ipc_ack, chip->ipc_ack_mask,
465064520e8SBard Liao 				       chip->ipc_ack_mask);
466064520e8SBard Liao 
467064520e8SBard Liao 	/* step 4: enable interrupts */
468064520e8SBard Liao 	ret = mtl_enable_interrupts(sdev);
469064520e8SBard Liao 	if (ret < 0) {
470064520e8SBard Liao 		if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
471064520e8SBard Liao 			dev_err(sdev->dev, "%s: failed to enable interrupts\n", __func__);
472064520e8SBard Liao 		goto err;
473064520e8SBard Liao 	}
474064520e8SBard Liao 
475064520e8SBard Liao 	mtl_enable_ipc_interrupts(sdev);
476064520e8SBard Liao 
477064520e8SBard Liao 	/*
478064520e8SBard Liao 	 * ACE workaround: don't wait for ROM INIT.
479064520e8SBard Liao 	 * The platform cannot catch ROM_INIT_DONE because of a very short
480064520e8SBard Liao 	 * timing window. Follow the recommendations and skip this part.
481064520e8SBard Liao 	 */
482064520e8SBard Liao 
483064520e8SBard Liao 	return 0;
484064520e8SBard Liao 
485064520e8SBard Liao err:
486064520e8SBard Liao 	snd_sof_dsp_dbg_dump(sdev, "MTL DSP init fail", 0);
487064520e8SBard Liao 	mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE);
488064520e8SBard Liao 	return ret;
489064520e8SBard Liao }
490064520e8SBard Liao 
491064520e8SBard Liao static irqreturn_t mtl_ipc_irq_thread(int irq, void *context)
492064520e8SBard Liao {
493064520e8SBard Liao 	struct sof_ipc4_msg notification_data = {{ 0 }};
494064520e8SBard Liao 	struct snd_sof_dev *sdev = context;
495064520e8SBard Liao 	bool ipc_irq = false;
496064520e8SBard Liao 	u32 hipcida;
497064520e8SBard Liao 	u32 hipctdr;
498064520e8SBard Liao 
499064520e8SBard Liao 	hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA);
500064520e8SBard Liao 
501064520e8SBard Liao 	/* reply message from DSP */
502064520e8SBard Liao 	if (hipcida & MTL_DSP_REG_HFIPCXIDA_DONE) {
503064520e8SBard Liao 		/* DSP received the message */
504064520e8SBard Liao 		snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL,
505064520e8SBard Liao 					MTL_DSP_REG_HFIPCXCTL_DONE, 0);
506064520e8SBard Liao 
507064520e8SBard Liao 		mtl_ipc_dsp_done(sdev);
508064520e8SBard Liao 
509064520e8SBard Liao 		ipc_irq = true;
510064520e8SBard Liao 	}
511064520e8SBard Liao 
512064520e8SBard Liao 	hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR);
513064520e8SBard Liao 	if (hipctdr & MTL_DSP_REG_HFIPCXTDR_BUSY) {
514064520e8SBard Liao 		/* Message from DSP (reply or notification) */
515064520e8SBard Liao 		u32 extension = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDDY);
516064520e8SBard Liao 		u32 primary = hipctdr & MTL_DSP_REG_HFIPCXTDR_MSG_MASK;
517064520e8SBard Liao 
518064520e8SBard Liao 		/*
519064520e8SBard Liao 		 * ACE fw sends a new fw ipc message to host to
520064520e8SBard Liao 		 * notify the status of the last host ipc message
521064520e8SBard Liao 		 */
522064520e8SBard Liao 		if (primary & SOF_IPC4_MSG_DIR_MASK) {
523064520e8SBard Liao 			/* Reply received */
5241549a69bSPeter Ujfalusi 			if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
525064520e8SBard Liao 				struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
526064520e8SBard Liao 
527064520e8SBard Liao 				data->primary = primary;
528064520e8SBard Liao 				data->extension = extension;
529064520e8SBard Liao 
530064520e8SBard Liao 				spin_lock_irq(&sdev->ipc_lock);
531064520e8SBard Liao 
532064520e8SBard Liao 				snd_sof_ipc_get_reply(sdev);
533064520e8SBard Liao 				snd_sof_ipc_reply(sdev, data->primary);
534064520e8SBard Liao 
535064520e8SBard Liao 				spin_unlock_irq(&sdev->ipc_lock);
536064520e8SBard Liao 			} else {
5371549a69bSPeter Ujfalusi 				dev_dbg_ratelimited(sdev->dev,
5381549a69bSPeter Ujfalusi 						    "IPC reply before FW_READY: %#x|%#x\n",
5391549a69bSPeter Ujfalusi 						    primary, extension);
5401549a69bSPeter Ujfalusi 			}
5411549a69bSPeter Ujfalusi 		} else {
542064520e8SBard Liao 			/* Notification received */
543064520e8SBard Liao 			notification_data.primary = primary;
544064520e8SBard Liao 			notification_data.extension = extension;
545064520e8SBard Liao 
546064520e8SBard Liao 			sdev->ipc->msg.rx_data = &notification_data;
547064520e8SBard Liao 			snd_sof_ipc_msgs_rx(sdev);
548064520e8SBard Liao 			sdev->ipc->msg.rx_data = NULL;
549064520e8SBard Liao 		}
550064520e8SBard Liao 
551064520e8SBard Liao 		mtl_ipc_host_done(sdev);
552064520e8SBard Liao 
553064520e8SBard Liao 		ipc_irq = true;
554064520e8SBard Liao 	}
555064520e8SBard Liao 
556064520e8SBard Liao 	if (!ipc_irq) {
557064520e8SBard Liao 		/* This interrupt is not shared so no need to return IRQ_NONE. */
558b837870fSPierre-Louis Bossart 		dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n");
559064520e8SBard Liao 	}
560064520e8SBard Liao 
561064520e8SBard Liao 	return IRQ_HANDLED;
562064520e8SBard Liao }
563064520e8SBard Liao 
564064520e8SBard Liao static int mtl_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev)
565064520e8SBard Liao {
566064520e8SBard Liao 	return MTL_DSP_MBOX_UPLINK_OFFSET;
567064520e8SBard Liao }
568064520e8SBard Liao 
569064520e8SBard Liao static int mtl_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id)
570064520e8SBard Liao {
571064520e8SBard Liao 	return MTL_SRAM_WINDOW_OFFSET(id);
572064520e8SBard Liao }
573064520e8SBard Liao 
574064520e8SBard Liao static void mtl_ipc_dump(struct snd_sof_dev *sdev)
575064520e8SBard Liao {
576d01784eeSPeter Ujfalusi 	u32 hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl;
577064520e8SBard Liao 
578d01784eeSPeter Ujfalusi 	hipcidr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDR);
579d01784eeSPeter Ujfalusi 	hipcidd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDDY);
580064520e8SBard Liao 	hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA);
581064520e8SBard Liao 	hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR);
582d01784eeSPeter Ujfalusi 	hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDDY);
583d01784eeSPeter Ujfalusi 	hipctda = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDA);
584d01784eeSPeter Ujfalusi 	hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL);
585064520e8SBard Liao 
586064520e8SBard Liao 	dev_err(sdev->dev,
587d01784eeSPeter Ujfalusi 		"Host IPC initiator: %#x|%#x|%#x, target: %#x|%#x|%#x, ctl: %#x\n",
588d01784eeSPeter Ujfalusi 		hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl);
589064520e8SBard Liao }
590064520e8SBard Liao 
59139df087fSRanjani Sridharan static int mtl_dsp_disable_interrupts(struct snd_sof_dev *sdev)
59239df087fSRanjani Sridharan {
59339df087fSRanjani Sridharan 	mtl_disable_ipc_interrupts(sdev);
59439df087fSRanjani Sridharan 	return mtl_disable_interrupts(sdev);
59539df087fSRanjani Sridharan }
59639df087fSRanjani Sridharan 
597064520e8SBard Liao /* Meteorlake ops */
598064520e8SBard Liao struct snd_sof_dsp_ops sof_mtl_ops;
599064520e8SBard Liao EXPORT_SYMBOL_NS(sof_mtl_ops, SND_SOC_SOF_INTEL_HDA_COMMON);
600064520e8SBard Liao 
601064520e8SBard Liao int sof_mtl_ops_init(struct snd_sof_dev *sdev)
602064520e8SBard Liao {
603064520e8SBard Liao 	struct sof_ipc4_fw_data *ipc4_data;
604064520e8SBard Liao 
605064520e8SBard Liao 	/* common defaults */
606064520e8SBard Liao 	memcpy(&sof_mtl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops));
607064520e8SBard Liao 
608064520e8SBard Liao 	/* shutdown */
609064520e8SBard Liao 	sof_mtl_ops.shutdown = hda_dsp_shutdown;
610064520e8SBard Liao 
611064520e8SBard Liao 	/* doorbell */
612064520e8SBard Liao 	sof_mtl_ops.irq_thread = mtl_ipc_irq_thread;
613064520e8SBard Liao 
614064520e8SBard Liao 	/* ipc */
615064520e8SBard Liao 	sof_mtl_ops.send_msg = mtl_ipc_send_msg;
616064520e8SBard Liao 	sof_mtl_ops.get_mailbox_offset = mtl_dsp_ipc_get_mailbox_offset;
617064520e8SBard Liao 	sof_mtl_ops.get_window_offset = mtl_dsp_ipc_get_window_offset;
618064520e8SBard Liao 
619064520e8SBard Liao 	/* debug */
620064520e8SBard Liao 	sof_mtl_ops.debug_map = mtl_dsp_debugfs;
621064520e8SBard Liao 	sof_mtl_ops.debug_map_count = ARRAY_SIZE(mtl_dsp_debugfs);
622064520e8SBard Liao 	sof_mtl_ops.dbg_dump = mtl_dsp_dump;
623064520e8SBard Liao 	sof_mtl_ops.ipc_dump = mtl_ipc_dump;
624064520e8SBard Liao 
625064520e8SBard Liao 	/* pre/post fw run */
626064520e8SBard Liao 	sof_mtl_ops.pre_fw_run = mtl_dsp_pre_fw_run;
627064520e8SBard Liao 	sof_mtl_ops.post_fw_run = mtl_dsp_post_fw_run;
628064520e8SBard Liao 
629064520e8SBard Liao 	/* parse platform specific extended manifest */
630064520e8SBard Liao 	sof_mtl_ops.parse_platform_ext_manifest = NULL;
631064520e8SBard Liao 
632064520e8SBard Liao 	/* dsp core get/put */
633064520e8SBard Liao 	/* TODO: add core_get and core_put */
634064520e8SBard Liao 
635064520e8SBard Liao 	sdev->private = devm_kzalloc(sdev->dev, sizeof(struct sof_ipc4_fw_data), GFP_KERNEL);
636064520e8SBard Liao 	if (!sdev->private)
637064520e8SBard Liao 		return -ENOMEM;
638064520e8SBard Liao 
639064520e8SBard Liao 	ipc4_data = sdev->private;
640064520e8SBard Liao 	ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET;
641064520e8SBard Liao 
642cc4a3a19SPeter Ujfalusi 	ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_2;
643cc4a3a19SPeter Ujfalusi 
644*3ab2c21eSPeter Ujfalusi 	/* External library loading support */
645*3ab2c21eSPeter Ujfalusi 	ipc4_data->load_library = hda_dsp_ipc4_load_library;
646*3ab2c21eSPeter Ujfalusi 
647064520e8SBard Liao 	/* set DAI ops */
648064520e8SBard Liao 	hda_set_dai_drv_ops(sdev, &sof_mtl_ops);
649064520e8SBard Liao 
650064520e8SBard Liao 	return 0;
651064520e8SBard Liao };
652064520e8SBard Liao EXPORT_SYMBOL_NS(sof_mtl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON);
653064520e8SBard Liao 
654064520e8SBard Liao const struct sof_intel_dsp_desc mtl_chip_info = {
655064520e8SBard Liao 	.cores_num = 3,
656064520e8SBard Liao 	.init_core_mask = BIT(0),
657064520e8SBard Liao 	.host_managed_cores_mask = BIT(0),
658064520e8SBard Liao 	.ipc_req = MTL_DSP_REG_HFIPCXIDR,
659064520e8SBard Liao 	.ipc_req_mask = MTL_DSP_REG_HFIPCXIDR_BUSY,
660064520e8SBard Liao 	.ipc_ack = MTL_DSP_REG_HFIPCXIDA,
661064520e8SBard Liao 	.ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE,
662064520e8SBard Liao 	.ipc_ctl = MTL_DSP_REG_HFIPCXCTL,
663064520e8SBard Liao 	.rom_status_reg = MTL_DSP_ROM_STS,
664064520e8SBard Liao 	.rom_init_timeout	= 300,
6659ccbc2e1SPierre-Louis Bossart 	.ssp_count = MTL_SSP_COUNT,
666064520e8SBard Liao 	.ssp_base_offset = CNL_SSP_BASE_OFFSET,
667064520e8SBard Liao 	.sdw_shim_base = SDW_SHIM_BASE_ACE,
668064520e8SBard Liao 	.sdw_alh_base = SDW_ALH_BASE_ACE,
669064520e8SBard Liao 	.check_sdw_irq = mtl_dsp_check_sdw_irq,
670064520e8SBard Liao 	.check_ipc_irq = mtl_dsp_check_ipc_irq,
671064520e8SBard Liao 	.cl_init = mtl_dsp_cl_init,
6722090cb9bSFred Oh 	.power_down_dsp = mtl_power_down_dsp,
67339df087fSRanjani Sridharan 	.disable_interrupts = mtl_dsp_disable_interrupts,
674064520e8SBard Liao 	.hw_ip_version = SOF_INTEL_ACE_1_0,
675064520e8SBard Liao };
676064520e8SBard Liao EXPORT_SYMBOL_NS(mtl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
677