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-sst-dsp.h" 20 #include "skl-sst-ipc.h" 21 22 23 #define IPC_IXC_STATUS_BITS 24 24 25 /* Global Message - Generic */ 26 #define IPC_GLB_TYPE_SHIFT 24 27 #define IPC_GLB_TYPE_MASK (0xf << IPC_GLB_TYPE_SHIFT) 28 #define IPC_GLB_TYPE(x) ((x) << IPC_GLB_TYPE_SHIFT) 29 30 /* Global Message - Reply */ 31 #define IPC_GLB_REPLY_STATUS_SHIFT 24 32 #define IPC_GLB_REPLY_STATUS_MASK ((0x1 << IPC_GLB_REPLY_STATUS_SHIFT) - 1) 33 #define IPC_GLB_REPLY_STATUS(x) ((x) << IPC_GLB_REPLY_STATUS_SHIFT) 34 35 #define IPC_TIMEOUT_MSECS 3000 36 37 #define IPC_EMPTY_LIST_SIZE 8 38 39 #define IPC_MSG_TARGET_SHIFT 30 40 #define IPC_MSG_TARGET_MASK 0x1 41 #define IPC_MSG_TARGET(x) (((x) & IPC_MSG_TARGET_MASK) \ 42 << IPC_MSG_TARGET_SHIFT) 43 44 #define IPC_MSG_DIR_SHIFT 29 45 #define IPC_MSG_DIR_MASK 0x1 46 #define IPC_MSG_DIR(x) (((x) & IPC_MSG_DIR_MASK) \ 47 << IPC_MSG_DIR_SHIFT) 48 /* Global Notification Message */ 49 #define IPC_GLB_NOTIFY_TYPE_SHIFT 16 50 #define IPC_GLB_NOTIFY_TYPE_MASK 0xFF 51 #define IPC_GLB_NOTIFY_TYPE(x) (((x) >> IPC_GLB_NOTIFY_TYPE_SHIFT) \ 52 & IPC_GLB_NOTIFY_TYPE_MASK) 53 54 #define IPC_GLB_NOTIFY_MSG_TYPE_SHIFT 24 55 #define IPC_GLB_NOTIFY_MSG_TYPE_MASK 0x1F 56 #define IPC_GLB_NOTIFY_MSG_TYPE(x) (((x) >> IPC_GLB_NOTIFY_MSG_TYPE_SHIFT) \ 57 & IPC_GLB_NOTIFY_MSG_TYPE_MASK) 58 59 #define IPC_GLB_NOTIFY_RSP_SHIFT 29 60 #define IPC_GLB_NOTIFY_RSP_MASK 0x1 61 #define IPC_GLB_NOTIFY_RSP_TYPE(x) (((x) >> IPC_GLB_NOTIFY_RSP_SHIFT) \ 62 & IPC_GLB_NOTIFY_RSP_MASK) 63 64 /* Pipeline operations */ 65 66 /* Create pipeline message */ 67 #define IPC_PPL_MEM_SIZE_SHIFT 0 68 #define IPC_PPL_MEM_SIZE_MASK 0x7FF 69 #define IPC_PPL_MEM_SIZE(x) (((x) & IPC_PPL_MEM_SIZE_MASK) \ 70 << IPC_PPL_MEM_SIZE_SHIFT) 71 72 #define IPC_PPL_TYPE_SHIFT 11 73 #define IPC_PPL_TYPE_MASK 0x1F 74 #define IPC_PPL_TYPE(x) (((x) & IPC_PPL_TYPE_MASK) \ 75 << IPC_PPL_TYPE_SHIFT) 76 77 #define IPC_INSTANCE_ID_SHIFT 16 78 #define IPC_INSTANCE_ID_MASK 0xFF 79 #define IPC_INSTANCE_ID(x) (((x) & IPC_INSTANCE_ID_MASK) \ 80 << IPC_INSTANCE_ID_SHIFT) 81 82 /* Set pipeline state message */ 83 #define IPC_PPL_STATE_SHIFT 0 84 #define IPC_PPL_STATE_MASK 0x1F 85 #define IPC_PPL_STATE(x) (((x) & IPC_PPL_STATE_MASK) \ 86 << IPC_PPL_STATE_SHIFT) 87 88 /* Module operations primary register */ 89 #define IPC_MOD_ID_SHIFT 0 90 #define IPC_MOD_ID_MASK 0xFFFF 91 #define IPC_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \ 92 << IPC_MOD_ID_SHIFT) 93 94 #define IPC_MOD_INSTANCE_ID_SHIFT 16 95 #define IPC_MOD_INSTANCE_ID_MASK 0xFF 96 #define IPC_MOD_INSTANCE_ID(x) (((x) & IPC_MOD_INSTANCE_ID_MASK) \ 97 << IPC_MOD_INSTANCE_ID_SHIFT) 98 99 /* Init instance message extension register */ 100 #define IPC_PARAM_BLOCK_SIZE_SHIFT 0 101 #define IPC_PARAM_BLOCK_SIZE_MASK 0xFFFF 102 #define IPC_PARAM_BLOCK_SIZE(x) (((x) & IPC_PARAM_BLOCK_SIZE_MASK) \ 103 << IPC_PARAM_BLOCK_SIZE_SHIFT) 104 105 #define IPC_PPL_INSTANCE_ID_SHIFT 16 106 #define IPC_PPL_INSTANCE_ID_MASK 0xFF 107 #define IPC_PPL_INSTANCE_ID(x) (((x) & IPC_PPL_INSTANCE_ID_MASK) \ 108 << IPC_PPL_INSTANCE_ID_SHIFT) 109 110 #define IPC_CORE_ID_SHIFT 24 111 #define IPC_CORE_ID_MASK 0x1F 112 #define IPC_CORE_ID(x) (((x) & IPC_CORE_ID_MASK) \ 113 << IPC_CORE_ID_SHIFT) 114 115 /* Bind/Unbind message extension register */ 116 #define IPC_DST_MOD_ID_SHIFT 0 117 #define IPC_DST_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \ 118 << IPC_DST_MOD_ID_SHIFT) 119 120 #define IPC_DST_MOD_INSTANCE_ID_SHIFT 16 121 #define IPC_DST_MOD_INSTANCE_ID(x) (((x) & IPC_MOD_INSTANCE_ID_MASK) \ 122 << IPC_DST_MOD_INSTANCE_ID_SHIFT) 123 124 #define IPC_DST_QUEUE_SHIFT 24 125 #define IPC_DST_QUEUE_MASK 0x7 126 #define IPC_DST_QUEUE(x) (((x) & IPC_DST_QUEUE_MASK) \ 127 << IPC_DST_QUEUE_SHIFT) 128 129 #define IPC_SRC_QUEUE_SHIFT 27 130 #define IPC_SRC_QUEUE_MASK 0x7 131 #define IPC_SRC_QUEUE(x) (((x) & IPC_SRC_QUEUE_MASK) \ 132 << IPC_SRC_QUEUE_SHIFT) 133 134 /* Save pipeline messgae extension register */ 135 #define IPC_DMA_ID_SHIFT 0 136 #define IPC_DMA_ID_MASK 0x1F 137 #define IPC_DMA_ID(x) (((x) & IPC_DMA_ID_MASK) \ 138 << IPC_DMA_ID_SHIFT) 139 /* Large Config message extension register */ 140 #define IPC_DATA_OFFSET_SZ_SHIFT 0 141 #define IPC_DATA_OFFSET_SZ_MASK 0xFFFFF 142 #define IPC_DATA_OFFSET_SZ(x) (((x) & IPC_DATA_OFFSET_SZ_MASK) \ 143 << IPC_DATA_OFFSET_SZ_SHIFT) 144 #define IPC_DATA_OFFSET_SZ_CLEAR ~(IPC_DATA_OFFSET_SZ_MASK \ 145 << IPC_DATA_OFFSET_SZ_SHIFT) 146 147 #define IPC_LARGE_PARAM_ID_SHIFT 20 148 #define IPC_LARGE_PARAM_ID_MASK 0xFF 149 #define IPC_LARGE_PARAM_ID(x) (((x) & IPC_LARGE_PARAM_ID_MASK) \ 150 << IPC_LARGE_PARAM_ID_SHIFT) 151 152 #define IPC_FINAL_BLOCK_SHIFT 28 153 #define IPC_FINAL_BLOCK_MASK 0x1 154 #define IPC_FINAL_BLOCK(x) (((x) & IPC_FINAL_BLOCK_MASK) \ 155 << IPC_FINAL_BLOCK_SHIFT) 156 157 #define IPC_INITIAL_BLOCK_SHIFT 29 158 #define IPC_INITIAL_BLOCK_MASK 0x1 159 #define IPC_INITIAL_BLOCK(x) (((x) & IPC_INITIAL_BLOCK_MASK) \ 160 << IPC_INITIAL_BLOCK_SHIFT) 161 #define IPC_INITIAL_BLOCK_CLEAR ~(IPC_INITIAL_BLOCK_MASK \ 162 << IPC_INITIAL_BLOCK_SHIFT) 163 164 enum skl_ipc_msg_target { 165 IPC_FW_GEN_MSG = 0, 166 IPC_MOD_MSG = 1 167 }; 168 169 enum skl_ipc_msg_direction { 170 IPC_MSG_REQUEST = 0, 171 IPC_MSG_REPLY = 1 172 }; 173 174 /* Global Message Types */ 175 enum skl_ipc_glb_type { 176 IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */ 177 IPC_GLB_LOAD_MULTIPLE_MODS = 15, 178 IPC_GLB_UNLOAD_MULTIPLE_MODS = 16, 179 IPC_GLB_CREATE_PPL = 17, 180 IPC_GLB_DELETE_PPL = 18, 181 IPC_GLB_SET_PPL_STATE = 19, 182 IPC_GLB_GET_PPL_STATE = 20, 183 IPC_GLB_GET_PPL_CONTEXT_SIZE = 21, 184 IPC_GLB_SAVE_PPL = 22, 185 IPC_GLB_RESTORE_PPL = 23, 186 IPC_GLB_NOTIFY = 26, 187 IPC_GLB_MAX_IPC_MSG_NUMBER = 31 /* Maximum message number */ 188 }; 189 190 enum skl_ipc_glb_reply { 191 IPC_GLB_REPLY_SUCCESS = 0, 192 193 IPC_GLB_REPLY_UNKNOWN_MSG_TYPE = 1, 194 IPC_GLB_REPLY_ERROR_INVALID_PARAM = 2, 195 196 IPC_GLB_REPLY_BUSY = 3, 197 IPC_GLB_REPLY_PENDING = 4, 198 IPC_GLB_REPLY_FAILURE = 5, 199 IPC_GLB_REPLY_INVALID_REQUEST = 6, 200 201 IPC_GLB_REPLY_OUT_OF_MEMORY = 7, 202 IPC_GLB_REPLY_OUT_OF_MIPS = 8, 203 204 IPC_GLB_REPLY_INVALID_RESOURCE_ID = 9, 205 IPC_GLB_REPLY_INVALID_RESOURCE_STATE = 10, 206 207 IPC_GLB_REPLY_MOD_MGMT_ERROR = 100, 208 IPC_GLB_REPLY_MOD_LOAD_CL_FAILED = 101, 209 IPC_GLB_REPLY_MOD_LOAD_INVALID_HASH = 102, 210 211 IPC_GLB_REPLY_MOD_UNLOAD_INST_EXIST = 103, 212 IPC_GLB_REPLY_MOD_NOT_INITIALIZED = 104, 213 214 IPC_GLB_REPLY_INVALID_CONFIG_PARAM_ID = 120, 215 IPC_GLB_REPLY_INVALID_CONFIG_DATA_LEN = 121, 216 IPC_GLB_REPLY_GATEWAY_NOT_INITIALIZED = 140, 217 IPC_GLB_REPLY_GATEWAY_NOT_EXIST = 141, 218 219 IPC_GLB_REPLY_PPL_NOT_INITIALIZED = 160, 220 IPC_GLB_REPLY_PPL_NOT_EXIST = 161, 221 IPC_GLB_REPLY_PPL_SAVE_FAILED = 162, 222 IPC_GLB_REPLY_PPL_RESTORE_FAILED = 163, 223 224 IPC_MAX_STATUS = ((1<<IPC_IXC_STATUS_BITS)-1) 225 }; 226 227 enum skl_ipc_notification_type { 228 IPC_GLB_NOTIFY_GLITCH = 0, 229 IPC_GLB_NOTIFY_OVERRUN = 1, 230 IPC_GLB_NOTIFY_UNDERRUN = 2, 231 IPC_GLB_NOTIFY_END_STREAM = 3, 232 IPC_GLB_NOTIFY_PHRASE_DETECTED = 4, 233 IPC_GLB_NOTIFY_RESOURCE_EVENT = 5, 234 IPC_GLB_NOTIFY_LOG_BUFFER_STATUS = 6, 235 IPC_GLB_NOTIFY_TIMESTAMP_CAPTURED = 7, 236 IPC_GLB_NOTIFY_FW_READY = 8 237 }; 238 239 /* Module Message Types */ 240 enum skl_ipc_module_msg { 241 IPC_MOD_INIT_INSTANCE = 0, 242 IPC_MOD_CONFIG_GET = 1, 243 IPC_MOD_CONFIG_SET = 2, 244 IPC_MOD_LARGE_CONFIG_GET = 3, 245 IPC_MOD_LARGE_CONFIG_SET = 4, 246 IPC_MOD_BIND = 5, 247 IPC_MOD_UNBIND = 6, 248 IPC_MOD_SET_DX = 7 249 }; 250 251 static void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, 252 size_t tx_size) 253 { 254 if (tx_size) 255 memcpy(msg->tx_data, tx_data, tx_size); 256 } 257 258 static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp) 259 { 260 u32 hipci; 261 262 hipci = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCI); 263 return (hipci & SKL_ADSP_REG_HIPCI_BUSY); 264 } 265 266 /* Lock to be held by caller */ 267 static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) 268 { 269 struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header); 270 271 if (msg->tx_size) 272 sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); 273 sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE, 274 header->extension); 275 sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI, 276 header->primary | SKL_ADSP_REG_HIPCI_BUSY); 277 } 278 279 static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc, 280 u64 ipc_header) 281 { 282 struct ipc_message *msg = NULL; 283 struct skl_ipc_header *header = (struct skl_ipc_header *)(&ipc_header); 284 285 if (list_empty(&ipc->rx_list)) { 286 dev_err(ipc->dev, "ipc: rx list is empty but received 0x%x\n", 287 header->primary); 288 goto out; 289 } 290 291 msg = list_first_entry(&ipc->rx_list, struct ipc_message, list); 292 293 out: 294 return msg; 295 296 } 297 298 static int skl_ipc_process_notification(struct sst_generic_ipc *ipc, 299 struct skl_ipc_header header) 300 { 301 struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); 302 303 if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { 304 switch (IPC_GLB_NOTIFY_TYPE(header.primary)) { 305 306 case IPC_GLB_NOTIFY_UNDERRUN: 307 dev_err(ipc->dev, "FW Underrun %x\n", header.primary); 308 break; 309 310 case IPC_GLB_NOTIFY_RESOURCE_EVENT: 311 dev_err(ipc->dev, "MCPS Budget Violation: %x\n", 312 header.primary); 313 break; 314 315 case IPC_GLB_NOTIFY_FW_READY: 316 skl->boot_complete = true; 317 wake_up(&skl->boot_wait); 318 break; 319 320 default: 321 dev_err(ipc->dev, "ipc: Unhandled error msg=%x", 322 header.primary); 323 break; 324 } 325 } 326 327 return 0; 328 } 329 330 static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, 331 struct skl_ipc_header header) 332 { 333 struct ipc_message *msg; 334 u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK; 335 u64 *ipc_header = (u64 *)(&header); 336 337 msg = skl_ipc_reply_get_msg(ipc, *ipc_header); 338 if (msg == NULL) { 339 dev_dbg(ipc->dev, "ipc: rx list is empty\n"); 340 return; 341 } 342 343 /* first process the header */ 344 switch (reply) { 345 case IPC_GLB_REPLY_SUCCESS: 346 dev_info(ipc->dev, "ipc FW reply %x: success\n", header.primary); 347 break; 348 349 case IPC_GLB_REPLY_OUT_OF_MEMORY: 350 dev_err(ipc->dev, "ipc fw reply: %x: no memory\n", header.primary); 351 msg->errno = -ENOMEM; 352 break; 353 354 case IPC_GLB_REPLY_BUSY: 355 dev_err(ipc->dev, "ipc fw reply: %x: Busy\n", header.primary); 356 msg->errno = -EBUSY; 357 break; 358 359 default: 360 dev_err(ipc->dev, "Unknown ipc reply: 0x%x", reply); 361 msg->errno = -EINVAL; 362 break; 363 } 364 365 if (reply != IPC_GLB_REPLY_SUCCESS) { 366 dev_err(ipc->dev, "ipc FW reply: reply=%d", reply); 367 dev_err(ipc->dev, "FW Error Code: %u\n", 368 ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp)); 369 } 370 371 list_del(&msg->list); 372 sst_ipc_tx_msg_reply_complete(ipc, msg); 373 } 374 375 irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context) 376 { 377 struct sst_dsp *dsp = context; 378 struct skl_sst *skl = sst_dsp_get_thread_context(dsp); 379 struct sst_generic_ipc *ipc = &skl->ipc; 380 struct skl_ipc_header header = {0}; 381 u32 hipcie, hipct, hipcte; 382 int ipc_irq = 0; 383 384 if (dsp->intr_status & SKL_ADSPIS_CL_DMA) 385 skl_cldma_process_intr(dsp); 386 387 /* Here we handle IPC interrupts only */ 388 if (!(dsp->intr_status & SKL_ADSPIS_IPC)) 389 return IRQ_NONE; 390 391 hipcie = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCIE); 392 hipct = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCT); 393 394 /* reply message from DSP */ 395 if (hipcie & SKL_ADSP_REG_HIPCIE_DONE) { 396 sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL, 397 SKL_ADSP_REG_HIPCCTL_DONE, 0); 398 399 /* clear DONE bit - tell DSP we have completed the operation */ 400 sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCIE, 401 SKL_ADSP_REG_HIPCIE_DONE, SKL_ADSP_REG_HIPCIE_DONE); 402 403 ipc_irq = 1; 404 405 /* unmask Done interrupt */ 406 sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL, 407 SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE); 408 } 409 410 /* New message from DSP */ 411 if (hipct & SKL_ADSP_REG_HIPCT_BUSY) { 412 hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE); 413 header.primary = hipct; 414 header.extension = hipcte; 415 dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x", 416 header.primary); 417 dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x", 418 header.extension); 419 420 if (IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) { 421 /* Handle Immediate reply from DSP Core */ 422 skl_ipc_process_reply(ipc, header); 423 } else { 424 dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n"); 425 skl_ipc_process_notification(ipc, header); 426 } 427 /* clear busy interrupt */ 428 sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCT, 429 SKL_ADSP_REG_HIPCT_BUSY, SKL_ADSP_REG_HIPCT_BUSY); 430 ipc_irq = 1; 431 } 432 433 if (ipc_irq == 0) 434 return IRQ_NONE; 435 436 skl_ipc_int_enable(dsp); 437 438 /* continue to send any remaining messages... */ 439 queue_kthread_work(&ipc->kworker, &ipc->kwork); 440 441 return IRQ_HANDLED; 442 } 443 444 void skl_ipc_int_enable(struct sst_dsp *ctx) 445 { 446 sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_ADSPIC, 447 SKL_ADSPIC_IPC, SKL_ADSPIC_IPC); 448 } 449 450 void skl_ipc_int_disable(struct sst_dsp *ctx) 451 { 452 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC, 453 SKL_ADSPIC_IPC, 0); 454 } 455 456 void skl_ipc_op_int_enable(struct sst_dsp *ctx) 457 { 458 /* enable IPC DONE interrupt */ 459 sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL, 460 SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE); 461 462 /* Enable IPC BUSY interrupt */ 463 sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL, 464 SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY); 465 } 466 467 bool skl_ipc_int_status(struct sst_dsp *ctx) 468 { 469 return sst_dsp_shim_read_unlocked(ctx, 470 SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC; 471 } 472 473 int skl_ipc_init(struct device *dev, struct skl_sst *skl) 474 { 475 struct sst_generic_ipc *ipc; 476 int err; 477 478 ipc = &skl->ipc; 479 ipc->dsp = skl->dsp; 480 ipc->dev = dev; 481 482 ipc->tx_data_max_size = SKL_ADSP_W1_SZ; 483 ipc->rx_data_max_size = SKL_ADSP_W0_UP_SZ; 484 485 err = sst_ipc_init(ipc); 486 if (err) 487 return err; 488 489 ipc->ops.tx_msg = skl_ipc_tx_msg; 490 ipc->ops.tx_data_copy = skl_ipc_tx_data_copy; 491 ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy; 492 493 return 0; 494 } 495 496 void skl_ipc_free(struct sst_generic_ipc *ipc) 497 { 498 /* Disable IPC DONE interrupt */ 499 sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL, 500 SKL_ADSP_REG_HIPCCTL_DONE, 0); 501 502 /* Disable IPC BUSY interrupt */ 503 sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL, 504 SKL_ADSP_REG_HIPCCTL_BUSY, 0); 505 506 sst_ipc_fini(ipc); 507 } 508 509 int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc, 510 u16 ppl_mem_size, u8 ppl_type, u8 instance_id) 511 { 512 struct skl_ipc_header header = {0}; 513 u64 *ipc_header = (u64 *)(&header); 514 int ret; 515 516 header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); 517 header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 518 header.primary |= IPC_GLB_TYPE(IPC_GLB_CREATE_PPL); 519 header.primary |= IPC_INSTANCE_ID(instance_id); 520 header.primary |= IPC_PPL_TYPE(ppl_type); 521 header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size); 522 523 dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); 524 ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); 525 if (ret < 0) { 526 dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret); 527 return ret; 528 } 529 530 return ret; 531 } 532 EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline); 533 534 int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) 535 { 536 struct skl_ipc_header header = {0}; 537 u64 *ipc_header = (u64 *)(&header); 538 int ret; 539 540 header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); 541 header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 542 header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL); 543 header.primary |= IPC_INSTANCE_ID(instance_id); 544 545 dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); 546 ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); 547 if (ret < 0) { 548 dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret); 549 return ret; 550 } 551 552 return 0; 553 } 554 EXPORT_SYMBOL_GPL(skl_ipc_delete_pipeline); 555 556 int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc, 557 u8 instance_id, enum skl_ipc_pipeline_state state) 558 { 559 struct skl_ipc_header header = {0}; 560 u64 *ipc_header = (u64 *)(&header); 561 int ret; 562 563 header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); 564 header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 565 header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE); 566 header.primary |= IPC_INSTANCE_ID(instance_id); 567 header.primary |= IPC_PPL_STATE(state); 568 569 dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); 570 ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); 571 if (ret < 0) { 572 dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret); 573 return ret; 574 } 575 return ret; 576 } 577 EXPORT_SYMBOL_GPL(skl_ipc_set_pipeline_state); 578 579 int 580 skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id) 581 { 582 struct skl_ipc_header header = {0}; 583 u64 *ipc_header = (u64 *)(&header); 584 int ret; 585 586 header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); 587 header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 588 header.primary |= IPC_GLB_TYPE(IPC_GLB_SAVE_PPL); 589 header.primary |= IPC_INSTANCE_ID(instance_id); 590 591 header.extension = IPC_DMA_ID(dma_id); 592 dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); 593 ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); 594 if (ret < 0) { 595 dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret); 596 return ret; 597 } 598 599 return ret; 600 } 601 EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline); 602 603 int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) 604 { 605 struct skl_ipc_header header = {0}; 606 u64 *ipc_header = (u64 *)(&header); 607 int ret; 608 609 header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); 610 header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 611 header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL); 612 header.primary |= IPC_INSTANCE_ID(instance_id); 613 614 dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); 615 ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); 616 if (ret < 0) { 617 dev_err(ipc->dev, "ipc: restore pipeline failed, err: %d\n", ret); 618 return ret; 619 } 620 621 return ret; 622 } 623 EXPORT_SYMBOL_GPL(skl_ipc_restore_pipeline); 624 625 int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id, 626 u16 module_id, struct skl_ipc_dxstate_info *dx) 627 { 628 struct skl_ipc_header header = {0}; 629 u64 *ipc_header = (u64 *)(&header); 630 int ret; 631 632 header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); 633 header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 634 header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_DX); 635 header.primary |= IPC_MOD_INSTANCE_ID(instance_id); 636 header.primary |= IPC_MOD_ID(module_id); 637 638 dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, 639 header.primary, header.extension); 640 ret = sst_ipc_tx_message_wait(ipc, *ipc_header, 641 dx, sizeof(dx), NULL, 0); 642 if (ret < 0) { 643 dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret); 644 return ret; 645 } 646 647 return ret; 648 } 649 EXPORT_SYMBOL_GPL(skl_ipc_set_dx); 650 651 int skl_ipc_init_instance(struct sst_generic_ipc *ipc, 652 struct skl_ipc_init_instance_msg *msg, void *param_data) 653 { 654 struct skl_ipc_header header = {0}; 655 u64 *ipc_header = (u64 *)(&header); 656 int ret; 657 u32 *buffer = (u32 *)param_data; 658 /* param_block_size must be in dwords */ 659 u16 param_block_size = msg->param_data_size / sizeof(u32); 660 661 print_hex_dump(KERN_DEBUG, NULL, DUMP_PREFIX_NONE, 662 16, 4, buffer, param_block_size, false); 663 664 header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); 665 header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 666 header.primary |= IPC_GLB_TYPE(IPC_MOD_INIT_INSTANCE); 667 header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); 668 header.primary |= IPC_MOD_ID(msg->module_id); 669 670 header.extension = IPC_CORE_ID(msg->core_id); 671 header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id); 672 header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size); 673 674 dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, 675 header.primary, header.extension); 676 ret = sst_ipc_tx_message_wait(ipc, *ipc_header, param_data, 677 msg->param_data_size, NULL, 0); 678 679 if (ret < 0) { 680 dev_err(ipc->dev, "ipc: init instance failed\n"); 681 return ret; 682 } 683 684 return ret; 685 } 686 EXPORT_SYMBOL_GPL(skl_ipc_init_instance); 687 688 int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, 689 struct skl_ipc_bind_unbind_msg *msg) 690 { 691 struct skl_ipc_header header = {0}; 692 u64 *ipc_header = (u64 *)(&header); 693 u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND; 694 int ret; 695 696 header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); 697 header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 698 header.primary |= IPC_GLB_TYPE(bind_unbind); 699 header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); 700 header.primary |= IPC_MOD_ID(msg->module_id); 701 702 header.extension = IPC_DST_MOD_ID(msg->dst_module_id); 703 header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id); 704 header.extension |= IPC_DST_QUEUE(msg->dst_queue); 705 header.extension |= IPC_SRC_QUEUE(msg->src_queue); 706 707 dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary, 708 header.extension); 709 ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); 710 if (ret < 0) { 711 dev_err(ipc->dev, "ipc: bind/unbind faileden"); 712 return ret; 713 } 714 715 return ret; 716 } 717 EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind); 718 719 int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, 720 struct skl_ipc_large_config_msg *msg, u32 *param) 721 { 722 struct skl_ipc_header header = {0}; 723 u64 *ipc_header = (u64 *)(&header); 724 int ret = 0; 725 size_t sz_remaining, tx_size, data_offset; 726 727 header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); 728 header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 729 header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_SET); 730 header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); 731 header.primary |= IPC_MOD_ID(msg->module_id); 732 733 header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size); 734 header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id); 735 header.extension |= IPC_FINAL_BLOCK(0); 736 header.extension |= IPC_INITIAL_BLOCK(1); 737 738 sz_remaining = msg->param_data_size; 739 data_offset = 0; 740 while (sz_remaining != 0) { 741 tx_size = sz_remaining > SKL_ADSP_W1_SZ 742 ? SKL_ADSP_W1_SZ : sz_remaining; 743 if (tx_size == sz_remaining) 744 header.extension |= IPC_FINAL_BLOCK(1); 745 746 dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__, 747 header.primary, header.extension); 748 dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n", 749 (unsigned)data_offset, (unsigned)tx_size); 750 ret = sst_ipc_tx_message_wait(ipc, *ipc_header, 751 ((char *)param) + data_offset, 752 tx_size, NULL, 0); 753 if (ret < 0) { 754 dev_err(ipc->dev, 755 "ipc: set large config fail, err: %d\n", ret); 756 return ret; 757 } 758 sz_remaining -= tx_size; 759 data_offset = msg->param_data_size - sz_remaining; 760 761 /* clear the fields */ 762 header.extension &= IPC_INITIAL_BLOCK_CLEAR; 763 header.extension &= IPC_DATA_OFFSET_SZ_CLEAR; 764 /* fill the fields */ 765 header.extension |= IPC_INITIAL_BLOCK(0); 766 header.extension |= IPC_DATA_OFFSET_SZ(data_offset); 767 } 768 769 return ret; 770 } 771 EXPORT_SYMBOL_GPL(skl_ipc_set_large_config); 772