diff options
Diffstat (limited to 'sound/soc/sof/intel/byt.c')
-rw-r--r-- | sound/soc/sof/intel/byt.c | 172 |
1 files changed, 112 insertions, 60 deletions
diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 29fd1d86156c..49f67f1b94e0 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. @@ -82,33 +82,6 @@ static const struct snd_sof_debugfs_map byt_debugfs[] = { SOF_DEBUGFS_ACCESS_ALWAYS}, }; -static const struct snd_sof_debugfs_map cht_debugfs[] = { - {"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"dmac1", BYT_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"dmac2", BYT_DSP_BAR, DMAC2_OFFSET, DMAC_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"ssp0", BYT_DSP_BAR, SSP0_OFFSET, SSP_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"ssp1", BYT_DSP_BAR, SSP1_OFFSET, SSP_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"ssp2", BYT_DSP_BAR, SSP2_OFFSET, SSP_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"ssp3", BYT_DSP_BAR, SSP3_OFFSET, SSP_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"ssp4", BYT_DSP_BAR, SSP4_OFFSET, SSP_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"ssp5", BYT_DSP_BAR, SSP5_OFFSET, SSP_SIZE, - SOF_DEBUGFS_ACCESS_ALWAYS}, - {"iram", BYT_DSP_BAR, IRAM_OFFSET, IRAM_SIZE, - SOF_DEBUGFS_ACCESS_D0_ONLY}, - {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE, - SOF_DEBUGFS_ACCESS_D0_ONLY}, - {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE_CHT, - SOF_DEBUGFS_ACCESS_ALWAYS}, -}; - static void byt_host_done(struct snd_sof_dev *sdev); static void byt_dsp_done(struct snd_sof_dev *sdev); static void byt_get_reply(struct snd_sof_dev *sdev); @@ -187,13 +160,31 @@ static void byt_dump(struct snd_sof_dev *sdev, u32 flags) static irqreturn_t byt_irq_handler(int irq, void *context) { struct snd_sof_dev *sdev = context; - u64 isr; + u64 ipcx, ipcd; int ret = IRQ_NONE; - /* Interrupt arrived, check src */ - isr = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_ISRX); - if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY)) + ipcx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX); + ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD); + + if (ipcx & SHIM_BYT_IPCX_DONE) { + + /* reply message from DSP, Mask Done interrupt first */ + snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, + SHIM_IMRX, + SHIM_IMRX_DONE, + SHIM_IMRX_DONE); + ret = IRQ_WAKE_THREAD; + } + + if (ipcd & SHIM_BYT_IPCD_BUSY) { + + /* new message from DSP, Mask Busy interrupt first */ + snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, + SHIM_IMRX, + SHIM_IMRX_BUSY, + SHIM_IMRX_BUSY); ret = IRQ_WAKE_THREAD; + } return ret; } @@ -202,19 +193,12 @@ static irqreturn_t byt_irq_thread(int irq, void *context) { struct snd_sof_dev *sdev = context; u64 ipcx, ipcd; - u64 imrx; - imrx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IMRX); ipcx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX); + ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD); /* reply message from DSP */ - if (ipcx & SHIM_BYT_IPCX_DONE && - !(imrx & SHIM_IMRX_DONE)) { - /* Mask Done interrupt before first */ - snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, - SHIM_IMRX, - SHIM_IMRX_DONE, - SHIM_IMRX_DONE); + if (ipcx & SHIM_BYT_IPCX_DONE) { spin_lock_irq(&sdev->ipc_lock); @@ -234,14 +218,7 @@ static irqreturn_t byt_irq_thread(int irq, void *context) } /* new message from DSP */ - ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD); - if (ipcd & SHIM_BYT_IPCD_BUSY && - !(imrx & SHIM_IMRX_BUSY)) { - /* Mask Busy interrupt before return */ - snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, - SHIM_IMRX, - SHIM_IMRX_BUSY, - SHIM_IMRX_BUSY); + if (ipcd & SHIM_BYT_IPCD_BUSY) { /* Handle messages from DSP Core */ if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) { @@ -259,6 +236,10 @@ static irqreturn_t byt_irq_thread(int irq, void *context) static int byt_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) { + /* unmask and prepare to receive Done interrupt */ + snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_DONE, 0); + /* send the message */ sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, msg->msg_size); @@ -324,7 +305,7 @@ static void byt_host_done(struct snd_sof_dev *sdev) SHIM_BYT_IPCD_DONE, SHIM_BYT_IPCD_DONE); - /* unmask busy interrupt */ + /* unmask and prepare to receive next new message */ snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX, SHIM_IMRX_BUSY, 0); } @@ -334,10 +315,6 @@ static void byt_dsp_done(struct snd_sof_dev *sdev) /* clear DONE bit - tell DSP we have completed */ snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCX, SHIM_BYT_IPCX_DONE, 0); - - /* unmask Done interrupt */ - snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX, - SHIM_IMRX_DONE, 0); } /* @@ -594,9 +571,10 @@ irq: return ret; } - /* enable Interrupt from both sides */ - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0); - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0); + /* enable BUSY and disable DONE Interrupt by default */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_BUSY | SHIM_IMRX_DONE, + SHIM_IMRX_DONE); /* set default mailbox offset for FW ready message */ sdev->dsp_box.offset = MBOX_OFFSET; @@ -681,6 +659,69 @@ EXPORT_SYMBOL_NS(tng_chip_info, SND_SOC_SOF_MERRIFIELD); #if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) +static void byt_reset_dsp_disable_int(struct snd_sof_dev *sdev) +{ + /* Disable Interrupt from both sides */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x3); + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x3); + + /* Put DSP into reset, set reset vector */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR, + SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL, + SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL); +} + +static int byt_suspend(struct snd_sof_dev *sdev, u32 target_state) +{ + byt_reset_dsp_disable_int(sdev); + + return 0; +} + +static int byt_resume(struct snd_sof_dev *sdev) +{ + /* enable BUSY and disable DONE Interrupt by default */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_BUSY | SHIM_IMRX_DONE, + SHIM_IMRX_DONE); + + return 0; +} + +static int byt_remove(struct snd_sof_dev *sdev) +{ + byt_reset_dsp_disable_int(sdev); + + return 0; +} + +static const struct snd_sof_debugfs_map cht_debugfs[] = { + {"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"dmac1", BYT_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"dmac2", BYT_DSP_BAR, DMAC2_OFFSET, DMAC_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"ssp0", BYT_DSP_BAR, SSP0_OFFSET, SSP_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"ssp1", BYT_DSP_BAR, SSP1_OFFSET, SSP_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"ssp2", BYT_DSP_BAR, SSP2_OFFSET, SSP_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"ssp3", BYT_DSP_BAR, SSP3_OFFSET, SSP_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"ssp4", BYT_DSP_BAR, SSP4_OFFSET, SSP_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"ssp5", BYT_DSP_BAR, SSP5_OFFSET, SSP_SIZE, + SOF_DEBUGFS_ACCESS_ALWAYS}, + {"iram", BYT_DSP_BAR, IRAM_OFFSET, IRAM_SIZE, + SOF_DEBUGFS_ACCESS_D0_ONLY}, + {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE, + SOF_DEBUGFS_ACCESS_D0_ONLY}, + {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE_CHT, + SOF_DEBUGFS_ACCESS_ALWAYS}, +}; + static int byt_acpi_probe(struct snd_sof_dev *sdev) { struct snd_sof_pdata *pdata = sdev->pdata; @@ -769,9 +810,10 @@ irq: return ret; } - /* enable Interrupt from both sides */ - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0); - snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0); + /* enable BUSY and disable DONE Interrupt by default */ + snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, + SHIM_IMRX_BUSY | SHIM_IMRX_DONE, + SHIM_IMRX_DONE); /* set default mailbox offset for FW ready message */ sdev->dsp_box.offset = MBOX_OFFSET; @@ -783,6 +825,7 @@ irq: const struct snd_sof_dsp_ops sof_byt_ops = { /* device init */ .probe = byt_acpi_probe, + .remove = byt_remove, /* DSP core boot / reset */ .run = byt_run, @@ -832,6 +875,10 @@ const struct snd_sof_dsp_ops sof_byt_ops = { /*Firmware loading */ .load_firmware = snd_sof_load_firmware_memcpy, + /* PM */ + .suspend = byt_suspend, + .resume = byt_resume, + /* DAI drivers */ .drv = byt_dai, .num_drv = 3, /* we have only 3 SSPs on byt*/ @@ -857,6 +904,7 @@ EXPORT_SYMBOL_NS(byt_chip_info, SND_SOC_SOF_BAYTRAIL); const struct snd_sof_dsp_ops sof_cht_ops = { /* device init */ .probe = byt_acpi_probe, + .remove = byt_remove, /* DSP core boot / reset */ .run = byt_run, @@ -906,6 +954,10 @@ const struct snd_sof_dsp_ops sof_cht_ops = { /*Firmware loading */ .load_firmware = snd_sof_load_firmware_memcpy, + /* PM */ + .suspend = byt_suspend, + .resume = byt_resume, + /* DAI drivers */ .drv = byt_dai, /* all 6 SSPs may be available for cherrytrail */ |