[alsa-devel] [PATCH 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 --- 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 --- 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 f662ddd..33a4738 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 --- 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 = {
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 --- 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..1552537 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(snd_pcm_rate_mask_intersect);
At Fri, 10 Jan 2014 16:06:35 +0100, Lars-Peter Clausen wrote:
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
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..1552537 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(snd_pcm_rate_mask_intersect);
We can use EXPORT_SYMBOL_GPL() for new functions safely.
I suppose this patchset will go through ASoC tree? Then take my ack:
Reviewed-by: Takashi Iwai tiwai@suse.de
thanks,
Takashi
On 01/10/2014 04:17 PM, Takashi Iwai wrote:
At Fri, 10 Jan 2014 16:06:35 +0100, Lars-Peter Clausen wrote:
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
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..1552537 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(snd_pcm_rate_mask_intersect);
We can use EXPORT_SYMBOL_GPL() for new functions safely.
Ok, I'll change that.
I suppose this patchset will go through ASoC tree? Then take my ack:
Reviewed-by: Takashi Iwai <tiwai@suse.de>
Thanks.
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 --- 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 (2)
-
Lars-Peter Clausen
-
Takashi Iwai