bcm27xx: update 6.1 patches to latest version
[openwrt/staging/dangole.git] / target / linux / bcm27xx / patches-6.1 / 950-0895-ASOC-dwc-Fix-16-bit-audio-handling.patch
1 From 9c6694c24f26ea435165431d41c72451fadbd753 Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.com>
3 Date: Fri, 21 Jul 2023 12:07:16 +0100
4 Subject: [PATCH] ASOC: dwc: Fix 16-bit audio handling
5
6 IMO the Synopsys datasheet could be clearer in this area, but it seems
7 that the DMA data ports (DMATX and DMARX) expect left and right samples
8 in alternate writes; if a stereo pair is pushed in a single 32-bit
9 write, the upper half is ignored, leading to double speed audio with a
10 confused stereo image. Make sure the necessary changes happen by
11 updating the DMA configuration data in the hw_params method.
12
13 The set_bclk_ratio change was made at a time when it looked like it
14 could be causing an error, but I think the division of responsibilities
15 is clearer this way (and the kernel log clearer without the info-level
16 message).
17
18 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
19 ---
20 sound/soc/dwc/dwc-i2s.c | 22 +++++++++++++++-------
21 1 file changed, 15 insertions(+), 7 deletions(-)
22
23 --- a/sound/soc/dwc/dwc-i2s.c
24 +++ b/sound/soc/dwc/dwc-i2s.c
25 @@ -223,23 +223,34 @@ static int dw_i2s_hw_params(struct snd_p
26 {
27 struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
28 struct i2s_clk_config_data *config = &dev->config;
29 + union dw_i2s_snd_dma_data *dma_data = NULL;
30 int ret;
31
32 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
33 + dma_data = &dev->play_dma_data;
34 + else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
35 + dma_data = &dev->capture_dma_data;
36 + else
37 + return -1;
38 +
39 switch (params_format(params)) {
40 case SNDRV_PCM_FORMAT_S16_LE:
41 config->data_width = 16;
42 + dma_data->dt.addr_width = 2;
43 dev->ccr = 0x00;
44 dev->xfer_resolution = 0x02;
45 break;
46
47 case SNDRV_PCM_FORMAT_S24_LE:
48 config->data_width = 24;
49 + dma_data->dt.addr_width = 4;
50 dev->ccr = 0x08;
51 dev->xfer_resolution = 0x04;
52 break;
53
54 case SNDRV_PCM_FORMAT_S32_LE:
55 config->data_width = 32;
56 + dma_data->dt.addr_width = 4;
57 dev->ccr = 0x10;
58 dev->xfer_resolution = 0x05;
59 break;
60 @@ -418,24 +429,21 @@ static int dw_i2s_set_bclk_ratio(struct
61 struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
62 struct i2s_clk_config_data *config = &dev->config;
63
64 - dev_err(dev->dev, "%s(%d)\n", __func__, ratio);
65 + dev_dbg(dev->dev, "%s(%d)\n", __func__, ratio);
66 + if (ratio < config->data_width * 2)
67 + return -EINVAL;
68 +
69 switch (ratio) {
70 case 32:
71 - config->data_width = 16;
72 dev->ccr = 0x00;
73 - dev->xfer_resolution = 0x02;
74 break;
75
76 case 48:
77 - config->data_width = 24;
78 dev->ccr = 0x08;
79 - dev->xfer_resolution = 0x04;
80 break;
81
82 case 64:
83 - config->data_width = 32;
84 dev->ccr = 0x10;
85 - dev->xfer_resolution = 0x05;
86 break;
87 default:
88 return -EINVAL;