|
@@ -349,6 +349,8 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
|
|
|
switch (reply) {
|
|
|
case IPC_GLB_REPLY_SUCCESS:
|
|
|
dev_info(ipc->dev, "ipc FW reply %x: success\n", header.primary);
|
|
|
+ /* copy the rx data from the mailbox */
|
|
|
+ sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size);
|
|
|
break;
|
|
|
|
|
|
case IPC_GLB_REPLY_OUT_OF_MEMORY:
|
|
@@ -834,3 +836,54 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
|
|
|
return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(skl_ipc_set_large_config);
|
|
|
+
|
|
|
+int skl_ipc_get_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, rx_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_GET);
|
|
|
+ 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(1);
|
|
|
+ header.extension |= IPC_INITIAL_BLOCK(1);
|
|
|
+
|
|
|
+ sz_remaining = msg->param_data_size;
|
|
|
+ data_offset = 0;
|
|
|
+
|
|
|
+ while (sz_remaining != 0) {
|
|
|
+ rx_size = sz_remaining > SKL_ADSP_W1_SZ
|
|
|
+ ? SKL_ADSP_W1_SZ : sz_remaining;
|
|
|
+ if (rx_size == sz_remaining)
|
|
|
+ header.extension |= IPC_FINAL_BLOCK(1);
|
|
|
+
|
|
|
+ ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0,
|
|
|
+ ((char *)param) + data_offset,
|
|
|
+ msg->param_data_size);
|
|
|
+ if (ret < 0) {
|
|
|
+ dev_err(ipc->dev,
|
|
|
+ "ipc: get large config fail, err: %d\n", ret);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ sz_remaining -= rx_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(1);
|
|
|
+ header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(skl_ipc_get_large_config);
|