Add a new struct snd_pcm_hw_constraints under struct snd_soc_dpcm_runtime. The BE DAIs can use the new structure to add constraints that will not affect the FE of the PCM and will only apply to BE HW parameters. Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@xxxxxxxxxxxxx> --- include/sound/pcm.h | 9 ++++++++ include/sound/soc-dpcm.h | 1 + sound/core/pcm_lib.c | 12 +++++++++-- sound/core/pcm_native.c | 20 ++++++++++-------- sound/soc/soc-pcm.c | 44 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 76 insertions(+), 10 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index af7fce2b574d..198d37d04d78 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -977,6 +977,15 @@ int snd_interval_ratnum(struct snd_interval *i, void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params); void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var); +int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule); +int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule); +int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule); +int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule); + int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index e296a3949b18..c5825876824a 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -95,6 +95,7 @@ struct snd_soc_dpcm_runtime { int users; struct snd_pcm_runtime *runtime; struct snd_pcm_hw_params hw_params; + struct snd_pcm_hw_constraints hw_constraints; /* state and update */ enum snd_soc_dpcm_update runtime_update; diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 582144f99045..125fafdf7517 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -16,6 +16,7 @@ #include <sound/info.h> #include <sound/pcm.h> #include <sound/pcm_params.h> +#include <sound/soc.h> #include <sound/timer.h> #include "pcm_local.h" @@ -1121,12 +1122,19 @@ int snd_pcm_hw_rule_add(struct snd_pcm_substream *substream, unsigned int cond, snd_pcm_hw_rule_func_t func, void *private, int dep, ...) { - struct snd_pcm_hw_constraints *constrs = - &substream->runtime->hw_constraints; + struct snd_pcm_hw_constraints *constrs; struct snd_pcm_hw_rule *c; unsigned int k; va_list args; + if (substream->pcm->internal) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dpcm_runtime *dpcm = &rtd->dpcm[substream->stream]; + + constrs = &dpcm->hw_constraints; + } else { + constrs = &substream->runtime->hw_constraints; + } va_start(args, dep); if (constrs->rules_num >= constrs->rules_all) { struct snd_pcm_hw_rule *new; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 5feeef1b43f1..d6f14162bce5 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2278,23 +2278,25 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream) /* * hw configurator */ -static int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) +int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) { struct snd_interval t; snd_interval_mul(hw_param_interval_c(params, rule->deps[0]), hw_param_interval_c(params, rule->deps[1]), &t); return snd_interval_refine(hw_param_interval(params, rule->var), &t); } +EXPORT_SYMBOL(snd_pcm_hw_rule_mul); -static int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) +int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) { struct snd_interval t; snd_interval_div(hw_param_interval_c(params, rule->deps[0]), hw_param_interval_c(params, rule->deps[1]), &t); return snd_interval_refine(hw_param_interval(params, rule->var), &t); } +EXPORT_SYMBOL(snd_pcm_hw_rule_div); static int snd_pcm_hw_rule_muldivk(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) @@ -2316,8 +2318,8 @@ static int snd_pcm_hw_rule_mulkdiv(struct snd_pcm_hw_params *params, return snd_interval_refine(hw_param_interval(params, rule->var), &t); } -static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) +int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) { snd_pcm_format_t k; const struct snd_interval *i = @@ -2337,9 +2339,10 @@ static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params, } return snd_mask_refine(mask, &m); } +EXPORT_SYMBOL(snd_pcm_hw_rule_format); -static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) +int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) { struct snd_interval t; snd_pcm_format_t k; @@ -2363,6 +2366,7 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, t.integer = 1; return snd_interval_refine(hw_param_interval(params, rule->var), &t); } +EXPORT_SYMBOL(snd_pcm_hw_rule_sample_bits); #if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 #error "Change this table" diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 65f8ea73bae7..dae246918e0d 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1471,6 +1471,43 @@ void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream, } } +static int dpcm_hw_constraints_init(struct snd_pcm_substream *substream) +{ + int err; + + if (!substream->pcm->internal) + return 0; + + err = snd_pcm_hw_rule_add(substream, 0, SNDRV_PCM_HW_PARAM_FORMAT, + snd_pcm_hw_rule_format, NULL, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); + if (err < 0) + return err; + err = snd_pcm_hw_rule_add(substream, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + snd_pcm_hw_rule_sample_bits, NULL, + SNDRV_PCM_HW_PARAM_FORMAT, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); + if (err < 0) + return err; + err = snd_pcm_hw_rule_add(substream, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + snd_pcm_hw_rule_div, NULL, + SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1); + if (err < 0) + return err; + err = snd_pcm_hw_rule_add(substream, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS, + snd_pcm_hw_rule_mul, NULL, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1); + if (err < 0) + return err; + err = snd_pcm_hw_rule_add(substream, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + snd_pcm_hw_rule_div, NULL, + SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + -1); + if (err < 0) + return err; + return 0; +} + int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_soc_pcm_runtime *be; @@ -1513,6 +1550,13 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) stream ? "capture" : "playback", be->dai_link->name); be_substream->runtime = be->dpcm[stream].runtime; + + /* initialize the BE constraints */ + err = dpcm_hw_constraints_init(be_substream); + if (err < 0) { + dev_dbg(be->dev, "dpcm_hw_constraints_init failed\n"); + goto unwind; + } err = soc_pcm_open(be_substream); if (err < 0) { be->dpcm[stream].users--; -- 2.27.0