diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-12-04 16:22:32 +0100 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-12-04 16:22:32 +0100 |
commit | 79598324838a25cc378ecbb8c29dd1e3d3951d35 (patch) | |
tree | 7d29e81580cba854042df4e33bdc8f38bbd65d03 /sound | |
parent | 8ee763b9c82c6ca0a59a7271ce4fa29d7baf5c09 (diff) | |
parent | b00615d163cd24fa98d155acfc1f9d81d6fe1103 (diff) |
Merge branch 'topic/core-change' into for-linus
Diffstat (limited to 'sound')
49 files changed, 1163 insertions, 2260 deletions
diff --git a/sound/arm/Makefile b/sound/arm/Makefile index 5a549ed6c8a..8c0c851d464 100644 --- a/sound/arm/Makefile +++ b/sound/arm/Makefile @@ -3,7 +3,7 @@ # obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o -snd-aaci-objs := aaci.o devdma.o +snd-aaci-objs := aaci.o obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o snd-pxa2xx-pcm-objs := pxa2xx-pcm.o diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 6c160a038b2..1534f3d88bc 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -30,7 +30,6 @@ #include <sound/pcm_params.h> #include "aaci.h" -#include "devdma.h" #define DRIVER_NAME "aaci-pl041" @@ -492,7 +491,7 @@ static int aaci_pcm_hw_free(struct snd_pcm_substream *substream) /* * Clear out the DMA and any allocated buffers. */ - devdma_hw_free(NULL, substream); + snd_pcm_lib_free_pages(substream); return 0; } @@ -509,8 +508,8 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, aacirun->pcm_open = 0; } - err = devdma_hw_alloc(NULL, substream, - params_buffer_bytes(params)); + err = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(params)); if (err < 0) goto out; @@ -555,11 +554,6 @@ static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream) return bytes_to_frames(runtime, bytes); } -static int aaci_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma) -{ - return devdma_mmap(NULL, substream, vma); -} - /* * Playback specific ALSA stuff @@ -726,7 +720,6 @@ static struct snd_pcm_ops aaci_playback_ops = { .prepare = aaci_pcm_prepare, .trigger = aaci_pcm_playback_trigger, .pointer = aaci_pcm_pointer, - .mmap = aaci_pcm_mmap, }; static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream, @@ -854,7 +847,6 @@ static struct snd_pcm_ops aaci_capture_ops = { .prepare = aaci_pcm_capture_prepare, .trigger = aaci_pcm_capture_trigger, .pointer = aaci_pcm_pointer, - .mmap = aaci_pcm_mmap, }; /* @@ -1044,6 +1036,8 @@ static int __devinit aaci_init_pcm(struct aaci *aaci) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops); + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, + NULL, 0, 64 * 104); } return ret; diff --git a/sound/arm/devdma.c b/sound/arm/devdma.c deleted file mode 100644 index 9d1e6665b54..00000000000 --- a/sound/arm/devdma.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * linux/sound/arm/devdma.c - * - * Copyright (C) 2003-2004 Russell King, All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * ARM DMA shim for ALSA. - */ -#include <linux/device.h> -#include <linux/dma-mapping.h> - -#include <sound/core.h> -#include <sound/pcm.h> - -#include "devdma.h" - -void devdma_hw_free(struct device *dev, struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_dma_buffer *buf = runtime->dma_buffer_p; - - if (runtime->dma_area == NULL) - return; - - if (buf != &substream->dma_buffer) { - dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, buf->addr); - kfree(runtime->dma_buffer_p); - } - - snd_pcm_set_runtime_buffer(substream, NULL); -} - -int devdma_hw_alloc(struct device *dev, struct snd_pcm_substream *substream, size_t size) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_dma_buffer *buf = runtime->dma_buffer_p; - int ret = 0; - - if (buf) { - if (buf->bytes >= size) - goto out; - devdma_hw_free(dev, substream); - } - - if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) { - buf = &substream->dma_buffer; - } else { - buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL); - if (!buf) - goto nomem; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = dev; - buf->area = dma_alloc_coherent(dev, size, &buf->addr, GFP_KERNEL); - buf->bytes = size; - buf->private_data = NULL; - - if (!buf->area) - goto free; - } - snd_pcm_set_runtime_buffer(substream, buf); - ret = 1; - out: - runtime->dma_bytes = size; - return ret; - - free: - kfree(buf); - nomem: - return -ENOMEM; -} - -int devdma_mmap(struct device *dev, struct snd_pcm_substream *substream, struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - return dma_mmap_coherent(dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); -} diff --git a/sound/arm/devdma.h b/sound/arm/devdma.h deleted file mode 100644 index d025329c8a0..00000000000 --- a/sound/arm/devdma.h +++ /dev/null @@ -1,3 +0,0 @@ -void devdma_hw_free(struct device *dev, struct snd_pcm_substream *substream); -int devdma_hw_alloc(struct device *dev, struct snd_pcm_substream *substream, size_t size); -int devdma_mmap(struct device *dev, struct snd_pcm_substream *substream, struct vm_area_struct *vma); diff --git a/sound/core/control.c b/sound/core/control.c index a8b7fabe645..73dc10ac33f 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -75,7 +75,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file) ctl->card = card; ctl->prefer_pcm_subdevice = -1; ctl->prefer_rawmidi_subdevice = -1; - ctl->pid = current->pid; + ctl->pid = get_pid(task_pid(current)); file->private_data = ctl; write_lock_irqsave(&card->ctl_files_rwlock, flags); list_add_tail(&ctl->list, &card->ctl_files); @@ -125,6 +125,7 @@ static int snd_ctl_release(struct inode *inode, struct file *file) control->vd[idx].owner = NULL; up_write(&card->controls_rwsem); snd_ctl_empty_read_queue(ctl); + put_pid(ctl->pid); kfree(ctl); module_put(card->module); snd_card_file_remove(card, file); @@ -672,7 +673,7 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl, info->access |= SNDRV_CTL_ELEM_ACCESS_LOCK; if (vd->owner == ctl) info->access |= SNDRV_CTL_ELEM_ACCESS_OWNER; - info->owner = vd->owner_pid; + info->owner = pid_vnr(vd->owner->pid); } else { info->owner = -1; } @@ -827,7 +828,6 @@ static int snd_ctl_elem_lock(struct snd_ctl_file *file, result = -EBUSY; else { vd->owner = file; - vd->owner_pid = current->pid; result = 0; } } @@ -858,7 +858,6 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file, result = -EPERM; else { vd->owner = NULL; - vd->owner_pid = 0; result = 0; } } diff --git a/sound/core/isadma.c b/sound/core/isadma.c index 79f0f16af33..950e19ba91f 100644 --- a/sound/core/isadma.c +++ b/sound/core/isadma.c @@ -85,16 +85,24 @@ EXPORT_SYMBOL(snd_dma_disable); unsigned int snd_dma_pointer(unsigned long dma, unsigned int size) { unsigned long flags; - unsigned int result; + unsigned int result, result1; flags = claim_dma_lock(); clear_dma_ff(dma); if (!isa_dma_bridge_buggy) disable_dma(dma); result = get_dma_residue(dma); + /* + * HACK - read the counter again and choose higher value in order to + * avoid reading during counter lower byte roll over if the + * isa_dma_bridge_buggy is set. + */ + result1 = get_dma_residue(dma); if (!isa_dma_bridge_buggy) enable_dma(dma); release_dma_lock(flags); + if (unlikely(result < result1)) + result = result1; #ifdef CONFIG_SND_DEBUG if (result > size) snd_printk(KERN_ERR "pointer (0x%x) for DMA #%ld is greater than transfer size (0x%x)\n", result, dma, size); diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 772423889eb..54e2eb56e4c 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -1251,7 +1251,9 @@ static void snd_mixer_oss_build(struct snd_mixer_oss *mixer) { SOUND_MIXER_SYNTH, "FM", 0 }, /* fallback */ { SOUND_MIXER_SYNTH, "Music", 0 }, /* fallback */ { SOUND_MIXER_PCM, "PCM", 0 }, - { SOUND_MIXER_SPEAKER, "PC Speaker", 0 }, + { SOUND_MIXER_SPEAKER, "Beep", 0 }, + { SOUND_MIXER_SPEAKER, "PC Speaker", 0 }, /* fallback */ + { SOUND_MIXER_SPEAKER, "Speaker", 0 }, /* fallback */ { SOUND_MIXER_LINE, "Line", 0 }, { SOUND_MIXER_MIC, "Mic", 0 }, { SOUND_MIXER_CD, "CD", 0 }, diff --git a/sound/core/pcm.c b/sound/core/pcm.c index c69c60b2a48..6884ae031f6 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -435,6 +435,7 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, return; } snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state)); + snd_iprintf(buffer, "owner_pid : %d\n", pid_vnr(substream->pid)); snd_iprintf(buffer, "trigger_time: %ld.%09ld\n", status.trigger_tstamp.tv_sec, status.trigger_tstamp.tv_nsec); snd_iprintf(buffer, "tstamp : %ld.%09ld\n", @@ -809,7 +810,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, card = pcm->card; read_lock(&card->ctl_files_rwlock); list_for_each_entry(kctl, &card->ctl_files, list) { - if (kctl->pid == current->pid) { + if (kctl->pid == task_pid(current)) { prefer_subdevice = kctl->prefer_pcm_subdevice; if (prefer_subdevice != -1) break; @@ -900,6 +901,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, substream->private_data = pcm->private_data; substream->ref_count = 1; substream->f_flags = file->f_flags; + substream->pid = get_pid(task_pid(current)); pstr->substream_opened++; *rsubstream = substream; return 0; @@ -921,6 +923,8 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) kfree(runtime->hw_constraints.rules); kfree(runtime); substream->runtime = NULL; + put_pid(substream->pid); + substream->pid = NULL; substream->pstr->substream_opened--; } diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index ab73edf2c89..29ab46a12e1 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -26,6 +26,7 @@ #include <linux/time.h> #include <linux/pm_qos_params.h> #include <linux/uio.h> +#include <linux/dma-mapping.h> #include <sound/core.h> #include <sound/control.h> #include <sound/info.h> @@ -3061,6 +3062,27 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file } #endif /* coherent mmap */ +static inline struct page * +snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs) +{ + void *vaddr = substream->runtime->dma_area + ofs; +#if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT) + if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) + return virt_to_page(CAC_ADDR(vaddr)); +#endif +#if defined(CONFIG_PPC32) && defined(CONFIG_NOT_COHERENT_CACHE) + if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) { + dma_addr_t addr = substream->runtime->dma_addr + ofs; + addr -= get_dma_offset(substream->dma_buffer.dev.dev); + /* assume dma_handle set via pfn_to_phys() in + * mm/dma-noncoherent.c + */ + return pfn_to_page(addr >> PAGE_SHIFT); + } +#endif + return virt_to_page(vaddr); +} + /* * fault callback for mmapping a RAM page */ @@ -3071,7 +3093,6 @@ static int snd_pcm_mmap_data_fault(struct vm_area_struct *area, struct snd_pcm_runtime *runtime; unsigned long offset; struct page * page; - void *vaddr; size_t dma_bytes; if (substream == NULL) @@ -3081,36 +3102,53 @@ static int snd_pcm_mmap_data_fault(struct vm_area_struct *area, dma_bytes = PAGE_ALIGN(runtime->dma_bytes); if (offset > dma_bytes - PAGE_SIZE) return VM_FAULT_SIGBUS; - if (substream->ops->page) { + if (substream->ops->page) page = substream->ops->page(substream, offset); - if (!page) - return VM_FAULT_SIGBUS; - } else { - vaddr = runtime->dma_area + offset; - page = virt_to_page(vaddr); - } + else + page = snd_pcm_default_page_ops(substream, offset); + if (!page) + return VM_FAULT_SIGBUS; get_page(page); vmf->page = page; return 0; } -static const struct vm_operations_struct snd_pcm_vm_ops_data = -{ +static const struct vm_operations_struct snd_pcm_vm_ops_data = { + .open = snd_pcm_mmap_data_open, + .close = snd_pcm_mmap_data_close, +}; + +static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = { .open = snd_pcm_mmap_data_open, .close = snd_pcm_mmap_data_close, .fault = snd_pcm_mmap_data_fault, }; +#ifndef ARCH_HAS_DMA_MMAP_COHERENT +/* This should be defined / handled globally! */ +#ifdef CONFIG_ARM +#define ARCH_HAS_DMA_MMAP_COHERENT +#endif +#endif + /* * mmap the DMA buffer on RAM */ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *area) { - area->vm_ops = &snd_pcm_vm_ops_data; - area->vm_private_data = substream; area->vm_flags |= VM_RESERVED; - atomic_inc(&substream->mmap_count); +#ifdef ARCH_HAS_DMA_MMAP_COHERENT + if (!substream->ops->page && + substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) + return dma_mmap_coherent(substream->dma_buffer.dev.dev, + area, + substream->runtime->dma_area, + substream->runtime->dma_addr, + area->vm_end - area->vm_start); +#endif /* ARCH_HAS_DMA_MMAP_COHERENT */ + /* mmap with fault handler */ + area->vm_ops = &snd_pcm_vm_ops_data_fault; return 0; } @@ -3118,12 +3156,6 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, * mmap the DMA buffer on I/O memory area */ #if SNDRV_PCM_INFO_MMAP_IOMEM -static const struct vm_operations_struct snd_pcm_vm_ops_data_mmio = -{ - .open = snd_pcm_mmap_data_open, - .close = snd_pcm_mmap_data_close, -}; - int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_struct *area) { @@ -3133,8 +3165,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, #ifdef pgprot_noncached area->vm_page_prot = pgprot_noncached(area->vm_page_prot); #endif - area->vm_ops = &snd_pcm_vm_ops_data_mmio; - area->vm_private_data = substream; area->vm_flags |= VM_IO; size = area->vm_end - area->vm_start; offset = area->vm_pgoff << PAGE_SHIFT; @@ -3142,7 +3172,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, size, area->vm_page_prot)) return -EAGAIN; - atomic_inc(&substream->mmap_count); return 0; } @@ -3159,6 +3188,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, long size; unsigned long offset; size_t dma_bytes; + int err; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (!(area->vm_flags & (VM_WRITE|VM_READ))) @@ -3183,10 +3213,15 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, if (offset > dma_bytes - size) return -EINVAL; + area->vm_ops = &snd_pcm_vm_ops_data; + area->vm_private_data = substream; if (substream->ops->mmap) - return substream->ops->mmap(substream, area); + err = substream->ops->mmap(substream, area); else - return snd_pcm_default_mmap(substream, area); + err = snd_pcm_default_mmap(substream, area); + if (!err) + atomic_inc(&substream->mmap_count); + return err; } EXPORT_SYMBOL(snd_pcm_mmap_data); diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 70d6f25ba52..2f766123b15 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -242,8 +242,6 @@ static int assign_substream(struct snd_rawmidi *rmidi, int subdevice, return -ENXIO; if (subdevice >= 0 && subdevice >= s->substream_count) return -ENODEV; - if (s->substream_opened >= s->substream_count) - return -EAGAIN; list_for_each_entry(substream, &s->substreams, list) { if (substream->opened) { @@ -280,9 +278,10 @@ static int open_substream(struct snd_rawmidi *rmidi, substream->active_sensing = 0; if (mode & SNDRV_RAWMIDI_LFLG_APPEND) substream->append = 1; + substream->pid = get_pid(task_pid(current)); + rmidi->streams[substream->stream].substream_opened++; } substream->use_count++; - rmidi->streams[substream->stream].substream_opened++; return 0; } @@ -413,7 +412,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) subdevice = -1; read_lock(&card->ctl_files_rwlock); list_for_each_entry(kctl, &card->ctl_files, list) { - if (kctl->pid == current->pid) { + if (kctl->pid == task_pid(current)) { subdevice = kctl->prefer_rawmidi_subdevice; if (subdevice != -1) break; @@ -466,7 +465,6 @@ static void close_substream(struct snd_rawmidi *rmidi, struct snd_rawmidi_substream *substream, int cleanup) { - rmidi->streams[substream->stream].substream_opened--; if (--substream->use_count) return; @@ -491,6 +489,9 @@ static void close_substream(struct snd_rawmidi *rmidi, snd_rawmidi_runtime_free(substream); substream->opened = 0; substream->append = 0; + put_pid(substream->pid); + substream->pid = NULL; + rmidi->streams[substream->stream].substream_opened--; } static void rawmidi_release_priv(struct snd_rawmidi_file *rfile) @@ -1338,6 +1339,9 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, substream->number, (unsigned long) substream->bytes); if (substream->opened) { + snd_iprintf(buffer, + " Owner PID : %d\n", + pid_vnr(substream->pid)); runtime = substream->runtime; snd_iprintf(buffer, " Mode : %s\n" @@ -1359,6 +1363,9 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, substream->number, (unsigned long) substream->bytes); if (substream->opened) { + snd_iprintf(buffer, + " Owner PID : %d\n", + pid_vnr(substream->pid)); runtime = substream->runtime; snd_iprintf(buffer, " Buffer size : %lu\n" diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index b60cef257b5..f165c77d627 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c @@ -26,6 +26,7 @@ MODULE_ALIAS("platform:pcspkr"); static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ static int enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */ +static int nopcm; /* Disable PCM capability of the driver */ module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for pcsp soundcard."); @@ -33,6 +34,8 @@ module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for pcsp soundcard."); module_param(enable, bool, 0444); MODULE_PARM_DESC(enable, "Enable PC-Speaker sound."); +module_param(nopcm, bool, 0444); +MODULE_PARM_DESC(nopcm, "Disable PC-Speaker PCM sound. Only beeps remain."); struct snd_pcsp pcsp_chip; @@ -43,13 +46,16 @@ static int __devinit snd_pcsp_create(struct snd_card *card) int err; int div, min_div, order; - hrtimer_get_res(CLOCK_MONOTONIC, &tp); - if (tp.tv_sec || tp.tv_nsec > PCSP_MAX_PERIOD_NS) { - printk(KERN_ERR "PCSP: Timer resolution is not sufficient " - "(%linS)\n", tp.tv_nsec); - printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI " - "enabled.\n"); - return -EIO; + if (!nopcm) { + hrtimer_get_res(CLOCK_MONOTONIC, &tp); + if (tp.tv_sec || tp.tv_nsec > PCSP_MAX_PERIOD_NS) { + printk(KERN_ERR "PCSP: Timer resolution is not sufficient " + "(%linS)\n", tp.tv_nsec); + printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI " + "enabled.\n"); + printk(KERN_ERR "PCSP: Turned into nopcm mode.\n"); + nopcm = 1; + } } if (loops_per_jiffy >= PCSP_MIN_LPJ && tp.tv_nsec <= PCSP_MIN_PERIOD_NS) @@ -107,12 +113,14 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) snd_card_free(card); return err; } - err = snd_pcsp_new_pcm(&pcsp_chip); - if (err < 0) { - snd_card_free(card); - return err; + if (!nopcm) { + err = snd_pcsp_new_pcm(&pcsp_chip); + if (err < 0) { + snd_card_free(card); + return err; + } } - err = snd_pcsp_new_mixer(&pcsp_chip); + err = snd_pcsp_new_mixer(&pcsp_chip, nopcm); if (err < 0) { snd_card_free(card); return err; diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h index 174dd2ff0f2..1e123077923 100644 --- a/sound/drivers/pcsp/pcsp.h +++ b/sound/drivers/pcsp/pcsp.h @@ -83,6 +83,6 @@ extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle); extern void pcsp_sync_stop(struct snd_pcsp *chip); extern int snd_pcsp_new_pcm(struct snd_pcsp *chip); -extern int snd_pcsp_new_mixer(struct snd_pcsp *chip); +extern int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm); #endif diff --git a/sound/drivers/pcsp/pcsp_mixer.c b/sound/drivers/pcsp/pcsp_mixer.c index 903bc846763..6f633f4f3b9 100644 --- a/sound/drivers/pcsp/pcsp_mixer.c +++ b/sound/drivers/pcsp/pcsp_mixer.c @@ -119,24 +119,43 @@ static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol, .put = pcsp_##ctl_type##_put, \ } -static struct snd_kcontrol_new __devinitdata snd_pcsp_controls[] = { +static struct snd_kcontrol_new __devinitdata snd_pcsp_controls_pcm[] = { PCSP_MIXER_CONTROL(enable, "Master Playback Switch"), PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"), - PCSP_MIXER_CONTROL(pcspkr, "PC Speaker Playback Switch"), }; -int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip) +static struct snd_kcontrol_new __devinitdata snd_pcsp_controls_spkr[] = { + PCSP_MIXER_CONTROL(pcspkr, "Beep Playback Switch"), +}; + +static int __devinit snd_pcsp_ctls_add(struct snd_pcsp *chip, + struct snd_kcontrol_new *ctls, int num) { - struct snd_card *card = chip->card; int i, err; + struct snd_card *card = chip->card; + for (i = 0; i < num; i++) { + err = snd_ctl_add(card, snd_ctl_new1(ctls + i, chip)); + if (err < 0) + return err; + } + return 0; +} + +int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm) +{ + int err; + struct snd_card *card = chip->card; - for (i = 0; i < ARRAY_SIZE(snd_pcsp_controls); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(snd_pcsp_controls + i, - chip)); + if (!nopcm) { + err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_pcm, + ARRAY_SI |