diff options
author | Jochen Voss <voss@seehuhn.de> | 2006-10-04 12:04:10 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2007-02-09 03:00:03 -0500 |
commit | a58e7cb16dfae8a3c1c98a7ab7ca02a9e9b38921 (patch) | |
tree | a81382ccf27b01f0c28b1e9812fe27cb8a84fbd0 /sound/i2c | |
parent | e4f8e656d8c152c08cd44d0e3c21f009fab09952 (diff) |
[ALSA] Enable capture from line-in and CD on Revolution 5.1
Enable capture from line-in and CD on the Revolution 5.1 card.
This patch adds support for switching between the 5 input channels of
the AK5365 ADC and modifies the Revolution 5.1 driver to make use of
this facility. Previously the capture channel was fixed to channel 0
(microphone on the Revolution 5.1 card).
Signed-off-by: Jochen Voss <voss@seehuhn.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/i2c')
-rw-r--r-- | sound/i2c/other/ak4xxx-adda.c | 85 |
1 files changed, 83 insertions, 2 deletions
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index 5da49e2eb350..fe61b92f4e47 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c | |||
@@ -513,6 +513,66 @@ static int ak4xxx_switch_put(struct snd_kcontrol *kcontrol, | |||
513 | return change; | 513 | return change; |
514 | } | 514 | } |
515 | 515 | ||
516 | #define AK5365_NUM_INPUTS 5 | ||
517 | |||
518 | static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol, | ||
519 | struct snd_ctl_elem_info *uinfo) | ||
520 | { | ||
521 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | ||
522 | int mixer_ch = AK_GET_SHIFT(kcontrol->private_value); | ||
523 | const char **input_names; | ||
524 | int num_names, idx; | ||
525 | |||
526 | input_names = ak->adc_info[mixer_ch].input_names; | ||
527 | |||
528 | num_names = 0; | ||
529 | while (num_names < AK5365_NUM_INPUTS && input_names[num_names]) | ||
530 | ++num_names; | ||
531 | |||
532 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
533 | uinfo->count = 1; | ||
534 | uinfo->value.enumerated.items = num_names; | ||
535 | idx = uinfo->value.enumerated.item; | ||
536 | if (idx >= num_names) | ||
537 | return -EINVAL; | ||
538 | strncpy(uinfo->value.enumerated.name, input_names[idx], | ||
539 | sizeof(uinfo->value.enumerated.name)); | ||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | static int ak4xxx_capture_source_get(struct snd_kcontrol *kcontrol, | ||
544 | struct snd_ctl_elem_value *ucontrol) | ||
545 | { | ||
546 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | ||
547 | int chip = AK_GET_CHIP(kcontrol->private_value); | ||
548 | int addr = AK_GET_ADDR(kcontrol->private_value); | ||
549 | int mask = AK_GET_MASK(kcontrol->private_value); | ||
550 | unsigned char val; | ||
551 | |||
552 | val = snd_akm4xxx_get(ak, chip, addr) & mask; | ||
553 | ucontrol->value.enumerated.item[0] = val; | ||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | static int ak4xxx_capture_source_put(struct snd_kcontrol *kcontrol, | ||
558 | struct snd_ctl_elem_value *ucontrol) | ||
559 | { | ||
560 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | ||
561 | int chip = AK_GET_CHIP(kcontrol->private_value); | ||
562 | int addr = AK_GET_ADDR(kcontrol->private_value); | ||
563 | int mask = AK_GET_MASK(kcontrol->private_value); | ||
564 | unsigned char oval, val; | ||
565 | |||
566 | oval = snd_akm4xxx_get(ak, chip, addr); | ||
567 | val = oval & ~mask; | ||
568 | val |= ucontrol->value.enumerated.item[0] & mask; | ||
569 | if (val != oval) { | ||
570 | snd_akm4xxx_write(ak, chip, addr, val); | ||
571 | return 1; | ||
572 | } | ||
573 | return 0; | ||
574 | } | ||
575 | |||
516 | /* | 576 | /* |
517 | * build AK4xxx controls | 577 | * build AK4xxx controls |
518 | */ | 578 | */ |
@@ -647,9 +707,10 @@ static int build_adc_controls(struct snd_akm4xxx *ak) | |||
647 | 707 | ||
648 | if (ak->type == SND_AK5365 && (idx % 2) == 0) { | 708 | if (ak->type == SND_AK5365 && (idx % 2) == 0) { |
649 | if (! ak->adc_info || | 709 | if (! ak->adc_info || |
650 | ! ak->adc_info[mixer_ch].switch_name) | 710 | ! ak->adc_info[mixer_ch].switch_name) { |
651 | knew.name = "Capture Switch"; | 711 | knew.name = "Capture Switch"; |
652 | else | 712 | knew.index = mixer_ch + ak->idx_offset * 2; |
713 | } else | ||
653 | knew.name = ak->adc_info[mixer_ch].switch_name; | 714 | knew.name = ak->adc_info[mixer_ch].switch_name; |
654 | knew.info = ak4xxx_switch_info; | 715 | knew.info = ak4xxx_switch_info; |
655 | knew.get = ak4xxx_switch_get; | 716 | knew.get = ak4xxx_switch_get; |
@@ -662,6 +723,26 @@ static int build_adc_controls(struct snd_akm4xxx *ak) | |||
662 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); | 723 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); |
663 | if (err < 0) | 724 | if (err < 0) |
664 | return err; | 725 | return err; |
726 | |||
727 | memset(&knew, 0, sizeof(knew)); | ||
728 | knew.name = ak->adc_info[mixer_ch].selector_name; | ||
729 | if (!knew.name) { | ||
730 | knew.name = "Capture Channel"; | ||
731 | knew.index = mixer_ch + ak->idx_offset * 2; | ||
732 | } | ||
733 | |||
734 | knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
735 | knew.info = ak4xxx_capture_source_info; | ||
736 | knew.get = ak4xxx_capture_source_get; | ||
737 | knew.put = ak4xxx_capture_source_put; | ||
738 | knew.access = 0; | ||
739 | /* input selector control: reg. 1, bits 0-2. | ||
740 | * mis-use 'shift' to pass mixer_ch */ | ||
741 | knew.private_value | ||
742 | = AK_COMPOSE(idx/2, 1, mixer_ch, 0x07); | ||
743 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); | ||
744 | if (err < 0) | ||
745 | return err; | ||
665 | } | 746 | } |
666 | 747 | ||
667 | idx += num_stereo; | 748 | idx += num_stereo; |