diff --git a/tools/plugin/README.md b/tools/plugin/README.md index 673cbceb08ff..ce0cad4ea4cd 100644 --- a/tools/plugin/README.md +++ b/tools/plugin/README.md @@ -60,6 +60,19 @@ The command line is parsed as follows: - "default": The second default is the device name - "48k2c16b" is the config name for 48K, stereo, 16bit +Config name is optional in the command line. When it is not provided, hw_params will be used to +configure the endpoint. In this case, the command line can be simplified to: + +``` +aplay -Dsof:plugin:1:default:default +``` + +When using the default device, the command line can be further simplified to: + +``` +aplay -Dsof:plugin:1 +``` + This renders audio to the sof-pipe daemon using the sof-plugin topology playback PCM ID 1. The above example needs to be 48k as example pipe has no SRC/ASRC. diff --git a/tools/plugin/alsaplug/pcm.c b/tools/plugin/alsaplug/pcm.c index f8be6b348d95..5ed7d832eaa8 100644 --- a/tools/plugin/alsaplug/pcm.c +++ b/tools/plugin/alsaplug/pcm.c @@ -449,7 +449,7 @@ static int plug_pcm_prepare(snd_pcm_ioplug_t *io) return err; } -static int plug_init_shm_ctx(snd_sof_plug_t *plug); +static int plug_init_shm_ctx(snd_sof_plug_t *plug, snd_pcm_hw_params_t *params); static int plug_pcm_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params) { @@ -467,7 +467,7 @@ static int plug_pcm_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params) pcm->frame_us = ceil(1000000.0 / io->rate); /* now send IPCs to set up widgets */ - err = plug_set_up_pipelines(plug, pcm->capture); + err = plug_set_up_pipelines(plug, pcm->capture, params); if (err < 0) { fprintf(stderr, "error setting up pipelines\n"); return err; @@ -565,7 +565,7 @@ static int plug_pcm_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params) } /* set up the endpoint configs */ - err = plug_init_shm_ctx(plug); + err = plug_init_shm_ctx(plug, params); if (err < 0) { SNDERR("error: failed to init sof-pipe ep context: %s:%s", pcm->shm_pcm.name, strerror(err)); @@ -838,7 +838,7 @@ static int plug_create(snd_sof_plug_t *plug, snd_pcm_t **pcmp, const char *name, return 0; } -static int plug_init_shm_ctx(snd_sof_plug_t *plug) +static int plug_init_shm_ctx(snd_sof_plug_t *plug, snd_pcm_hw_params_t *params) { struct plug_shm_glb_state *glb = plug->glb_ctx.addr; struct endpoint_hw_config *ep; @@ -871,21 +871,38 @@ static int plug_init_shm_ctx(snd_sof_plug_t *plug) ep->period_frames = pc->period_frames; ep->period_time = pc->period_time; ep->rate = pc->rate; - ep->pipeline = ci->pcm; - strncpy(ep->card_name, ci->card_name, - sizeof(ep->card_name)); - strncpy(ep->dev_name, ci->dev_name, - sizeof(ep->dev_name)); - strncpy(ep->config_name, ci->config_name, - sizeof(ep->config_name)); + strncpy(ep->config_name, ci->config_name, sizeof(ep->config_name)); found = true; break; } + /* use hw_params if no matching config found or config missing in command line */ if (!found) { - SNDERR("error: config %s not found\n", ci->config_name); - return -EINVAL; + unsigned int channels, rate, dir, buffer_time, period_time; + snd_pcm_uframes_t buffer_size, period_size; + snd_pcm_format_t format; + + snd_pcm_hw_params_get_channels(params, &channels); + snd_pcm_hw_params_get_rate(params, &rate, &dir); + snd_pcm_hw_params_get_buffer_size(params, &buffer_size); + snd_pcm_hw_params_get_period_size(params, &period_size, &dir); + snd_pcm_hw_params_get_buffer_time(params, &buffer_time, &dir); + snd_pcm_hw_params_get_period_time(params, &period_time, &dir); + snd_pcm_hw_params_get_format(params, &format); + + ep = &glb->ep_config[glb->num_ep_configs++]; + ep->buffer_frames = buffer_size; + ep->buffer_time = buffer_time; + ep->channels = channels; + ep->format = format; + ep->period_frames = period_size; + ep->period_time = period_time; + ep->rate = rate; } + + ep->pipeline = ci->pcm; + strncpy(ep->card_name, ci->card_name, sizeof(ep->card_name)); + strncpy(ep->dev_name, ci->dev_name, sizeof(ep->dev_name)); } return 0; diff --git a/tools/plugin/alsaplug/plugin.c b/tools/plugin/alsaplug/plugin.c index be5ff0e69f2b..deb767a4133f 100644 --- a/tools/plugin/alsaplug/plugin.c +++ b/tools/plugin/alsaplug/plugin.c @@ -270,28 +270,29 @@ static int parse_client_cmdline(snd_sof_plug_t *plug, char *cmdline, bool just_t cmd_item = &plug->cmdline[plug->num_cmdline]; card = strtok_r(next, ":", &next); + /* card/dev names and config are all optional */ if (!card) { - SNDERR("Invalid card name\n"); - return -EINVAL; - } - dev = strtok_r(next, ":", &next); - if (!dev) { - SNDERR("Invalid dev name\n"); - return -EINVAL; - } - config = strtok_r(next, ":", &next); - - /* tuple needs all three, any missing ? */ - if (!config) { - SNDERR("invalid cmdline, expected pcm(%s):card(%s):dev(%s):config(%s) from %s", - pcm, card, dev, config, tplg); - return -EINVAL; + strncpy(cmd_item->card_name, "default", sizeof(cmd_item->card_name)); + strncpy(cmd_item->dev_name, "default", sizeof(cmd_item->dev_name)); + fprintf(stdout, "no config name provided, will use hw_params\n"); + } else { + strncpy(cmd_item->card_name, card, sizeof(cmd_item->card_name)); + dev = strtok_r(next, ":", &next); + /* dev name must be provided along with card name */ + if (!dev) { + SNDERR("Invalid dev name\n"); + return -EINVAL; + } + strncpy(cmd_item->dev_name, dev, sizeof(cmd_item->dev_name)); + config = strtok_r(next, ":", &next); + /* config name is optional */ + if (!config) + fprintf(stdout, "no config name provided, will use hw_params\n"); + else + strncpy(cmd_item->config_name, config, sizeof(cmd_item->config_name)); } cmd_item->pcm = atoi(pcm); - strncpy(cmd_item->card_name, card, sizeof(cmd_item->card_name)); - strncpy(cmd_item->dev_name, dev, sizeof(cmd_item->dev_name)); - strncpy(cmd_item->config_name, config, sizeof(cmd_item->config_name)); /* * dev name is special, we cant use "," in the command line diff --git a/tools/plugin/alsaplug/plugin.h b/tools/plugin/alsaplug/plugin.h index 37d93cc82701..dcc6f550ff53 100644 --- a/tools/plugin/alsaplug/plugin.h +++ b/tools/plugin/alsaplug/plugin.h @@ -61,7 +61,7 @@ int sofplug_load_hook(snd_config_t *root, snd_config_t *config, int plug_parse_conf(snd_sof_plug_t *plug, const char *name, snd_config_t *root, snd_config_t *conf, bool just_tplg); int plug_parse_topology(snd_sof_plug_t *plug); -int plug_set_up_pipelines(snd_sof_plug_t *plug, int dir); +int plug_set_up_pipelines(snd_sof_plug_t *plug, int dir, snd_pcm_hw_params_t *params); int plug_free_pipelines(snd_sof_plug_t *plug, struct tplg_pipeline_list *pipeline_list, int dir); void plug_free_topology(snd_sof_plug_t *plug); int plug_kcontrol_cb_new(struct snd_soc_tplg_ctl_hdr *tplg_ctl, void *_comp, void *arg, int index); diff --git a/tools/plugin/alsaplug/tplg.c b/tools/plugin/alsaplug/tplg.c index cbd8ba0cddf1..b3f04f4ee456 100644 --- a/tools/plugin/alsaplug/tplg.c +++ b/tools/plugin/alsaplug/tplg.c @@ -688,23 +688,29 @@ static int plug_is_single_format(struct sof_ipc4_pin_format *fmts, int num_forma } static int plug_match_audio_format(snd_sof_plug_t *plug, struct tplg_comp_info *comp_info, - struct plug_config *config) + snd_pcm_hw_params_t *params) { struct sof_ipc4_available_audio_format *available_fmt = &comp_info->available_fmt; struct ipc4_base_module_cfg *base_cfg = &comp_info->basecfg; struct sof_ipc4_pin_format *fmt; - int config_valid_bits; + snd_pcm_format_t params_format; + unsigned int params_channels, params_rate, dir; + int params_valid_bits; int i; - switch (config->format) { + snd_pcm_hw_params_get_channels(params, ¶ms_channels); + snd_pcm_hw_params_get_rate(params, ¶ms_rate, &dir); + snd_pcm_hw_params_get_format(params, ¶ms_format); + + switch (params_format) { case SND_PCM_FORMAT_S16_LE: - config_valid_bits = 16; + params_valid_bits = 16; break; case SND_PCM_FORMAT_S32_LE: - config_valid_bits = 32; + params_valid_bits = 32; break; case SND_PCM_FORMAT_S24_LE: - config_valid_bits = 24; + params_valid_bits = 24; break; default: break; @@ -725,14 +731,14 @@ static int plug_match_audio_format(snd_sof_plug_t *plug, struct tplg_comp_info * channels = fmt->audio_fmt.fmt_cfg & MASK(7, 0); valid_bits = (fmt->audio_fmt.fmt_cfg & MASK(15, 8)) >> 8; - if (rate == config->rate && channels == config->channels && - valid_bits == config_valid_bits) + if (rate == params_rate && channels == params_channels && + valid_bits == params_valid_bits) break; } if (i == available_fmt->num_input_formats) { SNDERR("Cannot find matching format for rate %d channels %d valid_bits %d for %s\n", - config->rate, config->channels, config_valid_bits, comp_info->name); + params_rate, params_channels, params_valid_bits, comp_info->name); return -EINVAL; } out: @@ -755,29 +761,13 @@ static int plug_match_audio_format(snd_sof_plug_t *plug, struct tplg_comp_info * return 0; } -static int plug_set_up_widget_base_config(snd_sof_plug_t *plug, struct tplg_comp_info *comp_info) +static int plug_set_up_widget_base_config(snd_sof_plug_t *plug, struct tplg_comp_info *comp_info, + snd_pcm_hw_params_t *params) { - struct plug_cmdline_item *cmd_item = &plug->cmdline[0]; - struct plug_config *config; - bool config_found = false; int ret, i; - for (i < 0; i < plug->num_configs; i++) { - config = &plug->config[i]; - - if (!strcmp(config->name, cmd_item->config_name)) { - config_found = true; - break; - } - } - - if (!config_found) { - SNDERR("unsupported config requested %s\n", cmd_item->config_name); - return -ENOTSUP; - } - /* match audio formats and populate base config */ - ret = plug_match_audio_format(plug, comp_info, config); + ret = plug_match_audio_format(plug, comp_info, params); if (ret < 0) return ret; @@ -985,7 +975,8 @@ static int plug_set_up_pipeline(snd_sof_plug_t *plug, struct tplg_pipeline_info } static int plug_prepare_widget(snd_sof_plug_t *plug, struct tplg_pcm_info *pcm_info, - struct tplg_comp_info *comp_info, int dir) + struct tplg_comp_info *comp_info, int dir, + snd_pcm_hw_params_t *params) { struct tplg_pipeline_list *pipeline_list; int ret, i; @@ -996,7 +987,7 @@ static int plug_prepare_widget(snd_sof_plug_t *plug, struct tplg_pcm_info *pcm_i pipeline_list = &pcm_info->playback_pipeline_list; /* populate base config */ - ret = plug_set_up_widget_base_config(plug, comp_info); + ret = plug_set_up_widget_base_config(plug, comp_info, params); if (ret < 0) return ret; @@ -1021,7 +1012,8 @@ static int plug_prepare_widget(snd_sof_plug_t *plug, struct tplg_pcm_info *pcm_i static int plug_prepare_widgets(snd_sof_plug_t *plug, struct tplg_pcm_info *pcm_info, struct tplg_comp_info *starting_comp_info, - struct tplg_comp_info *current_comp_info) + struct tplg_comp_info *current_comp_info, + snd_pcm_hw_params_t *params) { struct list_item *item; int ret; @@ -1036,13 +1028,13 @@ static int plug_prepare_widgets(snd_sof_plug_t *plug, struct tplg_pcm_info *pcm_ /* set up source widget if it is the starting widget */ if (starting_comp_info == current_comp_info) { - ret = plug_prepare_widget(plug, pcm_info, current_comp_info, 0); + ret = plug_prepare_widget(plug, pcm_info, current_comp_info, 0, params); if (ret < 0) return ret; } /* set up the sink widget */ - ret = plug_prepare_widget(plug, pcm_info, route_info->sink, 0); + ret = plug_prepare_widget(plug, pcm_info, route_info->sink, 0, params); if (ret < 0) return ret; @@ -1050,7 +1042,7 @@ static int plug_prepare_widgets(snd_sof_plug_t *plug, struct tplg_pcm_info *pcm_ if (route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_IN || route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_OUT) { ret = plug_prepare_widgets(plug, pcm_info, starting_comp_info, - route_info->sink); + route_info->sink, params); if (ret < 0) return ret; } @@ -1061,7 +1053,8 @@ static int plug_prepare_widgets(snd_sof_plug_t *plug, struct tplg_pcm_info *pcm_ static int plug_prepare_widgets_capture(snd_sof_plug_t *plug, struct tplg_pcm_info *pcm_info, struct tplg_comp_info *starting_comp_info, - struct tplg_comp_info *current_comp_info) + struct tplg_comp_info *current_comp_info, + snd_pcm_hw_params_t *params) { struct list_item *item; int ret; @@ -1076,13 +1069,13 @@ static int plug_prepare_widgets_capture(snd_sof_plug_t *plug, struct tplg_pcm_in /* set up sink widget if it is the starting widget */ if (starting_comp_info == current_comp_info) { - ret = plug_prepare_widget(plug, pcm_info, current_comp_info, 1); + ret = plug_prepare_widget(plug, pcm_info, current_comp_info, 1, params); if (ret < 0) return ret; } /* set up the source widget */ - ret = plug_prepare_widget(plug, pcm_info, route_info->source, 1); + ret = plug_prepare_widget(plug, pcm_info, route_info->source, 1, params); if (ret < 0) return ret; @@ -1090,7 +1083,7 @@ static int plug_prepare_widgets_capture(snd_sof_plug_t *plug, struct tplg_pcm_in if (route_info->source->type != SND_SOC_TPLG_DAPM_DAI_IN && route_info->source->type != SND_SOC_TPLG_DAPM_DAI_OUT) { ret = plug_prepare_widgets_capture(plug, pcm_info, starting_comp_info, - route_info->source); + route_info->source, params); if (ret < 0) return ret; } @@ -1282,7 +1275,7 @@ static int plug_set_up_widgets_capture(snd_sof_plug_t *plug, return 0; } -int plug_set_up_pipelines(snd_sof_plug_t *plug, int dir) +int plug_set_up_pipelines(snd_sof_plug_t *plug, int dir, snd_pcm_hw_params_t *params) { struct tplg_comp_info *host = NULL; struct tplg_pcm_info *pcm_info; @@ -1309,7 +1302,7 @@ int plug_set_up_pipelines(snd_sof_plug_t *plug, int dir) plug->pcm_info = pcm_info; if (dir) { - ret = plug_prepare_widgets_capture(plug, pcm_info, host, host); + ret = plug_prepare_widgets_capture(plug, pcm_info, host, host, params); if (ret < 0) return ret; @@ -1322,7 +1315,7 @@ int plug_set_up_pipelines(snd_sof_plug_t *plug, int dir) return 0; } - ret = plug_prepare_widgets(plug, pcm_info, host, host); + ret = plug_prepare_widgets(plug, pcm_info, host, host, params); if (ret < 0) return ret;