aboutsummaryrefslogtreecommitdiff
path: root/sound/usb/stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/stream.c')
-rw-r--r--sound/usb/stream.c83
1 files changed, 51 insertions, 32 deletions
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index c4339f97226..310a3822d2b 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -273,16 +273,14 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
SNDRV_CHMAP_TSL, /* top side left */
SNDRV_CHMAP_TSR, /* top side right */
SNDRV_CHMAP_BC, /* bottom center */
- SNDRV_CHMAP_BLC, /* bottom left center */
- SNDRV_CHMAP_BRC, /* bottom right center */
+ SNDRV_CHMAP_RLC, /* back left of center */
+ SNDRV_CHMAP_RRC, /* back right of center */
0 /* terminator */
};
struct snd_pcm_chmap_elem *chmap;
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++)
@@ -403,10 +411,9 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
if (!csep || csep->bLength < 7 ||
csep->bDescriptorSubtype != UAC_EP_GENERAL) {
- snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
- " class specific endpoint descriptor\n",
- chip->dev->devnum, iface_no,
- altsd->bAlternateSetting);
+ usb_audio_warn(chip,
+ "%u:%d : no or invalid class specific endpoint descriptor\n",
+ iface_no, altsd->bAlternateSetting);
return 0;
}
@@ -525,8 +532,8 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
/* get audio formats */
switch (protocol) {
default:
- snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n",
- dev->devnum, iface_no, altno, protocol);
+ dev_dbg(&dev->dev, "%u:%d: unknown interface protocol %#02x, assuming v1\n",
+ iface_no, altno, protocol);
protocol = UAC_VERSION_1;
/* fall through */
@@ -536,14 +543,16 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
struct uac_input_terminal_descriptor *iterm;
if (!as) {
- snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
- dev->devnum, iface_no, altno);
+ dev_err(&dev->dev,
+ "%u:%d : UAC_AS_GENERAL descriptor not found\n",
+ iface_no, altno);
continue;
}
if (as->bLength < sizeof(*as)) {
- snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
- dev->devnum, iface_no, altno);
+ dev_err(&dev->dev,
+ "%u:%d : invalid UAC_AS_GENERAL desc\n",
+ iface_no, altno);
continue;
}
@@ -566,19 +575,22 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
if (!as) {
- snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
- dev->devnum, iface_no, altno);
+ dev_err(&dev->dev,
+ "%u:%d : UAC_AS_GENERAL descriptor not found\n",
+ iface_no, altno);
continue;
}
if (as->bLength < sizeof(*as)) {
- snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
- dev->devnum, iface_no, altno);
+ dev_err(&dev->dev,
+ "%u:%d : invalid UAC_AS_GENERAL desc\n",
+ iface_no, altno);
continue;
}
num_channels = as->bNrChannels;
format = le32_to_cpu(as->bmFormats);
+ chconfig = le32_to_cpu(as->bmChannelConfig);
/* lookup the terminal associated to this interface
* to extract the clock */
@@ -586,7 +598,8 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
as->bTerminalLink);
if (input_term) {
clock = input_term->bCSourceID;
- chconfig = le32_to_cpu(input_term->bmChannelConfig);
+ if (!chconfig && (num_channels == input_term->bNrChannels))
+ chconfig = le32_to_cpu(input_term->bmChannelConfig);
break;
}
@@ -597,8 +610,9 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
break;
}
- snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n",
- dev->devnum, iface_no, altno, as->bTerminalLink);
+ dev_err(&dev->dev,
+ "%u:%d : bogus bTerminalLink %d\n",
+ iface_no, altno, as->bTerminalLink);
continue;
}
}
@@ -606,14 +620,16 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
/* get format type */
fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE);
if (!fmt) {
- snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n",
- dev->devnum, iface_no, altno);
+ dev_err(&dev->dev,
+ "%u:%d : no UAC_FORMAT_TYPE desc\n",
+ iface_no, altno);
continue;
}
if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) {
- snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
- dev->devnum, iface_no, altno);
+ dev_err(&dev->dev,
+ "%u:%d : invalid UAC_FORMAT_TYPE desc\n",
+ iface_no, altno);
continue;
}
@@ -634,7 +650,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
fp = kzalloc(sizeof(*fp), GFP_KERNEL);
if (! fp) {
- snd_printk(KERN_ERR "cannot malloc\n");
+ dev_err(&dev->dev, "cannot malloc\n");
return -ENOMEM;
}
@@ -652,7 +668,6 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
* (fp->maxpacksize & 0x7ff);
fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
fp->clock = clock;
- fp->chmap = convert_chmap(num_channels, chconfig, protocol);
/* some quirks for attributes here */
@@ -688,13 +703,17 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
/* ok, let's parse further... */
if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream) < 0) {
kfree(fp->rate_table);
- kfree(fp->chmap);
kfree(fp);
fp = NULL;
continue;
}
- snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
+ /* Create chmap */
+ if (fp->channels != num_channels)
+ chconfig = 0;
+ fp->chmap = convert_chmap(fp->channels, chconfig, protocol);
+
+ dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint);
err = snd_usb_add_audio_stream(chip, stream, fp);
if (err < 0) {
kfree(fp->rate_table);