diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-05-27 08:02:59 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-05-27 08:02:59 +0200 |
commit | d1227e3fe0c63a258db855f4f1536b0b34cd8725 (patch) | |
tree | d1fba37609a1b357eeb1051d0a6709385dd3bf90 | |
parent | 9477c58e3308f54a108a5d1eb9621830b329b0ca (diff) | |
parent | 78fa2c4d2465d014e67d3e12d948425856587251 (diff) |
Merge branch 'fix/misc' into for-linus
-rw-r--r-- | MAINTAINERS | 7 | ||||
-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 |
14 files changed, 157 insertions, 55 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 6e645474654..c3106cd266e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2582,6 +2582,13 @@ S: Maintained F: drivers/hwmon/f75375s.c F: include/linux/f75375s.h +FIREWIRE AUDIO DRIVERS +M: Clemens Ladisch <clemens@ladisch.de> +L: alsa-devel@alsa-project.org (moderated for non-subscribers) +T: git git://git.alsa-project.org/alsa-kernel.git +S: Maintained +F: sound/firewire/ + FIREWIRE SUBSYSTEM M: Stefan Richter <stefanr@s5r6.in-berlin.de> L: linux1394-devel@lists.sourceforge.net diff --git a/sound/core/control.c b/sound/core/control.c index 5d98194bcad..f8c5be46451 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, struct snd_ctl_elem_list list; struct snd_kcontrol *kctl; struct snd_ctl_elem_id *dst, *id; - unsigned int offset, space, first, jidx; + unsigned int offset, space, jidx; if (copy_from_user(&list, _list, sizeof(list))) return -EFAULT; offset = list.offset; space = list.space; - first = 0; /* try limit maximum space */ if (space > 16384) return -ENOMEM; diff --git a/sound/core/init.c b/sound/core/init.c index 30ecad41403..2c041bb36ab 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -342,7 +342,6 @@ static const struct file_operations snd_shutdown_f_ops = int snd_card_disconnect(struct snd_card *card) { struct snd_monitor_file *mfile; - struct file *file; int err; if (!card) @@ -366,8 +365,6 @@ int snd_card_disconnect(struct snd_card *card) spin_lock(&card->files_lock); list_for_each_entry(mfile, &card->files_list, list) { - file = mfile->file; - /* it's critical part, use endless loop */ /* we have no room to fail */ mfile->disconnected_f_op = mfile->file->f_op; diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c index 13b3f6f49fa..2045697f449 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, struct snd_pcm_plugin_channel *dst_channels, snd_pcm_uframes_t frames) { - struct linear_priv *data; - if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) return -ENXIO; - data = (struct linear_priv *)plugin->extra_data; if (frames == 0) return 0; #ifdef CONFIG_SND_DEBUG diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index abfeff1611c..f1341308bed 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, wait_queue_t wait; int err = 0; snd_pcm_uframes_t avail = 0; - long tout; - + long wait_time, tout; + + if (runtime->no_period_wakeup) + wait_time = MAX_SCHEDULE_TIMEOUT; + else { + wait_time = 10; + if (runtime->rate) { + long t = runtime->period_size * 2 / runtime->rate; + wait_time = max(t, wait_time); + } + wait_time = msecs_to_jiffies(wait_time * 1000); + } init_waitqueue_entry(&wait, current); add_wait_queue(&runtime->tsleep, &wait); for (;;) { @@ -1765,9 +1775,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream, err = -ERESTARTSYS; break; } - set_current_state(TASK_INTERRUPTIBLE); snd_pcm_stream_unlock_irq(substream); - tout = schedule_timeout(msecs_to_jiffies(10000)); + tout = schedule_timeout_interruptible(wait_time); snd_pcm_stream_lock_irq(substream); switch (runtime->status->state) { case SNDRV_PCM_STATE_SUSPENDED: diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 1a07750f383..1c6be91dfb9 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, break; /* all drained */ init_waitqueue_entry(&wait, current); add_wait_queue(&to_check->sleep, &wait); - set_current_state(TASK_INTERRUPTIBLE); snd_pcm_stream_unlock_irq(substream); up_read(&snd_pcm_link_rwsem); snd_power_unlock(card); - tout = schedule_timeout(10 * HZ); + if (runtime->no_period_wakeup) + tout = MAX_SCHEDULE_TIMEOUT; + else { + tout = 10; + if (runtime->rate) { + long t = runtime->period_size * 2 / runtime->rate; + tout = max(t, tout); + } + tout = msecs_to_jiffies(tout * 1000); + } + tout = schedule_timeout_interruptible(tout); snd_power_lock(card); down_read(&snd_pcm_link_rwsem); snd_pcm_stream_lock_irq(substream); @@ -1518,13 +1527,11 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, static int snd_pcm_drop(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime; - struct snd_card *card; int result = 0; if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - card = substream->pcm->card; if (runtime->status->state == SNDRV_PCM_STATE_OPEN || runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED || @@ -2056,7 +2063,6 @@ static int snd_pcm_open_file(struct file *file, { struct snd_pcm_file *pcm_file; struct snd_pcm_substream *substream; - struct snd_pcm_str *str; int err; if (rpcm_file) @@ -2073,7 +2079,6 @@ static int snd_pcm_open_file(struct file *file, } pcm_file->substream = substream; if (substream->ref_count == 1) { - str = substream->pstr; substream->file = pcm_file; substream->pcm_release = pcm_release_private; } @@ -3015,11 +3020,9 @@ static const struct vm_operations_struct snd_pcm_vm_ops_status = static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area) { - struct snd_pcm_runtime *runtime; long size; if (!(area->vm_flags & VM_READ)) return -EINVAL; - runtime = substream->runtime; size = area->vm_end - area->vm_start; if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))) return -EINVAL; @@ -3054,11 +3057,9 @@ static const struct vm_operations_struct snd_pcm_vm_ops_control = static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area) { - struct snd_pcm_runtime *runtime; long size; if (!(area->vm_flags & VM_READ)) return -EINVAL; - runtime = substream->runtime; size = area->vm_end - area->vm_start; if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control))) return -EINVAL; diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index e7a8e9e4edb..f9077361c11 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) int snd_seq_queue_timer_close(int queueid) { struct snd_seq_queue *queue; - struct snd_seq_timer *tmr; int result = 0; queue = queueptr(queueid); if (queue == NULL) return -EINVAL; - tmr = queue->timer; snd_seq_timer_close(queue); queuefree(queue); return result; diff --git a/sound/usb/card.c b/sound/usb/card.c index a90662af2d6..220c6167dd8 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -48,6 +48,7 @@ #include <linux/usb/audio.h> #include <linux/usb/audio-v2.h> +#include <sound/control.h> #include <sound/core.h> #include <sound/info.h> #include <sound/pcm.h> @@ -492,14 +493,6 @@ static void *snd_usb_audio_probe(struct usb_device *dev, } } - chip->txfr_quirk = 0; - err = 1; /* continue */ - if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) { - /* need some special handlings */ - if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0) - goto __error; - } - /* * For devices with more than one control interface, we assume the * 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, if (!chip->ctrl_intf) chip->ctrl_intf = alts; + chip->txfr_quirk = 0; + err = 1; /* continue */ + if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) { + /* need some special handlings */ + if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0) + goto __error; + } + if (err > 0) { /* create normal USB audio interfaces */ if (snd_usb_create_streams(chip, ifnum) < 0 || diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index eab06edcc9b..c22fa76e363 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -86,16 +86,6 @@ struct mixer_build { const struct usbmix_selector_map *selector_map; }; -enum { - USB_MIXER_BOOLEAN, - USB_MIXER_INV_BOOLEAN, - USB_MIXER_S8, - USB_MIXER_U8, - USB_MIXER_S16, - USB_MIXER_U16, -}; - - /*E-mu 0202/0404/0204 eXtension Unit(XU) control*/ enum { USB_XU_CLOCK_RATE = 0xe301, @@ -535,20 +525,21 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou * if failed, give up and free the control instance. */ -static int add_control_to_empty(struct mixer_build *state, struct snd_kcontrol *kctl) +int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, + struct snd_kcontrol *kctl) { struct usb_mixer_elem_info *cval = kctl->private_data; int err; - while (snd_ctl_find_id(state->chip->card, &kctl->id)) + while (snd_ctl_find_id(mixer->chip->card, &kctl->id)) kctl->id.index++; - if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) { + if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) { snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); return err; } cval->elem_id = &kctl->id; - cval->next_id_elem = state->mixer->id_elems[cval->id]; - state->mixer->id_elems[cval->id] = cval; + cval->next_id_elem = mixer->id_elems[cval->id]; + mixer->id_elems[cval->id] = cval; return 0; } @@ -984,6 +975,9 @@ static struct snd_kcontrol_new usb_feature_unit_ctl_ro = { .put = NULL, }; +/* This symbol is exported in order to allow the mixer quirks to + * hook up to the standard feature unit control mechanism */ +struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl; /* * build a feature control @@ -1176,7 +1170,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); - add_control_to_empty(state, kctl); + snd_usb_mixer_add_control(state->mixer, kctl); } @@ -1340,7 +1334,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max); - add_control_to_empty(state, kctl); + snd_usb_mixer_add_control(state->mixer, kctl); } @@ -1641,7 +1635,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max); - if ((err = add_control_to_empty(state, kctl)) < 0) + if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) return err; } return 0; @@ -1858,7 +1852,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", cval->id, kctl->id.name, desc->bNrInPins); - if ((err = add_control_to_empty(state, kctl)) < 0) + if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) return err; return 0; diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index b4a2c8165e4..ae1a14dcfe8 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -24,7 +24,16 @@ struct usb_mixer_interface { u8 xonar_u1_status; }; -#define MAX_CHANNELS 10 /* max logical channels */ +#define MAX_CHANNELS 16 /* max logical channels */ + +enum { + USB_MIXER_BOOLEAN, + USB_MIXER_INV_BOOLEAN, + USB_MIXER_S8, + USB_MIXER_U8, + USB_MIXER_S16, + USB_MIXER_U16, +}; struct usb_mixer_elem_info { struct usb_mixer_interface *mixer; @@ -55,4 +64,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer); int snd_usb_mixer_activate(struct usb_mixer_interface *mixer); +int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, + struct snd_kcontrol *kctl); + #endif /* __USBMIXER_H */ diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 9146cffa6ed..3d0f4873112 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -40,6 +40,8 @@ #include "mixer_quirks.h" #include "helper.h" +extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; + /* * Sound Blaster remote control configuration * @@ -492,6 +494,69 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer, return err; } +/* M-Audio FastTrack Ultra quirks */ + +/* private_free callback */ +static void usb_mixer_elem_free(struct snd_kcontrol *kctl) +{ + kfree(kctl->private_data); + kctl->private_data = NULL; +} + +static int snd_maudio_ftu_create_ctl(struct usb_mixer_interface *mixer, + int in, int out, const char *name) +{ + struct usb_mixer_elem_info *cval; + struct snd_kcontrol *kctl; + + cval = kzalloc(sizeof(*cval), GFP_KERNEL); + if (!cval) + return -ENOMEM; + + cval->id = 5; + cval->mixer = mixer; + cval->val_type = USB_MIXER_S16; + cval->channels = 1; + cval->control = out + 1; + cval->cmask = 1 << in; + + kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval); + if (!kctl) { + kfree(cval); + return -ENOMEM; + } + + snprintf(kctl->id.name, sizeof(kctl->id.name), name); + kctl->private_free = usb_mixer_elem_free; + return snd_usb_mixer_add_control(mixer, kctl); +} + +static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer) +{ + char name[64]; + int in, out, err; + + for (out = 0; out < 8; out++) { + for (in = 0; in < 8; in++) { + snprintf(name, sizeof(name), + "AIn%d - Out%d Capture Volume", in + 1, out + 1); + err = snd_maudio_ftu_create_ctl(mixer, in, out, name); + if (err < 0) + return err; + } + + for (in = 8; in < 16; in++) { + snprintf(name, sizeof(name), + "DIn%d - Out%d Playback Volume", in - 7, out + 1); + err = snd_maudio_ftu_create_ctl(mixer, in, out, name); + if (err < 0) + return err; + } + } + + return 0; +} + void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, unsigned char samplerate_id) { @@ -533,6 +598,11 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) snd_audigy2nx_proc_read); break; + case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */ + case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */ + err = snd_maudio_ftu_create_mixer(mixer); + break; + case USB_ID(0x0b05, 0x1739): case USB_ID(0x0b05, 0x1743): err = snd_xonar_u1_controls_create(mixer); diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 78792a8900c..0b2ae8e1c02 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -1988,7 +1988,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .data = & (const struct snd_usb_audio_quirk[]) { { .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE + .type = QUIRK_AUDIO_STANDARD_MIXER, }, { .ifnum = 1, @@ -2055,7 +2055,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .data = & (const struct snd_usb_audio_quirk[]) { { .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE + .type = QUIRK_AUDIO_STANDARD_MIXER, }, { .ifnum = 1, diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index bd13d725724..2e969cbb393 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -19,6 +19,7 @@ #include <linux/usb.h> #include <linux/usb/audio.h> +#include <sound/control.h> #include <sound/core.h> #include <sound/info.h> #include <sound/pcm.h> @@ -263,6 +264,20 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, } /* + * Create a standard mixer for the specified interface. + */ +static int create_standard_mixer_quirk(struct snd_usb_audio *chip, + struct usb_interface *iface, + struct usb_driver *driver, + const struct snd_usb_audio_quirk *quirk) +{ + if (quirk->ifnum < 0) + return 0; + + return snd_usb_create_mixer(chip, quirk->ifnum, 0); +} + +/* * audio-interface quirks * * returns zero if no standard audio/MIDI parsing is needed. @@ -294,7 +309,8 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip, [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, - [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk + [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk, + [QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk, }; if (quirk->type < QUIRK_TYPE_COUNT) { diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 32f2a97f2f1..1e79986b577 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -84,6 +84,7 @@ enum quirk_type { QUIRK_AUDIO_FIXED_ENDPOINT, QUIRK_AUDIO_EDIROL_UAXX, QUIRK_AUDIO_ALIGN_TRANSFER, + QUIRK_AUDIO_STANDARD_MIXER, QUIRK_TYPE_COUNT }; |