Skip to content
Merged
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
4 changes: 4 additions & 0 deletions sound/soc/sof/ipc4-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
{
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
struct snd_sof_dai *dai = snd_sof_find_dai(component, rtd->dai_link->name);
struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct sof_ipc4_copier *ipc4_copier;
Expand All @@ -201,6 +202,9 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
snd_mask_none(fmt);
snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE);

rate->min = ipc4_copier->available_fmt.base_config->audio_fmt.sampling_frequency;
rate->max = rate->min;

/*
* Set trigger order for capture to SND_SOC_DPCM_TRIGGER_PRE. This is required
* to ensure that the BE DAI pipeline gets stopped/suspended before the FE DAI
Expand Down
120 changes: 117 additions & 3 deletions sound/soc/sof/ipc4-topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ static const struct sof_topology_token gain_tokens[] = {
get_token_u32, offsetof(struct sof_ipc4_gain_data, init_val)},
};

/* SRC */
static const struct sof_topology_token src_tokens[] = {
{SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
offsetof(struct sof_ipc4_src, sink_rate)},
};

static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = {
[SOF_DAI_TOKENS] = {"DAI tokens", dai_tokens, ARRAY_SIZE(dai_tokens)},
[SOF_PIPELINE_TOKENS] = {"Pipeline tokens", pipeline_tokens, ARRAY_SIZE(pipeline_tokens)},
Expand All @@ -134,6 +140,7 @@ static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = {
[SOF_AUDIO_FMT_NUM_TOKENS] = {"IPC4 Audio format number tokens",
ipc4_audio_fmt_num_tokens, ARRAY_SIZE(ipc4_audio_fmt_num_tokens)},
[SOF_GAIN_TOKENS] = {"Gain tokens", gain_tokens, ARRAY_SIZE(gain_tokens)},
[SOF_SRC_TOKENS] = {"SRC tokens", src_tokens, ARRAY_SIZE(src_tokens)},
};

static void sof_ipc4_dbg_audio_format(struct device *dev,
Expand Down Expand Up @@ -307,6 +314,7 @@ static int sof_ipc4_widget_set_module_info(struct snd_sof_widget *swidget)
static int sof_ipc4_widget_setup_msg(struct snd_sof_widget *swidget, struct sof_ipc4_msg *msg)
{
struct sof_ipc4_fw_module *fw_module;
uint32_t type;
int ret;

ret = sof_ipc4_widget_set_module_info(swidget);
Expand All @@ -323,6 +331,9 @@ static int sof_ipc4_widget_setup_msg(struct snd_sof_widget *swidget, struct sof_
msg->extension = SOF_IPC4_MOD_EXT_PPL_ID(swidget->pipeline_id);
msg->extension |= SOF_IPC4_MOD_EXT_CORE_ID(swidget->core);

type = fw_module->man4_module_entry.type & SOF_IPC4_MODULE_DP ? 1 : 0;
msg->extension |= SOF_IPC4_MOD_EXT_DOMAIN(type);

return 0;
}

Expand Down Expand Up @@ -740,6 +751,58 @@ static int sof_ipc4_widget_setup_comp_mixer(struct snd_sof_widget *swidget)
return ret;
}

static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget)
{
struct snd_soc_component *scomp = swidget->scomp;
struct sof_ipc4_src *src;
int ret;

dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name);

src = kzalloc(sizeof(*src), GFP_KERNEL);
if (!src)
return -ENOMEM;

swidget->private = src;

/* The out_audio_fmt in topology is ignored as it is not required by SRC */
ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, false);
if (ret)
goto err;

ret = sof_update_ipc_object(scomp, src, SOF_SRC_TOKENS, swidget->tuples,
swidget->num_tuples, sizeof(src), 1);
if (ret) {
dev_err(scomp->dev, "Parsing SRC tokens failed\n");
goto err;
}

dev_dbg(scomp->dev, "SRC sink rate %d\n", src->sink_rate);

ret = sof_ipc4_widget_setup_msg(swidget, &src->msg);
if (ret)
goto err;

return 0;
err:
sof_ipc4_free_audio_fmt(&src->available_fmt);
kfree(src);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Only a nit-pick, but if you:

kfree(swidget->private);
swidget->private = NULL;

then the reader does not need to scroll up to see that swidget->private = src; in line 762.

Copy link
Author

Choose a reason for hiding this comment

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

thanks. I want it to be consistent with above gain and mixer, so I did it.

swidget->private = NULL;
return ret;
}

static void sof_ipc4_widget_free_comp_src(struct snd_sof_widget *swidget)
{
struct sof_ipc4_src *src = swidget->private;

if (!src)
return;

sof_ipc4_free_audio_fmt(&src->available_fmt);
kfree(swidget->private);
swidget->private = NULL;
}

static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget)
{
struct sof_ipc4_mixer *mixer = swidget->private;
Expand Down Expand Up @@ -1305,6 +1368,37 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
return 0;
}

static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
struct snd_pcm_hw_params *fe_params,
struct snd_sof_platform_stream_params *platform_params,
struct snd_pcm_hw_params *pipeline_params, int dir)
{
struct snd_soc_component *scomp = swidget->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct sof_ipc4_src *src = swidget->private;
struct snd_interval *rate;
int ret;

src->available_fmt.ref_audio_fmt = &src->available_fmt.base_config->audio_fmt;

/* output format is not required to be sent to the FW for SRC */
ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config,
NULL, pipeline_params, &src->available_fmt,
sizeof(src->base_config));
if (ret < 0)
return ret;

/* update pipeline memory usage */
sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &src->base_config);

/* update pipeline_params for sink widgets */
rate = hw_param_interval(pipeline_params, SNDRV_PCM_HW_PARAM_RATE);
rate->min = src->sink_rate;
rate->max = rate->min;

return 0;
}

static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
{
struct sof_ipc4_control_data *control_data;
Expand Down Expand Up @@ -1360,7 +1454,6 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
u32 ipc_size = 0;
int ret;


switch (swidget->id) {
case snd_soc_dapm_scheduler:
pipeline = swidget->private;
Expand Down Expand Up @@ -1415,6 +1508,16 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
msg = &mixer->msg;
break;
}
case snd_soc_dapm_src:
{
struct sof_ipc4_src *src = swidget->private;

ipc_size = sizeof(struct sof_ipc4_base_module_cfg) + sizeof(src->sink_rate);
ipc_data = src;

msg = &src->msg;
break;
}
default:
dev_err(sdev->dev, "widget type %d not supported", swidget->id);
return -EINVAL;
Expand All @@ -1433,8 +1536,6 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget

msg->extension &= ~SOF_IPC4_MOD_EXT_PARAM_SIZE_MASK;
msg->extension |= ipc_size >> 2;
msg->extension &= ~SOF_IPC4_MOD_EXT_DOMAIN_MASK;
msg->extension |= SOF_IPC4_MOD_EXT_DOMAIN(pipeline->lp_mode);
}
dev_dbg(sdev->dev, "Create widget %s instance %d - pipe %d - core %d\n",
swidget->widget->name, swidget->instance_id, swidget->pipeline_id, swidget->core);
Expand Down Expand Up @@ -1762,6 +1863,15 @@ static enum sof_tokens mixer_token_list[] = {
SOF_COMP_EXT_TOKENS,
};

static enum sof_tokens src_token_list[] = {
SOF_COMP_TOKENS,
SOF_SRC_TOKENS,
SOF_AUDIO_FMT_NUM_TOKENS,
SOF_IN_AUDIO_FORMAT_TOKENS,
SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS,
SOF_COMP_EXT_TOKENS,
};

static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = {
[snd_soc_dapm_aif_in] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm,
host_token_list, ARRAY_SIZE(host_token_list), NULL,
Expand Down Expand Up @@ -1790,6 +1900,10 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TY
mixer_token_list, ARRAY_SIZE(mixer_token_list),
NULL, sof_ipc4_prepare_mixer_module,
NULL},
[snd_soc_dapm_src] = {sof_ipc4_widget_setup_comp_src, sof_ipc4_widget_free_comp_src,
src_token_list, ARRAY_SIZE(src_token_list),
NULL, sof_ipc4_prepare_src_module,
NULL},
};

const struct sof_ipc_tplg_ops ipc4_tplg_ops = {
Expand Down
27 changes: 26 additions & 1 deletion sound/soc/sof/ipc4-topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,18 @@
#define SOF_IPC4_FW_PAGE(x) ((((x) + BIT(12) - 1) & ~(BIT(12) - 1)) >> 12)
#define SOF_IPC4_FW_ROUNDUP(x) (((x) + BIT(6) - 1) & (~(BIT(6) - 1)))

#define SOF_IPC4_MODULE_LL BIT(5)
#define SOF_IPC4_MODULE_LOAD_TYPE GENMASK(3, 0)
#define SOF_IPC4_MODULE_AUTO_START BIT(4)
Copy link
Collaborator

Choose a reason for hiding this comment

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

where are these 2 definitions used?

Copy link
Author

Choose a reason for hiding this comment

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

they are not used now, but may be in future. I prefer to add it by one shot

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it makes sense to add them when used

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm still not in favor of adding macros that are not yet used in this patch. But if everyone else is OK with it, please go ahead with it.

Copy link
Member

Choose a reason for hiding this comment

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

It's not so bad, and it also explains why the LL/DP definitions don't start at zero.

/*
* Two module schedule domains in fw :
* LL domain - Low latency domain
* DP domain - Data processing domain
* The LL setting should be equal to !DP setting
*/
#define SOF_IPC4_MODULE_LL BIT(5)
#define SOF_IPC4_MODULE_DP BIT(6)
#define SOF_IPC4_MODULE_LIB_CODE BIT(7)

#define SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE 12
#define SOF_IPC4_PIPELINE_OBJECT_SIZE 448
#define SOF_IPC4_DATA_QUEUE_OBJECT_SIZE 128
Expand Down Expand Up @@ -242,4 +253,18 @@ struct sof_ipc4_mixer {
struct sof_ipc4_msg msg;
};

/**
* struct sof_ipc4_src SRC config data
* @base_config: IPC base config data
* @sink_rate: Output rate for sink module
* @available_fmt: Available audio format
* @msg: IPC4 message struct containing header and data info
*/
struct sof_ipc4_src {
struct sof_ipc4_base_module_cfg base_config;
uint32_t sink_rate;
struct sof_ipc4_available_audio_format available_fmt;
struct sof_ipc4_msg msg;
};

#endif