aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMaxim Levitsky <maximlevitsky@gmail.com>2007-09-03 09:29:37 -0400
committerJaroslav Kysela <perex@perex.cz>2007-10-16 09:59:49 -0400
commit5f10c4a9a0c02597206fe2f027026ee25d3e07ad (patch)
tree24019b2fa8105534bacbffb3a3f3c8267120b02a /sound
parent0fb87bb474f978446786263deff6263284e6e011 (diff)
[ALSA] hda-codec - add support for analog loopback to STAC9204/9205/922x/927x
The analog loopback routes the sound just before it enters ADC0 to output of DAC0. Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_sigmatel.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 297f74019279..c94775c8a0bf 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -147,6 +147,7 @@ struct sigmatel_spec {
147 /* i/o switches */ 147 /* i/o switches */
148 unsigned int io_switch[2]; 148 unsigned int io_switch[2];
149 unsigned int clfe_swap; 149 unsigned int clfe_swap;
150 unsigned int aloopback;
150 151
151 struct hda_pcm pcm_rec[2]; /* PCM information */ 152 struct hda_pcm pcm_rec[2]; /* PCM information */
152 153
@@ -296,6 +297,49 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
296 spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); 297 spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]);
297} 298}
298 299
300#define stac92xx_aloopback_info snd_ctl_boolean_mono_info
301
302static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol,
303 struct snd_ctl_elem_value *ucontrol)
304{
305 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
306 struct sigmatel_spec *spec = codec->spec;
307
308 ucontrol->value.integer.value[0] = spec->aloopback;
309 return 0;
310}
311
312static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol,
313 struct snd_ctl_elem_value *ucontrol)
314{
315 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
316 struct sigmatel_spec *spec = codec->spec;
317 unsigned int dac_mode;
318
319 if (spec->aloopback == ucontrol->value.integer.value[0])
320 return 0;
321
322 spec->aloopback = ucontrol->value.integer.value[0];
323
324
325 dac_mode = snd_hda_codec_read(codec, codec->afg, 0,
326 kcontrol->private_value & 0xFFFF, 0x0);
327
328 if (spec->aloopback) {
329 snd_hda_power_up(codec);
330 dac_mode |= 0x40;
331 } else {
332 snd_hda_power_down(codec);
333 dac_mode &= ~0x40;
334 }
335
336 snd_hda_codec_write_cache(codec, codec->afg, 0,
337 kcontrol->private_value >> 16, dac_mode);
338
339 return 1;
340}
341
342
299static struct hda_verb stac9200_core_init[] = { 343static struct hda_verb stac9200_core_init[] = {
300 /* set dac0mux for dac converter */ 344 /* set dac0mux for dac converter */
301 { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 345 { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
@@ -346,6 +390,17 @@ static struct hda_verb stac9205_core_init[] = {
346 .put = stac92xx_mux_enum_put, \ 390 .put = stac92xx_mux_enum_put, \
347 } 391 }
348 392
393#define STAC_ANALOG_LOOPBACK(verb_read,verb_write) \
394 { \
395 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
396 .name = "Analog Loopback", \
397 .count = 1, \
398 .info = stac92xx_aloopback_info, \
399 .get = stac92xx_aloopback_get, \
400 .put = stac92xx_aloopback_put, \
401 .private_value = verb_read | (verb_write << 16), \
402 }
403
349 404
350static struct snd_kcontrol_new stac9200_mixer[] = { 405static struct snd_kcontrol_new stac9200_mixer[] = {
351 HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), 406 HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
@@ -377,6 +432,7 @@ static struct snd_kcontrol_new stac922x_mixer[] = {
377/* This needs to be generated dynamically based on sequence */ 432/* This needs to be generated dynamically based on sequence */
378static struct snd_kcontrol_new stac9227_mixer[] = { 433static struct snd_kcontrol_new stac9227_mixer[] = {
379 STAC_INPUT_SOURCE, 434 STAC_INPUT_SOURCE,
435 STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB),
380 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), 436 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
381 HDA_CODEC_MUTE("Capture Switch", 0x1b, 0x0, HDA_OUTPUT), 437 HDA_CODEC_MUTE("Capture Switch", 0x1b, 0x0, HDA_OUTPUT),
382 { } /* end */ 438 { } /* end */
@@ -384,6 +440,7 @@ static struct snd_kcontrol_new stac9227_mixer[] = {
384 440
385static struct snd_kcontrol_new stac927x_mixer[] = { 441static struct snd_kcontrol_new stac927x_mixer[] = {
386 STAC_INPUT_SOURCE, 442 STAC_INPUT_SOURCE,
443 STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB),
387 HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT), 444 HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT),
388 HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT), 445 HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT),
389 HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1b, 0x0, HDA_OUTPUT), 446 HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1b, 0x0, HDA_OUTPUT),
@@ -400,6 +457,7 @@ static struct snd_kcontrol_new stac9205_mixer[] = {
400 .put = stac92xx_dmux_enum_put, 457 .put = stac92xx_dmux_enum_put,
401 }, 458 },
402 STAC_INPUT_SOURCE, 459 STAC_INPUT_SOURCE,
460 STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0),
403 HDA_CODEC_VOLUME("InMux Capture Volume", 0x19, 0x0, HDA_OUTPUT), 461 HDA_CODEC_VOLUME("InMux Capture Volume", 0x19, 0x0, HDA_OUTPUT),
404 HDA_CODEC_VOLUME("InVol Capture Volume", 0x1b, 0x0, HDA_INPUT), 462 HDA_CODEC_VOLUME("InVol Capture Volume", 0x1b, 0x0, HDA_INPUT),
405 HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1d, 0x0, HDA_OUTPUT), 463 HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1d, 0x0, HDA_OUTPUT),