1b81fd263SSubhransu S. Prusty /* 2b81fd263SSubhransu S. Prusty * skl-sst-ipc.c - Intel skl IPC Support 3b81fd263SSubhransu S. Prusty * 4b81fd263SSubhransu S. Prusty * Copyright (C) 2014-15, Intel Corporation. 5b81fd263SSubhransu S. Prusty * 6b81fd263SSubhransu S. Prusty * This program is free software; you can redistribute it and/or modify 7b81fd263SSubhransu S. Prusty * it under the terms of the GNU General Public License as version 2, as 8b81fd263SSubhransu S. Prusty * published by the Free Software Foundation. 9b81fd263SSubhransu S. Prusty * 10b81fd263SSubhransu S. Prusty * This program is distributed in the hope that it will be useful, but 11b81fd263SSubhransu S. Prusty * WITHOUT ANY WARRANTY; without even the implied warranty of 12b81fd263SSubhransu S. Prusty * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13b81fd263SSubhransu S. Prusty * General Public License for more details. 14b81fd263SSubhransu S. Prusty */ 15b81fd263SSubhransu S. Prusty #include <linux/device.h> 16b81fd263SSubhransu S. Prusty 17b81fd263SSubhransu S. Prusty #include "../common/sst-dsp.h" 18b81fd263SSubhransu S. Prusty #include "../common/sst-dsp-priv.h" 19721c3e36SDharageswari.R #include "skl.h" 20b81fd263SSubhransu S. Prusty #include "skl-sst-dsp.h" 21b81fd263SSubhransu S. Prusty #include "skl-sst-ipc.h" 22721c3e36SDharageswari.R #include "sound/hdaudio_ext.h" 23b81fd263SSubhransu S. Prusty 24b81fd263SSubhransu S. Prusty 25b81fd263SSubhransu S. Prusty #define IPC_IXC_STATUS_BITS 24 26b81fd263SSubhransu S. Prusty 27b81fd263SSubhransu S. Prusty /* Global Message - Generic */ 28b81fd263SSubhransu S. Prusty #define IPC_GLB_TYPE_SHIFT 24 29b81fd263SSubhransu S. Prusty #define IPC_GLB_TYPE_MASK (0xf << IPC_GLB_TYPE_SHIFT) 30b81fd263SSubhransu S. Prusty #define IPC_GLB_TYPE(x) ((x) << IPC_GLB_TYPE_SHIFT) 31b81fd263SSubhransu S. Prusty 32b81fd263SSubhransu S. Prusty /* Global Message - Reply */ 33b81fd263SSubhransu S. Prusty #define IPC_GLB_REPLY_STATUS_SHIFT 24 34b81fd263SSubhransu S. Prusty #define IPC_GLB_REPLY_STATUS_MASK ((0x1 << IPC_GLB_REPLY_STATUS_SHIFT) - 1) 35b81fd263SSubhransu S. Prusty #define IPC_GLB_REPLY_STATUS(x) ((x) << IPC_GLB_REPLY_STATUS_SHIFT) 36b81fd263SSubhransu S. Prusty 37b81fd263SSubhransu S. Prusty #define IPC_TIMEOUT_MSECS 3000 38b81fd263SSubhransu S. Prusty 39b81fd263SSubhransu S. Prusty #define IPC_EMPTY_LIST_SIZE 8 40b81fd263SSubhransu S. Prusty 41b81fd263SSubhransu S. Prusty #define IPC_MSG_TARGET_SHIFT 30 42b81fd263SSubhransu S. Prusty #define IPC_MSG_TARGET_MASK 0x1 43b81fd263SSubhransu S. Prusty #define IPC_MSG_TARGET(x) (((x) & IPC_MSG_TARGET_MASK) \ 44b81fd263SSubhransu S. Prusty << IPC_MSG_TARGET_SHIFT) 45b81fd263SSubhransu S. Prusty 46b81fd263SSubhransu S. Prusty #define IPC_MSG_DIR_SHIFT 29 47b81fd263SSubhransu S. Prusty #define IPC_MSG_DIR_MASK 0x1 48b81fd263SSubhransu S. Prusty #define IPC_MSG_DIR(x) (((x) & IPC_MSG_DIR_MASK) \ 49b81fd263SSubhransu S. Prusty << IPC_MSG_DIR_SHIFT) 50b81fd263SSubhransu S. Prusty /* Global Notification Message */ 51b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_TYPE_SHIFT 16 52b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_TYPE_MASK 0xFF 53b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_TYPE(x) (((x) >> IPC_GLB_NOTIFY_TYPE_SHIFT) \ 54b81fd263SSubhransu S. Prusty & IPC_GLB_NOTIFY_TYPE_MASK) 55b81fd263SSubhransu S. Prusty 56b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_MSG_TYPE_SHIFT 24 57b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_MSG_TYPE_MASK 0x1F 58b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_MSG_TYPE(x) (((x) >> IPC_GLB_NOTIFY_MSG_TYPE_SHIFT) \ 59b81fd263SSubhransu S. Prusty & IPC_GLB_NOTIFY_MSG_TYPE_MASK) 60b81fd263SSubhransu S. Prusty 61b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_RSP_SHIFT 29 62b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_RSP_MASK 0x1 63b81fd263SSubhransu S. Prusty #define IPC_GLB_NOTIFY_RSP_TYPE(x) (((x) >> IPC_GLB_NOTIFY_RSP_SHIFT) \ 64b81fd263SSubhransu S. Prusty & IPC_GLB_NOTIFY_RSP_MASK) 65b81fd263SSubhransu S. Prusty 66b81fd263SSubhransu S. Prusty /* Pipeline operations */ 67b81fd263SSubhransu S. Prusty 68b81fd263SSubhransu S. Prusty /* Create pipeline message */ 69b81fd263SSubhransu S. Prusty #define IPC_PPL_MEM_SIZE_SHIFT 0 70b81fd263SSubhransu S. Prusty #define IPC_PPL_MEM_SIZE_MASK 0x7FF 71b81fd263SSubhransu S. Prusty #define IPC_PPL_MEM_SIZE(x) (((x) & IPC_PPL_MEM_SIZE_MASK) \ 72b81fd263SSubhransu S. Prusty << IPC_PPL_MEM_SIZE_SHIFT) 73b81fd263SSubhransu S. Prusty 74b81fd263SSubhransu S. Prusty #define IPC_PPL_TYPE_SHIFT 11 75b81fd263SSubhransu S. Prusty #define IPC_PPL_TYPE_MASK 0x1F 76b81fd263SSubhransu S. Prusty #define IPC_PPL_TYPE(x) (((x) & IPC_PPL_TYPE_MASK) \ 77b81fd263SSubhransu S. Prusty << IPC_PPL_TYPE_SHIFT) 78b81fd263SSubhransu S. Prusty 79b81fd263SSubhransu S. Prusty #define IPC_INSTANCE_ID_SHIFT 16 80b81fd263SSubhransu S. Prusty #define IPC_INSTANCE_ID_MASK 0xFF 81b81fd263SSubhransu S. Prusty #define IPC_INSTANCE_ID(x) (((x) & IPC_INSTANCE_ID_MASK) \ 82b81fd263SSubhransu S. Prusty << IPC_INSTANCE_ID_SHIFT) 83b81fd263SSubhransu S. Prusty 848a0cb236SVinod Koul #define IPC_PPL_LP_MODE_SHIFT 0 858a0cb236SVinod Koul #define IPC_PPL_LP_MODE_MASK 0x1 868a0cb236SVinod Koul #define IPC_PPL_LP_MODE(x) (((x) & IPC_PPL_LP_MODE_MASK) \ 878a0cb236SVinod Koul << IPC_PPL_LP_MODE_SHIFT) 888a0cb236SVinod Koul 89b81fd263SSubhransu S. Prusty /* Set pipeline state message */ 90b81fd263SSubhransu S. Prusty #define IPC_PPL_STATE_SHIFT 0 91b81fd263SSubhransu S. Prusty #define IPC_PPL_STATE_MASK 0x1F 92b81fd263SSubhransu S. Prusty #define IPC_PPL_STATE(x) (((x) & IPC_PPL_STATE_MASK) \ 93b81fd263SSubhransu S. Prusty << IPC_PPL_STATE_SHIFT) 94b81fd263SSubhransu S. Prusty 95b81fd263SSubhransu S. Prusty /* Module operations primary register */ 96b81fd263SSubhransu S. Prusty #define IPC_MOD_ID_SHIFT 0 97b81fd263SSubhransu S. Prusty #define IPC_MOD_ID_MASK 0xFFFF 98b81fd263SSubhransu S. Prusty #define IPC_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \ 99b81fd263SSubhransu S. Prusty << IPC_MOD_ID_SHIFT) 100b81fd263SSubhransu S. Prusty 101b81fd263SSubhransu S. Prusty #define IPC_MOD_INSTANCE_ID_SHIFT 16 102b81fd263SSubhransu S. Prusty #define IPC_MOD_INSTANCE_ID_MASK 0xFF 103b81fd263SSubhransu S. Prusty #define IPC_MOD_INSTANCE_ID(x) (((x) & IPC_MOD_INSTANCE_ID_MASK) \ 104b81fd263SSubhransu S. Prusty << IPC_MOD_INSTANCE_ID_SHIFT) 105b81fd263SSubhransu S. Prusty 106b81fd263SSubhransu S. Prusty /* Init instance message extension register */ 107b81fd263SSubhransu S. Prusty #define IPC_PARAM_BLOCK_SIZE_SHIFT 0 108b81fd263SSubhransu S. Prusty #define IPC_PARAM_BLOCK_SIZE_MASK 0xFFFF 109b81fd263SSubhransu S. Prusty #define IPC_PARAM_BLOCK_SIZE(x) (((x) & IPC_PARAM_BLOCK_SIZE_MASK) \ 110b81fd263SSubhransu S. Prusty << IPC_PARAM_BLOCK_SIZE_SHIFT) 111b81fd263SSubhransu S. Prusty 112b81fd263SSubhransu S. Prusty #define IPC_PPL_INSTANCE_ID_SHIFT 16 113b81fd263SSubhransu S. Prusty #define IPC_PPL_INSTANCE_ID_MASK 0xFF 114b81fd263SSubhransu S. Prusty #define IPC_PPL_INSTANCE_ID(x) (((x) & IPC_PPL_INSTANCE_ID_MASK) \ 115b81fd263SSubhransu S. Prusty << IPC_PPL_INSTANCE_ID_SHIFT) 116b81fd263SSubhransu S. Prusty 117b81fd263SSubhransu S. Prusty #define IPC_CORE_ID_SHIFT 24 118b81fd263SSubhransu S. Prusty #define IPC_CORE_ID_MASK 0x1F 119b81fd263SSubhransu S. Prusty #define IPC_CORE_ID(x) (((x) & IPC_CORE_ID_MASK) \ 120b81fd263SSubhransu S. Prusty << IPC_CORE_ID_SHIFT) 121b81fd263SSubhransu S. Prusty 1223d4006cdSSenthilnathan Veppur #define IPC_DOMAIN_SHIFT 28 1233d4006cdSSenthilnathan Veppur #define IPC_DOMAIN_MASK 0x1 1243d4006cdSSenthilnathan Veppur #define IPC_DOMAIN(x) (((x) & IPC_DOMAIN_MASK) \ 1253d4006cdSSenthilnathan Veppur << IPC_DOMAIN_SHIFT) 1263d4006cdSSenthilnathan Veppur 127b81fd263SSubhransu S. Prusty /* Bind/Unbind message extension register */ 128b81fd263SSubhransu S. Prusty #define IPC_DST_MOD_ID_SHIFT 0 129b81fd263SSubhransu S. Prusty #define IPC_DST_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \ 130b81fd263SSubhransu S. Prusty << IPC_DST_MOD_ID_SHIFT) 131b81fd263SSubhransu S. Prusty 132b81fd263SSubhransu S. Prusty #define IPC_DST_MOD_INSTANCE_ID_SHIFT 16 133b81fd263SSubhransu S. Prusty #define IPC_DST_MOD_INSTANCE_ID(x) (((x) & IPC_MOD_INSTANCE_ID_MASK) \ 134b81fd263SSubhransu S. Prusty << IPC_DST_MOD_INSTANCE_ID_SHIFT) 135b81fd263SSubhransu S. Prusty 136b81fd263SSubhransu S. Prusty #define IPC_DST_QUEUE_SHIFT 24 137b81fd263SSubhransu S. Prusty #define IPC_DST_QUEUE_MASK 0x7 138b81fd263SSubhransu S. Prusty #define IPC_DST_QUEUE(x) (((x) & IPC_DST_QUEUE_MASK) \ 139b81fd263SSubhransu S. Prusty << IPC_DST_QUEUE_SHIFT) 140b81fd263SSubhransu S. Prusty 141b81fd263SSubhransu S. Prusty #define IPC_SRC_QUEUE_SHIFT 27 142b81fd263SSubhransu S. Prusty #define IPC_SRC_QUEUE_MASK 0x7 143b81fd263SSubhransu S. Prusty #define IPC_SRC_QUEUE(x) (((x) & IPC_SRC_QUEUE_MASK) \ 144b81fd263SSubhransu S. Prusty << IPC_SRC_QUEUE_SHIFT) 1456c5768b3SDharageswari R /* Load Module count */ 1466c5768b3SDharageswari R #define IPC_LOAD_MODULE_SHIFT 0 1476c5768b3SDharageswari R #define IPC_LOAD_MODULE_MASK 0xFF 1486c5768b3SDharageswari R #define IPC_LOAD_MODULE_CNT(x) (((x) & IPC_LOAD_MODULE_MASK) \ 1496c5768b3SDharageswari R << IPC_LOAD_MODULE_SHIFT) 150b81fd263SSubhransu S. Prusty 151b81fd263SSubhransu S. Prusty /* Save pipeline messgae extension register */ 152b81fd263SSubhransu S. Prusty #define IPC_DMA_ID_SHIFT 0 153b81fd263SSubhransu S. Prusty #define IPC_DMA_ID_MASK 0x1F 154b81fd263SSubhransu S. Prusty #define IPC_DMA_ID(x) (((x) & IPC_DMA_ID_MASK) \ 155b81fd263SSubhransu S. Prusty << IPC_DMA_ID_SHIFT) 156b81fd263SSubhransu S. Prusty /* Large Config message extension register */ 157b81fd263SSubhransu S. Prusty #define IPC_DATA_OFFSET_SZ_SHIFT 0 158b81fd263SSubhransu S. Prusty #define IPC_DATA_OFFSET_SZ_MASK 0xFFFFF 159b81fd263SSubhransu S. Prusty #define IPC_DATA_OFFSET_SZ(x) (((x) & IPC_DATA_OFFSET_SZ_MASK) \ 160b81fd263SSubhransu S. Prusty << IPC_DATA_OFFSET_SZ_SHIFT) 161b81fd263SSubhransu S. Prusty #define IPC_DATA_OFFSET_SZ_CLEAR ~(IPC_DATA_OFFSET_SZ_MASK \ 162b81fd263SSubhransu S. Prusty << IPC_DATA_OFFSET_SZ_SHIFT) 163b81fd263SSubhransu S. Prusty 164b81fd263SSubhransu S. Prusty #define IPC_LARGE_PARAM_ID_SHIFT 20 165b81fd263SSubhransu S. Prusty #define IPC_LARGE_PARAM_ID_MASK 0xFF 166b81fd263SSubhransu S. Prusty #define IPC_LARGE_PARAM_ID(x) (((x) & IPC_LARGE_PARAM_ID_MASK) \ 167b81fd263SSubhransu S. Prusty << IPC_LARGE_PARAM_ID_SHIFT) 168b81fd263SSubhransu S. Prusty 169b81fd263SSubhransu S. Prusty #define IPC_FINAL_BLOCK_SHIFT 28 170b81fd263SSubhransu S. Prusty #define IPC_FINAL_BLOCK_MASK 0x1 171b81fd263SSubhransu S. Prusty #define IPC_FINAL_BLOCK(x) (((x) & IPC_FINAL_BLOCK_MASK) \ 172b81fd263SSubhransu S. Prusty << IPC_FINAL_BLOCK_SHIFT) 173b81fd263SSubhransu S. Prusty 174b81fd263SSubhransu S. Prusty #define IPC_INITIAL_BLOCK_SHIFT 29 175b81fd263SSubhransu S. Prusty #define IPC_INITIAL_BLOCK_MASK 0x1 176b81fd263SSubhransu S. Prusty #define IPC_INITIAL_BLOCK(x) (((x) & IPC_INITIAL_BLOCK_MASK) \ 177b81fd263SSubhransu S. Prusty << IPC_INITIAL_BLOCK_SHIFT) 178b81fd263SSubhransu S. Prusty #define IPC_INITIAL_BLOCK_CLEAR ~(IPC_INITIAL_BLOCK_MASK \ 179b81fd263SSubhransu S. Prusty << IPC_INITIAL_BLOCK_SHIFT) 18041b7523fSPardha Saradhi K /* Set D0ix IPC extension register */ 18141b7523fSPardha Saradhi K #define IPC_D0IX_WAKE_SHIFT 0 18241b7523fSPardha Saradhi K #define IPC_D0IX_WAKE_MASK 0x1 18341b7523fSPardha Saradhi K #define IPC_D0IX_WAKE(x) (((x) & IPC_D0IX_WAKE_MASK) \ 18441b7523fSPardha Saradhi K << IPC_D0IX_WAKE_SHIFT) 18541b7523fSPardha Saradhi K 18641b7523fSPardha Saradhi K #define IPC_D0IX_STREAMING_SHIFT 1 18741b7523fSPardha Saradhi K #define IPC_D0IX_STREAMING_MASK 0x1 18841b7523fSPardha Saradhi K #define IPC_D0IX_STREAMING(x) (((x) & IPC_D0IX_STREAMING_MASK) \ 18941b7523fSPardha Saradhi K << IPC_D0IX_STREAMING_SHIFT) 19041b7523fSPardha Saradhi K 191b81fd263SSubhransu S. Prusty 192b81fd263SSubhransu S. Prusty enum skl_ipc_msg_target { 193b81fd263SSubhransu S. Prusty IPC_FW_GEN_MSG = 0, 194b81fd263SSubhransu S. Prusty IPC_MOD_MSG = 1 195b81fd263SSubhransu S. Prusty }; 196b81fd263SSubhransu S. Prusty 197b81fd263SSubhransu S. Prusty enum skl_ipc_msg_direction { 198b81fd263SSubhransu S. Prusty IPC_MSG_REQUEST = 0, 199b81fd263SSubhransu S. Prusty IPC_MSG_REPLY = 1 200b81fd263SSubhransu S. Prusty }; 201b81fd263SSubhransu S. Prusty 202b81fd263SSubhransu S. Prusty /* Global Message Types */ 203b81fd263SSubhransu S. Prusty enum skl_ipc_glb_type { 204b81fd263SSubhransu S. Prusty IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */ 205b81fd263SSubhransu S. Prusty IPC_GLB_LOAD_MULTIPLE_MODS = 15, 206b81fd263SSubhransu S. Prusty IPC_GLB_UNLOAD_MULTIPLE_MODS = 16, 207b81fd263SSubhransu S. Prusty IPC_GLB_CREATE_PPL = 17, 208b81fd263SSubhransu S. Prusty IPC_GLB_DELETE_PPL = 18, 209b81fd263SSubhransu S. Prusty IPC_GLB_SET_PPL_STATE = 19, 210b81fd263SSubhransu S. Prusty IPC_GLB_GET_PPL_STATE = 20, 211b81fd263SSubhransu S. Prusty IPC_GLB_GET_PPL_CONTEXT_SIZE = 21, 212b81fd263SSubhransu S. Prusty IPC_GLB_SAVE_PPL = 22, 213b81fd263SSubhransu S. Prusty IPC_GLB_RESTORE_PPL = 23, 21420fb2fbdSRamesh Babu IPC_GLB_LOAD_LIBRARY = 24, 215b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY = 26, 216b81fd263SSubhransu S. Prusty IPC_GLB_MAX_IPC_MSG_NUMBER = 31 /* Maximum message number */ 217b81fd263SSubhransu S. Prusty }; 218b81fd263SSubhransu S. Prusty 219b81fd263SSubhransu S. Prusty enum skl_ipc_glb_reply { 220b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_SUCCESS = 0, 221b81fd263SSubhransu S. Prusty 222b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_UNKNOWN_MSG_TYPE = 1, 223b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_ERROR_INVALID_PARAM = 2, 224b81fd263SSubhransu S. Prusty 225b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_BUSY = 3, 226b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_PENDING = 4, 227b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_FAILURE = 5, 228b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_INVALID_REQUEST = 6, 229b81fd263SSubhransu S. Prusty 230b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_OUT_OF_MEMORY = 7, 231b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_OUT_OF_MIPS = 8, 232b81fd263SSubhransu S. Prusty 233b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_INVALID_RESOURCE_ID = 9, 234b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_INVALID_RESOURCE_STATE = 10, 235b81fd263SSubhransu S. Prusty 236b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_MOD_MGMT_ERROR = 100, 237b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_MOD_LOAD_CL_FAILED = 101, 238b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_MOD_LOAD_INVALID_HASH = 102, 239b81fd263SSubhransu S. Prusty 240b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_MOD_UNLOAD_INST_EXIST = 103, 241b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_MOD_NOT_INITIALIZED = 104, 242b81fd263SSubhransu S. Prusty 243b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_INVALID_CONFIG_PARAM_ID = 120, 244b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_INVALID_CONFIG_DATA_LEN = 121, 245b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_GATEWAY_NOT_INITIALIZED = 140, 246b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_GATEWAY_NOT_EXIST = 141, 247b81fd263SSubhransu S. Prusty 248b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_PPL_NOT_INITIALIZED = 160, 249b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_PPL_NOT_EXIST = 161, 250b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_PPL_SAVE_FAILED = 162, 251b81fd263SSubhransu S. Prusty IPC_GLB_REPLY_PPL_RESTORE_FAILED = 163, 252b81fd263SSubhransu S. Prusty 253b81fd263SSubhransu S. Prusty IPC_MAX_STATUS = ((1<<IPC_IXC_STATUS_BITS)-1) 254b81fd263SSubhransu S. Prusty }; 255b81fd263SSubhransu S. Prusty 256b81fd263SSubhransu S. Prusty enum skl_ipc_notification_type { 257b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_GLITCH = 0, 258b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_OVERRUN = 1, 259b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_UNDERRUN = 2, 260b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_END_STREAM = 3, 261b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_PHRASE_DETECTED = 4, 262b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_RESOURCE_EVENT = 5, 263b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_LOG_BUFFER_STATUS = 6, 264b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_TIMESTAMP_CAPTURED = 7, 265b81fd263SSubhransu S. Prusty IPC_GLB_NOTIFY_FW_READY = 8 266b81fd263SSubhransu S. Prusty }; 267b81fd263SSubhransu S. Prusty 268b81fd263SSubhransu S. Prusty /* Module Message Types */ 269b81fd263SSubhransu S. Prusty enum skl_ipc_module_msg { 270b81fd263SSubhransu S. Prusty IPC_MOD_INIT_INSTANCE = 0, 271b81fd263SSubhransu S. Prusty IPC_MOD_CONFIG_GET = 1, 272b81fd263SSubhransu S. Prusty IPC_MOD_CONFIG_SET = 2, 273b81fd263SSubhransu S. Prusty IPC_MOD_LARGE_CONFIG_GET = 3, 274b81fd263SSubhransu S. Prusty IPC_MOD_LARGE_CONFIG_SET = 4, 275b81fd263SSubhransu S. Prusty IPC_MOD_BIND = 5, 276b81fd263SSubhransu S. Prusty IPC_MOD_UNBIND = 6, 27741b7523fSPardha Saradhi K IPC_MOD_SET_DX = 7, 27841b7523fSPardha Saradhi K IPC_MOD_SET_D0IX = 8 279b81fd263SSubhransu S. Prusty }; 280b81fd263SSubhransu S. Prusty 281b81fd263SSubhransu S. Prusty static void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, 282b81fd263SSubhransu S. Prusty size_t tx_size) 283b81fd263SSubhransu S. Prusty { 284b81fd263SSubhransu S. Prusty if (tx_size) 285b81fd263SSubhransu S. Prusty memcpy(msg->tx_data, tx_data, tx_size); 286b81fd263SSubhransu S. Prusty } 287b81fd263SSubhransu S. Prusty 288b81fd263SSubhransu S. Prusty static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp) 289b81fd263SSubhransu S. Prusty { 290b81fd263SSubhransu S. Prusty u32 hipci; 291b81fd263SSubhransu S. Prusty 292b81fd263SSubhransu S. Prusty hipci = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCI); 293b81fd263SSubhransu S. Prusty return (hipci & SKL_ADSP_REG_HIPCI_BUSY); 294b81fd263SSubhransu S. Prusty } 295b81fd263SSubhransu S. Prusty 296b81fd263SSubhransu S. Prusty /* Lock to be held by caller */ 297b81fd263SSubhransu S. Prusty static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) 298b81fd263SSubhransu S. Prusty { 299b81fd263SSubhransu S. Prusty struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header); 300b81fd263SSubhransu S. Prusty 301b81fd263SSubhransu S. Prusty if (msg->tx_size) 302b81fd263SSubhransu S. Prusty sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); 303b81fd263SSubhransu S. Prusty sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE, 304b81fd263SSubhransu S. Prusty header->extension); 305b81fd263SSubhransu S. Prusty sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI, 306b81fd263SSubhransu S. Prusty header->primary | SKL_ADSP_REG_HIPCI_BUSY); 307b81fd263SSubhransu S. Prusty } 308b81fd263SSubhransu S. Prusty 309a83e3b4cSVinod Koul int skl_ipc_check_D0i0(struct sst_dsp *dsp, bool state) 310a83e3b4cSVinod Koul { 311a83e3b4cSVinod Koul int ret; 312a83e3b4cSVinod Koul 313a83e3b4cSVinod Koul /* check D0i3 support */ 314a83e3b4cSVinod Koul if (!dsp->fw_ops.set_state_D0i0) 315a83e3b4cSVinod Koul return 0; 316a83e3b4cSVinod Koul 317a83e3b4cSVinod Koul /* Attempt D0i0 or D0i3 based on state */ 318a83e3b4cSVinod Koul if (state) 319a83e3b4cSVinod Koul ret = dsp->fw_ops.set_state_D0i0(dsp); 320a83e3b4cSVinod Koul else 321a83e3b4cSVinod Koul ret = dsp->fw_ops.set_state_D0i3(dsp); 322a83e3b4cSVinod Koul 323a83e3b4cSVinod Koul return ret; 324a83e3b4cSVinod Koul } 325a83e3b4cSVinod Koul 326b81fd263SSubhransu S. Prusty static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc, 327b81fd263SSubhransu S. Prusty u64 ipc_header) 328b81fd263SSubhransu S. Prusty { 329b81fd263SSubhransu S. Prusty struct ipc_message *msg = NULL; 330b81fd263SSubhransu S. Prusty struct skl_ipc_header *header = (struct skl_ipc_header *)(&ipc_header); 331b81fd263SSubhransu S. Prusty 332b81fd263SSubhransu S. Prusty if (list_empty(&ipc->rx_list)) { 333b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: rx list is empty but received 0x%x\n", 334b81fd263SSubhransu S. Prusty header->primary); 335b81fd263SSubhransu S. Prusty goto out; 336b81fd263SSubhransu S. Prusty } 337b81fd263SSubhransu S. Prusty 338b81fd263SSubhransu S. Prusty msg = list_first_entry(&ipc->rx_list, struct ipc_message, list); 339b81fd263SSubhransu S. Prusty 340b81fd263SSubhransu S. Prusty out: 341b81fd263SSubhransu S. Prusty return msg; 342b81fd263SSubhransu S. Prusty 343b81fd263SSubhransu S. Prusty } 344b81fd263SSubhransu S. Prusty 345b81fd263SSubhransu S. Prusty static int skl_ipc_process_notification(struct sst_generic_ipc *ipc, 346b81fd263SSubhransu S. Prusty struct skl_ipc_header header) 347b81fd263SSubhransu S. Prusty { 348b81fd263SSubhransu S. Prusty struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); 349b81fd263SSubhransu S. Prusty 350b81fd263SSubhransu S. Prusty if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { 351b81fd263SSubhransu S. Prusty switch (IPC_GLB_NOTIFY_TYPE(header.primary)) { 352b81fd263SSubhransu S. Prusty 353b81fd263SSubhransu S. Prusty case IPC_GLB_NOTIFY_UNDERRUN: 354b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "FW Underrun %x\n", header.primary); 355b81fd263SSubhransu S. Prusty break; 356b81fd263SSubhransu S. Prusty 357b81fd263SSubhransu S. Prusty case IPC_GLB_NOTIFY_RESOURCE_EVENT: 358b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "MCPS Budget Violation: %x\n", 359b81fd263SSubhransu S. Prusty header.primary); 360b81fd263SSubhransu S. Prusty break; 361b81fd263SSubhransu S. Prusty 362b81fd263SSubhransu S. Prusty case IPC_GLB_NOTIFY_FW_READY: 363b81fd263SSubhransu S. Prusty skl->boot_complete = true; 364b81fd263SSubhransu S. Prusty wake_up(&skl->boot_wait); 365b81fd263SSubhransu S. Prusty break; 366b81fd263SSubhransu S. Prusty 367721c3e36SDharageswari.R case IPC_GLB_NOTIFY_PHRASE_DETECTED: 368721c3e36SDharageswari.R dev_dbg(ipc->dev, "***** Phrase Detected **********\n"); 369721c3e36SDharageswari.R 370721c3e36SDharageswari.R /* 371721c3e36SDharageswari.R * Per HW recomendation, After phrase detection, 372721c3e36SDharageswari.R * clear the CGCTL.MISCBDCGE. 373721c3e36SDharageswari.R * 374721c3e36SDharageswari.R * This will be set back on stream closure 375721c3e36SDharageswari.R */ 376721c3e36SDharageswari.R skl->enable_miscbdcge(ipc->dev, false); 377721c3e36SDharageswari.R skl->miscbdcg_disabled = true; 378721c3e36SDharageswari.R break; 379721c3e36SDharageswari.R 380b81fd263SSubhransu S. Prusty default: 381ecd286a9SColin Ian King dev_err(ipc->dev, "ipc: Unhandled error msg=%x\n", 382b81fd263SSubhransu S. Prusty header.primary); 383b81fd263SSubhransu S. Prusty break; 384b81fd263SSubhransu S. Prusty } 385b81fd263SSubhransu S. Prusty } 386b81fd263SSubhransu S. Prusty 387b81fd263SSubhransu S. Prusty return 0; 388b81fd263SSubhransu S. Prusty } 389b81fd263SSubhransu S. Prusty 390b81fd263SSubhransu S. Prusty static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, 391b81fd263SSubhransu S. Prusty struct skl_ipc_header header) 392b81fd263SSubhransu S. Prusty { 393b81fd263SSubhransu S. Prusty struct ipc_message *msg; 394b81fd263SSubhransu S. Prusty u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK; 395b81fd263SSubhransu S. Prusty u64 *ipc_header = (u64 *)(&header); 396b81fd263SSubhransu S. Prusty 397b81fd263SSubhransu S. Prusty msg = skl_ipc_reply_get_msg(ipc, *ipc_header); 398b81fd263SSubhransu S. Prusty if (msg == NULL) { 399b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "ipc: rx list is empty\n"); 400b81fd263SSubhransu S. Prusty return; 401b81fd263SSubhransu S. Prusty } 402b81fd263SSubhransu S. Prusty 403b81fd263SSubhransu S. Prusty /* first process the header */ 404b81fd263SSubhransu S. Prusty switch (reply) { 405b81fd263SSubhransu S. Prusty case IPC_GLB_REPLY_SUCCESS: 40691c18325SVedang Patel dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary); 407cce1c7f3SMousami Jana /* copy the rx data from the mailbox */ 408cce1c7f3SMousami Jana sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size); 409b81fd263SSubhransu S. Prusty break; 410b81fd263SSubhransu S. Prusty 411b81fd263SSubhransu S. Prusty case IPC_GLB_REPLY_OUT_OF_MEMORY: 412b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc fw reply: %x: no memory\n", header.primary); 413b81fd263SSubhransu S. Prusty msg->errno = -ENOMEM; 414b81fd263SSubhransu S. Prusty break; 415b81fd263SSubhransu S. Prusty 416b81fd263SSubhransu S. Prusty case IPC_GLB_REPLY_BUSY: 417b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc fw reply: %x: Busy\n", header.primary); 418b81fd263SSubhransu S. Prusty msg->errno = -EBUSY; 419b81fd263SSubhransu S. Prusty break; 420b81fd263SSubhransu S. Prusty 421b81fd263SSubhransu S. Prusty default: 422ecd286a9SColin Ian King dev_err(ipc->dev, "Unknown ipc reply: 0x%x\n", reply); 423b81fd263SSubhransu S. Prusty msg->errno = -EINVAL; 424b81fd263SSubhransu S. Prusty break; 425b81fd263SSubhransu S. Prusty } 426b81fd263SSubhransu S. Prusty 42728f3b6f1SOmair M Abdullah if (reply != IPC_GLB_REPLY_SUCCESS) { 428ecd286a9SColin Ian King dev_err(ipc->dev, "ipc FW reply: reply=%d\n", reply); 42928f3b6f1SOmair M Abdullah dev_err(ipc->dev, "FW Error Code: %u\n", 43028f3b6f1SOmair M Abdullah ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp)); 43128f3b6f1SOmair M Abdullah } 43228f3b6f1SOmair M Abdullah 433b81fd263SSubhransu S. Prusty list_del(&msg->list); 434b81fd263SSubhransu S. Prusty sst_ipc_tx_msg_reply_complete(ipc, msg); 435b81fd263SSubhransu S. Prusty } 436b81fd263SSubhransu S. Prusty 437b81fd263SSubhransu S. Prusty irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context) 438b81fd263SSubhransu S. Prusty { 439b81fd263SSubhransu S. Prusty struct sst_dsp *dsp = context; 440b81fd263SSubhransu S. Prusty struct skl_sst *skl = sst_dsp_get_thread_context(dsp); 441b81fd263SSubhransu S. Prusty struct sst_generic_ipc *ipc = &skl->ipc; 442b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0}; 443b81fd263SSubhransu S. Prusty u32 hipcie, hipct, hipcte; 444b81fd263SSubhransu S. Prusty int ipc_irq = 0; 445b81fd263SSubhransu S. Prusty 4466cb00333SSubhransu S. Prusty if (dsp->intr_status & SKL_ADSPIS_CL_DMA) 4476cb00333SSubhransu S. Prusty skl_cldma_process_intr(dsp); 4486cb00333SSubhransu S. Prusty 449b81fd263SSubhransu S. Prusty /* Here we handle IPC interrupts only */ 450b81fd263SSubhransu S. Prusty if (!(dsp->intr_status & SKL_ADSPIS_IPC)) 451b81fd263SSubhransu S. Prusty return IRQ_NONE; 452b81fd263SSubhransu S. Prusty 453b81fd263SSubhransu S. Prusty hipcie = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCIE); 454b81fd263SSubhransu S. Prusty hipct = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCT); 455b81fd263SSubhransu S. Prusty 456b81fd263SSubhransu S. Prusty /* reply message from DSP */ 457b81fd263SSubhransu S. Prusty if (hipcie & SKL_ADSP_REG_HIPCIE_DONE) { 458b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL, 459b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCCTL_DONE, 0); 460b81fd263SSubhransu S. Prusty 461b81fd263SSubhransu S. Prusty /* clear DONE bit - tell DSP we have completed the operation */ 462b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCIE, 463b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCIE_DONE, SKL_ADSP_REG_HIPCIE_DONE); 464b81fd263SSubhransu S. Prusty 465b81fd263SSubhransu S. Prusty ipc_irq = 1; 466b81fd263SSubhransu S. Prusty 467b81fd263SSubhransu S. Prusty /* unmask Done interrupt */ 468b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL, 469b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE); 470b81fd263SSubhransu S. Prusty } 471b81fd263SSubhransu S. Prusty 472b81fd263SSubhransu S. Prusty /* New message from DSP */ 473b81fd263SSubhransu S. Prusty if (hipct & SKL_ADSP_REG_HIPCT_BUSY) { 474b81fd263SSubhransu S. Prusty hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE); 475b81fd263SSubhransu S. Prusty header.primary = hipct; 476b81fd263SSubhransu S. Prusty header.extension = hipcte; 477ecd286a9SColin Ian King dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x\n", 478b81fd263SSubhransu S. Prusty header.primary); 479ecd286a9SColin Ian King dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x\n", 480b81fd263SSubhransu S. Prusty header.extension); 481b81fd263SSubhransu S. Prusty 482b81fd263SSubhransu S. Prusty if (IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) { 483b81fd263SSubhransu S. Prusty /* Handle Immediate reply from DSP Core */ 484b81fd263SSubhransu S. Prusty skl_ipc_process_reply(ipc, header); 485b81fd263SSubhransu S. Prusty } else { 486b81fd263SSubhransu S. Prusty dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n"); 487b81fd263SSubhransu S. Prusty skl_ipc_process_notification(ipc, header); 488b81fd263SSubhransu S. Prusty } 489b81fd263SSubhransu S. Prusty /* clear busy interrupt */ 490b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCT, 491b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCT_BUSY, SKL_ADSP_REG_HIPCT_BUSY); 492b81fd263SSubhransu S. Prusty ipc_irq = 1; 493b81fd263SSubhransu S. Prusty } 494b81fd263SSubhransu S. Prusty 495b81fd263SSubhransu S. Prusty if (ipc_irq == 0) 496b81fd263SSubhransu S. Prusty return IRQ_NONE; 497b81fd263SSubhransu S. Prusty 498b81fd263SSubhransu S. Prusty skl_ipc_int_enable(dsp); 499b81fd263SSubhransu S. Prusty 500b81fd263SSubhransu S. Prusty /* continue to send any remaining messages... */ 5013989144fSPetr Mladek kthread_queue_work(&ipc->kworker, &ipc->kwork); 502b81fd263SSubhransu S. Prusty 503b81fd263SSubhransu S. Prusty return IRQ_HANDLED; 504b81fd263SSubhransu S. Prusty } 505b81fd263SSubhransu S. Prusty 506b81fd263SSubhransu S. Prusty void skl_ipc_int_enable(struct sst_dsp *ctx) 507b81fd263SSubhransu S. Prusty { 508b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_ADSPIC, 509b81fd263SSubhransu S. Prusty SKL_ADSPIC_IPC, SKL_ADSPIC_IPC); 510b81fd263SSubhransu S. Prusty } 511b81fd263SSubhransu S. Prusty 512b81fd263SSubhransu S. Prusty void skl_ipc_int_disable(struct sst_dsp *ctx) 513b81fd263SSubhransu S. Prusty { 514b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC, 515b81fd263SSubhransu S. Prusty SKL_ADSPIC_IPC, 0); 516b81fd263SSubhransu S. Prusty } 517b81fd263SSubhransu S. Prusty 518b81fd263SSubhransu S. Prusty void skl_ipc_op_int_enable(struct sst_dsp *ctx) 519b81fd263SSubhransu S. Prusty { 520b81fd263SSubhransu S. Prusty /* enable IPC DONE interrupt */ 521b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL, 522b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE); 523b81fd263SSubhransu S. Prusty 524b81fd263SSubhransu S. Prusty /* Enable IPC BUSY interrupt */ 525b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL, 526b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY); 527b81fd263SSubhransu S. Prusty } 528b81fd263SSubhransu S. Prusty 52984c9e283SJeeja KP void skl_ipc_op_int_disable(struct sst_dsp *ctx) 53084c9e283SJeeja KP { 53184c9e283SJeeja KP /* disable IPC DONE interrupt */ 53284c9e283SJeeja KP sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL, 53384c9e283SJeeja KP SKL_ADSP_REG_HIPCCTL_DONE, 0); 53484c9e283SJeeja KP 53584c9e283SJeeja KP /* Disable IPC BUSY interrupt */ 53684c9e283SJeeja KP sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL, 53784c9e283SJeeja KP SKL_ADSP_REG_HIPCCTL_BUSY, 0); 53884c9e283SJeeja KP 53984c9e283SJeeja KP } 54084c9e283SJeeja KP 541b81fd263SSubhransu S. Prusty bool skl_ipc_int_status(struct sst_dsp *ctx) 542b81fd263SSubhransu S. Prusty { 543b81fd263SSubhransu S. Prusty return sst_dsp_shim_read_unlocked(ctx, 544b81fd263SSubhransu S. Prusty SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC; 545b81fd263SSubhransu S. Prusty } 546b81fd263SSubhransu S. Prusty 547b81fd263SSubhransu S. Prusty int skl_ipc_init(struct device *dev, struct skl_sst *skl) 548b81fd263SSubhransu S. Prusty { 549b81fd263SSubhransu S. Prusty struct sst_generic_ipc *ipc; 550b81fd263SSubhransu S. Prusty int err; 551b81fd263SSubhransu S. Prusty 552b81fd263SSubhransu S. Prusty ipc = &skl->ipc; 553b81fd263SSubhransu S. Prusty ipc->dsp = skl->dsp; 554b81fd263SSubhransu S. Prusty ipc->dev = dev; 555b81fd263SSubhransu S. Prusty 556b81fd263SSubhransu S. Prusty ipc->tx_data_max_size = SKL_ADSP_W1_SZ; 557b81fd263SSubhransu S. Prusty ipc->rx_data_max_size = SKL_ADSP_W0_UP_SZ; 558b81fd263SSubhransu S. Prusty 559b81fd263SSubhransu S. Prusty err = sst_ipc_init(ipc); 560b81fd263SSubhransu S. Prusty if (err) 561b81fd263SSubhransu S. Prusty return err; 562b81fd263SSubhransu S. Prusty 563b81fd263SSubhransu S. Prusty ipc->ops.tx_msg = skl_ipc_tx_msg; 564b81fd263SSubhransu S. Prusty ipc->ops.tx_data_copy = skl_ipc_tx_data_copy; 565b81fd263SSubhransu S. Prusty ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy; 566b81fd263SSubhransu S. Prusty 567b81fd263SSubhransu S. Prusty return 0; 568b81fd263SSubhransu S. Prusty } 569b81fd263SSubhransu S. Prusty 570b81fd263SSubhransu S. Prusty void skl_ipc_free(struct sst_generic_ipc *ipc) 571b81fd263SSubhransu S. Prusty { 572b81fd263SSubhransu S. Prusty /* Disable IPC DONE interrupt */ 573b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL, 574b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCCTL_DONE, 0); 575b81fd263SSubhransu S. Prusty 576b81fd263SSubhransu S. Prusty /* Disable IPC BUSY interrupt */ 577b81fd263SSubhransu S. Prusty sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL, 578b81fd263SSubhransu S. Prusty SKL_ADSP_REG_HIPCCTL_BUSY, 0); 579a750ba5fSSubhransu S. Prusty 580a750ba5fSSubhransu S. Prusty sst_ipc_fini(ipc); 581b81fd263SSubhransu S. Prusty } 582b81fd263SSubhransu S. Prusty 583b81fd263SSubhransu S. Prusty int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc, 5848a0cb236SVinod Koul u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode) 585b81fd263SSubhransu S. Prusty { 586b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0}; 587b81fd263SSubhransu S. Prusty u64 *ipc_header = (u64 *)(&header); 588b81fd263SSubhransu S. Prusty int ret; 589b81fd263SSubhransu S. Prusty 590b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); 591b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 592b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_GLB_CREATE_PPL); 593b81fd263SSubhransu S. Prusty header.primary |= IPC_INSTANCE_ID(instance_id); 594b81fd263SSubhransu S. Prusty header.primary |= IPC_PPL_TYPE(ppl_type); 595b81fd263SSubhransu S. Prusty header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size); 596b81fd263SSubhransu S. Prusty 5978a0cb236SVinod Koul header.extension = IPC_PPL_LP_MODE(lp_mode); 5988a0cb236SVinod Koul 599b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); 600b81fd263SSubhransu S. Prusty ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); 601b81fd263SSubhransu S. Prusty if (ret < 0) { 602b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret); 603b81fd263SSubhransu S. Prusty return ret; 604b81fd263SSubhransu S. Prusty } 605b81fd263SSubhransu S. Prusty 606b81fd263SSubhransu S. Prusty return ret; 607b81fd263SSubhransu S. Prusty } 608b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline); 609b81fd263SSubhransu S. Prusty 610b81fd263SSubhransu S. Prusty int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) 611b81fd263SSubhransu S. Prusty { 612b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0}; 613b81fd263SSubhransu S. Prusty u64 *ipc_header = (u64 *)(&header); 614b81fd263SSubhransu S. Prusty int ret; 615b81fd263SSubhransu S. Prusty 616b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); 617b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 618b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL); 619b81fd263SSubhransu S. Prusty header.primary |= IPC_INSTANCE_ID(instance_id); 620b81fd263SSubhransu S. Prusty 621b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); 622b81fd263SSubhransu S. Prusty ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); 623b81fd263SSubhransu S. Prusty if (ret < 0) { 624b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret); 625b81fd263SSubhransu S. Prusty return ret; 626b81fd263SSubhransu S. Prusty } 627b81fd263SSubhransu S. Prusty 628b81fd263SSubhransu S. Prusty return 0; 629b81fd263SSubhransu S. Prusty } 630b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_delete_pipeline); 631b81fd263SSubhransu S. Prusty 632b81fd263SSubhransu S. Prusty int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc, 633b81fd263SSubhransu S. Prusty u8 instance_id, enum skl_ipc_pipeline_state state) 634b81fd263SSubhransu S. Prusty { 635b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0}; 636b81fd263SSubhransu S. Prusty u64 *ipc_header = (u64 *)(&header); 637b81fd263SSubhransu S. Prusty int ret; 638b81fd263SSubhransu S. Prusty 639b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); 640b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 641b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE); 642b81fd263SSubhransu S. Prusty header.primary |= IPC_INSTANCE_ID(instance_id); 643b81fd263SSubhransu S. Prusty header.primary |= IPC_PPL_STATE(state); 644b81fd263SSubhransu S. Prusty 645b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); 646b81fd263SSubhransu S. Prusty ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); 647b81fd263SSubhransu S. Prusty if (ret < 0) { 648b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret); 649b81fd263SSubhransu S. Prusty return ret; 650b81fd263SSubhransu S. Prusty } 651b81fd263SSubhransu S. Prusty return ret; 652b81fd263SSubhransu S. Prusty } 653b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_set_pipeline_state); 654b81fd263SSubhransu S. Prusty 655b81fd263SSubhransu S. Prusty int 656b81fd263SSubhransu S. Prusty skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id) 657b81fd263SSubhransu S. Prusty { 658b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0}; 659b81fd263SSubhransu S. Prusty u64 *ipc_header = (u64 *)(&header); 660b81fd263SSubhransu S. Prusty int ret; 661b81fd263SSubhransu S. Prusty 662b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); 663b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 664b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_GLB_SAVE_PPL); 665b81fd263SSubhransu S. Prusty header.primary |= IPC_INSTANCE_ID(instance_id); 666b81fd263SSubhransu S. Prusty 667b81fd263SSubhransu S. Prusty header.extension = IPC_DMA_ID(dma_id); 668b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); 669b81fd263SSubhransu S. Prusty ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); 670b81fd263SSubhransu S. Prusty if (ret < 0) { 671b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret); 672b81fd263SSubhransu S. Prusty return ret; 673b81fd263SSubhransu S. Prusty } 674b81fd263SSubhransu S. Prusty 675b81fd263SSubhransu S. Prusty return ret; 676b81fd263SSubhransu S. Prusty } 677b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline); 678b81fd263SSubhransu S. Prusty 679b81fd263SSubhransu S. Prusty int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) 680b81fd263SSubhransu S. Prusty { 681b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0}; 682b81fd263SSubhransu S. Prusty u64 *ipc_header = (u64 *)(&header); 683b81fd263SSubhransu S. Prusty int ret; 684b81fd263SSubhransu S. Prusty 685b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); 686b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 687b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL); 688b81fd263SSubhransu S. Prusty header.primary |= IPC_INSTANCE_ID(instance_id); 689b81fd263SSubhransu S. Prusty 690b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); 691b81fd263SSubhransu S. Prusty ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); 692b81fd263SSubhransu S. Prusty if (ret < 0) { 693b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: restore pipeline failed, err: %d\n", ret); 694b81fd263SSubhransu S. Prusty return ret; 695b81fd263SSubhransu S. Prusty } 696b81fd263SSubhransu S. Prusty 697b81fd263SSubhransu S. Prusty return ret; 698b81fd263SSubhransu S. Prusty } 699b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_restore_pipeline); 700b81fd263SSubhransu S. Prusty 701b81fd263SSubhransu S. Prusty int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id, 702b81fd263SSubhransu S. Prusty u16 module_id, struct skl_ipc_dxstate_info *dx) 703b81fd263SSubhransu S. Prusty { 704b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0}; 705b81fd263SSubhransu S. Prusty u64 *ipc_header = (u64 *)(&header); 706b81fd263SSubhransu S. Prusty int ret; 707b81fd263SSubhransu S. Prusty 708b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); 709b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 710b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_DX); 711b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_INSTANCE_ID(instance_id); 712b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_ID(module_id); 713b81fd263SSubhransu S. Prusty 714b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, 715b81fd263SSubhransu S. Prusty header.primary, header.extension); 716b81fd263SSubhransu S. Prusty ret = sst_ipc_tx_message_wait(ipc, *ipc_header, 717aaec7e9fSVincent Stehlé dx, sizeof(*dx), NULL, 0); 718b81fd263SSubhransu S. Prusty if (ret < 0) { 719b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret); 720b81fd263SSubhransu S. Prusty return ret; 721b81fd263SSubhransu S. Prusty } 722b81fd263SSubhransu S. Prusty 723b81fd263SSubhransu S. Prusty return ret; 724b81fd263SSubhransu S. Prusty } 725b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_set_dx); 726b81fd263SSubhransu S. Prusty 727b81fd263SSubhransu S. Prusty int skl_ipc_init_instance(struct sst_generic_ipc *ipc, 728b81fd263SSubhransu S. Prusty struct skl_ipc_init_instance_msg *msg, void *param_data) 729b81fd263SSubhransu S. Prusty { 730b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0}; 731b81fd263SSubhransu S. Prusty u64 *ipc_header = (u64 *)(&header); 732b81fd263SSubhransu S. Prusty int ret; 733b81fd263SSubhransu S. Prusty u32 *buffer = (u32 *)param_data; 734b81fd263SSubhransu S. Prusty /* param_block_size must be in dwords */ 735b81fd263SSubhransu S. Prusty u16 param_block_size = msg->param_data_size / sizeof(u32); 736b81fd263SSubhransu S. Prusty 73796bd6033SVedang Patel print_hex_dump_debug("Param data:", DUMP_PREFIX_NONE, 738b81fd263SSubhransu S. Prusty 16, 4, buffer, param_block_size, false); 739b81fd263SSubhransu S. Prusty 740b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); 741b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 742b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_MOD_INIT_INSTANCE); 743b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); 744b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_ID(msg->module_id); 745b81fd263SSubhransu S. Prusty 746b81fd263SSubhransu S. Prusty header.extension = IPC_CORE_ID(msg->core_id); 747b81fd263SSubhransu S. Prusty header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id); 748b81fd263SSubhransu S. Prusty header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size); 7493d4006cdSSenthilnathan Veppur header.extension |= IPC_DOMAIN(msg->domain); 750b81fd263SSubhransu S. Prusty 751b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, 752b81fd263SSubhransu S. Prusty header.primary, header.extension); 753b81fd263SSubhransu S. Prusty ret = sst_ipc_tx_message_wait(ipc, *ipc_header, param_data, 754b81fd263SSubhransu S. Prusty msg->param_data_size, NULL, 0); 755b81fd263SSubhransu S. Prusty 756b81fd263SSubhransu S. Prusty if (ret < 0) { 757b81fd263SSubhransu S. Prusty dev_err(ipc->dev, "ipc: init instance failed\n"); 758b81fd263SSubhransu S. Prusty return ret; 759b81fd263SSubhransu S. Prusty } 760b81fd263SSubhransu S. Prusty 761b81fd263SSubhransu S. Prusty return ret; 762b81fd263SSubhransu S. Prusty } 763b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_init_instance); 764b81fd263SSubhransu S. Prusty 765b81fd263SSubhransu S. Prusty int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, 766b81fd263SSubhransu S. Prusty struct skl_ipc_bind_unbind_msg *msg) 767b81fd263SSubhransu S. Prusty { 768b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0}; 769b81fd263SSubhransu S. Prusty u64 *ipc_header = (u64 *)(&header); 770b81fd263SSubhransu S. Prusty u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND; 771b81fd263SSubhransu S. Prusty int ret; 772b81fd263SSubhransu S. Prusty 773b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); 774b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 775b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(bind_unbind); 776b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); 777b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_ID(msg->module_id); 778b81fd263SSubhransu S. Prusty 779b81fd263SSubhransu S. Prusty header.extension = IPC_DST_MOD_ID(msg->dst_module_id); 780b81fd263SSubhransu S. Prusty header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id); 781b81fd263SSubhransu S. Prusty header.extension |= IPC_DST_QUEUE(msg->dst_queue); 782b81fd263SSubhransu S. Prusty header.extension |= IPC_SRC_QUEUE(msg->src_queue); 783b81fd263SSubhransu S. Prusty 784b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary, 785b81fd263SSubhransu S. Prusty header.extension); 786b81fd263SSubhransu S. Prusty ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); 787b81fd263SSubhransu S. Prusty if (ret < 0) { 788ecd286a9SColin Ian King dev_err(ipc->dev, "ipc: bind/unbind failed\n"); 789b81fd263SSubhransu S. Prusty return ret; 790b81fd263SSubhransu S. Prusty } 791b81fd263SSubhransu S. Prusty 792b81fd263SSubhransu S. Prusty return ret; 793b81fd263SSubhransu S. Prusty } 794b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind); 795b81fd263SSubhransu S. Prusty 7966c5768b3SDharageswari R /* 7976c5768b3SDharageswari R * In order to load a module we need to send IPC to initiate that. DMA will 7986c5768b3SDharageswari R * performed to load the module memory. The FW supports multiple module load 7996c5768b3SDharageswari R * at single shot, so we can send IPC with N modules represented by 8006c5768b3SDharageswari R * module_cnt 8016c5768b3SDharageswari R */ 8026c5768b3SDharageswari R int skl_ipc_load_modules(struct sst_generic_ipc *ipc, 8036c5768b3SDharageswari R u8 module_cnt, void *data) 8046c5768b3SDharageswari R { 8056c5768b3SDharageswari R struct skl_ipc_header header = {0}; 8066c5768b3SDharageswari R u64 *ipc_header = (u64 *)(&header); 8076c5768b3SDharageswari R int ret; 8086c5768b3SDharageswari R 8096c5768b3SDharageswari R header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); 8106c5768b3SDharageswari R header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 8116c5768b3SDharageswari R header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS); 8126c5768b3SDharageswari R header.primary |= IPC_LOAD_MODULE_CNT(module_cnt); 8136c5768b3SDharageswari R 8146c5768b3SDharageswari R ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data, 8156c5768b3SDharageswari R (sizeof(u16) * module_cnt), NULL, 0); 8166c5768b3SDharageswari R if (ret < 0) 8176c5768b3SDharageswari R dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret); 8186c5768b3SDharageswari R 8196c5768b3SDharageswari R return ret; 8206c5768b3SDharageswari R } 8216c5768b3SDharageswari R EXPORT_SYMBOL_GPL(skl_ipc_load_modules); 8226c5768b3SDharageswari R 8236c5768b3SDharageswari R int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt, 8246c5768b3SDharageswari R void *data) 8256c5768b3SDharageswari R { 8266c5768b3SDharageswari R struct skl_ipc_header header = {0}; 8276c5768b3SDharageswari R u64 *ipc_header = (u64 *)(&header); 8286c5768b3SDharageswari R int ret; 8296c5768b3SDharageswari R 8306c5768b3SDharageswari R header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); 8316c5768b3SDharageswari R header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 8326c5768b3SDharageswari R header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS); 8336c5768b3SDharageswari R header.primary |= IPC_LOAD_MODULE_CNT(module_cnt); 8346c5768b3SDharageswari R 8356c5768b3SDharageswari R ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data, 8366c5768b3SDharageswari R (sizeof(u16) * module_cnt), NULL, 0); 8376c5768b3SDharageswari R if (ret < 0) 8386c5768b3SDharageswari R dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret); 8396c5768b3SDharageswari R 8406c5768b3SDharageswari R return ret; 8416c5768b3SDharageswari R } 8426c5768b3SDharageswari R EXPORT_SYMBOL_GPL(skl_ipc_unload_modules); 8436c5768b3SDharageswari R 844b81fd263SSubhransu S. Prusty int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, 845b81fd263SSubhransu S. Prusty struct skl_ipc_large_config_msg *msg, u32 *param) 846b81fd263SSubhransu S. Prusty { 847b81fd263SSubhransu S. Prusty struct skl_ipc_header header = {0}; 848b81fd263SSubhransu S. Prusty u64 *ipc_header = (u64 *)(&header); 849b81fd263SSubhransu S. Prusty int ret = 0; 850b81fd263SSubhransu S. Prusty size_t sz_remaining, tx_size, data_offset; 851b81fd263SSubhransu S. Prusty 852b81fd263SSubhransu S. Prusty header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); 853b81fd263SSubhransu S. Prusty header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 854b81fd263SSubhransu S. Prusty header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_SET); 855b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); 856b81fd263SSubhransu S. Prusty header.primary |= IPC_MOD_ID(msg->module_id); 857b81fd263SSubhransu S. Prusty 858b81fd263SSubhransu S. Prusty header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size); 859b81fd263SSubhransu S. Prusty header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id); 860b81fd263SSubhransu S. Prusty header.extension |= IPC_FINAL_BLOCK(0); 861b81fd263SSubhransu S. Prusty header.extension |= IPC_INITIAL_BLOCK(1); 862b81fd263SSubhransu S. Prusty 863b81fd263SSubhransu S. Prusty sz_remaining = msg->param_data_size; 864b81fd263SSubhransu S. Prusty data_offset = 0; 865b81fd263SSubhransu S. Prusty while (sz_remaining != 0) { 866b81fd263SSubhransu S. Prusty tx_size = sz_remaining > SKL_ADSP_W1_SZ 867b81fd263SSubhransu S. Prusty ? SKL_ADSP_W1_SZ : sz_remaining; 868b81fd263SSubhransu S. Prusty if (tx_size == sz_remaining) 869b81fd263SSubhransu S. Prusty header.extension |= IPC_FINAL_BLOCK(1); 870b81fd263SSubhransu S. Prusty 871b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__, 872b81fd263SSubhransu S. Prusty header.primary, header.extension); 873b81fd263SSubhransu S. Prusty dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n", 874b81fd263SSubhransu S. Prusty (unsigned)data_offset, (unsigned)tx_size); 875b81fd263SSubhransu S. Prusty ret = sst_ipc_tx_message_wait(ipc, *ipc_header, 876b81fd263SSubhransu S. Prusty ((char *)param) + data_offset, 877b81fd263SSubhransu S. Prusty tx_size, NULL, 0); 878b81fd263SSubhransu S. Prusty if (ret < 0) { 879b81fd263SSubhransu S. Prusty dev_err(ipc->dev, 880b81fd263SSubhransu S. Prusty "ipc: set large config fail, err: %d\n", ret); 881b81fd263SSubhransu S. Prusty return ret; 882b81fd263SSubhransu S. Prusty } 883b81fd263SSubhransu S. Prusty sz_remaining -= tx_size; 884b81fd263SSubhransu S. Prusty data_offset = msg->param_data_size - sz_remaining; 885b81fd263SSubhransu S. Prusty 886b81fd263SSubhransu S. Prusty /* clear the fields */ 887b81fd263SSubhransu S. Prusty header.extension &= IPC_INITIAL_BLOCK_CLEAR; 888b81fd263SSubhransu S. Prusty header.extension &= IPC_DATA_OFFSET_SZ_CLEAR; 889b81fd263SSubhransu S. Prusty /* fill the fields */ 890b81fd263SSubhransu S. Prusty header.extension |= IPC_INITIAL_BLOCK(0); 891b81fd263SSubhransu S. Prusty header.extension |= IPC_DATA_OFFSET_SZ(data_offset); 892b81fd263SSubhransu S. Prusty } 893b81fd263SSubhransu S. Prusty 894b81fd263SSubhransu S. Prusty return ret; 895b81fd263SSubhransu S. Prusty } 896b81fd263SSubhransu S. Prusty EXPORT_SYMBOL_GPL(skl_ipc_set_large_config); 897cce1c7f3SMousami Jana 898cce1c7f3SMousami Jana int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, 899cce1c7f3SMousami Jana struct skl_ipc_large_config_msg *msg, u32 *param) 900cce1c7f3SMousami Jana { 901cce1c7f3SMousami Jana struct skl_ipc_header header = {0}; 902cce1c7f3SMousami Jana u64 *ipc_header = (u64 *)(&header); 903cce1c7f3SMousami Jana int ret = 0; 904cce1c7f3SMousami Jana size_t sz_remaining, rx_size, data_offset; 905cce1c7f3SMousami Jana 906cce1c7f3SMousami Jana header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); 907cce1c7f3SMousami Jana header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 908cce1c7f3SMousami Jana header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_GET); 909cce1c7f3SMousami Jana header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); 910cce1c7f3SMousami Jana header.primary |= IPC_MOD_ID(msg->module_id); 911cce1c7f3SMousami Jana 912cce1c7f3SMousami Jana header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size); 913cce1c7f3SMousami Jana header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id); 914cce1c7f3SMousami Jana header.extension |= IPC_FINAL_BLOCK(1); 915cce1c7f3SMousami Jana header.extension |= IPC_INITIAL_BLOCK(1); 916cce1c7f3SMousami Jana 917cce1c7f3SMousami Jana sz_remaining = msg->param_data_size; 918cce1c7f3SMousami Jana data_offset = 0; 919cce1c7f3SMousami Jana 920cce1c7f3SMousami Jana while (sz_remaining != 0) { 921cce1c7f3SMousami Jana rx_size = sz_remaining > SKL_ADSP_W1_SZ 922cce1c7f3SMousami Jana ? SKL_ADSP_W1_SZ : sz_remaining; 923cce1c7f3SMousami Jana if (rx_size == sz_remaining) 924cce1c7f3SMousami Jana header.extension |= IPC_FINAL_BLOCK(1); 925cce1c7f3SMousami Jana 926cce1c7f3SMousami Jana ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, 927cce1c7f3SMousami Jana ((char *)param) + data_offset, 928cce1c7f3SMousami Jana msg->param_data_size); 929cce1c7f3SMousami Jana if (ret < 0) { 930cce1c7f3SMousami Jana dev_err(ipc->dev, 931cce1c7f3SMousami Jana "ipc: get large config fail, err: %d\n", ret); 932cce1c7f3SMousami Jana return ret; 933cce1c7f3SMousami Jana } 934cce1c7f3SMousami Jana sz_remaining -= rx_size; 935cce1c7f3SMousami Jana data_offset = msg->param_data_size - sz_remaining; 936cce1c7f3SMousami Jana 937cce1c7f3SMousami Jana /* clear the fields */ 938cce1c7f3SMousami Jana header.extension &= IPC_INITIAL_BLOCK_CLEAR; 939cce1c7f3SMousami Jana header.extension &= IPC_DATA_OFFSET_SZ_CLEAR; 940cce1c7f3SMousami Jana /* fill the fields */ 941cce1c7f3SMousami Jana header.extension |= IPC_INITIAL_BLOCK(1); 942cce1c7f3SMousami Jana header.extension |= IPC_DATA_OFFSET_SZ(data_offset); 943cce1c7f3SMousami Jana } 944cce1c7f3SMousami Jana 945cce1c7f3SMousami Jana return ret; 946cce1c7f3SMousami Jana } 947cce1c7f3SMousami Jana EXPORT_SYMBOL_GPL(skl_ipc_get_large_config); 94820fb2fbdSRamesh Babu 94920fb2fbdSRamesh Babu int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, 95020fb2fbdSRamesh Babu u8 dma_id, u8 table_id) 95120fb2fbdSRamesh Babu { 95220fb2fbdSRamesh Babu struct skl_ipc_header header = {0}; 95320fb2fbdSRamesh Babu u64 *ipc_header = (u64 *)(&header); 95420fb2fbdSRamesh Babu int ret = 0; 95520fb2fbdSRamesh Babu 95620fb2fbdSRamesh Babu header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); 95720fb2fbdSRamesh Babu header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 95820fb2fbdSRamesh Babu header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY); 95920fb2fbdSRamesh Babu header.primary |= IPC_MOD_INSTANCE_ID(table_id); 96020fb2fbdSRamesh Babu header.primary |= IPC_MOD_ID(dma_id); 96120fb2fbdSRamesh Babu 96220fb2fbdSRamesh Babu ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); 96320fb2fbdSRamesh Babu 96420fb2fbdSRamesh Babu if (ret < 0) 96520fb2fbdSRamesh Babu dev_err(ipc->dev, "ipc: load lib failed\n"); 96620fb2fbdSRamesh Babu 96720fb2fbdSRamesh Babu return ret; 96820fb2fbdSRamesh Babu } 96920fb2fbdSRamesh Babu EXPORT_SYMBOL_GPL(skl_sst_ipc_load_library); 97041b7523fSPardha Saradhi K 97141b7523fSPardha Saradhi K int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg) 97241b7523fSPardha Saradhi K { 97341b7523fSPardha Saradhi K struct skl_ipc_header header = {0}; 97441b7523fSPardha Saradhi K u64 *ipc_header = (u64 *)(&header); 97541b7523fSPardha Saradhi K int ret; 97641b7523fSPardha Saradhi K 97741b7523fSPardha Saradhi K header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); 97841b7523fSPardha Saradhi K header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); 97941b7523fSPardha Saradhi K header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_D0IX); 98041b7523fSPardha Saradhi K header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); 98141b7523fSPardha Saradhi K header.primary |= IPC_MOD_ID(msg->module_id); 98241b7523fSPardha Saradhi K 98341b7523fSPardha Saradhi K header.extension = IPC_D0IX_WAKE(msg->wake); 98441b7523fSPardha Saradhi K header.extension |= IPC_D0IX_STREAMING(msg->streaming); 98541b7523fSPardha Saradhi K 98641b7523fSPardha Saradhi K dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__, 98741b7523fSPardha Saradhi K header.primary, header.extension); 98841b7523fSPardha Saradhi K 98941b7523fSPardha Saradhi K /* 99041b7523fSPardha Saradhi K * Use the nopm IPC here as we dont want it checking for D0iX 99141b7523fSPardha Saradhi K */ 99241b7523fSPardha Saradhi K ret = sst_ipc_tx_message_nopm(ipc, *ipc_header, NULL, 0, NULL, 0); 99341b7523fSPardha Saradhi K if (ret < 0) 99441b7523fSPardha Saradhi K dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret); 99541b7523fSPardha Saradhi K 99641b7523fSPardha Saradhi K return ret; 99741b7523fSPardha Saradhi K } 99841b7523fSPardha Saradhi K EXPORT_SYMBOL_GPL(skl_ipc_set_d0ix); 999