xref: /linux/sound/soc/sof/intel/hda-ipc.c (revision 294b9e7e8ecafd4dd4b1cc13d7585082451be0e7)
1 // SPDX-License-Identifier: (GPL-2.0-only 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
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 
18 #include <sound/hda_register.h>
19 #include <sound/sof/ipc4/header.h>
20 #include <trace/events/sof_intel.h>
21 #include "../ops.h"
22 #include "hda.h"
23 #include "telemetry.h"
24 
25 EXPORT_TRACEPOINT_SYMBOL(sof_intel_ipc_firmware_initiated);
26 EXPORT_TRACEPOINT_SYMBOL(sof_intel_ipc_firmware_response);
27 EXPORT_TRACEPOINT_SYMBOL(sof_intel_hda_irq_ipc_check);
28 
29 static void hda_dsp_ipc_host_done(struct snd_sof_dev *sdev)
30 {
31 	/*
32 	 * tell DSP cmd is done - clear busy
33 	 * interrupt and send reply msg to dsp
34 	 */
35 	snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
36 				       HDA_DSP_REG_HIPCT,
37 				       HDA_DSP_REG_HIPCT_BUSY,
38 				       HDA_DSP_REG_HIPCT_BUSY);
39 
40 	/* unmask BUSY interrupt */
41 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
42 				HDA_DSP_REG_HIPCCTL,
43 				HDA_DSP_REG_HIPCCTL_BUSY,
44 				HDA_DSP_REG_HIPCCTL_BUSY);
45 }
46 
47 static void hda_dsp_ipc_dsp_done(struct snd_sof_dev *sdev)
48 {
49 	/*
50 	 * set DONE bit - tell DSP we have received the reply msg
51 	 * from DSP, and processed it, don't send more reply to host
52 	 */
53 	snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
54 				       HDA_DSP_REG_HIPCIE,
55 				       HDA_DSP_REG_HIPCIE_DONE,
56 				       HDA_DSP_REG_HIPCIE_DONE);
57 
58 	/* unmask Done interrupt */
59 	snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
60 				HDA_DSP_REG_HIPCCTL,
61 				HDA_DSP_REG_HIPCCTL_DONE,
62 				HDA_DSP_REG_HIPCCTL_DONE);
63 }
64 
65 int hda_dsp_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
66 {
67 	/* send IPC message to DSP */
68 	sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
69 			  msg->msg_size);
70 	snd_sof_dsp_write(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI,
71 			  HDA_DSP_REG_HIPCI_BUSY);
72 
73 	return 0;
74 }
75 EXPORT_SYMBOL_NS(hda_dsp_ipc_send_msg, "SND_SOC_SOF_INTEL_HDA_COMMON");
76 
77 static inline bool hda_dsp_ipc4_pm_msg(u32 primary)
78 {
79 	/* pm setting is only supported by module msg */
80 	if (SOF_IPC4_MSG_IS_MODULE_MSG(primary) != SOF_IPC4_MODULE_MSG)
81 		return false;
82 
83 	if (SOF_IPC4_MSG_TYPE_GET(primary) == SOF_IPC4_MOD_SET_DX ||
84 	    SOF_IPC4_MSG_TYPE_GET(primary) == SOF_IPC4_MOD_SET_D0IX)
85 		return true;
86 
87 	return false;
88 }
89 
90 void hda_dsp_ipc4_schedule_d0i3_work(struct sof_intel_hda_dev *hdev,
91 				     struct snd_sof_ipc_msg *msg)
92 {
93 	struct sof_ipc4_msg *msg_data = msg->msg_data;
94 
95 	/* Schedule a delayed work for d0i3 entry after sending non-pm ipc msg */
96 	if (hda_dsp_ipc4_pm_msg(msg_data->primary))
97 		return;
98 
99 	mod_delayed_work(system_dfl_wq, &hdev->d0i3_work,
100 			 msecs_to_jiffies(SOF_HDA_D0I3_WORK_DELAY_MS));
101 }
102 EXPORT_SYMBOL_NS(hda_dsp_ipc4_schedule_d0i3_work, "SND_SOC_SOF_INTEL_HDA_COMMON");
103 
104 int hda_dsp_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
105 {
106 	struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
107 	struct sof_ipc4_msg *msg_data = msg->msg_data;
108 
109 	if (hda_ipc4_tx_is_busy(sdev)) {
110 		hdev->delayed_ipc_tx_msg = msg;
111 		return 0;
112 	}
113 
114 	hdev->delayed_ipc_tx_msg = NULL;
115 
116 	/* send the message via mailbox */
117 	if (msg_data->data_size)
118 		sof_mailbox_write(sdev, sdev->host_box.offset, msg_data->data_ptr,
119 				  msg_data->data_size);
120 
121 	snd_sof_dsp_write(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCIE, msg_data->extension);
122 	snd_sof_dsp_write(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI,
123 			  msg_data->primary | HDA_DSP_REG_HIPCI_BUSY);
124 
125 	hda_dsp_ipc4_schedule_d0i3_work(hdev, msg);
126 
127 	return 0;
128 }
129 EXPORT_SYMBOL_NS(hda_dsp_ipc4_send_msg, "SND_SOC_SOF_INTEL_HDA_COMMON");
130 
131 void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev)
132 {
133 	struct snd_sof_ipc_msg *msg = sdev->msg;
134 	struct sof_ipc_reply reply;
135 	struct sof_ipc_cmd_hdr *hdr;
136 
137 	/*
138 	 * Sometimes, there is unexpected reply ipc arriving. The reply
139 	 * ipc belongs to none of the ipcs sent from driver.
140 	 * In this case, the driver must ignore the ipc.
141 	 */
142 	if (!msg) {
143 		dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n");
144 		return;
145 	}
146 
147 	hdr = msg->msg_data;
148 	if (hdr->cmd == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CTX_SAVE) ||
149 	    hdr->cmd == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_GATE)) {
150 		/*
151 		 * memory windows are powered off before sending IPC reply,
152 		 * so we can't read the mailbox for CTX_SAVE and PM_GATE
153 		 * replies.
154 		 */
155 		reply.error = 0;
156 		reply.hdr.cmd = SOF_IPC_GLB_REPLY;
157 		reply.hdr.size = sizeof(reply);
158 		memcpy(msg->reply_data, &reply, sizeof(reply));
159 
160 		msg->reply_error = 0;
161 	} else {
162 		snd_sof_ipc_get_reply(sdev);
163 	}
164 }
165 EXPORT_SYMBOL_NS(hda_dsp_ipc_get_reply, "SND_SOC_SOF_INTEL_HDA_COMMON");
166 
167 irqreturn_t hda_dsp_ipc4_irq_thread(int irq, void *context)
168 {
169 	struct sof_ipc4_msg notification_data = {{ 0 }};
170 	struct snd_sof_dev *sdev = context;
171 	bool ack_received = false;
172 	bool ipc_irq = false;
173 	u32 hipcie, hipct;
174 
175 	hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCIE);
176 	hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT);
177 
178 	if (hipcie & HDA_DSP_REG_HIPCIE_DONE) {
179 		/* DSP received the message */
180 		snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCCTL,
181 					HDA_DSP_REG_HIPCCTL_DONE, 0);
182 		hda_dsp_ipc_dsp_done(sdev);
183 
184 		ipc_irq = true;
185 		ack_received = true;
186 	}
187 
188 	if (hipct & HDA_DSP_REG_HIPCT_BUSY) {
189 		/* Message from DSP (reply or notification) */
190 		u32 hipcte = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
191 					      HDA_DSP_REG_HIPCTE);
192 		u32 primary = hipct & HDA_DSP_REG_HIPCT_MSG_MASK;
193 		u32 extension = hipcte & HDA_DSP_REG_HIPCTE_MSG_MASK;
194 
195 		/* mask BUSY interrupt */
196 		snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCCTL,
197 					HDA_DSP_REG_HIPCCTL_BUSY, 0);
198 
199 		if (primary & SOF_IPC4_MSG_DIR_MASK) {
200 			/* Reply received */
201 			if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
202 				struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
203 
204 				data->primary = primary;
205 				data->extension = extension;
206 
207 				guard(spinlock_irq)(&sdev->ipc_lock);
208 				snd_sof_ipc_get_reply(sdev);
209 				hda_dsp_ipc_host_done(sdev);
210 				snd_sof_ipc_reply(sdev, data->primary);
211 			} else {
212 				dev_dbg_ratelimited(sdev->dev,
213 						    "IPC reply before FW_READY: %#x|%#x\n",
214 						    primary, extension);
215 			}
216 		} else {
217 			/* Notification received */
218 
219 			notification_data.primary = primary;
220 			notification_data.extension = extension;
221 			sdev->ipc->msg.rx_data = &notification_data;
222 			snd_sof_ipc_msgs_rx(sdev);
223 			sdev->ipc->msg.rx_data = NULL;
224 
225 			/* Let DSP know that we have finished processing the message */
226 			hda_dsp_ipc_host_done(sdev);
227 		}
228 
229 		ipc_irq = true;
230 	}
231 
232 	if (!ipc_irq)
233 		/* This interrupt is not shared so no need to return IRQ_NONE. */
234 		dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n");
235 
236 	if (ack_received) {
237 		struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
238 
239 		if (hdev->delayed_ipc_tx_msg)
240 			hda_dsp_ipc4_send_msg(sdev, hdev->delayed_ipc_tx_msg);
241 	}
242 
243 	return IRQ_HANDLED;
244 }
245 EXPORT_SYMBOL_NS(hda_dsp_ipc4_irq_thread, "SND_SOC_SOF_INTEL_HDA_COMMON");
246 
247 /* IPC handler thread */
248 irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context)
249 {
250 	struct snd_sof_dev *sdev = context;
251 	u32 hipci;
252 	u32 hipcie;
253 	u32 hipct;
254 	u32 hipcte;
255 	u32 msg;
256 	u32 msg_ext;
257 	bool ipc_irq = false;
258 
259 	/* read IPC status */
260 	hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
261 				  HDA_DSP_REG_HIPCIE);
262 	hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT);
263 	hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI);
264 	hipcte = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCTE);
265 
266 	/* is this a reply message from the DSP */
267 	if (hipcie & HDA_DSP_REG_HIPCIE_DONE) {
268 		msg = hipci & HDA_DSP_REG_HIPCI_MSG_MASK;
269 		msg_ext = hipcie & HDA_DSP_REG_HIPCIE_MSG_MASK;
270 
271 		trace_sof_intel_ipc_firmware_response(sdev, msg, msg_ext);
272 
273 		/* mask Done interrupt */
274 		snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
275 					HDA_DSP_REG_HIPCCTL,
276 					HDA_DSP_REG_HIPCCTL_DONE, 0);
277 
278 		/*
279 		 * Make sure the interrupt thread cannot be preempted between
280 		 * waking up the sender and re-enabling the interrupt. Also
281 		 * protect against a theoretical race with sof_ipc_tx_message():
282 		 * if the DSP is fast enough to receive an IPC message, reply to
283 		 * it, and the host interrupt processing calls this function on
284 		 * a different core from the one, where the sending is taking
285 		 * place, the message might not yet be marked as expecting a
286 		 * reply.
287 		 */
288 		if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
289 			/* handle immediate reply from DSP core */
290 			guard(spinlock_irq)(&sdev->ipc_lock);
291 			hda_dsp_ipc_get_reply(sdev);
292 			snd_sof_ipc_reply(sdev, msg);
293 			/* set the done bit */
294 			hda_dsp_ipc_dsp_done(sdev);
295 		} else {
296 			dev_dbg_ratelimited(sdev->dev, "IPC reply before FW_READY: %#x\n",
297 					    msg);
298 		}
299 
300 		ipc_irq = true;
301 	}
302 
303 	/* is this a new message from DSP */
304 	if (hipct & HDA_DSP_REG_HIPCT_BUSY) {
305 		msg = hipct & HDA_DSP_REG_HIPCT_MSG_MASK;
306 		msg_ext = hipcte & HDA_DSP_REG_HIPCTE_MSG_MASK;
307 
308 		trace_sof_intel_ipc_firmware_initiated(sdev, msg, msg_ext);
309 
310 		/* mask BUSY interrupt */
311 		snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
312 					HDA_DSP_REG_HIPCCTL,
313 					HDA_DSP_REG_HIPCCTL_BUSY, 0);
314 
315 		/* handle messages from DSP */
316 		if ((hipct & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
317 			struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
318 			bool non_recoverable = true;
319 
320 			/*
321 			 * This is a PANIC message!
322 			 *
323 			 * If it is arriving during firmware boot and it is not
324 			 * the last boot attempt then change the non_recoverable
325 			 * to false as the DSP might be able to boot in the next
326 			 * iteration(s)
327 			 */
328 			if (sdev->fw_state == SOF_FW_BOOT_IN_PROGRESS &&
329 			    hda->boot_iteration < HDA_FW_BOOT_ATTEMPTS)
330 				non_recoverable = false;
331 
332 			snd_sof_dsp_panic(sdev, HDA_DSP_PANIC_OFFSET(msg_ext),
333 					  non_recoverable);
334 		} else {
335 			/* normal message - process normally */
336 			snd_sof_ipc_msgs_rx(sdev);
337 		}
338 
339 		hda_dsp_ipc_host_done(sdev);
340 
341 		ipc_irq = true;
342 	}
343 
344 	if (!ipc_irq) {
345 		/*
346 		 * This interrupt is not shared so no need to return IRQ_NONE.
347 		 */
348 		dev_dbg_ratelimited(sdev->dev,
349 				    "nothing to do in IPC IRQ thread\n");
350 	}
351 
352 	return IRQ_HANDLED;
353 }
354 EXPORT_SYMBOL_NS(hda_dsp_ipc_irq_thread, "SND_SOC_SOF_INTEL_HDA_COMMON");
355 
356 /* Check if an IPC IRQ occurred */
357 bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev)
358 {
359 	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
360 	bool ret = false;
361 	u32 irq_status;
362 
363 	if (sdev->dspless_mode_selected)
364 		return false;
365 
366 	/* store status */
367 	irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIS);
368 	trace_sof_intel_hda_irq_ipc_check(sdev, irq_status);
369 
370 	/* invalid message ? */
371 	if (irq_status == 0xffffffff)
372 		goto out;
373 
374 	/* IPC message ? */
375 	if (irq_status & HDA_DSP_ADSPIS_IPC)
376 		ret = true;
377 
378 	/* CLDMA message ? */
379 	if (irq_status & HDA_DSP_ADSPIS_CL_DMA) {
380 		hda->code_loading = 0;
381 		wake_up(&hda->waitq);
382 		ret = false;
383 	}
384 
385 out:
386 	return ret;
387 }
388 EXPORT_SYMBOL_NS(hda_dsp_check_ipc_irq, "SND_SOC_SOF_INTEL_HDA_COMMON");
389 
390 int hda_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev)
391 {
392 	return HDA_DSP_MBOX_UPLINK_OFFSET;
393 }
394 EXPORT_SYMBOL_NS(hda_dsp_ipc_get_mailbox_offset, "SND_SOC_SOF_INTEL_HDA_COMMON");
395 
396 int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id)
397 {
398 	return SRAM_WINDOW_OFFSET(id);
399 }
400 EXPORT_SYMBOL_NS(hda_dsp_ipc_get_window_offset, "SND_SOC_SOF_INTEL_HDA_COMMON");
401 
402 int hda_ipc_msg_data(struct snd_sof_dev *sdev,
403 		     struct snd_sof_pcm_stream *sps,
404 		     void *p, size_t sz)
405 {
406 	if (!sps || !sdev->stream_box.size) {
407 		sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
408 	} else {
409 		struct snd_pcm_substream *substream = sps->substream;
410 		struct hdac_stream *hstream = substream->runtime->private_data;
411 		struct sof_intel_hda_stream *hda_stream;
412 
413 		hda_stream = container_of(hstream,
414 					  struct sof_intel_hda_stream,
415 					  hext_stream.hstream);
416 
417 		/* The stream might already be closed */
418 		if (!hstream)
419 			return -ESTRPIPE;
420 
421 		sof_mailbox_read(sdev, hda_stream->sof_intel_stream.posn_offset, p, sz);
422 	}
423 
424 	return 0;
425 }
426 EXPORT_SYMBOL_NS(hda_ipc_msg_data, "SND_SOC_SOF_INTEL_HDA_COMMON");
427 
428 int hda_set_stream_data_offset(struct snd_sof_dev *sdev,
429 			       struct snd_sof_pcm_stream *sps,
430 			       size_t posn_offset)
431 {
432 	struct snd_pcm_substream *substream = sps->substream;
433 	struct hdac_stream *hstream = substream->runtime->private_data;
434 	struct sof_intel_hda_stream *hda_stream;
435 
436 	hda_stream = container_of(hstream, struct sof_intel_hda_stream,
437 				  hext_stream.hstream);
438 
439 	/* check for unaligned offset or overflow */
440 	if (posn_offset > sdev->stream_box.size ||
441 	    posn_offset % sizeof(struct sof_ipc_stream_posn) != 0)
442 		return -EINVAL;
443 
444 	hda_stream->sof_intel_stream.posn_offset = sdev->stream_box.offset + posn_offset;
445 
446 	dev_dbg(sdev->dev, "pcm: stream dir %d, posn mailbox offset is %zu",
447 		substream->stream, hda_stream->sof_intel_stream.posn_offset);
448 
449 	return 0;
450 }
451 EXPORT_SYMBOL_NS(hda_set_stream_data_offset, "SND_SOC_SOF_INTEL_HDA_COMMON");
452 
453 void hda_ipc4_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
454 {
455 	char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR;
456 
457 	/* print ROM/FW status */
458 	hda_dsp_get_state(sdev, level);
459 
460 	if (flags & SOF_DBG_DUMP_REGS)
461 		sof_ipc4_intel_dump_telemetry_state(sdev, flags);
462 	else
463 		hda_dsp_dump_ext_rom_status(sdev, level, flags);
464 }
465 EXPORT_SYMBOL_NS(hda_ipc4_dsp_dump, "SND_SOC_SOF_INTEL_HDA_COMMON");
466 
467 bool hda_check_ipc_irq(struct snd_sof_dev *sdev)
468 {
469 	const struct sof_intel_dsp_desc *chip;
470 
471 	chip = get_chip_info(sdev->pdata);
472 	if (chip && chip->check_ipc_irq)
473 		return chip->check_ipc_irq(sdev);
474 
475 	return false;
476 }
477 EXPORT_SYMBOL_NS(hda_check_ipc_irq, "SND_SOC_SOF_INTEL_HDA_COMMON");
478 
479 void hda_ipc_irq_dump(struct snd_sof_dev *sdev)
480 {
481 	u32 adspis;
482 	u32 intsts;
483 	u32 intctl;
484 	u32 ppsts;
485 	u8 rirbsts;
486 
487 	/* read key IRQ stats and config registers */
488 	adspis = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIS);
489 	intsts = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS);
490 	intctl = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL);
491 	ppsts = snd_sof_dsp_read(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPSTS);
492 	rirbsts = snd_sof_dsp_read8(sdev, HDA_DSP_HDA_BAR, AZX_REG_RIRBSTS);
493 
494 	dev_err(sdev->dev, "hda irq intsts 0x%8.8x intlctl 0x%8.8x rirb %2.2x\n",
495 		intsts, intctl, rirbsts);
496 	dev_err(sdev->dev, "dsp irq ppsts 0x%8.8x adspis 0x%8.8x\n", ppsts, adspis);
497 }
498 EXPORT_SYMBOL_NS(hda_ipc_irq_dump, "SND_SOC_SOF_INTEL_HDA_COMMON");
499 
500 void hda_ipc_dump(struct snd_sof_dev *sdev)
501 {
502 	u32 hipcie;
503 	u32 hipct;
504 	u32 hipcctl;
505 
506 	hda_ipc_irq_dump(sdev);
507 
508 	/* read IPC status */
509 	hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCIE);
510 	hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT);
511 	hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCCTL);
512 
513 	/* dump the IPC regs */
514 	/* TODO: parse the raw msg */
515 	dev_err(sdev->dev, "host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n",
516 		hipcie, hipct, hipcctl);
517 }
518 EXPORT_SYMBOL_NS(hda_ipc_dump, "SND_SOC_SOF_INTEL_HDA_COMMON");
519 
520 void hda_ipc4_dump(struct snd_sof_dev *sdev)
521 {
522 	u32 hipci, hipcie, hipct, hipcte, hipcctl;
523 
524 	hda_ipc_irq_dump(sdev);
525 
526 	hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI);
527 	hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCIE);
528 	hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT);
529 	hipcte = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCTE);
530 	hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCCTL);
531 
532 	/* dump the IPC regs */
533 	/* TODO: parse the raw msg */
534 	dev_err(sdev->dev, "Host IPC initiator: %#x|%#x, target: %#x|%#x, ctl: %#x\n",
535 		hipci, hipcie, hipct, hipcte, hipcctl);
536 }
537 EXPORT_SYMBOL_NS(hda_ipc4_dump, "SND_SOC_SOF_INTEL_HDA_COMMON");
538 
539 bool hda_ipc4_tx_is_busy(struct snd_sof_dev *sdev)
540 {
541 	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
542 	const struct sof_intel_dsp_desc *chip = hda->desc;
543 	u32 val;
544 
545 	val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->ipc_req);
546 
547 	return !!(val & chip->ipc_req_mask);
548 }
549 EXPORT_SYMBOL_NS(hda_ipc4_tx_is_busy, "SND_SOC_SOF_INTEL_HDA_COMMON");
550