aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorFelix Homann <linuxaudio@showlabor.de>2012-04-23 14:24:27 -0400
committerTakashi Iwai <tiwai@suse.de>2012-04-24 02:06:06 -0400
commitd34bf1485192b9cedb7b0dec8988324099b6a0b1 (patch)
tree774696ae5d1d055b35f2339c4fb68bae17436889 /sound/usb
parentcfe8f97c8243cec6614524779424f2de9c335c5c (diff)
ALSA: usb-audio: M-Audio Fast Track Ultra: Add effect controls
This adds controls for the effects section on the FTU devices. Some of these controls need volume quirks. They are added to mixer.c. [fixed missing break by tiwai] Signed-off-by: Felix Homann <linuxaudio@showlabor.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/mixer.c20
-rw-r--r--sound/usb/mixer_quirks.c299
2 files changed, 319 insertions, 0 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index bb56f5353fe0..3d70245ab442 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -770,6 +770,26 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
770 struct snd_kcontrol *kctl) 770 struct snd_kcontrol *kctl)
771{ 771{
772 switch (cval->mixer->chip->usb_id) { 772 switch (cval->mixer->chip->usb_id) {
773 case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
774 case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
775 if (strcmp(kctl->id.name, "Effect Duration") == 0) {
776 snd_printk(KERN_INFO
777 "usb-audio: set quirk for FTU Effect Duration\n");
778 cval->min = 0x0000;
779 cval->max = 0x7f00;
780 cval->res = 0x0100;
781 break;
782 }
783 if (strcmp(kctl->id.name, "Effect Volume") == 0 ||
784 strcmp(kctl->id.name, "Effect Feedback Volume") == 0) {
785 snd_printk(KERN_INFO
786 "usb-audio: set quirks for FTU Effect Feedback/Volume\n");
787 cval->min = 0x00;
788 cval->max = 0x7f;
789 break;
790 }
791 break;
792
773 case USB_ID(0x0471, 0x0101): 793 case USB_ID(0x0471, 0x0101):
774 case USB_ID(0x0471, 0x0104): 794 case USB_ID(0x0471, 0x0104):
775 case USB_ID(0x0471, 0x0105): 795 case USB_ID(0x0471, 0x0105):
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 6671e64a7630..b44df6e5109b 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -574,6 +574,186 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
574} 574}
575 575
576/* M-Audio FastTrack Ultra quirks */ 576/* M-Audio FastTrack Ultra quirks */
577/* FTU Effect switch */
578struct snd_ftu_eff_switch_priv_val {
579 struct usb_mixer_interface *mixer;
580 int cached_value;
581 int is_cached;
582};
583
584static int snd_ftu_eff_switch_info(struct snd_kcontrol *kcontrol,
585 struct snd_ctl_elem_info *uinfo)
586{
587 static const char *texts[8] = {"Room 1",
588 "Room 2",
589 "Room 3",
590 "Hall 1",
591 "Hall 2",
592 "Plate",
593 "Delay",
594 "Echo"
595 };
596
597 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
598 uinfo->count = 1;
599 uinfo->value.enumerated.items = 8;
600 if (uinfo->value.enumerated.item > 7)
601 uinfo->value.enumerated.item = 7;
602 strcpy(uinfo->value.enumerated.name,
603 texts[uinfo->value.enumerated.item]);
604
605 return 0;
606}
607
608static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,
609 struct snd_ctl_elem_value *ucontrol)
610{
611 struct snd_usb_audio *chip;
612 struct usb_mixer_interface *mixer;
613 struct snd_ftu_eff_switch_priv_val *pval;
614 int err;
615 unsigned char value[2];
616
617 const int id = 6;
618 const int validx = 1;
619 const int val_len = 2;
620
621 value[0] = 0x00;
622 value[1] = 0x00;
623
624 pval = (struct snd_ftu_eff_switch_priv_val *)
625 kctl->private_value;
626
627 if (pval->is_cached) {
628 ucontrol->value.enumerated.item[0] = pval->cached_value;
629 return 0;
630 }
631
632 mixer = (struct usb_mixer_interface *) pval->mixer;
633 if (snd_BUG_ON(!mixer))
634 return -EINVAL;
635
636 chip = (struct snd_usb_audio *) mixer->chip;
637 if (snd_BUG_ON(!chip))
638 return -EINVAL;
639
640
641 err = snd_usb_ctl_msg(chip->dev,
642 usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
643 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
644 validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
645 value, val_len);
646 if (err < 0)
647 return err;
648
649 ucontrol->value.enumerated.item[0] = value[0];
650 pval->cached_value = value[0];
651 pval->is_cached = 1;
652
653 return 0;
654}
655
656static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
657 struct snd_ctl_elem_value *ucontrol)
658{
659 struct snd_usb_audio *chip;
660 struct snd_ftu_eff_switch_priv_val *pval;
661
662 struct usb_mixer_interface *mixer;
663 int changed, cur_val, err, new_val;
664 unsigned char value[2];
665
666
667 const int id = 6;
668 const int validx = 1;
669 const int val_len = 2;
670
671 changed = 0;
672
673 pval = (struct snd_ftu_eff_switch_priv_val *)
674 kctl->private_value;
675 cur_val = pval->cached_value;
676 new_val = ucontrol->value.enumerated.item[0];
677
678 mixer = (struct usb_mixer_interface *) pval->mixer;
679 if (snd_BUG_ON(!mixer))
680 return -EINVAL;
681
682 chip = (struct snd_usb_audio *) mixer->chip;
683 if (snd_BUG_ON(!chip))
684 return -EINVAL;
685
686 if (!pval->is_cached) {
687 /* Read current value */
688 err = snd_usb_ctl_msg(chip->dev,
689 usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
690 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
691 validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
692 value, val_len);
693 if (err < 0)
694 return err;
695
696 cur_val = value[0];
697 pval->cached_value = cur_val;
698 pval->is_cached = 1;
699 }
700 /* update value if needed */
701 if (cur_val != new_val) {
702 value[0] = new_val;
703 value[1] = 0;
704 err = snd_usb_ctl_msg(chip->dev,
705 usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
706 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
707 validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
708 value, val_len);
709 if (err < 0)
710 return err;
711
712 pval->cached_value = new_val;
713 pval->is_cached = 1;
714 changed = 1;
715 }
716
717 return changed;
718}
719
720static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer)
721{
722 static struct snd_kcontrol_new template = {
723 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
724 .name = "Effect Program Switch",
725 .index = 0,
726 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
727 .info = snd_ftu_eff_switch_info,
728 .get = snd_ftu_eff_switch_get,
729 .put = snd_ftu_eff_switch_put
730 };
731
732 int err;
733 struct snd_kcontrol *kctl;
734 struct snd_ftu_eff_switch_priv_val *pval;
735
736 pval = kzalloc(sizeof(*pval), GFP_KERNEL);
737 if (!pval)
738 return -ENOMEM;
739
740 pval->cached_value = 0;
741 pval->is_cached = 0;
742 pval->mixer = mixer;
743
744 template.private_value = (unsigned long) pval;
745 kctl = snd_ctl_new1(&template, mixer->chip);
746 if (!kctl) {
747 kfree(pval);
748 return -ENOMEM;
749 }
750
751 err = snd_ctl_add(mixer->chip->card, kctl);
752 if (err < 0)
753 return err;
754
755 return 0;
756}
577 757
578/* Create volume controls for FTU devices*/ 758/* Create volume controls for FTU devices*/
579static int snd_ftu_create_volume_ctls(struct usb_mixer_interface *mixer) 759static int snd_ftu_create_volume_ctls(struct usb_mixer_interface *mixer)
@@ -614,6 +794,102 @@ static int snd_ftu_create_volume_ctls(struct usb_mixer_interface *mixer)
614 return 0; 794 return 0;
615} 795}
616 796
797/* This control needs a volume quirk, see mixer.c */
798static int snd_ftu_create_effect_volume_ctl(struct usb_mixer_interface *mixer)
799{
800 static const char name[] = "Effect Volume";
801 const unsigned int id = 6;
802 const int val_type = USB_MIXER_U8;
803 const unsigned int control = 2;
804 const unsigned int cmask = 0;
805
806 return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
807 name, snd_usb_mixer_vol_tlv);
808}
809
810/* This control needs a volume quirk, see mixer.c */
811static int snd_ftu_create_effect_duration_ctl(struct usb_mixer_interface *mixer)
812{
813 static const char name[] = "Effect Duration";
814 const unsigned int id = 6;
815 const int val_type = USB_MIXER_S16;
816 const unsigned int control = 3;
817 const unsigned int cmask = 0;
818
819 return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
820 name, snd_usb_mixer_vol_tlv);
821}
822
823/* This control needs a volume quirk, see mixer.c */
824static int snd_ftu_create_effect_feedback_ctl(struct usb_mixer_interface *mixer)
825{
826 static const char name[] = "Effect Feedback Volume";
827 const unsigned int id = 6;
828 const int val_type = USB_MIXER_U8;
829 const unsigned int control = 4;
830 const unsigned int cmask = 0;
831
832 return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type,
833 name, NULL);
834}
835
836static int snd_ftu_create_effect_return_ctls(struct usb_mixer_interface *mixer)
837{
838 unsigned int cmask;
839 int err, ch;
840 char name[48];
841
842 const unsigned int id = 7;
843 const int val_type = USB_MIXER_S16;
844 const unsigned int control = 7;
845
846 for (ch = 0; ch < 4; ++ch) {
847 cmask = 1 << ch;
848 snprintf(name, sizeof(name),
849 "Effect Return %d Volume", ch + 1);
850 err = snd_create_std_mono_ctl(mixer, id, control,
851 cmask, val_type, name,
852 snd_usb_mixer_vol_tlv);
853 if (err < 0)
854 return err;
855 }
856
857 return 0;
858}
859
860static int snd_ftu_create_effect_send_ctls(struct usb_mixer_interface *mixer)
861{
862 unsigned int cmask;
863 int err, ch;
864 char name[48];
865
866 const unsigned int id = 5;
867 const int val_type = USB_MIXER_S16;
868 const unsigned int control = 9;
869
870 for (ch = 0; ch < 8; ++ch) {
871 cmask = 1 << ch;
872 snprintf(name, sizeof(name),
873 "Effect Send AIn%d Volume", ch + 1);
874 err = snd_create_std_mono_ctl(mixer, id, control, cmask,
875 val_type, name,
876 snd_usb_mixer_vol_tlv);
877 if (err < 0)
878 return err;
879 }
880 for (ch = 8; ch < 16; ++ch) {
881 cmask = 1 << ch;
882 snprintf(name, sizeof(name),
883 "Effect Send DIn%d Volume", ch - 7);
884 err = snd_create_std_mono_ctl(mixer, id, control, cmask,
885 val_type, name,
886 snd_usb_mixer_vol_tlv);
887 if (err < 0)
888 return err;
889 }
890 return 0;
891}
892
617static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer) 893static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer)
618{ 894{
619 int err; 895 int err;
@@ -622,6 +898,29 @@ static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer)
622 if (err < 0) 898 if (err < 0)
623 return err; 899 return err;
624 900
901 err = snd_ftu_create_effect_switch(mixer);
902 if (err < 0)
903 return err;
904 err = snd_ftu_create_effect_volume_ctl(mixer);
905 if (err < 0)
906 return err;
907
908 err = snd_ftu_create_effect_duration_ctl(mixer);
909 if (err < 0)
910 return err;
911
912 err = snd_ftu_create_effect_feedback_ctl(mixer);
913 if (err < 0)
914 return err;
915
916 err = snd_ftu_create_effect_return_ctls(mixer);
917 if (err < 0)
918 return err;
919
920 err = snd_ftu_create_effect_send_ctls(mixer);
921 if (err < 0)
922 return err;
923
625 return 0; 924 return 0;
626} 925}
627 926