diff options
Diffstat (limited to 'sound/usb/format.c')
| -rw-r--r-- | sound/usb/format.c | 164 | 
1 files changed, 90 insertions, 74 deletions
diff --git a/sound/usb/format.c b/sound/usb/format.c index 69148212aa7..8bcc87cf566 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -30,6 +30,7 @@  #include "helper.h"  #include "debug.h"  #include "clock.h" +#include "format.h"  /*   * parse the audio format type I descriptor @@ -42,13 +43,12 @@   */  static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,  				     struct audioformat *fp, -				     int format, void *_fmt, -				     int protocol) +				     unsigned int format, void *_fmt)  {  	int sample_width, sample_bytes; -	u64 pcm_formats; +	u64 pcm_formats = 0; -	switch (protocol) { +	switch (fp->protocol) {  	case UAC_VERSION_1:  	default: {  		struct uac_format_type_i_discrete_descriptor *fmt = _fmt; @@ -62,24 +62,30 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,  		struct uac_format_type_i_ext_descriptor *fmt = _fmt;  		sample_width = fmt->bBitResolution;  		sample_bytes = fmt->bSubslotSize; + +		if (format & UAC2_FORMAT_TYPE_I_RAW_DATA) +			pcm_formats |= SNDRV_PCM_FMTBIT_SPECIAL; +  		format <<= 1;  		break;  	}  	} -	pcm_formats = 0; - -	if (format == 0 || format == (1 << UAC_FORMAT_TYPE_I_UNDEFINED)) { +	if ((pcm_formats == 0) && +	    (format == 0 || format == (1 << UAC_FORMAT_TYPE_I_UNDEFINED))) {  		/* some devices don't define this correctly... */ -		snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n", -			    chip->dev->devnum, fp->iface, fp->altsetting); +		usb_audio_info(chip, "%u:%d : format type 0 is detected, processed as PCM\n", +			fp->iface, fp->altsetting);  		format = 1 << UAC_FORMAT_TYPE_I_PCM;  	}  	if (format & (1 << UAC_FORMAT_TYPE_I_PCM)) { -		if (sample_width > sample_bytes * 8) { -			snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n", -				   chip->dev->devnum, fp->iface, fp->altsetting, -				   sample_width, sample_bytes); +		if (chip->usb_id == USB_ID(0x0582, 0x0016) /* Edirol SD-90 */ && +		    sample_width == 24 && sample_bytes == 2) +			sample_bytes = 3; +		else if (sample_width > sample_bytes * 8) { +			usb_audio_info(chip, "%u:%d : sample bitwidth %d in over sample bytes %d\n", +				 fp->iface, fp->altsetting, +				 sample_width, sample_bytes);  		}  		/* check the format byte size */  		switch (sample_bytes) { @@ -102,9 +108,10 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,  			pcm_formats |= SNDRV_PCM_FMTBIT_S32_LE;  			break;  		default: -			snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n", -				   chip->dev->devnum, fp->iface, fp->altsetting, -				   sample_width, sample_bytes); +			usb_audio_info(chip, +				 "%u:%d : unsupported sample bitwidth %d in %d bytes\n", +				 fp->iface, fp->altsetting, +				 sample_width, sample_bytes);  			break;  		}  	} @@ -126,9 +133,13 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,  		pcm_formats |= SNDRV_PCM_FMTBIT_MU_LAW;  	}  	if (format & ~0x3f) { -		snd_printk(KERN_INFO "%d:%u:%d : unsupported format bits %#x\n", -			   chip->dev->devnum, fp->iface, fp->altsetting, format); +		usb_audio_info(chip, +			 "%u:%d : unsupported format bits %#x\n", +			 fp->iface, fp->altsetting, format);  	} + +	pcm_formats |= snd_usb_interface_dsd_format_quirks(chip, fp, sample_bytes); +  	return pcm_formats;  } @@ -149,9 +160,10 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof  	int nr_rates = fmt[offset];  	if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) { -		snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n", -				   chip->dev->devnum, fp->iface, fp->altsetting); -		return -1; +		usb_audio_err(chip, +			"%u:%d : invalid UAC_FORMAT_TYPE desc\n", +			fp->iface, fp->altsetting); +		return -EINVAL;  	}  	if (nr_rates) { @@ -162,8 +174,8 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof  		fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);  		if (fp->rate_table == NULL) { -			snd_printk(KERN_ERR "cannot malloc\n"); -			return -1; +			usb_audio_err(chip, "cannot malloc\n"); +			return -ENOMEM;  		}  		fp->nr_rates = 0; @@ -173,13 +185,17 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof  			if (!rate)  				continue;  			/* C-Media CM6501 mislabels its 96 kHz altsetting */ +			/* Terratec Aureon 7.1 USB C-Media 6206, too */  			if (rate == 48000 && nr_rates == 1 &&  			    (chip->usb_id == USB_ID(0x0d8c, 0x0201) || -			     chip->usb_id == USB_ID(0x0d8c, 0x0102)) && +			     chip->usb_id == USB_ID(0x0d8c, 0x0102) || +			     chip->usb_id == USB_ID(0x0ccd, 0x00b1)) &&  			    fp->altsetting == 5 && fp->maxpacksize == 392)  				rate = 96000; -			/* Creative VF0470 Live Cam reports 16 kHz instead of 8kHz */ -			if (rate == 16000 && chip->usb_id == USB_ID(0x041e, 0x4068)) +			/* Creative VF0420/VF0470 Live Cams report 16 kHz instead of 8kHz */ +			if (rate == 16000 && +			    (chip->usb_id == USB_ID(0x041e, 0x4064) || +			     chip->usb_id == USB_ID(0x041e, 0x4068)))  				rate = 8000;  			fp->rate_table[fp->nr_rates] = rate; @@ -192,7 +208,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof  		}  		if (!fp->nr_rates) {  			hwc_debug("All rates were zero. Skipping format!\n"); -			return -1; +			return -EINVAL;  		}  	} else {  		/* continuous rates */ @@ -209,7 +225,8 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof   * get to know how many sample rates we have to expect.   * Then fp->rate_table can be allocated and filled.   */ -static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets, +static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip, +					struct audioformat *fp, int nr_triplets,  					const unsigned char *data)  {  	int i, nr_rates = 0; @@ -220,7 +237,7 @@ static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,  		int min = combine_quad(&data[2 + 12 * i]);  		int max = combine_quad(&data[6 + 12 * i]);  		int res = combine_quad(&data[10 + 12 * i]); -		int rate; +		unsigned int rate;  		if ((max < 0) || (min < 0) || (res < 0) || (max < min))  			continue; @@ -247,6 +264,10 @@ static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,  			fp->rates |= snd_pcm_rate_to_rate_bit(rate);  			nr_rates++; +			if (nr_rates >= MAX_NR_RATES) { +				usb_audio_err(chip, "invalid uac2 rates\n"); +				break; +			}  			/* avoid endless loop */  			if (res == 0) @@ -267,10 +288,11 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,  	struct usb_device *dev = chip->dev;  	unsigned char tmp[2], *data;  	int nr_triplets, data_size, ret = 0; -	int clock = snd_usb_clock_find_source(chip, fp->clock); +	int clock = snd_usb_clock_find_source(chip, fp->clock, false);  	if (clock < 0) { -		snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n", +		dev_err(&dev->dev, +			"%s(): unable to find clock source (clock %d)\n",  				__func__, clock);  		goto err;  	} @@ -280,10 +302,11 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,  			      USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,  			      UAC2_CS_CONTROL_SAM_FREQ << 8,  			      snd_usb_ctrl_intf(chip) | (clock << 8), -			      tmp, sizeof(tmp), 1000); +			      tmp, sizeof(tmp));  	if (ret < 0) { -		snd_printk(KERN_ERR "%s(): unable to retrieve number of sample rates (clock %d)\n", +		dev_err(&dev->dev, +			"%s(): unable to retrieve number of sample rates (clock %d)\n",  				__func__, clock);  		goto err;  	} @@ -301,10 +324,11 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,  			      USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,  			      UAC2_CS_CONTROL_SAM_FREQ << 8,  			      snd_usb_ctrl_intf(chip) | (clock << 8), -			      data, data_size, 1000); +			      data, data_size);  	if (ret < 0) { -		snd_printk(KERN_ERR "%s(): unable to retrieve sample rate range (clock %d)\n", +		dev_err(&dev->dev, +			"%s(): unable to retrieve sample rate range (clock %d)\n",  				__func__, clock);  		ret = -EINVAL;  		goto err_free; @@ -315,7 +339,7 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,  	 * will have to deal with. */  	kfree(fp->rate_table);  	fp->rate_table = NULL; -	fp->nr_rates = parse_uac2_sample_rate_range(fp, nr_triplets, data); +	fp->nr_rates = parse_uac2_sample_rate_range(chip, fp, nr_triplets, data);  	if (fp->nr_rates == 0) {  		/* SNDRV_PCM_RATE_CONTINUOUS */ @@ -331,7 +355,7 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,  	/* Call the triplet parser again, but this time, fp->rate_table is  	 * allocated, so the rates will be stored */ -	parse_uac2_sample_rate_range(fp, nr_triplets, data); +	parse_uac2_sample_rate_range(chip, fp, nr_triplets, data);  err_free:  	kfree(data); @@ -343,13 +367,11 @@ err:   * parse the format type I and III descriptors   */  static int parse_audio_format_i(struct snd_usb_audio *chip, -				struct audioformat *fp, int format, -				struct uac_format_type_i_continuous_descriptor *fmt, -				struct usb_host_interface *iface) +				struct audioformat *fp, unsigned int format, +				struct uac_format_type_i_continuous_descriptor *fmt)  { -	struct usb_interface_descriptor *altsd = get_iface_desc(iface); -	int protocol = altsd->bInterfaceProtocol; -	int pcm_format, ret; +	snd_pcm_format_t pcm_format; +	int ret;  	if (fmt->bFormatType == UAC_FORMAT_TYPE_III) {  		/* FIXME: the format type is really IECxxx @@ -368,12 +390,11 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,  		default:  			pcm_format = SNDRV_PCM_FORMAT_S16_LE;  		} -		fp->formats = 1uLL << pcm_format; +		fp->formats = pcm_format_to_bits(pcm_format);  	} else { -		fp->formats = parse_audio_format_i_type(chip, fp, format, -							fmt, protocol); +		fp->formats = parse_audio_format_i_type(chip, fp, format, fmt);  		if (!fp->formats) -			return -1; +			return -EINVAL;  	}  	/* gather possible sample rates */ @@ -381,11 +402,8 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,  	 * proprietary class specific descriptor.  	 * audio class v2 uses class specific EP0 range requests for that.  	 */ -	switch (protocol) { +	switch (fp->protocol) {  	default: -		snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n", -			   chip->dev->devnum, fp->iface, fp->altsetting, protocol); -		/* fall through */  	case UAC_VERSION_1:  		fp->channels = fmt->bNrChannels;  		ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7); @@ -397,9 +415,10 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,  	}  	if (fp->channels < 1) { -		snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n", -			   chip->dev->devnum, fp->iface, fp->altsetting, fp->channels); -		return -1; +		usb_audio_err(chip, +			"%u:%d : invalid channels %d\n", +			fp->iface, fp->altsetting, fp->channels); +		return -EINVAL;  	}  	return ret; @@ -410,12 +429,9 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,   */  static int parse_audio_format_ii(struct snd_usb_audio *chip,  				 struct audioformat *fp, -				 int format, void *_fmt, -				 struct usb_host_interface *iface) +				 int format, void *_fmt)  {  	int brate, framesize, ret; -	struct usb_interface_descriptor *altsd = get_iface_desc(iface); -	int protocol = altsd->bInterfaceProtocol;  	switch (format) {  	case UAC_FORMAT_TYPE_II_AC3: @@ -427,24 +443,22 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,  		fp->formats = SNDRV_PCM_FMTBIT_MPEG;  		break;  	default: -		snd_printd(KERN_INFO "%d:%u:%d : unknown format tag %#x is detected.  processed as MPEG.\n", -			   chip->dev->devnum, fp->iface, fp->altsetting, format); +		usb_audio_info(chip, +			 "%u:%d : unknown format tag %#x is detected.  processed as MPEG.\n", +			 fp->iface, fp->altsetting, format);  		fp->formats = SNDRV_PCM_FMTBIT_MPEG;  		break;  	}  	fp->channels = 1; -	switch (protocol) { +	switch (fp->protocol) {  	default: -		snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n", -			   chip->dev->devnum, fp->iface, fp->altsetting, protocol); -		/* fall through */  	case UAC_VERSION_1: {  		struct uac_format_type_ii_discrete_descriptor *fmt = _fmt;  		brate = le16_to_cpu(fmt->wMaxBitRate);  		framesize = le16_to_cpu(fmt->wSamplesPerFrame); -		snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); +		usb_audio_info(chip, "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);  		fp->frame_size = framesize;  		ret = parse_audio_format_rates_v1(chip, fp, _fmt, 8); /* fmt[8..] sample rates */  		break; @@ -453,7 +467,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,  		struct uac_format_type_ii_ext_descriptor *fmt = _fmt;  		brate = le16_to_cpu(fmt->wMaxBitRate);  		framesize = le16_to_cpu(fmt->wSamplesPerFrame); -		snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); +		usb_audio_info(chip, "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);  		fp->frame_size = framesize;  		ret = parse_audio_format_rates_v2(chip, fp);  		break; @@ -463,24 +477,26 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,  	return ret;  } -int snd_usb_parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp, -			       int format, struct uac_format_type_i_continuous_descriptor *fmt, -			       int stream, struct usb_host_interface *iface) +int snd_usb_parse_audio_format(struct snd_usb_audio *chip, +			       struct audioformat *fp, unsigned int format, +			       struct uac_format_type_i_continuous_descriptor *fmt, +			       int stream)  {  	int err;  	switch (fmt->bFormatType) {  	case UAC_FORMAT_TYPE_I:  	case UAC_FORMAT_TYPE_III: -		err = parse_audio_format_i(chip, fp, format, fmt, iface); +		err = parse_audio_format_i(chip, fp, format, fmt);  		break;  	case UAC_FORMAT_TYPE_II: -		err = parse_audio_format_ii(chip, fp, format, fmt, iface); +		err = parse_audio_format_ii(chip, fp, format, fmt);  		break;  	default: -		snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", -			   chip->dev->devnum, fp->iface, fp->altsetting, -			   fmt->bFormatType); +		usb_audio_info(chip, +			 "%u:%d : format type %d is not supported yet\n", +			 fp->iface, fp->altsetting, +			 fmt->bFormatType);  		return -ENOTSUPP;  	}  	fp->fmt_type = fmt->bFormatType;  | 
