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 = ¬ification_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