2 * sound/arm/omap/omap-alsa-tsc2102-mixer.c
4 * Alsa mixer driver for TSC2102 chip for OMAP platforms.
6 * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
7 * Code based on the TSC2101 ALSA driver.
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
20 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 * You should have received a copy of the GNU General Public License along
26 * with this program; if not, write to the Free Software Foundation, Inc.,
27 * 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <linux/types.h>
31 #include <linux/spi/tsc2102.h>
33 #include <asm/arch/omap-alsa.h>
35 #include <sound/initval.h>
36 #include <sound/control.h>
38 #include "omap-alsa-tsc2102.h"
39 #include "omap-alsa-dma.h"
41 static int vol[2], mute[2], filter[2];
44 * Converts the Alsa mixer volume (0 - 100) to actual Digital
45 * Gain Control (DGC) value that can be written or read from the
48 * Note that the number "OUTPUT_VOLUME_MAX" is smaller than
49 * OUTPUT_VOLUME_MIN because DGC works as a volume decreaser. (The
50 * higher the value sent to DAC, the more the volume of controlled
51 * channel is decreased)
53 static void set_dac_gain_stereo(int left_ch, int right_ch)
63 lch = OUTPUT_VOLUME_MIN - vol[0] *
64 (OUTPUT_VOLUME_MIN - OUTPUT_VOLUME_MAX) / 100;
68 else if (right_ch < 0)
72 rch = OUTPUT_VOLUME_MIN - vol[1] *
73 (OUTPUT_VOLUME_MIN - OUTPUT_VOLUME_MAX) / 100;
75 tsc2102_set_volume(lch, rch);
78 void init_playback_targets(void)
80 set_dac_gain_stereo(DEFAULT_OUTPUT_VOLUME, DEFAULT_OUTPUT_VOLUME);
83 tsc2102_set_mute(0, 0);
92 * Initializes TSC 2102 and playback target.
94 void snd_omap_init_mixer(void)
98 init_playback_targets();
103 static int __pcm_playback_volume_info(struct snd_kcontrol *kcontrol,
104 struct snd_ctl_elem_info *uinfo)
106 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
108 uinfo->value.integer.min = 0;
109 uinfo->value.integer.max = 100;
113 static int __pcm_playback_volume_get(struct snd_kcontrol *kcontrol,
114 struct snd_ctl_elem_value *ucontrol)
116 ucontrol->value.integer.value[0] = vol[0]; /* L */
117 ucontrol->value.integer.value[1] = vol[1]; /* R */
122 static int __pcm_playback_volume_put(struct snd_kcontrol *kcontrol,
123 struct snd_ctl_elem_value *ucontrol)
126 ucontrol->value.integer.value[0], /* L */
127 ucontrol->value.integer.value[1]); /* R */
131 static int __pcm_playback_switch_info(struct snd_kcontrol *kcontrol,
132 struct snd_ctl_elem_info *uinfo)
134 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
136 uinfo->value.integer.min = 0;
137 uinfo->value.integer.max = 1;
141 static int __pcm_playback_switch_get(struct snd_kcontrol *kcontrol,
142 struct snd_ctl_elem_value *ucontrol)
144 ucontrol->value.integer.value[0] = !mute[0]; /* L */
145 ucontrol->value.integer.value[1] = !mute[1]; /* R */
150 static int __pcm_playback_switch_put(struct snd_kcontrol *kcontrol,
151 struct snd_ctl_elem_value *ucontrol)
153 mute[0] = (ucontrol->value.integer.value[0] == 0); /* L */
154 mute[1] = (ucontrol->value.integer.value[1] == 0); /* R */
156 tsc2102_set_mute(mute[0], mute[1]);
160 static int __pcm_playback_deemphasis_info(struct snd_kcontrol *kcontrol,
161 struct snd_ctl_elem_info *uinfo)
163 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
165 uinfo->value.integer.min = 0;
166 uinfo->value.integer.max = 1;
170 static int __pcm_playback_deemphasis_get(struct snd_kcontrol *kcontrol,
171 struct snd_ctl_elem_value *ucontrol)
173 ucontrol->value.integer.value[0] = filter[0];
177 static int __pcm_playback_deemphasis_put(struct snd_kcontrol *kcontrol,
178 struct snd_ctl_elem_value *ucontrol)
180 filter[0] = (ucontrol->value.integer.value[0] > 0);
182 tsc2102_set_deemphasis(filter[0]);
186 static int __pcm_playback_bassboost_info(struct snd_kcontrol *kcontrol,
187 struct snd_ctl_elem_info *uinfo)
189 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
191 uinfo->value.integer.min = 0;
192 uinfo->value.integer.max = 1;
196 static int __pcm_playback_bassboost_get(struct snd_kcontrol *kcontrol,
197 struct snd_ctl_elem_value *ucontrol)
199 ucontrol->value.integer.value[0] = filter[1];
203 static int __pcm_playback_bassboost_put(struct snd_kcontrol *kcontrol,
204 struct snd_ctl_elem_value *ucontrol)
206 filter[1] = (ucontrol->value.integer.value[0] > 0);
208 tsc2102_set_bassboost(filter[1]);
212 static struct snd_kcontrol_new tsc2102_controls[] __devinitdata = {
214 .name = "Master Playback Volume",
215 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
217 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
218 .info = __pcm_playback_volume_info,
219 .get = __pcm_playback_volume_get,
220 .put = __pcm_playback_volume_put,
223 .name = "Master Playback Switch",
224 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
226 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
227 .info = __pcm_playback_switch_info,
228 .get = __pcm_playback_switch_get,
229 .put = __pcm_playback_switch_put,
232 .name = "De-emphasis Filter Switch",
233 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
235 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
236 .info = __pcm_playback_deemphasis_info,
237 .get = __pcm_playback_deemphasis_get,
238 .put = __pcm_playback_deemphasis_put,
241 .name = "Bass-boost Filter Switch",
242 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
244 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
245 .info = __pcm_playback_bassboost_info,
246 .get = __pcm_playback_bassboost_get,
247 .put = __pcm_playback_bassboost_put,
252 void snd_omap_suspend_mixer(void)
257 void snd_omap_resume_mixer(void)
259 /* The chip was reset, restore the last used values */
260 set_dac_gain_stereo(vol[0], vol[1]);
262 tsc2102_set_mute(mute[0], mute[1]);
263 tsc2102_set_deemphasis(filter[0]);
264 tsc2102_set_bassboost(filter[1]);
268 int snd_omap_mixer(struct snd_card_omap_codec *tsc2102)
275 for (i = 0; i < ARRAY_SIZE(tsc2102_controls); i++) {
276 err = snd_ctl_add(tsc2102->card,
277 snd_ctl_new1(&tsc2102_controls[i],