summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Henningsson <david.henningsson@canonical.com>2013-11-05 03:41:06 (GMT)
committerTakashi Iwai <tiwai@suse.de>2013-11-05 06:46:15 (GMT)
commit0dca01c37a68017fe7112b46bc4b48c927db18c6 (patch)
tree8da8f7085ec2369893331c8b859b1d37a58836ac
parent24eff328f65c8ef352c90b6adb7c2f39eb94205d (diff)
downloadlinux-fsl-qoriq-0dca01c37a68017fe7112b46bc4b48c927db18c6.tar.xz
ALSA: usb: supply channel maps even when wChannelConfig is unspecified
If wChannelconfig is given for some formats but not others, userspace might not be able to set the channel map. This is RFC because I'm not sure what the best behaviour is - to guess the channel map from the given number of channels (it's quite likely that one channel is MONO and two channels is FL FR), or just to supply UNKNOWN for all channels. But the complete lack of channel map for a format leads userspace to believe that the format is not available at all. Or am I misunderstanding how this should be used? Signed-off-by: David Henningsson <david.henningsson@canonical.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/usb/stream.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index c4339f9..b43b6ee 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,
const unsigned int *maps;
int c;
- if (!bits)
- return NULL;
if (channels > ARRAY_SIZE(chmap->map))
return NULL;
@@ -293,9 +291,19 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
maps = protocol == UAC_VERSION_2 ? uac2_maps : uac1_maps;
chmap->channels = channels;
c = 0;
- for (; bits && *maps; maps++, bits >>= 1) {
- if (bits & 1)
- chmap->map[c++] = *maps;
+
+ if (bits) {
+ for (; bits && *maps; maps++, bits >>= 1)
+ if (bits & 1)
+ chmap->map[c++] = *maps;
+ } else {
+ /* If we're missing wChannelConfig, then guess something
+ to make sure the channel map is not skipped entirely */
+ if (channels == 1)
+ chmap->map[c++] = SNDRV_CHMAP_MONO;
+ else
+ for (; c < channels && *maps; maps++)
+ chmap->map[c++] = *maps;
}
for (; c < channels; c++)