Commit ece8df79 authored by Jaroslav Kysela's avatar Jaroslav Kysela

Merge suse.cz:/home/perex/bk/linux-sound/linux-2.5

into suse.cz:/home/perex/bk/linux-sound/linux-sound
parents 771a7305 72815e1f
VIA82xx mixer
=============
On many VIA82xx boards, the 'Input Source Select' mixer control does not work.
Setting it to 'Input2' on such boards will cause recording to hang, or fail
with EIO (input/output error) via OSS emulation. This control should be left
at 'Input1' for such cards.
This diff is collapsed.
......@@ -23,12 +23,12 @@ send the F5 NN command sequence at all; perhaps it ought to.
Usage example for simple serial converter:
/sbin/setserial /dev/ttyS0 none
/sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 speed=115200
Usage example for Roland SoundCanvas with 4 MIDI ports:
/sbin/setserial /dev/ttyS0 none
/sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 outs=4
In MS-124T mode, one raw MIDI substream is supported (midiCnD0); the outs
......@@ -38,7 +38,7 @@ parameter to match (A=19200, B=9600).
Usage example for MS-124T, with A-B switch in A position:
/sbin/setserial /dev/ttyS0 none
/sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=1 \
speed=19200
......@@ -48,7 +48,7 @@ the same data to all four MIDI Out connectors at full MIDI speed.
Usage example for S/A mode:
/sbin/setserial /dev/ttyS0 none
/sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=2
In MS-124W M/B mode, the driver supports 16 ALSA raw MIDI substreams;
......@@ -64,7 +64,7 @@ one byte every 320 us per port.
Usage example for M/B mode:
/sbin/setserial /dev/ttyS0 none
/sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=3
The MS-124W hardware's M/A mode is currently not supported. This mode allows
......
This diff is collapsed.
......@@ -106,7 +106,7 @@
#define AK4117_DIF_24L (AK4117_DIF2) /* STDO: 24-bit, left justified */
#define AK4117_DIF_24I2S (AK4117_DIF2|AK4117_DIF0) /* STDO: I2S */
/* AK4117_REG_INT0_MASK & AK4117_INT1_MASK */
/* AK4117_REG_INT0_MASK & AK4117_REG_INT1_MASK */
#define AK4117_MULK (1<<7) /* mask enable for UNLOCK bit */
#define AK4117_MPAR (1<<6) /* mask enable for PAR bit */
#define AK4117_MAUTO (1<<5) /* mask enable for AUTO bit */
......@@ -181,8 +181,8 @@ struct ak4117 {
int snd_ak4117_create(snd_card_t *card, ak4117_read_t *read, ak4117_write_t *write,
unsigned char pgm[5], void *private_data, ak4117_t **r_ak4117);
void snd_ak4117_reg_write(ak4117_t *chip, unsigned char reg, unsigned char mask, unsigned char val);
void snd_ak4117_reinit(ak4117_t *chip);
void snd_ak4117_reg_write(ak4117_t *ak4117, unsigned char reg, unsigned char mask, unsigned char val);
void snd_ak4117_reinit(ak4117_t *ak4117);
int snd_ak4117_build(ak4117_t *ak4117, snd_pcm_substream_t *capture_substream);
int snd_ak4117_external_rate(ak4117_t *ak4117);
int snd_ak4117_check_rate_and_errors(ak4117_t *ak4117, unsigned int flags);
......
......@@ -50,7 +50,8 @@ struct snd_akm4xxx {
/* template should fill the following fields */
unsigned int idx_offset; /* control index offset */
enum {
SND_AK4524, SND_AK4528, SND_AK4529, SND_AK4355, SND_AK4381
SND_AK4524, SND_AK4528, SND_AK4529,
SND_AK4355, SND_AK4358, SND_AK4381
} type;
struct snd_ak4xxx_ops ops;
};
......
......@@ -119,6 +119,13 @@ int snd_ctl_create(snd_card_t *card);
int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn);
#ifdef CONFIG_COMPAT
int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn);
int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
#else
#define snd_ctl_register_ioctl_compat(fcn)
#define snd_ctl_unregister_ioctl_compat(fcn)
#endif
int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *control);
int snd_ctl_elem_write(snd_card_t *card, snd_ctl_file_t *file, snd_ctl_elem_value_t *control);
......
......@@ -26,6 +26,7 @@
#include <asm/semaphore.h> /* struct semaphore */
#include <linux/rwsem.h> /* struct rw_semaphore */
#include <linux/workqueue.h> /* struct workqueue_struct */
#include <linux/pm.h> /* pm_message_t */
/* Typedef's */
typedef struct timespec snd_timestamp_t;
......@@ -167,13 +168,15 @@ struct _snd_card {
struct device *dev;
#ifdef CONFIG_PM
int (*pm_suspend)(snd_card_t *card, unsigned int state);
int (*pm_resume)(snd_card_t *card, unsigned int state);
struct pm_dev *pm_dev; /* for ISA */
int (*pm_suspend)(snd_card_t *card, pm_message_t state);
int (*pm_resume)(snd_card_t *card);
void *pm_private_data;
unsigned int power_state; /* power state */
struct semaphore power_lock; /* power lock */
wait_queue_head_t power_sleep;
#ifdef CONFIG_SND_GENERIC_PM
struct snd_generic_device *pm_dev; /* for ISA */
#endif
#endif
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
......@@ -206,36 +209,34 @@ static inline void snd_power_change_state(snd_card_t *card, unsigned int state)
wake_up(&card->power_sleep);
}
int snd_card_set_pm_callback(snd_card_t *card,
int (*suspend)(snd_card_t *, unsigned int),
int (*resume)(snd_card_t *, unsigned int),
int (*suspend)(snd_card_t *, pm_message_t),
int (*resume)(snd_card_t *),
void *private_data);
int snd_card_set_dev_pm_callback(snd_card_t *card, int type,
int (*suspend)(snd_card_t *, unsigned int),
int (*resume)(snd_card_t *, unsigned int),
void *private_data);
int snd_card_set_generic_pm_callback(snd_card_t *card,
int (*suspend)(snd_card_t *, pm_message_t),
int (*resume)(snd_card_t *),
void *private_data);
#define snd_card_set_isa_pm_callback(card,suspend,resume,data) \
snd_card_set_dev_pm_callback(card, PM_ISA_DEV, suspend, resume, data)
#ifdef CONFIG_PCI
#ifndef SND_PCI_PM_CALLBACKS
int snd_card_pci_suspend(struct pci_dev *dev, u32 state);
snd_card_set_generic_pm_callback(card, suspend, resume, data)
struct pci_dev;
int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state);
int snd_card_pci_resume(struct pci_dev *dev);
#define SND_PCI_PM_CALLBACKS \
.suspend = snd_card_pci_suspend, .resume = snd_card_pci_resume
#endif
#endif
#else
#else /* ! CONFIG_PM */
#define snd_power_lock(card) do { (void)(card); } while (0)
#define snd_power_unlock(card) do { (void)(card); } while (0)
static inline int snd_power_wait(snd_card_t *card, unsigned int state, struct file *file) { return 0; }
#define snd_power_get_state(card) SNDRV_CTL_POWER_D0
#define snd_power_change_state(card, state) do { (void)(card); } while (0)
#define snd_card_set_pm_callback(card,suspend,resume,data)
#define snd_card_set_dev_pm_callback(card,suspend,resume,data)
#define snd_card_set_generic_pm_callback(card,suspend,resume,data)
#define snd_card_set_isa_pm_callback(card,suspend,resume,data)
#ifdef CONFIG_PCI
#define SND_PCI_PM_CALLBACKS
#endif
#endif
#endif /* CONFIG_PM */
/* device.c */
......
This diff is collapsed.
......@@ -230,7 +230,7 @@ typedef struct {
int mode; /* operation mode */
int client; /* sequencer client number */
int port; /* sequencer port number */
int midi_has_voices: 1;
unsigned int midi_has_voices: 1;
} snd_gus_port_t;
typedef struct _snd_gus_voice snd_gus_voice_t;
......@@ -264,7 +264,7 @@ typedef enum {
struct _snd_gus_voice {
int number;
int use: 1,
unsigned int use: 1,
pcm: 1,
synth:1,
midi: 1;
......
......@@ -38,6 +38,7 @@ typedef struct _snd_hwdep_ops {
int (*release) (snd_hwdep_t * hw, struct file * file);
unsigned int (*poll) (snd_hwdep_t * hw, struct file * file, poll_table * wait);
int (*ioctl) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg);
int (*ioctl_compat) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg);
int (*mmap) (snd_hwdep_t * hw, struct file * file, struct vm_area_struct * vma);
int (*dsp_status) (snd_hwdep_t * hw, snd_hwdep_dsp_status_t * status);
int (*dsp_load) (snd_hwdep_t * hw, snd_hwdep_dsp_image_t * image);
......
......@@ -38,7 +38,7 @@ typedef int (*snd_mixer_oss_put_recsrce_t)(snd_mixer_oss_file_t *fmixer, unsigne
struct _snd_oss_mixer_slot {
int number;
int stereo: 1;
unsigned int stereo: 1;
snd_mixer_oss_get_volume_t get_volume;
snd_mixer_oss_put_volume_t put_volume;
snd_mixer_oss_get_recsrc_t get_recsrc;
......
......@@ -86,9 +86,6 @@ struct _snd_mpu401 {
spinlock_t output_lock;
spinlock_t timer_lock;
atomic_t rx_loop;
atomic_t tx_loop;
struct timer_list timer;
void (*write) (mpu401_t * mpu, unsigned char data, unsigned long addr);
......
......@@ -23,6 +23,7 @@
*/
#include <sound/asound.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <asm/semaphore.h>
......@@ -65,8 +66,7 @@ typedef struct _snd_rawmidi_global_ops {
} snd_rawmidi_global_ops_t;
struct _snd_rawmidi_runtime {
unsigned int trigger: 1, /* transfer is running */
drain: 1, /* drain stage */
unsigned int drain: 1, /* drain stage */
oss: 1; /* OSS compatible mode */
/* midi stream buffer */
unsigned char *buffer; /* buffer for MIDI data */
......@@ -80,6 +80,7 @@ struct _snd_rawmidi_runtime {
spinlock_t lock;
wait_queue_head_t sleep;
/* event handler (room [output] or new bytes [input]) */
struct tasklet_struct event_tasklet;
void (*event)(snd_rawmidi_substream_t *substream);
/* private data */
void *private_data;
......
......@@ -38,7 +38,7 @@ typedef struct _snd_virmidi {
int seq_mode;
int client;
int port;
int trigger: 1;
unsigned int trigger: 1;
snd_midi_event_t *parser;
snd_seq_event_t event;
snd_virmidi_dev_t *rdev;
......
......@@ -290,7 +290,7 @@ typedef struct {
int mode; /* operation mode */
int client; /* sequencer client number */
int port; /* sequencer port number */
int midi_has_voices: 1;
unsigned int midi_has_voices: 1;
} snd_trident_port_t;
typedef struct snd_trident_memblk_arg {
......@@ -308,7 +308,7 @@ typedef struct {
struct _snd_trident_voice {
unsigned int number;
int use: 1,
unsigned int use: 1,
pcm: 1,
synth:1,
midi: 1;
......@@ -347,7 +347,7 @@ struct _snd_trident_voice {
trident_t *trident;
snd_pcm_substream_t *substream;
snd_trident_voice_t *extra; /* extra PCM voice (acts as interrupt generator) */
int running: 1,
unsigned int running: 1,
capture: 1,
spdif: 1,
foldback: 1,
......
......@@ -266,7 +266,7 @@ typedef enum {
struct _snd_ymfpci_voice {
ymfpci_t *chip;
int number;
int use: 1,
unsigned int use: 1,
pcm: 1,
synth: 1,
midi: 1;
......@@ -292,9 +292,9 @@ struct _snd_ymfpci_pcm {
snd_ymfpci_pcm_type_t type;
snd_pcm_substream_t *substream;
ymfpci_voice_t *voices[2]; /* playback only */
int running: 1;
int output_front: 1;
int output_rear: 1;
unsigned int running: 1;
unsigned int output_front: 1;
unsigned int output_rear: 1;
u32 period_size; /* cached from runtime->period_size */
u32 buffer_size; /* cached from runtime->buffer_size */
u32 period_pos;
......
#ifndef __SOUND_YSS225_H
#define __SOUND_YSS225_H
extern unsigned char page_zero[256];
extern unsigned char page_one[256];
extern unsigned char page_two[128];
extern unsigned char page_three[128];
extern unsigned char page_four[128];
extern unsigned char page_six[192];
extern unsigned char page_seven[256];
extern unsigned char page_zero_v2[96];
extern unsigned char page_one_v2[96];
extern unsigned char page_two_v2[48];
extern unsigned char page_three_v2[48];
extern unsigned char page_four_v2[48];
extern unsigned char page_seven_v2[96];
extern unsigned char mod_v2[304];
extern unsigned char coefficients[364];
extern unsigned char coefficients2[56];
extern unsigned char coefficients3[404];
#endif /* __SOUND_YSS225_H */
......@@ -21,7 +21,7 @@
* merged HAL layer (patches from Brian)
*/
/* $Id: sa11xx-uda1341.c,v 1.19 2004/12/15 15:26:10 tiwai Exp $ */
/* $Id: sa11xx-uda1341.c,v 1.21 2005/01/28 19:34:04 tiwai Exp $ */
/***************************************************************************************************
*
......@@ -862,7 +862,7 @@ static int __init snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341_t *sa11xx_uda1341,
#ifdef CONFIG_PM
static int snd_sa11xx_uda1341_suspend(snd_card_t *card, unsigned int state)
static int snd_sa11xx_uda1341_suspend(snd_card_t *card, pm_message_t state)
{
sa11xx_uda1341_t *chip = card->pm_private_data;
......@@ -878,7 +878,7 @@ static int snd_sa11xx_uda1341_suspend(snd_card_t *card, unsigned int state)
return 0;
}
static int snd_sa11xx_uda1341_resume(snd_card_t *card, unsigned int state)
static int snd_sa11xx_uda1341_resume(snd_card_t *card)
{
sa11xx_uda1341_t *chip = card->pm_private_data;
......@@ -938,7 +938,7 @@ static int __init sa11xx_uda1341_init(void)
if ((err = snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341, 0)) < 0)
goto nodev;
snd_card_set_dev_pm_callback(card, PM_SYS_DEV,
snd_card_set_generic_pm_callback(card,
snd_sa11xx_uda1341_suspend, snd_sa11_uda1341_resume,
sa11xx_uda1341);
......
# ALSA soundcard-configuration
config SND_TIMER
tristate
depends on SND
config SND_PCM
tristate
select SND_TIMER
depends on SND
config SND_HWDEP
tristate
depends on SND
config SND_RAWMIDI
tristate
depends on SND
config SND_SEQUENCER
tristate "Sequencer support"
......@@ -40,6 +44,7 @@ config SND_SEQ_DUMMY
config SND_OSSEMUL
bool
depends on SND
config SND_MIXER_OSS
tristate "OSS Mixer API"
......@@ -70,7 +75,7 @@ config SND_PCM_OSS
config SND_SEQUENCER_OSS
bool "OSS Sequencer API"
depends on SND_SEQUENCER
depends on SND && SND_SEQUENCER
select SND_OSSEMUL
help
Say Y here to enable OSS sequencer emulation (both
......@@ -81,20 +86,6 @@ config SND_SEQUENCER_OSS
To compile this driver as a module, choose M here: the module
will be called snd-seq-oss.
config SND_BIT32_EMUL
tristate "Emulation for 32-bit applications"
depends on SND && COMPAT
select SND_PCM
select SND_RAWMIDI
select SND_TIMER
select SND_HWDEP
help
Say Y here to enable the emulation for 32-bit ALSA-native
applications.
To compile this driver as a module, choose M here: the module
will be called snd-ioctl32.
config SND_RTCTIMER
tristate "RTC Timer support"
depends on SND && RTC
......@@ -137,3 +128,6 @@ config SND_DEBUG_DETECT
Say Y here to enable extra-verbose log messages printed when
detecting devices.
config SND_GENERIC_PM
bool
depends on SND
......@@ -31,4 +31,3 @@ obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
obj-$(CONFIG_SND_OSSEMUL) += oss/
obj-$(CONFIG_SND_SEQUENCER) += seq/
obj-$(CONFIG_SND_BIT32_EMUL) += ioctl32/
This diff is collapsed.
......@@ -232,8 +232,7 @@ static int snd_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t __user *_in
return 0;
}
static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file,
unsigned int cmd, unsigned long arg)
static long snd_hwdep_ioctl(struct file * file, unsigned int cmd, unsigned long arg)
{
snd_hwdep_t *hw = file->private_data;
void __user *argp = (void __user *)arg;
......@@ -252,17 +251,6 @@ static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file,
return -ENOTTY;
}
/* FIXME: need to unlock BKL to allow preemption */
static int snd_hwdep_ioctl(struct inode *inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
int err;
unlock_kernel();
err = _snd_hwdep_ioctl(inode, file, cmd, arg);
lock_kernel();
return err;
}
static int snd_hwdep_mmap(struct file * file, struct vm_area_struct * vma)
{
snd_hwdep_t *hw = file->private_data;
......@@ -315,6 +303,12 @@ static int snd_hwdep_control_ioctl(snd_card_t * card, snd_ctl_file_t * control,
return -ENOIOCTLCMD;
}
#ifdef CONFIG_COMPAT
#include "hwdep_compat.c"
#else
#define snd_hwdep_ioctl_compat NULL
#endif
/*
*/
......@@ -328,7 +322,8 @@ static struct file_operations snd_hwdep_f_ops =
.open = snd_hwdep_open,
.release = snd_hwdep_release,
.poll = snd_hwdep_poll,
.ioctl = snd_hwdep_ioctl,
.unlocked_ioctl = snd_hwdep_ioctl,
.compat_ioctl = snd_hwdep_ioctl_compat,
.mmap = snd_hwdep_mmap,
};
......@@ -509,12 +504,14 @@ static int __init alsa_hwdep_init(void)
}
snd_hwdep_proc_entry = entry;
snd_ctl_register_ioctl(snd_hwdep_control_ioctl);
snd_ctl_register_ioctl_compat(snd_hwdep_control_ioctl);
return 0;
}
static void __exit alsa_hwdep_exit(void)
{
snd_ctl_unregister_ioctl(snd_hwdep_control_ioctl);
snd_ctl_unregister_ioctl_compat(snd_hwdep_control_ioctl);
if (snd_hwdep_proc_entry) {
snd_info_unregister(snd_hwdep_proc_entry);
snd_hwdep_proc_entry = NULL;
......
......@@ -18,13 +18,9 @@
*
*/
#include <sound/driver.h>
#include <linux/time.h>
#include <linux/fs.h>
#include <sound/core.h>
#include <sound/hwdep.h>
#include <asm/uaccess.h>
#include "ioctl32.h"
/* This file is included from hwdep.c */
#include <linux/compat.h>
struct sndrv_hwdep_dsp_image32 {
u32 index;
......@@ -34,40 +30,48 @@ struct sndrv_hwdep_dsp_image32 {
u32 driver_data;
} /* don't set packed attribute here */;
static inline int _snd_ioctl32_hwdep_dsp_image(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
static int snd_hwdep_dsp_load_compat(snd_hwdep_t *hw,
struct sndrv_hwdep_dsp_image32 __user *src)
{
struct sndrv_hwdep_dsp_image __user *data, *dst;
struct sndrv_hwdep_dsp_image32 __user *data32, *src;
struct sndrv_hwdep_dsp_image *dst;
compat_caddr_t ptr;
u32 val;
data32 = compat_ptr(arg);
data = compat_alloc_user_space(sizeof(*data));
dst = compat_alloc_user_space(sizeof(*dst));
/* index and name */
if (copy_in_user(data, data32, 4 + 64))
if (copy_in_user(dst, src, 4 + 64))
return -EFAULT;
if (__get_user(ptr, &data32->image) ||
__put_user(compat_ptr(ptr), &data->image))
if (get_user(ptr, &src->image) ||
put_user(compat_ptr(ptr), &dst->image))
return -EFAULT;
if (get_user(val, &src->length) ||
put_user(val, &dst->length))
return -EFAULT;
if (get_user(val, &src->driver_data) ||
put_user(val, &dst->driver_data))
return -EFAULT;
src = data32;
dst = data;
COPY_CVT(length);
COPY_CVT(driver_data);
return file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
}
DEFINE_ALSA_IOCTL_ENTRY(hwdep_dsp_image, hwdep_dsp_image, SNDRV_HWDEP_IOCTL_DSP_LOAD);
#define AP(x) snd_ioctl32_##x
return snd_hwdep_dsp_load(hw, dst);
}
enum {
SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image32)
};
struct ioctl32_mapper hwdep_mappers[] = {
MAP_COMPAT(SNDRV_HWDEP_IOCTL_PVERSION),
MAP_COMPAT(SNDRV_HWDEP_IOCTL_INFO),
MAP_COMPAT(SNDRV_HWDEP_IOCTL_DSP_STATUS),
{ SNDRV_HWDEP_IOCTL_DSP_LOAD32, AP(hwdep_dsp_image) },
{ 0 },
};
static long snd_hwdep_ioctl_compat(struct file * file, unsigned int cmd, unsigned long arg)
{
snd_hwdep_t *hw = file->private_data;
void __user *argp = compat_ptr(arg);
switch (cmd) {
case SNDRV_HWDEP_IOCTL_PVERSION:
case SNDRV_HWDEP_IOCTL_INFO:
case SNDRV_HWDEP_IOCTL_DSP_STATUS:
return snd_hwdep_ioctl(file, cmd, (unsigned long)argp);
case SNDRV_HWDEP_IOCTL_DSP_LOAD32:
return snd_hwdep_dsp_load_compat(hw, argp);
}
if (hw->ops.ioctl_compat)
return hw->ops.ioctl_compat(hw, file, cmd, arg);
return -ENOIOCTLCMD;
}
......@@ -39,7 +39,7 @@ struct snd_shutdown_f_ops {
unsigned int snd_cards_lock = 0; /* locked for registering/using */
snd_card_t *snd_cards[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = NULL};
rwlock_t snd_card_rwlock = RW_LOCK_UNLOCKED;
DEFINE_RWLOCK(snd_card_rwlock);
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
int (*snd_mixer_oss_notify_callback)(snd_card_t *card, int free_flag);
......@@ -84,16 +84,13 @@ snd_card_t *snd_card_new(int idx, const char *xid,
write_lock(&snd_card_rwlock);
if (idx < 0) {
int idx2;
for (idx2 = 0; idx2 < snd_ecards_limit; idx2++)
if (!(snd_cards_lock & (1 << idx2))) {
for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
if (~snd_cards_lock & idx & 1<<idx2) {
idx = idx2;
if (idx >= snd_ecards_limit)
snd_ecards_limit = idx + 1;
break;
}
if (idx < 0 && snd_ecards_limit < SNDRV_CARDS)
/* for dynamically additional devices like hotplug:
* increment the limit if still free slot exists.
*/
idx = snd_ecards_limit++;
} else if (idx < snd_ecards_limit) {
if (snd_cards_lock & (1 << idx))
err = -ENODEV; /* invalid */
......@@ -229,6 +226,10 @@ int snd_card_disconnect(snd_card_t * card)
return 0;
}
#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM)
static void snd_generic_device_unregister(struct snd_generic_device *dev);
#endif
/**
* snd_card_free - frees given soundcard structure
* @card: soundcard structure
......@@ -252,9 +253,9 @@ int snd_card_free(snd_card_t * card)
#ifdef CONFIG_PM
wake_up(&card->power_sleep);
#ifdef CONFIG_ISA
#ifdef CONFIG_SND_GENERIC_PM
if (card->pm_dev) {
pm_unregister(card->pm_dev);
snd_generic_device_unregister(card->pm_dev);
card->pm_dev = NULL;
}
#endif
......@@ -374,7 +375,7 @@ static void choose_default_id(snd_card_t * card)
while (1) {
if (loops-- == 0) {
snd_printk(KERN_ERR "unable to choose default card id (%s)", id);
snd_printk(KERN_ERR "unable to choose default card id (%s)\n", id);
strcpy(card->id, card->proc_root->name);
return;
}
......@@ -719,8 +720,8 @@ int snd_power_wait(snd_card_t *card, unsigned int power_state, struct file *file
* handler and from the control API.
*/
int snd_card_set_pm_callback(snd_card_t *card,
int (*suspend)(snd_card_t *, unsigned int),
int (*resume)(snd_card_t *, unsigned int),
int (*suspend)(snd_card_t *, pm_message_t),
int (*resume)(snd_card_t *),
void *private_data)
{
card->pm_suspend = suspend;
......@@ -729,56 +730,132 @@ int snd_card_set_pm_callback(snd_card_t *card,
return 0;
}
static int snd_generic_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
#ifdef CONFIG_SND_GENERIC_PM
/*
* use platform_device for generic power-management without a proper bus
* (e.g. ISA)
*/
struct snd_generic_device {
struct platform_device pdev;
snd_card_t *card;
};
#define get_snd_generic_card(dev) container_of(to_platform_device(dev), struct snd_generic_device, pdev)->card
#define SND_GENERIC_NAME "snd_generic_pm"
static int snd_generic_suspend(struct device *dev, u32 state, u32 level);
static int snd_generic_resume(struct device *dev, u32 level);
static struct device_driver snd_generic_driver = {
.name = SND_GENERIC_NAME,
.bus = &platform_bus_type,
.suspend = snd_generic_suspend,
.resume = snd_generic_resume,
};
static int generic_driver_registered;
static void generic_driver_unregister(void)
{
if (generic_driver_registered) {
generic_driver_registered--;
if (! generic_driver_registered)
driver_unregister(&snd_generic_driver);
}
}
static struct snd_generic_device *snd_generic_device_register(snd_card_t *card)
{
snd_card_t *card = dev->data;
struct snd_generic_device *dev;
switch (rqst) {
case PM_SUSPEND:
if (card->power_state == SNDRV_CTL_POWER_D3hot)
break;
/* FIXME: the correct state value? */
card->pm_suspend(card, 0);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
break;
case PM_RESUME:
if (card->power_state == SNDRV_CTL_POWER_D0)
break;
/* FIXME: the correct state value? */
card->pm_resume(card, 0);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
break;
if (! generic_driver_registered) {
if (driver_register(&snd_generic_driver) < 0)
return NULL;
}
generic_driver_registered++;
dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
if (! dev) {
generic_driver_unregister();
return NULL;
}
dev->pdev.name = SND_GENERIC_NAME;
dev->pdev.id = card->number;
dev->card = card;
if (platform_device_register(&dev->pdev) < 0) {
kfree(dev);
generic_driver_unregister();
return NULL;
}
return dev;
}
static void snd_generic_device_unregister(struct snd_generic_device *dev)
{
platform_device_unregister(&dev->pdev);
kfree(dev);
generic_driver_unregister();
}
/* suspend/resume callbacks for snd_generic platform device */
static int snd_generic_suspend(struct device *dev, u32 state, u32 level)
{
snd_card_t *card;
if (level != SUSPEND_DISABLE)
return 0;
card = get_snd_generic_card(dev);
if (card->power_state == SNDRV_CTL_POWER_D3hot)
return 0;
card->pm_suspend(card, PMSG_SUSPEND);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
return 0;
}
static int snd_generic_resume(struct device *dev, u32 level)
{
snd_card_t *card;
if (level != RESUME_ENABLE)
return 0;
card = get_snd_generic_card(dev);
if (card->power_state == SNDRV_CTL_POWER_D0)
return 0;
card->pm_resume(card);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
/**
* snd_card_set_dev_pm_callback - set the generic power-management callbacks
* snd_card_set_generic_pm_callback - set the generic power-management callbacks
* @card: soundcard structure
* @type: PM device type (PM_XXX)
* @suspend: suspend callback function
* @resume: resume callback function
* @private_data: private data to pass to the callback functions
*
* Registers the power-management and sets the lowlevel callbacks for
* the given card with the given PM type. These callbacks are called
* from the ALSA's common PM handler and from the control API.
* the given card. These callbacks are called from the ALSA's common
* PM handler and from the control API.
*/
int snd_card_set_dev_pm_callback(snd_card_t *card, int type,
int (*suspend)(snd_card_t *, unsigned int),
int (*resume)(snd_card_t *, unsigned int),
int snd_card_set_generic_pm_callback(snd_card_t *card,
int (*suspend)(snd_card_t *, pm_message_t),
int (*resume)(snd_card_t *),
void *private_data)
{
card->pm_dev = pm_register(type, 0, snd_generic_pm_callback);
card->pm_dev = snd_generic_device_register(card);
if (! card->pm_dev)
return -ENOMEM;
card->pm_dev->data = card;
snd_card_set_pm_callback(card, suspend, resume, private_data);
return 0;
}
#endif /* CONFIG_SND_GENERIC_PM */
#ifdef CONFIG_PCI
int snd_card_pci_suspend(struct pci_dev *dev, u32 state)
int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state)
{
snd_card_t *card = pci_get_drvdata(dev);
int err;
......@@ -786,8 +863,7 @@ int snd_card_pci_suspend(struct pci_dev *dev, u32 state)
return 0;
if (card->power_state == SNDRV_CTL_POWER_D3hot)
return 0;
/* FIXME: correct state value? */
err = card->pm_suspend(card, 0);
err = card->pm_suspend(card, PMSG_SUSPEND);
pci_save_state(dev);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
return err;
......@@ -802,8 +878,7 @@ int snd_card_pci_resume(struct pci_dev *dev)
return 0;
/* restore the PCI config space */
pci_restore_state(dev);
/* FIXME: correct state value? */
card->pm_resume(card, 0);
card->pm_resume(card);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
......
#
# Makefile for ALSA
# Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
#
snd-ioctl32-objs := ioctl32.o pcm32.o rawmidi32.o timer32.o hwdep32.o
ifneq ($(CONFIG_SND_SEQUENCER),n)
snd-ioctl32-objs += seq32.o
endif
obj-$(CONFIG_SND_BIT32_EMUL) += snd-ioctl32.o
/*
* 32bit -> 64bit ioctl helpers
* Copyright (c) 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
*
*
* This file registers the converters from 32-bit ioctls to 64-bit ones.
* The converter assumes that a 32-bit user-pointer can be casted by compat_ptr(x)
* macro to a valid 64-bit pointer which is accessible via copy_from/to_user.
*
*/
#ifndef __ALSA_IOCTL32_H
#define __ALSA_IOCTL32_H
#include <linux/compat.h>
#define COPY(x) \
do { \
if (copy_in_user(&dst->x, &src->x, sizeof(dst->x))) \
return -EFAULT; \
} while (0)
#define COPY_ARRAY(x) \
do { \
if (copy_in_user(dst->x, src->x, sizeof(dst->x))) \
return -EFAULT; \
} while (0)
#define COPY_CVT(x) \
do { \
__typeof__(src->x) __val_tmp; \
if (get_user(__val_tmp, &src->x) || \
put_user(__val_tmp, &dst->x))\
return -EFAULT; \
} while (0)
#define convert_from_32(type, dstp, srcp)\
{\
struct sndrv_##type __user *dst = dstp;\
struct sndrv_##type##32 __user *src = srcp;\
CVT_##sndrv_##type();\
}
#define convert_to_32(type, dstp, srcp)\
{\
struct sndrv_##type __user *src = srcp;\
struct sndrv_##type##32 __user *dst = dstp;\
CVT_##sndrv_##type();\
}
#define DEFINE_ALSA_IOCTL(type) \
static inline int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
{\
struct sndrv_##type##32 __user *data32;\
struct sndrv_##type __user *data;\
int err;\
data32 = compat_ptr(arg);\
data = compat_alloc_user_space(sizeof(*data));\
convert_from_32(type, data, data32);\
err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);\
if (err < 0) \
return err;\
if (native_ctl & (_IOC_READ << _IOC_DIRSHIFT)) {\
convert_to_32(type, data32, data);\
}\
return 0;\
}
#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);\
}
#define MAP_COMPAT(ctl) { ctl, snd_ioctl32_compat }
struct ioctl32_mapper {
unsigned int cmd;
int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
int registered;
};
int snd_ioctl32_compat(unsigned int, unsigned int, unsigned long, struct file *);
int snd_ioctl32_register(struct ioctl32_mapper *mappers);
void snd_ioctl32_unregister(struct ioctl32_mapper *mappers);
#endif /* __ALSA_IOCTL32_H */
......@@ -50,8 +50,8 @@ static long snd_alloc_kmalloc;
static long snd_alloc_vmalloc;
static LIST_HEAD(snd_alloc_kmalloc_list);
static LIST_HEAD(snd_alloc_vmalloc_list);
static spinlock_t snd_alloc_kmalloc_lock = SPIN_LOCK_UNLOCKED;
static spinlock_t snd_alloc_vmalloc_lock = SPIN_LOCK_UNLOCKED;
static DEFINE_SPINLOCK(snd_alloc_kmalloc_lock);
static DEFINE_SPINLOCK(snd_alloc_vmalloc_lock);
#define KMALLOC_MAGIC 0x87654321
#define VMALLOC_MAGIC 0x87654320
static snd_info_entry_t *snd_memory_info_entry;
......
......@@ -359,16 +359,9 @@ static int snd_mixer_oss_ioctl1(snd_mixer_oss_file_t *fmixer, unsigned int cmd,
return -ENXIO;
}
/* FIXME: need to unlock BKL to allow preemption */
static int snd_mixer_oss_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int err;
/* FIXME: need to unlock BKL to allow preemption */
unlock_kernel();
err = snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
lock_kernel();
return err;
return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
}
int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg)
......@@ -384,6 +377,13 @@ int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long a
return snd_mixer_oss_ioctl1(&fmixer, cmd, arg);
}
#ifdef CONFIG_COMPAT
/* all compatible */
#define snd_mixer_oss_ioctl_compat snd_mixer_oss_ioctl
#else
#define snd_mixer_oss_ioctl_compat NULL
#endif
/*
* REGISTRATION PART
*/
......@@ -393,7 +393,8 @@ static struct file_operations snd_mixer_oss_f_ops =
.owner = THIS_MODULE,
.open = snd_mixer_oss_open,
.release = snd_mixer_oss_release,
.ioctl = snd_mixer_oss_ioctl,
.unlocked_ioctl = snd_mixer_oss_ioctl,
.compat_ioctl = snd_mixer_oss_ioctl_compat,
};
static snd_minor_t snd_mixer_oss_reg =
......@@ -521,7 +522,7 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
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);
snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, goto __unalloc);
*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]);
......@@ -615,7 +616,7 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
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);
snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, goto __unalloc);
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);
......
......@@ -636,10 +636,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char
if (in_kernel) {
mm_segment_t fs;
fs = snd_enter_user();
ret = snd_pcm_lib_write(substream, ptr, frames);
ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
snd_leave_user(fs);
} else {
ret = snd_pcm_lib_write(substream, ptr, frames);
ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
}
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
......@@ -679,10 +679,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, s
if (in_kernel) {
mm_segment_t fs;
fs = snd_enter_user();
ret = snd_pcm_lib_read(substream, ptr, frames);
ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
snd_leave_user(fs);
} else {
ret = snd_pcm_lib_read(substream, ptr, frames);
ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
}
if (ret == -EPIPE) {
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
......@@ -718,10 +718,10 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **buf
if (in_kernel) {
mm_segment_t fs;
fs = snd_enter_user();
ret = snd_pcm_lib_writev(substream, bufs, frames);
ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
snd_leave_user(fs);
} else {
ret = snd_pcm_lib_writev(substream, bufs, frames);
ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
}
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
......@@ -758,10 +758,10 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs
if (in_kernel) {
mm_segment_t fs;
fs = snd_enter_user();
ret = snd_pcm_lib_readv(substream, bufs, frames);
ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
snd_leave_user(fs);
} else {
ret = snd_pcm_lib_readv(substream, bufs, frames);
ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
}
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
......@@ -777,7 +777,7 @@ static ssize_t snd_pcm_oss_write2(snd_pcm_substream_t *substream, const char *bu
snd_pcm_plugin_channel_t *channels;
size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
if (!in_kernel) {
if (copy_from_user(runtime->oss.buffer, buf, bytes))
if (copy_from_user(runtime->oss.buffer, (const char __user *)buf, bytes))
return -EFAULT;
buf = runtime->oss.buffer;
}
......@@ -839,7 +839,7 @@ static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char __u
return xfer > 0 ? xfer : -EAGAIN;
}
} else {
tmp = snd_pcm_oss_write2(substream, (char *)buf, runtime->oss.period_bytes, 0);
tmp = snd_pcm_oss_write2(substream, (const char *)buf, runtime->oss.period_bytes, 0);
if (tmp <= 0)
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
runtime->oss.bytes += tmp;
......@@ -858,7 +858,7 @@ static ssize_t snd_pcm_oss_read2(snd_pcm_substream_t *substream, char *buf, size
{
snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_sframes_t frames, frames1;
char *final_dst = buf;
char __user *final_dst = (char __user *)buf;
if (runtime->oss.plugin_first) {
snd_pcm_plugin_channel_t *channels;
size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;
......@@ -1058,6 +1058,7 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file)
if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
size = (runtime->frame_bits * size) / 8;
while (size > 0) {
mm_segment_t fs;
size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes;
size -= size1;
size1 *= 8;
......@@ -1065,7 +1066,9 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file)
snd_pcm_format_set_silence(runtime->format,
runtime->oss.buffer,
size1);
snd_pcm_lib_write(substream, runtime->oss.buffer, size1);
fs = snd_enter_user();
snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1);
snd_leave_user(fs);
}
} else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
void __user *buffers[runtime->channels];
......@@ -1913,8 +1916,7 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file)
return 0;
}
static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
snd_pcm_oss_file_t *pcm_oss_file;
int __user *p = (int __user *)arg;
......@@ -2073,16 +2075,12 @@ static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
}
/* FIXME: need to unlock BKL to allow preemption */
static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int err;
unlock_kernel();
err = _snd_pcm_oss_ioctl(inode, file, cmd, arg);
lock_kernel();
return err;
}
#ifdef CONFIG_COMPAT
/* all compatible */
#define snd_pcm_oss_ioctl_compat snd_pcm_oss_ioctl
#else
#define snd_pcm_oss_ioctl_compat NULL
#endif
static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
......@@ -2410,7 +2408,8 @@ static struct file_operations snd_pcm_oss_f_reg =
.open = snd_pcm_oss_open,
.release = snd_pcm_oss_release,
.poll = snd_pcm_oss_poll,
.ioctl = snd_pcm_oss_ioctl,
.unlocked_ioctl = snd_pcm_oss_ioctl,
.compat_ioctl = snd_pcm_oss_ioctl_compat,
.mmap = snd_pcm_oss_mmap,
};
......
......@@ -1004,6 +1004,7 @@ static int __init alsa_pcm_init(void)
snd_info_entry_t *entry;
snd_ctl_register_ioctl(snd_pcm_control_ioctl);
snd_ctl_register_ioctl_compat(snd_pcm_control_ioctl);
if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) {
snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128, snd_pcm_proc_read);
if (snd_info_register(entry) < 0) {
......@@ -1018,6 +1019,7 @@ static int __init alsa_pcm_init(void)
static void __exit alsa_pcm_exit(void)
{
snd_ctl_unregister_ioctl(snd_pcm_control_ioctl);
snd_ctl_unregister_ioctl_compat(snd_pcm_control_ioctl);
if (snd_pcm_proc_entry) {
snd_info_unregister(snd_pcm_proc_entry);
snd_pcm_proc_entry = NULL;
......
......@@ -1863,9 +1863,8 @@ static void snd_pcm_system_tick_set(snd_pcm_substream_t *substream,
if (ticks == 0)
del_timer(&runtime->tick_timer);
else {
ticks += (1000000 / HZ) - 1;
ticks /= (1000000 / HZ);
if (ticks % (1000000 / HZ))
ticks++;
mod_timer(&runtime->tick_timer, jiffies + ticks);
}
}
......@@ -2142,11 +2141,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
break;
}
appl_ptr += frames;
if (appl_ptr >= runtime->boundary) {
runtime->control->appl_ptr = 0;
} else {
runtime->control->appl_ptr = appl_ptr;
}
if (appl_ptr >= runtime->boundary)
appl_ptr -= runtime->boundary;
runtime->control->appl_ptr = appl_ptr;
if (substream->ops->ack)
substream->ops->ack(substream);
......@@ -2441,11 +2438,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream,
break;
}
appl_ptr += frames;
if (appl_ptr >= runtime->boundary) {
runtime->control->appl_ptr = 0;
} else {
runtime->control->appl_ptr = appl_ptr;
}
if (appl_ptr >= runtime->boundary)
appl_ptr -= runtime->boundary;
runtime->control->appl_ptr = appl_ptr;
if (substream->ops->ack)
substream->ops->ack(substream);
......
......@@ -291,7 +291,7 @@ struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned lon
* @substream: the substream to allocate the DMA buffer to
* @size: the requested buffer size in bytes
*
* Allocates the DMA buffer on the BUS type given by
* Allocates the DMA buffer on the BUS type given earlier to
* snd_pcm_lib_preallocate_xxx_pages().
*
* Returns 1 if the buffer is changed, 0 if not changed, or a negative
......
......@@ -65,7 +65,7 @@ static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sn
*
*/
rwlock_t snd_pcm_link_rwlock = RW_LOCK_UNLOCKED;
DEFINE_RWLOCK(snd_pcm_link_rwlock);
static DECLARE_RWSEM(snd_pcm_link_rwsem);
......@@ -602,17 +602,13 @@ static int snd_pcm_status_user(snd_pcm_substream_t * substream, snd_pcm_status_t
return 0;
}
static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info)
static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t * info)
{
snd_pcm_channel_info_t info;
snd_pcm_runtime_t *runtime;
int res;
unsigned int channel;
snd_assert(substream != NULL, return -ENXIO);
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
channel = info.channel;
channel = info->channel;
runtime = substream->runtime;
snd_pcm_stream_lock_irq(substream);
if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
......@@ -622,9 +618,19 @@ static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel
snd_pcm_stream_unlock_irq(substream);
if (channel >= runtime->channels)
return -EINVAL;
memset(&info, 0, sizeof(info));
info.channel = channel;
res = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, &info);
memset(info, 0, sizeof(*info));
info->channel = channel;
return substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, info);
}
static int snd_pcm_channel_info_user(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info)
{
snd_pcm_channel_info_t info;
int res;
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
res = snd_pcm_channel_info(substream, &info);
if (res < 0)
return res;
if (copy_to_user(_info, &info, sizeof(info)))
......@@ -2440,7 +2446,7 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream,
case SNDRV_PCM_IOCTL_STATUS:
return snd_pcm_status_user(substream, arg);
case SNDRV_PCM_IOCTL_CHANNEL_INFO:
return snd_pcm_channel_info(substream, arg);
return snd_pcm_channel_info_user(substream, arg);
case SNDRV_PCM_IOCTL_PREPARE:
return snd_pcm_prepare(substream);
case SNDRV_PCM_IOCTL_RESET:
......@@ -2640,40 +2646,28 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_common_ioctl1(substream, cmd, arg);
}
static int snd_pcm_playback_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
snd_pcm_file_t *pcm_file;
int err;
pcm_file = file->private_data;
if (((cmd >> 8) & 0xff) != 'A')
return -ENOTTY;
/* FIXME: need to unlock BKL to allow preemption */
unlock_kernel();
err = snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
lock_kernel();
return err;
return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
}
static int snd_pcm_capture_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
snd_pcm_file_t *pcm_file;
int err;
pcm_file = file->private_data;
if (((cmd >> 8) & 0xff) != 'A')
return -ENOTTY;
/* FIXME: need to unlock BKL to allow preemption */
unlock_kernel();
err = snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
lock_kernel();
return err;
return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
}
int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream,
......@@ -2683,7 +2677,7 @@ int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream,
int result;
fs = snd_enter_user();
result = snd_pcm_playback_ioctl1(substream, cmd, arg);
result = snd_pcm_playback_ioctl1(substream, cmd, (void __user *)arg);
snd_leave_user(fs);
return result;
}
......@@ -2695,7 +2689,7 @@ int snd_pcm_kernel_capture_ioctl(snd_pcm_substream_t *substream,
int result;
fs = snd_enter_user();
result = snd_pcm_capture_ioctl1(substream, cmd, arg);
result = snd_pcm_capture_ioctl1(substream, cmd, (void __user *)arg);
snd_leave_user(fs);
return result;
}
......@@ -3197,6 +3191,15 @@ static int snd_pcm_fasync(int fd, struct file * file, int on)
return 0;
}
/*
* ioctl32 compat
*/
#ifdef CONFIG_COMPAT
#include "pcm_compat.c"
#else
#define snd_pcm_ioctl_compat NULL
#endif
/*
* To be removed helpers to keep binary compatibility
*/
......@@ -3318,7 +3321,8 @@ static struct file_operations snd_pcm_f_ops_playback = {
.open = snd_pcm_open,
.release = snd_pcm_release,
.poll = snd_pcm_playback_poll,
.ioctl = snd_pcm_playback_ioctl,
.unlocked_ioctl = snd_pcm_playback_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
.fasync = snd_pcm_fasync,
};
......@@ -3330,7 +3334,8 @@ static struct file_operations snd_pcm_f_ops_capture = {
.open = snd_pcm_open,
.release = snd_pcm_release,
.poll = snd_pcm_capture_poll,
.ioctl = snd_pcm_capture_ioctl,
.unlocked_ioctl = snd_pcm_capture_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
.fasync = snd_pcm_fasync,
};
......
This diff is collapsed.
......@@ -183,4 +183,6 @@ MODULE_PARM_DESC(rtctimer_freq, "timer frequency in Hz");
MODULE_LICENSE("GPL");
MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_RTC));
#endif /* CONFIG_RTC || CONFIG_RTC_MODULE */
This diff is collapsed.
......@@ -56,7 +56,7 @@ struct seq_oss_midi_t {
static int max_midi_devs;
static seq_oss_midi_t *midi_devs[SNDRV_SEQ_OSS_MAX_MIDI_DEVS];
static spinlock_t register_lock = SPIN_LOCK_UNLOCKED;
static DEFINE_SPINLOCK(register_lock);
/*
* prototypes
......
......@@ -24,6 +24,7 @@
#include "seq_oss_event.h"
#include <sound/seq_oss_legacy.h>
#include "../seq_lock.h"
#include <linux/wait.h>
/*
* constants
......@@ -165,7 +166,9 @@ snd_seq_oss_readq_pick(seq_oss_readq_t *q, evrec_t *rec)
void
snd_seq_oss_readq_wait(seq_oss_readq_t *q)
{
interruptible_sleep_on_timeout(&q->midi_sleep, q->pre_event_timeout);
wait_event_interruptible_timeout(q->midi_sleep,
(q->qlen > 0 || q->head == q->tail),
q->pre_event_timeout);
}
/*
......
......@@ -75,7 +75,7 @@ static seq_oss_synth_t midi_synth_dev = {
"MIDI", /* name */
};
static spinlock_t register_lock = SPIN_LOCK_UNLOCKED;
static DEFINE_SPINLOCK(register_lock);
/*
* prototypes
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment