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 mutex_lock(&chip->audio_mutex);
82 BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));
84 if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
85 ucontrol->value.integer.value[0] = chip2alsa(chip->volume);
86 else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
87 ucontrol->value.integer.value[0] = chip->mute;
88 else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
89 ucontrol->value.integer.value[0] = chip->dest;
91 mutex_unlock(&chip->audio_mutex);
95 static int snd_bcm2835_ctl_put(struct snd_kcontrol *kcontrol,
96 struct snd_ctl_elem_value *ucontrol)
98 struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
101 mutex_lock(&chip->audio_mutex);
103 if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
104 audio_info("Volume change attempted.. volume = %d new_volume = %d\n", chip->volume, (int)ucontrol->value.integer.value[0]);
105 if (chip->mute == CTRL_VOL_MUTE) {
106 /* changed = toggle_mute(chip, CTRL_VOL_UNMUTE); */
107 changed = 1; /* should return 0 to signify no change but the mixer takes this as the opposite sign (no idea why) */
110 if (changed || (ucontrol->value.integer.value[0] != chip2alsa(chip->volume))) {
111 chip->volume = alsa2chip(ucontrol->value.integer.value[0]);
115 } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) {
116 /* Now implemented */
117 audio_info(" Mute attempted\n");
118 changed = toggle_mute(chip, ucontrol->value.integer.value[0]);
120 } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) {
121 if (ucontrol->value.integer.value[0] != chip->dest) {
122 chip->dest = ucontrol->value.integer.value[0];
127 if (changed && bcm2835_audio_set_ctls(chip))
128 dev_err(chip->card->dev, "Failed to set ALSA controls..\n");
131 mutex_unlock(&chip->audio_mutex);
135 static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, CTRL_VOL_MIN, 1, 1);
137 static struct snd_kcontrol_new snd_bcm2835_ctl[] = {
139 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
140 .name = "PCM Playback Volume",
142 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
143 .private_value = PCM_PLAYBACK_VOLUME,
144 .info = snd_bcm2835_ctl_info,
145 .get = snd_bcm2835_ctl_get,
146 .put = snd_bcm2835_ctl_put,
148 .tlv = {.p = snd_bcm2835_db_scale}
151 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
152 .name = "PCM Playback Switch",
154 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
155 .private_value = PCM_PLAYBACK_MUTE,
156 .info = snd_bcm2835_ctl_info,
157 .get = snd_bcm2835_ctl_get,
158 .put = snd_bcm2835_ctl_put,
162 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
163 .name = "PCM Playback Route",
165 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
166 .private_value = PCM_PLAYBACK_DEVICE,
167 .info = snd_bcm2835_ctl_info,
168 .get = snd_bcm2835_ctl_get,
169 .put = snd_bcm2835_ctl_put,
174 static int snd_bcm2835_spdif_default_info(struct snd_kcontrol *kcontrol,
175 struct snd_ctl_elem_info *uinfo)
177 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
182 static int snd_bcm2835_spdif_default_get(struct snd_kcontrol *kcontrol,
183 struct snd_ctl_elem_value *ucontrol)
185 struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
188 mutex_lock(&chip->audio_mutex);
190 for (i = 0; i < 4; i++)
191 ucontrol->value.iec958.status[i] =
192 (chip->spdif_status >> (i * 8)) & 0xff;
194 mutex_unlock(&chip->audio_mutex);
198 static int snd_bcm2835_spdif_default_put(struct snd_kcontrol *kcontrol,
199 struct snd_ctl_elem_value *ucontrol)
201 struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
202 unsigned int val = 0;
205 mutex_lock(&chip->audio_mutex);
207 for (i = 0; i < 4; i++)
208 val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
210 change = val != chip->spdif_status;
211 chip->spdif_status = val;
213 mutex_unlock(&chip->audio_mutex);
217 static int snd_bcm2835_spdif_mask_info(struct snd_kcontrol *kcontrol,
218 struct snd_ctl_elem_info *uinfo)
220 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
225 static int snd_bcm2835_spdif_mask_get(struct snd_kcontrol *kcontrol,
226 struct snd_ctl_elem_value *ucontrol)
229 * bcm2835 supports only consumer mode and sets all other format flags
230 * automatically. So the only thing left is signalling non-audio content
232 ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO;
236 static struct snd_kcontrol_new snd_bcm2835_spdif[] = {
238 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
239 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
240 .info = snd_bcm2835_spdif_default_info,
241 .get = snd_bcm2835_spdif_default_get,
242 .put = snd_bcm2835_spdif_default_put
245 .access = SNDRV_CTL_ELEM_ACCESS_READ,
246 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
247 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
248 .info = snd_bcm2835_spdif_mask_info,
249 .get = snd_bcm2835_spdif_mask_get,
253 int snd_bcm2835_new_ctl(struct bcm2835_chip *chip)
258 strcpy(chip->card->mixername, "Broadcom Mixer");
259 for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_ctl); idx++) {
260 err = snd_ctl_add(chip->card,
261 snd_ctl_new1(&snd_bcm2835_ctl[idx], chip));
265 for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_spdif); idx++) {
266 err = snd_ctl_add(chip->card,
267 snd_ctl_new1(&snd_bcm2835_spdif[idx], chip));
274 static struct snd_kcontrol_new snd_bcm2835_headphones_ctl[] = {
276 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
277 .name = "Headphone Playback Volume",
279 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
280 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
281 .private_value = PCM_PLAYBACK_VOLUME,
282 .info = snd_bcm2835_ctl_info,
283 .get = snd_bcm2835_ctl_get,
284 .put = snd_bcm2835_ctl_put,
286 .tlv = {.p = snd_bcm2835_db_scale}
289 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
290 .name = "Headphone Playback Switch",
292 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
293 .private_value = PCM_PLAYBACK_MUTE,
294 .info = snd_bcm2835_ctl_info,
295 .get = snd_bcm2835_ctl_get,
296 .put = snd_bcm2835_ctl_put,
301 int snd_bcm2835_new_headphones_ctl(struct bcm2835_chip *chip)
306 strcpy(chip->card->mixername, "Broadcom Mixer");
307 for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_headphones_ctl); idx++) {
308 err = snd_ctl_add(chip->card,
309 snd_ctl_new1(&snd_bcm2835_headphones_ctl[idx],
317 static struct snd_kcontrol_new snd_bcm2835_hdmi[] = {
319 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
320 .name = "HDMI Playback Volume",
322 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
323 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
324 .private_value = PCM_PLAYBACK_VOLUME,
325 .info = snd_bcm2835_ctl_info,
326 .get = snd_bcm2835_ctl_get,
327 .put = snd_bcm2835_ctl_put,
329 .tlv = {.p = snd_bcm2835_db_scale}
332 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
333 .name = "HDMI Playback Switch",
335 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
336 .private_value = PCM_PLAYBACK_MUTE,
337 .info = snd_bcm2835_ctl_info,
338 .get = snd_bcm2835_ctl_get,
339 .put = snd_bcm2835_ctl_put,
344 int snd_bcm2835_new_hdmi_ctl(struct bcm2835_chip *chip)
349 strcpy(chip->card->mixername, "Broadcom Mixer");
350 for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_hdmi); idx++) {
351 err = snd_ctl_add(chip->card,
352 snd_ctl_new1(&snd_bcm2835_hdmi[idx], chip));