18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// This file is provided under a dual BSD/GPLv2 license. When using or 48c2ecf20Sopenharmony_ci// redistributing this file, you may do so under either license. 58c2ecf20Sopenharmony_ci// 68c2ecf20Sopenharmony_ci// Copyright(c) 2018 Intel Corporation. All rights reserved. 78c2ecf20Sopenharmony_ci// 88c2ecf20Sopenharmony_ci// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> 98c2ecf20Sopenharmony_ci// 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/* 128c2ecf20Sopenharmony_ci * Hardware interface for audio DSP on Broadwell 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <sound/sof.h> 178c2ecf20Sopenharmony_ci#include <sound/sof/xtensa.h> 188c2ecf20Sopenharmony_ci#include "../ops.h" 198c2ecf20Sopenharmony_ci#include "shim.h" 208c2ecf20Sopenharmony_ci#include "../sof-audio.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* BARs */ 238c2ecf20Sopenharmony_ci#define BDW_DSP_BAR 0 248c2ecf20Sopenharmony_ci#define BDW_PCI_BAR 1 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* 278c2ecf20Sopenharmony_ci * Debug 288c2ecf20Sopenharmony_ci */ 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* DSP memories for BDW */ 318c2ecf20Sopenharmony_ci#define IRAM_OFFSET 0xA0000 328c2ecf20Sopenharmony_ci#define BDW_IRAM_SIZE (10 * 32 * 1024) 338c2ecf20Sopenharmony_ci#define DRAM_OFFSET 0x00000 348c2ecf20Sopenharmony_ci#define BDW_DRAM_SIZE (20 * 32 * 1024) 358c2ecf20Sopenharmony_ci#define SHIM_OFFSET 0xFB000 368c2ecf20Sopenharmony_ci#define SHIM_SIZE 0x100 378c2ecf20Sopenharmony_ci#define MBOX_OFFSET 0x9E000 388c2ecf20Sopenharmony_ci#define MBOX_SIZE 0x1000 398c2ecf20Sopenharmony_ci#define MBOX_DUMP_SIZE 0x30 408c2ecf20Sopenharmony_ci#define EXCEPT_OFFSET 0x800 418c2ecf20Sopenharmony_ci#define EXCEPT_MAX_HDR_SIZE 0x400 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* DSP peripherals */ 448c2ecf20Sopenharmony_ci#define DMAC0_OFFSET 0xFE000 458c2ecf20Sopenharmony_ci#define DMAC1_OFFSET 0xFF000 468c2ecf20Sopenharmony_ci#define DMAC_SIZE 0x420 478c2ecf20Sopenharmony_ci#define SSP0_OFFSET 0xFC000 488c2ecf20Sopenharmony_ci#define SSP1_OFFSET 0xFD000 498c2ecf20Sopenharmony_ci#define SSP_SIZE 0x100 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#define BDW_STACK_DUMP_SIZE 32 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define BDW_PANIC_OFFSET(x) ((x) & 0xFFFF) 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic const struct snd_sof_debugfs_map bdw_debugfs[] = { 568c2ecf20Sopenharmony_ci {"dmac0", BDW_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE, 578c2ecf20Sopenharmony_ci SOF_DEBUGFS_ACCESS_ALWAYS}, 588c2ecf20Sopenharmony_ci {"dmac1", BDW_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE, 598c2ecf20Sopenharmony_ci SOF_DEBUGFS_ACCESS_ALWAYS}, 608c2ecf20Sopenharmony_ci {"ssp0", BDW_DSP_BAR, SSP0_OFFSET, SSP_SIZE, 618c2ecf20Sopenharmony_ci SOF_DEBUGFS_ACCESS_ALWAYS}, 628c2ecf20Sopenharmony_ci {"ssp1", BDW_DSP_BAR, SSP1_OFFSET, SSP_SIZE, 638c2ecf20Sopenharmony_ci SOF_DEBUGFS_ACCESS_ALWAYS}, 648c2ecf20Sopenharmony_ci {"iram", BDW_DSP_BAR, IRAM_OFFSET, BDW_IRAM_SIZE, 658c2ecf20Sopenharmony_ci SOF_DEBUGFS_ACCESS_D0_ONLY}, 668c2ecf20Sopenharmony_ci {"dram", BDW_DSP_BAR, DRAM_OFFSET, BDW_DRAM_SIZE, 678c2ecf20Sopenharmony_ci SOF_DEBUGFS_ACCESS_D0_ONLY}, 688c2ecf20Sopenharmony_ci {"shim", BDW_DSP_BAR, SHIM_OFFSET, SHIM_SIZE, 698c2ecf20Sopenharmony_ci SOF_DEBUGFS_ACCESS_ALWAYS}, 708c2ecf20Sopenharmony_ci}; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic void bdw_host_done(struct snd_sof_dev *sdev); 738c2ecf20Sopenharmony_cistatic void bdw_dsp_done(struct snd_sof_dev *sdev); 748c2ecf20Sopenharmony_cistatic void bdw_get_reply(struct snd_sof_dev *sdev); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/* 778c2ecf20Sopenharmony_ci * DSP Control. 788c2ecf20Sopenharmony_ci */ 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic int bdw_run(struct snd_sof_dev *sdev) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci /* set opportunistic mode on engine 0,1 for all channels */ 838c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_HMDC, 848c2ecf20Sopenharmony_ci SHIM_HMDC_HDDA_E0_ALLCH | 858c2ecf20Sopenharmony_ci SHIM_HMDC_HDDA_E1_ALLCH, 0); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci /* set DSP to RUN */ 888c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR, 898c2ecf20Sopenharmony_ci SHIM_CSR_STALL, 0x0); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci /* return init core mask */ 928c2ecf20Sopenharmony_ci return 1; 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic int bdw_reset(struct snd_sof_dev *sdev) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci /* put DSP into reset and stall */ 988c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR, 998c2ecf20Sopenharmony_ci SHIM_CSR_RST | SHIM_CSR_STALL, 1008c2ecf20Sopenharmony_ci SHIM_CSR_RST | SHIM_CSR_STALL); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci /* keep in reset for 10ms */ 1038c2ecf20Sopenharmony_ci mdelay(10); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci /* take DSP out of reset and keep stalled for FW loading */ 1068c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR, 1078c2ecf20Sopenharmony_ci SHIM_CSR_RST | SHIM_CSR_STALL, 1088c2ecf20Sopenharmony_ci SHIM_CSR_STALL); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci return 0; 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic int bdw_set_dsp_D0(struct snd_sof_dev *sdev) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci int tries = 10; 1168c2ecf20Sopenharmony_ci u32 reg; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */ 1198c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2, 1208c2ecf20Sopenharmony_ci PCI_VDRTCL2_DCLCGE | 1218c2ecf20Sopenharmony_ci PCI_VDRTCL2_DTCGE, 0); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci /* Disable D3PG (VDRTCTL0.D3PGD = 1) */ 1248c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL0, 1258c2ecf20Sopenharmony_ci PCI_VDRTCL0_D3PGD, PCI_VDRTCL0_D3PGD); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* Set D0 state */ 1288c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_PMCS, 1298c2ecf20Sopenharmony_ci PCI_PMCS_PS_MASK, 0); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci /* check that ADSP shim is enabled */ 1328c2ecf20Sopenharmony_ci while (tries--) { 1338c2ecf20Sopenharmony_ci reg = readl(sdev->bar[BDW_PCI_BAR] + PCI_PMCS) 1348c2ecf20Sopenharmony_ci & PCI_PMCS_PS_MASK; 1358c2ecf20Sopenharmony_ci if (reg == 0) 1368c2ecf20Sopenharmony_ci goto finish; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci msleep(20); 1398c2ecf20Sopenharmony_ci } 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci return -ENODEV; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cifinish: 1448c2ecf20Sopenharmony_ci /* 1458c2ecf20Sopenharmony_ci * select SSP1 19.2MHz base clock, SSP clock 0, 1468c2ecf20Sopenharmony_ci * turn off Low Power Clock 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR, 1498c2ecf20Sopenharmony_ci SHIM_CSR_S1IOCS | SHIM_CSR_SBCS1 | 1508c2ecf20Sopenharmony_ci SHIM_CSR_LPCS, 0x0); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci /* stall DSP core, set clk to 192/96Mhz */ 1538c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, 1548c2ecf20Sopenharmony_ci SHIM_CSR, SHIM_CSR_STALL | 1558c2ecf20Sopenharmony_ci SHIM_CSR_DCS_MASK, 1568c2ecf20Sopenharmony_ci SHIM_CSR_STALL | 1578c2ecf20Sopenharmony_ci SHIM_CSR_DCS(4)); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci /* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */ 1608c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CLKCTL, 1618c2ecf20Sopenharmony_ci SHIM_CLKCTL_MASK | 1628c2ecf20Sopenharmony_ci SHIM_CLKCTL_DCPLCG | 1638c2ecf20Sopenharmony_ci SHIM_CLKCTL_SCOE0, 1648c2ecf20Sopenharmony_ci SHIM_CLKCTL_MASK | 1658c2ecf20Sopenharmony_ci SHIM_CLKCTL_DCPLCG | 1668c2ecf20Sopenharmony_ci SHIM_CLKCTL_SCOE0); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci /* Stall and reset core, set CSR */ 1698c2ecf20Sopenharmony_ci bdw_reset(sdev); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */ 1728c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2, 1738c2ecf20Sopenharmony_ci PCI_VDRTCL2_DCLCGE | 1748c2ecf20Sopenharmony_ci PCI_VDRTCL2_DTCGE, 1758c2ecf20Sopenharmony_ci PCI_VDRTCL2_DCLCGE | 1768c2ecf20Sopenharmony_ci PCI_VDRTCL2_DTCGE); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci usleep_range(50, 55); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* switch on audio PLL */ 1818c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2, 1828c2ecf20Sopenharmony_ci PCI_VDRTCL2_APLLSE_MASK, 0); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci /* 1858c2ecf20Sopenharmony_ci * set default power gating control, enable power gating control for 1868c2ecf20Sopenharmony_ci * all blocks. that is, can't be accessed, please enable each block 1878c2ecf20Sopenharmony_ci * before accessing. 1888c2ecf20Sopenharmony_ci */ 1898c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL0, 1908c2ecf20Sopenharmony_ci 0xfffffffC, 0x0); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci /* disable DMA finish function for SSP0 & SSP1 */ 1938c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR2, 1948c2ecf20Sopenharmony_ci SHIM_CSR2_SDFD_SSP1, 1958c2ecf20Sopenharmony_ci SHIM_CSR2_SDFD_SSP1); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci /* set on-demond mode on engine 0,1 for all channels */ 1988c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_HMDC, 1998c2ecf20Sopenharmony_ci SHIM_HMDC_HDDA_E0_ALLCH | 2008c2ecf20Sopenharmony_ci SHIM_HMDC_HDDA_E1_ALLCH, 2018c2ecf20Sopenharmony_ci SHIM_HMDC_HDDA_E0_ALLCH | 2028c2ecf20Sopenharmony_ci SHIM_HMDC_HDDA_E1_ALLCH); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci /* Enable Interrupt from both sides */ 2058c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_IMRX, 2068c2ecf20Sopenharmony_ci (SHIM_IMRX_BUSY | SHIM_IMRX_DONE), 0x0); 2078c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_IMRD, 2088c2ecf20Sopenharmony_ci (SHIM_IMRD_DONE | SHIM_IMRD_BUSY | 2098c2ecf20Sopenharmony_ci SHIM_IMRD_SSP0 | SHIM_IMRD_DMAC), 0x0); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci /* clear IPC registers */ 2128c2ecf20Sopenharmony_ci snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCX, 0x0); 2138c2ecf20Sopenharmony_ci snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCD, 0x0); 2148c2ecf20Sopenharmony_ci snd_sof_dsp_write(sdev, BDW_DSP_BAR, 0x80, 0x6); 2158c2ecf20Sopenharmony_ci snd_sof_dsp_write(sdev, BDW_DSP_BAR, 0xe0, 0x300a); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci return 0; 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistatic void bdw_get_registers(struct snd_sof_dev *sdev, 2218c2ecf20Sopenharmony_ci struct sof_ipc_dsp_oops_xtensa *xoops, 2228c2ecf20Sopenharmony_ci struct sof_ipc_panic_info *panic_info, 2238c2ecf20Sopenharmony_ci u32 *stack, size_t stack_words) 2248c2ecf20Sopenharmony_ci{ 2258c2ecf20Sopenharmony_ci u32 offset = sdev->dsp_oops_offset; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* first read registers */ 2288c2ecf20Sopenharmony_ci sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops)); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci /* note: variable AR register array is not read */ 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci /* then get panic info */ 2338c2ecf20Sopenharmony_ci if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) { 2348c2ecf20Sopenharmony_ci dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n", 2358c2ecf20Sopenharmony_ci xoops->arch_hdr.totalsize); 2368c2ecf20Sopenharmony_ci return; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci offset += xoops->arch_hdr.totalsize; 2398c2ecf20Sopenharmony_ci sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info)); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci /* then get the stack */ 2428c2ecf20Sopenharmony_ci offset += sizeof(*panic_info); 2438c2ecf20Sopenharmony_ci sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32)); 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic void bdw_dump(struct snd_sof_dev *sdev, u32 flags) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci struct sof_ipc_dsp_oops_xtensa xoops; 2498c2ecf20Sopenharmony_ci struct sof_ipc_panic_info panic_info; 2508c2ecf20Sopenharmony_ci u32 stack[BDW_STACK_DUMP_SIZE]; 2518c2ecf20Sopenharmony_ci u32 status, panic, imrx, imrd; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* now try generic SOF status messages */ 2548c2ecf20Sopenharmony_ci status = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD); 2558c2ecf20Sopenharmony_ci panic = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCX); 2568c2ecf20Sopenharmony_ci bdw_get_registers(sdev, &xoops, &panic_info, stack, 2578c2ecf20Sopenharmony_ci BDW_STACK_DUMP_SIZE); 2588c2ecf20Sopenharmony_ci snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack, 2598c2ecf20Sopenharmony_ci BDW_STACK_DUMP_SIZE); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci /* provide some context for firmware debug */ 2628c2ecf20Sopenharmony_ci imrx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRX); 2638c2ecf20Sopenharmony_ci imrd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRD); 2648c2ecf20Sopenharmony_ci dev_err(sdev->dev, 2658c2ecf20Sopenharmony_ci "error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n", 2668c2ecf20Sopenharmony_ci (panic & SHIM_IPCX_BUSY) ? "yes" : "no", 2678c2ecf20Sopenharmony_ci (panic & SHIM_IPCX_DONE) ? "yes" : "no", panic); 2688c2ecf20Sopenharmony_ci dev_err(sdev->dev, 2698c2ecf20Sopenharmony_ci "error: mask host: pending %s complete %s raw 0x%8.8x\n", 2708c2ecf20Sopenharmony_ci (imrx & SHIM_IMRX_BUSY) ? "yes" : "no", 2718c2ecf20Sopenharmony_ci (imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx); 2728c2ecf20Sopenharmony_ci dev_err(sdev->dev, 2738c2ecf20Sopenharmony_ci "error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n", 2748c2ecf20Sopenharmony_ci (status & SHIM_IPCD_BUSY) ? "yes" : "no", 2758c2ecf20Sopenharmony_ci (status & SHIM_IPCD_DONE) ? "yes" : "no", status); 2768c2ecf20Sopenharmony_ci dev_err(sdev->dev, 2778c2ecf20Sopenharmony_ci "error: mask DSP: pending %s complete %s raw 0x%8.8x\n", 2788c2ecf20Sopenharmony_ci (imrd & SHIM_IMRD_BUSY) ? "yes" : "no", 2798c2ecf20Sopenharmony_ci (imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd); 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci/* 2838c2ecf20Sopenharmony_ci * IPC Doorbell IRQ handler and thread. 2848c2ecf20Sopenharmony_ci */ 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistatic irqreturn_t bdw_irq_handler(int irq, void *context) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci struct snd_sof_dev *sdev = context; 2898c2ecf20Sopenharmony_ci u32 isr; 2908c2ecf20Sopenharmony_ci int ret = IRQ_NONE; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci /* Interrupt arrived, check src */ 2938c2ecf20Sopenharmony_ci isr = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_ISRX); 2948c2ecf20Sopenharmony_ci if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY)) 2958c2ecf20Sopenharmony_ci ret = IRQ_WAKE_THREAD; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci return ret; 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic irqreturn_t bdw_irq_thread(int irq, void *context) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci struct snd_sof_dev *sdev = context; 3038c2ecf20Sopenharmony_ci u32 ipcx, ipcd, imrx; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci imrx = snd_sof_dsp_read64(sdev, BDW_DSP_BAR, SHIM_IMRX); 3068c2ecf20Sopenharmony_ci ipcx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCX); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci /* reply message from DSP */ 3098c2ecf20Sopenharmony_ci if (ipcx & SHIM_IPCX_DONE && 3108c2ecf20Sopenharmony_ci !(imrx & SHIM_IMRX_DONE)) { 3118c2ecf20Sopenharmony_ci /* Mask Done interrupt before return */ 3128c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, 3138c2ecf20Sopenharmony_ci SHIM_IMRX, SHIM_IMRX_DONE, 3148c2ecf20Sopenharmony_ci SHIM_IMRX_DONE); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci spin_lock_irq(&sdev->ipc_lock); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci /* 3198c2ecf20Sopenharmony_ci * handle immediate reply from DSP core. If the msg is 3208c2ecf20Sopenharmony_ci * found, set done bit in cmd_done which is called at the 3218c2ecf20Sopenharmony_ci * end of message processing function, else set it here 3228c2ecf20Sopenharmony_ci * because the done bit can't be set in cmd_done function 3238c2ecf20Sopenharmony_ci * which is triggered by msg 3248c2ecf20Sopenharmony_ci */ 3258c2ecf20Sopenharmony_ci bdw_get_reply(sdev); 3268c2ecf20Sopenharmony_ci snd_sof_ipc_reply(sdev, ipcx); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci bdw_dsp_done(sdev); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci spin_unlock_irq(&sdev->ipc_lock); 3318c2ecf20Sopenharmony_ci } 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci ipcd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci /* new message from DSP */ 3368c2ecf20Sopenharmony_ci if (ipcd & SHIM_IPCD_BUSY && 3378c2ecf20Sopenharmony_ci !(imrx & SHIM_IMRX_BUSY)) { 3388c2ecf20Sopenharmony_ci /* Mask Busy interrupt before return */ 3398c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, 3408c2ecf20Sopenharmony_ci SHIM_IMRX, SHIM_IMRX_BUSY, 3418c2ecf20Sopenharmony_ci SHIM_IMRX_BUSY); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci /* Handle messages from DSP Core */ 3448c2ecf20Sopenharmony_ci if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) { 3458c2ecf20Sopenharmony_ci snd_sof_dsp_panic(sdev, BDW_PANIC_OFFSET(ipcx) + 3468c2ecf20Sopenharmony_ci MBOX_OFFSET); 3478c2ecf20Sopenharmony_ci } else { 3488c2ecf20Sopenharmony_ci snd_sof_ipc_msgs_rx(sdev); 3498c2ecf20Sopenharmony_ci } 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci bdw_host_done(sdev); 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci return IRQ_HANDLED; 3558c2ecf20Sopenharmony_ci} 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci/* 3588c2ecf20Sopenharmony_ci * IPC Mailbox IO 3598c2ecf20Sopenharmony_ci */ 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic int bdw_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci /* send the message */ 3648c2ecf20Sopenharmony_ci sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, 3658c2ecf20Sopenharmony_ci msg->msg_size); 3668c2ecf20Sopenharmony_ci snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCX, SHIM_IPCX_BUSY); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci return 0; 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_cistatic void bdw_get_reply(struct snd_sof_dev *sdev) 3728c2ecf20Sopenharmony_ci{ 3738c2ecf20Sopenharmony_ci struct snd_sof_ipc_msg *msg = sdev->msg; 3748c2ecf20Sopenharmony_ci struct sof_ipc_reply reply; 3758c2ecf20Sopenharmony_ci int ret = 0; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci /* 3788c2ecf20Sopenharmony_ci * Sometimes, there is unexpected reply ipc arriving. The reply 3798c2ecf20Sopenharmony_ci * ipc belongs to none of the ipcs sent from driver. 3808c2ecf20Sopenharmony_ci * In this case, the driver must ignore the ipc. 3818c2ecf20Sopenharmony_ci */ 3828c2ecf20Sopenharmony_ci if (!msg) { 3838c2ecf20Sopenharmony_ci dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n"); 3848c2ecf20Sopenharmony_ci return; 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci /* get reply */ 3888c2ecf20Sopenharmony_ci sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply)); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci if (reply.error < 0) { 3918c2ecf20Sopenharmony_ci memcpy(msg->reply_data, &reply, sizeof(reply)); 3928c2ecf20Sopenharmony_ci ret = reply.error; 3938c2ecf20Sopenharmony_ci } else { 3948c2ecf20Sopenharmony_ci /* reply correct size ? */ 3958c2ecf20Sopenharmony_ci if (reply.hdr.size != msg->reply_size) { 3968c2ecf20Sopenharmony_ci dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n", 3978c2ecf20Sopenharmony_ci msg->reply_size, reply.hdr.size); 3988c2ecf20Sopenharmony_ci ret = -EINVAL; 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci /* read the message */ 4028c2ecf20Sopenharmony_ci if (msg->reply_size > 0) 4038c2ecf20Sopenharmony_ci sof_mailbox_read(sdev, sdev->host_box.offset, 4048c2ecf20Sopenharmony_ci msg->reply_data, msg->reply_size); 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci msg->reply_error = ret; 4088c2ecf20Sopenharmony_ci} 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cistatic int bdw_get_mailbox_offset(struct snd_sof_dev *sdev) 4118c2ecf20Sopenharmony_ci{ 4128c2ecf20Sopenharmony_ci return MBOX_OFFSET; 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_cistatic int bdw_get_window_offset(struct snd_sof_dev *sdev, u32 id) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci return MBOX_OFFSET; 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic void bdw_host_done(struct snd_sof_dev *sdev) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci /* clear BUSY bit and set DONE bit - accept new messages */ 4238c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCD, 4248c2ecf20Sopenharmony_ci SHIM_IPCD_BUSY | SHIM_IPCD_DONE, 4258c2ecf20Sopenharmony_ci SHIM_IPCD_DONE); 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci /* unmask busy interrupt */ 4288c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX, 4298c2ecf20Sopenharmony_ci SHIM_IMRX_BUSY, 0); 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistatic void bdw_dsp_done(struct snd_sof_dev *sdev) 4338c2ecf20Sopenharmony_ci{ 4348c2ecf20Sopenharmony_ci /* clear DONE bit - tell DSP we have completed */ 4358c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCX, 4368c2ecf20Sopenharmony_ci SHIM_IPCX_DONE, 0); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci /* unmask Done interrupt */ 4398c2ecf20Sopenharmony_ci snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX, 4408c2ecf20Sopenharmony_ci SHIM_IMRX_DONE, 0); 4418c2ecf20Sopenharmony_ci} 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci/* 4448c2ecf20Sopenharmony_ci * Probe and remove. 4458c2ecf20Sopenharmony_ci */ 4468c2ecf20Sopenharmony_cistatic int bdw_probe(struct snd_sof_dev *sdev) 4478c2ecf20Sopenharmony_ci{ 4488c2ecf20Sopenharmony_ci struct snd_sof_pdata *pdata = sdev->pdata; 4498c2ecf20Sopenharmony_ci const struct sof_dev_desc *desc = pdata->desc; 4508c2ecf20Sopenharmony_ci struct platform_device *pdev = 4518c2ecf20Sopenharmony_ci container_of(sdev->dev, struct platform_device, dev); 4528c2ecf20Sopenharmony_ci struct resource *mmio; 4538c2ecf20Sopenharmony_ci u32 base, size; 4548c2ecf20Sopenharmony_ci int ret; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci /* LPE base */ 4578c2ecf20Sopenharmony_ci mmio = platform_get_resource(pdev, IORESOURCE_MEM, 4588c2ecf20Sopenharmony_ci desc->resindex_lpe_base); 4598c2ecf20Sopenharmony_ci if (mmio) { 4608c2ecf20Sopenharmony_ci base = mmio->start; 4618c2ecf20Sopenharmony_ci size = resource_size(mmio); 4628c2ecf20Sopenharmony_ci } else { 4638c2ecf20Sopenharmony_ci dev_err(sdev->dev, "error: failed to get LPE base at idx %d\n", 4648c2ecf20Sopenharmony_ci desc->resindex_lpe_base); 4658c2ecf20Sopenharmony_ci return -EINVAL; 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size); 4698c2ecf20Sopenharmony_ci sdev->bar[BDW_DSP_BAR] = devm_ioremap(sdev->dev, base, size); 4708c2ecf20Sopenharmony_ci if (!sdev->bar[BDW_DSP_BAR]) { 4718c2ecf20Sopenharmony_ci dev_err(sdev->dev, 4728c2ecf20Sopenharmony_ci "error: failed to ioremap LPE base 0x%x size 0x%x\n", 4738c2ecf20Sopenharmony_ci base, size); 4748c2ecf20Sopenharmony_ci return -ENODEV; 4758c2ecf20Sopenharmony_ci } 4768c2ecf20Sopenharmony_ci dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BDW_DSP_BAR]); 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci /* TODO: add offsets */ 4798c2ecf20Sopenharmony_ci sdev->mmio_bar = BDW_DSP_BAR; 4808c2ecf20Sopenharmony_ci sdev->mailbox_bar = BDW_DSP_BAR; 4818c2ecf20Sopenharmony_ci sdev->dsp_oops_offset = MBOX_OFFSET; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci /* PCI base */ 4848c2ecf20Sopenharmony_ci mmio = platform_get_resource(pdev, IORESOURCE_MEM, 4858c2ecf20Sopenharmony_ci desc->resindex_pcicfg_base); 4868c2ecf20Sopenharmony_ci if (mmio) { 4878c2ecf20Sopenharmony_ci base = mmio->start; 4888c2ecf20Sopenharmony_ci size = resource_size(mmio); 4898c2ecf20Sopenharmony_ci } else { 4908c2ecf20Sopenharmony_ci dev_err(sdev->dev, "error: failed to get PCI base at idx %d\n", 4918c2ecf20Sopenharmony_ci desc->resindex_pcicfg_base); 4928c2ecf20Sopenharmony_ci return -ENODEV; 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci dev_dbg(sdev->dev, "PCI base at 0x%x size 0x%x", base, size); 4968c2ecf20Sopenharmony_ci sdev->bar[BDW_PCI_BAR] = devm_ioremap(sdev->dev, base, size); 4978c2ecf20Sopenharmony_ci if (!sdev->bar[BDW_PCI_BAR]) { 4988c2ecf20Sopenharmony_ci dev_err(sdev->dev, 4998c2ecf20Sopenharmony_ci "error: failed to ioremap PCI base 0x%x size 0x%x\n", 5008c2ecf20Sopenharmony_ci base, size); 5018c2ecf20Sopenharmony_ci return -ENODEV; 5028c2ecf20Sopenharmony_ci } 5038c2ecf20Sopenharmony_ci dev_dbg(sdev->dev, "PCI VADDR %p\n", sdev->bar[BDW_PCI_BAR]); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci /* register our IRQ */ 5068c2ecf20Sopenharmony_ci sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc); 5078c2ecf20Sopenharmony_ci if (sdev->ipc_irq < 0) 5088c2ecf20Sopenharmony_ci return sdev->ipc_irq; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq); 5118c2ecf20Sopenharmony_ci ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq, 5128c2ecf20Sopenharmony_ci bdw_irq_handler, bdw_irq_thread, 5138c2ecf20Sopenharmony_ci IRQF_SHARED, "AudioDSP", sdev); 5148c2ecf20Sopenharmony_ci if (ret < 0) { 5158c2ecf20Sopenharmony_ci dev_err(sdev->dev, "error: failed to register IRQ %d\n", 5168c2ecf20Sopenharmony_ci sdev->ipc_irq); 5178c2ecf20Sopenharmony_ci return ret; 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci /* enable the DSP SHIM */ 5218c2ecf20Sopenharmony_ci ret = bdw_set_dsp_D0(sdev); 5228c2ecf20Sopenharmony_ci if (ret < 0) { 5238c2ecf20Sopenharmony_ci dev_err(sdev->dev, "error: failed to set DSP D0\n"); 5248c2ecf20Sopenharmony_ci return ret; 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci /* DSP DMA can only access low 31 bits of host memory */ 5288c2ecf20Sopenharmony_ci ret = dma_coerce_mask_and_coherent(sdev->dev, DMA_BIT_MASK(31)); 5298c2ecf20Sopenharmony_ci if (ret < 0) { 5308c2ecf20Sopenharmony_ci dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret); 5318c2ecf20Sopenharmony_ci return ret; 5328c2ecf20Sopenharmony_ci } 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci /* set default mailbox */ 5358c2ecf20Sopenharmony_ci snd_sof_dsp_mailbox_init(sdev, MBOX_OFFSET, MBOX_SIZE, 0, 0); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci return ret; 5388c2ecf20Sopenharmony_ci} 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_cistatic void bdw_machine_select(struct snd_sof_dev *sdev) 5418c2ecf20Sopenharmony_ci{ 5428c2ecf20Sopenharmony_ci struct snd_sof_pdata *sof_pdata = sdev->pdata; 5438c2ecf20Sopenharmony_ci const struct sof_dev_desc *desc = sof_pdata->desc; 5448c2ecf20Sopenharmony_ci struct snd_soc_acpi_mach *mach; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci mach = snd_soc_acpi_find_machine(desc->machines); 5478c2ecf20Sopenharmony_ci if (!mach) { 5488c2ecf20Sopenharmony_ci dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n"); 5498c2ecf20Sopenharmony_ci return; 5508c2ecf20Sopenharmony_ci } 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci sof_pdata->tplg_filename = mach->sof_tplg_filename; 5538c2ecf20Sopenharmony_ci mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc; 5548c2ecf20Sopenharmony_ci sof_pdata->machine = mach; 5558c2ecf20Sopenharmony_ci} 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_cistatic void bdw_set_mach_params(const struct snd_soc_acpi_mach *mach, 5588c2ecf20Sopenharmony_ci struct device *dev) 5598c2ecf20Sopenharmony_ci{ 5608c2ecf20Sopenharmony_ci struct snd_soc_acpi_mach_params *mach_params; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params; 5638c2ecf20Sopenharmony_ci mach_params->platform = dev_name(dev); 5648c2ecf20Sopenharmony_ci} 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci/* Broadwell DAIs */ 5678c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver bdw_dai[] = { 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci .name = "ssp0-port", 5708c2ecf20Sopenharmony_ci .playback = { 5718c2ecf20Sopenharmony_ci .channels_min = 1, 5728c2ecf20Sopenharmony_ci .channels_max = 8, 5738c2ecf20Sopenharmony_ci }, 5748c2ecf20Sopenharmony_ci .capture = { 5758c2ecf20Sopenharmony_ci .channels_min = 1, 5768c2ecf20Sopenharmony_ci .channels_max = 8, 5778c2ecf20Sopenharmony_ci }, 5788c2ecf20Sopenharmony_ci}, 5798c2ecf20Sopenharmony_ci{ 5808c2ecf20Sopenharmony_ci .name = "ssp1-port", 5818c2ecf20Sopenharmony_ci .playback = { 5828c2ecf20Sopenharmony_ci .channels_min = 1, 5838c2ecf20Sopenharmony_ci .channels_max = 8, 5848c2ecf20Sopenharmony_ci }, 5858c2ecf20Sopenharmony_ci .capture = { 5868c2ecf20Sopenharmony_ci .channels_min = 1, 5878c2ecf20Sopenharmony_ci .channels_max = 8, 5888c2ecf20Sopenharmony_ci }, 5898c2ecf20Sopenharmony_ci}, 5908c2ecf20Sopenharmony_ci}; 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci/* broadwell ops */ 5938c2ecf20Sopenharmony_ciconst struct snd_sof_dsp_ops sof_bdw_ops = { 5948c2ecf20Sopenharmony_ci /*Device init */ 5958c2ecf20Sopenharmony_ci .probe = bdw_probe, 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci /* DSP Core Control */ 5988c2ecf20Sopenharmony_ci .run = bdw_run, 5998c2ecf20Sopenharmony_ci .reset = bdw_reset, 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci /* Register IO */ 6028c2ecf20Sopenharmony_ci .write = sof_io_write, 6038c2ecf20Sopenharmony_ci .read = sof_io_read, 6048c2ecf20Sopenharmony_ci .write64 = sof_io_write64, 6058c2ecf20Sopenharmony_ci .read64 = sof_io_read64, 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci /* Block IO */ 6088c2ecf20Sopenharmony_ci .block_read = sof_block_read, 6098c2ecf20Sopenharmony_ci .block_write = sof_block_write, 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci /* ipc */ 6128c2ecf20Sopenharmony_ci .send_msg = bdw_send_msg, 6138c2ecf20Sopenharmony_ci .fw_ready = sof_fw_ready, 6148c2ecf20Sopenharmony_ci .get_mailbox_offset = bdw_get_mailbox_offset, 6158c2ecf20Sopenharmony_ci .get_window_offset = bdw_get_window_offset, 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci .ipc_msg_data = intel_ipc_msg_data, 6188c2ecf20Sopenharmony_ci .ipc_pcm_params = intel_ipc_pcm_params, 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci /* machine driver */ 6218c2ecf20Sopenharmony_ci .machine_select = bdw_machine_select, 6228c2ecf20Sopenharmony_ci .machine_register = sof_machine_register, 6238c2ecf20Sopenharmony_ci .machine_unregister = sof_machine_unregister, 6248c2ecf20Sopenharmony_ci .set_mach_params = bdw_set_mach_params, 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci /* debug */ 6278c2ecf20Sopenharmony_ci .debug_map = bdw_debugfs, 6288c2ecf20Sopenharmony_ci .debug_map_count = ARRAY_SIZE(bdw_debugfs), 6298c2ecf20Sopenharmony_ci .dbg_dump = bdw_dump, 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci /* stream callbacks */ 6328c2ecf20Sopenharmony_ci .pcm_open = intel_pcm_open, 6338c2ecf20Sopenharmony_ci .pcm_close = intel_pcm_close, 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci /* Module loading */ 6368c2ecf20Sopenharmony_ci .load_module = snd_sof_parse_module_memcpy, 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci /*Firmware loading */ 6398c2ecf20Sopenharmony_ci .load_firmware = snd_sof_load_firmware_memcpy, 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci /* DAI drivers */ 6428c2ecf20Sopenharmony_ci .drv = bdw_dai, 6438c2ecf20Sopenharmony_ci .num_drv = ARRAY_SIZE(bdw_dai), 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci /* ALSA HW info flags */ 6468c2ecf20Sopenharmony_ci .hw_info = SNDRV_PCM_INFO_MMAP | 6478c2ecf20Sopenharmony_ci SNDRV_PCM_INFO_MMAP_VALID | 6488c2ecf20Sopenharmony_ci SNDRV_PCM_INFO_INTERLEAVED | 6498c2ecf20Sopenharmony_ci SNDRV_PCM_INFO_PAUSE | 6508c2ecf20Sopenharmony_ci SNDRV_PCM_INFO_BATCH, 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci .arch_ops = &sof_xtensa_arch_ops, 6538c2ecf20Sopenharmony_ci}; 6548c2ecf20Sopenharmony_ciEXPORT_SYMBOL_NS(sof_bdw_ops, SND_SOC_SOF_BROADWELL); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ciconst struct sof_intel_dsp_desc bdw_chip_info = { 6578c2ecf20Sopenharmony_ci .cores_num = 1, 6588c2ecf20Sopenharmony_ci .host_managed_cores_mask = 1, 6598c2ecf20Sopenharmony_ci}; 6608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_NS(bdw_chip_info, SND_SOC_SOF_BROADWELL); 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 6638c2ecf20Sopenharmony_ciMODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC); 6648c2ecf20Sopenharmony_ciMODULE_IMPORT_NS(SND_SOC_SOF_XTENSA); 665