diff --git a/[refs] b/[refs]
index 3ce91c633db2..40732c82a3cb 100644
--- a/[refs]
+++ b/[refs]
@@ -1,2 +1,2 @@
---
-refs/heads/master: 94eb7f4cefaf3ed8e97504ce4f3946bdb908e501
+refs/heads/master: 718a538f945a84244a460df434c3f6f04701957b
diff --git a/trunk/CREDITS b/trunk/CREDITS
index 3b7a1548aaf9..2993348ce6ce 100644
--- a/trunk/CREDITS
+++ b/trunk/CREDITS
@@ -2380,10 +2380,9 @@ E: tmolina@cablespeed.com
D: bug fixes, documentation, minor hackery
N: James Morris
-E: jmorris@redhat.com
+E: jmorris@intercode.com.au
W: http://www.intercode.com.au/jmorris/
-D: Netfilter, Linux Security Modules (LSM), SELinux, IPSec,
-D: Crypto API, general networking, miscellaneous.
+D: Netfilter, Linux Security Modules (LSM).
S: PO Box 707
S: Spit Junction NSW 2088
S: Australia
diff --git a/trunk/Documentation/sound/alsa/ALSA-Configuration.txt b/trunk/Documentation/sound/alsa/ALSA-Configuration.txt
index 104a994b8289..71ef0498d5e0 100644
--- a/trunk/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/trunk/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -615,11 +615,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module snd-hda-intel
--------------------
- Module for Intel HD Audio (ICH6, ICH6M, ICH7), ATI SB450,
- VIA VT8251/VT8237A
+ Module for Intel HD Audio (ICH6, ICH6M, ICH7)
model - force the model name
- position_fix - Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF)
Module supports up to 8 cards.
@@ -637,10 +635,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
5stack 5-jack in back, 2-jack in front
5stack-digout 5-jack in back, 2-jack in front, a SPDIF out
w810 3-jack
- z71v 3-jack (HP shared SPDIF)
- asus 3-jack
- uniwill 3-jack
- F1734 2-jack
CMI9880
minimal 3-jack in back
@@ -648,15 +642,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
full 6-jack in back, 2-jack in front
full_dig 6-jack in back, 2-jack in front, SPDIF I/O
allout 5-jack in back, 2-jack in front, SPDIF out
- auto auto-config reading BIOS (default)
-
- Note 2: If you get click noises on output, try the module option
- position_fix=1 or 2. position_fix=1 will use the SD_LPIB
- register value without FIFO size correction as the current
- DMA pointer. position_fix=2 will make the driver to use
- the position buffer instead of reading SD_LPIB register.
- (Usually SD_LPLIB register is more accurate than the
- position buffer.)
Module snd-hdsp
---------------
@@ -675,19 +660,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
module did formerly. It will allocate the buffers in advance
when any HDSP cards are found. To make the buffer
allocation sure, load snd-page-alloc module in the early
- stage of boot sequence. See "Early Buffer Allocation"
- section.
-
- Module snd-hdspm
- ----------------
-
- Module for RME HDSP MADI board.
-
- precise_ptr - Enable precise pointer, or disable.
- line_outs_monitor - Send playback streams to analog outs by default.
- enable_monitor - Enable Analog Out on Channel 63/64 by default.
-
- See hdspm.txt for details.
+ stage of boot sequence.
Module snd-ice1712
------------------
@@ -704,19 +677,15 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
* TerraTec EWS 88D
* TerraTec EWX 24/96
* TerraTec DMX 6Fire
- * TerraTec Phase 88
* Hoontech SoundTrack DSP 24
* Hoontech SoundTrack DSP 24 Value
* Hoontech SoundTrack DSP 24 Media 7.1
- * Event Electronics, EZ8
* Digigram VX442
- * Lionstracs, Mediastaton
model - Use the given board model, one of the following:
delta1010, dio2496, delta66, delta44, audiophile, delta410,
delta1010lt, vx442, ewx2496, ews88mt, ews88mt_new, ews88d,
- dmx6fire, dsp24, dsp24_value, dsp24_71, ez8,
- phase88, mediastation
+ dmx6fire, dsp24, dsp24_value, dsp24_71, ez8
omni - Omni I/O support for MidiMan M-Audio Delta44/66
cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever)
in msec resolution, default value is 500 (0.5 sec)
@@ -725,46 +694,20 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
is not used with all Envy24 based cards (for example in the MidiMan Delta
serie).
- Note: The supported board is detected by reading EEPROM or PCI
- SSID (if EEPROM isn't available). You can override the
- model by passing "model" module option in case that the
- driver isn't configured properly or you want to try another
- type for testing.
-
Module snd-ice1724
------------------
- Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
+ Module for Envy24HT (VT/ICE1724) based PCI sound cards.
* MidiMan M Audio Revolution 7.1
* AMP Ltd AUDIO2000
- * TerraTec Aureon 5.1 Sky
- * TerraTec Aureon 7.1 Space
- * TerraTec Aureon 7.1 Universe
- * TerraTec Phase 22
- * TerraTec Phase 28
- * AudioTrak Prodigy 7.1
- * AudioTrak Prodigy 192
- * Pontis MS300
- * Albatron K8X800 Pro II
- * Chaintech ZNF3-150
- * Chaintech ZNF3-250
- * Chaintech 9CJS
- * Chaintech AV-710
- * Shuttle SN25P
+ * TerraTec Aureon Sky-5.1, Space-7.1
model - Use the given board model, one of the following:
- revo71, amp2000, prodigy71, prodigy192, aureon51,
- aureon71, universe, k8x800, phase22, phase28, ms300,
- av710
+ revo71, amp2000, prodigy71, aureon51, aureon71,
+ k8x800
Module supports up to 8 cards and autoprobe.
- Note: The supported board is detected by reading EEPROM or PCI
- SSID (if EEPROM isn't available). You can override the
- model by passing "model" module option in case that the
- driver isn't configured properly or you want to try another
- type for testing.
-
Module snd-intel8x0
-------------------
@@ -1083,8 +1026,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
module did formerly. It will allocate the buffers in advance
when any RME9652 cards are found. To make the buffer
allocation sure, load snd-page-alloc module in the early
- stage of boot sequence. See "Early Buffer Allocation"
- section.
+ stage of boot sequence.
Module snd-sa11xx-uda1341 (on arm only)
---------------------------------------
@@ -1269,18 +1211,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
------------------
Module for AC'97 motherboards based on VIA 82C686A/686B, 8233,
- 8233A, 8233C, 8235, 8237 (south) bridge.
+ 8233A, 8233C, 8235 (south) bridge.
mpu_port - 0x300,0x310,0x320,0x330, otherwise obtain BIOS setup
[VIA686A/686B only]
joystick - Enable joystick (default off) [VIA686A/686B only]
ac97_clock - AC'97 codec clock base (default 48000Hz)
dxs_support - support DXS channels,
- 0 = auto (default), 1 = enable, 2 = disable,
- 3 = 48k only, 4 = no VRA, 5 = enable any sample
- rate and different sample rates on different
- channels
- [VIA8233/C, 8235, 8237 only]
+ 0 = auto (defalut), 1 = enable, 2 = disable,
+ 3 = 48k only, 4 = no VRA
+ [VIA8233/C,8235 only]
ac97_quirk - AC'97 workaround for strange hardware
See the description of intel8x0 module for details.
@@ -1292,23 +1232,18 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
default value 1.4. Then the interrupt number will be
assigned under 15. You might also upgrade your BIOS.
- Note: VIA8233/5/7 (not VIA8233A) can support DXS (direct sound)
+ Note: VIA8233/5 (not VIA8233A) can support DXS (direct sound)
channels as the first PCM. On these channels, up to 4
- streams can be played at the same time, and the controller
- can perform sample rate conversion with separate rates for
- each channel.
+ streams can be played at the same time.
As default (dxs_support = 0), 48k fixed rate is chosen
except for the known devices since the output is often
noisy except for 48k on some mother boards due to the
bug of BIOS.
- Please try once dxs_support=5 and if it works on other
+ Please try once dxs_support=1 and if it works on other
sample rates (e.g. 44.1kHz of mp3 playback), please let us
know the PCI subsystem vendor/device id's (output of
"lspci -nv").
- If dxs_support=5 does not work, try dxs_support=4; if it
- doesn't work too, try dxs_support=1. (dxs_support=1 is
- usually for old motherboards. The correct implementated
- board should work with 4 or 5.) If it still doesn't
+ If it doesn't work, try dxs_support=4. If it still doesn't
work and the default setting is ok, dxs_support=3 is the
right choice. If the default setting doesn't work at all,
try dxs_support=2 to disable the DXS channels.
@@ -1562,36 +1497,6 @@ Proc interfaces (/proc/asound)
echo "rvplayer 0 0 block" > /proc/asound/card0/pcm0p/oss
-Early Buffer Allocation
-=======================
-
-Some drivers (e.g. hdsp) require the large contiguous buffers, and
-sometimes it's too late to find such spaces when the driver module is
-actually loaded due to memory fragmentation. You can pre-allocate the
-PCM buffers by loading snd-page-alloc module and write commands to its
-proc file in prior, for example, in the early boot stage like
-/etc/init.d/*.local scripts.
-
-Reading the proc file /proc/drivers/snd-page-alloc shows the current
-usage of page allocation. In writing, you can send the following
-commands to the snd-page-alloc driver:
-
- - add VENDOR DEVICE MASK SIZE BUFFERS
-
- VENDOR and DEVICE are PCI vendor and device IDs. They take
- integer numbers (0x prefix is needed for the hex).
- MASK is the PCI DMA mask. Pass 0 if not restricted.
- SIZE is the size of each buffer to allocate. You can pass
- k and m suffix for KB and MB. The max number is 16MB.
- BUFFERS is the number of buffers to allocate. It must be greater
- than 0. The max number is 4.
-
- - erase
-
- This will erase the all pre-allocated buffers which are not in
- use.
-
-
Links
=====
diff --git a/trunk/Documentation/sound/alsa/CMIPCI.txt b/trunk/Documentation/sound/alsa/CMIPCI.txt
index 1872e24442a4..4a7df771b806 100644
--- a/trunk/Documentation/sound/alsa/CMIPCI.txt
+++ b/trunk/Documentation/sound/alsa/CMIPCI.txt
@@ -89,22 +89,19 @@ and use the interleaved 4 channel data.
There are some control switchs affecting to the speaker connections:
-"Line-In Mode" - an enum control to change the behavior of line-in
- jack. Either "Line-In", "Rear Output" or "Bass Output" can
- be selected. The last item is available only with model 039
- or newer.
- When "Rear Output" is chosen, the surround channels 3 and 4
- are output to line-in jack.
-"Mic-In Mode" - an enum control to change the behavior of mic-in
- jack. Either "Mic-In" or "Center/LFE Output" can be
- selected.
- When "Center/LFE Output" is chosen, the center and bass
- channels (channels 5 and 6) are output to mic-in jack.
+"Line-In As Rear" - As mentioned above, the line-in jack is used
+ for the rear (3th and 4th channels) output.
+"Line-In As Bass" - The line-in jack is used for the bass (5th
+ and 6th channels) output.
+"Mic As Center/LFE" - The mic jack is used for the bass output.
+ If this switch is on, you cannot use a microphone as a capture
+ source, of course.
+
Digital I/O
-----------
-The CM8x38 provides the excellent SPDIF capability with very cheap
+The CM8x38 provides the excellent SPDIF capability with very chip
price (yes, that's the reason I bought the card :)
The SPDIF playback and capture are done via the third PCM device
@@ -125,9 +122,8 @@ respectively, so you cannot playback both analog and digital streams
simultaneously.
To enable SPDIF output, you need to turn on "IEC958 Output Switch"
-control via mixer or alsactl ("IEC958" is the official name of
-so-called S/PDIF). Then you'll see the red light on from the card so
-you know that's working obviously :)
+control via mixer or alsactl. Then you'll see the red light on from
+the card so you know that's working obviously :)
The SPDIF input is always enabled, so you can hear SPDIF input data
from line-out with "IEC958 In Monitor" switch at any time (see
below).
@@ -209,10 +205,9 @@ In addition to the standard SB mixer, CM8x38 provides more functions.
MIDI CONTROLLER
---------------
-The MPU401-UART interface is disabled as default. You need to set
-module option "mpu_port" with a valid I/O port address to enable the
-MIDI support. The valid I/O ports are 0x300, 0x310, 0x320 and 0x330.
-Choose the value which doesn't conflict with other cards.
+The MPU401-UART interface is enabled as default only for the first
+(CMIPCI) card. You need to set module option "midi_port" properly
+for the 2nd (CMIPCI) card.
There is _no_ hardware wavetable function on this chip (except for
OPL3 synth below).
@@ -234,11 +229,9 @@ I don't know why..
Joystick and Modem
------------------
-The legacy joystick is supported. To enable the joystick support, pass
-joystick_port=1 module option. The value 1 means the auto-detection.
-If the auto-detection fails, try to pass the exact I/O address.
-
-The modem is enabled dynamically via a card control switch "Modem".
+The joystick and modem should be available by enabling the control
+switch "Joystick" and "Modem" respectively. But I myself have never
+tested them yet.
Debugging Information
diff --git a/trunk/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/trunk/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index db0b7d2dc477..e789475304b6 100644
--- a/trunk/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/trunk/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -371,7 +371,7 @@
create probe() callback.
create remove() callback.
create pci_driver table which contains the three pointers above.
- create init() function just calling pci_register_driver() to register the pci_driver table defined above.
+ create init() function just calling pci_module_init() to register the pci_driver table defined above.
create exit() function to call pci_unregister_driver() function.
@@ -1198,7 +1198,7 @@
/* initialization of the module */
static int __init alsa_card_mychip_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
/* clean up the module */
@@ -1654,7 +1654,7 @@
-
-
- Here as a first value the channel-index is taken to get/set the
- corresponding mixer channel, where 0-63 are the input to output
- fader and 64-127 the playback to outputs fader. Value 0
- is channel muted 0 and 32768 an amplification of 1.
-
- Chn 1-64
-
- fast mixer for the ALSA-mixer utils. The diagonal of the
- mixer-matrix is implemented from playback to output.
-
-
- Line Out
-
- Name -- "Line Out"
-
- Access -- Read Write
-
- Values -- 0 1
-
- Switching on and off the analog out, which has nothing to do
- with mixing or routing. the analog outs reflects channel 63,64.
-
-
---- information (only read access):
-
- Sample Rate
-
- Name -- "System Sample Rate"
-
- Access -- Read-only
-
- getting the sample rate.
-
-
- External Rate measured
-
- Name -- "External Rate"
-
- Access -- Read only
-
-
- Should be "Autosync Rate", but Name used is
- ALSA-Scheme. External Sample frequency liked used on Autosync is
- reported.
-
-
- MADI Sync Status
-
- Name -- "MADI Sync Lock Status"
-
- Access -- Read
-
- Values -- 0,1,2
-
- MADI-Input is 0=Unlocked, 1=Locked, or 2=Synced.
-
-
- Word Clock Sync Status
-
- Name -- "Word Clock Lock Status"
-
- Access -- Read
-
- Values -- 0,1,2
-
- Word Clock Input is 0=Unlocked, 1=Locked, or 2=Synced.
-
- AutoSync
-
- Name -- "AutoSync Reference"
-
- Access -- Read
-
- Values -- "WordClock", "MADI", "None"
-
- Sync-Reference is either "WordClock", "MADI" or none.
-
- RX 64ch --- noch nicht implementiert
-
- MADI-Receiver is in 64 channel mode oder 56 channel mode.
-
-
- AB_inp --- not tested
-
- Used input for Auto-Input.
-
-
- actual Buffer Position --- not implemented
-
- !!! this is a ALSA internal function, so no control is used !!!
-
-
-
-Calling Parameter:
-
- index int array (min = 1, max = 8),
- "Index value for RME HDSPM interface." card-index within ALSA
-
- note: ALSA-standard
-
- id string array (min = 1, max = 8),
- "ID string for RME HDSPM interface."
-
- note: ALSA-standard
-
- enable int array (min = 1, max = 8),
- "Enable/disable specific HDSPM sound-cards."
-
- note: ALSA-standard
-
- precise_ptr int array (min = 1, max = 8),
- "Enable precise pointer, or disable."
-
- note: Use only when the application supports this (which is a special case).
-
- line_outs_monitor int array (min = 1, max = 8),
- "Send playback streams to analog outs by default."
-
-
- note: each playback channel is mixed to the same numbered output
- channel (routed). This is against the ALSA-convention, where all
- channels have to be muted on after loading the driver, but was
- used before on other cards, so i historically use it again)
-
-
-
- enable_monitor int array (min = 1, max = 8),
- "Enable Analog Out on Channel 63/64 by default."
-
- note: here the analog output is enabled (but not routed).
\ No newline at end of file
diff --git a/trunk/drivers/w1/w1_family.h b/trunk/drivers/w1/w1_family.h
index 07fa49412a90..2995c6cb869f 100644
--- a/trunk/drivers/w1/w1_family.h
+++ b/trunk/drivers/w1/w1_family.h
@@ -27,8 +27,10 @@
#include
#define W1_FAMILY_DEFAULT 0
-#define W1_FAMILY_THERM 0x10
#define W1_FAMILY_SMEM 0x01
+#define W1_THERM_DS18S20 0x10
+#define W1_THERM_DS1822 0x22
+#define W1_THERM_DS18B20 0x28
#define MAXNAMELEN 32
diff --git a/trunk/drivers/w1/w1_therm.c b/trunk/drivers/w1/w1_therm.c
index 70310f7a722e..84e8043a4499 100644
--- a/trunk/drivers/w1/w1_therm.c
+++ b/trunk/drivers/w1/w1_therm.c
@@ -53,6 +53,50 @@ static struct w1_family_ops w1_therm_fops = {
.rvalname = "temp1_input",
};
+static struct w1_family w1_therm_family_DS18S20 = {
+ .fid = W1_THERM_DS18S20,
+ .fops = &w1_therm_fops,
+};
+
+static struct w1_family w1_therm_family_DS18B20 = {
+ .fid = W1_THERM_DS18B20,
+ .fops = &w1_therm_fops,
+};
+static struct w1_family w1_therm_family_DS1822 = {
+ .fid = W1_THERM_DS1822,
+ .fops = &w1_therm_fops,
+};
+
+struct w1_therm_family_converter
+{
+ u8 fid;
+ u8 broken;
+ u16 reserved;
+ struct w1_family *f;
+ int (*convert)(u8 rom[9]);
+};
+
+static inline int w1_DS18B20_convert_temp(u8 rom[9]);
+static inline int w1_DS18S20_convert_temp(u8 rom[9]);
+
+static struct w1_therm_family_converter w1_therm_families[] = {
+ {
+ .fid = W1_THERM_DS18S20,
+ .f = &w1_therm_family_DS18S20,
+ .convert = w1_DS18S20_convert_temp
+ },
+ {
+ .fid = W1_THERM_DS1822,
+ .f = &w1_therm_family_DS1822,
+ .convert = w1_DS18B20_convert_temp
+ },
+ {
+ .fid = W1_THERM_DS18B20,
+ .f = &w1_therm_family_DS18B20,
+ .convert = w1_DS18B20_convert_temp
+ },
+};
+
static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
@@ -60,9 +104,19 @@ static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *a
return sprintf(buf, "%s\n", sl->name);
}
-static inline int w1_convert_temp(u8 rom[9])
+static inline int w1_DS18B20_convert_temp(u8 rom[9])
+{
+ int t = (rom[1] << 8) | rom[0];
+ t /= 16;
+ return t;
+}
+
+static inline int w1_DS18S20_convert_temp(u8 rom[9])
{
int t, h;
+
+ if (!rom[7])
+ return 0;
if (rom[1] == 0)
t = ((s32)rom[0] >> 1)*1000;
@@ -77,11 +131,22 @@ static inline int w1_convert_temp(u8 rom[9])
return t;
}
+static inline int w1_convert_temp(u8 rom[9], u8 fid)
+{
+ int i;
+
+ for (i=0; irom));
+ return sprintf(buf, "%d\n", w1_convert_temp(sl->rom, sl->family->fid));
}
static int w1_therm_check_rom(u8 rom[9])
@@ -176,7 +241,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
for (i = 0; i < 9; ++i)
count += sprintf(buf + count, "%02x ", sl->rom[i]);
- count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom));
+ count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom, sl->family->fid));
out:
up(&dev->mutex);
out_dec:
@@ -186,19 +251,26 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
return count;
}
-static struct w1_family w1_therm_family = {
- .fid = W1_FAMILY_THERM,
- .fops = &w1_therm_fops,
-};
-
static int __init w1_therm_init(void)
{
- return w1_register_family(&w1_therm_family);
+ int err, i;
+
+ for (i=0; i center, 0x12 -> lfe */
unsigned char spdif_bug; /* Has Spdif phasing bug */
unsigned char ac97_chip; /* Has an AC97 chip */
unsigned char ecard; /* APS EEPROM */
- const char *driver;
- const char *name;
- const char *id; /* for backward compatibility - can be NULL if not needed */
+ char * driver;
+ char * name;
} emu_chip_details_t;
struct _snd_emu10k1 {
int irq;
unsigned long port; /* I/O port number */
- unsigned int tos_link: 1, /* tos link detected */
- rear_ac97: 1; /* rear channels are on AC'97 */
+ unsigned int APS: 1, /* APS flag */
+ no_ac97: 1, /* no AC'97 */
+ tos_link: 1, /* tos link detected */
+ rear_ac97: 1, /* rear channels are on AC'97 */
+ spk71:1; /* 7.1 configuration (Audigy 2 ZS) */
const emu_chip_details_t *card_capabilities; /* Contains profile of card capabilities */
unsigned int audigy; /* is Audigy? */
unsigned int revision; /* chip revision */
@@ -1127,10 +1109,7 @@ struct _snd_emu10k1 {
emu10k1_voice_t voices[NUM_G];
emu10k1_voice_t p16v_voices[4];
- emu10k1_voice_t p16v_capture_voice;
int p16v_device_offset;
- u32 p16v_capture_source;
- u32 p16v_capture_channel;
emu10k1_pcm_mixer_t pcm_mixer[32];
emu10k1_pcm_mixer_t efx_pcm_mixer[NUM_EFX_PLAYBACK];
snd_kcontrol_t *ctl_send_routing;
@@ -1474,6 +1453,7 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
#endif
typedef struct {
+ unsigned int card; /* card type */
unsigned int internal_tram_size; /* in samples */
unsigned int external_tram_size; /* in samples */
char fxbus_names[16][32]; /* names of FXBUSes */
diff --git a/trunk/include/sound/gus.h b/trunk/include/sound/gus.h
index b4b461ca173d..8b6287a6fff5 100644
--- a/trunk/include/sound/gus.h
+++ b/trunk/include/sound/gus.h
@@ -526,6 +526,9 @@ extern void snd_gf1_adlib_write(snd_gus_card_t * gus, unsigned char reg, unsigne
extern void snd_gf1_dram_addr(snd_gus_card_t * gus, unsigned int addr);
extern void snd_gf1_poke(snd_gus_card_t * gus, unsigned int addr, unsigned char data);
extern unsigned char snd_gf1_peek(snd_gus_card_t * gus, unsigned int addr);
+extern void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data);
+extern unsigned short snd_gf1_peekw(snd_gus_card_t * gus, unsigned int addr);
+extern void snd_gf1_dram_setmem(snd_gus_card_t * gus, unsigned int addr, unsigned short value, unsigned int count);
extern void snd_gf1_write_addr(snd_gus_card_t * gus, unsigned char reg, unsigned int addr, short w_16bit);
extern unsigned int snd_gf1_read_addr(snd_gus_card_t * gus, unsigned char reg, short w_16bit);
extern void snd_gf1_i_ctrl_stop(snd_gus_card_t * gus, unsigned char reg);
@@ -541,6 +544,9 @@ extern inline unsigned short snd_gf1_i_read16(snd_gus_card_t * gus, unsigned cha
{
return snd_gf1_i_look16(gus, reg | 0x80);
}
+extern void snd_gf1_i_adlib_write(snd_gus_card_t * gus, unsigned char reg, unsigned char data);
+extern void snd_gf1_i_write_addr(snd_gus_card_t * gus, unsigned char reg, unsigned int addr, short w_16bit);
+extern unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus, unsigned char reg, short w_16bit);
extern void snd_gf1_select_active_voices(snd_gus_card_t * gus);
@@ -574,6 +580,10 @@ extern void snd_gf1_lfo_command(snd_gus_card_t * gus, int voice, unsigned char *
void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup);
int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block);
+snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
+ unsigned int address);
+snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
+ unsigned int *share_id);
snd_gf1_mem_block_t *snd_gf1_mem_alloc(snd_gf1_mem_t * alloc, int owner,
char *name, int size, int w_16,
int align, unsigned int *share_id);
@@ -598,13 +608,23 @@ int snd_gf1_dma_transfer_block(snd_gus_card_t * gus,
/* gus_volume.c */
unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol);
+unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol);
+unsigned int snd_gf1_calc_ramp_rate(snd_gus_card_t * gus,
+ unsigned short start,
+ unsigned short end,
+ unsigned int us);
unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq2);
+unsigned short snd_gf1_compute_pitchbend(unsigned short pitchbend, unsigned short sens);
+unsigned short snd_gf1_compute_freq(unsigned int freq,
+ unsigned int rate,
+ unsigned short mix_rate);
/* gus_reset.c */
void snd_gf1_set_default_handlers(snd_gus_card_t * gus, unsigned int what);
void snd_gf1_smart_stop_voice(snd_gus_card_t * gus, unsigned short voice);
void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice);
+void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max);
void snd_gf1_stop_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max);
snd_gus_voice_t *snd_gf1_alloc_voice(snd_gus_card_t * gus, int type, int client, int port);
void snd_gf1_free_voice(snd_gus_card_t * gus, snd_gus_voice_t *voice);
@@ -621,6 +641,9 @@ int snd_gf1_pcm_new(snd_gus_card_t * gus, int pcm_dev, int control_index, snd_pc
#ifdef CONFIG_SND_DEBUG
extern void snd_gf1_print_voice_registers(snd_gus_card_t * gus);
+extern void snd_gf1_print_global_registers(snd_gus_card_t * gus);
+extern void snd_gf1_print_setup_registers(snd_gus_card_t * gus);
+extern void snd_gf1_peek_print_block(snd_gus_card_t * gus, unsigned int addr, int count, int w_16bit);
#endif
/* gus.c */
diff --git a/trunk/include/sound/hdspm.h b/trunk/include/sound/hdspm.h
deleted file mode 100644
index c34427ccd0b3..000000000000
--- a/trunk/include/sound/hdspm.h
+++ /dev/null
@@ -1,131 +0,0 @@
-#ifndef __SOUND_HDSPM_H /* -*- linux-c -*- */
-#define __SOUND_HDSPM_H
-/*
- * Copyright (C) 2003 Winfried Ritsch (IEM)
- * based on hdsp.h from Thomas Charbonnel (thomas@undata.org)
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
-#define HDSPM_MAX_CHANNELS 64
-
-/* -------------------- IOCTL Peak/RMS Meters -------------------- */
-
-typedef struct _snd_hdspm_peak_rms hdspm_peak_rms_t;
-
-/* peam rms level structure like we get from hardware
-
- maybe in future we can memory map it so I just copy it
- to user on ioctl call now an dont change anything
- rms are made out of low and high values
- where (long) ????_rms = (????_rms_l >> 8) + ((????_rms_h & 0xFFFFFF00)<<24)
- (i asume so from the code)
-*/
-
-struct _snd_hdspm_peak_rms {
-
- unsigned int level_offset[1024];
-
- unsigned int input_peak[64];
- unsigned int playback_peak[64];
- unsigned int output_peak[64];
- unsigned int xxx_peak[64]; /* not used */
-
- unsigned int reserved[256]; /* not used */
-
- unsigned int input_rms_l[64];
- unsigned int playback_rms_l[64];
- unsigned int output_rms_l[64];
- unsigned int xxx_rms_l[64]; /* not used */
-
- unsigned int input_rms_h[64];
- unsigned int playback_rms_h[64];
- unsigned int output_rms_h[64];
- unsigned int xxx_rms_h[64]; /* not used */
-};
-
-struct sndrv_hdspm_peak_rms_ioctl {
- hdspm_peak_rms_t *peak;
-};
-
-/* use indirect access due to the limit of ioctl bit size */
-#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct sndrv_hdspm_peak_rms_ioctl)
-
-/* ------------ CONFIG block IOCTL ---------------------- */
-
-typedef struct _snd_hdspm_config_info hdspm_config_info_t;
-
-struct _snd_hdspm_config_info {
- unsigned char pref_sync_ref;
- unsigned char wordclock_sync_check;
- unsigned char madi_sync_check;
- unsigned int system_sample_rate;
- unsigned int autosync_sample_rate;
- unsigned char system_clock_mode;
- unsigned char clock_source;
- unsigned char autosync_ref;
- unsigned char line_out;
- unsigned int passthru;
- unsigned int analog_out;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, hdspm_config_info_t)
-
-
-/* get Soundcard Version */
-
-typedef struct _snd_hdspm_version hdspm_version_t;
-
-struct _snd_hdspm_version {
- unsigned short firmware_rev;
-};
-
-#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x43, hdspm_version_t)
-
-
-/* ------------- get Matrix Mixer IOCTL --------------- */
-
-/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte = 32768 Bytes */
-
-/* organisation is 64 channelfader in a continous memory block */
-/* equivalent to hardware definition, maybe for future feature of mmap of them */
-/* each of 64 outputs has 64 infader and 64 outfader:
- Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */
-
-#define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS
-
-typedef struct _snd_hdspm_channelfader snd_hdspm_channelfader_t;
-
-struct _snd_hdspm_channelfader {
- unsigned int in[HDSPM_MIXER_CHANNELS];
- unsigned int pb[HDSPM_MIXER_CHANNELS];
-};
-
-typedef struct _snd_hdspm_mixer hdspm_mixer_t;
-
-struct _snd_hdspm_mixer {
- snd_hdspm_channelfader_t ch[HDSPM_MIXER_CHANNELS];
-};
-
-struct sndrv_hdspm_mixer_ioctl {
- hdspm_mixer_t *mixer;
-};
-
-/* use indirect access due to the limit of ioctl bit size */
-#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct sndrv_hdspm_mixer_ioctl)
-
-#endif /* __SOUND_HDSPM_H */
diff --git a/trunk/include/sound/pcm.h b/trunk/include/sound/pcm.h
index d935417575b5..53fc04d75bad 100644
--- a/trunk/include/sound/pcm.h
+++ b/trunk/include/sound/pcm.h
@@ -848,6 +848,23 @@ int snd_interval_ratnum(snd_interval_t *i,
void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params);
void _snd_pcm_hw_param_setempty(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var);
+int snd_pcm_hw_param_min(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var,
+ unsigned int val, int *dir);
+int snd_pcm_hw_param_max(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var,
+ unsigned int val, int *dir);
+int snd_pcm_hw_param_setinteger(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var);
+int snd_pcm_hw_param_first(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, int *dir);
+int snd_pcm_hw_param_last(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, int *dir);
int snd_pcm_hw_param_near(snd_pcm_substream_t *substream,
snd_pcm_hw_params_t *params,
snd_pcm_hw_param_t var,
@@ -859,6 +876,7 @@ int snd_pcm_hw_param_set(snd_pcm_substream_t *pcm,
int snd_pcm_hw_params_choose(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
int snd_pcm_hw_refine(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
+int snd_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
int snd_pcm_hw_constraints_init(snd_pcm_substream_t *substream);
int snd_pcm_hw_constraints_complete(snd_pcm_substream_t *substream);
@@ -904,22 +922,8 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format);
int snd_pcm_format_linear(snd_pcm_format_t format);
int snd_pcm_format_little_endian(snd_pcm_format_t format);
int snd_pcm_format_big_endian(snd_pcm_format_t format);
-/**
- * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
- * @format: the format to check
- *
- * Returns 1 if the given PCM format is CPU-endian, 0 if
- * opposite, or a negative error code if endian not specified.
- */
-/* int snd_pcm_format_cpu_endian(snd_pcm_format_t format); */
-#ifdef SNDRV_LITTLE_ENDIAN
-#define snd_pcm_format_cpu_endian snd_pcm_format_little_endian
-#else
-#define snd_pcm_format_cpu_endian snd_pcm_format_big_endian
-#endif
int snd_pcm_format_width(snd_pcm_format_t format); /* in bits */
int snd_pcm_format_physical_width(snd_pcm_format_t format); /* in bits */
-ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples);
const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format);
int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames);
snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian);
diff --git a/trunk/include/sound/seq_midi_event.h b/trunk/include/sound/seq_midi_event.h
index 8857e2bd31a5..4357cac07500 100644
--- a/trunk/include/sound/seq_midi_event.h
+++ b/trunk/include/sound/seq_midi_event.h
@@ -41,7 +41,9 @@ struct snd_midi_event_t {
};
int snd_midi_event_new(int bufsize, snd_midi_event_t **rdev);
+int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize);
void snd_midi_event_free(snd_midi_event_t *dev);
+void snd_midi_event_init(snd_midi_event_t *dev);
void snd_midi_event_reset_encode(snd_midi_event_t *dev);
void snd_midi_event_reset_decode(snd_midi_event_t *dev);
void snd_midi_event_no_status(snd_midi_event_t *dev, int on);
diff --git a/trunk/include/sound/seq_virmidi.h b/trunk/include/sound/seq_virmidi.h
index 1ad27e859af3..cf4e2388103f 100644
--- a/trunk/include/sound/seq_virmidi.h
+++ b/trunk/include/sound/seq_virmidi.h
@@ -79,5 +79,6 @@ struct _snd_virmidi_dev {
#define SNDRV_VIRMIDI_SEQ_DISPATCH 2
int snd_virmidi_new(snd_card_t *card, int device, snd_rawmidi_t **rrmidi);
+int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev);
#endif /* __SOUND_SEQ_VIRMIDI */
diff --git a/trunk/include/sound/timer.h b/trunk/include/sound/timer.h
index 1898511a0f38..57fde990606e 100644
--- a/trunk/include/sound/timer.h
+++ b/trunk/include/sound/timer.h
@@ -152,4 +152,6 @@ extern int snd_timer_pause(snd_timer_instance_t * timeri);
extern void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left);
+extern unsigned int snd_timer_system_resolution(void);
+
#endif /* __SOUND_TIMER_H */
diff --git a/trunk/include/sound/version.h b/trunk/include/sound/version.h
index 46acfa8c9988..98b4230778ed 100644
--- a/trunk/include/sound/version.h
+++ b/trunk/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h. Generated by configure. */
-#define CONFIG_SND_VERSION "1.0.9"
-#define CONFIG_SND_DATE " (Sun May 29 07:31:02 2005 UTC)"
+#define CONFIG_SND_VERSION "1.0.9rc2"
+#define CONFIG_SND_DATE " (Thu Mar 24 10:33:39 2005 UTC)"
diff --git a/trunk/net/ipv4/Kconfig b/trunk/net/ipv4/Kconfig
index 567b03b1c349..05107e0dc145 100644
--- a/trunk/net/ipv4/Kconfig
+++ b/trunk/net/ipv4/Kconfig
@@ -2,7 +2,7 @@
# IP configuration
#
choice
- prompt "Choose IP: FIB lookup"
+ prompt "Choose IP: FIB lookup""
depends on INET
default IP_FIB_HASH
diff --git a/trunk/sound/Kconfig b/trunk/sound/Kconfig
index ee794ae06040..047d59ea0573 100644
--- a/trunk/sound/Kconfig
+++ b/trunk/sound/Kconfig
@@ -42,11 +42,6 @@ menu "Advanced Linux Sound Architecture"
config SND
tristate "Advanced Linux Sound Architecture"
depends on SOUND
- help
- Say 'Y' or 'M' to enable ALSA (Advanced Linux Sound Architecture),
- the new base sound system.
-
- For more information, see
source "sound/core/Kconfig"
diff --git a/trunk/sound/arm/Kconfig b/trunk/sound/arm/Kconfig
index 34c1740aa6e9..cdacf4d3a387 100644
--- a/trunk/sound/arm/Kconfig
+++ b/trunk/sound/arm/Kconfig
@@ -14,11 +14,5 @@ config SND_SA11XX_UDA1341
To compile this driver as a module, choose M here: the module
will be called snd-sa11xx-uda1341.
-config SND_ARMAACI
- tristate "ARM PrimeCell PL041 AC Link support"
- depends on SND && ARM_AMBA
- select SND_PCM
- select SND_AC97_CODEC
-
endmenu
diff --git a/trunk/sound/arm/Makefile b/trunk/sound/arm/Makefile
index f74ec28e1068..d7e7dc0c3cdf 100644
--- a/trunk/sound/arm/Makefile
+++ b/trunk/sound/arm/Makefile
@@ -6,6 +6,3 @@ snd-sa11xx-uda1341-objs := sa11xx-uda1341.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o
-
-obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o
-snd-aaci-objs := aaci.o devdma.o
diff --git a/trunk/sound/arm/aaci.c b/trunk/sound/arm/aaci.c
deleted file mode 100644
index 08cc3ddca96f..000000000000
--- a/trunk/sound/arm/aaci.c
+++ /dev/null
@@ -1,968 +0,0 @@
-/*
- * linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver
- *
- * Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Documentation: ARM DDI 0173B
- */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "aaci.h"
-#include "devdma.h"
-
-#define DRIVER_NAME "aaci-pl041"
-
-/*
- * PM support is not complete. Turn it off.
- */
-#undef CONFIG_PM
-
-static void aaci_ac97_select_codec(struct aaci *aaci, ac97_t *ac97)
-{
- u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num);
-
- /*
- * Ensure that the slot 1/2 RX registers are empty.
- */
- v = readl(aaci->base + AACI_SLFR);
- if (v & SLFR_2RXV)
- readl(aaci->base + AACI_SL2RX);
- if (v & SLFR_1RXV)
- readl(aaci->base + AACI_SL1RX);
-
- writel(maincr, aaci->base + AACI_MAINCR);
-}
-
-/*
- * P29:
- * The recommended use of programming the external codec through slot 1
- * and slot 2 data is to use the channels during setup routines and the
- * slot register at any other time. The data written into slot 1, slot 2
- * and slot 12 registers is transmitted only when their corresponding
- * SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR
- * register.
- */
-static void aaci_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
-{
- struct aaci *aaci = ac97->private_data;
- u32 v;
-
- if (ac97->num >= 4)
- return;
-
- down(&aaci->ac97_sem);
-
- aaci_ac97_select_codec(aaci, ac97);
-
- /*
- * P54: You must ensure that AACI_SL2TX is always written
- * to, if required, before data is written to AACI_SL1TX.
- */
- writel(val << 4, aaci->base + AACI_SL2TX);
- writel(reg << 12, aaci->base + AACI_SL1TX);
-
- /*
- * Wait for the transmission of both slots to complete.
- */
- do {
- v = readl(aaci->base + AACI_SLFR);
- } while (v & (SLFR_1TXB|SLFR_2TXB));
-
- up(&aaci->ac97_sem);
-}
-
-/*
- * Read an AC'97 register.
- */
-static unsigned short aaci_ac97_read(ac97_t *ac97, unsigned short reg)
-{
- struct aaci *aaci = ac97->private_data;
- u32 v;
-
- if (ac97->num >= 4)
- return ~0;
-
- down(&aaci->ac97_sem);
-
- aaci_ac97_select_codec(aaci, ac97);
-
- /*
- * Write the register address to slot 1.
- */
- writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX);
-
- /*
- * Wait for the transmission to complete.
- */
- do {
- v = readl(aaci->base + AACI_SLFR);
- } while (v & SLFR_1TXB);
-
- /*
- * Give the AC'97 codec more than enough time
- * to respond. (42us = ~2 frames at 48kHz.)
- */
- udelay(42);
-
- /*
- * Wait for slot 2 to indicate data.
- */
- do {
- cond_resched();
- v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV);
- } while (v != (SLFR_1RXV|SLFR_2RXV));
-
- v = readl(aaci->base + AACI_SL1RX) >> 12;
- if (v == reg) {
- v = readl(aaci->base + AACI_SL2RX) >> 4;
- } else {
- dev_err(&aaci->dev->dev,
- "wrong ac97 register read back (%x != %x)\n",
- v, reg);
- v = ~0;
- }
-
- up(&aaci->ac97_sem);
- return v;
-}
-
-static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun)
-{
- u32 val;
- int timeout = 5000;
-
- do {
- val = readl(aacirun->base + AACI_SR);
- } while (val & (SR_TXB|SR_RXB) && timeout--);
-}
-
-
-
-/*
- * Interrupt support.
- */
-static void aaci_fifo_irq(struct aaci *aaci, u32 mask)
-{
- if (mask & ISR_URINTR) {
- writel(ICLR_TXUEC1, aaci->base + AACI_INTCLR);
- }
-
- if (mask & ISR_TXINTR) {
- struct aaci_runtime *aacirun = &aaci->playback;
- void *ptr;
-
- if (!aacirun->substream || !aacirun->start) {
- dev_warn(&aaci->dev->dev, "TX interrupt???");
- writel(0, aacirun->base + AACI_IE);
- return;
- }
-
- ptr = aacirun->ptr;
- do {
- unsigned int len = aacirun->fifosz;
- u32 val;
-
- if (aacirun->bytes <= 0) {
- aacirun->bytes += aacirun->period;
- aacirun->ptr = ptr;
- spin_unlock(&aaci->lock);
- snd_pcm_period_elapsed(aacirun->substream);
- spin_lock(&aaci->lock);
- }
- if (!(aacirun->cr & TXCR_TXEN))
- break;
-
- val = readl(aacirun->base + AACI_SR);
- if (!(val & SR_TXHE))
- break;
- if (!(val & SR_TXFE))
- len >>= 1;
-
- aacirun->bytes -= len;
-
- /* writing 16 bytes at a time */
- for ( ; len > 0; len -= 16) {
- asm(
- "ldmia %0!, {r0, r1, r2, r3}\n\t"
- "stmia %1, {r0, r1, r2, r3}"
- : "+r" (ptr)
- : "r" (aacirun->fifo)
- : "r0", "r1", "r2", "r3", "cc");
-
- if (ptr >= aacirun->end)
- ptr = aacirun->start;
- }
- } while (1);
-
- aacirun->ptr = ptr;
- }
-}
-
-static irqreturn_t aaci_irq(int irq, void *devid, struct pt_regs *regs)
-{
- struct aaci *aaci = devid;
- u32 mask;
- int i;
-
- spin_lock(&aaci->lock);
- mask = readl(aaci->base + AACI_ALLINTS);
- if (mask) {
- u32 m = mask;
- for (i = 0; i < 4; i++, m >>= 7) {
- if (m & 0x7f) {
- aaci_fifo_irq(aaci, m);
- }
- }
- }
- spin_unlock(&aaci->lock);
-
- return mask ? IRQ_HANDLED : IRQ_NONE;
-}
-
-
-
-/*
- * ALSA support.
- */
-
-struct aaci_stream {
- unsigned char codec_idx;
- unsigned char rate_idx;
-};
-
-static struct aaci_stream aaci_streams[] = {
- [ACSTREAM_FRONT] = {
- .codec_idx = 0,
- .rate_idx = AC97_RATES_FRONT_DAC,
- },
- [ACSTREAM_SURROUND] = {
- .codec_idx = 0,
- .rate_idx = AC97_RATES_SURR_DAC,
- },
- [ACSTREAM_LFE] = {
- .codec_idx = 0,
- .rate_idx = AC97_RATES_LFE_DAC,
- },
-};
-
-static inline unsigned int aaci_rate_mask(struct aaci *aaci, int streamid)
-{
- struct aaci_stream *s = aaci_streams + streamid;
- return aaci->ac97_bus->codec[s->codec_idx]->rates[s->rate_idx];
-}
-
-static unsigned int rate_list[] = {
- 5512, 8000, 11025, 16000, 22050, 32000, 44100,
- 48000, 64000, 88200, 96000, 176400, 192000
-};
-
-/*
- * Double-rate rule: we can support double rate iff channels == 2
- * (unimplemented)
- */
-static int
-aaci_rule_rate_by_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule)
-{
- struct aaci *aaci = rule->private;
- unsigned int rate_mask = SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_5512;
- snd_interval_t *c = hw_param_interval(p, SNDRV_PCM_HW_PARAM_CHANNELS);
-
- switch (c->max) {
- case 6:
- rate_mask &= aaci_rate_mask(aaci, ACSTREAM_LFE);
- case 4:
- rate_mask &= aaci_rate_mask(aaci, ACSTREAM_SURROUND);
- case 2:
- rate_mask &= aaci_rate_mask(aaci, ACSTREAM_FRONT);
- }
-
- return snd_interval_list(hw_param_interval(p, rule->var),
- ARRAY_SIZE(rate_list), rate_list,
- rate_mask);
-}
-
-static snd_pcm_hardware_t aaci_hw_info = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_RESUME,
-
- /*
- * ALSA doesn't support 18-bit or 20-bit packed into 32-bit
- * words. It also doesn't support 12-bit at all.
- */
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
-
- /* should this be continuous or knot? */
- .rates = SNDRV_PCM_RATE_CONTINUOUS,
- .rate_max = 48000,
- .rate_min = 4000,
- .channels_min = 2,
- .channels_max = 6,
- .buffer_bytes_max = 64 * 1024,
- .period_bytes_min = 256,
- .period_bytes_max = PAGE_SIZE,
- .periods_min = 4,
- .periods_max = PAGE_SIZE / 16,
-};
-
-static int aaci_pcm_open(struct aaci *aaci, snd_pcm_substream_t *substream,
- struct aaci_runtime *aacirun)
-{
- snd_pcm_runtime_t *runtime = substream->runtime;
- int ret;
-
- aacirun->substream = substream;
- runtime->private_data = aacirun;
- runtime->hw = aaci_hw_info;
-
- /*
- * FIXME: ALSA specifies fifo_size in bytes. If we're in normal
- * mode, each 32-bit word contains one sample. If we're in
- * compact mode, each 32-bit word contains two samples, effectively
- * halving the FIFO size. However, we don't know for sure which
- * we'll be using at this point. We set this to the lower limit.
- */
- runtime->hw.fifo_size = aaci->fifosize * 2;
-
- /*
- * Add rule describing hardware rate dependency
- * on the number of channels.
- */
- ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
- aaci_rule_rate_by_channels, aaci,
- SNDRV_PCM_HW_PARAM_CHANNELS,
- SNDRV_PCM_HW_PARAM_RATE, -1);
- if (ret)
- goto out;
-
- ret = request_irq(aaci->dev->irq[0], aaci_irq, SA_SHIRQ|SA_INTERRUPT,
- DRIVER_NAME, aaci);
- if (ret)
- goto out;
-
- return 0;
-
- out:
- return ret;
-}
-
-
-/*
- * Common ALSA stuff
- */
-static int aaci_pcm_close(snd_pcm_substream_t *substream)
-{
- struct aaci *aaci = substream->private_data;
- struct aaci_runtime *aacirun = substream->runtime->private_data;
-
- WARN_ON(aacirun->cr & TXCR_TXEN);
-
- aacirun->substream = NULL;
- free_irq(aaci->dev->irq[0], aaci);
-
- return 0;
-}
-
-static int aaci_pcm_hw_free(snd_pcm_substream_t *substream)
-{
- struct aaci_runtime *aacirun = substream->runtime->private_data;
-
- /*
- * This must not be called with the device enabled.
- */
- WARN_ON(aacirun->cr & TXCR_TXEN);
-
- if (aacirun->pcm_open)
- snd_ac97_pcm_close(aacirun->pcm);
- aacirun->pcm_open = 0;
-
- /*
- * Clear out the DMA and any allocated buffers.
- */
- devdma_hw_free(NULL, substream);
-
- return 0;
-}
-
-static int aaci_pcm_hw_params(snd_pcm_substream_t *substream,
- struct aaci_runtime *aacirun,
- snd_pcm_hw_params_t *params)
-{
- int err;
-
- aaci_pcm_hw_free(substream);
-
- err = devdma_hw_alloc(NULL, substream,
- params_buffer_bytes(params));
- if (err < 0)
- goto out;
-
- err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
- params_channels(params),
- aacirun->pcm->r[0].slots);
- if (err)
- goto out;
-
- aacirun->pcm_open = 1;
-
- out:
- return err;
-}
-
-static int aaci_pcm_prepare(snd_pcm_substream_t *substream)
-{
- snd_pcm_runtime_t *runtime = substream->runtime;
- struct aaci_runtime *aacirun = runtime->private_data;
-
- aacirun->start = (void *)runtime->dma_area;
- aacirun->end = aacirun->start + runtime->dma_bytes;
- aacirun->ptr = aacirun->start;
- aacirun->period =
- aacirun->bytes = frames_to_bytes(runtime, runtime->period_size);
-
- return 0;
-}
-
-static snd_pcm_uframes_t aaci_pcm_pointer(snd_pcm_substream_t *substream)
-{
- snd_pcm_runtime_t *runtime = substream->runtime;
- struct aaci_runtime *aacirun = runtime->private_data;
- ssize_t bytes = aacirun->ptr - aacirun->start;
-
- return bytes_to_frames(runtime, bytes);
-}
-
-static int aaci_pcm_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *vma)
-{
- return devdma_mmap(NULL, substream, vma);
-}
-
-
-/*
- * Playback specific ALSA stuff
- */
-static const u32 channels_to_txmask[] = {
- [2] = TXCR_TX3 | TXCR_TX4,
- [4] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8,
- [6] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8 | TXCR_TX6 | TXCR_TX9,
-};
-
-/*
- * We can support two and four channel audio. Unfortunately
- * six channel audio requires a non-standard channel ordering:
- * 2 -> FL(3), FR(4)
- * 4 -> FL(3), FR(4), SL(7), SR(8)
- * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required)
- * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual)
- * This requires an ALSA configuration file to correct.
- */
-static unsigned int channel_list[] = { 2, 4, 6 };
-
-static int
-aaci_rule_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule)
-{
- struct aaci *aaci = rule->private;
- unsigned int chan_mask = 1 << 0, slots;
-
- /*
- * pcms[0] is the our 5.1 PCM instance.
- */
- slots = aaci->ac97_bus->pcms[0].r[0].slots;
- if (slots & (1 << AC97_SLOT_PCM_SLEFT)) {
- chan_mask |= 1 << 1;
- if (slots & (1 << AC97_SLOT_LFE))
- chan_mask |= 1 << 2;
- }
-
- return snd_interval_list(hw_param_interval(p, rule->var),
- ARRAY_SIZE(channel_list), channel_list,
- chan_mask);
-}
-
-static int aaci_pcm_playback_open(snd_pcm_substream_t *substream)
-{
- struct aaci *aaci = substream->private_data;
- int ret;
-
- /*
- * Add rule describing channel dependency.
- */
- ret = snd_pcm_hw_rule_add(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_CHANNELS,
- aaci_rule_channels, aaci,
- SNDRV_PCM_HW_PARAM_CHANNELS, -1);
- if (ret)
- return ret;
-
- return aaci_pcm_open(aaci, substream, &aaci->playback);
-}
-
-static int aaci_pcm_playback_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params)
-{
- struct aaci *aaci = substream->private_data;
- struct aaci_runtime *aacirun = substream->runtime->private_data;
- unsigned int channels = params_channels(params);
- int ret;
-
- WARN_ON(channels >= ARRAY_SIZE(channels_to_txmask) ||
- !channels_to_txmask[channels]);
-
- ret = aaci_pcm_hw_params(substream, aacirun, params);
-
- /*
- * Enable FIFO, compact mode, 16 bits per sample.
- * FIXME: double rate slots?
- */
- if (ret >= 0) {
- aacirun->cr = TXCR_FEN | TXCR_COMPACT | TXCR_TSZ16;
- aacirun->cr |= channels_to_txmask[channels];
-
- aacirun->fifosz = aaci->fifosize * 4;
- if (aacirun->cr & TXCR_COMPACT)
- aacirun->fifosz >>= 1;
- }
- return ret;
-}
-
-static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)
-{
- u32 ie;
-
- ie = readl(aacirun->base + AACI_IE);
- ie &= ~(IE_URIE|IE_TXIE);
- writel(ie, aacirun->base + AACI_IE);
- aacirun->cr &= ~TXCR_TXEN;
- aaci_chan_wait_ready(aacirun);
- writel(aacirun->cr, aacirun->base + AACI_TXCR);
-}
-
-static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
-{
- u32 ie;
-
- aaci_chan_wait_ready(aacirun);
- aacirun->cr |= TXCR_TXEN;
-
- ie = readl(aacirun->base + AACI_IE);
- ie |= IE_URIE | IE_TXIE;
- writel(ie, aacirun->base + AACI_IE);
- writel(aacirun->cr, aacirun->base + AACI_TXCR);
-}
-
-static int aaci_pcm_playback_trigger(snd_pcm_substream_t *substream, int cmd)
-{
- struct aaci *aaci = substream->private_data;
- struct aaci_runtime *aacirun = substream->runtime->private_data;
- unsigned long flags;
- int ret = 0;
-
- spin_lock_irqsave(&aaci->lock, flags);
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- aaci_pcm_playback_start(aacirun);
- break;
-
- case SNDRV_PCM_TRIGGER_RESUME:
- aaci_pcm_playback_start(aacirun);
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- aaci_pcm_playback_stop(aacirun);
- break;
-
- case SNDRV_PCM_TRIGGER_SUSPEND:
- aaci_pcm_playback_stop(aacirun);
- break;
-
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- break;
-
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- break;
-
- default:
- ret = -EINVAL;
- }
- spin_unlock_irqrestore(&aaci->lock, flags);
-
- return ret;
-}
-
-static snd_pcm_ops_t aaci_playback_ops = {
- .open = aaci_pcm_playback_open,
- .close = aaci_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = aaci_pcm_playback_hw_params,
- .hw_free = aaci_pcm_hw_free,
- .prepare = aaci_pcm_prepare,
- .trigger = aaci_pcm_playback_trigger,
- .pointer = aaci_pcm_pointer,
- .mmap = aaci_pcm_mmap,
-};
-
-
-
-/*
- * Power Management.
- */
-#ifdef CONFIG_PM
-static int aaci_do_suspend(snd_card_t *card, unsigned int state)
-{
- struct aaci *aaci = card->private_data;
- if (aaci->card->power_state != SNDRV_CTL_POWER_D3cold) {
- snd_pcm_suspend_all(aaci->pcm);
- snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D3cold);
- }
- return 0;
-}
-
-static int aaci_do_resume(snd_card_t *card, unsigned int state)
-{
- struct aaci *aaci = card->private_data;
- if (aaci->card->power_state != SNDRV_CTL_POWER_D0) {
- snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D0);
- }
- return 0;
-}
-
-static int aaci_suspend(struct amba_device *dev, u32 state)
-{
- snd_card_t *card = amba_get_drvdata(dev);
- return card ? aaci_do_suspend(card) : 0;
-}
-
-static int aaci_resume(struct amba_device *dev)
-{
- snd_card_t *card = amba_get_drvdata(dev);
- return card ? aaci_do_resume(card) : 0;
-}
-#else
-#define aaci_do_suspend NULL
-#define aaci_do_resume NULL
-#define aaci_suspend NULL
-#define aaci_resume NULL
-#endif
-
-
-static struct ac97_pcm ac97_defs[] __devinitdata = {
- [0] = { /* Front PCM */
- .exclusive = 1,
- .r = {
- [0] = {
- .slots = (1 << AC97_SLOT_PCM_LEFT) |
- (1 << AC97_SLOT_PCM_RIGHT) |
- (1 << AC97_SLOT_PCM_CENTER) |
- (1 << AC97_SLOT_PCM_SLEFT) |
- (1 << AC97_SLOT_PCM_SRIGHT) |
- (1 << AC97_SLOT_LFE),
- },
- },
- },
- [1] = { /* PCM in */
- .stream = 1,
- .exclusive = 1,
- .r = {
- [0] = {
- .slots = (1 << AC97_SLOT_PCM_LEFT) |
- (1 << AC97_SLOT_PCM_RIGHT),
- },
- },
- },
- [2] = { /* Mic in */
- .stream = 1,
- .exclusive = 1,
- .r = {
- [0] = {
- .slots = (1 << AC97_SLOT_MIC),
- },
- },
- }
-};
-
-static ac97_bus_ops_t aaci_bus_ops = {
- .write = aaci_ac97_write,
- .read = aaci_ac97_read,
-};
-
-static int __devinit aaci_probe_ac97(struct aaci *aaci)
-{
- ac97_template_t ac97_template;
- ac97_bus_t *ac97_bus;
- ac97_t *ac97;
- int ret;
-
- /*
- * Assert AACIRESET for 2us
- */
- writel(0, aaci->base + AACI_RESET);
- udelay(2);
- writel(RESET_NRST, aaci->base + AACI_RESET);
-
- /*
- * Give the AC'97 codec more than enough time
- * to wake up. (42us = ~2 frames at 48kHz.)
- */
- udelay(42);
-
- ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus);
- if (ret)
- goto out;
-
- ac97_bus->clock = 48000;
- aaci->ac97_bus = ac97_bus;
-
- memset(&ac97_template, 0, sizeof(ac97_template_t));
- ac97_template.private_data = aaci;
- ac97_template.num = 0;
- ac97_template.scaps = AC97_SCAP_SKIP_MODEM;
-
- ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);
- if (ret)
- goto out;
-
- /*
- * Disable AC97 PC Beep input on audio codecs.
- */
- if (ac97_is_audio(ac97))
- snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e);
-
- ret = snd_ac97_pcm_assign(ac97_bus, ARRAY_SIZE(ac97_defs), ac97_defs);
- if (ret)
- goto out;
-
- aaci->playback.pcm = &ac97_bus->pcms[0];
-
- out:
- return ret;
-}
-
-static void aaci_free_card(snd_card_t *card)
-{
- struct aaci *aaci = card->private_data;
- if (aaci->base)
- iounmap(aaci->base);
-}
-
-static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
-{
- struct aaci *aaci;
- snd_card_t *card;
-
- card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
- THIS_MODULE, sizeof(struct aaci));
- if (card == NULL)
- return ERR_PTR(-ENOMEM);
-
- card->private_free = aaci_free_card;
- snd_card_set_pm_callback(card, aaci_do_suspend, aaci_do_resume, NULL);
-
- strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
- strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));
- snprintf(card->longname, sizeof(card->longname),
- "%s at 0x%08lx, irq %d",
- card->shortname, dev->res.start, dev->irq[0]);
-
- aaci = card->private_data;
- init_MUTEX(&aaci->ac97_sem);
- spin_lock_init(&aaci->lock);
- aaci->card = card;
- aaci->dev = dev;
-
- /* Set MAINCR to allow slot 1 and 2 data IO */
- aaci->maincr = MAINCR_IE | MAINCR_SL1RXEN | MAINCR_SL1TXEN |
- MAINCR_SL2RXEN | MAINCR_SL2TXEN;
-
- return aaci;
-}
-
-static int __devinit aaci_init_pcm(struct aaci *aaci)
-{
- snd_pcm_t *pcm;
- int ret;
-
- ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 0, &pcm);
- if (ret == 0) {
- aaci->pcm = pcm;
- pcm->private_data = aaci;
- pcm->info_flags = 0;
-
- strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
-
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
- }
-
- return ret;
-}
-
-static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
-{
- void *base = aaci->base + AACI_CSCH1;
- int i;
-
- writel(TXCR_FEN | TXCR_TSZ16 | TXCR_TXEN, base + AACI_TXCR);
-
- for (i = 0; !(readl(base + AACI_SR) & SR_TXFF) && i < 4096; i++)
- writel(0, aaci->base + AACI_DR1);
-
- writel(0, base + AACI_TXCR);
-
- /*
- * Re-initialise the AACI after the FIFO depth test, to
- * ensure that the FIFOs are empty. Unfortunately, merely
- * disabling the channel doesn't clear the FIFO.
- */
- writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR);
- writel(aaci->maincr, aaci->base + AACI_MAINCR);
-
- /*
- * If we hit 4096, we failed. Go back to the specified
- * fifo depth.
- */
- if (i == 4096)
- i = 8;
-
- return i;
-}
-
-static int __devinit aaci_probe(struct amba_device *dev, void *id)
-{
- struct aaci *aaci;
- int ret, i;
-
- ret = amba_request_regions(dev, NULL);
- if (ret)
- return ret;
-
- aaci = aaci_init_card(dev);
- if (IS_ERR(aaci)) {
- ret = PTR_ERR(aaci);
- goto out;
- }
-
- aaci->base = ioremap(dev->res.start, SZ_4K);
- if (!aaci->base) {
- ret = -ENOMEM;
- goto out;
- }
-
- /*
- * Playback uses AACI channel 0
- */
- aaci->playback.base = aaci->base + AACI_CSCH1;
- aaci->playback.fifo = aaci->base + AACI_DR1;
-
- for (i = 0; i < 4; i++) {
- void *base = aaci->base + i * 0x14;
-
- writel(0, base + AACI_IE);
- writel(0, base + AACI_TXCR);
- writel(0, base + AACI_RXCR);
- }
-
- writel(0x1fff, aaci->base + AACI_INTCLR);
- writel(aaci->maincr, aaci->base + AACI_MAINCR);
-
- /*
- * Size the FIFOs.
- */
- aaci->fifosize = aaci_size_fifo(aaci);
-
- ret = aaci_probe_ac97(aaci);
- if (ret)
- goto out;
-
- ret = aaci_init_pcm(aaci);
- if (ret)
- goto out;
-
- ret = snd_card_register(aaci->card);
- if (ret == 0) {
- dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname,
- aaci->fifosize);
- amba_set_drvdata(dev, aaci->card);
- return ret;
- }
-
- out:
- if (aaci)
- snd_card_free(aaci->card);
- amba_release_regions(dev);
- return ret;
-}
-
-static int __devexit aaci_remove(struct amba_device *dev)
-{
- snd_card_t *card = amba_get_drvdata(dev);
-
- amba_set_drvdata(dev, NULL);
-
- if (card) {
- struct aaci *aaci = card->private_data;
- writel(0, aaci->base + AACI_MAINCR);
-
- snd_card_free(card);
- amba_release_regions(dev);
- }
-
- return 0;
-}
-
-static struct amba_id aaci_ids[] = {
- {
- .id = 0x00041041,
- .mask = 0x000fffff,
- },
- { 0, 0 },
-};
-
-static struct amba_driver aaci_driver = {
- .drv = {
- .name = DRIVER_NAME,
- },
- .probe = aaci_probe,
- .remove = __devexit_p(aaci_remove),
- .suspend = aaci_suspend,
- .resume = aaci_resume,
- .id_table = aaci_ids,
-};
-
-static int __init aaci_init(void)
-{
- return amba_driver_register(&aaci_driver);
-}
-
-static void __exit aaci_exit(void)
-{
- amba_driver_unregister(&aaci_driver);
-}
-
-module_init(aaci_init);
-module_exit(aaci_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("ARM PrimeCell PL041 Advanced Audio CODEC Interface driver");
diff --git a/trunk/sound/arm/aaci.h b/trunk/sound/arm/aaci.h
deleted file mode 100644
index d752e6426894..000000000000
--- a/trunk/sound/arm/aaci.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver
- *
- * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef AACI_H
-#define AACI_H
-
-/*
- * Control and status register offsets
- * P39.
- */
-#define AACI_CSCH1 0x000
-#define AACI_CSCH2 0x014
-#define AACI_CSCH3 0x028
-#define AACI_CSCH4 0x03c
-
-#define AACI_RXCR 0x000 /* 29 bits Control Rx FIFO */
-#define AACI_TXCR 0x004 /* 17 bits Control Tx FIFO */
-#define AACI_SR 0x008 /* 12 bits Status */
-#define AACI_ISR 0x00c /* 7 bits Int Status */
-#define AACI_IE 0x010 /* 7 bits Int Enable */
-
-/*
- * Other registers
- */
-#define AACI_SL1RX 0x050
-#define AACI_SL1TX 0x054
-#define AACI_SL2RX 0x058
-#define AACI_SL2TX 0x05c
-#define AACI_SL12RX 0x060
-#define AACI_SL12TX 0x064
-#define AACI_SLFR 0x068 /* slot flags */
-#define AACI_SLISTAT 0x06c /* slot interrupt status */
-#define AACI_SLIEN 0x070 /* slot interrupt enable */
-#define AACI_INTCLR 0x074 /* interrupt clear */
-#define AACI_MAINCR 0x078 /* main control */
-#define AACI_RESET 0x07c /* reset control */
-#define AACI_SYNC 0x080 /* sync control */
-#define AACI_ALLINTS 0x084 /* all fifo interrupt status */
-#define AACI_MAINFR 0x088 /* main flag register */
-#define AACI_DR1 0x090 /* data read/written fifo 1 */
-#define AACI_DR2 0x0b0 /* data read/written fifo 2 */
-#define AACI_DR3 0x0d0 /* data read/written fifo 3 */
-#define AACI_DR4 0x0f0 /* data read/written fifo 4 */
-
-/*
- * transmit fifo control register. P48
- */
-#define TXCR_FEN (1 << 16) /* fifo enable */
-#define TXCR_COMPACT (1 << 15) /* compact mode */
-#define TXCR_TSZ16 (0 << 13) /* 16 bits */
-#define TXCR_TSZ18 (1 << 13) /* 18 bits */
-#define TXCR_TSZ20 (2 << 13) /* 20 bits */
-#define TXCR_TSZ12 (3 << 13) /* 12 bits */
-#define TXCR_TX12 (1 << 12) /* transmits slot 12 */
-#define TXCR_TX11 (1 << 11) /* transmits slot 12 */
-#define TXCR_TX10 (1 << 10) /* transmits slot 12 */
-#define TXCR_TX9 (1 << 9) /* transmits slot 12 */
-#define TXCR_TX8 (1 << 8) /* transmits slot 12 */
-#define TXCR_TX7 (1 << 7) /* transmits slot 12 */
-#define TXCR_TX6 (1 << 6) /* transmits slot 12 */
-#define TXCR_TX5 (1 << 5) /* transmits slot 12 */
-#define TXCR_TX4 (1 << 4) /* transmits slot 12 */
-#define TXCR_TX3 (1 << 3) /* transmits slot 12 */
-#define TXCR_TX2 (1 << 2) /* transmits slot 12 */
-#define TXCR_TX1 (1 << 1) /* transmits slot 12 */
-#define TXCR_TXEN (1 << 0) /* transmit enable */
-
-/*
- * status register bits. P49
- */
-#define SR_RXTOFE (1 << 11) /* rx timeout fifo empty */
-#define SR_TXTO (1 << 10) /* rx timeout fifo nonempty */
-#define SR_TXU (1 << 9) /* tx underrun */
-#define SR_RXO (1 << 8) /* rx overrun */
-#define SR_TXB (1 << 7) /* tx busy */
-#define SR_RXB (1 << 6) /* rx busy */
-#define SR_TXFF (1 << 5) /* tx fifo full */
-#define SR_RXFF (1 << 4) /* rx fifo full */
-#define SR_TXHE (1 << 3) /* tx fifo half empty */
-#define SR_RXHF (1 << 2) /* rx fifo half full */
-#define SR_TXFE (1 << 1) /* tx fifo empty */
-#define SR_RXFE (1 << 0) /* rx fifo empty */
-
-/*
- * interrupt status register bits.
- */
-#define ISR_RXTOFEINTR (1 << 6) /* rx fifo empty */
-#define ISR_URINTR (1 << 5) /* tx underflow */
-#define ISR_ORINTR (1 << 4) /* rx overflow */
-#define ISR_RXINTR (1 << 3) /* rx fifo */
-#define ISR_TXINTR (1 << 2) /* tx fifo intr */
-#define ISR_RXTOINTR (1 << 1) /* tx timeout */
-#define ISR_TXCINTR (1 << 0) /* tx complete */
-
-/*
- * interrupt enable register bits.
- */
-#define IE_RXTOIE (1 << 6)
-#define IE_URIE (1 << 5)
-#define IE_ORIE (1 << 4)
-#define IE_RXIE (1 << 3)
-#define IE_TXIE (1 << 2)
-#define IE_RXTIE (1 << 1)
-#define IE_TXCIE (1 << 0)
-
-/*
- * interrupt status. P51
- */
-#define ISR_RXTOFE (1 << 6) /* rx timeout fifo empty */
-#define ISR_UR (1 << 5) /* tx fifo underrun */
-#define ISR_OR (1 << 4) /* rx fifo overrun */
-#define ISR_RX (1 << 3) /* rx interrupt status */
-#define ISR_TX (1 << 2) /* tx interrupt status */
-#define ISR_RXTO (1 << 1) /* rx timeout */
-#define ISR_TXC (1 << 0) /* tx complete */
-
-/*
- * interrupt enable. P52
- */
-#define IE_RXTOFE (1 << 6) /* rx timeout fifo empty */
-#define IE_UR (1 << 5) /* tx fifo underrun */
-#define IE_OR (1 << 4) /* rx fifo overrun */
-#define IE_RX (1 << 3) /* rx interrupt status */
-#define IE_TX (1 << 2) /* tx interrupt status */
-#define IE_RXTO (1 << 1) /* rx timeout */
-#define IE_TXC (1 << 0) /* tx complete */
-
-/*
- * slot flag register bits. P56
- */
-#define SLFR_RWIS (1 << 13) /* raw wake-up interrupt status */
-#define SLFR_RGPIOINTR (1 << 12) /* raw gpio interrupt */
-#define SLFR_12TXE (1 << 11) /* slot 12 tx empty */
-#define SLFR_12RXV (1 << 10) /* slot 12 rx valid */
-#define SLFR_2TXE (1 << 9) /* slot 2 tx empty */
-#define SLFR_2RXV (1 << 8) /* slot 2 rx valid */
-#define SLFR_1TXE (1 << 7) /* slot 1 tx empty */
-#define SLFR_1RXV (1 << 6) /* slot 1 rx valid */
-#define SLFR_12TXB (1 << 5) /* slot 12 tx busy */
-#define SLFR_12RXB (1 << 4) /* slot 12 rx busy */
-#define SLFR_2TXB (1 << 3) /* slot 2 tx busy */
-#define SLFR_2RXB (1 << 2) /* slot 2 rx busy */
-#define SLFR_1TXB (1 << 1) /* slot 1 tx busy */
-#define SLFR_1RXB (1 << 0) /* slot 1 rx busy */
-
-/*
- * Interrupt clear register.
- */
-#define ICLR_RXTOFEC4 (1 << 12)
-#define ICLR_RXTOFEC3 (1 << 11)
-#define ICLR_RXTOFEC2 (1 << 10)
-#define ICLR_RXTOFEC1 (1 << 9)
-#define ICLR_TXUEC4 (1 << 8)
-#define ICLR_TXUEC3 (1 << 7)
-#define ICLR_TXUEC2 (1 << 6)
-#define ICLR_TXUEC1 (1 << 5)
-#define ICLR_RXOEC4 (1 << 4)
-#define ICLR_RXOEC3 (1 << 3)
-#define ICLR_RXOEC2 (1 << 2)
-#define ICLR_RXOEC1 (1 << 1)
-#define ICLR_WISC (1 << 0)
-
-/*
- * Main control register bits. P62
- */
-#define MAINCR_SCRA(x) ((x) << 10) /* secondary codec reg access */
-#define MAINCR_DMAEN (1 << 9) /* dma enable */
-#define MAINCR_SL12TXEN (1 << 8) /* slot 12 transmit enable */
-#define MAINCR_SL12RXEN (1 << 7) /* slot 12 receive enable */
-#define MAINCR_SL2TXEN (1 << 6) /* slot 2 transmit enable */
-#define MAINCR_SL2RXEN (1 << 5) /* slot 2 receive enable */
-#define MAINCR_SL1TXEN (1 << 4) /* slot 1 transmit enable */
-#define MAINCR_SL1RXEN (1 << 3) /* slot 1 receive enable */
-#define MAINCR_LPM (1 << 2) /* low power mode */
-#define MAINCR_LOOPBK (1 << 1) /* loopback */
-#define MAINCR_IE (1 << 0) /* aaci interface enable */
-
-/*
- * Reset register bits. P65
- */
-#define RESET_NRST (1 << 0)
-
-/*
- * Sync register bits. P65
- */
-#define SYNC_FORCE (1 << 0)
-
-/*
- * Main flag register bits. P66
- */
-#define MAINFR_TXB (1 << 1) /* transmit busy */
-#define MAINFR_RXB (1 << 0) /* receive busy */
-
-
-
-struct aaci_runtime {
- void *base;
- void *fifo;
-
- struct ac97_pcm *pcm;
- int pcm_open;
-
- u32 cr;
- snd_pcm_substream_t *substream;
-
- /*
- * PIO support
- */
- void *start;
- void *end;
- void *ptr;
- int bytes;
- unsigned int period;
- unsigned int fifosz;
-};
-
-struct aaci {
- struct amba_device *dev;
- snd_card_t *card;
- void *base;
- unsigned int fifosize;
-
- /* AC'97 */
- struct semaphore ac97_sem;
- ac97_bus_t *ac97_bus;
-
- u32 maincr;
- spinlock_t lock;
-
- struct aaci_runtime playback;
- struct aaci_runtime capture;
-
- snd_pcm_t *pcm;
-};
-
-#define ACSTREAM_FRONT 0
-#define ACSTREAM_SURROUND 1
-#define ACSTREAM_LFE 2
-
-#endif
diff --git a/trunk/sound/arm/devdma.c b/trunk/sound/arm/devdma.c
deleted file mode 100644
index 60826a5324b4..000000000000
--- a/trunk/sound/arm/devdma.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * linux/sound/arm/devdma.c
- *
- * Copyright (C) 2003-2004 Russell King, All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * ARM DMA shim for ALSA.
- */
-#include
-#include
-
-#include
-#include
-#include
-
-#include "devdma.h"
-
-void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream)
-{
- snd_pcm_runtime_t *runtime = substream->runtime;
- struct snd_dma_buffer *buf = runtime->dma_buffer_p;
-
- if (runtime->dma_area == NULL)
- return;
-
- if (buf != &substream->dma_buffer) {
- dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, buf->addr);
- kfree(runtime->dma_buffer_p);
- }
-
- snd_pcm_set_runtime_buffer(substream, NULL);
-}
-
-int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t size)
-{
- snd_pcm_runtime_t *runtime = substream->runtime;
- struct snd_dma_buffer *buf = runtime->dma_buffer_p;
- int ret = 0;
-
- if (buf) {
- if (buf->bytes >= size)
- goto out;
- devdma_hw_free(dev, substream);
- }
-
- if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
- buf = &substream->dma_buffer;
- } else {
- buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL);
- if (!buf)
- goto nomem;
-
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = dev;
- buf->area = dma_alloc_coherent(dev, size, &buf->addr, GFP_KERNEL);
- buf->bytes = size;
- buf->private_data = NULL;
-
- if (!buf->area)
- goto free;
- }
- snd_pcm_set_runtime_buffer(substream, buf);
- ret = 1;
- out:
- runtime->dma_bytes = size;
- return ret;
-
- free:
- kfree(buf);
- nomem:
- return -ENOMEM;
-}
-
-int devdma_mmap(struct device *dev, snd_pcm_substream_t *substream, struct vm_area_struct *vma)
-{
- snd_pcm_runtime_t *runtime = substream->runtime;
- return dma_mmap_coherent(dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
-}
diff --git a/trunk/sound/arm/devdma.h b/trunk/sound/arm/devdma.h
deleted file mode 100644
index 5a33b6bacc34..000000000000
--- a/trunk/sound/arm/devdma.h
+++ /dev/null
@@ -1,3 +0,0 @@
-void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream);
-int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t size);
-int devdma_mmap(struct device *dev, snd_pcm_substream_t *substream, struct vm_area_struct *vma);
diff --git a/trunk/sound/core/control.c b/trunk/sound/core/control.c
index 227f3cf02771..f4ea6bff1dd3 100644
--- a/trunk/sound/core/control.c
+++ b/trunk/sound/core/control.c
@@ -215,7 +215,7 @@ snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control, unsigned int access)
*
* Returns the pointer of the newly generated instance, or NULL on failure.
*/
-snd_kcontrol_t *snd_ctl_new1(const snd_kcontrol_new_t * ncontrol, void *private_data)
+snd_kcontrol_t *snd_ctl_new1(snd_kcontrol_new_t * ncontrol, void *private_data)
{
snd_kcontrol_t kctl;
unsigned int access;
@@ -1102,7 +1102,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
}
}
up_read(&snd_ioctl_rwsem);
- snd_printdd("unknown ioctl = 0x%x\n", cmd);
+ snd_printd("unknown ioctl = 0x%x\n", cmd);
return -ENOTTY;
}
diff --git a/trunk/sound/core/memalloc.c b/trunk/sound/core/memalloc.c
index dbc23e35fa06..344a83fd7c2e 100644
--- a/trunk/sound/core/memalloc.c
+++ b/trunk/sound/core/memalloc.c
@@ -28,7 +28,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -47,6 +46,13 @@ MODULE_LICENSE("GPL");
#define SNDRV_CARDS 8
#endif
+/* FIXME: so far only some PCI devices have the preallocation table */
+#ifdef CONFIG_PCI
+static int enable[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable cards to allocate buffers.");
+#endif
+
/*
*/
@@ -445,13 +451,9 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
list_for_each(p, &mem_list_head) {
mem = list_entry(p, struct snd_mem_list, list);
if (mem->id == id &&
- (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL ||
- ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) {
- struct device *dev = dmab->dev.dev;
+ ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev))) {
list_del(p);
*dmab = mem->buffer;
- if (dmab->dev.dev == NULL)
- dmab->dev.dev = dev;
kfree(mem);
up(&list_mutex);
return dmab->bytes;
@@ -506,13 +508,91 @@ static void free_all_reserved_pages(void)
}
+
+/*
+ * allocation of buffers for pre-defined devices
+ */
+
+#ifdef CONFIG_PCI
+/* FIXME: for pci only - other bus? */
+struct prealloc_dev {
+ unsigned short vendor;
+ unsigned short device;
+ unsigned long dma_mask;
+ unsigned int size;
+ unsigned int buffers;
+};
+
+#define HAMMERFALL_BUFFER_SIZE (16*1024*4*(26+1)+0x10000)
+
+static struct prealloc_dev prealloc_devices[] __initdata = {
+ {
+ /* hammerfall */
+ .vendor = 0x10ee,
+ .device = 0x3fc4,
+ .dma_mask = 0xffffffff,
+ .size = HAMMERFALL_BUFFER_SIZE,
+ .buffers = 2
+ },
+ {
+ /* HDSP */
+ .vendor = 0x10ee,
+ .device = 0x3fc5,
+ .dma_mask = 0xffffffff,
+ .size = HAMMERFALL_BUFFER_SIZE,
+ .buffers = 2
+ },
+ { }, /* terminator */
+};
+
+static void __init preallocate_cards(void)
+{
+ struct pci_dev *pci = NULL;
+ int card;
+
+ card = 0;
+
+ while ((pci = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci)) != NULL) {
+ struct prealloc_dev *dev;
+ unsigned int i;
+ if (card >= SNDRV_CARDS)
+ break;
+ for (dev = prealloc_devices; dev->vendor; dev++) {
+ if (dev->vendor == pci->vendor && dev->device == pci->device)
+ break;
+ }
+ if (! dev->vendor)
+ continue;
+ if (! enable[card++]) {
+ printk(KERN_DEBUG "snd-page-alloc: skipping card %d, device %04x:%04x\n", card, pci->vendor, pci->device);
+ continue;
+ }
+
+ if (pci_set_dma_mask(pci, dev->dma_mask) < 0 ||
+ pci_set_consistent_dma_mask(pci, dev->dma_mask) < 0) {
+ printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", dev->dma_mask, dev->vendor, dev->device);
+ continue;
+ }
+ for (i = 0; i < dev->buffers; i++) {
+ struct snd_dma_buffer dmab;
+ memset(&dmab, 0, sizeof(dmab));
+ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+ dev->size, &dmab) < 0)
+ printk(KERN_WARNING "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", dev->size);
+ else
+ snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
+ }
+ }
+}
+#else
+#define preallocate_cards() /* NOP */
+#endif
+
+
#ifdef CONFIG_PROC_FS
/*
* proc file interface
*/
-#define SND_MEM_PROC_FILE "driver/snd-page-alloc"
-struct proc_dir_entry *snd_mem_proc;
-
static int snd_mem_proc_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
@@ -541,97 +621,6 @@ static int snd_mem_proc_read(char *page, char **start, off_t off,
up(&list_mutex);
return len;
}
-
-/* FIXME: for pci only - other bus? */
-#ifdef CONFIG_PCI
-#define gettoken(bufp) strsep(bufp, " \t\n")
-
-static int snd_mem_proc_write(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
-{
- char buf[128];
- char *token, *p;
-
- if (count > ARRAY_SIZE(buf) - 1)
- count = ARRAY_SIZE(buf) - 1;
- if (copy_from_user(buf, buffer, count))
- return -EFAULT;
- buf[ARRAY_SIZE(buf) - 1] = '\0';
-
- p = buf;
- token = gettoken(&p);
- if (! token || *token == '#')
- return (int)count;
- if (strcmp(token, "add") == 0) {
- char *endp;
- int vendor, device, size, buffers;
- long mask;
- int i, alloced;
- struct pci_dev *pci;
-
- if ((token = gettoken(&p)) == NULL ||
- (vendor = simple_strtol(token, NULL, 0)) <= 0 ||
- (token = gettoken(&p)) == NULL ||
- (device = simple_strtol(token, NULL, 0)) <= 0 ||
- (token = gettoken(&p)) == NULL ||
- (mask = simple_strtol(token, NULL, 0)) < 0 ||
- (token = gettoken(&p)) == NULL ||
- (size = memparse(token, &endp)) < 64*1024 ||
- size > 16*1024*1024 /* too big */ ||
- (token = gettoken(&p)) == NULL ||
- (buffers = simple_strtol(token, NULL, 0)) <= 0 ||
- buffers > 4) {
- printk(KERN_ERR "snd-page-alloc: invalid proc write format\n");
- return (int)count;
- }
- vendor &= 0xffff;
- device &= 0xffff;
-
- alloced = 0;
- pci = NULL;
- while ((pci = pci_find_device(vendor, device, pci)) != NULL) {
- if (mask > 0 && mask < 0xffffffff) {
- if (pci_set_dma_mask(pci, mask) < 0 ||
- pci_set_consistent_dma_mask(pci, mask) < 0) {
- printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device);
- return (int)count;
- }
- }
- for (i = 0; i < buffers; i++) {
- struct snd_dma_buffer dmab;
- memset(&dmab, 0, sizeof(dmab));
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
- size, &dmab) < 0) {
- printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
- return (int)count;
- }
- snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
- }
- alloced++;
- }
- if (! alloced) {
- for (i = 0; i < buffers; i++) {
- struct snd_dma_buffer dmab;
- memset(&dmab, 0, sizeof(dmab));
- /* FIXME: We can allocate only in ZONE_DMA
- * without a device pointer!
- */
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, NULL,
- size, &dmab) < 0) {
- printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
- break;
- }
- snd_dma_reserve_buf(&dmab, (unsigned int)((vendor << 16) | device));
- }
- }
- } else if (strcmp(token, "erase") == 0)
- /* FIXME: need for releasing each buffer chunk? */
- free_all_reserved_pages();
- else
- printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n");
- return (int)count;
-}
-#endif /* CONFIG_PCI */
#endif /* CONFIG_PROC_FS */
/*
@@ -641,21 +630,15 @@ static int snd_mem_proc_write(struct file *file, const char __user *buffer,
static int __init snd_mem_init(void)
{
#ifdef CONFIG_PROC_FS
- snd_mem_proc = create_proc_entry(SND_MEM_PROC_FILE, 0644, NULL);
- if (snd_mem_proc) {
- snd_mem_proc->read_proc = snd_mem_proc_read;
-#ifdef CONFIG_PCI
- snd_mem_proc->write_proc = snd_mem_proc_write;
-#endif
- }
+ create_proc_read_entry("driver/snd-page-alloc", 0, NULL, snd_mem_proc_read, NULL);
#endif
+ preallocate_cards();
return 0;
}
static void __exit snd_mem_exit(void)
{
- if (snd_mem_proc)
- remove_proc_entry(SND_MEM_PROC_FILE, NULL);
+ remove_proc_entry("driver/snd-page-alloc", NULL);
free_all_reserved_pages();
if (snd_allocated_pages > 0)
printk(KERN_ERR "snd-malloc: Memory leak? pages not freed = %li\n", snd_allocated_pages);
diff --git a/trunk/sound/core/oss/pcm_oss.c b/trunk/sound/core/oss/pcm_oss.c
index cab30977e7c0..1a805020f57a 100644
--- a/trunk/sound/core/oss/pcm_oss.c
+++ b/trunk/sound/core/oss/pcm_oss.c
@@ -125,26 +125,17 @@ int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin)
static long snd_pcm_oss_bytes(snd_pcm_substream_t *substream, long frames)
{
snd_pcm_runtime_t *runtime = substream->runtime;
- long buffer_size = snd_pcm_lib_buffer_bytes(substream);
- long bytes = frames_to_bytes(runtime, frames);
+ snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream);
+ frames = frames_to_bytes(runtime, frames);
if (buffer_size == runtime->oss.buffer_bytes)
- return bytes;
-#if BITS_PER_LONG >= 64
- return runtime->oss.buffer_bytes * bytes / buffer_size;
-#else
- {
- u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes;
- u32 rem;
- div64_32(&bsize, buffer_size, &rem);
- return (long)bsize;
- }
-#endif
+ return frames;
+ return (runtime->oss.buffer_bytes * frames) / buffer_size;
}
static long snd_pcm_alsa_frames(snd_pcm_substream_t *substream, long bytes)
{
snd_pcm_runtime_t *runtime = substream->runtime;
- long buffer_size = snd_pcm_lib_buffer_bytes(substream);
+ snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream);
if (buffer_size == runtime->oss.buffer_bytes)
return bytes_to_frames(runtime, bytes);
return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes);
@@ -473,8 +464,7 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream)
sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
sw_params->period_step = 1;
sw_params->sleep_min = 0;
- sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- 1 : runtime->period_size;
+ sw_params->avail_min = 1;
sw_params->xfer_align = 1;
if (atomic_read(&runtime->mmap_count) ||
(substream->oss.setup && substream->oss.setup->nosilence)) {
@@ -1537,15 +1527,12 @@ static int snd_pcm_oss_get_ptr(snd_pcm_oss_file_t *pcm_oss_file, int stream, str
snd_pcm_oss_simulate_fill(substream, delay);
info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX;
} else {
- delay = snd_pcm_oss_bytes(substream, delay);
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
+ delay = snd_pcm_oss_bytes(substream, delay) + fixup;
+ info.blocks = delay / runtime->oss.period_bytes;
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
info.bytes = (runtime->oss.bytes - delay) & INT_MAX;
- } else {
- delay += fixup;
- info.blocks = delay / runtime->oss.period_bytes;
+ else
info.bytes = (runtime->oss.bytes + delay) & INT_MAX;
- }
}
if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT;
diff --git a/trunk/sound/core/oss/pcm_plugin.c b/trunk/sound/core/oss/pcm_plugin.c
index 6430410c6c04..6bb31009f0b4 100644
--- a/trunk/sound/core/oss/pcm_plugin.c
+++ b/trunk/sound/core/oss/pcm_plugin.c
@@ -663,7 +663,10 @@ static int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug,
bitset_t *dstmask = bs;
int err;
bitset_one(dstmask, schannels);
-
+ if (plugin == NULL) {
+ bitset_and(client_vmask, dstmask, schannels);
+ return 0;
+ }
while (1) {
err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
if (err < 0)
diff --git a/trunk/sound/core/pcm.c b/trunk/sound/core/pcm.c
index 9f4c9209b271..8d94325529a8 100644
--- a/trunk/sound/core/pcm.c
+++ b/trunk/sound/core/pcm.c
@@ -451,7 +451,6 @@ static int snd_pcm_stream_proc_init(snd_pcm_str_t *pstr)
entry->c.text.read = snd_pcm_xrun_debug_read;
entry->c.text.write_size = 64;
entry->c.text.write = snd_pcm_xrun_debug_write;
- entry->mode |= S_IWUSR;
entry->private_data = pstr;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
@@ -1049,6 +1048,7 @@ EXPORT_SYMBOL(snd_pcm_release_substream);
EXPORT_SYMBOL(snd_pcm_format_name);
/* pcm_native.c */
EXPORT_SYMBOL(snd_pcm_link_rwlock);
+EXPORT_SYMBOL(snd_pcm_start);
#ifdef CONFIG_PM
EXPORT_SYMBOL(snd_pcm_suspend);
EXPORT_SYMBOL(snd_pcm_suspend_all);
@@ -1068,7 +1068,6 @@ EXPORT_SYMBOL(snd_pcm_format_little_endian);
EXPORT_SYMBOL(snd_pcm_format_big_endian);
EXPORT_SYMBOL(snd_pcm_format_width);
EXPORT_SYMBOL(snd_pcm_format_physical_width);
-EXPORT_SYMBOL(snd_pcm_format_size);
EXPORT_SYMBOL(snd_pcm_format_silence_64);
EXPORT_SYMBOL(snd_pcm_format_set_silence);
EXPORT_SYMBOL(snd_pcm_build_linear_format);
diff --git a/trunk/sound/core/pcm_lib.c b/trunk/sound/core/pcm_lib.c
index c5bfd0918cff..151fd99ca2c9 100644
--- a/trunk/sound/core/pcm_lib.c
+++ b/trunk/sound/core/pcm_lib.c
@@ -1143,8 +1143,7 @@ int snd_pcm_hw_constraint_pow2(snd_pcm_runtime_t *runtime,
#define INT_MIN ((int)((unsigned int)INT_MAX+1))
#endif
-static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var)
+void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var)
{
if (hw_is_mask(var)) {
snd_mask_any(hw_param_mask(params, var));
@@ -1161,7 +1160,6 @@ static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params,
snd_BUG();
}
-#if 0
/**
* snd_pcm_hw_param_any
*/
@@ -1171,7 +1169,6 @@ int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
_snd_pcm_hw_param_any(params, var);
return snd_pcm_hw_refine(pcm, params);
}
-#endif /* 0 */
void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
{
@@ -1184,7 +1181,6 @@ void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
params->info = ~0U;
}
-#if 0
/**
* snd_pcm_hw_params_any
*
@@ -1195,7 +1191,6 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
_snd_pcm_hw_params_any(params);
return snd_pcm_hw_refine(pcm, params);
}
-#endif /* 0 */
/**
* snd_pcm_hw_param_value
@@ -1203,8 +1198,8 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
* Return the value for field PAR if it's fixed in configuration space
* defined by PARAMS. Return -EINVAL otherwise
*/
-static int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, int *dir)
+int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, int *dir)
{
if (hw_is_mask(var)) {
const snd_mask_t *mask = hw_param_mask_c(params, var);
@@ -1301,7 +1296,6 @@ int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params,
return changed;
}
-#if 0
/**
* snd_pcm_hw_param_setinteger
*
@@ -1323,10 +1317,9 @@ int snd_pcm_hw_param_setinteger(snd_pcm_t *pcm,
}
return 0;
}
-#endif /* 0 */
-static int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var)
+int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var)
{
int changed;
if (hw_is_mask(var))
@@ -1352,9 +1345,9 @@ static int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
* values > minimum. Reduce configuration space accordingly.
* Return the minimum.
*/
-static int snd_pcm_hw_param_first(snd_pcm_t *pcm,
- snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, int *dir)
+int snd_pcm_hw_param_first(snd_pcm_t *pcm,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, int *dir)
{
int changed = _snd_pcm_hw_param_first(params, var);
if (changed < 0)
@@ -1366,8 +1359,8 @@ static int snd_pcm_hw_param_first(snd_pcm_t *pcm,
return snd_pcm_hw_param_value(params, var, dir);
}
-static int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var)
+int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var)
{
int changed;
if (hw_is_mask(var))
@@ -1393,9 +1386,9 @@ static int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
* values < maximum. Reduce configuration space accordingly.
* Return the maximum.
*/
-static int snd_pcm_hw_param_last(snd_pcm_t *pcm,
- snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, int *dir)
+int snd_pcm_hw_param_last(snd_pcm_t *pcm,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, int *dir)
{
int changed = _snd_pcm_hw_param_last(params, var);
if (changed < 0)
@@ -1444,9 +1437,8 @@ int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params,
* values < VAL. Reduce configuration space accordingly.
* Return new minimum or -EINVAL if the configuration space is empty
*/
-static int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, unsigned int val,
- int *dir)
+int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, unsigned int val, int *dir)
{
int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
if (changed < 0)
@@ -1459,9 +1451,8 @@ static int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
return snd_pcm_hw_param_value_min(params, var, dir);
}
-static int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, unsigned int val,
- int dir)
+int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, unsigned int val, int dir)
{
int changed;
int open = 0;
@@ -1499,9 +1490,8 @@ static int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
* values >= VAL + 1. Reduce configuration space accordingly.
* Return new maximum or -EINVAL if the configuration space is empty
*/
-static int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, unsigned int val,
- int *dir)
+int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, unsigned int val, int *dir)
{
int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
if (changed < 0)
@@ -2574,6 +2564,9 @@ snd_pcm_sframes_t snd_pcm_lib_readv(snd_pcm_substream_t *substream,
EXPORT_SYMBOL(snd_interval_refine);
EXPORT_SYMBOL(snd_interval_list);
EXPORT_SYMBOL(snd_interval_ratnum);
+EXPORT_SYMBOL(snd_interval_muldivk);
+EXPORT_SYMBOL(snd_interval_mulkdiv);
+EXPORT_SYMBOL(snd_interval_div);
EXPORT_SYMBOL(_snd_pcm_hw_params_any);
EXPORT_SYMBOL(_snd_pcm_hw_param_min);
EXPORT_SYMBOL(_snd_pcm_hw_param_set);
@@ -2587,6 +2580,7 @@ EXPORT_SYMBOL(snd_pcm_hw_param_last);
EXPORT_SYMBOL(snd_pcm_hw_param_near);
EXPORT_SYMBOL(snd_pcm_hw_param_set);
EXPORT_SYMBOL(snd_pcm_hw_refine);
+EXPORT_SYMBOL(snd_pcm_hw_params);
EXPORT_SYMBOL(snd_pcm_hw_constraints_init);
EXPORT_SYMBOL(snd_pcm_hw_constraints_complete);
EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
diff --git a/trunk/sound/core/pcm_memory.c b/trunk/sound/core/pcm_memory.c
index 9a174fb96565..f1d5f7a6ee0c 100644
--- a/trunk/sound/core/pcm_memory.c
+++ b/trunk/sound/core/pcm_memory.c
@@ -204,7 +204,6 @@ static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream,
entry->c.text.read = snd_pcm_lib_preallocate_proc_read;
entry->c.text.write_size = 64;
entry->c.text.write = snd_pcm_lib_preallocate_proc_write;
- entry->mode |= S_IWUSR;
entry->private_data = substream;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
diff --git a/trunk/sound/core/pcm_misc.c b/trunk/sound/core/pcm_misc.c
index 1453743e4da0..422b8db14154 100644
--- a/trunk/sound/core/pcm_misc.c
+++ b/trunk/sound/core/pcm_misc.c
@@ -269,6 +269,22 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format)
return !val;
}
+/**
+ * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
+ * @format: the format to check
+ *
+ * Returns 1 if the given PCM format is CPU-endian, 0 if
+ * opposite, or a negative error code if endian not specified.
+ */
+int snd_pcm_format_cpu_endian(snd_pcm_format_t format)
+{
+#ifdef SNDRV_LITTLE_ENDIAN
+ return snd_pcm_format_little_endian(format);
+#else
+ return snd_pcm_format_big_endian(format);
+#endif
+}
+
/**
* snd_pcm_format_width - return the bit-width of the format
* @format: the format to check
diff --git a/trunk/sound/core/pcm_native.c b/trunk/sound/core/pcm_native.c
index 10c2c9832649..cad9bbde9986 100644
--- a/trunk/sound/core/pcm_native.c
+++ b/trunk/sound/core/pcm_native.c
@@ -337,8 +337,8 @@ static int snd_pcm_hw_refine_user(snd_pcm_substream_t * substream, snd_pcm_hw_pa
return err;
}
-static int snd_pcm_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params)
+int snd_pcm_hw_params(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t *params)
{
snd_pcm_runtime_t *runtime;
int err;
@@ -1368,32 +1368,43 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
+ down_read(&snd_pcm_link_rwsem);
snd_power_lock(card);
if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
- if (result < 0) {
- snd_power_unlock(card);
- return result;
- }
+ if (result < 0)
+ goto _unlock;
}
/* allocate temporary record for drain sync */
- down_read(&snd_pcm_link_rwsem);
if (snd_pcm_stream_linked(substream)) {
drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL);
if (! drec) {
- up_read(&snd_pcm_link_rwsem);
- snd_power_unlock(card);
- return -ENOMEM;
+ result = -ENOMEM;
+ goto _unlock;
}
} else
drec = &drec_tmp;
- /* count only playback streams */
+ snd_pcm_stream_lock_irq(substream);
+ /* resume pause */
+ if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
+ snd_pcm_pause(substream, 0);
+
+ /* pre-start/stop - all running streams are changed to DRAINING state */
+ result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
+ if (result < 0)
+ goto _end;
+
+ /* check streams with PLAYBACK & DRAINING */
num_drecs = 0;
snd_pcm_group_for_each(pos, substream) {
snd_pcm_substream_t *s = snd_pcm_group_substream_entry(pos);
runtime = s->runtime;
+ if (runtime->status->state != SNDRV_PCM_STATE_DRAINING) {
+ runtime->status->state = SNDRV_PCM_STATE_SETUP;
+ continue;
+ }
if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
d = &drec[num_drecs++];
d->substream = s;
@@ -1407,21 +1418,9 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
runtime->stop_threshold = runtime->buffer_size;
}
}
- up_read(&snd_pcm_link_rwsem);
- if (! num_drecs)
- goto _error;
- snd_pcm_stream_lock_irq(substream);
- /* resume pause */
- if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
- snd_pcm_pause(substream, 0);
-
- /* pre-start/stop - all running streams are changed to DRAINING state */
- result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
- if (result < 0) {
- snd_pcm_stream_unlock_irq(substream);
- goto _error;
- }
+ if (! num_drecs)
+ goto _end;
for (;;) {
long tout;
@@ -1429,15 +1428,6 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
result = -ERESTARTSYS;
break;
}
- /* all finished? */
- for (i = 0; i < num_drecs; i++) {
- runtime = drec[i].substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
- break;
- }
- if (i == num_drecs)
- break; /* yes, all drained */
-
set_current_state(TASK_INTERRUPTIBLE);
snd_pcm_stream_unlock_irq(substream);
snd_power_unlock(card);
@@ -1454,11 +1444,15 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
}
break;
}
+ /* all finished? */
+ for (i = 0; i < num_drecs; i++) {
+ runtime = drec[i].substream->runtime;
+ if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+ break;
+ }
+ if (i == num_drecs)
+ break;
}
-
- snd_pcm_stream_unlock_irq(substream);
-
- _error:
for (i = 0; i < num_drecs; i++) {
d = &drec[i];
runtime = d->substream->runtime;
@@ -1466,9 +1460,13 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
runtime->stop_threshold = d->stop_threshold;
}
+ _end:
+ snd_pcm_stream_unlock_irq(substream);
if (drec != &drec_tmp)
kfree(drec);
+ _unlock:
snd_power_unlock(card);
+ up_read(&snd_pcm_link_rwsem);
return result;
}
diff --git a/trunk/sound/core/seq/oss/seq_oss_synth.c b/trunk/sound/core/seq/oss/seq_oss_synth.c
index 1a7736cbf3a4..638cc148706d 100644
--- a/trunk/sound/core/seq/oss/seq_oss_synth.c
+++ b/trunk/sound/core/seq/oss/seq_oss_synth.c
@@ -325,10 +325,14 @@ snd_seq_oss_synth_cleanup(seq_oss_devinfo_t *dp)
}
snd_use_lock_free(&rec->use_lock);
}
- kfree(info->sysex);
- info->sysex = NULL;
- kfree(info->ch);
- info->ch = NULL;
+ if (info->sysex) {
+ kfree(info->sysex);
+ info->sysex = NULL;
+ }
+ if (info->ch) {
+ kfree(info->ch);
+ info->ch = NULL;
+ }
}
dp->synth_opened = 0;
dp->max_synthdev = 0;
@@ -414,10 +418,14 @@ snd_seq_oss_synth_reset(seq_oss_devinfo_t *dp, int dev)
dp->file_mode) < 0) {
midi_synth_dev.opened--;
info->opened = 0;
- kfree(info->sysex);
- info->sysex = NULL;
- kfree(info->ch);
- info->ch = NULL;
+ if (info->sysex) {
+ kfree(info->sysex);
+ info->sysex = NULL;
+ }
+ if (info->ch) {
+ kfree(info->ch);
+ info->ch = NULL;
+ }
}
return;
}
diff --git a/trunk/sound/core/seq/seq_dummy.c b/trunk/sound/core/seq/seq_dummy.c
index ea945a5d2a0b..e88967c5b93d 100644
--- a/trunk/sound/core/seq/seq_dummy.c
+++ b/trunk/sound/core/seq/seq_dummy.c
@@ -140,7 +140,10 @@ dummy_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int
static void
dummy_free(void *private_data)
{
- kfree(private_data);
+ snd_seq_dummy_port_t *p;
+
+ p = private_data;
+ kfree(p);
}
/*
diff --git a/trunk/sound/core/seq/seq_midi.c b/trunk/sound/core/seq/seq_midi.c
index 57be9155eb62..18247db45db6 100644
--- a/trunk/sound/core/seq/seq_midi.c
+++ b/trunk/sound/core/seq/seq_midi.c
@@ -414,8 +414,6 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
if (newclient)
synths[card->number] = client;
up(®ister_mutex);
- kfree(info);
- kfree(port);
return 0; /* success */
__nomem:
diff --git a/trunk/sound/core/seq/seq_midi_event.c b/trunk/sound/core/seq/seq_midi_event.c
index df1e2bb39745..21e569062bc3 100644
--- a/trunk/sound/core/seq/seq_midi_event.c
+++ b/trunk/sound/core/seq/seq_midi_event.c
@@ -171,13 +171,11 @@ void snd_midi_event_reset_decode(snd_midi_event_t *dev)
spin_unlock_irqrestore(&dev->lock, flags);
}
-#if 0
void snd_midi_event_init(snd_midi_event_t *dev)
{
snd_midi_event_reset_encode(dev);
snd_midi_event_reset_decode(dev);
}
-#endif /* 0 */
void snd_midi_event_no_status(snd_midi_event_t *dev, int on)
{
@@ -187,7 +185,6 @@ void snd_midi_event_no_status(snd_midi_event_t *dev, int on)
/*
* resize buffer
*/
-#if 0
int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize)
{
unsigned char *new_buf, *old_buf;
@@ -207,7 +204,6 @@ int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize)
kfree(old_buf);
return 0;
}
-#endif /* 0 */
/*
* read bytes and encode to sequencer event if finished
@@ -521,6 +517,8 @@ static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int coun
EXPORT_SYMBOL(snd_midi_event_new);
EXPORT_SYMBOL(snd_midi_event_free);
+EXPORT_SYMBOL(snd_midi_event_resize_buffer);
+EXPORT_SYMBOL(snd_midi_event_init);
EXPORT_SYMBOL(snd_midi_event_reset_encode);
EXPORT_SYMBOL(snd_midi_event_reset_decode);
EXPORT_SYMBOL(snd_midi_event_no_status);
diff --git a/trunk/sound/core/seq/seq_queue.c b/trunk/sound/core/seq/seq_queue.c
index 98de2e711fde..3afc7cc0c9a7 100644
--- a/trunk/sound/core/seq/seq_queue.c
+++ b/trunk/sound/core/seq/seq_queue.c
@@ -672,8 +672,7 @@ static void queue_broadcast_event(queue_t *q, snd_seq_event_t *ev, int atomic, i
* process a received queue-control event.
* this function is exported for seq_sync.c.
*/
-static void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev,
- int atomic, int hop)
+void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop)
{
switch (ev->type) {
case SNDRV_SEQ_EVENT_START:
diff --git a/trunk/sound/core/seq/seq_queue.h b/trunk/sound/core/seq/seq_queue.h
index ea3c54216ea8..b1bf5519fb3b 100644
--- a/trunk/sound/core/seq/seq_queue.h
+++ b/trunk/sound/core/seq/seq_queue.h
@@ -111,6 +111,7 @@ int snd_seq_queue_use(int queueid, int client, int use);
int snd_seq_queue_is_used(int queueid, int client);
int snd_seq_control_queue(snd_seq_event_t *ev, int atomic, int hop);
+void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop);
/*
* 64bit division - for sync stuff..
diff --git a/trunk/sound/core/seq/seq_timer.c b/trunk/sound/core/seq/seq_timer.c
index a7f76fc95280..753f1c0863cc 100644
--- a/trunk/sound/core/seq/seq_timer.c
+++ b/trunk/sound/core/seq/seq_timer.c
@@ -36,8 +36,7 @@ extern int seq_default_timer_resolution;
#define SKEW_BASE 0x10000 /* 16bit shift */
-static void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick,
- int tempo, int ppq, int nticks)
+void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, int tempo, int ppq, int nticks)
{
if (tempo < 1000000)
tick->resolution = (tempo * 1000) / ppq;
diff --git a/trunk/sound/core/seq/seq_timer.h b/trunk/sound/core/seq/seq_timer.h
index 287ed68591de..4c0872df8931 100644
--- a/trunk/sound/core/seq/seq_timer.h
+++ b/trunk/sound/core/seq/seq_timer.h
@@ -64,6 +64,8 @@ extern seq_timer_t *snd_seq_timer_new(void);
/* delete timer (destructor) */
extern void snd_seq_timer_delete(seq_timer_t **tmr);
+void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, int tempo, int ppq, int nticks);
+
/* */
static inline void snd_seq_timer_update_tick(seq_timer_tick_t *tick, unsigned long resolution)
{
diff --git a/trunk/sound/core/seq/seq_virmidi.c b/trunk/sound/core/seq/seq_virmidi.c
index a66484b5cf0e..6b4e630ace54 100644
--- a/trunk/sound/core/seq/seq_virmidi.c
+++ b/trunk/sound/core/seq/seq_virmidi.c
@@ -110,7 +110,7 @@ static int snd_virmidi_dev_receive_event(snd_virmidi_dev_t *rdev, snd_seq_event_
* handler of a remote port which is attached to the virmidi via
* SNDRV_VIRMIDI_SEQ_ATTACH.
*/
-#if 0
+/* exported */
int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev)
{
snd_virmidi_dev_t *rdev;
@@ -118,7 +118,6 @@ int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev)
rdev = rmidi->private_data;
return snd_virmidi_dev_receive_event(rdev, ev);
}
-#endif /* 0 */
/*
* event handler of virmidi port
@@ -385,7 +384,7 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev)
info->client = client;
info->type = KERNEL_CLIENT;
sprintf(info->name, "%s %d-%d", rdev->rmidi->name, rdev->card->number, rdev->device);
- snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, info);
+ snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &info);
/* create a port */
memset(pinfo, 0, sizeof(*pinfo));
@@ -406,7 +405,7 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev)
pcallbacks.unuse = snd_virmidi_unuse;
pcallbacks.event_input = snd_virmidi_event_input;
pinfo->kernel = &pcallbacks;
- err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, pinfo);
+ err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, &pinfo);
if (err < 0) {
snd_seq_delete_kernel_client(client);
rdev->client = -1;
@@ -549,3 +548,4 @@ module_init(alsa_virmidi_init)
module_exit(alsa_virmidi_exit)
EXPORT_SYMBOL(snd_virmidi_new);
+EXPORT_SYMBOL(snd_virmidi_receive);
diff --git a/trunk/sound/core/sound.c b/trunk/sound/core/sound.c
index 0815fadeb3ec..33eaa5e5d284 100644
--- a/trunk/sound/core/sound.c
+++ b/trunk/sound/core/sound.c
@@ -431,6 +431,7 @@ EXPORT_SYMBOL(snd_card_pci_resume);
EXPORT_SYMBOL(snd_device_new);
EXPORT_SYMBOL(snd_device_register);
EXPORT_SYMBOL(snd_device_free);
+EXPORT_SYMBOL(snd_device_free_all);
/* isadma.c */
#ifdef CONFIG_ISA
EXPORT_SYMBOL(snd_dma_program);
diff --git a/trunk/sound/core/timer.c b/trunk/sound/core/timer.c
index b498e5482d77..fa762ca439be 100644
--- a/trunk/sound/core/timer.c
+++ b/trunk/sound/core/timer.c
@@ -69,7 +69,6 @@ typedef struct {
struct timespec tstamp; /* trigger tstamp */
wait_queue_head_t qchange_sleep;
struct fasync_struct *fasync;
- struct semaphore tread_sem;
} snd_timer_user_t;
/* list of timers */
@@ -845,7 +844,7 @@ int snd_timer_dev_register(snd_device_t *dev)
return 0;
}
-static int snd_timer_unregister(snd_timer_t *timer)
+int snd_timer_unregister(snd_timer_t *timer)
{
struct list_head *p, *n;
snd_timer_instance_t *ti;
@@ -946,6 +945,11 @@ struct snd_timer_system_private {
unsigned long correction;
};
+unsigned int snd_timer_system_resolution(void)
+{
+ return 1000000000L / HZ;
+}
+
static void snd_timer_s_function(unsigned long data)
{
snd_timer_t *timer = (snd_timer_t *)data;
@@ -1204,7 +1208,6 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
return -ENOMEM;
spin_lock_init(&tu->qlock);
init_waitqueue_head(&tu->qchange_sleep);
- init_MUTEX(&tu->tread_sem);
tu->ticks = 1;
tu->queue_size = 128;
tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL);
@@ -1451,51 +1454,46 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user *
snd_timer_user_t *tu;
snd_timer_select_t tselect;
char str[32];
- int err = 0;
+ int err;
tu = file->private_data;
- down(&tu->tread_sem);
- if (tu->timeri) {
+ if (tu->timeri)
snd_timer_close(tu->timeri);
- tu->timeri = NULL;
- }
- if (copy_from_user(&tselect, _tselect, sizeof(tselect))) {
- err = -EFAULT;
- goto __err;
- }
+ if (copy_from_user(&tselect, _tselect, sizeof(tselect)))
+ return -EFAULT;
sprintf(str, "application %i", current->pid);
if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE)
tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION;
if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0)
- goto __err;
+ return err;
- kfree(tu->queue);
- tu->queue = NULL;
- kfree(tu->tqueue);
- tu->tqueue = NULL;
+ if (tu->queue) {
+ kfree(tu->queue);
+ tu->queue = NULL;
+ }
+ if (tu->tqueue) {
+ kfree(tu->tqueue);
+ tu->tqueue = NULL;
+ }
if (tu->tread) {
tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL);
- if (tu->tqueue == NULL)
- err = -ENOMEM;
+ if (tu->tqueue == NULL) {
+ snd_timer_close(tu->timeri);
+ return -ENOMEM;
+ }
} else {
tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL);
- if (tu->queue == NULL)
- err = -ENOMEM;
+ if (tu->queue == NULL) {
+ snd_timer_close(tu->timeri);
+ return -ENOMEM;
+ }
}
- if (err < 0) {
- snd_timer_close(tu->timeri);
- tu->timeri = NULL;
- } else {
- tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
- tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
- tu->timeri->ccallback = snd_timer_user_ccallback;
- tu->timeri->callback_data = (void *)tu;
- }
-
- __err:
- up(&tu->tread_sem);
- return err;
+ tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
+ tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
+ tu->timeri->ccallback = snd_timer_user_ccallback;
+ tu->timeri->callback_data = (void *)tu;
+ return 0;
}
static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info)
@@ -1671,23 +1669,6 @@ static int snd_timer_user_continue(struct file *file)
return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0;
}
-static int snd_timer_user_pause(struct file *file)
-{
- int err;
- snd_timer_user_t *tu;
-
- tu = file->private_data;
- snd_assert(tu->timeri != NULL, return -ENXIO);
- return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0;
-}
-
-enum {
- SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20),
- SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21),
- SNDRV_TIMER_IOCTL_CONTINUE_OLD = _IO('T', 0x22),
- SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
-};
-
static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
snd_timer_user_t *tu;
@@ -1704,17 +1685,11 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l
{
int xarg;
- down(&tu->tread_sem);
- if (tu->timeri) { /* too late */
- up(&tu->tread_sem);
+ if (tu->timeri) /* too late */
return -EBUSY;
- }
- if (get_user(xarg, p)) {
- up(&tu->tread_sem);
+ if (get_user(xarg, p))
return -EFAULT;
- }
tu->tread = xarg ? 1 : 0;
- up(&tu->tread_sem);
return 0;
}
case SNDRV_TIMER_IOCTL_GINFO:
@@ -1732,17 +1707,11 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l
case SNDRV_TIMER_IOCTL_STATUS:
return snd_timer_user_status(file, argp);
case SNDRV_TIMER_IOCTL_START:
- case SNDRV_TIMER_IOCTL_START_OLD:
return snd_timer_user_start(file);
case SNDRV_TIMER_IOCTL_STOP:
- case SNDRV_TIMER_IOCTL_STOP_OLD:
return snd_timer_user_stop(file);
case SNDRV_TIMER_IOCTL_CONTINUE:
- case SNDRV_TIMER_IOCTL_CONTINUE_OLD:
return snd_timer_user_continue(file);
- case SNDRV_TIMER_IOCTL_PAUSE:
- case SNDRV_TIMER_IOCTL_PAUSE_OLD:
- return snd_timer_user_pause(file);
}
return -ENOTTY;
}
@@ -1929,3 +1898,4 @@ EXPORT_SYMBOL(snd_timer_global_free);
EXPORT_SYMBOL(snd_timer_global_register);
EXPORT_SYMBOL(snd_timer_global_unregister);
EXPORT_SYMBOL(snd_timer_interrupt);
+EXPORT_SYMBOL(snd_timer_system_resolution);
diff --git a/trunk/sound/core/timer_compat.c b/trunk/sound/core/timer_compat.c
index 3de552dfe80f..9fbc3957a22d 100644
--- a/trunk/sound/core/timer_compat.c
+++ b/trunk/sound/core/timer_compat.c
@@ -106,13 +106,8 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns
case SNDRV_TIMER_IOCTL_SELECT:
case SNDRV_TIMER_IOCTL_PARAMS:
case SNDRV_TIMER_IOCTL_START:
- case SNDRV_TIMER_IOCTL_START_OLD:
case SNDRV_TIMER_IOCTL_STOP:
- case SNDRV_TIMER_IOCTL_STOP_OLD:
case SNDRV_TIMER_IOCTL_CONTINUE:
- case SNDRV_TIMER_IOCTL_CONTINUE_OLD:
- case SNDRV_TIMER_IOCTL_PAUSE:
- case SNDRV_TIMER_IOCTL_PAUSE_OLD:
case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
return snd_timer_user_ioctl(file, cmd, (unsigned long)argp);
case SNDRV_TIMER_IOCTL_INFO32:
diff --git a/trunk/sound/drivers/vx/vx_pcm.c b/trunk/sound/drivers/vx/vx_pcm.c
index af381b15fe5c..98587176b327 100644
--- a/trunk/sound/drivers/vx/vx_pcm.c
+++ b/trunk/sound/drivers/vx/vx_pcm.c
@@ -1264,10 +1264,14 @@ static void snd_vx_pcm_free(snd_pcm_t *pcm)
{
vx_core_t *chip = pcm->private_data;
chip->pcm[pcm->device] = NULL;
- kfree(chip->playback_pipes);
- chip->playback_pipes = NULL;
- kfree(chip->capture_pipes);
- chip->capture_pipes = NULL;
+ if (chip->playback_pipes) {
+ kfree(chip->playback_pipes);
+ chip->playback_pipes = NULL;
+ }
+ if (chip->capture_pipes) {
+ kfree(chip->capture_pipes);
+ chip->capture_pipes = NULL;
+ }
}
/*
diff --git a/trunk/sound/i2c/tea6330t.c b/trunk/sound/i2c/tea6330t.c
index 2da8d7f157f4..bb503e70b664 100644
--- a/trunk/sound/i2c/tea6330t.c
+++ b/trunk/sound/i2c/tea6330t.c
@@ -266,7 +266,8 @@ TEA6330T_TREBLE("Tone Control - Treble", 0)
static void snd_tea6330_free(snd_i2c_device_t *device)
{
- kfree(device->private_data);
+ tea6330t_t *tea = device->private_data;
+ kfree(tea);
}
int snd_tea6330t_update_mixer(snd_card_t * card,
diff --git a/trunk/sound/isa/Kconfig b/trunk/sound/isa/Kconfig
index 148a856a43ad..3a3228b18726 100644
--- a/trunk/sound/isa/Kconfig
+++ b/trunk/sound/isa/Kconfig
@@ -179,7 +179,6 @@ config SND_INTERWAVE_STB
select SND_RAWMIDI
select SND_CS4231_LIB
select SND_GUS_SYNTH
- select ISAPNP
help
Say Y here to include support for AMD InterWave based
soundcards with a TEA6330T bass and treble regulator
diff --git a/trunk/sound/isa/ad1816a/ad1816a.c b/trunk/sound/isa/ad1816a/ad1816a.c
index 563296d02894..9fa7a78da6c3 100644
--- a/trunk/sound/isa/ad1816a/ad1816a.c
+++ b/trunk/sound/isa/ad1816a/ad1816a.c
@@ -83,8 +83,6 @@ struct snd_card_ad1816a {
static struct pnp_card_device_id snd_ad1816a_pnpids[] = {
/* Analog Devices AD1815 */
{ .id = "ADS7150", .devs = { { .id = "ADS7150" }, { .id = "ADS7151" } } },
- /* Analog Device AD1816? */
- { .id = "ADS7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
/* Analog Devices AD1816A - added by Kenneth Platz */
{ .id = "ADS7181", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
/* Analog Devices AD1816A - Aztech/Newcom SC-16 3D */
diff --git a/trunk/sound/isa/cs423x/cs4236.c b/trunk/sound/isa/cs423x/cs4236.c
index 39f4eff44f5c..e745a54e00a1 100644
--- a/trunk/sound/isa/cs423x/cs4236.c
+++ b/trunk/sound/isa/cs423x/cs4236.c
@@ -349,7 +349,8 @@ static int __devinit snd_card_cs4236_pnp(int dev, struct snd_card_cs4236 *acard,
pnp_init_resource_table(cfg);
if (mpu_port[dev] != SNDRV_AUTO_PORT)
pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
- if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0)
+ if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0 &&
+ pnp_irq_valid(pdev, 0))
pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
err = pnp_manual_config_dev(pdev, cfg, 0);
if (err < 0)
diff --git a/trunk/sound/isa/gus/gus_io.c b/trunk/sound/isa/gus/gus_io.c
index 337b0e2a8a36..f0570f2bf75f 100644
--- a/trunk/sound/isa/gus/gus_io.c
+++ b/trunk/sound/isa/gus/gus_io.c
@@ -244,8 +244,6 @@ unsigned short snd_gf1_i_look16(snd_gus_card_t * gus, unsigned char reg)
return res;
}
-#if 0
-
void snd_gf1_i_adlib_write(snd_gus_card_t * gus,
unsigned char reg,
unsigned char data)
@@ -267,8 +265,6 @@ void snd_gf1_i_write_addr(snd_gus_card_t * gus, unsigned char reg,
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-#endif /* 0 */
-
unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus,
unsigned char reg, short w_16bit)
{
@@ -333,8 +329,6 @@ unsigned char snd_gf1_peek(snd_gus_card_t * gus, unsigned int addr)
return res;
}
-#if 0
-
void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data)
{
unsigned long flags;
@@ -411,7 +405,9 @@ void snd_gf1_dram_setmem(snd_gus_card_t * gus, unsigned int addr,
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-#endif /* 0 */
+/*
+
+ */
void snd_gf1_select_active_voices(snd_gus_card_t * gus)
{
@@ -473,8 +469,6 @@ void snd_gf1_print_voice_registers(snd_gus_card_t * gus)
printk(" -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c));
}
-#if 0
-
void snd_gf1_print_global_registers(snd_gus_card_t * gus)
{
unsigned char global_mode = 0x00;
@@ -534,6 +528,4 @@ void snd_gf1_peek_print_block(snd_gus_card_t * gus, unsigned int addr, int count
}
}
-#endif /* 0 */
-
#endif
diff --git a/trunk/sound/isa/gus/gus_main.c b/trunk/sound/isa/gus/gus_main.c
index 94bbd344be5e..73f81c14f768 100644
--- a/trunk/sound/isa/gus/gus_main.c
+++ b/trunk/sound/isa/gus/gus_main.c
@@ -459,6 +459,7 @@ EXPORT_SYMBOL(snd_gf1_write16);
EXPORT_SYMBOL(snd_gf1_look16);
EXPORT_SYMBOL(snd_gf1_i_write8);
EXPORT_SYMBOL(snd_gf1_i_look8);
+EXPORT_SYMBOL(snd_gf1_i_write16);
EXPORT_SYMBOL(snd_gf1_i_look16);
EXPORT_SYMBOL(snd_gf1_dram_addr);
EXPORT_SYMBOL(snd_gf1_write_addr);
@@ -469,6 +470,8 @@ EXPORT_SYMBOL(snd_gf1_alloc_voice);
EXPORT_SYMBOL(snd_gf1_free_voice);
EXPORT_SYMBOL(snd_gf1_ctrl_stop);
EXPORT_SYMBOL(snd_gf1_stop_voice);
+EXPORT_SYMBOL(snd_gf1_start);
+EXPORT_SYMBOL(snd_gf1_stop);
/* gus_mixer.c */
EXPORT_SYMBOL(snd_gf1_new_mixer);
/* gus_pcm.c */
diff --git a/trunk/sound/isa/gus/gus_mem.c b/trunk/sound/isa/gus/gus_mem.c
index 609838e8ef67..bfc2b91001d5 100644
--- a/trunk/sound/isa/gus/gus_mem.c
+++ b/trunk/sound/isa/gus/gus_mem.c
@@ -39,8 +39,8 @@ void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup)
}
}
-static snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc,
- snd_gf1_mem_block_t * block)
+snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc,
+ snd_gf1_mem_block_t * block)
{
snd_gf1_mem_block_t *pblock, *nblock;
@@ -105,8 +105,8 @@ int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block)
return 0;
}
-static snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
- unsigned int address)
+snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
+ unsigned int address)
{
snd_gf1_mem_block_t *block;
@@ -118,8 +118,8 @@ static snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
return NULL;
}
-static snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
- unsigned int *share_id)
+snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
+ unsigned int *share_id)
{
snd_gf1_mem_block_t *block;
diff --git a/trunk/sound/isa/gus/gus_pcm.c b/trunk/sound/isa/gus/gus_pcm.c
index b75066ab46fc..8995ad9c516d 100644
--- a/trunk/sound/isa/gus/gus_pcm.c
+++ b/trunk/sound/isa/gus/gus_pcm.c
@@ -656,7 +656,8 @@ static snd_pcm_hardware_t snd_gf1_pcm_capture =
static void snd_gf1_pcm_playback_free(snd_pcm_runtime_t *runtime)
{
- kfree(runtime->private_data);
+ gus_pcm_private_t * pcmp = runtime->private_data;
+ kfree(pcmp);
}
static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream)
diff --git a/trunk/sound/isa/gus/gus_reset.c b/trunk/sound/isa/gus/gus_reset.c
index ef687abc7070..b4e66f6a10ae 100644
--- a/trunk/sound/isa/gus/gus_reset.c
+++ b/trunk/sound/isa/gus/gus_reset.c
@@ -161,8 +161,7 @@ void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice)
#endif
}
-static void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min,
- unsigned short v_max)
+void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max)
{
unsigned long flags;
unsigned int daddr;
diff --git a/trunk/sound/isa/gus/gus_synth.c b/trunk/sound/isa/gus/gus_synth.c
index f51c386ee192..66552e6013a4 100644
--- a/trunk/sound/isa/gus/gus_synth.c
+++ b/trunk/sound/isa/gus/gus_synth.c
@@ -99,8 +99,7 @@ static void snd_gus_synth_free_private_instruments(snd_gus_port_t *p, int client
snd_seq_instr_list_free_cond(p->gus->gf1.ilist, &ifree, client, 0);
}
-static int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct,
- void *private_data, int atomic, int hop)
+int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int hop)
{
snd_gus_port_t * p = (snd_gus_port_t *) private_data;
diff --git a/trunk/sound/isa/gus/gus_tables.h b/trunk/sound/isa/gus/gus_tables.h
index 4adf098d3269..ed8e9d85ad31 100644
--- a/trunk/sound/isa/gus/gus_tables.h
+++ b/trunk/sound/isa/gus/gus_tables.h
@@ -23,8 +23,6 @@
#ifdef __GUS_TABLES_ALLOC__
-#if 0
-
unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] =
{
8372, 8870, 9397, 9956, 10548, 11175,
@@ -51,8 +49,6 @@ unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] =
12123977, 12844906
};
-#endif /* 0 */
-
unsigned short snd_gf1_atten_table[SNDRV_GF1_ATTEN_TABLE_SIZE] = {
4095 /* 0 */,1789 /* 1 */,1533 /* 2 */,1383 /* 3 */,1277 /* 4 */,
1195 /* 5 */,1127 /* 6 */,1070 /* 7 */,1021 /* 8 */,978 /* 9 */,
diff --git a/trunk/sound/isa/gus/gus_volume.c b/trunk/sound/isa/gus/gus_volume.c
index 3d36f6c8ee6a..b72bcfb28617 100644
--- a/trunk/sound/isa/gus/gus_volume.c
+++ b/trunk/sound/isa/gus/gus_volume.c
@@ -55,8 +55,6 @@ unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol)
return (e << 8) | m;
}
-#if 0
-
unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol)
{
unsigned int rvol;
@@ -110,8 +108,6 @@ unsigned int snd_gf1_calc_ramp_rate(snd_gus_card_t * gus,
return (range << 6) | (increment & 0x3f);
}
-#endif /* 0 */
-
unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16)
{
freq16 >>= 3;
@@ -124,8 +120,6 @@ unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16)
return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq;
}
-#if 0
-
short snd_gf1_compute_vibrato(short cents, unsigned short fc_register)
{
static short vibrato_table[] =
@@ -214,5 +208,3 @@ unsigned short snd_gf1_compute_freq(unsigned int freq,
}
return (unsigned short) fc;
}
-
-#endif /* 0 */
diff --git a/trunk/sound/pci/Kconfig b/trunk/sound/pci/Kconfig
index 6d7a00f34d82..428efdbd70a1 100644
--- a/trunk/sound/pci/Kconfig
+++ b/trunk/sound/pci/Kconfig
@@ -274,19 +274,6 @@ config SND_HDSP
To compile this driver as a module, choose M here: the module
will be called snd-hdsp.
-config SND_HDSPM
- tristate "RME Hammerfall DSP MADI"
- depends on SND
- select SND_HWDEP
- select SND_RAWMIDI
- select SND_PCM
- help
- Say Y here to include support for RME Hammerfall DSP MADI
- soundcards.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-hdspm.
-
config SND_TRIDENT
tristate "Trident 4D-Wave DX/NX; SiS 7018"
depends on SND
diff --git a/trunk/sound/pci/ac97/ac97_codec.c b/trunk/sound/pci/ac97/ac97_codec.c
index a4b72cd2eea0..0b024ec1f709 100644
--- a/trunk/sound/pci/ac97/ac97_codec.c
+++ b/trunk/sound/pci/ac97/ac97_codec.c
@@ -120,7 +120,6 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x414c4770, 0xfffffff0, "ALC203", NULL, NULL },
{ 0x434d4941, 0xffffffff, "CMI9738", patch_cm9738, NULL },
{ 0x434d4961, 0xffffffff, "CMI9739", patch_cm9739, NULL },
-{ 0x434d4969, 0xffffffff, "CMI9780", patch_cm9780, NULL },
{ 0x434d4978, 0xffffffff, "CMI9761", patch_cm9761, NULL },
{ 0x434d4982, 0xffffffff, "CMI9761", patch_cm9761, NULL },
{ 0x434d4983, 0xffffffff, "CMI9761", patch_cm9761, NULL },
@@ -150,7 +149,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x4e534331, 0xffffffff, "LM4549", NULL, NULL },
{ 0x4e534350, 0xffffffff, "LM4550", NULL, NULL },
{ 0x50534304, 0xffffffff, "UCB1400", NULL, NULL },
-{ 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH },
+{ 0x53494c20, 0xffffffe0, "Si3036,8", NULL, mpatch_si3036 },
{ 0x54524102, 0xffffffff, "TR28022", NULL, NULL },
{ 0x54524106, 0xffffffff, "TR28026", NULL, NULL },
{ 0x54524108, 0xffffffff, "TR28028", patch_tritech_tr28028, NULL }, // added by xin jin [07/09/99]
@@ -463,14 +462,12 @@ int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u
{
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
- unsigned short val, bitmask;
+ unsigned short val;
- for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
- ;
val = snd_ac97_read_cache(ac97, e->reg);
- ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
+ ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (e->mask - 1);
if (e->shift_l != e->shift_r)
- ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (bitmask - 1);
+ ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (e->mask - 1);
return 0;
}
@@ -480,19 +477,17 @@ int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
unsigned short val;
- unsigned short mask, bitmask;
+ unsigned short mask;
- for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
- ;
if (ucontrol->value.enumerated.item[0] > e->mask - 1)
return -EINVAL;
val = ucontrol->value.enumerated.item[0] << e->shift_l;
- mask = (bitmask - 1) << e->shift_l;
+ mask = (e->mask - 1) << e->shift_l;
if (e->shift_l != e->shift_r) {
if (ucontrol->value.enumerated.item[1] > e->mask - 1)
return -EINVAL;
val |= ucontrol->value.enumerated.item[1] << e->shift_r;
- mask |= (bitmask - 1) << e->shift_r;
+ mask |= (e->mask - 1) << e->shift_r;
}
return snd_ac97_update_bits(ac97, e->reg, mask, val);
}
@@ -663,14 +658,14 @@ AC97_SINGLE("LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 1, 1),
AC97_SINGLE("LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 31, 1)
};
+static const snd_kcontrol_new_t snd_ac97_controls_surround[2] = {
+AC97_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1),
+AC97_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
+};
+
static const snd_kcontrol_new_t snd_ac97_control_eapd =
AC97_SINGLE("External Amplifier", AC97_POWERDOWN, 15, 1, 1);
-static const snd_kcontrol_new_t snd_ac97_controls_modem_switches[2] = {
-AC97_SINGLE("Off-hook Switch", AC97_GPIO_STATUS, 0, 1, 0),
-AC97_SINGLE("Caller ID Switch", AC97_GPIO_STATUS, 2, 1, 0)
-};
-
/* change the existing EAPD control as inverted */
static void set_inv_eapd(ac97_t *ac97, snd_kcontrol_t *kctl)
{
@@ -1077,9 +1072,9 @@ static void check_volume_resolution(ac97_t *ac97, int reg, unsigned char *lo_max
unsigned short val;
snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8));
val = snd_ac97_read(ac97, reg);
- if (! *lo_max && (val & 0x7f) == cbit[i])
+ if (! *lo_max && (val & cbit[i]))
*lo_max = max[i];
- if (! *hi_max && ((val >> 8) & 0x7f) == cbit[i])
+ if (! *hi_max && (val & (cbit[i] << 8)))
*hi_max = max[i];
if (*lo_max && *hi_max)
break;
@@ -1531,25 +1526,13 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
static int snd_ac97_modem_build(snd_card_t * card, ac97_t * ac97)
{
- int err, idx;
-
+ /* TODO */
//printk("AC97_GPIO_CFG = %x\n",snd_ac97_read(ac97,AC97_GPIO_CFG));
snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH));
snd_ac97_write(ac97, AC97_GPIO_POLARITY, 0xffff & ~(AC97_GPIO_LINE1_OH));
snd_ac97_write(ac97, AC97_GPIO_STICKY, 0xffff);
snd_ac97_write(ac97, AC97_GPIO_WAKEUP, 0x0);
snd_ac97_write(ac97, AC97_MISC_AFE, 0x0);
-
- /* build modem switches */
- for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_modem_switches); idx++)
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_modem_switches[idx], ac97))) < 0)
- return err;
-
- /* build chip specific controls */
- if (ac97->build_ops->build_specific)
- if ((err = ac97->build_ops->build_specific(ac97)) < 0)
- return err;
-
return 0;
}
@@ -1889,11 +1872,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
goto __access_ok;
}
- /* reset to defaults */
- if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO))
- snd_ac97_write(ac97, AC97_RESET, 0);
- if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM))
- snd_ac97_write(ac97, AC97_EXTENDED_MID, 0);
+ snd_ac97_write(ac97, AC97_RESET, 0); /* reset to defaults */
if (bus->ops->wait)
bus->ops->wait(ac97);
else {
@@ -1985,21 +1964,21 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
/* note: it's important to set the rate at first */
tmp = AC97_MEA_GPIO;
if (ac97->ext_mid & AC97_MEI_LINE1) {
- snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 8000);
+ snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 12000);
tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1;
}
if (ac97->ext_mid & AC97_MEI_LINE2) {
- snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 8000);
+ snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 12000);
tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2;
}
if (ac97->ext_mid & AC97_MEI_HANDSET) {
- snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 8000);
+ snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 12000);
tmp |= AC97_MEA_HADC | AC97_MEA_HDAC;
}
- snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0);
+ snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));
udelay(100);
/* nothing should be in powerdown mode */
- snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0);
+ snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));
end_time = jiffies + (HZ / 10);
do {
if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp)
@@ -2542,11 +2521,11 @@ int snd_ac97_tune_hardware(ac97_t *ac97, struct ac97_quirk *quirk, const char *o
return result;
}
- for (; quirk->subvendor; quirk++) {
- if (quirk->subvendor != ac97->subsystem_vendor)
+ for (; quirk->vendor; quirk++) {
+ if (quirk->vendor != ac97->subsystem_vendor)
continue;
- if ((! quirk->mask && quirk->subdevice == ac97->subsystem_device) ||
- quirk->subdevice == (quirk->mask & ac97->subsystem_device)) {
+ if ((! quirk->mask && quirk->device == ac97->subsystem_device) ||
+ quirk->device == (quirk->mask & ac97->subsystem_device)) {
if (quirk->codec_id && quirk->codec_id != ac97->id)
continue;
snd_printdd("ac97 quirk for %s (%04x:%04x)\n", quirk->name, ac97->subsystem_vendor, ac97->subsystem_device);
diff --git a/trunk/sound/pci/ac97/ac97_patch.c b/trunk/sound/pci/ac97/ac97_patch.c
index a15eb8522b7c..13c34a5d8206 100644
--- a/trunk/sound/pci/ac97/ac97_patch.c
+++ b/trunk/sound/pci/ac97/ac97_patch.c
@@ -64,116 +64,6 @@ static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned shor
return ret;
}
-/*
- * shared line-in/mic controls
- */
-static int ac97_enum_text_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo,
- const char **texts, unsigned int nums)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = nums;
- if (uinfo->value.enumerated.item > nums - 1)
- uinfo->value.enumerated.item = nums - 1;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int ac97_surround_jack_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
- static const char *texts[] = { "Shared", "Independent" };
- return ac97_enum_text_info(kcontrol, uinfo, texts, 2);
-}
-
-static int ac97_surround_jack_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.enumerated.item[0] = ac97->indep_surround;
- return 0;
-}
-
-static int ac97_surround_jack_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned char indep = !!ucontrol->value.enumerated.item[0];
-
- if (indep != ac97->indep_surround) {
- ac97->indep_surround = indep;
- if (ac97->build_ops->update_jacks)
- ac97->build_ops->update_jacks(ac97);
- return 1;
- }
- return 0;
-}
-
-static int ac97_channel_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
- static const char *texts[] = { "2ch", "4ch", "6ch" };
- if (kcontrol->private_value)
- return ac97_enum_text_info(kcontrol, uinfo, texts, 2); /* 4ch only */
- return ac97_enum_text_info(kcontrol, uinfo, texts, 3);
-}
-
-static int ac97_channel_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.enumerated.item[0] = ac97->channel_mode;
- return 0;
-}
-
-static int ac97_channel_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned char mode = ucontrol->value.enumerated.item[0];
-
- if (mode != ac97->channel_mode) {
- ac97->channel_mode = mode;
- if (ac97->build_ops->update_jacks)
- ac97->build_ops->update_jacks(ac97);
- return 1;
- }
- return 0;
-}
-
-#define AC97_SURROUND_JACK_MODE_CTL \
- { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = "Surround Jack Mode", \
- .info = ac97_surround_jack_mode_info, \
- .get = ac97_surround_jack_mode_get, \
- .put = ac97_surround_jack_mode_put, \
- }
-#define AC97_CHANNEL_MODE_CTL \
- { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = "Channel Mode", \
- .info = ac97_channel_mode_info, \
- .get = ac97_channel_mode_get, \
- .put = ac97_channel_mode_put, \
- }
-#define AC97_CHANNEL_MODE_4CH_CTL \
- { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = "Channel Mode", \
- .info = ac97_channel_mode_info, \
- .get = ac97_channel_mode_get, \
- .put = ac97_channel_mode_put, \
- .private_value = 1, \
- }
-
-static inline int is_shared_linein(ac97_t *ac97)
-{
- return ! ac97->indep_surround && ac97->channel_mode >= 1;
-}
-
-static inline int is_shared_micin(ac97_t *ac97)
-{
- return ! ac97->indep_surround && ac97->channel_mode >= 2;
-}
-
-
/* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
/* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
@@ -1500,16 +1390,6 @@ static int snd_ac97_ad1888_downmix_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val);
}
-static void ad1888_update_jacks(ac97_t *ac97)
-{
- /* shared Line-In */
- snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12,
- is_shared_linein(ac97) ? 0 : 1 << 12);
- /* shared Mic */
- snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11,
- is_shared_micin(ac97) ? 0 : 1 << 11);
-}
-
static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1526,8 +1406,8 @@ static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = {
.get = snd_ac97_ad1888_downmix_get,
.put = snd_ac97_ad1888_downmix_put
},
- AC97_SURROUND_JACK_MODE_CTL,
- AC97_CHANNEL_MODE_CTL,
+ AC97_SINGLE("Surround Jack as Input", AC97_AD_MISC, 12, 1, 0),
+ AC97_SINGLE("Center/LFE Jack as Input", AC97_AD_MISC, 11, 1, 0),
};
static int patch_ad1888_specific(ac97_t *ac97)
@@ -1542,9 +1422,8 @@ static struct snd_ac97_build_ops patch_ad1888_build_ops = {
.build_post_spdif = patch_ad198x_post_spdif,
.build_specific = patch_ad1888_specific,
#ifdef CONFIG_PM
- .resume = ad18xx_resume,
+ .resume = ad18xx_resume
#endif
- .update_jacks = ad1888_update_jacks,
};
int patch_ad1888(ac97_t * ac97)
@@ -1580,9 +1459,8 @@ static struct snd_ac97_build_ops patch_ad1980_build_ops = {
.build_post_spdif = patch_ad198x_post_spdif,
.build_specific = patch_ad1980_specific,
#ifdef CONFIG_PM
- .resume = ad18xx_resume,
+ .resume = ad18xx_resume
#endif
- .update_jacks = ad1888_update_jacks,
};
int patch_ad1980(ac97_t * ac97)
@@ -1593,21 +1471,10 @@ int patch_ad1980(ac97_t * ac97)
}
static const snd_kcontrol_new_t snd_ac97_ad1985_controls[] = {
+ AC97_SINGLE("Center/LFE Jack as Mic", AC97_AD_SERIAL_CFG, 9, 1, 0),
AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0)
};
-static void ad1985_update_jacks(ac97_t *ac97)
-{
- /* shared Line-In */
- snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12,
- is_shared_linein(ac97) ? 0 : 1 << 12);
- /* shared Mic */
- snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11,
- is_shared_micin(ac97) ? 0 : 1 << 11);
- snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9,
- is_shared_micin(ac97) ? 0 : 1 << 9);
-}
-
static int patch_ad1985_specific(ac97_t *ac97)
{
int err;
@@ -1621,9 +1488,8 @@ static struct snd_ac97_build_ops patch_ad1985_build_ops = {
.build_post_spdif = patch_ad198x_post_spdif,
.build_specific = patch_ad1985_specific,
#ifdef CONFIG_PM
- .resume = ad18xx_resume,
+ .resume = ad18xx_resume
#endif
- .update_jacks = ad1985_update_jacks,
};
int patch_ad1985(ac97_t * ac97)
@@ -1655,25 +1521,31 @@ int patch_ad1985(ac97_t * ac97)
/*
* realtek ALC65x/850 codecs
*/
-static void alc650_update_jacks(ac97_t *ac97)
+static int snd_ac97_alc650_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- int shared;
-
- /* shared Line-In */
- shared = is_shared_linein(ac97);
- snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9,
- shared ? (1 << 9) : 0);
- /* update shared Mic */
- shared = is_shared_micin(ac97);
- /* disable/enable vref */
- snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
- shared ? (1 << 12) : 0);
- /* turn on/off center-on-mic */
- snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
- shared ? (1 << 10) : 0);
- /* GPIO0 high for mic */
- snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
- shared ? 0 : 0x100);
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
+ return 0;
+}
+
+static int snd_ac97_alc650_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ int change, val;
+ val = !!(snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10));
+ change = (ucontrol->value.integer.value[0] != val);
+ if (change) {
+ /* disable/enable vref */
+ snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
+ ucontrol->value.integer.value[0] ? (1 << 12) : 0);
+ /* turn on/off center-on-mic */
+ snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
+ ucontrol->value.integer.value[0] ? (1 << 10) : 0);
+ /* GPIO0 high for mic */
+ snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
+ ucontrol->value.integer.value[0] ? 0 : 0x100);
+ }
+ return change;
}
static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
@@ -1686,8 +1558,8 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
/* 6: Independent Master Volume Right */
/* 7: Independent Master Volume Left */
/* 8: reserved */
- /* 9: Line-In/Surround share */
- /* 10: Mic/CLFE share */
+ AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
+ /* 10: mic, see below */
/* 11-13: in IEC958 controls */
AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0),
#if 0 /* always set in patch_alc650 */
@@ -1698,8 +1570,14 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
#endif
- AC97_SURROUND_JACK_MODE_CTL,
- AC97_CHANNEL_MODE_CTL,
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic As Center/LFE",
+ .info = snd_ac97_info_volsw,
+ .get = snd_ac97_alc650_mic_get,
+ .put = snd_ac97_alc650_mic_put,
+ .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+ },
};
static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {
@@ -1723,8 +1601,7 @@ static int patch_alc650_specific(ac97_t * ac97)
}
static struct snd_ac97_build_ops patch_alc650_ops = {
- .build_specific = patch_alc650_specific,
- .update_jacks = alc650_update_jacks
+ .build_specific = patch_alc650_specific
};
int patch_alc650(ac97_t * ac97)
@@ -1782,27 +1659,37 @@ int patch_alc650(ac97_t * ac97)
return 0;
}
-static void alc655_update_jacks(ac97_t *ac97)
+static int snd_ac97_alc655_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- int shared;
-
- /* shared Line-In */
- shared = is_shared_linein(ac97);
- ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9,
- shared ? (1 << 9) : 0, 0);
- /* update shared mic */
- shared = is_shared_micin(ac97);
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
+ return 0;
+}
+
+static int snd_ac97_alc655_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
/* misc control; vrefout disable */
snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
- shared ? (1 << 12) : 0);
- ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
- shared ? (1 << 10) : 0, 0);
+ ucontrol->value.integer.value[0] ? (1 << 12) : 0);
+ return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
+ ucontrol->value.integer.value[0] ? (1 << 10) : 0,
+ 0);
}
+
static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = {
AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
- AC97_SURROUND_JACK_MODE_CTL,
- AC97_CHANNEL_MODE_CTL,
+ AC97_PAGE_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0, 0),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic As Center/LFE",
+ .info = snd_ac97_info_volsw,
+ .get = snd_ac97_alc655_mic_get,
+ .put = snd_ac97_alc655_mic_put,
+ .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+ },
};
static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -1872,8 +1759,7 @@ static int patch_alc655_specific(ac97_t * ac97)
}
static struct snd_ac97_build_ops patch_alc655_ops = {
- .build_specific = patch_alc655_specific,
- .update_jacks = alc655_update_jacks
+ .build_specific = patch_alc655_specific
};
int patch_alc655(ac97_t * ac97)
@@ -1912,33 +1798,63 @@ int patch_alc655(ac97_t * ac97)
#define AC97_ALC850_JACK_SELECT 0x76
#define AC97_ALC850_MISC1 0x7a
-static void alc850_update_jacks(ac97_t *ac97)
+static int ac97_alc850_surround_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- int shared;
-
- /* shared Line-In */
- shared = is_shared_linein(ac97);
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 12) & 7) == 2;
+ return 0;
+}
+
+static int ac97_alc850_surround_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
/* SURR 1kOhm (bit4), Amp (bit5) */
snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
- shared ? (1<<5) : (1<<4));
+ ucontrol->value.integer.value[0] ? (1<<5) : (1<<4));
/* LINE-IN = 0, SURROUND = 2 */
- snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
- shared ? (2<<12) : (0<<12));
- /* update shared mic */
- shared = is_shared_micin(ac97);
+ return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
+ ucontrol->value.integer.value[0] ? (2<<12) : (0<<12));
+}
+
+static int ac97_alc850_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 4) & 7) == 2;
+ return 0;
+}
+
+static int ac97_alc850_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
/* Vref disable (bit12), 1kOhm (bit13) */
snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
- shared ? (1<<12) : (1<<13));
+ ucontrol->value.integer.value[0] ? (1<<12) : (1<<13));
/* MIC-IN = 1, CENTER-LFE = 2 */
- snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
- shared ? (2<<4) : (1<<4));
+ return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
+ ucontrol->value.integer.value[0] ? (2<<4) : (1<<4));
}
static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = {
AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
- AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
- AC97_SURROUND_JACK_MODE_CTL,
- AC97_CHANNEL_MODE_CTL,
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Line-In As Surround",
+ .info = snd_ac97_info_volsw,
+ .get = ac97_alc850_surround_get,
+ .put = ac97_alc850_surround_put,
+ .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic As Center/LFE",
+ .info = snd_ac97_info_volsw,
+ .get = ac97_alc850_mic_get,
+ .put = ac97_alc850_mic_put,
+ .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+ },
+
};
static int patch_alc850_specific(ac97_t *ac97)
@@ -1955,8 +1871,7 @@ static int patch_alc850_specific(ac97_t *ac97)
}
static struct snd_ac97_build_ops patch_alc850_ops = {
- .build_specific = patch_alc850_specific,
- .update_jacks = alc850_update_jacks
+ .build_specific = patch_alc850_specific
};
int patch_alc850(ac97_t *ac97)
@@ -1996,17 +1911,9 @@ int patch_alc850(ac97_t *ac97)
/*
* C-Media CM97xx codecs
*/
-static void cm9738_update_jacks(ac97_t *ac97)
-{
- /* shared Line-In */
- snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10,
- is_shared_linein(ac97) ? (1 << 10) : 0);
-}
-
static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {
+ AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0),
AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
- AC97_SURROUND_JACK_MODE_CTL,
- AC97_CHANNEL_MODE_4CH_CTL,
};
static int patch_cm9738_specific(ac97_t * ac97)
@@ -2015,8 +1922,7 @@ static int patch_cm9738_specific(ac97_t * ac97)
}
static struct snd_ac97_build_ops patch_cm9738_ops = {
- .build_specific = patch_cm9738_specific,
- .update_jacks = cm9738_update_jacks
+ .build_specific = patch_cm9738_specific
};
int patch_cm9738(ac97_t * ac97)
@@ -2080,19 +1986,34 @@ static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = {
/* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
};
-static void cm9739_update_jacks(ac97_t *ac97)
+static int snd_ac97_cm9739_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000)
+ ucontrol->value.integer.value[0] = 1;
+ else
+ ucontrol->value.integer.value[0] = 0;
+ return 0;
+}
+
+static int snd_ac97_cm9739_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- /* shared Line-In */
- snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10,
- is_shared_linein(ac97) ? (1 << 10) : 0);
- /* shared Mic */
- snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
- is_shared_micin(ac97) ? 0x1000 : 0x2000);
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
+ ucontrol->value.integer.value[0] ?
+ 0x1000 : 0x2000);
}
static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = {
- AC97_SURROUND_JACK_MODE_CTL,
- AC97_CHANNEL_MODE_CTL,
+ AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic As Center/LFE",
+ .info = snd_ac97_info_volsw,
+ .get = snd_ac97_cm9739_center_mic_get,
+ .put = snd_ac97_cm9739_center_mic_put,
+ .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+ },
};
static int patch_cm9739_specific(ac97_t * ac97)
@@ -2107,8 +2028,7 @@ static int patch_cm9739_post_spdif(ac97_t * ac97)
static struct snd_ac97_build_ops patch_cm9739_ops = {
.build_specific = patch_cm9739_specific,
- .build_post_spdif = patch_cm9739_post_spdif,
- .update_jacks = cm9739_update_jacks
+ .build_post_spdif = patch_cm9739_post_spdif
};
int patch_cm9739(ac97_t * ac97)
@@ -2167,97 +2087,71 @@ int patch_cm9739(ac97_t * ac97)
}
#define AC97_CM9761_MULTI_CHAN 0x64
-#define AC97_CM9761_FUNC 0x66
#define AC97_CM9761_SPDIF_CTRL 0x6c
-static void cm9761_update_jacks(ac97_t *ac97)
+static int snd_ac97_cm9761_linein_rear_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- unsigned short surr_vals[2][2] = {
- { 0x0008, 0x0400 }, /* off, on */
- { 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */
- };
- unsigned short clfe_vals[2][2] = {
- { 0x2000, 0x1880 }, /* off, on */
- { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */
- };
-
- /* shared Line-In */
- snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x0408,
- surr_vals[ac97->spec.dev_flags][is_shared_linein(ac97)]);
- /* shared Mic */
- snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3880,
- clfe_vals[ac97->spec.dev_flags][is_shared_micin(ac97)]);
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x0400)
+ ucontrol->value.integer.value[0] = 1;
+ else
+ ucontrol->value.integer.value[0] = 0;
+ return 0;
}
-static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = {
- AC97_SURROUND_JACK_MODE_CTL,
- AC97_CHANNEL_MODE_CTL,
-};
-
-static int cm9761_spdif_out_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ac97_cm9761_linein_rear_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- static char *texts[] = { "AC-Link", "ADC", "SPDIF-In" };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 3;
- if (uinfo->value.enumerated.item > 2)
- uinfo->value.enumerated.item = 2;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ unsigned short vals[2][2] = {
+ { 0x0008, 0x0400 }, /* off, on */
+ { 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */
+ };
+ return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x0408,
+ vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]);
}
-static int cm9761_spdif_out_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ac97_cm9761_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-
- if (ac97->regs[AC97_CM9761_FUNC] & 0x1)
- ucontrol->value.enumerated.item[0] = 2; /* SPDIF-loopback */
- else if (ac97->regs[AC97_CM9761_SPDIF_CTRL] & 0x2)
- ucontrol->value.enumerated.item[0] = 1; /* ADC loopback */
+ if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000)
+ ucontrol->value.integer.value[0] = 1;
else
- ucontrol->value.enumerated.item[0] = 0; /* AC-link */
+ ucontrol->value.integer.value[0] = 0;
+ if (ac97->spec.dev_flags) /* 9761-82 rev.B */
+ ucontrol->value.integer.value[0] = !ucontrol->value.integer.value[0];
return 0;
}
-static int cm9761_spdif_out_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ac97_cm9761_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-
- if (ucontrol->value.enumerated.item[0] == 2)
- return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1);
- snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0);
- return snd_ac97_update_bits(ac97, AC97_CM9761_SPDIF_CTRL, 0x2,
- ucontrol->value.enumerated.item[0] == 1 ? 0x2 : 0);
+ unsigned short vals[2][2] = {
+ { 0x2000, 0x1880 }, /* off, on */
+ { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */
+ };
+ return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3880,
+ vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]);
}
-static const char *cm9761_dac_clock[] = { "AC-Link", "SPDIF-In", "Both" };
-static const struct ac97_enum cm9761_dac_clock_enum =
- AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock);
-
-static const snd_kcontrol_new_t snd_ac97_cm9761_controls_spdif[] = {
- { /* BIT 1: SPDIFS */
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
- .info = cm9761_spdif_out_source_info,
- .get = cm9761_spdif_out_source_get,
- .put = cm9761_spdif_out_source_put,
+static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Line-In As Surround",
+ .info = snd_ac97_info_volsw,
+ .get = snd_ac97_cm9761_linein_rear_get,
+ .put = snd_ac97_cm9761_linein_rear_put,
+ .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic As Center/LFE",
+ .info = snd_ac97_info_volsw,
+ .get = snd_ac97_cm9761_center_mic_get,
+ .put = snd_ac97_cm9761_center_mic_put,
+ .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
},
- /* BIT 2: IG_SPIV */
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9761_SPDIF_CTRL, 2, 1, 0),
- /* BIT 3: SPI2F */
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9761_SPDIF_CTRL, 3, 1, 0),
- /* BIT 4: SPI2SDI */
- AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9761_SPDIF_CTRL, 4, 1, 0),
- /* BIT 9-10: DAC_CTL */
- AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum),
};
-static int patch_cm9761_post_spdif(ac97_t * ac97)
-{
- return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif));
-}
-
static int patch_cm9761_specific(ac97_t * ac97)
{
return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls));
@@ -2265,8 +2159,7 @@ static int patch_cm9761_specific(ac97_t * ac97)
static struct snd_ac97_build_ops patch_cm9761_ops = {
.build_specific = patch_cm9761_specific,
- .build_post_spdif = patch_cm9761_post_spdif,
- .update_jacks = cm9761_update_jacks
+ .build_post_spdif = patch_cm9739_post_spdif /* hope it's identical... */
};
int patch_cm9761(ac97_t *ac97)
@@ -2300,25 +2193,24 @@ int patch_cm9761(ac97_t *ac97)
/* to be sure: we overwrite the ext status bits */
snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0);
/* Don't set 0x0200 here. This results in the silent analog output */
- snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0001); /* enable spdif-in */
+ snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0009);
ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
/* set-up multi channel */
/* bit 15: pc master beep off
- * bit 14: pin47 = EAPD/SPDIF
+ * bit 14: ??
* bit 13: vref ctl [= cm9739]
- * bit 12: CLFE control (reverted on rev B)
- * bit 11: Mic/center share (reverted on rev B)
- * bit 10: suddound/line share
- * bit 9: Analog-in mix -> surround
- * bit 8: Analog-in mix -> CLFE
- * bit 7: Mic/LFE share (mic/center/lfe)
- * bit 5: vref select (9761A)
- * bit 4: front control
- * bit 3: surround control (revereted with rev B)
- * bit 2: front mic
- * bit 1: stereo mic
- * bit 0: mic boost level (0=20dB, 1=30dB)
+ * bit 12: center/mic [= cm9739] (reverted on rev B)
+ * bit 11: ?? (mic/center/lfe) (reverted on rev B)
+ * bit 10: suddound/line [= cm9739]
+ * bit 9: mix 2 surround
+ * bit 8: ?
+ * bit 7: ?? (mic/center/lfe)
+ * bit 4: ?? (front)
+ * bit 3: ?? (line-in/rear share) (revereted with rev B)
+ * bit 2: ?? (surround)
+ * bit 1: front mic
+ * bit 0: mic boost
*/
#if 0
@@ -2338,47 +2230,6 @@ int patch_cm9761(ac97_t *ac97)
return 0;
}
-#define AC97_CM9780_SIDE 0x60
-#define AC97_CM9780_JACK 0x62
-#define AC97_CM9780_MIXER 0x64
-#define AC97_CM9780_MULTI_CHAN 0x66
-#define AC97_CM9780_SPDIF 0x6c
-
-static const char *cm9780_ch_select[] = { "Front", "Side", "Center/LFE", "Rear" };
-static const struct ac97_enum cm9780_ch_select_enum =
- AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select);
-static const snd_kcontrol_new_t cm9780_controls[] = {
- AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1),
- AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0),
- AC97_ENUM("Side Playback Route", cm9780_ch_select_enum),
-};
-
-static int patch_cm9780_specific(ac97_t *ac97)
-{
- return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls));
-}
-
-static struct snd_ac97_build_ops patch_cm9780_ops = {
- .build_specific = patch_cm9780_specific,
- .build_post_spdif = patch_cm9761_post_spdif /* identical with CM9761 */
-};
-
-int patch_cm9780(ac97_t *ac97)
-{
- unsigned short val;
-
- ac97->build_ops = &patch_cm9780_ops;
-
- /* enable spdif */
- if (ac97->ext_id & AC97_EI_SPDIF) {
- ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
- val = snd_ac97_read(ac97, AC97_CM9780_SPDIF);
- val |= 0x1; /* SPDI_EN */
- snd_ac97_write_cache(ac97, AC97_CM9780_SPDIF, val);
- }
-
- return 0;
-}
/*
* VIA VT1616 codec
@@ -2412,21 +2263,9 @@ int patch_vt1616(ac97_t * ac97)
return 0;
}
-/*
- */
-static void it2646_update_jacks(ac97_t *ac97)
-{
- /* shared Line-In */
- snd_ac97_update_bits(ac97, 0x76, 1 << 9,
- is_shared_linein(ac97) ? (1<<9) : 0);
- /* shared Mic */
- snd_ac97_update_bits(ac97, 0x76, 1 << 10,
- is_shared_micin(ac97) ? (1<<10) : 0);
-}
-
static const snd_kcontrol_new_t snd_ac97_controls_it2646[] = {
- AC97_SURROUND_JACK_MODE_CTL,
- AC97_CHANNEL_MODE_CTL,
+ AC97_SINGLE("Line-In As Surround", 0x76, 9, 1, 0),
+ AC97_SINGLE("Mic As Center/LFE", 0x76, 10, 1, 0),
};
static const snd_kcontrol_new_t snd_ac97_spdif_controls_it2646[] = {
@@ -2446,8 +2285,7 @@ static int patch_it2646_specific(ac97_t * ac97)
}
static struct snd_ac97_build_ops patch_it2646_ops = {
- .build_specific = patch_it2646_specific,
- .update_jacks = it2646_update_jacks
+ .build_specific = patch_it2646_specific
};
int patch_it2646(ac97_t * ac97)
@@ -2459,29 +2297,12 @@ int patch_it2646(ac97_t * ac97)
return 0;
}
-/*
- * Si3036 codec
- */
-
+/* Si3036/8 specific registers */
#define AC97_SI3036_CHIP_ID 0x5a
-#define AC97_SI3036_LINE_CFG 0x5c
-
-static const snd_kcontrol_new_t snd_ac97_controls_si3036[] = {
-AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1)
-};
-
-static int patch_si3036_specific(ac97_t * ac97)
-{
- return patch_build_controls(ac97, snd_ac97_controls_si3036, ARRAY_SIZE(snd_ac97_controls_si3036));
-}
-
-static struct snd_ac97_build_ops patch_si3036_ops = {
- .build_specific = patch_si3036_specific,
-};
int mpatch_si3036(ac97_t * ac97)
{
- ac97->build_ops = &patch_si3036_ops;
+ //printk("mpatch_si3036: chip id = %x\n", snd_ac97_read(ac97, 0x5a));
snd_ac97_write_cache(ac97, 0x5c, 0xf210 );
snd_ac97_write_cache(ac97, 0x68, 0);
return 0;
diff --git a/trunk/sound/pci/ac97/ac97_patch.h b/trunk/sound/pci/ac97/ac97_patch.h
index 7b7377d0f2ae..6db51c96f5d0 100644
--- a/trunk/sound/pci/ac97/ac97_patch.h
+++ b/trunk/sound/pci/ac97/ac97_patch.h
@@ -54,7 +54,6 @@ int patch_alc850(ac97_t * ac97);
int patch_cm9738(ac97_t * ac97);
int patch_cm9739(ac97_t * ac97);
int patch_cm9761(ac97_t * ac97);
-int patch_cm9780(ac97_t * ac97);
int patch_vt1616(ac97_t * ac97);
int patch_it2646(ac97_t * ac97);
int mpatch_si3036(ac97_t * ac97);
diff --git a/trunk/sound/pci/ali5451/ali5451.c b/trunk/sound/pci/ali5451/ali5451.c
index eb5c36d31a52..984d5d4ba4e1 100644
--- a/trunk/sound/pci/ali5451/ali5451.c
+++ b/trunk/sound/pci/ali5451/ali5451.c
@@ -98,8 +98,6 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
#define ALI_LEF_CHANNEL 23
#define ALI_SURR_LEFT_CHANNEL 26
#define ALI_SURR_RIGHT_CHANNEL 25
-#define ALI_MODEM_IN_CHANNEL 21
-#define ALI_MODEM_OUT_CHANNEL 20
#define SNDRV_ALI_VOICE_TYPE_PCM 01
#define SNDRV_ALI_VOICE_TYPE_OTH 02
@@ -124,15 +122,7 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
#define ALI_SCTRL 0x48
#define ALI_SPDIF_OUT_ENABLE 0x20
-#define ALI_SCTRL_LINE_IN2 (1 << 9)
-#define ALI_SCTRL_GPIO_IN2 (1 << 13)
-#define ALI_SCTRL_LINE_OUT_EN (1 << 20)
-#define ALI_SCTRL_GPIO_OUT_EN (1 << 23)
-#define ALI_SCTRL_CODEC1_READY (1 << 24)
-#define ALI_SCTRL_CODEC2_READY (1 << 25)
#define ALI_AC97_GPIO 0x4c
-#define ALI_AC97_GPIO_ENABLE 0x8000
-#define ALI_AC97_GPIO_DATA_SHIFT 16
#define ALI_SPDIF_CS 0x70
#define ALI_SPDIF_CTRL 0x74
#define ALI_SPDIF_IN_FUNC_ENABLE 0x02
@@ -153,7 +143,6 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
#define TARGET_REACHED 0x00008000
#define MIXER_OVERFLOW 0x00000800
#define MIXER_UNDERFLOW 0x00000400
- #define GPIO_IRQ 0x01000000
#define ALI_SBBL_SBCL 0xc0
#define ALI_SBCTRL_SBE2R_SBDD 0xc4
#define ALI_STIMER 0xc8
@@ -173,9 +162,6 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
#define ALI_REG(codec, x) ((codec)->port + x)
-#define MAX_CODECS 2
-
-
typedef struct snd_stru_ali ali_t;
typedef struct snd_ali_stru_voice snd_ali_voice_t;
@@ -259,7 +245,7 @@ struct snd_stru_ali {
struct pci_dev *pci_m7101;
snd_card_t *card;
- snd_pcm_t *pcm[MAX_CODECS];
+ snd_pcm_t *pcm;
alidev_t synth;
snd_ali_channel_control_t chregs;
@@ -269,10 +255,8 @@ struct snd_stru_ali {
unsigned int spurious_irq_count;
unsigned int spurious_irq_max_delta;
- unsigned int num_of_codecs;
-
ac97_bus_t *ac97_bus;
- ac97_t *ac97[MAX_CODECS];
+ ac97_t *ac97;
unsigned short ac97_ext_id;
unsigned short ac97_ext_status;
@@ -505,12 +489,7 @@ static void snd_ali_codec_write(ac97_t *ac97,
ali_t *codec = ac97->private_data;
snd_ali_printk("codec_write: reg=%xh data=%xh.\n", reg, val);
- if(reg == AC97_GPIO_STATUS) {
- outl((val << ALI_AC97_GPIO_DATA_SHIFT)|ALI_AC97_GPIO_ENABLE,
- ALI_REG(codec, ALI_AC97_GPIO));
- return;
- }
- snd_ali_codec_poke(codec, ac97->num, reg, val);
+ snd_ali_codec_poke(codec, 0, reg, val);
return ;
}
@@ -520,7 +499,7 @@ static unsigned short snd_ali_codec_read(ac97_t *ac97, unsigned short reg)
ali_t *codec = ac97->private_data;
snd_ali_printk("codec_read reg=%xh.\n", reg);
- return (snd_ali_codec_peek(codec, ac97->num, reg));
+ return (snd_ali_codec_peek(codec, 0, reg));
}
/*
@@ -1072,7 +1051,7 @@ static irqreturn_t snd_ali_card_interrupt(int irq,
}
-static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec, int channel)
+static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec)
{
snd_ali_voice_t *pvoice = NULL;
unsigned long flags;
@@ -1082,8 +1061,7 @@ static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec, in
spin_lock_irqsave(&codec->voice_alloc, flags);
if (type == SNDRV_ALI_VOICE_TYPE_PCM) {
- idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) :
- snd_ali_find_free_channel(codec,rec);
+ idx = snd_ali_find_free_channel(codec,rec);
if(idx < 0) {
snd_printk("ali_alloc_voice: err.\n");
spin_unlock_irqrestore(&codec->voice_alloc, flags);
@@ -1319,7 +1297,7 @@ static int snd_ali_playback_hw_params(snd_pcm_substream_t * substream,
if (params_buffer_size(hw_params)/2 != params_period_size(hw_params)) {
if (evoice == NULL) {
- evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0, -1);
+ evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0);
if (evoice == NULL)
return -ENOMEM;
pvoice->extra = evoice;
@@ -1350,13 +1328,13 @@ static int snd_ali_playback_hw_free(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ali_hw_params(snd_pcm_substream_t * substream,
+static int snd_ali_capture_hw_params(snd_pcm_substream_t * substream,
snd_pcm_hw_params_t * hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_ali_hw_free(snd_pcm_substream_t * substream)
+static int snd_ali_capture_hw_free(snd_pcm_substream_t * substream)
{
return snd_pcm_lib_free_pages(substream);
}
@@ -1450,7 +1428,7 @@ static int snd_ali_playback_prepare(snd_pcm_substream_t * substream)
}
-static int snd_ali_prepare(snd_pcm_substream_t * substream)
+static int snd_ali_capture_prepare(snd_pcm_substream_t * substream)
{
ali_t *codec = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1468,13 +1446,11 @@ static int snd_ali_prepare(snd_pcm_substream_t * substream)
spin_lock_irqsave(&codec->reg_lock, flags);
- snd_ali_printk("ali_prepare...\n");
+ snd_ali_printk("capture_prepare...\n");
snd_ali_enable_special_channel(codec,pvoice->number);
- Delta = (pvoice->number == ALI_MODEM_IN_CHANNEL ||
- pvoice->number == ALI_MODEM_OUT_CHANNEL) ?
- 0x1000 : snd_ali_convert_rate(runtime->rate, pvoice->mode);
+ Delta = snd_ali_convert_rate(runtime->rate, 1);
// Prepare capture intr channel
if (pvoice->number == ALI_SPDIF_IN_CHANNEL) {
@@ -1558,7 +1534,7 @@ static snd_pcm_uframes_t snd_ali_playback_pointer(snd_pcm_substream_t *substream
}
-static snd_pcm_uframes_t snd_ali_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_ali_capture_pointer(snd_pcm_substream_t *substream)
{
ali_t *codec = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1640,8 +1616,7 @@ static void snd_ali_pcm_free_substream(snd_pcm_runtime_t *runtime)
}
}
-static int snd_ali_open(snd_pcm_substream_t * substream, int rec, int channel,
- snd_pcm_hardware_t *phw)
+static int snd_ali_playback_open(snd_pcm_substream_t * substream)
{
ali_t *codec = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1649,7 +1624,7 @@ static int snd_ali_open(snd_pcm_substream_t * substream, int rec, int channel,
unsigned long flags = 0;
spin_lock_irqsave(&codec->reg_lock, flags);
- pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec, channel);
+ pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0);
if (pvoice == NULL) {
spin_unlock_irqrestore(&codec->reg_lock, flags);
return -EAGAIN;
@@ -1661,31 +1636,49 @@ static int snd_ali_open(snd_pcm_substream_t * substream, int rec, int channel,
runtime->private_data = pvoice;
runtime->private_free = snd_ali_pcm_free_substream;
- runtime->hw = *phw;
+ runtime->hw = snd_ali_playback;
snd_pcm_set_sync(substream);
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
return 0;
}
-static int snd_ali_playback_open(snd_pcm_substream_t * substream)
-{
- return snd_ali_open(substream, 0, -1, &snd_ali_playback);
-}
static int snd_ali_capture_open(snd_pcm_substream_t * substream)
{
- return snd_ali_open(substream, 1, -1, &snd_ali_capture);
+ ali_t *codec = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ snd_ali_voice_t *pvoice;
+ unsigned long flags;
+
+ spin_lock_irqsave(&codec->reg_lock, flags);
+ pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 1);
+ if (pvoice == NULL) {
+ spin_unlock_irqrestore(&codec->reg_lock, flags);
+ return -EAGAIN;
+ }
+ pvoice->codec = codec;
+ spin_unlock_irqrestore(&codec->reg_lock, flags);
+
+ pvoice->substream = substream;
+ runtime->private_data = pvoice;
+ runtime->private_free = snd_ali_pcm_free_substream;
+ runtime->hw = snd_ali_capture;
+ snd_pcm_set_sync(substream);
+ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
+ return 0;
}
+
static int snd_ali_playback_close(snd_pcm_substream_t * substream)
{
return 0;
}
-static int snd_ali_close(snd_pcm_substream_t * substream)
+static int snd_ali_capture_close(snd_pcm_substream_t * substream)
{
ali_t *codec = snd_pcm_substream_chip(substream);
- snd_ali_voice_t *pvoice = (snd_ali_voice_t *) substream->runtime->private_data;
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
snd_ali_disable_special_channel(codec,pvoice->number);
@@ -1705,121 +1698,29 @@ static snd_pcm_ops_t snd_ali_playback_ops = {
static snd_pcm_ops_t snd_ali_capture_ops = {
.open = snd_ali_capture_open,
- .close = snd_ali_close,
+ .close = snd_ali_capture_close,
.ioctl = snd_ali_ioctl,
- .hw_params = snd_ali_hw_params,
- .hw_free = snd_ali_hw_free,
- .prepare = snd_ali_prepare,
- .trigger = snd_ali_trigger,
- .pointer = snd_ali_pointer,
-};
-
-/*
- * Modem PCM
- */
-
-static int snd_ali_modem_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
-{
- ali_t *chip = snd_pcm_substream_chip(substream);
- unsigned int modem_num = chip->num_of_codecs - 1;
- snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE, params_rate(hw_params));
- snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_LEVEL, 0);
- return snd_ali_hw_params(substream, hw_params);
-}
-
-static snd_pcm_hardware_t snd_ali_modem =
-{
- .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_RESUME |
- SNDRV_PCM_INFO_SYNC_START),
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_KNOT|SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000,
- .rate_min = 8000,
- .rate_max = 16000,
- .channels_min = 1,
- .channels_max = 1,
- .buffer_bytes_max = (256*1024),
- .period_bytes_min = 64,
- .period_bytes_max = (256*1024),
- .periods_min = 1,
- .periods_max = 1024,
- .fifo_size = 0,
-};
-
-static int snd_ali_modem_open(snd_pcm_substream_t * substream, int rec, int channel)
-{
- static unsigned int rates [] = {8000,9600,12000,16000};
- static snd_pcm_hw_constraint_list_t hw_constraint_rates = {
- .count = ARRAY_SIZE(rates),
- .list = rates,
- .mask = 0,
- };
- int err = snd_ali_open(substream, rec, channel, &snd_ali_modem);
- if (err)
- return err;
- return snd_pcm_hw_constraint_list(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);
-}
-
-static int snd_ali_modem_playback_open(snd_pcm_substream_t * substream)
-{
- return snd_ali_modem_open(substream, 0, ALI_MODEM_OUT_CHANNEL);
-}
-
-static int snd_ali_modem_capture_open(snd_pcm_substream_t * substream)
-{
- return snd_ali_modem_open(substream, 1, ALI_MODEM_IN_CHANNEL);
-}
-
-static snd_pcm_ops_t snd_ali_modem_playback_ops = {
- .open = snd_ali_modem_playback_open,
- .close = snd_ali_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_ali_modem_hw_params,
- .hw_free = snd_ali_hw_free,
- .prepare = snd_ali_prepare,
- .trigger = snd_ali_trigger,
- .pointer = snd_ali_pointer,
-};
-
-static snd_pcm_ops_t snd_ali_modem_capture_ops = {
- .open = snd_ali_modem_capture_open,
- .close = snd_ali_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_ali_modem_hw_params,
- .hw_free = snd_ali_hw_free,
- .prepare = snd_ali_prepare,
+ .hw_params = snd_ali_capture_hw_params,
+ .hw_free = snd_ali_capture_hw_free,
+ .prepare = snd_ali_capture_prepare,
.trigger = snd_ali_trigger,
- .pointer = snd_ali_pointer,
-};
-
-
-struct ali_pcm_description {
- char *name;
- unsigned int playback_num;
- unsigned int capture_num;
- snd_pcm_ops_t *playback_ops;
- snd_pcm_ops_t *capture_ops;
+ .pointer = snd_ali_capture_pointer,
};
static void snd_ali_pcm_free(snd_pcm_t *pcm)
{
ali_t *codec = pcm->private_data;
- codec->pcm[pcm->device] = NULL;
+ codec->pcm = NULL;
}
-
-static int __devinit snd_ali_pcm(ali_t * codec, int device, struct ali_pcm_description *desc)
+static int __devinit snd_ali_pcm(ali_t * codec, int device, snd_pcm_t ** rpcm)
{
snd_pcm_t *pcm;
int err;
- err = snd_pcm_new(codec->card, desc->name, device,
- desc->playback_num, desc->capture_num, &pcm);
+ if (rpcm) *rpcm = NULL;
+ err = snd_pcm_new(codec->card, "ALI 5451", device, ALI_CHANNELS, 1, &pcm);
if (err < 0) {
snd_printk("snd_ali_pcm: err called snd_pcm_new.\n");
return err;
@@ -1827,36 +1728,20 @@ static int __devinit snd_ali_pcm(ali_t * codec, int device, struct ali_pcm_descr
pcm->private_data = codec;
pcm->private_free = snd_ali_pcm_free;
pcm->info_flags = 0;
- if (desc->playback_ops)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, desc->playback_ops);
- if (desc->capture_ops)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, desc->capture_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ali_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ali_capture_ops);
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(codec->pci), 64*1024, 128*1024);
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
- strcpy(pcm->name, desc->name);
- codec->pcm[0] = pcm;
+ strcpy(pcm->name, "ALI 5451");
+ codec->pcm = pcm;
+ if (rpcm) *rpcm = pcm;
return 0;
}
-struct ali_pcm_description ali_pcms[] = {
- { "ALI 5451", ALI_CHANNELS, 1, &snd_ali_playback_ops, &snd_ali_capture_ops },
- { "ALI 5451 modem", 1, 1, &snd_ali_modem_playback_ops, &snd_ali_modem_capture_ops }
-};
-
-static int __devinit snd_ali_build_pcms(ali_t *codec)
-{
- int i, err;
- for(i = 0 ; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms) ; i++)
- if((err = snd_ali_pcm(codec, i, &ali_pcms[i])) < 0)
- return err;
- return 0;
-}
-
-
#define ALI5451_SPDIF(xname, xindex, value) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
.info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \
@@ -1975,14 +1860,14 @@ static void snd_ali_mixer_free_ac97_bus(ac97_bus_t *bus)
static void snd_ali_mixer_free_ac97(ac97_t *ac97)
{
ali_t *codec = ac97->private_data;
- codec->ac97[ac97->num] = NULL;
+ codec->ac97 = NULL;
}
static int __devinit snd_ali_mixer(ali_t * codec)
{
ac97_template_t ac97;
unsigned int idx;
- int i, err;
+ int err;
static ac97_bus_ops_t ops = {
.write = snd_ali_codec_write,
.read = snd_ali_codec_read,
@@ -1995,16 +1880,10 @@ static int __devinit snd_ali_mixer(ali_t * codec)
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = codec;
ac97.private_free = snd_ali_mixer_free_ac97;
-
- for ( i = 0 ; i < codec->num_of_codecs ; i++) {
- ac97.num = i;
- if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i])) < 0) {
- snd_printk("ali mixer %d creating error.\n", i);
- if(i == 0)
+ if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97)) < 0) {
+ snd_printk("ali mixer creating error.\n");
return err;
}
- }
-
if (codec->spdif_support) {
for(idx = 0; idx < ARRAY_SIZE(snd_ali5451_mixer_spdif); idx++) {
err=snd_ctl_add(codec->card, snd_ctl_new1(&snd_ali5451_mixer_spdif[idx], codec));
@@ -2025,12 +1904,8 @@ static int ali_suspend(snd_card_t *card, pm_message_t state)
if (! im)
return 0;
- for(i = 0 ; i < chip->num_of_codecs ; i++) {
- if (chip->pcm[i])
- snd_pcm_suspend_all(chip->pcm[i]);
- if(chip->ac97[i])
- snd_ac97_suspend(chip->ac97[i]);
- }
+ snd_pcm_suspend_all(chip->pcm);
+ snd_ac97_suspend(chip->ac97);
spin_lock_irq(&chip->reg_lock);
@@ -2094,9 +1969,7 @@ static int ali_resume(snd_card_t *card)
spin_unlock_irq(&chip->reg_lock);
- for(i = 0 ; i < chip->num_of_codecs ; i++)
- if(chip->ac97[i])
- snd_ac97_resume(chip->ac97[i]);
+ snd_ac97_resume(chip->ac97);
return 0;
}
@@ -2163,37 +2036,11 @@ static int snd_ali_chip_init(ali_t *codec)
codec->spdif_mask = 0x00000002;
}
- codec->num_of_codecs = 1;
-
- /* secondary codec - modem */
- if (inl(ALI_REG(codec, ALI_SCTRL)) & ALI_SCTRL_CODEC2_READY) {
- codec->num_of_codecs++;
- outl(inl(ALI_REG(codec, ALI_SCTRL)) |
- (ALI_SCTRL_LINE_IN2|ALI_SCTRL_GPIO_IN2|ALI_SCTRL_LINE_OUT_EN),
- ALI_REG(codec, ALI_SCTRL));
- }
-
snd_ali_printk("chip initialize succeed.\n");
return 0;
}
-/* proc for register dump */
-static void snd_ali_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buf)
-{
- ali_t *codec = entry->private_data;
- int i;
- for(i = 0 ; i < 256 ; i+= 4)
- snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i)));
-}
-
-static void __devinit snd_ali_proc_init(ali_t *codec)
-{
- snd_info_entry_t *entry;
- if(!snd_card_proc_new(codec->card, "ali5451", &entry))
- snd_info_set_text_ops(entry, codec, 1024, snd_ali_proc_read);
-}
-
static int __devinit snd_ali_resources(ali_t *codec)
{
int err;
@@ -2386,13 +2233,11 @@ static int __devinit snd_ali_probe(struct pci_dev *pci,
}
snd_ali_printk("pcm building ...\n");
- if ((err = snd_ali_build_pcms(codec)) < 0) {
+ if ((err = snd_ali_pcm(codec, 0, NULL)) < 0) {
snd_card_free(card);
return err;
}
- snd_ali_proc_init(codec);
-
strcpy(card->driver, "ALI5451");
strcpy(card->shortname, "ALI 5451");
@@ -2425,7 +2270,7 @@ static struct pci_driver driver = {
static int __init alsa_card_ali_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_ali_exit(void)
diff --git a/trunk/sound/pci/als4000.c b/trunk/sound/pci/als4000.c
index ca28b229c704..f1a5f5723ee6 100644
--- a/trunk/sound/pci/als4000.c
+++ b/trunk/sound/pci/als4000.c
@@ -367,7 +367,7 @@ static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id, struct pt_regs *
if ((gcr_status & 0x40) && (chip->capture_substream)) /* capturing */
snd_pcm_period_elapsed(chip->capture_substream);
if ((gcr_status & 0x10) && (chip->rmidi)) /* MPU401 interrupt */
- snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
+ snd_mpu401_uart_interrupt(irq, chip->rmidi, regs);
/* release the gcr */
outb(gcr_status, chip->alt_port + 0xe);
@@ -777,7 +777,7 @@ static struct pci_driver driver = {
static int __init alsa_card_als4000_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_als4000_exit(void)
diff --git a/trunk/sound/pci/atiixp.c b/trunk/sound/pci/atiixp.c
index cafab4af5c57..6b04c0acc6f7 100644
--- a/trunk/sound/pci/atiixp.c
+++ b/trunk/sound/pci/atiixp.c
@@ -1334,8 +1334,8 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *r
static struct ac97_quirk ac97_quirks[] __devinitdata = {
{
- .subvendor = 0x103c,
- .subdevice = 0x006b,
+ .vendor = 0x103c,
+ .device = 0x006b,
.name = "HP Pavilion ZV5030US",
.type = AC97_TUNE_MUTE_LED
},
@@ -1645,7 +1645,7 @@ static struct pci_driver driver = {
static int __init alsa_card_atiixp_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_atiixp_exit(void)
diff --git a/trunk/sound/pci/atiixp_modem.c b/trunk/sound/pci/atiixp_modem.c
index a6b4b8d589fd..fb7cecea846d 100644
--- a/trunk/sound/pci/atiixp_modem.c
+++ b/trunk/sound/pci/atiixp_modem.c
@@ -463,11 +463,6 @@ static unsigned short snd_atiixp_ac97_read(ac97_t *ac97, unsigned short reg)
static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
{
atiixp_t *chip = ac97->private_data;
- if (reg == AC97_GPIO_STATUS) {
- atiixp_write(chip, MODEM_OUT_GPIO,
- (val << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN);
- return;
- }
snd_atiixp_codec_write(chip, ac97->num, reg, val);
}
@@ -668,33 +663,44 @@ static int snd_atiixp_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
{
atiixp_t *chip = snd_pcm_substream_chip(substream);
atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
- int err = 0;
+ unsigned int reg = 0;
+ int i;
snd_assert(dma->ops->enable_transfer && dma->ops->flush_dma, return -EINVAL);
+ if (cmd != SNDRV_PCM_TRIGGER_START && cmd != SNDRV_PCM_TRIGGER_STOP)
+ return -EINVAL;
+
spin_lock(&chip->reg_lock);
- switch(cmd) {
- case SNDRV_PCM_TRIGGER_START:
+
+ /* hook off/on: via GPIO_OUT */
+ for (i = 0; i < NUM_ATI_CODECS; i++) {
+ if (chip->ac97[i]) {
+ reg = snd_ac97_read(chip->ac97[i], AC97_GPIO_STATUS);
+ break;
+ }
+ }
+ if(cmd == SNDRV_PCM_TRIGGER_START)
+ reg |= AC97_GPIO_LINE1_OH;
+ else
+ reg &= ~AC97_GPIO_LINE1_OH;
+ reg = (reg << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN ;
+ atiixp_write(chip, MODEM_OUT_GPIO, reg);
+
+ if (cmd == SNDRV_PCM_TRIGGER_START) {
dma->ops->enable_transfer(chip, 1);
dma->running = 1;
- break;
- case SNDRV_PCM_TRIGGER_STOP:
+ } else {
dma->ops->enable_transfer(chip, 0);
dma->running = 0;
- break;
- default:
- err = -EINVAL;
- break;
}
- if (! err) {
snd_atiixp_check_bus_busy(chip);
if (cmd == SNDRV_PCM_TRIGGER_STOP) {
dma->ops->flush_dma(chip);
snd_atiixp_check_bus_busy(chip);
}
- }
spin_unlock(&chip->reg_lock);
- return err;
+ return 0;
}
@@ -1326,7 +1332,7 @@ static struct pci_driver driver = {
static int __init alsa_card_atiixp_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_atiixp_exit(void)
diff --git a/trunk/sound/pci/au88x0/au88x0.c b/trunk/sound/pci/au88x0/au88x0.c
index f6236c63aaaa..889b4a1a51a1 100644
--- a/trunk/sound/pci/au88x0/au88x0.c
+++ b/trunk/sound/pci/au88x0/au88x0.c
@@ -375,7 +375,7 @@ static struct pci_driver driver = {
// initialization of the module
static int __init alsa_card_vortex_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
// clean up the module
diff --git a/trunk/sound/pci/azt3328.c b/trunk/sound/pci/azt3328.c
index 72bba7b2d983..b8ae534125c1 100644
--- a/trunk/sound/pci/azt3328.c
+++ b/trunk/sound/pci/azt3328.c
@@ -1520,7 +1520,7 @@ static int __init alsa_card_azf3328_init(void)
{
int err;
snd_azf3328_dbgcallenter();
- err = pci_register_driver(&driver);
+ err = pci_module_init(&driver);
snd_azf3328_dbgcallleave();
return err;
}
diff --git a/trunk/sound/pci/bt87x.c b/trunk/sound/pci/bt87x.c
index defdc5a459f0..89a7ffe5e7d7 100644
--- a/trunk/sound/pci/bt87x.c
+++ b/trunk/sound/pci/bt87x.c
@@ -918,7 +918,7 @@ static int __init alsa_card_bt87x_init(void)
{
if (load_all)
driver.id_table = snd_bt87x_default_ids;
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_bt87x_exit(void)
diff --git a/trunk/sound/pci/ca0106/ca0106.h b/trunk/sound/pci/ca0106/ca0106.h
index da09cab405a9..deb028851056 100644
--- a/trunk/sound/pci/ca0106/ca0106.h
+++ b/trunk/sound/pci/ca0106/ca0106.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2004 James Courtier-Dutton
* Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- * Version: 0.0.21
+ * Version: 0.0.20
*
* FEATURES currently supported:
* See ca0106_main.c for features.
@@ -45,8 +45,6 @@
* Added I2C and SPI registers. Filled in interrupt enable.
* 0.0.20
* Added GPIO info for SB Live 24bit.
- * 0.0.21
- * Implement support for Line-in capture on SB Live 24bit.
*
*
* This code was initally based on code from ALSA's emu10k1x.c which is:
@@ -154,7 +152,7 @@
* bit 9 0 = Mute / 1 = Analog out.
* bit 10 0 = Line-in / 1 = Mic-in.
* bit 11 0 = ? / 1 = ?
- * bit 12 0 = 48 Khz / 1 = 96 Khz Analog out on SB Live 24bit.
+ * bit 12 0 = ? / 1 = ?
* bit 13 0 = ? / 1 = ?
* bit 14 0 = Mute / 1 = Analog out
* bit 15 0 = ? / 1 = ?
@@ -477,56 +475,9 @@
/* Causes interrupts based on timer intervals. */
#define SPI 0x7a /* SPI: Serial Interface Register */
#define I2C_A 0x7b /* I2C Address. 32 bit */
-#define I2C_D0 0x7c /* I2C Data Port 0. 32 bit */
-#define I2C_D1 0x7d /* I2C Data Port 1. 32 bit */
-//I2C values
-#define I2C_A_ADC_ADD_MASK 0x000000fe //The address is a 7 bit address
-#define I2C_A_ADC_RW_MASK 0x00000001 //bit mask for R/W
-#define I2C_A_ADC_TRANS_MASK 0x00000010 //Bit mask for I2c address DAC value
-#define I2C_A_ADC_ABORT_MASK 0x00000020 //Bit mask for I2C transaction abort flag
-#define I2C_A_ADC_LAST_MASK 0x00000040 //Bit mask for Last word transaction
-#define I2C_A_ADC_BYTE_MASK 0x00000080 //Bit mask for Byte Mode
+#define I2C_0 0x7c /* I2C Data Port 0. 32 bit */
+#define I2C_1 0x7d /* I2C Data Port 1. 32 bit */
-#define I2C_A_ADC_ADD 0x00000034 //This is the Device address for ADC
-#define I2C_A_ADC_READ 0x00000001 //To perform a read operation
-#define I2C_A_ADC_START 0x00000100 //Start I2C transaction
-#define I2C_A_ADC_ABORT 0x00000200 //I2C transaction abort
-#define I2C_A_ADC_LAST 0x00000400 //I2C last transaction
-#define I2C_A_ADC_BYTE 0x00000800 //I2C one byte mode
-
-#define I2C_D_ADC_REG_MASK 0xfe000000 //ADC address register
-#define I2C_D_ADC_DAT_MASK 0x01ff0000 //ADC data register
-
-#define ADC_TIMEOUT 0x00000007 //ADC Timeout Clock Disable
-#define ADC_IFC_CTRL 0x0000000b //ADC Interface Control
-#define ADC_MASTER 0x0000000c //ADC Master Mode Control
-#define ADC_POWER 0x0000000d //ADC PowerDown Control
-#define ADC_ATTEN_ADCL 0x0000000e //ADC Attenuation ADCL
-#define ADC_ATTEN_ADCR 0x0000000f //ADC Attenuation ADCR
-#define ADC_ALC_CTRL1 0x00000010 //ADC ALC Control 1
-#define ADC_ALC_CTRL2 0x00000011 //ADC ALC Control 2
-#define ADC_ALC_CTRL3 0x00000012 //ADC ALC Control 3
-#define ADC_NOISE_CTRL 0x00000013 //ADC Noise Gate Control
-#define ADC_LIMIT_CTRL 0x00000014 //ADC Limiter Control
-#define ADC_MUX 0x00000015 //ADC Mux offset
-
-#if 0
-/* FIXME: Not tested yet. */
-#define ADC_GAIN_MASK 0x000000ff //Mask for ADC Gain
-#define ADC_ZERODB 0x000000cf //Value to set ADC to 0dB
-#define ADC_MUTE_MASK 0x000000c0 //Mask for ADC mute
-#define ADC_MUTE 0x000000c0 //Value to mute ADC
-#define ADC_OSR 0x00000008 //Mask for ADC oversample rate select
-#define ADC_TIMEOUT_DISABLE 0x00000008 //Value and mask to disable Timeout clock
-#define ADC_HPF_DISABLE 0x00000100 //Value and mask to disable High pass filter
-#define ADC_TRANWIN_MASK 0x00000070 //Mask for Length of Transient Window
-#endif
-
-#define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux
-#define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux
-#define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux
-#define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used)
-#define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux
#define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */
#define PCM_FRONT_CHANNEL 0
@@ -557,18 +508,9 @@ struct snd_ca0106_pcm {
unsigned short running;
};
-typedef struct {
- u32 serial;
- char * name;
- int ac97;
- int gpio_type;
- int i2c_adc;
-} ca0106_details_t;
-
// definition of the chip-specific record
struct snd_ca0106 {
snd_card_t *card;
- ca0106_details_t *details;
struct pci_dev *pci;
unsigned long port;
@@ -589,7 +531,6 @@ struct snd_ca0106 {
u32 spdif_bits[4]; /* s/pdif out setup */
int spdif_enable;
int capture_source;
- int capture_mic_line_in;
struct snd_dma_buffer buffer;
};
@@ -606,6 +547,3 @@ void snd_ca0106_ptr_write(ca0106_t *emu,
unsigned int chn,
unsigned int data);
-int snd_ca0106_i2c_write(ca0106_t *emu, u32 reg, u32 value);
-
-
diff --git a/trunk/sound/pci/ca0106/ca0106_main.c b/trunk/sound/pci/ca0106/ca0106_main.c
index 95c289284267..82533b45bc8c 100644
--- a/trunk/sound/pci/ca0106/ca0106_main.c
+++ b/trunk/sound/pci/ca0106/ca0106_main.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2004 James Courtier-Dutton
* Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- * Version: 0.0.23
+ * Version: 0.0.22
*
* FEATURES currently supported:
* Front, Rear and Center/LFE.
@@ -77,8 +77,6 @@
* Add SPDIF capture using optional digital I/O module for SB Live 24bit. (Analog capture does not yet work.)
* 0.0.22
* Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901
- * 0.0.23
- * Implement support for Line-in capture on SB Live 24bit.
*
* BUGS:
* Some stability problems when unloading the snd-ca0106 kernel module.
@@ -138,7 +136,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -164,32 +161,18 @@ MODULE_PARM_DESC(enable, "Enable the CA0106 soundcard.");
#include "ca0106.h"
-static ca0106_details_t ca0106_chip_details[] = {
- /* AudigyLS[SB0310] */
- { .serial = 0x10021102,
- .name = "AudigyLS [SB0310]",
- .ac97 = 1 } ,
- /* Unknown AudigyLS that also says SB0310 on it */
- { .serial = 0x10051102,
- .name = "AudigyLS [SB0310b]",
- .ac97 = 1 } ,
- /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
- { .serial = 0x10061102,
- .name = "Live! 7.1 24bit [SB0410]",
- .gpio_type = 1,
- .i2c_adc = 1 } ,
- /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */
- { .serial = 0x10071102,
- .name = "Live! 7.1 24bit [SB0413]",
- .gpio_type = 1,
- .i2c_adc = 1 } ,
- /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
- { .serial = 0x10091462,
- .name = "MSI K8N Diamond MB [SB0438]",
- .gpio_type = 1,
- .i2c_adc = 1 } ,
- { .serial = 0,
- .name = "AudigyLS [Unknown]" }
+typedef struct {
+ u32 serial;
+ char * name;
+} ca0106_names_t;
+
+static ca0106_names_t ca0106_chip_names[] = {
+ { 0x10021102, "AudigyLS [SB0310]"} ,
+ { 0x10051102, "AudigyLS [SB0310b]"} , /* Unknown AudigyLS that also says SB0310 on it */
+ { 0x10061102, "Live! 7.1 24bit [SB0410]"} , /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
+ { 0x10071102, "Live! 7.1 24bit [SB0413]"} , /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */
+ { 0x10091462, "MSI K8N Diamond MB [SB0438]"}, /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
+ { 0, "AudigyLS [Unknown]" }
};
/* hardware definition */
@@ -217,10 +200,10 @@ static snd_pcm_hardware_t snd_ca0106_capture_hw = {
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID),
- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
- .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
- .rate_min = 44100,
- .rate_max = 192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
.buffer_bytes_max = ((65536 - 64) * 8),
@@ -263,62 +246,6 @@ void snd_ca0106_ptr_write(ca0106_t *emu,
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-int snd_ca0106_i2c_write(ca0106_t *emu,
- u32 reg,
- u32 value)
-{
- u32 tmp;
- int timeout=0;
- int status;
- int retry;
- if ((reg > 0x7f) || (value > 0x1ff))
- {
- snd_printk("i2c_write: invalid values.\n");
- return -EINVAL;
- }
-
- tmp = reg << 25 | value << 16;
- /* Not sure what this I2C channel controls. */
- /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
-
- /* This controls the I2C connected to the WM8775 ADC Codec */
- snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);
-
- for(retry=0;retry<10;retry++)
- {
- /* Send the data to i2c */
- tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
- tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
- tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
- snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
-
- /* Wait till the transaction ends */
- while(1)
- {
- status = snd_ca0106_ptr_read(emu, I2C_A, 0);
- //snd_printk("I2C:status=0x%x\n", status);
- timeout++;
- if((status & I2C_A_ADC_START)==0)
- break;
-
- if(timeout>1000)
- break;
- }
- //Read back and see if the transaction is successful
- if((status & I2C_A_ADC_ABORT)==0)
- break;
- }
-
- if(retry==10)
- {
- snd_printk("Writing to ADC failed!\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-
static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb)
{
unsigned long flags;
@@ -332,7 +259,11 @@ static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb)
static void snd_ca0106_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
- kfree(runtime->private_data);
+ ca0106_pcm_t *epcm = runtime->private_data;
+
+ if (epcm) {
+ kfree(epcm);
+ }
}
/* open_playback callback */
@@ -607,61 +538,6 @@ static int snd_ca0106_pcm_prepare_capture(snd_pcm_substream_t *substream)
snd_pcm_runtime_t *runtime = substream->runtime;
ca0106_pcm_t *epcm = runtime->private_data;
int channel = epcm->channel_id;
- u32 hcfg_mask = HCFG_CAPTURE_S32_LE;
- u32 hcfg_set = 0x00000000;
- u32 hcfg;
- u32 over_sampling=0x2;
- u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */
- u32 reg71_set = 0;
- u32 reg71;
-
- //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1));
- //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
- //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
- /* reg71 controls ADC rate. */
- switch (runtime->rate) {
- case 44100:
- reg71_set = 0x00004000;
- break;
- case 48000:
- reg71_set = 0;
- break;
- case 96000:
- reg71_set = 0x00008000;
- over_sampling=0xa;
- break;
- case 192000:
- reg71_set = 0x0000c000;
- over_sampling=0xa;
- break;
- default:
- reg71_set = 0;
- break;
- }
- /* Format is a global setting */
- /* FIXME: Only let the first channel accessed set this. */
- switch (runtime->format) {
- case SNDRV_PCM_FORMAT_S16_LE:
- hcfg_set = 0;
- break;
- case SNDRV_PCM_FORMAT_S32_LE:
- hcfg_set = HCFG_CAPTURE_S32_LE;
- break;
- default:
- hcfg_set = 0;
- break;
- }
- hcfg = inl(emu->port + HCFG) ;
- hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
- outl(hcfg, emu->port + HCFG);
- reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
- reg71 = (reg71 & ~reg71_mask) | reg71_set;
- snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
- if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
- snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */
- }
-
-
//printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1));
snd_ca0106_ptr_write(emu, 0x13, channel, 0);
snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
@@ -934,7 +810,6 @@ static int snd_ca0106_ac97(ca0106_t *chip)
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = chip;
- ac97.scaps = AC97_SCAP_NO_SPDIF;
return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
}
@@ -1118,7 +993,6 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
ca0106_t **rchip)
{
ca0106_t *chip;
- ca0106_details_t *c;
int err;
int ch;
static snd_device_ops_t ops = {
@@ -1129,8 +1003,8 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
- pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
+ if (pci_set_dma_mask(pci, 0xffffffffUL) < 0 ||
+ pci_set_consistent_dma_mask(pci, 0xffffffffUL) < 0) {
printk(KERN_ERR "error to set 32bit mask DMA\n");
pci_disable_device(pci);
return -ENXIO;
@@ -1180,15 +1054,6 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model,
chip->revision, chip->serial);
#endif
- strcpy(card->driver, "CA0106");
- strcpy(card->shortname, "CA0106");
-
- for (c=ca0106_chip_details; c->serial; c++) {
- if (c->serial == chip->serial) break;
- }
- chip->details = c;
- sprintf(card->longname, "%s at 0x%lx irq %i",
- c->name, chip->port, chip->irq);
outl(0, chip->port + INTE);
@@ -1248,7 +1113,7 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
//snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
/* Analog or Digital output */
snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
- snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */
+ snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000b0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers */
chip->spdif_enable = 0; /* Set digital SPDIF output off */
chip->capture_source = 3; /* Set CAPTURE_SOURCE */
//snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
@@ -1273,11 +1138,13 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */
chip->capture_source = 3; /* Set CAPTURE_SOURCE */
- if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
+ if ((chip->serial == 0x10061102) ||
+ (chip->serial == 0x10071102) ||
+ (chip->serial == 0x10091462)) { /* The SB0410 and SB0413 use GPIO differently. */
/* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
outl(0x0, chip->port+GPIO);
//outl(0x00f0e000, chip->port+GPIO); /* Analog */
- outl(0x005f5301, chip->port+GPIO); /* Analog */
+ outl(0x005f4300, chip->port+GPIO); /* Analog */
} else {
outl(0x0, chip->port+GPIO);
outl(0x005f03a3, chip->port+GPIO); /* Analog */
@@ -1290,10 +1157,6 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
//outl(0x00000009, chip->port+HCFG);
outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
- if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
- snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */
- }
-
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
chip, &ops)) < 0) {
snd_ca0106_free(chip);
@@ -1309,6 +1172,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
static int dev;
snd_card_t *card;
ca0106_t *chip;
+ ca0106_names_t *c;
int err;
if (dev >= SNDRV_CARDS)
@@ -1343,7 +1207,9 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
- if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */
+ if ((chip->serial != 0x10061102) &&
+ (chip->serial != 0x10071102) &&
+ (chip->serial != 0x10091462) ) { /* The SB0410 and SB0413 do not have an ac97 chip. */
if ((err = snd_ca0106_ac97(chip)) < 0) {
snd_card_free(card);
return err;
@@ -1356,6 +1222,15 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
snd_ca0106_proc_init(chip);
+ strcpy(card->driver, "CA0106");
+ strcpy(card->shortname, "CA0106");
+
+ for (c=ca0106_chip_names; c->serial; c++) {
+ if (c->serial == chip->serial) break;
+ }
+ sprintf(card->longname, "%s at 0x%lx irq %i",
+ c->name, chip->port, chip->irq);
+
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
return err;
@@ -1392,7 +1267,7 @@ static int __init alsa_card_ca0106_init(void)
{
int err;
- if ((err = pci_register_driver(&driver)) > 0)
+ if ((err = pci_module_init(&driver)) > 0)
return err;
return 0;
diff --git a/trunk/sound/pci/ca0106/ca0106_mixer.c b/trunk/sound/pci/ca0106/ca0106_mixer.c
index 0e5e9ce0ff28..97bed1b0899d 100644
--- a/trunk/sound/pci/ca0106/ca0106_mixer.c
+++ b/trunk/sound/pci/ca0106/ca0106_mixer.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2004 James Courtier-Dutton
* Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- * Version: 0.0.17
+ * Version: 0.0.16
*
* FEATURES currently supported:
* See ca0106_main.c for features.
@@ -37,8 +37,6 @@
* Separated ca0106.c into separate functional .c files.
* 0.0.16
* Modified Copyright message.
- * 0.0.17
- * Implement Mic and Line in Capture.
*
* This code was initally based on code from ALSA's emu10k1x.c which is:
* Copyright (c) by Francisco Moraes
@@ -115,7 +113,7 @@ static int snd_ca0106_shared_spdif_put(snd_kcontrol_t * kcontrol,
} else {
/* Analog */
snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
- snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
+ snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000b0000);
snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000);
mask = inl(emu->port + GPIO) | 0x101;
@@ -185,65 +183,6 @@ static snd_kcontrol_new_t snd_ca0106_capture_source __devinitdata =
.put = snd_ca0106_capture_source_put
};
-static int snd_ca0106_capture_mic_line_in_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[2] = { "Line in", "Mic in" };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 2;
- if (uinfo->value.enumerated.item > 1)
- uinfo->value.enumerated.item = 1;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_ca0106_capture_mic_line_in_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- ca0106_t *emu = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
- return 0;
-}
-
-static int snd_ca0106_capture_mic_line_in_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- ca0106_t *emu = snd_kcontrol_chip(kcontrol);
- unsigned int val;
- int change = 0;
- u32 tmp;
-
- val = ucontrol->value.enumerated.item[0] ;
- change = (emu->capture_mic_line_in != val);
- if (change) {
- emu->capture_mic_line_in = val;
- if (val) {
- snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */
- tmp = inl(emu->port+GPIO) & ~0x400;
- tmp = tmp | 0x400;
- outl(tmp, emu->port+GPIO);
- snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
- } else {
- snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */
- tmp = inl(emu->port+GPIO) & ~0x400;
- outl(tmp, emu->port+GPIO);
- snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
- }
- }
- return change;
-}
-
-static snd_kcontrol_new_t snd_ca0106_capture_mic_line_in __devinitdata =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Mic/Line in Capture",
- .info = snd_ca0106_capture_mic_line_in_info,
- .get = snd_ca0106_capture_mic_line_in_get,
- .put = snd_ca0106_capture_mic_line_in_put
-};
-
static int snd_ca0106_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
@@ -498,7 +437,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_analog_center_lfe =
static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog Side Volume",
+ .name = "Analog Unknown Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_analog_unknown,
.put = snd_ca0106_volume_put_analog_unknown
@@ -681,11 +620,10 @@ int __devinit snd_ca0106_mixer(ca0106_t *emu)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
return err;
- if (emu->details->i2c_adc == 1) {
- if ((kctl = snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
+ if ((kctl = ctl_find(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT))) != NULL) {
+ /* already defined by ac97, remove it */
+ /* FIXME: or do we need both controls? */
+ remove_ctl(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT));
}
if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_control, emu)) == NULL)
return -ENOMEM;
diff --git a/trunk/sound/pci/ca0106/ca0106_proc.c b/trunk/sound/pci/ca0106/ca0106_proc.c
index 1c9cc821d1b9..afb711421e47 100644
--- a/trunk/sound/pci/ca0106/ca0106_proc.c
+++ b/trunk/sound/pci/ca0106/ca0106_proc.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2004 James Courtier-Dutton
* Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- * Version: 0.0.18
+ * Version: 0.0.17
*
* FEATURES currently supported:
* See ca0106_main.c for features.
@@ -39,9 +39,7 @@
* Modified Copyright message.
* 0.0.17
* Add iec958 file in proc file system to show status of SPDIF in.
- * 0.0.18
- * Implement support for Line-in capture on SB Live 24bit.
- *
+ *
* This code was initally based on code from ALSA's emu10k1x.c which is:
* Copyright (c) by Francisco Moraes
*
@@ -97,7 +95,7 @@ static struct snd_ca0106_category_str snd_ca0106_con_category[] = {
};
-static void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value)
+void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value)
{
int i;
u32 status[4];
@@ -409,20 +407,6 @@ static void snd_ca0106_proc_reg_write(snd_info_entry_t *entry,
}
}
-static void snd_ca0106_proc_i2c_write(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
-{
- ca0106_t *emu = entry->private_data;
- char line[64];
- unsigned int reg, val;
- while (!snd_info_get_line(buffer, line, sizeof(line))) {
- if (sscanf(line, "%x %x", ®, &val) != 2)
- continue;
- if ((reg <= 0x7f) || (val <= 0x1ff)) {
- snd_ca0106_i2c_write(emu, reg, val);
- }
- }
-}
int __devinit snd_ca0106_proc_init(ca0106_t * emu)
{
@@ -434,7 +418,6 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu)
snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read32);
entry->c.text.write_size = 64;
entry->c.text.write = snd_ca0106_proc_reg_write32;
- entry->mode |= S_IWUSR;
}
if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry))
snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read16);
@@ -444,14 +427,6 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu)
snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read1);
entry->c.text.write_size = 64;
entry->c.text.write = snd_ca0106_proc_reg_write;
- entry->mode |= S_IWUSR;
-// entry->private_data = emu;
- }
- if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) {
- snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_i2c_write);
- entry->c.text.write_size = 64;
- entry->c.text.write = snd_ca0106_proc_i2c_write;
- entry->mode |= S_IWUSR;
// entry->private_data = emu;
}
if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry))
diff --git a/trunk/sound/pci/cmipci.c b/trunk/sound/pci/cmipci.c
index b4503385ea69..113208fbde1b 100644
--- a/trunk/sound/pci/cmipci.c
+++ b/trunk/sound/pci/cmipci.c
@@ -519,50 +519,40 @@ inline static unsigned char snd_cmipci_read_b(cmipci_t *cm, unsigned int cmd)
}
/* bit operations for dword register */
-static int snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
+static void snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
{
- unsigned int val, oval;
- val = oval = inl(cm->iobase + cmd);
+ unsigned int val;
+ val = inl(cm->iobase + cmd);
val |= flag;
- if (val == oval)
- return 0;
outl(val, cm->iobase + cmd);
- return 1;
}
-static int snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
+static void snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
{
- unsigned int val, oval;
- val = oval = inl(cm->iobase + cmd);
+ unsigned int val;
+ val = inl(cm->iobase + cmd);
val &= ~flag;
- if (val == oval)
- return 0;
outl(val, cm->iobase + cmd);
- return 1;
}
+#if 0 // not used
/* bit operations for byte register */
-static int snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
+static void snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
{
- unsigned char val, oval;
- val = oval = inb(cm->iobase + cmd);
+ unsigned char val;
+ val = inb(cm->iobase + cmd);
val |= flag;
- if (val == oval)
- return 0;
outb(val, cm->iobase + cmd);
- return 1;
}
-static int snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
+static void snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
{
- unsigned char val, oval;
- val = oval = inb(cm->iobase + cmd);
+ unsigned char val;
+ val = inb(cm->iobase + cmd);
val &= ~flag;
- if (val == oval)
- return 0;
outb(val, cm->iobase + cmd);
- return 1;
}
+#endif
/*
@@ -2260,8 +2250,8 @@ DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, 0, 0, 0); /* rever
DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0);
#endif
DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0);
-// DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0);
-// DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0);
+DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0);
+DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0);
// DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */
DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0);
@@ -2310,114 +2300,10 @@ static int snd_cmipci_spdout_enable_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_v
}
-static int snd_cmipci_line_in_mode_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
-{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
- static char *texts[3] = { "Line-In", "Rear Output", "Bass Output" };
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = cm->chip_version >= 39 ? 3 : 2;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static inline unsigned int get_line_in_mode(cmipci_t *cm)
-{
- unsigned int val;
- if (cm->chip_version >= 39) {
- val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL);
- if (val & CM_LINE_AS_BASS)
- return 2;
- }
- val = snd_cmipci_read_b(cm, CM_REG_MIXER1);
- if (val & CM_SPK4)
- return 1;
- return 0;
-}
-
-static int snd_cmipci_line_in_mode_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
-{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
-
- spin_lock_irq(&cm->reg_lock);
- ucontrol->value.enumerated.item[0] = get_line_in_mode(cm);
- spin_unlock_irq(&cm->reg_lock);
- return 0;
-}
-
-static int snd_cmipci_line_in_mode_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
-{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
- int change;
-
- spin_lock_irq(&cm->reg_lock);
- if (ucontrol->value.enumerated.item[0] == 2)
- change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS);
- else
- change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS);
- if (ucontrol->value.enumerated.item[0] == 1)
- change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_SPK4);
- else
- change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_SPK4);
- spin_unlock_irq(&cm->reg_lock);
- return change;
-}
-
-static int snd_cmipci_mic_in_mode_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
-{
- static char *texts[2] = { "Mic-In", "Center/LFE Output" };
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 2;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_cmipci_mic_in_mode_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
-{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
- /* same bit as spdi_phase */
- spin_lock_irq(&cm->reg_lock);
- ucontrol->value.enumerated.item[0] =
- (snd_cmipci_read_b(cm, CM_REG_MISC) & CM_SPDIF_INVERSE) ? 1 : 0;
- spin_unlock_irq(&cm->reg_lock);
- return 0;
-}
-
-static int snd_cmipci_mic_in_mode_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
-{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
- int change;
-
- spin_lock_irq(&cm->reg_lock);
- if (ucontrol->value.enumerated.item[0])
- change = snd_cmipci_set_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE);
- else
- change = snd_cmipci_clear_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE);
- spin_unlock_irq(&cm->reg_lock);
- return change;
-}
-
/* both for CM8338/8738 */
static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = {
DEFINE_MIXER_SWITCH("Four Channel Mode", fourch),
- {
- .name = "Line-In Mode",
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .info = snd_cmipci_line_in_mode_info,
- .get = snd_cmipci_line_in_mode_get,
- .put = snd_cmipci_line_in_mode_put,
- },
+ DEFINE_MIXER_SWITCH("Line-In As Rear", line_rear),
};
/* for non-multichannel chips */
@@ -2455,15 +2341,10 @@ static snd_kcontrol_new_t snd_cmipci_old_mixer_switches[] __devinitdata = {
/* only for model 039 or later */
static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = {
+ DEFINE_MIXER_SWITCH("Line-In As Bass", line_bass),
DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2),
DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2),
- {
- .name = "Mic-In Mode",
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .info = snd_cmipci_mic_in_mode_info,
- .get = snd_cmipci_mic_in_mode_get,
- .put = snd_cmipci_mic_in_mode_put,
- }
+ DEFINE_MIXER_SWITCH("Mic As Center/LFE", spdi_phase), /* same bit as spdi_phase */
};
/* card control switches */
@@ -3063,7 +2944,7 @@ static struct pci_driver driver = {
static int __init alsa_card_cmipci_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_cmipci_exit(void)
diff --git a/trunk/sound/pci/cs4281.c b/trunk/sound/pci/cs4281.c
index b6e1854e9389..d7e06b3caf97 100644
--- a/trunk/sound/pci/cs4281.c
+++ b/trunk/sound/pci/cs4281.c
@@ -206,10 +206,7 @@ MODULE_PARM_DESC(dual_codec, "Secondary Codec ID (0 = disabled).");
#define BA0_PMCS 0x0344 /* Power Management Control/Status */
#define BA0_CWPR 0x03e0 /* Configuration Write Protect */
-
#define BA0_EPPMC 0x03e4 /* Extended PCI Power Management Control */
-#define BA0_EPPMC_FPDN (1<<14) /* Full Power DowN */
-
#define BA0_GPIOR 0x03e8 /* GPIO Pin Interface Register */
#define BA0_SPMC 0x03ec /* Serial Port Power Management Control (& ASDIN2 enable) */
@@ -1464,11 +1461,6 @@ static int snd_cs4281_chip_init(cs4281_t *chip)
int timeout;
int retry_count = 2;
- /* Having EPPMC.FPDN=1 prevent proper chip initialisation */
- tmp = snd_cs4281_peekBA0(chip, BA0_EPPMC);
- if (tmp & BA0_EPPMC_FPDN)
- snd_cs4281_pokeBA0(chip, BA0_EPPMC, tmp & ~BA0_EPPMC_FPDN);
-
__retry:
tmp = snd_cs4281_peekBA0(chip, BA0_CFLR);
if (tmp != BA0_CFLR_DEFAULT) {
@@ -2132,7 +2124,7 @@ static struct pci_driver driver = {
static int __init alsa_card_cs4281_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_cs4281_exit(void)
diff --git a/trunk/sound/pci/cs46xx/cs46xx.c b/trunk/sound/pci/cs46xx/cs46xx.c
index db212ecd792a..25d6466a867c 100644
--- a/trunk/sound/pci/cs46xx/cs46xx.c
+++ b/trunk/sound/pci/cs46xx/cs46xx.c
@@ -171,7 +171,7 @@ static struct pci_driver driver = {
static int __init alsa_card_cs46xx_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_cs46xx_exit(void)
diff --git a/trunk/sound/pci/cs46xx/cs46xx_lib.c b/trunk/sound/pci/cs46xx/cs46xx_lib.c
index fd4c50c88bc9..5f2ffb7efa06 100644
--- a/trunk/sound/pci/cs46xx/cs46xx_lib.c
+++ b/trunk/sound/pci/cs46xx/cs46xx_lib.c
@@ -1295,7 +1295,8 @@ static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
- kfree(runtime->private_data);
+ cs46xx_pcm_t * cpcm = runtime->private_data;
+ kfree(cpcm);
}
static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id)
diff --git a/trunk/sound/pci/emu10k1/emu10k1.c b/trunk/sound/pci/emu10k1/emu10k1.c
index 2085a998eaeb..6446afe19d80 100644
--- a/trunk/sound/pci/emu10k1/emu10k1.c
+++ b/trunk/sound/pci/emu10k1/emu10k1.c
@@ -228,7 +228,7 @@ static struct pci_driver driver = {
static int __init alsa_card_emu10k1_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_emu10k1_exit(void)
diff --git a/trunk/sound/pci/emu10k1/emu10k1_main.c b/trunk/sound/pci/emu10k1/emu10k1_main.c
index a341e758acde..c3c96f9f2c7f 100644
--- a/trunk/sound/pci/emu10k1/emu10k1_main.c
+++ b/trunk/sound/pci/emu10k1/emu10k1_main.c
@@ -170,7 +170,7 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
SPCS_GENERATIONSTATUS | 0x00001200 |
0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
- if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
+ if (emu->audigy && emu->revision == 4) { /* audigy2 */
/* Hacks for Alice3 to work independent of haP16V driver */
u32 tmp;
@@ -189,7 +189,7 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
/* Enabled Phased (8-channel) P16V playback */
outl(0x0201, emu->port + HCFG2);
/* Set playback routing. */
- snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4);
+ snd_emu10k1_ptr_write(emu, CAPTURE_P16V_SOURCE, 0, 78e4);
}
if (emu->audigy && (emu->serial == 0x10011102) ) { /* audigy2 Value */
/* Hacks for Alice3 to work independent of haP16V driver */
@@ -600,7 +600,7 @@ static int snd_emu10k1_free(emu10k1_t *emu)
if (emu->port)
pci_release_regions(emu->pci);
pci_disable_device(emu->pci);
- if (emu->card_capabilities->ca0151_chip) /* P16V */
+ if (emu->audigy && emu->revision == 4) /* P16V */
snd_p16v_free(emu);
kfree(emu);
return 0;
@@ -612,24 +612,21 @@ static int snd_emu10k1_dev_free(snd_device_t *device)
return snd_emu10k1_free(emu);
}
+/* vendor, device, subsystem, emu10k1_chip, emu10k2_chip, ca0102_chip, ca0108_chip, ca0151_chip, spk71, spdif_bug, ac97_chip, ecard, driver, name */
+
static emu_chip_details_t emu_chip_details[] = {
/* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102,
.driver = "Audigy2", .name = "Audigy 2 Value [SB0400]",
- .id = "Audigy2",
.emu10k2_chip = 1,
.ca0108_chip = 1,
- .spk71 = 1,
- .ac97_chip = 1} ,
+ .spk71 = 1} ,
{.vendor = 0x1102, .device = 0x0008,
.driver = "Audigy2", .name = "Audigy 2 Value [Unknown]",
- .id = "Audigy2",
.emu10k2_chip = 1,
- .ca0108_chip = 1,
- .ac97_chip = 1} ,
+ .ca0108_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
.driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]",
- .id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ca0151_chip = 1,
@@ -638,7 +635,6 @@ static emu_chip_details_t emu_chip_details[] = {
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102,
.driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]",
- .id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ca0151_chip = 1,
@@ -647,7 +643,6 @@ static emu_chip_details_t emu_chip_details[] = {
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102,
.driver = "Audigy2", .name = "Audigy 2 ZS [2001]",
- .id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ca0151_chip = 1,
@@ -656,7 +651,6 @@ static emu_chip_details_t emu_chip_details[] = {
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102,
.driver = "Audigy2", .name = "Audigy 2 [SB0240]",
- .id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ca0151_chip = 1,
@@ -665,165 +659,35 @@ static emu_chip_details_t emu_chip_details[] = {
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102,
.driver = "Audigy2", .name = "Audigy 2 EX [1005]",
- .id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ca0151_chip = 1,
.spdif_bug = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
.driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]",
- .id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ca0151_chip = 1,
.spk71 = 1,
.spdif_bug = 1,
.ac97_chip = 1} ,
- {.vendor = 0x1102, .device = 0x0004, .revision = 0x04,
- .driver = "Audigy2", .name = "Audigy 2 [Unknown]",
- .id = "Audigy2",
- .emu10k2_chip = 1,
- .ca0102_chip = 1,
- .ca0151_chip = 1,
- .spdif_bug = 1,
- .ac97_chip = 1} ,
- {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10020052,
- .driver = "Audigy", .name = "Audigy 1 ES [SB0160]",
- .id = "Audigy",
- .emu10k2_chip = 1,
- .ca0102_chip = 1,
- .spdif_bug = 1,
- .ac97_chip = 1} ,
- {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102,
- .driver = "Audigy", .name = "Audigy 1 [SB0090]",
- .id = "Audigy",
- .emu10k2_chip = 1,
- .ca0102_chip = 1,
- .ac97_chip = 1} ,
- {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102,
- .driver = "Audigy", .name = "Audigy 1 [SB0090]",
- .id = "Audigy",
- .emu10k2_chip = 1,
- .ca0102_chip = 1,
- .ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004,
- .driver = "Audigy", .name = "Audigy 1 [Unknown]",
- .id = "Audigy",
+ .driver = "Audigy", .name = "Audigy 1 or 2 [Unknown]",
.emu10k2_chip = 1,
.ca0102_chip = 1,
- .ac97_chip = 1} ,
+ .spdif_bug = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102,
.driver = "EMU10K1", .name = "E-mu APS [4001]",
- .id = "APS",
.emu10k1_chip = 1,
.ecard = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
- .driver = "EMU10K1", .name = "SBLive! Player 5.1 [SB0060]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102,
.driver = "EMU10K1", .name = "SB Live 5.1",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102,
- .driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]",
- .id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102,
- .driver = "EMU10K1", .name = "SBLive! [CT4620]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4670]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4780]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102,
- .driver = "EMU10K1", .name = "SB PCI512 [CT4790]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4830]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4831]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4832]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4850]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4870]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102,
- .driver = "EMU10K1", .name = "SBLive! Value [CT4871]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
- .driver = "EMU10K1", .name = "SBLive! Value [SB0060]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102,
- .driver = "EMU10K1", .name = "SBLive! Value [SB0101]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806A1102,
- .driver = "EMU10K1", .name = "SBLive! Value [SB0103]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102,
- .driver = "EMU10K1", .name = "SBLive! [SB0105]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002,
.driver = "EMU10K1", .name = "SB Live [Unknown]",
- .id = "Live",
.emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
+ .ac97_chip = 1} ,
{ } /* terminator */
};
@@ -874,15 +738,13 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
emu->revision = revision;
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model);
+ emu->card_type = EMU10K1_CARD_CREATIVE;
snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model);
for (c = emu_chip_details; c->vendor; c++) {
if (c->vendor == pci->vendor && c->device == pci->device) {
- if (c->subsystem && c->subsystem != emu->serial)
- continue;
- if (c->revision && c->revision != emu->revision)
- continue;
- break;
+ if (c->subsystem == emu->serial) break;
+ if (c->subsystem == 0) break;
}
}
if (c->vendor == 0) {
@@ -897,23 +759,6 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
else
snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x\n", c->name, pci->vendor, pci->device, emu->serial);
- if (!*card->id && c->id) {
- int i, n = 0;
- strlcpy(card->id, c->id, sizeof(card->id));
- for (;;) {
- for (i = 0; i < snd_ecards_limit; i++) {
- if (snd_cards[i] && !strcmp(snd_cards[i]->id, card->id))
- break;
- }
- if (i >= snd_ecards_limit)
- break;
- n++;
- if (n >= SNDRV_CARDS)
- break;
- snprintf(card->id, sizeof(card->id), "%s_%d", c->id, n);
- }
- }
-
is_audigy = emu->audigy = c->emu10k2_chip;
/* set the DMA transfer mask */
@@ -971,6 +816,15 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
pci_set_master(pci);
+ if (c->ecard) {
+ emu->card_type = EMU10K1_CARD_EMUAPS;
+ emu->APS = 1;
+ }
+ if (! c->ac97_chip)
+ emu->no_ac97 = 1;
+
+ emu->spk71 = c->spk71;
+
emu->fx8010.fxbus_mask = 0x303f;
if (extin_mask == 0)
extin_mask = 0x3fcf;
@@ -979,7 +833,7 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
emu->fx8010.extin_mask = extin_mask;
emu->fx8010.extout_mask = extout_mask;
- if (emu->card_capabilities->ecard) {
+ if (emu->APS) {
if ((err = snd_emu10k1_ecard_init(emu)) < 0) {
snd_emu10k1_free(emu);
return err;
diff --git a/trunk/sound/pci/emu10k1/emu10k1x.c b/trunk/sound/pci/emu10k1/emu10k1x.c
index e90c5ddd1d17..27dfd8ddddf4 100644
--- a/trunk/sound/pci/emu10k1/emu10k1x.c
+++ b/trunk/sound/pci/emu10k1/emu10k1x.c
@@ -361,7 +361,10 @@ static void snd_emu10k1x_gpio_write(emu10k1x_t *emu, unsigned int value)
static void snd_emu10k1x_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
- kfree(runtime->private_data);
+ emu10k1x_pcm_t *epcm = runtime->private_data;
+
+ if (epcm)
+ kfree(epcm);
}
static void snd_emu10k1x_pcm_interrupt(emu10k1x_t *emu, emu10k1x_voice_t *voice)
@@ -1072,7 +1075,6 @@ static int __devinit snd_emu10k1x_proc_init(emu10k1x_t * emu)
snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1x_proc_reg_read);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu10k1x_proc_reg_write;
- entry->mode |= S_IWUSR;
entry->private_data = emu;
}
@@ -1625,7 +1627,7 @@ static int __init alsa_card_emu10k1x_init(void)
{
int err;
- if ((err = pci_register_driver(&driver)) > 0)
+ if ((err = pci_module_init(&driver)) > 0)
return err;
return 0;
diff --git a/trunk/sound/pci/emu10k1/emufx.c b/trunk/sound/pci/emu10k1/emufx.c
index 0529fb281125..b9fa2e887fee 100644
--- a/trunk/sound/pci/emu10k1/emufx.c
+++ b/trunk/sound/pci/emu10k1/emufx.c
@@ -1077,7 +1077,7 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
gpr += 2;
/* PCM Side Playback (independent from stereo mix) */
- if (emu->card_capabilities->spk71) {
+ if (emu->spk71) {
A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE));
A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE));
snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100);
@@ -1145,14 +1145,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_SPDIF_CD_L);
A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_SPDIF_CD_R);
snd_emu10k1_init_stereo_control(&controls[nctl++],
- emu->card_capabilities->ac97_chip ? "Audigy CD Playback Volume" : "CD Playback Volume",
+ emu->no_ac97 ? "CD Playback Volume" : "Audigy CD Playback Volume",
gpr, 0);
gpr += 2;
/* Audigy CD Capture Volume */
A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L);
A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R);
snd_emu10k1_init_stereo_control(&controls[nctl++],
- emu->card_capabilities->ac97_chip ? "Audigy CD Capture Volume" : "CD Capture Volume",
+ emu->no_ac97 ? "CD Capture Volume" : "Audigy CD Capture Volume",
gpr, 0);
gpr += 2;
@@ -1171,14 +1171,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_LINE2_L);
A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_LINE2_R);
snd_emu10k1_init_stereo_control(&controls[nctl++],
- emu->card_capabilities->ac97_chip ? "Line2 Playback Volume" : "Line Playback Volume",
+ emu->no_ac97 ? "Line Playback Volume" : "Line2 Playback Volume",
gpr, 0);
gpr += 2;
/* Line2 Capture Volume */
A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_LINE2_L);
A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_LINE2_R);
snd_emu10k1_init_stereo_control(&controls[nctl++],
- emu->card_capabilities->ac97_chip ? "Line2 Capture Volume" : "Line Capture Volume",
+ emu->no_ac97 ? "Line Capture Volume" : "Line2 Capture Volume",
gpr, 0);
gpr += 2;
@@ -1197,14 +1197,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AUX2_L);
A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AUX2_R);
snd_emu10k1_init_stereo_control(&controls[nctl++],
- emu->card_capabilities->ac97_chip ? "Aux2 Playback Volume" : "Aux Playback Volume",
+ emu->no_ac97 ? "Aux Playback Volume" : "Aux2 Playback Volume",
gpr, 0);
gpr += 2;
/* Aux2 Capture Volume */
A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AUX2_L);
A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AUX2_R);
snd_emu10k1_init_stereo_control(&controls[nctl++],
- emu->card_capabilities->ac97_chip ? "Aux2 Capture Volume" : "Aux Capture Volume",
+ emu->no_ac97 ? "Aux Capture Volume" : "Aux2 Capture Volume",
gpr, 0);
gpr += 2;
@@ -1232,7 +1232,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0);
gpr++;
- if (emu->card_capabilities->spk71) {
+ if (emu->spk71) {
/* Stereo Mix Side Playback */
A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix));
A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1));
@@ -1266,7 +1266,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), A_GPR(playback + 3), A_C_00000000, A_C_00000000); /* rear right */
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), A_GPR(playback + 5), A_C_00000000, A_C_00000000); /* LFE */
- if (emu->card_capabilities->spk71) {
+ if (emu->spk71) {
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 6), A_GPR(playback + 6), A_C_00000000, A_C_00000000); /* side left */
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 7), A_GPR(playback + 7), A_C_00000000, A_C_00000000); /* side right */
}
@@ -1359,7 +1359,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
- if (emu->card_capabilities->spk71)
+ if (emu->spk71)
A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS);
/* headphone */
@@ -1982,27 +1982,22 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000);
/* EFX capture - capture the 16 EXTINS */
- if (emu->card_capabilities->sblive51) {
- /* On the Live! 5.1, FXBUS2(1) and FXBUS(2) are shared with EXTOUT_ACENTER
- * and EXTOUT_ALFE, so we can't connect inputs to them for multitrack recording.
- *
- * Since only 14 of the 16 EXTINs are used, this is not a big problem.
- * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture
- * 0 and 3, then the rest of the EXTINs to the corresponding FX capture
- * channel. Multitrack recorders will still see the center/lfe output signal
- * on the second and third channels.
- */
- OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
- OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
- OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
- OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
- for (z = 4; z < 14; z++)
- OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
- } else {
- for (z = 0; z < 16; z++)
- OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
+ OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
+ OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
+ OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
+ OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
+ /* Dont connect anything to FXBUS2 1 and 2. These are shared with
+ * Center/LFE on the SBLive 5.1. The kX driver only changes the
+ * routing when it detects an SBLive 5.1.
+ *
+ * Since only 14 of the 16 EXTINs are used, this is not a big problem.
+ * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture
+ * 0 and 3, then the rest of the EXTINs to the corresponding FX capture
+ * channel.
+ */
+ for (z = 4; z < 14; z++) {
+ OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
}
-
if (gpr > tmp) {
snd_BUG();
@@ -2133,6 +2128,7 @@ static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info)
int res;
memset(info, 0, sizeof(info));
+ info->card = emu->card_type;
info->internal_tram_size = emu->fx8010.itram_size;
info->external_tram_size = emu->fx8010.etram_pages.bytes / 2;
fxbus = fxbuses;
diff --git a/trunk/sound/pci/emu10k1/emumixer.c b/trunk/sound/pci/emu10k1/emumixer.c
index 6be82c5fe138..044663d31aa7 100644
--- a/trunk/sound/pci/emu10k1/emumixer.c
+++ b/trunk/sound/pci/emu10k1/emumixer.c
@@ -68,7 +68,6 @@ static int snd_emu10k1_spdif_get_mask(snd_kcontrol_t * kcontrol,
return 0;
}
-#if 0
static int snd_audigy_spdif_output_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
static char *texts[] = {"44100", "48000", "96000"};
@@ -153,7 +152,6 @@ static snd_kcontrol_new_t snd_audigy_spdif_output_rate =
.get = snd_audigy_spdif_output_rate_get,
.put = snd_audigy_spdif_output_rate_put
};
-#endif
static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
@@ -793,7 +791,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
NULL
};
- if (emu->card_capabilities->ac97_chip) {
+ if (!emu->no_ac97) {
ac97_bus_t *pbus;
ac97_template_t ac97;
static ac97_bus_ops_t ops = {
@@ -835,7 +833,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
for (; *c; c++)
remove_ctl(card, *c);
} else {
- if (emu->card_capabilities->ecard)
+ if (emu->APS)
strcpy(emu->card->mixername, "EMU APS");
else if (emu->audigy)
strcpy(emu->card->mixername, "SB Audigy");
@@ -920,7 +918,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
mix->attn[0] = 0xffff;
}
- if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
+ if (! emu->APS) { /* FIXME: APS has these controls? */
/* sb live! and audigy */
if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
return -ENOMEM;
@@ -937,20 +935,18 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
return err;
-#if 0
if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
return err;
-#endif
- } else if (! emu->card_capabilities->ecard) {
+ } else if (! emu->APS) {
/* sb live! */
if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
return err;
}
- if (emu->card_capabilities->ca0151_chip) { /* P16V */
+ if (emu->audigy && emu->revision == 4) { /* P16V */
if ((err = snd_p16v_mixer(emu)))
return err;
}
diff --git a/trunk/sound/pci/emu10k1/emupcm.c b/trunk/sound/pci/emu10k1/emupcm.c
index 520b99af5f55..d1c2a02c486b 100644
--- a/trunk/sound/pci/emu10k1/emupcm.c
+++ b/trunk/sound/pci/emu10k1/emupcm.c
@@ -262,7 +262,7 @@ static unsigned int emu10k1_select_interprom(unsigned int pitch_target)
*
* returns: cache invalidate size in samples
*/
-static inline int emu10k1_ccis(int stereo, int w_16)
+static int inline emu10k1_ccis(int stereo, int w_16)
{
if (w_16) {
return stereo ? 24 : 26;
@@ -991,7 +991,9 @@ static void snd_emu10k1_pcm_efx_mixer_notify(emu10k1_t *emu, int idx, int activa
static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
- kfree(runtime->private_data);
+ emu10k1_pcm_t *epcm = runtime->private_data;
+
+ kfree(epcm);
}
static int snd_emu10k1_efx_playback_close(snd_pcm_substream_t * substream)
diff --git a/trunk/sound/pci/emu10k1/emuproc.c b/trunk/sound/pci/emu10k1/emuproc.c
index cc22707c91fa..d990d5eb45a8 100644
--- a/trunk/sound/pci/emu10k1/emuproc.c
+++ b/trunk/sound/pci/emu10k1/emuproc.c
@@ -30,7 +30,6 @@
#include
#include
#include
-#include "p16v.h"
static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu,
snd_info_buffer_t * buffer,
@@ -45,34 +44,28 @@ static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu,
unsigned int status, rate = 0;
status = snd_emu10k1_ptr_read(emu, status_reg, 0);
+ if (rate_reg > 0)
+ rate = snd_emu10k1_ptr_read(emu, rate_reg, 0);
snd_iprintf(buffer, "\n%s\n", title);
- if (status != 0xffffffff) {
- snd_iprintf(buffer, "Professional Mode : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no");
- snd_iprintf(buffer, "Not Audio Data : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no");
- snd_iprintf(buffer, "Copyright : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no");
- snd_iprintf(buffer, "Emphasis : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]);
- snd_iprintf(buffer, "Mode : %i\n", (status & SPCS_MODEMASK) >> 6);
- snd_iprintf(buffer, "Category Code : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8);
- snd_iprintf(buffer, "Generation Status : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy");
- snd_iprintf(buffer, "Source Mask : %i\n", (status & SPCS_SOURCENUMMASK) >> 16);
- snd_iprintf(buffer, "Channel Number : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]);
- snd_iprintf(buffer, "Sample Rate : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]);
- snd_iprintf(buffer, "Clock Accuracy : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]);
-
- if (rate_reg > 0) {
- rate = snd_emu10k1_ptr_read(emu, rate_reg, 0);
- snd_iprintf(buffer, "S/PDIF Valid : %s\n", rate & SRCS_SPDIFVALID ? "on" : "off");
- snd_iprintf(buffer, "S/PDIF Locked : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off");
- snd_iprintf(buffer, "Rate Locked : %s\n", rate & SRCS_RATELOCKED ? "on" : "off");
- /* From ((Rate * 48000 ) / 262144); */
- snd_iprintf(buffer, "Estimated Sample Rate : %d\n", ((rate & 0xFFFFF ) * 375) >> 11);
- }
- } else {
- snd_iprintf(buffer, "No signal detected.\n");
+ snd_iprintf(buffer, "Professional Mode : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no");
+ snd_iprintf(buffer, "Not Audio Data : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no");
+ snd_iprintf(buffer, "Copyright : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no");
+ snd_iprintf(buffer, "Emphasis : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]);
+ snd_iprintf(buffer, "Mode : %i\n", (status & SPCS_MODEMASK) >> 6);
+ snd_iprintf(buffer, "Category Code : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8);
+ snd_iprintf(buffer, "Generation Status : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy");
+ snd_iprintf(buffer, "Source Mask : %i\n", (status & SPCS_SOURCENUMMASK) >> 16);
+ snd_iprintf(buffer, "Channel Number : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]);
+ snd_iprintf(buffer, "Sample Rate : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]);
+ snd_iprintf(buffer, "Clock Accuracy : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]);
+
+ if (rate_reg > 0) {
+ snd_iprintf(buffer, "S/PDIF Locked : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off");
+ snd_iprintf(buffer, "Rate Locked : %s\n", rate & SRCS_RATELOCKED ? "on" : "off");
+ snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", rate & SRCS_ESTSAMPLERATE);
}
-
}
static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
@@ -189,7 +182,7 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "EMU10K1\n\n");
snd_iprintf(buffer, "Card : %s\n",
- emu->audigy ? "Audigy" : (emu->card_capabilities->ecard ? "EMU APS" : "Creative"));
+ emu->audigy ? "Audigy" : (emu->APS ? "EMU APS" : "Creative"));
snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size);
snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes / 2);
snd_iprintf(buffer, "\n");
@@ -230,35 +223,15 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "\nAll FX Outputs :\n");
for (idx = 0; idx < (emu->audigy ? 64 : 32); idx++)
snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]);
-}
-
-static void snd_emu10k1_proc_spdif_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
-{
- emu10k1_t *emu = entry->private_data;
- snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS);
- snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS);
-#if 0
+ snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 0", SPCS0, -1);
+ snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 1", SPCS1, -1);
+ snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 2/3", SPCS2, -1);
+ snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF", CDCS, CDSRCS);
+ snd_emu10k1_proc_spdif_status(emu, buffer, "General purpose S/PDIF", GPSCS, GPSRCS);
val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0);
snd_iprintf(buffer, "\nZoomed Video\n");
snd_iprintf(buffer, "Rate Locked : %s\n", val & SRCS_RATELOCKED ? "on" : "off");
snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", val & SRCS_ESTSAMPLERATE);
-#endif
-}
-
-static void snd_emu10k1_proc_rates_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
-{
- static int samplerate[8] = { 44100, 48000, 96000, 192000, 4, 5, 6, 7 };
- emu10k1_t *emu = entry->private_data;
- unsigned int val, tmp, n;
- val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0);
- tmp = (val >> 16) & 0x8;
- for (n=0;n<4;n++) {
- tmp = val >> (16 + (n*4));
- if (tmp & 0x8) snd_iprintf(buffer, "Channel %d: Rate=%d\n", n, samplerate[tmp & 0x7]);
- else snd_iprintf(buffer, "Channel %d: No input\n", n);
- }
}
static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry,
@@ -527,46 +500,32 @@ int __devinit snd_emu10k1_proc_init(emu10k1_t * emu)
snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_io_reg_read);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu_proc_io_reg_write;
- entry->mode |= S_IWUSR;
}
if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) {
snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00a);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu_proc_ptr_reg_write00;
- entry->mode |= S_IWUSR;
}
if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) {
snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00b);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu_proc_ptr_reg_write00;
- entry->mode |= S_IWUSR;
}
if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) {
snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20a);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu_proc_ptr_reg_write20;
- entry->mode |= S_IWUSR;
}
if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) {
snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20b);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu_proc_ptr_reg_write20;
- entry->mode |= S_IWUSR;
}
#endif
if (! snd_card_proc_new(emu->card, "emu10k1", &entry))
snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read);
- if (emu->card_capabilities->emu10k2_chip) {
- if (! snd_card_proc_new(emu->card, "spdif-in", &entry))
- snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_spdif_read);
- }
- if (emu->card_capabilities->ca0151_chip) {
- if (! snd_card_proc_new(emu->card, "capture-rates", &entry))
- snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_rates_read);
- }
-
if (! snd_card_proc_new(emu->card, "voices", &entry))
snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read);
diff --git a/trunk/sound/pci/emu10k1/irq.c b/trunk/sound/pci/emu10k1/irq.c
index cd8460d56752..b81a7cafff39 100644
--- a/trunk/sound/pci/emu10k1/irq.c
+++ b/trunk/sound/pci/emu10k1/irq.c
@@ -37,7 +37,7 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
int handled = 0;
while ((status = inl(emu->port + IPR)) != 0) {
- //printk("emu10k1 irq - status = 0x%x\n", status);
+ // printk("irq - status = 0x%x\n", status);
orig_status = status;
handled = 1;
if (status & IPR_PCIERROR) {
@@ -147,36 +147,9 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE);
status &= ~IPR_FXDSP;
}
- if (status & IPR_P16V) {
- while ((status2 = inl(emu->port + IPR2)) != 0) {
- u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */
- emu10k1_voice_t *pvoice = &(emu->p16v_voices[0]);
- emu10k1_voice_t *cvoice = &(emu->p16v_capture_voice);
-
- //printk(KERN_INFO "status2=0x%x\n", status2);
- orig_status2 = status2;
- if(status2 & mask) {
- if(pvoice->use) {
- snd_pcm_period_elapsed(pvoice->epcm->substream);
- } else {
- snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use);
- }
- }
- if(status2 & 0x110000) {
- //printk(KERN_INFO "capture int found\n");
- if(cvoice->use) {
- //printk(KERN_INFO "capture period_elapsed\n");
- snd_pcm_period_elapsed(cvoice->epcm->substream);
- }
- }
- outl(orig_status2, emu->port + IPR2); /* ack all */
- }
- status &= ~IPR_P16V;
- }
-
if (status) {
unsigned int bits;
- snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
+ //snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
//make sure any interrupts we don't handle are disabled:
bits = INTE_FXDSPENABLE |
INTE_PCIERRORENABLE |
@@ -197,5 +170,20 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
outl(orig_status, emu->port + IPR); /* ack all */
}
+ if (emu->audigy && emu->revision == 4) { /* P16V */
+ while ((status2 = inl(emu->port + IPR2)) != 0) {
+ u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */
+ emu10k1_voice_t *pvoice = &(emu->p16v_voices[0]);
+ orig_status2 = status2;
+ if(status2 & mask) {
+ if(pvoice->use) {
+ snd_pcm_period_elapsed(pvoice->epcm->substream);
+ } else {
+ snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use);
+ }
+ }
+ outl(orig_status2, emu->port + IPR2); /* ack all */
+ }
+ }
return IRQ_RETVAL(handled);
}
diff --git a/trunk/sound/pci/emu10k1/p16v.c b/trunk/sound/pci/emu10k1/p16v.c
index 98f980189892..d03cb2fefc9e 100644
--- a/trunk/sound/pci/emu10k1/p16v.c
+++ b/trunk/sound/pci/emu10k1/p16v.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) by James Courtier-Dutton
* Driver p16v chips
- * Version: 0.25
+ * Version: 0.22
*
* FEATURES currently supported:
* Output fixed at S32_LE, 2 channel to hw:0,0
@@ -41,15 +41,7 @@
* Integrated with snd-emu10k1 driver.
* 0.22
* Removed #if 0 ... #endif
- * 0.23
- * Implement different capture rates.
- * 0.24
- * Implement different capture source channels.
- * e.g. When HD Capture source is set to SPDIF,
- * setting HD Capture channel to 0 captures from CDROM digital input.
- * setting HD Capture channel to 1 captures from SPDIF in.
- * 0.25
- * Include capture buffer sizes.
+ *
*
* BUGS:
* Some stability problems when unloading the snd-p16v kernel module.
@@ -127,41 +119,22 @@ static snd_pcm_hardware_t snd_p16v_playback_hw = {
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */
- .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
- .rate_min = 44100,
+ .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 ,
+ .rate_min = 48000,
.rate_max = 192000,
.channels_min = 8,
.channels_max = 8,
- .buffer_bytes_max = ((65536 - 64) * 8),
+ .buffer_bytes_max = (32*1024),
.period_bytes_min = 64,
- .period_bytes_max = (65536 - 64),
+ .period_bytes_max = (16*1024),
.periods_min = 2,
.periods_max = 8,
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_p16v_capture_hw = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID),
- .formats = SNDRV_PCM_FMTBIT_S32_LE,
- .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
- .rate_min = 44100,
- .rate_max = 192000,
- .channels_min = 2,
- .channels_max = 2,
- .buffer_bytes_max = (65536 - 64),
- .period_bytes_min = 64,
- .period_bytes_max = (65536 - 128) >> 1, /* size has to be N*64 bytes */
- .periods_min = 2,
- .periods_max = 2,
- .fifo_size = 0,
-};
-
static void snd_p16v_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
- emu10k1_pcm_t *epcm = runtime->private_data;
+ snd_pcm_t *epcm = runtime->private_data;
if (epcm) {
//snd_printk("epcm free: %p\n", epcm);
@@ -205,63 +178,15 @@ static int snd_p16v_pcm_open_playback_channel(snd_pcm_substream_t *substream, in
return 0;
}
-/* open_capture callback */
-static int snd_p16v_pcm_open_capture_channel(snd_pcm_substream_t *substream, int channel_id)
-{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- emu10k1_voice_t *channel = &(emu->p16v_capture_voice);
- emu10k1_pcm_t *epcm;
- snd_pcm_runtime_t *runtime = substream->runtime;
- int err;
-
- epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
- //snd_printk("epcm kcalloc: %p\n", epcm);
-
- if (epcm == NULL)
- return -ENOMEM;
- epcm->emu = emu;
- epcm->substream = substream;
- //snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id);
-
- runtime->private_data = epcm;
- runtime->private_free = snd_p16v_pcm_free_substream;
-
- runtime->hw = snd_p16v_capture_hw;
-
- channel->emu = emu;
- channel->number = channel_id;
-
- channel->use=1;
- //snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use);
- //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
- //channel->interrupt = snd_p16v_pcm_channel_interrupt;
- channel->epcm=epcm;
- if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
- return err;
-
- return 0;
-}
-
/* close callback */
static int snd_p16v_pcm_close_playback(snd_pcm_substream_t *substream)
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
//snd_pcm_runtime_t *runtime = substream->runtime;
- //emu10k1_pcm_t *epcm = runtime->private_data;
- emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
- /* FIXME: maybe zero others */
- return 0;
-}
-
-/* close callback */
-static int snd_p16v_pcm_close_capture(snd_pcm_substream_t *substream)
-{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- //snd_pcm_runtime_t *runtime = substream->runtime;
- //emu10k1_pcm_t *epcm = runtime->private_data;
- emu->p16v_capture_voice.use=0;
- /* FIXME: maybe zero others */
+ //emu10k1_pcm_t *epcm = runtime->private_data;
+ emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
+/* FIXME: maybe zero others */
return 0;
}
@@ -270,55 +195,36 @@ static int snd_p16v_pcm_open_playback_front(snd_pcm_substream_t *substream)
return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
}
-static int snd_p16v_pcm_open_capture(snd_pcm_substream_t *substream)
-{
- // Only using channel 0 for now, but the card has 2 channels.
- return snd_p16v_pcm_open_capture_channel(substream, 0);
-}
-
/* hw_params callback */
static int snd_p16v_pcm_hw_params_playback(snd_pcm_substream_t *substream,
snd_pcm_hw_params_t * hw_params)
{
int result;
+ //snd_printk("hw_params alloc: substream=%p\n", substream);
result = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
+ //snd_printk("hw_params alloc: result=%d\n", result);
+ //dump_stack();
return result;
}
-/* hw_params callback */
-static int snd_p16v_pcm_hw_params_capture(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t * hw_params)
-{
- int result;
- result = snd_pcm_lib_malloc_pages(substream,
- params_buffer_bytes(hw_params));
- return result;
-}
-
-
/* hw_free callback */
static int snd_p16v_pcm_hw_free_playback(snd_pcm_substream_t *substream)
{
int result;
+ //snd_printk("hw_params free: substream=%p\n", substream);
result = snd_pcm_lib_free_pages(substream);
+ //snd_printk("hw_params free: result=%d\n", result);
+ //dump_stack();
return result;
}
-/* hw_free callback */
-static int snd_p16v_pcm_hw_free_capture(snd_pcm_substream_t *substream)
-{
- int result;
- result = snd_pcm_lib_free_pages(substream);
- return result;
-}
-
-
/* prepare playback callback */
static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
+ //emu10k1_pcm_t *epcm = runtime->private_data;
int channel = substream->pcm->device - emu->p16v_device_offset;
u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel));
u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
@@ -331,21 +237,23 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
switch (runtime->rate) {
case 44100:
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080);
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x8000); /* FIXME: This will change the capture rate as well! */
+ break;
+ case 48000:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x0000); /* FIXME: This will change the capture rate as well! */
break;
case 96000:
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040);
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x4000); /* FIXME: This will change the capture rate as well! */
break;
case 192000:
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020);
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x2000); /* FIXME: This will change the capture rate as well! */
break;
- case 48000:
default:
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000);
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, 0x0000); /* FIXME: This will change the capture rate as well! */
break;
}
/* FIXME: Check emu->buffer.size before actually writing to it. */
- for(i=0; i < runtime->periods; i++) {
+ for(i=0; i < runtime->periods; i++) {
table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
table_base[(i*2)+1]=period_size_bytes<<16;
}
@@ -354,8 +262,7 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
- //snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
- snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0);
snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0);
snd_emu10k1_ptr20_write(emu, 0x08, channel, 0);
@@ -363,41 +270,6 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
return 0;
}
-/* prepare capture callback */
-static int snd_p16v_pcm_prepare_capture(snd_pcm_substream_t *substream)
-{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- int channel = substream->pcm->device - emu->p16v_device_offset;
- u32 tmp;
- //printk("prepare capture:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1));
- tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
- switch (runtime->rate) {
- case 44100:
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0800);
- break;
- case 96000:
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0400);
- break;
- case 192000:
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0200);
- break;
- case 48000:
- default:
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0000);
- break;
- }
- /* FIXME: Check emu->buffer.size before actually writing to it. */
- snd_emu10k1_ptr20_write(emu, 0x13, channel, 0);
- snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
- snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
- snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0);
- //snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */
- //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
- int channel = 0;
- int result = 0;
- u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- snd_p16v_intr_enable(emu, inte);
- snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<running = 1;
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<running = 0;
- break;
- default:
- result = -EINVAL;
- break;
- }
- return result;
-}
-
/* pointer_playback callback */
static snd_pcm_uframes_t
snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream)
@@ -528,31 +370,6 @@ snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream)
return ptr;
}
-/* pointer_capture callback */
-static snd_pcm_uframes_t
-snd_p16v_pcm_pointer_capture(snd_pcm_substream_t *substream)
-{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
- snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
- int channel = 0;
-
- if (!epcm->running)
- return 0;
-
- ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel);
- ptr2 = bytes_to_frames(runtime, ptr1);
- ptr=ptr2;
- if (ptr >= runtime->buffer_size) {
- ptr -= runtime->buffer_size;
- printk("buffer capture limited!\n");
- }
- //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate);
-
- return ptr;
-}
-
/* operators */
static snd_pcm_ops_t snd_p16v_playback_front_ops = {
.open = snd_p16v_pcm_open_playback_front,
@@ -565,18 +382,6 @@ static snd_pcm_ops_t snd_p16v_playback_front_ops = {
.pointer = snd_p16v_pcm_pointer_playback,
};
-static snd_pcm_ops_t snd_p16v_capture_ops = {
- .open = snd_p16v_pcm_open_capture,
- .close = snd_p16v_pcm_close_capture,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_p16v_pcm_hw_params_capture,
- .hw_free = snd_p16v_pcm_hw_free_capture,
- .prepare = snd_p16v_pcm_prepare_capture,
- .trigger = snd_p16v_pcm_trigger_capture,
- .pointer = snd_p16v_pcm_pointer_capture,
-};
-
-
int snd_p16v_free(emu10k1_t *chip)
{
// release the data
@@ -600,22 +405,20 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
snd_pcm_t *pcm;
snd_pcm_substream_t *substream;
int err;
- int capture=1;
+ int capture=0;
//snd_printk("snd_p16v_pcm called. device=%d\n", device);
emu->p16v_device_offset = device;
if (rpcm)
*rpcm = NULL;
-
+ //if (device == 0) capture=1;
if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0)
return err;
pcm->private_data = emu;
pcm->private_free = snd_p16v_pcm_free;
- // Single playback 8 channel device.
- // Single capture 2 channel device.
+
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops);
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_p16v_capture_ops);
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
@@ -628,7 +431,7 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
if ((err = snd_pcm_lib_preallocate_pages(substream,
SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(emu->pci),
- ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0)
+ 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */
return err;
//snd_printk("preallocate playback substream: err=%d\n", err);
}
@@ -639,7 +442,7 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
if ((err = snd_pcm_lib_preallocate_pages(substream,
SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(emu->pci),
- 65536 - 64, 65536 - 64)) < 0)
+ 64*1024, 64*1024)) < 0)
return err;
//snd_printk("preallocate capture substream: err=%d\n", err);
}
@@ -891,106 +694,6 @@ static snd_kcontrol_new_t snd_p16v_volume_control_spdif_rear =
.put = snd_p16v_volume_put_spdif_rear
};
-static int snd_p16v_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[8] = { "SPDIF", "I2S", "SRC48", "SRCMulti_SPDIF", "SRCMulti_I2S", "CDIF", "FX", "AC97" };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 8;
- if (uinfo->value.enumerated.item > 7)
- uinfo->value.enumerated.item = 7;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_p16v_capture_source_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.enumerated.item[0] = emu->p16v_capture_source;
- return 0;
-}
-
-static int snd_p16v_capture_source_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- unsigned int val;
- int change = 0;
- u32 mask;
- u32 source;
-
- val = ucontrol->value.enumerated.item[0] ;
- change = (emu->p16v_capture_source != val);
- if (change) {
- emu->p16v_capture_source = val;
- source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
- mask = snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & 0xffff;
- snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, source | mask);
- }
- return change;
-}
-
-static snd_kcontrol_new_t snd_p16v_capture_source __devinitdata =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "HD Capture source",
- .info = snd_p16v_capture_source_info,
- .get = snd_p16v_capture_source_get,
- .put = snd_p16v_capture_source_put
-};
-
-static int snd_p16v_capture_channel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[4] = { "0", "1", "2", "3", };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 4;
- if (uinfo->value.enumerated.item > 3)
- uinfo->value.enumerated.item = 3;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_p16v_capture_channel_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.enumerated.item[0] = emu->p16v_capture_channel;
- return 0;
-}
-
-static int snd_p16v_capture_channel_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- unsigned int val;
- int change = 0;
- u32 tmp;
-
- val = ucontrol->value.enumerated.item[0] ;
- change = (emu->p16v_capture_channel != val);
- if (change) {
- emu->p16v_capture_channel = val;
- tmp = snd_emu10k1_ptr20_read(emu, CAPTURE_P16V_SOURCE, 0) & 0xfffc;
- snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, tmp | val);
- }
- return change;
-}
-
-static snd_kcontrol_new_t snd_p16v_capture_channel __devinitdata =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "HD Capture channel",
- .info = snd_p16v_capture_channel_info,
- .get = snd_p16v_capture_channel_get,
- .put = snd_p16v_capture_channel_put
-};
-
int snd_p16v_mixer(emu10k1_t *emu)
{
int err;
@@ -1028,14 +731,6 @@ int snd_p16v_mixer(emu10k1_t *emu)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
return err;
- if ((kctl = snd_ctl_new1(&snd_p16v_capture_source, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_p16v_capture_channel, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
return 0;
}
diff --git a/trunk/sound/pci/ens1370.c b/trunk/sound/pci/ens1370.c
index 4e63498a58b2..f910399db5c3 100644
--- a/trunk/sound/pci/ens1370.c
+++ b/trunk/sound/pci/ens1370.c
@@ -2401,7 +2401,7 @@ static struct pci_driver driver = {
static int __init alsa_card_ens137x_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_ens137x_exit(void)
diff --git a/trunk/sound/pci/es1938.c b/trunk/sound/pci/es1938.c
index b492777bc30f..b4ca8adf393c 100644
--- a/trunk/sound/pci/es1938.c
+++ b/trunk/sound/pci/es1938.c
@@ -1761,7 +1761,7 @@ static struct pci_driver driver = {
static int __init alsa_card_es1938_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_es1938_exit(void)
diff --git a/trunk/sound/pci/es1968.c b/trunk/sound/pci/es1968.c
index ea889b311390..faf63ff19c42 100644
--- a/trunk/sound/pci/es1968.c
+++ b/trunk/sound/pci/es1968.c
@@ -2559,7 +2559,6 @@ static struct ess_device_list pm_whitelist[] __devinitdata = {
{ TYPE_MAESTRO2E, 0x103c },
{ TYPE_MAESTRO2E, 0x1179 },
{ TYPE_MAESTRO2E, 0x14c0 }, /* HP omnibook 4150 */
- { TYPE_MAESTRO2E, 0x1558 },
};
static struct ess_device_list mpu_blacklist[] __devinitdata = {
@@ -2796,7 +2795,7 @@ static struct pci_driver driver = {
static int __init alsa_card_es1968_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_es1968_exit(void)
diff --git a/trunk/sound/pci/fm801.c b/trunk/sound/pci/fm801.c
index ff10e637a95e..08e7c5a296d5 100644
--- a/trunk/sound/pci/fm801.c
+++ b/trunk/sound/pci/fm801.c
@@ -195,7 +195,6 @@ struct _snd_fm801 {
static struct pci_device_id snd_fm801_ids[] = {
{ 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* FM801 */
- { 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* Gallant Odyssey Sound 4 */
{ 0, }
};
@@ -1469,7 +1468,7 @@ static struct pci_driver driver = {
static int __init alsa_card_fm801_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_fm801_exit(void)
diff --git a/trunk/sound/pci/hda/Makefile b/trunk/sound/pci/hda/Makefile
index bd8cb33c4fb4..570a59d33b41 100644
--- a/trunk/sound/pci/hda/Makefile
+++ b/trunk/sound/pci/hda/Makefile
@@ -1,5 +1,5 @@
snd-hda-intel-objs := hda_intel.o
-snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o
+snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o
ifdef CONFIG_PROC_FS
snd-hda-codec-objs += hda_proc.o
endif
diff --git a/trunk/sound/pci/hda/hda_codec.c b/trunk/sound/pci/hda/hda_codec.c
index e2cf02387289..9ed117ac0c09 100644
--- a/trunk/sound/pci/hda/hda_codec.c
+++ b/trunk/sound/pci/hda/hda_codec.c
@@ -49,10 +49,8 @@ struct hda_vendor_id {
/* codec vendor labels */
static struct hda_vendor_id hda_vendor_ids[] = {
{ 0x10ec, "Realtek" },
- { 0x11d4, "Analog Devices" },
{ 0x13f6, "C-Media" },
{ 0x434d, "C-Media" },
- { 0x8384, "SigmaTel" },
{} /* terminator */
};
@@ -510,7 +508,7 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
/* FIXME: support for multiple AFGs? */
codec->afg = look_for_afg_node(codec);
if (! codec->afg) {
- snd_printdd("hda_codec: no AFG node found\n");
+ snd_printk(KERN_ERR "hda_codec: no AFG node found\n");
snd_hda_codec_free(codec);
return -ENODEV;
}
@@ -550,9 +548,6 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag,
int channel_id, int format)
{
- if (! nid)
- return;
-
snd_printdd("hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
nid, stream_tag, channel_id, format);
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
@@ -566,10 +561,9 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stre
* amp access functions
*/
-/* FIXME: more better hash key? */
-#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
+#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + (idx) * 32 + (dir) * 64)
#define INFO_AMP_CAPS (1<<0)
-#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
+#define INFO_AMP_VOL (1<<1)
/* initialize the hash table */
static void init_amp_hash(struct hda_codec *codec)
@@ -628,29 +622,28 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
/*
* read the current volume to info
- * if the cache exists, read the cache value.
+ * if the cache exists, read from the cache.
*/
-static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
+static void get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
hda_nid_t nid, int ch, int direction, int index)
{
u32 val, parm;
- if (info->status & INFO_AMP_VOL(ch))
- return info->vol[ch];
+ if (info->status & (INFO_AMP_VOL << ch))
+ return;
parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
parm |= index;
val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, parm);
info->vol[ch] = val & 0xff;
- info->status |= INFO_AMP_VOL(ch);
- return info->vol[ch];
+ info->status |= INFO_AMP_VOL << ch;
}
/*
- * write the current volume in info to the h/w and update the cache
+ * write the current volume in info to the h/w
*/
-static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
+static void put_vol_mute(struct hda_codec *codec,
hda_nid_t nid, int ch, int direction, int index, int val)
{
u32 parm;
@@ -660,34 +653,30 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
parm |= index << AC_AMP_SET_INDEX_SHIFT;
parm |= val;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
- info->vol[ch] = val;
}
/*
- * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
+ * read/write AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
*/
-static int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index)
+int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index)
{
struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
if (! info)
return 0;
- return get_vol_mute(codec, info, nid, ch, direction, index);
+ get_vol_mute(codec, info, nid, ch, direction, index);
+ return info->vol[ch];
}
-/*
- * update the AMP value, mask = bit mask to set, val = the value
- */
-static int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int mask, int val)
+int snd_hda_codec_amp_write(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int val)
{
struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
-
if (! info)
return 0;
- val &= mask;
- val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
+ get_vol_mute(codec, info, nid, ch, direction, idx);
if (info->vol[ch] == val && ! codec->in_resume)
return 0;
- put_vol_mute(codec, info, nid, ch, direction, idx, val);
+ put_vol_mute(codec, nid, ch, direction, idx, val);
+ info->vol[ch] = val;
return 1;
}
@@ -746,15 +735,21 @@ int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
int chs = get_amp_channels(kcontrol);
int dir = get_amp_direction(kcontrol);
int idx = get_amp_index(kcontrol);
+ int val;
long *valp = ucontrol->value.integer.value;
int change = 0;
- if (chs & 1)
- change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
- 0x7f, *valp);
- if (chs & 2)
- change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
- 0x7f, valp[1]);
+ if (chs & 1) {
+ val = *valp & 0x7f;
+ val |= snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x80;
+ change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val);
+ valp++;
+ }
+ if (chs & 2) {
+ val = *valp & 0x7f;
+ val |= snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x80;
+ change |= snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val);
+ }
return change;
}
@@ -793,15 +788,21 @@ int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
int chs = get_amp_channels(kcontrol);
int dir = get_amp_direction(kcontrol);
int idx = get_amp_index(kcontrol);
+ int val;
long *valp = ucontrol->value.integer.value;
int change = 0;
- if (chs & 1)
- change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
- 0x80, *valp ? 0 : 0x80);
- if (chs & 2)
- change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
- 0x80, valp[1] ? 0 : 0x80);
+ if (chs & 1) {
+ val = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f;
+ val |= *valp ? 0 : 0x80;
+ change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val);
+ valp++;
+ }
+ if (chs & 2) {
+ val = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f;
+ val |= *valp ? 0 : 0x80;
+ change = snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val);
+ }
return change;
}
@@ -1447,6 +1448,10 @@ static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream
snd_assert(info->nid, return -EINVAL);
info->ops.prepare = hda_pcm_default_prepare;
}
+ if (info->ops.prepare == NULL) {
+ snd_assert(info->nid, return -EINVAL);
+ info->ops.prepare = hda_pcm_default_prepare;
+ }
if (info->ops.cleanup == NULL) {
snd_assert(info->nid, return -EINVAL);
info->ops.cleanup = hda_pcm_default_cleanup;
@@ -1520,12 +1525,12 @@ int snd_hda_build_pcms(struct hda_bus *bus)
*
* If no entries are matching, the function returns a negative value.
*/
-int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl)
+int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl)
{
- const struct hda_board_config *c;
+ struct hda_board_config *c;
if (codec->bus->modelname) {
- for (c = tbl; c->modelname || c->pci_subvendor; c++) {
+ for (c = tbl; c->modelname || c->pci_vendor; c++) {
if (c->modelname &&
! strcmp(codec->bus->modelname, c->modelname)) {
snd_printd(KERN_INFO "hda_codec: model '%s' is selected\n", c->modelname);
@@ -1538,10 +1543,9 @@ int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_c
u16 subsystem_vendor, subsystem_device;
pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_ID, &subsystem_device);
- for (c = tbl; c->modelname || c->pci_subvendor; c++) {
- if (c->pci_subvendor == subsystem_vendor &&
- (! c->pci_subdevice /* all match */||
- (c->pci_subdevice == subsystem_device)))
+ for (c = tbl; c->modelname || c->pci_vendor; c++) {
+ if (c->pci_vendor == subsystem_vendor &&
+ c->pci_device == subsystem_device)
return c->config;
}
}
@@ -1683,12 +1687,11 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o
snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format);
/* surrounds */
for (i = 1; i < mout->num_dacs; i++) {
- if (chs >= (i + 1) * 2) /* independent out */
+ if (i == HDA_REAR && chs == 2) /* copy front to rear */
+ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format);
+ else if (chs >= (i + 1) * 2) /* independent out */
snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2,
format);
- else /* copy front */
- snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0,
- format);
}
return 0;
}
@@ -1714,105 +1717,6 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o
return 0;
}
-/*
- * Helper for automatic ping configuration
- */
-/* parse all pin widgets and store the useful pin nids to cfg */
-int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg)
-{
- hda_nid_t nid, nid_start;
- int i, j, nodes;
- short seq, sequences[4], assoc_line_out;
-
- memset(cfg, 0, sizeof(*cfg));
-
- memset(sequences, 0, sizeof(sequences));
- assoc_line_out = 0;
-
- nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start);
- for (nid = nid_start; nid < nodes + nid_start; nid++) {
- unsigned int wid_caps = snd_hda_param_read(codec, nid,
- AC_PAR_AUDIO_WIDGET_CAP);
- unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
- unsigned int def_conf;
- short assoc, loc;
-
- /* read all default configuration for pin complex */
- if (wid_type != AC_WID_PIN)
- continue;
- def_conf = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
- continue;
- loc = get_defcfg_location(def_conf);
- switch (get_defcfg_device(def_conf)) {
- case AC_JACK_LINE_OUT:
- case AC_JACK_SPEAKER:
- seq = get_defcfg_sequence(def_conf);
- assoc = get_defcfg_association(def_conf);
- if (! assoc)
- continue;
- if (! assoc_line_out)
- assoc_line_out = assoc;
- else if (assoc_line_out != assoc)
- continue;
- if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
- continue;
- cfg->line_out_pins[cfg->line_outs] = nid;
- sequences[cfg->line_outs] = seq;
- cfg->line_outs++;
- break;
- case AC_JACK_HP_OUT:
- cfg->hp_pin = nid;
- break;
- case AC_JACK_MIC_IN:
- if (loc == AC_JACK_LOC_FRONT)
- cfg->input_pins[AUTO_PIN_FRONT_MIC] = nid;
- else
- cfg->input_pins[AUTO_PIN_MIC] = nid;
- break;
- case AC_JACK_LINE_IN:
- if (loc == AC_JACK_LOC_FRONT)
- cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
- else
- cfg->input_pins[AUTO_PIN_LINE] = nid;
- break;
- case AC_JACK_CD:
- cfg->input_pins[AUTO_PIN_CD] = nid;
- break;
- case AC_JACK_AUX:
- cfg->input_pins[AUTO_PIN_AUX] = nid;
- break;
- case AC_JACK_SPDIF_OUT:
- cfg->dig_out_pin = nid;
- break;
- case AC_JACK_SPDIF_IN:
- cfg->dig_in_pin = nid;
- break;
- }
- }
-
- /* sort by sequence */
- for (i = 0; i < cfg->line_outs; i++)
- for (j = i + 1; j < cfg->line_outs; j++)
- if (sequences[i] > sequences[j]) {
- seq = sequences[i];
- sequences[i] = sequences[j];
- sequences[j] = seq;
- nid = cfg->line_out_pins[i];
- cfg->line_out_pins[i] = cfg->line_out_pins[j];
- cfg->line_out_pins[j] = nid;
- }
-
- /* Swap surround and CLFE: the association order is front/CLFE/surr/back */
- if (cfg->line_outs >= 3) {
- nid = cfg->line_out_pins[1];
- cfg->line_out_pins[1] = cfg->line_out_pins[2];
- cfg->line_out_pins[2] = nid;
- }
-
- return 0;
-}
-
#ifdef CONFIG_PM
/*
* power management
diff --git a/trunk/sound/pci/hda/hda_codec.h b/trunk/sound/pci/hda/hda_codec.h
index 59991560d492..c9e9dc9c7c98 100644
--- a/trunk/sound/pci/hda/hda_codec.h
+++ b/trunk/sound/pci/hda/hda_codec.h
@@ -75,9 +75,6 @@ enum {
#define AC_VERB_GET_DIGI_CONVERT 0x0f0d
#define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f
/* f10-f1a: GPIO */
-#define AC_VERB_GET_GPIO_DATA 0x0f15
-#define AC_VERB_GET_GPIO_MASK 0x0f16
-#define AC_VERB_GET_GPIO_DIRECTION 0x0f17
#define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c
/*
@@ -100,9 +97,6 @@ enum {
#define AC_VERB_SET_DIGI_CONVERT_1 0x70d
#define AC_VERB_SET_DIGI_CONVERT_2 0x70e
#define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f
-#define AC_VERB_SET_GPIO_DATA 0x715
-#define AC_VERB_SET_GPIO_MASK 0x716
-#define AC_VERB_SET_GPIO_DIRECTION 0x717
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 0x71c
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e
@@ -182,15 +176,16 @@ enum {
#define AC_PINCAP_OUT (1<<4) /* output capable */
#define AC_PINCAP_IN (1<<5) /* input capable */
#define AC_PINCAP_BALANCE (1<<6) /* balanced I/O capable */
-#define AC_PINCAP_VREF (0x37<<8)
+#define AC_PINCAP_VREF (7<<8)
#define AC_PINCAP_VREF_SHIFT 8
#define AC_PINCAP_EAPD (1<<16) /* EAPD capable */
-/* Vref status (used in pin cap) */
-#define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */
-#define AC_PINCAP_VREF_50 (1<<1) /* 50% */
-#define AC_PINCAP_VREF_GRD (1<<2) /* ground */
-#define AC_PINCAP_VREF_80 (1<<4) /* 80% */
-#define AC_PINCAP_VREF_100 (1<<5) /* 100% */
+/* Vref status (used in pin cap and pin ctl) */
+#define AC_PIN_VREF_HIZ (1<<0) /* Hi-Z */
+#define AC_PIN_VREF_50 (1<<1) /* 50% */
+#define AC_PIN_VREF_GRD (1<<2) /* ground */
+#define AC_PIN_VREF_80 (1<<4) /* 80% */
+#define AC_PIN_VREF_100 (1<<5) /* 100% */
+
/* Amplifier capabilities */
#define AC_AMPCAP_OFFSET (0x7f<<0) /* 0dB offset */
@@ -253,11 +248,6 @@ enum {
/* Pin widget control - 8bit */
#define AC_PINCTL_VREFEN (0x7<<0)
-#define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */
-#define AC_PINCTL_VREF_50 1 /* 50% */
-#define AC_PINCTL_VREF_GRD 2 /* ground */
-#define AC_PINCTL_VREF_80 4 /* 80% */
-#define AC_PINCTL_VREF_100 5 /* 100% */
#define AC_PINCTL_IN_EN (1<<5)
#define AC_PINCTL_OUT_EN (1<<6)
#define AC_PINCTL_HP_EN (1<<7)
@@ -265,9 +255,7 @@ enum {
/* configuration default - 32bit */
#define AC_DEFCFG_SEQUENCE (0xf<<0)
#define AC_DEFCFG_DEF_ASSOC (0xf<<4)
-#define AC_DEFCFG_ASSOC_SHIFT 4
#define AC_DEFCFG_MISC (0xf<<8)
-#define AC_DEFCFG_MISC_SHIFT 8
#define AC_DEFCFG_COLOR (0xf<<12)
#define AC_DEFCFG_COLOR_SHIFT 12
#define AC_DEFCFG_CONN_TYPE (0xf<<16)
@@ -425,7 +413,7 @@ struct hda_bus {
/* codec linked list */
struct list_head codec_list;
- struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; /* caddr -> codec */
+ struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS]; /* caddr -> codec */
struct semaphore cmd_mutex;
diff --git a/trunk/sound/pci/hda/hda_generic.c b/trunk/sound/pci/hda/hda_generic.c
index 2d046abb5911..69f7b6c4cf83 100644
--- a/trunk/sound/pci/hda/hda_generic.c
+++ b/trunk/sound/pci/hda/hda_generic.c
@@ -44,7 +44,7 @@ struct hda_gnode {
struct list_head list;
};
-/* patch-specific record */
+/* pathc-specific record */
struct hda_gspec {
struct hda_gnode *dac_node; /* DAC node */
struct hda_gnode *out_pin_node; /* Output pin (Line-Out) node */
@@ -68,8 +68,8 @@ struct hda_gspec {
/*
* retrieve the default device type from the default config value
*/
-#define defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
-#define defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
+#define get_defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+#define get_defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
/*
* destructor
@@ -323,7 +323,7 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec,
if (! (node->pin_caps & AC_PINCAP_OUT))
continue;
if (jack_type >= 0) {
- if (jack_type != defcfg_type(node))
+ if (jack_type != get_defcfg_type(node))
continue;
if (node->wid_caps & AC_WCAP_DIGITAL)
continue; /* skip SPDIF */
@@ -418,15 +418,15 @@ static int capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
*/
static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl)
{
- unsigned int location = defcfg_location(node);
- switch (defcfg_type(node)) {
+ unsigned int location = get_defcfg_location(node);
+ switch (get_defcfg_type(node)) {
case AC_JACK_LINE_IN:
if ((location & 0x0f) == AC_JACK_LOC_FRONT)
return "Front Line";
return "Line";
case AC_JACK_CD:
if (pinctl)
- *pinctl |= AC_PINCTL_VREF_GRD;
+ *pinctl |= AC_PIN_VREF_GRD;
return "CD";
case AC_JACK_AUX:
if ((location & 0x0f) == AC_JACK_LOC_FRONT)
diff --git a/trunk/sound/pci/hda/hda_intel.c b/trunk/sound/pci/hda/hda_intel.c
index 5e0cca36ed57..959953ca320a 100644
--- a/trunk/sound/pci/hda/hda_intel.c
+++ b/trunk/sound/pci/hda/hda_intel.c
@@ -51,7 +51,6 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
static char *model[SNDRV_CARDS];
-static int position_fix[SNDRV_CARDS];
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -61,17 +60,12 @@ module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
module_param_array(model, charp, NULL, 0444);
MODULE_PARM_DESC(model, "Use the given board model.");
-module_param_array(position_fix, int, NULL, 0444);
-MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF).");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
"{Intel, ICH6M},"
"{Intel, ICH7},"
- "{Intel, ESB2},"
- "{ATI, SB450},"
- "{VIA, VT8251},"
- "{VIA, VT8237A}}");
+ "{Intel, ESB2}}");
MODULE_DESCRIPTION("Intel HDA driver");
#define SFX "hda-intel: "
@@ -156,7 +150,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
/* STATESTS int mask: SD2,SD1,SD0 */
#define STATESTS_INT_MASK 0x07
-#define AZX_MAX_CODECS 4
+#define AZX_MAX_CODECS 3
/* SD_CTL bits */
#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */
@@ -189,18 +183,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define ICH6_MAX_CORB_ENTRIES 256
#define ICH6_MAX_RIRB_ENTRIES 256
-/* position fix mode */
-enum {
- POS_FIX_FIFO,
- POS_FIX_NONE,
- POS_FIX_POSBUF
-};
-
-/* Defines for ATI HD Audio support in SB450 south bridge */
-#define ATI_SB450_HDAUDIO_PCI_DEVICE_ID 0x437b
-#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42
-#define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02
-
/*
* Use CORB/RIRB for communication from/to codecs.
@@ -208,6 +190,12 @@ enum {
*/
#define USE_CORB_RIRB
+/*
+ * Define this if use the position buffer instead of reading SD_LPIB
+ * It's not used as default since SD_LPIB seems to give more accurate position
+ */
+/* #define USE_POSBUF */
+
/*
*/
@@ -283,10 +271,6 @@ struct snd_azx {
struct snd_dma_buffer bdl;
struct snd_dma_buffer rb;
struct snd_dma_buffer posbuf;
-
- /* flags */
- int position_fix;
- unsigned int initialized: 1;
};
/*
@@ -654,7 +638,7 @@ static void azx_stream_stop(azx_t *chip, azx_dev_t *azx_dev)
*/
static void azx_init_chip(azx_t *chip)
{
- unsigned char tcsel_reg, ati_misc_cntl2;
+ unsigned char tcsel_reg;
/* Clear bits 0-2 of PCI register TCSEL (at offset 0x44)
* TCSEL == Traffic Class Select Register, which sets PCI express QOS
@@ -673,20 +657,11 @@ static void azx_init_chip(azx_t *chip)
/* initialize the codec command I/O */
azx_init_cmd_io(chip);
- if (chip->position_fix == POS_FIX_POSBUF) {
- /* program the position buffer */
- azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
- azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
- }
-
- /* For ATI SB450 azalia HD audio, we need to enable snoop */
- if (chip->pci->vendor == PCI_VENDOR_ID_ATI &&
- chip->pci->device == ATI_SB450_HDAUDIO_PCI_DEVICE_ID) {
- pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
- &ati_misc_cntl2);
- pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
- (ati_misc_cntl2 & 0xf8) | ATI_SB450_HDAUDIO_ENABLE_SNOOP);
- }
+#ifdef USE_POSBUF
+ /* program the position buffer */
+ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
+ azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
+#endif
}
@@ -816,12 +791,11 @@ static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev)
/* upper BDL address */
azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
- if (chip->position_fix == POS_FIX_POSBUF) {
- /* enable the position buffer */
- if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
- azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
- }
-
+#ifdef USE_POSBUF
+ /* enable the position buffer */
+ if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
+#endif
/* set the interrupt enable bits in the descriptor control register */
azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);
@@ -1062,20 +1036,16 @@ static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream)
{
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- azx_t *chip = apcm->chip;
azx_dev_t *azx_dev = get_azx_dev(substream);
unsigned int pos;
- if (chip->position_fix == POS_FIX_POSBUF) {
- /* use the position buffer */
- pos = *azx_dev->posbuf;
- } else {
- /* read LPIB */
- pos = azx_sd_readl(azx_dev, SD_LPIB);
- if (chip->position_fix == POS_FIX_FIFO)
- pos += azx_dev->fifo_size;
- }
+#ifdef USE_POSBUF
+ /* use the position buffer */
+ pos = *azx_dev->posbuf;
+#else
+ /* read LPIB */
+ pos = azx_sd_readl(azx_dev, SD_LPIB) + azx_dev->fifo_size;
+#endif
if (pos >= azx_dev->bufsize)
pos = 0;
return bytes_to_frames(substream->runtime, pos);
@@ -1185,8 +1155,9 @@ static int __devinit azx_init_stream(azx_t *chip)
azx_dev_t *azx_dev = &chip->azx_dev[i];
azx_dev->bdl = (u32 *)(chip->bdl.area + off);
azx_dev->bdl_addr = chip->bdl.addr + off;
- if (chip->position_fix == POS_FIX_POSBUF)
- azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
+#ifdef USE_POSBUF
+ azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
+#endif
/* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
/* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
@@ -1236,7 +1207,7 @@ static int azx_resume(snd_card_t *card)
*/
static int azx_free(azx_t *chip)
{
- if (chip->initialized) {
+ if (chip->remap_addr) {
int i;
for (i = 0; i < MAX_ICH6_DEV; i++)
@@ -1266,8 +1237,10 @@ static int azx_free(azx_t *chip)
snd_dma_free_pages(&chip->bdl);
if (chip->rb.area)
snd_dma_free_pages(&chip->rb);
+#ifdef USE_POSBUF
if (chip->posbuf.area)
snd_dma_free_pages(&chip->posbuf);
+#endif
pci_release_regions(chip->pci);
pci_disable_device(chip->pci);
kfree(chip);
@@ -1283,8 +1256,7 @@ static int azx_dev_free(snd_device_t *device)
/*
* constructor
*/
-static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
- int posfix, azx_t **rchip)
+static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **rchip)
{
azx_t *chip;
int err = 0;
@@ -1311,8 +1283,6 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
chip->pci = pci;
chip->irq = -1;
- chip->position_fix = posfix;
-
if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) {
kfree(chip);
pci_disable_device(pci);
@@ -1344,14 +1314,14 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
goto errout;
}
- if (chip->position_fix == POS_FIX_POSBUF) {
- /* allocate memory for the position buffer */
- if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
- MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) {
- snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
- goto errout;
- }
+#ifdef USE_POSBUF
+ /* allocate memory for the position buffer */
+ if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+ MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) {
+ snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
+ goto errout;
}
+#endif
/* allocate CORB/RIRB */
if ((err = azx_alloc_cmd_io(chip)) < 0)
goto errout;
@@ -1362,8 +1332,6 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
/* initialize chip */
azx_init_chip(chip);
- chip->initialized = 1;
-
/* codec detection */
if (! chip->codec_mask) {
snd_printk(KERN_ERR SFX "no codecs found!\n");
@@ -1404,7 +1372,7 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *
return -ENOMEM;
}
- if ((err = azx_create(card, pci, position_fix[dev], &chip)) < 0) {
+ if ((err = azx_create(card, pci, &chip)) < 0) {
snd_card_free(card);
return err;
}
@@ -1456,9 +1424,6 @@ static struct pci_device_id azx_ids[] = {
{ 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH6 */
{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH7 */
{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ESB2 */
- { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ATI SB450 */
- { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* VIA VT8251/VT8237A */
- { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ALI 5461? */
{ 0, }
};
MODULE_DEVICE_TABLE(pci, azx_ids);
@@ -1474,7 +1439,7 @@ static struct pci_driver driver = {
static int __init alsa_card_azx_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_azx_exit(void)
diff --git a/trunk/sound/pci/hda/hda_local.h b/trunk/sound/pci/hda/hda_local.h
index 810cfd2d9bba..7c7b849875a0 100644
--- a/trunk/sound/pci/hda/hda_local.h
+++ b/trunk/sound/pci/hda/hda_local.h
@@ -126,11 +126,11 @@ static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; }
struct hda_board_config {
const char *modelname;
int config;
- unsigned short pci_subvendor;
- unsigned short pci_subdevice;
+ unsigned short pci_vendor;
+ unsigned short pci_device;
};
-int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl);
+int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl);
int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew);
/*
@@ -158,35 +158,4 @@ struct hda_bus_unsolicited {
struct work_struct work;
};
-/*
- * Helper for automatic ping configuration
- */
-
-enum {
- AUTO_PIN_MIC,
- AUTO_PIN_FRONT_MIC,
- AUTO_PIN_LINE,
- AUTO_PIN_FRONT_LINE,
- AUTO_PIN_CD,
- AUTO_PIN_AUX,
- AUTO_PIN_LAST
-};
-
-struct auto_pin_cfg {
- int line_outs;
- hda_nid_t line_out_pins[4]; /* sorted in the order of Front/Surr/CLFE/Side */
- hda_nid_t hp_pin;
- hda_nid_t input_pins[AUTO_PIN_LAST];
- hda_nid_t dig_out_pin;
- hda_nid_t dig_in_pin;
-};
-
-#define get_defcfg_connect(cfg) ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT)
-#define get_defcfg_association(cfg) ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT)
-#define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
-#define get_defcfg_sequence(cfg) (cfg & AC_DEFCFG_SEQUENCE)
-#define get_defcfg_device(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
-
-int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg);
-
#endif /* __SOUND_HDA_LOCAL_H */
diff --git a/trunk/sound/pci/hda/hda_patch.h b/trunk/sound/pci/hda/hda_patch.h
index a5de684b6944..cf6abce42bc9 100644
--- a/trunk/sound/pci/hda/hda_patch.h
+++ b/trunk/sound/pci/hda/hda_patch.h
@@ -8,13 +8,10 @@ extern struct hda_codec_preset snd_hda_preset_realtek[];
extern struct hda_codec_preset snd_hda_preset_cmedia[];
/* Analog Devices codecs */
extern struct hda_codec_preset snd_hda_preset_analog[];
-/* SigmaTel codecs */
-extern struct hda_codec_preset snd_hda_preset_sigmatel[];
static const struct hda_codec_preset *hda_preset_tables[] = {
snd_hda_preset_realtek,
snd_hda_preset_cmedia,
snd_hda_preset_analog,
- snd_hda_preset_sigmatel,
NULL
};
diff --git a/trunk/sound/pci/hda/hda_proc.c b/trunk/sound/pci/hda/hda_proc.c
index de1217bd8e68..4d5db7faad8d 100644
--- a/trunk/sound/pci/hda/hda_proc.c
+++ b/trunk/sound/pci/hda/hda_proc.c
@@ -68,27 +68,21 @@ static void print_amp_caps(snd_info_buffer_t *buffer,
static void print_amp_vals(snd_info_buffer_t *buffer,
struct hda_codec *codec, hda_nid_t nid,
- int dir, int stereo, int indices)
+ int dir, int stereo)
{
unsigned int val;
- int i;
-
- if (dir == HDA_OUTPUT)
- dir = AC_AMP_GET_OUTPUT;
- else
- dir = AC_AMP_GET_INPUT;
- for (i = 0; i < indices; i++) {
- snd_iprintf(buffer, " [");
- if (stereo) {
- val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
- AC_AMP_GET_LEFT | dir | i);
- snd_iprintf(buffer, "0x%02x ", val);
- }
+ if (stereo) {
val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
- AC_AMP_GET_RIGHT | dir | i);
- snd_iprintf(buffer, "0x%02x]", val);
+ AC_AMP_GET_LEFT |
+ (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT :
+ AC_AMP_GET_INPUT));
+ snd_iprintf(buffer, "0x%02x ", val);
}
- snd_iprintf(buffer, "\n");
+ val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
+ AC_AMP_GET_RIGHT |
+ (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT :
+ AC_AMP_GET_INPUT));
+ snd_iprintf(buffer, "0x%02x\n", val);
}
static void print_pcm_caps(snd_info_buffer_t *buffer,
@@ -163,7 +157,6 @@ static const char *get_jack_color(u32 cfg)
static void print_pin_caps(snd_info_buffer_t *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
- static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" };
static char *jack_types[16] = {
"Line Out", "Speaker", "HP Out", "CD",
"SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
@@ -183,8 +176,7 @@ static void print_pin_caps(snd_info_buffer_t *buffer,
snd_iprintf(buffer, " HP");
snd_iprintf(buffer, "\n");
caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps,
- jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT],
+ snd_iprintf(buffer, " Pin Default 0x%08x: %s at %s %s\n", caps,
jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT],
jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3],
get_jack_location(caps));
@@ -223,9 +215,6 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
unsigned int wid_caps = snd_hda_param_read(codec, nid,
AC_PAR_AUDIO_WIDGET_CAP);
unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
- int conn_len = 0;
- hda_nid_t conn[HDA_MAX_CONNECTIONS];
-
snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid,
get_wid_type_name(wid_type), wid_caps);
if (wid_caps & AC_WCAP_STEREO)
@@ -240,23 +229,19 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
snd_iprintf(buffer, " Amp-Out");
snd_iprintf(buffer, "\n");
- if (wid_caps & AC_WCAP_CONN_LIST)
- conn_len = snd_hda_get_connections(codec, nid, conn,
- HDA_MAX_CONNECTIONS);
-
if (wid_caps & AC_WCAP_IN_AMP) {
snd_iprintf(buffer, " Amp-In caps: ");
print_amp_caps(buffer, codec, nid, HDA_INPUT);
snd_iprintf(buffer, " Amp-In vals: ");
print_amp_vals(buffer, codec, nid, HDA_INPUT,
- wid_caps & AC_WCAP_STEREO, conn_len);
+ wid_caps & AC_WCAP_STEREO);
}
if (wid_caps & AC_WCAP_OUT_AMP) {
snd_iprintf(buffer, " Amp-Out caps: ");
print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
snd_iprintf(buffer, " Amp-Out vals: ");
print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
- wid_caps & AC_WCAP_STEREO, 1);
+ wid_caps & AC_WCAP_STEREO);
}
if (wid_type == AC_WID_PIN) {
@@ -280,17 +265,14 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
}
if (wid_caps & AC_WCAP_CONN_LIST) {
- int c, curr = -1;
- if (conn_len > 1 && wid_type != AC_WID_AUD_MIX)
- curr = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONNECT_SEL, 0);
+ hda_nid_t conn[HDA_MAX_CONNECTIONS];
+ int c, conn_len;
+ conn_len = snd_hda_get_connections(codec, nid, conn,
+ HDA_MAX_CONNECTIONS);
snd_iprintf(buffer, " Connection: %d\n", conn_len);
snd_iprintf(buffer, " ");
- for (c = 0; c < conn_len; c++) {
+ for (c = 0; c < conn_len; c++)
snd_iprintf(buffer, " 0x%02x", conn[c]);
- if (c == curr)
- snd_iprintf(buffer, "*");
- }
snd_iprintf(buffer, "\n");
}
}
diff --git a/trunk/sound/pci/hda/patch_analog.c b/trunk/sound/pci/hda/patch_analog.c
index 2fd05bb84136..75d23849f71a 100644
--- a/trunk/sound/pci/hda/patch_analog.c
+++ b/trunk/sound/pci/hda/patch_analog.c
@@ -1,5 +1,5 @@
/*
- * HD audio interface patch for AD1981HD, AD1983, AD1986A
+ * HD audio interface patch for AD1986A
*
* Copyright (c) 2005 Takashi Iwai
*
@@ -27,239 +27,13 @@
#include "hda_codec.h"
#include "hda_local.h"
-struct ad198x_spec {
+struct ad1986a_spec {
struct semaphore amp_mutex; /* PCM volume/mute control mutex */
struct hda_multi_out multiout; /* playback */
- hda_nid_t adc_nid;
- const struct hda_input_mux *input_mux;
unsigned int cur_mux; /* capture source */
- unsigned int spdif_route;
- snd_kcontrol_new_t *mixers;
- const struct hda_verb *init_verbs;
struct hda_pcm pcm_rec[2]; /* PCM information */
};
-/*
- * input MUX handling (common part)
- */
-static int ad198x_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *spec = codec->spec;
-
- return snd_hda_input_mux_info(spec->input_mux, uinfo);
-}
-
-static int ad198x_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->cur_mux;
- return 0;
-}
-
-static int ad198x_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *spec = codec->spec;
-
- return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
- spec->adc_nid, &spec->cur_mux);
-}
-
-/*
- * initialization (common callbacks)
- */
-static int ad198x_init(struct hda_codec *codec)
-{
- struct ad198x_spec *spec = codec->spec;
- snd_hda_sequence_write(codec, spec->init_verbs);
- return 0;
-}
-
-static int ad198x_build_controls(struct hda_codec *codec)
-{
- struct ad198x_spec *spec = codec->spec;
- int err;
-
- err = snd_hda_add_new_ctls(codec, spec->mixers);
- if (err < 0)
- return err;
- if (spec->multiout.dig_out_nid)
- err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
- if (err < 0)
- return err;
- return 0;
-}
-
-/*
- * Analog playback callbacks
- */
-static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct ad198x_spec *spec = codec->spec;
- return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
-}
-
-static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- snd_pcm_substream_t *substream)
-{
- struct ad198x_spec *spec = codec->spec;
- return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
- format, substream);
-}
-
-static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct ad198x_spec *spec = codec->spec;
- return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
-}
-
-/*
- * Digital out
- */
-static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct ad198x_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct ad198x_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-/*
- * Analog capture
- */
-static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- snd_pcm_substream_t *substream)
-{
- struct ad198x_spec *spec = codec->spec;
- snd_hda_codec_setup_stream(codec, spec->adc_nid, stream_tag, 0, format);
- return 0;
-}
-
-static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct ad198x_spec *spec = codec->spec;
- snd_hda_codec_setup_stream(codec, spec->adc_nid, 0, 0, 0);
- return 0;
-}
-
-
-/*
- */
-static struct hda_pcm_stream ad198x_pcm_analog_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 6,
- .nid = 0, /* fill later */
- .ops = {
- .open = ad198x_playback_pcm_open,
- .prepare = ad198x_playback_pcm_prepare,
- .cleanup = ad198x_playback_pcm_cleanup
- },
-};
-
-static struct hda_pcm_stream ad198x_pcm_analog_capture = {
- .substreams = 2,
- .channels_min = 2,
- .channels_max = 2,
- .nid = 0, /* fill later */
- .ops = {
- .prepare = ad198x_capture_pcm_prepare,
- .cleanup = ad198x_capture_pcm_cleanup
- },
-};
-
-static struct hda_pcm_stream ad198x_pcm_digital_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- .nid = 0, /* fill later */
- .ops = {
- .open = ad198x_dig_playback_pcm_open,
- .close = ad198x_dig_playback_pcm_close
- },
-};
-
-static int ad198x_build_pcms(struct hda_codec *codec)
-{
- struct ad198x_spec *spec = codec->spec;
- struct hda_pcm *info = spec->pcm_rec;
-
- codec->num_pcms = 1;
- codec->pcm_info = info;
-
- info->name = "AD198x Analog";
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
- info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nid;
-
- if (spec->multiout.dig_out_nid) {
- info++;
- codec->num_pcms++;
- info->name = "AD198x Digital";
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
- }
-
- return 0;
-}
-
-static void ad198x_free(struct hda_codec *codec)
-{
- kfree(codec->spec);
-}
-
-#ifdef CONFIG_PM
-static int ad198x_resume(struct hda_codec *codec)
-{
- struct ad198x_spec *spec = codec->spec;
-
- ad198x_init(codec);
- snd_hda_resume_ctls(codec, spec->mixers);
- snd_hda_resume_spdif_out(codec);
- return 0;
-}
-#endif
-
-static struct hda_codec_ops ad198x_patch_ops = {
- .build_controls = ad198x_build_controls,
- .build_pcms = ad198x_build_pcms,
- .init = ad198x_init,
- .free = ad198x_free,
-#ifdef CONFIG_PM
- .resume = ad198x_resume,
-#endif
-};
-
-
-/*
- * AD1986A specific
- */
-
#define AD1986A_SPDIF_OUT 0x02
#define AD1986A_FRONT_DAC 0x03
#define AD1986A_SURR_DAC 0x04
@@ -294,7 +68,7 @@ static struct hda_input_mux ad1986a_capture_source = {
static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *ad = codec->spec;
+ struct ad1986a_spec *ad = codec->spec;
down(&ad->amp_mutex);
snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
@@ -305,7 +79,7 @@ static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *ad = codec->spec;
+ struct ad1986a_spec *ad = codec->spec;
int i, change = 0;
down(&ad->amp_mutex);
@@ -318,12 +92,12 @@ static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
return change;
}
-#define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info
+#define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_volume_info
static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *ad = codec->spec;
+ struct ad1986a_spec *ad = codec->spec;
down(&ad->amp_mutex);
snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
@@ -334,7 +108,7 @@ static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *ad = codec->spec;
+ struct ad1986a_spec *ad = codec->spec;
int i, change = 0;
down(&ad->amp_mutex);
@@ -347,6 +121,32 @@ static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return change;
}
+/*
+ * input MUX handling
+ */
+static int ad1986a_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ return snd_hda_input_mux_info(&ad1986a_capture_source, uinfo);
+}
+
+static int ad1986a_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad1986a_spec *spec = codec->spec;
+
+ ucontrol->value.enumerated.item[0] = spec->cur_mux;
+ return 0;
+}
+
+static int ad1986a_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad1986a_spec *spec = codec->spec;
+
+ return snd_hda_input_mux_put(codec, &ad1986a_capture_source, ucontrol,
+ AD1986A_ADC, &spec->cur_mux);
+}
+
/*
* mixers
*/
@@ -394,9 +194,9 @@ static snd_kcontrol_new_t ad1986a_mixers[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
- .info = ad198x_mux_enum_info,
- .get = ad198x_mux_enum_get,
- .put = ad198x_mux_enum_put,
+ .info = ad1986a_mux_enum_info,
+ .get = ad1986a_mux_enum_get,
+ .put = ad1986a_mux_enum_put,
},
HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
{ } /* end */
@@ -441,328 +241,183 @@ static struct hda_verb ad1986a_init_verbs[] = {
{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- /* HP Pin */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
- /* Front, Surround, CLFE Pins */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* Mono Pin */
- {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* Mic Pin */
- {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- /* Line, Aux, CD, Beep-In Pin */
- {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
{ } /* end */
};
-static int patch_ad1986a(struct hda_codec *codec)
+static int ad1986a_init(struct hda_codec *codec)
{
- struct ad198x_spec *spec;
-
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- init_MUTEX(&spec->amp_mutex);
- codec->spec = spec;
-
- spec->multiout.max_channels = 6;
- spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
- spec->multiout.dac_nids = ad1986a_dac_nids;
- spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
- spec->adc_nid = AD1986A_ADC;
- spec->input_mux = &ad1986a_capture_source;
- spec->mixers = ad1986a_mixers;
- spec->init_verbs = ad1986a_init_verbs;
+ snd_hda_sequence_write(codec, ad1986a_init_verbs);
+ return 0;
+}
- codec->patch_ops = ad198x_patch_ops;
+static int ad1986a_build_controls(struct hda_codec *codec)
+{
+ int err;
+ err = snd_hda_add_new_ctls(codec, ad1986a_mixers);
+ if (err < 0)
+ return err;
+ err = snd_hda_create_spdif_out_ctls(codec, AD1986A_SPDIF_OUT);
+ if (err < 0)
+ return err;
return 0;
}
/*
- * AD1983 specific
+ * Analog playback callbacks
*/
+static int ad1986a_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
-#define AD1983_SPDIF_OUT 0x02
-#define AD1983_DAC 0x03
-#define AD1983_ADC 0x04
-
-static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
+static int ad1986a_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ snd_pcm_substream_t *substream)
+{
+ struct ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+ format, substream);
+}
-static struct hda_input_mux ad1983_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x1 },
- { "Mix", 0x2 },
- { "Mix Mono", 0x3 },
- },
-};
+static int ad1986a_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
/*
- * SPDIF playback route
+ * Digital out
*/
-static int ad1983_spdif_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int ad1986a_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
{
- static char *texts[] = { "PCM", "ADC" };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 2;
- if (uinfo->value.enumerated.item > 1)
- uinfo->value.enumerated.item = 1;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
+ struct ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_open(codec, &spec->multiout);
}
-static int ad1983_spdif_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int ad1986a_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *spec = codec->spec;
+ struct ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
- ucontrol->value.enumerated.item[0] = spec->spdif_route;
+/*
+ * Analog capture
+ */
+static int ad1986a_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ snd_pcm_substream_t *substream)
+{
+ snd_hda_codec_setup_stream(codec, AD1986A_ADC, stream_tag, 0, format);
return 0;
}
-static int ad1983_spdif_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int ad1986a_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad198x_spec *spec = codec->spec;
-
- if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
- spec->spdif_route = ucontrol->value.enumerated.item[0];
- snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0,
- AC_VERB_SET_CONNECT_SEL, spec->spdif_route);
- return 1;
- }
+ snd_hda_codec_setup_stream(codec, AD1986A_ADC, 0, 0, 0);
return 0;
}
-static snd_kcontrol_new_t ad1983_mixers[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .info = ad198x_mux_enum_info,
- .get = ad198x_mux_enum_get,
- .put = ad198x_mux_enum_put,
+
+/*
+ */
+static struct hda_pcm_stream ad1986a_pcm_analog_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 6,
+ .nid = AD1986A_FRONT_DAC, /* NID to query formats and rates */
+ .ops = {
+ .open = ad1986a_playback_pcm_open,
+ .prepare = ad1986a_playback_pcm_prepare,
+ .cleanup = ad1986a_playback_pcm_cleanup
},
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Playback Route",
- .info = ad1983_spdif_route_info,
- .get = ad1983_spdif_route_get,
- .put = ad1983_spdif_route_put,
+};
+
+static struct hda_pcm_stream ad1986a_pcm_analog_capture = {
+ .substreams = 2,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = AD1986A_ADC, /* NID to query formats and rates */
+ .ops = {
+ .prepare = ad1986a_capture_pcm_prepare,
+ .cleanup = ad1986a_capture_pcm_cleanup
},
- { } /* end */
};
-static struct hda_verb ad1983_init_verbs[] = {
- /* Front, HP, Mono; mute as default */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- /* Beep, PCM, Mic, Line-In: mute */
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- /* Front, HP selectors; from Mix */
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* Mono selector; from Mix */
- {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
- /* Mic selector; Mic */
- {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
- /* Line-in selector: Line-in */
- {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
- /* Mic boost: 0dB */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* Record selector: mic */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- /* SPDIF route: PCM */
- {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
- /* Front Pin */
- {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* HP Pin */
- {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
- /* Mono Pin */
- {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* Mic Pin */
- {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- /* Line Pin */
- {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- { } /* end */
+static struct hda_pcm_stream ad1986a_pcm_digital_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = AD1986A_SPDIF_OUT,
+ .ops = {
+ .open = ad1986a_dig_playback_pcm_open,
+ .close = ad1986a_dig_playback_pcm_close
+ },
};
-static int patch_ad1983(struct hda_codec *codec)
+static int ad1986a_build_pcms(struct hda_codec *codec)
{
- struct ad198x_spec *spec;
-
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
+ struct ad1986a_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
- init_MUTEX(&spec->amp_mutex);
- codec->spec = spec;
+ codec->num_pcms = 2;
+ codec->pcm_info = info;
- spec->multiout.max_channels = 2;
- spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
- spec->multiout.dac_nids = ad1983_dac_nids;
- spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
- spec->adc_nid = AD1983_ADC;
- spec->input_mux = &ad1983_capture_source;
- spec->mixers = ad1983_mixers;
- spec->init_verbs = ad1983_init_verbs;
- spec->spdif_route = 0;
+ info->name = "AD1986A Analog";
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_analog_playback;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1986a_pcm_analog_capture;
+ info++;
- codec->patch_ops = ad198x_patch_ops;
+ info->name = "AD1986A Digital";
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_digital_playback;
return 0;
}
+static void ad1986a_free(struct hda_codec *codec)
+{
+ kfree(codec->spec);
+}
-/*
- * AD1981 HD specific
- */
-
-#define AD1981_SPDIF_OUT 0x02
-#define AD1981_DAC 0x03
-#define AD1981_ADC 0x04
-
-static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
-
-/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
-static struct hda_input_mux ad1981_capture_source = {
- .num_items = 7,
- .items = {
- { "Front Mic", 0x0 },
- { "Line", 0x1 },
- { "Mix", 0x2 },
- { "Mix Mono", 0x3 },
- { "CD", 0x4 },
- { "Mic", 0x6 },
- { "Aux", 0x7 },
- },
-};
-
-static snd_kcontrol_new_t ad1981_mixers[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .info = ad198x_mux_enum_info,
- .get = ad198x_mux_enum_get,
- .put = ad198x_mux_enum_put,
- },
- /* identical with AD1983 */
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "IEC958 Playback Route",
- .info = ad1983_spdif_route_info,
- .get = ad1983_spdif_route_get,
- .put = ad1983_spdif_route_put,
- },
- { } /* end */
-};
+#ifdef CONFIG_PM
+static int ad1986a_resume(struct hda_codec *codec)
+{
+ ad1986a_init(codec);
+ snd_hda_resume_ctls(codec, ad1986a_mixers);
+ snd_hda_resume_spdif_out(codec);
+ return 0;
+}
+#endif
-static struct hda_verb ad1981_init_verbs[] = {
- /* Front, HP, Mono; mute as default */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- /* Front, HP selectors; from Mix */
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* Mono selector; from Mix */
- {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
- /* Mic Mixer; select Front Mic */
- {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- /* Mic boost: 0dB */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* Record selector: Front mic */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- /* SPDIF route: PCM */
- {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
- /* Front Pin */
- {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* HP Pin */
- {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
- /* Mono Pin */
- {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* Front & Rear Mic Pins */
- {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- /* Line Pin */
- {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- /* Digital Beep */
- {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Line-Out as Input: disabled */
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- { } /* end */
+static struct hda_codec_ops ad1986a_patch_ops = {
+ .build_controls = ad1986a_build_controls,
+ .build_pcms = ad1986a_build_pcms,
+ .init = ad1986a_init,
+ .free = ad1986a_free,
+#ifdef CONFIG_PM
+ .resume = ad1986a_resume,
+#endif
};
-static int patch_ad1981(struct hda_codec *codec)
+static int patch_ad1986a(struct hda_codec *codec)
{
- struct ad198x_spec *spec;
+ struct ad1986a_spec *spec;
spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -771,28 +426,20 @@ static int patch_ad1981(struct hda_codec *codec)
init_MUTEX(&spec->amp_mutex);
codec->spec = spec;
- spec->multiout.max_channels = 2;
- spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
- spec->multiout.dac_nids = ad1981_dac_nids;
- spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
- spec->adc_nid = AD1981_ADC;
- spec->input_mux = &ad1981_capture_source;
- spec->mixers = ad1981_mixers;
- spec->init_verbs = ad1981_init_verbs;
- spec->spdif_route = 0;
+ spec->multiout.max_channels = 6;
+ spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
+ spec->multiout.dac_nids = ad1986a_dac_nids;
+ spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
- codec->patch_ops = ad198x_patch_ops;
+ codec->patch_ops = ad1986a_patch_ops;
return 0;
}
-
/*
* patch entries
*/
struct hda_codec_preset snd_hda_preset_analog[] = {
- { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
- { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
{ .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
{} /* terminator */
};
diff --git a/trunk/sound/pci/hda/patch_cmedia.c b/trunk/sound/pci/hda/patch_cmedia.c
index 2d6e3e3d0a38..b7cc8e4bffb7 100644
--- a/trunk/sound/pci/hda/patch_cmedia.c
+++ b/trunk/sound/pci/hda/patch_cmedia.c
@@ -29,7 +29,6 @@
#include
#include "hda_codec.h"
#include "hda_local.h"
-#define NUM_PINS 11
/* board config type */
@@ -39,7 +38,6 @@ enum {
CMI_FULL, /* back 6-jack + front-panel 2-jack */
CMI_FULL_DIG, /* back 6-jack + front-panel 2-jack + digital I/O */
CMI_ALLOUT, /* back 5-jack + front-panel 2-jack + digital out */
- CMI_AUTO, /* let driver guess it */
};
struct cmi_spec {
@@ -50,8 +48,6 @@ struct cmi_spec {
/* playback */
struct hda_multi_out multiout;
- hda_nid_t dac_nids[4]; /* NID for each DAC */
- int num_dacs;
/* capture */
hda_nid_t *adc_nids;
@@ -67,30 +63,8 @@ struct cmi_spec {
const struct cmi_channel_mode *channel_modes;
struct hda_pcm pcm_rec[2]; /* PCM information */
-
- /* pin deafault configuration */
- hda_nid_t pin_nid[NUM_PINS];
- unsigned int def_conf[NUM_PINS];
- unsigned int pin_def_confs;
-
- /* multichannel pins */
- hda_nid_t multich_pin[4]; /* max 8-channel */
- struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */
};
-/* amp values */
-#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
-#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
-#define AMP_OUT_MUTE 0xb080
-#define AMP_OUT_UNMUTE 0xb000
-#define AMP_OUT_ZERO 0xb000
-/* pinctl values */
-#define PIN_IN 0x20
-#define PIN_VREF80 0x24
-#define PIN_VREF50 0x21
-#define PIN_OUT 0x40
-#define PIN_HP 0xc0
-
/*
* input MUX
*/
@@ -128,9 +102,9 @@ static int cmi_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
/* 3-stack / 2 channel */
static struct hda_verb cmi9880_ch2_init[] = {
/* set line-in PIN for input */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
/* set mic PIN for input, also enable vref */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
/* route front PCM (DAC1) to HP */
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
{}
@@ -139,9 +113,9 @@ static struct hda_verb cmi9880_ch2_init[] = {
/* 3-stack / 6 channel */
static struct hda_verb cmi9880_ch6_init[] = {
/* set line-in PIN for output */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
/* set mic PIN for output */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
/* route front PCM (DAC1) to HP */
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
{}
@@ -150,9 +124,9 @@ static struct hda_verb cmi9880_ch6_init[] = {
/* 3-stack+front / 8 channel */
static struct hda_verb cmi9880_ch8_init[] = {
/* set line-in PIN for output */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
/* set mic PIN for output */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
/* route rear-surround PCM (DAC4) to HP */
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 },
{}
@@ -295,27 +269,25 @@ static hda_nid_t cmi9880_adc_nids[2] = {
*/
static struct hda_verb cmi9880_basic_init[] = {
/* port-D for line out (rear panel) */
- { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+ { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
/* port-E for HP out (front panel) */
- { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+ { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
/* route front PCM to HP */
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
/* port-A for surround (rear panel) */
- { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+ { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
/* port-G for CLFE (rear panel) */
- { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
- { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
+ { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
/* port-H for side (rear panel) */
- { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
- { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
+ { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
/* port-C for line-in (rear panel) */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
/* port-B for mic-in (rear panel) with vref */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
/* port-F for mic-in (front panel) with vref */
- { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+ { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
/* CD-in */
- { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+ { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
/* route front mic to ADC1/2 */
{ 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
{ 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
@@ -324,27 +296,23 @@ static struct hda_verb cmi9880_basic_init[] = {
static struct hda_verb cmi9880_allout_init[] = {
/* port-D for line out (rear panel) */
- { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+ { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
/* port-E for HP out (front panel) */
- { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+ { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
/* route front PCM to HP */
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
/* port-A for side (rear panel) */
- { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+ { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
/* port-G for CLFE (rear panel) */
- { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
- { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
- /* port-H for side (rear panel) */
- { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
- { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
+ { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
/* port-C for surround (rear panel) */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
/* port-B for mic-in (rear panel) with vref */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
/* port-F for mic-in (front panel) with vref */
- { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+ { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
/* CD-in */
- { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+ { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
/* route front mic to ADC1/2 */
{ 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
{ 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
@@ -379,81 +347,6 @@ static int cmi9880_build_controls(struct hda_codec *codec)
return 0;
}
-/* fill in the multi_dac_nids table, which will decide
- which audio widget to use for each channel */
-static int cmi9880_fill_multi_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
-{
- struct cmi_spec *spec = codec->spec;
- hda_nid_t nid;
- int assigned[4];
- int i, j;
-
- /* clear the table, only one c-media dac assumed here */
- memset(spec->dac_nids, 0, sizeof(spec->dac_nids));
- memset(assigned, 0, sizeof(assigned));
- /* check the pins we found */
- for (i = 0; i < cfg->line_outs; i++) {
- nid = cfg->line_out_pins[i];
- /* nid 0x0b~0x0e is hardwired to audio widget 0x3~0x6 */
- if (nid >= 0x0b && nid <= 0x0e) {
- spec->dac_nids[i] = (nid - 0x0b) + 0x03;
- assigned[nid - 0x0b] = 1;
- }
- }
- /* left pin can be connect to any audio widget */
- for (i = 0; i < cfg->line_outs; i++) {
- nid = cfg->line_out_pins[i];
- if (nid <= 0x0e)
- continue;
- /* search for an empty channel */
- for (j = 0; j < cfg->line_outs; j++) {
- if (! assigned[j]) {
- spec->dac_nids[i] = i + 0x03;
- assigned[j] = 1;
- break;
- }
- }
- }
- spec->num_dacs = cfg->line_outs;
- return 0;
-}
-
-/* create multi_init table, which is used for multichannel initialization */
-static int cmi9880_fill_multi_init(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
-{
- struct cmi_spec *spec = codec->spec;
- hda_nid_t nid;
- int i, j, k, len;
-
- /* clear the table, only one c-media dac assumed here */
- memset(spec->multi_init, 0, sizeof(spec->multi_init));
- for (j = 0, i = 0; i < cfg->line_outs; i++) {
- hda_nid_t conn[4];
- nid = cfg->line_out_pins[i];
- /* set as output */
- spec->multi_init[j].nid = nid;
- spec->multi_init[j].verb = AC_VERB_SET_PIN_WIDGET_CONTROL;
- spec->multi_init[j].param = PIN_OUT;
- j++;
- if (nid > 0x0e) {
- /* set connection */
- spec->multi_init[j].nid = nid;
- spec->multi_init[j].verb = AC_VERB_SET_CONNECT_SEL;
- spec->multi_init[j].param = 0;
- /* find the index in connect list */
- len = snd_hda_get_connections(codec, nid, conn, 4);
- for (k = 0; k < len; k++)
- if (conn[k] == spec->dac_nids[i]) {
- spec->multi_init[j].param = j;
- break;
- }
- j++;
- break;
- }
- }
- return 0;
-}
-
static int cmi9880_init(struct hda_codec *codec)
{
struct cmi_spec *spec = codec->spec;
@@ -461,8 +354,6 @@ static int cmi9880_init(struct hda_codec *codec)
snd_hda_sequence_write(codec, cmi9880_allout_init);
else
snd_hda_sequence_write(codec, cmi9880_basic_init);
- if (spec->board_config == CMI_AUTO)
- snd_hda_sequence_write(codec, spec->multi_init);
return 0;
}
@@ -649,7 +540,6 @@ static struct hda_board_config cmi9880_cfg_tbl[] = {
{ .modelname = "full", .config = CMI_FULL },
{ .modelname = "full_dig", .config = CMI_FULL_DIG },
{ .modelname = "allout", .config = CMI_ALLOUT },
- { .modelname = "auto", .config = CMI_AUTO },
{} /* terminator */
};
@@ -674,14 +564,10 @@ static int patch_cmi9880(struct hda_codec *codec)
codec->spec = spec;
spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl);
if (spec->board_config < 0) {
- snd_printdd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
- spec->board_config = CMI_AUTO; /* try everything */
+ snd_printd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
+ spec->board_config = CMI_FULL_DIG; /* try everything */
}
- /* copy default DAC NIDs */
- memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids));
- spec->num_dacs = 4;
-
switch (spec->board_config) {
case CMI_MINIMAL:
case CMI_MIN_FP:
@@ -713,58 +599,10 @@ static int patch_cmi9880(struct hda_codec *codec)
spec->input_mux = &cmi9880_no_line_mux;
spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
break;
- case CMI_AUTO:
- {
- unsigned int port_e, port_f, port_g, port_h;
- unsigned int port_spdifi, port_spdifo;
- struct auto_pin_cfg cfg;
-
- /* collect pin default configuration */
- port_e = snd_hda_codec_read(codec, 0x0f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- port_f = snd_hda_codec_read(codec, 0x10, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- spec->front_panel = 1;
- if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE ||
- get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) {
- port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- spec->surr_switch = 1;
- /* no front panel */
- if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE ||
- get_defcfg_connect(port_h) == AC_JACK_PORT_NONE) {
- /* no optional rear panel */
- spec->board_config = CMI_MINIMAL;
- spec->front_panel = 0;
- spec->num_ch_modes = 2;
- } else {
- spec->board_config = CMI_MIN_FP;
- spec->num_ch_modes = 3;
- }
- spec->channel_modes = cmi9880_channel_modes;
- spec->input_mux = &cmi9880_basic_mux;
- spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
- } else {
- spec->input_mux = &cmi9880_basic_mux;
- port_spdifi = snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- port_spdifo = snd_hda_codec_read(codec, 0x12, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE)
- spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
- if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE)
- spec->dig_in_nid = CMI_DIG_IN_NID;
- spec->multiout.max_channels = 8;
- }
- snd_hda_parse_pin_def_config(codec, &cfg);
- if (cfg.line_outs) {
- spec->multiout.max_channels = cfg.line_outs * 2;
- cmi9880_fill_multi_dac_nids(codec, &cfg);
- cmi9880_fill_multi_init(codec, &cfg);
- } else
- snd_printd("patch_cmedia: cannot detect association in defcfg\n");
- break;
- }
}
- spec->multiout.num_dacs = spec->num_dacs;
- spec->multiout.dac_nids = spec->dac_nids;
+ spec->multiout.num_dacs = 4;
+ spec->multiout.dac_nids = cmi9880_dac_nids;
spec->adc_nids = cmi9880_adc_nids;
diff --git a/trunk/sound/pci/hda/patch_realtek.c b/trunk/sound/pci/hda/patch_realtek.c
index 9edd558d6bd3..17c5062423ae 100644
--- a/trunk/sound/pci/hda/patch_realtek.c
+++ b/trunk/sound/pci/hda/patch_realtek.c
@@ -33,73 +33,38 @@
/* ALC880 board config type */
enum {
+ ALC880_MINIMAL,
ALC880_3ST,
ALC880_3ST_DIG,
ALC880_5ST,
ALC880_5ST_DIG,
ALC880_W810,
- ALC880_Z71V,
- ALC880_AUTO,
- ALC880_6ST_DIG,
- ALC880_F1734,
- ALC880_ASUS,
- ALC880_ASUS_DIG,
- ALC880_ASUS_W1V,
- ALC880_UNIWILL_DIG,
-#ifdef CONFIG_SND_DEBUG
- ALC880_TEST,
-#endif
- ALC880_MODEL_LAST /* last tag */
-};
-
-/* ALC260 models */
-enum {
- ALC260_BASIC,
- ALC260_HP,
- ALC260_MODEL_LAST /* last tag */
};
-/* amp values */
-#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
-#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
-#define AMP_OUT_MUTE 0xb080
-#define AMP_OUT_UNMUTE 0xb000
-#define AMP_OUT_ZERO 0xb000
-/* pinctl values */
-#define PIN_IN 0x20
-#define PIN_VREF80 0x24
-#define PIN_VREF50 0x21
-#define PIN_OUT 0x40
-#define PIN_HP 0xc0
-
struct alc_spec {
/* codec parameterization */
- snd_kcontrol_new_t *mixers[3]; /* mixer arrays */
+ unsigned int front_panel: 1;
+
+ snd_kcontrol_new_t* mixers[2];
unsigned int num_mixers;
- const struct hda_verb *init_verbs[3]; /* initialization verbs
- * don't forget NULL termination!
- */
- unsigned int num_init_verbs;
+ struct hda_verb *init_verbs;
- char *stream_name_analog; /* analog PCM stream */
+ char* stream_name_analog;
struct hda_pcm_stream *stream_analog_playback;
struct hda_pcm_stream *stream_analog_capture;
- char *stream_name_digital; /* digital PCM stream */
+ char* stream_name_digital;
struct hda_pcm_stream *stream_digital_playback;
struct hda_pcm_stream *stream_digital_capture;
/* playback */
- struct hda_multi_out multiout; /* playback set-up
- * max_channels, dacs must be set
- * dig_out_nid and hp_nid are optional
- */
+ struct hda_multi_out multiout;
/* capture */
unsigned int num_adc_nids;
hda_nid_t *adc_nids;
- hda_nid_t dig_in_nid; /* digital-in NID; optional */
+ hda_nid_t dig_in_nid;
/* capture source */
const struct hda_input_mux *input_mux;
@@ -110,17 +75,61 @@ struct alc_spec {
int num_channel_mode;
/* PCM information */
- struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */
+ struct hda_pcm pcm_rec[2];
+};
+
+/* DAC/ADC assignment */
+
+static hda_nid_t alc880_dac_nids[4] = {
+ /* front, rear, clfe, rear_surr */
+ 0x02, 0x05, 0x04, 0x03
+};
+
+static hda_nid_t alc880_w810_dac_nids[3] = {
+ /* front, rear/surround, clfe */
+ 0x02, 0x03, 0x04
+};
+
+static hda_nid_t alc880_adc_nids[3] = {
+ /* ADC0-2 */
+ 0x07, 0x08, 0x09,
+};
+
+#define ALC880_DIGOUT_NID 0x06
+#define ALC880_DIGIN_NID 0x0a
+
+static hda_nid_t alc260_dac_nids[1] = {
+ /* front */
+ 0x02,
+};
+
+static hda_nid_t alc260_adc_nids[2] = {
+ /* ADC0-1 */
+ 0x04, 0x05,
+};
- struct semaphore bind_mutex; /* for bound controls */
+#define ALC260_DIGOUT_NID 0x03
+#define ALC260_DIGIN_NID 0x06
- /* dynamic controls, init_verbs and input_mux */
- struct auto_pin_cfg autocfg;
- unsigned int num_kctl_alloc, num_kctl_used;
- snd_kcontrol_new_t *kctl_alloc;
- struct hda_input_mux private_imux;
+static struct hda_input_mux alc880_capture_source = {
+ .num_items = 4,
+ .items = {
+ { "Mic", 0x0 },
+ { "Front Mic", 0x3 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ },
};
+static struct hda_input_mux alc260_capture_source = {
+ .num_items = 4,
+ .items = {
+ { "Mic", 0x0 },
+ { "Front Mic", 0x1 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ },
+};
/*
* input MUX handling
@@ -151,7 +160,6 @@ static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
}
-
/*
* channel mode setting
*/
@@ -160,18 +168,135 @@ struct alc_channel_mode {
const struct hda_verb *sequence;
};
+
+/*
+ * channel source setting (2/6 channel selection for 3-stack)
+ */
+
+/*
+ * set the path ways for 2 channel output
+ * need to set the codec line out and mic 1 pin widgets to inputs
+ */
+static struct hda_verb alc880_threestack_ch2_init[] = {
+ /* set pin widget 1Ah (line in) for input */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ /* set pin widget 18h (mic1) for input, for mic also enable the vref */
+ { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ /* mute the output for Line In PW */
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
+ /* mute for Mic1 PW */
+ { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
+ { } /* end */
+};
+
+/*
+ * 6ch mode
+ * need to set the codec line out and mic 1 pin widgets to outputs
+ */
+static struct hda_verb alc880_threestack_ch6_init[] = {
+ /* set pin widget 1Ah (line in) for output */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* set pin widget 18h (mic1) for output */
+ { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* unmute the output for Line In PW */
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
+ /* unmute for Mic1 PW */
+ { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
+ /* for rear channel output using Line In 1
+ * set select widget connection (nid = 0x12) - to summer node
+ * for rear NID = 0x0f...offset 3 in connection list
+ */
+ { 0x12, AC_VERB_SET_CONNECT_SEL, 0x3 },
+ /* for Mic1 - retask for center/lfe */
+ /* set select widget connection (nid = 0x10) - to summer node for
+ * front CLFE NID = 0x0e...offset 2 in connection list
+ */
+ { 0x10, AC_VERB_SET_CONNECT_SEL, 0x2 },
+ { } /* end */
+};
+
+static struct alc_channel_mode alc880_threestack_modes[2] = {
+ { 2, alc880_threestack_ch2_init },
+ { 6, alc880_threestack_ch6_init },
+};
+
+
+/*
+ * channel source setting (6/8 channel selection for 5-stack)
+ */
+
+/* set the path ways for 6 channel output
+ * need to set the codec line out and mic 1 pin widgets to inputs
+ */
+static struct hda_verb alc880_fivestack_ch6_init[] = {
+ /* set pin widget 1Ah (line in) for input */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ /* mute the output for Line In PW */
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
+ { } /* end */
+};
+
+/* need to set the codec line out and mic 1 pin widgets to outputs */
+static struct hda_verb alc880_fivestack_ch8_init[] = {
+ /* set pin widget 1Ah (line in) for output */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* unmute the output for Line In PW */
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
+ /* output for surround channel output using Line In 1 */
+ /* set select widget connection (nid = 0x12) - to summer node
+ * for surr_rear NID = 0x0d...offset 1 in connection list
+ */
+ { 0x12, AC_VERB_SET_CONNECT_SEL, 0x1 },
+ { } /* end */
+};
+
+static struct alc_channel_mode alc880_fivestack_modes[2] = {
+ { 6, alc880_fivestack_ch6_init },
+ { 8, alc880_fivestack_ch8_init },
+};
+
+/*
+ * channel source setting for W810 system
+ *
+ * W810 has rear IO for:
+ * Front (DAC 02)
+ * Surround (DAC 03)
+ * Center/LFE (DAC 04)
+ * Digital out (06)
+ *
+ * The system also has a pair of internal speakers, and a headphone jack.
+ * These are both connected to Line2 on the codec, hence to DAC 02.
+ *
+ * There is a variable resistor to control the speaker or headphone
+ * volume. This is a hardware-only device without a software API.
+ *
+ * Plugging headphones in will disable the internal speakers. This is
+ * implemented in hardware, not via the driver using jack sense. In
+ * a similar fashion, plugging into the rear socket marked "front" will
+ * disable both the speakers and headphones.
+ *
+ * For input, there's a microphone jack, and an "audio in" jack.
+ * These may not do anything useful with this driver yet, because I
+ * haven't setup any initialization verbs for these yet...
+ */
+
+static struct alc_channel_mode alc880_w810_modes[1] = {
+ { 6, NULL }
+};
+
+/*
+ */
static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
- int items = kcontrol->private_value ? (int)kcontrol->private_value : 2;
snd_assert(spec->channel_mode, return -ENXIO);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
- uinfo->value.enumerated.items = items;
- if (uinfo->value.enumerated.item >= items)
- uinfo->value.enumerated.item = items - 1;
+ uinfo->value.enumerated.items = 2;
+ if (uinfo->value.enumerated.item >= 2)
+ uinfo->value.enumerated.item = 1;
sprintf(uinfo->value.enumerated.name, "%dch",
spec->channel_mode[uinfo->value.enumerated.item].channels);
return 0;
@@ -181,16 +306,10 @@ static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
- int items = kcontrol->private_value ? (int)kcontrol->private_value : 2;
- int i;
snd_assert(spec->channel_mode, return -ENXIO);
- for (i = 0; i < items; i++) {
- if (spec->multiout.max_channels == spec->channel_mode[i].channels) {
- ucontrol->value.enumerated.item[0] = i;
- break;
- }
- }
+ ucontrol->value.enumerated.item[0] =
+ (spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1;
return 0;
}
@@ -216,149 +335,21 @@ static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
/*
- * bound volume controls
- *
- * bind multiple volumes (# indices, from 0)
- */
-
-#define AMP_VAL_IDX_SHIFT 19
-#define AMP_VAL_IDX_MASK (0x0f<<19)
-
-static int alc_bind_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- unsigned long pval;
-
- down(&spec->bind_mutex);
- pval = kcontrol->private_value;
- kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
- snd_hda_mixer_amp_switch_info(kcontrol, uinfo);
- kcontrol->private_value = pval;
- up(&spec->bind_mutex);
- return 0;
-}
-
-static int alc_bind_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- unsigned long pval;
-
- down(&spec->bind_mutex);
- pval = kcontrol->private_value;
- kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
- snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
- kcontrol->private_value = pval;
- up(&spec->bind_mutex);
- return 0;
-}
-
-static int alc_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- unsigned long pval;
- int i, indices, change = 0;
-
- down(&spec->bind_mutex);
- pval = kcontrol->private_value;
- indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
- for (i = 0; i < indices; i++) {
- kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | (i << AMP_VAL_IDX_SHIFT);
- change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
- }
- kcontrol->private_value = pval;
- up(&spec->bind_mutex);
- return change;
-}
-
-#define ALC_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
- .info = alc_bind_switch_info, \
- .get = alc_bind_switch_get, \
- .put = alc_bind_switch_put, \
- .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) }
-
-#define ALC_BIND_MUTE(xname,nid,indices,dir) ALC_BIND_MUTE_MONO(xname,nid,3,indices,dir)
-
-
-/*
- * ALC880 3-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
- * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b
- * HP = 0x19
*/
-static hda_nid_t alc880_dac_nids[4] = {
- /* front, rear, clfe, rear_surr */
- 0x02, 0x05, 0x04, 0x03
-};
-
-static hda_nid_t alc880_adc_nids[3] = {
- /* ADC0-2 */
- 0x07, 0x08, 0x09,
-};
-
-/* The datasheet says the node 0x07 is connected from inputs,
- * but it shows zero connection in the real implementation on some devices.
+/* 3-stack mode
+ * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b
+ * HP=0x19
*/
-static hda_nid_t alc880_adc_nids_alt[2] = {
- /* ADC1-2 */
- 0x08, 0x09,
-};
-
-#define ALC880_DIGOUT_NID 0x06
-#define ALC880_DIGIN_NID 0x0a
-
-static struct hda_input_mux alc880_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x3 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-/* channel source setting (2/6 channel selection for 3-stack) */
-/* 2ch mode */
-static struct hda_verb alc880_threestack_ch2_init[] = {
- /* set line-in to input, mute it */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- /* set mic-in to input vref 80%, mute it */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { } /* end */
-};
-
-/* 6ch mode */
-static struct hda_verb alc880_threestack_ch6_init[] = {
- /* set line-in to output, unmute it */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- /* set mic-in to output, unmute it */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { } /* end */
-};
-
-static struct alc_channel_mode alc880_threestack_modes[2] = {
- { 2, alc880_threestack_ch2_init },
- { 6, alc880_threestack_ch6_init },
-};
-
-static snd_kcontrol_new_t alc880_three_stack_mixer[] = {
+static snd_kcontrol_new_t alc880_base_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
+ HDA_CODEC_MUTE("Surround Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x18, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x18, 2, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
@@ -369,7 +360,25 @@ static snd_kcontrol_new_t alc880_three_stack_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ * FIXME: the controls appear in the "playback" view!
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -380,14 +389,37 @@ static snd_kcontrol_new_t alc880_three_stack_mixer[] = {
{ } /* end */
};
-/* capture mixer elements */
-static snd_kcontrol_new_t alc880_capture_mixer[] = {
+/* 5-stack mode
+ * Pin assignment: Front=0x14, Rear=0x17, CLFE=0x16
+ * Line-In/Side=0x1a, Mic=0x18, F-Mic=0x1b, HP=0x19
+ */
+static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Surround Playback Switch", 0x17, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Side Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
+ HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* The multiple "Capture Source" controls confuse alsamixer
@@ -396,20 +428,37 @@ static snd_kcontrol_new_t alc880_capture_mixer[] = {
*/
/* .name = "Capture Source", */
.name = "Input Source",
- .count = 3,
+ .count = 2,
.info = alc_mux_enum_info,
.get = alc_mux_enum_get,
.put = alc_mux_enum_put,
},
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Channel Mode",
+ .info = alc880_ch_mode_info,
+ .get = alc880_ch_mode_get,
+ .put = alc880_ch_mode_put,
+ },
{ } /* end */
};
-/* capture mixer elements (in case NID 0x07 not available) */
-static snd_kcontrol_new_t alc880_capture_alt_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* The multiple "Capture Source" controls confuse alsamixer
@@ -418,7 +467,7 @@ static snd_kcontrol_new_t alc880_capture_alt_mixer[] = {
*/
/* .name = "Capture Source", */
.name = "Input Source",
- .count = 2,
+ .count = 3,
.info = alc_mux_enum_info,
.get = alc_mux_enum_get,
.put = alc_mux_enum_put,
@@ -426,268 +475,7 @@ static snd_kcontrol_new_t alc880_capture_alt_mixer[] = {
{ } /* end */
};
-
-
-/*
- * ALC880 5-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd)
- * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
- * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
- */
-
-/* additional mixers to alc880_three_stack_mixer */
-static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
- { } /* end */
-};
-
-/* channel source setting (6/8 channel selection for 5-stack) */
-/* 6ch mode */
-static struct hda_verb alc880_fivestack_ch6_init[] = {
- /* set line-in to input, mute it */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { } /* end */
-};
-
-/* 8ch mode */
-static struct hda_verb alc880_fivestack_ch8_init[] = {
- /* set line-in to output, unmute it */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { } /* end */
-};
-
-static struct alc_channel_mode alc880_fivestack_modes[2] = {
- { 6, alc880_fivestack_ch6_init },
- { 8, alc880_fivestack_ch8_init },
-};
-
-
-/*
- * ALC880 6-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f)
- * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
- * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
- */
-
-static hda_nid_t alc880_6st_dac_nids[4] = {
- /* front, rear, clfe, rear_surr */
- 0x02, 0x03, 0x04, 0x05
-};
-
-static struct hda_input_mux alc880_6stack_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-/* fixed 8-channels */
-static struct alc_channel_mode alc880_sixstack_modes[1] = {
- { 8, NULL },
-};
-
-static snd_kcontrol_new_t alc880_six_stack_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
- HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc880_ch_mode_info,
- .get = alc880_ch_mode_get,
- .put = alc880_ch_mode_put,
- },
- { } /* end */
-};
-
-
-/*
- * ALC880 W810 model
- *
- * W810 has rear IO for:
- * Front (DAC 02)
- * Surround (DAC 03)
- * Center/LFE (DAC 04)
- * Digital out (06)
- *
- * The system also has a pair of internal speakers, and a headphone jack.
- * These are both connected to Line2 on the codec, hence to DAC 02.
- *
- * There is a variable resistor to control the speaker or headphone
- * volume. This is a hardware-only device without a software API.
- *
- * Plugging headphones in will disable the internal speakers. This is
- * implemented in hardware, not via the driver using jack sense. In
- * a similar fashion, plugging into the rear socket marked "front" will
- * disable both the speakers and headphones.
- *
- * For input, there's a microphone jack, and an "audio in" jack.
- * These may not do anything useful with this driver yet, because I
- * haven't setup any initialization verbs for these yet...
- */
-
-static hda_nid_t alc880_w810_dac_nids[3] = {
- /* front, rear/surround, clfe */
- 0x02, 0x03, 0x04
-};
-
-/* fixed 6 channels */
-static struct alc_channel_mode alc880_w810_modes[1] = {
- { 6, NULL }
-};
-
-/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
-static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- { } /* end */
-};
-
-
-/*
- * Z710V model
- *
- * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
- * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a
- */
-
-static hda_nid_t alc880_z71v_dac_nids[1] = {
- 0x02
-};
-#define ALC880_Z71V_HP_DAC 0x03
-
-/* fixed 2 channels */
-static struct alc_channel_mode alc880_2_jack_modes[1] = {
- { 2, NULL }
-};
-
-static snd_kcontrol_new_t alc880_z71v_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-
-/* FIXME! */
-/*
- * ALC880 F1734 model
- *
- * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
- * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
- */
-
-static hda_nid_t alc880_f1734_dac_nids[1] = {
- 0x03
-};
-#define ALC880_F1734_HP_DAC 0x02
-
-static snd_kcontrol_new_t alc880_f1734_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-
-/* FIXME! */
-/*
- * ALC880 ASUS model
- *
- * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
- * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
- * Mic = 0x18, Line = 0x1a
- */
-
-#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
-#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
-
-static snd_kcontrol_new_t alc880_asus_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc880_ch_mode_info,
- .get = alc880_ch_mode_get,
- .put = alc880_ch_mode_put,
- },
- { } /* end */
-};
-
-/* FIXME! */
-/*
- * ALC880 ASUS W1V model
- *
- * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
- * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
- * Mic = 0x18, Line = 0x1a, Line2 = 0x1b
- */
-
-/* additional mixers to alc880_asus_mixer */
-static snd_kcontrol_new_t alc880_asus_w1v_mixer[] = {
- HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
- HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
- { } /* end */
-};
-
-
/*
- * build control elements
*/
static int alc_build_controls(struct hda_codec *codec)
{
@@ -714,297 +502,227 @@ static int alc_build_controls(struct hda_codec *codec)
return 0;
}
-
/*
* initialize the codec volumes, etc
*/
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static struct hda_verb alc880_volume_init_verbs[] = {
- /*
- * Unmute ADC0-2 and set the default input to mic-in
- */
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
- * mixer widget
+static struct hda_verb alc880_init_verbs_three_stack[] = {
+ /* Line In pin widget for input */
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ /* CD pin widget for input */
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ /* Mic1 (rear panel) pin widget for input and vref at 80% */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* Mic2 (front panel) pin widget for input and vref at 80% */
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* unmute amp left and right */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+ /* set connection select to line in (default select for this ADC) */
+ {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
+ /* unmute front mixer amp left (volume = 0) */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* unmute rear mixer amp left and right (volume = 0) */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* unmute rear mixer amp left and right (volume = 0) */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+
+ /* using rear surround as the path for headphone output */
+ /* unmute rear surround mixer amp left and right (volume = 0) */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* PASD 3 stack boards use the Mic 2 as the headphone output */
+ /* need to program the selector associated with the Mic 2 pin widget to
+ * surround path (index 0x01) for headphone output */
+ {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* need to retask the Mic 2 pin widget to output */
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+ /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer widget(nid=0x0B)
+ * to support the input path of analog loopback
* Note: PASD motherboards uses the Line In 2 as the input for front panel
* mic (mic 2)
*/
- /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
-
- /*
- * Set up output mixers (0x0c - 0x0f)
+ /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
+ /* unmute CD */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
+ /* unmute Line In */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
+ /* unmute Mic 1 */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ /* unmute Line In 2 (for PASD boards Mic 2) */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
+
+ /* Unmute input amps for the line out paths to support the output path of
+ * analog loopback
+ * the mixers on the output path has 2 inputs, one from the DAC and one
+ * from the mixer
*/
- /* set vol=0 to output mixers */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* set up input amps for analog loopback */
- /* Amp Indices: DAC = 0, mixer = 1 */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
+ /* Unmute Front out path */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute Surround (used as HP) out path */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute C/LFE out path */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
+ /* Unmute rear Surround out path */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
{ }
};
-/*
- * 3-stack pin configuration:
- * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
- */
-static struct hda_verb alc880_pin_3stack_init_verbs[] = {
- /*
- * preset connection lists of input pins
- * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
- */
- {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
- {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
-
- /*
- * Set pin mode and muting
- */
- /* set front pin widgets 0x14 for output */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Mic2 (as headphone out) for HP output */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+static struct hda_verb alc880_init_verbs_five_stack[] = {
/* Line In pin widget for input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line2 (as front mic) pin widget for input and vref at 80% */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
/* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ /* Mic1 (rear panel) pin widget for input and vref at 80% */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* Mic2 (front panel) pin widget for input and vref at 80% */
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* unmute amp left and right */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+ /* set connection select to line in (default select for this ADC) */
+ {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
+ /* unmute front mixer amp left and right (volume = 0) */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* five rear and clfe */
+ /* unmute rear mixer amp left and right (volume = 0) */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* unmute clfe mixer amp left and right (volume = 0) */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+
+ /* using rear surround as the path for headphone output */
+ /* unmute rear surround mixer amp left and right (volume = 0) */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* PASD 3 stack boards use the Mic 2 as the headphone output */
+ /* need to program the selector associated with the Mic 2 pin widget to
+ * surround path (index 0x01) for headphone output
+ */
+ {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* need to retask the Mic 2 pin widget to output */
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+ /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer
+ * widget(nid=0x0B) to support the input path of analog loopback
+ */
+ /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */
+ /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/
+ /* unmute CD */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
+ /* unmute Line In */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
+ /* unmute Mic 1 */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ /* unmute Line In 2 (for PASD boards Mic 2) */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
+
+ /* Unmute input amps for the line out paths to support the output path of
+ * analog loopback
+ * the mixers on the output path has 2 inputs, one from the DAC and
+ * one from the mixer
+ */
+ /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
+ /* Unmute Front out path */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute Surround (used as HP) out path */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute C/LFE out path */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
+ /* Unmute rear Surround out path */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
{ }
};
-/*
- * 5-stack pin configuration:
- * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
- * line-in/side = 0x1a, f-mic = 0x1b
- */
-static struct hda_verb alc880_pin_5stack_init_verbs[] = {
- /*
- * preset connection lists of input pins
- * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
- */
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
- {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
+static struct hda_verb alc880_w810_init_verbs[] = {
+ /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
- /*
- * Set pin mode and muting
- */
- /* set pin widgets 0x14-0x17 for output */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* unmute pins for output (no gain on this amp) */
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Mic2 (as headphone out) for HP output */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Line In pin widget for input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line2 (as front mic) pin widget for input and vref at 80% */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ /* front channel selector/amp: output 0: unmuted, max volume */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- { }
-};
+ /* front out pin: muted, (no volume selection) */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-/*
- * W810 pin configuration:
- * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
- */
-static struct hda_verb alc880_pin_w810_init_verbs[] = {
- /* hphone/speaker input selector: front DAC */
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* front out pin: NOT headphone enable, out enable, vref disabled */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* surround channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
- { }
-};
+ /* surround channel selector/amp: input 1: capture mix: muted, (no volume selection) */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
-/*
- * Z71V pin configuration:
- * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
- */
-static struct hda_verb alc880_pin_z71v_init_verbs[] = {
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* surround channel selector/amp: output 0: unmuted, max volume */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ /* surround out pin: muted, (no volume selection) */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- { }
-};
+ /* surround out pin: NOT headphone enable, out enable, vref disabled */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-/*
- * 6-stack pin configuration:
- * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19,
- * line = 0x1a, HP = 0x1b
- */
-static struct hda_verb alc880_pin_6stack_init_verbs[] = {
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- { }
-};
-/* FIXME! */
-/*
- * F1734 pin configuration:
- * HP = 0x14, speaker-out = 0x15, mic = 0x18
- */
-static struct hda_verb alc880_pin_f1734_init_verbs[] = {
- {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ /* c/lfe channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
- { }
-};
+ /* c/lfe channel selector/amp: input 1: capture mix: muted, (no volume selection) */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
-/* FIXME! */
-/*
- * ASUS pin configuration:
- * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
- */
-static struct hda_verb alc880_pin_asus_init_verbs[] = {
- {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- { }
-};
+ /* c/lfe channel selector/amp: output 0: unmuted, max volume */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-/* Enable GPIO mask and set output */
-static struct hda_verb alc880_gpio1_init_verbs[] = {
- {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
- {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
- {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
-};
+ /* c/lfe out pin: muted, (no volume selection) */
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-/* Enable GPIO mask and set output */
-static struct hda_verb alc880_gpio2_init_verbs[] = {
- {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
- {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
- {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
-};
+ /* c/lfe out pin: NOT headphone enable, out enable, vref disabled */
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-/*
- */
+ /* hphone/speaker input selector: front DAC */
+ {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
+
+ /* hphone/speaker out pin: muted, (no volume selection) */
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+
+ /* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+
+ { }
+};
static int alc_init(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int i;
-
- for (i = 0; i < spec->num_init_verbs; i++)
- snd_hda_sequence_write(codec, spec->init_verbs[i]);
+ snd_hda_sequence_write(codec, spec->init_verbs);
return 0;
}
@@ -1018,8 +736,9 @@ static int alc_resume(struct hda_codec *codec)
int i;
alc_init(codec);
- for (i = 0; i < spec->num_mixers; i++)
+ for (i = 0; i < spec->num_mixers; i++) {
snd_hda_resume_ctls(codec, spec->mixers[i]);
+ }
if (spec->multiout.dig_out_nid)
snd_hda_resume_spdif_out(codec);
if (spec->dig_in_nid)
@@ -1060,1070 +779,295 @@ static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
}
/*
- * Digital out
- */
-static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct alc_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct alc_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-/*
- * Analog capture
- */
-static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- snd_pcm_substream_t *substream)
-{
- struct alc_spec *spec = codec->spec;
-
- snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
- stream_tag, 0, format);
- return 0;
-}
-
-static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct alc_spec *spec = codec->spec;
-
- snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
- return 0;
-}
-
-
-/*
- */
-static struct hda_pcm_stream alc880_pcm_analog_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 8,
- /* NID is set in alc_build_pcms */
- .ops = {
- .open = alc880_playback_pcm_open,
- .prepare = alc880_playback_pcm_prepare,
- .cleanup = alc880_playback_pcm_cleanup
- },
-};
-
-static struct hda_pcm_stream alc880_pcm_analog_capture = {
- .substreams = 2,
- .channels_min = 2,
- .channels_max = 2,
- /* NID is set in alc_build_pcms */
- .ops = {
- .prepare = alc880_capture_pcm_prepare,
- .cleanup = alc880_capture_pcm_cleanup
- },
-};
-
-static struct hda_pcm_stream alc880_pcm_digital_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- /* NID is set in alc_build_pcms */
- .ops = {
- .open = alc880_dig_playback_pcm_open,
- .close = alc880_dig_playback_pcm_close
- },
-};
-
-static struct hda_pcm_stream alc880_pcm_digital_capture = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- /* NID is set in alc_build_pcms */
-};
-
-static int alc_build_pcms(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- struct hda_pcm *info = spec->pcm_rec;
- int i;
-
- codec->num_pcms = 1;
- codec->pcm_info = info;
-
- info->name = spec->stream_name_analog;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
- info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
-
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
- for (i = 0; i < spec->num_channel_mode; i++) {
- if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
- }
- }
-
- if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
- codec->num_pcms++;
- info++;
- info->name = spec->stream_name_digital;
- if (spec->multiout.dig_out_nid) {
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
- }
- if (spec->dig_in_nid) {
- info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
- }
- }
-
- return 0;
-}
-
-static void alc_free(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- unsigned int i;
-
- if (! spec)
- return;
-
- if (spec->kctl_alloc) {
- for (i = 0; i < spec->num_kctl_used; i++)
- kfree(spec->kctl_alloc[i].name);
- kfree(spec->kctl_alloc);
- }
- kfree(spec);
-}
-
-/*
- */
-static struct hda_codec_ops alc_patch_ops = {
- .build_controls = alc_build_controls,
- .build_pcms = alc_build_pcms,
- .init = alc_init,
- .free = alc_free,
-#ifdef CONFIG_PM
- .resume = alc_resume,
-#endif
-};
-
-
-/*
- * Test configuration for debugging
- *
- * Almost all inputs/outputs are enabled. I/O pins can be configured via
- * enum controls.
- */
-#ifdef CONFIG_SND_DEBUG
-static hda_nid_t alc880_test_dac_nids[4] = {
- 0x02, 0x03, 0x04, 0x05
-};
-
-static struct hda_input_mux alc880_test_capture_source = {
- .num_items = 5,
- .items = {
- { "In-1", 0x0 },
- { "In-2", 0x1 },
- { "In-3", 0x2 },
- { "In-4", 0x3 },
- { "CD", 0x4 },
- },
-};
-
-static struct alc_channel_mode alc880_test_modes[4] = {
- { 2, NULL },
- { 4, NULL },
- { 6, NULL },
- { 8, NULL },
-};
-
-static int alc_test_pin_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
- static char *texts[] = {
- "N/A", "Line Out", "HP Out",
- "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
- };
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 8;
- if (uinfo->value.enumerated.item >= 8)
- uinfo->value.enumerated.item = 7;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int alc_test_pin_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
- unsigned int pin_ctl, item = 0;
-
- pin_ctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- if (pin_ctl & AC_PINCTL_OUT_EN) {
- if (pin_ctl & AC_PINCTL_HP_EN)
- item = 2;
- else
- item = 1;
- } else if (pin_ctl & AC_PINCTL_IN_EN) {
- switch (pin_ctl & AC_PINCTL_VREFEN) {
- case AC_PINCTL_VREF_HIZ: item = 3; break;
- case AC_PINCTL_VREF_50: item = 4; break;
- case AC_PINCTL_VREF_GRD: item = 5; break;
- case AC_PINCTL_VREF_80: item = 6; break;
- case AC_PINCTL_VREF_100: item = 7; break;
- }
- }
- ucontrol->value.enumerated.item[0] = item;
- return 0;
-}
-
-static int alc_test_pin_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
- static unsigned int ctls[] = {
- 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
- };
- unsigned int old_ctl, new_ctl;
-
- old_ctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- new_ctl = ctls[ucontrol->value.enumerated.item[0]];
- if (old_ctl != new_ctl) {
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl);
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000);
- return 1;
- }
- return 0;
-}
-
-static int alc_test_pin_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
- static char *texts[] = {
- "Front", "Surround", "CLFE", "Side"
- };
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 4;
- if (uinfo->value.enumerated.item >= 4)
- uinfo->value.enumerated.item = 3;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int alc_test_pin_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
- unsigned int sel;
-
- sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
- ucontrol->value.enumerated.item[0] = sel & 3;
- return 0;
-}
-
-static int alc_test_pin_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
- unsigned int sel;
-
- sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
- if (ucontrol->value.enumerated.item[0] != sel) {
- sel = ucontrol->value.enumerated.item[0] & 3;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel);
- return 1;
- }
- return 0;
-}
-
-#define PIN_CTL_TEST(xname,nid) { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .info = alc_test_pin_ctl_info, \
- .get = alc_test_pin_ctl_get, \
- .put = alc_test_pin_ctl_put, \
- .private_value = nid \
- }
-
-#define PIN_SRC_TEST(xname,nid) { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .info = alc_test_pin_src_info, \
- .get = alc_test_pin_src_get, \
- .put = alc_test_pin_src_put, \
- .private_value = nid \
- }
-
-static snd_kcontrol_new_t alc880_test_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- ALC_BIND_MUTE("CLFE Playback Volume", 0x0e, 2, HDA_INPUT),
- ALC_BIND_MUTE("Side Playback Volume", 0x0f, 2, HDA_INPUT),
- PIN_CTL_TEST("Front Pin Mode", 0x14),
- PIN_CTL_TEST("Surround Pin Mode", 0x15),
- PIN_CTL_TEST("CLFE Pin Mode", 0x16),
- PIN_CTL_TEST("Side Pin Mode", 0x17),
- PIN_CTL_TEST("In-1 Pin Mode", 0x18),
- PIN_CTL_TEST("In-2 Pin Mode", 0x19),
- PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
- PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
- PIN_SRC_TEST("In-1 Pin Source", 0x18),
- PIN_SRC_TEST("In-2 Pin Source", 0x19),
- PIN_SRC_TEST("In-3 Pin Source", 0x1a),
- PIN_SRC_TEST("In-4 Pin Source", 0x1b),
- HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
- HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
- HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
- HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Input Source",
- .count = 2,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc880_ch_mode_info,
- .get = alc880_ch_mode_get,
- .put = alc880_ch_mode_put,
- },
- { } /* end */
-};
-
-static struct hda_verb alc880_test_init_verbs[] = {
- /* Unmute inputs of 0x0c - 0x0f */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* Vol output for 0x0c-0x0f */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* Set output pins 0x14-0x17 */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* Unmute output pins 0x14-0x17 */
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Set input pins 0x18-0x1c */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* Mute input pins 0x18-0x1b */
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* ADC set up */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Analog input/passthru */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- { }
-};
-#endif
-
-/*
- */
-
-static struct hda_board_config alc880_cfg_tbl[] = {
- /* Back 3 jack, front 2 jack */
- { .modelname = "3stack", .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST },
- { .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST },
- { .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST },
- { .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST },
- { .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST },
- { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST },
- { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST },
-
- /* Back 3 jack, front 2 jack (Internal add Aux-In) */
- { .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
- { .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST },
-
- /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
- { .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG },
-
- /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG },
- { .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG },
-
- /* Back 5 jack, front 2 jack */
- { .modelname = "5stack", .config = ALC880_5ST },
- { .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST },
- { .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST },
- { .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST },
- { .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST },
- { .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST },
-
- /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
- { .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG },
- { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG },
- { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG },
- { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG },
- { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG },
- { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG },
-
- { .modelname = "w810", .config = ALC880_W810 },
- { .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 },
-
- { .modelname = "z71v", .config = ALC880_Z71V },
- { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V },
-
- { .modelname = "6statack-digout", .config = ALC880_6ST_DIG },
- { .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG },
- { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG },
- { .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG },
-
- { .modelname = "asus", .config = ALC880_ASUS },
- { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
- { .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG },
- { .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG },
- { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG },
- { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS },
- { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG },
- { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS },
- { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG },
- { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS },
- { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V },
-
- { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG },
- { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },
-
- { .modelname = "F1734", .config = ALC880_F1734 },
- { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 },
-
-#ifdef CONFIG_SND_DEBUG
- { .modelname = "test", .config = ALC880_TEST },
-#endif
-
- {}
-};
-
-/*
- * configuration template - to be copied to the spec instance
- */
-struct alc_config_preset {
- snd_kcontrol_new_t *mixers[4];
- const struct hda_verb *init_verbs[4];
- unsigned int num_dacs;
- hda_nid_t *dac_nids;
- hda_nid_t dig_out_nid; /* optional */
- hda_nid_t hp_nid; /* optional */
- unsigned int num_adc_nids;
- hda_nid_t *adc_nids;
- unsigned int num_channel_mode;
- const struct alc_channel_mode *channel_mode;
- const struct hda_input_mux *input_mux;
-};
-
-static struct alc_config_preset alc880_presets[] = {
- [ALC880_3ST] = {
- .mixers = { alc880_three_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
- .channel_mode = alc880_threestack_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_3ST_DIG] = {
- .mixers = { alc880_three_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
- .channel_mode = alc880_threestack_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_5ST] = {
- .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer},
- .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
- .channel_mode = alc880_fivestack_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_5ST_DIG] = {
- .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
- .channel_mode = alc880_fivestack_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_6ST_DIG] = {
- .mixers = { alc880_six_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
- .dac_nids = alc880_6st_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
- .channel_mode = alc880_sixstack_modes,
- .input_mux = &alc880_6stack_capture_source,
- },
- [ALC880_W810] = {
- .mixers = { alc880_w810_base_mixer },
- .init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
- .dac_nids = alc880_w810_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
- .channel_mode = alc880_w810_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_Z71V] = {
- .mixers = { alc880_z71v_mixer },
- .init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs,
- alc880_gpio2_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
- .dac_nids = alc880_z71v_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
- .channel_mode = alc880_2_jack_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_F1734] = {
- .mixers = { alc880_f1734_mixer },
- .init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
- .dac_nids = alc880_f1734_dac_nids,
- .hp_nid = 0x02,
- .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
- .channel_mode = alc880_2_jack_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_ASUS] = {
- .mixers = { alc880_asus_mixer },
- .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
- .channel_mode = alc880_asus_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_ASUS_DIG] = {
- .mixers = { alc880_asus_mixer },
- .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
- .channel_mode = alc880_asus_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_ASUS_W1V] = {
- .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
- .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
- .channel_mode = alc880_asus_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_UNIWILL_DIG] = {
- .mixers = { alc880_asus_mixer },
- .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
- .channel_mode = alc880_asus_modes,
- .input_mux = &alc880_capture_source,
- },
-#ifdef CONFIG_SND_DEBUG
- [ALC880_TEST] = {
- .mixers = { alc880_test_mixer },
- .init_verbs = { alc880_test_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
- .dac_nids = alc880_test_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_test_modes),
- .channel_mode = alc880_test_modes,
- .input_mux = &alc880_test_capture_source,
- },
-#endif
-};
-
-/*
- * Automatic parse of I/O pins from the BIOS configuration
- */
-
-#define NUM_CONTROL_ALLOC 32
-#define NUM_VERB_ALLOC 32
-
-enum {
- ALC_CTL_WIDGET_VOL,
- ALC_CTL_WIDGET_MUTE,
- ALC_CTL_BIND_MUTE,
-};
-static snd_kcontrol_new_t alc880_control_templates[] = {
- HDA_CODEC_VOLUME(NULL, 0, 0, 0),
- HDA_CODEC_MUTE(NULL, 0, 0, 0),
- ALC_BIND_MUTE(NULL, 0, 0, 0),
-};
-
-/* add dynamic controls */
-static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val)
-{
- snd_kcontrol_new_t *knew;
-
- if (spec->num_kctl_used >= spec->num_kctl_alloc) {
- int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
-
- knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
- if (! knew)
- return -ENOMEM;
- if (spec->kctl_alloc) {
- memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
- kfree(spec->kctl_alloc);
- }
- spec->kctl_alloc = knew;
- spec->num_kctl_alloc = num;
- }
-
- knew = &spec->kctl_alloc[spec->num_kctl_used];
- *knew = alc880_control_templates[type];
- knew->name = snd_kmalloc_strdup(name, GFP_KERNEL);
- if (! knew->name)
- return -ENOMEM;
- knew->private_value = val;
- spec->num_kctl_used++;
- return 0;
-}
-
-#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
-#define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
-#define alc880_is_multi_pin(nid) ((nid) >= 0x18)
-#define alc880_multi_pin_idx(nid) ((nid) - 0x18)
-#define alc880_is_input_pin(nid) ((nid) >= 0x18)
-#define alc880_input_pin_idx(nid) ((nid) - 0x18)
-#define alc880_idx_to_dac(nid) ((nid) + 0x02)
-#define alc880_dac_to_idx(nid) ((nid) - 0x02)
-#define alc880_idx_to_mixer(nid) ((nid) + 0x0c)
-#define alc880_idx_to_selector(nid) ((nid) + 0x10)
-#define ALC880_PIN_CD_NID 0x1c
-
-/* fill in the dac_nids table from the parsed pin configuration */
-static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
-{
- hda_nid_t nid;
- int assigned[4];
- int i, j;
-
- memset(assigned, 0, sizeof(assigned));
-
- /* check the pins hardwired to audio widget */
- for (i = 0; i < cfg->line_outs; i++) {
- nid = cfg->line_out_pins[i];
- if (alc880_is_fixed_pin(nid)) {
- int idx = alc880_fixed_pin_idx(nid);
- spec->multiout.dac_nids[i] = alc880_dac_to_idx(idx);
- assigned[idx] = 1;
- }
- }
- /* left pins can be connect to any audio widget */
- for (i = 0; i < cfg->line_outs; i++) {
- nid = cfg->line_out_pins[i];
- if (alc880_is_fixed_pin(nid))
- continue;
- /* search for an empty channel */
- for (j = 0; j < cfg->line_outs; j++) {
- if (! assigned[j]) {
- spec->multiout.dac_nids[i] = alc880_idx_to_dac(j);
- assigned[j] = 1;
- break;
- }
- }
- }
- spec->multiout.num_dacs = cfg->line_outs;
- return 0;
-}
-
-/* add playback controls from the parsed DAC table */
-static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
-{
- char name[32];
- static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
- hda_nid_t nid;
- int i, err;
-
- for (i = 0; i < cfg->line_outs; i++) {
- if (! spec->multiout.dac_nids[i])
- continue;
- nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
- if (i == 2) {
- /* Center/LFE */
- if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume",
- HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
- return err;
- if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume",
- HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
- return err;
- if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
- HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0)
- return err;
- if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
- HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0)
- return err;
- } else {
- sprintf(name, "%s Playback Volume", chname[i]);
- if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
- HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
- return err;
- sprintf(name, "%s Playback Switch", chname[i]);
- if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
- HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
- return err;
- }
- }
-
- return 0;
-}
-
-/* add playback controls for HP output */
-static int alc880_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
-{
- hda_nid_t nid;
- int err;
-
- if (! pin)
- return 0;
-
- if (alc880_is_fixed_pin(pin)) {
- nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
- if (! spec->multiout.dac_nids[0]) {
- /* use this as the primary output */
- spec->multiout.dac_nids[0] = nid;
- if (! spec->multiout.num_dacs)
- spec->multiout.num_dacs = 1;
- } else
- /* specify the DAC as the extra HP output */
- spec->multiout.hp_nid = nid;
- /* control HP volume/switch on the output mixer amp */
- nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
- if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
- HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
- return err;
- if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Headphone Playback Switch",
- HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
- return err;
- } else if (alc880_is_multi_pin(pin)) {
- /* set manual connection */
- if (! spec->multiout.dac_nids[0]) {
- /* use this as the primary output */
- spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin));
- if (! spec->multiout.num_dacs)
- spec->multiout.num_dacs = 1;
- }
- /* we have only a switch on HP-out PIN */
- if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
- HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0)
- return err;
- }
- return 0;
-}
-
-/* create input playback/capture controls for the given pin */
-static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname)
-{
- char name[32];
- int err, idx;
-
- sprintf(name, "%s Playback Volume", ctlname);
- idx = alc880_input_pin_idx(pin);
- if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
- HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0)
- return err;
- sprintf(name, "%s Playback Switch", ctlname);
- if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
- HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0)
- return err;
- return 0;
-}
-
-/* create playback/capture controls for input pins */
-static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+ * Digital out
+ */
+static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
{
- static char *labels[AUTO_PIN_LAST] = {
- "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
- };
- struct hda_input_mux *imux = &spec->private_imux;
- int i, err;
-
- for (i = 0; i < AUTO_PIN_LAST; i++) {
- if (alc880_is_input_pin(cfg->input_pins[i])) {
- err = new_analog_input(spec, cfg->input_pins[i], labels[i]);
- if (err < 0)
- return err;
- imux->items[imux->num_items].label = labels[i];
- imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]);
- imux->num_items++;
- }
- }
- return 0;
+ struct alc_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_open(codec, &spec->multiout);
}
-static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type,
- int dac_idx)
+static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
{
- /* set as output */
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
- /* need the manual connection? */
- if (alc880_is_multi_pin(nid)) {
- struct alc_spec *spec = codec->spec;
- int idx = alc880_multi_pin_idx(nid);
- snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
- AC_VERB_SET_CONNECT_SEL,
- alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
- }
+ struct alc_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_close(codec, &spec->multiout);
}
-static void alc880_auto_init_multi_out(struct hda_codec *codec)
+/*
+ * Analog capture
+ */
+static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ snd_pcm_substream_t *substream)
{
struct alc_spec *spec = codec->spec;
- int i;
- for (i = 0; i < spec->autocfg.line_outs; i++) {
- hda_nid_t nid = spec->autocfg.line_out_pins[i];
- alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
- }
+ snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+ stream_tag, 0, format);
+ return 0;
}
-static void alc880_auto_init_hp_out(struct hda_codec *codec)
+static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
{
struct alc_spec *spec = codec->spec;
- hda_nid_t pin;
- pin = spec->autocfg.hp_pin;
- if (pin) /* connect to front */
- alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+ snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+ return 0;
}
-static void alc880_auto_init_analog_input(struct hda_codec *codec)
+
+/*
+ */
+static struct hda_pcm_stream alc880_pcm_analog_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 8,
+ .nid = 0x02, /* NID to query formats and rates */
+ .ops = {
+ .open = alc880_playback_pcm_open,
+ .prepare = alc880_playback_pcm_prepare,
+ .cleanup = alc880_playback_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream alc880_pcm_analog_capture = {
+ .substreams = 2,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = 0x07, /* NID to query formats and rates */
+ .ops = {
+ .prepare = alc880_capture_pcm_prepare,
+ .cleanup = alc880_capture_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream alc880_pcm_digital_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ /* NID is set in alc_build_pcms */
+ .ops = {
+ .open = alc880_dig_playback_pcm_open,
+ .close = alc880_dig_playback_pcm_close
+ },
+};
+
+static struct hda_pcm_stream alc880_pcm_digital_capture = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ /* NID is set in alc_build_pcms */
+};
+
+static int alc_build_pcms(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
int i;
- for (i = 0; i < AUTO_PIN_LAST; i++) {
- hda_nid_t nid = spec->autocfg.input_pins[i];
- if (alc880_is_input_pin(nid)) {
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
- if (nid != ALC880_PIN_CD_NID)
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- AMP_OUT_MUTE);
+ codec->num_pcms = 1;
+ codec->pcm_info = info;
+
+ info->name = spec->stream_name_analog;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
+
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
+ for (i = 0; i < spec->num_channel_mode; i++) {
+ if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
+ }
+ }
+
+ if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
+ codec->num_pcms++;
+ info++;
+ info->name = spec->stream_name_digital;
+ if (spec->multiout.dig_out_nid) {
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+ }
+ if (spec->dig_in_nid) {
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
}
}
+
+ return 0;
}
-/* parse the BIOS configuration and set up the alc_spec */
-/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
-static int alc880_parse_auto_config(struct hda_codec *codec)
+static void alc_free(struct hda_codec *codec)
{
- struct alc_spec *spec = codec->spec;
- int err;
+ kfree(codec->spec);
+}
+
+/*
+ */
+static struct hda_codec_ops alc_patch_ops = {
+ .build_controls = alc_build_controls,
+ .build_pcms = alc_build_pcms,
+ .init = alc_init,
+ .free = alc_free,
+#ifdef CONFIG_PM
+ .resume = alc_resume,
+#endif
+};
- if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0)
- return err;
- if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0)
- return err;
- if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin)
- return 0; /* can't find valid BIOS pin config */
- if ((err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
- (err = alc880_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 ||
- (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
- return err;
+/*
+ */
- spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+static struct hda_board_config alc880_cfg_tbl[] = {
+ /* Back 3 jack, front 2 jack */
+ { .modelname = "3stack", .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe302, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe303, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe304, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe306, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe307, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST },
- if (spec->autocfg.dig_out_pin)
- spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
- if (spec->autocfg.dig_in_pin)
- spec->dig_in_nid = ALC880_DIGIN_NID;
+ /* Back 3 jack, front 2 jack (Internal add Aux-In) */
+ { .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST },
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+ /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
+ { .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xe308, .config = ALC880_3ST_DIG },
- spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
+ /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
+ { .pci_vendor = 0x8086, .pci_device = 0xe305, .config = ALC880_3ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xd402, .config = ALC880_3ST_DIG },
+ { .pci_vendor = 0x1025, .pci_device = 0xe309, .config = ALC880_3ST_DIG },
- spec->input_mux = &spec->private_imux;
+ /* Back 5 jack, front 2 jack */
+ { .modelname = "5stack", .config = ALC880_5ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x3033, .config = ALC880_5ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x4039, .config = ALC880_5ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x3032, .config = ALC880_5ST },
+ { .pci_vendor = 0x103c, .pci_device = 0x2a09, .config = ALC880_5ST },
- return 1;
-}
+ /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
+ { .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xe224, .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xe400, .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xe401, .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xe402, .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xd400, .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xd401, .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG },
-/* init callback for auto-configuration model -- overriding the default init */
-static int alc880_auto_init(struct hda_codec *codec)
-{
- alc_init(codec);
- alc880_auto_init_multi_out(codec);
- alc880_auto_init_hp_out(codec);
- alc880_auto_init_analog_input(codec);
- return 0;
-}
+ { .modelname = "w810", .config = ALC880_W810 },
+ { .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 },
-/*
- * OK, here we have finally the patch for ALC880
- */
+ {}
+};
static int patch_alc880(struct hda_codec *codec)
{
struct alc_spec *spec;
int board_config;
- int i, err;
spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
- init_MUTEX(&spec->bind_mutex);
codec->spec = spec;
board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
- if (board_config < 0 || board_config >= ALC880_MODEL_LAST) {
- printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n");
- board_config = ALC880_AUTO;
+ if (board_config < 0) {
+ snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n");
+ board_config = ALC880_MINIMAL;
}
- if (board_config == ALC880_AUTO) {
- /* automatic parse from the BIOS config */
- err = alc880_parse_auto_config(codec);
- if (err < 0) {
- alc_free(codec);
- return err;
- } else if (! err) {
- printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 3-stack mode...\n");
- board_config = ALC880_3ST;
- }
+ switch (board_config) {
+ case ALC880_W810:
+ spec->mixers[spec->num_mixers] = alc880_w810_base_mixer;
+ spec->num_mixers++;
+ break;
+ case ALC880_5ST:
+ case ALC880_5ST_DIG:
+ spec->mixers[spec->num_mixers] = alc880_five_stack_mixer;
+ spec->num_mixers++;
+ break;
+ default:
+ spec->mixers[spec->num_mixers] = alc880_base_mixer;
+ spec->num_mixers++;
+ break;
}
- if (board_config != ALC880_AUTO) {
- /* set up from the preset table */
- const struct alc_config_preset *preset;
-
- preset = &alc880_presets[board_config];
-
- for (i = 0; preset->mixers[i]; i++) {
- snd_assert(spec->num_mixers < ARRAY_SIZE(spec->mixers), break);
- spec->mixers[spec->num_mixers++] = preset->mixers[i];
- }
- for (i = 0; preset->init_verbs[i]; i++) {
- snd_assert(spec->num_init_verbs < ARRAY_SIZE(spec->init_verbs), break);
- spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i];
- }
-
- spec->channel_mode = preset->channel_mode;
- spec->num_channel_mode = preset->num_channel_mode;
-
- spec->multiout.max_channels = spec->channel_mode[0].channels;
-
- spec->multiout.num_dacs = preset->num_dacs;
- spec->multiout.dac_nids = preset->dac_nids;
- spec->multiout.dig_out_nid = preset->dig_out_nid;
- spec->multiout.hp_nid = preset->hp_nid;
+ switch (board_config) {
+ case ALC880_3ST_DIG:
+ case ALC880_5ST_DIG:
+ case ALC880_W810:
+ spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
+ break;
+ default:
+ break;
+ }
- spec->input_mux = preset->input_mux;
+ switch (board_config) {
+ case ALC880_3ST:
+ case ALC880_3ST_DIG:
+ case ALC880_5ST:
+ case ALC880_5ST_DIG:
+ case ALC880_W810:
+ spec->front_panel = 1;
+ break;
+ default:
+ break;
+ }
- spec->num_adc_nids = preset->num_adc_nids;
- spec->adc_nids = preset->adc_nids;
+ switch (board_config) {
+ case ALC880_5ST:
+ case ALC880_5ST_DIG:
+ spec->init_verbs = alc880_init_verbs_five_stack;
+ spec->channel_mode = alc880_fivestack_modes;
+ spec->num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes);
+ break;
+ case ALC880_W810:
+ spec->init_verbs = alc880_w810_init_verbs;
+ spec->channel_mode = alc880_w810_modes;
+ spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes);
+ break;
+ default:
+ spec->init_verbs = alc880_init_verbs_three_stack;
+ spec->channel_mode = alc880_threestack_modes;
+ spec->num_channel_mode = ARRAY_SIZE(alc880_threestack_modes);
+ break;
}
spec->stream_name_analog = "ALC880 Analog";
@@ -2134,64 +1078,34 @@ static int patch_alc880(struct hda_codec *codec)
spec->stream_digital_playback = &alc880_pcm_digital_playback;
spec->stream_digital_capture = &alc880_pcm_digital_capture;
- if (! spec->adc_nids && spec->input_mux) {
- /* check whether NID 0x07 is valid */
- unsigned int wcap = snd_hda_param_read(codec, alc880_adc_nids[0],
- AC_PAR_AUDIO_WIDGET_CAP);
- wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
- if (wcap != AC_WID_AUD_IN) {
- spec->adc_nids = alc880_adc_nids_alt;
- spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
- spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer;
- spec->num_mixers++;
- } else {
- spec->adc_nids = alc880_adc_nids;
- spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
- spec->mixers[spec->num_mixers] = alc880_capture_mixer;
- spec->num_mixers++;
- }
+ spec->multiout.max_channels = spec->channel_mode[0].channels;
+
+ switch (board_config) {
+ case ALC880_W810:
+ spec->multiout.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids);
+ spec->multiout.dac_nids = alc880_w810_dac_nids;
+ // No dedicated headphone socket - it's shared with built-in speakers.
+ break;
+ default:
+ spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids);
+ spec->multiout.dac_nids = alc880_dac_nids;
+ spec->multiout.hp_nid = 0x03; /* rear-surround NID */
+ break;
}
+ spec->input_mux = &alc880_capture_source;
+ spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
+ spec->adc_nids = alc880_adc_nids;
+
codec->patch_ops = alc_patch_ops;
- if (board_config == ALC880_AUTO)
- codec->patch_ops.init = alc880_auto_init;
return 0;
}
-
/*
* ALC260 support
*/
-static hda_nid_t alc260_dac_nids[1] = {
- /* front */
- 0x02,
-};
-
-static hda_nid_t alc260_adc_nids[1] = {
- /* ADC0 */
- 0x04,
-};
-
-static hda_nid_t alc260_hp_adc_nids[1] = {
- /* ADC1 */
- 0x05,
-};
-
-#define ALC260_DIGOUT_NID 0x03
-#define ALC260_DIGIN_NID 0x06
-
-static struct hda_input_mux alc260_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
/*
* This is just place-holder, so there's something for alc_build_pcms to look
* at when it calculates the maximum number of channels. ALC260 has no mixer
@@ -2202,9 +1116,11 @@ static struct alc_channel_mode alc260_modes[1] = {
{ 2, NULL },
};
-static snd_kcontrol_new_t alc260_base_mixer[] = {
+snd_kcontrol_new_t alc260_base_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
+ /* use LINE2 for the output */
+ /* HDA_CODEC_MUTE("Front Playback Switch", 0x0f, 0x0, HDA_OUTPUT), */
+ HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
@@ -2216,9 +1132,9 @@ static snd_kcontrol_new_t alc260_base_mixer[] = {
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
{
@@ -2231,91 +1147,60 @@ static snd_kcontrol_new_t alc260_base_mixer[] = {
{ } /* end */
};
-static snd_kcontrol_new_t alc260_hp_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
- { } /* end */
-};
-
static struct hda_verb alc260_init_verbs[] = {
/* Line In pin widget for input */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
/* CD pin widget for input */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
/* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
/* Mic2 (front panel) pin widget for input and vref at 80% */
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
/* LINE-2 is used for line-out in rear */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
/* select line-out */
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
/* LINE-OUT pin */
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
/* enable HP */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
/* enable Mono */
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* mute capture amp left and right */
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* unmute amp left and right */
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
/* set connection select to line in (default select for this ADC) */
{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* mute capture amp left and right */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* set connection select to line in (default select for this ADC) */
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* set vol=0 Line-Out mixer amp left and right */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* unmute pin widget amp left and right (no gain on this amp) */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* set vol=0 HP mixer amp left and right */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* unmute pin widget amp left and right (no gain on this amp) */
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* set vol=0 Mono mixer amp left and right */
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* unmute pin widget amp left and right (no gain on this amp) */
- {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* unmute LINE-2 out pin */
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* unmute Line-Out mixer amp left and right (volume = 0) */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* unmute HP mixer amp left and right (volume = 0) */
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* unmute Mono mixer amp left and right (volume = 0) */
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* mute LINE-2 out */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
- /* mute CD */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
- /* mute Line In */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- /* mute Mic */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ /* unmute CD */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
+ /* unmute Line In */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
+ /* unmute Mic */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
- /* mute Front out path */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* mute Headphone out path */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* mute Mono out path */
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ /* Unmute Front out path */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute Headphone out path */
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute Mono out path */
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
{ }
};
@@ -2323,52 +1208,30 @@ static struct hda_pcm_stream alc260_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
+ .nid = 0x2,
};
static struct hda_pcm_stream alc260_pcm_analog_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
-};
-
-static struct hda_board_config alc260_cfg_tbl[] = {
- { .modelname = "hp", .config = ALC260_HP },
- { .pci_subvendor = 0x103c, .config = ALC260_HP },
- {}
+ .nid = 0x4,
};
static int patch_alc260(struct hda_codec *codec)
{
struct alc_spec *spec;
- int board_config;
spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
- init_MUTEX(&spec->bind_mutex);
codec->spec = spec;
- board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl);
- if (board_config < 0 || board_config >= ALC260_MODEL_LAST) {
- snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n");
- board_config = ALC260_BASIC;
- }
-
- switch (board_config) {
- case ALC260_HP:
- spec->mixers[spec->num_mixers] = alc260_hp_mixer;
- spec->num_mixers++;
- break;
- default:
- spec->mixers[spec->num_mixers] = alc260_base_mixer;
- spec->num_mixers++;
- break;
- }
-
- spec->init_verbs[0] = alc260_init_verbs;
- spec->num_init_verbs = 1;
+ spec->mixers[spec->num_mixers] = alc260_base_mixer;
+ spec->num_mixers++;
+ spec->init_verbs = alc260_init_verbs;
spec->channel_mode = alc260_modes;
spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
@@ -2381,23 +1244,14 @@ static int patch_alc260(struct hda_codec *codec)
spec->multiout.dac_nids = alc260_dac_nids;
spec->input_mux = &alc260_capture_source;
- switch (board_config) {
- case ALC260_HP:
- spec->num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids);
- spec->adc_nids = alc260_hp_adc_nids;
- break;
- default:
- spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
- spec->adc_nids = alc260_adc_nids;
- break;
- }
+ spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
+ spec->adc_nids = alc260_adc_nids;
codec->patch_ops = alc_patch_ops;
return 0;
}
-
/*
* ALC882 support
*
@@ -2470,15 +1324,15 @@ static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u
*/
static snd_kcontrol_new_t alc882_base_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+ HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+ HDA_CODEC_MUTE("Side Playback Switch", 0x17, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
@@ -2510,80 +1364,89 @@ static snd_kcontrol_new_t alc882_base_mixer[] = {
static struct hda_verb alc882_init_verbs[] = {
/* Front mixer: unmute input/output amp left and right (volume = 0) */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
/* Rear mixer */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
/* CLFE mixer */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
/* Side mixer */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
- /* Front Pin: output 0 (0x0c) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+
+ /* Front Pin: to output mode */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* Front Pin: mute amp left and right (no volume) */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* select Front mixer (0x0c, index 0) */
{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Rear Pin: output 1 (0x0d) */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Rear Pin */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* Rear Pin: mute amp left and right (no volume) */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* select Rear mixer (0x0d, index 1) */
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* CLFE Pin: output 2 (0x0e) */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* CLFE Pin */
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* CLFE Pin: mute amp left and right (no volume) */
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* select CLFE mixer (0x0e, index 2) */
{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* Side Pin: output 3 (0x0f) */
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Side Pin */
+ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* Side Pin: mute amp left and right (no volume) */
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* select Side mixer (0x0f, index 3) */
{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
- /* Mic (rear) pin: input vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Front Mic pin: input vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line In pin: input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line-2 In: Headphone output (output 0 - 0x0c) */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Headphone Pin */
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* Headphone Pin: mute amp left and right (no volume) */
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* select Front mixer (0x0c, index 0) */
{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* Mic (rear) pin widget for input and vref at 80% */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* Front Mic pin widget for input and vref at 80% */
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* Line In pin widget for input */
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
/* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
/* FIXME: use matrix-type input source selection */
/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
/* Input mixer2 */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
/* Input mixer3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* ADC1: mute amp left and right */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* ADC2: mute amp left and right */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* ADC3: mute amp left and right */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+ /* ADC1: unmute amp left and right */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+ /* ADC2: unmute amp left and right */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+ /* ADC3: unmute amp left and right */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+
+ /* Unmute front loopback */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute rear loopback */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Mute CLFE loopback */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
+ /* Unmute side loopback */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
{ }
};
@@ -2596,7 +1459,6 @@ static int patch_alc882(struct hda_codec *codec)
if (spec == NULL)
return -ENOMEM;
- init_MUTEX(&spec->bind_mutex);
codec->spec = spec;
spec->mixers[spec->num_mixers] = alc882_base_mixer;
@@ -2604,9 +1466,8 @@ static int patch_alc882(struct hda_codec *codec)
spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
spec->dig_in_nid = ALC880_DIGIN_NID;
- spec->init_verbs[0] = alc882_init_verbs;
- spec->num_init_verbs = 1;
-
+ spec->front_panel = 1;
+ spec->init_verbs = alc882_init_verbs;
spec->channel_mode = alc882_ch_modes;
spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes);
diff --git a/trunk/sound/pci/hda/patch_sigmatel.c b/trunk/sound/pci/hda/patch_sigmatel.c
deleted file mode 100644
index 013be2ea513a..000000000000
--- a/trunk/sound/pci/hda/patch_sigmatel.c
+++ /dev/null
@@ -1,666 +0,0 @@
-/*
- * Universal Interface for Intel High Definition Audio Codec
- *
- * HD audio interface patch for SigmaTel STAC92xx
- *
- * Copyright (c) 2005 Embedded Alley Solutions, Inc.
- *
- *
- * Based on patch_cmedia.c and patch_realtek.c
- * Copyright (c) 2004 Takashi Iwai
- *
- * This driver is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This driver is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include "hda_codec.h"
-#include "hda_local.h"
-
-#undef STAC_TEST
-
-struct sigmatel_spec {
- /* playback */
- struct hda_multi_out multiout;
- hda_nid_t playback_nid;
-
- /* capture */
- hda_nid_t *adc_nids;
- unsigned int num_adcs;
- hda_nid_t *mux_nids;
- unsigned int num_muxes;
- hda_nid_t capture_nid;
- hda_nid_t dig_in_nid;
-
- /* power management*/
- hda_nid_t *pstate_nids;
- unsigned int num_pstates;
-
- /* pin widgets */
- hda_nid_t *pin_nids;
- unsigned int num_pins;
-#ifdef STAC_TEST
- unsigned int *pin_configs;
-#endif
-
- /* codec specific stuff */
- struct hda_verb *init;
- snd_kcontrol_new_t *mixer;
-
- /* capture source */
- struct hda_input_mux input_mux;
- char input_labels[HDA_MAX_NUM_INPUTS][16];
- unsigned int cur_mux[2];
-
- /* channel mode */
- unsigned int num_ch_modes;
- unsigned int cur_ch_mode;
- const struct sigmatel_channel_mode *channel_modes;
-
- struct hda_pcm pcm_rec[1]; /* PCM information */
-};
-
-static hda_nid_t stac9200_adc_nids[1] = {
- 0x03,
-};
-
-static hda_nid_t stac9200_mux_nids[1] = {
- 0x0c,
-};
-
-static hda_nid_t stac9200_dac_nids[1] = {
- 0x02,
-};
-
-static hda_nid_t stac9200_pstate_nids[3] = {
- 0x01, 0x02, 0x03,
-};
-
-static hda_nid_t stac9200_pin_nids[8] = {
- 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
-};
-
-static hda_nid_t stac922x_adc_nids[2] = {
- 0x06, 0x07,
-};
-
-static hda_nid_t stac922x_mux_nids[2] = {
- 0x12, 0x13,
-};
-
-static hda_nid_t stac922x_dac_nids[4] = {
- 0x02, 0x03, 0x04, 0x05,
-};
-
-static hda_nid_t stac922x_pstate_nids[8] = {
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x11,
-};
-
-static hda_nid_t stac922x_pin_nids[10] = {
- 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
- 0x0f, 0x10, 0x11, 0x15, 0x1b,
-};
-
-static int stac92xx_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
- return snd_hda_input_mux_info(&spec->input_mux, uinfo);
-}
-
-static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
- unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
- ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
- return 0;
-}
-
-static int stac92xx_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
- unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
- return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol,
- spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]);
-}
-
-static struct hda_verb stac9200_ch2_init[] = {
- /* set dac0mux for dac converter */
- { 0x07, 0x701, 0x00},
- {}
-};
-
-static struct hda_verb stac922x_ch2_init[] = {
- /* set master volume and direct control */
- { 0x16, 0x70f, 0xff},
- {}
-};
-
-struct sigmatel_channel_mode {
- unsigned int channels;
- const struct hda_verb *sequence;
-};
-
-static snd_kcontrol_new_t stac9200_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Input Source",
- .count = 1,
- .info = stac92xx_mux_enum_info,
- .get = stac92xx_mux_enum_get,
- .put = stac92xx_mux_enum_put,
- },
- HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Input Mux Volume", 0x0c, 0, HDA_OUTPUT),
- { } /* end */
-};
-
-static snd_kcontrol_new_t stac922x_mixer[] = {
- HDA_CODEC_VOLUME("PCM Playback Volume", 0x2, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("PCM Playback Switch", 0x2, 0x0, HDA_OUTPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Input Source",
- .count = 1,
- .info = stac92xx_mux_enum_info,
- .get = stac92xx_mux_enum_get,
- .put = stac92xx_mux_enum_put,
- },
- HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT),
- { } /* end */
-};
-
-static int stac92xx_build_controls(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
- int err;
-
- err = snd_hda_add_new_ctls(codec, spec->mixer);
- if (err < 0)
- return err;
- if (spec->multiout.dig_out_nid) {
- err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
- if (err < 0)
- return err;
- }
- if (spec->dig_in_nid) {
- err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
- if (err < 0)
- return err;
- }
- return 0;
-}
-
-#ifdef STAC_TEST
-static unsigned int stac9200_pin_configs[8] = {
- 0x01c47010, 0x01447010, 0x0221401f, 0x01114010,
- 0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
-};
-
-static unsigned int stac922x_pin_configs[14] = {
- 0x40000100, 0x40000100, 0x40000100, 0x01114010,
- 0x01813122, 0x40000100, 0x01447010, 0x01c47010,
- 0x40000100, 0x40000100,
-};
-
-static void stac92xx_set_config_regs(struct hda_codec *codec)
-{
- int i;
- struct sigmatel_spec *spec = codec->spec;
- unsigned int pin_cfg;
-
- for (i=0; i < spec->num_pins; i++) {
- snd_hda_codec_write(codec, spec->pin_nids[i], 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
- spec->pin_configs[i] & 0x000000ff);
- snd_hda_codec_write(codec, spec->pin_nids[i], 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
- (spec->pin_configs[i] & 0x0000ff00) >> 8);
- snd_hda_codec_write(codec, spec->pin_nids[i], 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
- (spec->pin_configs[i] & 0x00ff0000) >> 16);
- snd_hda_codec_write(codec, spec->pin_nids[i], 0,
- AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
- spec->pin_configs[i] >> 24);
- pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
- AC_VERB_GET_CONFIG_DEFAULT,
- 0x00);
- printk("pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg);
- }
-}
-#endif
-
-static int stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, unsigned int value)
-{
- unsigned int pin_ctl;
-
- pin_ctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL,
- 0x00);
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- pin_ctl | value);
-
- return 0;
-}
-
-static int stac92xx_set_vref(struct hda_codec *codec, hda_nid_t nid)
-{
- unsigned int vref_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) >> AC_PINCAP_VREF_SHIFT;
- unsigned int vref_ctl = AC_PINCTL_VREF_HIZ;
-
- if (vref_caps & AC_PINCAP_VREF_100)
- vref_ctl = AC_PINCTL_VREF_100;
- else if (vref_caps & AC_PINCAP_VREF_80)
- vref_ctl = AC_PINCTL_VREF_80;
- else if (vref_caps & AC_PINCAP_VREF_50)
- vref_ctl = AC_PINCTL_VREF_50;
- else if (vref_caps & AC_PINCAP_VREF_GRD)
- vref_ctl = AC_PINCTL_VREF_GRD;
-
- stac92xx_set_pinctl(codec, nid, vref_ctl);
-
- return 0;
-}
-
-/*
- * retrieve the default device type from the default config value
- */
-#define get_defcfg_type(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
-#define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
-
-static int stac92xx_config_pin(struct hda_codec *codec, hda_nid_t nid, unsigned int pin_cfg)
-{
- struct sigmatel_spec *spec = codec->spec;
- u32 location = get_defcfg_location(pin_cfg);
- char *label;
- const char *type = NULL;
- int ainput = 0;
-
- switch(get_defcfg_type(pin_cfg)) {
- case AC_JACK_HP_OUT:
- /* Enable HP amp */
- stac92xx_set_pinctl(codec, nid, AC_PINCTL_HP_EN);
- /* Fall through */
- case AC_JACK_SPDIF_OUT:
- case AC_JACK_LINE_OUT:
- case AC_JACK_SPEAKER:
- /* Enable output */
- stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
- break;
- case AC_JACK_SPDIF_IN:
- stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
- break;
- case AC_JACK_MIC_IN:
- if ((location & 0x0f) == AC_JACK_LOC_FRONT)
- type = "Front Mic";
- else
- type = "Mic";
- ainput = 1;
- /* Set vref */
- stac92xx_set_vref(codec, nid);
- stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
- break;
- case AC_JACK_CD:
- type = "CD";
- ainput = 1;
- stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
- break;
- case AC_JACK_LINE_IN:
- if ((location & 0x0f) == AC_JACK_LOC_FRONT)
- type = "Front Line";
- else
- type = "Line";
- ainput = 1;
- stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
- break;
- case AC_JACK_AUX:
- if ((location & 0x0f) == AC_JACK_LOC_FRONT)
- type = "Front Aux";
- else
- type = "Aux";
- ainput = 1;
- stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
- break;
- }
-
- if (ainput) {
- hda_nid_t con_lst[HDA_MAX_NUM_INPUTS];
- int i, j, num_cons, index = -1;
- if (!type)
- type = "Input";
- label = spec->input_labels[spec->input_mux.num_items];
- strcpy(label, type);
- spec->input_mux.items[spec->input_mux.num_items].label = label;
- for (i=0; inum_muxes; i++) {
- num_cons = snd_hda_get_connections(codec, spec->mux_nids[i], con_lst, HDA_MAX_NUM_INPUTS);
- for (j=0; j= 0)
- break;
- }
- spec->input_mux.items[spec->input_mux.num_items].index = index;
- spec->input_mux.num_items++;
- }
-
- return 0;
-}
-
-static int stac92xx_config_pins(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
- int i;
- unsigned int pin_cfg;
-
- for (i=0; i < spec->num_pins; i++) {
- /* Default to disabled */
- snd_hda_codec_write(codec, spec->pin_nids[i], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- 0x00);
-
- pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
- AC_VERB_GET_CONFIG_DEFAULT,
- 0x00);
- if (((pin_cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) == AC_JACK_PORT_NONE)
- continue; /* Move on */
-
- stac92xx_config_pin(codec, spec->pin_nids[i], pin_cfg);
- }
-
- return 0;
-}
-
-static int stac92xx_init(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
- int i;
-
- for (i=0; i < spec->num_pstates; i++)
- snd_hda_codec_write(codec, spec->pstate_nids[i], 0,
- AC_VERB_SET_POWER_STATE, 0x00);
-
- mdelay(100);
-
- snd_hda_sequence_write(codec, spec->init);
-
-#ifdef STAC_TEST
- stac92xx_set_config_regs(codec);
-#endif
-
- stac92xx_config_pins(codec);
-
- return 0;
-}
-
-/*
- * Analog playback callbacks
- */
-static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct sigmatel_spec *spec = codec->spec;
- return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
-}
-
-static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- snd_pcm_substream_t *substream)
-{
- struct sigmatel_spec *spec = codec->spec;
- return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
- format, substream);
-}
-
-static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct sigmatel_spec *spec = codec->spec;
- return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
-}
-
-/*
- * Digital playback callbacks
- */
-static int stac92xx_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct sigmatel_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct sigmatel_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-
-/*
- * Analog capture callbacks
- */
-static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- snd_pcm_substream_t *substream)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
- stream_tag, 0, format);
- return 0;
-}
-
-static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
- return 0;
-}
-
-static struct hda_pcm_stream stac92xx_pcm_digital_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- /* NID is set in stac92xx_build_pcms */
- .ops = {
- .open = stac92xx_dig_playback_pcm_open,
- .close = stac92xx_dig_playback_pcm_close
- },
-};
-
-static struct hda_pcm_stream stac92xx_pcm_digital_capture = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- /* NID is set in stac92xx_build_pcms */
-};
-
-static struct hda_pcm_stream stac92xx_pcm_analog_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- .nid = 0x02, /* NID to query formats and rates */
- .ops = {
- .open = stac92xx_playback_pcm_open,
- .prepare = stac92xx_playback_pcm_prepare,
- .cleanup = stac92xx_playback_pcm_cleanup
- },
-};
-
-static struct hda_pcm_stream stac92xx_pcm_analog_capture = {
- .substreams = 2,
- .channels_min = 2,
- .channels_max = 2,
- .nid = 0x06, /* NID to query formats and rates */
- .ops = {
- .prepare = stac92xx_capture_pcm_prepare,
- .cleanup = stac92xx_capture_pcm_cleanup
- },
-};
-
-static int stac92xx_build_pcms(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
- struct hda_pcm *info = spec->pcm_rec;
-
- codec->num_pcms = 1;
- codec->pcm_info = info;
-
- info->name = "STAC92xx";
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->playback_nid;
- info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->capture_nid;
-
- if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
- codec->num_pcms++;
- info++;
- info->name = "STAC92xx Digital";
- if (spec->multiout.dig_out_nid) {
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
- }
- if (spec->dig_in_nid) {
- info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_digital_capture;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
- }
- }
-
- return 0;
-}
-
-static void stac92xx_free(struct hda_codec *codec)
-{
- kfree(codec->spec);
-}
-
-static struct hda_codec_ops stac92xx_patch_ops = {
- .build_controls = stac92xx_build_controls,
- .build_pcms = stac92xx_build_pcms,
- .init = stac92xx_init,
- .free = stac92xx_free,
-};
-
-static int patch_stac9200(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec;
-
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
-
- spec->multiout.max_channels = 2;
- spec->multiout.num_dacs = 1;
- spec->multiout.dac_nids = stac9200_dac_nids;
- spec->multiout.dig_out_nid = 0x05;
- spec->dig_in_nid = 0x04;
- spec->adc_nids = stac9200_adc_nids;
- spec->mux_nids = stac9200_mux_nids;
- spec->num_muxes = 1;
- spec->input_mux.num_items = 0;
- spec->pstate_nids = stac9200_pstate_nids;
- spec->num_pstates = 3;
- spec->pin_nids = stac9200_pin_nids;
-#ifdef STAC_TEST
- spec->pin_configs = stac9200_pin_configs;
-#endif
- spec->num_pins = 8;
- spec->init = stac9200_ch2_init;
- spec->mixer = stac9200_mixer;
- spec->playback_nid = 0x02;
- spec->capture_nid = 0x03;
-
- codec->patch_ops = stac92xx_patch_ops;
-
- return 0;
-}
-
-static int patch_stac922x(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec;
-
- spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- codec->spec = spec;
-
- spec->multiout.max_channels = 2;
- spec->multiout.num_dacs = 4;
- spec->multiout.dac_nids = stac922x_dac_nids;
- spec->multiout.dig_out_nid = 0x08;
- spec->dig_in_nid = 0x09;
- spec->adc_nids = stac922x_adc_nids;
- spec->mux_nids = stac922x_mux_nids;
- spec->num_muxes = 2;
- spec->input_mux.num_items = 0;
- spec->pstate_nids = stac922x_pstate_nids;
- spec->num_pstates = 8;
- spec->pin_nids = stac922x_pin_nids;
-#ifdef STAC_TEST
- spec->pin_configs = stac922x_pin_configs;
-#endif
- spec->num_pins = 10;
- spec->init = stac922x_ch2_init;
- spec->mixer = stac922x_mixer;
- spec->playback_nid = 0x02;
- spec->capture_nid = 0x06;
-
- codec->patch_ops = stac92xx_patch_ops;
-
- return 0;
-}
-
-/*
- * patch entries
- */
-struct hda_codec_preset snd_hda_preset_sigmatel[] = {
- { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 },
- { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x },
- { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x },
- { .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x },
- { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x },
- { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x },
- { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x },
- {} /* terminator */
-};
diff --git a/trunk/sound/pci/ice1712/amp.c b/trunk/sound/pci/ice1712/amp.c
index 289b0b5711e4..779951725e1e 100644
--- a/trunk/sound/pci/ice1712/amp.c
+++ b/trunk/sound/pci/ice1712/amp.c
@@ -30,39 +30,16 @@
#include
#include "ice1712.h"
-#include "envy24ht.h"
#include "amp.h"
-static void wm_put(ice1712_t *ice, int reg, unsigned short val)
-{
- unsigned short cval;
- cval = (reg << 9) | val;
- snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
-}
static int __devinit snd_vt1724_amp_init(ice1712_t *ice)
{
- static unsigned short wm_inits[] = {
- WM_ATTEN_L, 0x0000, /* 0 db */
- WM_ATTEN_R, 0x0000, /* 0 db */
- WM_DAC_CTRL, 0x0008, /* 24bit I2S */
- WM_INT_CTRL, 0x0001, /* 24bit I2S */
- };
-
- unsigned int i;
-
/* only use basic functionality for now */
ice->num_total_dacs = 2; /* only PSDOUT0 is connected */
ice->num_total_adcs = 2;
- /* Chaintech AV-710 has another codecs, which need initialization */
- /* initialize WM8728 codec */
- if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AV710) {
- for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2)
- wm_put(ice, wm_inits[i], wm_inits[i+1]);
- }
-
return 0;
}
@@ -76,13 +53,6 @@ static int __devinit snd_vt1724_amp_add_controls(ice1712_t *ice)
/* entry point */
struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = {
- {
- .subvendor = VT1724_SUBDEVICE_AV710,
- .name = "Chaintech AV-710",
- .model = "av710",
- .chip_init = snd_vt1724_amp_init,
- .build_controls = snd_vt1724_amp_add_controls,
- },
{
.subvendor = VT1724_SUBDEVICE_AUDIO2000,
.name = "AMP Ltd AUDIO2000",
diff --git a/trunk/sound/pci/ice1712/amp.h b/trunk/sound/pci/ice1712/amp.h
index a0fc89b48122..d58d43383e83 100644
--- a/trunk/sound/pci/ice1712/amp.h
+++ b/trunk/sound/pci/ice1712/amp.h
@@ -24,23 +24,9 @@
*
*/
-#define AMP_AUDIO2000_DEVICE_DESC "{AMP Ltd,AUDIO2000},"\
- "{Chaintech,AV-710},"
+#define AMP_AUDIO2000_DEVICE_DESC "{AMP Ltd,AUDIO2000},"
-#if 0
#define VT1724_SUBDEVICE_AUDIO2000 0x12142417 /* Advanced Micro Peripherals Ltd AUDIO2000 */
-#else
-#define VT1724_SUBDEVICE_AUDIO2000 0x00030003 /* a dummy ID for AMP Audio2000 */
-#endif
-#define VT1724_SUBDEVICE_AV710 0x12142417 /* AV710 - the same ID with Audio2000! */
-
-/* WM8728 on I2C for AV710 */
-#define WM_DEV 0x36
-
-#define WM_ATTEN_L 0x00
-#define WM_ATTEN_R 0x01
-#define WM_DAC_CTRL 0x02
-#define WM_INT_CTRL 0x03
extern struct snd_ice1712_card_info snd_vt1724_amp_cards[];
diff --git a/trunk/sound/pci/ice1712/ice1712.c b/trunk/sound/pci/ice1712/ice1712.c
index a2545a5b26c4..79fba6be3503 100644
--- a/trunk/sound/pci/ice1712/ice1712.c
+++ b/trunk/sound/pci/ice1712/ice1712.c
@@ -2748,7 +2748,7 @@ static struct pci_driver driver = {
static int __init alsa_card_ice1712_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_ice1712_exit(void)
diff --git a/trunk/sound/pci/ice1712/ice1712.h b/trunk/sound/pci/ice1712/ice1712.h
index 5ad4728daa7b..8bb1c58c26a0 100644
--- a/trunk/sound/pci/ice1712/ice1712.h
+++ b/trunk/sound/pci/ice1712/ice1712.h
@@ -373,11 +373,6 @@ struct _snd_ice1712 {
unsigned short master[2];
unsigned short vol[8];
} aureon;
- /* AC97 register cache for Phase28 */
- struct phase28_spec {
- unsigned short master[2];
- unsigned short vol[8];
- } phase28;
/* Hoontech-specific setting */
struct hoontech_spec {
unsigned char boxbits[4];
diff --git a/trunk/sound/pci/ice1712/ice1724.c b/trunk/sound/pci/ice1712/ice1724.c
index 79b5f12e06fc..95500f06f0c6 100644
--- a/trunk/sound/pci/ice1712/ice1724.c
+++ b/trunk/sound/pci/ice1712/ice1724.c
@@ -2328,7 +2328,7 @@ static struct pci_driver driver = {
static int __init alsa_card_ice1724_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_ice1724_exit(void)
diff --git a/trunk/sound/pci/ice1712/phase.c b/trunk/sound/pci/ice1712/phase.c
index 5bf734b04fa0..d1f90832443c 100644
--- a/trunk/sound/pci/ice1712/phase.c
+++ b/trunk/sound/pci/ice1712/phase.c
@@ -45,47 +45,6 @@
#include "envy24ht.h"
#include "phase.h"
-/* WM8770 registers */
-#define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
-#define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
-#define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
-#define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
-#define WM_PHASE_SWAP 0x12 /* DAC phase */
-#define WM_DAC_CTRL1 0x13 /* DAC control bits */
-#define WM_MUTE 0x14 /* mute controls */
-#define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
-#define WM_INT_CTRL 0x16 /* interface control */
-#define WM_MASTER 0x17 /* master clock and mode */
-#define WM_POWERDOWN 0x18 /* power-down controls */
-#define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
-#define WM_ADC_MUX 0x1b /* input MUX */
-#define WM_OUT_MUX1 0x1c /* output MUX */
-#define WM_OUT_MUX2 0x1e /* output MUX */
-#define WM_RESET 0x1f /* software reset */
-
-
-/*
- * Logarithmic volume values for WM8770
- * Computed as 20 * Log10(255 / x)
- */
-static unsigned char wm_vol[256] = {
- 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
- 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
- 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
- 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0
-};
-
-#define WM_VOL_MAX (sizeof(wm_vol) - 1)
-#define WM_VOL_MUTE 0x8000
-
static akm4xxx_t akm_phase22 __devinitdata = {
.type = SND_AK4524,
.num_dacs = 2,
@@ -165,684 +124,6 @@ static unsigned char phase22_eeprom[] __devinitdata = {
0x00, /* GPIO_STATE2 */
};
-static unsigned char phase28_eeprom[] __devinitdata = {
- 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
- 0x80, /* ACLINK: I2S */
- 0xfc, /* I2S: vol, 96k, 24bit, 192k */
- 0xc3, /* SPDIF: out-en, out-int, spdif-in */
- 0xff, /* GPIO_DIR */
- 0xff, /* GPIO_DIR1 */
- 0x5f, /* GPIO_DIR2 */
- 0x00, /* GPIO_MASK */
- 0x00, /* GPIO_MASK1 */
- 0x00, /* GPIO_MASK2 */
- 0x00, /* GPIO_STATE */
- 0x00, /* GPIO_STATE1 */
- 0x00, /* GPIO_STATE2 */
-};
-
-/*
- * write data in the SPI mode
- */
-static void phase28_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
-{
- unsigned int tmp;
- int i;
-
- tmp = snd_ice1712_gpio_read(ice);
-
- snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI|PHASE28_SPI_CLK|
- PHASE28_WM_CS));
- tmp |= PHASE28_WM_RW;
- tmp &= ~cs;
- snd_ice1712_gpio_write(ice, tmp);
- udelay(1);
-
- for (i = bits - 1; i >= 0; i--) {
- tmp &= ~PHASE28_SPI_CLK;
- snd_ice1712_gpio_write(ice, tmp);
- udelay(1);
- if (data & (1 << i))
- tmp |= PHASE28_SPI_MOSI;
- else
- tmp &= ~PHASE28_SPI_MOSI;
- snd_ice1712_gpio_write(ice, tmp);
- udelay(1);
- tmp |= PHASE28_SPI_CLK;
- snd_ice1712_gpio_write(ice, tmp);
- udelay(1);
- }
-
- tmp &= ~PHASE28_SPI_CLK;
- tmp |= cs;
- snd_ice1712_gpio_write(ice, tmp);
- udelay(1);
- tmp |= PHASE28_SPI_CLK;
- snd_ice1712_gpio_write(ice, tmp);
- udelay(1);
-}
-
-/*
- * get the current register value of WM codec
- */
-static unsigned short wm_get(ice1712_t *ice, int reg)
-{
- reg <<= 1;
- return ((unsigned short)ice->akm[0].images[reg] << 8) |
- ice->akm[0].images[reg + 1];
-}
-
-/*
- * set the register value of WM codec
- */
-static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
-{
- phase28_spi_write(ice, PHASE28_WM_CS, (reg << 9) | (val & 0x1ff), 16);
-}
-
-/*
- * set the register value of WM codec and remember it
- */
-static void wm_put(ice1712_t *ice, int reg, unsigned short val)
-{
- wm_put_nocache(ice, reg, val);
- reg <<= 1;
- ice->akm[0].images[reg] = val >> 8;
- ice->akm[0].images[reg + 1] = val;
-}
-
-static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, unsigned short master)
-{
- unsigned char nvol;
-
- if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
- nvol = 0;
- else
- nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
-
- wm_put(ice, index, nvol);
- wm_put_nocache(ice, index, 0x180 | nvol);
-}
-
-/*
- * DAC mute control
- */
-#define wm_pcm_mute_info phase28_mono_bool_info
-
-static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
-
- down(&ice->gpio_mutex);
- ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
- up(&ice->gpio_mutex);
- return 0;
-}
-
-static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- unsigned short nval, oval;
- int change;
-
- snd_ice1712_save_gpio_status(ice);
- oval = wm_get(ice, WM_MUTE);
- nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
- if ((change = (nval != oval)))
- wm_put(ice, WM_MUTE, nval);
- snd_ice1712_restore_gpio_status(ice);
-
- return change;
-}
-
-/*
- * Master volume attenuation mixer control
- */
-static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = WM_VOL_MAX;
- return 0;
-}
-
-static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- int i;
- for (i=0; i<2; i++)
- ucontrol->value.integer.value[i] = ice->spec.phase28.master[i] & ~WM_VOL_MUTE;
- return 0;
-}
-
-static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- int ch, change = 0;
-
- snd_ice1712_save_gpio_status(ice);
- for (ch = 0; ch < 2; ch++) {
- if (ucontrol->value.integer.value[ch] != ice->spec.phase28.master[ch]) {
- int dac;
- ice->spec.phase28.master[ch] &= WM_VOL_MUTE;
- ice->spec.phase28.master[ch] |= ucontrol->value.integer.value[ch];
- for (dac = 0; dac < ice->num_total_dacs; dac += 2)
- wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
- ice->spec.phase28.vol[dac + ch],
- ice->spec.phase28.master[ch]);
- change = 1;
- }
- }
- snd_ice1712_restore_gpio_status(ice);
- return change;
-}
-
-static int __devinit phase28_init(ice1712_t *ice)
-{
- static unsigned short wm_inits_phase28[] = {
- /* These come first to reduce init pop noise */
- 0x1b, 0x044, /* ADC Mux (AC'97 source) */
- 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
- 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
-
- 0x18, 0x000, /* All power-up */
-
- 0x16, 0x122, /* I2S, normal polarity, 24bit */
- 0x17, 0x022, /* 256fs, slave mode */
- 0x00, 0, /* DAC1 analog mute */
- 0x01, 0, /* DAC2 analog mute */
- 0x02, 0, /* DAC3 analog mute */
- 0x03, 0, /* DAC4 analog mute */
- 0x04, 0, /* DAC5 analog mute */
- 0x05, 0, /* DAC6 analog mute */
- 0x06, 0, /* DAC7 analog mute */
- 0x07, 0, /* DAC8 analog mute */
- 0x08, 0x100, /* master analog mute */
- 0x09, 0xff, /* DAC1 digital full */
- 0x0a, 0xff, /* DAC2 digital full */
- 0x0b, 0xff, /* DAC3 digital full */
- 0x0c, 0xff, /* DAC4 digital full */
- 0x0d, 0xff, /* DAC5 digital full */
- 0x0e, 0xff, /* DAC6 digital full */
- 0x0f, 0xff, /* DAC7 digital full */
- 0x10, 0xff, /* DAC8 digital full */
- 0x11, 0x1ff, /* master digital full */
- 0x12, 0x000, /* phase normal */
- 0x13, 0x090, /* unmute DAC L/R */
- 0x14, 0x000, /* all unmute */
- 0x15, 0x000, /* no deemphasis, no ZFLG */
- 0x19, 0x000, /* -12dB ADC/L */
- 0x1a, 0x000, /* -12dB ADC/R */
- (unsigned short)-1
- };
-
- unsigned int tmp;
- akm4xxx_t *ak;
- unsigned short *p;
- int i;
-
- ice->num_total_dacs = 8;
- ice->num_total_adcs = 2;
-
- // Initialize analog chips
- ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
- if (!ak)
- return -ENOMEM;
- ice->akm_codecs = 1;
-
- snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
-
- /* reset the wm codec as the SPI mode */
- snd_ice1712_save_gpio_status(ice);
- snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|PHASE28_HP_SEL));
-
- tmp = snd_ice1712_gpio_read(ice);
- tmp &= ~PHASE28_WM_RESET;
- snd_ice1712_gpio_write(ice, tmp);
- udelay(1);
- tmp |= PHASE28_WM_CS;
- snd_ice1712_gpio_write(ice, tmp);
- udelay(1);
- tmp |= PHASE28_WM_RESET;
- snd_ice1712_gpio_write(ice, tmp);
- udelay(1);
-
- p = wm_inits_phase28;
- for (; *p != (unsigned short)-1; p += 2)
- wm_put(ice, p[0], p[1]);
-
- snd_ice1712_restore_gpio_status(ice);
-
- ice->spec.phase28.master[0] = WM_VOL_MUTE;
- ice->spec.phase28.master[1] = WM_VOL_MUTE;
- for (i = 0; i < ice->num_total_dacs; i++) {
- ice->spec.phase28.vol[i] = WM_VOL_MUTE;
- wm_set_vol(ice, i, ice->spec.phase28.vol[i], ice->spec.phase28.master[i % 2]);
- }
-
- return 0;
-}
-
-/*
- * DAC volume attenuation mixer control
- */
-static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
- int voices = kcontrol->private_value >> 8;
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = voices;
- uinfo->value.integer.min = 0; /* mute (-101dB) */
- uinfo->value.integer.max = 0x7F; /* 0dB */
- return 0;
-}
-
-static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- int i, ofs, voices;
-
- voices = kcontrol->private_value >> 8;
- ofs = kcontrol->private_value & 0xff;
- for (i = 0; i < voices; i++)
- ucontrol->value.integer.value[i] = ice->spec.phase28.vol[ofs+i] & ~WM_VOL_MUTE;
- return 0;
-}
-
-static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- int i, idx, ofs, voices;
- int change = 0;
-
- voices = kcontrol->private_value >> 8;
- ofs = kcontrol->private_value & 0xff;
- snd_ice1712_save_gpio_status(ice);
- for (i = 0; i < voices; i++) {
- idx = WM_DAC_ATTEN + ofs + i;
- if (ucontrol->value.integer.value[i] != ice->spec.phase28.vol[ofs+i]) {
- ice->spec.phase28.vol[ofs+i] &= WM_VOL_MUTE;
- ice->spec.phase28.vol[ofs+i] |= ucontrol->value.integer.value[i];
- wm_set_vol(ice, idx, ice->spec.phase28.vol[ofs+i],
- ice->spec.phase28.master[i]);
- change = 1;
- }
- }
- snd_ice1712_restore_gpio_status(ice);
- return change;
-}
-
-/*
- * WM8770 mute control
- */
-static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = kcontrol->private_value >> 8;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
-static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- int voices, ofs, i;
-
- voices = kcontrol->private_value >> 8;
- ofs = kcontrol->private_value & 0xFF;
-
- for (i = 0; i < voices; i++)
- ucontrol->value.integer.value[i] = (ice->spec.phase28.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
- return 0;
-}
-
-static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- int change = 0, voices, ofs, i;
-
- voices = kcontrol->private_value >> 8;
- ofs = kcontrol->private_value & 0xFF;
-
- snd_ice1712_save_gpio_status(ice);
- for (i = 0; i < voices; i++) {
- int val = (ice->spec.phase28.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
- if (ucontrol->value.integer.value[i] != val) {
- ice->spec.phase28.vol[ofs + i] &= ~WM_VOL_MUTE;
- ice->spec.phase28.vol[ofs + i] |=
- ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
- wm_set_vol(ice, ofs + i, ice->spec.phase28.vol[ofs + i],
- ice->spec.phase28.master[i]);
- change = 1;
- }
- }
- snd_ice1712_restore_gpio_status(ice);
-
- return change;
-}
-
-/*
- * WM8770 master mute control
- */
-static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
-static int wm_master_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.integer.value[0] = (ice->spec.phase28.master[0] & WM_VOL_MUTE) ? 0 : 1;
- ucontrol->value.integer.value[1] = (ice->spec.phase28.master[1] & WM_VOL_MUTE) ? 0 : 1;
- return 0;
-}
-
-static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- int change = 0, i;
-
- snd_ice1712_save_gpio_status(ice);
- for (i = 0; i < 2; i++) {
- int val = (ice->spec.phase28.master[i] & WM_VOL_MUTE) ? 0 : 1;
- if (ucontrol->value.integer.value[i] != val) {
- int dac;
- ice->spec.phase28.master[i] &= ~WM_VOL_MUTE;
- ice->spec.phase28.master[i] |=
- ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
- for (dac = 0; dac < ice->num_total_dacs; dac += 2)
- wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
- ice->spec.phase28.vol[dac + i],
- ice->spec.phase28.master[i]);
- change = 1;
- }
- }
- snd_ice1712_restore_gpio_status(ice);
-
- return change;
-}
-
-/* digital master volume */
-#define PCM_0dB 0xff
-#define PCM_RES 128 /* -64dB */
-#define PCM_MIN (PCM_0dB - PCM_RES)
-static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0; /* mute (-64dB) */
- uinfo->value.integer.max = PCM_RES; /* 0dB */
- return 0;
-}
-
-static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- unsigned short val;
-
- down(&ice->gpio_mutex);
- val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
- val = val > PCM_MIN ? (val - PCM_MIN) : 0;
- ucontrol->value.integer.value[0] = val;
- up(&ice->gpio_mutex);
- return 0;
-}
-
-static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- unsigned short ovol, nvol;
- int change = 0;
-
- snd_ice1712_save_gpio_status(ice);
- nvol = ucontrol->value.integer.value[0];
- nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
- ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
- if (ovol != nvol) {
- wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
- wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
- change = 1;
- }
- snd_ice1712_restore_gpio_status(ice);
- return change;
-}
-
-/*
- */
-static int phase28_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
-/*
- * Deemphasis
- */
-#define phase28_deemp_info phase28_mono_bool_info
-
-static int phase28_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
- return 0;
-}
-
-static int phase28_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- int temp, temp2;
- temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
- if (ucontrol->value.integer.value[0])
- temp |= 0xf;
- else
- temp &= ~0xf;
- if (temp != temp2) {
- wm_put(ice, WM_DAC_CTRL2, temp);
- return 1;
- }
- return 0;
-}
-
-/*
- * ADC Oversampling
- */
-static int phase28_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
-{
- static char *texts[2] = { "128x", "64x" };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 2;
-
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
-
- return 0;
-}
-
-static int phase28_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
- return 0;
-}
-
-static int phase28_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- int temp, temp2;
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
-
- temp2 = temp = wm_get(ice, WM_MASTER);
-
- if (ucontrol->value.enumerated.item[0])
- temp |= 0x8;
- else
- temp &= ~0x8;
-
- if (temp != temp2) {
- wm_put(ice, WM_MASTER, temp);
- return 1;
- }
- return 0;
-}
-
-static snd_kcontrol_new_t phase28_dac_controls[] __devinitdata = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .info = wm_master_mute_info,
- .get = wm_master_mute_get,
- .put = wm_master_mute_put
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Volume",
- .info = wm_master_vol_info,
- .get = wm_master_vol_get,
- .put = wm_master_vol_put
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Front Playback Switch",
- .info = wm_mute_info,
- .get = wm_mute_get,
- .put = wm_mute_put,
- .private_value = (2 << 8) | 0
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Front Playback Volume",
- .info = wm_vol_info,
- .get = wm_vol_get,
- .put = wm_vol_put,
- .private_value = (2 << 8) | 0
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Rear Playback Switch",
- .info = wm_mute_info,
- .get = wm_mute_get,
- .put = wm_mute_put,
- .private_value = (2 << 8) | 2
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Rear Playback Volume",
- .info = wm_vol_info,
- .get = wm_vol_get,
- .put = wm_vol_put,
- .private_value = (2 << 8) | 2
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Center Playback Switch",
- .info = wm_mute_info,
- .get = wm_mute_get,
- .put = wm_mute_put,
- .private_value = (1 << 8) | 4
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Center Playback Volume",
- .info = wm_vol_info,
- .get = wm_vol_get,
- .put = wm_vol_put,
- .private_value = (1 << 8) | 4
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "LFE Playback Switch",
- .info = wm_mute_info,
- .get = wm_mute_get,
- .put = wm_mute_put,
- .private_value = (1 << 8) | 5
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "LFE Playback Volume",
- .info = wm_vol_info,
- .get = wm_vol_get,
- .put = wm_vol_put,
- .private_value = (1 << 8) | 5
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Side Playback Switch",
- .info = wm_mute_info,
- .get = wm_mute_get,
- .put = wm_mute_put,
- .private_value = (2 << 8) | 6
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Side Playback Volume",
- .info = wm_vol_info,
- .get = wm_vol_get,
- .put = wm_vol_put,
- .private_value = (2 << 8) | 6
- }
-};
-
-static snd_kcontrol_new_t wm_controls[] __devinitdata = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Playback Switch",
- .info = wm_pcm_mute_info,
- .get = wm_pcm_mute_get,
- .put = wm_pcm_mute_put
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "PCM Playback Volume",
- .info = wm_pcm_vol_info,
- .get = wm_pcm_vol_get,
- .put = wm_pcm_vol_put
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "DAC Deemphasis Switch",
- .info = phase28_deemp_info,
- .get = phase28_deemp_get,
- .put = phase28_deemp_put
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "ADC Oversampling",
- .info = phase28_oversampling_info,
- .get = phase28_oversampling_get,
- .put = phase28_oversampling_put
- }
-};
-
-static int __devinit phase28_add_controls(ice1712_t *ice)
-{
- unsigned int i, counts;
- int err;
-
- counts = ARRAY_SIZE(phase28_dac_controls);
- for (i = 0; i < counts; i++) {
- err = snd_ctl_add(ice->card, snd_ctl_new1(&phase28_dac_controls[i], ice));
- if (err < 0)
- return err;
- }
-
- for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
- err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
{
.subvendor = VT1724_SUBDEVICE_PHASE22,
@@ -853,14 +134,5 @@ struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
.eeprom_size = sizeof(phase22_eeprom),
.eeprom_data = phase22_eeprom,
},
- {
- .subvendor = VT1724_SUBDEVICE_PHASE28,
- .name = "Terratec PHASE 28",
- .model = "phase28",
- .chip_init = phase28_init,
- .build_controls = phase28_add_controls,
- .eeprom_size = sizeof(phase28_eeprom),
- .eeprom_data = phase28_eeprom,
- },
{ } /* terminator */
};
diff --git a/trunk/sound/pci/ice1712/phase.h b/trunk/sound/pci/ice1712/phase.h
index 13e841b55488..6230cf16989f 100644
--- a/trunk/sound/pci/ice1712/phase.h
+++ b/trunk/sound/pci/ice1712/phase.h
@@ -24,28 +24,11 @@
*
*/
-#define PHASE_DEVICE_DESC "{Terratec,Phase 22},"\
- "{Terratec,Phase 28},"
+#define PHASE_DEVICE_DESC "{Terratec,Phase 22},"
#define VT1724_SUBDEVICE_PHASE22 0x3b155011
-#define VT1724_SUBDEVICE_PHASE28 0x3b154911
/* entry point */
extern struct snd_ice1712_card_info snd_vt1724_phase_cards[];
-/* PHASE28 GPIO bits */
-#define PHASE28_SPI_MISO (1 << 21)
-#define PHASE28_WM_RESET (1 << 20)
-#define PHASE28_SPI_CLK (1 << 19)
-#define PHASE28_SPI_MOSI (1 << 18)
-#define PHASE28_WM_RW (1 << 17)
-#define PHASE28_AC97_RESET (1 << 16)
-#define PHASE28_DIGITAL_SEL1 (1 << 15)
-#define PHASE28_HP_SEL (1 << 14)
-#define PHASE28_WM_CS (1 << 12)
-#define PHASE28_AC97_COMMIT (1 << 11)
-#define PHASE28_AC97_ADDR (1 << 10)
-#define PHASE28_AC97_DATA_LOW (1 << 9)
-#define PHASE28_AC97_DATA_HIGH (1 << 8)
-#define PHASE28_AC97_DATA_MASK 0xFF
#endif /* __SOUND_PHASE */
diff --git a/trunk/sound/pci/ice1712/vt1720_mobo.c b/trunk/sound/pci/ice1712/vt1720_mobo.c
index ab61e383024f..3bd92627231c 100644
--- a/trunk/sound/pci/ice1712/vt1720_mobo.c
+++ b/trunk/sound/pci/ice1712/vt1720_mobo.c
@@ -110,15 +110,6 @@ struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
.eeprom_size = sizeof(k8x800_eeprom),
.eeprom_data = k8x800_eeprom,
},
- {
- .subvendor = VT1720_SUBDEVICE_SN25P,
- .name = "Shuttle SN25P",
- /* identical with k8x800 */
- .chip_init = k8x800_init,
- .build_controls = k8x800_add_controls,
- .eeprom_size = sizeof(k8x800_eeprom),
- .eeprom_data = k8x800_eeprom,
- },
{ } /* terminator */
};
diff --git a/trunk/sound/pci/ice1712/vt1720_mobo.h b/trunk/sound/pci/ice1712/vt1720_mobo.h
index 0b1b0ee1bea7..f949eb804cae 100644
--- a/trunk/sound/pci/ice1712/vt1720_mobo.h
+++ b/trunk/sound/pci/ice1712/vt1720_mobo.h
@@ -27,14 +27,12 @@
#define VT1720_MOBO_DEVICE_DESC "{Albatron,K8X800 Pro II},"\
"{Chaintech,ZNF3-150},"\
"{Chaintech,ZNF3-250},"\
- "{Chaintech,9CJS},"\
- "{Shuttle,SN25P},"
+ "{Chaintech,9CJS},"
#define VT1720_SUBDEVICE_K8X800 0xf217052c
#define VT1720_SUBDEVICE_ZNF3_150 0x0f2741f6
#define VT1720_SUBDEVICE_ZNF3_250 0x0f2745f6
#define VT1720_SUBDEVICE_9CJS 0x0f272327
-#define VT1720_SUBDEVICE_SN25P 0x97123650
extern struct snd_ice1712_card_info snd_vt1720_mobo_cards[];
diff --git a/trunk/sound/pci/intel8x0.c b/trunk/sound/pci/intel8x0.c
index cc16f95f9cef..8b33b12fa5dc 100644
--- a/trunk/sound/pci/intel8x0.c
+++ b/trunk/sound/pci/intel8x0.c
@@ -1725,235 +1725,229 @@ static struct ac97_pcm ac97_pcm_defs[] __devinitdata = {
static struct ac97_quirk ac97_quirks[] __devinitdata = {
{
- .subvendor = 0x0e11,
- .subdevice = 0x008a,
+ .vendor = 0x0e11,
+ .device = 0x008a,
.name = "Compaq Evo W4000", /* AD1885 */
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x0e11,
- .subdevice = 0x00b8,
+ .vendor = 0x0e11,
+ .device = 0x00b8,
.name = "Compaq Evo D510C",
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x0e11,
- .subdevice = 0x0860,
+ .vendor = 0x0e11,
+ .device = 0x0860,
.name = "HP/Compaq nx7010",
.type = AC97_TUNE_MUTE_LED
},
{
- .subvendor = 0x1014,
- .subdevice = 0x1f00,
+ .vendor = 0x1014,
+ .device = 0x1f00,
.name = "MS-9128",
.type = AC97_TUNE_ALC_JACK
},
{
- .subvendor = 0x1028,
- .subdevice = 0x00d8,
+ .vendor = 0x1028,
+ .device = 0x00d8,
.name = "Dell Precision 530", /* AD1885 */
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x1028,
- .subdevice = 0x010d,
+ .vendor = 0x1028,
+ .device = 0x010d,
.name = "Dell", /* which model? AD1885 */
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x1028,
- .subdevice = 0x0126,
+ .vendor = 0x1028,
+ .device = 0x0126,
.name = "Dell Optiplex GX260", /* AD1981A */
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x1028,
- .subdevice = 0x012c,
+ .vendor = 0x1028,
+ .device = 0x012c,
.name = "Dell Precision 650", /* AD1981A */
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x1028,
- .subdevice = 0x012d,
+ .vendor = 0x1028,
+ .device = 0x012d,
.name = "Dell Precision 450", /* AD1981B*/
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x1028,
- .subdevice = 0x0147,
+ .vendor = 0x1028,
+ .device = 0x0147,
.name = "Dell", /* which model? AD1981B*/
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x1028,
- .subdevice = 0x0163,
+ .vendor = 0x1028,
+ .device = 0x0163,
.name = "Dell Unknown", /* STAC9750/51 */
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x103c,
- .subdevice = 0x006d,
+ .vendor = 0x103c,
+ .device = 0x006d,
.name = "HP zv5000",
.type = AC97_TUNE_MUTE_LED /*AD1981B*/
},
{ /* FIXME: which codec? */
- .subvendor = 0x103c,
- .subdevice = 0x00c3,
+ .vendor = 0x103c,
+ .device = 0x00c3,
.name = "HP xw6000",
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x103c,
- .subdevice = 0x088c,
+ .vendor = 0x103c,
+ .device = 0x088c,
.name = "HP nc8000",
.type = AC97_TUNE_MUTE_LED
},
{
- .subvendor = 0x103c,
- .subdevice = 0x0890,
+ .vendor = 0x103c,
+ .device = 0x0890,
.name = "HP nc6000",
.type = AC97_TUNE_MUTE_LED
},
{
- .subvendor = 0x103c,
- .subdevice = 0x129d,
+ .vendor = 0x103c,
+ .device = 0x129d,
.name = "HP xw8000",
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x103c,
- .subdevice = 0x12f1,
+ .vendor = 0x103c,
+ .device = 0x12f1,
.name = "HP xw8200", /* AD1981B*/
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x103c,
- .subdevice = 0x12f2,
+ .vendor = 0x103c,
+ .device = 0x12f2,
.name = "HP xw6200",
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x103c,
- .subdevice = 0x3008,
+ .vendor = 0x103c,
+ .device = 0x3008,
.name = "HP xw4200", /* AD1981B*/
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x104d,
- .subdevice = 0x8197,
+ .vendor = 0x104d,
+ .device = 0x8197,
.name = "Sony S1XP",
.type = AC97_TUNE_INV_EAPD
},
{
- .subvendor = 0x1043,
- .subdevice = 0x80f3,
+ .vendor = 0x1043,
+ .device = 0x80f3,
.name = "ASUS ICH5/AD1985",
.type = AC97_TUNE_AD_SHARING
},
{
- .subvendor = 0x10cf,
- .subdevice = 0x11c3,
+ .vendor = 0x10cf,
+ .device = 0x11c3,
.name = "Fujitsu-Siemens E4010",
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x10cf,
- .subdevice = 0x1225,
- .name = "Fujitsu-Siemens T3010",
- .type = AC97_TUNE_HP_ONLY
- },
- {
- .subvendor = 0x10cf,
- .subdevice = 0x1253,
+ .vendor = 0x10cf,
+ .device = 0x1253,
.name = "Fujitsu S6210", /* STAC9750/51 */
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x10f1,
- .subdevice = 0x2665,
+ .vendor = 0x10f1,
+ .device = 0x2665,
.name = "Fujitsu-Siemens Celsius", /* AD1981? */
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x10f1,
- .subdevice = 0x2885,
+ .vendor = 0x10f1,
+ .device = 0x2885,
.name = "AMD64 Mobo", /* ALC650 */
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x110a,
- .subdevice = 0x0056,
+ .vendor = 0x110a,
+ .device = 0x0056,
.name = "Fujitsu-Siemens Scenic", /* AD1981? */
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x11d4,
- .subdevice = 0x5375,
+ .vendor = 0x11d4,
+ .device = 0x5375,
.name = "ADI AD1985 (discrete)",
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x1462,
- .subdevice = 0x5470,
+ .vendor = 0x1462,
+ .device = 0x5470,
.name = "MSI P4 ATX 645 Ultra",
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x1734,
- .subdevice = 0x0088,
+ .vendor = 0x1734,
+ .device = 0x0088,
.name = "Fujitsu-Siemens D1522", /* AD1981 */
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x8086,
- .subdevice = 0x2000,
+ .vendor = 0x8086,
+ .device = 0x2000,
.mask = 0xfff0,
.name = "Intel ICH5/AD1985",
.type = AC97_TUNE_AD_SHARING
},
{
- .subvendor = 0x8086,
- .subdevice = 0x4000,
+ .vendor = 0x8086,
+ .device = 0x4000,
.mask = 0xfff0,
.name = "Intel ICH5/AD1985",
.type = AC97_TUNE_AD_SHARING
},
{
- .subvendor = 0x8086,
- .subdevice = 0x4856,
+ .vendor = 0x8086,
+ .device = 0x4856,
.name = "Intel D845WN (82801BA)",
.type = AC97_TUNE_SWAP_HP
},
{
- .subvendor = 0x8086,
- .subdevice = 0x4d44,
+ .vendor = 0x8086,
+ .device = 0x4d44,
.name = "Intel D850EMV2", /* AD1885 */
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x8086,
- .subdevice = 0x4d56,
+ .vendor = 0x8086,
+ .device = 0x4d56,
.name = "Intel ICH/AD1885",
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x8086,
- .subdevice = 0x6000,
+ .vendor = 0x8086,
+ .device = 0x6000,
.mask = 0xfff0,
.name = "Intel ICH5/AD1985",
.type = AC97_TUNE_AD_SHARING
},
{
- .subvendor = 0x8086,
- .subdevice = 0xe000,
+ .vendor = 0x8086,
+ .device = 0xe000,
.mask = 0xfff0,
.name = "Intel ICH5/AD1985",
.type = AC97_TUNE_AD_SHARING
},
#if 0 /* FIXME: this seems wrong on most boards */
{
- .subvendor = 0x8086,
- .subdevice = 0xa000,
+ .vendor = 0x8086,
+ .device = 0xa000,
.mask = 0xfff0,
.name = "Intel ICH5/AD1985",
.type = AC97_TUNE_HP_ONLY
@@ -2855,7 +2849,7 @@ static struct pci_driver driver = {
static int __init alsa_card_intel8x0_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_intel8x0_exit(void)
diff --git a/trunk/sound/pci/intel8x0m.c b/trunk/sound/pci/intel8x0m.c
index bb758c77d211..67da096d659b 100644
--- a/trunk/sound/pci/intel8x0m.c
+++ b/trunk/sound/pci/intel8x0m.c
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
#include
MODULE_AUTHOR("Jaroslav Kysela ");
@@ -291,9 +292,60 @@ static struct pci_device_id snd_intel8x0m_ids[] = {
#endif
{ 0, }
};
+static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol);
+static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol);
+static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_info_t *uinfo);
+
+#define PRIVATE_VALUE_INITIALIZER(r,m) (((r) & 0xffff) << 16 | ((m) & 0xffff))
+#define PRIVATE_VALUE_MASK(control) ((control)->private_value & 0xffff)
+#define PRIVATE_VALUE_REG(control) (((control)->private_value >> 16) & 0xffff)
+
+static snd_kcontrol_new_t snd_intel8x0m_mixer_switches[] __devinitdata = {
+ { .name = "Off-hook Switch",
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .info = snd_intel8x0m_switch_default_info,
+ .get = snd_intel8x0m_switch_default_get,
+ .put = snd_intel8x0m_switch_default_put,
+ .private_value = PRIVATE_VALUE_INITIALIZER(AC97_GPIO_STATUS,AC97_GPIO_LINE1_OH)
+ }
+};
MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids);
+static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_info_t *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ unsigned short mask = PRIVATE_VALUE_MASK(kcontrol);
+ unsigned short reg = PRIVATE_VALUE_REG(kcontrol);
+ intel8x0_t *chip = snd_kcontrol_chip(kcontrol);
+ unsigned int status;
+ status = snd_ac97_read(chip->ac97, reg) & mask ? 1 : 0;
+ ucontrol->value.integer.value[0] = status;
+ return 0;
+}
+static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ unsigned short mask = PRIVATE_VALUE_MASK(kcontrol);
+ unsigned short reg = PRIVATE_VALUE_REG(kcontrol);
+ intel8x0_t *chip = snd_kcontrol_chip(kcontrol);
+ unsigned short new_status = ucontrol->value.integer.value[0] ? mask : ~mask;
+ return snd_ac97_update_bits(chip->ac97, reg,
+ mask, new_status);
+}
/*
* Lowlevel I/O - busmaster
*/
@@ -448,8 +500,6 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
res = 0xffff;
}
}
- if (reg == AC97_GPIO_STATUS)
- iagetword(chip, 0); /* clear semaphore */
return res;
}
@@ -648,6 +698,21 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substrea
return bytes_to_frames(substream->runtime, ptr);
}
+static int snd_intel8x0m_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+{
+ /* hook off/on on start/stop */
+ /* Moved this to mixer control */
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ break;
+ default:
+ return -EINVAL;
+ }
+ return snd_intel8x0_pcm_trigger(substream,cmd);
+}
+
static int snd_intel8x0m_pcm_prepare(snd_pcm_substream_t * substream)
{
intel8x0_t *chip = snd_pcm_substream_chip(substream);
@@ -743,7 +808,7 @@ static snd_pcm_ops_t snd_intel8x0m_playback_ops = {
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0m_pcm_prepare,
- .trigger = snd_intel8x0_pcm_trigger,
+ .trigger = snd_intel8x0m_pcm_trigger,
.pointer = snd_intel8x0_pcm_pointer,
};
@@ -754,7 +819,7 @@ static snd_pcm_ops_t snd_intel8x0m_capture_ops = {
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0m_pcm_prepare,
- .trigger = snd_intel8x0_pcm_trigger,
+ .trigger = snd_intel8x0m_pcm_trigger,
.pointer = snd_intel8x0_pcm_pointer,
};
@@ -882,6 +947,7 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
ac97_t *x97;
int err;
unsigned int glob_sta = 0;
+ unsigned int idx;
static ac97_bus_ops_t ops = {
.write = snd_intel8x0_codec_write,
.read = snd_intel8x0_codec_read,
@@ -917,6 +983,10 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
chip->ichd[ICHD_MDMIN].ac97 = x97;
chip->ichd[ICHD_MDMOUT].ac97 = x97;
}
+ for (idx = 0; idx < ARRAY_SIZE(snd_intel8x0m_mixer_switches); idx++) {
+ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_intel8x0m_mixer_switches[idx], chip))) < 0)
+ goto __err;
+ }
chip->in_ac97_init = 0;
return 0;
@@ -1380,7 +1450,7 @@ static struct pci_driver driver = {
static int __init alsa_card_intel8x0m_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_intel8x0m_exit(void)
diff --git a/trunk/sound/pci/korg1212/korg1212.c b/trunk/sound/pci/korg1212/korg1212.c
index 79d8eda54f0d..bb1de2008176 100644
--- a/trunk/sound/pci/korg1212/korg1212.c
+++ b/trunk/sound/pci/korg1212/korg1212.c
@@ -2541,7 +2541,7 @@ static struct pci_driver driver = {
static int __init alsa_card_korg1212_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_korg1212_exit(void)
diff --git a/trunk/sound/pci/maestro3.c b/trunk/sound/pci/maestro3.c
index 096f15132853..2cf33083d7cc 100644
--- a/trunk/sound/pci/maestro3.c
+++ b/trunk/sound/pci/maestro3.c
@@ -779,12 +779,6 @@ struct m3_quirk {
(e.g. for IrDA on Dell Inspirons) */
};
-struct m3_hv_quirk {
- u16 vendor, device, subsystem_vendor, subsystem_device;
- u32 config; /* ALLEGRO_CONFIG hardware volume bits */
- int is_omnibook; /* Do HP OmniBook GPIO magic? */
-};
-
struct m3_list {
int curlen;
int mem_addr;
@@ -834,7 +828,6 @@ struct snd_m3 {
struct pci_dev *pci;
struct m3_quirk *quirk;
- struct m3_hv_quirk *hv_quirk;
int dacs_active;
int timer_users;
@@ -858,11 +851,6 @@ struct snd_m3 {
m3_dma_t *substreams;
spinlock_t reg_lock;
- spinlock_t ac97_lock;
-
- snd_kcontrol_t *master_switch;
- snd_kcontrol_t *master_volume;
- struct tasklet_struct hwvol_tq;
#ifdef CONFIG_PM
u16 *suspend_mem;
@@ -980,71 +968,6 @@ static struct m3_quirk m3_quirk_list[] = {
{ NULL }
};
-/* These values came from the Windows driver. */
-static struct m3_hv_quirk m3_hv_quirk_list[] = {
- /* Allegro chips */
- { 0x125D, 0x1988, 0x0E11, 0x002E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x0E11, 0x0094, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x0E11, 0xB112, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x0E11, 0xB114, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x103C, 0x0012, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x103C, 0x0018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x103C, 0x001C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x103C, 0x001D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x103C, 0x001E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x107B, 0x3350, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x10F7, 0x8338, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x10F7, 0x833C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x10F7, 0x833D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x10F7, 0x833E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x10F7, 0x833F, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x13BD, 0x1018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x13BD, 0x1019, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x13BD, 0x101A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x14FF, 0x0F03, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x14FF, 0x0F04, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x14FF, 0x0F05, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x156D, 0xB400, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x156D, 0xB795, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x156D, 0xB797, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x156D, 0xC700, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
- { 0x125D, 0x1988, 0x1033, 0x80F1, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
- { 0x125D, 0x1988, 0x103C, 0x001A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, /* HP OmniBook 6100 */
- { 0x125D, 0x1988, 0x107B, 0x340A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
- { 0x125D, 0x1988, 0x107B, 0x3450, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
- { 0x125D, 0x1988, 0x109F, 0x3134, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
- { 0x125D, 0x1988, 0x109F, 0x3161, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
- { 0x125D, 0x1988, 0x144D, 0x3280, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
- { 0x125D, 0x1988, 0x144D, 0x3281, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
- { 0x125D, 0x1988, 0x144D, 0xC002, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
- { 0x125D, 0x1988, 0x144D, 0xC003, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
- { 0x125D, 0x1988, 0x1509, 0x1740, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
- { 0x125D, 0x1988, 0x1610, 0x0010, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
- { 0x125D, 0x1988, 0x1042, 0x1042, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x1988, 0x107B, 0x9500, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x1988, 0x14FF, 0x0F06, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x1988, 0x1558, 0x8586, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x1988, 0x161F, 0x2011, HV_CTRL_ENABLE, 0 },
- /* Maestro3 chips */
- { 0x125D, 0x1998, 0x103C, 0x000E, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x1998, 0x103C, 0x0010, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 6000 */
- { 0x125D, 0x1998, 0x103C, 0x0011, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 500 */
- { 0x125D, 0x1998, 0x103C, 0x001B, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x1998, 0x104D, 0x80A6, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x1998, 0x104D, 0x80AA, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x1998, 0x107B, 0x5300, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x1998, 0x110A, 0x1998, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x1998, 0x13BD, 0x1015, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x1998, 0x13BD, 0x101C, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x1998, 0x13BD, 0x1802, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x1998, 0x1599, 0x0715, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x1998, 0x5643, 0x5643, HV_CTRL_ENABLE, 0 },
- { 0x125D, 0x199A, 0x144D, 0x3260, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
- { 0x125D, 0x199A, 0x144D, 0x3261, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
- { 0x125D, 0x199A, 0x144D, 0xC000, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
- { 0x125D, 0x199A, 0x144D, 0xC001, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
- { 0 }
-};
/*
* lowlevel functions
@@ -1642,68 +1565,6 @@ static void snd_m3_update_ptr(m3_t *chip, m3_dma_t *s)
}
}
-static void snd_m3_update_hw_volume(unsigned long private_data)
-{
- m3_t *chip = (m3_t *) private_data;
- int x, val;
- unsigned long flags;
-
- /* Figure out which volume control button was pushed,
- based on differences from the default register
- values. */
- x = inb(chip->iobase + SHADOW_MIX_REG_VOICE) & 0xee;
-
- /* Reset the volume control registers. */
- outb(0x88, chip->iobase + SHADOW_MIX_REG_VOICE);
- outb(0x88, chip->iobase + HW_VOL_COUNTER_VOICE);
- outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER);
- outb(0x88, chip->iobase + HW_VOL_COUNTER_MASTER);
-
- if (!chip->master_switch || !chip->master_volume)
- return;
-
- /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */
- spin_lock_irqsave(&chip->ac97_lock, flags);
-
- val = chip->ac97->regs[AC97_MASTER_VOL];
- switch (x) {
- case 0x88:
- /* mute */
- val ^= 0x8000;
- chip->ac97->regs[AC97_MASTER_VOL] = val;
- outw(val, chip->iobase + CODEC_DATA);
- outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
- snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
- &chip->master_switch->id);
- break;
- case 0xaa:
- /* volume up */
- if ((val & 0x7f) > 0)
- val--;
- if ((val & 0x7f00) > 0)
- val -= 0x0100;
- chip->ac97->regs[AC97_MASTER_VOL] = val;
- outw(val, chip->iobase + CODEC_DATA);
- outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
- snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
- &chip->master_volume->id);
- break;
- case 0x66:
- /* volume down */
- if ((val & 0x7f) < 0x1f)
- val++;
- if ((val & 0x7f00) < 0x1f00)
- val += 0x0100;
- chip->ac97->regs[AC97_MASTER_VOL] = val;
- outw(val, chip->iobase + CODEC_DATA);
- outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
- snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
- &chip->master_volume->id);
- break;
- }
- spin_unlock_irqrestore(&chip->ac97_lock, flags);
-}
-
static irqreturn_t
snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -1715,10 +1576,7 @@ snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (status == 0xff)
return IRQ_NONE;
-
- if (status & HV_INT_PENDING)
- tasklet_hi_schedule(&chip->hwvol_tq);
-
+
/*
* ack an assp int if its running
* and has an int pending
@@ -1747,7 +1605,7 @@ snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#endif
/* ack ints */
- outb(status, chip->iobase + HOST_INT_STATUS);
+ snd_m3_outw(chip, HOST_INT_STATUS, status);
return IRQ_HANDLED;
}
@@ -1984,32 +1842,24 @@ static unsigned short
snd_m3_ac97_read(ac97_t *ac97, unsigned short reg)
{
m3_t *chip = ac97->private_data;
- unsigned long flags;
- unsigned short data;
if (snd_m3_ac97_wait(chip))
return 0xffff;
- spin_lock_irqsave(&chip->ac97_lock, flags);
snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND);
if (snd_m3_ac97_wait(chip))
return 0xffff;
- data = snd_m3_inw(chip, CODEC_DATA);
- spin_unlock_irqrestore(&chip->ac97_lock, flags);
- return data;
+ return snd_m3_inw(chip, CODEC_DATA);
}
static void
snd_m3_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
{
m3_t *chip = ac97->private_data;
- unsigned long flags;
if (snd_m3_ac97_wait(chip))
return;
- spin_lock_irqsave(&chip->ac97_lock, flags);
snd_m3_outw(chip, val, CODEC_DATA);
snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND);
- spin_unlock_irqrestore(&chip->ac97_lock, flags);
}
@@ -2118,7 +1968,6 @@ static int __devinit snd_m3_mixer(m3_t *chip)
{
ac97_bus_t *pbus;
ac97_template_t ac97;
- snd_ctl_elem_id_t id;
int err;
static ac97_bus_ops_t ops = {
.write = snd_m3_ac97_write,
@@ -2139,15 +1988,6 @@ static int __devinit snd_m3_mixer(m3_t *chip)
schedule_timeout(HZ / 10);
snd_ac97_write(chip->ac97, AC97_PCM, 0);
- memset(&id, 0, sizeof(id));
- id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- strcpy(id.name, "Master Playback Switch");
- chip->master_switch = snd_ctl_find_id(chip->card, &id);
- memset(&id, 0, sizeof(id));
- id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- strcpy(id.name, "Master Playback Volume");
- chip->master_volume = snd_ctl_find_id(chip->card, &id);
-
return 0;
}
@@ -2453,7 +2293,6 @@ static int
snd_m3_chip_init(m3_t *chip)
{
struct pci_dev *pcidev = chip->pci;
- unsigned long io = chip->iobase;
u32 n;
u16 w;
u8 t; /* makes as much sense as 'n', no? */
@@ -2464,27 +2303,8 @@ snd_m3_chip_init(m3_t *chip)
DISABLE_LEGACY);
pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w);
- if (chip->hv_quirk && chip->hv_quirk->is_omnibook) {
- /*
- * Volume buttons on some HP OmniBook laptops don't work
- * correctly. This makes them work for the most part.
- *
- * Volume up and down buttons on the laptop side work.
- * Fn+cursor_up (volme up) works.
- * Fn+cursor_down (volume down) doesn't work.
- * Fn+F7 (mute) works acts as volume up.
- */
- outw(~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_MASK);
- outw(inw(io + GPIO_DIRECTION) & ~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DIRECTION);
- outw((GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DATA);
- outw(0xffff, io + GPIO_MASK);
- }
pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n);
- n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD);
- if (chip->hv_quirk)
- n |= chip->hv_quirk->config;
- /* For some reason we must always use reduced debounce. */
- n |= REDUCED_DEBOUNCE;
+ n &= REDUCED_DEBOUNCE;
n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING;
pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n);
@@ -2512,12 +2332,6 @@ snd_m3_chip_init(m3_t *chip)
outb(RUN_ASSP, chip->iobase + ASSP_CONTROL_B);
- outb(0x00, io + HARDWARE_VOL_CTRL);
- outb(0x88, io + SHADOW_MIX_REG_VOICE);
- outb(0x88, io + HW_VOL_COUNTER_VOICE);
- outb(0x88, io + SHADOW_MIX_REG_MASTER);
- outb(0x88, io + HW_VOL_COUNTER_MASTER);
-
return 0;
}
@@ -2527,7 +2341,7 @@ snd_m3_enable_ints(m3_t *chip)
unsigned long io = chip->iobase;
/* TODO: MPU401 not supported yet */
- outw(ASSP_INT_ENABLE | HV_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL);
+ outw(ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL);
outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE,
io + ASSP_CONTROL_C);
}
@@ -2553,7 +2367,7 @@ static int snd_m3_free(m3_t *chip)
kfree(chip->substreams);
}
if (chip->iobase) {
- outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */
+ snd_m3_outw(chip, HOST_INT_CTRL, 0); /* disable ints */
}
#ifdef CONFIG_PM
@@ -2672,7 +2486,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
m3_t *chip;
int i, err;
struct m3_quirk *quirk;
- struct m3_hv_quirk *hv_quirk;
+ u16 subsystem_vendor, subsystem_device;
static snd_device_ops_t ops = {
.dev_free = snd_m3_dev_free,
};
@@ -2710,25 +2524,18 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
chip->pci = pci;
chip->irq = -1;
+ pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
+ pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
+
for (quirk = m3_quirk_list; quirk->vendor; quirk++) {
- if (pci->subsystem_vendor == quirk->vendor &&
- pci->subsystem_device == quirk->device) {
+ if (subsystem_vendor == quirk->vendor &&
+ subsystem_device == quirk->device) {
printk(KERN_INFO "maestro3: enabled hack for '%s'\n", quirk->name);
chip->quirk = quirk;
break;
}
}
- for (hv_quirk = m3_hv_quirk_list; hv_quirk->vendor; hv_quirk++) {
- if (pci->vendor == hv_quirk->vendor &&
- pci->device == hv_quirk->device &&
- pci->subsystem_vendor == hv_quirk->subsystem_vendor &&
- pci->subsystem_device == hv_quirk->subsystem_device) {
- chip->hv_quirk = hv_quirk;
- break;
- }
- }
-
chip->external_amp = enable_amp;
if (amp_gpio >= 0 && amp_gpio <= 0x0f)
chip->amp_gpio = amp_gpio;
@@ -2786,9 +2593,6 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
return err;
}
- spin_lock_init(&chip->ac97_lock);
- tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
-
if ((err = snd_m3_mixer(chip)) < 0)
return err;
@@ -2898,7 +2702,7 @@ static struct pci_driver driver = {
static int __init alsa_card_m3_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_m3_exit(void)
diff --git a/trunk/sound/pci/mixart/mixart.c b/trunk/sound/pci/mixart/mixart.c
index 082c0d0f73d2..65bb0f47af2c 100644
--- a/trunk/sound/pci/mixart/mixart.c
+++ b/trunk/sound/pci/mixart/mixart.c
@@ -1431,7 +1431,7 @@ static struct pci_driver driver = {
static int __init alsa_card_mixart_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_mixart_exit(void)
diff --git a/trunk/sound/pci/nm256/nm256.c b/trunk/sound/pci/nm256/nm256.c
index 8a52091f8552..356fbeac6f9e 100644
--- a/trunk/sound/pci/nm256/nm256.c
+++ b/trunk/sound/pci/nm256/nm256.c
@@ -1645,7 +1645,7 @@ static struct pci_driver driver = {
static int __init alsa_card_nm256_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_nm256_exit(void)
diff --git a/trunk/sound/pci/rme32.c b/trunk/sound/pci/rme32.c
index b7b554df6705..b96acd5a57db 100644
--- a/trunk/sound/pci/rme32.c
+++ b/trunk/sound/pci/rme32.c
@@ -2031,7 +2031,7 @@ static struct pci_driver driver = {
static int __init alsa_card_rme32_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_rme32_exit(void)
diff --git a/trunk/sound/pci/rme96.c b/trunk/sound/pci/rme96.c
index 10c4f45a913c..8e2666841d21 100644
--- a/trunk/sound/pci/rme96.c
+++ b/trunk/sound/pci/rme96.c
@@ -2437,7 +2437,7 @@ static struct pci_driver driver = {
static int __init alsa_card_rme96_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_rme96_exit(void)
diff --git a/trunk/sound/pci/rme9652/Makefile b/trunk/sound/pci/rme9652/Makefile
index d2c294e136f9..917374c9cd40 100644
--- a/trunk/sound/pci/rme9652/Makefile
+++ b/trunk/sound/pci/rme9652/Makefile
@@ -5,9 +5,7 @@
snd-rme9652-objs := rme9652.o
snd-hdsp-objs := hdsp.o
-snd-hdspm-objs := hdspm.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_RME9652) += snd-rme9652.o
obj-$(CONFIG_SND_HDSP) += snd-hdsp.o
-obj-$(CONFIG_SND_HDSPM) +=snd-hdspm.o
diff --git a/trunk/sound/pci/rme9652/hdsp.c b/trunk/sound/pci/rme9652/hdsp.c
index a673cc438b91..12efbf0fab54 100644
--- a/trunk/sound/pci/rme9652/hdsp.c
+++ b/trunk/sound/pci/rme9652/hdsp.c
@@ -559,22 +559,18 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
{
dmab->dev.type = SNDRV_DMA_TYPE_DEV;
dmab->dev.dev = snd_dma_pci_data(pci);
- if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
- if (dmab->bytes >= size)
- return 0;
+ if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
+ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+ size, dmab) < 0)
+ return -ENOMEM;
}
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
- size, dmab) < 0)
- return -ENOMEM;
return 0;
}
static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
{
- if (dmab->area) {
- dmab->dev.dev = NULL; /* make it anonymous */
+ if (dmab->area)
snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
- }
}
@@ -4916,9 +4912,19 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
release_firmware(fw);
return -EINVAL;
}
-
+#ifdef SNDRV_BIG_ENDIAN
+ {
+ int i;
+ u32 *src = (u32*)fw->data;
+ for (i = 0; i < ARRAY_SIZE(hdsp->firmware_cache); i++, src++)
+ hdsp->firmware_cache[i] = ((*src & 0x000000ff) << 16) |
+ ((*src & 0x0000ff00) << 8) |
+ ((*src & 0x00ff0000) >> 8) |
+ ((*src & 0xff000000) >> 16);
+ }
+#else
memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
-
+#endif
release_firmware(fw);
hdsp->state |= HDSP_FirmwareCached;
@@ -5188,7 +5194,7 @@ static struct pci_driver driver = {
static int __init alsa_card_hdsp_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_hdsp_exit(void)
diff --git a/trunk/sound/pci/rme9652/hdspm.c b/trunk/sound/pci/rme9652/hdspm.c
deleted file mode 100644
index 9e86d0eb41ce..000000000000
--- a/trunk/sound/pci/rme9652/hdspm.c
+++ /dev/null
@@ -1,3671 +0,0 @@
-/* -*- linux-c -*-
- *
- * ALSA driver for RME Hammerfall DSP MADI audio interface(s)
- *
- * Copyright (c) 2003 Winfried Ritsch (IEM)
- * code based on hdsp.c Paul Davis
- * Marcus Andersson
- * Thomas Charbonnel
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
-
-/* Disable precise pointer at start */
-static int precise_ptr[SNDRV_CARDS];
-
-/* Send all playback to line outs */
-static int line_outs_monitor[SNDRV_CARDS];
-
-/* Enable Analog Outs on Channel 63/64 by default */
-static int enable_monitor[SNDRV_CARDS];
-
-module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
-
-module_param_array(id, charp, NULL, 0444);
-MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
-
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
-
-module_param_array(precise_ptr, bool, NULL, 0444);
-MODULE_PARM_DESC(precise_ptr, "Enable precise pointer, or disable.");
-
-module_param_array(line_outs_monitor, bool, NULL, 0444);
-MODULE_PARM_DESC(line_outs_monitor,
- "Send playback streams to analog outs by default.");
-
-module_param_array(enable_monitor, bool, NULL, 0444);
-MODULE_PARM_DESC(enable_monitor,
- "Enable Analog Out on Channel 63/64 by default.");
-
-MODULE_AUTHOR
- ("Winfried Ritsch , Paul Davis , "
- "Marcus Andersson, Thomas Charbonnel ");
-MODULE_DESCRIPTION("RME HDSPM");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
-
-/* --- Write registers. ---
- These are defined as byte-offsets from the iobase value. */
-
-#define HDSPM_controlRegister 64
-#define HDSPM_interruptConfirmation 96
-#define HDSPM_control2Reg 256 /* not in specs ???????? */
-#define HDSPM_midiDataOut0 352 /* just believe in old code */
-#define HDSPM_midiDataOut1 356
-
-/* DMA enable for 64 channels, only Bit 0 is relevant */
-#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
-#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
-
-/* 16 page addresses for each of the 64 channels DMA buffer in and out
- (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
-#define HDSPM_pageAddressBufferOut 8192
-#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
-
-#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
-
-#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
-
-/* --- Read registers. ---
- These are defined as byte-offsets from the iobase value */
-#define HDSPM_statusRegister 0
-#define HDSPM_statusRegister2 96
-
-#define HDSPM_midiDataIn0 360
-#define HDSPM_midiDataIn1 364
-
-/* status is data bytes in MIDI-FIFO (0-128) */
-#define HDSPM_midiStatusOut0 384
-#define HDSPM_midiStatusOut1 388
-#define HDSPM_midiStatusIn0 392
-#define HDSPM_midiStatusIn1 396
-
-
-/* the meters are regular i/o-mapped registers, but offset
- considerably from the rest. the peak registers are reset
- when read; the least-significant 4 bits are full-scale counters;
- the actual peak value is in the most-significant 24 bits.
-*/
-#define HDSPM_MADI_peakrmsbase 4096 /* 4096-8191 2x64x32Bit Meters */
-
-/* --- Control Register bits --------- */
-#define HDSPM_Start (1<<0) /* start engine */
-
-#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
-#define HDSPM_Latency1 (1<<2) /* where n is defined */
-#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
-
-#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */
-
-#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
-
-#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
-#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
-#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
-#define HDSPM_QuadSpeed (1<<31) /* quad speed bit, not implemented now */
-
-#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
- 56channelMODE=0 */
-
-#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
- 0=off, 1=on */
-
-#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */
-#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
-
-#define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */
-#define HDSPM_SyncRef1 (1<<17) /* should be 0 */
-
-#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
- AES additional bits in
- lower 5 Audiodatabits ??? */
-
-#define HDSPM_Midi0InterruptEnable (1<<22)
-#define HDSPM_Midi1InterruptEnable (1<<23)
-
-#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
-
-
-/* --- bit helper defines */
-#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
-#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1)
-#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
-#define HDSPM_InputOptical 0
-#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
-#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1)
-#define HDSPM_SyncRef_Word 0
-#define HDSPM_SyncRef_MADI (HDSPM_SyncRef0)
-
-#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
-#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
-
-#define HDSPM_Frequency32KHz HDSPM_Frequency0
-#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
-#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
-#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
-#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
-#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
-
-/* --- for internal discrimination */
-#define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */
-#define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ 1
-#define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ 2
-#define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ 3
-#define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ 4
-#define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ 5
-#define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ 6
-#define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ 7
-#define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
-#define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ 9
-
-/* Synccheck Status */
-#define HDSPM_SYNC_CHECK_NO_LOCK 0
-#define HDSPM_SYNC_CHECK_LOCK 1
-#define HDSPM_SYNC_CHECK_SYNC 2
-
-/* AutoSync References - used by "autosync_ref" control switch */
-#define HDSPM_AUTOSYNC_FROM_WORD 0
-#define HDSPM_AUTOSYNC_FROM_MADI 1
-#define HDSPM_AUTOSYNC_FROM_NONE 2
-
-/* Possible sources of MADI input */
-#define HDSPM_OPTICAL 0 /* optical */
-#define HDSPM_COAXIAL 1 /* BNC */
-
-#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
-#define hdspm_decode_latency(x) (((x) & HDSPM_LatencyMask)>>1)
-
-#define hdspm_encode_in(x) (((x)&0x3)<<14)
-#define hdspm_decode_in(x) (((x)>>14)&0x3)
-
-/* --- control2 register bits --- */
-#define HDSPM_TMS (1<<0)
-#define HDSPM_TCK (1<<1)
-#define HDSPM_TDI (1<<2)
-#define HDSPM_JTAG (1<<3)
-#define HDSPM_PWDN (1<<4)
-#define HDSPM_PROGRAM (1<<5)
-#define HDSPM_CONFIG_MODE_0 (1<<6)
-#define HDSPM_CONFIG_MODE_1 (1<<7)
-/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
-#define HDSPM_BIGENDIAN_MODE (1<<9)
-#define HDSPM_RD_MULTIPLE (1<<10)
-
-/* --- Status Register bits --- */
-#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
-#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn. MODE=0 */
-#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 (like inp0) */
-#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
-
-#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
- /* since 64byte accurate last 6 bits
- are not used */
-
-#define HDSPM_madiSync (1<<18) /* MADI is in sync */
-#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
-
-#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
-#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
-#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
-#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
-
-#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with Interrupt */
-#define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */
-#define HDSPM_midi1IRQPending (1<<31) /* and aktiv */
-
-/* --- status bit helpers */
-#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2|HDSPM_madiFreq3)
-#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
-#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
-#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
-#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
-#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
-#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
-#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
-#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
-#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
-
-/* Status2 Register bits */
-
-#define HDSPM_version0 (1<<0) /* not realy defined but I guess */
-#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
-#define HDSPM_version2 (1<<2)
-
-#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
-#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
-
-#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
-#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
-#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */
-/* missing Bit for 111=128, 1000=176.4, 1001=192 */
-
-#define HDSPM_SelSyncRef0 (1<<8) /* Sync Source in slave mode */
-#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
-#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
-
-#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
-
-#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
-#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
-#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
-#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
-#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
-#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
-#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
-
-
-#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
-#define HDSPM_SelSyncRef_WORD 0
-#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
-#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
-
-/* Mixer Values */
-#define UNITY_GAIN 32768 /* = 65536/2 */
-#define MINUS_INFINITY_GAIN 0
-
-/* PCI info */
-#ifndef PCI_VENDOR_ID_XILINX
-#define PCI_VENDOR_ID_XILINX 0x10ee
-#endif
-#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
-#endif
-#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
-#endif
-
-
-/* Number of channels for different Speed Modes */
-#define MADI_SS_CHANNELS 64
-#define MADI_DS_CHANNELS 32
-#define MADI_QS_CHANNELS 16
-
-/* the size of a substream (1 mono data stream) */
-#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
-#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
-
-/* the size of the area we need to allocate for DMA transfers. the
- size is the same regardless of the number of channels, and
- also the latency to use.
- for one direction !!!
-*/
-#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
-#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
-
-typedef struct _hdspm hdspm_t;
-typedef struct _hdspm_midi hdspm_midi_t;
-
-struct _hdspm_midi {
- hdspm_t *hdspm;
- int id;
- snd_rawmidi_t *rmidi;
- snd_rawmidi_substream_t *input;
- snd_rawmidi_substream_t *output;
- char istimer; /* timer in use */
- struct timer_list timer;
- spinlock_t lock;
- int pending;
-};
-
-struct _hdspm {
- spinlock_t lock;
- snd_pcm_substream_t *capture_substream; /* only one playback */
- snd_pcm_substream_t *playback_substream; /* and/or capture stream */
-
- char *card_name; /* for procinfo */
- unsigned short firmware_rev; /* dont know if relevant */
-
- int precise_ptr; /* use precise pointers, to be tested */
- int monitor_outs; /* set up monitoring outs init flag */
-
- u32 control_register; /* cached value */
- u32 control2_register; /* cached value */
-
- hdspm_midi_t midi[2];
- struct tasklet_struct midi_tasklet;
-
- size_t period_bytes;
- unsigned char ss_channels; /* channels of card in single speed */
- unsigned char ds_channels; /* Double Speed */
- unsigned char qs_channels; /* Quad Speed */
-
- unsigned char *playback_buffer; /* suitably aligned address */
- unsigned char *capture_buffer; /* suitably aligned address */
-
- pid_t capture_pid; /* process id which uses capture */
- pid_t playback_pid; /* process id which uses capture */
- int running; /* running status */
-
- int last_external_sample_rate; /* samplerate mystic ... */
- int last_internal_sample_rate;
- int system_sample_rate;
-
- char *channel_map; /* channel map for DS and Quadspeed */
-
- int dev; /* Hardware vars... */
- int irq;
- unsigned long port;
- void __iomem *iobase;
-
- int irq_count; /* for debug */
-
- snd_card_t *card; /* one card */
- snd_pcm_t *pcm; /* has one pcm */
- snd_hwdep_t *hwdep; /* and a hwdep for additional ioctl */
- struct pci_dev *pci; /* and an pci info */
-
- /* Mixer vars */
- snd_kcontrol_t *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; /* fast alsa mixer */
- snd_kcontrol_t *input_mixer_ctls[HDSPM_MAX_CHANNELS]; /* but input to much, so not used */
- hdspm_mixer_t *mixer; /* full mixer accessable over mixer ioctl or hwdep-device */
-
-};
-
-/* These tables map the ALSA channels 1..N to the channels that we
- need to use in order to find the relevant channel buffer. RME
- refer to this kind of mapping as between "the ADAT channel and
- the DMA channel." We index it using the logical audio channel,
- and the value is the DMA channel (i.e. channel buffer number)
- where the data for that channel can be read/written from/to.
-*/
-
-static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = {
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63
-};
-
-static char channel_map_madi_ds[HDSPM_MAX_CHANNELS] = {
- 0, 2, 4, 6, 8, 10, 12, 14,
- 16, 18, 20, 22, 24, 26, 28, 30,
- 32, 34, 36, 38, 40, 42, 44, 46,
- 48, 50, 52, 54, 56, 58, 60, 62,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1
-};
-
-static char channel_map_madi_qs[HDSPM_MAX_CHANNELS] = {
- 0, 4, 8, 12, 16, 20, 24, 28,
- 32, 36, 40, 44, 48, 52, 56, 60
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1
-};
-
-
-static struct pci_device_id snd_hdspm_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_XILINX,
- .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .class = 0,
- .class_mask = 0,
- .driver_data = 0},
- {0,}
-};
-
-MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
-
-/* prototypes */
-static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card,
- hdspm_t * hdspm);
-static int __devinit snd_hdspm_create_pcm(snd_card_t * card,
- hdspm_t * hdspm);
-
-static inline void snd_hdspm_initialize_midi_flush(hdspm_t * hdspm);
-static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm);
-static int hdspm_autosync_ref(hdspm_t * hdspm);
-static int snd_hdspm_set_defaults(hdspm_t * hdspm);
-static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf,
- unsigned int reg, int channels);
-
-/* Write/read to/from HDSPM with Adresses in Bytes
- not words but only 32Bit writes are allowed */
-
-static inline void hdspm_write(hdspm_t * hdspm, unsigned int reg,
- unsigned int val)
-{
- writel(val, hdspm->iobase + reg);
-}
-
-static inline unsigned int hdspm_read(hdspm_t * hdspm, unsigned int reg)
-{
- return readl(hdspm->iobase + reg);
-}
-
-/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
- mixer is write only on hardware so we have to cache him for read
- each fader is a u32, but uses only the first 16 bit */
-
-static inline int hdspm_read_in_gain(hdspm_t * hdspm, unsigned int chan,
- unsigned int in)
-{
- if (chan > HDSPM_MIXER_CHANNELS || in > HDSPM_MIXER_CHANNELS)
- return 0;
-
- return hdspm->mixer->ch[chan].in[in];
-}
-
-static inline int hdspm_read_pb_gain(hdspm_t * hdspm, unsigned int chan,
- unsigned int pb)
-{
- if (chan > HDSPM_MIXER_CHANNELS || pb > HDSPM_MIXER_CHANNELS)
- return 0;
- return hdspm->mixer->ch[chan].pb[pb];
-}
-
-static inline int hdspm_write_in_gain(hdspm_t * hdspm, unsigned int chan,
- unsigned int in, unsigned short data)
-{
- if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
- return -1;
-
- hdspm_write(hdspm,
- HDSPM_MADI_mixerBase +
- ((in + 128 * chan) * sizeof(u32)),
- (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
- return 0;
-}
-
-static inline int hdspm_write_pb_gain(hdspm_t * hdspm, unsigned int chan,
- unsigned int pb, unsigned short data)
-{
- if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
- return -1;
-
- hdspm_write(hdspm,
- HDSPM_MADI_mixerBase +
- ((64 + pb + 128 * chan) * sizeof(u32)),
- (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
- return 0;
-}
-
-
-/* enable DMA for specific channels, now available for DSP-MADI */
-static inline void snd_hdspm_enable_in(hdspm_t * hdspm, int i, int v)
-{
- hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
-}
-
-static inline void snd_hdspm_enable_out(hdspm_t * hdspm, int i, int v)
-{
- hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
-}
-
-/* check if same process is writing and reading */
-static inline int snd_hdspm_use_is_exclusive(hdspm_t * hdspm)
-{
- unsigned long flags;
- int ret = 1;
-
- spin_lock_irqsave(&hdspm->lock, flags);
- if ((hdspm->playback_pid != hdspm->capture_pid) &&
- (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
- ret = 0;
- }
- spin_unlock_irqrestore(&hdspm->lock, flags);
- return ret;
-}
-
-/* check for external sample rate */
-static inline int hdspm_external_sample_rate(hdspm_t * hdspm)
-{
- unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
- unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
- unsigned int rate_bits;
- int rate = 0;
-
- /* if wordclock has synced freq and wordclock is valid */
- if ((status2 & HDSPM_wcLock) != 0 &&
- (status & HDSPM_SelSyncRef0) == 0) {
-
- rate_bits = status2 & HDSPM_wcFreqMask;
-
- switch (rate_bits) {
- case HDSPM_wcFreq32:
- rate = 32000;
- break;
- case HDSPM_wcFreq44_1:
- rate = 44100;
- break;
- case HDSPM_wcFreq48:
- rate = 48000;
- break;
- case HDSPM_wcFreq64:
- rate = 64000;
- break;
- case HDSPM_wcFreq88_2:
- rate = 88200;
- break;
- case HDSPM_wcFreq96:
- rate = 96000;
- break;
- /* Quadspeed Bit missing ???? */
- default:
- rate = 0;
- break;
- }
- }
-
- /* if rate detected and Syncref is Word than have it, word has priority to MADI */
- if (rate != 0
- && (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
- return rate;
-
- /* maby a madi input (which is taken if sel sync is madi) */
- if (status & HDSPM_madiLock) {
- rate_bits = status & HDSPM_madiFreqMask;
-
- switch (rate_bits) {
- case HDSPM_madiFreq32:
- rate = 32000;
- break;
- case HDSPM_madiFreq44_1:
- rate = 44100;
- break;
- case HDSPM_madiFreq48:
- rate = 48000;
- break;
- case HDSPM_madiFreq64:
- rate = 64000;
- break;
- case HDSPM_madiFreq88_2:
- rate = 88200;
- break;
- case HDSPM_madiFreq96:
- rate = 96000;
- break;
- case HDSPM_madiFreq128:
- rate = 128000;
- break;
- case HDSPM_madiFreq176_4:
- rate = 176400;
- break;
- case HDSPM_madiFreq192:
- rate = 192000;
- break;
- default:
- rate = 0;
- break;
- }
- }
- return rate;
-}
-
-/* Latency function */
-static inline void hdspm_compute_period_size(hdspm_t * hdspm)
-{
- hdspm->period_bytes =
- 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
-}
-
-static snd_pcm_uframes_t hdspm_hw_pointer(hdspm_t * hdspm)
-{
- int position;
-
- position = hdspm_read(hdspm, HDSPM_statusRegister);
-
- if (!hdspm->precise_ptr) {
- return (position & HDSPM_BufferID) ? (hdspm->period_bytes /
- 4) : 0;
- }
-
- /* hwpointer comes in bytes and is 64Bytes accurate (by docu since PCI Burst)
- i have experimented that it is at most 64 Byte to much for playing
- so substraction of 64 byte should be ok for ALSA, but use it only
- for application where you know what you do since if you come to
- near with record pointer it can be a disaster */
-
- position &= HDSPM_BufferPositionMask;
- position = ((position - 64) % (2 * hdspm->period_bytes)) / 4;
-
- return position;
-}
-
-
-static inline void hdspm_start_audio(hdspm_t * s)
-{
- s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
- hdspm_write(s, HDSPM_controlRegister, s->control_register);
-}
-
-static inline void hdspm_stop_audio(hdspm_t * s)
-{
- s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
- hdspm_write(s, HDSPM_controlRegister, s->control_register);
-}
-
-/* should I silence all or only opened ones ? doit all for first even is 4MB*/
-static inline void hdspm_silence_playback(hdspm_t * hdspm)
-{
- int i;
- int n = hdspm->period_bytes;
- void *buf = hdspm->playback_buffer;
-
- snd_assert(buf != NULL, return);
-
- for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
- memset(buf, 0, n);
- buf += HDSPM_CHANNEL_BUFFER_BYTES;
- }
-}
-
-static int hdspm_set_interrupt_interval(hdspm_t * s, unsigned int frames)
-{
- int n;
-
- spin_lock_irq(&s->lock);
-
- frames >>= 7;
- n = 0;
- while (frames) {
- n++;
- frames >>= 1;
- }
- s->control_register &= ~HDSPM_LatencyMask;
- s->control_register |= hdspm_encode_latency(n);
-
- hdspm_write(s, HDSPM_controlRegister, s->control_register);
-
- hdspm_compute_period_size(s);
-
- spin_unlock_irq(&s->lock);
-
- return 0;
-}
-
-
-/* dummy set rate lets see what happens */
-static int hdspm_set_rate(hdspm_t * hdspm, int rate, int called_internally)
-{
- int reject_if_open = 0;
- int current_rate;
- int rate_bits;
- int not_set = 0;
-
- /* ASSUMPTION: hdspm->lock is either set, or there is no need for
- it (e.g. during module initialization).
- */
-
- if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
-
- /* SLAVE --- */
- if (called_internally) {
-
- /* request from ctl or card initialization
- just make a warning an remember setting
- for future master mode switching */
-
- snd_printk
- (KERN_WARNING "HDSPM: Warning: device is not running as a clock master.\n");
- not_set = 1;
- } else {
-
- /* hw_param request while in AutoSync mode */
- int external_freq =
- hdspm_external_sample_rate(hdspm);
-
- if ((hdspm_autosync_ref(hdspm) ==
- HDSPM_AUTOSYNC_FROM_NONE)) {
-
- snd_printk(KERN_WARNING "HDSPM: Detected no Externel Sync \n");
- not_set = 1;
-
- } else if (rate != external_freq) {
-
- snd_printk
- (KERN_WARNING "HDSPM: Warning: No AutoSync source for requested rate\n");
- not_set = 1;
- }
- }
- }
-
- current_rate = hdspm->system_sample_rate;
-
- /* Changing between Singe, Double and Quad speed is not
- allowed if any substreams are open. This is because such a change
- causes a shift in the location of the DMA buffers and a reduction
- in the number of available buffers.
-
- Note that a similar but essentially insoluble problem exists for
- externally-driven rate changes. All we can do is to flag rate
- changes in the read/write routines.
- */
-
- switch (rate) {
- case 32000:
- if (current_rate > 48000) {
- reject_if_open = 1;
- }
- rate_bits = HDSPM_Frequency32KHz;
- break;
- case 44100:
- if (current_rate > 48000) {
- reject_if_open = 1;
- }
- rate_bits = HDSPM_Frequency44_1KHz;
- break;
- case 48000:
- if (current_rate > 48000) {
- reject_if_open = 1;
- }
- rate_bits = HDSPM_Frequency48KHz;
- break;
- case 64000:
- if (current_rate <= 48000) {
- reject_if_open = 1;
- }
- rate_bits = HDSPM_Frequency64KHz;
- break;
- case 88200:
- if (current_rate <= 48000) {
- reject_if_open = 1;
- }
- rate_bits = HDSPM_Frequency88_2KHz;
- break;
- case 96000:
- if (current_rate <= 48000) {
- reject_if_open = 1;
- }
- rate_bits = HDSPM_Frequency96KHz;
- break;
- default:
- return -EINVAL;
- }
-
- if (reject_if_open
- && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
- snd_printk
- (KERN_ERR "HDSPM: cannot change between single- and double-speed mode (capture PID = %d, playback PID = %d)\n",
- hdspm->capture_pid, hdspm->playback_pid);
- return -EBUSY;
- }
-
- hdspm->control_register &= ~HDSPM_FrequencyMask;
- hdspm->control_register |= rate_bits;
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
- if (rate > 64000)
- hdspm->channel_map = channel_map_madi_qs;
- else if (rate > 48000)
- hdspm->channel_map = channel_map_madi_ds;
- else
- hdspm->channel_map = channel_map_madi_ss;
-
- hdspm->system_sample_rate = rate;
-
- if (not_set != 0)
- return -1;
-
- return 0;
-}
-
-/* mainly for init to 0 on load */
-static void all_in_all_mixer(hdspm_t * hdspm, int sgain)
-{
- int i, j;
- unsigned int gain =
- (sgain > UNITY_GAIN) ? UNITY_GAIN : (sgain < 0) ? 0 : sgain;
-
- for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
- for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
- hdspm_write_in_gain(hdspm, i, j, gain);
- hdspm_write_pb_gain(hdspm, i, j, gain);
- }
-}
-
-/*----------------------------------------------------------------------------
- MIDI
- ----------------------------------------------------------------------------*/
-
-static inline unsigned char snd_hdspm_midi_read_byte (hdspm_t *hdspm, int id)
-{
- /* the hardware already does the relevant bit-mask with 0xff */
- if (id)
- return hdspm_read(hdspm, HDSPM_midiDataIn1);
- else
- return hdspm_read(hdspm, HDSPM_midiDataIn0);
-}
-
-static inline void snd_hdspm_midi_write_byte (hdspm_t *hdspm, int id, int val)
-{
- /* the hardware already does the relevant bit-mask with 0xff */
- if (id)
- return hdspm_write(hdspm, HDSPM_midiDataOut1, val);
- else
- return hdspm_write(hdspm, HDSPM_midiDataOut0, val);
-}
-
-static inline int snd_hdspm_midi_input_available (hdspm_t *hdspm, int id)
-{
- if (id)
- return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff);
- else
- return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff);
-}
-
-static inline int snd_hdspm_midi_output_possible (hdspm_t *hdspm, int id)
-{
- int fifo_bytes_used;
-
- if (id)
- fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xff;
- else
- fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xff;
-
- if (fifo_bytes_used < 128)
- return 128 - fifo_bytes_used;
- else
- return 0;
-}
-
-static inline void snd_hdspm_flush_midi_input (hdspm_t *hdspm, int id)
-{
- while (snd_hdspm_midi_input_available (hdspm, id))
- snd_hdspm_midi_read_byte (hdspm, id);
-}
-
-static int snd_hdspm_midi_output_write (hdspm_midi_t *hmidi)
-{
- unsigned long flags;
- int n_pending;
- int to_write;
- int i;
- unsigned char buf[128];
-
- /* Output is not interrupt driven */
-
- spin_lock_irqsave (&hmidi->lock, flags);
- if (hmidi->output) {
- if (!snd_rawmidi_transmit_empty (hmidi->output)) {
- if ((n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, hmidi->id)) > 0) {
- if (n_pending > (int)sizeof (buf))
- n_pending = sizeof (buf);
-
- if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
- for (i = 0; i < to_write; ++i)
- snd_hdspm_midi_write_byte (hmidi->hdspm, hmidi->id, buf[i]);
- }
- }
- }
- }
- spin_unlock_irqrestore (&hmidi->lock, flags);
- return 0;
-}
-
-static int snd_hdspm_midi_input_read (hdspm_midi_t *hmidi)
-{
- unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
- unsigned long flags;
- int n_pending;
- int i;
-
- spin_lock_irqsave (&hmidi->lock, flags);
- if ((n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id)) > 0) {
- if (hmidi->input) {
- if (n_pending > (int)sizeof (buf)) {
- n_pending = sizeof (buf);
- }
- for (i = 0; i < n_pending; ++i) {
- buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
- }
- if (n_pending) {
- snd_rawmidi_receive (hmidi->input, buf, n_pending);
- }
- } else {
- /* flush the MIDI input FIFO */
- while (n_pending--) {
- snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
- }
- }
- }
- hmidi->pending = 0;
- if (hmidi->id) {
- hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable;
- } else {
- hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable;
- }
- hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register);
- spin_unlock_irqrestore (&hmidi->lock, flags);
- return snd_hdspm_midi_output_write (hmidi);
-}
-
-static void snd_hdspm_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
-{
- hdspm_t *hdspm;
- hdspm_midi_t *hmidi;
- unsigned long flags;
- u32 ie;
-
- hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
- hdspm = hmidi->hdspm;
- ie = hmidi->id ? HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable;
- spin_lock_irqsave (&hdspm->lock, flags);
- if (up) {
- if (!(hdspm->control_register & ie)) {
- snd_hdspm_flush_midi_input (hdspm, hmidi->id);
- hdspm->control_register |= ie;
- }
- } else {
- hdspm->control_register &= ~ie;
- }
-
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
- spin_unlock_irqrestore (&hdspm->lock, flags);
-}
-
-static void snd_hdspm_midi_output_timer(unsigned long data)
-{
- hdspm_midi_t *hmidi = (hdspm_midi_t *) data;
- unsigned long flags;
-
- snd_hdspm_midi_output_write(hmidi);
- spin_lock_irqsave (&hmidi->lock, flags);
-
- /* this does not bump hmidi->istimer, because the
- kernel automatically removed the timer when it
- expired, and we are now adding it back, thus
- leaving istimer wherever it was set before.
- */
-
- if (hmidi->istimer) {
- hmidi->timer.expires = 1 + jiffies;
- add_timer(&hmidi->timer);
- }
-
- spin_unlock_irqrestore (&hmidi->lock, flags);
-}
-
-static void snd_hdspm_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
-{
- hdspm_midi_t *hmidi;
- unsigned long flags;
-
- hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
- spin_lock_irqsave (&hmidi->lock, flags);
- if (up) {
- if (!hmidi->istimer) {
- init_timer(&hmidi->timer);
- hmidi->timer.function = snd_hdspm_midi_output_timer;
- hmidi->timer.data = (unsigned long) hmidi;
- hmidi->timer.expires = 1 + jiffies;
- add_timer(&hmidi->timer);
- hmidi->istimer++;
- }
- } else {
- if (hmidi->istimer && --hmidi->istimer <= 0) {
- del_timer (&hmidi->timer);
- }
- }
- spin_unlock_irqrestore (&hmidi->lock, flags);
- if (up)
- snd_hdspm_midi_output_write(hmidi);
-}
-
-static int snd_hdspm_midi_input_open(snd_rawmidi_substream_t * substream)
-{
- hdspm_midi_t *hmidi;
-
- hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
- spin_lock_irq (&hmidi->lock);
- snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
- hmidi->input = substream;
- spin_unlock_irq (&hmidi->lock);
-
- return 0;
-}
-
-static int snd_hdspm_midi_output_open(snd_rawmidi_substream_t * substream)
-{
- hdspm_midi_t *hmidi;
-
- hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
- spin_lock_irq (&hmidi->lock);
- hmidi->output = substream;
- spin_unlock_irq (&hmidi->lock);
-
- return 0;
-}
-
-static int snd_hdspm_midi_input_close(snd_rawmidi_substream_t * substream)
-{
- hdspm_midi_t *hmidi;
-
- snd_hdspm_midi_input_trigger (substream, 0);
-
- hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
- spin_lock_irq (&hmidi->lock);
- hmidi->input = NULL;
- spin_unlock_irq (&hmidi->lock);
-
- return 0;
-}
-
-static int snd_hdspm_midi_output_close(snd_rawmidi_substream_t * substream)
-{
- hdspm_midi_t *hmidi;
-
- snd_hdspm_midi_output_trigger (substream, 0);
-
- hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
- spin_lock_irq (&hmidi->lock);
- hmidi->output = NULL;
- spin_unlock_irq (&hmidi->lock);
-
- return 0;
-}
-
-snd_rawmidi_ops_t snd_hdspm_midi_output =
-{
- .open = snd_hdspm_midi_output_open,
- .close = snd_hdspm_midi_output_close,
- .trigger = snd_hdspm_midi_output_trigger,
-};
-
-snd_rawmidi_ops_t snd_hdspm_midi_input =
-{
- .open = snd_hdspm_midi_input_open,
- .close = snd_hdspm_midi_input_close,
- .trigger = snd_hdspm_midi_input_trigger,
-};
-
-static int __devinit snd_hdspm_create_midi (snd_card_t *card, hdspm_t *hdspm, int id)
-{
- int err;
- char buf[32];
-
- hdspm->midi[id].id = id;
- hdspm->midi[id].rmidi = NULL;
- hdspm->midi[id].input = NULL;
- hdspm->midi[id].output = NULL;
- hdspm->midi[id].hdspm = hdspm;
- hdspm->midi[id].istimer = 0;
- hdspm->midi[id].pending = 0;
- spin_lock_init (&hdspm->midi[id].lock);
-
- sprintf (buf, "%s MIDI %d", card->shortname, id+1);
- if ((err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi)) < 0)
- return err;
-
- sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
- hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
-
- snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdspm_midi_output);
- snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdspm_midi_input);
-
- hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
- SNDRV_RAWMIDI_INFO_INPUT |
- SNDRV_RAWMIDI_INFO_DUPLEX;
-
- return 0;
-}
-
-
-static void hdspm_midi_tasklet(unsigned long arg)
-{
- hdspm_t *hdspm = (hdspm_t *)arg;
-
- if (hdspm->midi[0].pending)
- snd_hdspm_midi_input_read (&hdspm->midi[0]);
- if (hdspm->midi[1].pending)
- snd_hdspm_midi_input_read (&hdspm->midi[1]);
-}
-
-
-/*-----------------------------------------------------------------------------
- Status Interface
- ----------------------------------------------------------------------------*/
-
-/* get the system sample rate which is set */
-
-#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
- .name = xname, \
- .index = xindex, \
- .access = SNDRV_CTL_ELEM_ACCESS_READ, \
- .info = snd_hdspm_info_system_sample_rate, \
- .get = snd_hdspm_get_system_sample_rate \
-}
-
-static int snd_hdspm_info_system_sample_rate(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- return 0;
-}
-
-static int snd_hdspm_get_system_sample_rate(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t *
- ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate;
- return 0;
-}
-
-#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
- .name = xname, \
- .index = xindex, \
- .access = SNDRV_CTL_ELEM_ACCESS_READ, \
- .info = snd_hdspm_info_autosync_sample_rate, \
- .get = snd_hdspm_get_autosync_sample_rate \
-}
-
-static int snd_hdspm_info_autosync_sample_rate(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[] = { "32000", "44100", "48000",
- "64000", "88200", "96000",
- "128000", "176400", "192000",
- "None"
- };
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 10;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item =
- uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name,
- texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_hdspm_get_autosync_sample_rate(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t *
- ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
-
- switch (hdspm_external_sample_rate(hdspm)) {
- case 32000:
- ucontrol->value.enumerated.item[0] = 0;
- break;
- case 44100:
- ucontrol->value.enumerated.item[0] = 1;
- break;
- case 48000:
- ucontrol->value.enumerated.item[0] = 2;
- break;
- case 64000:
- ucontrol->value.enumerated.item[0] = 3;
- break;
- case 88200:
- ucontrol->value.enumerated.item[0] = 4;
- break;
- case 96000:
- ucontrol->value.enumerated.item[0] = 5;
- break;
- case 128000:
- ucontrol->value.enumerated.item[0] = 6;
- break;
- case 176400:
- ucontrol->value.enumerated.item[0] = 7;
- break;
- case 192000:
- ucontrol->value.enumerated.item[0] = 8;
- break;
-
- default:
- ucontrol->value.enumerated.item[0] = 9;
- }
- return 0;
-}
-
-#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
- .name = xname, \
- .index = xindex, \
- .access = SNDRV_CTL_ELEM_ACCESS_READ, \
- .info = snd_hdspm_info_system_clock_mode, \
- .get = snd_hdspm_get_system_clock_mode, \
-}
-
-
-
-static int hdspm_system_clock_mode(hdspm_t * hdspm)
-{
- /* Always reflect the hardware info, rme is never wrong !!!! */
-
- if (hdspm->control_register & HDSPM_ClockModeMaster)
- return 0;
- return 1;
-}
-
-static int snd_hdspm_info_system_clock_mode(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[] = { "Master", "Slave" };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 2;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item =
- uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name,
- texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_hdspm_get_system_clock_mode(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.enumerated.item[0] =
- hdspm_system_clock_mode(hdspm);
- return 0;
-}
-
-#define HDSPM_CLOCK_SOURCE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
- .name = xname, \
- .index = xindex, \
- .info = snd_hdspm_info_clock_source, \
- .get = snd_hdspm_get_clock_source, \
- .put = snd_hdspm_put_clock_source \
-}
-
-static int hdspm_clock_source(hdspm_t * hdspm)
-{
- if (hdspm->control_register & HDSPM_ClockModeMaster) {
- switch (hdspm->system_sample_rate) {
- case 32000:
- return 1;
- case 44100:
- return 2;
- case 48000:
- return 3;
- case 64000:
- return 4;
- case 88200:
- return 5;
- case 96000:
- return 6;
- case 128000:
- return 7;
- case 176400:
- return 8;
- case 192000:
- return 9;
- default:
- return 3;
- }
- } else {
- return 0;
- }
-}
-
-static int hdspm_set_clock_source(hdspm_t * hdspm, int mode)
-{
- int rate;
- switch (mode) {
-
- case HDSPM_CLOCK_SOURCE_AUTOSYNC:
- if (hdspm_external_sample_rate(hdspm) != 0) {
- hdspm->control_register &= ~HDSPM_ClockModeMaster;
- hdspm_write(hdspm, HDSPM_controlRegister,
- hdspm->control_register);
- return 0;
- }
- return -1;
- case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
- rate = 32000;
- break;
- case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
- rate = 44100;
- break;
- case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
- rate = 48000;
- break;
- case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
- rate = 64000;
- break;
- case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
- rate = 88200;
- break;
- case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
- rate = 96000;
- break;
- case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
- rate = 128000;
- break;
- case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
- rate = 176400;
- break;
- case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
- rate = 192000;
- break;
-
- default:
- rate = 44100;
- }
- hdspm->control_register |= HDSPM_ClockModeMaster;
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
- hdspm_set_rate(hdspm, rate, 1);
- return 0;
-}
-
-static int snd_hdspm_info_clock_source(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[] = { "AutoSync",
- "Internal 32.0 kHz", "Internal 44.1 kHz",
- "Internal 48.0 kHz",
- "Internal 64.0 kHz", "Internal 88.2 kHz",
- "Internal 96.0 kHz",
- "Internal 128.0 kHz", "Internal 176.4 kHz",
- "Internal 192.0 kHz"
- };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 10;
-
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item =
- uinfo->value.enumerated.items - 1;
-
- strcpy(uinfo->value.enumerated.name,
- texts[uinfo->value.enumerated.item]);
-
- return 0;
-}
-
-static int snd_hdspm_get_clock_source(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
- return 0;
-}
-
-static int snd_hdspm_put_clock_source(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
- int change;
- int val;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
- val = ucontrol->value.enumerated.item[0];
- if (val < 0)
- val = 0;
- if (val > 6)
- val = 6;
- spin_lock_irq(&hdspm->lock);
- if (val != hdspm_clock_source(hdspm))
- change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
- else
- change = 0;
- spin_unlock_irq(&hdspm->lock);
- return change;
-}
-
-#define HDSPM_PREF_SYNC_REF(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
- .name = xname, \
- .index = xindex, \
- .info = snd_hdspm_info_pref_sync_ref, \
- .get = snd_hdspm_get_pref_sync_ref, \
- .put = snd_hdspm_put_pref_sync_ref \
-}
-
-static int hdspm_pref_sync_ref(hdspm_t * hdspm)
-{
- /* Notice that this looks at the requested sync source,
- not the one actually in use.
- */
- switch (hdspm->control_register & HDSPM_SyncRefMask) {
- case HDSPM_SyncRef_Word:
- return HDSPM_SYNC_FROM_WORD;
- case HDSPM_SyncRef_MADI:
- return HDSPM_SYNC_FROM_MADI;
- }
-
- return HDSPM_SYNC_FROM_WORD;
-}
-
-static int hdspm_set_pref_sync_ref(hdspm_t * hdspm, int pref)
-{
- hdspm->control_register &= ~HDSPM_SyncRefMask;
-
- switch (pref) {
- case HDSPM_SYNC_FROM_MADI:
- hdspm->control_register |= HDSPM_SyncRef_MADI;
- break;
- case HDSPM_SYNC_FROM_WORD:
- hdspm->control_register |= HDSPM_SyncRef_Word;
- break;
- default:
- return -1;
- }
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
- return 0;
-}
-
-static int snd_hdspm_info_pref_sync_ref(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[] = { "Word", "MADI" };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
-
- uinfo->value.enumerated.items = 2;
-
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item =
- uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name,
- texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_hdspm_get_pref_sync_ref(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
- return 0;
-}
-
-static int snd_hdspm_put_pref_sync_ref(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
- int change, max;
- unsigned int val;
-
- max = 2;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
-
- val = ucontrol->value.enumerated.item[0] % max;
-
- spin_lock_irq(&hdspm->lock);
- change = (int) val != hdspm_pref_sync_ref(hdspm);
- hdspm_set_pref_sync_ref(hdspm, val);
- spin_unlock_irq(&hdspm->lock);
- return change;
-}
-
-#define HDSPM_AUTOSYNC_REF(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
- .name = xname, \
- .index = xindex, \
- .access = SNDRV_CTL_ELEM_ACCESS_READ, \
- .info = snd_hdspm_info_autosync_ref, \
- .get = snd_hdspm_get_autosync_ref, \
-}
-
-static int hdspm_autosync_ref(hdspm_t * hdspm)
-{
- /* This looks at the autosync selected sync reference */
- unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
-
- switch (status2 & HDSPM_SelSyncRefMask) {
-
- case HDSPM_SelSyncRef_WORD:
- return HDSPM_AUTOSYNC_FROM_WORD;
-
- case HDSPM_SelSyncRef_MADI:
- return HDSPM_AUTOSYNC_FROM_MADI;
-
- case HDSPM_SelSyncRef_NVALID:
- return HDSPM_AUTOSYNC_FROM_NONE;
-
- default:
- return 0;
- }
-
- return 0;
-}
-
-static int snd_hdspm_info_autosync_ref(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[] = { "WordClock", "MADI", "None" };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 3;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item =
- uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name,
- texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_hdspm_get_autosync_ref(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
- return 0;
-}
-
-#define HDSPM_LINE_OUT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
- .name = xname, \
- .index = xindex, \
- .info = snd_hdspm_info_line_out, \
- .get = snd_hdspm_get_line_out, \
- .put = snd_hdspm_put_line_out \
-}
-
-static int hdspm_line_out(hdspm_t * hdspm)
-{
- return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
-}
-
-
-static int hdspm_set_line_output(hdspm_t * hdspm, int out)
-{
- if (out)
- hdspm->control_register |= HDSPM_LineOut;
- else
- hdspm->control_register &= ~HDSPM_LineOut;
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
- return 0;
-}
-
-static int snd_hdspm_info_line_out(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
-static int snd_hdspm_get_line_out(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
-
- spin_lock_irq(&hdspm->lock);
- ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
- spin_unlock_irq(&hdspm->lock);
- return 0;
-}
-
-static int snd_hdspm_put_line_out(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
- int change;
- unsigned int val;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
- val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irq(&hdspm->lock);
- change = (int) val != hdspm_line_out(hdspm);
- hdspm_set_line_output(hdspm, val);
- spin_unlock_irq(&hdspm->lock);
- return change;
-}
-
-#define HDSPM_TX_64(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
- .name = xname, \
- .index = xindex, \
- .info = snd_hdspm_info_tx_64, \
- .get = snd_hdspm_get_tx_64, \
- .put = snd_hdspm_put_tx_64 \
-}
-
-static int hdspm_tx_64(hdspm_t * hdspm)
-{
- return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
-}
-
-static int hdspm_set_tx_64(hdspm_t * hdspm, int out)
-{
- if (out)
- hdspm->control_register |= HDSPM_TX_64ch;
- else
- hdspm->control_register &= ~HDSPM_TX_64ch;
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
- return 0;
-}
-
-static int snd_hdspm_info_tx_64(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
-static int snd_hdspm_get_tx_64(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
-
- spin_lock_irq(&hdspm->lock);
- ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
- spin_unlock_irq(&hdspm->lock);
- return 0;
-}
-
-static int snd_hdspm_put_tx_64(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
- int change;
- unsigned int val;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
- val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irq(&hdspm->lock);
- change = (int) val != hdspm_tx_64(hdspm);
- hdspm_set_tx_64(hdspm, val);
- spin_unlock_irq(&hdspm->lock);
- return change;
-}
-
-#define HDSPM_C_TMS(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
- .name = xname, \
- .index = xindex, \
- .info = snd_hdspm_info_c_tms, \
- .get = snd_hdspm_get_c_tms, \
- .put = snd_hdspm_put_c_tms \
-}
-
-static int hdspm_c_tms(hdspm_t * hdspm)
-{
- return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
-}
-
-static int hdspm_set_c_tms(hdspm_t * hdspm, int out)
-{
- if (out)
- hdspm->control_register |= HDSPM_clr_tms;
- else
- hdspm->control_register &= ~HDSPM_clr_tms;
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
- return 0;
-}
-
-static int snd_hdspm_info_c_tms(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
-static int snd_hdspm_get_c_tms(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
-
- spin_lock_irq(&hdspm->lock);
- ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
- spin_unlock_irq(&hdspm->lock);
- return 0;
-}
-
-static int snd_hdspm_put_c_tms(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
- int change;
- unsigned int val;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
- val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irq(&hdspm->lock);
- change = (int) val != hdspm_c_tms(hdspm);
- hdspm_set_c_tms(hdspm, val);
- spin_unlock_irq(&hdspm->lock);
- return change;
-}
-
-#define HDSPM_SAFE_MODE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
- .name = xname, \
- .index = xindex, \
- .info = snd_hdspm_info_safe_mode, \
- .get = snd_hdspm_get_safe_mode, \
- .put = snd_hdspm_put_safe_mode \
-}
-
-static int hdspm_safe_mode(hdspm_t * hdspm)
-{
- return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
-}
-
-static int hdspm_set_safe_mode(hdspm_t * hdspm, int out)
-{
- if (out)
- hdspm->control_register |= HDSPM_AutoInp;
- else
- hdspm->control_register &= ~HDSPM_AutoInp;
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
- return 0;
-}
-
-static int snd_hdspm_info_safe_mode(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
-static int snd_hdspm_get_safe_mode(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
-
- spin_lock_irq(&hdspm->lock);
- ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
- spin_unlock_irq(&hdspm->lock);
- return 0;
-}
-
-static int snd_hdspm_put_safe_mode(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
- int change;
- unsigned int val;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
- val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irq(&hdspm->lock);
- change = (int) val != hdspm_safe_mode(hdspm);
- hdspm_set_safe_mode(hdspm, val);
- spin_unlock_irq(&hdspm->lock);
- return change;
-}
-
-#define HDSPM_INPUT_SELECT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
- .name = xname, \
- .index = xindex, \
- .info = snd_hdspm_info_input_select, \
- .get = snd_hdspm_get_input_select, \
- .put = snd_hdspm_put_input_select \
-}
-
-static int hdspm_input_select(hdspm_t * hdspm)
-{
- return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
-}
-
-static int hdspm_set_input_select(hdspm_t * hdspm, int out)
-{
- if (out)
- hdspm->control_register |= HDSPM_InputSelect0;
- else
- hdspm->control_register &= ~HDSPM_InputSelect0;
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
- return 0;
-}
-
-static int snd_hdspm_info_input_select(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[] = { "optical", "coaxial" };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 2;
-
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item =
- uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name,
- texts[uinfo->value.enumerated.item]);
-
- return 0;
-}
-
-static int snd_hdspm_get_input_select(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
-
- spin_lock_irq(&hdspm->lock);
- ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
- spin_unlock_irq(&hdspm->lock);
- return 0;
-}
-
-static int snd_hdspm_put_input_select(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
- int change;
- unsigned int val;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
- val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irq(&hdspm->lock);
- change = (int) val != hdspm_input_select(hdspm);
- hdspm_set_input_select(hdspm, val);
- spin_unlock_irq(&hdspm->lock);
- return change;
-}
-
-/* Simple Mixer
- deprecated since to much faders ???
- MIXER interface says output (source, destination, value)
- where source > MAX_channels are playback channels
- on MADICARD
- - playback mixer matrix: [channelout+64] [output] [value]
- - input(thru) mixer matrix: [channelin] [output] [value]
- (better do 2 kontrols for seperation ?)
-*/
-
-#define HDSPM_MIXER(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
- .name = xname, \
- .index = xindex, \
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
- SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
- .info = snd_hdspm_info_mixer, \
- .get = snd_hdspm_get_mixer, \
- .put = snd_hdspm_put_mixer \
-}
-
-static int snd_hdspm_info_mixer(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 3;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 65535;
- uinfo->value.integer.step = 1;
- return 0;
-}
-
-static int snd_hdspm_get_mixer(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
- int source;
- int destination;
-
- source = ucontrol->value.integer.value[0];
- if (source < 0)
- source = 0;
- else if (source >= 2 * HDSPM_MAX_CHANNELS)
- source = 2 * HDSPM_MAX_CHANNELS - 1;
-
- destination = ucontrol->value.integer.value[1];
- if (destination < 0)
- destination = 0;
- else if (destination >= HDSPM_MAX_CHANNELS)
- destination = HDSPM_MAX_CHANNELS - 1;
-
- spin_lock_irq(&hdspm->lock);
- if (source >= HDSPM_MAX_CHANNELS)
- ucontrol->value.integer.value[2] =
- hdspm_read_pb_gain(hdspm, destination,
- source - HDSPM_MAX_CHANNELS);
- else
- ucontrol->value.integer.value[2] =
- hdspm_read_in_gain(hdspm, destination, source);
-
- spin_unlock_irq(&hdspm->lock);
-
- return 0;
-}
-
-static int snd_hdspm_put_mixer(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
- int change;
- int source;
- int destination;
- int gain;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
-
- source = ucontrol->value.integer.value[0];
- destination = ucontrol->value.integer.value[1];
-
- if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
- return -1;
- if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
- return -1;
-
- gain = ucontrol->value.integer.value[2];
-
- spin_lock_irq(&hdspm->lock);
-
- if (source >= HDSPM_MAX_CHANNELS)
- change = gain != hdspm_read_pb_gain(hdspm, destination,
- source -
- HDSPM_MAX_CHANNELS);
- else
- change =
- gain != hdspm_read_in_gain(hdspm, destination, source);
-
- if (change) {
- if (source >= HDSPM_MAX_CHANNELS)
- hdspm_write_pb_gain(hdspm, destination,
- source - HDSPM_MAX_CHANNELS,
- gain);
- else
- hdspm_write_in_gain(hdspm, destination, source,
- gain);
- }
- spin_unlock_irq(&hdspm->lock);
-
- return change;
-}
-
-/* The simple mixer control(s) provide gain control for the
- basic 1:1 mappings of playback streams to output
- streams.
-*/
-
-#define HDSPM_PLAYBACK_MIXER \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
- SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
- .info = snd_hdspm_info_playback_mixer, \
- .get = snd_hdspm_get_playback_mixer, \
- .put = snd_hdspm_put_playback_mixer \
-}
-
-static int snd_hdspm_info_playback_mixer(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 65536;
- uinfo->value.integer.step = 1;
- return 0;
-}
-
-static int snd_hdspm_get_playback_mixer(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
- int channel;
- int mapped_channel;
-
- channel = ucontrol->id.index - 1;
-
- snd_assert(channel >= 0
- || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
-
- if ((mapped_channel = hdspm->channel_map[channel]) < 0)
- return -EINVAL;
-
- spin_lock_irq(&hdspm->lock);
- ucontrol->value.integer.value[0] =
- hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel);
- spin_unlock_irq(&hdspm->lock);
-
- /* snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, value %d\n",
- ucontrol->id.index, channel, mapped_channel, ucontrol->value.integer.value[0]);
- */
-
- return 0;
-}
-
-static int snd_hdspm_put_playback_mixer(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
- int change;
- int channel;
- int mapped_channel;
- int gain;
-
- if (!snd_hdspm_use_is_exclusive(hdspm))
- return -EBUSY;
-
- channel = ucontrol->id.index - 1;
-
- snd_assert(channel >= 0
- || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
-
- if ((mapped_channel = hdspm->channel_map[channel]) < 0)
- return -EINVAL;
-
- gain = ucontrol->value.integer.value[0];
-
- spin_lock_irq(&hdspm->lock);
- change =
- gain != hdspm_read_pb_gain(hdspm, mapped_channel,
- mapped_channel);
- if (change)
- hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel,
- gain);
- spin_unlock_irq(&hdspm->lock);
- return change;
-}
-
-#define HDSPM_WC_SYNC_CHECK(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
- .name = xname, \
- .index = xindex, \
- .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
- .info = snd_hdspm_info_sync_check, \
- .get = snd_hdspm_get_wc_sync_check \
-}
-
-static int snd_hdspm_info_sync_check(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[] = { "No Lock", "Lock", "Sync" };
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 3;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item =
- uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name,
- texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int hdspm_wc_sync_check(hdspm_t * hdspm)
-{
- int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
- if (status2 & HDSPM_wcLock) {
- if (status2 & HDSPM_wcSync)
- return 2;
- else
- return 1;
- }
- return 0;
-}
-
-static int snd_hdspm_get_wc_sync_check(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm);
- return 0;
-}
-
-
-#define HDSPM_MADI_SYNC_CHECK(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
- .name = xname, \
- .index = xindex, \
- .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
- .info = snd_hdspm_info_sync_check, \
- .get = snd_hdspm_get_madisync_sync_check \
-}
-
-static int hdspm_madisync_sync_check(hdspm_t * hdspm)
-{
- int status = hdspm_read(hdspm, HDSPM_statusRegister);
- if (status & HDSPM_madiLock) {
- if (status & HDSPM_madiSync)
- return 2;
- else
- return 1;
- }
- return 0;
-}
-
-static int snd_hdspm_get_madisync_sync_check(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t *
- ucontrol)
-{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.enumerated.item[0] =
- hdspm_madisync_sync_check(hdspm);
- return 0;
-}
-
-
-
-
-static snd_kcontrol_new_t snd_hdspm_controls[] = {
-
- HDSPM_MIXER("Mixer", 0),
-/* 'Sample Clock Source' complies with the alsa control naming scheme */
- HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
-
- HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
- HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
- HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
- HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
-/* 'External Rate' complies with the alsa control naming scheme */
- HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
- HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
- HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0),
- HDSPM_LINE_OUT("Line Out", 0),
- HDSPM_TX_64("TX 64 channels mode", 0),
- HDSPM_C_TMS("Clear Track Marker", 0),
- HDSPM_SAFE_MODE("Safe Mode", 0),
- HDSPM_INPUT_SELECT("Input Select", 0),
-};
-
-static snd_kcontrol_new_t snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
-
-
-static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm)
-{
- int i;
-
- for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) {
- if (hdspm->system_sample_rate > 48000) {
- hdspm->playback_mixer_ctls[i]->vd[0].access =
- SNDRV_CTL_ELEM_ACCESS_INACTIVE |
- SNDRV_CTL_ELEM_ACCESS_READ |
- SNDRV_CTL_ELEM_ACCESS_VOLATILE;
- } else {
- hdspm->playback_mixer_ctls[i]->vd[0].access =
- SNDRV_CTL_ELEM_ACCESS_READWRITE |
- SNDRV_CTL_ELEM_ACCESS_VOLATILE;
- }
- snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
- SNDRV_CTL_EVENT_MASK_INFO,
- &hdspm->playback_mixer_ctls[i]->id);
- }
-
- return 0;
-}
-
-
-static int snd_hdspm_create_controls(snd_card_t * card, hdspm_t * hdspm)
-{
- unsigned int idx, limit;
- int err;
- snd_kcontrol_t *kctl;
-
- /* add control list first */
-
- for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls); idx++) {
- if ((err =
- snd_ctl_add(card, kctl =
- snd_ctl_new1(&snd_hdspm_controls[idx],
- hdspm))) < 0) {
- return err;
- }
- }
-
- /* Channel playback mixer as default control
- Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats to big for any alsamixer
- they are accesible via special IOCTL on hwdep
- and the mixer 2dimensional mixer control */
-
- snd_hdspm_playback_mixer.name = "Chn";
- limit = HDSPM_MAX_CHANNELS;
-
- /* The index values are one greater than the channel ID so that alsamixer
- will display them correctly. We want to use the index for fast lookup
- of the relevant channel, but if we use it at all, most ALSA software
- does the wrong thing with it ...
- */
-
- for (idx = 0; idx < limit; ++idx) {
- snd_hdspm_playback_mixer.index = idx + 1;
- if ((err = snd_ctl_add(card,
- kctl =
- snd_ctl_new1
- (&snd_hdspm_playback_mixer,
- hdspm)))) {
- return err;
- }
- hdspm->playback_mixer_ctls[idx] = kctl;
- }
-
- return 0;
-}
-
-/*------------------------------------------------------------
- /proc interface
- ------------------------------------------------------------*/
-
-static void
-snd_hdspm_proc_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer)
-{
- hdspm_t *hdspm = (hdspm_t *) entry->private_data;
- unsigned int status;
- unsigned int status2;
- char *pref_sync_ref;
- char *autosync_ref;
- char *system_clock_mode;
- char *clock_source;
- char *insel;
- char *syncref;
- int x, x2;
-
- status = hdspm_read(hdspm, HDSPM_statusRegister);
- status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
-
- snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
- hdspm->card_name, hdspm->card->number + 1,
- hdspm->firmware_rev,
- (status2 & HDSPM_version0) |
- (status2 & HDSPM_version1) | (status2 &
- HDSPM_version2));
-
- snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
- hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
-
- snd_iprintf(buffer, "--- System ---\n");
-
- snd_iprintf(buffer,
- "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
- status & HDSPM_audioIRQPending,
- (status & HDSPM_midi0IRQPending) ? 1 : 0,
- (status & HDSPM_midi1IRQPending) ? 1 : 0,
- hdspm->irq_count);
- snd_iprintf(buffer,
- "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n",
- ((status & HDSPM_BufferID) ? 1 : 0),
- (status & HDSPM_BufferPositionMask),
- (status & HDSPM_BufferPositionMask) % (2 *
- (int)hdspm->
- period_bytes),
- ((status & HDSPM_BufferPositionMask) -
- 64) % (2 * (int)hdspm->period_bytes),
- (long) hdspm_hw_pointer(hdspm) * 4);
-
- snd_iprintf(buffer,
- "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
- hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
- hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
- hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
- hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
- snd_iprintf(buffer,
- "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x\n",
- hdspm->control_register, hdspm->control2_register,
- status, status2);
-
- snd_iprintf(buffer, "--- Settings ---\n");
-
- x = 1 << (6 +
- hdspm_decode_latency(hdspm->
- control_register &
- HDSPM_LatencyMask));
-
- snd_iprintf(buffer,
- "Size (Latency): %d samples (2 periods of %lu bytes)\n",
- x, (unsigned long) hdspm->period_bytes);
-
- snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n",
- (hdspm->
- control_register & HDSPM_LineOut) ? "on " : "off",
- (hdspm->precise_ptr) ? "on" : "off");
-
- switch (hdspm->control_register & HDSPM_InputMask) {
- case HDSPM_InputOptical:
- insel = "Optical";
- break;
- case HDSPM_InputCoaxial:
- insel = "Coaxial";
- break;
- default:
- insel = "Unkown";
- }
-
- switch (hdspm->control_register & HDSPM_SyncRefMask) {
- case HDSPM_SyncRef_Word:
- syncref = "WordClock";
- break;
- case HDSPM_SyncRef_MADI:
- syncref = "MADI";
- break;
- default:
- syncref = "Unkown";
- }
- snd_iprintf(buffer, "Inputsel = %s, SyncRef = %s\n", insel,
- syncref);
-
- snd_iprintf(buffer,
- "ClearTrackMarker = %s, Transmit in %s Channel Mode, Auto Input %s\n",
- (hdspm->
- control_register & HDSPM_clr_tms) ? "on" : "off",
- (hdspm->
- control_register & HDSPM_TX_64ch) ? "64" : "56",
- (hdspm->
- control_register & HDSPM_AutoInp) ? "on" : "off");
-
- switch (hdspm_clock_source(hdspm)) {
- case HDSPM_CLOCK_SOURCE_AUTOSYNC:
- clock_source = "AutoSync";
- break;
- case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
- clock_source = "Internal 32 kHz";
- break;
- case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
- clock_source = "Internal 44.1 kHz";
- break;
- case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
- clock_source = "Internal 48 kHz";
- break;
- case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
- clock_source = "Internal 64 kHz";
- break;
- case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
- clock_source = "Internal 88.2 kHz";
- break;
- case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
- clock_source = "Internal 96 kHz";
- break;
- default:
- clock_source = "Error";
- }
- snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
- if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
- system_clock_mode = "Slave";
- } else {
- system_clock_mode = "Master";
- }
- snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
-
- switch (hdspm_pref_sync_ref(hdspm)) {
- case HDSPM_SYNC_FROM_WORD:
- pref_sync_ref = "Word Clock";
- break;
- case HDSPM_SYNC_FROM_MADI:
- pref_sync_ref = "MADI Sync";
- break;
- default:
- pref_sync_ref = "XXXX Clock";
- break;
- }
- snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
- pref_sync_ref);
-
- snd_iprintf(buffer, "System Clock Frequency: %d\n",
- hdspm->system_sample_rate);
-
-
- snd_iprintf(buffer, "--- Status:\n");
-
- x = status & HDSPM_madiSync;
- x2 = status2 & HDSPM_wcSync;
-
- snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
- (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
- "NoLock",
- (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
- "NoLock");
-
- switch (hdspm_autosync_ref(hdspm)) {
- case HDSPM_AUTOSYNC_FROM_WORD:
- autosync_ref = "Word Clock";
- break;
- case HDSPM_AUTOSYNC_FROM_MADI:
- autosync_ref = "MADI Sync";
- break;
- case HDSPM_AUTOSYNC_FROM_NONE:
- autosync_ref = "Input not valid";
- break;
- default:
- autosync_ref = "---";
- break;
- }
- snd_iprintf(buffer,
- "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
- autosync_ref, hdspm_external_sample_rate(hdspm),
- (status & HDSPM_madiFreqMask) >> 22,
- (status2 & HDSPM_wcFreqMask) >> 5);
-
- snd_iprintf(buffer, "Input: %s, Mode=%s\n",
- (status & HDSPM_AB_int) ? "Coax" : "Optical",
- (status & HDSPM_RX_64ch) ? "64 channels" :
- "56 channels");
-
- snd_iprintf(buffer, "\n");
-}
-
-static void __devinit snd_hdspm_proc_init(hdspm_t * hdspm)
-{
- snd_info_entry_t *entry;
-
- if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
- snd_info_set_text_ops(entry, hdspm, 1024,
- snd_hdspm_proc_read);
-}
-
-/*------------------------------------------------------------
- hdspm intitialize
- ------------------------------------------------------------*/
-
-static int snd_hdspm_set_defaults(hdspm_t * hdspm)
-{
- unsigned int i;
-
- /* ASSUMPTION: hdspm->lock is either held, or there is no need to
- hold it (e.g. during module initalization).
- */
-
- /* set defaults: */
-
- hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */
- hdspm_encode_latency(7) | /* latency maximum = 8192 samples */
- HDSPM_InputCoaxial | /* Input Coax not Optical */
- HDSPM_SyncRef_MADI | /* Madi is syncclock */
- HDSPM_LineOut | /* Analog output in */
- HDSPM_TX_64ch | /* transmit in 64ch mode */
- HDSPM_AutoInp; /* AutoInput chossing (takeover) */
-
- /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */
- /* ! HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */
- /* ! HDSPM_clr_tms = do not clear bits in track marks */
-
- hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
-
-#ifdef SNDRV_BIG_ENDIAN
- hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
-#else
- hdspm->control2_register = 0;
-#endif
-
- hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
- hdspm_compute_period_size(hdspm);
-
- /* silence everything */
-
- all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
-
- if (line_outs_monitor[hdspm->dev]) {
-
- snd_printk(KERN_INFO "HDSPM: sending all playback streams to line outs.\n");
-
- for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) {
- if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN))
- return -EIO;
- }
- }
-
- /* set a default rate so that the channel map is set up. */
- hdspm->channel_map = channel_map_madi_ss;
- hdspm_set_rate(hdspm, 44100, 1);
-
- return 0;
-}
-
-
-/*------------------------------------------------------------
- interupt
- ------------------------------------------------------------*/
-
-static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id,
- struct pt_regs *regs)
-{
- hdspm_t *hdspm = (hdspm_t *) dev_id;
- unsigned int status;
- int audio;
- int midi0;
- int midi1;
- unsigned int midi0status;
- unsigned int midi1status;
- int schedule = 0;
-
- status = hdspm_read(hdspm, HDSPM_statusRegister);
-
- audio = status & HDSPM_audioIRQPending;
- midi0 = status & HDSPM_midi0IRQPending;
- midi1 = status & HDSPM_midi1IRQPending;
-
- if (!audio && !midi0 && !midi1)
- return IRQ_NONE;
-
- hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
- hdspm->irq_count++;
-
- midi0status = hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff;
- midi1status = hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff;
-
- if (audio) {
-
- if (hdspm->capture_substream)
- snd_pcm_period_elapsed(hdspm->pcm->
- streams
- [SNDRV_PCM_STREAM_CAPTURE].
- substream);
-
- if (hdspm->playback_substream)
- snd_pcm_period_elapsed(hdspm->pcm->
- streams
- [SNDRV_PCM_STREAM_PLAYBACK].
- substream);
- }
-
- if (midi0 && midi0status) {
- /* we disable interrupts for this input until processing is done */
- hdspm->control_register &= ~HDSPM_Midi0InterruptEnable;
- hdspm_write(hdspm, HDSPM_controlRegister,
- hdspm->control_register);
- hdspm->midi[0].pending = 1;
- schedule = 1;
- }
- if (midi1 && midi1status) {
- /* we disable interrupts for this input until processing is done */
- hdspm->control_register &= ~HDSPM_Midi1InterruptEnable;
- hdspm_write(hdspm, HDSPM_controlRegister,
- hdspm->control_register);
- hdspm->midi[1].pending = 1;
- schedule = 1;
- }
- if (schedule)
- tasklet_hi_schedule(&hdspm->midi_tasklet);
- return IRQ_HANDLED;
-}
-
-/*------------------------------------------------------------
- pcm interface
- ------------------------------------------------------------*/
-
-
-static snd_pcm_uframes_t snd_hdspm_hw_pointer(snd_pcm_substream_t *
- substream)
-{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
- return hdspm_hw_pointer(hdspm);
-}
-
-static char *hdspm_channel_buffer_location(hdspm_t * hdspm,
- int stream, int channel)
-{
- int mapped_channel;
-
- snd_assert(channel >= 0
- || channel < HDSPM_MAX_CHANNELS, return NULL);
-
- if ((mapped_channel = hdspm->channel_map[channel]) < 0)
- return NULL;
-
- if (stream == SNDRV_PCM_STREAM_CAPTURE) {
- return hdspm->capture_buffer +
- mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
- } else {
- return hdspm->playback_buffer +
- mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
- }
-}
-
-
-/* dont know why need it ??? */
-static int snd_hdspm_playback_copy(snd_pcm_substream_t * substream,
- int channel, snd_pcm_uframes_t pos,
- void __user *src, snd_pcm_uframes_t count)
-{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
- char *channel_buf;
-
- snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
- return -EINVAL);
-
- channel_buf = hdspm_channel_buffer_location(hdspm,
- substream->pstr->
- stream, channel);
-
- snd_assert(channel_buf != NULL, return -EIO);
-
- return copy_from_user(channel_buf + pos * 4, src, count * 4);
-}
-
-static int snd_hdspm_capture_copy(snd_pcm_substream_t * substream,
- int channel, snd_pcm_uframes_t pos,
- void __user *dst, snd_pcm_uframes_t count)
-{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
- char *channel_buf;
-
- snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
- return -EINVAL);
-
- channel_buf = hdspm_channel_buffer_location(hdspm,
- substream->pstr->
- stream, channel);
- snd_assert(channel_buf != NULL, return -EIO);
- return copy_to_user(dst, channel_buf + pos * 4, count * 4);
-}
-
-static int snd_hdspm_hw_silence(snd_pcm_substream_t * substream,
- int channel, snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
-{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
- char *channel_buf;
-
- channel_buf =
- hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
- channel);
- snd_assert(channel_buf != NULL, return -EIO);
- memset(channel_buf + pos * 4, 0, count * 4);
- return 0;
-}
-
-static int snd_hdspm_reset(snd_pcm_substream_t * substream)
-{
- snd_pcm_runtime_t *runtime = substream->runtime;
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
- snd_pcm_substream_t *other;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- other = hdspm->capture_substream;
- else
- other = hdspm->playback_substream;
-
- if (hdspm->running)
- runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
- else
- runtime->status->hw_ptr = 0;
- if (other) {
- struct list_head *pos;
- snd_pcm_substream_t *s;
- snd_pcm_runtime_t *oruntime = other->runtime;
- snd_pcm_group_for_each(pos, substream) {
- s = snd_pcm_group_substream_entry(pos);
- if (s == other) {
- oruntime->status->hw_ptr =
- runtime->status->hw_ptr;
- break;
- }
- }
- }
- return 0;
-}
-
-static int snd_hdspm_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * params)
-{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
- int err;
- int i;
- pid_t this_pid;
- pid_t other_pid;
- struct snd_sg_buf *sgbuf;
-
-
- spin_lock_irq(&hdspm->lock);
-
- if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- this_pid = hdspm->playback_pid;
- other_pid = hdspm->capture_pid;
- } else {
- this_pid = hdspm->capture_pid;
- other_pid = hdspm->playback_pid;
- }
-
- if ((other_pid > 0) && (this_pid != other_pid)) {
-
- /* The other stream is open, and not by the same
- task as this one. Make sure that the parameters
- that matter are the same.
- */
-
- if (params_rate(params) != hdspm->system_sample_rate) {
- spin_unlock_irq(&hdspm->lock);
- _snd_pcm_hw_param_setempty(params,
- SNDRV_PCM_HW_PARAM_RATE);
- return -EBUSY;
- }
-
- if (params_period_size(params) != hdspm->period_bytes / 4) {
- spin_unlock_irq(&hdspm->lock);
- _snd_pcm_hw_param_setempty(params,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
- return -EBUSY;
- }
-
- }
- /* We're fine. */
- spin_unlock_irq(&hdspm->lock);
-
- /* how to make sure that the rate matches an externally-set one ? */
-
- spin_lock_irq(&hdspm->lock);
- if ((err = hdspm_set_rate(hdspm, params_rate(params), 0)) < 0) {
- spin_unlock_irq(&hdspm->lock);
- _snd_pcm_hw_param_setempty(params,
- SNDRV_PCM_HW_PARAM_RATE);
- return err;
- }
- spin_unlock_irq(&hdspm->lock);
-
- if ((err =
- hdspm_set_interrupt_interval(hdspm,
- params_period_size(params))) <
- 0) {
- _snd_pcm_hw_param_setempty(params,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
- return err;
- }
-
- /* Memory allocation, takashi's method, dont know if we should spinlock */
- /* malloc all buffer even if not enabled to get sure */
- /* malloc only needed bytes */
- err =
- snd_pcm_lib_malloc_pages(substream,
- HDSPM_CHANNEL_BUFFER_BYTES *
- params_channels(params));
- if (err < 0)
- return err;
-
- sgbuf = snd_pcm_substream_sgbuf(substream);
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-
- hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferOut,
- params_channels(params));
-
- for (i = 0; i < params_channels(params); ++i)
- snd_hdspm_enable_out(hdspm, i, 1);
-
- hdspm->playback_buffer =
- (unsigned char *) substream->runtime->dma_area;
- } else {
- hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn,
- params_channels(params));
-
- for (i = 0; i < params_channels(params); ++i)
- snd_hdspm_enable_in(hdspm, i, 1);
-
- hdspm->capture_buffer =
- (unsigned char *) substream->runtime->dma_area;
- }
- return 0;
-}
-
-static int snd_hdspm_hw_free(snd_pcm_substream_t * substream)
-{
- int i;
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-
- /* params_channels(params) should be enough,
- but to get sure in case of error */
- for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
- snd_hdspm_enable_out(hdspm, i, 0);
-
- hdspm->playback_buffer = NULL;
- } else {
- for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
- snd_hdspm_enable_in(hdspm, i, 0);
-
- hdspm->capture_buffer = NULL;
-
- }
-
- snd_pcm_lib_free_pages(substream);
-
- return 0;
-}
-
-static int snd_hdspm_channel_info(snd_pcm_substream_t * substream,
- snd_pcm_channel_info_t * info)
-{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
- int mapped_channel;
-
- snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL);
-
- if ((mapped_channel = hdspm->channel_map[info->channel]) < 0)
- return -EINVAL;
-
- info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
- info->first = 0;
- info->step = 32;
- return 0;
-}
-
-static int snd_hdspm_ioctl(snd_pcm_substream_t * substream,
- unsigned int cmd, void *arg)
-{
- switch (cmd) {
- case SNDRV_PCM_IOCTL1_RESET:
- {
- return snd_hdspm_reset(substream);
- }
-
- case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
- {
- snd_pcm_channel_info_t *info = arg;
- return snd_hdspm_channel_info(substream, info);
- }
- default:
- break;
- }
-
- return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-
-static int snd_hdspm_trigger(snd_pcm_substream_t * substream, int cmd)
-{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
- snd_pcm_substream_t *other;
- int running;
-
- spin_lock(&hdspm->lock);
- running = hdspm->running;
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- running |= 1 << substream->stream;
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- running &= ~(1 << substream->stream);
- break;
- default:
- snd_BUG();
- spin_unlock(&hdspm->lock);
- return -EINVAL;
- }
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- other = hdspm->capture_substream;
- else
- other = hdspm->playback_substream;
-
- if (other) {
- struct list_head *pos;
- snd_pcm_substream_t *s;
- snd_pcm_group_for_each(pos, substream) {
- s = snd_pcm_group_substream_entry(pos);
- if (s == other) {
- snd_pcm_trigger_done(s, substream);
- if (cmd == SNDRV_PCM_TRIGGER_START)
- running |= 1 << s->stream;
- else
- running &= ~(1 << s->stream);
- goto _ok;
- }
- }
- if (cmd == SNDRV_PCM_TRIGGER_START) {
- if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
- && substream->stream ==
- SNDRV_PCM_STREAM_CAPTURE)
- hdspm_silence_playback(hdspm);
- } else {
- if (running &&
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- hdspm_silence_playback(hdspm);
- }
- } else {
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- hdspm_silence_playback(hdspm);
- }
- _ok:
- snd_pcm_trigger_done(substream, substream);
- if (!hdspm->running && running)
- hdspm_start_audio(hdspm);
- else if (hdspm->running && !running)
- hdspm_stop_audio(hdspm);
- hdspm->running = running;
- spin_unlock(&hdspm->lock);
-
- return 0;
-}
-
-static int snd_hdspm_prepare(snd_pcm_substream_t * substream)
-{
- return 0;
-}
-
-static unsigned int period_sizes[] =
- { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
-
-static snd_pcm_hardware_t snd_hdspm_playback_subinfo = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_NONINTERLEAVED |
- SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
- .formats = SNDRV_PCM_FMTBIT_S32_LE,
- .rates = (SNDRV_PCM_RATE_32000 |
- SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000 |
- SNDRV_PCM_RATE_64000 |
- SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000),
- .rate_min = 32000,
- .rate_max = 96000,
- .channels_min = 1,
- .channels_max = HDSPM_MAX_CHANNELS,
- .buffer_bytes_max =
- HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
- .period_bytes_min = (64 * 4),
- .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
- .periods_min = 2,
- .periods_max = 2,
- .fifo_size = 0
-};
-
-static snd_pcm_hardware_t snd_hdspm_capture_subinfo = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_NONINTERLEAVED |
- SNDRV_PCM_INFO_SYNC_START),
- .formats = SNDRV_PCM_FMTBIT_S32_LE,
- .rates = (SNDRV_PCM_RATE_32000 |
- SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000 |
- SNDRV_PCM_RATE_64000 |
- SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000),
- .rate_min = 32000,
- .rate_max = 96000,
- .channels_min = 1,
- .channels_max = HDSPM_MAX_CHANNELS,
- .buffer_bytes_max =
- HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
- .period_bytes_min = (64 * 4),
- .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
- .periods_min = 2,
- .periods_max = 2,
- .fifo_size = 0
-};
-
-static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
- .count = ARRAY_SIZE(period_sizes),
- .list = period_sizes,
- .mask = 0
-};
-
-
-static int snd_hdspm_hw_rule_channels_rate(snd_pcm_hw_params_t * params,
- snd_pcm_hw_rule_t * rule)
-{
- hdspm_t *hdspm = rule->private;
- snd_interval_t *c =
- hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- snd_interval_t *r =
- hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
-
- if (r->min > 48000) {
- snd_interval_t t = {
- .min = 1,
- .max = hdspm->ds_channels,
- .integer = 1,
- };
- return snd_interval_refine(c, &t);
- } else if (r->max < 64000) {
- snd_interval_t t = {
- .min = 1,
- .max = hdspm->ss_channels,
- .integer = 1,
- };
- return snd_interval_refine(c, &t);
- }
- return 0;
-}
-
-static int snd_hdspm_hw_rule_rate_channels(snd_pcm_hw_params_t * params,
- snd_pcm_hw_rule_t * rule)
-{
- hdspm_t *hdspm = rule->private;
- snd_interval_t *c =
- hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- snd_interval_t *r =
- hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
-
- if (c->min <= hdspm->ss_channels) {
- snd_interval_t t = {
- .min = 32000,
- .max = 48000,
- .integer = 1,
- };
- return snd_interval_refine(r, &t);
- } else if (c->max > hdspm->ss_channels) {
- snd_interval_t t = {
- .min = 64000,
- .max = 96000,
- .integer = 1,
- };
-
- return snd_interval_refine(r, &t);
- }
- return 0;
-}
-
-static int snd_hdspm_playback_open(snd_pcm_substream_t * substream)
-{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
-
- snd_printdd("Open device substream %d\n", substream->stream);
-
- spin_lock_irq(&hdspm->lock);
-
- snd_pcm_set_sync(substream);
-
- runtime->hw = snd_hdspm_playback_subinfo;
-
- if (hdspm->capture_substream == NULL)
- hdspm_stop_audio(hdspm);
-
- hdspm->playback_pid = current->pid;
- hdspm->playback_substream = substream;
-
- spin_unlock_irq(&hdspm->lock);
-
- snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
-
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
- &hw_constraints_period_sizes);
-
- snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
- snd_hdspm_hw_rule_channels_rate, hdspm,
- SNDRV_PCM_HW_PARAM_RATE, -1);
-
- snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
- snd_hdspm_hw_rule_rate_channels, hdspm,
- SNDRV_PCM_HW_PARAM_CHANNELS, -1);
-
- return 0;
-}
-
-static int snd_hdspm_playback_release(snd_pcm_substream_t * substream)
-{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
-
- spin_lock_irq(&hdspm->lock);
-
- hdspm->playback_pid = -1;
- hdspm->playback_substream = NULL;
-
- spin_unlock_irq(&hdspm->lock);
-
- return 0;
-}
-
-
-static int snd_hdspm_capture_open(snd_pcm_substream_t * substream)
-{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
-
- spin_lock_irq(&hdspm->lock);
- snd_pcm_set_sync(substream);
- runtime->hw = snd_hdspm_capture_subinfo;
-
- if (hdspm->playback_substream == NULL)
- hdspm_stop_audio(hdspm);
-
- hdspm->capture_pid = current->pid;
- hdspm->capture_substream = substream;
-
- spin_unlock_irq(&hdspm->lock);
-
- snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
- &hw_constraints_period_sizes);
-
- snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
- snd_hdspm_hw_rule_channels_rate, hdspm,
- SNDRV_PCM_HW_PARAM_RATE, -1);
-
- snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
- snd_hdspm_hw_rule_rate_channels, hdspm,
- SNDRV_PCM_HW_PARAM_CHANNELS, -1);
- return 0;
-}
-
-static int snd_hdspm_capture_release(snd_pcm_substream_t * substream)
-{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
-
- spin_lock_irq(&hdspm->lock);
-
- hdspm->capture_pid = -1;
- hdspm->capture_substream = NULL;
-
- spin_unlock_irq(&hdspm->lock);
- return 0;
-}
-
-static int snd_hdspm_hwdep_dummy_op(snd_hwdep_t * hw, struct file *file)
-{
- /* we have nothing to initialize but the call is required */
- return 0;
-}
-
-
-static int snd_hdspm_hwdep_ioctl(snd_hwdep_t * hw, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- hdspm_t *hdspm = (hdspm_t *) hw->private_data;
- struct sndrv_hdspm_mixer_ioctl mixer;
- hdspm_config_info_t info;
- hdspm_version_t hdspm_version;
- struct sndrv_hdspm_peak_rms_ioctl rms;
-
- switch (cmd) {
-
-
- case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
- if (copy_from_user(&rms, (void __user *)arg, sizeof(rms)))
- return -EFAULT;
- /* maybe there is a chance to memorymap in future so dont touch just copy */
- if(copy_to_user_fromio((void __user *)rms.peak,
- hdspm->iobase+HDSPM_MADI_peakrmsbase,
- sizeof(hdspm_peak_rms_t)) != 0 )
- return -EFAULT;
-
- break;
-
-
- case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO:
-
- spin_lock_irq(&hdspm->lock);
- info.pref_sync_ref =
- (unsigned char) hdspm_pref_sync_ref(hdspm);
- info.wordclock_sync_check =
- (unsigned char) hdspm_wc_sync_check(hdspm);
-
- info.system_sample_rate = hdspm->system_sample_rate;
- info.autosync_sample_rate =
- hdspm_external_sample_rate(hdspm);
- info.system_clock_mode =
- (unsigned char) hdspm_system_clock_mode(hdspm);
- info.clock_source =
- (unsigned char) hdspm_clock_source(hdspm);
- info.autosync_ref =
- (unsigned char) hdspm_autosync_ref(hdspm);
- info.line_out = (unsigned char) hdspm_line_out(hdspm);
- info.passthru = 0;
- spin_unlock_irq(&hdspm->lock);
- if (copy_to_user((void __user *) arg, &info, sizeof(info)))
- return -EFAULT;
- break;
-
- case SNDRV_HDSPM_IOCTL_GET_VERSION:
- hdspm_version.firmware_rev = hdspm->firmware_rev;
- if (copy_to_user((void __user *) arg, &hdspm_version,
- sizeof(hdspm_version)))
- return -EFAULT;
- break;
-
- case SNDRV_HDSPM_IOCTL_GET_MIXER:
- if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
- return -EFAULT;
- if (copy_to_user
- ((void __user *)mixer.mixer, hdspm->mixer, sizeof(hdspm_mixer_t)))
- return -EFAULT;
- break;
-
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static snd_pcm_ops_t snd_hdspm_playback_ops = {
- .open = snd_hdspm_playback_open,
- .close = snd_hdspm_playback_release,
- .ioctl = snd_hdspm_ioctl,
- .hw_params = snd_hdspm_hw_params,
- .hw_free = snd_hdspm_hw_free,
- .prepare = snd_hdspm_prepare,
- .trigger = snd_hdspm_trigger,
- .pointer = snd_hdspm_hw_pointer,
- .copy = snd_hdspm_playback_copy,
- .silence = snd_hdspm_hw_silence,
- .page = snd_pcm_sgbuf_ops_page,
-};
-
-static snd_pcm_ops_t snd_hdspm_capture_ops = {
- .open = snd_hdspm_capture_open,
- .close = snd_hdspm_capture_release,
- .ioctl = snd_hdspm_ioctl,
- .hw_params = snd_hdspm_hw_params,
- .hw_free = snd_hdspm_hw_free,
- .prepare = snd_hdspm_prepare,
- .trigger = snd_hdspm_trigger,
- .pointer = snd_hdspm_hw_pointer,
- .copy = snd_hdspm_capture_copy,
- .page = snd_pcm_sgbuf_ops_page,
-};
-
-static int __devinit snd_hdspm_create_hwdep(snd_card_t * card,
- hdspm_t * hdspm)
-{
- snd_hwdep_t *hw;
- int err;
-
- if ((err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw)) < 0)
- return err;
-
- hdspm->hwdep = hw;
- hw->private_data = hdspm;
- strcpy(hw->name, "HDSPM hwdep interface");
-
- hw->ops.open = snd_hdspm_hwdep_dummy_op;
- hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
- hw->ops.release = snd_hdspm_hwdep_dummy_op;
-
- return 0;
-}
-
-
-/*------------------------------------------------------------
- memory interface
- ------------------------------------------------------------*/
-static int __devinit snd_hdspm_preallocate_memory(hdspm_t * hdspm)
-{
- int err;
- snd_pcm_t *pcm;
- size_t wanted;
-
- pcm = hdspm->pcm;
-
- wanted = HDSPM_DMA_AREA_BYTES + 4096; /* dont know why, but it works */
-
- if ((err =
- snd_pcm_lib_preallocate_pages_for_all(pcm,
- SNDRV_DMA_TYPE_DEV_SG,
- snd_dma_pci_data(hdspm->pci),
- wanted,
- wanted)) < 0) {
- snd_printdd("Could not preallocate %d Bytes\n", wanted);
-
- return err;
- } else
- snd_printdd(" Preallocated %d Bytes\n", wanted);
-
- return 0;
-}
-
-static int snd_hdspm_memory_free(hdspm_t * hdspm)
-{
- snd_printdd("memory_free_for_all %p\n", hdspm->pcm);
-
- snd_pcm_lib_preallocate_free_for_all(hdspm->pcm);
- return 0;
-}
-
-
-static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf,
- unsigned int reg, int channels)
-{
- int i;
- for (i = 0; i < (channels * 16); i++)
- hdspm_write(hdspm, reg + 4 * i,
- snd_pcm_sgbuf_get_addr(sgbuf,
- (size_t) 4096 * i));
-}
-
-/* ------------- ALSA Devices ---------------------------- */
-static int __devinit snd_hdspm_create_pcm(snd_card_t * card,
- hdspm_t * hdspm)
-{
- snd_pcm_t *pcm;
- int err;
-
- if ((err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm)) < 0)
- return err;
-
- hdspm->pcm = pcm;
- pcm->private_data = hdspm;
- strcpy(pcm->name, hdspm->card_name);
-
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- &snd_hdspm_playback_ops);
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
- &snd_hdspm_capture_ops);
-
- pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
-
- if ((err = snd_hdspm_preallocate_memory(hdspm)) < 0)
- return err;
-
- return 0;
-}
-
-static inline void snd_hdspm_initialize_midi_flush(hdspm_t * hdspm)
-{
- snd_hdspm_flush_midi_input(hdspm, 0);
- snd_hdspm_flush_midi_input(hdspm, 1);
-}
-
-static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card,
- hdspm_t * hdspm)
-{
- int err;
-
- snd_printdd("Create card...\n");
- if ((err = snd_hdspm_create_pcm(card, hdspm)) < 0)
- return err;
-
- if ((err = snd_hdspm_create_midi(card, hdspm, 0)) < 0)
- return err;
-
- if ((err = snd_hdspm_create_midi(card, hdspm, 1)) < 0)
- return err;
-
- if ((err = snd_hdspm_create_controls(card, hdspm)) < 0)
- return err;
-
- if ((err = snd_hdspm_create_hwdep(card, hdspm)) < 0)
- return err;
-
- snd_printdd("proc init...\n");
- snd_hdspm_proc_init(hdspm);
-
- hdspm->system_sample_rate = -1;
- hdspm->last_external_sample_rate = -1;
- hdspm->last_internal_sample_rate = -1;
- hdspm->playback_pid = -1;
- hdspm->capture_pid = -1;
- hdspm->capture_substream = NULL;
- hdspm->playback_substream = NULL;
-
- snd_printdd("Set defaults...\n");
- if ((err = snd_hdspm_set_defaults(hdspm)) < 0)
- return err;
-
- snd_printdd("Update mixer controls...\n");
- hdspm_update_simple_mixer_controls(hdspm);
-
- snd_printdd("Initializeing complete ???\n");
-
- if ((err = snd_card_register(card)) < 0) {
- snd_printk(KERN_ERR "HDSPM: error registering card\n");
- return err;
- }
-
- snd_printdd("... yes now\n");
-
- return 0;
-}
-
-static int __devinit snd_hdspm_create(snd_card_t * card, hdspm_t * hdspm,
- int precise_ptr, int enable_monitor)
-{
- struct pci_dev *pci = hdspm->pci;
- int err;
- int i;
-
- unsigned long io_extent;
-
- hdspm->irq = -1;
- hdspm->irq_count = 0;
-
- hdspm->midi[0].rmidi = NULL;
- hdspm->midi[1].rmidi = NULL;
- hdspm->midi[0].input = NULL;
- hdspm->midi[1].input = NULL;
- hdspm->midi[0].output = NULL;
- hdspm->midi[1].output = NULL;
- spin_lock_init(&hdspm->midi[0].lock);
- spin_lock_init(&hdspm->midi[1].lock);
- hdspm->iobase = NULL;
- hdspm->control_register = 0;
- hdspm->control2_register = 0;
-
- hdspm->playback_buffer = NULL;
- hdspm->capture_buffer = NULL;
-
- for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
- hdspm->playback_mixer_ctls[i] = NULL;
- hdspm->mixer = NULL;
-
- hdspm->card = card;
-
- spin_lock_init(&hdspm->lock);
-
- tasklet_init(&hdspm->midi_tasklet,
- hdspm_midi_tasklet, (unsigned long) hdspm);
-
- pci_read_config_word(hdspm->pci,
- PCI_CLASS_REVISION, &hdspm->firmware_rev);
-
- strcpy(card->driver, "HDSPM");
- strcpy(card->mixername, "Xilinx FPGA");
- hdspm->card_name = "RME HDSPM MADI";
-
- if ((err = pci_enable_device(pci)) < 0)
- return err;
-
- pci_set_master(hdspm->pci);
-
- if ((err = pci_request_regions(pci, "hdspm")) < 0)
- return err;
-
- hdspm->port = pci_resource_start(pci, 0);
- io_extent = pci_resource_len(pci, 0);
-
- snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
- hdspm->port, hdspm->port + io_extent - 1);
-
-
- if ((hdspm->iobase = ioremap_nocache(hdspm->port, io_extent)) == NULL) {
- snd_printk(KERN_ERR "HDSPM: unable to remap region 0x%lx-0x%lx\n",
- hdspm->port, hdspm->port + io_extent - 1);
- return -EBUSY;
- }
- snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
- (unsigned long)hdspm->iobase, hdspm->port,
- hdspm->port + io_extent - 1);
-
- if (request_irq(pci->irq, snd_hdspm_interrupt,
- SA_INTERRUPT | SA_SHIRQ, "hdspm",
- (void *) hdspm)) {
- snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
- return -EBUSY;
- }
-
- snd_printdd("use IRQ %d\n", pci->irq);
-
- hdspm->irq = pci->irq;
- hdspm->precise_ptr = precise_ptr;
-
- hdspm->monitor_outs = enable_monitor;
-
- snd_printdd("kmalloc Mixer memory of %d Bytes\n",
- sizeof(hdspm_mixer_t));
- if ((hdspm->mixer =
- (hdspm_mixer_t *) kmalloc(sizeof(hdspm_mixer_t), GFP_KERNEL))
- == NULL) {
- snd_printk(KERN_ERR "HDSPM: unable to kmalloc Mixer memory of %d Bytes\n",
- (int)sizeof(hdspm_mixer_t));
- return err;
- }
-
- hdspm->ss_channels = MADI_SS_CHANNELS;
- hdspm->ds_channels = MADI_DS_CHANNELS;
- hdspm->qs_channels = MADI_QS_CHANNELS;
-
- snd_printdd("create alsa devices.\n");
- if ((err = snd_hdspm_create_alsa_devices(card, hdspm)) < 0)
- return err;
-
- snd_hdspm_initialize_midi_flush(hdspm);
-
- return 0;
-}
-
-static int snd_hdspm_free(hdspm_t * hdspm)
-{
-
- if (hdspm->port) {
-
- /* stop th audio, and cancel all interrupts */
- hdspm->control_register &=
- ~(HDSPM_Start | HDSPM_AudioInterruptEnable
- | HDSPM_Midi0InterruptEnable |
- HDSPM_Midi1InterruptEnable);
- hdspm_write(hdspm, HDSPM_controlRegister,
- hdspm->control_register);
- }
-
- if (hdspm->irq >= 0)
- free_irq(hdspm->irq, (void *) hdspm);
-
-
- if (hdspm->mixer)
- kfree(hdspm->mixer);
-
- if (hdspm->iobase)
- iounmap(hdspm->iobase);
-
- snd_hdspm_memory_free(hdspm);
-
- if (hdspm->port)
- pci_release_regions(hdspm->pci);
-
- pci_disable_device(hdspm->pci);
- return 0;
-}
-
-static void snd_hdspm_card_free(snd_card_t * card)
-{
- hdspm_t *hdspm = (hdspm_t *) card->private_data;
-
- if (hdspm)
- snd_hdspm_free(hdspm);
-}
-
-static int __devinit snd_hdspm_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
-{
- static int dev;
- hdspm_t *hdspm;
- snd_card_t *card;
- int err;
-
- if (dev >= SNDRV_CARDS)
- return -ENODEV;
- if (!enable[dev]) {
- dev++;
- return -ENOENT;
- }
-
- if (!(card = snd_card_new(index[dev], id[dev],
- THIS_MODULE, sizeof(hdspm_t))))
- return -ENOMEM;
-
- hdspm = (hdspm_t *) card->private_data;
- card->private_free = snd_hdspm_card_free;
- hdspm->dev = dev;
- hdspm->pci = pci;
-
- if ((err =
- snd_hdspm_create(card, hdspm, precise_ptr[dev],
- enable_monitor[dev])) < 0) {
- snd_card_free(card);
- return err;
- }
-
- strcpy(card->shortname, "HDSPM MADI");
- sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name,
- hdspm->port, hdspm->irq);
-
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
-
- pci_set_drvdata(pci, card);
-
- dev++;
- return 0;
-}
-
-static void __devexit snd_hdspm_remove(struct pci_dev *pci)
-{
- snd_card_free(pci_get_drvdata(pci));
- pci_set_drvdata(pci, NULL);
-}
-
-static struct pci_driver driver = {
- .name = "RME Hammerfall DSP MADI",
- .id_table = snd_hdspm_ids,
- .probe = snd_hdspm_probe,
- .remove = __devexit_p(snd_hdspm_remove),
-};
-
-
-static int __init alsa_card_hdspm_init(void)
-{
- return pci_register_driver(&driver);
-}
-
-static void __exit alsa_card_hdspm_exit(void)
-{
- pci_unregister_driver(&driver);
-}
-
-module_init(alsa_card_hdspm_init)
-module_exit(alsa_card_hdspm_exit)
diff --git a/trunk/sound/pci/rme9652/rme9652.c b/trunk/sound/pci/rme9652/rme9652.c
index f3037402d58f..69cd81eaa111 100644
--- a/trunk/sound/pci/rme9652/rme9652.c
+++ b/trunk/sound/pci/rme9652/rme9652.c
@@ -303,22 +303,18 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
{
dmab->dev.type = SNDRV_DMA_TYPE_DEV;
dmab->dev.dev = snd_dma_pci_data(pci);
- if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
- if (dmab->bytes >= size)
- return 0;
+ if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
+ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+ size, dmab) < 0)
+ return -ENOMEM;
}
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
- size, dmab) < 0)
- return -ENOMEM;
return 0;
}
static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
{
- if (dmab->area) {
- dmab->dev.dev = NULL; /* make it anonymous */
+ if (dmab->area)
snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
- }
}
@@ -2668,7 +2664,7 @@ static struct pci_driver driver = {
static int __init alsa_card_hammerfall_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_hammerfall_exit(void)
diff --git a/trunk/sound/pci/sonicvibes.c b/trunk/sound/pci/sonicvibes.c
index 60ecb2bdb65e..cfd2c5fd6ddf 100644
--- a/trunk/sound/pci/sonicvibes.c
+++ b/trunk/sound/pci/sonicvibes.c
@@ -1522,7 +1522,7 @@ static struct pci_driver driver = {
static int __init alsa_card_sonicvibes_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_sonicvibes_exit(void)
diff --git a/trunk/sound/pci/trident/trident.c b/trunk/sound/pci/trident/trident.c
index 940d531575c0..ad58e08d66e2 100644
--- a/trunk/sound/pci/trident/trident.c
+++ b/trunk/sound/pci/trident/trident.c
@@ -143,8 +143,7 @@ static int __devinit snd_trident_probe(struct pci_dev *pci,
return err;
}
}
- if (trident->device != TRIDENT_DEVICE_ID_SI7018 &&
- (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
+ if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
trident->midi_port, 1,
trident->irq, 0, &trident->rmidi)) < 0) {
snd_card_free(card);
@@ -185,7 +184,7 @@ static struct pci_driver driver = {
static int __init alsa_card_trident_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_trident_exit(void)
diff --git a/trunk/sound/pci/via82xx.c b/trunk/sound/pci/via82xx.c
index 42c48f0ce8e8..9b4d74d49f98 100644
--- a/trunk/sound/pci/via82xx.c
+++ b/trunk/sound/pci/via82xx.c
@@ -101,7 +101,7 @@ MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
module_param_array(ac97_quirk, charp, NULL, 0444);
MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
module_param_array(dxs_support, int, NULL, 0444);
-MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)");
+MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA)");
/* pci ids */
@@ -302,7 +302,6 @@ DEFINE_VIA_REGSET(CAPTURE_8233, 0x60);
#define VIA_DXS_DISABLE 2
#define VIA_DXS_48K 3
#define VIA_DXS_NO_VRA 4
-#define VIA_DXS_SRC 5
/*
@@ -381,7 +380,6 @@ struct _snd_via82xx {
struct via_rate_lock rates[2]; /* playback and capture */
unsigned int dxs_fixed: 1; /* DXS channel accepts only 48kHz */
unsigned int no_vra: 1; /* no need to set VRA on DXS channels */
- unsigned int dxs_src: 1; /* use full SRC capabilities of DXS */
unsigned int spdif_on: 1; /* only spdif rates work to external DACs */
snd_pcm_t *pcms[2];
@@ -491,8 +489,10 @@ static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
snd_dma_free_pages(&dev->table);
dev->table.area = NULL;
}
- kfree(dev->idx_table);
- dev->idx_table = NULL;
+ if (dev->idx_table) {
+ kfree(dev->idx_table);
+ dev->idx_table = NULL;
+ }
return 0;
}
@@ -924,17 +924,15 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream)
via82xx_t *chip = snd_pcm_substream_chip(substream);
viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
snd_pcm_runtime_t *runtime = substream->runtime;
- int ac97_rate = chip->dxs_src ? 48000 : runtime->rate;
int rate_changed;
u32 rbits;
- if ((rate_changed = via_lock_rate(&chip->rates[0], ac97_rate)) < 0)
+ if ((rate_changed = via_lock_rate(&chip->rates[0], runtime->rate)) < 0)
return rate_changed;
if (rate_changed) {
snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE,
chip->no_vra ? 48000 : runtime->rate);
- snd_ac97_set_rate(chip->ac97, AC97_SPDIF,
- chip->no_vra ? 48000 : runtime->rate);
+ snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate);
}
if (runtime->rate == 48000)
rbits = 0xfffff;
@@ -1076,12 +1074,6 @@ static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_subst
/* fixed DXS playback rate */
runtime->hw.rates = SNDRV_PCM_RATE_48000;
runtime->hw.rate_min = runtime->hw.rate_max = 48000;
- } else if (chip->dxs_src && viadev->reg_offset < 0x40) {
- /* use full SRC capabilities of DXS */
- runtime->hw.rates = (SNDRV_PCM_RATE_CONTINUOUS |
- SNDRV_PCM_RATE_8000_48000);
- runtime->hw.rate_min = 8000;
- runtime->hw.rate_max = 48000;
} else if (! ratep->rate) {
int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC;
runtime->hw.rates = chip->ac97->rates[idx];
@@ -1558,51 +1550,51 @@ static void snd_via82xx_mixer_free_ac97(ac97_t *ac97)
static struct ac97_quirk ac97_quirks[] = {
{
- .subvendor = 0x1106,
- .subdevice = 0x4161,
+ .vendor = 0x1106,
+ .device = 0x4161,
.codec_id = 0x56494161, /* VT1612A */
.name = "Soltek SL-75DRV5",
.type = AC97_TUNE_NONE
},
{ /* FIXME: which codec? */
- .subvendor = 0x1106,
- .subdevice = 0x4161,
+ .vendor = 0x1106,
+ .device = 0x4161,
.name = "ASRock K7VT2",
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x1019,
- .subdevice = 0x0a81,
+ .vendor = 0x1019,
+ .device = 0x0a81,
.name = "ECS K7VTA3",
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x1019,
- .subdevice = 0x0a85,
+ .vendor = 0x1019,
+ .device = 0x0a85,
.name = "ECS L7VMM2",
.type = AC97_TUNE_HP_ONLY
},
{
- .subvendor = 0x1849,
- .subdevice = 0x3059,
+ .vendor = 0x1849,
+ .device = 0x3059,
.name = "ASRock K7VM2",
.type = AC97_TUNE_HP_ONLY /* VT1616 */
},
{
- .subvendor = 0x14cd,
- .subdevice = 0x7002,
+ .vendor = 0x14cd,
+ .device = 0x7002,
.name = "Unknown",
.type = AC97_TUNE_ALC_JACK
},
{
- .subvendor = 0x1071,
- .subdevice = 0x8590,
+ .vendor = 0x1071,
+ .device = 0x8590,
.name = "Mitac Mobo",
.type = AC97_TUNE_ALC_JACK
},
{
- .subvendor = 0x161f,
- .subdevice = 0x202b,
+ .vendor = 0x161f,
+ .device = 0x202b,
.name = "Arima Notebook",
.type = AC97_TUNE_HP_ONLY,
},
@@ -2140,8 +2132,8 @@ static struct via823x_info via823x_cards[] __devinitdata = {
* auto detection of DXS channel supports.
*/
struct dxs_whitelist {
- unsigned short subvendor;
- unsigned short subdevice;
+ unsigned short vendor;
+ unsigned short device;
unsigned short mask;
short action; /* new dxs_support value */
};
@@ -2149,44 +2141,38 @@ struct dxs_whitelist {
static int __devinit check_dxs_list(struct pci_dev *pci)
{
static struct dxs_whitelist whitelist[] = {
- { .subvendor = 0x1005, .subdevice = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
- { .subvendor = 0x1019, .subdevice = 0x0996, .action = VIA_DXS_48K },
- { .subvendor = 0x1019, .subdevice = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
- { .subvendor = 0x1019, .subdevice = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */
- { .subvendor = 0x1025, .subdevice = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */
- { .subvendor = 0x1043, .subdevice = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
- { .subvendor = 0x1043, .subdevice = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
- { .subvendor = 0x1043, .subdevice = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/
- { .subvendor = 0x1043, .subdevice = 0x812a, .action = VIA_DXS_SRC }, /* ASUS A8V Deluxe */
- { .subvendor = 0x1071, .subdevice = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
- { .subvendor = 0x1071, .subdevice = 0x8399, .action = VIA_DXS_NO_VRA }, /* Umax AB 595T (VIA K8N800A - VT8237) */
- { .subvendor = 0x10cf, .subdevice = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
- { .subvendor = 0x1106, .subdevice = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
- { .subvendor = 0x1106, .subdevice = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */
- { .subvendor = 0x1106, .subdevice = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */
- { .subvendor = 0x1106, .subdevice = 0xc001, .action = VIA_DXS_SRC }, /* Insight P4-ITX */
- { .subvendor = 0x1297, .subdevice = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */
- { .subvendor = 0x1297, .subdevice = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */
- { .subvendor = 0x1458, .subdevice = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
- { .subvendor = 0x1462, .subdevice = 0x0080, .action = VIA_DXS_SRC }, /* MSI K8T Neo-FIS2R */
- { .subvendor = 0x1462, .subdevice = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
- { .subvendor = 0x1462, .subdevice = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
- { .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */
- { .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
- { .subvendor = 0x147b, .subdevice = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
- { .subvendor = 0x147b, .subdevice = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */
- { .subvendor = 0x147b, .subdevice = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */
- { .subvendor = 0x147b, .subdevice = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */
- { .subvendor = 0x14ff, .subdevice = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */
- { .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_NO_VRA }, /* Twinhead mobo */
- { .subvendor = 0x1584, .subdevice = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */
- { .subvendor = 0x1584, .subdevice = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */
- { .subvendor = 0x161f, .subdevice = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */
- { .subvendor = 0x161f, .subdevice = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
- { .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
- { .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
- { .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */
- { .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */
+ { .vendor = 0x1005, .device = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
+ { .vendor = 0x1019, .device = 0x0996, .action = VIA_DXS_48K },
+ { .vendor = 0x1019, .device = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
+ { .vendor = 0x1019, .device = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */
+ { .vendor = 0x1025, .device = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */
+ { .vendor = 0x1043, .device = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
+ { .vendor = 0x1043, .device = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
+ { .vendor = 0x1043, .device = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/
+ { .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
+ { .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
+ { .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
+ { .vendor = 0x1106, .device = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */
+ { .vendor = 0x1106, .device = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */
+ { .vendor = 0x1297, .device = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */
+ { .vendor = 0x1297, .device = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */
+ { .vendor = 0x1458, .device = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
+ { .vendor = 0x1462, .device = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
+ { .vendor = 0x1462, .device = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
+ { .vendor = 0x1462, .device = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */
+ { .vendor = 0x1462, .device = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
+ { .vendor = 0x147b, .device = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
+ { .vendor = 0x147b, .device = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */
+ { .vendor = 0x147b, .device = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */
+ { .vendor = 0x147b, .device = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */
+ { .vendor = 0x14ff, .device = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */
+ { .vendor = 0x1584, .device = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */
+ { .vendor = 0x1584, .device = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */
+ { .vendor = 0x161f, .device = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */
+ { .vendor = 0x161f, .device = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
+ { .vendor = 0x1631, .device = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
+ { .vendor = 0x1695, .device = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
+ { .vendor = 0x1849, .device = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */
{ } /* terminator */
};
struct dxs_whitelist *w;
@@ -2196,14 +2182,14 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
- for (w = whitelist; w->subvendor; w++) {
- if (w->subvendor != subsystem_vendor)
+ for (w = whitelist; w->vendor; w++) {
+ if (w->vendor != subsystem_vendor)
continue;
if (w->mask) {
- if ((w->mask & subsystem_device) == w->subdevice)
+ if ((w->mask & subsystem_device) == w->device)
return w->action;
} else {
- if (subsystem_device == w->subdevice)
+ if (subsystem_device == w->device)
return w->action;
}
}
@@ -2212,9 +2198,8 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
* not detected, try 48k rate only to be sure.
*/
printk(KERN_INFO "via82xx: Assuming DXS channels with 48k fixed sample rate.\n");
- printk(KERN_INFO " Please try dxs_support=5 option\n");
+ printk(KERN_INFO " Please try dxs_support=1 or dxs_support=4 option\n");
printk(KERN_INFO " and report if it works on your machine.\n");
- printk(KERN_INFO " For more details, read ALSA-Configuration.txt.\n");
return VIA_DXS_48K;
};
@@ -2303,10 +2288,6 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
chip->dxs_fixed = 1;
else if (dxs_support[dev] == VIA_DXS_NO_VRA)
chip->no_vra = 1;
- else if (dxs_support[dev] == VIA_DXS_SRC) {
- chip->no_vra = 1;
- chip->dxs_src = 1;
- }
}
if ((err = snd_via8233_init_misc(chip, dev)) < 0)
goto __error;
@@ -2353,7 +2334,7 @@ static struct pci_driver driver = {
static int __init alsa_card_via82xx_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_via82xx_exit(void)
diff --git a/trunk/sound/pci/via82xx_modem.c b/trunk/sound/pci/via82xx_modem.c
index 5896d289f9ac..ea5c6f640159 100644
--- a/trunk/sound/pci/via82xx_modem.c
+++ b/trunk/sound/pci/via82xx_modem.c
@@ -352,8 +352,10 @@ static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
snd_dma_free_pages(&dev->table);
dev->table.area = NULL;
}
- kfree(dev->idx_table);
- dev->idx_table = NULL;
+ if (dev->idx_table) {
+ kfree(dev->idx_table);
+ dev->idx_table = NULL;
+ }
return 0;
}
@@ -418,10 +420,7 @@ static void snd_via82xx_codec_write(ac97_t *ac97,
{
via82xx_t *chip = ac97->private_data;
unsigned int xval;
- if(reg == AC97_GPIO_STATUS) {
- outl(val, VIAREG(chip, GPI_STATUS));
- return;
- }
+
xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY;
xval <<= VIA_REG_AC97_CODEC_ID_SHIFT;
xval |= reg << VIA_REG_AC97_CMD_SHIFT;
@@ -545,6 +544,25 @@ static int snd_via82xx_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
return 0;
}
+static int snd_via82xx_modem_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
+{
+ via82xx_t *chip = snd_pcm_substream_chip(substream);
+ unsigned int val = 0;
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ val = snd_ac97_read(chip->ac97, AC97_GPIO_STATUS);
+ outl(val|AC97_GPIO_LINE1_OH, VIAREG(chip, GPI_STATUS));
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ val = snd_ac97_read(chip->ac97, AC97_GPIO_STATUS);
+ outl(val&~AC97_GPIO_LINE1_OH, VIAREG(chip, GPI_STATUS));
+ break;
+ default:
+ break;
+ }
+ return snd_via82xx_pcm_trigger(substream, cmd);
+}
+
/*
* pointer callbacks
*/
@@ -788,7 +806,7 @@ static snd_pcm_ops_t snd_via686_playback_ops = {
.hw_params = snd_via82xx_hw_params,
.hw_free = snd_via82xx_hw_free,
.prepare = snd_via82xx_pcm_prepare,
- .trigger = snd_via82xx_pcm_trigger,
+ .trigger = snd_via82xx_modem_pcm_trigger,
.pointer = snd_via686_pcm_pointer,
.page = snd_pcm_sgbuf_ops_page,
};
@@ -801,7 +819,7 @@ static snd_pcm_ops_t snd_via686_capture_ops = {
.hw_params = snd_via82xx_hw_params,
.hw_free = snd_via82xx_hw_free,
.prepare = snd_via82xx_pcm_prepare,
- .trigger = snd_via82xx_pcm_trigger,
+ .trigger = snd_via82xx_modem_pcm_trigger,
.pointer = snd_via686_pcm_pointer,
.page = snd_pcm_sgbuf_ops_page,
};
@@ -920,7 +938,7 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip)
*
*/
-static int snd_via82xx_chip_init(via82xx_t *chip)
+static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
{
unsigned int val;
int max_count;
@@ -1215,7 +1233,7 @@ static struct pci_driver driver = {
static int __init alsa_card_via82xx_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_via82xx_exit(void)
diff --git a/trunk/sound/pci/vx222/vx222.c b/trunk/sound/pci/vx222/vx222.c
index dca6bd2c7580..4ffbb25658a5 100644
--- a/trunk/sound/pci/vx222/vx222.c
+++ b/trunk/sound/pci/vx222/vx222.c
@@ -260,7 +260,7 @@ static struct pci_driver driver = {
static int __init alsa_card_vx222_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_vx222_exit(void)
diff --git a/trunk/sound/pci/ymfpci/ymfpci.c b/trunk/sound/pci/ymfpci/ymfpci.c
index 5b5b624b47d0..9f3ef22df08d 100644
--- a/trunk/sound/pci/ymfpci/ymfpci.c
+++ b/trunk/sound/pci/ymfpci/ymfpci.c
@@ -360,7 +360,7 @@ static struct pci_driver driver = {
static int __init alsa_card_ymfpci_init(void)
{
- return pci_register_driver(&driver);
+ return pci_module_init(&driver);
}
static void __exit alsa_card_ymfpci_exit(void)
diff --git a/trunk/sound/pci/ymfpci/ymfpci_main.c b/trunk/sound/pci/ymfpci/ymfpci_main.c
index 2ae79610ecb5..05f1629760bc 100644
--- a/trunk/sound/pci/ymfpci/ymfpci_main.c
+++ b/trunk/sound/pci/ymfpci/ymfpci_main.c
@@ -829,7 +829,9 @@ static snd_pcm_hardware_t snd_ymfpci_capture =
static void snd_ymfpci_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
- kfree(runtime->private_data);
+ ymfpci_pcm_t *ypcm = runtime->private_data;
+
+ kfree(ypcm);
}
static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream)
@@ -1419,15 +1421,17 @@ static snd_kcontrol_new_t snd_ymfpci_drec_source __devinitdata = {
static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
+ unsigned int mask = 1;
+
switch (kcontrol->private_value) {
case YDSXGR_SPDIFOUTCTRL: break;
case YDSXGR_SPDIFINCTRL: break;
default: return -EINVAL;
}
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
+ uinfo->value.integer.max = mask;
return 0;
}
@@ -1435,7 +1439,7 @@ static int snd_ymfpci_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
{
ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value;
- unsigned int shift = 0, mask = 1;
+ unsigned int shift = 0, mask = 1, invert = 0;
switch (kcontrol->private_value) {
case YDSXGR_SPDIFOUTCTRL: break;
@@ -1443,6 +1447,8 @@ static int snd_ymfpci_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
default: return -EINVAL;
}
ucontrol->value.integer.value[0] = (snd_ymfpci_readl(chip, reg) >> shift) & mask;
+ if (invert)
+ ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
return 0;
}
@@ -1450,7 +1456,7 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
{
ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value;
- unsigned int shift = 0, mask = 1;
+ unsigned int shift = 0, mask = 1, invert = 0;
int change;
unsigned int val, oval;
@@ -1460,6 +1466,8 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
default: return -EINVAL;
}
val = (ucontrol->value.integer.value[0] & mask);
+ if (invert)
+ val = mask - val;
val <<= shift;
spin_lock_irq(&chip->reg_lock);
oval = snd_ymfpci_readl(chip, reg);
@@ -1479,13 +1487,14 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
static int snd_ymfpci_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
unsigned int reg = kcontrol->private_value;
+ unsigned int mask = 16383;
if (reg < 0x80 || reg >= 0xc0)
return -EINVAL;
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 16383;
+ uinfo->value.integer.max = mask;
return 0;
}
@@ -1493,7 +1502,7 @@ static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
{
ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
unsigned int reg = kcontrol->private_value;
- unsigned int shift_left = 0, shift_right = 16, mask = 16383;
+ unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0;
unsigned int val;
if (reg < 0x80 || reg >= 0xc0)
@@ -1503,6 +1512,10 @@ static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
spin_unlock_irq(&chip->reg_lock);
ucontrol->value.integer.value[0] = (val >> shift_left) & mask;
ucontrol->value.integer.value[1] = (val >> shift_right) & mask;
+ if (invert) {
+ ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
+ ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
+ }
return 0;
}
@@ -1510,7 +1523,7 @@ static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
{
ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
unsigned int reg = kcontrol->private_value;
- unsigned int shift_left = 0, shift_right = 16, mask = 16383;
+ unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0;
int change;
unsigned int val1, val2, oval;
@@ -1518,6 +1531,10 @@ static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return -EINVAL;
val1 = ucontrol->value.integer.value[0] & mask;
val2 = ucontrol->value.integer.value[1] & mask;
+ if (invert) {
+ val1 = mask - val1;
+ val2 = mask - val2;
+ }
val1 <<= shift_left;
val2 <<= shift_right;
spin_lock_irq(&chip->reg_lock);
diff --git a/trunk/sound/pcmcia/vx/vx_entry.c b/trunk/sound/pcmcia/vx/vx_entry.c
index 332bbca3dfc4..53d8172c52ae 100644
--- a/trunk/sound/pcmcia/vx/vx_entry.c
+++ b/trunk/sound/pcmcia/vx/vx_entry.c
@@ -68,7 +68,8 @@ static int snd_vxpocket_free(vx_core_t *chip)
if (hw)
hw->card_list[vxp->index] = NULL;
chip->card = NULL;
- kfree(chip->dev);
+ if (chip->dev)
+ kfree(chip->dev);
snd_vx_free_firmware(chip);
kfree(chip);
diff --git a/trunk/sound/synth/emux/emux_effect.c b/trunk/sound/synth/emux/emux_effect.c
index 4764940f11a0..ec3fc1ba7fca 100644
--- a/trunk/sound/synth/emux/emux_effect.c
+++ b/trunk/sound/synth/emux/emux_effect.c
@@ -291,8 +291,10 @@ snd_emux_create_effect(snd_emux_port_t *p)
void
snd_emux_delete_effect(snd_emux_port_t *p)
{
- kfree(p->effect);
- p->effect = NULL;
+ if (p->effect) {
+ kfree(p->effect);
+ p->effect = NULL;
+ }
}
void
diff --git a/trunk/sound/usb/Kconfig b/trunk/sound/usb/Kconfig
index f05d02f5b69f..9329e992c841 100644
--- a/trunk/sound/usb/Kconfig
+++ b/trunk/sound/usb/Kconfig
@@ -6,7 +6,6 @@ menu "USB devices"
config SND_USB_AUDIO
tristate "USB Audio/MIDI driver"
depends on SND && USB
- select SND_HWDEP
select SND_RAWMIDI
select SND_PCM
help
diff --git a/trunk/sound/usb/usbaudio.c b/trunk/sound/usb/usbaudio.c
index a75695045f29..aae66144d411 100644
--- a/trunk/sound/usb/usbaudio.c
+++ b/trunk/sound/usb/usbaudio.c
@@ -98,7 +98,7 @@ MODULE_PARM_DESC(async_unlink, "Use async unlink mode.");
#define MAX_PACKS 10
#define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */
#define MAX_URBS 5 /* max. 20ms long packets */
-#define SYNC_URBS 4 /* always four urbs for sync */
+#define SYNC_URBS 2 /* always two urbs for sync */
#define MIN_PACKS_URB 1 /* minimum 1 packet per urb */
typedef struct snd_usb_substream snd_usb_substream_t;
@@ -177,7 +177,7 @@ struct snd_usb_substream {
unsigned int nurbs; /* # urbs */
snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */
snd_urb_ctx_t syncurb[SYNC_URBS]; /* sync urb table */
- char syncbuf[SYNC_URBS * 4]; /* sync buffer; it's so small - let's get static */
+ char syncbuf[SYNC_URBS * MAX_PACKS * 4]; /* sync buffer; it's so small - let's get static */
char *tmpbuf; /* temporary buffer for playback */
u64 formats; /* format bitmasks (all or'ed) */
@@ -251,13 +251,17 @@ static int prepare_capture_sync_urb(snd_usb_substream_t *subs,
{
unsigned char *cp = urb->transfer_buffer;
snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
+ int i, offs;
+ urb->number_of_packets = ctx->packets;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
- urb->iso_frame_desc[0].length = 3;
- urb->iso_frame_desc[0].offset = 0;
- cp[0] = subs->freqn >> 2;
- cp[1] = subs->freqn >> 10;
- cp[2] = subs->freqn >> 18;
+ for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4, cp += 4) {
+ urb->iso_frame_desc[i].length = 3;
+ urb->iso_frame_desc[i].offset = offs;
+ cp[0] = subs->freqn >> 2;
+ cp[1] = subs->freqn >> 10;
+ cp[2] = subs->freqn >> 18;
+ }
return 0;
}
@@ -273,14 +277,18 @@ static int prepare_capture_sync_urb_hs(snd_usb_substream_t *subs,
{
unsigned char *cp = urb->transfer_buffer;
snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
+ int i, offs;
+ urb->number_of_packets = ctx->packets;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
- urb->iso_frame_desc[0].length = 4;
- urb->iso_frame_desc[0].offset = 0;
- cp[0] = subs->freqn;
- cp[1] = subs->freqn >> 8;
- cp[2] = subs->freqn >> 16;
- cp[3] = subs->freqn >> 24;
+ for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4, cp += 4) {
+ urb->iso_frame_desc[i].length = 4;
+ urb->iso_frame_desc[i].offset = offs;
+ cp[0] = subs->freqn;
+ cp[1] = subs->freqn >> 8;
+ cp[2] = subs->freqn >> 16;
+ cp[3] = subs->freqn >> 24;
+ }
return 0;
}
@@ -410,11 +418,15 @@ static int prepare_playback_sync_urb(snd_usb_substream_t *subs,
snd_pcm_runtime_t *runtime,
struct urb *urb)
{
+ int i, offs;
snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
+ urb->number_of_packets = ctx->packets;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
- urb->iso_frame_desc[0].length = 3;
- urb->iso_frame_desc[0].offset = 0;
+ for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4) {
+ urb->iso_frame_desc[i].length = 3;
+ urb->iso_frame_desc[i].offset = offs;
+ }
return 0;
}
@@ -428,11 +440,15 @@ static int prepare_playback_sync_urb_hs(snd_usb_substream_t *subs,
snd_pcm_runtime_t *runtime,
struct urb *urb)
{
+ int i, offs;
snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
+ urb->number_of_packets = ctx->packets;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
- urb->iso_frame_desc[0].length = 4;
- urb->iso_frame_desc[0].offset = 0;
+ for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4) {
+ urb->iso_frame_desc[i].length = 4;
+ urb->iso_frame_desc[i].offset = offs;
+ }
return 0;
}
@@ -446,17 +462,31 @@ static int retire_playback_sync_urb(snd_usb_substream_t *subs,
snd_pcm_runtime_t *runtime,
struct urb *urb)
{
- unsigned int f;
+ int i;
+ unsigned int f, found;
+ unsigned char *cp = urb->transfer_buffer;
unsigned long flags;
- if (urb->iso_frame_desc[0].status == 0 &&
- urb->iso_frame_desc[0].actual_length == 3) {
- f = combine_triple((u8*)urb->transfer_buffer) << 2;
- if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
- spin_lock_irqsave(&subs->lock, flags);
- subs->freqm = f;
- spin_unlock_irqrestore(&subs->lock, flags);
+ found = 0;
+ for (i = 0; i < urb->number_of_packets; i++, cp += 4) {
+ if (urb->iso_frame_desc[i].status ||
+ urb->iso_frame_desc[i].actual_length < 3)
+ continue;
+ f = combine_triple(cp) << 2;
+#if 0
+ if (f < subs->freqn - (subs->freqn>>3) || f > subs->freqmax) {
+ snd_printd(KERN_WARNING "requested frequency %d (%u,%03uHz) out of range (current nominal %d (%u,%03uHz))\n",
+ f, f >> 14, (f & ((1 << 14) - 1) * 1000) / ((1 << 14) - 1),
+ subs->freqn, subs->freqn >> 14, (subs->freqn & ((1 << 14) - 1) * 1000) / ((1 << 14) - 1));
+ continue;
}
+#endif
+ found = f;
+ }
+ if (found) {
+ spin_lock_irqsave(&subs->lock, flags);
+ subs->freqm = found;
+ spin_unlock_irqrestore(&subs->lock, flags);
}
return 0;
@@ -472,17 +502,22 @@ static int retire_playback_sync_urb_hs(snd_usb_substream_t *subs,
snd_pcm_runtime_t *runtime,
struct urb *urb)
{
- unsigned int f;
+ int i;
+ unsigned int found;
+ unsigned char *cp = urb->transfer_buffer;
unsigned long flags;
- if (urb->iso_frame_desc[0].status == 0 &&
- urb->iso_frame_desc[0].actual_length == 4) {
- f = combine_quad((u8*)urb->transfer_buffer) & 0x0fffffff;
- if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
- spin_lock_irqsave(&subs->lock, flags);
- subs->freqm = f;
- spin_unlock_irqrestore(&subs->lock, flags);
- }
+ found = 0;
+ for (i = 0; i < urb->number_of_packets; i++, cp += 4) {
+ if (urb->iso_frame_desc[i].status ||
+ urb->iso_frame_desc[i].actual_length < 4)
+ continue;
+ found = combine_quad(cp) & 0x0fffffff;
+ }
+ if (found) {
+ spin_lock_irqsave(&subs->lock, flags);
+ subs->freqm = found;
+ spin_unlock_irqrestore(&subs->lock, flags);
}
return 0;
@@ -565,8 +600,6 @@ static int prepare_playback_urb(snd_usb_substream_t *subs,
/* set the buffer pointer */
urb->transfer_buffer = runtime->dma_area + subs->hwptr * stride;
subs->hwptr += offs;
- if (subs->hwptr == runtime->buffer_size)
- subs->hwptr = 0;
}
spin_unlock_irqrestore(&subs->lock, flags);
urb->transfer_buffer_length = offs * stride;
@@ -859,8 +892,10 @@ static void release_urb_ctx(snd_urb_ctx_t *u)
usb_free_urb(u->urb);
u->urb = NULL;
}
- kfree(u->buf);
- u->buf = NULL;
+ if (u->buf) {
+ kfree(u->buf);
+ u->buf = NULL;
+ }
}
/*
@@ -878,8 +913,10 @@ static void release_substream_urbs(snd_usb_substream_t *subs, int force)
release_urb_ctx(&subs->dataurb[i]);
for (i = 0; i < SYNC_URBS; i++)
release_urb_ctx(&subs->syncurb[i]);
- kfree(subs->tmpbuf);
- subs->tmpbuf = NULL;
+ if (subs->tmpbuf) {
+ kfree(subs->tmpbuf);
+ subs->tmpbuf = NULL;
+ }
subs->nurbs = 0;
}
@@ -1002,19 +1039,22 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
snd_urb_ctx_t *u = &subs->syncurb[i];
u->index = i;
u->subs = subs;
- u->packets = 1;
- u->urb = usb_alloc_urb(1, GFP_KERNEL);
+ u->packets = nrpacks;
+ u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
if (! u->urb) {
release_substream_urbs(subs, 0);
return -ENOMEM;
}
- u->urb->transfer_buffer = subs->syncbuf + i * 4;
- u->urb->transfer_buffer_length = 4;
+ u->urb->transfer_buffer = subs->syncbuf + i * nrpacks * 4;
+ u->urb->transfer_buffer_length = nrpacks * 4;
u->urb->dev = subs->dev;
u->urb->pipe = subs->syncpipe;
u->urb->transfer_flags = URB_ISO_ASAP;
- u->urb->number_of_packets = 1;
- u->urb->interval = 1 << subs->syncinterval;
+ u->urb->number_of_packets = u->packets;
+ if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)
+ u->urb->interval = 8;
+ else
+ u->urb->interval = 1;
u->urb->context = u;
u->urb->complete = snd_usb_complete_callback(snd_complete_sync_urb);
}
@@ -1232,17 +1272,7 @@ static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt)
subs->syncpipe = usb_rcvisocpipe(dev, ep);
else
subs->syncpipe = usb_sndisocpipe(dev, ep);
- if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
- get_endpoint(alts, 1)->bRefresh >= 1 &&
- get_endpoint(alts, 1)->bRefresh <= 9)
- subs->syncinterval = get_endpoint(alts, 1)->bRefresh;
- else if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
- subs->syncinterval = 1;
- else if (get_endpoint(alts, 1)->bInterval >= 1 &&
- get_endpoint(alts, 1)->bInterval <= 16)
- subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1;
- else
- subs->syncinterval = 3;
+ subs->syncinterval = get_endpoint(alts, 1)->bRefresh;
}
/* always fill max packet size */
@@ -1960,11 +1990,10 @@ static void proc_dump_substream_status(snd_usb_substream_t *subs, snd_info_buffe
snd_iprintf(buffer, "%d ", subs->dataurb[i].packets);
snd_iprintf(buffer, "]\n");
snd_iprintf(buffer, " Packet Size = %d\n", subs->curpacksize);
- snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n",
+ snd_iprintf(buffer, " Momentary freq = %u Hz\n",
snd_usb_get_speed(subs->dev) == USB_SPEED_FULL
? get_full_speed_hz(subs->freqm)
- : get_high_speed_hz(subs->freqm),
- subs->freqm >> 16, subs->freqm & 0xffff);
+ : get_high_speed_hz(subs->freqm));
} else {
snd_iprintf(buffer, " Status: Stop\n");
}
@@ -2154,15 +2183,17 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor
/*
* check if the device uses big-endian samples
*/
-static int is_big_endian_format(snd_usb_audio_t *chip, struct audioformat *fp)
+static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp)
{
- switch (chip->usb_id) {
- case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */
- if (fp->endpoint & USB_DIR_IN)
+ /* M-Audio */
+ if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763) {
+ /* Quattro: captured data only */
+ if (le16_to_cpu(dev->descriptor.idProduct) == 0x2001 &&
+ fp->endpoint & USB_DIR_IN)
+ return 1;
+ /* Audiophile USB */
+ if (le16_to_cpu(dev->descriptor.idProduct) == 0x2003)
return 1;
- break;
- case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
- return 1;
}
return 0;
}
@@ -2176,7 +2207,7 @@ static int is_big_endian_format(snd_usb_audio_t *chip, struct audioformat *fp)
* @format: the format tag (wFormatTag)
* @fmt: the format type descriptor
*/
-static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *fp,
+static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat *fp,
int format, unsigned char *fmt)
{
int pcm_format;
@@ -2189,12 +2220,12 @@ static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *
switch (format) {
case 0: /* some devices don't define this correctly... */
snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n",
- chip->dev->devnum, fp->iface, fp->altsetting);
+ dev->devnum, fp->iface, fp->altsetting);
/* fall-through */
case USB_AUDIO_FORMAT_PCM:
if (sample_width > sample_bytes * 8) {
snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n",
- chip->dev->devnum, fp->iface, fp->altsetting,
+ dev->devnum, fp->iface, fp->altsetting,
sample_width, sample_bytes);
}
/* check the format byte size */
@@ -2203,13 +2234,13 @@ static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *
pcm_format = SNDRV_PCM_FORMAT_S8;
break;
case 2:
- if (is_big_endian_format(chip, fp))
+ if (is_big_endian_format(dev, fp))
pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */
else
pcm_format = SNDRV_PCM_FORMAT_S16_LE;
break;
case 3:
- if (is_big_endian_format(chip, fp))
+ if (is_big_endian_format(dev, fp))
pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */
else
pcm_format = SNDRV_PCM_FORMAT_S24_3LE;
@@ -2219,14 +2250,14 @@ static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *
break;
default:
snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n",
- chip->dev->devnum, fp->iface,
- fp->altsetting, sample_width, sample_bytes);
+ dev->devnum, fp->iface, fp->altsetting, sample_width, sample_bytes);
break;
}
break;
case USB_AUDIO_FORMAT_PCM8:
/* Dallas DS4201 workaround */
- if (chip->usb_id == USB_ID(0x04fa, 0x4201))
+ if (le16_to_cpu(dev->descriptor.idVendor) == 0x04fa &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x4201)
pcm_format = SNDRV_PCM_FORMAT_S8;
else
pcm_format = SNDRV_PCM_FORMAT_U8;
@@ -2242,7 +2273,7 @@ static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *
break;
default:
snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n",
- chip->dev->devnum, fp->iface, fp->altsetting, format);
+ dev->devnum, fp->iface, fp->altsetting, format);
break;
}
return pcm_format;
@@ -2259,13 +2290,13 @@ static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *
* @offset: the start offset of descriptor pointing the rate type
* (7 for type I and II, 8 for type II)
*/
-static int parse_audio_format_rates(snd_usb_audio_t *chip, struct audioformat *fp,
+static int parse_audio_format_rates(struct usb_device *dev, struct audioformat *fp,
unsigned char *fmt, int offset)
{
int nr_rates = fmt[offset];
if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
- chip->dev->devnum, fp->iface, fp->altsetting);
+ dev->devnum, fp->iface, fp->altsetting);
return -1;
}
@@ -2312,7 +2343,7 @@ static int parse_audio_format_rates(snd_usb_audio_t *chip, struct audioformat *f
/*
* parse the format type I and III descriptors
*/
-static int parse_audio_format_i(snd_usb_audio_t *chip, struct audioformat *fp,
+static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp,
int format, unsigned char *fmt)
{
int pcm_format;
@@ -2324,7 +2355,7 @@ static int parse_audio_format_i(snd_usb_audio_t *chip, struct audioformat *fp,
*/
pcm_format = SNDRV_PCM_FORMAT_S16_LE;
} else {
- pcm_format = parse_audio_format_i_type(chip, fp, format, fmt);
+ pcm_format = parse_audio_format_i_type(dev, fp, format, fmt);
if (pcm_format < 0)
return -1;
}
@@ -2332,16 +2363,16 @@ static int parse_audio_format_i(snd_usb_audio_t *chip, struct audioformat *fp,
fp->channels = fmt[4];
if (fp->channels < 1) {
snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n",
- chip->dev->devnum, fp->iface, fp->altsetting, fp->channels);
+ dev->devnum, fp->iface, fp->altsetting, fp->channels);
return -1;
}
- return parse_audio_format_rates(chip, fp, fmt, 7);
+ return parse_audio_format_rates(dev, fp, fmt, 7);
}
/*
* prase the format type II descriptor
*/
-static int parse_audio_format_ii(snd_usb_audio_t *chip, struct audioformat *fp,
+static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp,
int format, unsigned char *fmt)
{
int brate, framesize;
@@ -2356,7 +2387,7 @@ static int parse_audio_format_ii(snd_usb_audio_t *chip, struct audioformat *fp,
break;
default:
snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected. processed as MPEG.\n",
- chip->dev->devnum, fp->iface, fp->altsetting, format);
+ dev->devnum, fp->iface, fp->altsetting, format);
fp->format = SNDRV_PCM_FORMAT_MPEG;
break;
}
@@ -2365,10 +2396,10 @@ static int parse_audio_format_ii(snd_usb_audio_t *chip, struct audioformat *fp,
framesize = combine_word(&fmt[6]); /* fmt[6,7]: wSamplesPerFrame */
snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
fp->frame_size = framesize;
- return parse_audio_format_rates(chip, fp, fmt, 8); /* fmt[8..] sample rates */
+ return parse_audio_format_rates(dev, fp, fmt, 8); /* fmt[8..] sample rates */
}
-static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp,
+static int parse_audio_format(struct usb_device *dev, struct audioformat *fp,
int format, unsigned char *fmt, int stream)
{
int err;
@@ -2376,30 +2407,29 @@ static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp,
switch (fmt[3]) {
case USB_FORMAT_TYPE_I:
case USB_FORMAT_TYPE_III:
- err = parse_audio_format_i(chip, fp, format, fmt);
+ err = parse_audio_format_i(dev, fp, format, fmt);
break;
case USB_FORMAT_TYPE_II:
- err = parse_audio_format_ii(chip, fp, format, fmt);
+ err = parse_audio_format_ii(dev, fp, format, fmt);
break;
default:
snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n",
- chip->dev->devnum, fp->iface, fp->altsetting, fmt[3]);
+ dev->devnum, fp->iface, fp->altsetting, fmt[3]);
return -1;
}
fp->fmt_type = fmt[3];
if (err < 0)
return err;
#if 1
- /* FIXME: temporary hack for extigy/audigy 2 nx */
+ /* FIXME: temporary hack for extigy */
/* extigy apparently supports sample rates other than 48k
* but not in ordinary way. so we enable only 48k atm.
*/
- if (chip->usb_id == USB_ID(0x041e, 0x3000) ||
- chip->usb_id == USB_ID(0x041e, 0x3020)) {
+ if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x3000) {
if (fmt[3] == USB_FORMAT_TYPE_I &&
stream == SNDRV_PCM_STREAM_PLAYBACK &&
- fp->rates != SNDRV_PCM_RATE_48000 &&
- fp->rates != SNDRV_PCM_RATE_96000)
+ fp->rates != SNDRV_PCM_RATE_48000)
return -1; /* use 48k only */
}
#endif
@@ -2498,35 +2528,40 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
/* some quirks for attributes here */
- switch (chip->usb_id) {
- case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */
+ /* workaround for AudioTrak Optoplay */
+ if (le16_to_cpu(dev->descriptor.idVendor) == 0x0a92 &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x0053) {
/* Optoplay sets the sample rate attribute although
* it seems not supporting it in fact.
*/
fp->attributes &= ~EP_CS_ATTR_SAMPLE_RATE;
- break;
- case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
- case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
+ }
+
+ /* workaround for M-Audio Audiophile USB */
+ if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763 &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x2003) {
/* doesn't set the sample rate attribute, but supports it */
fp->attributes |= EP_CS_ATTR_SAMPLE_RATE;
- break;
- case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
- case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
- an older model 77d:223) */
+ }
+
/*
* plantronics headset and Griffin iMic have set adaptive-in
* although it's really not...
*/
+ if ((le16_to_cpu(dev->descriptor.idVendor) == 0x047f &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x0ca1) ||
+ /* Griffin iMic (note that there is an older model 77d:223) */
+ (le16_to_cpu(dev->descriptor.idVendor) == 0x077d &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x07af)) {
fp->ep_attr &= ~EP_ATTR_MASK;
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
fp->ep_attr |= EP_ATTR_ADAPTIVE;
else
fp->ep_attr |= EP_ATTR_SYNC;
- break;
}
/* ok, let's parse further... */
- if (parse_audio_format(chip, fp, format, fmt, stream) < 0) {
+ if (parse_audio_format(dev, fp, format, fmt, stream) < 0) {
kfree(fp->rate_table);
kfree(fp);
continue;
@@ -2552,7 +2587,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
* disconnect streams
* called from snd_usb_audio_disconnect()
*/
-static void snd_usb_stream_disconnect(struct list_head *head)
+static void snd_usb_stream_disconnect(struct list_head *head, struct usb_driver *driver)
{
int idx;
snd_usb_stream_t *as;
@@ -2761,7 +2796,7 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
.data = &ua25_ep
};
- if (chip->usb_id == USB_ID(0x0582, 0x002b))
+ if (le16_to_cpu(chip->dev->descriptor.idProduct) == 0x002b)
return snd_usb_create_midi_interface(chip, iface,
&ua700_quirk);
else
@@ -2924,25 +2959,6 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac
return 0;
}
-static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev)
-{
-#if 0
- /* TODO: enable this when high speed synchronization actually works */
- u8 buf = 1;
-
- snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
- 0, 0, &buf, 1, 1000);
- if (buf == 0) {
- snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0x29,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
- 1, 2000, NULL, 0, 1000);
- return -ENODEV;
- }
-#endif
- return 0;
-}
-
/*
* audio-interface quirks
@@ -2999,8 +3015,8 @@ static void proc_audio_usbid_read(snd_info_entry_t *entry, snd_info_buffer_t *bu
snd_usb_audio_t *chip = entry->private_data;
if (! chip->shutdown)
snd_iprintf(buffer, "%04x:%04x\n",
- USB_ID_VENDOR(chip->usb_id),
- USB_ID_PRODUCT(chip->usb_id));
+ le16_to_cpu(chip->dev->descriptor.idVendor),
+ le16_to_cpu(chip->dev->descriptor.idProduct));
}
static void snd_usb_audio_create_proc(snd_usb_audio_t *chip)
@@ -3070,11 +3086,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
chip->index = idx;
chip->dev = dev;
chip->card = card;
- chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct));
INIT_LIST_HEAD(&chip->pcm_list);
INIT_LIST_HEAD(&chip->midi_list);
- INIT_LIST_HEAD(&chip->mixer_list);
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
snd_usb_audio_free(chip);
@@ -3084,7 +3097,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
strcpy(card->driver, "USB-Audio");
sprintf(component, "USB%04x:%04x",
- USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id));
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
snd_component_add(card, component);
/* retrieve the device string as shortname */
@@ -3096,8 +3110,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
card->shortname, sizeof(card->shortname)) <= 0) {
/* no name available from anywhere, so use ID */
sprintf(card->shortname, "USB Device %#04x:%#04x",
- USB_ID_VENDOR(chip->usb_id),
- USB_ID_PRODUCT(chip->usb_id));
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
}
}
@@ -3128,6 +3142,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
snd_usb_audio_create_proc(chip);
+ snd_card_set_dev(card, &dev->dev);
+
*rchip = chip;
return 0;
}
@@ -3153,28 +3169,21 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
snd_usb_audio_t *chip;
struct usb_host_interface *alts;
int ifnum;
- u32 id;
alts = &intf->altsetting[0];
ifnum = get_iface_desc(alts)->bInterfaceNumber;
- id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct));
if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum)
goto __err_val;
/* SB Extigy needs special boot-up sequence */
/* if more models come, this will go to the quirk list. */
- if (id == USB_ID(0x041e, 0x3000)) {
+ if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x3000) {
if (snd_usb_extigy_boot_quirk(dev, intf) < 0)
goto __err_val;
config = dev->actconfig;
}
- /* SB Audigy 2 NX needs its own boot-up magic, too */
- if (id == USB_ID(0x041e, 0x3020)) {
- if (snd_usb_audigy2nx_boot_quirk(dev) < 0)
- goto __err_val;
- }
/*
* found a config. now register to ALSA
@@ -3204,12 +3213,11 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
}
for (i = 0; i < SNDRV_CARDS; i++)
if (enable[i] && ! usb_chip[i] &&
- (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) &&
- (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) {
+ (vid[i] == -1 || vid[i] == le16_to_cpu(dev->descriptor.idVendor)) &&
+ (pid[i] == -1 || pid[i] == le16_to_cpu(dev->descriptor.idProduct))) {
if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) {
goto __error;
}
- snd_card_set_dev(chip->card, &intf->dev);
break;
}
if (! chip) {
@@ -3273,15 +3281,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
snd_card_disconnect(card);
/* release the pcm resources */
list_for_each(p, &chip->pcm_list) {
- snd_usb_stream_disconnect(p);
+ snd_usb_stream_disconnect(p, &usb_audio_driver);
}
/* release the midi resources */
list_for_each(p, &chip->midi_list) {
- snd_usbmidi_disconnect(p);
- }
- /* release mixer resources */
- list_for_each(p, &chip->mixer_list) {
- snd_usb_mixer_disconnect(p);
+ snd_usbmidi_disconnect(p, &usb_audio_driver);
}
usb_chip[chip->index] = NULL;
up(®ister_mutex);
diff --git a/trunk/sound/usb/usbaudio.h b/trunk/sound/usb/usbaudio.h
index aedb42aaa749..eecbf19fcb6f 100644
--- a/trunk/sound/usb/usbaudio.h
+++ b/trunk/sound/usb/usbaudio.h
@@ -118,11 +118,6 @@
/* maximum number of endpoints per interface */
#define MIDI_MAX_ENDPOINTS 2
-/* handling of USB vendor/product ID pairs as 32-bit numbers */
-#define USB_ID(vendor, product) (((vendor) << 16) | (product))
-#define USB_ID_VENDOR(id) ((id) >> 16)
-#define USB_ID_PRODUCT(id) ((u16)(id))
-
/*
*/
@@ -132,7 +127,6 @@ struct snd_usb_audio {
int index;
struct usb_device *dev;
snd_card_t *card;
- u32 usb_id;
int shutdown;
int num_interfaces;
@@ -142,7 +136,7 @@ struct snd_usb_audio {
struct list_head midi_list; /* list of midi interfaces */
int next_midi_device;
- struct list_head mixer_list; /* list of mixer interfaces */
+ unsigned int ignore_ctl_error; /* for mixer */
};
/*
@@ -225,12 +219,11 @@ void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsub
int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout);
int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif);
-void snd_usb_mixer_disconnect(struct list_head *p);
int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk);
void snd_usbmidi_input_stop(struct list_head* p);
void snd_usbmidi_input_start(struct list_head* p);
-void snd_usbmidi_disconnect(struct list_head *p);
+void snd_usbmidi_disconnect(struct list_head *p, struct usb_driver *driver);
/*
* retrieve usb_interface descriptor from the host interface
diff --git a/trunk/sound/usb/usbmidi.c b/trunk/sound/usb/usbmidi.c
index bee70068dce0..5d32857ff955 100644
--- a/trunk/sound/usb/usbmidi.c
+++ b/trunk/sound/usb/usbmidi.c
@@ -912,7 +912,7 @@ static void snd_usbmidi_free(snd_usb_midi_t* umidi)
/*
* Unlinks all URBs (must be done before the usb_device is deleted).
*/
-void snd_usbmidi_disconnect(struct list_head* p)
+void snd_usbmidi_disconnect(struct list_head* p, struct usb_driver *driver)
{
snd_usb_midi_t* umidi;
int i;
@@ -955,87 +955,88 @@ static snd_rawmidi_substream_t* snd_usbmidi_find_substream(snd_usb_midi_t* umidi
* such as internal control or synthesizer ports.
*/
static struct {
- u32 id;
+ __u16 vendor;
+ __u16 product;
int port;
const char *name_format;
} snd_usbmidi_port_names[] = {
/* Roland UA-100 */
- { USB_ID(0x0582, 0x0000), 2, "%s Control" },
+ {0x0582, 0x0000, 2, "%s Control"},
/* Roland SC-8850 */
- { USB_ID(0x0582, 0x0003), 0, "%s Part A" },
- { USB_ID(0x0582, 0x0003), 1, "%s Part B" },
- { USB_ID(0x0582, 0x0003), 2, "%s Part C" },
- { USB_ID(0x0582, 0x0003), 3, "%s Part D" },
- { USB_ID(0x0582, 0x0003), 4, "%s MIDI 1" },
- { USB_ID(0x0582, 0x0003), 5, "%s MIDI 2" },
+ {0x0582, 0x0003, 0, "%s Part A"},
+ {0x0582, 0x0003, 1, "%s Part B"},
+ {0x0582, 0x0003, 2, "%s Part C"},
+ {0x0582, 0x0003, 3, "%s Part D"},
+ {0x0582, 0x0003, 4, "%s MIDI 1"},
+ {0x0582, 0x0003, 5, "%s MIDI 2"},
/* Roland U-8 */
- { USB_ID(0x0582, 0x0004), 0, "%s MIDI" },
- { USB_ID(0x0582, 0x0004), 1, "%s Control" },
+ {0x0582, 0x0004, 0, "%s MIDI"},
+ {0x0582, 0x0004, 1, "%s Control"},
/* Roland SC-8820 */
- { USB_ID(0x0582, 0x0007), 0, "%s Part A" },
- { USB_ID(0x0582, 0x0007), 1, "%s Part B" },
- { USB_ID(0x0582, 0x0007), 2, "%s MIDI" },
+ {0x0582, 0x0007, 0, "%s Part A"},
+ {0x0582, 0x0007, 1, "%s Part B"},
+ {0x0582, 0x0007, 2, "%s MIDI"},
/* Roland SK-500 */
- { USB_ID(0x0582, 0x000b), 0, "%s Part A" },
- { USB_ID(0x0582, 0x000b), 1, "%s Part B" },
- { USB_ID(0x0582, 0x000b), 2, "%s MIDI" },
+ {0x0582, 0x000b, 0, "%s Part A"},
+ {0x0582, 0x000b, 1, "%s Part B"},
+ {0x0582, 0x000b, 2, "%s MIDI"},
/* Roland SC-D70 */
- { USB_ID(0x0582, 0x000c), 0, "%s Part A" },
- { USB_ID(0x0582, 0x000c), 1, "%s Part B" },
- { USB_ID(0x0582, 0x000c), 2, "%s MIDI" },
+ {0x0582, 0x000c, 0, "%s Part A"},
+ {0x0582, 0x000c, 1, "%s Part B"},
+ {0x0582, 0x000c, 2, "%s MIDI"},
/* Edirol UM-880 */
- { USB_ID(0x0582, 0x0014), 8, "%s Control" },
+ {0x0582, 0x0014, 8, "%s Control"},
/* Edirol SD-90 */
- { USB_ID(0x0582, 0x0016), 0, "%s Part A" },
- { USB_ID(0x0582, 0x0016), 1, "%s Part B" },
- { USB_ID(0x0582, 0x0016), 2, "%s MIDI 1" },
- { USB_ID(0x0582, 0x0016), 3, "%s MIDI 2" },
+ {0x0582, 0x0016, 0, "%s Part A"},
+ {0x0582, 0x0016, 1, "%s Part B"},
+ {0x0582, 0x0016, 2, "%s MIDI 1"},
+ {0x0582, 0x0016, 3, "%s MIDI 2"},
/* Edirol UM-550 */
- { USB_ID(0x0582, 0x0023), 5, "%s Control" },
+ {0x0582, 0x0023, 5, "%s Control"},
/* Edirol SD-20 */
- { USB_ID(0x0582, 0x0027), 0, "%s Part A" },
- { USB_ID(0x0582, 0x0027), 1, "%s Part B" },
- { USB_ID(0x0582, 0x0027), 2, "%s MIDI" },
+ {0x0582, 0x0027, 0, "%s Part A"},
+ {0x0582, 0x0027, 1, "%s Part B"},
+ {0x0582, 0x0027, 2, "%s MIDI"},
/* Edirol SD-80 */
- { USB_ID(0x0582, 0x0029), 0, "%s Part A" },
- { USB_ID(0x0582, 0x0029), 1, "%s Part B" },
- { USB_ID(0x0582, 0x0029), 2, "%s MIDI 1" },
- { USB_ID(0x0582, 0x0029), 3, "%s MIDI 2" },
+ {0x0582, 0x0029, 0, "%s Part A"},
+ {0x0582, 0x0029, 1, "%s Part B"},
+ {0x0582, 0x0029, 2, "%s MIDI 1"},
+ {0x0582, 0x0029, 3, "%s MIDI 2"},
/* Edirol UA-700 */
- { USB_ID(0x0582, 0x002b), 0, "%s MIDI" },
- { USB_ID(0x0582, 0x002b), 1, "%s Control" },
+ {0x0582, 0x002b, 0, "%s MIDI"},
+ {0x0582, 0x002b, 1, "%s Control"},
/* Roland VariOS */
- { USB_ID(0x0582, 0x002f), 0, "%s MIDI" },
- { USB_ID(0x0582, 0x002f), 1, "%s External MIDI" },
- { USB_ID(0x0582, 0x002f), 2, "%s Sync" },
+ {0x0582, 0x002f, 0, "%s MIDI"},
+ {0x0582, 0x002f, 1, "%s External MIDI"},
+ {0x0582, 0x002f, 2, "%s Sync"},
/* Edirol PCR */
- { USB_ID(0x0582, 0x0033), 0, "%s MIDI" },
- { USB_ID(0x0582, 0x0033), 1, "%s 1" },
- { USB_ID(0x0582, 0x0033), 2, "%s 2" },
+ {0x0582, 0x0033, 0, "%s MIDI"},
+ {0x0582, 0x0033, 1, "%s 1"},
+ {0x0582, 0x0033, 2, "%s 2"},
/* BOSS GS-10 */
- { USB_ID(0x0582, 0x003b), 0, "%s MIDI" },
- { USB_ID(0x0582, 0x003b), 1, "%s Control" },
+ {0x0582, 0x003b, 0, "%s MIDI"},
+ {0x0582, 0x003b, 1, "%s Control"},
/* Edirol UA-1000 */
- { USB_ID(0x0582, 0x0044), 0, "%s MIDI" },
- { USB_ID(0x0582, 0x0044), 1, "%s Control" },
+ {0x0582, 0x0044, 0, "%s MIDI"},
+ {0x0582, 0x0044, 1, "%s Control"},
/* Edirol UR-80 */
- { USB_ID(0x0582, 0x0048), 0, "%s MIDI" },
- { USB_ID(0x0582, 0x0048), 1, "%s 1" },
- { USB_ID(0x0582, 0x0048), 2, "%s 2" },
+ {0x0582, 0x0048, 0, "%s MIDI"},
+ {0x0582, 0x0048, 1, "%s 1"},
+ {0x0582, 0x0048, 2, "%s 2"},
/* Edirol PCR-A */
- { USB_ID(0x0582, 0x004d), 0, "%s MIDI" },
- { USB_ID(0x0582, 0x004d), 1, "%s 1" },
- { USB_ID(0x0582, 0x004d), 2, "%s 2" },
+ {0x0582, 0x004d, 0, "%s MIDI"},
+ {0x0582, 0x004d, 1, "%s 1"},
+ {0x0582, 0x004d, 2, "%s 2"},
/* M-Audio MidiSport 8x8 */
- { USB_ID(0x0763, 0x1031), 8, "%s Control" },
- { USB_ID(0x0763, 0x1033), 8, "%s Control" },
+ {0x0763, 0x1031, 8, "%s Control"},
+ {0x0763, 0x1033, 8, "%s Control"},
/* MOTU Fastlane */
- { USB_ID(0x07fd, 0x0001), 0, "%s MIDI A" },
- { USB_ID(0x07fd, 0x0001), 1, "%s MIDI B" },
+ {0x07fd, 0x0001, 0, "%s MIDI A"},
+ {0x07fd, 0x0001, 1, "%s MIDI B"},
/* Emagic Unitor8/AMT8/MT4 */
- { USB_ID(0x086a, 0x0001), 8, "%s Broadcast" },
- { USB_ID(0x086a, 0x0002), 8, "%s Broadcast" },
- { USB_ID(0x086a, 0x0003), 4, "%s Broadcast" },
+ {0x086a, 0x0001, 8, "%s Broadcast"},
+ {0x086a, 0x0002, 8, "%s Broadcast"},
+ {0x086a, 0x0003, 4, "%s Broadcast"},
};
static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
@@ -1043,6 +1044,7 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
snd_rawmidi_substream_t** rsubstream)
{
int i;
+ __u16 vendor, product;
const char *name_format;
snd_rawmidi_substream_t* substream = snd_usbmidi_find_substream(umidi, stream, number);
@@ -1053,8 +1055,11 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
/* TODO: read port name from jack descriptor */
name_format = "%s MIDI %d";
+ vendor = le16_to_cpu(umidi->chip->dev->descriptor.idVendor);
+ product = le16_to_cpu(umidi->chip->dev->descriptor.idProduct);
for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) {
- if (snd_usbmidi_port_names[i].id == umidi->chip->usb_id &&
+ if (snd_usbmidi_port_names[i].vendor == vendor &&
+ snd_usbmidi_port_names[i].product == product &&
snd_usbmidi_port_names[i].port == number) {
name_format = snd_usbmidi_port_names[i].name_format;
break;
@@ -1221,12 +1226,9 @@ static int snd_usbmidi_detect_endpoints(snd_usb_midi_t* umidi,
struct usb_endpoint_descriptor* epd;
int i, out_eps = 0, in_eps = 0;
- if (USB_ID_VENDOR(umidi->chip->usb_id) == 0x0582)
+ if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) == 0x0582)
snd_usbmidi_switch_roland_altsetting(umidi);
- if (endpoint[0].out_ep || endpoint[0].in_ep)
- return 0;
-
intf = umidi->iface;
if (!intf || intf->num_altsetting < 1)
return -ENOENT;
diff --git a/trunk/sound/usb/usbmixer.c b/trunk/sound/usb/usbmixer.c
index e73c1c9d3e73..5f1906915aa6 100644
--- a/trunk/sound/usb/usbmixer.c
+++ b/trunk/sound/usb/usbmixer.c
@@ -35,11 +35,10 @@
#include
#include
#include
-#include
-#include
#include "usbaudio.h"
+
/*
*/
@@ -51,31 +50,6 @@ typedef struct usb_audio_term usb_audio_term_t;
typedef struct usb_mixer_elem_info usb_mixer_elem_info_t;
-struct usb_mixer_interface {
- snd_usb_audio_t *chip;
- unsigned int ctrlif;
- struct list_head list;
- unsigned int ignore_ctl_error;
- struct urb *urb;
- usb_mixer_elem_info_t **id_elems; /* array[256], indexed by unit id */
-
- /* Sound Blaster remote control stuff */
- enum {
- RC_NONE,
- RC_EXTIGY,
- RC_AUDIGY2NX,
- } rc_type;
- unsigned long rc_hwdep_open;
- u32 rc_code;
- wait_queue_head_t rc_waitq;
- struct urb *rc_urb;
- struct usb_ctrlrequest *rc_setup_packet;
- u8 rc_buffer[6];
-
- u8 audigy2nx_leds[3];
-};
-
-
struct usb_audio_term {
int id;
int type;
@@ -88,26 +62,26 @@ struct usbmix_name_map;
struct usb_mixer_build {
snd_usb_audio_t *chip;
- struct usb_mixer_interface *mixer;
unsigned char *buffer;
unsigned int buflen;
- DECLARE_BITMAP(unitbitmap, 256);
+ unsigned int ctrlif;
+ unsigned short vendor;
+ unsigned short product;
+ DECLARE_BITMAP(unitbitmap, 32*32);
usb_audio_term_t oterm;
const struct usbmix_name_map *map;
- const struct usbmix_selector_map *selector_map;
};
struct usb_mixer_elem_info {
- struct usb_mixer_interface *mixer;
- usb_mixer_elem_info_t *next_id_elem; /* list of controls with same id */
- snd_ctl_elem_id_t *elem_id;
+ snd_usb_audio_t *chip;
+ unsigned int ctrlif;
unsigned int id;
unsigned int control; /* CS or ICN (high byte) */
unsigned int cmask; /* channel mask bitmap: 0 = master */
int channels;
int val_type;
int min, max, res;
- u8 initialized;
+ unsigned int initialized: 1;
};
@@ -213,21 +187,6 @@ static int check_ignored_ctl(mixer_build_t *state, int unitid, int control)
return 0;
}
-/* get the mapped selector source name */
-static int check_mapped_selector_name(mixer_build_t *state, int unitid,
- int index, char *buf, int buflen)
-{
- const struct usbmix_selector_map *p;
-
- if (! state->selector_map)
- return 0;
- for (p = state->selector_map; p->id; p++) {
- if (p->id == unitid && index < p->count)
- return strlcpy(buf, p->names[index], buflen);
- }
- return 0;
-}
-
/*
* find an audio control unit with the given unit id
*/
@@ -342,18 +301,16 @@ static int get_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
int timeout = 10;
while (timeout-- > 0) {
- if (snd_usb_ctl_msg(cval->mixer->chip->dev,
- usb_rcvctrlpipe(cval->mixer->chip->dev, 0),
+ if (snd_usb_ctl_msg(cval->chip->dev, usb_rcvctrlpipe(cval->chip->dev, 0),
request,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- validx, cval->mixer->ctrlif | (cval->id << 8),
+ validx, cval->ctrlif | (cval->id << 8),
buf, val_len, 100) >= 0) {
*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
return 0;
}
}
- snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
- request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type);
+ snd_printdd(KERN_ERR "cannot get ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type);
return -EINVAL;
}
@@ -382,15 +339,13 @@ static int set_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
buf[0] = value_set & 0xff;
buf[1] = (value_set >> 8) & 0xff;
while (timeout -- > 0)
- if (snd_usb_ctl_msg(cval->mixer->chip->dev,
- usb_sndctrlpipe(cval->mixer->chip->dev, 0),
+ if (snd_usb_ctl_msg(cval->chip->dev, usb_sndctrlpipe(cval->chip->dev, 0),
request,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
- validx, cval->mixer->ctrlif | (cval->id << 8),
+ validx, cval->ctrlif | (cval->id << 8),
buf, val_len, 100) >= 0)
return 0;
- snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
- request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]);
+ snd_printdd(KERN_ERR "cannot set ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d, data = 0x%x/0x%x\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]);
return -EINVAL;
}
@@ -430,22 +385,16 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou
* if failed, give up and free the control instance.
*/
-static int add_control_to_empty(mixer_build_t *state, snd_kcontrol_t *kctl)
+static int add_control_to_empty(snd_card_t *card, snd_kcontrol_t *kctl)
{
- usb_mixer_elem_info_t *cval = kctl->private_data;
int err;
-
- while (snd_ctl_find_id(state->chip->card, &kctl->id))
+ while (snd_ctl_find_id(card, &kctl->id))
kctl->id.index++;
- if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) {
+ if ((err = snd_ctl_add(card, kctl)) < 0) {
snd_printd(KERN_ERR "cannot add control (err = %d)\n", err);
snd_ctl_free_one(kctl);
- return err;
}
- cval->elem_id = &kctl->id;
- cval->next_id_elem = state->mixer->id_elems[cval->id];
- state->mixer->id_elems[cval->id] = cval;
- return 0;
+ return err;
}
@@ -623,8 +572,10 @@ static struct usb_feature_control_info audio_feature_info[] = {
/* private_free callback */
static void usb_mixer_elem_free(snd_kcontrol_t *kctl)
{
- kfree(kctl->private_data);
- kctl->private_data = NULL;
+ if (kctl->private_data) {
+ kfree(kctl->private_data);
+ kctl->private_data = NULL;
+ }
}
@@ -657,8 +608,7 @@ static int get_min_max(usb_mixer_elem_info_t *cval, int default_min)
}
if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
- snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n",
- cval->id, cval->mixer->ctrlif, cval->control, cval->id);
+ snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", cval->id, cval->ctrlif, cval->control, cval->id);
return -EINVAL;
}
if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) {
@@ -718,7 +668,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
if (cval->cmask & (1 << c)) {
err = get_cur_mix_value(cval, c + 1, &val);
if (err < 0) {
- if (cval->mixer->ignore_ctl_error) {
+ if (cval->chip->ignore_ctl_error) {
ucontrol->value.integer.value[0] = cval->min;
return 0;
}
@@ -734,7 +684,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
/* master channel */
err = get_cur_mix_value(cval, 0, &val);
if (err < 0) {
- if (cval->mixer->ignore_ctl_error) {
+ if (cval->chip->ignore_ctl_error) {
ucontrol->value.integer.value[0] = cval->min;
return 0;
}
@@ -760,7 +710,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
if (cval->cmask & (1 << c)) {
err = get_cur_mix_value(cval, c + 1, &oval);
if (err < 0) {
- if (cval->mixer->ignore_ctl_error)
+ if (cval->chip->ignore_ctl_error)
return 0;
return err;
}
@@ -777,7 +727,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
} else {
/* master channel */
err = get_cur_mix_value(cval, 0, &oval);
- if (err < 0 && cval->mixer->ignore_ctl_error)
+ if (err < 0 && cval->chip->ignore_ctl_error)
return 0;
if (err < 0)
return err;
@@ -829,7 +779,8 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return;
}
- cval->mixer = state->mixer;
+ cval->chip = state->chip;
+ cval->ctrlif = state->ctrlif;
cval->id = unitid;
cval->control = control;
cval->cmask = ctl_mask;
@@ -904,21 +855,16 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
/* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */
/* is not very clear from datasheets */
/* I hope that the min value is -15360 for newer firmware --jk */
- switch (state->chip->usb_id) {
- case USB_ID(0x0471, 0x0101):
- case USB_ID(0x0471, 0x0104):
- case USB_ID(0x0471, 0x0105):
- case USB_ID(0x0672, 0x1041):
- if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
- cval->min == -15616) {
- snd_printk("using volume control quirk for the UDA1321/N101 chip\n");
- cval->max = -256;
- }
+ if (((state->vendor == 0x471 && (state->product == 0x104 || state->product == 0x105 || state->product == 0x101)) ||
+ (state->vendor == 0x672 && state->product == 0x1041)) && !strcmp(kctl->id.name, "PCM Playback Volume") &&
+ cval->min == -15616) {
+ snd_printk("USB Audio: using volume control quirk for the UDA1321/N101 chip\n");
+ cval->max = -256;
}
snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
- add_control_to_empty(state, kctl);
+ add_control_to_empty(state->chip->card, kctl);
}
@@ -1001,7 +947,8 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
if (! cval)
return;
- cval->mixer = state->mixer;
+ cval->chip = state->chip;
+ cval->ctrlif = state->ctrlif;
cval->id = unitid;
cval->control = in_ch + 1; /* based on 1 */
cval->val_type = USB_MIXER_S16;
@@ -1032,7 +979,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n",
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
- add_control_to_empty(state, kctl);
+ add_control_to_empty(state->chip->card, kctl);
}
@@ -1095,7 +1042,7 @@ static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
int err, val;
err = get_cur_ctl_value(cval, cval->control << 8, &val);
- if (err < 0 && cval->mixer->ignore_ctl_error) {
+ if (err < 0 && cval->chip->ignore_ctl_error) {
ucontrol->value.integer.value[0] = cval->min;
return 0;
}
@@ -1114,7 +1061,7 @@ static int mixer_ctl_procunit_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
err = get_cur_ctl_value(cval, cval->control << 8, &oval);
if (err < 0) {
- if (cval->mixer->ignore_ctl_error)
+ if (cval->chip->ignore_ctl_error)
return 0;
return err;
}
@@ -1232,6 +1179,9 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
}
type = combine_word(&dsc[4]);
+ if (! type)
+ return 0; /* undefined? */
+
for (info = list; info && info->type; info++)
if (info->type == type)
break;
@@ -1249,7 +1199,8 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return -ENOMEM;
}
- cval->mixer = state->mixer;
+ cval->chip = state->chip;
+ cval->ctrlif = state->ctrlif;
cval->id = unitid;
cval->control = valinfo->control;
cval->val_type = valinfo->val_type;
@@ -1290,7 +1241,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n",
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
- if ((err = add_control_to_empty(state, kctl)) < 0)
+ if ((err = add_control_to_empty(state->chip->card, kctl)) < 0)
return err;
}
return 0;
@@ -1338,7 +1289,7 @@ static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
err = get_cur_ctl_value(cval, 0, &val);
if (err < 0) {
- if (cval->mixer->ignore_ctl_error) {
+ if (cval->chip->ignore_ctl_error) {
ucontrol->value.enumerated.item[0] = 0;
return 0;
}
@@ -1357,7 +1308,7 @@ static int mixer_ctl_selector_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
err = get_cur_ctl_value(cval, 0, &oval);
if (err < 0) {
- if (cval->mixer->ignore_ctl_error)
+ if (cval->chip->ignore_ctl_error)
return 0;
return err;
}
@@ -1435,7 +1386,8 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return -ENOMEM;
}
- cval->mixer = state->mixer;
+ cval->chip = state->chip;
+ cval->ctrlif = state->ctrlif;
cval->id = unitid;
cval->val_type = USB_MIXER_U8;
cval->channels = 1;
@@ -1463,9 +1415,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
kfree(cval);
return -ENOMEM;
}
- len = check_mapped_selector_name(state, unitid, i, namelist[i],
- MAX_ITEM_NAME_LEN);
- if (! len && check_input_term(state, desc[5 + i], &iterm) >= 0)
+ if (check_input_term(state, desc[5 + i], &iterm) >= 0)
len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0);
if (! len)
sprintf(namelist[i], "Input %d", i);
@@ -1500,7 +1450,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
cval->id, kctl->id.name, num_ins);
- if ((err = add_control_to_empty(state, kctl)) < 0)
+ if ((err = add_control_to_empty(state->chip->card, kctl)) < 0)
return err;
return 0;
@@ -1543,55 +1493,41 @@ static int parse_audio_unit(mixer_build_t *state, int unitid)
}
}
-static void snd_usb_mixer_free(struct usb_mixer_interface *mixer)
-{
- kfree(mixer->id_elems);
- if (mixer->urb) {
- kfree(mixer->urb->transfer_buffer);
- usb_free_urb(mixer->urb);
- }
- if (mixer->rc_urb)
- usb_free_urb(mixer->rc_urb);
- kfree(mixer->rc_setup_packet);
- kfree(mixer);
-}
-
-static int snd_usb_mixer_dev_free(snd_device_t *device)
-{
- struct usb_mixer_interface *mixer = device->device_data;
- snd_usb_mixer_free(mixer);
- return 0;
-}
-
/*
* create mixer controls
*
* walk through all OUTPUT_TERMINAL descriptors to search for mixers
*/
-static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
+int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
{
unsigned char *desc;
mixer_build_t state;
int err;
const struct usbmix_ctl_map *map;
- struct usb_host_interface *hostif;
+ struct usb_device_descriptor *dev = &chip->dev->descriptor;
+ struct usb_host_interface *hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0];
+
+ strcpy(chip->card->mixername, "USB Mixer");
- hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0];
memset(&state, 0, sizeof(state));
- state.chip = mixer->chip;
- state.mixer = mixer;
+ state.chip = chip;
state.buffer = hostif->extra;
state.buflen = hostif->extralen;
+ state.ctrlif = ctrlif;
+ state.vendor = le16_to_cpu(dev->idVendor);
+ state.product = le16_to_cpu(dev->idProduct);
/* check the mapping table */
- for (map = usbmix_ctl_maps; map->id; map++) {
- if (map->id == state.chip->usb_id) {
+ for (map = usbmix_ctl_maps; map->vendor; map++) {
+ if (map->vendor == state.vendor && map->product == state.product) {
state.map = map->map;
- state.selector_map = map->selector_map;
- mixer->ignore_ctl_error = map->ignore_ctl_error;
+ chip->ignore_ctl_error = map->ignore_ctl_error;
break;
}
}
+#ifdef IGNORE_CTL_ERROR
+ chip->ignore_ctl_error = 1;
+#endif
desc = NULL;
while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) {
@@ -1607,393 +1543,3 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
}
return 0;
}
-
-static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer,
- int unitid)
-{
- usb_mixer_elem_info_t *info;
-
- for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem)
- snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
- info->elem_id);
-}
-
-static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
- int unitid)
-{
- if (mixer->rc_type == RC_NONE)
- return;
- /* unit ids specific to Extigy/Audigy 2 NX: */
- switch (unitid) {
- case 0: /* remote control */
- mixer->rc_urb->dev = mixer->chip->dev;
- usb_submit_urb(mixer->rc_urb, GFP_ATOMIC);
- break;
- case 4: /* digital in jack */
- case 7: /* line in jacks */
- case 19: /* speaker out jacks */
- case 20: /* headphones out jack */
- break;
- default:
- snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid);
- break;
- }
-}
-
-static void snd_usb_mixer_status_complete(struct urb *urb, struct pt_regs *regs)
-{
- struct usb_mixer_interface *mixer = urb->context;
-
- if (urb->status == 0) {
- u8 *buf = urb->transfer_buffer;
- int i;
-
- for (i = urb->actual_length; i >= 2; buf += 2, i -= 2) {
- snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n",
- buf[0], buf[1]);
- /* ignore any notifications not from the control interface */
- if ((buf[0] & 0x0f) != 0)
- continue;
- if (!(buf[0] & 0x40))
- snd_usb_mixer_notify_id(mixer, buf[1]);
- else
- snd_usb_mixer_memory_change(mixer, buf[1]);
- }
- }
- if (urb->status != -ENOENT && urb->status != -ECONNRESET) {
- urb->dev = mixer->chip->dev;
- usb_submit_urb(urb, GFP_ATOMIC);
- }
-}
-
-/* create the handler for the optional status interrupt endpoint */
-static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
-{
- struct usb_host_interface *hostif;
- struct usb_endpoint_descriptor *ep;
- void *transfer_buffer;
- int buffer_length;
- unsigned int epnum;
-
- hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0];
- /* we need one interrupt input endpoint */
- if (get_iface_desc(hostif)->bNumEndpoints < 1)
- return 0;
- ep = get_endpoint(hostif, 0);
- if ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN ||
- (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
- return 0;
-
- epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
- buffer_length = le16_to_cpu(ep->wMaxPacketSize);
- transfer_buffer = kmalloc(buffer_length, GFP_KERNEL);
- if (!transfer_buffer)
- return -ENOMEM;
- mixer->urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!mixer->urb) {
- kfree(transfer_buffer);
- return -ENOMEM;
- }
- usb_fill_int_urb(mixer->urb, mixer->chip->dev,
- usb_rcvintpipe(mixer->chip->dev, epnum),
- transfer_buffer, buffer_length,
- snd_usb_mixer_status_complete, mixer, ep->bInterval);
- usb_submit_urb(mixer->urb, GFP_KERNEL);
- return 0;
-}
-
-static void snd_usb_soundblaster_remote_complete(struct urb *urb,
- struct pt_regs *regs)
-{
- struct usb_mixer_interface *mixer = urb->context;
- /*
- * format of remote control data:
- * Extigy: xx 00
- * Audigy 2 NX: 06 80 xx 00 00 00
- */
- int offset = mixer->rc_type == RC_EXTIGY ? 0 : 2;
- u32 code;
-
- if (urb->status < 0 || urb->actual_length <= offset)
- return;
- code = mixer->rc_buffer[offset];
- /* the Mute button actually changes the mixer control */
- if (code == 13)
- snd_usb_mixer_notify_id(mixer, 18);
- mixer->rc_code = code;
- wmb();
- wake_up(&mixer->rc_waitq);
-}
-
-static int snd_usb_sbrc_hwdep_open(snd_hwdep_t *hw, struct file *file)
-{
- struct usb_mixer_interface *mixer = hw->private_data;
-
- if (test_and_set_bit(0, &mixer->rc_hwdep_open))
- return -EBUSY;
- return 0;
-}
-
-static int snd_usb_sbrc_hwdep_release(snd_hwdep_t *hw, struct file *file)
-{
- struct usb_mixer_interface *mixer = hw->private_data;
-
- clear_bit(0, &mixer->rc_hwdep_open);
- smp_mb__after_clear_bit();
- return 0;
-}
-
-static long snd_usb_sbrc_hwdep_read(snd_hwdep_t *hw, char __user *buf,
- long count, loff_t *offset)
-{
- struct usb_mixer_interface *mixer = hw->private_data;
- int err;
- u32 rc_code;
-
- if (count != 1 && count != 4)
- return -EINVAL;
- err = wait_event_interruptible(mixer->rc_waitq,
- (rc_code = xchg(&mixer->rc_code, 0)) != 0);
- if (err == 0) {
- if (count == 1)
- err = put_user(rc_code, buf);
- else
- err = put_user(rc_code, (u32 __user *)buf);
- }
- return err < 0 ? err : count;
-}
-
-static unsigned int snd_usb_sbrc_hwdep_poll(snd_hwdep_t *hw, struct file *file,
- poll_table *wait)
-{
- struct usb_mixer_interface *mixer = hw->private_data;
-
- poll_wait(file, &mixer->rc_waitq, wait);
- return mixer->rc_code ? POLLIN | POLLRDNORM : 0;
-}
-
-static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
-{
- snd_hwdep_t *hwdep;
- int err, len;
-
- switch (mixer->chip->usb_id) {
- case USB_ID(0x041e, 0x3000):
- mixer->rc_type = RC_EXTIGY;
- len = 2;
- break;
- case USB_ID(0x041e, 0x3020):
- mixer->rc_type = RC_AUDIGY2NX;
- len = 6;
- break;
- default:
- return 0;
- }
-
- init_waitqueue_head(&mixer->rc_waitq);
- err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
- if (err < 0)
- return err;
- snprintf(hwdep->name, sizeof(hwdep->name),
- "%s remote control", mixer->chip->card->shortname);
- hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC;
- hwdep->private_data = mixer;
- hwdep->ops.read = snd_usb_sbrc_hwdep_read;
- hwdep->ops.open = snd_usb_sbrc_hwdep_open;
- hwdep->ops.release = snd_usb_sbrc_hwdep_release;
- hwdep->ops.poll = snd_usb_sbrc_hwdep_poll;
-
- mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!mixer->rc_urb)
- return -ENOMEM;
- mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL);
- if (!mixer->rc_setup_packet) {
- usb_free_urb(mixer->rc_urb);
- mixer->rc_urb = NULL;
- return -ENOMEM;
- }
- mixer->rc_setup_packet->bRequestType =
- USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
- mixer->rc_setup_packet->bRequest = GET_MEM;
- mixer->rc_setup_packet->wValue = cpu_to_le16(0);
- mixer->rc_setup_packet->wIndex = cpu_to_le16(0);
- mixer->rc_setup_packet->wLength = cpu_to_le16(len);
- usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev,
- usb_rcvctrlpipe(mixer->chip->dev, 0),
- (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len,
- snd_usb_soundblaster_remote_complete, mixer);
- return 0;
-}
-
-static int snd_audigy2nx_led_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
-static int snd_audigy2nx_led_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
- int index = kcontrol->private_value;
-
- ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index];
- return 0;
-}
-
-static int snd_audigy2nx_led_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
- int index = kcontrol->private_value;
- int value = ucontrol->value.integer.value[0];
- int err, changed;
-
- if (value > 1)
- return -EINVAL;
- changed = value != mixer->audigy2nx_leds[index];
- err = snd_usb_ctl_msg(mixer->chip->dev,
- usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
- value, index + 2, NULL, 0, 100);
- if (err < 0)
- return err;
- mixer->audigy2nx_leds[index] = value;
- return changed;
-}
-
-static snd_kcontrol_new_t snd_audigy2nx_controls[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "CMSS LED Switch",
- .info = snd_audigy2nx_led_info,
- .get = snd_audigy2nx_led_get,
- .put = snd_audigy2nx_led_put,
- .private_value = 0,
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Power LED Switch",
- .info = snd_audigy2nx_led_info,
- .get = snd_audigy2nx_led_get,
- .put = snd_audigy2nx_led_put,
- .private_value = 1,
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Dolby Digital LED Switch",
- .info = snd_audigy2nx_led_info,
- .get = snd_audigy2nx_led_get,
- .put = snd_audigy2nx_led_put,
- .private_value = 2,
- },
-};
-
-static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
-{
- int i, err;
-
- for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
- err = snd_ctl_add(mixer->chip->card,
- snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
- if (err < 0)
- return err;
- }
- mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */
- return 0;
-}
-
-static void snd_audigy2nx_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t *buffer)
-{
- static const struct {
- int unitid;
- const char *name;
- } jacks[] = {
- {4, "dig in "},
- {7, "line in"},
- {19, "spk out"},
- {20, "hph out"},
- };
- struct usb_mixer_interface *mixer = entry->private_data;
- int i, err;
- u8 buf[3];
-
- snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
- for (i = 0; i < ARRAY_SIZE(jacks); ++i) {
- snd_iprintf(buffer, "%s: ", jacks[i].name);
- err = snd_usb_ctl_msg(mixer->chip->dev,
- usb_rcvctrlpipe(mixer->chip->dev, 0),
- GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
- USB_RECIP_INTERFACE, 0,
- jacks[i].unitid << 8, buf, 3, 100);
- if (err == 3 && buf[0] == 3)
- snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
- else
- snd_iprintf(buffer, "?\n");
- }
-}
-
-int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
-{
- static snd_device_ops_t dev_ops = {
- .dev_free = snd_usb_mixer_dev_free
- };
- struct usb_mixer_interface *mixer;
- int err;
-
- strcpy(chip->card->mixername, "USB Mixer");
-
- mixer = kcalloc(1, sizeof(*mixer), GFP_KERNEL);
- if (!mixer)
- return -ENOMEM;
- mixer->chip = chip;
- mixer->ctrlif = ctrlif;
-#ifdef IGNORE_CTL_ERROR
- mixer->ignore_ctl_error = 1;
-#endif
- mixer->id_elems = kcalloc(256, sizeof(*mixer->id_elems), GFP_KERNEL);
- if (!mixer->id_elems) {
- kfree(mixer);
- return -ENOMEM;
- }
-
- if ((err = snd_usb_mixer_controls(mixer)) < 0 ||
- (err = snd_usb_mixer_status_create(mixer)) < 0)
- goto _error;
-
- if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
- goto _error;
-
- if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) {
- snd_info_entry_t *entry;
-
- if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
- goto _error;
- if (!snd_card_proc_new(chip->card, "audigy2nx", &entry))
- snd_info_set_text_ops(entry, mixer, 1024,
- snd_audigy2nx_proc_read);
- }
-
- err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops);
- if (err < 0)
- goto _error;
- list_add(&mixer->list, &chip->mixer_list);
- return 0;
-
-_error:
- snd_usb_mixer_free(mixer);
- return err;
-}
-
-void snd_usb_mixer_disconnect(struct list_head *p)
-{
- struct usb_mixer_interface *mixer;
-
- mixer = list_entry(p, struct usb_mixer_interface, list);
- if (mixer->urb)
- usb_kill_urb(mixer->urb);
- if (mixer->rc_urb)
- usb_kill_urb(mixer->rc_urb);
-}
diff --git a/trunk/sound/usb/usbmixer_maps.c b/trunk/sound/usb/usbmixer_maps.c
index f05500b05ec0..c69b4b0875f8 100644
--- a/trunk/sound/usb/usbmixer_maps.c
+++ b/trunk/sound/usb/usbmixer_maps.c
@@ -26,16 +26,10 @@ struct usbmix_name_map {
int control;
};
-struct usbmix_selector_map {
- int id;
- int count;
- const char **names;
-};
-
struct usbmix_ctl_map {
- u32 id;
+ int vendor;
+ int product;
const struct usbmix_name_map *map;
- const struct usbmix_selector_map *selector_map;
int ignore_ctl_error;
};
@@ -97,96 +91,6 @@ static struct usbmix_name_map extigy_map[] = {
{ 0 } /* terminator */
};
-/* Sound Blaster MP3+ controls mapping
- * The default mixer channels have totally misleading names,
- * e.g. no Master and fake PCM volume
- * Pavel Mihaylov
- */
-static struct usbmix_name_map mp3plus_map[] = {
- /* 1: IT pcm */
- /* 2: IT mic */
- /* 3: IT line */
- /* 4: IT digital in */
- /* 5: OT digital out */
- /* 6: OT speaker */
- /* 7: OT pcm capture */
- { 8, "Capture Input Source" }, /* FU, default PCM Capture Source */
- /* (Mic, Input 1 = Line input, Input 2 = Optical input) */
- { 9, "Master Playback" }, /* FU, default Speaker 1 */
- /* { 10, "Mic Capture", 1 }, */ /* FU, Mic Capture */
- /* { 10, "Mic Capture", 2 }, */ /* FU, Mic Capture */
- { 10, "Mic Boost", 7 }, /* FU, default Auto Gain Input */
- { 11, "Line Capture" }, /* FU, default PCM Capture */
- { 12, "Digital In Playback" }, /* FU, default PCM 1 */
- /* { 13, "Mic Playback" }, */ /* FU, default Mic Playback */
- { 14, "Line Playback" }, /* FU, default Speaker */
- /* 15: MU */
- { 0 } /* terminator */
-};
-
-/* Topology of SB Audigy 2 NX
-
- +----------------------------->EU[27]--+
- | v
- | +----------------------------------->SU[29]---->FU[22]-->Dig_OUT[24]
- | | ^
-USB_IN[1]-+------------+ +->EU[17]->+->FU[11]-+
- | v | v |
-Dig_IN[4]---+->FU[6]-->MU[16]->FU[18]-+->EU[21]->SU[31]----->FU[30]->Hph_OUT[20]
- | ^ | |
-Lin_IN[7]-+--->FU[8]---+ +->EU[23]->FU[28]------------->Spk_OUT[19]
- | | v
- +--->FU[12]------------------------------------->SU[14]--->USB_OUT[15]
- | ^
- +->FU[13]--------------------------------------+
-*/
-static struct usbmix_name_map audigy2nx_map[] = {
- /* 1: IT pcm playback */
- /* 4: IT digital in */
- { 6, "Digital In Playback" }, /* FU */
- /* 7: IT line in */
- { 8, "Line Playback" }, /* FU */
- { 11, "What-U-Hear Capture" }, /* FU */
- { 12, "Line Capture" }, /* FU */
- { 13, "Digital In Capture" }, /* FU */
- { 14, "Capture Source" }, /* SU */
- /* 15: OT pcm capture */
- /* 16: MU w/o controls */
- { 17, NULL }, /* DISABLED: EU (for what?) */
- { 18, "Master Playback" }, /* FU */
- /* 19: OT speaker */
- /* 20: OT headphone */
- { 21, NULL }, /* DISABLED: EU (for what?) */
- { 22, "Digital Out Playback" }, /* FU */
- { 23, NULL }, /* DISABLED: EU (for what?) */
- /* 24: OT digital out */
- { 27, NULL }, /* DISABLED: EU (for what?) */
- { 28, "Speaker Playback" }, /* FU */
- { 29, "Digital Out Source" }, /* SU */
- { 30, "Headphone Playback" }, /* FU */
- { 31, "Headphone Source" }, /* SU */
- { 0 } /* terminator */
-};
-
-static struct usbmix_selector_map audigy2nx_selectors[] = {
- {
- .id = 14, /* Capture Source */
- .count = 3,
- .names = (const char*[]) {"Line", "Digital In", "What-U-Hear"}
- },
- {
- .id = 29, /* Digital Out Source */
- .count = 3,
- .names = (const char*[]) {"Front", "PCM", "Digital In"}
- },
- {
- .id = 31, /* Headphone Source */
- .count = 2,
- .names = (const char*[]) {"Front", "Side"}
- },
- { 0 } /* terminator */
-};
-
/* LineX FM Transmitter entry - needed to bypass controls bug */
static struct usbmix_name_map linex_map[] = {
/* 1: IT pcm */
@@ -223,29 +127,9 @@ static struct usbmix_name_map justlink_map[] = {
*/
static struct usbmix_ctl_map usbmix_ctl_maps[] = {
- {
- .id = USB_ID(0x041e, 0x3000),
- .map = extigy_map,
- .ignore_ctl_error = 1,
- },
- {
- .id = USB_ID(0x041e, 0x3010),
- .map = mp3plus_map,
- },
- {
- .id = USB_ID(0x041e, 0x3020),
- .map = audigy2nx_map,
- .selector_map = audigy2nx_selectors,
- },
- {
- .id = USB_ID(0x08bb, 0x2702),
- .map = linex_map,
- .ignore_ctl_error = 1,
- },
- {
- .id = USB_ID(0x0c45, 0x1158),
- .map = justlink_map,
- },
+ { 0x41e, 0x3000, extigy_map, 1 },
+ { 0x8bb, 0x2702, linex_map, 1 },
+ { 0xc45, 0x1158, justlink_map, 0 },
{ 0 } /* terminator */
};
diff --git a/trunk/sound/usb/usbquirks.h b/trunk/sound/usb/usbquirks.h
index f5135641b3e2..88bbd944d4be 100644
--- a/trunk/sound/usb/usbquirks.h
+++ b/trunk/sound/usb/usbquirks.h
@@ -203,28 +203,11 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "UM-4",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
- {
- .ifnum = 0,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 1,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x000f,
- .in_cables = 0x000f
- }
- },
- {
- .ifnum = -1
- }
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x000f,
+ .in_cables = 0x000f
}
}
},
@@ -233,28 +216,11 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "SC-8850",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
- {
- .ifnum = 0,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 1,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x003f,
- .in_cables = 0x003f
- }
- },
- {
- .ifnum = -1
- }
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x003f,
+ .in_cables = 0x003f
}
}
},
@@ -263,28 +229,11 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "U-8",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
- {
- .ifnum = 0,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 1,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0005,
- .in_cables = 0x0005
- }
- },
- {
- .ifnum = -1
- }
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0005,
+ .in_cables = 0x0005
}
}
},
@@ -293,28 +242,11 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "UM-2",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
- {
- .ifnum = 0,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 1,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0003,
- .in_cables = 0x0003
- }
- },
- {
- .ifnum = -1
- }
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0003,
+ .in_cables = 0x0003
}
}
},
@@ -323,28 +255,11 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "SC-8820",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
- {
- .ifnum = 0,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 1,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0013,
- .in_cables = 0x0013
- }
- },
- {
- .ifnum = -1
- }
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0013,
+ .in_cables = 0x0013
}
}
},
@@ -353,28 +268,11 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "PC-300",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
- {
- .ifnum = 0,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 1,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0001,
- .in_cables = 0x0001
- }
- },
- {
- .ifnum = -1
- }
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
}
}
},
@@ -383,28 +281,11 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "UM-1",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
- {
- .ifnum = 0,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 1,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0001,
- .in_cables = 0x0001
- }
- },
- {
- .ifnum = -1
- }
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
}
}
},
@@ -413,28 +294,11 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "SK-500",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
- {
- .ifnum = 0,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 1,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0013,
- .in_cables = 0x0013
- }
- },
- {
- .ifnum = -1
- }
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0013,
+ .in_cables = 0x0013
}
}
},
@@ -557,28 +421,11 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "SD-90",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
- {
- .ifnum = 0,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 1,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x000f,
- .in_cables = 0x000f
- }
- },
- {
- .ifnum = -1
- }
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x000f,
+ .in_cables = 0x000f
}
}
},
@@ -587,28 +434,11 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "MMP-2",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
- {
- .ifnum = 0,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 1,
- .type = QUIRK_IGNORE_INTERFACE
- },
- {
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0001,
- .in_cables = 0x0001
- }
- },
- {
- .ifnum = -1
- }
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
}
}
},
@@ -779,33 +609,15 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
- /*
- * This quirk is for the "Advanced Driver" mode. If off, the GS-10
- * has ID 0x003c and is standard compliant, but has only 16-bit PCM
- * and no MIDI.
- */
USB_DEVICE_VENDOR_SPEC(0x0582, 0x003b),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "BOSS",
.product_name = "GS-10",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_COMPOSITE,
- .data = & (const snd_usb_audio_quirk_t[]) {
- {
- .ifnum = 1,
- .type = QUIRK_AUDIO_STANDARD_INTERFACE
- },
- {
- .ifnum = 2,
- .type = QUIRK_AUDIO_STANDARD_INTERFACE
- },
- {
- .ifnum = 3,
- .type = QUIRK_MIDI_STANDARD_INTERFACE
- },
- {
- .ifnum = -1
- }
+ .ifnum = 3,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0003,
+ .in_cables = 0x0003
}
}
},
diff --git a/trunk/sound/usb/usx2y/usbusx2y.c b/trunk/sound/usb/usx2y/usbusx2y.c
index e6e6da159671..89ee8b732013 100644
--- a/trunk/sound/usb/usx2y/usbusx2y.c
+++ b/trunk/sound/usb/usx2y/usbusx2y.c
@@ -442,7 +442,7 @@ static void usX2Y_usb_disconnect(struct usb_device* device, void* ptr)
snd_card_disconnect((snd_card_t*)ptr);
/* release the midi resources */
list_for_each(p, &usX2Y->chip.midi_list) {
- snd_usbmidi_disconnect(p);
+ snd_usbmidi_disconnect(p, &snd_usX2Y_usb_driver);
}
if (usX2Y->us428ctls_sharedmem)
wake_up(&usX2Y->us428ctls_wait_queue_head);
diff --git a/trunk/sound/usb/usx2y/usbusx2yaudio.c b/trunk/sound/usb/usx2y/usbusx2yaudio.c
index 62dfd28b3b07..4c292e090069 100644
--- a/trunk/sound/usb/usx2y/usbusx2yaudio.c
+++ b/trunk/sound/usb/usx2y/usbusx2yaudio.c
@@ -401,8 +401,10 @@ static void usX2Y_urbs_release(snd_usX2Y_substream_t *subs)
for (i = 0; i < NRURBS; i++)
usX2Y_urb_release(subs->urb + i, subs != subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]);
- kfree(subs->tmpbuf);
- subs->tmpbuf = NULL;
+ if (subs->tmpbuf) {
+ kfree(subs->tmpbuf);
+ subs->tmpbuf = NULL;
+ }
}
/*
* initialize a substream's urbs