brcm2708: update linux 4.4 patches to latest version
[openwrt.git] / target / linux / brcm2708 / patches-4.4 / 0132-bcm2835-access-controls-under-the-audio-mutex.patch
1 From 2a64337156d0f84537e04338b2ebd89eb6ec1f09 Mon Sep 17 00:00:00 2001
2 From: wm4 <wm4@nowhere>
3 Date: Wed, 13 Jan 2016 19:43:35 +0100
4 Subject: [PATCH 132/170] bcm2835: access controls under the audio mutex
5
6 I don't think the ALSA framework provides any kind of automatic
7 synchronization within the control callbacks. We most likely need
8 to ensure this manually, so add locking around all access to shared
9 mutable data. In particular, bcm2835_audio_set_ctls() should
10 probably always be called under our own audio lock.
11 ---
12  sound/arm/bcm2835-ctl.c | 74 +++++++++++++++++++++++++++++++++++++++++--------
13  sound/arm/bcm2835-pcm.c |  4 +++
14  2 files changed, 66 insertions(+), 12 deletions(-)
15
16 --- a/sound/arm/bcm2835-ctl.c
17 +++ b/sound/arm/bcm2835-ctl.c
18 @@ -94,6 +94,9 @@ static int snd_bcm2835_ctl_get(struct sn
19  {
20         struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
21  
22 +       if (mutex_lock_interruptible(&chip->audio_mutex))
23 +               return -EINTR;
24 +
25         BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));
26  
27         if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
28 @@ -103,6 +106,7 @@ static int snd_bcm2835_ctl_get(struct sn
29         else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
30                 ucontrol->value.integer.value[0] = chip->dest;
31  
32 +       mutex_unlock(&chip->audio_mutex);
33         return 0;
34  }
35  
36 @@ -112,11 +116,15 @@ static int snd_bcm2835_ctl_put(struct sn
37         struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
38         int changed = 0;
39  
40 +       if (mutex_lock_interruptible(&chip->audio_mutex))
41 +               return -EINTR;
42 +
43         if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
44                 audio_info("Volume change attempted.. volume = %d new_volume = %d\n", chip->volume, (int)ucontrol->value.integer.value[0]);
45                 if (chip->mute == CTRL_VOL_MUTE) {
46                         /* changed = toggle_mute(chip, CTRL_VOL_UNMUTE); */
47 -                       return 1; /* should return 0 to signify no change but the mixer takes this as the opposite sign (no idea why) */
48 +                       changed = 1; /* should return 0 to signify no change but the mixer takes this as the opposite sign (no idea why) */
49 +                       goto unlock;
50                 }
51                 if (changed
52                     || (ucontrol->value.integer.value[0] != chip2alsa(chip->volume))) {
53 @@ -142,6 +150,8 @@ static int snd_bcm2835_ctl_put(struct sn
54                         printk(KERN_ERR "Failed to set ALSA controls..\n");
55         }
56  
57 +unlock:
58 +       mutex_unlock(&chip->audio_mutex);
59         return changed;
60  }
61  
62 @@ -198,10 +208,14 @@ static int snd_bcm2835_spdif_default_get
63         struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
64         int i;
65  
66 +       if (mutex_lock_interruptible(&chip->audio_mutex))
67 +               return -EINTR;
68 +
69         for (i = 0; i < 4; i++)
70                 ucontrol->value.iec958.status[i] =
71                         (chip->spdif_status >> (i * 8)) && 0xff;
72  
73 +       mutex_unlock(&chip->audio_mutex);
74         return 0;
75  }
76  
77 @@ -212,12 +226,16 @@ static int snd_bcm2835_spdif_default_put
78         unsigned int val = 0;
79         int i, change;
80  
81 +       if (mutex_lock_interruptible(&chip->audio_mutex))
82 +               return -EINTR;
83 +
84         for (i = 0; i < 4; i++)
85                 val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
86  
87         change = val != chip->spdif_status;
88         chip->spdif_status = val;
89  
90 +       mutex_unlock(&chip->audio_mutex);
91         return change;
92  }
93  
94 @@ -253,9 +271,14 @@ static int snd_bcm2835_spdif_stream_get(
95         struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
96         int i;
97  
98 +       if (mutex_lock_interruptible(&chip->audio_mutex))
99 +               return -EINTR;
100 +
101         for (i = 0; i < 4; i++)
102                 ucontrol->value.iec958.status[i] =
103                         (chip->spdif_status >> (i * 8)) & 0xff;
104 +
105 +       mutex_unlock(&chip->audio_mutex);
106         return 0;
107  }
108  
109 @@ -266,11 +289,15 @@ static int snd_bcm2835_spdif_stream_put(
110         unsigned int val = 0;
111         int i, change;
112  
113 +       if (mutex_lock_interruptible(&chip->audio_mutex))
114 +               return -EINTR;
115 +
116         for (i = 0; i < 4; i++)
117                 val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
118         change = val != chip->spdif_status;
119         chip->spdif_status = val;
120  
121 +       mutex_unlock(&chip->audio_mutex);
122         return change;
123  }
124  
125 @@ -454,11 +481,17 @@ static int snd_bcm2835_chmap_ctl_get(str
126         unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
127         struct snd_pcm_substream *substream = snd_pcm_chmap_substream(info, idx);
128         struct cea_channel_speaker_allocation *ch = NULL;
129 +       int res = 0;
130         int cur = 0;
131         int i;
132  
133 -       if (!substream || !substream->runtime)
134 -               return -ENODEV;
135 +       if (mutex_lock_interruptible(&chip->audio_mutex))
136 +               return -EINTR;
137 +
138 +       if (!substream || !substream->runtime) {
139 +               res = -ENODEV;
140 +               goto unlock;
141 +       }
142  
143         for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
144                 if (channel_allocations[i].ca_index == chip->cea_chmap)
145 @@ -476,7 +509,10 @@ static int snd_bcm2835_chmap_ctl_get(str
146         }
147         while (cur < 8)
148                 ucontrol->value.integer.value[cur++] = SNDRV_CHMAP_NA;
149 -       return 0;
150 +
151 +unlock:
152 +       mutex_unlock(&chip->audio_mutex);
153 +       return res;
154  }
155  
156  static int snd_bcm2835_chmap_ctl_put(struct snd_kcontrol *kcontrol,
157 @@ -487,10 +523,16 @@ static int snd_bcm2835_chmap_ctl_put(str
158         unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
159         struct snd_pcm_substream *substream = snd_pcm_chmap_substream(info, idx);
160         int i, prepared = 0, cea_chmap = -1;
161 +       int res = 0;
162         int remap[8];
163  
164 -       if (!substream || !substream->runtime)
165 -               return -ENODEV;
166 +       if (mutex_lock_interruptible(&chip->audio_mutex))
167 +               return -EINTR;
168 +
169 +       if (!substream || !substream->runtime) {
170 +               res = -ENODEV;
171 +               goto unlock;
172 +       }
173  
174         switch (substream->runtime->status->state) {
175         case SNDRV_PCM_STATE_OPEN:
176 @@ -500,7 +542,8 @@ static int snd_bcm2835_chmap_ctl_put(str
177                 prepared = 1;
178                 break;
179         default:
180 -               return -EBUSY;
181 +               res = -EBUSY;
182 +               goto unlock;
183         }
184  
185         for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
186 @@ -538,19 +581,26 @@ static int snd_bcm2835_chmap_ctl_put(str
187                 }
188         }
189  
190 -       if (cea_chmap < 0)
191 -               return -EINVAL;
192 +       if (cea_chmap < 0) {
193 +               res = -EINVAL;
194 +               goto unlock;
195 +       }
196  
197         /* don't change the layout if another substream is active */
198 -       if (chip->opened != (1 << substream->number) && chip->cea_chmap != cea_chmap)
199 -               return -EBUSY; /* unsure whether this is a good error code */
200 +       if (chip->opened != (1 << substream->number) && chip->cea_chmap != cea_chmap) {
201 +               res = -EBUSY; /* unsure whether this is a good error code */
202 +               goto unlock;
203 +       }
204  
205         chip->cea_chmap = cea_chmap;
206         for (i = 0; i < 8; i++)
207                 chip->map_channels[i] = remap[i];
208         if (prepared)
209                 snd_bcm2835_pcm_prepare_again(substream);
210 -       return 0;
211 +
212 +unlock:
213 +       mutex_unlock(&chip->audio_mutex);
214 +       return res;
215  }
216  
217  static int snd_bcm2835_add_chmap_ctl(bcm2835_chip_t * chip)
218 --- a/sound/arm/bcm2835-pcm.c
219 +++ b/sound/arm/bcm2835-pcm.c
220 @@ -379,6 +379,9 @@ static int snd_bcm2835_pcm_prepare(struc
221  
222         audio_info(" .. IN\n");
223  
224 +       if (mutex_lock_interruptible(&chip->audio_mutex))
225 +               return -EINTR;
226 +
227         snd_bcm2835_pcm_prepare_again(substream);
228  
229         bcm2835_audio_setup(alsa_stream);
230 @@ -401,6 +404,7 @@ static int snd_bcm2835_pcm_prepare(struc
231                       alsa_stream->buffer_size, alsa_stream->period_size,
232                       alsa_stream->pos, runtime->frame_bits);
233  
234 +       mutex_unlock(&chip->audio_mutex);
235         audio_info(" .. OUT\n");
236         return 0;
237  }