diff options
Diffstat (limited to 'sound/usb/stream.c')
-rw-r--r-- | sound/usb/stream.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/sound/usb/stream.c b/sound/usb/stream.c index c4339f97226b..d737d0e6e558 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c | |||
@@ -281,8 +281,6 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits, | |||
281 | const unsigned int *maps; | 281 | const unsigned int *maps; |
282 | int c; | 282 | int c; |
283 | 283 | ||
284 | if (!bits) | ||
285 | return NULL; | ||
286 | if (channels > ARRAY_SIZE(chmap->map)) | 284 | if (channels > ARRAY_SIZE(chmap->map)) |
287 | return NULL; | 285 | return NULL; |
288 | 286 | ||
@@ -293,9 +291,19 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits, | |||
293 | maps = protocol == UAC_VERSION_2 ? uac2_maps : uac1_maps; | 291 | maps = protocol == UAC_VERSION_2 ? uac2_maps : uac1_maps; |
294 | chmap->channels = channels; | 292 | chmap->channels = channels; |
295 | c = 0; | 293 | c = 0; |
296 | for (; bits && *maps; maps++, bits >>= 1) { | 294 | |
297 | if (bits & 1) | 295 | if (bits) { |
298 | chmap->map[c++] = *maps; | 296 | for (; bits && *maps; maps++, bits >>= 1) |
297 | if (bits & 1) | ||
298 | chmap->map[c++] = *maps; | ||
299 | } else { | ||
300 | /* If we're missing wChannelConfig, then guess something | ||
301 | to make sure the channel map is not skipped entirely */ | ||
302 | if (channels == 1) | ||
303 | chmap->map[c++] = SNDRV_CHMAP_MONO; | ||
304 | else | ||
305 | for (; c < channels && *maps; maps++) | ||
306 | chmap->map[c++] = *maps; | ||
299 | } | 307 | } |
300 | 308 | ||
301 | for (; c < channels; c++) | 309 | for (; c < channels; c++) |
@@ -579,6 +587,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
579 | 587 | ||
580 | num_channels = as->bNrChannels; | 588 | num_channels = as->bNrChannels; |
581 | format = le32_to_cpu(as->bmFormats); | 589 | format = le32_to_cpu(as->bmFormats); |
590 | chconfig = le32_to_cpu(as->bmChannelConfig); | ||
582 | 591 | ||
583 | /* lookup the terminal associated to this interface | 592 | /* lookup the terminal associated to this interface |
584 | * to extract the clock */ | 593 | * to extract the clock */ |
@@ -586,7 +595,8 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
586 | as->bTerminalLink); | 595 | as->bTerminalLink); |
587 | if (input_term) { | 596 | if (input_term) { |
588 | clock = input_term->bCSourceID; | 597 | clock = input_term->bCSourceID; |
589 | chconfig = le32_to_cpu(input_term->bmChannelConfig); | 598 | if (!chconfig && (num_channels == input_term->bNrChannels)) |
599 | chconfig = le32_to_cpu(input_term->bmChannelConfig); | ||
590 | break; | 600 | break; |
591 | } | 601 | } |
592 | 602 | ||
@@ -652,7 +662,6 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
652 | * (fp->maxpacksize & 0x7ff); | 662 | * (fp->maxpacksize & 0x7ff); |
653 | fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no); | 663 | fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no); |
654 | fp->clock = clock; | 664 | fp->clock = clock; |
655 | fp->chmap = convert_chmap(num_channels, chconfig, protocol); | ||
656 | 665 | ||
657 | /* some quirks for attributes here */ | 666 | /* some quirks for attributes here */ |
658 | 667 | ||
@@ -688,12 +697,16 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
688 | /* ok, let's parse further... */ | 697 | /* ok, let's parse further... */ |
689 | if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream) < 0) { | 698 | if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream) < 0) { |
690 | kfree(fp->rate_table); | 699 | kfree(fp->rate_table); |
691 | kfree(fp->chmap); | ||
692 | kfree(fp); | 700 | kfree(fp); |
693 | fp = NULL; | 701 | fp = NULL; |
694 | continue; | 702 | continue; |
695 | } | 703 | } |
696 | 704 | ||
705 | /* Create chmap */ | ||
706 | if (fp->channels != num_channels) | ||
707 | chconfig = 0; | ||
708 | fp->chmap = convert_chmap(fp->channels, chconfig, protocol); | ||
709 | |||
697 | snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint); | 710 | snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint); |
698 | err = snd_usb_add_audio_stream(chip, stream, fp); | 711 | err = snd_usb_add_audio_stream(chip, stream, fp); |
699 | if (err < 0) { | 712 | if (err < 0) { |