aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-05-27 02:02:59 -0400
committerTakashi Iwai <tiwai@suse.de>2011-05-27 02:02:59 -0400
commitd1227e3fe0c63a258db855f4f1536b0b34cd8725 (patch)
treed1fba37609a1b357eeb1051d0a6709385dd3bf90 /sound
parent9477c58e3308f54a108a5d1eb9621830b329b0ca (diff)
parent78fa2c4d2465d014e67d3e12d948425856587251 (diff)
Merge branch 'fix/misc' into for-linus
Diffstat (limited to 'sound')
-rw-r--r--sound/core/control.c3
-rw-r--r--sound/core/init.c3
-rw-r--r--sound/core/oss/linear.c3
-rw-r--r--sound/core/pcm_lib.c17
-rw-r--r--sound/core/pcm_native.c21
-rw-r--r--sound/core/seq/seq_queue.c2
-rw-r--r--sound/usb/card.c17
-rw-r--r--sound/usb/mixer.c32
-rw-r--r--sound/usb/mixer.h14
-rw-r--r--sound/usb/mixer_quirks.c70
-rw-r--r--sound/usb/quirks-table.h4
-rw-r--r--sound/usb/quirks.c18
-rw-r--r--sound/usb/usbaudio.h1
13 files changed, 150 insertions, 55 deletions
diff --git a/sound/core/control.c b/sound/core/control.c
index 5d98194bcad5..f8c5be464510 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -704,13 +704,12 @@ static int snd_ctl_elem_list(struct snd_card *card,
704 struct snd_ctl_elem_list list; 704 struct snd_ctl_elem_list list;
705 struct snd_kcontrol *kctl; 705 struct snd_kcontrol *kctl;
706 struct snd_ctl_elem_id *dst, *id; 706 struct snd_ctl_elem_id *dst, *id;
707 unsigned int offset, space, first, jidx; 707 unsigned int offset, space, jidx;
708 708
709 if (copy_from_user(&list, _list, sizeof(list))) 709 if (copy_from_user(&list, _list, sizeof(list)))
710 return -EFAULT; 710 return -EFAULT;
711 offset = list.offset; 711 offset = list.offset;
712 space = list.space; 712 space = list.space;
713 first = 0;
714 /* try limit maximum space */ 713 /* try limit maximum space */
715 if (space > 16384) 714 if (space > 16384)
716 return -ENOMEM; 715 return -ENOMEM;
diff --git a/sound/core/init.c b/sound/core/init.c
index 30ecad41403c..2c041bb36ab3 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -342,7 +342,6 @@ static const struct file_operations snd_shutdown_f_ops =
342int snd_card_disconnect(struct snd_card *card) 342int snd_card_disconnect(struct snd_card *card)
343{ 343{
344 struct snd_monitor_file *mfile; 344 struct snd_monitor_file *mfile;
345 struct file *file;
346 int err; 345 int err;
347 346
348 if (!card) 347 if (!card)
@@ -366,8 +365,6 @@ int snd_card_disconnect(struct snd_card *card)
366 365
367 spin_lock(&card->files_lock); 366 spin_lock(&card->files_lock);
368 list_for_each_entry(mfile, &card->files_list, list) { 367 list_for_each_entry(mfile, &card->files_list, list) {
369 file = mfile->file;
370
371 /* it's critical part, use endless loop */ 368 /* it's critical part, use endless loop */
372 /* we have no room to fail */ 369 /* we have no room to fail */
373 mfile->disconnected_f_op = mfile->file->f_op; 370 mfile->disconnected_f_op = mfile->file->f_op;
diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c
index 13b3f6f49fae..2045697f449d 100644
--- a/sound/core/oss/linear.c
+++ b/sound/core/oss/linear.c
@@ -90,11 +90,8 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
90 struct snd_pcm_plugin_channel *dst_channels, 90 struct snd_pcm_plugin_channel *dst_channels,
91 snd_pcm_uframes_t frames) 91 snd_pcm_uframes_t frames)
92{ 92{
93 struct linear_priv *data;
94
95 if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) 93 if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
96 return -ENXIO; 94 return -ENXIO;
97 data = (struct linear_priv *)plugin->extra_data;
98 if (frames == 0) 95 if (frames == 0)
99 return 0; 96 return 0;
100#ifdef CONFIG_SND_DEBUG 97#ifdef CONFIG_SND_DEBUG
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index abfeff1611ce..f1341308beda 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1756,8 +1756,18 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
1756 wait_queue_t wait; 1756 wait_queue_t wait;
1757 int err = 0; 1757 int err = 0;
1758 snd_pcm_uframes_t avail = 0; 1758 snd_pcm_uframes_t avail = 0;
1759 long tout; 1759 long wait_time, tout;
1760 1760
1761 if (runtime->no_period_wakeup)
1762 wait_time = MAX_SCHEDULE_TIMEOUT;
1763 else {
1764 wait_time = 10;
1765 if (runtime->rate) {
1766 long t = runtime->period_size * 2 / runtime->rate;
1767 wait_time = max(t, wait_time);
1768 }
1769 wait_time = msecs_to_jiffies(wait_time * 1000);
1770 }
1761 init_waitqueue_entry(&wait, current); 1771 init_waitqueue_entry(&wait, current);
1762 add_wait_queue(&runtime->tsleep, &wait); 1772 add_wait_queue(&runtime->tsleep, &wait);
1763 for (;;) { 1773 for (;;) {
@@ -1765,9 +1775,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
1765 err = -ERESTARTSYS; 1775 err = -ERESTARTSYS;
1766 break; 1776 break;
1767 } 1777 }
1768 set_current_state(TASK_INTERRUPTIBLE);
1769 snd_pcm_stream_unlock_irq(substream); 1778 snd_pcm_stream_unlock_irq(substream);
1770 tout = schedule_timeout(msecs_to_jiffies(10000)); 1779 tout = schedule_timeout_interruptible(wait_time);
1771 snd_pcm_stream_lock_irq(substream); 1780 snd_pcm_stream_lock_irq(substream);
1772 switch (runtime->status->state) { 1781 switch (runtime->status->state) {
1773 case SNDRV_PCM_STATE_SUSPENDED: 1782 case SNDRV_PCM_STATE_SUSPENDED:
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 1a07750f3836..1c6be91dfb98 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1481,11 +1481,20 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
1481 break; /* all drained */ 1481 break; /* all drained */
1482 init_waitqueue_entry(&wait, current); 1482 init_waitqueue_entry(&wait, current);
1483 add_wait_queue(&to_check->sleep, &wait); 1483 add_wait_queue(&to_check->sleep, &wait);
1484 set_current_state(TASK_INTERRUPTIBLE);
1485 snd_pcm_stream_unlock_irq(substream); 1484 snd_pcm_stream_unlock_irq(substream);
1486 up_read(&snd_pcm_link_rwsem); 1485 up_read(&snd_pcm_link_rwsem);
1487 snd_power_unlock(card); 1486 snd_power_unlock(card);
1488 tout = schedule_timeout(10 * HZ); 1487 if (runtime->no_period_wakeup)
1488 tout = MAX_SCHEDULE_TIMEOUT;
1489 else {
1490 tout = 10;
1491 if (runtime->rate) {
1492 long t = runtime->period_size * 2 / runtime->rate;
1493 tout = max(t, tout);
1494 }
1495 tout = msecs_to_jiffies(tout * 1000);
1496 }
1497 tout = schedule_timeout_interruptible(tout);
1489 snd_power_lock(card); 1498 snd_power_lock(card);
1490 down_read(&snd_pcm_link_rwsem); 1499 down_read(&snd_pcm_link_rwsem);
1491 snd_pcm_stream_lock_irq(substream); 1500 snd_pcm_stream_lock_irq(substream);
@@ -1518,13 +1527,11 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
1518static int snd_pcm_drop(struct snd_pcm_substream *substream) 1527static int snd_pcm_drop(struct snd_pcm_substream *substream)
1519{ 1528{
1520 struct snd_pcm_runtime *runtime; 1529 struct snd_pcm_runtime *runtime;
1521 struct snd_card *card;
1522 int result = 0; 1530 int result = 0;
1523 1531
1524 if (PCM_RUNTIME_CHECK(substream)) 1532 if (PCM_RUNTIME_CHECK(substream))
1525 return -ENXIO; 1533 return -ENXIO;
1526 runtime = substream->runtime; 1534 runtime = substream->runtime;
1527 card = substream->pcm->card;
1528 1535
1529 if (runtime->status->state == SNDRV_PCM_STATE_OPEN || 1536 if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
1530 runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED || 1537 runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED ||
@@ -2056,7 +2063,6 @@ static int snd_pcm_open_file(struct file *file,
2056{ 2063{
2057 struct snd_pcm_file *pcm_file; 2064 struct snd_pcm_file *pcm_file;
2058 struct snd_pcm_substream *substream; 2065 struct snd_pcm_substream *substream;
2059 struct snd_pcm_str *str;
2060 int err; 2066 int err;
2061 2067
2062 if (rpcm_file) 2068 if (rpcm_file)
@@ -2073,7 +2079,6 @@ static int snd_pcm_open_file(struct file *file,
2073 } 2079 }
2074 pcm_file->substream = substream; 2080 pcm_file->substream = substream;
2075 if (substream->ref_count == 1) { 2081 if (substream->ref_count == 1) {
2076 str = substream->pstr;
2077 substream->file = pcm_file; 2082 substream->file = pcm_file;
2078 substream->pcm_release = pcm_release_private; 2083 substream->pcm_release = pcm_release_private;
2079 } 2084 }
@@ -3015,11 +3020,9 @@ static const struct vm_operations_struct snd_pcm_vm_ops_status =
3015static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file, 3020static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
3016 struct vm_area_struct *area) 3021 struct vm_area_struct *area)
3017{ 3022{
3018 struct snd_pcm_runtime *runtime;
3019 long size; 3023 long size;
3020 if (!(area->vm_flags & VM_READ)) 3024 if (!(area->vm_flags & VM_READ))
3021 return -EINVAL; 3025 return -EINVAL;
3022 runtime = substream->runtime;
3023 size = area->vm_end - area->vm_start; 3026 size = area->vm_end - area->vm_start;
3024 if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))) 3027 if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)))
3025 return -EINVAL; 3028 return -EINVAL;
@@ -3054,11 +3057,9 @@ static const struct vm_operations_struct snd_pcm_vm_ops_control =
3054static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file, 3057static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
3055 struct vm_area_struct *area) 3058 struct vm_area_struct *area)
3056{ 3059{
3057 struct snd_pcm_runtime *runtime;
3058 long size; 3060 long size;
3059 if (!(area->vm_flags & VM_READ)) 3061 if (!(area->vm_flags & VM_READ))
3060 return -EINVAL; 3062 return -EINVAL;
3061 runtime = substream->runtime;
3062 size = area->vm_end - area->vm_start; 3063 size = area->vm_end - area->vm_start;
3063 if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control))) 3064 if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)))
3064 return -EINVAL; 3065 return -EINVAL;
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index e7a8e9e4edb2..f9077361c119 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -467,13 +467,11 @@ int snd_seq_queue_timer_open(int queueid)
467int snd_seq_queue_timer_close(int queueid) 467int snd_seq_queue_timer_close(int queueid)
468{ 468{
469 struct snd_seq_queue *queue; 469 struct snd_seq_queue *queue;
470 struct snd_seq_timer *tmr;
471 int result = 0; 470 int result = 0;
472 471
473 queue = queueptr(queueid); 472 queue = queueptr(queueid);
474 if (queue == NULL) 473 if (queue == NULL)
475 return -EINVAL; 474 return -EINVAL;
476 tmr = queue->timer;
477 snd_seq_timer_close(queue); 475 snd_seq_timer_close(queue);
478 queuefree(queue); 476 queuefree(queue);
479 return result; 477 return result;
diff --git a/sound/usb/card.c b/sound/usb/card.c
index a90662af2d6b..220c6167dd86 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -48,6 +48,7 @@
48#include <linux/usb/audio.h> 48#include <linux/usb/audio.h>
49#include <linux/usb/audio-v2.h> 49#include <linux/usb/audio-v2.h>
50 50
51#include <sound/control.h>
51#include <sound/core.h> 52#include <sound/core.h>
52#include <sound/info.h> 53#include <sound/info.h>
53#include <sound/pcm.h> 54#include <sound/pcm.h>
@@ -492,14 +493,6 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
492 } 493 }
493 } 494 }
494 495
495 chip->txfr_quirk = 0;
496 err = 1; /* continue */
497 if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
498 /* need some special handlings */
499 if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0)
500 goto __error;
501 }
502
503 /* 496 /*
504 * For devices with more than one control interface, we assume the 497 * For devices with more than one control interface, we assume the
505 * first contains the audio controls. We might need a more specific 498 * first contains the audio controls. We might need a more specific
@@ -508,6 +501,14 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
508 if (!chip->ctrl_intf) 501 if (!chip->ctrl_intf)
509 chip->ctrl_intf = alts; 502 chip->ctrl_intf = alts;
510 503
504 chip->txfr_quirk = 0;
505 err = 1; /* continue */
506 if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
507 /* need some special handlings */
508 if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0)
509 goto __error;
510 }
511
511 if (err > 0) { 512 if (err > 0) {
512 /* create normal USB audio interfaces */ 513 /* create normal USB audio interfaces */
513 if (snd_usb_create_streams(chip, ifnum) < 0 || 514 if (snd_usb_create_streams(chip, ifnum) < 0 ||
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index eab06edcc9b7..c22fa76e363a 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -86,16 +86,6 @@ struct mixer_build {
86 const struct usbmix_selector_map *selector_map; 86 const struct usbmix_selector_map *selector_map;
87}; 87};
88 88
89enum {
90 USB_MIXER_BOOLEAN,
91 USB_MIXER_INV_BOOLEAN,
92 USB_MIXER_S8,
93 USB_MIXER_U8,
94 USB_MIXER_S16,
95 USB_MIXER_U16,
96};
97
98
99/*E-mu 0202/0404/0204 eXtension Unit(XU) control*/ 89/*E-mu 0202/0404/0204 eXtension Unit(XU) control*/
100enum { 90enum {
101 USB_XU_CLOCK_RATE = 0xe301, 91 USB_XU_CLOCK_RATE = 0xe301,
@@ -535,20 +525,21 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou
535 * if failed, give up and free the control instance. 525 * if failed, give up and free the control instance.
536 */ 526 */
537 527
538static int add_control_to_empty(struct mixer_build *state, struct snd_kcontrol *kctl) 528int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
529 struct snd_kcontrol *kctl)
539{ 530{
540 struct usb_mixer_elem_info *cval = kctl->private_data; 531 struct usb_mixer_elem_info *cval = kctl->private_data;
541 int err; 532 int err;
542 533
543 while (snd_ctl_find_id(state->chip->card, &kctl->id)) 534 while (snd_ctl_find_id(mixer->chip->card, &kctl->id))
544 kctl->id.index++; 535 kctl->id.index++;
545 if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) { 536 if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) {
546 snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); 537 snd_printd(KERN_ERR "cannot add control (err = %d)\n", err);
547 return err; 538 return err;
548 } 539 }
549 cval->elem_id = &kctl->id; 540 cval->elem_id = &kctl->id;
550 cval->next_id_elem = state->mixer->id_elems[cval->id]; 541 cval->next_id_elem = mixer->id_elems[cval->id];
551 state->mixer->id_elems[cval->id] = cval; 542 mixer->id_elems[cval->id] = cval;
552 return 0; 543 return 0;
553} 544}
554 545
@@ -984,6 +975,9 @@ static struct snd_kcontrol_new usb_feature_unit_ctl_ro = {
984 .put = NULL, 975 .put = NULL,
985}; 976};
986 977
978/* This symbol is exported in order to allow the mixer quirks to
979 * hook up to the standard feature unit control mechanism */
980struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl;
987 981
988/* 982/*
989 * build a feature control 983 * build a feature control
@@ -1176,7 +1170,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
1176 1170
1177 snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", 1171 snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
1178 cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); 1172 cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
1179 add_control_to_empty(state, kctl); 1173 snd_usb_mixer_add_control(state->mixer, kctl);
1180} 1174}
1181 1175
1182 1176
@@ -1340,7 +1334,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
1340 1334
1341 snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", 1335 snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n",
1342 cval->id, kctl->id.name, cval->channels, cval->min, cval->max); 1336 cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
1343 add_control_to_empty(state, kctl); 1337 snd_usb_mixer_add_control(state->mixer, kctl);
1344} 1338}
1345 1339
1346 1340
@@ -1641,7 +1635,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw
1641 1635
1642 snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", 1636 snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n",
1643 cval->id, kctl->id.name, cval->channels, cval->min, cval->max); 1637 cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
1644 if ((err = add_control_to_empty(state, kctl)) < 0) 1638 if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0)
1645 return err; 1639 return err;
1646 } 1640 }
1647 return 0; 1641 return 0;
@@ -1858,7 +1852,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
1858 1852
1859 snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", 1853 snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
1860 cval->id, kctl->id.name, desc->bNrInPins); 1854 cval->id, kctl->id.name, desc->bNrInPins);
1861 if ((err = add_control_to_empty(state, kctl)) < 0) 1855 if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0)
1862 return err; 1856 return err;
1863 1857
1864 return 0; 1858 return 0;
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index b4a2c8165e4b..ae1a14dcfe82 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -24,7 +24,16 @@ struct usb_mixer_interface {
24 u8 xonar_u1_status; 24 u8 xonar_u1_status;
25}; 25};
26 26
27#define MAX_CHANNELS 10 /* max logical channels */ 27#define MAX_CHANNELS 16 /* max logical channels */
28
29enum {
30 USB_MIXER_BOOLEAN,
31 USB_MIXER_INV_BOOLEAN,
32 USB_MIXER_S8,
33 USB_MIXER_U8,
34 USB_MIXER_S16,
35 USB_MIXER_U16,
36};
28 37
29struct usb_mixer_elem_info { 38struct usb_mixer_elem_info {
30 struct usb_mixer_interface *mixer; 39 struct usb_mixer_interface *mixer;
@@ -55,4 +64,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
55void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer); 64void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer);
56int snd_usb_mixer_activate(struct usb_mixer_interface *mixer); 65int snd_usb_mixer_activate(struct usb_mixer_interface *mixer);
57 66
67int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
68 struct snd_kcontrol *kctl);
69
58#endif /* __USBMIXER_H */ 70#endif /* __USBMIXER_H */
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 9146cffa6ede..3d0f4873112b 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -40,6 +40,8 @@
40#include "mixer_quirks.h" 40#include "mixer_quirks.h"
41#include "helper.h" 41#include "helper.h"
42 42
43extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
44
43/* 45/*
44 * Sound Blaster remote control configuration 46 * Sound Blaster remote control configuration
45 * 47 *
@@ -492,6 +494,69 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
492 return err; 494 return err;
493} 495}
494 496
497/* M-Audio FastTrack Ultra quirks */
498
499/* private_free callback */
500static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
501{
502 kfree(kctl->private_data);
503 kctl->private_data = NULL;
504}
505
506static int snd_maudio_ftu_create_ctl(struct usb_mixer_interface *mixer,
507 int in, int out, const char *name)
508{
509 struct usb_mixer_elem_info *cval;
510 struct snd_kcontrol *kctl;
511
512 cval = kzalloc(sizeof(*cval), GFP_KERNEL);
513 if (!cval)
514 return -ENOMEM;
515
516 cval->id = 5;
517 cval->mixer = mixer;
518 cval->val_type = USB_MIXER_S16;
519 cval->channels = 1;
520 cval->control = out + 1;
521 cval->cmask = 1 << in;
522
523 kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval);
524 if (!kctl) {
525 kfree(cval);
526 return -ENOMEM;
527 }
528
529 snprintf(kctl->id.name, sizeof(kctl->id.name), name);
530 kctl->private_free = usb_mixer_elem_free;
531 return snd_usb_mixer_add_control(mixer, kctl);
532}
533
534static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer)
535{
536 char name[64];
537 int in, out, err;
538
539 for (out = 0; out < 8; out++) {
540 for (in = 0; in < 8; in++) {
541 snprintf(name, sizeof(name),
542 "AIn%d - Out%d Capture Volume", in + 1, out + 1);
543 err = snd_maudio_ftu_create_ctl(mixer, in, out, name);
544 if (err < 0)
545 return err;
546 }
547
548 for (in = 8; in < 16; in++) {
549 snprintf(name, sizeof(name),
550 "DIn%d - Out%d Playback Volume", in - 7, out + 1);
551 err = snd_maudio_ftu_create_ctl(mixer, in, out, name);
552 if (err < 0)
553 return err;
554 }
555 }
556
557 return 0;
558}
559
495void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, 560void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
496 unsigned char samplerate_id) 561 unsigned char samplerate_id)
497{ 562{
@@ -533,6 +598,11 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
533 snd_audigy2nx_proc_read); 598 snd_audigy2nx_proc_read);
534 break; 599 break;
535 600
601 case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
602 case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
603 err = snd_maudio_ftu_create_mixer(mixer);
604 break;
605
536 case USB_ID(0x0b05, 0x1739): 606 case USB_ID(0x0b05, 0x1739):
537 case USB_ID(0x0b05, 0x1743): 607 case USB_ID(0x0b05, 0x1743):
538 err = snd_xonar_u1_controls_create(mixer); 608 err = snd_xonar_u1_controls_create(mixer);
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 78792a8900c3..0b2ae8e1c02d 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -1988,7 +1988,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
1988 .data = & (const struct snd_usb_audio_quirk[]) { 1988 .data = & (const struct snd_usb_audio_quirk[]) {
1989 { 1989 {
1990 .ifnum = 0, 1990 .ifnum = 0,
1991 .type = QUIRK_IGNORE_INTERFACE 1991 .type = QUIRK_AUDIO_STANDARD_MIXER,
1992 }, 1992 },
1993 { 1993 {
1994 .ifnum = 1, 1994 .ifnum = 1,
@@ -2055,7 +2055,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
2055 .data = & (const struct snd_usb_audio_quirk[]) { 2055 .data = & (const struct snd_usb_audio_quirk[]) {
2056 { 2056 {
2057 .ifnum = 0, 2057 .ifnum = 0,
2058 .type = QUIRK_IGNORE_INTERFACE 2058 .type = QUIRK_AUDIO_STANDARD_MIXER,
2059 }, 2059 },
2060 { 2060 {
2061 .ifnum = 1, 2061 .ifnum = 1,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index bd13d7257240..2e969cbb393b 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -19,6 +19,7 @@
19#include <linux/usb.h> 19#include <linux/usb.h>
20#include <linux/usb/audio.h> 20#include <linux/usb/audio.h>
21 21
22#include <sound/control.h>
22#include <sound/core.h> 23#include <sound/core.h>
23#include <sound/info.h> 24#include <sound/info.h>
24#include <sound/pcm.h> 25#include <sound/pcm.h>
@@ -263,6 +264,20 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
263} 264}
264 265
265/* 266/*
267 * Create a standard mixer for the specified interface.
268 */
269static int create_standard_mixer_quirk(struct snd_usb_audio *chip,
270 struct usb_interface *iface,
271 struct usb_driver *driver,
272 const struct snd_usb_audio_quirk *quirk)
273{
274 if (quirk->ifnum < 0)
275 return 0;
276
277 return snd_usb_create_mixer(chip, quirk->ifnum, 0);
278}
279
280/*
266 * audio-interface quirks 281 * audio-interface quirks
267 * 282 *
268 * returns zero if no standard audio/MIDI parsing is needed. 283 * returns zero if no standard audio/MIDI parsing is needed.
@@ -294,7 +309,8 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
294 [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, 309 [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
295 [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, 310 [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
296 [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, 311 [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
297 [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk 312 [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk,
313 [QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk,
298 }; 314 };
299 315
300 if (quirk->type < QUIRK_TYPE_COUNT) { 316 if (quirk->type < QUIRK_TYPE_COUNT) {
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 32f2a97f2f14..1e79986b5777 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -84,6 +84,7 @@ enum quirk_type {
84 QUIRK_AUDIO_FIXED_ENDPOINT, 84 QUIRK_AUDIO_FIXED_ENDPOINT,
85 QUIRK_AUDIO_EDIROL_UAXX, 85 QUIRK_AUDIO_EDIROL_UAXX,
86 QUIRK_AUDIO_ALIGN_TRANSFER, 86 QUIRK_AUDIO_ALIGN_TRANSFER,
87 QUIRK_AUDIO_STANDARD_MIXER,
87 88
88 QUIRK_TYPE_COUNT 89 QUIRK_TYPE_COUNT
89}; 90};