Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions include/sound/sof/ipc4/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,10 @@ enum sof_ipc4_pipeline_state {
#define SOF_IPC4_GLB_PIPE_EXT_CORE_ID_MASK GENMASK(23, 20)
#define SOF_IPC4_GLB_PIPE_EXT_CORE_ID(x) ((x) << SOF_IPC4_GLB_PIPE_EXT_CORE_ID_SHIFT)

#define SOF_IPC4_GLB_PIPE_PAYLOAD_SHIFT 29
#define SOF_IPC4_GLB_PIPE_PAYLOAD_MASK BIT(29)
#define SOF_IPC4_GLB_PIPE_PAYLOAD(x) ((x) << SOF_IPC4_GLB_PIPE_PAYLOAD_SHIFT)

/* pipeline set state ipc msg */
#define SOF_IPC4_GLB_PIPE_STATE_ID_SHIFT 16
#define SOF_IPC4_GLB_PIPE_STATE_ID_MASK GENMASK(23, 16)
Expand Down Expand Up @@ -691,6 +695,79 @@ struct sof_ipc4_mod_init_ext_dp_memory_data {
u32 heap_bytes; /* stack size in bytes, 0 means default size */
} __packed __aligned(4);


/*
* This set of macros are very similar to the set above, but these are
* for building payload to SOF_IPC4_GLB_CREATE_PIPELINE message.
*
* Macros for creating struct sof_ipc4_glb_pipe_payload payload with
* its associated data. ext_init payload should be the first piece of
* payload following SOF_IPC4_GLB_CREATE_PIPELINE msg, and its
* existence is indicated with SOF_IPC4_GLB_PIPE_PAYLOAD bit.
*
* The macros below apply to sof_ipc4_glb_pipe_payload.word0
*/
#define SOF_IPC4_GLB_PIPE_PAYLOAD_WORDS_SHIFT 0
#define SOF_IPC4_GLB_PIPE_PAYLOAD_WORDS_MASK GENMASK(23, 0)
#define SOF_IPC4_GLB_PIPE_PAYLOAD_WORDS(x) ((x) << SOF_IPC4_GLB_PIPE_PAYLOAD_WORDS_SHIFT)

#define SOF_IPC4_GLB_PIPE_EXT_OBJ_ARRAY_SHIFT 24
#define SOF_IPC4_GLB_PIPE_EXT_OBJ_ARRAY_MASK BIT(24)
#define SOF_IPC4_GLB_PIPE_EXT_OBJ_ARRAY(x) ((x) << SOF_IPC4_GLB_PIPE_EXT_OBJ_ARRAY_SHIFT)

struct sof_ipc4_glb_pipe_payload {
u32 word0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you do bitfields instead e.g.

u32 payload : 24;
u32 array : 8;

? Or at least pick up a more informative name like payload_array and maybe use __bitwise?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is Linux kernel style, at least in SOF driver, and in all other Linux drivers I've been working on. In SOF driver every other IPC message and payload structure is defined with macros, not with bitfields. I don't think I should diverge from this in PR either.

u32 rsvd1;
u32 rsvd2;
} __packed __aligned(4);

/*
* SOF_IPC4_GLB_CREATE_PIPELINE payload may be followed by arbitrary
* number of object array objects. SOF_IPC4_GLB_PIPE_EXT_OBJ_ARRAY-bit
* indicates that an array object follows struct
* sof_ipc4_glb_pipe_payload.
*
* The object header's SOF_IPC4_GLB_PIPE_EXT_OBJ_LAST-bit in struct
* sof_ipc4_module_init_ext_object indicates if the array is continued
* with another object. The header has also fields to identify the
* object, SOF_IPC4_GLB_PIPE_EXT_OBJ_ID, and to indicate the object's
* size in 32-bit words, SOF_IPC4_GLB_PIPE_EXT_OBJ_WORDS, not
* including the header itself.
*
* The macros below apply to sof_ipc4_glb_pipe_ext_object.header
*/
#define SOF_IPC4_GLB_PIPE_EXT_OBJ_LAST_SHIFT 0
#define SOF_IPC4_GLB_PIPE_EXT_OBJ_LAST_MASK BIT(0)
#define SOF_IPC4_GLB_PIPE_EXT_OBJ_LAST(x) ((x) << SOF_IPC4_GLB_PIPE_EXT_OBJ_LAST_SHIFT)

#define SOF_IPC4_GLB_PIPE_EXT_OBJ_ID_SHIFT 1
#define SOF_IPC4_GLB_PIPE_EXT_OBJ_ID_MASK GENMASK(15, 1)
#define SOF_IPC4_GLB_PIPE_EXT_OBJ_ID(x) ((x) << SOF_IPC4_GLB_PIPE_EXT_OBJ_ID_SHIFT)

#define SOF_IPC4_GLB_PIPE_EXT_OBJ_WORDS_SHIFT 16
#define SOF_IPC4_GLB_PIPE_EXT_OBJ_WORDS_MASK GENMASK(31, 16)
#define SOF_IPC4_GLB_PIPE_EXT_OBJ_WORDS(x) ((x) << SOF_IPC4_GLB_PIPE_EXT_OBJ_WORDS_SHIFT)

struct sof_ipc4_glb_pipe_ext_object {
u32 header;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could also be split into sub-fields

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

u32 data[];
} __packed __aligned(4);

enum sof_ipc4_glb_pipe_ext_obj_id {
SOF_IPC4_GLB_PIPE_DATA_ID_INVALID = 0,
SOF_IPC4_GLB_PIPE_DATA_ID_MEM_DATA,
SOF_IPC4_GLB_PIPE_DATA_ID_MAX = SOF_IPC4_GLB_PIPE_DATA_ID_MEM_DATA,
};

/* Pipeline memory configuration data object for ext_init object array */
struct sof_ipc4_glb_pipe_ext_obj_memory_data {
u32 domain_id; /* userspace domain ID */
u32 stack_bytes; /* stack size in bytes */
u32 interim_bytes; /* interim heap size in bytes */
u32 lifetime_bytes; /* lifetime heap size in bytes */
u32 shared_bytes; /* shared size in bytes */
} __packed __aligned(4);

/** @}*/

#endif
6 changes: 4 additions & 2 deletions include/uapi/sound/sof/tokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,10 @@

#define SOF_TKN_COMP_SCHED_DOMAIN 418
#define SOF_TKN_COMP_DOMAIN_ID 419
#define SOF_TKN_COMP_HEAP_BYTES_REQUIREMENT 420
#define SOF_TKN_COMP_STACK_BYTES_REQUIREMENT 421
#define SOF_TKN_COMP_STACK_BYTES_REQUIREMENT 420
#define SOF_TKN_COMP_INTERIM_HEAP_BYTES_REQUIREMENT 421
#define SOF_TKN_COMP_LIFETIME_HEAP_BYTES_REQUIREMENT 422
#define SOF_TKN_COMP_SHARED_BYTES_REQUIREMENT 423

/* SSP */
#define SOF_TKN_INTEL_SSP_CLKS_CONTROL 500
Expand Down
121 changes: 104 additions & 17 deletions sound/soc/sof/ipc4-topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,15 @@ static const struct sof_topology_token comp_ext_tokens[] = {
{SOF_TKN_COMP_SCHED_DOMAIN, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_domain,
offsetof(struct snd_sof_widget, comp_domain)},
{SOF_TKN_COMP_DOMAIN_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
offsetof(struct snd_sof_widget, dp_domain_id)},
{SOF_TKN_COMP_HEAP_BYTES_REQUIREMENT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
offsetof(struct snd_sof_widget, dp_heap_bytes)},
offsetof(struct snd_sof_widget, domain_id)},
{SOF_TKN_COMP_STACK_BYTES_REQUIREMENT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
offsetof(struct snd_sof_widget, dp_stack_bytes)},
offsetof(struct snd_sof_widget, stack_bytes)},
{SOF_TKN_COMP_INTERIM_HEAP_BYTES_REQUIREMENT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
offsetof(struct snd_sof_widget, interim_bytes)},
{SOF_TKN_COMP_LIFETIME_HEAP_BYTES_REQUIREMENT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
offsetof(struct snd_sof_widget, lifetime_bytes)},
{SOF_TKN_COMP_SHARED_BYTES_REQUIREMENT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
offsetof(struct snd_sof_widget, shared_bytes)},
};

static const struct sof_topology_token gain_tokens[] = {
Expand Down Expand Up @@ -1313,6 +1317,26 @@ sof_ipc4_update_resource_usage(struct snd_sof_dev *sdev, struct snd_sof_widget *
pipeline = pipe_widget->private;
pipeline->mem_usage += total;

/*
* If this is not a Data Processing module instance, add the
* required heap sizes to the sum of all modules instance's
* belonging to same pipeline and find the maximun stack
* requirement of all module instances belonging to the same
* pipeline.
*/
if (swidget->comp_domain != SOF_COMP_DOMAIN_DP) {
pipe_widget->interim_bytes += swidget->interim_bytes;
pipe_widget->lifetime_bytes += swidget->lifetime_bytes;
pipe_widget->shared_bytes += swidget->shared_bytes;
if (pipe_widget->stack_bytes < swidget->stack_bytes)
pipe_widget->stack_bytes = swidget->stack_bytes;

dev_dbg(sdev->dev, "%s mem reqs to %s lifetime %u heap %u shared %u stack %u",
swidget->widget->name, pipe_widget->widget->name,
pipe_widget->lifetime_bytes, pipe_widget->interim_bytes,
pipe_widget->shared_bytes, pipe_widget->stack_bytes);
}

/* Update base_config->cpc from the module manifest */
sof_ipc4_update_cpc_from_manifest(sdev, fw_module, base_config);

Expand Down Expand Up @@ -2993,11 +3017,11 @@ static int sof_ipc4_control_setup(struct snd_sof_dev *sdev, struct snd_sof_contr
return 0;
}

static int sof_ipc4_widget_setup_msg_payload(struct snd_sof_dev *sdev,
struct snd_sof_widget *swidget,
struct sof_ipc4_msg *msg,
void *ipc_data, u32 ipc_size,
void **new_data)
static int sof_ipc4_widget_mod_init_msg_payload(struct snd_sof_dev *sdev,
struct snd_sof_widget *swidget,
struct sof_ipc4_msg *msg,
void *ipc_data, u32 ipc_size,
void **new_data)
{
struct sof_ipc4_mod_init_ext_dp_memory_data *dp_mem_data;
struct sof_ipc4_module_init_ext_init *ext_init;
Expand All @@ -3021,26 +3045,26 @@ static int sof_ipc4_widget_setup_msg_payload(struct snd_sof_dev *sdev,

/* Add ext_init first and set objects array flag to 1 */
ext_init = (struct sof_ipc4_module_init_ext_init *)payload;
ext_init->word0 |= SOF_IPC4_MOD_INIT_EXT_OBJ_ARRAY_MASK;
ext_pos = DIV_ROUND_UP(sizeof(*ext_init), sizeof(u32));

/* Add object array objects after ext_init */

/* Add dp_memory_data if comp_domain indicates DP */
/* Add memory_data if comp_domain indicates DP */
if (swidget->comp_domain == SOF_COMP_DOMAIN_DP) {
ext_init->word0 |= SOF_IPC4_MOD_INIT_EXT_OBJ_ARRAY_MASK;

hdr = (struct sof_ipc4_module_init_ext_object *)&payload[ext_pos];
hdr->header = SOF_IPC4_MOD_INIT_EXT_OBJ_LAST_MASK |
SOF_IPC4_MOD_INIT_EXT_OBJ_ID(SOF_IPC4_MOD_INIT_DATA_ID_DP_DATA) |
SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS(DIV_ROUND_UP(sizeof(*dp_mem_data),
sizeof(u32)));
ext_pos += DIV_ROUND_UP(sizeof(*hdr), sizeof(u32));
dp_mem_data = (struct sof_ipc4_mod_init_ext_dp_memory_data *)&payload[ext_pos];
dp_mem_data->domain_id = swidget->dp_domain_id;
dp_mem_data->stack_bytes = swidget->dp_stack_bytes;
dp_mem_data->heap_bytes = swidget->dp_heap_bytes;
dp_mem_data->domain_id = swidget->domain_id;
dp_mem_data->stack_bytes = swidget->stack_bytes;
dp_mem_data->heap_bytes = swidget->interim_bytes;
ext_pos += DIV_ROUND_UP(sizeof(*dp_mem_data), sizeof(u32));
}

/* If another array object is added, remember clear previous OBJ_LAST bit */

/* Calculate final size and check that it fits to max payload size */
Expand All @@ -3064,6 +3088,58 @@ static int sof_ipc4_widget_setup_msg_payload(struct snd_sof_dev *sdev,
return new_size;
}

static int sof_ipc4_widget_pipe_create_msg_payload(struct snd_sof_dev *sdev,
struct snd_sof_widget *swidget,
struct sof_ipc4_msg *msg,
void **new_data)
{
struct sof_ipc4_glb_pipe_ext_obj_memory_data *mem_data;
struct sof_ipc4_glb_pipe_payload *payload_hdr;
struct sof_ipc4_glb_pipe_ext_object *obj;
u32 *payload;
u32 ext_pos;

payload = kzalloc(sdev->ipc->max_payload_size, GFP_KERNEL);
if (!payload)
return -ENOMEM;

/* Add sof_ipc4_glb_pipe_payload and set array bit to 1 */
payload_hdr = (struct sof_ipc4_glb_pipe_payload *)payload;
payload_hdr->word0 |= SOF_IPC4_GLB_PIPE_EXT_OBJ_ARRAY_MASK;
ext_pos = DIV_ROUND_UP(sizeof(*payload_hdr), sizeof(u32));

obj = (struct sof_ipc4_glb_pipe_ext_object *)&payload[ext_pos];
/* Add object array objects after payload_hdr */
obj->header = SOF_IPC4_GLB_PIPE_EXT_OBJ_LAST_MASK |
SOF_IPC4_GLB_PIPE_EXT_OBJ_ID(SOF_IPC4_GLB_PIPE_DATA_ID_MEM_DATA) |
SOF_IPC4_GLB_PIPE_EXT_OBJ_WORDS(DIV_ROUND_UP(sizeof(*mem_data),
sizeof(u32)));
ext_pos += DIV_ROUND_UP(sizeof(*obj), sizeof(u32));
mem_data = (struct sof_ipc4_glb_pipe_ext_obj_memory_data *)&payload[ext_pos];
mem_data->domain_id = swidget->domain_id;
mem_data->stack_bytes = swidget->stack_bytes;
mem_data->interim_bytes = swidget->interim_bytes;
mem_data->lifetime_bytes = swidget->lifetime_bytes;
mem_data->shared_bytes = swidget->shared_bytes;
ext_pos += DIV_ROUND_UP(sizeof(*mem_data), sizeof(u32));

/* If another array object is added, remember clear previous OBJ_LAST bit */

/* Put total payload size in words to the payload header */
payload_hdr->word0 |= SOF_IPC4_GLB_PIPE_PAYLOAD_WORDS(ext_pos);
*new_data = payload;

/* Update msg extension bits according to the payload changes */
msg->extension |= SOF_IPC4_GLB_PIPE_PAYLOAD_MASK;

dev_dbg(sdev->dev,
"payload word0 %#x domain_id %u stack %u interim %u lifetime %u shared %u bytes",
payload_hdr->word0, mem_data->domain_id, mem_data->stack_bytes,
mem_data->interim_bytes, mem_data->lifetime_bytes, mem_data->shared_bytes);

return ext_pos * sizeof(int32_t);
}

static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
{
struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
Expand Down Expand Up @@ -3217,8 +3293,8 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
swidget->widget->name, swidget->pipeline_id, module_id,
swidget->instance_id, swidget->core);

ret = sof_ipc4_widget_setup_msg_payload(sdev, swidget, msg, ipc_data, ipc_size,
&ext_data);
ret = sof_ipc4_widget_mod_init_msg_payload(sdev, swidget, msg, ipc_data, ipc_size,
&ext_data);
if (ret < 0)
goto fail;

Expand All @@ -3230,6 +3306,17 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
dev_dbg(sdev->dev, "Create pipeline %s (pipe %d) - instance %d, core %d\n",
swidget->widget->name, swidget->pipeline_id,
swidget->instance_id, swidget->core);

msg->extension &= ~SOF_IPC4_GLB_PIPE_PAYLOAD_MASK;
ret = sof_ipc4_widget_pipe_create_msg_payload(sdev, swidget, msg,
&ext_data);
if (ret < 0)
goto fail;

if (ret > 0) {
ipc_size = ret;
ipc_data = ext_data;
}
}

msg->data_size = ipc_size;
Expand Down
10 changes: 6 additions & 4 deletions sound/soc/sof/sof-audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,10 +459,12 @@ struct snd_sof_widget {
/* Scheduling domain (enum sof_comp_domain), unset, Low Latency, or Data Processing */
u32 comp_domain;

/* The values below are added to mod_init pay load if comp_domain indicates DP component */
u32 dp_domain_id; /* DP process userspace domain ID */
u32 dp_stack_bytes; /* DP process stack size requirement in bytes */
u32 dp_heap_bytes; /* DP process heap size requirement in bytes */
/* Module instance's memory configureation. */
u32 domain_id; /* Module instance's userspace domain ID */
u32 stack_bytes; /* Module instance's stack size requirement */
u32 interim_bytes; /* Module instance's interim heap size requirement */
u32 lifetime_bytes; /* Module instance's lifetime heap requirement */
u32 shared_bytes; /* Module instance's shared memory requirement */

struct snd_soc_dapm_widget *widget;
struct list_head list; /* list in sdev widget list */
Expand Down
Loading