1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
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.
6 // Copyright(c) 2018 Intel Corporation. All rights reserved.
8 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
12 * Hardware interface for audio DSP on Baytrail, Braswell and Cherrytrail.
15 #include <linux/module.h>
16 #include <sound/sof.h>
17 #include <sound/sof/xtensa.h>
20 #include "../sof-audio.h"
21 #include "../../intel/common/soc-intel-quirks.h"
24 #define IRAM_OFFSET 0x0C0000
25 #define IRAM_SIZE (80 * 1024)
26 #define DRAM_OFFSET 0x100000
27 #define DRAM_SIZE (160 * 1024)
28 #define SHIM_OFFSET 0x140000
29 #define SHIM_SIZE 0x100
30 #define MBOX_OFFSET 0x144000
31 #define MBOX_SIZE 0x1000
32 #define EXCEPT_OFFSET 0x800
33 #define EXCEPT_MAX_HDR_SIZE 0x400
36 #define DMAC0_OFFSET 0x098000
37 #define DMAC1_OFFSET 0x09c000
38 #define DMAC2_OFFSET 0x094000
39 #define DMAC_SIZE 0x420
40 #define SSP0_OFFSET 0x0a0000
41 #define SSP1_OFFSET 0x0a1000
42 #define SSP2_OFFSET 0x0a2000
43 #define SSP3_OFFSET 0x0a4000
44 #define SSP4_OFFSET 0x0a5000
45 #define SSP5_OFFSET 0x0a6000
46 #define SSP_SIZE 0x100
48 #define BYT_STACK_DUMP_SIZE 32
50 #define BYT_PCI_BAR_SIZE 0x200000
52 #define BYT_PANIC_OFFSET(x) (((x) & GENMASK_ULL(47, 32)) >> 32)
58 #define MBOX_DUMP_SIZE 0x30
65 static const struct snd_sof_debugfs_map byt_debugfs[] = {
66 {"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
67 SOF_DEBUGFS_ACCESS_ALWAYS},
68 {"dmac1", BYT_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,
69 SOF_DEBUGFS_ACCESS_ALWAYS},
70 {"ssp0", BYT_DSP_BAR, SSP0_OFFSET, SSP_SIZE,
71 SOF_DEBUGFS_ACCESS_ALWAYS},
72 {"ssp1", BYT_DSP_BAR, SSP1_OFFSET, SSP_SIZE,
73 SOF_DEBUGFS_ACCESS_ALWAYS},
74 {"ssp2", BYT_DSP_BAR, SSP2_OFFSET, SSP_SIZE,
75 SOF_DEBUGFS_ACCESS_ALWAYS},
76 {"iram", BYT_DSP_BAR, IRAM_OFFSET, IRAM_SIZE,
77 SOF_DEBUGFS_ACCESS_D0_ONLY},
78 {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
79 SOF_DEBUGFS_ACCESS_D0_ONLY},
80 {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE,
81 SOF_DEBUGFS_ACCESS_ALWAYS},
84 static const struct snd_sof_debugfs_map cht_debugfs[] = {
85 {"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
86 SOF_DEBUGFS_ACCESS_ALWAYS},
87 {"dmac1", BYT_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,
88 SOF_DEBUGFS_ACCESS_ALWAYS},
89 {"dmac2", BYT_DSP_BAR, DMAC2_OFFSET, DMAC_SIZE,
90 SOF_DEBUGFS_ACCESS_ALWAYS},
91 {"ssp0", BYT_DSP_BAR, SSP0_OFFSET, SSP_SIZE,
92 SOF_DEBUGFS_ACCESS_ALWAYS},
93 {"ssp1", BYT_DSP_BAR, SSP1_OFFSET, SSP_SIZE,
94 SOF_DEBUGFS_ACCESS_ALWAYS},
95 {"ssp2", BYT_DSP_BAR, SSP2_OFFSET, SSP_SIZE,
96 SOF_DEBUGFS_ACCESS_ALWAYS},
97 {"ssp3", BYT_DSP_BAR, SSP3_OFFSET, SSP_SIZE,
98 SOF_DEBUGFS_ACCESS_ALWAYS},
99 {"ssp4", BYT_DSP_BAR, SSP4_OFFSET, SSP_SIZE,
100 SOF_DEBUGFS_ACCESS_ALWAYS},
101 {"ssp5", BYT_DSP_BAR, SSP5_OFFSET, SSP_SIZE,
102 SOF_DEBUGFS_ACCESS_ALWAYS},
103 {"iram", BYT_DSP_BAR, IRAM_OFFSET, IRAM_SIZE,
104 SOF_DEBUGFS_ACCESS_D0_ONLY},
105 {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
106 SOF_DEBUGFS_ACCESS_D0_ONLY},
107 {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE,
108 SOF_DEBUGFS_ACCESS_ALWAYS},
111 static void byt_host_done(struct snd_sof_dev *sdev);
112 static void byt_dsp_done(struct snd_sof_dev *sdev);
113 static void byt_get_reply(struct snd_sof_dev *sdev);
119 static void byt_get_registers(struct snd_sof_dev *sdev,
120 struct sof_ipc_dsp_oops_xtensa *xoops,
121 struct sof_ipc_panic_info *panic_info,
122 u32 *stack, size_t stack_words)
124 u32 offset = sdev->dsp_oops_offset;
126 /* first read regsisters */
127 sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
129 /* note: variable AR register array is not read */
131 /* then get panic info */
132 if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
133 dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
134 xoops->arch_hdr.totalsize);
137 offset += xoops->arch_hdr.totalsize;
138 sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
140 /* then get the stack */
141 offset += sizeof(*panic_info);
142 sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
145 static void byt_dump(struct snd_sof_dev *sdev, u32 flags)
147 struct sof_ipc_dsp_oops_xtensa xoops;
148 struct sof_ipc_panic_info panic_info;
149 u32 stack[BYT_STACK_DUMP_SIZE];
150 u32 status, panic, imrd, imrx;
152 /* now try generic SOF status messages */
153 status = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IPCD);
154 panic = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IPCX);
155 byt_get_registers(sdev, &xoops, &panic_info, stack,
156 BYT_STACK_DUMP_SIZE);
157 snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack,
158 BYT_STACK_DUMP_SIZE);
160 /* provide some context for firmware debug */
161 imrx = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IMRX);
162 imrd = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IMRD);
164 "error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n",
165 (panic & SHIM_IPCX_BUSY) ? "yes" : "no",
166 (panic & SHIM_IPCX_DONE) ? "yes" : "no", panic);
168 "error: mask host: pending %s complete %s raw 0x%8.8x\n",
169 (imrx & SHIM_IMRX_BUSY) ? "yes" : "no",
170 (imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx);
172 "error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n",
173 (status & SHIM_IPCD_BUSY) ? "yes" : "no",
174 (status & SHIM_IPCD_DONE) ? "yes" : "no", status);
176 "error: mask DSP: pending %s complete %s raw 0x%8.8x\n",
177 (imrd & SHIM_IMRD_BUSY) ? "yes" : "no",
178 (imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd);
183 * IPC Doorbell IRQ handler and thread.
186 static irqreturn_t byt_irq_handler(int irq, void *context)
188 struct snd_sof_dev *sdev = context;
192 /* Interrupt arrived, check src */
193 isr = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_ISRX);
194 if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY))
195 ret = IRQ_WAKE_THREAD;
200 static irqreturn_t byt_irq_thread(int irq, void *context)
202 struct snd_sof_dev *sdev = context;
206 imrx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IMRX);
207 ipcx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX);
209 /* reply message from DSP */
210 if (ipcx & SHIM_BYT_IPCX_DONE &&
211 !(imrx & SHIM_IMRX_DONE)) {
212 /* Mask Done interrupt before first */
213 snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR,
218 spin_lock_irq(&sdev->ipc_lock);
221 * handle immediate reply from DSP core. If the msg is
222 * found, set done bit in cmd_done which is called at the
223 * end of message processing function, else set it here
224 * because the done bit can't be set in cmd_done function
225 * which is triggered by msg
228 snd_sof_ipc_reply(sdev, ipcx);
232 spin_unlock_irq(&sdev->ipc_lock);
235 /* new message from DSP */
236 ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD);
237 if (ipcd & SHIM_BYT_IPCD_BUSY &&
238 !(imrx & SHIM_IMRX_BUSY)) {
239 /* Mask Busy interrupt before return */
240 snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR,
245 /* Handle messages from DSP Core */
246 if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
247 snd_sof_dsp_panic(sdev, BYT_PANIC_OFFSET(ipcd) +
250 snd_sof_ipc_msgs_rx(sdev);
259 static int byt_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
261 /* send the message */
262 sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
264 snd_sof_dsp_write64(sdev, BYT_DSP_BAR, SHIM_IPCX, SHIM_BYT_IPCX_BUSY);
269 static void byt_get_reply(struct snd_sof_dev *sdev)
271 struct snd_sof_ipc_msg *msg = sdev->msg;
272 struct sof_ipc_reply reply;
276 * Sometimes, there is unexpected reply ipc arriving. The reply
277 * ipc belongs to none of the ipcs sent from driver.
278 * In this case, the driver must ignore the ipc.
281 dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n");
286 sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
288 if (reply.error < 0) {
289 memcpy(msg->reply_data, &reply, sizeof(reply));
292 /* reply correct size ? */
293 if (reply.hdr.size != msg->reply_size) {
294 dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n",
295 msg->reply_size, reply.hdr.size);
299 /* read the message */
300 if (msg->reply_size > 0)
301 sof_mailbox_read(sdev, sdev->host_box.offset,
302 msg->reply_data, msg->reply_size);
305 msg->reply_error = ret;
308 static int byt_get_mailbox_offset(struct snd_sof_dev *sdev)
313 static int byt_get_window_offset(struct snd_sof_dev *sdev, u32 id)
318 static void byt_host_done(struct snd_sof_dev *sdev)
320 /* clear BUSY bit and set DONE bit - accept new messages */
321 snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCD,
326 /* unmask busy interrupt */
327 snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
331 static void byt_dsp_done(struct snd_sof_dev *sdev)
333 /* clear DONE bit - tell DSP we have completed */
334 snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCX,
335 SHIM_BYT_IPCX_DONE, 0);
337 /* unmask Done interrupt */
338 snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
346 static int byt_run(struct snd_sof_dev *sdev)
350 /* release stall and wait to unstall */
351 snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
352 SHIM_BYT_CSR_STALL, 0x0);
354 if (!(snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_CSR) &
355 SHIM_BYT_CSR_PWAITMODE))
360 dev_err(sdev->dev, "error: unable to run DSP firmware\n");
361 byt_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX);
365 /* return init core mask */
369 static int byt_reset(struct snd_sof_dev *sdev)
371 /* put DSP into reset, set reset vector and stall */
372 snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
373 SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
375 SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
378 usleep_range(10, 15);
380 /* take DSP out of reset and keep stalled for FW loading */
381 snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
382 SHIM_BYT_CSR_RST, 0);
387 static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
388 const char *sof_tplg_filename,
391 const char *tplg_filename = NULL;
395 filename = devm_kstrdup(sdev->dev, sof_tplg_filename, GFP_KERNEL);
399 /* this assumes a .tplg extension */
400 split_ext = strsep(&filename, ".");
402 tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
408 return tplg_filename;
411 static void byt_machine_select(struct snd_sof_dev *sdev)
413 struct snd_sof_pdata *sof_pdata = sdev->pdata;
414 const struct sof_dev_desc *desc = sof_pdata->desc;
415 struct snd_soc_acpi_mach *mach;
416 struct platform_device *pdev;
417 const char *tplg_filename;
419 mach = snd_soc_acpi_find_machine(desc->machines);
421 dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
425 pdev = to_platform_device(sdev->dev);
426 if (soc_intel_is_byt_cr(pdev)) {
428 "BYT-CR detected, SSP0 used instead of SSP2\n");
430 tplg_filename = fixup_tplg_name(sdev,
431 mach->sof_tplg_filename,
434 tplg_filename = mach->sof_tplg_filename;
437 if (!tplg_filename) {
439 "error: no topology filename\n");
443 sof_pdata->tplg_filename = tplg_filename;
444 mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc;
445 sof_pdata->machine = mach;
448 static void byt_set_mach_params(const struct snd_soc_acpi_mach *mach,
451 struct snd_soc_acpi_mach_params *mach_params;
453 mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params;
454 mach_params->platform = dev_name(dev);
458 static struct snd_soc_dai_driver byt_dai[] = {
483 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD)
485 static int tangier_pci_probe(struct snd_sof_dev *sdev)
487 struct snd_sof_pdata *pdata = sdev->pdata;
488 const struct sof_dev_desc *desc = pdata->desc;
489 struct pci_dev *pci = to_pci_dev(sdev->dev);
493 /* DSP DMA can only access low 31 bits of host memory */
494 ret = dma_coerce_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31));
496 dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
501 base = pci_resource_start(pci, desc->resindex_lpe_base) - IRAM_OFFSET;
502 size = BYT_PCI_BAR_SIZE;
504 dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
505 sdev->bar[BYT_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
506 if (!sdev->bar[BYT_DSP_BAR]) {
507 dev_err(sdev->dev, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
511 dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BYT_DSP_BAR]);
513 /* IMR base - optional */
514 if (desc->resindex_imr_base == -1)
517 base = pci_resource_start(pci, desc->resindex_imr_base);
518 size = pci_resource_len(pci, desc->resindex_imr_base);
520 /* some BIOSes don't map IMR */
521 if (base == 0x55aa55aa || base == 0x0) {
522 dev_info(sdev->dev, "IMR not set by BIOS. Ignoring\n");
526 dev_dbg(sdev->dev, "IMR base at 0x%x size 0x%x", base, size);
527 sdev->bar[BYT_IMR_BAR] = devm_ioremap(sdev->dev, base, size);
528 if (!sdev->bar[BYT_IMR_BAR]) {
529 dev_err(sdev->dev, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
533 dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[BYT_IMR_BAR]);
536 /* register our IRQ */
537 sdev->ipc_irq = pci->irq;
538 dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
539 ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
540 byt_irq_handler, byt_irq_thread,
541 0, "AudioDSP", sdev);
543 dev_err(sdev->dev, "error: failed to register IRQ %d\n",
548 /* enable Interrupt from both sides */
549 snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0);
550 snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0);
552 /* set default mailbox offset for FW ready message */
553 sdev->dsp_box.offset = MBOX_OFFSET;
558 const struct snd_sof_dsp_ops sof_tng_ops = {
560 .probe = tangier_pci_probe,
562 /* DSP core boot / reset */
567 .write = sof_io_write,
569 .write64 = sof_io_write64,
570 .read64 = sof_io_read64,
573 .block_read = sof_block_read,
574 .block_write = sof_block_write,
577 .irq_handler = byt_irq_handler,
578 .irq_thread = byt_irq_thread,
581 .send_msg = byt_send_msg,
582 .fw_ready = sof_fw_ready,
583 .get_mailbox_offset = byt_get_mailbox_offset,
584 .get_window_offset = byt_get_window_offset,
586 .ipc_msg_data = intel_ipc_msg_data,
587 .ipc_pcm_params = intel_ipc_pcm_params,
590 .machine_select = byt_machine_select,
591 .machine_register = sof_machine_register,
592 .machine_unregister = sof_machine_unregister,
593 .set_mach_params = byt_set_mach_params,
596 .debug_map = byt_debugfs,
597 .debug_map_count = ARRAY_SIZE(byt_debugfs),
598 .dbg_dump = byt_dump,
600 /* stream callbacks */
601 .pcm_open = intel_pcm_open,
602 .pcm_close = intel_pcm_close,
605 .load_module = snd_sof_parse_module_memcpy,
607 /*Firmware loading */
608 .load_firmware = snd_sof_load_firmware_memcpy,
612 .num_drv = 3, /* we have only 3 SSPs on byt*/
614 /* ALSA HW info flags */
615 .hw_info = SNDRV_PCM_INFO_MMAP |
616 SNDRV_PCM_INFO_MMAP_VALID |
617 SNDRV_PCM_INFO_INTERLEAVED |
618 SNDRV_PCM_INFO_PAUSE |
619 SNDRV_PCM_INFO_BATCH,
621 EXPORT_SYMBOL(sof_tng_ops);
623 const struct sof_intel_dsp_desc tng_chip_info = {
627 EXPORT_SYMBOL(tng_chip_info);
629 #endif /* CONFIG_SND_SOC_SOF_MERRIFIELD */
631 #if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
633 static int byt_acpi_probe(struct snd_sof_dev *sdev)
635 struct snd_sof_pdata *pdata = sdev->pdata;
636 const struct sof_dev_desc *desc = pdata->desc;
637 struct platform_device *pdev =
638 container_of(sdev->dev, struct platform_device, dev);
639 struct resource *mmio;
643 /* DSP DMA can only access low 31 bits of host memory */
644 ret = dma_coerce_mask_and_coherent(sdev->dev, DMA_BIT_MASK(31));
646 dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
651 mmio = platform_get_resource(pdev, IORESOURCE_MEM,
652 desc->resindex_lpe_base);
655 size = resource_size(mmio);
657 dev_err(sdev->dev, "error: failed to get LPE base at idx %d\n",
658 desc->resindex_lpe_base);
662 dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
663 sdev->bar[BYT_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
664 if (!sdev->bar[BYT_DSP_BAR]) {
665 dev_err(sdev->dev, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
669 dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BYT_DSP_BAR]);
671 /* TODO: add offsets */
672 sdev->mmio_bar = BYT_DSP_BAR;
673 sdev->mailbox_bar = BYT_DSP_BAR;
675 /* IMR base - optional */
676 if (desc->resindex_imr_base == -1)
679 mmio = platform_get_resource(pdev, IORESOURCE_MEM,
680 desc->resindex_imr_base);
683 size = resource_size(mmio);
685 dev_err(sdev->dev, "error: failed to get IMR base at idx %d\n",
686 desc->resindex_imr_base);
690 /* some BIOSes don't map IMR */
691 if (base == 0x55aa55aa || base == 0x0) {
692 dev_info(sdev->dev, "IMR not set by BIOS. Ignoring\n");
696 dev_dbg(sdev->dev, "IMR base at 0x%x size 0x%x", base, size);
697 sdev->bar[BYT_IMR_BAR] = devm_ioremap(sdev->dev, base, size);
698 if (!sdev->bar[BYT_IMR_BAR]) {
699 dev_err(sdev->dev, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
703 dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[BYT_IMR_BAR]);
706 /* register our IRQ */
707 sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc);
708 if (sdev->ipc_irq < 0)
709 return sdev->ipc_irq;
711 dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
712 ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
713 byt_irq_handler, byt_irq_thread,
714 IRQF_SHARED, "AudioDSP", sdev);
716 dev_err(sdev->dev, "error: failed to register IRQ %d\n",
721 /* enable Interrupt from both sides */
722 snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0);
723 snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0);
725 /* set default mailbox offset for FW ready message */
726 sdev->dsp_box.offset = MBOX_OFFSET;
732 const struct snd_sof_dsp_ops sof_byt_ops = {
734 .probe = byt_acpi_probe,
736 /* DSP core boot / reset */
741 .write = sof_io_write,
743 .write64 = sof_io_write64,
744 .read64 = sof_io_read64,
747 .block_read = sof_block_read,
748 .block_write = sof_block_write,
751 .irq_handler = byt_irq_handler,
752 .irq_thread = byt_irq_thread,
755 .send_msg = byt_send_msg,
756 .fw_ready = sof_fw_ready,
757 .get_mailbox_offset = byt_get_mailbox_offset,
758 .get_window_offset = byt_get_window_offset,
760 .ipc_msg_data = intel_ipc_msg_data,
761 .ipc_pcm_params = intel_ipc_pcm_params,
764 .machine_select = byt_machine_select,
765 .machine_register = sof_machine_register,
766 .machine_unregister = sof_machine_unregister,
767 .set_mach_params = byt_set_mach_params,
770 .debug_map = byt_debugfs,
771 .debug_map_count = ARRAY_SIZE(byt_debugfs),
772 .dbg_dump = byt_dump,
774 /* stream callbacks */
775 .pcm_open = intel_pcm_open,
776 .pcm_close = intel_pcm_close,
779 .load_module = snd_sof_parse_module_memcpy,
781 /*Firmware loading */
782 .load_firmware = snd_sof_load_firmware_memcpy,
786 .num_drv = 3, /* we have only 3 SSPs on byt*/
788 /* ALSA HW info flags */
789 .hw_info = SNDRV_PCM_INFO_MMAP |
790 SNDRV_PCM_INFO_MMAP_VALID |
791 SNDRV_PCM_INFO_INTERLEAVED |
792 SNDRV_PCM_INFO_PAUSE |
793 SNDRV_PCM_INFO_BATCH,
795 EXPORT_SYMBOL(sof_byt_ops);
797 const struct sof_intel_dsp_desc byt_chip_info = {
801 EXPORT_SYMBOL(byt_chip_info);
803 /* cherrytrail and braswell ops */
804 const struct snd_sof_dsp_ops sof_cht_ops = {
806 .probe = byt_acpi_probe,
808 /* DSP core boot / reset */
813 .write = sof_io_write,
815 .write64 = sof_io_write64,
816 .read64 = sof_io_read64,
819 .block_read = sof_block_read,
820 .block_write = sof_block_write,
823 .irq_handler = byt_irq_handler,
824 .irq_thread = byt_irq_thread,
827 .send_msg = byt_send_msg,
828 .fw_ready = sof_fw_ready,
829 .get_mailbox_offset = byt_get_mailbox_offset,
830 .get_window_offset = byt_get_window_offset,
832 .ipc_msg_data = intel_ipc_msg_data,
833 .ipc_pcm_params = intel_ipc_pcm_params,
836 .machine_select = byt_machine_select,
837 .machine_register = sof_machine_register,
838 .machine_unregister = sof_machine_unregister,
839 .set_mach_params = byt_set_mach_params,
842 .debug_map = cht_debugfs,
843 .debug_map_count = ARRAY_SIZE(cht_debugfs),
844 .dbg_dump = byt_dump,
846 /* stream callbacks */
847 .pcm_open = intel_pcm_open,
848 .pcm_close = intel_pcm_close,
851 .load_module = snd_sof_parse_module_memcpy,
853 /*Firmware loading */
854 .load_firmware = snd_sof_load_firmware_memcpy,
858 /* all 6 SSPs may be available for cherrytrail */
859 .num_drv = ARRAY_SIZE(byt_dai),
861 /* ALSA HW info flags */
862 .hw_info = SNDRV_PCM_INFO_MMAP |
863 SNDRV_PCM_INFO_MMAP_VALID |
864 SNDRV_PCM_INFO_INTERLEAVED |
865 SNDRV_PCM_INFO_PAUSE |
866 SNDRV_PCM_INFO_BATCH,
868 EXPORT_SYMBOL(sof_cht_ops);
870 const struct sof_intel_dsp_desc cht_chip_info = {
874 EXPORT_SYMBOL(cht_chip_info);
876 #endif /* CONFIG_SND_SOC_SOF_BAYTRAIL */
878 MODULE_LICENSE("Dual BSD/GPL");