diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-01-17 06:01:12 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-01-17 06:01:12 -0500 |
commit | d1a020050c6ce1a0794ff73582ccf47e4db536f7 (patch) | |
tree | 1b7250410f24703cd77c76156e758db9887137aa /sound/usb | |
parent | dc61b66fc724f89d357c43e2319d2cb7bec1e517 (diff) | |
parent | 641b4879444c0edb276fedca5c2fcbd2e5c70044 (diff) |
Merge branch 'topic/usb-mixer-cache' into next/usb-audio
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/caiaq/caiaq-device.c | 2 | ||||
-rw-r--r-- | sound/usb/caiaq/caiaq-device.h | 1 | ||||
-rw-r--r-- | sound/usb/caiaq/caiaq-midi.c | 32 | ||||
-rw-r--r-- | sound/usb/usbmixer.c | 122 | ||||
-rw-r--r-- | sound/usb/usx2y/usbusx2y.c | 2 |
5 files changed, 91 insertions, 68 deletions
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c index a62500e387a6..41c36b055f6b 100644 --- a/sound/usb/caiaq/caiaq-device.c +++ b/sound/usb/caiaq/caiaq-device.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | 44 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); |
45 | MODULE_DESCRIPTION("caiaq USB audio, version 1.3.9"); | 45 | MODULE_DESCRIPTION("caiaq USB audio, version 1.3.10"); |
46 | MODULE_LICENSE("GPL"); | 46 | MODULE_LICENSE("GPL"); |
47 | MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," | 47 | MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," |
48 | "{Native Instruments, RigKontrol3}," | 48 | "{Native Instruments, RigKontrol3}," |
diff --git a/sound/usb/caiaq/caiaq-device.h b/sound/usb/caiaq/caiaq-device.h index f9fbdbae269d..ab56e738c5fc 100644 --- a/sound/usb/caiaq/caiaq-device.h +++ b/sound/usb/caiaq/caiaq-device.h | |||
@@ -75,6 +75,7 @@ struct snd_usb_caiaqdev { | |||
75 | wait_queue_head_t ep1_wait_queue; | 75 | wait_queue_head_t ep1_wait_queue; |
76 | wait_queue_head_t prepare_wait_queue; | 76 | wait_queue_head_t prepare_wait_queue; |
77 | int spec_received, audio_parm_answer; | 77 | int spec_received, audio_parm_answer; |
78 | int midi_out_active; | ||
78 | 79 | ||
79 | char vendor_name[CAIAQ_USB_STR_LEN]; | 80 | char vendor_name[CAIAQ_USB_STR_LEN]; |
80 | char product_name[CAIAQ_USB_STR_LEN]; | 81 | char product_name[CAIAQ_USB_STR_LEN]; |
diff --git a/sound/usb/caiaq/caiaq-midi.c b/sound/usb/caiaq/caiaq-midi.c index 30b57f97c6e4..f19fd360c936 100644 --- a/sound/usb/caiaq/caiaq-midi.c +++ b/sound/usb/caiaq/caiaq-midi.c | |||
@@ -59,6 +59,11 @@ static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substrea | |||
59 | 59 | ||
60 | static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream) | 60 | static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream) |
61 | { | 61 | { |
62 | struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; | ||
63 | if (dev->midi_out_active) { | ||
64 | usb_kill_urb(&dev->midi_out_urb); | ||
65 | dev->midi_out_active = 0; | ||
66 | } | ||
62 | return 0; | 67 | return 0; |
63 | } | 68 | } |
64 | 69 | ||
@@ -69,7 +74,8 @@ static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev, | |||
69 | 74 | ||
70 | dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE; | 75 | dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE; |
71 | dev->midi_out_buf[1] = 0; /* port */ | 76 | dev->midi_out_buf[1] = 0; /* port */ |
72 | len = snd_rawmidi_transmit_peek(substream, dev->midi_out_buf+3, EP1_BUFSIZE-3); | 77 | len = snd_rawmidi_transmit(substream, dev->midi_out_buf + 3, |
78 | EP1_BUFSIZE - 3); | ||
73 | 79 | ||
74 | if (len <= 0) | 80 | if (len <= 0) |
75 | return; | 81 | return; |
@@ -79,24 +85,24 @@ static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev, | |||
79 | 85 | ||
80 | ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC); | 86 | ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC); |
81 | if (ret < 0) | 87 | if (ret < 0) |
82 | log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed, %d\n", | 88 | log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed," |
83 | substream, ret); | 89 | "ret=%d, len=%d\n", |
90 | substream, ret, len); | ||
91 | else | ||
92 | dev->midi_out_active = 1; | ||
84 | } | 93 | } |
85 | 94 | ||
86 | static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) | 95 | static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) |
87 | { | 96 | { |
88 | struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; | 97 | struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; |
89 | 98 | ||
90 | if (dev->midi_out_substream != NULL) | 99 | if (up) { |
91 | return; | 100 | dev->midi_out_substream = substream; |
92 | 101 | if (!dev->midi_out_active) | |
93 | if (!up) { | 102 | snd_usb_caiaq_midi_send(dev, substream); |
103 | } else { | ||
94 | dev->midi_out_substream = NULL; | 104 | dev->midi_out_substream = NULL; |
95 | return; | ||
96 | } | 105 | } |
97 | |||
98 | dev->midi_out_substream = substream; | ||
99 | snd_usb_caiaq_midi_send(dev, substream); | ||
100 | } | 106 | } |
101 | 107 | ||
102 | 108 | ||
@@ -161,16 +167,14 @@ int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device) | |||
161 | void snd_usb_caiaq_midi_output_done(struct urb* urb) | 167 | void snd_usb_caiaq_midi_output_done(struct urb* urb) |
162 | { | 168 | { |
163 | struct snd_usb_caiaqdev *dev = urb->context; | 169 | struct snd_usb_caiaqdev *dev = urb->context; |
164 | char *buf = urb->transfer_buffer; | ||
165 | 170 | ||
171 | dev->midi_out_active = 0; | ||
166 | if (urb->status != 0) | 172 | if (urb->status != 0) |
167 | return; | 173 | return; |
168 | 174 | ||
169 | if (!dev->midi_out_substream) | 175 | if (!dev->midi_out_substream) |
170 | return; | 176 | return; |
171 | 177 | ||
172 | snd_rawmidi_transmit_ack(dev->midi_out_substream, buf[2]); | ||
173 | dev->midi_out_substream = NULL; | ||
174 | snd_usb_caiaq_midi_send(dev, dev->midi_out_substream); | 178 | snd_usb_caiaq_midi_send(dev, dev->midi_out_substream); |
175 | } | 179 | } |
176 | 180 | ||
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 | |||
114 | struct usb_mixer_elem_info { | 116 | struct 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 */ |
380 | static inline int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int *value) | 382 | static 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 | ||
388 | static 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 | ||
416 | static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int value) | 442 | static 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 | } |
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index ca26c532e77e..11639bd72a51 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c | |||
@@ -238,7 +238,7 @@ static void i_usX2Y_In04Int(struct urb *urb) | |||
238 | send = 0; | 238 | send = 0; |
239 | for (j = 0; j < URBS_AsyncSeq && !err; ++j) | 239 | for (j = 0; j < URBS_AsyncSeq && !err; ++j) |
240 | if (0 == usX2Y->AS04.urb[j]->status) { | 240 | if (0 == usX2Y->AS04.urb[j]->status) { |
241 | struct us428_p4out *p4out = us428ctls->p4out + send; // FIXME if more then 1 p4out is new, 1 gets lost. | 241 | struct us428_p4out *p4out = us428ctls->p4out + send; // FIXME if more than 1 p4out is new, 1 gets lost. |
242 | usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->chip.dev, | 242 | usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->chip.dev, |
243 | usb_sndbulkpipe(usX2Y->chip.dev, 0x04), &p4out->val.vol, | 243 | usb_sndbulkpipe(usX2Y->chip.dev, 0x04), &p4out->val.vol, |
244 | p4out->type == eLT_Light ? sizeof(struct us428_lights) : 5, | 244 | p4out->type == eLT_Light ? sizeof(struct us428_lights) : 5, |