diff options
Diffstat (limited to 'sound')
71 files changed, 2748 insertions, 926 deletions
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index 67893372173..3ff8cc5f487 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c @@ -437,9 +437,11 @@ static int i2sbus_shutdown(struct macio_dev* dev) } static struct macio_driver i2sbus_drv = { - .name = "soundbus-i2s", - .owner = THIS_MODULE, - .match_table = i2sbus_match, + .driver = { + .name = "soundbus-i2s", + .owner = THIS_MODULE, + .of_match_table = i2sbus_match, + }, .probe = i2sbus_probe, .remove = i2sbus_remove, #ifdef CONFIG_PM diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 428121a7e70..10c3a871a12 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -657,7 +657,7 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev) if (sr & AC97C_SR_CAEVT) { struct snd_pcm_runtime *runtime; int offset, next_period, block_size; - dev_info(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n", + dev_dbg(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n", casr & AC97C_CSR_OVRUN ? " OVRUN" : "", casr & AC97C_CSR_RXRDY ? " RXRDY" : "", casr & AC97C_CSR_UNRUN ? " UNRUN" : "", diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index e9d98be190c..e23e0e7ab26 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -67,6 +67,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram } else { if (new_hw_ptr == ULONG_MAX) { /* initialization */ snd_pcm_sframes_t avail = snd_pcm_playback_hw_avail(runtime); + if (avail > runtime->buffer_size) + avail = runtime->buffer_size; runtime->silence_filled = avail > 0 ? avail : 0; runtime->silence_start = (runtime->status->hw_ptr + runtime->silence_filled) % @@ -287,8 +289,11 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream, return -EPIPE; } } - if (avail >= runtime->control->avail_min) - wake_up(runtime->twake ? &runtime->tsleep : &runtime->sleep); + if (runtime->twake) { + if (avail >= runtime->twake) + wake_up(&runtime->tsleep); + } else if (avail >= runtime->control->avail_min) + wake_up(&runtime->sleep); return 0; } @@ -1707,7 +1712,7 @@ EXPORT_SYMBOL(snd_pcm_period_elapsed); * The available space is stored on availp. When err = 0 and avail = 0 * on the capture stream, it indicates the stream is in DRAINING state. */ -static int wait_for_avail_min(struct snd_pcm_substream *substream, +static int wait_for_avail(struct snd_pcm_substream *substream, snd_pcm_uframes_t *availp) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -1757,7 +1762,7 @@ static int wait_for_avail_min(struct snd_pcm_substream *substream, avail = snd_pcm_playback_avail(runtime); else avail = snd_pcm_capture_avail(runtime); - if (avail >= runtime->control->avail_min) + if (avail >= runtime->twake) break; } _endloop: @@ -1820,7 +1825,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, goto _end_unlock; } - runtime->twake = 1; + runtime->twake = runtime->control->avail_min ? : 1; while (size > 0) { snd_pcm_uframes_t frames, appl_ptr, appl_ofs; snd_pcm_uframes_t avail; @@ -1833,7 +1838,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, err = -EAGAIN; goto _end_unlock; } - err = wait_for_avail_min(substream, &avail); + runtime->twake = min_t(snd_pcm_uframes_t, size, + runtime->control->avail_min ? : 1); + err = wait_for_avail(substream, &avail); if (err < 0) goto _end_unlock; } @@ -2042,7 +2049,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, goto _end_unlock; } - runtime->twake = 1; + runtime->twake = runtime->control->avail_min ? : 1; while (size > 0) { snd_pcm_uframes_t frames, appl_ptr, appl_ofs; snd_pcm_uframes_t avail; @@ -2060,7 +2067,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, err = -EAGAIN; goto _end_unlock; } - err = wait_for_avail_min(substream, &avail); + runtime->twake = min_t(snd_pcm_uframes_t, size, + runtime->control->avail_min ? : 1); + err = wait_for_avail(substream, &avail); if (err < 0) goto _end_unlock; if (!avail) diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index ea2bf82c937..434af3c56d5 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c @@ -128,6 +128,14 @@ static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = { .width = 4, .phys = 4, .le = -1, .signd = -1, .silence = {}, }, + [SNDRV_PCM_FORMAT_G723_24] = { + .width = 3, .phys = 3, .le = -1, .signd = -1, + .silence = {}, + }, + [SNDRV_PCM_FORMAT_G723_40] = { + .width = 5, .phys = 5, .le = -1, .signd = -1, + .silence = {}, + }, /* FIXME: the following three formats are not defined properly yet */ [SNDRV_PCM_FORMAT_MPEG] = { .le = -1, .signd = -1, @@ -186,6 +194,14 @@ static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = { .width = 18, .phys = 24, .le = 0, .signd = 0, .silence = { 0x02, 0x00, 0x00 }, }, + [SNDRV_PCM_FORMAT_G723_24_1B] = { + .width = 3, .phys = 8, .le = -1, .signd = -1, + .silence = {}, + }, + [SNDRV_PCM_FORMAT_G723_40_1B] = { + .width = 5, .phys = 8, .le = -1, .signd = -1, + .silence = {}, + }, }; diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig index 84714a65e5c..32646000ab9 100644 --- a/sound/drivers/Kconfig +++ b/sound/drivers/Kconfig @@ -170,9 +170,25 @@ config SND_AC97_POWER_SAVE AC97 codecs. In this mode, the power-mode is dynamically controlled at each open/close. - The mode is activated by passing power_save=1 option to - snd-ac97-codec driver. You can toggle it dynamically over - sysfs, too. + The mode is activated by passing 'power_save=X' to the + snd-ac97-codec driver module, where 'X' is the time-out + value, a nonnegative integer that specifies how many + seconds of idle time the driver must count before it may + put the AC97 into power-save mode; a value of 0 (zero) + disables the use of this power-save mode. + + After the snd-ac97-codec driver module has been loaded, + the 'power_save' parameter can be set via sysfs as follows: + + echo 10 > /sys/module/snd_ac97_codec/parameters/power_save + + In this case, the time-out is set to 10 seconds; setting + the time-out to 1 second (the minimum activation value) + isn't recommended because many applications try to reopen + the device frequently. A value of 10 seconds would be a + good choice for normal operations. + + See Documentation/sound/alsa/powersave.txt for more details. config SND_AC97_POWER_SAVE_DEFAULT int "Default time-out for AC97 power-save mode" @@ -182,4 +198,6 @@ config SND_AC97_POWER_SAVE_DEFAULT The default time-out value in seconds for AC97 automatic power-save mode. 0 means to disable the power-save mode. + See SND_AC97_POWER_SAVE for more details. + endif # SND_DRIVERS diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 60b6abd7161..5f3e68401f9 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -549,7 +549,10 @@ static int __devinit snd_msnd_attach(struct snd_card *card) printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq); return err; } - request_region(chip->io, DSP_NUMIO, card->shortname); + if (request_region(chip->io, DSP_NUMIO, card->shortname) == NULL) { + free_irq(chip->irq, chip); + return -EBUSY; + } if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) { printk(KERN_ERR LOGNAME diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c index ccedbfed061..2f85c66f8e3 100644 --- a/sound/isa/sb/emu8000_pcm.c +++ b/sound/isa/sb/emu8000_pcm.c @@ -433,7 +433,8 @@ static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned sh while (count > 0) { unsigned short sval; CHECK_SCHEDULER(); - get_user(sval, buf); + if (get_user(sval, buf)) + return -EFAULT; EMU8000_SMLD_WRITE(emu, sval); buf++; count--; @@ -525,12 +526,14 @@ static int emu8k_pcm_copy(struct snd_pcm_substream *subs, while (count-- > 0) { unsigned short sval; CHECK_SCHEDULER(); - get_user(sval, buf); + if (get_user(sval, buf)) + return -EFAULT; EMU8000_SMLD_WRITE(emu, sval); buf++; if (rec->voices > 1) { CHECK_SCHEDULER(); - get_user(sval, buf); + if (get_user(sval, buf)) + return -EFAULT; EMU8000_SMRD_WRITE(emu, sval); buf++; } diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c index 24793c5b65a..4d2a6ae978f 100644 --- a/sound/oss/ad1848.c +++ b/sound/oss/ad1848.c @@ -716,7 +716,7 @@ static int ad1848_mixer_ioctl(int dev, unsigned int cmd, void __user *arg) default: if (get_user(val, (int __user *)arg)) - return -EFAULT; + return -EFAULT; val = ad1848_mixer_set(devc, cmd & 0xff, val); break; } diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c index c1070e33b32..c6f2621221b 100644 --- a/sound/oss/au1550_ac97.c +++ b/sound/oss/au1550_ac97.c @@ -43,13 +43,13 @@ #include <linux/sound.h> #include <linux/slab.h> #include <linux/soundcard.h> +#include <linux/smp_lock.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/poll.h> #include <linux/bitops.h> #include <linux/spinlock.h> -#include <linux/smp_lock.h> #include <linux/ac97_codec.h> #include <linux/mutex.h> @@ -162,19 +162,10 @@ ld2(unsigned int x) static void au1550_delay(int msec) { - unsigned long tmo; - signed long tmo2; - if (in_interrupt()) return; - tmo = jiffies + (msec * HZ) / 1000; - for (;;) { - tmo2 = tmo - jiffies; - if (tmo2 <= 0) - break; - schedule_timeout(tmo2); - } + schedule_timeout_uninterruptible(msecs_to_jiffies(msec)); } static u16 @@ -807,7 +798,9 @@ au1550_llseek(struct file *file, loff_t offset, int origin) static int au1550_open_mixdev(struct inode *inode, struct file *file) { + lock_kernel(); file->private_data = &au1550_state; + unlock_kernel(); return 0; } @@ -824,22 +817,26 @@ mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd, return codec->mixer_ioctl(codec, cmd, arg); } -static int -au1550_ioctl_mixdev(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long +au1550_ioctl_mixdev(struct file *file, unsigned int cmd, unsigned long arg) { struct au1550_state *s = (struct au1550_state *)file->private_data; struct ac97_codec *codec = s->codec; + int ret; - return mixdev_ioctl(codec, cmd, arg); + lock_kernel(); + ret = mixdev_ioctl(codec, cmd, arg); + unlock_kernel(); + + return ret; } static /*const */ struct file_operations au1550_mixer_fops = { - owner:THIS_MODULE, - llseek:au1550_llseek, - ioctl:au1550_ioctl_mixdev, - open:au1550_open_mixdev, - release:au1550_release_mixdev, + .owner = THIS_MODULE, + .llseek = au1550_llseek, + .unlocked_ioctl = au1550_ioctl_mixdev, + .open = au1550_open_mixdev, + .release = au1550_release_mixdev, }; static int @@ -1343,8 +1340,7 @@ dma_count_done(struct dmabuf *db) static int -au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +au1550_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct au1550_state *s = (struct au1550_state *)file->private_data; unsigned long flags; @@ -1780,6 +1776,17 @@ au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return mixdev_ioctl(s->codec, cmd, arg); } +static long +au1550_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret; + + lock_kernel(); + ret = au1550_ioctl(file, cmd, arg); + unlock_kernel(); + + return ret; +} static int au1550_open(struct inode *inode, struct file *file) @@ -1797,21 +1804,22 @@ au1550_open(struct inode *inode, struct file *file) #endif file->private_data = s; + lock_kernel(); /* wait for device to become free */ mutex_lock(&s->open_mutex); while (s->open_mode & file->f_mode) { - if (file->f_flags & O_NONBLOCK) { - mutex_unlock(&s->open_mutex); - return -EBUSY; - } + ret = -EBUSY; + if (file->f_flags & O_NONBLOCK) + goto out; add_wait_queue(&s->open_wait, &wait); __set_current_state(TASK_INTERRUPTIBLE); mutex_unlock(&s->open_mutex); schedule(); remove_wait_queue(&s->open_wait, &wait); set_current_state(TASK_RUNNING); + ret = -ERESTARTSYS; if (signal_pending(current)) - return -ERESTARTSYS; + goto out2; mutex_lock(&s->open_mutex); } @@ -1840,17 +1848,21 @@ au1550_open(struct inode *inode, struct file *file) if (file->f_mode & FMODE_READ) { if ((ret = prog_dmabuf_adc(s))) - return ret; + goto out; } if (file->f_mode & FMODE_WRITE) { if ((ret = prog_dmabuf_dac(s))) - return ret; + goto out; } s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); - mutex_unlock(&s->open_mutex); mutex_init(&s->sem); - return 0; + ret = 0; +out: + mutex_unlock(&s->open_mutex); +out2: + unlock_kernel(); + return ret; } static int @@ -1885,15 +1897,15 @@ au1550_release(struct inode *inode, struct file *file) } static /*const */ struct file_operations au1550_audio_fops = { - owner: THIS_MODULE, - llseek: au1550_llseek, - read: au1550_read, - write: au1550_write, - poll: au1550_poll, - ioctl: au1550_ioctl, - mmap: au1550_mmap, - open: au1550_open, - release: au1550_release, + .owner = THIS_MODULE, + .llseek = au1550_llseek, + .read = au1550_read, + .write = au1550_write, + .poll = au1550_poll, + .unlocked_ioctl = au1550_unlocked_ioctl, + .mmap = au1550_mmap, + .open = au1550_open, + .release = au1550_release, }; MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com"); diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c index 3f3c3f71db4..6ecd41abb06 100644 --- a/sound/oss/dmasound/dmasound_core.c +++ b/sound/oss/dmasound/dmasound_core.c @@ -323,9 +323,13 @@ static struct { static int mixer_open(struct inode *inode, struct file *file) { - if (!try_module_get(dmasound.mach.owner)) + lock_kernel(); + if (!try_module_get(dmasound.mach.owner)) { + unlock_kernel(); return -ENODEV; + } mixer.busy = 1; + unlock_kernel(); return 0; } @@ -337,8 +341,8 @@ static int mixer_release(struct inode *inode, struct file *file) unlock_kernel(); return 0; } -static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg) + +static int mixer_ioctl(struct file *file, u_int cmd, u_long arg) { if (_SIOC_DIR(cmd) & _SIOC_WRITE) mixer.modify_counter++; @@ -362,11 +366,22 @@ st |