aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/usbmixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/usbmixer.c')
-rw-r--r--sound/usb/usbmixer.c122
1 files changed, 70 insertions, 52 deletions
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index bc8bd00047ad..330f2fbff2d1 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -111,6 +111,8 @@ struct mixer_build {
111 const struct usbmix_selector_map *selector_map; 111 const struct usbmix_selector_map *selector_map;
112}; 112};
113 113
114#define MAX_CHANNELS 10 /* max logical channels */
115
114struct usb_mixer_elem_info { 116struct usb_mixer_elem_info {
115 struct usb_mixer_interface *mixer; 117 struct usb_mixer_interface *mixer;
116 struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */ 118 struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */
@@ -121,6 +123,8 @@ struct usb_mixer_elem_info {
121 int channels; 123 int channels;
122 int val_type; 124 int val_type;
123 int min, max, res; 125 int min, max, res;
126 int cached;
127 int cache_val[MAX_CHANNELS];
124 u8 initialized; 128 u8 initialized;
125}; 129};
126 130
@@ -182,8 +186,6 @@ enum {
182 USB_PROC_DCR_RELEASE = 6, 186 USB_PROC_DCR_RELEASE = 6,
183}; 187};
184 188
185#define MAX_CHANNELS 10 /* max logical channels */
186
187 189
188/* 190/*
189 * manual mapping of mixer names 191 * manual mapping of mixer names
@@ -377,11 +379,35 @@ static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *
377} 379}
378 380
379/* channel = 0: master, 1 = first channel */ 381/* channel = 0: master, 1 = first channel */
380static inline int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int *value) 382static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval,
383 int channel, int *value)
381{ 384{
382 return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value); 385 return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value);
383} 386}
384 387
388static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
389 int channel, int index, int *value)
390{
391 int err;
392
393 if (cval->cached & (1 << channel)) {
394 *value = cval->cache_val[index];
395 return 0;
396 }
397 err = get_cur_mix_raw(cval, channel, value);
398 if (err < 0) {
399 if (!cval->mixer->ignore_ctl_error)
400 snd_printd(KERN_ERR "cannot get current value for "
401 "control %d ch %d: err = %d\n",
402 cval->control, channel, err);
403 return err;
404 }
405 cval->cached |= 1 << channel;
406 cval->cache_val[index] = *value;
407 return 0;
408}
409
410
385/* 411/*
386 * set a mixer value 412 * set a mixer value
387 */ 413 */
@@ -413,9 +439,17 @@ static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int v
413 return set_ctl_value(cval, SET_CUR, validx, value); 439 return set_ctl_value(cval, SET_CUR, validx, value);
414} 440}
415 441
416static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int value) 442static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
443 int index, int value)
417{ 444{
418 return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); 445 int err;
446 err = set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel,
447 value);
448 if (err < 0)
449 return err;
450 cval->cached |= 1 << channel;
451 cval->cache_val[index] = value;
452 return 0;
419} 453}
420 454
421/* 455/*
@@ -719,7 +753,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
719 if (cval->min + cval->res < cval->max) { 753 if (cval->min + cval->res < cval->max) {
720 int last_valid_res = cval->res; 754 int last_valid_res = cval->res;
721 int saved, test, check; 755 int saved, test, check;
722 get_cur_mix_value(cval, minchn, &saved); 756 get_cur_mix_raw(cval, minchn, &saved);
723 for (;;) { 757 for (;;) {
724 test = saved; 758 test = saved;
725 if (test < cval->max) 759 if (test < cval->max)
@@ -727,8 +761,8 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
727 else 761 else
728 test -= cval->res; 762 test -= cval->res;
729 if (test < cval->min || test > cval->max || 763 if (test < cval->min || test > cval->max ||
730 set_cur_mix_value(cval, minchn, test) || 764 set_cur_mix_value(cval, minchn, 0, test) ||
731 get_cur_mix_value(cval, minchn, &check)) { 765 get_cur_mix_raw(cval, minchn, &check)) {
732 cval->res = last_valid_res; 766 cval->res = last_valid_res;
733 break; 767 break;
734 } 768 }
@@ -736,7 +770,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
736 break; 770 break;
737 cval->res *= 2; 771 cval->res *= 2;
738 } 772 }
739 set_cur_mix_value(cval, minchn, saved); 773 set_cur_mix_value(cval, minchn, 0, saved);
740 } 774 }
741 775
742 cval->initialized = 1; 776 cval->initialized = 1;
@@ -776,35 +810,25 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e
776 struct usb_mixer_elem_info *cval = kcontrol->private_data; 810 struct usb_mixer_elem_info *cval = kcontrol->private_data;
777 int c, cnt, val, err; 811 int c, cnt, val, err;
778 812
813 ucontrol->value.integer.value[0] = cval->min;
779 if (cval->cmask) { 814 if (cval->cmask) {
780 cnt = 0; 815 cnt = 0;
781 for (c = 0; c < MAX_CHANNELS; c++) { 816 for (c = 0; c < MAX_CHANNELS; c++) {
782 if (cval->cmask & (1 << c)) { 817 if (!(cval->cmask & (1 << c)))
783 err = get_cur_mix_value(cval, c + 1, &val); 818 continue;
784 if (err < 0) { 819 err = get_cur_mix_value(cval, c + 1, cnt, &val);
785 if (cval->mixer->ignore_ctl_error) { 820 if (err < 0)
786 ucontrol->value.integer.value[0] = cval->min; 821 return cval->mixer->ignore_ctl_error ? 0 : err;
787 return 0; 822 val = get_relative_value(cval, val);
788 } 823 ucontrol->value.integer.value[cnt] = val;
789 snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", cval->control, c + 1, err); 824 cnt++;
790 return err;
791 }
792 val = get_relative_value(cval, val);
793 ucontrol->value.integer.value[cnt] = val;
794 cnt++;
795 }
796 } 825 }
826 return 0;
797 } else { 827 } else {
798 /* master channel */ 828 /* master channel */
799 err = get_cur_mix_value(cval, 0, &val); 829 err = get_cur_mix_value(cval, 0, 0, &val);
800 if (err < 0) { 830 if (err < 0)
801 if (cval->mixer->ignore_ctl_error) { 831 return cval->mixer->ignore_ctl_error ? 0 : err;
802 ucontrol->value.integer.value[0] = cval->min;
803 return 0;
804 }
805 snd_printd(KERN_ERR "cannot get current value for control %d master ch: err = %d\n", cval->control, err);
806 return err;
807 }
808 val = get_relative_value(cval, val); 832 val = get_relative_value(cval, val);
809 ucontrol->value.integer.value[0] = val; 833 ucontrol->value.integer.value[0] = val;
810 } 834 }
@@ -821,34 +845,28 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
821 if (cval->cmask) { 845 if (cval->cmask) {
822 cnt = 0; 846 cnt = 0;
823 for (c = 0; c < MAX_CHANNELS; c++) { 847 for (c = 0; c < MAX_CHANNELS; c++) {
824 if (cval->cmask & (1 << c)) { 848 if (!(cval->cmask & (1 << c)))
825 err = get_cur_mix_value(cval, c + 1, &oval); 849 continue;
826 if (err < 0) { 850 err = get_cur_mix_value(cval, c + 1, cnt, &oval);
827 if (cval->mixer->ignore_ctl_error) 851 if (err < 0)
828 return 0; 852 return cval->mixer->ignore_ctl_error ? 0 : err;
829 return err; 853 val = ucontrol->value.integer.value[cnt];
830 } 854 val = get_abs_value(cval, val);
831 val = ucontrol->value.integer.value[cnt]; 855 if (oval != val) {
832 val = get_abs_value(cval, val); 856 set_cur_mix_value(cval, c + 1, cnt, val);
833 if (oval != val) { 857 changed = 1;
834 set_cur_mix_value(cval, c + 1, val);
835 changed = 1;
836 }
837 get_cur_mix_value(cval, c + 1, &val);
838 cnt++;
839 } 858 }
859 cnt++;
840 } 860 }
841 } else { 861 } else {
842 /* master channel */ 862 /* master channel */
843 err = get_cur_mix_value(cval, 0, &oval); 863 err = get_cur_mix_value(cval, 0, 0, &oval);
844 if (err < 0 && cval->mixer->ignore_ctl_error)
845 return 0;
846 if (err < 0) 864 if (err < 0)
847 return err; 865 return cval->mixer->ignore_ctl_error ? 0 : err;
848 val = ucontrol->value.integer.value[0]; 866 val = ucontrol->value.integer.value[0];
849 val = get_abs_value(cval, val); 867 val = get_abs_value(cval, val);
850 if (val != oval) { 868 if (val != oval) {
851 set_cur_mix_value(cval, 0, val); 869 set_cur_mix_value(cval, 0, 0, val);
852 changed = 1; 870 changed = 1;
853 } 871 }
854 } 872 }