提交 7f46e6ca 编写于 作者: L Linus Torvalds

Merge branch 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa

* 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa: (102 commits)
  [ALSA] version 1.0.14
  [ALSA] remove duplicate Logitech Quickcam USB ID in usbquirks.h
  [ALSA] hda-codec - Fix input with STAC92xx
  [ALSA] hda-intel: support for iMac 24'' released on 09/2006
  [ALSA] hda-codec - Add quirk for Asus P5LD2
  [ALSA] snd-ca0106: Add support for X-Fi Extreme Audio.
  [ALSA] snd-emu10k1:Enable E-Mu 1616m notebook firmware loading.
  [ALSA] snd-emu10k1: Initial support for E-Mu 1616 and 1616m.
  [ALSA] cs46xx - Fix PM resume
  [ALSA] hda: Enable SPDIF in/out on some stac9205 boards
  [ALSA] timer: check for incorrect device state in non-debug compiles, too
  [ALSA] snd-aoa-codec-onyx: fix typo
  [ALSA] hda-codec - Add quirks for HP dx2200/dx2250
  [ALSA] hda-codec - Rename HP model-specific quirks
  [ALSA] hda-codec - Add quirk for HP Samba
  [ALSA] hda-codec - Add LG LW20 line-in capture source
  [ALSA] usb-audio - Fix AC3 with M-Audio Audiophile USB
  [ALSA] hda: stac9202 mixer fix
  [ALSA] Make s3c24xx_i2s_set_clkdiv() change the correct bits
  [ALSA] hda-codec - Add LG LW20 si3054 modem id
  ...
...@@ -2212,13 +2212,13 @@ S: 2300 Copenhagen S ...@@ -2212,13 +2212,13 @@ S: 2300 Copenhagen S
S: Denmark S: Denmark
N: Claudio S. Matsuoka N: Claudio S. Matsuoka
E: claudio@conectiva.com E: cmatsuoka@gmail.com
E: claudio@helllabs.org E: claudio@mandriva.com
W: http://helllabs.org/~claudio W: http://helllabs.org/~claudio
D: V4L, OV511 driver hacks D: V4L, OV511 and HDA-codec hacks
S: Conectiva S.A. S: Conectiva S.A.
S: R. Tocantins 89 S: Souza Naves 1250
S: 80050-430 Curitiba PR S: 80050-040 Curitiba PR
S: Brazil S: Brazil
N: Heinz Mauelshagen N: Heinz Mauelshagen
......
...@@ -467,7 +467,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -467,7 +467,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
above explicitly. above explicitly.
The power-management is supported. The power-management is supported.
Module snd-cs5530
_________________
Module for Cyrix/NatSemi Geode 5530 chip.
Module snd-cs5535audio Module snd-cs5535audio
---------------------- ----------------------
...@@ -759,6 +764,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -759,6 +764,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
model - force the model name model - force the model name
position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size) 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_cmd - Use single immediate commands to communicate with single_cmd - Use single immediate commands to communicate with
codecs (for debugging only) codecs (for debugging only)
enable_msi - Enable Message Signaled Interrupt (MSI) (default = off) enable_msi - Enable Message Signaled Interrupt (MSI) (default = off)
...@@ -803,6 +809,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -803,6 +809,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
hp-3013 HP machines (3013-variant) hp-3013 HP machines (3013-variant)
fujitsu Fujitsu S7020 fujitsu Fujitsu S7020
acer Acer TravelMate acer Acer TravelMate
will Will laptops (PB V7900)
replacer Replacer 672V
basic fixed pin assignment (old default model) basic fixed pin assignment (old default model)
auto auto-config reading BIOS (default) auto auto-config reading BIOS (default)
...@@ -811,16 +819,31 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -811,16 +819,31 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
hp-bpc HP xw4400/6400/8400/9400 laptops hp-bpc HP xw4400/6400/8400/9400 laptops
hp-bpc-d7000 HP BPC D7000 hp-bpc-d7000 HP BPC D7000
benq Benq ED8 benq Benq ED8
benq-t31 Benq T31
hippo Hippo (ATI) with jack detection, Sony UX-90s hippo Hippo (ATI) with jack detection, Sony UX-90s
hippo_1 Hippo (Benq) with jack detection hippo_1 Hippo (Benq) with jack detection
sony-assamd Sony ASSAMD
basic fixed pin assignment w/o SPDIF basic fixed pin assignment w/o SPDIF
auto auto-config reading BIOS (default) auto auto-config reading BIOS (default)
ALC268
3stack 3-stack model
auto auto-config reading BIOS (default)
ALC662
3stack-dig 3-stack (2-channel) with SPDIF
3stack-6ch 3-stack (6-channel)
3stack-6ch-dig 3-stack (6-channel) with SPDIF
6stack-dig 6-stack with SPDIF
lenovo-101e Lenovo laptop
auto auto-config reading BIOS (default)
ALC882/885 ALC882/885
3stack-dig 3-jack with SPDIF I/O 3stack-dig 3-jack with SPDIF I/O
6stack-dig 6-jack digital with SPDIF I/O 6stack-dig 6-jack digital with SPDIF I/O
arima Arima W820Di1 arima Arima W820Di1
macpro MacPro support macpro MacPro support
imac24 iMac 24'' with jack detection
w2jc ASUS W2JC w2jc ASUS W2JC
auto auto-config reading BIOS (default) auto auto-config reading BIOS (default)
...@@ -832,9 +855,15 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -832,9 +855,15 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
6stack-dig-demo 6-jack digital for Intel demo board 6stack-dig-demo 6-jack digital for Intel demo board
acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc) acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
medion Medion Laptops medion Medion Laptops
medion-md2 Medion MD2
targa-dig Targa/MSI targa-dig Targa/MSI
targa-2ch-dig Targs/MSI with 2-channel targa-2ch-dig Targs/MSI with 2-channel
laptop-eapd 3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE) laptop-eapd 3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE)
lenovo-101e Lenovo 101E
lenovo-nb0763 Lenovo NB0763
lenovo-ms7195-dig Lenovo MS7195
6stack-hp HP machines with 6stack (Nettle boards)
3stack-hp HP machines with 3stack (Lucknow, Samba boards)
auto auto-config reading BIOS (default) auto auto-config reading BIOS (default)
ALC861/660 ALC861/660
...@@ -853,7 +882,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -853,7 +882,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
3stack-dig 3-jack with SPDIF OUT 3stack-dig 3-jack with SPDIF OUT
6stack-dig 6-jack with SPDIF OUT 6stack-dig 6-jack with SPDIF OUT
3stack-660 3-jack (for ALC660VD) 3stack-660 3-jack (for ALC660VD)
3stack-660-digout 3-jack with SPDIF OUT (for ALC660VD)
lenovo Lenovo 3000 C200 lenovo Lenovo 3000 C200
dallas Dallas laptops
auto auto-config reading BIOS (default) auto auto-config reading BIOS (default)
CMI9880 CMI9880
...@@ -864,12 +895,26 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -864,12 +895,26 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
allout 5-jack in back, 2-jack in front, SPDIF out allout 5-jack in back, 2-jack in front, SPDIF out
auto auto-config reading BIOS (default) auto auto-config reading BIOS (default)
AD1882
3stack 3-stack mode (default)
6stack 6-stack mode
AD1884
N/A
AD1981 AD1981
basic 3-jack (default) basic 3-jack (default)
hp HP nx6320 hp HP nx6320
thinkpad Lenovo Thinkpad T60/X60/Z60 thinkpad Lenovo Thinkpad T60/X60/Z60
toshiba Toshiba U205 toshiba Toshiba U205
AD1983
N/A
AD1984
basic default configuration
thinkpad Lenovo Thinkpad T61/X61
AD1986A AD1986A
6stack 6-jack, separate surrounds (default) 6stack 6-jack, separate surrounds (default)
3stack 3-stack, shared surrounds 3stack 3-stack, shared surrounds
...@@ -907,11 +952,18 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -907,11 +952,18 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
ref Reference board ref Reference board
3stack D945 3stack 3stack D945 3stack
5stack D945 5stack + SPDIF 5stack D945 5stack + SPDIF
macmini Intel Mac Mini dell Dell XPS M1210
macbook Intel Mac Book intel-mac-v1 Intel Mac Type 1
macbook-pro-v1 Intel Mac Book Pro 1st generation intel-mac-v2 Intel Mac Type 2
macbook-pro Intel Mac Book Pro 2nd generation intel-mac-v3 Intel Mac Type 3
imac-intel Intel iMac intel-mac-v4 Intel Mac Type 4
intel-mac-v5 Intel Mac Type 5
macmini Intel Mac Mini (equivalent with type 3)
macbook Intel Mac Book (eq. type 5)
macbook-pro-v1 Intel Mac Book Pro 1st generation (eq. type 3)
macbook-pro Intel Mac Book Pro 2nd generation (eq. type 3)
imac-intel Intel iMac (eq. type 2)
imac-intel-20 Intel iMac (newer version) (eq. type 3)
STAC9202/9250/9251 STAC9202/9250/9251
ref Reference board, base config ref Reference board, base config
...@@ -956,6 +1008,17 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -956,6 +1008,17 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
from the irq. Remember this is a last resort, and should be from the irq. Remember this is a last resort, and should be
avoided as much as possible... avoided as much as possible...
MORE NOTES ON "azx_get_response timeout" PROBLEMS:
On some hardwares, you may need to add a proper probe_mask option
to avoid the "azx_get_response timeout" problem above, instead.
This occurs when the access to non-existing or non-working codec slot
(likely a modem one) causes a stall of the communication via HD-audio
bus. You can see which codec slots are probed by enabling
CONFIG_SND_DEBUG_DETECT, or simply from the file name of the codec
proc files. Then limit the slots to probe by probe_mask option.
For example, probe_mask=1 means to probe only the first slot, and
probe_mask=4 means only the third slot.
The power-management is supported. The power-management is supported.
Module snd-hdsp Module snd-hdsp
......
Guide to using M-Audio Audiophile USB with ALSA and Jack v1.3 Guide to using M-Audio Audiophile USB with ALSA and Jack v1.5
======================================================== ========================================================
Thibault Le Meur <Thibault.LeMeur@supelec.fr> Thibault Le Meur <Thibault.LeMeur@supelec.fr>
...@@ -6,8 +6,19 @@ ...@@ -6,8 +6,19 @@
This document is a guide to using the M-Audio Audiophile USB (tm) device with This document is a guide to using the M-Audio Audiophile USB (tm) device with
ALSA and JACK. ALSA and JACK.
History
=======
* v1.4 - Thibault Le Meur (2007-07-11)
- Added Low Endianness nature of 16bits-modes
found by Hakan Lennestal <Hakan.Lennestal@brfsodrahamn.se>
- Modifying document structure
* v1.5 - Thibault Le Meur (2007-07-12)
- Added AC3/DTS passthru info
1 - Audiophile USB Specs and correct usage 1 - Audiophile USB Specs and correct usage
========================================== ==========================================
This part is a reminder of important facts about the functions and limitations This part is a reminder of important facts about the functions and limitations
of the device. of the device.
...@@ -25,18 +36,18 @@ The device has 4 audio interfaces, and 2 MIDI ports: ...@@ -25,18 +36,18 @@ The device has 4 audio interfaces, and 2 MIDI ports:
The internal DAC/ADC has the following characteristics: The internal DAC/ADC has the following characteristics:
* sample depth of 16 or 24 bits * sample depth of 16 or 24 bits
* sample rate from 8kHz to 96kHz * sample rate from 8kHz to 96kHz
* Two ports can't use different sample depths at the same time. Moreover, the * Two interfaces can't use different sample depths at the same time.
Audiophile USB documentation gives the following Warning: "Please exit any Moreover, the Audiophile USB documentation gives the following Warning:
audio application running before switching between bit depths" "Please exit any audio application running before switching between bit depths"
Due to the USB 1.1 bandwidth limitation, a limited number of interfaces can be Due to the USB 1.1 bandwidth limitation, a limited number of interfaces can be
activated at the same time depending on the audio mode selected: activated at the same time depending on the audio mode selected:
* 16-bit/48kHz ==> 4 channels in/4 channels out * 16-bit/48kHz ==> 4 channels in + 4 channels out
- Ai+Ao+Di+Do - Ai+Ao+Di+Do
* 24-bit/48kHz ==> 4 channels in/2 channels out, * 24-bit/48kHz ==> 4 channels in + 2 channels out,
or 2 channels in/4 channels out or 2 channels in + 4 channels out
- Ai+Ao+Do or Ai+Di+Ao or Ai+Di+Do or Di+Ao+Do - Ai+Ao+Do or Ai+Di+Ao or Ai+Di+Do or Di+Ao+Do
* 24-bit/96kHz ==> 2 channels in, or 2 channels out (half duplex only) * 24-bit/96kHz ==> 2 channels in _or_ 2 channels out (half duplex only)
- Ai or Ao or Di or Do - Ai or Ao or Di or Do
Important facts about the Digital interface: Important facts about the Digital interface:
...@@ -52,44 +63,56 @@ source is connected ...@@ -52,44 +63,56 @@ source is connected
synchronization error (for instance sound played at an odd sample rate) synchronization error (for instance sound played at an odd sample rate)
2 - Audiophile USB support in ALSA 2 - Audiophile USB MIDI support in ALSA
================================== =======================================
2.1 - MIDI ports The Audiophile USB MIDI ports will be automatically supported once the
----------------
The Audiophile USB MIDI ports will be automatically supported once the
following modules have been loaded: following modules have been loaded:
* snd-usb-audio * snd-usb-audio
* snd-seq-midi * snd-seq-midi
No additional setting is required. No additional setting is required.
2.2 - Audio ports
----------------- 3 - Audiophile USB Audio support in ALSA
========================================
Audio functions of the Audiophile USB device are handled by the snd-usb-audio Audio functions of the Audiophile USB device are handled by the snd-usb-audio
module. This module can work in a default mode (without any device-specific module. This module can work in a default mode (without any device-specific
parameter), or in an "advanced" mode with the device-specific parameter called parameter), or in an "advanced" mode with the device-specific parameter called
"device_setup". "device_setup".
2.2.1 - Default Alsa driver mode 3.1 - Default Alsa driver mode
------------------------------
The default behavior of the snd-usb-audio driver is to parse the device
capabilities at startup and enable all functions inside the device (including The default behavior of the snd-usb-audio driver is to list the device
all ports at any supported sample rates and sample depths). This approach capabilities at startup and activate the required mode when required
has the advantage to let the driver easily switch from sample rates/depths by the applications: for instance if the user is recording in a
automatically according to the need of the application claiming the device. 24bit-depth-mode and immediately after wants to switch to a 16bit-depth mode,
the snd-usb-audio module will reconfigure the device on the fly.
In this case the Audiophile ports are mapped to alsa pcm devices in the
following way (I suppose the device's index is 1): This approach has the advantage to let the driver automatically switch from sample
rates/depths automatically according to the user's needs. However, those who
are using the device under windows know that this is not how the device is meant to
work: under windows applications must be closed before using the m-audio control
panel to switch the device working mode. Thus as we'll see in next section, this
Default Alsa driver mode can lead to device misconfigurations.
Let's get back to the Default Alsa driver mode for now. In this case the
Audiophile interfaces are mapped to alsa pcm devices in the following
way (I suppose the device's index is 1):
* hw:1,0 is Ao in playback and Di in capture * hw:1,0 is Ao in playback and Di in capture
* hw:1,1 is Do in playback and Ai in capture * hw:1,1 is Do in playback and Ai in capture
* hw:1,2 is Do in AC3/DTS passthrough mode * hw:1,2 is Do in AC3/DTS passthrough mode
You must note as well that the device uses Big Endian byte encoding so that In this mode, the device uses Big Endian byte-encoding so that
supported audio format are S16_BE for 16-bit depth modes and S24_3BE for supported audio format are S16_BE for 16-bit depth modes and S24_3BE for
24-bits depth mode. One exception is the hw:1,2 port which is Little Endian 24-bits depth mode.
compliant and thus uses S16_LE.
One exception is the hw:1,2 port which was reported to be Little Endian
compliant (supposedly supporting S16_LE) but processes in fact only S16_BE streams.
This has been fixed in kernel 2.6.23 and above and now the hw:1,2 interface
is reported to be big endian in this default driver mode.
Examples: Examples:
* playing a S24_3BE encoded raw file to the Ao port * playing a S24_3BE encoded raw file to the Ao port
...@@ -98,22 +121,26 @@ Examples: ...@@ -98,22 +121,26 @@ Examples:
% arecord -D hw:1,1 -c2 -t raw -r48000 -fS24_3BE test.raw % arecord -D hw:1,1 -c2 -t raw -r48000 -fS24_3BE test.raw
* playing a S16_BE encoded raw file to the Do port * playing a S16_BE encoded raw file to the Do port
% aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test.raw % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test.raw
* playing an ac3 sample file to the Do port
% aplay -D hw:1,2 --channels=6 ac3_S16_BE_encoded_file.raw
If you're happy with the default Alsa driver setup and don't experience any If you're happy with the default Alsa driver mode and don't experience any
issue with this mode, then you can skip the following chapter. issue with this mode, then you can skip the following chapter.
2.2.2 - Advanced module setup 3.2 - Advanced module setup
---------------------------
Due to the hardware constraints described above, the device initialization made Due to the hardware constraints described above, the device initialization made
by the Alsa driver in default mode may result in a corrupted state of the by the Alsa driver in default mode may result in a corrupted state of the
device. For instance, a particularly annoying issue is that the sound captured device. For instance, a particularly annoying issue is that the sound captured
from the Ai port sounds distorted (as if boosted with an excessive high volume from the Ai interface sounds distorted (as if boosted with an excessive high
gain). volume gain).
For people having this problem, the snd-usb-audio module has a new module For people having this problem, the snd-usb-audio module has a new module
parameter called "device_setup". parameter called "device_setup" (this parameter was introduced in kernel
release 2.6.17)
2.2.2.1 - Initializing the working mode of the Audiophile USB 3.2.1 - Initializing the working mode of the Audiophile USB
As far as the Audiophile USB device is concerned, this value let the user As far as the Audiophile USB device is concerned, this value let the user
specify: specify:
...@@ -121,33 +148,57 @@ specify: ...@@ -121,33 +148,57 @@ specify:
* the sample rate * the sample rate
* whether the Di port is used or not * whether the Di port is used or not
Here is a list of supported device_setup values for this device: When initialized with "device_setup=0x00", the snd-usb-audio module has
* device_setup=0x00 (or omitted) the same behaviour as when the parameter is omitted (see paragraph "Default
- Alsa driver default mode Alsa driver mode" above)
- maintains backward compatibility with setups that do not use this
parameter by not introducing any change Others modes are described in the following subsections.
- results sometimes in corrupted sound as described earlier
3.2.1.1 - 16-bit modes
The two supported modes are:
* device_setup=0x01 * device_setup=0x01
- 16bits 48kHz mode with Di disabled - 16bits 48kHz mode with Di disabled
- Ai,Ao,Do can be used at the same time - Ai,Ao,Do can be used at the same time
- hw:1,0 is not available in capture mode - hw:1,0 is not available in capture mode
- hw:1,2 is not available - hw:1,2 is not available
* device_setup=0x11 * device_setup=0x11
- 16bits 48kHz mode with Di enabled - 16bits 48kHz mode with Di enabled
- Ai,Ao,Di,Do can be used at the same time - Ai,Ao,Di,Do can be used at the same time
- hw:1,0 is available in capture mode - hw:1,0 is available in capture mode
- hw:1,2 is not available - hw:1,2 is not available
In this modes the device operates only at 16bits-modes. Before kernel 2.6.23,
the devices where reported to be Big-Endian when in fact they were Little-Endian
so that playing a file was a matter of using:
% aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test_S16_LE.raw
where "test_S16_LE.raw" was in fact a little-endian sample file.
Thanks to Hakan Lennestal (who discovered the Little-Endiannes of the device in
these modes) a fix has been committed (expected in kernel 2.6.23) and
Alsa now reports Little-Endian interfaces. Thus playing a file now is as simple as
using:
% aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_LE test_S16_LE.raw
3.2.1.2 - 24-bit modes
The three supported modes are:
* device_setup=0x09 * device_setup=0x09
- 24bits 48kHz mode with Di disabled - 24bits 48kHz mode with Di disabled
- Ai,Ao,Do can be used at the same time - Ai,Ao,Do can be used at the same time
- hw:1,0 is not available in capture mode - hw:1,0 is not available in capture mode
- hw:1,2 is not available - hw:1,2 is not available
* device_setup=0x19 * device_setup=0x19
- 24bits 48kHz mode with Di enabled - 24bits 48kHz mode with Di enabled
- 3 ports from {Ai,Ao,Di,Do} can be used at the same time - 3 ports from {Ai,Ao,Di,Do} can be used at the same time
- hw:1,0 is available in capture mode and an active digital source must be - hw:1,0 is available in capture mode and an active digital source must be
connected to Di connected to Di
- hw:1,2 is not available - hw:1,2 is not available
* device_setup=0x0D or 0x10 * device_setup=0x0D or 0x10
- 24bits 96kHz mode - 24bits 96kHz mode
- Di is enabled by default for this mode but does not need to be connected - Di is enabled by default for this mode but does not need to be connected
...@@ -155,34 +206,64 @@ Here is a list of supported device_setup values for this device: ...@@ -155,34 +206,64 @@ Here is a list of supported device_setup values for this device:
- Only 1 port from {Ai,Ao,Di,Do} can be used at the same time - Only 1 port from {Ai,Ao,Di,Do} can be used at the same time
- hw:1,0 is available in captured mode - hw:1,0 is available in captured mode
- hw:1,2 is not available - hw:1,2 is not available
In these modes the device is only Big-Endian compliant (see "Default Alsa driver
mode" above for an aplay command example)
3.2.1.3 - AC3 w/ DTS passthru mode
Thanks to Hakan Lennestal, I now have a report saying that this mode works.
* device_setup=0x03 * device_setup=0x03
- 16bits 48kHz mode with only the Do port enabled - 16bits 48kHz mode with only the Do port enabled
- AC3 with DTS passthru (not tested) - AC3 with DTS passthru
- Caution with this setup the Do port is mapped to the pcm device hw:1,0 - Caution with this setup the Do port is mapped to the pcm device hw:1,0
2.2.2.2 - Setting and switching configurations with the device_setup parameter The command line used to playback the AC3/DTS encoded .wav-files in this mode:
% aplay -D hw:1,0 --channels=6 ac3_S16_LE_encoded_file.raw
3.2.2 - How to use the device_setup parameter
----------------------------------------------
The parameter can be given: The parameter can be given:
* By manually probing the device (as root): * By manually probing the device (as root):
# modprobe -r snd-usb-audio # modprobe -r snd-usb-audio
# modprobe snd-usb-audio index=1 device_setup=0x09 # modprobe snd-usb-audio index=1 device_setup=0x09
* Or while configuring the modules options in your modules configuration file * Or while configuring the modules options in your modules configuration file
- For Fedora distributions, edit the /etc/modprobe.conf file: - For Fedora distributions, edit the /etc/modprobe.conf file:
alias snd-card-1 snd-usb-audio alias snd-card-1 snd-usb-audio
options snd-usb-audio index=1 device_setup=0x09 options snd-usb-audio index=1 device_setup=0x09
IMPORTANT NOTE WHEN SWITCHING CONFIGURATION: CAUTION when initializaing the device
------------------------------------------- -------------------------------------
* You may need to _first_ initialize the module with the correct device_setup
parameter and _only_after_ turn on the Audiophile USB device * Correct initialization on the device requires that device_setup is given to
* This is especially true when switching the sample depth: the module BEFORE the device is turned on. So, if you use the "manual probing"
method described above, take care to power-on the device AFTER this initialization.
* Failing to respect this will lead in a misconfiguration of the device. In this case
turn off the device, unproble the snd-usb-audio module, then probe it again with
correct device_setup parameter and then (and only then) turn on the device again.
* If you've correctly initialized the device in a valid mode and then want to switch
to another mode (possibly with another sample-depth), please use also the following
procedure:
- first turn off the device - first turn off the device
- de-register the snd-usb-audio module (modprobe -r) - de-register the snd-usb-audio module (modprobe -r)
- change the device_setup parameter by changing the device_setup - change the device_setup parameter by changing the device_setup
option in /etc/modprobe.conf option in /etc/modprobe.conf
- turn on the device - turn on the device
* A workaround for this last issue has been applied to kernel 2.6.23, but it may not
be enough to ensure the 'stability' of the device initialization.
2.2.2.3 - Audiophile USB's device_setup structure 3.2.3 - Technical details for hackers
-------------------------------------
This section is for hackers, wanting to understand details about the device
internals and how Alsa supports it.
3.2.3.1 - Audiophile USB's device_setup structure
If you want to understand the device_setup magic numbers for the Audiophile If you want to understand the device_setup magic numbers for the Audiophile
USB, you need some very basic understanding of binary computation. However, USB, you need some very basic understanding of binary computation. However,
...@@ -228,12 +309,12 @@ Caution: ...@@ -228,12 +309,12 @@ Caution:
- choosing b2 will prepare all interfaces for 24bits/96kHz but you'll - choosing b2 will prepare all interfaces for 24bits/96kHz but you'll
only be able to use one at the same time only be able to use one at the same time
2.2.3 - USB implementation details for this device 3.2.3.2 - USB implementation details for this device
You may safely skip this section if you're not interested in driver You may safely skip this section if you're not interested in driver
development. hacking.
This section describes some internal aspects of the device and summarize the This section describes some internal aspects of the device and summarizes the
data I got by usb-snooping the windows and Linux drivers. data I got by usb-snooping the windows and Linux drivers.
The M-Audio Audiophile USB has 7 USB Interfaces: The M-Audio Audiophile USB has 7 USB Interfaces:
...@@ -293,43 +374,45 @@ parse_audio_endpoints function uses a quirk called ...@@ -293,43 +374,45 @@ parse_audio_endpoints function uses a quirk called
"audiophile_skip_setting_quirk" in order to prevent AltSettings not "audiophile_skip_setting_quirk" in order to prevent AltSettings not
corresponding to device_setup from being registered in the driver. corresponding to device_setup from being registered in the driver.
3 - Audiophile USB and Jack support 4 - Audiophile USB and Jack support
=================================== ===================================
This section deals with support of the Audiophile USB device in Jack. This section deals with support of the Audiophile USB device in Jack.
The main issue regarding this support is that the device is Big Endian
compliant.
3.1 - Using the plug alsa plugin There are 2 main potential issues when using Jackd with the device:
-------------------------------- * support for Big-Endian devices in 24-bit modes
* support for 4-in / 4-out channels
4.1 - Direct support in Jackd
-----------------------------
Jack doesn't directly support big endian devices. Thus, one way to have support Jack supports big endian devices only in recent versions (thanks to
for this device with Alsa is to use the Alsa "plug" converter. Andreas Steinmetz for his first big-endian patch). I can't remember
extacly when this support was released into jackd, let's just say that
with jackd version 0.103.0 it's almost ok (just a small bug is affecting
16bits Big-Endian devices, but since you've read carefully the above
paragraphs, you're now using kernel >= 2.6.23 and your 16bits devices
are now Little Endians ;-) ).
You can run jackd with the following command for playback with Ao and
record with Ai:
% jackd -R -dalsa -Phw:1,0 -r48000 -p128 -n2 -D -Chw:1,1
4.2 - Using Alsa plughw
-----------------------
If you don't have a recent Jackd installed, you can downgrade to using
the Alsa "plug" converter.
For instance here is one way to run Jack with 2 playback channels on Ao and 2 For instance here is one way to run Jack with 2 playback channels on Ao and 2
capture channels from Ai: capture channels from Ai:
% jackd -R -dalsa -dplughw:1 -r48000 -p256 -n2 -D -Cplughw:1,1 % jackd -R -dalsa -dplughw:1 -r48000 -p256 -n2 -D -Cplughw:1,1
However you may see the following warning message: However you may see the following warning message:
"You appear to be using the ALSA software "plug" layer, probably a result of "You appear to be using the ALSA software "plug" layer, probably a result of
using the "default" ALSA device. This is less efficient than it could be. using the "default" ALSA device. This is less efficient than it could be.
Consider using a hardware device instead rather than using the plug layer." Consider using a hardware device instead rather than using the plug layer."
3.2 - Patching alsa to use direct pcm device 4.3 - Getting 2 input and/or output interfaces in Jack
--------------------------------------------
A patch for Jack by Andreas Steinmetz adds support for Big Endian devices.
However it has not been included in the CVS tree.
You can find it at the following URL:
http://sourceforge.net/tracker/index.php?func=detail&aid=1289682&group_id=39687&
atid=425939
After having applied the patch you can run jackd with the following command
line:
% jackd -R -dalsa -Phw:1,0 -r48000 -p128 -n2 -D -Chw:1,1
3.2 - Getting 2 input and/or output interfaces in Jack
------------------------------------------------------ ------------------------------------------------------
As you can see, starting the Jack server this way will only enable 1 stereo As you can see, starting the Jack server this way will only enable 1 stereo
...@@ -339,6 +422,7 @@ This is due to the following restrictions: ...@@ -339,6 +422,7 @@ This is due to the following restrictions:
* Jack can only open one capture device and one playback device at a time * Jack can only open one capture device and one playback device at a time
* The Audiophile USB is seen as 2 (or three) Alsa devices: hw:1,0, hw:1,1 * The Audiophile USB is seen as 2 (or three) Alsa devices: hw:1,0, hw:1,1
(and optionally hw:1,2) (and optionally hw:1,2)
If you want to get Ai+Di and/or Ao+Do support with Jack, you would need to If you want to get Ai+Di and/or Ao+Do support with Jack, you would need to
combine the Alsa devices into one logical "complex" device. combine the Alsa devices into one logical "complex" device.
...@@ -348,13 +432,11 @@ It is related to another device (ice1712) but can be adapted to suit ...@@ -348,13 +432,11 @@ It is related to another device (ice1712) but can be adapted to suit
the Audiophile USB. the Audiophile USB.
Enabling multiple Audiophile USB interfaces for Jackd will certainly require: Enabling multiple Audiophile USB interfaces for Jackd will certainly require:
* patching Jack with the previously mentioned "Big Endian" patch * Making sure your Jackd version has the MMAP_COMPLEX patch (see the ice1712 page)
* patching Jackd with the MMAP_COMPLEX patch (see the ice1712 page) * (maybe) patching the alsa-lib/src/pcm/pcm_multi.c file (see the ice1712 page)
* patching the alsa-lib/src/pcm/pcm_multi.c file (see the ice1712 page)
* define a multi device (combination of hw:1,0 and hw:1,1) in your .asoundrc * define a multi device (combination of hw:1,0 and hw:1,1) in your .asoundrc
file file
* start jackd with this device * start jackd with this device
I had no success in testing this for now, but this may be due to my OS I had no success in testing this for now, if you have any success with this kind
configuration. If you have any success with this kind of setup, please of setup, please drop me an email.
drop me an email.
...@@ -278,6 +278,21 @@ current mixer configuration by reading and writing the whole file ...@@ -278,6 +278,21 @@ current mixer configuration by reading and writing the whole file
image. image.
Duplex Streams
==============
Note that when attempting to use a single device file for playback and
capture, the OSS API provides no way to set the format, sample rate or
number of channels different in each direction. Thus
io_handle = open("device", O_RDWR)
will only function correctly if the values are the same in each direction.
To use different values in the two directions, use both
input_handle = open("device", O_RDONLY)
output_handle = open("device", O_WRONLY)
and set the values for the corresponding handle.
Unsupported Features Unsupported Features
==================== ====================
......
...@@ -115,9 +115,10 @@ ...@@ -115,9 +115,10 @@
#define I2C_DRIVERID_KS0127 86 /* Samsung ks0127 video decoder */ #define I2C_DRIVERID_KS0127 86 /* Samsung ks0127 video decoder */
#define I2C_DRIVERID_TLV320AIC23B 87 /* TI TLV320AIC23B audio codec */ #define I2C_DRIVERID_TLV320AIC23B 87 /* TI TLV320AIC23B audio codec */
#define I2C_DRIVERID_ISL1208 88 /* Intersil ISL1208 RTC */ #define I2C_DRIVERID_ISL1208 88 /* Intersil ISL1208 RTC */
#define I2C_DRIVERID_WM8731 89 /* Wolfson WM8731 audio codec */ #define I2C_DRIVERID_WM8731 89 /* Wolfson WM8731 audio codec */
#define I2C_DRIVERID_WM8750 90 /* Wolfson WM8750 audio codec */ #define I2C_DRIVERID_WM8750 90 /* Wolfson WM8750 audio codec */
#define I2C_DRIVERID_WM8753 91 /* Wolfson WM8753 audio codec */ #define I2C_DRIVERID_WM8753 91 /* Wolfson WM8753 audio codec */
#define I2C_DRIVERID_LM4857 92 /* LM4857 Audio Amplifier */
#define I2C_DRIVERID_I2CDEV 900 #define I2C_DRIVERID_I2CDEV 900
#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */
......
...@@ -43,6 +43,7 @@ struct snd_ak4xxx_ops { ...@@ -43,6 +43,7 @@ struct snd_ak4xxx_ops {
struct snd_akm4xxx_dac_channel { struct snd_akm4xxx_dac_channel {
char *name; /* mixer volume name */ char *name; /* mixer volume name */
unsigned int num_channels; unsigned int num_channels;
char *switch_name; /* mixer switch*/
}; };
/* ADC labels and channels */ /* ADC labels and channels */
......
...@@ -1723,6 +1723,10 @@ struct snd_cs46xx { ...@@ -1723,6 +1723,10 @@ struct snd_cs46xx {
struct snd_cs46xx_pcm *playback_pcm; struct snd_cs46xx_pcm *playback_pcm;
unsigned int play_ctl; unsigned int play_ctl;
#endif #endif
#ifdef CONFIG_PM
u32 *saved_regs;
#endif
}; };
int snd_cs46xx_create(struct snd_card *card, int snd_cs46xx_create(struct snd_card *card,
......
...@@ -107,6 +107,7 @@ struct dsp_scb_descriptor { ...@@ -107,6 +107,7 @@ struct dsp_scb_descriptor {
char scb_name[DSP_MAX_SCB_NAME]; char scb_name[DSP_MAX_SCB_NAME];
u32 address; u32 address;
int index; int index;
u32 *data;
struct dsp_scb_descriptor * sub_list_ptr; struct dsp_scb_descriptor * sub_list_ptr;
struct dsp_scb_descriptor * next_scb_ptr; struct dsp_scb_descriptor * next_scb_ptr;
...@@ -127,6 +128,7 @@ struct dsp_task_descriptor { ...@@ -127,6 +128,7 @@ struct dsp_task_descriptor {
int size; int size;
u32 address; u32 address;
int index; int index;
u32 *data;
}; };
struct dsp_pcm_channel_descriptor { struct dsp_pcm_channel_descriptor {
......
...@@ -1120,6 +1120,16 @@ ...@@ -1120,6 +1120,16 @@
/************************************************************************************************/ /************************************************************************************************/
/* EMU1010m HANA Destinations */ /* EMU1010m HANA Destinations */
/************************************************************************************************/ /************************************************************************************************/
/* 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.
*/
/* EMU32 = 32-bit serial channel between Alice2 (audigy) and Hana (FPGA) */
/* EMU_DST_ALICE2_EMU32_X - data channels from Hana to Alice2 used for capture.
* Which data is fed into a EMU_DST_ALICE2_EMU32_X channel in Hana depends on
* setup of mixer control for each destination - see emumixer.c -
* snd_emu1010_output_enum_ctls[], snd_emu1010_input_enum_ctls[]
*/
#define EMU_DST_ALICE2_EMU32_0 0x000f /* 16 EMU32 channels to Alice2 +0 to +0xf */ #define EMU_DST_ALICE2_EMU32_0 0x000f /* 16 EMU32 channels to Alice2 +0 to +0xf */
#define EMU_DST_ALICE2_EMU32_1 0x0000 /* 16 EMU32 channels to Alice2 +0 to +0xf */ #define EMU_DST_ALICE2_EMU32_1 0x0000 /* 16 EMU32 channels to Alice2 +0 to +0xf */
#define EMU_DST_ALICE2_EMU32_2 0x0001 /* 16 EMU32 channels to Alice2 +0 to +0xf */ #define EMU_DST_ALICE2_EMU32_2 0x0001 /* 16 EMU32 channels to Alice2 +0 to +0xf */
...@@ -1199,6 +1209,12 @@ ...@@ -1199,6 +1209,12 @@
/************************************************************************************************/ /************************************************************************************************/
/* EMU1010m HANA Sources */ /* EMU1010m HANA Sources */
/************************************************************************************************/ /************************************************************************************************/
/* 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,
* or outputs from Alice (audigy) - 16 x EMU_SRC_ALICE_EMU32A +
* 16 x EMU_SRC_ALICE_EMU32B
*/
#define EMU_SRC_SILENCE 0x0000 /* Silence */ #define EMU_SRC_SILENCE 0x0000 /* Silence */
#define EMU_SRC_DOCK_MIC_A1 0x0100 /* Audio Dock Mic A, 1st or 48kHz only */ #define EMU_SRC_DOCK_MIC_A1 0x0100 /* Audio Dock Mic A, 1st or 48kHz only */
#define EMU_SRC_DOCK_MIC_A2 0x0101 /* Audio Dock Mic A, 2nd or 96kHz */ #define EMU_SRC_DOCK_MIC_A2 0x0101 /* Audio Dock Mic A, 2nd or 96kHz */
......
...@@ -38,6 +38,7 @@ enum sb_hw_type { ...@@ -38,6 +38,7 @@ enum sb_hw_type {
SB_HW_ALS100, /* Avance Logic ALS100 chip */ SB_HW_ALS100, /* Avance Logic ALS100 chip */
SB_HW_ALS4000, /* Avance Logic ALS4000 chip */ SB_HW_ALS4000, /* Avance Logic ALS4000 chip */
SB_HW_DT019X, /* Diamond Tech. DT-019X / Avance Logic ALS-007 */ SB_HW_DT019X, /* Diamond Tech. DT-019X / Avance Logic ALS-007 */
SB_HW_CS5530, /* Cyrix/NatSemi 5530 VSA1 */
}; };
#define SB_OPEN_PCM 0x01 #define SB_OPEN_PCM 0x01
......
/* include/version.h. Generated by alsa/ksync script. */ /* include/version.h. Generated by alsa/ksync script. */
#define CONFIG_SND_VERSION "1.0.14" #define CONFIG_SND_VERSION "1.0.14"
#define CONFIG_SND_DATE " (Thu May 31 09:03:25 2007 UTC)" #define CONFIG_SND_DATE " (Fri Jul 20 09:12:58 2007 UTC)"
#ifndef __SOUND_WAVEFRONT_FX_H
#define __SOUND_WAVEFRONT_FX_H
extern int snd_wavefront_fx_detect (snd_wavefront_t *);
extern void snd_wavefront_fx_ioctl (snd_synth_t *sdev,
unsigned int cmd,
unsigned long arg);
#endif __SOUND_WAVEFRONT_FX_H
...@@ -65,6 +65,8 @@ source "sound/arm/Kconfig" ...@@ -65,6 +65,8 @@ source "sound/arm/Kconfig"
source "sound/mips/Kconfig" source "sound/mips/Kconfig"
source "sound/sh/Kconfig"
# the following will depend on the order of config. # the following will depend on the order of config.
# here assuming USB is defined before ALSA # here assuming USB is defined before ALSA
source "sound/usb/Kconfig" source "sound/usb/Kconfig"
......
...@@ -5,7 +5,7 @@ obj-$(CONFIG_SOUND) += soundcore.o ...@@ -5,7 +5,7 @@ obj-$(CONFIG_SOUND) += soundcore.o
obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o
obj-$(CONFIG_SOUND_PRIME) += oss/ obj-$(CONFIG_SOUND_PRIME) += oss/
obj-$(CONFIG_DMASOUND) += oss/ obj-$(CONFIG_DMASOUND) += oss/
obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ soc/ obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ soc/
obj-$(CONFIG_SND_AOA) += aoa/ obj-$(CONFIG_SND_AOA) += aoa/
# This one must be compilable even if sound is configured out # This one must be compilable even if sound is configured out
......
...@@ -661,7 +661,7 @@ static struct transfer_info onyx_transfers[] = { ...@@ -661,7 +661,7 @@ static struct transfer_info onyx_transfers[] = {
.tag = 2, .tag = 2,
}, },
#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
Once alsa gets supports for this kind of thing we can add it... /* Once alsa gets supports for this kind of thing we can add it... */
{ {
/* digital compressed output */ /* digital compressed output */
.formats = SNDRV_PCM_FMTBIT_COMPRESSED_16BE, .formats = SNDRV_PCM_FMTBIT_COMPRESSED_16BE,
...@@ -713,7 +713,7 @@ static int onyx_prepare(struct codec_info_item *cii, ...@@ -713,7 +713,7 @@ static int onyx_prepare(struct codec_info_item *cii,
if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) { if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) {
/* mute and lock analog output */ /* mute and lock analog output */
onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
if (onyx_write_register(onyx if (onyx_write_register(onyx,
ONYX_REG_DAC_CONTROL, ONYX_REG_DAC_CONTROL,
v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT)) v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT))
goto out_unlock; goto out_unlock;
......
...@@ -1487,7 +1487,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) ...@@ -1487,7 +1487,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
snd_pcm_stream_lock_irq(substream); snd_pcm_stream_lock_irq(substream);
/* resume pause */ /* resume pause */
if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) if (substream->runtime->status->state == SNDRV_PCM_STATE_PAUSED)
snd_pcm_pause(substream, 0); snd_pcm_pause(substream, 0);
/* pre-start/stop - all running streams are changed to DRAINING state */ /* pre-start/stop - all running streams are changed to DRAINING state */
......
...@@ -109,7 +109,7 @@ void snd_seq_instr_list_free(struct snd_seq_kinstr_list **list_ptr) ...@@ -109,7 +109,7 @@ void snd_seq_instr_list_free(struct snd_seq_kinstr_list **list_ptr)
spin_lock_irqsave(&list->lock, flags); spin_lock_irqsave(&list->lock, flags);
while (instr->use) { while (instr->use) {
spin_unlock_irqrestore(&list->lock, flags); spin_unlock_irqrestore(&list->lock, flags);
schedule_timeout_interruptible(1); schedule_timeout(1);
spin_lock_irqsave(&list->lock, flags); spin_lock_irqsave(&list->lock, flags);
} }
spin_unlock_irqrestore(&list->lock, flags); spin_unlock_irqrestore(&list->lock, flags);
...@@ -199,7 +199,7 @@ int snd_seq_instr_list_free_cond(struct snd_seq_kinstr_list *list, ...@@ -199,7 +199,7 @@ int snd_seq_instr_list_free_cond(struct snd_seq_kinstr_list *list,
instr = flist; instr = flist;
flist = instr->next; flist = instr->next;
while (instr->use) while (instr->use)
schedule_timeout_interruptible(1); schedule_timeout(1);
if (snd_seq_instr_free(instr, atomic)<0) if (snd_seq_instr_free(instr, atomic)<0)
snd_printk(KERN_WARNING "instrument free problem\n"); snd_printk(KERN_WARNING "instrument free problem\n");
instr = next; instr = next;
...@@ -555,7 +555,7 @@ static int instr_free(struct snd_seq_kinstr_ops *ops, ...@@ -555,7 +555,7 @@ static int instr_free(struct snd_seq_kinstr_ops *ops,
SNDRV_SEQ_INSTR_NOTIFY_REMOVE); SNDRV_SEQ_INSTR_NOTIFY_REMOVE);
while (instr->use) { while (instr->use) {
spin_unlock_irqrestore(&list->lock, flags); spin_unlock_irqrestore(&list->lock, flags);
schedule_timeout_interruptible(1); schedule_timeout(1);
spin_lock_irqsave(&list->lock, flags); spin_lock_irqsave(&list->lock, flags);
} }
spin_unlock_irqrestore(&list->lock, flags); spin_unlock_irqrestore(&list->lock, flags);
......
...@@ -1549,9 +1549,11 @@ static int snd_timer_user_info(struct file *file, ...@@ -1549,9 +1549,11 @@ static int snd_timer_user_info(struct file *file,
int err = 0; int err = 0;
tu = file->private_data; tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO); if (!tu->timeri)
return -EBADFD;
t = tu->timeri->timer; t = tu->timeri->timer;
snd_assert(t != NULL, return -ENXIO); if (!t)
return -EBADFD;
info = kzalloc(sizeof(*info), GFP_KERNEL); info = kzalloc(sizeof(*info), GFP_KERNEL);
if (! info) if (! info)
...@@ -1579,9 +1581,11 @@ static int snd_timer_user_params(struct file *file, ...@@ -1579,9 +1581,11 @@ static int snd_timer_user_params(struct file *file,
int err; int err;
tu = file->private_data; tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO); if (!tu->timeri)
return -EBADFD;
t = tu->timeri->timer; t = tu->timeri->timer;
snd_assert(t != NULL, return -ENXIO); if (!t)
return -EBADFD;
if (copy_from_user(&params, _params, sizeof(params))) if (copy_from_user(&params, _params, sizeof(params)))
return -EFAULT; return -EFAULT;
if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE) && params.ticks < 1) { if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE) && params.ticks < 1) {
...@@ -1675,7 +1679,8 @@ static int snd_timer_user_status(struct file *file, ...@@ -1675,7 +1679,8 @@ static int snd_timer_user_status(struct file *file,
struct snd_timer_status status; struct snd_timer_status status;
tu = file->private_data; tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO); if (!tu->timeri)
return -EBADFD;
memset(&status, 0, sizeof(status)); memset(&status, 0, sizeof(status));
status.tstamp = tu->tstamp; status.tstamp = tu->tstamp;
status.resolution = snd_timer_resolution(tu->timeri); status.resolution = snd_timer_resolution(tu->timeri);
...@@ -1695,7 +1700,8 @@ static int snd_timer_user_start(struct file *file) ...@@ -1695,7 +1700,8 @@ static int snd_timer_user_start(struct file *file)
struct snd_timer_user *tu; struct snd_timer_user *tu;
tu = file->private_data; tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO); if (!tu->timeri)
return -EBADFD;
snd_timer_stop(tu->timeri); snd_timer_stop(tu->timeri);
tu->timeri->lost = 0; tu->timeri->lost = 0;
tu->last_resolution = 0; tu->last_resolution = 0;
...@@ -1708,7 +1714,8 @@ static int snd_timer_user_stop(struct file *file) ...@@ -1708,7 +1714,8 @@ static int snd_timer_user_stop(struct file *file)
struct snd_timer_user *tu; struct snd_timer_user *tu;
tu = file->private_data; tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO); if (!tu->timeri)
return -EBADFD;
return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0; return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0;
} }
...@@ -1718,7 +1725,8 @@ static int snd_timer_user_continue(struct file *file) ...@@ -1718,7 +1725,8 @@ static int snd_timer_user_continue(struct file *file)
struct snd_timer_user *tu; struct snd_timer_user *tu;
tu = file->private_data; tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO); if (!tu->timeri)
return -EBADFD;
tu->timeri->lost = 0; tu->timeri->lost = 0;
return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0;
} }
...@@ -1729,7 +1737,8 @@ static int snd_timer_user_pause(struct file *file) ...@@ -1729,7 +1737,8 @@ static int snd_timer_user_pause(struct file *file)
struct snd_timer_user *tu; struct snd_timer_user *tu;
tu = file->private_data; tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO); if (!tu->timeri)
return -EBADFD;
return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0; return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0;
} }
......
...@@ -659,7 +659,7 @@ static struct platform_driver snd_dummy_driver = { ...@@ -659,7 +659,7 @@ static struct platform_driver snd_dummy_driver = {
}, },
}; };
static void __init_or_module snd_dummy_unregister_all(void) static void snd_dummy_unregister_all(void)
{ {
int i; int i;
......
...@@ -228,7 +228,7 @@ static struct pnp_driver snd_mpu401_pnp_driver = { ...@@ -228,7 +228,7 @@ static struct pnp_driver snd_mpu401_pnp_driver = {
static struct pnp_driver snd_mpu401_pnp_driver; static struct pnp_driver snd_mpu401_pnp_driver;
#endif #endif
static void __init_or_module snd_mpu401_unregister_all(void) static void snd_mpu401_unregister_all(void)
{ {
int i; int i;
......
...@@ -833,7 +833,7 @@ static struct platform_driver snd_portman_driver = { ...@@ -833,7 +833,7 @@ static struct platform_driver snd_portman_driver = {
/********************************************************************* /*********************************************************************
* module init stuff * module init stuff
*********************************************************************/ *********************************************************************/
static void __init_or_module snd_portman_unregister_all(void) static void snd_portman_unregister_all(void)
{ {
int i; int i;
......
...@@ -998,7 +998,7 @@ static struct platform_driver snd_serial_driver = { ...@@ -998,7 +998,7 @@ static struct platform_driver snd_serial_driver = {
}, },
}; };
static void __init_or_module snd_serial_unregister_all(void) static void snd_serial_unregister_all(void)
{ {
int i; int i;
......
...@@ -145,7 +145,7 @@ static struct platform_driver snd_virmidi_driver = { ...@@ -145,7 +145,7 @@ static struct platform_driver snd_virmidi_driver = {
}, },
}; };
static void __init_or_module snd_virmidi_unregister_all(void) static void snd_virmidi_unregister_all(void)
{ {
int i; int i;
......
...@@ -481,8 +481,8 @@ static int ak4xxx_switch_get(struct snd_kcontrol *kcontrol, ...@@ -481,8 +481,8 @@ static int ak4xxx_switch_get(struct snd_kcontrol *kcontrol,
int addr = AK_GET_ADDR(kcontrol->private_value); int addr = AK_GET_ADDR(kcontrol->private_value);
int shift = AK_GET_SHIFT(kcontrol->private_value); int shift = AK_GET_SHIFT(kcontrol->private_value);
int invert = AK_GET_INVERT(kcontrol->private_value); int invert = AK_GET_INVERT(kcontrol->private_value);
unsigned char val = snd_akm4xxx_get(ak, chip, addr); /* we observe the (1<<shift) bit only */
unsigned char val = snd_akm4xxx_get(ak, chip, addr) & (1<<shift);
if (invert) if (invert)
val = ! val; val = ! val;
ucontrol->value.integer.value[0] = (val & (1<<shift)) != 0; ucontrol->value.integer.value[0] = (val & (1<<shift)) != 0;
...@@ -585,6 +585,26 @@ static int build_dac_controls(struct snd_akm4xxx *ak) ...@@ -585,6 +585,26 @@ static int build_dac_controls(struct snd_akm4xxx *ak)
mixer_ch = 0; mixer_ch = 0;
for (idx = 0; idx < ak->num_dacs; ) { for (idx = 0; idx < ak->num_dacs; ) {
/* mute control for Revolution 7.1 - AK4381 */
if (ak->type == SND_AK4381
&& ak->dac_info[mixer_ch].switch_name) {
memset(&knew, 0, sizeof(knew));
knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
knew.count = 1;
knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
knew.name = ak->dac_info[mixer_ch].switch_name;
knew.info = ak4xxx_switch_info;
knew.get = ak4xxx_switch_get;
knew.put = ak4xxx_switch_put;
knew.access = 0;
/* register 1, bit 0 (SMUTE): 0 = normal operation,
1 = mute */
knew.private_value =
AK_COMPOSE(idx/2, 1, 0, 0) | AK_INVERT;
err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));
if (err < 0)
return err;
}
memset(&knew, 0, sizeof(knew)); memset(&knew, 0, sizeof(knew));
if (! ak->dac_info || ! ak->dac_info[mixer_ch].name) { if (! ak->dac_info || ! ak->dac_info[mixer_ch].name) {
knew.name = "DAC Volume"; knew.name = "DAC Volume";
......
# ALSA ISA drivers # ALSA ISA drivers
menu "ISA devices"
depends on SND!=n && ISA && ISA_DMA_API
config SND_AD1848_LIB config SND_AD1848_LIB
tristate tristate
select SND_PCM select SND_PCM
...@@ -11,6 +8,22 @@ config SND_CS4231_LIB ...@@ -11,6 +8,22 @@ config SND_CS4231_LIB
tristate tristate
select SND_PCM select SND_PCM
config SND_SB_COMMON
tristate
config SND_SB8_DSP
tristate
select SND_PCM
select SND_SB_COMMON
config SND_SB16_DSP
tristate
select SND_PCM
select SND_SB_COMMON
menu "ISA devices"
depends on SND!=n && ISA && ISA_DMA_API
config SND_ADLIB config SND_ADLIB
tristate "AdLib FM card" tristate "AdLib FM card"
depends on SND depends on SND
...@@ -55,7 +68,7 @@ config SND_ALS100 ...@@ -55,7 +68,7 @@ config SND_ALS100
select ISAPNP select ISAPNP
select SND_OPL3_LIB select SND_OPL3_LIB
select SND_MPU401_UART select SND_MPU401_UART
select SND_PCM select SND_SB16_DSP
help help
Say Y here to include support for soundcards based on Avance Say Y here to include support for soundcards based on Avance
Logic ALS100, ALS110, ALS120 and ALS200 chips. Logic ALS100, ALS110, ALS120 and ALS200 chips.
...@@ -81,6 +94,7 @@ config SND_CMI8330 ...@@ -81,6 +94,7 @@ config SND_CMI8330
tristate "C-Media CMI8330" tristate "C-Media CMI8330"
depends on SND depends on SND
select SND_AD1848_LIB select SND_AD1848_LIB
select SND_SB16_DSP
help help
Say Y here to include support for soundcards based on the Say Y here to include support for soundcards based on the
C-Media CMI8330 chip. C-Media CMI8330 chip.
...@@ -132,7 +146,7 @@ config SND_DT019X ...@@ -132,7 +146,7 @@ config SND_DT019X
select ISAPNP select ISAPNP
select SND_OPL3_LIB select SND_OPL3_LIB
select SND_MPU401_UART select SND_MPU401_UART
select SND_PCM select SND_SB16_DSP
help help
Say Y here to include support for soundcards based on the Say Y here to include support for soundcards based on the
Diamond Technologies DT-019X or Avance Logic ALS-007 chips. Diamond Technologies DT-019X or Avance Logic ALS-007 chips.
...@@ -145,7 +159,7 @@ config SND_ES968 ...@@ -145,7 +159,7 @@ config SND_ES968
depends on SND && PNP && ISA depends on SND && PNP && ISA
select ISAPNP select ISAPNP
select SND_MPU401_UART select SND_MPU401_UART
select SND_PCM select SND_SB8_DSP
help help
Say Y here to include support for ESS AudioDrive ES968 chips. Say Y here to include support for ESS AudioDrive ES968 chips.
...@@ -321,7 +335,7 @@ config SND_SB8 ...@@ -321,7 +335,7 @@ config SND_SB8
depends on SND depends on SND
select SND_OPL3_LIB select SND_OPL3_LIB
select SND_RAWMIDI select SND_RAWMIDI
select SND_PCM select SND_SB8_DSP
help help
Say Y here to include support for Creative Sound Blaster 1.0/ Say Y here to include support for Creative Sound Blaster 1.0/
2.0/Pro (8-bit) or 100% compatible soundcards. 2.0/Pro (8-bit) or 100% compatible soundcards.
...@@ -334,7 +348,7 @@ config SND_SB16 ...@@ -334,7 +348,7 @@ config SND_SB16
depends on SND depends on SND
select SND_OPL3_LIB select SND_OPL3_LIB
select SND_MPU401_UART select SND_MPU401_UART
select SND_PCM select SND_SB16_DSP
help help
Say Y here to include support for Sound Blaster 16 soundcards Say Y here to include support for Sound Blaster 16 soundcards
(including the Plug and Play version). (including the Plug and Play version).
...@@ -347,7 +361,7 @@ config SND_SBAWE ...@@ -347,7 +361,7 @@ config SND_SBAWE
depends on SND depends on SND
select SND_OPL3_LIB select SND_OPL3_LIB
select SND_MPU401_UART select SND_MPU401_UART
select SND_PCM select SND_SB16_DSP
help help
Say Y here to include support for Sound Blaster AWE soundcards Say Y here to include support for Sound Blaster AWE soundcards
(including the Plug and Play version). (including the Plug and Play version).
......
...@@ -245,7 +245,7 @@ static void snd_ad1848_mce_down(struct snd_ad1848 *chip) ...@@ -245,7 +245,7 @@ static void snd_ad1848_mce_down(struct snd_ad1848 *chip)
snd_printk(KERN_ERR "mce_down - auto calibration time out (2)\n"); snd_printk(KERN_ERR "mce_down - auto calibration time out (2)\n");
return; return;
} }
time = schedule_timeout_interruptible(time); time = schedule_timeout(time);
spin_lock_irqsave(&chip->reg_lock, flags); spin_lock_irqsave(&chip->reg_lock, flags);
} }
#if 0 #if 0
...@@ -258,7 +258,7 @@ static void snd_ad1848_mce_down(struct snd_ad1848 *chip) ...@@ -258,7 +258,7 @@ static void snd_ad1848_mce_down(struct snd_ad1848 *chip)
snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
return; return;
} }
time = schedule_timeout_interruptible(time); time = schedule_timeout(time);
spin_lock_irqsave(&chip->reg_lock, flags); spin_lock_irqsave(&chip->reg_lock, flags);
} }
spin_unlock_irqrestore(&chip->reg_lock, flags); spin_unlock_irqrestore(&chip->reg_lock, flags);
......
...@@ -164,6 +164,8 @@ static struct pnp_card_device_id snd_opl3sa2_pnpids[] = { ...@@ -164,6 +164,8 @@ static struct pnp_card_device_id snd_opl3sa2_pnpids[] = {
{ .id = "YMH0801", .devs = { { "YMH0021" } } }, { .id = "YMH0801", .devs = { { "YMH0021" } } },
/* NeoMagic MagicWave 3DX */ /* NeoMagic MagicWave 3DX */
{ .id = "NMX2200", .devs = { { "YMH2210" } } }, { .id = "NMX2200", .devs = { { "YMH2210" } } },
/* NeoMagic MagicWave 3D */
{ .id = "NMX2200", .devs = { { "NMX2210" } } },
/* --- */ /* --- */
{ .id = "" } /* end */ { .id = "" } /* end */
}; };
......
...@@ -1927,10 +1927,12 @@ static struct snd_card *snd_opti9xx_card_new(void) ...@@ -1927,10 +1927,12 @@ static struct snd_card *snd_opti9xx_card_new(void)
static int __devinit snd_opti9xx_isa_match(struct device *devptr, static int __devinit snd_opti9xx_isa_match(struct device *devptr,
unsigned int dev) unsigned int dev)
{ {
#ifdef CONFIG_PNP
if (snd_opti9xx_pnp_is_probed) if (snd_opti9xx_pnp_is_probed)
return 0; return 0;
if (isapnp) if (isapnp)
return 0; return 0;
#endif
return 1; return 1;
} }
...@@ -2096,6 +2098,7 @@ static int __init alsa_card_opti9xx_init(void) ...@@ -2096,6 +2098,7 @@ static int __init alsa_card_opti9xx_init(void)
pnp_register_card_driver(&opti9xx_pnpc_driver); pnp_register_card_driver(&opti9xx_pnpc_driver);
if (snd_opti9xx_pnp_is_probed) if (snd_opti9xx_pnp_is_probed)
return 0; return 0;
pnp_unregister_card_driver(&opti9xx_pnpc_driver);
#endif #endif
return isa_register_driver(&snd_opti9xx_driver, 1); return isa_register_driver(&snd_opti9xx_driver, 1);
} }
......
...@@ -22,14 +22,13 @@ snd-es968-objs := es968.o ...@@ -22,14 +22,13 @@ snd-es968-objs := es968.o
sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1))) sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
# Toplevel Module Dependency # Toplevel Module Dependency
obj-$(CONFIG_SND_ALS100) += snd-sb16-dsp.o snd-sb-common.o obj-$(CONFIG_SND_SB_COMMON) += snd-sb-common.o
obj-$(CONFIG_SND_CMI8330) += snd-sb16-dsp.o snd-sb-common.o obj-$(CONFIG_SND_SB16_DSP) += snd-sb16-dsp.o
obj-$(CONFIG_SND_DT019X) += snd-sb16-dsp.o snd-sb-common.o obj-$(CONFIG_SND_SB8_DSP) += snd-sb8-dsp.o
obj-$(CONFIG_SND_SB8) += snd-sb8.o snd-sb8-dsp.o snd-sb-common.o obj-$(CONFIG_SND_SB8) += snd-sb8.o
obj-$(CONFIG_SND_SB16) += snd-sb16.o snd-sb16-dsp.o snd-sb-common.o obj-$(CONFIG_SND_SB16) += snd-sb16.o
obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o snd-sb16-dsp.o snd-sb-common.o obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o
obj-$(CONFIG_SND_ES968) += snd-es968.o snd-sb8-dsp.o snd-sb-common.o obj-$(CONFIG_SND_ES968) += snd-es968.o
obj-$(CONFIG_SND_ALS4000) += snd-sb-common.o
ifeq ($(CONFIG_SND_SB16_CSP),y) ifeq ($(CONFIG_SND_SB16_CSP),y)
obj-$(CONFIG_SND_SB16) += snd-sb16-csp.o obj-$(CONFIG_SND_SB16) += snd-sb16-csp.o
obj-$(CONFIG_SND_SBAWE) += snd-sb16-csp.o obj-$(CONFIG_SND_SBAWE) += snd-sb16-csp.o
......
...@@ -563,6 +563,11 @@ static int snd_sb16_playback_open(struct snd_pcm_substream *substream) ...@@ -563,6 +563,11 @@ static int snd_sb16_playback_open(struct snd_pcm_substream *substream)
__open_ok: __open_ok:
if (chip->hardware == SB_HW_ALS100) if (chip->hardware == SB_HW_ALS100)
runtime->hw.rate_max = 48000; runtime->hw.rate_max = 48000;
if (chip->hardware == SB_HW_CS5530) {
runtime->hw.buffer_bytes_max = 32 * 1024;
runtime->hw.periods_min = 2;
runtime->hw.rate_min = 44100;
}
if (chip->mode & SB_RATE_LOCK) if (chip->mode & SB_RATE_LOCK)
runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate; runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate;
chip->playback_substream = substream; chip->playback_substream = substream;
...@@ -633,6 +638,11 @@ static int snd_sb16_capture_open(struct snd_pcm_substream *substream) ...@@ -633,6 +638,11 @@ static int snd_sb16_capture_open(struct snd_pcm_substream *substream)
__open_ok: __open_ok:
if (chip->hardware == SB_HW_ALS100) if (chip->hardware == SB_HW_ALS100)
runtime->hw.rate_max = 48000; runtime->hw.rate_max = 48000;
if (chip->hardware == SB_HW_CS5530) {
runtime->hw.buffer_bytes_max = 32 * 1024;
runtime->hw.periods_min = 2;
runtime->hw.rate_min = 44100;
}
if (chip->mode & SB_RATE_LOCK) if (chip->mode & SB_RATE_LOCK)
runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate; runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate;
chip->capture_substream = substream; chip->capture_substream = substream;
......
...@@ -128,7 +128,7 @@ static int snd_sbdsp_probe(struct snd_sb * chip) ...@@ -128,7 +128,7 @@ static int snd_sbdsp_probe(struct snd_sb * chip)
minor = version & 0xff; minor = version & 0xff;
snd_printdd("SB [0x%lx]: DSP chip found, version = %i.%i\n", snd_printdd("SB [0x%lx]: DSP chip found, version = %i.%i\n",
chip->port, major, minor); chip->port, major, minor);
switch (chip->hardware) { switch (chip->hardware) {
case SB_HW_AUTO: case SB_HW_AUTO:
switch (major) { switch (major) {
...@@ -168,6 +168,9 @@ static int snd_sbdsp_probe(struct snd_sb * chip) ...@@ -168,6 +168,9 @@ static int snd_sbdsp_probe(struct snd_sb * chip)
case SB_HW_DT019X: case SB_HW_DT019X:
str = "(DT019X/ALS007)"; str = "(DT019X/ALS007)";
break; break;
case SB_HW_CS5530:
str = "16 (CS5530)";
break;
default: default:
return -ENODEV; return -ENODEV;
} }
......
...@@ -821,6 +821,7 @@ int snd_sbmixer_new(struct snd_sb *chip) ...@@ -821,6 +821,7 @@ int snd_sbmixer_new(struct snd_sb *chip)
break; break;
case SB_HW_16: case SB_HW_16:
case SB_HW_ALS100: case SB_HW_ALS100:
case SB_HW_CS5530:
if ((err = snd_sbmixer_init(chip, if ((err = snd_sbmixer_init(chip,
snd_sb16_controls, snd_sb16_controls,
ARRAY_SIZE(snd_sb16_controls), ARRAY_SIZE(snd_sb16_controls),
...@@ -950,6 +951,7 @@ void snd_sbmixer_suspend(struct snd_sb *chip) ...@@ -950,6 +951,7 @@ void snd_sbmixer_suspend(struct snd_sb *chip)
break; break;
case SB_HW_16: case SB_HW_16:
case SB_HW_ALS100: case SB_HW_ALS100:
case SB_HW_CS5530:
save_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs)); save_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs));
break; break;
case SB_HW_ALS4000: case SB_HW_ALS4000:
...@@ -975,6 +977,7 @@ void snd_sbmixer_resume(struct snd_sb *chip) ...@@ -975,6 +977,7 @@ void snd_sbmixer_resume(struct snd_sb *chip)
break; break;
case SB_HW_16: case SB_HW_16:
case SB_HW_ALS100: case SB_HW_ALS100:
case SB_HW_CS5530:
restore_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs)); restore_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs));
break; break;
case SB_HW_ALS4000: case SB_HW_ALS4000:
......
...@@ -382,7 +382,7 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout) ...@@ -382,7 +382,7 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout)
unsigned long flags; unsigned long flags;
unsigned char x; unsigned char x;
schedule_timeout_interruptible(1); schedule_timeout(1);
spin_lock_irqsave(&s->lock, flags); spin_lock_irqsave(&s->lock, flags);
x = inb(HOST_DATA_IO(s->io_base)); x = inb(HOST_DATA_IO(s->io_base));
...@@ -409,7 +409,7 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout) ...@@ -409,7 +409,7 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout)
unsigned long flags; unsigned long flags;
unsigned char x; unsigned char x;
schedule_timeout_interruptible(1); schedule_timeout(1);
spin_lock_irqsave(&s->lock, flags); spin_lock_irqsave(&s->lock, flags);
x = inb(HOST_DATA_IO(s->io_base)); x = inb(HOST_DATA_IO(s->io_base));
......
...@@ -1780,7 +1780,7 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev, ...@@ -1780,7 +1780,7 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev,
outb (val,port); outb (val,port);
spin_unlock_irq(&dev->irq_lock); spin_unlock_irq(&dev->irq_lock);
while (1) { while (1) {
if ((timeout = schedule_timeout_interruptible(timeout)) == 0) if ((timeout = schedule_timeout(timeout)) == 0)
return; return;
if (dev->irq_ok) if (dev->irq_ok)
return; return;
......
...@@ -33,6 +33,7 @@ config SND_ALS4000 ...@@ -33,6 +33,7 @@ config SND_ALS4000
select SND_OPL3_LIB select SND_OPL3_LIB
select SND_MPU401_UART select SND_MPU401_UART
select SND_PCM select SND_PCM
select SND_SB_COMMON
help help
Say Y here to include support for soundcards based on Avance Logic Say Y here to include support for soundcards based on Avance Logic
ALS4000 chips. ALS4000 chips.
...@@ -215,6 +216,16 @@ config SND_CS46XX_NEW_DSP ...@@ -215,6 +216,16 @@ config SND_CS46XX_NEW_DSP
This works better than the old code, so say Y. This works better than the old code, so say Y.
config SND_CS5530
tristate "CS5530 Audio"
depends on SND && ISA_DMA_API
select SND_SB16_DSP
help
Say Y here to include support for audio on Cyrix/NatSemi CS5530 chips.
To compile this driver as a module, choose M here: the module
will be called snd-cs5530.
config SND_CS5535AUDIO config SND_CS5535AUDIO
tristate "CS5535/CS5536 Audio" tristate "CS5535/CS5536 Audio"
depends on SND && X86 && !X86_64 depends on SND && X86 && !X86_64
......
...@@ -12,6 +12,7 @@ snd-azt3328-objs := azt3328.o ...@@ -12,6 +12,7 @@ snd-azt3328-objs := azt3328.o
snd-bt87x-objs := bt87x.o snd-bt87x-objs := bt87x.o
snd-cmipci-objs := cmipci.o snd-cmipci-objs := cmipci.o
snd-cs4281-objs := cs4281.o snd-cs4281-objs := cs4281.o
snd-cs5530-objs := cs5530.o
snd-ens1370-objs := ens1370.o snd-ens1370-objs := ens1370.o
snd-ens1371-objs := ens1371.o snd-ens1371-objs := ens1371.o
snd-es1938-objs := es1938.o snd-es1938-objs := es1938.o
...@@ -36,6 +37,7 @@ obj-$(CONFIG_SND_AZT3328) += snd-azt3328.o ...@@ -36,6 +37,7 @@ obj-$(CONFIG_SND_AZT3328) += snd-azt3328.o
obj-$(CONFIG_SND_BT87X) += snd-bt87x.o obj-$(CONFIG_SND_BT87X) += snd-bt87x.o
obj-$(CONFIG_SND_CMIPCI) += snd-cmipci.o obj-$(CONFIG_SND_CMIPCI) += snd-cmipci.o
obj-$(CONFIG_SND_CS4281) += snd-cs4281.o obj-$(CONFIG_SND_CS4281) += snd-cs4281.o
obj-$(CONFIG_SND_CS5530) += snd-cs5530.o
obj-$(CONFIG_SND_ENS1370) += snd-ens1370.o obj-$(CONFIG_SND_ENS1370) += snd-ens1370.o
obj-$(CONFIG_SND_ENS1371) += snd-ens1371.o obj-$(CONFIG_SND_ENS1371) += snd-ens1371.o
obj-$(CONFIG_SND_ES1938) += snd-es1938.o obj-$(CONFIG_SND_ES1938) += snd-es1938.o
......
...@@ -239,7 +239,7 @@ struct snd_ali_image { ...@@ -239,7 +239,7 @@ struct snd_ali_image {
struct snd_ali { struct snd_ali {
unsigned long irq; int irq;
unsigned long port; unsigned long port;
unsigned char revision; unsigned char revision;
...@@ -731,8 +731,7 @@ static void snd_ali_detect_spdif_rate(struct snd_ali *codec) ...@@ -731,8 +731,7 @@ static void snd_ali_detect_spdif_rate(struct snd_ali *codec)
return; return;
} }
count = 0; for (count = 0; count <= 50000; count++) {
while (count++ <= 50000) {
snd_ali_delay(codec, 6); snd_ali_delay(codec, 6);
bval = inb(ALI_REG(codec,ALI_SPDIF_CTRL + 1)); bval = inb(ALI_REG(codec,ALI_SPDIF_CTRL + 1));
R2 = bval & 0x1F; R2 = bval & 0x1F;
...@@ -2343,7 +2342,7 @@ static int __devinit snd_ali_probe(struct pci_dev *pci, ...@@ -2343,7 +2342,7 @@ static int __devinit snd_ali_probe(struct pci_dev *pci,
strcpy(card->driver, "ALI5451"); strcpy(card->driver, "ALI5451");
strcpy(card->shortname, "ALI 5451"); strcpy(card->shortname, "ALI 5451");
sprintf(card->longname, "%s at 0x%lx, irq %li", sprintf(card->longname, "%s at 0x%lx, irq %i",
card->shortname, codec->port, codec->irq); card->shortname, codec->port, codec->irq);
snd_ali_printk("register card.\n"); snd_ali_printk("register card.\n");
......
...@@ -88,8 +88,8 @@ ...@@ -88,8 +88,8 @@
#define PLAYBACK_BLOCK_COUNTER 0x9A #define PLAYBACK_BLOCK_COUNTER 0x9A
#define RECORD_BLOCK_COUNTER 0x9B #define RECORD_BLOCK_COUNTER 0x9B
#define DEBUG_CALLS 1 #define DEBUG_CALLS 0
#define DEBUG_PLAY_REC 1 #define DEBUG_PLAY_REC 0
#if DEBUG_CALLS #if DEBUG_CALLS
#define snd_als300_dbgcalls(format, args...) printk(format, ##args) #define snd_als300_dbgcalls(format, args...) printk(format, ##args)
...@@ -733,7 +733,8 @@ static int __devinit snd_als300_create(struct snd_card *card, ...@@ -733,7 +733,8 @@ static int __devinit snd_als300_create(struct snd_card *card,
snd_als300_init(chip); snd_als300_init(chip);
if (snd_als300_ac97(chip) < 0) { err = snd_als300_ac97(chip);
if (err < 0) {
snd_printk(KERN_WARNING "Could not create ac97\n"); snd_printk(KERN_WARNING "Could not create ac97\n");
snd_als300_free(chip); snd_als300_free(chip);
return err; return err;
......
...@@ -168,6 +168,25 @@ MODULE_PARM_DESC(subsystem, "Force card subsystem model."); ...@@ -168,6 +168,25 @@ MODULE_PARM_DESC(subsystem, "Force card subsystem model.");
#include "ca0106.h" #include "ca0106.h"
static struct snd_ca0106_details ca0106_chip_details[] = { static struct snd_ca0106_details ca0106_chip_details[] = {
/* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */
/* It is really just a normal SB Live 24bit. */
/*
* CTRL:CA0111-WTLF
* ADC: WM8775SEDS
* DAC: CS4382-KQZ
*/
/* Tested:
* Playback on front, rear, center/lfe speakers
* Capture from Mic in.
* Not-Tested:
* Capture from Line in.
* Playback to digital out.
*/
{ .serial = 0x10121102,
.name = "X-Fi Extreme Audio [SB0790]",
.gpio_type = 1,
.i2c_adc = 1 } ,
/* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */
/* AudigyLS[SB0310] */ /* AudigyLS[SB0310] */
{ .serial = 0x10021102, { .serial = 0x10021102,
.name = "AudigyLS [SB0310]", .name = "AudigyLS [SB0310]",
......
...@@ -2897,6 +2897,10 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip) ...@@ -2897,6 +2897,10 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
} }
#endif #endif
#ifdef CONFIG_PM
kfree(chip->saved_regs);
#endif
pci_disable_device(chip->pci); pci_disable_device(chip->pci);
kfree(chip); kfree(chip);
return 0; return 0;
...@@ -3140,6 +3144,23 @@ static int snd_cs46xx_chip_init(struct snd_cs46xx *chip) ...@@ -3140,6 +3144,23 @@ static int snd_cs46xx_chip_init(struct snd_cs46xx *chip)
/* /*
* start and load DSP * start and load DSP
*/ */
static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip)
{
unsigned int tmp;
snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM);
tmp = snd_cs46xx_peek(chip, BA1_PFIE);
tmp &= ~0x0000f03f;
snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt enable */
tmp = snd_cs46xx_peek(chip, BA1_CIE);
tmp &= ~0x0000003f;
tmp |= 0x00000001;
snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt enable */
}
int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip) int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
{ {
unsigned int tmp; unsigned int tmp;
...@@ -3214,19 +3235,7 @@ int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip) ...@@ -3214,19 +3235,7 @@ int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
snd_cs46xx_proc_start(chip); snd_cs46xx_proc_start(chip);
/* cs46xx_enable_stream_irqs(chip);
* Enable interrupts on the part.
*/
snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM);
tmp = snd_cs46xx_peek(chip, BA1_PFIE);
tmp &= ~0x0000f03f;
snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt enable */
tmp = snd_cs46xx_peek(chip, BA1_CIE);
tmp &= ~0x0000003f;
tmp |= 0x00000001;
snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt enable */
#ifndef CONFIG_SND_CS46XX_NEW_DSP #ifndef CONFIG_SND_CS46XX_NEW_DSP
/* set the attenuation to 0dB */ /* set the attenuation to 0dB */
...@@ -3665,11 +3674,19 @@ static struct cs_card_type __devinitdata cards[] = { ...@@ -3665,11 +3674,19 @@ static struct cs_card_type __devinitdata cards[] = {
* APM support * APM support
*/ */
#ifdef CONFIG_PM #ifdef CONFIG_PM
static unsigned int saved_regs[] = {
BA0_ACOSV,
BA0_ASER_FADDR,
BA0_ASER_MASTER,
BA1_PVOL,
BA1_CVOL,
};
int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state)
{ {
struct snd_card *card = pci_get_drvdata(pci); struct snd_card *card = pci_get_drvdata(pci);
struct snd_cs46xx *chip = card->private_data; struct snd_cs46xx *chip = card->private_data;
int amp_saved; int i, amp_saved;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
chip->in_suspend = 1; chip->in_suspend = 1;
...@@ -3680,6 +3697,10 @@ int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) ...@@ -3680,6 +3697,10 @@ int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state)
snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
/* save some registers */
for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
chip->saved_regs[i] = snd_cs46xx_peekBA0(chip, saved_regs[i]);
amp_saved = chip->amplifier; amp_saved = chip->amplifier;
/* turn off amp */ /* turn off amp */
chip->amplifier_ctrl(chip, -chip->amplifier); chip->amplifier_ctrl(chip, -chip->amplifier);
...@@ -3698,7 +3719,7 @@ int snd_cs46xx_resume(struct pci_dev *pci) ...@@ -3698,7 +3719,7 @@ int snd_cs46xx_resume(struct pci_dev *pci)
{ {
struct snd_card *card = pci_get_drvdata(pci); struct snd_card *card = pci_get_drvdata(pci);
struct snd_cs46xx *chip = card->private_data; struct snd_cs46xx *chip = card->private_data;
int amp_saved; int i, amp_saved;
pci_set_power_state(pci, PCI_D0); pci_set_power_state(pci, PCI_D0);
pci_restore_state(pci); pci_restore_state(pci);
...@@ -3716,6 +3737,16 @@ int snd_cs46xx_resume(struct pci_dev *pci) ...@@ -3716,6 +3737,16 @@ int snd_cs46xx_resume(struct pci_dev *pci)
snd_cs46xx_chip_init(chip); snd_cs46xx_chip_init(chip);
snd_cs46xx_reset(chip);
#ifdef CONFIG_SND_CS46XX_NEW_DSP
cs46xx_dsp_resume(chip);
/* restore some registers */
for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
snd_cs46xx_pokeBA0(chip, saved_regs[i], chip->saved_regs[i]);
#else
snd_cs46xx_download_image(chip);
#endif
#if 0 #if 0
snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE, snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE,
chip->ac97_general_purpose); chip->ac97_general_purpose);
...@@ -3730,6 +3761,13 @@ int snd_cs46xx_resume(struct pci_dev *pci) ...@@ -3730,6 +3761,13 @@ int snd_cs46xx_resume(struct pci_dev *pci)
snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
/* reset playback/capture */
snd_cs46xx_set_play_sample_rate(chip, 8000);
snd_cs46xx_set_capture_sample_rate(chip, 8000);
snd_cs46xx_proc_start(chip);
cs46xx_enable_stream_irqs(chip);
if (amp_saved) if (amp_saved)
chip->amplifier_ctrl(chip, 1); /* turn amp on */ chip->amplifier_ctrl(chip, 1); /* turn amp on */
else else
...@@ -3896,6 +3934,15 @@ int __devinit snd_cs46xx_create(struct snd_card *card, ...@@ -3896,6 +3934,15 @@ int __devinit snd_cs46xx_create(struct snd_card *card,
snd_cs46xx_proc_init(card, chip); snd_cs46xx_proc_init(card, chip);
#ifdef CONFIG_PM
chip->saved_regs = kmalloc(sizeof(*chip->saved_regs) *
ARRAY_SIZE(saved_regs), GFP_KERNEL);
if (!chip->saved_regs) {
snd_cs46xx_free(chip);
return -ENOMEM;
}
#endif
chip->active_ctrl(chip, -1); /* disable CLKRUN */ chip->active_ctrl(chip, -1); /* disable CLKRUN */
snd_card_set_dev(card, &pci->dev); snd_card_set_dev(card, &pci->dev);
......
...@@ -86,6 +86,9 @@ static inline unsigned int snd_cs46xx_peekBA0(struct snd_cs46xx *chip, unsigned ...@@ -86,6 +86,9 @@ static inline unsigned int snd_cs46xx_peekBA0(struct snd_cs46xx *chip, unsigned
struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip); struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip);
void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip); void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip);
int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module); int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module);
#ifdef CONFIG_PM
int cs46xx_dsp_resume(struct snd_cs46xx * chip);
#endif
struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name,
int symbol_type); int symbol_type);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
......
...@@ -306,13 +306,59 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) ...@@ -306,13 +306,59 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip)
mutex_unlock(&chip->spos_mutex); mutex_unlock(&chip->spos_mutex);
} }
static int dsp_load_parameter(struct snd_cs46xx *chip,
struct dsp_segment_desc *parameter)
{
u32 doffset, dsize;
if (!parameter) {
snd_printdd("dsp_spos: module got no parameter segment\n");
return 0;
}
doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET);
dsize = parameter->size * 4;
snd_printdd("dsp_spos: "
"downloading parameter data to chip (%08x-%08x)\n",
doffset,doffset + dsize);
if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) {
snd_printk(KERN_ERR "dsp_spos: "
"failed to download parameter data to DSP\n");
return -EINVAL;
}
return 0;
}
static int dsp_load_sample(struct snd_cs46xx *chip,
struct dsp_segment_desc *sample)
{
u32 doffset, dsize;
if (!sample) {
snd_printdd("dsp_spos: module got no sample segment\n");
return 0;
}
doffset = (sample->offset * 4 + DSP_SAMPLE_BYTE_OFFSET);
dsize = sample->size * 4;
snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n",
doffset,doffset + dsize);
if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) {
snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n");
return -EINVAL;
}
return 0;
}
int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module) int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module)
{ {
struct dsp_spos_instance * ins = chip->dsp_spos_instance; struct dsp_spos_instance * ins = chip->dsp_spos_instance;
struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM); struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM);
struct dsp_segment_desc * parameter = get_segment_desc (module,SEGTYPE_SP_PARAMETER);
struct dsp_segment_desc * sample = get_segment_desc (module,SEGTYPE_SP_SAMPLE);
u32 doffset, dsize; u32 doffset, dsize;
int err;
if (ins->nmodules == DSP_MAX_MODULES - 1) { if (ins->nmodules == DSP_MAX_MODULES - 1) {
snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n"); snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n");
...@@ -326,49 +372,20 @@ int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * m ...@@ -326,49 +372,20 @@ int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * m
snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE); snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE);
} }
if (parameter == NULL) { err = dsp_load_parameter(chip, get_segment_desc(module,
snd_printdd("dsp_spos: module got no parameter segment\n"); SEGTYPE_SP_PARAMETER));
} else { if (err < 0)
if (ins->nmodules > 0) { return err;
snd_printk(KERN_WARNING "dsp_spos: WARNING current parameter data may be overwriten!\n");
}
doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET);
dsize = parameter->size * 4;
snd_printdd("dsp_spos: downloading parameter data to chip (%08x-%08x)\n",
doffset,doffset + dsize);
if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) {
snd_printk(KERN_ERR "dsp_spos: failed to download parameter data to DSP\n");
return -EINVAL;
}
}
if (ins->nmodules == 0) { if (ins->nmodules == 0) {
snd_printdd("dsp_spos: clearing sample area\n"); snd_printdd("dsp_spos: clearing sample area\n");
snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE); snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE);
} }
if (sample == NULL) { err = dsp_load_sample(chip, get_segment_desc(module,
snd_printdd("dsp_spos: module got no sample segment\n"); SEGTYPE_SP_SAMPLE));
} else { if (err < 0)
if (ins->nmodules > 0) { return err;
snd_printk(KERN_WARNING "dsp_spos: WARNING current sample data may be overwriten\n");
}
doffset = (sample->offset * 4 + DSP_SAMPLE_BYTE_OFFSET);
dsize = sample->size * 4;
snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n",
doffset,doffset + dsize);
if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) {
snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n");
return -EINVAL;
}
}
if (ins->nmodules == 0) { if (ins->nmodules == 0) {
snd_printdd("dsp_spos: clearing code area\n"); snd_printdd("dsp_spos: clearing code area\n");
...@@ -986,7 +1003,10 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size) ...@@ -986,7 +1003,10 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size)
return NULL; return NULL;
} }
strcpy(ins->tasks[ins->ntask].task_name,name); if (name)
strcpy(ins->tasks[ins->ntask].task_name, name);
else
strcpy(ins->tasks[ins->ntask].task_name, "(NULL)");
ins->tasks[ins->ntask].address = dest; ins->tasks[ins->ntask].address = dest;
ins->tasks[ins->ntask].size = size; ins->tasks[ins->ntask].size = size;
...@@ -995,7 +1015,8 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size) ...@@ -995,7 +1015,8 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size)
desc = (ins->tasks + ins->ntask); desc = (ins->tasks + ins->ntask);
ins->ntask++; ins->ntask++;
add_symbol (chip,name,dest,SYMBOL_PARAMETER); if (name)
add_symbol (chip,name,dest,SYMBOL_PARAMETER);
return desc; return desc;
} }
...@@ -1006,6 +1027,7 @@ cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 ...@@ -1006,6 +1027,7 @@ cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32
desc = _map_scb (chip,name,dest); desc = _map_scb (chip,name,dest);
if (desc) { if (desc) {
desc->data = scb_data;
_dsp_create_scb(chip,scb_data,dest); _dsp_create_scb(chip,scb_data,dest);
} else { } else {
snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n");
...@@ -1023,6 +1045,7 @@ cs46xx_dsp_create_task_tree (struct snd_cs46xx *chip, char * name, u32 * task_da ...@@ -1023,6 +1045,7 @@ cs46xx_dsp_create_task_tree (struct snd_cs46xx *chip, char * name, u32 * task_da
desc = _map_task_tree (chip,name,dest,size); desc = _map_task_tree (chip,name,dest,size);
if (desc) { if (desc) {
desc->data = task_data;
_dsp_create_task_tree(chip,task_data,dest,size); _dsp_create_task_tree(chip,task_data,dest,size);
} else { } else {
snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n"); snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n");
...@@ -1320,8 +1343,10 @@ int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip) ...@@ -1320,8 +1343,10 @@ int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip)
0x0000ffff 0x0000ffff
}; };
/* dirty hack ... */ if (!cs46xx_dsp_create_task_tree(chip, NULL,
_dsp_create_task_tree (chip,(u32 *)&mix2_ostream_spb,WRITE_BACK_SPB,2); (u32 *)&mix2_ostream_spb,
WRITE_BACK_SPB, 2))
goto _fail_end;
} }
/* input sample converter */ /* input sample converter */
...@@ -1622,7 +1647,6 @@ static int cs46xx_dsp_async_init (struct snd_cs46xx *chip, ...@@ -1622,7 +1647,6 @@ static int cs46xx_dsp_async_init (struct snd_cs46xx *chip,
return 0; return 0;
} }
static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip) static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip)
{ {
struct dsp_spos_instance * ins = chip->dsp_spos_instance; struct dsp_spos_instance * ins = chip->dsp_spos_instance;
...@@ -1894,3 +1918,61 @@ int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right) ...@@ -1894,3 +1918,61 @@ int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right)
return 0; return 0;
} }
#ifdef CONFIG_PM
int cs46xx_dsp_resume(struct snd_cs46xx * chip)
{
struct dsp_spos_instance * ins = chip->dsp_spos_instance;
int i, err;
/* clear parameter, sample and code areas */
snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET,
DSP_PARAMETER_BYTE_SIZE);
snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET,
DSP_SAMPLE_BYTE_SIZE);
snd_cs46xx_clear_BA1(chip, DSP_CODE_BYTE_OFFSET, DSP_CODE_BYTE_SIZE);
for (i = 0; i < ins->nmodules; i++) {
struct dsp_module_desc *module = &ins->modules[i];
struct dsp_segment_desc *seg;
u32 doffset, dsize;
seg = get_segment_desc(module, SEGTYPE_SP_PARAMETER);
err = dsp_load_parameter(chip, seg);
if (err < 0)
return err;
seg = get_segment_desc(module, SEGTYPE_SP_SAMPLE);
err = dsp_load_sample(chip, seg);
if (err < 0)
return err;
seg = get_segment_desc(module, SEGTYPE_SP_PROGRAM);
if (!seg)
continue;
doffset = seg->offset * 4 + module->load_address * 4
+ DSP_CODE_BYTE_OFFSET;
dsize = seg->size * 4;
err = snd_cs46xx_download(chip,
ins->code.data + module->load_address,
doffset, dsize);
if (err < 0)
return err;
}
for (i = 0; i < ins->ntask; i++) {
struct dsp_task_descriptor *t = &ins->tasks[i];
_dsp_create_task_tree(chip, t->data, t->address, t->size);
}
for (i = 0; i < ins->nscb; i++) {
struct dsp_scb_descriptor *s = &ins->scbs[i];
if (s->deleted)
continue;
_dsp_create_scb(chip, s->data, s->address);
}
return 0;
}
#endif
/*
* cs5530.c - Initialisation code for Cyrix/NatSemi VSA1 softaudio
*
* (C) Copyright 2007 Ash Willis <ashwillis@programmer.net>
* (C) Copyright 2003 Red Hat Inc <alan@redhat.com>
*
* This driver was ported (shamelessly ripped ;) from oss/kahlua.c but I did
* mess with it a bit. The chip seems to have to have trouble with full duplex
* mode. If we're recording in 8bit 8000kHz, say, and we then attempt to
* simultaneously play back audio at 16bit 44100kHz, the device actually plays
* back in the same format in which it is capturing. By forcing the chip to
* always play/capture in 16/44100, we can let alsa-lib convert the samples and
* that way we can hack up some full duplex audio.
*
* XpressAudio(tm) is used on the Cyrix MediaGX (now NatSemi Geode) systems.
* The older version (VSA1) provides fairly good soundblaster emulation
* although there are a couple of bugs: large DMA buffers break record,
* and the MPU event handling seems suspect. VSA2 allows the native driver
* to control the AC97 audio engine directly and requires a different driver.
*
* Thanks to National Semiconductor for providing the needed information
* on the XpressAudio(tm) internals.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* TO DO:
* Investigate whether we can portably support Cognac (5520) in the
* same manner.
*/
#include <sound/driver.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <sound/core.h>
#include <sound/sb.h>
#include <sound/initval.h>
MODULE_AUTHOR("Ash Willis");
MODULE_DESCRIPTION("CS5530 Audio");
MODULE_LICENSE("GPL");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
struct snd_cs5530 {
struct snd_card *card;
struct pci_dev *pci;
struct snd_sb *sb;
unsigned long pci_base;
};
static struct pci_device_id snd_cs5530_ids[] = {
{PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO, PCI_ANY_ID,
PCI_ANY_ID, 0, 0},
{0,}
};
MODULE_DEVICE_TABLE(pci, snd_cs5530_ids);
static int snd_cs5530_free(struct snd_cs5530 *chip)
{
pci_release_regions(chip->pci);
pci_disable_device(chip->pci);
kfree(chip);
return 0;
}
static int snd_cs5530_dev_free(struct snd_device *device)
{
struct snd_cs5530 *chip = device->device_data;
return snd_cs5530_free(chip);
}
static void __devexit snd_cs5530_remove(struct pci_dev *pci)
{
snd_card_free(pci_get_drvdata(pci));
pci_set_drvdata(pci, NULL);
}
static u8 __devinit snd_cs5530_mixer_read(unsigned long io, u8 reg)
{
outb(reg, io + 4);
udelay(20);
reg = inb(io + 5);
udelay(20);
return reg;
}
static int __devinit snd_cs5530_create(struct snd_card *card,
struct pci_dev *pci,
struct snd_cs5530 **rchip)
{
struct snd_cs5530 *chip;
unsigned long sb_base;
u8 irq, dma8, dma16 = 0;
u16 map;
void __iomem *mem;
int err;
static struct snd_device_ops ops = {
.dev_free = snd_cs5530_dev_free,
};
*rchip = NULL;
err = pci_enable_device(pci);
if (err < 0)
return err;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
pci_disable_device(pci);
return -ENOMEM;
}
chip->card = card;
chip->pci = pci;
err = pci_request_regions(pci, "CS5530");
if (err < 0) {
kfree(chip);
pci_disable_device(pci);
return err;
}
chip->pci_base = pci_resource_start(pci, 0);
mem = ioremap_nocache(chip->pci_base, pci_resource_len(pci, 0));
if (mem == NULL) {
kfree(chip);
pci_disable_device(pci);
return -EBUSY;
}
map = readw(mem + 0x18);
iounmap(mem);
/* Map bits
0:1 * 0x20 + 0x200 = sb base
2 sb enable
3 adlib enable
5 MPU enable 0x330
6 MPU enable 0x300
The other bits may be used internally so must be masked */
sb_base = 0x220 + 0x20 * (map & 3);
if (map & (1<<2))
printk(KERN_INFO "CS5530: XpressAudio at 0x%lx\n", sb_base);
else {
printk(KERN_ERR "Could not find XpressAudio!\n");
snd_cs5530_free(chip);
return -ENODEV;
}
if (map & (1<<5))
printk(KERN_INFO "CS5530: MPU at 0x300\n");
else if (map & (1<<6))
printk(KERN_INFO "CS5530: MPU at 0x330\n");
irq = snd_cs5530_mixer_read(sb_base, 0x80) & 0x0F;
dma8 = snd_cs5530_mixer_read(sb_base, 0x81);
if (dma8 & 0x20)
dma16 = 5;
else if (dma8 & 0x40)
dma16 = 6;
else if (dma8 & 0x80)
dma16 = 7;
else {
printk(KERN_ERR "CS5530: No 16bit DMA enabled\n");
snd_cs5530_free(chip);
return -ENODEV;
}
if (dma8 & 0x01)
dma8 = 0;
else if (dma8 & 02)
dma8 = 1;
else if (dma8 & 0x08)
dma8 = 3;
else {
printk(KERN_ERR "CS5530: No 8bit DMA enabled\n");
snd_cs5530_free(chip);
return -ENODEV;
}
if (irq & 1)
irq = 9;
else if (irq & 2)
irq = 5;
else if (irq & 4)
irq = 7;
else if (irq & 8)
irq = 10;
else {
printk(KERN_ERR "CS5530: SoundBlaster IRQ not set\n");
snd_cs5530_free(chip);
return -ENODEV;
}
printk(KERN_INFO "CS5530: IRQ: %d DMA8: %d DMA16: %d\n", irq, dma8,
dma16);
err = snd_sbdsp_create(card, sb_base, irq, snd_sb16dsp_interrupt, dma8,
dma16, SB_HW_CS5530, &chip->sb);
if (err < 0) {
printk(KERN_ERR "CS5530: Could not create SoundBlaster\n");
snd_cs5530_free(chip);
return err;
}
err = snd_sb16dsp_pcm(chip->sb, 0, &chip->sb->pcm);
if (err < 0) {
printk(KERN_ERR "CS5530: Could not create PCM\n");
snd_cs5530_free(chip);
return err;
}
err = snd_sbmixer_new(chip->sb);
if (err < 0) {
printk(KERN_ERR "CS5530: Could not create Mixer\n");
snd_cs5530_free(chip);
return err;
}
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err < 0) {
snd_cs5530_free(chip);
return err;
}
snd_card_set_dev(card, &pci->dev);
*rchip = chip;
return 0;
}
static int __devinit snd_cs5530_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
struct snd_card *card;
struct snd_cs5530 *chip = NULL;
int err;
if (dev >= SNDRV_CARDS)
return -ENODEV;
if (!enable[dev]) {
dev++;
return -ENOENT;
}
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
if (card == NULL)
return -ENOMEM;
err = snd_cs5530_create(card, pci, &chip);
if (err < 0) {
snd_card_free(card);
return err;
}
strcpy(card->driver, "CS5530");
strcpy(card->shortname, "CS5530 Audio");
sprintf(card->longname, "%s at 0x%lx", card->shortname, chip->pci_base);
err = snd_card_register(card);
if (err < 0) {
snd_card_free(card);
return err;
}
pci_set_drvdata(pci, card);
dev++;
return 0;
}
static struct pci_driver driver = {
.name = "CS5530_Audio",
.id_table = snd_cs5530_ids,
.probe = snd_cs5530_probe,
.remove = __devexit_p(snd_cs5530_remove),
};
static int __init alsa_card_cs5530_init(void)
{
return pci_register_driver(&driver);
}
static void __exit alsa_card_cs5530_exit(void)
{
pci_unregister_driver(&driver);
}
module_init(alsa_card_cs5530_init)
module_exit(alsa_card_cs5530_exit)
...@@ -51,9 +51,15 @@ ...@@ -51,9 +51,15 @@
#define HANA_FILENAME "emu/hana.fw" #define HANA_FILENAME "emu/hana.fw"
#define DOCK_FILENAME "emu/audio_dock.fw" #define DOCK_FILENAME "emu/audio_dock.fw"
#define EMU1010B_FILENAME "emu/emu1010b.fw"
#define MICRO_DOCK_FILENAME "emu/micro_dock.fw"
#define EMU1010_NOTEBOOK_FILENAME "emu/emu1010_notebook.fw"
MODULE_FIRMWARE(HANA_FILENAME); MODULE_FIRMWARE(HANA_FILENAME);
MODULE_FIRMWARE(DOCK_FILENAME); MODULE_FIRMWARE(DOCK_FILENAME);
MODULE_FIRMWARE(EMU1010B_FILENAME);
MODULE_FIRMWARE(MICRO_DOCK_FILENAME);
MODULE_FIRMWARE(EMU1010_NOTEBOOK_FILENAME);
/************************************************************************* /*************************************************************************
...@@ -660,10 +666,12 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file ...@@ -660,10 +666,12 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file
return err; return err;
} }
snd_printk(KERN_INFO "firmware size=0x%zx\n", fw_entry->size); snd_printk(KERN_INFO "firmware size=0x%zx\n", fw_entry->size);
#if 0
if (fw_entry->size != 0x133a4) { if (fw_entry->size != 0x133a4) {
snd_printk(KERN_ERR "firmware: %s wrong size.\n",filename); snd_printk(KERN_ERR "firmware: %s wrong size.\n",filename);
return -EINVAL; return -EINVAL;
} }
#endif
/* The FPGA is a Xilinx Spartan IIE XC2S50E */ /* The FPGA is a Xilinx Spartan IIE XC2S50E */
/* GPIO7 -> FPGA PGMN /* GPIO7 -> FPGA PGMN
...@@ -694,6 +702,37 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file ...@@ -694,6 +702,37 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file
return 0; return 0;
} }
/*
* EMU-1010 - details found out from this driver, official MS Win drivers,
* testing the card:
*
* Audigy2 (aka Alice2):
* ---------------------
* * communication over PCI
* * conversion of 32-bit data coming over EMU32 links from HANA FPGA
* to 2 x 16-bit, using internal DSP instructions
* * slave mode, clock supplied by HANA
* * linked to HANA using:
* 32 x 32-bit serial EMU32 output channels
* 16 x EMU32 input channels
* (?) x I2S I/O channels (?)
*
* FPGA (aka HANA):
* ---------------
* * provides all (?) physical inputs and outputs of the card
* (ADC, DAC, SPDIF I/O, ADAT I/O, etc.)
* * provides clock signal for the card and Alice2
* * two crystals - for 44.1kHz and 48kHz multiples
* * provides internal routing of signal sources to signal destinations
* * inputs/outputs to Alice2 - see above
*
* Current status of the driver:
* ----------------------------
* * only 44.1/48kHz supported (the MS Win driver supports up to 192 kHz)
* * PCM device nb. 2:
* 16 x 16-bit playback - snd_emu10k1_fx8010_playback_ops
* 16 x 32-bit capture - snd_emu10k1_capture_efx_ops
*/
static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
{ {
unsigned int i; unsigned int i;
...@@ -727,7 +766,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) ...@@ -727,7 +766,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
/* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */ /* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */
snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg ); snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
snd_printdd("reg1=0x%x\n",reg); snd_printdd("reg1=0x%x\n",reg);
if (reg == 0x55) { if ((reg & 0x3f) == 0x15) {
/* FPGA netlist already present so clear it */ /* FPGA netlist already present so clear it */
/* Return to programming mode */ /* Return to programming mode */
...@@ -735,19 +774,32 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) ...@@ -735,19 +774,32 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
} }
snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg ); snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
snd_printdd("reg2=0x%x\n",reg); snd_printdd("reg2=0x%x\n",reg);
if (reg == 0x55) { if ((reg & 0x3f) == 0x15) {
/* FPGA failed to return to programming mode */ /* FPGA failed to return to programming mode */
snd_printk(KERN_INFO "emu1010: FPGA failed to return to programming mode\n");
return -ENODEV; return -ENODEV;
} }
snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg); snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg);
if ((err = snd_emu1010_load_firmware(emu, HANA_FILENAME)) != 0) { if (emu->card_capabilities->emu1010 == 1) {
snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file %s failed\n", HANA_FILENAME); if ((err = snd_emu1010_load_firmware(emu, HANA_FILENAME)) != 0) {
return err; snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file %s failed\n", HANA_FILENAME);
return err;
}
} else if (emu->card_capabilities->emu1010 == 2) {
if ((err = snd_emu1010_load_firmware(emu, EMU1010B_FILENAME)) != 0) {
snd_printk(KERN_INFO "emu1010: Loading Firmware file %s failed\n", EMU1010B_FILENAME);
return err;
}
} else if (emu->card_capabilities->emu1010 == 3) {
if ((err = snd_emu1010_load_firmware(emu, EMU1010_NOTEBOOK_FILENAME)) != 0) {
snd_printk(KERN_INFO "emu1010: Loading Firmware file %s failed\n", EMU1010_NOTEBOOK_FILENAME);
return err;
}
} }
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */ /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg ); snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
if (reg != 0x55) { if ((reg & 0x3f) != 0x15) {
/* FPGA failed to be programmed */ /* FPGA failed to be programmed */
snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg=0x%x\n", reg); snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg=0x%x\n", reg);
return -ENODEV; return -ENODEV;
...@@ -850,6 +902,27 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) ...@@ -850,6 +902,27 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
EMU_DST_ALICE2_EMU32_6, EMU_SRC_DOCK_ADC2_LEFT1); EMU_DST_ALICE2_EMU32_6, EMU_SRC_DOCK_ADC2_LEFT1);
snd_emu1010_fpga_link_dst_src_write(emu, snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE2_EMU32_7, EMU_SRC_DOCK_ADC2_RIGHT1); EMU_DST_ALICE2_EMU32_7, EMU_SRC_DOCK_ADC2_RIGHT1);
/* Pavel Hofman - setting defaults for 8 more capture channels
* Defaults only, users will set their own values anyways, let's
* just copy/paste.
*/
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE2_EMU32_8, EMU_SRC_DOCK_MIC_A1);
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE2_EMU32_9, EMU_SRC_DOCK_MIC_B1);
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE2_EMU32_A, EMU_SRC_HAMOA_ADC_LEFT2);
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE2_EMU32_B, EMU_SRC_HAMOA_ADC_LEFT2);
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE2_EMU32_C, EMU_SRC_DOCK_ADC1_LEFT1);
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE2_EMU32_D, EMU_SRC_DOCK_ADC1_RIGHT1);
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE2_EMU32_E, EMU_SRC_DOCK_ADC2_LEFT1);
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE2_EMU32_F, EMU_SRC_DOCK_ADC2_RIGHT1);
#endif #endif
#if 0 #if 0
/* Original */ /* Original */
...@@ -943,16 +1016,27 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) ...@@ -943,16 +1016,27 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
/* Return to Audio Dock programming mode */ /* Return to Audio Dock programming mode */
snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK ); snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK );
if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) { if (emu->card_capabilities->emu1010 == 1) {
return err; if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) {
return err;
}
} else if (emu->card_capabilities->emu1010 == 2) {
if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) {
return err;
}
} else if (emu->card_capabilities->emu1010 == 3) {
if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) {
return err;
}
} }
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 ); snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 );
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg ); snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg );
snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg); snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg);
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */ /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg ); snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg); snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg);
if (reg != 0x55) { if ((reg & 0x3f) != 0x15) {
/* FPGA failed to be programmed */ /* FPGA failed to be programmed */
snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg); snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg);
return 0; return 0;
...@@ -1227,9 +1311,15 @@ static struct snd_emu_chip_details emu_chip_details[] = { ...@@ -1227,9 +1311,15 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.emu10k2_chip = 1, .emu10k2_chip = 1,
.ca0108_chip = 1, .ca0108_chip = 1,
.ca_cardbus_chip = 1, .ca_cardbus_chip = 1,
.spi_dac = 1, .spk71 = 1 ,
.i2c_adc = 1, .emu1010 = 3} ,
.spk71 = 1} , {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102,
.driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM????]",
.id = "EMU1010",
.emu10k2_chip = 1,
.ca0108_chip = 1,
.spk71 = 1 ,
.emu1010 = 2} ,
{.vendor = 0x1102, .device = 0x0008, {.vendor = 0x1102, .device = 0x0008,
.driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]",
.id = "Audigy2", .id = "Audigy2",
...@@ -1663,12 +1753,13 @@ int __devinit snd_emu10k1_create(struct snd_card *card, ...@@ -1663,12 +1753,13 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
emu->fx8010.extout_mask = extout_mask; emu->fx8010.extout_mask = extout_mask;
emu->enable_ir = enable_ir; emu->enable_ir = enable_ir;
if (emu->card_capabilities->ca_cardbus_chip) {
if ((err = snd_emu10k1_cardbus_init(emu)) < 0)
goto error;
}
if (emu->card_capabilities->ecard) { if (emu->card_capabilities->ecard) {
if ((err = snd_emu10k1_ecard_init(emu)) < 0) if ((err = snd_emu10k1_ecard_init(emu)) < 0)
goto error; goto error;
} else if (emu->card_capabilities->ca_cardbus_chip) {
if ((err = snd_emu10k1_cardbus_init(emu)) < 0)
goto error;
} else if (emu->card_capabilities->emu1010) { } else if (emu->card_capabilities->emu1010) {
if ((err = snd_emu10k1_emu1010_init(emu)) < 0) { if ((err = snd_emu10k1_emu1010_init(emu)) < 0) {
snd_emu10k1_free(emu); snd_emu10k1_free(emu);
...@@ -1814,10 +1905,10 @@ void snd_emu10k1_suspend_regs(struct snd_emu10k1 *emu) ...@@ -1814,10 +1905,10 @@ void snd_emu10k1_suspend_regs(struct snd_emu10k1 *emu)
void snd_emu10k1_resume_init(struct snd_emu10k1 *emu) void snd_emu10k1_resume_init(struct snd_emu10k1 *emu)
{ {
if (emu->card_capabilities->ca_cardbus_chip)
snd_emu10k1_cardbus_init(emu);
if (emu->card_capabilities->ecard) if (emu->card_capabilities->ecard)
snd_emu10k1_ecard_init(emu); snd_emu10k1_ecard_init(emu);
else if (emu->card_capabilities->ca_cardbus_chip)
snd_emu10k1_cardbus_init(emu);
else if (emu->card_capabilities->emu1010) else if (emu->card_capabilities->emu1010)
snd_emu10k1_emu1010_init(emu); snd_emu10k1_emu1010_init(emu);
else else
......
...@@ -1123,6 +1123,11 @@ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl ...@@ -1123,6 +1123,11 @@ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl
ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF; ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
} }
/*
* Used for emu1010 - conversion from 32-bit capture inputs from HANA
* to 2 x 16-bit registers in audigy - their values are read via DMA.
* Conversion is performed by Audigy DSP instructions of FX8010.
*/
static int snd_emu10k1_audigy_dsp_convert_32_to_2x16( static int snd_emu10k1_audigy_dsp_convert_32_to_2x16(
struct snd_emu10k1_fx8010_code *icode, struct snd_emu10k1_fx8010_code *icode,
u32 *ptr, int tmp, int bit_shifter16, u32 *ptr, int tmp, int bit_shifter16,
...@@ -1193,7 +1198,11 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) ...@@ -1193,7 +1198,11 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP); snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
#if 1 #if 1
/* PCM front Playback Volume (independent from stereo mix) */ /* PCM front Playback Volume (independent from stereo mix)
* playback = 0 + ( gpr * FXBUS_PCM_LEFT_FRONT >> 31)
* where gpr contains attenuation from corresponding mixer control
* (snd_emu10k1_init_stereo_control)
*/
A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT)); A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT));
A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT)); A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT));
snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100); snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100);
...@@ -1549,7 +1558,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) ...@@ -1549,7 +1558,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
if (emu->card_capabilities->emu1010) { if (emu->card_capabilities->emu1010) {
snd_printk("EMU inputs on\n"); snd_printk("EMU inputs on\n");
/* Capture 8 channels of S32_LE sound */ /* Capture 16 (originally 8) channels of S32_LE sound */
/* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */ /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */
/* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */
...@@ -1560,6 +1569,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) ...@@ -1560,6 +1569,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) ); snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) );
/* Right ADC in 1 of 2 */ /* Right ADC in 1 of 2 */
gpr_map[gpr++] = 0x00000000; gpr_map[gpr++] = 0x00000000;
/* Delaying by one sample: instead of copying the input
* value A_P16VIN to output A_FXBUS2 as in the first channel,
* we use an auxiliary register, delaying the value by one
* sample
*/
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) ); snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) );
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000); A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000);
gpr_map[gpr++] = 0x00000000; gpr_map[gpr++] = 0x00000000;
...@@ -1583,6 +1597,66 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) ...@@ -1583,6 +1597,66 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
gpr_map[gpr++] = 0x00000000; gpr_map[gpr++] = 0x00000000;
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) ); snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) );
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000); A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000);
/* Pavel Hofman - we still have voices, A_FXBUS2s, and
* A_P16VINs available -
* let's add 8 more capture channels - total of 16
*/
gpr_map[gpr++] = 0x00000000;
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
bit_shifter16,
A_GPR(gpr - 1),
A_FXBUS2(0x10));
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8),
A_C_00000000, A_C_00000000);
gpr_map[gpr++] = 0x00000000;
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
bit_shifter16,
A_GPR(gpr - 1),
A_FXBUS2(0x12));
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9),
A_C_00000000, A_C_00000000);
gpr_map[gpr++] = 0x00000000;
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
bit_shifter16,
A_GPR(gpr - 1),
A_FXBUS2(0x14));
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa),
A_C_00000000, A_C_00000000);
gpr_map[gpr++] = 0x00000000;
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
bit_shifter16,
A_GPR(gpr - 1),
A_FXBUS2(0x16));
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb),
A_C_00000000, A_C_00000000);
gpr_map[gpr++] = 0x00000000;
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
bit_shifter16,
A_GPR(gpr - 1),
A_FXBUS2(0x18));
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc),
A_C_00000000, A_C_00000000);
gpr_map[gpr++] = 0x00000000;
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
bit_shifter16,
A_GPR(gpr - 1),
A_FXBUS2(0x1a));
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd),
A_C_00000000, A_C_00000000);
gpr_map[gpr++] = 0x00000000;
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
bit_shifter16,
A_GPR(gpr - 1),
A_FXBUS2(0x1c));
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe),
A_C_00000000, A_C_00000000);
gpr_map[gpr++] = 0x00000000;
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
bit_shifter16,
A_GPR(gpr - 1),
A_FXBUS2(0x1e));
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf),
A_C_00000000, A_C_00000000);
#if 0 #if 0
for (z = 4; z < 8; z++) { for (z = 4; z < 8; z++) {
......
...@@ -77,6 +77,10 @@ static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol, ...@@ -77,6 +77,10 @@ static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
return 0; return 0;
} }
/*
* Items labels in enum mixer controls assigning source data to
* each destination
*/
static char *emu1010_src_texts[] = { static char *emu1010_src_texts[] = {
"Silence", "Silence",
"Dock Mic A", "Dock Mic A",
...@@ -133,6 +137,9 @@ static char *emu1010_src_texts[] = { ...@@ -133,6 +137,9 @@ static char *emu1010_src_texts[] = {
"DSP 31", "DSP 31",
}; };
/*
* List of data sources available for each destination
*/
static unsigned int emu1010_src_regs[] = { static unsigned int emu1010_src_regs[] = {
EMU_SRC_SILENCE,/* 0 */ EMU_SRC_SILENCE,/* 0 */
EMU_SRC_DOCK_MIC_A1, /* 1 */ EMU_SRC_DOCK_MIC_A1, /* 1 */
...@@ -189,6 +196,10 @@ static unsigned int emu1010_src_regs[] = { ...@@ -189,6 +196,10 @@ static unsigned int emu1010_src_regs[] = {
EMU_SRC_ALICE_EMU32B+0xf, /* 52 */ EMU_SRC_ALICE_EMU32B+0xf, /* 52 */
}; };
/*
* Data destinations - physical EMU outputs.
* Each destination has an enum mixer control to choose a data source
*/
static unsigned int emu1010_output_dst[] = { static unsigned int emu1010_output_dst[] = {
EMU_DST_DOCK_DAC1_LEFT1, /* 0 */ EMU_DST_DOCK_DAC1_LEFT1, /* 0 */
EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */ EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */
...@@ -216,6 +227,11 @@ static unsigned int emu1010_output_dst[] = { ...@@ -216,6 +227,11 @@ static unsigned int emu1010_output_dst[] = {
EMU_DST_HANA_ADAT+7, /* 23 */ EMU_DST_HANA_ADAT+7, /* 23 */
}; };
/*
* Data destinations - HANA outputs going to Alice2 (audigy) for
* capture (EMU32 + I2S links)
* Each destination has an enum mixer control to choose a data source
*/
static unsigned int emu1010_input_dst[] = { static unsigned int emu1010_input_dst[] = {
EMU_DST_ALICE2_EMU32_0, EMU_DST_ALICE2_EMU32_0,
EMU_DST_ALICE2_EMU32_1, EMU_DST_ALICE2_EMU32_1,
......
...@@ -1233,24 +1233,26 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) ...@@ -1233,24 +1233,26 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream)
runtime->hw.rate_min = runtime->hw.rate_max = 48000; runtime->hw.rate_min = runtime->hw.rate_max = 48000;
spin_lock_irq(&emu->reg_lock); spin_lock_irq(&emu->reg_lock);
if (emu->card_capabilities->emu1010) { if (emu->card_capabilities->emu1010) {
/* TODO /* Nb. of channels has been increased to 16 */
/* TODO
* SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE * SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE
* SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | * SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
* SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | * SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
* SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 * SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000
* rate_min = 44100, * rate_min = 44100,
* rate_max = 192000, * rate_max = 192000,
* channels_min = 8, * channels_min = 16,
* channels_max = 8, * channels_max = 16,
* Need to add mixer control to fix sample rate * Need to add mixer control to fix sample rate
* *
* There are 16 mono channels of 16bits each. * There are 32 mono channels of 16bits each.
* 24bit Audio uses 2x channels over 16bit * 24bit Audio uses 2x channels over 16bit
* 96kHz uses 2x channels over 48kHz * 96kHz uses 2x channels over 48kHz
* 192kHz uses 4x channels over 48kHz * 192kHz uses 4x channels over 48kHz
* So, for 48kHz 24bit, one has 8 channels * So, for 48kHz 24bit, one has 16 channels
* for 96kHz 24bit, one has 4 channels * for 96kHz 24bit, one has 8 channels
* for 192kHz 24bit, one has 2 channels * for 192kHz 24bit, one has 4 channels
*
*/ */
#if 1 #if 1
switch (emu->emu1010.internal_clock) { switch (emu->emu1010.internal_clock) {
...@@ -1258,13 +1260,15 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) ...@@ -1258,13 +1260,15 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream)
/* For 44.1kHz */ /* For 44.1kHz */
runtime->hw.rates = SNDRV_PCM_RATE_44100; runtime->hw.rates = SNDRV_PCM_RATE_44100;
runtime->hw.rate_min = runtime->hw.rate_max = 44100; runtime->hw.rate_min = runtime->hw.rate_max = 44100;
runtime->hw.channels_min = runtime->hw.channels_max = 8; runtime->hw.channels_min =
runtime->hw.channels_max = 16;
break; break;
case 1: case 1:
/* For 48kHz */ /* For 48kHz */
runtime->hw.rates = SNDRV_PCM_RATE_48000; runtime->hw.rates = SNDRV_PCM_RATE_48000;
runtime->hw.rate_min = runtime->hw.rate_max = 48000; runtime->hw.rate_min = runtime->hw.rate_max = 48000;
runtime->hw.channels_min = runtime->hw.channels_max = 8; runtime->hw.channels_min =
runtime->hw.channels_max = 16;
break; break;
}; };
#endif #endif
...@@ -1282,7 +1286,7 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) ...@@ -1282,7 +1286,7 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream)
#endif #endif
runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE; runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
/* efx_voices_mask[0] is expected to be zero /* efx_voices_mask[0] is expected to be zero
* efx_voices_mask[1] is expected to have 16bits set * efx_voices_mask[1] is expected to have 32bits set
*/ */
} else { } else {
runtime->hw.channels_min = runtime->hw.channels_max = 0; runtime->hw.channels_min = runtime->hw.channels_max = 0;
...@@ -1787,11 +1791,24 @@ int __devinit snd_emu10k1_pcm_efx(struct snd_emu10k1 * emu, int device, struct s ...@@ -1787,11 +1791,24 @@ int __devinit snd_emu10k1_pcm_efx(struct snd_emu10k1 * emu, int device, struct s
/* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */ /* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */
if (emu->audigy) { if (emu->audigy) {
emu->efx_voices_mask[0] = 0; emu->efx_voices_mask[0] = 0;
emu->efx_voices_mask[1] = 0xffff; if (emu->card_capabilities->emu1010)
/* Pavel Hofman - 32 voices will be used for
* capture (write mode) -
* each bit = corresponding voice
*/
emu->efx_voices_mask[1] = 0xffffffff;
else
emu->efx_voices_mask[1] = 0xffff;
} else { } else {
emu->efx_voices_mask[0] = 0xffff0000; emu->efx_voices_mask[0] = 0xffff0000;
emu->efx_voices_mask[1] = 0; emu->efx_voices_mask[1] = 0;
} }
/* For emu1010, the control has to set 32 upper bits (voices)
* out of the 64 bits (voices) to true for the 16-channels capture
* to work correctly. Correct A_FXWC2 initial value (0xffffffff)
* is already defined but the snd_emu10k1_pcm_efx_voices_mask
* control can override this register's value.
*/
kctl = snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu); kctl = snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu);
if (!kctl) if (!kctl)
return -ENOMEM; return -ENOMEM;
......
...@@ -1607,8 +1607,8 @@ struct es1371_quirk { ...@@ -1607,8 +1607,8 @@ struct es1371_quirk {
unsigned char rev; /* revision */ unsigned char rev; /* revision */
}; };
static int __devinit es1371_quirk_lookup(struct ensoniq *ensoniq, static int es1371_quirk_lookup(struct ensoniq *ensoniq,
struct es1371_quirk *list) struct es1371_quirk *list)
{ {
while (list->vid != (unsigned short)PCI_ANY_ID) { while (list->vid != (unsigned short)PCI_ANY_ID) {
if (ensoniq->pci->vendor == list->vid && if (ensoniq->pci->vendor == list->vid &&
......
...@@ -341,6 +341,9 @@ struct azx { ...@@ -341,6 +341,9 @@ struct azx {
unsigned int single_cmd :1; unsigned int single_cmd :1;
unsigned int polling_mode :1; unsigned int polling_mode :1;
unsigned int msi :1; unsigned int msi :1;
/* for debugging */
unsigned int last_cmd; /* last issued command (to sync) */
}; };
/* driver types */ /* driver types */
...@@ -466,18 +469,10 @@ static void azx_free_cmd_io(struct azx *chip) ...@@ -466,18 +469,10 @@ static void azx_free_cmd_io(struct azx *chip)
} }
/* send a command */ /* send a command */
static int azx_corb_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, static int azx_corb_send_cmd(struct hda_codec *codec, u32 val)
unsigned int verb, unsigned int para)
{ {
struct azx *chip = codec->bus->private_data; struct azx *chip = codec->bus->private_data;
unsigned int wp; unsigned int wp;
u32 val;
val = (u32)(codec->addr & 0x0f) << 28;
val |= (u32)direct << 27;
val |= (u32)nid << 20;
val |= verb << 8;
val |= para;
/* add command to corb */ /* add command to corb */
wp = azx_readb(chip, CORBWP); wp = azx_readb(chip, CORBWP);
...@@ -538,12 +533,12 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) ...@@ -538,12 +533,12 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
} }
if (! chip->rirb.cmds) if (! chip->rirb.cmds)
return chip->rirb.res; /* the last value */ return chip->rirb.res; /* the last value */
schedule_timeout_interruptible(1); schedule_timeout(1);
} while (time_after_eq(timeout, jiffies)); } while (time_after_eq(timeout, jiffies));
if (chip->msi) { if (chip->msi) {
snd_printk(KERN_WARNING "hda_intel: No response from codec, " snd_printk(KERN_WARNING "hda_intel: No response from codec, "
"disabling MSI...\n"); "disabling MSI: last cmd=0x%08x\n", chip->last_cmd);
free_irq(chip->irq, chip); free_irq(chip->irq, chip);
chip->irq = -1; chip->irq = -1;
pci_disable_msi(chip->pci); pci_disable_msi(chip->pci);
...@@ -555,13 +550,15 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) ...@@ -555,13 +550,15 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
if (!chip->polling_mode) { if (!chip->polling_mode) {
snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, " snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, "
"switching to polling mode...\n"); "switching to polling mode: last cmd=0x%08x\n",
chip->last_cmd);
chip->polling_mode = 1; chip->polling_mode = 1;
goto again; goto again;
} }
snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
"switching to single_cmd mode...\n"); "switching to single_cmd mode: last cmd=0x%08x\n",
chip->last_cmd);
chip->rirb.rp = azx_readb(chip, RIRBWP); chip->rirb.rp = azx_readb(chip, RIRBWP);
chip->rirb.cmds = 0; chip->rirb.cmds = 0;
/* switch to single_cmd mode */ /* switch to single_cmd mode */
...@@ -581,20 +578,11 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) ...@@ -581,20 +578,11 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
*/ */
/* send a command */ /* send a command */
static int azx_single_send_cmd(struct hda_codec *codec, hda_nid_t nid, static int azx_single_send_cmd(struct hda_codec *codec, u32 val)
int direct, unsigned int verb,
unsigned int para)
{ {
struct azx *chip = codec->bus->private_data; struct azx *chip = codec->bus->private_data;
u32 val;
int timeout = 50; int timeout = 50;
val = (u32)(codec->addr & 0x0f) << 28;
val |= (u32)direct << 27;
val |= (u32)nid << 20;
val |= verb << 8;
val |= para;
while (timeout--) { while (timeout--) {
/* check ICB busy bit */ /* check ICB busy bit */
if (! (azx_readw(chip, IRS) & ICH6_IRS_BUSY)) { if (! (azx_readw(chip, IRS) & ICH6_IRS_BUSY)) {
...@@ -639,10 +627,19 @@ static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, ...@@ -639,10 +627,19 @@ static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid,
unsigned int para) unsigned int para)
{ {
struct azx *chip = codec->bus->private_data; struct azx *chip = codec->bus->private_data;
u32 val;
val = (u32)(codec->addr & 0x0f) << 28;
val |= (u32)direct << 27;
val |= (u32)nid << 20;
val |= verb << 8;
val |= para;
chip->last_cmd = val;
if (chip->single_cmd) if (chip->single_cmd)
return azx_single_send_cmd(codec, nid, direct, verb, para); return azx_single_send_cmd(codec, val);
else else
return azx_corb_send_cmd(codec, nid, direct, verb, para); return azx_corb_send_cmd(codec, val);
} }
/* get a response */ /* get a response */
...@@ -1788,6 +1785,12 @@ static struct pci_device_id azx_ids[] = { ...@@ -1788,6 +1785,12 @@ static struct pci_device_id azx_ids[] = {
{ 0x10de, 0x044b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */ { 0x10de, 0x044b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
{ 0x10de, 0x055c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */ { 0x10de, 0x055c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
{ 0x10de, 0x055d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */ { 0x10de, 0x055d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
{ 0x10de, 0x07fc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */
{ 0x10de, 0x07fd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */
{ 0x10de, 0x0774, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
{ 0x10de, 0x0775, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
{ 0x10de, 0x0776, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
{ 0x10de, 0x0777, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE(pci, azx_ids); MODULE_DEVICE_TABLE(pci, azx_ids);
......
...@@ -250,6 +250,12 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe ...@@ -250,6 +250,12 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe
snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id);
snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id);
snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id); snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
if (codec->mfg)
snd_iprintf(buffer, "Modem Function Group: 0x%x\n", codec->mfg);
else
snd_iprintf(buffer, "No Modem Function Group found\n");
if (! codec->afg) if (! codec->afg)
return; return;
snd_iprintf(buffer, "Default PCM:\n"); snd_iprintf(buffer, "Default PCM:\n");
......
此差异已折叠。
...@@ -172,6 +172,7 @@ static int patch_atihdmi(struct hda_codec *codec) ...@@ -172,6 +172,7 @@ static int patch_atihdmi(struct hda_codec *codec)
*/ */
struct hda_codec_preset snd_hda_preset_atihdmi[] = { struct hda_codec_preset snd_hda_preset_atihdmi[] = {
{ .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi }, { .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
{ .id = 0x10027919, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
{ .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi }, { .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi },
{ .id = 0x1002aa01, .name = "ATI R600 HDMI", .patch = patch_atihdmi }, { .id = 0x1002aa01, .name = "ATI R600 HDMI", .patch = patch_atihdmi },
{} /* terminator */ {} /* terminator */
......
...@@ -801,7 +801,9 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = { ...@@ -801,7 +801,9 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV Series", CXT5045_LAPTOP), SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV Series", CXT5045_LAPTOP),
SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2120", CXT5045_LAPTOP), SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2120", CXT5045_LAPTOP),
SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP), SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP),
SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP),
SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_FUJITSU), SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_FUJITSU),
SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP),
SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP), SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP),
{} {}
}; };
......
此差异已折叠。
...@@ -304,8 +304,12 @@ struct hda_codec_preset snd_hda_preset_si3054[] = { ...@@ -304,8 +304,12 @@ struct hda_codec_preset snd_hda_preset_si3054[] = {
{ .id = 0x10573055, .name = "Si3054", .patch = patch_si3054 }, { .id = 0x10573055, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 }, { .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x10573155, .name = "Si3054", .patch = patch_si3054 }, { .id = 0x10573155, .name = "Si3054", .patch = patch_si3054 },
/* VIA HDA on Clevo m540 */
{ .id = 0x11063288, .name = "Si3054", .patch = patch_si3054 },
/* Asus A8J Modem (SM56) */ /* Asus A8J Modem (SM56) */
{ .id = 0x15433155, .name = "Si3054", .patch = patch_si3054 }, { .id = 0x15433155, .name = "Si3054", .patch = patch_si3054 },
/* LG LW20 modem */
{ .id = 0x18540018, .name = "Si3054", .patch = patch_si3054 },
{} {}
}; };
...@@ -44,6 +44,7 @@ enum { ...@@ -44,6 +44,7 @@ enum {
enum { enum {
STAC_9205_REF, STAC_9205_REF,
STAC_M43xx,
STAC_9205_MODELS STAC_9205_MODELS
}; };
...@@ -59,11 +60,19 @@ enum { ...@@ -59,11 +60,19 @@ enum {
STAC_D945_REF, STAC_D945_REF,
STAC_D945GTP3, STAC_D945GTP3,
STAC_D945GTP5, STAC_D945GTP5,
STAC_922X_DELL,
STAC_INTEL_MAC_V1,
STAC_INTEL_MAC_V2,
STAC_INTEL_MAC_V3,
STAC_INTEL_MAC_V4,
STAC_INTEL_MAC_V5,
/* for backward compitability */
STAC_MACMINI, STAC_MACMINI,
STAC_MACBOOK, STAC_MACBOOK,
STAC_MACBOOK_PRO_V1, STAC_MACBOOK_PRO_V1,
STAC_MACBOOK_PRO_V2, STAC_MACBOOK_PRO_V2,
STAC_IMAC_INTEL, STAC_IMAC_INTEL,
STAC_IMAC_INTEL_20,
STAC_922X_MODELS STAC_922X_MODELS
}; };
...@@ -210,7 +219,6 @@ static hda_nid_t stac9205_pin_nids[12] = { ...@@ -210,7 +219,6 @@ static hda_nid_t stac9205_pin_nids[12] = {
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x14, 0x16, 0x17, 0x18, 0x0f, 0x14, 0x16, 0x17, 0x18,
0x21, 0x22, 0x21, 0x22,
}; };
static int stac92xx_dmux_enum_info(struct snd_kcontrol *kcontrol, static int stac92xx_dmux_enum_info(struct snd_kcontrol *kcontrol,
...@@ -326,8 +334,6 @@ static struct snd_kcontrol_new stac9200_mixer[] = { ...@@ -326,8 +334,6 @@ static struct snd_kcontrol_new stac9200_mixer[] = {
}; };
static struct snd_kcontrol_new stac925x_mixer[] = { static struct snd_kcontrol_new stac925x_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0xe, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Master Playback Switch", 0xe, 0, HDA_OUTPUT),
{ {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Input Source", .name = "Input Source",
...@@ -549,44 +555,78 @@ static unsigned int d945gtp5_pin_configs[10] = { ...@@ -549,44 +555,78 @@ static unsigned int d945gtp5_pin_configs[10] = {
0x02a19320, 0x40000100, 0x02a19320, 0x40000100,
}; };
static unsigned int macbook_pro_v1_pin_configs[10] = { static unsigned int intel_mac_v1_pin_configs[10] = {
0x0321e230, 0x03a1e020, 0x9017e110, 0x01014010, 0x0121e21f, 0x400000ff, 0x9017e110, 0x400000fd,
0x01a19021, 0x0381e021, 0x1345e240, 0x13c5e22e, 0x400000fe, 0x0181e020, 0x1145e030, 0x11c5e240,
0x02a19320, 0x400000fb 0x400000fc, 0x400000fb,
};
static unsigned int intel_mac_v2_pin_configs[10] = {
0x0121e21f, 0x90a7012e, 0x9017e110, 0x400000fd,
0x400000fe, 0x0181e020, 0x1145e230, 0x500000fa,
0x400000fc, 0x400000fb,
};
static unsigned int intel_mac_v3_pin_configs[10] = {
0x0121e21f, 0x90a7012e, 0x9017e110, 0x400000fd,
0x400000fe, 0x0181e020, 0x1145e230, 0x11c5e240,
0x400000fc, 0x400000fb,
}; };
static unsigned int macbook_pro_v2_pin_configs[10] = { static unsigned int intel_mac_v4_pin_configs[10] = {
0x0221401f, 0x90a70120, 0x01813024, 0x01014010, 0x0321e21f, 0x03a1e02e, 0x9017e110, 0x9017e11f,
0x400000fd, 0x01016011, 0x1345e240, 0x13c5e22e, 0x400000fe, 0x0381e020, 0x1345e230, 0x13c5e240,
0x400000fc, 0x400000fb, 0x400000fc, 0x400000fb,
}; };
static unsigned int imac_intel_pin_configs[10] = { static unsigned int intel_mac_v5_pin_configs[10] = {
0x0121e230, 0x90a70120, 0x9017e110, 0x400000fe, 0x0321e21f, 0x03a1e02e, 0x9017e110, 0x9017e11f,
0x400000fd, 0x0181e021, 0x1145e040, 0x400000fa, 0x400000fe, 0x0381e020, 0x1345e230, 0x13c5e240,
0x400000fc, 0x400000fb, 0x400000fc, 0x400000fb,
}; };
static unsigned int stac922x_dell_pin_configs[10] = {
0x0221121e, 0x408103ff, 0x02a1123e, 0x90100310,
0x408003f1, 0x0221122f, 0x03451340, 0x40c003f2,
0x50a003f3, 0x405003f4
};
static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
[STAC_D945_REF] = ref922x_pin_configs, [STAC_D945_REF] = ref922x_pin_configs,
[STAC_D945GTP3] = d945gtp3_pin_configs, [STAC_D945GTP3] = d945gtp3_pin_configs,
[STAC_D945GTP5] = d945gtp5_pin_configs, [STAC_D945GTP5] = d945gtp5_pin_configs,
[STAC_MACMINI] = macbook_pro_v1_pin_configs, [STAC_922X_DELL] = stac922x_dell_pin_configs,
[STAC_MACBOOK] = macbook_pro_v1_pin_configs, [STAC_INTEL_MAC_V1] = intel_mac_v1_pin_configs,
[STAC_MACBOOK_PRO_V1] = macbook_pro_v1_pin_configs, [STAC_INTEL_MAC_V2] = intel_mac_v2_pin_configs,
[STAC_MACBOOK_PRO_V2] = macbook_pro_v2_pin_configs, [STAC_INTEL_MAC_V3] = intel_mac_v3_pin_configs,
[STAC_IMAC_INTEL] = imac_intel_pin_configs, [STAC_INTEL_MAC_V4] = intel_mac_v4_pin_configs,
[STAC_INTEL_MAC_V5] = intel_mac_v5_pin_configs,
/* for backward compitability */
[STAC_MACMINI] = intel_mac_v3_pin_configs,
[STAC_MACBOOK] = intel_mac_v5_pin_configs,
[STAC_MACBOOK_PRO_V1] = intel_mac_v3_pin_configs,
[STAC_MACBOOK_PRO_V2] = intel_mac_v3_pin_configs,
[STAC_IMAC_INTEL] = intel_mac_v2_pin_configs,
[STAC_IMAC_INTEL_20] = intel_mac_v3_pin_configs,
}; };
static const char *stac922x_models[STAC_922X_MODELS] = { static const char *stac922x_models[STAC_922X_MODELS] = {
[STAC_D945_REF] = "ref", [STAC_D945_REF] = "ref",
[STAC_D945GTP5] = "5stack", [STAC_D945GTP5] = "5stack",
[STAC_D945GTP3] = "3stack", [STAC_D945GTP3] = "3stack",
[STAC_922X_DELL] = "dell",
[STAC_INTEL_MAC_V1] = "intel-mac-v1",
[STAC_INTEL_MAC_V2] = "intel-mac-v2",
[STAC_INTEL_MAC_V3] = "intel-mac-v3",
[STAC_INTEL_MAC_V4] = "intel-mac-v4",
[STAC_INTEL_MAC_V5] = "intel-mac-v5",
/* for backward compitability */
[STAC_MACMINI] = "macmini", [STAC_MACMINI] = "macmini",
[STAC_MACBOOK] = "macbook", [STAC_MACBOOK] = "macbook",
[STAC_MACBOOK_PRO_V1] = "macbook-pro-v1", [STAC_MACBOOK_PRO_V1] = "macbook-pro-v1",
[STAC_MACBOOK_PRO_V2] = "macbook-pro", [STAC_MACBOOK_PRO_V2] = "macbook-pro",
[STAC_IMAC_INTEL] = "imac-intel", [STAC_IMAC_INTEL] = "imac-intel",
[STAC_IMAC_INTEL_20] = "imac-intel-20",
}; };
static struct snd_pci_quirk stac922x_cfg_tbl[] = { static struct snd_pci_quirk stac922x_cfg_tbl[] = {
...@@ -649,7 +689,10 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { ...@@ -649,7 +689,10 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = {
/* other systems */ /* other systems */
/* Apple Mac Mini (early 2006) */ /* Apple Mac Mini (early 2006) */
SND_PCI_QUIRK(0x8384, 0x7680, SND_PCI_QUIRK(0x8384, 0x7680,
"Mac Mini", STAC_MACMINI), "Mac Mini", STAC_INTEL_MAC_V3),
/* Dell */
SND_PCI_QUIRK(0x1028, 0x01d7, "Dell XPS M1210", STAC_922X_DELL),
{} /* terminator */ {} /* terminator */
}; };
...@@ -730,7 +773,8 @@ static unsigned int ref9205_pin_configs[12] = { ...@@ -730,7 +773,8 @@ static unsigned int ref9205_pin_configs[12] = {
}; };
static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = { static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
ref9205_pin_configs, [STAC_REF] = ref9205_pin_configs,
[STAC_M43xx] = NULL,
}; };
static const char *stac9205_models[STAC_9205_MODELS] = { static const char *stac9205_models[STAC_9205_MODELS] = {
...@@ -741,6 +785,10 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = { ...@@ -741,6 +785,10 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
/* SigmaTel reference board */ /* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_9205_REF), "DFI LanParty", STAC_9205_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01f8,
"Dell Precision", STAC_M43xx),
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01ff,
"Dell Precision", STAC_M43xx),
{} /* terminator */ {} /* terminator */
}; };
...@@ -770,33 +818,56 @@ static int stac92xx_save_bios_config_regs(struct hda_codec *codec) ...@@ -770,33 +818,56 @@ static int stac92xx_save_bios_config_regs(struct hda_codec *codec)
return 0; return 0;
} }
static void stac92xx_set_config_reg(struct hda_codec *codec,
hda_nid_t pin_nid, unsigned int pin_config)
{
int i;
snd_hda_codec_write(codec, pin_nid, 0,
AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
pin_config & 0x000000ff);
snd_hda_codec_write(codec, pin_nid, 0,
AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
(pin_config & 0x0000ff00) >> 8);
snd_hda_codec_write(codec, pin_nid, 0,
AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
(pin_config & 0x00ff0000) >> 16);
snd_hda_codec_write(codec, pin_nid, 0,
AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
pin_config >> 24);
i = snd_hda_codec_read(codec, pin_nid, 0,
AC_VERB_GET_CONFIG_DEFAULT,
0x00);
snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n",
pin_nid, i);
}
static void stac92xx_set_config_regs(struct hda_codec *codec) static void stac92xx_set_config_regs(struct hda_codec *codec)
{ {
int i; int i;
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
unsigned int pin_cfg;
if (! spec->pin_nids || ! spec->pin_configs) if (!spec->pin_configs)
return; return;
for (i = 0; i < spec->num_pins; i++) { for (i = 0; i < spec->num_pins; i++)
snd_hda_codec_write(codec, spec->pin_nids[i], 0, stac92xx_set_config_reg(codec, spec->pin_nids[i],
AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, spec->pin_configs[i]);
spec->pin_configs[i] & 0x000000ff); }
snd_hda_codec_write(codec, spec->pin_nids[i], 0,
AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, static void stac92xx_enable_gpio_mask(struct hda_codec *codec,
(spec->pin_configs[i] & 0x0000ff00) >> 8); int gpio_mask, int gpio_data)
snd_hda_codec_write(codec, spec->pin_nids[i], 0, {
AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, /* Configure GPIOx as output */
(spec->pin_configs[i] & 0x00ff0000) >> 16); snd_hda_codec_write(codec, codec->afg, 0,
snd_hda_codec_write(codec, spec->pin_nids[i], 0, AC_VERB_SET_GPIO_DIRECTION, gpio_mask);
AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, /* Configure GPIOx as CMOS */
spec->pin_configs[i] >> 24); snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0x00000000);
pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0, /* Assert GPIOx */
AC_VERB_GET_CONFIG_DEFAULT, snd_hda_codec_write(codec, codec->afg, 0,
0x00); AC_VERB_SET_GPIO_DATA, gpio_data);
snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg); /* Enable GPIOx */
} snd_hda_codec_write(codec, codec->afg, 0,
AC_VERB_SET_GPIO_MASK, gpio_mask);
} }
/* /*
...@@ -1168,7 +1239,7 @@ static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) ...@@ -1168,7 +1239,7 @@ static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
* and 9202/925x. For those, dac_nids[] must be hard-coded. * and 9202/925x. For those, dac_nids[] must be hard-coded.
*/ */
static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec,
const struct auto_pin_cfg *cfg) struct auto_pin_cfg *cfg)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
int i, j, conn_len = 0; int i, j, conn_len = 0;
...@@ -1193,6 +1264,13 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, ...@@ -1193,6 +1264,13 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec,
} }
if (j == conn_len) { if (j == conn_len) {
if (spec->multiout.num_dacs > 0) {
/* we have already working output pins,
* so let's drop the broken ones again
*/
cfg->line_outs = spec->multiout.num_dacs;
break;
}
/* error out, no available DAC found */ /* error out, no available DAC found */
snd_printk(KERN_ERR snd_printk(KERN_ERR
"%s: No available DAC for pin 0x%x\n", "%s: No available DAC for pin 0x%x\n",
...@@ -1334,7 +1412,15 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, ...@@ -1334,7 +1412,15 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
continue; continue;
add_spec_dacs(spec, nid); add_spec_dacs(spec, nid);
} }
for (i = 0; i < cfg->line_outs; i++) {
nid = snd_hda_codec_read(codec, cfg->line_out_pins[i], 0,
AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
if (check_in_dac_nids(spec, nid))
nid = 0;
if (! nid)
continue;
add_spec_dacs(spec, nid);
}
for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) { for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) {
static const char *pfxs[] = { static const char *pfxs[] = {
"Speaker", "External Speaker", "Speaker2", "Speaker", "External Speaker", "Speaker2",
...@@ -1891,7 +1977,7 @@ static int patch_stac9200(struct hda_codec *codec) ...@@ -1891,7 +1977,7 @@ static int patch_stac9200(struct hda_codec *codec)
return -ENOMEM; return -ENOMEM;
codec->spec = spec; codec->spec = spec;
spec->num_pins = 8; spec->num_pins = ARRAY_SIZE(stac9200_pin_nids);
spec->pin_nids = stac9200_pin_nids; spec->pin_nids = stac9200_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
stac9200_models, stac9200_models,
...@@ -1941,7 +2027,7 @@ static int patch_stac925x(struct hda_codec *codec) ...@@ -1941,7 +2027,7 @@ static int patch_stac925x(struct hda_codec *codec)
return -ENOMEM; return -ENOMEM;
codec->spec = spec; codec->spec = spec;
spec->num_pins = 8; spec->num_pins = ARRAY_SIZE(stac925x_pin_nids);
spec->pin_nids = stac925x_pin_nids; spec->pin_nids = stac925x_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS, spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS,
stac925x_models, stac925x_models,
...@@ -2013,29 +2099,41 @@ static int patch_stac922x(struct hda_codec *codec) ...@@ -2013,29 +2099,41 @@ static int patch_stac922x(struct hda_codec *codec)
return -ENOMEM; return -ENOMEM;
codec->spec = spec; codec->spec = spec;
spec->num_pins = 10; spec->num_pins = ARRAY_SIZE(stac922x_pin_nids);
spec->pin_nids = stac922x_pin_nids; spec->pin_nids = stac922x_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS, spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS,
stac922x_models, stac922x_models,
stac922x_cfg_tbl); stac922x_cfg_tbl);
if (spec->board_config == STAC_MACMINI) { if (spec->board_config == STAC_INTEL_MAC_V3) {
spec->gpio_mute = 1; spec->gpio_mute = 1;
/* Intel Macs have all same PCI SSID, so we need to check /* Intel Macs have all same PCI SSID, so we need to check
* codec SSID to distinguish the exact models * codec SSID to distinguish the exact models
*/ */
printk(KERN_INFO "hda_codec: STAC922x, Apple subsys_id=%x\n", codec->subsystem_id); printk(KERN_INFO "hda_codec: STAC922x, Apple subsys_id=%x\n", codec->subsystem_id);
switch (codec->subsystem_id) { switch (codec->subsystem_id) {
case 0x106b0a00: /* MacBook First generatoin */
spec->board_config = STAC_MACBOOK; case 0x106b0800:
spec->board_config = STAC_INTEL_MAC_V1;
break;
case 0x106b0600:
case 0x106b0700:
spec->board_config = STAC_INTEL_MAC_V2;
break; break;
case 0x106b0200: /* MacBook Pro first generation */ case 0x106b0e00:
spec->board_config = STAC_MACBOOK_PRO_V1; case 0x106b0f00:
case 0x106b1600:
case 0x106b1700:
case 0x106b0200:
case 0x106b1e00:
spec->board_config = STAC_INTEL_MAC_V3;
break; break;
case 0x106b1e00: /* MacBook Pro second generation */ case 0x106b1a00:
spec->board_config = STAC_MACBOOK_PRO_V2; case 0x00000100:
spec->board_config = STAC_INTEL_MAC_V4;
break; break;
case 0x106b0700: /* Intel-based iMac */ case 0x106b0a00:
spec->board_config = STAC_IMAC_INTEL; case 0x106b2200:
spec->board_config = STAC_INTEL_MAC_V5;
break; break;
} }
} }
...@@ -2082,6 +2180,13 @@ static int patch_stac922x(struct hda_codec *codec) ...@@ -2082,6 +2180,13 @@ static int patch_stac922x(struct hda_codec *codec)
codec->patch_ops = stac92xx_patch_ops; codec->patch_ops = stac92xx_patch_ops;
/* Fix Mux capture level; max to 2 */
snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT,
(0 << AC_AMPCAP_OFFSET_SHIFT) |
(2 << AC_AMPCAP_NUM_STEPS_SHIFT) |
(0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) |
(0 << AC_AMPCAP_MUTE_SHIFT));
return 0; return 0;
} }
...@@ -2095,7 +2200,7 @@ static int patch_stac927x(struct hda_codec *codec) ...@@ -2095,7 +2200,7 @@ static int patch_stac927x(struct hda_codec *codec)
return -ENOMEM; return -ENOMEM;
codec->spec = spec; codec->spec = spec;
spec->num_pins = 14; spec->num_pins = ARRAY_SIZE(stac927x_pin_nids);
spec->pin_nids = stac927x_pin_nids; spec->pin_nids = stac927x_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS, spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS,
stac927x_models, stac927x_models,
...@@ -2141,7 +2246,9 @@ static int patch_stac927x(struct hda_codec *codec) ...@@ -2141,7 +2246,9 @@ static int patch_stac927x(struct hda_codec *codec)
} }
spec->multiout.dac_nids = spec->dac_nids; spec->multiout.dac_nids = spec->dac_nids;
/* GPIO0 High = Enable EAPD */
stac92xx_enable_gpio_mask(codec, 0x00000001, 0x00000001);
err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); err = stac92xx_parse_auto_config(codec, 0x1e, 0x20);
if (!err) { if (!err) {
if (spec->board_config < 0) { if (spec->board_config < 0) {
...@@ -2159,27 +2266,20 @@ static int patch_stac927x(struct hda_codec *codec) ...@@ -2159,27 +2266,20 @@ static int patch_stac927x(struct hda_codec *codec)
codec->patch_ops = stac92xx_patch_ops; codec->patch_ops = stac92xx_patch_ops;
/* Fix Mux capture level; max to 2 */
snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT,
(0 << AC_AMPCAP_OFFSET_SHIFT) |
(2 << AC_AMPCAP_NUM_STEPS_SHIFT) |
(0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) |
(0 << AC_AMPCAP_MUTE_SHIFT));
return 0; return 0;
} }
static int patch_stac9205(struct hda_codec *codec) static int patch_stac9205(struct hda_codec *codec)
{ {
struct sigmatel_spec *spec; struct sigmatel_spec *spec;
int err; int err, gpio_mask, gpio_data;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL) if (spec == NULL)
return -ENOMEM; return -ENOMEM;
codec->spec = spec; codec->spec = spec;
spec->num_pins = 14; spec->num_pins = ARRAY_SIZE(stac9205_pin_nids);
spec->pin_nids = stac9205_pin_nids; spec->pin_nids = stac9205_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS, spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS,
stac9205_models, stac9205_models,
...@@ -2209,19 +2309,21 @@ static int patch_stac9205(struct hda_codec *codec) ...@@ -2209,19 +2309,21 @@ static int patch_stac9205(struct hda_codec *codec)
spec->mixer = stac9205_mixer; spec->mixer = stac9205_mixer;
spec->multiout.dac_nids = spec->dac_nids; spec->multiout.dac_nids = spec->dac_nids;
if (spec->board_config == STAC_M43xx) {
/* Enable SPDIF in/out */
stac92xx_set_config_reg(codec, 0x1f, 0x01441030);
stac92xx_set_config_reg(codec, 0x20, 0x1c410030);
gpio_mask = 0x00000007; /* GPIO0-2 */
/* GPIO0 High = EAPD, GPIO1 Low = DRM,
* GPIO2 High = Headphone Mute
*/
gpio_data = 0x00000005;
} else
gpio_mask = gpio_data = 0x00000001; /* GPIO0 High = EAPD */
/* Configure GPIO0 as EAPD output */ stac92xx_enable_gpio_mask(codec, gpio_mask, gpio_data);
snd_hda_codec_write(codec, codec->afg, 0,
AC_VERB_SET_GPIO_DIRECTION, 0x00000001);
/* Configure GPIO0 as CMOS */
snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0x00000000);
/* Assert GPIO0 high */
snd_hda_codec_write(codec, codec->afg, 0,
AC_VERB_SET_GPIO_DATA, 0x00000001);
/* Enable GPIO0 */
snd_hda_codec_write(codec, codec->afg, 0,
AC_VERB_SET_GPIO_MASK, 0x00000001);
err = stac92xx_parse_auto_config(codec, 0x1f, 0x20); err = stac92xx_parse_auto_config(codec, 0x1f, 0x20);
if (!err) { if (!err) {
if (spec->board_config < 0) { if (spec->board_config < 0) {
...@@ -2256,8 +2358,8 @@ static struct hda_input_mux vaio_mux = { ...@@ -2256,8 +2358,8 @@ static struct hda_input_mux vaio_mux = {
.num_items = 2, .num_items = 2,
.items = { .items = {
/* { "HP", 0x0 }, */ /* { "HP", 0x0 }, */
{ "Line", 0x1 }, { "Mic Jack", 0x1 },
{ "Mic", 0x2 }, { "Internal Mic", 0x2 },
{ "PCM", 0x3 }, { "PCM", 0x3 },
} }
}; };
...@@ -2268,7 +2370,7 @@ static struct hda_verb vaio_init[] = { ...@@ -2268,7 +2370,7 @@ static struct hda_verb vaio_init[] = {
{0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */
{0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */
{0x15, AC_VERB_SET_CONNECT_SEL, 0x2}, /* mic-sel: 0a,0d,14,02 */ {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */
...@@ -2284,7 +2386,7 @@ static struct hda_verb vaio_ar_init[] = { ...@@ -2284,7 +2386,7 @@ static struct hda_verb vaio_ar_init[] = {
{0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
/* {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */ /* {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */
{0x15, AC_VERB_SET_CONNECT_SEL, 0x2}, /* mic-sel: 0a,0d,14,02 */ {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */
/* {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */ /* {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */
......
...@@ -186,7 +186,12 @@ static int revo51_i2c_init(struct snd_ice1712 *ice, ...@@ -186,7 +186,12 @@ static int revo51_i2c_init(struct snd_ice1712 *ice,
#define AK_DAC(xname,xch) { .name = xname, .num_channels = xch } #define AK_DAC(xname,xch) { .name = xname, .num_channels = xch }
static const struct snd_akm4xxx_dac_channel revo71_front[] = { static const struct snd_akm4xxx_dac_channel revo71_front[] = {
AK_DAC("PCM Playback Volume", 2) {
.name = "PCM Playback Volume",
.num_channels = 2,
/* front channels DAC supports muting */
.switch_name = "PCM Playback Switch",
},
}; };
static const struct snd_akm4xxx_dac_channel revo71_surround[] = { static const struct snd_akm4xxx_dac_channel revo71_surround[] = {
......
...@@ -1533,7 +1533,8 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci, ...@@ -1533,7 +1533,8 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
printk(KERN_ERR " force the driver to load by " printk(KERN_ERR " force the driver to load by "
"passing in the module parameter\n"); "passing in the module parameter\n");
printk(KERN_ERR " force_ac97=1\n"); printk(KERN_ERR " force_ac97=1\n");
printk(KERN_ERR " or try sb16 or cs423x drivers instead.\n"); printk(KERN_ERR " or try sb16, opl3sa2, or "
"cs423x drivers instead.\n");
err = -ENXIO; err = -ENXIO;
goto __error; goto __error;
} }
......
...@@ -406,7 +406,7 @@ static snd_pcm_uframes_t rme9652_hw_pointer(struct snd_rme9652 *rme9652) ...@@ -406,7 +406,7 @@ static snd_pcm_uframes_t rme9652_hw_pointer(struct snd_rme9652 *rme9652)
} else if (!frag) } else if (!frag)
return 0; return 0;
offset -= rme9652->max_jitter; offset -= rme9652->max_jitter;
if (offset < 0) if ((int)offset < 0)
offset += period_size * 2; offset += period_size * 2;
} else { } else {
if (offset > period_size + rme9652->max_jitter) { if (offset > period_size + rme9652->max_jitter) {
......
...@@ -2098,7 +2098,7 @@ static int snd_via82xx_chip_init(struct via82xx *chip) ...@@ -2098,7 +2098,7 @@ static int snd_via82xx_chip_init(struct via82xx *chip)
pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval);
if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */
break; break;
schedule_timeout_uninterruptible(1); schedule_timeout(1);
} while (time_before(jiffies, end_time)); } while (time_before(jiffies, end_time));
if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)
...@@ -2117,7 +2117,7 @@ static int snd_via82xx_chip_init(struct via82xx *chip) ...@@ -2117,7 +2117,7 @@ static int snd_via82xx_chip_init(struct via82xx *chip)
chip->ac97_secondary = 1; chip->ac97_secondary = 1;
goto __ac97_ok2; goto __ac97_ok2;
} }
schedule_timeout_interruptible(1); schedule_timeout(1);
} while (time_before(jiffies, end_time)); } while (time_before(jiffies, end_time));
/* This is ok, the most of motherboards have only one codec */ /* This is ok, the most of motherboards have only one codec */
......
...@@ -983,7 +983,7 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) ...@@ -983,7 +983,7 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip)
pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval);
if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */
break; break;
schedule_timeout_uninterruptible(1); schedule_timeout(1);
} while (time_before(jiffies, end_time)); } while (time_before(jiffies, end_time));
if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)
...@@ -1001,7 +1001,7 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) ...@@ -1001,7 +1001,7 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip)
chip->ac97_secondary = 1; chip->ac97_secondary = 1;
goto __ac97_ok2; goto __ac97_ok2;
} }
schedule_timeout_interruptible(1); schedule_timeout(1);
} while (time_before(jiffies, end_time)); } while (time_before(jiffies, end_time));
/* This is ok, the most of motherboards have only one codec */ /* This is ok, the most of motherboards have only one codec */
......
...@@ -33,3 +33,23 @@ config SND_POWERMAC_AUTO_DRC ...@@ -33,3 +33,23 @@ config SND_POWERMAC_AUTO_DRC
option. option.
endmenu endmenu
menu "ALSA PowerPC devices"
depends on SND!=n && ( PPC64 || PPC32 )
config SND_PS3
tristate "PS3 Audio support"
depends on SND && PS3_PS3AV
select SND_PCM
default m
help
Say Y here to include support for audio on the PS3
To compile this driver as a module, choose M here: the module
will be called snd_ps3.
config SND_PS3_DEFAULT_START_DELAY
int "Startup delay time in ms"
depends on SND_PS3
default "2000"
endmenu
...@@ -6,4 +6,5 @@ ...@@ -6,4 +6,5 @@
snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o
# Toplevel Module Dependency # Toplevel Module Dependency
obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o
obj-$(CONFIG_SND_PS3) += snd_ps3.o
此差异已折叠。
此差异已折叠。
此差异已折叠。
# ALSA SH drivers
menu "SUPERH devices"
depends on SND!=n && SUPERH
config SND_AICA
tristate "Dreamcast Yamaha AICA sound"
depends on SH_DREAMCAST && SND
select SND_PCM
help
ALSA Sound driver for the SEGA Dreamcast console.
endmenu
#
# Makefile for ALSA
#
snd-aica-objs := aica.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_AICA) += snd-aica.o
此差异已折叠。
此差异已折叠。
...@@ -27,6 +27,7 @@ config SND_SOC ...@@ -27,6 +27,7 @@ config SND_SOC
source "sound/soc/at91/Kconfig" source "sound/soc/at91/Kconfig"
source "sound/soc/pxa/Kconfig" source "sound/soc/pxa/Kconfig"
source "sound/soc/s3c24xx/Kconfig" source "sound/soc/s3c24xx/Kconfig"
source "sound/soc/sh/Kconfig"
# Supported codecs # Supported codecs
source "sound/soc/codecs/Kconfig" source "sound/soc/codecs/Kconfig"
......
snd-soc-core-objs := soc-core.o soc-dapm.o snd-soc-core-objs := soc-core.o soc-dapm.o
obj-$(CONFIG_SND_SOC) += snd-soc-core.o obj-$(CONFIG_SND_SOC) += snd-soc-core.o
obj-$(CONFIG_SND_SOC) += codecs/ at91/ pxa/ s3c24xx/ obj-$(CONFIG_SND_SOC) += codecs/ at91/ pxa/ s3c24xx/ sh/
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册