linux/sound/soc/intel/skylake/skl-sst-ipc.c
<<
>>
Prefs
   1/*
   2 * skl-sst-ipc.c - Intel skl IPC Support
   3 *
   4 * Copyright (C) 2014-15, Intel Corporation.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as version 2, as
   8 * published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful, but
  11 * WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 * General Public License for more details.
  14 */
  15#include <linux/device.h>
  16
  17#include "../common/sst-dsp.h"
  18#include "../common/sst-dsp-priv.h"
  19#include "skl.h"
  20#include "skl-sst-dsp.h"
  21#include "skl-sst-ipc.h"
  22#include "sound/hdaudio_ext.h"
  23
  24
  25#define IPC_IXC_STATUS_BITS             24
  26
  27/* Global Message - Generic */
  28#define IPC_GLB_TYPE_SHIFT              24
  29#define IPC_GLB_TYPE_MASK               (0xf << IPC_GLB_TYPE_SHIFT)
  30#define IPC_GLB_TYPE(x)                 ((x) << IPC_GLB_TYPE_SHIFT)
  31
  32/* Global Message - Reply */
  33#define IPC_GLB_REPLY_STATUS_SHIFT      24
  34#define IPC_GLB_REPLY_STATUS_MASK       ((0x1 << IPC_GLB_REPLY_STATUS_SHIFT) - 1)
  35#define IPC_GLB_REPLY_STATUS(x)         ((x) << IPC_GLB_REPLY_STATUS_SHIFT)
  36
  37#define IPC_GLB_REPLY_TYPE_SHIFT        29
  38#define IPC_GLB_REPLY_TYPE_MASK         0x1F
  39#define IPC_GLB_REPLY_TYPE(x)           (((x) >> IPC_GLB_REPLY_TYPE_SHIFT) \
  40                                        & IPC_GLB_RPLY_TYPE_MASK)
  41
  42#define IPC_TIMEOUT_MSECS               3000
  43
  44#define IPC_EMPTY_LIST_SIZE             8
  45
  46#define IPC_MSG_TARGET_SHIFT            30
  47#define IPC_MSG_TARGET_MASK             0x1
  48#define IPC_MSG_TARGET(x)               (((x) & IPC_MSG_TARGET_MASK) \
  49                                        << IPC_MSG_TARGET_SHIFT)
  50
  51#define IPC_MSG_DIR_SHIFT               29
  52#define IPC_MSG_DIR_MASK                0x1
  53#define IPC_MSG_DIR(x)                  (((x) & IPC_MSG_DIR_MASK) \
  54                                        << IPC_MSG_DIR_SHIFT)
  55/* Global Notification Message */
  56#define IPC_GLB_NOTIFY_TYPE_SHIFT       16
  57#define IPC_GLB_NOTIFY_TYPE_MASK        0xFF
  58#define IPC_GLB_NOTIFY_TYPE(x)          (((x) >> IPC_GLB_NOTIFY_TYPE_SHIFT) \
  59                                        & IPC_GLB_NOTIFY_TYPE_MASK)
  60
  61#define IPC_GLB_NOTIFY_MSG_TYPE_SHIFT   24
  62#define IPC_GLB_NOTIFY_MSG_TYPE_MASK    0x1F
  63#define IPC_GLB_NOTIFY_MSG_TYPE(x)      (((x) >> IPC_GLB_NOTIFY_MSG_TYPE_SHIFT) \
  64                                                & IPC_GLB_NOTIFY_MSG_TYPE_MASK)
  65
  66#define IPC_GLB_NOTIFY_RSP_SHIFT        29
  67#define IPC_GLB_NOTIFY_RSP_MASK         0x1
  68#define IPC_GLB_NOTIFY_RSP_TYPE(x)      (((x) >> IPC_GLB_NOTIFY_RSP_SHIFT) \
  69                                        & IPC_GLB_NOTIFY_RSP_MASK)
  70
  71/* Pipeline operations */
  72
  73/* Create pipeline message */
  74#define IPC_PPL_MEM_SIZE_SHIFT          0
  75#define IPC_PPL_MEM_SIZE_MASK           0x7FF
  76#define IPC_PPL_MEM_SIZE(x)             (((x) & IPC_PPL_MEM_SIZE_MASK) \
  77                                        << IPC_PPL_MEM_SIZE_SHIFT)
  78
  79#define IPC_PPL_TYPE_SHIFT              11
  80#define IPC_PPL_TYPE_MASK               0x1F
  81#define IPC_PPL_TYPE(x)                 (((x) & IPC_PPL_TYPE_MASK) \
  82                                        << IPC_PPL_TYPE_SHIFT)
  83
  84#define IPC_INSTANCE_ID_SHIFT           16
  85#define IPC_INSTANCE_ID_MASK            0xFF
  86#define IPC_INSTANCE_ID(x)              (((x) & IPC_INSTANCE_ID_MASK) \
  87                                        << IPC_INSTANCE_ID_SHIFT)
  88
  89#define IPC_PPL_LP_MODE_SHIFT           0
  90#define IPC_PPL_LP_MODE_MASK            0x1
  91#define IPC_PPL_LP_MODE(x)              (((x) & IPC_PPL_LP_MODE_MASK) \
  92                                        << IPC_PPL_LP_MODE_SHIFT)
  93
  94/* Set pipeline state message */
  95#define IPC_PPL_STATE_SHIFT             0
  96#define IPC_PPL_STATE_MASK              0x1F
  97#define IPC_PPL_STATE(x)                (((x) & IPC_PPL_STATE_MASK) \
  98                                        << IPC_PPL_STATE_SHIFT)
  99
 100/* Module operations primary register */
 101#define IPC_MOD_ID_SHIFT                0
 102#define IPC_MOD_ID_MASK         0xFFFF
 103#define IPC_MOD_ID(x)           (((x) & IPC_MOD_ID_MASK) \
 104                                        << IPC_MOD_ID_SHIFT)
 105
 106#define IPC_MOD_INSTANCE_ID_SHIFT       16
 107#define IPC_MOD_INSTANCE_ID_MASK        0xFF
 108#define IPC_MOD_INSTANCE_ID(x)  (((x) & IPC_MOD_INSTANCE_ID_MASK) \
 109                                        << IPC_MOD_INSTANCE_ID_SHIFT)
 110
 111/* Init instance message extension register */
 112#define IPC_PARAM_BLOCK_SIZE_SHIFT      0
 113#define IPC_PARAM_BLOCK_SIZE_MASK       0xFFFF
 114#define IPC_PARAM_BLOCK_SIZE(x)         (((x) & IPC_PARAM_BLOCK_SIZE_MASK) \
 115                                        << IPC_PARAM_BLOCK_SIZE_SHIFT)
 116
 117#define IPC_PPL_INSTANCE_ID_SHIFT       16
 118#define IPC_PPL_INSTANCE_ID_MASK        0xFF
 119#define IPC_PPL_INSTANCE_ID(x)          (((x) & IPC_PPL_INSTANCE_ID_MASK) \
 120                                        << IPC_PPL_INSTANCE_ID_SHIFT)
 121
 122#define IPC_CORE_ID_SHIFT               24
 123#define IPC_CORE_ID_MASK                0x1F
 124#define IPC_CORE_ID(x)                  (((x) & IPC_CORE_ID_MASK) \
 125                                        << IPC_CORE_ID_SHIFT)
 126
 127#define IPC_DOMAIN_SHIFT                28
 128#define IPC_DOMAIN_MASK                 0x1
 129#define IPC_DOMAIN(x)                   (((x) & IPC_DOMAIN_MASK) \
 130                                        << IPC_DOMAIN_SHIFT)
 131
 132/* Bind/Unbind message extension register */
 133#define IPC_DST_MOD_ID_SHIFT            0
 134#define IPC_DST_MOD_ID(x)               (((x) & IPC_MOD_ID_MASK) \
 135                                        << IPC_DST_MOD_ID_SHIFT)
 136
 137#define IPC_DST_MOD_INSTANCE_ID_SHIFT 16
 138#define IPC_DST_MOD_INSTANCE_ID(x)      (((x) & IPC_MOD_INSTANCE_ID_MASK) \
 139                                        << IPC_DST_MOD_INSTANCE_ID_SHIFT)
 140
 141#define IPC_DST_QUEUE_SHIFT             24
 142#define IPC_DST_QUEUE_MASK              0x7
 143#define IPC_DST_QUEUE(x)                (((x) & IPC_DST_QUEUE_MASK) \
 144                                        << IPC_DST_QUEUE_SHIFT)
 145
 146#define IPC_SRC_QUEUE_SHIFT             27
 147#define IPC_SRC_QUEUE_MASK              0x7
 148#define IPC_SRC_QUEUE(x)                (((x) & IPC_SRC_QUEUE_MASK) \
 149                                        << IPC_SRC_QUEUE_SHIFT)
 150/* Load Module count */
 151#define IPC_LOAD_MODULE_SHIFT           0
 152#define IPC_LOAD_MODULE_MASK            0xFF
 153#define IPC_LOAD_MODULE_CNT(x)          (((x) & IPC_LOAD_MODULE_MASK) \
 154                                        << IPC_LOAD_MODULE_SHIFT)
 155
 156/* Save pipeline messgae extension register */
 157#define IPC_DMA_ID_SHIFT                0
 158#define IPC_DMA_ID_MASK                 0x1F
 159#define IPC_DMA_ID(x)                   (((x) & IPC_DMA_ID_MASK) \
 160                                        << IPC_DMA_ID_SHIFT)
 161/* Large Config message extension register */
 162#define IPC_DATA_OFFSET_SZ_SHIFT        0
 163#define IPC_DATA_OFFSET_SZ_MASK         0xFFFFF
 164#define IPC_DATA_OFFSET_SZ(x)           (((x) & IPC_DATA_OFFSET_SZ_MASK) \
 165                                        << IPC_DATA_OFFSET_SZ_SHIFT)
 166#define IPC_DATA_OFFSET_SZ_CLEAR        ~(IPC_DATA_OFFSET_SZ_MASK \
 167                                          << IPC_DATA_OFFSET_SZ_SHIFT)
 168
 169#define IPC_LARGE_PARAM_ID_SHIFT        20
 170#define IPC_LARGE_PARAM_ID_MASK         0xFF
 171#define IPC_LARGE_PARAM_ID(x)           (((x) & IPC_LARGE_PARAM_ID_MASK) \
 172                                        << IPC_LARGE_PARAM_ID_SHIFT)
 173
 174#define IPC_FINAL_BLOCK_SHIFT           28
 175#define IPC_FINAL_BLOCK_MASK            0x1
 176#define IPC_FINAL_BLOCK(x)              (((x) & IPC_FINAL_BLOCK_MASK) \
 177                                        << IPC_FINAL_BLOCK_SHIFT)
 178
 179#define IPC_INITIAL_BLOCK_SHIFT         29
 180#define IPC_INITIAL_BLOCK_MASK          0x1
 181#define IPC_INITIAL_BLOCK(x)            (((x) & IPC_INITIAL_BLOCK_MASK) \
 182                                        << IPC_INITIAL_BLOCK_SHIFT)
 183#define IPC_INITIAL_BLOCK_CLEAR         ~(IPC_INITIAL_BLOCK_MASK \
 184                                          << IPC_INITIAL_BLOCK_SHIFT)
 185/* Set D0ix IPC extension register */
 186#define IPC_D0IX_WAKE_SHIFT             0
 187#define IPC_D0IX_WAKE_MASK              0x1
 188#define IPC_D0IX_WAKE(x)                (((x) & IPC_D0IX_WAKE_MASK) \
 189                                        << IPC_D0IX_WAKE_SHIFT)
 190
 191#define IPC_D0IX_STREAMING_SHIFT        1
 192#define IPC_D0IX_STREAMING_MASK         0x1
 193#define IPC_D0IX_STREAMING(x)           (((x) & IPC_D0IX_STREAMING_MASK) \
 194                                        << IPC_D0IX_STREAMING_SHIFT)
 195
 196
 197enum skl_ipc_msg_target {
 198        IPC_FW_GEN_MSG = 0,
 199        IPC_MOD_MSG = 1
 200};
 201
 202enum skl_ipc_msg_direction {
 203        IPC_MSG_REQUEST = 0,
 204        IPC_MSG_REPLY = 1
 205};
 206
 207/* Global Message Types */
 208enum skl_ipc_glb_type {
 209        IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */
 210        IPC_GLB_LOAD_MULTIPLE_MODS = 15,
 211        IPC_GLB_UNLOAD_MULTIPLE_MODS = 16,
 212        IPC_GLB_CREATE_PPL = 17,
 213        IPC_GLB_DELETE_PPL = 18,
 214        IPC_GLB_SET_PPL_STATE = 19,
 215        IPC_GLB_GET_PPL_STATE = 20,
 216        IPC_GLB_GET_PPL_CONTEXT_SIZE = 21,
 217        IPC_GLB_SAVE_PPL = 22,
 218        IPC_GLB_RESTORE_PPL = 23,
 219        IPC_GLB_LOAD_LIBRARY = 24,
 220        IPC_GLB_NOTIFY = 26,
 221        IPC_GLB_MAX_IPC_MSG_NUMBER = 31 /* Maximum message number */
 222};
 223
 224enum skl_ipc_glb_reply {
 225        IPC_GLB_REPLY_SUCCESS = 0,
 226
 227        IPC_GLB_REPLY_UNKNOWN_MSG_TYPE = 1,
 228        IPC_GLB_REPLY_ERROR_INVALID_PARAM = 2,
 229
 230        IPC_GLB_REPLY_BUSY = 3,
 231        IPC_GLB_REPLY_PENDING = 4,
 232        IPC_GLB_REPLY_FAILURE = 5,
 233        IPC_GLB_REPLY_INVALID_REQUEST = 6,
 234
 235        IPC_GLB_REPLY_OUT_OF_MEMORY = 7,
 236        IPC_GLB_REPLY_OUT_OF_MIPS = 8,
 237
 238        IPC_GLB_REPLY_INVALID_RESOURCE_ID = 9,
 239        IPC_GLB_REPLY_INVALID_RESOURCE_STATE = 10,
 240
 241        IPC_GLB_REPLY_MOD_MGMT_ERROR = 100,
 242        IPC_GLB_REPLY_MOD_LOAD_CL_FAILED = 101,
 243        IPC_GLB_REPLY_MOD_LOAD_INVALID_HASH = 102,
 244
 245        IPC_GLB_REPLY_MOD_UNLOAD_INST_EXIST = 103,
 246        IPC_GLB_REPLY_MOD_NOT_INITIALIZED = 104,
 247
 248        IPC_GLB_REPLY_INVALID_CONFIG_PARAM_ID = 120,
 249        IPC_GLB_REPLY_INVALID_CONFIG_DATA_LEN = 121,
 250        IPC_GLB_REPLY_GATEWAY_NOT_INITIALIZED = 140,
 251        IPC_GLB_REPLY_GATEWAY_NOT_EXIST = 141,
 252
 253        IPC_GLB_REPLY_PPL_NOT_INITIALIZED = 160,
 254        IPC_GLB_REPLY_PPL_NOT_EXIST = 161,
 255        IPC_GLB_REPLY_PPL_SAVE_FAILED = 162,
 256        IPC_GLB_REPLY_PPL_RESTORE_FAILED = 163,
 257
 258        IPC_MAX_STATUS = ((1<<IPC_IXC_STATUS_BITS)-1)
 259};
 260
 261enum skl_ipc_notification_type {
 262        IPC_GLB_NOTIFY_GLITCH = 0,
 263        IPC_GLB_NOTIFY_OVERRUN = 1,
 264        IPC_GLB_NOTIFY_UNDERRUN = 2,
 265        IPC_GLB_NOTIFY_END_STREAM = 3,
 266        IPC_GLB_NOTIFY_PHRASE_DETECTED = 4,
 267        IPC_GLB_NOTIFY_RESOURCE_EVENT = 5,
 268        IPC_GLB_NOTIFY_LOG_BUFFER_STATUS = 6,
 269        IPC_GLB_NOTIFY_TIMESTAMP_CAPTURED = 7,
 270        IPC_GLB_NOTIFY_FW_READY = 8
 271};
 272
 273/* Module Message Types */
 274enum skl_ipc_module_msg {
 275        IPC_MOD_INIT_INSTANCE = 0,
 276        IPC_MOD_CONFIG_GET = 1,
 277        IPC_MOD_CONFIG_SET = 2,
 278        IPC_MOD_LARGE_CONFIG_GET = 3,
 279        IPC_MOD_LARGE_CONFIG_SET = 4,
 280        IPC_MOD_BIND = 5,
 281        IPC_MOD_UNBIND = 6,
 282        IPC_MOD_SET_DX = 7,
 283        IPC_MOD_SET_D0IX = 8
 284};
 285
 286static void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data,
 287                size_t tx_size)
 288{
 289        if (tx_size)
 290                memcpy(msg->tx_data, tx_data, tx_size);
 291}
 292
 293static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp)
 294{
 295        u32 hipci;
 296
 297        hipci = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCI);
 298        return (hipci & SKL_ADSP_REG_HIPCI_BUSY);
 299}
 300
 301/* Lock to be held by caller */
 302static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
 303{
 304        struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header);
 305
 306        if (msg->tx_size)
 307                sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size);
 308        sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE,
 309                                                header->extension);
 310        sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI,
 311                header->primary | SKL_ADSP_REG_HIPCI_BUSY);
 312}
 313
 314int skl_ipc_check_D0i0(struct sst_dsp *dsp, bool state)
 315{
 316        int ret;
 317
 318        /* check D0i3 support */
 319        if (!dsp->fw_ops.set_state_D0i0)
 320                return 0;
 321
 322        /* Attempt D0i0 or D0i3 based on state */
 323        if (state)
 324                ret = dsp->fw_ops.set_state_D0i0(dsp);
 325        else
 326                ret = dsp->fw_ops.set_state_D0i3(dsp);
 327
 328        return ret;
 329}
 330
 331static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc,
 332                                u64 ipc_header)
 333{
 334        struct ipc_message *msg =  NULL;
 335        struct skl_ipc_header *header = (struct skl_ipc_header *)(&ipc_header);
 336
 337        if (list_empty(&ipc->rx_list)) {
 338                dev_err(ipc->dev, "ipc: rx list is empty but received 0x%x\n",
 339                        header->primary);
 340                goto out;
 341        }
 342
 343        msg = list_first_entry(&ipc->rx_list, struct ipc_message, list);
 344
 345out:
 346        return msg;
 347
 348}
 349
 350static int skl_ipc_process_notification(struct sst_generic_ipc *ipc,
 351                struct skl_ipc_header header)
 352{
 353        struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc);
 354
 355        if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
 356                switch (IPC_GLB_NOTIFY_TYPE(header.primary)) {
 357
 358                case IPC_GLB_NOTIFY_UNDERRUN:
 359                        dev_err(ipc->dev, "FW Underrun %x\n", header.primary);
 360                        break;
 361
 362                case IPC_GLB_NOTIFY_RESOURCE_EVENT:
 363                        dev_err(ipc->dev, "MCPS Budget Violation: %x\n",
 364                                                header.primary);
 365                        break;
 366
 367                case IPC_GLB_NOTIFY_FW_READY:
 368                        skl->boot_complete = true;
 369                        wake_up(&skl->boot_wait);
 370                        break;
 371
 372                case IPC_GLB_NOTIFY_PHRASE_DETECTED:
 373                        dev_dbg(ipc->dev, "***** Phrase Detected **********\n");
 374
 375                        /*
 376                         * Per HW recomendation, After phrase detection,
 377                         * clear the CGCTL.MISCBDCGE.
 378                         *
 379                         * This will be set back on stream closure
 380                         */
 381                        skl->enable_miscbdcge(ipc->dev, false);
 382                        skl->miscbdcg_disabled = true;
 383                        break;
 384
 385                default:
 386                        dev_err(ipc->dev, "ipc: Unhandled error msg=%x\n",
 387                                                header.primary);
 388                        break;
 389                }
 390        }
 391
 392        return 0;
 393}
 394
 395static int skl_ipc_set_reply_error_code(u32 reply)
 396{
 397        switch (reply) {
 398        case IPC_GLB_REPLY_OUT_OF_MEMORY:
 399                return -ENOMEM;
 400
 401        case IPC_GLB_REPLY_BUSY:
 402                return -EBUSY;
 403
 404        default:
 405                return -EINVAL;
 406        }
 407}
 408
 409static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
 410                struct skl_ipc_header header)
 411{
 412        struct ipc_message *msg;
 413        u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK;
 414        u64 *ipc_header = (u64 *)(&header);
 415        struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc);
 416        unsigned long flags;
 417
 418        spin_lock_irqsave(&ipc->dsp->spinlock, flags);
 419        msg = skl_ipc_reply_get_msg(ipc, *ipc_header);
 420        spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
 421        if (msg == NULL) {
 422                dev_dbg(ipc->dev, "ipc: rx list is empty\n");
 423                return;
 424        }
 425
 426        /* first process the header */
 427        if (reply == IPC_GLB_REPLY_SUCCESS) {
 428                dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary);
 429                /* copy the rx data from the mailbox */
 430                sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size);
 431                switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
 432                case IPC_GLB_LOAD_MULTIPLE_MODS:
 433                case IPC_GLB_LOAD_LIBRARY:
 434                        skl->mod_load_complete = true;
 435                        skl->mod_load_status = true;
 436                        wake_up(&skl->mod_load_wait);
 437                        break;
 438
 439                default:
 440                        break;
 441
 442                }
 443        } else {
 444                msg->errno = skl_ipc_set_reply_error_code(reply);
 445                dev_err(ipc->dev, "ipc FW reply: reply=%d\n", reply);
 446                dev_err(ipc->dev, "FW Error Code: %u\n",
 447                        ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
 448                switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
 449                case IPC_GLB_LOAD_MULTIPLE_MODS:
 450                case IPC_GLB_LOAD_LIBRARY:
 451                        skl->mod_load_complete = true;
 452                        skl->mod_load_status = false;
 453                        wake_up(&skl->mod_load_wait);
 454                        break;
 455
 456                default:
 457                        break;
 458
 459                }
 460        }
 461
 462        spin_lock_irqsave(&ipc->dsp->spinlock, flags);
 463        list_del(&msg->list);
 464        sst_ipc_tx_msg_reply_complete(ipc, msg);
 465        spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
 466}
 467
 468irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context)
 469{
 470        struct sst_dsp *dsp = context;
 471        struct skl_sst *skl = sst_dsp_get_thread_context(dsp);
 472        struct sst_generic_ipc *ipc = &skl->ipc;
 473        struct skl_ipc_header header = {0};
 474        u32 hipcie, hipct, hipcte;
 475        int ipc_irq = 0;
 476
 477        if (dsp->intr_status & SKL_ADSPIS_CL_DMA)
 478                skl_cldma_process_intr(dsp);
 479
 480        /* Here we handle IPC interrupts only */
 481        if (!(dsp->intr_status & SKL_ADSPIS_IPC))
 482                return IRQ_NONE;
 483
 484        hipcie = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCIE);
 485        hipct = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCT);
 486
 487        /* reply message from DSP */
 488        if (hipcie & SKL_ADSP_REG_HIPCIE_DONE) {
 489                sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
 490                        SKL_ADSP_REG_HIPCCTL_DONE, 0);
 491
 492                /* clear DONE bit - tell DSP we have completed the operation */
 493                sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCIE,
 494                        SKL_ADSP_REG_HIPCIE_DONE, SKL_ADSP_REG_HIPCIE_DONE);
 495
 496                ipc_irq = 1;
 497
 498                /* unmask Done interrupt */
 499                sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
 500                        SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
 501        }
 502
 503        /* New message from DSP */
 504        if (hipct & SKL_ADSP_REG_HIPCT_BUSY) {
 505                hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE);
 506                header.primary = hipct;
 507                header.extension = hipcte;
 508                dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x\n",
 509                                                header.primary);
 510                dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x\n",
 511                                                header.extension);
 512
 513                if (IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) {
 514                        /* Handle Immediate reply from DSP Core */
 515                        skl_ipc_process_reply(ipc, header);
 516                } else {
 517                        dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n");
 518                        skl_ipc_process_notification(ipc, header);
 519                }
 520                /* clear  busy interrupt */
 521                sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCT,
 522                        SKL_ADSP_REG_HIPCT_BUSY, SKL_ADSP_REG_HIPCT_BUSY);
 523                ipc_irq = 1;
 524        }
 525
 526        if (ipc_irq == 0)
 527                return IRQ_NONE;
 528
 529        skl_ipc_int_enable(dsp);
 530
 531        /* continue to send any remaining messages... */
 532        schedule_work(&ipc->kwork);
 533
 534        return IRQ_HANDLED;
 535}
 536
 537void skl_ipc_int_enable(struct sst_dsp *ctx)
 538{
 539        sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_ADSPIC,
 540                        SKL_ADSPIC_IPC, SKL_ADSPIC_IPC);
 541}
 542
 543void skl_ipc_int_disable(struct sst_dsp *ctx)
 544{
 545        sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC,
 546                        SKL_ADSPIC_IPC, 0);
 547}
 548
 549void skl_ipc_op_int_enable(struct sst_dsp *ctx)
 550{
 551        /* enable IPC DONE interrupt */
 552        sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
 553                SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
 554
 555        /* Enable IPC BUSY interrupt */
 556        sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
 557                SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY);
 558}
 559
 560void skl_ipc_op_int_disable(struct sst_dsp *ctx)
 561{
 562        /* disable IPC DONE interrupt */
 563        sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
 564                                        SKL_ADSP_REG_HIPCCTL_DONE, 0);
 565
 566        /* Disable IPC BUSY interrupt */
 567        sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
 568                                        SKL_ADSP_REG_HIPCCTL_BUSY, 0);
 569
 570}
 571
 572bool skl_ipc_int_status(struct sst_dsp *ctx)
 573{
 574        return sst_dsp_shim_read_unlocked(ctx,
 575                        SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC;
 576}
 577
 578int skl_ipc_init(struct device *dev, struct skl_sst *skl)
 579{
 580        struct sst_generic_ipc *ipc;
 581        int err;
 582
 583        ipc = &skl->ipc;
 584        ipc->dsp = skl->dsp;
 585        ipc->dev = dev;
 586
 587        ipc->tx_data_max_size = SKL_ADSP_W1_SZ;
 588        ipc->rx_data_max_size = SKL_ADSP_W0_UP_SZ;
 589
 590        err = sst_ipc_init(ipc);
 591        if (err)
 592                return err;
 593
 594        ipc->ops.tx_msg = skl_ipc_tx_msg;
 595        ipc->ops.tx_data_copy = skl_ipc_tx_data_copy;
 596        ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy;
 597
 598        return 0;
 599}
 600
 601void skl_ipc_free(struct sst_generic_ipc *ipc)
 602{
 603        /* Disable IPC DONE interrupt */
 604        sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
 605                SKL_ADSP_REG_HIPCCTL_DONE, 0);
 606
 607        /* Disable IPC BUSY interrupt */
 608        sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
 609                SKL_ADSP_REG_HIPCCTL_BUSY, 0);
 610
 611        sst_ipc_fini(ipc);
 612}
 613
 614int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc,
 615                u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode)
 616{
 617        struct skl_ipc_header header = {0};
 618        u64 *ipc_header = (u64 *)(&header);
 619        int ret;
 620
 621        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 622        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 623        header.primary |= IPC_GLB_TYPE(IPC_GLB_CREATE_PPL);
 624        header.primary |= IPC_INSTANCE_ID(instance_id);
 625        header.primary |= IPC_PPL_TYPE(ppl_type);
 626        header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size);
 627
 628        header.extension = IPC_PPL_LP_MODE(lp_mode);
 629
 630        dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
 631        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
 632        if (ret < 0) {
 633                dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret);
 634                return ret;
 635        }
 636
 637        return ret;
 638}
 639EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline);
 640
 641int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
 642{
 643        struct skl_ipc_header header = {0};
 644        u64 *ipc_header = (u64 *)(&header);
 645        int ret;
 646
 647        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 648        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 649        header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL);
 650        header.primary |= IPC_INSTANCE_ID(instance_id);
 651
 652        dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
 653        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
 654        if (ret < 0) {
 655                dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret);
 656                return ret;
 657        }
 658
 659        return 0;
 660}
 661EXPORT_SYMBOL_GPL(skl_ipc_delete_pipeline);
 662
 663int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc,
 664                u8 instance_id, enum skl_ipc_pipeline_state state)
 665{
 666        struct skl_ipc_header header = {0};
 667        u64 *ipc_header = (u64 *)(&header);
 668        int ret;
 669
 670        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 671        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 672        header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE);
 673        header.primary |= IPC_INSTANCE_ID(instance_id);
 674        header.primary |= IPC_PPL_STATE(state);
 675
 676        dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
 677        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
 678        if (ret < 0) {
 679                dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret);
 680                return ret;
 681        }
 682        return ret;
 683}
 684EXPORT_SYMBOL_GPL(skl_ipc_set_pipeline_state);
 685
 686int
 687skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id)
 688{
 689        struct skl_ipc_header header = {0};
 690        u64 *ipc_header = (u64 *)(&header);
 691        int ret;
 692
 693        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 694        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 695        header.primary |= IPC_GLB_TYPE(IPC_GLB_SAVE_PPL);
 696        header.primary |= IPC_INSTANCE_ID(instance_id);
 697
 698        header.extension = IPC_DMA_ID(dma_id);
 699        dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
 700        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
 701        if (ret < 0) {
 702                dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret);
 703                return ret;
 704        }
 705
 706        return ret;
 707}
 708EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline);
 709
 710int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
 711{
 712        struct skl_ipc_header header = {0};
 713        u64 *ipc_header = (u64 *)(&header);
 714        int ret;
 715
 716        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 717        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 718        header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL);
 719        header.primary |= IPC_INSTANCE_ID(instance_id);
 720
 721        dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
 722        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
 723        if (ret < 0) {
 724                dev_err(ipc->dev, "ipc: restore  pipeline failed, err: %d\n", ret);
 725                return ret;
 726        }
 727
 728        return ret;
 729}
 730EXPORT_SYMBOL_GPL(skl_ipc_restore_pipeline);
 731
 732int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id,
 733                u16 module_id, struct skl_ipc_dxstate_info *dx)
 734{
 735        struct skl_ipc_header header = {0};
 736        u64 *ipc_header = (u64 *)(&header);
 737        int ret;
 738
 739        header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
 740        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 741        header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_DX);
 742        header.primary |= IPC_MOD_INSTANCE_ID(instance_id);
 743        header.primary |= IPC_MOD_ID(module_id);
 744
 745        dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
 746                         header.primary, header.extension);
 747        ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
 748                                dx, sizeof(*dx), NULL, 0);
 749        if (ret < 0) {
 750                dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret);
 751                return ret;
 752        }
 753
 754        return ret;
 755}
 756EXPORT_SYMBOL_GPL(skl_ipc_set_dx);
 757
 758int skl_ipc_init_instance(struct sst_generic_ipc *ipc,
 759                struct skl_ipc_init_instance_msg *msg, void *param_data)
 760{
 761        struct skl_ipc_header header = {0};
 762        u64 *ipc_header = (u64 *)(&header);
 763        int ret;
 764        u32 *buffer = (u32 *)param_data;
 765         /* param_block_size must be in dwords */
 766        u16 param_block_size = msg->param_data_size / sizeof(u32);
 767
 768        print_hex_dump_debug("Param data:", DUMP_PREFIX_NONE,
 769                16, 4, buffer, param_block_size, false);
 770
 771        header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
 772        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 773        header.primary |= IPC_GLB_TYPE(IPC_MOD_INIT_INSTANCE);
 774        header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
 775        header.primary |= IPC_MOD_ID(msg->module_id);
 776
 777        header.extension = IPC_CORE_ID(msg->core_id);
 778        header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id);
 779        header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size);
 780        header.extension |= IPC_DOMAIN(msg->domain);
 781
 782        dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
 783                         header.primary, header.extension);
 784        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, param_data,
 785                        msg->param_data_size, NULL, 0);
 786
 787        if (ret < 0) {
 788                dev_err(ipc->dev, "ipc: init instance failed\n");
 789                return ret;
 790        }
 791
 792        return ret;
 793}
 794EXPORT_SYMBOL_GPL(skl_ipc_init_instance);
 795
 796int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc,
 797                struct skl_ipc_bind_unbind_msg *msg)
 798{
 799        struct skl_ipc_header header = {0};
 800        u64 *ipc_header = (u64 *)(&header);
 801        u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND;
 802        int ret;
 803
 804        header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
 805        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 806        header.primary |= IPC_GLB_TYPE(bind_unbind);
 807        header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
 808        header.primary |= IPC_MOD_ID(msg->module_id);
 809
 810        header.extension = IPC_DST_MOD_ID(msg->dst_module_id);
 811        header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id);
 812        header.extension |= IPC_DST_QUEUE(msg->dst_queue);
 813        header.extension |= IPC_SRC_QUEUE(msg->src_queue);
 814
 815        dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary,
 816                         header.extension);
 817        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
 818        if (ret < 0) {
 819                dev_err(ipc->dev, "ipc: bind/unbind failed\n");
 820                return ret;
 821        }
 822
 823        return ret;
 824}
 825EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind);
 826
 827/*
 828 * In order to load a module we need to send IPC to initiate that. DMA will
 829 * performed to load the module memory. The FW supports multiple module load
 830 * at single shot, so we can send IPC with N modules represented by
 831 * module_cnt
 832 */
 833int skl_ipc_load_modules(struct sst_generic_ipc *ipc,
 834                                u8 module_cnt, void *data)
 835{
 836        struct skl_ipc_header header = {0};
 837        u64 *ipc_header = (u64 *)(&header);
 838        int ret;
 839
 840        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 841        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 842        header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS);
 843        header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
 844
 845        ret = sst_ipc_tx_message_nowait(ipc, *ipc_header, data,
 846                                (sizeof(u16) * module_cnt));
 847        if (ret < 0)
 848                dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret);
 849
 850        return ret;
 851}
 852EXPORT_SYMBOL_GPL(skl_ipc_load_modules);
 853
 854int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt,
 855                                                        void *data)
 856{
 857        struct skl_ipc_header header = {0};
 858        u64 *ipc_header = (u64 *)(&header);
 859        int ret;
 860
 861        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 862        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 863        header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS);
 864        header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
 865
 866        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data,
 867                                (sizeof(u16) * module_cnt), NULL, 0);
 868        if (ret < 0)
 869                dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret);
 870
 871        return ret;
 872}
 873EXPORT_SYMBOL_GPL(skl_ipc_unload_modules);
 874
 875int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
 876                struct skl_ipc_large_config_msg *msg, u32 *param)
 877{
 878        struct skl_ipc_header header = {0};
 879        u64 *ipc_header = (u64 *)(&header);
 880        int ret = 0;
 881        size_t sz_remaining, tx_size, data_offset;
 882
 883        header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
 884        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 885        header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_SET);
 886        header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
 887        header.primary |= IPC_MOD_ID(msg->module_id);
 888
 889        header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
 890        header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
 891        header.extension |= IPC_FINAL_BLOCK(0);
 892        header.extension |= IPC_INITIAL_BLOCK(1);
 893
 894        sz_remaining = msg->param_data_size;
 895        data_offset = 0;
 896        while (sz_remaining != 0) {
 897                tx_size = sz_remaining > SKL_ADSP_W1_SZ
 898                                ? SKL_ADSP_W1_SZ : sz_remaining;
 899                if (tx_size == sz_remaining)
 900                        header.extension |= IPC_FINAL_BLOCK(1);
 901
 902                dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__,
 903                        header.primary, header.extension);
 904                dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n",
 905                        (unsigned)data_offset, (unsigned)tx_size);
 906                ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
 907                                          ((char *)param) + data_offset,
 908                                          tx_size, NULL, 0);
 909                if (ret < 0) {
 910                        dev_err(ipc->dev,
 911                                "ipc: set large config fail, err: %d\n", ret);
 912                        return ret;
 913                }
 914                sz_remaining -= tx_size;
 915                data_offset = msg->param_data_size - sz_remaining;
 916
 917                /* clear the fields */
 918                header.extension &= IPC_INITIAL_BLOCK_CLEAR;
 919                header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
 920                /* fill the fields */
 921                header.extension |= IPC_INITIAL_BLOCK(0);
 922                header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
 923        }
 924
 925        return ret;
 926}
 927EXPORT_SYMBOL_GPL(skl_ipc_set_large_config);
 928
 929int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
 930                struct skl_ipc_large_config_msg *msg, u32 *param)
 931{
 932        struct skl_ipc_header header = {0};
 933        u64 *ipc_header = (u64 *)(&header);
 934        int ret = 0;
 935        size_t sz_remaining, rx_size, data_offset;
 936
 937        header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
 938        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 939        header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_GET);
 940        header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
 941        header.primary |= IPC_MOD_ID(msg->module_id);
 942
 943        header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
 944        header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
 945        header.extension |= IPC_FINAL_BLOCK(1);
 946        header.extension |= IPC_INITIAL_BLOCK(1);
 947
 948        sz_remaining = msg->param_data_size;
 949        data_offset = 0;
 950
 951        while (sz_remaining != 0) {
 952                rx_size = sz_remaining > SKL_ADSP_W1_SZ
 953                                ? SKL_ADSP_W1_SZ : sz_remaining;
 954                if (rx_size == sz_remaining)
 955                        header.extension |= IPC_FINAL_BLOCK(1);
 956
 957                ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0,
 958                                              ((char *)param) + data_offset,
 959                                              msg->param_data_size);
 960                if (ret < 0) {
 961                        dev_err(ipc->dev,
 962                                "ipc: get large config fail, err: %d\n", ret);
 963                        return ret;
 964                }
 965                sz_remaining -= rx_size;
 966                data_offset = msg->param_data_size - sz_remaining;
 967
 968                /* clear the fields */
 969                header.extension &= IPC_INITIAL_BLOCK_CLEAR;
 970                header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
 971                /* fill the fields */
 972                header.extension |= IPC_INITIAL_BLOCK(1);
 973                header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
 974        }
 975
 976        return ret;
 977}
 978EXPORT_SYMBOL_GPL(skl_ipc_get_large_config);
 979
 980int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc,
 981                                u8 dma_id, u8 table_id, bool wait)
 982{
 983        struct skl_ipc_header header = {0};
 984        u64 *ipc_header = (u64 *)(&header);
 985        int ret = 0;
 986
 987        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 988        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 989        header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY);
 990        header.primary |= IPC_MOD_INSTANCE_ID(table_id);
 991        header.primary |= IPC_MOD_ID(dma_id);
 992
 993        if (wait)
 994                ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
 995                                        NULL, 0, NULL, 0);
 996        else
 997                ret = sst_ipc_tx_message_nowait(ipc, *ipc_header, NULL, 0);
 998
 999        if (ret < 0)
1000                dev_err(ipc->dev, "ipc: load lib failed\n");
1001
1002        return ret;
1003}
1004EXPORT_SYMBOL_GPL(skl_sst_ipc_load_library);
1005
1006int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg)
1007{
1008        struct skl_ipc_header header = {0};
1009        u64 *ipc_header = (u64 *)(&header);
1010        int ret;
1011
1012        header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
1013        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
1014        header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_D0IX);
1015        header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
1016        header.primary |= IPC_MOD_ID(msg->module_id);
1017
1018        header.extension = IPC_D0IX_WAKE(msg->wake);
1019        header.extension |= IPC_D0IX_STREAMING(msg->streaming);
1020
1021        dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__,
1022                        header.primary, header.extension);
1023
1024        /*
1025         * Use the nopm IPC here as we dont want it checking for D0iX
1026         */
1027        ret = sst_ipc_tx_message_nopm(ipc, *ipc_header, NULL, 0, NULL, 0);
1028        if (ret < 0)
1029                dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret);
1030
1031        return ret;
1032}
1033EXPORT_SYMBOL_GPL(skl_ipc_set_d0ix);
1034