Loading sound/usb/format.c +38 −55 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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; } Loading @@ -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, Loading @@ -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", Loading @@ -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; } Loading Loading @@ -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. Loading sound/usb/quirks-table.h +1 −1 Original line number Diff line number Diff line Loading @@ -2203,7 +2203,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .ifnum = 1, .type = QUIRK_AUDIO_FIXED_ENDPOINT, .data = &(const struct audioformat) { .format = SNDRV_PCM_FORMAT_S24_3BE, .formats = SNDRV_PCM_FMTBIT_S24_3BE, .channels = 2, .iface = 1, .altsetting = 1, Loading Loading
sound/usb/format.c +38 −55 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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; } Loading @@ -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, Loading @@ -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", Loading @@ -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; } Loading Loading @@ -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. Loading
sound/usb/quirks-table.h +1 −1 Original line number Diff line number Diff line Loading @@ -2203,7 +2203,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .ifnum = 1, .type = QUIRK_AUDIO_FIXED_ENDPOINT, .data = &(const struct audioformat) { .format = SNDRV_PCM_FORMAT_S24_3BE, .formats = SNDRV_PCM_FMTBIT_S24_3BE, .channels = 2, .iface = 1, .altsetting = 1, Loading