Merge branch 'for-next' into for-linus
Pull 4.15 updates to take over the previous urgent fixes. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
commit
c429bda21f
171 changed files with 452 additions and 41482 deletions
|
@ -82,6 +82,8 @@ tpt460
|
|||
Lenovo Thinkpad T460/560 setup
|
||||
dual-codecs
|
||||
Lenovo laptops with dual codecs
|
||||
alc700-ref
|
||||
Intel reference board with ALC700 codec
|
||||
|
||||
ALC66x/67x/892
|
||||
==============
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
ALS-007/ALS-100/ALS-200 based sound cards
|
||||
=========================================
|
||||
|
||||
Support for sound cards based around the Avance Logic
|
||||
ALS-007/ALS-100/ALS-200 chip is included. These chips are a single
|
||||
chip PnP sound solution which is mostly hardware compatible with the
|
||||
Sound Blaster 16 card, with most differences occurring in the use of
|
||||
the mixer registers. For this reason the ALS code is integrated
|
||||
as part of the Sound Blaster 16 driver (adding only 800 bytes to the
|
||||
SB16 driver).
|
||||
|
||||
To use an ALS sound card under Linux, enable the following options as
|
||||
modules in the sound configuration section of the kernel config:
|
||||
- 100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support
|
||||
- FM synthesizer (YM3812/OPL-3) support
|
||||
- standalone MPU401 support may be required for some cards; for the
|
||||
ALS-007, when using isapnptools, it is required
|
||||
Since the ALS-007/100/200 are PnP cards, ISAPnP support should probably be
|
||||
compiled in. If kernel level PnP support is not included, isapnptools will
|
||||
be required to configure the card before the sound modules are loaded.
|
||||
|
||||
When using kernel level ISAPnP, the kernel should correctly identify and
|
||||
configure all resources required by the card when the "sb" module is
|
||||
inserted. Note that the ALS-007 does not have a 16 bit DMA channel and that
|
||||
the MPU401 interface on this card uses a different interrupt to the audio
|
||||
section. This should all be correctly configured by the kernel; if problems
|
||||
with the MPU401 interface surface, try using the standalone MPU401 module,
|
||||
passing "0" as the "sb" module's "mpu_io" module parameter to prevent the
|
||||
soundblaster driver attempting to register the MPU401 itself. The onboard
|
||||
synth device can be accessed using the "opl3" module.
|
||||
|
||||
If isapnptools is used to wake up the sound card (as in 2.2.x), the settings
|
||||
of the card's resources should be passed to the kernel modules ("sb", "opl3"
|
||||
and "mpu401") using the module parameters. When configuring an ALS-007, be
|
||||
sure to specify different IRQs for the audio and MPU401 sections - this card
|
||||
requires they be different. For "sb", "io", "irq" and "dma" should be set
|
||||
to the same values used to configure the audio section of the card with
|
||||
isapnp. "dma16" should be explicitly set to "-1" for an ALS-007 since this
|
||||
card does not have a 16 bit dma channel; if not specified the kernel will
|
||||
default to using channel 5 anyway which will cause audio not to work.
|
||||
"mpu_io" should be set to 0. The "io" parameter of the "opl3" module should
|
||||
also agree with the setting used by isapnp. To get the MPU401 interface
|
||||
working on an ALS-007 card, the "mpu401" module will be required since this
|
||||
card uses separate IRQs for the audio and MPU401 sections and there is no
|
||||
parameter available to pass a different IRQ to the "sb" driver (whose
|
||||
inbuilt MPU401 driver would otherwise be fine). Insert the mpu401 module
|
||||
passing appropriate values using the "io" and "irq" parameters.
|
||||
|
||||
The resulting sound driver will provide the following capabilities:
|
||||
- 8 and 16 bit audio playback
|
||||
- 8 and 16 bit audio recording
|
||||
- Software selection of record source (line in, CD, FM, mic, master)
|
||||
- Record and playback of midi data via the external MPU-401
|
||||
- Playback of midi data using inbuilt FM synthesizer
|
||||
- Control of the ALS-007 mixer via any OSS-compatible mixer programs.
|
||||
Controls available are Master (L&R), Line in (L&R), CD (L&R),
|
||||
DSP/PCM/audio out (L&R), FM (L&R) and Mic in (mono).
|
||||
|
||||
Jonathan Woithe
|
||||
jwoithe@just42.net
|
||||
30 March 1998
|
||||
|
||||
Modified 2000-02-26 by Dave Forrest, drf5n@virginia.edu to add ALS100/ALS200
|
||||
Modified 2000-04-10 by Paul Laufer, pelaufer@csupomona.edu to add ISAPnP info.
|
||||
Modified 2000-11-19 by Jonathan Woithe, jwoithe@just42.net
|
||||
- updated information for kernel 2.4.x.
|
|
@ -1,101 +0,0 @@
|
|||
Driver
|
||||
------
|
||||
|
||||
Information about Audio Excel DSP 16 driver can be found in the source
|
||||
file aedsp16.c
|
||||
Please, read the head of the source before using it. It contain useful
|
||||
information.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
The Audio Excel configuration, is now done with the standard Linux setup.
|
||||
You have to configure the sound card (Sound Blaster or Microsoft Sound System)
|
||||
and, if you want it, the Roland MPU-401 (do not use the Sound Blaster MPU-401,
|
||||
SB-MPU401) in the main driver menu. Activate the lowlevel drivers then select
|
||||
the Audio Excel hardware that you want to initialize. Check the IRQ/DMA/MIRQ
|
||||
of the Audio Excel initialization: it must be the same as the SBPRO (or MSS)
|
||||
setup. If the parameters are different, correct it.
|
||||
I you own a Gallant's audio card based on SC-6600, activate the SC-6600 support.
|
||||
If you want to change the configuration of the sound board, be sure to
|
||||
check off all the configuration items before re-configure it.
|
||||
|
||||
Module parameters
|
||||
-----------------
|
||||
To use this driver as a module, you must configure some module parameters, to
|
||||
set up I/O addresses, IRQ lines and DMA channels. Some parameters are
|
||||
mandatory while some others are optional. Here a list of parameters you can
|
||||
use with this module:
|
||||
|
||||
Name Description
|
||||
==== ===========
|
||||
MANDATORY
|
||||
io I/O base address (0x220 or 0x240)
|
||||
irq irq line (5, 7, 9, 10 or 11)
|
||||
dma dma channel (0, 1 or 3)
|
||||
|
||||
OPTIONAL
|
||||
mss_base I/O base address for activate MSS mode (default SBPRO)
|
||||
(0x530 or 0xE80)
|
||||
mpu_base I/O base address for activate MPU-401 mode
|
||||
(0x300, 0x310, 0x320 or 0x330)
|
||||
mpu_irq MPU-401 irq line (5, 7, 9, 10 or 0)
|
||||
|
||||
A configuration file in /etc/modprobe.d/ directory will have lines like this:
|
||||
|
||||
options opl3 io=0x388
|
||||
options ad1848 io=0x530 irq=11 dma=3
|
||||
options aedsp16 io=0x220 irq=11 dma=3 mss_base=0x530
|
||||
|
||||
Where the aedsp16 options are the options for this driver while opl3 and
|
||||
ad1848 are the corresponding options for the MSS and OPL3 modules.
|
||||
|
||||
Loading MSS and OPL3 needs to pre load the aedsp16 module to set up correctly
|
||||
the sound card. Installation dependencies must be written in configuration
|
||||
files under /etc/modprobe.d/ directory:
|
||||
|
||||
softdep ad1848 pre: aedsp16
|
||||
softdep opl3 pre: aedsp16
|
||||
|
||||
Then you must load the sound modules stack in this order:
|
||||
sound -> aedsp16 -> [ ad1848, opl3 ]
|
||||
|
||||
With the above configuration, loading ad1848 or opl3 modules, will
|
||||
automatically load all the sound stack.
|
||||
|
||||
Sound cards supported
|
||||
---------------------
|
||||
This driver supports the SC-6000 and SC-6600 based Gallant's sound card.
|
||||
It don't support the Audio Excel DSP 16 III (try the SC-6600 code).
|
||||
I'm working on the III version of the card: if someone have useful
|
||||
information about it, please let me know.
|
||||
For all the non-supported audio cards, you have to boot MS-DOS (or WIN95)
|
||||
activating the audio card with the MS-DOS device driver, then you have to
|
||||
<ctrl>-<alt>-<del> and boot Linux.
|
||||
Follow these steps:
|
||||
|
||||
1) Compile Linux kernel with standard sound driver, using the emulation
|
||||
you want, with the parameters of your audio card,
|
||||
e.g. Microsoft Sound System irq10 dma3
|
||||
2) Install your new kernel as the default boot kernel.
|
||||
3) Boot MS-DOS and configure the audio card with the boot time device
|
||||
driver, for MSS irq10 dma3 in our example.
|
||||
4) <ctrl>-<alt>-<del> and boot Linux. This will maintain the DOS configuration
|
||||
and will boot the new kernel with sound driver. The sound driver will find
|
||||
the audio card and will recognize and attach it.
|
||||
|
||||
Reports on User successes
|
||||
-------------------------
|
||||
|
||||
> Date: Mon, 29 Jul 1996 08:35:40 +0100
|
||||
> From: Mr S J Greenaway <sjg95@unixfe.rl.ac.uk>
|
||||
> To: riccardo@cdc8g5.cdc.polimi.it (Riccardo Facchetti)
|
||||
> Subject: Re: Audio Excel DSP 16 initialization code
|
||||
>
|
||||
> Just to let you know got my Audio Excel (emulating a MSS) working
|
||||
> with my original SB16, thanks for the driver!
|
||||
|
||||
|
||||
Last revised: 20 August 1998
|
||||
Riccardo Facchetti
|
||||
fizban@tin.it
|
|
@ -1,152 +0,0 @@
|
|||
Documentation for CMI 8330 (SoundPRO)
|
||||
-------------------------------------
|
||||
Alessandro Zummo <azummo@ita.flashnet.it>
|
||||
|
||||
( Be sure to read Documentation/sound/oss/SoundPro too )
|
||||
|
||||
|
||||
This adapter is now directly supported by the sb driver.
|
||||
|
||||
The only thing you have to do is to compile the kernel sound
|
||||
support as a module and to enable kernel ISAPnP support,
|
||||
as shown below.
|
||||
|
||||
|
||||
CONFIG_SOUND=m
|
||||
CONFIG_SOUND_SB=m
|
||||
|
||||
CONFIG_PNP=y
|
||||
CONFIG_ISAPNP=y
|
||||
|
||||
|
||||
and optionally:
|
||||
|
||||
|
||||
CONFIG_SOUND_MPU401=m
|
||||
|
||||
for MPU401 support.
|
||||
|
||||
|
||||
(I suggest you to use "make menuconfig" or "make xconfig"
|
||||
for a more comfortable configuration editing)
|
||||
|
||||
|
||||
|
||||
Then you can do
|
||||
|
||||
modprobe sb
|
||||
|
||||
and everything will be (hopefully) configured.
|
||||
|
||||
You should get something similar in syslog:
|
||||
|
||||
sb: CMI8330 detected.
|
||||
sb: CMI8330 sb base located at 0x220
|
||||
sb: CMI8330 mpu base located at 0x330
|
||||
sb: CMI8330 mail reports to Alessandro Zummo <azummo@ita.flashnet.it>
|
||||
sb: ISAPnP reports CMI 8330 SoundPRO at i/o 0x220, irq 7, dma 1,5
|
||||
|
||||
|
||||
|
||||
|
||||
The old documentation file follows for reference
|
||||
purposes.
|
||||
|
||||
|
||||
How to enable CMI 8330 (SOUNDPRO) soundchip on Linux
|
||||
------------------------------------------
|
||||
Stefan Laudat <Stefan.Laudat@asit.ro>
|
||||
|
||||
[Note: The CMI 8338 is unrelated and is supported by cmpci.o]
|
||||
|
||||
|
||||
In order to use CMI8330 under Linux you just have to use a proper isapnp.conf, a good isapnp and a little bit of patience. I use isapnp 1.17, but
|
||||
you may get a better one I guess at http://www.roestock.demon.co.uk/isapnptools/.
|
||||
|
||||
Of course you will have to compile kernel sound support as module, as shown below:
|
||||
|
||||
CONFIG_SOUND=m
|
||||
CONFIG_SOUND_OSS=m
|
||||
CONFIG_SOUND_SB=m
|
||||
CONFIG_SOUND_ADLIB=m
|
||||
CONFIG_SOUND_MPU401=m
|
||||
# Mikro$chaft sound system (kinda useful here ;))
|
||||
CONFIG_SOUND_MSS=m
|
||||
|
||||
The /etc/isapnp.conf file will be:
|
||||
|
||||
<snip below>
|
||||
|
||||
|
||||
(READPORT 0x0203)
|
||||
(ISOLATE PRESERVE)
|
||||
(IDENTIFY *)
|
||||
(VERBOSITY 2)
|
||||
(CONFLICT (IO FATAL)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) # or WARNING
|
||||
(VERIFYLD N)
|
||||
|
||||
|
||||
# WSS
|
||||
|
||||
(CONFIGURE CMI0001/16777472 (LD 0
|
||||
(IO 0 (SIZE 8) (BASE 0x0530))
|
||||
(IO 1 (SIZE 8) (BASE 0x0388))
|
||||
(INT 0 (IRQ 7 (MODE +E)))
|
||||
(DMA 0 (CHANNEL 0))
|
||||
(NAME "CMI0001/16777472[0]{CMI8330/C3D Audio Adapter}")
|
||||
(ACT Y)
|
||||
))
|
||||
|
||||
# MPU
|
||||
|
||||
(CONFIGURE CMI0001/16777472 (LD 1
|
||||
(IO 0 (SIZE 2) (BASE 0x0330))
|
||||
(INT 0 (IRQ 11 (MODE +E)))
|
||||
(NAME "CMI0001/16777472[1]{CMI8330/C3D Audio Adapter}")
|
||||
(ACT Y)
|
||||
))
|
||||
|
||||
# Joystick
|
||||
|
||||
(CONFIGURE CMI0001/16777472 (LD 2
|
||||
(IO 0 (SIZE 8) (BASE 0x0200))
|
||||
(NAME "CMI0001/16777472[2]{CMI8330/C3D Audio Adapter}")
|
||||
(ACT Y)
|
||||
))
|
||||
|
||||
# SoundBlaster
|
||||
|
||||
(CONFIGURE CMI0001/16777472 (LD 3
|
||||
(IO 0 (SIZE 16) (BASE 0x0220))
|
||||
(INT 0 (IRQ 5 (MODE +E)))
|
||||
(DMA 0 (CHANNEL 1))
|
||||
(DMA 1 (CHANNEL 5))
|
||||
(NAME "CMI0001/16777472[3]{CMI8330/C3D Audio Adapter}")
|
||||
(ACT Y)
|
||||
))
|
||||
|
||||
|
||||
(WAITFORKEY)
|
||||
|
||||
<end of snip>
|
||||
|
||||
The module sequence is trivial:
|
||||
|
||||
/sbin/insmod soundcore
|
||||
/sbin/insmod sound
|
||||
/sbin/insmod uart401
|
||||
# insert this first
|
||||
/sbin/insmod ad1848 io=0x530 irq=7 dma=0 soundpro=1
|
||||
# The sb module is an alternative to the ad1848 (Microsoft Sound System)
|
||||
# Anyhow, this is full duplex and has MIDI
|
||||
/sbin/insmod sb io=0x220 dma=1 dma16=5 irq=5 mpu_io=0x330
|
||||
|
||||
|
||||
|
||||
Alma Chao <elysian@ethereal.torsion.org> suggests the following in
|
||||
a /etc/modprobe.d/*conf file:
|
||||
|
||||
alias sound ad1848
|
||||
alias synth0 opl3
|
||||
options ad1848 io=0x530 irq=7 dma=0 soundpro=1
|
||||
options opl3 io=0x388
|
|
@ -1,34 +0,0 @@
|
|||
Documentation for the ESS AudioDrive chips
|
||||
|
||||
In 2.4 kernels the SoundBlaster driver not only tries to detect an ESS chip, it
|
||||
tries to detect the type of ESS chip too. The correct detection of the chip
|
||||
doesn't always succeed however, so unless you use the kernel isapnp facilities
|
||||
(and you chip is pnp capable) the default behaviour is 2.0 behaviour which
|
||||
means: only detect ES688 and ES1688.
|
||||
|
||||
All ESS chips now have a recording level setting. This is a need-to-have for
|
||||
people who want to use their ESS for recording sound.
|
||||
|
||||
Every chip that's detected as a later-than-es1688 chip has a 6 bits logarithmic
|
||||
master volume control.
|
||||
|
||||
Every chip that's detected as a ES1887 now has Full Duplex support. Made a
|
||||
little testprogram that shows that is works, haven't seen a real program that
|
||||
needs this however.
|
||||
|
||||
For ESS chips an additional parameter "esstype" can be specified. This controls
|
||||
the (auto) detection of the ESS chips. It can have 3 kinds of values:
|
||||
|
||||
-1 Act like 2.0 kernels: only detect ES688 or ES1688.
|
||||
0 Try to auto-detect the chip (may fail for ES1688)
|
||||
688 The chip will be treated as ES688
|
||||
1688 ,, ,, ,, ,, ,, ,, ES1688
|
||||
1868 ,, ,, ,, ,, ,, ,, ES1868
|
||||
1869 ,, ,, ,, ,, ,, ,, ES1869
|
||||
1788 ,, ,, ,, ,, ,, ,, ES1788
|
||||
1887 ,, ,, ,, ,, ,, ,, ES1887
|
||||
1888 ,, ,, ,, ,, ,, ,, ES1888
|
||||
|
||||
Because Full Duplex is supported for ES1887 you can specify a second DMA
|
||||
channel by specifying module parameter dma16. It can be one of: 0, 1, 3 or 5.
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
Documentation for the ESS1868F AudioDrive PnP sound card
|
||||
|
||||
The ESS1868 sound card is a PnP ESS1688-compatible 16-bit sound card.
|
||||
|
||||
It should be automatically detected by the Linux Kernel isapnp support when you
|
||||
load the sb.o module. Otherwise you should take care of:
|
||||
|
||||
* The ESS1868 does not allow use of a 16-bit DMA, thus DMA 0, 1, 2, and 3
|
||||
may only be used.
|
||||
|
||||
* isapnptools version 1.14 does work with ESS1868. Earlier versions might
|
||||
not.
|
||||
|
||||
* Sound support MUST be compiled as MODULES, not statically linked
|
||||
into the kernel.
|
||||
|
||||
|
||||
NOTE: this is only needed when not using the kernel isapnp support!
|
||||
|
||||
For configuring the sound card's I/O addresses, IRQ and DMA, here is a
|
||||
sample copy of the isapnp.conf directives regarding the ESS1868:
|
||||
|
||||
(CONFIGURE ESS1868/-1 (LD 1
|
||||
(IO 0 (BASE 0x0220))
|
||||
(IO 1 (BASE 0x0388))
|
||||
(IO 2 (BASE 0x0330))
|
||||
(DMA 0 (CHANNEL 1))
|
||||
(INT 0 (IRQ 5 (MODE +E)))
|
||||
(ACT Y)
|
||||
))
|
||||
|
||||
(for a full working isapnp.conf file, remember the
|
||||
(ISOLATE)
|
||||
(IDENTIFY *)
|
||||
at the beginning and the
|
||||
(WAITFORKEY)
|
||||
at the end.)
|
||||
|
||||
In this setup, the main card I/O is 0x0220, FM synthesizer is 0x0388, and
|
||||
the MPU-401 MIDI port is located at 0x0330. IRQ is IRQ 5, DMA is channel 1.
|
||||
|
||||
After configuring the sound card via isapnp, to use the card you must load
|
||||
the sound modules with the proper I/O information. Here is my setup:
|
||||
|
||||
# ESS1868F AudioDrive initialization
|
||||
|
||||
/sbin/modprobe sound
|
||||
/sbin/insmod uart401
|
||||
/sbin/insmod sb io=0x220 irq=5 dma=1 dma16=-1
|
||||
/sbin/insmod mpu401 io=0x330
|
||||
/sbin/insmod opl3 io=0x388
|
||||
/sbin/insmod v_midi
|
||||
|
||||
opl3 is the FM synthesizer
|
||||
/sbin/insmod opl3 io=0x388
|
|
@ -1,459 +0,0 @@
|
|||
Introduction Notes on Modular Sound Drivers and Soundcore
|
||||
Wade Hampton
|
||||
2/14/2001
|
||||
|
||||
Purpose:
|
||||
========
|
||||
This document provides some general notes on the modular
|
||||
sound drivers and their configuration, along with the
|
||||
support modules sound.o and soundcore.o.
|
||||
|
||||
Note, some of this probably should be added to the Sound-HOWTO!
|
||||
|
||||
Note, soundlow.o was present with 2.2 kernels but is not
|
||||
required for 2.4.x kernels. References have been removed
|
||||
to this.
|
||||
|
||||
|
||||
Copying:
|
||||
========
|
||||
none
|
||||
|
||||
|
||||
History:
|
||||
========
|
||||
0.1.0 11/20/1998 First version, draft
|
||||
1.0.0 11/1998 Alan Cox changes, incorporation in 2.2.0
|
||||
as Documentation/sound/oss/Introduction
|
||||
1.1.0 6/30/1999 Second version, added notes on making the drivers,
|
||||
added info on multiple sound cards of similar types,]
|
||||
added more diagnostics info, added info about esd.
|
||||
added info on OSS and ALSA.
|
||||
1.1.1 19991031 Added notes on sound-slot- and sound-service.
|
||||
(Alan Cox)
|
||||
1.1.2 20000920 Modified for Kernel 2.4 (Christoph Hellwig)
|
||||
1.1.3 20010214 Minor notes and corrections (Wade Hampton)
|
||||
Added examples of sound-slot-0, etc.
|
||||
|
||||
|
||||
Modular Sound Drivers:
|
||||
======================
|
||||
|
||||
Thanks to the GREAT work by Alan Cox (alan@lxorguk.ukuu.org.uk),
|
||||
|
||||
[And Oleg Drokin, Thomas Sailer, Andrew Veliath and more than a few
|
||||
others - not to mention Hannu's original code being designed well
|
||||
enough to cope with that kind of chopping up](Alan)
|
||||
|
||||
the standard Linux kernels support a modular sound driver. From
|
||||
Alan's comments in linux/drivers/sound/README.FIRST:
|
||||
|
||||
The modular sound driver patches were funded by Red Hat Software
|
||||
(www.redhat.com). The sound driver here is thus a modified version of
|
||||
Hannu's code. Please bear that in mind when considering the appropriate
|
||||
forums for bug reporting.
|
||||
|
||||
The modular sound drivers may be loaded via insmod or modprobe.
|
||||
To support all the various sound modules, there are two general
|
||||
support modules that must be loaded first:
|
||||
|
||||
soundcore.o: Top level handler for the sound system, provides
|
||||
a set of functions for registration of devices
|
||||
by type.
|
||||
|
||||
sound.o: Common sound functions required by all modules.
|
||||
|
||||
For the specific sound modules (e.g., sb.o for the Soundblaster),
|
||||
read the documentation on that module to determine what options
|
||||
are available, for example IRQ, address, DMA.
|
||||
|
||||
Warning, the options for different cards sometime use different names
|
||||
for the same or a similar feature (dma1= versus dma16=). As a last
|
||||
resort, inspect the code (search for module_param).
|
||||
|
||||
Notes:
|
||||
|
||||
1. There is a new OpenSource sound driver called ALSA which is
|
||||
currently under development: http://www.alsa-project.org/
|
||||
The ALSA drivers support some newer hardware that may not
|
||||
be supported by this sound driver and also provide some
|
||||
additional features.
|
||||
|
||||
2. The commercial OSS driver may be obtained from the site:
|
||||
http://www.opensound.com. This may be used for cards that
|
||||
are unsupported by the kernel driver, or may be used
|
||||
by other operating systems.
|
||||
|
||||
3. The enlightenment sound daemon may be used for playing
|
||||
multiple sounds at the same time via a single card, eliminating
|
||||
some of the requirements for multiple sound card systems. For
|
||||
more information, see: http://www.tux.org/~ricdude/EsounD.html
|
||||
The "esd" program may be used with the real-player and mpeg
|
||||
players like mpg123 and x11amp. The newer real-player
|
||||
and some games even include built-in support for ESD!
|
||||
|
||||
|
||||
Building the Modules:
|
||||
=====================
|
||||
|
||||
This document does not provide full details on building the
|
||||
kernel, etc. The notes below apply only to making the kernel
|
||||
sound modules. If this conflicts with the kernel's README,
|
||||
the README takes precedence.
|
||||
|
||||
1. To make the kernel sound modules, cd to your /usr/src/linux
|
||||
directory (typically) and type make config, make menuconfig,
|
||||
or make xconfig (to start the command line, dialog, or x-based
|
||||
configuration tool).
|
||||
|
||||
2. Select the Sound option and a dialog will be displayed.
|
||||
|
||||
3. Select M (module) for "Sound card support".
|
||||
|
||||
4. Select your sound driver(s) as a module. For ProAudio, Sound
|
||||
Blaster, etc., select M (module) for OSS sound modules.
|
||||
[thanks to Marvin Stodolsky <stodolsk@erols.com>]A
|
||||
|
||||
5. Make the kernel (e.g., make bzImage), and install the kernel.
|
||||
|
||||
6. Make the modules and install them (make modules; make modules_install).
|
||||
|
||||
Note, for 2.5.x kernels, make sure you have the newer module-init-tools
|
||||
installed or modules will not be loaded properly. 2.5.x requires an
|
||||
updated module-init-tools.
|
||||
|
||||
|
||||
Plug and Play (PnP:
|
||||
===================
|
||||
|
||||
If the sound card is an ISA PnP card, isapnp may be used
|
||||
to configure the card. See the file isapnp.txt in the
|
||||
directory one level up (e.g., /usr/src/linux/Documentation).
|
||||
|
||||
Also the 2.4.x kernels provide PnP capabilities, see the
|
||||
file NEWS in this directory.
|
||||
|
||||
PCI sound cards are highly recommended, as they are far
|
||||
easier to configure and from what I have read, they use
|
||||
less resources and are more CPU efficient.
|
||||
|
||||
|
||||
INSMOD:
|
||||
=======
|
||||
|
||||
If loading via insmod, the common modules must be loaded in the
|
||||
order below BEFORE loading the other sound modules. The card-specific
|
||||
modules may then be loaded (most require parameters). For example,
|
||||
I use the following via a shell script to load my SoundBlaster:
|
||||
|
||||
SB_BASE=0x240
|
||||
SB_IRQ=9
|
||||
SB_DMA=3
|
||||
SB_DMA2=5
|
||||
SB_MPU=0x300
|
||||
#
|
||||
echo Starting sound
|
||||
/sbin/insmod soundcore
|
||||
/sbin/insmod sound
|
||||
#
|
||||
echo Starting sound blaster....
|
||||
/sbin/insmod uart401
|
||||
/sbin/insmod sb io=$SB_BASE irq=$SB_IRQ dma=$SB_DMA dma16=$SB_DMA2 mpu_io=$SB_MP
|
||||
|
||||
When using sound as a module, I typically put these commands
|
||||
in a file such as /root/soundon.sh.
|
||||
|
||||
|
||||
MODPROBE:
|
||||
=========
|
||||
|
||||
If loading via modprobe, these common files are automatically loaded when
|
||||
requested by modprobe. For example, my /etc/modprobe.d/oss.conf contains:
|
||||
|
||||
alias sound sb
|
||||
options sb io=0x240 irq=9 dma=3 dma16=5 mpu_io=0x300
|
||||
|
||||
All you need to do to load the module is:
|
||||
|
||||
/sbin/modprobe sb
|
||||
|
||||
|
||||
Sound Status:
|
||||
=============
|
||||
|
||||
The status of sound may be read/checked by:
|
||||
cat (anyfile).au >/dev/audio
|
||||
|
||||
[WWH: This may not work properly for SoundBlaster PCI 128 cards
|
||||
such as the es1370/1 (see the es1370/1 files in this directory)
|
||||
as they do not automatically support uLaw on /dev/audio.]
|
||||
|
||||
The status of the modules and which modules depend on
|
||||
which other modules may be checked by:
|
||||
/sbin/lsmod
|
||||
|
||||
/sbin/lsmod should show something like the following:
|
||||
sb 26280 0
|
||||
uart401 5640 0 [sb]
|
||||
sound 57112 0 [sb uart401]
|
||||
soundcore 1968 8 [sb sound]
|
||||
|
||||
|
||||
Removing Sound:
|
||||
===============
|
||||
|
||||
Sound may be removed by using /sbin/rmmod in the reverse order
|
||||
in which you load the modules. Note, if a program has a sound device
|
||||
open (e.g., xmixer), that module (and the modules on which it
|
||||
depends) may not be unloaded.
|
||||
|
||||
For example, I use the following to remove my Soundblaster (rmmod
|
||||
in the reverse order in which I loaded the modules):
|
||||
|
||||
/sbin/rmmod sb
|
||||
/sbin/rmmod uart401
|
||||
/sbin/rmmod sound
|
||||
/sbin/rmmod soundcore
|
||||
|
||||
When using sound as a module, I typically put these commands
|
||||
in a script such as /root/soundoff.sh.
|
||||
|
||||
|
||||
Removing Sound for use with OSS:
|
||||
================================
|
||||
|
||||
If you get really stuck or have a card that the kernel modules
|
||||
will not support, you can get a commercial sound driver from
|
||||
http://www.opensound.com. Before loading the commercial sound
|
||||
driver, you should do the following:
|
||||
|
||||
1. remove sound modules (detailed above)
|
||||
2. remove the sound modules from /etc/modprobe.d/*.conf
|
||||
3. move the sound modules from /lib/modules/<kernel>/misc
|
||||
(for example, I make a /lib/modules/<kernel>/misc/tmp
|
||||
directory and copy the sound module files to that
|
||||
directory).
|
||||
|
||||
|
||||
Multiple Sound Cards:
|
||||
=====================
|
||||
|
||||
The sound drivers will support multiple sound cards and there
|
||||
are some great applications like multitrack that support them.
|
||||
Typically, you need two sound cards of different types. Note, this
|
||||
uses more precious interrupts and DMA channels and sometimes
|
||||
can be a configuration nightmare. I have heard reports of 3-4
|
||||
sound cards (typically I only use 2). You can sometimes use
|
||||
multiple PCI sound cards of the same type.
|
||||
|
||||
On my machine I have two sound cards (cs4232 and Soundblaster Vibra
|
||||
16). By loading sound as modules, I can control which is the first
|
||||
sound device (/dev/dsp, /dev/audio, /dev/mixer) and which is
|
||||
the second. Normally, the cs4232 (Dell sound on the motherboard)
|
||||
would be the first sound device, but I prefer the Soundblaster.
|
||||
All you have to do is to load the one you want as /dev/dsp
|
||||
first (in my case "sb") and then load the other one
|
||||
(in my case "cs4232").
|
||||
|
||||
If you have two cards of the same type that are jumpered
|
||||
cards or different PnP revisions, you may load the same
|
||||
module twice. For example, I have a SoundBlaster vibra 16
|
||||
and an older SoundBlaster 16 (jumpers). To load the module
|
||||
twice, you need to do the following:
|
||||
|
||||
1. Copy the sound modules to a new name. For example
|
||||
sb.o could be copied (or symlinked) to sb1.o for the
|
||||
second SoundBlaster.
|
||||
|
||||
2. Make a second entry in /etc/modprobe.d/*conf, for example,
|
||||
sound1 or sb1. This second entry should refer to the
|
||||
new module names for example sb1, and should include
|
||||
the I/O, etc. for the second sound card.
|
||||
|
||||
3. Update your soundon.sh script, etc.
|
||||
|
||||
Warning: I have never been able to get two PnP sound cards of the
|
||||
same type to load at the same time. I have tried this several times
|
||||
with the Soundblaster Vibra 16 cards. OSS has indicated that this
|
||||
is a PnP problem.... If anyone has any luck doing this, please
|
||||
send me an E-MAIL. PCI sound cards should not have this problem.a
|
||||
Since this was originally release, I have received a couple of
|
||||
mails from people who have accomplished this!
|
||||
|
||||
NOTE: In Linux 2.4 the Sound Blaster driver (and only this one yet)
|
||||
supports multiple cards with one module by default.
|
||||
Read the file 'Soundblaster' in this directory for details.
|
||||
|
||||
|
||||
Sound Problems:
|
||||
===============
|
||||
|
||||
First RTFM (including the troubleshooting section
|
||||
in the Sound-HOWTO).
|
||||
|
||||
1) If you are having problems loading the modules (for
|
||||
example, if you get device conflict errors) try the
|
||||
following:
|
||||
|
||||
A) If you have Win95 or NT on the same computer,
|
||||
write down what addresses, IRQ, and DMA channels
|
||||
those were using for the same hardware. You probably
|
||||
can use these addresses, IRQs, and DMA channels.
|
||||
You should really do this BEFORE attempting to get
|
||||
sound working!
|
||||
|
||||
B) Check (cat) /proc/interrupts, /proc/ioports,
|
||||
and /proc/dma. Are you trying to use an address,
|
||||
IRQ or DMA port that another device is using?
|
||||
|
||||
C) Check (cat) /proc/isapnp
|
||||
|
||||
D) Inspect your /var/log/messages file. Often that will
|
||||
indicate what IRQ or IO port could not be obtained.
|
||||
|
||||
E) Try another port or IRQ. Note this may involve
|
||||
using the PnP tools to move the sound card to
|
||||
another location. Sometimes this is the only way
|
||||
and it is more or less trial and error.
|
||||
|
||||
2) If you get motor-boating (the same sound or part of a
|
||||
sound clip repeated), you probably have either an IRQ
|
||||
or DMA conflict. Move the card to another IRQ or DMA
|
||||
port. This has happened to me when playing long files
|
||||
when I had an IRQ conflict.
|
||||
|
||||
3. If you get dropouts or pauses when playing high sample
|
||||
rate files such as using mpg123 or x11amp/xmms, you may
|
||||
have too slow of a CPU and may have to use the options to
|
||||
play the files at 1/2 speed. For example, you may use
|
||||
the -2 or -4 option on mpg123. You may also get this
|
||||
when trying to play mpeg files stored on a CD-ROM
|
||||
(my Toshiba T8000 PII/366 sometimes has this problem).
|
||||
|
||||
4. If you get "cannot access device" errors, your /dev/dsp
|
||||
files, etc. may be set to owner root, mode 600. You
|
||||
may have to use the command:
|
||||
chmod 666 /dev/dsp /dev/mixer /dev/audio
|
||||
|
||||
5. If you get "device busy" errors, another program has the
|
||||
sound device open. For example, if using the Enlightenment
|
||||
sound daemon "esd", the "esd" program has the sound device.
|
||||
If using "esd", please RTFM the docs on ESD. For example,
|
||||
esddsp <program> may be used to play files via a non-esd
|
||||
aware program.
|
||||
|
||||
6) Ask for help on the sound list or send E-MAIL to the
|
||||
sound driver author/maintainer.
|
||||
|
||||
7) Turn on debug in drivers/sound/sound_config.h (DEB, DDB, MDB).
|
||||
|
||||
8) If the system reports insufficient DMA memory then you may want to
|
||||
load sound with the "dmabufs=1" option. Or in /etc/conf.modules add
|
||||
|
||||
preinstall sound dmabufs=1
|
||||
|
||||
This makes the sound system allocate its buffers and hang onto them.
|
||||
|
||||
You may also set persistent DMA when building a 2.4.x kernel.
|
||||
|
||||
|
||||
Configuring Sound:
|
||||
==================
|
||||
|
||||
There are several ways of configuring your sound:
|
||||
|
||||
1) On the kernel command line (when using the sound driver(s)
|
||||
compiled in the kernel). Check the driver source and
|
||||
documentation for details.
|
||||
|
||||
2) On the command line when using insmod or in a bash script
|
||||
using command line calls to load sound.
|
||||
|
||||
3) In /etc/modprobe.d/*conf when using modprobe.
|
||||
|
||||
4) Via Red Hat's GPL'd /usr/sbin/sndconfig program (text based).
|
||||
|
||||
5) Via the OSS soundconf program (with the commercial version
|
||||
of the OSS driver.
|
||||
|
||||
6) By just loading the module and let isapnp do everything relevant
|
||||
for you. This works only with a few drivers yet and - of course -
|
||||
only with isapnp hardware.
|
||||
|
||||
And I am sure, several other ways.
|
||||
|
||||
Anyone want to write a linuxconf module for configuring sound?
|
||||
|
||||
|
||||
Module Loading:
|
||||
===============
|
||||
|
||||
When a sound card is first referenced and sound is modular, the sound system
|
||||
will ask for the sound devices to be loaded. Initially it requests that
|
||||
the driver for the sound system is loaded. It then will ask for
|
||||
sound-slot-0, where 0 is the first sound card. (sound-slot-1 the second and
|
||||
so on). Thus you can do
|
||||
|
||||
alias sound-slot-0 sb
|
||||
|
||||
To load a soundblaster at this point. If the slot loading does not provide
|
||||
the desired device - for example a soundblaster does not directly provide
|
||||
a midi synth in all cases then it will request "sound-service-0-n" where n
|
||||
is
|
||||
|
||||
0 Mixer
|
||||
|
||||
2 MIDI
|
||||
|
||||
3, 4 DSP audio
|
||||
|
||||
|
||||
For example, I use the following to load my Soundblaster PCI 128
|
||||
(ES 1371) card first, followed by my SoundBlaster Vibra 16 card,
|
||||
then by my TV card:
|
||||
|
||||
# Load the Soundblaster PCI 128 as /dev/dsp, /dev/dsp1, /dev/mixer
|
||||
alias sound-slot-0 es1371
|
||||
|
||||
# Load the Soundblaster Vibra 16 as /dev/dsp2, /dev/mixer1
|
||||
alias sound-slot-1 sb
|
||||
options sb io=0x240 irq=5 dma=1 dma16=5 mpu_io=0x330
|
||||
|
||||
# Load the BTTV (TV card) as /dev/mixer2
|
||||
alias sound-slot-2 bttv
|
||||
alias sound-service-2-0 tvmixer
|
||||
|
||||
pre-install bttv modprobe tuner ; modprobe tvmixer
|
||||
pre-install tvmixer modprobe msp3400; modprobe tvaudio
|
||||
options tuner debug=0 type=8
|
||||
options bttv card=0 radio=0 pll=0
|
||||
|
||||
|
||||
For More Information (RTFM):
|
||||
============================
|
||||
1) Information on kernel modules: manual pages for insmod and modprobe.
|
||||
|
||||
2) Information on PnP, RTFM manual pages for isapnp.
|
||||
|
||||
3) Sound-HOWTO and Sound-Playing-HOWTO.
|
||||
|
||||
4) OSS's WWW site at http://www.opensound.com.
|
||||
|
||||
5) All the files in Documentation/sound.
|
||||
|
||||
6) The comments and code in linux/drivers/sound.
|
||||
|
||||
7) The sndconfig and rhsound documentation from Red Hat.
|
||||
|
||||
8) The Linux-sound mailing list: sound-list@redhat.com.
|
||||
|
||||
9) Enlightenment documentation (for info on esd)
|
||||
http://www.tux.org/~ricdude/EsounD.html.
|
||||
|
||||
10) ALSA home page: http://www.alsa-project.org/
|
||||
|
||||
|
||||
Contact Information:
|
||||
====================
|
||||
Wade Hampton: (whampton@staffnet.com)
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +0,0 @@
|
|||
A pure OPL3 card is nice and easy to configure. Simply do
|
||||
|
||||
insmod opl3 io=0x388
|
||||
|
||||
Change the I/O address in the very unlikely case this card is differently
|
||||
configured
|
|
@ -1,218 +0,0 @@
|
|||
Support for the OPTi 82C931 chip
|
||||
--------------------------------
|
||||
Note: parts of this README file apply also to other
|
||||
cards that use the mad16 driver.
|
||||
|
||||
Some items in this README file are based on features
|
||||
added to the sound driver after Linux-2.1.91 was out.
|
||||
By the time of writing this I do not know which official
|
||||
kernel release will include these features.
|
||||
Please do not report inconsistencies on older Linux
|
||||
kernels.
|
||||
|
||||
The OPTi 82C931 is supported in its non-PnP mode.
|
||||
Usually you do not need to set jumpers, etc. The sound driver
|
||||
will check the card status and if it is required it will
|
||||
force the card into a mode in which it can be programmed.
|
||||
|
||||
If you have another OS installed on your computer it is recommended
|
||||
that Linux and the other OS use the same resources.
|
||||
|
||||
Also, it is recommended that resources specified in /etc/modprobe.d/*.conf
|
||||
and resources specified in /etc/isapnp.conf agree.
|
||||
|
||||
Compiling the sound driver
|
||||
--------------------------
|
||||
I highly recommend that you build a modularized sound driver.
|
||||
This document does not cover a sound-driver which is built in
|
||||
the kernel.
|
||||
|
||||
Sound card support should be enabled as a module (chose m).
|
||||
Answer 'm' for these items:
|
||||
Generic OPL2/OPL3 FM synthesizer support (CONFIG_SOUND_ADLIB)
|
||||
Microsoft Sound System support (CONFIG_SOUND_MSS)
|
||||
Support for OPTi MAD16 and/or Mozart based cards (CONFIG_SOUND_MAD16)
|
||||
FM synthesizer (YM3812/OPL-3) support (CONFIG_SOUND_YM3812)
|
||||
|
||||
The configuration menu may ask for addresses, IRQ lines or DMA
|
||||
channels. If the card is used as a module the module loading
|
||||
options will override these values.
|
||||
|
||||
For the OPTi 931 you can answer 'n' to:
|
||||
Support MIDI in older MAD16 based cards (requires SB) (CONFIG_SOUND_MAD16_OLDCARD)
|
||||
If you do need MIDI support in a Mozart or C928 based card you
|
||||
need to answer 'm' to the above question. In that case you will
|
||||
also need to answer 'm' to:
|
||||
'100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' (CONFIG_SOUND_SB)
|
||||
|
||||
Go on and compile your kernel and modules. Install the modules. Run depmod -a.
|
||||
|
||||
Using isapnptools
|
||||
-----------------
|
||||
In most systems with a PnP BIOS you do not need to use isapnp. The
|
||||
initialization provided by the BIOS is sufficient for the driver
|
||||
to pick up the card and continue initialization.
|
||||
|
||||
If that fails, or if you have other PnP cards, you need to use isapnp
|
||||
to initialize the card.
|
||||
This was tested with isapnptools-1.11 but I recommend that you use
|
||||
isapnptools-1.13 (or newer). Run pnpdump to dump the information
|
||||
about your PnP cards. Then edit the resulting file and select
|
||||
the options of your choice. This file is normally installed as
|
||||
/etc/isapnp.conf.
|
||||
|
||||
The driver has one limitation with respect to I/O port resources:
|
||||
IO3 base must be 0x0E0C. Although isapnp allows other ports, this
|
||||
address is hard-coded into the driver.
|
||||
|
||||
Using kmod and autoloading the sound driver
|
||||
-------------------------------------------
|
||||
Config files in '/etc/modprobe.d/' are used as below:
|
||||
|
||||
alias mixer0 mad16
|
||||
alias audio0 mad16
|
||||
alias midi0 mad16
|
||||
alias synth0 opl3
|
||||
options sb mad16=1
|
||||
options mad16 irq=10 dma=0 dma16=1 io=0x530 joystick=1 cdtype=0
|
||||
options opl3 io=0x388
|
||||
install mad16 /sbin/modprobe -i mad16 && /sbin/ad1848_mixer_reroute 14 8 15 3 16 6
|
||||
|
||||
If you have an MPU daughtercard or onboard MPU you will want to add to the
|
||||
"options mad16" line - eg
|
||||
|
||||
options mad16 irq=5 dma=0 dma16=3 io=0x530 mpu_io=0x330 mpu_irq=9
|
||||
|
||||
To set the I/O and IRQ of the MPU.
|
||||
|
||||
|
||||
Explain:
|
||||
|
||||
alias mixer0 mad16
|
||||
alias audio0 mad16
|
||||
alias midi0 mad16
|
||||
alias synth0 opl3
|
||||
|
||||
When any sound device is opened the kernel requests auto-loading
|
||||
of char-major-14. There is a built-in alias that translates this
|
||||
request to loading the main sound module.
|
||||
|
||||
The sound module in its turn will request loading of a sub-driver
|
||||
for mixer, audio, midi or synthesizer device. The first 3 are
|
||||
supported by the mad16 driver. The synth device is supported
|
||||
by the opl3 driver.
|
||||
|
||||
There is currently no way to autoload the sound device driver
|
||||
if more than one card is installed.
|
||||
|
||||
options sb mad16=1
|
||||
|
||||
This is left for historical reasons. If you enable the
|
||||
config option 'Support MIDI in older MAD16 based cards (requires SB)'
|
||||
or if you use an older mad16 driver it will force loading of the
|
||||
SoundBlaster driver. This option tells the SB driver not to look
|
||||
for a SB card but to wait for the mad16 driver.
|
||||
|
||||
options mad16 irq=10 dma=0 dma16=1 io=0x530 joystick=1 cdtype=0
|
||||
options opl3 io=0x388
|
||||
|
||||
post-install mad16 /sbin/ad1848_mixer_reroute 14 8 15 3 16 6
|
||||
|
||||
This sets resources and options for the mad16 and opl3 drivers.
|
||||
I use two DMA channels (only one is required) to enable full duplex.
|
||||
joystick=1 enables the joystick port. cdtype=0 disables the cd port.
|
||||
You can also set mpu_io and mpu_irq in the mad16 options for the
|
||||
uart401 driver.
|
||||
|
||||
This tells modprobe to run /sbin/ad1848_mixer_reroute after
|
||||
mad16 is successfully loaded and initialized. The source
|
||||
for ad1848_mixer_reroute is appended to the end of this readme
|
||||
file. It is impossible for the sound driver to know the actual
|
||||
connections to the mixer. The 3 inputs intended for cd, synth
|
||||
and line-in are mapped to the generic inputs line1, line2 and
|
||||
line3. This program reroutes these mixer channels to their
|
||||
right names (note the right mapping depends on the actual sound
|
||||
card that you use).
|
||||
The numeric parameters mean:
|
||||
14=line1 8=cd - reroute line1 to the CD input.
|
||||
15=line2 3=synth - reroute line2 to the synthesizer input.
|
||||
16=line3 6=line - reroute line3 to the line input.
|
||||
For reference on other input names look at the file
|
||||
/usr/include/linux/soundcard.h.
|
||||
|
||||
Using a joystick
|
||||
-----------------
|
||||
You must enable a joystick in the mad16 options. (also
|
||||
in /etc/isapnp.conf if you use it).
|
||||
Tested with regular analog joysticks.
|
||||
|
||||
A CDROM drive connected to the sound card
|
||||
-----------------------------------------
|
||||
The 82C931 chip has support only for secondary ATAPI cdrom.
|
||||
(cdtype=8). Loading the mad16 driver resets the C931 chip
|
||||
and if a cdrom was already mounted it may cause a complete
|
||||
system hang. Do not use the sound card if you have an alternative.
|
||||
If you do use the sound card it is important that you load
|
||||
the mad16 driver (use "modprobe mad16" to prevent auto-unloading)
|
||||
before the cdrom is accessed the first time.
|
||||
|
||||
Using the sound driver built-in to the kernel may help here, but...
|
||||
Most new systems have a PnP BIOS and also two IDE controllers.
|
||||
The IDE controller on the sound card may be needed only on older
|
||||
systems (which have only one IDE controller) but these systems
|
||||
also do not have a PnP BIOS - requiring isapnptools and a modularized
|
||||
driver.
|
||||
|
||||
Known problems
|
||||
--------------
|
||||
1. See the section on "A CDROM drive connected to the sound card".
|
||||
|
||||
2. On my system the codec cannot capture companded sound samples.
|
||||
(eg., recording from /dev/audio). When any companded capture is
|
||||
requested I get stereo-16 bit samples instead. Playback of
|
||||
companded samples works well. Apparently this problem is not common
|
||||
to all C931 based cards. I do not know how to identify cards that
|
||||
have this problem.
|
||||
|
||||
Source for ad1848_mixer_reroute.c
|
||||
---------------------------------
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/soundcard.h>
|
||||
|
||||
static char *mixer_names[SOUND_MIXER_NRDEVICES] =
|
||||
SOUND_DEVICE_LABELS;
|
||||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
int val, from, to;
|
||||
int i, fd;
|
||||
|
||||
fd = open("/dev/mixer", O_RDWR);
|
||||
if(fd < 0) {
|
||||
perror("/dev/mixer");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(i = 2; i < argc; i += 2) {
|
||||
from = atoi(argv[i-1]);
|
||||
to = atoi(argv[i]);
|
||||
|
||||
if(to == SOUND_MIXER_NONE)
|
||||
fprintf(stderr, "%s: turning off mixer %s\n",
|
||||
argv[0], mixer_names[to]);
|
||||
else
|
||||
fprintf(stderr, "%s: rerouting mixer %s to %s\n",
|
||||
argv[0], mixer_names[from], mixer_names[to]);
|
||||
|
||||
val = from << 8 | to;
|
||||
|
||||
if(ioctl(fd, SOUND_MIXER_PRIVATE2, &val)) {
|
||||
perror("AD1848 mixer reroute");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,162 +0,0 @@
|
|||
Pro Audio Spectrum 16 for 2.3.99 and later
|
||||
=========================================
|
||||
by Thomas Molina (tmolina@home.com)
|
||||
last modified 3 Mar 2001
|
||||
Acknowledgement to Axel Boldt (boldt@math.ucsb.edu) for stuff taken
|
||||
from Configure.help, Riccardo Facchetti for stuff from README.OSS,
|
||||
and others whose names I could not find.
|
||||
|
||||
This documentation is relevant for the PAS16 driver (pas2_card.c and
|
||||
friends) under kernel version 2.3.99 and later. If you are
|
||||
unfamiliar with configuring sound under Linux, please read the
|
||||
Sound-HOWTO, Documentation/sound/oss/Introduction and other
|
||||
relevant docs first.
|
||||
|
||||
The following information is relevant information from README.OSS
|
||||
and legacy docs for the Pro Audio Spectrum 16 (PAS16):
|
||||
==================================================================
|
||||
|
||||
The pas2_card.c driver supports the following cards --
|
||||
Pro Audio Spectrum 16 (PAS16) and compatibles:
|
||||
Pro Audio Spectrum 16
|
||||
Pro Audio Studio 16
|
||||
Logitech Sound Man 16
|
||||
NOTE! The original Pro Audio Spectrum as well as the PAS+ are not
|
||||
and will not be supported by the driver.
|
||||
|
||||
The sound driver configuration dialog
|
||||
-------------------------------------
|
||||
|
||||
Sound configuration starts by making some yes/no questions. Be careful
|
||||
when answering to these questions since answering y to a question may
|
||||
prevent some later ones from being asked. For example don't answer y to
|
||||
the question about (PAS16) if you don't really have a PAS16. Sound
|
||||
configuration may also be made modular by answering m to configuration
|
||||
options presented.
|
||||
|
||||
Note also that all questions may not be asked. The configuration program
|
||||
may disable some questions depending on the earlier choices. It may also
|
||||
select some options automatically as well.
|
||||
|
||||
"ProAudioSpectrum 16 support",
|
||||
- Answer 'y'_ONLY_ if you have a Pro Audio Spectrum _16_,
|
||||
Pro Audio Studio 16 or Logitech SoundMan 16 (be sure that
|
||||
you read the above list correctly). Don't answer 'y' if you
|
||||
have some other card made by Media Vision or Logitech since they
|
||||
are not PAS16 compatible.
|
||||
NOTE! Since 3.5-beta10 you need to enable SB support (next question)
|
||||
if you want to use the SB emulation of PAS16. It's also possible to
|
||||
the emulation if you want to use a true SB card together with PAS16
|
||||
(there is another question about this that is asked later).
|
||||
|
||||
"Generic OPL2/OPL3 FM synthesizer support",
|
||||
- Answer 'y' if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
|
||||
The PAS16 has an OPL3-compatible FM chip.
|
||||
|
||||
With PAS16 you can use two audio device files at the same time. /dev/dsp (and
|
||||
/dev/audio) is connected to the 8/16 bit native codec and the /dev/dsp1 (and
|
||||
/dev/audio1) is connected to the SB emulation (8 bit mono only).
|
||||
|
||||
|
||||
The new stuff for 2.3.99 and later
|
||||
============================================================================
|
||||
The following configuration options are relevant to configuring the PAS16:
|
||||
|
||||
Sound card support
|
||||
CONFIG_SOUND
|
||||
If you have a sound card in your computer, i.e. if it can say more
|
||||
than an occasional beep, say Y. Be sure to have all the information
|
||||
about your sound card and its configuration down (I/O port,
|
||||
interrupt and DMA channel), because you will be asked for it.
|
||||
|
||||
You want to read the Sound-HOWTO, available from
|
||||
http://www.tldp.org/docs.html#howto . General information
|
||||
about the modular sound system is contained in the files
|
||||
Documentation/sound/oss/Introduction. The file
|
||||
Documentation/sound/oss/README.OSS contains some slightly outdated but
|
||||
still useful information as well.
|
||||
|
||||
OSS sound modules
|
||||
CONFIG_SOUND_OSS
|
||||
OSS is the Open Sound System suite of sound card drivers. They make
|
||||
sound programming easier since they provide a common API. Say Y or M
|
||||
here (the module will be called sound.o) if you haven't found a
|
||||
driver for your sound card above, then pick your driver from the
|
||||
list below.
|
||||
|
||||
Persistent DMA buffers
|
||||
CONFIG_SOUND_DMAP
|
||||
Linux can often have problems allocating DMA buffers for ISA sound
|
||||
cards on machines with more than 16MB of RAM. This is because ISA
|
||||
DMA buffers must exist below the 16MB boundary and it is quite
|
||||
possible that a large enough free block in this region cannot be
|
||||
found after the machine has been running for a while. If you say Y
|
||||
here the DMA buffers (64Kb) will be allocated at boot time and kept
|
||||
until the shutdown. This option is only useful if you said Y to
|
||||
"OSS sound modules", above. If you said M to "OSS sound modules"
|
||||
then you can get the persistent DMA buffer functionality by passing
|
||||
the command-line argument "dmabuf=1" to the sound.o module.
|
||||
|
||||
Say y here for PAS16.
|
||||
|
||||
ProAudioSpectrum 16 support
|
||||
CONFIG_SOUND_PAS
|
||||
Answer Y only if you have a Pro Audio Spectrum 16, ProAudio Studio
|
||||
16 or Logitech SoundMan 16 sound card. Don't answer Y if you have
|
||||
some other card made by Media Vision or Logitech since they are not
|
||||
PAS16 compatible. It is not necessary to enable the separate
|
||||
Sound Blaster support; it is included in the PAS driver.
|
||||
|
||||
If you compile the driver into the kernel, you have to add
|
||||
"pas2=<io>,<irq>,<dma>,<dma2>,<sbio>,<sbirq>,<sbdma>,<sbdma2>
|
||||
to the kernel command line.
|
||||
|
||||
FM Synthesizer (YM3812/OPL-3) support
|
||||
CONFIG_SOUND_YM3812
|
||||
Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
|
||||
Answering Y is usually a safe and recommended choice, however some
|
||||
cards may have software (TSR) FM emulation. Enabling FM support with
|
||||
these cards may cause trouble (I don't currently know of any such
|
||||
cards, however).
|
||||
Please read the file Documentation/sound/oss/OPL3 if your card has an
|
||||
OPL3 chip.
|
||||
If you compile the driver into the kernel, you have to add
|
||||
"opl3=<io>" to the kernel command line.
|
||||
|
||||
If you compile your drivers into the kernel, you MUST configure
|
||||
OPL3 support as a module for PAS16 support to work properly.
|
||||
You can then get OPL3 functionality by issuing the command:
|
||||
insmod opl3
|
||||
In addition, you must either add the following line to
|
||||
/etc/modprobe.d/*.conf:
|
||||
options opl3 io=0x388
|
||||
or else add the following line to /etc/lilo.conf:
|
||||
opl3=0x388
|
||||
|
||||
|
||||
EXAMPLES
|
||||
===================================================================
|
||||
To use the PAS16 in my computer I have enabled the following sound
|
||||
configuration options:
|
||||
|
||||
CONFIG_SOUND=y
|
||||
CONFIG_SOUND_OSS=y
|
||||
CONFIG_SOUND_TRACEINIT=y
|
||||
CONFIG_SOUND_DMAP=y
|
||||
CONFIG_SOUND_PAS=y
|
||||
CONFIG_SOUND_SB=n
|
||||
CONFIG_SOUND_YM3812=m
|
||||
|
||||
I have also included the following append line in /etc/lilo.conf:
|
||||
append="pas2=0x388,10,3,-1,0x220,5,1,-1 sb=0x220,5,1,-1 opl3=0x388"
|
||||
|
||||
The io address of 0x388 is default configuration on the PAS16. The
|
||||
irq of 10 and dma of 3 may not match your installation. The above
|
||||
configuration enables PAS16, 8-bit Soundblaster and OPL3
|
||||
functionality. If Soundblaster functionality is not desired, the
|
||||
following line would be appropriate:
|
||||
append="pas2=0x388,10,3,-1,0,-1,-1,-1 opl3=0x388"
|
||||
|
||||
If sound is built totally modular, the above options may be
|
||||
specified in /etc/modprobe.d/*.conf for pas2, sb and opl3
|
||||
respectively.
|
|
@ -1,41 +0,0 @@
|
|||
The PSS cards and other ECHO based cards provide an onboard DSP with
|
||||
downloadable programs and also has an AD1848 "Microsoft Sound System"
|
||||
device. The PSS driver enables MSS and MPU401 modes of the card. SB
|
||||
is not enabled since it doesn't work concurrently with MSS.
|
||||
|
||||
If you build this driver as a module then the driver takes the following
|
||||
parameters
|
||||
|
||||
pss_io. The I/O base the PSS card is configured at (normally 0x220
|
||||
or 0x240)
|
||||
|
||||
mss_io The base address of the Microsoft Sound System interface.
|
||||
This is normally 0x530, but may be 0x604 or other addresses.
|
||||
|
||||
mss_irq The interrupt assigned to the Microsoft Sound System
|
||||
emulation. IRQ's 3,5,7,9,10,11 and 12 are available. If you
|
||||
get IRQ errors be sure to check the interrupt is set to
|
||||
"ISA/Legacy" in the BIOS on modern machines.
|
||||
|
||||
mss_dma The DMA channel used by the Microsoft Sound System.
|
||||
This can be 0, 1, or 3. DMA 0 is not available on older
|
||||
machines and will cause a crash on them.
|
||||
|
||||
mpu_io The MPU emulation base address. This sets the base of the
|
||||
synthesizer. It is typically 0x330 but can be altered.
|
||||
|
||||
mpu_irq The interrupt to use for the synthesizer. It must differ
|
||||
from the IRQ used by the Microsoft Sound System port.
|
||||
|
||||
|
||||
The mpu_io/mpu_irq fields are optional. If they are not specified the
|
||||
synthesizer parts are not configured.
|
||||
|
||||
When the module is loaded it looks for a file called
|
||||
/etc/sound/pss_synth. This is the firmware file from the DOS install disks.
|
||||
This fil holds a general MIDI emulation. The file expected is called
|
||||
genmidi.ld on newer DOS driver install disks and synth.ld on older ones.
|
||||
|
||||
You can also load alternative DSP algorithms into the card if you wish. One
|
||||
alternative driver can be found at http://www.mpg123.de/
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
This file contains notes for users of PSS sound cards who wish to use the
|
||||
newly added features of the newest version of this driver.
|
||||
|
||||
The major enhancements present in this new revision of this driver is the
|
||||
addition of two new module parameters that allow you to take full advantage of
|
||||
all the features present on your PSS sound card. These features include the
|
||||
ability to enable both the builtin CDROM and joystick ports.
|
||||
|
||||
pss_enable_joystick
|
||||
|
||||
This parameter is basically a flag. A 0 will leave the joystick port
|
||||
disabled, while a non-zero value would enable the joystick port. The default
|
||||
setting is pss_enable_joystick=0 as this keeps this driver fully compatible
|
||||
with systems that were using previous versions of this driver. If you wish to
|
||||
enable the joystick port you will have to add pss_enable_joystick=1 as an
|
||||
argument to the driver. To actually use the joystick port you will then have
|
||||
to load the joystick driver itself. Just remember to load the joystick driver
|
||||
AFTER the pss sound driver.
|
||||
|
||||
pss_cdrom_port
|
||||
|
||||
This parameter takes a port address as its parameter. Any available port
|
||||
address can be specified to enable the CDROM port, except for 0x0 and -1 as
|
||||
these values would leave the port disabled. Like the joystick port, the cdrom
|
||||
port will require that an appropriate CDROM driver be loaded before you can make
|
||||
use of the newly enabled CDROM port. Like the joystick port option above,
|
||||
remember to load the CDROM driver AFTER the pss sound driver. While it may
|
||||
differ on some PSS sound cards, all the PSS sound cards that I have seen have a
|
||||
builtin Wearnes CDROM port. If this is the case with your PSS sound card you
|
||||
should load aztcd with the appropriate port option that matches the port you
|
||||
assigned to the CDROM port when you loaded your pss sound driver. (ex.
|
||||
modprobe pss pss_cdrom_port=0x340 && modprobe aztcd aztcd=0x340) The default
|
||||
setting of this parameter leaves the CDROM port disabled to maintain full
|
||||
compatibility with systems using previous versions of this driver.
|
||||
|
||||
Other options have also been added for the added convenience and utility
|
||||
of the user. These options are only available if this driver is loaded as a
|
||||
module.
|
||||
|
||||
pss_no_sound
|
||||
|
||||
This module parameter is a flag that can be used to tell the driver to
|
||||
just configure non-sound components. 0 configures all components, a non-0
|
||||
value will only attempt to configure the CDROM and joystick ports. This
|
||||
parameter can be used by a user who only wished to use the builtin joystick
|
||||
and/or CDROM port(s) of his PSS sound card. If this driver is loaded with this
|
||||
parameter and with the parameter below set to true then a user can safely unload
|
||||
this driver with the following command "rmmod pss && rmmod ad1848 && rmmod
|
||||
mpu401 && rmmod sound && rmmod soundcore" and retain the full functionality of
|
||||
his CDROM and/or joystick port(s) while gaining back the memory previously used
|
||||
by the sound drivers. This default setting of this parameter is 0 to retain
|
||||
full behavioral compatibility with previous versions of this driver.
|
||||
|
||||
pss_keep_settings
|
||||
|
||||
This parameter can be used to specify whether you want the driver to reset
|
||||
all emulations whenever its unloaded. This can be useful for those who are
|
||||
sharing resources (io ports, IRQ's, DMA's) between different ISA cards. This
|
||||
flag can also be useful in that future versions of this driver may reset all
|
||||
emulations by default on the driver's unloading (as it probably should), so
|
||||
specifying it now will ensure that all future versions of this driver will
|
||||
continue to work as expected. The default value of this parameter is 1 to
|
||||
retain full behavioral compatibility with previous versions of this driver.
|
||||
|
||||
pss_firmware
|
||||
|
||||
This parameter can be used to specify the file containing the firmware
|
||||
code so that a user could tell the driver where that file is located instead
|
||||
of having to put it in a predefined location with a predefined name. The
|
||||
default setting of this parameter is "/etc/sound/pss_synth" as this was the
|
||||
path and filename the hardcoded value in the previous versions of this driver.
|
||||
|
||||
Examples:
|
||||
|
||||
# Normal PSS sound card system, loading of drivers.
|
||||
# Should be specified in an rc file (ex. Slackware uses /etc/rc.d/rc.modules).
|
||||
|
||||
/sbin/modprobe pss pss_io=0x220 mpu_io=0x338 mpu_irq=9 mss_io=0x530 mss_irq=10 mss_dma=1 pss_cdrom_port=0x340 pss_enable_joystick=1
|
||||
/sbin/modprobe aztcd aztcd=0x340
|
||||
/sbin/modprobe joystick
|
||||
|
||||
# System using the PSS sound card just for its CDROM and joystick ports.
|
||||
# Should be specified in an rc file (ex. Slackware uses /etc/rc.d/rc.modules).
|
||||
|
||||
/sbin/modprobe pss pss_io=0x220 pss_cdrom_port=0x340 pss_enable_joystick=1 pss_no_sound=1
|
||||
/sbin/rmmod pss && /sbin/rmmod ad1848 && /sbin/rmmod mpu401 && /sbin/rmmod sound && /sbin/rmmod soundcore # This line not needed, but saves memory.
|
||||
/sbin/modprobe aztcd aztcd=0x340
|
||||
/sbin/modprobe joystick
|
File diff suppressed because it is too large
Load diff
|
@ -1,106 +0,0 @@
|
|||
Building a modular sound driver
|
||||
================================
|
||||
|
||||
The following information is current as of linux-2.1.85. Check the other
|
||||
readme files, especially README.OSS, for information not specific to
|
||||
making sound modular.
|
||||
|
||||
First, configure your kernel. This is an idea of what you should be
|
||||
setting in the sound section:
|
||||
|
||||
<M> Sound card support
|
||||
|
||||
<M> 100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support
|
||||
|
||||
I have SoundBlaster. Select your card from the list.
|
||||
|
||||
<M> Generic OPL2/OPL3 FM synthesizer support
|
||||
<M> FM synthesizer (YM3812/OPL-3) support
|
||||
|
||||
If you don't set these, you will probably find you can play .wav files
|
||||
but not .midi. As the help for them says, set them unless you know your
|
||||
card does not use one of these chips for FM support.
|
||||
|
||||
Once you are configured, make zlilo, modules, modules_install; reboot.
|
||||
Note that it is no longer necessary or possible to configure sound in the
|
||||
drivers/sound dir. Now one simply configures and makes one's kernel and
|
||||
modules in the usual way.
|
||||
|
||||
Then, add to your /etc/modprobe.d/oss.conf something like:
|
||||
|
||||
alias char-major-14-* sb
|
||||
install sb /sbin/modprobe -i sb && /sbin/modprobe adlib_card
|
||||
options sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330
|
||||
options adlib_card io=0x388 # FM synthesizer
|
||||
|
||||
Alternatively, if you have compiled in kernel level ISAPnP support:
|
||||
|
||||
alias char-major-14 sb
|
||||
softdep sb post: adlib_card
|
||||
options adlib_card io=0x388
|
||||
|
||||
The effect of this is that the sound driver and all necessary bits and
|
||||
pieces autoload on demand, assuming you use kerneld (a sound choice) and
|
||||
autoclean when not in use. Also, options for the device drivers are
|
||||
set. They will not work without them. Change as appropriate for your card.
|
||||
If you are not yet using the very cool kerneld, you will have to "modprobe
|
||||
-k sb" yourself to get things going. Eventually things may be fixed so
|
||||
that this kludgery is not necessary; for the time being, it seems to work
|
||||
well.
|
||||
|
||||
Replace 'sb' with the driver for your card, and give it the right
|
||||
options. To find the filename of the driver, look in
|
||||
/lib/modules/<kernel-version>/misc. Mine looks like:
|
||||
|
||||
adlib_card.o # This is the generic OPLx driver
|
||||
opl3.o # The OPL3 driver
|
||||
sb.o # <<The SoundBlaster driver. Yours may differ.>>
|
||||
sound.o # The sound driver
|
||||
uart401.o # Used by sb, maybe other cards
|
||||
|
||||
Whichever card you have, try feeding it the options that would be the
|
||||
default if you were making the driver wired, not as modules. You can
|
||||
look at function referred to by module_init() for the card to see what
|
||||
args are expected.
|
||||
|
||||
Note that at present there is no way to configure the io, irq and other
|
||||
parameters for the modular drivers as one does for the wired drivers.. One
|
||||
needs to pass the modules the necessary parameters as arguments, either
|
||||
with /etc/modprobe.d/*.conf or with command-line args to modprobe, e.g.
|
||||
|
||||
modprobe sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330
|
||||
modprobe adlib_card io=0x388
|
||||
|
||||
recommend using /etc/modprobe.d/*.conf.
|
||||
|
||||
Persistent DMA Buffers:
|
||||
|
||||
The sound modules normally allocate DMA buffers during open() and
|
||||
deallocate them during close(). Linux can often have problems allocating
|
||||
DMA buffers for ISA cards on machines with more than 16MB RAM. This is
|
||||
because ISA DMA buffers must exist below the 16MB boundary and it is quite
|
||||
possible that we can't find a large enough free block in this region after
|
||||
the machine has been running for any amount of time. The way to avoid this
|
||||
problem is to allocate the DMA buffers during module load and deallocate
|
||||
them when the module is unloaded. For this to be effective we need to load
|
||||
the sound modules right after the kernel boots, either manually or by an
|
||||
init script, and keep them around until we shut down. This is a little
|
||||
wasteful of RAM, but it guarantees that sound always works.
|
||||
|
||||
To make the sound driver use persistent DMA buffers we need to pass the
|
||||
sound.o module a "dmabuf=1" command-line argument. This is normally done
|
||||
in /etc/modprobe.d/*.conf files like so:
|
||||
|
||||
options sound dmabuf=1
|
||||
|
||||
If you have 16MB or less RAM or a PCI sound card, this is wasteful and
|
||||
unnecessary. It is possible that machine with 16MB or less RAM will find
|
||||
this option useful, but if your machine is so memory-starved that it
|
||||
cannot find a 64K block free, you will be wasting even more RAM by keeping
|
||||
the sound modules loaded and the DMA buffers allocated when they are not
|
||||
needed. The proper solution is to upgrade your RAM. But you do also have
|
||||
this improper solution as well. Use it wisely.
|
||||
|
||||
I'm afraid I know nothing about anything but my setup, being more of a
|
||||
text-mode guy anyway. If you have options for other cards or other helpful
|
||||
hints, send them to me, Jim Bray, jb@as220.org, http://as220.org/jb.
|
|
@ -1,107 +0,0 @@
|
|||
Legacy audio driver for YMF7xx PCI cards.
|
||||
|
||||
|
||||
FIRST OF ALL
|
||||
============
|
||||
|
||||
This code references YAMAHA's sample codes and data sheets.
|
||||
I respect and thank for all people they made open the information
|
||||
about YMF7xx cards.
|
||||
|
||||
And this codes heavily based on Jeff Garzik <jgarzik@pobox.com>'s
|
||||
old VIA 82Cxxx driver (via82cxxx.c). I also respect him.
|
||||
|
||||
|
||||
DISCLIMER
|
||||
=========
|
||||
|
||||
This driver is currently at early ALPHA stage. It may cause serious
|
||||
damage to your computer when used.
|
||||
PLEASE USE IT AT YOUR OWN RISK.
|
||||
|
||||
|
||||
ABOUT THIS DRIVER
|
||||
=================
|
||||
|
||||
This code enables you to use your YMF724[A-F], YMF740[A-C], YMF744, YMF754
|
||||
cards. When enabled, your card acts as "SoundBlaster Pro" compatible card.
|
||||
It can only play 22.05kHz / 8bit / Stereo samples, control external MIDI
|
||||
port.
|
||||
If you want to use your card as recent "16-bit" card, you should use
|
||||
Alsa or OSS/Linux driver. Of course you can write native PCI driver for
|
||||
your cards :)
|
||||
|
||||
|
||||
USAGE
|
||||
=====
|
||||
|
||||
# modprobe ymfsb (options)
|
||||
|
||||
|
||||
OPTIONS FOR MODULE
|
||||
==================
|
||||
|
||||
io : SB base address (0x220, 0x240, 0x260, 0x280)
|
||||
synth_io : OPL3 base address (0x388, 0x398, 0x3a0, 0x3a8)
|
||||
dma : DMA number (0,1,3)
|
||||
master_volume: AC'97 PCM out Vol (0-100)
|
||||
spdif_out : SPDIF-out flag (0:disable 1:enable)
|
||||
|
||||
These options will change in future...
|
||||
|
||||
|
||||
FREQUENCY
|
||||
=========
|
||||
|
||||
When playing sounds via this driver, you will hear its pitch is slightly
|
||||
lower than original sounds. Since this driver recognizes your card acts
|
||||
with 21.739kHz sample rates rather than 22.050kHz (I think it must be
|
||||
hardware restriction). So many players become tone deafness.
|
||||
To prevent this, you should express some options to your sound player
|
||||
that specify correct sample frequency. For example, to play your MP3 file
|
||||
correctly with mpg123, specify the frequency like following:
|
||||
|
||||
% mpg123 -r 21739 foo.mp3
|
||||
|
||||
|
||||
SPDIF OUT
|
||||
=========
|
||||
|
||||
With installing modules with option 'spdif_out=1', you can enjoy your
|
||||
sounds from SPDIF-out of your card (if it had).
|
||||
Its Fs is fixed to 48kHz (It never means the sample frequency become
|
||||
up to 48kHz. All sounds via SPDIF-out also 22kHz samples). So your
|
||||
digital-in capable components has to be able to handle 48kHz Fs.
|
||||
|
||||
|
||||
COPYING
|
||||
=======
|
||||
|
||||
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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
|
||||
TODO
|
||||
====
|
||||
* support for multiple cards
|
||||
(set the different SB_IO,MPU_IO,OPL_IO for each cards)
|
||||
|
||||
* support for OPL (dmfm) : There will be no requirements... :-<
|
||||
|
||||
|
||||
AUTHOR
|
||||
======
|
||||
|
||||
Daisuke Nagano <breeze.nagano@nifty.ne.jp>
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
Documentation for the SoundPro CMI8330 extensions in the WSS driver (ad1848.o)
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
( Be sure to read Documentation/sound/oss/CMI8330 too )
|
||||
|
||||
Ion Badulescu, ionut@cs.columbia.edu
|
||||
February 24, 1999
|
||||
|
||||
(derived from the OPL3-SA2 documentation by Scott Murray)
|
||||
|
||||
The SoundPro CMI8330 (ISA) is a chip usually found on some Taiwanese
|
||||
motherboards. The official name in the documentation is CMI8330, SoundPro
|
||||
is the nickname and the big inscription on the chip itself.
|
||||
|
||||
The chip emulates a WSS as well as a SB16, but it has certain differences
|
||||
in the mixer section which require separate support. It also emulates an
|
||||
MPU401 and an OPL3 synthesizer, so you probably want to enable support
|
||||
for these, too.
|
||||
|
||||
The chip identifies itself as an AD1848, but its mixer is significantly
|
||||
more advanced than the original AD1848 one. If your system works with
|
||||
either WSS or SB16 and you are having problems with some mixer controls
|
||||
(no CD audio, no line-in, etc), you might want to give this driver a try.
|
||||
Detection should work, but it hasn't been widely tested, so it might still
|
||||
mis-identify the chip. You can still force soundpro=1 in the modprobe
|
||||
parameters for ad1848. Please let me know if it happens to you, so I can
|
||||
adjust the detection routine.
|
||||
|
||||
The chip is capable of doing full-duplex, but since the driver sees it as an
|
||||
AD1848, it cannot take advantage of this. Moreover, the full-duplex mode is
|
||||
not achievable through the WSS interface, b/c it needs a dma16 line which is
|
||||
assigned only to the SB16 subdevice (with isapnp). Windows documentation
|
||||
says the user must use WSS Playback and SB16 Recording for full-duplex, so
|
||||
it might be possible to do the same thing under Linux. You can try loading
|
||||
up both ad1848 and sb then use one for playback and the other for
|
||||
recording. I don't know if this works, b/c I haven't tested it. Anyway, if
|
||||
you try it, be very careful: the SB16 mixer *mostly* works, but certain
|
||||
settings can have unexpected effects. Use the WSS mixer for best results.
|
||||
|
||||
There is also a PCI SoundPro chip. I have not seen this chip, so I have
|
||||
no idea if the driver will work with it. I suspect it won't.
|
||||
|
||||
As with PnP cards, some configuration is required. There are two ways
|
||||
of doing this. The most common is to use the isapnptools package to
|
||||
initialize the card, and use the kernel module form of the sound
|
||||
subsystem and sound drivers. Alternatively, some BIOS's allow manual
|
||||
configuration of installed PnP devices in a BIOS menu, which should
|
||||
allow using the non-modular sound drivers, i.e. built into the kernel.
|
||||
Since in this latter case you cannot use module parameters, you will
|
||||
have to enable support for the SoundPro at compile time.
|
||||
|
||||
The IRQ and DMA values can be any that are considered acceptable for a
|
||||
WSS. Assuming you've got isapnp all happy, then you should be able to
|
||||
do something like the following (which *must* match the isapnp/BIOS
|
||||
configuration):
|
||||
|
||||
modprobe ad1848 io=0x530 irq=11 dma=0 soundpro=1
|
||||
-and maybe-
|
||||
modprobe sb io=0x220 irq=5 dma=1 dma16=5
|
||||
|
||||
-then-
|
||||
modprobe mpu401 io=0x330 irq=9
|
||||
modprobe opl3 io=0x388
|
||||
|
||||
If all goes well and you see no error messages, you should be able to
|
||||
start using the sound capabilities of your system. If you get an
|
||||
error message while trying to insert the module(s), then make
|
||||
sure that the values of the various arguments match what you specified
|
||||
in your isapnp configuration file, and that there is no conflict with
|
||||
another device for an I/O port or interrupt. Checking the contents of
|
||||
/proc/ioports and /proc/interrupts can be useful to see if you're
|
||||
butting heads with another device.
|
||||
|
||||
If you do not see the chipset version message, and none of the other
|
||||
messages present in the system log are helpful, try adding 'debug=1'
|
||||
to the ad1848 parameters, email me the syslog results and I'll do
|
||||
my best to help.
|
||||
|
||||
Lastly, if you're using modules and want to set up automatic module
|
||||
loading with kmod, the kernel module loader, here is the section I
|
||||
currently use in my conf.modules file:
|
||||
|
||||
# Sound
|
||||
post-install sound modprobe -k ad1848; modprobe -k mpu401; modprobe -k opl3
|
||||
options ad1848 io=0x530 irq=11 dma=0
|
||||
options sb io=0x220 irq=5 dma=1 dma16=5
|
||||
options mpu401 io=0x330 irq=9
|
||||
options opl3 io=0x388
|
||||
|
||||
The above ensures that ad1848 will be loaded whenever the sound system
|
||||
is being used.
|
||||
|
||||
Good luck.
|
||||
|
||||
Ion
|
||||
|
||||
NOT REALLY TESTED:
|
||||
- recording
|
||||
- recording device selection
|
||||
- full-duplex
|
||||
|
||||
TODO:
|
||||
- implement mixer support for surround, loud, digital CD switches.
|
||||
- come up with a scheme which allows recording volumes for each subdevice.
|
||||
This is a major OSS API change.
|
|
@ -1,53 +0,0 @@
|
|||
modprobe sound
|
||||
insmod uart401
|
||||
insmod sb ...
|
||||
|
||||
This loads the driver for the Sound Blaster and assorted clones. Cards that
|
||||
are covered by other drivers should not be using this driver.
|
||||
|
||||
The Sound Blaster module takes the following arguments
|
||||
|
||||
io I/O address of the Sound Blaster chip (0x220,0x240,0x260,0x280)
|
||||
irq IRQ of the Sound Blaster chip (5,7,9,10)
|
||||
dma 8-bit DMA channel for the Sound Blaster (0,1,3)
|
||||
dma16 16-bit DMA channel for SB16 and equivalent cards (5,6,7)
|
||||
mpu_io I/O for MPU chip if present (0x300,0x330)
|
||||
|
||||
sm_games=1 Set if you have a Logitech soundman games
|
||||
acer=1 Set this to detect cards in some ACER notebooks
|
||||
mwave_bug=1 Set if you are trying to use this driver with mwave (see on)
|
||||
type Use this to specify a specific card type
|
||||
|
||||
The following arguments are taken if ISAPnP support is compiled in
|
||||
|
||||
isapnp=0 Set this to disable ISAPnP detection (use io=0xXXX etc. above)
|
||||
multiple=0 Set to disable detection of multiple Soundblaster cards.
|
||||
Consider it a bug if this option is needed, and send in a
|
||||
report.
|
||||
pnplegacy=1 Set this to be able to use a PnP card(s) along with a single
|
||||
non-PnP (legacy) card. Above options for io, irq, etc. are
|
||||
needed, and will apply only to the legacy card.
|
||||
reverse=1 Reverses the order of the search in the PnP table.
|
||||
uart401=1 Set to enable detection of mpu devices on some clones.
|
||||
isapnpjump=n Jumps to slot n in the driver's PnP table. Use the source,
|
||||
Luke.
|
||||
|
||||
You may well want to load the opl3 driver for synth music on most SB and
|
||||
clone SB devices
|
||||
|
||||
insmod opl3 io=0x388
|
||||
|
||||
Using Mwave
|
||||
|
||||
To make this driver work with Mwave you must set mwave_bug. You also need
|
||||
to warm boot from DOS/Windows with the required firmware loaded under this
|
||||
OS. IBM are being difficult about documenting how to load this firmware.
|
||||
|
||||
Avance Logic ALS007
|
||||
|
||||
This card is supported; see the separate file ALS007 for full details.
|
||||
|
||||
Avance Logic ALS100
|
||||
|
||||
This card is supported; setup should be as for a standard Sound Blaster 16.
|
||||
The driver will identify the audio device as a "Sound Blaster 16 (ALS-100)".
|
|
@ -1,26 +0,0 @@
|
|||
From: Paul Barton-Davis <pbd@op.net>
|
||||
|
||||
Here is the configuration I use with a Tropez+ and my modular
|
||||
driver:
|
||||
|
||||
alias char-major-14 wavefront
|
||||
alias synth0 wavefront
|
||||
alias mixer0 cs4232
|
||||
alias audio0 cs4232
|
||||
pre-install wavefront modprobe "-k" "cs4232"
|
||||
post-install wavefront modprobe "-k" "opl3"
|
||||
options wavefront io=0x200 irq=9
|
||||
options cs4232 synthirq=9 synthio=0x200 io=0x530 irq=5 dma=1 dma2=0
|
||||
options opl3 io=0x388
|
||||
|
||||
Things to note:
|
||||
|
||||
the wavefront options "io" and "irq" ***MUST*** match the "synthio"
|
||||
and "synthirq" cs4232 options.
|
||||
|
||||
you can do without the opl3 module if you don't
|
||||
want to use the OPL/[34] synth on the soundcard
|
||||
|
||||
the opl3 io parameter is conventionally not adjustable.
|
||||
|
||||
Please see drivers/sound/README.wavefront for more details.
|
|
@ -1,80 +0,0 @@
|
|||
Sound Blaster 16X Vibra addendum
|
||||
--------------------------------
|
||||
by Marius Ilioaea <mariusi@protv.ro>
|
||||
Stefan Laudat <stefan@asit.ro>
|
||||
|
||||
Sat Mar 6 23:55:27 EET 1999
|
||||
|
||||
Hello again,
|
||||
|
||||
Playing with a SB Vibra 16x soundcard we found it very difficult
|
||||
to setup because the kernel reported a lot of DMA errors and wouldn't
|
||||
simply play any sound.
|
||||
A good starting point is that the vibra16x chip full-duplex facility
|
||||
is neither still exploited by the sb driver found in the linux kernel
|
||||
(tried it with a 2.2.2-ac7), nor in the commercial OSS package (it reports
|
||||
it as half-duplex soundcard). Oh, I almost forgot, the RedHat sndconfig
|
||||
failed detecting it ;)
|
||||
So, the big problem still remains, because the sb module wants a
|
||||
8-bit and a 16-bit dma, which we could not allocate for vibra... it supports
|
||||
only two 8-bit dma channels, the second one will be passed to the module
|
||||
as a 16 bit channel, the kernel will yield about that but everything will
|
||||
be okay, trust us.
|
||||
The only inconvenient you may find is that you will have
|
||||
some sound playing jitters if you have HDD dma support enabled - but this
|
||||
will happen with almost all soundcards...
|
||||
|
||||
A fully working isapnp.conf is just here:
|
||||
|
||||
<snip here>
|
||||
|
||||
(READPORT 0x0203)
|
||||
(ISOLATE PRESERVE)
|
||||
(IDENTIFY *)
|
||||
(VERBOSITY 2)
|
||||
(CONFLICT (IO FATAL)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) # or WARNING
|
||||
# SB 16 and OPL3 devices
|
||||
(CONFIGURE CTL00f0/-1 (LD 0
|
||||
(INT 0 (IRQ 5 (MODE +E)))
|
||||
(DMA 0 (CHANNEL 1))
|
||||
(DMA 1 (CHANNEL 3))
|
||||
(IO 0 (SIZE 16) (BASE 0x0220))
|
||||
(IO 2 (SIZE 4) (BASE 0x0388))
|
||||
(NAME "CTL00f0/-1[0]{Audio }")
|
||||
(ACT Y)
|
||||
))
|
||||
|
||||
# Joystick device - only if you need it :-/
|
||||
|
||||
(CONFIGURE CTL00f0/-1 (LD 1
|
||||
(IO 0 (SIZE 1) (BASE 0x0200))
|
||||
(NAME "CTL00f0/-1[1]{Game }")
|
||||
(ACT Y)
|
||||
))
|
||||
(WAITFORKEY)
|
||||
|
||||
<end of snipping>
|
||||
|
||||
So, after a good kernel modules compilation and a 'depmod -a kernel_ver'
|
||||
you may want to:
|
||||
|
||||
modprobe sb io=0x220 irq=5 dma=1 dma16=3
|
||||
|
||||
Or, take the hard way:
|
||||
|
||||
modprobe soundcore
|
||||
modprobe sound
|
||||
modprobe uart401
|
||||
modprobe sb io=0x220 irq=5 dma=1 dma16=3
|
||||
# do you need MIDI?
|
||||
modprobe opl3=0x388
|
||||
|
||||
Just in case, the kernel sound support should be:
|
||||
|
||||
CONFIG_SOUND=m
|
||||
CONFIG_SOUND_OSS=m
|
||||
CONFIG_SOUND_SB=m
|
||||
|
||||
Enjoy your new noisy Linux box! ;)
|
||||
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
|
||||
(the following is from the armlinux CVS)
|
||||
|
||||
WaveArtist mixer and volume levels can be accessed via these commands:
|
||||
|
||||
nn30 read registers nn, where nn = 00 - 09 for mixer settings
|
||||
0a - 13 for channel volumes
|
||||
mm31 write the volume setting in pairs, where mm = (nn - 10) / 2
|
||||
rr32 write the mixer settings in pairs, where rr = nn/2
|
||||
xx33 reset all settings to default
|
||||
0y34 select mono source, y=0 = left, y=1 = right
|
||||
|
||||
bits
|
||||
nn 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
00 | 0 | 0 0 1 1 | left line mixer gain | left aux1 mixer gain |lmute|
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
01 | 0 | 0 1 0 1 | left aux2 mixer gain | right 2 left mic gain |mmute|
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
02 | 0 | 0 1 1 1 | left mic mixer gain | left mic | left mixer gain |dith |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
03 | 0 | 1 0 0 1 | left mixer input select |lrfg | left ADC gain |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
04 | 0 | 1 0 1 1 | right line mixer gain | right aux1 mixer gain |rmute|
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
05 | 0 | 1 1 0 1 | right aux2 mixer gain | left 2 right mic gain |test |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
06 | 0 | 1 1 1 1 | right mic mixer gain | right mic |right mixer gain |rbyps|
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
07 | 1 | 0 0 0 1 | right mixer select |rrfg | right ADC gain |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
08 | 1 | 0 0 1 1 | mono mixer gain |right ADC mux sel|left ADC mux sel |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
09 | 1 | 0 1 0 1 |loopb|left linout|loop|ADCch|TxFch|OffCD|test |loopb|loopb|osamp|
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
0a | 0 | left PCM channel volume |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
0b | 0 | right PCM channel volume |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
0c | 0 | left FM channel volume |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
0d | 0 | right FM channel volume |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
0e | 0 | left wavetable channel volume |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
0f | 0 | right wavetable channel volume |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
10 | 0 | left PCM expansion channel volume |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
11 | 0 | right PCM expansion channel volume |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
12 | 0 | left FM expansion channel volume |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
13 | 0 | right FM expansion channel volume |
|
||||
----+---+------------+-----+-----+-----+----+-----+-----+-----+-----+-----+-----+-----+
|
||||
|
||||
lmute: left mute
|
||||
mmute: mono mute
|
||||
dith: dithds
|
||||
lrfg:
|
||||
rmute: right mute
|
||||
rbyps: right bypass
|
||||
rrfg:
|
||||
ADCch:
|
||||
TxFch:
|
||||
OffCD:
|
||||
osamp:
|
||||
|
||||
And the following diagram is derived from the description in the CVS archive:
|
||||
|
||||
MIC L (mouthpiece)
|
||||
+------+
|
||||
-->PreAmp>-\
|
||||
+--^---+ |
|
||||
| |
|
||||
r2b4-5 | +--------+
|
||||
/----*-------------------------------->5 |
|
||||
| | |
|
||||
| /----------------------------------->4 |
|
||||
| | | |
|
||||
| | /--------------------------------->3 1of5 | +---+
|
||||
| | | | mux >-->AMP>--> ADC L
|
||||
| | | /------------------------------->2 | +-^-+
|
||||
| | | | | | |
|
||||
Line | | | | +----+ +------+ +---+ /---->1 | r3b3-0
|
||||
------------*->mute>--> Gain >--> | | | |
|
||||
L | | | +----+ +------+ | | | *->0 |
|
||||
| | | | | | +---^----+
|
||||
Aux2 | | | +----+ +------+ | | | |
|
||||
----------*--->mute>--> Gain >--> M | | r8b0-2
|
||||
L | | +----+ +------+ | | |
|
||||
| | | | \------\
|
||||
Aux1 | | +----+ +------+ | | |
|
||||
--------*----->mute>--> Gain >--> I | |
|
||||
L | +----+ +------+ | | |
|
||||
| | | |
|
||||
| +----+ +------+ | | +---+ |
|
||||
*------->mute>--> Gain >--> X >-->AMP>--*
|
||||
| +----+ +------+ | | +-^-+ |
|
||||
| | | | |
|
||||
| +----+ +------+ | | r2b1-3 |
|
||||
| /----->mute>--> Gain >--> E | |
|
||||
| | +----+ +------+ | | |
|
||||
| | | | |
|
||||
| | +----+ +------+ | | |
|
||||
| | /--->mute>--> Gain >--> R | |
|
||||
| | | +----+ +------+ | | |
|
||||
| | | | | | r9b8-9
|
||||
| | | +----+ +------+ | | | |
|
||||
| | | /->mute>--> Gain >--> | | +---v---+
|
||||
| | | | +----+ +------+ +---+ /-*->0 |
|
||||
DAC | | | | | | |
|
||||
------------*----------------------------------->? | +----+
|
||||
L | | | | | Mux >-->mute>--> L output
|
||||
| | | | /->? | +--^-+
|
||||
| | | | | | | |
|
||||
| | | /--------->? | r0b0
|
||||
| | | | | | +-------+
|
||||
| | | | | |
|
||||
Mono | | | | | | +-------+
|
||||
----------* | \---> | +----+
|
||||
| | | | | | Mix >-->mute>--> Mono output
|
||||
| | | | *-> | +--^-+
|
||||
| | | | | +-------+ |
|
||||
| | | | | r1b0
|
||||
DAC | | | | | +-------+
|
||||
------------*-------------------------*--------->1 | +----+
|
||||
R | | | | | | Mux >-->mute>--> R output
|
||||
| | | | +----+ +------+ +---+ *->0 | +--^-+
|
||||
| | | \->mute>--> Gain >--> | | +---^---+ |
|
||||
| | | +----+ +------+ | | | | r5b0
|
||||
| | | | | | r6b0
|
||||
| | | +----+ +------+ | | |
|
||||
| | \--->mute>--> Gain >--> M | |
|
||||
| | +----+ +------+ | | |
|
||||
| | | | |
|
||||
| | +----+ +------+ | | |
|
||||
| *----->mute>--> Gain >--> I | |
|
||||
| | +----+ +------+ | | |
|
||||
| | | | |
|
||||
| | +----+ +------+ | | +---+ |
|
||||
\------->mute>--> Gain >--> X >-->AMP>--*
|
||||
| +----+ +------+ | | +-^-+ |
|
||||
/--/ | | | |
|
||||
Aux1 | +----+ +------+ | | r6b1-3 |
|
||||
-------*------>mute>--> Gain >--> E | |
|
||||
R | | +----+ +------+ | | |
|
||||
| | | | |
|
||||
Aux2 | | +----+ +------+ | | /------/
|
||||
---------*---->mute>--> Gain >--> R | |
|
||||
R | | | +----+ +------+ | | |
|
||||
| | | | | | +--------+
|
||||
Line | | | +----+ +------+ | | | *->0 |
|
||||
-----------*-->mute>--> Gain >--> | | | |
|
||||
R | | | | +----+ +------+ +---+ \---->1 |
|
||||
| | | | | |
|
||||
| | | \-------------------------------->2 | +---+
|
||||
| | | | Mux >-->AMP>--> ADC R
|
||||
| | \---------------------------------->3 | +-^-+
|
||||
| | | | |
|
||||
| \------------------------------------>4 | r7b3-0
|
||||
| | |
|
||||
\-----*-------------------------------->5 |
|
||||
| +---^----+
|
||||
r6b4-5 | |
|
||||
| | r8b3-5
|
||||
+--v---+ |
|
||||
-->PreAmp>-/
|
||||
+------+
|
||||
MIC R (electret mic)
|
|
@ -1,92 +0,0 @@
|
|||
|
||||
Intro
|
||||
=====
|
||||
|
||||
people start bugging me about this with questions, looks like I
|
||||
should write up some documentation for this beast. That way I
|
||||
don't have to answer that much mails I hope. Yes, I'm lazy...
|
||||
|
||||
|
||||
You might have noticed that the bt878 grabber cards have actually
|
||||
_two_ PCI functions:
|
||||
|
||||
$ lspci
|
||||
[ ... ]
|
||||
00:0a.0 Multimedia video controller: Brooktree Corporation Bt878 (rev 02)
|
||||
00:0a.1 Multimedia controller: Brooktree Corporation Bt878 (rev 02)
|
||||
[ ... ]
|
||||
|
||||
The first does video, it is backward compatible to the bt848. The second
|
||||
does audio. btaudio is a driver for the second function. It's a sound
|
||||
driver which can be used for recording sound (and _only_ recording, no
|
||||
playback). As most TV cards come with a short cable which can be plugged
|
||||
into your sound card's line-in you probably don't need this driver if all
|
||||
you want to do is just watching TV...
|
||||
|
||||
|
||||
Driver Status
|
||||
=============
|
||||
|
||||
Still somewhat experimental. The driver should work stable, i.e. it
|
||||
should'nt crash your box. It might not work as expected, have bugs,
|
||||
not being fully OSS API compliant, ...
|
||||
|
||||
Latest versions are available from http://bytesex.org/bttv/, the
|
||||
driver is in the bttv tarball. Kernel patches might be available too,
|
||||
have a look at http://bytesex.org/bttv/listing.html.
|
||||
|
||||
The chip knows two different modes. btaudio registers two dsp
|
||||
devices, one for each mode. They can not be used at the same time.
|
||||
|
||||
|
||||
Digital audio mode
|
||||
==================
|
||||
|
||||
The chip gives you 16 bit stereo sound. The sample rate depends on
|
||||
the external source which feeds the bt878 with digital sound via I2S
|
||||
interface. There is a insmod option (rate) to tell the driver which
|
||||
sample rate the hardware uses (32000 is the default).
|
||||
|
||||
One possible source for digital sound is the msp34xx audio processor
|
||||
chip which provides digital sound via I2S with 32 kHz sample rate. My
|
||||
Hauppauge board works this way.
|
||||
|
||||
The Osprey-200 reportly gives you digital sound with 44100 Hz sample
|
||||
rate. It is also possible that you get no sound at all.
|
||||
|
||||
|
||||
analog mode (A/D)
|
||||
=================
|
||||
|
||||
You can tell the driver to use this mode with the insmod option "analog=1".
|
||||
The chip has three analog inputs. Consequently you'll get a mixer device
|
||||
to control these.
|
||||
|
||||
The analog mode supports mono only. Both 8 + 16 bit. Both are _signed_
|
||||
int, which is uncommon for the 8 bit case. Sample rate range is 119 kHz
|
||||
to 448 kHz. Yes, the number of digits is correct. The driver supports
|
||||
downsampling by powers of two, so you can ask for more usual sample rates
|
||||
like 44 kHz too.
|
||||
|
||||
With my Hauppauge I get noisy sound on the second input (mapped to line2
|
||||
by the mixer device). Others get a useable signal on line1.
|
||||
|
||||
|
||||
some examples
|
||||
=============
|
||||
|
||||
* read audio data from btaudio (dsp2), send to es1730 (dsp,dsp1):
|
||||
$ sox -w -r 32000 -t ossdsp /dev/dsp2 -t ossdsp /dev/dsp
|
||||
|
||||
* read audio data from btaudio, send to esound daemon (which might be
|
||||
running on another host):
|
||||
$ sox -c 2 -w -r 32000 -t ossdsp /dev/dsp2 -t sw - | esdcat -r 32000
|
||||
$ sox -c 1 -w -r 32000 -t ossdsp /dev/dsp2 -t sw - | esdcat -m -r 32000
|
||||
|
||||
|
||||
Have fun,
|
||||
|
||||
Gerd
|
||||
|
||||
--
|
||||
Gerd Knorr <kraxel@bytesex.org>
|
|
@ -1,185 +0,0 @@
|
|||
How to try to survive an IBM Mwave under Linux SB drivers
|
||||
|
||||
|
||||
+ IBM have now released documentation of sorts and Torsten is busy
|
||||
trying to make the Mwave work. This is not however a trivial task.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
OK, first thing - the IRQ problem IS a problem, whether the test is bypassed or
|
||||
not. It is NOT a Linux problem, but an MWAVE problem that is fixed with the
|
||||
latest MWAVE patches. So, in other words, don't bypass the test for MWAVES!
|
||||
|
||||
I have Windows 95 on /dev/hda1, swap on /dev/hda2, and Red Hat 5 on /dev/hda3.
|
||||
|
||||
The steps, then:
|
||||
|
||||
Boot to Linux.
|
||||
Mount Windows 95 file system (assume mount point = /dos95).
|
||||
mkdir /dos95/linux
|
||||
mkdir /dos95/linux/boot
|
||||
mkdir /dos95/linux/boot/parms
|
||||
|
||||
Copy the kernel, any initrd image, and loadlin to /dos95/linux/boot/.
|
||||
|
||||
Reboot to Windows 95.
|
||||
|
||||
Edit C:/msdos.sys and add or change the following:
|
||||
|
||||
Logo=0
|
||||
BootGUI=0
|
||||
|
||||
Note that msdos.sys is a text file but it needs to be made 'unhidden',
|
||||
readable and writable before it can be edited. This can be done with
|
||||
DOS' "attrib" command.
|
||||
|
||||
Edit config.sys to have multiple config menus. I have one for windows 95 and
|
||||
five for Linux, like this:
|
||||
------------
|
||||
[menu]
|
||||
menuitem=W95, Windows 95
|
||||
menuitem=LINTP, Linux - ThinkPad
|
||||
menuitem=LINTP3, Linux - ThinkPad Console
|
||||
menuitem=LINDOC, Linux - Docked
|
||||
menuitem=LINDOC3, Linux - Docked Console
|
||||
menuitem=LIN1, Linux - Single User Mode
|
||||
REM menudefault=W95,10
|
||||
|
||||
[W95]
|
||||
|
||||
[LINTP]
|
||||
|
||||
[LINDOC]
|
||||
|
||||
[LINTP3]
|
||||
|
||||
[LINDOC3]
|
||||
|
||||
[LIN1]
|
||||
|
||||
[COMMON]
|
||||
FILES=30
|
||||
REM Please read README.TXT in C:\MWW subdirectory before changing the DOS= statement.
|
||||
DOS=HIGH,UMB
|
||||
DEVICE=C:\MWW\MANAGER\MWD50430.EXE
|
||||
SHELL=c:\command.com /e:2048
|
||||
-------------------
|
||||
|
||||
The important things are the SHELL and DEVICE statements.
|
||||
|
||||
Then change autoexec.bat. Basically everything in there originally should be
|
||||
done ONLY when Windows 95 is booted. Then you add new things specifically
|
||||
for Linux. Mine is as follows
|
||||
|
||||
---------------
|
||||
@ECHO OFF
|
||||
if "%CONFIG%" == "W95" goto W95
|
||||
|
||||
REM
|
||||
REM Linux stuff
|
||||
REM
|
||||
SET MWPATH=C:\MWW\DLL;C:\MWW\MWGAMES;C:\MWW\DSP
|
||||
SET BLASTER=A220 I5 D1
|
||||
SET MWROOT=C:\MWW
|
||||
SET LIBPATH=C:\MWW\DLL
|
||||
SET PATH=C:\WINDOWS;C:\MWW\DLL;
|
||||
CALL MWAVE START NOSHOW
|
||||
c:\linux\boot\loadlin.exe @c:\linux\boot\parms\%CONFIG%.par
|
||||
|
||||
:W95
|
||||
REM
|
||||
REM Windows 95 stuff
|
||||
REM
|
||||
c:\toolkit\guard
|
||||
SET MSINPUT=C:\MSINPUT
|
||||
SET MWPATH=C:\MWW\DLL;C:\MWW\MWGAMES;C:\MWW\DSP
|
||||
REM The following is used by DOS games to recognize Sound Blaster hardware.
|
||||
REM If hardware settings are changed, please change this line as well.
|
||||
REM See the Mwave README file for instructions.
|
||||
SET BLASTER=A220 I5 D1
|
||||
SET MWROOT=C:\MWW
|
||||
SET LIBPATH=C:\MWW\DLL
|
||||
SET PATH=C:\WINDOWS;C:\WINDOWS\COMMAND;E:\ORAWIN95\BIN;f:\msdev\bin;e:\v30\bin.dbg;v:\devt\v30\bin;c:\JavaSDK\Bin;C:\MWW\DLL;
|
||||
SET INCLUDE=f:\MSDEV\INCLUDE;F:\MSDEV\MFC\INCLUDE
|
||||
SET LIB=F:\MSDEV\LIB;F:\MSDEV\MFC\LIB
|
||||
win
|
||||
|
||||
------------------------
|
||||
|
||||
Now build a file in c:\linux\boot\parms for each Linux config that you have.
|
||||
|
||||
For example, my LINDOC3 config is for a docked Thinkpad at runlevel 3 with no
|
||||
initrd image, and has a parameter file named LINDOC3.PAR in c:\linux\boot\parms:
|
||||
|
||||
-----------------------
|
||||
# LOADLIN @param_file image=other_image root=/dev/other
|
||||
#
|
||||
# Linux Console in docking station
|
||||
#
|
||||
c:\linux\boot\zImage.krn # First value must be filename of Linux kernel.
|
||||
root=/dev/hda3 # device which gets mounted as root FS
|
||||
ro # Other kernel arguments go here.
|
||||
apm=off
|
||||
doc=yes
|
||||
3
|
||||
-----------------------
|
||||
|
||||
The doc=yes parameter is an environment variable used by my init scripts, not
|
||||
a kernel argument.
|
||||
|
||||
However, the apm=off parameter IS a kernel argument! APM, at least in my setup,
|
||||
causes the kernel to crash when loaded via loadlin (but NOT when loaded via
|
||||
LILO). The APM stuff COULD be forced out of the kernel via the kernel compile
|
||||
options. Instead, I got an unofficial patch to the APM drivers that allows them
|
||||
to be dynamically deactivated via kernel arguments. Whatever you chose to
|
||||
document, APM, it seems, MUST be off for setups like mine.
|
||||
|
||||
Now make sure C:\MWW\MWCONFIG.REF looks like this:
|
||||
|
||||
----------------------
|
||||
[NativeDOS]
|
||||
Default=SB1.5
|
||||
SBInputSource=CD
|
||||
SYNTH=FM
|
||||
QSound=OFF
|
||||
Reverb=OFF
|
||||
Chorus=OFF
|
||||
ReverbDepth=5
|
||||
ChorusDepth=5
|
||||
SBInputVolume=5
|
||||
SBMainVolume=10
|
||||
SBWaveVolume=10
|
||||
SBSynthVolume=10
|
||||
WaveTableVolume=10
|
||||
AudioPowerDriver=ON
|
||||
|
||||
[FastCFG]
|
||||
Show=No
|
||||
HideOption=Off
|
||||
-----------------------------
|
||||
|
||||
OR the Default= line COULD be
|
||||
|
||||
Default=SBPRO
|
||||
|
||||
Reboot to Windows 95 and choose Linux. When booted, use sndconfig to configure
|
||||
the sound modules and voilà - ThinkPad sound with Linux.
|
||||
|
||||
Now the gotchas - you can either have CD sound OR Mixers but not both. That's a
|
||||
problem with the SB1.5 (CD sound) or SBPRO (Mixers) settings. No one knows why
|
||||
this is!
|
||||
|
||||
For some reason MPEG3 files, when played through mpg123, sound like they
|
||||
are playing at 1/8th speed - not very useful! If you have ANY insight
|
||||
on why this second thing might be happening, I would be grateful.
|
||||
|
||||
===========================================================
|
||||
_/ _/_/_/_/
|
||||
_/_/ _/_/ _/
|
||||
_/ _/_/ _/_/_/_/ Martin John Bartlett
|
||||
_/ _/ _/ _/ (martin@nitram.demon.co.uk)
|
||||
_/ _/_/_/_/
|
||||
_/
|
||||
_/ _/
|
||||
_/_/
|
||||
===========================================================
|
|
@ -1,51 +0,0 @@
|
|||
OSS Kernel Parameters
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
See Documentation/admin-guide/kernel-parameters.rst for general information on
|
||||
specifying module parameters.
|
||||
|
||||
This document may not be entirely up to date and comprehensive. The command
|
||||
"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
|
||||
module. Loadable modules, after being loaded into the running kernel, also
|
||||
reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
|
||||
parameters may be changed at runtime by the command
|
||||
"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}".
|
||||
|
||||
|
||||
ad1848= [HW,OSS]
|
||||
Format: <io>,<irq>,<dma>,<dma2>,<type>
|
||||
|
||||
aedsp16= [HW,OSS] Audio Excel DSP 16
|
||||
Format: <io>,<irq>,<dma>,<mss_io>,<mpu_io>,<mpu_irq>
|
||||
See also header of sound/oss/aedsp16.c.
|
||||
|
||||
dmasound= [HW,OSS] Sound subsystem buffers
|
||||
|
||||
mpu401= [HW,OSS]
|
||||
Format: <io>,<irq>
|
||||
|
||||
opl3= [HW,OSS]
|
||||
Format: <io>
|
||||
|
||||
pas2= [HW,OSS] Format:
|
||||
<io>,<irq>,<dma>,<dma16>,<sb_io>,<sb_irq>,<sb_dma>,<sb_dma16>
|
||||
|
||||
pss= [HW,OSS] Personal Sound System (ECHO ESC614)
|
||||
Format:
|
||||
<io>,<mss_io>,<mss_irq>,<mss_dma>,<mpu_io>,<mpu_irq>
|
||||
|
||||
sscape= [HW,OSS]
|
||||
Format: <io>,<irq>,<dma>,<mpu_io>,<mpu_irq>
|
||||
|
||||
trix= [HW,OSS] MediaTrix AudioTrix Pro
|
||||
Format:
|
||||
<io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq>
|
||||
|
||||
uart401= [HW,OSS]
|
||||
Format: <io>,<irq>
|
||||
|
||||
uart6850= [HW,OSS]
|
||||
Format: <io>,<irq>
|
||||
|
||||
waveartist= [HW,OSS]
|
||||
Format: <io>,<irq>,<dma>,<dma2>
|
|
@ -1,30 +0,0 @@
|
|||
modprobe sound
|
||||
insmod ad1848
|
||||
insmod gus io=* irq=* dma=* ...
|
||||
|
||||
This loads the driver for the Gravis Ultrasound family of sound cards.
|
||||
|
||||
The gus module takes the following arguments
|
||||
|
||||
io I/O address of the Ultrasound card (eg. io=0x220)
|
||||
irq IRQ of the Sound Blaster card
|
||||
dma DMA channel for the Sound Blaster
|
||||
dma16 2nd DMA channel, only needed for full duplex operation
|
||||
type 1 for PnP card
|
||||
gus16 1 for using 16 bit sampling daughter board
|
||||
no_wave_dma Set to disable DMA usage for wavetable (see note)
|
||||
db16 ???
|
||||
|
||||
|
||||
no_wave_dma option
|
||||
|
||||
This option defaults to a value of 0, which allows the Ultrasound wavetable
|
||||
DSP to use DMA for playback and downloading samples. This is the same
|
||||
as the old behaviour. If set to 1, no DMA is needed for downloading samples,
|
||||
and allows owners of a GUS MAX to make use of simultaneous digital audio
|
||||
(/dev/dsp), MIDI, and wavetable playback.
|
||||
|
||||
|
||||
If you have problems in recording with GUS MAX, you could try to use
|
||||
just one 8 bit DMA channel. Recording will not work with one DMA
|
||||
channel if it's a 16 bit one.
|
11
MAINTAINERS
11
MAINTAINERS
|
@ -527,11 +527,6 @@ W: http://ez.analog.com/community/linux-device-drivers
|
|||
S: Supported
|
||||
F: drivers/input/misc/adxl34x.c
|
||||
|
||||
AEDSP16 DRIVER
|
||||
M: Riccardo Facchetti <fizban@tin.it>
|
||||
S: Maintained
|
||||
F: sound/oss/aedsp16.c
|
||||
|
||||
AF9013 MEDIA DRIVER
|
||||
M: Antti Palosaari <crope@iki.fi>
|
||||
L: linux-media@vger.kernel.org
|
||||
|
@ -9199,12 +9194,6 @@ F: include/linux/dt-bindings/mux/
|
|||
F: include/linux/mux/
|
||||
F: drivers/mux/
|
||||
|
||||
MULTISOUND SOUND DRIVER
|
||||
M: Andrew Veliath <andrewtv@usa.net>
|
||||
S: Maintained
|
||||
F: Documentation/sound/oss/MultiSound
|
||||
F: sound/oss/msnd*
|
||||
|
||||
MULTITECH MULTIPORT CARD (ISICOM)
|
||||
S: Orphan
|
||||
F: drivers/tty/isicom.c
|
||||
|
|
|
@ -187,6 +187,31 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
|
|||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
static const int pipetypes[4] = {
|
||||
PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
|
||||
};
|
||||
|
||||
/**
|
||||
* usb_urb_ep_type_check - sanity check of endpoint in the given urb
|
||||
* @urb: urb to be checked
|
||||
*
|
||||
* This performs a light-weight sanity check for the endpoint in the
|
||||
* given urb. It returns 0 if the urb contains a valid endpoint, otherwise
|
||||
* a negative error code.
|
||||
*/
|
||||
int usb_urb_ep_type_check(const struct urb *urb)
|
||||
{
|
||||
const struct usb_host_endpoint *ep;
|
||||
|
||||
ep = usb_pipe_endpoint(urb->dev, urb->pipe);
|
||||
if (!ep)
|
||||
return -EINVAL;
|
||||
if (usb_pipetype(urb->pipe) != pipetypes[usb_endpoint_type(&ep->desc)])
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_urb_ep_type_check);
|
||||
|
||||
/**
|
||||
* usb_submit_urb - issue an asynchronous transfer request for an endpoint
|
||||
* @urb: pointer to the urb describing the request
|
||||
|
@ -326,9 +351,6 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
|
|||
*/
|
||||
int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
||||
{
|
||||
static int pipetypes[4] = {
|
||||
PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
|
||||
};
|
||||
int xfertype, max;
|
||||
struct usb_device *dev;
|
||||
struct usb_host_endpoint *ep;
|
||||
|
@ -444,7 +466,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
|||
*/
|
||||
|
||||
/* Check that the pipe's type matches the endpoint's type */
|
||||
if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
|
||||
if (usb_urb_ep_type_check(urb))
|
||||
dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
|
||||
usb_pipetype(urb->pipe), pipetypes[xfertype]);
|
||||
|
||||
|
|
|
@ -1728,6 +1728,8 @@ static inline int usb_urb_dir_out(struct urb *urb)
|
|||
return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_OUT;
|
||||
}
|
||||
|
||||
int usb_urb_ep_type_check(const struct urb *urb);
|
||||
|
||||
void *usb_alloc_coherent(struct usb_device *dev, size_t size,
|
||||
gfp_t mem_flags, dma_addr_t *dma);
|
||||
void usb_free_coherent(struct usb_device *dev, size_t size,
|
||||
|
|
|
@ -133,6 +133,7 @@ struct snd_card {
|
|||
struct device card_dev; /* cardX object for sysfs */
|
||||
const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */
|
||||
bool registered; /* card_dev is registered? */
|
||||
wait_queue_head_t remove_sleep;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
unsigned int power_state; /* power state */
|
||||
|
@ -240,6 +241,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
|
|||
struct snd_card **card_ret);
|
||||
|
||||
int snd_card_disconnect(struct snd_card *card);
|
||||
void snd_card_disconnect_sync(struct snd_card *card);
|
||||
int snd_card_free(struct snd_card *card);
|
||||
int snd_card_free_when_closed(struct snd_card *card);
|
||||
void snd_card_set_id(struct snd_card *card, const char *id);
|
||||
|
|
|
@ -111,8 +111,7 @@ void snd_hdac_device_unregister(struct hdac_device *codec);
|
|||
int snd_hdac_device_set_chip_name(struct hdac_device *codec, const char *name);
|
||||
int snd_hdac_codec_modalias(struct hdac_device *hdac, char *buf, size_t size);
|
||||
|
||||
int snd_hdac_refresh_widgets(struct hdac_device *codec);
|
||||
int snd_hdac_refresh_widget_sysfs(struct hdac_device *codec);
|
||||
int snd_hdac_refresh_widgets(struct hdac_device *codec, bool sysfs);
|
||||
|
||||
unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid,
|
||||
unsigned int verb, unsigned int parm);
|
||||
|
|
|
@ -28,6 +28,7 @@ struct _snd_wavefront_midi {
|
|||
struct snd_rawmidi_substream *substream_output[2];
|
||||
struct snd_rawmidi_substream *substream_input[2];
|
||||
struct timer_list timer;
|
||||
snd_wavefront_card_t *timer_card;
|
||||
spinlock_t open;
|
||||
spinlock_t virtual; /* protects isvirtual */
|
||||
};
|
||||
|
|
|
@ -3,25 +3,7 @@ menuconfig SOUND
|
|||
depends on HAS_IOMEM
|
||||
help
|
||||
If you have a sound card in your computer, i.e. if it can say more
|
||||
than an occasional beep, say Y. Be sure to have all the information
|
||||
about your sound card and its configuration down (I/O port,
|
||||
interrupt and DMA channel), because you will be asked for it.
|
||||
|
||||
You want to read the Sound-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>. General information about
|
||||
the modular sound system is contained in the files
|
||||
<file:Documentation/sound/oss/Introduction>. The file
|
||||
<file:Documentation/sound/oss/README.OSS> contains some slightly
|
||||
outdated but still useful information as well. Newer sound
|
||||
driver documentation is found in <file:Documentation/sound/alsa/*>.
|
||||
|
||||
If you have a PnP sound card and you want to configure it at boot
|
||||
time using the ISA PnP tools (read
|
||||
<http://www.roestock.demon.co.uk/isapnptools/>), then you need to
|
||||
compile the sound card support as a module and load that module
|
||||
after the PnP configuration is finished. To do this, choose M here
|
||||
and read <file:Documentation/sound/oss/README.modules>; the module
|
||||
will be called soundcore.
|
||||
than an occasional beep, say Y.
|
||||
|
||||
if SOUND
|
||||
|
||||
|
@ -114,19 +96,6 @@ source "sound/synth/Kconfig"
|
|||
|
||||
endif # SND
|
||||
|
||||
menuconfig SOUND_PRIME
|
||||
tristate "Open Sound System (DEPRECATED)"
|
||||
select SOUND_OSS_CORE
|
||||
depends on BROKEN
|
||||
help
|
||||
Say 'Y' or 'M' to enable Open Sound System drivers.
|
||||
|
||||
if SOUND_PRIME
|
||||
|
||||
source "sound/oss/Kconfig"
|
||||
|
||||
endif # SOUND_PRIME
|
||||
|
||||
endif # !UML
|
||||
|
||||
endif # SOUND
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_SOUND) += soundcore.o
|
||||
obj-$(CONFIG_SOUND_PRIME) += oss/
|
||||
obj-$(CONFIG_DMASOUND) += oss/
|
||||
obj-$(CONFIG_DMASOUND) += oss/dmasound/
|
||||
obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
|
||||
firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ hda/ x86/
|
||||
obj-$(CONFIG_SND_AOA) += aoa/
|
||||
|
|
|
@ -127,7 +127,7 @@ static int snd_hrtimer_stop(struct snd_timer *t)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_timer_hardware hrtimer_hw = {
|
||||
static const struct snd_timer_hardware hrtimer_hw __initconst = {
|
||||
.flags = SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_TASKLET,
|
||||
.open = snd_hrtimer_open,
|
||||
.close = snd_hrtimer_close,
|
||||
|
|
|
@ -228,6 +228,8 @@ static int snd_hwdep_dsp_load(struct snd_hwdep *hw,
|
|||
memset(&info, 0, sizeof(info));
|
||||
if (copy_from_user(&info, _info, sizeof(info)))
|
||||
return -EFAULT;
|
||||
if (info.index >= 32)
|
||||
return -EINVAL;
|
||||
/* check whether the dsp was already loaded */
|
||||
if (hw->dsp_loaded & (1 << info.index))
|
||||
return -EBUSY;
|
||||
|
|
|
@ -255,6 +255,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
|
|||
#ifdef CONFIG_PM
|
||||
init_waitqueue_head(&card->power_sleep);
|
||||
#endif
|
||||
init_waitqueue_head(&card->remove_sleep);
|
||||
|
||||
device_initialize(&card->card_dev);
|
||||
card->card_dev.parent = parent;
|
||||
|
@ -452,6 +453,35 @@ int snd_card_disconnect(struct snd_card *card)
|
|||
}
|
||||
EXPORT_SYMBOL(snd_card_disconnect);
|
||||
|
||||
/**
|
||||
* snd_card_disconnect_sync - disconnect card and wait until files get closed
|
||||
* @card: card object to disconnect
|
||||
*
|
||||
* This calls snd_card_disconnect() for disconnecting all belonging components
|
||||
* and waits until all pending files get closed.
|
||||
* It assures that all accesses from user-space finished so that the driver
|
||||
* can release its resources gracefully.
|
||||
*/
|
||||
void snd_card_disconnect_sync(struct snd_card *card)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = snd_card_disconnect(card);
|
||||
if (err < 0) {
|
||||
dev_err(card->dev,
|
||||
"snd_card_disconnect error (%d), skipping sync\n",
|
||||
err);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irq(&card->files_lock);
|
||||
wait_event_lock_irq(card->remove_sleep,
|
||||
list_empty(&card->files_list),
|
||||
card->files_lock);
|
||||
spin_unlock_irq(&card->files_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_card_disconnect_sync);
|
||||
|
||||
static int snd_card_do_free(struct snd_card *card)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
|
||||
|
@ -957,6 +987,8 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (list_empty(&card->files_list))
|
||||
wake_up_all(&card->remove_sleep);
|
||||
spin_unlock(&card->files_lock);
|
||||
if (!found) {
|
||||
dev_err(card->dev, "card file remove problem (%p)\n", file);
|
||||
|
|
|
@ -310,7 +310,7 @@ EXPORT_SYMBOL(snd_jack_set_parent);
|
|||
* @type: Jack report type for this key
|
||||
* @keytype: Input layer key type to be reported
|
||||
*
|
||||
* Map a SND_JACK_BTN_ button type to an input layer key, allowing
|
||||
* Map a SND_JACK_BTN_* button type to an input layer key, allowing
|
||||
* reporting of keys on accessories via the jack abstraction. If no
|
||||
* mapping is provided but keys are enabled in the jack type then
|
||||
* BTN_n numeric buttons will be reported.
|
||||
|
|
|
@ -775,6 +775,9 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
|
|||
.dev_register = snd_pcm_dev_register,
|
||||
.dev_disconnect = snd_pcm_dev_disconnect,
|
||||
};
|
||||
static struct snd_device_ops internal_ops = {
|
||||
.dev_free = snd_pcm_dev_free,
|
||||
};
|
||||
|
||||
if (snd_BUG_ON(!card))
|
||||
return -ENXIO;
|
||||
|
@ -801,7 +804,8 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
|
|||
if (err < 0)
|
||||
goto free_pcm;
|
||||
|
||||
err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops);
|
||||
err = snd_device_new(card, SNDRV_DEV_PCM, pcm,
|
||||
internal ? &internal_ops : &ops);
|
||||
if (err < 0)
|
||||
goto free_pcm;
|
||||
|
||||
|
@ -1099,8 +1103,6 @@ static int snd_pcm_dev_register(struct snd_device *device)
|
|||
if (snd_BUG_ON(!device || !device->device_data))
|
||||
return -ENXIO;
|
||||
pcm = device->device_data;
|
||||
if (pcm->internal)
|
||||
return 0;
|
||||
|
||||
mutex_lock(®ister_mutex);
|
||||
err = snd_pcm_add(pcm);
|
||||
|
@ -1152,6 +1154,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
|
|||
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
if (substream->runtime) {
|
||||
if (snd_pcm_running(substream))
|
||||
snd_pcm_stop(substream,
|
||||
SNDRV_PCM_STATE_DISCONNECTED);
|
||||
/* to be sure, set the state unconditionally */
|
||||
substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
|
||||
wake_up(&substream->runtime->sleep);
|
||||
wake_up(&substream->runtime->tsleep);
|
||||
|
@ -1159,12 +1165,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
|
|||
snd_pcm_stream_unlock_irq(substream);
|
||||
}
|
||||
}
|
||||
if (!pcm->internal) {
|
||||
pcm_call_notify(pcm, n_disconnect);
|
||||
}
|
||||
|
||||
pcm_call_notify(pcm, n_disconnect);
|
||||
for (cidx = 0; cidx < 2; cidx++) {
|
||||
if (!pcm->internal)
|
||||
snd_unregister_device(&pcm->streams[cidx].dev);
|
||||
snd_unregister_device(&pcm->streams[cidx].dev);
|
||||
free_chmap(&pcm->streams[cidx]);
|
||||
}
|
||||
mutex_unlock(&pcm->open_mutex);
|
||||
|
|
|
@ -195,7 +195,6 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
|
|||
|
||||
int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime;
|
||||
struct snd_pcm *pcm = substream->pcm;
|
||||
struct snd_pcm_str *pstr = substream->pstr;
|
||||
|
||||
|
@ -211,7 +210,6 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
|
|||
info->subdevices_count = pstr->substream_count;
|
||||
info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
|
||||
strlcpy(info->subname, substream->name, sizeof(info->subname));
|
||||
runtime = substream->runtime;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -802,6 +802,10 @@ static int snd_seq_deliver_event(struct snd_seq_client *client, struct snd_seq_e
|
|||
return -EMLINK;
|
||||
}
|
||||
|
||||
if (snd_seq_ev_is_variable(event) &&
|
||||
snd_BUG_ON(atomic && (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR)))
|
||||
return -EINVAL;
|
||||
|
||||
if (event->queue == SNDRV_SEQ_ADDRESS_SUBSCRIBERS ||
|
||||
event->dest.client == SNDRV_SEQ_ADDRESS_SUBSCRIBERS)
|
||||
result = deliver_to_subscribers(client, event, atomic, hop);
|
||||
|
|
|
@ -1069,15 +1069,17 @@ EXPORT_SYMBOL(snd_timer_global_register);
|
|||
|
||||
struct snd_timer_system_private {
|
||||
struct timer_list tlist;
|
||||
struct snd_timer *snd_timer;
|
||||
unsigned long last_expires;
|
||||
unsigned long last_jiffies;
|
||||
unsigned long correction;
|
||||
};
|
||||
|
||||
static void snd_timer_s_function(unsigned long data)
|
||||
static void snd_timer_s_function(struct timer_list *t)
|
||||
{
|
||||
struct snd_timer *timer = (struct snd_timer *)data;
|
||||
struct snd_timer_system_private *priv = timer->private_data;
|
||||
struct snd_timer_system_private *priv = from_timer(priv, t,
|
||||
tlist);
|
||||
struct snd_timer *timer = priv->snd_timer;
|
||||
unsigned long jiff = jiffies;
|
||||
if (time_after(jiff, priv->last_expires))
|
||||
priv->correction += (long)jiff - (long)priv->last_expires;
|
||||
|
@ -1159,7 +1161,8 @@ static int snd_timer_register_system(void)
|
|||
snd_timer_free(timer);
|
||||
return -ENOMEM;
|
||||
}
|
||||
setup_timer(&priv->tlist, snd_timer_s_function, (unsigned long) timer);
|
||||
priv->snd_timer = timer;
|
||||
timer_setup(&priv->tlist, snd_timer_s_function, 0);
|
||||
timer->private_data = priv;
|
||||
timer->private_free = snd_timer_free_system;
|
||||
return snd_timer_global_register(timer);
|
||||
|
|
|
@ -529,9 +529,9 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
|
|||
return running;
|
||||
}
|
||||
|
||||
static void loopback_timer_function(unsigned long data)
|
||||
static void loopback_timer_function(struct timer_list *t)
|
||||
{
|
||||
struct loopback_pcm *dpcm = (struct loopback_pcm *)data;
|
||||
struct loopback_pcm *dpcm = from_timer(dpcm, t, timer);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dpcm->cable->lock, flags);
|
||||
|
@ -675,8 +675,7 @@ static int loopback_open(struct snd_pcm_substream *substream)
|
|||
}
|
||||
dpcm->loopback = loopback;
|
||||
dpcm->substream = substream;
|
||||
setup_timer(&dpcm->timer, loopback_timer_function,
|
||||
(unsigned long)dpcm);
|
||||
timer_setup(&dpcm->timer, loopback_timer_function, 0);
|
||||
|
||||
cable = loopback->cables[substream->number][dev];
|
||||
if (!cable) {
|
||||
|
|
|
@ -306,9 +306,9 @@ static int dummy_systimer_prepare(struct snd_pcm_substream *substream)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void dummy_systimer_callback(unsigned long data)
|
||||
static void dummy_systimer_callback(struct timer_list *t)
|
||||
{
|
||||
struct dummy_systimer_pcm *dpcm = (struct dummy_systimer_pcm *)data;
|
||||
struct dummy_systimer_pcm *dpcm = from_timer(dpcm, t, timer);
|
||||
unsigned long flags;
|
||||
int elapsed = 0;
|
||||
|
||||
|
@ -343,8 +343,7 @@ static int dummy_systimer_create(struct snd_pcm_substream *substream)
|
|||
if (!dpcm)
|
||||
return -ENOMEM;
|
||||
substream->runtime->private_data = dpcm;
|
||||
setup_timer(&dpcm->timer, dummy_systimer_callback,
|
||||
(unsigned long) dpcm);
|
||||
timer_setup(&dpcm->timer, dummy_systimer_callback, 0);
|
||||
spin_lock_init(&dpcm->lock);
|
||||
dpcm->substream = substream;
|
||||
return 0;
|
||||
|
|
|
@ -169,9 +169,9 @@ EXPORT_SYMBOL(snd_mpu401_uart_interrupt_tx);
|
|||
* timer callback
|
||||
* reprogram the timer and call the interrupt job
|
||||
*/
|
||||
static void snd_mpu401_uart_timer(unsigned long data)
|
||||
static void snd_mpu401_uart_timer(struct timer_list *t)
|
||||
{
|
||||
struct snd_mpu401 *mpu = (struct snd_mpu401 *)data;
|
||||
struct snd_mpu401 *mpu = from_timer(mpu, t, timer);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mpu->timer_lock, flags);
|
||||
|
@ -191,8 +191,7 @@ static void snd_mpu401_uart_add_timer (struct snd_mpu401 *mpu, int input)
|
|||
|
||||
spin_lock_irqsave (&mpu->timer_lock, flags);
|
||||
if (mpu->timer_invoked == 0) {
|
||||
setup_timer(&mpu->timer, snd_mpu401_uart_timer,
|
||||
(unsigned long)mpu);
|
||||
timer_setup(&mpu->timer, snd_mpu401_uart_timer, 0);
|
||||
mod_timer(&mpu->timer, 1 + jiffies);
|
||||
}
|
||||
mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER :
|
||||
|
|
|
@ -406,10 +406,10 @@ static void snd_mtpav_input_trigger(struct snd_rawmidi_substream *substream, int
|
|||
* timer interrupt for outputs
|
||||
*/
|
||||
|
||||
static void snd_mtpav_output_timer(unsigned long data)
|
||||
static void snd_mtpav_output_timer(struct timer_list *t)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct mtpav *chip = (struct mtpav *)data;
|
||||
struct mtpav *chip = from_timer(chip, t, timer);
|
||||
int p;
|
||||
|
||||
spin_lock_irqsave(&chip->spinlock, flags);
|
||||
|
@ -707,8 +707,7 @@ static int snd_mtpav_probe(struct platform_device *dev)
|
|||
mtp_card->share_irq = 0;
|
||||
mtp_card->inmidistate = 0;
|
||||
mtp_card->outmidihwport = 0xffffffff;
|
||||
setup_timer(&mtp_card->timer, snd_mtpav_output_timer,
|
||||
(unsigned long) mtp_card);
|
||||
timer_setup(&mtp_card->timer, snd_mtpav_output_timer, 0);
|
||||
|
||||
card->private_free = snd_mtpav_free;
|
||||
|
||||
|
|
|
@ -238,10 +238,10 @@ static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op,
|
|||
/*
|
||||
* System timer interrupt function
|
||||
*/
|
||||
void snd_opl3_timer_func(unsigned long data)
|
||||
void snd_opl3_timer_func(struct timer_list *t)
|
||||
{
|
||||
|
||||
struct snd_opl3 *opl3 = (struct snd_opl3 *)data;
|
||||
struct snd_opl3 *opl3 = from_timer(opl3, t, tlist);
|
||||
unsigned long flags;
|
||||
int again = 0;
|
||||
int i;
|
||||
|
|
|
@ -248,7 +248,7 @@ static int snd_opl3_seq_probe(struct device *_dev)
|
|||
}
|
||||
|
||||
/* setup system timer */
|
||||
setup_timer(&opl3->tlist, snd_opl3_timer_func, (unsigned long) opl3);
|
||||
timer_setup(&opl3->tlist, snd_opl3_timer_func, 0);
|
||||
spin_lock_init(&opl3->sys_timer_lock);
|
||||
opl3->sys_timer_status = 0;
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan, struct snd_midi_chann
|
|||
void snd_opl3_sysex(void *p, unsigned char *buf, int len, int parsed, struct snd_midi_channel_set *chset);
|
||||
|
||||
void snd_opl3_calc_volume(unsigned char *reg, int vel, struct snd_midi_channel *chan);
|
||||
void snd_opl3_timer_func(unsigned long data);
|
||||
void snd_opl3_timer_func(struct timer_list *t);
|
||||
|
||||
/* Prototypes for opl3_drums.c */
|
||||
void snd_opl3_load_drums(struct snd_opl3 *opl3);
|
||||
|
|
|
@ -309,12 +309,12 @@ static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id)
|
|||
}
|
||||
|
||||
/* When the polling mode, this function calls snd_uart16550_io_loop. */
|
||||
static void snd_uart16550_buffer_timer(unsigned long data)
|
||||
static void snd_uart16550_buffer_timer(struct timer_list *t)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct snd_uart16550 *uart;
|
||||
|
||||
uart = (struct snd_uart16550 *)data;
|
||||
uart = from_timer(uart, t, buffer_timer);
|
||||
spin_lock_irqsave(&uart->open_lock, flags);
|
||||
snd_uart16550_del_timer(uart);
|
||||
snd_uart16550_io_loop(uart);
|
||||
|
@ -828,8 +828,7 @@ static int snd_uart16550_create(struct snd_card *card,
|
|||
uart->prev_in = 0;
|
||||
uart->rstatus = 0;
|
||||
memset(uart->prev_status, 0x80, sizeof(unsigned char) * SNDRV_SERIAL_MAX_OUTS);
|
||||
setup_timer(&uart->buffer_timer, snd_uart16550_buffer_timer,
|
||||
(unsigned long)uart);
|
||||
timer_setup(&uart->buffer_timer, snd_uart16550_buffer_timer, 0);
|
||||
uart->timer_running = 0;
|
||||
|
||||
/* Register device */
|
||||
|
|
|
@ -319,7 +319,8 @@ int snd_hdac_bus_parse_capabilities(struct hdac_bus *bus)
|
|||
break;
|
||||
|
||||
default:
|
||||
dev_dbg(bus->dev, "Unknown capability %d\n", cur_cap);
|
||||
dev_err(bus->dev, "Unknown capability %d\n", cur_cap);
|
||||
cur_cap = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus,
|
|||
|
||||
fg = codec->afg ? codec->afg : codec->mfg;
|
||||
|
||||
err = snd_hdac_refresh_widgets(codec);
|
||||
err = snd_hdac_refresh_widgets(codec, false);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
|
@ -388,11 +388,12 @@ static void setup_fg_nodes(struct hdac_device *codec)
|
|||
/**
|
||||
* snd_hdac_refresh_widgets - Reset the widget start/end nodes
|
||||
* @codec: the codec object
|
||||
* @sysfs: re-initialize sysfs tree, too
|
||||
*/
|
||||
int snd_hdac_refresh_widgets(struct hdac_device *codec)
|
||||
int snd_hdac_refresh_widgets(struct hdac_device *codec, bool sysfs)
|
||||
{
|
||||
hda_nid_t start_nid;
|
||||
int nums;
|
||||
int nums, err;
|
||||
|
||||
nums = snd_hdac_get_sub_nodes(codec, codec->afg, &start_nid);
|
||||
if (!start_nid || nums <= 0 || nums >= 0xff) {
|
||||
|
@ -401,6 +402,12 @@ int snd_hdac_refresh_widgets(struct hdac_device *codec)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sysfs) {
|
||||
err = hda_widget_sysfs_reinit(codec, start_nid, nums);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
codec->num_nodes = nums;
|
||||
codec->start_nid = start_nid;
|
||||
codec->end_nid = start_nid + nums;
|
||||
|
@ -408,36 +415,6 @@ int snd_hdac_refresh_widgets(struct hdac_device *codec)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_refresh_widgets);
|
||||
|
||||
/**
|
||||
* snd_hdac_refresh_widget_sysfs - Reset the codec widgets and reinit the
|
||||
* codec sysfs
|
||||
* @codec: the codec object
|
||||
*
|
||||
* first we need to remove sysfs, then refresh widgets and lastly
|
||||
* recreate it
|
||||
*/
|
||||
int snd_hdac_refresh_widget_sysfs(struct hdac_device *codec)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (device_is_registered(&codec->dev))
|
||||
hda_widget_sysfs_exit(codec);
|
||||
ret = snd_hdac_refresh_widgets(codec);
|
||||
if (ret) {
|
||||
dev_err(&codec->dev, "failed to refresh widget: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (device_is_registered(&codec->dev)) {
|
||||
ret = hda_widget_sysfs_init(codec);
|
||||
if (ret) {
|
||||
dev_err(&codec->dev, "failed to init sysfs: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_refresh_widget_sysfs);
|
||||
|
||||
/* return CONNLIST_LEN parameter of the given widget */
|
||||
static unsigned int get_num_conns(struct hdac_device *codec, hda_nid_t nid)
|
||||
{
|
||||
|
|
|
@ -414,3 +414,50 @@ void hda_widget_sysfs_exit(struct hdac_device *codec)
|
|||
{
|
||||
widget_tree_free(codec);
|
||||
}
|
||||
|
||||
int hda_widget_sysfs_reinit(struct hdac_device *codec,
|
||||
hda_nid_t start_nid, int num_nodes)
|
||||
{
|
||||
struct hdac_widget_tree *tree;
|
||||
hda_nid_t end_nid = start_nid + num_nodes;
|
||||
hda_nid_t nid;
|
||||
int i;
|
||||
|
||||
if (!codec->widgets)
|
||||
return hda_widget_sysfs_init(codec);
|
||||
|
||||
tree = kmemdup(codec->widgets, sizeof(*tree), GFP_KERNEL);
|
||||
if (!tree)
|
||||
return -ENOMEM;
|
||||
|
||||
tree->nodes = kcalloc(num_nodes + 1, sizeof(*tree->nodes), GFP_KERNEL);
|
||||
if (!tree->nodes) {
|
||||
kfree(tree);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* prune non-existing nodes */
|
||||
for (i = 0, nid = codec->start_nid; i < codec->num_nodes; i++, nid++) {
|
||||
if (nid < start_nid || nid >= end_nid)
|
||||
free_widget_node(codec->widgets->nodes[i],
|
||||
&widget_node_group);
|
||||
}
|
||||
|
||||
/* add new nodes */
|
||||
for (i = 0, nid = start_nid; i < num_nodes; i++, nid++) {
|
||||
if (nid < codec->start_nid || nid >= codec->end_nid)
|
||||
add_widget_node(tree->root, nid, &widget_node_group,
|
||||
&tree->nodes[i]);
|
||||
else
|
||||
tree->nodes[i] =
|
||||
codec->widgets->nodes[nid - codec->start_nid];
|
||||
}
|
||||
|
||||
/* replace with the new tree */
|
||||
kfree(codec->widgets->nodes);
|
||||
kfree(codec->widgets);
|
||||
codec->widgets = tree;
|
||||
|
||||
kobject_uevent(tree->root, KOBJ_CHANGE);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ static inline unsigned int get_wcaps_channels(u32 wcaps)
|
|||
|
||||
extern const struct attribute_group *hdac_dev_attr_groups[];
|
||||
int hda_widget_sysfs_init(struct hdac_device *codec);
|
||||
int hda_widget_sysfs_reinit(struct hdac_device *codec, hda_nid_t start_nid,
|
||||
int num_nodes);
|
||||
void hda_widget_sysfs_exit(struct hdac_device *codec);
|
||||
|
||||
#endif /* __HDAC_LOCAL_H */
|
||||
|
|
|
@ -35,7 +35,7 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
#define AK4117_ADDR 0x00 /* fixed address */
|
||||
|
||||
static void snd_ak4117_timer(unsigned long data);
|
||||
static void snd_ak4117_timer(struct timer_list *t);
|
||||
|
||||
static void reg_write(struct ak4117 *ak4117, unsigned char reg, unsigned char val)
|
||||
{
|
||||
|
@ -91,7 +91,7 @@ int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t
|
|||
chip->read = read;
|
||||
chip->write = write;
|
||||
chip->private_data = private_data;
|
||||
setup_timer(&chip->timer, snd_ak4117_timer, (unsigned long)chip);
|
||||
timer_setup(&chip->timer, snd_ak4117_timer, 0);
|
||||
|
||||
for (reg = 0; reg < 5; reg++)
|
||||
chip->regmap[reg] = pgm[reg];
|
||||
|
@ -529,9 +529,9 @@ int snd_ak4117_check_rate_and_errors(struct ak4117 *ak4117, unsigned int flags)
|
|||
return res;
|
||||
}
|
||||
|
||||
static void snd_ak4117_timer(unsigned long data)
|
||||
static void snd_ak4117_timer(struct timer_list *t)
|
||||
{
|
||||
struct ak4117 *chip = (struct ak4117 *)data;
|
||||
struct ak4117 *chip = from_timer(chip, t, timer);
|
||||
|
||||
if (chip->init)
|
||||
return;
|
||||
|
|
|
@ -193,9 +193,9 @@ static inline int emu8k_get_curpos(struct snd_emu8k_pcm *rec, int ch)
|
|||
* timer interrupt handler
|
||||
* check the current position and update the period if necessary.
|
||||
*/
|
||||
static void emu8k_pcm_timer_func(unsigned long data)
|
||||
static void emu8k_pcm_timer_func(struct timer_list *t)
|
||||
{
|
||||
struct snd_emu8k_pcm *rec = (struct snd_emu8k_pcm *)data;
|
||||
struct snd_emu8k_pcm *rec = from_timer(rec, t, timer);
|
||||
int ptr, delta;
|
||||
|
||||
spin_lock(&rec->timer_lock);
|
||||
|
@ -241,7 +241,7 @@ static int emu8k_pcm_open(struct snd_pcm_substream *subs)
|
|||
runtime->private_data = rec;
|
||||
|
||||
spin_lock_init(&rec->timer_lock);
|
||||
setup_timer(&rec->timer, emu8k_pcm_timer_func, (unsigned long)rec);
|
||||
timer_setup(&rec->timer, emu8k_pcm_timer_func, 0);
|
||||
|
||||
runtime->hw = emu8k_pcm_hw;
|
||||
runtime->hw.buffer_bytes_max = emu->mem_size - LOOP_BLANK_SIZE * 3;
|
||||
|
|
|
@ -138,6 +138,7 @@ static int snd_sb8dsp_midi_output_close(struct snd_rawmidi_substream *substream)
|
|||
struct snd_sb *chip;
|
||||
|
||||
chip = substream->rmidi->private_data;
|
||||
del_timer_sync(&chip->midi_timer);
|
||||
spin_lock_irqsave(&chip->open_lock, flags);
|
||||
chip->open &= ~(SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER);
|
||||
chip->midi_substream_output = NULL;
|
||||
|
@ -209,10 +210,10 @@ static void snd_sb8dsp_midi_output_write(struct snd_rawmidi_substream *substream
|
|||
}
|
||||
}
|
||||
|
||||
static void snd_sb8dsp_midi_output_timer(unsigned long data)
|
||||
static void snd_sb8dsp_midi_output_timer(struct timer_list *t)
|
||||
{
|
||||
struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *) data;
|
||||
struct snd_sb * chip = substream->rmidi->private_data;
|
||||
struct snd_sb *chip = from_timer(chip, t, midi_timer);
|
||||
struct snd_rawmidi_substream *substream = chip->midi_substream_output;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chip->open_lock, flags);
|
||||
|
@ -230,9 +231,6 @@ static void snd_sb8dsp_midi_output_trigger(struct snd_rawmidi_substream *substre
|
|||
spin_lock_irqsave(&chip->open_lock, flags);
|
||||
if (up) {
|
||||
if (!(chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER)) {
|
||||
setup_timer(&chip->midi_timer,
|
||||
snd_sb8dsp_midi_output_timer,
|
||||
(unsigned long) substream);
|
||||
mod_timer(&chip->midi_timer, 1 + jiffies);
|
||||
chip->open |= SB_OPEN_MIDI_OUTPUT_TRIGGER;
|
||||
}
|
||||
|
@ -275,6 +273,7 @@ int snd_sb8dsp_midi(struct snd_sb *chip, int device)
|
|||
if (chip->hardware >= SB_HW_20)
|
||||
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
|
||||
rmidi->private_data = chip;
|
||||
timer_setup(&chip->midi_timer, snd_sb8dsp_midi_output_timer, 0);
|
||||
chip->rmidi = rmidi;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -349,10 +349,10 @@ static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *subst
|
|||
spin_unlock_irqrestore (&midi->virtual, flags);
|
||||
}
|
||||
|
||||
static void snd_wavefront_midi_output_timer(unsigned long data)
|
||||
static void snd_wavefront_midi_output_timer(struct timer_list *t)
|
||||
{
|
||||
snd_wavefront_card_t *card = (snd_wavefront_card_t *)data;
|
||||
snd_wavefront_midi_t *midi = &card->wavefront.midi;
|
||||
snd_wavefront_midi_t *midi = from_timer(midi, t, timer);
|
||||
snd_wavefront_card_t *card = midi->timer_card;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave (&midi->virtual, flags);
|
||||
|
@ -383,9 +383,9 @@ static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *subs
|
|||
if (up) {
|
||||
if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
|
||||
if (!midi->istimer) {
|
||||
setup_timer(&midi->timer,
|
||||
timer_setup(&midi->timer,
|
||||
snd_wavefront_midi_output_timer,
|
||||
(unsigned long) substream->rmidi->card->private_data);
|
||||
0);
|
||||
mod_timer(&midi->timer, 1 + jiffies);
|
||||
}
|
||||
midi->istimer++;
|
||||
|
|
|
@ -1,369 +0,0 @@
|
|||
Note these changes relate to Hannu's code and don't include the changes
|
||||
made outside of this for modularising the sound
|
||||
|
||||
Changelog for version 3.8o
|
||||
--------------------------
|
||||
|
||||
Since 3.8h
|
||||
- Included support for OPL3-SA1 and SoftOSS
|
||||
|
||||
Since 3.8
|
||||
- Fixed SNDCTL_DSP_GETOSPACE
|
||||
- Compatibility fixes for Linux 2.1.47
|
||||
|
||||
Since 3.8-beta21
|
||||
- Fixed all known bugs (I think).
|
||||
|
||||
Since 3.8-beta8
|
||||
- Lot of fixes to audio playback code in dmabuf.c
|
||||
|
||||
Since 3.8-beta6
|
||||
- Fixed the famous Quake delay bug.
|
||||
|
||||
Since 3.8-beta5
|
||||
- Fixed many bugs in audio playback.
|
||||
|
||||
Since 3.8-beta4
|
||||
- Just minor changes.
|
||||
|
||||
Since 3.8-beta1
|
||||
- Major rewrite of audio playback handling.
|
||||
- Added AWE32 support by Takashi Iwai (in ./lowlevel/).
|
||||
|
||||
Since 3.7-beta#
|
||||
- Passing of ioctl() parameters between soundcard.c and other modules has been
|
||||
changed so that arg always points to kernel space.
|
||||
- Some bugfixes.
|
||||
|
||||
Since 3.7-beta5
|
||||
- Disabled MIDI input with GUS PnP (Interwave). There seems to be constant
|
||||
stream of received 0x00 bytes when the MIDI receiver is enabled.
|
||||
|
||||
Since 3.5
|
||||
- Changes almost everywhere.
|
||||
- Support for OPTi 82C924-based sound cards.
|
||||
|
||||
Since 3.5.4-beta8
|
||||
- Fixed a bug in handling of non-fragment sized writes in 16 bit/stereo mode
|
||||
with GUS.
|
||||
- Limited minimum fragment size with some audio devices (GUS=512 and
|
||||
SB=32). These devices require more time to "recover" from processing
|
||||
of each fragment.
|
||||
|
||||
Since 3.5.4-beta6/7
|
||||
- There seems to be problems in the OPTi 82C930 so cards based on this
|
||||
chip don't necessarily work yet. There are problems in detecting the
|
||||
MIDI interface. Also mixer volumes may be seriously wrong on some systems.
|
||||
You can safely use this driver version with C930 if it looks to work.
|
||||
However please don't complain if you have problems with it. C930 support
|
||||
should be fixed in future releases.
|
||||
- Got initialization of GUS PnP to work. With this version GUS PnP should
|
||||
work in GUS compatible mode after initialization using isapnptools.
|
||||
- Fixed a bug in handling of full duplex cards in write only mode. This has
|
||||
been causing "audio device opening" errors with RealAudio player.
|
||||
|
||||
Since 3.5.4.beta5
|
||||
- Changes to OPTi 82C930 driver.
|
||||
- Major changes to the Soundscape driver. The driver requires now just one
|
||||
DMA channel. The extra audio/dsp device (the "Not functional" one) used
|
||||
for code download in the earlier versions has been eliminated. There is now
|
||||
just one /dev/dsp# device which is used both for code download and audio.
|
||||
|
||||
Since 3.5.4.beta4
|
||||
- Minor changes.
|
||||
|
||||
Since 3.5.4-beta2
|
||||
- Fixed silent playback with ESS 688/1688.
|
||||
- Got SB16 to work without the 16 bit DMA channel (only the 8 bit one
|
||||
is required for 8 and 16 bit modes).
|
||||
- Added the "lowlevel" subdirectory for additional low level drivers that
|
||||
are not part of USS core. See lowlevel/README for more info.
|
||||
- Included support for ACI mixer (by Markus Kuhn). ACI is a mixer used in
|
||||
miroPCM sound cards. See lowlevel/aci.readme for more info.
|
||||
- Support for Aztech Washington chipset (AZT2316 ASIC).
|
||||
|
||||
Since 3.5.4-beta1
|
||||
- Reduced clicking with AD1848.
|
||||
- Support for OPTi 82C930. Only half duplex at this time. 16 bit playback
|
||||
is sometimes just white noise (occurs randomly).
|
||||
|
||||
Since 3.5.2
|
||||
- Major changes to the SB/Jazz16/ESS driver (most parts rewritten).
|
||||
The most noticeable new feature is support for multiple SB cards at the same
|
||||
time.
|
||||
- Renamed sb16_midi.c to uart401.c. Also modified it to work also with
|
||||
other MPU401 UART compatible cards than SB16/ESS/Jazz.
|
||||
- Some changes which reduce clicking in audio playback.
|
||||
- Copying policy is now GPL.
|
||||
|
||||
Since 3.5.1
|
||||
- TB Maui initialization support
|
||||
Since 3.5
|
||||
- Improved handling of playback underrun situations.
|
||||
|
||||
Since 3.5-beta10
|
||||
- Bug fixing
|
||||
|
||||
Since 3.5-beta9
|
||||
- Fixed for compatibility with Linux 1.3.70 and later.
|
||||
- Changed boot time passing of 16 bit DMA channel number to SB driver.
|
||||
|
||||
Since 3.5-beta8
|
||||
- Minor changes
|
||||
|
||||
Since 3.5-beta7
|
||||
- enhancements to configure program (by Jeff Tranter):
|
||||
- prompts are in same format as 1.3.x Linux kernel config program
|
||||
- on-line help for each question
|
||||
- fixed some compile warnings detected by gcc/g++ -Wall
|
||||
- minor grammatical changes to prompts
|
||||
|
||||
Since 3.5-beta6
|
||||
- Fixed bugs in mmap() support.
|
||||
- Minor changes to Maui driver.
|
||||
|
||||
Since 3.5-beta5
|
||||
- Fixed crash after recording with ESS688. It's generally a good
|
||||
idea to stop inbound DMA transfers before freeing the memory
|
||||
buffer.
|
||||
- Fixed handling of AD1845 codec (for example Shuttle Sound System).
|
||||
- Few other fixes.
|
||||
|
||||
Since 3.5-beta4
|
||||
- Fixed bug in handling of uninitialized instruments with GUS.
|
||||
|
||||
Since 3.5-beta3
|
||||
- Few changes which decrease popping at end/beginning of audio playback.
|
||||
|
||||
Since 3.5-beta2
|
||||
- Removed MAD16+CS4231 hack made in previous version since it didn't
|
||||
help.
|
||||
- Fixed the above bug in proper way and in proper place. Many thanks
|
||||
to James Hightower.
|
||||
|
||||
Since 3.5-beta1
|
||||
- Bug fixes.
|
||||
- Full duplex audio with MAD16+CS4231 may work now. The driver configures
|
||||
SB DMA of MAD16 so that it doesn't conflict with codec's DMA channels.
|
||||
The side effect is that all 8 bit DMA channels (0,1,3) are populated in
|
||||
duplex mode.
|
||||
|
||||
Since 3.5-alpha9
|
||||
- Bug fixes (mostly in Jazz16 and ESS1688/688 supports).
|
||||
- Temporarily disabled recording with ESS1688/688 since it causes crash.
|
||||
- Changed audio buffer partitioning algorithm so that it selects
|
||||
smaller fragment size than earlier. This improves real time capabilities
|
||||
of the driver and makes recording to disk to work better. Unfortunately
|
||||
this change breaks some programs which assume that fragments cannot be
|
||||
shorter than 4096 bytes.
|
||||
|
||||
Since 3.5-alpha8
|
||||
- Bug fixes
|
||||
|
||||
Since 3.5-alpha7
|
||||
- Linux kernel compatible configuration (_EXPERIMENTAL_). Enable
|
||||
using command "cd /linux/drivers/sound;make script" and then
|
||||
just run kernel's make config normally.
|
||||
- Minor fixes to the SB support. Hopefully the driver works with
|
||||
all SB models now.
|
||||
- Added support for ESS ES1688 "AudioDrive" based cards.
|
||||
|
||||
Since 3.5-alpha6
|
||||
- SB Pro and SB16 supports are no longer separately selectable options.
|
||||
Enabling SB enables them too.
|
||||
- Changed all #ifndef EXCLUDE_xx stuff to #ifdef CONFIG_xx. Modified
|
||||
configure to handle this.
|
||||
- Removed initialization messages from the
|
||||
modularized version. They can be enabled by using init_trace=1 in
|
||||
the insmod command line (insmod sound init_trace=1).
|
||||
- More AIX stuff.
|
||||
- Added support for synchronizing dsp/audio devices with /dev/sequencer.
|
||||
- mmap() support for dsp/audio devices.
|
||||
|
||||
Since 3.5-alpha5
|
||||
- AIX port.
|
||||
- Changed some xxx_PATCH macros in soundcard.h to work with
|
||||
big endian machines.
|
||||
|
||||
Since 3.5-alpha4
|
||||
- Removed the 'setfx' stuff from the version distributed with kernel
|
||||
sources. Running 'setfx' is required again.
|
||||
|
||||
Since 3.5-alpha3
|
||||
- Moved stuff from the 'setfx' program to the AudioTrix Pro driver.
|
||||
|
||||
Since 3.5-alpha2
|
||||
- Modifications to makefile and configure.c. Unnecessary sources
|
||||
are no longer compiled. Newly created local.h is also copied to
|
||||
/etc/soundconf. "make oldconfig" reads /etc/soundconf and produces
|
||||
new local.h which is compatible with current version of the driver.
|
||||
- Some fixes to the SB16 support.
|
||||
- Fixed random protection fault in gus_wave.c
|
||||
|
||||
Since 3.5-alpha1
|
||||
- Modified to work with Linux-1.3.33 and later
|
||||
- Some minor changes
|
||||
|
||||
Since 3.0.2
|
||||
- Support for CS4232 based PnP cards (AcerMagic S23 etc).
|
||||
- Full duplex support for some CS4231, CS4232 and AD1845 based cards
|
||||
(GUS MAX, AudioTrix Pro, AcerMagic S23 and many MAD16/Mozart cards
|
||||
having a codec mentioned above).
|
||||
- Almost fully rewritten loadable modules support.
|
||||
- Fixed some bugs.
|
||||
- Huge amount of testing (more testing is still required).
|
||||
- mmap() support (works with some cards). Requires much more testing.
|
||||
- Sample/patch/program loading for TB Maui/Tropez. No initialization
|
||||
since TB doesn't allow me to release that code.
|
||||
- Using CS4231 compatible codecs as timer for /dev/music.
|
||||
|
||||
Since 3.0.1
|
||||
- Added allocation of I/O ports, DMA channels and interrupts
|
||||
to the initialization code. This may break modules support since
|
||||
the driver may not free some resources on unload. Should be fixed soon.
|
||||
|
||||
Since 3.0
|
||||
- Some important bug fixes.
|
||||
- select() for /dev/dsp and /dev/audio (Linux only).
|
||||
(To use select() with read, you have to call read() to start
|
||||
the recording. Calling write() kills recording immediately so
|
||||
use select() carefully when you are writing a half duplex app.
|
||||
Full duplex mode is not implemented yet.) Select works also with
|
||||
/dev/sequencer and /dev/music. Maybe with /dev/midi## too.
|
||||
|
||||
Since 3.0-beta2
|
||||
- Minor fixes.
|
||||
- Added Readme.cards
|
||||
|
||||
Since 3.0-beta1
|
||||
- Minor fixes to the modules support.
|
||||
- Eliminated call to sb_free_irq() in ad1848.c
|
||||
- Rewritten MAD16&Mozart support (not tested with MAD16 Pro).
|
||||
- Fix to DMA initialization of PSS cards.
|
||||
- Some fixes to ad1848/cs42xx mixer support (GUS MAX, MSS, etc.)
|
||||
- Fixed some bugs in the PSS driver which caused I/O errors with
|
||||
the MSS mode (/dev/dsp).
|
||||
|
||||
Since 3.0-950506
|
||||
- Recording with GUS MAX fixed. It works when the driver is configured
|
||||
to use two DMA channels with GUS MAX (16 bit ones recommended).
|
||||
|
||||
Since 3.0-94xxxx
|
||||
- Too many changes
|
||||
|
||||
Since 3.0-940818
|
||||
- Fixes for Linux 1.1.4x.
|
||||
- Disables Disney Sound System with SG NX Pro 16 (less noise).
|
||||
|
||||
Since 2.90-2
|
||||
- Fixes to soundcard.h
|
||||
- Non blocking mode to /dev/sequencer
|
||||
- Experimental detection code for Ensoniq Soundscape.
|
||||
|
||||
Since 2.90
|
||||
- Minor and major bug fixes
|
||||
|
||||
Since pre-3.0-940712
|
||||
- GUS MAX support
|
||||
- Partially working MSS/WSS support (could work with some cards).
|
||||
- Hardware u-Law and A-Law support with AD1848/CS4248 and CS4231 codecs
|
||||
(GUS MAX, GUS16, WSS etc). Hardware ADPCM is possible with GUS16 and
|
||||
GUS MAX, but it doesn't work yet.
|
||||
Since pre-3.0-940426
|
||||
- AD1848/CS4248/CS4231 codec support (MSS, GUS MAX, Aztec, Orchid etc).
|
||||
This codec chip is used in various sound cards. This version is developed
|
||||
for the 16 bit daughtercard of GUS. It should work with other cards also
|
||||
if the following requirements are met:
|
||||
- The I/O, IRQ and DMA settings are jumper selectable or
|
||||
the card is initialized by booting DOS before booting Linux (etc.).
|
||||
- You add the IO, IRQ and DMA settings manually to the local.h.
|
||||
(Just define GUS16_BASE, GUS16_IRQ and GUS16_DMA). Note that
|
||||
the base address bust be the base address of the codec chip not the
|
||||
card itself. For the GUS16 these are the same but most MSS compatible
|
||||
cards have the codec located at card_base+4.
|
||||
- Some minor changes
|
||||
|
||||
Since 2.5 (******* MAJOR REWRITE ***********)
|
||||
|
||||
This version is based on v2.3. I have tried to maintain two versions
|
||||
together so that this one should have the same features than v2.5.
|
||||
Something may still be missing. If you notice such things, please let me
|
||||
know.
|
||||
|
||||
The Readme.v30 contains more details.
|
||||
|
||||
- /dev/midi## devices.
|
||||
- /dev/sequencer2
|
||||
|
||||
Since 2.5-beta2
|
||||
- Some fine tuning to the GUS v3.7 mixer code.
|
||||
- Fixed speed limits for the plain SB (1.0 to 2.0).
|
||||
|
||||
Since 2.5-beta
|
||||
- Fixed OPL-3 detection with SB. Caused problems with PAS16.
|
||||
- GUS v3.7 mixer support.
|
||||
|
||||
Since 2.4
|
||||
- Mixer support for Sound Galaxy NX Pro (define __SGNXPRO__ on your local.h).
|
||||
- Fixed truncated sound on /dev/dsp when the device is closed.
|
||||
- Linear volume mode for GUS
|
||||
- Pitch bends larger than +/- 2 octaves.
|
||||
- MIDI recording for SB and SB Pro. (Untested).
|
||||
- Some other fixes.
|
||||
- SB16 MIDI and DSP drivers only initialized if SB16 actually installed.
|
||||
- Implemented better detection for OPL-3. This should be useful if you
|
||||
have an old SB Pro (the non-OPL-3 one) or a SB 2.0 clone which has a OPL-3.
|
||||
- SVR4.2 support by Ian Hartas. Initial ALPHA TEST version (untested).
|
||||
|
||||
Since 2.3b
|
||||
- Fixed bug which made it impossible to make long recordings to disk.
|
||||
Recording was not restarted after a buffer overflow situation.
|
||||
- Limited mixer support for GUS.
|
||||
- Numerous improvements to the GUS driver by Andrew Robinson. Including
|
||||
some click removal etc.
|
||||
|
||||
Since 2.3
|
||||
- Fixed some minor bugs in the SB16 driver.
|
||||
|
||||
Since 2.2b
|
||||
- Full SB16 DSP support. 8/16 bit, mono/stereo
|
||||
- The SCO and FreeBSD versions should be in sync now. There are some
|
||||
problems with SB16 and GUS in the FreeBSD versions.
|
||||
The DMA buffer allocation of the SCO version has been polished but
|
||||
there could still be some problems. At least it hogs memory.
|
||||
The DMA channel
|
||||
configuration method used in the SCO/System is a hack.
|
||||
- Support for the MPU emulation of the SB16.
|
||||
- Some big arrays are now allocated boot time. This makes the BSS segment
|
||||
smaller which makes it possible to use the full driver with
|
||||
NetBSD. These arrays are not allocated if no suitable sound card is available.
|
||||
- Fixed a bug in the compute_and_set_volume in gus_wave.c
|
||||
- Fixed the too fast mono playback problem of SB Pro and PAS16.
|
||||
|
||||
Since 2.2
|
||||
- Stereo recording for SB Pro. Somehow it was missing and nobody
|
||||
had noticed it earlier.
|
||||
- Minor polishing.
|
||||
- Interpreting of boot time arguments (sound=) for Linux.
|
||||
- Breakup of sb_dsp.c. Parts of the code has been moved to
|
||||
sb_mixer.c and sb_midi.c
|
||||
|
||||
Since 2.1
|
||||
- Preliminary support for SB16.
|
||||
- The SB16 mixer is supported in its native mode.
|
||||
- Digitized voice capability up to 44.1 kHz/8 bit/mono
|
||||
(16 bit and stereo support coming in the next release).
|
||||
- Fixed some bugs in the digitized voice driver for PAS16.
|
||||
- Proper initialization of the SB emulation of latest PAS16 models.
|
||||
|
||||
- Significantly improved /dev/dsp and /dev/audio support.
|
||||
- Now supports half duplex mode. It's now possible to record and
|
||||
playback without closing and reopening the device.
|
||||
- It's possible to use smaller buffers than earlier. There is a new
|
||||
ioctl(fd, SNDCTL_DSP_SUBDIVIDE, &n) where n should be 1, 2 or 4.
|
||||
This call instructs the driver to use smaller buffers. The default
|
||||
buffer size (0.5 to 1.0 seconds) is divided by n. Should be called
|
||||
immediately after opening the device.
|
||||
|
||||
Since 2.0
|
||||
Just cosmetic changes.
|
|
@ -1,533 +0,0 @@
|
|||
# 18 Apr 1998, Michael Elizabeth Chastain, <mailto:mec@shout.net>
|
||||
# More hacking for modularisation.
|
||||
#
|
||||
# Prompt user for primary drivers.
|
||||
|
||||
config SOUND_BCM_CS4297A
|
||||
tristate "Crystal Sound CS4297a (for Swarm)"
|
||||
depends on SIBYTE_SWARM
|
||||
help
|
||||
The BCM91250A has a Crystal CS4297a on synchronous serial
|
||||
port B (in addition to the DB-9 serial port). Say Y or M
|
||||
here to enable the sound chip instead of the UART. Also
|
||||
note that CONFIG_KGDB should not be enabled at the same
|
||||
time, since it also attempts to use this UART port.
|
||||
|
||||
config SOUND_MSNDCLAS
|
||||
tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey"
|
||||
depends on (m || !STANDALONE) && ISA
|
||||
help
|
||||
Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or
|
||||
Monterey (not for the Pinnacle or Fiji).
|
||||
|
||||
See <file:Documentation/sound/oss/MultiSound> for important information
|
||||
about this driver. Note that it has been discontinued, but the
|
||||
Voyetra Turtle Beach knowledge base entry for it is still available
|
||||
at <http://www.turtlebeach.com/site/kb_ftp/790.asp>.
|
||||
|
||||
comment "Compiled-in MSND Classic support requires firmware during compilation."
|
||||
depends on SOUND_PRIME && SOUND_MSNDCLAS=y
|
||||
|
||||
config MSNDCLAS_HAVE_BOOT
|
||||
bool
|
||||
depends on SOUND_MSNDCLAS=y && !STANDALONE
|
||||
default y
|
||||
|
||||
config MSNDCLAS_INIT_FILE
|
||||
string "Full pathname of MSNDINIT.BIN firmware file"
|
||||
depends on SOUND_MSNDCLAS
|
||||
default "/etc/sound/msndinit.bin"
|
||||
help
|
||||
The MultiSound cards have two firmware files which are required for
|
||||
operation, and are not currently included. These files can be
|
||||
obtained from Turtle Beach. See
|
||||
<file:Documentation/sound/oss/MultiSound> for information on how to
|
||||
obtain this.
|
||||
|
||||
config MSNDCLAS_PERM_FILE
|
||||
string "Full pathname of MSNDPERM.BIN firmware file"
|
||||
depends on SOUND_MSNDCLAS
|
||||
default "/etc/sound/msndperm.bin"
|
||||
help
|
||||
The MultiSound cards have two firmware files which are required for
|
||||
operation, and are not currently included. These files can be
|
||||
obtained from Turtle Beach. See
|
||||
<file:Documentation/sound/oss/MultiSound> for information on how to
|
||||
obtain this.
|
||||
|
||||
config MSNDCLAS_IRQ
|
||||
int "MSND Classic IRQ 5, 7, 9, 10, 11, 12"
|
||||
depends on SOUND_MSNDCLAS=y
|
||||
default "5"
|
||||
help
|
||||
Interrupt Request line for the MultiSound Classic and related cards.
|
||||
|
||||
config MSNDCLAS_MEM
|
||||
hex "MSND Classic memory B0000, C8000, D0000, D8000, E0000, E8000"
|
||||
depends on SOUND_MSNDCLAS=y
|
||||
default "D0000"
|
||||
help
|
||||
Memory-mapped I/O base address for the MultiSound Classic and
|
||||
related cards.
|
||||
|
||||
config MSNDCLAS_IO
|
||||
hex "MSND Classic I/O 210, 220, 230, 240, 250, 260, 290, 3E0"
|
||||
depends on SOUND_MSNDCLAS=y
|
||||
default "290"
|
||||
help
|
||||
I/O port address for the MultiSound Classic and related cards.
|
||||
|
||||
config SOUND_MSNDPIN
|
||||
tristate "Support for Turtle Beach MultiSound Pinnacle, Fiji"
|
||||
depends on (m || !STANDALONE) && ISA
|
||||
help
|
||||
Say M here if you have a Turtle Beach MultiSound Pinnacle or Fiji.
|
||||
See <file:Documentation/sound/oss/MultiSound> for important information
|
||||
about this driver. Note that it has been discontinued, but the
|
||||
Voyetra Turtle Beach knowledge base entry for it is still available
|
||||
at <http://www.turtlebeach.com/site/kb_ftp/600.asp>.
|
||||
|
||||
comment "Compiled-in MSND Pinnacle support requires firmware during compilation."
|
||||
depends on SOUND_PRIME && SOUND_MSNDPIN=y
|
||||
|
||||
config MSNDPIN_HAVE_BOOT
|
||||
bool
|
||||
depends on SOUND_MSNDPIN=y
|
||||
default y
|
||||
|
||||
config MSNDPIN_INIT_FILE
|
||||
string "Full pathname of PNDSPINI.BIN firmware file"
|
||||
depends on SOUND_MSNDPIN
|
||||
default "/etc/sound/pndspini.bin"
|
||||
help
|
||||
The MultiSound cards have two firmware files which are required
|
||||
for operation, and are not currently included. These files can be
|
||||
obtained from Turtle Beach. See
|
||||
<file:Documentation/sound/oss/MultiSound> for information on how to
|
||||
obtain this.
|
||||
|
||||
config MSNDPIN_PERM_FILE
|
||||
string "Full pathname of PNDSPERM.BIN firmware file"
|
||||
depends on SOUND_MSNDPIN
|
||||
default "/etc/sound/pndsperm.bin"
|
||||
help
|
||||
The MultiSound cards have two firmware files which are required for
|
||||
operation, and are not currently included. These files can be
|
||||
obtained from Turtle Beach. See
|
||||
<file:Documentation/sound/oss/MultiSound> for information on how to
|
||||
obtain this.
|
||||
|
||||
config MSNDPIN_IRQ
|
||||
int "MSND Pinnacle IRQ 5, 7, 9, 10, 11, 12"
|
||||
depends on SOUND_MSNDPIN=y
|
||||
default "5"
|
||||
help
|
||||
Interrupt request line for the primary synthesizer on MultiSound
|
||||
Pinnacle and Fiji sound cards.
|
||||
|
||||
config MSNDPIN_MEM
|
||||
hex "MSND Pinnacle memory B0000, C8000, D0000, D8000, E0000, E8000"
|
||||
depends on SOUND_MSNDPIN=y
|
||||
default "D0000"
|
||||
help
|
||||
Memory-mapped I/O base address for the primary synthesizer on
|
||||
MultiSound Pinnacle and Fiji sound cards.
|
||||
|
||||
config MSNDPIN_IO
|
||||
hex "MSND Pinnacle I/O 210, 220, 230, 240, 250, 260, 290, 3E0"
|
||||
depends on SOUND_MSNDPIN=y
|
||||
default "290"
|
||||
help
|
||||
Memory-mapped I/O base address for the primary synthesizer on
|
||||
MultiSound Pinnacle and Fiji sound cards.
|
||||
|
||||
config MSNDPIN_DIGITAL
|
||||
bool "MSND Pinnacle has S/PDIF I/O"
|
||||
depends on SOUND_MSNDPIN=y
|
||||
help
|
||||
If you have the S/PDIF daughter board for the Pinnacle or Fiji,
|
||||
answer Y here; otherwise, say N. If you have this, you will be able
|
||||
to play and record from the S/PDIF port (digital signal). See
|
||||
<file:Documentation/sound/oss/MultiSound> for information on how to make
|
||||
use of this capability.
|
||||
|
||||
config MSNDPIN_NONPNP
|
||||
bool "MSND Pinnacle non-PnP Mode"
|
||||
depends on SOUND_MSNDPIN=y
|
||||
help
|
||||
The Pinnacle and Fiji card resources can be configured either with
|
||||
PnP, or through a configuration port. Say Y here if your card is NOT
|
||||
in PnP mode. For the Pinnacle, configuration in non-PnP mode allows
|
||||
use of the IDE and joystick peripherals on the card as well; these
|
||||
do not show up when the card is in PnP mode. Specifying zero for any
|
||||
resource of a device will disable the device. If you are running the
|
||||
card in PnP mode, you must say N here and use isapnptools to
|
||||
configure the card's resources.
|
||||
|
||||
comment "MSND Pinnacle DSP section will be configured to above parameters."
|
||||
depends on SOUND_MSNDPIN=y && MSNDPIN_NONPNP
|
||||
|
||||
config MSNDPIN_CFG
|
||||
hex "MSND Pinnacle config port 250,260,270"
|
||||
depends on MSNDPIN_NONPNP
|
||||
default "250"
|
||||
help
|
||||
This is the port which the Pinnacle and Fiji uses to configure the
|
||||
card's resources when not in PnP mode. If your card is in PnP mode,
|
||||
then be sure to say N to the previous option, "MSND Pinnacle Non-PnP
|
||||
Mode".
|
||||
|
||||
comment "Pinnacle-specific Device Configuration (0 disables)"
|
||||
depends on SOUND_MSNDPIN=y && MSNDPIN_NONPNP
|
||||
|
||||
config MSNDPIN_MPU_IO
|
||||
hex "MSND Pinnacle MPU I/O (e.g. 330)"
|
||||
depends on MSNDPIN_NONPNP
|
||||
default "0"
|
||||
help
|
||||
Memory-mapped I/O base address for the Kurzweil daughterboard
|
||||
synthesizer on MultiSound Pinnacle and Fiji sound cards.
|
||||
|
||||
config MSNDPIN_MPU_IRQ
|
||||
int "MSND Pinnacle MPU IRQ (e.g. 9)"
|
||||
depends on MSNDPIN_NONPNP
|
||||
default "0"
|
||||
help
|
||||
Interrupt request number for the Kurzweil daughterboard
|
||||
synthesizer on MultiSound Pinnacle and Fiji sound cards.
|
||||
|
||||
config MSNDPIN_IDE_IO0
|
||||
hex "MSND Pinnacle IDE I/O 0 (e.g. 170)"
|
||||
depends on MSNDPIN_NONPNP
|
||||
default "0"
|
||||
help
|
||||
CD-ROM drive 0 memory-mapped I/O base address for the MultiSound
|
||||
Pinnacle and Fiji sound cards.
|
||||
|
||||
config MSNDPIN_IDE_IO1
|
||||
hex "MSND Pinnacle IDE I/O 1 (e.g. 376)"
|
||||
depends on MSNDPIN_NONPNP
|
||||
default "0"
|
||||
help
|
||||
CD-ROM drive 1 memory-mapped I/O base address for the MultiSound
|
||||
Pinnacle and Fiji sound cards.
|
||||
|
||||
config MSNDPIN_IDE_IRQ
|
||||
int "MSND Pinnacle IDE IRQ (e.g. 15)"
|
||||
depends on MSNDPIN_NONPNP
|
||||
default "0"
|
||||
help
|
||||
Interrupt request number for the IDE CD-ROM interface on the
|
||||
MultiSound Pinnacle and Fiji sound cards.
|
||||
|
||||
config MSNDPIN_JOYSTICK_IO
|
||||
hex "MSND Pinnacle joystick I/O (e.g. 200)"
|
||||
depends on MSNDPIN_NONPNP
|
||||
default "0"
|
||||
help
|
||||
Memory-mapped I/O base address for the joystick port on MultiSound
|
||||
Pinnacle and Fiji sound cards.
|
||||
|
||||
config MSND_FIFOSIZE
|
||||
int "MSND buffer size (kB)"
|
||||
depends on SOUND_MSNDPIN=y || SOUND_MSNDCLAS=y
|
||||
default "128"
|
||||
help
|
||||
Configures the size of each audio buffer, in kilobytes, for
|
||||
recording and playing in the MultiSound drivers (both the Classic
|
||||
and Pinnacle). Larger values reduce the chance of data overruns at
|
||||
the expense of overall latency. If unsure, use the default.
|
||||
|
||||
menuconfig SOUND_OSS
|
||||
tristate "OSS sound modules"
|
||||
depends on ISA_DMA_API && (VIRT_TO_BUS || ARCH_RPC || ARCH_NETWINDER)
|
||||
depends on !GENERIC_ISA_DMA_SUPPORT_BROKEN
|
||||
help
|
||||
OSS is the Open Sound System suite of sound card drivers. They make
|
||||
sound programming easier since they provide a common API. Say Y or
|
||||
M here (the module will be called sound) if you haven't found a
|
||||
driver for your sound card above, then pick your driver from the
|
||||
list below.
|
||||
|
||||
if SOUND_OSS
|
||||
|
||||
config SOUND_TRACEINIT
|
||||
bool "Verbose initialisation"
|
||||
help
|
||||
Verbose soundcard initialization -- affects the format of autoprobe
|
||||
and initialization messages at boot time.
|
||||
|
||||
config SOUND_DMAP
|
||||
bool "Persistent DMA buffers"
|
||||
---help---
|
||||
Linux can often have problems allocating DMA buffers for ISA sound
|
||||
cards on machines with more than 16MB of RAM. This is because ISA
|
||||
DMA buffers must exist below the 16MB boundary and it is quite
|
||||
possible that a large enough free block in this region cannot be
|
||||
found after the machine has been running for a while. If you say Y
|
||||
here the DMA buffers (64Kb) will be allocated at boot time and kept
|
||||
until the shutdown. This option is only useful if you said Y to
|
||||
"OSS sound modules", above. If you said M to "OSS sound modules"
|
||||
then you can get the persistent DMA buffer functionality by passing
|
||||
the command-line argument "dmabuf=1" to the sound module.
|
||||
|
||||
Say Y unless you have 16MB or more RAM or a PCI sound card.
|
||||
|
||||
config SOUND_VMIDI
|
||||
tristate "Loopback MIDI device support"
|
||||
help
|
||||
Support for MIDI loopback on port 1 or 2.
|
||||
|
||||
config SOUND_TRIX
|
||||
tristate "MediaTrix AudioTrix Pro support"
|
||||
help
|
||||
Answer Y if you have the AudioTriX Pro sound card manufactured
|
||||
by MediaTrix.
|
||||
|
||||
config TRIX_HAVE_BOOT
|
||||
bool "Have TRXPRO.HEX firmware file"
|
||||
depends on SOUND_TRIX=y && !STANDALONE
|
||||
help
|
||||
The MediaTrix AudioTrix Pro has an on-board microcontroller which
|
||||
needs to be initialized by downloading the code from the file
|
||||
TRXPRO.HEX in the DOS driver directory. If you don't have the
|
||||
TRXPRO.HEX file handy you may skip this step. However, the SB and
|
||||
MPU-401 modes of AudioTrix Pro will not work without this file!
|
||||
|
||||
config TRIX_BOOT_FILE
|
||||
string "Full pathname of TRXPRO.HEX firmware file"
|
||||
depends on TRIX_HAVE_BOOT
|
||||
default "/etc/sound/trxpro.hex"
|
||||
help
|
||||
Enter the full pathname of your TRXPRO.HEX file, starting from /.
|
||||
|
||||
config SOUND_MSS
|
||||
tristate "Microsoft Sound System support"
|
||||
---help---
|
||||
Again think carefully before answering Y to this question. It's
|
||||
safe to answer Y if you have the original Windows Sound System card
|
||||
made by Microsoft or Aztech SG 16 Pro (or NX16 Pro). Also you may
|
||||
say Y in case your card is NOT among these:
|
||||
|
||||
ATI Stereo F/X, AdLib, Audio Excell DSP16, Cardinal DSP16,
|
||||
Ensoniq SoundScape (and compatibles made by Reveal and Spea),
|
||||
Gravis Ultrasound, Gravis Ultrasound ACE, Gravis Ultrasound Max,
|
||||
Gravis Ultrasound with 16 bit option, Logitech Sound Man 16,
|
||||
Logitech SoundMan Games, Logitech SoundMan Wave, MAD16 Pro (OPTi
|
||||
82C929), Media Vision Jazz16, MediaTriX AudioTriX Pro, Microsoft
|
||||
Windows Sound System (MSS/WSS), Mozart (OAK OTI-601), Orchid
|
||||
SW32, Personal Sound System (PSS), Pro Audio Spectrum 16, Pro
|
||||
Audio Studio 16, Pro Sonic 16, Roland MPU-401 MIDI interface,
|
||||
Sound Blaster 1.0, Sound Blaster 16, Sound Blaster 16ASP, Sound
|
||||
Blaster 2.0, Sound Blaster AWE32, Sound Blaster Pro, TI TM4000M
|
||||
notebook, ThunderBoard, Turtle Beach Tropez, Yamaha FM
|
||||
synthesizers (OPL2, OPL3 and OPL4), 6850 UART MIDI Interface.
|
||||
|
||||
For cards having native support in VoxWare, consult the card
|
||||
specific instructions in <file:Documentation/sound/oss/README.OSS>.
|
||||
Some drivers have their own MSS support and saying Y to this option
|
||||
will cause a conflict.
|
||||
|
||||
If you compile the driver into the kernel, you have to add
|
||||
"ad1848=<io>,<irq>,<dma>,<dma2>[,<type>]" to the kernel command
|
||||
line.
|
||||
|
||||
config SOUND_MPU401
|
||||
tristate "MPU-401 support (NOT for SB16)"
|
||||
---help---
|
||||
Be careful with this question. The MPU401 interface is supported by
|
||||
all sound cards. However, some natively supported cards have their
|
||||
own driver for MPU401. Enabling this MPU401 option with these cards
|
||||
will cause a conflict. Also, enabling MPU401 on a system that
|
||||
doesn't really have a MPU401 could cause some trouble. If your card
|
||||
was in the list of supported cards, look at the card specific
|
||||
instructions in the <file:Documentation/sound/oss/README.OSS> file. It
|
||||
is safe to answer Y if you have a true MPU401 MIDI interface card.
|
||||
|
||||
If you compile the driver into the kernel, you have to add
|
||||
"mpu401=<io>,<irq>" to the kernel command line.
|
||||
|
||||
config SOUND_PAS
|
||||
tristate "ProAudioSpectrum 16 support"
|
||||
---help---
|
||||
Answer Y only if you have a Pro Audio Spectrum 16, ProAudio Studio
|
||||
16 or Logitech SoundMan 16 sound card. Answer N if you have some
|
||||
other card made by Media Vision or Logitech since those are not
|
||||
PAS16 compatible. Please read <file:Documentation/sound/oss/PAS16>.
|
||||
It is not necessary to add Sound Blaster support separately; it
|
||||
is included in PAS support.
|
||||
|
||||
If you compile the driver into the kernel, you have to add
|
||||
"pas2=<io>,<irq>,<dma>,<dma2>,<sbio>,<sbirq>,<sbdma>,<sbdma2>
|
||||
to the kernel command line.
|
||||
|
||||
config PAS_JOYSTICK
|
||||
bool "Enable PAS16 joystick port"
|
||||
depends on SOUND_PAS=y
|
||||
help
|
||||
Say Y here to enable the Pro Audio Spectrum 16's auxiliary joystick
|
||||
port.
|
||||
|
||||
config SOUND_PSS
|
||||
tristate "PSS (AD1848, ADSP-2115, ESC614) support"
|
||||
help
|
||||
Answer Y or M if you have an Orchid SW32, Cardinal DSP16, Beethoven
|
||||
ADSP-16 or some other card based on the PSS chipset (AD1848 codec +
|
||||
ADSP-2115 DSP chip + Echo ESC614 ASIC CHIP). For more information on
|
||||
how to compile it into the kernel or as a module see the file
|
||||
<file:Documentation/sound/oss/PSS>.
|
||||
|
||||
If you compile the driver into the kernel, you have to add
|
||||
"pss=<io>,<mssio>,<mssirq>,<mssdma>,<mpuio>,<mpuirq>" to the kernel
|
||||
command line.
|
||||
|
||||
config PSS_MIXER
|
||||
bool "Enable PSS mixer (Beethoven ADSP-16 and other compatible)"
|
||||
depends on SOUND_PSS
|
||||
help
|
||||
Answer Y for Beethoven ADSP-16. You may try to say Y also for other
|
||||
cards if they have master volume, bass, treble, and you can't
|
||||
control it under Linux. If you answer N for Beethoven ADSP-16, you
|
||||
can't control master volume, bass, treble and synth volume.
|
||||
|
||||
If you said M to "PSS support" above, you may enable or disable this
|
||||
PSS mixer with the module parameter pss_mixer. For more information
|
||||
see the file <file:Documentation/sound/oss/PSS>.
|
||||
|
||||
config PSS_HAVE_BOOT
|
||||
bool "Have DSPxxx.LD firmware file"
|
||||
depends on SOUND_PSS && !STANDALONE
|
||||
help
|
||||
If you have the DSPxxx.LD file or SYNTH.LD file for you card, say Y
|
||||
to include this file. Without this file the synth device (OPL) may
|
||||
not work.
|
||||
|
||||
config PSS_BOOT_FILE
|
||||
string "Full pathname of DSPxxx.LD firmware file"
|
||||
depends on PSS_HAVE_BOOT
|
||||
default "/etc/sound/dsp001.ld"
|
||||
help
|
||||
Enter the full pathname of your DSPxxx.LD file or SYNTH.LD file,
|
||||
starting from /.
|
||||
|
||||
config SOUND_SB
|
||||
tristate "100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support"
|
||||
---help---
|
||||
Answer Y if you have an original Sound Blaster card made by Creative
|
||||
Labs or a 100% hardware compatible clone (like the Thunderboard or
|
||||
SM Games). For an unknown card you may answer Y if the card claims
|
||||
to be Sound Blaster-compatible.
|
||||
|
||||
Please read the file <file:Documentation/sound/oss/Soundblaster>.
|
||||
|
||||
You should also say Y here for cards based on the Avance Logic
|
||||
ALS-007 and ALS-1X0 chips (read <file:Documentation/sound/oss/ALS>) and
|
||||
for cards based on ESS chips (read
|
||||
<file:Documentation/sound/oss/ESS1868> and
|
||||
<file:Documentation/sound/oss/ESS>). If you have an IBM Mwave
|
||||
card, say Y here and read <file:Documentation/sound/oss/mwave>.
|
||||
|
||||
If you compile the driver into the kernel and don't want to use
|
||||
isapnp, you have to add "sb=<io>,<irq>,<dma>,<dma2>" to the kernel
|
||||
command line.
|
||||
|
||||
You can say M here to compile this driver as a module; the module is
|
||||
called sb.
|
||||
|
||||
config SOUND_YM3812
|
||||
tristate "Yamaha FM synthesizer (YM3812/OPL-3) support"
|
||||
---help---
|
||||
Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
|
||||
Answering Y is usually a safe and recommended choice, however some
|
||||
cards may have software (TSR) FM emulation. Enabling FM support with
|
||||
these cards may cause trouble (I don't currently know of any such
|
||||
cards, however). Please read the file
|
||||
<file:Documentation/sound/oss/OPL3> if your card has an OPL3 chip.
|
||||
|
||||
If you compile the driver into the kernel, you have to add
|
||||
"opl3=<io>" to the kernel command line.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config SOUND_UART6850
|
||||
tristate "6850 UART support"
|
||||
help
|
||||
This option enables support for MIDI interfaces based on the 6850
|
||||
UART chip. This interface is rarely found on sound cards. It's safe
|
||||
to answer N to this question.
|
||||
|
||||
If you compile the driver into the kernel, you have to add
|
||||
"uart6850=<io>,<irq>" to the kernel command line.
|
||||
|
||||
config SOUND_AEDSP16
|
||||
tristate "Gallant Audio Cards (SC-6000 and SC-6600 based)"
|
||||
---help---
|
||||
Answer Y if you have a Gallant's Audio Excel DSP 16 card. This
|
||||
driver supports Audio Excel DSP 16 but not the III nor PnP versions
|
||||
of this card.
|
||||
|
||||
The Gallant's Audio Excel DSP 16 card can emulate either an SBPro or
|
||||
a Microsoft Sound System card, so you should have said Y to either
|
||||
"100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support"
|
||||
or "Microsoft Sound System support", above, and you need to answer
|
||||
the "MSS emulation" and "SBPro emulation" questions below
|
||||
accordingly. You should say Y to one and only one of these two
|
||||
questions.
|
||||
|
||||
Read the <file:Documentation/sound/oss/README.OSS> file and the head of
|
||||
<file:sound/oss/aedsp16.c> as well as
|
||||
<file:Documentation/sound/oss/AudioExcelDSP16> to get more information
|
||||
about this driver and its configuration.
|
||||
|
||||
config SC6600
|
||||
bool "SC-6600 based audio cards (new Audio Excel DSP 16)"
|
||||
depends on SOUND_AEDSP16
|
||||
help
|
||||
The SC6600 is the new version of DSP mounted on the Audio Excel DSP
|
||||
16 cards. Find in the manual the FCC ID of your audio card and
|
||||
answer Y if you have an SC6600 DSP.
|
||||
|
||||
config SC6600_JOY
|
||||
bool "Activate SC-6600 Joystick Interface"
|
||||
depends on SC6600
|
||||
help
|
||||
Say Y here in order to use the joystick interface of the Audio Excel
|
||||
DSP 16 card.
|
||||
|
||||
config SC6600_CDROM
|
||||
int "SC-6600 CDROM Interface (4=None, 3=IDE, 1=Panasonic, 0=?Sony?)"
|
||||
depends on SC6600
|
||||
default "4"
|
||||
help
|
||||
This is used to activate the CD-ROM interface of the Audio Excel
|
||||
DSP 16 card. Enter: 0 for Sony, 1 for Panasonic, 2 for IDE, 4 for no
|
||||
CD-ROM present.
|
||||
|
||||
config SC6600_CDROMBASE
|
||||
hex "SC-6600 CDROM Interface I/O Address"
|
||||
depends on SC6600
|
||||
default "0"
|
||||
help
|
||||
Base I/O port address for the CD-ROM interface of the Audio Excel
|
||||
DSP 16 card.
|
||||
|
||||
config SOUND_VIDC
|
||||
tristate "VIDC 16-bit sound"
|
||||
depends on ARM && ARCH_ACORN
|
||||
help
|
||||
16-bit support for the VIDC onboard sound hardware found on Acorn
|
||||
machines.
|
||||
|
||||
config SOUND_WAVEARTIST
|
||||
tristate "Netwinder WaveArtist"
|
||||
depends on ARM && ARCH_NETWINDER
|
||||
help
|
||||
Say Y here to include support for the Rockwell WaveArtist sound
|
||||
system. This driver is mainly for the NetWinder.
|
||||
|
||||
config SOUND_KAHLUA
|
||||
tristate "XpressAudio Sound Blaster emulation"
|
||||
depends on SOUND_SB
|
||||
|
||||
endif # SOUND_OSS
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
# Makefile for the Linux sound card driver
|
||||
#
|
||||
# 18 Apr 1998, Michael Elizabeth Chastain, <mailto:mec@shout.net>
|
||||
# Rewritten to use lists instead of if-statements.
|
||||
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
obj-$(CONFIG_SOUND_OSS) += sound.o
|
||||
|
||||
# Please leave it as is, cause the link order is significant !
|
||||
|
||||
obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o
|
||||
obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o
|
||||
obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb_lib.o uart401.o
|
||||
obj-$(CONFIG_SOUND_MSS) += ad1848.o
|
||||
obj-$(CONFIG_SOUND_PAS) += pas2.o sb.o sb_lib.o uart401.o
|
||||
obj-$(CONFIG_SOUND_SB) += sb.o sb_lib.o uart401.o
|
||||
obj-$(CONFIG_SOUND_KAHLUA) += kahlua.o
|
||||
obj-$(CONFIG_SOUND_MPU401) += mpu401.o
|
||||
obj-$(CONFIG_SOUND_UART6850) += uart6850.o
|
||||
obj-$(CONFIG_SOUND_YM3812) += opl3.o
|
||||
obj-$(CONFIG_SOUND_VMIDI) += v_midi.o
|
||||
obj-$(CONFIG_SOUND_VIDC) += vidc_mod.o
|
||||
obj-$(CONFIG_SOUND_WAVEARTIST) += waveartist.o
|
||||
obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o
|
||||
obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o
|
||||
obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o
|
||||
|
||||
obj-$(CONFIG_DMASOUND) += dmasound/
|
||||
|
||||
# Declare multi-part drivers.
|
||||
|
||||
sound-objs := \
|
||||
dev_table.o soundcard.o \
|
||||
audio.o dmabuf.o \
|
||||
midi_synth.o midibuf.o \
|
||||
sequencer.o sound_timer.o sys_timer.o
|
||||
|
||||
pas2-objs := pas2_card.o pas2_midi.o pas2_mixer.o pas2_pcm.o
|
||||
sb-objs := sb_card.o
|
||||
sb_lib-objs := sb_common.o sb_audio.o sb_midi.o sb_mixer.o sb_ess.o
|
||||
vidc_mod-objs := vidc.o vidc_fill.o
|
||||
|
||||
hostprogs-y := bin2hex hex2hex
|
||||
|
||||
# Files generated that shall be removed upon make clean
|
||||
clean-files := msndperm.c msndinit.c pndsperm.c pndspini.c \
|
||||
pss_boot.h trix_boot.h
|
||||
|
||||
# Firmware files that need translation
|
||||
#
|
||||
# The translated files are protected by a file that keeps track
|
||||
# of what name was used to build them. If the name changes, they
|
||||
# will be forced to be remade.
|
||||
#
|
||||
|
||||
# Turtle Beach MultiSound
|
||||
|
||||
ifeq ($(CONFIG_MSNDCLAS_HAVE_BOOT),y)
|
||||
$(obj)/msnd_classic.o: $(obj)/msndperm.c $(obj)/msndinit.c
|
||||
|
||||
$(obj)/msndperm.c: $(patsubst "%", %, $(CONFIG_MSNDCLAS_PERM_FILE)) $(obj)/bin2hex
|
||||
$(obj)/bin2hex msndperm < $< > $@
|
||||
|
||||
$(obj)/msndinit.c: $(patsubst "%", %, $(CONFIG_MSNDCLAS_INIT_FILE)) $(obj)/bin2hex
|
||||
$(obj)/bin2hex msndinit < $< > $@
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MSNDPIN_HAVE_BOOT),y)
|
||||
$(obj)/msnd_pinnacle.o: $(obj)/pndsperm.c $(obj)/pndspini.c
|
||||
|
||||
$(obj)/pndsperm.c: $(patsubst "%", %, $(CONFIG_MSNDPIN_PERM_FILE)) $(obj)/bin2hex
|
||||
$(obj)/bin2hex pndsperm < $< > $@
|
||||
|
||||
$(obj)/pndspini.c: $(patsubst "%", %, $(CONFIG_MSNDPIN_INIT_FILE)) $(obj)/bin2hex
|
||||
$(obj)/bin2hex pndspini < $< > $@
|
||||
endif
|
||||
|
||||
# PSS (ECHO-ADI2111)
|
||||
|
||||
$(obj)/pss.o: $(obj)/pss_boot.h
|
||||
|
||||
ifeq ($(CONFIG_PSS_HAVE_BOOT),y)
|
||||
$(obj)/pss_boot.h: $(patsubst "%", %, $(CONFIG_PSS_BOOT_FILE)) $(obj)/bin2hex
|
||||
$(obj)/bin2hex pss_synth < $< > $@
|
||||
else
|
||||
$(obj)/pss_boot.h:
|
||||
$(Q)( \
|
||||
echo 'static unsigned char * pss_synth = NULL;'; \
|
||||
echo 'static int pss_synthLen = 0;'; \
|
||||
) > $@
|
||||
endif
|
||||
|
||||
# MediaTrix AudioTrix Pro
|
||||
|
||||
$(obj)/trix.o: $(obj)/trix_boot.h
|
||||
|
||||
ifeq ($(CONFIG_TRIX_HAVE_BOOT),y)
|
||||
$(obj)/trix_boot.h: $(patsubst "%", %, $(CONFIG_TRIX_BOOT_FILE)) $(obj)/hex2hex
|
||||
$(obj)/hex2hex -i trix_boot < $< > $@
|
||||
else
|
||||
$(obj)/trix_boot.h:
|
||||
$(Q)( \
|
||||
echo 'static unsigned char * trix_boot = NULL;'; \
|
||||
echo 'static int trix_boot_len = 0;'; \
|
||||
) > $@
|
||||
endif
|
|
@ -1,6 +0,0 @@
|
|||
The modular sound driver patches were funded by Red Hat Software
|
||||
(www.redhat.com). The sound driver here is thus a modified version of
|
||||
Hannu's code. Please bear that in mind when considering the appropriate
|
||||
forums for bug reporting.
|
||||
|
||||
Alan Cox
|
3062
sound/oss/ad1848.c
3062
sound/oss/ad1848.c
File diff suppressed because it is too large
Load diff
|
@ -1,24 +0,0 @@
|
|||
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#define AD_F_CS4231 0x0001 /* Returned if a CS4232 (or compatible) detected */
|
||||
#define AD_F_CS4248 0x0001 /* Returned if a CS4248 (or compatible) detected */
|
||||
|
||||
#define AD1848_SET_XTAL 1
|
||||
#define AD1848_MIXER_REROUTE 2
|
||||
|
||||
#define AD1848_REROUTE(oldctl, newctl) \
|
||||
ad1848_control(AD1848_MIXER_REROUTE, ((oldctl)<<8)|(newctl))
|
||||
|
||||
|
||||
int ad1848_init(char *name, struct resource *ports, int irq, int dma_playback,
|
||||
int dma_capture, int share_dma, int *osp, struct module *owner);
|
||||
void ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int share_dma);
|
||||
|
||||
int ad1848_detect (struct resource *ports, int *flags, int *osp);
|
||||
int ad1848_control(int cmd, int arg);
|
||||
|
||||
void attach_ms_sound(struct address_info * hw_config, struct resource *ports, struct module * owner);
|
||||
|
||||
int probe_ms_sound(struct address_info *hw_config, struct resource *ports);
|
||||
void unload_ms_sound(struct address_info *hw_info);
|
|
@ -1,253 +0,0 @@
|
|||
/*
|
||||
* sound/oss/ad1848_mixer.h
|
||||
*
|
||||
* Definitions for the mixer of AD1848 and compatible codecs.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) by Hannu Savolainen 1993-1997
|
||||
*
|
||||
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
|
||||
* Version 2 (June 1991). See the "COPYING" file distributed with this software
|
||||
* for more info.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The AD1848 codec has generic input lines called Line, Aux1 and Aux2.
|
||||
* Sound card manufacturers have connected actual inputs (CD, synth, line,
|
||||
* etc) to these inputs in different order. Therefore it's difficult
|
||||
* to assign mixer channels to these inputs correctly. The following
|
||||
* contains two alternative mappings. The first one is for GUS MAX and
|
||||
* the second is just a generic one (line1, line2 and line3).
|
||||
* (Actually this is not a mapping but rather some kind of interleaving
|
||||
* solution).
|
||||
*/
|
||||
#define MODE1_REC_DEVICES (SOUND_MASK_LINE3 | SOUND_MASK_MIC | \
|
||||
SOUND_MASK_LINE1 | SOUND_MASK_IMIX)
|
||||
|
||||
#define SPRO_REC_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \
|
||||
SOUND_MASK_CD | SOUND_MASK_LINE1)
|
||||
|
||||
#define MODE1_MIXER_DEVICES (SOUND_MASK_LINE1 | SOUND_MASK_MIC | \
|
||||
SOUND_MASK_LINE2 | \
|
||||
SOUND_MASK_IGAIN | \
|
||||
SOUND_MASK_PCM | SOUND_MASK_IMIX)
|
||||
|
||||
#define MODE2_MIXER_DEVICES (SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | \
|
||||
SOUND_MASK_MIC | \
|
||||
SOUND_MASK_LINE3 | SOUND_MASK_SPEAKER | \
|
||||
SOUND_MASK_IGAIN | \
|
||||
SOUND_MASK_PCM | SOUND_MASK_IMIX)
|
||||
|
||||
#define MODE3_MIXER_DEVICES (MODE2_MIXER_DEVICES | SOUND_MASK_VOLUME)
|
||||
|
||||
/* OPTi 82C930 has no IMIX level control, but it can still be selected as an
|
||||
* input
|
||||
*/
|
||||
#define C930_MIXER_DEVICES (SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | \
|
||||
SOUND_MASK_MIC | SOUND_MASK_VOLUME | \
|
||||
SOUND_MASK_LINE3 | \
|
||||
SOUND_MASK_IGAIN | SOUND_MASK_PCM)
|
||||
|
||||
#define SPRO_MIXER_DEVICES (SOUND_MASK_VOLUME | SOUND_MASK_PCM | \
|
||||
SOUND_MASK_LINE | SOUND_MASK_SYNTH | \
|
||||
SOUND_MASK_CD | SOUND_MASK_MIC | \
|
||||
SOUND_MASK_SPEAKER | SOUND_MASK_LINE1 | \
|
||||
SOUND_MASK_OGAIN)
|
||||
|
||||
struct mixer_def {
|
||||
unsigned int regno:6; /* register number for volume */
|
||||
unsigned int polarity:1; /* volume polarity: 0=normal, 1=reversed */
|
||||
unsigned int bitpos:3; /* position of bits in register for volume */
|
||||
unsigned int nbits:3; /* number of bits in register for volume */
|
||||
unsigned int mutereg:6; /* register number for mute bit */
|
||||
unsigned int mutepol:1; /* mute polarity: 0=normal, 1=reversed */
|
||||
unsigned int mutepos:4; /* position of mute bit in register */
|
||||
unsigned int recreg:6; /* register number for recording bit */
|
||||
unsigned int recpol:1; /* recording polarity: 0=normal, 1=reversed */
|
||||
unsigned int recpos:4; /* position of recording bit in register */
|
||||
};
|
||||
|
||||
static char mix_cvt[101] = {
|
||||
0, 0, 3, 7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
|
||||
43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65,
|
||||
65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79,
|
||||
80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90,
|
||||
91,91,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,98,99,99,
|
||||
100
|
||||
};
|
||||
|
||||
typedef struct mixer_def mixer_ent;
|
||||
typedef mixer_ent mixer_ents[2];
|
||||
|
||||
/*
|
||||
* Most of the mixer entries work in backwards. Setting the polarity field
|
||||
* makes them to work correctly.
|
||||
*
|
||||
* The channel numbering used by individual sound cards is not fixed. Some
|
||||
* cards have assigned different meanings for the AUX1, AUX2 and LINE inputs.
|
||||
* The current version doesn't try to compensate this.
|
||||
*/
|
||||
|
||||
#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r, mute_bit) \
|
||||
[name] = {{reg_l, pola_l, pos_l, len_l, reg_l, 0, mute_bit, 0, 0, 8}, \
|
||||
{reg_r, pola_r, pos_r, len_r, reg_r, 0, mute_bit, 0, 0, 8}}
|
||||
|
||||
#define MIX_ENT2(name, reg_l, pola_l, pos_l, len_l, mute_reg_l, mute_pola_l, mute_pos_l, \
|
||||
rec_reg_l, rec_pola_l, rec_pos_l, \
|
||||
reg_r, pola_r, pos_r, len_r, mute_reg_r, mute_pola_r, mute_pos_r, \
|
||||
rec_reg_r, rec_pola_r, rec_pos_r) \
|
||||
[name] = {{reg_l, pola_l, pos_l, len_l, mute_reg_l, mute_pola_l, mute_pos_l, \
|
||||
rec_reg_l, rec_pola_l, rec_pos_l}, \
|
||||
{reg_r, pola_r, pos_r, len_r, mute_reg_r, mute_pola_r, mute_pos_r, \
|
||||
rec_reg_r, rec_pola_r, rec_pos_r}}
|
||||
|
||||
static mixer_ents ad1848_mix_devices[32] = {
|
||||
MIX_ENT(SOUND_MIXER_VOLUME, 27, 1, 0, 4, 29, 1, 0, 4, 8),
|
||||
MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
|
||||
MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8),
|
||||
MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
|
||||
MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7)
|
||||
};
|
||||
|
||||
static mixer_ents iwave_mix_devices[32] = {
|
||||
MIX_ENT(SOUND_MIXER_VOLUME, 25, 1, 0, 5, 27, 1, 0, 5, 8),
|
||||
MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
|
||||
MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8),
|
||||
MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_IMIX, 16, 1, 0, 5, 17, 1, 0, 5, 8),
|
||||
MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
|
||||
MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7)
|
||||
};
|
||||
|
||||
static mixer_ents cs42xb_mix_devices[32] = {
|
||||
/* Digital master volume actually has seven bits, but we only use
|
||||
six to avoid the discontinuity when the analog gain kicks in. */
|
||||
MIX_ENT(SOUND_MIXER_VOLUME, 46, 1, 0, 6, 47, 1, 0, 6, 7),
|
||||
MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
|
||||
MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_MIC, 34, 1, 0, 5, 35, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
|
||||
/* For the IMIX entry, it was not possible to use the MIX_ENT macro
|
||||
because the mute bit is in different positions for the two
|
||||
channels and requires reverse polarity. */
|
||||
[SOUND_MIXER_IMIX] = {{13, 1, 2, 6, 13, 1, 0, 0, 0, 8},
|
||||
{42, 1, 0, 6, 42, 1, 7, 0, 0, 8}},
|
||||
MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
|
||||
MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_LINE3, 38, 1, 0, 6, 39, 1, 0, 6, 7)
|
||||
};
|
||||
|
||||
/* OPTi 82C930 has somewhat different port addresses.
|
||||
* Note: VOLUME == SPEAKER, SYNTH == LINE2, LINE == LINE3, CD == LINE1
|
||||
* VOLUME, SYNTH, LINE, CD are not enabled above.
|
||||
* MIC is level of mic monitoring direct to output. Same for CD, LINE, etc.
|
||||
*/
|
||||
static mixer_ents c930_mix_devices[32] = {
|
||||
MIX_ENT(SOUND_MIXER_VOLUME, 22, 1, 1, 5, 23, 1, 1, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 5, 1, 1, 4, 7),
|
||||
MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 5, 7, 1, 0, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_SPEAKER, 22, 1, 1, 5, 23, 1, 1, 5, 7),
|
||||
MIX_ENT(SOUND_MIXER_LINE, 18, 1, 1, 4, 19, 1, 1, 4, 7),
|
||||
MIX_ENT(SOUND_MIXER_MIC, 20, 1, 1, 4, 21, 1, 1, 4, 7),
|
||||
MIX_ENT(SOUND_MIXER_CD, 2, 1, 1, 4, 3, 1, 1, 4, 7),
|
||||
MIX_ENT(SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
|
||||
MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 1, 4, 3, 1, 1, 4, 7),
|
||||
MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 1, 4, 5, 1, 1, 4, 7),
|
||||
MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 1, 4, 19, 1, 1, 4, 7)
|
||||
};
|
||||
|
||||
static mixer_ents spro_mix_devices[32] = {
|
||||
MIX_ENT (SOUND_MIXER_VOLUME, 19, 0, 4, 4, 19, 0, 0, 4, 8),
|
||||
MIX_ENT (SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT (SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT2(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 23, 0, 3, 0, 0, 8,
|
||||
5, 1, 1, 4, 23, 0, 3, 0, 0, 8),
|
||||
MIX_ENT (SOUND_MIXER_PCM, 6, 1, 1, 4, 7, 1, 1, 4, 8),
|
||||
MIX_ENT (SOUND_MIXER_SPEAKER, 18, 0, 3, 2, 0, 0, 0, 0, 8),
|
||||
MIX_ENT2(SOUND_MIXER_LINE, 20, 0, 4, 4, 17, 1, 4, 16, 0, 2,
|
||||
20, 0, 0, 4, 17, 1, 3, 16, 0, 1),
|
||||
MIX_ENT2(SOUND_MIXER_MIC, 18, 0, 0, 3, 17, 1, 0, 16, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
MIX_ENT2(SOUND_MIXER_CD, 21, 0, 4, 4, 17, 1, 2, 16, 0, 4,
|
||||
21, 0, 0, 4, 17, 1, 1, 16, 0, 3),
|
||||
MIX_ENT (SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT (SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT (SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT (SOUND_MIXER_IGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
|
||||
MIX_ENT (SOUND_MIXER_OGAIN, 17, 1, 6, 1, 0, 0, 0, 0, 8),
|
||||
/* This is external wavetable */
|
||||
MIX_ENT2(SOUND_MIXER_LINE1, 22, 0, 4, 4, 23, 1, 1, 23, 0, 4,
|
||||
22, 0, 0, 4, 23, 1, 0, 23, 0, 5),
|
||||
};
|
||||
|
||||
static int default_mixer_levels[32] =
|
||||
{
|
||||
0x3232, /* Master Volume */
|
||||
0x3232, /* Bass */
|
||||
0x3232, /* Treble */
|
||||
0x4b4b, /* FM */
|
||||
0x3232, /* PCM */
|
||||
0x1515, /* PC Speaker */
|
||||
0x2020, /* Ext Line */
|
||||
0x1010, /* Mic */
|
||||
0x4b4b, /* CD */
|
||||
0x0000, /* Recording monitor */
|
||||
0x4b4b, /* Second PCM */
|
||||
0x4b4b, /* Recording level */
|
||||
0x4b4b, /* Input gain */
|
||||
0x4b4b, /* Output gain */
|
||||
0x2020, /* Line1 */
|
||||
0x2020, /* Line2 */
|
||||
0x1515 /* Line3 (usually line in)*/
|
||||
};
|
||||
|
||||
#define LEFT_CHN 0
|
||||
#define RIGHT_CHN 1
|
||||
|
||||
/*
|
||||
* Channel enable bits for ioctl(SOUND_MIXER_PRIVATE1)
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_SPEAKER
|
||||
#define AUDIO_SPEAKER 0x01 /* Enable mono output */
|
||||
#define AUDIO_HEADPHONE 0x02 /* Sparc only */
|
||||
#define AUDIO_LINE_OUT 0x04 /* Sparc only */
|
||||
#endif
|
1373
sound/oss/aedsp16.c
1373
sound/oss/aedsp16.c
File diff suppressed because it is too large
Load diff
|
@ -1,985 +0,0 @@
|
|||
/*
|
||||
* sound/oss/audio.c
|
||||
*
|
||||
* Device file manager for /dev/audio
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) by Hannu Savolainen 1993-1997
|
||||
*
|
||||
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
|
||||
* Version 2 (June 1991). See the "COPYING" file distributed with this software
|
||||
* for more info.
|
||||
*/
|
||||
/*
|
||||
* Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
|
||||
* Thomas Sailer : moved several static variables into struct audio_operations
|
||||
* (which is grossly misnamed btw.) because they have the same
|
||||
* lifetime as the rest in there and dynamic allocation saves
|
||||
* 12k or so
|
||||
* Thomas Sailer : use more logical O_NONBLOCK semantics
|
||||
* Daniel Rodriksson: reworked the use of the device specific copy_user
|
||||
* still generic
|
||||
* Horst von Brand: Add missing #include <linux/string.h>
|
||||
* Chris Rankin : Update the module-usage counter for the coprocessor,
|
||||
* and decrement the counters again if we cannot open
|
||||
* the audio device.
|
||||
*/
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kmod.h>
|
||||
|
||||
#include "sound_config.h"
|
||||
#include "ulaw.h"
|
||||
#include "coproc.h"
|
||||
|
||||
#define NEUTRAL8 0x80
|
||||
#define NEUTRAL16 0x00
|
||||
|
||||
|
||||
static int dma_ioctl(int dev, unsigned int cmd, void __user *arg);
|
||||
|
||||
static int set_format(int dev, int fmt)
|
||||
{
|
||||
if (fmt != AFMT_QUERY)
|
||||
{
|
||||
audio_devs[dev]->local_conversion = 0;
|
||||
|
||||
if (!(audio_devs[dev]->format_mask & fmt)) /* Not supported */
|
||||
{
|
||||
if (fmt == AFMT_MU_LAW)
|
||||
{
|
||||
fmt = AFMT_U8;
|
||||
audio_devs[dev]->local_conversion = CNV_MU_LAW;
|
||||
}
|
||||
else
|
||||
fmt = AFMT_U8; /* This is always supported */
|
||||
}
|
||||
audio_devs[dev]->audio_format = audio_devs[dev]->d->set_bits(dev, fmt);
|
||||
audio_devs[dev]->local_format = fmt;
|
||||
}
|
||||
else
|
||||
return audio_devs[dev]->local_format;
|
||||
|
||||
if (audio_devs[dev]->local_conversion)
|
||||
return audio_devs[dev]->local_conversion;
|
||||
else
|
||||
return audio_devs[dev]->local_format;
|
||||
}
|
||||
|
||||
int audio_open(int dev, struct file *file)
|
||||
{
|
||||
int ret;
|
||||
int bits;
|
||||
int dev_type = dev & 0x0f;
|
||||
int mode = translate_mode(file);
|
||||
const struct audio_driver *driver;
|
||||
const struct coproc_operations *coprocessor;
|
||||
|
||||
dev = dev >> 4;
|
||||
|
||||
if (dev_type == SND_DEV_DSP16)
|
||||
bits = 16;
|
||||
else
|
||||
bits = 8;
|
||||
|
||||
if (dev < 0 || dev >= num_audiodevs)
|
||||
return -ENXIO;
|
||||
|
||||
driver = audio_devs[dev]->d;
|
||||
|
||||
if (!try_module_get(driver->owner))
|
||||
return -ENODEV;
|
||||
|
||||
if ((ret = DMAbuf_open(dev, mode)) < 0)
|
||||
goto error_1;
|
||||
|
||||
if ( (coprocessor = audio_devs[dev]->coproc) != NULL ) {
|
||||
if (!try_module_get(coprocessor->owner))
|
||||
goto error_2;
|
||||
|
||||
if ((ret = coprocessor->open(coprocessor->devc, COPR_PCM)) < 0) {
|
||||
printk(KERN_WARNING "Sound: Can't access coprocessor device\n");
|
||||
goto error_3;
|
||||
}
|
||||
}
|
||||
|
||||
audio_devs[dev]->local_conversion = 0;
|
||||
|
||||
if (dev_type == SND_DEV_AUDIO)
|
||||
set_format(dev, AFMT_MU_LAW);
|
||||
else
|
||||
set_format(dev, bits);
|
||||
|
||||
audio_devs[dev]->audio_mode = AM_NONE;
|
||||
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Clean-up stack: this is what needs (un)doing if
|
||||
* we can't open the audio device ...
|
||||
*/
|
||||
error_3:
|
||||
module_put(coprocessor->owner);
|
||||
|
||||
error_2:
|
||||
DMAbuf_release(dev, mode);
|
||||
|
||||
error_1:
|
||||
module_put(driver->owner);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sync_output(int dev)
|
||||
{
|
||||
int p, i;
|
||||
int l;
|
||||
struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
|
||||
|
||||
if (dmap->fragment_size <= 0)
|
||||
return;
|
||||
dmap->flags |= DMA_POST;
|
||||
|
||||
/* Align the write pointer with fragment boundaries */
|
||||
|
||||
if ((l = dmap->user_counter % dmap->fragment_size) > 0)
|
||||
{
|
||||
int len;
|
||||
unsigned long offs = dmap->user_counter % dmap->bytes_in_use;
|
||||
|
||||
len = dmap->fragment_size - l;
|
||||
memset(dmap->raw_buf + offs, dmap->neutral_byte, len);
|
||||
DMAbuf_move_wrpointer(dev, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean all unused buffer fragments.
|
||||
*/
|
||||
|
||||
p = dmap->qtail;
|
||||
dmap->flags |= DMA_POST;
|
||||
|
||||
for (i = dmap->qlen + 1; i < dmap->nbufs; i++)
|
||||
{
|
||||
p = (p + 1) % dmap->nbufs;
|
||||
if (((dmap->raw_buf + p * dmap->fragment_size) + dmap->fragment_size) >
|
||||
(dmap->raw_buf + dmap->buffsize))
|
||||
printk(KERN_ERR "audio: Buffer error 2\n");
|
||||
|
||||
memset(dmap->raw_buf + p * dmap->fragment_size,
|
||||
dmap->neutral_byte,
|
||||
dmap->fragment_size);
|
||||
}
|
||||
|
||||
dmap->flags |= DMA_DIRTY;
|
||||
}
|
||||
|
||||
void audio_release(int dev, struct file *file)
|
||||
{
|
||||
const struct coproc_operations *coprocessor;
|
||||
int mode = translate_mode(file);
|
||||
|
||||
dev = dev >> 4;
|
||||
|
||||
/*
|
||||
* We do this in DMAbuf_release(). Why are we doing it
|
||||
* here? Why don't we test the file mode before setting
|
||||
* both flags? DMAbuf_release() does.
|
||||
* ...pester...pester...pester...
|
||||
*/
|
||||
audio_devs[dev]->dmap_out->closing = 1;
|
||||
audio_devs[dev]->dmap_in->closing = 1;
|
||||
|
||||
/*
|
||||
* We need to make sure we allocated the dmap_out buffer
|
||||
* before we go mucking around with it in sync_output().
|
||||
*/
|
||||
if (mode & OPEN_WRITE)
|
||||
sync_output(dev);
|
||||
|
||||
if ( (coprocessor = audio_devs[dev]->coproc) != NULL ) {
|
||||
coprocessor->close(coprocessor->devc, COPR_PCM);
|
||||
module_put(coprocessor->owner);
|
||||
}
|
||||
DMAbuf_release(dev, mode);
|
||||
|
||||
module_put(audio_devs[dev]->d->owner);
|
||||
}
|
||||
|
||||
static void translate_bytes(const unsigned char *table, unsigned char *buff, int n)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
if (n <= 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
buff[i] = table[buff[i]];
|
||||
}
|
||||
|
||||
int audio_write(int dev, struct file *file, const char __user *buf, int count)
|
||||
{
|
||||
int c, p, l, buf_size, used, returned;
|
||||
int err;
|
||||
char *dma_buf;
|
||||
|
||||
dev = dev >> 4;
|
||||
|
||||
p = 0;
|
||||
c = count;
|
||||
|
||||
if(count < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
|
||||
return -EPERM;
|
||||
|
||||
if (audio_devs[dev]->flags & DMA_DUPLEX)
|
||||
audio_devs[dev]->audio_mode |= AM_WRITE;
|
||||
else
|
||||
audio_devs[dev]->audio_mode = AM_WRITE;
|
||||
|
||||
if (!count) /* Flush output */
|
||||
{
|
||||
sync_output(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (c)
|
||||
{
|
||||
if ((err = DMAbuf_getwrbuffer(dev, &dma_buf, &buf_size, !!(file->f_flags & O_NONBLOCK))) < 0)
|
||||
{
|
||||
/* Handle nonblocking mode */
|
||||
if ((file->f_flags & O_NONBLOCK) && err == -EAGAIN)
|
||||
return p? p : -EAGAIN; /* No more space. Return # of accepted bytes */
|
||||
return err;
|
||||
}
|
||||
l = c;
|
||||
|
||||
if (l > buf_size)
|
||||
l = buf_size;
|
||||
|
||||
returned = l;
|
||||
used = l;
|
||||
if (!audio_devs[dev]->d->copy_user)
|
||||
{
|
||||
if ((dma_buf + l) >
|
||||
(audio_devs[dev]->dmap_out->raw_buf + audio_devs[dev]->dmap_out->buffsize))
|
||||
{
|
||||
printk(KERN_ERR "audio: Buffer error 3 (%lx,%d), (%lx, %d)\n", (long) dma_buf, l, (long) audio_devs[dev]->dmap_out->raw_buf, (int) audio_devs[dev]->dmap_out->buffsize);
|
||||
return -EDOM;
|
||||
}
|
||||
if (dma_buf < audio_devs[dev]->dmap_out->raw_buf)
|
||||
{
|
||||
printk(KERN_ERR "audio: Buffer error 13 (%lx<%lx)\n", (long) dma_buf, (long) audio_devs[dev]->dmap_out->raw_buf);
|
||||
return -EDOM;
|
||||
}
|
||||
if(copy_from_user(dma_buf, &(buf)[p], l))
|
||||
return -EFAULT;
|
||||
}
|
||||
else audio_devs[dev]->d->copy_user (dev,
|
||||
dma_buf, 0,
|
||||
buf, p,
|
||||
c, buf_size,
|
||||
&used, &returned,
|
||||
l);
|
||||
l = returned;
|
||||
|
||||
if (audio_devs[dev]->local_conversion & CNV_MU_LAW)
|
||||
{
|
||||
translate_bytes(ulaw_dsp, (unsigned char *) dma_buf, l);
|
||||
}
|
||||
c -= used;
|
||||
p += used;
|
||||
DMAbuf_move_wrpointer(dev, l);
|
||||
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int audio_read(int dev, struct file *file, char __user *buf, int count)
|
||||
{
|
||||
int c, p, l;
|
||||
char *dmabuf;
|
||||
int buf_no;
|
||||
|
||||
dev = dev >> 4;
|
||||
p = 0;
|
||||
c = count;
|
||||
|
||||
if (!(audio_devs[dev]->open_mode & OPEN_READ))
|
||||
return -EPERM;
|
||||
|
||||
if ((audio_devs[dev]->audio_mode & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
|
||||
sync_output(dev);
|
||||
|
||||
if (audio_devs[dev]->flags & DMA_DUPLEX)
|
||||
audio_devs[dev]->audio_mode |= AM_READ;
|
||||
else
|
||||
audio_devs[dev]->audio_mode = AM_READ;
|
||||
|
||||
while(c)
|
||||
{
|
||||
if ((buf_no = DMAbuf_getrdbuffer(dev, &dmabuf, &l, !!(file->f_flags & O_NONBLOCK))) < 0)
|
||||
{
|
||||
/*
|
||||
* Nonblocking mode handling. Return current # of bytes
|
||||
*/
|
||||
|
||||
if (p > 0) /* Avoid throwing away data */
|
||||
return p; /* Return it instead */
|
||||
|
||||
if ((file->f_flags & O_NONBLOCK) && buf_no == -EAGAIN)
|
||||
return -EAGAIN;
|
||||
|
||||
return buf_no;
|
||||
}
|
||||
if (l > c)
|
||||
l = c;
|
||||
|
||||
/*
|
||||
* Insert any local processing here.
|
||||
*/
|
||||
|
||||
if (audio_devs[dev]->local_conversion & CNV_MU_LAW)
|
||||
{
|
||||
translate_bytes(dsp_ulaw, (unsigned char *) dmabuf, l);
|
||||
}
|
||||
|
||||
{
|
||||
char *fixit = dmabuf;
|
||||
|
||||
if(copy_to_user(&(buf)[p], fixit, l))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
DMAbuf_rmchars(dev, buf_no, l);
|
||||
|
||||
p += l;
|
||||
c -= l;
|
||||
}
|
||||
|
||||
return count - c;
|
||||
}
|
||||
|
||||
int audio_ioctl(int dev, struct file *file, unsigned int cmd, void __user *arg)
|
||||
{
|
||||
int val, count;
|
||||
unsigned long flags;
|
||||
struct dma_buffparms *dmap;
|
||||
int __user *p = arg;
|
||||
|
||||
dev = dev >> 4;
|
||||
|
||||
if (_IOC_TYPE(cmd) == 'C') {
|
||||
if (audio_devs[dev]->coproc) /* Coprocessor ioctl */
|
||||
return audio_devs[dev]->coproc->ioctl(audio_devs[dev]->coproc->devc, cmd, arg, 0);
|
||||
/* else
|
||||
printk(KERN_DEBUG"/dev/dsp%d: No coprocessor for this device\n", dev); */
|
||||
return -ENXIO;
|
||||
}
|
||||
else switch (cmd)
|
||||
{
|
||||
case SNDCTL_DSP_SYNC:
|
||||
if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
|
||||
return 0;
|
||||
if (audio_devs[dev]->dmap_out->fragment_size == 0)
|
||||
return 0;
|
||||
sync_output(dev);
|
||||
DMAbuf_sync(dev);
|
||||
DMAbuf_reset(dev);
|
||||
return 0;
|
||||
|
||||
case SNDCTL_DSP_POST:
|
||||
if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
|
||||
return 0;
|
||||
if (audio_devs[dev]->dmap_out->fragment_size == 0)
|
||||
return 0;
|
||||
audio_devs[dev]->dmap_out->flags |= DMA_POST | DMA_DIRTY;
|
||||
sync_output(dev);
|
||||
dma_ioctl(dev, SNDCTL_DSP_POST, NULL);
|
||||
return 0;
|
||||
|
||||
case SNDCTL_DSP_RESET:
|
||||
audio_devs[dev]->audio_mode = AM_NONE;
|
||||
DMAbuf_reset(dev);
|
||||
return 0;
|
||||
|
||||
case SNDCTL_DSP_GETFMTS:
|
||||
val = audio_devs[dev]->format_mask | AFMT_MU_LAW;
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_SETFMT:
|
||||
if (get_user(val, p))
|
||||
return -EFAULT;
|
||||
val = set_format(dev, val);
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_GETISPACE:
|
||||
if (!(audio_devs[dev]->open_mode & OPEN_READ))
|
||||
return 0;
|
||||
if ((audio_devs[dev]->audio_mode & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
|
||||
return -EBUSY;
|
||||
return dma_ioctl(dev, cmd, arg);
|
||||
|
||||
case SNDCTL_DSP_GETOSPACE:
|
||||
if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
|
||||
return -EPERM;
|
||||
if ((audio_devs[dev]->audio_mode & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
|
||||
return -EBUSY;
|
||||
return dma_ioctl(dev, cmd, arg);
|
||||
|
||||
case SNDCTL_DSP_NONBLOCK:
|
||||
spin_lock(&file->f_lock);
|
||||
file->f_flags |= O_NONBLOCK;
|
||||
spin_unlock(&file->f_lock);
|
||||
return 0;
|
||||
|
||||
case SNDCTL_DSP_GETCAPS:
|
||||
val = 1 | DSP_CAP_MMAP; /* Revision level of this ioctl() */
|
||||
if (audio_devs[dev]->flags & DMA_DUPLEX &&
|
||||
audio_devs[dev]->open_mode == OPEN_READWRITE)
|
||||
val |= DSP_CAP_DUPLEX;
|
||||
if (audio_devs[dev]->coproc)
|
||||
val |= DSP_CAP_COPROC;
|
||||
if (audio_devs[dev]->d->local_qlen) /* Device has hidden buffers */
|
||||
val |= DSP_CAP_BATCH;
|
||||
if (audio_devs[dev]->d->trigger) /* Supports SETTRIGGER */
|
||||
val |= DSP_CAP_TRIGGER;
|
||||
break;
|
||||
|
||||
case SOUND_PCM_WRITE_RATE:
|
||||
if (get_user(val, p))
|
||||
return -EFAULT;
|
||||
val = audio_devs[dev]->d->set_speed(dev, val);
|
||||
break;
|
||||
|
||||
case SOUND_PCM_READ_RATE:
|
||||
val = audio_devs[dev]->d->set_speed(dev, 0);
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_STEREO:
|
||||
if (get_user(val, p))
|
||||
return -EFAULT;
|
||||
if (val > 1 || val < 0)
|
||||
return -EINVAL;
|
||||
val = audio_devs[dev]->d->set_channels(dev, val + 1) - 1;
|
||||
break;
|
||||
|
||||
case SOUND_PCM_WRITE_CHANNELS:
|
||||
if (get_user(val, p))
|
||||
return -EFAULT;
|
||||
val = audio_devs[dev]->d->set_channels(dev, val);
|
||||
break;
|
||||
|
||||
case SOUND_PCM_READ_CHANNELS:
|
||||
val = audio_devs[dev]->d->set_channels(dev, 0);
|
||||
break;
|
||||
|
||||
case SOUND_PCM_READ_BITS:
|
||||
val = audio_devs[dev]->d->set_bits(dev, 0);
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_SETDUPLEX:
|
||||
if (audio_devs[dev]->open_mode != OPEN_READWRITE)
|
||||
return -EPERM;
|
||||
return (audio_devs[dev]->flags & DMA_DUPLEX) ? 0 : -EIO;
|
||||
|
||||
case SNDCTL_DSP_PROFILE:
|
||||
if (get_user(val, p))
|
||||
return -EFAULT;
|
||||
if (audio_devs[dev]->open_mode & OPEN_WRITE)
|
||||
audio_devs[dev]->dmap_out->applic_profile = val;
|
||||
if (audio_devs[dev]->open_mode & OPEN_READ)
|
||||
audio_devs[dev]->dmap_in->applic_profile = val;
|
||||
return 0;
|
||||
|
||||
case SNDCTL_DSP_GETODELAY:
|
||||
dmap = audio_devs[dev]->dmap_out;
|
||||
if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
|
||||
return -EINVAL;
|
||||
if (!(dmap->flags & DMA_ALLOC_DONE))
|
||||
{
|
||||
val=0;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dmap->lock,flags);
|
||||
/* Compute number of bytes that have been played */
|
||||
count = DMAbuf_get_buffer_pointer (dev, dmap, DMODE_OUTPUT);
|
||||
if (count < dmap->fragment_size && dmap->qhead != 0)
|
||||
count += dmap->bytes_in_use; /* Pointer wrap not handled yet */
|
||||
count += dmap->byte_counter;
|
||||
|
||||
/* Subtract current count from the number of bytes written by app */
|
||||
count = dmap->user_counter - count;
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
spin_unlock_irqrestore(&dmap->lock,flags);
|
||||
val = count;
|
||||
break;
|
||||
|
||||
default:
|
||||
return dma_ioctl(dev, cmd, arg);
|
||||
}
|
||||
return put_user(val, p);
|
||||
}
|
||||
|
||||
void audio_init_devices(void)
|
||||
{
|
||||
/*
|
||||
* NOTE! This routine could be called several times during boot.
|
||||
*/
|
||||
}
|
||||
|
||||
void reorganize_buffers(int dev, struct dma_buffparms *dmap, int recording)
|
||||
{
|
||||
/*
|
||||
* This routine breaks the physical device buffers to logical ones.
|
||||
*/
|
||||
|
||||
struct audio_operations *dsp_dev = audio_devs[dev];
|
||||
|
||||
unsigned i, n;
|
||||
unsigned sr, nc, sz, bsz;
|
||||
|
||||
sr = dsp_dev->d->set_speed(dev, 0);
|
||||
nc = dsp_dev->d->set_channels(dev, 0);
|
||||
sz = dsp_dev->d->set_bits(dev, 0);
|
||||
|
||||
if (sz == 8)
|
||||
dmap->neutral_byte = NEUTRAL8;
|
||||
else
|
||||
dmap->neutral_byte = NEUTRAL16;
|
||||
|
||||
if (sr < 1 || nc < 1 || sz < 1)
|
||||
{
|
||||
/* printk(KERN_DEBUG "Warning: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n", dev, sr, nc, sz);*/
|
||||
sr = DSP_DEFAULT_SPEED;
|
||||
nc = 1;
|
||||
sz = 8;
|
||||
}
|
||||
|
||||
sz = sr * nc * sz;
|
||||
|
||||
sz /= 8; /* #bits -> #bytes */
|
||||
dmap->data_rate = sz;
|
||||
|
||||
if (!dmap->needs_reorg)
|
||||
return;
|
||||
dmap->needs_reorg = 0;
|
||||
|
||||
if (dmap->fragment_size == 0)
|
||||
{
|
||||
/* Compute the fragment size using the default algorithm */
|
||||
|
||||
/*
|
||||
* Compute a buffer size for time not exceeding 1 second.
|
||||
* Usually this algorithm gives a buffer size for 0.5 to 1.0 seconds
|
||||
* of sound (using the current speed, sample size and #channels).
|
||||
*/
|
||||
|
||||
bsz = dmap->buffsize;
|
||||
while (bsz > sz)
|
||||
bsz /= 2;
|
||||
|
||||
if (bsz == dmap->buffsize)
|
||||
bsz /= 2; /* Needs at least 2 buffers */
|
||||
|
||||
/*
|
||||
* Split the computed fragment to smaller parts. After 3.5a9
|
||||
* the default subdivision is 4 which should give better
|
||||
* results when recording.
|
||||
*/
|
||||
|
||||
if (dmap->subdivision == 0) /* Not already set */
|
||||
{
|
||||
dmap->subdivision = 4; /* Init to the default value */
|
||||
|
||||
if ((bsz / dmap->subdivision) > 4096)
|
||||
dmap->subdivision *= 2;
|
||||
if ((bsz / dmap->subdivision) < 4096)
|
||||
dmap->subdivision = 1;
|
||||
}
|
||||
bsz /= dmap->subdivision;
|
||||
|
||||
if (bsz < 16)
|
||||
bsz = 16; /* Just a sanity check */
|
||||
|
||||
dmap->fragment_size = bsz;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* The process has specified the buffer size with SNDCTL_DSP_SETFRAGMENT or
|
||||
* the buffer size computation has already been done.
|
||||
*/
|
||||
if (dmap->fragment_size > (dmap->buffsize / 2))
|
||||
dmap->fragment_size = (dmap->buffsize / 2);
|
||||
bsz = dmap->fragment_size;
|
||||
}
|
||||
|
||||
if (audio_devs[dev]->min_fragment)
|
||||
if (bsz < (1 << audio_devs[dev]->min_fragment))
|
||||
bsz = 1 << audio_devs[dev]->min_fragment;
|
||||
if (audio_devs[dev]->max_fragment)
|
||||
if (bsz > (1 << audio_devs[dev]->max_fragment))
|
||||
bsz = 1 << audio_devs[dev]->max_fragment;
|
||||
bsz &= ~0x07; /* Force size which is multiple of 8 bytes */
|
||||
#ifdef OS_DMA_ALIGN_CHECK
|
||||
OS_DMA_ALIGN_CHECK(bsz);
|
||||
#endif
|
||||
|
||||
n = dmap->buffsize / bsz;
|
||||
if (n > MAX_SUB_BUFFERS)
|
||||
n = MAX_SUB_BUFFERS;
|
||||
if (n > dmap->max_fragments)
|
||||
n = dmap->max_fragments;
|
||||
|
||||
if (n < 2)
|
||||
{
|
||||
n = 2;
|
||||
bsz /= 2;
|
||||
}
|
||||
dmap->nbufs = n;
|
||||
dmap->bytes_in_use = n * bsz;
|
||||
dmap->fragment_size = bsz;
|
||||
dmap->max_byte_counter = (dmap->data_rate * 60 * 60) +
|
||||
dmap->bytes_in_use; /* Approximately one hour */
|
||||
|
||||
if (dmap->raw_buf)
|
||||
{
|
||||
memset(dmap->raw_buf, dmap->neutral_byte, dmap->bytes_in_use);
|
||||
}
|
||||
|
||||
for (i = 0; i < dmap->nbufs; i++)
|
||||
{
|
||||
dmap->counts[i] = 0;
|
||||
}
|
||||
|
||||
dmap->flags |= DMA_ALLOC_DONE | DMA_EMPTY;
|
||||
}
|
||||
|
||||
static int dma_subdivide(int dev, struct dma_buffparms *dmap, int fact)
|
||||
{
|
||||
if (fact == 0)
|
||||
{
|
||||
fact = dmap->subdivision;
|
||||
if (fact == 0)
|
||||
fact = 1;
|
||||
return fact;
|
||||
}
|
||||
if (dmap->subdivision != 0 || dmap->fragment_size) /* Too late to change */
|
||||
return -EINVAL;
|
||||
|
||||
if (fact > MAX_REALTIME_FACTOR)
|
||||
return -EINVAL;
|
||||
|
||||
if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16)
|
||||
return -EINVAL;
|
||||
|
||||
dmap->subdivision = fact;
|
||||
return fact;
|
||||
}
|
||||
|
||||
static int dma_set_fragment(int dev, struct dma_buffparms *dmap, int fact)
|
||||
{
|
||||
int bytes, count;
|
||||
|
||||
if (fact == 0)
|
||||
return -EIO;
|
||||
|
||||
if (dmap->subdivision != 0 ||
|
||||
dmap->fragment_size) /* Too late to change */
|
||||
return -EINVAL;
|
||||
|
||||
bytes = fact & 0xffff;
|
||||
count = (fact >> 16) & 0x7fff;
|
||||
|
||||
if (count == 0)
|
||||
count = MAX_SUB_BUFFERS;
|
||||
else if (count < MAX_SUB_BUFFERS)
|
||||
count++;
|
||||
|
||||
if (bytes < 4 || bytes > 17) /* <16 || > 512k */
|
||||
return -EINVAL;
|
||||
|
||||
if (count < 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (audio_devs[dev]->min_fragment > 0)
|
||||
if (bytes < audio_devs[dev]->min_fragment)
|
||||
bytes = audio_devs[dev]->min_fragment;
|
||||
|
||||
if (audio_devs[dev]->max_fragment > 0)
|
||||
if (bytes > audio_devs[dev]->max_fragment)
|
||||
bytes = audio_devs[dev]->max_fragment;
|
||||
|
||||
#ifdef OS_DMA_MINBITS
|
||||
if (bytes < OS_DMA_MINBITS)
|
||||
bytes = OS_DMA_MINBITS;
|
||||
#endif
|
||||
|
||||
dmap->fragment_size = (1 << bytes);
|
||||
dmap->max_fragments = count;
|
||||
|
||||
if (dmap->fragment_size > dmap->buffsize)
|
||||
dmap->fragment_size = dmap->buffsize;
|
||||
|
||||
if (dmap->fragment_size == dmap->buffsize &&
|
||||
audio_devs[dev]->flags & DMA_AUTOMODE)
|
||||
dmap->fragment_size /= 2; /* Needs at least 2 buffers */
|
||||
|
||||
dmap->subdivision = 1; /* Disable SNDCTL_DSP_SUBDIVIDE */
|
||||
return bytes | ((count - 1) << 16);
|
||||
}
|
||||
|
||||
static int dma_ioctl(int dev, unsigned int cmd, void __user *arg)
|
||||
{
|
||||
struct dma_buffparms *dmap_out = audio_devs[dev]->dmap_out;
|
||||
struct dma_buffparms *dmap_in = audio_devs[dev]->dmap_in;
|
||||
struct dma_buffparms *dmap;
|
||||
audio_buf_info info;
|
||||
count_info cinfo;
|
||||
int fact, ret, changed, bits, count, err;
|
||||
unsigned long flags;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case SNDCTL_DSP_SUBDIVIDE:
|
||||
ret = 0;
|
||||
if (get_user(fact, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
if (audio_devs[dev]->open_mode & OPEN_WRITE)
|
||||
ret = dma_subdivide(dev, dmap_out, fact);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (audio_devs[dev]->open_mode != OPEN_WRITE ||
|
||||
(audio_devs[dev]->flags & DMA_DUPLEX &&
|
||||
audio_devs[dev]->open_mode & OPEN_READ))
|
||||
ret = dma_subdivide(dev, dmap_in, fact);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_GETISPACE:
|
||||
case SNDCTL_DSP_GETOSPACE:
|
||||
dmap = dmap_out;
|
||||
if (cmd == SNDCTL_DSP_GETISPACE && !(audio_devs[dev]->open_mode & OPEN_READ))
|
||||
return -EINVAL;
|
||||
if (cmd == SNDCTL_DSP_GETOSPACE && !(audio_devs[dev]->open_mode & OPEN_WRITE))
|
||||
return -EINVAL;
|
||||
if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX)
|
||||
dmap = dmap_in;
|
||||
if (dmap->mapping_flags & DMA_MAP_MAPPED)
|
||||
return -EINVAL;
|
||||
if (!(dmap->flags & DMA_ALLOC_DONE))
|
||||
reorganize_buffers(dev, dmap, (cmd == SNDCTL_DSP_GETISPACE));
|
||||
info.fragstotal = dmap->nbufs;
|
||||
if (cmd == SNDCTL_DSP_GETISPACE)
|
||||
info.fragments = dmap->qlen;
|
||||
else
|
||||
{
|
||||
if (!DMAbuf_space_in_queue(dev))
|
||||
info.fragments = 0;
|
||||
else
|
||||
{
|
||||
info.fragments = DMAbuf_space_in_queue(dev);
|
||||
if (audio_devs[dev]->d->local_qlen)
|
||||
{
|
||||
int tmp = audio_devs[dev]->d->local_qlen(dev);
|
||||
if (tmp && info.fragments)
|
||||
tmp--; /*
|
||||
* This buffer has been counted twice
|
||||
*/
|
||||
info.fragments -= tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (info.fragments < 0)
|
||||
info.fragments = 0;
|
||||
else if (info.fragments > dmap->nbufs)
|
||||
info.fragments = dmap->nbufs;
|
||||
|
||||
info.fragsize = dmap->fragment_size;
|
||||
info.bytes = info.fragments * dmap->fragment_size;
|
||||
|
||||
if (cmd == SNDCTL_DSP_GETISPACE && dmap->qlen)
|
||||
info.bytes -= dmap->counts[dmap->qhead];
|
||||
else
|
||||
{
|
||||
info.fragments = info.bytes / dmap->fragment_size;
|
||||
info.bytes -= dmap->user_counter % dmap->fragment_size;
|
||||
}
|
||||
if (copy_to_user(arg, &info, sizeof(info)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case SNDCTL_DSP_SETTRIGGER:
|
||||
if (get_user(bits, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
bits &= audio_devs[dev]->open_mode;
|
||||
if (audio_devs[dev]->d->trigger == NULL)
|
||||
return -EINVAL;
|
||||
if (!(audio_devs[dev]->flags & DMA_DUPLEX) && (bits & PCM_ENABLE_INPUT) &&
|
||||
(bits & PCM_ENABLE_OUTPUT))
|
||||
return -EINVAL;
|
||||
|
||||
if (bits & PCM_ENABLE_INPUT)
|
||||
{
|
||||
spin_lock_irqsave(&dmap_in->lock,flags);
|
||||
changed = (audio_devs[dev]->enable_bits ^ bits) & PCM_ENABLE_INPUT;
|
||||
if (changed && audio_devs[dev]->go)
|
||||
{
|
||||
reorganize_buffers(dev, dmap_in, 1);
|
||||
if ((err = audio_devs[dev]->d->prepare_for_input(dev,
|
||||
dmap_in->fragment_size, dmap_in->nbufs)) < 0) {
|
||||
spin_unlock_irqrestore(&dmap_in->lock,flags);
|
||||
return err;
|
||||
}
|
||||
dmap_in->dma_mode = DMODE_INPUT;
|
||||
audio_devs[dev]->enable_bits |= PCM_ENABLE_INPUT;
|
||||
DMAbuf_activate_recording(dev, dmap_in);
|
||||
} else
|
||||
audio_devs[dev]->enable_bits &= ~PCM_ENABLE_INPUT;
|
||||
spin_unlock_irqrestore(&dmap_in->lock,flags);
|
||||
}
|
||||
if (bits & PCM_ENABLE_OUTPUT)
|
||||
{
|
||||
spin_lock_irqsave(&dmap_out->lock,flags);
|
||||
changed = (audio_devs[dev]->enable_bits ^ bits) & PCM_ENABLE_OUTPUT;
|
||||
if (changed &&
|
||||
(dmap_out->mapping_flags & DMA_MAP_MAPPED || dmap_out->qlen > 0) &&
|
||||
audio_devs[dev]->go)
|
||||
{
|
||||
if (!(dmap_out->flags & DMA_ALLOC_DONE))
|
||||
reorganize_buffers(dev, dmap_out, 0);
|
||||
dmap_out->dma_mode = DMODE_OUTPUT;
|
||||
audio_devs[dev]->enable_bits |= PCM_ENABLE_OUTPUT;
|
||||
dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size;
|
||||
DMAbuf_launch_output(dev, dmap_out);
|
||||
} else
|
||||
audio_devs[dev]->enable_bits &= ~PCM_ENABLE_OUTPUT;
|
||||
spin_unlock_irqrestore(&dmap_out->lock,flags);
|
||||
}
|
||||
#if 0
|
||||
if (changed && audio_devs[dev]->d->trigger)
|
||||
audio_devs[dev]->d->trigger(dev, bits * audio_devs[dev]->go);
|
||||
#endif
|
||||
/* Falls through... */
|
||||
|
||||
case SNDCTL_DSP_GETTRIGGER:
|
||||
ret = audio_devs[dev]->enable_bits;
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_SETSYNCRO:
|
||||
if (!audio_devs[dev]->d->trigger)
|
||||
return -EINVAL;
|
||||
audio_devs[dev]->d->trigger(dev, 0);
|
||||
audio_devs[dev]->go = 0;
|
||||
return 0;
|
||||
|
||||
case SNDCTL_DSP_GETIPTR:
|
||||
if (!(audio_devs[dev]->open_mode & OPEN_READ))
|
||||
return -EINVAL;
|
||||
spin_lock_irqsave(&dmap_in->lock,flags);
|
||||
cinfo.bytes = dmap_in->byte_counter;
|
||||
cinfo.ptr = DMAbuf_get_buffer_pointer(dev, dmap_in, DMODE_INPUT) & ~3;
|
||||
if (cinfo.ptr < dmap_in->fragment_size && dmap_in->qtail != 0)
|
||||
cinfo.bytes += dmap_in->bytes_in_use; /* Pointer wrap not handled yet */
|
||||
cinfo.blocks = dmap_in->qlen;
|
||||
cinfo.bytes += cinfo.ptr;
|
||||
if (dmap_in->mapping_flags & DMA_MAP_MAPPED)
|
||||
dmap_in->qlen = 0; /* Reset interrupt counter */
|
||||
spin_unlock_irqrestore(&dmap_in->lock,flags);
|
||||
if (copy_to_user(arg, &cinfo, sizeof(cinfo)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case SNDCTL_DSP_GETOPTR:
|
||||
if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&dmap_out->lock,flags);
|
||||
cinfo.bytes = dmap_out->byte_counter;
|
||||
cinfo.ptr = DMAbuf_get_buffer_pointer(dev, dmap_out, DMODE_OUTPUT) & ~3;
|
||||
if (cinfo.ptr < dmap_out->fragment_size && dmap_out->qhead != 0)
|
||||
cinfo.bytes += dmap_out->bytes_in_use; /* Pointer wrap not handled yet */
|
||||
cinfo.blocks = dmap_out->qlen;
|
||||
cinfo.bytes += cinfo.ptr;
|
||||
if (dmap_out->mapping_flags & DMA_MAP_MAPPED)
|
||||
dmap_out->qlen = 0; /* Reset interrupt counter */
|
||||
spin_unlock_irqrestore(&dmap_out->lock,flags);
|
||||
if (copy_to_user(arg, &cinfo, sizeof(cinfo)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case SNDCTL_DSP_GETODELAY:
|
||||
if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
|
||||
return -EINVAL;
|
||||
if (!(dmap_out->flags & DMA_ALLOC_DONE))
|
||||
{
|
||||
ret=0;
|
||||
break;
|
||||
}
|
||||
spin_lock_irqsave(&dmap_out->lock,flags);
|
||||
/* Compute number of bytes that have been played */
|
||||
count = DMAbuf_get_buffer_pointer (dev, dmap_out, DMODE_OUTPUT);
|
||||
if (count < dmap_out->fragment_size && dmap_out->qhead != 0)
|
||||
count += dmap_out->bytes_in_use; /* Pointer wrap not handled yet */
|
||||
count += dmap_out->byte_counter;
|
||||
/* Subtract current count from the number of bytes written by app */
|
||||
count = dmap_out->user_counter - count;
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
spin_unlock_irqrestore(&dmap_out->lock,flags);
|
||||
ret = count;
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_POST:
|
||||
if (audio_devs[dev]->dmap_out->qlen > 0)
|
||||
if (!(audio_devs[dev]->dmap_out->flags & DMA_ACTIVE))
|
||||
DMAbuf_launch_output(dev, audio_devs[dev]->dmap_out);
|
||||
return 0;
|
||||
|
||||
case SNDCTL_DSP_GETBLKSIZE:
|
||||
dmap = dmap_out;
|
||||
if (audio_devs[dev]->open_mode & OPEN_WRITE)
|
||||
reorganize_buffers(dev, dmap_out, (audio_devs[dev]->open_mode == OPEN_READ));
|
||||
if (audio_devs[dev]->open_mode == OPEN_READ ||
|
||||
(audio_devs[dev]->flags & DMA_DUPLEX &&
|
||||
audio_devs[dev]->open_mode & OPEN_READ))
|
||||
reorganize_buffers(dev, dmap_in, (audio_devs[dev]->open_mode == OPEN_READ));
|
||||
if (audio_devs[dev]->open_mode == OPEN_READ)
|
||||
dmap = dmap_in;
|
||||
ret = dmap->fragment_size;
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_SETFRAGMENT:
|
||||
ret = 0;
|
||||
if (get_user(fact, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
if (audio_devs[dev]->open_mode & OPEN_WRITE)
|
||||
ret = dma_set_fragment(dev, dmap_out, fact);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (audio_devs[dev]->open_mode == OPEN_READ ||
|
||||
(audio_devs[dev]->flags & DMA_DUPLEX &&
|
||||
audio_devs[dev]->open_mode & OPEN_READ))
|
||||
ret = dma_set_fragment(dev, dmap_in, fact);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!arg) /* don't know what this is good for, but preserve old semantics */
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!audio_devs[dev]->d->ioctl)
|
||||
return -EINVAL;
|
||||
return audio_devs[dev]->d->ioctl(dev, cmd, arg);
|
||||
}
|
||||
return put_user(ret, (int __user *)arg);
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main( int argc, const char * argv [] )
|
||||
{
|
||||
const char * varname;
|
||||
int i = 0;
|
||||
int c;
|
||||
int id = 0;
|
||||
|
||||
if(argv[1] && strcmp(argv[1],"-i")==0)
|
||||
{
|
||||
argv++;
|
||||
argc--;
|
||||
id=1;
|
||||
}
|
||||
|
||||
if(argc==1)
|
||||
{
|
||||
fprintf(stderr, "bin2hex: [-i] firmware\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
varname = argv[1];
|
||||
printf( "/* automatically generated by bin2hex */\n" );
|
||||
printf( "static unsigned char %s [] %s =\n{\n", varname , id?"__initdata":"");
|
||||
|
||||
while ( ( c = getchar( ) ) != EOF )
|
||||
{
|
||||
if ( i != 0 && i % 10 == 0 )
|
||||
printf( "\n" );
|
||||
printf( "0x%02lx,", c & 0xFFl );
|
||||
i++;
|
||||
}
|
||||
|
||||
printf( "};\nstatic int %sLen = %d;\n", varname, i );
|
||||
return 0;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
/*
|
||||
* Definitions for various on board processors on the sound cards. For
|
||||
* example DSP processors.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Coprocessor access types
|
||||
*/
|
||||
#define COPR_CUSTOM 0x0001 /* Custom applications */
|
||||
#define COPR_MIDI 0x0002 /* MIDI (MPU-401) emulation */
|
||||
#define COPR_PCM 0x0004 /* Digitized voice applications */
|
||||
#define COPR_SYNTH 0x0008 /* Music synthesis */
|
|
@ -1,256 +0,0 @@
|
|||
/*
|
||||
* sound/oss/dev_table.c
|
||||
*
|
||||
* Device call tables.
|
||||
*
|
||||
*
|
||||
* Copyright (C) by Hannu Savolainen 1993-1997
|
||||
*
|
||||
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
|
||||
* Version 2 (June 1991). See the "COPYING" file distributed with this software
|
||||
* for more info.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
#include "sound_config.h"
|
||||
|
||||
struct audio_operations *audio_devs[MAX_AUDIO_DEV];
|
||||
EXPORT_SYMBOL(audio_devs);
|
||||
|
||||
int num_audiodevs;
|
||||
EXPORT_SYMBOL(num_audiodevs);
|
||||
|
||||
struct mixer_operations *mixer_devs[MAX_MIXER_DEV];
|
||||
EXPORT_SYMBOL(mixer_devs);
|
||||
|
||||
int num_mixers;
|
||||
EXPORT_SYMBOL(num_mixers);
|
||||
|
||||
struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV];
|
||||
EXPORT_SYMBOL(synth_devs);
|
||||
|
||||
int num_synths;
|
||||
|
||||
struct midi_operations *midi_devs[MAX_MIDI_DEV];
|
||||
EXPORT_SYMBOL(midi_devs);
|
||||
|
||||
int num_midis;
|
||||
EXPORT_SYMBOL(num_midis);
|
||||
|
||||
struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = {
|
||||
&default_sound_timer, NULL
|
||||
};
|
||||
EXPORT_SYMBOL(sound_timer_devs);
|
||||
|
||||
int num_sound_timers = 1;
|
||||
|
||||
|
||||
static int sound_alloc_audiodev(void);
|
||||
|
||||
int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver,
|
||||
int driver_size, int flags, unsigned int format_mask,
|
||||
void *devc, int dma1, int dma2)
|
||||
{
|
||||
struct audio_driver *d;
|
||||
struct audio_operations *op;
|
||||
int num;
|
||||
|
||||
if (vers != AUDIO_DRIVER_VERSION || driver_size > sizeof(struct audio_driver)) {
|
||||
printk(KERN_ERR "Sound: Incompatible audio driver for %s\n", name);
|
||||
return -EINVAL;
|
||||
}
|
||||
num = sound_alloc_audiodev();
|
||||
|
||||
if (num == -1) {
|
||||
printk(KERN_ERR "sound: Too many audio drivers\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
d = (struct audio_driver *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_driver)));
|
||||
sound_nblocks++;
|
||||
if (sound_nblocks >= MAX_MEM_BLOCKS)
|
||||
sound_nblocks = MAX_MEM_BLOCKS - 1;
|
||||
|
||||
op = (struct audio_operations *) (sound_mem_blocks[sound_nblocks] = vzalloc(sizeof(struct audio_operations)));
|
||||
sound_nblocks++;
|
||||
if (sound_nblocks >= MAX_MEM_BLOCKS)
|
||||
sound_nblocks = MAX_MEM_BLOCKS - 1;
|
||||
|
||||
if (d == NULL || op == NULL) {
|
||||
printk(KERN_ERR "Sound: Can't allocate driver for (%s)\n", name);
|
||||
sound_unload_audiodev(num);
|
||||
return -ENOMEM;
|
||||
}
|
||||
init_waitqueue_head(&op->in_sleeper);
|
||||
init_waitqueue_head(&op->out_sleeper);
|
||||
init_waitqueue_head(&op->poll_sleeper);
|
||||
if (driver_size < sizeof(struct audio_driver))
|
||||
memset((char *) d, 0, sizeof(struct audio_driver));
|
||||
|
||||
memcpy((char *) d, (char *) driver, driver_size);
|
||||
|
||||
op->d = d;
|
||||
strlcpy(op->name, name, sizeof(op->name));
|
||||
op->flags = flags;
|
||||
op->format_mask = format_mask;
|
||||
op->devc = devc;
|
||||
|
||||
/*
|
||||
* Hardcoded defaults
|
||||
*/
|
||||
audio_devs[num] = op;
|
||||
|
||||
DMAbuf_init(num, dma1, dma2);
|
||||
|
||||
audio_init_devices();
|
||||
return num;
|
||||
}
|
||||
EXPORT_SYMBOL(sound_install_audiodrv);
|
||||
|
||||
int sound_install_mixer(int vers, char *name, struct mixer_operations *driver,
|
||||
int driver_size, void *devc)
|
||||
{
|
||||
struct mixer_operations *op;
|
||||
|
||||
int n = sound_alloc_mixerdev();
|
||||
|
||||
if (n == -1) {
|
||||
printk(KERN_ERR "Sound: Too many mixer drivers\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (vers != MIXER_DRIVER_VERSION ||
|
||||
driver_size > sizeof(struct mixer_operations)) {
|
||||
printk(KERN_ERR "Sound: Incompatible mixer driver for %s\n", name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* FIXME: This leaks a mixer_operations struct every time its called
|
||||
until you unload sound! */
|
||||
|
||||
op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vzalloc(sizeof(struct mixer_operations)));
|
||||
sound_nblocks++;
|
||||
if (sound_nblocks >= MAX_MEM_BLOCKS)
|
||||
sound_nblocks = MAX_MEM_BLOCKS - 1;
|
||||
|
||||
if (op == NULL) {
|
||||
printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy((char *) op, (char *) driver, driver_size);
|
||||
|
||||
strlcpy(op->name, name, sizeof(op->name));
|
||||
op->devc = devc;
|
||||
|
||||
mixer_devs[n] = op;
|
||||
return n;
|
||||
}
|
||||
EXPORT_SYMBOL(sound_install_mixer);
|
||||
|
||||
void sound_unload_audiodev(int dev)
|
||||
{
|
||||
if (dev != -1) {
|
||||
DMAbuf_deinit(dev);
|
||||
audio_devs[dev] = NULL;
|
||||
unregister_sound_dsp((dev<<4)+3);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(sound_unload_audiodev);
|
||||
|
||||
static int sound_alloc_audiodev(void)
|
||||
{
|
||||
int i = register_sound_dsp(&oss_sound_fops, -1);
|
||||
if(i==-1)
|
||||
return i;
|
||||
i>>=4;
|
||||
if(i>=num_audiodevs)
|
||||
num_audiodevs = i + 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
int sound_alloc_mididev(void)
|
||||
{
|
||||
int i = register_sound_midi(&oss_sound_fops, -1);
|
||||
if(i==-1)
|
||||
return i;
|
||||
i>>=4;
|
||||
if(i>=num_midis)
|
||||
num_midis = i + 1;
|
||||
return i;
|
||||
}
|
||||
EXPORT_SYMBOL(sound_alloc_mididev);
|
||||
|
||||
int sound_alloc_synthdev(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_SYNTH_DEV; i++) {
|
||||
if (synth_devs[i] == NULL) {
|
||||
if (i >= num_synths)
|
||||
num_synths++;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL(sound_alloc_synthdev);
|
||||
|
||||
int sound_alloc_mixerdev(void)
|
||||
{
|
||||
int i = register_sound_mixer(&oss_sound_fops, -1);
|
||||
if(i==-1)
|
||||
return -1;
|
||||
i>>=4;
|
||||
if(i>=num_mixers)
|
||||
num_mixers = i + 1;
|
||||
return i;
|
||||
}
|
||||
EXPORT_SYMBOL(sound_alloc_mixerdev);
|
||||
|
||||
int sound_alloc_timerdev(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_TIMER_DEV; i++) {
|
||||
if (sound_timer_devs[i] == NULL) {
|
||||
if (i >= num_sound_timers)
|
||||
num_sound_timers++;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL(sound_alloc_timerdev);
|
||||
|
||||
void sound_unload_mixerdev(int dev)
|
||||
{
|
||||
if (dev != -1) {
|
||||
mixer_devs[dev] = NULL;
|
||||
unregister_sound_mixer(dev<<4);
|
||||
num_mixers--;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(sound_unload_mixerdev);
|
||||
|
||||
void sound_unload_mididev(int dev)
|
||||
{
|
||||
if (dev != -1) {
|
||||
midi_devs[dev] = NULL;
|
||||
unregister_sound_midi((dev<<4)+2);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(sound_unload_mididev);
|
||||
|
||||
void sound_unload_synthdev(int dev)
|
||||
{
|
||||
if (dev != -1)
|
||||
synth_devs[dev] = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(sound_unload_synthdev);
|
||||
|
||||
void sound_unload_timerdev(int dev)
|
||||
{
|
||||
if (dev != -1)
|
||||
sound_timer_devs[dev] = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(sound_unload_timerdev);
|
||||
|
|
@ -1,390 +0,0 @@
|
|||
/*
|
||||
* dev_table.h
|
||||
*
|
||||
* Global definitions for device call tables
|
||||
*
|
||||
*
|
||||
* Copyright (C) by Hannu Savolainen 1993-1997
|
||||
*
|
||||
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
|
||||
* Version 2 (June 1991). See the "COPYING" file distributed with this software
|
||||
* for more info.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _DEV_TABLE_H_
|
||||
#define _DEV_TABLE_H_
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
/*
|
||||
* Sound card numbers 27 to 999. (1 to 26 are defined in soundcard.h)
|
||||
* Numbers 1000 to N are reserved for driver's internal use.
|
||||
*/
|
||||
|
||||
#define SNDCARD_DESKPROXL 27 /* Compaq Deskpro XL */
|
||||
#define SNDCARD_VIDC 28 /* ARMs VIDC */
|
||||
#define SNDCARD_SBPNP 29
|
||||
#define SNDCARD_SOFTOSS 36
|
||||
#define SNDCARD_VMIDI 37
|
||||
#define SNDCARD_OPL3SA1 38 /* Note: clash in msnd.h */
|
||||
#define SNDCARD_OPL3SA1_SB 39
|
||||
#define SNDCARD_OPL3SA1_MPU 40
|
||||
#define SNDCARD_WAVEFRONT 41
|
||||
#define SNDCARD_OPL3SA2 42
|
||||
#define SNDCARD_OPL3SA2_MPU 43
|
||||
#define SNDCARD_WAVEARTIST 44 /* Waveartist */
|
||||
#define SNDCARD_OPL3SA2_MSS 45 /* Originally missed */
|
||||
#define SNDCARD_AD1816 88
|
||||
|
||||
/*
|
||||
* NOTE! NOTE! NOTE! NOTE!
|
||||
*
|
||||
* If you modify this file, please check the dev_table.c also.
|
||||
*
|
||||
* NOTE! NOTE! NOTE! NOTE!
|
||||
*/
|
||||
|
||||
struct driver_info
|
||||
{
|
||||
char *driver_id;
|
||||
int card_subtype; /* Driver specific. Usually 0 */
|
||||
int card_type; /* From soundcard.h */
|
||||
char *name;
|
||||
void (*attach) (struct address_info *hw_config);
|
||||
int (*probe) (struct address_info *hw_config);
|
||||
void (*unload) (struct address_info *hw_config);
|
||||
};
|
||||
|
||||
struct card_info
|
||||
{
|
||||
int card_type; /* Link (search key) to the driver list */
|
||||
struct address_info config;
|
||||
int enabled;
|
||||
void *for_driver_use;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Device specific parameters (used only by dmabuf.c)
|
||||
*/
|
||||
#define MAX_SUB_BUFFERS (32*MAX_REALTIME_FACTOR)
|
||||
|
||||
#define DMODE_NONE 0
|
||||
#define DMODE_OUTPUT PCM_ENABLE_OUTPUT
|
||||
#define DMODE_INPUT PCM_ENABLE_INPUT
|
||||
|
||||
struct dma_buffparms
|
||||
{
|
||||
int dma_mode; /* DMODE_INPUT, DMODE_OUTPUT or DMODE_NONE */
|
||||
int closing;
|
||||
|
||||
/*
|
||||
* Pointers to raw buffers
|
||||
*/
|
||||
|
||||
char *raw_buf;
|
||||
unsigned long raw_buf_phys;
|
||||
int buffsize;
|
||||
|
||||
/*
|
||||
* Device state tables
|
||||
*/
|
||||
|
||||
unsigned long flags;
|
||||
#define DMA_BUSY 0x00000001
|
||||
#define DMA_RESTART 0x00000002
|
||||
#define DMA_ACTIVE 0x00000004
|
||||
#define DMA_STARTED 0x00000008
|
||||
#define DMA_EMPTY 0x00000010
|
||||
#define DMA_ALLOC_DONE 0x00000020
|
||||
#define DMA_SYNCING 0x00000040
|
||||
#define DMA_DIRTY 0x00000080
|
||||
#define DMA_POST 0x00000100
|
||||
#define DMA_NODMA 0x00000200
|
||||
#define DMA_NOTIMEOUT 0x00000400
|
||||
|
||||
int open_mode;
|
||||
|
||||
/*
|
||||
* Queue parameters.
|
||||
*/
|
||||
int qlen;
|
||||
int qhead;
|
||||
int qtail;
|
||||
spinlock_t lock;
|
||||
|
||||
int cfrag; /* Current incomplete fragment (write) */
|
||||
|
||||
int nbufs;
|
||||
int counts[MAX_SUB_BUFFERS];
|
||||
int subdivision;
|
||||
|
||||
int fragment_size;
|
||||
int needs_reorg;
|
||||
int max_fragments;
|
||||
|
||||
int bytes_in_use;
|
||||
|
||||
int underrun_count;
|
||||
unsigned long byte_counter;
|
||||
unsigned long user_counter;
|
||||
unsigned long max_byte_counter;
|
||||
int data_rate; /* Bytes/second */
|
||||
|
||||
int mapping_flags;
|
||||
#define DMA_MAP_MAPPED 0x00000001
|
||||
char neutral_byte;
|
||||
int dma; /* DMA channel */
|
||||
|
||||
int applic_profile; /* Application profile (APF_*) */
|
||||
/* Interrupt callback stuff */
|
||||
void (*audio_callback) (int dev, int parm);
|
||||
int callback_parm;
|
||||
|
||||
int buf_flags[MAX_SUB_BUFFERS];
|
||||
#define BUFF_EOF 0x00000001 /* Increment eof count */
|
||||
#define BUFF_DIRTY 0x00000002 /* Buffer written */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure for use with various microcontrollers and DSP processors
|
||||
* in the recent sound cards.
|
||||
*/
|
||||
typedef struct coproc_operations
|
||||
{
|
||||
char name[64];
|
||||
struct module *owner;
|
||||
int (*open) (void *devc, int sub_device);
|
||||
void (*close) (void *devc, int sub_device);
|
||||
int (*ioctl) (void *devc, unsigned int cmd, void __user * arg, int local);
|
||||
void (*reset) (void *devc);
|
||||
|
||||
void *devc; /* Driver specific info */
|
||||
} coproc_operations;
|
||||
|
||||
struct audio_driver
|
||||
{
|
||||
struct module *owner;
|
||||
int (*open) (int dev, int mode);
|
||||
void (*close) (int dev);
|
||||
void (*output_block) (int dev, unsigned long buf,
|
||||
int count, int intrflag);
|
||||
void (*start_input) (int dev, unsigned long buf,
|
||||
int count, int intrflag);
|
||||
int (*ioctl) (int dev, unsigned int cmd, void __user * arg);
|
||||
int (*prepare_for_input) (int dev, int bufsize, int nbufs);
|
||||
int (*prepare_for_output) (int dev, int bufsize, int nbufs);
|
||||
void (*halt_io) (int dev);
|
||||
int (*local_qlen)(int dev);
|
||||
void (*copy_user) (int dev,
|
||||
char *localbuf, int localoffs,
|
||||
const char __user *userbuf, int useroffs,
|
||||
int max_in, int max_out,
|
||||
int *used, int *returned,
|
||||
int len);
|
||||
void (*halt_input) (int dev);
|
||||
void (*halt_output) (int dev);
|
||||
void (*trigger) (int dev, int bits);
|
||||
int (*set_speed)(int dev, int speed);
|
||||
unsigned int (*set_bits)(int dev, unsigned int bits);
|
||||
short (*set_channels)(int dev, short channels);
|
||||
void (*postprocess_write)(int dev); /* Device spesific postprocessing for written data */
|
||||
void (*preprocess_read)(int dev); /* Device spesific preprocessing for read data */
|
||||
void (*mmap)(int dev);
|
||||
};
|
||||
|
||||
struct audio_operations
|
||||
{
|
||||
char name[128];
|
||||
int flags;
|
||||
#define NOTHING_SPECIAL 0x00
|
||||
#define NEEDS_RESTART 0x01
|
||||
#define DMA_AUTOMODE 0x02
|
||||
#define DMA_DUPLEX 0x04
|
||||
#define DMA_PSEUDO_AUTOMODE 0x08
|
||||
#define DMA_HARDSTOP 0x10
|
||||
#define DMA_EXACT 0x40
|
||||
#define DMA_NORESET 0x80
|
||||
int format_mask; /* Bitmask for supported audio formats */
|
||||
void *devc; /* Driver specific info */
|
||||
struct audio_driver *d;
|
||||
void *portc; /* Driver specific info */
|
||||
struct dma_buffparms *dmap_in, *dmap_out;
|
||||
struct coproc_operations *coproc;
|
||||
int mixer_dev;
|
||||
int enable_bits;
|
||||
int open_mode;
|
||||
int go;
|
||||
int min_fragment; /* 0 == unlimited */
|
||||
int max_fragment; /* 0 == unlimited */
|
||||
int parent_dev; /* 0 -> no parent, 1 to n -> parent=parent_dev+1 */
|
||||
|
||||
/* fields formerly in dmabuf.c */
|
||||
wait_queue_head_t in_sleeper;
|
||||
wait_queue_head_t out_sleeper;
|
||||
wait_queue_head_t poll_sleeper;
|
||||
|
||||
/* fields formerly in audio.c */
|
||||
int audio_mode;
|
||||
|
||||
#define AM_NONE 0
|
||||
#define AM_WRITE OPEN_WRITE
|
||||
#define AM_READ OPEN_READ
|
||||
|
||||
int local_format;
|
||||
int audio_format;
|
||||
int local_conversion;
|
||||
#define CNV_MU_LAW 0x00000001
|
||||
|
||||
/* large structures at the end to keep offsets small */
|
||||
struct dma_buffparms dmaps[2];
|
||||
};
|
||||
|
||||
int *load_mixer_volumes(char *name, int *levels, int present);
|
||||
|
||||
struct mixer_operations
|
||||
{
|
||||
struct module *owner;
|
||||
char id[16];
|
||||
char name[64];
|
||||
int (*ioctl) (int dev, unsigned int cmd, void __user * arg);
|
||||
|
||||
void *devc;
|
||||
int modify_counter;
|
||||
};
|
||||
|
||||
struct synth_operations
|
||||
{
|
||||
struct module *owner;
|
||||
char *id; /* Unique identifier (ASCII) max 29 char */
|
||||
struct synth_info *info;
|
||||
int midi_dev;
|
||||
int synth_type;
|
||||
int synth_subtype;
|
||||
|
||||
int (*open) (int dev, int mode);
|
||||
void (*close) (int dev);
|
||||
int (*ioctl) (int dev, unsigned int cmd, void __user * arg);
|
||||
int (*kill_note) (int dev, int voice, int note, int velocity);
|
||||
int (*start_note) (int dev, int voice, int note, int velocity);
|
||||
int (*set_instr) (int dev, int voice, int instr);
|
||||
void (*reset) (int dev);
|
||||
void (*hw_control) (int dev, unsigned char *event);
|
||||
int (*load_patch) (int dev, int format, const char __user *addr,
|
||||
int count, int pmgr_flag);
|
||||
void (*aftertouch) (int dev, int voice, int pressure);
|
||||
void (*controller) (int dev, int voice, int ctrl_num, int value);
|
||||
void (*panning) (int dev, int voice, int value);
|
||||
void (*volume_method) (int dev, int mode);
|
||||
void (*bender) (int dev, int chn, int value);
|
||||
int (*alloc_voice) (int dev, int chn, int note, struct voice_alloc_info *alloc);
|
||||
void (*setup_voice) (int dev, int voice, int chn);
|
||||
int (*send_sysex)(int dev, unsigned char *bytes, int len);
|
||||
|
||||
struct voice_alloc_info alloc;
|
||||
struct channel_info chn_info[16];
|
||||
int emulation;
|
||||
#define EMU_GM 1 /* General MIDI */
|
||||
#define EMU_XG 2 /* Yamaha XG */
|
||||
#define MAX_SYSEX_BUF 64
|
||||
unsigned char sysex_buf[MAX_SYSEX_BUF];
|
||||
int sysex_ptr;
|
||||
};
|
||||
|
||||
struct midi_input_info
|
||||
{
|
||||
/* MIDI input scanner variables */
|
||||
#define MI_MAX 10
|
||||
volatile int m_busy;
|
||||
unsigned char m_buf[MI_MAX];
|
||||
unsigned char m_prev_status; /* For running status */
|
||||
int m_ptr;
|
||||
#define MST_INIT 0
|
||||
#define MST_DATA 1
|
||||
#define MST_SYSEX 2
|
||||
int m_state;
|
||||
int m_left;
|
||||
};
|
||||
|
||||
struct midi_operations
|
||||
{
|
||||
struct module *owner;
|
||||
struct midi_info info;
|
||||
struct synth_operations *converter;
|
||||
struct midi_input_info in_info;
|
||||
int (*open) (int dev, int mode,
|
||||
void (*inputintr)(int dev, unsigned char data),
|
||||
void (*outputintr)(int dev)
|
||||
);
|
||||
void (*close) (int dev);
|
||||
int (*ioctl) (int dev, unsigned int cmd, void __user * arg);
|
||||
int (*outputc) (int dev, unsigned char data);
|
||||
int (*start_read) (int dev);
|
||||
int (*end_read) (int dev);
|
||||
void (*kick)(int dev);
|
||||
int (*command) (int dev, unsigned char *data);
|
||||
int (*buffer_status) (int dev);
|
||||
int (*prefix_cmd) (int dev, unsigned char status);
|
||||
struct coproc_operations *coproc;
|
||||
void *devc;
|
||||
};
|
||||
|
||||
struct sound_lowlev_timer
|
||||
{
|
||||
int dev;
|
||||
int priority;
|
||||
unsigned int (*tmr_start)(int dev, unsigned int usecs);
|
||||
void (*tmr_disable)(int dev);
|
||||
void (*tmr_restart)(int dev);
|
||||
};
|
||||
|
||||
struct sound_timer_operations
|
||||
{
|
||||
struct module *owner;
|
||||
struct sound_timer_info info;
|
||||
int priority;
|
||||
int devlink;
|
||||
int (*open)(int dev, int mode);
|
||||
void (*close)(int dev);
|
||||
int (*event)(int dev, unsigned char *ev);
|
||||
unsigned long (*get_time)(int dev);
|
||||
int (*ioctl) (int dev, unsigned int cmd, void __user * arg);
|
||||
void (*arm_timer)(int dev, long time);
|
||||
};
|
||||
|
||||
extern struct sound_timer_operations default_sound_timer;
|
||||
|
||||
extern struct audio_operations *audio_devs[MAX_AUDIO_DEV];
|
||||
extern int num_audiodevs;
|
||||
extern struct mixer_operations *mixer_devs[MAX_MIXER_DEV];
|
||||
extern int num_mixers;
|
||||
extern struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV];
|
||||
extern int num_synths;
|
||||
extern struct midi_operations *midi_devs[MAX_MIDI_DEV];
|
||||
extern int num_midis;
|
||||
extern struct sound_timer_operations * sound_timer_devs[MAX_TIMER_DEV];
|
||||
extern int num_sound_timers;
|
||||
|
||||
extern int sound_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc *info);
|
||||
void sound_timer_init (struct sound_lowlev_timer *t, char *name);
|
||||
void sound_dma_intr (int dev, struct dma_buffparms *dmap, int chan);
|
||||
|
||||
#define AUDIO_DRIVER_VERSION 2
|
||||
#define MIXER_DRIVER_VERSION 2
|
||||
int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver,
|
||||
int driver_size, int flags, unsigned int format_mask,
|
||||
void *devc, int dma1, int dma2);
|
||||
int sound_install_mixer(int vers, char *name, struct mixer_operations *driver,
|
||||
int driver_size, void *devc);
|
||||
|
||||
void sound_unload_audiodev(int dev);
|
||||
void sound_unload_mixerdev(int dev);
|
||||
void sound_unload_mididev(int dev);
|
||||
void sound_unload_synthdev(int dev);
|
||||
void sound_unload_timerdev(int dev);
|
||||
int sound_alloc_mixerdev(void);
|
||||
int sound_alloc_timerdev(void);
|
||||
int sound_alloc_synthdev(void);
|
||||
int sound_alloc_mididev(void);
|
||||
#endif /* _DEV_TABLE_H_ */
|
||||
|
1268
sound/oss/dmabuf.c
1268
sound/oss/dmabuf.c
File diff suppressed because it is too large
Load diff
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* hex2hex reads stdin in Intel HEX format and produces an
|
||||
* (unsigned char) array which contains the bytes and writes it
|
||||
* to stdout using C syntax
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ABANDON(why) { fprintf(stderr, "%s\n", why); exit(1); }
|
||||
#define MAX_SIZE (256*1024)
|
||||
unsigned char buf[MAX_SIZE];
|
||||
|
||||
static int loadhex(FILE *inf, unsigned char *buf)
|
||||
{
|
||||
int l=0, c, i;
|
||||
|
||||
while ((c=getc(inf))!=EOF)
|
||||
{
|
||||
if (c == ':') /* Sync with beginning of line */
|
||||
{
|
||||
int n, check;
|
||||
unsigned char sum;
|
||||
int addr;
|
||||
int linetype;
|
||||
|
||||
if (fscanf(inf, "%02x", &n) != 1)
|
||||
ABANDON("File format error");
|
||||
sum = n;
|
||||
|
||||
if (fscanf(inf, "%04x", &addr) != 1)
|
||||
ABANDON("File format error");
|
||||
sum += addr/256;
|
||||
sum += addr%256;
|
||||
|
||||
if (fscanf(inf, "%02x", &linetype) != 1)
|
||||
ABANDON("File format error");
|
||||
sum += linetype;
|
||||
|
||||
if (linetype != 0)
|
||||
continue;
|
||||
|
||||
for (i=0;i<n;i++)
|
||||
{
|
||||
if (fscanf(inf, "%02x", &c) != 1)
|
||||
ABANDON("File format error");
|
||||
if (addr >= MAX_SIZE)
|
||||
ABANDON("File too large");
|
||||
buf[addr++] = c;
|
||||
if (addr > l)
|
||||
l = addr;
|
||||
sum += c;
|
||||
}
|
||||
|
||||
if (fscanf(inf, "%02x", &check) != 1)
|
||||
ABANDON("File format error");
|
||||
|
||||
sum = ~sum + 1;
|
||||
if (check != sum)
|
||||
ABANDON("Line checksum error");
|
||||
}
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
int main( int argc, const char * argv [] )
|
||||
{
|
||||
const char * varline;
|
||||
int i,l;
|
||||
int id=0;
|
||||
|
||||
if(argv[1] && strcmp(argv[1], "-i")==0)
|
||||
{
|
||||
argv++;
|
||||
argc--;
|
||||
id=1;
|
||||
}
|
||||
if(argv[1]==NULL)
|
||||
{
|
||||
fprintf(stderr,"hex2hex: [-i] filename\n");
|
||||
exit(1);
|
||||
}
|
||||
varline = argv[1];
|
||||
l = loadhex(stdin, buf);
|
||||
|
||||
printf("/*\n *\t Computer generated file. Do not edit.\n */\n");
|
||||
printf("static int %s_len = %d;\n", varline, l);
|
||||
printf("static unsigned char %s[] %s = {\n", varline, id?"__initdata":"");
|
||||
|
||||
for (i=0;i<l;i++)
|
||||
{
|
||||
if (i) printf(",");
|
||||
if (i && !(i % 16)) printf("\n");
|
||||
printf("0x%02x", buf[i]);
|
||||
}
|
||||
|
||||
printf("\n};\n\n");
|
||||
return 0;
|
||||
}
|
|
@ -1,229 +0,0 @@
|
|||
/*
|
||||
* Initialisation code for Cyrix/NatSemi VSA1 softaudio
|
||||
*
|
||||
* (C) Copyright 2003 Red Hat Inc <alan@lxorguk.ukuu.org.uk>
|
||||
*
|
||||
* XpressAudio(tm) is used on the Cyrix MediaGX (now NatSemi Geode) systems.
|
||||
* The older version (VSA1) provides fairly good soundblaster emulation
|
||||
* although there are a couple of bugs: large DMA buffers break record,
|
||||
* and the MPU event handling seems suspect. VSA2 allows the native driver
|
||||
* to control the AC97 audio engine directly and requires a different driver.
|
||||
*
|
||||
* Thanks to National Semiconductor for providing the needed information
|
||||
* on the XpressAudio(tm) internals.
|
||||
*
|
||||
* 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, 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.
|
||||
*
|
||||
* TO DO:
|
||||
* Investigate whether we can portably support Cognac (5520) in the
|
||||
* same manner.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "sound_config.h"
|
||||
|
||||
#include "sb.h"
|
||||
|
||||
/*
|
||||
* Read a soundblaster compatible mixer register.
|
||||
* In this case we are actually reading an SMI trap
|
||||
* not real hardware.
|
||||
*/
|
||||
|
||||
static u8 mixer_read(unsigned long io, u8 reg)
|
||||
{
|
||||
outb(reg, io + 4);
|
||||
udelay(20);
|
||||
reg = inb(io + 5);
|
||||
udelay(20);
|
||||
return reg;
|
||||
}
|
||||
|
||||
static int probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
struct address_info *hw_config;
|
||||
unsigned long base;
|
||||
void __iomem *mem;
|
||||
unsigned long io;
|
||||
u16 map;
|
||||
u8 irq, dma8, dma16;
|
||||
int oldquiet;
|
||||
extern int sb_be_quiet;
|
||||
|
||||
base = pci_resource_start(pdev, 0);
|
||||
if(base == 0UL)
|
||||
return 1;
|
||||
|
||||
mem = ioremap(base, 128);
|
||||
if (!mem)
|
||||
return 1;
|
||||
map = readw(mem + 0x18); /* Read the SMI enables */
|
||||
iounmap(mem);
|
||||
|
||||
/* Map bits
|
||||
0:1 * 0x20 + 0x200 = sb base
|
||||
2 sb enable
|
||||
3 adlib enable
|
||||
5 MPU enable 0x330
|
||||
6 MPU enable 0x300
|
||||
|
||||
The other bits may be used internally so must be masked */
|
||||
|
||||
io = 0x220 + 0x20 * (map & 3);
|
||||
|
||||
if(map & (1<<2))
|
||||
printk(KERN_INFO "kahlua: XpressAudio at 0x%lx\n", io);
|
||||
else
|
||||
return 1;
|
||||
|
||||
if(map & (1<<5))
|
||||
printk(KERN_INFO "kahlua: MPU at 0x300\n");
|
||||
else if(map & (1<<6))
|
||||
printk(KERN_INFO "kahlua: MPU at 0x330\n");
|
||||
|
||||
irq = mixer_read(io, 0x80) & 0x0F;
|
||||
dma8 = mixer_read(io, 0x81);
|
||||
|
||||
// printk("IRQ=%x MAP=%x DMA=%x\n", irq, map, dma8);
|
||||
|
||||
if(dma8 & 0x20)
|
||||
dma16 = 5;
|
||||
else if(dma8 & 0x40)
|
||||
dma16 = 6;
|
||||
else if(dma8 & 0x80)
|
||||
dma16 = 7;
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "kahlua: No 16bit DMA enabled.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(dma8 & 0x01)
|
||||
dma8 = 0;
|
||||
else if(dma8 & 0x02)
|
||||
dma8 = 1;
|
||||
else if(dma8 & 0x08)
|
||||
dma8 = 3;
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "kahlua: No 8bit DMA enabled.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(irq & 1)
|
||||
irq = 9;
|
||||
else if(irq & 2)
|
||||
irq = 5;
|
||||
else if(irq & 4)
|
||||
irq = 7;
|
||||
else if(irq & 8)
|
||||
irq = 10;
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "kahlua: SB IRQ not set.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "kahlua: XpressAudio on IRQ %d, DMA %d, %d\n",
|
||||
irq, dma8, dma16);
|
||||
|
||||
hw_config = kzalloc(sizeof(struct address_info), GFP_KERNEL);
|
||||
if(hw_config == NULL)
|
||||
{
|
||||
printk(KERN_ERR "kahlua: out of memory.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pci_set_drvdata(pdev, hw_config);
|
||||
|
||||
hw_config->io_base = io;
|
||||
hw_config->irq = irq;
|
||||
hw_config->dma = dma8;
|
||||
hw_config->dma2 = dma16;
|
||||
hw_config->name = "Cyrix XpressAudio";
|
||||
hw_config->driver_use_1 = SB_NO_MIDI | SB_PCI_IRQ;
|
||||
|
||||
if (!request_region(io, 16, "soundblaster"))
|
||||
goto err_out_free;
|
||||
|
||||
if(sb_dsp_detect(hw_config, 0, 0, NULL)==0)
|
||||
{
|
||||
printk(KERN_ERR "kahlua: audio not responding.\n");
|
||||
release_region(io, 16);
|
||||
goto err_out_free;
|
||||
}
|
||||
|
||||
oldquiet = sb_be_quiet;
|
||||
sb_be_quiet = 1;
|
||||
if(sb_dsp_init(hw_config, THIS_MODULE))
|
||||
{
|
||||
sb_be_quiet = oldquiet;
|
||||
goto err_out_free;
|
||||
}
|
||||
sb_be_quiet = oldquiet;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_free:
|
||||
kfree(hw_config);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void remove_one(struct pci_dev *pdev)
|
||||
{
|
||||
struct address_info *hw_config = pci_get_drvdata(pdev);
|
||||
sb_dsp_unload(hw_config, 0);
|
||||
kfree(hw_config);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Alan Cox");
|
||||
MODULE_DESCRIPTION("Kahlua VSA1 PCI Audio");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/*
|
||||
* 5530 only. The 5510/5520 decode is different.
|
||||
*/
|
||||
|
||||
static const struct pci_device_id id_tbl[] = {
|
||||
{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO), 0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, id_tbl);
|
||||
|
||||
static struct pci_driver kahlua_driver = {
|
||||
.name = "kahlua",
|
||||
.id_table = id_tbl,
|
||||
.probe = probe_one,
|
||||
.remove = remove_one,
|
||||
};
|
||||
|
||||
|
||||
static int __init kahlua_init_module(void)
|
||||
{
|
||||
printk(KERN_INFO "Cyrix Kahlua VSA1 XpressAudio support (c) Copyright 2003 Red Hat Inc\n");
|
||||
return pci_register_driver(&kahlua_driver);
|
||||
}
|
||||
|
||||
static void kahlua_cleanup_module(void)
|
||||
{
|
||||
pci_unregister_driver(&kahlua_driver);
|
||||
}
|
||||
|
||||
|
||||
module_init(kahlua_init_module);
|
||||
module_exit(kahlua_cleanup_module);
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
static unsigned char ctrl_def_values[128] =
|
||||
{
|
||||
0x40,0x00,0x40,0x40, 0x40,0x40,0x40,0x7f, /* 0 to 7 */
|
||||
0x40,0x40,0x40,0x7f, 0x40,0x40,0x40,0x40, /* 8 to 15 */
|
||||
0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, /* 16 to 23 */
|
||||
0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, /* 24 to 31 */
|
||||
|
||||
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 32 to 39 */
|
||||
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 40 to 47 */
|
||||
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 48 to 55 */
|
||||
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 56 to 63 */
|
||||
|
||||
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 64 to 71 */
|
||||
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 72 to 79 */
|
||||
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 80 to 87 */
|
||||
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 88 to 95 */
|
||||
|
||||
0x00,0x00,0x7f,0x7f, 0x7f,0x7f,0x00,0x00, /* 96 to 103 */
|
||||
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 104 to 111 */
|
||||
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 112 to 119 */
|
||||
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 120 to 127 */
|
||||
};
|
|
@ -1,712 +0,0 @@
|
|||
/*
|
||||
* sound/oss/midi_synth.c
|
||||
*
|
||||
* High level midi sequencer manager for dumb MIDI interfaces.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) by Hannu Savolainen 1993-1997
|
||||
*
|
||||
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
|
||||
* Version 2 (June 1991). See the "COPYING" file distributed with this software
|
||||
* for more info.
|
||||
*/
|
||||
/*
|
||||
* Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
|
||||
* Andrew Veliath : fixed running status in MIDI input state machine
|
||||
*/
|
||||
#define USE_SEQ_MACROS
|
||||
#define USE_SIMPLE_MACROS
|
||||
|
||||
#include "sound_config.h"
|
||||
|
||||
#define _MIDI_SYNTH_C_
|
||||
|
||||
#include "midi_synth.h"
|
||||
|
||||
static int midi2synth[MAX_MIDI_DEV];
|
||||
static int sysex_state[MAX_MIDI_DEV] =
|
||||
{0};
|
||||
static unsigned char prev_out_status[MAX_MIDI_DEV];
|
||||
|
||||
#define STORE(cmd) \
|
||||
{ \
|
||||
int len; \
|
||||
unsigned char obuf[8]; \
|
||||
cmd; \
|
||||
seq_input_event(obuf, len); \
|
||||
}
|
||||
|
||||
#define _seqbuf obuf
|
||||
#define _seqbufptr 0
|
||||
#define _SEQ_ADVBUF(x) len=x
|
||||
|
||||
void
|
||||
do_midi_msg(int synthno, unsigned char *msg, int mlen)
|
||||
{
|
||||
switch (msg[0] & 0xf0)
|
||||
{
|
||||
case 0x90:
|
||||
if (msg[2] != 0)
|
||||
{
|
||||
STORE(SEQ_START_NOTE(synthno, msg[0] & 0x0f, msg[1], msg[2]));
|
||||
break;
|
||||
}
|
||||
msg[2] = 64;
|
||||
|
||||
case 0x80:
|
||||
STORE(SEQ_STOP_NOTE(synthno, msg[0] & 0x0f, msg[1], msg[2]));
|
||||
break;
|
||||
|
||||
case 0xA0:
|
||||
STORE(SEQ_KEY_PRESSURE(synthno, msg[0] & 0x0f, msg[1], msg[2]));
|
||||
break;
|
||||
|
||||
case 0xB0:
|
||||
STORE(SEQ_CONTROL(synthno, msg[0] & 0x0f,
|
||||
msg[1], msg[2]));
|
||||
break;
|
||||
|
||||
case 0xC0:
|
||||
STORE(SEQ_SET_PATCH(synthno, msg[0] & 0x0f, msg[1]));
|
||||
break;
|
||||
|
||||
case 0xD0:
|
||||
STORE(SEQ_CHN_PRESSURE(synthno, msg[0] & 0x0f, msg[1]));
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
STORE(SEQ_BENDER(synthno, msg[0] & 0x0f,
|
||||
(msg[1] & 0x7f) | ((msg[2] & 0x7f) << 7)));
|
||||
break;
|
||||
|
||||
default:
|
||||
/* printk( "MPU: Unknown midi channel message %02x\n", msg[0]); */
|
||||
;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(do_midi_msg);
|
||||
|
||||
static void
|
||||
midi_outc(int midi_dev, int data)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
for (timeout = 0; timeout < 3200; timeout++)
|
||||
if (midi_devs[midi_dev]->outputc(midi_dev, (unsigned char) (data & 0xff)))
|
||||
{
|
||||
if (data & 0x80) /*
|
||||
* Status byte
|
||||
*/
|
||||
prev_out_status[midi_dev] =
|
||||
(unsigned char) (data & 0xff); /*
|
||||
* Store for running status
|
||||
*/
|
||||
return; /*
|
||||
* Mission complete
|
||||
*/
|
||||
}
|
||||
/*
|
||||
* Sorry! No space on buffers.
|
||||
*/
|
||||
printk("Midi send timed out\n");
|
||||
}
|
||||
|
||||
static int
|
||||
prefix_cmd(int midi_dev, unsigned char status)
|
||||
{
|
||||
if ((char *) midi_devs[midi_dev]->prefix_cmd == NULL)
|
||||
return 1;
|
||||
|
||||
return midi_devs[midi_dev]->prefix_cmd(midi_dev, status);
|
||||
}
|
||||
|
||||
static void
|
||||
midi_synth_input(int orig_dev, unsigned char data)
|
||||
{
|
||||
int dev;
|
||||
struct midi_input_info *inc;
|
||||
|
||||
static unsigned char len_tab[] = /* # of data bytes following a status
|
||||
*/
|
||||
{
|
||||
2, /* 8x */
|
||||
2, /* 9x */
|
||||
2, /* Ax */
|
||||
2, /* Bx */
|
||||
1, /* Cx */
|
||||
1, /* Dx */
|
||||
2, /* Ex */
|
||||
0 /* Fx */
|
||||
};
|
||||
|
||||
if (orig_dev < 0 || orig_dev > num_midis || midi_devs[orig_dev] == NULL)
|
||||
return;
|
||||
|
||||
if (data == 0xfe) /* Ignore active sensing */
|
||||
return;
|
||||
|
||||
dev = midi2synth[orig_dev];
|
||||
inc = &midi_devs[orig_dev]->in_info;
|
||||
|
||||
switch (inc->m_state)
|
||||
{
|
||||
case MST_INIT:
|
||||
if (data & 0x80) /* MIDI status byte */
|
||||
{
|
||||
if ((data & 0xf0) == 0xf0) /* Common message */
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case 0xf0: /* Sysex */
|
||||
inc->m_state = MST_SYSEX;
|
||||
break; /* Sysex */
|
||||
|
||||
case 0xf1: /* MTC quarter frame */
|
||||
case 0xf3: /* Song select */
|
||||
inc->m_state = MST_DATA;
|
||||
inc->m_ptr = 1;
|
||||
inc->m_left = 1;
|
||||
inc->m_buf[0] = data;
|
||||
break;
|
||||
|
||||
case 0xf2: /* Song position pointer */
|
||||
inc->m_state = MST_DATA;
|
||||
inc->m_ptr = 1;
|
||||
inc->m_left = 2;
|
||||
inc->m_buf[0] = data;
|
||||
break;
|
||||
|
||||
default:
|
||||
inc->m_buf[0] = data;
|
||||
inc->m_ptr = 1;
|
||||
do_midi_msg(dev, inc->m_buf, inc->m_ptr);
|
||||
inc->m_ptr = 0;
|
||||
inc->m_left = 0;
|
||||
}
|
||||
} else
|
||||
{
|
||||
inc->m_state = MST_DATA;
|
||||
inc->m_ptr = 1;
|
||||
inc->m_left = len_tab[(data >> 4) - 8];
|
||||
inc->m_buf[0] = inc->m_prev_status = data;
|
||||
}
|
||||
} else if (inc->m_prev_status & 0x80) {
|
||||
/* Data byte (use running status) */
|
||||
inc->m_ptr = 2;
|
||||
inc->m_buf[1] = data;
|
||||
inc->m_buf[0] = inc->m_prev_status;
|
||||
inc->m_left = len_tab[(inc->m_buf[0] >> 4) - 8] - 1;
|
||||
if (inc->m_left > 0)
|
||||
inc->m_state = MST_DATA; /* Not done yet */
|
||||
else {
|
||||
inc->m_state = MST_INIT;
|
||||
do_midi_msg(dev, inc->m_buf, inc->m_ptr);
|
||||
inc->m_ptr = 0;
|
||||
}
|
||||
}
|
||||
break; /* MST_INIT */
|
||||
|
||||
case MST_DATA:
|
||||
inc->m_buf[inc->m_ptr++] = data;
|
||||
if (--inc->m_left <= 0)
|
||||
{
|
||||
inc->m_state = MST_INIT;
|
||||
do_midi_msg(dev, inc->m_buf, inc->m_ptr);
|
||||
inc->m_ptr = 0;
|
||||
}
|
||||
break; /* MST_DATA */
|
||||
|
||||
case MST_SYSEX:
|
||||
if (data == 0xf7) /* Sysex end */
|
||||
{
|
||||
inc->m_state = MST_INIT;
|
||||
inc->m_left = 0;
|
||||
inc->m_ptr = 0;
|
||||
}
|
||||
break; /* MST_SYSEX */
|
||||
|
||||
default:
|
||||
printk("MIDI%d: Unexpected state %d (%02x)\n", orig_dev, inc->m_state, (int) data);
|
||||
inc->m_state = MST_INIT;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
leave_sysex(int dev)
|
||||
{
|
||||
int orig_dev = synth_devs[dev]->midi_dev;
|
||||
int timeout = 0;
|
||||
|
||||
if (!sysex_state[dev])
|
||||
return;
|
||||
|
||||
sysex_state[dev] = 0;
|
||||
|
||||
while (!midi_devs[orig_dev]->outputc(orig_dev, 0xf7) &&
|
||||
timeout < 1000)
|
||||
timeout++;
|
||||
|
||||
sysex_state[dev] = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
midi_synth_output(int dev)
|
||||
{
|
||||
/*
|
||||
* Currently NOP
|
||||
*/
|
||||
}
|
||||
|
||||
int midi_synth_ioctl(int dev, unsigned int cmd, void __user *arg)
|
||||
{
|
||||
/*
|
||||
* int orig_dev = synth_devs[dev]->midi_dev;
|
||||
*/
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
case SNDCTL_SYNTH_INFO:
|
||||
if (__copy_to_user(arg, synth_devs[dev]->info, sizeof(struct synth_info)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case SNDCTL_SYNTH_MEMAVL:
|
||||
return 0x7fffffff;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_ioctl);
|
||||
|
||||
int
|
||||
midi_synth_kill_note(int dev, int channel, int note, int velocity)
|
||||
{
|
||||
int orig_dev = synth_devs[dev]->midi_dev;
|
||||
int msg, chn;
|
||||
|
||||
if (note < 0 || note > 127)
|
||||
return 0;
|
||||
if (channel < 0 || channel > 15)
|
||||
return 0;
|
||||
if (velocity < 0)
|
||||
velocity = 0;
|
||||
if (velocity > 127)
|
||||
velocity = 127;
|
||||
|
||||
leave_sysex(dev);
|
||||
|
||||
msg = prev_out_status[orig_dev] & 0xf0;
|
||||
chn = prev_out_status[orig_dev] & 0x0f;
|
||||
|
||||
if (chn == channel && ((msg == 0x90 && velocity == 64) || msg == 0x80))
|
||||
{ /*
|
||||
* Use running status
|
||||
*/
|
||||
if (!prefix_cmd(orig_dev, note))
|
||||
return 0;
|
||||
|
||||
midi_outc(orig_dev, note);
|
||||
|
||||
if (msg == 0x90) /*
|
||||
* Running status = Note on
|
||||
*/
|
||||
midi_outc(orig_dev, 0); /*
|
||||
* Note on with velocity 0 == note
|
||||
* off
|
||||
*/
|
||||
else
|
||||
midi_outc(orig_dev, velocity);
|
||||
} else
|
||||
{
|
||||
if (velocity == 64)
|
||||
{
|
||||
if (!prefix_cmd(orig_dev, 0x90 | (channel & 0x0f)))
|
||||
return 0;
|
||||
midi_outc(orig_dev, 0x90 | (channel & 0x0f)); /*
|
||||
* Note on
|
||||
*/
|
||||
midi_outc(orig_dev, note);
|
||||
midi_outc(orig_dev, 0); /*
|
||||
* Zero G
|
||||
*/
|
||||
} else
|
||||
{
|
||||
if (!prefix_cmd(orig_dev, 0x80 | (channel & 0x0f)))
|
||||
return 0;
|
||||
midi_outc(orig_dev, 0x80 | (channel & 0x0f)); /*
|
||||
* Note off
|
||||
*/
|
||||
midi_outc(orig_dev, note);
|
||||
midi_outc(orig_dev, velocity);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_kill_note);
|
||||
|
||||
int
|
||||
midi_synth_set_instr(int dev, int channel, int instr_no)
|
||||
{
|
||||
int orig_dev = synth_devs[dev]->midi_dev;
|
||||
|
||||
if (instr_no < 0 || instr_no > 127)
|
||||
instr_no = 0;
|
||||
if (channel < 0 || channel > 15)
|
||||
return 0;
|
||||
|
||||
leave_sysex(dev);
|
||||
|
||||
if (!prefix_cmd(orig_dev, 0xc0 | (channel & 0x0f)))
|
||||
return 0;
|
||||
midi_outc(orig_dev, 0xc0 | (channel & 0x0f)); /*
|
||||
* Program change
|
||||
*/
|
||||
midi_outc(orig_dev, instr_no);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_set_instr);
|
||||
|
||||
int
|
||||
midi_synth_start_note(int dev, int channel, int note, int velocity)
|
||||
{
|
||||
int orig_dev = synth_devs[dev]->midi_dev;
|
||||
int msg, chn;
|
||||
|
||||
if (note < 0 || note > 127)
|
||||
return 0;
|
||||
if (channel < 0 || channel > 15)
|
||||
return 0;
|
||||
if (velocity < 0)
|
||||
velocity = 0;
|
||||
if (velocity > 127)
|
||||
velocity = 127;
|
||||
|
||||
leave_sysex(dev);
|
||||
|
||||
msg = prev_out_status[orig_dev] & 0xf0;
|
||||
chn = prev_out_status[orig_dev] & 0x0f;
|
||||
|
||||
if (chn == channel && msg == 0x90)
|
||||
{ /*
|
||||
* Use running status
|
||||
*/
|
||||
if (!prefix_cmd(orig_dev, note))
|
||||
return 0;
|
||||
midi_outc(orig_dev, note);
|
||||
midi_outc(orig_dev, velocity);
|
||||
} else
|
||||
{
|
||||
if (!prefix_cmd(orig_dev, 0x90 | (channel & 0x0f)))
|
||||
return 0;
|
||||
midi_outc(orig_dev, 0x90 | (channel & 0x0f)); /*
|
||||
* Note on
|
||||
*/
|
||||
midi_outc(orig_dev, note);
|
||||
midi_outc(orig_dev, velocity);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_start_note);
|
||||
|
||||
void
|
||||
midi_synth_reset(int dev)
|
||||
{
|
||||
|
||||
leave_sysex(dev);
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_reset);
|
||||
|
||||
int
|
||||
midi_synth_open(int dev, int mode)
|
||||
{
|
||||
int orig_dev = synth_devs[dev]->midi_dev;
|
||||
int err;
|
||||
struct midi_input_info *inc;
|
||||
|
||||
if (orig_dev < 0 || orig_dev >= num_midis || midi_devs[orig_dev] == NULL)
|
||||
return -ENXIO;
|
||||
|
||||
midi2synth[orig_dev] = dev;
|
||||
sysex_state[dev] = 0;
|
||||
prev_out_status[orig_dev] = 0;
|
||||
|
||||
if ((err = midi_devs[orig_dev]->open(orig_dev, mode,
|
||||
midi_synth_input, midi_synth_output)) < 0)
|
||||
return err;
|
||||
inc = &midi_devs[orig_dev]->in_info;
|
||||
|
||||
/* save_flags(flags);
|
||||
cli();
|
||||
don't know against what irqhandler to protect*/
|
||||
inc->m_busy = 0;
|
||||
inc->m_state = MST_INIT;
|
||||
inc->m_ptr = 0;
|
||||
inc->m_left = 0;
|
||||
inc->m_prev_status = 0x00;
|
||||
/* restore_flags(flags); */
|
||||
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_open);
|
||||
|
||||
void
|
||||
midi_synth_close(int dev)
|
||||
{
|
||||
int orig_dev = synth_devs[dev]->midi_dev;
|
||||
|
||||
leave_sysex(dev);
|
||||
|
||||
/*
|
||||
* Shut up the synths by sending just single active sensing message.
|
||||
*/
|
||||
midi_devs[orig_dev]->outputc(orig_dev, 0xfe);
|
||||
|
||||
midi_devs[orig_dev]->close(orig_dev);
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_close);
|
||||
|
||||
void
|
||||
midi_synth_hw_control(int dev, unsigned char *event)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_hw_control);
|
||||
|
||||
int
|
||||
midi_synth_load_patch(int dev, int format, const char __user *addr,
|
||||
int count, int pmgr_flag)
|
||||
{
|
||||
int orig_dev = synth_devs[dev]->midi_dev;
|
||||
|
||||
struct sysex_info sysex;
|
||||
int i;
|
||||
unsigned long left, src_offs, eox_seen = 0;
|
||||
int first_byte = 1;
|
||||
int hdr_size = (unsigned long) &sysex.data[0] - (unsigned long) &sysex;
|
||||
|
||||
leave_sysex(dev);
|
||||
|
||||
if (!prefix_cmd(orig_dev, 0xf0))
|
||||
return 0;
|
||||
|
||||
/* Invalid patch format */
|
||||
if (format != SYSEX_PATCH)
|
||||
return -EINVAL;
|
||||
|
||||
/* Patch header too short */
|
||||
if (count < hdr_size)
|
||||
return -EINVAL;
|
||||
|
||||
count -= hdr_size;
|
||||
|
||||
/*
|
||||
* Copy the header from user space
|
||||
*/
|
||||
|
||||
if (copy_from_user(&sysex, addr, hdr_size))
|
||||
return -EFAULT;
|
||||
|
||||
/* Sysex record too short */
|
||||
if ((unsigned)count < (unsigned)sysex.len)
|
||||
sysex.len = count;
|
||||
|
||||
left = sysex.len;
|
||||
src_offs = 0;
|
||||
|
||||
for (i = 0; i < left && !signal_pending(current); i++)
|
||||
{
|
||||
unsigned char data;
|
||||
|
||||
if (get_user(data,
|
||||
(unsigned char __user *)(addr + hdr_size + i)))
|
||||
return -EFAULT;
|
||||
|
||||
eox_seen = (i > 0 && data & 0x80); /* End of sysex */
|
||||
|
||||
if (eox_seen && data != 0xf7)
|
||||
data = 0xf7;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
if (data != 0xf0)
|
||||
{
|
||||
printk(KERN_WARNING "midi_synth: Sysex start missing\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
while (!midi_devs[orig_dev]->outputc(orig_dev, (unsigned char) (data & 0xff)) &&
|
||||
!signal_pending(current))
|
||||
schedule();
|
||||
|
||||
if (!first_byte && data & 0x80)
|
||||
return 0;
|
||||
first_byte = 0;
|
||||
}
|
||||
|
||||
if (!eox_seen)
|
||||
midi_outc(orig_dev, 0xf7);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_load_patch);
|
||||
|
||||
void midi_synth_panning(int dev, int channel, int pressure)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_panning);
|
||||
|
||||
void midi_synth_aftertouch(int dev, int channel, int pressure)
|
||||
{
|
||||
int orig_dev = synth_devs[dev]->midi_dev;
|
||||
int msg, chn;
|
||||
|
||||
if (pressure < 0 || pressure > 127)
|
||||
return;
|
||||
if (channel < 0 || channel > 15)
|
||||
return;
|
||||
|
||||
leave_sysex(dev);
|
||||
|
||||
msg = prev_out_status[orig_dev] & 0xf0;
|
||||
chn = prev_out_status[orig_dev] & 0x0f;
|
||||
|
||||
if (msg != 0xd0 || chn != channel) /*
|
||||
* Test for running status
|
||||
*/
|
||||
{
|
||||
if (!prefix_cmd(orig_dev, 0xd0 | (channel & 0x0f)))
|
||||
return;
|
||||
midi_outc(orig_dev, 0xd0 | (channel & 0x0f)); /*
|
||||
* Channel pressure
|
||||
*/
|
||||
} else if (!prefix_cmd(orig_dev, pressure))
|
||||
return;
|
||||
|
||||
midi_outc(orig_dev, pressure);
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_aftertouch);
|
||||
|
||||
void
|
||||
midi_synth_controller(int dev, int channel, int ctrl_num, int value)
|
||||
{
|
||||
int orig_dev = synth_devs[dev]->midi_dev;
|
||||
int chn, msg;
|
||||
|
||||
if (ctrl_num < 0 || ctrl_num > 127)
|
||||
return;
|
||||
if (channel < 0 || channel > 15)
|
||||
return;
|
||||
|
||||
leave_sysex(dev);
|
||||
|
||||
msg = prev_out_status[orig_dev] & 0xf0;
|
||||
chn = prev_out_status[orig_dev] & 0x0f;
|
||||
|
||||
if (msg != 0xb0 || chn != channel)
|
||||
{
|
||||
if (!prefix_cmd(orig_dev, 0xb0 | (channel & 0x0f)))
|
||||
return;
|
||||
midi_outc(orig_dev, 0xb0 | (channel & 0x0f));
|
||||
} else if (!prefix_cmd(orig_dev, ctrl_num))
|
||||
return;
|
||||
|
||||
midi_outc(orig_dev, ctrl_num);
|
||||
midi_outc(orig_dev, value & 0x7f);
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_controller);
|
||||
|
||||
void
|
||||
midi_synth_bender(int dev, int channel, int value)
|
||||
{
|
||||
int orig_dev = synth_devs[dev]->midi_dev;
|
||||
int msg, prev_chn;
|
||||
|
||||
if (channel < 0 || channel > 15)
|
||||
return;
|
||||
|
||||
if (value < 0 || value > 16383)
|
||||
return;
|
||||
|
||||
leave_sysex(dev);
|
||||
|
||||
msg = prev_out_status[orig_dev] & 0xf0;
|
||||
prev_chn = prev_out_status[orig_dev] & 0x0f;
|
||||
|
||||
if (msg != 0xd0 || prev_chn != channel) /*
|
||||
* Test for running status
|
||||
*/
|
||||
{
|
||||
if (!prefix_cmd(orig_dev, 0xe0 | (channel & 0x0f)))
|
||||
return;
|
||||
midi_outc(orig_dev, 0xe0 | (channel & 0x0f));
|
||||
} else if (!prefix_cmd(orig_dev, value & 0x7f))
|
||||
return;
|
||||
|
||||
midi_outc(orig_dev, value & 0x7f);
|
||||
midi_outc(orig_dev, (value >> 7) & 0x7f);
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_bender);
|
||||
|
||||
void
|
||||
midi_synth_setup_voice(int dev, int voice, int channel)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_setup_voice);
|
||||
|
||||
int
|
||||
midi_synth_send_sysex(int dev, unsigned char *bytes, int len)
|
||||
{
|
||||
int orig_dev = synth_devs[dev]->midi_dev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
switch (bytes[i])
|
||||
{
|
||||
case 0xf0: /* Start sysex */
|
||||
if (!prefix_cmd(orig_dev, 0xf0))
|
||||
return 0;
|
||||
sysex_state[dev] = 1;
|
||||
break;
|
||||
|
||||
case 0xf7: /* End sysex */
|
||||
if (!sysex_state[dev]) /* Orphan sysex end */
|
||||
return 0;
|
||||
sysex_state[dev] = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!sysex_state[dev])
|
||||
return 0;
|
||||
|
||||
if (bytes[i] & 0x80) /* Error. Another message before sysex end */
|
||||
{
|
||||
bytes[i] = 0xf7; /* Sysex end */
|
||||
sysex_state[dev] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!midi_devs[orig_dev]->outputc(orig_dev, bytes[i]))
|
||||
{
|
||||
/*
|
||||
* Hardware level buffer is full. Abort the sysex message.
|
||||
*/
|
||||
|
||||
int timeout = 0;
|
||||
|
||||
bytes[i] = 0xf7;
|
||||
sysex_state[dev] = 0;
|
||||
|
||||
while (!midi_devs[orig_dev]->outputc(orig_dev, bytes[i]) &&
|
||||
timeout < 1000)
|
||||
timeout++;
|
||||
}
|
||||
if (!sysex_state[dev])
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(midi_synth_send_sysex);
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
int midi_synth_ioctl (int dev,
|
||||
unsigned int cmd, void __user * arg);
|
||||
int midi_synth_kill_note (int dev, int channel, int note, int velocity);
|
||||
int midi_synth_set_instr (int dev, int channel, int instr_no);
|
||||
int midi_synth_start_note (int dev, int channel, int note, int volume);
|
||||
void midi_synth_reset (int dev);
|
||||
int midi_synth_open (int dev, int mode);
|
||||
void midi_synth_close (int dev);
|
||||
void midi_synth_hw_control (int dev, unsigned char *event);
|
||||
int midi_synth_load_patch (int dev, int format, const char __user * addr,
|
||||
int count, int pmgr_flag);
|
||||
void midi_synth_panning (int dev, int channel, int pressure);
|
||||
void midi_synth_aftertouch (int dev, int channel, int pressure);
|
||||
void midi_synth_controller (int dev, int channel, int ctrl_num, int value);
|
||||
void midi_synth_bender (int dev, int chn, int value);
|
||||
void midi_synth_setup_voice (int dev, int voice, int chn);
|
||||
int midi_synth_send_sysex(int dev, unsigned char *bytes,int len);
|
||||
|
||||
#ifndef _MIDI_SYNTH_C_
|
||||
static struct synth_info std_synth_info =
|
||||
{MIDI_SYNTH_NAME, 0, SYNTH_TYPE_MIDI, 0, 0, 128, 0, 128, MIDI_SYNTH_CAPS};
|
||||
|
||||
static struct synth_operations std_midi_synth =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.id = "MIDI",
|
||||
.info = &std_synth_info,
|
||||
.midi_dev = 0,
|
||||
.synth_type = SYNTH_TYPE_MIDI,
|
||||
.synth_subtype = 0,
|
||||
.open = midi_synth_open,
|
||||
.close = midi_synth_close,
|
||||
.ioctl = midi_synth_ioctl,
|
||||
.kill_note = midi_synth_kill_note,
|
||||
.start_note = midi_synth_start_note,
|
||||
.set_instr = midi_synth_set_instr,
|
||||
.reset = midi_synth_reset,
|
||||
.hw_control = midi_synth_hw_control,
|
||||
.load_patch = midi_synth_load_patch,
|
||||
.aftertouch = midi_synth_aftertouch,
|
||||
.controller = midi_synth_controller,
|
||||
.panning = midi_synth_panning,
|
||||
.bender = midi_synth_bender,
|
||||
.setup_voice = midi_synth_setup_voice,
|
||||
.send_sysex = midi_synth_send_sysex
|
||||
};
|
||||
#endif
|
|
@ -1,427 +0,0 @@
|
|||
/*
|
||||
* sound/oss/midibuf.c
|
||||
*
|
||||
* Device file manager for /dev/midi#
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) by Hannu Savolainen 1993-1997
|
||||
*
|
||||
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
|
||||
* Version 2 (June 1991). See the "COPYING" file distributed with this software
|
||||
* for more info.
|
||||
*/
|
||||
/*
|
||||
* Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
|
||||
*/
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/sched/signal.h>
|
||||
|
||||
#define MIDIBUF_C
|
||||
|
||||
#include "sound_config.h"
|
||||
|
||||
|
||||
/*
|
||||
* Don't make MAX_QUEUE_SIZE larger than 4000
|
||||
*/
|
||||
|
||||
#define MAX_QUEUE_SIZE 4000
|
||||
|
||||
static wait_queue_head_t midi_sleeper[MAX_MIDI_DEV];
|
||||
static wait_queue_head_t input_sleeper[MAX_MIDI_DEV];
|
||||
|
||||
struct midi_buf
|
||||
{
|
||||
int len, head, tail;
|
||||
unsigned char queue[MAX_QUEUE_SIZE];
|
||||
};
|
||||
|
||||
struct midi_parms
|
||||
{
|
||||
long prech_timeout; /*
|
||||
* Timeout before the first ch
|
||||
*/
|
||||
};
|
||||
|
||||
static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] = {NULL};
|
||||
static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] = {NULL};
|
||||
static struct midi_parms parms[MAX_MIDI_DEV];
|
||||
|
||||
static void midi_poll(unsigned long dummy);
|
||||
|
||||
|
||||
static DEFINE_TIMER(poll_timer, midi_poll, 0, 0);
|
||||
|
||||
static volatile int open_devs;
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
|
||||
#define DATA_AVAIL(q) (q->len)
|
||||
#define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len)
|
||||
|
||||
#define QUEUE_BYTE(q, data) \
|
||||
if (SPACE_AVAIL(q)) \
|
||||
{ \
|
||||
unsigned long flags; \
|
||||
spin_lock_irqsave(&lock, flags); \
|
||||
q->queue[q->tail] = (data); \
|
||||
q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
|
||||
spin_unlock_irqrestore(&lock, flags); \
|
||||
}
|
||||
|
||||
#define REMOVE_BYTE(q, data) \
|
||||
if (DATA_AVAIL(q)) \
|
||||
{ \
|
||||
unsigned long flags; \
|
||||
spin_lock_irqsave(&lock, flags); \
|
||||
data = q->queue[q->head]; \
|
||||
q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
|
||||
spin_unlock_irqrestore(&lock, flags); \
|
||||
}
|
||||
|
||||
static void drain_midi_queue(int dev)
|
||||
{
|
||||
|
||||
/*
|
||||
* Give the Midi driver time to drain its output queues
|
||||
*/
|
||||
|
||||
if (midi_devs[dev]->buffer_status != NULL)
|
||||
wait_event_interruptible_timeout(midi_sleeper[dev],
|
||||
!midi_devs[dev]->buffer_status(dev), HZ/10);
|
||||
}
|
||||
|
||||
static void midi_input_intr(int dev, unsigned char data)
|
||||
{
|
||||
if (midi_in_buf[dev] == NULL)
|
||||
return;
|
||||
|
||||
if (data == 0xfe) /*
|
||||
* Active sensing
|
||||
*/
|
||||
return; /*
|
||||
* Ignore
|
||||
*/
|
||||
|
||||
if (SPACE_AVAIL(midi_in_buf[dev])) {
|
||||
QUEUE_BYTE(midi_in_buf[dev], data);
|
||||
wake_up(&input_sleeper[dev]);
|
||||
}
|
||||
}
|
||||
|
||||
static void midi_output_intr(int dev)
|
||||
{
|
||||
/*
|
||||
* Currently NOP
|
||||
*/
|
||||
}
|
||||
|
||||
static void midi_poll(unsigned long dummy)
|
||||
{
|
||||
unsigned long flags;
|
||||
int dev;
|
||||
|
||||
spin_lock_irqsave(&lock, flags);
|
||||
if (open_devs)
|
||||
{
|
||||
for (dev = 0; dev < num_midis; dev++)
|
||||
if (midi_devs[dev] != NULL && midi_out_buf[dev] != NULL)
|
||||
{
|
||||
while (DATA_AVAIL(midi_out_buf[dev]))
|
||||
{
|
||||
int ok;
|
||||
int c = midi_out_buf[dev]->queue[midi_out_buf[dev]->head];
|
||||
|
||||
spin_unlock_irqrestore(&lock,flags);/* Give some time to others */
|
||||
ok = midi_devs[dev]->outputc(dev, c);
|
||||
spin_lock_irqsave(&lock, flags);
|
||||
if (!ok)
|
||||
break;
|
||||
midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
|
||||
midi_out_buf[dev]->len--;
|
||||
}
|
||||
|
||||
if (DATA_AVAIL(midi_out_buf[dev]) < 100)
|
||||
wake_up(&midi_sleeper[dev]);
|
||||
}
|
||||
poll_timer.expires = (1) + jiffies;
|
||||
add_timer(&poll_timer);
|
||||
/*
|
||||
* Come back later
|
||||
*/
|
||||
}
|
||||
spin_unlock_irqrestore(&lock, flags);
|
||||
}
|
||||
|
||||
int MIDIbuf_open(int dev, struct file *file)
|
||||
{
|
||||
int mode, err;
|
||||
|
||||
dev = dev >> 4;
|
||||
mode = translate_mode(file);
|
||||
|
||||
if (num_midis > MAX_MIDI_DEV)
|
||||
{
|
||||
printk(KERN_ERR "midi: Too many midi interfaces\n");
|
||||
num_midis = MAX_MIDI_DEV;
|
||||
}
|
||||
if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL)
|
||||
return -ENXIO;
|
||||
/*
|
||||
* Interrupts disabled. Be careful
|
||||
*/
|
||||
|
||||
module_put(midi_devs[dev]->owner);
|
||||
|
||||
if ((err = midi_devs[dev]->open(dev, mode,
|
||||
midi_input_intr, midi_output_intr)) < 0)
|
||||
return err;
|
||||
|
||||
parms[dev].prech_timeout = MAX_SCHEDULE_TIMEOUT;
|
||||
midi_in_buf[dev] = vmalloc(sizeof(struct midi_buf));
|
||||
|
||||
if (midi_in_buf[dev] == NULL)
|
||||
{
|
||||
printk(KERN_WARNING "midi: Can't allocate buffer\n");
|
||||
midi_devs[dev]->close(dev);
|
||||
return -EIO;
|
||||
}
|
||||
midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
|
||||
|
||||
midi_out_buf[dev] = vmalloc(sizeof(struct midi_buf));
|
||||
|
||||
if (midi_out_buf[dev] == NULL)
|
||||
{
|
||||
printk(KERN_WARNING "midi: Can't allocate buffer\n");
|
||||
midi_devs[dev]->close(dev);
|
||||
vfree(midi_in_buf[dev]);
|
||||
midi_in_buf[dev] = NULL;
|
||||
return -EIO;
|
||||
}
|
||||
midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
|
||||
open_devs++;
|
||||
|
||||
init_waitqueue_head(&midi_sleeper[dev]);
|
||||
init_waitqueue_head(&input_sleeper[dev]);
|
||||
|
||||
if (open_devs < 2) /* This was first open */
|
||||
{
|
||||
poll_timer.expires = 1 + jiffies;
|
||||
add_timer(&poll_timer); /* Start polling */
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void MIDIbuf_release(int dev, struct file *file)
|
||||
{
|
||||
int mode;
|
||||
|
||||
dev = dev >> 4;
|
||||
mode = translate_mode(file);
|
||||
|
||||
if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Wait until the queue is empty
|
||||
*/
|
||||
|
||||
if (mode != OPEN_READ)
|
||||
{
|
||||
midi_devs[dev]->outputc(dev, 0xfe); /*
|
||||
* Active sensing to shut the
|
||||
* devices
|
||||
*/
|
||||
|
||||
wait_event_interruptible(midi_sleeper[dev],
|
||||
!DATA_AVAIL(midi_out_buf[dev]));
|
||||
/*
|
||||
* Sync
|
||||
*/
|
||||
|
||||
drain_midi_queue(dev); /*
|
||||
* Ensure the output queues are empty
|
||||
*/
|
||||
}
|
||||
|
||||
midi_devs[dev]->close(dev);
|
||||
|
||||
open_devs--;
|
||||
if (open_devs == 0)
|
||||
del_timer_sync(&poll_timer);
|
||||
vfree(midi_in_buf[dev]);
|
||||
vfree(midi_out_buf[dev]);
|
||||
midi_in_buf[dev] = NULL;
|
||||
midi_out_buf[dev] = NULL;
|
||||
|
||||
module_put(midi_devs[dev]->owner);
|
||||
}
|
||||
|
||||
int MIDIbuf_write(int dev, struct file *file, const char __user *buf, int count)
|
||||
{
|
||||
int c, n, i;
|
||||
unsigned char tmp_data;
|
||||
|
||||
dev = dev >> 4;
|
||||
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
c = 0;
|
||||
|
||||
while (c < count)
|
||||
{
|
||||
n = SPACE_AVAIL(midi_out_buf[dev]);
|
||||
|
||||
if (n == 0) { /*
|
||||
* No space just now.
|
||||
*/
|
||||
|
||||
if (file->f_flags & O_NONBLOCK) {
|
||||
c = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (wait_event_interruptible(midi_sleeper[dev],
|
||||
SPACE_AVAIL(midi_out_buf[dev])))
|
||||
{
|
||||
c = -EINTR;
|
||||
goto out;
|
||||
}
|
||||
n = SPACE_AVAIL(midi_out_buf[dev]);
|
||||
}
|
||||
if (n > (count - c))
|
||||
n = count - c;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
/* BROKE BROKE BROKE - CAN'T DO THIS WITH CLI !! */
|
||||
/* yes, think the same, so I removed the cli() brackets
|
||||
QUEUE_BYTE is protected against interrupts */
|
||||
if (copy_from_user((char *) &tmp_data, &(buf)[c], 1)) {
|
||||
c = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
QUEUE_BYTE(midi_out_buf[dev], tmp_data);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
out:
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
int MIDIbuf_read(int dev, struct file *file, char __user *buf, int count)
|
||||
{
|
||||
int n, c = 0;
|
||||
unsigned char tmp_data;
|
||||
|
||||
dev = dev >> 4;
|
||||
|
||||
if (!DATA_AVAIL(midi_in_buf[dev])) { /*
|
||||
* No data yet, wait
|
||||
*/
|
||||
if (file->f_flags & O_NONBLOCK) {
|
||||
c = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
wait_event_interruptible_timeout(input_sleeper[dev],
|
||||
DATA_AVAIL(midi_in_buf[dev]),
|
||||
parms[dev].prech_timeout);
|
||||
|
||||
if (signal_pending(current))
|
||||
c = -EINTR; /* The user is getting restless */
|
||||
}
|
||||
if (c == 0 && DATA_AVAIL(midi_in_buf[dev])) /*
|
||||
* Got some bytes
|
||||
*/
|
||||
{
|
||||
n = DATA_AVAIL(midi_in_buf[dev]);
|
||||
if (n > count)
|
||||
n = count;
|
||||
c = 0;
|
||||
|
||||
while (c < n)
|
||||
{
|
||||
char *fixit;
|
||||
REMOVE_BYTE(midi_in_buf[dev], tmp_data);
|
||||
fixit = (char *) &tmp_data;
|
||||
/* BROKE BROKE BROKE */
|
||||
/* yes removed the cli() brackets again
|
||||
should q->len,tail&head be atomic_t? */
|
||||
if (copy_to_user(&(buf)[c], fixit, 1)) {
|
||||
c = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
}
|
||||
out:
|
||||
return c;
|
||||
}
|
||||
|
||||
int MIDIbuf_ioctl(int dev, struct file *file,
|
||||
unsigned int cmd, void __user *arg)
|
||||
{
|
||||
int val;
|
||||
|
||||
dev = dev >> 4;
|
||||
|
||||
if (((cmd >> 8) & 0xff) == 'C')
|
||||
{
|
||||
if (midi_devs[dev]->coproc) /* Coprocessor ioctl */
|
||||
return midi_devs[dev]->coproc->ioctl(midi_devs[dev]->coproc->devc, cmd, arg, 0);
|
||||
/* printk("/dev/midi%d: No coprocessor for this device\n", dev);*/
|
||||
return -ENXIO;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
case SNDCTL_MIDI_PRETIME:
|
||||
if (get_user(val, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
if (val < 0)
|
||||
val = 0;
|
||||
val = (HZ * val) / 10;
|
||||
parms[dev].prech_timeout = val;
|
||||
return put_user(val, (int __user *)arg);
|
||||
|
||||
default:
|
||||
if (!midi_devs[dev]->ioctl)
|
||||
return -EINVAL;
|
||||
return midi_devs[dev]->ioctl(dev, cmd, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No kernel lock - fine */
|
||||
unsigned int MIDIbuf_poll(int dev, struct file *file, poll_table * wait)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
|
||||
dev = dev >> 4;
|
||||
|
||||
/* input */
|
||||
poll_wait(file, &input_sleeper[dev], wait);
|
||||
if (DATA_AVAIL(midi_in_buf[dev]))
|
||||
mask |= POLLIN | POLLRDNORM;
|
||||
|
||||
/* output */
|
||||
poll_wait(file, &midi_sleeper[dev], wait);
|
||||
if (!SPACE_AVAIL(midi_out_buf[dev]))
|
||||
mask |= POLLOUT | POLLWRNORM;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
int MIDIbuf_avail(int dev)
|
||||
{
|
||||
if (midi_in_buf[dev])
|
||||
return DATA_AVAIL (midi_in_buf[dev]);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(MIDIbuf_avail);
|
||||
|
1804
sound/oss/mpu401.c
1804
sound/oss/mpu401.c
File diff suppressed because it is too large
Load diff
|
@ -1,11 +0,0 @@
|
|||
|
||||
/* From uart401.c */
|
||||
int probe_uart401 (struct address_info *hw_config, struct module *owner);
|
||||
void unload_uart401 (struct address_info *hw_config);
|
||||
|
||||
irqreturn_t uart401intr (int irq, void *dev_id);
|
||||
|
||||
/* From mpu401.c */
|
||||
int probe_mpu401(struct address_info *hw_config, struct resource *ports);
|
||||
int attach_mpu401(struct address_info * hw_config, struct module *owner);
|
||||
void unload_mpu401(struct address_info *hw_info);
|
413
sound/oss/msnd.c
413
sound/oss/msnd.c
|
@ -1,413 +0,0 @@
|
|||
/*********************************************************************
|
||||
*
|
||||
* msnd.c - Driver Base
|
||||
*
|
||||
* Turtle Beach MultiSound Sound Card Driver for Linux
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Veliath
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
********************************************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/irq.h>
|
||||
#include "msnd.h"
|
||||
|
||||
#define LOGNAME "msnd"
|
||||
|
||||
#define MSND_MAX_DEVS 4
|
||||
|
||||
static multisound_dev_t *devs[MSND_MAX_DEVS];
|
||||
static int num_devs;
|
||||
|
||||
int msnd_register(multisound_dev_t *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MSND_MAX_DEVS; ++i)
|
||||
if (devs[i] == NULL)
|
||||
break;
|
||||
|
||||
if (i == MSND_MAX_DEVS)
|
||||
return -ENOMEM;
|
||||
|
||||
devs[i] = dev;
|
||||
++num_devs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void msnd_unregister(multisound_dev_t *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MSND_MAX_DEVS; ++i)
|
||||
if (devs[i] == dev)
|
||||
break;
|
||||
|
||||
if (i == MSND_MAX_DEVS) {
|
||||
printk(KERN_WARNING LOGNAME ": Unregistering unknown device\n");
|
||||
return;
|
||||
}
|
||||
|
||||
devs[i] = NULL;
|
||||
--num_devs;
|
||||
}
|
||||
|
||||
void msnd_init_queue(void __iomem *base, int start, int size)
|
||||
{
|
||||
writew(PCTODSP_BASED(start), base + JQS_wStart);
|
||||
writew(PCTODSP_OFFSET(size) - 1, base + JQS_wSize);
|
||||
writew(0, base + JQS_wHead);
|
||||
writew(0, base + JQS_wTail);
|
||||
}
|
||||
|
||||
void msnd_fifo_init(msnd_fifo *f)
|
||||
{
|
||||
f->data = NULL;
|
||||
}
|
||||
|
||||
void msnd_fifo_free(msnd_fifo *f)
|
||||
{
|
||||
vfree(f->data);
|
||||
f->data = NULL;
|
||||
}
|
||||
|
||||
int msnd_fifo_alloc(msnd_fifo *f, size_t n)
|
||||
{
|
||||
msnd_fifo_free(f);
|
||||
f->data = vmalloc(n);
|
||||
f->n = n;
|
||||
f->tail = 0;
|
||||
f->head = 0;
|
||||
f->len = 0;
|
||||
|
||||
if (!f->data)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void msnd_fifo_make_empty(msnd_fifo *f)
|
||||
{
|
||||
f->len = f->tail = f->head = 0;
|
||||
}
|
||||
|
||||
int msnd_fifo_write_io(msnd_fifo *f, char __iomem *buf, size_t len)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
while ((count < len) && (f->len != f->n)) {
|
||||
|
||||
int nwritten;
|
||||
|
||||
if (f->head <= f->tail) {
|
||||
nwritten = len - count;
|
||||
if (nwritten > f->n - f->tail)
|
||||
nwritten = f->n - f->tail;
|
||||
}
|
||||
else {
|
||||
nwritten = f->head - f->tail;
|
||||
if (nwritten > len - count)
|
||||
nwritten = len - count;
|
||||
}
|
||||
|
||||
memcpy_fromio(f->data + f->tail, buf, nwritten);
|
||||
|
||||
count += nwritten;
|
||||
buf += nwritten;
|
||||
f->len += nwritten;
|
||||
f->tail += nwritten;
|
||||
f->tail %= f->n;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
while ((count < len) && (f->len != f->n)) {
|
||||
|
||||
int nwritten;
|
||||
|
||||
if (f->head <= f->tail) {
|
||||
nwritten = len - count;
|
||||
if (nwritten > f->n - f->tail)
|
||||
nwritten = f->n - f->tail;
|
||||
}
|
||||
else {
|
||||
nwritten = f->head - f->tail;
|
||||
if (nwritten > len - count)
|
||||
nwritten = len - count;
|
||||
}
|
||||
|
||||
memcpy(f->data + f->tail, buf, nwritten);
|
||||
|
||||
count += nwritten;
|
||||
buf += nwritten;
|
||||
f->len += nwritten;
|
||||
f->tail += nwritten;
|
||||
f->tail %= f->n;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int msnd_fifo_read_io(msnd_fifo *f, char __iomem *buf, size_t len)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
while ((count < len) && (f->len > 0)) {
|
||||
|
||||
int nread;
|
||||
|
||||
if (f->tail <= f->head) {
|
||||
nread = len - count;
|
||||
if (nread > f->n - f->head)
|
||||
nread = f->n - f->head;
|
||||
}
|
||||
else {
|
||||
nread = f->tail - f->head;
|
||||
if (nread > len - count)
|
||||
nread = len - count;
|
||||
}
|
||||
|
||||
memcpy_toio(buf, f->data + f->head, nread);
|
||||
|
||||
count += nread;
|
||||
buf += nread;
|
||||
f->len -= nread;
|
||||
f->head += nread;
|
||||
f->head %= f->n;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
while ((count < len) && (f->len > 0)) {
|
||||
|
||||
int nread;
|
||||
|
||||
if (f->tail <= f->head) {
|
||||
nread = len - count;
|
||||
if (nread > f->n - f->head)
|
||||
nread = f->n - f->head;
|
||||
}
|
||||
else {
|
||||
nread = f->tail - f->head;
|
||||
if (nread > len - count)
|
||||
nread = len - count;
|
||||
}
|
||||
|
||||
memcpy(buf, f->data + f->head, nread);
|
||||
|
||||
count += nread;
|
||||
buf += nread;
|
||||
f->len -= nread;
|
||||
f->head += nread;
|
||||
f->head %= f->n;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int msnd_wait_TXDE(multisound_dev_t *dev)
|
||||
{
|
||||
register unsigned int io = dev->io;
|
||||
register int timeout = 1000;
|
||||
|
||||
while(timeout-- > 0)
|
||||
if (msnd_inb(io + HP_ISR) & HPISR_TXDE)
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int msnd_wait_HC0(multisound_dev_t *dev)
|
||||
{
|
||||
register unsigned int io = dev->io;
|
||||
register int timeout = 1000;
|
||||
|
||||
while(timeout-- > 0)
|
||||
if (!(msnd_inb(io + HP_CVR) & HPCVR_HC))
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
int msnd_send_dsp_cmd(multisound_dev_t *dev, BYTE cmd)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
if (msnd_wait_HC0(dev) == 0) {
|
||||
msnd_outb(cmd, dev->io + HP_CVR);
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
printk(KERN_DEBUG LOGNAME ": Send DSP command timeout\n");
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
int msnd_send_word(multisound_dev_t *dev, unsigned char high,
|
||||
unsigned char mid, unsigned char low)
|
||||
{
|
||||
register unsigned int io = dev->io;
|
||||
|
||||
if (msnd_wait_TXDE(dev) == 0) {
|
||||
msnd_outb(high, io + HP_TXH);
|
||||
msnd_outb(mid, io + HP_TXM);
|
||||
msnd_outb(low, io + HP_TXL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG LOGNAME ": Send host word timeout\n");
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
int msnd_upload_host(multisound_dev_t *dev, char *bin, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (len % 3 != 0) {
|
||||
printk(KERN_WARNING LOGNAME ": Upload host data not multiple of 3!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i += 3)
|
||||
if (msnd_send_word(dev, bin[i], bin[i + 1], bin[i + 2]) != 0)
|
||||
return -EIO;
|
||||
|
||||
msnd_inb(dev->io + HP_RXL);
|
||||
msnd_inb(dev->io + HP_CVR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msnd_enable_irq(multisound_dev_t *dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (dev->irq_ref++)
|
||||
return 0;
|
||||
|
||||
printk(KERN_DEBUG LOGNAME ": Enabling IRQ\n");
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
if (msnd_wait_TXDE(dev) == 0) {
|
||||
msnd_outb(msnd_inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR);
|
||||
if (dev->type == msndClassic)
|
||||
msnd_outb(dev->irqid, dev->io + HP_IRQM);
|
||||
msnd_outb(msnd_inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR);
|
||||
msnd_outb(msnd_inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR);
|
||||
enable_irq(dev->irq);
|
||||
msnd_init_queue(dev->DSPQ, dev->dspq_data_buff, dev->dspq_buff_size);
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
printk(KERN_DEBUG LOGNAME ": Enable IRQ failed\n");
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
int msnd_disable_irq(multisound_dev_t *dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (--dev->irq_ref > 0)
|
||||
return 0;
|
||||
|
||||
if (dev->irq_ref < 0)
|
||||
printk(KERN_DEBUG LOGNAME ": IRQ ref count is %d\n", dev->irq_ref);
|
||||
|
||||
printk(KERN_DEBUG LOGNAME ": Disabling IRQ\n");
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
if (msnd_wait_TXDE(dev) == 0) {
|
||||
msnd_outb(msnd_inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR);
|
||||
if (dev->type == msndClassic)
|
||||
msnd_outb(HPIRQ_NONE, dev->io + HP_IRQM);
|
||||
disable_irq(dev->irq);
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
printk(KERN_DEBUG LOGNAME ": Disable IRQ failed\n");
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#ifndef LINUX20
|
||||
EXPORT_SYMBOL(msnd_register);
|
||||
EXPORT_SYMBOL(msnd_unregister);
|
||||
|
||||
EXPORT_SYMBOL(msnd_init_queue);
|
||||
|
||||
EXPORT_SYMBOL(msnd_fifo_init);
|
||||
EXPORT_SYMBOL(msnd_fifo_free);
|
||||
EXPORT_SYMBOL(msnd_fifo_alloc);
|
||||
EXPORT_SYMBOL(msnd_fifo_make_empty);
|
||||
EXPORT_SYMBOL(msnd_fifo_write_io);
|
||||
EXPORT_SYMBOL(msnd_fifo_read_io);
|
||||
EXPORT_SYMBOL(msnd_fifo_write);
|
||||
EXPORT_SYMBOL(msnd_fifo_read);
|
||||
|
||||
EXPORT_SYMBOL(msnd_send_dsp_cmd);
|
||||
EXPORT_SYMBOL(msnd_send_word);
|
||||
EXPORT_SYMBOL(msnd_upload_host);
|
||||
|
||||
EXPORT_SYMBOL(msnd_enable_irq);
|
||||
EXPORT_SYMBOL(msnd_disable_irq);
|
||||
#endif
|
||||
|
||||
#ifdef MODULE
|
||||
MODULE_AUTHOR ("Andrew Veliath <andrewtv@usa.net>");
|
||||
MODULE_DESCRIPTION ("Turtle Beach MultiSound Driver Base");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
int init_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
{
|
||||
}
|
||||
#endif
|
278
sound/oss/msnd.h
278
sound/oss/msnd.h
|
@ -1,278 +0,0 @@
|
|||
/*********************************************************************
|
||||
*
|
||||
* msnd.h
|
||||
*
|
||||
* Turtle Beach MultiSound Sound Card Driver for Linux
|
||||
*
|
||||
* Some parts of this header file were derived from the Turtle Beach
|
||||
* MultiSound Driver Development Kit.
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Veliath
|
||||
* Copyright (C) 1993 Turtle Beach Systems, Inc.
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
********************************************************************/
|
||||
#ifndef __MSND_H
|
||||
#define __MSND_H
|
||||
|
||||
#define VERSION "0.8.3.1"
|
||||
|
||||
#define DEFSAMPLERATE DSP_DEFAULT_SPEED
|
||||
#define DEFSAMPLESIZE AFMT_U8
|
||||
#define DEFCHANNELS 1
|
||||
|
||||
#define DEFFIFOSIZE 128
|
||||
|
||||
#define SNDCARD_MSND 38
|
||||
|
||||
#define SRAM_BANK_SIZE 0x8000
|
||||
#define SRAM_CNTL_START 0x7F00
|
||||
|
||||
#define DSP_BASE_ADDR 0x4000
|
||||
#define DSP_BANK_BASE 0x4000
|
||||
|
||||
#define HP_ICR 0x00
|
||||
#define HP_CVR 0x01
|
||||
#define HP_ISR 0x02
|
||||
#define HP_IVR 0x03
|
||||
#define HP_NU 0x04
|
||||
#define HP_INFO 0x04
|
||||
#define HP_TXH 0x05
|
||||
#define HP_RXH 0x05
|
||||
#define HP_TXM 0x06
|
||||
#define HP_RXM 0x06
|
||||
#define HP_TXL 0x07
|
||||
#define HP_RXL 0x07
|
||||
|
||||
#define HP_ICR_DEF 0x00
|
||||
#define HP_CVR_DEF 0x12
|
||||
#define HP_ISR_DEF 0x06
|
||||
#define HP_IVR_DEF 0x0f
|
||||
#define HP_NU_DEF 0x00
|
||||
|
||||
#define HP_IRQM 0x09
|
||||
|
||||
#define HPR_BLRC 0x08
|
||||
#define HPR_SPR1 0x09
|
||||
#define HPR_SPR2 0x0A
|
||||
#define HPR_TCL0 0x0B
|
||||
#define HPR_TCL1 0x0C
|
||||
#define HPR_TCL2 0x0D
|
||||
#define HPR_TCL3 0x0E
|
||||
#define HPR_TCL4 0x0F
|
||||
|
||||
#define HPICR_INIT 0x80
|
||||
#define HPICR_HM1 0x40
|
||||
#define HPICR_HM0 0x20
|
||||
#define HPICR_HF1 0x10
|
||||
#define HPICR_HF0 0x08
|
||||
#define HPICR_TREQ 0x02
|
||||
#define HPICR_RREQ 0x01
|
||||
|
||||
#define HPCVR_HC 0x80
|
||||
|
||||
#define HPISR_HREQ 0x80
|
||||
#define HPISR_DMA 0x40
|
||||
#define HPISR_HF3 0x10
|
||||
#define HPISR_HF2 0x08
|
||||
#define HPISR_TRDY 0x04
|
||||
#define HPISR_TXDE 0x02
|
||||
#define HPISR_RXDF 0x01
|
||||
|
||||
#define HPIO_290 0
|
||||
#define HPIO_260 1
|
||||
#define HPIO_250 2
|
||||
#define HPIO_240 3
|
||||
#define HPIO_230 4
|
||||
#define HPIO_220 5
|
||||
#define HPIO_210 6
|
||||
#define HPIO_3E0 7
|
||||
|
||||
#define HPMEM_NONE 0
|
||||
#define HPMEM_B000 1
|
||||
#define HPMEM_C800 2
|
||||
#define HPMEM_D000 3
|
||||
#define HPMEM_D400 4
|
||||
#define HPMEM_D800 5
|
||||
#define HPMEM_E000 6
|
||||
#define HPMEM_E800 7
|
||||
|
||||
#define HPIRQ_NONE 0
|
||||
#define HPIRQ_5 1
|
||||
#define HPIRQ_7 2
|
||||
#define HPIRQ_9 3
|
||||
#define HPIRQ_10 4
|
||||
#define HPIRQ_11 5
|
||||
#define HPIRQ_12 6
|
||||
#define HPIRQ_15 7
|
||||
|
||||
#define HIMT_PLAY_DONE 0x00
|
||||
#define HIMT_RECORD_DONE 0x01
|
||||
#define HIMT_MIDI_EOS 0x02
|
||||
#define HIMT_MIDI_OUT 0x03
|
||||
|
||||
#define HIMT_MIDI_IN_UCHAR 0x0E
|
||||
#define HIMT_DSP 0x0F
|
||||
|
||||
#define HDEX_BASE 0x92
|
||||
#define HDEX_PLAY_START (0 + HDEX_BASE)
|
||||
#define HDEX_PLAY_STOP (1 + HDEX_BASE)
|
||||
#define HDEX_PLAY_PAUSE (2 + HDEX_BASE)
|
||||
#define HDEX_PLAY_RESUME (3 + HDEX_BASE)
|
||||
#define HDEX_RECORD_START (4 + HDEX_BASE)
|
||||
#define HDEX_RECORD_STOP (5 + HDEX_BASE)
|
||||
#define HDEX_MIDI_IN_START (6 + HDEX_BASE)
|
||||
#define HDEX_MIDI_IN_STOP (7 + HDEX_BASE)
|
||||
#define HDEX_MIDI_OUT_START (8 + HDEX_BASE)
|
||||
#define HDEX_MIDI_OUT_STOP (9 + HDEX_BASE)
|
||||
#define HDEX_AUX_REQ (10 + HDEX_BASE)
|
||||
|
||||
#define HIWORD(l) ((WORD)((((DWORD)(l)) >> 16) & 0xFFFF))
|
||||
#define LOWORD(l) ((WORD)(DWORD)(l))
|
||||
#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF))
|
||||
#define LOBYTE(w) ((BYTE)(w))
|
||||
#define MAKELONG(low,hi) ((long)(((WORD)(low))|(((DWORD)((WORD)(hi)))<<16)))
|
||||
#define MAKEWORD(low,hi) ((WORD)(((BYTE)(low))|(((WORD)((BYTE)(hi)))<<8)))
|
||||
|
||||
#define PCTODSP_OFFSET(w) (USHORT)((w)/2)
|
||||
#define PCTODSP_BASED(w) (USHORT)(((w)/2) + DSP_BASE_ADDR)
|
||||
#define DSPTOPC_BASED(w) (((w) - DSP_BASE_ADDR) * 2)
|
||||
|
||||
#ifdef SLOWIO
|
||||
#define msnd_outb outb_p
|
||||
#define msnd_inb inb_p
|
||||
#else
|
||||
#define msnd_outb outb
|
||||
#define msnd_inb inb
|
||||
#endif
|
||||
|
||||
/* JobQueueStruct */
|
||||
#define JQS_wStart 0x00
|
||||
#define JQS_wSize 0x02
|
||||
#define JQS_wHead 0x04
|
||||
#define JQS_wTail 0x06
|
||||
#define JQS__size 0x08
|
||||
|
||||
/* DAQueueDataStruct */
|
||||
#define DAQDS_wStart 0x00
|
||||
#define DAQDS_wSize 0x02
|
||||
#define DAQDS_wFormat 0x04
|
||||
#define DAQDS_wSampleSize 0x06
|
||||
#define DAQDS_wChannels 0x08
|
||||
#define DAQDS_wSampleRate 0x0A
|
||||
#define DAQDS_wIntMsg 0x0C
|
||||
#define DAQDS_wFlags 0x0E
|
||||
#define DAQDS__size 0x10
|
||||
|
||||
typedef u8 BYTE;
|
||||
typedef u16 USHORT;
|
||||
typedef u16 WORD;
|
||||
typedef u32 DWORD;
|
||||
typedef void __iomem * LPDAQD;
|
||||
|
||||
/* Generic FIFO */
|
||||
typedef struct {
|
||||
size_t n, len;
|
||||
char *data;
|
||||
int head, tail;
|
||||
} msnd_fifo;
|
||||
|
||||
typedef struct multisound_dev {
|
||||
/* Linux device info */
|
||||
char *name;
|
||||
int dsp_minor, mixer_minor;
|
||||
int ext_midi_dev, hdr_midi_dev;
|
||||
|
||||
/* Hardware resources */
|
||||
int io, numio;
|
||||
int memid, irqid;
|
||||
int irq, irq_ref;
|
||||
unsigned char info;
|
||||
void __iomem *base;
|
||||
|
||||
/* Motorola 56k DSP SMA */
|
||||
void __iomem *SMA;
|
||||
void __iomem *DAPQ, *DARQ, *MODQ, *MIDQ, *DSPQ;
|
||||
void __iomem *pwDSPQData, *pwMIDQData, *pwMODQData;
|
||||
int dspq_data_buff, dspq_buff_size;
|
||||
|
||||
/* State variables */
|
||||
enum { msndClassic, msndPinnacle } type;
|
||||
fmode_t mode;
|
||||
unsigned long flags;
|
||||
#define F_RESETTING 0
|
||||
#define F_HAVEDIGITAL 1
|
||||
#define F_AUDIO_WRITE_INUSE 2
|
||||
#define F_WRITING 3
|
||||
#define F_WRITEBLOCK 4
|
||||
#define F_WRITEFLUSH 5
|
||||
#define F_AUDIO_READ_INUSE 6
|
||||
#define F_READING 7
|
||||
#define F_READBLOCK 8
|
||||
#define F_EXT_MIDI_INUSE 9
|
||||
#define F_HDR_MIDI_INUSE 10
|
||||
#define F_DISABLE_WRITE_NDELAY 11
|
||||
wait_queue_head_t writeblock;
|
||||
wait_queue_head_t readblock;
|
||||
wait_queue_head_t writeflush;
|
||||
spinlock_t lock;
|
||||
int nresets;
|
||||
unsigned long recsrc;
|
||||
int left_levels[32];
|
||||
int right_levels[32];
|
||||
int mixer_mod_count;
|
||||
int calibrate_signal;
|
||||
int play_sample_size, play_sample_rate, play_channels;
|
||||
int play_ndelay;
|
||||
int rec_sample_size, rec_sample_rate, rec_channels;
|
||||
int rec_ndelay;
|
||||
BYTE bCurrentMidiPatch;
|
||||
|
||||
/* Digital audio FIFOs */
|
||||
msnd_fifo DAPF, DARF;
|
||||
int fifosize;
|
||||
int last_playbank, last_recbank;
|
||||
|
||||
/* MIDI in callback */
|
||||
void (*midi_in_interrupt)(struct multisound_dev *);
|
||||
} multisound_dev_t;
|
||||
|
||||
#ifndef mdelay
|
||||
# define mdelay(a) udelay((a) * 1000)
|
||||
#endif
|
||||
|
||||
int msnd_register(multisound_dev_t *dev);
|
||||
void msnd_unregister(multisound_dev_t *dev);
|
||||
|
||||
void msnd_init_queue(void __iomem *, int start, int size);
|
||||
|
||||
void msnd_fifo_init(msnd_fifo *f);
|
||||
void msnd_fifo_free(msnd_fifo *f);
|
||||
int msnd_fifo_alloc(msnd_fifo *f, size_t n);
|
||||
void msnd_fifo_make_empty(msnd_fifo *f);
|
||||
int msnd_fifo_write_io(msnd_fifo *f, char __iomem *buf, size_t len);
|
||||
int msnd_fifo_read_io(msnd_fifo *f, char __iomem *buf, size_t len);
|
||||
int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len);
|
||||
int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len);
|
||||
|
||||
int msnd_send_dsp_cmd(multisound_dev_t *dev, BYTE cmd);
|
||||
int msnd_send_word(multisound_dev_t *dev, unsigned char high,
|
||||
unsigned char mid, unsigned char low);
|
||||
int msnd_upload_host(multisound_dev_t *dev, char *bin, int len);
|
||||
int msnd_enable_irq(multisound_dev_t *dev);
|
||||
int msnd_disable_irq(multisound_dev_t *dev);
|
||||
|
||||
#endif /* __MSND_H */
|
|
@ -1,3 +0,0 @@
|
|||
/* The work is in msnd_pinnacle.c, just define MSND_CLASSIC before it. */
|
||||
#define MSND_CLASSIC
|
||||
#include "msnd_pinnacle.c"
|
|
@ -1,185 +0,0 @@
|
|||
/*********************************************************************
|
||||
*
|
||||
* msnd_classic.h
|
||||
*
|
||||
* Turtle Beach MultiSound Sound Card Driver for Linux
|
||||
*
|
||||
* Some parts of this header file were derived from the Turtle Beach
|
||||
* MultiSound Driver Development Kit.
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Veliath
|
||||
* Copyright (C) 1993 Turtle Beach Systems, Inc.
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
********************************************************************/
|
||||
#ifndef __MSND_CLASSIC_H
|
||||
#define __MSND_CLASSIC_H
|
||||
|
||||
|
||||
#define DSP_NUMIO 0x10
|
||||
|
||||
#define HP_MEMM 0x08
|
||||
|
||||
#define HP_BITM 0x0E
|
||||
#define HP_WAIT 0x0D
|
||||
#define HP_DSPR 0x0A
|
||||
#define HP_PROR 0x0B
|
||||
#define HP_BLKS 0x0C
|
||||
|
||||
#define HPPRORESET_OFF 0
|
||||
#define HPPRORESET_ON 1
|
||||
|
||||
#define HPDSPRESET_OFF 0
|
||||
#define HPDSPRESET_ON 1
|
||||
|
||||
#define HPBLKSEL_0 0
|
||||
#define HPBLKSEL_1 1
|
||||
|
||||
#define HPWAITSTATE_0 0
|
||||
#define HPWAITSTATE_1 1
|
||||
|
||||
#define HPBITMODE_16 0
|
||||
#define HPBITMODE_8 1
|
||||
|
||||
#define HIDSP_INT_PLAY_UNDER 0x00
|
||||
#define HIDSP_INT_RECORD_OVER 0x01
|
||||
#define HIDSP_INPUT_CLIPPING 0x02
|
||||
#define HIDSP_MIDI_IN_OVER 0x10
|
||||
#define HIDSP_MIDI_OVERRUN_ERR 0x13
|
||||
|
||||
#define HDEXAR_CLEAR_PEAKS 1
|
||||
#define HDEXAR_IN_SET_POTS 2
|
||||
#define HDEXAR_AUX_SET_POTS 3
|
||||
#define HDEXAR_CAL_A_TO_D 4
|
||||
#define HDEXAR_RD_EXT_DSP_BITS 5
|
||||
|
||||
#define TIME_PRO_RESET_DONE 0x028A
|
||||
#define TIME_PRO_SYSEX 0x0040
|
||||
#define TIME_PRO_RESET 0x0032
|
||||
|
||||
#define AGND 0x01
|
||||
#define SIGNAL 0x02
|
||||
|
||||
#define EXT_DSP_BIT_DCAL 0x0001
|
||||
#define EXT_DSP_BIT_MIDI_CON 0x0002
|
||||
|
||||
#define BUFFSIZE 0x8000
|
||||
#define HOSTQ_SIZE 0x40
|
||||
|
||||
#define SRAM_CNTL_START 0x7F00
|
||||
#define SMA_STRUCT_START 0x7F40
|
||||
|
||||
#define DAP_BUFF_SIZE 0x2400
|
||||
#define DAR_BUFF_SIZE 0x2000
|
||||
|
||||
#define DAPQ_STRUCT_SIZE 0x10
|
||||
#define DARQ_STRUCT_SIZE 0x10
|
||||
#define DAPQ_BUFF_SIZE (3 * 0x10)
|
||||
#define DARQ_BUFF_SIZE (3 * 0x10)
|
||||
#define MODQ_BUFF_SIZE 0x400
|
||||
#define MIDQ_BUFF_SIZE 0x200
|
||||
#define DSPQ_BUFF_SIZE 0x40
|
||||
|
||||
#define DAPQ_DATA_BUFF 0x6C00
|
||||
#define DARQ_DATA_BUFF 0x6C30
|
||||
#define MODQ_DATA_BUFF 0x6C60
|
||||
#define MIDQ_DATA_BUFF 0x7060
|
||||
#define DSPQ_DATA_BUFF 0x7260
|
||||
|
||||
#define DAPQ_OFFSET SRAM_CNTL_START
|
||||
#define DARQ_OFFSET (SRAM_CNTL_START + 0x08)
|
||||
#define MODQ_OFFSET (SRAM_CNTL_START + 0x10)
|
||||
#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18)
|
||||
#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20)
|
||||
|
||||
#define MOP_SYNTH 0x10
|
||||
#define MOP_EXTOUT 0x32
|
||||
#define MOP_EXTTHRU 0x02
|
||||
#define MOP_OUTMASK 0x01
|
||||
|
||||
#define MIP_EXTIN 0x01
|
||||
#define MIP_SYNTH 0x00
|
||||
#define MIP_INMASK 0x32
|
||||
|
||||
/* Classic SMA Common Data */
|
||||
#define SMA_wCurrPlayBytes 0x0000
|
||||
#define SMA_wCurrRecordBytes 0x0002
|
||||
#define SMA_wCurrPlayVolLeft 0x0004
|
||||
#define SMA_wCurrPlayVolRight 0x0006
|
||||
#define SMA_wCurrInVolLeft 0x0008
|
||||
#define SMA_wCurrInVolRight 0x000a
|
||||
#define SMA_wUser_3 0x000c
|
||||
#define SMA_wUser_4 0x000e
|
||||
#define SMA_dwUser_5 0x0010
|
||||
#define SMA_dwUser_6 0x0014
|
||||
#define SMA_wUser_7 0x0018
|
||||
#define SMA_wReserved_A 0x001a
|
||||
#define SMA_wReserved_B 0x001c
|
||||
#define SMA_wReserved_C 0x001e
|
||||
#define SMA_wReserved_D 0x0020
|
||||
#define SMA_wReserved_E 0x0022
|
||||
#define SMA_wReserved_F 0x0024
|
||||
#define SMA_wReserved_G 0x0026
|
||||
#define SMA_wReserved_H 0x0028
|
||||
#define SMA_wCurrDSPStatusFlags 0x002a
|
||||
#define SMA_wCurrHostStatusFlags 0x002c
|
||||
#define SMA_wCurrInputTagBits 0x002e
|
||||
#define SMA_wCurrLeftPeak 0x0030
|
||||
#define SMA_wCurrRightPeak 0x0032
|
||||
#define SMA_wExtDSPbits 0x0034
|
||||
#define SMA_bExtHostbits 0x0036
|
||||
#define SMA_bBoardLevel 0x0037
|
||||
#define SMA_bInPotPosRight 0x0038
|
||||
#define SMA_bInPotPosLeft 0x0039
|
||||
#define SMA_bAuxPotPosRight 0x003a
|
||||
#define SMA_bAuxPotPosLeft 0x003b
|
||||
#define SMA_wCurrMastVolLeft 0x003c
|
||||
#define SMA_wCurrMastVolRight 0x003e
|
||||
#define SMA_bUser_12 0x0040
|
||||
#define SMA_bUser_13 0x0041
|
||||
#define SMA_wUser_14 0x0042
|
||||
#define SMA_wUser_15 0x0044
|
||||
#define SMA_wCalFreqAtoD 0x0046
|
||||
#define SMA_wUser_16 0x0048
|
||||
#define SMA_wUser_17 0x004a
|
||||
#define SMA__size 0x004c
|
||||
|
||||
#ifdef HAVE_DSPCODEH
|
||||
# include "msndperm.c"
|
||||
# include "msndinit.c"
|
||||
# define PERMCODE msndperm
|
||||
# define INITCODE msndinit
|
||||
# define PERMCODESIZE sizeof(msndperm)
|
||||
# define INITCODESIZE sizeof(msndinit)
|
||||
#else
|
||||
# ifndef CONFIG_MSNDCLAS_INIT_FILE
|
||||
# define CONFIG_MSNDCLAS_INIT_FILE \
|
||||
"/etc/sound/msndinit.bin"
|
||||
# endif
|
||||
# ifndef CONFIG_MSNDCLAS_PERM_FILE
|
||||
# define CONFIG_MSNDCLAS_PERM_FILE \
|
||||
"/etc/sound/msndperm.bin"
|
||||
# endif
|
||||
# define PERMCODEFILE CONFIG_MSNDCLAS_PERM_FILE
|
||||
# define INITCODEFILE CONFIG_MSNDCLAS_INIT_FILE
|
||||
# define PERMCODE dspini
|
||||
# define INITCODE permini
|
||||
# define PERMCODESIZE sizeof_dspini
|
||||
# define INITCODESIZE sizeof_permini
|
||||
#endif
|
||||
#define LONGNAME "MultiSound (Classic/Monterey/Tahiti)"
|
||||
|
||||
#endif /* __MSND_CLASSIC_H */
|
File diff suppressed because it is too large
Load diff
|
@ -1,246 +0,0 @@
|
|||
/*********************************************************************
|
||||
*
|
||||
* msnd_pinnacle.h
|
||||
*
|
||||
* Turtle Beach MultiSound Sound Card Driver for Linux
|
||||
*
|
||||
* Some parts of this header file were derived from the Turtle Beach
|
||||
* MultiSound Driver Development Kit.
|
||||
*
|
||||
* Copyright (C) 1998 Andrew Veliath
|
||||
* Copyright (C) 1993 Turtle Beach Systems, Inc.
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
********************************************************************/
|
||||
#ifndef __MSND_PINNACLE_H
|
||||
#define __MSND_PINNACLE_H
|
||||
|
||||
|
||||
#define DSP_NUMIO 0x08
|
||||
|
||||
#define IREG_LOGDEVICE 0x07
|
||||
#define IREG_ACTIVATE 0x30
|
||||
#define LD_ACTIVATE 0x01
|
||||
#define LD_DISACTIVATE 0x00
|
||||
#define IREG_EECONTROL 0x3F
|
||||
#define IREG_MEMBASEHI 0x40
|
||||
#define IREG_MEMBASELO 0x41
|
||||
#define IREG_MEMCONTROL 0x42
|
||||
#define IREG_MEMRANGEHI 0x43
|
||||
#define IREG_MEMRANGELO 0x44
|
||||
#define MEMTYPE_8BIT 0x00
|
||||
#define MEMTYPE_16BIT 0x02
|
||||
#define MEMTYPE_RANGE 0x00
|
||||
#define MEMTYPE_HIADDR 0x01
|
||||
#define IREG_IO0_BASEHI 0x60
|
||||
#define IREG_IO0_BASELO 0x61
|
||||
#define IREG_IO1_BASEHI 0x62
|
||||
#define IREG_IO1_BASELO 0x63
|
||||
#define IREG_IRQ_NUMBER 0x70
|
||||
#define IREG_IRQ_TYPE 0x71
|
||||
#define IRQTYPE_HIGH 0x02
|
||||
#define IRQTYPE_LOW 0x00
|
||||
#define IRQTYPE_LEVEL 0x01
|
||||
#define IRQTYPE_EDGE 0x00
|
||||
|
||||
#define HP_DSPR 0x04
|
||||
#define HP_BLKS 0x04
|
||||
|
||||
#define HPDSPRESET_OFF 2
|
||||
#define HPDSPRESET_ON 0
|
||||
|
||||
#define HPBLKSEL_0 2
|
||||
#define HPBLKSEL_1 3
|
||||
|
||||
#define HIMT_DAT_OFF 0x03
|
||||
|
||||
#define HIDSP_PLAY_UNDER 0x00
|
||||
#define HIDSP_INT_PLAY_UNDER 0x01
|
||||
#define HIDSP_SSI_TX_UNDER 0x02
|
||||
#define HIDSP_RECQ_OVERFLOW 0x08
|
||||
#define HIDSP_INT_RECORD_OVER 0x09
|
||||
#define HIDSP_SSI_RX_OVERFLOW 0x0a
|
||||
|
||||
#define HIDSP_MIDI_IN_OVER 0x10
|
||||
|
||||
#define HIDSP_MIDI_FRAME_ERR 0x11
|
||||
#define HIDSP_MIDI_PARITY_ERR 0x12
|
||||
#define HIDSP_MIDI_OVERRUN_ERR 0x13
|
||||
|
||||
#define HIDSP_INPUT_CLIPPING 0x20
|
||||
#define HIDSP_MIX_CLIPPING 0x30
|
||||
#define HIDSP_DAT_IN_OFF 0x21
|
||||
|
||||
#define HDEXAR_SET_ANA_IN 0
|
||||
#define HDEXAR_CLEAR_PEAKS 1
|
||||
#define HDEXAR_IN_SET_POTS 2
|
||||
#define HDEXAR_AUX_SET_POTS 3
|
||||
#define HDEXAR_CAL_A_TO_D 4
|
||||
#define HDEXAR_RD_EXT_DSP_BITS 5
|
||||
|
||||
#define HDEXAR_SET_SYNTH_IN 4
|
||||
#define HDEXAR_READ_DAT_IN 5
|
||||
#define HDEXAR_MIC_SET_POTS 6
|
||||
#define HDEXAR_SET_DAT_IN 7
|
||||
|
||||
#define HDEXAR_SET_SYNTH_48 8
|
||||
#define HDEXAR_SET_SYNTH_44 9
|
||||
|
||||
#define TIME_PRO_RESET_DONE 0x028A
|
||||
#define TIME_PRO_SYSEX 0x001E
|
||||
#define TIME_PRO_RESET 0x0032
|
||||
|
||||
#define AGND 0x01
|
||||
#define SIGNAL 0x02
|
||||
|
||||
#define EXT_DSP_BIT_DCAL 0x0001
|
||||
#define EXT_DSP_BIT_MIDI_CON 0x0002
|
||||
|
||||
#define BUFFSIZE 0x8000
|
||||
#define HOSTQ_SIZE 0x40
|
||||
|
||||
#define SRAM_CNTL_START 0x7F00
|
||||
#define SMA_STRUCT_START 0x7F40
|
||||
|
||||
#define DAP_BUFF_SIZE 0x2400
|
||||
#define DAR_BUFF_SIZE 0x2000
|
||||
|
||||
#define DAPQ_STRUCT_SIZE 0x10
|
||||
#define DARQ_STRUCT_SIZE 0x10
|
||||
#define DAPQ_BUFF_SIZE (3 * 0x10)
|
||||
#define DARQ_BUFF_SIZE (3 * 0x10)
|
||||
#define MODQ_BUFF_SIZE 0x400
|
||||
#define MIDQ_BUFF_SIZE 0x800
|
||||
#define DSPQ_BUFF_SIZE 0x5A0
|
||||
|
||||
#define DAPQ_DATA_BUFF 0x6C00
|
||||
#define DARQ_DATA_BUFF 0x6C30
|
||||
#define MODQ_DATA_BUFF 0x6C60
|
||||
#define MIDQ_DATA_BUFF 0x7060
|
||||
#define DSPQ_DATA_BUFF 0x7860
|
||||
|
||||
#define DAPQ_OFFSET SRAM_CNTL_START
|
||||
#define DARQ_OFFSET (SRAM_CNTL_START + 0x08)
|
||||
#define MODQ_OFFSET (SRAM_CNTL_START + 0x10)
|
||||
#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18)
|
||||
#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20)
|
||||
|
||||
#define MOP_WAVEHDR 0
|
||||
#define MOP_EXTOUT 1
|
||||
#define MOP_HWINIT 0xfe
|
||||
#define MOP_NONE 0xff
|
||||
#define MOP_MAX 1
|
||||
|
||||
#define MIP_EXTIN 0
|
||||
#define MIP_WAVEHDR 1
|
||||
#define MIP_HWINIT 0xfe
|
||||
#define MIP_MAX 1
|
||||
|
||||
/* Pinnacle/Fiji SMA Common Data */
|
||||
#define SMA_wCurrPlayBytes 0x0000
|
||||
#define SMA_wCurrRecordBytes 0x0002
|
||||
#define SMA_wCurrPlayVolLeft 0x0004
|
||||
#define SMA_wCurrPlayVolRight 0x0006
|
||||
#define SMA_wCurrInVolLeft 0x0008
|
||||
#define SMA_wCurrInVolRight 0x000a
|
||||
#define SMA_wCurrMHdrVolLeft 0x000c
|
||||
#define SMA_wCurrMHdrVolRight 0x000e
|
||||
#define SMA_dwCurrPlayPitch 0x0010
|
||||
#define SMA_dwCurrPlayRate 0x0014
|
||||
#define SMA_wCurrMIDIIOPatch 0x0018
|
||||
#define SMA_wCurrPlayFormat 0x001a
|
||||
#define SMA_wCurrPlaySampleSize 0x001c
|
||||
#define SMA_wCurrPlayChannels 0x001e
|
||||
#define SMA_wCurrPlaySampleRate 0x0020
|
||||
#define SMA_wCurrRecordFormat 0x0022
|
||||
#define SMA_wCurrRecordSampleSize 0x0024
|
||||
#define SMA_wCurrRecordChannels 0x0026
|
||||
#define SMA_wCurrRecordSampleRate 0x0028
|
||||
#define SMA_wCurrDSPStatusFlags 0x002a
|
||||
#define SMA_wCurrHostStatusFlags 0x002c
|
||||
#define SMA_wCurrInputTagBits 0x002e
|
||||
#define SMA_wCurrLeftPeak 0x0030
|
||||
#define SMA_wCurrRightPeak 0x0032
|
||||
#define SMA_bMicPotPosLeft 0x0034
|
||||
#define SMA_bMicPotPosRight 0x0035
|
||||
#define SMA_bMicPotMaxLeft 0x0036
|
||||
#define SMA_bMicPotMaxRight 0x0037
|
||||
#define SMA_bInPotPosLeft 0x0038
|
||||
#define SMA_bInPotPosRight 0x0039
|
||||
#define SMA_bAuxPotPosLeft 0x003a
|
||||
#define SMA_bAuxPotPosRight 0x003b
|
||||
#define SMA_bInPotMaxLeft 0x003c
|
||||
#define SMA_bInPotMaxRight 0x003d
|
||||
#define SMA_bAuxPotMaxLeft 0x003e
|
||||
#define SMA_bAuxPotMaxRight 0x003f
|
||||
#define SMA_bInPotMaxMethod 0x0040
|
||||
#define SMA_bAuxPotMaxMethod 0x0041
|
||||
#define SMA_wCurrMastVolLeft 0x0042
|
||||
#define SMA_wCurrMastVolRight 0x0044
|
||||
#define SMA_wCalFreqAtoD 0x0046
|
||||
#define SMA_wCurrAuxVolLeft 0x0048
|
||||
#define SMA_wCurrAuxVolRight 0x004a
|
||||
#define SMA_wCurrPlay1VolLeft 0x004c
|
||||
#define SMA_wCurrPlay1VolRight 0x004e
|
||||
#define SMA_wCurrPlay2VolLeft 0x0050
|
||||
#define SMA_wCurrPlay2VolRight 0x0052
|
||||
#define SMA_wCurrPlay3VolLeft 0x0054
|
||||
#define SMA_wCurrPlay3VolRight 0x0056
|
||||
#define SMA_wCurrPlay4VolLeft 0x0058
|
||||
#define SMA_wCurrPlay4VolRight 0x005a
|
||||
#define SMA_wCurrPlay1PeakLeft 0x005c
|
||||
#define SMA_wCurrPlay1PeakRight 0x005e
|
||||
#define SMA_wCurrPlay2PeakLeft 0x0060
|
||||
#define SMA_wCurrPlay2PeakRight 0x0062
|
||||
#define SMA_wCurrPlay3PeakLeft 0x0064
|
||||
#define SMA_wCurrPlay3PeakRight 0x0066
|
||||
#define SMA_wCurrPlay4PeakLeft 0x0068
|
||||
#define SMA_wCurrPlay4PeakRight 0x006a
|
||||
#define SMA_wCurrPlayPeakLeft 0x006c
|
||||
#define SMA_wCurrPlayPeakRight 0x006e
|
||||
#define SMA_wCurrDATSR 0x0070
|
||||
#define SMA_wCurrDATRXCHNL 0x0072
|
||||
#define SMA_wCurrDATTXCHNL 0x0074
|
||||
#define SMA_wCurrDATRXRate 0x0076
|
||||
#define SMA_dwDSPPlayCount 0x0078
|
||||
#define SMA__size 0x007c
|
||||
|
||||
#ifdef HAVE_DSPCODEH
|
||||
# include "pndsperm.c"
|
||||
# include "pndspini.c"
|
||||
# define PERMCODE pndsperm
|
||||
# define INITCODE pndspini
|
||||
# define PERMCODESIZE sizeof(pndsperm)
|
||||
# define INITCODESIZE sizeof(pndspini)
|
||||
#else
|
||||
# ifndef CONFIG_MSNDPIN_INIT_FILE
|
||||
# define CONFIG_MSNDPIN_INIT_FILE \
|
||||
"/etc/sound/pndspini.bin"
|
||||
# endif
|
||||
# ifndef CONFIG_MSNDPIN_PERM_FILE
|
||||
# define CONFIG_MSNDPIN_PERM_FILE \
|
||||
"/etc/sound/pndsperm.bin"
|
||||
# endif
|
||||
# define PERMCODEFILE CONFIG_MSNDPIN_PERM_FILE
|
||||
# define INITCODEFILE CONFIG_MSNDPIN_INIT_FILE
|
||||
# define PERMCODE dspini
|
||||
# define INITCODE permini
|
||||
# define PERMCODESIZE sizeof_dspini
|
||||
# define INITCODESIZE sizeof_permini
|
||||
#endif
|
||||
#define LONGNAME "MultiSound (Pinnacle/Fiji)"
|
||||
|
||||
#endif /* __MSND_PINNACLE_H */
|
1255
sound/oss/opl3.c
1255
sound/oss/opl3.c
File diff suppressed because it is too large
Load diff
|
@ -1,246 +0,0 @@
|
|||
/*
|
||||
* opl3_hw.h - Definitions of the OPL-3 registers
|
||||
*
|
||||
*
|
||||
* Copyright (C) by Hannu Savolainen 1993-1997
|
||||
*
|
||||
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
|
||||
* Version 2 (June 1991). See the "COPYING" file distributed with this software
|
||||
* for more info.
|
||||
*
|
||||
*
|
||||
* The OPL-3 mode is switched on by writing 0x01, to the offset 5
|
||||
* of the right side.
|
||||
*
|
||||
* Another special register at the right side is at offset 4. It contains
|
||||
* a bit mask defining which voices are used as 4 OP voices.
|
||||
*
|
||||
* The percussive mode is implemented in the left side only.
|
||||
*
|
||||
* With the above exceptions the both sides can be operated independently.
|
||||
*
|
||||
* A 4 OP voice can be created by setting the corresponding
|
||||
* bit at offset 4 of the right side.
|
||||
*
|
||||
* For example setting the rightmost bit (0x01) changes the
|
||||
* first voice on the right side to the 4 OP mode. The fourth
|
||||
* voice is made inaccessible.
|
||||
*
|
||||
* If a voice is set to the 2 OP mode, it works like 2 OP modes
|
||||
* of the original YM3812 (AdLib). In addition the voice can
|
||||
* be connected the left, right or both stereo channels. It can
|
||||
* even be left unconnected. This works with 4 OP voices also.
|
||||
*
|
||||
* The stereo connection bits are located in the FEEDBACK_CONNECTION
|
||||
* register of the voice (0xC0-0xC8). In 4 OP voices these bits are
|
||||
* in the second half of the voice.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Register numbers for the global registers
|
||||
*/
|
||||
|
||||
#define TEST_REGISTER 0x01
|
||||
#define ENABLE_WAVE_SELECT 0x20
|
||||
|
||||
#define TIMER1_REGISTER 0x02
|
||||
#define TIMER2_REGISTER 0x03
|
||||
#define TIMER_CONTROL_REGISTER 0x04 /* Left side */
|
||||
#define IRQ_RESET 0x80
|
||||
#define TIMER1_MASK 0x40
|
||||
#define TIMER2_MASK 0x20
|
||||
#define TIMER1_START 0x01
|
||||
#define TIMER2_START 0x02
|
||||
|
||||
#define CONNECTION_SELECT_REGISTER 0x04 /* Right side */
|
||||
#define RIGHT_4OP_0 0x01
|
||||
#define RIGHT_4OP_1 0x02
|
||||
#define RIGHT_4OP_2 0x04
|
||||
#define LEFT_4OP_0 0x08
|
||||
#define LEFT_4OP_1 0x10
|
||||
#define LEFT_4OP_2 0x20
|
||||
|
||||
#define OPL3_MODE_REGISTER 0x05 /* Right side */
|
||||
#define OPL3_ENABLE 0x01
|
||||
#define OPL4_ENABLE 0x02
|
||||
|
||||
#define KBD_SPLIT_REGISTER 0x08 /* Left side */
|
||||
#define COMPOSITE_SINE_WAVE_MODE 0x80 /* Don't use with OPL-3? */
|
||||
#define KEYBOARD_SPLIT 0x40
|
||||
|
||||
#define PERCOSSION_REGISTER 0xbd /* Left side only */
|
||||
#define TREMOLO_DEPTH 0x80
|
||||
#define VIBRATO_DEPTH 0x40
|
||||
#define PERCOSSION_ENABLE 0x20
|
||||
#define BASSDRUM_ON 0x10
|
||||
#define SNAREDRUM_ON 0x08
|
||||
#define TOMTOM_ON 0x04
|
||||
#define CYMBAL_ON 0x02
|
||||
#define HIHAT_ON 0x01
|
||||
|
||||
/*
|
||||
* Offsets to the register banks for operators. To get the
|
||||
* register number just add the operator offset to the bank offset
|
||||
*
|
||||
* AM/VIB/EG/KSR/Multiple (0x20 to 0x35)
|
||||
*/
|
||||
#define AM_VIB 0x20
|
||||
#define TREMOLO_ON 0x80
|
||||
#define VIBRATO_ON 0x40
|
||||
#define SUSTAIN_ON 0x20
|
||||
#define KSR 0x10 /* Key scaling rate */
|
||||
#define MULTIPLE_MASK 0x0f /* Frequency multiplier */
|
||||
|
||||
/*
|
||||
* KSL/Total level (0x40 to 0x55)
|
||||
*/
|
||||
#define KSL_LEVEL 0x40
|
||||
#define KSL_MASK 0xc0 /* Envelope scaling bits */
|
||||
#define TOTAL_LEVEL_MASK 0x3f /* Strength (volume) of OP */
|
||||
|
||||
/*
|
||||
* Attack / Decay rate (0x60 to 0x75)
|
||||
*/
|
||||
#define ATTACK_DECAY 0x60
|
||||
#define ATTACK_MASK 0xf0
|
||||
#define DECAY_MASK 0x0f
|
||||
|
||||
/*
|
||||
* Sustain level / Release rate (0x80 to 0x95)
|
||||
*/
|
||||
#define SUSTAIN_RELEASE 0x80
|
||||
#define SUSTAIN_MASK 0xf0
|
||||
#define RELEASE_MASK 0x0f
|
||||
|
||||
/*
|
||||
* Wave select (0xE0 to 0xF5)
|
||||
*/
|
||||
#define WAVE_SELECT 0xe0
|
||||
|
||||
/*
|
||||
* Offsets to the register banks for voices. Just add to the
|
||||
* voice number to get the register number.
|
||||
*
|
||||
* F-Number low bits (0xA0 to 0xA8).
|
||||
*/
|
||||
#define FNUM_LOW 0xa0
|
||||
|
||||
/*
|
||||
* F-number high bits / Key on / Block (octave) (0xB0 to 0xB8)
|
||||
*/
|
||||
#define KEYON_BLOCK 0xb0
|
||||
#define KEYON_BIT 0x20
|
||||
#define BLOCKNUM_MASK 0x1c
|
||||
#define FNUM_HIGH_MASK 0x03
|
||||
|
||||
/*
|
||||
* Feedback / Connection (0xc0 to 0xc8)
|
||||
*
|
||||
* These registers have two new bits when the OPL-3 mode
|
||||
* is selected. These bits controls connecting the voice
|
||||
* to the stereo channels. For 4 OP voices this bit is
|
||||
* defined in the second half of the voice (add 3 to the
|
||||
* register offset).
|
||||
*
|
||||
* For 4 OP voices the connection bit is used in the
|
||||
* both halves (gives 4 ways to connect the operators).
|
||||
*/
|
||||
#define FEEDBACK_CONNECTION 0xc0
|
||||
#define FEEDBACK_MASK 0x0e /* Valid just for 1st OP of a voice */
|
||||
#define CONNECTION_BIT 0x01
|
||||
/*
|
||||
* In the 4 OP mode there is four possible configurations how the
|
||||
* operators can be connected together (in 2 OP modes there is just
|
||||
* AM or FM). The 4 OP connection mode is defined by the rightmost
|
||||
* bit of the FEEDBACK_CONNECTION (0xC0-0xC8) on the both halves.
|
||||
*
|
||||
* First half Second half Mode
|
||||
*
|
||||
* +---+
|
||||
* v |
|
||||
* 0 0 >+-1-+--2--3--4-->
|
||||
*
|
||||
*
|
||||
*
|
||||
* +---+
|
||||
* | |
|
||||
* 0 1 >+-1-+--2-+
|
||||
* |->
|
||||
* >--3----4-+
|
||||
*
|
||||
* +---+
|
||||
* | |
|
||||
* 1 0 >+-1-+-----+
|
||||
* |->
|
||||
* >--2--3--4-+
|
||||
*
|
||||
* +---+
|
||||
* | |
|
||||
* 1 1 >+-1-+--+
|
||||
* |
|
||||
* >--2--3-+->
|
||||
* |
|
||||
* >--4----+
|
||||
*/
|
||||
#define STEREO_BITS 0x30 /* OPL-3 only */
|
||||
#define VOICE_TO_LEFT 0x10
|
||||
#define VOICE_TO_RIGHT 0x20
|
||||
|
||||
/*
|
||||
* Definition table for the physical voices
|
||||
*/
|
||||
|
||||
struct physical_voice_info {
|
||||
unsigned char voice_num;
|
||||
unsigned char voice_mode; /* 0=unavailable, 2=2 OP, 4=4 OP */
|
||||
unsigned short ioaddr; /* I/O port (left or right side) */
|
||||
unsigned char op[4]; /* Operator offsets */
|
||||
};
|
||||
|
||||
/*
|
||||
* There is 18 possible 2 OP voices
|
||||
* (9 in the left and 9 in the right).
|
||||
* The first OP is the modulator and 2nd is the carrier.
|
||||
*
|
||||
* The first three voices in the both sides may be connected
|
||||
* with another voice to a 4 OP voice. For example voice 0
|
||||
* can be connected with voice 3. The operators of voice 3 are
|
||||
* used as operators 3 and 4 of the new 4 OP voice.
|
||||
* In this case the 2 OP voice number 0 is the 'first half' and
|
||||
* voice 3 is the second.
|
||||
*/
|
||||
|
||||
#define USE_LEFT 0
|
||||
#define USE_RIGHT 1
|
||||
|
||||
static struct physical_voice_info pv_map[18] =
|
||||
{
|
||||
/* No Mode Side OP1 OP2 OP3 OP4 */
|
||||
/* --------------------------------------------------- */
|
||||
{ 0, 2, USE_LEFT, {0x00, 0x03, 0x08, 0x0b}},
|
||||
{ 1, 2, USE_LEFT, {0x01, 0x04, 0x09, 0x0c}},
|
||||
{ 2, 2, USE_LEFT, {0x02, 0x05, 0x0a, 0x0d}},
|
||||
|
||||
{ 3, 2, USE_LEFT, {0x08, 0x0b, 0x00, 0x00}},
|
||||
{ 4, 2, USE_LEFT, {0x09, 0x0c, 0x00, 0x00}},
|
||||
{ 5, 2, USE_LEFT, {0x0a, 0x0d, 0x00, 0x00}},
|
||||
|
||||
{ 6, 2, USE_LEFT, {0x10, 0x13, 0x00, 0x00}}, /* Used by percussive voices */
|
||||
{ 7, 2, USE_LEFT, {0x11, 0x14, 0x00, 0x00}}, /* if the percussive mode */
|
||||
{ 8, 2, USE_LEFT, {0x12, 0x15, 0x00, 0x00}}, /* is selected */
|
||||
|
||||
{ 0, 2, USE_RIGHT, {0x00, 0x03, 0x08, 0x0b}},
|
||||
{ 1, 2, USE_RIGHT, {0x01, 0x04, 0x09, 0x0c}},
|
||||
{ 2, 2, USE_RIGHT, {0x02, 0x05, 0x0a, 0x0d}},
|
||||
|
||||
{ 3, 2, USE_RIGHT, {0x08, 0x0b, 0x00, 0x00}},
|
||||
{ 4, 2, USE_RIGHT, {0x09, 0x0c, 0x00, 0x00}},
|
||||
{ 5, 2, USE_RIGHT, {0x0a, 0x0d, 0x00, 0x00}},
|
||||
|
||||
{ 6, 2, USE_RIGHT, {0x10, 0x13, 0x00, 0x00}},
|
||||
{ 7, 2, USE_RIGHT, {0x11, 0x14, 0x00, 0x00}},
|
||||
{ 8, 2, USE_RIGHT, {0x12, 0x15, 0x00, 0x00}}
|
||||
};
|
||||
/*
|
||||
* DMA buffer calls
|
||||
*/
|
|
@ -1,45 +0,0 @@
|
|||
#define ALLOW_SELECT
|
||||
#undef NO_INLINE_ASM
|
||||
#define SHORT_BANNERS
|
||||
#define MANUAL_PNP
|
||||
#undef DO_TIMINGS
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/string.h>
|
||||
#include <linux/fs.h>
|
||||
#include <asm/dma.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/param.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <asm/page.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/pci.h>
|
||||
#endif
|
||||
|
||||
#include <linux/soundcard.h>
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
extern int sound_alloc_dma(int chn, char *deviceID);
|
||||
extern int sound_open_dma(int chn, char *deviceID);
|
||||
extern void sound_free_dma(int chn);
|
||||
extern void sound_close_dma(int chn);
|
||||
|
||||
extern void reprogram_timer(void);
|
||||
|
||||
#define USE_AUTOINIT_DMA
|
||||
|
||||
extern void *sound_mem_blocks[1024];
|
||||
extern int sound_nblocks;
|
||||
|
||||
#undef PSEUDO_DMA_AUTOINIT
|
||||
#define ALLOW_BUFFER_MAPPING
|
||||
|
||||
extern const struct file_operations oss_sound_fops;
|
|
@ -1,20 +0,0 @@
|
|||
|
||||
/* From pas_card.c */
|
||||
int pas_set_intr(int mask);
|
||||
int pas_remove_intr(int mask);
|
||||
unsigned char pas_read(int ioaddr);
|
||||
void pas_write(unsigned char data, int ioaddr);
|
||||
|
||||
/* From pas_audio.c */
|
||||
void pas_pcm_interrupt(unsigned char status, int cause);
|
||||
void pas_pcm_init(struct address_info *hw_config);
|
||||
|
||||
/* From pas_mixer.c */
|
||||
int pas_init_mixer(void);
|
||||
|
||||
/* From pas_midi.c */
|
||||
void pas_midi_init(void);
|
||||
void pas_midi_interrupt(void);
|
||||
|
||||
/* From pas2_mixer.c*/
|
||||
void mix_write(unsigned char data, int ioaddr);
|
|
@ -1,458 +0,0 @@
|
|||
/*
|
||||
* sound/oss/pas2_card.c
|
||||
*
|
||||
* Detection routine for the Pro Audio Spectrum cards.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include "sound_config.h"
|
||||
|
||||
#include "pas2.h"
|
||||
#include "sb.h"
|
||||
|
||||
static unsigned char dma_bits[] = {
|
||||
4, 1, 2, 3, 0, 5, 6, 7
|
||||
};
|
||||
|
||||
static unsigned char irq_bits[] = {
|
||||
0, 0, 1, 2, 3, 4, 5, 6, 0, 1, 7, 8, 9, 0, 10, 11
|
||||
};
|
||||
|
||||
static unsigned char sb_irq_bits[] = {
|
||||
0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x00, 0x20,
|
||||
0x00, 0x08, 0x28, 0x30, 0x38, 0, 0
|
||||
};
|
||||
|
||||
static unsigned char sb_dma_bits[] = {
|
||||
0x00, 0x40, 0x80, 0xC0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* The Address Translation code is used to convert I/O register addresses to
|
||||
* be relative to the given base -register
|
||||
*/
|
||||
|
||||
int pas_translate_code = 0;
|
||||
static int pas_intr_mask;
|
||||
static int pas_irq;
|
||||
static int pas_sb_base;
|
||||
DEFINE_SPINLOCK(pas_lock);
|
||||
#ifndef CONFIG_PAS_JOYSTICK
|
||||
static bool joystick;
|
||||
#else
|
||||
static bool joystick = 1;
|
||||
#endif
|
||||
#ifdef SYMPHONY_PAS
|
||||
static bool symphony = 1;
|
||||
#else
|
||||
static bool symphony;
|
||||
#endif
|
||||
#ifdef BROKEN_BUS_CLOCK
|
||||
static bool broken_bus_clock = 1;
|
||||
#else
|
||||
static bool broken_bus_clock;
|
||||
#endif
|
||||
|
||||
static struct address_info cfg;
|
||||
static struct address_info cfg2;
|
||||
|
||||
char pas_model = 0;
|
||||
static char *pas_model_names[] = {
|
||||
"",
|
||||
"Pro AudioSpectrum+",
|
||||
"CDPC",
|
||||
"Pro AudioSpectrum 16",
|
||||
"Pro AudioSpectrum 16D"
|
||||
};
|
||||
|
||||
/*
|
||||
* pas_read() and pas_write() are equivalents of inb and outb
|
||||
* These routines perform the I/O address translation required
|
||||
* to support other than the default base address
|
||||
*/
|
||||
|
||||
unsigned char pas_read(int ioaddr)
|
||||
{
|
||||
return inb(ioaddr + pas_translate_code);
|
||||
}
|
||||
|
||||
void pas_write(unsigned char data, int ioaddr)
|
||||
{
|
||||
outb((data), ioaddr + pas_translate_code);
|
||||
}
|
||||
|
||||
/******************* Begin of the Interrupt Handler ********************/
|
||||
|
||||
static irqreturn_t pasintr(int irq, void *dev_id)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = pas_read(0x0B89);
|
||||
pas_write(status, 0x0B89); /* Clear interrupt */
|
||||
|
||||
if (status & 0x08)
|
||||
{
|
||||
pas_pcm_interrupt(status, 1);
|
||||
status &= ~0x08;
|
||||
}
|
||||
if (status & 0x10)
|
||||
{
|
||||
pas_midi_interrupt();
|
||||
status &= ~0x10;
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int pas_set_intr(int mask)
|
||||
{
|
||||
if (!mask)
|
||||
return 0;
|
||||
|
||||
pas_intr_mask |= mask;
|
||||
|
||||
pas_write(pas_intr_mask, 0x0B8B);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pas_remove_intr(int mask)
|
||||
{
|
||||
if (!mask)
|
||||
return 0;
|
||||
|
||||
pas_intr_mask &= ~mask;
|
||||
pas_write(pas_intr_mask, 0x0B8B);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************* End of the Interrupt handler **********************/
|
||||
|
||||
/******************* Begin of the Initialization Code ******************/
|
||||
|
||||
static int __init config_pas_hw(struct address_info *hw_config)
|
||||
{
|
||||
char ok = 1;
|
||||
unsigned int_ptrs; /* scsi/sound interrupt pointers */
|
||||
|
||||
pas_irq = hw_config->irq;
|
||||
|
||||
pas_write(0x00, 0x0B8B);
|
||||
pas_write(0x36, 0x138B);
|
||||
pas_write(0x36, 0x1388);
|
||||
pas_write(0, 0x1388);
|
||||
pas_write(0x74, 0x138B);
|
||||
pas_write(0x74, 0x1389);
|
||||
pas_write(0, 0x1389);
|
||||
|
||||
pas_write(0x80 | 0x40 | 0x20 | 1, 0x0B8A);
|
||||
pas_write(0x80 | 0x20 | 0x10 | 0x08 | 0x01, 0xF8A);
|
||||
pas_write(0x01 | 0x02 | 0x04 | 0x10 /*
|
||||
* |
|
||||
* 0x80
|
||||
*/ , 0xB88);
|
||||
|
||||
pas_write(0x80 | (joystick ? 0x40 : 0), 0xF388);
|
||||
|
||||
if (pas_irq < 0 || pas_irq > 15)
|
||||
{
|
||||
printk(KERN_ERR "PAS16: Invalid IRQ %d", pas_irq);
|
||||
hw_config->irq=-1;
|
||||
ok = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int_ptrs = pas_read(0xF38A);
|
||||
int_ptrs = (int_ptrs & 0xf0) | irq_bits[pas_irq];
|
||||
pas_write(int_ptrs, 0xF38A);
|
||||
if (!irq_bits[pas_irq])
|
||||
{
|
||||
printk(KERN_ERR "PAS16: Invalid IRQ %d", pas_irq);
|
||||
hw_config->irq=-1;
|
||||
ok = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (request_irq(pas_irq, pasintr, 0, "PAS16",hw_config) < 0) {
|
||||
printk(KERN_ERR "PAS16: Cannot allocate IRQ %d\n",pas_irq);
|
||||
hw_config->irq=-1;
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hw_config->dma < 0 || hw_config->dma > 7)
|
||||
{
|
||||
printk(KERN_ERR "PAS16: Invalid DMA selection %d", hw_config->dma);
|
||||
hw_config->dma=-1;
|
||||
ok = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pas_write(dma_bits[hw_config->dma], 0xF389);
|
||||
if (!dma_bits[hw_config->dma])
|
||||
{
|
||||
printk(KERN_ERR "PAS16: Invalid DMA selection %d", hw_config->dma);
|
||||
hw_config->dma=-1;
|
||||
ok = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sound_alloc_dma(hw_config->dma, "PAS16"))
|
||||
{
|
||||
printk(KERN_ERR "pas2_card.c: Can't allocate DMA channel\n");
|
||||
hw_config->dma=-1;
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This fixes the timing problems of the PAS due to the Symphony chipset
|
||||
* as per Media Vision. Only define this if your PAS doesn't work correctly.
|
||||
*/
|
||||
|
||||
if(symphony)
|
||||
{
|
||||
outb((0x05), 0xa8);
|
||||
outb((0x60), 0xa9);
|
||||
}
|
||||
|
||||
if(broken_bus_clock)
|
||||
pas_write(0x01 | 0x10 | 0x20 | 0x04, 0x8388);
|
||||
else
|
||||
/*
|
||||
* pas_write(0x01, 0x8388);
|
||||
*/
|
||||
pas_write(0x01 | 0x10 | 0x20, 0x8388);
|
||||
|
||||
pas_write(0x18, 0x838A); /* ??? */
|
||||
pas_write(0x20 | 0x01, 0x0B8A); /* Mute off, filter = 17.897 kHz */
|
||||
pas_write(8, 0xBF8A);
|
||||
|
||||
mix_write(0x80 | 5, 0x078B);
|
||||
mix_write(5, 0x078B);
|
||||
|
||||
{
|
||||
struct address_info *sb_config;
|
||||
|
||||
sb_config = &cfg2;
|
||||
if (sb_config->io_base)
|
||||
{
|
||||
unsigned char irq_dma;
|
||||
|
||||
/*
|
||||
* Turn on Sound Blaster compatibility
|
||||
* bit 1 = SB emulation
|
||||
* bit 0 = MPU401 emulation (CDPC only :-( )
|
||||
*/
|
||||
|
||||
pas_write(0x02, 0xF788);
|
||||
|
||||
/*
|
||||
* "Emulation address"
|
||||
*/
|
||||
|
||||
pas_write((sb_config->io_base >> 4) & 0x0f, 0xF789);
|
||||
pas_sb_base = sb_config->io_base;
|
||||
|
||||
if (!sb_dma_bits[sb_config->dma])
|
||||
printk(KERN_ERR "PAS16 Warning: Invalid SB DMA %d\n\n", sb_config->dma);
|
||||
|
||||
if (!sb_irq_bits[sb_config->irq])
|
||||
printk(KERN_ERR "PAS16 Warning: Invalid SB IRQ %d\n\n", sb_config->irq);
|
||||
|
||||
irq_dma = sb_dma_bits[sb_config->dma] |
|
||||
sb_irq_bits[sb_config->irq];
|
||||
|
||||
pas_write(irq_dma, 0xFB8A);
|
||||
}
|
||||
else
|
||||
pas_write(0x00, 0xF788);
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
printk(KERN_WARNING "PAS16: Driver not enabled\n");
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int __init detect_pas_hw(struct address_info *hw_config)
|
||||
{
|
||||
unsigned char board_id, foo;
|
||||
|
||||
/*
|
||||
* WARNING: Setting an option like W:1 or so that disables warm boot reset
|
||||
* of the card will screw up this detect code something fierce. Adding code
|
||||
* to handle this means possibly interfering with other cards on the bus if
|
||||
* you have something on base port 0x388. SO be forewarned.
|
||||
*/
|
||||
|
||||
outb((0xBC), 0x9A01); /* Activate first board */
|
||||
outb((hw_config->io_base >> 2), 0x9A01); /* Set base address */
|
||||
pas_translate_code = hw_config->io_base - 0x388;
|
||||
pas_write(1, 0xBF88); /* Select one wait states */
|
||||
|
||||
board_id = pas_read(0x0B8B);
|
||||
|
||||
if (board_id == 0xff)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* We probably have a PAS-series board, now check for a PAS16-series board
|
||||
* by trying to change the board revision bits. PAS16-series hardware won't
|
||||
* let you do this - the bits are read-only.
|
||||
*/
|
||||
|
||||
foo = board_id ^ 0xe0;
|
||||
|
||||
pas_write(foo, 0x0B8B);
|
||||
foo = pas_read(0x0B8B);
|
||||
pas_write(board_id, 0x0B8B);
|
||||
|
||||
if (board_id != foo)
|
||||
return 0;
|
||||
|
||||
pas_model = pas_read(0xFF88);
|
||||
|
||||
return pas_model;
|
||||
}
|
||||
|
||||
static void __init attach_pas_card(struct address_info *hw_config)
|
||||
{
|
||||
pas_irq = hw_config->irq;
|
||||
|
||||
if (detect_pas_hw(hw_config))
|
||||
{
|
||||
|
||||
if ((pas_model = pas_read(0xFF88)))
|
||||
{
|
||||
char temp[100];
|
||||
|
||||
if (pas_model < 0 ||
|
||||
pas_model >= ARRAY_SIZE(pas_model_names)) {
|
||||
printk(KERN_ERR "pas2 unrecognized model.\n");
|
||||
return;
|
||||
}
|
||||
sprintf(temp,
|
||||
"%s rev %d", pas_model_names[(int) pas_model],
|
||||
pas_read(0x2789));
|
||||
conf_printf(temp, hw_config);
|
||||
}
|
||||
if (config_pas_hw(hw_config))
|
||||
{
|
||||
pas_pcm_init(hw_config);
|
||||
pas_midi_init();
|
||||
pas_init_mixer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline int __init probe_pas(struct address_info *hw_config)
|
||||
{
|
||||
return detect_pas_hw(hw_config);
|
||||
}
|
||||
|
||||
static void __exit unload_pas(struct address_info *hw_config)
|
||||
{
|
||||
extern int pas_audiodev;
|
||||
extern int pas2_mididev;
|
||||
|
||||
if (hw_config->dma>0)
|
||||
sound_free_dma(hw_config->dma);
|
||||
if (hw_config->irq>0)
|
||||
free_irq(hw_config->irq, hw_config);
|
||||
|
||||
if(pas_audiodev!=-1)
|
||||
sound_unload_mixerdev(audio_devs[pas_audiodev]->mixer_dev);
|
||||
if(pas2_mididev!=-1)
|
||||
sound_unload_mididev(pas2_mididev);
|
||||
if(pas_audiodev!=-1)
|
||||
sound_unload_audiodev(pas_audiodev);
|
||||
}
|
||||
|
||||
static int __initdata io = -1;
|
||||
static int __initdata irq = -1;
|
||||
static int __initdata dma = -1;
|
||||
static int __initdata dma16 = -1; /* Set this for modules that need it */
|
||||
|
||||
static int __initdata sb_io = 0;
|
||||
static int __initdata sb_irq = -1;
|
||||
static int __initdata sb_dma = -1;
|
||||
static int __initdata sb_dma16 = -1;
|
||||
|
||||
module_param_hw(io, int, ioport, 0);
|
||||
module_param_hw(irq, int, irq, 0);
|
||||
module_param_hw(dma, int, dma, 0);
|
||||
module_param_hw(dma16, int, dma, 0);
|
||||
|
||||
module_param_hw(sb_io, int, ioport, 0);
|
||||
module_param_hw(sb_irq, int, irq, 0);
|
||||
module_param_hw(sb_dma, int, dma, 0);
|
||||
module_param_hw(sb_dma16, int, dma, 0);
|
||||
|
||||
module_param(joystick, bool, 0);
|
||||
module_param(symphony, bool, 0);
|
||||
module_param(broken_bus_clock, bool, 0);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int __init init_pas2(void)
|
||||
{
|
||||
printk(KERN_INFO "Pro Audio Spectrum driver Copyright (C) by Hannu Savolainen 1993-1996\n");
|
||||
|
||||
cfg.io_base = io;
|
||||
cfg.irq = irq;
|
||||
cfg.dma = dma;
|
||||
cfg.dma2 = dma16;
|
||||
|
||||
cfg2.io_base = sb_io;
|
||||
cfg2.irq = sb_irq;
|
||||
cfg2.dma = sb_dma;
|
||||
cfg2.dma2 = sb_dma16;
|
||||
|
||||
if (cfg.io_base == -1 || cfg.dma == -1 || cfg.irq == -1) {
|
||||
printk(KERN_INFO "I/O, IRQ, DMA and type are mandatory\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!probe_pas(&cfg))
|
||||
return -ENODEV;
|
||||
attach_pas_card(&cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit cleanup_pas2(void)
|
||||
{
|
||||
unload_pas(&cfg);
|
||||
}
|
||||
|
||||
module_init(init_pas2);
|
||||
module_exit(cleanup_pas2);
|
||||
|
||||
#ifndef MODULE
|
||||
static int __init setup_pas2(char *str)
|
||||
{
|
||||
/* io, irq, dma, dma2, sb_io, sb_irq, sb_dma, sb_dma2 */
|
||||
int ints[9];
|
||||
|
||||
str = get_options(str, ARRAY_SIZE(ints), ints);
|
||||
|
||||
io = ints[1];
|
||||
irq = ints[2];
|
||||
dma = ints[3];
|
||||
dma16 = ints[4];
|
||||
|
||||
sb_io = ints[5];
|
||||
sb_irq = ints[6];
|
||||
sb_dma = ints[7];
|
||||
sb_dma16 = ints[8];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("pas2=", setup_pas2);
|
||||
#endif
|
|
@ -1,262 +0,0 @@
|
|||
/*
|
||||
* sound/oss/pas2_midi.c
|
||||
*
|
||||
* The low level driver for the PAS Midi Interface.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) by Hannu Savolainen 1993-1997
|
||||
*
|
||||
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
|
||||
* Version 2 (June 1991). See the "COPYING" file distributed with this software
|
||||
* for more info.
|
||||
*
|
||||
* Bartlomiej Zolnierkiewicz : Added __init to pas_init_mixer()
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include "sound_config.h"
|
||||
|
||||
#include "pas2.h"
|
||||
|
||||
extern spinlock_t pas_lock;
|
||||
|
||||
static int midi_busy, input_opened;
|
||||
static int my_dev;
|
||||
|
||||
int pas2_mididev=-1;
|
||||
|
||||
static unsigned char tmp_queue[256];
|
||||
static volatile int qlen;
|
||||
static volatile unsigned char qhead, qtail;
|
||||
|
||||
static void (*midi_input_intr) (int dev, unsigned char data);
|
||||
|
||||
static int pas_midi_open(int dev, int mode,
|
||||
void (*input) (int dev, unsigned char data),
|
||||
void (*output) (int dev)
|
||||
)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
unsigned char ctrl;
|
||||
|
||||
|
||||
if (midi_busy)
|
||||
return -EBUSY;
|
||||
|
||||
/*
|
||||
* Reset input and output FIFO pointers
|
||||
*/
|
||||
pas_write(0x20 | 0x40,
|
||||
0x178b);
|
||||
|
||||
spin_lock_irqsave(&pas_lock, flags);
|
||||
|
||||
if ((err = pas_set_intr(0x10)) < 0)
|
||||
{
|
||||
spin_unlock_irqrestore(&pas_lock, flags);
|
||||
return err;
|
||||
}
|
||||
/*
|
||||
* Enable input available and output FIFO empty interrupts
|
||||
*/
|
||||
|
||||
ctrl = 0;
|
||||
input_opened = 0;
|
||||
midi_input_intr = input;
|
||||
|
||||
if (mode == OPEN_READ || mode == OPEN_READWRITE)
|
||||
{
|
||||
ctrl |= 0x04; /* Enable input */
|
||||
input_opened = 1;
|
||||
}
|
||||
if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
|
||||
{
|
||||
ctrl |= 0x08 | 0x10; /* Enable output */
|
||||
}
|
||||
pas_write(ctrl, 0x178b);
|
||||
|
||||
/*
|
||||
* Acknowledge any pending interrupts
|
||||
*/
|
||||
|
||||
pas_write(0xff, 0x1B88);
|
||||
|
||||
spin_unlock_irqrestore(&pas_lock, flags);
|
||||
|
||||
midi_busy = 1;
|
||||
qlen = qhead = qtail = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pas_midi_close(int dev)
|
||||
{
|
||||
|
||||
/*
|
||||
* Reset FIFO pointers, disable intrs
|
||||
*/
|
||||
pas_write(0x20 | 0x40, 0x178b);
|
||||
|
||||
pas_remove_intr(0x10);
|
||||
midi_busy = 0;
|
||||
}
|
||||
|
||||
static int dump_to_midi(unsigned char midi_byte)
|
||||
{
|
||||
int fifo_space, x;
|
||||
|
||||
fifo_space = ((x = pas_read(0x1B89)) >> 4) & 0x0f;
|
||||
|
||||
/*
|
||||
* The MIDI FIFO space register and it's documentation is nonunderstandable.
|
||||
* There seem to be no way to differentiate between buffer full and buffer
|
||||
* empty situations. For this reason we don't never write the buffer
|
||||
* completely full. In this way we can assume that 0 (or is it 15)
|
||||
* means that the buffer is empty.
|
||||
*/
|
||||
|
||||
if (fifo_space < 2 && fifo_space != 0) /* Full (almost) */
|
||||
return 0; /* Ask upper layers to retry after some time */
|
||||
|
||||
pas_write(midi_byte, 0x178A);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pas_midi_out(int dev, unsigned char midi_byte)
|
||||
{
|
||||
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Drain the local queue first
|
||||
*/
|
||||
|
||||
spin_lock_irqsave(&pas_lock, flags);
|
||||
|
||||
while (qlen && dump_to_midi(tmp_queue[qhead]))
|
||||
{
|
||||
qlen--;
|
||||
qhead++;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&pas_lock, flags);
|
||||
|
||||
/*
|
||||
* Output the byte if the local queue is empty.
|
||||
*/
|
||||
|
||||
if (!qlen)
|
||||
if (dump_to_midi(midi_byte))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Put to the local queue
|
||||
*/
|
||||
|
||||
if (qlen >= 256)
|
||||
return 0; /* Local queue full */
|
||||
|
||||
spin_lock_irqsave(&pas_lock, flags);
|
||||
|
||||
tmp_queue[qtail] = midi_byte;
|
||||
qlen++;
|
||||
qtail++;
|
||||
|
||||
spin_unlock_irqrestore(&pas_lock, flags);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pas_midi_start_read(int dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pas_midi_end_read(int dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pas_midi_kick(int dev)
|
||||
{
|
||||
}
|
||||
|
||||
static int pas_buffer_status(int dev)
|
||||
{
|
||||
return qlen;
|
||||
}
|
||||
|
||||
#define MIDI_SYNTH_NAME "Pro Audio Spectrum Midi"
|
||||
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
|
||||
#include "midi_synth.h"
|
||||
|
||||
static struct midi_operations pas_midi_operations =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.info = {"Pro Audio Spectrum", 0, 0, SNDCARD_PAS},
|
||||
.converter = &std_midi_synth,
|
||||
.in_info = {0},
|
||||
.open = pas_midi_open,
|
||||
.close = pas_midi_close,
|
||||
.outputc = pas_midi_out,
|
||||
.start_read = pas_midi_start_read,
|
||||
.end_read = pas_midi_end_read,
|
||||
.kick = pas_midi_kick,
|
||||
.buffer_status = pas_buffer_status,
|
||||
};
|
||||
|
||||
void __init pas_midi_init(void)
|
||||
{
|
||||
int dev = sound_alloc_mididev();
|
||||
|
||||
if (dev == -1)
|
||||
{
|
||||
printk(KERN_WARNING "pas_midi_init: Too many midi devices detected\n");
|
||||
return;
|
||||
}
|
||||
std_midi_synth.midi_dev = my_dev = dev;
|
||||
midi_devs[dev] = &pas_midi_operations;
|
||||
pas2_mididev = dev;
|
||||
sequencer_init();
|
||||
}
|
||||
|
||||
void pas_midi_interrupt(void)
|
||||
{
|
||||
unsigned char stat;
|
||||
int i, incount;
|
||||
|
||||
stat = pas_read(0x1B88);
|
||||
|
||||
if (stat & 0x04) /* Input data available */
|
||||
{
|
||||
incount = pas_read(0x1B89) & 0x0f; /* Input FIFO size */
|
||||
if (!incount)
|
||||
incount = 16;
|
||||
|
||||
for (i = 0; i < incount; i++)
|
||||
if (input_opened)
|
||||
{
|
||||
midi_input_intr(my_dev, pas_read(0x178A));
|
||||
} else
|
||||
pas_read(0x178A); /* Flush */
|
||||
}
|
||||
if (stat & (0x08 | 0x10))
|
||||
{
|
||||
spin_lock(&pas_lock);/* called in irq context */
|
||||
|
||||
while (qlen && dump_to_midi(tmp_queue[qhead]))
|
||||
{
|
||||
qlen--;
|
||||
qhead++;
|
||||
}
|
||||
|
||||
spin_unlock(&pas_lock);
|
||||
}
|
||||
if (stat & 0x40)
|
||||
{
|
||||
printk(KERN_WARNING "MIDI output overrun %x,%x\n", pas_read(0x1B89), stat);
|
||||
}
|
||||
pas_write(stat, 0x1B88); /* Acknowledge interrupts */
|
||||
}
|
|
@ -1,327 +0,0 @@
|
|||
|
||||
/*
|
||||
* sound/oss/pas2_mixer.c
|
||||
*
|
||||
* Mixer routines for the Pro Audio Spectrum cards.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) by Hannu Savolainen 1993-1997
|
||||
*
|
||||
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
|
||||
* Version 2 (June 1991). See the "COPYING" file distributed with this software
|
||||
* for more info.
|
||||
*/
|
||||
/*
|
||||
* Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
|
||||
* Bartlomiej Zolnierkiewicz : added __init to pas_init_mixer()
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include "sound_config.h"
|
||||
|
||||
#include "pas2.h"
|
||||
|
||||
extern int pas_translate_code;
|
||||
extern char pas_model;
|
||||
extern int *pas_osp;
|
||||
extern int pas_audiodev;
|
||||
|
||||
static int rec_devices = (SOUND_MASK_MIC); /* Default recording source */
|
||||
static int mode_control;
|
||||
|
||||
#define POSSIBLE_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
|
||||
SOUND_MASK_CD | SOUND_MASK_ALTPCM)
|
||||
|
||||
#define SUPPORTED_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
|
||||
SOUND_MASK_CD | SOUND_MASK_ALTPCM | SOUND_MASK_IMIX | \
|
||||
SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_RECLEV)
|
||||
|
||||
static int *levels;
|
||||
|
||||
static int default_levels[32] =
|
||||
{
|
||||
0x3232, /* Master Volume */
|
||||
0x3232, /* Bass */
|
||||
0x3232, /* Treble */
|
||||
0x5050, /* FM */
|
||||
0x4b4b, /* PCM */
|
||||
0x3232, /* PC Speaker */
|
||||
0x4b4b, /* Ext Line */
|
||||
0x4b4b, /* Mic */
|
||||
0x4b4b, /* CD */
|
||||
0x6464, /* Recording monitor */
|
||||
0x4b4b, /* SB PCM */
|
||||
0x6464 /* Recording level */
|
||||
};
|
||||
|
||||
void
|
||||
mix_write(unsigned char data, int ioaddr)
|
||||
{
|
||||
/*
|
||||
* The Revision D cards have a problem with their MVA508 interface. The
|
||||
* kludge-o-rama fix is to make a 16-bit quantity with identical LSB and
|
||||
* MSBs out of the output byte and to do a 16-bit out to the mixer port -
|
||||
* 1. We need to do this because it isn't timing problem but chip access
|
||||
* sequence problem.
|
||||
*/
|
||||
|
||||
if (pas_model == 4)
|
||||
{
|
||||
outw(data | (data << 8), (ioaddr + pas_translate_code) - 1);
|
||||
outb((0x80), 0);
|
||||
} else
|
||||
pas_write(data, ioaddr);
|
||||
}
|
||||
|
||||
static int
|
||||
mixer_output(int right_vol, int left_vol, int div, int bits,
|
||||
int mixer) /* Input or output mixer */
|
||||
{
|
||||
int left = left_vol * div / 100;
|
||||
int right = right_vol * div / 100;
|
||||
|
||||
|
||||
if (bits & 0x10)
|
||||
{
|
||||
left |= mixer;
|
||||
right |= mixer;
|
||||
}
|
||||
if (bits == 0x03 || bits == 0x04)
|
||||
{
|
||||
mix_write(0x80 | bits, 0x078B);
|
||||
mix_write(left, 0x078B);
|
||||
right_vol = left_vol;
|
||||
} else
|
||||
{
|
||||
mix_write(0x80 | 0x20 | bits, 0x078B);
|
||||
mix_write(left, 0x078B);
|
||||
mix_write(0x80 | 0x40 | bits, 0x078B);
|
||||
mix_write(right, 0x078B);
|
||||
}
|
||||
|
||||
return (left_vol | (right_vol << 8));
|
||||
}
|
||||
|
||||
static void
|
||||
set_mode(int new_mode)
|
||||
{
|
||||
mix_write(0x80 | 0x05, 0x078B);
|
||||
mix_write(new_mode, 0x078B);
|
||||
|
||||
mode_control = new_mode;
|
||||
}
|
||||
|
||||
static int
|
||||
pas_mixer_set(int whichDev, unsigned int level)
|
||||
{
|
||||
int left, right, devmask, changed, i, mixer = 0;
|
||||
|
||||
left = level & 0x7f;
|
||||
right = (level & 0x7f00) >> 8;
|
||||
|
||||
if (whichDev < SOUND_MIXER_NRDEVICES) {
|
||||
if ((1 << whichDev) & rec_devices)
|
||||
mixer = 0x20;
|
||||
else
|
||||
mixer = 0x00;
|
||||
}
|
||||
|
||||
switch (whichDev)
|
||||
{
|
||||
case SOUND_MIXER_VOLUME: /* Master volume (0-63) */
|
||||
levels[whichDev] = mixer_output(right, left, 63, 0x01, 0);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Note! Bass and Treble are mono devices. Will use just the left
|
||||
* channel.
|
||||
*/
|
||||
case SOUND_MIXER_BASS: /* Bass (0-12) */
|
||||
levels[whichDev] = mixer_output(right, left, 12, 0x03, 0);
|
||||
break;
|
||||
case SOUND_MIXER_TREBLE: /* Treble (0-12) */
|
||||
levels[whichDev] = mixer_output(right, left, 12, 0x04, 0);
|
||||
break;
|
||||
|
||||
case SOUND_MIXER_SYNTH: /* Internal synthesizer (0-31) */
|
||||
levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x00, mixer);
|
||||
break;
|
||||
case SOUND_MIXER_PCM: /* PAS PCM (0-31) */
|
||||
levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x05, mixer);
|
||||
break;
|
||||
case SOUND_MIXER_ALTPCM: /* SB PCM (0-31) */
|
||||
levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x07, mixer);
|
||||
break;
|
||||
case SOUND_MIXER_SPEAKER: /* PC speaker (0-31) */
|
||||
levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x06, mixer);
|
||||
break;
|
||||
case SOUND_MIXER_LINE: /* External line (0-31) */
|
||||
levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x02, mixer);
|
||||
break;
|
||||
case SOUND_MIXER_CD: /* CD (0-31) */
|
||||
levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x03, mixer);
|
||||
break;
|
||||
case SOUND_MIXER_MIC: /* External microphone (0-31) */
|
||||
levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x04, mixer);
|
||||
break;
|
||||
case SOUND_MIXER_IMIX: /* Recording monitor (0-31) (Output mixer only) */
|
||||
levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x01,
|
||||
0x00);
|
||||
break;
|
||||
case SOUND_MIXER_RECLEV: /* Recording level (0-15) */
|
||||
levels[whichDev] = mixer_output(right, left, 15, 0x02, 0);
|
||||
break;
|
||||
|
||||
|
||||
case SOUND_MIXER_RECSRC:
|
||||
devmask = level & POSSIBLE_RECORDING_DEVICES;
|
||||
|
||||
changed = devmask ^ rec_devices;
|
||||
rec_devices = devmask;
|
||||
|
||||
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
|
||||
if (changed & (1 << i))
|
||||
{
|
||||
pas_mixer_set(i, levels[i]);
|
||||
}
|
||||
return rec_devices;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return (levels[whichDev]);
|
||||
}
|
||||
|
||||
/*****/
|
||||
|
||||
static void
|
||||
pas_mixer_reset(void)
|
||||
{
|
||||
int foo;
|
||||
|
||||
for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++)
|
||||
pas_mixer_set(foo, levels[foo]);
|
||||
|
||||
set_mode(0x04 | 0x01);
|
||||
}
|
||||
|
||||
static int pas_mixer_ioctl(int dev, unsigned int cmd, void __user *arg)
|
||||
{
|
||||
int level,v ;
|
||||
int __user *p = (int __user *)arg;
|
||||
|
||||
if (cmd == SOUND_MIXER_PRIVATE1) { /* Set loudness bit */
|
||||
if (get_user(level, p))
|
||||
return -EFAULT;
|
||||
if (level == -1) /* Return current settings */
|
||||
level = (mode_control & 0x04);
|
||||
else {
|
||||
mode_control &= ~0x04;
|
||||
if (level)
|
||||
mode_control |= 0x04;
|
||||
set_mode(mode_control);
|
||||
}
|
||||
level = !!level;
|
||||
return put_user(level, p);
|
||||
}
|
||||
if (cmd == SOUND_MIXER_PRIVATE2) { /* Set enhance bit */
|
||||
if (get_user(level, p))
|
||||
return -EFAULT;
|
||||
if (level == -1) { /* Return current settings */
|
||||
if (!(mode_control & 0x03))
|
||||
level = 0;
|
||||
else
|
||||
level = ((mode_control & 0x03) + 1) * 20;
|
||||
} else {
|
||||
int i = 0;
|
||||
|
||||
level &= 0x7f;
|
||||
if (level)
|
||||
i = (level / 20) - 1;
|
||||
mode_control &= ~0x03;
|
||||
mode_control |= i & 0x03;
|
||||
set_mode(mode_control);
|
||||
if (i)
|
||||
i = (i + 1) * 20;
|
||||
level = i;
|
||||
}
|
||||
return put_user(level, p);
|
||||
}
|
||||
if (cmd == SOUND_MIXER_PRIVATE3) { /* Set mute bit */
|
||||
if (get_user(level, p))
|
||||
return -EFAULT;
|
||||
if (level == -1) /* Return current settings */
|
||||
level = !(pas_read(0x0B8A) & 0x20);
|
||||
else {
|
||||
if (level)
|
||||
pas_write(pas_read(0x0B8A) & (~0x20), 0x0B8A);
|
||||
else
|
||||
pas_write(pas_read(0x0B8A) | 0x20, 0x0B8A);
|
||||
|
||||
level = !(pas_read(0x0B8A) & 0x20);
|
||||
}
|
||||
return put_user(level, p);
|
||||
}
|
||||
if (((cmd >> 8) & 0xff) == 'M') {
|
||||
if (get_user(v, p))
|
||||
return -EFAULT;
|
||||
if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
|
||||
v = pas_mixer_set(cmd & 0xff, v);
|
||||
} else {
|
||||
switch (cmd & 0xff) {
|
||||
case SOUND_MIXER_RECSRC:
|
||||
v = rec_devices;
|
||||
break;
|
||||
|
||||
case SOUND_MIXER_STEREODEVS:
|
||||
v = SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE);
|
||||
break;
|
||||
|
||||
case SOUND_MIXER_DEVMASK:
|
||||
v = SUPPORTED_MIXER_DEVICES;
|
||||
break;
|
||||
|
||||
case SOUND_MIXER_RECMASK:
|
||||
v = POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES;
|
||||
break;
|
||||
|
||||
case SOUND_MIXER_CAPS:
|
||||
v = 0; /* No special capabilities */
|
||||
break;
|
||||
|
||||
default:
|
||||
v = levels[cmd & 0xff];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return put_user(v, p);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct mixer_operations pas_mixer_operations =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.id = "PAS16",
|
||||
.name = "Pro Audio Spectrum 16",
|
||||
.ioctl = pas_mixer_ioctl
|
||||
};
|
||||
|
||||
int __init
|
||||
pas_init_mixer(void)
|
||||
{
|
||||
int d;
|
||||
|
||||
levels = load_mixer_volumes("PAS16_1", default_levels, 1);
|
||||
|
||||
pas_mixer_reset();
|
||||
|
||||
if ((d = sound_alloc_mixerdev()) != -1)
|
||||
{
|
||||
audio_devs[pas_audiodev]->mixer_dev = d;
|
||||
mixer_devs[d] = &pas_mixer_operations;
|
||||
}
|
||||
return 1;
|
||||
}
|
|
@ -1,419 +0,0 @@
|
|||
/*
|
||||
* pas2_pcm.c Audio routines for PAS16
|
||||
*
|
||||
*
|
||||
* Copyright (C) by Hannu Savolainen 1993-1997
|
||||
*
|
||||
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
|
||||
* Version 2 (June 1991). See the "COPYING" file distributed with this software
|
||||
* for more info.
|
||||
*
|
||||
*
|
||||
* Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
|
||||
* Alan Cox : Swatted a double allocation of device bug. Made a few
|
||||
* more things module options.
|
||||
* Bartlomiej Zolnierkiewicz : Added __init to pas_pcm_init()
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/timex.h>
|
||||
#include "sound_config.h"
|
||||
|
||||
#include "pas2.h"
|
||||
|
||||
#define PAS_PCM_INTRBITS (0x08)
|
||||
/*
|
||||
* Sample buffer timer interrupt enable
|
||||
*/
|
||||
|
||||
#define PCM_NON 0
|
||||
#define PCM_DAC 1
|
||||
#define PCM_ADC 2
|
||||
|
||||
static unsigned long pcm_speed; /* sampling rate */
|
||||
static unsigned char pcm_channels = 1; /* channels (1 or 2) */
|
||||
static unsigned char pcm_bits = 8; /* bits/sample (8 or 16) */
|
||||
static unsigned char pcm_filter; /* filter FLAG */
|
||||
static unsigned char pcm_mode = PCM_NON;
|
||||
static unsigned long pcm_count;
|
||||
static unsigned short pcm_bitsok = 8; /* mask of OK bits */
|
||||
static int pcm_busy;
|
||||
int pas_audiodev = -1;
|
||||
static int open_mode;
|
||||
|
||||
extern spinlock_t pas_lock;
|
||||
|
||||
static int pcm_set_speed(int arg)
|
||||
{
|
||||
int foo, tmp;
|
||||
unsigned long flags;
|
||||
|
||||
if (arg == 0)
|
||||
return pcm_speed;
|
||||
|
||||
if (arg > 44100)
|
||||
arg = 44100;
|
||||
if (arg < 5000)
|
||||
arg = 5000;
|
||||
|
||||
if (pcm_channels & 2)
|
||||
{
|
||||
foo = ((PIT_TICK_RATE / 2) + (arg / 2)) / arg;
|
||||
arg = ((PIT_TICK_RATE / 2) + (foo / 2)) / foo;
|
||||
}
|
||||
else
|
||||
{
|
||||
foo = (PIT_TICK_RATE + (arg / 2)) / arg;
|
||||
arg = (PIT_TICK_RATE + (foo / 2)) / foo;
|
||||
}
|
||||
|
||||
pcm_speed = arg;
|
||||
|
||||
tmp = pas_read(0x0B8A);
|
||||
|
||||
/*
|
||||
* Set anti-aliasing filters according to sample rate. You really *NEED*
|
||||
* to enable this feature for all normal recording unless you want to
|
||||
* experiment with aliasing effects.
|
||||
* These filters apply to the selected "recording" source.
|
||||
* I (pfw) don't know the encoding of these 5 bits. The values shown
|
||||
* come from the SDK found on ftp.uwp.edu:/pub/msdos/proaudio/.
|
||||
*
|
||||
* I cleared bit 5 of these values, since that bit controls the master
|
||||
* mute flag. (Olav Wölfelschneider)
|
||||
*
|
||||
*/
|
||||
#if !defined NO_AUTO_FILTER_SET
|
||||
tmp &= 0xe0;
|
||||
if (pcm_speed >= 2 * 17897)
|
||||
tmp |= 0x01;
|
||||
else if (pcm_speed >= 2 * 15909)
|
||||
tmp |= 0x02;
|
||||
else if (pcm_speed >= 2 * 11931)
|
||||
tmp |= 0x09;
|
||||
else if (pcm_speed >= 2 * 8948)
|
||||
tmp |= 0x11;
|
||||
else if (pcm_speed >= 2 * 5965)
|
||||
tmp |= 0x19;
|
||||
else if (pcm_speed >= 2 * 2982)
|
||||
tmp |= 0x04;
|
||||
pcm_filter = tmp;
|
||||
#endif
|
||||
|
||||
spin_lock_irqsave(&pas_lock, flags);
|
||||
|
||||
pas_write(tmp & ~(0x40 | 0x80), 0x0B8A);
|
||||
pas_write(0x00 | 0x30 | 0x04, 0x138B);
|
||||
pas_write(foo & 0xff, 0x1388);
|
||||
pas_write((foo >> 8) & 0xff, 0x1388);
|
||||
pas_write(tmp, 0x0B8A);
|
||||
|
||||
spin_unlock_irqrestore(&pas_lock, flags);
|
||||
|
||||
return pcm_speed;
|
||||
}
|
||||
|
||||
static int pcm_set_channels(int arg)
|
||||
{
|
||||
|
||||
if ((arg != 1) && (arg != 2))
|
||||
return pcm_channels;
|
||||
|
||||
if (arg != pcm_channels)
|
||||
{
|
||||
pas_write(pas_read(0xF8A) ^ 0x20, 0xF8A);
|
||||
|
||||
pcm_channels = arg;
|
||||
pcm_set_speed(pcm_speed); /* The speed must be reinitialized */
|
||||
}
|
||||
return pcm_channels;
|
||||
}
|
||||
|
||||
static int pcm_set_bits(int arg)
|
||||
{
|
||||
if (arg == 0)
|
||||
return pcm_bits;
|
||||
|
||||
if ((arg & pcm_bitsok) != arg)
|
||||
return pcm_bits;
|
||||
|
||||
if (arg != pcm_bits)
|
||||
{
|
||||
pas_write(pas_read(0x8389) ^ 0x04, 0x8389);
|
||||
|
||||
pcm_bits = arg;
|
||||
}
|
||||
return pcm_bits;
|
||||
}
|
||||
|
||||
static int pas_audio_ioctl(int dev, unsigned int cmd, void __user *arg)
|
||||
{
|
||||
int val, ret;
|
||||
int __user *p = arg;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case SOUND_PCM_WRITE_RATE:
|
||||
if (get_user(val, p))
|
||||
return -EFAULT;
|
||||
ret = pcm_set_speed(val);
|
||||
break;
|
||||
|
||||
case SOUND_PCM_READ_RATE:
|
||||
ret = pcm_speed;
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_STEREO:
|
||||
if (get_user(val, p))
|
||||
return -EFAULT;
|
||||
ret = pcm_set_channels(val + 1) - 1;
|
||||
break;
|
||||
|
||||
case SOUND_PCM_WRITE_CHANNELS:
|
||||
if (get_user(val, p))
|
||||
return -EFAULT;
|
||||
ret = pcm_set_channels(val);
|
||||
break;
|
||||
|
||||
case SOUND_PCM_READ_CHANNELS:
|
||||
ret = pcm_channels;
|
||||
break;
|
||||
|
||||
case SNDCTL_DSP_SETFMT:
|
||||
if (get_user(val, p))
|
||||
return -EFAULT;
|
||||
ret = pcm_set_bits(val);
|
||||
break;
|
||||
|
||||
case SOUND_PCM_READ_BITS:
|
||||
ret = pcm_bits;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return put_user(ret, p);
|
||||
}
|
||||
|
||||
static void pas_audio_reset(int dev)
|
||||
{
|
||||
pas_write(pas_read(0xF8A) & ~0x40, 0xF8A); /* Disable PCM */
|
||||
}
|
||||
|
||||
static int pas_audio_open(int dev, int mode)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&pas_lock, flags);
|
||||
if (pcm_busy)
|
||||
{
|
||||
spin_unlock_irqrestore(&pas_lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
pcm_busy = 1;
|
||||
spin_unlock_irqrestore(&pas_lock, flags);
|
||||
|
||||
if ((err = pas_set_intr(PAS_PCM_INTRBITS)) < 0)
|
||||
return err;
|
||||
|
||||
|
||||
pcm_count = 0;
|
||||
open_mode = mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pas_audio_close(int dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&pas_lock, flags);
|
||||
|
||||
pas_audio_reset(dev);
|
||||
pas_remove_intr(PAS_PCM_INTRBITS);
|
||||
pcm_mode = PCM_NON;
|
||||
|
||||
pcm_busy = 0;
|
||||
spin_unlock_irqrestore(&pas_lock, flags);
|
||||
}
|
||||
|
||||
static void pas_audio_output_block(int dev, unsigned long buf, int count,
|
||||
int intrflag)
|
||||
{
|
||||
unsigned long flags, cnt;
|
||||
|
||||
cnt = count;
|
||||
if (audio_devs[dev]->dmap_out->dma > 3)
|
||||
cnt >>= 1;
|
||||
|
||||
if (audio_devs[dev]->flags & DMA_AUTOMODE &&
|
||||
intrflag &&
|
||||
cnt == pcm_count)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&pas_lock, flags);
|
||||
|
||||
pas_write(pas_read(0xF8A) & ~0x40,
|
||||
0xF8A);
|
||||
|
||||
/* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */
|
||||
|
||||
if (audio_devs[dev]->dmap_out->dma > 3)
|
||||
count >>= 1;
|
||||
|
||||
if (count != pcm_count)
|
||||
{
|
||||
pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A);
|
||||
pas_write(0x40 | 0x30 | 0x04, 0x138B);
|
||||
pas_write(count & 0xff, 0x1389);
|
||||
pas_write((count >> 8) & 0xff, 0x1389);
|
||||
pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A);
|
||||
|
||||
pcm_count = count;
|
||||
}
|
||||
pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A);
|
||||
#ifdef NO_TRIGGER
|
||||
pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A);
|
||||
#endif
|
||||
|
||||
pcm_mode = PCM_DAC;
|
||||
|
||||
spin_unlock_irqrestore(&pas_lock, flags);
|
||||
}
|
||||
|
||||
static void pas_audio_start_input(int dev, unsigned long buf, int count,
|
||||
int intrflag)
|
||||
{
|
||||
unsigned long flags;
|
||||
int cnt;
|
||||
|
||||
cnt = count;
|
||||
if (audio_devs[dev]->dmap_out->dma > 3)
|
||||
cnt >>= 1;
|
||||
|
||||
if (audio_devs[pas_audiodev]->flags & DMA_AUTOMODE &&
|
||||
intrflag &&
|
||||
cnt == pcm_count)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&pas_lock, flags);
|
||||
|
||||
/* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */
|
||||
|
||||
if (audio_devs[dev]->dmap_out->dma > 3)
|
||||
count >>= 1;
|
||||
|
||||
if (count != pcm_count)
|
||||
{
|
||||
pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A);
|
||||
pas_write(0x40 | 0x30 | 0x04, 0x138B);
|
||||
pas_write(count & 0xff, 0x1389);
|
||||
pas_write((count >> 8) & 0xff, 0x1389);
|
||||
pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A);
|
||||
|
||||
pcm_count = count;
|
||||
}
|
||||
pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A);
|
||||
#ifdef NO_TRIGGER
|
||||
pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A);
|
||||
#endif
|
||||
|
||||
pcm_mode = PCM_ADC;
|
||||
|
||||
spin_unlock_irqrestore(&pas_lock, flags);
|
||||
}
|
||||
|
||||
#ifndef NO_TRIGGER
|
||||
static void pas_audio_trigger(int dev, int state)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&pas_lock, flags);
|
||||
state &= open_mode;
|
||||
|
||||
if (state & PCM_ENABLE_OUTPUT)
|
||||
pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A);
|
||||
else if (state & PCM_ENABLE_INPUT)
|
||||
pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A);
|
||||
else
|
||||
pas_write(pas_read(0xF8A) & ~0x40, 0xF8A);
|
||||
|
||||
spin_unlock_irqrestore(&pas_lock, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int pas_audio_prepare_for_input(int dev, int bsize, int bcount)
|
||||
{
|
||||
pas_audio_reset(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pas_audio_prepare_for_output(int dev, int bsize, int bcount)
|
||||
{
|
||||
pas_audio_reset(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct audio_driver pas_audio_driver =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.open = pas_audio_open,
|
||||
.close = pas_audio_close,
|
||||
.output_block = pas_audio_output_block,
|
||||
.start_input = pas_audio_start_input,
|
||||
.ioctl = pas_audio_ioctl,
|
||||
.prepare_for_input = pas_audio_prepare_for_input,
|
||||
.prepare_for_output = pas_audio_prepare_for_output,
|
||||
.halt_io = pas_audio_reset,
|
||||
.trigger = pas_audio_trigger
|
||||
};
|
||||
|
||||
void __init pas_pcm_init(struct address_info *hw_config)
|
||||
{
|
||||
pcm_bitsok = 8;
|
||||
if (pas_read(0xEF8B) & 0x08)
|
||||
pcm_bitsok |= 16;
|
||||
|
||||
pcm_set_speed(DSP_DEFAULT_SPEED);
|
||||
|
||||
if ((pas_audiodev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
|
||||
"Pro Audio Spectrum",
|
||||
&pas_audio_driver,
|
||||
sizeof(struct audio_driver),
|
||||
DMA_AUTOMODE,
|
||||
AFMT_U8 | AFMT_S16_LE,
|
||||
NULL,
|
||||
hw_config->dma,
|
||||
hw_config->dma)) < 0)
|
||||
printk(KERN_WARNING "PAS16: Too many PCM devices available\n");
|
||||
}
|
||||
|
||||
void pas_pcm_interrupt(unsigned char status, int cause)
|
||||
{
|
||||
if (cause == 1)
|
||||
{
|
||||
/*
|
||||
* Halt the PCM first. Otherwise we don't have time to start a new
|
||||
* block before the PCM chip proceeds to the next sample
|
||||
*/
|
||||
|
||||
if (!(audio_devs[pas_audiodev]->flags & DMA_AUTOMODE))
|
||||
pas_write(pas_read(0xF8A) & ~0x40, 0xF8A);
|
||||
|
||||
switch (pcm_mode)
|
||||
{
|
||||
case PCM_DAC:
|
||||
DMAbuf_outputintr(pas_audiodev, 1);
|
||||
break;
|
||||
|
||||
case PCM_ADC:
|
||||
DMAbuf_inputintr(pas_audiodev);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_WARNING "PAS: Unexpected PCM interrupt\n");
|
||||
}
|
||||
}
|
||||
}
|
1270
sound/oss/pss.c
1270
sound/oss/pss.c
File diff suppressed because it is too large
Load diff
185
sound/oss/sb.h
185
sound/oss/sb.h
|
@ -1,185 +0,0 @@
|
|||
#define DSP_RESET (devc->base + 0x6)
|
||||
#define DSP_READ (devc->base + 0xA)
|
||||
#define DSP_WRITE (devc->base + 0xC)
|
||||
#define DSP_COMMAND (devc->base + 0xC)
|
||||
#define DSP_STATUS (devc->base + 0xC)
|
||||
#define DSP_DATA_AVAIL (devc->base + 0xE)
|
||||
#define DSP_DATA_AVL16 (devc->base + 0xF)
|
||||
#define MIXER_ADDR (devc->base + 0x4)
|
||||
#define MIXER_DATA (devc->base + 0x5)
|
||||
#define OPL3_LEFT (devc->base + 0x0)
|
||||
#define OPL3_RIGHT (devc->base + 0x2)
|
||||
#define OPL3_BOTH (devc->base + 0x8)
|
||||
/* DSP Commands */
|
||||
|
||||
#define DSP_CMD_SPKON 0xD1
|
||||
#define DSP_CMD_SPKOFF 0xD3
|
||||
#define DSP_CMD_DMAON 0xD0
|
||||
#define DSP_CMD_DMAOFF 0xD4
|
||||
|
||||
#define IMODE_NONE 0
|
||||
#define IMODE_OUTPUT PCM_ENABLE_OUTPUT
|
||||
#define IMODE_INPUT PCM_ENABLE_INPUT
|
||||
#define IMODE_INIT 3
|
||||
#define IMODE_MIDI 4
|
||||
|
||||
#define NORMAL_MIDI 0
|
||||
#define UART_MIDI 1
|
||||
|
||||
|
||||
/*
|
||||
* Device models
|
||||
*/
|
||||
#define MDL_NONE 0
|
||||
#define MDL_SB1 1 /* SB1.0 or 1.5 */
|
||||
#define MDL_SB2 2 /* SB2.0 */
|
||||
#define MDL_SB201 3 /* SB2.01 */
|
||||
#define MDL_SBPRO 4 /* SB Pro */
|
||||
#define MDL_SB16 5 /* SB16/32/AWE */
|
||||
#define MDL_SBPNP 6 /* SB16/32/AWE PnP */
|
||||
#define MDL_JAZZ 10 /* Media Vision Jazz16 */
|
||||
#define MDL_SMW 11 /* Logitech SoundMan Wave (Jazz16) */
|
||||
#define MDL_ESS 12 /* ESS ES688 and ES1688 */
|
||||
#define MDL_AZTECH 13 /* Aztech Sound Galaxy family */
|
||||
#define MDL_ES1868MIDI 14 /* MIDI port of ESS1868 */
|
||||
#define MDL_AEDSP 15 /* Audio Excel DSP 16 */
|
||||
#define MDL_ESSPCI 16 /* ESS PCI card */
|
||||
#define MDL_YMPCI 17 /* Yamaha PCI sb in emulation */
|
||||
|
||||
#define SUBMDL_ALS007 42 /* ALS-007 differs from SB16 only in mixer */
|
||||
/* register assignment */
|
||||
#define SUBMDL_ALS100 43 /* ALS-100 allows sampling rates of up */
|
||||
/* to 48kHz */
|
||||
|
||||
/*
|
||||
* Config flags
|
||||
*/
|
||||
#define SB_NO_MIDI 0x00000001
|
||||
#define SB_NO_MIXER 0x00000002
|
||||
#define SB_NO_AUDIO 0x00000004
|
||||
#define SB_NO_RECORDING 0x00000008 /* No audio recording */
|
||||
#define SB_MIDI_ONLY (SB_NO_AUDIO|SB_NO_MIXER)
|
||||
#define SB_PCI_IRQ 0x00000010 /* PCI shared IRQ */
|
||||
|
||||
struct mixer_def {
|
||||
unsigned int regno: 8;
|
||||
unsigned int bitoffs:4;
|
||||
unsigned int nbits:4;
|
||||
};
|
||||
|
||||
typedef struct mixer_def mixer_tab[32][2];
|
||||
typedef struct mixer_def mixer_ent;
|
||||
|
||||
struct sb_module_options
|
||||
{
|
||||
int esstype; /* ESS chip type */
|
||||
int acer; /* Do acer notebook init? */
|
||||
int sm_games; /* Logitech soundman games? */
|
||||
};
|
||||
|
||||
typedef struct sb_devc {
|
||||
int dev;
|
||||
|
||||
/* Hardware parameters */
|
||||
int *osp;
|
||||
int minor, major;
|
||||
int type;
|
||||
int model, submodel;
|
||||
int caps;
|
||||
# define SBCAP_STEREO 0x00000001
|
||||
# define SBCAP_16BITS 0x00000002
|
||||
|
||||
/* Hardware resources */
|
||||
int base;
|
||||
int irq;
|
||||
int dma8, dma16;
|
||||
|
||||
int pcibase; /* For ESS Maestro etc */
|
||||
|
||||
/* State variables */
|
||||
int opened;
|
||||
/* new audio fields for full duplex support */
|
||||
int fullduplex;
|
||||
int duplex;
|
||||
int speed, bits, channels;
|
||||
volatile int irq_ok;
|
||||
volatile int intr_active, irq_mode;
|
||||
/* duplicate audio fields for full duplex support */
|
||||
volatile int intr_active_16, irq_mode_16;
|
||||
|
||||
/* Mixer fields */
|
||||
int *levels;
|
||||
mixer_tab *iomap;
|
||||
size_t iomap_sz; /* number or records in the iomap table */
|
||||
int mixer_caps, recmask, outmask, supported_devices;
|
||||
int supported_rec_devices, supported_out_devices;
|
||||
int my_mixerdev;
|
||||
int sbmixnum;
|
||||
|
||||
/* Audio fields */
|
||||
unsigned long trg_buf;
|
||||
int trigger_bits;
|
||||
int trg_bytes;
|
||||
int trg_intrflag;
|
||||
int trg_restart;
|
||||
/* duplicate audio fields for full duplex support */
|
||||
unsigned long trg_buf_16;
|
||||
int trigger_bits_16;
|
||||
int trg_bytes_16;
|
||||
int trg_intrflag_16;
|
||||
int trg_restart_16;
|
||||
|
||||
unsigned char tconst;
|
||||
|
||||
/* MIDI fields */
|
||||
int my_mididev;
|
||||
int input_opened;
|
||||
int midi_broken;
|
||||
void (*midi_input_intr) (int dev, unsigned char data);
|
||||
void *midi_irq_cookie; /* IRQ cookie for the midi */
|
||||
|
||||
spinlock_t lock;
|
||||
|
||||
struct sb_module_options sbmo; /* Module options */
|
||||
|
||||
} sb_devc;
|
||||
|
||||
/*
|
||||
* PCI card types
|
||||
*/
|
||||
|
||||
#define SB_PCI_ESSMAESTRO 1 /* ESS Maestro Legacy */
|
||||
#define SB_PCI_YAMAHA 2 /* Yamaha Legacy */
|
||||
|
||||
/*
|
||||
* Functions
|
||||
*/
|
||||
|
||||
int sb_dsp_command (sb_devc *devc, unsigned char val);
|
||||
int sb_dsp_get_byte(sb_devc * devc);
|
||||
int sb_dsp_reset (sb_devc *devc);
|
||||
void sb_setmixer (sb_devc *devc, unsigned int port, unsigned int value);
|
||||
unsigned int sb_getmixer (sb_devc *devc, unsigned int port);
|
||||
int sb_dsp_detect (struct address_info *hw_config, int pci, int pciio, struct sb_module_options *sbmo);
|
||||
int sb_dsp_init (struct address_info *hw_config, struct module *owner);
|
||||
void sb_dsp_unload(struct address_info *hw_config, int sbmpu);
|
||||
int sb_mixer_init(sb_devc *devc, struct module *owner);
|
||||
void sb_mixer_unload(sb_devc *devc);
|
||||
void sb_mixer_set_stereo (sb_devc *devc, int mode);
|
||||
void smw_mixer_init(sb_devc *devc);
|
||||
void sb_dsp_midi_init (sb_devc *devc, struct module *owner);
|
||||
void sb_audio_init (sb_devc *devc, char *name, struct module *owner);
|
||||
void sb_midi_interrupt (sb_devc *devc);
|
||||
void sb_chgmixer (sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val);
|
||||
int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right);
|
||||
|
||||
int sb_audio_open(int dev, int mode);
|
||||
void sb_audio_close(int dev);
|
||||
|
||||
/* From sb_common.c */
|
||||
void sb_dsp_disable_midi(int port);
|
||||
int probe_sbmpu (struct address_info *hw_config, struct module *owner);
|
||||
void unload_sbmpu (struct address_info *hw_config);
|
||||
|
||||
void unload_sb16(struct address_info *hw_info);
|
||||
void unload_sb16midi(struct address_info *hw_info);
|
1097
sound/oss/sb_audio.c
1097
sound/oss/sb_audio.c
File diff suppressed because it is too large
Load diff
|
@ -1,354 +0,0 @@
|
|||
/*
|
||||
* sound/oss/sb_card.c
|
||||
*
|
||||
* Detection routine for the ISA Sound Blaster and compatible sound
|
||||
* cards.
|
||||
*
|
||||
* This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
|
||||
* Version 2 (June 1991). See the "COPYING" file distributed with this
|
||||
* software for more info.
|
||||
*
|
||||
* This is a complete rewrite of the detection routines. This was
|
||||
* prompted by the PnP API change during v2.5 and the ugly state the
|
||||
* code was in.
|
||||
*
|
||||
* Copyright (C) by Paul Laufer 2002. Based on code originally by
|
||||
* Hannu Savolainen which was modified by many others over the
|
||||
* years. Authors specifically mentioned in the previous version were:
|
||||
* Daniel Stone, Alessandro Zummo, Jeff Garzik, Arnaldo Carvalho de
|
||||
* Melo, Daniel Church, and myself.
|
||||
*
|
||||
* 02-05-2003 Original Release, Paul Laufer <paul@laufernet.com>
|
||||
* 02-07-2003 Bug made it into first release. Take two.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include "sound_config.h"
|
||||
#include "sb_mixer.h"
|
||||
#include "sb.h"
|
||||
#ifdef CONFIG_PNP
|
||||
#include <linux/pnp.h>
|
||||
#endif /* CONFIG_PNP */
|
||||
#include "sb_card.h"
|
||||
|
||||
MODULE_DESCRIPTION("OSS Soundblaster ISA PnP and legacy sound driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
extern void *smw_free;
|
||||
|
||||
static int __initdata mpu_io = 0;
|
||||
static int __initdata io = -1;
|
||||
static int __initdata irq = -1;
|
||||
static int __initdata dma = -1;
|
||||
static int __initdata dma16 = -1;
|
||||
static int __initdata type = 0; /* Can set this to a specific card type */
|
||||
static int __initdata esstype = 0; /* ESS chip type */
|
||||
static int __initdata acer = 0; /* Do acer notebook init? */
|
||||
static int __initdata sm_games = 0; /* Logitech soundman games? */
|
||||
|
||||
static struct sb_card_config *legacy = NULL;
|
||||
|
||||
#ifdef CONFIG_PNP
|
||||
static int pnp_registered;
|
||||
static int __initdata pnp = 1;
|
||||
/*
|
||||
static int __initdata uart401 = 0;
|
||||
*/
|
||||
#else
|
||||
static int __initdata pnp = 0;
|
||||
#endif
|
||||
|
||||
module_param_hw(io, int, ioport, 000);
|
||||
MODULE_PARM_DESC(io, "Soundblaster i/o base address (0x220,0x240,0x260,0x280)");
|
||||
module_param_hw(irq, int, irq, 000);
|
||||
MODULE_PARM_DESC(irq, "IRQ (5,7,9,10)");
|
||||
module_param_hw(dma, int, dma, 000);
|
||||
MODULE_PARM_DESC(dma, "8-bit DMA channel (0,1,3)");
|
||||
module_param_hw(dma16, int, dma, 000);
|
||||
MODULE_PARM_DESC(dma16, "16-bit DMA channel (5,6,7)");
|
||||
module_param_hw(mpu_io, int, ioport, 000);
|
||||
MODULE_PARM_DESC(mpu_io, "MPU base address");
|
||||
module_param(type, int, 000);
|
||||
MODULE_PARM_DESC(type, "You can set this to specific card type (doesn't " \
|
||||
"work with pnp)");
|
||||
module_param(sm_games, int, 000);
|
||||
MODULE_PARM_DESC(sm_games, "Enable support for Logitech soundman games " \
|
||||
"(doesn't work with pnp)");
|
||||
module_param(esstype, int, 000);
|
||||
MODULE_PARM_DESC(esstype, "ESS chip type (doesn't work with pnp)");
|
||||
module_param(acer, int, 000);
|
||||
MODULE_PARM_DESC(acer, "Set this to detect cards in some ACER notebooks "\
|
||||
"(doesn't work with pnp)");
|
||||
|
||||
#ifdef CONFIG_PNP
|
||||
module_param(pnp, int, 000);
|
||||
MODULE_PARM_DESC(pnp, "Went set to 0 will disable detection using PnP. "\
|
||||
"Default is 1.\n");
|
||||
/* Not done yet.... */
|
||||
/*
|
||||
module_param(uart401, int, 000);
|
||||
MODULE_PARM_DESC(uart401, "When set to 1, will attempt to detect and enable"\
|
||||
"the mpu on some clones");
|
||||
*/
|
||||
#endif /* CONFIG_PNP */
|
||||
|
||||
/* OSS subsystem card registration shared by PnP and legacy routines */
|
||||
static int sb_register_oss(struct sb_card_config *scc, struct sb_module_options *sbmo)
|
||||
{
|
||||
if (!request_region(scc->conf.io_base, 16, "soundblaster")) {
|
||||
printk(KERN_ERR "sb: ports busy.\n");
|
||||
kfree(scc);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!sb_dsp_detect(&scc->conf, 0, 0, sbmo)) {
|
||||
release_region(scc->conf.io_base, 16);
|
||||
printk(KERN_ERR "sb: Failed DSP Detect.\n");
|
||||
kfree(scc);
|
||||
return -ENODEV;
|
||||
}
|
||||
if(!sb_dsp_init(&scc->conf, THIS_MODULE)) {
|
||||
printk(KERN_ERR "sb: Failed DSP init.\n");
|
||||
kfree(scc);
|
||||
return -ENODEV;
|
||||
}
|
||||
if(scc->mpucnf.io_base > 0) {
|
||||
scc->mpu = 1;
|
||||
printk(KERN_INFO "sb: Turning on MPU\n");
|
||||
if(!probe_sbmpu(&scc->mpucnf, THIS_MODULE))
|
||||
scc->mpu = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void sb_unload(struct sb_card_config *scc)
|
||||
{
|
||||
sb_dsp_unload(&scc->conf, 0);
|
||||
if(scc->mpu)
|
||||
unload_sbmpu(&scc->mpucnf);
|
||||
kfree(scc);
|
||||
}
|
||||
|
||||
/* Register legacy card with OSS subsystem */
|
||||
static int __init sb_init_legacy(void)
|
||||
{
|
||||
struct sb_module_options sbmo = {0};
|
||||
|
||||
if((legacy = kzalloc(sizeof(struct sb_card_config), GFP_KERNEL)) == NULL) {
|
||||
printk(KERN_ERR "sb: Error: Could not allocate memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
legacy->conf.io_base = io;
|
||||
legacy->conf.irq = irq;
|
||||
legacy->conf.dma = dma;
|
||||
legacy->conf.dma2 = dma16;
|
||||
legacy->conf.card_subtype = type;
|
||||
|
||||
legacy->mpucnf.io_base = mpu_io;
|
||||
legacy->mpucnf.irq = -1;
|
||||
legacy->mpucnf.dma = -1;
|
||||
legacy->mpucnf.dma2 = -1;
|
||||
|
||||
sbmo.esstype = esstype;
|
||||
sbmo.sm_games = sm_games;
|
||||
sbmo.acer = acer;
|
||||
|
||||
return sb_register_oss(legacy, &sbmo);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PNP
|
||||
|
||||
/* Populate the OSS subsystem structures with information from PnP */
|
||||
static void sb_dev2cfg(struct pnp_dev *dev, struct sb_card_config *scc)
|
||||
{
|
||||
scc->conf.io_base = -1;
|
||||
scc->conf.irq = -1;
|
||||
scc->conf.dma = -1;
|
||||
scc->conf.dma2 = -1;
|
||||
scc->mpucnf.io_base = -1;
|
||||
scc->mpucnf.irq = -1;
|
||||
scc->mpucnf.dma = -1;
|
||||
scc->mpucnf.dma2 = -1;
|
||||
|
||||
/* All clones layout their PnP tables differently and some use
|
||||
different logical devices for the MPU */
|
||||
if(!strncmp("CTL",scc->card_id,3)) {
|
||||
scc->conf.io_base = pnp_port_start(dev,0);
|
||||
scc->conf.irq = pnp_irq(dev,0);
|
||||
scc->conf.dma = pnp_dma(dev,0);
|
||||
scc->conf.dma2 = pnp_dma(dev,1);
|
||||
scc->mpucnf.io_base = pnp_port_start(dev,1);
|
||||
return;
|
||||
}
|
||||
if(!strncmp("tBA",scc->card_id,3)) {
|
||||
scc->conf.io_base = pnp_port_start(dev,0);
|
||||
scc->conf.irq = pnp_irq(dev,0);
|
||||
scc->conf.dma = pnp_dma(dev,0);
|
||||
scc->conf.dma2 = pnp_dma(dev,1);
|
||||
return;
|
||||
}
|
||||
if(!strncmp("ESS",scc->card_id,3)) {
|
||||
scc->conf.io_base = pnp_port_start(dev,0);
|
||||
scc->conf.irq = pnp_irq(dev,0);
|
||||
scc->conf.dma = pnp_dma(dev,0);
|
||||
scc->conf.dma2 = pnp_dma(dev,1);
|
||||
scc->mpucnf.io_base = pnp_port_start(dev,2);
|
||||
return;
|
||||
}
|
||||
if(!strncmp("CMI",scc->card_id,3)) {
|
||||
scc->conf.io_base = pnp_port_start(dev,0);
|
||||
scc->conf.irq = pnp_irq(dev,0);
|
||||
scc->conf.dma = pnp_dma(dev,0);
|
||||
scc->conf.dma2 = pnp_dma(dev,1);
|
||||
return;
|
||||
}
|
||||
if(!strncmp("RWB",scc->card_id,3)) {
|
||||
scc->conf.io_base = pnp_port_start(dev,0);
|
||||
scc->conf.irq = pnp_irq(dev,0);
|
||||
scc->conf.dma = pnp_dma(dev,0);
|
||||
return;
|
||||
}
|
||||
if(!strncmp("ALS",scc->card_id,3)) {
|
||||
if(!strncmp("ALS0007",scc->card_id,7)) {
|
||||
scc->conf.io_base = pnp_port_start(dev,0);
|
||||
scc->conf.irq = pnp_irq(dev,0);
|
||||
scc->conf.dma = pnp_dma(dev,0);
|
||||
} else {
|
||||
scc->conf.io_base = pnp_port_start(dev,0);
|
||||
scc->conf.irq = pnp_irq(dev,0);
|
||||
scc->conf.dma = pnp_dma(dev,1);
|
||||
scc->conf.dma2 = pnp_dma(dev,0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(!strncmp("RTL",scc->card_id,3)) {
|
||||
scc->conf.io_base = pnp_port_start(dev,0);
|
||||
scc->conf.irq = pnp_irq(dev,0);
|
||||
scc->conf.dma = pnp_dma(dev,1);
|
||||
scc->conf.dma2 = pnp_dma(dev,0);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int sb_pnp_devices;
|
||||
|
||||
/* Probe callback function for the PnP API */
|
||||
static int sb_pnp_probe(struct pnp_card_link *card, const struct pnp_card_device_id *card_id)
|
||||
{
|
||||
struct sb_card_config *scc;
|
||||
struct sb_module_options sbmo = {0}; /* Default to 0 for PnP */
|
||||
struct pnp_dev *dev = pnp_request_card_device(card, card_id->devs[0].id, NULL);
|
||||
|
||||
if(!dev){
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if((scc = kzalloc(sizeof(struct sb_card_config), GFP_KERNEL)) == NULL) {
|
||||
printk(KERN_ERR "sb: Error: Could not allocate memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "sb: PnP: Found Card Named = \"%s\", Card PnP id = " \
|
||||
"%s, Device PnP id = %s\n", card->card->name, card_id->id,
|
||||
dev->id->id);
|
||||
|
||||
scc->card_id = card_id->id;
|
||||
scc->dev_id = dev->id->id;
|
||||
sb_dev2cfg(dev, scc);
|
||||
|
||||
printk(KERN_INFO "sb: PnP: Detected at: io=0x%x, irq=%d, " \
|
||||
"dma=%d, dma16=%d\n", scc->conf.io_base, scc->conf.irq,
|
||||
scc->conf.dma, scc->conf.dma2);
|
||||
|
||||
pnp_set_card_drvdata(card, scc);
|
||||
sb_pnp_devices++;
|
||||
|
||||
return sb_register_oss(scc, &sbmo);
|
||||
}
|
||||
|
||||
static void sb_pnp_remove(struct pnp_card_link *card)
|
||||
{
|
||||
struct sb_card_config *scc = pnp_get_card_drvdata(card);
|
||||
|
||||
if(!scc)
|
||||
return;
|
||||
|
||||
printk(KERN_INFO "sb: PnP: Removing %s\n", scc->card_id);
|
||||
|
||||
sb_unload(scc);
|
||||
}
|
||||
|
||||
static struct pnp_card_driver sb_pnp_driver = {
|
||||
.name = "OSS SndBlstr", /* 16 character limit */
|
||||
.id_table = sb_pnp_card_table,
|
||||
.probe = sb_pnp_probe,
|
||||
.remove = sb_pnp_remove,
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pnp_card, sb_pnp_card_table);
|
||||
#endif /* CONFIG_PNP */
|
||||
|
||||
static void sb_unregister_all(void)
|
||||
{
|
||||
#ifdef CONFIG_PNP
|
||||
if (pnp_registered)
|
||||
pnp_unregister_card_driver(&sb_pnp_driver);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int __init sb_init(void)
|
||||
{
|
||||
int lres = 0;
|
||||
int pres = 0;
|
||||
|
||||
printk(KERN_INFO "sb: Init: Starting Probe...\n");
|
||||
|
||||
if(io != -1 && irq != -1 && dma != -1) {
|
||||
printk(KERN_INFO "sb: Probing legacy card with io=%x, "\
|
||||
"irq=%d, dma=%d, dma16=%d\n",io, irq, dma, dma16);
|
||||
lres = sb_init_legacy();
|
||||
} else if((io != -1 || irq != -1 || dma != -1) ||
|
||||
(!pnp && (io == -1 && irq == -1 && dma == -1)))
|
||||
printk(KERN_ERR "sb: Error: At least io, irq, and dma "\
|
||||
"must be set for legacy cards.\n");
|
||||
|
||||
#ifdef CONFIG_PNP
|
||||
if(pnp) {
|
||||
int err = pnp_register_card_driver(&sb_pnp_driver);
|
||||
if (!err)
|
||||
pnp_registered = 1;
|
||||
pres = sb_pnp_devices;
|
||||
}
|
||||
#endif
|
||||
printk(KERN_INFO "sb: Init: Done\n");
|
||||
|
||||
/* If either PnP or Legacy registered a card then return
|
||||
* success */
|
||||
if (pres == 0 && lres <= 0) {
|
||||
sb_unregister_all();
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit sb_exit(void)
|
||||
{
|
||||
printk(KERN_INFO "sb: Unloading...\n");
|
||||
|
||||
/* Unload legacy card */
|
||||
if (legacy) {
|
||||
printk (KERN_INFO "sb: Unloading legacy card\n");
|
||||
sb_unload(legacy);
|
||||
}
|
||||
|
||||
sb_unregister_all();
|
||||
|
||||
vfree(smw_free);
|
||||
smw_free = NULL;
|
||||
}
|
||||
|
||||
module_init(sb_init);
|
||||
module_exit(sb_exit);
|
|
@ -1,149 +0,0 @@
|
|||
/*
|
||||
* sound/oss/sb_card.h
|
||||
*
|
||||
* This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
|
||||
* Version 2 (June 1991). See the "COPYING" file distributed with this
|
||||
* software for more info.
|
||||
*
|
||||
* 02-05-2002 Original Release, Paul Laufer <paul@laufernet.com>
|
||||
*/
|
||||
|
||||
struct sb_card_config {
|
||||
struct address_info conf;
|
||||
struct address_info mpucnf;
|
||||
const char *card_id;
|
||||
const char *dev_id;
|
||||
int mpu;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PNP
|
||||
|
||||
/*
|
||||
* SoundBlaster PnP tables and structures.
|
||||
*/
|
||||
|
||||
/* Card PnP ID Table */
|
||||
static struct pnp_card_device_id sb_pnp_card_table[] = {
|
||||
/* Sound Blaster 16 */
|
||||
{.id = "CTL0024", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster 16 */
|
||||
{.id = "CTL0025", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster 16 */
|
||||
{.id = "CTL0026", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster 16 */
|
||||
{.id = "CTL0027", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster 16 */
|
||||
{.id = "CTL0028", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster 16 */
|
||||
{.id = "CTL0029", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster 16 */
|
||||
{.id = "CTL002a", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster 16 */
|
||||
{.id = "CTL002b", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster 16 */
|
||||
{.id = "CTL002c", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster 16 */
|
||||
{.id = "CTL00ed", .driver_data = 0, .devs = { {.id="CTL0041"}, } },
|
||||
/* Sound Blaster 16 */
|
||||
{.id = "CTL0086", .driver_data = 0, .devs = { {.id="CTL0041"}, } },
|
||||
/* Sound Blaster Vibra16S */
|
||||
{.id = "CTL0051", .driver_data = 0, .devs = { {.id="CTL0001"}, } },
|
||||
/* Sound Blaster Vibra16C */
|
||||
{.id = "CTL0070", .driver_data = 0, .devs = { {.id="CTL0001"}, } },
|
||||
/* Sound Blaster Vibra16CL */
|
||||
{.id = "CTL0080", .driver_data = 0, .devs = { {.id="CTL0041"}, } },
|
||||
/* Sound Blaster Vibra16CL */
|
||||
{.id = "CTL00F0", .driver_data = 0, .devs = { {.id="CTL0043"}, } },
|
||||
/* Sound Blaster AWE 32 */
|
||||
{.id = "CTL0039", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster AWE 32 */
|
||||
{.id = "CTL0042", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster AWE 32 */
|
||||
{.id = "CTL0043", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster AWE 32 */
|
||||
{.id = "CTL0044", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster AWE 32 */
|
||||
{.id = "CTL0045", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster AWE 32 */
|
||||
{.id = "CTL0046", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster AWE 32 */
|
||||
{.id = "CTL0047", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster AWE 32 */
|
||||
{.id = "CTL0048", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster AWE 32 */
|
||||
{.id = "CTL0054", .driver_data = 0, .devs = { {.id="CTL0031"}, } },
|
||||
/* Sound Blaster AWE 32 */
|
||||
{.id = "CTL009C", .driver_data = 0, .devs = { {.id="CTL0041"}, } },
|
||||
/* Createive SB32 PnP */
|
||||
{.id = "CTL009F", .driver_data = 0, .devs = { {.id="CTL0041"}, } },
|
||||
/* Sound Blaster AWE 64 */
|
||||
{.id = "CTL009D", .driver_data = 0, .devs = { {.id="CTL0042"}, } },
|
||||
/* Sound Blaster AWE 64 Gold */
|
||||
{.id = "CTL009E", .driver_data = 0, .devs = { {.id="CTL0044"}, } },
|
||||
/* Sound Blaster AWE 64 Gold */
|
||||
{.id = "CTL00B2", .driver_data = 0, .devs = { {.id="CTL0044"}, } },
|
||||
/* Sound Blaster AWE 64 */
|
||||
{.id = "CTL00C1", .driver_data = 0, .devs = { {.id="CTL0042"}, } },
|
||||
/* Sound Blaster AWE 64 */
|
||||
{.id = "CTL00C3", .driver_data = 0, .devs = { {.id="CTL0045"}, } },
|
||||
/* Sound Blaster AWE 64 */
|
||||
{.id = "CTL00C5", .driver_data = 0, .devs = { {.id="CTL0045"}, } },
|
||||
/* Sound Blaster AWE 64 */
|
||||
{.id = "CTL00C7", .driver_data = 0, .devs = { {.id="CTL0045"}, } },
|
||||
/* Sound Blaster AWE 64 */
|
||||
{.id = "CTL00E4", .driver_data = 0, .devs = { {.id="CTL0045"}, } },
|
||||
/* Sound Blaster AWE 64 */
|
||||
{.id = "CTL00E9", .driver_data = 0, .devs = { {.id="CTL0045"}, } },
|
||||
/* ESS 1868 */
|
||||
{.id = "ESS0968", .driver_data = 0, .devs = { {.id="ESS0968"}, } },
|
||||
/* ESS 1868 */
|
||||
{.id = "ESS1868", .driver_data = 0, .devs = { {.id="ESS1868"}, } },
|
||||
/* ESS 1868 */
|
||||
{.id = "ESS1868", .driver_data = 0, .devs = { {.id="ESS8611"}, } },
|
||||
/* ESS 1869 PnP AudioDrive */
|
||||
{.id = "ESS0003", .driver_data = 0, .devs = { {.id="ESS1869"}, } },
|
||||
/* ESS 1869 */
|
||||
{.id = "ESS1869", .driver_data = 0, .devs = { {.id="ESS1869"}, } },
|
||||
/* ESS 1878 */
|
||||
{.id = "ESS1878", .driver_data = 0, .devs = { {.id="ESS1878"}, } },
|
||||
/* ESS 1879 */
|
||||
{.id = "ESS1879", .driver_data = 0, .devs = { {.id="ESS1879"}, } },
|
||||
/* CMI 8330 SoundPRO */
|
||||
{.id = "CMI0001", .driver_data = 0, .devs = { {.id="@X@0001"},
|
||||
{.id="@H@0001"},
|
||||
{.id="@@@0001"}, } },
|
||||
/* Diamond DT0197H */
|
||||
{.id = "RWR1688", .driver_data = 0, .devs = { {.id="@@@0001"},
|
||||
{.id="@X@0001"},
|
||||
{.id="@H@0001"}, } },
|
||||
/* ALS007 */
|
||||
{.id = "ALS0007", .driver_data = 0, .devs = { {.id="@@@0001"},
|
||||
{.id="@X@0001"},
|
||||
{.id="@H@0001"}, } },
|
||||
/* ALS100 */
|
||||
{.id = "ALS0001", .driver_data = 0, .devs = { {.id="@@@0001"},
|
||||
{.id="@X@0001"},
|
||||
{.id="@H@0001"}, } },
|
||||
/* ALS110 */
|
||||
{.id = "ALS0110", .driver_data = 0, .devs = { {.id="@@@1001"},
|
||||
{.id="@X@1001"},
|
||||
{.id="@H@0001"}, } },
|
||||
/* ALS120 */
|
||||
{.id = "ALS0120", .driver_data = 0, .devs = { {.id="@@@2001"},
|
||||
{.id="@X@2001"},
|
||||
{.id="@H@0001"}, } },
|
||||
/* ALS200 */
|
||||
{.id = "ALS0200", .driver_data = 0, .devs = { {.id="@@@0020"},
|
||||
{.id="@X@0030"},
|
||||
{.id="@H@0001"}, } },
|
||||
/* ALS200 */
|
||||
{.id = "RTL3000", .driver_data = 0, .devs = { {.id="@@@2001"},
|
||||
{.id="@X@2001"},
|
||||
{.id="@H@0001"}, } },
|
||||
/* Sound Blaster 16 (Virtual PC 2004) */
|
||||
{.id = "tBA03b0", .driver_data = 0, .devs = { {.id="PNPb003"}, } },
|
||||
/* -end- */
|
||||
{.id = "", }
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
1822
sound/oss/sb_ess.c
1822
sound/oss/sb_ess.c
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue