de29b17d2185895142f075bed564bd06e89a1218
[openwrt/staging/lynxis.git] /
1 From 31e4f118a750f4ddb2aeaaf02c5f3630fb50a176 Mon Sep 17 00:00:00 2001
2 From: Takashi Iwai <tiwai@suse.de>
3 Date: Tue, 4 Sep 2018 17:58:34 +0200
4 Subject: [PATCH] staging: bcm2835-audio: Fix mute controls, volume
5 handling cleanup
6
7 commit 495e5a0d83d3902c741771f267a702ae19da8ab6 upstream.
8
9 In the current code, the mute control is dealt in a special manner,
10 modifying the current volume and saving the old volume, etc. This is
11 inconsistent (e.g. change the volume while muted, then unmute), and
12 way too complex.
13
14 Also, the whole volume handling code has conversion between ALSA
15 volume and raw volume values, which can lead to another
16 inconsistency and complexity.
17
18 This patch simplifies these points:
19 - The ALSA volume value is saved in chip->volume
20 - volume->mute saves the mute state
21 - The mute state is evaluated only when the actual volume is passed to
22 the hardware, bcm2835_audio_set_ctls()
23
24 Signed-off-by: Takashi Iwai <tiwai@suse.de>
25 Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
26 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
27 ---
28 .../vc04_services/bcm2835-audio/bcm2835-ctl.c | 84 +++++++------------
29 .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 6 +-
30 .../bcm2835-audio/bcm2835-vchiq.c | 32 ++-----
31 .../vc04_services/bcm2835-audio/bcm2835.h | 5 +-
32 4 files changed, 45 insertions(+), 82 deletions(-)
33
34 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
35 +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-ctl.c
36 @@ -12,6 +12,21 @@
37 #define CTRL_VOL_MAX 400
38 #define CTRL_VOL_MIN -10239 /* originally -10240 */
39
40 +static int bcm2835_audio_set_chip_ctls(struct bcm2835_chip *chip)
41 +{
42 + int i, err = 0;
43 +
44 + /* change ctls for all substreams */
45 + for (i = 0; i < MAX_SUBSTREAMS; i++) {
46 + if (chip->alsa_stream[i]) {
47 + err = bcm2835_audio_set_ctls(chip->alsa_stream[i]);
48 + if (err < 0)
49 + break;
50 + }
51 + }
52 + return err;
53 +}
54 +
55 static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol,
56 struct snd_ctl_elem_info *uinfo)
57 {
58 @@ -34,29 +49,6 @@ static int snd_bcm2835_ctl_info(struct s
59 return 0;
60 }
61
62 -/* toggles mute on or off depending on the value of nmute, and returns
63 - * 1 if the mute value was changed, otherwise 0
64 - */
65 -static int toggle_mute(struct bcm2835_chip *chip, int nmute)
66 -{
67 - /* if settings are ok, just return 0 */
68 - if (chip->mute == nmute)
69 - return 0;
70 -
71 - /* if the sound is muted then we need to unmute */
72 - if (chip->mute == CTRL_VOL_MUTE) {
73 - chip->volume = chip->old_volume; /* copy the old volume back */
74 - audio_info("Unmuting, old_volume = %d, volume = %d ...\n", chip->old_volume, chip->volume);
75 - } else /* otherwise we mute */ {
76 - chip->old_volume = chip->volume;
77 - chip->volume = 26214; /* set volume to minimum level AKA mute */
78 - audio_info("Muting, old_volume = %d, volume = %d ...\n", chip->old_volume, chip->volume);
79 - }
80 -
81 - chip->mute = nmute;
82 - return 1;
83 -}
84 -
85 static int snd_bcm2835_ctl_get(struct snd_kcontrol *kcontrol,
86 struct snd_ctl_elem_value *ucontrol)
87 {
88 @@ -65,7 +57,7 @@ static int snd_bcm2835_ctl_get(struct sn
89 mutex_lock(&chip->audio_mutex);
90
91 if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
92 - ucontrol->value.integer.value[0] = chip2alsa(chip->volume);
93 + ucontrol->value.integer.value[0] = chip->volume;
94 else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
95 ucontrol->value.integer.value[0] = chip->mute;
96 else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
97 @@ -79,38 +71,26 @@ static int snd_bcm2835_ctl_put(struct sn
98 struct snd_ctl_elem_value *ucontrol)
99 {
100 struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
101 + int val, *valp;
102 int changed = 0;
103
104 - mutex_lock(&chip->audio_mutex);
105 -
106 - if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
107 - audio_info("Volume change attempted.. volume = %d new_volume = %d\n", chip->volume, (int)ucontrol->value.integer.value[0]);
108 - if (chip->mute == CTRL_VOL_MUTE) {
109 - /* changed = toggle_mute(chip, CTRL_VOL_UNMUTE); */
110 - changed = 1; /* should return 0 to signify no change but the mixer takes this as the opposite sign (no idea why) */
111 - goto unlock;
112 - }
113 - if (changed || (ucontrol->value.integer.value[0] != chip2alsa(chip->volume))) {
114 - chip->volume = alsa2chip(ucontrol->value.integer.value[0]);
115 - changed = 1;
116 - }
117 -
118 - } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) {
119 - /* Now implemented */
120 - audio_info(" Mute attempted\n");
121 - changed = toggle_mute(chip, ucontrol->value.integer.value[0]);
122 + if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
123 + valp = &chip->volume;
124 + else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
125 + valp = &chip->mute;
126 + else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
127 + valp = &chip->dest;
128 + else
129 + return -EINVAL;
130
131 - } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) {
132 - if (ucontrol->value.integer.value[0] != chip->dest) {
133 - chip->dest = ucontrol->value.integer.value[0];
134 - changed = 1;
135 - }
136 + val = ucontrol->value.integer.value[0];
137 + mutex_lock(&chip->audio_mutex);
138 + if (val != *valp) {
139 + *valp = val;
140 + changed = 1;
141 + if (bcm2835_audio_set_chip_ctls(chip))
142 + dev_err(chip->card->dev, "Failed to set ALSA controls..\n");
143 }
144 -
145 - if (changed && bcm2835_audio_set_ctls(chip))
146 - dev_err(chip->card->dev, "Failed to set ALSA controls..\n");
147 -
148 -unlock:
149 mutex_unlock(&chip->audio_mutex);
150 return changed;
151 }
152 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
153 +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
154 @@ -280,7 +280,7 @@ static int snd_bcm2835_pcm_prepare(struc
155 bcm2835_audio_setup(alsa_stream);
156
157 /* in preparation of the stream, set the controls (volume level) of the stream */
158 - bcm2835_audio_set_ctls(alsa_stream->chip);
159 + bcm2835_audio_set_ctls(alsa_stream);
160
161 memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
162
163 @@ -441,7 +441,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_c
164 strcpy(pcm->name, "bcm2835 ALSA");
165 chip->pcm = pcm;
166 chip->dest = AUDIO_DEST_AUTO;
167 - chip->volume = alsa2chip(0);
168 + chip->volume = 0;
169 chip->mute = CTRL_VOL_UNMUTE; /*disable mute on startup */
170 /* set operators */
171 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
172 @@ -498,7 +498,7 @@ int snd_bcm2835_new_simple_pcm(struct bc
173 strcpy(pcm->name, name);
174 chip->pcm = pcm;
175 chip->dest = route;
176 - chip->volume = alsa2chip(0);
177 + chip->volume = 0;
178 chip->mute = CTRL_VOL_UNMUTE;
179
180 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
181 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
182 +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
183 @@ -460,11 +460,11 @@ free_wq:
184 return ret;
185 }
186
187 -static int bcm2835_audio_set_ctls_chan(struct bcm2835_alsa_stream *alsa_stream,
188 - struct bcm2835_chip *chip)
189 +int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream)
190 {
191 struct vc_audio_msg m;
192 struct bcm2835_audio_instance *instance = alsa_stream->instance;
193 + struct bcm2835_chip *chip = alsa_stream->chip;
194 int status;
195 int ret;
196
197 @@ -478,7 +478,10 @@ static int bcm2835_audio_set_ctls_chan(s
198
199 m.type = VC_AUDIO_MSG_TYPE_CONTROL;
200 m.u.control.dest = chip->dest;
201 - m.u.control.volume = chip->volume;
202 + if (!chip->mute)
203 + m.u.control.volume = CHIP_MIN_VOLUME;
204 + else
205 + m.u.control.volume = alsa2chip(chip->volume);
206
207 /* Create the message available completion */
208 init_completion(&instance->msg_avail_comp);
209 @@ -514,27 +517,6 @@ unlock:
210 return ret;
211 }
212
213 -int bcm2835_audio_set_ctls(struct bcm2835_chip *chip)
214 -{
215 - int i;
216 - int ret = 0;
217 -
218 - LOG_DBG(" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume);
219 -
220 - /* change ctls for all substreams */
221 - for (i = 0; i < MAX_SUBSTREAMS; i++) {
222 - if (!chip->alsa_stream[i])
223 - continue;
224 - if (bcm2835_audio_set_ctls_chan(chip->alsa_stream[i], chip) != 0) {
225 - LOG_ERR("Couldn't set the controls for stream %d\n", i);
226 - ret = -1;
227 - } else {
228 - LOG_DBG(" Controls set for stream %d\n", i);
229 - }
230 - }
231 - return ret;
232 -}
233 -
234 int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
235 unsigned int channels, unsigned int samplerate,
236 unsigned int bps)
237 @@ -548,7 +530,7 @@ int bcm2835_audio_set_params(struct bcm2
238 channels, samplerate, bps);
239
240 /* resend ctls - alsa_stream may not have been open when first send */
241 - ret = bcm2835_audio_set_ctls_chan(alsa_stream, alsa_stream->chip);
242 + ret = bcm2835_audio_set_ctls(alsa_stream);
243 if (ret) {
244 LOG_ERR(" Alsa controls not supported\n");
245 return -EINVAL;
246 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
247 +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h
248 @@ -74,6 +74,8 @@ enum {
249 // convert chip to alsa volume
250 #define chip2alsa(vol) -(((vol) * 100) >> 8)
251
252 +#define CHIP_MIN_VOLUME 26214 /* minimum level aka mute */
253 +
254 /* Some constants for values .. */
255 enum snd_bcm2835_route {
256 AUDIO_DEST_AUTO = 0,
257 @@ -102,7 +104,6 @@ struct bcm2835_chip {
258 struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS];
259
260 int volume;
261 - int old_volume; /* stores the volume value whist muted */
262 int dest;
263 int mute;
264
265 @@ -160,7 +161,7 @@ int bcm2835_audio_set_params(struct bcm2
266 int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream);
267 int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream);
268 int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream);
269 -int bcm2835_audio_set_ctls(struct bcm2835_chip *chip);
270 +int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream);
271 int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
272 unsigned int count,
273 void *src);