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