All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sven Van Asbroeck <thesven73@gmail.com>
To: Mark Brown <broonie@kernel.org>
Cc: alsa-devel@alsa-project.org, Liam Girdwood <lgirdwood@gmail.com>,
	Jyri Sarha <jsarha@ti.com>, Takashi Iwai <tiwai@suse.com>,
	Peter Ujfalusi <peter.ujfalusi@ti.com>,
	Russell King <rmk+kernel@armlinux.org.uk>
Subject: [RFC PATCH 1/4] alsa: make hw_params negotiation infrastructure 'bclk_ratio aware'
Date: Mon,  4 Mar 2019 11:59:52 -0500	[thread overview]
Message-ID: <20190304165955.21696-1-TheSven73@gmail.com> (raw)

Negotiation seems to work ok, but bclk_ratio is exposed to
userspace via snd_pcm_hw_params, which is not acceptable.

Constrain bclk_ratio by:
- cpu   dai capabilities && rules
- codec dai capabilities && rules
- minimum bclk_ratio is sample_width * channels

In hw_params_choose(), pick the smallest supported bclk_ratio,
which should correspond to the most efficient solution.

If cpu and codec dais do not specify or constrain supported
bclk_ratios, alsa will pick sample_width * channels.

Signed-off-by: Sven Van Asbroeck <TheSven73@gmail.com>
---
 include/sound/pcm.h         | 11 +++++++++++
 include/sound/soc.h         |  2 ++
 include/uapi/sound/asound.h |  5 +++--
 sound/core/pcm_native.c     | 34 +++++++++++++++++++++++++++++++++-
 sound/soc/soc-pcm.c         |  8 ++++++++
 5 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index d6bd3caf6878..71ac7e8de23d 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -56,6 +56,8 @@ struct snd_pcm_hardware {
 	unsigned int periods_min;	/* min # of periods */
 	unsigned int periods_max;	/* max # of periods */
 	size_t fifo_size;		/* fifo size in bytes */
+	unsigned int bclk_ratio_min;	/* min bclk ratio for wire format */
+	unsigned int bclk_ratio_max;	/* max bclk ratio for wire format */
 };
 
 struct snd_pcm_substream;
@@ -980,6 +982,15 @@ static inline unsigned int params_buffer_bytes(const struct snd_pcm_hw_params *p
 	return hw_param_interval_c(p, SNDRV_PCM_HW_PARAM_BUFFER_BYTES)->min;
 }
 
+/**
+ * params_bclk_ratio - Get the bclk_ratio from the hw params
+ * @p: hw params
+ */
+static inline unsigned int params_bclk_ratio(const struct snd_pcm_hw_params *p)
+{
+	return hw_param_interval_c(p, SNDRV_PCM_HW_PARAM_BCLK_RATIO)->min;
+}
+
 int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v);
 int snd_interval_list(struct snd_interval *i, unsigned int count,
 		      const unsigned int *list, unsigned int mask);
diff --git a/include/sound/soc.h b/include/sound/soc.h
index e665f111b0d2..96d669423688 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -732,6 +732,8 @@ struct snd_soc_pcm_stream {
 	unsigned int channels_min;	/* min channels */
 	unsigned int channels_max;	/* max channels */
 	unsigned int sig_bits;		/* number of bits of content */
+	unsigned int bclk_ratio_min;	/* min bclk ratio for wire format */
+	unsigned int bclk_ratio_max;	/* max bclk ratio for wire format */
 };
 
 /* SoC audio ops */
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
index 404d4b9ffe76..c3ea94eaaa77 100644
--- a/include/uapi/sound/asound.h
+++ b/include/uapi/sound/asound.h
@@ -371,8 +371,9 @@ typedef int snd_pcm_hw_param_t;
 #define	SNDRV_PCM_HW_PARAM_BUFFER_SIZE	17	/* Size of buffer in frames */
 #define	SNDRV_PCM_HW_PARAM_BUFFER_BYTES	18	/* Size of buffer in bytes */
 #define	SNDRV_PCM_HW_PARAM_TICK_TIME	19	/* Approx tick duration in us */
+#define SNDRV_PCM_HW_PARAM_BCLK_RATIO	20	/* bclk_ratio for wire format */
 #define	SNDRV_PCM_HW_PARAM_FIRST_INTERVAL	SNDRV_PCM_HW_PARAM_SAMPLE_BITS
-#define	SNDRV_PCM_HW_PARAM_LAST_INTERVAL	SNDRV_PCM_HW_PARAM_TICK_TIME
+#define	SNDRV_PCM_HW_PARAM_LAST_INTERVAL	SNDRV_PCM_HW_PARAM_BCLK_RATIO
 
 #define SNDRV_PCM_HW_PARAMS_NORESAMPLE	(1<<0)	/* avoid rate resampling */
 #define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER	(1<<1)	/* export buffer */
@@ -399,7 +400,7 @@ struct snd_pcm_hw_params {
 	struct snd_mask mres[5];	/* reserved masks */
 	struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
 				        SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
-	struct snd_interval ires[9];	/* reserved intervals */
+	struct snd_interval ires[8];	/* reserved intervals */
 	unsigned int rmask;		/* W: requested masks */
 	unsigned int cmask;		/* R: changed masks */
 	unsigned int info;		/* R: Info flags for returned setup */
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 818dff1de545..23dbe43a6691 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -516,6 +516,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
 		      struct snd_pcm_hw_params *params)
 {
 	int err;
+	struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_BCLK_RATIO);
 
 	params->info = 0;
 	params->fifo_size = 0;
@@ -525,6 +526,12 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
 		params->rate_num = 0;
 		params->rate_den = 0;
 	}
+	/*
+	 * if left zero (not empty), assume userspace is oblivious, and
+	 * completely flexible
+	 */
+	if (snd_interval_single(r) && snd_interval_min(r) == 0)
+		snd_interval_any(r);
 
 	err = constrain_mask_params(substream, params);
 	if (err < 0)
@@ -610,7 +617,8 @@ static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream,
  * Choose one configuration from configuration space defined by @params.
  * The configuration chosen is that obtained fixing in this order:
  * first access, first format, first subformat, min channels,
- * min rate, min period time, max buffer size, min tick time
+ * min rate, min period time, max buffer size, min tick time,
+ * min bclk_ratio
  *
  * Return: Zero if successful, or a negative error code on failure.
  */
@@ -626,6 +634,7 @@ static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
 		SNDRV_PCM_HW_PARAM_PERIOD_TIME,
 		SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
 		SNDRV_PCM_HW_PARAM_TICK_TIME,
+		SNDRV_PCM_HW_PARAM_BCLK_RATIO,
 		-1
 	};
 	const int *v;
@@ -2100,6 +2109,18 @@ static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params,
 	return snd_mask_refine(mask, &m);
 }
 
+static int snd_pcm_hw_rule_bclk_ratio(struct snd_pcm_hw_params *params,
+				  struct snd_pcm_hw_rule *rule)
+{
+	struct snd_interval i;
+	struct snd_interval *ratios = hw_param_interval(params, SNDRV_PCM_HW_PARAM_BCLK_RATIO);
+	snd_interval_any(&i);
+	i.openmax = 1;
+	i.min = params_channels(params) * params_width(params);
+	i.integer = 1;
+	return snd_interval_refine(ratios, &i);
+}
+
 static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
 				       struct snd_pcm_hw_rule *rule)
 {
@@ -2180,12 +2201,18 @@ int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
 	snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_BYTES));
 	snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_SAMPLE_BITS));
 	snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_FRAME_BITS));
+	snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BCLK_RATIO));
 
 	err = snd_pcm_hw_rule_add(runtime, 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(runtime, 0, SNDRV_PCM_HW_PARAM_BCLK_RATIO,
+				   snd_pcm_hw_rule_bclk_ratio, NULL,
+				   SNDRV_PCM_HW_PARAM_SAMPLE_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	if (err < 0)
+		return err;
 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 
 				  snd_pcm_hw_rule_sample_bits, NULL,
 				  SNDRV_PCM_HW_PARAM_FORMAT, 
@@ -2341,6 +2368,11 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
 	if (err < 0)
 		return err;
 
+	err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BCLK_RATIO,
+					   hw->bclk_ratio_min, hw->bclk_ratio_max);
+	if (err < 0)
+		return err;
+
 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 
 				  snd_pcm_hw_rule_buffer_bytes_max, substream,
 				  SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1);
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 03f36e534050..747026595634 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -381,6 +381,7 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
 	struct snd_soc_pcm_stream *cpu_stream;
 	unsigned int chan_min = 0, chan_max = UINT_MAX;
 	unsigned int rate_min = 0, rate_max = UINT_MAX;
+	unsigned int bclk_ratio_min = 0, bclk_ratio_max = UINT_MAX;
 	unsigned int rates = UINT_MAX;
 	u64 formats = ULLONG_MAX;
 	int i;
@@ -413,6 +414,8 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
 			codec_stream = &codec_dai_drv->capture;
 		chan_min = max(chan_min, codec_stream->channels_min);
 		chan_max = min(chan_max, codec_stream->channels_max);
+		bclk_ratio_min = max(bclk_ratio_min, codec_stream->bclk_ratio_min);
+		bclk_ratio_max = min_not_zero(bclk_ratio_max, codec_stream->bclk_ratio_max);
 		rate_min = max(rate_min, codec_stream->rate_min);
 		rate_max = min_not_zero(rate_max, codec_stream->rate_max);
 		formats &= codec_stream->formats;
@@ -443,6 +446,11 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
 	hw->rate_min = max(hw->rate_min, rate_min);
 	hw->rate_max = min_not_zero(hw->rate_max, cpu_stream->rate_max);
 	hw->rate_max = min_not_zero(hw->rate_max, rate_max);
+
+	hw->bclk_ratio_min = max(hw->bclk_ratio_min, cpu_stream->bclk_ratio_min);
+	hw->bclk_ratio_min = max(hw->bclk_ratio_min, bclk_ratio_min);
+	hw->bclk_ratio_max = min_not_zero(hw->bclk_ratio_max, cpu_stream->bclk_ratio_max);
+	hw->bclk_ratio_max = min_not_zero(hw->bclk_ratio_max, bclk_ratio_max);
 }
 
 static int soc_pcm_components_close(struct snd_pcm_substream *substream,
-- 
2.17.1

             reply	other threads:[~2019-03-04 17:00 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-04 16:59 Sven Van Asbroeck [this message]
2019-03-04 16:59 ` [RFC PATCH 2/4] ASoC: hdmi-codec: add support for bclk_ratio Sven Van Asbroeck
2019-03-04 16:59 ` [RFC PATCH 3/4] drm/i2c: tda998x: calculate CTS_N directly from the bclk_ratio Sven Van Asbroeck
2019-03-04 16:59 ` [RFC PATCH 4/4] ASoC: fsl_ssi: constrain bclk_ratio in i2s master mode Sven Van Asbroeck
2019-03-05  4:42 ` [RFC PATCH 1/4] alsa: make hw_params negotiation infrastructure 'bclk_ratio aware' Takashi Sakamoto
2019-03-05  9:35   ` Russell King - ARM Linux admin
2019-03-05 14:23   ` Sven Van Asbroeck
2019-03-06 15:53     ` Jaroslav Kysela
2019-03-08  4:10     ` Takashi Sakamoto
2019-03-08 12:59       ` Russell King - ARM Linux admin
2019-03-08 13:37         ` Russell King - ARM Linux admin
2019-03-08 14:29         ` Takashi Sakamoto
2019-03-08 14:55           ` Russell King - ARM Linux admin
2019-03-08 17:22         ` Mark Brown
2019-03-08 19:54           ` Jaroslav Kysela
2019-03-08 20:07             ` Sven Van Asbroeck
2019-03-08 20:49               ` Pierre-Louis Bossart
2019-03-08 21:13                 ` Mark Brown
2019-03-08 21:54                   ` Pierre-Louis Bossart
2019-03-11  8:15             ` Takashi Sakamoto
2019-03-11 15:43               ` Jaroslav Kysela
2019-03-12 15:03                 ` Mark Brown
2019-03-13  5:57                   ` Takashi Sakamoto

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190304165955.21696-1-TheSven73@gmail.com \
    --to=thesven73@gmail.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=broonie@kernel.org \
    --cc=jsarha@ti.com \
    --cc=lgirdwood@gmail.com \
    --cc=peter.ujfalusi@ti.com \
    --cc=rmk+kernel@armlinux.org.uk \
    --cc=tiwai@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.