Skip to content

Commit a858b2f

Browse files
author
Jyri Sarha
committed
ASoC: sof ipc4: Add sof_ipc4_widget_setup_msg_payload() and call it
Add of_ipc4_widget_setup_msg_payload() for adding struct sof_ipc4_module_init_ext_init payload with associated objects. The function allocates memory for the additional payload, sets up the payload according to date collected from topology, and copies pre-encoded module specific payload after the ext_init payload. The function is called in sof_ipc4_widget_setup(). Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com>
1 parent ef5d219 commit a858b2f

1 file changed

Lines changed: 85 additions & 0 deletions

File tree

sound/soc/sof/ipc4-topology.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2851,13 +2851,84 @@ static int sof_ipc4_control_setup(struct snd_sof_dev *sdev, struct snd_sof_contr
28512851
return 0;
28522852
}
28532853

2854+
static int sof_ipc4_widget_setup_msg_payload(struct snd_sof_dev *sdev,
2855+
struct snd_sof_widget *swidget,
2856+
struct sof_ipc4_msg *msg,
2857+
void *ipc_data, u32 ipc_size,
2858+
void **new_data, u32 *new_size)
2859+
{
2860+
struct sof_ipc4_mod_init_ext_dp_memory_data *dp_mem_data;
2861+
struct sof_ipc4_module_init_ext_init *ext_init;
2862+
struct sof_ipc4_module_init_ext_object *hdr;
2863+
u32 *payload;
2864+
u32 ext_pos;
2865+
2866+
/* For the moment the only reason for adding init_ext_init payload is DP
2867+
* memory data. If both stack and heap size are 0 (= use default), then
2868+
* there is no need for init_ext_init payload.
2869+
*/
2870+
if (swidget->comp_domain != SOF_COMP_DOMAIN_DP) {
2871+
msg->extension &= ~SOF_IPC4_MOD_EXT_EXTENDED_INIT_MASK;
2872+
return 0;
2873+
}
2874+
2875+
payload = kzalloc(sdev->ipc->max_payload_size, GFP_KERNEL);
2876+
if (!payload)
2877+
return -ENOMEM;
2878+
2879+
/* Add ext_init first and set objects array flag to 1 */
2880+
ext_init = (struct sof_ipc4_module_init_ext_init *) payload;
2881+
ext_init->word0 |= SOF_IPC4_MOD_INIT_EXT_OBJ_ARRAY_MASK;
2882+
ext_pos = DIV_ROUND_UP(sizeof(*ext_init), sizeof(u32));
2883+
2884+
/* Add object array objects after ext_init */
2885+
2886+
/* Add dp_memory_data if comp_domain indicates DP */
2887+
if (swidget->comp_domain == SOF_COMP_DOMAIN_DP) {
2888+
hdr = (struct sof_ipc4_module_init_ext_object *) &payload[ext_pos];
2889+
hdr->header = SOF_IPC4_MOD_INIT_EXT_OBJ_LAST_MASK |
2890+
SOF_IPC4_MOD_INIT_EXT_OBJ_ID(SOF_IPC4_MOD_INIT_DATA_ID_DP_DATA) |
2891+
SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS(DIV_ROUND_UP(sizeof(*dp_mem_data),
2892+
sizeof(u32)));
2893+
ext_pos += DIV_ROUND_UP(sizeof(*hdr), sizeof(u32));
2894+
dp_mem_data = (struct sof_ipc4_mod_init_ext_dp_memory_data *) &payload[ext_pos];
2895+
dp_mem_data->domain_id = swidget->dp_domain_id;
2896+
dp_mem_data->stack_bytes = swidget->dp_stack_bytes;
2897+
dp_mem_data->heap_bytes = swidget->dp_heap_bytes;
2898+
ext_pos += DIV_ROUND_UP(sizeof(*dp_mem_data), sizeof(u32));
2899+
}
2900+
2901+
/* If another array object is added, remember clear previous OBJ_LAST bit */
2902+
2903+
/* Calculate final size and check that it fits to max payload size */
2904+
*new_size = ext_pos * sizeof(u32) + ipc_size;
2905+
if (*new_size > sdev->ipc->max_payload_size) {
2906+
dev_err(sdev->dev, "Max ipc payload size %lu exceeded: %u",
2907+
sdev->ipc->max_payload_size, *new_size);
2908+
kfree(payload);
2909+
return -EINVAL;
2910+
}
2911+
*new_data = payload;
2912+
2913+
/* Copy module specific ipc_payload to end */
2914+
memcpy(&payload[ext_pos], ipc_data, ipc_size);
2915+
2916+
/* Update msg extension bits accoring to the payload changes */
2917+
msg->extension |= SOF_IPC4_MOD_EXT_EXTENDED_INIT_MASK;
2918+
msg->extension &= ~SOF_IPC4_MOD_EXT_PARAM_SIZE_MASK;
2919+
msg->extension |= SOF_IPC4_MOD_EXT_PARAM_SIZE(DIV_ROUND_UP(*new_size, sizeof(u32)));
2920+
2921+
return 1;
2922+
}
2923+
28542924
static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
28552925
{
28562926
struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
28572927
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
28582928
struct sof_ipc4_pipeline *pipeline;
28592929
struct sof_ipc4_msg *msg;
28602930
void *ipc_data = NULL;
2931+
void *ext_data = NULL;
28612932
u32 ipc_size = 0;
28622933
int ret;
28632934

@@ -2982,6 +3053,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
29823053

29833054
if (swidget->id != snd_soc_dapm_scheduler) {
29843055
int module_id = msg->primary & SOF_IPC4_MOD_ID_MASK;
3056+
u32 new_size = 0;
29853057

29863058
ret = sof_ipc4_widget_assign_instance_id(sdev, swidget);
29873059
if (ret < 0) {
@@ -3002,6 +3074,16 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
30023074
dev_dbg(sdev->dev, "Create widget %s (pipe %d) - ID %d, instance %d, core %d\n",
30033075
swidget->widget->name, swidget->pipeline_id, module_id,
30043076
swidget->instance_id, swidget->core);
3077+
3078+
ret = sof_ipc4_widget_setup_msg_payload(sdev, swidget, msg, ipc_data, ipc_size,
3079+
&ext_data, &new_size);
3080+
if (ret < 0)
3081+
goto fail;
3082+
3083+
if (ret > 0) {
3084+
ipc_size = new_size;
3085+
ipc_data = ext_data;
3086+
}
30053087
} else {
30063088
dev_dbg(sdev->dev, "Create pipeline %s (pipe %d) - instance %d, core %d\n",
30073089
swidget->widget->name, swidget->pipeline_id,
@@ -3012,6 +3094,8 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
30123094
msg->data_ptr = ipc_data;
30133095

30143096
ret = sof_ipc_tx_message_no_reply(sdev->ipc, msg, ipc_size);
3097+
3098+
fail:
30153099
if (ret < 0) {
30163100
dev_err(sdev->dev, "failed to create module %s\n", swidget->widget->name);
30173101

@@ -3024,6 +3108,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
30243108
}
30253109
}
30263110

3111+
kfree(ext_data);
30273112
return ret;
30283113
}
30293114

0 commit comments

Comments
 (0)