-
Notifications
You must be signed in to change notification settings - Fork 140
ASoC: SOF: IPC4: add SRC module support #3692
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -111,6 +111,12 @@ static const struct sof_topology_token gain_tokens[] = { | |
| get_token_u32, offsetof(struct sof_ipc4_gain_data, init_val)}, | ||
| }; | ||
|
|
||
| /* SRC */ | ||
RanderWang marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| static const struct sof_topology_token src_tokens[] = { | ||
RanderWang marked this conversation as resolved.
Show resolved
Hide resolved
plbossart marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| {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)}, | ||
|
|
@@ -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, | ||
|
|
@@ -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; | ||
plbossart marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| int ret; | ||
|
|
||
| ret = sof_ipc4_widget_set_module_info(swidget); | ||
|
|
@@ -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; | ||
plbossart marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| msg->extension |= SOF_IPC4_MOD_EXT_DOMAIN(type); | ||
RanderWang marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| return 0; | ||
| } | ||
|
|
||
|
|
@@ -740,6 +751,58 @@ static int sof_ipc4_widget_setup_comp_mixer(struct snd_sof_widget *swidget) | |
| return ret; | ||
RanderWang marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| 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); | ||
RanderWang marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if (ret) | ||
| goto err; | ||
RanderWang marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| 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); | ||
RanderWang marked this conversation as resolved.
Show resolved
Hide resolved
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only a nit-pick, but if you: then the reader does not need to scroll up to see that
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
ranj063 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget) | ||
| { | ||
| struct sof_ipc4_mixer *mixer = swidget->private; | ||
|
|
@@ -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; | ||
|
|
@@ -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; | ||
|
|
@@ -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; | ||
|
|
@@ -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); | ||
|
|
@@ -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, | ||
|
|
@@ -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 = { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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) | ||
|
||
| /* | ||
| * 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) | ||
plbossart marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| #define SOF_IPC4_MODULE_LIB_CODE BIT(7) | ||
RanderWang marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| #define SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE 12 | ||
| #define SOF_IPC4_PIPELINE_OBJECT_SIZE 448 | ||
| #define SOF_IPC4_DATA_QUEUE_OBJECT_SIZE 128 | ||
|
|
@@ -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 { | ||
RanderWang marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 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 | ||
Uh oh!
There was an error while loading. Please reload this page.