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        IPC_GLB_REPLY_SCLK_ALREADY_RUNNING = 150,
 253        IPC_GLB_REPLY_MCLK_ALREADY_RUNNING = 151,
 254
 255        IPC_GLB_REPLY_PPL_NOT_INITIALIZED = 160,
 256        IPC_GLB_REPLY_PPL_NOT_EXIST = 161,
 257        IPC_GLB_REPLY_PPL_SAVE_FAILED = 162,
 258        IPC_GLB_REPLY_PPL_RESTORE_FAILED = 163,
 259
 260        IPC_MAX_STATUS = ((1<<IPC_IXC_STATUS_BITS)-1)
 261};
 262
 263enum skl_ipc_notification_type {
 264        IPC_GLB_NOTIFY_GLITCH = 0,
 265        IPC_GLB_NOTIFY_OVERRUN = 1,
 266        IPC_GLB_NOTIFY_UNDERRUN = 2,
 267        IPC_GLB_NOTIFY_END_STREAM = 3,
 268        IPC_GLB_NOTIFY_PHRASE_DETECTED = 4,
 269        IPC_GLB_NOTIFY_RESOURCE_EVENT = 5,
 270        IPC_GLB_NOTIFY_LOG_BUFFER_STATUS = 6,
 271        IPC_GLB_NOTIFY_TIMESTAMP_CAPTURED = 7,
 272        IPC_GLB_NOTIFY_FW_READY = 8
 273};
 274
 275/* Module Message Types */
 276enum skl_ipc_module_msg {
 277        IPC_MOD_INIT_INSTANCE = 0,
 278        IPC_MOD_CONFIG_GET = 1,
 279        IPC_MOD_CONFIG_SET = 2,
 280        IPC_MOD_LARGE_CONFIG_GET = 3,
 281        IPC_MOD_LARGE_CONFIG_SET = 4,
 282        IPC_MOD_BIND = 5,
 283        IPC_MOD_UNBIND = 6,
 284        IPC_MOD_SET_DX = 7,
 285        IPC_MOD_SET_D0IX = 8
 286};
 287
 288void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data,
 289                size_t tx_size)
 290{
 291        if (tx_size)
 292                memcpy(msg->tx_data, tx_data, tx_size);
 293}
 294
 295static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp)
 296{
 297        u32 hipci;
 298
 299        hipci = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCI);
 300        return (hipci & SKL_ADSP_REG_HIPCI_BUSY);
 301}
 302
 303/* Lock to be held by caller */
 304static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
 305{
 306        struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header);
 307
 308        if (msg->tx_size)
 309                sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size);
 310        sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE,
 311                                                header->extension);
 312        sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI,
 313                header->primary | SKL_ADSP_REG_HIPCI_BUSY);
 314}
 315
 316int skl_ipc_check_D0i0(struct sst_dsp *dsp, bool state)
 317{
 318        int ret;
 319
 320        /* check D0i3 support */
 321        if (!dsp->fw_ops.set_state_D0i0)
 322                return 0;
 323
 324        /* Attempt D0i0 or D0i3 based on state */
 325        if (state)
 326                ret = dsp->fw_ops.set_state_D0i0(dsp);
 327        else
 328                ret = dsp->fw_ops.set_state_D0i3(dsp);
 329
 330        return ret;
 331}
 332
 333static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc,
 334                                u64 ipc_header)
 335{
 336        struct ipc_message *msg =  NULL;
 337        struct skl_ipc_header *header = (struct skl_ipc_header *)(&ipc_header);
 338
 339        if (list_empty(&ipc->rx_list)) {
 340                dev_err(ipc->dev, "ipc: rx list is empty but received 0x%x\n",
 341                        header->primary);
 342                goto out;
 343        }
 344
 345        msg = list_first_entry(&ipc->rx_list, struct ipc_message, list);
 346
 347out:
 348        return msg;
 349
 350}
 351
 352int skl_ipc_process_notification(struct sst_generic_ipc *ipc,
 353                struct skl_ipc_header header)
 354{
 355        struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc);
 356
 357        if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
 358                switch (IPC_GLB_NOTIFY_TYPE(header.primary)) {
 359
 360                case IPC_GLB_NOTIFY_UNDERRUN:
 361                        dev_err(ipc->dev, "FW Underrun %x\n", header.primary);
 362                        break;
 363
 364                case IPC_GLB_NOTIFY_RESOURCE_EVENT:
 365                        dev_err(ipc->dev, "MCPS Budget Violation: %x\n",
 366                                                header.primary);
 367                        break;
 368
 369                case IPC_GLB_NOTIFY_FW_READY:
 370                        skl->boot_complete = true;
 371                        wake_up(&skl->boot_wait);
 372                        break;
 373
 374                case IPC_GLB_NOTIFY_PHRASE_DETECTED:
 375                        dev_dbg(ipc->dev, "***** Phrase Detected **********\n");
 376
 377                        /*
 378                         * Per HW recomendation, After phrase detection,
 379                         * clear the CGCTL.MISCBDCGE.
 380                         *
 381                         * This will be set back on stream closure
 382                         */
 383                        skl->enable_miscbdcge(ipc->dev, false);
 384                        skl->miscbdcg_disabled = true;
 385                        break;
 386
 387                default:
 388                        dev_err(ipc->dev, "ipc: Unhandled error msg=%x\n",
 389                                                header.primary);
 390                        break;
 391                }
 392        }
 393
 394        return 0;
 395}
 396
 397struct skl_ipc_err_map {
 398        const char *msg;
 399        enum skl_ipc_glb_reply reply;
 400        int err;
 401};
 402
 403static struct skl_ipc_err_map skl_err_map[] = {
 404        {"DSP out of memory", IPC_GLB_REPLY_OUT_OF_MEMORY, -ENOMEM},
 405        {"DSP busy", IPC_GLB_REPLY_BUSY, -EBUSY},
 406        {"SCLK already running", IPC_GLB_REPLY_SCLK_ALREADY_RUNNING,
 407                        IPC_GLB_REPLY_SCLK_ALREADY_RUNNING},
 408        {"MCLK already running", IPC_GLB_REPLY_MCLK_ALREADY_RUNNING,
 409                        IPC_GLB_REPLY_MCLK_ALREADY_RUNNING},
 410};
 411
 412static int skl_ipc_set_reply_error_code(struct sst_generic_ipc *ipc, u32 reply)
 413{
 414        int i;
 415
 416        for (i = 0; i < ARRAY_SIZE(skl_err_map); i++) {
 417                if (skl_err_map[i].reply == reply)
 418                        break;
 419        }
 420
 421        if (i == ARRAY_SIZE(skl_err_map)) {
 422                dev_err(ipc->dev, "ipc FW reply: %d FW Error Code: %u\n",
 423                                reply,
 424                                ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
 425                return -EINVAL;
 426        }
 427
 428        if (skl_err_map[i].err < 0)
 429                dev_err(ipc->dev, "ipc FW reply: %s FW Error Code: %u\n",
 430                                skl_err_map[i].msg,
 431                                ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
 432        else
 433                dev_info(ipc->dev, "ipc FW reply: %s FW Error Code: %u\n",
 434                                skl_err_map[i].msg,
 435                                ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
 436
 437        return skl_err_map[i].err;
 438}
 439
 440void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
 441                struct skl_ipc_header header)
 442{
 443        struct ipc_message *msg;
 444        u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK;
 445        u64 *ipc_header = (u64 *)(&header);
 446        struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc);
 447        unsigned long flags;
 448
 449        spin_lock_irqsave(&ipc->dsp->spinlock, flags);
 450        msg = skl_ipc_reply_get_msg(ipc, *ipc_header);
 451        spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
 452        if (msg == NULL) {
 453                dev_dbg(ipc->dev, "ipc: rx list is empty\n");
 454                return;
 455        }
 456
 457        /* first process the header */
 458        if (reply == IPC_GLB_REPLY_SUCCESS) {
 459                dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary);
 460                /* copy the rx data from the mailbox */
 461                sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size);
 462                switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
 463                case IPC_GLB_LOAD_MULTIPLE_MODS:
 464                case IPC_GLB_LOAD_LIBRARY:
 465                        skl->mod_load_complete = true;
 466                        skl->mod_load_status = true;
 467                        wake_up(&skl->mod_load_wait);
 468                        break;
 469
 470                default:
 471                        break;
 472
 473                }
 474        } else {
 475                msg->errno = skl_ipc_set_reply_error_code(ipc, reply);
 476                switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
 477                case IPC_GLB_LOAD_MULTIPLE_MODS:
 478                case IPC_GLB_LOAD_LIBRARY:
 479                        skl->mod_load_complete = true;
 480                        skl->mod_load_status = false;
 481                        wake_up(&skl->mod_load_wait);
 482                        break;
 483
 484                default:
 485                        break;
 486
 487                }
 488        }
 489
 490        spin_lock_irqsave(&ipc->dsp->spinlock, flags);
 491        list_del(&msg->list);
 492        sst_ipc_tx_msg_reply_complete(ipc, msg);
 493        spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
 494}
 495
 496irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context)
 497{
 498        struct sst_dsp *dsp = context;
 499        struct skl_sst *skl = sst_dsp_get_thread_context(dsp);
 500        struct sst_generic_ipc *ipc = &skl->ipc;
 501        struct skl_ipc_header header = {0};
 502        u32 hipcie, hipct, hipcte;
 503        int ipc_irq = 0;
 504
 505        if (dsp->intr_status & SKL_ADSPIS_CL_DMA)
 506                skl_cldma_process_intr(dsp);
 507
 508        /* Here we handle IPC interrupts only */
 509        if (!(dsp->intr_status & SKL_ADSPIS_IPC))
 510                return IRQ_NONE;
 511
 512        hipcie = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCIE);
 513        hipct = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCT);
 514
 515        /* reply message from DSP */
 516        if (hipcie & SKL_ADSP_REG_HIPCIE_DONE) {
 517                sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
 518                        SKL_ADSP_REG_HIPCCTL_DONE, 0);
 519
 520                /* clear DONE bit - tell DSP we have completed the operation */
 521                sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCIE,
 522                        SKL_ADSP_REG_HIPCIE_DONE, SKL_ADSP_REG_HIPCIE_DONE);
 523
 524                ipc_irq = 1;
 525
 526                /* unmask Done interrupt */
 527                sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
 528                        SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
 529        }
 530
 531        /* New message from DSP */
 532        if (hipct & SKL_ADSP_REG_HIPCT_BUSY) {
 533                hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE);
 534                header.primary = hipct;
 535                header.extension = hipcte;
 536                dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x\n",
 537                                                header.primary);
 538                dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x\n",
 539                                                header.extension);
 540
 541                if (IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) {
 542                        /* Handle Immediate reply from DSP Core */
 543                        skl_ipc_process_reply(ipc, header);
 544                } else {
 545                        dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n");
 546                        skl_ipc_process_notification(ipc, header);
 547                }
 548                /* clear  busy interrupt */
 549                sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCT,
 550                        SKL_ADSP_REG_HIPCT_BUSY, SKL_ADSP_REG_HIPCT_BUSY);
 551                ipc_irq = 1;
 552        }
 553
 554        if (ipc_irq == 0)
 555                return IRQ_NONE;
 556
 557        skl_ipc_int_enable(dsp);
 558
 559        /* continue to send any remaining messages... */
 560        schedule_work(&ipc->kwork);
 561
 562        return IRQ_HANDLED;
 563}
 564
 565void skl_ipc_int_enable(struct sst_dsp *ctx)
 566{
 567        sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_ADSPIC,
 568                        SKL_ADSPIC_IPC, SKL_ADSPIC_IPC);
 569}
 570
 571void skl_ipc_int_disable(struct sst_dsp *ctx)
 572{
 573        sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC,
 574                        SKL_ADSPIC_IPC, 0);
 575}
 576
 577void skl_ipc_op_int_enable(struct sst_dsp *ctx)
 578{
 579        /* enable IPC DONE interrupt */
 580        sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
 581                SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
 582
 583        /* Enable IPC BUSY interrupt */
 584        sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
 585                SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY);
 586}
 587
 588void skl_ipc_op_int_disable(struct sst_dsp *ctx)
 589{
 590        /* disable IPC DONE interrupt */
 591        sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
 592                                        SKL_ADSP_REG_HIPCCTL_DONE, 0);
 593
 594        /* Disable IPC BUSY interrupt */
 595        sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
 596                                        SKL_ADSP_REG_HIPCCTL_BUSY, 0);
 597
 598}
 599
 600bool skl_ipc_int_status(struct sst_dsp *ctx)
 601{
 602        return sst_dsp_shim_read_unlocked(ctx,
 603                        SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC;
 604}
 605
 606int skl_ipc_init(struct device *dev, struct skl_sst *skl)
 607{
 608        struct sst_generic_ipc *ipc;
 609        int err;
 610
 611        ipc = &skl->ipc;
 612        ipc->dsp = skl->dsp;
 613        ipc->dev = dev;
 614
 615        ipc->tx_data_max_size = SKL_ADSP_W1_SZ;
 616        ipc->rx_data_max_size = SKL_ADSP_W0_UP_SZ;
 617
 618        err = sst_ipc_init(ipc);
 619        if (err)
 620                return err;
 621
 622        ipc->ops.tx_msg = skl_ipc_tx_msg;
 623        ipc->ops.tx_data_copy = skl_ipc_tx_data_copy;
 624        ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy;
 625
 626        return 0;
 627}
 628
 629void skl_ipc_free(struct sst_generic_ipc *ipc)
 630{
 631        /* Disable IPC DONE interrupt */
 632        sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
 633                SKL_ADSP_REG_HIPCCTL_DONE, 0);
 634
 635        /* Disable IPC BUSY interrupt */
 636        sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
 637                SKL_ADSP_REG_HIPCCTL_BUSY, 0);
 638
 639        sst_ipc_fini(ipc);
 640}
 641
 642int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc,
 643                u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode)
 644{
 645        struct skl_ipc_header header = {0};
 646        u64 *ipc_header = (u64 *)(&header);
 647        int ret;
 648
 649        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 650        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 651        header.primary |= IPC_GLB_TYPE(IPC_GLB_CREATE_PPL);
 652        header.primary |= IPC_INSTANCE_ID(instance_id);
 653        header.primary |= IPC_PPL_TYPE(ppl_type);
 654        header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size);
 655
 656        header.extension = IPC_PPL_LP_MODE(lp_mode);
 657
 658        dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
 659        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
 660        if (ret < 0) {
 661                dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret);
 662                return ret;
 663        }
 664
 665        return ret;
 666}
 667EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline);
 668
 669int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
 670{
 671        struct skl_ipc_header header = {0};
 672        u64 *ipc_header = (u64 *)(&header);
 673        int ret;
 674
 675        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 676        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 677        header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL);
 678        header.primary |= IPC_INSTANCE_ID(instance_id);
 679
 680        dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
 681        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
 682        if (ret < 0) {
 683                dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret);
 684                return ret;
 685        }
 686
 687        return 0;
 688}
 689EXPORT_SYMBOL_GPL(skl_ipc_delete_pipeline);
 690
 691int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc,
 692                u8 instance_id, enum skl_ipc_pipeline_state state)
 693{
 694        struct skl_ipc_header header = {0};
 695        u64 *ipc_header = (u64 *)(&header);
 696        int ret;
 697
 698        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 699        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 700        header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE);
 701        header.primary |= IPC_INSTANCE_ID(instance_id);
 702        header.primary |= IPC_PPL_STATE(state);
 703
 704        dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
 705        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
 706        if (ret < 0) {
 707                dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret);
 708                return ret;
 709        }
 710        return ret;
 711}
 712EXPORT_SYMBOL_GPL(skl_ipc_set_pipeline_state);
 713
 714int
 715skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id)
 716{
 717        struct skl_ipc_header header = {0};
 718        u64 *ipc_header = (u64 *)(&header);
 719        int ret;
 720
 721        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 722        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 723        header.primary |= IPC_GLB_TYPE(IPC_GLB_SAVE_PPL);
 724        header.primary |= IPC_INSTANCE_ID(instance_id);
 725
 726        header.extension = IPC_DMA_ID(dma_id);
 727        dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
 728        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
 729        if (ret < 0) {
 730                dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret);
 731                return ret;
 732        }
 733
 734        return ret;
 735}
 736EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline);
 737
 738int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
 739{
 740        struct skl_ipc_header header = {0};
 741        u64 *ipc_header = (u64 *)(&header);
 742        int ret;
 743
 744        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 745        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 746        header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL);
 747        header.primary |= IPC_INSTANCE_ID(instance_id);
 748
 749        dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
 750        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
 751        if (ret < 0) {
 752                dev_err(ipc->dev, "ipc: restore  pipeline failed, err: %d\n", ret);
 753                return ret;
 754        }
 755
 756        return ret;
 757}
 758EXPORT_SYMBOL_GPL(skl_ipc_restore_pipeline);
 759
 760int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id,
 761                u16 module_id, struct skl_ipc_dxstate_info *dx)
 762{
 763        struct skl_ipc_header header = {0};
 764        u64 *ipc_header = (u64 *)(&header);
 765        int ret;
 766
 767        header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
 768        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 769        header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_DX);
 770        header.primary |= IPC_MOD_INSTANCE_ID(instance_id);
 771        header.primary |= IPC_MOD_ID(module_id);
 772
 773        dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
 774                         header.primary, header.extension);
 775        ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
 776                                dx, sizeof(*dx), NULL, 0);
 777        if (ret < 0) {
 778                dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret);
 779                return ret;
 780        }
 781
 782        return ret;
 783}
 784EXPORT_SYMBOL_GPL(skl_ipc_set_dx);
 785
 786int skl_ipc_init_instance(struct sst_generic_ipc *ipc,
 787                struct skl_ipc_init_instance_msg *msg, void *param_data)
 788{
 789        struct skl_ipc_header header = {0};
 790        u64 *ipc_header = (u64 *)(&header);
 791        int ret;
 792        u32 *buffer = (u32 *)param_data;
 793         /* param_block_size must be in dwords */
 794        u16 param_block_size = msg->param_data_size / sizeof(u32);
 795
 796        print_hex_dump_debug("Param data:", DUMP_PREFIX_NONE,
 797                16, 4, buffer, param_block_size, false);
 798
 799        header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
 800        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 801        header.primary |= IPC_GLB_TYPE(IPC_MOD_INIT_INSTANCE);
 802        header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
 803        header.primary |= IPC_MOD_ID(msg->module_id);
 804
 805        header.extension = IPC_CORE_ID(msg->core_id);
 806        header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id);
 807        header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size);
 808        header.extension |= IPC_DOMAIN(msg->domain);
 809
 810        dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
 811                         header.primary, header.extension);
 812        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, param_data,
 813                        msg->param_data_size, NULL, 0);
 814
 815        if (ret < 0) {
 816                dev_err(ipc->dev, "ipc: init instance failed\n");
 817                return ret;
 818        }
 819
 820        return ret;
 821}
 822EXPORT_SYMBOL_GPL(skl_ipc_init_instance);
 823
 824int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc,
 825                struct skl_ipc_bind_unbind_msg *msg)
 826{
 827        struct skl_ipc_header header = {0};
 828        u64 *ipc_header = (u64 *)(&header);
 829        u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND;
 830        int ret;
 831
 832        header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
 833        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 834        header.primary |= IPC_GLB_TYPE(bind_unbind);
 835        header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
 836        header.primary |= IPC_MOD_ID(msg->module_id);
 837
 838        header.extension = IPC_DST_MOD_ID(msg->dst_module_id);
 839        header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id);
 840        header.extension |= IPC_DST_QUEUE(msg->dst_queue);
 841        header.extension |= IPC_SRC_QUEUE(msg->src_queue);
 842
 843        dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary,
 844                         header.extension);
 845        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
 846        if (ret < 0) {
 847                dev_err(ipc->dev, "ipc: bind/unbind failed\n");
 848                return ret;
 849        }
 850
 851        return ret;
 852}
 853EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind);
 854
 855/*
 856 * In order to load a module we need to send IPC to initiate that. DMA will
 857 * performed to load the module memory. The FW supports multiple module load
 858 * at single shot, so we can send IPC with N modules represented by
 859 * module_cnt
 860 */
 861int skl_ipc_load_modules(struct sst_generic_ipc *ipc,
 862                                u8 module_cnt, void *data)
 863{
 864        struct skl_ipc_header header = {0};
 865        u64 *ipc_header = (u64 *)(&header);
 866        int ret;
 867
 868        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 869        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 870        header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS);
 871        header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
 872
 873        ret = sst_ipc_tx_message_nowait(ipc, *ipc_header, data,
 874                                (sizeof(u16) * module_cnt));
 875        if (ret < 0)
 876                dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret);
 877
 878        return ret;
 879}
 880EXPORT_SYMBOL_GPL(skl_ipc_load_modules);
 881
 882int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt,
 883                                                        void *data)
 884{
 885        struct skl_ipc_header header = {0};
 886        u64 *ipc_header = (u64 *)(&header);
 887        int ret;
 888
 889        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
 890        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 891        header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS);
 892        header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
 893
 894        ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data,
 895                                (sizeof(u16) * module_cnt), NULL, 0);
 896        if (ret < 0)
 897                dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret);
 898
 899        return ret;
 900}
 901EXPORT_SYMBOL_GPL(skl_ipc_unload_modules);
 902
 903int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
 904                struct skl_ipc_large_config_msg *msg, u32 *param)
 905{
 906        struct skl_ipc_header header = {0};
 907        u64 *ipc_header = (u64 *)(&header);
 908        int ret = 0;
 909        size_t sz_remaining, tx_size, data_offset;
 910
 911        header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
 912        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 913        header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_SET);
 914        header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
 915        header.primary |= IPC_MOD_ID(msg->module_id);
 916
 917        header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
 918        header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
 919        header.extension |= IPC_FINAL_BLOCK(0);
 920        header.extension |= IPC_INITIAL_BLOCK(1);
 921
 922        sz_remaining = msg->param_data_size;
 923        data_offset = 0;
 924        while (sz_remaining != 0) {
 925                tx_size = sz_remaining > SKL_ADSP_W1_SZ
 926                                ? SKL_ADSP_W1_SZ : sz_remaining;
 927                if (tx_size == sz_remaining)
 928                        header.extension |= IPC_FINAL_BLOCK(1);
 929
 930                dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__,
 931                        header.primary, header.extension);
 932                dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n",
 933                        (unsigned)data_offset, (unsigned)tx_size);
 934                ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
 935                                          ((char *)param) + data_offset,
 936                                          tx_size, NULL, 0);
 937                if (ret < 0) {
 938                        dev_err(ipc->dev,
 939                                "ipc: set large config fail, err: %d\n", ret);
 940                        return ret;
 941                }
 942                sz_remaining -= tx_size;
 943                data_offset = msg->param_data_size - sz_remaining;
 944
 945                /* clear the fields */
 946                header.extension &= IPC_INITIAL_BLOCK_CLEAR;
 947                header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
 948                /* fill the fields */
 949                header.extension |= IPC_INITIAL_BLOCK(0);
 950                header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
 951        }
 952
 953        return ret;
 954}
 955EXPORT_SYMBOL_GPL(skl_ipc_set_large_config);
 956
 957int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
 958                struct skl_ipc_large_config_msg *msg, u32 *param)
 959{
 960        struct skl_ipc_header header = {0};
 961        u64 *ipc_header = (u64 *)(&header);
 962        int ret = 0;
 963        size_t sz_remaining, rx_size, data_offset;
 964
 965        header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
 966        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
 967        header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_GET);
 968        header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
 969        header.primary |= IPC_MOD_ID(msg->module_id);
 970
 971        header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
 972        header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
 973        header.extension |= IPC_FINAL_BLOCK(1);
 974        header.extension |= IPC_INITIAL_BLOCK(1);
 975
 976        sz_remaining = msg->param_data_size;
 977        data_offset = 0;
 978
 979        while (sz_remaining != 0) {
 980                rx_size = sz_remaining > SKL_ADSP_W1_SZ
 981                                ? SKL_ADSP_W1_SZ : sz_remaining;
 982                if (rx_size == sz_remaining)
 983                        header.extension |= IPC_FINAL_BLOCK(1);
 984
 985                ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0,
 986                                              ((char *)param) + data_offset,
 987                                              msg->param_data_size);
 988                if (ret < 0) {
 989                        dev_err(ipc->dev,
 990                                "ipc: get large config fail, err: %d\n", ret);
 991                        return ret;
 992                }
 993                sz_remaining -= rx_size;
 994                data_offset = msg->param_data_size - sz_remaining;
 995
 996                /* clear the fields */
 997                header.extension &= IPC_INITIAL_BLOCK_CLEAR;
 998                header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
 999                /* fill the fields */
1000                header.extension |= IPC_INITIAL_BLOCK(1);
1001                header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
1002        }
1003
1004        return ret;
1005}
1006EXPORT_SYMBOL_GPL(skl_ipc_get_large_config);
1007
1008int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc,
1009                                u8 dma_id, u8 table_id, bool wait)
1010{
1011        struct skl_ipc_header header = {0};
1012        u64 *ipc_header = (u64 *)(&header);
1013        int ret = 0;
1014
1015        header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
1016        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
1017        header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY);
1018        header.primary |= IPC_MOD_INSTANCE_ID(table_id);
1019        header.primary |= IPC_MOD_ID(dma_id);
1020
1021        if (wait)
1022                ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
1023                                        NULL, 0, NULL, 0);
1024        else
1025                ret = sst_ipc_tx_message_nowait(ipc, *ipc_header, NULL, 0);
1026
1027        if (ret < 0)
1028                dev_err(ipc->dev, "ipc: load lib failed\n");
1029
1030        return ret;
1031}
1032EXPORT_SYMBOL_GPL(skl_sst_ipc_load_library);
1033
1034int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg)
1035{
1036        struct skl_ipc_header header = {0};
1037        u64 *ipc_header = (u64 *)(&header);
1038        int ret;
1039
1040        header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
1041        header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
1042        header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_D0IX);
1043        header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
1044        header.primary |= IPC_MOD_ID(msg->module_id);
1045
1046        header.extension = IPC_D0IX_WAKE(msg->wake);
1047        header.extension |= IPC_D0IX_STREAMING(msg->streaming);
1048
1049        dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__,
1050                        header.primary, header.extension);
1051
1052        /*
1053         * Use the nopm IPC here as we dont want it checking for D0iX
1054         */
1055        ret = sst_ipc_tx_message_nopm(ipc, *ipc_header, NULL, 0, NULL, 0);
1056        if (ret < 0)
1057                dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret);
1058
1059        return ret;
1060}
1061EXPORT_SYMBOL_GPL(skl_ipc_set_d0ix);
1062