diff options
Diffstat (limited to 'sound/usb/mixer.c')
-rw-r--r-- | sound/usb/mixer.c | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 298070e8f2d4..ed4d89c8b52a 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -382,6 +382,8 @@ error: | |||
382 | 382 | ||
383 | static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) | 383 | static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) |
384 | { | 384 | { |
385 | validx += cval->idx_off; | ||
386 | |||
385 | return (cval->mixer->protocol == UAC_VERSION_1) ? | 387 | return (cval->mixer->protocol == UAC_VERSION_1) ? |
386 | get_ctl_value_v1(cval, request, validx, value_ret) : | 388 | get_ctl_value_v1(cval, request, validx, value_ret) : |
387 | get_ctl_value_v2(cval, request, validx, value_ret); | 389 | get_ctl_value_v2(cval, request, validx, value_ret); |
@@ -432,6 +434,8 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
432 | unsigned char buf[2]; | 434 | unsigned char buf[2]; |
433 | int idx = 0, val_len, err, timeout = 10; | 435 | int idx = 0, val_len, err, timeout = 10; |
434 | 436 | ||
437 | validx += cval->idx_off; | ||
438 | |||
435 | if (cval->mixer->protocol == UAC_VERSION_1) { | 439 | if (cval->mixer->protocol == UAC_VERSION_1) { |
436 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 440 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
437 | } else { /* UAC_VERSION_2 */ | 441 | } else { /* UAC_VERSION_2 */ |
@@ -719,8 +723,19 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_ | |||
719 | return 0; | 723 | return 0; |
720 | } | 724 | } |
721 | case UAC1_PROCESSING_UNIT: | 725 | case UAC1_PROCESSING_UNIT: |
722 | case UAC1_EXTENSION_UNIT: { | 726 | case UAC1_EXTENSION_UNIT: |
727 | /* UAC2_PROCESSING_UNIT_V2 */ | ||
728 | /* UAC2_EFFECT_UNIT */ { | ||
723 | struct uac_processing_unit_descriptor *d = p1; | 729 | struct uac_processing_unit_descriptor *d = p1; |
730 | |||
731 | if (state->mixer->protocol == UAC_VERSION_2 && | ||
732 | hdr[2] == UAC2_EFFECT_UNIT) { | ||
733 | /* UAC2/UAC1 unit IDs overlap here in an | ||
734 | * uncompatible way. Ignore this unit for now. | ||
735 | */ | ||
736 | return 0; | ||
737 | } | ||
738 | |||
724 | if (d->bNrInPins) { | 739 | if (d->bNrInPins) { |
725 | id = d->baSourceID[0]; | 740 | id = d->baSourceID[0]; |
726 | break; /* continue to parse */ | 741 | break; /* continue to parse */ |
@@ -791,6 +806,33 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, | |||
791 | struct snd_kcontrol *kctl) | 806 | struct snd_kcontrol *kctl) |
792 | { | 807 | { |
793 | switch (cval->mixer->chip->usb_id) { | 808 | switch (cval->mixer->chip->usb_id) { |
809 | case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ | ||
810 | if (strcmp(kctl->id.name, "Effect Duration") == 0) { | ||
811 | cval->min = 0x0000; | ||
812 | cval->max = 0xffff; | ||
813 | cval->res = 0x00e6; | ||
814 | break; | ||
815 | } | ||
816 | if (strcmp(kctl->id.name, "Effect Volume") == 0 || | ||
817 | strcmp(kctl->id.name, "Effect Feedback Volume") == 0) { | ||
818 | cval->min = 0x00; | ||
819 | cval->max = 0xff; | ||
820 | break; | ||
821 | } | ||
822 | if (strstr(kctl->id.name, "Effect Return") != NULL) { | ||
823 | cval->min = 0xb706; | ||
824 | cval->max = 0xff7b; | ||
825 | cval->res = 0x0073; | ||
826 | break; | ||
827 | } | ||
828 | if ((strstr(kctl->id.name, "Playback Volume") != NULL) || | ||
829 | (strstr(kctl->id.name, "Effect Send") != NULL)) { | ||
830 | cval->min = 0xb5fb; /* -73 dB = 0xb6ff */ | ||
831 | cval->max = 0xfcfe; | ||
832 | cval->res = 0x0073; | ||
833 | } | ||
834 | break; | ||
835 | |||
794 | case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */ | 836 | case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */ |
795 | case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */ | 837 | case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */ |
796 | if (strcmp(kctl->id.name, "Effect Duration") == 0) { | 838 | if (strcmp(kctl->id.name, "Effect Duration") == 0) { |
@@ -1094,6 +1136,32 @@ static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str) | |||
1094 | return strlcat(kctl->id.name, str, sizeof(kctl->id.name)); | 1136 | return strlcat(kctl->id.name, str, sizeof(kctl->id.name)); |
1095 | } | 1137 | } |
1096 | 1138 | ||
1139 | /* A lot of headsets/headphones have a "Speaker" mixer. Make sure we | ||
1140 | rename it to "Headphone". We determine if something is a headphone | ||
1141 | similar to how udev determines form factor. */ | ||
1142 | static void check_no_speaker_on_headset(struct snd_kcontrol *kctl, | ||
1143 | struct snd_card *card) | ||
1144 | { | ||
1145 | const char *names_to_check[] = { | ||
1146 | "Headset", "headset", "Headphone", "headphone", NULL}; | ||
1147 | const char **s; | ||
1148 | bool found = 0; | ||
1149 | |||
1150 | if (strcmp("Speaker", kctl->id.name)) | ||
1151 | return; | ||
1152 | |||
1153 | for (s = names_to_check; *s; s++) | ||
1154 | if (strstr(card->shortname, *s)) { | ||
1155 | found = 1; | ||
1156 | break; | ||
1157 | } | ||
1158 | |||
1159 | if (!found) | ||
1160 | return; | ||
1161 | |||
1162 | strlcpy(kctl->id.name, "Headphone", sizeof(kctl->id.name)); | ||
1163 | } | ||
1164 | |||
1097 | static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | 1165 | static void build_feature_ctl(struct mixer_build *state, void *raw_desc, |
1098 | unsigned int ctl_mask, int control, | 1166 | unsigned int ctl_mask, int control, |
1099 | struct usb_audio_term *iterm, int unitid, | 1167 | struct usb_audio_term *iterm, int unitid, |
@@ -1180,6 +1248,10 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1180 | len = snprintf(kctl->id.name, sizeof(kctl->id.name), | 1248 | len = snprintf(kctl->id.name, sizeof(kctl->id.name), |
1181 | "Feature %d", unitid); | 1249 | "Feature %d", unitid); |
1182 | } | 1250 | } |
1251 | |||
1252 | if (!mapped_name) | ||
1253 | check_no_speaker_on_headset(kctl, state->mixer->chip->card); | ||
1254 | |||
1183 | /* determine the stream direction: | 1255 | /* determine the stream direction: |
1184 | * if the connected output is USB stream, then it's likely a | 1256 | * if the connected output is USB stream, then it's likely a |
1185 | * capture stream. otherwise it should be playback (hopefully :) | 1257 | * capture stream. otherwise it should be playback (hopefully :) |