1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2011 Broadcom Corporation. All rights reserved. */
4 #include <linux/platform_device.h>
5 #include <linux/init.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>
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>
26 /* volume maximum and minimum in terms of 0.01dB */
27 #define CTRL_VOL_MAX 400
28 #define CTRL_VOL_MIN -10239 /* originally -10240 */
30 static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol,
31 struct snd_ctl_elem_info *uinfo)
33 if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
34 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
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;
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;
46 uinfo->value.integer.min = 0;
47 uinfo->value.integer.max = AUDIO_DEST_MAX - 1;
52 /* toggles mute on or off depending on the value of nmute, and returns
53 * 1 if the mute value was changed, otherwise 0
55 static int toggle_mute(struct bcm2835_chip *chip, int nmute)
57 /* if settings are ok, just return 0 */
58 if (chip->mute == nmute)
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);
75 static int snd_bcm2835_ctl_get(struct snd_kcontrol *kcontrol,
76 struct snd_ctl_elem_value *ucontrol)
78 struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
80 if (mutex_lock_interruptible(&chip->audio_mutex))
83 BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));
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;
92 mutex_unlock(&chip->audio_mutex);
96 static int snd_bcm2835_ctl_put(struct snd_kcontrol *kcontrol,
97 struct snd_ctl_elem_value *ucontrol)
99 struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
102 if (mutex_lock_interruptible(&chip->audio_mutex))
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) */
112 if (changed || (ucontrol->value.integer.value[0] != chip2alsa(chip->volume))) {
113 chip->volume = alsa2chip(ucontrol->value.integer.value[0]);
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]);
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];
129 if (changed && bcm2835_audio_set_ctls(chip))
130 dev_err(chip->card->dev, "Failed to set ALSA controls..\n");
133 mutex_unlock(&chip->audio_mutex);
137 static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, CTRL_VOL_MIN, 1, 1);
139 static struct snd_kcontrol_new snd_bcm2835_ctl[] = {
141 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
142 .name = "PCM Playback Volume",
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,
150 .tlv = {.p = snd_bcm2835_db_scale}
153 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
154 .name = "PCM Playback Switch",
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,
164 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
165 .name = "PCM Playback Route",
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,
176 static int snd_bcm2835_spdif_default_info(struct snd_kcontrol *kcontrol,
177 struct snd_ctl_elem_info *uinfo)
179 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
184 static int snd_bcm2835_spdif_default_get(struct snd_kcontrol *kcontrol,
185 struct snd_ctl_elem_value *ucontrol)
187 struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
190 if (mutex_lock_interruptible(&chip->audio_mutex))
193 for (i = 0; i < 4; i++)
194 ucontrol->value.iec958.status[i] =
195 (chip->spdif_status >> (i * 8)) & 0xff;
197 mutex_unlock(&chip->audio_mutex);
201 static int snd_bcm2835_spdif_default_put(struct snd_kcontrol *kcontrol,
202 struct snd_ctl_elem_value *ucontrol)
204 struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
205 unsigned int val = 0;
208 if (mutex_lock_interruptible(&chip->audio_mutex))
211 for (i = 0; i < 4; i++)
212 val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
214 change = val != chip->spdif_status;
215 chip->spdif_status = val;
217 mutex_unlock(&chip->audio_mutex);
221 static int snd_bcm2835_spdif_mask_info(struct snd_kcontrol *kcontrol,
222 struct snd_ctl_elem_info *uinfo)
224 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
229 static int snd_bcm2835_spdif_mask_get(struct snd_kcontrol *kcontrol,
230 struct snd_ctl_elem_value *ucontrol)
233 * bcm2835 supports only consumer mode and sets all other format flags
234 * automatically. So the only thing left is signalling non-audio content
236 ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO;
240 static int snd_bcm2835_spdif_stream_info(struct snd_kcontrol *kcontrol,
241 struct snd_ctl_elem_info *uinfo)
243 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
248 static int snd_bcm2835_spdif_stream_get(struct snd_kcontrol *kcontrol,
249 struct snd_ctl_elem_value *ucontrol)
251 struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
254 if (mutex_lock_interruptible(&chip->audio_mutex))
257 for (i = 0; i < 4; i++)
258 ucontrol->value.iec958.status[i] =
259 (chip->spdif_status >> (i * 8)) & 0xff;
261 mutex_unlock(&chip->audio_mutex);
265 static int snd_bcm2835_spdif_stream_put(struct snd_kcontrol *kcontrol,
266 struct snd_ctl_elem_value *ucontrol)
268 struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
269 unsigned int val = 0;
272 if (mutex_lock_interruptible(&chip->audio_mutex))
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;
280 mutex_unlock(&chip->audio_mutex);
284 static struct snd_kcontrol_new snd_bcm2835_spdif[] = {
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
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,
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,
310 int snd_bcm2835_new_ctl(struct bcm2835_chip *chip)
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));
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));
331 static struct snd_kcontrol_new snd_bcm2835_headphones_ctl[] = {
333 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
334 .name = "Headphone Playback Volume",
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,
343 .tlv = {.p = snd_bcm2835_db_scale}
346 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
347 .name = "Headphone Playback Switch",
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,
358 int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip)
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],
374 static struct snd_kcontrol_new snd_bcm2835_hdmi[] = {
376 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
377 .name = "HDMI Playback Volume",
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,
386 .tlv = {.p = snd_bcm2835_db_scale}
389 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
390 .name = "HDMI Playback Switch",
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,
401 int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip)
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));