diff options
author | Takashi Iwai <tiwai@suse.de> | 2014-11-20 11:20:46 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-11-21 05:59:17 -0500 |
commit | b61f90eac1ff9d1b30497e611aba4651d4066706 (patch) | |
tree | eb473cc5fe3590f9d1d759a24e7c57427ad5f4ca /sound/usb/mixer_scarlett.c | |
parent | 288673beae6cbd8198be94284adbaeb5cba7dbda (diff) |
ALSA: usb-audio: Add resume support for Scarlett mixers
Scarlett driver uses almost compatible usb_mixer_elem_info struct, so
we just need to add a couple of simple resume callbacks to handle them
accordingly.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/mixer_scarlett.c')
-rw-r--r-- | sound/usb/mixer_scarlett.c | 65 |
1 files changed, 51 insertions, 14 deletions
diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c index 92dba35660b3..9109652b88b9 100644 --- a/sound/usb/mixer_scarlett.c +++ b/sound/usb/mixer_scarlett.c | |||
@@ -285,6 +285,19 @@ static int scarlett_ctl_switch_put(struct snd_kcontrol *kctl, | |||
285 | return changed; | 285 | return changed; |
286 | } | 286 | } |
287 | 287 | ||
288 | static int scarlett_ctl_resume(struct usb_mixer_elem_list *list) | ||
289 | { | ||
290 | struct usb_mixer_elem_info *elem = | ||
291 | container_of(list, struct usb_mixer_elem_info, head); | ||
292 | int i; | ||
293 | |||
294 | for (i = 0; i < elem->channels; i++) | ||
295 | if (elem->cached & (1 << i)) | ||
296 | snd_usb_set_cur_mix_value(elem, i, i, | ||
297 | elem->cache_val[i]); | ||
298 | return 0; | ||
299 | } | ||
300 | |||
288 | static int scarlett_ctl_info(struct snd_kcontrol *kctl, | 301 | static int scarlett_ctl_info(struct snd_kcontrol *kctl, |
289 | struct snd_ctl_elem_info *uinfo) | 302 | struct snd_ctl_elem_info *uinfo) |
290 | { | 303 | { |
@@ -432,6 +445,16 @@ static int scarlett_ctl_enum_put(struct snd_kcontrol *kctl, | |||
432 | return 0; | 445 | return 0; |
433 | } | 446 | } |
434 | 447 | ||
448 | static int scarlett_ctl_enum_resume(struct usb_mixer_elem_list *list) | ||
449 | { | ||
450 | struct usb_mixer_elem_info *elem = | ||
451 | container_of(list, struct usb_mixer_elem_info, head); | ||
452 | |||
453 | if (elem->cached) | ||
454 | snd_usb_set_cur_mix_value(elem, 0, 0, *elem->cache_val); | ||
455 | return 0; | ||
456 | } | ||
457 | |||
435 | static int scarlett_ctl_meter_get(struct snd_kcontrol *kctl, | 458 | static int scarlett_ctl_meter_get(struct snd_kcontrol *kctl, |
436 | struct snd_ctl_elem_value *ucontrol) | 459 | struct snd_ctl_elem_value *ucontrol) |
437 | { | 460 | { |
@@ -514,6 +537,7 @@ static struct snd_kcontrol_new usb_scarlett_ctl_sync = { | |||
514 | 537 | ||
515 | static int add_new_ctl(struct usb_mixer_interface *mixer, | 538 | static int add_new_ctl(struct usb_mixer_interface *mixer, |
516 | const struct snd_kcontrol_new *ncontrol, | 539 | const struct snd_kcontrol_new *ncontrol, |
540 | usb_mixer_elem_resume_func_t resume, | ||
517 | int index, int offset, int num, | 541 | int index, int offset, int num, |
518 | int val_type, int channels, const char *name, | 542 | int val_type, int channels, const char *name, |
519 | const struct scarlett_mixer_elem_enum_info *opt, | 543 | const struct scarlett_mixer_elem_enum_info *opt, |
@@ -529,6 +553,7 @@ static int add_new_ctl(struct usb_mixer_interface *mixer, | |||
529 | return -ENOMEM; | 553 | return -ENOMEM; |
530 | 554 | ||
531 | elem->head.mixer = mixer; | 555 | elem->head.mixer = mixer; |
556 | elem->head.resume = resume; | ||
532 | elem->control = offset; | 557 | elem->control = offset; |
533 | elem->idx_off = num; | 558 | elem->idx_off = num; |
534 | elem->head.id = index; | 559 | elem->head.id = index; |
@@ -548,7 +573,7 @@ static int add_new_ctl(struct usb_mixer_interface *mixer, | |||
548 | 573 | ||
549 | strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); | 574 | strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); |
550 | 575 | ||
551 | err = snd_ctl_add(mixer->chip->card, kctl); | 576 | err = snd_usb_mixer_add_control(&elem->head, kctl); |
552 | if (err < 0) | 577 | if (err < 0) |
553 | return err; | 578 | return err; |
554 | 579 | ||
@@ -569,7 +594,8 @@ static int add_output_ctls(struct usb_mixer_interface *mixer, | |||
569 | /* Add mute switch */ | 594 | /* Add mute switch */ |
570 | snprintf(mx, sizeof(mx), "Master %d (%s) Playback Switch", | 595 | snprintf(mx, sizeof(mx), "Master %d (%s) Playback Switch", |
571 | index + 1, name); | 596 | index + 1, name); |
572 | err = add_new_ctl(mixer, &usb_scarlett_ctl_switch, 0x0a, 0x01, | 597 | err = add_new_ctl(mixer, &usb_scarlett_ctl_switch, |
598 | scarlett_ctl_resume, 0x0a, 0x01, | ||
573 | 2*index+1, USB_MIXER_S16, 2, mx, NULL, &elem); | 599 | 2*index+1, USB_MIXER_S16, 2, mx, NULL, &elem); |
574 | if (err < 0) | 600 | if (err < 0) |
575 | return err; | 601 | return err; |
@@ -577,7 +603,8 @@ static int add_output_ctls(struct usb_mixer_interface *mixer, | |||
577 | /* Add volume control and initialize to 0 */ | 603 | /* Add volume control and initialize to 0 */ |
578 | snprintf(mx, sizeof(mx), "Master %d (%s) Playback Volume", | 604 | snprintf(mx, sizeof(mx), "Master %d (%s) Playback Volume", |
579 | index + 1, name); | 605 | index + 1, name); |
580 | err = add_new_ctl(mixer, &usb_scarlett_ctl_master, 0x0a, 0x02, | 606 | err = add_new_ctl(mixer, &usb_scarlett_ctl_master, |
607 | scarlett_ctl_resume, 0x0a, 0x02, | ||
581 | 2*index+1, USB_MIXER_S16, 2, mx, NULL, &elem); | 608 | 2*index+1, USB_MIXER_S16, 2, mx, NULL, &elem); |
582 | if (err < 0) | 609 | if (err < 0) |
583 | return err; | 610 | return err; |
@@ -585,7 +612,8 @@ static int add_output_ctls(struct usb_mixer_interface *mixer, | |||
585 | /* Add L channel source playback enumeration */ | 612 | /* Add L channel source playback enumeration */ |
586 | snprintf(mx, sizeof(mx), "Master %dL (%s) Source Playback Enum", | 613 | snprintf(mx, sizeof(mx), "Master %dL (%s) Source Playback Enum", |
587 | index + 1, name); | 614 | index + 1, name); |
588 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, 0x33, 0x00, | 615 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, |
616 | scarlett_ctl_enum_resume, 0x33, 0x00, | ||
589 | 2*index, USB_MIXER_S16, 1, mx, &info->opt_master, | 617 | 2*index, USB_MIXER_S16, 1, mx, &info->opt_master, |
590 | &elem); | 618 | &elem); |
591 | if (err < 0) | 619 | if (err < 0) |
@@ -594,7 +622,8 @@ static int add_output_ctls(struct usb_mixer_interface *mixer, | |||
594 | /* Add R channel source playback enumeration */ | 622 | /* Add R channel source playback enumeration */ |
595 | snprintf(mx, sizeof(mx), "Master %dR (%s) Source Playback Enum", | 623 | snprintf(mx, sizeof(mx), "Master %dR (%s) Source Playback Enum", |
596 | index + 1, name); | 624 | index + 1, name); |
597 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, 0x33, 0x00, | 625 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, |
626 | scarlett_ctl_enum_resume, 0x33, 0x00, | ||
598 | 2*index+1, USB_MIXER_S16, 1, mx, &info->opt_master, | 627 | 2*index+1, USB_MIXER_S16, 1, mx, &info->opt_master, |
599 | &elem); | 628 | &elem); |
600 | if (err < 0) | 629 | if (err < 0) |
@@ -824,13 +853,15 @@ static int scarlett_controls_create_generic(struct usb_mixer_interface *mixer, | |||
824 | struct usb_mixer_elem_info *elem; | 853 | struct usb_mixer_elem_info *elem; |
825 | 854 | ||
826 | /* create master switch and playback volume */ | 855 | /* create master switch and playback volume */ |
827 | err = add_new_ctl(mixer, &usb_scarlett_ctl_switch, 0x0a, 0x01, 0, | 856 | err = add_new_ctl(mixer, &usb_scarlett_ctl_switch, |
857 | scarlett_ctl_resume, 0x0a, 0x01, 0, | ||
828 | USB_MIXER_S16, 1, "Master Playback Switch", NULL, | 858 | USB_MIXER_S16, 1, "Master Playback Switch", NULL, |
829 | &elem); | 859 | &elem); |
830 | if (err < 0) | 860 | if (err < 0) |
831 | return err; | 861 | return err; |
832 | 862 | ||
833 | err = add_new_ctl(mixer, &usb_scarlett_ctl_master, 0x0a, 0x02, 0, | 863 | err = add_new_ctl(mixer, &usb_scarlett_ctl_master, |
864 | scarlett_ctl_resume, 0x0a, 0x02, 0, | ||
834 | USB_MIXER_S16, 1, "Master Playback Volume", NULL, | 865 | USB_MIXER_S16, 1, "Master Playback Volume", NULL, |
835 | &elem); | 866 | &elem); |
836 | if (err < 0) | 867 | if (err < 0) |
@@ -848,7 +879,8 @@ static int scarlett_controls_create_generic(struct usb_mixer_interface *mixer, | |||
848 | break; | 879 | break; |
849 | case SCARLETT_SWITCH_IMPEDANCE: | 880 | case SCARLETT_SWITCH_IMPEDANCE: |
850 | sprintf(mx, "Input %d Impedance Switch", ctl->num); | 881 | sprintf(mx, "Input %d Impedance Switch", ctl->num); |
851 | err = add_new_ctl(mixer, &usb_scarlett_ctl_enum, 0x01, | 882 | err = add_new_ctl(mixer, &usb_scarlett_ctl_enum, |
883 | scarlett_ctl_enum_resume, 0x01, | ||
852 | 0x09, ctl->num, USB_MIXER_S16, 1, mx, | 884 | 0x09, ctl->num, USB_MIXER_S16, 1, mx, |
853 | &opt_impedance, &elem); | 885 | &opt_impedance, &elem); |
854 | if (err < 0) | 886 | if (err < 0) |
@@ -856,7 +888,8 @@ static int scarlett_controls_create_generic(struct usb_mixer_interface *mixer, | |||
856 | break; | 888 | break; |
857 | case SCARLETT_SWITCH_PAD: | 889 | case SCARLETT_SWITCH_PAD: |
858 | sprintf(mx, "Input %d Pad Switch", ctl->num); | 890 | sprintf(mx, "Input %d Pad Switch", ctl->num); |
859 | err = add_new_ctl(mixer, &usb_scarlett_ctl_enum, 0x01, | 891 | err = add_new_ctl(mixer, &usb_scarlett_ctl_enum, |
892 | scarlett_ctl_enum_resume, 0x01, | ||
860 | 0x0b, ctl->num, USB_MIXER_S16, 1, mx, | 893 | 0x0b, ctl->num, USB_MIXER_S16, 1, mx, |
861 | &opt_pad, &elem); | 894 | &opt_pad, &elem); |
862 | if (err < 0) | 895 | if (err < 0) |
@@ -912,7 +945,8 @@ int snd_scarlett_controls_create(struct usb_mixer_interface *mixer) | |||
912 | for (i = 0; i < info->matrix_in; i++) { | 945 | for (i = 0; i < info->matrix_in; i++) { |
913 | snprintf(mx, sizeof(mx), "Matrix %02d Input Playback Route", | 946 | snprintf(mx, sizeof(mx), "Matrix %02d Input Playback Route", |
914 | i+1); | 947 | i+1); |
915 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, 0x32, | 948 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, |
949 | scarlett_ctl_enum_resume, 0x32, | ||
916 | 0x06, i, USB_MIXER_S16, 1, mx, | 950 | 0x06, i, USB_MIXER_S16, 1, mx, |
917 | &info->opt_matrix, &elem); | 951 | &info->opt_matrix, &elem); |
918 | if (err < 0) | 952 | if (err < 0) |
@@ -921,7 +955,8 @@ int snd_scarlett_controls_create(struct usb_mixer_interface *mixer) | |||
921 | for (o = 0; o < info->matrix_out; o++) { | 955 | for (o = 0; o < info->matrix_out; o++) { |
922 | sprintf(mx, "Matrix %02d Mix %c Playback Volume", i+1, | 956 | sprintf(mx, "Matrix %02d Mix %c Playback Volume", i+1, |
923 | o+'A'); | 957 | o+'A'); |
924 | err = add_new_ctl(mixer, &usb_scarlett_ctl, 0x3c, 0x00, | 958 | err = add_new_ctl(mixer, &usb_scarlett_ctl, |
959 | scarlett_ctl_resume, 0x3c, 0x00, | ||
925 | (i << 3) + (o & 0x07), USB_MIXER_S16, | 960 | (i << 3) + (o & 0x07), USB_MIXER_S16, |
926 | 1, mx, NULL, &elem); | 961 | 1, mx, NULL, &elem); |
927 | if (err < 0) | 962 | if (err < 0) |
@@ -933,7 +968,8 @@ int snd_scarlett_controls_create(struct usb_mixer_interface *mixer) | |||
933 | for (i = 0; i < info->input_len; i++) { | 968 | for (i = 0; i < info->input_len; i++) { |
934 | snprintf(mx, sizeof(mx), "Input Source %02d Capture Route", | 969 | snprintf(mx, sizeof(mx), "Input Source %02d Capture Route", |
935 | i+1); | 970 | i+1); |
936 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, 0x34, | 971 | err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum, |
972 | scarlett_ctl_enum_resume, 0x34, | ||
937 | 0x00, i, USB_MIXER_S16, 1, mx, | 973 | 0x00, i, USB_MIXER_S16, 1, mx, |
938 | &info->opt_master, &elem); | 974 | &info->opt_master, &elem); |
939 | if (err < 0) | 975 | if (err < 0) |
@@ -941,14 +977,15 @@ int snd_scarlett_controls_create(struct usb_mixer_interface *mixer) | |||
941 | } | 977 | } |
942 | 978 | ||
943 | /* val_len == 1 needed here */ | 979 | /* val_len == 1 needed here */ |
944 | err = add_new_ctl(mixer, &usb_scarlett_ctl_enum, 0x28, 0x01, 0, | 980 | err = add_new_ctl(mixer, &usb_scarlett_ctl_enum, |
981 | scarlett_ctl_enum_resume, 0x28, 0x01, 0, | ||
945 | USB_MIXER_U8, 1, "Sample Clock Source", | 982 | USB_MIXER_U8, 1, "Sample Clock Source", |
946 | &opt_clock, &elem); | 983 | &opt_clock, &elem); |
947 | if (err < 0) | 984 | if (err < 0) |
948 | return err; | 985 | return err; |
949 | 986 | ||
950 | /* val_len == 1 and UAC2_CS_MEM */ | 987 | /* val_len == 1 and UAC2_CS_MEM */ |
951 | err = add_new_ctl(mixer, &usb_scarlett_ctl_sync, 0x3c, 0x00, 2, | 988 | err = add_new_ctl(mixer, &usb_scarlett_ctl_sync, NULL, 0x3c, 0x00, 2, |
952 | USB_MIXER_U8, 1, "Sample Clock Sync Status", | 989 | USB_MIXER_U8, 1, "Sample Clock Sync Status", |
953 | &opt_sync, &elem); | 990 | &opt_sync, &elem); |
954 | if (err < 0) | 991 | if (err < 0) |