[RFC PATCH 2/3] ASoC: soc-pcm: add hw_constraints for BE DAI links

From: Codrin Ciubotariu
Date: Tue Mar 23 2021 - 07:44:48 EST


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