From b848786f421d8cf65b75c9165f91d65453b9be3a Mon Sep 17 00:00:00 2001 From: Chao Song Date: Wed, 2 Jun 2021 13:59:53 +0800 Subject: [PATCH] topology: pre-process-dapm: update automatic attributes for buffer Add the function to compute the value for the "size" automatic attribute in the buffer objects. Signed-off-by: Chao Song Signed-off-by: Ranjani Sridharan Signed-off-by: Jaroslav Kysela --- topology/pre-process-dapm.c | 109 ++++++++++++++++++++++++++++++++++ topology/pre-process-object.c | 2 + topology/pre-processor.h | 2 + 3 files changed, 113 insertions(+) diff --git a/topology/pre-process-dapm.c b/topology/pre-process-dapm.c index dc510e1..647e66b 100644 --- a/topology/pre-process-dapm.c +++ b/topology/pre-process-dapm.c @@ -422,3 +422,112 @@ err: free(sink_widget_name); return ret; } + +static int tplg_get_sample_size_from_format(const char *format) +{ + if (!strcmp(format, "s32le") || !strcmp(format, "s24le") || !strcmp(format, "float")) + return 4; + + if (!strcmp(format, "s16le")) + return 2; + + SNDERR("Unsupported format: %s\n", format); + return -EINVAL; +} + +int tplg_update_buffer_auto_attr(struct tplg_pre_processor *tplg_pp, + snd_config_t *buffer_cfg, snd_config_t *parent) +{ + snd_config_iterator_t i, next; + snd_config_t *n, *pipeline_cfg, *child; + const char *buffer_id, *format; + long periods, channels, sample_size; + long sched_period, rate, frames; + long buffer_size; + int err; + + if (snd_config_get_id(buffer_cfg, &buffer_id) < 0) + return -EINVAL; + + if (!parent) { + SNDERR("No parent for buffer %s\n", buffer_id); + return -EINVAL; + } + + /* acquire attributes from buffer config */ + snd_config_for_each(i, next, buffer_cfg) { + const char *id; + + n = snd_config_iterator_entry(i); + if (snd_config_get_id(n, &id) < 0) + continue; + + if (!strcmp(id, "periods")) { + if (snd_config_get_integer(n, &periods)) { + SNDERR("Invalid number of periods for buffer %s\n", buffer_id); + return -EINVAL; + } + } + + if (!strcmp(id, "channels")) { + if (snd_config_get_integer(n, &channels)) { + SNDERR("Invalid number of channels for buffer %s\n", buffer_id); + return -EINVAL; + } + } + + if (!strcmp(id, "format")) { + if (snd_config_get_string(n, &format)) { + SNDERR("Invalid format for buffer %s\n", buffer_id); + return -EINVAL; + } + } + } + + pipeline_cfg = tplg_object_get_instance_config(tplg_pp, parent); + + /* acquire some other attributes from parent pipeline config */ + snd_config_for_each(i, next, pipeline_cfg) { + const char *id; + + n = snd_config_iterator_entry(i); + if (snd_config_get_id(n, &id) < 0) + continue; + + if (!strcmp(id, "period")) { + if (snd_config_get_integer(n, &sched_period)) { + SNDERR("Invalid period for buffer %s\n", buffer_id); + return -EINVAL; + } + } + + if (!strcmp(id, "rate")) { + if (snd_config_get_integer(n, &rate)) { + SNDERR("Invalid rate for buffer %s\n", buffer_id); + return -EINVAL; + } + } + } + + /* calculate buffer size */ + sample_size = tplg_get_sample_size_from_format(format); + if (sample_size < 0) { + SNDERR("Invalid sample size value for %s\n", buffer_id); + return sample_size; + } + frames = (rate * sched_period) / 1000000; + buffer_size = periods * sample_size * channels * frames; + + /* add size child config to buffer config */ + err = tplg_config_make_add(&child, "size", SND_CONFIG_TYPE_INTEGER, buffer_cfg); + if (err < 0) { + SNDERR("Error creating size config for %s\n", buffer_id); + return err; + } + + err = snd_config_set_integer(child, buffer_size); + if (err < 0) + SNDERR("Error setting size config for %s\n", buffer_id); + + return err; +} diff --git a/topology/pre-process-object.c b/topology/pre-process-object.c index a976cd3..4f7e257 100644 --- a/topology/pre-process-object.c +++ b/topology/pre-process-object.c @@ -941,6 +941,8 @@ const struct build_function_map object_build_map[] = { &hwcfg_config}, {"Base", "fe_dai", "dai", &tplg_build_fe_dai_object, NULL, &fe_dai_config}, {"Base", "route", "SectionGraph", &tplg_build_dapm_route_object, NULL, NULL}, + {"Widget", "buffer", "SectionWidget", &tplg_build_generic_object, + tplg_update_buffer_auto_attr, &widget_config}, {"Widget", "", "SectionWidget", &tplg_build_generic_object, NULL, &widget_config}, {"Control", "mixer", "SectionControlMixer", &tplg_build_mixer_control, NULL, &mixer_control_config}, diff --git a/topology/pre-processor.h b/topology/pre-processor.h index fce7b47..0a8bd77 100644 --- a/topology/pre-processor.h +++ b/topology/pre-processor.h @@ -81,6 +81,8 @@ int tplg_build_pcm_caps_object(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, snd_config_t *parent); int tplg_parent_update(struct tplg_pre_processor *tplg_pp, snd_config_t *parent, const char *section_name, const char *item_name); +int tplg_update_buffer_auto_attr(struct tplg_pre_processor *tplg_pp, + snd_config_t *buffer_cfg, snd_config_t *parent); /* object helpers */ int tplg_pre_process_objects(struct tplg_pre_processor *tplg_pp, snd_config_t *cfg,