linux/sound/soc/sof/intel/bdw.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
   2//
   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.
   5//
   6// Copyright(c) 2018 Intel Corporation. All rights reserved.
   7//
   8// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
   9//
  10
  11/*
  12 * Hardware interface for audio DSP on Broadwell
  13 */
  14
  15#include <linux/module.h>
  16#include <sound/sof.h>
  17#include <sound/sof/xtensa.h>
  18#include <sound/soc-acpi.h>
  19#include <sound/soc-acpi-intel-match.h>
  20#include <sound/intel-dsp-config.h>
  21#include "../ops.h"
  22#include "shim.h"
  23#include "../sof-acpi-dev.h"
  24#include "../sof-audio.h"
  25
  26/* BARs */
  27#define BDW_DSP_BAR 0
  28#define BDW_PCI_BAR 1
  29
  30/*
  31 * Debug
  32 */
  33
  34/* DSP memories for BDW */
  35#define IRAM_OFFSET     0xA0000
  36#define BDW_IRAM_SIZE       (10 * 32 * 1024)
  37#define DRAM_OFFSET     0x00000
  38#define BDW_DRAM_SIZE       (20 * 32 * 1024)
  39#define SHIM_OFFSET     0xFB000
  40#define SHIM_SIZE       0x100
  41#define MBOX_OFFSET     0x9E000
  42#define MBOX_SIZE       0x1000
  43#define MBOX_DUMP_SIZE 0x30
  44#define EXCEPT_OFFSET   0x800
  45#define EXCEPT_MAX_HDR_SIZE     0x400
  46
  47/* DSP peripherals */
  48#define DMAC0_OFFSET    0xFE000
  49#define DMAC1_OFFSET    0xFF000
  50#define DMAC_SIZE       0x420
  51#define SSP0_OFFSET     0xFC000
  52#define SSP1_OFFSET     0xFD000
  53#define SSP_SIZE        0x100
  54
  55#define BDW_STACK_DUMP_SIZE     32
  56
  57#define BDW_PANIC_OFFSET(x)     ((x) & 0xFFFF)
  58
  59static const struct snd_sof_debugfs_map bdw_debugfs[] = {
  60        {"dmac0", BDW_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
  61         SOF_DEBUGFS_ACCESS_ALWAYS},
  62        {"dmac1", BDW_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,
  63         SOF_DEBUGFS_ACCESS_ALWAYS},
  64        {"ssp0", BDW_DSP_BAR, SSP0_OFFSET, SSP_SIZE,
  65         SOF_DEBUGFS_ACCESS_ALWAYS},
  66        {"ssp1", BDW_DSP_BAR, SSP1_OFFSET, SSP_SIZE,
  67         SOF_DEBUGFS_ACCESS_ALWAYS},
  68        {"iram", BDW_DSP_BAR, IRAM_OFFSET, BDW_IRAM_SIZE,
  69         SOF_DEBUGFS_ACCESS_D0_ONLY},
  70        {"dram", BDW_DSP_BAR, DRAM_OFFSET, BDW_DRAM_SIZE,
  71         SOF_DEBUGFS_ACCESS_D0_ONLY},
  72        {"shim", BDW_DSP_BAR, SHIM_OFFSET, SHIM_SIZE,
  73         SOF_DEBUGFS_ACCESS_ALWAYS},
  74};
  75
  76static void bdw_host_done(struct snd_sof_dev *sdev);
  77static void bdw_dsp_done(struct snd_sof_dev *sdev);
  78static void bdw_get_reply(struct snd_sof_dev *sdev);
  79
  80/*
  81 * DSP Control.
  82 */
  83
  84static int bdw_run(struct snd_sof_dev *sdev)
  85{
  86        /* set opportunistic mode on engine 0,1 for all channels */
  87        snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_HMDC,
  88                                SHIM_HMDC_HDDA_E0_ALLCH |
  89                                SHIM_HMDC_HDDA_E1_ALLCH, 0);
  90
  91        /* set DSP to RUN */
  92        snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
  93                                         SHIM_CSR_STALL, 0x0);
  94
  95        /* return init core mask */
  96        return 1;
  97}
  98
  99static int bdw_reset(struct snd_sof_dev *sdev)
 100{
 101        /* put DSP into reset and stall */
 102        snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
 103                                         SHIM_CSR_RST | SHIM_CSR_STALL,
 104                                         SHIM_CSR_RST | SHIM_CSR_STALL);
 105
 106        /* keep in reset for 10ms */
 107        mdelay(10);
 108
 109        /* take DSP out of reset and keep stalled for FW loading */
 110        snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
 111                                         SHIM_CSR_RST | SHIM_CSR_STALL,
 112                                         SHIM_CSR_STALL);
 113
 114        return 0;
 115}
 116
 117static int bdw_set_dsp_D0(struct snd_sof_dev *sdev)
 118{
 119        int tries = 10;
 120        u32 reg;
 121
 122        /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
 123        snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,
 124                                         PCI_VDRTCL2_DCLCGE |
 125                                         PCI_VDRTCL2_DTCGE, 0);
 126
 127        /* Disable D3PG (VDRTCTL0.D3PGD = 1) */
 128        snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL0,
 129                                         PCI_VDRTCL0_D3PGD, PCI_VDRTCL0_D3PGD);
 130
 131        /* Set D0 state */
 132        snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_PMCS,
 133                                         PCI_PMCS_PS_MASK, 0);
 134
 135        /* check that ADSP shim is enabled */
 136        while (tries--) {
 137                reg = readl(sdev->bar[BDW_PCI_BAR] + PCI_PMCS)
 138                        & PCI_PMCS_PS_MASK;
 139                if (reg == 0)
 140                        goto finish;
 141
 142                msleep(20);
 143        }
 144
 145        return -ENODEV;
 146
 147finish:
 148        /*
 149         * select SSP1 19.2MHz base clock, SSP clock 0,
 150         * turn off Low Power Clock
 151         */
 152        snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
 153                                         SHIM_CSR_S1IOCS | SHIM_CSR_SBCS1 |
 154                                         SHIM_CSR_LPCS, 0x0);
 155
 156        /* stall DSP core, set clk to 192/96Mhz */
 157        snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,
 158                                         SHIM_CSR, SHIM_CSR_STALL |
 159                                         SHIM_CSR_DCS_MASK,
 160                                         SHIM_CSR_STALL |
 161                                         SHIM_CSR_DCS(4));
 162
 163        /* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */
 164        snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CLKCTL,
 165                                         SHIM_CLKCTL_MASK |
 166                                         SHIM_CLKCTL_DCPLCG |
 167                                         SHIM_CLKCTL_SCOE0,
 168                                         SHIM_CLKCTL_MASK |
 169                                         SHIM_CLKCTL_DCPLCG |
 170                                         SHIM_CLKCTL_SCOE0);
 171
 172        /* Stall and reset core, set CSR */
 173        bdw_reset(sdev);
 174
 175        /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
 176        snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,
 177                                         PCI_VDRTCL2_DCLCGE |
 178                                         PCI_VDRTCL2_DTCGE,
 179                                         PCI_VDRTCL2_DCLCGE |
 180                                         PCI_VDRTCL2_DTCGE);
 181
 182        usleep_range(50, 55);
 183
 184        /* switch on audio PLL */
 185        snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,
 186                                         PCI_VDRTCL2_APLLSE_MASK, 0);
 187
 188        /*
 189         * set default power gating control, enable power gating control for
 190         * all blocks. that is, can't be accessed, please enable each block
 191         * before accessing.
 192         */
 193        snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL0,
 194                                         0xfffffffC, 0x0);
 195
 196        /* disable DMA finish function for SSP0 & SSP1 */
 197        snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,  SHIM_CSR2,
 198                                         SHIM_CSR2_SDFD_SSP1,
 199                                         SHIM_CSR2_SDFD_SSP1);
 200
 201        /* set on-demond mode on engine 0,1 for all channels */
 202        snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_HMDC,
 203                                SHIM_HMDC_HDDA_E0_ALLCH |
 204                                SHIM_HMDC_HDDA_E1_ALLCH,
 205                                SHIM_HMDC_HDDA_E0_ALLCH |
 206                                SHIM_HMDC_HDDA_E1_ALLCH);
 207
 208        /* Enable Interrupt from both sides */
 209        snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_IMRX,
 210                                (SHIM_IMRX_BUSY | SHIM_IMRX_DONE), 0x0);
 211        snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_IMRD,
 212                                (SHIM_IMRD_DONE | SHIM_IMRD_BUSY |
 213                                SHIM_IMRD_SSP0 | SHIM_IMRD_DMAC), 0x0);
 214
 215        /* clear IPC registers */
 216        snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCX, 0x0);
 217        snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCD, 0x0);
 218        snd_sof_dsp_write(sdev, BDW_DSP_BAR, 0x80, 0x6);
 219        snd_sof_dsp_write(sdev, BDW_DSP_BAR, 0xe0, 0x300a);
 220
 221        return 0;
 222}
 223
 224static void bdw_get_registers(struct snd_sof_dev *sdev,
 225                              struct sof_ipc_dsp_oops_xtensa *xoops,
 226                              struct sof_ipc_panic_info *panic_info,
 227                              u32 *stack, size_t stack_words)
 228{
 229        u32 offset = sdev->dsp_oops_offset;
 230
 231        /* first read registers */
 232        sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
 233
 234        /* note: variable AR register array is not read */
 235
 236        /* then get panic info */
 237        if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
 238                dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
 239                        xoops->arch_hdr.totalsize);
 240                return;
 241        }
 242        offset += xoops->arch_hdr.totalsize;
 243        sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
 244
 245        /* then get the stack */
 246        offset += sizeof(*panic_info);
 247        sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
 248}
 249
 250static void bdw_dump(struct snd_sof_dev *sdev, u32 flags)
 251{
 252        struct sof_ipc_dsp_oops_xtensa xoops;
 253        struct sof_ipc_panic_info panic_info;
 254        u32 stack[BDW_STACK_DUMP_SIZE];
 255        u32 status, panic, imrx, imrd;
 256
 257        /* now try generic SOF status messages */
 258        status = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD);
 259        panic = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCX);
 260        bdw_get_registers(sdev, &xoops, &panic_info, stack,
 261                          BDW_STACK_DUMP_SIZE);
 262        snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack,
 263                           BDW_STACK_DUMP_SIZE);
 264
 265        /* provide some context for firmware debug */
 266        imrx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRX);
 267        imrd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRD);
 268        dev_err(sdev->dev,
 269                "error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n",
 270                (panic & SHIM_IPCX_BUSY) ? "yes" : "no",
 271                (panic & SHIM_IPCX_DONE) ? "yes" : "no", panic);
 272        dev_err(sdev->dev,
 273                "error: mask host: pending %s complete %s raw 0x%8.8x\n",
 274                (imrx & SHIM_IMRX_BUSY) ? "yes" : "no",
 275                (imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx);
 276        dev_err(sdev->dev,
 277                "error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n",
 278                (status & SHIM_IPCD_BUSY) ? "yes" : "no",
 279                (status & SHIM_IPCD_DONE) ? "yes" : "no", status);
 280        dev_err(sdev->dev,
 281                "error: mask DSP: pending %s complete %s raw 0x%8.8x\n",
 282                (imrd & SHIM_IMRD_BUSY) ? "yes" : "no",
 283                (imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd);
 284}
 285
 286/*
 287 * IPC Doorbell IRQ handler and thread.
 288 */
 289
 290static irqreturn_t bdw_irq_handler(int irq, void *context)
 291{
 292        struct snd_sof_dev *sdev = context;
 293        u32 isr;
 294        int ret = IRQ_NONE;
 295
 296        /* Interrupt arrived, check src */
 297        isr = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_ISRX);
 298        if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY))
 299                ret = IRQ_WAKE_THREAD;
 300
 301        return ret;
 302}
 303
 304static irqreturn_t bdw_irq_thread(int irq, void *context)
 305{
 306        struct snd_sof_dev *sdev = context;
 307        u32 ipcx, ipcd, imrx;
 308
 309        imrx = snd_sof_dsp_read64(sdev, BDW_DSP_BAR, SHIM_IMRX);
 310        ipcx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCX);
 311
 312        /* reply message from DSP */
 313        if (ipcx & SHIM_IPCX_DONE &&
 314            !(imrx & SHIM_IMRX_DONE)) {
 315                /* Mask Done interrupt before return */
 316                snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,
 317                                                 SHIM_IMRX, SHIM_IMRX_DONE,
 318                                                 SHIM_IMRX_DONE);
 319
 320                spin_lock_irq(&sdev->ipc_lock);
 321
 322                /*
 323                 * handle immediate reply from DSP core. If the msg is
 324                 * found, set done bit in cmd_done which is called at the
 325                 * end of message processing function, else set it here
 326                 * because the done bit can't be set in cmd_done function
 327                 * which is triggered by msg
 328                 */
 329                bdw_get_reply(sdev);
 330                snd_sof_ipc_reply(sdev, ipcx);
 331
 332                bdw_dsp_done(sdev);
 333
 334                spin_unlock_irq(&sdev->ipc_lock);
 335        }
 336
 337        ipcd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD);
 338
 339        /* new message from DSP */
 340        if (ipcd & SHIM_IPCD_BUSY &&
 341            !(imrx & SHIM_IMRX_BUSY)) {
 342                /* Mask Busy interrupt before return */
 343                snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,
 344                                                 SHIM_IMRX, SHIM_IMRX_BUSY,
 345                                                 SHIM_IMRX_BUSY);
 346
 347                /* Handle messages from DSP Core */
 348                if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
 349                        snd_sof_dsp_panic(sdev, BDW_PANIC_OFFSET(ipcx) +
 350                                          MBOX_OFFSET);
 351                } else {
 352                        snd_sof_ipc_msgs_rx(sdev);
 353                }
 354
 355                bdw_host_done(sdev);
 356        }
 357
 358        return IRQ_HANDLED;
 359}
 360
 361/*
 362 * IPC Mailbox IO
 363 */
 364
 365static int bdw_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
 366{
 367        /* send the message */
 368        sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
 369                          msg->msg_size);
 370        snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCX, SHIM_IPCX_BUSY);
 371
 372        return 0;
 373}
 374
 375static void bdw_get_reply(struct snd_sof_dev *sdev)
 376{
 377        struct snd_sof_ipc_msg *msg = sdev->msg;
 378        struct sof_ipc_reply reply;
 379        int ret = 0;
 380
 381        /*
 382         * Sometimes, there is unexpected reply ipc arriving. The reply
 383         * ipc belongs to none of the ipcs sent from driver.
 384         * In this case, the driver must ignore the ipc.
 385         */
 386        if (!msg) {
 387                dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n");
 388                return;
 389        }
 390
 391        /* get reply */
 392        sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
 393
 394        if (reply.error < 0) {
 395                memcpy(msg->reply_data, &reply, sizeof(reply));
 396                ret = reply.error;
 397        } else {
 398                /* reply correct size ? */
 399                if (reply.hdr.size != msg->reply_size) {
 400                        dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n",
 401                                msg->reply_size, reply.hdr.size);
 402                        ret = -EINVAL;
 403                }
 404
 405                /* read the message */
 406                if (msg->reply_size > 0)
 407                        sof_mailbox_read(sdev, sdev->host_box.offset,
 408                                         msg->reply_data, msg->reply_size);
 409        }
 410
 411        msg->reply_error = ret;
 412}
 413
 414static int bdw_get_mailbox_offset(struct snd_sof_dev *sdev)
 415{
 416        return MBOX_OFFSET;
 417}
 418
 419static int bdw_get_window_offset(struct snd_sof_dev *sdev, u32 id)
 420{
 421        return MBOX_OFFSET;
 422}
 423
 424static void bdw_host_done(struct snd_sof_dev *sdev)
 425{
 426        /* clear BUSY bit and set DONE bit - accept new messages */
 427        snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCD,
 428                                         SHIM_IPCD_BUSY | SHIM_IPCD_DONE,
 429                                         SHIM_IPCD_DONE);
 430
 431        /* unmask busy interrupt */
 432        snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX,
 433                                         SHIM_IMRX_BUSY, 0);
 434}
 435
 436static void bdw_dsp_done(struct snd_sof_dev *sdev)
 437{
 438        /* clear DONE bit - tell DSP we have completed */
 439        snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCX,
 440                                         SHIM_IPCX_DONE, 0);
 441
 442        /* unmask Done interrupt */
 443        snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX,
 444                                         SHIM_IMRX_DONE, 0);
 445}
 446
 447/*
 448 * Probe and remove.
 449 */
 450static int bdw_probe(struct snd_sof_dev *sdev)
 451{
 452        struct snd_sof_pdata *pdata = sdev->pdata;
 453        const struct sof_dev_desc *desc = pdata->desc;
 454        struct platform_device *pdev =
 455                container_of(sdev->dev, struct platform_device, dev);
 456        struct resource *mmio;
 457        u32 base, size;
 458        int ret;
 459
 460        /* LPE base */
 461        mmio = platform_get_resource(pdev, IORESOURCE_MEM,
 462                                     desc->resindex_lpe_base);
 463        if (mmio) {
 464                base = mmio->start;
 465                size = resource_size(mmio);
 466        } else {
 467                dev_err(sdev->dev, "error: failed to get LPE base at idx %d\n",
 468                        desc->resindex_lpe_base);
 469                return -EINVAL;
 470        }
 471
 472        dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
 473        sdev->bar[BDW_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
 474        if (!sdev->bar[BDW_DSP_BAR]) {
 475                dev_err(sdev->dev,
 476                        "error: failed to ioremap LPE base 0x%x size 0x%x\n",
 477                        base, size);
 478                return -ENODEV;
 479        }
 480        dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BDW_DSP_BAR]);
 481
 482        /* TODO: add offsets */
 483        sdev->mmio_bar = BDW_DSP_BAR;
 484        sdev->mailbox_bar = BDW_DSP_BAR;
 485        sdev->dsp_oops_offset = MBOX_OFFSET;
 486
 487        /* PCI base */
 488        mmio = platform_get_resource(pdev, IORESOURCE_MEM,
 489                                     desc->resindex_pcicfg_base);
 490        if (mmio) {
 491                base = mmio->start;
 492                size = resource_size(mmio);
 493        } else {
 494                dev_err(sdev->dev, "error: failed to get PCI base at idx %d\n",
 495                        desc->resindex_pcicfg_base);
 496                return -ENODEV;
 497        }
 498
 499        dev_dbg(sdev->dev, "PCI base at 0x%x size 0x%x", base, size);
 500        sdev->bar[BDW_PCI_BAR] = devm_ioremap(sdev->dev, base, size);
 501        if (!sdev->bar[BDW_PCI_BAR]) {
 502                dev_err(sdev->dev,
 503                        "error: failed to ioremap PCI base 0x%x size 0x%x\n",
 504                        base, size);
 505                return -ENODEV;
 506        }
 507        dev_dbg(sdev->dev, "PCI VADDR %p\n", sdev->bar[BDW_PCI_BAR]);
 508
 509        /* register our IRQ */
 510        sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc);
 511        if (sdev->ipc_irq < 0)
 512                return sdev->ipc_irq;
 513
 514        dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
 515        ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
 516                                        bdw_irq_handler, bdw_irq_thread,
 517                                        IRQF_SHARED, "AudioDSP", sdev);
 518        if (ret < 0) {
 519                dev_err(sdev->dev, "error: failed to register IRQ %d\n",
 520                        sdev->ipc_irq);
 521                return ret;
 522        }
 523
 524        /* enable the DSP SHIM */
 525        ret = bdw_set_dsp_D0(sdev);
 526        if (ret < 0) {
 527                dev_err(sdev->dev, "error: failed to set DSP D0\n");
 528                return ret;
 529        }
 530
 531        /* DSP DMA can only access low 31 bits of host memory */
 532        ret = dma_coerce_mask_and_coherent(sdev->dev, DMA_BIT_MASK(31));
 533        if (ret < 0) {
 534                dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
 535                return ret;
 536        }
 537
 538        /* set default mailbox */
 539        snd_sof_dsp_mailbox_init(sdev, MBOX_OFFSET, MBOX_SIZE, 0, 0);
 540
 541        return ret;
 542}
 543
 544static void bdw_machine_select(struct snd_sof_dev *sdev)
 545{
 546        struct snd_sof_pdata *sof_pdata = sdev->pdata;
 547        const struct sof_dev_desc *desc = sof_pdata->desc;
 548        struct snd_soc_acpi_mach *mach;
 549
 550        mach = snd_soc_acpi_find_machine(desc->machines);
 551        if (!mach) {
 552                dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
 553                return;
 554        }
 555
 556        sof_pdata->tplg_filename = mach->sof_tplg_filename;
 557        mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc;
 558        sof_pdata->machine = mach;
 559}
 560
 561static void bdw_set_mach_params(const struct snd_soc_acpi_mach *mach,
 562                                struct snd_sof_dev *sdev)
 563{
 564        struct snd_sof_pdata *pdata = sdev->pdata;
 565        const struct sof_dev_desc *desc = pdata->desc;
 566        struct snd_soc_acpi_mach_params *mach_params;
 567
 568        mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params;
 569        mach_params->platform = dev_name(sdev->dev);
 570        mach_params->num_dai_drivers = desc->ops->num_drv;
 571        mach_params->dai_drivers = desc->ops->drv;
 572}
 573
 574/* Broadwell DAIs */
 575static struct snd_soc_dai_driver bdw_dai[] = {
 576{
 577        .name = "ssp0-port",
 578        .playback = {
 579                .channels_min = 1,
 580                .channels_max = 8,
 581        },
 582        .capture = {
 583                .channels_min = 1,
 584                .channels_max = 8,
 585        },
 586},
 587{
 588        .name = "ssp1-port",
 589        .playback = {
 590                .channels_min = 1,
 591                .channels_max = 8,
 592        },
 593        .capture = {
 594                .channels_min = 1,
 595                .channels_max = 8,
 596        },
 597},
 598};
 599
 600/* broadwell ops */
 601static const struct snd_sof_dsp_ops sof_bdw_ops = {
 602        /*Device init */
 603        .probe          = bdw_probe,
 604
 605        /* DSP Core Control */
 606        .run            = bdw_run,
 607        .reset          = bdw_reset,
 608
 609        /* Register IO */
 610        .write          = sof_io_write,
 611        .read           = sof_io_read,
 612        .write64        = sof_io_write64,
 613        .read64         = sof_io_read64,
 614
 615        /* Block IO */
 616        .block_read     = sof_block_read,
 617        .block_write    = sof_block_write,
 618
 619        /* ipc */
 620        .send_msg       = bdw_send_msg,
 621        .fw_ready       = sof_fw_ready,
 622        .get_mailbox_offset = bdw_get_mailbox_offset,
 623        .get_window_offset = bdw_get_window_offset,
 624
 625        .ipc_msg_data   = intel_ipc_msg_data,
 626        .ipc_pcm_params = intel_ipc_pcm_params,
 627
 628        /* machine driver */
 629        .machine_select = bdw_machine_select,
 630        .machine_register = sof_machine_register,
 631        .machine_unregister = sof_machine_unregister,
 632        .set_mach_params = bdw_set_mach_params,
 633
 634        /* debug */
 635        .debug_map  = bdw_debugfs,
 636        .debug_map_count    = ARRAY_SIZE(bdw_debugfs),
 637        .dbg_dump   = bdw_dump,
 638
 639        /* stream callbacks */
 640        .pcm_open       = intel_pcm_open,
 641        .pcm_close      = intel_pcm_close,
 642
 643        /* Module loading */
 644        .load_module    = snd_sof_parse_module_memcpy,
 645
 646        /*Firmware loading */
 647        .load_firmware  = snd_sof_load_firmware_memcpy,
 648
 649        /* DAI drivers */
 650        .drv = bdw_dai,
 651        .num_drv = ARRAY_SIZE(bdw_dai),
 652
 653        /* ALSA HW info flags */
 654        .hw_info =      SNDRV_PCM_INFO_MMAP |
 655                        SNDRV_PCM_INFO_MMAP_VALID |
 656                        SNDRV_PCM_INFO_INTERLEAVED |
 657                        SNDRV_PCM_INFO_PAUSE |
 658                        SNDRV_PCM_INFO_BATCH,
 659
 660        .arch_ops = &sof_xtensa_arch_ops,
 661};
 662
 663static const struct sof_intel_dsp_desc bdw_chip_info = {
 664        .cores_num = 1,
 665        .host_managed_cores_mask = 1,
 666};
 667
 668static const struct sof_dev_desc sof_acpi_broadwell_desc = {
 669        .machines = snd_soc_acpi_intel_broadwell_machines,
 670        .resindex_lpe_base = 0,
 671        .resindex_pcicfg_base = 1,
 672        .resindex_imr_base = -1,
 673        .irqindex_host_ipc = 0,
 674        .chip_info = &bdw_chip_info,
 675        .default_fw_path = "intel/sof",
 676        .default_tplg_path = "intel/sof-tplg",
 677        .default_fw_filename = "sof-bdw.ri",
 678        .nocodec_tplg_filename = "sof-bdw-nocodec.tplg",
 679        .ops = &sof_bdw_ops,
 680};
 681
 682static const struct acpi_device_id sof_broadwell_match[] = {
 683        { "INT3438", (unsigned long)&sof_acpi_broadwell_desc },
 684        { }
 685};
 686MODULE_DEVICE_TABLE(acpi, sof_broadwell_match);
 687
 688static int sof_broadwell_probe(struct platform_device *pdev)
 689{
 690        struct device *dev = &pdev->dev;
 691        const struct acpi_device_id *id;
 692        const struct sof_dev_desc *desc;
 693        int ret;
 694
 695        id = acpi_match_device(dev->driver->acpi_match_table, dev);
 696        if (!id)
 697                return -ENODEV;
 698
 699        ret = snd_intel_acpi_dsp_driver_probe(dev, id->id);
 700        if (ret != SND_INTEL_DSP_DRIVER_ANY && ret != SND_INTEL_DSP_DRIVER_SOF) {
 701                dev_dbg(dev, "SOF ACPI driver not selected, aborting probe\n");
 702                return -ENODEV;
 703        }
 704
 705        desc = device_get_match_data(dev);
 706        if (!desc)
 707                return -ENODEV;
 708
 709        return sof_acpi_probe(pdev, device_get_match_data(dev));
 710}
 711
 712/* acpi_driver definition */
 713static struct platform_driver snd_sof_acpi_intel_bdw_driver = {
 714        .probe = sof_broadwell_probe,
 715        .remove = sof_acpi_remove,
 716        .driver = {
 717                .name = "sof-audio-acpi-intel-bdw",
 718                .pm = &sof_acpi_pm,
 719                .acpi_match_table = sof_broadwell_match,
 720        },
 721};
 722module_platform_driver(snd_sof_acpi_intel_bdw_driver);
 723
 724MODULE_LICENSE("Dual BSD/GPL");
 725MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC);
 726MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
 727MODULE_IMPORT_NS(SND_SOC_SOF_ACPI_DEV);
 728