diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-10-26 23:51:43 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-10-26 23:51:43 +0200 |
commit | d22665702226e9c40bc331098559e3d55e7cd43d (patch) | |
tree | 6e92734c9835dc9e064b20182624939f3486d28d /sound | |
parent | 5cdf745ebae0f5bcf9b798d8fd5cb57add592cc1 (diff) | |
parent | dde7ad8dee274763c8958769779aea8c993c950e (diff) |
Merge branch 'topic/misc' into for-linus
Diffstat (limited to 'sound')
80 files changed, 1983 insertions, 1558 deletions
diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index 3687a6cc988..762af68c899 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/core/control.c b/sound/core/control.c index f8c5be46451..978fe1a8e9f 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -989,7 +989,6 @@ struct user_element { void *tlv_data; /* TLV data */ unsigned long tlv_data_size; /* TLV data size */ void *priv_data; /* private data (like strings for enumerated type) */ - unsigned long priv_data_size; /* size of private data in bytes */ }; static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol, @@ -1001,6 +1000,28 @@ static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol, return 0; } +static int snd_ctl_elem_user_enum_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct user_element *ue = kcontrol->private_data; + const char *names; + unsigned int item; + + item = uinfo->value.enumerated.item; + + *uinfo = ue->info; + + item = min(item, uinfo->value.enumerated.items - 1); + uinfo->value.enumerated.item = item; + + names = ue->priv_data; + for (; item > 0; --item) + names += strlen(names) + 1; + strcpy(uinfo->value.enumerated.name, names); + + return 0; +} + static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1055,11 +1076,46 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol, return change; } +static int snd_ctl_elem_init_enum_names(struct user_element *ue) +{ + char *names, *p; + size_t buf_len, name_len; + unsigned int i; + + if (ue->info.value.enumerated.names_length > 64 * 1024) + return -EINVAL; + + names = memdup_user( + (const void __user *)ue->info.value.enumerated.names_ptr, + ue->info.value.enumerated.names_length); + if (IS_ERR(names)) + return PTR_ERR(names); + + /* check that there are enough valid names */ + buf_len = ue->info.value.enumerated.names_length; + p = names; + for (i = 0; i < ue->info.value.enumerated.items; ++i) { + name_len = strnlen(p, buf_len); + if (name_len == 0 || name_len >= 64 || name_len == buf_len) { + kfree(names); + return -EINVAL; + } + p += name_len + 1; + buf_len -= name_len + 1; + } + + ue->priv_data = names; + ue->info.value.enumerated.names_ptr = 0; + + return 0; +} + static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol) { struct user_element *ue = kcontrol->private_data; - if (ue->tlv_data) - kfree(ue->tlv_data); + + kfree(ue->tlv_data); + kfree(ue->priv_data); kfree(ue); } @@ -1072,8 +1128,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; @@ -1101,7 +1157,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, memcpy(&kctl.id, &info->id, sizeof(info->id)); kctl.count = info->owner ? info->owner : 1; access |= SNDRV_CTL_ELEM_ACCESS_USER; - kctl.info = snd_ctl_elem_user_info; + if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) + kctl.info = snd_ctl_elem_user_enum_info; + else + kctl.info = snd_ctl_elem_user_info; if (access & SNDRV_CTL_ELEM_ACCESS_READ) kctl.get = snd_ctl_elem_user_get; if (access & SNDRV_CTL_ELEM_ACCESS_WRITE) @@ -1122,6 +1181,11 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, if (info->count > 64) return -EINVAL; break; + case SNDRV_CTL_ELEM_TYPE_ENUMERATED: + private_size = sizeof(unsigned int); + if (info->count > 128 || info->value.enumerated.items == 0) + return -EINVAL; + break; case SNDRV_CTL_ELEM_TYPE_BYTES: private_size = sizeof(unsigned char); if (info->count > 512) @@ -1143,9 +1207,17 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, ue->info.access = 0; ue->elem_data = (char *)ue + sizeof(*ue); ue->elem_data_size = private_size; + if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) { + err = snd_ctl_elem_init_enum_names(ue); + if (err < 0) { + kfree(ue); + return err; + } + } kctl.private_free = snd_ctl_elem_user_free; _kctl = snd_ctl_new(&kctl, access); if (_kctl == NULL) { + kfree(ue->priv_data); kfree(ue); return -ENOMEM; } diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 426874429a5..2bb95a7a880 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -83,6 +83,8 @@ struct snd_ctl_elem_info32 { u32 items; u32 item; char name[64]; + u64 names_ptr; + u32 names_length; } enumerated; unsigned char reserved[128]; } value; @@ -372,6 +374,8 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, &data32->value.enumerated, sizeof(data->value.enumerated))) goto error; + data->value.enumerated.names_ptr = + (uintptr_t)compat_ptr(data->value.enumerated.names_ptr); break; default: break; diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index d8359cfeca1..1b5e0c49a0a 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -499,7 +499,7 @@ static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, c memset(&id, 0, sizeof(id)); id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(id.name, name); + strlcpy(id.name, name, sizeof(id.name)); id.index = index; return snd_ctl_find_id(card, &id); } diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 62e90b862a0..95d1e789715 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) { diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index b4bf4a4d94a..77d7df22e7c 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2058,16 +2058,12 @@ EXPORT_SYMBOL(snd_pcm_open_substream); static int snd_pcm_open_file(struct file *file, struct snd_pcm *pcm, - int stream, - struct snd_pcm_file **rpcm_file) + int stream) { struct snd_pcm_file *pcm_file; struct snd_pcm_substream *substream; int err; - if (rpcm_file) - *rpcm_file = NULL; - err = snd_pcm_open_substream(pcm, stream, file, &substream); if (err < 0) return err; @@ -2083,8 +2079,7 @@ static int snd_pcm_open_file(struct file *file, substream->pcm_release = pcm_release_private; } file->private_data = pcm_file; - if (rpcm_file) - *rpcm_file = pcm_file; + return 0; } @@ -2113,7 +2108,6 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) { int err; - struct snd_pcm_file *pcm_file; wait_queue_t wait; if (pcm == NULL) { @@ -2131,7 +2125,7 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) add_wait_queue(&pcm->open_wait, &wait); mutex_lock(&pcm->open_mutex); while (1) { - err = snd_pcm_open_file(file, pcm, stream, &pcm_file); + err = snd_pcm_open_file(file, pcm, stream); if (err >= 0) break; if (err == -EAGAIN) { diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index a0da7755fce..4067f154894 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -575,7 +575,8 @@ static void loopback_runtime_free(struct snd_pcm_runtime *runtime) static int loopback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); + return snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(params)); } static int loopback_hw_free(struct snd_pcm_substream *substream) @@ -587,7 +588,7 @@ static int loopback_hw_free(struct snd_pcm_substream *substream) mutex_lock(&dpcm->loopback->cable_lock); cable->valid &= ~(1 << substream->stream); mutex_unlock(&dpcm->loopback->cable_lock); - return snd_pcm_lib_free_pages(substream); + return snd_pcm_lib_free_vmalloc_buffer(substream); } static unsigned int get_cable_index(struct snd_pcm_substream *substream) @@ -740,6 +741,8 @@ static struct snd_pcm_ops loopback_playback_ops = { .prepare = loopback_prepare, .trigger = loopback_trigger, .pointer = loopback_pointer, + .page = snd_pcm_lib_get_vmalloc_page, + .mmap = snd_pcm_lib_mmap_vmalloc, }; static struct snd_pcm_ops loopback_capture_ops = { @@ -751,6 +754,8 @@ static struct snd_pcm_ops loopback_capture_ops = { .prepare = loopback_prepare, .trigger = loopback_trigger, .pointer = loopback_pointer, + .page = snd_pcm_lib_get_vmalloc_page, + .mmap = snd_pcm_lib_mmap_vmalloc, }; static int __devinit loopback_pcm_new(struct loopback *loopback, @@ -771,10 +776,6 @@ static int __devinit loopback_pcm_new(struct loopback *loopback, strcpy(pcm->name, "Loopback PCM"); loopback->pcm[device] = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 0, 2 * 1024 * 1024); return 0; } diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 149d05a8202..1c02852acee 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 2af09996a3d..9d01c181fec 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 440030818db..cd094ecaca3 100644 --- a/sound/fi |