diff options
Diffstat (limited to 'sound/usb/stream.c')
| -rw-r--r-- | sound/usb/stream.c | 83 | 
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);  | 
