0566-bcm2835-i2s-Changes-for-allowing-asymmetric-sample-f.patch 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. From b97a67a14e5c5904b84e52150e0d13da794fc9d7 Mon Sep 17 00:00:00 2001
  2. From: gtrainavicius <gtrainavicius@users.noreply.github.com>
  3. Date: Tue, 10 Jan 2017 21:59:39 +0200
  4. Subject: [PATCH] bcm2835-i2s: Changes for allowing asymmetric sample formats.
  5. (#1783)
  6. This is achieved by making changes only to the requested
  7. stream direction format, keeping the other stream direction
  8. configuration intact.
  9. Signed-off-by: Giedrius Trainavicius <giedrius@blokas.io>
  10. ---
  11. sound/soc/bcm/bcm2835-i2s.c | 54 +++++++++++++++++++++++++++++++--------------
  12. 1 file changed, 38 insertions(+), 16 deletions(-)
  13. --- a/sound/soc/bcm/bcm2835-i2s.c
  14. +++ b/sound/soc/bcm/bcm2835-i2s.c
  15. @@ -310,6 +310,7 @@ static int bcm2835_i2s_hw_params(struct
  16. unsigned int sampling_rate = params_rate(params);
  17. unsigned int data_length, data_delay, bclk_ratio;
  18. unsigned int ch1pos, ch2pos, mode, format;
  19. + unsigned int previous_ftxp, previous_frxp;
  20. unsigned int mash = BCM2835_CLK_MASH_1;
  21. unsigned int divi, divf, target_frequency;
  22. int clk_src = -1;
  23. @@ -320,6 +321,7 @@ static int bcm2835_i2s_hw_params(struct
  24. bool frame_master = (master == SND_SOC_DAIFMT_CBS_CFS
  25. || master == SND_SOC_DAIFMT_CBM_CFS);
  26. uint32_t csreg;
  27. + bool packed;
  28. /*
  29. * If a stream is already enabled,
  30. @@ -465,26 +467,46 @@ static int bcm2835_i2s_hw_params(struct
  31. return -EINVAL;
  32. }
  33. - /*
  34. - * Set format for both streams.
  35. - * We cannot set another frame length
  36. - * (and therefore word length) anyway,
  37. - * so the format will be the same.
  38. - */
  39. - regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format);
  40. - regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format);
  41. + /* Set the format for the matching stream direction. */
  42. + switch (substream->stream) {
  43. + case SNDRV_PCM_STREAM_PLAYBACK:
  44. + regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format);
  45. + break;
  46. + case SNDRV_PCM_STREAM_CAPTURE:
  47. + regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format);
  48. + break;
  49. + default:
  50. + return -EINVAL;
  51. + }
  52. /* Setup the I2S mode */
  53. + /* Keep existing FTXP and FRXP values. */
  54. + regmap_read(dev->i2s_regmap, BCM2835_I2S_MODE_A_REG, &mode);
  55. +
  56. + previous_ftxp = mode & BCM2835_I2S_FTXP;
  57. + previous_frxp = mode & BCM2835_I2S_FRXP;
  58. +
  59. mode = 0;
  60. - if (data_length <= 16) {
  61. - /*
  62. - * Use frame packed mode (2 channels per 32 bit word)
  63. - * We cannot set another frame length in the second stream
  64. - * (and therefore word length) anyway,
  65. - * so the format will be the same.
  66. - */
  67. - mode |= BCM2835_I2S_FTXP | BCM2835_I2S_FRXP;
  68. + /*
  69. + * Retain the frame packed mode (2 channels per 32 bit word)
  70. + * of the other direction stream intact. The formats of each
  71. + * direction can be different as long as the frame length is
  72. + * shared for both.
  73. + */
  74. + packed = data_length <= 16;
  75. +
  76. + switch (substream->stream) {
  77. + case SNDRV_PCM_STREAM_PLAYBACK:
  78. + mode |= previous_frxp;
  79. + mode |= packed ? BCM2835_I2S_FTXP : 0;
  80. + break;
  81. + case SNDRV_PCM_STREAM_CAPTURE:
  82. + mode |= previous_ftxp;
  83. + mode |= packed ? BCM2835_I2S_FRXP : 0;
  84. + break;
  85. + default:
  86. + return -EINVAL;
  87. }
  88. mode |= BCM2835_I2S_FLEN(bclk_ratio - 1);