141 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for Digigram VXpocket soundcards4 *5 * VX-pocket mixer6 *7 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>8 */9 10#include <sound/core.h>11#include <sound/control.h>12#include <sound/tlv.h>13#include "vxpocket.h"14 15#define MIC_LEVEL_MIN 016#define MIC_LEVEL_MAX 817 18/*19 * mic level control (for VXPocket)20 */21static int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)22{23 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;24 uinfo->count = 1;25 uinfo->value.integer.min = 0;26 uinfo->value.integer.max = MIC_LEVEL_MAX;27 return 0;28}29 30static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)31{32 struct vx_core *_chip = snd_kcontrol_chip(kcontrol);33 struct snd_vxpocket *chip = to_vxpocket(_chip);34 ucontrol->value.integer.value[0] = chip->mic_level;35 return 0;36}37 38static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)39{40 struct vx_core *_chip = snd_kcontrol_chip(kcontrol);41 struct snd_vxpocket *chip = to_vxpocket(_chip);42 unsigned int val = ucontrol->value.integer.value[0];43 44 if (val > MIC_LEVEL_MAX)45 return -EINVAL;46 mutex_lock(&_chip->mixer_mutex);47 if (chip->mic_level != ucontrol->value.integer.value[0]) {48 vx_set_mic_level(_chip, ucontrol->value.integer.value[0]);49 chip->mic_level = ucontrol->value.integer.value[0];50 mutex_unlock(&_chip->mixer_mutex);51 return 1;52 }53 mutex_unlock(&_chip->mixer_mutex);54 return 0;55}56 57static const DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0);58 59static const struct snd_kcontrol_new vx_control_mic_level = {60 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,61 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |62 SNDRV_CTL_ELEM_ACCESS_TLV_READ),63 .name = "Mic Capture Volume",64 .info = vx_mic_level_info,65 .get = vx_mic_level_get,66 .put = vx_mic_level_put,67 .tlv = { .p = db_scale_mic },68};69 70/*71 * mic boost level control (for VXP440)72 */73#define vx_mic_boost_info snd_ctl_boolean_mono_info74 75static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)76{77 struct vx_core *_chip = snd_kcontrol_chip(kcontrol);78 struct snd_vxpocket *chip = to_vxpocket(_chip);79 ucontrol->value.integer.value[0] = chip->mic_level;80 return 0;81}82 83static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)84{85 struct vx_core *_chip = snd_kcontrol_chip(kcontrol);86 struct snd_vxpocket *chip = to_vxpocket(_chip);87 int val = !!ucontrol->value.integer.value[0];88 mutex_lock(&_chip->mixer_mutex);89 if (chip->mic_level != val) {90 vx_set_mic_boost(_chip, val);91 chip->mic_level = val;92 mutex_unlock(&_chip->mixer_mutex);93 return 1;94 }95 mutex_unlock(&_chip->mixer_mutex);96 return 0;97}98 99static const struct snd_kcontrol_new vx_control_mic_boost = {100 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,101 .name = "Mic Boost",102 .info = vx_mic_boost_info,103 .get = vx_mic_boost_get,104 .put = vx_mic_boost_put,105};106 107 108int vxp_add_mic_controls(struct vx_core *_chip)109{110 struct snd_vxpocket *chip = to_vxpocket(_chip);111 int err;112 113 /* mute input levels */114 chip->mic_level = 0;115 switch (_chip->type) {116 case VX_TYPE_VXPOCKET:117 vx_set_mic_level(_chip, 0);118 break;119 case VX_TYPE_VXP440:120 vx_set_mic_boost(_chip, 0);121 break;122 }123 124 /* mic level */125 switch (_chip->type) {126 case VX_TYPE_VXPOCKET:127 err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_level, chip));128 if (err < 0)129 return err;130 break;131 case VX_TYPE_VXP440:132 err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_boost, chip));133 if (err < 0)134 return err;135 break;136 }137 138 return 0;139}140 141