Commit b8877144 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://linux-sound.bkbits.net/linux-sound

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 975d6b21 8d6ff919
......@@ -129,7 +129,7 @@ enum {
* *
*****************************************************************************/
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 2)
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 3)
typedef unsigned long sndrv_pcm_uframes_t;
typedef long sndrv_pcm_sframes_t;
......@@ -423,6 +423,7 @@ enum {
SNDRV_PCM_IOCTL_SW_PARAMS = _IOWR('A', 0x13, struct sndrv_pcm_sw_params),
SNDRV_PCM_IOCTL_STATUS = _IOR('A', 0x20, struct sndrv_pcm_status),
SNDRV_PCM_IOCTL_DELAY = _IOR('A', 0x21, sndrv_pcm_sframes_t),
SNDRV_PCM_IOCTL_HWSYNC = _IO('A', 0x22),
SNDRV_PCM_IOCTL_CHANNEL_INFO = _IOR('A', 0x32, struct sndrv_pcm_channel_info),
SNDRV_PCM_IOCTL_PREPARE = _IO('A', 0x40),
SNDRV_PCM_IOCTL_RESET = _IO('A', 0x41),
......
......@@ -225,7 +225,6 @@ int snd_minor_info_oss_init(void);
int snd_minor_info_oss_done(void);
int snd_oss_init_module(void);
void snd_oss_cleanup_module(void);
#endif
......
......@@ -164,7 +164,7 @@ static inline int snd_info_card_unregister(snd_card_t * card) { return 0; }
static inline int snd_info_register(snd_info_entry_t * entry) { return 0; }
static inline int snd_info_unregister(snd_info_entry_t * entry) { return 0; }
static inline struct proc_dir_entry *snd_create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent) { return 0; }
static inline struct proc_dir_entry *snd_create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent) { return NULL; }
static inline void snd_remove_proc_entry(struct proc_dir_entry *parent,
struct proc_dir_entry *de) { ; }
......@@ -174,7 +174,7 @@ static inline void snd_remove_proc_entry(struct proc_dir_entry *parent,
* OSS info part
*/
#ifdef CONFIG_SND_OSSEMUL
#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
#define SNDRV_OSS_INFO_DEV_AUDIO 0
#define SNDRV_OSS_INFO_DEV_SYNTH 1
......@@ -187,6 +187,6 @@ static inline void snd_remove_proc_entry(struct proc_dir_entry *parent,
extern int snd_oss_info_register(int dev, int num, char *string);
#define snd_oss_info_unregister(dev, num) snd_oss_info_register(dev, num, NULL)
#endif /* CONFIG_SND_OSSEMUL */
#endif /* CONFIG_SND_OSSEMUL && CONFIG_PROC_FS */
#endif /* __SOUND_INFO_H */
/* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0rc3"
#define CONFIG_SND_DATE " (Fri Oct 04 13:09:13 2002 UTC)"
#define CONFIG_SND_DATE " (Mon Oct 14 16:41:26 2002 UTC)"
......@@ -426,52 +426,59 @@ static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t *_info)
static int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *_control)
{
snd_ctl_elem_value_t control;
snd_ctl_elem_value_t *control;
snd_kcontrol_t *kctl;
int result, indirect;
if (copy_from_user(&control, _control, sizeof(control)))
control = kmalloc(sizeof(*control), GFP_KERNEL);
if (control == NULL)
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);
kctl = snd_ctl_find_id(card, &control->id);
if (kctl == NULL) {
result = -ENOENT;
} else {
indirect = kctl->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT ? 1 : 0;
if (control.indirect != indirect) {
if (control->indirect != indirect) {
result = -EACCES;
} else {
if ((kctl->access & SNDRV_CTL_ELEM_ACCESS_READ) && kctl->get != NULL) {
result = kctl->get(kctl, &control);
result = kctl->get(kctl, control);
if (result >= 0)
control.id = kctl->id;
control->id = kctl->id;
} else
result = -EPERM;
}
}
read_unlock(&card->control_rwlock);
if (result >= 0)
if (copy_to_user(_control, &control, sizeof(control)))
if (copy_to_user(_control, control, sizeof(*control)))
return -EFAULT;
kfree(control);
return result;
}
static int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t *_control)
{
snd_card_t *card = file->card;
snd_ctl_elem_value_t control;
snd_ctl_elem_value_t *control;
snd_kcontrol_t *kctl;
int result, indirect;
if (copy_from_user(&control, _control, sizeof(control)))
control = kmalloc(sizeof(*control), GFP_KERNEL);
if (control == NULL)
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);
kctl = snd_ctl_find_id(card, &control->id);
if (kctl == NULL) {
result = -ENOENT;
} else {
indirect = kctl->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT ? 1 : 0;
if (control.indirect != indirect) {
if (control->indirect != indirect) {
result = -EACCES;
} else {
read_lock(&card->control_owner_lock);
......@@ -480,9 +487,9 @@ static int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t *_contr
(kctl->owner != NULL && kctl->owner != file)) {
result = -EPERM;
} else {
result = kctl->put(kctl, &control);
result = kctl->put(kctl, control);
if (result >= 0)
control.id = kctl->id;
control->id = kctl->id;
}
read_unlock(&card->control_owner_lock);
if (result > 0) {
......@@ -496,8 +503,9 @@ static int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t *_contr
read_unlock(&card->control_rwlock);
__unlocked:
if (result >= 0)
if (copy_to_user(_control, &control, sizeof(control)))
if (copy_to_user(_control, control, sizeof(*control)))
return -EFAULT;
kfree(control);
return result;
}
......
......@@ -28,7 +28,7 @@
#include <sound/version.h>
#include <linux/utsname.h>
#ifdef CONFIG_SND_OSSEMUL
#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
/*
* OSS compatible part
......
......@@ -216,7 +216,7 @@ static void snd_card_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buff
snd_iprintf(buffer, "--- no soundcards ---\n");
}
#ifdef CONFIG_SND_OSSEMUL
#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
void snd_card_info_read_oss(snd_info_buffer_t * buffer)
{
......
......@@ -23,6 +23,7 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/time.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <sound/core.h>
#include <sound/control.h>
......@@ -264,46 +265,56 @@ static int get_ctl_type(struct file *file, snd_ctl_elem_id_t *id)
static int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
{
// too big?
struct sndrv_ctl_elem_value data;
struct sndrv_ctl_elem_value32 data32;
struct sndrv_ctl_elem_value *data;
struct sndrv_ctl_elem_value32 *data32;
int err, i;
int type;
mm_segment_t oldseg;
/* FIXME: check the sane ioctl.. */
if (copy_from_user(&data32, (void*)arg, sizeof(data32)))
return -EFAULT;
memset(&data, 0, sizeof(data));
data.id = data32.id;
data.indirect = data32.indirect;
if (data.indirect) /* FIXME: this is not correct for long arrays */
data.value.integer.value_ptr = (void*)TO_PTR(data32.value.integer.value_ptr);
type = get_ctl_type(file, &data.id);
if (type < 0)
return type;
if (! data.indirect) {
data = kmalloc(sizeof(*data), GFP_KERNEL);
data32 = kmalloc(sizeof(*data32), GFP_KERNEL);
if (data == NULL || data32 == NULL) {
err = -ENOMEM;
goto __end;
}
if (copy_from_user(data32, (void*)arg, sizeof(*data32))) {
err = -EFAULT;
goto __end;
}
memset(data, 0, sizeof(*data));
data->id = data32->id;
data->indirect = data32->indirect;
if (data->indirect) /* FIXME: this is not correct for long arrays */
data->value.integer.value_ptr = (void*)TO_PTR(data32->value.integer.value_ptr);
type = get_ctl_type(file, &data->id);
if (type < 0) {
err = type;
goto __end;
}
if (! data->indirect) {
switch (type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
case SNDRV_CTL_ELEM_TYPE_INTEGER:
for (i = 0; i < 128; i++)
data.value.integer.value[i] = data32.value.integer.value[i];
data->value.integer.value[i] = data32->value.integer.value[i];
break;
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
for (i = 0; i < 64; i++)
data.value.integer64.value[i] = data32.value.integer64.value[i];
data->value.integer64.value[i] = data32->value.integer64.value[i];
break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
for (i = 0; i < 128; i++)
data.value.enumerated.item[i] = data32.value.enumerated.item[i];
data->value.enumerated.item[i] = data32->value.enumerated.item[i];
break;
case SNDRV_CTL_ELEM_TYPE_BYTES:
memcpy(data.value.bytes.data, data32.value.bytes.data,
sizeof(data.value.bytes.data));
memcpy(data->value.bytes.data, data32->value.bytes.data,
sizeof(data->value.bytes.data));
break;
case SNDRV_CTL_ELEM_TYPE_IEC958:
data.value.iec958 = data32.value.iec958;
data->value.iec958 = data32->value.iec958;
break;
default:
printk("unknown type %d\n", type);
......@@ -313,40 +324,46 @@ static int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsign
oldseg = get_fs();
set_fs(KERNEL_DS);
err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
set_fs(oldseg);
if (err < 0)
return err;
goto __end;
/* restore info to 32bit */
if (! data.indirect) {
if (! data->indirect) {
switch (type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
case SNDRV_CTL_ELEM_TYPE_INTEGER:
for (i = 0; i < 128; i++)
data32.value.integer.value[i] = data.value.integer.value[i];
data32->value.integer.value[i] = data->value.integer.value[i];
break;
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
for (i = 0; i < 64; i++)
data32.value.integer64.value[i] = data.value.integer64.value[i];
data32->value.integer64.value[i] = data->value.integer64.value[i];
break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
for (i = 0; i < 128; i++)
data32.value.enumerated.item[i] = data.value.enumerated.item[i];
data32->value.enumerated.item[i] = data->value.enumerated.item[i];
break;
case SNDRV_CTL_ELEM_TYPE_BYTES:
memcpy(data32.value.bytes.data, data.value.bytes.data,
sizeof(data.value.bytes.data));
memcpy(data32->value.bytes.data, data->value.bytes.data,
sizeof(data->value.bytes.data));
break;
case SNDRV_CTL_ELEM_TYPE_IEC958:
data32.value.iec958 = data.value.iec958;
data32->value.iec958 = data->value.iec958;
break;
default:
break;
}
}
if (copy_to_user((void*)arg, &data32, sizeof(data32)))
return -EFAULT;
return 0;
err = 0;
if (copy_to_user((void*)arg, data32, sizeof(*data32)))
err = -EFAULT;
__end:
if (data32)
kfree(data32);
if (data)
kfree(data);
return err;
}
DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_read, ctl_elem_value, SNDRV_CTL_IOCTL_ELEM_READ);
......
......@@ -79,6 +79,44 @@ static int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long
return 0;\
}
#define DEFINE_ALSA_IOCTL_BIG(type) \
static int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
{\
struct sndrv_##type##32 *data32;\
struct sndrv_##type *data;\
mm_segment_t oldseg;\
int err;\
data32 = kmalloc(sizeof(*data32), GFP_KERNEL); \
data = kmalloc(sizeof(*data), GFP_KERNEL); \
if (data32 == NULL || data == NULL) { \
err = -ENOMEM; \
goto __end; \
}\
if (copy_from_user(data32, (void*)arg, sizeof(*data32))) { \
err = -EFAULT; \
goto __end; \
}\
memset(data, 0, sizeof(*data));\
convert_from_32(type, data, data32);\
oldseg = get_fs();\
set_fs(KERNEL_DS);\
err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);\
if (err < 0) \
goto __end;\
err = 0;\
if (native_ctl & (_IOC_READ << _IOC_DIRSHIFT)) {\
convert_to_32(type, data32, data);\
if (copy_to_user((void*)arg, data32, sizeof(*data32)))\
err = -EFAULT;\
}\
__end:\
if (data)\
kfree(data);\
if (data32)\
kfree(data32);\
return err;\
}
#define DEFINE_ALSA_IOCTL_ENTRY(name,type,native_ctl) \
static int snd_ioctl32_##name(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) {\
return _snd_ioctl32_##type(fd, cmd, arg, file, native_ctl);\
......
......@@ -20,6 +20,7 @@
#include <sound/driver.h>
#include <linux/time.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include "ioctl32.h"
......@@ -172,7 +173,7 @@ struct sndrv_pcm_status32 {
DEFINE_ALSA_IOCTL(pcm_uframes_str);
DEFINE_ALSA_IOCTL(pcm_sframes_str);
DEFINE_ALSA_IOCTL(pcm_hw_params);
DEFINE_ALSA_IOCTL_BIG(pcm_hw_params);
DEFINE_ALSA_IOCTL(pcm_sw_params);
DEFINE_ALSA_IOCTL(pcm_channel_info);
DEFINE_ALSA_IOCTL(pcm_status);
......@@ -230,7 +231,7 @@ static int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long a
snd_pcm_file_t *pcm_file;
snd_pcm_substream_t *substream;
struct sndrv_xfern32 data32, *srcptr = (struct sndrv_xfern32*)arg;
void *bufs[128];
void **bufs = NULL;
int err = 0, ch, i;
u32 *bufptr;
mm_segment_t oldseg;
......@@ -260,6 +261,9 @@ static int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long a
return -EFAULT;
__get_user(data32.bufs, &srcptr->bufs);
bufptr = (u32*)TO_PTR(data32.bufs);
bufs = kmalloc(sizeof(void *) * 128, GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < ch; i++) {
u32 ptr;
if (get_user(ptr, bufptr))
......@@ -278,10 +282,11 @@ static int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long a
break;
}
set_fs(oldseg);
if (err < 0)
return err;
if (put_user(err, &srcptr->result))
return -EFAULT;
if (err >= 0) {
if (put_user(err, &srcptr->result))
err = -EFAULT;
}
kfree(bufs);
return 0;
}
......@@ -343,24 +348,38 @@ static void snd_pcm_hw_convert_to_old_params(struct sndrv_pcm_hw_params_old32 *o
static int _snd_ioctl32_pcm_hw_params_old(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
{
struct sndrv_pcm_hw_params_old32 data32;
struct sndrv_pcm_hw_params data;
struct sndrv_pcm_hw_params_old32 *data32;
struct sndrv_pcm_hw_params *data;
mm_segment_t oldseg;
int err;
if (copy_from_user(&data32, (void*)arg, sizeof(data32)))
return -EFAULT;
snd_pcm_hw_convert_from_old_params(&data, &data32);
data32 = snd_kcalloc(sizeof(*data32), GFP_KERNEL);
data = snd_kcalloc(sizeof(*data), GFP_KERNEL);
if (data32 == NULL || data == NULL) {
err = -ENOMEM;
goto __end;
}
if (copy_from_user(data32, (void*)arg, sizeof(*data32))) {
err = -EFAULT;
goto __end;
}
snd_pcm_hw_convert_from_old_params(data, data32);
oldseg = get_fs();
set_fs(KERNEL_DS);
err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
set_fs(oldseg);
if (err < 0)
return err;
snd_pcm_hw_convert_to_old_params(&data32, &data);
if (copy_to_user((void*)arg, &data32, sizeof(data32)))
return -EFAULT;
return 0;
goto __end;
snd_pcm_hw_convert_to_old_params(data32, data);
err = 0;
if (copy_to_user((void*)arg, data32, sizeof(*data32)))
err = -EFAULT;
__end:
if (data)
kfree(data);
if (data32)
kfree(data32);
return err;
}
......
......@@ -499,10 +499,10 @@ char *snd_kmalloc_strdup(const char *string, int flags)
int copy_to_user_fromio(void *dst, unsigned long src, size_t count)
{
#if defined(__i386_) || defined(CONFIG_SPARC32)
#if defined(__i386__) || defined(CONFIG_SPARC32)
return copy_to_user(dst, (const void*)src, count) ? -EFAULT : 0;
#else
char buf[1024];
char buf[256];
while (count) {
size_t c = count;
if (c > sizeof(buf))
......@@ -520,10 +520,10 @@ int copy_to_user_fromio(void *dst, unsigned long src, size_t count)
int copy_from_user_toio(unsigned long dst, const void *src, size_t count)
{
#if defined(__i386_) || defined(CONFIG_SPARC32)
#if defined(__i386__) || defined(CONFIG_SPARC32)
return copy_from_user((void*)dst, src, count) ? -EFAULT : 0;
#else
char buf[1024];
char buf[256];
while (count) {
size_t c = count;
if (c > sizeof(buf))
......
......@@ -495,18 +495,25 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
snd_kcontrol_t *kctl,
int *left, int *right)
{
snd_ctl_elem_info_t uinfo;
snd_ctl_elem_value_t uctl;
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
snd_runtime_check(kctl != NULL, return);
memset(&uinfo, 0, sizeof(uinfo));
memset(&uctl, 0, sizeof(uctl));
snd_runtime_check(!kctl->info(kctl, &uinfo), return);
snd_runtime_check(!kctl->get(kctl, &uctl), return);
snd_runtime_check(uinfo.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo.value.integer.min != 0 || uinfo.value.integer.max != 1, return);
*left = snd_mixer_oss_conv1(uctl.value.integer.value[0], uinfo.value.integer.min, uinfo.value.integer.max, &pslot->volume[0]);
if (uinfo.count > 1)
*right = snd_mixer_oss_conv1(uctl.value.integer.value[1], uinfo.value.integer.min, uinfo.value.integer.max, &pslot->volume[1]);
uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC);
uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
snd_runtime_check(!kctl->get(kctl, uctl), goto __unalloc);
snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, return);
*left = snd_mixer_oss_conv1(uctl->value.integer.value[0], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[0]);
if (uinfo->count > 1)
*right = snd_mixer_oss_conv1(uctl->value.integer.value[1], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[1]);
__unalloc:
if (uctl)
kfree(uctl);
if (uinfo)
kfree(uinfo);
}
static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer,
......@@ -515,21 +522,28 @@ static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer,
int *left, int *right,
int route)
{
snd_ctl_elem_info_t uinfo;
snd_ctl_elem_value_t uctl;
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
snd_runtime_check(kctl != NULL, return);
memset(&uinfo, 0, sizeof(uinfo));
memset(&uctl, 0, sizeof(uctl));
snd_runtime_check(!kctl->info(kctl, &uinfo), return);
snd_runtime_check(!kctl->get(kctl, &uctl), return);
if (!uctl.value.integer.value[0]) {
uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC);
uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
snd_runtime_check(!kctl->get(kctl, uctl), goto __unalloc);
if (!uctl->value.integer.value[0]) {
*left = 0;
if (uinfo.count == 1)
if (uinfo->count == 1)
*right = 0;
}
if (uinfo.count > 1 && !uctl.value.integer.value[route ? 3 : 1])
if (uinfo->count > 1 && !uctl->value.integer.value[route ? 3 : 1])
*right = 0;
__unalloc:
if (uctl)
kfree(uctl);
if (uinfo)
kfree(uinfo);
}
static int snd_mixer_oss_get_volume1(snd_mixer_oss_file_t *fmixer,
......@@ -566,21 +580,28 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
snd_kcontrol_t *kctl,
int left, int right)
{
snd_ctl_elem_info_t uinfo;
snd_ctl_elem_value_t uctl;
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
int res;
snd_runtime_check(kctl != NULL, return);
memset(&uinfo, 0, sizeof(uinfo));
memset(&uctl, 0, sizeof(uctl));
snd_runtime_check(!kctl->info(kctl, &uinfo), return);
snd_runtime_check(uinfo.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo.value.integer.min != 0 || uinfo.value.integer.max != 1, return);
uctl.value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo.value.integer.min, uinfo.value.integer.max);
if (uinfo.count > 1)
uctl.value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo.value.integer.min, uinfo.value.integer.max);
snd_runtime_check((res = kctl->put(kctl, &uctl)) >= 0, return);
uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC);
uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, return);
uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max);
if (uinfo->count > 1)
uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max);
snd_runtime_check((res = kctl->put(kctl, uctl)) >= 0, goto __unalloc);
if (res > 0)
snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
__unalloc:
if (uctl)
kfree(uctl);
if (uinfo)
kfree(uinfo);
}
static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer,
......@@ -589,27 +610,34 @@ static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer,
int left, int right,
int route)
{
snd_ctl_elem_info_t uinfo;
snd_ctl_elem_value_t uctl;
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
int res;
snd_runtime_check(kctl != NULL, return);
memset(&uinfo, 0, sizeof(uinfo));
memset(&uctl, 0, sizeof(uctl));
snd_runtime_check(!kctl->info(kctl, &uinfo), return);
if (uinfo.count > 1) {
uctl.value.integer.value[0] = left > 0 ? 1 : 0;
uctl.value.integer.value[route ? 3 : 1] = right > 0 ? 1 : 0;
uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC);
uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
if (uinfo->count > 1) {
uctl->value.integer.value[0] = left > 0 ? 1 : 0;
uctl->value.integer.value[route ? 3 : 1] = right > 0 ? 1 : 0;
if (route) {
uctl.value.integer.value[1] =
uctl.value.integer.value[2] = 0;
uctl->value.integer.value[1] =
uctl->value.integer.value[2] = 0;
}
} else {
uctl.value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0;
uctl->value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0;
}
snd_runtime_check((res = kctl->put(kctl, &uctl)) >= 0, return);
snd_runtime_check((res = kctl->put(kctl, uctl)) >= 0, goto __unalloc);
if (res > 0)
snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
__unalloc:
if (uctl)
kfree(uctl);
if (uinfo)
kfree(uinfo);
}
static int snd_mixer_oss_put_volume1(snd_mixer_oss_file_t *fmixer,
......@@ -718,17 +746,21 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, int *active_i
snd_kcontrol_t *kctl;
snd_mixer_oss_slot_t *pslot;
struct slot *slot;
snd_ctl_elem_info_t uinfo;
snd_ctl_elem_value_t uctl;
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
int err, idx;
uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL) {
err = -ENOMEM;
goto __unlock;
}
read_lock(&card->control_rwlock);
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
snd_runtime_check(kctl != NULL, return -ENOENT);
memset(&uinfo, 0, sizeof(uinfo));
memset(&uctl, 0, sizeof(uctl));
snd_runtime_check(!(err = kctl->info(kctl, &uinfo)), read_unlock(&card->control_rwlock); return err);
snd_runtime_check(!(err = kctl->get(kctl, &uctl)), read_unlock(&card->control_rwlock); return err);
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)))
......@@ -739,12 +771,21 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, int *active_i
continue;
if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE))
continue;
if (slot->capture_item == uctl.value.enumerated.item[0]) {
if (slot->capture_item == uctl->value.enumerated.item[0]) {
*active_index = idx;
break;
}
}
return 0;
err = 0;
goto __unalloc;
__unlock:
read_unlock(&card->control_rwlock);
__unalloc:
if (uctl)
kfree(uctl);
if (uinfo)
kfree(uinfo);
return err;
}
static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, int active_index)
......@@ -754,16 +795,20 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, int active_in
snd_kcontrol_t *kctl;
snd_mixer_oss_slot_t *pslot;
struct slot *slot = NULL;
snd_ctl_elem_info_t uinfo;
snd_ctl_elem_value_t uctl;
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
int err, idx;
uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL) {
err = -ENOMEM;
goto __unlock;
}
read_lock(&card->control_rwlock);
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
snd_runtime_check(kctl != NULL, read_unlock(&card->control_rwlock); return -ENOENT);
memset(&uinfo, 0, sizeof(uinfo));
memset(&uctl, 0, sizeof(uctl));
snd_runtime_check(!(err = kctl->info(kctl, &uinfo)), read_unlock(&card->control_rwlock); return err);
snd_runtime_check(kctl != NULL, err = -ENOENT; goto __unlock);
snd_runtime_check(!(err = kctl->info(kctl, uinfo)), goto __unlock);
for (idx = 0; idx < 32; idx++) {
if (!(mixer->mask_recsrc & (1 << idx)))
continue;
......@@ -778,14 +823,19 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, int active_in
slot = NULL;
}
snd_runtime_check(slot != NULL, goto __unlock);
for (idx = 0; idx < uinfo.count; idx++)
uctl.value.enumerated.item[idx] = slot->capture_item;
snd_runtime_check((err = kctl->put(kctl, &uctl)) >= 0, );
for (idx = 0; idx < uinfo->count; idx++)
uctl->value.enumerated.item[idx] = slot->capture_item;
snd_runtime_check((err = kctl->put(kctl, uctl)) >= 0, );
if (err > 0)
snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
err = 0;
__unlock:
read_unlock(&card->control_rwlock);
return 0;
if (uctl)
kfree(uctl);
if (uinfo)
kfree(uinfo);
return err;
}
struct snd_mixer_oss_assign_table {
......@@ -1176,9 +1226,11 @@ static int snd_mixer_oss_notify_handler(snd_card_t * card, int free_flag)
mixer->name[sizeof(mixer->name)-1] = 0;
} else
strcpy(mixer->name, name);
#ifdef SNDRV_OSS_INFO_DEV_MIXERS
snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIXERS,
card->number,
mixer->name);
#endif
for (idx = 0; idx < SNDRV_OSS_MAX_MIXERS; idx++)
mixer->slots[idx].number = idx;
card->mixer_oss = mixer;
......@@ -1188,7 +1240,9 @@ static int snd_mixer_oss_notify_handler(snd_card_t * card, int free_flag)
snd_mixer_oss_t *mixer = card->mixer_oss;
if (mixer == NULL)
return 0;
#ifdef SNDRV_OSS_INFO_DEV_MIXERS
snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIXERS, mixer->card->number);
#endif
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, mixer->card, 0);
snd_mixer_oss_proc_done(mixer);
return snd_mixer_oss_free1(mixer);
......
......@@ -2123,9 +2123,11 @@ static int snd_pcm_oss_register_minor(unsigned short native_minor,
pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count &&
!(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX));
sprintf(name, "%s%s", pcm->name, duplex ? " (DUPLEX)" : "");
#ifdef SNDRV_OSS_INFO_DEV_AUDIO
snd_oss_info_register(SNDRV_OSS_INFO_DEV_AUDIO,
pcm->card->number,
name);
#endif
pcm->oss.reg++;
}
if (snd_adsp_map[pcm->card->number] == pcm->device) {
......@@ -2146,7 +2148,9 @@ static int snd_pcm_oss_unregister_minor(unsigned short native_minor,
if (snd_dsp_map[pcm->card->number] == pcm->device) {
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
pcm->card, 0);
#ifdef SNDRV_OSS_INFO_DEV_AUDIO
snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number);
#endif
}
if (snd_adsp_map[pcm->card->number] == pcm->device)
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
......
......@@ -1473,7 +1473,7 @@ static int boundary_nearer(int min, int mindir,
int snd_pcm_hw_param_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
snd_pcm_hw_param_t var, unsigned int best, int *dir)
{
snd_pcm_hw_params_t save;
snd_pcm_hw_params_t *save = NULL;
int v;
unsigned int saved_min;
int last = 0;
......@@ -1493,30 +1493,42 @@ int snd_pcm_hw_param_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
maxdir = 1;
max--;
}
save = *params;
save = kmalloc(sizeof(*save), GFP_KERNEL);
if (save == NULL)
return -ENOMEM;
*save = *params;
saved_min = min;
min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
if (min >= 0) {
snd_pcm_hw_params_t params1;
snd_pcm_hw_params_t *params1;
if (max < 0)
goto _end;
if ((unsigned int)min == saved_min && mindir == valdir)
goto _end;
params1 = save;
max = snd_pcm_hw_param_max(pcm, &params1, var, max, &maxdir);
if (max < 0)
params1 = kmalloc(sizeof(*params1), GFP_KERNEL);
if (params1 == NULL) {
kfree(save);
return -ENOMEM;
}
*params1 = *save;
max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir);
if (max < 0) {
kfree(params1);
goto _end;
}
if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
*params = params1;
*params = *params1;
last = 1;
}
kfree(params1);
} else {
*params = save;
*params = *save;
max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);
assert(max >= 0);
last = 1;
}
_end:
kfree(save);
if (last)
v = snd_pcm_hw_param_last(pcm, params, var, dir);
else
......@@ -1842,16 +1854,11 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
avail = snd_pcm_playback_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_PAUSED ||
runtime->status->state == SNDRV_PCM_STATE_PREPARED) {
if (avail < runtime->xfer_align) {
err = -EPIPE;
goto _end_unlock;
}
} else if (((avail < runtime->control->avail_min && size > avail) ||
(size >= runtime->xfer_align && avail < runtime->xfer_align))) {
if (((avail < runtime->control->avail_min && size > avail) ||
(size >= runtime->xfer_align && avail < runtime->xfer_align))) {
wait_queue_t wait;
enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED } state;
if (nonblock) {
err = -EAGAIN;
goto _end_unlock;
......@@ -1868,8 +1875,11 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
spin_unlock_irq(&runtime->lock);
if (schedule_timeout(10 * HZ) == 0) {
spin_lock_irq(&runtime->lock);
state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
break;
if (runtime->status->state != SNDRV_PCM_STATE_PREPARED &&
runtime->status->state != SNDRV_PCM_STATE_PAUSED) {
state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
break;
}
}
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
......@@ -1916,10 +1926,6 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
if (frames > cont)
frames = cont;
if (frames == 0 && runtime->status->state == SNDRV_PCM_STATE_PAUSED) {
err = -EPIPE;
goto _end_unlock;
}
snd_assert(frames != 0,
spin_unlock_irq(&runtime->lock);
return -EINVAL);
......@@ -2135,21 +2141,16 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void
if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
avail = snd_pcm_capture_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) {
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
if (avail < runtime->xfer_align) {
err = -EPIPE;
goto _end_unlock;
}
} else if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
if (avail < runtime->xfer_align) {
runtime->status->state = SNDRV_PCM_STATE_SETUP;
err = -EPIPE;
goto _end_unlock;
}
} else if ((avail < runtime->control->avail_min && size > avail) ||
(size >= runtime->xfer_align && avail < runtime->xfer_align)) {
wait_queue_t wait;
enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED } state;
if (nonblock) {
err = -EAGAIN;
goto _end_unlock;
......@@ -2166,8 +2167,11 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void
spin_unlock_irq(&runtime->lock);
if (schedule_timeout(10 * HZ) == 0) {
spin_lock_irq(&runtime->lock);
state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
break;
if (runtime->status->state != SNDRV_PCM_STATE_PREPARED &&
runtime->status->state != SNDRV_PCM_STATE_PAUSED) {
state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
break;
}
}
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
......
......@@ -1848,7 +1848,10 @@ int snd_pcm_release(struct inode *inode, struct file *file)
snd_assert(substream != NULL, return -ENXIO);
snd_assert(!atomic_read(&substream->runtime->mmap_count), );
pcm = substream->pcm;
snd_pcm_capture_drop(substream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
snd_pcm_playback_drop(substream);
else
snd_pcm_capture_drop(substream);
fasync_helper(-1, file, 0, &substream->runtime->fasync);
down(&pcm->open_mutex);
snd_pcm_release_file(pcm_file);
......@@ -1959,34 +1962,29 @@ snd_pcm_sframes_t snd_pcm_capture_rewind(snd_pcm_substream_t *substream, snd_pcm
return ret;
}
static int snd_pcm_playback_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
static int snd_pcm_hwsync(snd_pcm_substream_t *substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
int err = 0;
snd_pcm_sframes_t n;
int err;
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_DRAINING:
if (snd_pcm_update_hw_ptr(substream) >= 0) {
n = snd_pcm_playback_hw_avail(runtime);
if (put_user(n, res))
err = -EFAULT;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
goto __badfd;
case SNDRV_PCM_STATE_RUNNING:
if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
break;
} else {
err = SNDRV_PCM_STATE_RUNNING ? -EPIPE : -EBADFD;
}
break;
/* Fall through */
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_SUSPENDED:
if (runtime->status->suspended_state == SNDRV_PCM_STATE_RUNNING) {
n = snd_pcm_playback_hw_avail(runtime);
if (put_user(n, res))
err = -EFAULT;
} else {
err = -EBADFD;
}
err = 0;
break;
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
break;
default:
__badfd:
err = -EBADFD;
break;
}
......@@ -1994,41 +1992,43 @@ static int snd_pcm_playback_delay(snd_pcm_substream_t *substream, snd_pcm_sframe
return err;
}
static int snd_pcm_capture_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
static int snd_pcm_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
{
snd_pcm_runtime_t *runtime = substream->runtime;
int err = 0;
int err;
snd_pcm_sframes_t n;
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_DRAINING:
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
goto __badfd;
case SNDRV_PCM_STATE_RUNNING:
if (snd_pcm_update_hw_ptr(substream) >= 0) {
n = snd_pcm_capture_avail(runtime);
if (put_user(n, res))
err = -EFAULT;
if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
break;
}
/* Fall through */
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
break;
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_SUSPENDED:
if (runtime->status->suspended_state == SNDRV_PCM_STATE_RUNNING) {
err = 0;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
n = snd_pcm_playback_hw_avail(runtime);
else
n = snd_pcm_capture_avail(runtime);
if (put_user(n, res))
err = -EFAULT;
} else {
err = -EBADFD;
}
if (put_user(n, res))
err = -EFAULT;
break;
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
break;
default:
__badfd:
err = -EBADFD;
break;
}
spin_unlock_irq(&runtime->lock);
return err;
}
static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
unsigned int cmd, void *arg);
static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
......@@ -2076,6 +2076,10 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_resume(substream);
case SNDRV_PCM_IOCTL_XRUN:
return snd_pcm_xrun(substream);
case SNDRV_PCM_IOCTL_HWSYNC:
return snd_pcm_hwsync(substream);
case SNDRV_PCM_IOCTL_DELAY:
return snd_pcm_delay(substream, (snd_pcm_sframes_t *) arg);
case SNDRV_PCM_IOCTL_HW_REFINE_OLD:
return snd_pcm_hw_refine_old_user(substream, (struct sndrv_pcm_hw_params_old *) arg);
case SNDRV_PCM_IOCTL_HW_PARAMS_OLD:
......@@ -2110,7 +2114,7 @@ static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
{
snd_xfern_t xfern, *_xfern = arg;
snd_pcm_runtime_t *runtime = substream->runtime;
void *bufs[128];
void *bufs;
snd_pcm_sframes_t result;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
......@@ -2120,9 +2124,15 @@ static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
return -EFAULT;
if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
return -EFAULT;
if (copy_from_user(bufs, xfern.bufs, sizeof(*bufs) * runtime->channels))
bufs = kmalloc(sizeof(void *) * runtime->channels, GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
if (copy_from_user(bufs, xfern.bufs, sizeof(void *) * runtime->channels)) {
kfree(bufs);
return -EFAULT;
}
result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
kfree(bufs);
__put_user(result, &_xfern->result);
return result < 0 ? result : 0;
}
......@@ -2150,8 +2160,6 @@ static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_playback_drain(substream);
case SNDRV_PCM_IOCTL_DROP:
return snd_pcm_playback_drop(substream);
case SNDRV_PCM_IOCTL_DELAY:
return snd_pcm_playback_delay(substream, (snd_pcm_sframes_t*) arg);
}
return snd_pcm_common_ioctl1(substream, cmd, arg);
}
......@@ -2181,7 +2189,7 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
{
snd_xfern_t xfern, *_xfern = arg;
snd_pcm_runtime_t *runtime = substream->runtime;
void *bufs[128];
void *bufs;
snd_pcm_sframes_t result;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
......@@ -2191,9 +2199,15 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
return -EFAULT;
if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
return -EFAULT;
if (copy_from_user(bufs, xfern.bufs, sizeof(*bufs) * runtime->channels))
bufs = kmalloc(sizeof(void *) * runtime->channels, GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
if (copy_from_user(bufs, xfern.bufs, sizeof(void *) * runtime->channels)) {
kfree(bufs);
return -EFAULT;
}
result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
kfree(bufs);
__put_user(result, &_xfern->result);
return result < 0 ? result : 0;
}
......@@ -2213,8 +2227,6 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_capture_drain(substream);
case SNDRV_PCM_IOCTL_DROP:
return snd_pcm_capture_drop(substream);
case SNDRV_PCM_IOCTL_DELAY:
return snd_pcm_capture_delay(substream, (snd_pcm_sframes_t*) arg);
}
return snd_pcm_common_ioctl1(substream, cmd, arg);
}
......@@ -2311,7 +2323,9 @@ static ssize_t snd_pcm_write(struct file *file, const char *buf, size_t count, l
snd_pcm_runtime_t *runtime;
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);
substream = pcm_file->substream;
snd_assert(substream != NULL, result = -ENXIO; goto end);
......@@ -2329,7 +2343,9 @@ static ssize_t snd_pcm_write(struct file *file, const char *buf, size_t count, l
if (result > 0)
result = frames_to_bytes(runtime, result);
end:
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
down(&file->f_dentry->d_inode->i_sem);
#endif
return result;
}
......@@ -2343,7 +2359,7 @@ static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector,
snd_pcm_runtime_t *runtime;
snd_pcm_sframes_t result;
unsigned long i;
void *bufs[128];
void **bufs;
snd_pcm_uframes_t frames;
pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
......@@ -2352,16 +2368,20 @@ static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector,
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (count > 128 || count != runtime->channels)
if (count > 1024 || count != runtime->channels)
return -EINVAL;
if (!frame_aligned(runtime, _vector->iov_len))
return -EINVAL;
frames = bytes_to_samples(runtime, _vector->iov_len);
bufs = kmalloc(sizeof(void *) * count, GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < count; ++i)
bufs[i] = _vector[i].iov_base;
result = snd_pcm_lib_readv(substream, bufs, frames);
if (result > 0)
result = frames_to_bytes(runtime, result);
kfree(bufs);
return result;
}
......@@ -2373,10 +2393,12 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector,
snd_pcm_runtime_t *runtime;
snd_pcm_sframes_t result;
unsigned long i;
void *bufs[128];
void **bufs;
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);
substream = pcm_file->substream;
snd_assert(substream != NULL, result = -ENXIO; goto end);
......@@ -2391,13 +2413,19 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector,
goto end;
}
frames = bytes_to_samples(runtime, _vector->iov_len);
bufs = kmalloc(sizeof(void *) * count, GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < count; ++i)
bufs[i] = _vector[i].iov_base;
result = snd_pcm_lib_writev(substream, bufs, frames);
if (result > 0)
result = frames_to_bytes(runtime, result);
kfree(bufs);
end:
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
down(&file->f_dentry->d_inode->i_sem);
#endif
return result;
}
#endif
......@@ -2422,6 +2450,8 @@ unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
avail = snd_pcm_playback_avail(runtime);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
if (avail >= runtime->control->avail_min) {
mask = POLLOUT | POLLWRNORM;
break;
......@@ -2430,12 +2460,6 @@ unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
case SNDRV_PCM_STATE_DRAINING:
mask = 0;
break;
case SNDRV_PCM_STATE_PREPARED:
if (avail > 0) {
mask = POLLOUT | POLLWRNORM;
break;
}
/* Fall through */
default:
mask = POLLOUT | POLLWRNORM | POLLERR;
break;
......@@ -2464,6 +2488,8 @@ unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
avail = snd_pcm_capture_avail(runtime);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
if (avail >= runtime->control->avail_min) {
mask = POLLIN | POLLRDNORM;
break;
......
......@@ -1425,7 +1425,9 @@ static int snd_rawmidi_dev_register(snd_device_t *device)
snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0);
} else {
rmidi->ossreg++;
#ifdef SNDRV_OSS_INFO_DEV_MIDI
snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIDI, rmidi->card->number, rmidi->name);
#endif
}
}
if (rmidi->device == snd_amidi_map[rmidi->card->number]) {
......@@ -1436,7 +1438,7 @@ static int snd_rawmidi_dev_register(snd_device_t *device)
rmidi->ossreg++;
}
}
#endif
#endif /* CONFIG_SND_OSSEMUL */
up(&register_mutex);
sprintf(name, "midi%d", rmidi->device);
entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root);
......@@ -1484,13 +1486,15 @@ static int snd_rawmidi_dev_unregister(snd_device_t *device)
if (rmidi->ossreg) {
if (rmidi->device == snd_midi_map[rmidi->card->number]) {
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, rmidi->card, 0);
#ifdef SNDRV_OSS_INFO_DEV_MIDI
snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIDI, rmidi->card->number);
#endif
}
if (rmidi->device == snd_amidi_map[rmidi->card->number])
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, rmidi->card, 1);
rmidi->ossreg = 0;
}
#endif
#endif /* CONFIG_SND_OSSEMUL */
if (rmidi->ops && rmidi->ops->dev_unregister)
rmidi->ops->dev_unregister(rmidi);
snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
......
......@@ -159,9 +159,10 @@ snd_seq_oss_readq_pick(seq_oss_readq_t *q, int blocking, unsigned long *rflags)
spin_lock_irqsave(&q->lock, *rflags);
if (q->qlen == 0) {
if (blocking) {
snd_seq_sleep_timeout_in_lock(&q->midi_sleep,
&q->lock,
q->pre_event_timeout);
spin_unlock(&q->lock);
interruptible_sleep_on_timeout(&q->midi_sleep,
q->pre_event_timeout);
spin_lock(&q->lock);
}
if (q->qlen == 0) {
spin_unlock_irqrestore(&q->lock, *rflags);
......
......@@ -146,8 +146,10 @@ snd_seq_oss_synth_register(snd_seq_device_t *dev)
debug_printk(("synth %s registered %d\n", rec->name, i));
spin_unlock_irqrestore(&register_lock, flags);
dev->driver_data = rec;
#ifdef SNDRV_OSS_INFO_DEV_SYNTH
if (i < SNDRV_CARDS)
snd_oss_info_register(SNDRV_OSS_INFO_DEV_SYNTH, i, rec->name);
#endif
return 0;
}
......@@ -178,8 +180,10 @@ snd_seq_oss_synth_unregister(snd_seq_device_t *dev)
max_synth_devs = index + 1;
}
spin_unlock_irqrestore(&register_lock, flags);
#ifdef SNDRV_OSS_INFO_DEV_SYNTH
if (rec->seq_device < SNDRV_CARDS)
snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_SYNTH, rec->seq_device);
#endif
snd_use_lock_sync(&rec->use_lock);
kfree(rec);
......
......@@ -122,7 +122,9 @@ snd_seq_oss_writeq_sync(seq_oss_writeq_t *q)
}
/* wait for echo event */
snd_seq_sleep_timeout_in_lock(&q->sync_sleep, &q->sync_lock, HZ);
spin_unlock(&q->sync_lock);
interruptible_sleep_on_timeout(&q->sync_sleep, HZ);
spin_lock(&q->sync_lock);
if (signal_pending(current)) {
/* interrupted - return 0 to finish sync */
q->sync_event_put = 0;
......
......@@ -135,7 +135,7 @@ EXPORT_SYMBOL(snd_seq_event_port_attach);
EXPORT_SYMBOL(snd_seq_event_port_detach);
/* seq_lock.c */
#if defined(__SMP__) || defined(CONFIG_SND_DEBUG)
EXPORT_SYMBOL(snd_seq_sleep_in_lock);
EXPORT_SYMBOL(snd_seq_sleep_timeout_in_lock);
/*EXPORT_SYMBOL(snd_seq_sleep_in_lock);*/
/*EXPORT_SYMBOL(snd_seq_sleep_timeout_in_lock);*/
EXPORT_SYMBOL(snd_use_lock_sync_helper);
#endif
......@@ -152,9 +152,11 @@ client_t *snd_seq_client_use_ptr(int clientid)
}
} else if (clientid >= 64 && clientid < 128) {
int card = (clientid - 64) / 8;
if (card < snd_ecards_limit && ! card_requested[card]) {
card_requested[card] = 1;
snd_request_card(card);
if (card < snd_ecards_limit) {
if (! card_requested[card]) {
card_requested[card] = 1;
snd_request_card(card);
}
snd_seq_device_load_drivers();
}
}
......
......@@ -182,7 +182,9 @@ int snd_seq_fifo_cell_out(fifo_t *f, snd_seq_event_cell_t **cellp, int nonblock)
spin_unlock_irqrestore(&f->lock, flags);
return -EAGAIN;
}
snd_seq_sleep_in_lock(&f->input_sleep, &f->lock);
spin_unlock(&f->lock);
interruptible_sleep_on(&f->input_sleep);
spin_lock(&f->lock);
if (signal_pending(current)) {
spin_unlock_irqrestore(&f->lock, flags);
......
......@@ -25,6 +25,7 @@
#if defined(__SMP__) || defined(CONFIG_SND_DEBUG)
#if 0 /* NOT USED */
/* (interruptible) sleep_on during the specified spinlock */
void snd_seq_sleep_in_lock(wait_queue_head_t *p, spinlock_t *lock)
{
......@@ -60,6 +61,7 @@ long snd_seq_sleep_timeout_in_lock(wait_queue_head_t *p, spinlock_t *lock, long
return timeout;
}
#endif /* NOT USED */
/* wait until all locks are released */
void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line)
......
......@@ -20,12 +20,6 @@ typedef atomic_t snd_use_lock_t;
void snd_use_lock_sync_helper(snd_use_lock_t *lock, const char *file, int line);
#define snd_use_lock_sync(lockp) snd_use_lock_sync_helper(lockp, __BASE_FILE__, __LINE__)
/* (interruptible) sleep_on during the specified spinlock */
void snd_seq_sleep_in_lock(wait_queue_head_t *p, spinlock_t *lock);
/* (interruptible) sleep_on with timeout during the specified spinlock */
long snd_seq_sleep_timeout_in_lock(wait_queue_head_t *p, spinlock_t *lock, long timeout);
#else /* SMP || CONFIG_SND_DEBUG */
typedef spinlock_t snd_use_lock_t; /* dummy */
......@@ -34,9 +28,6 @@ typedef spinlock_t snd_use_lock_t; /* dummy */
#define snd_use_lock_free(lockp) /**/
#define snd_use_lock_sync(lockp) /**/
#define snd_seq_sleep_in_lock(p,lock) interruptible_sleep_on(p)
#define snd_seq_sleep_timeout_in_lock(p,lock,timeout) interruptible_sleep_on_timeout(p,timeout)
#endif /* SMP || CONFIG_SND_DEBUG */
#endif /* __SND_SEQ_LOCK_H */
......@@ -233,17 +233,21 @@ int snd_seq_cell_alloc(pool_t *pool, snd_seq_event_cell_t **cellp, int nonblock,
goto __error;
}
while (pool->free == NULL && ! nonblock && ! pool->closing) {
spin_unlock(&pool->lock);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
/* change semaphore to allow other clients
to access device file */
if (file)
up(&semaphore_of(file));
snd_seq_sleep_in_lock(&pool->output_sleep, &pool->lock);
#endif
interruptible_sleep_on(&pool->output_sleep);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
/* restore semaphore again */
if (file)
down(&semaphore_of(file));
#endif
spin_lock(&pool->lock);
/* interrupted? */
if (signal_pending(current)) {
err = -ERESTARTSYS;
......
......@@ -318,9 +318,6 @@ static int __init alsa_sound_init(void)
#endif
if (register_chrdev(snd_major, "alsa", &snd_fops)) {
snd_printk(KERN_ERR "unable to register native major device number %d\n", snd_major);
#ifdef CONFIG_SND_OSSEMUL
snd_oss_cleanup_module();
#endif
return -EIO;
}
#ifdef CONFIG_SND_DEBUG_MEMORY
......@@ -329,9 +326,6 @@ static int __init alsa_sound_init(void)
if (snd_info_init() < 0) {
#ifdef CONFIG_SND_DEBUG_MEMORY
snd_memory_done();
#endif
#ifdef CONFIG_SND_OSSEMUL
snd_oss_cleanup_module();
#endif
return -ENOMEM;
}
......@@ -369,7 +363,6 @@ static void __exit alsa_sound_exit(void)
#ifdef CONFIG_SND_OSSEMUL
snd_info_minor_unregister();
snd_oss_cleanup_module();
#endif
snd_info_done();
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) && defined(CONFIG_APM)
......@@ -455,6 +448,7 @@ EXPORT_SYMBOL(snd_dma_disable);
EXPORT_SYMBOL(snd_dma_residue);
#endif
/* info.c */
#ifdef CONFIG_PROC_FS
EXPORT_SYMBOL(snd_seq_root);
EXPORT_SYMBOL(snd_create_proc_entry);
EXPORT_SYMBOL(snd_remove_proc_entry);
......@@ -468,8 +462,9 @@ EXPORT_SYMBOL(snd_info_create_device);
EXPORT_SYMBOL(snd_info_free_device);
EXPORT_SYMBOL(snd_info_register);
EXPORT_SYMBOL(snd_info_unregister);
#endif
/* info_oss.c */
#ifdef CONFIG_SND_OSSEMUL
#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
EXPORT_SYMBOL(snd_oss_info_register);
#endif
/* control.c */
......
......@@ -183,6 +183,8 @@ int snd_unregister_oss_device(int type, snd_card_t * card, int dev)
* INFO PART
*/
#ifdef CONFIG_PROC_FS
static snd_info_entry_t *snd_minor_info_oss_entry = NULL;
static void snd_minor_info_oss_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
......@@ -207,8 +209,11 @@ static void snd_minor_info_oss_read(snd_info_entry_t *entry, snd_info_buffer_t *
up(&sound_oss_mutex);
}
#endif /* CONFIG_PROC_FS */
int __init snd_minor_info_oss_init(void)
{
#ifdef CONFIG_PROC_FS
snd_info_entry_t *entry;
entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root);
......@@ -222,13 +227,16 @@ int __init snd_minor_info_oss_init(void)
}
}
snd_minor_info_oss_entry = entry;
#endif
return 0;
}
int __exit snd_minor_info_oss_done(void)
{
#ifdef CONFIG_PROC_FS
if (snd_minor_info_oss_entry)
snd_info_unregister(snd_minor_info_oss_entry);
#endif
return 0;
}
......@@ -241,8 +249,4 @@ int __init snd_oss_init_module(void)
return 0;
}
void snd_oss_cleanup_module(void)
{
}
#endif /* CONFIG_SND_OSSEMUL */
......@@ -1356,7 +1356,7 @@ static int __init alsa_timer_init(void)
int err;
snd_info_entry_t *entry;
#ifdef CONFIG_SND_OSSEMUL
#ifdef SNDRV_OSS_INFO_DEV_TIMERS
snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1, "system timer");
#endif
if ((entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL)) != NULL) {
......@@ -1391,7 +1391,7 @@ static void __exit alsa_timer_exit(void)
snd_info_unregister(snd_timer_proc_entry);
snd_timer_proc_entry = NULL;
}
#ifdef CONFIG_SND_OSSEMUL
#ifdef SNDRV_OSS_INFO_DEV_TIMERS
snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1);
#endif
}
......
......@@ -1311,12 +1311,12 @@ static int __init snd_es18xx_initialize(es18xx_t *chip)
if (chip->caps & ES18XX_CONTROL) {
/* Hardware volume IRQ */
snd_es18xx_config_write(chip, 0x27, chip->irq);
if (chip->fm_port > SNDRV_AUTO_PORT) {
if (chip->fm_port > 0 && chip->fm_port != SNDRV_AUTO_PORT) {
/* FM I/O */
snd_es18xx_config_write(chip, 0x62, chip->fm_port >> 8);
snd_es18xx_config_write(chip, 0x63, chip->fm_port & 0xff);
}
if (chip->mpu_port > SNDRV_AUTO_PORT) {
if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
/* MPU-401 I/O */
snd_es18xx_config_write(chip, 0x64, chip->mpu_port >> 8);
snd_es18xx_config_write(chip, 0x65, chip->mpu_port & 0xff);
......@@ -1404,7 +1404,7 @@ static int __init snd_es18xx_initialize(es18xx_t *chip)
snd_es18xx_mixer_write(chip, 0x7A, 0x68);
/* Enable and set hardware volume interrupt */
snd_es18xx_mixer_write(chip, 0x64, 0x06);
if (chip->mpu_port > SNDRV_AUTO_PORT) {
if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
/* MPU401 share irq with audio
Joystick enabled
FM enabled */
......@@ -2040,7 +2040,7 @@ static int __init snd_audiodrive_isapnp(int dev, struct snd_audiodrive *acard)
/* skip csn and logdev initialization - already done in isapnp_configure */
isapnp_cfg_begin(pdev->bus->number, pdev->devfn);
isapnp_write_byte(0x27, pdev->irq_resource[0].start); /* Hardware Volume IRQ Number */
if (snd_mpu_port[dev] > SNDRV_AUTO_PORT)
if (snd_mpu_port[dev] != SNDRV_AUTO_PORT)
isapnp_write_byte(0x28, pdev->irq); /* MPU-401 IRQ Number */
isapnp_write_byte(0x72, pdev->irq_resource[0].start); /* second IRQ */
isapnp_cfg_end();
......@@ -2147,16 +2147,18 @@ static int __init snd_audiodrive_probe(int dev)
return err;
}
if (snd_opl3_create(card, chip->fm_port, chip->fm_port + 2, OPL3_HW_OPL3, 0, &opl3) < 0) {
printk(KERN_ERR PFX "opl3 not detected at 0x%lx\n", chip->port);
} else {
if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
snd_card_free(card);
return err;
if (snd_fm_port[dev] > 0 && snd_fm_port[dev] != SNDRV_AUTO_PORT) {
if (snd_opl3_create(card, chip->fm_port, chip->fm_port + 2, OPL3_HW_OPL3, 0, &opl3) < 0) {
printk(KERN_ERR PFX "opl3 not detected at 0x%lx\n", chip->fm_port);
} else {
if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
snd_card_free(card);
return err;
}
}
}
if (snd_mpu_port[dev] != SNDRV_AUTO_PORT) {
if (snd_mpu_port[dev] > 0 && snd_mpu_port[dev] != SNDRV_AUTO_PORT) {
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX,
chip->mpu_port, 0,
irq, 0,
......
......@@ -22,7 +22,6 @@
#include <sound/driver.h>
#include <asm/io.h>
#include <linux/init.h>
#include <linux/isapnp.h>
#include <linux/pm.h>
#include <linux/slab.h>
#ifndef LINUX_ISAPNP_H
......
......@@ -1138,11 +1138,13 @@ snd_emu8000_new(snd_card_t *card, int index, long port, int seq_ports, snd_seq_d
snd_emu8000_free(hw);
return err;
}
#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
sizeof(emu8000_t*), &awe) >= 0) {
strcpy(awe->name, "EMU-8000");
*(emu8000_t**)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw;
}
#endif
if (awe_ret)
*awe_ret = awe;
......
......@@ -114,7 +114,7 @@ MODULE_PARM_DESC(osrun_time, "how many seconds to wait for the ICS2115 OS");
#ifdef WF_DEBUG
#ifdef NEW_MACRO_VARARGS
#if defined(NEW_MACRO_VARARGS) || __GNUC__ >= 3
#define DPRINT(cond, ...) \
if ((dev->debug & (cond)) == (cond)) { \
snd_printk (__VA_ARGS__); \
......
......@@ -77,7 +77,7 @@ CONFIG_SND_ICE1712
CONFIG_SND_INTEL8X0
Say 'Y' or 'M' to include support for Intel8x0 based soundcards,
SiS 7012, AMD768/8111 and NVidia NForce chips.
SiS 7012, AMD768/8111, NVidia NForce and ALi 5455 chips.
CONFIG_SND_SONICVIBES
Say 'Y' or 'M' to include support for S3 SonicVibes based soundcards.
......
......@@ -4,9 +4,9 @@ mainmenu_option next_comment
comment 'PCI devices'
dep_tristate 'ALi PCI Audio M5451' CONFIG_SND_ALI5451 $CONFIG_SND
dep_tristate 'Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x' CONFIG_SND_CS46XX $CONFIG_SND
dep_tristate 'Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x' CONFIG_SND_CS46XX $CONFIG_SND $CONFIG_SOUND_GAMEPORT
dep_mbool ' Cirrus Logic (Sound Fusion) New DSP support (EXPERIMENTAL)' CONFIG_SND_CS46XX_NEW_DSP $CONFIG_SND_CS46XX $CONFIG_EXPERIMENTAL
dep_tristate 'Cirrus Logic (Sound Fusion) CS4281' CONFIG_SND_CS4281 $CONFIG_SND
dep_tristate 'Cirrus Logic (Sound Fusion) CS4281' CONFIG_SND_CS4281 $CONFIG_SND $CONFIG_SOUND_GAMEPORT
dep_tristate 'EMU10K1 (SB Live! & Audigy, E-mu APS)' CONFIG_SND_EMU10K1 $CONFIG_SND
dep_tristate 'Korg 1212 IO' CONFIG_SND_KORG1212 $CONFIG_SND
dep_tristate 'NeoMagic NM256AV/ZX' CONFIG_SND_NM256 $CONFIG_SND
......@@ -14,30 +14,19 @@ dep_tristate 'RME Digi32, 32/8, 32 PRO' CONFIG_SND_RME32 $CONFIG_SND
dep_tristate 'RME Digi96, 96/8, 96/8 PRO' CONFIG_SND_RME96 $CONFIG_SND
dep_tristate 'RME Digi9652 (Hammerfall)' CONFIG_SND_RME9652 $CONFIG_SND
dep_tristate 'RME Hammerfall DSP Audio' CONFIG_SND_HDSP $CONFIG_SND
dep_tristate 'Trident 4D-Wave DX/NX; SiS 7018' CONFIG_SND_TRIDENT $CONFIG_SND
dep_tristate 'Trident 4D-Wave DX/NX; SiS 7018' CONFIG_SND_TRIDENT $CONFIG_SND $CONFIG_SOUND_GAMEPORT
dep_tristate 'Yamaha YMF724/740/744/754' CONFIG_SND_YMFPCI $CONFIG_SND
dep_tristate 'Avance Logic ALS4000' CONFIG_SND_ALS4000 $CONFIG_SND
dep_tristate 'C-Media 8738, 8338' CONFIG_SND_CMIPCI $CONFIG_SND
dep_tristate '(Creative) Ensoniq AudioPCI 1370' CONFIG_SND_ENS1370 $CONFIG_SND
dep_tristate '(Creative) Ensoniq AudioPCI 1371/1373' CONFIG_SND_ENS1371 $CONFIG_SND
dep_tristate 'ESS ES1938/1946 (Solo-1)' CONFIG_SND_ES1938 $CONFIG_SND
dep_tristate 'ESS ES1938/1946 (Solo-1)' CONFIG_SND_ES1938 $CONFIG_SND $CONFIG_SOUND_GAMEPORT
dep_tristate 'ESS ES1968/1978 (Maestro-1/2/2E)' CONFIG_SND_ES1968 $CONFIG_SND
dep_tristate 'ESS Allegro/Maestro3' CONFIG_SND_MAESTRO3 $CONFIG_SND
dep_tristate 'ForteMedia FM801' CONFIG_SND_FM801 $CONFIG_SND
dep_tristate 'ICEnsemble ICE1712 (Envy24)' CONFIG_SND_ICE1712 $CONFIG_SND
dep_tristate 'Intel i8x0/MX440, SiS 7012; Ali 5455; NForce Audio; AMD768/8111' CONFIG_SND_INTEL8X0 $CONFIG_SND
dep_tristate 'S3 SonicVibes' CONFIG_SND_SONICVIBES $CONFIG_SND
dep_tristate 'S3 SonicVibes' CONFIG_SND_SONICVIBES $CONFIG_SND $CONFIG_SOUND_GAMEPORT
dep_tristate 'VIA 82C686A/B, 8233 South Bridge' CONFIG_SND_VIA82XX $CONFIG_SND
# define gameport if necessary
if [ "$CONFIG_INPUT_GAMEPORT" != "n" ]; then
if [ "$CONFIG_SND_CS4281" = "y" \
-o "$CONFIG_SND_ES1938" = "y" \
-o "$CONFIG_SND_CS46XX" = "y" \
-o "$CONFIG_SND_SONICVIBES" = "y" \
-o "$CONFIG_SND_TRIDENT" = "y" ]; then
define_tristate CONFIG_INPUT_GAMEPORT y
fi
fi
endmenu
......@@ -862,6 +862,7 @@ static void snd_emu10k1_tram_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
{
int tram;
memset(icode->tram_valid, 0, sizeof(icode->tram_valid));
for (tram = 0; tram < 0xa0; tram++) {
set_bit(tram, icode->tram_valid);
icode->tram_data_map[tram] = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + tram, 0);
......@@ -885,6 +886,7 @@ static void snd_emu10k1_code_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
{
u32 pc;
memset(icode->code_valid, 0, sizeof(icode->code_valid));
for (pc = 0; pc < 512; pc++) {
set_bit(pc, icode->code_valid);
icode->code[pc][0] = snd_emu10k1_efx_read(emu, pc * 2);
......@@ -1031,7 +1033,7 @@ static void snd_emu10k1_del_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icod
}
}
static void snd_emu10k1_list_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
static int snd_emu10k1_list_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
{
int i = 0, j;
unsigned int total = 0;
......@@ -1044,7 +1046,7 @@ static void snd_emu10k1_list_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *ico
list_for_each(list, &emu->fx8010.gpr_ctl) {
ctl = emu10k1_gpr_ctl(list);
total++;
if (i < icode->gpr_list_control_count) {
if (_gctl && i < icode->gpr_list_control_count) {
memset(&gctl, 0, sizeof(gctl));
id = &ctl->kcontrol->id;
gctl.id.iface = id->iface;
......@@ -1061,13 +1063,14 @@ static void snd_emu10k1_list_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *ico
gctl.min = ctl->min;
gctl.max = ctl->max;
gctl.translation = ctl->translation;
snd_runtime_check(copy_to_user(_gctl, &gctl, sizeof(gctl)) == 0, goto __next);
if (copy_to_user(_gctl, &gctl, sizeof(gctl)))
return -EFAULT;
_gctl++;
i++;
}
__next:
_gctl++;
i++;
}
icode->gpr_list_control_total = total;
return 0;
}
static int snd_emu10k1_icode_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
......@@ -1103,6 +1106,8 @@ static int snd_emu10k1_icode_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
static int snd_emu10k1_icode_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
{
int err;
down(&emu->fx8010.lock);
strncpy(icode->name, emu->fx8010.name, sizeof(icode->name)-1);
emu->fx8010.name[sizeof(emu->fx8010.name)-1] = '\0';
......@@ -1110,9 +1115,9 @@ static int snd_emu10k1_icode_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
snd_emu10k1_gpr_peek(emu, icode);
snd_emu10k1_tram_peek(emu, icode);
snd_emu10k1_code_peek(emu, icode);
snd_emu10k1_list_controls(emu, icode);
err = snd_emu10k1_list_controls(emu, icode);
up(&emu->fx8010.lock);
return 0;
return err;
}
static int snd_emu10k1_ipcm_poke(emu10k1_t *emu, emu10k1_fx8010_pcm_t *ipcm)
......@@ -2171,9 +2176,13 @@ static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigne
kfree(icode);
return res;
case SNDRV_EMU10K1_IOCTL_CODE_PEEK:
icode = (emu10k1_fx8010_code_t *)snd_kcalloc(sizeof(*icode), GFP_KERNEL);
icode = (emu10k1_fx8010_code_t *)kmalloc(sizeof(*icode), GFP_KERNEL);
if (icode == NULL)
return -ENOMEM;
if (copy_from_user(icode, (void *)arg, sizeof(*icode))) {
kfree(icode);
return -EFAULT;
}
res = snd_emu10k1_icode_peek(emu, icode);
if (res == 0 && copy_to_user((void *)arg, icode, sizeof(*icode))) {
kfree(icode);
......
......@@ -30,8 +30,11 @@
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/rawmidi.h>
#ifdef CHIP1371
#include <sound/ac97_codec.h>
#else
#include <sound/ak4531_codec.h>
#endif
#define SNDRV_GET_ID
#include <sound/initval.h>
......@@ -352,13 +355,16 @@ struct _snd_ensoniq {
unsigned int rev; /* chip revision */
union {
#ifdef CHIP1371
struct {
ac97_t *ac97;
} es1371;
#else
struct {
int pclkdiv_lock;
ak4531_t *ak4531;
} es1370;
#endif
} u;
struct pci_dev *pci;
......
......@@ -1538,6 +1538,7 @@ YMFPCI_DOUBLE("ADC Playback Volume", 0, YDSXGR_PRIADCOUTVOL),
YMFPCI_DOUBLE("ADC Capture Volume", 0, YDSXGR_PRIADCLOOPVOL),
YMFPCI_DOUBLE("ADC Playback Volume", 1, YDSXGR_SECADCOUTVOL),
YMFPCI_DOUBLE("ADC Capture Volume", 1, YDSXGR_SECADCLOOPVOL),
YMFPCI_DOUBLE("FM Legacy Volume", 0, YDSXGR_LEGACYOUTVOL),
YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ", PLAYBACK,VOLUME), 0, YDSXGR_ZVOUTVOL),
YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("", CAPTURE,VOLUME), 0, YDSXGR_ZVLOOPVOL),
YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ",PLAYBACK,VOLUME), 1, YDSXGR_SPDIFOUTVOL),
......@@ -2022,6 +2023,7 @@ static int __devinit snd_ymfpci_memalloc(ymfpci_t *chip)
snd_ymfpci_writel(chip, YDSXGR_NATIVEADCINVOL, 0x3fff3fff);
snd_ymfpci_writel(chip, YDSXGR_NATIVEDACINVOL, 0x3fff3fff);
snd_ymfpci_writel(chip, YDSXGR_PRIADCLOOPVOL, 0x3fff3fff);
snd_ymfpci_writel(chip, YDSXGR_LEGACYOUTVOL, 0x3fff3fff);
return 0;
}
......@@ -2036,6 +2038,7 @@ static int snd_ymfpci_free(ymfpci_t *chip)
if (chip->res_reg_area) { /* don't touch busy hardware */
snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0);
snd_ymfpci_writel(chip, YDSXGR_LEGACYOUTVOL, 0);
snd_ymfpci_writel(chip, YDSXGR_STATUS, ~0);
snd_ymfpci_disable_dsp(chip);
snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, 0);
......@@ -2100,6 +2103,7 @@ static int saved_regs_index[] = {
YDSXGR_SPDIFLOOPVOL,
YDSXGR_SPDIFOUTVOL,
YDSXGR_ZVOUTVOL,
YDSXGR_LEGACYOUTVOL,
/* address bases */
YDSXGR_PLAYCTRLBASE,
YDSXGR_RECCTRLBASE,
......@@ -2112,7 +2116,7 @@ static int saved_regs_index[] = {
YDSXGR_ADCFORMAT,
YDSXGR_ADCSLOTSR,
};
#define YDSXGR_NUM_SAVED_REGS (sizeof(saved_regs_index)/sizeof(saved_regs_index[0]))
#define YDSXGR_NUM_SAVED_REGS ARRAY_SIZE(saved_regs_index)
void snd_ymfpci_suspend(ymfpci_t *chip)
{
......
......@@ -957,6 +957,19 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
if (subs->interface >= 0 && subs->interface != fmt->iface) {
usb_set_interface(subs->dev, subs->interface, 0);
subs->interface = -1;
subs->format = 0;
}
/* set interface */
if (subs->interface != fmt->iface || subs->format != fmt->altset_idx) {
if (usb_set_interface(dev, fmt->iface, fmt->altset_idx) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed\n",
dev->devnum, fmt->iface, fmt->altsetting);
return -EIO;
}
snd_printdd(KERN_INFO "setting usb interface %d:%d\n", fmt->iface, fmt->altset_idx);
subs->interface = fmt->iface;
subs->format = fmt->altset_idx;
}
/* create a data pipe */
......@@ -965,7 +978,6 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
subs->datapipe = usb_sndisocpipe(dev, ep);
else
subs->datapipe = usb_rcvisocpipe(dev, ep);
subs->format = fmt->altset_idx;
subs->syncpipe = subs->syncinterval = 0;
subs->maxpacksize = alts->endpoint[0].wMaxPacketSize;
subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize);
......@@ -998,15 +1010,6 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
subs->syncinterval = alts->endpoint[1].bRefresh;
}
/* set interface */
if (usb_set_interface(dev, fmt->iface, fmt->altset_idx) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed\n",
dev->devnum, fmt->iface, fmt->altsetting);
return -EIO;
}
snd_printdd(KERN_INFO "setting usb interface %d:%d\n", fmt->iface, fmt->altset_idx);
subs->interface = fmt->iface;
ep = alts->endpoint[0].bEndpointAddress;
/* if endpoint has pitch control, enable it */
if (fmt->attributes & EP_CS_ATTR_PITCH_CONTROL) {
......@@ -1171,6 +1174,7 @@ static int snd_usb_pcm_open(snd_pcm_substream_t *substream, int direction,
snd_usb_substream_t *subs = &as->substream[direction];
subs->interface = -1;
subs->format = 0;
runtime->hw = *hw;
runtime->private_data = subs;
subs->pcm_substream = substream;
......@@ -1601,6 +1605,10 @@ static int parse_audio_format_type(struct usb_device *dev, int iface_no, int alt
/* FIXME: correct endianess and sign? */
pcm_format = -1;
switch (format) {
case 0: /* some devices don't define this correctly... */
snd_printd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n",
dev->devnum, iface_no, altno);
/* fall-through */
case USB_AUDIO_FORMAT_PCM:
/* check the format byte size */
switch (fmt[6]) {
......
......@@ -42,6 +42,9 @@
/*
*/
/* ignore error from controls - for debugging */
/* #define IGNORE_CTL_ERROR */
typedef struct usb_mixer_build mixer_build_t;
typedef struct usb_audio_term usb_audio_term_t;
typedef struct usb_mixer_elem_info usb_mixer_elem_info_t;
......@@ -55,6 +58,8 @@ struct usb_audio_term {
int name;
};
struct usbmix_name_map;
struct usb_mixer_build {
snd_usb_audio_t *chip;
unsigned char *buffer;
......@@ -62,6 +67,7 @@ struct usb_mixer_build {
unsigned int ctrlif;
DECLARE_BITMAP(unitbitmap, 32*32);
usb_audio_term_t oterm;
const struct usbmix_name_map *map;
};
struct usb_mixer_elem_info {
......@@ -78,7 +84,8 @@ struct usb_mixer_elem_info {
enum {
USB_FEATURE_MUTE = 0,
USB_FEATURE_NONE = 0,
USB_FEATURE_MUTE = 1,
USB_FEATURE_VOLUME,
USB_FEATURE_BASS,
USB_FEATURE_MID,
......@@ -99,9 +106,71 @@ enum {
USB_MIXER_U16,
};
enum {
USB_PROC_UPDOWN = 1,
USB_PROC_UPDOWN_SWITCH = 1,
USB_PROC_UPDOWN_MODE_SEL = 2,
USB_PROC_PROLOGIC = 2,
USB_PROC_PROLOGIC_SWITCH = 1,
USB_PROC_PROLOGIC_MODE_SEL = 2,
USB_PROC_3DENH = 3,
USB_PROC_3DENH_SWITCH = 1,
USB_PROC_3DENH_SPACE = 2,
USB_PROC_REVERB = 4,
USB_PROC_REVERB_SWITCH = 1,
USB_PROC_REVERB_LEVEL = 2,
USB_PROC_REVERB_TIME = 3,
USB_PROC_REVERB_DELAY = 4,
USB_PROC_CHORUS = 5,
USB_PROC_CHORUS_SWITCH = 1,
USB_PROC_CHORUS_LEVEL = 2,
USB_PROC_CHORUS_RATE = 3,
USB_PROC_CHORUS_DEPTH = 4,
USB_PROC_DCR = 6,
USB_PROC_DCR_SWITCH = 1,
USB_PROC_DCR_RATIO = 2,
USB_PROC_DCR_MAX_AMP = 3,
USB_PROC_DCR_THRESHOLD = 4,
USB_PROC_DCR_ATTACK = 5,
USB_PROC_DCR_RELEASE = 6,
};
#define MAX_CHANNELS 10 /* max logical channels */
/*
* manual mapping of mixer names
* if the mixer topology is too complicated and the parsed names are
* ambiguous, add the entries in usbmixer_maps.c.
*/
#include "usbmixer_maps.c"
/* get the mapped name if the unit matches */
static int check_mapped_name(mixer_build_t *state, int unitid, int control, char *buf, int buflen)
{
const struct usbmix_name_map *p;
if (! state->map)
return 0;
for (p = state->map; p->id; p++) {
if (p->id == unitid &&
(! control || ! p->control || control == p->control)) {
buflen--;
strncpy(buf, p->name, buflen);
buf[buflen] = 0;
return strlen(buf);
}
}
return 0;
}
/*
* find an audio control unit with the given unit id
*/
......@@ -213,8 +282,10 @@ static int get_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
request,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx, cval->ctrlif | (cval->id << 8),
buf, val_len, HZ) < 0)
buf, val_len, HZ) < 0) {
snd_printdd(KERN_ERR "cannot get ctl value: req = 0x%x, idx = 0x%x, val = 0x%x, type = %d\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type);
return -EINVAL;
}
*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
return 0;
}
......@@ -227,7 +298,7 @@ static int get_cur_ctl_value(usb_mixer_elem_info_t *cval, int validx, int *value
/* channel = 0: master, 1 = first channel */
inline static int get_cur_mix_value(usb_mixer_elem_info_t *cval, int channel, int *value)
{
return get_ctl_value(cval, GET_CUR, ((cval->control + 1) << 8) | channel, value);
return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value);
}
/*
......@@ -256,7 +327,7 @@ static int set_cur_ctl_value(usb_mixer_elem_info_t *cval, int validx, int value)
inline static int set_cur_mix_value(usb_mixer_elem_info_t *cval, int channel, int value)
{
return set_ctl_value(cval, SET_CUR, ((cval->control + 1) << 8) | channel, value);
return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value);
}
......@@ -291,7 +362,7 @@ static int add_control_to_empty(snd_card_t *card, snd_kcontrol_t *kctl)
while (snd_ctl_find_id(card, &kctl->id))
kctl->id.index++;
if ((err = snd_ctl_add(card, kctl)) < 0) {
snd_printk(KERN_ERR "cannot add control\n");
snd_printd(KERN_ERR "cannot add control (err = %d)\n", err);
snd_ctl_free_one(kctl);
}
return err;
......@@ -483,6 +554,39 @@ static void usb_mixer_elem_free(snd_kcontrol_t *kctl)
* interface to ALSA control for feature/mixer units
*/
/*
* retrieve the minimum and maximum values for the specified control
*/
static int get_min_max(usb_mixer_elem_info_t *cval)
{
/* for failsafe */
cval->min = 0;
cval->max = 1;
if (cval->val_type == USB_MIXER_BOOLEAN ||
cval->val_type == USB_MIXER_INV_BOOLEAN) {
cval->initialized = 1;
} else {
int minchn = 0;
if (cval->cmask) {
int i;
for (i = 0; i < MAX_CHANNELS; i++)
if (cval->cmask & (1 << i)) {
minchn = i + 1;
break;
}
}
if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", cval->id, cval->ctrlif, cval->control, cval->id);
return -EINVAL;
}
cval->initialized = 1;
}
return 0;
}
/* get a feature/mixer unit info */
static int mixer_ctl_feature_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
{
......@@ -499,23 +603,8 @@ static int mixer_ctl_feature_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 1;
} else {
if (! cval->initialized) {
int minchn = 0;
if (cval->cmask) {
int i;
for (i = 0; i < MAX_CHANNELS; i++)
if (cval->cmask & (1 << i)) {
minchn = i + 1;
break;
}
}
if (get_ctl_value(cval, GET_MAX, ((cval->control+1) << 8) | minchn, &cval->max) < 0 ||
get_ctl_value(cval, GET_MIN, ((cval->control+1) << 8) | minchn, &cval->min) < 0) {
snd_printk(KERN_ERR "%d:%d: cannot get min/max values for control %d\n", cval->id, cval->ctrlif, cval->control);
return -EINVAL;
}
cval->initialized = 1;
}
if (! cval->initialized)
get_min_max(cval);
uinfo->value.integer.min = 0;
uinfo->value.integer.max = cval->max - cval->min;
}
......@@ -533,8 +622,14 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
for (c = 0; c < MAX_CHANNELS; c++) {
if (cval->cmask & (1 << c)) {
err = get_cur_mix_value(cval, c + 1, &val);
#ifdef IGNORE_CTL_ERROR
if (err < 0) {
printk("cannot get current value for control %d ch %d: err = %d\n", cval->control, c + 1, err);
ucontrol->value.integer.value[0] = cval->min;
return 0;
}
#endif
if (err < 0) {
snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", cval->control, c + 1, err);
return err;
}
val = get_relative_value(cval, val);
......@@ -545,8 +640,14 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
} else {
/* master channel */
err = get_cur_mix_value(cval, 0, &val);
#ifdef IGNORE_CTL_ERROR
if (err < 0) {
ucontrol->value.integer.value[0] = cval->min;
return 0;
}
#endif
if (err < 0) {
printk("cannot get current value for control %d master ch: err = %d\n", cval->control, err);
snd_printd(KERN_ERR "cannot get current value for control %d master ch: err = %d\n", cval->control, err);
return err;
}
val = get_relative_value(cval, val);
......@@ -567,6 +668,10 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
for (c = 0; c < MAX_CHANNELS; c++) {
if (cval->cmask & (1 << c)) {
err = get_cur_mix_value(cval, c + 1, &oval);
#ifdef IGNORE_CTL_ERROR
if (err < 0)
return 0;
#endif
if (err < 0)
return err;
val = ucontrol->value.integer.value[cnt];
......@@ -581,6 +686,10 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
} else {
/* master channel */
err = get_cur_mix_value(cval, 0, &oval);
#ifdef IGNORE_CTL_ERROR
if (err < 0)
return 0;
#endif
if (err < 0)
return err;
val = ucontrol->value.integer.value[0];
......@@ -610,11 +719,12 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
unsigned int ctl_mask, int control,
usb_audio_term_t *iterm, int unitid)
{
int len = 0;
int len = 0, mapped_name = 0;
int nameid = desc[desc[0] - 1];
snd_kcontrol_t *kctl;
usb_mixer_elem_info_t *cval;
int minchn = 0;
control++; /* change from zero-based to 1-based value */
if (control == USB_FEATURE_GEQ) {
/* FIXME: not supported yet */
......@@ -623,7 +733,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
cval = snd_magic_kcalloc(usb_mixer_elem_info_t, 0, GFP_KERNEL);
if (! cval) {
snd_printk(KERN_ERR "cannot malloc kcontrol");
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return;
}
cval->chip = state->chip;
......@@ -631,42 +741,31 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
cval->id = unitid;
cval->control = control;
cval->cmask = ctl_mask;
cval->val_type = audio_feature_info[control].type;
cval->val_type = audio_feature_info[control-1].type;
if (ctl_mask == 0)
cval->channels = 1; /* master channel */
else {
int i, c = 0;
for (i = 0; i < 16; i++)
if (ctl_mask & (1 << i)) {
if (! minchn)
minchn = i + 1;
if (ctl_mask & (1 << i))
c++;
}
cval->channels = c;
}
/* get min/max values */
if (cval->val_type == USB_MIXER_BOOLEAN ||
cval->val_type == USB_MIXER_INV_BOOLEAN) {
cval->max = 1;
cval->initialized = 1;
} else {
if (get_ctl_value(cval, GET_MAX, ((cval->control+1) << 8) | minchn, &cval->max) < 0 ||
get_ctl_value(cval, GET_MIN, ((cval->control+1) << 8) | minchn, &cval->min) < 0)
snd_printk(KERN_ERR "%d:%d: cannot get min/max values for control %d\n", cval->id, cval->ctrlif, control);
else
cval->initialized = 1;
}
get_min_max(cval);
kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
if (! kctl) {
snd_printk(KERN_ERR "cannot malloc kcontrol");
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
snd_magic_kfree(cval);
return;
}
kctl->private_free = usb_mixer_elem_free;
if (nameid)
len = check_mapped_name(state, unitid, control, kctl->id.name, sizeof(kctl->id.name));
mapped_name = len != 0;
if (! len && nameid)
len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name));
switch (control) {
......@@ -679,7 +778,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
* - if the connected output can be determined, use it.
* - otherwise, anonymous name.
*/
if (! nameid) {
if (! len) {
len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 1);
if (! len)
len = get_term_name(state, &state->oterm, kctl->id.name, sizeof(kctl->id.name), 1);
......@@ -690,21 +789,26 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
* if the connected output is USB stream, then it's likely a
* capture stream. otherwise it should be playback (hopefully :)
*/
if (! (state->oterm.type >> 16)) {
if (! mapped_name && ! (state->oterm.type >> 16)) {
if ((state->oterm.type & 0xff00) == 0x0100) {
strcpy(kctl->id.name + len, " Capture");
len += 8;
if (len + 8 < sizeof(kctl->id.name)) {
strcpy(kctl->id.name + len, " Capture");
len += 8;
}
} else {
strcpy(kctl->id.name + len, " Playback");
len += 9;
if (len + 9 < sizeof(kctl->id.name)) {
strcpy(kctl->id.name + len, " Playback");
len += 9;
}
}
}
strcpy(kctl->id.name + len, control == USB_FEATURE_MUTE ? " Switch" : " Volume");
if (len + 7 < sizeof(kctl->id.name))
strcpy(kctl->id.name + len, control == USB_FEATURE_MUTE ? " Switch" : " Volume");
break;
default:
if (! nameid)
strcpy(kctl->id.name, audio_feature_info[control].name);
if (! len)
strcpy(kctl->id.name, audio_feature_info[control-1].name);
break;
}
......@@ -785,7 +889,6 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
int i, len;
snd_kcontrol_t *kctl;
usb_audio_term_t iterm;
int minchn = 0;
cval = snd_magic_kcalloc(usb_mixer_elem_info_t, 0, GFP_KERNEL);
if (! cval)
......@@ -797,36 +900,33 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
cval->chip = state->chip;
cval->ctrlif = state->ctrlif;
cval->id = unitid;
cval->control = in_ch;
cval->control = in_ch + 1; /* based on 1 */
cval->val_type = USB_MIXER_S16;
for (i = 0; i < num_outs; i++) {
if (check_matrix_bitmap(desc + 9 + num_ins, in_ch, i, num_outs)) {
cval->cmask |= (1 << i);
cval->channels++;
if (! minchn)
minchn = i + 1;
}
}
/* get min/max values */
if (get_ctl_value(cval, GET_MAX, ((in_ch+1) << 8) | minchn, &cval->max) < 0 ||
get_ctl_value(cval, GET_MIN, ((in_ch+1) << 8) | minchn, &cval->min) < 0)
snd_printk(KERN_ERR "cannot get min/max values for mixer\n");
else
cval->initialized = 1;
get_min_max(cval);
kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
if (! kctl) {
snd_printk(KERN_ERR "cannot malloc kcontrol");
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
snd_magic_kfree(cval);
return;
}
kctl->private_free = usb_mixer_elem_free;
len = get_term_name(state, &iterm, kctl->id.name, sizeof(kctl->id.name), 0);
len = check_mapped_name(state, unitid, 0, kctl->id.name, sizeof(kctl->id.name));
if (! len)
len = get_term_name(state, &iterm, kctl->id.name, sizeof(kctl->id.name), 0);
if (! len)
len = sprintf(kctl->id.name, "Mixer Source %d", in_ch);
strcpy(kctl->id.name + len, " Volume");
if (len + 7 < sizeof(kctl->id.name))
strcpy(kctl->id.name + len, " Volume");
snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n",
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
......@@ -866,6 +966,12 @@ static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
int err, val;
err = get_cur_ctl_value(cval, cval->control, &val);
#ifdef IGNORE_CTL_ERROR
if (err < 0) {
ucontrol->value.integer.value[0] = cval->min;
return 0;
}
#endif
if (err < 0)
return err;
val = get_relative_value(cval, val);
......@@ -880,6 +986,10 @@ static int mixer_ctl_procunit_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
int val, oval, err;
err = get_cur_ctl_value(cval, cval->control, &oval);
#ifdef IGNORE_CTL_ERROR
if (err < 0)
return 0;
#endif
if (err < 0)
return err;
val = ucontrol->value.integer.value[0];
......@@ -917,51 +1027,51 @@ struct procunit_info {
};
static struct procunit_value_info updown_proc_info[] = {
{ 0x01, "Switch", USB_MIXER_BOOLEAN },
{ 0x02, "Mode Select", USB_MIXER_U8 },
{ USB_PROC_UPDOWN_SWITCH, "Switch", USB_MIXER_BOOLEAN },
{ USB_PROC_UPDOWN_MODE_SEL, "Mode Select", USB_MIXER_U8 },
{ 0 }
};
static struct procunit_value_info prologic_proc_info[] = {
{ 0x01, "Switch", USB_MIXER_BOOLEAN },
{ 0x02, "Mode Select", USB_MIXER_U8 },
{ USB_PROC_PROLOGIC_SWITCH, "Switch", USB_MIXER_BOOLEAN },
{ USB_PROC_PROLOGIC_MODE_SEL, "Mode Select", USB_MIXER_U8 },
{ 0 }
};
static struct procunit_value_info threed_enh_proc_info[] = {
{ 0x01, "Switch", USB_MIXER_BOOLEAN },
{ 0x02, "Spaciousness", USB_MIXER_U8 },
{ USB_PROC_3DENH_SWITCH, "Switch", USB_MIXER_BOOLEAN },
{ USB_PROC_3DENH_SPACE, "Spaciousness", USB_MIXER_U8 },
{ 0 }
};
static struct procunit_value_info reverb_proc_info[] = {
{ 0x01, "Switch", USB_MIXER_BOOLEAN },
{ 0x02, "Level", USB_MIXER_U8 },
{ 0x03, "Time", USB_MIXER_U16 },
{ 0x04, "Delay", USB_MIXER_U8 },
{ USB_PROC_REVERB_SWITCH, "Switch", USB_MIXER_BOOLEAN },
{ USB_PROC_REVERB_LEVEL, "Level", USB_MIXER_U8 },
{ USB_PROC_REVERB_TIME, "Time", USB_MIXER_U16 },
{ USB_PROC_REVERB_DELAY, "Delay", USB_MIXER_U8 },
{ 0 }
};
static struct procunit_value_info chorus_proc_info[] = {
{ 0x01, "Switch", USB_MIXER_BOOLEAN },
{ 0x02, "Level", USB_MIXER_U8 },
{ 0x03, "Rate", USB_MIXER_U16 },
{ 0x04, "Depth", USB_MIXER_U16 },
{ USB_PROC_CHORUS_SWITCH, "Switch", USB_MIXER_BOOLEAN },
{ USB_PROC_CHORUS_LEVEL, "Level", USB_MIXER_U8 },
{ USB_PROC_CHORUS_RATE, "Rate", USB_MIXER_U16 },
{ USB_PROC_CHORUS_DEPTH, "Depth", USB_MIXER_U16 },
{ 0 }
};
static struct procunit_value_info dcr_proc_info[] = {
{ 0x01, "Switch", USB_MIXER_BOOLEAN },
{ 0x02, "Ratio", USB_MIXER_U16 },
{ 0x03, "Max Amp", USB_MIXER_S16 },
{ 0x04, "Threshold", USB_MIXER_S16 },
{ 0x05, "Attack Time", USB_MIXER_U16 },
{ 0x06, "Release Time", USB_MIXER_U16 },
{ USB_PROC_DCR_SWITCH, "Switch", USB_MIXER_BOOLEAN },
{ USB_PROC_DCR_RATIO, "Ratio", USB_MIXER_U16 },
{ USB_PROC_DCR_MAX_AMP, "Max Amp", USB_MIXER_S16 },
{ USB_PROC_DCR_THRESHOLD, "Threshold", USB_MIXER_S16 },
{ USB_PROC_DCR_ATTACK, "Attack Time", USB_MIXER_U16 },
{ USB_PROC_DCR_RELEASE, "Release Time", USB_MIXER_U16 },
{ 0 }
};
static struct procunit_info procunits[] = {
{ 0x01, "Up Down", updown_proc_info },
{ 0x02, "Dolby Prologic", prologic_proc_info },
{ 0x03, "3D Stereo Extender", threed_enh_proc_info },
{ 0x04, "Reverb", reverb_proc_info },
{ 0x05, "Chorus", chorus_proc_info },
{ 0x06, "DCR", dcr_proc_info },
{ USB_PROC_UPDOWN, "Up Down", updown_proc_info },
{ USB_PROC_PROLOGIC, "Dolby Prologic", prologic_proc_info },
{ USB_PROC_3DENH, "3D Stereo Extender", threed_enh_proc_info },
{ USB_PROC_REVERB, "Reverb", reverb_proc_info },
{ USB_PROC_CHORUS, "Chorus", chorus_proc_info },
{ USB_PROC_DCR, "DCR", dcr_proc_info },
{ 0 },
};
......@@ -973,7 +1083,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
int num_ins = dsc[6];
usb_mixer_elem_info_t *cval;
snd_kcontrol_t *kctl;
int i, err, nameid, type;
int i, err, nameid, type, len;
struct procunit_info *info;
struct procunit_value_info *valinfo;
static struct procunit_value_info default_value_info[] = {
......@@ -985,7 +1095,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
};
if (dsc[0] < 13 || dsc[0] < 13 + num_ins || dsc[0] < num_ins + dsc[11 + num_ins]) {
snd_printk(KERN_ERR "invalid %s descriptor %d\n", name, unitid);
snd_printk(KERN_ERR "invalid %s descriptor (id %d)\n", name, unitid);
return -EINVAL;
}
......@@ -1010,7 +1120,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
continue;
cval = snd_magic_kcalloc(usb_mixer_elem_info_t, 0, GFP_KERNEL);
if (! cval) {
snd_printk(KERN_ERR "cannot malloc kcontrol");
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return -ENOMEM;
}
cval->chip = state->chip;
......@@ -1021,31 +1131,35 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
cval->channels = 1;
/* get min/max values */
if (get_ctl_value(cval, GET_MAX, cval->control, &cval->max) < 0 ||
get_ctl_value(cval, GET_MIN, cval->control, &cval->min) < 0)
snd_printk(KERN_ERR "cannot get min/max values for proc/ext unit\n");
else
cval->initialized = 1;
get_min_max(cval);
kctl = snd_ctl_new1(&mixer_procunit_ctl, cval);
if (! kctl) {
snd_printk(KERN_ERR "cannot malloc kcontrol");
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
snd_magic_kfree(cval);
return -ENOMEM;
}
kctl->private_free = usb_mixer_elem_free;
if (info->name)
sprintf(kctl->id.name, "%s %s", info->name, valinfo->suffix);
if (check_mapped_name(state, unitid, cval->control, kctl->id.name, sizeof(kctl->id.name)))
;
else if (info->name)
strcpy(kctl->id.name, info->name);
else {
nameid = dsc[12 + num_ins + dsc[11 + num_ins]];
if (nameid) {
int len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name));
strcpy(kctl->id.name + len, valinfo->suffix);
} else
sprintf(kctl->id.name, "%s %s", name, valinfo->suffix);
len = 0;
if (nameid)
len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name));
if (! len) {
strncpy(kctl->id.name, name, sizeof(kctl->id.name) - 1);
kctl->id.name[sizeof(kctl->id.name)-1] = 0;
}
}
len = strlen(kctl->id.name);
if (len + sizeof(valinfo->suffix) + 1 < sizeof(kctl->id.name)) {
kctl->id.name[len] = ' ';
strcpy(kctl->id.name + len + 1, valinfo->suffix);
}
snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n",
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
if ((err = add_control_to_empty(state->chip->card, kctl)) < 0)
......@@ -1095,6 +1209,12 @@ static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
int val, err;
err = get_cur_ctl_value(cval, 0, &val);
#ifdef IGNORE_CTL_ERROR
if (err < 0) {
ucontrol->value.enumerated.item[0] = 0;
return 0;
}
#endif
if (err < 0)
return err;
val = get_relative_value(cval, val);
......@@ -1109,6 +1229,10 @@ static int mixer_ctl_selector_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
int val, oval, err;
err = get_cur_ctl_value(cval, 0, &oval);
#ifdef IGNORE_CTL_ERROR
if (err < 0)
return 0;
#endif
if (err < 0)
return err;
val = ucontrol->value.enumerated.item[0];
......@@ -1158,7 +1282,7 @@ static void usb_mixer_selector_elem_free(snd_kcontrol_t *kctl)
static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned char *desc)
{
int num_ins = desc[4];
int i, err, nameid;
int i, err, nameid, len;
usb_mixer_elem_info_t *cval;
snd_kcontrol_t *kctl;
char **namelist;
......@@ -1175,7 +1299,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
cval = snd_magic_kcalloc(usb_mixer_elem_info_t, 0, GFP_KERNEL);
if (! cval) {
snd_printk(KERN_ERR "cannot malloc kcontrol");
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return -ENOMEM;
}
cval->chip = state->chip;
......@@ -1196,7 +1320,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
#define MAX_ITEM_NAME_LEN 64
for (i = 0; i < num_ins; i++) {
usb_audio_term_t iterm;
int len = 0;
len = 0;
namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL);
if (! namelist[i]) {
snd_printk(KERN_ERR "cannot malloc\n");
......@@ -1214,7 +1338,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval);
if (! kctl) {
snd_printk(KERN_ERR "cannot malloc kcontrol");
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
snd_magic_kfree(cval);
return -ENOMEM;
}
......@@ -1222,17 +1346,23 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
kctl->private_free = usb_mixer_selector_elem_free;
nameid = desc[desc[0] - 1];
if (nameid)
len = check_mapped_name(state, unitid, 0, kctl->id.name, sizeof(kctl->id.name));
if (len)
;
else if (nameid)
snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name));
else {
int len = get_term_name(state, &state->oterm,
kctl->id.name, sizeof(kctl->id.name), 0);
len = get_term_name(state, &state->oterm,
kctl->id.name, sizeof(kctl->id.name), 0);
if (! len)
len = sprintf(kctl->id.name, "USB");
if ((state->oterm.type & 0xff00) == 0x0100)
strcpy(kctl->id.name + len, " Capture Source");
else
strcpy(kctl->id.name + len, " Playback Source");
if ((state->oterm.type & 0xff00) == 0x0100) {
if (len + 15 < sizeof(kctl->id.name))
strcpy(kctl->id.name + len, " Capture Source");
} else {
if (len + 16 < sizeof(kctl->id.name))
strcpy(kctl->id.name + len, " Playback Source");
}
}
snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
......@@ -1290,6 +1420,8 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif, unsigned char *buffe
unsigned char *desc;
mixer_build_t state;
int err;
const struct usbmix_ctl_map *map;
struct usb_device_descriptor *dev = &chip->dev->descriptor;
strcpy(chip->card->mixername, "USB Mixer");
......@@ -1298,6 +1430,15 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif, unsigned char *buffe
state.buffer = buffer;
state.buflen = buflen;
state.ctrlif = ctrlif;
/* check the mapping table */
for (map = usbmix_ctl_maps; map->vendor; map++) {
if (map->vendor == dev->idVendor && map->product == dev->idProduct) {
state.map = map->map;
break;
}
}
desc = NULL;
while ((desc = snd_usb_find_csint_desc(buffer, buflen, desc, OUTPUT_TERMINAL, ctrlif, -1)) != NULL) {
if (desc[0] < 9)
......
/*
* Additional mixer mapping
*
* 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
*
*/
struct usbmix_name_map {
int id;
const char *name;
int control;
};
struct usbmix_ctl_map {
int vendor;
int product;
const struct usbmix_name_map *map;
};
/*
* USB control mappers for SB Exitigy
*/
/*
* Topology of SB Extigy (see on the wide screen :)
USB_IN[1] --->FU[2]------------------------------+->MU[16]-->PE[17]-+->FU[18]--+->EU[27]--+->EU[21]-->FU[22]--+->FU[23] > Dig_OUT[24]
^ | | | |
USB_IN[3] -+->SU[5]-->FU[6]--+->MU[14] ->PE[15]->+ | | | +->FU[25] > Dig_OUT[26]
^ ^ | | | |
Dig_IN[4] -+ | | | | +->FU[28]---------------------> Spk_OUT[19]
| | | |
Lin-IN[7] -+-->FU[8]---------+ | | +----------------------------------------> Hph_OUT[20]
| | |
Mic-IN[9] --+->FU[10]----------------------------+ |
|| |
|| +----------------------------------------------------+
VV V
++--+->SU[11]-->FU[12] --------------------------------------------------------------------------------------> USB_OUT[13]
*/
static struct usbmix_name_map extigy_map[] = {
/* 1: IT pcm */
{ 2, "PCM Playback" }, /* FU */
/* 3: IT pcm */
/* 4: IT digital in */
{ 5, "Digital In Playback Source" }, /* SU */
{ 6, "Digital In" }, /* FU */
/* 7: IT line */
{ 8, "Line Playback" }, /* FU */
/* 9: IT mic */
{ 10, "Mic Playback" }, /* FU */
{ 11, "Capture Source" }, /* SU */
{ 12, "Capture" }, /* FU */
/* 13: OT pcm capture */
/* 14: MU (w/o controls) */
/* 15: PE (3D enh) */
/* 16: MU (w/o controls) */
/* 17: PE (updown) */ /* FIXME: what control? */
{ 18, "Tone Control - Bass", USB_FEATURE_BASS }, /* FU */
{ 18, "Tone Control - Treble", USB_FEATURE_TREBLE }, /* FU */
{ 18, "Master Playback" }, /* FU; others */
/* 19: OT speaker */
/* 20: OT headphone */
{ 21, "Digital Out Extension" }, /* EU */ /* FIXME: what? */
{ 22, "Digital Out Playback" }, /* FU */
{ 23, "Digital Out1 Playback" }, /* FU */ /* FIXME: corresponds to 24 */
/* 24: OT digital out */
{ 25, "Digital Out2 Playback" }, /* FU */ /* FIXME: corresponds to 26 */
/* 26: OT digital out */
{ 27, "Output Extension" }, /* EU */ /* FIXME: what? */
/* 28: FU (mute) */
{ 0 } /* terminator */
};
/*
* Control map entries
*/
static struct usbmix_ctl_map usbmix_ctl_maps[] = {
{ 0x41e, 0x3000, extigy_map },
{ 0 } /* terminator */
};
......@@ -38,7 +38,7 @@
/* Yamaha devices */
{
USB_DEVICE_VENDOR_SPEC(0x0499, 0x1000),
USB_DEVICE(0x0499, 0x1000),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "UX256",
......@@ -47,7 +47,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0499, 0x1001),
USB_DEVICE(0x0499, 0x1001),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "MU1000",
......@@ -56,7 +56,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0499, 0x1002),
USB_DEVICE(0x0499, 0x1002),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "MU2000",
......@@ -65,7 +65,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0499, 0x1003),
USB_DEVICE(0x0499, 0x1003),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "MU500",
......@@ -74,7 +74,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0499, 0x1004),
USB_DEVICE(0x0499, 0x1004),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "UW500",
......@@ -83,7 +83,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0499, 0x1005),
USB_DEVICE(0x0499, 0x1005),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "MOTIF6",
......@@ -92,7 +92,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0499, 0x1006),
USB_DEVICE(0x0499, 0x1006),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "MOTIF7",
......@@ -101,7 +101,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0499, 0x1007),
USB_DEVICE(0x0499, 0x1007),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "MOTIF8",
......@@ -110,7 +110,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0499, 0x1008),
USB_DEVICE(0x0499, 0x1008),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "UX96",
......@@ -119,7 +119,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0499, 0x1009),
USB_DEVICE(0x0499, 0x1009),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "UX16",
......@@ -128,7 +128,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0499, 0x100a),
USB_DEVICE(0x0499, 0x100a),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "EOS BX",
......@@ -137,7 +137,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0499, 0x100e),
USB_DEVICE(0x0499, 0x100e),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "S08",
......@@ -146,7 +146,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0499, 0x100f),
USB_DEVICE(0x0499, 0x100f),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "CLP-150",
......@@ -155,7 +155,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0499, 0x1010),
USB_DEVICE(0x0499, 0x1010),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Yamaha",
.product_name = "CLP-170",
......@@ -177,7 +177,7 @@
* class-specific descriptors.
*/
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0000),
USB_DEVICE(0x0582, 0x0000),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "UA-100",
......@@ -191,7 +191,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0002),
USB_DEVICE(0x0582, 0x0002),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "UM-4",
......@@ -205,7 +205,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0003),
USB_DEVICE(0x0582, 0x0003),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "SC-8850",
......@@ -219,7 +219,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0004),
USB_DEVICE(0x0582, 0x0004),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "U-8",
......@@ -233,7 +233,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0005),
USB_DEVICE(0x0582, 0x0005),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "UM-2",
......@@ -247,7 +247,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0007),
USB_DEVICE(0x0582, 0x0007),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "SC-8820",
......@@ -261,7 +261,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0008),
USB_DEVICE(0x0582, 0x0008),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "PC-300",
......@@ -275,7 +275,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0009),
USB_DEVICE(0x0582, 0x0009),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "UM-1",
......@@ -289,7 +289,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x000b),
USB_DEVICE(0x0582, 0x000b),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "SK-500",
......@@ -303,7 +303,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x000c),
USB_DEVICE(0x0582, 0x000c),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "SC-D70",
......@@ -317,7 +317,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0012),
USB_DEVICE(0x0582, 0x0012),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "XV-5050",
......@@ -331,7 +331,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0014),
USB_DEVICE(0x0582, 0x0014),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "UM-880",
......@@ -345,7 +345,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0016),
USB_DEVICE(0x0582, 0x0016),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "SD-90",
......@@ -359,7 +359,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0023),
USB_DEVICE(0x0582, 0x0023),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "UM-550",
......@@ -373,7 +373,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0027),
USB_DEVICE(0x0582, 0x0027),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "SD-20",
......@@ -387,7 +387,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0029),
USB_DEVICE(0x0582, 0x0029),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "SD-80",
......@@ -401,7 +401,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0582, 0x002b),
USB_DEVICE(0x0582, 0x002b),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "UA-700",
......@@ -467,7 +467,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0763, 0x2001),
USB_DEVICE(0x0763, 0x2001),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "M-Audio",
.product_name = "Quattro",
......@@ -477,7 +477,7 @@
}
},
{
USB_DEVICE_VENDOR_SPEC(0x0763, 0x2003),
USB_DEVICE(0x0763, 0x2003),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "M-Audio",
.product_name = "AudioPhile",
......
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