[alsa-devel] [PATCH v2 1/5] ASoC: pcm: Properly initialize hw->rate_max
If none of the components (CODEC or CPU DAI) sets a maximum sample rate we'll end up with the rate_max field of the runtime hardware set to 0. (Note that it is still possible for the components to constrain the supported sample rates using other methods, e.g. setting a list constraint) If rate_max is 0 this means that the sound card doesn't support any rates at all, which is not the desired result. So initialize rate_max to UINT_MAX. For symmetry reasons also set rate_min to 0.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- No changes in v2 --- sound/soc/soc-pcm.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 313adba..b6e0c32 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -252,6 +252,9 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_runtime *runtime, & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) hw->rates |= codec_stream->rates;
+ hw->rate_min = 0; + hw->rate_max = UINT_MAX; + snd_pcm_limit_hw_rates(runtime);
hw->rate_min = max(hw->rate_min, cpu_stream->rate_min);
SNDRV_PCM_RATE_CONTINUOUS means that all rates (possibly limited to a certain interval) are supported. There is no need to manually set other rate bits.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de Cc: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- No changes in v2 --- sound/soc/fsl/fsl_ssi.c | 3 +-- sound/soc/fsl/mpc5200_psc_i2s.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 7864ec5..f9090b1 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -81,8 +81,7 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set) * ALSA that we support all rates and let the codec driver decide what rates * are really supported. */ -#define FSLSSI_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \ - SNDRV_PCM_RATE_CONTINUOUS) +#define FSLSSI_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS
/** * FSLSSI_I2S_FORMATS: audio formats supported by the SSI diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index f4efaad..5d07e8a 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -26,8 +26,7 @@ * ALSA that we support all rates and let the codec driver decide what rates * are really supported. */ -#define PSC_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \ - SNDRV_PCM_RATE_CONTINUOUS) +#define PSC_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS
/** * PSC_I2S_FORMATS: audio formats supported by the PSC I2S mode
SNDRV_PCM_RATE_CONTINUOUS means that all rates (possibly limited to a certain interval) are supported. There is no need to manually set other rate bits.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de Cc: Acked-by: Daniel Glöckner daniel-gl@gmx.net --- No changes in v2 --- sound/soc/s6000/s6000-i2s.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c index 73bb99f..7eba797 100644 --- a/sound/soc/s6000/s6000-i2s.c +++ b/sound/soc/s6000/s6000-i2s.c @@ -405,8 +405,7 @@ static int s6000_i2s_dai_probe(struct snd_soc_dai *dai) return 0; }
-#define S6000_I2S_RATES (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_5512 | \ - SNDRV_PCM_RATE_8000_192000) +#define S6000_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS #define S6000_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
static const struct snd_soc_dai_ops s6000_i2s_dai_ops = {
On 01/11/2014 10:24 AM, Lars-Peter Clausen wrote:
SNDRV_PCM_RATE_CONTINUOUS means that all rates (possibly limited to a certain interval) are supported. There is no need to manually set other rate bits.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de Cc: Acked-by: Daniel Glöckner daniel-gl@gmx.net
Uhm, sorry, the "Acked-by:" should have not been there.
On Sat, Jan 11, 2014 at 10:29:26AM +0100, Lars-Peter Clausen wrote:
On 01/11/2014 10:24 AM, Lars-Peter Clausen wrote:
Signed-off-by: Lars-Peter Clausen lars@metafoo.de Cc: Acked-by: Daniel Glöckner daniel-gl@gmx.net
Uhm, sorry, the "Acked-by:" should have not been there.
Acked-by: Daniel Glöckner daniel-gl@gmx.net provided 4/5 and 5/5 get applied first
A bit of special care is necessary when creating the intersection of two rate masks. This comes from the special meaning of the SNDRV_PCM_RATE_CONTINUOUS and SNDRV_PCM_RATE_KNOT bits, which needs special handling when intersecting two rate masks. SNDRV_PCM_RATE_CONTINUOUS means the hardware supports all rates in a specific interval. SNDRV_PCM_RATE_KNOT means the hardware supports a set of discrete rates specified by a list constraint. For all other cases the supported rates are specified directly in the rate mask.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de Reviewed-by: Takashi Iwai tiwai@suse.de --- Changes since v1: * Use EXPORT_SYMBOL_GPL instead of EXPORT_SYMBOL --- include/sound/pcm.h | 2 ++ sound/core/pcm_misc.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 84b10f9..d017091 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -901,6 +901,8 @@ extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates; int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime); unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate); unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit); +unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a, + unsigned int rates_b);
static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream, struct snd_dma_buffer *bufp) diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index 43f24cc..4560ca0 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c @@ -514,3 +514,42 @@ unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit) return 0; } EXPORT_SYMBOL(snd_pcm_rate_bit_to_rate); + +static unsigned int snd_pcm_rate_mask_sanitize(unsigned int rates) +{ + if (rates & SNDRV_PCM_RATE_CONTINUOUS) + return SNDRV_PCM_RATE_CONTINUOUS; + else if (rates & SNDRV_PCM_RATE_KNOT) + return SNDRV_PCM_RATE_KNOT; + return rates; +} + +/** + * snd_pcm_rate_mask_intersect - computes the intersection between two rate masks + * @rates_a: The first rate mask + * @rates_b: The second rate mask + * + * This function computes the rates that are supported by both rate masks passed + * to the function. It will take care of the special handling of + * SNDRV_PCM_RATE_CONTINUOUS and SNDRV_PCM_RATE_KNOT. + * + * Return: A rate mask containing the rates that are supported by both rates_a + * and rates_b. + */ +unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a, + unsigned int rates_b) +{ + rates_a = snd_pcm_rate_mask_sanitize(rates_a); + rates_b = snd_pcm_rate_mask_sanitize(rates_b); + + if (rates_a & SNDRV_PCM_RATE_CONTINUOUS) + return rates_b; + else if (rates_b & SNDRV_PCM_RATE_CONTINUOUS) + return rates_a; + else if (rates_a & SNDRV_PCM_RATE_KNOT) + return rates_b; + else if (rates_b & SNDRV_PCM_RATE_KNOT) + return rates_a; + return rates_a & rates_b; +} +EXPORT_SYMBOL_GPL(snd_pcm_rate_mask_intersect);
Instead of open-coding the intersecting of two rate masks (and getting slightly wrong for some of the corner cases) use the new snd_pcm_rate_mask_intersect() helper function.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de --- No changes in v2 --- sound/soc/soc-pcm.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b6e0c32..5932971 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -244,13 +244,8 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_runtime *runtime, hw->formats &= codec_stream->formats & cpu_stream->formats; else hw->formats = codec_stream->formats & cpu_stream->formats; - hw->rates = codec_stream->rates & cpu_stream->rates; - if (codec_stream->rates - & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) - hw->rates |= cpu_stream->rates; - if (cpu_stream->rates - & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) - hw->rates |= codec_stream->rates; + hw->rates = snd_pcm_rate_mask_intersect(codec_stream->rates, + cpu_stream->rates);
hw->rate_min = 0; hw->rate_max = UINT_MAX;
participants (3)
-
Daniel Glöckner
-
Lars-Peter Clausen
-
Mark Brown