Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
0002 //
0003 // This file is provided under a dual BSD/GPLv2 license.  When using or
0004 // redistributing this file, you may do so under either license.
0005 //
0006 // Copyright(c) 2018 Intel Corporation. All rights reserved.
0007 //
0008 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
0009 //
0010 
0011 /*
0012  * Hardware interface for audio DSP on Broadwell
0013  */
0014 
0015 #include <linux/module.h>
0016 #include <sound/sof.h>
0017 #include <sound/sof/xtensa.h>
0018 #include <sound/soc-acpi.h>
0019 #include <sound/soc-acpi-intel-match.h>
0020 #include <sound/intel-dsp-config.h>
0021 #include "../ops.h"
0022 #include "shim.h"
0023 #include "../sof-acpi-dev.h"
0024 #include "../sof-audio.h"
0025 
0026 /* BARs */
0027 #define BDW_DSP_BAR 0
0028 #define BDW_PCI_BAR 1
0029 
0030 /*
0031  * Debug
0032  */
0033 
0034 /* DSP memories for BDW */
0035 #define IRAM_OFFSET     0xA0000
0036 #define BDW_IRAM_SIZE       (10 * 32 * 1024)
0037 #define DRAM_OFFSET     0x00000
0038 #define BDW_DRAM_SIZE       (20 * 32 * 1024)
0039 #define SHIM_OFFSET     0xFB000
0040 #define SHIM_SIZE       0x100
0041 #define MBOX_OFFSET     0x9E000
0042 #define MBOX_SIZE       0x1000
0043 #define MBOX_DUMP_SIZE 0x30
0044 #define EXCEPT_OFFSET   0x800
0045 #define EXCEPT_MAX_HDR_SIZE 0x400
0046 
0047 /* DSP peripherals */
0048 #define DMAC0_OFFSET    0xFE000
0049 #define DMAC1_OFFSET    0xFF000
0050 #define DMAC_SIZE       0x420
0051 #define SSP0_OFFSET     0xFC000
0052 #define SSP1_OFFSET     0xFD000
0053 #define SSP_SIZE    0x100
0054 
0055 #define BDW_STACK_DUMP_SIZE 32
0056 
0057 #define BDW_PANIC_OFFSET(x) ((x) & 0xFFFF)
0058 
0059 static const struct snd_sof_debugfs_map bdw_debugfs[] = {
0060     {"dmac0", BDW_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
0061      SOF_DEBUGFS_ACCESS_ALWAYS},
0062     {"dmac1", BDW_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,
0063      SOF_DEBUGFS_ACCESS_ALWAYS},
0064     {"ssp0", BDW_DSP_BAR, SSP0_OFFSET, SSP_SIZE,
0065      SOF_DEBUGFS_ACCESS_ALWAYS},
0066     {"ssp1", BDW_DSP_BAR, SSP1_OFFSET, SSP_SIZE,
0067      SOF_DEBUGFS_ACCESS_ALWAYS},
0068     {"iram", BDW_DSP_BAR, IRAM_OFFSET, BDW_IRAM_SIZE,
0069      SOF_DEBUGFS_ACCESS_D0_ONLY},
0070     {"dram", BDW_DSP_BAR, DRAM_OFFSET, BDW_DRAM_SIZE,
0071      SOF_DEBUGFS_ACCESS_D0_ONLY},
0072     {"shim", BDW_DSP_BAR, SHIM_OFFSET, SHIM_SIZE,
0073      SOF_DEBUGFS_ACCESS_ALWAYS},
0074 };
0075 
0076 static void bdw_host_done(struct snd_sof_dev *sdev);
0077 static void bdw_dsp_done(struct snd_sof_dev *sdev);
0078 
0079 /*
0080  * DSP Control.
0081  */
0082 
0083 static int bdw_run(struct snd_sof_dev *sdev)
0084 {
0085     /* set opportunistic mode on engine 0,1 for all channels */
0086     snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_HMDC,
0087                 SHIM_HMDC_HDDA_E0_ALLCH |
0088                 SHIM_HMDC_HDDA_E1_ALLCH, 0);
0089 
0090     /* set DSP to RUN */
0091     snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
0092                      SHIM_CSR_STALL, 0x0);
0093 
0094     /* return init core mask */
0095     return 1;
0096 }
0097 
0098 static int bdw_reset(struct snd_sof_dev *sdev)
0099 {
0100     /* put DSP into reset and stall */
0101     snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
0102                      SHIM_CSR_RST | SHIM_CSR_STALL,
0103                      SHIM_CSR_RST | SHIM_CSR_STALL);
0104 
0105     /* keep in reset for 10ms */
0106     mdelay(10);
0107 
0108     /* take DSP out of reset and keep stalled for FW loading */
0109     snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
0110                      SHIM_CSR_RST | SHIM_CSR_STALL,
0111                      SHIM_CSR_STALL);
0112 
0113     return 0;
0114 }
0115 
0116 static int bdw_set_dsp_D0(struct snd_sof_dev *sdev)
0117 {
0118     int tries = 10;
0119     u32 reg;
0120 
0121     /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
0122     snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,
0123                      PCI_VDRTCL2_DCLCGE |
0124                      PCI_VDRTCL2_DTCGE, 0);
0125 
0126     /* Disable D3PG (VDRTCTL0.D3PGD = 1) */
0127     snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL0,
0128                      PCI_VDRTCL0_D3PGD, PCI_VDRTCL0_D3PGD);
0129 
0130     /* Set D0 state */
0131     snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_PMCS,
0132                      PCI_PMCS_PS_MASK, 0);
0133 
0134     /* check that ADSP shim is enabled */
0135     while (tries--) {
0136         reg = readl(sdev->bar[BDW_PCI_BAR] + PCI_PMCS)
0137             & PCI_PMCS_PS_MASK;
0138         if (reg == 0)
0139             goto finish;
0140 
0141         msleep(20);
0142     }
0143 
0144     return -ENODEV;
0145 
0146 finish:
0147     /*
0148      * select SSP1 19.2MHz base clock, SSP clock 0,
0149      * turn off Low Power Clock
0150      */
0151     snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
0152                      SHIM_CSR_S1IOCS | SHIM_CSR_SBCS1 |
0153                      SHIM_CSR_LPCS, 0x0);
0154 
0155     /* stall DSP core, set clk to 192/96Mhz */
0156     snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,
0157                      SHIM_CSR, SHIM_CSR_STALL |
0158                      SHIM_CSR_DCS_MASK,
0159                      SHIM_CSR_STALL |
0160                      SHIM_CSR_DCS(4));
0161 
0162     /* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */
0163     snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CLKCTL,
0164                      SHIM_CLKCTL_MASK |
0165                      SHIM_CLKCTL_DCPLCG |
0166                      SHIM_CLKCTL_SCOE0,
0167                      SHIM_CLKCTL_MASK |
0168                      SHIM_CLKCTL_DCPLCG |
0169                      SHIM_CLKCTL_SCOE0);
0170 
0171     /* Stall and reset core, set CSR */
0172     bdw_reset(sdev);
0173 
0174     /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
0175     snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,
0176                      PCI_VDRTCL2_DCLCGE |
0177                      PCI_VDRTCL2_DTCGE,
0178                      PCI_VDRTCL2_DCLCGE |
0179                      PCI_VDRTCL2_DTCGE);
0180 
0181     usleep_range(50, 55);
0182 
0183     /* switch on audio PLL */
0184     snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,
0185                      PCI_VDRTCL2_APLLSE_MASK, 0);
0186 
0187     /*
0188      * set default power gating control, enable power gating control for
0189      * all blocks. that is, can't be accessed, please enable each block
0190      * before accessing.
0191      */
0192     snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL0,
0193                      0xfffffffC, 0x0);
0194 
0195     /* disable DMA finish function for SSP0 & SSP1 */
0196     snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,  SHIM_CSR2,
0197                      SHIM_CSR2_SDFD_SSP1,
0198                      SHIM_CSR2_SDFD_SSP1);
0199 
0200     /* set on-demond mode on engine 0,1 for all channels */
0201     snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_HMDC,
0202                 SHIM_HMDC_HDDA_E0_ALLCH |
0203                 SHIM_HMDC_HDDA_E1_ALLCH,
0204                 SHIM_HMDC_HDDA_E0_ALLCH |
0205                 SHIM_HMDC_HDDA_E1_ALLCH);
0206 
0207     /* Enable Interrupt from both sides */
0208     snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_IMRX,
0209                 (SHIM_IMRX_BUSY | SHIM_IMRX_DONE), 0x0);
0210     snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_IMRD,
0211                 (SHIM_IMRD_DONE | SHIM_IMRD_BUSY |
0212                 SHIM_IMRD_SSP0 | SHIM_IMRD_DMAC), 0x0);
0213 
0214     /* clear IPC registers */
0215     snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCX, 0x0);
0216     snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCD, 0x0);
0217     snd_sof_dsp_write(sdev, BDW_DSP_BAR, 0x80, 0x6);
0218     snd_sof_dsp_write(sdev, BDW_DSP_BAR, 0xe0, 0x300a);
0219 
0220     return 0;
0221 }
0222 
0223 static void bdw_get_registers(struct snd_sof_dev *sdev,
0224                   struct sof_ipc_dsp_oops_xtensa *xoops,
0225                   struct sof_ipc_panic_info *panic_info,
0226                   u32 *stack, size_t stack_words)
0227 {
0228     u32 offset = sdev->dsp_oops_offset;
0229 
0230     /* first read registers */
0231     sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
0232 
0233     /* note: variable AR register array is not read */
0234 
0235     /* then get panic info */
0236     if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
0237         dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
0238             xoops->arch_hdr.totalsize);
0239         return;
0240     }
0241     offset += xoops->arch_hdr.totalsize;
0242     sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
0243 
0244     /* then get the stack */
0245     offset += sizeof(*panic_info);
0246     sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
0247 }
0248 
0249 static void bdw_dump(struct snd_sof_dev *sdev, u32 flags)
0250 {
0251     struct sof_ipc_dsp_oops_xtensa xoops;
0252     struct sof_ipc_panic_info panic_info;
0253     u32 stack[BDW_STACK_DUMP_SIZE];
0254     u32 status, panic, imrx, imrd;
0255 
0256     /* now try generic SOF status messages */
0257     status = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD);
0258     panic = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCX);
0259     bdw_get_registers(sdev, &xoops, &panic_info, stack,
0260               BDW_STACK_DUMP_SIZE);
0261     sof_print_oops_and_stack(sdev, KERN_ERR, status, panic, &xoops,
0262                  &panic_info, stack, BDW_STACK_DUMP_SIZE);
0263 
0264     /* provide some context for firmware debug */
0265     imrx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRX);
0266     imrd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRD);
0267     dev_err(sdev->dev,
0268         "error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n",
0269         (panic & SHIM_IPCX_BUSY) ? "yes" : "no",
0270         (panic & SHIM_IPCX_DONE) ? "yes" : "no", panic);
0271     dev_err(sdev->dev,
0272         "error: mask host: pending %s complete %s raw 0x%8.8x\n",
0273         (imrx & SHIM_IMRX_BUSY) ? "yes" : "no",
0274         (imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx);
0275     dev_err(sdev->dev,
0276         "error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n",
0277         (status & SHIM_IPCD_BUSY) ? "yes" : "no",
0278         (status & SHIM_IPCD_DONE) ? "yes" : "no", status);
0279     dev_err(sdev->dev,
0280         "error: mask DSP: pending %s complete %s raw 0x%8.8x\n",
0281         (imrd & SHIM_IMRD_BUSY) ? "yes" : "no",
0282         (imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd);
0283 }
0284 
0285 /*
0286  * IPC Doorbell IRQ handler and thread.
0287  */
0288 
0289 static irqreturn_t bdw_irq_handler(int irq, void *context)
0290 {
0291     struct snd_sof_dev *sdev = context;
0292     u32 isr;
0293     int ret = IRQ_NONE;
0294 
0295     /* Interrupt arrived, check src */
0296     isr = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_ISRX);
0297     if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY))
0298         ret = IRQ_WAKE_THREAD;
0299 
0300     return ret;
0301 }
0302 
0303 static irqreturn_t bdw_irq_thread(int irq, void *context)
0304 {
0305     struct snd_sof_dev *sdev = context;
0306     u32 ipcx, ipcd, imrx;
0307 
0308     imrx = snd_sof_dsp_read64(sdev, BDW_DSP_BAR, SHIM_IMRX);
0309     ipcx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCX);
0310 
0311     /* reply message from DSP */
0312     if (ipcx & SHIM_IPCX_DONE &&
0313         !(imrx & SHIM_IMRX_DONE)) {
0314         /* Mask Done interrupt before return */
0315         snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,
0316                          SHIM_IMRX, SHIM_IMRX_DONE,
0317                          SHIM_IMRX_DONE);
0318 
0319         spin_lock_irq(&sdev->ipc_lock);
0320 
0321         /*
0322          * handle immediate reply from DSP core. If the msg is
0323          * found, set done bit in cmd_done which is called at the
0324          * end of message processing function, else set it here
0325          * because the done bit can't be set in cmd_done function
0326          * which is triggered by msg
0327          */
0328         snd_sof_ipc_process_reply(sdev, ipcx);
0329 
0330         bdw_dsp_done(sdev);
0331 
0332         spin_unlock_irq(&sdev->ipc_lock);
0333     }
0334 
0335     ipcd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD);
0336 
0337     /* new message from DSP */
0338     if (ipcd & SHIM_IPCD_BUSY &&
0339         !(imrx & SHIM_IMRX_BUSY)) {
0340         /* Mask Busy interrupt before return */
0341         snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,
0342                          SHIM_IMRX, SHIM_IMRX_BUSY,
0343                          SHIM_IMRX_BUSY);
0344 
0345         /* Handle messages from DSP Core */
0346         if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
0347             snd_sof_dsp_panic(sdev, BDW_PANIC_OFFSET(ipcx) + MBOX_OFFSET,
0348                       true);
0349         } else {
0350             snd_sof_ipc_msgs_rx(sdev);
0351         }
0352 
0353         bdw_host_done(sdev);
0354     }
0355 
0356     return IRQ_HANDLED;
0357 }
0358 
0359 /*
0360  * IPC Mailbox IO
0361  */
0362 
0363 static int bdw_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
0364 {
0365     /* send the message */
0366     sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
0367               msg->msg_size);
0368     snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCX, SHIM_IPCX_BUSY);
0369 
0370     return 0;
0371 }
0372 
0373 static int bdw_get_mailbox_offset(struct snd_sof_dev *sdev)
0374 {
0375     return MBOX_OFFSET;
0376 }
0377 
0378 static int bdw_get_window_offset(struct snd_sof_dev *sdev, u32 id)
0379 {
0380     return MBOX_OFFSET;
0381 }
0382 
0383 static void bdw_host_done(struct snd_sof_dev *sdev)
0384 {
0385     /* clear BUSY bit and set DONE bit - accept new messages */
0386     snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCD,
0387                      SHIM_IPCD_BUSY | SHIM_IPCD_DONE,
0388                      SHIM_IPCD_DONE);
0389 
0390     /* unmask busy interrupt */
0391     snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX,
0392                      SHIM_IMRX_BUSY, 0);
0393 }
0394 
0395 static void bdw_dsp_done(struct snd_sof_dev *sdev)
0396 {
0397     /* clear DONE bit - tell DSP we have completed */
0398     snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCX,
0399                      SHIM_IPCX_DONE, 0);
0400 
0401     /* unmask Done interrupt */
0402     snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX,
0403                      SHIM_IMRX_DONE, 0);
0404 }
0405 
0406 /*
0407  * Probe and remove.
0408  */
0409 static int bdw_probe(struct snd_sof_dev *sdev)
0410 {
0411     struct snd_sof_pdata *pdata = sdev->pdata;
0412     const struct sof_dev_desc *desc = pdata->desc;
0413     struct platform_device *pdev =
0414         container_of(sdev->dev, struct platform_device, dev);
0415     const struct sof_intel_dsp_desc *chip;
0416     struct resource *mmio;
0417     u32 base, size;
0418     int ret;
0419 
0420     chip = get_chip_info(sdev->pdata);
0421     if (!chip) {
0422         dev_err(sdev->dev, "error: no such device supported\n");
0423         return -EIO;
0424     }
0425 
0426     sdev->num_cores = chip->cores_num;
0427 
0428     /* LPE base */
0429     mmio = platform_get_resource(pdev, IORESOURCE_MEM,
0430                      desc->resindex_lpe_base);
0431     if (mmio) {
0432         base = mmio->start;
0433         size = resource_size(mmio);
0434     } else {
0435         dev_err(sdev->dev, "error: failed to get LPE base at idx %d\n",
0436             desc->resindex_lpe_base);
0437         return -EINVAL;
0438     }
0439 
0440     dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
0441     sdev->bar[BDW_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
0442     if (!sdev->bar[BDW_DSP_BAR]) {
0443         dev_err(sdev->dev,
0444             "error: failed to ioremap LPE base 0x%x size 0x%x\n",
0445             base, size);
0446         return -ENODEV;
0447     }
0448     dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BDW_DSP_BAR]);
0449 
0450     /* TODO: add offsets */
0451     sdev->mmio_bar = BDW_DSP_BAR;
0452     sdev->mailbox_bar = BDW_DSP_BAR;
0453     sdev->dsp_oops_offset = MBOX_OFFSET;
0454 
0455     /* PCI base */
0456     mmio = platform_get_resource(pdev, IORESOURCE_MEM,
0457                      desc->resindex_pcicfg_base);
0458     if (mmio) {
0459         base = mmio->start;
0460         size = resource_size(mmio);
0461     } else {
0462         dev_err(sdev->dev, "error: failed to get PCI base at idx %d\n",
0463             desc->resindex_pcicfg_base);
0464         return -ENODEV;
0465     }
0466 
0467     dev_dbg(sdev->dev, "PCI base at 0x%x size 0x%x", base, size);
0468     sdev->bar[BDW_PCI_BAR] = devm_ioremap(sdev->dev, base, size);
0469     if (!sdev->bar[BDW_PCI_BAR]) {
0470         dev_err(sdev->dev,
0471             "error: failed to ioremap PCI base 0x%x size 0x%x\n",
0472             base, size);
0473         return -ENODEV;
0474     }
0475     dev_dbg(sdev->dev, "PCI VADDR %p\n", sdev->bar[BDW_PCI_BAR]);
0476 
0477     /* register our IRQ */
0478     sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc);
0479     if (sdev->ipc_irq < 0)
0480         return sdev->ipc_irq;
0481 
0482     dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
0483     ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
0484                     bdw_irq_handler, bdw_irq_thread,
0485                     IRQF_SHARED, "AudioDSP", sdev);
0486     if (ret < 0) {
0487         dev_err(sdev->dev, "error: failed to register IRQ %d\n",
0488             sdev->ipc_irq);
0489         return ret;
0490     }
0491 
0492     /* enable the DSP SHIM */
0493     ret = bdw_set_dsp_D0(sdev);
0494     if (ret < 0) {
0495         dev_err(sdev->dev, "error: failed to set DSP D0\n");
0496         return ret;
0497     }
0498 
0499     /* DSP DMA can only access low 31 bits of host memory */
0500     ret = dma_coerce_mask_and_coherent(sdev->dev, DMA_BIT_MASK(31));
0501     if (ret < 0) {
0502         dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
0503         return ret;
0504     }
0505 
0506     /* set default mailbox offset for FW ready message */
0507     sdev->dsp_box.offset = MBOX_OFFSET;
0508 
0509     return ret;
0510 }
0511 
0512 static struct snd_soc_acpi_mach *bdw_machine_select(struct snd_sof_dev *sdev)
0513 {
0514     struct snd_sof_pdata *sof_pdata = sdev->pdata;
0515     const struct sof_dev_desc *desc = sof_pdata->desc;
0516     struct snd_soc_acpi_mach *mach;
0517 
0518     mach = snd_soc_acpi_find_machine(desc->machines);
0519     if (!mach) {
0520         dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
0521         return NULL;
0522     }
0523 
0524     sof_pdata->tplg_filename = mach->sof_tplg_filename;
0525     mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc;
0526 
0527     return mach;
0528 }
0529 
0530 static void bdw_set_mach_params(struct snd_soc_acpi_mach *mach,
0531                 struct snd_sof_dev *sdev)
0532 {
0533     struct snd_sof_pdata *pdata = sdev->pdata;
0534     const struct sof_dev_desc *desc = pdata->desc;
0535     struct snd_soc_acpi_mach_params *mach_params;
0536 
0537     mach_params = &mach->mach_params;
0538     mach_params->platform = dev_name(sdev->dev);
0539     mach_params->num_dai_drivers = desc->ops->num_drv;
0540     mach_params->dai_drivers = desc->ops->drv;
0541 }
0542 
0543 /* Broadwell DAIs */
0544 static struct snd_soc_dai_driver bdw_dai[] = {
0545 {
0546     .name = "ssp0-port",
0547     .playback = {
0548         .channels_min = 1,
0549         .channels_max = 8,
0550     },
0551     .capture = {
0552         .channels_min = 1,
0553         .channels_max = 8,
0554     },
0555 },
0556 {
0557     .name = "ssp1-port",
0558     .playback = {
0559         .channels_min = 1,
0560         .channels_max = 8,
0561     },
0562     .capture = {
0563         .channels_min = 1,
0564         .channels_max = 8,
0565     },
0566 },
0567 };
0568 
0569 /* broadwell ops */
0570 static struct snd_sof_dsp_ops sof_bdw_ops = {
0571     /*Device init */
0572     .probe          = bdw_probe,
0573 
0574     /* DSP Core Control */
0575     .run            = bdw_run,
0576     .reset          = bdw_reset,
0577 
0578     /* Register IO */
0579     .write      = sof_io_write,
0580     .read       = sof_io_read,
0581     .write64    = sof_io_write64,
0582     .read64     = sof_io_read64,
0583 
0584     /* Block IO */
0585     .block_read = sof_block_read,
0586     .block_write    = sof_block_write,
0587 
0588     /* Mailbox IO */
0589     .mailbox_read   = sof_mailbox_read,
0590     .mailbox_write  = sof_mailbox_write,
0591 
0592     /* ipc */
0593     .send_msg   = bdw_send_msg,
0594     .get_mailbox_offset = bdw_get_mailbox_offset,
0595     .get_window_offset = bdw_get_window_offset,
0596 
0597     .ipc_msg_data   = sof_ipc_msg_data,
0598     .set_stream_data_offset = sof_set_stream_data_offset,
0599 
0600     /* machine driver */
0601     .machine_select = bdw_machine_select,
0602     .machine_register = sof_machine_register,
0603     .machine_unregister = sof_machine_unregister,
0604     .set_mach_params = bdw_set_mach_params,
0605 
0606     /* debug */
0607     .debug_map  = bdw_debugfs,
0608     .debug_map_count    = ARRAY_SIZE(bdw_debugfs),
0609     .dbg_dump   = bdw_dump,
0610     .debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
0611 
0612     /* stream callbacks */
0613     .pcm_open   = sof_stream_pcm_open,
0614     .pcm_close  = sof_stream_pcm_close,
0615 
0616     /*Firmware loading */
0617     .load_firmware  = snd_sof_load_firmware_memcpy,
0618 
0619     /* DAI drivers */
0620     .drv = bdw_dai,
0621     .num_drv = ARRAY_SIZE(bdw_dai),
0622 
0623     /* ALSA HW info flags */
0624     .hw_info =  SNDRV_PCM_INFO_MMAP |
0625             SNDRV_PCM_INFO_MMAP_VALID |
0626             SNDRV_PCM_INFO_INTERLEAVED |
0627             SNDRV_PCM_INFO_PAUSE |
0628             SNDRV_PCM_INFO_BATCH,
0629 
0630     .dsp_arch_ops = &sof_xtensa_arch_ops,
0631 };
0632 
0633 static const struct sof_intel_dsp_desc bdw_chip_info = {
0634     .cores_num = 1,
0635     .host_managed_cores_mask = 1,
0636     .hw_ip_version = SOF_INTEL_BROADWELL,
0637 };
0638 
0639 static const struct sof_dev_desc sof_acpi_broadwell_desc = {
0640     .machines = snd_soc_acpi_intel_broadwell_machines,
0641     .resindex_lpe_base = 0,
0642     .resindex_pcicfg_base = 1,
0643     .resindex_imr_base = -1,
0644     .irqindex_host_ipc = 0,
0645     .chip_info = &bdw_chip_info,
0646     .ipc_supported_mask = BIT(SOF_IPC),
0647     .ipc_default = SOF_IPC,
0648     .default_fw_path = {
0649         [SOF_IPC] = "intel/sof",
0650     },
0651     .default_tplg_path = {
0652         [SOF_IPC] = "intel/sof-tplg",
0653     },
0654     .default_fw_filename = {
0655         [SOF_IPC] = "sof-bdw.ri",
0656     },
0657     .nocodec_tplg_filename = "sof-bdw-nocodec.tplg",
0658     .ops = &sof_bdw_ops,
0659 };
0660 
0661 static const struct acpi_device_id sof_broadwell_match[] = {
0662     { "INT3438", (unsigned long)&sof_acpi_broadwell_desc },
0663     { }
0664 };
0665 MODULE_DEVICE_TABLE(acpi, sof_broadwell_match);
0666 
0667 static int sof_broadwell_probe(struct platform_device *pdev)
0668 {
0669     struct device *dev = &pdev->dev;
0670     const struct acpi_device_id *id;
0671     const struct sof_dev_desc *desc;
0672     int ret;
0673 
0674     id = acpi_match_device(dev->driver->acpi_match_table, dev);
0675     if (!id)
0676         return -ENODEV;
0677 
0678     ret = snd_intel_acpi_dsp_driver_probe(dev, id->id);
0679     if (ret != SND_INTEL_DSP_DRIVER_ANY && ret != SND_INTEL_DSP_DRIVER_SOF) {
0680         dev_dbg(dev, "SOF ACPI driver not selected, aborting probe\n");
0681         return -ENODEV;
0682     }
0683 
0684     desc = (const struct sof_dev_desc *)id->driver_data;
0685     return sof_acpi_probe(pdev, desc);
0686 }
0687 
0688 /* acpi_driver definition */
0689 static struct platform_driver snd_sof_acpi_intel_bdw_driver = {
0690     .probe = sof_broadwell_probe,
0691     .remove = sof_acpi_remove,
0692     .driver = {
0693         .name = "sof-audio-acpi-intel-bdw",
0694         .pm = &sof_acpi_pm,
0695         .acpi_match_table = sof_broadwell_match,
0696     },
0697 };
0698 module_platform_driver(snd_sof_acpi_intel_bdw_driver);
0699 
0700 MODULE_LICENSE("Dual BSD/GPL");
0701 MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC);
0702 MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
0703 MODULE_IMPORT_NS(SND_SOC_SOF_ACPI_DEV);