format.c (015eb0b08150c6fef843efe22609589ead3d4fb8) format.c (29088fef3e3f62147c1dd53d764da4f04bf3188d)
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of

--- 23 unchanged lines hidden (view full) ---

32 * parse the audio format type I descriptor
33 * and returns the corresponding pcm format
34 *
35 * @dev: usb device
36 * @fp: audioformat record
37 * @format: the format tag (wFormatTag)
38 * @fmt: the format type descriptor
39 */
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of

--- 23 unchanged lines hidden (view full) ---

32 * parse the audio format type I descriptor
33 * and returns the corresponding pcm format
34 *
35 * @dev: usb device
36 * @fp: audioformat record
37 * @format: the format tag (wFormatTag)
38 * @fmt: the format type descriptor
39 */
40static int parse_audio_format_i_type(struct snd_usb_audio *chip,
40static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
41 struct audioformat *fp,
42 int format, void *_fmt,
43 int protocol)
44{
41 struct audioformat *fp,
42 int format, void *_fmt,
43 int protocol)
44{
45 int pcm_format, i;
46 int sample_width, sample_bytes;
45 int sample_width, sample_bytes;
46 u64 pcm_formats;
47
48 switch (protocol) {
49 case UAC_VERSION_1: {
50 struct uac_format_type_i_discrete_descriptor *fmt = _fmt;
51 sample_width = fmt->bBitResolution;
52 sample_bytes = fmt->bSubframeSize;
47
48 switch (protocol) {
49 case UAC_VERSION_1: {
50 struct uac_format_type_i_discrete_descriptor *fmt = _fmt;
51 sample_width = fmt->bBitResolution;
52 sample_bytes = fmt->bSubframeSize;
53 format = 1 << format;
53 break;
54 }
55
56 case UAC_VERSION_2: {
57 struct uac_format_type_i_ext_descriptor *fmt = _fmt;
58 sample_width = fmt->bBitResolution;
59 sample_bytes = fmt->bSubslotSize;
54 break;
55 }
56
57 case UAC_VERSION_2: {
58 struct uac_format_type_i_ext_descriptor *fmt = _fmt;
59 sample_width = fmt->bBitResolution;
60 sample_bytes = fmt->bSubslotSize;
60
61 /*
62 * FIXME
63 * USB audio class v2 devices specify a bitmap of possible
64 * audio formats rather than one fix value. For now, we just
65 * pick one of them and report that as the only possible
66 * value for this setting.
67 * The bit allocation map is in fact compatible to the
68 * wFormatTag of the v1 AS streaming descriptors, which is why
69 * we can simply map the matrix.
70 */
71
72 for (i = 0; i < 5; i++)
73 if (format & (1UL << i)) {
74 format = i + 1;
75 break;
76 }
77
61 format <<= 1;
78 break;
79 }
80
81 default:
82 return -EINVAL;
83 }
84
62 break;
63 }
64
65 default:
66 return -EINVAL;
67 }
68
85 /* FIXME: correct endianess and sign? */
86 pcm_format = -1;
69 pcm_formats = 0;
87
70
88 switch (format) {
89 case UAC_FORMAT_TYPE_I_UNDEFINED: /* some devices don't define this correctly... */
71 if (format == 0 || format == (1 << UAC_FORMAT_TYPE_I_UNDEFINED)) {
72 /* some devices don't define this correctly... */
90 snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n",
91 chip->dev->devnum, fp->iface, fp->altsetting);
73 snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n",
74 chip->dev->devnum, fp->iface, fp->altsetting);
92 /* fall-through */
93 case UAC_FORMAT_TYPE_I_PCM:
75 format = 1 << UAC_FORMAT_TYPE_I_PCM;
76 }
77 if (format & (1 << UAC_FORMAT_TYPE_I_PCM)) {
94 if (sample_width > sample_bytes * 8) {
95 snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n",
96 chip->dev->devnum, fp->iface, fp->altsetting,
97 sample_width, sample_bytes);
98 }
99 /* check the format byte size */
100 switch (sample_bytes) {
101 case 1:
78 if (sample_width > sample_bytes * 8) {
79 snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n",
80 chip->dev->devnum, fp->iface, fp->altsetting,
81 sample_width, sample_bytes);
82 }
83 /* check the format byte size */
84 switch (sample_bytes) {
85 case 1:
102 pcm_format = SNDRV_PCM_FORMAT_S8;
86 pcm_formats |= SNDRV_PCM_FMTBIT_S8;
103 break;
104 case 2:
105 if (snd_usb_is_big_endian_format(chip, fp))
87 break;
88 case 2:
89 if (snd_usb_is_big_endian_format(chip, fp))
106 pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */
90 pcm_formats |= SNDRV_PCM_FMTBIT_S16_BE; /* grrr, big endian!! */
107 else
91 else
108 pcm_format = SNDRV_PCM_FORMAT_S16_LE;
92 pcm_formats |= SNDRV_PCM_FMTBIT_S16_LE;
109 break;
110 case 3:
111 if (snd_usb_is_big_endian_format(chip, fp))
93 break;
94 case 3:
95 if (snd_usb_is_big_endian_format(chip, fp))
112 pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */
96 pcm_formats |= SNDRV_PCM_FMTBIT_S24_3BE; /* grrr, big endian!! */
113 else
97 else
114 pcm_format = SNDRV_PCM_FORMAT_S24_3LE;
98 pcm_formats |= SNDRV_PCM_FMTBIT_S24_3LE;
115 break;
116 case 4:
99 break;
100 case 4:
117 pcm_format = SNDRV_PCM_FORMAT_S32_LE;
101 pcm_formats |= SNDRV_PCM_FMTBIT_S32_LE;
118 break;
119 default:
120 snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n",
121 chip->dev->devnum, fp->iface, fp->altsetting,
122 sample_width, sample_bytes);
123 break;
124 }
102 break;
103 default:
104 snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n",
105 chip->dev->devnum, fp->iface, fp->altsetting,
106 sample_width, sample_bytes);
107 break;
108 }
125 break;
126 case UAC_FORMAT_TYPE_I_PCM8:
127 pcm_format = SNDRV_PCM_FORMAT_U8;
128
109 }
110 if (format & (1 << UAC_FORMAT_TYPE_I_PCM8)) {
129 /* Dallas DS4201 workaround: it advertises U8 format, but really
130 supports S8. */
131 if (chip->usb_id == USB_ID(0x04fa, 0x4201))
111 /* Dallas DS4201 workaround: it advertises U8 format, but really
112 supports S8. */
113 if (chip->usb_id == USB_ID(0x04fa, 0x4201))
132 pcm_format = SNDRV_PCM_FORMAT_S8;
133 break;
134 case UAC_FORMAT_TYPE_I_IEEE_FLOAT:
135 pcm_format = SNDRV_PCM_FORMAT_FLOAT_LE;
136 break;
137 case UAC_FORMAT_TYPE_I_ALAW:
138 pcm_format = SNDRV_PCM_FORMAT_A_LAW;
139 break;
140 case UAC_FORMAT_TYPE_I_MULAW:
141 pcm_format = SNDRV_PCM_FORMAT_MU_LAW;
142 break;
143 default:
144 snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n",
114 pcm_formats |= SNDRV_PCM_FMTBIT_S8;
115 else
116 pcm_formats |= SNDRV_PCM_FMTBIT_U8;
117 }
118 if (format & (1 << UAC_FORMAT_TYPE_I_IEEE_FLOAT)) {
119 pcm_formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
120 }
121 if (format & (1 << UAC_FORMAT_TYPE_I_ALAW)) {
122 pcm_formats |= SNDRV_PCM_FMTBIT_A_LAW;
123 }
124 if (format & (1 << UAC_FORMAT_TYPE_I_MULAW)) {
125 pcm_formats |= SNDRV_PCM_FMTBIT_MU_LAW;
126 }
127 if (format & ~0x3f) {
128 snd_printk(KERN_INFO "%d:%u:%d : unsupported format bits %#x\n",
145 chip->dev->devnum, fp->iface, fp->altsetting, format);
129 chip->dev->devnum, fp->iface, fp->altsetting, format);
146 break;
147 }
130 }
148 return pcm_format;
131 return pcm_formats;
149}
150
151
152/*
153 * parse the format descriptor and stores the possible sample rates
154 * on the audioformat table (audio class v1).
155 *
156 * @dev: usb device

--- 155 unchanged lines hidden (view full) ---

312 fp->altsetting == 6)
313 pcm_format = SNDRV_PCM_FORMAT_S16_BE;
314 else
315 pcm_format = SNDRV_PCM_FORMAT_S16_LE;
316 break;
317 default:
318 pcm_format = SNDRV_PCM_FORMAT_S16_LE;
319 }
132}
133
134
135/*
136 * parse the format descriptor and stores the possible sample rates
137 * on the audioformat table (audio class v1).
138 *
139 * @dev: usb device

--- 155 unchanged lines hidden (view full) ---

295 fp->altsetting == 6)
296 pcm_format = SNDRV_PCM_FORMAT_S16_BE;
297 else
298 pcm_format = SNDRV_PCM_FORMAT_S16_LE;
299 break;
300 default:
301 pcm_format = SNDRV_PCM_FORMAT_S16_LE;
302 }
303 fp->formats = 1uLL << pcm_format;
320 } else {
304 } else {
321 pcm_format = parse_audio_format_i_type(chip, fp, format, fmt, protocol);
322 if (pcm_format < 0)
305 fp->formats = parse_audio_format_i_type(chip, fp, format,
306 fmt, protocol);
307 if (!fp->formats)
323 return -1;
324 }
325
308 return -1;
309 }
310
326 fp->formats = 1uLL << pcm_format;
327
328 /* gather possible sample rates */
329 /* audio class v1 reports possible sample rates as part of the
330 * proprietary class specific descriptor.
331 * audio class v2 uses class specific EP0 range requests for that.
332 */
333 switch (protocol) {
334 case UAC_VERSION_1:
335 fp->channels = fmt->bNrChannels;

--- 110 unchanged lines hidden ---
311 /* gather possible sample rates */
312 /* audio class v1 reports possible sample rates as part of the
313 * proprietary class specific descriptor.
314 * audio class v2 uses class specific EP0 range requests for that.
315 */
316 switch (protocol) {
317 case UAC_VERSION_1:
318 fp->channels = fmt->bNrChannels;

--- 110 unchanged lines hidden ---