diff options
Diffstat (limited to 'sound/usb/endpoint.c')
-rw-r--r-- | sound/usb/endpoint.c | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 28ee1ce3971a..9593b91452b9 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c | |||
@@ -190,6 +190,38 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, | |||
190 | return attributes; | 190 | return attributes; |
191 | } | 191 | } |
192 | 192 | ||
193 | static struct uac2_input_terminal_descriptor * | ||
194 | snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, | ||
195 | int terminal_id) | ||
196 | { | ||
197 | struct uac2_input_terminal_descriptor *term = NULL; | ||
198 | |||
199 | while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, | ||
200 | ctrl_iface->extralen, | ||
201 | term, UAC_INPUT_TERMINAL))) { | ||
202 | if (term->bTerminalID == terminal_id) | ||
203 | return term; | ||
204 | } | ||
205 | |||
206 | return NULL; | ||
207 | } | ||
208 | |||
209 | static struct uac2_output_terminal_descriptor * | ||
210 | snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface, | ||
211 | int terminal_id) | ||
212 | { | ||
213 | struct uac2_output_terminal_descriptor *term = NULL; | ||
214 | |||
215 | while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, | ||
216 | ctrl_iface->extralen, | ||
217 | term, UAC_OUTPUT_TERMINAL))) { | ||
218 | if (term->bTerminalID == terminal_id) | ||
219 | return term; | ||
220 | } | ||
221 | |||
222 | return NULL; | ||
223 | } | ||
224 | |||
193 | int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | 225 | int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) |
194 | { | 226 | { |
195 | struct usb_device *dev; | 227 | struct usb_device *dev; |
@@ -199,7 +231,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
199 | int i, altno, err, stream; | 231 | int i, altno, err, stream; |
200 | int format = 0, num_channels = 0; | 232 | int format = 0, num_channels = 0; |
201 | struct audioformat *fp = NULL; | 233 | struct audioformat *fp = NULL; |
202 | int num, protocol; | 234 | int num, protocol, clock = 0; |
203 | struct uac_format_type_i_continuous_descriptor *fmt; | 235 | struct uac_format_type_i_continuous_descriptor *fmt; |
204 | 236 | ||
205 | dev = chip->dev; | 237 | dev = chip->dev; |
@@ -263,6 +295,8 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
263 | } | 295 | } |
264 | 296 | ||
265 | case UAC_VERSION_2: { | 297 | case UAC_VERSION_2: { |
298 | struct uac2_input_terminal_descriptor *input_term; | ||
299 | struct uac2_output_terminal_descriptor *output_term; | ||
266 | struct uac_as_header_descriptor_v2 *as = | 300 | struct uac_as_header_descriptor_v2 *as = |
267 | snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); | 301 | snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); |
268 | 302 | ||
@@ -281,7 +315,25 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
281 | num_channels = as->bNrChannels; | 315 | num_channels = as->bNrChannels; |
282 | format = le32_to_cpu(as->bmFormats); | 316 | format = le32_to_cpu(as->bmFormats); |
283 | 317 | ||
284 | break; | 318 | /* lookup the terminal associated to this interface |
319 | * to extract the clock */ | ||
320 | input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, | ||
321 | as->bTerminalLink); | ||
322 | if (input_term) { | ||
323 | clock = input_term->bCSourceID; | ||
324 | break; | ||
325 | } | ||
326 | |||
327 | output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf, | ||
328 | as->bTerminalLink); | ||
329 | if (output_term) { | ||
330 | clock = output_term->bCSourceID; | ||
331 | break; | ||
332 | } | ||
333 | |||
334 | snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n", | ||
335 | dev->devnum, iface_no, altno, as->bTerminalLink); | ||
336 | continue; | ||
285 | } | 337 | } |
286 | 338 | ||
287 | default: | 339 | default: |
@@ -338,6 +390,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
338 | fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) | 390 | fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) |
339 | * (fp->maxpacksize & 0x7ff); | 391 | * (fp->maxpacksize & 0x7ff); |
340 | fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no); | 392 | fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no); |
393 | fp->clock = clock; | ||
341 | 394 | ||
342 | /* some quirks for attributes here */ | 395 | /* some quirks for attributes here */ |
343 | 396 | ||