diff options
Diffstat (limited to 'sound/usb/format.c')
-rw-r--r-- | sound/usb/format.c | 93 |
1 files changed, 76 insertions, 17 deletions
diff --git a/sound/usb/format.c b/sound/usb/format.c index 2c44386e5569..49e7ec6d2399 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/usb.h> | 20 | #include <linux/usb.h> |
21 | #include <linux/usb/audio.h> | 21 | #include <linux/usb/audio.h> |
22 | #include <linux/usb/audio-v2.h> | 22 | #include <linux/usb/audio-v2.h> |
23 | #include <linux/usb/audio-v3.h> | ||
23 | 24 | ||
24 | #include <sound/core.h> | 25 | #include <sound/core.h> |
25 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
@@ -39,11 +40,11 @@ | |||
39 | * @dev: usb device | 40 | * @dev: usb device |
40 | * @fp: audioformat record | 41 | * @fp: audioformat record |
41 | * @format: the format tag (wFormatTag) | 42 | * @format: the format tag (wFormatTag) |
42 | * @fmt: the format type descriptor | 43 | * @fmt: the format type descriptor (v1/v2) or AudioStreaming descriptor (v3) |
43 | */ | 44 | */ |
44 | static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, | 45 | static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, |
45 | struct audioformat *fp, | 46 | struct audioformat *fp, |
46 | unsigned int format, void *_fmt) | 47 | u64 format, void *_fmt) |
47 | { | 48 | { |
48 | int sample_width, sample_bytes; | 49 | int sample_width, sample_bytes; |
49 | u64 pcm_formats = 0; | 50 | u64 pcm_formats = 0; |
@@ -54,7 +55,7 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, | |||
54 | struct uac_format_type_i_discrete_descriptor *fmt = _fmt; | 55 | struct uac_format_type_i_discrete_descriptor *fmt = _fmt; |
55 | sample_width = fmt->bBitResolution; | 56 | sample_width = fmt->bBitResolution; |
56 | sample_bytes = fmt->bSubframeSize; | 57 | sample_bytes = fmt->bSubframeSize; |
57 | format = 1 << format; | 58 | format = 1ULL << format; |
58 | break; | 59 | break; |
59 | } | 60 | } |
60 | 61 | ||
@@ -69,6 +70,18 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, | |||
69 | format <<= 1; | 70 | format <<= 1; |
70 | break; | 71 | break; |
71 | } | 72 | } |
73 | case UAC_VERSION_3: { | ||
74 | struct uac3_as_header_descriptor *as = _fmt; | ||
75 | |||
76 | sample_width = as->bBitResolution; | ||
77 | sample_bytes = as->bSubslotSize; | ||
78 | |||
79 | if (format & UAC3_FORMAT_TYPE_I_RAW_DATA) | ||
80 | pcm_formats |= SNDRV_PCM_FMTBIT_SPECIAL; | ||
81 | |||
82 | format <<= 1; | ||
83 | break; | ||
84 | } | ||
72 | } | 85 | } |
73 | 86 | ||
74 | if ((pcm_formats == 0) && | 87 | if ((pcm_formats == 0) && |
@@ -137,7 +150,7 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, | |||
137 | } | 150 | } |
138 | if (format & ~0x3f) { | 151 | if (format & ~0x3f) { |
139 | usb_audio_info(chip, | 152 | usb_audio_info(chip, |
140 | "%u:%d : unsupported format bits %#x\n", | 153 | "%u:%d : unsupported format bits %#llx\n", |
141 | fp->iface, fp->altsetting, format); | 154 | fp->iface, fp->altsetting, format); |
142 | } | 155 | } |
143 | 156 | ||
@@ -281,15 +294,16 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip, | |||
281 | 294 | ||
282 | /* | 295 | /* |
283 | * parse the format descriptor and stores the possible sample rates | 296 | * parse the format descriptor and stores the possible sample rates |
284 | * on the audioformat table (audio class v2). | 297 | * on the audioformat table (audio class v2 and v3). |
285 | */ | 298 | */ |
286 | static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, | 299 | static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip, |
287 | struct audioformat *fp) | 300 | struct audioformat *fp) |
288 | { | 301 | { |
289 | struct usb_device *dev = chip->dev; | 302 | struct usb_device *dev = chip->dev; |
290 | unsigned char tmp[2], *data; | 303 | unsigned char tmp[2], *data; |
291 | int nr_triplets, data_size, ret = 0; | 304 | int nr_triplets, data_size, ret = 0; |
292 | int clock = snd_usb_clock_find_source(chip, fp->clock, false); | 305 | int clock = snd_usb_clock_find_source(chip, fp->protocol, |
306 | fp->clock, false); | ||
293 | 307 | ||
294 | if (clock < 0) { | 308 | if (clock < 0) { |
295 | dev_err(&dev->dev, | 309 | dev_err(&dev->dev, |
@@ -368,13 +382,30 @@ err: | |||
368 | * parse the format type I and III descriptors | 382 | * parse the format type I and III descriptors |
369 | */ | 383 | */ |
370 | static int parse_audio_format_i(struct snd_usb_audio *chip, | 384 | static int parse_audio_format_i(struct snd_usb_audio *chip, |
371 | struct audioformat *fp, unsigned int format, | 385 | struct audioformat *fp, u64 format, |
372 | struct uac_format_type_i_continuous_descriptor *fmt) | 386 | void *_fmt) |
373 | { | 387 | { |
374 | snd_pcm_format_t pcm_format; | 388 | snd_pcm_format_t pcm_format; |
389 | unsigned int fmt_type; | ||
375 | int ret; | 390 | int ret; |
376 | 391 | ||
377 | if (fmt->bFormatType == UAC_FORMAT_TYPE_III) { | 392 | switch (fp->protocol) { |
393 | default: | ||
394 | case UAC_VERSION_1: | ||
395 | case UAC_VERSION_2: { | ||
396 | struct uac_format_type_i_continuous_descriptor *fmt = _fmt; | ||
397 | |||
398 | fmt_type = fmt->bFormatType; | ||
399 | break; | ||
400 | } | ||
401 | case UAC_VERSION_3: { | ||
402 | /* fp->fmt_type is already set in this case */ | ||
403 | fmt_type = fp->fmt_type; | ||
404 | break; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | if (fmt_type == UAC_FORMAT_TYPE_III) { | ||
378 | /* FIXME: the format type is really IECxxx | 409 | /* FIXME: the format type is really IECxxx |
379 | * but we give normal PCM format to get the existing | 410 | * but we give normal PCM format to get the existing |
380 | * apps working... | 411 | * apps working... |
@@ -393,7 +424,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, | |||
393 | } | 424 | } |
394 | fp->formats = pcm_format_to_bits(pcm_format); | 425 | fp->formats = pcm_format_to_bits(pcm_format); |
395 | } else { | 426 | } else { |
396 | fp->formats = parse_audio_format_i_type(chip, fp, format, fmt); | 427 | fp->formats = parse_audio_format_i_type(chip, fp, format, _fmt); |
397 | if (!fp->formats) | 428 | if (!fp->formats) |
398 | return -EINVAL; | 429 | return -EINVAL; |
399 | } | 430 | } |
@@ -405,15 +436,20 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, | |||
405 | */ | 436 | */ |
406 | switch (fp->protocol) { | 437 | switch (fp->protocol) { |
407 | default: | 438 | default: |
408 | case UAC_VERSION_1: | 439 | case UAC_VERSION_1: { |
440 | struct uac_format_type_i_continuous_descriptor *fmt = _fmt; | ||
441 | |||
409 | fp->channels = fmt->bNrChannels; | 442 | fp->channels = fmt->bNrChannels; |
410 | ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7); | 443 | ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7); |
411 | break; | 444 | break; |
445 | } | ||
412 | case UAC_VERSION_2: | 446 | case UAC_VERSION_2: |
447 | case UAC_VERSION_3: { | ||
413 | /* fp->channels is already set in this case */ | 448 | /* fp->channels is already set in this case */ |
414 | ret = parse_audio_format_rates_v2(chip, fp); | 449 | ret = parse_audio_format_rates_v2v3(chip, fp); |
415 | break; | 450 | break; |
416 | } | 451 | } |
452 | } | ||
417 | 453 | ||
418 | if (fp->channels < 1) { | 454 | if (fp->channels < 1) { |
419 | usb_audio_err(chip, | 455 | usb_audio_err(chip, |
@@ -430,7 +466,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, | |||
430 | */ | 466 | */ |
431 | static int parse_audio_format_ii(struct snd_usb_audio *chip, | 467 | static int parse_audio_format_ii(struct snd_usb_audio *chip, |
432 | struct audioformat *fp, | 468 | struct audioformat *fp, |
433 | int format, void *_fmt) | 469 | u64 format, void *_fmt) |
434 | { | 470 | { |
435 | int brate, framesize, ret; | 471 | int brate, framesize, ret; |
436 | 472 | ||
@@ -445,7 +481,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, | |||
445 | break; | 481 | break; |
446 | default: | 482 | default: |
447 | usb_audio_info(chip, | 483 | usb_audio_info(chip, |
448 | "%u:%d : unknown format tag %#x is detected. processed as MPEG.\n", | 484 | "%u:%d : unknown format tag %#llx is detected. processed as MPEG.\n", |
449 | fp->iface, fp->altsetting, format); | 485 | fp->iface, fp->altsetting, format); |
450 | fp->formats = SNDRV_PCM_FMTBIT_MPEG; | 486 | fp->formats = SNDRV_PCM_FMTBIT_MPEG; |
451 | break; | 487 | break; |
@@ -470,7 +506,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, | |||
470 | framesize = le16_to_cpu(fmt->wSamplesPerFrame); | 506 | framesize = le16_to_cpu(fmt->wSamplesPerFrame); |
471 | usb_audio_info(chip, "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); | 507 | usb_audio_info(chip, "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); |
472 | fp->frame_size = framesize; | 508 | fp->frame_size = framesize; |
473 | ret = parse_audio_format_rates_v2(chip, fp); | 509 | ret = parse_audio_format_rates_v2v3(chip, fp); |
474 | break; | 510 | break; |
475 | } | 511 | } |
476 | } | 512 | } |
@@ -479,7 +515,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, | |||
479 | } | 515 | } |
480 | 516 | ||
481 | int snd_usb_parse_audio_format(struct snd_usb_audio *chip, | 517 | int snd_usb_parse_audio_format(struct snd_usb_audio *chip, |
482 | struct audioformat *fp, unsigned int format, | 518 | struct audioformat *fp, u64 format, |
483 | struct uac_format_type_i_continuous_descriptor *fmt, | 519 | struct uac_format_type_i_continuous_descriptor *fmt, |
484 | int stream) | 520 | int stream) |
485 | { | 521 | { |
@@ -520,3 +556,26 @@ int snd_usb_parse_audio_format(struct snd_usb_audio *chip, | |||
520 | return 0; | 556 | return 0; |
521 | } | 557 | } |
522 | 558 | ||
559 | int snd_usb_parse_audio_format_v3(struct snd_usb_audio *chip, | ||
560 | struct audioformat *fp, | ||
561 | struct uac3_as_header_descriptor *as, | ||
562 | int stream) | ||
563 | { | ||
564 | u64 format = le64_to_cpu(as->bmFormats); | ||
565 | int err; | ||
566 | |||
567 | /* | ||
568 | * Type I format bits are D0..D6 | ||
569 | * This test works because type IV is not supported | ||
570 | */ | ||
571 | if (format & 0x7f) | ||
572 | fp->fmt_type = UAC_FORMAT_TYPE_I; | ||
573 | else | ||
574 | fp->fmt_type = UAC_FORMAT_TYPE_III; | ||
575 | |||
576 | err = parse_audio_format_i(chip, fp, format, as); | ||
577 | if (err < 0) | ||
578 | return err; | ||
579 | |||
580 | return 0; | ||
581 | } | ||