openwrt/target/linux/bcm27xx/patches-6.1/950-0895-ASOC-dwc-Fix-16-bit-audio-handling.patch
Marty Jones 2e715fb4fc bcm27xx: update 6.1 patches to latest version
Add support for BCM2712 (Raspberry Pi 5).
3bb5880ab3
Patches were generated from the diff between linux kernel branch linux-6.1.y
and rpi-6.1.y from raspberry pi kernel source:
- git format-patch linux-6.1.y...rpi-6.1.y

Build system: x86_64
Build-tested: bcm2708, bcm2709, bcm2710, bcm2711
Run-tested: bcm2710/RPi3B, bcm2711/RPi4B

Signed-off-by: Marty Jones <mj8263788@gmail.com>
[Remove applied and reverted patches, squash patches and config commits]
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2024-01-25 17:46:45 +01:00

89 lines
2.6 KiB
Diff

From 9c6694c24f26ea435165431d41c72451fadbd753 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.com>
Date: Fri, 21 Jul 2023 12:07:16 +0100
Subject: [PATCH] ASOC: dwc: Fix 16-bit audio handling
IMO the Synopsys datasheet could be clearer in this area, but it seems
that the DMA data ports (DMATX and DMARX) expect left and right samples
in alternate writes; if a stereo pair is pushed in a single 32-bit
write, the upper half is ignored, leading to double speed audio with a
confused stereo image. Make sure the necessary changes happen by
updating the DMA configuration data in the hw_params method.
The set_bclk_ratio change was made at a time when it looked like it
could be causing an error, but I think the division of responsibilities
is clearer this way (and the kernel log clearer without the info-level
message).
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
---
sound/soc/dwc/dwc-i2s.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
--- a/sound/soc/dwc/dwc-i2s.c
+++ b/sound/soc/dwc/dwc-i2s.c
@@ -223,23 +223,34 @@ static int dw_i2s_hw_params(struct snd_p
{
struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
struct i2s_clk_config_data *config = &dev->config;
+ union dw_i2s_snd_dma_data *dma_data = NULL;
int ret;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dma_data = &dev->play_dma_data;
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ dma_data = &dev->capture_dma_data;
+ else
+ return -1;
+
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
config->data_width = 16;
+ dma_data->dt.addr_width = 2;
dev->ccr = 0x00;
dev->xfer_resolution = 0x02;
break;
case SNDRV_PCM_FORMAT_S24_LE:
config->data_width = 24;
+ dma_data->dt.addr_width = 4;
dev->ccr = 0x08;
dev->xfer_resolution = 0x04;
break;
case SNDRV_PCM_FORMAT_S32_LE:
config->data_width = 32;
+ dma_data->dt.addr_width = 4;
dev->ccr = 0x10;
dev->xfer_resolution = 0x05;
break;
@@ -418,24 +429,21 @@ static int dw_i2s_set_bclk_ratio(struct
struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
struct i2s_clk_config_data *config = &dev->config;
- dev_err(dev->dev, "%s(%d)\n", __func__, ratio);
+ dev_dbg(dev->dev, "%s(%d)\n", __func__, ratio);
+ if (ratio < config->data_width * 2)
+ return -EINVAL;
+
switch (ratio) {
case 32:
- config->data_width = 16;
dev->ccr = 0x00;
- dev->xfer_resolution = 0x02;
break;
case 48:
- config->data_width = 24;
dev->ccr = 0x08;
- dev->xfer_resolution = 0x04;
break;
case 64:
- config->data_width = 32;
dev->ccr = 0x10;
- dev->xfer_resolution = 0x05;
break;
default:
return -EINVAL;