2 * sound/arm/omap/omap-alsa-sx1-mixer.c
4 * Alsa codec Driver for Siemens SX1 board.
5 * based on omap-alsa-tsc2101-mixer.c
7 * Copyright (C) 2006 Vladimir Ananiev (vovan888 at gmail com)
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 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "omap-alsa-sx1.h"
21 #include "omap-alsa-sx1-mixer.h"
23 #include <linux/types.h>
24 #include <sound/initval.h>
25 #include <sound/control.h>
27 static int current_playback_target = PLAYBACK_TARGET_LOUDSPEAKER;
28 static int current_rec_src = REC_SRC_SINGLE_ENDED_MICIN_HED;
29 static int current_volume; /* current volume, we cant read it */
30 static int current_fm_volume; /* current FM radio volume, we cant read it */
33 * Select SX1 recording source.
35 static void set_record_source(int val)
37 /* TODO Recording is done on McBSP2 and Mic only */
38 current_rec_src = val;
41 static int set_mixer_volume(int mixer_vol)
44 if ((mixer_vol < 0) || (mixer_vol > 9)) {
45 printk(KERN_ERR "Trying a bad mixer volume (%d)!\n", mixer_vol);
48 ret = (current_volume != mixer_vol);
49 current_volume = mixer_vol; /* set current volume, we cant read it */
51 i = cn_sx1snd_send(DAC_VOLUME_UPDATE, mixer_vol, 0);
57 static void set_loudspeaker_to_playback_target(void)
60 cn_sx1snd_send(DAC_SETAUDIODEVICE, SX1_DEVICE_SPEAKER, 0);
62 current_playback_target = PLAYBACK_TARGET_LOUDSPEAKER;
65 static void set_headphone_to_playback_target(void)
68 cn_sx1snd_send(DAC_SETAUDIODEVICE, SX1_DEVICE_HEADPHONE, 0);
70 current_playback_target = PLAYBACK_TARGET_HEADPHONE;
73 static void set_telephone_to_playback_target(void)
76 cn_sx1snd_send(DAC_SETAUDIODEVICE, SX1_DEVICE_PHONE, 0);
78 current_playback_target = PLAYBACK_TARGET_CELLPHONE;
81 static void set_telephone_to_record_source(void)
83 cn_sx1snd_send(DAC_SETAUDIODEVICE, SX1_DEVICE_PHONE, 0);
86 static void init_playback_targets(void)
88 set_loudspeaker_to_playback_target();
89 set_mixer_volume(DEFAULT_OUTPUT_VOLUME);
93 * Initializes SX1 record source (to mic) and playback target (to loudspeaker)
95 void snd_omap_init_mixer(void)
97 /* Select headset to record source */
98 set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED);
99 /* Init loudspeaker as a default playback target*/
100 init_playback_targets();
103 /* ---------------------------------------------------------------------- */
104 static int pcm_playback_target_info(struct snd_kcontrol *kcontrol,
105 struct snd_ctl_elem_info *uinfo)
107 static char *texts[PLAYBACK_TARGET_COUNT] = {
108 "Loudspeaker", "Headphone", "Cellphone"
111 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
113 uinfo->value.enumerated.items = PLAYBACK_TARGET_COUNT;
114 if (uinfo->value.enumerated.item > PLAYBACK_TARGET_COUNT - 1)
115 uinfo->value.enumerated.item = PLAYBACK_TARGET_COUNT - 1;
117 strcpy(uinfo->value.enumerated.name,
118 texts[uinfo->value.enumerated.item]);
122 static int pcm_playback_target_get(struct snd_kcontrol *kcontrol,
123 struct snd_ctl_elem_value *ucontrol)
125 ucontrol->value.integer.value[0] = current_playback_target;
129 static int pcm_playback_target_put(struct snd_kcontrol *kcontrol,
130 struct snd_ctl_elem_value *ucontrol)
133 int cur_val = ucontrol->value.integer.value[0];
135 if ((cur_val >= 0) &&
136 (cur_val < PLAYBACK_TARGET_COUNT) &&
137 (cur_val != current_playback_target)) {
138 if (cur_val == PLAYBACK_TARGET_LOUDSPEAKER) {
139 set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED);
140 set_loudspeaker_to_playback_target();
141 } else if (cur_val == PLAYBACK_TARGET_HEADPHONE) {
142 set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HND);
143 set_headphone_to_playback_target();
144 } else if (cur_val == PLAYBACK_TARGET_CELLPHONE) {
145 set_telephone_to_record_source();
146 set_telephone_to_playback_target();
153 /*-----------------------------------------------------------*/
154 static int pcm_playback_volume_info(struct snd_kcontrol *kcontrol,
155 struct snd_ctl_elem_info *uinfo)
157 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
159 uinfo->value.integer.min = 0;
160 uinfo->value.integer.max = 9;
164 static int pcm_playback_volume_get(struct snd_kcontrol *kcontrol,
165 struct snd_ctl_elem_value *ucontrol)
167 ucontrol->value.integer.value[0] = current_volume;
171 static int pcm_playback_volume_put(struct snd_kcontrol *kcontrol,
172 struct snd_ctl_elem_value *ucontrol)
174 return set_mixer_volume(ucontrol->value.integer.value[0]);
177 static int pcm_playback_switch_info(struct snd_kcontrol *kcontrol,
178 struct snd_ctl_elem_info *uinfo)
180 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
182 uinfo->value.integer.min = 0;
183 uinfo->value.integer.max = 1;
187 static int pcm_playback_switch_get(struct snd_kcontrol *kcontrol,
188 struct snd_ctl_elem_value *ucontrol)
190 ucontrol->value.integer.value[0] = 1;
194 static int pcm_playback_switch_put(struct snd_kcontrol *kcontrol,
195 struct snd_ctl_elem_value *ucontrol)
200 /* ----------------------------------------------------------- */
202 static int headset_playback_volume_info(struct snd_kcontrol *kcontrol,
203 struct snd_ctl_elem_info *uinfo)
205 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
207 uinfo->value.integer.min = 0;
208 uinfo->value.integer.max = 9;
212 static int headset_playback_volume_get(struct snd_kcontrol *kcontrol,
213 struct snd_ctl_elem_value *ucontrol)
215 ucontrol->value.integer.value[0] = current_volume;
219 static int headset_playback_volume_put(struct snd_kcontrol *kcontrol,
220 struct snd_ctl_elem_value *ucontrol)
222 return set_mixer_volume(ucontrol->value.integer.value[0]);
225 static int headset_playback_switch_info(struct snd_kcontrol *kcontrol,
226 struct snd_ctl_elem_info *uinfo)
228 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
230 uinfo->value.integer.min = 0;
231 uinfo->value.integer.max = 1;
235 static int headset_playback_switch_get(struct snd_kcontrol *kcontrol,
236 struct snd_ctl_elem_value *ucontrol)
238 ucontrol->value.integer.value[0] = 1;
242 static int headset_playback_switch_put(struct snd_kcontrol *kcontrol,
243 struct snd_ctl_elem_value *ucontrol)
245 /* mute/unmute headset */
247 return adc_pga_unmute_control(ucontrol->value.integer.value[0],
248 TSC2101_HEADSET_GAIN_CTRL,
253 /* ----------------------------------------------------------- */
254 static int fmradio_playback_volume_info(struct snd_kcontrol *kcontrol,
255 struct snd_ctl_elem_info *uinfo)
257 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
259 uinfo->value.integer.min = 0;
260 uinfo->value.integer.max = 9;
264 static int fmradio_playback_volume_get(struct snd_kcontrol *kcontrol,
265 struct snd_ctl_elem_value *ucontrol)
267 ucontrol->value.integer.value[0] = current_fm_volume;
271 static int fmradio_playback_volume_put(struct snd_kcontrol *kcontrol,
272 struct snd_ctl_elem_value *ucontrol)
274 int ret = current_fm_volume != ucontrol->value.integer.value[0];
276 current_fm_volume = ucontrol->value.integer.value[0];
277 i = cn_sx1snd_send(DAC_FMRADIO_OPEN, current_fm_volume, 0);
283 static int fmradio_playback_switch_info(struct snd_kcontrol *kcontrol,
284 struct snd_ctl_elem_info *uinfo)
286 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
288 uinfo->value.integer.min = 0;
289 uinfo->value.integer.max = 1;
293 static int fmradio_playback_switch_get(struct snd_kcontrol *kcontrol,
294 struct snd_ctl_elem_value *ucontrol)
296 ucontrol->value.integer.value[0] = 1;
300 static int fmradio_playback_switch_put(struct snd_kcontrol *kcontrol,
301 struct snd_ctl_elem_value *ucontrol)
303 /* mute/unmute FM radio */
304 if (ucontrol->value.integer.value[0])
305 cn_sx1snd_send(DAC_FMRADIO_OPEN, current_fm_volume, 0);
307 cn_sx1snd_send(DAC_FMRADIO_CLOSE, 0, 0);
311 /* ----------------------------------------------------------- */
312 static int cellphone_input_switch_info(struct snd_kcontrol *kcontrol,
313 struct snd_ctl_elem_info *uinfo)
315 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
317 uinfo->value.integer.min = 0;
318 uinfo->value.integer.max = 1;
322 static int cellphone_input_switch_get(struct snd_kcontrol *kcontrol,
323 struct snd_ctl_elem_value *ucontrol)
325 ucontrol->value.integer.value[0] = 1;
329 static int cellphone_input_switch_put(struct snd_kcontrol *kcontrol,
330 struct snd_ctl_elem_value *ucontrol)
333 return adc_pga_unmute_control(ucontrol->value.integer.value[0],
334 TSC2101_BUZZER_GAIN_CTRL, 15);
338 /* ----------------------------------------------------------- */
340 static int buzzer_input_switch_info(struct snd_kcontrol *kcontrol,
341 struct snd_ctl_elem_info *uinfo)
343 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
345 uinfo->value.integer.min = 0;
346 uinfo->value.integer.max = 1;
350 static int buzzer_input_switch_get(struct snd_kcontrol *kcontrol,
351 struct snd_ctl_elem_value *ucontrol)
353 ucontrol->value.integer.value[0] = 1;
357 static int buzzer_input_switch_put(struct snd_kcontrol *kcontrol,
358 struct snd_ctl_elem_value *ucontrol)
361 return adc_pga_unmute_control(ucontrol->value.integer.value[0],
362 TSC2101_BUZZER_GAIN_CTRL, 6);
366 /*-----------------------------------------------------------*/
368 static struct snd_kcontrol_new egold_control[] __devinitdata = {
370 .name = "Playback Playback Route",
371 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
373 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
374 .info = pcm_playback_target_info,
375 .get = pcm_playback_target_get,
376 .put = pcm_playback_target_put,
378 .name = "Master Playback Volume",
379 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
381 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
382 .info = pcm_playback_volume_info,
383 .get = pcm_playback_volume_get,
384 .put = pcm_playback_volume_put,
386 .name = "Master Playback Switch",
387 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
389 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
390 .info = pcm_playback_switch_info,
391 .get = pcm_playback_switch_get,
392 .put = pcm_playback_switch_put,
394 .name = "Headset Playback Volume",
395 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
397 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
398 .info = headset_playback_volume_info,
399 .get = headset_playback_volume_get,
400 .put = headset_playback_volume_put,
402 .name = "Headset Playback Switch",
403 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
405 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
406 .info = headset_playback_switch_info,
407 .get = headset_playback_switch_get,
408 .put = headset_playback_switch_put,
410 .name = "FM Playback Volume",
411 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
413 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
414 .info = fmradio_playback_volume_info,
415 .get = fmradio_playback_volume_get,
416 .put = fmradio_playback_volume_put,
418 .name = "FM Playback Switch",
419 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
421 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
422 .info = fmradio_playback_switch_info,
423 .get = fmradio_playback_switch_get,
424 .put = fmradio_playback_switch_put,
426 .name = "Cellphone Input Switch",
427 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
429 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
430 .info = cellphone_input_switch_info,
431 .get = cellphone_input_switch_get,
432 .put = cellphone_input_switch_put,
434 .name = "Buzzer Input Switch",
435 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
437 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
438 .info = buzzer_input_switch_info,
439 .get = buzzer_input_switch_get,
440 .put = buzzer_input_switch_put,
445 void snd_omap_suspend_mixer(void)
449 void snd_omap_resume_mixer(void)
451 snd_omap_init_mixer();
455 int snd_omap_mixer(struct snd_card_omap_codec *egold)
463 for (i = 0; i < ARRAY_SIZE(egold_control); i++) {
464 err = snd_ctl_add(egold->card,
465 snd_ctl_new1(&egold_control[i], egold->card));