Unverified Commit dd808d6b authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: SOF: ipc4: Send heap/stack bytes via new

Merge series from Peter Ujfalusi <peter.ujfalusi@linux.intel.com>:

Add new module init payload (this has already been partly specified in
SOF FW src/include/ipc4/module.h) and use that to pass new topology widget
properties to FW.

The original ext_init payload extension for this is already already
supported by the firmware.
parents e7c30ac3 fc6ceb7e
Loading
Loading
Loading
Loading
+75 −0
Original line number Diff line number Diff line
@@ -352,6 +352,10 @@ struct sof_ipc4_base_module_cfg {
#define SOF_IPC4_MOD_EXT_DOMAIN_MASK		BIT(28)
#define SOF_IPC4_MOD_EXT_DOMAIN(x)		((x) << SOF_IPC4_MOD_EXT_DOMAIN_SHIFT)

#define SOF_IPC4_MOD_EXT_EXTENDED_INIT_SHIFT	29
#define SOF_IPC4_MOD_EXT_EXTENDED_INIT_MASK	BIT(29)
#define SOF_IPC4_MOD_EXT_EXTENDED_INIT(x)	((x) << SOF_IPC4_MOD_EXT_EXTENDED_SHIFT)

/*  bind/unbind module ipc msg */
#define SOF_IPC4_MOD_EXT_DST_MOD_ID_SHIFT	0
#define SOF_IPC4_MOD_EXT_DST_MOD_ID_MASK	GENMASK(15, 0)
@@ -586,6 +590,77 @@ struct sof_ipc4_notify_module_data {
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_VAL		0xA15A0000
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_PARAMID_MASK	GENMASK(15, 0)

/*
 * Macros for creating struct sof_ipc4_module_init_ext_init payload
 * with its associated data. ext_init payload should be the first
 * piece of payload following SOF_IPC4_MOD_INIT_INSTANCE msg, and its
 * existence is indicated with SOF_IPC4_MOD_EXT_EXTENDED-bit.
 *
 * The macros below apply to sof_ipc4_module_init_ext_init.word0
 */
#define SOF_IPC4_MOD_INIT_EXT_RTOS_DOMAIN_SHIFT	0
#define SOF_IPC4_MOD_INIT_EXT_RTOS_DOMAIN_MASK	BIT(0)
#define SOF_IPC4_MOD_INIT_EXT_RTOS_DOMAIN(x)	((x) << SOF_IPC4_MOD_INIT_EXT_RTOS_DOMAIN_SHIFT)

#define SOF_IPC4_MOD_INIT_EXT_GNA_USED_SHIFT	1
#define SOF_IPC4_MOD_INIT_EXT_GNA_USED_MASK	BIT(1)
#define SOF_IPC4_MOD_INIT_EXT_GNA_USED(x)	((x) << SOF_IPC4_MOD_INIT_EXT_GNA_USED_SHIFT)

#define SOF_IPC4_MOD_INIT_EXT_OBJ_ARRAY_SHIFT	2
#define SOF_IPC4_MOD_INIT_EXT_OBJ_ARRAY_MASK	BIT(2)
#define SOF_IPC4_MOD_INIT_EXT_DATA_ARRAY(x)	((x) << SOF_IPC4_MOD_INIT_EXT_OBJ_ARRAY_SHIFT)

struct sof_ipc4_module_init_ext_init {
	u32 word0;
	u32 rsvd1;
	u32 rsvd2;
} __packed __aligned(4);

/*
 * SOF_IPC4_MOD_EXT_EXTENDED payload may be followed by arbitrary
 * number of object array objects. SOF_IPC4_MOD_INIT_EXT_DATA_ARRAY
 * -bit indicates that an array object follows struct
 * sof_ipc4_module_init_ext_init.
 *
 * The object header's SOF_IPC4_MOD_INIT_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_MOD_INIT_EXT_OBJ_ID, and to indicate the object's
 * size in 32-bit words, SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS, not
 * including the header itself.
 *
 * The macros below apply to sof_ipc4_module_init_ext_object.header
 */
#define SOF_IPC4_MOD_INIT_EXT_OBJ_LAST_SHIFT	0
#define SOF_IPC4_MOD_INIT_EXT_OBJ_LAST_MASK	BIT(0)
#define SOF_IPC4_MOD_INIT_EXT_OBJ_LAST(x)	((x) << SOF_IPC4_MOD_INIT_EXT_OBJ_LAST_SHIFT)

#define SOF_IPC4_MOD_INIT_EXT_OBJ_ID_SHIFT	1
#define SOF_IPC4_MOD_INIT_EXT_OBJ_ID_MASK	GENMASK(15, 1)
#define SOF_IPC4_MOD_INIT_EXT_OBJ_ID(x)		((x) << SOF_IPC4_MOD_INIT_EXT_OBJ_ID_SHIFT)

#define SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS_SHIFT	16
#define SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS_MASK	GENMASK(31, 16)
#define SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS(x)	((x) << SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS_SHIFT)

struct sof_ipc4_module_init_ext_object {
	u32 header;
	u32 data[];
} __packed __aligned(4);

enum sof_ipc4_mod_init_ext_obj_id {
	SOF_IPC4_MOD_INIT_DATA_ID_INVALID = 0,
	SOF_IPC4_MOD_INIT_DATA_ID_DP_DATA,
	SOF_IPC4_MOD_INIT_DATA_ID_MAX = SOF_IPC4_MOD_INIT_DATA_ID_DP_DATA,
};

/* DP module memory configuration data object for ext_init object array */
struct sof_ipc4_mod_init_ext_dp_memory_data {
	u32 domain_id;		/* userspace domain ID */
	u32 stack_bytes;	/* stack size in bytes, 0 means default size */
	u32 heap_bytes;		/* stack size in bytes, 0 means default size */
} __packed __aligned(4);

/** @}*/

#endif
+3 −0
Original line number Diff line number Diff line
@@ -107,6 +107,9 @@
#define SOF_TKN_COMP_NO_WNAME_IN_KCONTROL_NAME	417

#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

/* SSP */
#define SOF_TKN_INTEL_SSP_CLKS_CONTROL		500
+91 −0
Original line number Diff line number Diff line
@@ -158,6 +158,12 @@ static const struct sof_topology_token comp_ext_tokens[] = {
		offsetof(struct snd_sof_widget, core)},
	{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)},
	{SOF_TKN_COMP_STACK_BYTES_REQUIREMENT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
		offsetof(struct snd_sof_widget, dp_stack_bytes)},
};

static const struct sof_topology_token gain_tokens[] = {
@@ -2968,6 +2974,77 @@ 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)
{
	struct sof_ipc4_mod_init_ext_dp_memory_data *dp_mem_data;
	struct sof_ipc4_module_init_ext_init *ext_init;
	struct sof_ipc4_module_init_ext_object *hdr;
	int new_size;
	u32 *payload;
	u32 ext_pos;

	/* For the moment the only reason for adding init_ext_init payload is DP
	 * memory data. If both stack and heap size are 0 (= use default), then
	 * there is no need for init_ext_init payload.
	 */
	if (swidget->comp_domain != SOF_COMP_DOMAIN_DP) {
		msg->extension &= ~SOF_IPC4_MOD_EXT_EXTENDED_INIT_MASK;
		return 0;
	}

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

	/* 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 */
	if (swidget->comp_domain == SOF_COMP_DOMAIN_DP) {
		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;
		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 */
	new_size = ext_pos * sizeof(u32) + ipc_size;
	if (new_size > sdev->ipc->max_payload_size) {
		dev_err(sdev->dev, "Max ipc payload size %zu exceeded: %u",
			sdev->ipc->max_payload_size, new_size);
		kfree(payload);
		return -EINVAL;
	}
	*new_data = payload;

	/* Copy module specific ipc_payload to end */
	memcpy(&payload[ext_pos], ipc_data, ipc_size);

	/* Update msg extension bits according to the payload changes */
	msg->extension |= SOF_IPC4_MOD_EXT_EXTENDED_INIT_MASK;
	msg->extension &= ~SOF_IPC4_MOD_EXT_PARAM_SIZE_MASK;
	msg->extension |= SOF_IPC4_MOD_EXT_PARAM_SIZE(DIV_ROUND_UP(new_size, sizeof(u32)));

	return new_size;
}

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;
@@ -2975,6 +3052,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
	struct sof_ipc4_pipeline *pipeline;
	struct sof_ipc4_msg *msg;
	void *ipc_data = NULL;
	void *ext_data = NULL;
	u32 ipc_size = 0;
	int ret;

@@ -3119,6 +3197,16 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
		dev_dbg(sdev->dev, "Create widget %s (pipe %d) - ID %d, instance %d, core %d\n",
			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);
		if (ret < 0)
			goto fail;

		if (ret > 0) {
			ipc_size = ret;
			ipc_data = ext_data;
		}
	} else {
		dev_dbg(sdev->dev, "Create pipeline %s (pipe %d) - instance %d, core %d\n",
			swidget->widget->name, swidget->pipeline_id,
@@ -3129,6 +3217,8 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
	msg->data_ptr = ipc_data;

	ret = sof_ipc_tx_message_no_reply(sdev->ipc, msg, ipc_size);

fail:
	if (ret < 0) {
		dev_err(sdev->dev, "failed to create module %s\n", swidget->widget->name);

@@ -3141,6 +3231,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
		}
	}

	kfree(ext_data);
	return ret;
}

+5 −0
Original line number Diff line number Diff line
@@ -454,6 +454,11 @@ 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 */

	struct snd_soc_dapm_widget *widget;
	struct list_head list;	/* list in sdev widget list */
	struct snd_sof_pipeline *spipe;