aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/stream.c')
-rw-r--r--sound/usb/stream.c230
1 files changed, 225 insertions, 5 deletions
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 1de0c8c002a8..ad181d538bd9 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -23,6 +23,8 @@
23 23
24#include <sound/core.h> 24#include <sound/core.h>
25#include <sound/pcm.h> 25#include <sound/pcm.h>
26#include <sound/control.h>
27#include <sound/tlv.h>
26 28
27#include "usbaudio.h" 29#include "usbaudio.h"
28#include "card.h" 30#include "card.h"
@@ -47,6 +49,7 @@ static void free_substream(struct snd_usb_substream *subs)
47 list_for_each_safe(p, n, &subs->fmt_list) { 49 list_for_each_safe(p, n, &subs->fmt_list) {
48 struct audioformat *fp = list_entry(p, struct audioformat, list); 50 struct audioformat *fp = list_entry(p, struct audioformat, list);
49 kfree(fp->rate_table); 51 kfree(fp->rate_table);
52 kfree(fp->chmap);
50 kfree(fp); 53 kfree(fp);
51 } 54 }
52 kfree(subs->rate_list.list); 55 kfree(subs->rate_list.list);
@@ -99,6 +102,206 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,
99 subs->num_formats++; 102 subs->num_formats++;
100 subs->fmt_type = fp->fmt_type; 103 subs->fmt_type = fp->fmt_type;
101 subs->ep_num = fp->endpoint; 104 subs->ep_num = fp->endpoint;
105 if (fp->channels > subs->channels_max)
106 subs->channels_max = fp->channels;
107}
108
109/* kctl callbacks for usb-audio channel maps */
110static int usb_chmap_ctl_info(struct snd_kcontrol *kcontrol,
111 struct snd_ctl_elem_info *uinfo)
112{
113 struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
114 struct snd_usb_substream *subs = info->private_data;
115
116 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
117 uinfo->count = subs->channels_max;
118 uinfo->value.integer.min = 0;
119 uinfo->value.integer.max = SNDRV_CHMAP_LAST;
120 return 0;
121}
122
123/* check whether a duplicated entry exists in the audiofmt list */
124static bool have_dup_chmap(struct snd_usb_substream *subs,
125 struct audioformat *fp)
126{
127 struct list_head *p;
128
129 for (p = fp->list.prev; p != &subs->fmt_list; p = p->prev) {
130 struct audioformat *prev;
131 prev = list_entry(p, struct audioformat, list);
132 if (prev->chmap &&
133 !memcmp(prev->chmap, fp->chmap, sizeof(*fp->chmap)))
134 return true;
135 }
136 return false;
137}
138
139static int usb_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
140 unsigned int size, unsigned int __user *tlv)
141{
142 struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
143 struct snd_usb_substream *subs = info->private_data;
144 struct audioformat *fp;
145 unsigned int __user *dst;
146 int count = 0;
147
148 if (size < 8)
149 return -ENOMEM;
150 if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv))
151 return -EFAULT;
152 size -= 8;
153 dst = tlv + 2;
154 list_for_each_entry(fp, &subs->fmt_list, list) {
155 int i, ch_bytes;
156
157 if (!fp->chmap)
158 continue;
159 if (have_dup_chmap(subs, fp))
160 continue;
161 /* copy the entry */
162 ch_bytes = fp->chmap->channels * 4;
163 if (size < 8 + ch_bytes)
164 return -ENOMEM;
165 if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) ||
166 put_user(ch_bytes, dst + 1))
167 return -EFAULT;
168 dst += 2;
169 for (i = 0; i < fp->chmap->channels; i++, dst++) {
170 if (put_user(fp->chmap->map[i], dst))
171 return -EFAULT;
172 }
173
174 count += 8 + ch_bytes;
175 size -= 8 + ch_bytes;
176 }
177 if (put_user(count, tlv + 1))
178 return -EFAULT;
179 return 0;
180}
181
182static int usb_chmap_ctl_get(struct snd_kcontrol *kcontrol,
183 struct snd_ctl_elem_value *ucontrol)
184{
185 struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
186 struct snd_usb_substream *subs = info->private_data;
187 struct snd_pcm_chmap_elem *chmap = NULL;
188 int i;
189
190 memset(ucontrol->value.integer.value, 0,
191 sizeof(ucontrol->value.integer.value));
192 if (subs->cur_audiofmt)
193 chmap = subs->cur_audiofmt->chmap;
194 if (chmap) {
195 for (i = 0; i < chmap->channels; i++)
196 ucontrol->value.integer.value[i] = chmap->map[i];
197 }
198 return 0;
199}
200
201/* create a chmap kctl assigned to the given USB substream */
202static int add_chmap(struct snd_pcm *pcm, int stream,
203 struct snd_usb_substream *subs)
204{
205 struct audioformat *fp;
206 struct snd_pcm_chmap *chmap;
207 struct snd_kcontrol *kctl;
208 int err;
209
210 list_for_each_entry(fp, &subs->fmt_list, list)
211 if (fp->chmap)
212 goto ok;
213 /* no chmap is found */
214 return 0;
215
216 ok:
217 err = snd_pcm_add_chmap_ctls(pcm, stream, NULL, 0, 0, &chmap);
218 if (err < 0)
219 return err;
220
221 /* override handlers */
222 chmap->private_data = subs;
223 kctl = chmap->kctl;
224 kctl->info = usb_chmap_ctl_info;
225 kctl->get = usb_chmap_ctl_get;
226 kctl->tlv.c = usb_chmap_ctl_tlv;
227
228 return 0;
229}
230
231/* convert from USB ChannelConfig bits to ALSA chmap element */
232static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
233 int protocol)
234{
235 static unsigned int uac1_maps[] = {
236 SNDRV_CHMAP_FL, /* left front */
237 SNDRV_CHMAP_FR, /* right front */
238 SNDRV_CHMAP_FC, /* center front */
239 SNDRV_CHMAP_LFE, /* LFE */
240 SNDRV_CHMAP_SL, /* left surround */
241 SNDRV_CHMAP_SR, /* right surround */
242 SNDRV_CHMAP_FLC, /* left of center */
243 SNDRV_CHMAP_FRC, /* right of center */
244 SNDRV_CHMAP_RC, /* surround */
245 SNDRV_CHMAP_SL, /* side left */
246 SNDRV_CHMAP_SR, /* side right */
247 SNDRV_CHMAP_TC, /* top */
248 0 /* terminator */
249 };
250 static unsigned int uac2_maps[] = {
251 SNDRV_CHMAP_FL, /* front left */
252 SNDRV_CHMAP_FR, /* front right */
253 SNDRV_CHMAP_FC, /* front center */
254 SNDRV_CHMAP_LFE, /* LFE */
255 SNDRV_CHMAP_RL, /* back left */
256 SNDRV_CHMAP_RR, /* back right */
257 SNDRV_CHMAP_FLC, /* front left of center */
258 SNDRV_CHMAP_FRC, /* front right of center */
259 SNDRV_CHMAP_RC, /* back center */
260 SNDRV_CHMAP_SL, /* side left */
261 SNDRV_CHMAP_SR, /* side right */
262 SNDRV_CHMAP_TC, /* top center */
263 SNDRV_CHMAP_TFL, /* top front left */
264 SNDRV_CHMAP_TFC, /* top front center */
265 SNDRV_CHMAP_TFR, /* top front right */
266 SNDRV_CHMAP_TRL, /* top back left */
267 SNDRV_CHMAP_TRC, /* top back center */
268 SNDRV_CHMAP_TRR, /* top back right */
269 SNDRV_CHMAP_TFLC, /* top front left of center */
270 SNDRV_CHMAP_TFRC, /* top front right of center */
271 SNDRV_CHMAP_LLFE, /* left LFE */
272 SNDRV_CHMAP_RLFE, /* right LFE */
273 SNDRV_CHMAP_TSL, /* top side left */
274 SNDRV_CHMAP_TSR, /* top side right */
275 SNDRV_CHMAP_BC, /* bottom center */
276 SNDRV_CHMAP_BLC, /* bottom left center */
277 SNDRV_CHMAP_BRC, /* bottom right center */
278 0 /* terminator */
279 };
280 struct snd_pcm_chmap_elem *chmap;
281 const unsigned int *maps;
282 int c;
283
284 if (!bits)
285 return NULL;
286 if (channels > ARRAY_SIZE(chmap->map))
287 return NULL;
288
289 chmap = kzalloc(sizeof(*chmap), GFP_KERNEL);
290 if (!chmap)
291 return NULL;
292
293 maps = protocol == UAC_VERSION_2 ? uac2_maps : uac1_maps;
294 chmap->channels = channels;
295 c = 0;
296 for (; bits && *maps; maps++, bits >>= 1) {
297 if (bits & 1)
298 chmap->map[c++] = *maps;
299 }
300
301 for (; c < channels; c++)
302 chmap->map[c] = SNDRV_CHMAP_UNKNOWN;
303
304 return chmap;
102} 305}
103 306
104/* 307/*
@@ -140,7 +343,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
140 if (err < 0) 343 if (err < 0)
141 return err; 344 return err;
142 snd_usb_init_substream(as, stream, fp); 345 snd_usb_init_substream(as, stream, fp);
143 return 0; 346 return add_chmap(as->pcm, stream, subs);
144 } 347 }
145 348
146 /* create a new pcm */ 349 /* create a new pcm */
@@ -174,7 +377,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
174 377
175 snd_usb_proc_pcm_format_add(as); 378 snd_usb_proc_pcm_format_add(as);
176 379
177 return 0; 380 return add_chmap(pcm, stream, &as->substream[stream]);
178} 381}
179 382
180static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, 383static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
@@ -218,8 +421,11 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
218 return attributes; 421 return attributes;
219} 422}
220 423
221static struct uac2_input_terminal_descriptor * 424/* find an input terminal descriptor (either UAC1 or UAC2) with the given
222 snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, 425 * terminal id
426 */
427static void *
428snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
223 int terminal_id) 429 int terminal_id)
224{ 430{
225 struct uac2_input_terminal_descriptor *term = NULL; 431 struct uac2_input_terminal_descriptor *term = NULL;
@@ -261,6 +467,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
261 struct audioformat *fp = NULL; 467 struct audioformat *fp = NULL;
262 int num, protocol, clock = 0; 468 int num, protocol, clock = 0;
263 struct uac_format_type_i_continuous_descriptor *fmt; 469 struct uac_format_type_i_continuous_descriptor *fmt;
470 unsigned int chconfig;
264 471
265 dev = chip->dev; 472 dev = chip->dev;
266 473
@@ -300,6 +507,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
300 if (snd_usb_apply_interface_quirk(chip, iface_no, altno)) 507 if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
301 continue; 508 continue;
302 509
510 chconfig = 0;
303 /* get audio formats */ 511 /* get audio formats */
304 switch (protocol) { 512 switch (protocol) {
305 default: 513 default:
@@ -311,6 +519,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
311 case UAC_VERSION_1: { 519 case UAC_VERSION_1: {
312 struct uac1_as_header_descriptor *as = 520 struct uac1_as_header_descriptor *as =
313 snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); 521 snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
522 struct uac_input_terminal_descriptor *iterm;
314 523
315 if (!as) { 524 if (!as) {
316 snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n", 525 snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
@@ -325,6 +534,14 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
325 } 534 }
326 535
327 format = le16_to_cpu(as->wFormatTag); /* remember the format value */ 536 format = le16_to_cpu(as->wFormatTag); /* remember the format value */
537
538 iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
539 as->bTerminalLink);
540 if (iterm) {
541 num_channels = iterm->bNrChannels;
542 chconfig = le16_to_cpu(iterm->wChannelConfig);
543 }
544
328 break; 545 break;
329 } 546 }
330 547
@@ -355,6 +572,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
355 as->bTerminalLink); 572 as->bTerminalLink);
356 if (input_term) { 573 if (input_term) {
357 clock = input_term->bCSourceID; 574 clock = input_term->bCSourceID;
575 chconfig = le32_to_cpu(input_term->bmChannelConfig);
358 break; 576 break;
359 } 577 }
360 578
@@ -413,13 +631,13 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
413 fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; 631 fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
414 fp->datainterval = snd_usb_parse_datainterval(chip, alts); 632 fp->datainterval = snd_usb_parse_datainterval(chip, alts);
415 fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); 633 fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
416 /* num_channels is only set for v2 interfaces */
417 fp->channels = num_channels; 634 fp->channels = num_channels;
418 if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) 635 if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
419 fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) 636 fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
420 * (fp->maxpacksize & 0x7ff); 637 * (fp->maxpacksize & 0x7ff);
421 fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no); 638 fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
422 fp->clock = clock; 639 fp->clock = clock;
640 fp->chmap = convert_chmap(num_channels, chconfig, protocol);
423 641
424 /* some quirks for attributes here */ 642 /* some quirks for attributes here */
425 643
@@ -455,6 +673,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
455 /* ok, let's parse further... */ 673 /* ok, let's parse further... */
456 if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) { 674 if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
457 kfree(fp->rate_table); 675 kfree(fp->rate_table);
676 kfree(fp->chmap);
458 kfree(fp); 677 kfree(fp);
459 fp = NULL; 678 fp = NULL;
460 continue; 679 continue;
@@ -464,6 +683,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
464 err = snd_usb_add_audio_stream(chip, stream, fp); 683 err = snd_usb_add_audio_stream(chip, stream, fp);
465 if (err < 0) { 684 if (err < 0) {
466 kfree(fp->rate_table); 685 kfree(fp->rate_table);
686 kfree(fp->chmap);
467 kfree(fp); 687 kfree(fp);
468 return err; 688 return err;
469 } 689 }