162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Driver for Digigram VXpocket soundcards
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * VX-pocket mixer
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <sound/core.h>
1162306a36Sopenharmony_ci#include <sound/control.h>
1262306a36Sopenharmony_ci#include <sound/tlv.h>
1362306a36Sopenharmony_ci#include "vxpocket.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define MIC_LEVEL_MIN	0
1662306a36Sopenharmony_ci#define MIC_LEVEL_MAX	8
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/*
1962306a36Sopenharmony_ci * mic level control (for VXPocket)
2062306a36Sopenharmony_ci */
2162306a36Sopenharmony_cistatic int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
2262306a36Sopenharmony_ci{
2362306a36Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2462306a36Sopenharmony_ci	uinfo->count = 1;
2562306a36Sopenharmony_ci	uinfo->value.integer.min = 0;
2662306a36Sopenharmony_ci	uinfo->value.integer.max = MIC_LEVEL_MAX;
2762306a36Sopenharmony_ci	return 0;
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
3362306a36Sopenharmony_ci	struct snd_vxpocket *chip = to_vxpocket(_chip);
3462306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = chip->mic_level;
3562306a36Sopenharmony_ci	return 0;
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
4162306a36Sopenharmony_ci	struct snd_vxpocket *chip = to_vxpocket(_chip);
4262306a36Sopenharmony_ci	unsigned int val = ucontrol->value.integer.value[0];
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	if (val > MIC_LEVEL_MAX)
4562306a36Sopenharmony_ci		return -EINVAL;
4662306a36Sopenharmony_ci	mutex_lock(&_chip->mixer_mutex);
4762306a36Sopenharmony_ci	if (chip->mic_level != ucontrol->value.integer.value[0]) {
4862306a36Sopenharmony_ci		vx_set_mic_level(_chip, ucontrol->value.integer.value[0]);
4962306a36Sopenharmony_ci		chip->mic_level = ucontrol->value.integer.value[0];
5062306a36Sopenharmony_ci		mutex_unlock(&_chip->mixer_mutex);
5162306a36Sopenharmony_ci		return 1;
5262306a36Sopenharmony_ci	}
5362306a36Sopenharmony_ci	mutex_unlock(&_chip->mixer_mutex);
5462306a36Sopenharmony_ci	return 0;
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistatic const struct snd_kcontrol_new vx_control_mic_level = {
6062306a36Sopenharmony_ci	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
6162306a36Sopenharmony_ci	.access =	(SNDRV_CTL_ELEM_ACCESS_READWRITE |
6262306a36Sopenharmony_ci			 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
6362306a36Sopenharmony_ci	.name =		"Mic Capture Volume",
6462306a36Sopenharmony_ci	.info =		vx_mic_level_info,
6562306a36Sopenharmony_ci	.get =		vx_mic_level_get,
6662306a36Sopenharmony_ci	.put =		vx_mic_level_put,
6762306a36Sopenharmony_ci	.tlv = { .p = db_scale_mic },
6862306a36Sopenharmony_ci};
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/*
7162306a36Sopenharmony_ci * mic boost level control (for VXP440)
7262306a36Sopenharmony_ci */
7362306a36Sopenharmony_ci#define vx_mic_boost_info		snd_ctl_boolean_mono_info
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
7862306a36Sopenharmony_ci	struct snd_vxpocket *chip = to_vxpocket(_chip);
7962306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = chip->mic_level;
8062306a36Sopenharmony_ci	return 0;
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cistatic int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
8462306a36Sopenharmony_ci{
8562306a36Sopenharmony_ci	struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
8662306a36Sopenharmony_ci	struct snd_vxpocket *chip = to_vxpocket(_chip);
8762306a36Sopenharmony_ci	int val = !!ucontrol->value.integer.value[0];
8862306a36Sopenharmony_ci	mutex_lock(&_chip->mixer_mutex);
8962306a36Sopenharmony_ci	if (chip->mic_level != val) {
9062306a36Sopenharmony_ci		vx_set_mic_boost(_chip, val);
9162306a36Sopenharmony_ci		chip->mic_level = val;
9262306a36Sopenharmony_ci		mutex_unlock(&_chip->mixer_mutex);
9362306a36Sopenharmony_ci		return 1;
9462306a36Sopenharmony_ci	}
9562306a36Sopenharmony_ci	mutex_unlock(&_chip->mixer_mutex);
9662306a36Sopenharmony_ci	return 0;
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic const struct snd_kcontrol_new vx_control_mic_boost = {
10062306a36Sopenharmony_ci	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
10162306a36Sopenharmony_ci	.name =		"Mic Boost",
10262306a36Sopenharmony_ci	.info =		vx_mic_boost_info,
10362306a36Sopenharmony_ci	.get =		vx_mic_boost_get,
10462306a36Sopenharmony_ci	.put =		vx_mic_boost_put,
10562306a36Sopenharmony_ci};
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ciint vxp_add_mic_controls(struct vx_core *_chip)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	struct snd_vxpocket *chip = to_vxpocket(_chip);
11162306a36Sopenharmony_ci	int err;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	/* mute input levels */
11462306a36Sopenharmony_ci	chip->mic_level = 0;
11562306a36Sopenharmony_ci	switch (_chip->type) {
11662306a36Sopenharmony_ci	case VX_TYPE_VXPOCKET:
11762306a36Sopenharmony_ci		vx_set_mic_level(_chip, 0);
11862306a36Sopenharmony_ci		break;
11962306a36Sopenharmony_ci	case VX_TYPE_VXP440:
12062306a36Sopenharmony_ci		vx_set_mic_boost(_chip, 0);
12162306a36Sopenharmony_ci		break;
12262306a36Sopenharmony_ci	}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	/* mic level */
12562306a36Sopenharmony_ci	switch (_chip->type) {
12662306a36Sopenharmony_ci	case VX_TYPE_VXPOCKET:
12762306a36Sopenharmony_ci		err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_level, chip));
12862306a36Sopenharmony_ci		if (err < 0)
12962306a36Sopenharmony_ci			return err;
13062306a36Sopenharmony_ci		break;
13162306a36Sopenharmony_ci	case VX_TYPE_VXP440:
13262306a36Sopenharmony_ci		err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_boost, chip));
13362306a36Sopenharmony_ci		if (err < 0)
13462306a36Sopenharmony_ci			return err;
13562306a36Sopenharmony_ci		break;
13662306a36Sopenharmony_ci	}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	return 0;
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
141