Skip to content

Commit 4897c5c

Browse files
gtrainaviciuspelwell
authored andcommitted
bcm2835-i2s: Changes for allowing asymmetric sample formats. (#1783)
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 <[email protected]>
1 parent 9438f6f commit 4897c5c

File tree

1 file changed

+38
-16
lines changed

1 file changed

+38
-16
lines changed

sound/soc/bcm/bcm2835-i2s.c

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
310310
unsigned int sampling_rate = params_rate(params);
311311
unsigned int data_length, data_delay, bclk_ratio;
312312
unsigned int ch1pos, ch2pos, mode, format;
313+
unsigned int previous_ftxp, previous_frxp;
313314
unsigned int mash = BCM2835_CLK_MASH_1;
314315
unsigned int divi, divf, target_frequency;
315316
int clk_src = -1;
@@ -320,6 +321,7 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
320321
bool frame_master = (master == SND_SOC_DAIFMT_CBS_CFS
321322
|| master == SND_SOC_DAIFMT_CBM_CFS);
322323
uint32_t csreg;
324+
bool packed;
323325

324326
/*
325327
* If a stream is already enabled,
@@ -465,26 +467,46 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
465467
return -EINVAL;
466468
}
467469

468-
/*
469-
* Set format for both streams.
470-
* We cannot set another frame length
471-
* (and therefore word length) anyway,
472-
* so the format will be the same.
473-
*/
474-
regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format);
475-
regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format);
470+
/* Set the format for the matching stream direction. */
471+
switch (substream->stream) {
472+
case SNDRV_PCM_STREAM_PLAYBACK:
473+
regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format);
474+
break;
475+
case SNDRV_PCM_STREAM_CAPTURE:
476+
regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format);
477+
break;
478+
default:
479+
return -EINVAL;
480+
}
476481

477482
/* Setup the I2S mode */
483+
/* Keep existing FTXP and FRXP values. */
484+
regmap_read(dev->i2s_regmap, BCM2835_I2S_MODE_A_REG, &mode);
485+
486+
previous_ftxp = mode & BCM2835_I2S_FTXP;
487+
previous_frxp = mode & BCM2835_I2S_FRXP;
488+
478489
mode = 0;
479490

480-
if (data_length <= 16) {
481-
/*
482-
* Use frame packed mode (2 channels per 32 bit word)
483-
* We cannot set another frame length in the second stream
484-
* (and therefore word length) anyway,
485-
* so the format will be the same.
486-
*/
487-
mode |= BCM2835_I2S_FTXP | BCM2835_I2S_FRXP;
491+
/*
492+
* Retain the frame packed mode (2 channels per 32 bit word)
493+
* of the other direction stream intact. The formats of each
494+
* direction can be different as long as the frame length is
495+
* shared for both.
496+
*/
497+
packed = data_length <= 16;
498+
499+
switch (substream->stream) {
500+
case SNDRV_PCM_STREAM_PLAYBACK:
501+
mode |= previous_frxp;
502+
mode |= packed ? BCM2835_I2S_FTXP : 0;
503+
break;
504+
case SNDRV_PCM_STREAM_CAPTURE:
505+
mode |= previous_ftxp;
506+
mode |= packed ? BCM2835_I2S_FRXP : 0;
507+
break;
508+
default:
509+
return -EINVAL;
488510
}
489511

490512
mode |= BCM2835_I2S_FLEN(bclk_ratio - 1);

0 commit comments

Comments
 (0)