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