sound/soc/sof/intel/hda-ipc.c
Source file repositories/reference/linux-study-clean/sound/soc/sof/intel/hda-ipc.c
File Facts
- System
- Linux kernel
- Corpus path
sound/soc/sof/intel/hda-ipc.c- Extension
.c- Size
- 16130 bytes
- Lines
- 550
- Domain
- Driver Families
- Bucket
- sound/soc
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
sound/hda_register.hsound/sof/ipc4/header.htrace/events/sof_intel.h../ops.hhda.htelemetry.h
Detected Declarations
function hda_dsp_ipc_host_donefunction hda_dsp_ipc_dsp_donefunction hda_dsp_ipc_send_msgfunction hda_dsp_ipc4_pm_msgfunction hda_dsp_ipc4_schedule_d0i3_workfunction hda_dsp_ipc4_send_msgfunction hda_dsp_ipc_get_replyfunction hda_dsp_ipc4_irq_threadfunction hda_dsp_ipc_irq_threadfunction sof_ipc_tx_messagefunction hda_dsp_check_ipc_irqfunction hda_dsp_ipc_get_mailbox_offsetfunction hda_dsp_ipc_get_window_offsetfunction hda_ipc_msg_datafunction hda_set_stream_data_offsetfunction hda_ipc4_dsp_dumpfunction hda_check_ipc_irqfunction hda_ipc_irq_dumpfunction hda_ipc_dumpfunction hda_ipc4_dumpfunction hda_ipc4_tx_is_busy
Annotated Snippet
if (primary & SOF_IPC4_MSG_DIR_MASK) {
/* Reply received */
if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
data->primary = primary;
data->extension = extension;
guard(spinlock_irq)(&sdev->ipc_lock);
snd_sof_ipc_get_reply(sdev);
hda_dsp_ipc_host_done(sdev);
snd_sof_ipc_reply(sdev, data->primary);
} else {
dev_dbg_ratelimited(sdev->dev,
"IPC reply before FW_READY: %#x|%#x\n",
primary, extension);
}
} else {
/* Notification received */
notification_data.primary = primary;
notification_data.extension = extension;
sdev->ipc->msg.rx_data = ¬ification_data;
snd_sof_ipc_msgs_rx(sdev);
sdev->ipc->msg.rx_data = NULL;
/* Let DSP know that we have finished processing the message */
hda_dsp_ipc_host_done(sdev);
}
ipc_irq = true;
}
if (!ipc_irq)
/* This interrupt is not shared so no need to return IRQ_NONE. */
dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n");
if (ack_received) {
struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
if (hdev->delayed_ipc_tx_msg)
hda_dsp_ipc4_send_msg(sdev, hdev->delayed_ipc_tx_msg);
}
return IRQ_HANDLED;
}
EXPORT_SYMBOL_NS(hda_dsp_ipc4_irq_thread, "SND_SOC_SOF_INTEL_HDA_COMMON");
/* IPC handler thread */
irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context)
{
struct snd_sof_dev *sdev = context;
u32 hipci;
u32 hipcie;
u32 hipct;
u32 hipcte;
u32 msg;
u32 msg_ext;
bool ipc_irq = false;
/* read IPC status */
hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
HDA_DSP_REG_HIPCIE);
hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT);
hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI);
hipcte = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCTE);
/* is this a reply message from the DSP */
if (hipcie & HDA_DSP_REG_HIPCIE_DONE) {
msg = hipci & HDA_DSP_REG_HIPCI_MSG_MASK;
msg_ext = hipcie & HDA_DSP_REG_HIPCIE_MSG_MASK;
trace_sof_intel_ipc_firmware_response(sdev, msg, msg_ext);
/* mask Done interrupt */
snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
HDA_DSP_REG_HIPCCTL,
HDA_DSP_REG_HIPCCTL_DONE, 0);
/*
* Make sure the interrupt thread cannot be preempted between
* waking up the sender and re-enabling the interrupt. Also
* protect against a theoretical race with sof_ipc_tx_message():
* if the DSP is fast enough to receive an IPC message, reply to
* it, and the host interrupt processing calls this function on
* a different core from the one, where the sending is taking
* place, the message might not yet be marked as expecting a
* reply.
*/
if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
Annotation
- Immediate include surface: `sound/hda_register.h`, `sound/sof/ipc4/header.h`, `trace/events/sof_intel.h`, `../ops.h`, `hda.h`, `telemetry.h`.
- Detected declarations: `function hda_dsp_ipc_host_done`, `function hda_dsp_ipc_dsp_done`, `function hda_dsp_ipc_send_msg`, `function hda_dsp_ipc4_pm_msg`, `function hda_dsp_ipc4_schedule_d0i3_work`, `function hda_dsp_ipc4_send_msg`, `function hda_dsp_ipc_get_reply`, `function hda_dsp_ipc4_irq_thread`, `function hda_dsp_ipc_irq_thread`, `function sof_ipc_tx_message`.
- Atlas domain: Driver Families / sound/soc.
- Implementation status: integration implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.