1/*
2 * Driver for Digigram VXpocket soundcards
3 *
4 * VX-pocket mixer
5 *
6 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
7 *
8 *   This program is free software; you can redistribute it and/or modify
9 *   it under the terms of the GNU General Public License as published by
10 *   the Free Software Foundation; either version 2 of the License, or
11 *   (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21 */
22
23#include <sound/driver.h>
24#include <sound/core.h>
25#include <sound/control.h>
26#include <sound/tlv.h>
27#include "vxpocket.h"
28
29#define MIC_LEVEL_MIN	0
30#define MIC_LEVEL_MAX	8
31
32/*
33 * mic level control (for VXPocket)
34 */
35static int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
36{
37	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
38	uinfo->count = 1;
39	uinfo->value.integer.min = 0;
40	uinfo->value.integer.max = MIC_LEVEL_MAX;
41	return 0;
42}
43
44static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
45{
46	struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
47	struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
48	ucontrol->value.integer.value[0] = chip->mic_level;
49	return 0;
50}
51
52static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
53{
54	struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
55	struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
56	mutex_lock(&_chip->mixer_mutex);
57	if (chip->mic_level != ucontrol->value.integer.value[0]) {
58		vx_set_mic_level(_chip, ucontrol->value.integer.value[0]);
59		chip->mic_level = ucontrol->value.integer.value[0];
60		mutex_unlock(&_chip->mixer_mutex);
61		return 1;
62	}
63	mutex_unlock(&_chip->mixer_mutex);
64	return 0;
65}
66
67static const DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0);
68
69static struct snd_kcontrol_new vx_control_mic_level = {
70	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
71	.access =	(SNDRV_CTL_ELEM_ACCESS_READWRITE |
72			 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
73	.name =		"Mic Capture Volume",
74	.info =		vx_mic_level_info,
75	.get =		vx_mic_level_get,
76	.put =		vx_mic_level_put,
77	.tlv = { .p = db_scale_mic },
78};
79
80/*
81 * mic boost level control (for VXP440)
82 */
83static int vx_mic_boost_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
84{
85	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
86	uinfo->count = 1;
87	uinfo->value.integer.min = 0;
88	uinfo->value.integer.max = 1;
89	return 0;
90}
91
92static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
93{
94	struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
95	struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
96	ucontrol->value.integer.value[0] = chip->mic_level;
97	return 0;
98}
99
100static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
101{
102	struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
103	struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
104	mutex_lock(&_chip->mixer_mutex);
105	if (chip->mic_level != ucontrol->value.integer.value[0]) {
106		vx_set_mic_boost(_chip, ucontrol->value.integer.value[0]);
107		chip->mic_level = ucontrol->value.integer.value[0];
108		mutex_unlock(&_chip->mixer_mutex);
109		return 1;
110	}
111	mutex_unlock(&_chip->mixer_mutex);
112	return 0;
113}
114
115static struct snd_kcontrol_new vx_control_mic_boost = {
116	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
117	.name =		"Mic Boost",
118	.info =		vx_mic_boost_info,
119	.get =		vx_mic_boost_get,
120	.put =		vx_mic_boost_put,
121};
122
123
124int vxp_add_mic_controls(struct vx_core *_chip)
125{
126	struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
127	int err;
128
129	/* mute input levels */
130	chip->mic_level = 0;
131	switch (_chip->type) {
132	case VX_TYPE_VXPOCKET:
133		vx_set_mic_level(_chip, 0);
134		break;
135	case VX_TYPE_VXP440:
136		vx_set_mic_boost(_chip, 0);
137		break;
138	}
139
140	/* mic level */
141	switch (_chip->type) {
142	case VX_TYPE_VXPOCKET:
143		if ((err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_level, chip))) < 0)
144			return err;
145		break;
146	case VX_TYPE_VXP440:
147		if ((err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_boost, chip))) < 0)
148			return err;
149		break;
150	}
151
152	return 0;
153}
154