Commit a58bec86 authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA update

  - control API - replace global control lock with semaphore
  - ac97 - added VT1616 support
  - add code for PC98 architecture
  - ENS1370/1371 - added gameport code
  - HDSP - fixed oops when device is not detected
  - replace __SMP__ with CONFIG_SMP

parent 91fd73cd
......@@ -199,6 +199,10 @@
#define AC97_ALC650_MULTICH 0x6a
#define AC97_ALC650_CLOCK 0x7a
/* specific - Yamaha YMF753 */
#define AC97_YMF753_DIT_CTRL2 0x66 /* DIT Control 2 */
#define AC97_YMF753_3D_MODE_SEL 0x68 /* 3D Mode Select */
/* ac97->scaps */
#define AC97_SCAP_AUDIO (1<<0) /* audio AC'97 codec */
#define AC97_SCAP_MODEM (1<<1) /* modem AC'97 codec */
......
......@@ -24,6 +24,7 @@
#include <linux/sched.h> /* wake_up() */
#include <asm/semaphore.h> /* struct semaphore */
#include <linux/rwsem.h> /* struct rw_semaphore */
/* Typedef's */
typedef struct timeval snd_timestamp_t;
......@@ -141,8 +142,8 @@ struct _snd_card {
struct list_head devices; /* devices */
unsigned int last_numid; /* last used numeric ID */
rwlock_t control_rwlock; /* control list lock */
rwlock_t control_owner_lock; /* control list lock */
struct rw_semaphore controls_rwsem; /* controls list lock */
rwlock_t ctl_files_rwlock; /* ctl_files list lock */
int controls_count; /* count of all controls */
struct list_head controls; /* all controls for this card */
struct list_head ctl_files; /* active control files */
......
......@@ -155,11 +155,15 @@ static int __init get_id(char **str, char **dst)
return 0;
for (s = *str; isalpha(*s) || isdigit(*s) || *s == '_'; s++);
if (s != *str) {
*dst = (char *)kmalloc(s - *str, GFP_KERNEL);
*dst = (char *)kmalloc((s - *str) + 1, GFP_KERNEL);
s = *str; d = *dst;
while (isalpha(*s) || isdigit(*s) || *s == '_')
while (isalpha(*s) || isdigit(*s) || *s == '_') {
if (d != NULL)
*d++ = *s++;
*d++ = *s;
s++;
}
if (d != NULL)
*d = '\0';
}
*str = s;
if (*s == ',') {
......
......@@ -41,6 +41,7 @@
#define MPU401_HW_CMIPCI 15 /* CMIPCI MPU-401 UART */
#define MPU401_HW_ALS4000 16 /* Avance Logic ALS4000 */
#define MPU401_HW_INTEL8X0 17 /* Intel8x0 driver */
#define MPU401_HW_PC98II 18 /* Roland PC98II */
#define MPU401_MODE_BIT_INPUT 0
#define MPU401_MODE_BIT_OUTPUT 1
......@@ -64,6 +65,7 @@ struct _snd_mpu401 {
unsigned short hardware; /* MPU401_HW_XXXX */
unsigned long port; /* base port of MPU-401 chip */
unsigned long cport; /* port + 1 (usually) */
struct resource *res; /* port resource */
int irq; /* IRQ number of MPU-401 chip (-1 = poll) */
int irq_flags;
......@@ -89,8 +91,8 @@ struct _snd_mpu401 {
/* I/O ports */
#define MPU401C(mpu) ((mpu)->port + 1)
#define MPU401D(mpu) ((mpu)->port + 0)
#define MPU401C(mpu) (mpu)->cport
#define MPU401D(mpu) (mpu)->port
/*
......
......@@ -229,6 +229,7 @@
#define OPL3_HW_OPL3_CS 0x0302 /* CS4232/CS4236+ */
#define OPL3_HW_OPL3_FM801 0x0303 /* FM801 */
#define OPL3_HW_OPL3_CS4281 0x0304 /* CS4281 */
#define OPL3_HW_OPL3_PC98 0x0305 /* PC9800 */
#define OPL3_HW_OPL4 0x0400
#define OPL3_HW_MASK 0xff00
......
......@@ -15,7 +15,7 @@
* 2002-04-04 Tomas Kasparek better rates handling (allow non-standard rates)
*/
/* $Id: sa11xx-uda1341.c,v 1.5 2002/10/21 18:28:19 perex Exp $ */
/* $Id: sa11xx-uda1341.c,v 1.6 2002/12/04 18:52:05 perex Exp $ */
#include <sound/driver.h>
#include <linux/module.h>
......
......@@ -37,7 +37,7 @@ typedef struct _snd_kctl_ioctl {
#define snd_kctl_ioctl(n) list_entry(n, snd_kctl_ioctl_t, list)
static rwlock_t snd_ioctl_rwlock = RW_LOCK_UNLOCKED;
static DECLARE_RWSEM(snd_ioctl_rwsem);
static LIST_HEAD(snd_control_ioctls);
static inline void dec_mod_count(struct module *module)
......@@ -82,9 +82,9 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
ctl->card = card;
ctl->pid = current->pid;
file->private_data = ctl;
write_lock_irqsave(&card->control_rwlock, flags);
write_lock_irqsave(&card->ctl_files_rwlock, flags);
list_add_tail(&ctl->list, &card->ctl_files);
write_unlock_irqrestore(&card->control_rwlock, flags);
write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
return 0;
__error:
......@@ -123,16 +123,16 @@ static int snd_ctl_release(struct inode *inode, struct file *file)
fasync_helper(-1, file, 0, &ctl->fasync);
file->private_data = NULL;
card = ctl->card;
write_lock_irqsave(&card->control_rwlock, flags);
write_lock_irqsave(&card->ctl_files_rwlock, flags);
list_del(&ctl->list);
write_lock(&card->control_owner_lock);
write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
down_write(&card->controls_rwsem);
list_for_each(list, &card->controls) {
control = snd_kcontrol(list);
if (control->owner == ctl)
control->owner = NULL;
}
write_unlock(&card->control_owner_lock);
write_unlock_irqrestore(&card->control_rwlock, flags);
up_write(&card->controls_rwsem);
snd_ctl_empty_read_queue(ctl);
snd_magic_kfree(ctl);
dec_mod_count(card->module);
......@@ -151,7 +151,7 @@ void snd_ctl_notify(snd_card_t *card, unsigned int mask, snd_ctl_elem_id_t *id)
snd_kctl_event_t *ev;
snd_runtime_check(card != NULL && id != NULL, return);
read_lock_irqsave(&card->control_rwlock, flags);
read_lock(&card->ctl_files_rwlock);
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
card->mixer_oss_change_count++;
#endif
......@@ -160,7 +160,7 @@ void snd_ctl_notify(snd_card_t *card, unsigned int mask, snd_ctl_elem_id_t *id)
ctl = snd_ctl_file(flist);
if (!ctl->subscribed)
continue;
spin_lock(&ctl->read_lock);
spin_lock_irqsave(&ctl->read_lock, flags);
list_for_each(elist, &ctl->events) {
ev = snd_kctl_event(elist);
if (ev->id.numid == id->numid) {
......@@ -179,9 +179,9 @@ void snd_ctl_notify(snd_card_t *card, unsigned int mask, snd_ctl_elem_id_t *id)
_found:
wake_up(&ctl->change_sleep);
kill_fasync(&ctl->fasync, SIGIO, POLL_IN);
spin_unlock(&ctl->read_lock);
spin_unlock_irqrestore(&ctl->read_lock, flags);
}
read_unlock_irqrestore(&card->control_rwlock, flags);
read_unlock(&card->ctl_files_rwlock);
}
snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control)
......@@ -233,11 +233,11 @@ int snd_ctl_add(snd_card_t * card, snd_kcontrol_t * kcontrol)
snd_assert(kcontrol->info != NULL, return -EINVAL);
snd_assert(!(kcontrol->access & SNDRV_CTL_ELEM_ACCESS_READ) || kcontrol->get != NULL, return -EINVAL);
snd_assert(!(kcontrol->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || kcontrol->put != NULL, return -EINVAL);
write_lock(&card->control_rwlock);
down_write(&card->controls_rwsem);
list_add_tail(&kcontrol->list, &card->controls);
card->controls_count++;
kcontrol->id.numid = ++card->last_numid;
write_unlock(&card->control_rwlock);
up_write(&card->controls_rwsem);
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &kcontrol->id);
return 0;
}
......@@ -245,10 +245,10 @@ int snd_ctl_add(snd_card_t * card, snd_kcontrol_t * kcontrol)
int snd_ctl_remove(snd_card_t * card, snd_kcontrol_t * kcontrol)
{
snd_runtime_check(card != NULL && kcontrol != NULL, return -EINVAL);
write_lock(&card->control_rwlock);
down_write(&card->controls_rwsem);
list_del(&kcontrol->list);
card->controls_count--;
write_unlock(&card->control_rwlock);
up_write(&card->controls_rwsem);
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_REMOVE, &kcontrol->id);
snd_ctl_free_one(kcontrol);
return 0;
......@@ -264,47 +264,46 @@ int snd_ctl_remove_id(snd_card_t * card, snd_ctl_elem_id_t *id)
return snd_ctl_remove(card, kctl);
}
static snd_kcontrol_t *_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id); /* w/o lock */
int snd_ctl_rename_id(snd_card_t * card, snd_ctl_elem_id_t *src_id, snd_ctl_elem_id_t *dst_id)
{
snd_kcontrol_t *kctl;
kctl = snd_ctl_find_id(card, src_id);
if (kctl == NULL)
down_write(&card->controls_rwsem);
kctl = _ctl_find_id(card, src_id);
if (kctl == NULL) {
up_write(&card->controls_rwsem);
return -ENOENT;
write_lock(&card->control_rwlock);
}
kctl->id = *dst_id;
kctl->id.numid = ++card->last_numid;
write_unlock(&card->control_rwlock);
up_write(&card->controls_rwsem);
return 0;
}
snd_kcontrol_t *snd_ctl_find_numid(snd_card_t * card, unsigned int numid)
static snd_kcontrol_t *_ctl_find_numid(snd_card_t * card, unsigned int numid)
{
struct list_head *list;
snd_kcontrol_t *kctl;
snd_runtime_check(card != NULL && numid != 0, return NULL);
read_lock(&card->control_rwlock);
list_for_each(list, &card->controls) {
kctl = snd_kcontrol(list);
if (kctl->id.numid == numid) {
read_unlock(&card->control_rwlock);
if (kctl->id.numid == numid)
return kctl;
}
}
read_unlock(&card->control_rwlock);
return NULL;
}
snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id)
static snd_kcontrol_t *_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id)
{
struct list_head *list;
snd_kcontrol_t *kctl;
snd_runtime_check(card != NULL && id != NULL, return NULL);
if (id->numid != 0)
return snd_ctl_find_numid(card, id->numid);
read_lock(&card->control_rwlock);
return _ctl_find_numid(card, id->numid);
list_for_each(list, &card->controls) {
kctl = snd_kcontrol(list);
if (kctl->id.iface != id->iface)
......@@ -317,20 +316,38 @@ snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id)
continue;
if (kctl->id.index != id->index)
continue;
read_unlock(&card->control_rwlock);
return kctl;
}
read_unlock(&card->control_rwlock);
return NULL;
}
/* exported: with read lock */
snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id)
{
snd_kcontrol_t *kctl;
down_read(&card->controls_rwsem);
kctl = _ctl_find_id(card, id);
up_read(&card->controls_rwsem);
return kctl;
}
/* exported: with read lock */
snd_kcontrol_t *snd_ctl_find_numid(snd_card_t * card, unsigned int numid)
{
snd_kcontrol_t *kctl;
down_read(&card->controls_rwsem);
kctl = _ctl_find_numid(card, numid);
up_read(&card->controls_rwsem);
return kctl;
}
static int snd_ctl_card_info(snd_card_t * card, snd_ctl_file_t * ctl,
unsigned int cmd, unsigned long arg)
{
snd_ctl_card_info_t info;
memset(&info, 0, sizeof(info));
read_lock(&snd_ioctl_rwlock);
down_read(&snd_ioctl_rwsem);
info.card = card->number;
strncpy(info.id, card->id, sizeof(info.id) - 1);
strncpy(info.driver, card->driver, sizeof(info.driver) - 1);
......@@ -338,7 +355,7 @@ static int snd_ctl_card_info(snd_card_t * card, snd_ctl_file_t * ctl,
strncpy(info.longname, card->longname, sizeof(info.longname) - 1);
strncpy(info.mixername, card->mixername, sizeof(info.mixername) - 1);
strncpy(info.components, card->components, sizeof(info.components) - 1);
read_unlock(&snd_ioctl_rwlock);
up_read(&snd_ioctl_rwsem);
if (copy_to_user((void *) arg, &info, sizeof(snd_ctl_card_info_t)))
return -EFAULT;
return 0;
......@@ -364,7 +381,7 @@ static int snd_ctl_elem_list(snd_card_t *card, snd_ctl_elem_list_t *_list)
dst = vmalloc(space * sizeof(snd_ctl_elem_id_t));
if (dst == NULL)
return -ENOMEM;
read_lock(&card->control_rwlock);
down_read(&card->controls_rwsem);
list.count = card->controls_count;
plist = card->controls.next;
while (offset-- > 0 && plist != &card->controls)
......@@ -379,14 +396,14 @@ static int snd_ctl_elem_list(snd_card_t *card, snd_ctl_elem_list_t *_list)
space--;
list.used++;
}
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
if (list.used > 0 && copy_to_user(list.pids, dst, list.used * sizeof(snd_ctl_elem_id_t)))
return -EFAULT;
vfree(dst);
} else {
read_lock(&card->control_rwlock);
down_read(&card->controls_rwsem);
list.count = card->controls_count;
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
}
if (copy_to_user(_list, &list, sizeof(list)))
return -EFAULT;
......@@ -402,10 +419,10 @@ static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t *_info)
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
read_lock(&card->control_rwlock);
kctl = snd_ctl_find_id(card, &info.id);
down_read(&card->controls_rwsem);
kctl = _ctl_find_id(card, &info.id);
if (kctl == NULL) {
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
return -ENOENT;
}
#ifdef CONFIG_SND_DEBUG
......@@ -425,7 +442,7 @@ static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t *_info)
info.owner = -1;
}
}
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
if (result >= 0)
if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT;
......@@ -443,8 +460,8 @@ static int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *_control)
return -ENOMEM;
if (copy_from_user(control, _control, sizeof(*control)))
return -EFAULT;
read_lock(&card->control_rwlock);
kctl = snd_ctl_find_id(card, &control->id);
down_read(&card->controls_rwsem);
kctl = _ctl_find_id(card, &control->id);
if (kctl == NULL) {
result = -ENOENT;
} else {
......@@ -460,7 +477,7 @@ static int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *_control)
result = -EPERM;
}
}
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
if (result >= 0)
if (copy_to_user(_control, control, sizeof(*control)))
return -EFAULT;
......@@ -480,8 +497,8 @@ static int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t *_contr
return -ENOMEM;
if (copy_from_user(control, _control, sizeof(*control)))
return -EFAULT;
read_lock(&card->control_rwlock);
kctl = snd_ctl_find_id(card, &control->id);
down_read(&card->controls_rwsem);
kctl = _ctl_find_id(card, &control->id);
if (kctl == NULL) {
result = -ENOENT;
} else {
......@@ -489,7 +506,6 @@ static int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t *_contr
if (control->indirect != indirect) {
result = -EACCES;
} else {
read_lock(&card->control_owner_lock);
if (!(kctl->access & SNDRV_CTL_ELEM_ACCESS_WRITE) ||
kctl->put == NULL ||
(kctl->owner != NULL && kctl->owner != file)) {
......@@ -499,16 +515,15 @@ static int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t *_contr
if (result >= 0)
control->id = kctl->id;
}
read_unlock(&card->control_owner_lock);
if (result > 0) {
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
result = 0;
goto __unlocked;
}
}
}
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
__unlocked:
if (result >= 0)
if (copy_to_user(_control, control, sizeof(*control)))
......@@ -526,12 +541,11 @@ static int snd_ctl_elem_lock(snd_ctl_file_t *file, snd_ctl_elem_id_t *_id)
if (copy_from_user(&id, _id, sizeof(id)))
return -EFAULT;
read_lock(&card->control_rwlock);
kctl = snd_ctl_find_id(card, &id);
down_write(&card->controls_rwsem);
kctl = _ctl_find_id(card, &id);
if (kctl == NULL) {
result = -ENOENT;
} else {
write_lock(&card->control_owner_lock);
if (kctl->owner != NULL)
result = -EBUSY;
else {
......@@ -539,9 +553,8 @@ static int snd_ctl_elem_lock(snd_ctl_file_t *file, snd_ctl_elem_id_t *_id)
kctl->owner_pid = current->pid;
result = 0;
}
write_unlock(&card->control_owner_lock);
}
read_unlock(&card->control_rwlock);
up_write(&card->controls_rwsem);
return result;
}
......@@ -554,12 +567,11 @@ static int snd_ctl_elem_unlock(snd_ctl_file_t *file, snd_ctl_elem_id_t *_id)
if (copy_from_user(&id, _id, sizeof(id)))
return -EFAULT;
read_lock(&card->control_rwlock);
kctl = snd_ctl_find_id(card, &id);
down_write(&card->controls_rwsem);
kctl = _ctl_find_id(card, &id);
if (kctl == NULL) {
result = -ENOENT;
} else {
write_lock(&card->control_owner_lock);
if (kctl->owner == NULL)
result = -EINVAL;
else if (kctl->owner != file)
......@@ -569,9 +581,8 @@ static int snd_ctl_elem_unlock(snd_ctl_file_t *file, snd_ctl_elem_id_t *_id)
kctl->owner_pid = 0;
result = 0;
}
write_unlock(&card->control_owner_lock);
}
read_unlock(&card->control_rwlock);
up_write(&card->controls_rwsem);
return result;
}
......@@ -646,16 +657,16 @@ static int snd_ctl_ioctl(struct inode *inode, struct file *file,
return put_user(SNDRV_CTL_POWER_D0, (int *)arg) ? -EFAULT : 0;
#endif
}
read_lock(&snd_ioctl_rwlock);
down_read(&snd_ioctl_rwsem);
list_for_each(list, &snd_control_ioctls) {
p = list_entry(list, snd_kctl_ioctl_t, list);
err = p->fioctl(card, ctl, cmd, arg);
if (err != -ENOIOCTLCMD) {
read_unlock(&snd_ioctl_rwlock);
up_read(&snd_ioctl_rwsem);
return err;
}
}
read_unlock(&snd_ioctl_rwlock);
up_read(&snd_ioctl_rwsem);
snd_printd("unknown ioctl = 0x%x\n", cmd);
return -ENOTTY;
}
......@@ -740,9 +751,9 @@ int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn)
if (pn == NULL)
return -ENOMEM;
pn->fioctl = fcn;
write_lock(&snd_ioctl_rwlock);
down_write(&snd_ioctl_rwsem);
list_add_tail(&pn->list, &snd_control_ioctls);
write_unlock(&snd_ioctl_rwlock);
up_write(&snd_ioctl_rwsem);
return 0;
}
......@@ -752,17 +763,17 @@ int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn)
snd_kctl_ioctl_t *p;
snd_runtime_check(fcn != NULL, return -EINVAL);
write_lock(&snd_ioctl_rwlock);
down_write(&snd_ioctl_rwsem);
list_for_each(list, &snd_control_ioctls) {
p = list_entry(list, snd_kctl_ioctl_t, list);
if (p->fioctl == fcn) {
list_del(&p->list);
write_unlock(&snd_ioctl_rwlock);
up_write(&snd_ioctl_rwsem);
kfree(p);
return 0;
}
}
write_unlock(&snd_ioctl_rwlock);
up_write(&snd_ioctl_rwsem);
snd_BUG();
return -EINVAL;
}
......@@ -821,13 +832,13 @@ int snd_ctl_disconnect(snd_card_t *card)
struct list_head *flist;
snd_ctl_file_t *ctl;
read_lock_irq(&card->control_rwlock);
down_read(&card->controls_rwsem);
list_for_each(flist, &card->ctl_files) {
ctl = snd_ctl_file(flist);
wake_up(&ctl->change_sleep);
kill_fasync(&ctl->fasync, SIGIO, POLL_ERR);
}
read_unlock_irq(&card->control_rwlock);
up_read(&card->controls_rwsem);
return 0;
}
......
......@@ -1024,7 +1024,7 @@ static void snd_info_version_read(snd_info_entry_t *entry, snd_info_buffer_t * b
snd_iprintf(buffer,
"Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n"
"Compiled on " __DATE__ " for kernel %s"
#ifdef __SMP__
#ifdef CONFIG_SMP
" (SMP)"
#endif
#ifdef MODVERSIONS
......
......@@ -99,8 +99,8 @@ snd_card_t *snd_card_new(int idx, const char *xid,
card->number = idx;
card->module = module;
INIT_LIST_HEAD(&card->devices);
rwlock_init(&card->control_rwlock);
rwlock_init(&card->control_owner_lock);
init_rwsem(&card->controls_rwsem);
rwlock_init(&card->ctl_files_rwlock);
INIT_LIST_HEAD(&card->controls);
INIT_LIST_HEAD(&card->ctl_files);
spin_lock_init(&card->files_lock);
......@@ -393,8 +393,6 @@ static void choose_default_id(snd_card_t * card)
idx_flag++;
}
}
strcpy(card->id, id);
}
int snd_card_register(snd_card_t * card)
......
......@@ -562,7 +562,7 @@ static int snd_mixer_oss_get_volume1(snd_mixer_oss_file_t *fmixer,
struct slot *slot = (struct slot *)pslot->private_data;
*left = *right = 100;
read_lock(&card->control_rwlock);
down_read(&card->controls_rwsem);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) {
snd_mixer_oss_get_volume1_vol(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GVOLUME) {
......@@ -579,7 +579,7 @@ static int snd_mixer_oss_get_volume1(snd_mixer_oss_file_t *fmixer,
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) {
snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
}
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
return 0;
}
......@@ -655,7 +655,7 @@ static int snd_mixer_oss_put_volume1(snd_mixer_oss_file_t *fmixer,
snd_card_t *card = fmixer->card;
struct slot *slot = (struct slot *)pslot->private_data;
read_lock(&card->control_rwlock);
down_read(&card->controls_rwsem);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) {
snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_CVOLUME)
......@@ -685,7 +685,7 @@ static int snd_mixer_oss_put_volume1(snd_mixer_oss_file_t *fmixer,
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
}
}
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
return 0;
}
......@@ -698,9 +698,9 @@ static int snd_mixer_oss_get_recsrc1_sw(snd_mixer_oss_file_t *fmixer,
int left, right;
left = right = 1;
read_lock(&card->control_rwlock);
down_read(&card->controls_rwsem);
snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CSWITCH], &left, &right, 0);
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
*active = (left || right) ? 1 : 0;
return 0;
}
......@@ -714,9 +714,9 @@ static int snd_mixer_oss_get_recsrc1_route(snd_mixer_oss_file_t *fmixer,
int left, right;
left = right = 1;
read_lock(&card->control_rwlock);
down_read(&card->controls_rwsem);
snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CROUTE], &left, &right, 1);
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
*active = (left || right) ? 1 : 0;
return 0;
}
......@@ -728,9 +728,9 @@ static int snd_mixer_oss_put_recsrc1_sw(snd_mixer_oss_file_t *fmixer,
snd_card_t *card = fmixer->card;
struct slot *slot = (struct slot *)pslot->private_data;
read_lock(&card->control_rwlock);
down_read(&card->controls_rwsem);
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CSWITCH], active, active, 0);
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
return 0;
}
......@@ -741,9 +741,9 @@ static int snd_mixer_oss_put_recsrc1_route(snd_mixer_oss_file_t *fmixer,
snd_card_t *card = fmixer->card;
struct slot *slot = (struct slot *)pslot->private_data;
read_lock(&card->control_rwlock);
down_read(&card->controls_rwsem);
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CROUTE], active, active, 1);
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
return 0;
}
......@@ -764,12 +764,11 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, int *active_i
err = -ENOMEM;
goto __unlock;
}
read_lock(&card->control_rwlock);
down_read(&card->controls_rwsem);
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
snd_runtime_check(kctl != NULL, err = -ENOENT; goto __unlock);
snd_runtime_check(!(err = kctl->info(kctl, uinfo)), goto __unlock);
snd_runtime_check(!(err = kctl->get(kctl, uctl)), goto __unlock);
read_unlock(&card->control_rwlock);
for (idx = 0; idx < 32; idx++) {
if (!(mixer->mask_recsrc & (1 << idx)))
continue;
......@@ -785,10 +784,8 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, int *active_i
}
}
err = 0;
goto __unalloc;
__unlock:
read_unlock(&card->control_rwlock);
__unalloc:
up_read(&card->controls_rwsem);
if (uctl)
kfree(uctl);
if (uinfo)
......@@ -813,7 +810,7 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, int active_in
err = -ENOMEM;
goto __unlock;
}
read_lock(&card->control_rwlock);
down_read(&card->controls_rwsem);
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
snd_runtime_check(kctl != NULL, err = -ENOENT; goto __unlock);
snd_runtime_check(!(err = kctl->info(kctl, uinfo)), goto __unlock);
......@@ -838,7 +835,7 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, int active_in
snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
err = 0;
__unlock:
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
if (uctl)
kfree(uctl);
if (uinfo)
......
......@@ -698,7 +698,7 @@ int snd_pcm_open_substream(snd_pcm_t *pcm, int stream,
return -ENODEV;
card = pcm->card;
read_lock(&card->control_rwlock);
down_read(&card->controls_rwsem);
list_for_each(list, &card->ctl_files) {
kctl = snd_ctl_file(list);
if (kctl->pid == current->pid) {
......@@ -706,7 +706,7 @@ int snd_pcm_open_substream(snd_pcm_t *pcm, int stream,
break;
}
}
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
if (pstr->substream_count == 0)
return -ENODEV;
......
......@@ -412,7 +412,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
add_wait_queue(&rmidi->open_wait, &wait);
while (1) {
subdevice = -1;
read_lock(&card->control_rwlock);
down_read(&card->controls_rwsem);
list_for_each(list, &card->ctl_files) {
kctl = snd_ctl_file(list);
if (kctl->pid == current->pid) {
......@@ -420,7 +420,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
break;
}
}
read_unlock(&card->control_rwlock);
up_read(&card->controls_rwsem);
err = snd_rawmidi_kernel_open(cardnum, device, subdevice, fflags, rawmidi_file);
if (err >= 0)
break;
......
......@@ -44,6 +44,7 @@ obj-$(CONFIG_SND_AD1816A) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
obj-$(CONFIG_SND_CS4231) += $(RAWMIDI_OBJS)
obj-$(CONFIG_SND_CS4232) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
obj-$(CONFIG_SND_CS4236) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
obj-$(CONFIG_SND_PC98_CS4232) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
obj-$(CONFIG_SND_ES1688) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
obj-$(CONFIG_SND_GUSCLASSIC) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
obj-$(CONFIG_SND_GUSMAX) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
......
......@@ -19,6 +19,7 @@ obj-$(CONFIG_SND_OPL3SA2) += snd-ainstr-fm.o
obj-$(CONFIG_SND_AD1816A) += snd-ainstr-fm.o
obj-$(CONFIG_SND_CS4232) += snd-ainstr-fm.o
obj-$(CONFIG_SND_CS4236) += snd-ainstr-fm.o
obj-$(CONFIG_SND_PC98_CS4232) += snd-ainstr-fm.o
obj-$(CONFIG_SND_ES1688) += snd-ainstr-fm.o
obj-$(CONFIG_SND_GUSCLASSIC) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
obj-$(CONFIG_SND_GUSMAX) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
......
......@@ -134,7 +134,7 @@ EXPORT_SYMBOL(snd_seq_dump_var_event);
EXPORT_SYMBOL(snd_seq_event_port_attach);
EXPORT_SYMBOL(snd_seq_event_port_detach);
/* seq_lock.c */
#if defined(__SMP__) || defined(CONFIG_SND_DEBUG)
#if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG)
/*EXPORT_SYMBOL(snd_seq_sleep_in_lock);*/
/*EXPORT_SYMBOL(snd_seq_sleep_timeout_in_lock);*/
EXPORT_SYMBOL(snd_use_lock_sync_helper);
......
......@@ -23,7 +23,7 @@
#include <sound/core.h>
#include "seq_lock.h"
#if defined(__SMP__) || defined(CONFIG_SND_DEBUG)
#if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG)
#if 0 /* NOT USED */
/* (interruptible) sleep_on during the specified spinlock */
......
......@@ -3,7 +3,7 @@
#include <linux/sched.h>
#if defined(__SMP__) || defined(CONFIG_SND_DEBUG)
#if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG)
typedef atomic_t snd_use_lock_t;
......
......@@ -40,6 +40,9 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* MPU-401 port number */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* MPU-401 IRQ */
#ifdef CONFIG_PC9800
static int pc98ii[SNDRV_CARDS]; /* PC98-II dauther board */
#endif
MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(index, "Index value for MPU-401 device.");
......@@ -56,6 +59,11 @@ MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
MODULE_PARM(irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
#ifdef CONFIG_PC9800
MODULE_PARM(pc98ii, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(pc98ii, "Roland MPU-PC98II support.");
MODULE_PARM_SYNTAX(pc98ii, SNDRV_BOOLEAN_FALSE_DESC);
#endif
static snd_card_t *snd_mpu401_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
......@@ -76,7 +84,11 @@ static int __init snd_card_mpu401_probe(int dev)
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
if (card == NULL)
return -ENOMEM;
if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
if (snd_mpu401_uart_new(card, 0,
#ifdef CONFIG_PC9800
pc98ii[dev] ? MPU401_HW_PC98II :
#endif
MPU401_HW_MPU401,
port[dev], 0,
irq[dev], irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0) {
printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
......
......@@ -401,12 +401,17 @@ int snd_mpu401_uart_new(snd_card_t * card, int device,
spin_lock_init(&mpu->timer_lock);
mpu->hardware = hardware;
if (!integrated) {
if ((mpu->res = request_region(port, 2, "MPU401 UART")) == NULL) {
int res_size = hardware == MPU401_HW_PC98II ? 4 : 2;
if ((mpu->res = request_region(port, res_size, "MPU401 UART")) == NULL) {
snd_device_free(card, rmidi);
return -EBUSY;
}
}
mpu->port = port;
if (hardware == MPU401_HW_PC98II)
mpu->cport = port + 2;
else
mpu->cport = port + 1;
if (irq >= 0 && irq_flags) {
if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags, "MPU401 UART", (void *) mpu)) {
snd_printk("unable to grab IRQ %d\n", irq);
......
......@@ -419,6 +419,26 @@ int snd_opl3_create(snd_card_t * card,
case OPL3_HW_OPL3_CS:
case OPL3_HW_OPL3_FM801:
opl3->command = &snd_opl3_command;
break;
case OPL3_HW_OPL3_PC98:
opl3->command = &snd_opl3_command;
/* Initialize? */
opl3->command(opl3, OPL3_RIGHT | 0x05, 0x05);
opl3->command(opl3, OPL3_RIGHT | 0x08, 0x04);
opl3->command(opl3, OPL3_RIGHT | 0x08, 0x00);
opl3->command(opl3, OPL3_LEFT | 0xf7, 0x00);
opl3->command(opl3, OPL3_LEFT | 0x04, 0x60);
opl3->command(opl3, OPL3_LEFT | 0x04, 0x80);
inb(opl3->l_port);
opl3->command(opl3, OPL3_LEFT | 0x02, 0xff);
opl3->command(opl3, OPL3_LEFT | 0x04, 0x21);
inb(opl3->l_port);
opl3->command(opl3, OPL3_LEFT | 0x04, 0x60);
opl3->command(opl3, OPL3_LEFT | 0x04, 0x80);
break;
case OPL3_HW_OPL3_CS4281:
opl3->command = &snd_opl3_cs4281_command;
......@@ -438,6 +458,7 @@ int snd_opl3_create(snd_card_t * card,
opl3->command = &snd_opl3_command;
}
}
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT);
opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00); /* Melodic mode */
......
......@@ -104,13 +104,13 @@ config SND_CMIPCI
config SND_ENS1370
tristate "(Creative) Ensoniq AudioPCI 1370"
depends on SND
depends on SND && SOUND_GAMEPORT
help
Say 'Y' or 'M' to include support for Ensoniq AudioPCI ES1370.
config SND_ENS1371
tristate "(Creative) Ensoniq AudioPCI 1371/1373"
depends on SND
depends on SND && SOUND_GAMEPORT
help
Say 'Y' or 'M' to include support for Ensoniq AudioPCI ES1371 and
Sound Blaster PCI 64 or 128 soundcards.
......
......@@ -126,6 +126,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x48525300, 0xffffff00, "HMP9701", NULL },
{ 0x49434501, 0xffffffff, "ICE1230", NULL },
{ 0x49434511, 0xffffffff, "ICE1232", NULL }, // alias VIA VT1611A?
{ 0x49434551, 0xffffffff, "VT1616", NULL },
{ 0x49544520, 0xffffffff, "IT2226E", NULL },
{ 0x4e534300, 0xffffffff, "LM4540/43/45/46/48", NULL }, // only guess --jk
{ 0x4e534331, 0xffffffff, "LM4549", NULL },
......@@ -678,6 +679,13 @@ AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)
static const snd_kcontrol_new_t snd_ac97_control_eapd =
AC97_SINGLE("External Amplifier Power Down", AC97_POWERDOWN, 15, 1, 0);
static const snd_kcontrol_new_t snd_ac97_controls_vt1616[] = {
AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),
AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
};
static int snd_ac97_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
......@@ -1583,6 +1591,14 @@ static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_alc650[idx], ac97))) < 0)
return err;
break;
case AC97_ID_VT1616:
if (snd_ac97_try_bit(ac97, 0x5a, 9))
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_vt1616[0], ac97))) < 0)
return err;
for (idx = 1; idx < ARRAY_SIZE(snd_ac97_controls_vt1616); idx++)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_vt1616[idx], ac97))) < 0)
return err;
break;
default:
/* nothing */
break;
......
......@@ -46,3 +46,4 @@
#define AC97_ID_CS_MASK 0xfffffff8 /* bit 0-2: rev */
#define AC97_ID_ALC650 0x414c4720
#define AC97_ID_YMF753 0x594d4803
#define AC97_ID_VT1616 0x49434551
......@@ -3689,7 +3689,7 @@ struct cs_card_type
void (*mixer_init)(cs46xx_t *);
};
static struct cs_card_type __initdata cards[] = {
static struct cs_card_type __devinitdata cards[] = {
{0x1489, 0x7001, "Genius Soundmaker 128 value", NULL, amp_none, NULL, NULL},
{0x5053, 0x3357, "Voyetra", NULL, amp_voyetra, NULL, voyetra_mixer_init},
{0x1071, 0x6003, "Mitac MI6020/21", NULL, amp_voyetra, NULL, NULL},
......
......@@ -26,6 +26,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/gameport.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
......@@ -403,6 +404,9 @@ struct _snd_ensoniq {
unsigned char *bugbuf;
dma_addr_t bugbuf_addr;
#endif
struct gameport gameport;
struct semaphore joy_sem; // gameport configuration semaphore
};
static void snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs *regs);
......@@ -1572,8 +1576,67 @@ static int __devinit snd_ensoniq_1370_mixer(ensoniq_t * ensoniq)
* General Switches...
*/
/* MQ: gameport driver connectivity */
#define ENSONIQ_JOY_CONTROL(xname, mask) \
{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = xname, .info = snd_ensoniq_control_info, \
.get = snd_ensoniq_control_get, .put = snd_ensoniq_joy_control_put, \
.private_value = mask }
static int snd_ensoniq_joy_enable(ensoniq_t *ensoniq)
{
static int last_jiffies = 0;
unsigned long flags;
if (!request_region(ensoniq->gameport.io, 8, "ens137x: gameport")) {
#define ES___GAMEPORT_LOG_DELAY (30*HZ)
// avoid log pollution: limit to 2 infos per minute
if (jiffies > last_jiffies + ES___GAMEPORT_LOG_DELAY) {
last_jiffies = jiffies;
snd_printk("gameport io port 0x%03x in use", ensoniq->gameport.io);
}
return 0;
}
spin_lock_irqsave(&ensoniq->reg_lock, flags);
ensoniq->ctrl |= ES_JYSTK_EN;
outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
gameport_register_port(&ensoniq->gameport);
return 1;
}
static int snd_ensoniq_joy_disable(ensoniq_t *ensoniq)
{
unsigned long flags;
gameport_unregister_port(&ensoniq->gameport);
spin_lock_irqsave(&ensoniq->reg_lock, flags);
ensoniq->ctrl &= ~ES_JYSTK_EN;
outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
release_region(ensoniq->gameport.io, 8);
return 1;
}
static int snd_ensoniq_joy_control_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
unsigned int nval;
int change;
down(&ensoniq->joy_sem);
nval = ucontrol->value.integer.value[0] ? ES_JYSTK_EN : 0;
change = (ensoniq->ctrl & ES_JYSTK_EN) != nval; // spinlock shouldn't be needed because of joy_sem
if (change) {
if (nval) // enable
change = snd_ensoniq_joy_enable(ensoniq);
else change = snd_ensoniq_joy_disable(ensoniq);
}
up(&ensoniq->joy_sem);
return change;
}
static snd_kcontrol_new_t snd_ensoniq_control_joystick __devinitdata =
ENSONIQ_CONTROL("Joystick Enable", ES_JYSTK_EN);
ENSONIQ_JOY_CONTROL("Joystick Enable", ES_JYSTK_EN);
#ifdef CHIP1371
......@@ -1585,9 +1648,9 @@ static int snd_es1371_joystick_addr_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = 3;
if (uinfo->value.enumerated.item >= 3)
uinfo->value.enumerated.item = 2;
uinfo->value.enumerated.items = 4;
if (uinfo->value.enumerated.item >= 4)
uinfo->value.enumerated.item = 3;
sprintf(uinfo->value.enumerated.name, "port 0x%x", (uinfo->value.enumerated.item * 8) + 0x200);
return 0;
}
......@@ -1610,13 +1673,19 @@ static int snd_es1371_joystick_addr_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_
unsigned int nval;
int change;
down(&ensoniq->joy_sem);
nval = ES_1371_JOY_ASEL(ucontrol->value.integer.value[0]);
spin_lock_irqsave(&ensoniq->reg_lock, flags);
if (!(change = !(ensoniq->ctrl & ES_JYSTK_EN)))
goto no_change; // FIXME: now we allow change only when joystick is disabled
change = (ensoniq->ctrl & ES_1371_JOY_ASELM) != nval;
ensoniq->ctrl &= ~ES_1371_JOY_ASELM;
ensoniq->ctrl |= nval;
outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
ensoniq->gameport.io = 0x200 + ES_1371_JOY_ASELI(nval) * 8;
no_change:
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
up(&ensoniq->joy_sem);
return change;
}
......@@ -1680,6 +1749,8 @@ static void snd_ensoniq_proc_done(ensoniq_t * ensoniq)
static int snd_ensoniq_free(ensoniq_t *ensoniq)
{
if (ensoniq->ctrl & ES_JYSTK_EN)
snd_ensoniq_joy_disable(ensoniq);
snd_ensoniq_proc_done(ensoniq);
if (ensoniq->irq < 0)
goto __hw_end;
......@@ -1760,6 +1831,7 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
if (ensoniq == NULL)
return -ENOMEM;
spin_lock_init(&ensoniq->reg_lock);
init_MUTEX(&ensoniq->joy_sem);
ensoniq->card = card;
ensoniq->pci = pci;
ensoniq->irq = -1;
......@@ -1874,10 +1946,11 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
outb(ensoniq->uartc = 0x00, ES_REG(ensoniq, UART_CONTROL));
outb(0x00, ES_REG(ensoniq, UART_RES));
outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
snd_ctl_add(card, snd_ctl_new1(&snd_ensoniq_control_joystick, ensoniq));
#ifdef CHIP1371
snd_ctl_add(card, snd_ctl_new1(&snd_es1371_joystick_addr, ensoniq));
#endif
snd_ctl_add(card, snd_ctl_new1(&snd_ensoniq_control_joystick, ensoniq));
ensoniq->gameport.io = 0x200; // FIXME: is ES1371 configured like this above ?
synchronize_irq(ensoniq->irq);
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ensoniq, &ops)) < 0) {
......
......@@ -517,18 +517,18 @@ static snd_pcm_hardware_t snd_fm801_playback =
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID),
formats: SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
rates: SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
rate_min: 5500,
rate_max: 48000,
channels_min: 1,
channels_max: 2,
buffer_bytes_max: (128*1024),
period_bytes_min: 64,
period_bytes_max: (128*1024),
periods_min: 1,
periods_max: 1024,
fifo_size: 0,
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
.rate_min = 5500,
.rate_max = 48000,
.channels_min = 1,
.channels_max = 2,
.buffer_bytes_max = (128*1024),
.period_bytes_min = 64,
.period_bytes_max = (128*1024),
.periods_min = 1,
.periods_max = 1024,
.fifo_size = 0,
};
static snd_pcm_hardware_t snd_fm801_capture =
......@@ -536,18 +536,18 @@ static snd_pcm_hardware_t snd_fm801_capture =
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID),
formats: SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
rates: SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
rate_min: 5500,
rate_max: 48000,
channels_min: 1,
channels_max: 2,
buffer_bytes_max: (128*1024),
period_bytes_min: 64,
period_bytes_max: (128*1024),
periods_min: 1,
periods_max: 1024,
fifo_size: 0,
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
.rate_min = 5500,
.rate_max = 48000,
.channels_min = 1,
.channels_max = 2,
.buffer_bytes_max = (128*1024),
.period_bytes_min = 64,
.period_bytes_max = (128*1024),
.periods_min = 1,
.periods_max = 1024,
.fifo_size = 0,
};
static int snd_fm801_playback_open(snd_pcm_substream_t * substream)
......@@ -834,7 +834,7 @@ static void snd_fm801_mixer_free_ac97(ac97_t *ac97)
}
}
static int __init snd_fm801_mixer(fm801_t *chip)
static int __devinit snd_fm801_mixer(fm801_t *chip)
{
ac97_t ac97;
int err, i;
......@@ -920,13 +920,13 @@ static int __devinit snd_fm801_create(snd_card_t * card,
chip->irq = -1;
chip->port = pci_resource_start(pci, 0);
if ((chip->res_port = request_region(chip->port, 0x80, "FM801")) == NULL) {
snd_fm801_free(chip);
snd_printk("unable to grab region 0x%lx-0x%lx\n", chip->port, chip->port + 0x80 - 1);
snd_fm801_free(chip);
return -EBUSY;
}
if (request_irq(pci->irq, snd_fm801_interrupt, SA_INTERRUPT|SA_SHIRQ, "FM801", (void *)chip)) {
snd_fm801_free(chip);
snd_printk("unable to grab IRQ %d\n", chip->irq);
snd_fm801_free(chip);
return -EBUSY;
}
chip->irq = pci->irq;
......
......@@ -1894,7 +1894,7 @@ static void snd_korg1212_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *b
snd_iprintf(buffer, " Irq count: %ld\n", korg1212->irqcount);
}
static void __init snd_korg1212_proc_init(korg1212_t *korg1212)
static void __devinit snd_korg1212_proc_init(korg1212_t *korg1212)
{
snd_info_entry_t *entry;
......@@ -1920,7 +1920,7 @@ static void snd_korg1212_proc_done(korg1212_t * korg1212)
}
}
static int __init snd_korg1212_create(korg1212_t *korg1212)
static int __devinit snd_korg1212_create(korg1212_t *korg1212)
{
struct pci_dev *pci = korg1212->pci;
int err;
......
......@@ -305,7 +305,7 @@ snd_rme96_playback_pointer(snd_pcm_substream_t *substream);
static snd_pcm_uframes_t
snd_rme96_capture_pointer(snd_pcm_substream_t *substream);
static void __init
static void __devinit
snd_rme96_proc_init(rme96_t *rme96);
static void
......@@ -1589,7 +1589,7 @@ snd_rme96_free_adat_pcm(snd_pcm_t *pcm)
snd_pcm_lib_preallocate_free_for_all(pcm);
}
static int __init
static int __devinit
snd_rme96_create(rme96_t *rme96)
{
struct pci_dev *pci = rme96->pci;
......@@ -1838,7 +1838,7 @@ snd_rme96_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
}
}
static void __init
static void __devinit
snd_rme96_proc_init(rme96_t *rme96)
{
snd_info_entry_t *entry;
......
......@@ -3069,9 +3069,11 @@ static int __devinit snd_hdsp_create(snd_card_t *card,
static int snd_hdsp_free(hdsp_t *hdsp)
{
if (hdsp->res_port) {
/* stop the audio, and cancel all interrupts */
hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
}
if (hdsp->irq >= 0)
free_irq(hdsp->irq, (void *)hdsp);
......
......@@ -1799,7 +1799,7 @@ snd_rme9652_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
snd_iprintf(buffer, "\n");
}
static void __init snd_rme9652_proc_init(rme9652_t *rme9652)
static void __devinit snd_rme9652_proc_init(rme9652_t *rme9652)
{
snd_info_entry_t *entry;
......@@ -1869,7 +1869,7 @@ static int snd_rme9652_free(rme9652_t *rme9652)
return 0;
}
static int __init snd_rme9652_initialize_memory(rme9652_t *rme9652)
static int __devinit snd_rme9652_initialize_memory(rme9652_t *rme9652)
{
void *pb, *cb;
dma_addr_t pb_addr, cb_addr;
......@@ -2523,7 +2523,7 @@ static snd_pcm_ops_t snd_rme9652_capture_ops = {
.copy = snd_rme9652_capture_copy,
};
static int __init snd_rme9652_create_pcm(snd_card_t *card,
static int __devinit snd_rme9652_create_pcm(snd_card_t *card,
rme9652_t *rme9652)
{
snd_pcm_t *pcm;
......@@ -2547,7 +2547,7 @@ static int __init snd_rme9652_create_pcm(snd_card_t *card,
return 0;
}
static int __init snd_rme9652_create(snd_card_t *card,
static int __devinit snd_rme9652_create(snd_card_t *card,
rme9652_t *rme9652,
int precise_ptr)
{
......
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