diff options
88 files changed, 1996 insertions, 1635 deletions
diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl index 598c22f3b3ac..5de23c007078 100644 --- a/Documentation/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl @@ -4288,7 +4288,7 @@ struct _snd_pcm_runtime { <![CDATA[ struct snd_rawmidi *rmidi; snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags, - irq, irq_flags, &rmidi); + irq, &rmidi); ]]> </programlisting> </informalexample> @@ -4343,6 +4343,13 @@ struct _snd_pcm_runtime { by itself to start processing the output stream in the irq handler. </para> + <para> + If the MPU-401 interface shares its interrupt with the other logical + devices on the card, set <constant>MPU401_INFO_IRQ_HOOK</constant> + (see <link linkend="midi-interface-interrupt-handler"><citetitle> + below</citetitle></link>). + </para> + <para> Usually, the port address corresponds to the command port and port + 1 corresponds to the data port. If not, you may change @@ -4375,14 +4382,12 @@ struct _snd_pcm_runtime { </para> <para> - The 6th argument specifies the irq number for UART. If the irq - is already allocated, pass 0 to the 7th argument - (<parameter>irq_flags</parameter>). Otherwise, pass the flags - for irq allocation - (<constant>SA_XXX</constant> bits) to it, and the irq will be - reserved by the mpu401-uart layer. If the card doesn't generate - UART interrupts, pass -1 as the irq number. Then a timer - interrupt will be invoked for polling. + The 6th argument specifies the ISA irq number that will be + allocated. If no interrupt is to be allocated (because your + code is already allocating a shared interrupt, or because the + device does not use interrupts), pass -1 instead. + For a MPU-401 device without an interrupt, a polling timer + will be used instead. </para> </section> @@ -4390,12 +4395,13 @@ struct _snd_pcm_runtime { <title>Interrupt Handler</title> <para> When the interrupt is allocated in - <function>snd_mpu401_uart_new()</function>, the private - interrupt handler is used, hence you don't have anything else to do - than creating the mpu401 stuff. Otherwise, you have to call - <function>snd_mpu401_uart_interrupt()</function> explicitly when - a UART interrupt is invoked and checked in your own interrupt - handler. + <function>snd_mpu401_uart_new()</function>, an exclusive ISA + interrupt handler is automatically used, hence you don't have + anything else to do than creating the mpu401 stuff. Otherwise, you + have to set <constant>MPU401_INFO_IRQ_HOOK</constant>, and call + <function>snd_mpu401_uart_interrupt()</function> explicitly from your + own interrupt handler when it has determined that a UART interrupt + has occurred. </para> <para> diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index 0fd3fbdd8283..f30253599501 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -377,12 +377,6 @@ struct usb_endpoint_descriptor { #define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ #define USB_ENDPOINT_DIR_MASK 0x80 -#define USB_ENDPOINT_SYNCTYPE 0x0c -#define USB_ENDPOINT_SYNC_NONE (0 << 2) -#define USB_ENDPOINT_SYNC_ASYNC (1 << 2) -#define USB_ENDPOINT_SYNC_ADAPTIVE (2 << 2) -#define USB_ENDPOINT_SYNC_SYNC (3 << 2) - #define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ #define USB_ENDPOINT_XFER_CONTROL 0 #define USB_ENDPOINT_XFER_ISOC 1 @@ -390,6 +384,17 @@ struct usb_endpoint_descriptor { #define USB_ENDPOINT_XFER_INT 3 #define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 +#define USB_ENDPOINT_SYNCTYPE 0x0c +#define USB_ENDPOINT_SYNC_NONE (0 << 2) +#define USB_ENDPOINT_SYNC_ASYNC (1 << 2) +#define USB_ENDPOINT_SYNC_ADAPTIVE (2 << 2) +#define USB_ENDPOINT_SYNC_SYNC (3 << 2) + +#define USB_ENDPOINT_USAGE_MASK 0x30 +#define USB_ENDPOINT_USAGE_DATA 0x00 +#define USB_ENDPOINT_USAGE_FEEDBACK 0x10 +#define USB_ENDPOINT_USAGE_IMPLICIT_FB 0x20 /* Implicit feedback Data endpoint */ + /*-------------------------------------------------------------------------*/ /** diff --git a/include/sound/mpu401.h b/include/sound/mpu401.h index 1f1d53f8830b..20230db00ef1 100644 --- a/include/sound/mpu401.h +++ b/include/sound/mpu401.h @@ -50,7 +50,10 @@ #define MPU401_INFO_INTEGRATED (1 << 2) /* integrated h/w port */ #define MPU401_INFO_MMIO (1 << 3) /* MMIO access */ #define MPU401_INFO_TX_IRQ (1 << 4) /* independent TX irq */ +#define MPU401_INFO_IRQ_HOOK (1 << 5) /* mpu401 irq handler is called + from driver irq handler */ #define MPU401_INFO_NO_ACK (1 << 6) /* No ACK cmd needed */ +#define MPU401_INFO_USE_TIMER (1 << 15) /* internal */ #define MPU401_MODE_BIT_INPUT 0 #define MPU401_MODE_BIT_OUTPUT 1 @@ -73,8 +76,7 @@ struct snd_mpu401 { unsigned long port; /* base port of MPU-401 chip */ unsigned long cport; /* port + 1 (usually) */ struct resource *res; /* port resource */ - int irq; /* IRQ number of MPU-401 chip (-1 = poll) */ - int irq_flags; + int irq; /* IRQ number of MPU-401 chip */ unsigned long mode; /* MPU401_MODE_XXXX */ int timer_invoked; @@ -131,7 +133,6 @@ int snd_mpu401_uart_new(struct snd_card *card, unsigned long port, unsigned int info_flags, int irq, - int irq_flags, struct snd_rawmidi ** rrawmidi); #endif /* __SOUND_MPU401_H */ diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 57e71fa33f7c..dc36f756fe8d 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -825,6 +825,8 @@ int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime, int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime, unsigned int cond, snd_pcm_hw_param_t var); +int snd_pcm_hw_rule_noresample(struct snd_pcm_runtime *runtime, + unsigned int base_rate); int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond, int var, diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index 3687a6cc9881..762af68c8996 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c @@ -1067,7 +1067,6 @@ static int onyx_i2c_probe(struct i2c_client *client, printk(KERN_DEBUG PFX "created and attached onyx instance\n"); return 0; fail: - i2c_set_clientdata(client, NULL); kfree(onyx); return -ENODEV; } @@ -1112,8 +1111,7 @@ static int onyx_i2c_remove(struct i2c_client *client) aoa_codec_unregister(&onyx->codec); of_node_put(onyx->codec.node); - if (onyx->codec_info) - kfree(onyx->codec_info); + kfree(onyx->codec_info); kfree(onyx); return 0; } diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index 3fd1a7e24928..552b97afbca5 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c @@ -1073,10 +1073,10 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) sdev->pcmid = -1; list_del(&ldev->list); layouts_list_items--; + kfree(ldev); outnodev: of_node_put(sound); layout_device = NULL; - kfree(ldev); return -ENODEV; } diff --git a/sound/core/control.c b/sound/core/control.c index f8c5be464510..dc2a44048c85 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1072,8 +1072,8 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, long private_size; struct user_element *ue; int idx, err; - - if (card->user_ctl_count >= MAX_USER_CONTROLS) + + if (!replace && card->user_ctl_count >= MAX_USER_CONTROLS) return -ENOMEM; if (info->count < 1) return -EINVAL; diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 86d0caf91b35..95d1e789715f 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1399,6 +1399,32 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime, EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); +static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + unsigned int base_rate = (unsigned int)(uintptr_t)rule->private; + struct snd_interval *rate; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + return snd_interval_list(rate, 1, &base_rate, 0); +} + +/** + * snd_pcm_hw_rule_noresample - add a rule to allow disabling hw resampling + * @runtime: PCM runtime instance + * @base_rate: the rate at which the hardware does not resample + */ +int snd_pcm_hw_rule_noresample(struct snd_pcm_runtime *runtime, + unsigned int base_rate) +{ + return snd_pcm_hw_rule_add(runtime, SNDRV_PCM_HW_PARAMS_NORESAMPLE, + SNDRV_PCM_HW_PARAM_RATE, + snd_pcm_hw_rule_noresample_func, + (void *)(uintptr_t)base_rate, + SNDRV_PCM_HW_PARAM_RATE, -1); +} +EXPORT_SYMBOL(snd_pcm_hw_rule_noresample); + static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var) { @@ -1761,6 +1787,10 @@ static int wait_for_avail(struct snd_pcm_substream *substream, snd_pcm_uframes_t avail = 0; long wait_time, tout; + init_waitqueue_entry(&wait, current); + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&runtime->tsleep, &wait); + if (runtime->no_period_wakeup) wait_time = MAX_SCHEDULE_TIMEOUT; else { @@ -1771,16 +1801,32 @@ static int wait_for_avail(struct snd_pcm_substream *substream, } wait_time = msecs_to_jiffies(wait_time * 1000); } - init_waitqueue_entry(&wait, current); - add_wait_queue(&runtime->tsleep, &wait); + for (;;) { if (signal_pending(current)) { err = -ERESTARTSYS; break; } + + /* + * We need to check if space became available already + * (and thus the wakeup happened already) first to close + * the race of space already having become available. + * This check must happen after been added to the waitqueue + * and having current state be INTERRUPTIBLE. + */ + if (is_playback) + avail = snd_pcm_playback_avail(runtime); + else + avail = snd_pcm_capture_avail(runtime); + if (avail >= runtime->twake) + break; snd_pcm_stream_unlock_irq(substream); - tout = schedule_timeout_interruptible(wait_time); + + tout = schedule_timeout(wait_time); + snd_pcm_stream_lock_irq(substream); + set_current_state(TASK_INTERRUPTIBLE); switch (runtime->status->state) { case SNDRV_PCM_STATE_SUSPENDED: err = -ESTRPIPE; @@ -1806,14 +1852,9 @@ static int wait_for_avail(struct snd_pcm_substream *substream, err = -EIO; break; } - if (is_playback) - avail = snd_pcm_playback_avail(runtime); - else - avail = snd_pcm_capture_avail(runtime); - if (avail >= runtime->twake) - break; } _endloop: + set_current_state(TASK_RUNNING); remove_wait_queue(&runtime->tsleep, &wait); *availp = avail; return err; diff --git a/sound/core/timer.c b/sound/core/timer.c index 7c1cbf0a0dc4..67ebf1c21c04 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -328,6 +328,8 @@ int snd_timer_close(struct snd_timer_instance *timeri) mutex_unlock(®ister_mutex); } else { timer = timeri->timer; + if (snd_BUG_ON(!timer)) + goto out; /* wait, until the active callback is finished */ spin_lock_irq(&timer->lock); while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) { @@ -353,6 +355,7 @@ int snd_timer_close(struct snd_timer_instance *timeri) } mutex_unlock(®ister_mutex); } + out: if (timeri->private_free) timeri->private_free(timeri); kfree(timeri->owner); @@ -531,6 +534,8 @@ int snd_timer_stop(struct snd_timer_instance *timeri) if (err < 0) return err; timer = timeri->timer; + if (!timer) + return -EINVAL; spin_lock_irqsave(&timer->lock, flags); timeri->cticks = timeri->ticks; timeri->pticks = 0; diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 149d05a8202d..1c02852aceea 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c @@ -86,8 +86,7 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard) } err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0, - irq[dev], irq[dev] >= 0 ? IRQF_DISABLED : 0, - NULL); + irq[dev], NULL); if (err < 0) { printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]); goto _err; diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index 2af09996a3d0..9d01c181feca 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -3,7 +3,7 @@ * Routines for control of MPU-401 in UART mode * * MPU-401 supports UART mode which is not capable generate transmit - * interrupts thus output is done via polling. Also, if irq < 0, then + * interrupts thus output is done via polling. Without interrupt, * input is done also via polling. Do not expect good performance. * * @@ -374,7 +374,7 @@ snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) /* first time - flush FIFO */ while (max-- > 0) mpu->read(mpu, MPU401D(mpu)); - if (mpu->irq < 0) + if (mpu->info_flags & MPU401_INFO_USE_TIMER) snd_mpu401_uart_add_timer(mpu, 1); } @@ -383,7 +383,7 @@ snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) snd_mpu401_uart_input_read(mpu); spin_unlock_irqrestore(&mpu->input_lock, flags); } else { - if (mpu->irq < 0) + if (mpu->info_flags & MPU401_INFO_USE_TIMER) snd_mpu401_uart_remove_timer(mpu, 1); clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode); } @@ -496,7 +496,7 @@ static struct snd_rawmidi_ops snd_mpu401_uart_input = static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi) { struct snd_mpu401 *mpu = rmidi->private_data; - if (mpu->irq_flags && mpu->irq >= 0) + if (mpu->irq >= 0) free_irq(mpu->irq, (void *) mpu); release_and_free_resource(mpu->res); kfree(mpu); @@ -509,8 +509,7 @@ static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi) * @hardware: the hardware type, MPU401_HW_XXXX * @port: the base address of MPU401 port * @info_flags: bitflags MPU401_INFO_XXX - * @irq: the irq number, -1 if no interrupt for mpu - * @irq_flags: the irq request flags (SA_XXX), 0 if irq was already reserved. + * @irq: the ISA irq number, -1 if not to be allocated * @rrawmidi: the pointer to store the new rawmidi instance * * Creates a new MPU-401 instance. @@ -525,7 +524,7 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, unsigned short hardware, unsigned long port, unsigned int info_flags, - int irq, int irq_flags, + int irq, struct snd_rawmidi ** rrawmidi) { struct snd_mpu401 *mpu; @@ -577,8 +576,8 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, mpu->cport = port + 2; else mpu->cport = port + 1; - if (irq >= 0 && irq_flags) { - if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags, + if (irq >= 0) { + if (request_irq(irq, snd_mpu401_uart_interrupt, IRQF_DISABLED, "MPU401 UART", (void *) mpu)) { snd_printk(KERN_ERR "mpu401_uart: " "unable to grab IRQ %d\n", irq); @@ -586,9 +585,10 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, return -EBUSY; } } + if (irq < 0 && !(info_flags & MPU401_INFO_IRQ_HOOK)) + info_flags |= MPU401_INFO_USE_TIMER; mpu->info_flags = info_flags; mpu->irq = irq; - mpu->irq_flags = irq_flags; if (card->shortname[0]) snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI", card->shortname); diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index 440030818db7..cd094ecaca3b 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c @@ -51,7 +51,6 @@ struct isight { struct fw_unit *unit; struct fw_device *device; u64 audio_base; - struct fw_address_handler iris_handler; struct snd_pcm_substream *pcm; struct mutex mutex; struct iso_packets_buffer buffer; diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index 3cb75bc97699..a87a2b566e19 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c @@ -204,7 +204,7 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard if (mpu_port[dev] > 0) { if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port[dev], 0, mpu_irq[dev], IRQF_DISABLED, + mpu_port[dev], 0, mpu_irq[dev], NULL) < 0) printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", mpu_port[dev]); } diff --git a/sound/isa/als100.c b/sound/isa/als100.c index 20becc89f6f6..706effd6b3cd 100644 --- a/sound/isa/als100.c +++ b/sound/isa/als100.c @@ -256,7 +256,6 @@ static int __devinit snd_card_als100_probe(int dev, mpu_type, mpu_port[dev], 0, mpu_irq[dev], - mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0, NULL) < 0) snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]); } diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c index aac8dc15c2fe..b7bdbf307740 100644 --- a/sound/isa/azt2320.c +++ b/sound/isa/azt2320.c @@ -234,8 +234,7 @@ static int __devinit snd_card_azt2320_probe(int dev, if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { if (snd_mpu401_uart_new(card, 0, MPU401_HW_AZT2320, mpu_port[dev], 0, - mpu_irq[dev], IRQF_DISABLED, - NULL) < 0) + mpu_irq[dev], NULL) < 0) snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]); } diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index fe79a169acb5..dca69f80305f 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -597,7 +597,7 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) if (mpuport[dev] != SNDRV_AUTO_PORT) { if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, mpuport[dev], 0, mpuirq[dev], - IRQF_DISABLED, NULL) < 0) + NULL) < 0) printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", mpuport[dev]); } diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index cb9153e75b82..409fa0ad7843 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c @@ -131,7 +131,6 @@ static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n) mpu_irq[n] = -1; if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232, mpu_port[n], 0, mpu_irq[n], - mpu_irq[n] >= 0 ? IRQF_DISABLED : 0, NULL) < 0) dev_warn(dev, "MPU401 not detected\n"); } diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 999dc1e0fdbd..0dbde461e6c1 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -449,8 +449,7 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev) mpu_irq[dev] = -1; if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232, mpu_port[dev], 0, - mpu_irq[dev], - mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0, NULL) < 0) + mpu_irq[dev], NULL) < 0) printk(KERN_WARNING IDENT ": MPU401 not detected\n"); } diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index 0cde8131a575..5493e9e4bcd5 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c @@ -174,7 +174,7 @@ static int __devinit snd_es1688_probe(struct snd_card *card, unsigned int n) chip->mpu_port > 0) { error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, chip->mpu_port, 0, - mpu_irq[n], IRQF_DISABLED, NULL); + mpu_irq[n], NULL); if (error < 0) return error; } diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index fb4d6b34bbca..aeee8f8bf5e9 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -2160,8 +2160,8 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev) if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX, - mpu_port[dev], 0, - irq[dev], 0, &chip->rmidi); + mpu_port[dev], MPU401_INFO_IRQ_HOOK, + -1, &chip->rmidi); if (err < 0) return err; } diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c index ee54df082b9c..e51d3244742a 100644 --- a/sound/isa/galaxy/galaxy.c +++ b/sound/isa/galaxy/galaxy.c @@ -585,8 +585,7 @@ static int __devinit snd_galaxy_probe(struct device *dev, unsigned int n) if (mpu_port[n] >= 0) { err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port[n], 0, mpu_irq[n], - IRQF_DISABLED, NULL); + mpu_port[n], 0, mpu_irq[n], NULL); if (err < 0) goto error; } diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index 008e8e5bfa37..c4733c08b60b 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c @@ -317,8 +317,7 @@ static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n) if (es1688->mpu_port >= 0x300) { error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, - es1688->mpu_port, 0, - mpu_irq[n], IRQF_DISABLED, NULL); + es1688->mpu_port, 0, mpu_irq[n], NULL); if (error < 0) goto out; } diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 91d6023a63e5..0961e2cf20ca 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -600,7 +600,7 @@ static int __devinit snd_msnd_attach(struct snd_card *card) mpu_io[0], MPU401_MODE_INPUT | MPU401_MODE_OUTPUT, - mpu_irq[0], IRQF_DISABLED, + mpu_irq[0], &chip->rmidi); if (err < 0) { printk(KERN_ERR LOGNAME diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 9b915e27b5bd..de99f47770bf 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -707,8 +707,9 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev) } if (midi_port[dev] >= 0x300 && midi_port[dev] < 0x340) { if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_OPL3SA2, - midi_port[dev], 0, - xirq, 0, &chip->rmidi)) < 0) + midi_port[dev], + MPU401_INFO_IRQ_HOOK, -1, + &chip->rmidi)) < 0) return err; } sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 8c24102d0d93..d94d0f35cb76 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -1377,8 +1377,7 @@ static int __devinit snd_miro_probe(struct snd_card *card) rmidi = NULL; else { error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port, 0, miro->mpu_irq, IRQF_DISABLED, - &rmidi); + mpu_port, 0, miro->mpu_irq, &rmidi); if (error < 0) snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", mpu_port); diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index c35dc68930dc..346e12baa98e 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -914,7 +914,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) rmidi = NULL; else { error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port, 0, mpu_irq, IRQF_DISABLED, &rmidi); + mpu_port, 0, mpu_irq, &rmidi); if (error) snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", mpu_port); diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c index 8ccbcddf08e1..54e3c2c18060 100644 --- a/sound/isa/sb/jazz16.c +++ b/sound/isa/sb/jazz16.c @@ -322,7 +322,6 @@ static int __devinit snd_jazz16_probe(struct device *devptr, unsigned int dev) MPU401_HW_MPU401, mpu_port[dev], 0, mpu_irq[dev], - mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0, NULL) < 0) snd_printk(KERN_ERR "no MPU-401 device at 0x%lx\n", mpu_port[dev]); diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 4d1c5a300ff8..237f8bd7fbe4 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -394,8 +394,9 @@ static int __devinit snd_sb16_probe(struct snd_card *card, int dev) if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) { if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB, - chip->mpu_port, 0, - xirq, 0, &chip->rmidi)) < 0) + chip->mpu_port, + MPU401_INFO_IRQ_HOOK, -1, + &chip->rmidi)) < 0) return err; chip->rmidi_callback = snd_mpu401_uart_interrupt; } diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index 9a8bbf6dd62a..207c161f100c 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -658,8 +658,7 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, mpu_port[dev], 0, - mpu_irq[dev], IRQF_DISABLED, - NULL) < 0) + mpu_irq[dev], NULL) < 0) snd_printk(KERN_ERR "no MPU-401 device at 0x%lx ?\n", mpu_port[dev]); } diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index e2d5d2d3ed96..f2379e102b63 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -825,8 +825,7 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum, int err; err = snd_mpu401_uart_new(card, devnum, MPU401_HW_MPU401, port, - MPU401_INFO_INTEGRATED, irq, IRQF_DISABLED, - &rawmidi); + MPU401_INFO_INTEGRATED, irq, &rawmidi); if (err == 0) { struct snd_mpu401 *mpu = rawmidi->private_data; mpu->open_input = mpu401_open; diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 711670e4a425..83f291d89a95 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -449,8 +449,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) { err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232, cs4232_mpu_port[dev], 0, - cs4232_mpu_irq[dev], IRQF_DISABLED, - NULL); + cs4232_mpu_irq[dev], NULL); if (err < 0) { snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n"); return err; diff --git a/sound/oss/pas2_pcm.c b/sound/oss/pas2_pcm.c index 8f7d175767a2..6f13ab4afc6b 100644 --- a/sound/oss/pas2_pcm.c +++ b/sound/oss/pas2_pcm.c @@ -63,13 +63,13 @@ static int pcm_set_speed(int arg) if (pcm_channels & 2) { - foo = ((CLOCK_TICK_RATE / 2) + (arg / 2)) / arg; - arg = ((CLOCK_TICK_RATE / 2) + (foo / 2)) / foo; + foo = ((PIT_TICK_RATE / 2) + (arg / 2)) / arg; + arg = ((PIT_TICK_RATE / 2) + (foo / 2)) / foo; } else { - foo = (CLOCK_TICK_RATE + (arg / 2)) / arg; - arg = (CLOCK_TICK_RATE + (foo / 2)) / foo; + foo = (PIT_TICK_RATE + (arg / 2)) / arg; + arg = (PIT_TICK_RATE + (foo / 2)) / foo; } pcm_speed = arg; diff --git a/sound/oss/pss.c b/sound/oss/pss.c index 9b800ce5100e..2fc0624024b5 100644 --- a/sound/oss/pss.c +++ b/sound/oss/pss.c @@ -673,7 +673,8 @@ static void configure_nonsound_components(void) if (pss_cdrom_port == -1) { /* If cdrom port enablation wasn't requested */ printk(KERN_INFO "PSS: CDROM port not enabled.\n"); - } else if (check_region(pss_cdrom_port, 2)) { + } else if (!request_region(pss_cdrom_port, 2, "PSS CDROM")) { + pss_cdrom_port = -1; printk(KERN_ERR "PSS: CDROM I/O port conflict.\n"); } else { set_io_base(devc, CONF_CDROM, pss_cdrom_port); @@ -1232,7 +1233,8 @@ static void __exit cleanup_pss(void) if(pssmpu) unload_pss_mpu(&cfg_mpu); unload_pss(&cfg); - } + } else if (pss_cdrom_port != -1) + release_region(pss_cdrom_port, 2); if(!pss_keep_settings) /* Keep hardware settings if asked */ { diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 50abf5bf8e09..88168044375f 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -1,5 +1,10 @@ # ALSA PCI drivers +config SND_TEA575X + tristate + depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 + default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 + menuconfig SND_PCI bool "PCI sound devices" depends on PCI @@ -563,11 +568,6 @@ config SND_FM801_TEA575X_BOOL FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and SF64-PCR) into the snd-fm801 driver. -config SND_TEA575X - tristate - depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 - default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 - source "sound/pci/hda/Kconfig" config SND_HDSP diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 200c9a1d48b7..a872d0a82976 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1909,6 +1909,7 @@ static unsigned int ad1981_jacks_whitelist[] = { 0x103c0944, /* HP nc6220 */ 0x103c0934, /* HP nc8220 */ 0x103c006d, /* HP nx9105 */ + 0x103c300d, /* HP Compaq dc5100 SFF(PT003AW) */ 0x17340088, /* FSC Scenic-W */ 0 /* end */ }; diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index a9c1af33f276..04628696eb08 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -931,8 +931,9 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000, iobase + ALS4K_IOB_30_MIDI_DATA, - MPU401_INFO_INTEGRATED, - pci->irq, 0, &chip->rmidi)) < 0) { + MPU401_INFO_INTEGRATED | + MPU401_INFO_IRQ_HOOK, + -1, &chip->rmidi)) < 0) { printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n", iobase + ALS4K_IOB_30_MIDI_DATA); goto out_err; diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c index 65b7ca13115b..bd47521b24ec 100644 --- a/sound/pci/asihpi/hpicmn.c +++ b/sound/pci/asihpi/hpicmn.c @@ -631,13 +631,12 @@ struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count, if (!p_cache) return NULL; - p_cache->p_info = - kmalloc(sizeof(*p_cache->p_info) * control_count, GFP_KERNEL); + p_cache->p_info = kzalloc(sizeof(*p_cache->p_info) * control_count, + GFP_KERNEL); if (!p_cache->p_info) { kfree(p_cache); return NULL; } - memset(p_cache->p_info, 0, sizeof(*p_cache->p_info) * control_count); p_cache->cache_size_in_bytes = size_in_bytes; p_cache->control_count = control_count; p_cache->p_cache = p_dsp_control_buffer; diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c index 0dc8d259d1ed..e6c6a0febb75 100644 --- a/sound/pci/au88x0/au88x0_mpu401.c +++ b/sound/pci/au88x0/au88x0_mpu401.c @@ -84,7 +84,7 @@ static int __devinit snd_vortex_midi(vortex_t * vortex) #ifdef VORTEX_MPU401_LEGACY if ((temp = snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_MPU401, 0x330, - 0, 0, 0, &rmidi)) != 0) { + MPU401_INFO_IRQ_HOOK, -1, &rmidi)) != 0) { hwwrite(vortex->mmio, VORTEX_CTRL, (hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN); @@ -94,8 +94,8 @@ static int __devinit snd_vortex_midi(vortex_t * vortex) port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA); if ((temp = snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port, - MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO, - 0, 0, &rmidi)) != 0) { + MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO | + MPU401_INFO_IRQ_HOOK, -1, &rmidi)) != 0) { hwwrite(vortex->mmio, VORTEX_CTRL, (hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN); diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index e4d76a270c9f..d24fe425e87f 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -2625,16 +2625,19 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) int err; snd_azf3328_dbgcallenter(); - if (dev >= SNDRV_CARDS) - return -ENODEV; + if (dev >= SNDRV_CARDS) { + err = -ENODEV; + goto out; + } if (!enable[dev]) { dev++; - return -ENOENT; + err = -ENOENT; + goto out; } err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); if (err < 0) - return err; + goto out; strcpy(card->driver, "AZF3328"); strcpy(card->shortname, "Aztech AZF3328 (PCI168)"); @@ -2649,8 +2652,9 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) since our hardware ought to be similar, thus use same ID. */ err = snd_mpu401_uart_new( card, 0, - MPU401_HW_AZT2320, chip->mpu_io, MPU401_INFO_INTEGRATED, - pci->irq, 0, &chip->rmidi + MPU401_HW_AZT2320, chip->mpu_io, + MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, + -1, &chip->rmidi ); if (err < 0) { snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n", diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 9cf99fb7eb9c..da9c73211eca 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -3228,8 +3228,9 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, iomidi, (integrated_midi ? - MPU401_INFO_INTEGRATED : 0), - cm->irq, 0, &cm->rmidi)) < 0) { + MPU401_INFO_INTEGRATED : 0) | + MPU401_INFO_IRQ_HOOK, + -1, &cm->rmidi)) < 0) { printk(KERN_ERR "cmipci: no UART401 device at 0x%lx\n", iomidi); } } diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c index 457d21189b0d..2c8622617c8c 100644 --- a/sound/pci/ctxfi/ctpcm.c +++ b/sound/pci/ctxfi/ctpcm.c @@ -404,7 +404,7 @@ int ct_alsa_pcm_create(struct ct_atc *atc, int err; int playback_count, capture_count; - playback_count = (IEC958 == device) ? 1 : 8; + playback_count = (IEC958 == device) ? 1 : 256; capture_count = (FRONT == device) ? 1 : 0; err = snd_pcm_new(atc->card, "ctxfi", device, playback_count, capture_count, &pcm); diff --git a/sound/pci/ctxfi/ctsrc.c b/sound/pci/ctxfi/ctsrc.c index c749fa720889..e134b3a5780d 100644 --- a/sound/pci/ctxfi/ctsrc.c +++ b/sound/pci/ctxfi/ctsrc.c @@ -20,7 +20,7 @@ #include "cthardware.h" #include <linux/slab.h> -#define SRC_RESOURCE_NUM 64 +#define SRC_RESOURCE_NUM 256 #define SRCIMP_RESOURCE_NUM 256 static unsigned int conj_mask; diff --git a/sound/pci/ctxfi/ctvmem.h b/sound/pci/ctxfi/ctvmem.h index b23adfca4de6..e6da60eb19ce 100644 --- a/sound/pci/ctxfi/ctvmem.h +++ b/sound/pci/ctxfi/ctvmem.h @@ -18,7 +18,7 @@ #ifndef CTVMEM_H #define CTVMEM_H -#define CT_PTP_NUM 1 /* num of device page table pages */ +#define CT_PTP_NUM 4 /* num of device page table pages */ #include <linux/mutex.h> #include <linux/list.h> diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 622bace148e3..e22b8e2bbd88 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -1146,6 +1146,11 @@ static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream) kfree(epcm); return err; } + err = snd_pcm_hw_rule_noresample(runtime, 48000); + if (err < 0) { + kfree(epcm); + return err; + } mix = &emu->pcm_mixer[substream->number]; for (i = 0; i < 4; i++) mix->send_routing[0][i] = mix->send_routing[1][i] = mix->send_routing[2][i] = i; diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 26a5a2f25d4b..718a2643474e 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -1854,8 +1854,9 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci, } } if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - chip->mpu_port, MPU401_INFO_INTEGRATED, - chip->irq, 0, &chip->rmidi) < 0) { + chip->mpu_port, + MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, + -1, &chip->rmidi) < 0) { printk(KERN_ERR "es1938: unable to initialize MPU-401\n"); } else { // this line is vital for MIDI interrupt handling on ess-solo1 diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 99ea9320c6b5..407e4abc4356 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -2843,8 +2843,9 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci, if (enable_mpu[dev]) { if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, chip->io_port + ESM_MPU401_PORT, - MPU401_INFO_INTEGRATED, - chip->irq, 0, &chip->rmidi)) < 0) { + MPU401_INFO_INTEGRATED | + MPU401_INFO_IRQ_HOOK, + -1, &chip->rmidi)) < 0) { printk(KERN_WARNING "es1968: skipping MPU-401 MIDI support..\n"); } } diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index f9123f09e83e..c55b1b319b74 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -1306,8 +1306,9 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci, } if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801, FM801_REG(chip, MPU401_DATA), - MPU401_INFO_INTEGRATED, - chip->irq, 0, &chip->rmidi)) < 0) { + MPU401_INFO_INTEGRATED | + MPU401_INFO_IRQ_HOOK, + -1, &chip->rmidi)) < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/hda/alc268_quirks.c b/sound/pci/hda/alc268_quirks.c index be58bf2f3aec..2e5876ce71fe 100644 --- a/sound/pci/hda/alc268_quirks.c +++ b/sound/pci/hda/alc268_quirks.c @@ -476,8 +476,8 @@ static const struct snd_pci_quirk alc268_ssid_cfg_tbl[] = { static const struct alc_config_preset alc268_presets[] = { [ALC267_QUANTA_IL1] = { - .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer, - alc268_capture_nosrc_mixer }, + .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer }, + .cap_mixer = alc268_capture_nosrc_mixer, .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, alc267_quanta_il1_verbs }, .num_dacs = ARRAY_SIZE(alc268_dac_nids), @@ -492,8 +492,8 @@ static const struct alc_config_preset alc268_presets[] = { .init_hook = alc_inithook, }, [ALC268_3ST] = { - .mixers = { alc268_base_mixer, alc268_capture_alt_mixer, - alc268_beep_mixer }, + .mixers = { alc268_base_mixer, alc268_beep_mixer }, + .cap_mixer = alc268_capture_alt_mixer, .init_verbs = { alc268_base_init_verbs }, .num_dacs = ARRAY_SIZE(alc268_dac_nids), .dac_nids = alc268_dac_nids, @@ -507,8 +507,8 @@ static const struct alc_config_preset alc268_presets[] = { .input_mux = &alc268_capture_source, }, [ALC268_TOSHIBA] = { - .mixers = { alc268_toshiba_mixer, alc268_capture_alt_mixer, - alc268_beep_mixer }, + .mixers = { alc268_toshiba_mixer, alc268_beep_mixer }, + .cap_mixer = alc268_capture_alt_mixer, .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, alc268_toshiba_verbs }, .num_dacs = ARRAY_SIZE(alc268_dac_nids), @@ -525,8 +525,8 @@ static const struct alc_config_preset alc268_presets[] = { .init_hook = alc_inithook, }, [ALC268_ACER] = { - .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer, - alc268_beep_mixer }, + .mixers = { alc268_acer_mixer, alc268_beep_mixer }, + .cap_mixer = alc268_capture_alt_mixer, .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, alc268_acer_verbs }, .num_dacs = ARRAY_SIZE(alc268_dac_nids), @@ -543,8 +543,8 @@ static const struct alc_config_preset alc268_presets[] = { .init_hook = alc_inithook, }, [ALC268_ACER_DMIC] = { - .mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer, - alc268_beep_mixer }, + .mixers = { alc268_acer_dmic_mixer, alc268_beep_mixer }, + .cap_mixer = alc268_capture_alt_mixer, .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, alc268_acer_verbs }, .num_dacs = ARRAY_SIZE(alc268_dac_nids), @@ -561,9 +561,8 @@ static const struct alc_config_preset alc268_presets[] = { .init_hook = alc_inithook, }, [ALC268_ACER_ASPIRE_ONE] = { - .mixers = { alc268_acer_aspire_one_mixer, - alc268_beep_mixer, - alc268_capture_nosrc_mixer }, + .mixers = { alc268_acer_aspire_one_mixer, alc268_beep_mixer}, + .cap_mixer = alc268_capture_nosrc_mixer, .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, alc268_acer_aspire_one_verbs }, .num_dacs = ARRAY_SIZE(alc268_dac_nids), @@ -579,8 +578,8 @@ static const struct alc_config_preset alc268_presets[] = { .init_hook = alc_inithook, }, [ALC268_DELL] = { - .mixers = { alc268_dell_mixer, alc268_beep_mixer, - alc268_capture_nosrc_mixer }, + .mixers = { alc268_dell_mixer, alc268_beep_mixer}, + .cap_mixer = alc268_capture_nosrc_mixer, .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, alc268_dell_verbs }, .num_dacs = ARRAY_SIZE(alc268_dac_nids), @@ -596,8 +595,8 @@ static const struct alc_config_preset alc268_presets[] = { .init_hook = alc_inithook, }, [ALC268_ZEPTO] = { - .mixers = { alc268_base_mixer, alc268_capture_alt_mixer, - alc268_beep_mixer }, + .mixers = { alc268_base_mixer, alc268_beep_mixer }, + .cap_mixer = alc268_capture_alt_mixer, .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, alc268_toshiba_verbs }, .num_dacs = ARRAY_SIZE(alc268_dac_nids), @@ -616,7 +615,8 @@ static const struct alc_config_preset alc268_presets[] = { }, #ifdef CONFIG_SND_DEBUG [ALC268_TEST] = { - .mixers = { alc268_test_mixer, alc268_capture_mixer }, + .mixers = { alc268_test_mixer }, + .cap_mixer = alc268_capture_mixer, .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, alc268_volume_init_verbs, alc268_beep_init_verbs }, diff --git a/sound/pci/hda/alc269_quirks.c b/sound/pci/hda/alc269_quirks.c index 14fdcf29b154..5ac0e2162a46 100644 --- a/sound/pci/hda/alc269_quirks.c +++ b/sound/pci/hda/alc269_quirks.c @@ -531,17 +531,10 @@ static const struct snd_pci_quirk alc269_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC), SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC), SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC), - SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_DMIC), SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC), SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC), SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC), SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC), - SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901", - ALC269_DMIC), - SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101", - ALC269_DMIC), - SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC), - SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC), SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_AUTO), SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK), SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC), diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 3e7850c238c3..f3aefef37216 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -579,9 +579,13 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, return -1; } recursive++; - for (i = 0; i < nums; i++) + for (i = 0; i < nums; i++) { + unsigned int type = get_wcaps_type(get_wcaps(codec, conn[i])); + if (type == AC_WID_PIN || type == AC_WID_AUD_OUT) + continue; if (snd_hda_get_conn_index(codec, conn[i], nid, recursive) >= 0) return i; + } return -1; } EXPORT_SYMBOL_HDA(snd_hda_get_conn_index); diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 28ce17d09c33..c34f730f4815 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -144,25 +144,17 @@ static int cea_sampling_frequencies[8] = { SNDRV_PCM_RATE_192000, /* 7: 192000Hz */ }; -static unsigned char hdmi_get_eld_byte(struct hda_codec *codec, hda_nid_t nid, +static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid, int byte_index) { unsigned int val; val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_ELDD, byte_index); - #ifdef BE_PARANOID printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val); #endif - - if ((val & AC_ELDD_ELD_VALID) == 0) { - snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n", - byte_index); - val = 0; - } - - return val & AC_ELDD_ELD_DATA; + return val; } #define GRAB_BITS(buf, byte, lowbit, bits) \ @@ -344,11 +336,26 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, if (!buf) return -ENOMEM; - for (i = 0; i < size; i++) - buf[i] = hdmi_get_eld_byte(codec, nid, i); + for (i = 0; i < size; i++) { + unsigned int val = hdmi_get_eld_data(codec, nid, i); + if (!(val & AC_ELDD_ELD_VALID)) { + if (!i) { + snd_printd(KERN_INFO + "HDMI: invalid ELD data\n"); + ret = -EINVAL; + goto error; + } + snd_printd(KERN_INFO + "HDMI: invalid ELD data byte %d\n", i); + val = 0; + } else + val &= AC_ELDD_ELD_DATA; + buf[i] = val; + } ret = hdmi_update_eld(eld, buf, size); +error: kfree(buf); return ret; } diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 47d6ffc9b5b5..c45f3e69bcf0 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -375,7 +375,7 @@ static int is_ext_mic(struct hda_codec *codec, unsigned int idx) static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, unsigned int *idxp) { - int i; + int i, idx; hda_nid_t nid; nid = codec->start_nid; @@ -384,9 +384,11 @@ static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, type = get_wcaps_type(get_wcaps(codec, nid)); if (type != AC_WID_AUD_IN) continue; - *idxp = snd_hda_get_conn_index(codec, nid, pin, false); - if (*idxp >= 0) + idx = snd_hda_get_conn_index(codec, nid, pin, false); + if (idx >= 0) { + *idxp = idx; return nid; + } } return 0; } @@ -533,7 +535,7 @@ static int add_volume(struct hda_codec *codec, const char *name, int index, unsigned int pval, int dir, struct snd_kcontrol **kctlp) { - char tmp[32]; + char tmp[44]; struct snd_kcontrol_new knew = HDA_CODEC_VOLUME_IDX(tmp, index, 0, 0, HDA_OUTPUT); knew.private_value = pval; diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 502fc9499453..7696d05b9356 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3348,6 +3348,8 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t pin, #define MAX_AUTO_DACS 5 +#define DAC_SLAVE_FLAG 0x8000 /* filled dac is a slave */ + /* fill analog DAC list from the widget tree */ static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs) { @@ -3370,16 +3372,26 @@ static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs) /* fill pin_dac_pair list from the pin and dac list */ static int fill_dacs_for_pins(struct hda_codec *codec, hda_nid_t *pins, int num_pins, hda_nid_t *dacs, int *rest, - struct pin_dac_pair *filled, int type) + struct pin_dac_pair *filled, int nums, + int type) { - int i, nums; + int i, start = nums; - nums = 0; - for (i = 0; i < num_pins; i++) { + for (i = 0; i < num_pins; i++, nums++) { filled[nums].pin = pins[i]; filled[nums].type = type; filled[nums].dac = get_unassigned_dac(codec, pins[i], dacs, rest); - nums++; + if (filled[nums].dac) + continue; + if (filled[start].dac && get_connection_index(codec, pins[i], filled[start].dac) >= 0) { + filled[nums].dac = filled[start].dac | DAC_SLAVE_FLAG; + continue; + } + if (filled[0].dac && get_connection_index(codec, pins[i], filled[0].dac) >= 0) { + filled[nums].dac = filled[0].dac | DAC_SLAVE_FLAG; + continue; + } + snd_printdd("Failed to find a DAC for pin 0x%x", pins[i]); } return nums; } @@ -3395,19 +3407,19 @@ static void cx_auto_parse_output(struct hda_codec *codec) rest = fill_cx_auto_dacs(codec, dacs); /* parse all analog output pins */ nums = fill_dacs_for_pins(codec, cfg->line_out_pins, cfg->line_outs, - dacs, &rest, spec->dac_info, - AUTO_PIN_LINE_OUT); - nums += fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs, - dacs, &rest, spec->dac_info + nums, - AUTO_PIN_HP_OUT); - nums += fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs, - dacs, &rest, spec->dac_info + nums, - AUTO_PIN_SPEAKER_OUT); + dacs, &rest, spec->dac_info, 0, + AUTO_PIN_LINE_OUT); + nums = fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs, + dacs, &rest, spec->dac_info, nums, + AUTO_PIN_HP_OUT); + nums = fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs, + dacs, &rest, spec->dac_info, nums, + AUTO_PIN_SPEAKER_OUT); spec->dac_info_filled = nums; /* fill multiout struct */ for (i = 0; i < nums; i++) { hda_nid_t dac = spec->dac_info[i].dac; - if (!dac) + if (!dac || (dac & DAC_SLAVE_FLAG)) continue; switch (spec->dac_info[i].type) { case AUTO_PIN_LINE_OUT: @@ -3862,7 +3874,7 @@ static void cx_auto_parse_input(struct hda_codec *codec) } if (imux->num_items >= 2 && cfg->num_inputs == imux->num_items) cx_auto_check_auto_mic(codec); - if (imux->num_items > 1 && !spec->auto_mic) { + if (imux->num_items > 1) { for (i = 1; i < imux->num_items; i++) { if (spec->imux_info[i].adc != spec->imux_info[0].adc) { spec->adc_switching = 1; @@ -4035,6 +4047,8 @@ static void cx_auto_init_output(struct hda_codec *codec) nid = spec->dac_info[i].dac; if (!nid) nid = spec->multiout.dac_nids[0]; + else if (nid & DAC_SLAVE_FLAG) + nid &= ~DAC_SLAVE_FLAG; select_connection(codec, spec->dac_info[i].pin, nid); } if (spec->auto_mute) { @@ -4167,9 +4181,11 @@ static int try_add_pb_volume(struct hda_codec *codec, hda_nid_t dac, hda_nid_t pin, const char *name, int idx) { unsigned int caps; - caps = query_amp_caps(codec, dac, HDA_OUTPUT); - if (caps & AC_AMPCAP_NUM_STEPS) - return cx_auto_add_pb_volume(codec, dac, name, idx); + if (dac && !(dac & DAC_SLAVE_FLAG)) { + caps = query_amp_caps(codec, dac, HDA_OUTPUT); + if (caps & AC_AMPCAP_NUM_STEPS) + return cx_auto_add_pb_volume(codec, dac, name, idx); + } caps = query_amp_caps(codec, pin, HDA_OUTPUT); if (caps & AC_AMPCAP_NUM_STEPS) return cx_auto_add_pb_volume(codec, pin, name, idx); @@ -4191,8 +4207,7 @@ static int cx_auto_build_output_controls(struct hda_codec *codec) for (i = 0; i < spec->dac_info_filled; i++) { const char *label; int idx, type; - if (!spec->dac_info[i].dac) - continue; + hda_nid_t dac = spec->dac_info[i].dac; type = spec->dac_info[i].type; if (type == AUTO_PIN_LINE_OUT) type = spec->autocfg.line_out_type; @@ -4211,7 +4226,7 @@ static int cx_auto_build_output_controls(struct hda_codec *codec) idx = num_spk++; break; } - err = try_add_pb_volume(codec, spec->dac_info[i].dac, + err = try_add_pb_volume(codec, dac, spec->dac_info[i].pin, label, idx); if (err < 0) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e125c60fe352..7cabd7317163 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -565,11 +565,11 @@ static void alc_hp_automute(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - if (!spec->automute) - return; spec->jack_present = detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins), spec->autocfg.hp_pins); + if (!spec->automute) + return; update_speakers(codec); } @@ -578,11 +578,11 @@ static void alc_line_automute(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - if (!spec->automute || !spec->detect_line) - return; spec->line_jack_present = detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins), spec->autocfg.line_out_pins); + if (!spec->automute || !spec->detect_line) + return; update_speakers(codec); } @@ -1784,6 +1784,7 @@ static const char * const alc_slave_vols[] = { "Speaker Playback Volume", "Mono Playback Volume", "Line-Out Playback Volume", + "PCM Playback Volume", NULL, }; @@ -1798,6 +1799,7 @@ static const char * const alc_slave_sws[] = { "Mono Playback Switch", "IEC958 Playback Switch", "Line-Out Playback Switch", + "PCM Playback Switch", NULL, }; @@ -3081,16 +3083,22 @@ static void alc_auto_init_multi_out(struct hda_codec *codec) static void alc_auto_init_extra_out(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - hda_nid_t pin; + hda_nid_t pin, dac; pin = spec->autocfg.hp_pins[0]; - if (pin) - alc_auto_set_output_and_unmute(codec, pin, PIN_HP, - spec->multiout.hp_nid); + if (pin) { + dac = spec->multiout.hp_nid; + if (!dac) + dac = spec->multiout.dac_nids[0]; + alc_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); + } pin = spec->autocfg.speaker_pins[0]; - if (pin) - alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, - spec->multiout.extra_out_nid[0]); + if (pin) { + dac = spec->multiout.extra_out_nid[0]; + if (!dac) + dac = spec->multiout.dac_nids[0]; + alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac); + } } /* @@ -4484,6 +4492,22 @@ static void alc269_fixup_pcm_44k(struct hda_codec *codec, spec->stream_analog_capture = &alc269_44k_pcm_analog_capture; } +static void alc269_fixup_stereo_dmic(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + int coef; + + if (action != ALC_FIXUP_ACT_INIT) + return; + /* The digital-mic unit sends PDM (differential signal) instead of + * the standard PCM, thus you can't record a valid mono stream as is. + * Below is a workaround specific to ALC269 to control the dmic + * signal source as mono. + */ + coef = alc_read_coef_idx(codec, 0x07); + alc_write_coef_idx(codec, 0x07, coef | 0x80); +} + enum { ALC269_FIXUP_SONY_VAIO, ALC275_FIXUP_SONY_VAIO_GPIO2, @@ -4494,6 +4518,7 @@ enum { ALC275_FIXUP_SONY_HWEQ, ALC271_FIXUP_DMIC, ALC269_FIXUP_PCM_44K, + ALC269_FIXUP_STEREO_DMIC, }; static const struct alc_fixup alc269_fixups[] = { @@ -4556,10 +4581,19 @@ static const struct alc_fixup alc269_fixups[] = { .type = ALC_FIXUP_FUNC, .v.func = alc269_fixup_pcm_44k, }, + [ALC269_FIXUP_STEREO_DMIC] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc269_fixup_stereo_dmic, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), + SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2), SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index aa376b59c006..5145b663ef6e 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -673,6 +673,7 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, return 0; } +#ifdef CONFIG_SND_HDA_POWER_SAVE static int stac_vrefout_set(struct hda_codec *codec, hda_nid_t nid, unsigned int new_vref) { @@ -696,6 +697,7 @@ static int stac_vrefout_set(struct hda_codec *codec, return 1; } +#endif static unsigned int stac92xx_vref_set(struct hda_codec *codec, hda_nid_t nid, unsigned int new_vref) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 84d8798bf33a..4ebfbd874c9a 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -2084,7 +2084,7 @@ static int via_auto_create_speaker_ctls(struct hda_codec *codec) struct via_spec *spec = codec->spec; struct nid_path *path; bool check_dac; - hda_nid_t pin, dac; + hda_nid_t pin, dac = 0; int err; pin = spec->autocfg.speaker_pins[0]; diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 0ccc0eb75775..8531b983f3af 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -2748,8 +2748,9 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, if (!c->no_mpu401) { err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712, ICEREG(ice, MPU1_CTRL), - (c->mpu401_1_info_flags | MPU401_INFO_INTEGRATED), - ice->irq, 0, &ice->rmidi[0]); + c->mpu401_1_info_flags | + MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, + -1, &ice->rmidi[0]); if (err < 0) { snd_card_free(card); return err; @@ -2764,8 +2765,9 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, /* 2nd port used */ err = snd_mpu401_uart_new(card, 1, MPU401_HW_ICE1712, ICEREG(ice, MPU2_CTRL), - (c->mpu401_2_info_flags | MPU401_INFO_INTEGRATED), - ice->irq, 0, &ice->rmidi[1]); + c->mpu401_2_info_flags | + MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, + -1, &ice->rmidi[1]); if (err < 0) { snd_card_free(card); diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 0378126e6272..2fd4bf2d6653 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -2820,8 +2820,8 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) /* TODO enable MIDI IRQ and I/O */ err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401, chip->iobase + MPU401_DATA_PORT, - MPU401_INFO_INTEGRATED, - chip->irq, 0, &chip->rmidi); + MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, + -1, &chip->rmidi); if (err < 0) printk(KERN_WARNING "maestro3: no MIDI support.\n"); #endif diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 82311fcb86f6..53e5508abcbf 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c @@ -678,15 +678,15 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, goto err_card; if (chip->model.device_config & (MIDI_OUTPUT | MIDI_INPUT)) { - unsigned int info_flags = MPU401_INFO_INTEGRATED; + unsigned int info_flags = + MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK; if (chip->model.device_config & MIDI_OUTPUT) info_flags |= MPU401_INFO_OUTPUT; if (chip->model.device_config & MIDI_INPUT) info_flags |= MPU401_INFO_INPUT; err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, chip->addr + OXYGEN_MPU401, - info_flags, 0, 0, - &chip->midi); + info_flags, -1, &chip->midi); if (err < 0) goto err_card; } diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c index 32d096c98f5b..8433aa7c3d75 100644 --- a/sound/pci/oxygen/xonar_pcm179x.c +++ b/sound/pci/oxygen/xonar_pcm179x.c @@ -1074,6 +1074,7 @@ static const struct oxygen_model model_xonar_st = { .device_config = PLAYBACK_0_TO_I2S | PLAYBACK_1_TO_SPDIF | CAPTURE_0_FROM_I2S_2 | + CAPTURE_1_FROM_SPDIF | AC97_FMIC_SWITCH, .dac_channels_pcm = 2, .dac_channels_mixer = 2, diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index e34ae14908b3..88cc776aa38b 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -2109,7 +2109,7 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) val = mpu_port[dev]; pci_write_config_word(chip->pci, PCI_EXT_MPU_Base, val); err = snd_mpu401_uart_new(card, 0, MPU401_HW_RIPTIDE, - val, 0, chip->irq, 0, + val, MPU401_INFO_IRQ_HOOK, -1, &chip->rmidi); if (err < 0) snd_printk(KERN_WARNING diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 6edc67ced905..214110d6a2bf 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1241,10 +1241,30 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) return rate; } +/* return latency in samples per period */ +static int hdspm_get_latency(struct hdspm *hdspm) +{ + int n; + + n = hdspm_decode_latency(hdspm->control_register); + + /* Special case for new RME cards with 32 samples period size. + * The three latency bits in the control register + * (HDSP_LatencyMask) encode latency values of 64 samples as + * 0, 128 samples as 1 ... 4096 samples as 6. For old cards, 7 + * denotes 8192 samples, but on new cards like RayDAT or AIO, + * it corresponds to 32 samples. + */ + if ((7 == n) && (RayDAT == hdspm->io_type || AIO == hdspm->io_type)) + n = -1; + + return 1 << (n + 6); +} + /* Latency function */ static inline void hdspm_compute_period_size(struct hdspm *hdspm) { - hdspm->period_bytes = 1 << ((hdspm_decode_latency(hdspm->control_register) + 8)); + hdspm->period_bytes = 4 * hdspm_get_latency(hdspm); } @@ -1303,12 +1323,27 @@ static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames) spin_lock_irq(&s->lock); - frames >>= 7; - n = 0; - while (frames) { - n++; - frames >>= 1; + if (32 == frames) { + /* Special case for new RME cards like RayDAT/AIO which + * support period sizes of 32 samples. Since latency is + * encoded in the three bits of HDSP_LatencyMask, we can only + * have values from 0 .. 7. While 0 still means 64 samples and + * 6 represents 4096 samples on all cards, 7 represents 8192 + * on older cards and 32 samples on new cards. + * + * In other words, period size in samples is calculated by + * 2^(n+6) with n ranging from 0 .. 7. + */ + n = 7; + } else { + frames >>= 7; + n = 0; + while (frames) { + n++; + frames >>= 1; + } } + s->control_register &= ~HDSPM_LatencyMask; s->control_register |= hdspm_encode_latency(n); @@ -1339,6 +1374,10 @@ static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period) break; case MADIface: freq_const = 131072000000000ULL; + break; + default: + snd_BUG(); + return 0; } return div_u64(freq_const, period); @@ -1356,16 +1395,19 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) switch (hdspm->io_type) { case MADIface: - n = 131072000000000ULL; /* 125 MHz */ - break; + n = 131072000000000ULL; /* 125 MHz */ + break; case MADI: case AES32: - n = 110069313433624ULL; /* 105 MHz */ - break; + n = 110069313433624ULL; /* 105 MHz */ + break; case RayDAT: case AIO: - n = 104857600000000ULL; /* 100 MHz */ - break; + n = 104857600000000ULL; /* 100 MHz */ + break; + default: + snd_BUG(); + return; } n = div_u64(n, rate); @@ -4794,8 +4836,7 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, snd_iprintf(buffer, "--- Settings ---\n"); - x = 1 << (6 + hdspm_decode_latency(hdspm->control_register & - HDSPM_LatencyMask)); + x = hdspm_get_latency(hdspm); snd_iprintf(buffer, "Size (Latency): %d samples (2 periods of %lu bytes)\n", @@ -4958,8 +4999,7 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, snd_iprintf(buffer, "--- Settings ---\n"); - x = 1 << (6 + hdspm_decode_latency(hdspm->control_register & - HDSPM_LatencyMask)); + x = hdspm_get_latency(hdspm); snd_iprintf(buffer, "Size (Latency): %d samples (2 periods of %lu bytes)\n", @@ -5665,19 +5705,6 @@ static int snd_hdspm_prepare(struct snd_pcm_substream *substream) return 0; } -static unsigned int period_sizes_old[] = { - 64, 128, 256, 512, 1024, 2048, 4096 -}; - -static unsigned int period_sizes_new[] = { - 32, 64, 128, 256, 512, 1024, 2048, 4096 -}; - -/* RayDAT and AIO always have a buffer of 16384 samples per channel */ -static unsigned int raydat_aio_buffer_sizes[] = { - 16384 -}; - static struct snd_pcm_hardware snd_hdspm_playback_subinfo = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | @@ -5696,8 +5723,8 @@ static struct snd_pcm_hardware snd_hdspm_playback_subinfo = { .channels_max = HDSPM_MAX_CHANNELS, .buffer_bytes_max = HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, - .period_bytes_min = (64 * 4), - .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS, + .period_bytes_min = (32 * 4), + .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS, .periods_min = 2, .periods_max = 512, .fifo_size = 0 @@ -5721,31 +5748,13 @@ static struct snd_pcm_hardware snd_hdspm_capture_subinfo = { .channels_max = HDSPM_MAX_CHANNELS, .buffer_bytes_max = HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, - .period_bytes_min = (64 * 4), - .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS, + .period_bytes_min = (32 * 4), + .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS, .periods_min = 2, .periods_max = 512, .fifo_size = 0 }; -static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_old = { - .count = ARRAY_SIZE(period_sizes_old), - .list = period_sizes_old, - .mask = 0 -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_new = { - .count = ARRAY_SIZE(period_sizes_new), - .list = period_sizes_new, - .mask = 0 -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_raydat_io_buffer = { - .count = ARRAY_SIZE(raydat_aio_buffer_sizes), - .list = raydat_aio_buffer_sizes, - .mask = 0 -}; - static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { @@ -5946,26 +5955,29 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream) spin_unlock_irq(&hdspm->lock); snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); + snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); switch (hdspm->io_type) { case AIO: case RayDAT: - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - &hw_constraints_period_sizes_new); - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - &hw_constraints_raydat_io_buffer); - + snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + 32, 4096); + /* RayDAT & AIO have a fixed buffer of 16384 samples per channel */ + snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + 16384, 16384); break; default: - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - &hw_constraints_period_sizes_old); + snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + 64, 8192); + break; } if (AES32 == hdspm->io_type) { + runtime->hw.rates |= SNDRV_PCM_RATE_KNOT; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdspm_hw_constraints_aes32_sample_rates); } else { @@ -6018,24 +6030,28 @@ static int snd_hdspm_capture_open(struct snd_pcm_substream *substream) spin_unlock_irq(&hdspm->lock); snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); + snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); + switch (hdspm->io_type) { case AIO: case RayDAT: - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - &hw_constraints_period_sizes_new); - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - &hw_constraints_raydat_io_buffer); - break; + snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + 32, 4096); + snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + 16384, 16384); + break; default: - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - &hw_constraints_period_sizes_old); + snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + 64, 8192); + break; } if (AES32 == hdspm->io_type) { + runtime->hw.rates |= SNDRV_PCM_RATE_KNOT; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdspm_hw_constraints_aes32_sample_rates); } else { diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 2571a67b389a..c5008166cf1f 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -1493,9 +1493,10 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci, return err; } if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES, - sonic->midi_port, MPU401_INFO_INTEGRATED, - sonic->irq, 0, - &midi_uart)) < 0) { + sonic->midi_port, + MPU401_INFO_INTEGRATED | + MPU401_INFO_IRQ_HOOK, + -1, &midi_uart)) < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index d8a128f6fc02..5e707effdc7c 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c @@ -148,8 +148,9 @@ static int __devinit snd_trident_probe(struct pci_dev *pci, if (trident->device != TRIDENT_DEVICE_ID_SI7018 && (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE, trident->midi_port, - MPU401_INFO_INTEGRATED, - trident->irq, 0, &trident->rmidi)) < 0) { + MPU401_INFO_INTEGRATED | + MPU401_INFO_IRQ_HOOK, + -1, &trident->rmidi)) < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index f03fd620a2a0..c3656fffdb50 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -1175,6 +1175,7 @@ static int snd_via82xx_pcm_open(struct via82xx *chip, struct viadev *viadev, struct snd_pcm_runtime *runtime = substream->runtime; int err; struct via_rate_lock *ratep; + bool use_src = false; runtime->hw = snd_via82xx_hw; @@ -1196,6 +1197,7 @@ static int snd_via82xx_pcm_open(struct via82xx *chip, struct viadev *viadev, SNDRV_PCM_RATE_8000_48000); runtime->hw.rate_min = 8000; runtime->hw.rate_max = 48000; + use_src = true; } else if (! ratep->rate) { int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC; runtime->hw.rates = chip->ac97->rates[idx]; @@ -1212,6 +1214,12 @@ static int snd_via82xx_pcm_open(struct via82xx *chip, struct viadev *viadev, if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) return err; + if (use_src) { + err = snd_pcm_hw_rule_noresample(runtime, 48000); + if (err < 0) + return err; + } + runtime->private_data = viadev; viadev->substream = substream; @@ -2068,8 +2076,9 @@ static int __devinit snd_via686_init_misc(struct via82xx *chip) pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg); if (chip->mpu_res) { if (snd_mpu401_uart_new(chip->card, 0, MPU401_HW_VIA686A, - mpu_port, MPU401_INFO_INTEGRATED, - chip->irq, 0, &chip->rmidi) < 0) { + mpu_port, MPU401_INFO_INTEGRATED | + MPU401_INFO_IRQ_HOOK, -1, + &chip->rmidi) < 0) { printk(KERN_WARNING "unable to initialize MPU-401" " at 0x%lx, skipping\n", mpu_port); legacy &= ~VIA_FUNC_ENABLE_MIDI; diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 511d57653124..3253b04da184 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -305,8 +305,9 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, if (chip->mpu_res) { if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI, mpu_port[dev], - MPU401_INFO_INTEGRATED, - pci->irq, 0, &chip->rawmidi)) < 0) { + MPU401_INFO_INTEGRATED | + MPU401_INFO_IRQ_HOOK, + -1, &chip->rawmidi)) < 0) { printk(KERN_WARNING "ymfpci: cannot initialize MPU401 at 0x%lx, skipping...\n", mpu_port[dev]); legacy_ctrl &= ~YMFPCI_LEGACY_MIEN; /* disable MPU401 irq */ pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl); diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index f3260e658b8a..66ea71b2a70d 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -897,6 +897,18 @@ static int snd_ymfpci_playback_open_1(struct snd_pcm_substream *substream) struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_ymfpci_pcm *ypcm; + int err; + + runtime->hw = snd_ymfpci_playback; + /* FIXME? True value is 256/48 = 5.33333 ms */ + err = snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_PERIOD_TIME, + 5334, UINT_MAX); + if (err < 0) + return err; + err = snd_pcm_hw_rule_noresample(runtime, 48000); + if (err < 0) + return err; ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL); if (ypcm == NULL) @@ -904,11 +916,8 @@ static int snd_ymfpci_playback_open_1(struct snd_pcm_substream *substream) ypcm->chip = chip; ypcm->type = PLAYBACK_VOICE; ypcm->substream = substream; - runtime->hw = snd_ymfpci_playback; runtime->private_data = ypcm; runtime->private_free = snd_ymfpci_pcm_free_substream; - /* FIXME? True value is 256/48 = 5.33333 ms */ - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 5333, UINT_MAX); return 0; } @@ -1013,6 +1022,18 @@ static int snd_ymfpci_capture_open(struct snd_pcm_substream *substream, struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_ymfpci_pcm *ypcm; + int err; + + runtime->hw = snd_ymfpci_capture; + /* FIXME? True value is 256/48 = 5.33333 ms */ + err = snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_PERIOD_TIME, + 5334, UINT_MAX); + if (err < 0) + return err; + err = snd_pcm_hw_rule_noresample(runtime, 48000); + if (err < 0) + return err; ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL); if (ypcm == NULL) @@ -1022,9 +1043,6 @@ static int snd_ymfpci_capture_open(struct snd_pcm_substream *substream, ypcm->substream = substream; ypcm->capture_bank_number = capture_bank_number; chip->capture_substream[capture_bank_number] = substream; - runtime->hw = snd_ymfpci_capture; - /* FIXME? True value is 256/48 = 5.33333 ms */ - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 5333, UINT_MAX); runtime->private_data = ypcm; runtime->private_free = snd_ymfpci_pcm_free_substream; snd_ymfpci_hw_start(chip); @@ -1615,7 +1633,7 @@ YMFPCI_DOUBLE("ADC Playback Volume", 0, YDSXGR_PRIADCOUTVOL), YMFPCI_DOUBLE("ADC Capture Volume", 0, YDSXGR_PRIADCLOOPVOL), YMFPCI_DOUBLE("ADC Playback Volume", 1, YDSXGR_SECADCOUTVOL), YMFPCI_DOUBLE("ADC Capture Volume", 1, YDSXGR_SECADCLOOPVOL), -YMFPCI_DOUBLE("FM Legacy Volume", 0, YDSXGR_LEGACYOUTVOL), +YMFPCI_DOUBLE("FM Legacy Playback Volume", 0, YDSXGR_LEGACYOUTVOL), YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ", PLAYBACK,VOLUME), 0, YDSXGR_ZVOUTVOL), YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("", CAPTURE,VOLUME), 0, YDSXGR_ZVLOOPVOL), YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ",PLAYBACK,VOLUME), 1, YDSXGR_SPDIFOUTVOL), diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index 8f064c7ce745..4080becf4cef 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c @@ -82,7 +82,6 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter) static int keywest_remove(struct i2c_client *client) { - i2c_set_clientdata(client, NULL); if (! keywest_ctx) return 0; if (client == keywest_ctx->client) diff --git a/sound/usb/Makefile b/sound/usb/Makefile index cf9ed66445fa..ac256dc4c6be 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile @@ -3,16 +3,16 @@ # snd-usb-audio-objs := card.o \ + clock.o \ + endpoint.o \ + format.o \ + helper.o \ mixer.o \ mixer_quirks.o \ + pcm.o \ proc.o \ quirks.o \ - format.o \ - endpoint.o \ - urb.o \ - pcm.o \ - helper.o \ - clock.o + stream.o snd-usbmidi-lib-objs := midi.o diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index d0d493ca28ae..2cf87f5afed4 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c @@ -139,8 +139,12 @@ static void stream_stop(struct snd_usb_caiaqdev *dev) for (i = 0; i < N_URBS; i++) { usb_kill_urb(dev->data_urbs_in[i]); - usb_kill_urb(dev->data_urbs_out[i]); + + if (test_bit(i, &dev->outurb_active_mask)) + usb_kill_urb(dev->data_urbs_out[i]); } + + dev->outurb_active_mask = 0; } static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream) @@ -612,8 +616,9 @@ static void read_completed(struct urb *urb) { struct snd_usb_caiaq_cb_info *info = urb->context; struct snd_usb_caiaqdev *dev; - struct urb *out; - int frame, len, send_it = 0, outframe = 0; + struct urb *out = NULL; + int i, frame, len, send_it = 0, outframe = 0; + size_t offset = 0; if (urb->status || !info) return; @@ -623,7 +628,17 @@ static void read_completed(struct urb *urb) if (!dev->streaming) return; - out = dev->data_urbs_out[info->index]; + /* find an unused output urb that is unused */ + for (i = 0; i < N_URBS; i++) + if (test_and_set_bit(i, &dev->outurb_active_mask) == 0) { + out = dev->data_urbs_out[i]; + break; + } + + if (!out) { + log("Unable to find an output urb to use\n"); + goto requeue; + } /* read the recently received packet and send back one which has * the same layout */ @@ -634,7 +649,8 @@ static void read_completed(struct urb *urb) len = urb->iso_frame_desc[outframe].actual_length; out->iso_frame_desc[outframe].length = len; out->iso_frame_desc[outframe].actual_length = 0; - out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame; + out->iso_frame_desc[outframe].offset = offset; + offset += len; if (len > 0) { spin_lock(&dev->spinlock); @@ -650,11 +666,15 @@ static void read_completed(struct urb *urb) } if (send_it) { - out->number_of_packets = FRAMES_PER_URB; + out->number_of_packets = outframe; out->transfer_flags = URB_ISO_ASAP; usb_submit_urb(out, GFP_ATOMIC); + } else { + struct snd_usb_caiaq_cb_info *oinfo = out->context; + clear_bit(oinfo->index, &dev->outurb_active_mask); } +requeue: /* re-submit inbound urb */ for (frame = 0; frame < FRAMES_PER_URB; frame++) { urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame; @@ -676,6 +696,8 @@ static void write_completed(struct urb *urb) dev->output_running = 1; wake_up(&dev->prepare_wait_queue); } + + clear_bit(info->index, &dev->outurb_active_mask); } static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret) @@ -827,6 +849,9 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev) if (!dev->data_cb_info) return -ENOMEM; + dev->outurb_active_mask = 0; + BUILD_BUG_ON(N_URBS > (sizeof(dev->outurb_active_mask) * 8)); + for (i = 0; i < N_URBS; i++) { dev->data_cb_info[i].dev = dev; dev->data_cb_info[i].index = i; diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h index b2b310194ffa..3f9c6339ae90 100644 --- a/sound/usb/caiaq/device.h +++ b/sound/usb/caiaq/device.h @@ -96,6 +96,7 @@ struct snd_usb_caiaqdev { int input_panic, output_panic, warned; char *audio_in_buf, *audio_out_buf; unsigned int samplerates, bpp; + unsigned long outurb_active_mask; struct snd_pcm_substream *sub_playback[MAX_STREAMS]; struct snd_pcm_substream *sub_capture[MAX_STREAMS]; diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c index 4432ef7a70a9..a213813487bd 100644 --- a/sound/usb/caiaq/input.c +++ b/sound/usb/caiaq/input.c @@ -30,7 +30,7 @@ static unsigned short keycode_ak1[] = { KEY_C, KEY_B, KEY_A }; static unsigned short keycode_rk2[] = { KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7 }; static unsigned short keycode_rk3[] = { KEY_1, KEY_2, KEY_3, KEY_4, - KEY_5, KEY_6, KEY_7, KEY_5, KEY_6 }; + KEY_5, KEY_6, KEY_7, KEY_8, KEY_9 }; static unsigned short keycode_kore[] = { KEY_FN_F1, /* "menu" */ diff --git a/sound/usb/card.c b/sound/usb/card.c index 781d9e61adfb..d2a79d166e04 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -65,9 +65,9 @@ #include "helper.h" #include "debug.h" #include "pcm.h" -#include "urb.h" #include "format.h" #include "power.h" +#include "stream.h" MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); MODULE_DESCRIPTION("USB Audio"); @@ -185,7 +185,7 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int return -EINVAL; } - if (! snd_usb_parse_audio_endpoints(chip, interface)) { + if (! snd_usb_parse_audio_interface(chip, interface)) { usb_set_interface(dev, interface, 0); /* reset the current interface */ usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L); return -EINVAL; diff --git a/sound/usb/card.h b/sound/usb/card.h index ae4251d5abf7..a39edcc32a93 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -94,6 +94,8 @@ struct snd_usb_substream { spinlock_t lock; struct snd_urb_ops ops; /* callbacks (must be filled at init) */ + int last_frame_number; /* stored frame number */ + int last_delay; /* stored delay */ }; struct snd_usb_stream { diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 7c0d21ecd821..81c6edecd862 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -15,436 +15,951 @@ * */ +#include <linux/gfp.h> #include <linux/init.h> -#include <linux/slab.h> #include <linux/usb.h> #include <linux/usb/audio.h> -#include <linux/usb/audio-v2.h> #include <sound/core.h> #include <sound/pcm.h> #include "usbaudio.h" +#include "helper.h" #include "card.h" -#include "proc.h" -#include "quirks.h" #include "endpoint.h" -#include "urb.h" #include "pcm.h" -#include "helper.h" -#include "format.h" -#include "clock.h" /* - * free a substream + * convert a sampling rate into our full speed format (fs/1000 in Q16.16) + * this will overflow at approx 524 kHz */ -static void free_substream(struct snd_usb_substream *subs) +static inline unsigned get_usb_full_speed_rate(unsigned int rate) { - struct list_head *p, *n; - - if (!subs->num_formats) - return; /* not initialized */ - list_for_each_safe(p, n, &subs->fmt_list) { - struct audioformat *fp = list_entry(p, struct audioformat, list); - kfree(fp->rate_table); - kfree(fp); - } - kfree(subs->rate_list.list); + return ((rate << 13) + 62) / 125; } +/* + * convert a sampling rate into USB high speed format (fs/8000 in Q16.16) + * this will overflow at approx 4 MHz + */ +static inline unsigned get_usb_high_speed_rate(unsigned int rate) +{ + return ((rate << 10) + 62) / 125; +} /* - * free a usb stream instance + * unlink active urbs. */ -static void snd_usb_audio_stream_free(struct snd_usb_stream *stream) +static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sleep) { - free_substream(&stream->substream[0]); - free_substream(&stream->substream[1]); - list_del(&stream->list); - kfree(stream); + struct snd_usb_audio *chip = subs->stream->chip; + unsigned int i; + int async; + + subs->running = 0; + + if (!force && subs->stream->chip->shutdown) /* to be sure... */ + return -EBADFD; + + async = !can_sleep && chip->async_unlink; + + if (!async && in_interrupt()) + return 0; + + for (i = 0; i < subs->nurbs; i++) { + if (test_bit(i, &subs->active_mask)) { + if (!test_and_set_bit(i, &subs->unlink_mask)) { + struct urb *u = subs->dataurb[i].urb; + if (async) + usb_unlink_urb(u); + else + usb_kill_urb(u); + } + } + } + if (subs->syncpipe) { + for (i = 0; i < SYNC_URBS; i++) { + if (test_bit(i+16, &subs->active_mask)) { + if (!test_and_set_bit(i+16, &subs->unlink_mask)) { + struct urb *u = subs->syncurb[i].urb; + if (async) + usb_unlink_urb(u); + else + usb_kill_urb(u); + } + } + } + } + return 0; } -static void snd_usb_audio_pcm_free(struct snd_pcm *pcm) + +/* + * release a urb data + */ +static void release_urb_ctx(struct snd_urb_ctx *u) { - struct snd_usb_stream *stream = pcm->private_data; - if (stream) { - stream->pcm = NULL; - snd_usb_audio_stream_free(stream); + if (u->urb) { + if (u->buffer_size) + usb_free_coherent(u->subs->dev, u->buffer_size, + u->urb->transfer_buffer, + u->urb->transfer_dma); + usb_free_urb(u->urb); + u->urb = NULL; } } +/* + * wait until all urbs are processed. + */ +static int wait_clear_urbs(struct snd_usb_substream *subs) +{ + unsigned long end_time = jiffies + msecs_to_jiffies(1000); + unsigned int i; + int alive; + + do { + alive = 0; + for (i = 0; i < subs->nurbs; i++) { + if (test_bit(i, &subs->active_mask)) + alive++; + } + if (subs->syncpipe) { + for (i = 0; i < SYNC_URBS; i++) { + if (test_bit(i + 16, &subs->active_mask)) + alive++; + } + } + if (! alive) + break; + schedule_timeout_uninterruptible(1); + } while (time_before(jiffies, end_time)); + if (alive) + snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive); + return 0; +} /* - * add this endpoint to the chip instance. - * if a stream with the same endpoint already exists, append to it. - * if not, create a new pcm stream. + * release a substream */ -int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct audioformat *fp) +void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force) { - struct list_head *p; - struct snd_usb_stream *as; - struct snd_usb_substream *subs; - struct snd_pcm *pcm; - int err; + int i; + + /* stop urbs (to be sure) */ + deactivate_urbs(subs, force, 1); + wait_clear_urbs(subs); + + for (i = 0; i < MAX_URBS; i++) + release_urb_ctx(&subs->dataurb[i]); + for (i = 0; i < SYNC_URBS; i++) + release_urb_ctx(&subs->syncurb[i]); + usb_free_coherent(subs->dev, SYNC_URBS * 4, + subs->syncbuf, subs->sync_dma); + subs->syncbuf = NULL; + subs->nurbs = 0; +} - list_for_each(p, &chip->pcm_list) { - as = list_entry(p, struct snd_usb_stream, list); - if (as->fmt_type != fp->fmt_type) - continue; - subs = &as->substream[stream]; - if (!subs->endpoint) - continue; - if (subs->endpoint == fp->endpoint) { - list_add_tail(&fp->list, &subs->fmt_list); - subs->num_formats++; - subs->formats |= fp->formats; - return 0; +/* + * complete callback from data urb + */ +static void snd_complete_urb(struct urb *urb) +{ + struct snd_urb_ctx *ctx = urb->context; + struct snd_usb_substream *subs = ctx->subs; + struct snd_pcm_substream *substream = ctx->subs->pcm_substream; + int err = 0; + + if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) || + !subs->running || /* can be stopped during retire callback */ + (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 || + (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { + clear_bit(ctx->index, &subs->active_mask); + if (err < 0) { + snd_printd(KERN_ERR "cannot submit urb (err = %d)\n", err); + snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); } } - /* look for an empty stream */ - list_for_each(p, &chip->pcm_list) { - as = list_entry(p, struct snd_usb_stream, list); - if (as->fmt_type != fp->fmt_type) - continue; - subs = &as->substream[stream]; - if (subs->endpoint) - continue; - err = snd_pcm_new_stream(as->pcm, stream, 1); - if (err < 0) - return err; - snd_usb_init_substream(as, stream, fp); - return 0; +} + + +/* + * complete callback from sync urb + */ +static void snd_complete_sync_urb(struct urb *urb) +{ + struct snd_urb_ctx *ctx = urb->context; + struct snd_usb_substream *subs = ctx->subs; + struct snd_pcm_substream *substream = ctx->subs->pcm_substream; + int err = 0; + + if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) || + !subs->running || /* can be stopped during retire callback */ + (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 || + (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { + clear_bit(ctx->index + 16, &subs->active_mask); + if (err < 0) { + snd_printd(KERN_ERR "cannot submit sync urb (err = %d)\n", err); + snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + } } +} + - /* create a new pcm */ - as = kzalloc(sizeof(*as), GFP_KERNEL); - if (!as) - return -ENOMEM; - as->pcm_index = chip->pcm_devs; - as->chip = chip; - as->fmt_type = fp->fmt_type; - err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs, - stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0, - stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1, - &pcm); - if (err < 0) { - kfree(as); - return err; +/* + * initialize a substream for plaback/capture + */ +int snd_usb_init_substream_urbs(struct snd_usb_substream *subs, + unsigned int period_bytes, + unsigned int rate, + unsigned int frame_bits) +{ + unsigned int maxsize, i; + int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; + unsigned int urb_packs, total_packs, packs_per_ms; + struct snd_usb_audio *chip = subs->stream->chip; + + /* calculate the frequency in 16.16 format */ + if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) + subs->freqn = get_usb_full_speed_rate(rate); + else + subs->freqn = get_usb_high_speed_rate(rate); + subs->freqm = subs->freqn; + subs->freqshift = INT_MIN; + /* calculate max. frequency */ + if (subs->maxpacksize) { + /* whatever fits into a max. size packet */ + maxsize = subs->maxpacksize; + subs->freqmax = (maxsize / (frame_bits >> 3)) + << (16 - subs->datainterval); + } else { + /* no max. packet size: just take 25% higher than nominal */ + subs->freqmax = subs->freqn + (subs->freqn >> 2); + maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3)) + >> (16 - subs->datainterval); } - as->pcm = pcm; - pcm->private_data = as; - pcm->private_free = snd_usb_audio_pcm_free; - pcm->info_flags = 0; - if (chip->pcm_devs > 0) - sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs); + subs->phase = 0; + + if (subs->fill_max) + subs->curpacksize = subs->maxpacksize; else - strcpy(pcm->name, "USB Audio"); + subs->curpacksize = maxsize; - snd_usb_init_substream(as, stream, fp); + if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) + packs_per_ms = 8 >> subs->datainterval; + else + packs_per_ms = 1; + + if (is_playback) { + urb_packs = max(chip->nrpacks, 1); + urb_packs = min(urb_packs, (unsigned int)MAX_PACKS); + } else + urb_packs = 1; + urb_packs *= packs_per_ms; + if (subs->syncpipe) + urb_packs = min(urb_packs, 1U << subs->syncinterval); + + /* decide how many packets to be used */ + if (is_playback) { + unsigned int minsize, maxpacks; + /* determine how small a packet can be */ + minsize = (subs->freqn >> (16 - subs->datainterval)) + * (frame_bits >> 3); + /* with sync from device, assume it can be 12% lower */ + if (subs->syncpipe) + minsize -= minsize >> 3; + minsize = max(minsize, 1u); + total_packs = (period_bytes + minsize - 1) / minsize; + /* we need at least two URBs for queueing */ + if (total_packs < 2) { + total_packs = 2; + } else { + /* and we don't want too long a queue either */ + maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2); + total_packs = min(total_packs, maxpacks); + } + } else { + while (urb_packs > 1 && urb_packs * maxsize >= period_bytes) + urb_packs >>= 1; + total_packs = MAX_URBS * urb_packs; + } + subs->nurbs = (total_packs + urb_packs - 1) / urb_packs; + if (subs->nurbs > MAX_URBS) { + /* too much... */ + subs->nurbs = MAX_URBS; + total_packs = MAX_URBS * urb_packs; + } else if (subs->nurbs < 2) { + /* too little - we need at least two packets + * to ensure contiguous playback/capture + */ + subs->nurbs = 2; + } - list_add(&as->list, &chip->pcm_list); - chip->pcm_devs++; + /* allocate and initialize data urbs */ + for (i = 0; i < subs->nurbs; i++) { + struct snd_urb_ctx *u = &subs->dataurb[i]; + u->index = i; + u->subs = subs; + u->packets = (i + 1) * total_packs / subs->nurbs + - i * total_packs / subs->nurbs; + u->buffer_size = maxsize * u->packets; + if (subs->fmt_type == UAC_FORMAT_TYPE_II) + u->packets++; /* for transfer delimiter */ + u->urb = usb_alloc_urb(u->packets, GFP_KERNEL); + if (!u->urb) + goto out_of_memory; + u->urb->transfer_buffer = + usb_alloc_coherent(subs->dev, u->buffer_size, + GFP_KERNEL, &u->urb->transfer_dma); + if (!u->urb->transfer_buffer) + goto out_of_memory; + u->urb->pipe = subs->datapipe; + u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; + u->urb->interval = 1 << subs->datainterval; + u->urb->context = u; + u->urb->complete = snd_complete_urb; + } + + if (subs->syncpipe) { + /* allocate and initialize sync urbs */ + subs->syncbuf = usb_alloc_coherent(subs->dev, SYNC_URBS * 4, + GFP_KERNEL, &subs->sync_dma); + if (!subs->syncbuf) + goto out_of_memory; + for (i = 0; i < SYNC_URBS; i++) { + struct snd_urb_ctx *u = &subs->syncurb[i]; + u->index = i; + u->subs = subs; + u->packets = 1; + u->urb = usb_alloc_urb(1, GFP_KERNEL); + if (!u->urb) + goto out_of_memory; + u->urb->transfer_buffer = subs->syncbuf + i * 4; + u->urb->transfer_dma = subs->sync_dma + i * 4; + u->urb->transfer_buffer_length = 4; + u->urb->pipe = subs->syncpipe; + u->urb->transfer_flags = URB_ISO_ASAP | + URB_NO_TRANSFER_DMA_MAP; + u->urb->number_of_packets = 1; + u->urb->interval = 1 << subs->syncinterval; + u->urb->context = u; + u->urb->complete = snd_complete_sync_urb; + } + } + return 0; - snd_usb_proc_pcm_format_add(as); +out_of_memory: + snd_usb_release_substream_urbs(subs, 0); + return -ENOMEM; +} +/* + * prepare urb for full speed capture sync pipe + * + * fill the length and offset of each urb descriptor. + * the fixed 10.14 frequency is passed through the pipe. + */ +static int prepare_capture_sync_urb(struct snd_usb_substream *subs, + struct snd_pcm_runtime *runtime, + struct urb *urb) +{ + unsigned char *cp = urb->transfer_buffer; + struct snd_urb_ctx *ctx = urb->context; + + urb->dev = ctx->subs->dev; /* we need to set this at each time */ + urb->iso_frame_desc[0].length = 3; + urb->iso_frame_desc[0].offset = 0; + cp[0] = subs->freqn >> 2; + cp[1] = subs->freqn >> 10; + cp[2] = subs->freqn >> 18; return 0; } -static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, - struct usb_host_interface *alts, - int protocol, int iface_no) +/* + * prepare urb for high speed capture sync pipe + * + * fill the length and offset of each urb descriptor. + * the fixed 12.13 frequency is passed as 16.16 through the pipe. + */ +static int prepare_capture_sync_urb_hs(struct snd_usb_substream *subs, + struct snd_pcm_runtime *runtime, + struct urb *urb) { - /* parsed with a v1 header here. that's ok as we only look at the - * header first which is the same for both versions */ - struct uac_iso_endpoint_descriptor *csep; - struct usb_interface_descriptor *altsd = get_iface_desc(alts); - int attributes = 0; - - csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT); - - /* Creamware Noah has this descriptor after the 2nd endpoint */ - if (!csep && altsd->bNumEndpoints >= 2) - csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT); - - if (!csep || csep->bLength < 7 || - csep->bDescriptorSubtype != UAC_EP_GENERAL) { - snd_printk(KERN_WARNING "%d:%u:%d : no or invalid" - " class specific endpoint descriptor\n", - chip->dev->devnum, iface_no, - altsd->bAlternateSetting); - return 0; - } + unsigned char *cp = urb->transfer_buffer; + struct snd_urb_ctx *ctx = urb->context; + + urb->dev = ctx->subs->dev; /* we need to set this at each time */ + urb->iso_frame_desc[0].length = 4; + urb->iso_frame_desc[0].offset = 0; + cp[0] = subs->freqn; + cp[1] = subs->freqn >> 8; + cp[2] = subs->freqn >> 16; + cp[3] = subs->freqn >> 24; + return 0; +} - if (protocol == UAC_VERSION_1) { - attributes = csep->bmAttributes; - } else { - struct uac2_iso_endpoint_descriptor *csep2 = - (struct uac2_iso_endpoint_descriptor *) csep; +/* + * process after capture sync complete + * - nothing to do + */ +static int retire_capture_sync_urb(struct snd_usb_substream *subs, + struct snd_pcm_runtime *runtime, + struct urb *urb) +{ + return 0; +} - attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX; +/* + * prepare urb for capture data pipe + * + * fill the offset and length of each descriptor. + * + * we use a temporary buffer to write the captured data. + * since the length of written data is determined by host, we cannot + * write onto the pcm buffer directly... the data is thus copied + * later at complete callback to the global buffer. + */ +static int prepare_capture_urb(struct snd_usb_substream *subs, + struct snd_pcm_runtime *runtime, + struct urb *urb) +{ + int i, offs; + struct snd_urb_ctx *ctx = urb->context; + + offs = 0; + urb->dev = ctx->subs->dev; /* we need to set this at each time */ + for (i = 0; i < ctx->packets; i++) { + urb->iso_frame_desc[i].offset = offs; + urb->iso_frame_desc[i].length = subs->curpacksize; + offs += subs->curpacksize; + } + urb->transfer_buffer_length = offs; + urb->number_of_packets = ctx->packets; + return 0; +} - /* emulate the endpoint attributes of a v1 device */ - if (csep2->bmControls & UAC2_CONTROL_PITCH) - attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL; +/* + * process after capture complete + * + * copy the data from each desctiptor to the pcm buffer, and + * update the current position. + */ +static int retire_capture_urb(struct snd_usb_substream *subs, + struct snd_pcm_runtime *runtime, + struct urb *urb) +{ + unsigned long flags; + unsigned char *cp; + int i; + unsigned int stride, frames, bytes, oldptr; + int period_elapsed = 0; + + stride = runtime->frame_bits >> 3; + + for (i = 0; i < urb->number_of_packets; i++) { + cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset; + if (urb->iso_frame_desc[i].status) { + snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status); + // continue; + } + bytes = urb->iso_frame_desc[i].actual_length; + frames = bytes / stride; + if (!subs->txfr_quirk) + bytes = frames * stride; + if (bytes % (runtime->sample_bits >> 3) != 0) { +#ifdef CONFIG_SND_DEBUG_VERBOSE + int oldbytes = bytes; +#endif + bytes = frames * stride; + snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n", + oldbytes, bytes); + } + /* update the current pointer */ + spin_lock_irqsave(&subs->lock, flags); + oldptr = subs->hwptr_done; + subs->hwptr_done += bytes; + if (subs->hwptr_done >= runtime->buffer_size * stride) + subs->hwptr_done -= runtime->buffer_size * stride; + frames = (bytes + (oldptr % stride)) / stride; + subs->transfer_done += frames; + if (subs->transfer_done >= runtime->period_size) { + subs->transfer_done -= runtime->period_size; + period_elapsed = 1; + } + spin_unlock_irqrestore(&subs->lock, flags); + /* copy a data chunk */ + if (oldptr + bytes > runtime->buffer_size * stride) { + unsigned int bytes1 = + runtime->buffer_size * stride - oldptr; + memcpy(runtime->dma_area + oldptr, cp, bytes1); + memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1); + } else { + memcpy(runtime->dma_area + oldptr, cp, bytes); + } } + if (period_elapsed) + snd_pcm_period_elapsed(subs->pcm_substream); + return 0; +} - return attributes; +/* + * Process after capture complete when paused. Nothing to do. + */ +static int retire_paused_capture_urb(struct snd_usb_substream *subs, + struct snd_pcm_runtime *runtime, + struct urb *urb) +{ + return 0; } -static struct uac2_input_terminal_descriptor * - snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, - int terminal_id) + +/* + * prepare urb for playback sync pipe + * + * set up the offset and length to receive the current frequency. + */ +static int prepare_playback_sync_urb(struct snd_usb_substream *subs, + struct snd_pcm_runtime *runtime, + struct urb *urb) { - struct uac2_input_terminal_descriptor *term = NULL; + struct snd_urb_ctx *ctx = urb->context; + + urb->dev = ctx->subs->dev; /* we need to set this at each time */ + urb->iso_frame_desc[0].length = min(4u, ctx->subs->syncmaxsize); + urb->iso_frame_desc[0].offset = 0; + return 0; +} - while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, - ctrl_iface->extralen, - term, UAC_INPUT_TERMINAL))) { - if (term->bTerminalID == terminal_id) - return term; +/* + * process after playback sync complete + * + * Full speed devices report feedback values in 10.14 format as samples per + * frame, high speed devices in 16.16 format as samples per microframe. + * Because the Audio Class 1 spec was written before USB 2.0, many high speed + * devices use a wrong interpretation, some others use an entirely different + * format. Therefore, we cannot predict what format any particular device uses + * and must detect it automatically. + */ +static int retire_playback_sync_urb(struct snd_usb_substream *subs, + struct snd_pcm_runtime *runtime, + struct urb *urb) +{ + unsigned int f; + int shift; + unsigned long flags; + + if (urb->iso_frame_desc[0].status != 0 || + urb->iso_frame_desc[0].actual_length < 3) + return 0; + + f = le32_to_cpup(urb->transfer_buffer); + if (urb->iso_frame_desc[0].actual_length == 3) + f &= 0x00ffffff; + else + f &= 0x0fffffff; + if (f == 0) + return 0; + + if (unlikely(subs->freqshift == INT_MIN)) { + /* + * The first time we see a feedback value, determine its format + * by shifting it left or right until it matches the nominal + * frequency value. This assumes that the feedback does not + * differ from the nominal value more than +50% or -25%. + */ + shift = 0; + while (f < subs->freqn - subs->freqn / 4) { + f <<= 1; + shift++; + } + while (f > subs->freqn + subs->freqn / 2) { + f >>= 1; + shift--; + } + subs->freqshift = shift; + } + else if (subs->freqshift >= 0) + f <<= subs->freqshift; + else + f >>= -subs->freqshift; + + if (likely(f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax)) { + /* + * If the frequency looks valid, set it. + * This value is referred to in prepare_playback_urb(). + */ + spin_lock_irqsave(&subs->lock, flags); + subs->freqm = f; + spin_unlock_irqrestore(&subs->lock, flags); + } else { + /* + * Out of range; maybe the shift value is wrong. + * Reset it so that we autodetect again the next time. + */ + subs->freqshift = INT_MIN; } - return NULL; + return 0; } -static struct uac2_output_terminal_descriptor * - snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface, - int terminal_id) +/* determine the number of frames in the next packet */ +static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs) { - struct uac2_output_terminal_descriptor *term = NULL; - - while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, - ctrl_iface->extralen, - term, UAC_OUTPUT_TERMINAL))) { - if (term->bTerminalID == terminal_id) - return term; + if (subs->fill_max) + return subs->maxframesize; + else { + subs->phase = (subs->phase & 0xffff) + + (subs->freqm << subs->datainterval); + return min(subs->phase >> 16, subs->maxframesize); } +} - return NULL; +/* + * Prepare urb for streaming before playback starts or when paused. + * + * We don't have any data, so we send silence. + */ +static int prepare_nodata_playback_urb(struct snd_usb_substream *subs, + struct snd_pcm_runtime *runtime, + struct urb *urb) +{ + unsigned int i, offs, counts; + struct snd_urb_ctx *ctx = urb->context; + int stride = runtime->frame_bits >> 3; + + offs = 0; + urb->dev = ctx->subs->dev; + for (i = 0; i < ctx->packets; ++i) { + counts = snd_usb_audio_next_packet_size(subs); + urb->iso_frame_desc[i].offset = offs * stride; + urb->iso_frame_desc[i].length = counts * stride; + offs += counts; + } + urb->number_of_packets = ctx->packets; + urb->transfer_buffer_length = offs * stride; + memset(urb->transfer_buffer, + runtime->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0, + offs * stride); + return 0; } -int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) +/* + * prepare urb for playback data pipe + * + * Since a URB can handle only a single linear buffer, we must use double + * buffering when the data to be transferred overflows the buffer boundary. + * To avoid inconsistencies when updating hwptr_done, we use double buffering + * for all URBs. + */ +static int prepare_playback_urb(struct snd_usb_substream *subs, + struct snd_pcm_runtime *runtime, + struct urb *urb) { - struct usb_device *dev; - struct usb_interface *iface; - struct usb_host_interface *alts; - struct usb_interface_descriptor *altsd; - int i, altno, err, stream; - int format = 0, num_channels = 0; - struct audioformat *fp = NULL; - int num, protocol, clock = 0; - struct uac_format_type_i_continuous_descriptor *fmt; + int i, stride; + unsigned int counts, frames, bytes; + unsigned long flags; + int period_elapsed = 0; + struct snd_urb_ctx *ctx = urb->context; + + stride = runtime->frame_bits >> 3; + + frames = 0; + urb->dev = ctx->subs->dev; /* we need to set this at each time */ + urb->number_of_packets = 0; + spin_lock_irqsave(&subs->lock, flags); + for (i = 0; i < ctx->packets; i++) { + counts = snd_usb_audio_next_packet_size(subs); + /* set up descriptor */ + urb->iso_frame_desc[i].offset = frames * stride; + urb->iso_frame_desc[i].length = counts * stride; + frames += counts; + urb->number_of_packets++; + subs->transfer_done += counts; + if (subs->transfer_done >= runtime->period_size) { + subs->transfer_done -= runtime->period_size; + period_elapsed = 1; + if (subs->fmt_type == UAC_FORMAT_TYPE_II) { + if (subs->transfer_done > 0) { + /* FIXME: fill-max mode is not + * supported yet */ + frames -= subs->transfer_done; + counts -= subs->transfer_done; + urb->iso_frame_desc[i].length = + counts * stride; + subs->transfer_done = 0; + } + i++; + if (i < ctx->packets) { + /* add a transfer delimiter */ + urb->iso_frame_desc[i].offset = + frames * stride; + urb->iso_frame_desc[i].length = 0; + urb->number_of_packets++; + } + break; + } + } + if (period_elapsed) /* finish at the period boundary */ + break; + } + bytes = frames * stride; + if (subs->hwptr_done + bytes > runtime->buffer_size * stride) { + /* err, the transferred area goes over buffer boundary. */ + unsigned int bytes1 = + runtime->buffer_size * stride - subs->hwptr_done; + memcpy(urb->transfer_buffer, + runtime->dma_area + subs->hwptr_done, bytes1); + memcpy(urb->transfer_buffer + bytes1, + runtime->dma_area, bytes - bytes1); + } else { + memcpy(urb->transfer_buffer, + runtime->dma_area + subs->hwptr_done, bytes); + } + subs->hwptr_done += bytes; + if (subs->hwptr_done >= runtime->buffer_size * stride) + subs->hwptr_done -= runtime->buffer_size * stride; + + /* update delay with exact number of samples queued */ + runtime->delay = subs->last_delay; + runtime->delay += frames; + subs->last_delay = runtime->delay; + + /* realign last_frame_number */ + subs->last_frame_number = usb_get_current_frame_number(subs->dev); + subs->last_frame_number &= 0xFF; /* keep 8 LSBs */ + + spin_unlock_irqrestore(&subs->lock, flags); + urb->transfer_buffer_length = bytes; + if (period_elapsed) + snd_pcm_period_elapsed(subs->pcm_substream); + return 0; +} - dev = chip->dev; +/* + * process after playback data complete + * - decrease the delay count again + */ +static int retire_playback_urb(struct snd_usb_substream *subs, + struct snd_pcm_runtime *runtime, + struct urb *urb) +{ + unsigned long flags; + int stride = runtime->frame_bits >> 3; + int processed = urb->transfer_buffer_length / stride; + int est_delay; - /* parse the interface's altsettings */ - iface = usb_ifnum_to_if(dev, iface_no); + spin_lock_irqsave(&subs->lock, flags); - num = iface->num_altsetting; + est_delay = snd_usb_pcm_delay(subs, runtime->rate); + /* update delay with exact number of samples played */ + if (processed > subs->last_delay) + subs->last_delay = 0; + else + subs->last_delay -= processed; + runtime->delay = subs->last_delay; /* - * Dallas DS4201 workaround: It presents 5 altsettings, but the last - * one misses syncpipe, and does not produce any sound. + * Report when delay estimate is off by more than 2ms. + * The error should be lower than 2ms since the estimate relies + * on two reads of a counter updated every ms. */ - if (chip->usb_id == USB_ID(0x04fa, 0x4201)) - num = 4; - - for (i = 0; i < num; i++) { - alts = &iface->altsetting[i]; - altsd = get_iface_desc(alts); - protocol = altsd->bInterfaceProtocol; - /* skip invalid one */ - if ((altsd->bInterfaceClass != USB_CLASS_AUDIO && - altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || - (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING && - altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) || - altsd->bNumEndpoints < 1 || - le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0) - continue; - /* must be isochronous */ - if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != - USB_ENDPOINT_XFER_ISOC) - continue; - /* check direction */ - stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ? - SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; - altno = altsd->bAlternateSetting; - - if (snd_usb_apply_interface_quirk(chip, iface_no, altno)) - continue; - - /* get audio formats */ - switch (protocol) { - default: - snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n", - dev->devnum, iface_no, altno, protocol); - protocol = UAC_VERSION_1; - /* fall through */ - - case UAC_VERSION_1: { - struct uac1_as_header_descriptor *as = - snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); - - if (!as) { - snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n", - dev->devnum, iface_no, altno); - continue; - } + if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2) + snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n", + est_delay, subs->last_delay); - if (as->bLength < sizeof(*as)) { - snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n", - dev->devnum, iface_no, altno); - continue; - } + spin_unlock_irqrestore(&subs->lock, flags); + return 0; +} - format = le16_to_cpu(as->wFormatTag); /* remember the format value */ - break; - } +static const char *usb_error_string(int err) +{ + switch (err) { + case -ENODEV: + return "no device"; + case -ENOENT: + return "endpoint not enabled"; + case -EPIPE: + return "endpoint stalled"; + case -ENOSPC: + return "not enough bandwidth"; + case -ESHUTDOWN: + return "device disabled"; + case -EHOSTUNREACH: + return "device suspended"; + case -EINVAL: + case -EAGAIN: + case -EFBIG: + case -EMSGSIZE: + return "internal error"; + default: + return "unknown error"; + } +} - case UAC_VERSION_2: { - struct uac2_input_terminal_descriptor *input_term; - struct uac2_output_terminal_descriptor *output_term; - struct uac2_as_header_descriptor *as = - snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); +/* + * set up and start data/sync urbs + */ +static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime) +{ + unsigned int i; + int err; - if (!as) { - snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n", - dev->devnum, iface_no, altno); - continue; + if (subs->stream->chip->shutdown) + return -EBADFD; + + for (i = 0; i < subs->nurbs; i++) { + if (snd_BUG_ON(!subs->dataurb[i].urb)) + return -EINVAL; + if (subs->ops.prepare(subs, runtime, subs->dataurb[i].urb) < 0) { + snd_printk(KERN_ERR "cannot prepare datapipe for urb %d\n", i); + goto __error; + } + } + if (subs->syncpipe) { + for (i = 0; i < SYNC_URBS; i++) { + if (snd_BUG_ON(!subs->syncurb[i].urb)) + return -EINVAL; + if (subs->ops.prepare_sync(subs, runtime, subs->syncurb[i].urb) < 0) { + snd_printk(KERN_ERR "cannot prepare syncpipe for urb %d\n", i); + goto __error; } + } + } - if (as->bLength < sizeof(*as)) { - snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n", - dev->devnum, iface_no, altno); - continue; + subs->active_mask = 0; + subs->unlink_mask = 0; + subs->running = 1; + for (i = 0; i < subs->nurbs; i++) { + err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC); + if (err < 0) { + snd_printk(KERN_ERR "cannot submit datapipe " + "for urb %d, error %d: %s\n", + i, err, usb_error_string(err)); + goto __error; + } + set_bit(i, &subs->active_mask); + } + if (subs->syncpipe) { + for (i = 0; i < SYNC_URBS; i++) { + err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC); + if (err < 0) { + snd_printk(KERN_ERR "cannot submit syncpipe " + "for urb %d, error %d: %s\n", + i, err, usb_error_string(err)); + goto __error; } + set_bit(i + 16, &subs->active_mask); + } + } + return 0; - num_channels = as->bNrChannels; - format = le32_to_cpu(as->bmFormats); + __error: + // snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN); + deactivate_urbs(subs, 0, 0); + return -EPIPE; +} - /* lookup the terminal associated to this interface - * to extract the clock */ - input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, - as->bTerminalLink); - if (input_term) { - clock = input_term->bCSourceID; - break; - } - output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf, - as->bTerminalLink); - if (output_term) { - clock = output_term->bCSourceID; - break; - } +/* + */ +static struct snd_urb_ops audio_urb_ops[2] = { + { + .prepare = prepare_nodata_playback_urb, + .retire = retire_playback_urb, + .prepare_sync = prepare_playback_sync_urb, + .retire_sync = retire_playback_sync_urb, + }, + { + .prepare = prepare_capture_urb, + .retire = retire_capture_urb, + .prepare_sync = prepare_capture_sync_urb, + .retire_sync = retire_capture_sync_urb, + }, +}; - snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n", - dev->devnum, iface_no, altno, as->bTerminalLink); - continue; - } - } +/* + * initialize the substream instance. + */ - /* get format type */ - fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE); - if (!fmt) { - snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n", - dev->devnum, iface_no, altno); - continue; - } - if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) || - ((protocol == UAC_VERSION_2) && (fmt->bLength != 6))) { - snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n", - dev->devnum, iface_no, altno); - continue; - } +void snd_usb_init_substream(struct snd_usb_stream *as, + int stream, struct audioformat *fp) +{ + struct snd_usb_substream *subs = &as->substream[stream]; + + INIT_LIST_HEAD(&subs->fmt_list); + spin_lock_init(&subs->lock); + + subs->stream = as; + subs->direction = stream; + subs->dev = as->chip->dev; + subs->txfr_quirk = as->chip->txfr_quirk; + subs->ops = audio_urb_ops[stream]; + if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH) + subs->ops.prepare_sync = prepare_capture_sync_urb_hs; + + snd_usb_set_pcm_ops(as->pcm, stream); + + list_add_tail(&fp->list, &subs->fmt_list); + subs->formats |= fp->formats; + subs->endpoint = fp->endpoint; + subs->num_formats++; + subs->fmt_type = fp->fmt_type; +} - /* - * Blue Microphones workaround: The last altsetting is identical - * with the previous one, except for a larger packet size, but - * is actually a mislabeled two-channel setting; ignore it. - */ - if (fmt->bNrChannels == 1 && - fmt->bSubframeSize == 2 && - altno == 2 && num == 3 && - fp && fp->altsetting == 1 && fp->channels == 1 && - fp->formats == SNDRV_PCM_FMTBIT_S16_LE && - protocol == UAC_VERSION_1 && - le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == - fp->maxpacksize * 2) - continue; - - fp = kzalloc(sizeof(*fp), GFP_KERNEL); - if (! fp) { - snd_printk(KERN_ERR "cannot malloc\n"); - return -ENOMEM; - } +int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_usb_substream *subs = substream->runtime->private_data; - fp->iface = iface_no; - fp->altsetting = altno; - fp->altset_idx = i; - fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; - fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; - fp->datainterval = snd_usb_parse_datainterval(chip, alts); - fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); - /* num_channels is only set for v2 interfaces */ - fp->channels = num_channels; - if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) - fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) - * (fp->maxpacksize & 0x7ff); - fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no); - fp->clock = clock; - - /* some quirks for attributes here */ - - switch (chip->usb_id) { - case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */ - /* Optoplay sets the sample rate attribute although - * it seems not supporting it in fact. - */ - fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE; - break; - case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */ - case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ - /* doesn't set the sample rate attribute, but supports it */ - fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE; - break; - case USB_ID(0x0763, 0x2001): /* M-Audio Quattro USB */ - case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */ - case USB_ID(0x047f, 0x0ca1): /* plantronics headset */ - case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is - an older model 77d:223) */ - /* - * plantronics headset and Griffin iMic have set adaptive-in - * although it's really not... - */ - fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE; - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE; - else - fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC; - break; - } + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + subs->ops.prepare = prepare_playback_urb; + return 0; + case SNDRV_PCM_TRIGGER_STOP: + return deactivate_urbs(subs, 0, 0); + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + subs->ops.prepare = prepare_nodata_playback_urb; + return 0; + } - /* ok, let's parse further... */ - if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) { - kfree(fp->rate_table); - kfree(fp); - fp = NULL; - continue; - } + return -EINVAL; +} - snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint); - err = snd_usb_add_audio_endpoint(chip, stream, fp); - if (err < 0) { - kfree(fp->rate_table); - kfree(fp); - return err; - } - /* try to set the interface... */ - usb_set_interface(chip->dev, iface_no, altno); - snd_usb_init_pitch(chip, iface_no, alts, fp); - snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max); +int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_usb_substream *subs = substream->runtime->private_data; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + subs->ops.retire = retire_capture_urb; + return start_urbs(subs, substream->runtime); + case SNDRV_PCM_TRIGGER_STOP: + return deactivate_urbs(subs, 0, 0); + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + subs->ops.retire = retire_paused_capture_urb; + return 0; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + subs->ops.retire = retire_capture_urb; + return 0; } + + return -EINVAL; +} + +int snd_usb_substream_prepare(struct snd_usb_substream *subs, + struct snd_pcm_runtime *runtime) +{ + /* clear urbs (to be sure) */ + deactivate_urbs(subs, 0, 1); + wait_clear_urbs(subs); + + /* for playback, submit the URBs now; otherwise, the first hwptr_done + * updates for all URBs would happen at the same time when starting */ + if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { + subs->ops.prepare = prepare_nodata_playback_urb; + return start_urbs(subs, runtime); + } + return 0; } diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index 64dd0db023b2..88eb63a636eb 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -1,11 +1,21 @@ #ifndef __USBAUDIO_ENDPOINT_H #define __USBAUDIO_ENDPOINT_H -int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, - int iface_no); +void snd_usb_init_substream(struct snd_usb_stream *as, + int stream, + struct audioformat *fp); -int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip, - int stream, - struct audioformat *fp); +int snd_usb_init_substream_urbs(struct snd_usb_substream *subs, + unsigned int period_bytes, + unsigned int rate, + unsigned int frame_bits); + +void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force); + +int snd_usb_substream_prepare(struct snd_usb_substream *subs, + struct snd_pcm_runtime *runtime); + +int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd); +int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd); #endif /* __USBAUDIO_ENDPOINT_H */ diff --git a/sound/usb/midi.c b/sound/usb/midi.c index f9289102886a..e21f026d9577 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -816,6 +816,22 @@ static struct usb_protocol_ops snd_usbmidi_raw_ops = { .output = snd_usbmidi_raw_output, }; +/* + * FTDI protocol: raw MIDI bytes, but input packets have two modem status bytes. + */ + +static void snd_usbmidi_ftdi_input(struct snd_usb_midi_in_endpoint* ep, + uint8_t* buffer, int buffer_length) +{ + if (buffer_length > 2) + snd_usbmidi_input_data(ep, 0, buffer + 2, buffer_length - 2); +} + +static struct usb_protocol_ops snd_usbmidi_ftdi_ops = { + .input = snd_usbmidi_ftdi_input, + .output = snd_usbmidi_raw_output, +}; + static void snd_usbmidi_us122l_input(struct snd_usb_midi_in_endpoint *ep, uint8_t *buffer, int buffer_length) { @@ -2163,6 +2179,17 @@ int snd_usbmidi_create(struct snd_card *card, /* endpoint 1 is input-only */ endpoints[1].out_cables = 0; break; + case QUIRK_MIDI_FTDI: + umidi->usb_protocol_ops = &snd_usbmidi_ftdi_ops; + + /* set baud rate to 31250 (48 MHz / 16 / 96) */ + err = usb_control_msg(umidi->dev, usb_sndctrlpipe(umidi->dev, 0), + 3, 0x40, 0x60, 0, NULL, 0, 1000); + if (err < 0) + break; + + err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); + break; default: snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); err = -ENXIO; diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index c22fa76e363a..78a5abda6793 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -152,6 +152,7 @@ static inline void check_mapped_dB(const struct usbmix_name_map *p, if (p && p->dB) { cval->dBmin = p->dB->min; cval->dBmax = p->dB->max; + cval->initialized = 1; } } @@ -880,8 +881,17 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; } else { - if (! cval->initialized) - get_min_max(cval, 0); + if (!cval->initialized) { + get_min_max(cval, 0); + if (cval->initialized && cval->dBmin >= cval->dBmax) { + kcontrol->vd[0].access &= + ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ | + SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK); + snd_ctl_notify(cval->mixer->chip->card, + SNDRV_CTL_EVENT_MASK_INFO, + &kcontrol->id); + } + } uinfo->value.integer.min = 0; uinfo->value.integer.max = (cval->max - cval->min + cval->res - 1) / cval->res; @@ -1092,7 +1102,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, " Switch" : " Volume"); if (control == UAC_FU_VOLUME) { check_mapped_dB(map, cval); - if (cval->dBmin < cval->dBmax) { + if (cval->dBmin < cval->dBmax || !cval->initialized) { kctl->tlv.c = mixer_vol_tlv; kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ | @@ -1191,6 +1201,11 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void if (state->mixer->protocol == UAC_VERSION_1) { csize = hdr->bControlSize; + if (!csize) { + snd_printdd(KERN_ERR "usbaudio: unit %u: " + "invalid bControlSize == 0\n", unitid); + return -EINVAL; + } channels = (hdr->bLength - 7) / csize - 1; bmaControls = hdr->bmaControls; } else { @@ -1934,15 +1949,13 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) struct mixer_build state; int err; const struct usbmix_ctl_map *map; - struct usb_host_interface *hostif; void *p; - hostif = mixer->chip->ctrl_intf; memset(&state, 0, sizeof(state)); state.chip = mixer->chip; state.mixer = mixer; - state.buffer = hostif->extra; - state.buflen = hostif->extralen; + state.buffer = mixer->hostif->extra; + state.buflen = mixer->hostif->extralen; /* check the mapping table */ for (map = usbmix_ctl_maps; map->id; map++) { @@ -1955,7 +1968,8 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) } p = NULL; - while ((p = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, p, UAC_OUTPUT_TERMINAL)) != NULL) { + while ((p = snd_usb_find_csint_desc(mixer->hostif->extra, mixer->hostif->extralen, + p, UAC_OUTPUT_TERMINAL)) != NULL) { if (mixer->protocol == UAC_VERSION_1) { struct uac1_output_terminal_descriptor *desc = p; @@ -2162,17 +2176,15 @@ int snd_usb_mixer_activate(struct usb_mixer_interface *mixer) /* create the handler for the optional status interrupt endpoint */ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) { - struct usb_host_interface *hostif; struct usb_endpoint_descriptor *ep; void *transfer_buffer; int buffer_length; unsigned int epnum; - hostif = mixer->chip->ctrl_intf; /* we need one interrupt input endpoint */ - if (get_iface_desc(hostif)->bNumEndpoints < 1) + if (get_iface_desc(mixer->hostif)->bNumEndpoints < 1) return 0; - ep = get_endpoint(hostif, 0); + ep = get_endpoint(mixer->hostif, 0); if (!usb_endpoint_dir_in(ep) || !usb_endpoint_xfer_int(ep)) return 0; @@ -2202,7 +2214,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, }; struct usb_mixer_interface *mixer; struct snd_info_entry *entry; - struct usb_host_interface *host_iface; int err; strcpy(chip->card->mixername, "USB Mixer"); @@ -2219,8 +2230,8 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, return -ENOMEM; } - host_iface = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; - switch (get_iface_desc(host_iface)->bInterfaceProtocol) { + mixer->hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; + switch (get_iface_desc(mixer->hostif)->bInterfaceProtocol) { case UAC_VERSION_1: default: mixer->protocol = UAC_VERSION_1; diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index ae1a14dcfe82..81b2d8a32fb0 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -3,6 +3,7 @@ struct usb_mixer_interface { struct snd_usb_audio *chip; + struct usb_host_interface *hostif; struct list_head list; unsigned int ignore_ctl_error; struct urb *urb; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index b8dcbf407bbb..b5bc870878db 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -28,12 +28,36 @@ #include "card.h" #include "quirks.h" #include "debug.h" -#include "urb.h" +#include "endpoint.h" #include "helper.h" #include "pcm.h" #include "clock.h" #include "power.h" +/* return the estimated delay based on USB frame counters */ +snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, + unsigned int rate) +{ + int current_frame_number; + int frame_diff; + int est_delay; + + current_frame_number = usb_get_current_frame_number(subs->dev); + /* + * HCD implementations use different widths, use lower 8 bits. + * The delay will be managed up to 256ms, which is more than + * enough + */ + frame_diff = (current_frame_number - subs->last_frame_number) & 0xff; + + /* Approximation based on number of samples per USB frame (ms), + some truncation for 44.1 but the estimate is good enough */ + est_delay = subs->last_delay - (frame_diff * rate / 1000); + if (est_delay < 0) + est_delay = 0; + return est_delay; +} + /* * return the current pcm pointer. just based on the hwptr_done value. */ @@ -45,6 +69,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream subs = (struct snd_usb_substream *)substream->runtime->private_data; spin_lock(&subs->lock); hwptr_done = subs->hwptr_done; + substream->runtime->delay = snd_usb_pcm_delay(subs, + substream->runtime->rate); spin_unlock(&subs->lock); return hwptr_done / (substream->runtime->frame_bits >> 3); } @@ -417,6 +443,8 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) subs->hwptr_done = 0; subs->transfer_done = 0; subs->phase = 0; + subs->last_delay = 0; + subs->last_frame_number = 0; runtime->delay = 0; return snd_usb_substream_prepare(subs, runtime); diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h index ed3e283f618d..df7a003682ad 100644 --- a/sound/usb/pcm.h +++ b/sound/usb/pcm.h @@ -1,6 +1,9 @@ #ifndef __USBAUDIO_PCM_H #define __USBAUDIO_PCM_H +snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, + unsigned int rate); + void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream); int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index dba0b7f11c54..b61945f3af9e 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -39,6 +39,17 @@ .idProduct = prod, \ .bInterfaceClass = USB_CLASS_VENDOR_SPEC +/* FTDI devices */ +{ + USB_DEVICE(0x0403, 0xb8d8), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + /* .vendor_name = "STARR LABS", */ + /* .product_name = "Starr Labs MIDI USB device", */ + .ifnum = 0, + .type = QUIRK_MIDI_FTDI + } +}, + /* Creative/Toshiba Multimedia Center SB-0500 */ { USB_DEVICE(0x041e, 0x3048), @@ -1678,6 +1689,20 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { + /* Added support for Roland UM-ONE which differs from UM-1 */ + USB_DEVICE(0x0582, 0x012a), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + /* .vendor_name = "ROLAND", */ + /* .product_name = "UM-ONE", */ + .ifnum = 0, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0001, + .in_cables = 0x0003 + } + } +}, +{ USB_DEVICE(0x0582, 0x011e), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { /* .vendor_name = "BOSS", */ @@ -1707,6 +1732,40 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +{ + USB_DEVICE(0x0582, 0x0130), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + /* .vendor_name = "BOSS", */ + /* .product_name = "MICRO BR-80", */ + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 2, + .type = QUIRK_AUDIO_STANDARD_INTERFACE + }, + { + .ifnum = 3, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + }, + { + .ifnum = -1 + } + } + } +}, /* Guillemot devices */ { @@ -2417,6 +2476,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), .idProduct = 0x1020, }, +/* KeithMcMillen Stringport */ +{ + USB_DEVICE(0x1f38, 0x0001), + .bInterfaceClass = USB_CLASS_AUDIO, +}, + /* Miditech devices */ { USB_DEVICE(0x4752, 0x0011), diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 77762c99afbe..556edea28b90 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -34,6 +34,7 @@ #include "endpoint.h" #include "pcm.h" #include "clock.h" +#include "stream.h" /* * handle the quirks for the contained interfaces @@ -106,7 +107,7 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip, alts = &iface->altsetting[0]; altsd = get_iface_desc(alts); - err = snd_usb_parse_audio_endpoints(chip, altsd->bInterfaceNumber); + err = snd_usb_parse_audio_interface(chip, altsd->bInterfaceNumber); if (err < 0) { snd_printk(KERN_ERR "cannot setup if %d: error %d\n", altsd->bInterfaceNumber, err); @@ -147,7 +148,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, stream = (fp->endpoint & USB_DIR_IN) ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; - err = snd_usb_add_audio_endpoint(chip, stream, fp); + err = snd_usb_add_audio_stream(chip, stream, fp); if (err < 0) { kfree(fp); kfree(rate_table); @@ -254,7 +255,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, stream = (fp->endpoint & USB_DIR_IN) ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; - err = snd_usb_add_audio_endpoint(chip, stream, fp); + err = snd_usb_add_audio_stream(chip, stream, fp); if (err < 0) { kfree(fp); return err; @@ -306,6 +307,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip, [QUIRK_MIDI_EMAGIC] = create_any_midi_quirk, [QUIRK_MIDI_CME] = create_any_midi_quirk, [QUIRK_MIDI_AKAI] = create_any_midi_quirk, + [QUIRK_MIDI_FTDI] = create_any_midi_quirk, [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, @@ -426,7 +428,7 @@ static int snd_usb_cm106_boot_quirk(struct usb_device *dev) */ static int snd_usb_cm6206_boot_quirk(struct usb_device *dev) { - int err, reg; + int err = 0, reg; int val[] = {0x2004, 0x3000, 0xf800, 0x143f, 0x0000, 0x3000}; for (reg = 0; reg < ARRAY_SIZE(val); reg++) { diff --git a/sound/usb/stream.c b/sound/usb/stream.c new file mode 100644 index 000000000000..5ff8010b2d6f --- /dev/null +++ b/sound/usb/stream.c @@ -0,0 +1,452 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/usb.h> +#include <linux/usb/audio.h> +#include <linux/usb/audio-v2.h> + +#include <sound/core.h> +#include <sound/pcm.h> + +#include "usbaudio.h" +#include "card.h" +#include "proc.h" +#include "quirks.h" +#include "endpoint.h" +#include "pcm.h" +#include "helper.h" +#include "format.h" +#include "clock.h" +#include "stream.h" + +/* + * free a substream + */ +static void free_substream(struct snd_usb_substream *subs) +{ + struct list_head *p, *n; + + if (!subs->num_formats) + return; /* not initialized */ + list_for_each_safe(p, n, &subs->fmt_list) { + struct audioformat *fp = list_entry(p, struct audioformat, list); + kfree(fp->rate_table); + kfree(fp); + } + kfree(subs->rate_list.list); +} + + +/* + * free a usb stream instance + */ +static void snd_usb_audio_stream_free(struct snd_usb_stream *stream) +{ + free_substream(&stream->substream[0]); + free_substream(&stream->substream[1]); + list_del(&stream->list); + kfree(stream); +} + +static void snd_usb_audio_pcm_free(struct snd_pcm *pcm) +{ + struct snd_usb_stream *stream = pcm->private_data; + if (stream) { + stream->pcm = NULL; + snd_usb_audio_stream_free(stream); + } +} + + +/* + * add this endpoint to the chip instance. + * if a stream with the same endpoint already exists, append to it. + * if not, create a new pcm stream. + */ +int snd_usb_add_audio_stream(struct snd_usb_audio *chip, + int stream, + struct audioformat *fp) +{ + struct list_head *p; + struct snd_usb_stream *as; + struct snd_usb_substream *subs; + struct snd_pcm *pcm; + int err; + + list_for_each(p, &chip->pcm_list) { + as = list_entry(p, struct snd_usb_stream, list); + if (as->fmt_type != fp->fmt_type) + continue; + subs = &as->substream[stream]; + if (!subs->endpoint) + continue; + if (subs->endpoint == fp->endpoint) { + list_add_tail(&fp->list, &subs->fmt_list); + subs->num_formats++; + subs->formats |= fp->formats; + return 0; + } + } + /* look for an empty stream */ + list_for_each(p, &chip->pcm_list) { + as = list_entry(p, struct snd_usb_stream, list); + if (as->fmt_type != fp->fmt_type) + continue; + subs = &as->substream[stream]; + if (subs->endpoint) + continue; + err = snd_pcm_new_stream(as->pcm, stream, 1); + if (err < 0) + return err; + snd_usb_init_substream(as, stream, fp); + return 0; + } + + /* create a new pcm */ + as = kzalloc(sizeof(*as), GFP_KERNEL); + if (!as) + return -ENOMEM; + as->pcm_index = chip->pcm_devs; + as->chip = chip; + as->fmt_type = fp->fmt_type; + err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs, + stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0, + stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1, + &pcm); + if (err < 0) { + kfree(as); + return err; + } + as->pcm = pcm; + pcm->private_data = as; + pcm->private_free = snd_usb_audio_pcm_free; + pcm->info_flags = 0; + if (chip->pcm_devs > 0) + sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs); + else + strcpy(pcm->name, "USB Audio"); + + snd_usb_init_substream(as, stream, fp); + + list_add(&as->list, &chip->pcm_list); + chip->pcm_devs++; + + snd_usb_proc_pcm_format_add(as); + + return 0; +} + +static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, + struct usb_host_interface *alts, + int protocol, int iface_no) +{ + /* parsed with a v1 header here. that's ok as we only look at the + * header first which is the same for both versions */ + struct uac_iso_endpoint_descriptor *csep; + struct usb_interface_descriptor *altsd = get_iface_desc(alts); + int attributes = 0; + + csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT); + + /* Creamware Noah has this descriptor after the 2nd endpoint */ + if (!csep && altsd->bNumEndpoints >= 2) + csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT); + + if (!csep || csep->bLength < 7 || + csep->bDescriptorSubtype != UAC_EP_GENERAL) { + snd_printk(KERN_WARNING "%d:%u:%d : no or invalid" + " class specific endpoint descriptor\n", + chip->dev->devnum, iface_no, + altsd->bAlternateSetting); + return 0; + } + + if (protocol == UAC_VERSION_1) { + attributes = csep->bmAttributes; + } else { + struct uac2_iso_endpoint_descriptor *csep2 = + (struct uac2_iso_endpoint_descriptor *) csep; + + attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX; + + /* emulate the endpoint attributes of a v1 device */ + if (csep2->bmControls & UAC2_CONTROL_PITCH) + attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL; + } + + return attributes; +} + +static struct uac2_input_terminal_descriptor * + snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, + int terminal_id) +{ + struct uac2_input_terminal_descriptor *term = NULL; + + while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, + ctrl_iface->extralen, + term, UAC_INPUT_TERMINAL))) { + if (term->bTerminalID == terminal_id) + return term; + } + + return NULL; +} + +static struct uac2_output_terminal_descriptor * + snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface, + int terminal_id) +{ + struct uac2_output_terminal_descriptor *term = NULL; + + while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, + ctrl_iface->extralen, + term, UAC_OUTPUT_TERMINAL))) { + if (term->bTerminalID == terminal_id) + return term; + } + + return NULL; +} + +int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) +{ + struct usb_device *dev; + struct usb_interface *iface; + struct usb_host_interface *alts; + struct usb_interface_descriptor *altsd; + int i, altno, err, stream; + int format = 0, num_channels = 0; + struct audioformat *fp = NULL; + int num, protocol, clock = 0; + struct uac_format_type_i_continuous_descriptor *fmt; + + dev = chip->dev; + + /* parse the interface's altsettings */ + iface = usb_ifnum_to_if(dev, iface_no); + + num = iface->num_altsetting; + + /* + * Dallas DS4201 workaround: It presents 5 altsettings, but the last + * one misses syncpipe, and does not produce any sound. + */ + if (chip->usb_id == USB_ID(0x04fa, 0x4201)) + num = 4; + + for (i = 0; i < num; i++) { + alts = &iface->altsetting[i]; + altsd = get_iface_desc(alts); + protocol = altsd->bInterfaceProtocol; + /* skip invalid one */ + if ((altsd->bInterfaceClass != USB_CLASS_AUDIO && + altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || + (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING && + altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) || + altsd->bNumEndpoints < 1 || + le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0) + continue; + /* must be isochronous */ + if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != + USB_ENDPOINT_XFER_ISOC) + continue; + /* check direction */ + stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ? + SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; + altno = altsd->bAlternateSetting; + + if (snd_usb_apply_interface_quirk(chip, iface_no, altno)) + continue; + + /* get audio formats */ + switch (protocol) { + default: + snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n", + dev->devnum, iface_no, altno, protocol); + protocol = UAC_VERSION_1; + /* fall through */ + + case UAC_VERSION_1: { + struct uac1_as_header_descriptor *as = + snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); + + if (!as) { + snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n", + dev->devnum, iface_no, altno); + continue; + } + + if (as->bLength < sizeof(*as)) { + snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n", + dev->devnum, iface_no, altno); + continue; + } + + format = le16_to_cpu(as->wFormatTag); /* remember the format value */ + break; + } + + case UAC_VERSION_2: { + struct uac2_input_terminal_descriptor *input_term; + struct uac2_output_terminal_descriptor *output_term; + struct uac2_as_header_descriptor *as = + snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL); + + if (!as) { + snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n", + dev->devnum, iface_no, altno); + continue; + } + + if (as->bLength < sizeof(*as)) { + snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n", + dev->devnum, iface_no, altno); + continue; + } + + num_channels = as->bNrChannels; + format = le32_to_cpu(as->bmFormats); + + /* lookup the terminal associated to this interface + * to extract the clock */ + input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, + as->bTerminalLink); + if (input_term) { + clock = input_term->bCSourceID; + break; + } + + output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf, + as->bTerminalLink); + if (output_term) { + clock = output_term->bCSourceID; + break; + } + + snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n", + dev->devnum, iface_no, altno, as->bTerminalLink); + continue; + } + } + + /* get format type */ + fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE); + if (!fmt) { + snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n", + dev->devnum, iface_no, altno); + continue; + } + if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) || + ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) { + snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n", + dev->devnum, iface_no, altno); + continue; + } + + /* + * Blue Microphones workaround: The last altsetting is identical + * with the previous one, except for a larger packet size, but + * is actually a mislabeled two-channel setting; ignore it. + */ + if (fmt->bNrChannels == 1 && + fmt->bSubframeSize == 2 && + altno == 2 && num == 3 && + fp && fp->altsetting == 1 && fp->channels == 1 && + fp->formats == SNDRV_PCM_FMTBIT_S16_LE && + protocol == UAC_VERSION_1 && + le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == + fp->maxpacksize * 2) + continue; + + fp = kzalloc(sizeof(*fp), GFP_KERNEL); + if (! fp) { + snd_printk(KERN_ERR "cannot malloc\n"); + return -ENOMEM; + } + + fp->iface = iface_no; + fp->altsetting = altno; + fp->altset_idx = i; + fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; + fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; + fp->datainterval = snd_usb_parse_datainterval(chip, alts); + fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); + /* num_channels is only set for v2 interfaces */ + fp->channels = num_channels; + if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) + fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) + * (fp->maxpacksize & 0x7ff); + fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no); + fp->clock = clock; + + /* some quirks for attributes here */ + + switch (chip->usb_id) { + case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */ + /* Optoplay sets the sample rate attribute although + * it seems not supporting it in fact. + */ + fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE; + break; + case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */ + case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ + /* doesn't set the sample rate attribute, but supports it */ + fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE; + break; + case USB_ID(0x0763, 0x2001): /* M-Audio Quattro USB */ + case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */ + case USB_ID(0x047f, 0x0ca1): /* plantronics headset */ + case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is + an older model 77d:223) */ + /* + * plantronics headset and Griffin iMic have set adaptive-in + * although it's really not... + */ + fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE; + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE; + else + fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC; + break; + } + + /* ok, let's parse further... */ + if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) { + kfree(fp->rate_table); + kfree(fp); + fp = NULL; + continue; + } + + snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint); + err = snd_usb_add_audio_stream(chip, stream, fp); + if (err < 0) { + kfree(fp->rate_table); + kfree(fp); + return err; + } + /* try to set the interface... */ + usb_set_interface(chip->dev, iface_no, altno); + snd_usb_init_pitch(chip, iface_no, alts, fp); + snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max); + } + return 0; +} + diff --git a/sound/usb/stream.h b/sound/usb/stream.h new file mode 100644 index 000000000000..c97f679fc84f --- /dev/null +++ b/sound/usb/stream.h @@ -0,0 +1,12 @@ +#ifndef __USBAUDIO_STREAM_H +#define __USBAUDIO_STREAM_H + +int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, + int iface_no); + +int snd_usb_add_audio_stream(struct snd_usb_audio *chip, + int stream, + struct audioformat *fp); + +#endif /* __USBAUDIO_STREAM_H */ + diff --git a/sound/usb/urb.c b/sound/usb/urb.c deleted file mode 100644 index e184349aee83..000000000000 --- a/sound/usb/urb.c +++ /dev/null @@ -1,941 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/gfp.h> -#include <linux/init.h> -#include <linux/usb.h> -#include <linux/usb/audio.h> - -#include <sound/core.h> -#include <sound/pcm.h> - -#include "usbaudio.h" -#include "helper.h" -#include "card.h" -#include "urb.h" -#include "pcm.h" - -/* - * convert a sampling rate into our full speed format (fs/1000 in Q16.16) - * this will overflow at approx 524 kHz - */ -static inline unsigned get_usb_full_speed_rate(unsigned int rate) -{ - return ((rate << 13) + 62) / 125; -} - -/* - * convert a sampling rate into USB high speed format (fs/8000 in Q16.16) - * this will overflow at approx 4 MHz - */ -static inline unsigned get_usb_high_speed_rate(unsigned int rate) -{ - return ((rate << 10) + 62) / 125; -} - -/* - * unlink active urbs. - */ -static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sleep) -{ - struct snd_usb_audio *chip = subs->stream->chip; - unsigned int i; - int async; - - subs->running = 0; - - if (!force && subs->stream->chip->shutdown) /* to be sure... */ - return -EBADFD; - - async = !can_sleep && chip->async_unlink; - - if (!async && in_interrupt()) - return 0; - - for (i = 0; i < subs->nurbs; i++) { - if (test_bit(i, &subs->active_mask)) { - if (!test_and_set_bit(i, &subs->unlink_mask)) { - struct urb *u = subs->dataurb[i].urb; - if (async) - usb_unlink_urb(u); - else - usb_kill_urb(u); - } - } - } - if (subs->syncpipe) { - for (i = 0; i < SYNC_URBS; i++) { - if (test_bit(i+16, &subs->active_mask)) { - if (!test_and_set_bit(i+16, &subs->unlink_mask)) { - struct urb *u = subs->syncurb[i].urb; - if (async) - usb_unlink_urb(u); - else - usb_kill_urb(u); - } - } - } - } - return 0; -} - - -/* - * release a urb data - */ -static void release_urb_ctx(struct snd_urb_ctx *u) -{ - if (u->urb) { - if (u->buffer_size) - usb_free_coherent(u->subs->dev, u->buffer_size, - u->urb->transfer_buffer, - u->urb->transfer_dma); - usb_free_urb(u->urb); - u->urb = NULL; - } -} - -/* - * wait until all urbs are processed. - */ -static int wait_clear_urbs(struct snd_usb_substream *subs) -{ - unsigned long end_time = jiffies + msecs_to_jiffies(1000); - unsigned int i; - int alive; - - do { - alive = 0; - for (i = 0; i < subs->nurbs; i++) { - if (test_bit(i, &subs->active_mask)) - alive++; - } - if (subs->syncpipe) { - for (i = 0; i < SYNC_URBS; i++) { - if (test_bit(i + 16, &subs->active_mask)) - alive++; - } - } - if (! alive) - break; - schedule_timeout_uninterruptible(1); - } while (time_before(jiffies, end_time)); - if (alive) - snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive); - return 0; -} - -/* - * release a substream - */ -void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force) -{ - int i; - - /* stop urbs (to be sure) */ - deactivate_urbs(subs, force, 1); - wait_clear_urbs(subs); - - for (i = 0; i < MAX_URBS; i++) - release_urb_ctx(&subs->dataurb[i]); - for (i = 0; i < SYNC_URBS; i++) - release_urb_ctx(&subs->syncurb[i]); - usb_free_coherent(subs->dev, SYNC_URBS * 4, - subs->syncbuf, subs->sync_dma); - subs->syncbuf = NULL; - subs->nurbs = 0; -} - -/* - * complete callback from data urb - */ -static void snd_complete_urb(struct urb *urb) -{ - struct snd_urb_ctx *ctx = urb->context; - struct snd_usb_substream *subs = ctx->subs; - struct snd_pcm_substream *substream = ctx->subs->pcm_substream; - int err = 0; - - if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) || - !subs->running || /* can be stopped during retire callback */ - (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 || - (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { - clear_bit(ctx->index, &subs->active_mask); - if (err < 0) { - snd_printd(KERN_ERR "cannot submit urb (err = %d)\n", err); - snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); - } - } -} - - -/* - * complete callback from sync urb - */ -static void snd_complete_sync_urb(struct urb *urb) -{ - struct snd_urb_ctx *ctx = urb->context; - struct snd_usb_substream *subs = ctx->subs; - struct snd_pcm_substream *substream = ctx->subs->pcm_substream; - int err = 0; - - if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) || - !subs->running || /* can be stopped during retire callback */ - (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 || - (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { - clear_bit(ctx->index + 16, &subs->active_mask); - if (err < 0) { - snd_printd(KERN_ERR "cannot submit sync urb (err = %d)\n", err); - snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); - } - } -} - - -/* - * initialize a substream for plaback/capture - */ -int snd_usb_init_substream_urbs(struct snd_usb_substream *subs, - unsigned int period_bytes, - unsigned int rate, - unsigned int frame_bits) -{ - unsigned int maxsize, i; - int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK; - unsigned int urb_packs, total_packs, packs_per_ms; - struct snd_usb_audio *chip = subs->stream->chip; - - /* calculate the frequency in 16.16 format */ - if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) - subs->freqn = get_usb_full_speed_rate(rate); - else - subs->freqn = get_usb_high_speed_rate(rate); - subs->freqm = subs->freqn; - subs->freqshift = INT_MIN; - /* calculate max. frequency */ - if (subs->maxpacksize) { - /* whatever fits into a max. size packet */ - maxsize = subs->maxpacksize; - subs->freqmax = (maxsize / (frame_bits >> 3)) - << (16 - subs->datainterval); - } else { - /* no max. packet size: just take 25% higher than nominal */ - subs->freqmax = subs->freqn + (subs->freqn >> 2); - maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3)) - >> (16 - subs->datainterval); - } - subs->phase = 0; - - if (subs->fill_max) - subs->curpacksize = subs->maxpacksize; - else - subs->curpacksize = maxsize; - - if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) - packs_per_ms = 8 >> subs->datainterval; - else - packs_per_ms = 1; - - if (is_playback) { - urb_packs = max(chip->nrpacks, 1); - urb_packs = min(urb_packs, (unsigned int)MAX_PACKS); - } else - urb_packs = 1; - urb_packs *= packs_per_ms; - if (subs->syncpipe) - urb_packs = min(urb_packs, 1U << subs->syncinterval); - - /* decide how many packets to be used */ - if (is_playback) { - unsigned int minsize, maxpacks; - /* determine how small a packet can be */ - minsize = (subs->freqn >> (16 - subs->datainterval)) - * (frame_bits >> 3); - /* with sync from device, assume it can be 12% lower */ - if (subs->syncpipe) - minsize -= minsize >> 3; - minsize = max(minsize, 1u); - total_packs = (period_bytes + minsize - 1) / minsize; - /* we need at least two URBs for queueing */ - if (total_packs < 2) { - total_packs = 2; - } else { - /* and we don't want too long a queue either */ - maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2); - total_packs = min(total_packs, maxpacks); - } - } else { - while (urb_packs > 1 && urb_packs * maxsize >= period_bytes) - urb_packs >>= 1; - total_packs = MAX_URBS * urb_packs; - } - subs->nurbs = (total_packs + urb_packs - 1) / urb_packs; - if (subs->nurbs > MAX_URBS) { - /* too much... */ - subs->nurbs = MAX_URBS; - total_packs = MAX_URBS * urb_packs; - } else if (subs->nurbs < 2) { - /* too little - we need at least two packets - * to ensure contiguous playback/capture - */ - subs->nurbs = 2; - } - - /* allocate and initialize data urbs */ - for (i = 0; i < subs->nurbs; i++) { - struct snd_urb_ctx *u = &subs->dataurb[i]; - u->index = i; - u->subs = subs; - u->packets = (i + 1) * total_packs / subs->nurbs - - i * total_packs / subs->nurbs; - u->buffer_size = maxsize * u->packets; - if (subs->fmt_type == UAC_FORMAT_TYPE_II) - u->packets++; /* for transfer delimiter */ - u->urb = usb_alloc_urb(u->packets, GFP_KERNEL); - if (!u->urb) - goto out_of_memory; - u->urb->transfer_buffer = - usb_alloc_coherent(subs->dev, u->buffer_size, - GFP_KERNEL, &u->urb->transfer_dma); - if (!u->urb->transfer_buffer) - goto out_of_memory; - u->urb->pipe = subs->datapipe; - u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - u->urb->interval = 1 << subs->datainterval; - u->urb->context = u; - u->urb->complete = snd_complete_urb; - } - - if (subs->syncpipe) { - /* allocate and initialize sync urbs */ - subs->syncbuf = usb_alloc_coherent(subs->dev, SYNC_URBS * 4, - GFP_KERNEL, &subs->sync_dma); - if (!subs->syncbuf) - goto out_of_memory; - for (i = 0; i < SYNC_URBS; i++) { - struct snd_urb_ctx *u = &subs->syncurb[i]; - u->index = i; - u->subs = subs; - u->packets = 1; - u->urb = usb_alloc_urb(1, GFP_KERNEL); - if (!u->urb) - goto out_of_memory; - u->urb->transfer_buffer = subs->syncbuf + i * 4; - u->urb->transfer_dma = subs->sync_dma + i * 4; - u->urb->transfer_buffer_length = 4; - u->urb->pipe = subs->syncpipe; - u->urb->transfer_flags = URB_ISO_ASAP | - URB_NO_TRANSFER_DMA_MAP; - u->urb->number_of_packets = 1; - u->urb->interval = 1 << subs->syncinterval; - u->urb->context = u; - u->urb->complete = snd_complete_sync_urb; - } - } - return 0; - -out_of_memory: - snd_usb_release_substream_urbs(subs, 0); - return -ENOMEM; -} - -/* - * prepare urb for full speed capture sync pipe - * - * fill the length and offset of each urb descriptor. - * the fixed 10.14 frequency is passed through the pipe. - */ -static int prepare_capture_sync_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - unsigned char *cp = urb->transfer_buffer; - struct snd_urb_ctx *ctx = urb->context; - - urb->dev = ctx->subs->dev; /* we need to set this at each time */ - urb->iso_frame_desc[0].length = 3; - urb->iso_frame_desc[0].offset = 0; - cp[0] = subs->freqn >> 2; - cp[1] = subs->freqn >> 10; - cp[2] = subs->freqn >> 18; - return 0; -} - -/* - * prepare urb for high speed capture sync pipe - * - * fill the length and offset of each urb descriptor. - * the fixed 12.13 frequency is passed as 16.16 through the pipe. - */ -static int prepare_capture_sync_urb_hs(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - unsigned char *cp = urb->transfer_buffer; - struct snd_urb_ctx *ctx = urb->context; - - urb->dev = ctx->subs->dev; /* we need to set this at each time */ - urb->iso_frame_desc[0].length = 4; - urb->iso_frame_desc[0].offset = 0; - cp[0] = subs->freqn; - cp[1] = subs->freqn >> 8; - cp[2] = subs->freqn >> 16; - cp[3] = subs->freqn >> 24; - return 0; -} - -/* - * process after capture sync complete - * - nothing to do - */ -static int retire_capture_sync_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - return 0; -} - -/* - * prepare urb for capture data pipe - * - * fill the offset and length of each descriptor. - * - * we use a temporary buffer to write the captured data. - * since the length of written data is determined by host, we cannot - * write onto the pcm buffer directly... the data is thus copied - * later at complete callback to the global buffer. - */ -static int prepare_capture_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - int i, offs; - struct snd_urb_ctx *ctx = urb->context; - - offs = 0; - urb->dev = ctx->subs->dev; /* we need to set this at each time */ - for (i = 0; i < ctx->packets; i++) { - urb->iso_frame_desc[i].offset = offs; - urb->iso_frame_desc[i].length = subs->curpacksize; - offs += subs->curpacksize; - } - urb->transfer_buffer_length = offs; - urb->number_of_packets = ctx->packets; - return 0; -} - -/* - * process after capture complete - * - * copy the data from each desctiptor to the pcm buffer, and - * update the current position. - */ -static int retire_capture_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - unsigned long flags; - unsigned char *cp; - int i; - unsigned int stride, frames, bytes, oldptr; - int period_elapsed = 0; - - stride = runtime->frame_bits >> 3; - - for (i = 0; i < urb->number_of_packets; i++) { - cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset; - if (urb->iso_frame_desc[i].status) { - snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status); - // continue; - } - bytes = urb->iso_frame_desc[i].actual_length; - frames = bytes / stride; - if (!subs->txfr_quirk) - bytes = frames * stride; - if (bytes % (runtime->sample_bits >> 3) != 0) { -#ifdef CONFIG_SND_DEBUG_VERBOSE - int oldbytes = bytes; -#endif - bytes = frames * stride; - snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n", - oldbytes, bytes); - } - /* update the current pointer */ - spin_lock_irqsave(&subs->lock, flags); - oldptr = subs->hwptr_done; - subs->hwptr_done += bytes; - if (subs->hwptr_done >= runtime->buffer_size * stride) - subs->hwptr_done -= runtime->buffer_size * stride; - frames = (bytes + (oldptr % stride)) / stride; - subs->transfer_done += frames; - if (subs->transfer_done >= runtime->period_size) { - subs->transfer_done -= runtime->period_size; - period_elapsed = 1; - } - spin_unlock_irqrestore(&subs->lock, flags); - /* copy a data chunk */ - if (oldptr + bytes > runtime->buffer_size * stride) { - unsigned int bytes1 = - runtime->buffer_size * stride - oldptr; - memcpy(runtime->dma_area + oldptr, cp, bytes1); - memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1); - } else { - memcpy(runtime->dma_area + oldptr, cp, bytes); - } - } - if (period_elapsed) - snd_pcm_period_elapsed(subs->pcm_substream); - return 0; -} - -/* - * Process after capture complete when paused. Nothing to do. - */ -static int retire_paused_capture_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - return 0; -} - - -/* - * prepare urb for playback sync pipe - * - * set up the offset and length to receive the current frequency. - */ -static int prepare_playback_sync_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - struct snd_urb_ctx *ctx = urb->context; - - urb->dev = ctx->subs->dev; /* we need to set this at each time */ - urb->iso_frame_desc[0].length = min(4u, ctx->subs->syncmaxsize); - urb->iso_frame_desc[0].offset = 0; - return 0; -} - -/* - * process after playback sync complete - * - * Full speed devices report feedback values in 10.14 format as samples per - * frame, high speed devices in 16.16 format as samples per microframe. - * Because the Audio Class 1 spec was written before USB 2.0, many high speed - * devices use a wrong interpretation, some others use an entirely different - * format. Therefore, we cannot predict what format any particular device uses - * and must detect it automatically. - */ -static int retire_playback_sync_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - unsigned int f; - int shift; - unsigned long flags; - - if (urb->iso_frame_desc[0].status != 0 || - urb->iso_frame_desc[0].actual_length < 3) - return 0; - - f = le32_to_cpup(urb->transfer_buffer); - if (urb->iso_frame_desc[0].actual_length == 3) - f &= 0x00ffffff; - else - f &= 0x0fffffff; - if (f == 0) - return 0; - - if (unlikely(subs->freqshift == INT_MIN)) { - /* - * The first time we see a feedback value, determine its format - * by shifting it left or right until it matches the nominal - * frequency value. This assumes that the feedback does not - * differ from the nominal value more than +50% or -25%. - */ - shift = 0; - while (f < subs->freqn - subs->freqn / 4) { - f <<= 1; - shift++; - } - while (f > subs->freqn + subs->freqn / 2) { - f >>= 1; - shift--; - } - subs->freqshift = shift; - } - else if (subs->freqshift >= 0) - f <<= subs->freqshift; - else - f >>= -subs->freqshift; - - if (likely(f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax)) { - /* - * If the frequency looks valid, set it. - * This value is referred to in prepare_playback_urb(). - */ - spin_lock_irqsave(&subs->lock, flags); - subs->freqm = f; - spin_unlock_irqrestore(&subs->lock, flags); - } else { - /* - * Out of range; maybe the shift value is wrong. - * Reset it so that we autodetect again the next time. - */ - subs->freqshift = INT_MIN; - } - - return 0; -} - -/* determine the number of frames in the next packet */ -static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs) -{ - if (subs->fill_max) - return subs->maxframesize; - else { - subs->phase = (subs->phase & 0xffff) - + (subs->freqm << subs->datainterval); - return min(subs->phase >> 16, subs->maxframesize); - } -} - -/* - * Prepare urb for streaming before playback starts or when paused. - * - * We don't have any data, so we send silence. - */ -static int prepare_nodata_playback_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - unsigned int i, offs, counts; - struct snd_urb_ctx *ctx = urb->context; - int stride = runtime->frame_bits >> 3; - - offs = 0; - urb->dev = ctx->subs->dev; - for (i = 0; i < ctx->packets; ++i) { - counts = snd_usb_audio_next_packet_size(subs); - urb->iso_frame_desc[i].offset = offs * stride; - urb->iso_frame_desc[i].length = counts * stride; - offs += counts; - } - urb->number_of_packets = ctx->packets; - urb->transfer_buffer_length = offs * stride; - memset(urb->transfer_buffer, - runtime->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0, - offs * stride); - return 0; -} - -/* - * prepare urb for playback data pipe - * - * Since a URB can handle only a single linear buffer, we must use double - * buffering when the data to be transferred overflows the buffer boundary. - * To avoid inconsistencies when updating hwptr_done, we use double buffering - * for all URBs. - */ -static int prepare_playback_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - int i, stride; - unsigned int counts, frames, bytes; - unsigned long flags; - int period_elapsed = 0; - struct snd_urb_ctx *ctx = urb->context; - - stride = runtime->frame_bits >> 3; - - frames = 0; - urb->dev = ctx->subs->dev; /* we need to set this at each time */ - urb->number_of_packets = 0; - spin_lock_irqsave(&subs->lock, flags); - for (i = 0; i < ctx->packets; i++) { - counts = snd_usb_audio_next_packet_size(subs); - /* set up descriptor */ - urb->iso_frame_desc[i].offset = frames * stride; - urb->iso_frame_desc[i].length = counts * stride; - frames += counts; - urb->number_of_packets++; - subs->transfer_done += counts; - if (subs->transfer_done >= runtime->period_size) { - subs->transfer_done -= runtime->period_size; - period_elapsed = 1; - if (subs->fmt_type == UAC_FORMAT_TYPE_II) { - if (subs->transfer_done > 0) { - /* FIXME: fill-max mode is not - * supported yet */ - frames -= subs->transfer_done; - counts -= subs->transfer_done; - urb->iso_frame_desc[i].length = - counts * stride; - subs->transfer_done = 0; - } - i++; - if (i < ctx->packets) { - /* add a transfer delimiter */ - urb->iso_frame_desc[i].offset = - frames * stride; - urb->iso_frame_desc[i].length = 0; - urb->number_of_packets++; - } - break; - } - } - if (period_elapsed) /* finish at the period boundary */ - break; - } - bytes = frames * stride; - if (subs->hwptr_done + bytes > runtime->buffer_size * stride) { - /* err, the transferred area goes over buffer boundary. */ - unsigned int bytes1 = - runtime->buffer_size * stride - subs->hwptr_done; - memcpy(urb->transfer_buffer, - runtime->dma_area + subs->hwptr_done, bytes1); - memcpy(urb->transfer_buffer + bytes1, - runtime->dma_area, bytes - bytes1); - } else { - memcpy(urb->transfer_buffer, - runtime->dma_area + subs->hwptr_done, bytes); - } - subs->hwptr_done += bytes; - if (subs->hwptr_done >= runtime->buffer_size * stride) - subs->hwptr_done -= runtime->buffer_size * stride; - runtime->delay += frames; - spin_unlock_irqrestore(&subs->lock, flags); - urb->transfer_buffer_length = bytes; - if (period_elapsed) - snd_pcm_period_elapsed(subs->pcm_substream); - return 0; -} - -/* - * process after playback data complete - * - decrease the delay count again - */ -static int retire_playback_urb(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime, - struct urb *urb) -{ - unsigned long flags; - int stride = runtime->frame_bits >> 3; - int processed = urb->transfer_buffer_length / stride; - - spin_lock_irqsave(&subs->lock, flags); - if (processed > runtime->delay) - runtime->delay = 0; - else - runtime->delay -= processed; - spin_unlock_irqrestore(&subs->lock, flags); - return 0; -} - -static const char *usb_error_string(int err) -{ - switch (err) { - case -ENODEV: - return "no device"; - case -ENOENT: - return "endpoint not enabled"; - case -EPIPE: - return "endpoint stalled"; - case -ENOSPC: - return "not enough bandwidth"; - case -ESHUTDOWN: - return "device disabled"; - case -EHOSTUNREACH: - return "device suspended"; - case -EINVAL: - case -EAGAIN: - case -EFBIG: - case -EMSGSIZE: - return "internal error"; - default: - return "unknown error"; - } -} - -/* - * set up and start data/sync urbs - */ -static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime) -{ - unsigned int i; - int err; - - if (subs->stream->chip->shutdown) - return -EBADFD; - - for (i = 0; i < subs->nurbs; i++) { - if (snd_BUG_ON(!subs->dataurb[i].urb)) - return -EINVAL; - if (subs->ops.prepare(subs, runtime, subs->dataurb[i].urb) < 0) { - snd_printk(KERN_ERR "cannot prepare datapipe for urb %d\n", i); - goto __error; - } - } - if (subs->syncpipe) { - for (i = 0; i < SYNC_URBS; i++) { - if (snd_BUG_ON(!subs->syncurb[i].urb)) - return -EINVAL; - if (subs->ops.prepare_sync(subs, runtime, subs->syncurb[i].urb) < 0) { - snd_printk(KERN_ERR "cannot prepare syncpipe for urb %d\n", i); - goto __error; - } - } - } - - subs->active_mask = 0; - subs->unlink_mask = 0; - subs->running = 1; - for (i = 0; i < subs->nurbs; i++) { - err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC); - if (err < 0) { - snd_printk(KERN_ERR "cannot submit datapipe " - "for urb %d, error %d: %s\n", - i, err, usb_error_string(err)); - goto __error; - } - set_bit(i, &subs->active_mask); - } - if (subs->syncpipe) { - for (i = 0; i < SYNC_URBS; i++) { - err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC); - if (err < 0) { - snd_printk(KERN_ERR "cannot submit syncpipe " - "for urb %d, error %d: %s\n", - i, err, usb_error_string(err)); - goto __error; - } - set_bit(i + 16, &subs->active_mask); - } - } - return 0; - - __error: - // snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN); - deactivate_urbs(subs, 0, 0); - return -EPIPE; -} - - -/* - */ -static struct snd_urb_ops audio_urb_ops[2] = { - { - .prepare = prepare_nodata_playback_urb, - .retire = retire_playback_urb, - .prepare_sync = prepare_playback_sync_urb, - .retire_sync = retire_playback_sync_urb, - }, - { - .prepare = prepare_capture_urb, - .retire = retire_capture_urb, - .prepare_sync = prepare_capture_sync_urb, - .retire_sync = retire_capture_sync_urb, - }, -}; - -/* - * initialize the substream instance. - */ - -void snd_usb_init_substream(struct snd_usb_stream *as, - int stream, struct audioformat *fp) -{ - struct snd_usb_substream *subs = &as->substream[stream]; - - INIT_LIST_HEAD(&subs->fmt_list); - spin_lock_init(&subs->lock); - - subs->stream = as; - subs->direction = stream; - subs->dev = as->chip->dev; - subs->txfr_quirk = as->chip->txfr_quirk; - subs->ops = audio_urb_ops[stream]; - if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH) - subs->ops.prepare_sync = prepare_capture_sync_urb_hs; - - snd_usb_set_pcm_ops(as->pcm, stream); - - list_add_tail(&fp->list, &subs->fmt_list); - subs->formats |= fp->formats; - subs->endpoint = fp->endpoint; - subs->num_formats++; - subs->fmt_type = fp->fmt_type; -} - -int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_usb_substream *subs = substream->runtime->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - subs->ops.prepare = prepare_playback_urb; - return 0; - case SNDRV_PCM_TRIGGER_STOP: - return deactivate_urbs(subs, 0, 0); - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - subs->ops.prepare = prepare_nodata_playback_urb; - return 0; - } - - return -EINVAL; -} - -int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_usb_substream *subs = substream->runtime->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - subs->ops.retire = retire_capture_urb; - return start_urbs(subs, substream->runtime); - case SNDRV_PCM_TRIGGER_STOP: - return deactivate_urbs(subs, 0, 0); - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - subs->ops.retire = retire_paused_capture_urb; - return 0; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - subs->ops.retire = retire_capture_urb; - return 0; - } - - return -EINVAL; -} - -int snd_usb_substream_prepare(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime) -{ - /* clear urbs (to be sure) */ - deactivate_urbs(subs, 0, 1); - wait_clear_urbs(subs); - - /* for playback, submit the URBs now; otherwise, the first hwptr_done - * updates for all URBs would happen at the same time when starting */ - if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { - subs->ops.prepare = prepare_nodata_playback_urb; - return start_urbs(subs, runtime); - } - - return 0; -} - diff --git a/sound/usb/urb.h b/sound/usb/urb.h deleted file mode 100644 index 888da38079cf..000000000000 --- a/sound/usb/urb.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __USBAUDIO_URB_H -#define __USBAUDIO_URB_H - -void snd_usb_init_substream(struct snd_usb_stream *as, - int stream, - struct audioformat *fp); - -int snd_usb_init_substream_urbs(struct snd_usb_substream *subs, - unsigned int period_bytes, - unsigned int rate, - unsigned int frame_bits); - -void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force); - -int snd_usb_substream_prepare(struct snd_usb_substream *subs, - struct snd_pcm_runtime *runtime); - -int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd); -int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd); - -#endif /* __USBAUDIO_URB_H */ diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 1e79986b5777..3e2b03577936 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -80,6 +80,7 @@ enum quirk_type { QUIRK_MIDI_CME, QUIRK_MIDI_AKAI, QUIRK_MIDI_US122L, + QUIRK_MIDI_FTDI, QUIRK_AUDIO_STANDARD_INTERFACE, QUIRK_AUDIO_FIXED_ENDPOINT, QUIRK_AUDIO_EDIROL_UAXX, |