diff options
author | Maxim Levitsky <maximlevitsky@gmail.com> | 2007-09-03 09:29:37 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2007-10-16 09:59:49 -0400 |
commit | 5f10c4a9a0c02597206fe2f027026ee25d3e07ad (patch) | |
tree | 24019b2fa8105534bacbffb3a3f3c8267120b02a /sound | |
parent | 0fb87bb474f978446786263deff6263284e6e011 (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.c | 58 |
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 | |||
302 | static 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 | |||
312 | static 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 | |||
299 | static struct hda_verb stac9200_core_init[] = { | 343 | static 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 | ||
350 | static struct snd_kcontrol_new stac9200_mixer[] = { | 405 | static 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 */ |
378 | static struct snd_kcontrol_new stac9227_mixer[] = { | 433 | static 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 | ||
385 | static struct snd_kcontrol_new stac927x_mixer[] = { | 441 | static 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), |