Commit 92c256110fa9566de639ef8948b4fb430aa495b3
Committed by
Takashi Iwai
1 parent
43b8e3bc4a
Exists in
master
and in
7 other branches
ALSA: usb-audio: add support for UAC2 pitch control
This request is again handled differently in comparison to UAC1. Signed-off-by: Daniel Mack <daniel@caiaq.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Showing 1 changed file with 30 additions and 7 deletions Inline Diff
sound/usb/pcm.c
1 | /* | 1 | /* |
2 | * This program is free software; you can redistribute it and/or modify | 2 | * This program is free software; you can redistribute it and/or modify |
3 | * it under the terms of the GNU General Public License as published by | 3 | * it under the terms of the GNU General Public License as published by |
4 | * the Free Software Foundation; either version 2 of the License, or | 4 | * the Free Software Foundation; either version 2 of the License, or |
5 | * (at your option) any later version. | 5 | * (at your option) any later version. |
6 | * | 6 | * |
7 | * This program is distributed in the hope that it will be useful, | 7 | * This program is distributed in the hope that it will be useful, |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | * GNU General Public License for more details. | 10 | * GNU General Public License for more details. |
11 | * | 11 | * |
12 | * You should have received a copy of the GNU General Public License | 12 | * You should have received a copy of the GNU General Public License |
13 | * along with this program; if not, write to the Free Software | 13 | * along with this program; if not, write to the Free Software |
14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/usb.h> | 19 | #include <linux/usb.h> |
20 | #include <linux/usb/audio.h> | 20 | #include <linux/usb/audio.h> |
21 | #include <linux/usb/audio-v2.h> | 21 | #include <linux/usb/audio-v2.h> |
22 | 22 | ||
23 | #include <sound/core.h> | 23 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
25 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
26 | 26 | ||
27 | #include "usbaudio.h" | 27 | #include "usbaudio.h" |
28 | #include "card.h" | 28 | #include "card.h" |
29 | #include "quirks.h" | 29 | #include "quirks.h" |
30 | #include "debug.h" | 30 | #include "debug.h" |
31 | #include "urb.h" | 31 | #include "urb.h" |
32 | #include "helper.h" | 32 | #include "helper.h" |
33 | #include "pcm.h" | 33 | #include "pcm.h" |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * return the current pcm pointer. just based on the hwptr_done value. | 36 | * return the current pcm pointer. just based on the hwptr_done value. |
37 | */ | 37 | */ |
38 | static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream) | 38 | static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream) |
39 | { | 39 | { |
40 | struct snd_usb_substream *subs; | 40 | struct snd_usb_substream *subs; |
41 | unsigned int hwptr_done; | 41 | unsigned int hwptr_done; |
42 | 42 | ||
43 | subs = (struct snd_usb_substream *)substream->runtime->private_data; | 43 | subs = (struct snd_usb_substream *)substream->runtime->private_data; |
44 | spin_lock(&subs->lock); | 44 | spin_lock(&subs->lock); |
45 | hwptr_done = subs->hwptr_done; | 45 | hwptr_done = subs->hwptr_done; |
46 | spin_unlock(&subs->lock); | 46 | spin_unlock(&subs->lock); |
47 | return hwptr_done / (substream->runtime->frame_bits >> 3); | 47 | return hwptr_done / (substream->runtime->frame_bits >> 3); |
48 | } | 48 | } |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * find a matching audio format | 51 | * find a matching audio format |
52 | */ | 52 | */ |
53 | static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned int format, | 53 | static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned int format, |
54 | unsigned int rate, unsigned int channels) | 54 | unsigned int rate, unsigned int channels) |
55 | { | 55 | { |
56 | struct list_head *p; | 56 | struct list_head *p; |
57 | struct audioformat *found = NULL; | 57 | struct audioformat *found = NULL; |
58 | int cur_attr = 0, attr; | 58 | int cur_attr = 0, attr; |
59 | 59 | ||
60 | list_for_each(p, &subs->fmt_list) { | 60 | list_for_each(p, &subs->fmt_list) { |
61 | struct audioformat *fp; | 61 | struct audioformat *fp; |
62 | fp = list_entry(p, struct audioformat, list); | 62 | fp = list_entry(p, struct audioformat, list); |
63 | if (!(fp->formats & (1uLL << format))) | 63 | if (!(fp->formats & (1uLL << format))) |
64 | continue; | 64 | continue; |
65 | if (fp->channels != channels) | 65 | if (fp->channels != channels) |
66 | continue; | 66 | continue; |
67 | if (rate < fp->rate_min || rate > fp->rate_max) | 67 | if (rate < fp->rate_min || rate > fp->rate_max) |
68 | continue; | 68 | continue; |
69 | if (! (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) { | 69 | if (! (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) { |
70 | unsigned int i; | 70 | unsigned int i; |
71 | for (i = 0; i < fp->nr_rates; i++) | 71 | for (i = 0; i < fp->nr_rates; i++) |
72 | if (fp->rate_table[i] == rate) | 72 | if (fp->rate_table[i] == rate) |
73 | break; | 73 | break; |
74 | if (i >= fp->nr_rates) | 74 | if (i >= fp->nr_rates) |
75 | continue; | 75 | continue; |
76 | } | 76 | } |
77 | attr = fp->ep_attr & USB_ENDPOINT_SYNCTYPE; | 77 | attr = fp->ep_attr & USB_ENDPOINT_SYNCTYPE; |
78 | if (! found) { | 78 | if (! found) { |
79 | found = fp; | 79 | found = fp; |
80 | cur_attr = attr; | 80 | cur_attr = attr; |
81 | continue; | 81 | continue; |
82 | } | 82 | } |
83 | /* avoid async out and adaptive in if the other method | 83 | /* avoid async out and adaptive in if the other method |
84 | * supports the same format. | 84 | * supports the same format. |
85 | * this is a workaround for the case like | 85 | * this is a workaround for the case like |
86 | * M-audio audiophile USB. | 86 | * M-audio audiophile USB. |
87 | */ | 87 | */ |
88 | if (attr != cur_attr) { | 88 | if (attr != cur_attr) { |
89 | if ((attr == USB_ENDPOINT_SYNC_ASYNC && | 89 | if ((attr == USB_ENDPOINT_SYNC_ASYNC && |
90 | subs->direction == SNDRV_PCM_STREAM_PLAYBACK) || | 90 | subs->direction == SNDRV_PCM_STREAM_PLAYBACK) || |
91 | (attr == USB_ENDPOINT_SYNC_ADAPTIVE && | 91 | (attr == USB_ENDPOINT_SYNC_ADAPTIVE && |
92 | subs->direction == SNDRV_PCM_STREAM_CAPTURE)) | 92 | subs->direction == SNDRV_PCM_STREAM_CAPTURE)) |
93 | continue; | 93 | continue; |
94 | if ((cur_attr == USB_ENDPOINT_SYNC_ASYNC && | 94 | if ((cur_attr == USB_ENDPOINT_SYNC_ASYNC && |
95 | subs->direction == SNDRV_PCM_STREAM_PLAYBACK) || | 95 | subs->direction == SNDRV_PCM_STREAM_PLAYBACK) || |
96 | (cur_attr == USB_ENDPOINT_SYNC_ADAPTIVE && | 96 | (cur_attr == USB_ENDPOINT_SYNC_ADAPTIVE && |
97 | subs->direction == SNDRV_PCM_STREAM_CAPTURE)) { | 97 | subs->direction == SNDRV_PCM_STREAM_CAPTURE)) { |
98 | found = fp; | 98 | found = fp; |
99 | cur_attr = attr; | 99 | cur_attr = attr; |
100 | continue; | 100 | continue; |
101 | } | 101 | } |
102 | } | 102 | } |
103 | /* find the format with the largest max. packet size */ | 103 | /* find the format with the largest max. packet size */ |
104 | if (fp->maxpacksize > found->maxpacksize) { | 104 | if (fp->maxpacksize > found->maxpacksize) { |
105 | found = fp; | 105 | found = fp; |
106 | cur_attr = attr; | 106 | cur_attr = attr; |
107 | } | 107 | } |
108 | } | 108 | } |
109 | return found; | 109 | return found; |
110 | } | 110 | } |
111 | 111 | ||
112 | static int init_pitch_v1(struct snd_usb_audio *chip, int iface, | 112 | static int init_pitch_v1(struct snd_usb_audio *chip, int iface, |
113 | struct usb_host_interface *alts, | 113 | struct usb_host_interface *alts, |
114 | struct audioformat *fmt) | 114 | struct audioformat *fmt) |
115 | { | 115 | { |
116 | struct usb_device *dev = chip->dev; | 116 | struct usb_device *dev = chip->dev; |
117 | unsigned int ep; | 117 | unsigned int ep; |
118 | unsigned char data[1]; | 118 | unsigned char data[1]; |
119 | int err; | 119 | int err; |
120 | 120 | ||
121 | ep = get_endpoint(alts, 0)->bEndpointAddress; | 121 | ep = get_endpoint(alts, 0)->bEndpointAddress; |
122 | 122 | ||
123 | /* if endpoint doesn't have pitch control, bail out */ | ||
124 | if (!(fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL)) | ||
125 | return 0; | ||
126 | |||
127 | data[0] = 1; | 123 | data[0] = 1; |
128 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, | 124 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, |
129 | USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, | 125 | USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, |
130 | UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep, | 126 | UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep, |
131 | data, sizeof(data), 1000)) < 0) { | 127 | data, sizeof(data), 1000)) < 0) { |
132 | snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n", | 128 | snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n", |
133 | dev->devnum, iface, ep); | 129 | dev->devnum, iface, ep); |
134 | return err; | 130 | return err; |
135 | } | 131 | } |
136 | 132 | ||
137 | return 0; | 133 | return 0; |
138 | } | 134 | } |
139 | 135 | ||
136 | static int init_pitch_v2(struct snd_usb_audio *chip, int iface, | ||
137 | struct usb_host_interface *alts, | ||
138 | struct audioformat *fmt) | ||
139 | { | ||
140 | struct usb_device *dev = chip->dev; | ||
141 | unsigned char data[1]; | ||
142 | unsigned int ep; | ||
143 | int err; | ||
144 | |||
145 | ep = get_endpoint(alts, 0)->bEndpointAddress; | ||
146 | |||
147 | data[0] = 1; | ||
148 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR, | ||
149 | USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT, | ||
150 | UAC2_EP_CS_PITCH << 8, 0, | ||
151 | data, sizeof(data), 1000)) < 0) { | ||
152 | snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH (v2)\n", | ||
153 | dev->devnum, iface, fmt->altsetting); | ||
154 | return err; | ||
155 | } | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
140 | /* | 160 | /* |
141 | * initialize the picth control and sample rate | 161 | * initialize the pitch control and sample rate |
142 | */ | 162 | */ |
143 | int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, | 163 | int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, |
144 | struct usb_host_interface *alts, | 164 | struct usb_host_interface *alts, |
145 | struct audioformat *fmt) | 165 | struct audioformat *fmt) |
146 | { | 166 | { |
147 | struct usb_interface_descriptor *altsd = get_iface_desc(alts); | 167 | struct usb_interface_descriptor *altsd = get_iface_desc(alts); |
148 | 168 | ||
169 | /* if endpoint doesn't have pitch control, bail out */ | ||
170 | if (!(fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL)) | ||
171 | return 0; | ||
172 | |||
149 | switch (altsd->bInterfaceProtocol) { | 173 | switch (altsd->bInterfaceProtocol) { |
150 | case UAC_VERSION_1: | 174 | case UAC_VERSION_1: |
151 | return init_pitch_v1(chip, iface, alts, fmt); | 175 | return init_pitch_v1(chip, iface, alts, fmt); |
152 | 176 | ||
153 | case UAC_VERSION_2: | 177 | case UAC_VERSION_2: |
154 | /* not implemented yet */ | 178 | return init_pitch_v2(chip, iface, alts, fmt); |
155 | return 0; | ||
156 | } | 179 | } |
157 | 180 | ||
158 | return -EINVAL; | 181 | return -EINVAL; |
159 | } | 182 | } |
160 | 183 | ||
161 | static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, | 184 | static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, |
162 | struct usb_host_interface *alts, | 185 | struct usb_host_interface *alts, |
163 | struct audioformat *fmt, int rate) | 186 | struct audioformat *fmt, int rate) |
164 | { | 187 | { |
165 | struct usb_device *dev = chip->dev; | 188 | struct usb_device *dev = chip->dev; |
166 | unsigned int ep; | 189 | unsigned int ep; |
167 | unsigned char data[3]; | 190 | unsigned char data[3]; |
168 | int err, crate; | 191 | int err, crate; |
169 | 192 | ||
170 | ep = get_endpoint(alts, 0)->bEndpointAddress; | 193 | ep = get_endpoint(alts, 0)->bEndpointAddress; |
171 | /* if endpoint doesn't have sampling rate control, bail out */ | 194 | /* if endpoint doesn't have sampling rate control, bail out */ |
172 | if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) { | 195 | if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) { |
173 | snd_printk(KERN_WARNING "%d:%d:%d: endpoint lacks sample rate attribute bit, cannot set.\n", | 196 | snd_printk(KERN_WARNING "%d:%d:%d: endpoint lacks sample rate attribute bit, cannot set.\n", |
174 | dev->devnum, iface, fmt->altsetting); | 197 | dev->devnum, iface, fmt->altsetting); |
175 | return 0; | 198 | return 0; |
176 | } | 199 | } |
177 | 200 | ||
178 | data[0] = rate; | 201 | data[0] = rate; |
179 | data[1] = rate >> 8; | 202 | data[1] = rate >> 8; |
180 | data[2] = rate >> 16; | 203 | data[2] = rate >> 16; |
181 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, | 204 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, |
182 | USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, | 205 | USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, |
183 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, | 206 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, |
184 | data, sizeof(data), 1000)) < 0) { | 207 | data, sizeof(data), 1000)) < 0) { |
185 | snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n", | 208 | snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n", |
186 | dev->devnum, iface, fmt->altsetting, rate, ep); | 209 | dev->devnum, iface, fmt->altsetting, rate, ep); |
187 | return err; | 210 | return err; |
188 | } | 211 | } |
189 | if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR, | 212 | if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR, |
190 | USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN, | 213 | USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN, |
191 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, | 214 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, |
192 | data, sizeof(data), 1000)) < 0) { | 215 | data, sizeof(data), 1000)) < 0) { |
193 | snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n", | 216 | snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n", |
194 | dev->devnum, iface, fmt->altsetting, ep); | 217 | dev->devnum, iface, fmt->altsetting, ep); |
195 | return 0; /* some devices don't support reading */ | 218 | return 0; /* some devices don't support reading */ |
196 | } | 219 | } |
197 | crate = data[0] | (data[1] << 8) | (data[2] << 16); | 220 | crate = data[0] | (data[1] << 8) | (data[2] << 16); |
198 | if (crate != rate) { | 221 | if (crate != rate) { |
199 | snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate); | 222 | snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate); |
200 | // runtime->rate = crate; | 223 | // runtime->rate = crate; |
201 | } | 224 | } |
202 | 225 | ||
203 | return 0; | 226 | return 0; |
204 | } | 227 | } |
205 | 228 | ||
206 | static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface, | 229 | static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface, |
207 | struct usb_host_interface *alts, | 230 | struct usb_host_interface *alts, |
208 | struct audioformat *fmt, int rate) | 231 | struct audioformat *fmt, int rate) |
209 | { | 232 | { |
210 | struct usb_device *dev = chip->dev; | 233 | struct usb_device *dev = chip->dev; |
211 | unsigned char data[4]; | 234 | unsigned char data[4]; |
212 | int err, crate; | 235 | int err, crate; |
213 | 236 | ||
214 | data[0] = rate; | 237 | data[0] = rate; |
215 | data[1] = rate >> 8; | 238 | data[1] = rate >> 8; |
216 | data[2] = rate >> 16; | 239 | data[2] = rate >> 16; |
217 | data[3] = rate >> 24; | 240 | data[3] = rate >> 24; |
218 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR, | 241 | if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR, |
219 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | 242 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, |
220 | UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8, | 243 | UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8, |
221 | data, sizeof(data), 1000)) < 0) { | 244 | data, sizeof(data), 1000)) < 0) { |
222 | snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n", | 245 | snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n", |
223 | dev->devnum, iface, fmt->altsetting, rate); | 246 | dev->devnum, iface, fmt->altsetting, rate); |
224 | return err; | 247 | return err; |
225 | } | 248 | } |
226 | if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, | 249 | if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, |
227 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | 250 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, |
228 | UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8, | 251 | UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8, |
229 | data, sizeof(data), 1000)) < 0) { | 252 | data, sizeof(data), 1000)) < 0) { |
230 | snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n", | 253 | snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n", |
231 | dev->devnum, iface, fmt->altsetting); | 254 | dev->devnum, iface, fmt->altsetting); |
232 | return err; | 255 | return err; |
233 | } | 256 | } |
234 | crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); | 257 | crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); |
235 | if (crate != rate) | 258 | if (crate != rate) |
236 | snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate); | 259 | snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate); |
237 | 260 | ||
238 | return 0; | 261 | return 0; |
239 | } | 262 | } |
240 | 263 | ||
241 | int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, | 264 | int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, |
242 | struct usb_host_interface *alts, | 265 | struct usb_host_interface *alts, |
243 | struct audioformat *fmt, int rate) | 266 | struct audioformat *fmt, int rate) |
244 | { | 267 | { |
245 | struct usb_interface_descriptor *altsd = get_iface_desc(alts); | 268 | struct usb_interface_descriptor *altsd = get_iface_desc(alts); |
246 | 269 | ||
247 | switch (altsd->bInterfaceProtocol) { | 270 | switch (altsd->bInterfaceProtocol) { |
248 | case UAC_VERSION_1: | 271 | case UAC_VERSION_1: |
249 | return set_sample_rate_v1(chip, iface, alts, fmt, rate); | 272 | return set_sample_rate_v1(chip, iface, alts, fmt, rate); |
250 | 273 | ||
251 | case UAC_VERSION_2: | 274 | case UAC_VERSION_2: |
252 | return set_sample_rate_v2(chip, iface, alts, fmt, rate); | 275 | return set_sample_rate_v2(chip, iface, alts, fmt, rate); |
253 | } | 276 | } |
254 | 277 | ||
255 | return -EINVAL; | 278 | return -EINVAL; |
256 | } | 279 | } |
257 | 280 | ||
258 | /* | 281 | /* |
259 | * find a matching format and set up the interface | 282 | * find a matching format and set up the interface |
260 | */ | 283 | */ |
261 | static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | 284 | static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) |
262 | { | 285 | { |
263 | struct usb_device *dev = subs->dev; | 286 | struct usb_device *dev = subs->dev; |
264 | struct usb_host_interface *alts; | 287 | struct usb_host_interface *alts; |
265 | struct usb_interface_descriptor *altsd; | 288 | struct usb_interface_descriptor *altsd; |
266 | struct usb_interface *iface; | 289 | struct usb_interface *iface; |
267 | unsigned int ep, attr; | 290 | unsigned int ep, attr; |
268 | int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; | 291 | int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; |
269 | int err; | 292 | int err; |
270 | 293 | ||
271 | iface = usb_ifnum_to_if(dev, fmt->iface); | 294 | iface = usb_ifnum_to_if(dev, fmt->iface); |
272 | if (WARN_ON(!iface)) | 295 | if (WARN_ON(!iface)) |
273 | return -EINVAL; | 296 | return -EINVAL; |
274 | alts = &iface->altsetting[fmt->altset_idx]; | 297 | alts = &iface->altsetting[fmt->altset_idx]; |
275 | altsd = get_iface_desc(alts); | 298 | altsd = get_iface_desc(alts); |
276 | if (WARN_ON(altsd->bAlternateSetting != fmt->altsetting)) | 299 | if (WARN_ON(altsd->bAlternateSetting != fmt->altsetting)) |
277 | return -EINVAL; | 300 | return -EINVAL; |
278 | 301 | ||
279 | if (fmt == subs->cur_audiofmt) | 302 | if (fmt == subs->cur_audiofmt) |
280 | return 0; | 303 | return 0; |
281 | 304 | ||
282 | /* close the old interface */ | 305 | /* close the old interface */ |
283 | if (subs->interface >= 0 && subs->interface != fmt->iface) { | 306 | if (subs->interface >= 0 && subs->interface != fmt->iface) { |
284 | if (usb_set_interface(subs->dev, subs->interface, 0) < 0) { | 307 | if (usb_set_interface(subs->dev, subs->interface, 0) < 0) { |
285 | snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed\n", | 308 | snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed\n", |
286 | dev->devnum, fmt->iface, fmt->altsetting); | 309 | dev->devnum, fmt->iface, fmt->altsetting); |
287 | return -EIO; | 310 | return -EIO; |
288 | } | 311 | } |
289 | subs->interface = -1; | 312 | subs->interface = -1; |
290 | subs->altset_idx = 0; | 313 | subs->altset_idx = 0; |
291 | } | 314 | } |
292 | 315 | ||
293 | /* set interface */ | 316 | /* set interface */ |
294 | if (subs->interface != fmt->iface || subs->altset_idx != fmt->altset_idx) { | 317 | if (subs->interface != fmt->iface || subs->altset_idx != fmt->altset_idx) { |
295 | if (usb_set_interface(dev, fmt->iface, fmt->altsetting) < 0) { | 318 | if (usb_set_interface(dev, fmt->iface, fmt->altsetting) < 0) { |
296 | snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed\n", | 319 | snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed\n", |
297 | dev->devnum, fmt->iface, fmt->altsetting); | 320 | dev->devnum, fmt->iface, fmt->altsetting); |
298 | return -EIO; | 321 | return -EIO; |
299 | } | 322 | } |
300 | snd_printdd(KERN_INFO "setting usb interface %d:%d\n", fmt->iface, fmt->altsetting); | 323 | snd_printdd(KERN_INFO "setting usb interface %d:%d\n", fmt->iface, fmt->altsetting); |
301 | subs->interface = fmt->iface; | 324 | subs->interface = fmt->iface; |
302 | subs->altset_idx = fmt->altset_idx; | 325 | subs->altset_idx = fmt->altset_idx; |
303 | } | 326 | } |
304 | 327 | ||
305 | /* create a data pipe */ | 328 | /* create a data pipe */ |
306 | ep = fmt->endpoint & USB_ENDPOINT_NUMBER_MASK; | 329 | ep = fmt->endpoint & USB_ENDPOINT_NUMBER_MASK; |
307 | if (is_playback) | 330 | if (is_playback) |
308 | subs->datapipe = usb_sndisocpipe(dev, ep); | 331 | subs->datapipe = usb_sndisocpipe(dev, ep); |
309 | else | 332 | else |
310 | subs->datapipe = usb_rcvisocpipe(dev, ep); | 333 | subs->datapipe = usb_rcvisocpipe(dev, ep); |
311 | subs->datainterval = fmt->datainterval; | 334 | subs->datainterval = fmt->datainterval; |
312 | subs->syncpipe = subs->syncinterval = 0; | 335 | subs->syncpipe = subs->syncinterval = 0; |
313 | subs->maxpacksize = fmt->maxpacksize; | 336 | subs->maxpacksize = fmt->maxpacksize; |
314 | subs->fill_max = 0; | 337 | subs->fill_max = 0; |
315 | 338 | ||
316 | /* we need a sync pipe in async OUT or adaptive IN mode */ | 339 | /* we need a sync pipe in async OUT or adaptive IN mode */ |
317 | /* check the number of EP, since some devices have broken | 340 | /* check the number of EP, since some devices have broken |
318 | * descriptors which fool us. if it has only one EP, | 341 | * descriptors which fool us. if it has only one EP, |
319 | * assume it as adaptive-out or sync-in. | 342 | * assume it as adaptive-out or sync-in. |
320 | */ | 343 | */ |
321 | attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE; | 344 | attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE; |
322 | if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) || | 345 | if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) || |
323 | (! is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) && | 346 | (! is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) && |
324 | altsd->bNumEndpoints >= 2) { | 347 | altsd->bNumEndpoints >= 2) { |
325 | /* check sync-pipe endpoint */ | 348 | /* check sync-pipe endpoint */ |
326 | /* ... and check descriptor size before accessing bSynchAddress | 349 | /* ... and check descriptor size before accessing bSynchAddress |
327 | because there is a version of the SB Audigy 2 NX firmware lacking | 350 | because there is a version of the SB Audigy 2 NX firmware lacking |
328 | the audio fields in the endpoint descriptors */ | 351 | the audio fields in the endpoint descriptors */ |
329 | if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != 0x01 || | 352 | if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != 0x01 || |
330 | (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && | 353 | (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && |
331 | get_endpoint(alts, 1)->bSynchAddress != 0)) { | 354 | get_endpoint(alts, 1)->bSynchAddress != 0)) { |
332 | snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n", | 355 | snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n", |
333 | dev->devnum, fmt->iface, fmt->altsetting); | 356 | dev->devnum, fmt->iface, fmt->altsetting); |
334 | return -EINVAL; | 357 | return -EINVAL; |
335 | } | 358 | } |
336 | ep = get_endpoint(alts, 1)->bEndpointAddress; | 359 | ep = get_endpoint(alts, 1)->bEndpointAddress; |
337 | if (get_endpoint(alts, 0)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && | 360 | if (get_endpoint(alts, 0)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && |
338 | (( is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) || | 361 | (( is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) || |
339 | (!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)))) { | 362 | (!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)))) { |
340 | snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n", | 363 | snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n", |
341 | dev->devnum, fmt->iface, fmt->altsetting); | 364 | dev->devnum, fmt->iface, fmt->altsetting); |
342 | return -EINVAL; | 365 | return -EINVAL; |
343 | } | 366 | } |
344 | ep &= USB_ENDPOINT_NUMBER_MASK; | 367 | ep &= USB_ENDPOINT_NUMBER_MASK; |
345 | if (is_playback) | 368 | if (is_playback) |
346 | subs->syncpipe = usb_rcvisocpipe(dev, ep); | 369 | subs->syncpipe = usb_rcvisocpipe(dev, ep); |
347 | else | 370 | else |
348 | subs->syncpipe = usb_sndisocpipe(dev, ep); | 371 | subs->syncpipe = usb_sndisocpipe(dev, ep); |
349 | if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && | 372 | if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && |
350 | get_endpoint(alts, 1)->bRefresh >= 1 && | 373 | get_endpoint(alts, 1)->bRefresh >= 1 && |
351 | get_endpoint(alts, 1)->bRefresh <= 9) | 374 | get_endpoint(alts, 1)->bRefresh <= 9) |
352 | subs->syncinterval = get_endpoint(alts, 1)->bRefresh; | 375 | subs->syncinterval = get_endpoint(alts, 1)->bRefresh; |
353 | else if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) | 376 | else if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) |
354 | subs->syncinterval = 1; | 377 | subs->syncinterval = 1; |
355 | else if (get_endpoint(alts, 1)->bInterval >= 1 && | 378 | else if (get_endpoint(alts, 1)->bInterval >= 1 && |
356 | get_endpoint(alts, 1)->bInterval <= 16) | 379 | get_endpoint(alts, 1)->bInterval <= 16) |
357 | subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1; | 380 | subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1; |
358 | else | 381 | else |
359 | subs->syncinterval = 3; | 382 | subs->syncinterval = 3; |
360 | } | 383 | } |
361 | 384 | ||
362 | /* always fill max packet size */ | 385 | /* always fill max packet size */ |
363 | if (fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX) | 386 | if (fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX) |
364 | subs->fill_max = 1; | 387 | subs->fill_max = 1; |
365 | 388 | ||
366 | if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0) | 389 | if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0) |
367 | return err; | 390 | return err; |
368 | 391 | ||
369 | subs->cur_audiofmt = fmt; | 392 | subs->cur_audiofmt = fmt; |
370 | 393 | ||
371 | snd_usb_set_format_quirk(subs, fmt); | 394 | snd_usb_set_format_quirk(subs, fmt); |
372 | 395 | ||
373 | #if 0 | 396 | #if 0 |
374 | printk(KERN_DEBUG | 397 | printk(KERN_DEBUG |
375 | "setting done: format = %d, rate = %d..%d, channels = %d\n", | 398 | "setting done: format = %d, rate = %d..%d, channels = %d\n", |
376 | fmt->format, fmt->rate_min, fmt->rate_max, fmt->channels); | 399 | fmt->format, fmt->rate_min, fmt->rate_max, fmt->channels); |
377 | printk(KERN_DEBUG | 400 | printk(KERN_DEBUG |
378 | " datapipe = 0x%0x, syncpipe = 0x%0x\n", | 401 | " datapipe = 0x%0x, syncpipe = 0x%0x\n", |
379 | subs->datapipe, subs->syncpipe); | 402 | subs->datapipe, subs->syncpipe); |
380 | #endif | 403 | #endif |
381 | 404 | ||
382 | return 0; | 405 | return 0; |
383 | } | 406 | } |
384 | 407 | ||
385 | /* | 408 | /* |
386 | * hw_params callback | 409 | * hw_params callback |
387 | * | 410 | * |
388 | * allocate a buffer and set the given audio format. | 411 | * allocate a buffer and set the given audio format. |
389 | * | 412 | * |
390 | * so far we use a physically linear buffer although packetize transfer | 413 | * so far we use a physically linear buffer although packetize transfer |
391 | * doesn't need a continuous area. | 414 | * doesn't need a continuous area. |
392 | * if sg buffer is supported on the later version of alsa, we'll follow | 415 | * if sg buffer is supported on the later version of alsa, we'll follow |
393 | * that. | 416 | * that. |
394 | */ | 417 | */ |
395 | static int snd_usb_hw_params(struct snd_pcm_substream *substream, | 418 | static int snd_usb_hw_params(struct snd_pcm_substream *substream, |
396 | struct snd_pcm_hw_params *hw_params) | 419 | struct snd_pcm_hw_params *hw_params) |
397 | { | 420 | { |
398 | struct snd_usb_substream *subs = substream->runtime->private_data; | 421 | struct snd_usb_substream *subs = substream->runtime->private_data; |
399 | struct audioformat *fmt; | 422 | struct audioformat *fmt; |
400 | unsigned int channels, rate, format; | 423 | unsigned int channels, rate, format; |
401 | int ret, changed; | 424 | int ret, changed; |
402 | 425 | ||
403 | ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, | 426 | ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, |
404 | params_buffer_bytes(hw_params)); | 427 | params_buffer_bytes(hw_params)); |
405 | if (ret < 0) | 428 | if (ret < 0) |
406 | return ret; | 429 | return ret; |
407 | 430 | ||
408 | format = params_format(hw_params); | 431 | format = params_format(hw_params); |
409 | rate = params_rate(hw_params); | 432 | rate = params_rate(hw_params); |
410 | channels = params_channels(hw_params); | 433 | channels = params_channels(hw_params); |
411 | fmt = find_format(subs, format, rate, channels); | 434 | fmt = find_format(subs, format, rate, channels); |
412 | if (!fmt) { | 435 | if (!fmt) { |
413 | snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n", | 436 | snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n", |
414 | format, rate, channels); | 437 | format, rate, channels); |
415 | return -EINVAL; | 438 | return -EINVAL; |
416 | } | 439 | } |
417 | 440 | ||
418 | changed = subs->cur_audiofmt != fmt || | 441 | changed = subs->cur_audiofmt != fmt || |
419 | subs->period_bytes != params_period_bytes(hw_params) || | 442 | subs->period_bytes != params_period_bytes(hw_params) || |
420 | subs->cur_rate != rate; | 443 | subs->cur_rate != rate; |
421 | if ((ret = set_format(subs, fmt)) < 0) | 444 | if ((ret = set_format(subs, fmt)) < 0) |
422 | return ret; | 445 | return ret; |
423 | 446 | ||
424 | if (subs->cur_rate != rate) { | 447 | if (subs->cur_rate != rate) { |
425 | struct usb_host_interface *alts; | 448 | struct usb_host_interface *alts; |
426 | struct usb_interface *iface; | 449 | struct usb_interface *iface; |
427 | iface = usb_ifnum_to_if(subs->dev, fmt->iface); | 450 | iface = usb_ifnum_to_if(subs->dev, fmt->iface); |
428 | alts = &iface->altsetting[fmt->altset_idx]; | 451 | alts = &iface->altsetting[fmt->altset_idx]; |
429 | ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate); | 452 | ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate); |
430 | if (ret < 0) | 453 | if (ret < 0) |
431 | return ret; | 454 | return ret; |
432 | subs->cur_rate = rate; | 455 | subs->cur_rate = rate; |
433 | } | 456 | } |
434 | 457 | ||
435 | if (changed) { | 458 | if (changed) { |
436 | /* format changed */ | 459 | /* format changed */ |
437 | snd_usb_release_substream_urbs(subs, 0); | 460 | snd_usb_release_substream_urbs(subs, 0); |
438 | /* influenced: period_bytes, channels, rate, format, */ | 461 | /* influenced: period_bytes, channels, rate, format, */ |
439 | ret = snd_usb_init_substream_urbs(subs, params_period_bytes(hw_params), | 462 | ret = snd_usb_init_substream_urbs(subs, params_period_bytes(hw_params), |
440 | params_rate(hw_params), | 463 | params_rate(hw_params), |
441 | snd_pcm_format_physical_width(params_format(hw_params)) * | 464 | snd_pcm_format_physical_width(params_format(hw_params)) * |
442 | params_channels(hw_params)); | 465 | params_channels(hw_params)); |
443 | } | 466 | } |
444 | 467 | ||
445 | return ret; | 468 | return ret; |
446 | } | 469 | } |
447 | 470 | ||
448 | /* | 471 | /* |
449 | * hw_free callback | 472 | * hw_free callback |
450 | * | 473 | * |
451 | * reset the audio format and release the buffer | 474 | * reset the audio format and release the buffer |
452 | */ | 475 | */ |
453 | static int snd_usb_hw_free(struct snd_pcm_substream *substream) | 476 | static int snd_usb_hw_free(struct snd_pcm_substream *substream) |
454 | { | 477 | { |
455 | struct snd_usb_substream *subs = substream->runtime->private_data; | 478 | struct snd_usb_substream *subs = substream->runtime->private_data; |
456 | 479 | ||
457 | subs->cur_audiofmt = NULL; | 480 | subs->cur_audiofmt = NULL; |
458 | subs->cur_rate = 0; | 481 | subs->cur_rate = 0; |
459 | subs->period_bytes = 0; | 482 | subs->period_bytes = 0; |
460 | if (!subs->stream->chip->shutdown) | 483 | if (!subs->stream->chip->shutdown) |
461 | snd_usb_release_substream_urbs(subs, 0); | 484 | snd_usb_release_substream_urbs(subs, 0); |
462 | return snd_pcm_lib_free_vmalloc_buffer(substream); | 485 | return snd_pcm_lib_free_vmalloc_buffer(substream); |
463 | } | 486 | } |
464 | 487 | ||
465 | /* | 488 | /* |
466 | * prepare callback | 489 | * prepare callback |
467 | * | 490 | * |
468 | * only a few subtle things... | 491 | * only a few subtle things... |
469 | */ | 492 | */ |
470 | static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) | 493 | static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) |
471 | { | 494 | { |
472 | struct snd_pcm_runtime *runtime = substream->runtime; | 495 | struct snd_pcm_runtime *runtime = substream->runtime; |
473 | struct snd_usb_substream *subs = runtime->private_data; | 496 | struct snd_usb_substream *subs = runtime->private_data; |
474 | 497 | ||
475 | if (! subs->cur_audiofmt) { | 498 | if (! subs->cur_audiofmt) { |
476 | snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); | 499 | snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); |
477 | return -ENXIO; | 500 | return -ENXIO; |
478 | } | 501 | } |
479 | 502 | ||
480 | /* some unit conversions in runtime */ | 503 | /* some unit conversions in runtime */ |
481 | subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize); | 504 | subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize); |
482 | subs->curframesize = bytes_to_frames(runtime, subs->curpacksize); | 505 | subs->curframesize = bytes_to_frames(runtime, subs->curpacksize); |
483 | 506 | ||
484 | /* reset the pointer */ | 507 | /* reset the pointer */ |
485 | subs->hwptr_done = 0; | 508 | subs->hwptr_done = 0; |
486 | subs->transfer_done = 0; | 509 | subs->transfer_done = 0; |
487 | subs->phase = 0; | 510 | subs->phase = 0; |
488 | runtime->delay = 0; | 511 | runtime->delay = 0; |
489 | 512 | ||
490 | return snd_usb_substream_prepare(subs, runtime); | 513 | return snd_usb_substream_prepare(subs, runtime); |
491 | } | 514 | } |
492 | 515 | ||
493 | static struct snd_pcm_hardware snd_usb_hardware = | 516 | static struct snd_pcm_hardware snd_usb_hardware = |
494 | { | 517 | { |
495 | .info = SNDRV_PCM_INFO_MMAP | | 518 | .info = SNDRV_PCM_INFO_MMAP | |
496 | SNDRV_PCM_INFO_MMAP_VALID | | 519 | SNDRV_PCM_INFO_MMAP_VALID | |
497 | SNDRV_PCM_INFO_BATCH | | 520 | SNDRV_PCM_INFO_BATCH | |
498 | SNDRV_PCM_INFO_INTERLEAVED | | 521 | SNDRV_PCM_INFO_INTERLEAVED | |
499 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 522 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
500 | SNDRV_PCM_INFO_PAUSE, | 523 | SNDRV_PCM_INFO_PAUSE, |
501 | .buffer_bytes_max = 1024 * 1024, | 524 | .buffer_bytes_max = 1024 * 1024, |
502 | .period_bytes_min = 64, | 525 | .period_bytes_min = 64, |
503 | .period_bytes_max = 512 * 1024, | 526 | .period_bytes_max = 512 * 1024, |
504 | .periods_min = 2, | 527 | .periods_min = 2, |
505 | .periods_max = 1024, | 528 | .periods_max = 1024, |
506 | }; | 529 | }; |
507 | 530 | ||
508 | static int hw_check_valid_format(struct snd_usb_substream *subs, | 531 | static int hw_check_valid_format(struct snd_usb_substream *subs, |
509 | struct snd_pcm_hw_params *params, | 532 | struct snd_pcm_hw_params *params, |
510 | struct audioformat *fp) | 533 | struct audioformat *fp) |
511 | { | 534 | { |
512 | struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | 535 | struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); |
513 | struct snd_interval *ct = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | 536 | struct snd_interval *ct = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); |
514 | struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | 537 | struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); |
515 | struct snd_interval *pt = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME); | 538 | struct snd_interval *pt = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME); |
516 | struct snd_mask check_fmts; | 539 | struct snd_mask check_fmts; |
517 | unsigned int ptime; | 540 | unsigned int ptime; |
518 | 541 | ||
519 | /* check the format */ | 542 | /* check the format */ |
520 | snd_mask_none(&check_fmts); | 543 | snd_mask_none(&check_fmts); |
521 | check_fmts.bits[0] = (u32)fp->formats; | 544 | check_fmts.bits[0] = (u32)fp->formats; |
522 | check_fmts.bits[1] = (u32)(fp->formats >> 32); | 545 | check_fmts.bits[1] = (u32)(fp->formats >> 32); |
523 | snd_mask_intersect(&check_fmts, fmts); | 546 | snd_mask_intersect(&check_fmts, fmts); |
524 | if (snd_mask_empty(&check_fmts)) { | 547 | if (snd_mask_empty(&check_fmts)) { |
525 | hwc_debug(" > check: no supported format %d\n", fp->format); | 548 | hwc_debug(" > check: no supported format %d\n", fp->format); |
526 | return 0; | 549 | return 0; |
527 | } | 550 | } |
528 | /* check the channels */ | 551 | /* check the channels */ |
529 | if (fp->channels < ct->min || fp->channels > ct->max) { | 552 | if (fp->channels < ct->min || fp->channels > ct->max) { |
530 | hwc_debug(" > check: no valid channels %d (%d/%d)\n", fp->channels, ct->min, ct->max); | 553 | hwc_debug(" > check: no valid channels %d (%d/%d)\n", fp->channels, ct->min, ct->max); |
531 | return 0; | 554 | return 0; |
532 | } | 555 | } |
533 | /* check the rate is within the range */ | 556 | /* check the rate is within the range */ |
534 | if (fp->rate_min > it->max || (fp->rate_min == it->max && it->openmax)) { | 557 | if (fp->rate_min > it->max || (fp->rate_min == it->max && it->openmax)) { |
535 | hwc_debug(" > check: rate_min %d > max %d\n", fp->rate_min, it->max); | 558 | hwc_debug(" > check: rate_min %d > max %d\n", fp->rate_min, it->max); |
536 | return 0; | 559 | return 0; |
537 | } | 560 | } |
538 | if (fp->rate_max < it->min || (fp->rate_max == it->min && it->openmin)) { | 561 | if (fp->rate_max < it->min || (fp->rate_max == it->min && it->openmin)) { |
539 | hwc_debug(" > check: rate_max %d < min %d\n", fp->rate_max, it->min); | 562 | hwc_debug(" > check: rate_max %d < min %d\n", fp->rate_max, it->min); |
540 | return 0; | 563 | return 0; |
541 | } | 564 | } |
542 | /* check whether the period time is >= the data packet interval */ | 565 | /* check whether the period time is >= the data packet interval */ |
543 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) { | 566 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) { |
544 | ptime = 125 * (1 << fp->datainterval); | 567 | ptime = 125 * (1 << fp->datainterval); |
545 | if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { | 568 | if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { |
546 | hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); | 569 | hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); |
547 | return 0; | 570 | return 0; |
548 | } | 571 | } |
549 | } | 572 | } |
550 | return 1; | 573 | return 1; |
551 | } | 574 | } |
552 | 575 | ||
553 | static int hw_rule_rate(struct snd_pcm_hw_params *params, | 576 | static int hw_rule_rate(struct snd_pcm_hw_params *params, |
554 | struct snd_pcm_hw_rule *rule) | 577 | struct snd_pcm_hw_rule *rule) |
555 | { | 578 | { |
556 | struct snd_usb_substream *subs = rule->private; | 579 | struct snd_usb_substream *subs = rule->private; |
557 | struct list_head *p; | 580 | struct list_head *p; |
558 | struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | 581 | struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); |
559 | unsigned int rmin, rmax; | 582 | unsigned int rmin, rmax; |
560 | int changed; | 583 | int changed; |
561 | 584 | ||
562 | hwc_debug("hw_rule_rate: (%d,%d)\n", it->min, it->max); | 585 | hwc_debug("hw_rule_rate: (%d,%d)\n", it->min, it->max); |
563 | changed = 0; | 586 | changed = 0; |
564 | rmin = rmax = 0; | 587 | rmin = rmax = 0; |
565 | list_for_each(p, &subs->fmt_list) { | 588 | list_for_each(p, &subs->fmt_list) { |
566 | struct audioformat *fp; | 589 | struct audioformat *fp; |
567 | fp = list_entry(p, struct audioformat, list); | 590 | fp = list_entry(p, struct audioformat, list); |
568 | if (!hw_check_valid_format(subs, params, fp)) | 591 | if (!hw_check_valid_format(subs, params, fp)) |
569 | continue; | 592 | continue; |
570 | if (changed++) { | 593 | if (changed++) { |
571 | if (rmin > fp->rate_min) | 594 | if (rmin > fp->rate_min) |
572 | rmin = fp->rate_min; | 595 | rmin = fp->rate_min; |
573 | if (rmax < fp->rate_max) | 596 | if (rmax < fp->rate_max) |
574 | rmax = fp->rate_max; | 597 | rmax = fp->rate_max; |
575 | } else { | 598 | } else { |
576 | rmin = fp->rate_min; | 599 | rmin = fp->rate_min; |
577 | rmax = fp->rate_max; | 600 | rmax = fp->rate_max; |
578 | } | 601 | } |
579 | } | 602 | } |
580 | 603 | ||
581 | if (!changed) { | 604 | if (!changed) { |
582 | hwc_debug(" --> get empty\n"); | 605 | hwc_debug(" --> get empty\n"); |
583 | it->empty = 1; | 606 | it->empty = 1; |
584 | return -EINVAL; | 607 | return -EINVAL; |
585 | } | 608 | } |
586 | 609 | ||
587 | changed = 0; | 610 | changed = 0; |
588 | if (it->min < rmin) { | 611 | if (it->min < rmin) { |
589 | it->min = rmin; | 612 | it->min = rmin; |
590 | it->openmin = 0; | 613 | it->openmin = 0; |
591 | changed = 1; | 614 | changed = 1; |
592 | } | 615 | } |
593 | if (it->max > rmax) { | 616 | if (it->max > rmax) { |
594 | it->max = rmax; | 617 | it->max = rmax; |
595 | it->openmax = 0; | 618 | it->openmax = 0; |
596 | changed = 1; | 619 | changed = 1; |
597 | } | 620 | } |
598 | if (snd_interval_checkempty(it)) { | 621 | if (snd_interval_checkempty(it)) { |
599 | it->empty = 1; | 622 | it->empty = 1; |
600 | return -EINVAL; | 623 | return -EINVAL; |
601 | } | 624 | } |
602 | hwc_debug(" --> (%d, %d) (changed = %d)\n", it->min, it->max, changed); | 625 | hwc_debug(" --> (%d, %d) (changed = %d)\n", it->min, it->max, changed); |
603 | return changed; | 626 | return changed; |
604 | } | 627 | } |
605 | 628 | ||
606 | 629 | ||
607 | static int hw_rule_channels(struct snd_pcm_hw_params *params, | 630 | static int hw_rule_channels(struct snd_pcm_hw_params *params, |
608 | struct snd_pcm_hw_rule *rule) | 631 | struct snd_pcm_hw_rule *rule) |
609 | { | 632 | { |
610 | struct snd_usb_substream *subs = rule->private; | 633 | struct snd_usb_substream *subs = rule->private; |
611 | struct list_head *p; | 634 | struct list_head *p; |
612 | struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | 635 | struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); |
613 | unsigned int rmin, rmax; | 636 | unsigned int rmin, rmax; |
614 | int changed; | 637 | int changed; |
615 | 638 | ||
616 | hwc_debug("hw_rule_channels: (%d,%d)\n", it->min, it->max); | 639 | hwc_debug("hw_rule_channels: (%d,%d)\n", it->min, it->max); |
617 | changed = 0; | 640 | changed = 0; |
618 | rmin = rmax = 0; | 641 | rmin = rmax = 0; |
619 | list_for_each(p, &subs->fmt_list) { | 642 | list_for_each(p, &subs->fmt_list) { |
620 | struct audioformat *fp; | 643 | struct audioformat *fp; |
621 | fp = list_entry(p, struct audioformat, list); | 644 | fp = list_entry(p, struct audioformat, list); |
622 | if (!hw_check_valid_format(subs, params, fp)) | 645 | if (!hw_check_valid_format(subs, params, fp)) |
623 | continue; | 646 | continue; |
624 | if (changed++) { | 647 | if (changed++) { |
625 | if (rmin > fp->channels) | 648 | if (rmin > fp->channels) |
626 | rmin = fp->channels; | 649 | rmin = fp->channels; |
627 | if (rmax < fp->channels) | 650 | if (rmax < fp->channels) |
628 | rmax = fp->channels; | 651 | rmax = fp->channels; |
629 | } else { | 652 | } else { |
630 | rmin = fp->channels; | 653 | rmin = fp->channels; |
631 | rmax = fp->channels; | 654 | rmax = fp->channels; |
632 | } | 655 | } |
633 | } | 656 | } |
634 | 657 | ||
635 | if (!changed) { | 658 | if (!changed) { |
636 | hwc_debug(" --> get empty\n"); | 659 | hwc_debug(" --> get empty\n"); |
637 | it->empty = 1; | 660 | it->empty = 1; |
638 | return -EINVAL; | 661 | return -EINVAL; |
639 | } | 662 | } |
640 | 663 | ||
641 | changed = 0; | 664 | changed = 0; |
642 | if (it->min < rmin) { | 665 | if (it->min < rmin) { |
643 | it->min = rmin; | 666 | it->min = rmin; |
644 | it->openmin = 0; | 667 | it->openmin = 0; |
645 | changed = 1; | 668 | changed = 1; |
646 | } | 669 | } |
647 | if (it->max > rmax) { | 670 | if (it->max > rmax) { |
648 | it->max = rmax; | 671 | it->max = rmax; |
649 | it->openmax = 0; | 672 | it->openmax = 0; |
650 | changed = 1; | 673 | changed = 1; |
651 | } | 674 | } |
652 | if (snd_interval_checkempty(it)) { | 675 | if (snd_interval_checkempty(it)) { |
653 | it->empty = 1; | 676 | it->empty = 1; |
654 | return -EINVAL; | 677 | return -EINVAL; |
655 | } | 678 | } |
656 | hwc_debug(" --> (%d, %d) (changed = %d)\n", it->min, it->max, changed); | 679 | hwc_debug(" --> (%d, %d) (changed = %d)\n", it->min, it->max, changed); |
657 | return changed; | 680 | return changed; |
658 | } | 681 | } |
659 | 682 | ||
660 | static int hw_rule_format(struct snd_pcm_hw_params *params, | 683 | static int hw_rule_format(struct snd_pcm_hw_params *params, |
661 | struct snd_pcm_hw_rule *rule) | 684 | struct snd_pcm_hw_rule *rule) |
662 | { | 685 | { |
663 | struct snd_usb_substream *subs = rule->private; | 686 | struct snd_usb_substream *subs = rule->private; |
664 | struct list_head *p; | 687 | struct list_head *p; |
665 | struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | 688 | struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); |
666 | u64 fbits; | 689 | u64 fbits; |
667 | u32 oldbits[2]; | 690 | u32 oldbits[2]; |
668 | int changed; | 691 | int changed; |
669 | 692 | ||
670 | hwc_debug("hw_rule_format: %x:%x\n", fmt->bits[0], fmt->bits[1]); | 693 | hwc_debug("hw_rule_format: %x:%x\n", fmt->bits[0], fmt->bits[1]); |
671 | fbits = 0; | 694 | fbits = 0; |
672 | list_for_each(p, &subs->fmt_list) { | 695 | list_for_each(p, &subs->fmt_list) { |
673 | struct audioformat *fp; | 696 | struct audioformat *fp; |
674 | fp = list_entry(p, struct audioformat, list); | 697 | fp = list_entry(p, struct audioformat, list); |
675 | if (!hw_check_valid_format(subs, params, fp)) | 698 | if (!hw_check_valid_format(subs, params, fp)) |
676 | continue; | 699 | continue; |
677 | fbits |= fp->formats; | 700 | fbits |= fp->formats; |
678 | } | 701 | } |
679 | 702 | ||
680 | oldbits[0] = fmt->bits[0]; | 703 | oldbits[0] = fmt->bits[0]; |
681 | oldbits[1] = fmt->bits[1]; | 704 | oldbits[1] = fmt->bits[1]; |
682 | fmt->bits[0] &= (u32)fbits; | 705 | fmt->bits[0] &= (u32)fbits; |
683 | fmt->bits[1] &= (u32)(fbits >> 32); | 706 | fmt->bits[1] &= (u32)(fbits >> 32); |
684 | if (!fmt->bits[0] && !fmt->bits[1]) { | 707 | if (!fmt->bits[0] && !fmt->bits[1]) { |
685 | hwc_debug(" --> get empty\n"); | 708 | hwc_debug(" --> get empty\n"); |
686 | return -EINVAL; | 709 | return -EINVAL; |
687 | } | 710 | } |
688 | changed = (oldbits[0] != fmt->bits[0] || oldbits[1] != fmt->bits[1]); | 711 | changed = (oldbits[0] != fmt->bits[0] || oldbits[1] != fmt->bits[1]); |
689 | hwc_debug(" --> %x:%x (changed = %d)\n", fmt->bits[0], fmt->bits[1], changed); | 712 | hwc_debug(" --> %x:%x (changed = %d)\n", fmt->bits[0], fmt->bits[1], changed); |
690 | return changed; | 713 | return changed; |
691 | } | 714 | } |
692 | 715 | ||
693 | static int hw_rule_period_time(struct snd_pcm_hw_params *params, | 716 | static int hw_rule_period_time(struct snd_pcm_hw_params *params, |
694 | struct snd_pcm_hw_rule *rule) | 717 | struct snd_pcm_hw_rule *rule) |
695 | { | 718 | { |
696 | struct snd_usb_substream *subs = rule->private; | 719 | struct snd_usb_substream *subs = rule->private; |
697 | struct audioformat *fp; | 720 | struct audioformat *fp; |
698 | struct snd_interval *it; | 721 | struct snd_interval *it; |
699 | unsigned char min_datainterval; | 722 | unsigned char min_datainterval; |
700 | unsigned int pmin; | 723 | unsigned int pmin; |
701 | int changed; | 724 | int changed; |
702 | 725 | ||
703 | it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME); | 726 | it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME); |
704 | hwc_debug("hw_rule_period_time: (%u,%u)\n", it->min, it->max); | 727 | hwc_debug("hw_rule_period_time: (%u,%u)\n", it->min, it->max); |
705 | min_datainterval = 0xff; | 728 | min_datainterval = 0xff; |
706 | list_for_each_entry(fp, &subs->fmt_list, list) { | 729 | list_for_each_entry(fp, &subs->fmt_list, list) { |
707 | if (!hw_check_valid_format(subs, params, fp)) | 730 | if (!hw_check_valid_format(subs, params, fp)) |
708 | continue; | 731 | continue; |
709 | min_datainterval = min(min_datainterval, fp->datainterval); | 732 | min_datainterval = min(min_datainterval, fp->datainterval); |
710 | } | 733 | } |
711 | if (min_datainterval == 0xff) { | 734 | if (min_datainterval == 0xff) { |
712 | hwc_debug(" --> get emtpy\n"); | 735 | hwc_debug(" --> get emtpy\n"); |
713 | it->empty = 1; | 736 | it->empty = 1; |
714 | return -EINVAL; | 737 | return -EINVAL; |
715 | } | 738 | } |
716 | pmin = 125 * (1 << min_datainterval); | 739 | pmin = 125 * (1 << min_datainterval); |
717 | changed = 0; | 740 | changed = 0; |
718 | if (it->min < pmin) { | 741 | if (it->min < pmin) { |
719 | it->min = pmin; | 742 | it->min = pmin; |
720 | it->openmin = 0; | 743 | it->openmin = 0; |
721 | changed = 1; | 744 | changed = 1; |
722 | } | 745 | } |
723 | if (snd_interval_checkempty(it)) { | 746 | if (snd_interval_checkempty(it)) { |
724 | it->empty = 1; | 747 | it->empty = 1; |
725 | return -EINVAL; | 748 | return -EINVAL; |
726 | } | 749 | } |
727 | hwc_debug(" --> (%u,%u) (changed = %d)\n", it->min, it->max, changed); | 750 | hwc_debug(" --> (%u,%u) (changed = %d)\n", it->min, it->max, changed); |
728 | return changed; | 751 | return changed; |
729 | } | 752 | } |
730 | 753 | ||
731 | /* | 754 | /* |
732 | * If the device supports unusual bit rates, does the request meet these? | 755 | * If the device supports unusual bit rates, does the request meet these? |
733 | */ | 756 | */ |
734 | static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, | 757 | static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, |
735 | struct snd_usb_substream *subs) | 758 | struct snd_usb_substream *subs) |
736 | { | 759 | { |
737 | struct audioformat *fp; | 760 | struct audioformat *fp; |
738 | int count = 0, needs_knot = 0; | 761 | int count = 0, needs_knot = 0; |
739 | int err; | 762 | int err; |
740 | 763 | ||
741 | list_for_each_entry(fp, &subs->fmt_list, list) { | 764 | list_for_each_entry(fp, &subs->fmt_list, list) { |
742 | if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) | 765 | if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) |
743 | return 0; | 766 | return 0; |
744 | count += fp->nr_rates; | 767 | count += fp->nr_rates; |
745 | if (fp->rates & SNDRV_PCM_RATE_KNOT) | 768 | if (fp->rates & SNDRV_PCM_RATE_KNOT) |
746 | needs_knot = 1; | 769 | needs_knot = 1; |
747 | } | 770 | } |
748 | if (!needs_knot) | 771 | if (!needs_knot) |
749 | return 0; | 772 | return 0; |
750 | 773 | ||
751 | subs->rate_list.count = count; | 774 | subs->rate_list.count = count; |
752 | subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL); | 775 | subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL); |
753 | subs->rate_list.mask = 0; | 776 | subs->rate_list.mask = 0; |
754 | count = 0; | 777 | count = 0; |
755 | list_for_each_entry(fp, &subs->fmt_list, list) { | 778 | list_for_each_entry(fp, &subs->fmt_list, list) { |
756 | int i; | 779 | int i; |
757 | for (i = 0; i < fp->nr_rates; i++) | 780 | for (i = 0; i < fp->nr_rates; i++) |
758 | subs->rate_list.list[count++] = fp->rate_table[i]; | 781 | subs->rate_list.list[count++] = fp->rate_table[i]; |
759 | } | 782 | } |
760 | err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 783 | err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
761 | &subs->rate_list); | 784 | &subs->rate_list); |
762 | if (err < 0) | 785 | if (err < 0) |
763 | return err; | 786 | return err; |
764 | 787 | ||
765 | return 0; | 788 | return 0; |
766 | } | 789 | } |
767 | 790 | ||
768 | 791 | ||
769 | /* | 792 | /* |
770 | * set up the runtime hardware information. | 793 | * set up the runtime hardware information. |
771 | */ | 794 | */ |
772 | 795 | ||
773 | static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs) | 796 | static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs) |
774 | { | 797 | { |
775 | struct list_head *p; | 798 | struct list_head *p; |
776 | unsigned int pt, ptmin; | 799 | unsigned int pt, ptmin; |
777 | int param_period_time_if_needed; | 800 | int param_period_time_if_needed; |
778 | int err; | 801 | int err; |
779 | 802 | ||
780 | runtime->hw.formats = subs->formats; | 803 | runtime->hw.formats = subs->formats; |
781 | 804 | ||
782 | runtime->hw.rate_min = 0x7fffffff; | 805 | runtime->hw.rate_min = 0x7fffffff; |
783 | runtime->hw.rate_max = 0; | 806 | runtime->hw.rate_max = 0; |
784 | runtime->hw.channels_min = 256; | 807 | runtime->hw.channels_min = 256; |
785 | runtime->hw.channels_max = 0; | 808 | runtime->hw.channels_max = 0; |
786 | runtime->hw.rates = 0; | 809 | runtime->hw.rates = 0; |
787 | ptmin = UINT_MAX; | 810 | ptmin = UINT_MAX; |
788 | /* check min/max rates and channels */ | 811 | /* check min/max rates and channels */ |
789 | list_for_each(p, &subs->fmt_list) { | 812 | list_for_each(p, &subs->fmt_list) { |
790 | struct audioformat *fp; | 813 | struct audioformat *fp; |
791 | fp = list_entry(p, struct audioformat, list); | 814 | fp = list_entry(p, struct audioformat, list); |
792 | runtime->hw.rates |= fp->rates; | 815 | runtime->hw.rates |= fp->rates; |
793 | if (runtime->hw.rate_min > fp->rate_min) | 816 | if (runtime->hw.rate_min > fp->rate_min) |
794 | runtime->hw.rate_min = fp->rate_min; | 817 | runtime->hw.rate_min = fp->rate_min; |
795 | if (runtime->hw.rate_max < fp->rate_max) | 818 | if (runtime->hw.rate_max < fp->rate_max) |
796 | runtime->hw.rate_max = fp->rate_max; | 819 | runtime->hw.rate_max = fp->rate_max; |
797 | if (runtime->hw.channels_min > fp->channels) | 820 | if (runtime->hw.channels_min > fp->channels) |
798 | runtime->hw.channels_min = fp->channels; | 821 | runtime->hw.channels_min = fp->channels; |
799 | if (runtime->hw.channels_max < fp->channels) | 822 | if (runtime->hw.channels_max < fp->channels) |
800 | runtime->hw.channels_max = fp->channels; | 823 | runtime->hw.channels_max = fp->channels; |
801 | if (fp->fmt_type == UAC_FORMAT_TYPE_II && fp->frame_size > 0) { | 824 | if (fp->fmt_type == UAC_FORMAT_TYPE_II && fp->frame_size > 0) { |
802 | /* FIXME: there might be more than one audio formats... */ | 825 | /* FIXME: there might be more than one audio formats... */ |
803 | runtime->hw.period_bytes_min = runtime->hw.period_bytes_max = | 826 | runtime->hw.period_bytes_min = runtime->hw.period_bytes_max = |
804 | fp->frame_size; | 827 | fp->frame_size; |
805 | } | 828 | } |
806 | pt = 125 * (1 << fp->datainterval); | 829 | pt = 125 * (1 << fp->datainterval); |
807 | ptmin = min(ptmin, pt); | 830 | ptmin = min(ptmin, pt); |
808 | } | 831 | } |
809 | 832 | ||
810 | param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; | 833 | param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; |
811 | if (snd_usb_get_speed(subs->dev) != USB_SPEED_HIGH) | 834 | if (snd_usb_get_speed(subs->dev) != USB_SPEED_HIGH) |
812 | /* full speed devices have fixed data packet interval */ | 835 | /* full speed devices have fixed data packet interval */ |
813 | ptmin = 1000; | 836 | ptmin = 1000; |
814 | if (ptmin == 1000) | 837 | if (ptmin == 1000) |
815 | /* if period time doesn't go below 1 ms, no rules needed */ | 838 | /* if period time doesn't go below 1 ms, no rules needed */ |
816 | param_period_time_if_needed = -1; | 839 | param_period_time_if_needed = -1; |
817 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, | 840 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, |
818 | ptmin, UINT_MAX); | 841 | ptmin, UINT_MAX); |
819 | 842 | ||
820 | if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 843 | if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
821 | hw_rule_rate, subs, | 844 | hw_rule_rate, subs, |
822 | SNDRV_PCM_HW_PARAM_FORMAT, | 845 | SNDRV_PCM_HW_PARAM_FORMAT, |
823 | SNDRV_PCM_HW_PARAM_CHANNELS, | 846 | SNDRV_PCM_HW_PARAM_CHANNELS, |
824 | param_period_time_if_needed, | 847 | param_period_time_if_needed, |
825 | -1)) < 0) | 848 | -1)) < 0) |
826 | return err; | 849 | return err; |
827 | if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 850 | if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
828 | hw_rule_channels, subs, | 851 | hw_rule_channels, subs, |
829 | SNDRV_PCM_HW_PARAM_FORMAT, | 852 | SNDRV_PCM_HW_PARAM_FORMAT, |
830 | SNDRV_PCM_HW_PARAM_RATE, | 853 | SNDRV_PCM_HW_PARAM_RATE, |
831 | param_period_time_if_needed, | 854 | param_period_time_if_needed, |
832 | -1)) < 0) | 855 | -1)) < 0) |
833 | return err; | 856 | return err; |
834 | if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, | 857 | if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, |
835 | hw_rule_format, subs, | 858 | hw_rule_format, subs, |
836 | SNDRV_PCM_HW_PARAM_RATE, | 859 | SNDRV_PCM_HW_PARAM_RATE, |
837 | SNDRV_PCM_HW_PARAM_CHANNELS, | 860 | SNDRV_PCM_HW_PARAM_CHANNELS, |
838 | param_period_time_if_needed, | 861 | param_period_time_if_needed, |
839 | -1)) < 0) | 862 | -1)) < 0) |
840 | return err; | 863 | return err; |
841 | if (param_period_time_if_needed >= 0) { | 864 | if (param_period_time_if_needed >= 0) { |
842 | err = snd_pcm_hw_rule_add(runtime, 0, | 865 | err = snd_pcm_hw_rule_add(runtime, 0, |
843 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, | 866 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, |
844 | hw_rule_period_time, subs, | 867 | hw_rule_period_time, subs, |
845 | SNDRV_PCM_HW_PARAM_FORMAT, | 868 | SNDRV_PCM_HW_PARAM_FORMAT, |
846 | SNDRV_PCM_HW_PARAM_CHANNELS, | 869 | SNDRV_PCM_HW_PARAM_CHANNELS, |
847 | SNDRV_PCM_HW_PARAM_RATE, | 870 | SNDRV_PCM_HW_PARAM_RATE, |
848 | -1); | 871 | -1); |
849 | if (err < 0) | 872 | if (err < 0) |
850 | return err; | 873 | return err; |
851 | } | 874 | } |
852 | if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) | 875 | if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) |
853 | return err; | 876 | return err; |
854 | return 0; | 877 | return 0; |
855 | } | 878 | } |
856 | 879 | ||
857 | static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) | 880 | static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) |
858 | { | 881 | { |
859 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); | 882 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); |
860 | struct snd_pcm_runtime *runtime = substream->runtime; | 883 | struct snd_pcm_runtime *runtime = substream->runtime; |
861 | struct snd_usb_substream *subs = &as->substream[direction]; | 884 | struct snd_usb_substream *subs = &as->substream[direction]; |
862 | 885 | ||
863 | subs->interface = -1; | 886 | subs->interface = -1; |
864 | subs->altset_idx = 0; | 887 | subs->altset_idx = 0; |
865 | runtime->hw = snd_usb_hardware; | 888 | runtime->hw = snd_usb_hardware; |
866 | runtime->private_data = subs; | 889 | runtime->private_data = subs; |
867 | subs->pcm_substream = substream; | 890 | subs->pcm_substream = substream; |
868 | return setup_hw_info(runtime, subs); | 891 | return setup_hw_info(runtime, subs); |
869 | } | 892 | } |
870 | 893 | ||
871 | static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) | 894 | static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) |
872 | { | 895 | { |
873 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); | 896 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); |
874 | struct snd_usb_substream *subs = &as->substream[direction]; | 897 | struct snd_usb_substream *subs = &as->substream[direction]; |
875 | 898 | ||
876 | if (!as->chip->shutdown && subs->interface >= 0) { | 899 | if (!as->chip->shutdown && subs->interface >= 0) { |
877 | usb_set_interface(subs->dev, subs->interface, 0); | 900 | usb_set_interface(subs->dev, subs->interface, 0); |
878 | subs->interface = -1; | 901 | subs->interface = -1; |
879 | } | 902 | } |
880 | subs->pcm_substream = NULL; | 903 | subs->pcm_substream = NULL; |
881 | return 0; | 904 | return 0; |
882 | } | 905 | } |
883 | 906 | ||
884 | static int snd_usb_playback_open(struct snd_pcm_substream *substream) | 907 | static int snd_usb_playback_open(struct snd_pcm_substream *substream) |
885 | { | 908 | { |
886 | return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_PLAYBACK); | 909 | return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_PLAYBACK); |
887 | } | 910 | } |
888 | 911 | ||
889 | static int snd_usb_playback_close(struct snd_pcm_substream *substream) | 912 | static int snd_usb_playback_close(struct snd_pcm_substream *substream) |
890 | { | 913 | { |
891 | return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_PLAYBACK); | 914 | return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_PLAYBACK); |
892 | } | 915 | } |
893 | 916 | ||
894 | static int snd_usb_capture_open(struct snd_pcm_substream *substream) | 917 | static int snd_usb_capture_open(struct snd_pcm_substream *substream) |
895 | { | 918 | { |
896 | return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_CAPTURE); | 919 | return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_CAPTURE); |
897 | } | 920 | } |
898 | 921 | ||
899 | static int snd_usb_capture_close(struct snd_pcm_substream *substream) | 922 | static int snd_usb_capture_close(struct snd_pcm_substream *substream) |
900 | { | 923 | { |
901 | return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_CAPTURE); | 924 | return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_CAPTURE); |
902 | } | 925 | } |
903 | 926 | ||
904 | static struct snd_pcm_ops snd_usb_playback_ops = { | 927 | static struct snd_pcm_ops snd_usb_playback_ops = { |
905 | .open = snd_usb_playback_open, | 928 | .open = snd_usb_playback_open, |
906 | .close = snd_usb_playback_close, | 929 | .close = snd_usb_playback_close, |
907 | .ioctl = snd_pcm_lib_ioctl, | 930 | .ioctl = snd_pcm_lib_ioctl, |
908 | .hw_params = snd_usb_hw_params, | 931 | .hw_params = snd_usb_hw_params, |
909 | .hw_free = snd_usb_hw_free, | 932 | .hw_free = snd_usb_hw_free, |
910 | .prepare = snd_usb_pcm_prepare, | 933 | .prepare = snd_usb_pcm_prepare, |
911 | .trigger = snd_usb_substream_playback_trigger, | 934 | .trigger = snd_usb_substream_playback_trigger, |
912 | .pointer = snd_usb_pcm_pointer, | 935 | .pointer = snd_usb_pcm_pointer, |
913 | .page = snd_pcm_lib_get_vmalloc_page, | 936 | .page = snd_pcm_lib_get_vmalloc_page, |
914 | .mmap = snd_pcm_lib_mmap_vmalloc, | 937 | .mmap = snd_pcm_lib_mmap_vmalloc, |
915 | }; | 938 | }; |
916 | 939 | ||
917 | static struct snd_pcm_ops snd_usb_capture_ops = { | 940 | static struct snd_pcm_ops snd_usb_capture_ops = { |
918 | .open = snd_usb_capture_open, | 941 | .open = snd_usb_capture_open, |
919 | .close = snd_usb_capture_close, | 942 | .close = snd_usb_capture_close, |
920 | .ioctl = snd_pcm_lib_ioctl, | 943 | .ioctl = snd_pcm_lib_ioctl, |
921 | .hw_params = snd_usb_hw_params, | 944 | .hw_params = snd_usb_hw_params, |
922 | .hw_free = snd_usb_hw_free, | 945 | .hw_free = snd_usb_hw_free, |
923 | .prepare = snd_usb_pcm_prepare, | 946 | .prepare = snd_usb_pcm_prepare, |
924 | .trigger = snd_usb_substream_capture_trigger, | 947 | .trigger = snd_usb_substream_capture_trigger, |
925 | .pointer = snd_usb_pcm_pointer, | 948 | .pointer = snd_usb_pcm_pointer, |
926 | .page = snd_pcm_lib_get_vmalloc_page, | 949 | .page = snd_pcm_lib_get_vmalloc_page, |
927 | .mmap = snd_pcm_lib_mmap_vmalloc, | 950 | .mmap = snd_pcm_lib_mmap_vmalloc, |
928 | }; | 951 | }; |
929 | 952 | ||
930 | void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream) | 953 | void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream) |
931 | { | 954 | { |