kernel: update kernel 4.4 to 4.4.52
[openwrt/staging/lynxis/omap.git] / target / linux / brcm2708 / patches-4.9 / 0121-bcm2835-i2s-Changes-for-allowing-asymmetric-sample-f.patch
1 From 425ee76116894c97d5d97ad4883eb2612b8692f3 Mon Sep 17 00:00:00 2001
2 From: Giedrius Trainavicius <giedrius@blokas.io>
3 Date: Sun, 8 Jan 2017 15:58:54 +0200
4 Subject: [PATCH] bcm2835-i2s: Changes for allowing asymmetric sample formats.
5
6 This is achieved by making changes only to the requested
7 stream direction format, keeping the other stream direction
8 configuration intact.
9
10 Signed-off-by: Giedrius Trainavicius <giedrius@blokas.io>
11 ---
12 sound/soc/bcm/bcm2835-i2s.c | 54 +++++++++++++++++++++++++++++++--------------
13 1 file changed, 38 insertions(+), 16 deletions(-)
14
15 --- a/sound/soc/bcm/bcm2835-i2s.c
16 +++ b/sound/soc/bcm/bcm2835-i2s.c
17 @@ -237,7 +237,9 @@ static int bcm2835_i2s_hw_params(struct
18 unsigned int sampling_rate = params_rate(params);
19 unsigned int data_length, data_delay, bclk_ratio;
20 unsigned int ch1pos, ch2pos, mode, format;
21 + unsigned int previous_ftxp, previous_frxp;
22 uint32_t csreg;
23 + bool packed;
24
25 /*
26 * If a stream is already enabled,
27 @@ -320,26 +322,46 @@ static int bcm2835_i2s_hw_params(struct
28 return -EINVAL;
29 }
30
31 - /*
32 - * Set format for both streams.
33 - * We cannot set another frame length
34 - * (and therefore word length) anyway,
35 - * so the format will be the same.
36 - */
37 - regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format);
38 - regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format);
39 + /* Set the format for the matching stream direction. */
40 + switch (substream->stream) {
41 + case SNDRV_PCM_STREAM_PLAYBACK:
42 + regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format);
43 + break;
44 + case SNDRV_PCM_STREAM_CAPTURE:
45 + regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format);
46 + break;
47 + default:
48 + return -EINVAL;
49 + }
50
51 /* Setup the I2S mode */
52 + /* Keep existing FTXP and FRXP values. */
53 + regmap_read(dev->i2s_regmap, BCM2835_I2S_MODE_A_REG, &mode);
54 +
55 + previous_ftxp = mode & BCM2835_I2S_FTXP;
56 + previous_frxp = mode & BCM2835_I2S_FRXP;
57 +
58 mode = 0;
59
60 - if (data_length <= 16) {
61 - /*
62 - * Use frame packed mode (2 channels per 32 bit word)
63 - * We cannot set another frame length in the second stream
64 - * (and therefore word length) anyway,
65 - * so the format will be the same.
66 - */
67 - mode |= BCM2835_I2S_FTXP | BCM2835_I2S_FRXP;
68 + /*
69 + * Retain the frame packed mode (2 channels per 32 bit word)
70 + * of the other direction stream intact. The formats of each
71 + * direction can be different as long as the frame length is
72 + * shared for both.
73 + */
74 + packed = data_length <= 16;
75 +
76 + switch (substream->stream) {
77 + case SNDRV_PCM_STREAM_PLAYBACK:
78 + mode |= previous_frxp;
79 + mode |= packed ? BCM2835_I2S_FTXP : 0;
80 + break;
81 + case SNDRV_PCM_STREAM_CAPTURE:
82 + mode |= previous_ftxp;
83 + mode |= packed ? BCM2835_I2S_FRXP : 0;
84 + break;
85 + default:
86 + return -EINVAL;
87 }
88
89 mode |= BCM2835_I2S_FLEN(bclk_ratio - 1);