int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, struct skl_ipc_bind_unbind_msg *msg) { struct skl_ipc_header header = {0}; u64 *ipc_header = (u64 *)(&header); u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND; int ret; header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); header.primary |= IPC_GLB_TYPE(bind_unbind); header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); header.primary |= IPC_MOD_ID(msg->module_id); header.extension = IPC_DST_MOD_ID(msg->dst_module_id); header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id); header.extension |= IPC_DST_QUEUE(msg->dst_queue); header.extension |= IPC_SRC_QUEUE(msg->src_queue); dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary, header.extension); ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); if (ret < 0) { dev_err(ipc->dev, "ipc: bind/unbind faileden"); return ret; } return ret; }
int skl_ipc_init_instance(struct sst_generic_ipc *ipc, struct skl_ipc_init_instance_msg *msg, void *param_data) { struct skl_ipc_header header = {0}; u64 *ipc_header = (u64 *)(&header); int ret; u32 *buffer = (u32 *)param_data; /* param_block_size must be in dwords */ u16 param_block_size = msg->param_data_size / sizeof(u32); print_hex_dump(KERN_DEBUG, NULL, DUMP_PREFIX_NONE, 16, 4, buffer, param_block_size, false); header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); header.primary |= IPC_GLB_TYPE(IPC_MOD_INIT_INSTANCE); header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); header.primary |= IPC_MOD_ID(msg->module_id); header.extension = IPC_CORE_ID(msg->core_id); header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id); header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size); dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, header.primary, header.extension); ret = sst_ipc_tx_message_wait(ipc, *ipc_header, param_data, msg->param_data_size, NULL, 0); if (ret < 0) { dev_err(ipc->dev, "ipc: init instance failed\n"); return ret; } return ret; }
int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg) { struct skl_ipc_header header = {0}; u64 *ipc_header = (u64 *)(&header); int ret; header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_D0IX); header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); header.primary |= IPC_MOD_ID(msg->module_id); header.extension = IPC_D0IX_WAKE(msg->wake); header.extension |= IPC_D0IX_STREAMING(msg->streaming); dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__, header.primary, header.extension); /* * Use the nopm IPC here as we dont want it checking for D0iX */ ret = sst_ipc_tx_message_nopm(ipc, *ipc_header, NULL, 0, NULL, 0); if (ret < 0) dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret); return ret; }
int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, struct skl_ipc_large_config_msg *msg, u32 *param) { struct skl_ipc_header header = {0}; u64 *ipc_header = (u64 *)(&header); int ret = 0; size_t sz_remaining, tx_size, data_offset; header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_SET); header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); header.primary |= IPC_MOD_ID(msg->module_id); header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size); header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id); header.extension |= IPC_FINAL_BLOCK(0); header.extension |= IPC_INITIAL_BLOCK(1); sz_remaining = msg->param_data_size; data_offset = 0; while (sz_remaining != 0) { tx_size = sz_remaining > SKL_ADSP_W1_SZ ? SKL_ADSP_W1_SZ : sz_remaining; if (tx_size == sz_remaining) header.extension |= IPC_FINAL_BLOCK(1); dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__, header.primary, header.extension); dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n", (unsigned)data_offset, (unsigned)tx_size); ret = sst_ipc_tx_message_wait(ipc, *ipc_header, ((char *)param) + data_offset, tx_size, NULL, 0); if (ret < 0) { dev_err(ipc->dev, "ipc: set large config fail, err: %d\n", ret); return ret; } sz_remaining -= tx_size; data_offset = msg->param_data_size - sz_remaining; /* clear the fields */ header.extension &= IPC_INITIAL_BLOCK_CLEAR; header.extension &= IPC_DATA_OFFSET_SZ_CLEAR; /* fill the fields */ header.extension |= IPC_INITIAL_BLOCK(0); header.extension |= IPC_DATA_OFFSET_SZ(data_offset); } return ret; }
int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id, u16 module_id, struct skl_ipc_dxstate_info *dx) { struct skl_ipc_header header = {0}; u64 *ipc_header = (u64 *)(&header); int ret; header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_DX); header.primary |= IPC_MOD_INSTANCE_ID(instance_id); header.primary |= IPC_MOD_ID(module_id); dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, header.primary, header.extension); ret = sst_ipc_tx_message_wait(ipc, *ipc_header, dx, sizeof(dx), NULL, 0); if (ret < 0) { dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret); return ret; } return ret; }
int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, u8 dma_id, u8 table_id, bool wait) { struct skl_ipc_header header = {0}; u64 *ipc_header = (u64 *)(&header); int ret = 0; header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG); header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST); header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY); header.primary |= IPC_MOD_INSTANCE_ID(table_id); header.primary |= IPC_MOD_ID(dma_id); if (wait) ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0); else ret = sst_ipc_tx_message_nowait(ipc, *ipc_header, NULL, 0); if (ret < 0) dev_err(ipc->dev, "ipc: load lib failed\n"); return ret; }