Commit 1ff07d33 authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA update 0.9.4

  - added drivers for Digigram VXPocket V2, VXPocket 440 (pcmcia)
  - added driver for Digigram VXP220 V2/Mic (PCI)
  - added driver Harmony chipset (parisc)
  - added OPL4 driver
  - code cleanups - removed 2.2 and 2.4 code
  - nm256 driver - added Dell Latitude LS workaround
  - ac97 driver - fixes in intialization
  - usb audio driver - strlcat() fixes
parent 52a414a7
...@@ -994,6 +994,53 @@ Module parameters ...@@ -994,6 +994,53 @@ Module parameters
Module supports up to 8 cards. Module supports up to 8 cards.
Module snd-vx222
----------------
Module for Digigram VX-Pocket VX222, V222 v2 and Mic cards.
mic - Enable Microphone on V222 Mic (NYI)
Module supports up to 8 cards.
For loading the firmware, use vxloader utility in alsa-tools
package. You can load the firmware automatically by adding
the following to /etc/modules.conf
post-install snd-vx222 "/usr/bin/vxload"
Module snd-vxpocket
-------------------
Module for Digigram VX-Pocket VX2 PCMCIA card.
irq_mask - IRQ bitmask, specifies the available IRQs as bits
Module supports up to 8 cards. The module is compiled only when
PCMCIA is supported on kernel.
To activate the driver via the card manager, you'll need to set
up /etc/pcmcia/vxpocket.conf. See the sound/pcmcia/vx/vxpocket.c.
For loading the firmware, use vxloader utility in alsa-tools
package.
Module snd-vxp440
-----------------
Module for Digigram VX-Pocket 440 PCMCIA card.
irq_mask - IRQ bitmask, specifies the available IRQs as bits
Module supports up to 8 cards. The module is compiled only when
PCMCIA is supported on kernel.
To activate the driver via the card manager, you'll need to set
up /etc/pcmcia/vxp440.conf. See the sound/pcmcia/vx/vxp440.c.
For loading the firmware, use vxloader utility in alsa-tools
package.
Module snd-ymfpci Module snd-ymfpci
----------------- -----------------
......
#ifndef __SOUND_OPL4_H
#define __SOUND_OPL4_H
/*
* Global definitions for the OPL4 driver
* Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
*
* 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 <sound/opl3.h>
typedef struct opl4 opl4_t;
extern int snd_opl4_create(snd_card_t *card,
unsigned long fm_port, unsigned long pcm_port,
int seq_device,
opl3_t **opl3, opl4_t **opl4);
#endif /* __SOUND_OPL4_H */
...@@ -193,6 +193,9 @@ static inline int _snd_magic_bad(void *obj, unsigned long magic) ...@@ -193,6 +193,9 @@ static inline int _snd_magic_bad(void *obj, unsigned long magic)
#define snd_usb_midi_in_endpoint_t_magic 0xa15a3f03 #define snd_usb_midi_in_endpoint_t_magic 0xa15a3f03
#define ak4117_t_magic 0xa15a4000 #define ak4117_t_magic 0xa15a4000
#define psic_t_magic 0xa15a4100 #define psic_t_magic 0xa15a4100
#define opl4_t_magic 0xa15a2602
#define vx_core_t_magic 0xa15a4110
#define vx_pipe_t_magic 0xa15a4112
#else #else
......
/* include/version.h. Generated by configure. */ /* include/version.h. Generated by configure. */
#define CONFIG_SND_VERSION "0.9.3c" #define CONFIG_SND_VERSION "0.9.4"
#define CONFIG_SND_DATE " (Wed May 21 16:40:34 2003 UTC)" #define CONFIG_SND_DATE " (Sat May 31 13:37:06 2003 UTC)"
This diff is collapsed.
...@@ -24,8 +24,14 @@ source "sound/arm/Kconfig" ...@@ -24,8 +24,14 @@ source "sound/arm/Kconfig"
# here assuming USB is defined before ALSA # here assuming USB is defined before ALSA
source "sound/usb/Kconfig" source "sound/usb/Kconfig"
# the following will depenend on the order of config.
# here assuming PCMCIA is defined before ALSA
source "sound/pcmcia/Kconfig"
source "sound/sparc/Kconfig" source "sound/sparc/Kconfig"
source "sound/parisc/Kconfig"
endmenu endmenu
menu "Open Sound System" menu "Open Sound System"
......
...@@ -3,8 +3,7 @@ ...@@ -3,8 +3,7 @@
obj-$(CONFIG_SOUND) += soundcore.o obj-$(CONFIG_SOUND) += soundcore.o
obj-$(CONFIG_SOUND_PRIME) += oss/ obj-$(CONFIG_SOUND_PRIME) += oss/
obj-$(CONFIG_DMASOUND) += oss/ obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/
obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/
ifeq ($(CONFIG_SND),y) ifeq ($(CONFIG_SND),y)
obj-y += last.o obj-y += last.o
......
...@@ -103,5 +103,11 @@ ifeq ($(CONFIG_SND_SB16_CSP),y) ...@@ -103,5 +103,11 @@ ifeq ($(CONFIG_SND_SB16_CSP),y)
obj-$(CONFIG_SND_SBAWE) += snd-hwdep.o obj-$(CONFIG_SND_SBAWE) += snd-hwdep.o
endif endif
obj-$(CONFIG_SND_USB_AUDIO) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o obj-$(CONFIG_SND_USB_AUDIO) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-rawmidi.o
obj-$(CONFIG_SND_SUN_AMD7930) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
obj-$(CONFIG_SND_SUN_CS4231) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
obj-$(CONFIG_SND_HARMONY) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o
obj-$(CONFIG_SND_VXPOCKET) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-hwdep.o
obj-$(CONFIG_SND_VXP440) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-hwdep.o
obj-$(CONFIG_SND_VX222) += snd-pcm.o snd-timer.o snd-page-alloc.o snd.o snd-hwdep.o
obj-m := $(sort $(obj-m)) obj-m := $(sort $(obj-m))
...@@ -927,9 +927,7 @@ static int snd_ctl_fasync(int fd, struct file * file, int on) ...@@ -927,9 +927,7 @@ static int snd_ctl_fasync(int fd, struct file * file, int on)
static struct file_operations snd_ctl_f_ops = static struct file_operations snd_ctl_f_ops =
{ {
#ifndef LINUX_2_2
.owner = THIS_MODULE, .owner = THIS_MODULE,
#endif
.read = snd_ctl_read, .read = snd_ctl_read,
.open = snd_ctl_open, .open = snd_ctl_open,
.release = snd_ctl_release, .release = snd_ctl_release,
......
...@@ -292,9 +292,7 @@ static int snd_hwdep_control_ioctl(snd_card_t * card, snd_ctl_file_t * control, ...@@ -292,9 +292,7 @@ static int snd_hwdep_control_ioctl(snd_card_t * card, snd_ctl_file_t * control,
static struct file_operations snd_hwdep_f_ops = static struct file_operations snd_hwdep_f_ops =
{ {
#ifndef LINUX_2_2
.owner = THIS_MODULE, .owner = THIS_MODULE,
#endif
.llseek = snd_hwdep_llseek, .llseek = snd_hwdep_llseek,
.read = snd_hwdep_read, .read = snd_hwdep_read,
.write = snd_hwdep_write, .write = snd_hwdep_write,
......
...@@ -121,7 +121,6 @@ snd_info_entry_t *snd_seq_root = NULL; ...@@ -121,7 +121,6 @@ snd_info_entry_t *snd_seq_root = NULL;
snd_info_entry_t *snd_oss_root = NULL; snd_info_entry_t *snd_oss_root = NULL;
#endif #endif
#ifndef LINUX_2_2
static inline void snd_info_entry_prepare(struct proc_dir_entry *de) static inline void snd_info_entry_prepare(struct proc_dir_entry *de)
{ {
de->owner = THIS_MODULE; de->owner = THIS_MODULE;
...@@ -133,7 +132,6 @@ void snd_remove_proc_entry(struct proc_dir_entry *parent, ...@@ -133,7 +132,6 @@ void snd_remove_proc_entry(struct proc_dir_entry *parent,
if (de) if (de)
remove_proc_entry(de->name, parent); remove_proc_entry(de->name, parent);
} }
#endif
static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig) static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
{ {
...@@ -143,9 +141,7 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig) ...@@ -143,9 +141,7 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO); data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
entry = data->entry; entry = data->entry;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 3)
lock_kernel(); lock_kernel();
#endif
switch (entry->content) { switch (entry->content) {
case SNDRV_INFO_CONTENT_TEXT: case SNDRV_INFO_CONTENT_TEXT:
switch (orig) { switch (orig) {
...@@ -174,9 +170,7 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig) ...@@ -174,9 +170,7 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
} }
ret = -ENXIO; ret = -ENXIO;
out: out:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 3)
unlock_kernel(); unlock_kernel();
#endif
return ret; return ret;
} }
...@@ -495,9 +489,7 @@ static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -495,9 +489,7 @@ static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
static struct file_operations snd_info_entry_operations = static struct file_operations snd_info_entry_operations =
{ {
#ifndef LINUX_2_2
.owner = THIS_MODULE, .owner = THIS_MODULE,
#endif
.llseek = snd_info_entry_llseek, .llseek = snd_info_entry_llseek,
.read = snd_info_entry_read, .read = snd_info_entry_read,
.write = snd_info_entry_write, .write = snd_info_entry_write,
...@@ -508,13 +500,6 @@ static struct file_operations snd_info_entry_operations = ...@@ -508,13 +500,6 @@ static struct file_operations snd_info_entry_operations =
.release = snd_info_entry_release, .release = snd_info_entry_release,
}; };
#ifdef LINUX_2_2
static struct inode_operations snd_info_entry_inode_operations =
{
&snd_info_entry_operations, /* default sound info directory file-ops */
};
#endif /* LINUX_2_2 */
/** /**
* snd_create_proc_entry - create a procfs entry * snd_create_proc_entry - create a procfs entry
* @name: the name of the proc file * @name: the name of the proc file
...@@ -923,16 +908,9 @@ int snd_info_register(snd_info_entry_t * entry) ...@@ -923,16 +908,9 @@ int snd_info_register(snd_info_entry_t * entry)
up(&info_mutex); up(&info_mutex);
return -ENOMEM; return -ENOMEM;
} }
#ifndef LINUX_2_2
p->owner = entry->module; p->owner = entry->module;
#endif if (!S_ISDIR(entry->mode))
if (!S_ISDIR(entry->mode)) {
#ifndef LINUX_2_2
p->proc_fops = &snd_info_entry_operations; p->proc_fops = &snd_info_entry_operations;
#else
p->ops = &snd_info_entry_inode_operations;
#endif
}
p->size = entry->size; p->size = entry->size;
p->data = entry; p->data = entry;
entry->p = p; entry->p = p;
......
...@@ -193,9 +193,7 @@ int snd_card_disconnect(snd_card_t * card) ...@@ -193,9 +193,7 @@ int snd_card_disconnect(snd_card_t * card)
f_ops = &s_f_ops->f_ops; f_ops = &s_f_ops->f_ops;
memset(f_ops, 0, sizeof(*f_ops)); memset(f_ops, 0, sizeof(*f_ops));
#ifndef LINUX_2_2
f_ops->owner = file->f_op->owner; f_ops->owner = file->f_op->owner;
#endif
f_ops->release = file->f_op->release; f_ops->release = file->f_op->release;
f_ops->poll = snd_disconnect_poll; f_ops->poll = snd_disconnect_poll;
......
...@@ -80,7 +80,6 @@ struct snd_mem_list { ...@@ -80,7 +80,6 @@ struct snd_mem_list {
#define snd_assert(expr, args...) /**/ #define snd_assert(expr, args...) /**/
#endif #endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
#if defined(__i386__) || defined(__ppc__) || defined(__x86_64__) #if defined(__i386__) || defined(__ppc__) || defined(__x86_64__)
#define HACK_PCI_ALLOC_CONSISTENT #define HACK_PCI_ALLOC_CONSISTENT
...@@ -133,7 +132,6 @@ static void *snd_pci_hack_alloc_consistent(struct pci_dev *hwdev, size_t size, ...@@ -133,7 +132,6 @@ static void *snd_pci_hack_alloc_consistent(struct pci_dev *hwdev, size_t size,
#endif /* arch */ #endif /* arch */
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
#endif /* LINUX >= 2.4.0 */
/* /*
...@@ -261,14 +259,16 @@ void snd_dma_free_pages(const struct snd_dma_device *dev, struct snd_dma_buffer ...@@ -261,14 +259,16 @@ void snd_dma_free_pages(const struct snd_dma_device *dev, struct snd_dma_buffer
/* /*
* search for the device * search for the device
*/ */
static struct snd_mem_list *mem_list_find(const struct snd_dma_device *dev, int allow_unused) static struct snd_mem_list *mem_list_find(const struct snd_dma_device *dev, int search_empty)
{ {
struct list_head *p; struct list_head *p;
struct snd_mem_list *mem; struct snd_mem_list *mem;
list_for_each(p, &mem_list_head) { list_for_each(p, &mem_list_head) {
mem = list_entry(p, struct snd_mem_list, list); mem = list_entry(p, struct snd_mem_list, list);
if (compare_device(&mem->dev, dev, allow_unused)) if (mem->used && search_empty)
continue;
if (compare_device(&mem->dev, dev, search_empty))
return mem; return mem;
} }
return NULL; return NULL;
...@@ -623,7 +623,7 @@ void snd_free_pci_pages(struct pci_dev *pci, ...@@ -623,7 +623,7 @@ void snd_free_pci_pages(struct pci_dev *pci,
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) && defined(__i386__) #if defined(__i386__)
/* /*
* on ix86, we allocate a page with GFP_KERNEL to assure the * on ix86, we allocate a page with GFP_KERNEL to assure the
* allocation. the code is almost same with kernel/i386/pci-dma.c but * allocation. the code is almost same with kernel/i386/pci-dma.c but
......
...@@ -376,9 +376,7 @@ int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long a ...@@ -376,9 +376,7 @@ int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long a
static struct file_operations snd_mixer_oss_f_ops = static struct file_operations snd_mixer_oss_f_ops =
{ {
#ifndef LINUX_2_2
.owner = THIS_MODULE, .owner = THIS_MODULE,
#endif
.open = snd_mixer_oss_open, .open = snd_mixer_oss_open,
.release = snd_mixer_oss_release, .release = snd_mixer_oss_release,
.ioctl = snd_mixer_oss_ioctl, .ioctl = snd_mixer_oss_ioctl,
......
...@@ -1981,11 +1981,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) ...@@ -1981,11 +1981,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
if (runtime->oss.plugin_first != NULL) if (runtime->oss.plugin_first != NULL)
return -EIO; return -EIO;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 25)
if (area->vm_pgoff != 0) if (area->vm_pgoff != 0)
#else
if (area->vm_offset != 0)
#endif
return -EINVAL; return -EINVAL;
err = snd_pcm_mmap_data(substream, file, area); err = snd_pcm_mmap_data(substream, file, area);
...@@ -2148,9 +2144,7 @@ static void snd_pcm_oss_proc_done(snd_pcm_t *pcm) ...@@ -2148,9 +2144,7 @@ static void snd_pcm_oss_proc_done(snd_pcm_t *pcm)
static struct file_operations snd_pcm_oss_f_reg = static struct file_operations snd_pcm_oss_f_reg =
{ {
#ifndef LINUX_2_2
.owner = THIS_MODULE, .owner = THIS_MODULE,
#endif
.read = snd_pcm_oss_read, .read = snd_pcm_oss_read,
.write = snd_pcm_oss_write, .write = snd_pcm_oss_write,
.open = snd_pcm_oss_open, .open = snd_pcm_oss_open,
......
...@@ -2602,9 +2602,6 @@ static ssize_t snd_pcm_write(struct file *file, const char *buf, size_t count, l ...@@ -2602,9 +2602,6 @@ static ssize_t snd_pcm_write(struct file *file, const char *buf, size_t count, l
snd_pcm_runtime_t *runtime; snd_pcm_runtime_t *runtime;
snd_pcm_sframes_t result; snd_pcm_sframes_t result;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
up(&file->f_dentry->d_inode->i_sem);
#endif
pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, result = -ENXIO; goto end); pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, result = -ENXIO; goto end);
substream = pcm_file->substream; substream = pcm_file->substream;
snd_assert(substream != NULL, result = -ENXIO; goto end); snd_assert(substream != NULL, result = -ENXIO; goto end);
...@@ -2622,13 +2619,9 @@ static ssize_t snd_pcm_write(struct file *file, const char *buf, size_t count, l ...@@ -2622,13 +2619,9 @@ static ssize_t snd_pcm_write(struct file *file, const char *buf, size_t count, l
if (result > 0) if (result > 0)
result = frames_to_bytes(runtime, result); result = frames_to_bytes(runtime, result);
end: end:
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
down(&file->f_dentry->d_inode->i_sem);
#endif
return result; return result;
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 44)
static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector, static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector,
unsigned long count, loff_t * offset) unsigned long count, loff_t * offset)
...@@ -2675,9 +2668,6 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector, ...@@ -2675,9 +2668,6 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector,
void **bufs; void **bufs;
snd_pcm_uframes_t frames; snd_pcm_uframes_t frames;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
up(&file->f_dentry->d_inode->i_sem);
#endif
pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, result = -ENXIO; goto end); pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, result = -ENXIO; goto end);
substream = pcm_file->substream; substream = pcm_file->substream;
snd_assert(substream != NULL, result = -ENXIO; goto end); snd_assert(substream != NULL, result = -ENXIO; goto end);
...@@ -2702,12 +2692,8 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector, ...@@ -2702,12 +2692,8 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector,
result = frames_to_bytes(runtime, result); result = frames_to_bytes(runtime, result);
kfree(bufs); kfree(bufs);
end: end:
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
down(&file->f_dentry->d_inode->i_sem);
#endif
return result; return result;
} }
#endif
unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait) unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
{ {
...@@ -2789,22 +2775,7 @@ unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait) ...@@ -2789,22 +2775,7 @@ unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
return mask; return mask;
} }
#ifndef VM_RESERVED
#ifndef LINUX_2_2
static int snd_pcm_mmap_swapout(struct page * page, struct file * file)
#else
static int snd_pcm_mmap_swapout(struct vm_area_struct * area, struct page * page)
#endif
{
return 0;
}
#endif
#ifndef LINUX_2_2
static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, unsigned long address, int no_share) static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, unsigned long address, int no_share)
#else
static unsigned long snd_pcm_mmap_status_nopage(struct vm_area_struct *area, unsigned long address, int no_share)
#endif
{ {
snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data; snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
snd_pcm_runtime_t *runtime; snd_pcm_runtime_t *runtime;
...@@ -2815,19 +2786,12 @@ static unsigned long snd_pcm_mmap_status_nopage(struct vm_area_struct *area, uns ...@@ -2815,19 +2786,12 @@ static unsigned long snd_pcm_mmap_status_nopage(struct vm_area_struct *area, uns
runtime = substream->runtime; runtime = substream->runtime;
page = virt_to_page(runtime->status); page = virt_to_page(runtime->status);
get_page(page); get_page(page);
#ifndef LINUX_2_2
return page; return page;
#else
return page_address(page);
#endif
} }
static struct vm_operations_struct snd_pcm_vm_ops_status = static struct vm_operations_struct snd_pcm_vm_ops_status =
{ {
.nopage = snd_pcm_mmap_status_nopage, .nopage = snd_pcm_mmap_status_nopage,
#ifndef VM_RESERVED
.swapout = snd_pcm_mmap_swapout,
#endif
}; };
int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file, int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file,
...@@ -2843,22 +2807,12 @@ int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file, ...@@ -2843,22 +2807,12 @@ int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file,
if (size != PAGE_ALIGN(sizeof(snd_pcm_mmap_status_t))) if (size != PAGE_ALIGN(sizeof(snd_pcm_mmap_status_t)))
return -EINVAL; return -EINVAL;
area->vm_ops = &snd_pcm_vm_ops_status; area->vm_ops = &snd_pcm_vm_ops_status;
#ifndef LINUX_2_2
area->vm_private_data = substream; area->vm_private_data = substream;
#else
area->vm_private_data = (long)substream;
#endif
#ifdef VM_RESERVED
area->vm_flags |= VM_RESERVED; area->vm_flags |= VM_RESERVED;
#endif
return 0; return 0;
} }
#ifndef LINUX_2_2
static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area, unsigned long address, int no_share) static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area, unsigned long address, int no_share)
#else
static unsigned long snd_pcm_mmap_control_nopage(struct vm_area_struct *area, unsigned long address, int no_share)
#endif
{ {
snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data; snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
snd_pcm_runtime_t *runtime; snd_pcm_runtime_t *runtime;
...@@ -2869,19 +2823,12 @@ static unsigned long snd_pcm_mmap_control_nopage(struct vm_area_struct *area, un ...@@ -2869,19 +2823,12 @@ static unsigned long snd_pcm_mmap_control_nopage(struct vm_area_struct *area, un
runtime = substream->runtime; runtime = substream->runtime;
page = virt_to_page(runtime->control); page = virt_to_page(runtime->control);
get_page(page); get_page(page);
#ifndef LINUX_2_2
return page; return page;
#else
return page_address(page);
#endif
} }
static struct vm_operations_struct snd_pcm_vm_ops_control = static struct vm_operations_struct snd_pcm_vm_ops_control =
{ {
.nopage = snd_pcm_mmap_control_nopage, .nopage = snd_pcm_mmap_control_nopage,
#ifndef VM_RESERVED
.swapout = snd_pcm_mmap_swapout,
#endif
}; };
static int snd_pcm_mmap_control(snd_pcm_substream_t *substream, struct file *file, static int snd_pcm_mmap_control(snd_pcm_substream_t *substream, struct file *file,
...@@ -2897,14 +2844,8 @@ static int snd_pcm_mmap_control(snd_pcm_substream_t *substream, struct file *fil ...@@ -2897,14 +2844,8 @@ static int snd_pcm_mmap_control(snd_pcm_substream_t *substream, struct file *fil
if (size != PAGE_ALIGN(sizeof(snd_pcm_mmap_control_t))) if (size != PAGE_ALIGN(sizeof(snd_pcm_mmap_control_t)))
return -EINVAL; return -EINVAL;
area->vm_ops = &snd_pcm_vm_ops_control; area->vm_ops = &snd_pcm_vm_ops_control;
#ifndef LINUX_2_2
area->vm_private_data = substream; area->vm_private_data = substream;
#else
area->vm_private_data = (long)substream;
#endif
#ifdef VM_RESERVED
area->vm_flags |= VM_RESERVED; area->vm_flags |= VM_RESERVED;
#endif
return 0; return 0;
} }
...@@ -2920,11 +2861,7 @@ static void snd_pcm_mmap_data_close(struct vm_area_struct *area) ...@@ -2920,11 +2861,7 @@ static void snd_pcm_mmap_data_close(struct vm_area_struct *area)
atomic_dec(&substream->runtime->mmap_count); atomic_dec(&substream->runtime->mmap_count);
} }
#ifndef LINUX_2_2
static struct page * snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsigned long address, int no_share) static struct page * snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsigned long address, int no_share)
#else
static unsigned long snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsigned long address, int no_share)
#endif
{ {
snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data; snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
snd_pcm_runtime_t *runtime; snd_pcm_runtime_t *runtime;
...@@ -2936,11 +2873,7 @@ static unsigned long snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsig ...@@ -2936,11 +2873,7 @@ static unsigned long snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsig
if (substream == NULL) if (substream == NULL)
return NOPAGE_OOM; return NOPAGE_OOM;
runtime = substream->runtime; runtime = substream->runtime;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 25)
offset = area->vm_pgoff << PAGE_SHIFT; offset = area->vm_pgoff << PAGE_SHIFT;
#else
offset = area->vm_offset;
#endif
offset += address - area->vm_start; offset += address - area->vm_start;
snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_OOM); snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_OOM);
dma_bytes = PAGE_ALIGN(runtime->dma_bytes); dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
...@@ -2955,11 +2888,7 @@ static unsigned long snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsig ...@@ -2955,11 +2888,7 @@ static unsigned long snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsig
page = virt_to_page(vaddr); page = virt_to_page(vaddr);
} }
get_page(page); get_page(page);
#ifndef LINUX_2_2
return page; return page;
#else
return page_address(page);
#endif
} }
static struct vm_operations_struct snd_pcm_vm_ops_data = static struct vm_operations_struct snd_pcm_vm_ops_data =
...@@ -2967,9 +2896,6 @@ static struct vm_operations_struct snd_pcm_vm_ops_data = ...@@ -2967,9 +2896,6 @@ static struct vm_operations_struct snd_pcm_vm_ops_data =
.open = snd_pcm_mmap_data_open, .open = snd_pcm_mmap_data_open,
.close = snd_pcm_mmap_data_close, .close = snd_pcm_mmap_data_close,
.nopage = snd_pcm_mmap_data_nopage, .nopage = snd_pcm_mmap_data_nopage,
#ifndef VM_RESERVED
.swapout = snd_pcm_mmap_swapout,
#endif
}; };
int snd_pcm_mmap_data(snd_pcm_substream_t *substream, struct file *file, int snd_pcm_mmap_data(snd_pcm_substream_t *substream, struct file *file,
...@@ -2997,11 +2923,7 @@ int snd_pcm_mmap_data(snd_pcm_substream_t *substream, struct file *file, ...@@ -2997,11 +2923,7 @@ int snd_pcm_mmap_data(snd_pcm_substream_t *substream, struct file *file,
runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
return -EINVAL; return -EINVAL;
size = area->vm_end - area->vm_start; size = area->vm_end - area->vm_start;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 25)
offset = area->vm_pgoff << PAGE_SHIFT; offset = area->vm_pgoff << PAGE_SHIFT;
#else
offset = area->vm_offset;
#endif
dma_bytes = PAGE_ALIGN(runtime->dma_bytes); dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
if ((size_t)size > dma_bytes) if ((size_t)size > dma_bytes)
return -EINVAL; return -EINVAL;
...@@ -3009,14 +2931,8 @@ int snd_pcm_mmap_data(snd_pcm_substream_t *substream, struct file *file, ...@@ -3009,14 +2931,8 @@ int snd_pcm_mmap_data(snd_pcm_substream_t *substream, struct file *file,
return -EINVAL; return -EINVAL;
area->vm_ops = &snd_pcm_vm_ops_data; area->vm_ops = &snd_pcm_vm_ops_data;
#ifndef LINUX_2_2
area->vm_private_data = substream; area->vm_private_data = substream;
#else
area->vm_private_data = (long)substream;
#endif
#ifdef VM_RESERVED
area->vm_flags |= VM_RESERVED; area->vm_flags |= VM_RESERVED;
#endif
atomic_inc(&runtime->mmap_count); atomic_inc(&runtime->mmap_count);
return 0; return 0;
} }
...@@ -3031,11 +2947,7 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) ...@@ -3031,11 +2947,7 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
substream = pcm_file->substream; substream = pcm_file->substream;
snd_assert(substream != NULL, return -ENXIO); snd_assert(substream != NULL, return -ENXIO);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 25)
offset = area->vm_pgoff << PAGE_SHIFT; offset = area->vm_pgoff << PAGE_SHIFT;
#else
offset = area->vm_offset;
#endif
switch (offset) { switch (offset) {
case SNDRV_PCM_MMAP_OFFSET_STATUS: case SNDRV_PCM_MMAP_OFFSET_STATUS:
return snd_pcm_mmap_status(substream, file, area); return snd_pcm_mmap_status(substream, file, area);
...@@ -3143,13 +3055,9 @@ static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sn ...@@ -3143,13 +3055,9 @@ static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sn
*/ */
static struct file_operations snd_pcm_f_ops_playback = { static struct file_operations snd_pcm_f_ops_playback = {
#ifndef LINUX_2_2
.owner = THIS_MODULE, .owner = THIS_MODULE,
#endif
.write = snd_pcm_write, .write = snd_pcm_write,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 44)
.writev = snd_pcm_writev, .writev = snd_pcm_writev,
#endif
.open = snd_pcm_open, .open = snd_pcm_open,
.release = snd_pcm_release, .release = snd_pcm_release,
.poll = snd_pcm_playback_poll, .poll = snd_pcm_playback_poll,
...@@ -3159,13 +3067,9 @@ static struct file_operations snd_pcm_f_ops_playback = { ...@@ -3159,13 +3067,9 @@ static struct file_operations snd_pcm_f_ops_playback = {
}; };
static struct file_operations snd_pcm_f_ops_capture = { static struct file_operations snd_pcm_f_ops_capture = {
#ifndef LINUX_2_2
.owner = THIS_MODULE, .owner = THIS_MODULE,
#endif
.read = snd_pcm_read, .read = snd_pcm_read,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 44)
.readv = snd_pcm_readv, .readv = snd_pcm_readv,
#endif
.open = snd_pcm_open, .open = snd_pcm_open,
.release = snd_pcm_release, .release = snd_pcm_release,
.poll = snd_pcm_capture_poll, .poll = snd_pcm_capture_poll,
......
...@@ -1316,9 +1316,7 @@ static void snd_rawmidi_proc_info_read(snd_info_entry_t *entry, ...@@ -1316,9 +1316,7 @@ static void snd_rawmidi_proc_info_read(snd_info_entry_t *entry,
static struct file_operations snd_rawmidi_f_ops = static struct file_operations snd_rawmidi_f_ops =
{ {
#ifndef LINUX_2_2
.owner = THIS_MODULE, .owner = THIS_MODULE,
#endif
.read = snd_rawmidi_read, .read = snd_rawmidi_read,
.write = snd_rawmidi_write, .write = snd_rawmidi_write,
.open = snd_rawmidi_open, .open = snd_rawmidi_open,
......
...@@ -194,9 +194,7 @@ odev_poll(struct file *file, poll_table * wait) ...@@ -194,9 +194,7 @@ odev_poll(struct file *file, poll_table * wait)
static struct file_operations seq_oss_f_ops = static struct file_operations seq_oss_f_ops =
{ {
#ifndef LINUX_2_2
.owner = THIS_MODULE, .owner = THIS_MODULE,
#endif
.read = odev_read, .read = odev_read,
.write = odev_write, .write = odev_write,
.open = odev_open, .open = odev_open,
......
...@@ -2454,9 +2454,7 @@ void snd_seq_info_clients_read(snd_info_entry_t *entry, ...@@ -2454,9 +2454,7 @@ void snd_seq_info_clients_read(snd_info_entry_t *entry,
static struct file_operations snd_seq_f_ops = static struct file_operations snd_seq_f_ops =
{ {
#ifndef LINUX_2_2
.owner = THIS_MODULE, .owner = THIS_MODULE,
#endif
.read = snd_seq_read, .read = snd_seq_read,
.write = snd_seq_write, .write = snd_seq_write,
.open = snd_seq_open, .open = snd_seq_open,
......
...@@ -235,18 +235,7 @@ int snd_seq_cell_alloc(pool_t *pool, snd_seq_event_cell_t **cellp, int nonblock, ...@@ -235,18 +235,7 @@ int snd_seq_cell_alloc(pool_t *pool, snd_seq_event_cell_t **cellp, int nonblock,
while (pool->free == NULL && ! nonblock && ! pool->closing) { while (pool->free == NULL && ! nonblock && ! pool->closing) {
spin_unlock(&pool->lock); spin_unlock(&pool->lock);
#ifdef LINUX_2_2
/* change semaphore to allow other clients
to access device file */
if (file)
up(&semaphore_of(file));
#endif
interruptible_sleep_on(&pool->output_sleep); interruptible_sleep_on(&pool->output_sleep);
#ifdef LINUX_2_2
/* restore semaphore again */
if (file)
down(&semaphore_of(file));
#endif
spin_lock(&pool->lock); spin_lock(&pool->lock);
/* interrupted? */ /* interrupted? */
if (signal_pending(current)) { if (signal_pending(current)) {
......
...@@ -154,9 +154,7 @@ static int snd_open(struct inode *inode, struct file *file) ...@@ -154,9 +154,7 @@ static int snd_open(struct inode *inode, struct file *file)
struct file_operations snd_fops = struct file_operations snd_fops =
{ {
#ifndef LINUX_2_2
.owner = THIS_MODULE, .owner = THIS_MODULE,
#endif
.open = snd_open .open = snd_open
}; };
...@@ -365,9 +363,6 @@ static int __init alsa_sound_init(void) ...@@ -365,9 +363,6 @@ static int __init alsa_sound_init(void)
#endif #endif
#ifndef MODULE #ifndef MODULE
printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n"); printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n");
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) && defined(CONFIG_APM)
pm_init();
#endif #endif
return 0; return 0;
} }
...@@ -383,9 +378,6 @@ static void __exit alsa_sound_exit(void) ...@@ -383,9 +378,6 @@ static void __exit alsa_sound_exit(void)
snd_info_minor_unregister(); snd_info_minor_unregister();
#endif #endif
snd_info_done(); snd_info_done();
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) && defined(CONFIG_APM)
pm_done();
#endif
#ifdef CONFIG_SND_DEBUG_MEMORY #ifdef CONFIG_SND_DEBUG_MEMORY
snd_memory_done(); snd_memory_done();
#endif #endif
......
...@@ -1733,9 +1733,7 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait) ...@@ -1733,9 +1733,7 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait)
static struct file_operations snd_timer_f_ops = static struct file_operations snd_timer_f_ops =
{ {
#ifndef LINUX_2_2
.owner = THIS_MODULE, .owner = THIS_MODULE,
#endif
.read = snd_timer_user_read, .read = snd_timer_user_read,
.open = snd_timer_user_open, .open = snd_timer_user_open,
.release = snd_timer_user_release, .release = snd_timer_user_release,
......
...@@ -14,4 +14,4 @@ obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o ...@@ -14,4 +14,4 @@ obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o
obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o
obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o
obj-$(CONFIG_SND) += opl3/ mpu401/ obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/
...@@ -21,11 +21,7 @@ ...@@ -21,11 +21,7 @@
#include <sound/driver.h> #include <sound/driver.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/init.h> #include <linux/init.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
#include <linux/jiffies.h> #include <linux/jiffies.h>
#else
#include <linux/sched.h>
#endif
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/wait.h> #include <linux/wait.h>
...@@ -58,8 +54,8 @@ MODULE_DEVICES("{{ALSA,Dummy soundcard}}"); ...@@ -58,8 +54,8 @@ MODULE_DEVICES("{{ALSA,Dummy soundcard}}");
#if 0 /* ICE1712 emulation */ #if 0 /* ICE1712 emulation */
#define MAX_BUFFER_SIZE (256 * 1024) #define MAX_BUFFER_SIZE (256 * 1024)
#define USE_FORMATS SNDRV_PCM_FMTBIT_S32_LE #define USE_FORMATS SNDRV_PCM_FMTBIT_S32_LE
#define USE_CHANNELS_MIN 12 #define USE_CHANNELS_MIN 10
#define USE_CHANNELS_MAX 12 #define USE_CHANNELS_MAX 10
#define USE_PERIODS_MIN 1 #define USE_PERIODS_MIN 1
#define USE_PERIODS_MAX 1024 #define USE_PERIODS_MAX 1024
#endif #endif
...@@ -430,7 +426,7 @@ static int snd_dummy_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t ...@@ -430,7 +426,7 @@ static int snd_dummy_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
{ {
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2; uinfo->count = 2;
uinfo->value.integer.min = 0; uinfo->value.integer.min = -50;
uinfo->value.integer.max = 100; uinfo->value.integer.max = 100;
return 0; return 0;
} }
...@@ -455,8 +451,16 @@ static int snd_dummy_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t ...@@ -455,8 +451,16 @@ static int snd_dummy_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
int change, addr = kcontrol->private_value; int change, addr = kcontrol->private_value;
int left, right; int left, right;
left = ucontrol->value.integer.value[0] % 101; left = ucontrol->value.integer.value[0];
right = ucontrol->value.integer.value[1] % 101; if (left < -50)
left = -50;
if (left > 100)
left = 100;
right = ucontrol->value.integer.value[1];
if (right < -50)
right = -50;
if (right > 100)
right = 100;
spin_lock_irqsave(&dummy->mixer_lock, flags); spin_lock_irqsave(&dummy->mixer_lock, flags);
change = dummy->mixer_volume[addr][0] != left || change = dummy->mixer_volume[addr][0] != left ||
dummy->mixer_volume[addr][1] != right; dummy->mixer_volume[addr][1] != right;
......
...@@ -4,12 +4,10 @@ ...@@ -4,12 +4,10 @@
# #
snd-opl3-lib-objs := opl3_lib.o opl3_synth.o snd-opl3-lib-objs := opl3_lib.o opl3_synth.o
ifeq ($(subst m,y,$(CONFIG_SND_SEQUENCER)),y)
snd-opl3-synth-objs := opl3_seq.o opl3_midi.o opl3_drums.o snd-opl3-synth-objs := opl3_seq.o opl3_midi.o opl3_drums.o
ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
snd-opl3-synth-objs += opl3_oss.o snd-opl3-synth-objs += opl3_oss.o
endif endif
endif
OPL3_OBJS = snd-opl3-lib.o OPL3_OBJS = snd-opl3-lib.o
ifeq ($(subst m,y,$(CONFIG_SND_SEQUENCER)),y) ifeq ($(subst m,y,$(CONFIG_SND_SEQUENCER)),y)
......
#
# Makefile for ALSA
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
#
snd-opl4-lib-objs := opl4_lib.o opl4_mixer.o opl4_proc.o
snd-opl4-synth-objs := opl4_seq.o opl4_synth.o yrw801.o
OPL4_OBJS := snd-opl4-lib.o
ifeq ($(subst m,y,$(CONFIG_SND_SEQUENCER)),y)
OPL4_OBJS += snd-opl4-synth.o
endif
obj-$(CONFIG_SND_OPTI92X_AD1848) += $(OPL4_OBJS)
obj-$(CONFIG_SND_OPTI92X_CS4231) += $(OPL4_OBJS)
/*
* Functions for accessing OPL4 devices
* Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
*
* 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 "opl4_local.h"
#include <sound/initval.h>
#include <linux/ioport.h>
#include <asm/io.h>
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_DESCRIPTION("OPL4 driver");
MODULE_LICENSE("GPL");
MODULE_CLASSES("{sound}");
static void inline snd_opl4_wait(opl4_t *opl4)
{
int timeout = 10;
while ((inb(opl4->fm_port) & OPL4_STATUS_BUSY) && --timeout > 0)
;
}
void snd_opl4_write(opl4_t *opl4, u8 reg, u8 value)
{
unsigned long flags;
spin_lock_irqsave(&opl4->reg_lock, flags);
snd_opl4_wait(opl4);
outb(reg, opl4->pcm_port);
snd_opl4_wait(opl4);
outb(value, opl4->pcm_port + 1);
spin_unlock_irqrestore(&opl4->reg_lock, flags);
}
u8 snd_opl4_read(opl4_t *opl4, u8 reg)
{
unsigned long flags;
u8 value;
spin_lock_irqsave(&opl4->reg_lock, flags);
snd_opl4_wait(opl4);
outb(reg, opl4->pcm_port);
snd_opl4_wait(opl4);
value = inb(opl4->pcm_port + 1);
spin_unlock_irqrestore(&opl4->reg_lock, flags);
return value;
}
void snd_opl4_read_memory(opl4_t *opl4, char *buf, int offset, int size)
{
u8 memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT);
snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16);
snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8);
snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset);
for (; size > 0; size--)
*buf++ = snd_opl4_read(opl4, OPL4_REG_MEMORY_DATA);
snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg);
}
void snd_opl4_write_memory(opl4_t *opl4, const char *buf, int offset, int size)
{
u8 memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT);
snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16);
snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8);
snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset);
for (; size > 0; size--)
snd_opl4_write(opl4, OPL4_REG_MEMORY_DATA, *buf++);
snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg);
}
static void snd_opl4_enable_opl4(opl4_t *opl4)
{
outb(OPL3_REG_MODE, opl4->fm_port + 2);
inb(opl4->fm_port);
inb(opl4->fm_port);
outb(OPL3_OPL3_ENABLE | OPL3_OPL4_ENABLE, opl4->fm_port + 3);
inb(opl4->fm_port);
inb(opl4->fm_port);
}
static int snd_opl4_detect(opl4_t *opl4)
{
u8 id1, id2;
snd_opl4_enable_opl4(opl4);
id1 = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
snd_printdd("OPL4[02]=%02x\n", id1);
switch (id1 & OPL4_DEVICE_ID_MASK) {
case 0x20:
opl4->hardware = OPL3_HW_OPL4;
break;
case 0x40:
opl4->hardware = OPL3_HW_OPL4_ML;
break;
default:
return -ENODEV;
}
snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x00);
snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0xff);
id1 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_FM);
id2 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_PCM);
snd_printdd("OPL4 id1=%02x id2=%02x\n", id1, id2);
if (id1 != 0x00 || id2 != 0xff)
return -ENODEV;
snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x3f);
snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0x3f);
snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, 0x00);
return 0;
}
#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
static void snd_opl4_seq_dev_free(snd_seq_device_t *seq_dev)
{
opl4_t *opl4 = snd_magic_cast(opl4_t, seq_dev->private_data, return);
opl4->seq_dev = NULL;
}
static int snd_opl4_create_seq_dev(opl4_t *opl4, int seq_device)
{
opl4->seq_dev_num = seq_device;
if (snd_seq_device_new(opl4->card, seq_device, SNDRV_SEQ_DEV_ID_OPL4,
sizeof(opl4_t *), &opl4->seq_dev) >= 0) {
strcpy(opl4->seq_dev->name, "OPL4 Wavetable");
*(opl4_t **)SNDRV_SEQ_DEVICE_ARGPTR(opl4->seq_dev) = opl4;
opl4->seq_dev->private_data = opl4;
opl4->seq_dev->private_free = snd_opl4_seq_dev_free;
}
return 0;
}
#endif
static void snd_opl4_free(opl4_t *opl4)
{
#ifdef CONFIG_PROC_FS
snd_opl4_free_proc(opl4);
#endif
if (opl4->res_fm_port) {
release_resource(opl4->res_fm_port);
kfree_nocheck(opl4->res_fm_port);
}
if (opl4->res_pcm_port) {
release_resource(opl4->res_pcm_port);
kfree_nocheck(opl4->res_pcm_port);
}
snd_magic_kfree(opl4);
}
static int snd_opl4_dev_free(snd_device_t *device)
{
opl4_t *opl4 = snd_magic_cast(opl4_t, device->device_data, return -ENXIO);
snd_opl4_free(opl4);
return 0;
}
int snd_opl4_create(snd_card_t *card,
unsigned long fm_port, unsigned long pcm_port,
int seq_device,
opl3_t **ropl3, opl4_t **ropl4)
{
opl4_t *opl4;
opl3_t *opl3;
int err;
static snd_device_ops_t ops = {
.dev_free = snd_opl4_dev_free
};
if (ropl3)
*ropl3 = NULL;
if (ropl4)
*ropl4 = NULL;
opl4 = snd_magic_kcalloc(opl4_t, 0, GFP_KERNEL);
if (!opl4)
return -ENOMEM;
opl4->res_fm_port = request_region(fm_port, 8, "OPL4 FM");
opl4->res_pcm_port = request_region(pcm_port, 8, "OPL4 PCM/MIX");
if (!opl4->res_fm_port || !opl4->res_pcm_port) {
snd_opl4_free(opl4);
return -EBUSY;
}
opl4->card = card;
opl4->fm_port = fm_port;
opl4->pcm_port = pcm_port;
spin_lock_init(&opl4->reg_lock);
init_MUTEX(&opl4->access_mutex);
err = snd_opl4_detect(opl4);
if (err < 0) {
snd_opl4_free(opl4);
snd_printd("OPL4 chip not detected at %#lx/%#lx\n", fm_port, pcm_port);
return err;
}
err = snd_opl3_create(card, fm_port, fm_port + 2, opl4->hardware, 1, &opl3);
if (err < 0) {
snd_opl4_free(opl4);
return err;
}
/* opl3 initialization disabled opl4, so reenable */
snd_opl4_enable_opl4(opl4);
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, opl4, &ops);
if (err < 0) {
snd_device_free(card, opl3);
snd_opl4_free(opl4);
return err;
}
snd_opl4_create_mixer(opl4);
#ifdef CONFIG_PROC_FS
snd_opl4_create_proc(opl4);
#endif
#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
opl4->seq_client = -1;
if (opl4->hardware < OPL3_HW_OPL4_ML)
snd_opl4_create_seq_dev(opl4, seq_device);
#endif
if (ropl3)
*ropl3 = opl3;
if (ropl4)
*ropl4 = opl4;
return 0;
}
EXPORT_SYMBOL(snd_opl4_write);
EXPORT_SYMBOL(snd_opl4_read);
EXPORT_SYMBOL(snd_opl4_write_memory);
EXPORT_SYMBOL(snd_opl4_read_memory);
EXPORT_SYMBOL(snd_opl4_create);
static int __init alsa_opl4_init(void)
{
return 0;
}
static void __exit alsa_opl4_exit(void)
{
}
module_init(alsa_opl4_init)
module_exit(alsa_opl4_exit)
/*
* Local definitions for the OPL4 driver
*
* Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Alternatively, this software may be distributed and/or modified 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 SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __OPL4_LOCAL_H
#define __OPL4_LOCAL_H
#include <sound/opl4.h>
/*
* Register numbers
*/
#define OPL4_REG_TEST0 0x00
#define OPL4_REG_TEST1 0x01
#define OPL4_REG_MEMORY_CONFIGURATION 0x02
#define OPL4_MODE_BIT 0x01
#define OPL4_MTYPE_BIT 0x02
#define OPL4_TONE_HEADER_MASK 0x1c
#define OPL4_DEVICE_ID_MASK 0xe0
#define OPL4_REG_MEMORY_ADDRESS_HIGH 0x03
#define OPL4_REG_MEMORY_ADDRESS_MID 0x04
#define OPL4_REG_MEMORY_ADDRESS_LOW 0x05
#define OPL4_REG_MEMORY_DATA 0x06
/*
* Offsets to the register banks for voices. To get the
* register number just add the voice number to the bank offset.
*
* Wave Table Number low bits (0x08 to 0x1F)
*/
#define OPL4_REG_TONE_NUMBER 0x08
/* Wave Table Number high bit, F-Number low bits (0x20 to 0x37) */
#define OPL4_REG_F_NUMBER 0x20
#define OPL4_TONE_NUMBER_BIT8 0x01
#define OPL4_F_NUMBER_LOW_MASK 0xfe
/* F-Number high bits, Octave, Pseudo-Reverb (0x38 to 0x4F) */
#define OPL4_REG_OCTAVE 0x38
#define OPL4_F_NUMBER_HIGH_MASK 0x07
#define OPL4_BLOCK_MASK 0xf0
#define OPL4_PSEUDO_REVERB_BIT 0x08
/* Total Level, Level Direct (0x50 to 0x67) */
#define OPL4_REG_LEVEL 0x50
#define OPL4_TOTAL_LEVEL_MASK 0xfe
#define OPL4_LEVEL_DIRECT_BIT 0x01
/* Key On, Damp, LFO RST, CH, Panpot (0x68 to 0x7F) */
#define OPL4_REG_MISC 0x68
#define OPL4_KEY_ON_BIT 0x80
#define OPL4_DAMP_BIT 0x40
#define OPL4_LFO_RESET_BIT 0x20
#define OPL4_OUTPUT_CHANNEL_BIT 0x10
#define OPL4_PAN_POT_MASK 0x0f
/* LFO, VIB (0x80 to 0x97) */
#define OPL4_REG_LFO_VIBRATO 0x80
#define OPL4_LFO_FREQUENCY_MASK 0x38
#define OPL4_VIBRATO_DEPTH_MASK 0x07
#define OPL4_CHORUS_SEND_MASK 0xc0 /* ML only */
/* Attack / Decay 1 rate (0x98 to 0xAF) */
#define OPL4_REG_ATTACK_DECAY1 0x98
#define OPL4_ATTACK_RATE_MASK 0xf0
#define OPL4_DECAY1_RATE_MASK 0x0f
/* Decay level / 2 rate (0xB0 to 0xC7) */
#define OPL4_REG_LEVEL_DECAY2 0xb0
#define OPL4_DECAY_LEVEL_MASK 0xf0
#define OPL4_DECAY2_RATE_MASK 0x0f
/* Release rate / Rate correction (0xC8 to 0xDF) */
#define OPL4_REG_RELEASE_CORRECTION 0xc8
#define OPL4_RELEASE_RATE_MASK 0x0f
#define OPL4_RATE_INTERPOLATION_MASK 0xf0
/* AM (0xE0 to 0xF7) */
#define OPL4_REG_TREMOLO 0xe0
#define OPL4_TREMOLO_DEPTH_MASK 0x07
#define OPL4_REVERB_SEND_MASK 0xe0 /* ML only */
/* Mixer */
#define OPL4_REG_MIX_CONTROL_FM 0xf8
#define OPL4_REG_MIX_CONTROL_PCM 0xf9
#define OPL4_MIX_LEFT_MASK 0x07
#define OPL4_MIX_RIGHT_MASK 0x38
#define OPL4_REG_ATC 0xfa
#define OPL4_ATC_BIT 0x01 /* ???, ML only */
/* bits in the OPL3 Status register */
#define OPL4_STATUS_BUSY 0x01
#define OPL4_STATUS_LOAD 0x02
#define OPL4_MAX_VOICES 24
#define SNDRV_SEQ_DEV_ID_OPL4 "opl4-synth"
typedef struct opl4_sound {
u16 tone;
s16 pitch_offset;
u8 key_scaling;
s8 panpot;
u8 vibrato;
u8 tone_attenuate;
u8 volume_factor;
u8 reg_lfo_vibrato;
u8 reg_attack_decay1;
u8 reg_level_decay2;
u8 reg_release_correction;
u8 reg_tremolo;
} opl4_sound_t;
typedef struct opl4_region {
u8 key_min, key_max;
opl4_sound_t sound;
} opl4_region_t;
typedef struct opl4_region_ptr {
int count;
const opl4_region_t *regions;
} opl4_region_ptr_t;
typedef struct opl4_voice {
struct list_head list;
int number;
snd_midi_channel_t *chan;
int note;
int velocity;
const opl4_sound_t *sound;
u8 reg_f_number;
u8 reg_misc;
} opl4_voice_t;
struct opl4 {
unsigned long fm_port;
unsigned long pcm_port;
struct resource *res_fm_port;
struct resource *res_pcm_port;
unsigned short hardware;
spinlock_t reg_lock;
snd_card_t *card;
#ifdef CONFIG_PROC_FS
snd_info_entry_t *proc_entry;
int memory_access;
#endif
struct semaphore access_mutex;
#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
int used;
int seq_dev_num;
int seq_client;
snd_seq_device_t *seq_dev;
snd_midi_channel_set_t *chset;
opl4_voice_t voices[OPL4_MAX_VOICES];
struct list_head off_voices;
struct list_head on_voices;
spinlock_t voices_lock;
#endif
};
/* opl4_lib.c */
void snd_opl4_write(opl4_t *opl4, u8 reg, u8 value);
u8 snd_opl4_read(opl4_t *opl4, u8 reg);
void snd_opl4_read_memory(opl4_t *opl4, char *buf, int offset, int size);
void snd_opl4_write_memory(opl4_t *opl4, const char *buf, int offset, int size);
/* opl4_mixer.c */
int snd_opl4_create_mixer(opl4_t *opl4);
#ifdef CONFIG_PROC_FS
/* opl4_proc.c */
int snd_opl4_create_proc(opl4_t *opl4);
void snd_opl4_free_proc(opl4_t *opl4);
#endif
/* opl4_seq.c */
extern int volume_boost;
/* opl4_synth.c */
void snd_opl4_synth_reset(opl4_t *opl4);
void snd_opl4_synth_shutdown(opl4_t *opl4);
void snd_opl4_note_on(void *p, int note, int vel, snd_midi_channel_t *chan);
void snd_opl4_note_off(void *p, int note, int vel, snd_midi_channel_t *chan);
void snd_opl4_terminate_note(void *p, int note, snd_midi_channel_t *chan);
void snd_opl4_control(void *p, int type, snd_midi_channel_t *chan);
void snd_opl4_sysex(void *p, unsigned char *buf, int len, int parsed, snd_midi_channel_set_t *chset);
/* yrw801.c */
int snd_yrw801_detect(opl4_t *opl4);
extern const opl4_region_ptr_t snd_yrw801_regions[];
#endif /* __OPL4_LOCAL_H */
/*
* OPL4 mixer functions
* Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
*
* 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 "opl4_local.h"
#include <sound/control.h>
#define chip_t opl4_t
static int snd_opl4_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 7;
return 0;
}
static int snd_opl4_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
opl4_t *opl4 = snd_kcontrol_chip(kcontrol);
u8 reg = kcontrol->private_value;
u8 value;
value = snd_opl4_read(opl4, reg);
ucontrol->value.integer.value[0] = 7 - (value & 7);
ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7);
return 0;
}
static int snd_opl4_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
opl4_t *opl4 = snd_kcontrol_chip(kcontrol);
u8 reg = kcontrol->private_value;
u8 value, old_value;
value = (7 - (ucontrol->value.integer.value[0] & 7)) |
((7 - (ucontrol->value.integer.value[1] & 7)) << 3);
old_value = snd_opl4_read(opl4, reg);
snd_opl4_write(opl4, reg, value);
return value != old_value;
}
static snd_kcontrol_new_t snd_opl4_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "FM Playback Volume",
.info = snd_opl4_ctl_info,
.get = snd_opl4_ctl_get,
.put = snd_opl4_ctl_put,
.private_value = OPL4_REG_MIX_CONTROL_FM
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Wavetable Playback Volume",
.info = snd_opl4_ctl_info,
.get = snd_opl4_ctl_get,
.put = snd_opl4_ctl_put,
.private_value = OPL4_REG_MIX_CONTROL_PCM
}
};
int snd_opl4_create_mixer(opl4_t *opl4)
{
snd_card_t *card = opl4->card;
int i, err;
#if 0 /* already set by the codec driver */
strcpy(card->mixername, "OPL4 Mixer");
#endif
for (i = 0; i < 2; ++i) {
err = snd_ctl_add(card, snd_ctl_new1(&snd_opl4_controls[i], opl4));
if (err < 0)
return err;
}
return 0;
}
/*
* Functions for the OPL4 proc file
* Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
*
* 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 "opl4_local.h"
#include <sound/info.h>
#ifdef CONFIG_PROC_FS
static int snd_opl4_mem_proc_open(snd_info_entry_t *entry,
unsigned short mode, void **file_private_data)
{
opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
down(&opl4->access_mutex);
if (opl4->memory_access) {
up(&opl4->access_mutex);
return -EBUSY;
}
opl4->memory_access++;
up(&opl4->access_mutex);
return 0;
}
static int snd_opl4_mem_proc_release(snd_info_entry_t *entry,
unsigned short mode, void *file_private_data)
{
opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
down(&opl4->access_mutex);
opl4->memory_access--;
up(&opl4->access_mutex);
return 0;
}
static long snd_opl4_mem_proc_read(snd_info_entry_t *entry, void *file_private_data,
struct file *file, char *_buf, long count)
{
opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
long size;
char* buf;
size = count;
if (file->f_pos + size > entry->size)
size = entry->size - file->f_pos;
if (size > 0) {
buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
snd_opl4_read_memory(opl4, buf, file->f_pos, size);
if (copy_to_user(_buf, buf, size)) {
kfree(buf);
return -EFAULT;
}
kfree(buf);
file->f_pos += size;
return size;
}
return 0;
}
static long snd_opl4_mem_proc_write(snd_info_entry_t *entry, void *file_private_data,
struct file *file, const char *_buf, long count)
{
opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
long size;
char *buf;
size = count;
if (file->f_pos + size > entry->size)
size = entry->size - file->f_pos;
if (size > 0) {
buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
if (copy_from_user(buf, _buf, size)) {
kfree(buf);
return -EFAULT;
}
snd_opl4_write_memory(opl4, buf, file->f_pos, size);
kfree(buf);
file->f_pos += size;
return size;
}
return 0;
}
static long long snd_opl4_mem_proc_llseek(snd_info_entry_t *entry, void *file_private_data,
struct file *file, long long offset, int orig)
{
switch (orig) {
case 0: /* SEEK_SET */
file->f_pos = offset;
break;
case 1: /* SEEK_CUR */
file->f_pos += offset;
break;
case 2: /* SEEK_END, offset is negative */
file->f_pos = entry->size + offset;
break;
default:
return -EINVAL;
}
if (file->f_pos > entry->size)
file->f_pos = entry->size;
return file->f_pos;
}
static struct snd_info_entry_ops snd_opl4_mem_proc_ops = {
.open = snd_opl4_mem_proc_open,
.release = snd_opl4_mem_proc_release,
.read = snd_opl4_mem_proc_read,
.write = snd_opl4_mem_proc_write,
.llseek = snd_opl4_mem_proc_llseek,
};
int snd_opl4_create_proc(opl4_t *opl4)
{
snd_info_entry_t *entry;
entry = snd_info_create_card_entry(opl4->card, "opl4-mem", opl4->card->proc_root);
if (entry) {
if (opl4->hardware < OPL3_HW_OPL4_ML) {
/* OPL4 can access 4 MB external ROM/SRAM */
entry->mode |= S_IWUSR;
entry->size = 4 * 1024 * 1024;
} else {
/* OPL4-ML has 1 MB internal ROM */
entry->size = 1 * 1024 * 1024;
}
entry->content = SNDRV_INFO_CONTENT_DATA;
entry->c.ops = &snd_opl4_mem_proc_ops;
entry->module = THIS_MODULE;
entry->private_data = opl4;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;
}
}
opl4->proc_entry = entry;
return 0;
}
void snd_opl4_free_proc(opl4_t *opl4)
{
if (opl4->proc_entry)
snd_info_unregister(opl4->proc_entry);
}
#endif /* CONFIG_PROC_FS */
/*
* OPL4 sequencer functions
*
* Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Alternatively, this software may be distributed and/or modified 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 SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "opl4_local.h"
#include <linux/init.h>
#include <sound/initval.h>
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_DESCRIPTION("OPL4 wavetable synth driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_CLASSES("{sound}");
int volume_boost = 8;
MODULE_PARM(volume_boost, "i");
MODULE_PARM_DESC(volume_boost, "Additional volume for OPL4 wavetable sounds.");
MODULE_PARM_SYNTAX(volume_boost, "default:8");
static int snd_opl4_seq_use_inc(opl4_t *opl4)
{
if (!try_module_get(opl4->card->module))
return -EFAULT;
return 0;
}
static void snd_opl4_seq_use_dec(opl4_t *opl4)
{
module_put(opl4->card->module);
}
static int snd_opl4_seq_use(void *private_data, snd_seq_port_subscribe_t *info)
{
opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return -ENXIO);
int err;
down(&opl4->access_mutex);
if (opl4->used) {
up(&opl4->access_mutex);
return -EBUSY;
}
opl4->used++;
if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) {
err = snd_opl4_seq_use_inc(opl4);
if (err < 0) {
up(&opl4->access_mutex);
return err;
}
}
up(&opl4->access_mutex);
snd_opl4_synth_reset(opl4);
return 0;
}
static int snd_opl4_seq_unuse(void *private_data, snd_seq_port_subscribe_t *info)
{
opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return -ENXIO);
snd_opl4_synth_shutdown(opl4);
down(&opl4->access_mutex);
opl4->used--;
up(&opl4->access_mutex);
if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM)
snd_opl4_seq_use_dec(opl4);
return 0;
}
static snd_midi_op_t opl4_ops = {
.note_on = snd_opl4_note_on,
.note_off = snd_opl4_note_off,
.note_terminate = snd_opl4_terminate_note,
.control = snd_opl4_control,
.sysex = snd_opl4_sysex,
};
static int snd_opl4_seq_event_input(snd_seq_event_t *ev, int direct,
void *private_data, int atomic, int hop)
{
opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return -ENXIO);
snd_midi_process_event(&opl4_ops, ev, opl4->chset);
return 0;
}
static void snd_opl4_seq_free_port(void *private_data)
{
opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
snd_midi_channel_free_set(opl4->chset);
}
static int snd_opl4_seq_new_device(snd_seq_device_t *dev)
{
opl4_t *opl4;
int client;
snd_seq_client_callback_t callbacks;
snd_seq_client_info_t cinfo;
snd_seq_port_callback_t pcallbacks;
opl4 = *(opl4_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
if (!opl4)
return -EINVAL;
if (snd_yrw801_detect(opl4) < 0)
return -ENODEV;
opl4->chset = snd_midi_channel_alloc_set(16);
if (!opl4->chset)
return -ENOMEM;
opl4->chset->private_data = opl4;
/* allocate new client */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.private_data = opl4;
callbacks.allow_output = callbacks.allow_input = 1;
client = snd_seq_create_kernel_client(opl4->card, opl4->seq_dev_num, &callbacks);
if (client < 0) {
snd_midi_channel_free_set(opl4->chset);
return client;
}
opl4->seq_client = client;
opl4->chset->client = client;
/* change name of client */
memset(&cinfo, 0, sizeof(cinfo));
cinfo.client = client;
cinfo.type = KERNEL_CLIENT;
strcpy(cinfo.name, "OPL4 Wavetable");
snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
/* create new port */
memset(&pcallbacks, 0, sizeof(pcallbacks));
pcallbacks.owner = THIS_MODULE;
pcallbacks.use = snd_opl4_seq_use;
pcallbacks.unuse = snd_opl4_seq_unuse;
pcallbacks.event_input = snd_opl4_seq_event_input;
pcallbacks.private_free = snd_opl4_seq_free_port;
pcallbacks.private_data = opl4;
opl4->chset->port = snd_seq_event_port_attach(client, &pcallbacks,
SNDRV_SEQ_PORT_CAP_WRITE |
SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
SNDRV_SEQ_PORT_TYPE_MIDI_GM,
16, 24,
"OPL4 Wavetable Port");
if (opl4->chset->port < 0) {
int err = opl4->chset->port;
snd_midi_channel_free_set(opl4->chset);
snd_seq_delete_kernel_client(client);
opl4->seq_client = -1;
return err;
}
return 0;
}
static int snd_opl4_seq_delete_device(snd_seq_device_t *dev)
{
opl4_t *opl4;
opl4 = *(opl4_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
if (!opl4)
return -EINVAL;
if (opl4->seq_client >= 0) {
snd_seq_delete_kernel_client(opl4->seq_client);
opl4->seq_client = -1;
}
return 0;
}
static int __init alsa_opl4_synth_init(void)
{
static snd_seq_dev_ops_t ops = {
snd_opl4_seq_new_device,
snd_opl4_seq_delete_device
};
return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OPL4, &ops,
sizeof(opl4_t*));
}
static void __exit alsa_opl4_synth_exit(void)
{
snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OPL4);
}
module_init(alsa_opl4_synth_init)
module_exit(alsa_opl4_synth_exit)
This diff is collapsed.
This diff is collapsed.
#
# Makefile for ALSA
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
#
snd-vx-lib-objs := vx_core.o vx_hwdep.o vx_pcm.o vx_mixer.o vx_cmd.o vx_uer.o
obj-$(CONFIG_SND_VXPOCKET) += snd-vx-lib.o
obj-$(CONFIG_SND_VXP440) += snd-vx-lib.o
obj-$(CONFIG_SND_VX222) += snd-vx-lib.o
/*
* Driver for Digigram VX soundcards
*
* DSP commands
*
* Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
*
* 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 <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/vx_core.h>
#include "vx_cmd.h"
/*
* Array of DSP commands
*/
struct vx_cmd_info vx_dsp_cmds[] = {
[CMD_VERSION] = { 0x010000, 2, RMH_SSIZE_FIXED, 1 },
[CMD_SUPPORTED] = { 0x020000, 1, RMH_SSIZE_FIXED, 2 },
[CMD_TEST_IT] = { 0x040000, 1, RMH_SSIZE_FIXED, 1 },
[CMD_SEND_IRQA] = { 0x070001, 1, RMH_SSIZE_FIXED, 0 },
[CMD_IBL] = { 0x080000, 1, RMH_SSIZE_FIXED, 4 },
[CMD_ASYNC] = { 0x0A0000, 1, RMH_SSIZE_ARG, 0 },
[CMD_RES_PIPE] = { 0x400000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_FREE_PIPE] = { 0x410000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_CONF_PIPE] = { 0x42A101, 2, RMH_SSIZE_FIXED, 0 },
[CMD_ABORT_CONF_PIPE] = { 0x42A100, 2, RMH_SSIZE_FIXED, 0 },
[CMD_PARAM_OUTPUT_PIPE] = { 0x43A000, 2, RMH_SSIZE_FIXED, 0 },
[CMD_STOP_PIPE] = { 0x470004, 1, RMH_SSIZE_FIXED, 0 },
[CMD_PIPE_STATE] = { 0x480000, 1, RMH_SSIZE_FIXED, 1 },
[CMD_PIPE_SPL_COUNT] = { 0x49A000, 2, RMH_SSIZE_FIXED, 2 },
[CMD_CAN_START_PIPE] = { 0x4b0000, 1, RMH_SSIZE_FIXED, 1 },
[CMD_SIZE_HBUFFER] = { 0x4C0000, 1, RMH_SSIZE_FIXED, 1 },
[CMD_START_STREAM] = { 0x80A000, 2, RMH_SSIZE_FIXED, 0 },
[CMD_START_ONE_STREAM] = { 0x800000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_PAUSE_STREAM] = { 0x81A000, 2, RMH_SSIZE_FIXED, 0 },
[CMD_PAUSE_ONE_STREAM] = { 0x810000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_STREAM_OUT_LEVEL_ADJUST] = { 0x828000, 2, RMH_SSIZE_FIXED, 0 },
[CMD_STOP_STREAM] = { 0x830000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_FORMAT_STREAM_OUT] = { 0x868000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_FORMAT_STREAM_IN] = { 0x878800, 1, RMH_SSIZE_FIXED, 0 },
[CMD_GET_STREAM_STATE] = { 0x890001, 2, RMH_SSIZE_FIXED, 1 },
[CMD_DROP_BYTES_AWAY] = { 0x8A8000, 2, RMH_SSIZE_FIXED, 0 },
[CMD_GET_REMAINING_BYTES] = { 0x8D0800, 1, RMH_SSIZE_FIXED, 2 },
[CMD_CONNECT_AUDIO] = { 0xC10000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_AUDIO_LEVEL_ADJUST] = { 0xC2A000, 3, RMH_SSIZE_FIXED, 0 },
[CMD_AUDIO_VU_PIC_METER] = { 0xC3A003, 2, RMH_SSIZE_FIXED, 1 },
[CMD_GET_AUDIO_LEVELS] = { 0xC4A000, 2, RMH_SSIZE_FIXED, 0 },
[CMD_GET_NOTIFY_EVENT] = { 0x4D0000, 1, RMH_SSIZE_ARG, 0 },
[CMD_INFO_NOTIFIED] = { 0x0B0000, 1, RMH_SSIZE_FIXED, 2 },
[CMD_ACCESS_IO_FCT] = { 0x098000, 1, RMH_SSIZE_ARG, 0 },
[CMD_STATUS_R_BUFFERS] = { 0x440000, 1, RMH_SSIZE_ARG, 0 },
[CMD_UPDATE_R_BUFFERS] = { 0x848000, 4, RMH_SSIZE_FIXED, 0 },
[CMD_LOAD_EFFECT_CONTEXT] = { 0x0c8000, 3, RMH_SSIZE_FIXED, 1 },
[CMD_EFFECT_ONE_PIPE] = { 0x458000, 0, RMH_SSIZE_FIXED, 0 },
[CMD_MODIFY_CLOCK] = { 0x0d0000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_STREAM1_OUT_SET_N_LEVELS] ={ 0x858000, 3, RMH_SSIZE_FIXED, 0 },
[CMD_PURGE_STREAM_DCMDS] = { 0x8b8000, 3, RMH_SSIZE_FIXED, 0 },
[CMD_NOTIFY_PIPE_TIME] = { 0x4e0000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_LOAD_EFFECT_CONTEXT_PACKET] = { 0x0c8000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_RELIC_R_BUFFER] = { 0x8e0800, 1, RMH_SSIZE_FIXED, 1 },
[CMD_RESYNC_AUDIO_INPUTS] = { 0x0e0000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_NOTIFY_STREAM_TIME] = { 0x8f0000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_STREAM_SAMPLE_COUNT] = { 0x900000, 1, RMH_SSIZE_FIXED, 2 },
[CMD_CONFIG_TIME_CODE] = { 0x050000, 2, RMH_SSIZE_FIXED, 0 },
[CMD_GET_TIME_CODE] = { 0x060000, 1, RMH_SSIZE_FIXED, 5 },
[CMD_MANAGE_SIGNAL] = { 0x0f0000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_PARAMETER_STREAM_OUT] = { 0x91A000, 3, RMH_SSIZE_FIXED, 0 },
[CMD_READ_BOARD_FREQ] = { 0x030000, 1, RMH_SSIZE_FIXED, 2 },
[CMD_GET_STREAM_LEVELS] = { 0x8c0000, 1, RMH_SSIZE_FIXED, 3 },
[CMD_PURGE_PIPE_DCMDS] = { 0x4f8000, 3, RMH_SSIZE_FIXED, 0 },
// [CMD_SET_STREAM_OUT_EFFECTS] = { 0x888000, 34, RMH_SSIZE_FIXED, 0 },
// [CMD_GET_STREAM_OUT_EFFECTS] = { 0x928000, 2, RMH_SSIZE_FIXED, 32 },
[CMD_CONNECT_MONITORING] = { 0xC00000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_STREAM2_OUT_SET_N_LEVELS] = { 0x938000, 3, RMH_SSIZE_FIXED, 0 },
[CMD_CANCEL_R_BUFFERS] = { 0x948000, 4, RMH_SSIZE_FIXED, 0 },
[CMD_NOTIFY_END_OF_BUFFER] = { 0x950000, 1, RMH_SSIZE_FIXED, 0 },
[CMD_GET_STREAM_VU_METER] = { 0x95A000, 2, RMH_SSIZE_ARG, 0 },
};
/**
* vx_init_rmh - initialize the RMH instance
* @rmh: the rmh pointer to be initialized
* @cmd: the rmh command to be set
*/
void vx_init_rmh(struct vx_rmh *rmh, unsigned int cmd)
{
snd_assert(cmd < CMD_LAST_INDEX, return);
rmh->LgCmd = vx_dsp_cmds[cmd].length;
rmh->LgStat = vx_dsp_cmds[cmd].st_length;
rmh->DspStat = vx_dsp_cmds[cmd].st_type;
rmh->Cmd[0] = vx_dsp_cmds[cmd].opcode;
}
/*
* Driver for Digigram VX soundcards
*
* Definitions of DSP commands
*
* Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
*
* 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
*/
#ifndef __VX_CMD_H
#define __VX_CMD_H
enum {
CMD_VERSION,
CMD_SUPPORTED,
CMD_TEST_IT,
CMD_SEND_IRQA,
CMD_IBL,
CMD_ASYNC,
CMD_RES_PIPE,
CMD_FREE_PIPE,
CMD_CONF_PIPE,
CMD_ABORT_CONF_PIPE,
CMD_PARAM_OUTPUT_PIPE,
CMD_STOP_PIPE,
CMD_PIPE_STATE,
CMD_PIPE_SPL_COUNT,
CMD_CAN_START_PIPE,
CMD_SIZE_HBUFFER,
CMD_START_STREAM,
CMD_START_ONE_STREAM,
CMD_PAUSE_STREAM,
CMD_PAUSE_ONE_STREAM,
CMD_STREAM_OUT_LEVEL_ADJUST,
CMD_STOP_STREAM,
CMD_FORMAT_STREAM_OUT,
CMD_FORMAT_STREAM_IN,
CMD_GET_STREAM_STATE,
CMD_DROP_BYTES_AWAY,
CMD_GET_REMAINING_BYTES,
CMD_CONNECT_AUDIO,
CMD_AUDIO_LEVEL_ADJUST,
CMD_AUDIO_VU_PIC_METER,
CMD_GET_AUDIO_LEVELS,
CMD_GET_NOTIFY_EVENT,
CMD_INFO_NOTIFIED,
CMD_ACCESS_IO_FCT,
CMD_STATUS_R_BUFFERS,
CMD_UPDATE_R_BUFFERS,
CMD_LOAD_EFFECT_CONTEXT,
CMD_EFFECT_ONE_PIPE,
CMD_MODIFY_CLOCK,
CMD_STREAM1_OUT_SET_N_LEVELS,
CMD_PURGE_STREAM_DCMDS,
CMD_NOTIFY_PIPE_TIME,
CMD_LOAD_EFFECT_CONTEXT_PACKET,
CMD_RELIC_R_BUFFER,
CMD_RESYNC_AUDIO_INPUTS,
CMD_NOTIFY_STREAM_TIME,
CMD_STREAM_SAMPLE_COUNT,
CMD_CONFIG_TIME_CODE,
CMD_GET_TIME_CODE,
CMD_MANAGE_SIGNAL,
CMD_PARAMETER_STREAM_OUT,
CMD_READ_BOARD_FREQ,
CMD_GET_STREAM_LEVELS,
CMD_PURGE_PIPE_DCMDS,
// CMD_SET_STREAM_OUT_EFFECTS,
// CMD_GET_STREAM_OUT_EFFECTS,
CMD_CONNECT_MONITORING,
CMD_STREAM2_OUT_SET_N_LEVELS,
CMD_CANCEL_R_BUFFERS,
CMD_NOTIFY_END_OF_BUFFER,
CMD_GET_STREAM_VU_METER,
CMD_LAST_INDEX
};
struct vx_cmd_info {
unsigned int opcode; /* command word */
int length; /* command length (in words) */
int st_type; /* status type (RMH_SSIZE_XXX) */
int st_length; /* fixed length */
};
/* Family and code op of some DSP requests. */
#define CODE_OP_PIPE_TIME 0x004e0000
#define CODE_OP_START_STREAM 0x00800000
#define CODE_OP_PAUSE_STREAM 0x00810000
#define CODE_OP_OUT_STREAM_LEVEL 0x00820000
#define CODE_OP_UPDATE_R_BUFFERS 0x00840000
#define CODE_OP_OUT_STREAM1_LEVEL_CURVE 0x00850000
#define CODE_OP_OUT_STREAM2_LEVEL_CURVE 0x00930000
#define CODE_OP_OUT_STREAM_FORMAT 0x00860000
#define CODE_OP_STREAM_TIME 0x008f0000
#define CODE_OP_OUT_STREAM_EXTRAPARAMETER 0x00910000
#define CODE_OP_OUT_AUDIO_LEVEL 0x00c20000
#define NOTIFY_LAST_COMMAND 0x00400000
/* Values for a user delay */
#define DC_DIFFERED_DELAY (1<<BIT_DIFFERED_COMMAND)
#define DC_NOTIFY_DELAY (1<<BIT_NOTIFIED_COMMAND)
#define DC_HBUFFER_DELAY (1<<BIT_TIME_RELATIVE_TO_BUFFER)
#define DC_MULTIPLE_DELAY (1<<BIT_RESERVED)
#define DC_STREAM_TIME_DELAY (1<<BIT_STREAM_TIME)
#define DC_CANCELLED_DELAY (1<<BIT_CANCELLED_COMMAND)
/* Values for tiDelayed field in TIME_INFO structure,
* and for pbPause field in PLAY_BUFFER_INFO structure
*/
#define BIT_DIFFERED_COMMAND 0
#define BIT_NOTIFIED_COMMAND 1
#define BIT_TIME_RELATIVE_TO_BUFFER 2
#define BIT_RESERVED 3
#define BIT_STREAM_TIME 4
#define BIT_CANCELLED_COMMAND 5
/* Access to the "Size" field of the response of the CMD_GET_NOTIFY_EVENT request. */
#define GET_NOTIFY_EVENT_SIZE_FIELD_MASK 0x000000ff
/* DSP commands general masks */
#define OPCODE_MASK 0x00ff0000
#define DSP_DIFFERED_COMMAND_MASK 0x0000C000
/* Notifications (NOTIFY_INFO) */
#define ALL_CMDS_NOTIFIED 0x0000 // reserved
#define START_STREAM_NOTIFIED 0x0001
#define PAUSE_STREAM_NOTIFIED 0x0002
#define OUT_STREAM_LEVEL_NOTIFIED 0x0003
#define OUT_STREAM_PARAMETER_NOTIFIED 0x0004 // left for backward compatibility
#define OUT_STREAM_FORMAT_NOTIFIED 0x0004
#define PIPE_TIME_NOTIFIED 0x0005
#define OUT_AUDIO_LEVEL_NOTIFIED 0x0006
#define OUT_STREAM_LEVEL_CURVE_NOTIFIED 0x0007
#define STREAM_TIME_NOTIFIED 0x0008
#define OUT_STREAM_EXTRAPARAMETER_NOTIFIED 0x0009
#define UNKNOWN_COMMAND_NOTIFIED 0xffff
/* Output pipe parameters setting */
#define MASK_VALID_PIPE_MPEG_PARAM 0x000040
#define MASK_VALID_PIPE_BACKWARD_PARAM 0x000020
#define MASK_SET_PIPE_MPEG_PARAM 0x000002
#define MASK_SET_PIPE_BACKWARD_PARAM 0x000001
#define MASK_DSP_WORD 0x00FFFFFF
#define MASK_ALL_STREAM 0x00FFFFFF
#define MASK_DSP_WORD_LEVEL 0x000001FF
#define MASK_FIRST_FIELD 0x0000001F
#define FIELD_SIZE 5
#define COMMAND_RECORD_MASK 0x000800
/* PipeManagement definition bits (PIPE_DECL_INFO) */
#define P_UNDERRUN_SKIP_SOUND_MASK 0x01
#define P_PREPARE_FOR_MPEG3_MASK 0x02
#define P_DO_NOT_RESET_ANALOG_LEVELS 0x04
#define P_ALLOW_UNDER_ALLOCATION_MASK 0x08
#define P_DATA_MODE_MASK 0x10
#define P_ASIO_BUFFER_MANAGEMENT_MASK 0x20
#define BIT_SKIP_SOUND 0x08 // bit 3
#define BIT_DATA_MODE 0x10 // bit 4
/* Bits in the CMD_MODIFY_CLOCK request. */
#define CMD_MODIFY_CLOCK_FD_BIT 0x00000001
#define CMD_MODIFY_CLOCK_T_BIT 0x00000002
#define CMD_MODIFY_CLOCK_S_BIT 0x00000004
/* Access to the results of the CMD_GET_TIME_CODE RMH. */
#define TIME_CODE_V_MASK 0x00800000
#define TIME_CODE_N_MASK 0x00400000
#define TIME_CODE_B_MASK 0x00200000
#define TIME_CODE_W_MASK 0x00100000
/* Values for the CMD_MANAGE_SIGNAL RMH. */
#define MANAGE_SIGNAL_TIME_CODE 0x01
#define MANAGE_SIGNAL_MIDI 0x02
/* Values for the CMD_CONFIG_TIME_CODE RMH. */
#define CONFIG_TIME_CODE_CANCEL 0x00001000
/* Mask to get only the effective time from the
* high word out of the 2 returned by the DSP
*/
#define PCX_TIME_HI_MASK 0x000fffff
/* Values for setting a H-Buffer time */
#define HBUFFER_TIME_HIGH 0x00200000
#define HBUFFER_TIME_LOW 0x00000000
#define NOTIFY_MASK_TIME_HIGH 0x00400000
#define MULTIPLE_MASK_TIME_HIGH 0x00100000
#define STREAM_MASK_TIME_HIGH 0x00800000
/*
*
*/
extern struct vx_cmd_info vx_dsp_cmds[];
void vx_init_rmh(struct vx_rmh *rmh, unsigned int cmd);
/**
* vx_send_pipe_cmd_params - fill first command word for pipe commands
* @rmh: the rmh to be modified
* @is_capture: 0 = playback, 1 = capture operation
* @param1: first pipe-parameter
* @param2: second pipe-parameter
*/
static inline void vx_set_pipe_cmd_params(struct vx_rmh *rmh, int is_capture,
int param1, int param2)
{
if (is_capture)
rmh->Cmd[0] |= COMMAND_RECORD_MASK;
rmh->Cmd[0] |= (((u32)param1 & MASK_FIRST_FIELD) << FIELD_SIZE) & MASK_DSP_WORD;
if (param2)
rmh->Cmd[0] |= ((u32)param2 & MASK_FIRST_FIELD) & MASK_DSP_WORD;
}
/**
* vx_set_stream_cmd_params - fill first command word for stream commands
* @rmh: the rmh to be modified
* @is_capture: 0 = playback, 1 = capture operation
* @pipe: the pipe index (zero-based)
*/
static inline void vx_set_stream_cmd_params(struct vx_rmh *rmh, int is_capture, int pipe)
{
if (is_capture)
rmh->Cmd[0] |= COMMAND_RECORD_MASK;
rmh->Cmd[0] |= (((u32)pipe & MASK_FIRST_FIELD) << FIELD_SIZE) & MASK_DSP_WORD;
}
#endif /* __VX_CMD_H */
This diff is collapsed.
/*
* Driver for Digigram VX soundcards
*
* hwdep device manager
*
* Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
*
* 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 <sound/driver.h>
#include <sound/core.h>
#include <sound/hwdep.h>
#include <sound/vx_core.h>
static int vx_hwdep_open(snd_hwdep_t *hw, struct file *file)
{
return 0;
}
static int vx_hwdep_release(snd_hwdep_t *hw, struct file *file)
{
return 0;
}
static int vx_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
{
static char *type_ids[VX_TYPE_NUMS] = {
[VX_TYPE_BOARD] = "vxboard",
[VX_TYPE_V2] = "vx222",
[VX_TYPE_MIC] = "vx222",
[VX_TYPE_VXPOCKET] = "vxpocket",
[VX_TYPE_VXP440] = "vxp440",
};
vx_core_t *vx = snd_magic_cast(vx_core_t, hw->private_data, return -ENXIO);
snd_assert(type_ids[vx->type], return -EINVAL);
strcpy(info->id, type_ids[vx->type]);
if (vx_is_pcmcia(vx))
info->num_dsps = 4;
else
info->num_dsps = 3;
if (vx->chip_status & VX_STAT_CHIP_INIT)
info->chip_ready = 1;
info->version = VX_DRIVER_VERSION;
return 0;
}
static int vx_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
{
vx_core_t *vx = snd_magic_cast(vx_core_t, hw->private_data, return -ENXIO);
int index, err;
snd_assert(vx->ops->load_dsp, return -ENXIO);
err = vx->ops->load_dsp(vx, dsp);
if (err < 0)
return err;
index = dsp->index;
if (! vx_is_pcmcia(vx))
index++;
if (index == 1)
vx->chip_status |= VX_STAT_XILINX_LOADED;
if (index < 3)
return 0;
/* ok, we reached to the last one */
/* create the devices if not built yet */
if (! (vx->chip_status & VX_STAT_DEVICE_INIT)) {
if ((err = snd_vx_pcm_new(vx)) < 0)
return err;
if ((err = snd_vx_mixer_new(vx)) < 0)
return err;
if (vx->ops->add_controls)
if ((err = vx->ops->add_controls(vx)) < 0)
return err;
if ((err = snd_card_register(vx->card)) < 0)
return err;
vx->chip_status |= VX_STAT_DEVICE_INIT;
}
vx->chip_status |= VX_STAT_CHIP_INIT;
return 0;
}
/* exported */
int snd_vx_hwdep_new(vx_core_t *chip)
{
int err;
snd_hwdep_t *hw;
if ((err = snd_hwdep_new(chip->card, SND_VX_HWDEP_ID, 0, &hw)) < 0)
return err;
hw->iface = SNDRV_HWDEP_IFACE_VX;
hw->private_data = chip;
hw->ops.open = vx_hwdep_open;
hw->ops.release = vx_hwdep_release;
hw->ops.dsp_status = vx_hwdep_dsp_status;
hw->ops.dsp_load = vx_hwdep_dsp_load;
hw->exclusive = 1;
sprintf(hw->name, "VX Loader (%s)", chip->card->driver);
chip->hwdep = hw;
return 0;
}
This diff is collapsed.
This diff is collapsed.
/*
* Driver for Digigram VX soundcards
*
* IEC958 stuff
*
* Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
*
* 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 <sound/driver.h>
#include <linux/delay.h>
#include <sound/core.h>
#include <sound/vx_core.h>
#include "vx_cmd.h"
/*
* vx_modify_board_clock - tell the board that its clock has been modified
* @sync: DSP needs to resynchronize its FIFO
*/
static int vx_modify_board_clock(vx_core_t *chip, int sync)
{
struct vx_rmh rmh;
vx_init_rmh(&rmh, CMD_MODIFY_CLOCK);
/* Ask the DSP to resynchronize its FIFO. */
if (sync)
rmh.Cmd[0] |= CMD_MODIFY_CLOCK_S_BIT;
return vx_send_msg(chip, &rmh);
}
/*
* vx_modify_board_inputs - resync audio inputs
*/
static int vx_modify_board_inputs(vx_core_t *chip)
{
struct vx_rmh rmh;
vx_init_rmh(&rmh, CMD_RESYNC_AUDIO_INPUTS);
rmh.Cmd[0] |= 1 << 0; /* reference: AUDIO 0 */
return vx_send_msg(chip, &rmh);
}
/*
* vx_read_one_cbit - read one bit from UER config
* @index: the bit index
* returns 0 or 1.
*/
static int vx_read_one_cbit(vx_core_t *chip, int index)
{
unsigned long flags;
int val;
spin_lock_irqsave(&chip->lock, flags);
if (chip->type >= VX_TYPE_VXPOCKET) {
vx_outb(chip, CSUER, 1); /* read */
vx_outb(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK);
val = (vx_inb(chip, RUER) >> 7) & 0x01;
} else {
vx_outl(chip, CSUER, 1); /* read */
vx_outl(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK);
val = (vx_inl(chip, RUER) >> 7) & 0x01;
}
spin_unlock_irqrestore(&chip->lock, flags);
return val;
}
/*
* vx_write_one_cbit - write one bit to UER config
* @index: the bit index
* @val: bit value, 0 or 1
*/
static void vx_write_one_cbit(vx_core_t *chip, int index, int val)
{
unsigned long flags;
val = !!val; /* 0 or 1 */
spin_lock_irqsave(&chip->lock, flags);
if (vx_is_pcmcia(chip)) {
vx_outb(chip, CSUER, 0); /* write */
vx_outb(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK));
} else {
vx_outl(chip, CSUER, 0); /* write */
vx_outl(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK));
}
spin_unlock_irqrestore(&chip->lock, flags);
}
/*
* vx_read_uer_status - read the current UER status
* @mode: pointer to store the UER mode, VX_UER_MODE_XXX
*
* returns the frequency of UER, or 0 if not sync,
* or a negative error code.
*/
static int vx_read_uer_status(vx_core_t *chip, int *mode)
{
int val, freq;
/* Default values */
freq = 0;
/* Read UER status */
if (vx_is_pcmcia(chip))
val = vx_inb(chip, CSUER);
else
val = vx_inl(chip, CSUER);
if (val < 0)
return val;
/* If clock is present, read frequency */
if (val & VX_SUER_CLOCK_PRESENT_MASK) {
switch (val & VX_SUER_FREQ_MASK) {
case VX_SUER_FREQ_32KHz_MASK:
freq = 32000;
break;
case VX_SUER_FREQ_44KHz_MASK:
freq = 44100;
break;
case VX_SUER_FREQ_48KHz_MASK:
freq = 48000;
break;
}
}
if (val & VX_SUER_DATA_PRESENT_MASK)
/* bit 0 corresponds to consumer/professional bit */
*mode = vx_read_one_cbit(chip, 0) ?
VX_UER_MODE_PROFESSIONAL : VX_UER_MODE_CONSUMER;
else
*mode = VX_UER_MODE_NOT_PRESENT;
return freq;
}
/*
* compute the sample clock value from frequency
*
* The formula is as follows:
*
* HexFreq = (dword) ((double) ((double) 28224000 / (double) Frequency))
* switch ( HexFreq & 0x00000F00 )
* case 0x00000100: ;
* case 0x00000200:
* case 0x00000300: HexFreq -= 0x00000201 ;
* case 0x00000400:
* case 0x00000500:
* case 0x00000600:
* case 0x00000700: HexFreq = (dword) (((double) 28224000 / (double) (Frequency*2)) - 1)
* default : HexFreq = (dword) ((double) 28224000 / (double) (Frequency*4)) - 0x000001FF
*/
static int vx_calc_clock_from_freq(vx_core_t *chip, int freq)
{
#define XX_FECH48000 0x0000004B
#define XX_FECH32000 0x00000171
#define XX_FECH24000 0x0000024B
#define XX_FECH16000 0x00000371
#define XX_FECH12000 0x0000044B
#define XX_FECH8000 0x00000571
#define XX_FECH44100 0x0000007F
#define XX_FECH29400 0x0000016F
#define XX_FECH22050 0x0000027F
#define XX_FECH14000 0x000003EF
#define XX_FECH11025 0x0000047F
#define XX_FECH7350 0x000005BF
switch (freq) {
case 48000: return XX_FECH48000;
case 44100: return XX_FECH44100;
case 32000: return XX_FECH32000;
case 29400: return XX_FECH29400;
case 24000: return XX_FECH24000;
case 22050: return XX_FECH22050;
case 16000: return XX_FECH16000;
case 14000: return XX_FECH14000;
case 12000: return XX_FECH12000;
case 11025: return XX_FECH11025;
case 8000: return XX_FECH8000;
case 7350: return XX_FECH7350;
default: return freq; /* The value is already correct */
}
}
/*
* vx_change_clock_source - change the clock source
* @source: the new source
*/
void vx_change_clock_source(vx_core_t *chip, int source)
{
unsigned long flags;
/* we mute DAC to prevent clicks */
vx_toggle_dac_mute(chip, 1);
spin_lock_irqsave(&chip->lock, flags);
chip->ops->set_clock_source(chip, source);
chip->clock_source = source;
spin_unlock_irqrestore(&chip->lock, flags);
/* unmute */
vx_toggle_dac_mute(chip, 0);
}
/*
* set the internal clock
*/
void vx_set_internal_clock(vx_core_t *chip, unsigned int freq)
{
int clock;
unsigned long flags;
/* Get real clock value */
clock = vx_calc_clock_from_freq(chip, freq);
snd_printdd(KERN_DEBUG "set internal clock to 0x%x from freq %d\n", clock, freq);
spin_lock_irqsave(&chip->lock, flags);
if (vx_is_pcmcia(chip)) {
vx_outb(chip, HIFREQ, (clock >> 8) & 0x0f);
vx_outb(chip, LOFREQ, clock & 0xff);
} else {
vx_outl(chip, HIFREQ, (clock >> 8) & 0x0f);
vx_outl(chip, LOFREQ, clock & 0xff);
}
spin_unlock_irqrestore(&chip->lock, flags);
}
/*
* set the iec958 status bits
* @bits: 32-bit status bits
*/
void vx_set_iec958_status(vx_core_t *chip, unsigned int bits)
{
int i;
if (chip->chip_status & VX_STAT_IS_STALE)
return;
for (i = 0; i < 32; i++)
vx_write_one_cbit(chip, i, bits & (1 << i));
}
/*
* vx_set_clock - change the clock and audio source if necessary
*/
int vx_set_clock(vx_core_t *chip, unsigned int freq)
{
int src_changed = 0;
if (chip->chip_status & VX_STAT_IS_STALE)
return 0;
/* change the audio source if possible */
vx_sync_audio_source(chip);
switch (chip->audio_source) {
case VX_AUDIO_SRC_DIGITAL:
if (chip->clock_source != UER_SYNC) {
vx_change_clock_source(chip, UER_SYNC);
mdelay(6);
src_changed = 1;
}
if (chip->freq == freq)
return 0;
break;
default:
if (chip->clock_source != INTERNAL_QUARTZ) {
vx_change_clock_source(chip, INTERNAL_QUARTZ);
src_changed = 1;
}
if (chip->freq == freq)
return 0;
vx_set_internal_clock(chip, freq);
if (src_changed)
vx_modify_board_inputs(chip);
break;
}
chip->freq = freq;
vx_modify_board_clock(chip, 1);
return 0;
}
/*
* vx_change_frequency - called from interrupt handler
*/
int vx_change_frequency(vx_core_t *chip)
{
int freq;
if (chip->chip_status & VX_STAT_IS_STALE)
return 0;
if (chip->clock_source == INTERNAL_QUARTZ)
return 0;
/*
* Read the real UER board frequency
*/
freq = vx_read_uer_status(chip, &chip->uer_detected);
if (freq < 0)
return freq;
/*
* The frequency computed by the DSP is good and
* is different from the previous computed.
*/
if (freq == 48000 || freq == 44100 || freq == 32000)
chip->freq_detected = freq;
return 0;
}
...@@ -43,10 +43,8 @@ ...@@ -43,10 +43,8 @@
#endif /* CS4231 */ #endif /* CS4231 */
#include <sound/mpu401.h> #include <sound/mpu401.h>
#include <sound/opl3.h> #include <sound/opl3.h>
#ifdef USE_OPL4
#ifndef OPTi93X #ifndef OPTi93X
#include "opl4.h" /* <sound/opl4.h> */ #include <sound/opl4.h>
#endif
#endif #endif
#define SNDRV_LEGACY_FIND_FREE_IRQ #define SNDRV_LEGACY_FIND_FREE_IRQ
#define SNDRV_LEGACY_FIND_FREE_DMA #define SNDRV_LEGACY_FIND_FREE_DMA
...@@ -2105,7 +2103,6 @@ static int __devinit snd_card_opti9xx_probe(struct pnp_card_link *pcard, ...@@ -2105,7 +2103,6 @@ static int __devinit snd_card_opti9xx_probe(struct pnp_card_link *pcard,
if (chip->fm_port > 0) { if (chip->fm_port > 0) {
opl3_t *opl3 = NULL; opl3_t *opl3 = NULL;
#ifdef USE_OPL4
#ifndef OPTi93X #ifndef OPTi93X
if (chip->hardware == OPTi9XX_HW_82C928 || if (chip->hardware == OPTi9XX_HW_82C928 ||
chip->hardware == OPTi9XX_HW_82C929 || chip->hardware == OPTi9XX_HW_82C929 ||
...@@ -2124,7 +2121,6 @@ static int __devinit snd_card_opti9xx_probe(struct pnp_card_link *pcard, ...@@ -2124,7 +2121,6 @@ static int __devinit snd_card_opti9xx_probe(struct pnp_card_link *pcard,
} }
} }
#endif /* !OPTi93X */ #endif /* !OPTi93X */
#endif
if (!opl3 && snd_opl3_create(card, if (!opl3 && snd_opl3_create(card,
chip->fm_port, chip->fm_port,
chip->fm_port + 2, chip->fm_port + 2,
......
...@@ -1221,7 +1221,7 @@ static int __devinit create_sscape(const struct params *params, snd_card_t **rca ...@@ -1221,7 +1221,7 @@ static int __devinit create_sscape(const struct params *params, snd_card_t **rca
printk(KERN_ERR "sscape: Failed to create firmware device\n"); printk(KERN_ERR "sscape: Failed to create firmware device\n");
goto _release_card; goto _release_card;
} }
strncpy(sscape->hw->name, "SoundScape M68K", sizeof(sscape->hw->name) - 1); strlcpy(sscape->hw->name, "SoundScape M68K", sizeof(sscape->hw->name));
sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0'; sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0';
sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE; sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE;
sscape->hw->ops.open = sscape_hw_open; sscape->hw->ops.open = sscape_hw_open;
......
# ALSA PA-RISC drivers
menu "ALSA PA-RISC devices"
depends on SND!=n && PARISC
config SND_HARMONY
tristate "Harmony/Vivace sound chip"
depends on SND
help
Say 'Y' or 'M' to include support for Harmony/Vivace soundchip
on HP712s, 715/new and many other GSC based machines.
endmenu
#
# Makefile for ALSA
#
snd-harmony-objs := harmony.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_HARMONY) += snd-harmony.o
This diff is collapsed.
...@@ -177,5 +177,11 @@ config SND_VIA82XX ...@@ -177,5 +177,11 @@ config SND_VIA82XX
help help
Say 'Y' or 'M' to include support for VIA VT82C686A/B, VT8233 South Bridge. Say 'Y' or 'M' to include support for VIA VT82C686A/B, VT8233 South Bridge.
config SND_VX222
tristate "Digigram VX222"
depends on SND
help
Say 'Y' or 'M' to include support for Digigram VX222 soundcards
endmenu endmenu
...@@ -34,4 +34,4 @@ obj-$(CONFIG_SND_RME96) += snd-rme96.o ...@@ -34,4 +34,4 @@ obj-$(CONFIG_SND_RME96) += snd-rme96.o
obj-$(CONFIG_SND_SONICVIBES) += snd-sonicvibes.o obj-$(CONFIG_SND_SONICVIBES) += snd-sonicvibes.o
obj-$(CONFIG_SND_VIA82XX) += snd-via82xx.o obj-$(CONFIG_SND_VIA82XX) += snd-via82xx.o
obj-$(CONFIG_SND) += ac97/ ali5451/ cs46xx/ emu10k1/ korg1212/ nm256/ rme9652/ trident/ ymfpci/ ice1712/ obj-$(CONFIG_SND) += ac97/ ali5451/ cs46xx/ emu10k1/ korg1212/ nm256/ rme9652/ trident/ ymfpci/ ice1712/ vx222/
...@@ -89,7 +89,6 @@ static const ac97_codec_id_t snd_ac97_codec_id_vendors[] = { ...@@ -89,7 +89,6 @@ static const ac97_codec_id_t snd_ac97_codec_id_vendors[] = {
}; };
static const ac97_codec_id_t snd_ac97_codec_ids[] = { static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x014b0502, 0xffffffff, "NM256AV", NULL, NULL }, // FIXME: which real one?
{ 0x414b4d00, 0xffffffff, "AK4540", NULL, NULL }, { 0x414b4d00, 0xffffffff, "AK4540", NULL, NULL },
{ 0x414b4d01, 0xffffffff, "AK4542", NULL, NULL }, { 0x414b4d01, 0xffffffff, "AK4542", NULL, NULL },
{ 0x414b4d02, 0xffffffff, "AK4543", NULL, NULL }, { 0x414b4d02, 0xffffffff, "AK4543", NULL, NULL },
...@@ -2105,13 +2104,14 @@ int snd_ac97_mixer(snd_card_t * card, ac97_t * _ac97, ac97_t ** rac97) ...@@ -2105,13 +2104,14 @@ int snd_ac97_mixer(snd_card_t * card, ac97_t * _ac97, ac97_t ** rac97)
if (! (ac97->scaps & AC97_SCAP_AUDIO)) { if (! (ac97->scaps & AC97_SCAP_AUDIO)) {
/* test if we can write to the record gain volume register */ /* test if we can write to the record gain volume register */
snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a06); snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a06);
if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a06) { if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a06)
ac97->scaps |= AC97_SCAP_AUDIO; ac97->scaps |= AC97_SCAP_AUDIO;
ac97->caps = snd_ac97_read(ac97, AC97_RESET); }
ac97->ext_id = snd_ac97_read(ac97, AC97_EXTENDED_ID); if (ac97->scaps & AC97_SCAP_AUDIO) {
if (ac97->ext_id == 0xffff) /* invalid combination */ ac97->caps = snd_ac97_read(ac97, AC97_RESET);
ac97->ext_id = 0; ac97->ext_id = snd_ac97_read(ac97, AC97_EXTENDED_ID);
} if (ac97->ext_id == 0xffff) /* invalid combination */
ac97->ext_id = 0;
} }
/* test for MC'97 */ /* test for MC'97 */
......
...@@ -2204,7 +2204,7 @@ static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info) ...@@ -2204,7 +2204,7 @@ static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info)
unsigned short fxbus_mask, extin_mask, extout_mask; unsigned short fxbus_mask, extin_mask, extout_mask;
int res; int res;
memset(info, 0, sizeof(*info)); memset(info, 0, sizeof(info));
info->card = emu->card_type; info->card = emu->card_type;
info->internal_tram_size = emu->fx8010.itram_size; info->internal_tram_size = emu->fx8010.itram_size;
info->external_tram_size = emu->fx8010.etram_size; info->external_tram_size = emu->fx8010.etram_size;
......
...@@ -230,8 +230,9 @@ struct snd_nm256 { ...@@ -230,8 +230,9 @@ struct snd_nm256 {
u32 all_coeff_buf; /* coefficient buffer */ u32 all_coeff_buf; /* coefficient buffer */
u32 coeff_buf[2]; /* coefficient buffer for each stream */ u32 coeff_buf[2]; /* coefficient buffer for each stream */
int coeffs_current; /* coeff. table is loaded? */ unsigned int coeffs_current: 1; /* coeff. table is loaded? */
int use_cache; /* use one big coef. table */ unsigned int use_cache: 1; /* use one big coef. table */
unsigned int latitude_workaround: 1; /* Dell Latitude LS workaround needed */
int mixer_base; /* register offset of ac97 mixer */ int mixer_base; /* register offset of ac97 mixer */
int mixer_status_offset; /* offset of mixer status reg. */ int mixer_status_offset; /* offset of mixer status reg. */
...@@ -1181,9 +1182,10 @@ snd_nm256_ac97_reset(ac97_t *ac97) ...@@ -1181,9 +1182,10 @@ snd_nm256_ac97_reset(ac97_t *ac97)
spin_lock_irqsave(&chip->reg_lock, flags); spin_lock_irqsave(&chip->reg_lock, flags);
/* Reset the mixer. 'Tis magic! */ /* Reset the mixer. 'Tis magic! */
snd_nm256_writeb(chip, 0x6c0, 1); snd_nm256_writeb(chip, 0x6c0, 1);
#if 0 /* Dell latitude LS will lock up by this */ if (chip->latitude_workaround) {
snd_nm256_writeb(chip, 0x6cc, 0x87); /* Dell latitude LS will lock up by this */
#endif snd_nm256_writeb(chip, 0x6cc, 0x87);
}
snd_nm256_writeb(chip, 0x6cc, 0x80); snd_nm256_writeb(chip, 0x6cc, 0x80);
snd_nm256_writeb(chip, 0x6cc, 0x0); snd_nm256_writeb(chip, 0x6cc, 0x0);
spin_unlock_irqrestore(&chip->reg_lock, flags); spin_unlock_irqrestore(&chip->reg_lock, flags);
...@@ -1194,7 +1196,7 @@ static int __devinit ...@@ -1194,7 +1196,7 @@ static int __devinit
snd_nm256_mixer(nm256_t *chip) snd_nm256_mixer(nm256_t *chip)
{ {
ac97_t ac97; ac97_t ac97;
int i; int i, err;
/* looks like nm256 hangs up when unexpected registers are touched... */ /* looks like nm256 hangs up when unexpected registers are touched... */
static int mixer_regs[] = { static int mixer_regs[] = {
AC97_MASTER, AC97_HEADPHONE, AC97_MASTER_MONO, AC97_MASTER, AC97_HEADPHONE, AC97_MASTER_MONO,
...@@ -1215,7 +1217,14 @@ snd_nm256_mixer(nm256_t *chip) ...@@ -1215,7 +1217,14 @@ snd_nm256_mixer(nm256_t *chip)
for (i = 0; mixer_regs[i] >= 0; i++) for (i = 0; mixer_regs[i] >= 0; i++)
set_bit(mixer_regs[i], ac97.reg_accessed); set_bit(mixer_regs[i], ac97.reg_accessed);
ac97.private_data = chip; ac97.private_data = chip;
return snd_ac97_mixer(chip->card, &ac97, &chip->ac97); err = snd_ac97_mixer(chip->card, &ac97, &chip->ac97);
if (err < 0)
return err;
if (! (chip->ac97->id & (0xf0000000))) {
/* looks like an invalid id */
sprintf(chip->card->mixername, "%s AC97", chip->card->driver);
}
return 0;
} }
/* /*
...@@ -1395,6 +1404,7 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci, ...@@ -1395,6 +1404,7 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci,
.dev_free = snd_nm256_dev_free, .dev_free = snd_nm256_dev_free,
}; };
u32 addr; u32 addr;
u16 subsystem_vendor, subsystem_device;
*chip_ret = NULL; *chip_ret = NULL;
...@@ -1531,6 +1541,15 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci, ...@@ -1531,6 +1541,15 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci,
chip->coeffs_current = 0; chip->coeffs_current = 0;
/* check workarounds */
chip->latitude_workaround = 1;
pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
if (subsystem_vendor == 0x104d && subsystem_device == 0x8041) {
/* this workaround will cause lock-up after suspend/resume on Sony PCG-F305 */
chip->latitude_workaround = 0;
}
snd_nm256_init_chip(chip); snd_nm256_init_chip(chip);
if ((err = snd_nm256_pcm(chip, 0)) < 0) if ((err = snd_nm256_pcm(chip, 0)) < 0)
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
$Id: hammerfall_mem.c,v 1.8 2003/02/25 13:35:44 perex Exp $ $Id: hammerfall_mem.c,v 1.9 2003/05/31 11:33:57 perex Exp $
Tue Oct 17 2000 Jaroslav Kysela <perex@suse.cz> Tue Oct 17 2000 Jaroslav Kysela <perex@suse.cz>
...@@ -98,15 +98,7 @@ static void *hammerfall_malloc_pages(struct pci_dev *pci, ...@@ -98,15 +98,7 @@ static void *hammerfall_malloc_pages(struct pci_dev *pci,
{ {
void *res; void *res;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 3, 0)
res = (void *) pci_alloc_consistent(pci, size, dmaaddr); res = (void *) pci_alloc_consistent(pci, size, dmaaddr);
#else
int pg;
for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
res = (void *)__get_free_pages(GFP_KERNEL, pg);
if (res != NULL)
*dmaaddr = virt_to_bus(res);
#endif
if (res != NULL) { if (res != NULL) {
struct page *page = virt_to_page(res); struct page *page = virt_to_page(res);
struct page *last_page = page + (size + PAGE_SIZE - 1) / PAGE_SIZE; struct page *last_page = page + (size + PAGE_SIZE - 1) / PAGE_SIZE;
...@@ -127,19 +119,7 @@ static void hammerfall_free_pages(struct pci_dev *pci, unsigned long size, ...@@ -127,19 +119,7 @@ static void hammerfall_free_pages(struct pci_dev *pci, unsigned long size,
last_page = virt_to_page(ptr) + (size + PAGE_SIZE - 1) / PAGE_SIZE; last_page = virt_to_page(ptr) + (size + PAGE_SIZE - 1) / PAGE_SIZE;
while (page < last_page) while (page < last_page)
clear_bit(PG_reserved, &(page++)->flags); clear_bit(PG_reserved, &(page++)->flags);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 3, 0)
pci_free_consistent(pci, size, ptr, dmaaddr); pci_free_consistent(pci, size, ptr, dmaaddr);
#else
{
int pg;
for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
if (bus_to_virt(dmaaddr) != ptr) {
printk(KERN_ERR "hammerfall_free_pages: dmaaddr != ptr\n");
return;
}
free_pages((unsigned long)ptr, pg);
}
#endif
} }
void *snd_hammerfall_get_buffer (struct pci_dev *pcidev, dma_addr_t *dmaaddr) void *snd_hammerfall_get_buffer (struct pci_dev *pcidev, dma_addr_t *dmaaddr)
......
#
# Makefile for ALSA
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
#
snd-vx222-objs := vx222.o vx222_ops.o
obj-$(CONFIG_SND_VX222) += snd-vx222.o
This diff is collapsed.
/*
* Driver for Digigram VX222 PCI soundcards
*
* Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
*
* 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
*/
#ifndef __VX222_H
#define __VX222_H
#include <sound/vx_core.h>
struct snd_vx222 {
vx_core_t core;
/* h/w config; for PLX and for DSP */
unsigned long port[2];
struct resource *port_res[2];
unsigned int regCDSP; /* current CDSP register */
unsigned int regCFG; /* current CFG register */
unsigned int regSELMIC; /* current SELMIC reg. (for VX222 Mic) */
int input_level[2]; /* input level for vx222 mic */
int mic_level; /* mic level for vx222 mic */
};
/* we use a lookup table with 148 values, see vx_mixer.c */
#define VX2_AKM_LEVEL_MAX 0x93
extern struct snd_vx_ops vx222_ops;
extern struct snd_vx_ops vx222_old_ops;
/* Offset of registers with base equal to portDSP. */
#define VX_RESET_DMA_REGISTER_OFFSET 0x00000008
/* Constants used to access the INTCSR register. */
#define VX_INTCSR_VALUE 0x00000001
#define VX_PCI_INTERRUPT_MASK 0x00000040
/* Constants used to access the CDSP register (0x20). */
#define VX_CDSP_TEST1_MASK 0x00000080
#define VX_CDSP_TOR1_MASK 0x00000040
#define VX_CDSP_TOR2_MASK 0x00000020
#define VX_CDSP_RESERVED0_0_MASK 0x00000010
#define VX_CDSP_CODEC_RESET_MASK 0x00000008
#define VX_CDSP_VALID_IRQ_MASK 0x00000004
#define VX_CDSP_TEST0_MASK 0x00000002
#define VX_CDSP_DSP_RESET_MASK 0x00000001
#define VX_CDSP_GPIO_OUT_MASK 0x00000060
#define VX_GPIO_OUT_BIT_OFFSET 5 // transform output to bit 0 and 1
/* Constants used to access the CFG register (0x24). */
#define VX_CFG_SYNCDSP_MASK 0x00000080
#define VX_CFG_RESERVED0_0_MASK 0x00000040
#define VX_CFG_RESERVED1_0_MASK 0x00000020
#define VX_CFG_RESERVED2_0_MASK 0x00000010
#define VX_CFG_DATAIN_SEL_MASK 0x00000008 // 0 (ana), 1 (UER)
#define VX_CFG_RESERVED3_0_MASK 0x00000004
#define VX_CFG_RESERVED4_0_MASK 0x00000002
#define VX_CFG_CLOCKIN_SEL_MASK 0x00000001 // 0 (internal), 1 (AES/EBU)
/* Constants used to access the STATUS register (0x30). */
#define VX_STATUS_DATA_XICOR_MASK 0x00000080
#define VX_STATUS_VAL_TEST1_MASK 0x00000040
#define VX_STATUS_VAL_TEST0_MASK 0x00000020
#define VX_STATUS_RESERVED0_MASK 0x00000010
#define VX_STATUS_VAL_TOR1_MASK 0x00000008
#define VX_STATUS_VAL_TOR0_MASK 0x00000004
#define VX_STATUS_LEVEL_IN_MASK 0x00000002 // 6 dBu (0), 22 dBu (1)
#define VX_STATUS_MEMIRQ_MASK 0x00000001
#define VX_STATUS_GPIO_IN_MASK 0x0000000C
#define VX_GPIO_IN_BIT_OFFSET 0 // leave input as bit 2 and 3
/* Constants used to access the MICRO INPUT SELECT register (0x40). */
#define MICRO_SELECT_INPUT_NORM 0x00
#define MICRO_SELECT_INPUT_MUTE 0x01
#define MICRO_SELECT_INPUT_LIMIT 0x02
#define MICRO_SELECT_INPUT_MASK 0x03
#define MICRO_SELECT_PREAMPLI_G_0 0x00
#define MICRO_SELECT_PREAMPLI_G_1 0x04
#define MICRO_SELECT_PREAMPLI_G_2 0x08
#define MICRO_SELECT_PREAMPLI_G_3 0x0C
#define MICRO_SELECT_PREAMPLI_MASK 0x0C
#define MICRO_SELECT_PREAMPLI_OFFSET 2
#define MICRO_SELECT_RAISE_COMPR 0x10
#define MICRO_SELECT_NOISE_T_52DB 0x00
#define MICRO_SELECT_NOISE_T_42DB 0x20
#define MICRO_SELECT_NOISE_T_32DB 0x40
#define MICRO_SELECT_NOISE_T_MASK 0x60
#define MICRO_SELECT_PHANTOM_ALIM 0x80
#endif /* __VX222_H */
This diff is collapsed.
# ALSA PCMCIA drivers
menu "PCMCIA devices"
depends on SND!=n && PCMCIA
config SND_VXPOCKET
tristate "Digigram VXpocket"
depends on SND && PCMCIA
help
Say 'Y' or 'M' to include support for Digigram VXpocket soundcard.
config SND_VXP440
tristate "Digigram VXpocket 440"
depends on SND && PCMCIA
help
Say 'Y' or 'M' to include support for Digigram VXpocket 440 soundcard.
endmenu
#
# Makefile for ALSA
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
#
obj-$(CONFIG_SND) += vx/
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment