90 lines
2.7 KiB
Diff
90 lines
2.7 KiB
Diff
|
From 425ee76116894c97d5d97ad4883eb2612b8692f3 Mon Sep 17 00:00:00 2001
|
||
|
From: Giedrius Trainavicius <giedrius@blokas.io>
|
||
|
Date: Sun, 8 Jan 2017 15:58:54 +0200
|
||
|
Subject: [PATCH] bcm2835-i2s: Changes for allowing asymmetric sample formats.
|
||
|
|
||
|
This is achieved by making changes only to the requested
|
||
|
stream direction format, keeping the other stream direction
|
||
|
configuration intact.
|
||
|
|
||
|
Signed-off-by: Giedrius Trainavicius <giedrius@blokas.io>
|
||
|
---
|
||
|
sound/soc/bcm/bcm2835-i2s.c | 54 +++++++++++++++++++++++++++++++--------------
|
||
|
1 file changed, 38 insertions(+), 16 deletions(-)
|
||
|
|
||
|
--- a/sound/soc/bcm/bcm2835-i2s.c
|
||
|
+++ b/sound/soc/bcm/bcm2835-i2s.c
|
||
|
@@ -237,7 +237,9 @@ static int bcm2835_i2s_hw_params(struct
|
||
|
unsigned int sampling_rate = params_rate(params);
|
||
|
unsigned int data_length, data_delay, bclk_ratio;
|
||
|
unsigned int ch1pos, ch2pos, mode, format;
|
||
|
+ unsigned int previous_ftxp, previous_frxp;
|
||
|
uint32_t csreg;
|
||
|
+ bool packed;
|
||
|
|
||
|
/*
|
||
|
* If a stream is already enabled,
|
||
|
@@ -320,26 +322,46 @@ static int bcm2835_i2s_hw_params(struct
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
- /*
|
||
|
- * Set format for both streams.
|
||
|
- * We cannot set another frame length
|
||
|
- * (and therefore word length) anyway,
|
||
|
- * so the format will be the same.
|
||
|
- */
|
||
|
- regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format);
|
||
|
- regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format);
|
||
|
+ /* Set the format for the matching stream direction. */
|
||
|
+ switch (substream->stream) {
|
||
|
+ case SNDRV_PCM_STREAM_PLAYBACK:
|
||
|
+ regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format);
|
||
|
+ break;
|
||
|
+ case SNDRV_PCM_STREAM_CAPTURE:
|
||
|
+ regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format);
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
|
||
|
/* Setup the I2S mode */
|
||
|
+ /* Keep existing FTXP and FRXP values. */
|
||
|
+ regmap_read(dev->i2s_regmap, BCM2835_I2S_MODE_A_REG, &mode);
|
||
|
+
|
||
|
+ previous_ftxp = mode & BCM2835_I2S_FTXP;
|
||
|
+ previous_frxp = mode & BCM2835_I2S_FRXP;
|
||
|
+
|
||
|
mode = 0;
|
||
|
|
||
|
- if (data_length <= 16) {
|
||
|
- /*
|
||
|
- * Use frame packed mode (2 channels per 32 bit word)
|
||
|
- * We cannot set another frame length in the second stream
|
||
|
- * (and therefore word length) anyway,
|
||
|
- * so the format will be the same.
|
||
|
- */
|
||
|
- mode |= BCM2835_I2S_FTXP | BCM2835_I2S_FRXP;
|
||
|
+ /*
|
||
|
+ * Retain the frame packed mode (2 channels per 32 bit word)
|
||
|
+ * of the other direction stream intact. The formats of each
|
||
|
+ * direction can be different as long as the frame length is
|
||
|
+ * shared for both.
|
||
|
+ */
|
||
|
+ packed = data_length <= 16;
|
||
|
+
|
||
|
+ switch (substream->stream) {
|
||
|
+ case SNDRV_PCM_STREAM_PLAYBACK:
|
||
|
+ mode |= previous_frxp;
|
||
|
+ mode |= packed ? BCM2835_I2S_FTXP : 0;
|
||
|
+ break;
|
||
|
+ case SNDRV_PCM_STREAM_CAPTURE:
|
||
|
+ mode |= previous_ftxp;
|
||
|
+ mode |= packed ? BCM2835_I2S_FRXP : 0;
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ return -EINVAL;
|
||
|
}
|
||
|
|
||
|
mode |= BCM2835_I2S_FLEN(bclk_ratio - 1);
|