18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Driver for Digigram VXpocket soundcards 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * VX-pocket mixer 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <sound/core.h> 118c2ecf20Sopenharmony_ci#include <sound/control.h> 128c2ecf20Sopenharmony_ci#include <sound/tlv.h> 138c2ecf20Sopenharmony_ci#include "vxpocket.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define MIC_LEVEL_MIN 0 168c2ecf20Sopenharmony_ci#define MIC_LEVEL_MAX 8 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/* 198c2ecf20Sopenharmony_ci * mic level control (for VXPocket) 208c2ecf20Sopenharmony_ci */ 218c2ecf20Sopenharmony_cistatic int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 248c2ecf20Sopenharmony_ci uinfo->count = 1; 258c2ecf20Sopenharmony_ci uinfo->value.integer.min = 0; 268c2ecf20Sopenharmony_ci uinfo->value.integer.max = MIC_LEVEL_MAX; 278c2ecf20Sopenharmony_ci return 0; 288c2ecf20Sopenharmony_ci} 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci struct vx_core *_chip = snd_kcontrol_chip(kcontrol); 338c2ecf20Sopenharmony_ci struct snd_vxpocket *chip = to_vxpocket(_chip); 348c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = chip->mic_level; 358c2ecf20Sopenharmony_ci return 0; 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci struct vx_core *_chip = snd_kcontrol_chip(kcontrol); 418c2ecf20Sopenharmony_ci struct snd_vxpocket *chip = to_vxpocket(_chip); 428c2ecf20Sopenharmony_ci unsigned int val = ucontrol->value.integer.value[0]; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci if (val > MIC_LEVEL_MAX) 458c2ecf20Sopenharmony_ci return -EINVAL; 468c2ecf20Sopenharmony_ci mutex_lock(&_chip->mixer_mutex); 478c2ecf20Sopenharmony_ci if (chip->mic_level != ucontrol->value.integer.value[0]) { 488c2ecf20Sopenharmony_ci vx_set_mic_level(_chip, ucontrol->value.integer.value[0]); 498c2ecf20Sopenharmony_ci chip->mic_level = ucontrol->value.integer.value[0]; 508c2ecf20Sopenharmony_ci mutex_unlock(&_chip->mixer_mutex); 518c2ecf20Sopenharmony_ci return 1; 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci mutex_unlock(&_chip->mixer_mutex); 548c2ecf20Sopenharmony_ci return 0; 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new vx_control_mic_level = { 608c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 618c2ecf20Sopenharmony_ci .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 628c2ecf20Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_TLV_READ), 638c2ecf20Sopenharmony_ci .name = "Mic Capture Volume", 648c2ecf20Sopenharmony_ci .info = vx_mic_level_info, 658c2ecf20Sopenharmony_ci .get = vx_mic_level_get, 668c2ecf20Sopenharmony_ci .put = vx_mic_level_put, 678c2ecf20Sopenharmony_ci .tlv = { .p = db_scale_mic }, 688c2ecf20Sopenharmony_ci}; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/* 718c2ecf20Sopenharmony_ci * mic boost level control (for VXP440) 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_ci#define vx_mic_boost_info snd_ctl_boolean_mono_info 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci struct vx_core *_chip = snd_kcontrol_chip(kcontrol); 788c2ecf20Sopenharmony_ci struct snd_vxpocket *chip = to_vxpocket(_chip); 798c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = chip->mic_level; 808c2ecf20Sopenharmony_ci return 0; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci struct vx_core *_chip = snd_kcontrol_chip(kcontrol); 868c2ecf20Sopenharmony_ci struct snd_vxpocket *chip = to_vxpocket(_chip); 878c2ecf20Sopenharmony_ci int val = !!ucontrol->value.integer.value[0]; 888c2ecf20Sopenharmony_ci mutex_lock(&_chip->mixer_mutex); 898c2ecf20Sopenharmony_ci if (chip->mic_level != val) { 908c2ecf20Sopenharmony_ci vx_set_mic_boost(_chip, val); 918c2ecf20Sopenharmony_ci chip->mic_level = val; 928c2ecf20Sopenharmony_ci mutex_unlock(&_chip->mixer_mutex); 938c2ecf20Sopenharmony_ci return 1; 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci mutex_unlock(&_chip->mixer_mutex); 968c2ecf20Sopenharmony_ci return 0; 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new vx_control_mic_boost = { 1008c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1018c2ecf20Sopenharmony_ci .name = "Mic Boost", 1028c2ecf20Sopenharmony_ci .info = vx_mic_boost_info, 1038c2ecf20Sopenharmony_ci .get = vx_mic_boost_get, 1048c2ecf20Sopenharmony_ci .put = vx_mic_boost_put, 1058c2ecf20Sopenharmony_ci}; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ciint vxp_add_mic_controls(struct vx_core *_chip) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci struct snd_vxpocket *chip = to_vxpocket(_chip); 1118c2ecf20Sopenharmony_ci int err; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci /* mute input levels */ 1148c2ecf20Sopenharmony_ci chip->mic_level = 0; 1158c2ecf20Sopenharmony_ci switch (_chip->type) { 1168c2ecf20Sopenharmony_ci case VX_TYPE_VXPOCKET: 1178c2ecf20Sopenharmony_ci vx_set_mic_level(_chip, 0); 1188c2ecf20Sopenharmony_ci break; 1198c2ecf20Sopenharmony_ci case VX_TYPE_VXP440: 1208c2ecf20Sopenharmony_ci vx_set_mic_boost(_chip, 0); 1218c2ecf20Sopenharmony_ci break; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci /* mic level */ 1258c2ecf20Sopenharmony_ci switch (_chip->type) { 1268c2ecf20Sopenharmony_ci case VX_TYPE_VXPOCKET: 1278c2ecf20Sopenharmony_ci if ((err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_level, chip))) < 0) 1288c2ecf20Sopenharmony_ci return err; 1298c2ecf20Sopenharmony_ci break; 1308c2ecf20Sopenharmony_ci case VX_TYPE_VXP440: 1318c2ecf20Sopenharmony_ci if ((err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_boost, chip))) < 0) 1328c2ecf20Sopenharmony_ci return err; 1338c2ecf20Sopenharmony_ci break; 1348c2ecf20Sopenharmony_ci } 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci return 0; 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 139