diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-05-27 02:02:59 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-05-27 02:02:59 -0400 |
commit | d1227e3fe0c63a258db855f4f1536b0b34cd8725 (patch) | |
tree | d1fba37609a1b357eeb1051d0a6709385dd3bf90 /sound | |
parent | 9477c58e3308f54a108a5d1eb9621830b329b0ca (diff) | |
parent | 78fa2c4d2465d014e67d3e12d948425856587251 (diff) |
Merge branch 'fix/misc' into for-linus
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/control.c | 3 | ||||
-rw-r--r-- | sound/core/init.c | 3 | ||||
-rw-r--r-- | sound/core/oss/linear.c | 3 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 17 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 21 | ||||
-rw-r--r-- | sound/core/seq/seq_queue.c | 2 | ||||
-rw-r--r-- | sound/usb/card.c | 17 | ||||
-rw-r--r-- | sound/usb/mixer.c | 32 | ||||
-rw-r--r-- | sound/usb/mixer.h | 14 | ||||
-rw-r--r-- | sound/usb/mixer_quirks.c | 70 | ||||
-rw-r--r-- | sound/usb/quirks-table.h | 4 | ||||
-rw-r--r-- | sound/usb/quirks.c | 18 | ||||
-rw-r--r-- | sound/usb/usbaudio.h | 1 |
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 = | |||
342 | int snd_card_disconnect(struct snd_card *card) | 342 | int 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, | |||
1518 | static int snd_pcm_drop(struct snd_pcm_substream *substream) | 1527 | static 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 = | |||
3015 | static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file, | 3020 | static 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 = | |||
3054 | static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file, | 3057 | static 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) | |||
467 | int snd_seq_queue_timer_close(int queueid) | 467 | int 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 | ||
89 | enum { | ||
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*/ |
100 | enum { | 90 | enum { |
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 | ||
538 | static int add_control_to_empty(struct mixer_build *state, struct snd_kcontrol *kctl) | 528 | int 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 */ | ||
980 | struct 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 | |||
29 | enum { | ||
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 | ||
29 | struct usb_mixer_elem_info { | 38 | struct 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, | |||
55 | void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer); | 64 | void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer); |
56 | int snd_usb_mixer_activate(struct usb_mixer_interface *mixer); | 65 | int snd_usb_mixer_activate(struct usb_mixer_interface *mixer); |
57 | 66 | ||
67 | int 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 | ||
43 | extern 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 */ | ||
500 | static void usb_mixer_elem_free(struct snd_kcontrol *kctl) | ||
501 | { | ||
502 | kfree(kctl->private_data); | ||
503 | kctl->private_data = NULL; | ||
504 | } | ||
505 | |||
506 | static 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 | |||
534 | static 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 | |||
495 | void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, | 560 | void 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 | */ | ||
269 | static 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 | }; |