diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2011-01-11 04:35:29 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-01-11 11:54:15 -0500 |
commit | d1d7093f3f639e693fa763eb51d8d9c349bfd606 (patch) | |
tree | d502551d3690e341167615c858c8b35678972706 /sound/pci | |
parent | 5fc51524746430179c676297fd48aaab28e1b85f (diff) |
ALSA: oxygen: add S/PDIF source selection for Claro cards
Add a mixer control to switch between the optical and coaxial S/PDIF
inputs on the HT-Omega Claro and Claro halo cards.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/oxygen/oxygen.c | 92 |
1 files changed, 88 insertions, 4 deletions
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index db39cfc3b4f3..d7e8ddd9a67b 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c | |||
@@ -34,6 +34,7 @@ | |||
34 | * GPIO 6 -> enable on-board S/PDIF input | 34 | * GPIO 6 -> enable on-board S/PDIF input |
35 | * | 35 | * |
36 | * Claro models: | 36 | * Claro models: |
37 | * GPIO 6 -> S/PDIF from optical (0) or coaxial (1) input | ||
37 | * GPIO 8 -> enable headphone amplifier | 38 | * GPIO 8 -> enable headphone amplifier |
38 | * | 39 | * |
39 | * CM9780: | 40 | * CM9780: |
@@ -137,6 +138,7 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids); | |||
137 | #define GPIO_MERIDIAN_DIG_EXT 0x0010 | 138 | #define GPIO_MERIDIAN_DIG_EXT 0x0010 |
138 | #define GPIO_MERIDIAN_DIG_BOARD 0x0040 | 139 | #define GPIO_MERIDIAN_DIG_BOARD 0x0040 |
139 | 140 | ||
141 | #define GPIO_CLARO_DIG_COAX 0x0040 | ||
140 | #define GPIO_CLARO_HP 0x0100 | 142 | #define GPIO_CLARO_HP 0x0100 |
141 | 143 | ||
142 | struct generic_data { | 144 | struct generic_data { |
@@ -268,6 +270,8 @@ static void claro_enable_hp(struct oxygen *chip) | |||
268 | 270 | ||
269 | static void claro_init(struct oxygen *chip) | 271 | static void claro_init(struct oxygen *chip) |
270 | { | 272 | { |
273 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_DIG_COAX); | ||
274 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_DIG_COAX); | ||
271 | ak4396_init(chip); | 275 | ak4396_init(chip); |
272 | wm8785_init(chip); | 276 | wm8785_init(chip); |
273 | claro_enable_hp(chip); | 277 | claro_enable_hp(chip); |
@@ -275,6 +279,8 @@ static void claro_init(struct oxygen *chip) | |||
275 | 279 | ||
276 | static void claro_halo_init(struct oxygen *chip) | 280 | static void claro_halo_init(struct oxygen *chip) |
277 | { | 281 | { |
282 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_DIG_COAX); | ||
283 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_DIG_COAX); | ||
278 | ak4396_init(chip); | 284 | ak4396_init(chip); |
279 | ak5385_init(chip); | 285 | ak5385_init(chip); |
280 | claro_enable_hp(chip); | 286 | claro_enable_hp(chip); |
@@ -523,14 +529,24 @@ static const struct snd_kcontrol_new hpf_control = { | |||
523 | .put = hpf_put, | 529 | .put = hpf_put, |
524 | }; | 530 | }; |
525 | 531 | ||
526 | static int meridian_dig_source_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) | 532 | static int meridian_dig_source_info(struct snd_kcontrol *ctl, |
533 | struct snd_ctl_elem_info *info) | ||
527 | { | 534 | { |
528 | static const char *const names[2] = { "On-board", "Extension" }; | 535 | static const char *const names[2] = { "On-board", "Extension" }; |
529 | 536 | ||
530 | return snd_ctl_enum_info(info, 1, 2, names); | 537 | return snd_ctl_enum_info(info, 1, 2, names); |
531 | } | 538 | } |
532 | 539 | ||
533 | static int meridian_dig_source_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | 540 | static int claro_dig_source_info(struct snd_kcontrol *ctl, |
541 | struct snd_ctl_elem_info *info) | ||
542 | { | ||
543 | static const char *const names[2] = { "Optical", "Coaxial" }; | ||
544 | |||
545 | return snd_ctl_enum_info(info, 1, 2, names); | ||
546 | } | ||
547 | |||
548 | static int meridian_dig_source_get(struct snd_kcontrol *ctl, | ||
549 | struct snd_ctl_elem_value *value) | ||
534 | { | 550 | { |
535 | struct oxygen *chip = ctl->private_data; | 551 | struct oxygen *chip = ctl->private_data; |
536 | 552 | ||
@@ -540,7 +556,19 @@ static int meridian_dig_source_get(struct snd_kcontrol *ctl, struct snd_ctl_elem | |||
540 | return 0; | 556 | return 0; |
541 | } | 557 | } |
542 | 558 | ||
543 | static int meridian_dig_source_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | 559 | static int claro_dig_source_get(struct snd_kcontrol *ctl, |
560 | struct snd_ctl_elem_value *value) | ||
561 | { | ||
562 | struct oxygen *chip = ctl->private_data; | ||
563 | |||
564 | value->value.enumerated.item[0] = | ||
565 | !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & | ||
566 | GPIO_CLARO_DIG_COAX); | ||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | static int meridian_dig_source_put(struct snd_kcontrol *ctl, | ||
571 | struct snd_ctl_elem_value *value) | ||
544 | { | 572 | { |
545 | struct oxygen *chip = ctl->private_data; | 573 | struct oxygen *chip = ctl->private_data; |
546 | u16 old_reg, new_reg; | 574 | u16 old_reg, new_reg; |
@@ -560,6 +588,25 @@ static int meridian_dig_source_put(struct snd_kcontrol *ctl, struct snd_ctl_elem | |||
560 | return changed; | 588 | return changed; |
561 | } | 589 | } |
562 | 590 | ||
591 | static int claro_dig_source_put(struct snd_kcontrol *ctl, | ||
592 | struct snd_ctl_elem_value *value) | ||
593 | { | ||
594 | struct oxygen *chip = ctl->private_data; | ||
595 | u16 old_reg, new_reg; | ||
596 | int changed; | ||
597 | |||
598 | mutex_lock(&chip->mutex); | ||
599 | old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA); | ||
600 | new_reg = old_reg & ~GPIO_CLARO_DIG_COAX; | ||
601 | if (value->value.enumerated.item[0]) | ||
602 | new_reg |= GPIO_CLARO_DIG_COAX; | ||
603 | changed = new_reg != old_reg; | ||
604 | if (changed) | ||
605 | oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg); | ||
606 | mutex_unlock(&chip->mutex); | ||
607 | return changed; | ||
608 | } | ||
609 | |||
563 | static const struct snd_kcontrol_new meridian_dig_source_control = { | 610 | static const struct snd_kcontrol_new meridian_dig_source_control = { |
564 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 611 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
565 | .name = "IEC958 Source Capture Enum", | 612 | .name = "IEC958 Source Capture Enum", |
@@ -568,6 +615,14 @@ static const struct snd_kcontrol_new meridian_dig_source_control = { | |||
568 | .put = meridian_dig_source_put, | 615 | .put = meridian_dig_source_put, |
569 | }; | 616 | }; |
570 | 617 | ||
618 | static const struct snd_kcontrol_new claro_dig_source_control = { | ||
619 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
620 | .name = "IEC958 Source Capture Enum", | ||
621 | .info = claro_dig_source_info, | ||
622 | .get = claro_dig_source_get, | ||
623 | .put = claro_dig_source_put, | ||
624 | }; | ||
625 | |||
571 | static int generic_mixer_init(struct oxygen *chip) | 626 | static int generic_mixer_init(struct oxygen *chip) |
572 | { | 627 | { |
573 | return snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip)); | 628 | return snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip)); |
@@ -600,6 +655,34 @@ static int meridian_mixer_init(struct oxygen *chip) | |||
600 | return 0; | 655 | return 0; |
601 | } | 656 | } |
602 | 657 | ||
658 | static int claro_mixer_init(struct oxygen *chip) | ||
659 | { | ||
660 | int err; | ||
661 | |||
662 | err = generic_wm8785_mixer_init(chip); | ||
663 | if (err < 0) | ||
664 | return err; | ||
665 | err = snd_ctl_add(chip->card, | ||
666 | snd_ctl_new1(&claro_dig_source_control, chip)); | ||
667 | if (err < 0) | ||
668 | return err; | ||
669 | return 0; | ||
670 | } | ||
671 | |||
672 | static int claro_halo_mixer_init(struct oxygen *chip) | ||
673 | { | ||
674 | int err; | ||
675 | |||
676 | err = generic_mixer_init(chip); | ||
677 | if (err < 0) | ||
678 | return err; | ||
679 | err = snd_ctl_add(chip->card, | ||
680 | snd_ctl_new1(&claro_dig_source_control, chip)); | ||
681 | if (err < 0) | ||
682 | return err; | ||
683 | return 0; | ||
684 | } | ||
685 | |||
603 | static void dump_ak4396_registers(struct oxygen *chip, | 686 | static void dump_ak4396_registers(struct oxygen *chip, |
604 | struct snd_info_buffer *buffer) | 687 | struct snd_info_buffer *buffer) |
605 | { | 688 | { |
@@ -700,13 +783,14 @@ static int __devinit get_oxygen_model(struct oxygen *chip, | |||
700 | break; | 783 | break; |
701 | case MODEL_CLARO: | 784 | case MODEL_CLARO: |
702 | chip->model.init = claro_init; | 785 | chip->model.init = claro_init; |
786 | chip->model.mixer_init = claro_mixer_init; | ||
703 | chip->model.cleanup = claro_cleanup; | 787 | chip->model.cleanup = claro_cleanup; |
704 | chip->model.suspend = claro_suspend; | 788 | chip->model.suspend = claro_suspend; |
705 | chip->model.resume = claro_resume; | 789 | chip->model.resume = claro_resume; |
706 | break; | 790 | break; |
707 | case MODEL_CLARO_HALO: | 791 | case MODEL_CLARO_HALO: |
708 | chip->model.init = claro_halo_init; | 792 | chip->model.init = claro_halo_init; |
709 | chip->model.mixer_init = generic_mixer_init; | 793 | chip->model.mixer_init = claro_halo_mixer_init; |
710 | chip->model.cleanup = claro_cleanup; | 794 | chip->model.cleanup = claro_cleanup; |
711 | chip->model.suspend = claro_suspend; | 795 | chip->model.suspend = claro_suspend; |
712 | chip->model.resume = claro_resume; | 796 | chip->model.resume = claro_resume; |