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/driver.h>
36 #include <sound/initval.h>
37 #include <sound/control.h>
39 #include "omap-alsa-tsc2102.h"
40 #include "omap-alsa-dma.h"
42 static int vol[2], mute[2], filter[2];
45 * Converts the Alsa mixer volume (0 - 100) to actual Digital
46 * Gain Control (DGC) value that can be written or read from the
49 * Note that the number "OUTPUT_VOLUME_MAX" is smaller than
50 * OUTPUT_VOLUME_MIN because DGC works as a volume decreaser. (The
51 * higher the value sent to DAC, the more the volume of controlled
52 * channel is decreased)
54 static void set_dac_gain_stereo(int left_ch, int right_ch)
64 lch = OUTPUT_VOLUME_MIN - vol[0] *
65 (OUTPUT_VOLUME_MIN - OUTPUT_VOLUME_MAX) / 100;
69 else if (right_ch < 0)
73 rch = OUTPUT_VOLUME_MIN - vol[1] *
74 (OUTPUT_VOLUME_MIN - OUTPUT_VOLUME_MAX) / 100;
76 tsc2102_set_volume(lch, rch);
79 void init_playback_targets(void)
81 set_dac_gain_stereo(DEFAULT_OUTPUT_VOLUME, DEFAULT_OUTPUT_VOLUME);
84 tsc2102_set_mute(0, 0);
86 mute[0] = mute[1] = 0;
87 filter[0] = filter[1] = 0;
91 * Initializes TSC 2102 and playback target.
93 void snd_omap_init_mixer(void)
97 init_playback_targets();
102 static int __pcm_playback_volume_info(struct snd_kcontrol *kcontrol,
103 struct snd_ctl_elem_info *uinfo)
105 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
107 uinfo->value.integer.min = 0;
108 uinfo->value.integer.max = 100;
112 static int __pcm_playback_volume_get(struct snd_kcontrol *kcontrol,
113 struct snd_ctl_elem_value *ucontrol)
115 ucontrol->value.integer.value[0] = vol[0]; /* L */
116 ucontrol->value.integer.value[1] = vol[1]; /* R */
121 static int __pcm_playback_volume_put(struct snd_kcontrol *kcontrol,
122 struct snd_ctl_elem_value *ucontrol)
125 ucontrol->value.integer.value[0], /* L */
126 ucontrol->value.integer.value[1]); /* R */
130 static int __pcm_playback_switch_info(struct snd_kcontrol *kcontrol,
131 struct snd_ctl_elem_info *uinfo)
133 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
135 uinfo->value.integer.min = 0;
136 uinfo->value.integer.max = 1;
140 static int __pcm_playback_switch_get(struct snd_kcontrol *kcontrol,
141 struct snd_ctl_elem_value *ucontrol)
143 ucontrol->value.integer.value[0] = !mute[0]; /* L */
144 ucontrol->value.integer.value[1] = !mute[1]; /* R */
149 static int __pcm_playback_switch_put(struct snd_kcontrol *kcontrol,
150 struct snd_ctl_elem_value *ucontrol)
152 mute[0] = (ucontrol->value.integer.value[0] == 0); /* L */
153 mute[1] = (ucontrol->value.integer.value[1] == 0); /* R */
155 tsc2102_set_mute(mute[0], mute[1]);
159 static int __pcm_playback_deemphasis_info(struct snd_kcontrol *kcontrol,
160 struct snd_ctl_elem_info *uinfo)
162 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
164 uinfo->value.integer.min = 0;
165 uinfo->value.integer.max = 1;
169 static int __pcm_playback_deemphasis_get(struct snd_kcontrol *kcontrol,
170 struct snd_ctl_elem_value *ucontrol)
172 ucontrol->value.integer.value[0] = filter[0];
176 static int __pcm_playback_deemphasis_put(struct snd_kcontrol *kcontrol,
177 struct snd_ctl_elem_value *ucontrol)
179 filter[0] = (ucontrol->value.integer.value[0] > 0);
181 tsc2102_set_deemphasis(filter[0]);
185 static int __pcm_playback_bassboost_info(struct snd_kcontrol *kcontrol,
186 struct snd_ctl_elem_info *uinfo)
188 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
190 uinfo->value.integer.min = 0;
191 uinfo->value.integer.max = 1;
195 static int __pcm_playback_bassboost_get(struct snd_kcontrol *kcontrol,
196 struct snd_ctl_elem_value *ucontrol)
198 ucontrol->value.integer.value[0] = filter[1];
202 static int __pcm_playback_bassboost_put(struct snd_kcontrol *kcontrol,
203 struct snd_ctl_elem_value *ucontrol)
205 filter[1] = (ucontrol->value.integer.value[0] > 0);
207 tsc2102_set_bassboost(filter[1]);
211 static struct snd_kcontrol_new tsc2102_controls[] __devinitdata = {
213 .name = "Master Playback Volume",
214 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
216 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
217 .info = __pcm_playback_volume_info,
218 .get = __pcm_playback_volume_get,
219 .put = __pcm_playback_volume_put,
222 .name = "Master Playback Switch",
223 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
225 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
226 .info = __pcm_playback_switch_info,
227 .get = __pcm_playback_switch_get,
228 .put = __pcm_playback_switch_put,
231 .name = "De-emphasis Filter Switch",
232 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
234 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
235 .info = __pcm_playback_deemphasis_info,
236 .get = __pcm_playback_deemphasis_get,
237 .put = __pcm_playback_deemphasis_put,
240 .name = "Bass-boost Filter Switch",
241 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
243 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
244 .info = __pcm_playback_bassboost_info,
245 .get = __pcm_playback_bassboost_get,
246 .put = __pcm_playback_bassboost_put,
251 void snd_omap_suspend_mixer(void)
256 void snd_omap_resume_mixer(void)
258 /* The chip was reset, restore the last used values */
259 set_dac_gain_stereo(vol[0], vol[1]);
261 tsc2102_set_mute(mute[0], mute[1]);
262 tsc2102_set_deemphasis(filter[0]);
263 tsc2102_set_bassboost(filter[1]);
267 int snd_omap_mixer(struct snd_card_omap_codec *tsc2102)
274 for (i = 0; i < ARRAY_SIZE(tsc2102_controls); i ++) {
275 err = snd_ctl_add(tsc2102->card,
276 snd_ctl_new1(&tsc2102_controls[i],