ea2d72b39c0cf2b32dbc9567e32468df2b67ee41
[oweals/openwrt.git] /
1 From 8e1cbe403cccb0269ad6563cf223a220f2173964 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 444/703] 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);