From df6cfa77e374971162e032f224fab0dc2cec5c08 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 26 Apr 2021 13:34:26 -0700 Subject: [PATCH] topology: pre-process-dai: add support for pcm_caps objects Add support for processing pcm_caps objects. For ex: Object.PCM.pcm."0" { name "Port0" direction "duplex" Object.Base.fe_dai."Port 0" {} Object.PCM.pcm_caps."playback" { name "Port0 Playback" } Object.PCM.pcm_caps."capture" { name "Port0 Capture" } } Would convert into: SectionPCMCapabilities { 'Port0 Playback' { formats 'S32_LE,S24_LE,S16_LE' rate_min 48000 rate_max 48000 channels_min 2 channels_max 2 periods_min 2 periods_max 16 period_size_min 192 period_size_max 16384 buffer_size_min 65536 buffer_size_max 65536 } 'Port0 Capture' { formats 'S32_LE,S24_LE,S16_LE' rate_min 48000 rate_max 48000 channels_min 2 channels_max 2 periods_min 2 periods_max 16 period_size_min 192 period_size_max 16384 buffer_size_min 65536 buffer_size_max 65536 } } and the SectionPCM updated as follows: SectionPCM { Port0 { id 0 dai { 'Port 0' { id 0 } } pcm { playback { capabilities 'Port0 Playback' } capture { capabilities 'Port0 Capture' } } } } Signed-off-by: Ranjani Sridharan Signed-off-by: Jaroslav Kysela --- topology/pre-process-dai.c | 87 +++++++++++++++++++++++++++++++++++ topology/pre-process-object.c | 9 ++++ topology/pre-processor.h | 2 + 3 files changed, 98 insertions(+) diff --git a/topology/pre-process-dai.c b/topology/pre-process-dai.c index 6ff378d..1158afd 100644 --- a/topology/pre-process-dai.c +++ b/topology/pre-process-dai.c @@ -51,3 +51,90 @@ int tplg_build_fe_dai_object(struct tplg_pre_processor *tplg_pp, snd_config_t *o { return tplg_build_base_object(tplg_pp, obj_cfg, parent, false); } + +static int tplg_update_pcm_object(struct tplg_pre_processor *tplg_pp, + snd_config_t *obj_cfg, snd_config_t *parent) +{ + snd_config_t *top, *parent_obj, *obj, *dest, *cfg, *pcm, *child; + const char *parent_name, *item_name, *direction; + int ret; + + /* get object name */ + obj = tplg_object_get_instance_config(tplg_pp, obj_cfg); + item_name = tplg_object_get_name(tplg_pp, obj); + if (!item_name) + return -EINVAL; + + /* get direction */ + ret = snd_config_search(obj, "direction", &cfg); + if (ret < 0) { + SNDERR("no direction attribute in %s\n", item_name); + return ret; + } + + ret = snd_config_get_string(cfg, &direction); + if (ret < 0) { + SNDERR("Invalid direction attribute in %s\n", item_name); + return ret; + } + + /* add to parent section */ + top = tplg_object_get_section(tplg_pp, parent); + if (!top) { + SNDERR("Cannot find parent for %s\n", item_name); + return -EINVAL; + } + + parent_obj = tplg_object_get_instance_config(tplg_pp, parent); + + /* get parent name. if parent has no name, skip adding config */ + parent_name = tplg_object_get_name(tplg_pp, parent_obj); + if (!parent_name) + return 0; + + /* find parent config with name */ + dest = tplg_find_config(top, parent_name); + if (!dest) { + SNDERR("Cannot find parent section %s\n", parent_name); + return -EINVAL; + } + + ret = snd_config_search(dest, "pcm", &pcm); + if (ret < 0) { + ret = tplg_config_make_add(&pcm, "pcm", SND_CONFIG_TYPE_COMPOUND, dest); + if (ret < 0) { + SNDERR("Error creating pcm config in %s\n", parent_name); + return ret; + } + } + + ret = snd_config_search(pcm, direction, &cfg); + if (ret >= 0) { + SNDERR("pcm.%s exists already in %s\n", direction, parent_name); + return -EEXIST; + } + + ret = tplg_config_make_add(&cfg, direction, SND_CONFIG_TYPE_COMPOUND, pcm); + + if (ret >= 0) + ret = tplg_config_make_add(&child, "capabilities", SND_CONFIG_TYPE_STRING, cfg); + + if (ret >= 0) + ret = snd_config_set_string(child, item_name); + + return ret; +} + +int tplg_build_pcm_caps_object(struct tplg_pre_processor *tplg_pp, + snd_config_t *obj_cfg, snd_config_t *parent) +{ + snd_config_t *caps; + int ret; + + ret = tplg_build_object_from_template(tplg_pp, obj_cfg, &caps, NULL, false); + if (ret < 0) + return ret; + + /* add pcm capabilities to parent */ + return tplg_update_pcm_object(tplg_pp, obj_cfg, parent); +} diff --git a/topology/pre-process-object.c b/topology/pre-process-object.c index d5359cb..0117577 100644 --- a/topology/pre-process-object.c +++ b/topology/pre-process-object.c @@ -858,6 +858,13 @@ static int tplg_build_generic_object(struct tplg_pre_processor *tplg_pp, snd_con return ret; } +const struct config_template_items pcm_caps_config = { + .int_config_ids = {"rate_min", "rate_max", "channels_min", "channels_max", "periods_min", + "periods_max", "period_size_min", "period_size_max", "buffer_size_min", + "buffer_size_max", "sig_bits"}, + .string_config_ids = {"formats", "rates"}, +}; + const struct config_template_items fe_dai_config = { .int_config_ids = {"id"}, }; @@ -932,6 +939,8 @@ const struct build_function_map object_build_map[] = { &bytes_control_config}, {"Dai", "", "SectionBE", &tplg_build_generic_object, &be_dai_config}, {"PCM", "pcm", "SectionPCM", &tplg_build_generic_object, &pcm_config}, + {"PCM", "pcm_caps", "SectionPCMCapabilities", &tplg_build_pcm_caps_object, + &pcm_caps_config}, }; static const struct build_function_map *tplg_object_get_map(struct tplg_pre_processor *tplg_pp, diff --git a/topology/pre-processor.h b/topology/pre-processor.h index 6f4eb4c..0c54a83 100644 --- a/topology/pre-processor.h +++ b/topology/pre-processor.h @@ -73,6 +73,8 @@ int tplg_build_fe_dai_object(struct tplg_pre_processor *tplg_pp, snd_config_t *o snd_config_t *parent); int tplg_build_base_object(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, snd_config_t *parent, bool skip_name); +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);