xref: /openbmc/linux/sound/pcmcia/vx/vxp_mixer.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * Driver for Digigram VXpocket soundcards
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * VX-pocket mixer
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds 
101da177e4SLinus Torvalds #include <sound/core.h>
111da177e4SLinus Torvalds #include <sound/control.h>
12d0ae4847STakashi Iwai #include <sound/tlv.h>
131da177e4SLinus Torvalds #include "vxpocket.h"
141da177e4SLinus Torvalds 
151da177e4SLinus Torvalds #define MIC_LEVEL_MIN	0
161da177e4SLinus Torvalds #define MIC_LEVEL_MAX	8
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds /*
191da177e4SLinus Torvalds  * mic level control (for VXPocket)
201da177e4SLinus Torvalds  */
vx_mic_level_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)21af26367fSTakashi Iwai static int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
221da177e4SLinus Torvalds {
231da177e4SLinus Torvalds 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
241da177e4SLinus Torvalds 	uinfo->count = 1;
251da177e4SLinus Torvalds 	uinfo->value.integer.min = 0;
261da177e4SLinus Torvalds 	uinfo->value.integer.max = MIC_LEVEL_MAX;
271da177e4SLinus Torvalds 	return 0;
281da177e4SLinus Torvalds }
291da177e4SLinus Torvalds 
vx_mic_level_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)30af26367fSTakashi Iwai static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
311da177e4SLinus Torvalds {
32af26367fSTakashi Iwai 	struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
332e0de6eaSTakashi Iwai 	struct snd_vxpocket *chip = to_vxpocket(_chip);
341da177e4SLinus Torvalds 	ucontrol->value.integer.value[0] = chip->mic_level;
351da177e4SLinus Torvalds 	return 0;
361da177e4SLinus Torvalds }
371da177e4SLinus Torvalds 
vx_mic_level_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)38af26367fSTakashi Iwai static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
391da177e4SLinus Torvalds {
40af26367fSTakashi Iwai 	struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
412e0de6eaSTakashi Iwai 	struct snd_vxpocket *chip = to_vxpocket(_chip);
42d05ab185STakashi Iwai 	unsigned int val = ucontrol->value.integer.value[0];
43d05ab185STakashi Iwai 
44d05ab185STakashi Iwai 	if (val > MIC_LEVEL_MAX)
45d05ab185STakashi Iwai 		return -EINVAL;
4612aa7579SIngo Molnar 	mutex_lock(&_chip->mixer_mutex);
471da177e4SLinus Torvalds 	if (chip->mic_level != ucontrol->value.integer.value[0]) {
481da177e4SLinus Torvalds 		vx_set_mic_level(_chip, ucontrol->value.integer.value[0]);
491da177e4SLinus Torvalds 		chip->mic_level = ucontrol->value.integer.value[0];
5012aa7579SIngo Molnar 		mutex_unlock(&_chip->mixer_mutex);
511da177e4SLinus Torvalds 		return 1;
521da177e4SLinus Torvalds 	}
5312aa7579SIngo Molnar 	mutex_unlock(&_chip->mixer_mutex);
541da177e4SLinus Torvalds 	return 0;
551da177e4SLinus Torvalds }
561da177e4SLinus Torvalds 
570cb29ea0STakashi Iwai static const DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0);
58d0ae4847STakashi Iwai 
59905e46acSBhumika Goyal static const struct snd_kcontrol_new vx_control_mic_level = {
601da177e4SLinus Torvalds 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
61d0ae4847STakashi Iwai 	.access =	(SNDRV_CTL_ELEM_ACCESS_READWRITE |
62d0ae4847STakashi Iwai 			 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
631da177e4SLinus Torvalds 	.name =		"Mic Capture Volume",
641da177e4SLinus Torvalds 	.info =		vx_mic_level_info,
651da177e4SLinus Torvalds 	.get =		vx_mic_level_get,
661da177e4SLinus Torvalds 	.put =		vx_mic_level_put,
67d0ae4847STakashi Iwai 	.tlv = { .p = db_scale_mic },
681da177e4SLinus Torvalds };
691da177e4SLinus Torvalds 
701da177e4SLinus Torvalds /*
711da177e4SLinus Torvalds  * mic boost level control (for VXP440)
721da177e4SLinus Torvalds  */
73a5ce8890STakashi Iwai #define vx_mic_boost_info		snd_ctl_boolean_mono_info
741da177e4SLinus Torvalds 
vx_mic_boost_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)75af26367fSTakashi Iwai static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
761da177e4SLinus Torvalds {
77af26367fSTakashi Iwai 	struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
782e0de6eaSTakashi Iwai 	struct snd_vxpocket *chip = to_vxpocket(_chip);
791da177e4SLinus Torvalds 	ucontrol->value.integer.value[0] = chip->mic_level;
801da177e4SLinus Torvalds 	return 0;
811da177e4SLinus Torvalds }
821da177e4SLinus Torvalds 
vx_mic_boost_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)83af26367fSTakashi Iwai static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
841da177e4SLinus Torvalds {
85af26367fSTakashi Iwai 	struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
862e0de6eaSTakashi Iwai 	struct snd_vxpocket *chip = to_vxpocket(_chip);
87d05ab185STakashi Iwai 	int val = !!ucontrol->value.integer.value[0];
8812aa7579SIngo Molnar 	mutex_lock(&_chip->mixer_mutex);
89d05ab185STakashi Iwai 	if (chip->mic_level != val) {
90d05ab185STakashi Iwai 		vx_set_mic_boost(_chip, val);
91d05ab185STakashi Iwai 		chip->mic_level = val;
9212aa7579SIngo Molnar 		mutex_unlock(&_chip->mixer_mutex);
931da177e4SLinus Torvalds 		return 1;
941da177e4SLinus Torvalds 	}
9512aa7579SIngo Molnar 	mutex_unlock(&_chip->mixer_mutex);
961da177e4SLinus Torvalds 	return 0;
971da177e4SLinus Torvalds }
981da177e4SLinus Torvalds 
99905e46acSBhumika Goyal static const struct snd_kcontrol_new vx_control_mic_boost = {
1001da177e4SLinus Torvalds 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
1011da177e4SLinus Torvalds 	.name =		"Mic Boost",
1021da177e4SLinus Torvalds 	.info =		vx_mic_boost_info,
1031da177e4SLinus Torvalds 	.get =		vx_mic_boost_get,
1041da177e4SLinus Torvalds 	.put =		vx_mic_boost_put,
1051da177e4SLinus Torvalds };
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds 
vxp_add_mic_controls(struct vx_core * _chip)108af26367fSTakashi Iwai int vxp_add_mic_controls(struct vx_core *_chip)
1091da177e4SLinus Torvalds {
1102e0de6eaSTakashi Iwai 	struct snd_vxpocket *chip = to_vxpocket(_chip);
1111da177e4SLinus Torvalds 	int err;
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds 	/* mute input levels */
1141da177e4SLinus Torvalds 	chip->mic_level = 0;
1151da177e4SLinus Torvalds 	switch (_chip->type) {
1161da177e4SLinus Torvalds 	case VX_TYPE_VXPOCKET:
1171da177e4SLinus Torvalds 		vx_set_mic_level(_chip, 0);
1181da177e4SLinus Torvalds 		break;
1191da177e4SLinus Torvalds 	case VX_TYPE_VXP440:
1201da177e4SLinus Torvalds 		vx_set_mic_boost(_chip, 0);
1211da177e4SLinus Torvalds 		break;
1221da177e4SLinus Torvalds 	}
1231da177e4SLinus Torvalds 
1241da177e4SLinus Torvalds 	/* mic level */
1251da177e4SLinus Torvalds 	switch (_chip->type) {
1261da177e4SLinus Torvalds 	case VX_TYPE_VXPOCKET:
127*2073fa44STakashi Iwai 		err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_level, chip));
128*2073fa44STakashi Iwai 		if (err < 0)
1291da177e4SLinus Torvalds 			return err;
1301da177e4SLinus Torvalds 		break;
1311da177e4SLinus Torvalds 	case VX_TYPE_VXP440:
132*2073fa44STakashi Iwai 		err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_boost, chip));
133*2073fa44STakashi Iwai 		if (err < 0)
1341da177e4SLinus Torvalds 			return err;
1351da177e4SLinus Torvalds 		break;
1361da177e4SLinus Torvalds 	}
1371da177e4SLinus Torvalds 
1381da177e4SLinus Torvalds 	return 0;
1391da177e4SLinus Torvalds }
1401da177e4SLinus Torvalds 
141