--- /dev/null
+ 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.
--- /dev/null
+
+ Sound Blaster Live mixer / default DSP code
+ ===========================================
+
+
+The EMU10K1 chips have a DSP part which can be programmed to support
+various ways of sample processing, which is described here.
+(This acticle does not deal with the overall functionality of the
+EMU10K1 chips. See the manuals section for further details.)
+
+The ALSA driver programs this portion of chip by default code
+(can be altered later) which offers the following functionality:
+
+
+1) IEC958 (S/PDIF) raw PCM
+--------------------------
+
+This PCM device (it's the 4th PCM device (index 3!) and first subdevice
+(index 0) for a given card) allows to forward 48kHz, stereo, 16-bit
+little endian streams without any modifications to the digital output
+(coaxial or optical). The universal interface allows the creation of up
+to 8 raw PCM devices operating at 48kHz, 16-bit little endian. It would
+be easy to add support for multichannel devices to the current code,
+but the conversion routines exist only for stereo (2-channel streams)
+at the time.
+
+Look to tram_poke routines in lowlevel/emu10k1/emufx.c for more details.
+
+
+2) Digital mixer controls
+-------------------------
+
+These controls are built using the DSP instructions. They offer extended
+functionality. Only the default build-in code in the ALSA driver is described
+here. Note that the controls work as attenuators: the maximum value is the
+neutral position leaving the signal unchanged. Note that if the same destination
+is mentioned in multiple controls, the signal is accumulated and can be wrapped
+(set to maximal or minimal value without checking of overflow).
+
+
+Explanation of used abbreviations:
+
+DAC - digital to analog converter
+ADC - analog to digital converter
+I2S - one-way three wire serial bus for digital sound by Philips Semiconductors
+ (this standard is used for connecting standalone DAC and ADC converters)
+LFE - low frequency effects (subwoofer signal)
+AC97 - a chip containing an analog mixer, DAC and ADC converters
+IEC958 - S/PDIF
+FX-bus - the EMU10K1 chip has an effect bus containing 16 accumulators.
+ Each of the synthesizer voices can feed its output to these accumulators
+ and the DSP microcontroller can operate with the resulting sum.
+
+
+name='Wave Playback Volume',index=0
+
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
+The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
+
+name='Wave Surround Playback Volume',index=0
+
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
+The result samples are forwarded to the rear I2S DACs. These DACs operates
+separately (they are not inside the AC97 codec).
+
+name='Wave Center Playback Volume',index=0
+
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
+The result is mixed to mono signal (single channel) and forwarded to
+the ??rear?? right DAC PCM slot of the AC97 codec.
+
+name='Wave LFE Playback Volume',index=0
+
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulators. ALSA uses accumulators 0 and 1 for left and right PCM.
+The result is mixed to mono signal (single channel) and forwarded to
+the ??rear?? left DAC PCM slot of the AC97 codec.
+
+name='Wave Capture Volume',index=0
+name='Wave Capture Switch',index=0
+
+These controls are used to attenuate samples for left and right PCM FX-bus
+accumulator. ALSA uses accumulators 0 and 1 for left and right PCM.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+name='Music Playback Volume',index=0
+
+This control is used to attenuate samples for left and right MIDI FX-bus
+accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
+The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
+
+name='Music Capture Volume',index=0
+name='Music Capture Switch',index=0
+
+These controls are used to attenuate samples for left and right MIDI FX-bus
+accumulator. ALSA uses accumulators 4 and 5 for left and right PCM.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+name='Surround Digital Playback Volume',index=0
+
+This control is used to attenuate samples for left and right rear PCM FX-bus
+accumulators. ALSA uses accumulators 2 and 3 for left and right rear PCM samples.
+The result samples are forwarded to the rear I2S DACs. These DACs operate
+separately (they are not inside the AC97 codec).
+
+name='Surround Digital Capture Volume',index=0
+name='Surround Digital Capture Switch',index=0
+
+These controls are used to attenuate samples for left and right rear PCM FX-bus
+accumulators. ALSA uses accumulators 2 and 3 for left and right rear PCM samples.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+name='Center Playback Volume',index=0
+
+This control is used to attenuate sample for center PCM FX-bus accumulator.
+ALSA uses accumulator 6 for center PCM sample. The result sample is forwarded
+to the ??rear?? right DAC PCM slot of the AC97 codec.
+
+name='LFE Playback Volume',index=0
+
+This control is used to attenuate sample for center PCM FX-bus accumulator.
+ALSA uses accumulator 6 for center PCM sample. The result sample is forwarded
+to the ??rear?? left DAC PCM slot of the AC97 codec.
+
+name='AC97 Playback Volume',index=0
+
+This control is used to attenuate samples for left and right front ADC PCM slots
+of the AC97 codec. The result samples are forwarded to the front DAC PCM
+slots of the AC97 codec.
+********************************************************************************
+*** Note: This control should be zero for the standard operations, otherwise ***
+*** a digital loopback is activated. ***
+********************************************************************************
+
+name='AC97 Capture Volume',index=0
+
+This control is used to attenuate samples for left and right front ADC PCM slots
+of the AC97 codec. The result is forwarded to the ADC capture FIFO (thus to
+the standard capture PCM device).
+********************************************************************************
+*** Note: This control should be 100 (maximal value), otherwise no analog ***
+*** inputs of the AC97 codec can be captured (recorded). ***
+********************************************************************************
+
+name='IEC958 TTL Playback Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 TTL
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the front DAC PCM slots of the AC97 codec.
+
+name='IEC958 TTL Capture Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 TTL
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
+
+name='Zoom Video Playback Volume',index=0
+
+This control is used to attenuate samples from left and right zoom video
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the front DAC PCM slots of the AC97 codec.
+
+name='Zoom Video Capture Volume',index=0
+
+This control is used to attenuate samples from left and right zoom video
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
+
+name='IEC958 Optical Playback Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 optical
+digital input. The result samples are forwarded to the front DAC PCM slots
+of the AC97 codec.
+
+name='IEC958 Optical Capture Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 optical
+digital inputs. The result samples are forwarded to the ADC capture FIFO
+(thus to the standard capture PCM device).
+
+name='IEC958 Coaxial Playback Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 coaxial
+digital inputs. The result samples are forwarded to the front DAC PCM slots
+of the AC97 codec.
+
+name='IEC958 Coaxial Capture Volume',index=0
+
+This control is used to attenuate samples from left and right IEC958 coaxial
+digital inputs. The result samples are forwarded to the ADC capture FIFO
+(thus to the standard capture PCM device).
+
+name='Line LiveDrive Playback Volume',index=0
+name='Line LiveDrive Playback Volume',index=1
+
+This control is used to attenuate samples from left and right I2S ADC
+inputs (on the LiveDrive). The result samples are forwarded to the front
+DAC PCM slots of the AC97 codec.
+
+name='Line LiveDrive Capture Volume',index=1
+name='Line LiveDrive Capture Volume',index=1
+
+This control is used to attenuate samples from left and right I2S ADC
+inputs (on the LiveDrive). The result samples are forwarded to the ADC
+capture FIFO (thus to the standard capture PCM device).
+
+name='Tone Control - Switch',index=0
+
+This control turns the tone control on or off. The samples for front, rear
+and center / LFE outputs are affected.
+
+name='Tone Control - Bass',index=0
+
+This control sets the bass intensity. There is no neutral value!!
+When the tone control code is activated, the samples are always modified.
+The closest value to pure signal is 20.
+
+name='Tone Control - Treble',index=0
+
+This control sets the treble intensity. There is no neutral value!!
+When the tone control code is activated, the samples are always modified.
+The closest value to pure signal is 20.
+
+name='IEC958 Optical Raw Playback Switch',index=0
+
+If this switch is on, then the samples for the IEC958 (S/PDIF) digital
+output are taken only from the raw FX8010 PCM, otherwise standard front
+PCM samples are taken.
+
+name='Headphone Playback Volume',index=1
+
+This control attenuates the samples for the headphone output.
+
+name='Headphone Center Playback Switch',index=1
+
+If this switch is on, then the sample for the center PCM is put to the
+left headphone output (useful for SB Live cards without separate center/LFE
+output).
+
+name='Headphone LFE Playback Switch',index=1
+
+If this switch is on, then the sample for the center PCM is put to the
+right headphone output (useful for SB Live cards without separate center/LFE
+output).
+
+
+3) PCM stream related controls
+------------------------------
+
+name='EMU10K1 PCM Volume',index 0-31
+
+Channel volume attenuation in range 0-0xffff. The maximum value (no
+attenuation) is default. The channel mapping for three values is
+as follows:
+
+ 0 - mono, default 0xffff (no attenuation)
+ 1 - left, default 0xffff (no attenuation)
+ 2 - right, default 0xffff (no attenuation)
+
+name='EMU10K1 PCM Send Routing',index 0-31
+
+This control specifies the destination - FX-bus accumulators. There are
+twelve values with this mapping:
+
+ 0 - mono, A destination (FX-bus 0-15), default 0
+ 1 - mono, B destination (FX-bus 0-15), default 1
+ 2 - mono, C destination (FX-bus 0-15), default 2
+ 3 - mono, D destination (FX-bus 0-15), default 3
+ 4 - left, A destination (FX-bus 0-15), default 0
+ 5 - left, B destination (FX-bus 0-15), default 1
+ 6 - left, C destination (FX-bus 0-15), default 2
+ 7 - left, D destination (FX-bus 0-15), default 3
+ 8 - right, A destination (FX-bus 0-15), default 0
+ 9 - right, B destination (FX-bus 0-15), default 1
+ 10 - right, C destination (FX-bus 0-15), default 2
+ 11 - right, D destination (FX-bus 0-15), default 3
+
+Don't forget that it's illegal to assign a channel to the same FX-bus accumulator
+more than once (it means 0=0 && 1=0 is an invalid combination).
+
+name='EMU10K1 PCM Send Volume',index 0-31
+
+It specifies the attenuation (amount) for given destination in range 0-255.
+The channel mapping is following:
+
+ 0 - mono, A destination attn, default 255 (no attenuation)
+ 1 - mono, B destination attn, default 255 (no attenuation)
+ 2 - mono, C destination attn, default 0 (mute)
+ 3 - mono, D destination attn, default 0 (mute)
+ 4 - left, A destination attn, default 255 (no attenuation)
+ 5 - left, B destination attn, default 0 (mute)
+ 6 - left, C destination attn, default 0 (mute)
+ 7 - left, D destination attn, default 0 (mute)
+ 8 - right, A destination attn, default 0 (mute)
+ 9 - right, B destination attn, default 255 (no attenuation)
+ 10 - right, C destination attn, default 0 (mute)
+ 11 - right, D destination attn, default 0 (mute)
+
+
+
+4) MANUALS/PATENTS:
+-------------------
+
+ftp://opensource.creative.com/pub/doc
+-------------------------------------
+
+ Files:
+ LM4545.pdf AC97 Codec
+
+ m2049.pdf The EMU10K1 Digital Audio Processor
+
+ hog63.ps FX8010 - A DSP Chip Architecture for Audio Effects
+
+
+WIPO Patents
+------------
+ Patent numbers:
+ WO 9901813 (A1) Audio Effects Processor with multiple asynchronous (Jan. 14, 1999)
+ streams
+
+ WO 9901814 (A1) Processor with Instruction Set for Audio Effects (Jan. 14, 1999)
+
+ WO 9901953 (A1) Audio Effects Processor having Decoupled Instruction
+ Execution and Audio Data Sequencing (Jan. 14, 1999)
+
+
+US Patents (http://www.uspto.gov/)
+----------------------------------
+
+ US 5925841 Digital Sampling Instrument employing cache memory (Jul. 20, 1999)
+
+ US 5928342 Audio Effects Processor integrated on a single chip (Jul. 27, 1999)
+ with a multiport memory onto which multiple asynchronous
+ digital sound samples can be concurrently loaded
+
+ US 5930158 Processor with Instruction Set for Audio Effects (Jul. 27, 1999)
+
+ US 6032235 Memory initialization circuit (Tram) (Feb. 29, 2000)
+
+ US 6138207 Interpolation looping of audio samples in cache connected to (Oct. 24, 2000)
+ system bus with prioritization and modification of bus transfers
+ in accordance with loop ends and minimum block sizes
+
+ US 6151670 Method for conserving memory storage using a (Nov. 21, 2000)
+ pool of short term memory registers
+
+ US 6195715 Interrupt control for multiple programs communicating with (Feb. 27, 2001)
+ a common interrupt by associating programs to GP registers,
+ defining interrupt register, polling GP registers, and invoking
+ callback routine associated with defined interrupt register
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+ <TITLE>OSS Sequencer Emulation on ALSA</TITLE>
+</HEAD>
+<BODY>
+
+<CENTER>
+<H1>
+
+<HR WIDTH="100%"></H1></CENTER>
+
+<CENTER>
+<H1>
+OSS Sequencer Emulation on ALSA</H1></CENTER>
+
+<HR WIDTH="100%">
+<P>Copyright (c) 1998,1999 by Takashi Iwai
+<TT><A HREF="mailto:iwai@ww.uni-erlangen.de"><iwai@ww.uni-erlangen.de></A></TT>
+<P>ver.0.1.8; Nov. 16, 1999
+<H2>
+
+<HR WIDTH="100%"></H2>
+
+<H2>
+1. Description</H2>
+This directory contains the OSS sequencer emulation driver on ALSA. Note
+that this program is still in the development state.
+<P>What this does - it provides the emulation of the OSS sequencer, access
+via
+<TT>/dev/sequencer</TT> and <TT>/dev/music</TT> devices.
+The most of applications using OSS can run if the appropriate ALSA
+sequencer is prepared.
+<P>The following features are emulated by this driver:
+<UL>
+<LI>
+Normal sequencer and MIDI events:</LI>
+
+<BR>They are converted to the ALSA sequencer events, and sent to the corresponding
+port.
+<LI>
+Timer events:</LI>
+
+<BR>The timer is not selectable by ioctl. The control rate is fixed to
+100 regardless of HZ. That is, even on Alpha system, a tick is always
+1/100 second. The base rate and tempo can be changed in <TT>/dev/music</TT>.
+
+<LI>
+Patch loading:</LI>
+
+<BR>It purely depends on the synth drivers whether it's supported since
+the patch loading is realized by callback to the synth driver.
+<LI>
+I/O controls:</LI>
+
+<BR>Most of controls are accepted. Some controls
+are dependent on the synth driver, as well as even on original OSS.</UL>
+Furthermore, you can find the following advanced features:
+<UL>
+<LI>
+Better queue mechanism:</LI>
+
+<BR>The events are queued before processing them.
+<LI>
+Multiple applications:</LI>
+
+<BR>You can run two or more applications simultaneously (even for OSS sequencer)!
+However, each MIDI device is exclusive - that is, if a MIDI device is opened
+once by some application, other applications can't use it. No such a restriction
+in synth devices.
+<LI>
+Real-time event processing:</LI>
+
+<BR>The events can be processed in real time without using out of bound
+ioctl. To switch to real-time mode, send ABSTIME 0 event. The followed
+events will be processed in real-time without queued. To switch off the
+real-time mode, send RELTIME 0 event.
+<LI>
+<TT>/proc</TT> interface:</LI>
+
+<BR>The status of applications and devices can be shown via <TT>/proc/asound/seq/oss</TT>
+at any time. In the later version, configuration will be changed via <TT>/proc</TT>
+interface, too.</UL>
+
+<H2>
+2. Installation</H2>
+Run configure script with both sequencer support (<TT>--with-sequencer=yes</TT>)
+and OSS emulation (<TT>--with-oss=yes</TT>) options. A module <TT>snd-seq-oss.o</TT>
+will be created. If the synth module of your sound card supports for OSS
+emulation (so far, only Emu8000 driver), this module will be loaded automatically.
+Otherwise, you need to load this module manually.
+<P>At beginning, this module probes all the MIDI ports which have been
+already connected to the sequencer. Once after that, the creation and deletion
+of ports are watched by announcement mechanism of ALSA sequencer.
+<P>The available synth and MIDI devices can be found in proc interface.
+Run "<TT>cat /proc/asound/seq/oss</TT>", and check the devices. For example,
+if you use an AWE64 card, you'll see like the following:
+<PRE> OSS sequencer emulation version 0.1.8
+ ALSA client number 63
+ ALSA receiver port 0
+
+ Number of applications: 0
+
+ Number of synth devices: 1
+
+ synth 0: [EMU8000]
+ type 0x1 : subtype 0x20 : voices 32
+ capabilties : ioctl enabled / load_patch enabled
+
+ Number of MIDI devices: 3
+
+ midi 0: [Emu8000 Port-0] ALSA port 65:0
+ capability write / opened none
+
+ midi 1: [Emu8000 Port-1] ALSA port 65:1
+ capability write / opened none
+
+ midi 2: [0: MPU-401 (UART)] ALSA port 64:0
+ capability read/write / opened none</PRE>
+Note that the device number may be different from the information of
+<TT>/proc/asound/oss-devices</TT>
+or ones of the original OSS driver. Use the device number listed in <TT>/proc/asound/seq/oss</TT>
+to play via OSS sequencer emulation.
+<H2>
+3. Using Synthesizer Devices</H2>
+Run your favorite program. I've tested playmidi-2.4, awemidi-0.4.3, gmod-3.1
+and xmp-1.1.5. You can load samples via <TT>/dev/sequencer</TT> like sfxload,
+too.
+<P>If the lowlevel driver supports multiple access to synth devices (like
+Emu8000 driver), two or more applications are allowed to run at the same
+time.
+<H2>
+4. Using MIDI Devices</H2>
+So far, only MIDI output was tested. MIDI input was not checked at all,
+but hopefully it will work. Use the device number listed in <TT>/proc/asound/seq/oss</TT>.
+Be aware that these numbers are mostly different from the list in
+<TT>/proc/asound/oss-devices</TT>.
+<H2>
+5. Module Options</H2>
+The following module options are available:
+<UL>
+<LI>
+<TT>maxqlen</TT></LI>
+
+<BR>specifies the maximum read/write queue length. This queue is private
+for OSS sequencer, so that it is independent from the queue length of ALSA
+sequencer. Default value is 1024.
+<LI>
+<TT>seq_oss_debug</TT></LI>
+
+<BR>specifies the debug level and accepts zero (= no debug message) or
+positive integer. Default value is 0.</UL>
+
+<H2>
+6. Queue Mechanism</H2>
+OSS sequencer emulation uses an ALSA priority queue. The
+events from <TT>/dev/sequencer</TT> are processed and put onto the queue
+specified by module option.
+<P>All the events from <TT>/dev/sequencer</TT> are parsed at beginning.
+The timing events are also parsed at this moment, so that the events may
+be processed in real-time. Sending an event ABSTIME 0 switches the operation
+mode to real-time mode, and sending an event RELTIME 0 switches it off.
+In the real-time mode, all events are dispatched immediately.
+<P>The queued events are dispatched to the corresponding ALSA sequencer
+ports after scheduled time by ALSA sequencer dispatcher.
+<P>If the write-queue is full, the application sleeps until a certain amount
+(as default one half) becomes empty in blocking mode. The synchronization
+to write timing was implemented, too.
+<P>The input from MIDI devices or echo-back events are stored on read FIFO
+queue. If application reads <TT>/dev/sequencer</TT> in blocking mode, the
+process will be awaked.
+
+<H2>
+7. Interface to Synthesizer Device</H2>
+
+<H3>
+7.1. Registration</H3>
+To register an OSS synthesizer device, use <TT>snd_seq_oss_synth_register</TT>
+function.
+<PRE>int snd_seq_oss_synth_register(char *name, int type, int subtype, int nvoices,
+ snd_seq_oss_callback_t *oper, void *private_data)</PRE>
+The arguments <TT>name</TT>, <TT>type</TT>, <TT>subtype</TT> and
+<TT>nvoices</TT>
+are used for making the appropriate synth_info structure for ioctl. The
+return value is an index number of this device. This index must be remembered
+for unregister. If registration is failed, -errno will be returned.
+<P>To release this device, call <TT>snd_seq_oss_synth_unregister function</TT>:
+<PRE>int snd_seq_oss_synth_unregister(int index),</PRE>
+where the <TT>index</TT> is the index number returned by register function.
+<H3>
+7.2. Callbacks</H3>
+OSS synthesizer devices have capability for sample downloading and ioctls
+like sample reset. In OSS emulation, these special features are realized
+by using callbacks. The registration argument oper is used to specify these
+callbacks. The following callback functions must be defined:
+<PRE>snd_seq_oss_callback_t:
+ int (*open)(snd_seq_oss_arg_t *p, void *closure);
+ int (*close)(snd_seq_oss_arg_t *p);
+ int (*ioctl)(snd_seq_oss_arg_t *p, unsigned int cmd, unsigned long arg);
+ int (*load_patch)(snd_seq_oss_arg_t *p, int format, const char *buf, int offs, int count);
+ int (*reset)(snd_seq_oss_arg_t *p);
+Except for <TT>open</TT> and <TT>close</TT> callbacks, they are allowed
+to be NULL.
+<P>Each callback function takes the argument type snd_seq_oss_arg_t as the
+first argument.
+<PRE>struct snd_seq_oss_arg_t {
+ int app_index;
+ int file_mode;
+ int seq_mode;
+ snd_seq_addr_t addr;
+ void *private_data;
+ int event_passing;
+};</PRE>
+The first three fields, <TT>app_index</TT>, <TT>file_mode</TT> and
+<TT>seq_mode</TT>
+are initialized by OSS sequencer. The <TT>app_index</TT> is the application
+index which is unique to each application opening OSS sequencer. The
+<TT>file_mode</TT>
+is bit-flags indicating the file operation mode. See
+<TT>seq_oss.h</TT>
+for its meaning. The <TT>seq_mode</TT> is sequencer operation mode. In
+the current version, only <TT>SND_OSSSEQ_MODE_SYNTH</TT> is used.
+<P>The next two fields, <TT>addr</TT> and <TT>private_data</TT>, must be
+filled by the synth driver at open callback. The <TT>addr</TT> contains
+the address of ALSA sequencer port which is assigned to this device. If
+the driver allocates memory for <TT>private_data</TT>, it must be released
+in close callback by itself.
+<P>The last field, <TT>event_passing</TT>, indicates how to translate note-on
+/ off events. In <TT>PROCESS_EVENTS</TT> mode, the note 255 is regarded
+as velocity change, and key pressure event is passed to the port. In <TT>PASS_EVENTS</TT>
+mode, all note on/off events are passed to the port without modified. <TT>PROCESS_KEYPRESS</TT>
+mode checks the note above 128 and regards it as key pressure event (mainly
+for Emu8000 driver).
+<H4>
+7.2.1. Open Callback</H4>
+The <TT>open</TT> is called at each time this device is opened by an application
+using OSS sequencer. This must not be NULL. Typically, the open callback
+does the following procedure:
+<OL>
+<LI>
+Allocate private data record.</LI>
+
+<LI>
+Create an ALSA sequencer port.</LI>
+
+<LI>
+Set the new port address on arg->addr.</LI>
+
+<LI>
+Set the private data record pointer on arg->private_data.</LI>
+</OL>
+Note that the type bit-flags in port_info of this synth port must NOT contain
+<TT>TYPE_MIDI_GENERIC</TT>
+bit. Instead, <TT>TYPE_SPECIFIC</TT> should be used. Also, <TT>CAP_SUBSCRIPTION</TT>
+bit should NOT be included, too. This is necessary to tell it from other
+normal MIDI devices. If the open procedure succeeded, return zero. Otherwise,
+return -errno.
+<H4>
+7.2.2 Ioctl Callback</H4>
+The <TT>ioctl</TT> callback is called when the sequencer receives device-specific
+ioctls. The following two ioctls should be processed by this callback:
+<UL>
+<LI>
+<TT>IOCTL_SEQ_RESET_SAMPLES</TT></LI>
+
+<BR>reset all samples on memory -- return 0
+<LI>
+<TT>IOCTL_SYNTH_MEMAVL</TT></LI>
+
+<BR>return the available memory size
+<LI>
+<TT>FM_4OP_ENABLE</TT></LI>
+
+<BR>can be ignored usually</UL>
+The other ioctls are processed inside the sequencer without passing to
+the lowlevel driver.
+<H4>
+7.2.3 Load_Patch Callback</H4>
+The <TT>load_patch</TT> callback is used for sample-downloading. This callback
+must read the data on user-space and transfer to each device. Return 0
+if succeeded, and -errno if failed. The format argument is the patch key
+in patch_info record. The buf is user-space pointer where patch_info record
+is stored. The offs can be ignored. The count is total data size of this
+sample data.
+<H4>
+7.2.4 Close Callback</H4>
+The <TT>close</TT> callback is called when this device is closed by the
+applicaion. If any private data was allocated in open callback, it must
+be released in the close callback. The deletion of ALSA port should be
+done here, too. This callback must not be NULL.
+<H4>
+7.2.5 Reset Callback</H4>
+The <TT>reset</TT> callback is called when sequencer device is reset or
+closed by applications. The callback should turn off the sounds on the
+relevant port immediately, and initialize the status of the port. If this
+callback is undefined, OSS seq sends a <TT>HEARTBEAT</TT> event to the
+port.
+<H3>
+7.3 Events</H3>
+Most of the events are processed by sequencer and translated to the adequate
+ALSA sequencer events, so that each synth device can receive by input_event
+callback of ALSA sequencer port. The following ALSA events should be implemented
+by the driver:
+<BR>
+<TABLE BORDER WIDTH="75%" NOSAVE >
+<TR NOSAVE>
+<TD NOSAVE><B>ALSA event</B></TD>
+
+<TD><B>Original OSS events</B></TD>
+</TR>
+
+<TR>
+<TD>NOTEON</TD>
+
+<TD>SEQ_NOTEON
+<BR>MIDI_NOTEON</TD>
+</TR>
+
+<TR>
+<TD>NOTE</TD>
+
+<TD>SEQ_NOTEOFF
+<BR>MIDI_NOTEOFF</TD>
+</TR>
+
+<TR NOSAVE>
+<TD NOSAVE>KEYPRESS</TD>
+
+<TD>MIDI_KEY_PRESSURE</TD>
+</TR>
+
+<TR NOSAVE>
+<TD>CHANPRESS</TD>
+
+<TD NOSAVE>SEQ_AFTERTOUCH
+<BR>MIDI_CHN_PRESSURE</TD>
+</TR>
+
+<TR NOSAVE>
+<TD NOSAVE>PGMCHANGE</TD>
+
+<TD NOSAVE>SEQ_PGMCHANGE
+<BR>MIDI_PGM_CHANGE</TD>
+</TR>
+
+<TR>
+<TD>PITCHBEND</TD>
+
+<TD>SEQ_CONTROLLER(CTRL_PITCH_BENDER)
+<BR>MIDI_PITCH_BEND</TD>
+</TR>
+
+<TR>
+<TD>CONTROLLER</TD>
+
+<TD>MIDI_CTL_CHANGE
+<BR>SEQ_BALANCE (with CTL_PAN)</TD>
+</TR>
+
+<TR>
+<TD>CONTROL14</TD>
+
+<TD>SEQ_CONTROLLER</TD>
+</TR>
+
+<TR>
+<TD>REGPARAM</TD>
+
+<TD>SEQ_CONTROLLER(CTRL_PITCH_BENDER_RANGE)</TD>
+</TR>
+
+<TR>
+<TD>SYSEX</TD>
+
+<TD>SEQ_SYSEX</TD>
+</TR>
+</TABLE>
+
+<P>The most of these behavior can be realized by MIDI emulation driver
+included in the Emu8000 lowlevel driver. In the future release, this module
+will be independent.
+<P>Some OSS events (<TT>SEQ_PRIVATE</TT> and <TT>SEQ_VOLUME</TT> events) are passed as event
+type SND_SEQ_OSS_PRIVATE. The OSS sequencer passes these event 8 byte
+packets without any modification. The lowlevel driver should process these
+events appropriately.
+<H2>
+8. Interface to MIDI Device</H2>
+Since the OSS emulation probes the creation and deletion of ALSA MIDI sequencer
+ports automatically by receiving announcement from ALSA sequencer, the
+MIDI devices don't need to be registered explicitly like synth devices.
+However, the MIDI port_info registered to ALSA sequencer must include a group
+name <TT>SND_SEQ_GROUP_DEVICE</TT> and a capability-bit <TT>CAP_READ</TT> or
+<TT>CAP_WRITE</TT>. Also, subscription capabilities, <TT>CAP_SUBS_READ</TT> or <TT>CAP_SUBS_WRITE</TT>,
+must be defined, too. If these conditions are not satisfied, the port is not
+registered as OSS sequencer MIDI device.
+<P>The events via MIDI devices are parsed in OSS sequencer and converted
+to the corresponding ALSA sequencer events. The input from MIDI sequencer
+is also converted to MIDI byte events by OSS sequencer. This works just
+a reverse way of seq_midi module.
+<H2>
+9. Known Problems / TODO's</H2>
+
+<UL>
+<LI>
+Patch loading via ALSA instrument layer is not implemented yet.</LI>
+</UL>
+
+</BODY>
+</HTML>
*
*/
+#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;
#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 */
#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);
#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; }
#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;
*
*/
-#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)"
--- /dev/null
+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>.
--- /dev/null
+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
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
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
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
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
#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
"memdebug",
"detect",
"devices",
- "oss-devices",
+ "oss",
"cards",
"timers",
"synth",
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)
{
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) {
goto out;
case 2: /* SEEK_END */
default:
+ ret = -EINVAL;
goto out;
}
break;
}
ret = -ENXIO;
out:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 3)
unlock_kernel();
+#endif
return ret;
}
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;
#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);
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;
--- /dev/null
+#
+# 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)
--- /dev/null
+/*
+ * 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 },
+};
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 },
+};
--- /dev/null
+/*
+ * 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 },
+};
--- /dev/null
+/*
+ * 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 },
+};
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 ||
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 */
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 ||
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;
}
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 ||
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)
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 ||
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;
}
* 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>
/*
- * 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,
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 */
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;
}
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;
}
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;
}
*/
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 */
}
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
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;
}
/*
- * exported stuffs
+ * exported stuff
*/
module_init(rtctimer_init)
module_exit(rtctimer_exit)
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
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},
{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 */
{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);
}
}
dev->bufsize = bufsize;
+ dev->lastcmd = 0xff;
spin_lock_init(&dev->lock);
*rdev = dev;
return 0;
}
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;
{
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;
--- /dev/null
+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.
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
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/mpu401.h>
#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>
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
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
#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");
*
* 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
*
* 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
*
* 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.
#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
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
--- /dev/null
+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.
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/ad1816a.h>
#include <asm/dma.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/ad1848.h>
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),
#include <linux/pm.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/ioport.h>
#include <sound/core.h>
#include <sound/cs4231.h>
#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>
#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>
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),
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
#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>
#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
#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>
#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>
static int dma_bits[] = {1, 2, 0, 3};
int tmp, tmp1;
- unsigned int flags;
+ unsigned long flags;
if ((tmp = inb(port + 3)) == 0xff)
{
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
{
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++) {
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);
--- /dev/null
+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.
}
legacy_ctrl = 0;
- legacy_ctrl2 = 0;
+ legacy_ctrl2 = 0x0800; /* SMOD = 01 */
if (id->device >= 0x0010) { /* YMF 744/754 */
if (snd_fm_port[dev] < 0)
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