0127-bcm2835-restrict-channels-rate-to-8-960000.patch 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. From f204c383ca1e309b94e7c447b1b15f1063a4d2ba Mon Sep 17 00:00:00 2001
  2. From: wm4 <wm4@nowhere>
  3. Date: Wed, 13 Jan 2016 19:42:18 +0100
  4. Subject: [PATCH] bcm2835: restrict channels*rate to 8*960000
  5. This is required at least for SPDIF. If the bitrate goes above,
  6. videocore will either resample the audio or corrupt it due to
  7. underruns. Supposedly the hardware isn't designed to output
  8. higher rates, but it can still resample it down to supported
  9. rates.
  10. Some code is based on ac97_pcm.c.
  11. ---
  12. sound/arm/bcm2835-pcm.c | 41 +++++++++++++++++++++++++++++++++++++++++
  13. 1 file changed, 41 insertions(+)
  14. --- a/sound/arm/bcm2835-pcm.c
  15. +++ b/sound/arm/bcm2835-pcm.c
  16. @@ -19,6 +19,9 @@
  17. #include "bcm2835.h"
  18. +/* The hardware can not do much more num_channels*samplerate then this value */
  19. +#define MAX_COMBINED_RATE 768000
  20. +
  21. /* hardware definition */
  22. static struct snd_pcm_hardware snd_bcm2835_playback_hw = {
  23. .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
  24. @@ -107,6 +110,31 @@ static irqreturn_t bcm2835_playback_fifo
  25. return IRQ_HANDLED;
  26. }
  27. +
  28. +static int rate_hw_constraint_rate(struct snd_pcm_hw_params *params,
  29. + struct snd_pcm_hw_rule *rule)
  30. +{
  31. + struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  32. + struct snd_interval rates = {
  33. + .min = 8000,
  34. + .max = min(192000u, MAX_COMBINED_RATE / max(channels->min, 1u)),
  35. + };
  36. + struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
  37. + return snd_interval_refine(rate, &rates);
  38. +}
  39. +
  40. +static int rate_hw_constraint_channels(struct snd_pcm_hw_params *params,
  41. + struct snd_pcm_hw_rule *rule)
  42. +{
  43. + struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
  44. + struct snd_interval channels_interval = {
  45. + .min = 1,
  46. + .max = min(8u, MAX_COMBINED_RATE / max(rate->min, 1u)),
  47. + };
  48. + struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  49. + return snd_interval_refine(channels, &channels_interval);
  50. +}
  51. +
  52. /* open callback */
  53. static int snd_bcm2835_playback_open_generic(
  54. struct snd_pcm_substream *substream, int spdif)
  55. @@ -188,6 +216,19 @@ static int snd_bcm2835_playback_open_gen
  56. snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
  57. 16);
  58. + /* When playing PCM, pretend that we support the full range of channels
  59. + * and sample rates. The GPU can't output it, but is able to resample
  60. + * the data to a rate the hardware can handle it. This won't work with
  61. + * compressed data; the resampler would just destroy it. */
  62. + if (spdif) {
  63. + err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
  64. + rate_hw_constraint_rate, NULL,
  65. + SNDRV_PCM_HW_PARAM_CHANNELS, -1);
  66. + err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
  67. + rate_hw_constraint_channels, NULL,
  68. + SNDRV_PCM_HW_PARAM_RATE, -1);
  69. + }
  70. +
  71. chip->alsa_stream[idx] = alsa_stream;
  72. chip->opened |= (1 << idx);