1 From fb9b7c60bed82b9a4c6ed329b349e6e5b8a60db9 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 130/304] bcm2835: access controls under the audio mutex
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.
12 sound/arm/bcm2835-ctl.c | 74 +++++++++++++++++++++++++++++++++++++++++--------
13 sound/arm/bcm2835-pcm.c | 4 +++
14 2 files changed, 66 insertions(+), 12 deletions(-)
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
20 struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
22 + if (mutex_lock_interruptible(&chip->audio_mutex))
25 BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));
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;
32 + mutex_unlock(&chip->audio_mutex);
36 @@ -112,11 +116,15 @@ static int snd_bcm2835_ctl_put(struct sn
37 struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
40 + if (mutex_lock_interruptible(&chip->audio_mutex))
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) */
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");
58 + mutex_unlock(&chip->audio_mutex);
62 @@ -198,10 +208,14 @@ static int snd_bcm2835_spdif_default_get
63 struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
66 + if (mutex_lock_interruptible(&chip->audio_mutex))
69 for (i = 0; i < 4; i++)
70 ucontrol->value.iec958.status[i] =
71 (chip->spdif_status >> (i * 8)) && 0xff;
73 + mutex_unlock(&chip->audio_mutex);
77 @@ -212,12 +226,16 @@ static int snd_bcm2835_spdif_default_put
81 + if (mutex_lock_interruptible(&chip->audio_mutex))
84 for (i = 0; i < 4; i++)
85 val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
87 change = val != chip->spdif_status;
88 chip->spdif_status = val;
90 + mutex_unlock(&chip->audio_mutex);
94 @@ -253,9 +271,14 @@ static int snd_bcm2835_spdif_stream_get(
95 struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
98 + if (mutex_lock_interruptible(&chip->audio_mutex))
101 for (i = 0; i < 4; i++)
102 ucontrol->value.iec958.status[i] =
103 (chip->spdif_status >> (i * 8)) & 0xff;
105 + mutex_unlock(&chip->audio_mutex);
109 @@ -266,11 +289,15 @@ static int snd_bcm2835_spdif_stream_put(
110 unsigned int val = 0;
113 + if (mutex_lock_interruptible(&chip->audio_mutex))
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;
121 + mutex_unlock(&chip->audio_mutex);
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;
133 - if (!substream || !substream->runtime)
135 + if (mutex_lock_interruptible(&chip->audio_mutex))
138 + if (!substream || !substream->runtime) {
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
148 ucontrol->value.integer.value[cur++] = SNDRV_CHMAP_NA;
152 + mutex_unlock(&chip->audio_mutex);
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;
164 - if (!substream || !substream->runtime)
166 + if (mutex_lock_interruptible(&chip->audio_mutex))
169 + if (!substream || !substream->runtime) {
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
185 for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
186 @@ -538,19 +581,26 @@ static int snd_bcm2835_chmap_ctl_put(str
192 + if (cea_chmap < 0) {
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 */
205 chip->cea_chmap = cea_chmap;
206 for (i = 0; i < 8; i++)
207 chip->map_channels[i] = remap[i];
209 snd_bcm2835_pcm_prepare_again(substream);
213 + mutex_unlock(&chip->audio_mutex);
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
222 audio_info(" .. IN\n");
224 + if (mutex_lock_interruptible(&chip->audio_mutex))
227 snd_bcm2835_pcm_prepare_again(substream);
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);
234 + mutex_unlock(&chip->audio_mutex);
235 audio_info(" .. OUT\n");