Commit bbf5aea1 authored by Jaroslav Kysela's avatar Jaroslav Kysela Committed by Linus Torvalds

[PATCH] ALSA patch for 2.5.6pre2

Hello,

	this recent ALSA patch includes:

- added initial version of Config.help files
- moved /proc/asound/sndstat to /proc/asound/oss/sndstat
- moved /proc/asound/oss-devices to /proc/asound/oss/devices
- snd-rtctimer updates (blocking of RTC driver change)
- added ioctl conversion code for 32-bit applications running on 64-bit kernels
- fixed dependencies in makefiles
- wavefront driver cleanups (removed LOOPS_PER_SEC)
- created Documentation/sound/alsa directory

						Jaroslav
parent adc4bc97
Brief Notes on C-Media 8738/8338 Driver
=======================================
Takashi Iwai <tiwai@suse.de>
Front/Rear Multi-channel Playback
---------------------------------
CM8x38 chip can use ADC as the second DAC so that two different stereo
channels can be used for front/rear playbacks. Since there are two
DACs, both streams are handled independently unlike the 4/6ch multi-
channel playbacks in the section below.
As default, ALSA driver assigns the first PCM device (i.e. hw:0,0 for
card#0) for front and 4/6ch playbacks, while the second PCM device
(hw:0,1) is assigned to the second DAC for rear playback.
There are slight difference between two DACs.
- The first DAC supports U8 and S16LE formats, while the second DAC
supports only S16LE.
- The second DAC supports only two channel stereo.
Please note that the CM8x38 DAC doesn't support continuous playback
rate but only fixed rates: 5512, 8000, 11025, 16000, 22050, 32000,
44100 and 48000 Hz.
The rear output can be heard only when "Four Channel Mode" switch is
disabled. Otherwise no signal will be routed to the rear speakers.
As default it's turned on.
*** WARNING ***
When "Four Channel Mode" switch is off, the output from rear speakers
will be FULL VOLUME regardless of Master and PCM volumes.
This might damage your audio equipment. Please disconnect speakers
before your turn off this switch.
*** WARNING ***
[ Well.. I once got the output with correct volume (i.e. same with the
front one) and was so excited. It was even with "Four Channel" bit
on and "double DAC" mode. Actually I could hear separate 4 channels
from front and rear speakers! But.. after reboot, all was gone.
It's a very pity that I didn't save the register dump at that
time.. Maybe there is an unknown register to achieve this... ]
If your card has an extra output jack for the rear output, the rear
playback should be routed there as default. If not, there is a
control switch in the driver "Line-In As Rear", which you can change
via alsamixer or somewhat else. When this switch is on, line-in jack
is used as rear output.
There are two more controls regarding to the rear output.
The "Exchange DAC" switch is used to exchange front and rear playback
routes, i.e. the 2nd DAC is output from front output.
4/6 Multi-Channel Playback
--------------------------
The recent CM8738 chips support for the 4/6 multi-channel playback
function. This is useful especially for AC3 decoding.
When the multi-channel is supported, the driver name has a suffix
"-MC" such like "CMI8738-MC6". You can check this name from
/proc/asound/cards.
When the 4/6-ch output is enabled, the front DAC accepts up to 6 (or
4) channels. This is different from the dual DACs described in the
previous section. While the dual DAC supports two different rates or
formats, the 4/6-ch playback supports only the same condition for all
channels.
For using 4/6 channel playback, you need to specify the PCM channels
as you like and set the format S16LE. For example, for playback with
4 channels,
snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED);
// or mmap if you like
snd_pcm_hw_params_set_format(pcm, hw, SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_channels(pcm, hw, 4);
and use the interleaved 4 channel data.
There is a control switch, "Line-In As Bass". As you can imagine from
its name, the line-in jack is used for the bass (5th and 6th channels)
output.
Digital I/O
-----------
The CM8x38 provides the excellent SPDIF capability with very chip
price (yes, that's the reason I bought the card :)
The SPDIF playback and capture are done via the third PCM device
(hw:0,2). Usually this is assigned to the PCM device "spdif".
The available rates are 44100 and 48000 Hz.
For playback with aplay, you can run like below:
% aplay -Dhw:0,2 foo.wav
or
% aplay -Dspdif foo.wav
So far, only S16LE format is supported. Still no 24bit. Sorry, not
enough info for this.
The playback and capture over SPDIF use normal DAC and ADC,
respectively, so you cannot playback both analog and digital streams
simultaneously.
To enable SPDIF output, you need to turn on "IEC958 Output Switch"
control via mixer or alsactl. Then you'll see the red light on from
the card so you know that's working obviously :)
The SPDIF input is always enabled, so you can hear SPDIF input data
from line-out with "IEC958 In Monitor" switch at any time (see
below).
You can play via SPDIF even with the first device (hw:0,0),
but SPDIF is enabled only when the proper format (S16LE), sample rate
(441100 or 48000) and channels (2) are used. Otherwise it's turned
off. (Also don't forget to turn on "IEC958 Output Switch", too.)
Additionally there are relevant control switches:
"IEC958 Mix Analog" - Mix analog PCM playback and FM-OPL/3 streams and
output through SPDIF. This switch appears only on old chip
models (CM8738 033 and 037).
Note: without this control you can output PCM to SPDIF.
This is "mixing" of streams, so e.g. it's not for AC3 output
(see the next section).
"IEC958 In Select" - Select SPDIF input, the internal CD-in (false)
and the external input (true). This switch appears only on
the chip models 039 or later.
"IEC958 Loop" - SPDIF input data is loop back into SPDIF
output (aka bypass)
"IEC958 Copyright" - Set the copyright bit.
"IEC958 5V" - Select 0.5V (coax) or 5V (optical) interface.
On some cards this doesn't work and you need to change the
configuration with hardware dip-switch.
"IEC958 In Monitor" - SPDIF input is routed to DAC.
"IEC958 In Phase Inverse" - Set SPDIF input format as inverse.
[FIXME: this doesn't work on all chips..]
"IEC958 In Valid" - Set input validity flag detection.
Note: When "PCM Playback Switch" is on, you'll hear the digital output
stream through analog line-out.
The AC3 (RAW DIGITAL) OUTPUT
----------------------------
The driver supports raw digital (typically AC3) i/o over SPDIF. This
can be toggled via IEC958 playback control, but usually you need to
access it via alsa-lib. See alsa-lib documents for more details.
On the raw digital mode, the "PCM Playback Switch" is automatically
turned off so that non-audio data is heard from the analog line-out.
Similarly the following switches are off: "IEC958 Mix Analog" and
"IEC958 Loop". The switches are resumed after closing the SPDIF PCM
device automatically to the previous state.
ANALOG MIXER INTERFACE
----------------------
The mixer interface on CM8x38 is similar to SB16.
There are Master, PCM, Synth, CD, Line, Mic and PC Speaker playback
volumes. Synth, CD, Line and Mic have playback and capture switches,
too, as well as SB16.
In addition to the standard SB mixer, CM8x38 provides more functions.
- PCM playback switch
- PCM capture switch (to capture the data sent to DAC)
- Mic Boost switch
- Mic capture volume
- Aux playback volume/switch and capture switch
- 3D control switch
MIDI CONTROLLER
---------------
The MPU401-UART interface is enabled as default only for the first
(CMIPCI) card. You need to set module option "snd_midi_port" properly
for the 2nd (CMIPCI) card.
There is _no_ hardware wavetable function on this chip (except for
OPL3 synth below).
What's said as MIDI synth on Windows is a software synthesizer
emulation. On Linux use TiMidity or other softsynth program for
playing MIDI music.
FM OPL/3 Synth
--------------
The FM OPL/3 is also enabled as default only for the first card.
Set "snd_fm_port" module option for more cards.
The output quality of FM OPL/3 is, however, very weird.
I don't know why..
Joystick and Modem
------------------
The joystick and modem should be available by enabling the control
switch "Joystick" and "Modem" respectively. But I myself have never
tested them yet.
Debugging Information
---------------------
The registers are shown in /proc/asound/cardX/cmipci. If you have any
problem (especially unexpected behavior of mixer), please attach the
output of this proc file together with the bug report.
This diff is collapsed.
This diff is collapsed.
......@@ -22,6 +22,10 @@
*
*/
#ifdef CONFIG_PM
#include <linux/sched.h> /* wake_up() and struct semaphore */
#endif
/* Typedef's */
typedef struct timeval snd_timestamp_t;
typedef struct sndrv_interval snd_interval_t;
......
......@@ -78,12 +78,4 @@ void snd_wrapper_vfree(void *);
#include "sndmagic.h"
/*
* Temporary hack, until linux/init.h is fixed.
*/
#include <linux/init.h>
#ifndef __devexit_p
#define __devexit_p(x) x
#endif
#endif /* __SOUND_DRIVER_H */
......@@ -104,6 +104,11 @@ extern int snd_info_minor_unregister(void);
#ifdef CONFIG_PROC_FS
extern snd_info_entry_t *snd_seq_root;
#ifdef CONFIG_SND_OSSEMUL
extern snd_info_entry_t *snd_oss_root;
#else
#define snd_oss_root NULL
#endif
int snd_iprintf(snd_info_buffer_t * buffer, char *fmt,...) __attribute__ ((format (printf, 2, 3)));
int snd_info_init(void);
......@@ -138,6 +143,7 @@ void snd_remove_proc_entry(struct proc_dir_entry *parent,
#else
#define snd_seq_root NULL
#define snd_oss_root NULL
static inline int snd_iprintf(snd_info_buffer_t * buffer, char *fmt,...) { return 0; }
static inline int snd_info_init(void) { return 0; }
......
......@@ -25,6 +25,7 @@
#include <sound/asound.h>
#include <linux/poll.h>
#include <linux/bitops.h>
typedef sndrv_pcm_uframes_t snd_pcm_uframes_t;
typedef sndrv_pcm_sframes_t snd_pcm_sframes_t;
......
......@@ -22,8 +22,6 @@
*
*/
#include <linux/bitops.h>
extern int snd_pcm_hw_param_mask(snd_pcm_substream_t *pcm, snd_pcm_hw_params_t *params,
snd_pcm_hw_param_t var, const snd_mask_t *val);
extern unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params,
......
/* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0beta12"
#define CONFIG_SND_DATE " (Tue Feb 26 09:34:24 2002 UTC)"
#define CONFIG_SND_DATE " (Wed Mar 06 07:56:20 2002 UTC)"
CONFIG_SOUND_PRIME
Say 'Y' or 'M' to enable Open Sound System drivers.
CONFIG_SOUND_SND
Say 'Y' or 'M' to enable Advanced Linux Sound Architecture (ALSA) drivers.
You need to install also alsa-lib and alsa-utils packages available on
the ALSA website at <http://www.alsa-project.org>.
CONFIG_SND_SEQUENCER
Say 'Y' or 'M' to enable MIDI sequencer and router support. This feature
allows routing and enqueing MIDI events. Events can be processed at given
time.
CONFIG_SND_SEQ_DUMMY
Say 'Y' or 'M' to enable dummy sequencer client. This client is a simple
midi-through client. All normal input events are redirected to output port
immediately.
CONFIG_SND_OSSEMUL
Say 'Y' to enable OSS (Open Sound System) API emulation code.
CONFIG_SND_MIXER_OSS
Say 'Y' or 'M' to enable mixer OSS API emulation (/dev/mixer*).
CONFIG_SND_PCM_OSS
Say 'Y' or 'M' to enable digital audio (PCM) OSS API emulation (/dev/dsp*).
CONFIG_SND_SEQUENCER_OSS
Say 'Y' or 'M' to enable OSS sequencer emulation (both /dev/sequencer and
/dev/music interfaces).
CONFIG_SND_RTCTIMER
Say 'Y' or 'M' to enable RTC timer support for ALSA. ALSA code uses RTC
timer as precise timing source and maps the RTC timer to the ALSA's timer
interface. ALSA sequencer code can also use this timing source.
CONFIG_SND_VERBOSE_PRINTK
Say 'Y' to enable verbose log messages. These messages will help to
identify source file and position containing printed messages.
CONFIG_SND_DEBUG
Say 'Y' to enable ALSA debug code.
CONFIG_SND_DEBUG_MEMORY
Say 'Y' to enable debugging of memory allocation.
CONFIG_SND_DEBUG_DETECTION
Say 'Y' to enable debugging of hardware detection.
# ALSA soundcard-configuration
if [ "$CONFIG_X86_64" = "y" -a "$CONFIG_IA32_EMULATION" = "y" ]; then
dep_tristate ' Emulation for 32-bit applications' CONFIG_SND_BIT32_EMUL
fi
if [ "$CONFIG_PPC64" = "y" ]; then
dep_tristate ' Emulation for 32-bit applications' CONFIG_SND_BIT32_EMUL
fi
if [ "$CONFIG_SPARC64" = "y" ]; then
dep_tristate ' Emulation for 32-bit applications' CONFIG_SND_BIT32_EMUL
fi
dep_tristate ' Sequencer support' CONFIG_SND_SEQUENCER $CONFIG_SND
if [ "$CONFIG_SND_SEQUENCER" != "n" ]; then
dep_tristate ' Sequencer dummy client' CONFIG_SND_SEQ_DUMMY $CONFIG_SND_SEQUENCER
......
......@@ -45,6 +45,11 @@ endif
obj-$(CONFIG_SND_SEQUENCER) += snd-timer.o
subdir-$(CONFIG_SND_BIT32_EMUL) += ioctl32
ifeq ($(CONFIG_SND_BIT32_EMUL),y)
obj-y += ioctl32/_ioctl32.o
endif
# Toplevel Module Dependency
obj-$(CONFIG_SND_DUMMY) += snd-pcm.o snd-timer.o snd.o
obj-$(CONFIG_SND_VIRMIDI) += snd-rawmidi.o snd.o snd-timer.o
......@@ -72,8 +77,8 @@ obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o sn
obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
obj-$(CONFIG_SND_OPTI93X) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
obj-$(CONFIG_SND_SB8) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
obj-$(CONFIG_SND_SB16) += snd-pcm.o snd-timer.o snd.o snd-hwdep.o snd-rawmidi.o
obj-$(CONFIG_SND_SBAWE) += snd-pcm.o snd-timer.o snd.o snd-hwdep.o snd-rawmidi.o
obj-$(CONFIG_SND_SB16) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
obj-$(CONFIG_SND_SBAWE) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
obj-$(CONFIG_SND_ES968) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
obj-$(CONFIG_SND_WAVEFRONT) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
obj-$(CONFIG_SND_ALS4000) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
......@@ -85,7 +90,7 @@ obj-$(CONFIG_SND_ES1938) += snd-pcm.o snd-timer.o snd.o snd-hwdep.o snd-rawmidi.
obj-$(CONFIG_SND_ES1968) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
obj-$(CONFIG_SND_FM801) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
obj-$(CONFIG_SND_ICE1712) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
obj-$(CONFIG_SND_INTEL8X0) += snd-pcm.o snd-timer.o snd.o
obj-$(CONFIG_SND_INTEL8X0) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
obj-$(CONFIG_SND_MAESTRO3) += snd-pcm.o snd-timer.o snd.o
obj-$(CONFIG_SND_RME96) += snd-pcm.o snd-timer.o snd.o
obj-$(CONFIG_SND_SONICVIBES) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
......@@ -100,6 +105,10 @@ obj-$(CONFIG_SND_RME9652) += snd-pcm.o snd-timer.o snd.o
obj-$(CONFIG_SND_TRIDENT) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o
obj-$(CONFIG_SND_YMFPCI) += snd-pcm.o snd-timer.o snd.o snd-rawmidi.o snd-hwdep.o
obj-$(CONFIG_SND_POWERMAC) += snd-pcm.o snd-timer.o snd.o
ifeq ($(CONFIG_SND_SB16_CSP),y)
obj-$(CONFIG_SND_SB16) += snd-hwdep.o
obj-$(CONFIG_SND_SBAWE) += snd-hwdep.o
endif
include $(TOPDIR)/Rules.make
......
......@@ -24,12 +24,12 @@
#include <linux/init.h>
#include <linux/vmalloc.h>
#include <linux/time.h>
#include <linux/smp_lock.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/info.h>
#include <sound/version.h>
#include <linux/proc_fs.h>
#include <linux/smp_lock.h>
#ifdef CONFIG_DEVFS_FS
#include <linux/devfs_fs_kernel.h>
#endif
......@@ -55,7 +55,7 @@ int snd_info_check_reserved_words(const char *str)
"memdebug",
"detect",
"devices",
"oss-devices",
"oss",
"cards",
"timers",
"synth",
......@@ -124,6 +124,9 @@ int snd_iprintf(snd_info_buffer_t * buffer, char *fmt,...)
struct proc_dir_entry *snd_proc_root = NULL;
struct proc_dir_entry *snd_proc_dev = NULL;
snd_info_entry_t *snd_seq_root = NULL;
#ifdef CONFIG_SND_OSSEMUL
snd_info_entry_t *snd_oss_root = NULL;
#endif
#ifdef LINUX_2_2
static void snd_info_fill_inode(struct inode *inode, int fill)
......@@ -163,11 +166,13 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
{
snd_info_private_data_t *data;
struct snd_info_entry *entry;
int ret = -EINVAL;
loff_t ret;
data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
entry = data->entry;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 3)
lock_kernel();
#endif
switch (entry->content) {
case SNDRV_INFO_CONTENT_TEXT:
switch (orig) {
......@@ -181,6 +186,7 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
goto out;
case 2: /* SEEK_END */
default:
ret = -EINVAL;
goto out;
}
break;
......@@ -195,7 +201,9 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
}
ret = -ENXIO;
out:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 3)
unlock_kernel();
#endif
return ret;
}
......@@ -623,6 +631,19 @@ int __init snd_info_init(void)
if (p == NULL)
return -ENOMEM;
snd_proc_dev = p;
#ifdef CONFIG_SND_OSSEMUL
{
snd_info_entry_t *entry;
if ((entry = snd_info_create_module_entry(THIS_MODULE, "oss", NULL)) == NULL)
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM;
}
snd_oss_root = entry;
}
#endif
#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
{
snd_info_entry_t *entry;
......@@ -663,6 +684,10 @@ int __exit snd_info_done(void)
#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
if (snd_seq_root)
snd_info_unregister(snd_seq_root);
#endif
#ifdef CONFIG_SND_OSSEMUL
if (snd_oss_root)
snd_info_unregister(snd_oss_root);
#endif
snd_remove_proc_entry(snd_proc_root, snd_proc_dev);
snd_remove_proc_entry(&proc_root, snd_proc_root);
......
......@@ -114,7 +114,7 @@ int snd_info_minor_register(void)
snd_info_entry_t *entry;
memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings));
if ((entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", NULL)) != NULL) {
if ((entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", snd_oss_root)) != NULL) {
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->c.text.read_size = 2048;
entry->c.text.read = snd_sndstat_proc_read;
......
#
# Makefile for ALSA
# Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
#
O_TARGET := _ioctl32.o
list-multi := snd-ioctl32.o
snd-ioctl32-objs := ioctl32.o pcm32.o rawmidi32.o timer32.o hwdep32.o
obj-$(CONFIG_SND_BIT32_EMUL) += snd-ioctl32.o
include $(TOPDIR)/Rules.make
snd-ioctl32.o: $(snd-ioctl32-objs)
$(LD) $(LD_RFLAG) -r -o $@ $(snd-ioctl32-objs)
/*
* 32bit -> 64bit ioctl wrapper for timer API
* 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
*
*/
#define __NO_VERSION__
#include <sound/driver.h>
#include <linux/time.h>
#include <sound/core.h>
#include <sound/timer.h>
#include <asm/uaccess.h>
#include "ioctl32.h"
#define AP(x) snd_ioctl32_##x
struct ioctl32_mapper hwdep_mappers[] = {
{ SNDRV_HWDEP_IOCTL_PVERSION, NULL },
{ SNDRV_HWDEP_IOCTL_INFO, NULL },
{ SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE, NULL },
{ SNDRV_CTL_IOCTL_HWDEP_INFO, NULL },
{ 0 },
};
/*
* 32bit -> 64bit ioctl wrapper for control API
* 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
*
*/
#define __NO_VERSION__
#include <sound/driver.h>
#include <linux/smp_lock.h>
#include <linux/time.h>
#include <sound/core.h>
#include <sound/control.h>
#include <asm/uaccess.h>
#include "ioctl32.h"
/*
* register/unregister mappers
* exported for other modules
*/
int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *));
int unregister_ioctl32_conversion(unsigned int cmd);
int snd_ioctl32_register(struct ioctl32_mapper *mappers)
{
int err;
struct ioctl32_mapper *m;
lock_kernel();
for (m = mappers; m->cmd; m++) {
err = register_ioctl32_conversion(m->cmd, m->handler);
if (err < 0) {
unlock_kernel();
return err;
}
m->registered++;
}
return 0;
}
void snd_ioctl32_unregister(struct ioctl32_mapper *mappers)
{
struct ioctl32_mapper *m;
lock_kernel();
for (m = mappers; m->cmd; m++) {
if (m->registered) {
unregister_ioctl32_conversion(m->cmd);
m->registered = 0;
}
}
unlock_kernel();
}
/*
* Controls
*/
struct sndrv_ctl_elem_list32 {
u32 offset;
u32 space;
u32 used;
u32 count;
u32 pids;
unsigned char reserved[50];
};
#define CVT_sndrv_ctl_elem_list()\
{\
COPY(offset);\
COPY(space);\
COPY(used);\
COPY(count);\
CPTR(pids);\
}
DEFINE_ALSA_IOCTL(ctl_elem_list);
/*
* control element info
* it uses union, so the things are not easy..
*/
struct sndrv_ctl_elem_info32 {
struct sndrv_ctl_elem_id id; // the size of struct is same
s32 type;
u32 access;
u32 count;
s32 owner;
union {
struct {
s32 min;
s32 max;
s32 step;
} integer;
struct {
u32 items;
u32 item;
char name[64];
} enumerated;
unsigned char reserved[128];
} value;
unsigned char reserved[64];
};
static int snd_ioctl32_ctl_elem_info(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file)
{
struct sndrv_ctl_elem_info data;
struct sndrv_ctl_elem_info32 data32;
int err;
if (copy_from_user(&data32, (void*)arg, sizeof(data32)))
return -EFAULT;
memset(&data, 0, sizeof(data));
data.id = data32.id;
err = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, (unsigned long)&data);
if (err < 0)
return err;
/* restore info to 32bit */
data32.type = data.type;
data32.access = data.access;
data32.count = data.count;
data32.owner = data.owner;
switch (data.type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
case SNDRV_CTL_ELEM_TYPE_INTEGER:
data32.value.integer.min = data.value.integer.min;
data32.value.integer.max = data.value.integer.min;
data32.value.integer.step = data.value.integer.step;
break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
data32.value.enumerated.items = data.value.enumerated.items;
data32.value.enumerated.item = data.value.enumerated.item;
memcpy(data32.value.enumerated.name, data.value.enumerated.name,
sizeof(data.value.enumerated.name));
break;
default:
break;
}
if (copy_to_user((void*)arg, &data32, sizeof(data32)))
return -EFAULT;
return err;
}
struct sndrv_ctl_elem_value32 {
struct sndrv_ctl_elem_id id;
unsigned int indirect: 1;
union {
union {
s32 value[128];
u32 value_ptr;
} integer;
union {
u32 item[128];
u32 item_ptr;
} enumerated;
union {
unsigned char data[512];
u32 data_ptr;
} bytes;
struct sndrv_aes_iec958 iec958;
} value;
unsigned char reserved[128];
};
/* hmm, it's so hard to retrieve the value type from the control id.. */
static int get_ctl_type(struct file *file, snd_ctl_elem_id_t *id)
{
snd_ctl_file_t *ctl;
snd_kcontrol_t *kctl;
snd_ctl_elem_info_t info;
int err;
ctl = snd_magic_cast(snd_ctl_file_t, file->private_data, return -ENXIO);
read_lock(&ctl->card->control_rwlock);
kctl = snd_ctl_find_id(ctl->card, id);
if (! kctl) {
read_unlock(&ctl->card->control_rwlock);
return -ENXIO;
}
info.id = *id;
err = kctl->info(kctl, &info);
if (err >= 0)
err = info.type;
read_unlock(&ctl->card->control_rwlock);
return err;
}
static int snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file)
{
// too big?
struct sndrv_ctl_elem_value data;
struct sndrv_ctl_elem_value32 data32;
int err, i;
int type;
/* 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) {
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];
break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
for (i = 0; i < 128; 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));
break;
case SNDRV_CTL_ELEM_TYPE_IEC958:
data.value.iec958 = data32.value.iec958;
break;
default:
break;
}
}
err = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, (unsigned long)&data);
if (err < 0)
return err;
/* restore info to 32bit */
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];
break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
for (i = 0; i < 128; 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));
break;
case SNDRV_CTL_ELEM_TYPE_IEC958:
data.value.iec958 = data32.value.iec958;
break;
default:
break;
}
}
if (copy_to_user((void*)arg, &data32, sizeof(data32)))
return -EFAULT;
return err;
}
/*
*/
#define AP(x) snd_ioctl32_##x
static struct ioctl32_mapper control_mappers[] = {
/* controls (without rawmidi, hwdep, timer releated ones) */
{ SNDRV_CTL_IOCTL_PVERSION, NULL },
{ SNDRV_CTL_IOCTL_CARD_INFO , NULL },
{ SNDRV_CTL_IOCTL_ELEM_LIST, AP(ctl_elem_list) },
{ SNDRV_CTL_IOCTL_ELEM_INFO, AP(ctl_elem_info) },
{ SNDRV_CTL_IOCTL_ELEM_READ, AP(ctl_elem_value) },
{ SNDRV_CTL_IOCTL_ELEM_WRITE, AP(ctl_elem_value) },
{ SNDRV_CTL_IOCTL_ELEM_LOCK, NULL },
{ SNDRV_CTL_IOCTL_ELEM_UNLOCK, NULL },
{ SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS, NULL },
{ SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE, NULL },
{ SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE, NULL },
{ SNDRV_CTL_IOCTL_PCM_INFO, NULL },
{ SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE, NULL },
{ SNDRV_CTL_IOCTL_POWER, NULL },
{ SNDRV_CTL_IOCTL_POWER_STATE, NULL },
{ 0 }
};
/*
*/
extern struct ioctl32_mapper pcm_mappers[];
extern struct ioctl32_mapper rawmidi_mappers[];
extern struct ioctl32_mapper timer_mappers[];
extern struct ioctl32_mapper hwdep_mappers[];
static void snd_ioctl32_done(void)
{
snd_ioctl32_unregister(hwdep_mappers);
snd_ioctl32_unregister(timer_mappers);
snd_ioctl32_unregister(rawmidi_mappers);
snd_ioctl32_unregister(pcm_mappers);
snd_ioctl32_unregister(control_mappers);
}
static int __init snd_ioctl32_init(void)
{
int err;
err = snd_ioctl32_register(control_mappers);
if (err < 0)
return err;
err = snd_ioctl32_register(pcm_mappers);
if (err < 0) {
snd_ioctl32_done();
return err;
}
err = snd_ioctl32_register(rawmidi_mappers);
if (err < 0) {
snd_ioctl32_done();
return err;
}
err = snd_ioctl32_register(timer_mappers);
if (err < 0) {
snd_ioctl32_done();
return err;
}
err = snd_ioctl32_register(hwdep_mappers);
if (err < 0) {
snd_ioctl32_done();
return err;
}
}
module_init(snd_ioctl32_init)
module_exit(snd_ioctl32_done)
/*
* 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 A(x)
* macro to a valid 64-bit pointer which is accessible via copy_from/to_user.
*
*/
#ifndef __ALSA_IOCTL32_H
#define __ALSA_IOCTL32_H
#define TO_PTR(x) A(x)
#define COPY(x) (dst->x = src->x)
#define CPTR(x) (dst->x = (typeof(dst->x))A(src->x))
#define convert_from_32(type, dstp, srcp)\
{\
struct sndrv_##type *dst = dstp;\
struct sndrv_##type##32 *src = srcp;\
CVT_##sndrv_##type();\
}
#define convert_to_32(type, dstp, srcp)\
{\
struct sndrv_##type *src = srcp;\
struct sndrv_##type##32 *dst = dstp;\
CVT_##sndrv_##type();\
}
#define DEFINE_ALSA_IOCTL(type) \
static int snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file)\
{\
struct sndrv_##type##32 data32;\
struct sndrv_##type data;\
int err;\
if (copy_from_user(&data32, (void*)arg, sizeof(data32)))\
return -EFAULT;\
memset(&data, 0, sizeof(data));\
convert_from_32(type, &data, &data32);\
err = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, (unsigned long)&data);\
if (err < 0)\
return err;\
if (cmd & (_IOC_READ << _IOC_DIRSHIFT)) {\
convert_to_32(type, &data32, &data);\
if (copy_to_user((void*)arg, &data32, sizeof(data32)))\
return -EFAULT;\
}\
return err;\
}
struct ioctl32_mapper {
unsigned int cmd;
int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
int registered;
};
int snd_ioctl32_register(struct ioctl32_mapper *mappers);
void snd_ioctl32_unregister(struct ioctl32_mapper *mappers);
#endif /* __ALSA_IOCTL32_H */
/*
* 32bit -> 64bit ioctl wrapper for PCM API
* 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
*
*/
#define __NO_VERSION__
#include <sound/driver.h>
#include <linux/time.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include "ioctl32.h"
/* wrapper for sndrv_pcm_[us]frames */
struct sndrv_pcm_sframes_str {
sndrv_pcm_sframes_t val;
};
struct sndrv_pcm_sframes_str32 {
s32 val;
};
struct sndrv_pcm_uframes_str {
sndrv_pcm_uframes_t val;
};
struct sndrv_pcm_uframes_str32 {
u32 val;
};
#define CVT_sndrv_pcm_sframes_str() { COPY(val); }
#define CVT_sndrv_pcm_uframes_str() { COPY(val); }
struct sndrv_interval32 {
u32 min, max;
unsigned int openmin:1,
openmax:1,
integer:1,
empty:1;
};
struct sndrv_pcm_hw_params32 {
u32 flags;
u32 masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
struct sndrv_interval32 intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
u32 rmask;
u32 cmask;
u32 info;
u32 msbits;
u32 rate_num;
u32 rate_den;
u32 fifo_size;
unsigned char reserved[64];
};
#define numberof(array) (sizeof(array)/sizeof(array[0]))
#define CVT_sndrv_pcm_hw_params()\
{\
int i;\
COPY(flags);\
for (i = 0; i < numberof(dst->masks); i++)\
COPY(masks[i]);\
for (i = 0; i < numberof(dst->intervals); i++) {\
COPY(intervals[i].min);\
COPY(intervals[i].max);\
COPY(intervals[i].openmin);\
COPY(intervals[i].openmax);\
COPY(intervals[i].integer);\
COPY(intervals[i].empty);\
}\
COPY(rmask);\
COPY(cmask);\
COPY(info);\
COPY(msbits);\
COPY(rate_num);\
COPY(rate_den);\
COPY(fifo_size);\
}
struct sndrv_pcm_sw_params32 {
s32 tstamp_mode;
u32 period_step;
u32 sleep_min;
u32 avail_min;
u32 xfer_align;
u32 start_threshold;
u32 stop_threshold;
u32 silence_threshold;
u32 silence_size;
u32 boundary;
unsigned char reserved[64];
};
#define CVT_sndrv_pcm_sw_params()\
{\
COPY(tstamp_mode);\
COPY(period_step);\
COPY(sleep_min);\
COPY(avail_min);\
COPY(xfer_align);\
COPY(start_threshold);\
COPY(stop_threshold);\
COPY(silence_threshold);\
COPY(silence_size);\
COPY(boundary);\
}
struct sndrv_pcm_channel_info32 {
u32 channel;
u32 offset;
u32 first;
u32 step;
};
#define CVT_sndrv_pcm_channel_info()\
{\
COPY(channel);\
COPY(offset);\
COPY(first);\
COPY(step);\
}
struct timeval32 {
s32 tv_sec;
s32 tv_usec;
};
struct sndrv_pcm_status32 {
s32 state;
struct timeval32 trigger_tstamp;
struct timeval32 tstamp;
u32 appl_ptr;
u32 hw_ptr;
s32 delay;
u32 avail;
u32 avail_max;
u32 overrange;
s32 suspended_state;
unsigned char reserved[60];
};
#define CVT_sndrv_pcm_status()\
{\
COPY(state);\
COPY(trigger_tstamp.tv_sec);\
COPY(trigger_tstamp.tv_usec);\
COPY(tstamp.tv_sec);\
COPY(tstamp.tv_usec);\
COPY(appl_ptr);\
COPY(hw_ptr);\
COPY(delay);\
COPY(avail);\
COPY(avail_max);\
COPY(overrange);\
COPY(suspended_state);\
}
struct sndrv_xferi32 {
s32 result;
u32 buf;
u32 frames;
};
#define CVT_sndrv_xferi()\
{\
COPY(result);\
CPTR(buf);\
COPY(frames);\
}
DEFINE_ALSA_IOCTL(pcm_uframes_str);
DEFINE_ALSA_IOCTL(pcm_sframes_str);
DEFINE_ALSA_IOCTL(pcm_hw_params);
DEFINE_ALSA_IOCTL(pcm_sw_params);
DEFINE_ALSA_IOCTL(pcm_channel_info);
DEFINE_ALSA_IOCTL(pcm_status);
DEFINE_ALSA_IOCTL(xferi);
/* snd_xfern needs remapping of bufs */
struct sndrv_xfern32 {
s32 result;
u32 bufs; /* this is void **; */
u32 frames;
};
/*
* xfern ioctl nees to copy (up to) 128 pointers on stack.
* although we may pass the copied pointers through f_op->ioctl, but the ioctl
* handler there expands again the same 128 pointers on stack, so it is better
* to handle the function (calling pcm_readv/writev) directly in this handler.
*/
static int snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file)
{
snd_pcm_file_t *pcm_file;
snd_pcm_substream_t *substream;
struct sndrv_xfern32 data32, *srcptr = (struct sndrv_xfern32*)arg;
void *bufs[128];
int err = 0, ch, i;
u32 *bufptr;
/* FIXME: need to check whether fop->ioctl is sane */
pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
substream = pcm_file->substream;
snd_assert(substream != NULL && substream->runtime, return -ENXIO);
/* check validty of the command */
switch (cmd) {
case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
return -EINVAL;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
case SNDRV_PCM_IOCTL_READN_FRAMES:
if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
return -EINVAL;
break;
}
if ((ch = substream->runtime->channels) > 128)
return -EINVAL;
if (get_user(data32.frames, &srcptr->frames))
return -EFAULT;
__get_user(data32.bufs, &srcptr->bufs);
bufptr = (u32*)TO_PTR(data32.bufs);
for (i = 0; i < ch; i++) {
u32 ptr;
if (get_user(ptr, bufptr))
return -EFAULT;
bufs[ch] = (void*)TO_PTR(ptr);
bufptr++;
}
switch (cmd) {
case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
err = snd_pcm_lib_writev(substream, bufs, data32.frames);
break;
case SNDRV_PCM_IOCTL_READN_FRAMES:
err = snd_pcm_lib_readv(substream, bufs, data32.frames);
break;
}
if (err < 0)
return err;
if (put_user(err, &srcptr->result))
return -EFAULT;
return err < 0 ? err : 0;
}
#define AP(x) snd_ioctl32_##x
struct ioctl32_mapper pcm_mappers[] = {
{ SNDRV_PCM_IOCTL_PVERSION, NULL },
{ SNDRV_PCM_IOCTL_INFO, NULL },
{ SNDRV_PCM_IOCTL_HW_REFINE, AP(pcm_hw_params) },
{ SNDRV_PCM_IOCTL_HW_PARAMS, AP(pcm_hw_params) },
{ SNDRV_PCM_IOCTL_HW_FREE, NULL },
{ SNDRV_PCM_IOCTL_SW_PARAMS, AP(pcm_sw_params) },
{ SNDRV_PCM_IOCTL_STATUS, AP(pcm_status) },
{ SNDRV_PCM_IOCTL_DELAY, AP(pcm_sframes_str) },
{ SNDRV_PCM_IOCTL_CHANNEL_INFO, AP(pcm_channel_info) },
{ SNDRV_PCM_IOCTL_PREPARE, NULL },
{ SNDRV_PCM_IOCTL_RESET, NULL },
{ SNDRV_PCM_IOCTL_START, NULL },
{ SNDRV_PCM_IOCTL_DROP, NULL },
{ SNDRV_PCM_IOCTL_DRAIN, NULL },
{ SNDRV_PCM_IOCTL_PAUSE, NULL },
{ SNDRV_PCM_IOCTL_REWIND, AP(pcm_uframes_str) },
{ SNDRV_PCM_IOCTL_RESUME, NULL },
{ SNDRV_PCM_IOCTL_XRUN, NULL },
{ SNDRV_PCM_IOCTL_WRITEI_FRAMES, AP(xferi) },
{ SNDRV_PCM_IOCTL_READI_FRAMES, AP(xferi) },
{ SNDRV_PCM_IOCTL_WRITEN_FRAMES, AP(xfern) },
{ SNDRV_PCM_IOCTL_READN_FRAMES, AP(xfern) },
{ SNDRV_PCM_IOCTL_LINK, NULL },
{ SNDRV_PCM_IOCTL_UNLINK, NULL },
{ SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE, NULL },
{ SNDRV_CTL_IOCTL_PCM_INFO, NULL },
{ SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE, NULL },
{ 0 },
};
/*
* 32bit -> 64bit ioctl wrapper for raw MIDI API
* 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
*
*/
#define __NO_VERSION__
#include <sound/driver.h>
#include <linux/time.h>
#include <sound/core.h>
#include <sound/rawmidi.h>
#include <asm/uaccess.h>
#include "ioctl32.h"
struct sndrv_rawmidi_params32 {
s32 stream;
u32 buffer_size;
u32 avail_min;
unsigned int no_active_sensing: 1;
unsigned char reserved[16];
};
#define CVT_sndrv_rawmidi_params()\
{\
COPY(stream);\
COPY(buffer_size);\
COPY(avail_min);\
COPY(no_active_sensing);\
}
struct timeval32 {
s32 tv_sec;
s32 tv_usec;
};
struct sndrv_rawmidi_status32 {
s32 stream;
struct timeval32 tstamp;
u32 avail;
u32 xruns;
unsigned char reserved[16];
};
#define CVT_sndrv_rawmidi_status()\
{\
COPY(stream);\
COPY(tstamp.tv_sec);\
COPY(tstamp.tv_usec);\
COPY(avail);\
COPY(xruns);\
}
DEFINE_ALSA_IOCTL(rawmidi_params);
DEFINE_ALSA_IOCTL(rawmidi_status);
#define AP(x) snd_ioctl32_##x
struct ioctl32_mapper rawmidi_mappers[] = {
{ SNDRV_RAWMIDI_IOCTL_PVERSION, NULL },
{ SNDRV_RAWMIDI_IOCTL_INFO, NULL },
{ SNDRV_RAWMIDI_IOCTL_PARAMS, AP(rawmidi_params) },
{ SNDRV_RAWMIDI_IOCTL_STATUS, AP(rawmidi_status) },
{ SNDRV_RAWMIDI_IOCTL_DROP, NULL },
{ SNDRV_RAWMIDI_IOCTL_DRAIN, NULL },
{ SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE, NULL },
{ SNDRV_CTL_IOCTL_RAWMIDI_INFO, NULL },
{ SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE, NULL },
{ 0 },
};
/*
* 32bit -> 64bit ioctl wrapper for timer API
* 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
*
*/
#define __NO_VERSION__
#include <sound/driver.h>
#include <linux/time.h>
#include <sound/core.h>
#include <sound/timer.h>
#include <asm/uaccess.h>
#include "ioctl32.h"
struct sndrv_timer_info32 {
u32 flags;
s32 card;
unsigned char id[64];
unsigned char name[80];
u32 ticks;
u32 resolution;
unsigned char reserved[64];
};
#define CVT_sndrv_timer_info()\
{\
COPY(flags);\
COPY(card);\
memcpy(dst->id, src->id, sizeof(src->id));\
memcpy(dst->name, src->name, sizeof(src->name));\
COPY(ticks);\
COPY(resolution);\
}
struct timeval32 {
s32 tv_sec;
s32 tv_usec;
};
struct sndrv_timer_status32 {
struct timeval32 tstamp;
u32 resolution;
u32 lost;
u32 overrun;
u32 queue;
unsigned char reserved[64];
};
#define CVT_sndrv_timer_status()\
{\
COPY(tstamp.tv_sec);\
COPY(tstamp.tv_usec);\
COPY(resolution);\
COPY(lost);\
COPY(overrun);\
COPY(queue);\
}
DEFINE_ALSA_IOCTL(timer_info);
DEFINE_ALSA_IOCTL(timer_status);
/*
*/
#define AP(x) snd_ioctl32_##x
struct ioctl32_mapper timer_mappers[] = {
{ SNDRV_TIMER_IOCTL_PVERSION, NULL },
{ SNDRV_TIMER_IOCTL_NEXT_DEVICE, NULL },
{ SNDRV_TIMER_IOCTL_SELECT, NULL },
{ SNDRV_TIMER_IOCTL_INFO, AP(timer_info) },
{ SNDRV_TIMER_IOCTL_PARAMS, NULL },
{ SNDRV_TIMER_IOCTL_STATUS, AP(timer_status) },
{ SNDRV_TIMER_IOCTL_START, NULL },
{ SNDRV_TIMER_IOCTL_STOP, NULL },
{ SNDRV_TIMER_IOCTL_CONTINUE, NULL },
{ 0 },
};
......@@ -516,7 +516,6 @@ static int snd_pcm_oss_make_ready(snd_pcm_substream_t *substream)
snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel)
{
snd_pcm_runtime_t *runtime = substream->runtime;
mm_segment_t fs;
int ret;
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
......@@ -525,11 +524,14 @@ snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char
if (ret < 0)
break;
}
if (in_kernel)
if (in_kernel) {
mm_segment_t fs;
fs = snd_enter_user();
ret = snd_pcm_lib_write(substream, ptr, frames);
if (in_kernel)
ret = snd_pcm_lib_write(substream, ptr, frames);
snd_leave_user(fs);
} else {
ret = snd_pcm_lib_write(substream, ptr, frames);
}
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
/* test, if we can't store new data, because the stream */
......@@ -543,7 +545,6 @@ snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char
snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel)
{
snd_pcm_runtime_t *runtime = substream->runtime;
mm_segment_t fs;
int ret;
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
......@@ -556,11 +557,15 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, s
if (ret < 0)
break;
}
if (in_kernel)
fs = snd_enter_user();
ret = snd_pcm_lib_read(substream, ptr, frames);
if (in_kernel)
if (in_kernel) {
mm_segment_t fs;
fs = snd_enter_user();
ret = snd_pcm_lib_read(substream, ptr, frames);
snd_leave_user(fs);
} else {
ret = snd_pcm_lib_read(substream, ptr, frames);
}
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
}
......@@ -570,7 +575,6 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, s
snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
{
snd_pcm_runtime_t *runtime = substream->runtime;
mm_segment_t fs;
int ret;
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
......@@ -579,13 +583,17 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **buf
if (ret < 0)
break;
}
if (in_kernel)
if (in_kernel) {
mm_segment_t fs;
fs = snd_enter_user();
ret = snd_pcm_lib_writev(substream, bufs, frames);
if (in_kernel)
ret = snd_pcm_lib_writev(substream, bufs, frames);
snd_leave_user(fs);
} else {
ret = snd_pcm_lib_writev(substream, bufs, frames);
}
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
/* test, if we can't store new data, because the stream */
/* has not been started */
if (runtime->status->state == SNDRV_PCM_STATE_PREPARED)
......@@ -597,7 +605,6 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **buf
snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
{
snd_pcm_runtime_t *runtime = substream->runtime;
mm_segment_t fs;
int ret;
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
......@@ -610,11 +617,14 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs
if (ret < 0)
break;
}
if (in_kernel)
if (in_kernel) {
mm_segment_t fs;
fs = snd_enter_user();
ret = snd_pcm_lib_readv(substream, bufs, frames);
if (in_kernel)
ret = snd_pcm_lib_readv(substream, bufs, frames);
snd_leave_user(fs);
} else {
ret = snd_pcm_lib_readv(substream, bufs, frames);
}
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
}
......
......@@ -18,19 +18,12 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
*================================================================
* For enabling this timer, apply the patch file to your kernel.
* The configure script checks the patch automatically.
* The patches, rtc-xxx.dif, are found under utils/patches, where
* xxx is the kernel version.
*================================================================
*
*/
#include <sound/driver.h>
#include <linux/init.h>
#include <linux/time.h>
#include <linux/interrupt.h>
#include <sound/core.h>
#include <sound/timer.h>
#include <sound/info.h>
......@@ -59,7 +52,7 @@ static int rtctimer_stop(snd_timer_t *t);
/*
* The harware depenant description for this timer.
* The hardware dependent description for this timer.
*/
static struct _snd_timer_hardware rtc_hw = {
flags: SNDRV_TIMER_HW_FIRST|SNDRV_TIMER_HW_AUTO,
......@@ -72,7 +65,7 @@ static struct _snd_timer_hardware rtc_hw = {
int rtctimer_freq = RTC_FREQ; /* frequency */
static snd_timer_t *rtctimer;
static volatile int rtc_inc = 0;
static atomic_t rtc_inc = ATOMIC_INIT(0);
static rtc_task_t rtc_task;
/* tasklet */
......@@ -83,6 +76,10 @@ static struct tasklet_struct rtc_tq;
static int
rtctimer_open(snd_timer_t *t)
{
err = rtc_register(&rtc_task);
if (err < 0)
return err;
t->private_data = &rtc_task;
MOD_INC_USE_COUNT;
return 0;
}
......@@ -90,6 +87,11 @@ rtctimer_open(snd_timer_t *t)
static int
rtctimer_close(snd_timer_t *t)
{
rtc_task_t *rtc = t->private_data;
if (rtc) {
rtc_unregister(rtc);
t->private_data = NULL;
}
MOD_DEC_USE_COUNT;
return 0;
}
......@@ -101,7 +103,7 @@ rtctimer_start(snd_timer_t *timer)
snd_assert(rtc != NULL, return -EINVAL);
rtc_control(rtc, RTC_IRQP_SET, rtctimer_freq);
rtc_control(rtc, RTC_PIE_ON, 0);
rtc_inc = 0;
atomic_set(&rtc_inc, 0);
return 0;
}
......@@ -119,12 +121,15 @@ rtctimer_stop(snd_timer_t *timer)
*/
static void rtctimer_interrupt(void *private_data)
{
rtc_inc++;
atomic_inc(&rtc_inc);
#ifdef USE_TASKLET
tasklet_hi_schedule(&rtc_tq);
#else
snd_timer_interrupt((snd_timer_t*)private_data, rtc_inc);
rtc_inc = 0;
{
int ticks = atomic_read(&rtc_inc);
snd_timer_interrupt((snd_timer_t*)private_data, ticks);
atomic_sub(ticks, &rtc_inc);
}
#endif /* USE_TASKLET */
}
......@@ -132,20 +137,16 @@ static void rtctimer_interrupt(void *private_data)
static void rtctimer_interrupt2(unsigned long private_data)
{
snd_timer_t *timer = (snd_timer_t *)private_data;
int ticks;
snd_assert(timer != NULL, return);
do {
snd_timer_interrupt(timer, 1);
} while (--rtc_inc > 0);
ticks = atomic_read(&rtc_inc);
snd_timer_interrupt(timer, ticks);
} while (!atomic_sub_and_test(ticks, &rtc_inc));
}
#endif /* USE_TASKLET */
static void rtctimer_private_free(snd_timer_t *timer)
{
rtc_task_t *rtc = timer->private_data;
if (rtc)
rtc_unregister(rtc);
}
/*
* ENTRY functions
......@@ -179,23 +180,16 @@ static int __init rtctimer_init(void)
timer->hw = rtc_hw;
timer->hw.resolution = NANO_SEC / rtctimer_freq;
/* register RTC callback */
/* set up RTC callback */
rtc_task.func = rtctimer_interrupt;
rtc_task.private_data = timer;
err = rtc_register(&rtc_task);
if (err < 0) {
snd_timer_global_free(timer);
return err;
}
timer->private_data = &rtc_task;
timer->private_free = rtctimer_private_free;
err = snd_timer_global_register(timer);
if (err < 0) {
snd_timer_global_free(timer);
return err;
}
rtctimer = timer;
rtctimer = timer; /* remember this */
return 0;
}
......@@ -210,7 +204,7 @@ static void __exit rtctimer_exit(void)
/*
* exported stuffs
* exported stuff
*/
module_init(rtctimer_init)
module_exit(rtctimer_exit)
......
......@@ -72,6 +72,7 @@ obj-$(CONFIG_SND_ES1938) += snd-seq-device.o snd-seq-midi-emul.o snd-seq.o snd-s
obj-$(CONFIG_SND_ES1968) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o
obj-$(CONFIG_SND_FM801) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
obj-$(CONFIG_SND_ICE1712) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o
obj-$(CONFIG_SND_INTEL8X0) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o
obj-$(CONFIG_SND_SONICVIBES) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
obj-$(CONFIG_SND_VIA686) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o
obj-$(CONFIG_SND_ALI5451) += snd-seq-midi.o snd-seq.o snd-seq-device.o snd-seq-midi-event.o
......
......@@ -68,8 +68,8 @@ static struct status_event_list_t {
event_decode_t decode;
} status_event[] = {
/* 0x80 - 0xf0 */
{SNDRV_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode},
{SNDRV_SEQ_EVENT_NOTEON, 2, note_event, note_decode},
{SNDRV_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode},
{SNDRV_SEQ_EVENT_NOTEON, 2, note_event, note_decode},
{SNDRV_SEQ_EVENT_KEYPRESS, 2, note_event, note_decode},
{SNDRV_SEQ_EVENT_CONTROLLER, 2, two_param_ctrl_event, two_param_decode},
{SNDRV_SEQ_EVENT_PGMCHANGE, 1, one_param_ctrl_event, one_param_decode},
......@@ -78,9 +78,9 @@ static struct status_event_list_t {
{SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf0 */
/* 0xf0 - 0xff */
{SNDRV_SEQ_EVENT_SYSEX, 1, NULL, NULL}, /* sysex: 0xf0 */
{SNDRV_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */
{SNDRV_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */
{SNDRV_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */
{SNDRV_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */
{SNDRV_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */
{SNDRV_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */
{SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf4 */
{SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf5 */
{SNDRV_SEQ_EVENT_TUNE_REQUEST, 0, NULL, NULL}, /* 0xf6 */
......@@ -92,7 +92,7 @@ static struct status_event_list_t {
{SNDRV_SEQ_EVENT_STOP, 0, NULL, NULL}, /* 0xfc */
{SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xfd */
{SNDRV_SEQ_EVENT_SENSING, 0, NULL, NULL}, /* 0xfe */
{SNDRV_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */
{SNDRV_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */
};
static int extra_decode_ctrl14(snd_midi_event_t *dev, unsigned char *buf, int len, snd_seq_event_t *ev);
......@@ -128,6 +128,7 @@ int snd_midi_event_new(int bufsize, snd_midi_event_t **rdev)
}
}
dev->bufsize = bufsize;
dev->lastcmd = 0xff;
spin_lock_init(&dev->lock);
*rdev = dev;
return 0;
......
......@@ -233,8 +233,7 @@ static int snd_virmidi_output_open(snd_rawmidi_substream_t * substream)
}
vmidi->seq_mode = rdev->seq_mode;
vmidi->client = rdev->client;
vmidi->port = rdev->port;
snd_midi_event_init(vmidi->parser);
vmidi->port = rdev->port;
snd_virmidi_init_event(vmidi, &vmidi->event);
vmidi->rdev = rdev;
runtime->private_data = vmidi;
......
......@@ -212,7 +212,7 @@ int __init snd_minor_info_oss_init(void)
{
snd_info_entry_t *entry;
entry = snd_info_create_module_entry(THIS_MODULE, "oss-devices", NULL);
entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root);
if (entry) {
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->c.text.read_size = PAGE_SIZE;
......
CONFIG_SND_DUMMY
Say 'Y' or 'M' to include dummy driver. This driver does nothing, but
emulates various mixer controls and PCM devices.
CONFIG_SND_VIRMIDI
Say 'Y' or 'M' to include virtual MIDI driver. This driver allows to
connect applications using raw MIDI devices to sequencer.
CONFIG_SND_MTPAV
Say 'Y' or 'M' to include support for MOTU MidiTimePiece AV multiport
MIDI adapter.
CONFIG_SND_SERIAL_U16550
Say 'Y' or 'M' to include support for MIDI serial port driver. It works
with serial UARTs 16550 and better.
CONFIG_SND_MPU401
Say 'Y' or 'M' to include support for MPU401 hardware using UART access.
......@@ -37,6 +37,7 @@ obj-$(CONFIG_SND_ES1938) += snd-mpu401-uart.o
obj-$(CONFIG_SND_ES1968) += snd-mpu401-uart.o
obj-$(CONFIG_SND_FM801) += snd-mpu401-uart.o
obj-$(CONFIG_SND_ICE1712) += snd-mpu401-uart.o
obj-$(CONFIG_SND_INTEL8X0) += snd-mpu401-uart.o
obj-$(CONFIG_SND_SONICVIBES) += snd-mpu401-uart.o
obj-$(CONFIG_SND_VIA686) += snd-mpu401-uart.o
obj-$(CONFIG_SND_ALI5451) += snd-mpu401-uart.o
......
......@@ -28,6 +28,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/mpu401.h>
......
......@@ -54,6 +54,7 @@
#include <asm/io.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <sound/core.h>
#define SNDRV_GET_ID
#include <sound/initval.h>
......
......@@ -29,7 +29,7 @@ obj-$(CONFIG_SND_GUSEXTREME) += snd-opl3-lib.o
obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-opl3-lib.o
obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-opl3-lib.o
obj-$(CONFIG_SND_OPTI93X) += snd-opl3-lib.o
obj-$(CONFIG_SND_SB) += snd-opl3-lib.o
obj-$(CONFIG_SND_SB8) += snd-opl3-lib.o
obj-$(CONFIG_SND_SB16) += snd-opl3-lib.o
obj-$(CONFIG_SND_SBAWE) += snd-opl3-lib.o
obj-$(CONFIG_SND_WAVEFRONT) += snd-opl3-lib.o
......@@ -54,7 +54,7 @@ ifeq ($(subst m,y,$(CONFIG_SND_SEQUENCER)),y)
obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-opl3-synth.o
obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-opl3-synth.o
obj-$(CONFIG_SND_OPTI93X) += snd-opl3-synth.o
obj-$(CONFIG_SND_SB) += snd-opl3-synth.o
obj-$(CONFIG_SND_SB8) += snd-opl3-synth.o
obj-$(CONFIG_SND_SB16) += snd-opl3-synth.o
obj-$(CONFIG_SND_SBAWE) += snd-opl3-synth.o
obj-$(CONFIG_SND_WAVEFRONT) += snd-opl3-synth.o
......
......@@ -28,6 +28,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <sound/minors.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Hannu Savolainen 1993-1996, Rob Hooft");
......
......@@ -39,7 +39,7 @@
*
* Usage example for MS-124T, with A-B switch in A position:
* setserial /dev/ttyS0 uart none
* /sbin/modprobe snd-card-serial snd_port=0x3f8 snd_irq=4 \
* /sbin/modprobe snd-serial-u16550 snd_port=0x3f8 snd_irq=4 \
* snd_adaptor=1 snd_speed=19200
*
* - In MS-124W S/A mode, one raw MIDI substream is supported
......@@ -49,7 +49,7 @@
*
* Usage example for S/A mode:
* setserial /dev/ttyS0 uart none
* /sbin/modprobe snd-card-serial snd_port=0x3f8 snd_irq=4 \
* /sbin/modprobe snd-serial-u16550 snd_port=0x3f8 snd_irq=4 \
* snd_adaptor=2
*
* - In MS-124W M/B mode, the driver supports 16 ALSA raw MIDI
......@@ -67,7 +67,7 @@
*
* Usage example for M/B mode:
* setserial /dev/ttyS0 uart none
* /sbin/insmod snd-card-serial snd_port=0x3f8 snd_irq=4 \
* /sbin/insmod snd-serial-u16550 snd_port=0x3f8 snd_irq=4 \
* snd_adaptor=3
*
* - The MS-124W hardware's M/A mode is currently not supported.
......@@ -106,6 +106,7 @@
#include <asm/io.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/rawmidi.h>
#define SNDRV_GET_ID
......
......@@ -13,7 +13,7 @@ snd-i2c-objs := i2c.o
snd-cs8427-objs := cs8427.o
snd-tea6330t-objs := tea6330t.o
# Module Dependency
# Toplevel Module Dependency
obj-$(CONFIG_SND_INTERWAVE_STB) += snd-tea6330t.o snd-i2c.o
obj-$(CONFIG_SND_ICE1712) += snd-cs8427.o snd-i2c.o
......
CONFIG_SND_AD1816A
Say 'Y' or 'M' to include support for Analog Devices SoundPort AD1816A or
compatible sound chips.
CONFIG_SND_AD1848
Say 'Y' or 'M' to include support for AD1848 (Analog Devices) or CS4248
(Cirrus Logic - Crystal Semiconductors) chips. Please, for newer chips
from Cirrus Logic, use CS4231, CS4232 or CS4236+ driver.
CONFIG_SND_CS4231
Say 'Y' or 'M' to include support for CS4231 chips from Cirrus Logic -
Crystal Semiconductors.
CONFIG_SND_CS4232
Say 'Y' or 'M' to include support for CS4232 chips from Cirrus Logic -
Crystal Semiconductors.
CONFIG_SND_CS4236
Say 'Y' or 'M' to include support for CS4235,CS4236,CS4237B,CS4238B,CS4239
chips from Cirrus Logic - Crystal Semiconductors.
CONFIG_SND_ES968
Say 'Y' or 'M' to include support for ESS AudioDrive ES968 chip.
CONFIG_SND_ES1688
Say 'Y' or 'M' to include support for ESS AudioDrive ES688 or ES1688 chips.
CONFIG_SND_ES18XX
Say 'Y' or 'M' to include support for ESS AudioDrive ES18xx chips.
CONFIG_SND_GUSCLASSIC
Say 'Y' or 'M' to include support for Gravis UltraSound Classic soundcard.
CONFIG_SND_GUSEXTREME
Say 'Y' or 'M' to include support for Gravis UltraSound Extreme soundcard.
CONFIG_SND_GUSMAX
Say 'Y' or 'M' to include support for Gravis UltraSound MAX soundcard.
CONFIG_SND_INTERWAVE
Say 'Y' or 'M' to include support for AMD InterWave based soundcards
(Gravis UltraSound Plug & Play, STB SoundRage32, MED3210, Dynasonic Pro,
Panasonic PCA761AW).
CONFIG_SND_INTERWAVE_STB
Say 'Y' or 'M' to include support for AMD InterWave based soundcards
with TEA6330T bass and treble regulator (UltraSound 32-Pro).
CONFIG_SND_OPTI92X_AD1848
Say 'Y' or 'M' to include support for Opti92x soundcards equiped with
AD1848 codec.
CONFIG_SND_OPTI92X_CS4231
Say 'Y' or 'M' to include support for Opti92x soundcards equiped with
CS4231 codec.
CONFIG_SND_OPTI93X
Say 'Y' or 'M' to include support for Opti93x soundcards.
CONFIG_SND_SB8
Say 'Y' or 'M' to include support for Sound Blaster 1.0/2.0/Pro (8-bit)
soundcards or 100% compatible from Creative.
CONFIG_SND_SB16
Say 'Y' or 'M' to include support for Sound Blaster 16 (including
Plug and Play version).
CONFIG_SND_SBAWE
Say 'Y' or 'M' to include support for Sound Blaster AWE (including
Plug and Play version).
CONFIG_SND_SB16_CSP
Say 'Y' to include support for CSP core. This special coprocessor
can do variable tasks like various compression and decompression
algorithms.
CONFIG_SND_WAVEFRONT
Say 'Y' or 'M' to include support for Turtle Beach Maui, Tropez
and Tropez+ soundcards based on Wavefront chip.
CONFIG_SND_ALS100
Say 'Y' or 'M' to include support for Avance Logic ALS100, ALS110,
ALS120 and ALS200 soundcards.
CONFIG_SND_AZT2320
Say 'Y' or 'M' to include support for Aztech Systems AZT2320 soundcard.
CONFIG_SND_CMI8330
Say 'Y' or 'M' to include support for C-Media CMI8330 based soundcards.
CONFIG_SND_DT0197H
Say 'Y' or 'M' to include support for Diamond Technologies DT-0197H
soundcards.
CONFIG_SND_OPL3SA2
Say 'Y' or 'M' to include support for Yamaha OPL3SA2 or OPL3SA3 chips.
CONFIG_SND_SGALAXY
Say 'Y' or 'M' to include support for Aztech Sound Galaxy.
......@@ -24,6 +24,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/ad1816a.h>
......
......@@ -25,6 +25,7 @@
#include <asm/dma.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/ad1848.h>
......
......@@ -134,7 +134,7 @@ static const struct isapnp_card_id *snd_azt2320_isapnp_id[SNDRV_CARDS] __devinit
static struct isapnp_card_id snd_azt2320_pnpids[] __devinitdata = {
/* PRO16V */
ISAPNP_AZT2320('A','Z','T',0x1008,0x1008,0x2001),
/* --- */
/* Aztech Sound Galaxy 16 */
ISAPNP_AZT2320('A','Z','T',0x2320,0x0001,0x0002),
/* Packard Bell Sound III 336 AM/SP */
ISAPNP_AZT2320('A','Z','T',0x3000,0x1003,0x2001),
......
......@@ -32,6 +32,7 @@
#include <linux/pm.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/cs4231.h>
......
......@@ -25,6 +25,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/es1688.h>
#include <sound/initval.h>
......
......@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/gus.h>
#include <sound/control.h>
......
......@@ -177,7 +177,7 @@ static struct isapnp_card_id snd_opl3sa2_pnpids[] __devinitdata = {
ISAPNP_OPL3SA2('Y','M','H',0x0020,0x0021),
/* Yamaha OPL3-SA3 (integrated on Intel's Pentium II AL440LX motherboard) */
ISAPNP_OPL3SA2('Y','M','H',0x0030,0x0021),
/* ??? */
/* Yamaha OPL3-SA2 */
ISAPNP_OPL3SA2('Y','M','H',0x0800,0x0021),
/* NeoMagic MagicWave 3DX */
ISAPNP_OPL3SA2('N','M','X',0x2200,0x2210),
......
......@@ -27,12 +27,12 @@ obj-$(CONFIG_SND_DT0197H) += snd-sb16-dsp.o snd-sb-common.o
obj-$(CONFIG_SND_SB8) += snd-sb8.o snd-sb8-dsp.o snd-sb-common.o
obj-$(CONFIG_SND_SB16) += snd-sb16.o snd-sb16-dsp.o snd-sb-common.o
obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o snd-sb16-dsp.o snd-sb-common.o
obj-$(CONFIG_SND_ES968) += snd-es968.o snd-sb8-dsp.o snd-sb-common.o
obj-$(CONFIG_SND_ALS4000) += snd-sb-common.o
ifeq ($(CONFIG_SND_SB16_CSP),y)
obj-$(CONFIG_SND_SB16) += snd-sb16-csp.o
obj-$(CONFIG_SND_SBAWE) += snd-sb16-csp.o
endif
obj-$(CONFIG_SND_ES968) += snd-es968.o snd-sb8-dsp.o snd-sb-common.o
obj-$(CONFIG_SND_ALS4000) += snd-sb-common.o
ifeq ($(subst m,y,$(CONFIG_SND_SEQUENCER)),y)
obj-$(CONFIG_SND_SBAWE) += snd-emu8000-synth.o
endif
......
......@@ -25,6 +25,7 @@
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/emu8000.h>
#include <sound/emu8000_reg.h>
......
......@@ -209,11 +209,11 @@ static void snd_sb16_csp_capture_close(sb_t *chip)
#else
#define snd_sb16_csp_playback_prepare(chip, runtime) /*nop*/
#define snd_sb16_csp_capture_prepare(chip, runtime) /*nop*/
#define snd_sb16_csp_update(chip) /*nop*/
#define snd_sb16_csp_update(chip) /*nop*/
#define snd_sb16_csp_playback_open(chip, runtime) /*nop*/
#define snd_sb16_csp_playback_close(chip) /*nop*/
#define snd_sb16_csp_playback_close(chip) /*nop*/
#define snd_sb16_csp_capture_open(chip, runtime) /*nop*/
#define snd_sb16_csp_capture_close(chip) /*nop*/
#define snd_sb16_csp_capture_close(chip) /*nop*/
#endif
......
......@@ -22,6 +22,7 @@
#include <sound/driver.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/sb.h>
#include <sound/opl3.h>
......
......@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/sb.h>
#include <sound/initval.h>
......
......@@ -119,7 +119,7 @@ static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
static int dma_bits[] = {1, 2, 0, 3};
int tmp, tmp1;
unsigned int flags;
unsigned long flags;
if ((tmp = inb(port + 3)) == 0xff)
{
......
......@@ -111,30 +111,6 @@ MODULE_PARM_DESC(ramcheck_time, "how many seconds to wait for the RAM test");
MODULE_PARM(osrun_time,"i");
MODULE_PARM_DESC(osrun_time, "how many seconds to wait for the ICS2115 OS");
/*
* This sucks, hopefully it'll get standardised
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,18) && LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
#define loops_per_sec loops_per_jiffy*HZ
#elif LINUX_VERSION_CODE == KERNEL_VERSION(2,4,0) && defined(I_DIRTY_PAGES) /* linux/fs.h */
#define loops_per_sec loops_per_jiffy*HZ
#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0)
#define loops_per_sec loops_per_jiffy*HZ
#endif
#if defined(__alpha__) || defined(__powerpc__)
#ifdef __SMP__
#define LOOPS_PER_SEC (cpu_data[smp_processor_id()].loops_per_sec)
#else
#define LOOPS_PER_SEC (loops_per_sec)
#endif
#endif
#if defined(__i386__)
#define LOOPS_PER_SEC (current_cpu_data.loops_per_sec)
#endif
/* if WF_DEBUG not defined, no run-time debugging messages will
be available via the debug flag setting. Given the current
beta state of the driver, this will remain set until a future
......@@ -323,26 +299,16 @@ wavefront_wait (snd_wavefront_t *dev, int mask)
{
int i;
static int short_loop_cnt = 0;
/* Compute the loop count that lets us sleep for about the
right amount of time, cache issues, bus speeds and all
other issues being unequal but largely irrelevant.
*/
if (short_loop_cnt == 0) {
short_loop_cnt = wait_usecs *
(LOOPS_PER_SEC / 1000000);
}
/* Spin for a short period of time, because >99% of all
requests to the WaveFront can be serviced inline like this.
*/
for (i = 0; i < short_loop_cnt; i++) {
for (i = 0; i < wait_usecs; i += 5) {
if (wavefront_status (dev) & mask) {
return 1;
}
udelay(5);
}
for (i = 0; i < sleep_tries; i++) {
......@@ -1316,18 +1282,21 @@ wavefront_fetch_multisample (snd_wavefront_t *dev,
for (i = 0; i < num_samples; i++) {
char d[2];
int val;
if ((d[0] = wavefront_read (dev)) == -1) {
if ((val = wavefront_read (dev)) == -1) {
snd_printk ("upload multisample failed "
"during sample loop.\n");
return -(EIO);
}
d[0] = val;
if ((d[1] = wavefront_read (dev)) == -1) {
if ((val = wavefront_read (dev)) == -1) {
snd_printk ("upload multisample failed "
"during sample loop.\n");
return -(EIO);
}
d[1] = val;
header->hdr.ms.SampleNumber[i] =
demunge_int32 ((unsigned char *) d, 2);
......
CONFIG_SND_ALI5451
Say 'Y' or 'M' to include support for ALI PCI Audio M5451 sound core.
CONFIG_SND_CS46XX
Say 'Y' or 'M' to include support for Cirrus Logic CS4610 / CS4612 /
CS4614 / CS4615 / CS4622 / CS4624 / CS4630 / CS4280 chips.
CONFIG_SND_CS46XX_ACCEPT_VALID
Say 'Y' to allow sample resolution for mmap() transfers.
CONFIG_SND_EMU10K1
Say 'Y' or 'M' to include support for Sound Blaster PCI 512, Live!,
Audigy and E-mu APS (partially supported).
CONFIG_SND_KORG1212
Say 'Y' or 'M' to include support for Korg 1212IO.
CONFIG_SND_NM256
Say 'Y' or 'M' to include support for NeoMagic NM256AV/ZX chips.
CONFIG_SND_RME96
Say 'Y' or 'M' to include support for RME Digi96, Digi96/8 and
Digi96/8 PRO/PAD/PST.
CONFIG_SND_RME9652
Say 'Y' or 'M' to include support for RME Hammerfall (RME Digi9652 /
Digi9636) soundcards.
CONFIG_SND_TRIDENT
CONFIG_SND_YMFPCI
Say 'Y' or 'M' to include support for Yamaha PCI audio chips -
YMF724, YMF724F, YMF740, YMF740C, YMF744, YMF754.
CONFIG_SND_ALS4000
Say 'Y' or 'M' to include support for Avance Logic ALS4000.
CONFIG_SND_CMIPCI
Say 'Y' or 'M' to include support for C-Media CMI8338 and 8738 PCI
soundcards.
CONFIG_SND_ENS1370
Say 'Y' or 'M' to include support for Ensoniq AudioPCI ES1370.
CONFIG_SND_ENS1371
Say 'Y' or 'M' to include support for Ensoniq AudioPCI ES1371 and
Sound Blaster PCI 64 or 128 soundcards.
CONFIG_SND_ES1938
Say 'Y' or 'M' to include support for ESS Solo-1 (ES1938, ES1946)
soundcard.
CONFIG_SND_ES1968
Say 'Y' or 'M' to include support for ESS Maestro 1/2/2E.
CONFIG_SND_MAESTRO3
Say 'Y' or 'M' to include support for ESS Maestro 3 (Allegro) soundcard.
CONFIG_SND_FM801
Say 'Y' or 'M' to include support for ForteMedia FM801 based soundcards.
CONFIG_SND_ICE1712
Say 'Y' or 'M' to include support for ICE1712 (Envy24) based soundcards.
CONFIG_SND_INTEL8X0
Say 'Y' or 'M' to include support for Intel8x0 based soundcards.
CONFIG_SND_SONICVIBES
Say 'Y' or 'M' to include support for S3 SonicVibes based soundcards.
CONFIG_SND_VIA686
Say 'Y' or 'M' to include support for VIA VT82C686A/B South Bridge.
CONFIG_SND_VIA8233
Say 'Y' or 'M' to include support for VIA VT8233 South Bridge.
......@@ -109,7 +109,7 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
}
legacy_ctrl = 0;
legacy_ctrl2 = 0;
legacy_ctrl2 = 0x0800; /* SMOD = 01 */
if (id->device >= 0x0010) { /* YMF 744/754 */
if (snd_fm_port[dev] < 0)
......
......@@ -15,8 +15,8 @@ export-objs := util_mem.o
snd-util-mem-objs := util_mem.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_TRIDENT) += snd-util-mem.o
obj-$(CONFIG_SND_EMU10K1) += snd-util-mem.o
obj-$(CONFIG_SND_TRIDENT) += snd-util-mem.o
ifeq ($(subst m,y,$(CONFIG_SND_SEQUENCER)),y)
obj-$(CONFIG_SND_SBAWE) += snd-util-mem.o
endif
......
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