Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/perex/alsa
* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/perex/alsa: (299 commits) [ALSA] version 1.0.16rc2 [ALSA] hda: fix Mic in as output [ALSA] emu10k1 - Another EMU0404 Board ID [ALSA] emu10k1 - Fix kthread handling at resume [ALSA] emu10k1: General cleanup, add new locks, fix alsa bug#3501, kernel bug#9304. [ALSA] emu10k1 - Use enum for emu_model types [ALSA] emu10k1 - Don't create emu1010 controls for non-emu boards [ALSA] emu10k1 - 1616(M) cardbus improvements [ALSA] snd:emu10k1: E-Mu updates. Fixes to firmware loading and support for 0404. [ALSA] emu10k1: Add comments regarding E-Mu ins and outs. [ALSA] oxygen: revert SPI clock frequency change for AK4396/WM8785 [ALSA] es1938 - improve capture hw pointer reads [ALSA] HDA-Intel - Add support for Intel SCH [ALSA] hda: Add GPIO mute support to STAC9205 [ALSA] hda-codec - Add Dell T3400 support [ALSA] hda-codec - Add model for HP DV9553EG laptop [ALSA] hda-codec - Control SPDIF as slave [ALSA] hda_intel: ALSA HD Audio patch for Intel ICH10 DeviceID's [ALSA] Fix Oops with PCM OSS sync [ALSA] hda-codec - Add speaker automute to ALC262 HP models ...
This commit is contained in:
commit
e1a9c9872d
|
@ -57,7 +57,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
- Default: 1
|
||||
- For auto-loading more than one card, specify this
|
||||
option together with snd-card-X aliases.
|
||||
|
||||
slots - Reserve the slot index for the given driver.
|
||||
This option takes multiple strings.
|
||||
See "Module Autoloading Support" section for details.
|
||||
|
||||
Module snd-pcm-oss
|
||||
------------------
|
||||
|
@ -148,13 +150,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for sound cards based on Analog Devices AD1816A/AD1815 ISA chips.
|
||||
|
||||
port - port # for AD1816A chip (PnP setup)
|
||||
mpu_port - port # for MPU-401 UART (PnP setup)
|
||||
fm_port - port # for OPL3 (PnP setup)
|
||||
irq - IRQ # for AD1816A chip (PnP setup)
|
||||
mpu_irq - IRQ # for MPU-401 UART (PnP setup)
|
||||
dma1 - first DMA # for AD1816A chip (PnP setup)
|
||||
dma2 - second DMA # for AD1816A chip (PnP setup)
|
||||
clockfreq - Clock frequency for AD1816A chip (default = 0, 33000Hz)
|
||||
|
||||
This module supports multiple cards, autoprobe and PnP.
|
||||
|
@ -201,14 +196,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for sound cards based on Avance Logic ALS100/ALS120 ISA chips.
|
||||
|
||||
port - port # for ALS100 (SB16) chip (PnP setup)
|
||||
irq - IRQ # for ALS100 (SB16) chip (PnP setup)
|
||||
dma8 - 8-bit DMA # for ALS100 (SB16) chip (PnP setup)
|
||||
dma16 - 16-bit DMA # for ALS100 (SB16) chip (PnP setup)
|
||||
mpu_port - port # for MPU-401 UART (PnP setup)
|
||||
mpu_irq - IRQ # for MPU-401 (PnP setup)
|
||||
fm_port - port # for OPL3 FM (PnP setup)
|
||||
|
||||
This module supports multiple cards, autoprobe and PnP.
|
||||
|
||||
The power-management is supported.
|
||||
|
@ -302,15 +289,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for sound cards based on Aztech System AZT2320 ISA chip (PnP only).
|
||||
|
||||
port - port # for AZT2320 chip (PnP setup)
|
||||
wss_port - port # for WSS (PnP setup)
|
||||
mpu_port - port # for MPU-401 UART (PnP setup)
|
||||
fm_port - FM port # for AZT2320 chip (PnP setup)
|
||||
irq - IRQ # for AZT2320 (WSS) chip (PnP setup)
|
||||
mpu_irq - IRQ # for MPU-401 UART (PnP setup)
|
||||
dma1 - 1st DMA # for AZT2320 (WSS) chip (PnP setup)
|
||||
dma2 - 2nd DMA # for AZT2320 (WSS) chip (PnP setup)
|
||||
|
||||
This module supports multiple cards, PnP and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
@ -350,6 +328,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for sound cards based on C-Media CMI8330 ISA chips.
|
||||
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
with isapnp=0, the following options are available:
|
||||
|
||||
wssport - port # for CMI8330 chip (WSS)
|
||||
wssirq - IRQ # for CMI8330 chip (WSS)
|
||||
wssdma - first DMA # for CMI8330 chip (WSS)
|
||||
|
@ -404,6 +386,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for sound cards based on CS4232/CS4232A ISA chips.
|
||||
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
with isapnp=0, the following options are available:
|
||||
|
||||
port - port # for CS4232 chip (PnP setup - 0x534)
|
||||
cport - control port # for CS4232 chip (PnP setup - 0x120,0x210,0xf00)
|
||||
mpu_port - port # for MPU-401 UART (PnP setup - 0x300), -1 = disable
|
||||
|
@ -412,10 +398,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
mpu_irq - IRQ # for MPU-401 UART (9,11,12,15)
|
||||
dma1 - first DMA # for CS4232 chip (0,1,3)
|
||||
dma2 - second DMA # for Yamaha CS4232 chip (0,1,3), -1 = disable
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
This module supports multiple cards. This module does not support autoprobe
|
||||
thus main port must be specified!!! Other ports are optional.
|
||||
(if ISA PnP is not used) thus main port must be specified!!! Other ports are
|
||||
optional.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
|
@ -425,6 +411,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
Module for sound cards based on CS4235/CS4236/CS4236B/CS4237B/
|
||||
CS4238B/CS4239 ISA chips.
|
||||
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
with isapnp=0, the following options are available:
|
||||
|
||||
port - port # for CS4236 chip (PnP setup - 0x534)
|
||||
cport - control port # for CS4236 chip (PnP setup - 0x120,0x210,0xf00)
|
||||
mpu_port - port # for MPU-401 UART (PnP setup - 0x300), -1 = disable
|
||||
|
@ -433,7 +423,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
mpu_irq - IRQ # for MPU-401 UART (9,11,12,15)
|
||||
dma1 - first DMA # for CS4236 chip (0,1,3)
|
||||
dma2 - second DMA # for CS4236 chip (0,1,3), -1 = disable
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
This module supports multiple cards. This module does not support autoprobe
|
||||
(if ISA PnP is not used) thus main port and control port must be
|
||||
|
@ -503,13 +492,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
Module for Diamond Technologies DT-019X / Avance Logic ALS-007 (PnP
|
||||
only)
|
||||
|
||||
port - Port # (PnP setup)
|
||||
mpu_port - Port # for MPU-401 (PnP setup)
|
||||
fm_port - Port # for FM OPL-3 (PnP setup)
|
||||
irq - IRQ # (PnP setup)
|
||||
mpu_irq - IRQ # for MPU-401 (PnP setup)
|
||||
dma8 - DMA # (PnP setup)
|
||||
|
||||
This module supports multiple cards. This module is enabled only with
|
||||
ISA PnP support.
|
||||
|
||||
|
@ -607,10 +589,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for sound cards based on ESS ES968 chip (PnP only).
|
||||
|
||||
port - port # for ES968 (SB8) chip (PnP setup)
|
||||
irq - IRQ # for ES968 (SB8) chip (PnP setup)
|
||||
dma1 - DMA # for ES968 (SB8) chip (PnP setup)
|
||||
|
||||
This module supports multiple cards, PnP and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
@ -633,13 +611,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for ESS AudioDrive ES-18xx sound cards.
|
||||
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
with isapnp=0, the following options are available:
|
||||
|
||||
port - port # for ES-18xx chip (0x220,0x240,0x260)
|
||||
mpu_port - port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
|
||||
fm_port - port # for FM (optional, not used)
|
||||
irq - IRQ # for ES-18xx chip (5,7,9,10)
|
||||
dma1 - first DMA # for ES-18xx chip (0,1,3)
|
||||
dma2 - first DMA # for ES-18xx chip (0,1,3)
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
This module supports multiple cards, ISA PnP and autoprobe (without MPU-401
|
||||
port if native ISA PnP routines are not used).
|
||||
|
@ -763,9 +744,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
VIA VT8251/VT8237A,
|
||||
SIS966, ULI M5461
|
||||
|
||||
[Multiple options for each card instance]
|
||||
model - force the model name
|
||||
position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)
|
||||
probe_mask - Bitmask to probe codecs (default = -1, meaning all slots)
|
||||
|
||||
[Single (global) options]
|
||||
single_cmd - Use single immediate commands to communicate with
|
||||
codecs (for debugging only)
|
||||
enable_msi - Enable Message Signaled Interrupt (MSI) (default = off)
|
||||
|
@ -774,7 +758,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
power_save_controller - Reset HD-audio controller in power-saving mode
|
||||
(default = on)
|
||||
|
||||
This module supports one card and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Each codec may have a model table for different configurations.
|
||||
If your machine isn't listed there, the default (usually minimal)
|
||||
|
@ -817,17 +801,23 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
will Will laptops (PB V7900)
|
||||
replacer Replacer 672V
|
||||
basic fixed pin assignment (old default model)
|
||||
test for testing/debugging purpose, almost all controls can
|
||||
adjusted. Appearing only when compiled with
|
||||
$CONFIG_SND_DEBUG=y
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
ALC262
|
||||
fujitsu Fujitsu Laptop
|
||||
hp-bpc HP xw4400/6400/8400/9400 laptops
|
||||
hp-bpc-d7000 HP BPC D7000
|
||||
hp-tc-t5735 HP Thin Client T5735
|
||||
hp-rp5700 HP RP5700
|
||||
benq Benq ED8
|
||||
benq-t31 Benq T31
|
||||
hippo Hippo (ATI) with jack detection, Sony UX-90s
|
||||
hippo_1 Hippo (Benq) with jack detection
|
||||
sony-assamd Sony ASSAMD
|
||||
ultra Samsung Q1 Ultra Vista model
|
||||
basic fixed pin assignment w/o SPDIF
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
|
@ -835,6 +825,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
3stack 3-stack model
|
||||
toshiba Toshiba A205
|
||||
acer Acer laptops
|
||||
dell Dell OEM laptops (Vostro 1200)
|
||||
test for testing/debugging purpose, almost all controls can
|
||||
adjusted. Appearing only when compiled with
|
||||
$CONFIG_SND_DEBUG=y
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
ALC662
|
||||
|
@ -843,6 +837,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
3stack-6ch-dig 3-stack (6-channel) with SPDIF
|
||||
6stack-dig 6-stack with SPDIF
|
||||
lenovo-101e Lenovo laptop
|
||||
eeepc-p701 ASUS Eeepc P701
|
||||
eeepc-ep20 ASUS Eeepc EP20
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
ALC882/885
|
||||
|
@ -877,6 +873,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
haier-w66 Haier W66
|
||||
6stack-hp HP machines with 6stack (Nettle boards)
|
||||
3stack-hp HP machines with 3stack (Lucknow, Samba boards)
|
||||
6stack-dell Dell machines with 6stack (Inspiron 530)
|
||||
mitac Mitac 8252D
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
ALC861/660
|
||||
|
@ -928,6 +926,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
AD1984
|
||||
basic default configuration
|
||||
thinkpad Lenovo Thinkpad T61/X61
|
||||
dell Dell T3400
|
||||
|
||||
AD1986A
|
||||
6stack 6-jack, separate surrounds (default)
|
||||
|
@ -947,7 +946,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
auto auto-config reading BIOS (default)
|
||||
|
||||
Conexant 5045
|
||||
laptop Laptop config
|
||||
laptop-hpsense Laptop with HP sense (old model laptop)
|
||||
laptop-micsense Laptop with Mic sense (old model fujitsu)
|
||||
laptop-hpmicsense Laptop with HP and Mic senses
|
||||
benq Benq R55E
|
||||
test for testing/debugging purpose, almost all controls
|
||||
can be adjusted. Appearing only when compiled with
|
||||
$CONFIG_SND_DEBUG=y
|
||||
|
@ -960,6 +962,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
can be adjusted. Appearing only when compiled with
|
||||
$CONFIG_SND_DEBUG=y
|
||||
|
||||
Conexant 5051
|
||||
laptop Basic Laptop config (default)
|
||||
hp HP Spartan laptop
|
||||
|
||||
STAC9200
|
||||
ref Reference board
|
||||
dell-d21 Dell (unknown)
|
||||
|
@ -1091,6 +1097,15 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
See hdspm.txt for details.
|
||||
|
||||
Module snd-hifier
|
||||
-----------------
|
||||
|
||||
Module for the MediaTek/TempoTec HiFier Fantasia sound card.
|
||||
|
||||
This module supports autoprobe and multiple cards.
|
||||
|
||||
Power management is _not_ supported.
|
||||
|
||||
Module snd-ice1712
|
||||
------------------
|
||||
|
||||
|
@ -1156,11 +1171,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
* Chaintech 9CJS
|
||||
* Chaintech AV-710
|
||||
* Shuttle SN25P
|
||||
* Onkyo SE-90PCI
|
||||
* Onkyo SE-200PCI
|
||||
|
||||
model - Use the given board model, one of the following:
|
||||
revo51, revo71, amp2000, prodigy71, prodigy71lt,
|
||||
prodigy192, aureon51, aureon71, universe, ap192,
|
||||
k8x800, phase22, phase28, ms300, av710
|
||||
k8x800, phase22, phase28, ms300, av710, se200pci,
|
||||
se90pci
|
||||
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
|
@ -1257,15 +1275,19 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
Module for Gravis UltraSound PnP, Dynasonic 3-D/Pro, STB Sound Rage 32
|
||||
and other sound cards based on AMD InterWave (tm) chip.
|
||||
|
||||
port - port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
|
||||
irq - IRQ # for InterWave chip (3,5,9,11,12,15)
|
||||
dma1 - DMA # for InterWave chip (0,1,3,5,6,7)
|
||||
dma2 - DMA # for InterWave chip (0,1,3,5,6,7,-1=disable)
|
||||
joystick_dac - 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
|
||||
midi - 1 = MIDI UART enable, 0 = MIDI UART disable (default)
|
||||
pcm_voices - reserved PCM voices for the synthesizer (default 2)
|
||||
effect - 1 = InterWave effects enable (default 0);
|
||||
requires 8 voices
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
with isapnp=0, the following options are available:
|
||||
|
||||
port - port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
|
||||
irq - IRQ # for InterWave chip (3,5,9,11,12,15)
|
||||
dma1 - DMA # for InterWave chip (0,1,3,5,6,7)
|
||||
dma2 - DMA # for InterWave chip (0,1,3,5,6,7,-1=disable)
|
||||
|
||||
This module supports multiple cards, autoprobe and ISA PnP.
|
||||
|
||||
|
@ -1276,16 +1298,20 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
and other sound cards based on AMD InterWave (tm) chip with TEA6330T
|
||||
circuit for extended control of bass, treble and master volume.
|
||||
|
||||
port - port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
|
||||
port_tc - tone control (i2c bus) port # for TEA6330T chip (0x350,0x360,0x370,0x380)
|
||||
irq - IRQ # for InterWave chip (3,5,9,11,12,15)
|
||||
dma1 - DMA # for InterWave chip (0,1,3,5,6,7)
|
||||
dma2 - DMA # for InterWave chip (0,1,3,5,6,7,-1=disable)
|
||||
joystick_dac - 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
|
||||
midi - 1 = MIDI UART enable, 0 = MIDI UART disable (default)
|
||||
pcm_voices - reserved PCM voices for the synthesizer (default 2)
|
||||
effect - 1 = InterWave effects enable (default 0);
|
||||
requires 8 voices
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
with isapnp=0, the following options are available:
|
||||
|
||||
port - port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
|
||||
port_tc - tone control (i2c bus) port # for TEA6330T chip (0x350,0x360,0x370,0x380)
|
||||
irq - IRQ # for InterWave chip (3,5,9,11,12,15)
|
||||
dma1 - DMA # for InterWave chip (0,1,3,5,6,7)
|
||||
dma2 - DMA # for InterWave chip (0,1,3,5,6,7,-1=disable)
|
||||
|
||||
This module supports multiple cards, autoprobe and ISA PnP.
|
||||
|
||||
|
@ -1473,6 +1499,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for Yamaha OPL3-SA2/SA3 sound cards.
|
||||
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
with isapnp=0, the following options are available:
|
||||
|
||||
port - control port # for OPL3-SA chip (0x370)
|
||||
sb_port - SB port # for OPL3-SA chip (0x220,0x240)
|
||||
wss_port - WSS port # for OPL3-SA chip (0x530,0xe80,0xf40,0x604)
|
||||
|
@ -1481,7 +1511,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
irq - IRQ # for OPL3-SA chip (5,7,9,10)
|
||||
dma1 - first DMA # for Yamaha OPL3-SA chip (0,1,3)
|
||||
dma2 - second DMA # for Yamaha OPL3-SA chip (0,1,3), -1 = disable
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
This module supports multiple cards and ISA PnP. It does not support
|
||||
autoprobe (if ISA PnP is not used) thus all ports must be specified!!!
|
||||
|
@ -1494,6 +1523,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
Module for sound cards based on OPTi 82c92x and Analog Devices AD1848 chips.
|
||||
Module works with OAK Mozart cards as well.
|
||||
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
with isapnp=0, the following options are available:
|
||||
|
||||
port - port # for WSS chip (0x530,0xe80,0xf40,0x604)
|
||||
mpu_port - port # for MPU-401 UART (0x300,0x310,0x320,0x330)
|
||||
fm_port - port # for OPL3 device (0x388)
|
||||
|
@ -1508,6 +1541,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for sound cards based on OPTi 82c92x and Crystal CS4231 chips.
|
||||
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
with isapnp=0, the following options are available:
|
||||
|
||||
port - port # for WSS chip (0x530,0xe80,0xf40,0x604)
|
||||
mpu_port - port # for MPU-401 UART (0x300,0x310,0x320,0x330)
|
||||
fm_port - port # for OPL3 device (0x388)
|
||||
|
@ -1523,6 +1560,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for sound cards based on OPTi 82c93x chips.
|
||||
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
with isapnp=0, the following options are available:
|
||||
|
||||
port - port # for WSS chip (0x530,0xe80,0xf40,0x604)
|
||||
mpu_port - port # for MPU-401 UART (0x300,0x310,0x320,0x330)
|
||||
fm_port - port # for OPL3 device (0x388)
|
||||
|
@ -1533,6 +1574,22 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
This module supports only one card, autoprobe and PnP.
|
||||
|
||||
Module snd-oxygen
|
||||
-----------------
|
||||
|
||||
Module for sound cards based on the C-Media CMI8788 chip:
|
||||
* Asound A-8788
|
||||
* AuzenTech X-Meridian
|
||||
* Bgears b-Enspirer
|
||||
* Club3D Theatron DTS
|
||||
* HT-Omega Claro
|
||||
* Razer Barracuda AC-1
|
||||
* Sondigo Inferno
|
||||
|
||||
This module supports autoprobe and multiple cards.
|
||||
|
||||
Power management is _not_ supported.
|
||||
|
||||
Module snd-pcxhr
|
||||
----------------
|
||||
|
||||
|
@ -1647,6 +1704,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
SoundBlaster AWE 32 (PnP),
|
||||
SoundBlaster AWE 64 PnP
|
||||
|
||||
mic_agc - Mic Auto-Gain-Control - 0 = disable, 1 = enable (default)
|
||||
csp - ASP/CSP chip support - 0 = disable (default), 1 = enable
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
with isapnp=0, the following options are available:
|
||||
|
||||
port - port # for SB DSP 4.x chip (0x220,0x240,0x260)
|
||||
mpu_port - port # for MPU-401 UART (0x300,0x330), -1 = disable
|
||||
awe_port - base port # for EMU8000 synthesizer (0x620,0x640,0x660)
|
||||
|
@ -1654,9 +1717,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
irq - IRQ # for SB DSP 4.x chip (5,7,9,10)
|
||||
dma8 - 8-bit DMA # for SB DSP 4.x chip (0,1,3)
|
||||
dma16 - 16-bit DMA # for SB DSP 4.x chip (5,6,7)
|
||||
mic_agc - Mic Auto-Gain-Control - 0 = disable, 1 = enable (default)
|
||||
csp - ASP/CSP chip support - 0 = disable (default), 1 = enable
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
This module supports multiple cards, autoprobe and ISA PnP.
|
||||
|
||||
|
@ -1739,18 +1799,21 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for Turtle Beach Maui, Tropez and Tropez+ sound cards.
|
||||
|
||||
use_cs4232_midi - Use CS4232 MPU-401 interface
|
||||
(inaccessibly located inside your computer)
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
with isapnp=0, the following options are available:
|
||||
|
||||
cs4232_pcm_port - Port # for CS4232 PCM interface.
|
||||
cs4232_pcm_irq - IRQ # for CS4232 PCM interface (5,7,9,11,12,15).
|
||||
cs4232_mpu_port - Port # for CS4232 MPU-401 interface.
|
||||
cs4232_mpu_irq - IRQ # for CS4232 MPU-401 interface (9,11,12,15).
|
||||
use_cs4232_midi - Use CS4232 MPU-401 interface
|
||||
(inaccessibly located inside your computer)
|
||||
ics2115_port - Port # for ICS2115
|
||||
ics2115_irq - IRQ # for ICS2115
|
||||
fm_port - FM OPL-3 Port #
|
||||
dma1 - DMA1 # for CS4232 PCM interface.
|
||||
dma2 - DMA2 # for CS4232 PCM interface.
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
The below are options for wavefront_synth features:
|
||||
wf_raw - Assume that we need to boot the OS (default:no)
|
||||
|
@ -1965,6 +2028,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-virtuoso
|
||||
-------------------
|
||||
|
||||
Module for sound cards based on the Asus AV200 chip, i.e.,
|
||||
Xonar D2 and Xonar D2X.
|
||||
|
||||
This module supports autoprobe and multiple cards.
|
||||
|
||||
Power management is _not_ supported.
|
||||
|
||||
Module snd-vx222
|
||||
----------------
|
||||
|
||||
|
@ -2135,6 +2208,23 @@ alias sound-slot-1 snd-ens1371
|
|||
In this example, the interwave card is always loaded as the first card
|
||||
(index 0) and ens1371 as the second (index 1).
|
||||
|
||||
Alternative (and new) way to fixate the slot assignment is to use
|
||||
"slots" option of snd module. In the case above, specify like the
|
||||
following:
|
||||
|
||||
options snd slots=snd-interwave,snd-ens1371
|
||||
|
||||
Then, the first slot (#0) is reserved for snd-interwave driver, and
|
||||
the second (#1) for snd-ens1371. You can omit index option in each
|
||||
driver if slots option is used (although you can still have them at
|
||||
the same time as long as they don't conflict).
|
||||
|
||||
The slots option is especially useful for avoiding the possible
|
||||
hot-plugging and the resultant slot conflict. For example, in the
|
||||
case above again, the first two slots are already reserved. If any
|
||||
other driver (e.g. snd-usb-audio) is loaded before snd-interwave or
|
||||
snd-ens1371, it will be assigned to the third or later slot.
|
||||
|
||||
|
||||
ALSA PCM devices to OSS devices mapping
|
||||
=======================================
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
|||
ASoC currently supports the three main Digital Audio Interfaces (DAI) found on
|
||||
SoC controllers and portable audio CODECS today, namely AC97, I2S and PCM.
|
||||
SoC controllers and portable audio CODECs today, namely AC97, I2S and PCM.
|
||||
|
||||
|
||||
AC97
|
||||
|
@ -25,7 +25,7 @@ left/right clock (LRC) synchronise the link. I2S is flexible in that either the
|
|||
controller or CODEC can drive (master) the BCLK and LRC clock lines. Bit clock
|
||||
usually varies depending on the sample rate and the master system clock
|
||||
(SYSCLK). LRCLK is the same as the sample rate. A few devices support separate
|
||||
ADC and DAC LRCLK's, this allows for simultaneous capture and playback at
|
||||
ADC and DAC LRCLKs, this allows for simultaneous capture and playback at
|
||||
different sample rates.
|
||||
|
||||
I2S has several different operating modes:-
|
||||
|
@ -35,7 +35,7 @@ I2S has several different operating modes:-
|
|||
|
||||
o Left Justified - MSB is transmitted on transition of LRC.
|
||||
|
||||
o Right Justified - MSB is transmitted sample size BCLK's before LRC
|
||||
o Right Justified - MSB is transmitted sample size BCLKs before LRC
|
||||
transition.
|
||||
|
||||
PCM
|
||||
|
|
|
@ -13,7 +13,7 @@ or SYSCLK). This audio master clock can be derived from a number of sources
|
|||
(e.g. crystal, PLL, CPU clock) and is responsible for producing the correct
|
||||
audio playback and capture sample rates.
|
||||
|
||||
Some master clocks (e.g. PLL's and CPU based clocks) are configurable in that
|
||||
Some master clocks (e.g. PLLs and CPU based clocks) are configurable in that
|
||||
their speed can be altered by software (depending on the system use and to save
|
||||
power). Other master clocks are fixed at a set frequency (i.e. crystals).
|
||||
|
||||
|
@ -41,11 +41,11 @@ BCLK = LRC * x
|
|||
BCLK = LRC * Channels * Word Size
|
||||
|
||||
This relationship depends on the codec or SoC CPU in particular. In general
|
||||
it's best to configure BCLK to the lowest possible speed (depending on your
|
||||
it is best to configure BCLK to the lowest possible speed (depending on your
|
||||
rate, number of channels and word size) to save on power.
|
||||
|
||||
It's also desirable to use the codec (if possible) to drive (or master) the
|
||||
audio clocks as it's usually gives more accurate sample rates than the CPU.
|
||||
It is also desirable to use the codec (if possible) to drive (or master) the
|
||||
audio clocks as it usually gives more accurate sample rates than the CPU.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ code should be added to the platform and machine drivers respectively.
|
|||
Each codec driver *must* provide the following features:-
|
||||
|
||||
1) Codec DAI and PCM configuration
|
||||
2) Codec control IO - using I2C, 3 Wire(SPI) or both API's
|
||||
2) Codec control IO - using I2C, 3 Wire(SPI) or both APIs
|
||||
3) Mixers and audio controls
|
||||
4) Codec audio operations
|
||||
|
||||
|
@ -19,7 +19,7 @@ Optionally, codec drivers can also provide:-
|
|||
6) DAPM event handler.
|
||||
7) DAC Digital mute control.
|
||||
|
||||
It's probably best to use this guide in conjunction with the existing codec
|
||||
Its probably best to use this guide in conjunction with the existing codec
|
||||
driver code in sound/soc/codecs/
|
||||
|
||||
ASoC Codec driver breakdown
|
||||
|
@ -27,8 +27,8 @@ ASoC Codec driver breakdown
|
|||
|
||||
1 - Codec DAI and PCM configuration
|
||||
-----------------------------------
|
||||
Each codec driver must have a struct snd_soc_codec_dai to define it's DAI and
|
||||
PCM's capabilities and operations. This struct is exported so that it can be
|
||||
Each codec driver must have a struct snd_soc_codec_dai to define its DAI and
|
||||
PCM capabilities and operations. This struct is exported so that it can be
|
||||
registered with the core by your machine driver.
|
||||
|
||||
e.g.
|
||||
|
@ -67,18 +67,18 @@ EXPORT_SYMBOL_GPL(wm8731_dai);
|
|||
|
||||
2 - Codec control IO
|
||||
--------------------
|
||||
The codec can usually be controlled via an I2C or SPI style interface (AC97
|
||||
combines control with data in the DAI). The codec drivers will have to provide
|
||||
functions to read and write the codec registers along with supplying a register
|
||||
cache:-
|
||||
The codec can usually be controlled via an I2C or SPI style interface
|
||||
(AC97 combines control with data in the DAI). The codec drivers provide
|
||||
functions to read and write the codec registers along with supplying a
|
||||
register cache:-
|
||||
|
||||
/* IO control data and register cache */
|
||||
void *control_data; /* codec control (i2c/3wire) data */
|
||||
void *reg_cache;
|
||||
|
||||
Codec read/write should do any data formatting and call the hardware read write
|
||||
below to perform the IO. These functions are called by the core and alsa when
|
||||
performing DAPM or changing the mixer:-
|
||||
Codec read/write should do any data formatting and call the hardware
|
||||
read write below to perform the IO. These functions are called by the
|
||||
core and ALSA when performing DAPM or changing the mixer:-
|
||||
|
||||
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
|
||||
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
|
||||
|
@ -131,7 +131,7 @@ Defines a stereo enumerated control
|
|||
|
||||
4 - Codec Audio Operations
|
||||
--------------------------
|
||||
The codec driver also supports the following alsa operations:-
|
||||
The codec driver also supports the following ALSA operations:-
|
||||
|
||||
/* SoC audio ops */
|
||||
struct snd_soc_ops {
|
||||
|
@ -142,15 +142,15 @@ struct snd_soc_ops {
|
|||
int (*prepare)(struct snd_pcm_substream *);
|
||||
};
|
||||
|
||||
Please refer to the alsa driver PCM documentation for details.
|
||||
Please refer to the ALSA driver PCM documentation for details.
|
||||
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
|
||||
|
||||
|
||||
5 - DAPM description.
|
||||
---------------------
|
||||
The Dynamic Audio Power Management description describes the codec's power
|
||||
components, their relationships and registers to the ASoC core. Please read
|
||||
dapm.txt for details of building the description.
|
||||
The Dynamic Audio Power Management description describes the codec power
|
||||
components and their relationships and registers to the ASoC core.
|
||||
Please read dapm.txt for details of building the description.
|
||||
|
||||
Please also see the examples in other codec drivers.
|
||||
|
||||
|
@ -158,8 +158,8 @@ Please also see the examples in other codec drivers.
|
|||
6 - DAPM event handler
|
||||
----------------------
|
||||
This function is a callback that handles codec domain PM calls and system
|
||||
domain PM calls (e.g. suspend and resume). It's used to put the codec to sleep
|
||||
when not in use.
|
||||
domain PM calls (e.g. suspend and resume). It is used to put the codec
|
||||
to sleep when not in use.
|
||||
|
||||
Power states:-
|
||||
|
||||
|
@ -175,13 +175,14 @@ Power states:-
|
|||
SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
|
||||
|
||||
|
||||
7 - Codec DAC digital mute control.
|
||||
------------------------------------
|
||||
Most codecs have a digital mute before the DAC's that can be used to minimise
|
||||
any system noise. The mute stops any digital data from entering the DAC.
|
||||
7 - Codec DAC digital mute control
|
||||
----------------------------------
|
||||
Most codecs have a digital mute before the DACs that can be used to
|
||||
minimise any system noise. The mute stops any digital data from
|
||||
entering the DAC.
|
||||
|
||||
A callback can be created that is called by the core for each codec DAI when the
|
||||
mute is applied or freed.
|
||||
A callback can be created that is called by the core for each codec DAI
|
||||
when the mute is applied or freed.
|
||||
|
||||
i.e.
|
||||
|
||||
|
|
|
@ -4,20 +4,20 @@ Dynamic Audio Power Management for Portable Devices
|
|||
1. Description
|
||||
==============
|
||||
|
||||
Dynamic Audio Power Management (DAPM) is designed to allow portable Linux devices
|
||||
to use the minimum amount of power within the audio subsystem at all times. It
|
||||
is independent of other kernel PM and as such, can easily co-exist with the
|
||||
other PM systems.
|
||||
Dynamic Audio Power Management (DAPM) is designed to allow portable
|
||||
Linux devices to use the minimum amount of power within the audio
|
||||
subsystem at all times. It is independent of other kernel PM and as
|
||||
such, can easily co-exist with the other PM systems.
|
||||
|
||||
DAPM is also completely transparent to all user space applications as all power
|
||||
switching is done within the ASoC core. No code changes or recompiling are
|
||||
required for user space applications. DAPM makes power switching decisions based
|
||||
upon any audio stream (capture/playback) activity and audio mixer settings
|
||||
within the device.
|
||||
DAPM is also completely transparent to all user space applications as
|
||||
all power switching is done within the ASoC core. No code changes or
|
||||
recompiling are required for user space applications. DAPM makes power
|
||||
switching decisions based upon any audio stream (capture/playback)
|
||||
activity and audio mixer settings within the device.
|
||||
|
||||
DAPM spans the whole machine. It covers power control within the entire audio
|
||||
subsystem, this includes internal codec power blocks and machine level power
|
||||
systems.
|
||||
DAPM spans the whole machine. It covers power control within the entire
|
||||
audio subsystem, this includes internal codec power blocks and machine
|
||||
level power systems.
|
||||
|
||||
There are 4 power domains within DAPM
|
||||
|
||||
|
@ -34,7 +34,7 @@ There are 4 power domains within DAPM
|
|||
Automatically set when mixer and mux settings are changed by the user.
|
||||
e.g. alsamixer, amixer.
|
||||
|
||||
4. Stream domain - DAC's and ADC's.
|
||||
4. Stream domain - DACs and ADCs.
|
||||
Enabled and disabled when stream playback/capture is started and
|
||||
stopped respectively. e.g. aplay, arecord.
|
||||
|
||||
|
@ -51,7 +51,7 @@ widgets hereafter.
|
|||
Audio DAPM widgets fall into a number of types:-
|
||||
|
||||
o Mixer - Mixes several analog signals into a single analog signal.
|
||||
o Mux - An analog switch that outputs only 1 of it's inputs.
|
||||
o Mux - An analog switch that outputs only one of many inputs.
|
||||
o PGA - A programmable gain amplifier or attenuation widget.
|
||||
o ADC - Analog to Digital Converter
|
||||
o DAC - Digital to Analog Converter
|
||||
|
@ -78,14 +78,14 @@ parameters for stream name and kcontrols.
|
|||
2.1 Stream Domain Widgets
|
||||
-------------------------
|
||||
|
||||
Stream Widgets relate to the stream power domain and only consist of ADC's
|
||||
(analog to digital converters) and DAC's (digital to analog converters).
|
||||
Stream Widgets relate to the stream power domain and only consist of ADCs
|
||||
(analog to digital converters) and DACs (digital to analog converters).
|
||||
|
||||
Stream widgets have the following format:-
|
||||
|
||||
SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
|
||||
|
||||
NOTE: the stream name must match the corresponding stream name in your codecs
|
||||
NOTE: the stream name must match the corresponding stream name in your codec
|
||||
snd_soc_codec_dai.
|
||||
|
||||
e.g. stream widgets for HiFi playback and capture
|
||||
|
@ -97,7 +97,7 @@ SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
|
|||
2.2 Path Domain Widgets
|
||||
-----------------------
|
||||
|
||||
Path domain widgets have a ability to control or effect the audio signal or
|
||||
Path domain widgets have a ability to control or affect the audio signal or
|
||||
audio paths within the audio subsystem. They have the following form:-
|
||||
|
||||
SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)
|
||||
|
@ -149,7 +149,7 @@ SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
|
|||
2.4 Codec Domain
|
||||
----------------
|
||||
|
||||
The Codec power domain has no widgets and is handled by the codecs DAPM event
|
||||
The codec power domain has no widgets and is handled by the codecs DAPM event
|
||||
handler. This handler is called when the codec powerstate is changed wrt to any
|
||||
stream event or by kernel PM events.
|
||||
|
||||
|
@ -158,8 +158,8 @@ stream event or by kernel PM events.
|
|||
-------------------
|
||||
|
||||
Sometimes widgets exist in the codec or machine audio map that don't have any
|
||||
corresponding register bit for power control. In this case it's necessary to
|
||||
create a virtual widget - a widget with no control bits e.g.
|
||||
corresponding soft power control. In this case it is necessary to create
|
||||
a virtual widget - a widget with no control bits e.g.
|
||||
|
||||
SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
|
||||
|
||||
|
@ -172,13 +172,14 @@ subsystem individually with a call to snd_soc_dapm_new_control().
|
|||
3. Codec Widget Interconnections
|
||||
================================
|
||||
|
||||
Widgets are connected to each other within the codec and machine by audio
|
||||
paths (called interconnections). Each interconnection must be defined in order
|
||||
to create a map of all audio paths between widgets.
|
||||
Widgets are connected to each other within the codec and machine by audio paths
|
||||
(called interconnections). Each interconnection must be defined in order to
|
||||
create a map of all audio paths between widgets.
|
||||
|
||||
This is easiest with a diagram of the codec (and schematic of the machine audio
|
||||
system), as it requires joining widgets together via their audio signal paths.
|
||||
|
||||
i.e. from the WM8731 codec's output mixer (wm8731.c)
|
||||
e.g., from the WM8731 output mixer (wm8731.c)
|
||||
|
||||
The WM8731 output mixer has 3 inputs (sources)
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ struct snd_soc_machine {
|
|||
int (*remove)(struct platform_device *pdev);
|
||||
|
||||
/* the pre and post PM functions are used to do any PM work before and
|
||||
* after the codec and DAI's do any PM work. */
|
||||
* after the codec and DAIs do any PM work. */
|
||||
int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
|
||||
int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
|
||||
int (*resume_pre)(struct platform_device *pdev);
|
||||
|
@ -38,7 +38,7 @@ probe/remove are optional. Do any machine specific probe here.
|
|||
suspend()/resume()
|
||||
------------------
|
||||
The machine driver has pre and post versions of suspend and resume to take care
|
||||
of any machine audio tasks that have to be done before or after the codec, DAI's
|
||||
of any machine audio tasks that have to be done before or after the codec, DAIs
|
||||
and DMA is suspended and resumed. Optional.
|
||||
|
||||
|
||||
|
@ -49,10 +49,10 @@ The machine specific audio operations can be set here. Again this is optional.
|
|||
|
||||
Machine DAI Configuration
|
||||
-------------------------
|
||||
The machine DAI configuration glues all the codec and CPU DAI's together. It can
|
||||
The machine DAI configuration glues all the codec and CPU DAIs together. It can
|
||||
also be used to set up the DAI system clock and for any machine related DAI
|
||||
initialisation e.g. the machine audio map can be connected to the codec audio
|
||||
map, unconnnected codec pins can be set as such. Please see corgi.c, spitz.c
|
||||
map, unconnected codec pins can be set as such. Please see corgi.c, spitz.c
|
||||
for examples.
|
||||
|
||||
struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
|
||||
|
@ -67,7 +67,7 @@ static struct snd_soc_dai_link corgi_dai = {
|
|||
.ops = &corgi_ops,
|
||||
};
|
||||
|
||||
struct snd_soc_machine then sets up the machine with it's DAI's. e.g.
|
||||
struct snd_soc_machine then sets up the machine with it's DAIs. e.g.
|
||||
|
||||
/* corgi audio machine driver */
|
||||
static struct snd_soc_machine snd_soc_machine_corgi = {
|
||||
|
@ -110,4 +110,4 @@ details.
|
|||
Machine Controls
|
||||
----------------
|
||||
|
||||
Machine specific audio mixer controls can be added in the dai init function.
|
||||
Machine specific audio mixer controls can be added in the DAI init function.
|
||||
|
|
|
@ -1,25 +1,26 @@
|
|||
ALSA SoC Layer
|
||||
==============
|
||||
|
||||
The overall project goal of the ALSA System on Chip (ASoC) layer is to provide
|
||||
better ALSA support for embedded system-on-chip processors (e.g. pxa2xx, au1x00,
|
||||
iMX, etc) and portable audio codecs. Currently there is some support in the
|
||||
kernel for SoC audio, however it has some limitations:-
|
||||
The overall project goal of the ALSA System on Chip (ASoC) layer is to
|
||||
provide better ALSA support for embedded system-on-chip processors (e.g.
|
||||
pxa2xx, au1x00, iMX, etc) and portable audio codecs. Prior to the ASoC
|
||||
subsystem there was some support in the kernel for SoC audio, however it
|
||||
had some limitations:-
|
||||
|
||||
* Currently, codec drivers are often tightly coupled to the underlying SoC
|
||||
CPU. This is not ideal and leads to code duplication i.e. Linux now has 4
|
||||
different wm8731 drivers for 4 different SoC platforms.
|
||||
* Codec drivers were often tightly coupled to the underlying SoC
|
||||
CPU. This is not ideal and leads to code duplication - for example,
|
||||
Linux had different wm8731 drivers for 4 different SoC platforms.
|
||||
|
||||
* There is no standard method to signal user initiated audio events (e.g.
|
||||
* There was no standard method to signal user initiated audio events (e.g.
|
||||
Headphone/Mic insertion, Headphone/Mic detection after an insertion
|
||||
event). These are quite common events on portable devices and often require
|
||||
machine specific code to re-route audio, enable amps, etc., after such an
|
||||
event.
|
||||
|
||||
* Current drivers tend to power up the entire codec when playing
|
||||
(or recording) audio. This is fine for a PC, but tends to waste a lot of
|
||||
power on portable devices. There is also no support for saving power via
|
||||
changing codec oversampling rates, bias currents, etc.
|
||||
* Drivers tended to power up the entire codec when playing (or
|
||||
recording) audio. This is fine for a PC, but tends to waste a lot of
|
||||
power on portable devices. There was also no support for saving
|
||||
power via changing codec oversampling rates, bias currents, etc.
|
||||
|
||||
|
||||
ASoC Design
|
||||
|
@ -31,12 +32,13 @@ features :-
|
|||
* Codec independence. Allows reuse of codec drivers on other platforms
|
||||
and machines.
|
||||
|
||||
* Easy I2S/PCM audio interface setup between codec and SoC. Each SoC interface
|
||||
and codec registers it's audio interface capabilities with the core and are
|
||||
subsequently matched and configured when the application hw params are known.
|
||||
* Easy I2S/PCM audio interface setup between codec and SoC. Each SoC
|
||||
interface and codec registers it's audio interface capabilities with the
|
||||
core and are subsequently matched and configured when the application
|
||||
hardware parameters are known.
|
||||
|
||||
* Dynamic Audio Power Management (DAPM). DAPM automatically sets the codec to
|
||||
it's minimum power state at all times. This includes powering up/down
|
||||
its minimum power state at all times. This includes powering up/down
|
||||
internal power blocks depending on the internal codec audio routing and any
|
||||
active streams.
|
||||
|
||||
|
@ -45,16 +47,16 @@ features :-
|
|||
signals the codec when to change power states.
|
||||
|
||||
* Machine specific controls: Allow machines to add controls to the sound card
|
||||
(e.g. volume control for speaker amp).
|
||||
(e.g. volume control for speaker amplifier).
|
||||
|
||||
To achieve all this, ASoC basically splits an embedded audio system into 3
|
||||
components :-
|
||||
|
||||
* Codec driver: The codec driver is platform independent and contains audio
|
||||
controls, audio interface capabilities, codec dapm definition and codec IO
|
||||
controls, audio interface capabilities, codec DAPM definition and codec IO
|
||||
functions.
|
||||
|
||||
* Platform driver: The platform driver contains the audio dma engine and audio
|
||||
* Platform driver: The platform driver contains the audio DMA engine and audio
|
||||
interface drivers (e.g. I2S, AC97, PCM) for that platform.
|
||||
|
||||
* Machine driver: The machine driver handles any machine specific controls and
|
||||
|
|
|
@ -8,7 +8,7 @@ specific code.
|
|||
Audio DMA
|
||||
=========
|
||||
|
||||
The platform DMA driver optionally supports the following alsa operations:-
|
||||
The platform DMA driver optionally supports the following ALSA operations:-
|
||||
|
||||
/* SoC audio ops */
|
||||
struct snd_soc_ops {
|
||||
|
@ -38,7 +38,7 @@ struct snd_soc_platform {
|
|||
struct snd_pcm_ops *pcm_ops;
|
||||
};
|
||||
|
||||
Please refer to the alsa driver documentation for details of audio DMA.
|
||||
Please refer to the ALSA driver documentation for details of audio DMA.
|
||||
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
|
||||
|
||||
An example DMA driver is soc/pxa/pxa2xx-pcm.c
|
||||
|
@ -52,7 +52,7 @@ Each SoC DAI driver must provide the following features:-
|
|||
1) Digital audio interface (DAI) description
|
||||
2) Digital audio interface configuration
|
||||
3) PCM's description
|
||||
4) Sysclk configuration
|
||||
4) SYSCLK configuration
|
||||
5) Suspend and resume (optional)
|
||||
|
||||
Please see codec.txt for a description of items 1 - 4.
|
||||
|
|
|
@ -15,11 +15,11 @@ click every time a component power state is changed.
|
|||
Minimising Playback Pops and Clicks
|
||||
===================================
|
||||
|
||||
Playback pops in portable audio subsystems cannot be completely eliminated atm,
|
||||
however future audio codec hardware will have better pop and click suppression.
|
||||
Pops can be reduced within playback by powering the audio components in a
|
||||
specific order. This order is different for startup and shutdown and follows
|
||||
some basic rules:-
|
||||
Playback pops in portable audio subsystems cannot be completely eliminated
|
||||
currently, however future audio codec hardware will have better pop and click
|
||||
suppression. Pops can be reduced within playback by powering the audio
|
||||
components in a specific order. This order is different for startup and
|
||||
shutdown and follows some basic rules:-
|
||||
|
||||
Startup Order :- DAC --> Mixers --> Output PGA --> Digital Unmute
|
||||
|
||||
|
|
|
@ -3571,6 +3571,9 @@ S: Maintained
|
|||
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT
|
||||
P: Liam Girdwood
|
||||
M: liam.girdwood@wolfsonmicro.com
|
||||
P: Mark Brown
|
||||
M: broonie@opensource.wolfsonmicro.com
|
||||
T: git opensource.wolfsonmicro.com/linux-2.6-asoc
|
||||
L: alsa-devel@alsa-project.org (subscribers-only)
|
||||
S: Supported
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <linux/kthread.h>
|
||||
#include <linux/freezer.h>
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/ac97_codec.h>
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <linux/pci.h>
|
||||
|
||||
#include <asm/delay.h>
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <linux/time.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/module.h>
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/pcm.h>
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include <media/ir-common.h>
|
||||
#include <media/ir-kbd-i2c.h>
|
||||
#include <media/videobuf-dma-sg.h>
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <linux/utsname.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/rawmidi.h>
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include <asm/arch/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
|
||||
/* master codec clock source */
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#ifndef __OMAP_ALSA_H
|
||||
#define __OMAP_ALSA_H
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <asm/arch/dma.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef __ASM_ARCH_AUDIO_H__
|
||||
#define __ASM_ARCH_AUDIO_H__
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
#define AD1848_IFACE_CTRL 0x09 /* interface control - bits 7-2 MCE */
|
||||
#define AD1848_PIN_CTRL 0x0a /* pin control */
|
||||
#define AD1848_TEST_INIT 0x0b /* test and initialization */
|
||||
#define AD1848_MISC_INFO 0x0c /* miscellaneaous information */
|
||||
#define AD1848_MISC_INFO 0x0c /* miscellaneous information */
|
||||
#define AD1848_LOOPBACK 0x0d /* loopback control */
|
||||
#define AD1848_DATA_UPR_CNT 0x0e /* playback/capture upper base count */
|
||||
#define AD1848_DATA_LWR_CNT 0x0f /* playback/capture lower base count */
|
||||
|
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* Advanced Linux Sound Architecture
|
||||
*
|
||||
* FM (OPL2/3) Instrument Format
|
||||
* Copyright (c) 2000 Uros Bizjak <uros@kss-loka.si>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SOUND_AINSTR_FM_H
|
||||
#define __SOUND_AINSTR_FM_H
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include <asm/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* share types (share ID 1)
|
||||
*/
|
||||
|
||||
#define FM_SHARE_FILE 0
|
||||
|
||||
/*
|
||||
* FM operator
|
||||
*/
|
||||
|
||||
struct fm_operator {
|
||||
unsigned char am_vib;
|
||||
unsigned char ksl_level;
|
||||
unsigned char attack_decay;
|
||||
unsigned char sustain_release;
|
||||
unsigned char wave_select;
|
||||
};
|
||||
|
||||
/*
|
||||
* Instrument
|
||||
*/
|
||||
|
||||
#define FM_PATCH_OPL2 0x01 /* OPL2 2 operators FM instrument */
|
||||
#define FM_PATCH_OPL3 0x02 /* OPL3 4 operators FM instrument */
|
||||
|
||||
struct fm_instrument {
|
||||
unsigned int share_id[4]; /* share id - zero = no sharing */
|
||||
unsigned char type; /* instrument type */
|
||||
|
||||
struct fm_operator op[4];
|
||||
unsigned char feedback_connection[2];
|
||||
|
||||
unsigned char echo_delay;
|
||||
unsigned char echo_atten;
|
||||
unsigned char chorus_spread;
|
||||
unsigned char trnsps;
|
||||
unsigned char fix_dur;
|
||||
unsigned char modes;
|
||||
unsigned char fix_key;
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
* Kernel <-> user space
|
||||
* Hardware (CPU) independent section
|
||||
*
|
||||
* * = zero or more
|
||||
* + = one or more
|
||||
*
|
||||
* fm_xinstrument FM_STRU_INSTR
|
||||
*
|
||||
*/
|
||||
|
||||
#define FM_STRU_INSTR __cpu_to_be32(('I'<<24)|('N'<<16)|('S'<<8)|'T')
|
||||
|
||||
/*
|
||||
* FM operator
|
||||
*/
|
||||
|
||||
struct fm_xoperator {
|
||||
__u8 am_vib;
|
||||
__u8 ksl_level;
|
||||
__u8 attack_decay;
|
||||
__u8 sustain_release;
|
||||
__u8 wave_select;
|
||||
};
|
||||
|
||||
/*
|
||||
* Instrument
|
||||
*/
|
||||
|
||||
struct fm_xinstrument {
|
||||
__u32 stype; /* structure type */
|
||||
|
||||
__u32 share_id[4]; /* share id - zero = no sharing */
|
||||
__u8 type; /* instrument type */
|
||||
|
||||
struct fm_xoperator op[4]; /* fm operators */
|
||||
__u8 feedback_connection[2];
|
||||
|
||||
__u8 echo_delay;
|
||||
__u8 echo_atten;
|
||||
__u8 chorus_spread;
|
||||
__u8 trnsps;
|
||||
__u8 fix_dur;
|
||||
__u8 modes;
|
||||
__u8 fix_key;
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include "seq_instr.h"
|
||||
|
||||
int snd_seq_fm_init(struct snd_seq_kinstr_ops * ops,
|
||||
struct snd_seq_kinstr_ops * next);
|
||||
|
||||
#endif
|
||||
|
||||
/* typedefs for compatibility to user-space */
|
||||
typedef struct fm_xoperator fm_xoperator_t;
|
||||
typedef struct fm_xinstrument fm_xinstrument_t;
|
||||
|
||||
#endif /* __SOUND_AINSTR_FM_H */
|
|
@ -1,229 +0,0 @@
|
|||
/*
|
||||
* Advanced Linux Sound Architecture
|
||||
*
|
||||
* GF1 (GUS) Patch Instrument Format
|
||||
* Copyright (c) 1994-99 by Jaroslav Kysela <perex@perex.cz>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SOUND_AINSTR_GF1_H
|
||||
#define __SOUND_AINSTR_GF1_H
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include <asm/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* share types (share ID 1)
|
||||
*/
|
||||
|
||||
#define GF1_SHARE_FILE 0
|
||||
|
||||
/*
|
||||
* wave formats
|
||||
*/
|
||||
|
||||
#define GF1_WAVE_16BIT 0x0001 /* 16-bit wave */
|
||||
#define GF1_WAVE_UNSIGNED 0x0002 /* unsigned wave */
|
||||
#define GF1_WAVE_INVERT 0x0002 /* same as unsigned wave */
|
||||
#define GF1_WAVE_BACKWARD 0x0004 /* backward mode (maybe used for reverb or ping-ping loop) */
|
||||
#define GF1_WAVE_LOOP 0x0008 /* loop mode */
|
||||
#define GF1_WAVE_BIDIR 0x0010 /* bidirectional mode */
|
||||
#define GF1_WAVE_STEREO 0x0100 /* stereo mode */
|
||||
#define GF1_WAVE_ULAW 0x0200 /* uLaw compression mode */
|
||||
|
||||
/*
|
||||
* Wavetable definitions
|
||||
*/
|
||||
|
||||
struct gf1_wave {
|
||||
unsigned int share_id[4]; /* share id - zero = no sharing */
|
||||
unsigned int format; /* wave format */
|
||||
|
||||
struct {
|
||||
unsigned int number; /* some other ID for this instrument */
|
||||
unsigned int memory; /* begin of waveform in onboard memory */
|
||||
unsigned char *ptr; /* pointer to waveform in system memory */
|
||||
} address;
|
||||
|
||||
unsigned int size; /* size of waveform in samples */
|
||||
unsigned int start; /* start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
unsigned int loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
unsigned int loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
unsigned short loop_repeat; /* loop repeat - 0 = forever */
|
||||
|
||||
unsigned char flags; /* GF1 patch flags */
|
||||
unsigned char pad;
|
||||
unsigned int sample_rate; /* sample rate in Hz */
|
||||
unsigned int low_frequency; /* low frequency range */
|
||||
unsigned int high_frequency; /* high frequency range */
|
||||
unsigned int root_frequency; /* root frequency range */
|
||||
signed short tune;
|
||||
unsigned char balance;
|
||||
unsigned char envelope_rate[6];
|
||||
unsigned char envelope_offset[6];
|
||||
unsigned char tremolo_sweep;
|
||||
unsigned char tremolo_rate;
|
||||
unsigned char tremolo_depth;
|
||||
unsigned char vibrato_sweep;
|
||||
unsigned char vibrato_rate;
|
||||
unsigned char vibrato_depth;
|
||||
unsigned short scale_frequency;
|
||||
unsigned short scale_factor; /* 0-2048 or 0-2 */
|
||||
|
||||
struct gf1_wave *next;
|
||||
};
|
||||
|
||||
/*
|
||||
* Instrument
|
||||
*/
|
||||
|
||||
#define IWFFFF_EXCLUDE_NONE 0x0000 /* exclusion mode - none */
|
||||
#define IWFFFF_EXCLUDE_SINGLE 0x0001 /* exclude single - single note from the instrument group */
|
||||
#define IWFFFF_EXCLUDE_MULTIPLE 0x0002 /* exclude multiple - stop only same note from this instrument */
|
||||
|
||||
#define IWFFFF_EFFECT_NONE 0
|
||||
#define IWFFFF_EFFECT_REVERB 1
|
||||
#define IWFFFF_EFFECT_CHORUS 2
|
||||
#define IWFFFF_EFFECT_ECHO 3
|
||||
|
||||
struct gf1_instrument {
|
||||
unsigned short exclusion;
|
||||
unsigned short exclusion_group; /* 0 - none, 1-65535 */
|
||||
|
||||
unsigned char effect1; /* effect 1 */
|
||||
unsigned char effect1_depth; /* 0-127 */
|
||||
unsigned char effect2; /* effect 2 */
|
||||
unsigned char effect2_depth; /* 0-127 */
|
||||
|
||||
struct gf1_wave *wave; /* first waveform */
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
* Kernel <-> user space
|
||||
* Hardware (CPU) independent section
|
||||
*
|
||||
* * = zero or more
|
||||
* + = one or more
|
||||
*
|
||||
* gf1_xinstrument IWFFFF_STRU_INSTR
|
||||
* +gf1_xwave IWFFFF_STRU_WAVE
|
||||
*
|
||||
*/
|
||||
|
||||
#define GF1_STRU_WAVE __cpu_to_be32(('W'<<24)|('A'<<16)|('V'<<8)|'E')
|
||||
#define GF1_STRU_INSTR __cpu_to_be32(('I'<<24)|('N'<<16)|('S'<<8)|'T')
|
||||
|
||||
/*
|
||||
* Wavetable definitions
|
||||
*/
|
||||
|
||||
struct gf1_xwave {
|
||||
__u32 stype; /* structure type */
|
||||
|
||||
__u32 share_id[4]; /* share id - zero = no sharing */
|
||||
__u32 format; /* wave format */
|
||||
|
||||
__u32 size; /* size of waveform in samples */
|
||||
__u32 start; /* start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
__u32 loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
__u32 loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
__u16 loop_repeat; /* loop repeat - 0 = forever */
|
||||
|
||||
__u8 flags; /* GF1 patch flags */
|
||||
__u8 pad;
|
||||
__u32 sample_rate; /* sample rate in Hz */
|
||||
__u32 low_frequency; /* low frequency range */
|
||||
__u32 high_frequency; /* high frequency range */
|
||||
__u32 root_frequency; /* root frequency range */
|
||||
__s16 tune;
|
||||
__u8 balance;
|
||||
__u8 envelope_rate[6];
|
||||
__u8 envelope_offset[6];
|
||||
__u8 tremolo_sweep;
|
||||
__u8 tremolo_rate;
|
||||
__u8 tremolo_depth;
|
||||
__u8 vibrato_sweep;
|
||||
__u8 vibrato_rate;
|
||||
__u8 vibrato_depth;
|
||||
__u16 scale_frequency;
|
||||
__u16 scale_factor; /* 0-2048 or 0-2 */
|
||||
};
|
||||
|
||||
/*
|
||||
* Instrument
|
||||
*/
|
||||
|
||||
struct gf1_xinstrument {
|
||||
__u32 stype;
|
||||
|
||||
__u16 exclusion;
|
||||
__u16 exclusion_group; /* 0 - none, 1-65535 */
|
||||
|
||||
__u8 effect1; /* effect 1 */
|
||||
__u8 effect1_depth; /* 0-127 */
|
||||
__u8 effect2; /* effect 2 */
|
||||
__u8 effect2_depth; /* 0-127 */
|
||||
};
|
||||
|
||||
/*
|
||||
* Instrument info
|
||||
*/
|
||||
|
||||
#define GF1_INFO_ENVELOPE (1<<0)
|
||||
#define GF1_INFO_TREMOLO (1<<1)
|
||||
#define GF1_INFO_VIBRATO (1<<2)
|
||||
|
||||
struct gf1_info {
|
||||
unsigned char flags; /* supported wave flags */
|
||||
unsigned char pad[3];
|
||||
unsigned int features; /* supported features */
|
||||
unsigned int max8_len; /* maximum 8-bit wave length */
|
||||
unsigned int max16_len; /* maximum 16-bit wave length */
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include "seq_instr.h"
|
||||
|
||||
struct snd_gf1_ops {
|
||||
void *private_data;
|
||||
int (*info)(void *private_data, struct gf1_info *info);
|
||||
int (*put_sample)(void *private_data, struct gf1_wave *wave,
|
||||
char __user *data, long len, int atomic);
|
||||
int (*get_sample)(void *private_data, struct gf1_wave *wave,
|
||||
char __user *data, long len, int atomic);
|
||||
int (*remove_sample)(void *private_data, struct gf1_wave *wave,
|
||||
int atomic);
|
||||
void (*notify)(void *private_data, struct snd_seq_kinstr *instr, int what);
|
||||
struct snd_seq_kinstr_ops kops;
|
||||
};
|
||||
|
||||
int snd_seq_gf1_init(struct snd_gf1_ops *ops,
|
||||
void *private_data,
|
||||
struct snd_seq_kinstr_ops *next);
|
||||
|
||||
#endif
|
||||
|
||||
/* typedefs for compatibility to user-space */
|
||||
typedef struct gf1_xwave gf1_xwave_t;
|
||||
typedef struct gf1_xinstrument gf1_xinstrument_t;
|
||||
|
||||
#endif /* __SOUND_AINSTR_GF1_H */
|
|
@ -1,384 +0,0 @@
|
|||
/*
|
||||
* Advanced Linux Sound Architecture
|
||||
*
|
||||
* InterWave FFFF Instrument Format
|
||||
* Copyright (c) 1994-99 by Jaroslav Kysela <perex@perex.cz>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SOUND_AINSTR_IW_H
|
||||
#define __SOUND_AINSTR_IW_H
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include <asm/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* share types (share ID 1)
|
||||
*/
|
||||
|
||||
#define IWFFFF_SHARE_FILE 0
|
||||
|
||||
/*
|
||||
* wave formats
|
||||
*/
|
||||
|
||||
#define IWFFFF_WAVE_16BIT 0x0001 /* 16-bit wave */
|
||||
#define IWFFFF_WAVE_UNSIGNED 0x0002 /* unsigned wave */
|
||||
#define IWFFFF_WAVE_INVERT 0x0002 /* same as unsigned wave */
|
||||
#define IWFFFF_WAVE_BACKWARD 0x0004 /* backward mode (maybe used for reverb or ping-ping loop) */
|
||||
#define IWFFFF_WAVE_LOOP 0x0008 /* loop mode */
|
||||
#define IWFFFF_WAVE_BIDIR 0x0010 /* bidirectional mode */
|
||||
#define IWFFFF_WAVE_ULAW 0x0020 /* uLaw compressed wave */
|
||||
#define IWFFFF_WAVE_RAM 0x0040 /* wave is _preloaded_ in RAM (it is used for ROM simulation) */
|
||||
#define IWFFFF_WAVE_ROM 0x0080 /* wave is in ROM */
|
||||
#define IWFFFF_WAVE_STEREO 0x0100 /* wave is stereo */
|
||||
|
||||
/*
|
||||
* Wavetable definitions
|
||||
*/
|
||||
|
||||
struct iwffff_wave {
|
||||
unsigned int share_id[4]; /* share id - zero = no sharing */
|
||||
unsigned int format; /* wave format */
|
||||
|
||||
struct {
|
||||
unsigned int number; /* some other ID for this wave */
|
||||
unsigned int memory; /* begin of waveform in onboard memory */
|
||||
unsigned char *ptr; /* pointer to waveform in system memory */
|
||||
} address;
|
||||
|
||||
unsigned int size; /* size of waveform in samples */
|
||||
unsigned int start; /* start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
unsigned int loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
unsigned int loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
unsigned short loop_repeat; /* loop repeat - 0 = forever */
|
||||
unsigned int sample_ratio; /* sample ratio (44100 * 1024 / rate) */
|
||||
unsigned char attenuation; /* 0 - 127 (no corresponding midi controller) */
|
||||
unsigned char low_note; /* lower frequency range for this waveform */
|
||||
unsigned char high_note; /* higher frequency range for this waveform */
|
||||
unsigned char pad;
|
||||
|
||||
struct iwffff_wave *next;
|
||||
};
|
||||
|
||||
/*
|
||||
* Layer
|
||||
*/
|
||||
|
||||
#define IWFFFF_LFO_SHAPE_TRIANGLE 0
|
||||
#define IWFFFF_LFO_SHAPE_POSTRIANGLE 1
|
||||
|
||||
struct iwffff_lfo {
|
||||
unsigned short freq; /* (0-2047) 0.01Hz - 21.5Hz */
|
||||
signed short depth; /* volume +- (0-255) 0.48675dB/step */
|
||||
signed short sweep; /* 0 - 950 deciseconds */
|
||||
unsigned char shape; /* see to IWFFFF_LFO_SHAPE_XXXX */
|
||||
unsigned char delay; /* 0 - 255 deciseconds */
|
||||
};
|
||||
|
||||
#define IWFFFF_ENV_FLAG_RETRIGGER 0x0001 /* flag - retrigger */
|
||||
|
||||
#define IWFFFF_ENV_MODE_ONE_SHOT 0x0001 /* mode - one shot */
|
||||
#define IWFFFF_ENV_MODE_SUSTAIN 0x0002 /* mode - sustain */
|
||||
#define IWFFFF_ENV_MODE_NO_SUSTAIN 0x0003 /* mode - no sustain */
|
||||
|
||||
#define IWFFFF_ENV_INDEX_VELOCITY 0x0001 /* index - velocity */
|
||||
#define IWFFFF_ENV_INDEX_FREQUENCY 0x0002 /* index - frequency */
|
||||
|
||||
struct iwffff_env_point {
|
||||
unsigned short offset;
|
||||
unsigned short rate;
|
||||
};
|
||||
|
||||
struct iwffff_env_record {
|
||||
unsigned short nattack;
|
||||
unsigned short nrelease;
|
||||
unsigned short sustain_offset;
|
||||
unsigned short sustain_rate;
|
||||
unsigned short release_rate;
|
||||
unsigned char hirange;
|
||||
unsigned char pad;
|
||||
struct iwffff_env_record *next;
|
||||
/* points are stored here */
|
||||
/* count of points = nattack + nrelease */
|
||||
};
|
||||
|
||||
struct iwffff_env {
|
||||
unsigned char flags;
|
||||
unsigned char mode;
|
||||
unsigned char index;
|
||||
unsigned char pad;
|
||||
struct iwffff_env_record *record;
|
||||
};
|
||||
|
||||
#define IWFFFF_LAYER_FLAG_RETRIGGER 0x0001 /* retrigger */
|
||||
|
||||
#define IWFFFF_LAYER_VELOCITY_TIME 0x0000 /* velocity mode = time */
|
||||
#define IWFFFF_LAYER_VELOCITY_RATE 0x0001 /* velocity mode = rate */
|
||||
|
||||
#define IWFFFF_LAYER_EVENT_KUP 0x0000 /* layer event - key up */
|
||||
#define IWFFFF_LAYER_EVENT_KDOWN 0x0001 /* layer event - key down */
|
||||
#define IWFFFF_LAYER_EVENT_RETRIG 0x0002 /* layer event - retrigger */
|
||||
#define IWFFFF_LAYER_EVENT_LEGATO 0x0003 /* layer event - legato */
|
||||
|
||||
struct iwffff_layer {
|
||||
unsigned char flags;
|
||||
unsigned char velocity_mode;
|
||||
unsigned char layer_event;
|
||||
unsigned char low_range; /* range for layer based */
|
||||
unsigned char high_range; /* on either velocity or frequency */
|
||||
unsigned char pan; /* pan offset from CC1 (0 left - 127 right) */
|
||||
unsigned char pan_freq_scale; /* position based on frequency (0-127) */
|
||||
unsigned char attenuation; /* 0-127 (no corresponding midi controller) */
|
||||
struct iwffff_lfo tremolo; /* tremolo effect */
|
||||
struct iwffff_lfo vibrato; /* vibrato effect */
|
||||
unsigned short freq_scale; /* 0-2048, 1024 is equal to semitone scaling */
|
||||
unsigned char freq_center; /* center for keyboard frequency scaling */
|
||||
unsigned char pad;
|
||||
struct iwffff_env penv; /* pitch envelope */
|
||||
struct iwffff_env venv; /* volume envelope */
|
||||
|
||||
struct iwffff_wave *wave;
|
||||
struct iwffff_layer *next;
|
||||
};
|
||||
|
||||
/*
|
||||
* Instrument
|
||||
*/
|
||||
|
||||
#define IWFFFF_EXCLUDE_NONE 0x0000 /* exclusion mode - none */
|
||||
#define IWFFFF_EXCLUDE_SINGLE 0x0001 /* exclude single - single note from the instrument group */
|
||||
#define IWFFFF_EXCLUDE_MULTIPLE 0x0002 /* exclude multiple - stop only same note from this instrument */
|
||||
|
||||
#define IWFFFF_LAYER_NONE 0x0000 /* not layered */
|
||||
#define IWFFFF_LAYER_ON 0x0001 /* layered */
|
||||
#define IWFFFF_LAYER_VELOCITY 0x0002 /* layered by velocity */
|
||||
#define IWFFFF_LAYER_FREQUENCY 0x0003 /* layered by frequency */
|
||||
|
||||
#define IWFFFF_EFFECT_NONE 0
|
||||
#define IWFFFF_EFFECT_REVERB 1
|
||||
#define IWFFFF_EFFECT_CHORUS 2
|
||||
#define IWFFFF_EFFECT_ECHO 3
|
||||
|
||||
struct iwffff_instrument {
|
||||
unsigned short exclusion;
|
||||
unsigned short layer_type;
|
||||
unsigned short exclusion_group; /* 0 - none, 1-65535 */
|
||||
|
||||
unsigned char effect1; /* effect 1 */
|
||||
unsigned char effect1_depth; /* 0-127 */
|
||||
unsigned char effect2; /* effect 2 */
|
||||
unsigned char effect2_depth; /* 0-127 */
|
||||
|
||||
struct iwffff_layer *layer; /* first layer */
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
* Kernel <-> user space
|
||||
* Hardware (CPU) independent section
|
||||
*
|
||||
* * = zero or more
|
||||
* + = one or more
|
||||
*
|
||||
* iwffff_xinstrument IWFFFF_STRU_INSTR
|
||||
* +iwffff_xlayer IWFFFF_STRU_LAYER
|
||||
* *iwffff_xenv_record IWFFFF_STRU_ENV_RECT (tremolo)
|
||||
* *iwffff_xenv_record IWFFFF_STRU_EVN_RECT (vibrato)
|
||||
* +iwffff_xwave IWFFFF_STRU_WAVE
|
||||
*
|
||||
*/
|
||||
|
||||
#define IWFFFF_STRU_WAVE __cpu_to_be32(('W'<<24)|('A'<<16)|('V'<<8)|'E')
|
||||
#define IWFFFF_STRU_ENV_RECP __cpu_to_be32(('E'<<24)|('N'<<16)|('R'<<8)|'P')
|
||||
#define IWFFFF_STRU_ENV_RECV __cpu_to_be32(('E'<<24)|('N'<<16)|('R'<<8)|'V')
|
||||
#define IWFFFF_STRU_LAYER __cpu_to_be32(('L'<<24)|('A'<<16)|('Y'<<8)|'R')
|
||||
#define IWFFFF_STRU_INSTR __cpu_to_be32(('I'<<24)|('N'<<16)|('S'<<8)|'T')
|
||||
|
||||
/*
|
||||
* Wavetable definitions
|
||||
*/
|
||||
|
||||
struct iwffff_xwave {
|
||||
__u32 stype; /* structure type */
|
||||
|
||||
__u32 share_id[4]; /* share id - zero = no sharing */
|
||||
|
||||
__u32 format; /* wave format */
|
||||
__u32 offset; /* offset to ROM (address) */
|
||||
|
||||
__u32 size; /* size of waveform in samples */
|
||||
__u32 start; /* start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
__u32 loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
__u32 loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
__u16 loop_repeat; /* loop repeat - 0 = forever */
|
||||
__u32 sample_ratio; /* sample ratio (44100 * 1024 / rate) */
|
||||
__u8 attenuation; /* 0 - 127 (no corresponding midi controller) */
|
||||
__u8 low_note; /* lower frequency range for this waveform */
|
||||
__u8 high_note; /* higher frequency range for this waveform */
|
||||
__u8 pad;
|
||||
};
|
||||
|
||||
/*
|
||||
* Layer
|
||||
*/
|
||||
|
||||
struct iwffff_xlfo {
|
||||
__u16 freq; /* (0-2047) 0.01Hz - 21.5Hz */
|
||||
__s16 depth; /* volume +- (0-255) 0.48675dB/step */
|
||||
__s16 sweep; /* 0 - 950 deciseconds */
|
||||
__u8 shape; /* see to ULTRA_IW_LFO_SHAPE_XXXX */
|
||||
__u8 delay; /* 0 - 255 deciseconds */
|
||||
};
|
||||
|
||||
struct iwffff_xenv_point {
|
||||
__u16 offset;
|
||||
__u16 rate;
|
||||
};
|
||||
|
||||
struct iwffff_xenv_record {
|
||||
__u32 stype;
|
||||
__u16 nattack;
|
||||
__u16 nrelease;
|
||||
__u16 sustain_offset;
|
||||
__u16 sustain_rate;
|
||||
__u16 release_rate;
|
||||
__u8 hirange;
|
||||
__u8 pad;
|
||||
/* points are stored here.. */
|
||||
/* count of points = nattack + nrelease */
|
||||
};
|
||||
|
||||
struct iwffff_xenv {
|
||||
__u8 flags;
|
||||
__u8 mode;
|
||||
__u8 index;
|
||||
__u8 pad;
|
||||
};
|
||||
|
||||
struct iwffff_xlayer {
|
||||
__u32 stype;
|
||||
__u8 flags;
|
||||
__u8 velocity_mode;
|
||||
__u8 layer_event;
|
||||
__u8 low_range; /* range for layer based */
|
||||
__u8 high_range; /* on either velocity or frequency */
|
||||
__u8 pan; /* pan offset from CC1 (0 left - 127 right) */
|
||||
__u8 pan_freq_scale; /* position based on frequency (0-127) */
|
||||
__u8 attenuation; /* 0-127 (no corresponding midi controller) */
|
||||
struct iwffff_xlfo tremolo; /* tremolo effect */
|
||||
struct iwffff_xlfo vibrato; /* vibrato effect */
|
||||
__u16 freq_scale; /* 0-2048, 1024 is equal to semitone scaling */
|
||||
__u8 freq_center; /* center for keyboard frequency scaling */
|
||||
__u8 pad;
|
||||
struct iwffff_xenv penv; /* pitch envelope */
|
||||
struct iwffff_xenv venv; /* volume envelope */
|
||||
};
|
||||
|
||||
/*
|
||||
* Instrument
|
||||
*/
|
||||
|
||||
struct iwffff_xinstrument {
|
||||
__u32 stype;
|
||||
|
||||
__u16 exclusion;
|
||||
__u16 layer_type;
|
||||
__u16 exclusion_group; /* 0 - none, 1-65535 */
|
||||
|
||||
__u8 effect1; /* effect 1 */
|
||||
__u8 effect1_depth; /* 0-127 */
|
||||
__u8 effect2; /* effect 2 */
|
||||
__u8 effect2_depth; /* 0-127 */
|
||||
};
|
||||
|
||||
/*
|
||||
* ROM support
|
||||
* InterWave ROMs are Little-Endian (x86)
|
||||
*/
|
||||
|
||||
#define IWFFFF_ROM_HDR_SIZE 512
|
||||
|
||||
struct iwffff_rom_header {
|
||||
__u8 iwave[8];
|
||||
__u8 revision;
|
||||
__u8 series_number;
|
||||
__u8 series_name[16];
|
||||
__u8 date[10];
|
||||
__u16 vendor_revision_major;
|
||||
__u16 vendor_revision_minor;
|
||||
__u32 rom_size;
|
||||
__u8 copyright[128];
|
||||
__u8 vendor_name[64];
|
||||
__u8 description[128];
|
||||
};
|
||||
|
||||
/*
|
||||
* Instrument info
|
||||
*/
|
||||
|
||||
#define IWFFFF_INFO_LFO_VIBRATO (1<<0)
|
||||
#define IWFFFF_INFO_LFO_VIBRATO_SHAPE (1<<1)
|
||||
#define IWFFFF_INFO_LFO_TREMOLO (1<<2)
|
||||
#define IWFFFF_INFO_LFO_TREMOLO_SHAPE (1<<3)
|
||||
|
||||
struct iwffff_info {
|
||||
unsigned int format; /* supported format bits */
|
||||
unsigned int effects; /* supported effects (1 << IWFFFF_EFFECT*) */
|
||||
unsigned int lfos; /* LFO effects */
|
||||
unsigned int max8_len; /* maximum 8-bit wave length */
|
||||
unsigned int max16_len; /* maximum 16-bit wave length */
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include "seq_instr.h"
|
||||
|
||||
struct snd_iwffff_ops {
|
||||
void *private_data;
|
||||
int (*info)(void *private_data, struct iwffff_info *info);
|
||||
int (*put_sample)(void *private_data, struct iwffff_wave *wave,
|
||||
char __user *data, long len, int atomic);
|
||||
int (*get_sample)(void *private_data, struct iwffff_wave *wave,
|
||||
char __user *data, long len, int atomic);
|
||||
int (*remove_sample)(void *private_data, struct iwffff_wave *wave,
|
||||
int atomic);
|
||||
void (*notify)(void *private_data, struct snd_seq_kinstr *instr, int what);
|
||||
struct snd_seq_kinstr_ops kops;
|
||||
};
|
||||
|
||||
int snd_seq_iwffff_init(struct snd_iwffff_ops *ops,
|
||||
void *private_data,
|
||||
struct snd_seq_kinstr_ops *next);
|
||||
|
||||
#endif
|
||||
|
||||
/* typedefs for compatibility to user-space */
|
||||
typedef struct iwffff_xwave iwffff_xwave_t;
|
||||
typedef struct iwffff_xlfo iwffff_xlfo_t;
|
||||
typedef struct iwffff_xenv_point iwffff_xenv_point_t;
|
||||
typedef struct iwffff_xenv_record iwffff_xenv_record_t;
|
||||
typedef struct iwffff_xenv iwffff_xenv_t;
|
||||
typedef struct iwffff_xlayer iwffff_xlayer_t;
|
||||
typedef struct iwffff_xinstrument iwffff_xinstrument_t;
|
||||
typedef struct iwffff_rom_header iwffff_rom_header_t;
|
||||
typedef struct iwffff_info iwffff_info_t;
|
||||
|
||||
#endif /* __SOUND_AINSTR_IW_H */
|
|
@ -1,159 +0,0 @@
|
|||
/*
|
||||
* Advanced Linux Sound Architecture
|
||||
*
|
||||
* Simple (MOD player) Instrument Format
|
||||
* Copyright (c) 1994-99 by Jaroslav Kysela <perex@perex.cz>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SOUND_AINSTR_SIMPLE_H
|
||||
#define __SOUND_AINSTR_SIMPLE_H
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include <asm/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* share types (share ID 1)
|
||||
*/
|
||||
|
||||
#define SIMPLE_SHARE_FILE 0
|
||||
|
||||
/*
|
||||
* wave formats
|
||||
*/
|
||||
|
||||
#define SIMPLE_WAVE_16BIT 0x0001 /* 16-bit wave */
|
||||
#define SIMPLE_WAVE_UNSIGNED 0x0002 /* unsigned wave */
|
||||
#define SIMPLE_WAVE_INVERT 0x0002 /* same as unsigned wave */
|
||||
#define SIMPLE_WAVE_BACKWARD 0x0004 /* backward mode (maybe used for reverb or ping-ping loop) */
|
||||
#define SIMPLE_WAVE_LOOP 0x0008 /* loop mode */
|
||||
#define SIMPLE_WAVE_BIDIR 0x0010 /* bidirectional mode */
|
||||
#define SIMPLE_WAVE_STEREO 0x0100 /* stereo wave */
|
||||
#define SIMPLE_WAVE_ULAW 0x0200 /* uLaw compression mode */
|
||||
|
||||
/*
|
||||
* instrument effects
|
||||
*/
|
||||
|
||||
#define SIMPLE_EFFECT_NONE 0
|
||||
#define SIMPLE_EFFECT_REVERB 1
|
||||
#define SIMPLE_EFFECT_CHORUS 2
|
||||
#define SIMPLE_EFFECT_ECHO 3
|
||||
|
||||
/*
|
||||
* instrument info
|
||||
*/
|
||||
|
||||
struct simple_instrument_info {
|
||||
unsigned int format; /* supported format bits */
|
||||
unsigned int effects; /* supported effects (1 << SIMPLE_EFFECT_*) */
|
||||
unsigned int max8_len; /* maximum 8-bit wave length */
|
||||
unsigned int max16_len; /* maximum 16-bit wave length */
|
||||
};
|
||||
|
||||
/*
|
||||
* Instrument
|
||||
*/
|
||||
|
||||
struct simple_instrument {
|
||||
unsigned int share_id[4]; /* share id - zero = no sharing */
|
||||
unsigned int format; /* wave format */
|
||||
|
||||
struct {
|
||||
unsigned int number; /* some other ID for this instrument */
|
||||
unsigned int memory; /* begin of waveform in onboard memory */
|
||||
unsigned char *ptr; /* pointer to waveform in system memory */
|
||||
} address;
|
||||
|
||||
unsigned int size; /* size of waveform in samples */
|
||||
unsigned int start; /* start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
unsigned int loop_start; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
unsigned int loop_end; /* loop end offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
unsigned short loop_repeat; /* loop repeat - 0 = forever */
|
||||
|
||||
unsigned char effect1; /* effect 1 */
|
||||
unsigned char effect1_depth; /* 0-127 */
|
||||
unsigned char effect2; /* effect 2 */
|
||||
unsigned char effect2_depth; /* 0-127 */
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
* Kernel <-> user space
|
||||
* Hardware (CPU) independent section
|
||||
*
|
||||
* * = zero or more
|
||||
* + = one or more
|
||||
*
|
||||
* simple_xinstrument SIMPLE_STRU_INSTR
|
||||
*
|
||||
*/
|
||||
|
||||
#define SIMPLE_STRU_INSTR __cpu_to_be32(('I'<<24)|('N'<<16)|('S'<<8)|'T')
|
||||
|
||||
/*
|
||||
* Instrument
|
||||
*/
|
||||
|
||||
struct simple_xinstrument {
|
||||
__u32 stype;
|
||||
|
||||
__u32 share_id[4]; /* share id - zero = no sharing */
|
||||
__u32 format; /* wave format */
|
||||
|
||||
__u32 size; /* size of waveform in samples */
|
||||
__u32 start; /* start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
__u32 loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
__u32 loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */
|
||||
__u16 loop_repeat; /* loop repeat - 0 = forever */
|
||||
|
||||
__u8 effect1; /* effect 1 */
|
||||
__u8 effect1_depth; /* 0-127 */
|
||||
__u8 effect2; /* effect 2 */
|
||||
__u8 effect2_depth; /* 0-127 */
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include "seq_instr.h"
|
||||
|
||||
struct snd_simple_ops {
|
||||
void *private_data;
|
||||
int (*info)(void *private_data, struct simple_instrument_info *info);
|
||||
int (*put_sample)(void *private_data, struct simple_instrument *instr,
|
||||
char __user *data, long len, int atomic);
|
||||
int (*get_sample)(void *private_data, struct simple_instrument *instr,
|
||||
char __user *data, long len, int atomic);
|
||||
int (*remove_sample)(void *private_data, struct simple_instrument *instr,
|
||||
int atomic);
|
||||
void (*notify)(void *private_data, struct snd_seq_kinstr *instr, int what);
|
||||
struct snd_seq_kinstr_ops kops;
|
||||
};
|
||||
|
||||
int snd_seq_simple_init(struct snd_simple_ops *ops,
|
||||
void *private_data,
|
||||
struct snd_seq_kinstr_ops *next);
|
||||
|
||||
#endif
|
||||
|
||||
/* typedefs for compatibility to user-space */
|
||||
typedef struct simple_xinstrument simple_xinstrument_t;
|
||||
|
||||
#endif /* __SOUND_AINSTR_SIMPLE_H */
|
|
@ -68,7 +68,7 @@ struct snd_akm4xxx {
|
|||
enum {
|
||||
SND_AK4524, SND_AK4528, SND_AK4529,
|
||||
SND_AK4355, SND_AK4358, SND_AK4381,
|
||||
SND_AK5365
|
||||
SND_AK5365, NON_AKM
|
||||
} type;
|
||||
|
||||
/* (array) information of combined codecs */
|
||||
|
|
|
@ -110,18 +110,7 @@
|
|||
#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED 66 /* ports connected */
|
||||
#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67 /* ports disconnected */
|
||||
|
||||
/** synthesizer events
|
||||
* event data type = snd_seq_eve_sample_control
|
||||
*/
|
||||
#define SNDRV_SEQ_EVENT_SAMPLE 70 /* sample select */
|
||||
#define SNDRV_SEQ_EVENT_SAMPLE_CLUSTER 71 /* sample cluster select */
|
||||
#define SNDRV_SEQ_EVENT_SAMPLE_START 72 /* voice start */
|
||||
#define SNDRV_SEQ_EVENT_SAMPLE_STOP 73 /* voice stop */
|
||||
#define SNDRV_SEQ_EVENT_SAMPLE_FREQ 74 /* playback frequency */
|
||||
#define SNDRV_SEQ_EVENT_SAMPLE_VOLUME 75 /* volume and balance */
|
||||
#define SNDRV_SEQ_EVENT_SAMPLE_LOOP 76 /* sample loop */
|
||||
#define SNDRV_SEQ_EVENT_SAMPLE_POSITION 77 /* sample position */
|
||||
#define SNDRV_SEQ_EVENT_SAMPLE_PRIVATE1 78 /* private (hardware dependent) event */
|
||||
/* 70-89: synthesizer events - obsoleted */
|
||||
|
||||
/** user-defined events with fixed length
|
||||
* event data type = any
|
||||
|
@ -137,28 +126,7 @@
|
|||
#define SNDRV_SEQ_EVENT_USR8 98
|
||||
#define SNDRV_SEQ_EVENT_USR9 99
|
||||
|
||||
/** instrument layer
|
||||
* variable length data can be passed directly to the driver
|
||||
*/
|
||||
#define SNDRV_SEQ_EVENT_INSTR_BEGIN 100 /* begin of instrument management */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_END 101 /* end of instrument management */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_INFO 102 /* instrument interface info */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_INFO_RESULT 103 /* result */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_FINFO 104 /* get format info */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_FINFO_RESULT 105 /* get format info */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_RESET 106 /* reset instrument memory */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_STATUS 107 /* instrument interface status */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_STATUS_RESULT 108 /* result */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_PUT 109 /* put instrument to port */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_GET 110 /* get instrument from port */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_GET_RESULT 111 /* result */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_FREE 112 /* free instrument(s) */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_LIST 113 /* instrument list */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_LIST_RESULT 114 /* result */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_CLUSTER 115 /* cluster parameters */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_CLUSTER_GET 116 /* get cluster parameters */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_CLUSTER_RESULT 117 /* result */
|
||||
#define SNDRV_SEQ_EVENT_INSTR_CHANGE 118 /* instrument change */
|
||||
/* 100-118: instrument layer - obsoleted */
|
||||
/* 119-129: reserved */
|
||||
|
||||
/* 130-139: variable length events
|
||||
|
@ -258,78 +226,6 @@ struct snd_seq_ev_ext {
|
|||
void *ptr; /* pointer to data (note: maybe 64-bit) */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Instrument cluster type */
|
||||
typedef unsigned int snd_seq_instr_cluster_t;
|
||||
|
||||
/* Instrument type */
|
||||
struct snd_seq_instr {
|
||||
snd_seq_instr_cluster_t cluster;
|
||||
unsigned int std; /* the upper byte means a private instrument (owner - client #) */
|
||||
unsigned short bank;
|
||||
unsigned short prg;
|
||||
};
|
||||
|
||||
/* sample number */
|
||||
struct snd_seq_ev_sample {
|
||||
unsigned int std;
|
||||
unsigned short bank;
|
||||
unsigned short prg;
|
||||
};
|
||||
|
||||
/* sample cluster */
|
||||
struct snd_seq_ev_cluster {
|
||||
snd_seq_instr_cluster_t cluster;
|
||||
};
|
||||
|
||||
/* sample position */
|
||||
typedef unsigned int snd_seq_position_t; /* playback position (in samples) * 16 */
|
||||
|
||||
/* sample stop mode */
|
||||
enum {
|
||||
SAMPLE_STOP_IMMEDIATELY = 0, /* terminate playing immediately */
|
||||
SAMPLE_STOP_VENVELOPE = 1, /* finish volume envelope */
|
||||
SAMPLE_STOP_LOOP = 2 /* terminate loop and finish wave */
|
||||
};
|
||||
|
||||
/* sample frequency */
|
||||
typedef int snd_seq_frequency_t; /* playback frequency in HZ * 16 */
|
||||
|
||||
/* sample volume control; if any value is set to -1 == do not change */
|
||||
struct snd_seq_ev_volume {
|
||||
signed short volume; /* range: 0-16383 */
|
||||
signed short lr; /* left-right balance; range: 0-16383 */
|
||||
signed short fr; /* front-rear balance; range: 0-16383 */
|
||||
signed short du; /* down-up balance; range: 0-16383 */
|
||||
};
|
||||
|
||||
/* simple loop redefinition */
|
||||
struct snd_seq_ev_loop {
|
||||
unsigned int start; /* loop start (in samples) * 16 */
|
||||
unsigned int end; /* loop end (in samples) * 16 */
|
||||
};
|
||||
|
||||
struct snd_seq_ev_sample_control {
|
||||
unsigned char channel;
|
||||
unsigned char unused1, unused2, unused3; /* pad */
|
||||
union {
|
||||
struct snd_seq_ev_sample sample;
|
||||
struct snd_seq_ev_cluster cluster;
|
||||
snd_seq_position_t position;
|
||||
int stop_mode;
|
||||
snd_seq_frequency_t frequency;
|
||||
struct snd_seq_ev_volume volume;
|
||||
struct snd_seq_ev_loop loop;
|
||||
unsigned char raw8[8];
|
||||
} param;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* INSTR_BEGIN event */
|
||||
struct snd_seq_ev_instr_begin {
|
||||
int timeout; /* zero = forever, otherwise timeout in ms */
|
||||
};
|
||||
|
||||
struct snd_seq_result {
|
||||
int event; /* processed event type */
|
||||
int result;
|
||||
|
@ -399,8 +295,6 @@ struct snd_seq_event {
|
|||
struct snd_seq_addr addr;
|
||||
struct snd_seq_connect connect;
|
||||
struct snd_seq_result result;
|
||||
struct snd_seq_ev_instr_begin instr_begin;
|
||||
struct snd_seq_ev_sample_control sample;
|
||||
struct snd_seq_ev_quote quote;
|
||||
} data;
|
||||
};
|
||||
|
@ -441,8 +335,6 @@ struct snd_seq_event_bounce {
|
|||
#define snd_seq_ev_is_user_type(ev) ((ev)->type >= 90 && (ev)->type < 99)
|
||||
/* fixed length events: 0-99 */
|
||||
#define snd_seq_ev_is_fixed_type(ev) ((ev)->type < 100)
|
||||
/* instrument layer events: 100-129 */
|
||||
#define snd_seq_ev_is_instr_type(ev) ((ev)->type >= 100 && (ev)->type < 130)
|
||||
/* variable length events: 130-139 */
|
||||
#define snd_seq_ev_is_variable_type(ev) ((ev)->type >= 130 && (ev)->type < 140)
|
||||
/* reserved for kernel */
|
||||
|
@ -737,136 +629,6 @@ struct snd_seq_query_subs {
|
|||
};
|
||||
|
||||
|
||||
/*
|
||||
* Instrument abstraction layer
|
||||
* - based on events
|
||||
*/
|
||||
|
||||
/* instrument types */
|
||||
#define SNDRV_SEQ_INSTR_ATYPE_DATA 0 /* instrument data */
|
||||
#define SNDRV_SEQ_INSTR_ATYPE_ALIAS 1 /* instrument alias */
|
||||
|
||||
/* instrument ASCII identifiers */
|
||||
#define SNDRV_SEQ_INSTR_ID_DLS1 "DLS1"
|
||||
#define SNDRV_SEQ_INSTR_ID_DLS2 "DLS2"
|
||||
#define SNDRV_SEQ_INSTR_ID_SIMPLE "Simple Wave"
|
||||
#define SNDRV_SEQ_INSTR_ID_SOUNDFONT "SoundFont"
|
||||
#define SNDRV_SEQ_INSTR_ID_GUS_PATCH "GUS Patch"
|
||||
#define SNDRV_SEQ_INSTR_ID_INTERWAVE "InterWave FFFF"
|
||||
#define SNDRV_SEQ_INSTR_ID_OPL2_3 "OPL2/3 FM"
|
||||
#define SNDRV_SEQ_INSTR_ID_OPL4 "OPL4"
|
||||
|
||||
/* instrument types */
|
||||
#define SNDRV_SEQ_INSTR_TYPE0_DLS1 (1<<0) /* MIDI DLS v1 */
|
||||
#define SNDRV_SEQ_INSTR_TYPE0_DLS2 (1<<1) /* MIDI DLS v2 */
|
||||
#define SNDRV_SEQ_INSTR_TYPE1_SIMPLE (1<<0) /* Simple Wave */
|
||||
#define SNDRV_SEQ_INSTR_TYPE1_SOUNDFONT (1<<1) /* EMU SoundFont */
|
||||
#define SNDRV_SEQ_INSTR_TYPE1_GUS_PATCH (1<<2) /* Gravis UltraSound Patch */
|
||||
#define SNDRV_SEQ_INSTR_TYPE1_INTERWAVE (1<<3) /* InterWave FFFF */
|
||||
#define SNDRV_SEQ_INSTR_TYPE2_OPL2_3 (1<<0) /* Yamaha OPL2/3 FM */
|
||||
#define SNDRV_SEQ_INSTR_TYPE2_OPL4 (1<<1) /* Yamaha OPL4 */
|
||||
|
||||
/* put commands */
|
||||
#define SNDRV_SEQ_INSTR_PUT_CMD_CREATE 0
|
||||
#define SNDRV_SEQ_INSTR_PUT_CMD_REPLACE 1
|
||||
#define SNDRV_SEQ_INSTR_PUT_CMD_MODIFY 2
|
||||
#define SNDRV_SEQ_INSTR_PUT_CMD_ADD 3
|
||||
#define SNDRV_SEQ_INSTR_PUT_CMD_REMOVE 4
|
||||
|
||||
/* get commands */
|
||||
#define SNDRV_SEQ_INSTR_GET_CMD_FULL 0
|
||||
#define SNDRV_SEQ_INSTR_GET_CMD_PARTIAL 1
|
||||
|
||||
/* query flags */
|
||||
#define SNDRV_SEQ_INSTR_QUERY_FOLLOW_ALIAS (1<<0)
|
||||
|
||||
/* free commands */
|
||||
#define SNDRV_SEQ_INSTR_FREE_CMD_ALL 0
|
||||
#define SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE 1
|
||||
#define SNDRV_SEQ_INSTR_FREE_CMD_CLUSTER 2
|
||||
#define SNDRV_SEQ_INSTR_FREE_CMD_SINGLE 3
|
||||
|
||||
/* size of ROM/RAM */
|
||||
typedef unsigned int snd_seq_instr_size_t;
|
||||
|
||||
/* INSTR_INFO */
|
||||
|
||||
struct snd_seq_instr_info {
|
||||
int result; /* operation result */
|
||||
unsigned int formats[8]; /* bitmap of supported formats */
|
||||
int ram_count; /* count of RAM banks */
|
||||
snd_seq_instr_size_t ram_sizes[16]; /* size of RAM banks */
|
||||
int rom_count; /* count of ROM banks */
|
||||
snd_seq_instr_size_t rom_sizes[8]; /* size of ROM banks */
|
||||
char reserved[128];
|
||||
};
|
||||
|
||||
/* INSTR_STATUS */
|
||||
|
||||
struct snd_seq_instr_status {
|
||||
int result; /* operation result */
|
||||
snd_seq_instr_size_t free_ram[16]; /* free RAM in banks */
|
||||
int instrument_count; /* count of downloaded instruments */
|
||||
char reserved[128];
|
||||
};
|
||||
|
||||
/* INSTR_FORMAT_INFO */
|
||||
|
||||
struct snd_seq_instr_format_info {
|
||||
char format[16]; /* format identifier - SNDRV_SEQ_INSTR_ID_* */
|
||||
unsigned int len; /* max data length (without this structure) */
|
||||
};
|
||||
|
||||
struct snd_seq_instr_format_info_result {
|
||||
int result; /* operation result */
|
||||
char format[16]; /* format identifier */
|
||||
unsigned int len; /* filled data length (without this structure) */
|
||||
};
|
||||
|
||||
/* instrument data */
|
||||
struct snd_seq_instr_data {
|
||||
char name[32]; /* instrument name */
|
||||
char reserved[16]; /* for the future use */
|
||||
int type; /* instrument type */
|
||||
union {
|
||||
char format[16]; /* format identifier */
|
||||
struct snd_seq_instr alias;
|
||||
} data;
|
||||
};
|
||||
|
||||
/* INSTR_PUT/GET, data are stored in one block (extended), header + data */
|
||||
|
||||
struct snd_seq_instr_header {
|
||||
union {
|
||||
struct snd_seq_instr instr;
|
||||
snd_seq_instr_cluster_t cluster;
|
||||
} id; /* instrument identifier */
|
||||
unsigned int cmd; /* get/put/free command */
|
||||
unsigned int flags; /* query flags (only for get) */
|
||||
unsigned int len; /* real instrument data length (without header) */
|
||||
int result; /* operation result */
|
||||
char reserved[16]; /* for the future */
|
||||
struct snd_seq_instr_data data; /* instrument data (for put/get result) */
|
||||
};
|
||||
|
||||
/* INSTR_CLUSTER_SET */
|
||||
|
||||
struct snd_seq_instr_cluster_set {
|
||||
snd_seq_instr_cluster_t cluster; /* cluster identifier */
|
||||
char name[32]; /* cluster name */
|
||||
int priority; /* cluster priority */
|
||||
char reserved[64]; /* for the future use */
|
||||
};
|
||||
|
||||
/* INSTR_CLUSTER_GET */
|
||||
|
||||
struct snd_seq_instr_cluster_get {
|
||||
snd_seq_instr_cluster_t cluster; /* cluster identifier */
|
||||
char name[32]; /* cluster name */
|
||||
int priority; /* cluster priority */
|
||||
char reserved[64]; /* for the future use */
|
||||
};
|
||||
|
||||
/*
|
||||
* IOCTL commands
|
||||
*/
|
||||
|
|
|
@ -95,7 +95,7 @@ enum {
|
|||
SNDRV_HWDEP_IFACE_HDA, /* HD-audio */
|
||||
|
||||
/* Don't forget to change the following: */
|
||||
SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_SB_RC
|
||||
SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_HDA
|
||||
};
|
||||
|
||||
struct snd_hwdep_info {
|
||||
|
@ -138,7 +138,7 @@ enum {
|
|||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 8)
|
||||
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 9)
|
||||
|
||||
typedef unsigned long snd_pcm_uframes_t;
|
||||
typedef signed long snd_pcm_sframes_t;
|
||||
|
@ -354,8 +354,8 @@ struct snd_pcm_hw_params {
|
|||
|
||||
enum {
|
||||
SNDRV_PCM_TSTAMP_NONE = 0,
|
||||
SNDRV_PCM_TSTAMP_MMAP,
|
||||
SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_MMAP,
|
||||
SNDRV_PCM_TSTAMP_ENABLE,
|
||||
SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
|
||||
};
|
||||
|
||||
struct snd_pcm_sw_params {
|
||||
|
@ -363,7 +363,7 @@ struct snd_pcm_sw_params {
|
|||
unsigned int period_step;
|
||||
unsigned int sleep_min; /* min ticks to sleep */
|
||||
snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */
|
||||
snd_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */
|
||||
snd_pcm_uframes_t xfer_align; /* obsolete: xfer size need to be a multiple */
|
||||
snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */
|
||||
snd_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */
|
||||
snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */
|
||||
|
@ -434,10 +434,17 @@ struct snd_xfern {
|
|||
snd_pcm_uframes_t frames;
|
||||
};
|
||||
|
||||
enum {
|
||||
SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0, /* gettimeofday equivalent */
|
||||
SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, /* posix_clock_monotonic equivalent */
|
||||
SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
|
||||
};
|
||||
|
||||
enum {
|
||||
SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int),
|
||||
SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct snd_pcm_info),
|
||||
SNDRV_PCM_IOCTL_TSTAMP = _IOW('A', 0x02, int),
|
||||
SNDRV_PCM_IOCTL_TTSTAMP = _IOW('A', 0x03, int),
|
||||
SNDRV_PCM_IOCTL_HW_REFINE = _IOWR('A', 0x10, struct snd_pcm_hw_params),
|
||||
SNDRV_PCM_IOCTL_HW_PARAMS = _IOWR('A', 0x11, struct snd_pcm_hw_params),
|
||||
SNDRV_PCM_IOCTL_HW_FREE = _IO('A', 0x12),
|
||||
|
@ -689,7 +696,7 @@ struct snd_timer_tread {
|
|||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 4)
|
||||
#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 5)
|
||||
|
||||
struct snd_ctl_card_info {
|
||||
int card; /* card number */
|
||||
|
@ -738,8 +745,7 @@ typedef int __bitwise snd_ctl_elem_iface_t;
|
|||
#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */
|
||||
#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */
|
||||
#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */
|
||||
#define SNDRV_CTL_ELEM_ACCESS_DINDIRECT (1<<30) /* indirect access for matrix dimensions in the info structure */
|
||||
#define SNDRV_CTL_ELEM_ACCESS_INDIRECT (1<<31) /* indirect access for element value in the value structure */
|
||||
/* bits 30 and 31 are obsoleted (for indirect access) */
|
||||
|
||||
/* for further details see the ACPI and PCI power management specification */
|
||||
#define SNDRV_CTL_POWER_D0 0x0000 /* full On */
|
||||
|
@ -793,30 +799,30 @@ struct snd_ctl_elem_info {
|
|||
} value;
|
||||
union {
|
||||
unsigned short d[4]; /* dimensions */
|
||||
unsigned short *d_ptr; /* indirect */
|
||||
unsigned short *d_ptr; /* indirect - obsoleted */
|
||||
} dimen;
|
||||
unsigned char reserved[64-4*sizeof(unsigned short)];
|
||||
};
|
||||
|
||||
struct snd_ctl_elem_value {
|
||||
struct snd_ctl_elem_id id; /* W: element ID */
|
||||
unsigned int indirect: 1; /* W: use indirect pointer (xxx_ptr member) */
|
||||
unsigned int indirect: 1; /* W: indirect access - obsoleted */
|
||||
union {
|
||||
union {
|
||||
long value[128];
|
||||
long *value_ptr;
|
||||
long *value_ptr; /* obsoleted */
|
||||
} integer;
|
||||
union {
|
||||
long long value[64];
|
||||
long long *value_ptr;
|
||||
long long *value_ptr; /* obsoleted */
|
||||
} integer64;
|
||||
union {
|
||||
unsigned int item[128];
|
||||
unsigned int *item_ptr;
|
||||
unsigned int *item_ptr; /* obsoleted */
|
||||
} enumerated;
|
||||
union {
|
||||
unsigned char data[512];
|
||||
unsigned char *data_ptr;
|
||||
unsigned char *data_ptr; /* obsoleted */
|
||||
} bytes;
|
||||
struct snd_aes_iec958 iec958;
|
||||
} value; /* RO */
|
||||
|
|
|
@ -104,6 +104,8 @@ struct snd_dm_fm_params {
|
|||
#define SNDRV_DM_FM_IOCTL_SET_MODE _IOW('H', 0x25, int)
|
||||
/* for OPL3 only */
|
||||
#define SNDRV_DM_FM_IOCTL_SET_CONNECTION _IOW('H', 0x26, int)
|
||||
/* SBI patch management */
|
||||
#define SNDRV_DM_FM_IOCTL_CLEAR_PATCHES _IO ('H', 0x40)
|
||||
|
||||
#define SNDRV_DM_FM_OSS_IOCTL_RESET 0x20
|
||||
#define SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE 0x21
|
||||
|
@ -112,4 +114,21 @@ struct snd_dm_fm_params {
|
|||
#define SNDRV_DM_FM_OSS_IOCTL_SET_MODE 0x24
|
||||
#define SNDRV_DM_FM_OSS_IOCTL_SET_OPL 0x25
|
||||
|
||||
/*
|
||||
* Patch Record - fixed size for write
|
||||
*/
|
||||
|
||||
#define FM_KEY_SBI "SBI\032"
|
||||
#define FM_KEY_2OP "2OP\032"
|
||||
#define FM_KEY_4OP "4OP\032"
|
||||
|
||||
struct sbi_patch {
|
||||
unsigned char prog;
|
||||
unsigned char bank;
|
||||
char key[4];
|
||||
char name[25];
|
||||
char extension[7];
|
||||
unsigned char data[32];
|
||||
};
|
||||
|
||||
#endif /* __SOUND_ASOUND_FM_H */
|
||||
|
|
|
@ -22,12 +22,22 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h> /* wake_up() */
|
||||
#include <linux/mutex.h> /* struct mutex */
|
||||
#include <linux/rwsem.h> /* struct rw_semaphore */
|
||||
#include <linux/pm.h> /* pm_message_t */
|
||||
#include <linux/device.h>
|
||||
|
||||
/* number of supported soundcards */
|
||||
#ifdef CONFIG_SND_DYNAMIC_MINORS
|
||||
#define SNDRV_CARDS 32
|
||||
#else
|
||||
#define SNDRV_CARDS 8 /* don't change - minor numbers */
|
||||
#endif
|
||||
|
||||
#define CONFIG_SND_MAJOR 116 /* standard configuration */
|
||||
|
||||
/* forward declarations */
|
||||
#ifdef CONFIG_PCI
|
||||
struct pci_dev;
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#define CS4231_IFACE_CTRL 0x09 /* interface control - bits 7-2 MCE */
|
||||
#define CS4231_PIN_CTRL 0x0a /* pin control */
|
||||
#define CS4231_TEST_INIT 0x0b /* test and initialization */
|
||||
#define CS4231_MISC_INFO 0x0c /* miscellaneaous information */
|
||||
#define CS4231_MISC_INFO 0x0c /* miscellaneous information */
|
||||
#define CS4231_LOOPBACK 0x0d /* loopback control */
|
||||
#define CS4231_PLY_UPR_CNT 0x0e /* playback upper base count */
|
||||
#define CS4231_PLY_LWR_CNT 0x0f /* playback lower base count */
|
||||
|
|
|
@ -1708,9 +1708,6 @@ struct snd_cs46xx {
|
|||
|
||||
struct gameport *gameport;
|
||||
|
||||
#ifdef CONFIG_SND_CS46XX_DEBUG_GPIO
|
||||
int current_gpio;
|
||||
#endif
|
||||
#ifdef CONFIG_SND_CS46XX_NEW_DSP
|
||||
struct mutex spos_mutex;
|
||||
|
||||
|
|
|
@ -1,51 +1 @@
|
|||
#ifndef __SOUND_DRIVER_H
|
||||
#define __SOUND_DRIVER_H
|
||||
|
||||
/*
|
||||
* Main header file for the ALSA driver
|
||||
* Copyright (c) 1994-2000 by Jaroslav Kysela <perex@perex.cz>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef ALSA_BUILD
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* number of supported soundcards */
|
||||
#ifdef CONFIG_SND_DYNAMIC_MINORS
|
||||
#define SNDRV_CARDS 32
|
||||
#else
|
||||
#define SNDRV_CARDS 8 /* don't change - minor numbers */
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SND_MAJOR /* standard configuration */
|
||||
#define CONFIG_SND_MAJOR 116
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SND_DEBUG
|
||||
#undef CONFIG_SND_DEBUG_MEMORY
|
||||
#endif
|
||||
|
||||
#ifdef ALSA_BUILD
|
||||
#include "adriver.h"
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#endif /* __SOUND_DRIVER_H */
|
||||
#warning "This file is deprecated"
|
||||
|
|
|
@ -1120,6 +1120,99 @@
|
|||
/************************************************************************************************/
|
||||
/* EMU1010m HANA Destinations */
|
||||
/************************************************************************************************/
|
||||
/* Hana, original 1010,1212,1820 using Alice2
|
||||
* Destiniations for SRATEX = 1X rates: 44.1 kHz or 48 kHz
|
||||
* 0x00, 0x00-0x0f: 16 EMU32 channels to Alice2
|
||||
* 0x01, 0x10-0x1f: 32 Elink channels to Audio Dock
|
||||
* 0x01, 0x00: Dock DAC 1 Left
|
||||
* 0x01, 0x04: Dock DAC 1 Right
|
||||
* 0x01, 0x08: Dock DAC 2 Left
|
||||
* 0x01, 0x0c: Dock DAC 2 Right
|
||||
* 0x01, 0x10: Dock DAC 3 Left
|
||||
* 0x01, 0x12: PHONES Left
|
||||
* 0x01, 0x14: Dock DAC 3 Right
|
||||
* 0x01, 0x16: PHONES Right
|
||||
* 0x01, 0x18: Dock DAC 4 Left
|
||||
* 0x01, 0x1a: S/PDIF Left
|
||||
* 0x01, 0x1c: Dock DAC 4 Right
|
||||
* 0x01, 0x1e: S/PDIF Right
|
||||
* 0x02, 0x00: Hana S/PDIF Left
|
||||
* 0x02, 0x01: Hana S/PDIF Right
|
||||
* 0x03, 0x00: Hanoa DAC Left
|
||||
* 0x03, 0x01: Hanoa DAC Right
|
||||
* 0x04, 0x00-0x07: Hana ADAT
|
||||
* 0x05, 0x00: I2S0 Left to Alice2
|
||||
* 0x05, 0x01: I2S0 Right to Alice2
|
||||
* 0x06, 0x00: I2S0 Left to Alice2
|
||||
* 0x06, 0x01: I2S0 Right to Alice2
|
||||
* 0x07, 0x00: I2S0 Left to Alice2
|
||||
* 0x07, 0x01: I2S0 Right to Alice2
|
||||
*
|
||||
* Hana2 never released, but used Tina
|
||||
* Not needed.
|
||||
*
|
||||
* Hana3, rev2 1010,1212,1616 using Tina
|
||||
* Destinations for SRATEX = 1X rates: 44.1 kHz or 48 kHz
|
||||
* 0x00, 0x00-0x0f: 16 EMU32A channels to Tina
|
||||
* 0x01, 0x10-0x1f: 32 EDI channels to Micro Dock
|
||||
* 0x01, 0x00: Dock DAC 1 Left
|
||||
* 0x01, 0x04: Dock DAC 1 Right
|
||||
* 0x01, 0x08: Dock DAC 2 Left
|
||||
* 0x01, 0x0c: Dock DAC 2 Right
|
||||
* 0x01, 0x10: Dock DAC 3 Left
|
||||
* 0x01, 0x12: Dock S/PDIF Left
|
||||
* 0x01, 0x14: Dock DAC 3 Right
|
||||
* 0x01, 0x16: Dock S/PDIF Right
|
||||
* 0x01, 0x18-0x1f: Dock ADAT 0-7
|
||||
* 0x02, 0x00: Hana3 S/PDIF Left
|
||||
* 0x02, 0x01: Hana3 S/PDIF Right
|
||||
* 0x03, 0x00: Hanoa DAC Left
|
||||
* 0x03, 0x01: Hanoa DAC Right
|
||||
* 0x04, 0x00-0x07: Hana3 ADAT 0-7
|
||||
* 0x05, 0x00-0x0f: 16 EMU32B channels to Tina
|
||||
* 0x06-0x07: Not used
|
||||
*
|
||||
* HanaLite, rev1 0404 using Alice2
|
||||
* Destiniations for SRATEX = 1X rates: 44.1 kHz or 48 kHz
|
||||
* 0x00, 0x00-0x0f: 16 EMU32 channels to Alice2
|
||||
* 0x01: Not used
|
||||
* 0x02, 0x00: S/PDIF Left
|
||||
* 0x02, 0x01: S/PDIF Right
|
||||
* 0x03, 0x00: DAC Left
|
||||
* 0x03, 0x01: DAC Right
|
||||
* 0x04-0x07: Not used
|
||||
*
|
||||
* HanaLiteLite, rev2 0404 using Alice2
|
||||
* Destiniations for SRATEX = 1X rates: 44.1 kHz or 48 kHz
|
||||
* 0x00, 0x00-0x0f: 16 EMU32 channels to Alice2
|
||||
* 0x01: Not used
|
||||
* 0x02, 0x00: S/PDIF Left
|
||||
* 0x02, 0x01: S/PDIF Right
|
||||
* 0x03, 0x00: DAC Left
|
||||
* 0x03, 0x01: DAC Right
|
||||
* 0x04-0x07: Not used
|
||||
*
|
||||
* Mana, Cardbus 1616 using Tina2
|
||||
* Destinations for SRATEX = 1X rates: 44.1 kHz or 48 kHz
|
||||
* 0x00, 0x00-0x0f: 16 EMU32A channels to Tina2
|
||||
* 0x01, 0x10-0x1f: 32 EDI channels to Micro Dock
|
||||
* 0x01, 0x00: Dock DAC 1 Left
|
||||
* 0x01, 0x04: Dock DAC 1 Right
|
||||
* 0x01, 0x08: Dock DAC 2 Left
|
||||
* 0x01, 0x0c: Dock DAC 2 Right
|
||||
* 0x01, 0x10: Dock DAC 3 Left
|
||||
* 0x01, 0x12: Dock S/PDIF Left
|
||||
* 0x01, 0x14: Dock DAC 3 Right
|
||||
* 0x01, 0x16: Dock S/PDIF Right
|
||||
* 0x01, 0x18-0x1f: Dock ADAT 0-7
|
||||
* 0x02: Not used
|
||||
* 0x03, 0x00: Mana DAC Left
|
||||
* 0x03, 0x01: Mana DAC Right
|
||||
* 0x04, 0x00-0x0f: 16 EMU32B channels to Tina2
|
||||
* 0x05-0x07: Not used
|
||||
*
|
||||
*
|
||||
*/
|
||||
/* 32-bit destinations of signal in the Hana FPGA. Destinations are either
|
||||
* physical outputs of Hana, or outputs going to Alice2 (audigy) for capture
|
||||
* - 16 x EMU_DST_ALICE2_EMU32_X.
|
||||
|
@ -1206,9 +1299,122 @@
|
|||
#define EMU_DST_ALICE_I2S2_LEFT 0x0700 /* Alice2 I2S2 Left */
|
||||
#define EMU_DST_ALICE_I2S2_RIGHT 0x0701 /* Alice2 I2S2 Right */
|
||||
|
||||
/* Additional destinations for 1616(M)/Microdock */
|
||||
/* Microdock S/PDIF OUT Left, 1st or 48kHz only */
|
||||
#define EMU_DST_MDOCK_SPDIF_LEFT1 0x0112
|
||||
/* Microdock S/PDIF OUT Left, 2nd or 96kHz */
|
||||
#define EMU_DST_MDOCK_SPDIF_LEFT2 0x0113
|
||||
/* Microdock S/PDIF OUT Right, 1st or 48kHz only */
|
||||
#define EMU_DST_MDOCK_SPDIF_RIGHT1 0x0116
|
||||
/* Microdock S/PDIF OUT Right, 2nd or 96kHz */
|
||||
#define EMU_DST_MDOCK_SPDIF_RIGHT2 0x0117
|
||||
/* Microdock S/PDIF ADAT 8 channel out +8 to +f */
|
||||
#define EMU_DST_MDOCK_ADAT 0x0118
|
||||
|
||||
/* Headphone jack on 1010 cardbus? 44.1/48kHz only? */
|
||||
#define EMU_DST_MANA_DAC_LEFT 0x0300
|
||||
/* Headphone jack on 1010 cardbus? 44.1/48kHz only? */
|
||||
#define EMU_DST_MANA_DAC_RIGHT 0x0301
|
||||
|
||||
/************************************************************************************************/
|
||||
/* EMU1010m HANA Sources */
|
||||
/************************************************************************************************/
|
||||
/* Hana, original 1010,1212,1820 using Alice2
|
||||
* Sources SRATEX = 1X rates: 44.1 kHz or 48 kHz
|
||||
* 0x00,0x00-0x1f: Silence
|
||||
* 0x01, 0x10-0x1f: 32 Elink channels from Audio Dock
|
||||
* 0x01, 0x00: Dock Mic A
|
||||
* 0x01, 0x04: Dock Mic B
|
||||
* 0x01, 0x08: Dock ADC 1 Left
|
||||
* 0x01, 0x0c: Dock ADC 1 Right
|
||||
* 0x01, 0x10: Dock ADC 2 Left
|
||||
* 0x01, 0x14: Dock ADC 2 Right
|
||||
* 0x01, 0x18: Dock ADC 3 Left
|
||||
* 0x01, 0x1c: Dock ADC 3 Right
|
||||
* 0x02, 0x00: Hana ADC Left
|
||||
* 0x02, 0x01: Hana ADC Right
|
||||
* 0x03, 0x00-0x0f: 16 inputs from Alice2 Emu32A output
|
||||
* 0x03, 0x10-0x1f: 16 inputs from Alice2 Emu32B output
|
||||
* 0x04, 0x00-0x07: Hana ADAT
|
||||
* 0x05, 0x00: Hana S/PDIF Left
|
||||
* 0x05, 0x01: Hana S/PDIF Right
|
||||
* 0x06-0x07: Not used
|
||||
*
|
||||
* Hana2 never released, but used Tina
|
||||
* Not needed.
|
||||
*
|
||||
* Hana3, rev2 1010,1212,1616 using Tina
|
||||
* Sources SRATEX = 1X rates: 44.1 kHz or 48 kHz
|
||||
* 0x00,0x00-0x1f: Silence
|
||||
* 0x01, 0x10-0x1f: 32 Elink channels from Audio Dock
|
||||
* 0x01, 0x00: Dock Mic A
|
||||
* 0x01, 0x04: Dock Mic B
|
||||
* 0x01, 0x08: Dock ADC 1 Left
|
||||
* 0x01, 0x0c: Dock ADC 1 Right
|
||||
* 0x01, 0x10: Dock ADC 2 Left
|
||||
* 0x01, 0x12: Dock S/PDIF Left
|
||||
* 0x01, 0x14: Dock ADC 2 Right
|
||||
* 0x01, 0x16: Dock S/PDIF Right
|
||||
* 0x01, 0x18-0x1f: Dock ADAT 0-7
|
||||
* 0x01, 0x18: Dock ADC 3 Left
|
||||
* 0x01, 0x1c: Dock ADC 3 Right
|
||||
* 0x02, 0x00: Hanoa ADC Left
|
||||
* 0x02, 0x01: Hanoa ADC Right
|
||||
* 0x03, 0x00-0x0f: 16 inputs from Tina Emu32A output
|
||||
* 0x03, 0x10-0x1f: 16 inputs from Tina Emu32B output
|
||||
* 0x04, 0x00-0x07: Hana3 ADAT
|
||||
* 0x05, 0x00: Hana3 S/PDIF Left
|
||||
* 0x05, 0x01: Hana3 S/PDIF Right
|
||||
* 0x06-0x07: Not used
|
||||
*
|
||||
* HanaLite, rev1 0404 using Alice2
|
||||
* Sources SRATEX = 1X rates: 44.1 kHz or 48 kHz
|
||||
* 0x00,0x00-0x1f: Silence
|
||||
* 0x01: Not used
|
||||
* 0x02, 0x00: ADC Left
|
||||
* 0x02, 0x01: ADC Right
|
||||
* 0x03, 0x00-0x0f: 16 inputs from Alice2 Emu32A output
|
||||
* 0x03, 0x10-0x1f: 16 inputs from Alice2 Emu32B output
|
||||
* 0x04: Not used
|
||||
* 0x05, 0x00: S/PDIF Left
|
||||
* 0x05, 0x01: S/PDIF Right
|
||||
* 0x06-0x07: Not used
|
||||
*
|
||||
* HanaLiteLite, rev2 0404 using Alice2
|
||||
* Sources SRATEX = 1X rates: 44.1 kHz or 48 kHz
|
||||
* 0x00,0x00-0x1f: Silence
|
||||
* 0x01: Not used
|
||||
* 0x02, 0x00: ADC Left
|
||||
* 0x02, 0x01: ADC Right
|
||||
* 0x03, 0x00-0x0f: 16 inputs from Alice2 Emu32A output
|
||||
* 0x03, 0x10-0x1f: 16 inputs from Alice2 Emu32B output
|
||||
* 0x04: Not used
|
||||
* 0x05, 0x00: S/PDIF Left
|
||||
* 0x05, 0x01: S/PDIF Right
|
||||
* 0x06-0x07: Not used
|
||||
*
|
||||
* Mana, Cardbus 1616 using Tina2
|
||||
* Sources SRATEX = 1X rates: 44.1 kHz or 48 kHz
|
||||
* 0x00,0x00-0x1f: Silence
|
||||
* 0x01, 0x10-0x1f: 32 Elink channels from Audio Dock
|
||||
* 0x01, 0x00: Dock Mic A
|
||||
* 0x01, 0x04: Dock Mic B
|
||||
* 0x01, 0x08: Dock ADC 1 Left
|
||||
* 0x01, 0x0c: Dock ADC 1 Right
|
||||
* 0x01, 0x10: Dock ADC 2 Left
|
||||
* 0x01, 0x12: Dock S/PDIF Left
|
||||
* 0x01, 0x14: Dock ADC 2 Right
|
||||
* 0x01, 0x16: Dock S/PDIF Right
|
||||
* 0x01, 0x18-0x1f: Dock ADAT 0-7
|
||||
* 0x01, 0x18: Dock ADC 3 Left
|
||||
* 0x01, 0x1c: Dock ADC 3 Right
|
||||
* 0x02: Not used
|
||||
* 0x03, 0x00-0x0f: 16 inputs from Tina Emu32A output
|
||||
* 0x03, 0x10-0x1f: 16 inputs from Tina Emu32B output
|
||||
* 0x04-0x07: Not used
|
||||
*
|
||||
*/
|
||||
|
||||
/* 32-bit sources of signal in the Hana FPGA. The sources are routed to
|
||||
* destinations using mixer control for each destination - see emumixer.c
|
||||
* Sources are either physical inputs of FPGA,
|
||||
|
@ -1263,6 +1469,19 @@
|
|||
#define EMU_SRC_HANA_SPDIF_LEFT2 0x0502 /* Hana SPDIF Left, 2nd or 96kHz */
|
||||
#define EMU_SRC_HANA_SPDIF_RIGHT1 0x0501 /* Hana SPDIF Right, 1st or 48kHz only */
|
||||
#define EMU_SRC_HANA_SPDIF_RIGHT2 0x0503 /* Hana SPDIF Right, 2nd or 96kHz */
|
||||
|
||||
/* Additional inputs for 1616(M)/Microdock */
|
||||
/* Microdock S/PDIF Left, 1st or 48kHz only */
|
||||
#define EMU_SRC_MDOCK_SPDIF_LEFT1 0x0112
|
||||
/* Microdock S/PDIF Left, 2nd or 96kHz */
|
||||
#define EMU_SRC_MDOCK_SPDIF_LEFT2 0x0113
|
||||
/* Microdock S/PDIF Right, 1st or 48kHz only */
|
||||
#define EMU_SRC_MDOCK_SPDIF_RIGHT1 0x0116
|
||||
/* Microdock S/PDIF Right, 2nd or 96kHz */
|
||||
#define EMU_SRC_MDOCK_SPDIF_RIGHT2 0x0117
|
||||
/* Microdock ADAT 8 channel in +8 to +f */
|
||||
#define EMU_SRC_MDOCK_ADAT 0x0118
|
||||
|
||||
/* 0x600 and 0x700 no used */
|
||||
|
||||
/* ------------------- STRUCTURES -------------------- */
|
||||
|
@ -1423,6 +1642,14 @@ struct snd_emu10k1_midi {
|
|||
void (*interrupt)(struct snd_emu10k1 *emu, unsigned int status);
|
||||
};
|
||||
|
||||
enum {
|
||||
EMU_MODEL_SB,
|
||||
EMU_MODEL_EMU1010,
|
||||
EMU_MODEL_EMU1010B,
|
||||
EMU_MODEL_EMU1616,
|
||||
EMU_MODEL_EMU0404,
|
||||
};
|
||||
|
||||
struct snd_emu_chip_details {
|
||||
u32 vendor;
|
||||
u32 device;
|
||||
|
@ -1439,7 +1666,7 @@ struct snd_emu_chip_details {
|
|||
unsigned char spdif_bug; /* Has Spdif phasing bug */
|
||||
unsigned char ac97_chip; /* Has an AC97 chip: 1 = mandatory, 2 = optional */
|
||||
unsigned char ecard; /* APS EEPROM */
|
||||
unsigned char emu1010; /* EMU 1010m card */
|
||||
unsigned char emu_model; /* EMU model type */
|
||||
unsigned char spi_dac; /* SPI interface for DAC */
|
||||
unsigned char i2c_adc; /* I2C interface for ADC */
|
||||
unsigned char adc_1361t; /* Use Philips 1361T ADC */
|
||||
|
@ -1515,6 +1742,8 @@ struct snd_emu10k1 {
|
|||
spinlock_t reg_lock;
|
||||
spinlock_t emu_lock;
|
||||
spinlock_t voice_lock;
|
||||
spinlock_t spi_lock; /* serialises access to spi port */
|
||||
spinlock_t i2c_lock; /* serialises access to i2c port */
|
||||
|
||||
struct snd_emu10k1_voice voices[NUM_G];
|
||||
struct snd_emu10k1_voice p16v_voices[4];
|
||||
|
|
|
@ -27,13 +27,8 @@
|
|||
#include "timer.h"
|
||||
#include "seq_midi_emul.h"
|
||||
#include "seq_device.h"
|
||||
#include "ainstr_iw.h"
|
||||
#include "ainstr_gf1.h"
|
||||
#include "ainstr_simple.h"
|
||||
#include <asm/io.h>
|
||||
|
||||
#define SNDRV_SEQ_DEV_ID_GUS "gus-synth"
|
||||
|
||||
/* IO ports */
|
||||
|
||||
#define GUSP(gus, x) ((gus)->gf1.port + SNDRV_g_u_s_##x)
|
||||
|
@ -234,16 +229,6 @@ struct snd_gus_port {
|
|||
|
||||
struct snd_gus_voice;
|
||||
|
||||
struct snd_gus_sample_ops {
|
||||
void (*sample_start)(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position);
|
||||
void (*sample_stop)(struct snd_gus_card *gus, struct snd_gus_voice *voice, int mode);
|
||||
void (*sample_freq)(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_frequency_t freq);
|
||||
void (*sample_volume)(struct snd_gus_card *gus, struct snd_gus_voice *voice, struct snd_seq_ev_volume *volume);
|
||||
void (*sample_loop)(struct snd_gus_card *card, struct snd_gus_voice *voice, struct snd_seq_ev_loop *loop);
|
||||
void (*sample_pos)(struct snd_gus_card *card, struct snd_gus_voice *voice, snd_seq_position_t position);
|
||||
void (*sample_private1)(struct snd_gus_card *card, struct snd_gus_voice *voice, unsigned char *data);
|
||||
};
|
||||
|
||||
#define SNDRV_GF1_VOICE_TYPE_PCM 0
|
||||
#define SNDRV_GF1_VOICE_TYPE_SYNTH 1
|
||||
#define SNDRV_GF1_VOICE_TYPE_MIDI 2
|
||||
|
@ -284,12 +269,8 @@ struct snd_gus_voice {
|
|||
|
||||
struct snd_gus_sample_ops *sample_ops;
|
||||
|
||||
struct snd_seq_instr instr;
|
||||
|
||||
/* running status / registers */
|
||||
|
||||
struct snd_seq_ev_volume sample_volume;
|
||||
|
||||
unsigned short fc_register;
|
||||
unsigned short fc_lfo;
|
||||
unsigned short gf1_volume;
|
||||
|
@ -382,10 +363,6 @@ struct snd_gf1 {
|
|||
|
||||
int seq_client;
|
||||
struct snd_gus_port seq_ports[4];
|
||||
struct snd_seq_kinstr_list *ilist;
|
||||
struct snd_iwffff_ops iwffff_ops;
|
||||
struct snd_gf1_ops gf1_ops;
|
||||
struct snd_simple_ops simple_ops;
|
||||
|
||||
/* timer */
|
||||
|
||||
|
@ -458,8 +435,6 @@ struct snd_gus_card {
|
|||
struct snd_rawmidi_substream *midi_substream_output;
|
||||
struct snd_rawmidi_substream *midi_substream_input;
|
||||
|
||||
struct snd_seq_device *seq_dev;
|
||||
|
||||
spinlock_t reg_lock;
|
||||
spinlock_t voice_alloc;
|
||||
spinlock_t active_voice_lock;
|
||||
|
@ -647,48 +622,10 @@ void snd_gus_irq_profile_init(struct snd_gus_card *gus);
|
|||
|
||||
int snd_gf1_rawmidi_new(struct snd_gus_card * gus, int device, struct snd_rawmidi **rrawmidi);
|
||||
|
||||
#if 0
|
||||
extern void snd_engine_instrument_register(unsigned short mode,
|
||||
struct _SND_INSTRUMENT_VOICE_COMMANDS *voice_cmds,
|
||||
struct _SND_INSTRUMENT_NOTE_COMMANDS *note_cmds,
|
||||
struct _SND_INSTRUMENT_CHANNEL_COMMANDS *channel_cmds);
|
||||
extern int snd_engine_instrument_register_ask(unsigned short mode);
|
||||
#endif
|
||||
|
||||
/* gus_dram.c */
|
||||
int snd_gus_dram_write(struct snd_gus_card *gus, char __user *ptr,
|
||||
unsigned int addr, unsigned int size);
|
||||
int snd_gus_dram_read(struct snd_gus_card *gus, char __user *ptr,
|
||||
unsigned int addr, unsigned int size, int rom);
|
||||
|
||||
#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
|
||||
|
||||
/* gus_sample.c */
|
||||
void snd_gus_sample_event(struct snd_seq_event *ev, struct snd_gus_port *p);
|
||||
|
||||
/* gus_simple.c */
|
||||
void snd_gf1_simple_init(struct snd_gus_voice *voice);
|
||||
|
||||
/* gus_instr.c */
|
||||
int snd_gus_iwffff_put_sample(void *private_data, struct iwffff_wave *wave,
|
||||
char __user *data, long len, int atomic);
|
||||
int snd_gus_iwffff_get_sample(void *private_data, struct iwffff_wave *wave,
|
||||
char __user *data, long len, int atomic);
|
||||
int snd_gus_iwffff_remove_sample(void *private_data, struct iwffff_wave *wave,
|
||||
int atomic);
|
||||
int snd_gus_gf1_put_sample(void *private_data, struct gf1_wave *wave,
|
||||
char __user *data, long len, int atomic);
|
||||
int snd_gus_gf1_get_sample(void *private_data, struct gf1_wave *wave,
|
||||
char __user *data, long len, int atomic);
|
||||
int snd_gus_gf1_remove_sample(void *private_data, struct gf1_wave *wave,
|
||||
int atomic);
|
||||
int snd_gus_simple_put_sample(void *private_data, struct simple_instrument *instr,
|
||||
char __user *data, long len, int atomic);
|
||||
int snd_gus_simple_get_sample(void *private_data, struct simple_instrument *instr,
|
||||
char __user *data, long len, int atomic);
|
||||
int snd_gus_simple_remove_sample(void *private_data, struct simple_instrument *instr,
|
||||
int atomic);
|
||||
|
||||
#endif /* CONFIG_SND_SEQUENCER */
|
||||
|
||||
#endif /* __SOUND_GUS_H */
|
||||
|
|
|
@ -100,8 +100,10 @@ int snd_info_minor_unregister(void);
|
|||
extern struct snd_info_entry *snd_seq_root;
|
||||
#ifdef CONFIG_SND_OSSEMUL
|
||||
extern struct snd_info_entry *snd_oss_root;
|
||||
void snd_card_info_read_oss(struct snd_info_buffer *buffer);
|
||||
#else
|
||||
#define snd_oss_root NULL
|
||||
static inline void snd_card_info_read_oss(struct snd_info_buffer *buffer) {}
|
||||
#endif
|
||||
|
||||
int snd_iprintf(struct snd_info_buffer * buffer, char *fmt,...) __attribute__ ((format (printf, 2, 3)));
|
||||
|
|
|
@ -51,19 +51,16 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "driver.h"
|
||||
#include <linux/time.h>
|
||||
#include <linux/mutex.h>
|
||||
#include "core.h"
|
||||
#include "hwdep.h"
|
||||
#include "timer.h"
|
||||
#include "seq_midi_emul.h"
|
||||
#include <sound/core.h>
|
||||
#include <sound/hwdep.h>
|
||||
#include <sound/timer.h>
|
||||
#include <sound/seq_midi_emul.h>
|
||||
#ifdef CONFIG_SND_SEQUENCER_OSS
|
||||
#include "seq_oss.h"
|
||||
#include "seq_oss_legacy.h"
|
||||
#include <sound/seq_oss.h>
|
||||
#include <sound/seq_oss_legacy.h>
|
||||
#endif
|
||||
#include "seq_device.h"
|
||||
#include "ainstr_fm.h"
|
||||
#include <sound/seq_device.h>
|
||||
#include <sound/asound_fm.h>
|
||||
|
||||
/*
|
||||
* Register numbers for the global registers
|
||||
|
@ -239,6 +236,47 @@
|
|||
|
||||
struct snd_opl3;
|
||||
|
||||
/*
|
||||
* Instrument record, aka "Patch"
|
||||
*/
|
||||
|
||||
/* FM operator */
|
||||
struct fm_operator {
|
||||
unsigned char am_vib;
|
||||
unsigned char ksl_level;
|
||||
unsigned char attack_decay;
|
||||
unsigned char sustain_release;
|
||||
unsigned char wave_select;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Instrument data */
|
||||
struct fm_instrument {
|
||||
struct fm_operator op[4];
|
||||
unsigned char feedback_connection[2];
|
||||
unsigned char echo_delay;
|
||||
unsigned char echo_atten;
|
||||
unsigned char chorus_spread;
|
||||
unsigned char trnsps;
|
||||
unsigned char fix_dur;
|
||||
unsigned char modes;
|
||||
unsigned char fix_key;
|
||||
};
|
||||
|
||||
/* type */
|
||||
#define FM_PATCH_OPL2 0x01 /* OPL2 2 operators FM instrument */
|
||||
#define FM_PATCH_OPL3 0x02 /* OPL3 4 operators FM instrument */
|
||||
|
||||
/* Instrument record */
|
||||
struct fm_patch {
|
||||
unsigned char prog;
|
||||
unsigned char bank;
|
||||
unsigned char type;
|
||||
struct fm_instrument inst;
|
||||
char name[24];
|
||||
struct fm_patch *next;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* A structure to keep track of each hardware voice
|
||||
*/
|
||||
|
@ -277,9 +315,9 @@ struct snd_opl3 {
|
|||
void *private_data;
|
||||
void (*private_free)(struct snd_opl3 *);
|
||||
|
||||
struct snd_hwdep *hwdep;
|
||||
spinlock_t reg_lock;
|
||||
struct snd_card *card; /* The card that this belongs to */
|
||||
int used; /* usage flag - exclusive */
|
||||
unsigned char fm_mode; /* OPL mode, see SNDRV_DM_FM_MODE_XXX */
|
||||
unsigned char rhythm; /* percussion mode flag */
|
||||
unsigned char max_voices; /* max number of voices */
|
||||
|
@ -297,8 +335,8 @@ struct snd_opl3 {
|
|||
struct snd_midi_channel_set * oss_chset;
|
||||
#endif
|
||||
|
||||
struct snd_seq_kinstr_ops fm_ops;
|
||||
struct snd_seq_kinstr_list *ilist;
|
||||
#define OPL3_PATCH_HASH_SIZE 32
|
||||
struct fm_patch *patch_table[OPL3_PATCH_HASH_SIZE];
|
||||
|
||||
struct snd_opl3_voice voices[MAX_OPL3_VOICES]; /* Voices (OPL3 'channel') */
|
||||
int use_time; /* allocation counter */
|
||||
|
@ -312,7 +350,6 @@ struct snd_opl3 {
|
|||
int sys_timer_status; /* system timer run status */
|
||||
spinlock_t sys_timer_lock; /* Lock for system timer access */
|
||||
#endif
|
||||
struct mutex access_mutex; /* locking */
|
||||
};
|
||||
|
||||
/* opl3.c */
|
||||
|
@ -333,8 +370,19 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3, int device, int seq_device,
|
|||
int snd_opl3_open(struct snd_hwdep * hw, struct file *file);
|
||||
int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
long snd_opl3_write(struct snd_hwdep *hw, const char __user *buf, long count,
|
||||
loff_t *offset);
|
||||
int snd_opl3_release(struct snd_hwdep * hw, struct file *file);
|
||||
|
||||
void snd_opl3_reset(struct snd_opl3 * opl3);
|
||||
|
||||
int snd_opl3_load_patch(struct snd_opl3 *opl3,
|
||||
int prog, int bank, int type,
|
||||
const char *name,
|
||||
const unsigned char *ext,
|
||||
const unsigned char *data);
|
||||
struct fm_patch *snd_opl3_find_patch(struct snd_opl3 *opl3, int prog, int bank,
|
||||
int create_patch);
|
||||
void snd_opl3_clear_patches(struct snd_opl3 *opl3);
|
||||
|
||||
#endif /* __SOUND_OPL3_H */
|
||||
|
|
|
@ -274,7 +274,6 @@ struct snd_pcm_runtime {
|
|||
snd_pcm_uframes_t period_size; /* period size */
|
||||
unsigned int periods; /* periods */
|
||||
snd_pcm_uframes_t buffer_size; /* buffer size */
|
||||
unsigned int tick_time; /* tick time */
|
||||
snd_pcm_uframes_t min_align; /* Min alignment for the format */
|
||||
size_t byte_align;
|
||||
unsigned int frame_bits;
|
||||
|
@ -286,8 +285,6 @@ struct snd_pcm_runtime {
|
|||
/* -- SW params -- */
|
||||
int tstamp_mode; /* mmap timestamp is updated */
|
||||
unsigned int period_step;
|
||||
unsigned int sleep_min; /* min ticks to sleep */
|
||||
snd_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */
|
||||
snd_pcm_uframes_t start_threshold;
|
||||
snd_pcm_uframes_t stop_threshold;
|
||||
snd_pcm_uframes_t silence_threshold; /* Silence filling happens when
|
||||
|
@ -306,7 +303,6 @@ struct snd_pcm_runtime {
|
|||
|
||||
/* -- locking / scheduling -- */
|
||||
wait_queue_head_t sleep;
|
||||
struct timer_list tick_timer;
|
||||
struct fasync_struct *fasync;
|
||||
|
||||
/* -- private section -- */
|
||||
|
@ -323,6 +319,7 @@ struct snd_pcm_runtime {
|
|||
|
||||
/* -- timer -- */
|
||||
unsigned int timer_resolution; /* timer resolution */
|
||||
int tstamp_type; /* timestamp type */
|
||||
|
||||
/* -- DMA -- */
|
||||
unsigned char *dma_area; /* DMA area */
|
||||
|
@ -810,7 +807,6 @@ static inline const struct snd_interval *hw_param_interval_c(const struct snd_pc
|
|||
#define params_periods(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_PERIODS)->min
|
||||
#define params_buffer_size(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_BUFFER_SIZE)->min
|
||||
#define params_buffer_bytes(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_BUFFER_BYTES)->min
|
||||
#define params_tick_time(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_TICK_TIME)->min
|
||||
|
||||
|
||||
int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v);
|
||||
|
@ -908,9 +904,6 @@ int snd_pcm_capture_xrun_check(struct snd_pcm_substream *substream);
|
|||
int snd_pcm_playback_xrun_asap(struct snd_pcm_substream *substream);
|
||||
int snd_pcm_capture_xrun_asap(struct snd_pcm_substream *substream);
|
||||
void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_uframes_t new_hw_ptr);
|
||||
void snd_pcm_tick_prepare(struct snd_pcm_substream *substream);
|
||||
void snd_pcm_tick_set(struct snd_pcm_substream *substream, unsigned long ticks);
|
||||
void snd_pcm_tick_elapsed(struct snd_pcm_substream *substream);
|
||||
void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
|
||||
snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream,
|
||||
const void __user *buf,
|
||||
|
@ -952,6 +945,15 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream);
|
|||
void snd_pcm_timer_init(struct snd_pcm_substream *substream);
|
||||
void snd_pcm_timer_done(struct snd_pcm_substream *substream);
|
||||
|
||||
static inline void snd_pcm_gettime(struct snd_pcm_runtime *runtime,
|
||||
struct timespec *tv)
|
||||
{
|
||||
if (runtime->tstamp_type == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
|
||||
do_posix_clock_monotonic_gettime(tv);
|
||||
else
|
||||
getnstimeofday(tv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Memory
|
||||
*/
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
#ifndef __SOUND_SEQ_INSTR_H
|
||||
#define __SOUND_SEQ_INSTR_H
|
||||
|
||||
/*
|
||||
* Main kernel header file for the ALSA sequencer
|
||||
* Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include "seq_kernel.h"
|
||||
|
||||
/* Instrument cluster */
|
||||
struct snd_seq_kcluster {
|
||||
snd_seq_instr_cluster_t cluster;
|
||||
char name[32];
|
||||
int priority;
|
||||
struct snd_seq_kcluster *next;
|
||||
};
|
||||
|
||||
/* return pointer to private data */
|
||||
#define KINSTR_DATA(kinstr) (void *)(((char *)kinstr) + sizeof(struct snd_seq_kinstr))
|
||||
|
||||
/* Instrument structure */
|
||||
struct snd_seq_kinstr {
|
||||
struct snd_seq_instr instr;
|
||||
char name[32];
|
||||
int type; /* instrument type */
|
||||
int use; /* use count */
|
||||
int busy; /* not useable */
|
||||
int add_len; /* additional length */
|
||||
struct snd_seq_kinstr_ops *ops; /* operations */
|
||||
struct snd_seq_kinstr *next;
|
||||
};
|
||||
|
||||
#define SNDRV_SEQ_INSTR_HASH_SIZE 32
|
||||
|
||||
/* Instrument flags */
|
||||
#define SNDRV_SEQ_INSTR_FLG_DIRECT (1<<0) /* accept only direct events */
|
||||
|
||||
/* List of all instruments */
|
||||
struct snd_seq_kinstr_list {
|
||||
struct snd_seq_kinstr *hash[SNDRV_SEQ_INSTR_HASH_SIZE];
|
||||
int count; /* count of all instruments */
|
||||
|
||||
struct snd_seq_kcluster *chash[SNDRV_SEQ_INSTR_HASH_SIZE];
|
||||
int ccount; /* count of all clusters */
|
||||
|
||||
int owner; /* current owner of the instrument list */
|
||||
unsigned int flags;
|
||||
|
||||
spinlock_t lock;
|
||||
spinlock_t ops_lock;
|
||||
struct mutex ops_mutex;
|
||||
unsigned long ops_flags;
|
||||
};
|
||||
|
||||
#define SNDRV_SEQ_INSTR_NOTIFY_REMOVE 0
|
||||
#define SNDRV_SEQ_INSTR_NOTIFY_CHANGE 1
|
||||
|
||||
struct snd_seq_kinstr_ops {
|
||||
void *private_data;
|
||||
long add_len; /* additional length */
|
||||
char *instr_type;
|
||||
int (*info)(void *private_data, char *info_data, long len);
|
||||
int (*put)(void *private_data, struct snd_seq_kinstr *kinstr,
|
||||
char __user *instr_data, long len, int atomic, int cmd);
|
||||
int (*get)(void *private_data, struct snd_seq_kinstr *kinstr,
|
||||
char __user *instr_data, long len, int atomic, int cmd);
|
||||
int (*get_size)(void *private_data, struct snd_seq_kinstr *kinstr, long *size);
|
||||
int (*remove)(void *private_data, struct snd_seq_kinstr *kinstr, int atomic);
|
||||
void (*notify)(void *private_data, struct snd_seq_kinstr *kinstr, int what);
|
||||
struct snd_seq_kinstr_ops *next;
|
||||
};
|
||||
|
||||
|
||||
/* instrument operations */
|
||||
struct snd_seq_kinstr_list *snd_seq_instr_list_new(void);
|
||||
void snd_seq_instr_list_free(struct snd_seq_kinstr_list **list);
|
||||
int snd_seq_instr_list_free_cond(struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_instr_header *ifree,
|
||||
int client,
|
||||
int atomic);
|
||||
struct snd_seq_kinstr *snd_seq_instr_find(struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_instr *instr,
|
||||
int exact,
|
||||
int follow_alias);
|
||||
void snd_seq_instr_free_use(struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_kinstr *instr);
|
||||
int snd_seq_instr_event(struct snd_seq_kinstr_ops *ops,
|
||||
struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_event *ev,
|
||||
int client,
|
||||
int atomic,
|
||||
int hop);
|
||||
|
||||
#endif /* __SOUND_SEQ_INSTR_H */
|
|
@ -22,7 +22,7 @@
|
|||
#define SND_SOC_NOPM -1
|
||||
|
||||
/*
|
||||
* SoC dynamic audio power managment
|
||||
* SoC dynamic audio power management
|
||||
*
|
||||
* We can have upto 4 power domains
|
||||
* 1. Codec domain - VREF, VMID
|
||||
|
@ -131,18 +131,34 @@
|
|||
.shift = wshift, .invert = winvert}
|
||||
|
||||
/* dapm kcontrol types */
|
||||
#define SOC_DAPM_SINGLE(xname, reg, shift, mask, invert) \
|
||||
#define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, mask, invert) }
|
||||
#define SOC_DAPM_DOUBLE(xname, reg, shift_left, shift_right, mask, invert, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
||||
#define SOC_DAPM_DOUBLE(xname, reg, shift_left, shift_right, max, invert, \
|
||||
power) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) |\
|
||||
((mask) << 16) | ((invert) << 24) }
|
||||
((max) << 16) | ((invert) << 24) }
|
||||
#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
||||
#define SOC_DAPM_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, \
|
||||
power, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) |\
|
||||
((max) << 16) | ((invert) << 24) }
|
||||
#define SOC_DAPM_ENUM(xname, xenum) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_enum_double, \
|
||||
|
@ -199,6 +215,7 @@ void snd_soc_dapm_free(struct snd_soc_device *socdev);
|
|||
/* dapm events */
|
||||
int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream,
|
||||
int event);
|
||||
int snd_soc_dapm_device_event(struct snd_soc_device *socdev, int event);
|
||||
|
||||
/* dapm sys fs - used by the core */
|
||||
int snd_soc_dapm_sys_add(struct device *dev);
|
||||
|
@ -272,7 +289,7 @@ struct snd_soc_dapm_widget {
|
|||
|
||||
/* external events */
|
||||
unsigned short event_flags; /* flags to specify event types */
|
||||
int (*event)(struct snd_soc_dapm_widget*, int);
|
||||
int (*event)(struct snd_soc_dapm_widget*, struct snd_kcontrol *, int);
|
||||
|
||||
/* kcontrols that relate to this widget */
|
||||
int num_kcontrols;
|
||||
|
|
|
@ -16,38 +16,63 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/ac97_codec.h>
|
||||
|
||||
#define SND_SOC_VERSION "0.13.1"
|
||||
#define SND_SOC_VERSION "0.13.2"
|
||||
|
||||
/*
|
||||
* Convenience kcontrol builders
|
||||
*/
|
||||
#define SOC_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) |\
|
||||
((shift) << 12) | ((mask) << 16) | ((invert) << 24))
|
||||
#define SOC_SINGLE_VALUE_EXT(reg,mask,invert) ((reg) | ((mask) << 16) |\
|
||||
#define SOC_SINGLE_VALUE(reg, shift, max, invert) ((reg) | ((shift) << 8) |\
|
||||
((shift) << 12) | ((max) << 16) | ((invert) << 24))
|
||||
#define SOC_SINGLE_VALUE_EXT(reg, max, invert) ((reg) | ((max) << 16) |\
|
||||
((invert) << 31))
|
||||
#define SOC_SINGLE(xname, reg, shift, mask, invert) \
|
||||
#define SOC_SINGLE(xname, reg, shift, max, invert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, mask, invert) }
|
||||
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
||||
#define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
||||
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = (reg) | ((shift_left) << 8) | \
|
||||
((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) }
|
||||
#define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert) \
|
||||
((shift_right) << 12) | ((max) << 16) | ((invert) << 24) }
|
||||
#define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, max, invert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.info = snd_soc_info_volsw_2r, \
|
||||
.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
|
||||
.private_value = (reg_left) | ((shift) << 8) | \
|
||||
((mask) << 12) | ((invert) << 20) | ((reg_right) << 24) }
|
||||
((max) << 12) | ((invert) << 20) | ((reg_right) << 24) }
|
||||
#define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
||||
.put = snd_soc_put_volsw, \
|
||||
.private_value = (reg) | ((shift_left) << 8) | \
|
||||
((shift_right) << 12) | ((max) << 16) | ((invert) << 24) }
|
||||
#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, shift, max, invert, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw_2r, \
|
||||
.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
|
||||
.private_value = (reg_left) | ((shift) << 8) | \
|
||||
((max) << 12) | ((invert) << 20) | ((reg_right) << 24) }
|
||||
#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \
|
||||
{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
|
||||
.mask = xmask, .texts = xtexts }
|
||||
|
@ -104,10 +129,22 @@
|
|||
#define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */
|
||||
#define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated when not Tx/Rx */
|
||||
|
||||
/*
|
||||
* DAI Sync
|
||||
* Synchronous LR (Left Right) clocks and Frame signals.
|
||||
*/
|
||||
#define SND_SOC_DAIFMT_SYNC (0 << 5) /* Tx FRM = Rx FRM */
|
||||
#define SND_SOC_DAIFMT_ASYNC (1 << 5) /* Tx FRM ~ Rx FRM */
|
||||
|
||||
/*
|
||||
* TDM
|
||||
*/
|
||||
#define SND_SOC_DAIFMT_TDM (1 << 6)
|
||||
|
||||
/*
|
||||
* DAI hardware signal inversions
|
||||
*/
|
||||
#define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bit clock + frame */
|
||||
#define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bclk + frm */
|
||||
#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */
|
||||
#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */
|
||||
#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */
|
||||
|
@ -410,6 +447,9 @@ struct snd_soc_dai_link {
|
|||
|
||||
/* codec/machine specific init - e.g. add machine controls */
|
||||
int (*init)(struct snd_soc_codec *codec);
|
||||
|
||||
/* DAI pcm */
|
||||
struct snd_pcm *pcm;
|
||||
};
|
||||
|
||||
/* SoC machine */
|
||||
|
@ -426,6 +466,9 @@ struct snd_soc_machine {
|
|||
int (*resume_pre)(struct platform_device *pdev);
|
||||
int (*resume_post)(struct platform_device *pdev);
|
||||
|
||||
/* callbacks */
|
||||
int (*dapm_event)(struct snd_soc_machine *, int event);
|
||||
|
||||
/* CPU <--> Codec DAI links */
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
int num_links;
|
||||
|
|
|
@ -30,6 +30,7 @@ struct snd_tea575x;
|
|||
struct snd_tea575x_ops {
|
||||
void (*write)(struct snd_tea575x *tea, unsigned int val);
|
||||
unsigned int (*read)(struct snd_tea575x *tea);
|
||||
void (*mute)(struct snd_tea575x *tea, unsigned int mute);
|
||||
};
|
||||
|
||||
struct snd_tea575x {
|
||||
|
|
|
@ -26,19 +26,12 @@
|
|||
#include "pcm.h"
|
||||
#include "mpu401.h"
|
||||
#include "ac97_codec.h"
|
||||
#include "seq_midi_emul.h"
|
||||
#include "seq_device.h"
|
||||
#include "util_mem.h"
|
||||
//#include "ainstr_iw.h"
|
||||
//#include "ainstr_gf1.h"
|
||||
#include "ainstr_simple.h"
|
||||
|
||||
#define TRIDENT_DEVICE_ID_DX ((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_DX)
|
||||
#define TRIDENT_DEVICE_ID_NX ((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_NX)
|
||||
#define TRIDENT_DEVICE_ID_SI7018 ((PCI_VENDOR_ID_SI<<16)|PCI_DEVICE_ID_SI_7018)
|
||||
|
||||
#define SNDRV_SEQ_DEV_ID_TRIDENT "trident-synth"
|
||||
|
||||
#define SNDRV_TRIDENT_VOICE_TYPE_PCM 0
|
||||
#define SNDRV_TRIDENT_VOICE_TYPE_SYNTH 1
|
||||
#define SNDRV_TRIDENT_VOICE_TYPE_MIDI 2
|
||||
|
@ -257,16 +250,6 @@ struct snd_trident;
|
|||
struct snd_trident_voice;
|
||||
struct snd_trident_pcm_mixer;
|
||||
|
||||
struct snd_trident_sample_ops {
|
||||
void (*sample_start)(struct snd_trident *gus, struct snd_trident_voice *voice, snd_seq_position_t position);
|
||||
void (*sample_stop)(struct snd_trident *gus, struct snd_trident_voice *voice, int mode);
|
||||
void (*sample_freq)(struct snd_trident *gus, struct snd_trident_voice *voice, snd_seq_frequency_t freq);
|
||||
void (*sample_volume)(struct snd_trident *gus, struct snd_trident_voice *voice, struct snd_seq_ev_volume *volume);
|
||||
void (*sample_loop)(struct snd_trident *card, struct snd_trident_voice *voice, struct snd_seq_ev_loop *loop);
|
||||
void (*sample_pos)(struct snd_trident *card, struct snd_trident_voice *voice, snd_seq_position_t position);
|
||||
void (*sample_private1)(struct snd_trident *card, struct snd_trident_voice *voice, unsigned char *data);
|
||||
};
|
||||
|
||||
struct snd_trident_port {
|
||||
struct snd_midi_channel_set * chset;
|
||||
struct snd_trident * trident;
|
||||
|
@ -300,7 +283,6 @@ struct snd_trident_voice {
|
|||
unsigned char port;
|
||||
unsigned char index;
|
||||
|
||||
struct snd_seq_instr instr;
|
||||
struct snd_trident_sample_ops *sample_ops;
|
||||
|
||||
/* channel parameters */
|
||||
|
@ -354,9 +336,6 @@ struct snd_4dwave {
|
|||
int seq_client;
|
||||
|
||||
struct snd_trident_port seq_ports[4];
|
||||
struct snd_simple_ops simple_ops;
|
||||
struct snd_seq_kinstr_list *ilist;
|
||||
|
||||
struct snd_trident_voice voices[64];
|
||||
|
||||
int ChanSynthCount; /* number of allocated synth channels */
|
||||
|
@ -416,7 +395,6 @@ struct snd_trident {
|
|||
struct snd_pcm *foldback; /* Foldback PCM */
|
||||
struct snd_pcm *spdif; /* SPDIF PCM */
|
||||
struct snd_rawmidi *rmidi;
|
||||
struct snd_seq_device *seq_dev;
|
||||
|
||||
struct snd_ac97_bus *ac97_bus;
|
||||
struct snd_ac97 *ac97;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
/* include/version.h. Generated by alsa/ksync script. */
|
||||
#define CONFIG_SND_VERSION "1.0.15"
|
||||
#define CONFIG_SND_DATE " (Tue Nov 20 19:16:42 2007 UTC)"
|
||||
#define CONFIG_SND_VERSION "1.0.16rc2"
|
||||
#define CONFIG_SND_DATE " (Thu Jan 31 16:40:16 2008 UTC)"
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
#define __AOA_H
|
||||
#include <asm/prom.h>
|
||||
#include <linux/module.h>
|
||||
/* So apparently there's a reason for requiring driver.h to be included first! */
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/asound.h>
|
||||
#include <sound/control.h>
|
||||
|
|
|
@ -138,6 +138,13 @@ static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol,
|
|||
struct onyx *onyx = snd_kcontrol_chip(kcontrol);
|
||||
s8 l, r;
|
||||
|
||||
if (ucontrol->value.integer.value[0] < -128 + VOLUME_RANGE_SHIFT ||
|
||||
ucontrol->value.integer.value[0] > -1 + VOLUME_RANGE_SHIFT)
|
||||
return -EINVAL;
|
||||
if (ucontrol->value.integer.value[1] < -128 + VOLUME_RANGE_SHIFT ||
|
||||
ucontrol->value.integer.value[1] > -1 + VOLUME_RANGE_SHIFT)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&onyx->mutex);
|
||||
onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
|
||||
onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
|
||||
|
@ -206,6 +213,9 @@ static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol,
|
|||
struct onyx *onyx = snd_kcontrol_chip(kcontrol);
|
||||
u8 v, n;
|
||||
|
||||
if (ucontrol->value.integer.value[0] < 3 + INPUTGAIN_RANGE_SHIFT ||
|
||||
ucontrol->value.integer.value[0] > 28 + INPUTGAIN_RANGE_SHIFT)
|
||||
return -EINVAL;
|
||||
mutex_lock(&onyx->mutex);
|
||||
onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
|
||||
n = v;
|
||||
|
@ -272,6 +282,8 @@ static void onyx_set_capture_source(struct onyx *onyx, int mic)
|
|||
static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
if (ucontrol->value.enumerated.item[0] > 1)
|
||||
return -EINVAL;
|
||||
onyx_set_capture_source(snd_kcontrol_chip(kcontrol),
|
||||
ucontrol->value.enumerated.item[0]);
|
||||
return 1;
|
||||
|
|
|
@ -248,6 +248,13 @@ static int tas_snd_vol_put(struct snd_kcontrol *kcontrol,
|
|||
{
|
||||
struct tas *tas = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
if (ucontrol->value.integer.value[0] < 0 ||
|
||||
ucontrol->value.integer.value[0] > 177)
|
||||
return -EINVAL;
|
||||
if (ucontrol->value.integer.value[1] < 0 ||
|
||||
ucontrol->value.integer.value[1] > 177)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&tas->mtx);
|
||||
if (tas->cached_volume_l == ucontrol->value.integer.value[0]
|
||||
&& tas->cached_volume_r == ucontrol->value.integer.value[1]) {
|
||||
|
@ -401,6 +408,10 @@ static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol,
|
|||
{
|
||||
struct tas *tas = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
if (ucontrol->value.integer.value[0] < 0 ||
|
||||
ucontrol->value.integer.value[0] > TAS3004_DRC_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&tas->mtx);
|
||||
if (tas->drc_range == ucontrol->value.integer.value[0]) {
|
||||
mutex_unlock(&tas->mtx);
|
||||
|
@ -447,7 +458,7 @@ static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol,
|
|||
return 0;
|
||||
}
|
||||
|
||||
tas->drc_enabled = ucontrol->value.integer.value[0];
|
||||
tas->drc_enabled = !!ucontrol->value.integer.value[0];
|
||||
if (tas->hw_enabled)
|
||||
tas3004_set_drc(tas);
|
||||
mutex_unlock(&tas->mtx);
|
||||
|
@ -494,6 +505,8 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol,
|
|||
struct tas *tas = snd_kcontrol_chip(kcontrol);
|
||||
int oldacr;
|
||||
|
||||
if (ucontrol->value.enumerated.item[0] > 1)
|
||||
return -EINVAL;
|
||||
mutex_lock(&tas->mtx);
|
||||
oldacr = tas->acr;
|
||||
|
||||
|
@ -562,6 +575,9 @@ static int tas_snd_treble_put(struct snd_kcontrol *kcontrol,
|
|||
{
|
||||
struct tas *tas = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
if (ucontrol->value.integer.value[0] < TAS3004_TREBLE_MIN ||
|
||||
ucontrol->value.integer.value[0] > TAS3004_TREBLE_MAX)
|
||||
return -EINVAL;
|
||||
mutex_lock(&tas->mtx);
|
||||
if (tas->treble == ucontrol->value.integer.value[0]) {
|
||||
mutex_unlock(&tas->mtx);
|
||||
|
@ -610,6 +626,9 @@ static int tas_snd_bass_put(struct snd_kcontrol *kcontrol,
|
|||
{
|
||||
struct tas *tas = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
if (ucontrol->value.integer.value[0] < TAS3004_BASS_MIN ||
|
||||
ucontrol->value.integer.value[0] > TAS3004_BASS_MAX)
|
||||
return -EINVAL;
|
||||
mutex_lock(&tas->mtx);
|
||||
if (tas->bass == ucontrol->value.integer.value[0]) {
|
||||
mutex_unlock(&tas->mtx);
|
||||
|
|
|
@ -600,7 +600,7 @@ static int n##_control_put(struct snd_kcontrol *kcontrol, \
|
|||
struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \
|
||||
if (gpio->methods && gpio->methods->get_##n) \
|
||||
gpio->methods->set_##n(gpio, \
|
||||
ucontrol->value.integer.value[0]); \
|
||||
!!ucontrol->value.integer.value[0]); \
|
||||
return 1; \
|
||||
} \
|
||||
static struct snd_kcontrol_new n##_ctl = { \
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
|
||||
#include <asm/macio.h>
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
|
||||
#include <asm/io.h>
|
||||
#include <linux/delay.h>
|
||||
/* So apparently there's a reason for requiring driver.h
|
||||
* to be included first, even if I don't know it... */
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <asm/macio.h>
|
||||
#include <linux/pci.h>
|
||||
|
@ -194,6 +191,12 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
|
|||
hw->period_bytes_max = 16384;
|
||||
hw->periods_min = 3;
|
||||
hw->periods_max = MAX_DBDMA_COMMANDS;
|
||||
err = snd_pcm_hw_constraint_integer(pi->substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_PERIODS);
|
||||
if (err < 0) {
|
||||
result = err;
|
||||
goto out_unlock;
|
||||
}
|
||||
list_for_each_entry(cii, &sdev->codec_list, list) {
|
||||
if (cii->codec->open) {
|
||||
err = cii->codec->open(cii, pi->substream);
|
||||
|
@ -990,6 +993,7 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
|
|||
if (dev->pcm->card != card) {
|
||||
printk(KERN_ERR
|
||||
"Can't attach same bus to different cards!\n");
|
||||
err = -EINVAL;
|
||||
goto out_put_ci_module;
|
||||
}
|
||||
err = snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 1);
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <asm/irq.h>
|
||||
#include <asm/sizes.h>
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/ac97_codec.h>
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include <linux/wait.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/ac97_codec.h>
|
||||
|
@ -352,6 +351,7 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
|
|||
snprintf(card->longname, sizeof(card->longname),
|
||||
"%s (%s)", dev->dev.driver->name, card->mixername);
|
||||
|
||||
snd_card_set_dev(card, &dev->dev);
|
||||
ret = snd_card_register(card);
|
||||
if (ret == 0) {
|
||||
platform_set_drvdata(dev, card);
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
|
|
@ -59,7 +59,6 @@
|
|||
*
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/threads.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -232,8 +231,6 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
|
|||
access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
|
||||
(ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
|
||||
SNDRV_CTL_ELEM_ACCESS_INACTIVE|
|
||||
SNDRV_CTL_ELEM_ACCESS_DINDIRECT|
|
||||
SNDRV_CTL_ELEM_ACCESS_INDIRECT|
|
||||
SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE|
|
||||
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK));
|
||||
kctl.info = ncontrol->info;
|
||||
|
@ -692,7 +689,7 @@ int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control)
|
|||
struct snd_kcontrol *kctl;
|
||||
struct snd_kcontrol_volatile *vd;
|
||||
unsigned int index_offset;
|
||||
int result, indirect;
|
||||
int result;
|
||||
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, &control->id);
|
||||
|
@ -701,18 +698,13 @@ int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control)
|
|||
} else {
|
||||
index_offset = snd_ctl_get_ioff(kctl, &control->id);
|
||||
vd = &kctl->vd[index_offset];
|
||||
indirect = vd->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT ? 1 : 0;
|
||||
if (control->indirect != indirect) {
|
||||
result = -EACCES;
|
||||
} else {
|
||||
if ((vd->access & SNDRV_CTL_ELEM_ACCESS_READ) && kctl->get != NULL) {
|
||||
if ((vd->access & SNDRV_CTL_ELEM_ACCESS_READ) &&
|
||||
kctl->get != NULL) {
|
||||
snd_ctl_build_ioff(&control->id, kctl, index_offset);
|
||||
result = kctl->get(kctl, control);
|
||||
} else {
|
||||
} else
|
||||
result = -EPERM;
|
||||
}
|
||||
}
|
||||
}
|
||||
up_read(&card->controls_rwsem);
|
||||
return result;
|
||||
}
|
||||
|
@ -748,7 +740,7 @@ int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
|
|||
struct snd_kcontrol *kctl;
|
||||
struct snd_kcontrol_volatile *vd;
|
||||
unsigned int index_offset;
|
||||
int result, indirect;
|
||||
int result;
|
||||
|
||||
down_read(&card->controls_rwsem);
|
||||
kctl = snd_ctl_find_id(card, &control->id);
|
||||
|
@ -757,13 +749,9 @@ int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
|
|||
} else {
|
||||
index_offset = snd_ctl_get_ioff(kctl, &control->id);
|
||||
vd = &kctl->vd[index_offset];
|
||||
indirect = vd->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT ? 1 : 0;
|
||||
if (control->indirect != indirect) {
|
||||
result = -EACCES;
|
||||
} else {
|
||||
if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) ||
|
||||
kctl->put == NULL ||
|
||||
(file && vd->owner != NULL && vd->owner != file)) {
|
||||
(file && vd->owner && vd->owner != file)) {
|
||||
result = -EPERM;
|
||||
} else {
|
||||
snd_ctl_build_ioff(&control->id, kctl, index_offset);
|
||||
|
@ -771,11 +759,11 @@ int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
|
|||
}
|
||||
if (result > 0) {
|
||||
up_read(&card->controls_rwsem);
|
||||
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &control->id);
|
||||
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
|
||||
&control->id);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
up_read(&card->controls_rwsem);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -219,7 +219,8 @@ static int copy_ctl_value_from_user(struct snd_card *card,
|
|||
struct snd_ctl_elem_value32 __user *data32,
|
||||
int *typep, int *countp)
|
||||
{
|
||||
int i, type, count, size;
|
||||
int i, type, size;
|
||||
int uninitialized_var(count);
|
||||
unsigned int indirect;
|
||||
|
||||
if (copy_from_user(&data->id, &data32->id, sizeof(data->id)))
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/errno.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/smp_lock.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/string.h>
|
||||
|
@ -66,8 +65,6 @@ int snd_oss_info_register(int dev, int num, char *string)
|
|||
|
||||
EXPORT_SYMBOL(snd_oss_info_register);
|
||||
|
||||
extern void snd_card_info_read_oss(struct snd_info_buffer *buffer);
|
||||
|
||||
static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev)
|
||||
{
|
||||
int idx, ok = -1;
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/file.h>
|
||||
|
@ -43,6 +42,40 @@ EXPORT_SYMBOL(snd_cards);
|
|||
|
||||
static DEFINE_MUTEX(snd_card_mutex);
|
||||
|
||||
static char *slots[SNDRV_CARDS];
|
||||
module_param_array(slots, charp, NULL, 0444);
|
||||
MODULE_PARM_DESC(slots, "Module names assigned to the slots.");
|
||||
|
||||
/* return non-zero if the given index is already reserved for another
|
||||
* module via slots option
|
||||
*/
|
||||
static int module_slot_mismatch(struct module *module, int idx)
|
||||
{
|
||||
#ifdef MODULE
|
||||
char *s1, *s2;
|
||||
if (!module || !module->name || !slots[idx])
|
||||
return 0;
|
||||
s1 = slots[idx];
|
||||
s2 = module->name;
|
||||
/* compare module name strings
|
||||
* hyphens are handled as equivalent with underscore
|
||||
*/
|
||||
for (;;) {
|
||||
char c1 = *s1++;
|
||||
char c2 = *s2++;
|
||||
if (c1 == '-')
|
||||
c1 = '_';
|
||||
if (c2 == '-')
|
||||
c2 = '_';
|
||||
if (c1 != c2)
|
||||
return 1;
|
||||
if (!c1)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
|
||||
int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag);
|
||||
EXPORT_SYMBOL(snd_mixer_oss_notify_callback);
|
||||
|
@ -115,6 +148,8 @@ struct snd_card *snd_card_new(int idx, const char *xid,
|
|||
for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
|
||||
/* idx == -1 == 0xffff means: take any free slot */
|
||||
if (~snd_cards_lock & idx & 1<<idx2) {
|
||||
if (module_slot_mismatch(module, idx2))
|
||||
continue;
|
||||
idx = idx2;
|
||||
if (idx >= snd_ecards_limit)
|
||||
snd_ecards_limit = idx + 1;
|
||||
|
@ -304,8 +339,8 @@ int snd_card_disconnect(struct snd_card *card)
|
|||
list_add(&mfile->shutdown_list, &shutdown_files);
|
||||
spin_unlock(&shutdown_lock);
|
||||
|
||||
fops_get(&snd_shutdown_f_ops);
|
||||
mfile->file->f_op = &snd_shutdown_f_ops;
|
||||
fops_get(mfile->file->f_op);
|
||||
|
||||
mfile = mfile->next;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
#undef HAVE_REALLY_SLOW_DMA_CONTROLLER
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <asm/dma.h>
|
||||
|
||||
|
|
|
@ -568,6 +568,7 @@ static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer,
|
|||
if (pci_set_dma_mask(pci, mask) < 0 ||
|
||||
pci_set_consistent_dma_mask(pci, mask) < 0) {
|
||||
printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device);
|
||||
pci_dev_put(pci);
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <sound/core.h>
|
||||
|
||||
/**
|
||||
* copy_to_user_fromio - copy data from mmio-space to user-space
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/ioport.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/time.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/time.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/time.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/time.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#define OSS_DEBUG
|
||||
#endif
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
|
@ -985,10 +984,8 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
|
|||
sw_params->stop_threshold = runtime->buffer_size;
|
||||
sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
|
||||
sw_params->period_step = 1;
|
||||
sw_params->sleep_min = 0;
|
||||
sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
|
||||
1 : runtime->period_size;
|
||||
sw_params->xfer_align = 1;
|
||||
if (atomic_read(&substream->mmap_count) ||
|
||||
substream->oss.setup.nosilence) {
|
||||
sw_params->silence_threshold = 0;
|
||||
|
@ -1624,6 +1621,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
|
|||
snd_pcm_format_set_silence(runtime->format,
|
||||
runtime->oss.buffer,
|
||||
size1);
|
||||
size1 /= runtime->channels; /* frames */
|
||||
fs = snd_enter_user();
|
||||
snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1);
|
||||
snd_leave_user(fs);
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#define PLUGIN_DEBUG
|
||||
#endif
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/time.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
#include <sound/core.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
|
@ -228,7 +227,7 @@ static char *snd_pcm_subformat_names[] = {
|
|||
|
||||
static char *snd_pcm_tstamp_mode_names[] = {
|
||||
TSTAMP(NONE),
|
||||
TSTAMP(MMAP),
|
||||
TSTAMP(ENABLE),
|
||||
};
|
||||
|
||||
static const char *snd_pcm_stream_name(int stream)
|
||||
|
@ -359,7 +358,6 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
|
|||
snd_iprintf(buffer, "rate: %u (%u/%u)\n", runtime->rate, runtime->rate_num, runtime->rate_den);
|
||||
snd_iprintf(buffer, "period_size: %lu\n", runtime->period_size);
|
||||
snd_iprintf(buffer, "buffer_size: %lu\n", runtime->buffer_size);
|
||||
snd_iprintf(buffer, "tick_time: %u\n", runtime->tick_time);
|
||||
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
|
||||
if (substream->oss.oss) {
|
||||
snd_iprintf(buffer, "OSS format: %s\n", snd_pcm_oss_format_name(runtime->oss.format));
|
||||
|
@ -387,9 +385,7 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
|
|||
}
|
||||
snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode));
|
||||
snd_iprintf(buffer, "period_step: %u\n", runtime->period_step);
|
||||
snd_iprintf(buffer, "sleep_min: %u\n", runtime->sleep_min);
|
||||
snd_iprintf(buffer, "avail_min: %lu\n", runtime->control->avail_min);
|
||||
snd_iprintf(buffer, "xfer_align: %lu\n", runtime->xfer_align);
|
||||
snd_iprintf(buffer, "start_threshold: %lu\n", runtime->start_threshold);
|
||||
snd_iprintf(buffer, "stop_threshold: %lu\n", runtime->stop_threshold);
|
||||
snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold);
|
||||
|
@ -765,12 +761,6 @@ static int snd_pcm_dev_free(struct snd_device *device)
|
|||
return snd_pcm_free(pcm);
|
||||
}
|
||||
|
||||
static void snd_pcm_tick_timer_func(unsigned long data)
|
||||
{
|
||||
struct snd_pcm_substream *substream = (struct snd_pcm_substream *) data;
|
||||
snd_pcm_tick_elapsed(substream);
|
||||
}
|
||||
|
||||
int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
|
||||
struct file *file,
|
||||
struct snd_pcm_substream **rsubstream)
|
||||
|
@ -877,9 +867,6 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
|
|||
memset((void*)runtime->control, 0, size);
|
||||
|
||||
init_waitqueue_head(&runtime->sleep);
|
||||
init_timer(&runtime->tick_timer);
|
||||
runtime->tick_timer.function = snd_pcm_tick_timer_func;
|
||||
runtime->tick_timer.data = (unsigned long) substream;
|
||||
|
||||
runtime->status->state = SNDRV_PCM_STATE_OPEN;
|
||||
|
||||
|
|
|
@ -484,6 +484,7 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
|
|||
case SNDRV_PCM_IOCTL_PVERSION:
|
||||
case SNDRV_PCM_IOCTL_INFO:
|
||||
case SNDRV_PCM_IOCTL_TSTAMP:
|
||||
case SNDRV_PCM_IOCTL_TTSTAMP:
|
||||
case SNDRV_PCM_IOCTL_HWSYNC:
|
||||
case SNDRV_PCM_IOCTL_PREPARE:
|
||||
case SNDRV_PCM_IOCTL_RESET:
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
#include <sound/core.h>
|
||||
|
@ -145,11 +144,11 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substre
|
|||
{
|
||||
snd_pcm_uframes_t pos;
|
||||
|
||||
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
|
||||
snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
|
||||
pos = substream->ops->pointer(substream);
|
||||
if (pos == SNDRV_PCM_POS_XRUN)
|
||||
return pos; /* XRUN */
|
||||
if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP)
|
||||
getnstimeofday((struct timespec *)&runtime->status->tstamp);
|
||||
#ifdef CONFIG_SND_DEBUG
|
||||
if (pos >= runtime->buffer_size) {
|
||||
snd_printk(KERN_ERR "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size);
|
||||
|
@ -1139,7 +1138,7 @@ EXPORT_SYMBOL(snd_pcm_hw_constraint_step);
|
|||
|
||||
static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
|
||||
{
|
||||
static int pow2_sizes[] = {
|
||||
static unsigned int pow2_sizes[] = {
|
||||
1<<0, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7,
|
||||
1<<8, 1<<9, 1<<10, 1<<11, 1<<12, 1<<13, 1<<14, 1<<15,
|
||||
1<<16, 1<<17, 1<<18, 1<<19, 1<<20, 1<<21, 1<<22, 1<<23,
|
||||
|
@ -1451,108 +1450,13 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
|
|||
|
||||
EXPORT_SYMBOL(snd_pcm_lib_ioctl);
|
||||
|
||||
/*
|
||||
* Conditions
|
||||
*/
|
||||
|
||||
static void snd_pcm_system_tick_set(struct snd_pcm_substream *substream,
|
||||
unsigned long ticks)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
if (ticks == 0)
|
||||
del_timer(&runtime->tick_timer);
|
||||
else {
|
||||
ticks += (1000000 / HZ) - 1;
|
||||
ticks /= (1000000 / HZ);
|
||||
mod_timer(&runtime->tick_timer, jiffies + ticks);
|
||||
}
|
||||
}
|
||||
|
||||
/* Temporary alias */
|
||||
void snd_pcm_tick_set(struct snd_pcm_substream *substream, unsigned long ticks)
|
||||
{
|
||||
snd_pcm_system_tick_set(substream, ticks);
|
||||
}
|
||||
|
||||
void snd_pcm_tick_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
snd_pcm_uframes_t frames = ULONG_MAX;
|
||||
snd_pcm_uframes_t avail, dist;
|
||||
unsigned int ticks;
|
||||
u_int64_t n;
|
||||
u_int32_t r;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
if (runtime->silence_size >= runtime->boundary) {
|
||||
frames = 1;
|
||||
} else if (runtime->silence_size > 0 &&
|
||||
runtime->silence_filled < runtime->buffer_size) {
|
||||
snd_pcm_sframes_t noise_dist;
|
||||
noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled;
|
||||
if (noise_dist > (snd_pcm_sframes_t)runtime->silence_threshold)
|
||||
frames = noise_dist - runtime->silence_threshold;
|
||||
}
|
||||
avail = snd_pcm_playback_avail(runtime);
|
||||
} else {
|
||||
avail = snd_pcm_capture_avail(runtime);
|
||||
}
|
||||
if (avail < runtime->control->avail_min) {
|
||||
snd_pcm_sframes_t n = runtime->control->avail_min - avail;
|
||||
if (n > 0 && frames > (snd_pcm_uframes_t)n)
|
||||
frames = n;
|
||||
}
|
||||
if (avail < runtime->buffer_size) {
|
||||
snd_pcm_sframes_t n = runtime->buffer_size - avail;
|
||||
if (n > 0 && frames > (snd_pcm_uframes_t)n)
|
||||
frames = n;
|
||||
}
|
||||
if (frames == ULONG_MAX) {
|
||||
snd_pcm_tick_set(substream, 0);
|
||||
return;
|
||||
}
|
||||
dist = runtime->status->hw_ptr - runtime->hw_ptr_base;
|
||||
/* Distance to next interrupt */
|
||||
dist = runtime->period_size - dist % runtime->period_size;
|
||||
if (dist <= frames) {
|
||||
snd_pcm_tick_set(substream, 0);
|
||||
return;
|
||||
}
|
||||
/* the base time is us */
|
||||
n = frames;
|
||||
n *= 1000000;
|
||||
div64_32(&n, runtime->tick_time * runtime->rate, &r);
|
||||
ticks = n + (r > 0 ? 1 : 0);
|
||||
if (ticks < runtime->sleep_min)
|
||||
ticks = runtime->sleep_min;
|
||||
snd_pcm_tick_set(substream, (unsigned long) ticks);
|
||||
}
|
||||
|
||||
void snd_pcm_tick_elapsed(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime;
|
||||
unsigned long flags;
|
||||
|
||||
snd_assert(substream != NULL, return);
|
||||
runtime = substream->runtime;
|
||||
snd_assert(runtime != NULL, return);
|
||||
|
||||
snd_pcm_stream_lock_irqsave(substream, flags);
|
||||
if (!snd_pcm_running(substream) ||
|
||||
snd_pcm_update_hw_ptr(substream) < 0)
|
||||
goto _end;
|
||||
if (runtime->sleep_min)
|
||||
snd_pcm_tick_prepare(substream);
|
||||
_end:
|
||||
snd_pcm_stream_unlock_irqrestore(substream, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_pcm_period_elapsed - update the pcm status for the next period
|
||||
* @substream: the pcm substream instance
|
||||
*
|
||||
* This function is called from the interrupt handler when the
|
||||
* PCM has processed the period size. It will update the current
|
||||
* pointer, set up the tick, wake up sleepers, etc.
|
||||
* pointer, wake up sleepers, etc.
|
||||
*
|
||||
* Even if more than one periods have elapsed since the last call, you
|
||||
* have to call this only once.
|
||||
|
@ -1576,8 +1480,6 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
|
|||
|
||||
if (substream->timer_running)
|
||||
snd_timer_interrupt(substream->timer, 1);
|
||||
if (runtime->sleep_min)
|
||||
snd_pcm_tick_prepare(substream);
|
||||
_end:
|
||||
snd_pcm_stream_unlock_irqrestore(substream, flags);
|
||||
if (runtime->transfer_ack_end)
|
||||
|
@ -1587,6 +1489,71 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
|
|||
|
||||
EXPORT_SYMBOL(snd_pcm_period_elapsed);
|
||||
|
||||
/*
|
||||
* Wait until avail_min data becomes available
|
||||
* Returns a negative error code if any error occurs during operation.
|
||||
* The available space is stored on availp. When err = 0 and avail = 0
|
||||
* on the capture stream, it indicates the stream is in DRAINING state.
|
||||
*/
|
||||
static int wait_for_avail_min(struct snd_pcm_substream *substream,
|
||||
snd_pcm_uframes_t *availp)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
int is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
||||
wait_queue_t wait;
|
||||
int err = 0;
|
||||
snd_pcm_uframes_t avail = 0;
|
||||
long tout;
|
||||
|
||||
init_waitqueue_entry(&wait, current);
|
||||
add_wait_queue(&runtime->sleep, &wait);
|
||||
for (;;) {
|
||||
if (signal_pending(current)) {
|
||||
err = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
tout = schedule_timeout(msecs_to_jiffies(10000));
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
switch (runtime->status->state) {
|
||||
case SNDRV_PCM_STATE_SUSPENDED:
|
||||
err = -ESTRPIPE;
|
||||
goto _endloop;
|
||||
case SNDRV_PCM_STATE_XRUN:
|
||||
err = -EPIPE;
|
||||
goto _endloop;
|
||||
case SNDRV_PCM_STATE_DRAINING:
|
||||
if (is_playback)
|
||||
err = -EPIPE;
|
||||
else
|
||||
avail = 0; /* indicate draining */
|
||||
goto _endloop;
|
||||
case SNDRV_PCM_STATE_OPEN:
|
||||
case SNDRV_PCM_STATE_SETUP:
|
||||
case SNDRV_PCM_STATE_DISCONNECTED:
|
||||
err = -EBADFD;
|
||||
goto _endloop;
|
||||
}
|
||||
if (!tout) {
|
||||
snd_printd("%s write error (DMA or IRQ trouble?)\n",
|
||||
is_playback ? "playback" : "capture");
|
||||
err = -EIO;
|
||||
break;
|
||||
}
|
||||
if (is_playback)
|
||||
avail = snd_pcm_playback_avail(runtime);
|
||||
else
|
||||
avail = snd_pcm_capture_avail(runtime);
|
||||
if (avail >= runtime->control->avail_min)
|
||||
break;
|
||||
}
|
||||
_endloop:
|
||||
remove_wait_queue(&runtime->sleep, &wait);
|
||||
*availp = avail;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
|
||||
unsigned int hwoff,
|
||||
unsigned long data, unsigned int off,
|
||||
|
@ -1624,8 +1591,6 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
|
|||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
if (size > runtime->xfer_align)
|
||||
size -= size % runtime->xfer_align;
|
||||
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
switch (runtime->status->state) {
|
||||
|
@ -1648,84 +1613,18 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
|
|||
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
|
||||
snd_pcm_uframes_t avail;
|
||||
snd_pcm_uframes_t cont;
|
||||
if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
|
||||
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
|
||||
snd_pcm_update_hw_ptr(substream);
|
||||
avail = snd_pcm_playback_avail(runtime);
|
||||
if (((avail < runtime->control->avail_min && size > avail) ||
|
||||
(size >= runtime->xfer_align && avail < runtime->xfer_align))) {
|
||||
wait_queue_t wait;
|
||||
enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED, DROPPED } state;
|
||||
long tout;
|
||||
|
||||
if (!avail) {
|
||||
if (nonblock) {
|
||||
err = -EAGAIN;
|
||||
goto _end_unlock;
|
||||
}
|
||||
|
||||
init_waitqueue_entry(&wait, current);
|
||||
add_wait_queue(&runtime->sleep, &wait);
|
||||
while (1) {
|
||||
if (signal_pending(current)) {
|
||||
state = SIGNALED;
|
||||
break;
|
||||
}
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
tout = schedule_timeout(10 * HZ);
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
if (tout == 0) {
|
||||
if (runtime->status->state != SNDRV_PCM_STATE_PREPARED &&
|
||||
runtime->status->state != SNDRV_PCM_STATE_PAUSED) {
|
||||
state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (runtime->status->state) {
|
||||
case SNDRV_PCM_STATE_XRUN:
|
||||
case SNDRV_PCM_STATE_DRAINING:
|
||||
state = ERROR;
|
||||
goto _end_loop;
|
||||
case SNDRV_PCM_STATE_SUSPENDED:
|
||||
state = SUSPENDED;
|
||||
goto _end_loop;
|
||||
case SNDRV_PCM_STATE_SETUP:
|
||||
state = DROPPED;
|
||||
goto _end_loop;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
avail = snd_pcm_playback_avail(runtime);
|
||||
if (avail >= runtime->control->avail_min) {
|
||||
state = READY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_end_loop:
|
||||
remove_wait_queue(&runtime->sleep, &wait);
|
||||
|
||||
switch (state) {
|
||||
case ERROR:
|
||||
err = -EPIPE;
|
||||
err = wait_for_avail_min(substream, &avail);
|
||||
if (err < 0)
|
||||
goto _end_unlock;
|
||||
case SUSPENDED:
|
||||
err = -ESTRPIPE;
|
||||
goto _end_unlock;
|
||||
case SIGNALED:
|
||||
err = -ERESTARTSYS;
|
||||
goto _end_unlock;
|
||||
case EXPIRED:
|
||||
snd_printd("playback write error (DMA or IRQ trouble?)\n");
|
||||
err = -EIO;
|
||||
goto _end_unlock;
|
||||
case DROPPED:
|
||||
err = -EBADFD;
|
||||
goto _end_unlock;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (avail > runtime->xfer_align)
|
||||
avail -= avail % runtime->xfer_align;
|
||||
frames = size > avail ? avail : size;
|
||||
cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
|
||||
if (frames > cont)
|
||||
|
@ -1763,9 +1662,6 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
|
|||
if (err < 0)
|
||||
goto _end_unlock;
|
||||
}
|
||||
if (runtime->sleep_min &&
|
||||
runtime->status->state == SNDRV_PCM_STATE_RUNNING)
|
||||
snd_pcm_tick_prepare(substream);
|
||||
}
|
||||
_end_unlock:
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
|
@ -1893,8 +1789,6 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
|
|||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
if (size > runtime->xfer_align)
|
||||
size -= size % runtime->xfer_align;
|
||||
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
switch (runtime->status->state) {
|
||||
|
@ -1924,91 +1818,25 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
|
|||
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
|
||||
snd_pcm_uframes_t avail;
|
||||
snd_pcm_uframes_t cont;
|
||||
if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
|
||||
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
|
||||
snd_pcm_update_hw_ptr(substream);
|
||||
__draining:
|
||||
avail = snd_pcm_capture_avail(runtime);
|
||||
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
|
||||
if (avail < runtime->xfer_align) {
|
||||
err = -EPIPE;
|
||||
if (!avail) {
|
||||
if (runtime->status->state ==
|
||||
SNDRV_PCM_STATE_DRAINING) {
|
||||
snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
|
||||
goto _end_unlock;
|
||||
}
|
||||
} else if ((avail < runtime->control->avail_min && size > avail) ||
|
||||
(size >= runtime->xfer_align && avail < runtime->xfer_align)) {
|
||||
wait_queue_t wait;
|
||||
enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED, DROPPED } state;
|
||||
long tout;
|
||||
|
||||
if (nonblock) {
|
||||
err = -EAGAIN;
|
||||
goto _end_unlock;
|
||||
}
|
||||
|
||||
init_waitqueue_entry(&wait, current);
|
||||
add_wait_queue(&runtime->sleep, &wait);
|
||||
while (1) {
|
||||
if (signal_pending(current)) {
|
||||
state = SIGNALED;
|
||||
break;
|
||||
}
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
tout = schedule_timeout(10 * HZ);
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
if (tout == 0) {
|
||||
if (runtime->status->state != SNDRV_PCM_STATE_PREPARED &&
|
||||
runtime->status->state != SNDRV_PCM_STATE_PAUSED) {
|
||||
state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (runtime->status->state) {
|
||||
case SNDRV_PCM_STATE_XRUN:
|
||||
state = ERROR;
|
||||
goto _end_loop;
|
||||
case SNDRV_PCM_STATE_SUSPENDED:
|
||||
state = SUSPENDED;
|
||||
goto _end_loop;
|
||||
case SNDRV_PCM_STATE_DRAINING:
|
||||
goto __draining;
|
||||
case SNDRV_PCM_STATE_SETUP:
|
||||
state = DROPPED;
|
||||
goto _end_loop;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
avail = snd_pcm_capture_avail(runtime);
|
||||
if (avail >= runtime->control->avail_min) {
|
||||
state = READY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_end_loop:
|
||||
remove_wait_queue(&runtime->sleep, &wait);
|
||||
|
||||
switch (state) {
|
||||
case ERROR:
|
||||
err = -EPIPE;
|
||||
err = wait_for_avail_min(substream, &avail);
|
||||
if (err < 0)
|
||||
goto _end_unlock;
|
||||
case SUSPENDED:
|
||||
err = -ESTRPIPE;
|
||||
goto _end_unlock;
|
||||
case SIGNALED:
|
||||
err = -ERESTARTSYS;
|
||||
goto _end_unlock;
|
||||
case EXPIRED:
|
||||
snd_printd("capture read error (DMA or IRQ trouble?)\n");
|
||||
err = -EIO;
|
||||
goto _end_unlock;
|
||||
case DROPPED:
|
||||
err = -EBADFD;
|
||||
goto _end_unlock;
|
||||
default:
|
||||
break;
|
||||
if (!avail)
|
||||
continue; /* draining */
|
||||
}
|
||||
}
|
||||
if (avail > runtime->xfer_align)
|
||||
avail -= avail % runtime->xfer_align;
|
||||
frames = size > avail ? avail : size;
|
||||
cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
|
||||
if (frames > cont)
|
||||
|
@ -2040,9 +1868,6 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
|
|||
offset += frames;
|
||||
size -= frames;
|
||||
xfer += frames;
|
||||
if (runtime->sleep_min &&
|
||||
runtime->status->state == SNDRV_PCM_STATE_RUNNING)
|
||||
snd_pcm_tick_prepare(substream);
|
||||
}
|
||||
_end_unlock:
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/time.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
@ -75,7 +74,7 @@ static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
|
|||
},
|
||||
[SNDRV_PCM_FORMAT_U24_BE] = {
|
||||
.width = 24, .phys = 32, .le = 0, .signd = 0,
|
||||
.silence = { 0x80, 0x00, 0x00 },
|
||||
.silence = { 0x00, 0x80, 0x00, 0x00 },
|
||||
},
|
||||
[SNDRV_PCM_FORMAT_S32_LE] = {
|
||||
.width = 32, .phys = 32, .le = 1, .signd = 1,
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -413,7 +412,6 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
runtime->period_size = params_period_size(params);
|
||||
runtime->periods = params_periods(params);
|
||||
runtime->buffer_size = params_buffer_size(params);
|
||||
runtime->tick_time = params_tick_time(params);
|
||||
runtime->info = params->info;
|
||||
runtime->rate_num = params->rate_num;
|
||||
runtime->rate_den = params->rate_den;
|
||||
|
@ -433,9 +431,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
/* Default sw params */
|
||||
runtime->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
|
||||
runtime->period_step = 1;
|
||||
runtime->sleep_min = 0;
|
||||
runtime->control->avail_min = runtime->period_size;
|
||||
runtime->xfer_align = runtime->period_size;
|
||||
runtime->start_threshold = 1;
|
||||
runtime->stop_threshold = runtime->buffer_size;
|
||||
runtime->silence_threshold = 0;
|
||||
|
@ -532,9 +528,6 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
|
|||
return -EINVAL;
|
||||
if (params->avail_min == 0)
|
||||
return -EINVAL;
|
||||
if (params->xfer_align == 0 ||
|
||||
params->xfer_align % runtime->min_align != 0)
|
||||
return -EINVAL;
|
||||
if (params->silence_size >= runtime->boundary) {
|
||||
if (params->silence_threshold != 0)
|
||||
return -EINVAL;
|
||||
|
@ -546,20 +539,14 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
|
|||
}
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
runtime->tstamp_mode = params->tstamp_mode;
|
||||
runtime->sleep_min = params->sleep_min;
|
||||
runtime->period_step = params->period_step;
|
||||
runtime->control->avail_min = params->avail_min;
|
||||
runtime->start_threshold = params->start_threshold;
|
||||
runtime->stop_threshold = params->stop_threshold;
|
||||
runtime->silence_threshold = params->silence_threshold;
|
||||
runtime->silence_size = params->silence_size;
|
||||
runtime->xfer_align = params->xfer_align;
|
||||
params->boundary = runtime->boundary;
|
||||
if (snd_pcm_running(substream)) {
|
||||
if (runtime->sleep_min)
|
||||
snd_pcm_tick_prepare(substream);
|
||||
else
|
||||
snd_pcm_tick_set(substream, 0);
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
|
||||
runtime->silence_size > 0)
|
||||
snd_pcm_playback_silence(substream, ULONG_MAX);
|
||||
|
@ -595,12 +582,13 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
|
|||
status->trigger_tstamp = runtime->trigger_tstamp;
|
||||
if (snd_pcm_running(substream)) {
|
||||
snd_pcm_update_hw_ptr(substream);
|
||||
if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP)
|
||||
if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
|
||||
status->tstamp = runtime->status->tstamp;
|
||||
else
|
||||
getnstimeofday(&status->tstamp);
|
||||
} else
|
||||
getnstimeofday(&status->tstamp);
|
||||
goto _tstamp_end;
|
||||
}
|
||||
}
|
||||
snd_pcm_gettime(runtime, &status->tstamp);
|
||||
_tstamp_end:
|
||||
status->appl_ptr = runtime->control->appl_ptr;
|
||||
status->hw_ptr = runtime->status->hw_ptr;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
|
@ -688,7 +676,7 @@ static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream)
|
|||
if (runtime->trigger_master == NULL)
|
||||
return;
|
||||
if (runtime->trigger_master == substream) {
|
||||
getnstimeofday(&runtime->trigger_tstamp);
|
||||
snd_pcm_gettime(runtime, &runtime->trigger_tstamp);
|
||||
} else {
|
||||
snd_pcm_trigger_tstamp(runtime->trigger_master);
|
||||
runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp;
|
||||
|
@ -875,8 +863,6 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
|
|||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
|
||||
runtime->silence_size > 0)
|
||||
snd_pcm_playback_silence(substream, ULONG_MAX);
|
||||
if (runtime->sleep_min)
|
||||
snd_pcm_tick_prepare(substream);
|
||||
if (substream->timer)
|
||||
snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTART,
|
||||
&runtime->trigger_tstamp);
|
||||
|
@ -930,7 +916,6 @@ static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state)
|
|||
snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTOP,
|
||||
&runtime->trigger_tstamp);
|
||||
runtime->status->state = state;
|
||||
snd_pcm_tick_set(substream, 0);
|
||||
}
|
||||
wake_up(&runtime->sleep);
|
||||
}
|
||||
|
@ -1014,12 +999,9 @@ static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push)
|
|||
snd_timer_notify(substream->timer,
|
||||
SNDRV_TIMER_EVENT_MPAUSE,
|
||||
&runtime->trigger_tstamp);
|
||||
snd_pcm_tick_set(substream, 0);
|
||||
wake_up(&runtime->sleep);
|
||||
} else {
|
||||
runtime->status->state = SNDRV_PCM_STATE_RUNNING;
|
||||
if (runtime->sleep_min)
|
||||
snd_pcm_tick_prepare(substream);
|
||||
if (substream->timer)
|
||||
snd_timer_notify(substream->timer,
|
||||
SNDRV_TIMER_EVENT_MCONTINUE,
|
||||
|
@ -1074,7 +1056,6 @@ static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state)
|
|||
&runtime->trigger_tstamp);
|
||||
runtime->status->suspended_state = runtime->status->state;
|
||||
runtime->status->state = SNDRV_PCM_STATE_SUSPENDED;
|
||||
snd_pcm_tick_set(substream, 0);
|
||||
wake_up(&runtime->sleep);
|
||||
}
|
||||
|
||||
|
@ -1177,8 +1158,6 @@ static void snd_pcm_post_resume(struct snd_pcm_substream *substream, int state)
|
|||
snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MRESUME,
|
||||
&runtime->trigger_tstamp);
|
||||
runtime->status->state = runtime->status->suspended_state;
|
||||
if (runtime->sleep_min)
|
||||
snd_pcm_tick_prepare(substream);
|
||||
}
|
||||
|
||||
static struct action_ops snd_pcm_action_resume = {
|
||||
|
@ -1395,10 +1374,10 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
|
|||
} else {
|
||||
/* stop running stream */
|
||||
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) {
|
||||
int state = snd_pcm_capture_avail(runtime) > 0 ?
|
||||
int new_state = snd_pcm_capture_avail(runtime) > 0 ?
|
||||
SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP;
|
||||
snd_pcm_do_stop(substream, state);
|
||||
snd_pcm_post_stop(substream, state);
|
||||
snd_pcm_do_stop(substream, new_state);
|
||||
snd_pcm_post_stop(substream, new_state);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -2007,8 +1986,6 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
|
|||
}
|
||||
|
||||
/* FIXME: this belong to lowlevel */
|
||||
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_TICK_TIME,
|
||||
1000000 / HZ, 1000000 / HZ);
|
||||
snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
|
||||
|
||||
return 0;
|
||||
|
@ -2244,15 +2221,10 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst
|
|||
}
|
||||
if (frames > (snd_pcm_uframes_t)hw_avail)
|
||||
frames = hw_avail;
|
||||
else
|
||||
frames -= frames % runtime->xfer_align;
|
||||
appl_ptr = runtime->control->appl_ptr - frames;
|
||||
if (appl_ptr < 0)
|
||||
appl_ptr += runtime->boundary;
|
||||
runtime->control->appl_ptr = appl_ptr;
|
||||
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING &&
|
||||
runtime->sleep_min)
|
||||
snd_pcm_tick_prepare(substream);
|
||||
ret = frames;
|
||||
__end:
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
|
@ -2294,15 +2266,10 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr
|
|||
}
|
||||
if (frames > (snd_pcm_uframes_t)hw_avail)
|
||||
frames = hw_avail;
|
||||
else
|
||||
frames -= frames % runtime->xfer_align;
|
||||
appl_ptr = runtime->control->appl_ptr - frames;
|
||||
if (appl_ptr < 0)
|
||||
appl_ptr += runtime->boundary;
|
||||
runtime->control->appl_ptr = appl_ptr;
|
||||
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING &&
|
||||
runtime->sleep_min)
|
||||
snd_pcm_tick_prepare(substream);
|
||||
ret = frames;
|
||||
__end:
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
|
@ -2345,15 +2312,10 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs
|
|||
}
|
||||
if (frames > (snd_pcm_uframes_t)avail)
|
||||
frames = avail;
|
||||
else
|
||||
frames -= frames % runtime->xfer_align;
|
||||
appl_ptr = runtime->control->appl_ptr + frames;
|
||||
if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
|
||||
appl_ptr -= runtime->boundary;
|
||||
runtime->control->appl_ptr = appl_ptr;
|
||||
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING &&
|
||||
runtime->sleep_min)
|
||||
snd_pcm_tick_prepare(substream);
|
||||
ret = frames;
|
||||
__end:
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
|
@ -2396,15 +2358,10 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst
|
|||
}
|
||||
if (frames > (snd_pcm_uframes_t)avail)
|
||||
frames = avail;
|
||||
else
|
||||
frames -= frames % runtime->xfer_align;
|
||||
appl_ptr = runtime->control->appl_ptr + frames;
|
||||
if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
|
||||
appl_ptr -= runtime->boundary;
|
||||
runtime->control->appl_ptr = appl_ptr;
|
||||
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING &&
|
||||
runtime->sleep_min)
|
||||
snd_pcm_tick_prepare(substream);
|
||||
ret = frames;
|
||||
__end:
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
|
@ -2520,6 +2477,21 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
int arg;
|
||||
|
||||
if (get_user(arg, _arg))
|
||||
return -EFAULT;
|
||||
if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST)
|
||||
return -EINVAL;
|
||||
runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY;
|
||||
if (arg == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
|
||||
runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_common_ioctl1(struct file *file,
|
||||
struct snd_pcm_substream *substream,
|
||||
unsigned int cmd, void __user *arg)
|
||||
|
@ -2533,6 +2505,8 @@ static int snd_pcm_common_ioctl1(struct file *file,
|
|||
return snd_pcm_info_user(substream, arg);
|
||||
case SNDRV_PCM_IOCTL_TSTAMP: /* just for compatibility */
|
||||
return 0;
|
||||
case SNDRV_PCM_IOCTL_TTSTAMP:
|
||||
return snd_pcm_tstamp(substream, arg);
|
||||
case SNDRV_PCM_IOCTL_HW_REFINE:
|
||||
return snd_pcm_hw_refine_user(substream, arg);
|
||||
case SNDRV_PCM_IOCTL_HW_PARAMS:
|
||||
|
@ -3018,26 +2992,23 @@ static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
|
|||
/*
|
||||
* mmap status record
|
||||
*/
|
||||
static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area,
|
||||
unsigned long address, int *type)
|
||||
static int snd_pcm_mmap_status_fault(struct vm_area_struct *area,
|
||||
struct vm_fault *vmf)
|
||||
{
|
||||
struct snd_pcm_substream *substream = area->vm_private_data;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
struct page * page;
|
||||
|
||||
if (substream == NULL)
|
||||
return NOPAGE_SIGBUS;
|
||||
return VM_FAULT_SIGBUS;
|
||||
runtime = substream->runtime;
|
||||
page = virt_to_page(runtime->status);
|
||||
get_page(page);
|
||||
if (type)
|
||||
*type = VM_FAULT_MINOR;
|
||||
return page;
|
||||
vmf->page = virt_to_page(runtime->status);
|
||||
get_page(vmf->page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct vm_operations_struct snd_pcm_vm_ops_status =
|
||||
{
|
||||
.nopage = snd_pcm_mmap_status_nopage,
|
||||
.fault = snd_pcm_mmap_status_fault,
|
||||
};
|
||||
|
||||
static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
|
||||
|
@ -3061,26 +3032,23 @@ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file
|
|||
/*
|
||||
* mmap control record
|
||||
*/
|
||||
static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area,
|
||||
unsigned long address, int *type)
|
||||
static int snd_pcm_mmap_control_fault(struct vm_area_struct *area,
|
||||
struct vm_fault *vmf)
|
||||
{
|
||||
struct snd_pcm_substream *substream = area->vm_private_data;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
struct page * page;
|
||||
|
||||
if (substream == NULL)
|
||||
return NOPAGE_SIGBUS;
|
||||
return VM_FAULT_SIGBUS;
|
||||
runtime = substream->runtime;
|
||||
page = virt_to_page(runtime->control);
|
||||
get_page(page);
|
||||
if (type)
|
||||
*type = VM_FAULT_MINOR;
|
||||
return page;
|
||||
vmf->page = virt_to_page(runtime->control);
|
||||
get_page(vmf->page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct vm_operations_struct snd_pcm_vm_ops_control =
|
||||
{
|
||||
.nopage = snd_pcm_mmap_control_nopage,
|
||||
.fault = snd_pcm_mmap_control_fault,
|
||||
};
|
||||
|
||||
static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
|
||||
|
@ -3117,10 +3085,10 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
|
|||
#endif /* coherent mmap */
|
||||
|
||||
/*
|
||||
* nopage callback for mmapping a RAM page
|
||||
* fault callback for mmapping a RAM page
|
||||
*/
|
||||
static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area,
|
||||
unsigned long address, int *type)
|
||||
static int snd_pcm_mmap_data_fault(struct vm_area_struct *area,
|
||||
struct vm_fault *vmf)
|
||||
{
|
||||
struct snd_pcm_substream *substream = area->vm_private_data;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
|
@ -3130,33 +3098,30 @@ static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area,
|
|||
size_t dma_bytes;
|
||||
|
||||
if (substream == NULL)
|
||||
return NOPAGE_SIGBUS;
|
||||
return VM_FAULT_SIGBUS;
|
||||
runtime = substream->runtime;
|
||||
offset = area->vm_pgoff << PAGE_SHIFT;
|
||||
offset += address - area->vm_start;
|
||||
snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_SIGBUS);
|
||||
offset = vmf->pgoff << PAGE_SHIFT;
|
||||
dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
|
||||
if (offset > dma_bytes - PAGE_SIZE)
|
||||
return NOPAGE_SIGBUS;
|
||||
return VM_FAULT_SIGBUS;
|
||||
if (substream->ops->page) {
|
||||
page = substream->ops->page(substream, offset);
|
||||
if (!page)
|
||||
return NOPAGE_OOM; /* XXX: is this really due to OOM? */
|
||||
return VM_FAULT_SIGBUS;
|
||||
} else {
|
||||
vaddr = runtime->dma_area + offset;
|
||||
page = virt_to_page(vaddr);
|
||||
}
|
||||
get_page(page);
|
||||
if (type)
|
||||
*type = VM_FAULT_MINOR;
|
||||
return page;
|
||||
vmf->page = page;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct vm_operations_struct snd_pcm_vm_ops_data =
|
||||
{
|
||||
.open = snd_pcm_mmap_data_open,
|
||||
.close = snd_pcm_mmap_data_close,
|
||||
.nopage = snd_pcm_mmap_data_nopage,
|
||||
.fault = snd_pcm_mmap_data_fault,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/time.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -912,7 +911,8 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
|
|||
}
|
||||
|
||||
static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
|
||||
unsigned char *buf, long count, int kernel)
|
||||
unsigned char __user *userbuf,
|
||||
unsigned char *kernelbuf, long count)
|
||||
{
|
||||
unsigned long flags;
|
||||
long result = 0, count1;
|
||||
|
@ -925,11 +925,11 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
|
|||
spin_lock_irqsave(&runtime->lock, flags);
|
||||
if (count1 > (int)runtime->avail)
|
||||
count1 = runtime->avail;
|
||||
if (kernel) {
|
||||
memcpy(buf + result, runtime->buffer + runtime->appl_ptr, count1);
|
||||
} else {
|
||||
if (kernelbuf)
|
||||
memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1);
|
||||
if (userbuf) {
|
||||
spin_unlock_irqrestore(&runtime->lock, flags);
|
||||
if (copy_to_user((char __user *)buf + result,
|
||||
if (copy_to_user(userbuf + result,
|
||||
runtime->buffer + runtime->appl_ptr, count1)) {
|
||||
return result > 0 ? result : -EFAULT;
|
||||
}
|
||||
|
@ -949,7 +949,7 @@ long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream,
|
|||
unsigned char *buf, long count)
|
||||
{
|
||||
snd_rawmidi_input_trigger(substream, 1);
|
||||
return snd_rawmidi_kernel_read1(substream, buf, count, 1);
|
||||
return snd_rawmidi_kernel_read1(substream, NULL/*userbuf*/, buf, count);
|
||||
}
|
||||
|
||||
static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t count,
|
||||
|
@ -990,8 +990,9 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
|
|||
}
|
||||
spin_unlock_irq(&runtime->lock);
|
||||
count1 = snd_rawmidi_kernel_read1(substream,
|
||||
(unsigned char __force *)buf,
|
||||
count, 0);
|
||||
(unsigned char __user *)buf,
|
||||
NULL/*kernelbuf*/,
|
||||
count);
|
||||
if (count1 < 0)
|
||||
return result > 0 ? result : count1;
|
||||
result += count1;
|
||||
|
@ -1132,13 +1133,15 @@ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
|
|||
}
|
||||
|
||||
static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
|
||||
const unsigned char *buf, long count, int kernel)
|
||||
const unsigned char __user *userbuf,
|
||||
const unsigned char *kernelbuf,
|
||||
long count)
|
||||
{
|
||||
unsigned long flags;
|
||||
long count1, result;
|
||||
struct snd_rawmidi_runtime *runtime = substream->runtime;
|
||||
|
||||
snd_assert(buf != NULL, return -EINVAL);
|
||||
snd_assert(kernelbuf != NULL || userbuf != NULL, return -EINVAL);
|
||||
snd_assert(runtime->buffer != NULL, return -EINVAL);
|
||||
|
||||
result = 0;
|
||||
|
@ -1155,12 +1158,13 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
|
|||
count1 = count;
|
||||
if (count1 > (long)runtime->avail)
|
||||
count1 = runtime->avail;
|
||||
if (kernel) {
|
||||
memcpy(runtime->buffer + runtime->appl_ptr, buf, count1);
|
||||
} else {
|
||||
if (kernelbuf)
|
||||
memcpy(runtime->buffer + runtime->appl_ptr,
|
||||
kernelbuf + result, count1);
|
||||
else if (userbuf) {
|
||||
spin_unlock_irqrestore(&runtime->lock, flags);
|
||||
if (copy_from_user(runtime->buffer + runtime->appl_ptr,
|
||||
(char __user *)buf, count1)) {
|
||||
userbuf + result, count1)) {
|
||||
spin_lock_irqsave(&runtime->lock, flags);
|
||||
result = result > 0 ? result : -EFAULT;
|
||||
goto __end;
|
||||
|
@ -1171,7 +1175,6 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
|
|||
runtime->appl_ptr %= runtime->buffer_size;
|
||||
runtime->avail -= count1;
|
||||
result += count1;
|
||||
buf += count1;
|
||||
count -= count1;
|
||||
}
|
||||
__end:
|
||||
|
@ -1185,7 +1188,7 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
|
|||
long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream,
|
||||
const unsigned char *buf, long count)
|
||||
{
|
||||
return snd_rawmidi_kernel_write1(substream, buf, count, 1);
|
||||
return snd_rawmidi_kernel_write1(substream, NULL, buf, count);
|
||||
}
|
||||
|
||||
static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
|
||||
|
@ -1225,9 +1228,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
|
|||
spin_lock_irq(&runtime->lock);
|
||||
}
|
||||
spin_unlock_irq(&runtime->lock);
|
||||
count1 = snd_rawmidi_kernel_write1(substream,
|
||||
(unsigned char __force *)buf,
|
||||
count, 0);
|
||||
count1 = snd_rawmidi_kernel_write1(substream, buf, NULL, count);
|
||||
if (count1 < 0)
|
||||
return result > 0 ? result : count1;
|
||||
result += count1;
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
|
||||
#
|
||||
|
||||
obj-$(CONFIG_SND) += instr/
|
||||
ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
|
||||
obj-$(CONFIG_SND_SEQUENCER) += oss/
|
||||
endif
|
||||
|
@ -15,7 +14,6 @@ snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \
|
|||
snd-seq-midi-objs := seq_midi.o
|
||||
snd-seq-midi-emul-objs := seq_midi_emul.o
|
||||
snd-seq-midi-event-objs := seq_midi_event.o
|
||||
snd-seq-instr-objs := seq_instr.o
|
||||
snd-seq-dummy-objs := seq_dummy.o
|
||||
snd-seq-virmidi-objs := seq_virmidi.o
|
||||
|
||||
|
@ -36,9 +34,7 @@ obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o
|
|||
# Toplevel Module Dependency
|
||||
obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o
|
||||
obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o
|
||||
obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
|
||||
obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
|
||||
obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-seq-midi-emul.o snd-seq-instr.o
|
||||
obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o
|
||||
obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o
|
||||
obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o
|
||||
obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o
|
||||
obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-seq-midi-emul.o snd-seq-instr.o
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
#
|
||||
# Makefile for ALSA
|
||||
# Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
|
||||
#
|
||||
|
||||
snd-ainstr-fm-objs := ainstr_fm.o
|
||||
snd-ainstr-simple-objs := ainstr_simple.o
|
||||
snd-ainstr-gf1-objs := ainstr_gf1.o
|
||||
snd-ainstr-iw-objs := ainstr_iw.o
|
||||
|
||||
#
|
||||
# this function returns:
|
||||
# "m" - CONFIG_SND_SEQUENCER is m
|
||||
# <empty string> - CONFIG_SND_SEQUENCER is undefined
|
||||
# otherwise parameter #1 value
|
||||
#
|
||||
sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
|
||||
|
||||
# Toplevel Module Dependency
|
||||
obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-ainstr-fm.o
|
||||
obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-ainstr-fm.o
|
||||
obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-ainstr-gf1.o snd-ainstr-simple.o snd-ainstr-iw.o
|
||||
obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-ainstr-simple.o
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
* FM (OPL2/3) Instrument routines
|
||||
* Copyright (c) 2000 Uros Bizjak <uros@kss-loka.si>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/ainstr_fm.h>
|
||||
#include <sound/initval.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
|
||||
MODULE_DESCRIPTION("Advanced Linux Sound Architecture FM Instrument support.");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int snd_seq_fm_put(void *private_data, struct snd_seq_kinstr *instr,
|
||||
char __user *instr_data, long len, int atomic, int cmd)
|
||||
{
|
||||
struct fm_instrument *ip;
|
||||
struct fm_xinstrument ix;
|
||||
int idx;
|
||||
|
||||
if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
|
||||
return -EINVAL;
|
||||
/* copy instrument data */
|
||||
if (len < (long)sizeof(ix))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&ix, instr_data, sizeof(ix)))
|
||||
return -EFAULT;
|
||||
if (ix.stype != FM_STRU_INSTR)
|
||||
return -EINVAL;
|
||||
ip = (struct fm_instrument *)KINSTR_DATA(instr);
|
||||
ip->share_id[0] = le32_to_cpu(ix.share_id[0]);
|
||||
ip->share_id[1] = le32_to_cpu(ix.share_id[1]);
|
||||
ip->share_id[2] = le32_to_cpu(ix.share_id[2]);
|
||||
ip->share_id[3] = le32_to_cpu(ix.share_id[3]);
|
||||
ip->type = ix.type;
|
||||
for (idx = 0; idx < 4; idx++) {
|
||||
ip->op[idx].am_vib = ix.op[idx].am_vib;
|
||||
ip->op[idx].ksl_level = ix.op[idx].ksl_level;
|
||||
ip->op[idx].attack_decay = ix.op[idx].attack_decay;
|
||||
ip->op[idx].sustain_release = ix.op[idx].sustain_release;
|
||||
ip->op[idx].wave_select = ix.op[idx].wave_select;
|
||||
}
|
||||
for (idx = 0; idx < 2; idx++) {
|
||||
ip->feedback_connection[idx] = ix.feedback_connection[idx];
|
||||
}
|
||||
ip->echo_delay = ix.echo_delay;
|
||||
ip->echo_atten = ix.echo_atten;
|
||||
ip->chorus_spread = ix.chorus_spread;
|
||||
ip->trnsps = ix.trnsps;
|
||||
ip->fix_dur = ix.fix_dur;
|
||||
ip->modes = ix.modes;
|
||||
ip->fix_key = ix.fix_key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_seq_fm_get(void *private_data, struct snd_seq_kinstr *instr,
|
||||
char __user *instr_data, long len, int atomic,
|
||||
int cmd)
|
||||
{
|
||||
struct fm_instrument *ip;
|
||||
struct fm_xinstrument ix;
|
||||
int idx;
|
||||
|
||||
if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
|
||||
return -EINVAL;
|
||||
if (len < (long)sizeof(ix))
|
||||
return -ENOMEM;
|
||||
memset(&ix, 0, sizeof(ix));
|
||||
ip = (struct fm_instrument *)KINSTR_DATA(instr);
|
||||
ix.stype = FM_STRU_INSTR;
|
||||
ix.share_id[0] = cpu_to_le32(ip->share_id[0]);
|
||||
ix.share_id[1] = cpu_to_le32(ip->share_id[1]);
|
||||
ix.share_id[2] = cpu_to_le32(ip->share_id[2]);
|
||||
ix.share_id[3] = cpu_to_le32(ip->share_id[3]);
|
||||
ix.type = ip->type;
|
||||
for (idx = 0; idx < 4; idx++) {
|
||||
ix.op[idx].am_vib = ip->op[idx].am_vib;
|
||||
ix.op[idx].ksl_level = ip->op[idx].ksl_level;
|
||||
ix.op[idx].attack_decay = ip->op[idx].attack_decay;
|
||||
ix.op[idx].sustain_release = ip->op[idx].sustain_release;
|
||||
ix.op[idx].wave_select = ip->op[idx].wave_select;
|
||||
}
|
||||
for (idx = 0; idx < 2; idx++) {
|
||||
ix.feedback_connection[idx] = ip->feedback_connection[idx];
|
||||
}
|
||||
if (copy_to_user(instr_data, &ix, sizeof(ix)))
|
||||
return -EFAULT;
|
||||
ix.echo_delay = ip->echo_delay;
|
||||
ix.echo_atten = ip->echo_atten;
|
||||
ix.chorus_spread = ip->chorus_spread;
|
||||
ix.trnsps = ip->trnsps;
|
||||
ix.fix_dur = ip->fix_dur;
|
||||
ix.modes = ip->modes;
|
||||
ix.fix_key = ip->fix_key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_seq_fm_get_size(void *private_data, struct snd_seq_kinstr *instr,
|
||||
long *size)
|
||||
{
|
||||
*size = sizeof(struct fm_xinstrument);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_seq_fm_init(struct snd_seq_kinstr_ops *ops,
|
||||
struct snd_seq_kinstr_ops *next)
|
||||
{
|
||||
memset(ops, 0, sizeof(*ops));
|
||||
// ops->private_data = private_data;
|
||||
ops->add_len = sizeof(struct fm_instrument);
|
||||
ops->instr_type = SNDRV_SEQ_INSTR_ID_OPL2_3;
|
||||
ops->put = snd_seq_fm_put;
|
||||
ops->get = snd_seq_fm_get;
|
||||
ops->get_size = snd_seq_fm_get_size;
|
||||
// ops->remove = snd_seq_fm_remove;
|
||||
// ops->notify = snd_seq_fm_notify;
|
||||
ops->next = next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Init part
|
||||
*/
|
||||
|
||||
static int __init alsa_ainstr_fm_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit alsa_ainstr_fm_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(alsa_ainstr_fm_init)
|
||||
module_exit(alsa_ainstr_fm_exit)
|
||||
|
||||
EXPORT_SYMBOL(snd_seq_fm_init);
|
|
@ -1,359 +0,0 @@
|
|||
/*
|
||||
* GF1 (GUS) Patch - Instrument routines
|
||||
* Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/ainstr_gf1.h>
|
||||
#include <sound/initval.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
|
||||
MODULE_DESCRIPTION("Advanced Linux Sound Architecture GF1 (GUS) Patch support.");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static unsigned int snd_seq_gf1_size(unsigned int size, unsigned int format)
|
||||
{
|
||||
unsigned int result = size;
|
||||
|
||||
if (format & GF1_WAVE_16BIT)
|
||||
result <<= 1;
|
||||
if (format & GF1_WAVE_STEREO)
|
||||
result <<= 1;
|
||||
return format;
|
||||
}
|
||||
|
||||
static int snd_seq_gf1_copy_wave_from_stream(struct snd_gf1_ops *ops,
|
||||
struct gf1_instrument *ip,
|
||||
char __user **data,
|
||||
long *len,
|
||||
int atomic)
|
||||
{
|
||||
struct gf1_wave *wp, *prev;
|
||||
struct gf1_xwave xp;
|
||||
int err;
|
||||
gfp_t gfp_mask;
|
||||
unsigned int real_size;
|
||||
|
||||
gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
|
||||
if (*len < (long)sizeof(xp))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&xp, *data, sizeof(xp)))
|
||||
return -EFAULT;
|
||||
*data += sizeof(xp);
|
||||
*len -= sizeof(xp);
|
||||
wp = kzalloc(sizeof(*wp), gfp_mask);
|
||||
if (wp == NULL)
|
||||
return -ENOMEM;
|
||||
wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
|
||||
wp->share_id[1] = le32_to_cpu(xp.share_id[1]);
|
||||
wp->share_id[2] = le32_to_cpu(xp.share_id[2]);
|
||||
wp->share_id[3] = le32_to_cpu(xp.share_id[3]);
|
||||
wp->format = le32_to_cpu(xp.format);
|
||||
wp->size = le32_to_cpu(xp.size);
|
||||
wp->start = le32_to_cpu(xp.start);
|
||||
wp->loop_start = le32_to_cpu(xp.loop_start);
|
||||
wp->loop_end = le32_to_cpu(xp.loop_end);
|
||||
wp->loop_repeat = le16_to_cpu(xp.loop_repeat);
|
||||
wp->flags = xp.flags;
|
||||
wp->sample_rate = le32_to_cpu(xp.sample_rate);
|
||||
wp->low_frequency = le32_to_cpu(xp.low_frequency);
|
||||
wp->high_frequency = le32_to_cpu(xp.high_frequency);
|
||||
wp->root_frequency = le32_to_cpu(xp.root_frequency);
|
||||
wp->tune = le16_to_cpu(xp.tune);
|
||||
wp->balance = xp.balance;
|
||||
memcpy(wp->envelope_rate, xp.envelope_rate, 6);
|
||||
memcpy(wp->envelope_offset, xp.envelope_offset, 6);
|
||||
wp->tremolo_sweep = xp.tremolo_sweep;
|
||||
wp->tremolo_rate = xp.tremolo_rate;
|
||||
wp->tremolo_depth = xp.tremolo_depth;
|
||||
wp->vibrato_sweep = xp.vibrato_sweep;
|
||||
wp->vibrato_rate = xp.vibrato_rate;
|
||||
wp->vibrato_depth = xp.vibrato_depth;
|
||||
wp->scale_frequency = le16_to_cpu(xp.scale_frequency);
|
||||
wp->scale_factor = le16_to_cpu(xp.scale_factor);
|
||||
real_size = snd_seq_gf1_size(wp->size, wp->format);
|
||||
if ((long)real_size > *len) {
|
||||
kfree(wp);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (ops->put_sample) {
|
||||
err = ops->put_sample(ops->private_data, wp,
|
||||
*data, real_size, atomic);
|
||||
if (err < 0) {
|
||||
kfree(wp);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
*data += real_size;
|
||||
*len -= real_size;
|
||||
prev = ip->wave;
|
||||
if (prev) {
|
||||
while (prev->next) prev = prev->next;
|
||||
prev->next = wp;
|
||||
} else {
|
||||
ip->wave = wp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void snd_seq_gf1_wave_free(struct snd_gf1_ops *ops,
|
||||
struct gf1_wave *wave,
|
||||
int atomic)
|
||||
{
|
||||
if (ops->remove_sample)
|
||||
ops->remove_sample(ops->private_data, wave, atomic);
|
||||
kfree(wave);
|
||||
}
|
||||
|
||||
static void snd_seq_gf1_instr_free(struct snd_gf1_ops *ops,
|
||||
struct gf1_instrument *ip,
|
||||
int atomic)
|
||||
{
|
||||
struct gf1_wave *wave;
|
||||
|
||||
while ((wave = ip->wave) != NULL) {
|
||||
ip->wave = wave->next;
|
||||
snd_seq_gf1_wave_free(ops, wave, atomic);
|
||||
}
|
||||
}
|
||||
|
||||
static int snd_seq_gf1_put(void *private_data, struct snd_seq_kinstr *instr,
|
||||
char __user *instr_data, long len, int atomic,
|
||||
int cmd)
|
||||
{
|
||||
struct snd_gf1_ops *ops = private_data;
|
||||
struct gf1_instrument *ip;
|
||||
struct gf1_xinstrument ix;
|
||||
int err;
|
||||
gfp_t gfp_mask;
|
||||
|
||||
if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
|
||||
return -EINVAL;
|
||||
gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
|
||||
/* copy instrument data */
|
||||
if (len < (long)sizeof(ix))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&ix, instr_data, sizeof(ix)))
|
||||
return -EFAULT;
|
||||
if (ix.stype != GF1_STRU_INSTR)
|
||||
return -EINVAL;
|
||||
instr_data += sizeof(ix);
|
||||
len -= sizeof(ix);
|
||||
ip = (struct gf1_instrument *)KINSTR_DATA(instr);
|
||||
ip->exclusion = le16_to_cpu(ix.exclusion);
|
||||
ip->exclusion_group = le16_to_cpu(ix.exclusion_group);
|
||||
ip->effect1 = ix.effect1;
|
||||
ip->effect1_depth = ix.effect1_depth;
|
||||
ip->effect2 = ix.effect2;
|
||||
ip->effect2_depth = ix.effect2_depth;
|
||||
/* copy layers */
|
||||
while (len > (long)sizeof(__u32)) {
|
||||
__u32 stype;
|
||||
|
||||
if (copy_from_user(&stype, instr_data, sizeof(stype)))
|
||||
return -EFAULT;
|
||||
if (stype != GF1_STRU_WAVE) {
|
||||
snd_seq_gf1_instr_free(ops, ip, atomic);
|
||||
return -EINVAL;
|
||||
}
|
||||
err = snd_seq_gf1_copy_wave_from_stream(ops,
|
||||
ip,
|
||||
&instr_data,
|
||||
&len,
|
||||
atomic);
|
||||
if (err < 0) {
|
||||
snd_seq_gf1_instr_free(ops, ip, atomic);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_seq_gf1_copy_wave_to_stream(struct snd_gf1_ops *ops,
|
||||
struct gf1_instrument *ip,
|
||||
char __user **data,
|
||||
long *len,
|
||||
int atomic)
|
||||
{
|
||||
struct gf1_wave *wp;
|
||||
struct gf1_xwave xp;
|
||||
int err;
|
||||
unsigned int real_size;
|
||||
|
||||
for (wp = ip->wave; wp; wp = wp->next) {
|
||||
if (*len < (long)sizeof(xp))
|
||||
return -ENOMEM;
|
||||
memset(&xp, 0, sizeof(xp));
|
||||
xp.stype = GF1_STRU_WAVE;
|
||||
xp.share_id[0] = cpu_to_le32(wp->share_id[0]);
|
||||
xp.share_id[1] = cpu_to_le32(wp->share_id[1]);
|
||||
xp.share_id[2] = cpu_to_le32(wp->share_id[2]);
|
||||
xp.share_id[3] = cpu_to_le32(wp->share_id[3]);
|
||||
xp.format = cpu_to_le32(wp->format);
|
||||
xp.size = cpu_to_le32(wp->size);
|
||||
xp.start = cpu_to_le32(wp->start);
|
||||
xp.loop_start = cpu_to_le32(wp->loop_start);
|
||||
xp.loop_end = cpu_to_le32(wp->loop_end);
|
||||
xp.loop_repeat = cpu_to_le32(wp->loop_repeat);
|
||||
xp.flags = wp->flags;
|
||||
xp.sample_rate = cpu_to_le32(wp->sample_rate);
|
||||
xp.low_frequency = cpu_to_le32(wp->low_frequency);
|
||||
xp.high_frequency = cpu_to_le32(wp->high_frequency);
|
||||
xp.root_frequency = cpu_to_le32(wp->root_frequency);
|
||||
xp.tune = cpu_to_le16(wp->tune);
|
||||
xp.balance = wp->balance;
|
||||
memcpy(xp.envelope_rate, wp->envelope_rate, 6);
|
||||
memcpy(xp.envelope_offset, wp->envelope_offset, 6);
|
||||
xp.tremolo_sweep = wp->tremolo_sweep;
|
||||
xp.tremolo_rate = wp->tremolo_rate;
|
||||
xp.tremolo_depth = wp->tremolo_depth;
|
||||
xp.vibrato_sweep = wp->vibrato_sweep;
|
||||
xp.vibrato_rate = wp->vibrato_rate;
|
||||
xp.vibrato_depth = wp->vibrato_depth;
|
||||
xp.scale_frequency = cpu_to_le16(wp->scale_frequency);
|
||||
xp.scale_factor = cpu_to_le16(wp->scale_factor);
|
||||
if (copy_to_user(*data, &xp, sizeof(xp)))
|
||||
return -EFAULT;
|
||||
*data += sizeof(xp);
|
||||
*len -= sizeof(xp);
|
||||
real_size = snd_seq_gf1_size(wp->size, wp->format);
|
||||
if (*len < (long)real_size)
|
||||
return -ENOMEM;
|
||||
if (ops->get_sample) {
|
||||
err = ops->get_sample(ops->private_data, wp,
|
||||
*data, real_size, atomic);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
*data += wp->size;
|
||||
*len -= wp->size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_seq_gf1_get(void *private_data, struct snd_seq_kinstr *instr,
|
||||
char __user *instr_data, long len, int atomic,
|
||||
int cmd)
|
||||
{
|
||||
struct snd_gf1_ops *ops = private_data;
|
||||
struct gf1_instrument *ip;
|
||||
struct gf1_xinstrument ix;
|
||||
|
||||
if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
|
||||
return -EINVAL;
|
||||
if (len < (long)sizeof(ix))
|
||||
return -ENOMEM;
|
||||
memset(&ix, 0, sizeof(ix));
|
||||
ip = (struct gf1_instrument *)KINSTR_DATA(instr);
|
||||
ix.stype = GF1_STRU_INSTR;
|
||||
ix.exclusion = cpu_to_le16(ip->exclusion);
|
||||
ix.exclusion_group = cpu_to_le16(ip->exclusion_group);
|
||||
ix.effect1 = cpu_to_le16(ip->effect1);
|
||||
ix.effect1_depth = cpu_to_le16(ip->effect1_depth);
|
||||
ix.effect2 = ip->effect2;
|
||||
ix.effect2_depth = ip->effect2_depth;
|
||||
if (copy_to_user(instr_data, &ix, sizeof(ix)))
|
||||
return -EFAULT;
|
||||
instr_data += sizeof(ix);
|
||||
len -= sizeof(ix);
|
||||
return snd_seq_gf1_copy_wave_to_stream(ops,
|
||||
ip,
|
||||
&instr_data,
|
||||
&len,
|
||||
atomic);
|
||||
}
|
||||
|
||||
static int snd_seq_gf1_get_size(void *private_data, struct snd_seq_kinstr *instr,
|
||||
long *size)
|
||||
{
|
||||
long result;
|
||||
struct gf1_instrument *ip;
|
||||
struct gf1_wave *wp;
|
||||
|
||||
*size = 0;
|
||||
ip = (struct gf1_instrument *)KINSTR_DATA(instr);
|
||||
result = sizeof(struct gf1_xinstrument);
|
||||
for (wp = ip->wave; wp; wp = wp->next) {
|
||||
result += sizeof(struct gf1_xwave);
|
||||
result += wp->size;
|
||||
}
|
||||
*size = result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_seq_gf1_remove(void *private_data,
|
||||
struct snd_seq_kinstr *instr,
|
||||
int atomic)
|
||||
{
|
||||
struct snd_gf1_ops *ops = private_data;
|
||||
struct gf1_instrument *ip;
|
||||
|
||||
ip = (struct gf1_instrument *)KINSTR_DATA(instr);
|
||||
snd_seq_gf1_instr_free(ops, ip, atomic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void snd_seq_gf1_notify(void *private_data,
|
||||
struct snd_seq_kinstr *instr,
|
||||
int what)
|
||||
{
|
||||
struct snd_gf1_ops *ops = private_data;
|
||||
|
||||
if (ops->notify)
|
||||
ops->notify(ops->private_data, instr, what);
|
||||
}
|
||||
|
||||
int snd_seq_gf1_init(struct snd_gf1_ops *ops,
|
||||
void *private_data,
|
||||
struct snd_seq_kinstr_ops *next)
|
||||
{
|
||||
memset(ops, 0, sizeof(*ops));
|
||||
ops->private_data = private_data;
|
||||
ops->kops.private_data = ops;
|
||||
ops->kops.add_len = sizeof(struct gf1_instrument);
|
||||
ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_GUS_PATCH;
|
||||
ops->kops.put = snd_seq_gf1_put;
|
||||
ops->kops.get = snd_seq_gf1_get;
|
||||
ops->kops.get_size = snd_seq_gf1_get_size;
|
||||
ops->kops.remove = snd_seq_gf1_remove;
|
||||
ops->kops.notify = snd_seq_gf1_notify;
|
||||
ops->kops.next = next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Init part
|
||||
*/
|
||||
|
||||
static int __init alsa_ainstr_gf1_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit alsa_ainstr_gf1_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(alsa_ainstr_gf1_init)
|
||||
module_exit(alsa_ainstr_gf1_exit)
|
||||
|
||||
EXPORT_SYMBOL(snd_seq_gf1_init);
|
|
@ -1,623 +0,0 @@
|
|||
/*
|
||||
* IWFFFF - AMD InterWave (tm) - Instrument routines
|
||||
* Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/ainstr_iw.h>
|
||||
#include <sound/initval.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
|
||||
MODULE_DESCRIPTION("Advanced Linux Sound Architecture IWFFFF support.");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static unsigned int snd_seq_iwffff_size(unsigned int size, unsigned int format)
|
||||
{
|
||||
unsigned int result = size;
|
||||
|
||||
if (format & IWFFFF_WAVE_16BIT)
|
||||
result <<= 1;
|
||||
if (format & IWFFFF_WAVE_STEREO)
|
||||
result <<= 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void snd_seq_iwffff_copy_lfo_from_stream(struct iwffff_lfo *fp,
|
||||
struct iwffff_xlfo *fx)
|
||||
{
|
||||
fp->freq = le16_to_cpu(fx->freq);
|
||||
fp->depth = le16_to_cpu(fx->depth);
|
||||
fp->sweep = le16_to_cpu(fx->sweep);
|
||||
fp->shape = fx->shape;
|
||||
fp->delay = fx->delay;
|
||||
}
|
||||
|
||||
static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype,
|
||||
struct iwffff_layer *lp,
|
||||
struct iwffff_env *ep,
|
||||
struct iwffff_xenv *ex,
|
||||
char __user **data,
|
||||
long *len,
|
||||
gfp_t gfp_mask)
|
||||
{
|
||||
__u32 stype;
|
||||
struct iwffff_env_record *rp, *rp_last;
|
||||
struct iwffff_xenv_record rx;
|
||||
struct iwffff_env_point *pp;
|
||||
struct iwffff_xenv_point px;
|
||||
int points_size, idx;
|
||||
|
||||
ep->flags = ex->flags;
|
||||
ep->mode = ex->mode;
|
||||
ep->index = ex->index;
|
||||
rp_last = NULL;
|
||||
while (1) {
|
||||
if (*len < (long)sizeof(__u32))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&stype, *data, sizeof(stype)))
|
||||
return -EFAULT;
|
||||
if (stype == IWFFFF_STRU_WAVE)
|
||||
return 0;
|
||||
if (req_stype != stype) {
|
||||
if (stype == IWFFFF_STRU_ENV_RECP ||
|
||||
stype == IWFFFF_STRU_ENV_RECV)
|
||||
return 0;
|
||||
}
|
||||
if (*len < (long)sizeof(rx))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&rx, *data, sizeof(rx)))
|
||||
return -EFAULT;
|
||||
*data += sizeof(rx);
|
||||
*len -= sizeof(rx);
|
||||
points_size = (le16_to_cpu(rx.nattack) + le16_to_cpu(rx.nrelease)) * 2 * sizeof(__u16);
|
||||
if (points_size > *len)
|
||||
return -EINVAL;
|
||||
rp = kzalloc(sizeof(*rp) + points_size, gfp_mask);
|
||||
if (rp == NULL)
|
||||
return -ENOMEM;
|
||||
rp->nattack = le16_to_cpu(rx.nattack);
|
||||
rp->nrelease = le16_to_cpu(rx.nrelease);
|
||||
rp->sustain_offset = le16_to_cpu(rx.sustain_offset);
|
||||
rp->sustain_rate = le16_to_cpu(rx.sustain_rate);
|
||||
rp->release_rate = le16_to_cpu(rx.release_rate);
|
||||
rp->hirange = rx.hirange;
|
||||
pp = (struct iwffff_env_point *)(rp + 1);
|
||||
for (idx = 0; idx < rp->nattack + rp->nrelease; idx++) {
|
||||
if (copy_from_user(&px, *data, sizeof(px)))
|
||||
return -EFAULT;
|
||||
*data += sizeof(px);
|
||||
*len -= sizeof(px);
|
||||
pp->offset = le16_to_cpu(px.offset);
|
||||
pp->rate = le16_to_cpu(px.rate);
|
||||
}
|
||||
if (ep->record == NULL) {
|
||||
ep->record = rp;
|
||||
} else {
|
||||
rp_last = rp;
|
||||
}
|
||||
rp_last = rp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_seq_iwffff_copy_wave_from_stream(struct snd_iwffff_ops *ops,
|
||||
struct iwffff_layer *lp,
|
||||
char __user **data,
|
||||
long *len,
|
||||
int atomic)
|
||||
{
|
||||
struct iwffff_wave *wp, *prev;
|
||||
struct iwffff_xwave xp;
|
||||
int err;
|
||||
gfp_t gfp_mask;
|
||||
unsigned int real_size;
|
||||
|
||||
gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
|
||||
if (*len < (long)sizeof(xp))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&xp, *data, sizeof(xp)))
|
||||
return -EFAULT;
|
||||
*data += sizeof(xp);
|
||||
*len -= sizeof(xp);
|
||||
wp = kzalloc(sizeof(*wp), gfp_mask);
|
||||
if (wp == NULL)
|
||||
return -ENOMEM;
|
||||
wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
|
||||
wp->share_id[1] = le32_to_cpu(xp.share_id[1]);
|
||||
wp->share_id[2] = le32_to_cpu(xp.share_id[2]);
|
||||
wp->share_id[3] = le32_to_cpu(xp.share_id[3]);
|
||||
wp->format = le32_to_cpu(xp.format);
|
||||
wp->address.memory = le32_to_cpu(xp.offset);
|
||||
wp->size = le32_to_cpu(xp.size);
|
||||
wp->start = le32_to_cpu(xp.start);
|
||||
wp->loop_start = le32_to_cpu(xp.loop_start);
|
||||
wp->loop_end = le32_to_cpu(xp.loop_end);
|
||||
wp->loop_repeat = le16_to_cpu(xp.loop_repeat);
|
||||
wp->sample_ratio = le32_to_cpu(xp.sample_ratio);
|
||||
wp->attenuation = xp.attenuation;
|
||||
wp->low_note = xp.low_note;
|
||||
wp->high_note = xp.high_note;
|
||||
real_size = snd_seq_iwffff_size(wp->size, wp->format);
|
||||
if (!(wp->format & IWFFFF_WAVE_ROM)) {
|
||||
if ((long)real_size > *len) {
|
||||
kfree(wp);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
if (ops->put_sample) {
|
||||
err = ops->put_sample(ops->private_data, wp,
|
||||
*data, real_size, atomic);
|
||||
if (err < 0) {
|
||||
kfree(wp);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if (!(wp->format & IWFFFF_WAVE_ROM)) {
|
||||
*data += real_size;
|
||||
*len -= real_size;
|
||||
}
|
||||
prev = lp->wave;
|
||||
if (prev) {
|
||||
while (prev->next) prev = prev->next;
|
||||
prev->next = wp;
|
||||
} else {
|
||||
lp->wave = wp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void snd_seq_iwffff_env_free(struct snd_iwffff_ops *ops,
|
||||
struct iwffff_env *env,
|
||||
int atomic)
|
||||
{
|
||||
struct iwffff_env_record *rec;
|
||||
|
||||
while ((rec = env->record) != NULL) {
|
||||
env->record = rec->next;
|
||||
kfree(rec);
|
||||
}
|
||||
}
|
||||
|
||||
static void snd_seq_iwffff_wave_free(struct snd_iwffff_ops *ops,
|
||||
struct iwffff_wave *wave,
|
||||
int atomic)
|
||||
{
|
||||
if (ops->remove_sample)
|
||||
ops->remove_sample(ops->private_data, wave, atomic);
|
||||
kfree(wave);
|
||||
}
|
||||
|
||||
static void snd_seq_iwffff_instr_free(struct snd_iwffff_ops *ops,
|
||||
struct iwffff_instrument *ip,
|
||||
int atomic)
|
||||
{
|
||||
struct iwffff_layer *layer;
|
||||
struct iwffff_wave *wave;
|
||||
|
||||
while ((layer = ip->layer) != NULL) {
|
||||
ip->layer = layer->next;
|
||||
snd_seq_iwffff_env_free(ops, &layer->penv, atomic);
|
||||
snd_seq_iwffff_env_free(ops, &layer->venv, atomic);
|
||||
while ((wave = layer->wave) != NULL) {
|
||||
layer->wave = wave->next;
|
||||
snd_seq_iwffff_wave_free(ops, wave, atomic);
|
||||
}
|
||||
kfree(layer);
|
||||
}
|
||||
}
|
||||
|
||||
static int snd_seq_iwffff_put(void *private_data, struct snd_seq_kinstr *instr,
|
||||
char __user *instr_data, long len, int atomic,
|
||||
int cmd)
|
||||
{
|
||||
struct snd_iwffff_ops *ops = private_data;
|
||||
struct iwffff_instrument *ip;
|
||||
struct iwffff_xinstrument ix;
|
||||
struct iwffff_layer *lp, *prev_lp;
|
||||
struct iwffff_xlayer lx;
|
||||
int err;
|
||||
gfp_t gfp_mask;
|
||||
|
||||
if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
|
||||
return -EINVAL;
|
||||
gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
|
||||
/* copy instrument data */
|
||||
if (len < (long)sizeof(ix))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&ix, instr_data, sizeof(ix)))
|
||||
return -EFAULT;
|
||||
if (ix.stype != IWFFFF_STRU_INSTR)
|
||||
return -EINVAL;
|
||||
instr_data += sizeof(ix);
|
||||
len -= sizeof(ix);
|
||||
ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
|
||||
ip->exclusion = le16_to_cpu(ix.exclusion);
|
||||
ip->layer_type = le16_to_cpu(ix.layer_type);
|
||||
ip->exclusion_group = le16_to_cpu(ix.exclusion_group);
|
||||
ip->effect1 = ix.effect1;
|
||||
ip->effect1_depth = ix.effect1_depth;
|
||||
ip->effect2 = ix.effect2;
|
||||
ip->effect2_depth = ix.effect2_depth;
|
||||
/* copy layers */
|
||||
prev_lp = NULL;
|
||||
while (len > 0) {
|
||||
if (len < (long)sizeof(struct iwffff_xlayer)) {
|
||||
snd_seq_iwffff_instr_free(ops, ip, atomic);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (copy_from_user(&lx, instr_data, sizeof(lx)))
|
||||
return -EFAULT;
|
||||
instr_data += sizeof(lx);
|
||||
len -= sizeof(lx);
|
||||
if (lx.stype != IWFFFF_STRU_LAYER) {
|
||||
snd_seq_iwffff_instr_free(ops, ip, atomic);
|
||||
return -EINVAL;
|
||||
}
|
||||
lp = kzalloc(sizeof(*lp), gfp_mask);
|
||||
if (lp == NULL) {
|
||||
snd_seq_iwffff_instr_free(ops, ip, atomic);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (prev_lp) {
|
||||
prev_lp->next = lp;
|
||||
} else {
|
||||
ip->layer = lp;
|
||||
}
|
||||
prev_lp = lp;
|
||||
lp->flags = lx.flags;
|
||||
lp->velocity_mode = lx.velocity_mode;
|
||||
lp->layer_event = lx.layer_event;
|
||||
lp->low_range = lx.low_range;
|
||||
lp->high_range = lx.high_range;
|
||||
lp->pan = lx.pan;
|
||||
lp->pan_freq_scale = lx.pan_freq_scale;
|
||||
lp->attenuation = lx.attenuation;
|
||||
snd_seq_iwffff_copy_lfo_from_stream(&lp->tremolo, &lx.tremolo);
|
||||
snd_seq_iwffff_copy_lfo_from_stream(&lp->vibrato, &lx.vibrato);
|
||||
lp->freq_scale = le16_to_cpu(lx.freq_scale);
|
||||
lp->freq_center = lx.freq_center;
|
||||
err = snd_seq_iwffff_copy_env_from_stream(IWFFFF_STRU_ENV_RECP,
|
||||
lp,
|
||||
&lp->penv, &lx.penv,
|
||||
&instr_data, &len,
|
||||
gfp_mask);
|
||||
if (err < 0) {
|
||||
snd_seq_iwffff_instr_free(ops, ip, atomic);
|
||||
return err;
|
||||
}
|
||||
err = snd_seq_iwffff_copy_env_from_stream(IWFFFF_STRU_ENV_RECV,
|
||||
lp,
|
||||
&lp->venv, &lx.venv,
|
||||
&instr_data, &len,
|
||||
gfp_mask);
|
||||
if (err < 0) {
|
||||
snd_seq_iwffff_instr_free(ops, ip, atomic);
|
||||
return err;
|
||||
}
|
||||
while (len > (long)sizeof(__u32)) {
|
||||
__u32 stype;
|
||||
|
||||
if (copy_from_user(&stype, instr_data, sizeof(stype)))
|
||||
return -EFAULT;
|
||||
if (stype != IWFFFF_STRU_WAVE)
|
||||
break;
|
||||
err = snd_seq_iwffff_copy_wave_from_stream(ops,
|
||||
lp,
|
||||
&instr_data,
|
||||
&len,
|
||||
atomic);
|
||||
if (err < 0) {
|
||||
snd_seq_iwffff_instr_free(ops, ip, atomic);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void snd_seq_iwffff_copy_lfo_to_stream(struct iwffff_xlfo *fx,
|
||||
struct iwffff_lfo *fp)
|
||||
{
|
||||
fx->freq = cpu_to_le16(fp->freq);
|
||||
fx->depth = cpu_to_le16(fp->depth);
|
||||
fx->sweep = cpu_to_le16(fp->sweep);
|
||||
fp->shape = fx->shape;
|
||||
fp->delay = fx->delay;
|
||||
}
|
||||
|
||||
static int snd_seq_iwffff_copy_env_to_stream(__u32 req_stype,
|
||||
struct iwffff_layer *lp,
|
||||
struct iwffff_xenv *ex,
|
||||
struct iwffff_env *ep,
|
||||
char __user **data,
|
||||
long *len)
|
||||
{
|
||||
struct iwffff_env_record *rp;
|
||||
struct iwffff_xenv_record rx;
|
||||
struct iwffff_env_point *pp;
|
||||
struct iwffff_xenv_point px;
|
||||
int points_size, idx;
|
||||
|
||||
ex->flags = ep->flags;
|
||||
ex->mode = ep->mode;
|
||||
ex->index = ep->index;
|
||||
for (rp = ep->record; rp; rp = rp->next) {
|
||||
if (*len < (long)sizeof(rx))
|
||||
return -ENOMEM;
|
||||
memset(&rx, 0, sizeof(rx));
|
||||
rx.stype = req_stype;
|
||||
rx.nattack = cpu_to_le16(rp->nattack);
|
||||
rx.nrelease = cpu_to_le16(rp->nrelease);
|
||||
rx.sustain_offset = cpu_to_le16(rp->sustain_offset);
|
||||
rx.sustain_rate = cpu_to_le16(rp->sustain_rate);
|
||||
rx.release_rate = cpu_to_le16(rp->release_rate);
|
||||
rx.hirange = cpu_to_le16(rp->hirange);
|
||||
if (copy_to_user(*data, &rx, sizeof(rx)))
|
||||
return -EFAULT;
|
||||
*data += sizeof(rx);
|
||||
*len -= sizeof(rx);
|
||||
points_size = (rp->nattack + rp->nrelease) * 2 * sizeof(__u16);
|
||||
if (*len < points_size)
|
||||
return -ENOMEM;
|
||||
pp = (struct iwffff_env_point *)(rp + 1);
|
||||
for (idx = 0; idx < rp->nattack + rp->nrelease; idx++) {
|
||||
px.offset = cpu_to_le16(pp->offset);
|
||||
px.rate = cpu_to_le16(pp->rate);
|
||||
if (copy_to_user(*data, &px, sizeof(px)))
|
||||
return -EFAULT;
|
||||
*data += sizeof(px);
|
||||
*len -= sizeof(px);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_seq_iwffff_copy_wave_to_stream(struct snd_iwffff_ops *ops,
|
||||
struct iwffff_layer *lp,
|
||||
char __user **data,
|
||||
long *len,
|
||||
int atomic)
|
||||
{
|
||||
struct iwffff_wave *wp;
|
||||
struct iwffff_xwave xp;
|
||||
int err;
|
||||
unsigned int real_size;
|
||||
|
||||
for (wp = lp->wave; wp; wp = wp->next) {
|
||||
if (*len < (long)sizeof(xp))
|
||||
return -ENOMEM;
|
||||
memset(&xp, 0, sizeof(xp));
|
||||
xp.stype = IWFFFF_STRU_WAVE;
|
||||
xp.share_id[0] = cpu_to_le32(wp->share_id[0]);
|
||||
xp.share_id[1] = cpu_to_le32(wp->share_id[1]);
|
||||
xp.share_id[2] = cpu_to_le32(wp->share_id[2]);
|
||||
xp.share_id[3] = cpu_to_le32(wp->share_id[3]);
|
||||
xp.format = cpu_to_le32(wp->format);
|
||||
if (wp->format & IWFFFF_WAVE_ROM)
|
||||
xp.offset = cpu_to_le32(wp->address.memory);
|
||||
xp.size = cpu_to_le32(wp->size);
|
||||
xp.start = cpu_to_le32(wp->start);
|
||||
xp.loop_start = cpu_to_le32(wp->loop_start);
|
||||
xp.loop_end = cpu_to_le32(wp->loop_end);
|
||||
xp.loop_repeat = cpu_to_le32(wp->loop_repeat);
|
||||
xp.sample_ratio = cpu_to_le32(wp->sample_ratio);
|
||||
xp.attenuation = wp->attenuation;
|
||||
xp.low_note = wp->low_note;
|
||||
xp.high_note = wp->high_note;
|
||||
if (copy_to_user(*data, &xp, sizeof(xp)))
|
||||
return -EFAULT;
|
||||
*data += sizeof(xp);
|
||||
*len -= sizeof(xp);
|
||||
real_size = snd_seq_iwffff_size(wp->size, wp->format);
|
||||
if (!(wp->format & IWFFFF_WAVE_ROM)) {
|
||||
if (*len < (long)real_size)
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (ops->get_sample) {
|
||||
err = ops->get_sample(ops->private_data, wp,
|
||||
*data, real_size, atomic);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (!(wp->format & IWFFFF_WAVE_ROM)) {
|
||||
*data += real_size;
|
||||
*len -= real_size;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_seq_iwffff_get(void *private_data, struct snd_seq_kinstr *instr,
|
||||
char __user *instr_data, long len, int atomic, int cmd)
|
||||
{
|
||||
struct snd_iwffff_ops *ops = private_data;
|
||||
struct iwffff_instrument *ip;
|
||||
struct iwffff_xinstrument ix;
|
||||
struct iwffff_layer *lp;
|
||||
struct iwffff_xlayer lx;
|
||||
char __user *layer_instr_data;
|
||||
int err;
|
||||
|
||||
if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
|
||||
return -EINVAL;
|
||||
if (len < (long)sizeof(ix))
|
||||
return -ENOMEM;
|
||||
memset(&ix, 0, sizeof(ix));
|
||||
ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
|
||||
ix.stype = IWFFFF_STRU_INSTR;
|
||||
ix.exclusion = cpu_to_le16(ip->exclusion);
|
||||
ix.layer_type = cpu_to_le16(ip->layer_type);
|
||||
ix.exclusion_group = cpu_to_le16(ip->exclusion_group);
|
||||
ix.effect1 = cpu_to_le16(ip->effect1);
|
||||
ix.effect1_depth = cpu_to_le16(ip->effect1_depth);
|
||||
ix.effect2 = ip->effect2;
|
||||
ix.effect2_depth = ip->effect2_depth;
|
||||
if (copy_to_user(instr_data, &ix, sizeof(ix)))
|
||||
return -EFAULT;
|
||||
instr_data += sizeof(ix);
|
||||
len -= sizeof(ix);
|
||||
for (lp = ip->layer; lp; lp = lp->next) {
|
||||
if (len < (long)sizeof(lx))
|
||||
return -ENOMEM;
|
||||
memset(&lx, 0, sizeof(lx));
|
||||
lx.stype = IWFFFF_STRU_LAYER;
|
||||
lx.flags = lp->flags;
|
||||
lx.velocity_mode = lp->velocity_mode;
|
||||
lx.layer_event = lp->layer_event;
|
||||
lx.low_range = lp->low_range;
|
||||
lx.high_range = lp->high_range;
|
||||
lx.pan = lp->pan;
|
||||
lx.pan_freq_scale = lp->pan_freq_scale;
|
||||
lx.attenuation = lp->attenuation;
|
||||
snd_seq_iwffff_copy_lfo_to_stream(&lx.tremolo, &lp->tremolo);
|
||||
snd_seq_iwffff_copy_lfo_to_stream(&lx.vibrato, &lp->vibrato);
|
||||
layer_instr_data = instr_data;
|
||||
instr_data += sizeof(lx);
|
||||
len -= sizeof(lx);
|
||||
err = snd_seq_iwffff_copy_env_to_stream(IWFFFF_STRU_ENV_RECP,
|
||||
lp,
|
||||
&lx.penv, &lp->penv,
|
||||
&instr_data, &len);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = snd_seq_iwffff_copy_env_to_stream(IWFFFF_STRU_ENV_RECV,
|
||||
lp,
|
||||
&lx.venv, &lp->venv,
|
||||
&instr_data, &len);
|
||||
if (err < 0)
|
||||
return err;
|
||||
/* layer structure updating is now finished */
|
||||
if (copy_to_user(layer_instr_data, &lx, sizeof(lx)))
|
||||
return -EFAULT;
|
||||
err = snd_seq_iwffff_copy_wave_to_stream(ops,
|
||||
lp,
|
||||
&instr_data,
|
||||
&len,
|
||||
atomic);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long snd_seq_iwffff_env_size_in_stream(struct iwffff_env *ep)
|
||||
{
|
||||
long result = 0;
|
||||
struct iwffff_env_record *rp;
|
||||
|
||||
for (rp = ep->record; rp; rp = rp->next) {
|
||||
result += sizeof(struct iwffff_xenv_record);
|
||||
result += (rp->nattack + rp->nrelease) * 2 * sizeof(__u16);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long snd_seq_iwffff_wave_size_in_stream(struct iwffff_layer *lp)
|
||||
{
|
||||
long result = 0;
|
||||
struct iwffff_wave *wp;
|
||||
|
||||
for (wp = lp->wave; wp; wp = wp->next) {
|
||||
result += sizeof(struct iwffff_xwave);
|
||||
if (!(wp->format & IWFFFF_WAVE_ROM))
|
||||
result += wp->size;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int snd_seq_iwffff_get_size(void *private_data, struct snd_seq_kinstr *instr,
|
||||
long *size)
|
||||
{
|
||||
long result;
|
||||
struct iwffff_instrument *ip;
|
||||
struct iwffff_layer *lp;
|
||||
|
||||
*size = 0;
|
||||
ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
|
||||
result = sizeof(struct iwffff_xinstrument);
|
||||
for (lp = ip->layer; lp; lp = lp->next) {
|
||||
result += sizeof(struct iwffff_xlayer);
|
||||
result += snd_seq_iwffff_env_size_in_stream(&lp->penv);
|
||||
result += snd_seq_iwffff_env_size_in_stream(&lp->venv);
|
||||
result += snd_seq_iwffff_wave_size_in_stream(lp);
|
||||
}
|
||||
*size = result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_seq_iwffff_remove(void *private_data,
|
||||
struct snd_seq_kinstr *instr,
|
||||
int atomic)
|
||||
{
|
||||
struct snd_iwffff_ops *ops = private_data;
|
||||
struct iwffff_instrument *ip;
|
||||
|
||||
ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
|
||||
snd_seq_iwffff_instr_free(ops, ip, atomic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void snd_seq_iwffff_notify(void *private_data,
|
||||
struct snd_seq_kinstr *instr,
|
||||
int what)
|
||||
{
|
||||
struct snd_iwffff_ops *ops = private_data;
|
||||
|
||||
if (ops->notify)
|
||||
ops->notify(ops->private_data, instr, what);
|
||||
}
|
||||
|
||||
int snd_seq_iwffff_init(struct snd_iwffff_ops *ops,
|
||||
void *private_data,
|
||||
struct snd_seq_kinstr_ops *next)
|
||||
{
|
||||
memset(ops, 0, sizeof(*ops));
|
||||
ops->private_data = private_data;
|
||||
ops->kops.private_data = ops;
|
||||
ops->kops.add_len = sizeof(struct iwffff_instrument);
|
||||
ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_INTERWAVE;
|
||||
ops->kops.put = snd_seq_iwffff_put;
|
||||
ops->kops.get = snd_seq_iwffff_get;
|
||||
ops->kops.get_size = snd_seq_iwffff_get_size;
|
||||
ops->kops.remove = snd_seq_iwffff_remove;
|
||||
ops->kops.notify = snd_seq_iwffff_notify;
|
||||
ops->kops.next = next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Init part
|
||||
*/
|
||||
|
||||
static int __init alsa_ainstr_iw_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit alsa_ainstr_iw_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(alsa_ainstr_iw_init)
|
||||
module_exit(alsa_ainstr_iw_exit)
|
||||
|
||||
EXPORT_SYMBOL(snd_seq_iwffff_init);
|
|
@ -1,215 +0,0 @@
|
|||
/*
|
||||
* Simple (MOD player) - Instrument routines
|
||||
* Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/ainstr_simple.h>
|
||||
#include <sound/initval.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
|
||||
MODULE_DESCRIPTION("Advanced Linux Sound Architecture Simple Instrument support.");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static unsigned int snd_seq_simple_size(unsigned int size, unsigned int format)
|
||||
{
|
||||
unsigned int result = size;
|
||||
|
||||
if (format & SIMPLE_WAVE_16BIT)
|
||||
result <<= 1;
|
||||
if (format & SIMPLE_WAVE_STEREO)
|
||||
result <<= 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void snd_seq_simple_instr_free(struct snd_simple_ops *ops,
|
||||
struct simple_instrument *ip,
|
||||
int atomic)
|
||||
{
|
||||
if (ops->remove_sample)
|
||||
ops->remove_sample(ops->private_data, ip, atomic);
|
||||
}
|
||||
|
||||
static int snd_seq_simple_put(void *private_data, struct snd_seq_kinstr *instr,
|
||||
char __user *instr_data, long len,
|
||||
int atomic, int cmd)
|
||||
{
|
||||
struct snd_simple_ops *ops = private_data;
|
||||
struct simple_instrument *ip;
|
||||
struct simple_xinstrument ix;
|
||||
int err;
|
||||
gfp_t gfp_mask;
|
||||
unsigned int real_size;
|
||||
|
||||
if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
|
||||
return -EINVAL;
|
||||
gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
|
||||
/* copy instrument data */
|
||||
if (len < (long)sizeof(ix))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&ix, instr_data, sizeof(ix)))
|
||||
return -EFAULT;
|
||||
if (ix.stype != SIMPLE_STRU_INSTR)
|
||||
return -EINVAL;
|
||||
instr_data += sizeof(ix);
|
||||
len -= sizeof(ix);
|
||||
ip = (struct simple_instrument *)KINSTR_DATA(instr);
|
||||
ip->share_id[0] = le32_to_cpu(ix.share_id[0]);
|
||||
ip->share_id[1] = le32_to_cpu(ix.share_id[1]);
|
||||
ip->share_id[2] = le32_to_cpu(ix.share_id[2]);
|
||||
ip->share_id[3] = le32_to_cpu(ix.share_id[3]);
|
||||
ip->format = le32_to_cpu(ix.format);
|
||||
ip->size = le32_to_cpu(ix.size);
|
||||
ip->start = le32_to_cpu(ix.start);
|
||||
ip->loop_start = le32_to_cpu(ix.loop_start);
|
||||
ip->loop_end = le32_to_cpu(ix.loop_end);
|
||||
ip->loop_repeat = le16_to_cpu(ix.loop_repeat);
|
||||
ip->effect1 = ix.effect1;
|
||||
ip->effect1_depth = ix.effect1_depth;
|
||||
ip->effect2 = ix.effect2;
|
||||
ip->effect2_depth = ix.effect2_depth;
|
||||
real_size = snd_seq_simple_size(ip->size, ip->format);
|
||||
if (len < (long)real_size)
|
||||
return -EINVAL;
|
||||
if (ops->put_sample) {
|
||||
err = ops->put_sample(ops->private_data, ip,
|
||||
instr_data, real_size, atomic);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_seq_simple_get(void *private_data, struct snd_seq_kinstr *instr,
|
||||
char __user *instr_data, long len,
|
||||
int atomic, int cmd)
|
||||
{
|
||||
struct snd_simple_ops *ops = private_data;
|
||||
struct simple_instrument *ip;
|
||||
struct simple_xinstrument ix;
|
||||
int err;
|
||||
unsigned int real_size;
|
||||
|
||||
if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
|
||||
return -EINVAL;
|
||||
if (len < (long)sizeof(ix))
|
||||
return -ENOMEM;
|
||||
memset(&ix, 0, sizeof(ix));
|
||||
ip = (struct simple_instrument *)KINSTR_DATA(instr);
|
||||
ix.stype = SIMPLE_STRU_INSTR;
|
||||
ix.share_id[0] = cpu_to_le32(ip->share_id[0]);
|
||||
ix.share_id[1] = cpu_to_le32(ip->share_id[1]);
|
||||
ix.share_id[2] = cpu_to_le32(ip->share_id[2]);
|
||||
ix.share_id[3] = cpu_to_le32(ip->share_id[3]);
|
||||
ix.format = cpu_to_le32(ip->format);
|
||||
ix.size = cpu_to_le32(ip->size);
|
||||
ix.start = cpu_to_le32(ip->start);
|
||||
ix.loop_start = cpu_to_le32(ip->loop_start);
|
||||
ix.loop_end = cpu_to_le32(ip->loop_end);
|
||||
ix.loop_repeat = cpu_to_le32(ip->loop_repeat);
|
||||
ix.effect1 = cpu_to_le16(ip->effect1);
|
||||
ix.effect1_depth = cpu_to_le16(ip->effect1_depth);
|
||||
ix.effect2 = ip->effect2;
|
||||
ix.effect2_depth = ip->effect2_depth;
|
||||
if (copy_to_user(instr_data, &ix, sizeof(ix)))
|
||||
return -EFAULT;
|
||||
instr_data += sizeof(ix);
|
||||
len -= sizeof(ix);
|
||||
real_size = snd_seq_simple_size(ip->size, ip->format);
|
||||
if (len < (long)real_size)
|
||||
return -ENOMEM;
|
||||
if (ops->get_sample) {
|
||||
err = ops->get_sample(ops->private_data, ip,
|
||||
instr_data, real_size, atomic);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_seq_simple_get_size(void *private_data, struct snd_seq_kinstr *instr,
|
||||
long *size)
|
||||
{
|
||||
struct simple_instrument *ip;
|
||||
|
||||
ip = (struct simple_instrument *)KINSTR_DATA(instr);
|
||||
*size = sizeof(struct simple_xinstrument) + snd_seq_simple_size(ip->size, ip->format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_seq_simple_remove(void *private_data,
|
||||
struct snd_seq_kinstr *instr,
|
||||
int atomic)
|
||||
{
|
||||
struct snd_simple_ops *ops = private_data;
|
||||
struct simple_instrument *ip;
|
||||
|
||||
ip = (struct simple_instrument *)KINSTR_DATA(instr);
|
||||
snd_seq_simple_instr_free(ops, ip, atomic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void snd_seq_simple_notify(void *private_data,
|
||||
struct snd_seq_kinstr *instr,
|
||||
int what)
|
||||
{
|
||||
struct snd_simple_ops *ops = private_data;
|
||||
|
||||
if (ops->notify)
|
||||
ops->notify(ops->private_data, instr, what);
|
||||
}
|
||||
|
||||
int snd_seq_simple_init(struct snd_simple_ops *ops,
|
||||
void *private_data,
|
||||
struct snd_seq_kinstr_ops *next)
|
||||
{
|
||||
memset(ops, 0, sizeof(*ops));
|
||||
ops->private_data = private_data;
|
||||
ops->kops.private_data = ops;
|
||||
ops->kops.add_len = sizeof(struct simple_instrument);
|
||||
ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_SIMPLE;
|
||||
ops->kops.put = snd_seq_simple_put;
|
||||
ops->kops.get = snd_seq_simple_get;
|
||||
ops->kops.get_size = snd_seq_simple_get_size;
|
||||
ops->kops.remove = snd_seq_simple_remove;
|
||||
ops->kops.notify = snd_seq_simple_notify;
|
||||
ops->kops.next = next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Init part
|
||||
*/
|
||||
|
||||
static int __init alsa_ainstr_simple_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit alsa_ainstr_simple_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(alsa_ainstr_simple_init)
|
||||
module_exit(alsa_ainstr_simple_exit)
|
||||
|
||||
EXPORT_SYMBOL(snd_seq_simple_init);
|
|
@ -20,7 +20,6 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/mutex.h>
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#ifndef __SEQ_OSS_DEVICE_H
|
||||
#define __SEQ_OSS_DEVICE_H
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <sound/core.h>
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
|
@ -130,8 +129,6 @@ static struct snd_seq_client *clientptr(int clientid)
|
|||
return clienttab[clientid];
|
||||
}
|
||||
|
||||
extern int seq_client_load[];
|
||||
|
||||
struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -966,8 +963,7 @@ static int check_event_type_and_length(struct snd_seq_event *ev)
|
|||
return -EINVAL;
|
||||
break;
|
||||
case SNDRV_SEQ_EVENT_LENGTH_VARUSR:
|
||||
if (! snd_seq_ev_is_instr_type(ev) ||
|
||||
! snd_seq_ev_is_direct(ev))
|
||||
if (! snd_seq_ev_is_direct(ev))
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -98,4 +98,6 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table
|
|||
int snd_seq_client_notify_subscription(int client, int port,
|
||||
struct snd_seq_port_subscribe *info, int evtype);
|
||||
|
||||
extern int seq_client_load[15];
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/info.h>
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include <linux/slab.h>
|
||||
#include "seq_fifo.h"
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <sound/core.h>
|
||||
|
||||
|
|
|
@ -1,655 +0,0 @@
|
|||
/*
|
||||
* Generic Instrument routines for ALSA sequencer
|
||||
* Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/core.h>
|
||||
#include "seq_clientmgr.h"
|
||||
#include <sound/seq_instr.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
|
||||
MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer instrument library.");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
static void snd_instr_lock_ops(struct snd_seq_kinstr_list *list)
|
||||
{
|
||||
if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) {
|
||||
spin_lock_irqsave(&list->ops_lock, list->ops_flags);
|
||||
} else {
|
||||
mutex_lock(&list->ops_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void snd_instr_unlock_ops(struct snd_seq_kinstr_list *list)
|
||||
{
|
||||
if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) {
|
||||
spin_unlock_irqrestore(&list->ops_lock, list->ops_flags);
|
||||
} else {
|
||||
mutex_unlock(&list->ops_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static struct snd_seq_kinstr *snd_seq_instr_new(int add_len, int atomic)
|
||||
{
|
||||
struct snd_seq_kinstr *instr;
|
||||
|
||||
instr = kzalloc(sizeof(struct snd_seq_kinstr) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
|
||||
if (instr == NULL)
|
||||
return NULL;
|
||||
instr->add_len = add_len;
|
||||
return instr;
|
||||
}
|
||||
|
||||
static int snd_seq_instr_free(struct snd_seq_kinstr *instr, int atomic)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (instr == NULL)
|
||||
return -EINVAL;
|
||||
if (instr->ops && instr->ops->remove)
|
||||
result = instr->ops->remove(instr->ops->private_data, instr, 1);
|
||||
if (!result)
|
||||
kfree(instr);
|
||||
return result;
|
||||
}
|
||||
|
||||
struct snd_seq_kinstr_list *snd_seq_instr_list_new(void)
|
||||
{
|
||||
struct snd_seq_kinstr_list *list;
|
||||
|
||||
list = kzalloc(sizeof(struct snd_seq_kinstr_list), GFP_KERNEL);
|
||||
if (list == NULL)
|
||||
return NULL;
|
||||
spin_lock_init(&list->lock);
|
||||
spin_lock_init(&list->ops_lock);
|
||||
mutex_init(&list->ops_mutex);
|
||||
list->owner = -1;
|
||||
return list;
|
||||
}
|
||||
|
||||
void snd_seq_instr_list_free(struct snd_seq_kinstr_list **list_ptr)
|
||||
{
|
||||
struct snd_seq_kinstr_list *list;
|
||||
struct snd_seq_kinstr *instr;
|
||||
struct snd_seq_kcluster *cluster;
|
||||
int idx;
|
||||
unsigned long flags;
|
||||
|
||||
if (list_ptr == NULL)
|
||||
return;
|
||||
list = *list_ptr;
|
||||
*list_ptr = NULL;
|
||||
if (list == NULL)
|
||||
return;
|
||||
|
||||
for (idx = 0; idx < SNDRV_SEQ_INSTR_HASH_SIZE; idx++) {
|
||||
while ((instr = list->hash[idx]) != NULL) {
|
||||
list->hash[idx] = instr->next;
|
||||
list->count--;
|
||||
spin_lock_irqsave(&list->lock, flags);
|
||||
while (instr->use) {
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
schedule_timeout_uninterruptible(1);
|
||||
spin_lock_irqsave(&list->lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
if (snd_seq_instr_free(instr, 0)<0)
|
||||
snd_printk(KERN_WARNING "instrument free problem\n");
|
||||
}
|
||||
while ((cluster = list->chash[idx]) != NULL) {
|
||||
list->chash[idx] = cluster->next;
|
||||
list->ccount--;
|
||||
kfree(cluster);
|
||||
}
|
||||
}
|
||||
kfree(list);
|
||||
}
|
||||
|
||||
static int instr_free_compare(struct snd_seq_kinstr *instr,
|
||||
struct snd_seq_instr_header *ifree,
|
||||
unsigned int client)
|
||||
{
|
||||
switch (ifree->cmd) {
|
||||
case SNDRV_SEQ_INSTR_FREE_CMD_ALL:
|
||||
/* all, except private for other clients */
|
||||
if ((instr->instr.std & 0xff000000) == 0)
|
||||
return 0;
|
||||
if (((instr->instr.std >> 24) & 0xff) == client)
|
||||
return 0;
|
||||
return 1;
|
||||
case SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE:
|
||||
/* all my private instruments */
|
||||
if ((instr->instr.std & 0xff000000) == 0)
|
||||
return 1;
|
||||
if (((instr->instr.std >> 24) & 0xff) == client)
|
||||
return 0;
|
||||
return 1;
|
||||
case SNDRV_SEQ_INSTR_FREE_CMD_CLUSTER:
|
||||
/* all my private instruments */
|
||||
if ((instr->instr.std & 0xff000000) == 0) {
|
||||
if (instr->instr.cluster == ifree->id.cluster)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
if (((instr->instr.std >> 24) & 0xff) == client) {
|
||||
if (instr->instr.cluster == ifree->id.cluster)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int snd_seq_instr_list_free_cond(struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_instr_header *ifree,
|
||||
int client,
|
||||
int atomic)
|
||||
{
|
||||
struct snd_seq_kinstr *instr, *prev, *next, *flist;
|
||||
int idx;
|
||||
unsigned long flags;
|
||||
|
||||
snd_instr_lock_ops(list);
|
||||
for (idx = 0; idx < SNDRV_SEQ_INSTR_HASH_SIZE; idx++) {
|
||||
spin_lock_irqsave(&list->lock, flags);
|
||||
instr = list->hash[idx];
|
||||
prev = flist = NULL;
|
||||
while (instr) {
|
||||
while (instr && instr_free_compare(instr, ifree, (unsigned int)client)) {
|
||||
prev = instr;
|
||||
instr = instr->next;
|
||||
}
|
||||
if (instr == NULL)
|
||||
continue;
|
||||
if (instr->ops && instr->ops->notify)
|
||||
instr->ops->notify(instr->ops->private_data, instr, SNDRV_SEQ_INSTR_NOTIFY_REMOVE);
|
||||
next = instr->next;
|
||||
if (prev == NULL) {
|
||||
list->hash[idx] = next;
|
||||
} else {
|
||||
prev->next = next;
|
||||
}
|
||||
list->count--;
|
||||
instr->next = flist;
|
||||
flist = instr;
|
||||
instr = next;
|
||||
}
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
while (flist) {
|
||||
instr = flist;
|
||||
flist = instr->next;
|
||||
while (instr->use) {
|
||||
schedule_timeout_uninterruptible(1);
|
||||
barrier();
|
||||
}
|
||||
if (snd_seq_instr_free(instr, atomic)<0)
|
||||
snd_printk(KERN_WARNING "instrument free problem\n");
|
||||
instr = next;
|
||||
}
|
||||
}
|
||||
snd_instr_unlock_ops(list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compute_hash_instr_key(struct snd_seq_instr *instr)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = instr->bank | (instr->prg << 16);
|
||||
result += result >> 24;
|
||||
result += result >> 16;
|
||||
result += result >> 8;
|
||||
return result & (SNDRV_SEQ_INSTR_HASH_SIZE-1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int compute_hash_cluster_key(snd_seq_instr_cluster_t cluster)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = cluster;
|
||||
result += result >> 24;
|
||||
result += result >> 16;
|
||||
result += result >> 8;
|
||||
return result & (SNDRV_SEQ_INSTR_HASH_SIZE-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int compare_instr(struct snd_seq_instr *i1, struct snd_seq_instr *i2, int exact)
|
||||
{
|
||||
if (exact) {
|
||||
if (i1->cluster != i2->cluster ||
|
||||
i1->bank != i2->bank ||
|
||||
i1->prg != i2->prg)
|
||||
return 1;
|
||||
if ((i1->std & 0xff000000) != (i2->std & 0xff000000))
|
||||
return 1;
|
||||
if (!(i1->std & i2->std))
|
||||
return 1;
|
||||
return 0;
|
||||
} else {
|
||||
unsigned int client_check;
|
||||
|
||||
if (i2->cluster && i1->cluster != i2->cluster)
|
||||
return 1;
|
||||
client_check = i2->std & 0xff000000;
|
||||
if (client_check) {
|
||||
if ((i1->std & 0xff000000) != client_check)
|
||||
return 1;
|
||||
} else {
|
||||
if ((i1->std & i2->std) != i2->std)
|
||||
return 1;
|
||||
}
|
||||
return i1->bank != i2->bank || i1->prg != i2->prg;
|
||||
}
|
||||
}
|
||||
|
||||
struct snd_seq_kinstr *snd_seq_instr_find(struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_instr *instr,
|
||||
int exact,
|
||||
int follow_alias)
|
||||
{
|
||||
unsigned long flags;
|
||||
int depth = 0;
|
||||
struct snd_seq_kinstr *result;
|
||||
|
||||
if (list == NULL || instr == NULL)
|
||||
return NULL;
|
||||
spin_lock_irqsave(&list->lock, flags);
|
||||
__again:
|
||||
result = list->hash[compute_hash_instr_key(instr)];
|
||||
while (result) {
|
||||
if (!compare_instr(&result->instr, instr, exact)) {
|
||||
if (follow_alias && (result->type == SNDRV_SEQ_INSTR_ATYPE_ALIAS)) {
|
||||
instr = (struct snd_seq_instr *)KINSTR_DATA(result);
|
||||
if (++depth > 10)
|
||||
goto __not_found;
|
||||
goto __again;
|
||||
}
|
||||
result->use++;
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
return result;
|
||||
}
|
||||
result = result->next;
|
||||
}
|
||||
__not_found:
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void snd_seq_instr_free_use(struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_kinstr *instr)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (list == NULL || instr == NULL)
|
||||
return;
|
||||
spin_lock_irqsave(&list->lock, flags);
|
||||
if (instr->use <= 0) {
|
||||
snd_printk(KERN_ERR "free_use: fatal!!! use = %i, name = '%s'\n", instr->use, instr->name);
|
||||
} else {
|
||||
instr->use--;
|
||||
}
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
}
|
||||
|
||||
static struct snd_seq_kinstr_ops *instr_ops(struct snd_seq_kinstr_ops *ops,
|
||||
char *instr_type)
|
||||
{
|
||||
while (ops) {
|
||||
if (!strcmp(ops->instr_type, instr_type))
|
||||
return ops;
|
||||
ops = ops->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int instr_result(struct snd_seq_event *ev,
|
||||
int type, int result,
|
||||
int atomic)
|
||||
{
|
||||
struct snd_seq_event sev;
|
||||
|
||||
memset(&sev, 0, sizeof(sev));
|
||||
sev.type = SNDRV_SEQ_EVENT_RESULT;
|
||||
sev.flags = SNDRV_SEQ_TIME_STAMP_REAL | SNDRV_SEQ_EVENT_LENGTH_FIXED |
|
||||
SNDRV_SEQ_PRIORITY_NORMAL;
|
||||
sev.source = ev->dest;
|
||||
sev.dest = ev->source;
|
||||
sev.data.result.event = type;
|
||||
sev.data.result.result = result;
|
||||
#if 0
|
||||
printk("instr result - type = %i, result = %i, queue = %i, source.client:port = %i:%i, dest.client:port = %i:%i\n",
|
||||
type, result,
|
||||
sev.queue,
|
||||
sev.source.client, sev.source.port,
|
||||
sev.dest.client, sev.dest.port);
|
||||
#endif
|
||||
return snd_seq_kernel_client_dispatch(sev.source.client, &sev, atomic, 0);
|
||||
}
|
||||
|
||||
static int instr_begin(struct snd_seq_kinstr_ops *ops,
|
||||
struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_event *ev,
|
||||
int atomic, int hop)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&list->lock, flags);
|
||||
if (list->owner >= 0 && list->owner != ev->source.client) {
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_BEGIN, -EBUSY, atomic);
|
||||
}
|
||||
list->owner = ev->source.client;
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_BEGIN, 0, atomic);
|
||||
}
|
||||
|
||||
static int instr_end(struct snd_seq_kinstr_ops *ops,
|
||||
struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_event *ev,
|
||||
int atomic, int hop)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/* TODO: timeout handling */
|
||||
spin_lock_irqsave(&list->lock, flags);
|
||||
if (list->owner == ev->source.client) {
|
||||
list->owner = -1;
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_END, 0, atomic);
|
||||
}
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_END, -EINVAL, atomic);
|
||||
}
|
||||
|
||||
static int instr_info(struct snd_seq_kinstr_ops *ops,
|
||||
struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_event *ev,
|
||||
int atomic, int hop)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static int instr_format_info(struct snd_seq_kinstr_ops *ops,
|
||||
struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_event *ev,
|
||||
int atomic, int hop)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static int instr_reset(struct snd_seq_kinstr_ops *ops,
|
||||
struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_event *ev,
|
||||
int atomic, int hop)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static int instr_status(struct snd_seq_kinstr_ops *ops,
|
||||
struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_event *ev,
|
||||
int atomic, int hop)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static int instr_put(struct snd_seq_kinstr_ops *ops,
|
||||
struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_event *ev,
|
||||
int atomic, int hop)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct snd_seq_instr_header put;
|
||||
struct snd_seq_kinstr *instr;
|
||||
int result = -EINVAL, len, key;
|
||||
|
||||
if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARUSR)
|
||||
goto __return;
|
||||
|
||||
if (ev->data.ext.len < sizeof(struct snd_seq_instr_header))
|
||||
goto __return;
|
||||
if (copy_from_user(&put, (void __user *)ev->data.ext.ptr,
|
||||
sizeof(struct snd_seq_instr_header))) {
|
||||
result = -EFAULT;
|
||||
goto __return;
|
||||
}
|
||||
snd_instr_lock_ops(list);
|
||||
if (put.id.instr.std & 0xff000000) { /* private instrument */
|
||||
put.id.instr.std &= 0x00ffffff;
|
||||
put.id.instr.std |= (unsigned int)ev->source.client << 24;
|
||||
}
|
||||
if ((instr = snd_seq_instr_find(list, &put.id.instr, 1, 0))) {
|
||||
snd_seq_instr_free_use(list, instr);
|
||||
snd_instr_unlock_ops(list);
|
||||
result = -EBUSY;
|
||||
goto __return;
|
||||
}
|
||||
ops = instr_ops(ops, put.data.data.format);
|
||||
if (ops == NULL) {
|
||||
snd_instr_unlock_ops(list);
|
||||
goto __return;
|
||||
}
|
||||
len = ops->add_len;
|
||||
if (put.data.type == SNDRV_SEQ_INSTR_ATYPE_ALIAS)
|
||||
len = sizeof(struct snd_seq_instr);
|
||||
instr = snd_seq_instr_new(len, atomic);
|
||||
if (instr == NULL) {
|
||||
snd_instr_unlock_ops(list);
|
||||
result = -ENOMEM;
|
||||
goto __return;
|
||||
}
|
||||
instr->ops = ops;
|
||||
instr->instr = put.id.instr;
|
||||
strlcpy(instr->name, put.data.name, sizeof(instr->name));
|
||||
instr->type = put.data.type;
|
||||
if (instr->type == SNDRV_SEQ_INSTR_ATYPE_DATA) {
|
||||
result = ops->put(ops->private_data,
|
||||
instr,
|
||||
(void __user *)ev->data.ext.ptr + sizeof(struct snd_seq_instr_header),
|
||||
ev->data.ext.len - sizeof(struct snd_seq_instr_header),
|
||||
atomic,
|
||||
put.cmd);
|
||||
if (result < 0) {
|
||||
snd_seq_instr_free(instr, atomic);
|
||||
snd_instr_unlock_ops(list);
|
||||
goto __return;
|
||||
}
|
||||
}
|
||||
key = compute_hash_instr_key(&instr->instr);
|
||||
spin_lock_irqsave(&list->lock, flags);
|
||||
instr->next = list->hash[key];
|
||||
list->hash[key] = instr;
|
||||
list->count++;
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
snd_instr_unlock_ops(list);
|
||||
result = 0;
|
||||
__return:
|
||||
instr_result(ev, SNDRV_SEQ_EVENT_INSTR_PUT, result, atomic);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int instr_get(struct snd_seq_kinstr_ops *ops,
|
||||
struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_event *ev,
|
||||
int atomic, int hop)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static int instr_free(struct snd_seq_kinstr_ops *ops,
|
||||
struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_event *ev,
|
||||
int atomic, int hop)
|
||||
{
|
||||
struct snd_seq_instr_header ifree;
|
||||
struct snd_seq_kinstr *instr, *prev;
|
||||
int result = -EINVAL;
|
||||
unsigned long flags;
|
||||
unsigned int hash;
|
||||
|
||||
if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARUSR)
|
||||
goto __return;
|
||||
|
||||
if (ev->data.ext.len < sizeof(struct snd_seq_instr_header))
|
||||
goto __return;
|
||||
if (copy_from_user(&ifree, (void __user *)ev->data.ext.ptr,
|
||||
sizeof(struct snd_seq_instr_header))) {
|
||||
result = -EFAULT;
|
||||
goto __return;
|
||||
}
|
||||
if (ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_ALL ||
|
||||
ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE ||
|
||||
ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_CLUSTER) {
|
||||
result = snd_seq_instr_list_free_cond(list, &ifree, ev->dest.client, atomic);
|
||||
goto __return;
|
||||
}
|
||||
if (ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_SINGLE) {
|
||||
if (ifree.id.instr.std & 0xff000000) {
|
||||
ifree.id.instr.std &= 0x00ffffff;
|
||||
ifree.id.instr.std |= (unsigned int)ev->source.client << 24;
|
||||
}
|
||||
hash = compute_hash_instr_key(&ifree.id.instr);
|
||||
snd_instr_lock_ops(list);
|
||||
spin_lock_irqsave(&list->lock, flags);
|
||||
instr = list->hash[hash];
|
||||
prev = NULL;
|
||||
while (instr) {
|
||||
if (!compare_instr(&instr->instr, &ifree.id.instr, 1))
|
||||
goto __free_single;
|
||||
prev = instr;
|
||||
instr = instr->next;
|
||||
}
|
||||
result = -ENOENT;
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
snd_instr_unlock_ops(list);
|
||||
goto __return;
|
||||
|
||||
__free_single:
|
||||
if (prev) {
|
||||
prev->next = instr->next;
|
||||
} else {
|
||||
list->hash[hash] = instr->next;
|
||||
}
|
||||
if (instr->ops && instr->ops->notify)
|
||||
instr->ops->notify(instr->ops->private_data, instr,
|
||||
SNDRV_SEQ_INSTR_NOTIFY_REMOVE);
|
||||
while (instr->use) {
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
schedule_timeout_uninterruptible(1);
|
||||
spin_lock_irqsave(&list->lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
result = snd_seq_instr_free(instr, atomic);
|
||||
snd_instr_unlock_ops(list);
|
||||
goto __return;
|
||||
}
|
||||
|
||||
__return:
|
||||
instr_result(ev, SNDRV_SEQ_EVENT_INSTR_FREE, result, atomic);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int instr_list(struct snd_seq_kinstr_ops *ops,
|
||||
struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_event *ev,
|
||||
int atomic, int hop)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static int instr_cluster(struct snd_seq_kinstr_ops *ops,
|
||||
struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_event *ev,
|
||||
int atomic, int hop)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
int snd_seq_instr_event(struct snd_seq_kinstr_ops *ops,
|
||||
struct snd_seq_kinstr_list *list,
|
||||
struct snd_seq_event *ev,
|
||||
int client,
|
||||
int atomic,
|
||||
int hop)
|
||||
{
|
||||
int direct = 0;
|
||||
|
||||
snd_assert(ops != NULL && list != NULL && ev != NULL, return -EINVAL);
|
||||
if (snd_seq_ev_is_direct(ev)) {
|
||||
direct = 1;
|
||||
switch (ev->type) {
|
||||
case SNDRV_SEQ_EVENT_INSTR_BEGIN:
|
||||
return instr_begin(ops, list, ev, atomic, hop);
|
||||
case SNDRV_SEQ_EVENT_INSTR_END:
|
||||
return instr_end(ops, list, ev, atomic, hop);
|
||||
}
|
||||
}
|
||||
if ((list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT) && !direct)
|
||||
return -EINVAL;
|
||||
switch (ev->type) {
|
||||
case SNDRV_SEQ_EVENT_INSTR_INFO:
|
||||
return instr_info(ops, list, ev, atomic, hop);
|
||||
case SNDRV_SEQ_EVENT_INSTR_FINFO:
|
||||
return instr_format_info(ops, list, ev, atomic, hop);
|
||||
case SNDRV_SEQ_EVENT_INSTR_RESET:
|
||||
return instr_reset(ops, list, ev, atomic, hop);
|
||||
case SNDRV_SEQ_EVENT_INSTR_STATUS:
|
||||
return instr_status(ops, list, ev, atomic, hop);
|
||||
case SNDRV_SEQ_EVENT_INSTR_PUT:
|
||||
return instr_put(ops, list, ev, atomic, hop);
|
||||
case SNDRV_SEQ_EVENT_INSTR_GET:
|
||||
return instr_get(ops, list, ev, atomic, hop);
|
||||
case SNDRV_SEQ_EVENT_INSTR_FREE:
|
||||
return instr_free(ops, list, ev, atomic, hop);
|
||||
case SNDRV_SEQ_EVENT_INSTR_LIST:
|
||||
return instr_list(ops, list, ev, atomic, hop);
|
||||
case SNDRV_SEQ_EVENT_INSTR_CLUSTER:
|
||||
return instr_cluster(ops, list, ev, atomic, hop);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Init part
|
||||
*/
|
||||
|
||||
static int __init alsa_seq_instr_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit alsa_seq_instr_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(alsa_seq_instr_init)
|
||||
module_exit(alsa_seq_instr_exit)
|
||||
|
||||
EXPORT_SYMBOL(snd_seq_instr_list_new);
|
||||
EXPORT_SYMBOL(snd_seq_instr_list_free);
|
||||
EXPORT_SYMBOL(snd_seq_instr_list_free_cond);
|
||||
EXPORT_SYMBOL(snd_seq_instr_find);
|
||||
EXPORT_SYMBOL(snd_seq_instr_free_use);
|
||||
EXPORT_SYMBOL(snd_seq_instr_event);
|
|
@ -19,7 +19,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <sound/core.h>
|
||||
#include "seq_lock.h"
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue