From e5779998bf8b70e48a6cc208c8b61b33bd6117ea Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 4 Mar 2010 19:46:13 +0100 Subject: ALSA: usb-audio: refactor code Clean up the usb audio driver by factoring out a lot of functions to separate files. Code for procfs, quirks, urbs, format parsers etc all got a new home now. Moved almost all special quirk handling to quirks.c and introduced new generic functions to handle them, so the exceptions do not pollute the whole driver. Renamed usbaudio.c to card.c because this is what it actually does now. Renamed usbmidi.c to midi.c for namespace clarity. Removed more things from usbaudio.h. The non-standard drivers were adopted accordingly. Signed-off-by: Daniel Mack Cc: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/format.c | 445 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 445 insertions(+) create mode 100644 sound/usb/format.c (limited to 'sound/usb/format.c') diff --git a/sound/usb/format.c b/sound/usb/format.c new file mode 100644 index 000000000000..cbfe0c23dbd6 --- /dev/null +++ b/sound/usb/format.c @@ -0,0 +1,445 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include + +#include +#include + +#include "usbaudio.h" +#include "card.h" +#include "quirks.h" +#include "helper.h" +#include "debug.h" + +/* + * parse the audio format type I descriptor + * and returns the corresponding pcm format + * + * @dev: usb device + * @fp: audioformat record + * @format: the format tag (wFormatTag) + * @fmt: the format type descriptor + */ +static int parse_audio_format_i_type(struct snd_usb_audio *chip, + struct audioformat *fp, + int format, void *_fmt, + int protocol) +{ + int pcm_format, i; + int sample_width, sample_bytes; + + switch (protocol) { + case UAC_VERSION_1: { + struct uac_format_type_i_discrete_descriptor *fmt = _fmt; + sample_width = fmt->bBitResolution; + sample_bytes = fmt->bSubframeSize; + break; + } + + case UAC_VERSION_2: { + struct uac_format_type_i_ext_descriptor *fmt = _fmt; + sample_width = fmt->bBitResolution; + sample_bytes = fmt->bSubslotSize; + + /* + * FIXME + * USB audio class v2 devices specify a bitmap of possible + * audio formats rather than one fix value. For now, we just + * pick one of them and report that as the only possible + * value for this setting. + * The bit allocation map is in fact compatible to the + * wFormatTag of the v1 AS streaming descriptors, which is why + * we can simply map the matrix. + */ + + for (i = 0; i < 5; i++) + if (format & (1UL << i)) { + format = i + 1; + break; + } + + break; + } + + default: + return -EINVAL; + } + + /* FIXME: correct endianess and sign? */ + pcm_format = -1; + + switch (format) { + case 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); + /* fall-through */ + case 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); + } + /* check the format byte size */ + switch (sample_bytes) { + case 1: + pcm_format = SNDRV_PCM_FORMAT_S8; + break; + case 2: + if (snd_usb_is_big_endian_format(chip, fp)) + pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */ + else + pcm_format = SNDRV_PCM_FORMAT_S16_LE; + break; + case 3: + if (snd_usb_is_big_endian_format(chip, fp)) + pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */ + else + pcm_format = SNDRV_PCM_FORMAT_S24_3LE; + break; + case 4: + pcm_format = SNDRV_PCM_FORMAT_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); + break; + } + break; + case UAC_FORMAT_TYPE_I_PCM8: + pcm_format = SNDRV_PCM_FORMAT_U8; + + /* Dallas DS4201 workaround: it advertises U8 format, but really + supports S8. */ + if (chip->usb_id == USB_ID(0x04fa, 0x4201)) + pcm_format = SNDRV_PCM_FORMAT_S8; + break; + case UAC_FORMAT_TYPE_I_IEEE_FLOAT: + pcm_format = SNDRV_PCM_FORMAT_FLOAT_LE; + break; + case UAC_FORMAT_TYPE_I_ALAW: + pcm_format = SNDRV_PCM_FORMAT_A_LAW; + break; + case UAC_FORMAT_TYPE_I_MULAW: + pcm_format = SNDRV_PCM_FORMAT_MU_LAW; + break; + default: + snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n", + chip->dev->devnum, fp->iface, fp->altsetting, format); + break; + } + return pcm_format; +} + + +/* + * parse the format descriptor and stores the possible sample rates + * on the audioformat table (audio class v1). + * + * @dev: usb device + * @fp: audioformat record + * @fmt: the format descriptor + * @offset: the start offset of descriptor pointing the rate type + * (7 for type I and II, 8 for type II) + */ +static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audioformat *fp, + unsigned char *fmt, int offset) +{ + 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; + } + + if (nr_rates) { + /* + * build the rate table and bitmap flags + */ + int r, idx; + + fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL); + if (fp->rate_table == NULL) { + snd_printk(KERN_ERR "cannot malloc\n"); + return -1; + } + + fp->nr_rates = 0; + fp->rate_min = fp->rate_max = 0; + for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) { + unsigned int rate = combine_triple(&fmt[idx]); + if (!rate) + continue; + /* C-Media CM6501 mislabels its 96 kHz altsetting */ + if (rate == 48000 && nr_rates == 1 && + (chip->usb_id == USB_ID(0x0d8c, 0x0201) || + chip->usb_id == USB_ID(0x0d8c, 0x0102)) && + 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)) + rate = 8000; + + fp->rate_table[fp->nr_rates] = rate; + if (!fp->rate_min || rate < fp->rate_min) + fp->rate_min = rate; + if (!fp->rate_max || rate > fp->rate_max) + fp->rate_max = rate; + fp->rates |= snd_pcm_rate_to_rate_bit(rate); + fp->nr_rates++; + } + if (!fp->nr_rates) { + hwc_debug("All rates were zero. Skipping format!\n"); + return -1; + } + } else { + /* continuous rates */ + fp->rates = SNDRV_PCM_RATE_CONTINUOUS; + fp->rate_min = combine_triple(&fmt[offset + 1]); + fp->rate_max = combine_triple(&fmt[offset + 4]); + } + return 0; +} + +/* + * parse the format descriptor and stores the possible sample rates + * on the audioformat table (audio class v2). + */ +static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, + struct audioformat *fp, + struct usb_host_interface *iface) +{ + struct usb_device *dev = chip->dev; + unsigned char tmp[2], *data; + int i, nr_rates, data_size, ret = 0; + + /* get the number of sample rates first by only fetching 2 bytes */ + ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, + 0x0100, chip->clock_id << 8, tmp, sizeof(tmp), 1000); + + if (ret < 0) { + snd_printk(KERN_ERR "unable to retrieve number of sample rates\n"); + goto err; + } + + nr_rates = (tmp[1] << 8) | tmp[0]; + data_size = 2 + 12 * nr_rates; + data = kzalloc(data_size, GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto err; + } + + /* now get the full information */ + ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, + 0x0100, chip->clock_id << 8, data, data_size, 1000); + + if (ret < 0) { + snd_printk(KERN_ERR "unable to retrieve sample rate range\n"); + ret = -EINVAL; + goto err_free; + } + + fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL); + if (!fp->rate_table) { + ret = -ENOMEM; + goto err_free; + } + + fp->nr_rates = 0; + fp->rate_min = fp->rate_max = 0; + + for (i = 0; i < nr_rates; i++) { + int rate = combine_quad(&data[2 + 12 * i]); + + fp->rate_table[fp->nr_rates] = rate; + if (!fp->rate_min || rate < fp->rate_min) + fp->rate_min = rate; + if (!fp->rate_max || rate > fp->rate_max) + fp->rate_max = rate; + fp->rates |= snd_pcm_rate_to_rate_bit(rate); + fp->nr_rates++; + } + +err_free: + kfree(data); +err: + return ret; +} + +/* + * parse the format type I and III descriptors + */ +static int parse_audio_format_i(struct snd_usb_audio *chip, + struct audioformat *fp, + int format, void *_fmt, + struct usb_host_interface *iface) +{ + struct usb_interface_descriptor *altsd = get_iface_desc(iface); + struct uac_format_type_i_discrete_descriptor *fmt = _fmt; + int protocol = altsd->bInterfaceProtocol; + int pcm_format, ret; + + if (fmt->bFormatType == UAC_FORMAT_TYPE_III) { + /* FIXME: the format type is really IECxxx + * but we give normal PCM format to get the existing + * apps working... + */ + switch (chip->usb_id) { + + case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ + if (chip->setup == 0x00 && + fp->altsetting == 6) + pcm_format = SNDRV_PCM_FORMAT_S16_BE; + else + pcm_format = SNDRV_PCM_FORMAT_S16_LE; + break; + default: + pcm_format = SNDRV_PCM_FORMAT_S16_LE; + } + } else { + pcm_format = parse_audio_format_i_type(chip, fp, format, fmt, protocol); + if (pcm_format < 0) + return -1; + } + + fp->format = pcm_format; + + /* gather possible sample rates */ + /* audio class v1 reports possible sample rates as part of the + * proprietary class specific descriptor. + * audio class v2 uses class specific EP0 range requests for that. + */ + switch (protocol) { + case UAC_VERSION_1: + fp->channels = fmt->bNrChannels; + ret = parse_audio_format_rates_v1(chip, fp, _fmt, 7); + break; + case UAC_VERSION_2: + /* fp->channels is already set in this case */ + ret = parse_audio_format_rates_v2(chip, fp, iface); + break; + } + + 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; + } + + return ret; +} + +/* + * parse the format type II descriptor + */ +static int parse_audio_format_ii(struct snd_usb_audio *chip, + struct audioformat *fp, + int format, void *_fmt, + struct usb_host_interface *iface) +{ + 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: + /* FIXME: there is no AC3 format defined yet */ + // fp->format = SNDRV_PCM_FORMAT_AC3; + fp->format = SNDRV_PCM_FORMAT_U8; /* temporarily hack to receive byte streams */ + break; + case UAC_FORMAT_TYPE_II_MPEG: + fp->format = SNDRV_PCM_FORMAT_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); + fp->format = SNDRV_PCM_FORMAT_MPEG; + break; + } + + fp->channels = 1; + + switch (protocol) { + 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); + fp->frame_size = framesize; + ret = parse_audio_format_rates_v1(chip, fp, _fmt, 8); /* fmt[8..] sample rates */ + break; + } + case UAC_VERSION_2: { + 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); + fp->frame_size = framesize; + ret = parse_audio_format_rates_v2(chip, fp, iface); + break; + } + } + + return ret; +} + +int snd_usb_parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp, + int format, unsigned char *fmt, int stream, + struct usb_host_interface *iface) +{ + int err; + + switch (fmt[3]) { + case UAC_FORMAT_TYPE_I: + case UAC_FORMAT_TYPE_III: + err = parse_audio_format_i(chip, fp, format, fmt, iface); + break; + case UAC_FORMAT_TYPE_II: + err = parse_audio_format_ii(chip, fp, format, fmt, iface); + 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[3]); + return -1; + } + fp->fmt_type = fmt[3]; + if (err < 0) + return err; +#if 1 + /* FIXME: temporary hack for extigy/audigy 2 nx/zs */ + /* extigy apparently supports sample rates other than 48k + * but not in ordinary way. so we enable only 48k atm. + */ + if (chip->usb_id == USB_ID(0x041e, 0x3000) || + chip->usb_id == USB_ID(0x041e, 0x3020) || + chip->usb_id == USB_ID(0x041e, 0x3061)) { + if (fmt[3] == UAC_FORMAT_TYPE_I && + fp->rates != SNDRV_PCM_RATE_48000 && + fp->rates != SNDRV_PCM_RATE_96000) + return -1; + } +#endif + return 0; +} + -- cgit From 015eb0b08150c6fef843efe22609589ead3d4fb8 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 4 Mar 2010 19:46:15 +0100 Subject: ALSA: usb-audio: use a format bitmask per alternate setting In preparation for USB audio 2.0 support, change the audioformat structure so that it uses a bitmask to specify possible formats. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/format.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound/usb/format.c') diff --git a/sound/usb/format.c b/sound/usb/format.c index cbfe0c23dbd6..87f07f042c63 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -323,7 +323,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, return -1; } - fp->format = pcm_format; + fp->formats = 1uLL << pcm_format; /* gather possible sample rates */ /* audio class v1 reports possible sample rates as part of the @@ -365,16 +365,16 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, switch (format) { case UAC_FORMAT_TYPE_II_AC3: /* FIXME: there is no AC3 format defined yet */ - // fp->format = SNDRV_PCM_FORMAT_AC3; - fp->format = SNDRV_PCM_FORMAT_U8; /* temporarily hack to receive byte streams */ + // fp->formats = SNDRV_PCM_FMTBIT_AC3; + fp->formats = SNDRV_PCM_FMTBIT_U8; /* temporary hack to receive byte streams */ break; case UAC_FORMAT_TYPE_II_MPEG: - fp->format = SNDRV_PCM_FORMAT_MPEG; + 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); - fp->format = SNDRV_PCM_FORMAT_MPEG; + fp->formats = SNDRV_PCM_FMTBIT_MPEG; break; } -- cgit From 29088fef3e3f62147c1dd53d764da4f04bf3188d Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 4 Mar 2010 19:46:16 +0100 Subject: ALSA: usb-audio: support multiple formats with audio class v2 devices Change the parser to correctly handle v2 descriptors with multiple format bits set. Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/format.c | 93 ++++++++++++++++++++++-------------------------------- 1 file changed, 38 insertions(+), 55 deletions(-) (limited to 'sound/usb/format.c') diff --git a/sound/usb/format.c b/sound/usb/format.c index 87f07f042c63..b613e0aaeb63 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -37,19 +37,20 @@ * @format: the format tag (wFormatTag) * @fmt: the format type descriptor */ -static int parse_audio_format_i_type(struct snd_usb_audio *chip, +static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, struct audioformat *fp, int format, void *_fmt, int protocol) { - int pcm_format, i; int sample_width, sample_bytes; + u64 pcm_formats; switch (protocol) { case UAC_VERSION_1: { struct uac_format_type_i_discrete_descriptor *fmt = _fmt; sample_width = fmt->bBitResolution; sample_bytes = fmt->bSubframeSize; + format = 1 << format; break; } @@ -57,24 +58,7 @@ static int 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; - - /* - * FIXME - * USB audio class v2 devices specify a bitmap of possible - * audio formats rather than one fix value. For now, we just - * pick one of them and report that as the only possible - * value for this setting. - * The bit allocation map is in fact compatible to the - * wFormatTag of the v1 AS streaming descriptors, which is why - * we can simply map the matrix. - */ - - for (i = 0; i < 5; i++) - if (format & (1UL << i)) { - format = i + 1; - break; - } - + format <<= 1; break; } @@ -82,15 +66,15 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip, return -EINVAL; } - /* FIXME: correct endianess and sign? */ - pcm_format = -1; + pcm_formats = 0; - switch (format) { - case UAC_FORMAT_TYPE_I_UNDEFINED: /* some devices don't define this correctly... */ + if (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); - /* fall-through */ - case UAC_FORMAT_TYPE_I_PCM: + 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, @@ -99,22 +83,22 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip, /* check the format byte size */ switch (sample_bytes) { case 1: - pcm_format = SNDRV_PCM_FORMAT_S8; + pcm_formats |= SNDRV_PCM_FMTBIT_S8; break; case 2: if (snd_usb_is_big_endian_format(chip, fp)) - pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */ + pcm_formats |= SNDRV_PCM_FMTBIT_S16_BE; /* grrr, big endian!! */ else - pcm_format = SNDRV_PCM_FORMAT_S16_LE; + pcm_formats |= SNDRV_PCM_FMTBIT_S16_LE; break; case 3: if (snd_usb_is_big_endian_format(chip, fp)) - pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */ + pcm_formats |= SNDRV_PCM_FMTBIT_S24_3BE; /* grrr, big endian!! */ else - pcm_format = SNDRV_PCM_FORMAT_S24_3LE; + pcm_formats |= SNDRV_PCM_FMTBIT_S24_3LE; break; case 4: - pcm_format = SNDRV_PCM_FORMAT_S32_LE; + pcm_formats |= SNDRV_PCM_FMTBIT_S32_LE; break; default: snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n", @@ -122,30 +106,29 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip, sample_width, sample_bytes); break; } - break; - case UAC_FORMAT_TYPE_I_PCM8: - pcm_format = SNDRV_PCM_FORMAT_U8; - + } + if (format & (1 << UAC_FORMAT_TYPE_I_PCM8)) { /* Dallas DS4201 workaround: it advertises U8 format, but really supports S8. */ if (chip->usb_id == USB_ID(0x04fa, 0x4201)) - pcm_format = SNDRV_PCM_FORMAT_S8; - break; - case UAC_FORMAT_TYPE_I_IEEE_FLOAT: - pcm_format = SNDRV_PCM_FORMAT_FLOAT_LE; - break; - case UAC_FORMAT_TYPE_I_ALAW: - pcm_format = SNDRV_PCM_FORMAT_A_LAW; - break; - case UAC_FORMAT_TYPE_I_MULAW: - pcm_format = SNDRV_PCM_FORMAT_MU_LAW; - break; - default: - snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n", + pcm_formats |= SNDRV_PCM_FMTBIT_S8; + else + pcm_formats |= SNDRV_PCM_FMTBIT_U8; + } + if (format & (1 << UAC_FORMAT_TYPE_I_IEEE_FLOAT)) { + pcm_formats |= SNDRV_PCM_FMTBIT_FLOAT_LE; + } + if (format & (1 << UAC_FORMAT_TYPE_I_ALAW)) { + pcm_formats |= SNDRV_PCM_FMTBIT_A_LAW; + } + if (format & (1 << UAC_FORMAT_TYPE_I_MULAW)) { + 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); - break; } - return pcm_format; + return pcm_formats; } @@ -317,14 +300,14 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, default: pcm_format = SNDRV_PCM_FORMAT_S16_LE; } + fp->formats = 1uLL << pcm_format; } else { - pcm_format = parse_audio_format_i_type(chip, fp, format, fmt, protocol); - if (pcm_format < 0) + fp->formats = parse_audio_format_i_type(chip, fp, format, + fmt, protocol); + if (!fp->formats) return -1; } - fp->formats = 1uLL << pcm_format; - /* gather possible sample rates */ /* audio class v1 reports possible sample rates as part of the * proprietary class specific descriptor. -- cgit From 7e847894039d7590321de306fca2b1ae58662f29 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 11 Mar 2010 21:13:20 +0100 Subject: linux/usb/audio.h: split header - Split the audio.h file in two to clearly denote the differences between the standards. - Add many more defines to audio-v2.h. Most of them are not currently used. - Replaced a magic value with a proper define Signed-off-by: Daniel Mack Acked-by: Greg Kroah-Hartman Cc: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/format.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/usb/format.c') diff --git a/sound/usb/format.c b/sound/usb/format.c index b613e0aaeb63..0e04efe9551e 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include -- cgit From 45d760567a7d773237b8996584a4ae0440d5e369 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 11 Mar 2010 21:13:21 +0100 Subject: ALSA: usb-mixer: use defines from audio.h No need for the private enum. Signed-off-by: Daniel Mack Cc: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/format.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound/usb/format.c') diff --git a/sound/usb/format.c b/sound/usb/format.c index 0e04efe9551e..fcadedd94543 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -218,7 +218,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, /* get the number of sample rates first by only fetching 2 bytes */ ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, - 0x0100, chip->clock_id << 8, tmp, sizeof(tmp), 1000); + UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8, + tmp, sizeof(tmp), 1000); if (ret < 0) { snd_printk(KERN_ERR "unable to retrieve number of sample rates\n"); @@ -236,7 +237,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, /* now get the full information */ ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, - 0x0100, chip->clock_id << 8, data, data_size, 1000); + UAC2_CS_CONTROL_SAM_FREQ << 8, chip->clock_id << 8, + data, data_size, 1000); if (ret < 0) { snd_printk(KERN_ERR "unable to retrieve sample rate range\n"); -- cgit From 36db0456582484aa78809376f1e41ec2873fc9d5 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 29 Mar 2010 16:02:50 +1100 Subject: ALSA: usb - use of kmalloc/kfree requires the include of slab.h Signed-off-by: Stephen Rothwell Signed-off-by: Takashi Iwai --- sound/usb/format.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/usb/format.c') diff --git a/sound/usb/format.c b/sound/usb/format.c index fcadedd94543..b87cf87c4e7b 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -16,6 +16,7 @@ */ #include +#include #include #include #include -- cgit