GNU Linux-libre 4.19.304-gnu1
[releases.git] / drivers / staging / vc04_services / bcm2835-audio / bcm2835-ctl.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2011 Broadcom Corporation.  All rights reserved. */
3
4 #include <linux/platform_device.h>
5 #include <linux/init.h>
6 #include <linux/io.h>
7 #include <linux/jiffies.h>
8 #include <linux/slab.h>
9 #include <linux/time.h>
10 #include <linux/wait.h>
11 #include <linux/delay.h>
12 #include <linux/moduleparam.h>
13 #include <linux/sched.h>
14
15 #include <sound/core.h>
16 #include <sound/control.h>
17 #include <sound/pcm.h>
18 #include <sound/pcm_params.h>
19 #include <sound/rawmidi.h>
20 #include <sound/initval.h>
21 #include <sound/tlv.h>
22 #include <sound/asoundef.h>
23
24 #include "bcm2835.h"
25
26 /* volume maximum and minimum in terms of 0.01dB */
27 #define CTRL_VOL_MAX 400
28 #define CTRL_VOL_MIN -10239 /* originally -10240 */
29
30 static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol,
31                                 struct snd_ctl_elem_info *uinfo)
32 {
33         if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
34                 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
35                 uinfo->count = 1;
36                 uinfo->value.integer.min = CTRL_VOL_MIN;
37                 uinfo->value.integer.max = CTRL_VOL_MAX; /* 2303 */
38         } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) {
39                 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
40                 uinfo->count = 1;
41                 uinfo->value.integer.min = 0;
42                 uinfo->value.integer.max = 1;
43         } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) {
44                 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
45                 uinfo->count = 1;
46                 uinfo->value.integer.min = 0;
47                 uinfo->value.integer.max = AUDIO_DEST_MAX - 1;
48         }
49         return 0;
50 }
51
52 /* toggles mute on or off depending on the value of nmute, and returns
53  * 1 if the mute value was changed, otherwise 0
54  */
55 static int toggle_mute(struct bcm2835_chip *chip, int nmute)
56 {
57         /* if settings are ok, just return 0 */
58         if (chip->mute == nmute)
59                 return 0;
60
61         /* if the sound is muted then we need to unmute */
62         if (chip->mute == CTRL_VOL_MUTE) {
63                 chip->volume = chip->old_volume; /* copy the old volume back */
64                 audio_info("Unmuting, old_volume = %d, volume = %d ...\n", chip->old_volume, chip->volume);
65         } else /* otherwise we mute */ {
66                 chip->old_volume = chip->volume;
67                 chip->volume = 26214; /* set volume to minimum level AKA mute */
68                 audio_info("Muting, old_volume = %d, volume = %d ...\n", chip->old_volume, chip->volume);
69         }
70
71         chip->mute = nmute;
72         return 1;
73 }
74
75 static int snd_bcm2835_ctl_get(struct snd_kcontrol *kcontrol,
76                                struct snd_ctl_elem_value *ucontrol)
77 {
78         struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
79
80         if (mutex_lock_interruptible(&chip->audio_mutex))
81                 return -EINTR;
82
83         BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));
84
85         if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
86                 ucontrol->value.integer.value[0] = chip2alsa(chip->volume);
87         else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
88                 ucontrol->value.integer.value[0] = chip->mute;
89         else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
90                 ucontrol->value.integer.value[0] = chip->dest;
91
92         mutex_unlock(&chip->audio_mutex);
93         return 0;
94 }
95
96 static int snd_bcm2835_ctl_put(struct snd_kcontrol *kcontrol,
97                                 struct snd_ctl_elem_value *ucontrol)
98 {
99         struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
100         int changed = 0;
101
102         if (mutex_lock_interruptible(&chip->audio_mutex))
103                 return -EINTR;
104
105         if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
106                 audio_info("Volume change attempted.. volume = %d new_volume = %d\n", chip->volume, (int)ucontrol->value.integer.value[0]);
107                 if (chip->mute == CTRL_VOL_MUTE) {
108                         /* changed = toggle_mute(chip, CTRL_VOL_UNMUTE); */
109                         changed = 1; /* should return 0 to signify no change but the mixer takes this as the opposite sign (no idea why) */
110                         goto unlock;
111                 }
112                 if (changed || (ucontrol->value.integer.value[0] != chip2alsa(chip->volume))) {
113                         chip->volume = alsa2chip(ucontrol->value.integer.value[0]);
114                         changed = 1;
115                 }
116
117         } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) {
118                 /* Now implemented */
119                 audio_info(" Mute attempted\n");
120                 changed = toggle_mute(chip, ucontrol->value.integer.value[0]);
121
122         } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) {
123                 if (ucontrol->value.integer.value[0] != chip->dest) {
124                         chip->dest = ucontrol->value.integer.value[0];
125                         changed = 1;
126                 }
127         }
128
129         if (changed && bcm2835_audio_set_ctls(chip))
130                 dev_err(chip->card->dev, "Failed to set ALSA controls..\n");
131
132 unlock:
133         mutex_unlock(&chip->audio_mutex);
134         return changed;
135 }
136
137 static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, CTRL_VOL_MIN, 1, 1);
138
139 static struct snd_kcontrol_new snd_bcm2835_ctl[] = {
140         {
141                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
142                 .name = "PCM Playback Volume",
143                 .index = 0,
144                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
145                 .private_value = PCM_PLAYBACK_VOLUME,
146                 .info = snd_bcm2835_ctl_info,
147                 .get = snd_bcm2835_ctl_get,
148                 .put = snd_bcm2835_ctl_put,
149                 .count = 1,
150                 .tlv = {.p = snd_bcm2835_db_scale}
151         },
152         {
153                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
154                 .name = "PCM Playback Switch",
155                 .index = 0,
156                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
157                 .private_value = PCM_PLAYBACK_MUTE,
158                 .info = snd_bcm2835_ctl_info,
159                 .get = snd_bcm2835_ctl_get,
160                 .put = snd_bcm2835_ctl_put,
161                 .count = 1,
162         },
163         {
164                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
165                 .name = "PCM Playback Route",
166                 .index = 0,
167                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
168                 .private_value = PCM_PLAYBACK_DEVICE,
169                 .info = snd_bcm2835_ctl_info,
170                 .get = snd_bcm2835_ctl_get,
171                 .put = snd_bcm2835_ctl_put,
172                 .count = 1,
173         },
174 };
175
176 static int snd_bcm2835_spdif_default_info(struct snd_kcontrol *kcontrol,
177         struct snd_ctl_elem_info *uinfo)
178 {
179         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
180         uinfo->count = 1;
181         return 0;
182 }
183
184 static int snd_bcm2835_spdif_default_get(struct snd_kcontrol *kcontrol,
185         struct snd_ctl_elem_value *ucontrol)
186 {
187         struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
188         int i;
189
190         if (mutex_lock_interruptible(&chip->audio_mutex))
191                 return -EINTR;
192
193         for (i = 0; i < 4; i++)
194                 ucontrol->value.iec958.status[i] =
195                         (chip->spdif_status >> (i * 8)) & 0xff;
196
197         mutex_unlock(&chip->audio_mutex);
198         return 0;
199 }
200
201 static int snd_bcm2835_spdif_default_put(struct snd_kcontrol *kcontrol,
202         struct snd_ctl_elem_value *ucontrol)
203 {
204         struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
205         unsigned int val = 0;
206         int i, change;
207
208         if (mutex_lock_interruptible(&chip->audio_mutex))
209                 return -EINTR;
210
211         for (i = 0; i < 4; i++)
212                 val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
213
214         change = val != chip->spdif_status;
215         chip->spdif_status = val;
216
217         mutex_unlock(&chip->audio_mutex);
218         return change;
219 }
220
221 static int snd_bcm2835_spdif_mask_info(struct snd_kcontrol *kcontrol,
222         struct snd_ctl_elem_info *uinfo)
223 {
224         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
225         uinfo->count = 1;
226         return 0;
227 }
228
229 static int snd_bcm2835_spdif_mask_get(struct snd_kcontrol *kcontrol,
230         struct snd_ctl_elem_value *ucontrol)
231 {
232         /*
233          * bcm2835 supports only consumer mode and sets all other format flags
234          * automatically. So the only thing left is signalling non-audio content
235          */
236         ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO;
237         return 0;
238 }
239
240 static int snd_bcm2835_spdif_stream_info(struct snd_kcontrol *kcontrol,
241         struct snd_ctl_elem_info *uinfo)
242 {
243         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
244         uinfo->count = 1;
245         return 0;
246 }
247
248 static int snd_bcm2835_spdif_stream_get(struct snd_kcontrol *kcontrol,
249         struct snd_ctl_elem_value *ucontrol)
250 {
251         struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
252         int i;
253
254         if (mutex_lock_interruptible(&chip->audio_mutex))
255                 return -EINTR;
256
257         for (i = 0; i < 4; i++)
258                 ucontrol->value.iec958.status[i] =
259                 (chip->spdif_status >> (i * 8)) & 0xff;
260
261         mutex_unlock(&chip->audio_mutex);
262         return 0;
263 }
264
265 static int snd_bcm2835_spdif_stream_put(struct snd_kcontrol *kcontrol,
266         struct snd_ctl_elem_value *ucontrol)
267 {
268         struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
269         unsigned int val = 0;
270         int i, change;
271
272         if (mutex_lock_interruptible(&chip->audio_mutex))
273                 return -EINTR;
274
275         for (i = 0; i < 4; i++)
276                 val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
277         change = val != chip->spdif_status;
278         chip->spdif_status = val;
279
280         mutex_unlock(&chip->audio_mutex);
281         return change;
282 }
283
284 static struct snd_kcontrol_new snd_bcm2835_spdif[] = {
285         {
286                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
287                 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
288                 .info = snd_bcm2835_spdif_default_info,
289                 .get = snd_bcm2835_spdif_default_get,
290                 .put = snd_bcm2835_spdif_default_put
291         },
292         {
293                 .access = SNDRV_CTL_ELEM_ACCESS_READ,
294                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
295                 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
296                 .info = snd_bcm2835_spdif_mask_info,
297                 .get = snd_bcm2835_spdif_mask_get,
298         },
299         {
300                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
301                 SNDRV_CTL_ELEM_ACCESS_INACTIVE,
302                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
303                 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
304                 .info = snd_bcm2835_spdif_stream_info,
305                 .get = snd_bcm2835_spdif_stream_get,
306                 .put = snd_bcm2835_spdif_stream_put,
307         },
308 };
309
310 int snd_bcm2835_new_ctl(struct bcm2835_chip *chip)
311 {
312         int err;
313         unsigned int idx;
314
315         strcpy(chip->card->mixername, "Broadcom Mixer");
316         for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_ctl); idx++) {
317                 err = snd_ctl_add(chip->card,
318                                   snd_ctl_new1(&snd_bcm2835_ctl[idx], chip));
319                 if (err < 0)
320                         return err;
321         }
322         for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_spdif); idx++) {
323                 err = snd_ctl_add(chip->card,
324                                   snd_ctl_new1(&snd_bcm2835_spdif[idx], chip));
325                 if (err < 0)
326                         return err;
327         }
328         return 0;
329 }
330
331 static struct snd_kcontrol_new snd_bcm2835_headphones_ctl[] = {
332         {
333                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
334                 .name = "Headphone Playback Volume",
335                 .index = 0,
336                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
337                           SNDRV_CTL_ELEM_ACCESS_TLV_READ,
338                 .private_value = PCM_PLAYBACK_VOLUME,
339                 .info = snd_bcm2835_ctl_info,
340                 .get = snd_bcm2835_ctl_get,
341                 .put = snd_bcm2835_ctl_put,
342                 .count = 1,
343                 .tlv = {.p = snd_bcm2835_db_scale}
344         },
345         {
346                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
347                 .name = "Headphone Playback Switch",
348                 .index = 0,
349                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
350                 .private_value = PCM_PLAYBACK_MUTE,
351                 .info = snd_bcm2835_ctl_info,
352                 .get = snd_bcm2835_ctl_get,
353                 .put = snd_bcm2835_ctl_put,
354                 .count = 1,
355         }
356 };
357
358 int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip)
359 {
360         int err;
361         unsigned int idx;
362
363         strcpy(chip->card->mixername, "Broadcom Mixer");
364         for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_headphones_ctl); idx++) {
365                 err = snd_ctl_add(chip->card,
366                                   snd_ctl_new1(&snd_bcm2835_headphones_ctl[idx],
367                                                chip));
368                 if (err)
369                         return err;
370         }
371         return 0;
372 }
373
374 static struct snd_kcontrol_new snd_bcm2835_hdmi[] = {
375         {
376                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
377                 .name = "HDMI Playback Volume",
378                 .index = 0,
379                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
380                           SNDRV_CTL_ELEM_ACCESS_TLV_READ,
381                 .private_value = PCM_PLAYBACK_VOLUME,
382                 .info = snd_bcm2835_ctl_info,
383                 .get = snd_bcm2835_ctl_get,
384                 .put = snd_bcm2835_ctl_put,
385                 .count = 1,
386                 .tlv = {.p = snd_bcm2835_db_scale}
387         },
388         {
389                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
390                 .name = "HDMI Playback Switch",
391                 .index = 0,
392                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
393                 .private_value = PCM_PLAYBACK_MUTE,
394                 .info = snd_bcm2835_ctl_info,
395                 .get = snd_bcm2835_ctl_get,
396                 .put = snd_bcm2835_ctl_put,
397                 .count = 1,
398         }
399 };
400
401 int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip)
402 {
403         int err;
404         unsigned int idx;
405
406         strcpy(chip->card->mixername, "Broadcom Mixer");
407         for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_hdmi); idx++) {
408                 err = snd_ctl_add(chip->card,
409                                   snd_ctl_new1(&snd_bcm2835_hdmi[idx], chip));
410                 if (err)
411                         return err;
412         }
413         return 0;
414 }
415