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 197 enum skl_ipc_msg_target { 198 IPC_FW_GEN_MSG = 0, 199 IPC_MOD_MSG = 1 200 }; 201 202 enum skl_ipc_msg_direction { 203 IPC_MSG_REQUEST = 0, 204 IPC_MSG_REPLY = 1 205 }; 206 207 /* Global Message Types */ 208 enum 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 224 enum 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 263 enum 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 */ 276 enum 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 288 void 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 295 static 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 */ 304 static 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 316 int 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 333 static 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 347 out: 348 return msg; 349 350 } 351 352 int 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 397 struct skl_ipc_err_map { 398 const char *msg; 399 enum skl_ipc_glb_reply reply; 400 int err; 401 }; 402 403 static 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 412 static 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 440 void 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 496 irqreturn_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 565 void 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 571 void 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 577 void 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 588 void 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 600 bool 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 606 int 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 629 void 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 642 int 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 } 667 EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline); 668 669 int 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 } 689 EXPORT_SYMBOL_GPL(skl_ipc_delete_pipeline); 690 691 int 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 } 712 EXPORT_SYMBOL_GPL(skl_ipc_set_pipeline_state); 713 714 int 715 skl_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 } 736 EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline); 737 738 int 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 } 758 EXPORT_SYMBOL_GPL(skl_ipc_restore_pipeline); 759 760 int 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 } 784 EXPORT_SYMBOL_GPL(skl_ipc_set_dx); 785 786 int 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 } 822 EXPORT_SYMBOL_GPL(skl_ipc_init_instance); 823 824 int 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 } 853 EXPORT_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 */ 861 int 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 } 880 EXPORT_SYMBOL_GPL(skl_ipc_load_modules); 881 882 int 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 } 901 EXPORT_SYMBOL_GPL(skl_ipc_unload_modules); 902 903 int 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 } 955 EXPORT_SYMBOL_GPL(skl_ipc_set_large_config); 956 957 int 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 } 1006 EXPORT_SYMBOL_GPL(skl_ipc_get_large_config); 1007 1008 int 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 } 1032 EXPORT_SYMBOL_GPL(skl_sst_ipc_load_library); 1033 1034 int 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 } 1061 EXPORT_SYMBOL_GPL(skl_ipc_set_d0ix); 1062