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