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