diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index b117e42a6166..e0e54a27fc10 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -746,8 +746,10 @@ 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, ESB2, ICH7, ICH8),
- ATI SB450, SB600, RS600,
+ Module for Intel HD Audio (ICH6, ICH6M, ESB2, ICH7, ICH8, ICH9, ICH10,
+ PCH, SCH),
+ ATI SB450, SB600, R600, RS600, RS690, RS780, RV610, RV620,
+ RV630, RV635, RV670, RV770,
VIA VT8251/VT8237A,
SIS966, ULI M5461
@@ -807,6 +809,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
ALC260
hp HP machines
hp-3013 HP machines (3013-variant)
+ hp-dc7600 HP DC7600
fujitsu Fujitsu S7020
acer Acer TravelMate
will Will laptops (PB V7900)
@@ -828,8 +831,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
hippo Hippo (ATI) with jack detection, Sony UX-90s
hippo_1 Hippo (Benq) with jack detection
sony-assamd Sony ASSAMD
+ toshiba-s06 Toshiba S06
+ toshiba-rx1 Toshiba RX1
ultra Samsung Q1 Ultra Vista model
lenovo-3000 Lenovo 3000 y410
+ nec NEC Versa S9100
basic fixed pin assignment w/o SPDIF
auto auto-config reading BIOS (default)
@@ -838,6 +844,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
3stack 3-stack model
toshiba Toshiba A205
acer Acer laptops
+ acer-aspire Acer Aspire One
dell Dell OEM laptops (Vostro 1200)
zepto Zepto laptops
test for testing/debugging purpose, almost all controls can
@@ -847,6 +854,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
ALC269
basic Basic preset
+ quanta Quanta FL1
+ eeepc-p703 ASUS Eeepc P703 P900A
+ eeepc-p901 ASUS Eeepc P901 S101
ALC662/663
3stack-dig 3-stack (2-channel) with SPDIF
@@ -856,10 +866,17 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
lenovo-101e Lenovo laptop
eeepc-p701 ASUS Eeepc P701
eeepc-ep20 ASUS Eeepc EP20
+ ecs ECS/Foxconn mobo
m51va ASUS M51VA
g71v ASUS G71V
h13 ASUS H13
g50v ASUS G50V
+ asus-mode1 ASUS
+ asus-mode2 ASUS
+ asus-mode3 ASUS
+ asus-mode4 ASUS
+ asus-mode5 ASUS
+ asus-mode6 ASUS
auto auto-config reading BIOS (default)
ALC882/885
@@ -891,12 +908,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
lenovo-101e Lenovo 101E
lenovo-nb0763 Lenovo NB0763
lenovo-ms7195-dig Lenovo MS7195
+ lenovo-sky Lenovo Sky
haier-w66 Haier W66
3stack-hp HP machines with 3stack (Lucknow, Samba boards)
6stack-dell Dell machines with 6stack (Inspiron 530)
mitac Mitac 8252D
clevo-m720 Clevo M720 laptop series
fujitsu-pi2515 Fujitsu AMILO Pi2515
+ 3stack-6ch-intel Intel DG33* boards
auto auto-config reading BIOS (default)
ALC861/660
@@ -929,7 +948,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
allout 5-jack in back, 2-jack in front, SPDIF out
auto auto-config reading BIOS (default)
- AD1882
+ AD1882 / AD1882A
3stack 3-stack mode (default)
6stack 6-stack mode
@@ -1079,7 +1098,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
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
+ (Usually SD_LPIB register is more accurate than the
position buffer.)
NB: If you get many "azx_get_response timeout" messages at
@@ -1166,6 +1185,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
* Event Electronics, EZ8
* Digigram VX442
* Lionstracs, Mediastaton
+ * Terrasoniq TS 88
model - Use the given board model, one of the following:
delta1010, dio2496, delta66, delta44, audiophile, delta410,
@@ -1200,7 +1220,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
* TerraTec Phase 22
* TerraTec Phase 28
* AudioTrak Prodigy 7.1
- * AudioTrak Prodigy 7.1LT
+ * AudioTrak Prodigy 7.1 LT
+ * AudioTrak Prodigy 7.1 XT
+ * AudioTrak Prodigy 7.1 HIFI
+ * AudioTrak Prodigy 7.1 HD2
* AudioTrak Prodigy 192
* Pontis MS300
* Albatron K8X800 Pro II
@@ -1211,12 +1234,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
* Shuttle SN25P
* Onkyo SE-90PCI
* Onkyo SE-200PCI
+ * ESI Juli@
+ * Hercules Fortissimo IV
+ * EGO-SYS WaveTerminal 192M
model - Use the given board model, one of the following:
revo51, revo71, amp2000, prodigy71, prodigy71lt,
- prodigy192, aureon51, aureon71, universe, ap192,
- k8x800, phase22, phase28, ms300, av710, se200pci,
- se90pci
+ prodigy71xt, prodigy71hifi, prodigyhd2, prodigy192,
+ juli, aureon51, aureon71, universe, ap192, k8x800,
+ phase22, phase28, ms300, av710, se200pci, se90pci,
+ fortissimo4, sn25p, WT192M
This module supports multiple cards and autoprobe.
@@ -1255,7 +1282,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module for AC'97 motherboards from Intel and compatibles.
* Intel i810/810E, i815, i820, i830, i84x, MX440
- ICH5, ICH6, ICH7, ESB2
+ ICH5, ICH6, ICH7, 6300ESB, ESB2
* SiS 7012 (SiS 735)
* NVidia NForce, NForce2, NForce3, MCP04, CK804
CK8, CK8S, MCP501
@@ -1951,6 +1978,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
* CHIC True Sound 4Dwave
* Shark Predator4D-PCI
* Jaton SonicWave 4D
+ * SiS SI7018 PCI Audio
+ * Hoontech SoundTrack Digital 4DWave NX
pcm_channels - max channels (voices) reserved for PCM
wavetable_size - max wavetable size in kB (4-?kb)
@@ -1966,12 +1995,25 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
vid - Vendor ID for the device (optional)
pid - Product ID for the device (optional)
+ nrpacks - Max. number of packets per URB (default: 8)
+ async_unlink - Use async unlink mode (default: yes)
device_setup - Device specific magic number (optional)
- Influence depends on the device
- Default: 0x0000
+ ignore_ctl_error - Ignore any USB-controller regarding mixer
+ interface (default: no)
This module supports multiple devices, autoprobe and hotplugging.
+ NB: nrpacks parameter can be modified dynamically via sysfs.
+ Don't put the value over 20. Changing via sysfs has no sanity
+ check.
+ NB: async_unlink=0 would cause Oops. It remains just for
+ debugging purpose (if any).
+ NB: ignore_ctl_error=1 may help when you get an error at accessing
+ the mixer element such as URB error -22. This happens on some
+ buggy USB device or the controller.
+
Module snd-usb-caiaq
--------------------
@@ -2078,7 +2120,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
-------------------
Module for sound cards based on the Asus AV100/AV200 chips,
- i.e., Xonar D1, DX, D2 and D2X.
+ i.e., Xonar D1, DX, D2, D2X and HDAV1.3 (Deluxe).
This module supports autoprobe and multiple cards.
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index e13c4e67029f..b54cb5048dfa 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -6135,44 +6135,58 @@ struct _snd_pcm_runtime {
-
- snd_assert()
-
- snd_assert() macro is similar with the
- normal assert() macro. For example,
-
-
-
-
-
-
-
-
-
- The first argument is the expression to evaluate, and the
- second argument is the action if it fails. When
- CONFIG_SND_DEBUG, is set, it will show an
- error message such as BUG? (xxx)
- together with stack trace.
-
-
- When no debug flag is set, this macro is ignored.
-
-
-
snd_BUG()
It shows the BUG? message and
- stack trace as well as snd_assert at the point.
+ stack trace as well as snd_BUG_ON at the point.
It's useful to show that a fatal error happens there.
When no debug flag is set, this macro is ignored.
+
+
+ snd_BUG_ON()
+
+ snd_BUG_ON() macro is similar with
+ WARN_ON() macro. For example,
+
+
+
+
+
+
+
+ or it can be used as the condition,
+
+
+
+
+
+
+
+
+
+ The macro takes an conditional expression to evaluate.
+ When CONFIG_SND_DEBUG, is set, the
+ expression is actually evaluated. If it's non-zero, it shows
+ the warning message such as
+ BUG? (xxx)
+ normally followed by stack trace. It returns the evaluated
+ value.
+ When no CONFIG_SND_DEBUG is set, this
+ macro always returns zero.
+
+
+
+
diff --git a/MAINTAINERS b/MAINTAINERS
index 7a03bd5a91a3..ece4e27f9972 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3828,6 +3828,8 @@ S: Maintained
SOUND
P: Jaroslav Kysela
M: perex@perex.cz
+P: Takashi Iwai
+M: tiwai@suse.de
L: alsa-devel@alsa-project.org (subscribers-only)
S: Maintained
diff --git a/arch/arm/plat-omap/include/mach/mtd-xip.h b/arch/arm/plat-omap/include/mach/mtd-xip.h
index 5cee7e16a1b4..39b591ff54bb 100644
--- a/arch/arm/plat-omap/include/mach/mtd-xip.h
+++ b/arch/arm/plat-omap/include/mach/mtd-xip.h
@@ -3,7 +3,7 @@
*
* Do not include this file directly. It's included from linux/mtd/xip.h
*
- * Author: Vladimir Barinov
+ * Author: Vladimir Barinov
*
* (c) 2005 MontaVista Software, Inc. This file is licensed under the
* terms of the GNU General Public License version 2. This program is
diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char
index 1b238ebae6b3..70dabd1e0652 100644
--- a/arch/um/Kconfig.char
+++ b/arch/um/Kconfig.char
@@ -203,6 +203,10 @@ config SOUND
tristate
default UML_SOUND
+config SOUND_OSS_CORE
+ bool
+ default UML_SOUND
+
config HOSTAUDIO
tristate
default UML_SOUND
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index 9929d20320b4..26194a0ce927 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -488,10 +488,12 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
period_size = params_period_bytes(hw_params);
periods = params_periods(hw_params);
- snd_assert(period_size >= 0x100 && period_size <= 0x10000,
- return -EINVAL);
- snd_assert(periods >= 4, return -EINVAL);
- snd_assert(period_size * periods <= 1024 * 1024, return -EINVAL);
+ if (period_size < 0x100 || period_size > 0x10000)
+ return -EINVAL;
+ if (periods < 4)
+ return -EINVAL;
+ if (period_size * periods > 1024 * 1024)
+ return -EINVAL;
dev = saa7134->dev;
@@ -942,7 +944,8 @@ static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip)
unsigned int idx;
int err;
- snd_assert(chip != NULL, return -EINVAL);
+ if (snd_BUG_ON(!chip))
+ return -EINVAL;
strcpy(card->mixername, "SAA7134 Mixer");
for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_controls); idx++) {
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
index f9575c409124..9c32063a0c2f 100644
--- a/drivers/usb/host/ehci-ixp4xx.c
+++ b/drivers/usb/host/ehci-ixp4xx.c
@@ -1,7 +1,7 @@
/*
* IXP4XX EHCI Host Controller Driver
*
- * Author: Vladimir Barinov
+ * Author: Vladimir Barinov
*
* Based on "ehci-fsl.c" by Randy Vinson
*
diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h
deleted file mode 100644
index d9aebdf6db63..000000000000
--- a/include/sound/ad1848.h
+++ /dev/null
@@ -1,218 +0,0 @@
-#ifndef __SOUND_AD1848_H
-#define __SOUND_AD1848_H
-
-/*
- * Copyright (c) by Jaroslav Kysela
- * Definitions for AD1847/AD1848/CS4248 chips
- *
- *
- * 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 "pcm.h"
-#include
-
-/* IO ports */
-
-#define AD1848P( chip, x ) ( (chip) -> port + c_d_c_AD1848##x )
-
-#define c_d_c_AD1848REGSEL 0
-#define c_d_c_AD1848REG 1
-#define c_d_c_AD1848STATUS 2
-#define c_d_c_AD1848PIO 3
-
-/* codec registers */
-
-#define AD1848_LEFT_INPUT 0x00 /* left input control */
-#define AD1848_RIGHT_INPUT 0x01 /* right input control */
-#define AD1848_AUX1_LEFT_INPUT 0x02 /* left AUX1 input control */
-#define AD1848_AUX1_RIGHT_INPUT 0x03 /* right AUX1 input control */
-#define AD1848_AUX2_LEFT_INPUT 0x04 /* left AUX2 input control */
-#define AD1848_AUX2_RIGHT_INPUT 0x05 /* right AUX2 input control */
-#define AD1848_LEFT_OUTPUT 0x06 /* left output control register */
-#define AD1848_RIGHT_OUTPUT 0x07 /* right output control register */
-#define AD1848_DATA_FORMAT 0x08 /* clock and data format - playback/capture - bits 7-0 MCE */
-#define AD1848_IFACE_CTRL 0x09 /* interface control - bits 7-2 MCE */
-#define AD1848_PIN_CTRL 0x0a /* pin control */
-#define AD1848_TEST_INIT 0x0b /* test and initialization */
-#define AD1848_MISC_INFO 0x0c /* miscellaneous information */
-#define AD1848_LOOPBACK 0x0d /* loopback control */
-#define AD1848_DATA_UPR_CNT 0x0e /* playback/capture upper base count */
-#define AD1848_DATA_LWR_CNT 0x0f /* playback/capture lower base count */
-
-/* definitions for codec register select port - CODECP( REGSEL ) */
-
-#define AD1848_INIT 0x80 /* CODEC is initializing */
-#define AD1848_MCE 0x40 /* mode change enable */
-#define AD1848_TRD 0x20 /* transfer request disable */
-
-/* definitions for codec status register - CODECP( STATUS ) */
-
-#define AD1848_GLOBALIRQ 0x01 /* IRQ is active */
-
-/* definitions for AD1848_LEFT_INPUT and AD1848_RIGHT_INPUT registers */
-
-#define AD1848_ENABLE_MIC_GAIN 0x20
-
-#define AD1848_MIXS_LINE1 0x00
-#define AD1848_MIXS_AUX1 0x40
-#define AD1848_MIXS_LINE2 0x80
-#define AD1848_MIXS_ALL 0xc0
-
-/* definitions for clock and data format register - AD1848_PLAYBK_FORMAT */
-
-#define AD1848_LINEAR_8 0x00 /* 8-bit unsigned data */
-#define AD1848_ALAW_8 0x60 /* 8-bit A-law companded */
-#define AD1848_ULAW_8 0x20 /* 8-bit U-law companded */
-#define AD1848_LINEAR_16 0x40 /* 16-bit twos complement data - little endian */
-#define AD1848_STEREO 0x10 /* stereo mode */
-/* bits 3-1 define frequency divisor */
-#define AD1848_XTAL1 0x00 /* 24.576 crystal */
-#define AD1848_XTAL2 0x01 /* 16.9344 crystal */
-
-/* definitions for interface control register - AD1848_IFACE_CTRL */
-
-#define AD1848_CAPTURE_PIO 0x80 /* capture PIO enable */
-#define AD1848_PLAYBACK_PIO 0x40 /* playback PIO enable */
-#define AD1848_CALIB_MODE 0x18 /* calibration mode bits */
-#define AD1848_AUTOCALIB 0x08 /* auto calibrate */
-#define AD1848_SINGLE_DMA 0x04 /* use single DMA channel */
-#define AD1848_CAPTURE_ENABLE 0x02 /* capture enable */
-#define AD1848_PLAYBACK_ENABLE 0x01 /* playback enable */
-
-/* definitions for pin control register - AD1848_PIN_CTRL */
-
-#define AD1848_IRQ_ENABLE 0x02 /* enable IRQ */
-#define AD1848_XCTL1 0x40 /* external control #1 */
-#define AD1848_XCTL0 0x80 /* external control #0 */
-
-/* definitions for test and init register - AD1848_TEST_INIT */
-
-#define AD1848_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */
-#define AD1848_DMA_REQUEST 0x10 /* DMA request in progress */
-
-/* defines for codec.mode */
-
-#define AD1848_MODE_NONE 0x0000
-#define AD1848_MODE_PLAY 0x0001
-#define AD1848_MODE_CAPTURE 0x0002
-#define AD1848_MODE_TIMER 0x0004
-#define AD1848_MODE_OPEN (AD1848_MODE_PLAY|AD1848_MODE_CAPTURE|AD1848_MODE_TIMER)
-#define AD1848_MODE_RUNNING 0x0010
-
-/* defines for codec.hardware */
-
-#define AD1848_HW_DETECT 0x0000 /* let AD1848 driver detect chip */
-#define AD1848_HW_AD1847 0x0001 /* AD1847 chip */
-#define AD1848_HW_AD1848 0x0002 /* AD1848 chip */
-#define AD1848_HW_CS4248 0x0003 /* CS4248 chip */
-#define AD1848_HW_CMI8330 0x0004 /* CMI8330 chip */
-#define AD1848_HW_THINKPAD 0x0005 /* Thinkpad 360/750/755 */
-
-/* IBM Thinkpad specific stuff */
-#define AD1848_THINKPAD_CTL_PORT1 0x15e8
-#define AD1848_THINKPAD_CTL_PORT2 0x15e9
-#define AD1848_THINKPAD_CS4248_ENABLE_BIT 0x02
-
-struct snd_ad1848 {
- unsigned long port; /* i/o port */
- struct resource *res_port;
- int irq; /* IRQ line */
- int dma; /* data DMA */
- unsigned short version; /* version of CODEC chip */
- unsigned short mode; /* see to AD1848_MODE_XXXX */
- unsigned short hardware; /* see to AD1848_HW_XXXX */
- unsigned short single_dma:1; /* forced single DMA mode (GUS 16-bit daughter board) or dma1 == dma2 */
-
- struct snd_pcm *pcm;
- struct snd_pcm_substream *playback_substream;
- struct snd_pcm_substream *capture_substream;
- struct snd_card *card;
-
- unsigned char image[32]; /* SGalaxy needs an access to extended registers */
- int mce_bit;
- int calibrate_mute;
- int dma_size;
- int thinkpad_flag; /* Thinkpad CS4248 needs some extra help */
-
-#ifdef CONFIG_PM
- void (*suspend)(struct snd_ad1848 *chip);
- void (*resume)(struct snd_ad1848 *chip);
-#endif
-
- spinlock_t reg_lock;
-};
-
-/* exported functions */
-
-void snd_ad1848_out(struct snd_ad1848 *chip, unsigned char reg, unsigned char value);
-
-int snd_ad1848_create(struct snd_card *card,
- unsigned long port,
- int irq, int dma,
- unsigned short hardware,
- struct snd_ad1848 ** chip);
-
-int snd_ad1848_pcm(struct snd_ad1848 * chip, int device, struct snd_pcm **rpcm);
-const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction);
-int snd_ad1848_mixer(struct snd_ad1848 * chip);
-
-/* exported mixer stuffs */
-enum { AD1848_MIX_SINGLE, AD1848_MIX_DOUBLE, AD1848_MIX_CAPTURE };
-
-#define AD1848_MIXVAL_SINGLE(reg, shift, mask, invert) \
- ((reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24))
-#define AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert) \
- ((left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | ((shift_right) << 19) | ((mask) << 24) | ((invert) << 22))
-
-/* for ease of use */
-struct ad1848_mix_elem {
- const char *name;
- int index;
- int type;
- unsigned long private_value;
- const unsigned int *tlv;
-};
-
-#define AD1848_SINGLE(xname, xindex, reg, shift, mask, invert) \
-{ .name = xname, \
- .index = xindex, \
- .type = AD1848_MIX_SINGLE, \
- .private_value = AD1848_MIXVAL_SINGLE(reg, shift, mask, invert) }
-
-#define AD1848_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
-{ .name = xname, \
- .index = xindex, \
- .type = AD1848_MIX_SINGLE, \
- .private_value = AD1848_MIXVAL_SINGLE(reg, shift, mask, invert), \
- .tlv = xtlv }
-
-#define AD1848_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
-{ .name = xname, \
- .index = xindex, \
- .type = AD1848_MIX_DOUBLE, \
- .private_value = AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert) }
-
-#define AD1848_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \
-{ .name = xname, \
- .index = xindex, \
- .type = AD1848_MIX_DOUBLE, \
- .private_value = AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert), \
- .tlv = xtlv }
-
-int snd_ad1848_add_ctl_elem(struct snd_ad1848 *chip, const struct ad1848_mix_elem *c);
-
-#endif /* __SOUND_AD1848_H */
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 3eaf155b850d..2c4dc908a54a 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -93,9 +93,10 @@ enum {
SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */
SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */
SNDRV_HWDEP_IFACE_HDA, /* HD-audio */
+ SNDRV_HWDEP_IFACE_USB_STREAM, /* direct access to usb stream */
/* Don't forget to change the following: */
- SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_HDA
+ SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
};
struct snd_hwdep_info {
@@ -296,29 +297,39 @@ struct snd_pcm_info {
unsigned char reserved[64]; /* reserved for future... */
};
-typedef int __bitwise snd_pcm_hw_param_t;
-#define SNDRV_PCM_HW_PARAM_ACCESS ((__force snd_pcm_hw_param_t) 0) /* Access type */
-#define SNDRV_PCM_HW_PARAM_FORMAT ((__force snd_pcm_hw_param_t) 1) /* Format */
-#define SNDRV_PCM_HW_PARAM_SUBFORMAT ((__force snd_pcm_hw_param_t) 2) /* Subformat */
+typedef int snd_pcm_hw_param_t;
+#define SNDRV_PCM_HW_PARAM_ACCESS 0 /* Access type */
+#define SNDRV_PCM_HW_PARAM_FORMAT 1 /* Format */
+#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2 /* Subformat */
#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS
#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT
-#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS ((__force snd_pcm_hw_param_t) 8) /* Bits per sample */
-#define SNDRV_PCM_HW_PARAM_FRAME_BITS ((__force snd_pcm_hw_param_t) 9) /* Bits per frame */
-#define SNDRV_PCM_HW_PARAM_CHANNELS ((__force snd_pcm_hw_param_t) 10) /* Channels */
-#define SNDRV_PCM_HW_PARAM_RATE ((__force snd_pcm_hw_param_t) 11) /* Approx rate */
-#define SNDRV_PCM_HW_PARAM_PERIOD_TIME ((__force snd_pcm_hw_param_t) 12) /* Approx distance between interrupts in us */
-#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE ((__force snd_pcm_hw_param_t) 13) /* Approx frames between interrupts */
-#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES ((__force snd_pcm_hw_param_t) 14) /* Approx bytes between interrupts */
-#define SNDRV_PCM_HW_PARAM_PERIODS ((__force snd_pcm_hw_param_t) 15) /* Approx interrupts per buffer */
-#define SNDRV_PCM_HW_PARAM_BUFFER_TIME ((__force snd_pcm_hw_param_t) 16) /* Approx duration of buffer in us */
-#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE ((__force snd_pcm_hw_param_t) 17) /* Size of buffer in frames */
-#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES ((__force snd_pcm_hw_param_t) 18) /* Size of buffer in bytes */
-#define SNDRV_PCM_HW_PARAM_TICK_TIME ((__force snd_pcm_hw_param_t) 19) /* Approx tick duration in us */
+#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8 /* Bits per sample */
+#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9 /* Bits per frame */
+#define SNDRV_PCM_HW_PARAM_CHANNELS 10 /* Channels */
+#define SNDRV_PCM_HW_PARAM_RATE 11 /* Approx rate */
+#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12 /* Approx distance between
+ * interrupts in us
+ */
+#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13 /* Approx frames between
+ * interrupts
+ */
+#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14 /* Approx bytes between
+ * interrupts
+ */
+#define SNDRV_PCM_HW_PARAM_PERIODS 15 /* Approx interrupts per
+ * buffer
+ */
+#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16 /* Approx duration of buffer
+ * in us
+ */
+#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17 /* Size of buffer in frames */
+#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18 /* Size of buffer in bytes */
+#define SNDRV_PCM_HW_PARAM_TICK_TIME 19 /* Approx tick duration in us */
#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS
#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME
-#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */
+#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */
struct snd_interval {
unsigned int min, max;
@@ -696,7 +707,7 @@ struct snd_timer_tread {
* *
****************************************************************************/
-#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 5)
+#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
struct snd_ctl_card_info {
int card; /* card number */
@@ -707,8 +718,7 @@ struct snd_ctl_card_info {
unsigned char longname[80]; /* name + info text about soundcard */
unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */
unsigned char mixername[80]; /* visual mixer identification */
- unsigned char components[80]; /* card components / fine identification, delimited with one space (AC97 etc..) */
- unsigned char reserved[48]; /* reserved for future */
+ unsigned char components[128]; /* card components / fine identification, delimited with one space (AC97 etc..) */
};
typedef int __bitwise snd_ctl_elem_type_t;
diff --git a/include/sound/asoundef.h b/include/sound/asoundef.h
index a6e0facf8a37..20ebf3298eba 100644
--- a/include/sound/asoundef.h
+++ b/include/sound/asoundef.h
@@ -60,35 +60,56 @@
#define IEC958_AES1_PRO_USERBITS_UDEF (12<<4) /* user defined application */
#define IEC958_AES1_CON_CATEGORY 0x7f
#define IEC958_AES1_CON_GENERAL 0x00
-#define IEC958_AES1_CON_EXPERIMENTAL 0x40
-#define IEC958_AES1_CON_SOLIDMEM_MASK 0x0f
-#define IEC958_AES1_CON_SOLIDMEM_ID 0x08
-#define IEC958_AES1_CON_BROADCAST1_MASK 0x07
-#define IEC958_AES1_CON_BROADCAST1_ID 0x04
-#define IEC958_AES1_CON_DIGDIGCONV_MASK 0x07
-#define IEC958_AES1_CON_DIGDIGCONV_ID 0x02
-#define IEC958_AES1_CON_ADC_COPYRIGHT_MASK 0x1f
-#define IEC958_AES1_CON_ADC_COPYRIGHT_ID 0x06
-#define IEC958_AES1_CON_ADC_MASK 0x1f
-#define IEC958_AES1_CON_ADC_ID 0x16
-#define IEC958_AES1_CON_BROADCAST2_MASK 0x0f
-#define IEC958_AES1_CON_BROADCAST2_ID 0x0e
#define IEC958_AES1_CON_LASEROPT_MASK 0x07
#define IEC958_AES1_CON_LASEROPT_ID 0x01
-#define IEC958_AES1_CON_MUSICAL_MASK 0x07
-#define IEC958_AES1_CON_MUSICAL_ID 0x05
-#define IEC958_AES1_CON_MAGNETIC_MASK 0x07
-#define IEC958_AES1_CON_MAGNETIC_ID 0x03
#define IEC958_AES1_CON_IEC908_CD (IEC958_AES1_CON_LASEROPT_ID|0x00)
#define IEC958_AES1_CON_NON_IEC908_CD (IEC958_AES1_CON_LASEROPT_ID|0x08)
+#define IEC958_AES1_CON_MINI_DISC (IEC958_AES1_CON_LASEROPT_ID|0x48)
+#define IEC958_AES1_CON_DVD (IEC958_AES1_CON_LASEROPT_ID|0x18)
+#define IEC958_AES1_CON_LASTEROPT_OTHER (IEC958_AES1_CON_LASEROPT_ID|0x78)
+#define IEC958_AES1_CON_DIGDIGCONV_MASK 0x07
+#define IEC958_AES1_CON_DIGDIGCONV_ID 0x02
#define IEC958_AES1_CON_PCM_CODER (IEC958_AES1_CON_DIGDIGCONV_ID|0x00)
-#define IEC958_AES1_CON_SAMPLER (IEC958_AES1_CON_DIGDIGCONV_ID|0x20)
#define IEC958_AES1_CON_MIXER (IEC958_AES1_CON_DIGDIGCONV_ID|0x10)
#define IEC958_AES1_CON_RATE_CONVERTER (IEC958_AES1_CON_DIGDIGCONV_ID|0x18)
-#define IEC958_AES1_CON_SYNTHESIZER (IEC958_AES1_CON_MUSICAL_ID|0x00)
-#define IEC958_AES1_CON_MICROPHONE (IEC958_AES1_CON_MUSICAL_ID|0x08)
+#define IEC958_AES1_CON_SAMPLER (IEC958_AES1_CON_DIGDIGCONV_ID|0x20)
+#define IEC958_AES1_CON_DSP (IEC958_AES1_CON_DIGDIGCONV_ID|0x28)
+#define IEC958_AES1_CON_DIGDIGCONV_OTHER (IEC958_AES1_CON_DIGDIGCONV_ID|0x78)
+#define IEC958_AES1_CON_MAGNETIC_MASK 0x07
+#define IEC958_AES1_CON_MAGNETIC_ID 0x03
#define IEC958_AES1_CON_DAT (IEC958_AES1_CON_MAGNETIC_ID|0x00)
#define IEC958_AES1_CON_VCR (IEC958_AES1_CON_MAGNETIC_ID|0x08)
+#define IEC958_AES1_CON_DCC (IEC958_AES1_CON_MAGNETIC_ID|0x40)
+#define IEC958_AES1_CON_MAGNETIC_DISC (IEC958_AES1_CON_MAGNETIC_ID|0x18)
+#define IEC958_AES1_CON_MAGNETIC_OTHER (IEC958_AES1_CON_MAGNETIC_ID|0x78)
+#define IEC958_AES1_CON_BROADCAST1_MASK 0x07
+#define IEC958_AES1_CON_BROADCAST1_ID 0x04
+#define IEC958_AES1_CON_DAB_JAPAN (IEC958_AES1_CON_BROADCAST1_ID|0x00)
+#define IEC958_AES1_CON_DAB_EUROPE (IEC958_AES1_CON_BROADCAST1_ID|0x08)
+#define IEC958_AES1_CON_DAB_USA (IEC958_AES1_CON_BROADCAST1_ID|0x60)
+#define IEC958_AES1_CON_SOFTWARE (IEC958_AES1_CON_BROADCAST1_ID|0x40)
+#define IEC958_AES1_CON_IEC62105 (IEC958_AES1_CON_BROADCAST1_ID|0x20)
+#define IEC958_AES1_CON_BROADCAST1_OTHER (IEC958_AES1_CON_BROADCAST1_ID|0x78)
+#define IEC958_AES1_CON_BROADCAST2_MASK 0x0f
+#define IEC958_AES1_CON_BROADCAST2_ID 0x0e
+#define IEC958_AES1_CON_MUSICAL_MASK 0x07
+#define IEC958_AES1_CON_MUSICAL_ID 0x05
+#define IEC958_AES1_CON_SYNTHESIZER (IEC958_AES1_CON_MUSICAL_ID|0x00)
+#define IEC958_AES1_CON_MICROPHONE (IEC958_AES1_CON_MUSICAL_ID|0x08)
+#define IEC958_AES1_CON_MUSICAL_OTHER (IEC958_AES1_CON_MUSICAL_ID|0x78)
+#define IEC958_AES1_CON_ADC_MASK 0x1f
+#define IEC958_AES1_CON_ADC_ID 0x06
+#define IEC958_AES1_CON_ADC (IEC958_AES1_CON_ADC_ID|0x00)
+#define IEC958_AES1_CON_ADC_OTHER (IEC958_AES1_CON_ADC_ID|0x60)
+#define IEC958_AES1_CON_ADC_COPYRIGHT_MASK 0x1f
+#define IEC958_AES1_CON_ADC_COPYRIGHT_ID 0x16
+#define IEC958_AES1_CON_ADC_COPYRIGHT (IEC958_AES1_CON_ADC_COPYRIGHT_ID|0x00)
+#define IEC958_AES1_CON_ADC_COPYRIGHT_OTHER (IEC958_AES1_CON_ADC_COPYRIGHT_ID|0x60)
+#define IEC958_AES1_CON_SOLIDMEM_MASK 0x0f
+#define IEC958_AES1_CON_SOLIDMEM_ID 0x08
+#define IEC958_AES1_CON_SOLIDMEM_DIGITAL_RECORDER_PLAYER (IEC958_AES1_CON_SOLIDMEM_ID|0x00)
+#define IEC958_AES1_CON_SOLIDMEM_OTHER (IEC958_AES1_CON_SOLIDMEM_ID|0x70)
+#define IEC958_AES1_CON_EXPERIMENTAL 0x40
#define IEC958_AES1_CON_ORIGINAL (1<<7) /* this bits depends on the category code */
#define IEC958_AES2_PRO_SBITS (7<<0) /* mask - sample bits */
#define IEC958_AES2_PRO_SBITS_20 (2<<0) /* 20-bit - coordination */
@@ -106,8 +127,16 @@
#define IEC958_AES2_CON_CHANNEL_UNSPEC (0<<4) /* unspecified */
#define IEC958_AES3_CON_FS (15<<0) /* mask - sample frequency */
#define IEC958_AES3_CON_FS_44100 (0<<0) /* 44.1kHz */
+#define IEC958_AES3_CON_FS_NOTID (1<<0) /* non indicated */
#define IEC958_AES3_CON_FS_48000 (2<<0) /* 48kHz */
#define IEC958_AES3_CON_FS_32000 (3<<0) /* 32kHz */
+#define IEC958_AES3_CON_FS_22050 (4<<0) /* 22.05kHz */
+#define IEC958_AES3_CON_FS_24000 (6<<0) /* 24kHz */
+#define IEC958_AES3_CON_FS_88200 (8<<0) /* 88.2kHz */
+#define IEC958_AES3_CON_FS_768000 (9<<0) /* 768kHz */
+#define IEC958_AES3_CON_FS_96000 (10<<0) /* 96kHz */
+#define IEC958_AES3_CON_FS_176400 (12<<0) /* 176.4kHz */
+#define IEC958_AES3_CON_FS_192000 (14<<0) /* 192kHz */
#define IEC958_AES3_CON_CLOCK (3<<4) /* mask - clock accuracy */
#define IEC958_AES3_CON_CLOCK_1000PPM (0<<4) /* 1000 ppm */
#define IEC958_AES3_CON_CLOCK_50PPM (1<<4) /* 50 ppm */
@@ -120,6 +149,26 @@
#define IEC958_AES4_CON_WORDLEN_23_19 (4<<1) /* 23-bit or 19-bit */
#define IEC958_AES4_CON_WORDLEN_24_20 (5<<1) /* 24-bit or 20-bit */
#define IEC958_AES4_CON_WORDLEN_21_17 (6<<1) /* 21-bit or 17-bit */
+#define IEC958_AES4_CON_ORIGFS (15<<4) /* mask - original sample frequency */
+#define IEC958_AES4_CON_ORIGFS_NOTID (0<<4) /* not indicated */
+#define IEC958_AES4_CON_ORIGFS_192000 (1<<4) /* 192kHz */
+#define IEC958_AES4_CON_ORIGFS_12000 (2<<4) /* 12kHz */
+#define IEC958_AES4_CON_ORIGFS_176400 (3<<4) /* 176.4kHz */
+#define IEC958_AES4_CON_ORIGFS_96000 (5<<4) /* 96kHz */
+#define IEC958_AES4_CON_ORIGFS_8000 (6<<4) /* 8kHz */
+#define IEC958_AES4_CON_ORIGFS_88200 (7<<4) /* 88.2kHz */
+#define IEC958_AES4_CON_ORIGFS_16000 (8<<4) /* 16kHz */
+#define IEC958_AES4_CON_ORIGFS_24000 (9<<4) /* 24kHz */
+#define IEC958_AES4_CON_ORIGFS_11025 (10<<4) /* 11.025kHz */
+#define IEC958_AES4_CON_ORIGFS_22050 (11<<4) /* 22.05kHz */
+#define IEC958_AES4_CON_ORIGFS_32000 (12<<4) /* 32kHz */
+#define IEC958_AES4_CON_ORIGFS_48000 (13<<4) /* 48kHz */
+#define IEC958_AES4_CON_ORIGFS_44100 (15<<4) /* 44.1kHz */
+#define IEC958_AES5_CON_CGMSA (3<<0) /* mask - CGMS-A */
+#define IEC958_AES5_CON_CGMSA_COPYFREELY (0<<0) /* copying is permitted without restriction */
+#define IEC958_AES5_CON_CGMSA_COPYONCE (1<<0) /* one generation of copies may be made */
+#define IEC958_AES5_CON_CGMSA_COPYNOMORE (2<<0) /* condition not be used */
+#define IEC958_AES5_CON_CGMSA_COPYNEVER (3<<0) /* no copying is permitted */
/*****************************************************************************
* *
diff --git a/include/sound/core.h b/include/sound/core.h
index 558b96284bd2..e5eec5f73502 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -28,6 +28,7 @@
#include /* struct rw_semaphore */
#include /* pm_message_t */
#include
+#include
/* number of supported soundcards */
#ifdef CONFIG_SND_DYNAMIC_MINORS
@@ -63,6 +64,7 @@ typedef int __bitwise snd_device_type_t;
#define SNDRV_DEV_INFO ((__force snd_device_type_t) 0x1006)
#define SNDRV_DEV_BUS ((__force snd_device_type_t) 0x1007)
#define SNDRV_DEV_CODEC ((__force snd_device_type_t) 0x1008)
+#define SNDRV_DEV_JACK ((__force snd_device_type_t) 0x1009)
#define SNDRV_DEV_LOWLEVEL ((__force snd_device_type_t) 0x2000)
typedef int __bitwise snd_device_state_t;
@@ -114,7 +116,7 @@ struct snd_card {
char shortname[32]; /* short name of this soundcard */
char longname[80]; /* name of this soundcard */
char mixername[80]; /* mixer name */
- char components[80]; /* card components delimited with
+ char components[128]; /* card components delimited with
space */
struct module *module; /* top-level module */
@@ -366,8 +368,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
#ifdef CONFIG_SND_DEBUG
-#define __ASTRING__(x) #x
-
#ifdef CONFIG_SND_VERBOSE_PRINTK
/**
* snd_printd - debug printk
@@ -382,33 +382,15 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
#define snd_printd(fmt, args...) \
printk(fmt ,##args)
#endif
-/**
- * snd_assert - run-time assertion macro
- * @expr: expression
- *
- * This macro checks the expression in run-time and invokes the commands
- * given in the rest arguments if the assertion is failed.
- * When CONFIG_SND_DEBUG is not set, the expression is executed but
- * not checked.
- */
-#define snd_assert(expr, args...) do { \
- if (unlikely(!(expr))) { \
- snd_printk(KERN_ERR "BUG? (%s)\n", __ASTRING__(expr)); \
- dump_stack(); \
- args; \
- } \
-} while (0)
-#define snd_BUG() do { \
- snd_printk(KERN_ERR "BUG?\n"); \
- dump_stack(); \
-} while (0)
+#define snd_BUG() WARN(1, "BUG?\n")
+#define snd_BUG_ON(cond) WARN((cond), "BUG? (%s)\n", __stringify(cond))
#else /* !CONFIG_SND_DEBUG */
#define snd_printd(fmt, args...) /* nothing */
-#define snd_assert(expr, args...) (void)(expr)
#define snd_BUG() /* nothing */
+#define snd_BUG_ON(cond) ({/*(void)(cond);*/ 0;}) /* always false */
#endif /* CONFIG_SND_DEBUG */
diff --git a/include/sound/cs4231.h b/include/sound/cs4231.h
deleted file mode 100644
index f0785f9f4ae4..000000000000
--- a/include/sound/cs4231.h
+++ /dev/null
@@ -1,175 +0,0 @@
-#ifndef __SOUND_CS4231_H
-#define __SOUND_CS4231_H
-
-/*
- * Copyright (c) by Jaroslav Kysela
- * Definitions for CS4231 & InterWave chips & compatible chips
- *
- *
- * 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 "control.h"
-#include "pcm.h"
-#include "timer.h"
-
-#include "cs4231-regs.h"
-
-/* defines for codec.mode */
-
-#define CS4231_MODE_NONE 0x0000
-#define CS4231_MODE_PLAY 0x0001
-#define CS4231_MODE_RECORD 0x0002
-#define CS4231_MODE_TIMER 0x0004
-#define CS4231_MODE_OPEN (CS4231_MODE_PLAY|CS4231_MODE_RECORD|CS4231_MODE_TIMER)
-
-/* defines for codec.hardware */
-
-#define CS4231_HW_DETECT 0x0000 /* let CS4231 driver detect chip */
-#define CS4231_HW_DETECT3 0x0001 /* allow mode 3 */
-#define CS4231_HW_TYPE_MASK 0xff00 /* type mask */
-#define CS4231_HW_CS4231_MASK 0x0100 /* CS4231 serie */
-#define CS4231_HW_CS4231 0x0100 /* CS4231 chip */
-#define CS4231_HW_CS4231A 0x0101 /* CS4231A chip */
-#define CS4231_HW_AD1845 0x0102 /* AD1845 chip */
-#define CS4231_HW_CS4232_MASK 0x0200 /* CS4232 serie (has control ports) */
-#define CS4231_HW_CS4232 0x0200 /* CS4232 */
-#define CS4231_HW_CS4232A 0x0201 /* CS4232A */
-#define CS4231_HW_CS4236 0x0202 /* CS4236 */
-#define CS4231_HW_CS4236B_MASK 0x0400 /* CS4236B serie (has extended control regs) */
-#define CS4231_HW_CS4235 0x0400 /* CS4235 - Crystal Clear (tm) stereo enhancement */
-#define CS4231_HW_CS4236B 0x0401 /* CS4236B */
-#define CS4231_HW_CS4237B 0x0402 /* CS4237B - SRS 3D */
-#define CS4231_HW_CS4238B 0x0403 /* CS4238B - QSOUND 3D */
-#define CS4231_HW_CS4239 0x0404 /* CS4239 - Crystal Clear (tm) stereo enhancement */
-/* compatible, but clones */
-#define CS4231_HW_INTERWAVE 0x1000 /* InterWave chip */
-#define CS4231_HW_OPL3SA2 0x1101 /* OPL3-SA2 chip, similar to cs4231 */
-#define CS4231_HW_OPTI93X 0x1102 /* Opti 930/931/933 */
-
-/* defines for codec.hwshare */
-#define CS4231_HWSHARE_IRQ (1<<0)
-#define CS4231_HWSHARE_DMA1 (1<<1)
-#define CS4231_HWSHARE_DMA2 (1<<2)
-
-struct snd_cs4231 {
- unsigned long port; /* base i/o port */
- struct resource *res_port;
- unsigned long cport; /* control base i/o port (CS4236) */
- struct resource *res_cport;
- int irq; /* IRQ line */
- int dma1; /* playback DMA */
- int dma2; /* record DMA */
- unsigned short version; /* version of CODEC chip */
- unsigned short mode; /* see to CS4231_MODE_XXXX */
- unsigned short hardware; /* see to CS4231_HW_XXXX */
- unsigned short hwshare; /* shared resources */
- unsigned short single_dma:1, /* forced single DMA mode (GUS 16-bit daughter board) or dma1 == dma2 */
- ebus_flag:1; /* SPARC: EBUS present */
-
- struct snd_card *card;
- struct snd_pcm *pcm;
- struct snd_pcm_substream *playback_substream;
- struct snd_pcm_substream *capture_substream;
- struct snd_timer *timer;
-
- unsigned char image[32]; /* registers image */
- unsigned char eimage[32]; /* extended registers image */
- unsigned char cimage[16]; /* control registers image */
- int mce_bit;
- int calibrate_mute;
- int sw_3d_bit;
- unsigned int p_dma_size;
- unsigned int c_dma_size;
-
- spinlock_t reg_lock;
- struct mutex mce_mutex;
- struct mutex open_mutex;
-
- int (*rate_constraint) (struct snd_pcm_runtime *runtime);
- void (*set_playback_format) (struct snd_cs4231 *chip, struct snd_pcm_hw_params *hw_params, unsigned char pdfr);
- void (*set_capture_format) (struct snd_cs4231 *chip, struct snd_pcm_hw_params *hw_params, unsigned char cdfr);
- void (*trigger) (struct snd_cs4231 *chip, unsigned int what, int start);
-#ifdef CONFIG_PM
- void (*suspend) (struct snd_cs4231 *chip);
- void (*resume) (struct snd_cs4231 *chip);
-#endif
- void *dma_private_data;
- int (*claim_dma) (struct snd_cs4231 *chip, void *dma_private_data, int dma);
- int (*release_dma) (struct snd_cs4231 *chip, void *dma_private_data, int dma);
-};
-
-/* exported functions */
-
-void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val);
-unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg);
-void snd_cs4236_ext_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val);
-unsigned char snd_cs4236_ext_in(struct snd_cs4231 *chip, unsigned char reg);
-void snd_cs4231_mce_up(struct snd_cs4231 *chip);
-void snd_cs4231_mce_down(struct snd_cs4231 *chip);
-
-void snd_cs4231_overrange(struct snd_cs4231 *chip);
-
-irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id);
-
-const char *snd_cs4231_chip_id(struct snd_cs4231 *chip);
-
-int snd_cs4231_create(struct snd_card *card,
- unsigned long port,
- unsigned long cport,
- int irq, int dma1, int dma2,
- unsigned short hardware,
- unsigned short hwshare,
- struct snd_cs4231 ** rchip);
-int snd_cs4231_pcm(struct snd_cs4231 * chip, int device, struct snd_pcm **rpcm);
-int snd_cs4231_timer(struct snd_cs4231 * chip, int device, struct snd_timer **rtimer);
-int snd_cs4231_mixer(struct snd_cs4231 * chip);
-
-int snd_cs4236_create(struct snd_card *card,
- unsigned long port,
- unsigned long cport,
- int irq, int dma1, int dma2,
- unsigned short hardware,
- unsigned short hwshare,
- struct snd_cs4231 ** rchip);
-int snd_cs4236_pcm(struct snd_cs4231 * chip, int device, struct snd_pcm **rpcm);
-int snd_cs4236_mixer(struct snd_cs4231 * chip);
-
-/*
- * mixer library
- */
-
-#define CS4231_SINGLE(xname, xindex, reg, shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
- .info = snd_cs4231_info_single, \
- .get = snd_cs4231_get_single, .put = snd_cs4231_put_single, \
- .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-
-int snd_cs4231_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
-int snd_cs4231_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
-int snd_cs4231_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
-
-#define CS4231_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
- .info = snd_cs4231_info_double, \
- .get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \
- .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
-
-int snd_cs4231_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
-int snd_cs4231_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
-int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
-
-#endif /* __SOUND_CS4231_H */
diff --git a/include/sound/jack.h b/include/sound/jack.h
new file mode 100644
index 000000000000..b1b2b8b59adb
--- /dev/null
+++ b/include/sound/jack.h
@@ -0,0 +1,75 @@
+#ifndef __SOUND_JACK_H
+#define __SOUND_JACK_H
+
+/*
+ * Jack abstraction layer
+ *
+ * Copyright 2008 Wolfson Microelectronics plc
+ *
+ *
+ * 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
+
+struct input_dev;
+
+/**
+ * Jack types which can be reported. These values are used as a
+ * bitmask.
+ */
+enum snd_jack_types {
+ SND_JACK_HEADPHONE = 0x0001,
+ SND_JACK_MICROPHONE = 0x0002,
+ SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
+};
+
+struct snd_jack {
+ struct input_dev *input_dev;
+ int registered;
+ int type;
+ const char *id;
+ char name[100];
+};
+
+#ifdef CONFIG_SND_JACK
+
+int snd_jack_new(struct snd_card *card, const char *id, int type,
+ struct snd_jack **jack);
+void snd_jack_set_parent(struct snd_jack *jack, struct device *parent);
+
+void snd_jack_report(struct snd_jack *jack, int status);
+
+#else
+
+static inline int snd_jack_new(struct snd_card *card, const char *id, int type,
+ struct snd_jack **jack)
+{
+ return 0;
+}
+
+static inline void snd_jack_set_parent(struct snd_jack *jack,
+ struct device *parent)
+{
+}
+
+static inline void snd_jack_report(struct snd_jack *jack, int status)
+{
+}
+
+#endif
+
+#endif
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
index ae2921d9ddcc..d787a6b4a101 100644
--- a/include/sound/memalloc.h
+++ b/include/sound/memalloc.h
@@ -65,6 +65,11 @@ struct snd_dma_buffer {
/*
* Scatter-Gather generic device pages
*/
+void *snd_malloc_sgbuf_pages(struct device *device,
+ size_t size, struct snd_dma_buffer *dmab,
+ size_t *res_size);
+int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab);
+
struct snd_sg_page {
void *buf;
dma_addr_t addr;
@@ -92,9 +97,18 @@ static inline unsigned int snd_sgbuf_aligned_pages(size_t size)
*/
static inline dma_addr_t snd_sgbuf_get_addr(struct snd_sg_buf *sgbuf, size_t offset)
{
- return sgbuf->table[offset >> PAGE_SHIFT].addr + offset % PAGE_SIZE;
+ dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr;
+ addr &= PAGE_MASK;
+ return addr + offset % PAGE_SIZE;
}
+/*
+ * return the virtual address at the corresponding offset
+ */
+static inline void *snd_sgbuf_get_ptr(struct snd_sg_buf *sgbuf, size_t offset)
+{
+ return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE;
+}
/* allocate/release a buffer */
int snd_dma_alloc_pages(int type, struct device *dev, size_t size,
diff --git a/include/sound/minors.h b/include/sound/minors.h
index 46bcd2023ed8..a81798ab73ed 100644
--- a/include/sound/minors.h
+++ b/include/sound/minors.h
@@ -21,6 +21,8 @@
*
*/
+#define SNDRV_OS_MINORS 256
+
#define SNDRV_MINOR_DEVICES 32
#define SNDRV_MINOR_CARD(minor) ((minor) >> 5)
#define SNDRV_MINOR_DEVICE(minor) ((minor) & 0x001f)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 51d58ccda2d8..40c5a6fa6bcd 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -25,6 +25,7 @@
#include
#include
+#include
#include
#include
#include
@@ -84,7 +85,11 @@ struct snd_pcm_ops {
*
*/
-#define SNDRV_PCM_DEVICES 8
+#if defined(CONFIG_SND_DYNAMIC_MINORS)
+#define SNDRV_PCM_DEVICES (SNDRV_OS_MINORS-2)
+#else
+#define SNDRV_PCM_DEVICES 8
+#endif
#define SNDRV_PCM_IOCTL1_FALSE ((void *)0)
#define SNDRV_PCM_IOCTL1_TRUE ((void *)1)
@@ -416,7 +421,7 @@ struct snd_pcm_str {
struct snd_pcm {
struct snd_card *card;
struct list_head list;
- unsigned int device; /* device number */
+ int device; /* device number */
unsigned int info_flags;
unsigned short dev_class;
unsigned short dev_subclass;
@@ -969,10 +974,30 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size);
int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream);
-#define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_buffer_p->private_data)
-#define snd_pcm_sgbuf_pages(size) snd_sgbuf_aligned_pages(size)
-#define snd_pcm_sgbuf_get_addr(sgbuf,ofs) snd_sgbuf_get_addr(sgbuf,ofs)
-struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset);
+/*
+ * SG-buffer handling
+ */
+#define snd_pcm_substream_sgbuf(substream) \
+ ((substream)->runtime->dma_buffer_p->private_data)
+
+static inline dma_addr_t
+snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs)
+{
+ struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream);
+ return snd_sgbuf_get_addr(sg, ofs);
+}
+
+static inline void *
+snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs)
+{
+ struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream);
+ return snd_sgbuf_get_ptr(sg, ofs);
+}
+
+struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream,
+ unsigned long offset);
+unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream,
+ unsigned int ofs, unsigned int size);
/* handle mmap counter - PCM mmap callback should handle this counter properly */
static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area)
@@ -1010,4 +1035,6 @@ static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
(IEC958_AES1_CON_PCM_CODER<<8)|\
(IEC958_AES3_CON_FS_48000<<24))
+#define PCM_RUNTIME_CHECK(sub) snd_BUG_ON(!(sub) || !(sub)->runtime)
+
#endif /* __SOUND_PCM_H */
diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h
new file mode 100644
index 000000000000..2fd3d251d9a5
--- /dev/null
+++ b/include/sound/pxa2xx-lib.h
@@ -0,0 +1,45 @@
+#ifndef PXA2XX_LIB_H
+#define PXA2XX_LIB_H
+
+#include
+#include
+
+/* PCM */
+
+struct pxa2xx_pcm_dma_params {
+ char *name; /* stream identifier */
+ u32 dcmd; /* DMA descriptor dcmd field */
+ volatile u32 *drcmr; /* the DMA request channel to use */
+ u32 dev_addr; /* device physical address for DMA */
+};
+
+extern int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params);
+extern int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream);
+extern int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
+extern snd_pcm_uframes_t pxa2xx_pcm_pointer(struct snd_pcm_substream *substream);
+extern int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream);
+extern void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id);
+extern int __pxa2xx_pcm_open(struct snd_pcm_substream *substream);
+extern int __pxa2xx_pcm_close(struct snd_pcm_substream *substream);
+extern int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma);
+extern int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream);
+extern void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm);
+
+/* AC97 */
+
+extern unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg);
+extern void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val);
+
+extern bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97);
+extern bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97);
+extern void pxa2xx_ac97_finish_reset(struct snd_ac97 *ac97);
+
+extern int pxa2xx_ac97_hw_suspend(void);
+extern int pxa2xx_ac97_hw_resume(void);
+
+extern int pxa2xx_ac97_hw_probe(struct platform_device *dev);
+extern void pxa2xx_ac97_hw_remove(struct platform_device *dev);
+
+#endif
diff --git a/include/sound/sb.h b/include/sound/sb.h
index d0c9ed3546c8..85f93c5fe1e4 100644
--- a/include/sound/sb.h
+++ b/include/sound/sb.h
@@ -240,11 +240,15 @@ struct snd_sb {
#define SB_DT019X_CAP_MAIN 0x07
#define SB_ALS4000_MONO_IO_CTRL 0x4b
+#define SB_ALS4000_OUT_MIXER_CTRL_2 0x4c
#define SB_ALS4000_MIC_IN_GAIN 0x4d
+#define SB_ALS4000_ANALOG_REFRNC_VOLT_CTRL 0x4e
#define SB_ALS4000_FMDAC 0x4f
#define SB_ALS4000_3D_SND_FX 0x50
#define SB_ALS4000_3D_TIME_DELAY 0x51
#define SB_ALS4000_3D_AUTO_MUTE 0x52
+#define SB_ALS4000_ANALOG_BLOCK_CTRL 0x53
+#define SB_ALS4000_3D_DELAYLINE_PATTERN 0x54
#define SB_ALS4000_QSOUND 0xdb
/* IRQ setting bitmap */
@@ -257,6 +261,7 @@ struct snd_sb {
#define SB_IRQTYPE_8BIT 0x01
#define SB_IRQTYPE_16BIT 0x02
#define SB_IRQTYPE_MPUIN 0x04
+#define ALS4K_IRQTYPE_CR1E_DMA 0x20
/* DMA setting bitmap */
#define SB_DMASETUP_DMA0 0x01
diff --git a/include/sound/snd_wavefront.h b/include/sound/snd_wavefront.h
index 9688d4be918e..fa149ca77e4b 100644
--- a/include/sound/snd_wavefront.h
+++ b/include/sound/snd_wavefront.h
@@ -1,7 +1,6 @@
#ifndef __SOUND_SND_WAVEFRONT_H__
#define __SOUND_SND_WAVEFRONT_H__
-#include "cs4231.h"
#include "mpu401.h"
#include "hwdep.h"
#include "rawmidi.h"
diff --git a/include/sound/soc-of-simple.h b/include/sound/soc-of-simple.h
new file mode 100644
index 000000000000..a064e1934a56
--- /dev/null
+++ b/include/sound/soc-of-simple.h
@@ -0,0 +1,25 @@
+/*
+ * OF helpers for ALSA SoC
+ *
+ * Copyright (C) 2008, Secret Lab Technologies Ltd.
+ */
+
+#ifndef _INCLUDE_SOC_OF_H_
+#define _INCLUDE_SOC_OF_H_
+
+#if defined(CONFIG_SND_SOC_OF_SIMPLE) || defined(CONFIG_SND_SOC_OF_SIMPLE_MODULE)
+
+#include
+#include
+
+int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev,
+ void *codec_data, struct snd_soc_dai *dai,
+ struct device_node *node);
+
+int of_snd_soc_register_platform(struct snd_soc_platform *platform,
+ struct device_node *node,
+ struct snd_soc_dai *cpu_dai);
+
+#endif
+
+#endif /* _INCLUDE_SOC_OF_H_ */
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 1890d87c5204..a1e0357a84d7 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -26,10 +26,12 @@
/*
* Convenience kcontrol builders
*/
-#define SOC_SINGLE_VALUE(reg, shift, max, invert) ((reg) | ((shift) << 8) |\
- ((shift) << 12) | ((max) << 16) | ((invert) << 24))
-#define SOC_SINGLE_VALUE_EXT(reg, max, invert) ((reg) | ((max) << 16) |\
- ((invert) << 31))
+#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
+ ((unsigned long)&(struct soc_mixer_control) \
+ {.reg = xreg, .shift = xshift, .max = xmax, .invert = xinvert})
+#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
+ ((unsigned long)&(struct soc_mixer_control) \
+ {.reg = xreg, .max = xmax, .invert = xinvert})
#define SOC_SINGLE(xname, reg, shift, max, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
@@ -43,64 +45,68 @@
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
.put = snd_soc_put_volsw, \
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
-#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
+#define SOC_DOUBLE(xname, xreg, shift_left, shift_right, xmax, xinvert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
.put = snd_soc_put_volsw, \
- .private_value = (reg) | ((shift_left) << 8) | \
- ((shift_right) << 12) | ((max) << 16) | ((invert) << 24) }
-#define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, max, invert) \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = xreg, .shift = shift_left, .rshift = shift_right, \
+ .max = xmax, .invert = xinvert} }
+#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.info = snd_soc_info_volsw_2r, \
.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
- .private_value = (reg_left) | ((shift) << 8) | \
- ((max) << 12) | ((invert) << 20) | ((reg_right) << 24) }
-#define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
+ .max = xmax, .invert = xinvert} }
+#define SOC_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
.put = snd_soc_put_volsw, \
- .private_value = (reg) | ((shift_left) << 8) | \
- ((shift_right) << 12) | ((max) << 16) | ((invert) << 24) }
-#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, shift, max, invert, tlv_array) \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
+ .max = xmax, .invert = xinvert} }
+#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw_2r, \
.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
- .private_value = (reg_left) | ((shift) << 8) | \
- ((max) << 12) | ((invert) << 20) | ((reg_right) << 24) }
-#define SOC_DOUBLE_S8_TLV(xname, reg, min, max, tlv_array) \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
+ .max = xmax, .invert = xinvert} }
+#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw_s8, .get = snd_soc_get_volsw_s8, \
.put = snd_soc_put_volsw_s8, \
- .private_value = (reg) | (((signed char)max) << 16) | \
- (((signed char)min) << 24) }
-#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = xreg, .min = xmin, .max = xmax} }
+#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \
{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
- .mask = xmask, .texts = xtexts }
-#define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \
- SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts)
-#define SOC_ENUM_SINGLE_EXT(xmask, xtexts) \
-{ .mask = xmask, .texts = xtexts }
+ .max = xmax, .texts = xtexts }
+#define SOC_ENUM_SINGLE(xreg, xshift, xmax, xtexts) \
+ SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts)
+#define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \
+{ .max = xmax, .texts = xtexts }
#define SOC_ENUM(xname, xenum) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
.info = snd_soc_info_enum_double, \
.get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \
.private_value = (unsigned long)&xenum }
-#define SOC_SINGLE_EXT(xname, xreg, xshift, xmask, xinvert,\
+#define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\
xhandler_get, xhandler_put) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
.get = xhandler_get, .put = xhandler_put, \
- .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmask, xinvert) }
-#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmask, xinvert,\
+ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
+#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
xhandler_get, xhandler_put, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
@@ -108,7 +114,7 @@
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw, \
.get = xhandler_get, .put = xhandler_put, \
- .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmask, xinvert) }
+ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
#define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_bool_ext, \
@@ -410,6 +416,8 @@ struct snd_soc_codec {
void *control_data; /* codec control (i2c/3wire) data */
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
+ int (*display_register)(struct snd_soc_codec *, char *,
+ size_t, unsigned int);
hw_write_t hw_write;
hw_read_t hw_read;
void *reg_cache;
@@ -516,13 +524,19 @@ struct snd_soc_pcm_runtime {
struct snd_soc_device *socdev;
};
+/* mixer control */
+struct soc_mixer_control {
+ int min, max;
+ unsigned int reg, rreg, shift, rshift, invert;
+};
+
/* enumerated kcontrol */
struct soc_enum {
unsigned short reg;
unsigned short reg2;
unsigned char shift_l;
unsigned char shift_r;
- unsigned int mask;
+ unsigned int max;
const char **texts;
void *dapm;
};
diff --git a/include/sound/version.h b/include/sound/version.h
index 6b78aff273a8..4aafeda88634 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h */
-#define CONFIG_SND_VERSION "1.0.17"
+#define CONFIG_SND_VERSION "1.0.18rc3"
#define CONFIG_SND_DATE ""
diff --git a/include/sound/vx_core.h b/include/sound/vx_core.h
index 4830651cc4cf..5456343ebe4c 100644
--- a/include/sound/vx_core.h
+++ b/include/sound/vx_core.h
@@ -235,37 +235,31 @@ irqreturn_t snd_vx_irq_handler(int irq, void *dev);
*/
static inline int vx_test_and_ack(struct vx_core *chip)
{
- snd_assert(chip->ops->test_and_ack, return -ENXIO);
return chip->ops->test_and_ack(chip);
}
static inline void vx_validate_irq(struct vx_core *chip, int enable)
{
- snd_assert(chip->ops->validate_irq, return);
chip->ops->validate_irq(chip, enable);
}
static inline unsigned char snd_vx_inb(struct vx_core *chip, int reg)
{
- snd_assert(chip->ops->in8, return 0);
return chip->ops->in8(chip, reg);
}
static inline unsigned int snd_vx_inl(struct vx_core *chip, int reg)
{
- snd_assert(chip->ops->in32, return 0);
return chip->ops->in32(chip, reg);
}
static inline void snd_vx_outb(struct vx_core *chip, int reg, unsigned char val)
{
- snd_assert(chip->ops->out8, return);
chip->ops->out8(chip, reg, val);
}
static inline void snd_vx_outl(struct vx_core *chip, int reg, unsigned int val)
{
- snd_assert(chip->ops->out32, return);
chip->ops->out32(chip, reg, val);
}
@@ -276,7 +270,6 @@ static inline void snd_vx_outl(struct vx_core *chip, int reg, unsigned int val)
static inline void vx_reset_dsp(struct vx_core *chip)
{
- snd_assert(chip->ops->reset_dsp, return);
chip->ops->reset_dsp(chip);
}
@@ -304,14 +297,12 @@ int snd_vx_check_reg_bit(struct vx_core *chip, int reg, int mask, int bit, int t
static inline void vx_pseudo_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
struct vx_pipe *pipe, int count)
{
- snd_assert(chip->ops->dma_write, return);
chip->ops->dma_write(chip, runtime, pipe, count);
}
static inline void vx_pseudo_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
struct vx_pipe *pipe, int count)
{
- snd_assert(chip->ops->dma_read, return);
chip->ops->dma_read(chip, runtime, pipe, count);
}
diff --git a/include/sound/wss.h b/include/sound/wss.h
new file mode 100644
index 000000000000..fd01f22825cd
--- /dev/null
+++ b/include/sound/wss.h
@@ -0,0 +1,235 @@
+#ifndef __SOUND_WSS_H
+#define __SOUND_WSS_H
+
+/*
+ * Copyright (c) by Jaroslav Kysela
+ * Definitions for CS4231 & InterWave chips & compatible chips
+ *
+ *
+ * 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 "control.h"
+#include "pcm.h"
+#include "timer.h"
+
+#include "cs4231-regs.h"
+
+/* defines for codec.mode */
+
+#define WSS_MODE_NONE 0x0000
+#define WSS_MODE_PLAY 0x0001
+#define WSS_MODE_RECORD 0x0002
+#define WSS_MODE_TIMER 0x0004
+#define WSS_MODE_OPEN (WSS_MODE_PLAY|WSS_MODE_RECORD|WSS_MODE_TIMER)
+
+/* defines for codec.hardware */
+
+#define WSS_HW_DETECT 0x0000 /* let CS4231 driver detect chip */
+#define WSS_HW_DETECT3 0x0001 /* allow mode 3 */
+#define WSS_HW_TYPE_MASK 0xff00 /* type mask */
+#define WSS_HW_CS4231_MASK 0x0100 /* CS4231 serie */
+#define WSS_HW_CS4231 0x0100 /* CS4231 chip */
+#define WSS_HW_CS4231A 0x0101 /* CS4231A chip */
+#define WSS_HW_AD1845 0x0102 /* AD1845 chip */
+#define WSS_HW_CS4232_MASK 0x0200 /* CS4232 serie (has control ports) */
+#define WSS_HW_CS4232 0x0200 /* CS4232 */
+#define WSS_HW_CS4232A 0x0201 /* CS4232A */
+#define WSS_HW_CS4236 0x0202 /* CS4236 */
+#define WSS_HW_CS4236B_MASK 0x0400 /* CS4236B serie (has extended control regs) */
+#define WSS_HW_CS4235 0x0400 /* CS4235 - Crystal Clear (tm) stereo enhancement */
+#define WSS_HW_CS4236B 0x0401 /* CS4236B */
+#define WSS_HW_CS4237B 0x0402 /* CS4237B - SRS 3D */
+#define WSS_HW_CS4238B 0x0403 /* CS4238B - QSOUND 3D */
+#define WSS_HW_CS4239 0x0404 /* CS4239 - Crystal Clear (tm) stereo enhancement */
+#define WSS_HW_AD1848_MASK 0x0800 /* AD1848 serie (half duplex) */
+#define WSS_HW_AD1847 0x0801 /* AD1847 chip */
+#define WSS_HW_AD1848 0x0802 /* AD1848 chip */
+#define WSS_HW_CS4248 0x0803 /* CS4248 chip */
+#define WSS_HW_CMI8330 0x0804 /* CMI8330 chip */
+#define WSS_HW_THINKPAD 0x0805 /* Thinkpad 360/750/755 */
+/* compatible, but clones */
+#define WSS_HW_INTERWAVE 0x1000 /* InterWave chip */
+#define WSS_HW_OPL3SA2 0x1101 /* OPL3-SA2 chip, similar to cs4231 */
+#define WSS_HW_OPTI93X 0x1102 /* Opti 930/931/933 */
+
+/* defines for codec.hwshare */
+#define WSS_HWSHARE_IRQ (1<<0)
+#define WSS_HWSHARE_DMA1 (1<<1)
+#define WSS_HWSHARE_DMA2 (1<<2)
+
+/* IBM Thinkpad specific stuff */
+#define AD1848_THINKPAD_CTL_PORT1 0x15e8
+#define AD1848_THINKPAD_CTL_PORT2 0x15e9
+#define AD1848_THINKPAD_CS4248_ENABLE_BIT 0x02
+
+struct snd_wss {
+ unsigned long port; /* base i/o port */
+ struct resource *res_port;
+ unsigned long cport; /* control base i/o port (CS4236) */
+ struct resource *res_cport;
+ int irq; /* IRQ line */
+ int dma1; /* playback DMA */
+ int dma2; /* record DMA */
+ unsigned short version; /* version of CODEC chip */
+ unsigned short mode; /* see to WSS_MODE_XXXX */
+ unsigned short hardware; /* see to WSS_HW_XXXX */
+ unsigned short hwshare; /* shared resources */
+ unsigned short single_dma:1, /* forced single DMA mode (GUS 16-bit */
+ /* daughter board) or dma1 == dma2 */
+ ebus_flag:1, /* SPARC: EBUS present */
+ thinkpad_flag:1; /* Thinkpad CS4248 needs extra help */
+
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
+ struct snd_timer *timer;
+
+ unsigned char image[32]; /* registers image */
+ unsigned char eimage[32]; /* extended registers image */
+ unsigned char cimage[16]; /* control registers image */
+ int mce_bit;
+ int calibrate_mute;
+ int sw_3d_bit;
+ unsigned int p_dma_size;
+ unsigned int c_dma_size;
+
+ spinlock_t reg_lock;
+ struct mutex mce_mutex;
+ struct mutex open_mutex;
+
+ int (*rate_constraint) (struct snd_pcm_runtime *runtime);
+ void (*set_playback_format) (struct snd_wss *chip,
+ struct snd_pcm_hw_params *hw_params,
+ unsigned char pdfr);
+ void (*set_capture_format) (struct snd_wss *chip,
+ struct snd_pcm_hw_params *hw_params,
+ unsigned char cdfr);
+ void (*trigger) (struct snd_wss *chip, unsigned int what, int start);
+#ifdef CONFIG_PM
+ void (*suspend) (struct snd_wss *chip);
+ void (*resume) (struct snd_wss *chip);
+#endif
+ void *dma_private_data;
+ int (*claim_dma) (struct snd_wss *chip,
+ void *dma_private_data, int dma);
+ int (*release_dma) (struct snd_wss *chip,
+ void *dma_private_data, int dma);
+};
+
+/* exported functions */
+
+void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char val);
+unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg);
+void snd_cs4236_ext_out(struct snd_wss *chip,
+ unsigned char reg, unsigned char val);
+unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg);
+void snd_wss_mce_up(struct snd_wss *chip);
+void snd_wss_mce_down(struct snd_wss *chip);
+
+void snd_wss_overrange(struct snd_wss *chip);
+
+irqreturn_t snd_wss_interrupt(int irq, void *dev_id);
+
+const char *snd_wss_chip_id(struct snd_wss *chip);
+
+int snd_wss_create(struct snd_card *card,
+ unsigned long port,
+ unsigned long cport,
+ int irq, int dma1, int dma2,
+ unsigned short hardware,
+ unsigned short hwshare,
+ struct snd_wss **rchip);
+int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm);
+int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer);
+int snd_wss_mixer(struct snd_wss *chip);
+
+const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction);
+
+int snd_cs4236_create(struct snd_card *card,
+ unsigned long port,
+ unsigned long cport,
+ int irq, int dma1, int dma2,
+ unsigned short hardware,
+ unsigned short hwshare,
+ struct snd_wss **rchip);
+int snd_cs4236_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm);
+int snd_cs4236_mixer(struct snd_wss *chip);
+
+/*
+ * mixer library
+ */
+
+#define WSS_SINGLE(xname, xindex, reg, shift, mask, invert) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = xname, \
+ .index = xindex, \
+ .info = snd_wss_info_single, \
+ .get = snd_wss_get_single, \
+ .put = snd_wss_put_single, \
+ .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
+
+int snd_wss_info_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo);
+int snd_wss_get_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int snd_wss_put_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+
+#define WSS_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = xname, \
+ .index = xindex, \
+ .info = snd_wss_info_double, \
+ .get = snd_wss_get_double, \
+ .put = snd_wss_put_double, \
+ .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
+ (shift_right << 19) | (mask << 24) | (invert << 22) }
+
+#define WSS_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
+ .name = xname, \
+ .index = xindex, \
+ .info = snd_wss_info_single, \
+ .get = snd_wss_get_single, \
+ .put = snd_wss_put_single, \
+ .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
+ .tlv = { .p = (xtlv) } }
+
+#define WSS_DOUBLE_TLV(xname, xindex, left_reg, right_reg, \
+ shift_left, shift_right, mask, invert, xtlv) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
+ .name = xname, \
+ .index = xindex, \
+ .info = snd_wss_info_double, \
+ .get = snd_wss_get_double, \
+ .put = snd_wss_put_double, \
+ .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
+ (shift_right << 19) | (mask << 24) | (invert << 22), \
+ .tlv = { .p = (xtlv) } }
+
+
+int snd_wss_info_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo);
+int snd_wss_get_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int snd_wss_put_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+
+#endif /* __SOUND_WSS_H */
diff --git a/sound/Kconfig b/sound/Kconfig
index 8ebf512ced6c..200aca1faa71 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -28,6 +28,10 @@ menuconfig SOUND
if SOUND
+config SOUND_OSS_CORE
+ bool
+ default n
+
source "sound/oss/dmasound/Kconfig"
if !M68K
@@ -80,6 +84,7 @@ endif # SND
menuconfig SOUND_PRIME
tristate "Open Sound System (DEPRECATED)"
+ select SOUND_OSS_CORE
help
Say 'Y' or 'M' to enable Open Sound System drivers.
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c
index 7a16a3331f7e..6c515b2b8bbd 100644
--- a/sound/aoa/codecs/snd-aoa-codec-tas.c
+++ b/sound/aoa/codecs/snd-aoa-codec-tas.c
@@ -654,15 +654,13 @@ static struct snd_kcontrol_new bass_control = {
static struct transfer_info tas_transfers[] = {
{
/* input */
- .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE |
- SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE,
+ .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S24_BE,
.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
.transfer_in = 1,
},
{
/* output */
- .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE |
- SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE,
+ .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S24_BE,
.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
.transfer_in = 0,
},
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig
index 351e19ea3785..f8e6de48d816 100644
--- a/sound/arm/Kconfig
+++ b/sound/arm/Kconfig
@@ -32,11 +32,20 @@ config SND_PXA2XX_PCM
tristate
select SND_PCM
+config SND_PXA2XX_LIB
+ tristate
+ select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97
+
+config SND_PXA2XX_LIB_AC97
+ bool
+
config SND_PXA2XX_AC97
tristate "AC97 driver for the Intel PXA2xx chip"
depends on ARCH_PXA
select SND_PXA2XX_PCM
select SND_AC97_CODEC
+ select SND_PXA2XX_LIB
+ select SND_PXA2XX_LIB_AC97
help
Say Y or M if you want to support any AC97 codec attached to
the PXA2xx AC97 interface.
diff --git a/sound/arm/Makefile b/sound/arm/Makefile
index 4ef6dd00c6ee..2054de11de8a 100644
--- a/sound/arm/Makefile
+++ b/sound/arm/Makefile
@@ -11,5 +11,9 @@ snd-aaci-objs := aaci.o devdma.o
obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o
snd-pxa2xx-pcm-objs := pxa2xx-pcm.o
+obj-$(CONFIG_SND_PXA2XX_LIB) += snd-pxa2xx-lib.o
+snd-pxa2xx-lib-y := pxa2xx-pcm-lib.o
+snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o
+
obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o
snd-pxa2xx-ac97-objs := pxa2xx-ac97.o
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index b0a474494966..89096e811a4b 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -999,7 +999,7 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
THIS_MODULE, sizeof(struct aaci));
if (card == NULL)
- return ERR_PTR(-ENOMEM);
+ return NULL;
card->private_free = aaci_free_card;
@@ -1083,8 +1083,8 @@ static int __devinit aaci_probe(struct amba_device *dev, void *id)
return ret;
aaci = aaci_init_card(dev);
- if (IS_ERR(aaci)) {
- ret = PTR_ERR(aaci);
+ if (!aaci) {
+ ret = -ENOMEM;
goto out;
}
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
new file mode 100644
index 000000000000..99026dfb81ea
--- /dev/null
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -0,0 +1,384 @@
+/*
+ * Based on sound/arm/pxa2xx-ac97.c and sound/soc/pxa/pxa2xx-ac97.c
+ * which contain:
+ *
+ * Author: Nicolas Pitre
+ * Created: Dec 02, 2004
+ * Copyright: MontaVista Software Inc.
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+static DEFINE_MUTEX(car_mutex);
+static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
+static volatile long gsr_bits;
+static struct clk *ac97_clk;
+static struct clk *ac97conf_clk;
+
+/*
+ * Beware PXA27x bugs:
+ *
+ * o Slot 12 read from modem space will hang controller.
+ * o CDONE, SDONE interrupt fails after any slot 12 IO.
+ *
+ * We therefore have an hybrid approach for waiting on SDONE (interrupt or
+ * 1 jiffy timeout if interrupt never comes).
+ */
+
+unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
+{
+ unsigned short val = -1;
+ volatile u32 *reg_addr;
+
+ mutex_lock(&car_mutex);
+
+ /* set up primary or secondary codec space */
+ if ((cpu_is_pxa21x() || cpu_is_pxa25x()) && reg == AC97_GPIO_STATUS)
+ reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
+ else
+ reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
+ reg_addr += (reg >> 1);
+
+ /* start read access across the ac97 link */
+ GSR = GSR_CDONE | GSR_SDONE;
+ gsr_bits = 0;
+ val = *reg_addr;
+ if (reg == AC97_GPIO_STATUS)
+ goto out;
+ if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 &&
+ !((GSR | gsr_bits) & GSR_SDONE)) {
+ printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",
+ __func__, reg, GSR | gsr_bits);
+ val = -1;
+ goto out;
+ }
+
+ /* valid data now */
+ GSR = GSR_CDONE | GSR_SDONE;
+ gsr_bits = 0;
+ val = *reg_addr;
+ /* but we've just started another cycle... */
+ wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
+
+out: mutex_unlock(&car_mutex);
+ return val;
+}
+EXPORT_SYMBOL_GPL(pxa2xx_ac97_read);
+
+void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+ unsigned short val)
+{
+ volatile u32 *reg_addr;
+
+ mutex_lock(&car_mutex);
+
+ /* set up primary or secondary codec space */
+ if ((cpu_is_pxa21x() || cpu_is_pxa25x()) && reg == AC97_GPIO_STATUS)
+ reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
+ else
+ reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
+ reg_addr += (reg >> 1);
+
+ GSR = GSR_CDONE | GSR_SDONE;
+ gsr_bits = 0;
+ *reg_addr = val;
+ if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 &&
+ !((GSR | gsr_bits) & GSR_CDONE))
+ printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n",
+ __func__, reg, GSR | gsr_bits);
+
+ mutex_unlock(&car_mutex);
+}
+EXPORT_SYMBOL_GPL(pxa2xx_ac97_write);
+
+#ifdef CONFIG_PXA25x
+static inline void pxa_ac97_warm_pxa25x(void)
+{
+ gsr_bits = 0;
+
+ GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
+ wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
+}
+
+static inline void pxa_ac97_cold_pxa25x(void)
+{
+ GCR &= GCR_COLD_RST; /* clear everything but nCRST */
+ GCR &= ~GCR_COLD_RST; /* then assert nCRST */
+
+ gsr_bits = 0;
+
+ GCR = GCR_COLD_RST;
+ GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
+ wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
+}
+#endif
+
+#ifdef CONFIG_PXA27x
+static inline void pxa_ac97_warm_pxa27x(void)
+{
+ gsr_bits = 0;
+
+ /* warm reset broken on Bulverde,
+ so manually keep AC97 reset high */
+ pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH);
+ udelay(10);
+ GCR |= GCR_WARM_RST;
+ pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+ udelay(500);
+}
+
+static inline void pxa_ac97_cold_pxa27x(void)
+{
+ GCR &= GCR_COLD_RST; /* clear everything but nCRST */
+ GCR &= ~GCR_COLD_RST; /* then assert nCRST */
+
+ gsr_bits = 0;
+
+ /* PXA27x Developers Manual section 13.5.2.2.1 */
+ clk_enable(ac97conf_clk);
+ udelay(5);
+ clk_disable(ac97conf_clk);
+ GCR = GCR_COLD_RST;
+ udelay(50);
+}
+#endif
+
+#ifdef CONFIG_PXA3xx
+static inline void pxa_ac97_warm_pxa3xx(void)
+{
+ int timeout = 100;
+
+ gsr_bits = 0;
+
+ /* Can't use interrupts */
+ GCR |= GCR_WARM_RST;
+ while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
+ mdelay(1);
+}
+
+static inline void pxa_ac97_cold_pxa3xx(void)
+{
+ int timeout = 1000;
+
+ /* Hold CLKBPB for 100us */
+ GCR = 0;
+ GCR = GCR_CLKBPB;
+ udelay(100);
+ GCR = 0;
+
+ GCR &= GCR_COLD_RST; /* clear everything but nCRST */
+ GCR &= ~GCR_COLD_RST; /* then assert nCRST */
+
+ gsr_bits = 0;
+
+ /* Can't use interrupts on PXA3xx */
+ GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
+
+ GCR = GCR_WARM_RST | GCR_COLD_RST;
+ while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
+ mdelay(10);
+}
+#endif
+
+bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97)
+{
+#ifdef CONFIG_PXA25x
+ if (cpu_is_pxa21x() || cpu_is_pxa25x())
+ pxa_ac97_warm_pxa25x();
+ else
+#endif
+#ifdef CONFIG_PXA27x
+ if (cpu_is_pxa27x())
+ pxa_ac97_warm_pxa27x();
+ else
+#endif
+#ifdef CONFIG_PXA3xx
+ if (cpu_is_pxa3xx())
+ pxa_ac97_warm_pxa3xx();
+ else
+#endif
+ BUG();
+
+ if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) {
+ printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
+ __func__, gsr_bits);
+
+ return false;
+ }
+
+ return true;
+}
+EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_warm_reset);
+
+bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97)
+{
+#ifdef CONFIG_PXA25x
+ if (cpu_is_pxa21x() || cpu_is_pxa25x())
+ pxa_ac97_cold_pxa25x();
+ else
+#endif
+#ifdef CONFIG_PXA27x
+ if (cpu_is_pxa27x())
+ pxa_ac97_cold_pxa27x();
+ else
+#endif
+#ifdef CONFIG_PXA3xx
+ if (cpu_is_pxa3xx())
+ pxa_ac97_cold_pxa3xx();
+ else
+#endif
+ BUG();
+
+ if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) {
+ printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
+ __func__, gsr_bits);
+
+ return false;
+ }
+
+ return true;
+}
+EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_cold_reset);
+
+
+void pxa2xx_ac97_finish_reset(struct snd_ac97 *ac97)
+{
+ GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
+ GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
+}
+EXPORT_SYMBOL_GPL(pxa2xx_ac97_finish_reset);
+
+static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
+{
+ long status;
+
+ status = GSR;
+ if (status) {
+ GSR = status;
+ gsr_bits |= status;
+ wake_up(&gsr_wq);
+
+ /* Although we don't use those we still need to clear them
+ since they tend to spuriously trigger when MMC is used
+ (hardware bug? go figure)... */
+ if (cpu_is_pxa27x()) {
+ MISR = MISR_EOC;
+ PISR = PISR_EOC;
+ MCSR = MCSR_EOC;
+ }
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+#ifdef CONFIG_PM
+int pxa2xx_ac97_hw_suspend(void)
+{
+ GCR |= GCR_ACLINK_OFF;
+ clk_disable(ac97_clk);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend);
+
+int pxa2xx_ac97_hw_resume(void)
+{
+ if (cpu_is_pxa21x() || cpu_is_pxa25x() || cpu_is_pxa27x()) {
+ pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
+ pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
+ pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
+ pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
+ }
+ if (cpu_is_pxa27x()) {
+ /* Use GPIO 113 as AC97 Reset on Bulverde */
+ pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+ }
+ clk_enable(ac97_clk);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
+#endif
+
+int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
+{
+ int ret;
+
+ ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL);
+ if (ret < 0)
+ goto err;
+
+ if (cpu_is_pxa21x() || cpu_is_pxa25x() || cpu_is_pxa27x()) {
+ pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
+ pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
+ pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
+ pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
+ }
+
+ if (cpu_is_pxa27x()) {
+ /* Use GPIO 113 as AC97 Reset on Bulverde */
+ pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+ ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
+ if (IS_ERR(ac97conf_clk)) {
+ ret = PTR_ERR(ac97conf_clk);
+ ac97conf_clk = NULL;
+ goto err_irq;
+ }
+ }
+
+ ac97_clk = clk_get(&dev->dev, "AC97CLK");
+ if (IS_ERR(ac97_clk)) {
+ ret = PTR_ERR(ac97_clk);
+ ac97_clk = NULL;
+ goto err_irq;
+ }
+
+ return clk_enable(ac97_clk);
+
+err_irq:
+ GCR |= GCR_ACLINK_OFF;
+ if (ac97conf_clk) {
+ clk_put(ac97conf_clk);
+ ac97conf_clk = NULL;
+ }
+ free_irq(IRQ_AC97, NULL);
+err:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe);
+
+void pxa2xx_ac97_hw_remove(struct platform_device *dev)
+{
+ GCR |= GCR_ACLINK_OFF;
+ free_irq(IRQ_AC97, NULL);
+ if (ac97conf_clk) {
+ clk_put(ac97conf_clk);
+ ac97conf_clk = NULL;
+ }
+ clk_disable(ac97_clk);
+ clk_put(ac97_clk);
+ ac97_clk = NULL;
+}
+EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_remove);
+
+MODULE_AUTHOR("Nicolas Pitre");
+MODULE_DESCRIPTION("Intel/Marvell PXA sound library");
+MODULE_LICENSE("GPL");
+
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 199cca3366df..cba71d867542 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -12,198 +12,27 @@
#include
#include
-#include
#include
-#include
-#include
-#include
-#include
#include
#include
#include
#include
+#include
-#include
-#include
#include
#include
-#include
#include
#include "pxa2xx-pcm.h"
-
-static DEFINE_MUTEX(car_mutex);
-static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
-static volatile long gsr_bits;
-static struct clk *ac97_clk;
-#ifdef CONFIG_PXA27x
-static struct clk *ac97conf_clk;
-#endif
-
-/*
- * Beware PXA27x bugs:
- *
- * o Slot 12 read from modem space will hang controller.
- * o CDONE, SDONE interrupt fails after any slot 12 IO.
- *
- * We therefore have an hybrid approach for waiting on SDONE (interrupt or
- * 1 jiffy timeout if interrupt never comes).
- */
-
-static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
-{
- unsigned short val = -1;
- volatile u32 *reg_addr;
-
- mutex_lock(&car_mutex);
-
- /* set up primary or secondary codec space */
- reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE;
- reg_addr += (reg >> 1);
-
- /* start read access across the ac97 link */
- GSR = GSR_CDONE | GSR_SDONE;
- gsr_bits = 0;
- val = *reg_addr;
- if (reg == AC97_GPIO_STATUS)
- goto out;
- if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 &&
- !((GSR | gsr_bits) & GSR_SDONE)) {
- printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",
- __func__, reg, GSR | gsr_bits);
- val = -1;
- goto out;
- }
-
- /* valid data now */
- GSR = GSR_CDONE | GSR_SDONE;
- gsr_bits = 0;
- val = *reg_addr;
- /* but we've just started another cycle... */
- wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
-
-out: mutex_unlock(&car_mutex);
- return val;
-}
-
-static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
-{
- volatile u32 *reg_addr;
-
- mutex_lock(&car_mutex);
-
- /* set up primary or secondary codec space */
- reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE;
- reg_addr += (reg >> 1);
-
- GSR = GSR_CDONE | GSR_SDONE;
- gsr_bits = 0;
- *reg_addr = val;
- if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 &&
- !((GSR | gsr_bits) & GSR_CDONE))
- printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n",
- __func__, reg, GSR | gsr_bits);
-
- mutex_unlock(&car_mutex);
-}
-
static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
{
- /* First, try cold reset */
-#ifdef CONFIG_PXA3xx
- int timeout;
-
- /* Hold CLKBPB for 100us */
- GCR = 0;
- GCR = GCR_CLKBPB;
- udelay(100);
- GCR = 0;
-#endif
-
- GCR &= GCR_COLD_RST; /* clear everything but nCRST */
- GCR &= ~GCR_COLD_RST; /* then assert nCRST */
-
- gsr_bits = 0;
-#ifdef CONFIG_PXA27x
- /* PXA27x Developers Manual section 13.5.2.2.1 */
- clk_enable(ac97conf_clk);
- udelay(5);
- clk_disable(ac97conf_clk);
- GCR = GCR_COLD_RST;
- udelay(50);
-#elif defined(CONFIG_PXA3xx)
- timeout = 1000;
- /* Can't use interrupts on PXA3xx */
- GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
-
- GCR = GCR_WARM_RST | GCR_COLD_RST;
- while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
- mdelay(10);
-#else
- GCR = GCR_COLD_RST;
- GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
- wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
-#endif
-
- if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) {
- printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
- __func__, gsr_bits);
-
- /* let's try warm reset */
- gsr_bits = 0;
-#ifdef CONFIG_PXA27x
- /* warm reset broken on Bulverde,
- so manually keep AC97 reset high */
- pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH);
- udelay(10);
- GCR |= GCR_WARM_RST;
- pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
- udelay(500);
-#elif defined(CONFIG_PXA3xx)
- timeout = 100;
- /* Can't use interrupts */
- GCR |= GCR_WARM_RST;
- while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
- mdelay(1);
-#else
- GCR |= GCR_WARM_RST|GCR_PRIRDY_IEN|GCR_SECRDY_IEN;
- wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
-#endif
-
- if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
- printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
- __func__, gsr_bits);
+ if (!pxa2xx_ac97_try_cold_reset(ac97)) {
+ pxa2xx_ac97_try_warm_reset(ac97);
}
- GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
- GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
-}
-
-static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
-{
- long status;
-
- status = GSR;
- if (status) {
- GSR = status;
- gsr_bits |= status;
- wake_up(&gsr_wq);
-
-#ifdef CONFIG_PXA27x
- /* Although we don't use those we still need to clear them
- since they tend to spuriously trigger when MMC is used
- (hardware bug? go figure)... */
- MISR = MISR_EOC;
- PISR = PISR_EOC;
- MCSR = MCSR_EOC;
-#endif
-
- return IRQ_HANDLED;
- }
-
- return IRQ_NONE;
+ pxa2xx_ac97_finish_reset(ac97);
}
static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
@@ -288,17 +117,19 @@ static int pxa2xx_ac97_do_suspend(struct snd_card *card, pm_message_t state)
snd_ac97_suspend(pxa2xx_ac97_ac97);
if (platform_ops && platform_ops->suspend)
platform_ops->suspend(platform_ops->priv);
- GCR |= GCR_ACLINK_OFF;
- clk_disable(ac97_clk);
- return 0;
+ return pxa2xx_ac97_hw_suspend();
}
static int pxa2xx_ac97_do_resume(struct snd_card *card)
{
pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
+ int rc;
+
+ rc = pxa2xx_ac97_hw_resume();
+ if (rc)
+ return rc;
- clk_enable(ac97_clk);
if (platform_ops && platform_ops->resume)
platform_ops->resume(platform_ops->priv);
snd_ac97_resume(pxa2xx_ac97_ac97);
@@ -354,40 +185,17 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
if (ret)
goto err;
- ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL);
- if (ret < 0)
+ ret = pxa2xx_ac97_hw_probe(dev);
+ if (ret)
goto err;
- pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
- pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
- pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
- pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
-#ifdef CONFIG_PXA27x
- /* Use GPIO 113 as AC97 Reset on Bulverde */
- pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
- ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
- if (IS_ERR(ac97conf_clk)) {
- ret = PTR_ERR(ac97conf_clk);
- ac97conf_clk = NULL;
- goto err;
- }
-#endif
-
- ac97_clk = clk_get(&dev->dev, "AC97CLK");
- if (IS_ERR(ac97_clk)) {
- ret = PTR_ERR(ac97_clk);
- ac97_clk = NULL;
- goto err;
- }
- clk_enable(ac97_clk);
-
ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus);
if (ret)
- goto err;
+ goto err_remove;
memset(&ac97_template, 0, sizeof(ac97_template));
ret = snd_ac97_mixer(ac97_bus, &ac97_template, &pxa2xx_ac97_ac97);
if (ret)
- goto err;
+ goto err_remove;
snprintf(card->shortname, sizeof(card->shortname),
"%s", snd_ac97_get_short_name(pxa2xx_ac97_ac97));
@@ -401,22 +209,11 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
return 0;
}
- err:
+err_remove:
+ pxa2xx_ac97_hw_remove(dev);
+err:
if (card)
snd_card_free(card);
- if (ac97_clk) {
- GCR |= GCR_ACLINK_OFF;
- free_irq(IRQ_AC97, NULL);
- clk_disable(ac97_clk);
- clk_put(ac97_clk);
- ac97_clk = NULL;
- }
-#ifdef CONFIG_PXA27x
- if (ac97conf_clk) {
- clk_put(ac97conf_clk);
- ac97conf_clk = NULL;
- }
-#endif
return ret;
}
@@ -427,15 +224,7 @@ static int __devexit pxa2xx_ac97_remove(struct platform_device *dev)
if (card) {
snd_card_free(card);
platform_set_drvdata(dev, NULL);
- GCR |= GCR_ACLINK_OFF;
- free_irq(IRQ_AC97, NULL);
- clk_disable(ac97_clk);
- clk_put(ac97_clk);
- ac97_clk = NULL;
-#ifdef CONFIG_PXA27x
- clk_put(ac97conf_clk);
- ac97conf_clk = NULL;
-#endif
+ pxa2xx_ac97_hw_remove(dev);
}
return 0;
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c
new file mode 100644
index 000000000000..1c93eb77cb99
--- /dev/null
+++ b/sound/arm/pxa2xx-pcm-lib.c
@@ -0,0 +1,278 @@
+/*
+ * 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.
+ */
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "pxa2xx-pcm.h"
+
+static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .period_bytes_min = 32,
+ .period_bytes_max = 8192 - 32,
+ .periods_min = 1,
+ .periods_max = PAGE_SIZE/sizeof(pxa_dma_desc),
+ .buffer_bytes_max = 128 * 1024,
+ .fifo_size = 32,
+};
+
+int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct pxa2xx_runtime_data *rtd = runtime->private_data;
+ size_t totsize = params_buffer_bytes(params);
+ size_t period = params_period_bytes(params);
+ pxa_dma_desc *dma_desc;
+ dma_addr_t dma_buff_phys, next_desc_phys;
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ runtime->dma_bytes = totsize;
+
+ dma_desc = rtd->dma_desc_array;
+ next_desc_phys = rtd->dma_desc_array_phys;
+ dma_buff_phys = runtime->dma_addr;
+ do {
+ next_desc_phys += sizeof(pxa_dma_desc);
+ dma_desc->ddadr = next_desc_phys;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ dma_desc->dsadr = dma_buff_phys;
+ dma_desc->dtadr = rtd->params->dev_addr;
+ } else {
+ dma_desc->dsadr = rtd->params->dev_addr;
+ dma_desc->dtadr = dma_buff_phys;
+ }
+ if (period > totsize)
+ period = totsize;
+ dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN;
+ dma_desc++;
+ dma_buff_phys += period;
+ } while (totsize -= period);
+ dma_desc[-1].ddadr = rtd->dma_desc_array_phys;
+
+ return 0;
+}
+EXPORT_SYMBOL(__pxa2xx_pcm_hw_params);
+
+int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
+
+ if (rtd && rtd->params)
+ *rtd->params->drcmr = 0;
+
+ snd_pcm_set_runtime_buffer(substream, NULL);
+ return 0;
+}
+EXPORT_SYMBOL(__pxa2xx_pcm_hw_free);
+
+int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
+ int ret = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
+ DCSR(prtd->dma_ch) = DCSR_RUN;
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ DCSR(prtd->dma_ch) &= ~DCSR_RUN;
+ break;
+
+ case SNDRV_PCM_TRIGGER_RESUME:
+ DCSR(prtd->dma_ch) |= DCSR_RUN;
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
+ DCSR(prtd->dma_ch) |= DCSR_RUN;
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(pxa2xx_pcm_trigger);
+
+snd_pcm_uframes_t
+pxa2xx_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct pxa2xx_runtime_data *prtd = runtime->private_data;
+
+ dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ DSADR(prtd->dma_ch) : DTADR(prtd->dma_ch);
+ snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr);
+
+ if (x == runtime->buffer_size)
+ x = 0;
+ return x;
+}
+EXPORT_SYMBOL(pxa2xx_pcm_pointer);
+
+int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
+
+ DCSR(prtd->dma_ch) &= ~DCSR_RUN;
+ DCSR(prtd->dma_ch) = 0;
+ DCMD(prtd->dma_ch) = 0;
+ *prtd->params->drcmr = prtd->dma_ch | DRCMR_MAPVLD;
+
+ return 0;
+}
+EXPORT_SYMBOL(__pxa2xx_pcm_prepare);
+
+void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
+{
+ struct snd_pcm_substream *substream = dev_id;
+ struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
+ int dcsr;
+
+ dcsr = DCSR(dma_ch);
+ DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN;
+
+ if (dcsr & DCSR_ENDINTR) {
+ snd_pcm_period_elapsed(substream);
+ } else {
+ printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
+ rtd->params->name, dma_ch, dcsr);
+ snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+ }
+}
+EXPORT_SYMBOL(pxa2xx_pcm_dma_irq);
+
+int __pxa2xx_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct pxa2xx_runtime_data *rtd;
+ int ret;
+
+ runtime->hw = pxa2xx_pcm_hardware;
+
+ /*
+ * For mysterious reasons (and despite what the manual says)
+ * playback samples are lost if the DMA count is not a multiple
+ * of the DMA burst size. Let's add a rule to enforce that.
+ */
+ ret = snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
+ if (ret)
+ goto out;
+
+ ret = snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
+ if (ret)
+ goto out;
+
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ goto out;
+
+ ret = -ENOMEM;
+ rtd = kmalloc(sizeof(*rtd), GFP_KERNEL);
+ if (!rtd)
+ goto out;
+ rtd->dma_desc_array =
+ dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE,
+ &rtd->dma_desc_array_phys, GFP_KERNEL);
+ if (!rtd->dma_desc_array)
+ goto err1;
+
+ runtime->private_data = rtd;
+ return 0;
+
+ err1:
+ kfree(rtd);
+ out:
+ return ret;
+}
+EXPORT_SYMBOL(__pxa2xx_pcm_open);
+
+int __pxa2xx_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct pxa2xx_runtime_data *rtd = runtime->private_data;
+
+ dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE,
+ rtd->dma_desc_array, rtd->dma_desc_array_phys);
+ kfree(rtd);
+ return 0;
+}
+EXPORT_SYMBOL(__pxa2xx_pcm_close);
+
+int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+ runtime->dma_area,
+ runtime->dma_addr,
+ runtime->dma_bytes);
+}
+EXPORT_SYMBOL(pxa2xx_pcm_mmap);
+
+int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
+ size_t size = pxa2xx_pcm_hardware.buffer_bytes_max;
+ buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ buf->dev.dev = pcm->card->dev;
+ buf->private_data = NULL;
+ buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+ &buf->addr, GFP_KERNEL);
+ if (!buf->area)
+ return -ENOMEM;
+ buf->bytes = size;
+ return 0;
+}
+EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer);
+
+void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_dma_buffer *buf;
+ int stream;
+
+ for (stream = 0; stream < 2; stream++) {
+ substream = pcm->streams[stream].substream;
+ if (!substream)
+ continue;
+ buf = &substream->dma_buffer;
+ if (!buf->area)
+ continue;
+ dma_free_writecombine(pcm->card->dev, buf->bytes,
+ buf->area, buf->addr);
+ buf->area = NULL;
+ }
+}
+EXPORT_SYMBOL(pxa2xx_pcm_free_dma_buffers);
+
+MODULE_AUTHOR("Nicolas Pitre");
+MODULE_DESCRIPTION("Intel PXA2xx sound library");
+MODULE_LICENSE("GPL");
diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c
index 381094aab235..535704f77496 100644
--- a/sound/arm/pxa2xx-pcm.c
+++ b/sound/arm/pxa2xx-pcm.c
@@ -10,183 +10,20 @@
* published by the Free Software Foundation.
*/
-#include
-#include
-#include
-#include
-#include
-
#include
-#include
-#include
-
-#include
-#include
-#include
+#include
#include "pxa2xx-pcm.h"
-
-static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .period_bytes_min = 32,
- .period_bytes_max = 8192 - 32,
- .periods_min = 1,
- .periods_max = PAGE_SIZE/sizeof(pxa_dma_desc),
- .buffer_bytes_max = 128 * 1024,
- .fifo_size = 32,
-};
-
-struct pxa2xx_runtime_data {
- int dma_ch;
- struct pxa2xx_pcm_dma_params *params;
- pxa_dma_desc *dma_desc_array;
- dma_addr_t dma_desc_array_phys;
-};
-
-static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct pxa2xx_runtime_data *rtd = runtime->private_data;
- size_t totsize = params_buffer_bytes(params);
- size_t period = params_period_bytes(params);
- pxa_dma_desc *dma_desc;
- dma_addr_t dma_buff_phys, next_desc_phys;
-
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = totsize;
-
- dma_desc = rtd->dma_desc_array;
- next_desc_phys = rtd->dma_desc_array_phys;
- dma_buff_phys = runtime->dma_addr;
- do {
- next_desc_phys += sizeof(pxa_dma_desc);
- dma_desc->ddadr = next_desc_phys;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- dma_desc->dsadr = dma_buff_phys;
- dma_desc->dtadr = rtd->params->dev_addr;
- } else {
- dma_desc->dsadr = rtd->params->dev_addr;
- dma_desc->dtadr = dma_buff_phys;
- }
- if (period > totsize)
- period = totsize;
- dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN;
- dma_desc++;
- dma_buff_phys += period;
- } while (totsize -= period);
- dma_desc[-1].ddadr = rtd->dma_desc_array_phys;
-
- return 0;
-}
-
-static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
-
- *rtd->params->drcmr = 0;
- snd_pcm_set_runtime_buffer(substream, NULL);
- return 0;
-}
-
static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
{
struct pxa2xx_pcm_client *client = substream->private_data;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct pxa2xx_runtime_data *rtd = runtime->private_data;
- DCSR(rtd->dma_ch) &= ~DCSR_RUN;
- DCSR(rtd->dma_ch) = 0;
- DCMD(rtd->dma_ch) = 0;
- *rtd->params->drcmr = rtd->dma_ch | DRCMR_MAPVLD;
+ __pxa2xx_pcm_prepare(substream);
return client->prepare(substream);
}
-static int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
- int ret = 0;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- DDADR(rtd->dma_ch) = rtd->dma_desc_array_phys;
- DCSR(rtd->dma_ch) = DCSR_RUN;
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- DCSR(rtd->dma_ch) &= ~DCSR_RUN;
- break;
-
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- DCSR(rtd->dma_ch) |= DCSR_RUN;
- break;
-
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
-{
- struct snd_pcm_substream *substream = dev_id;
- struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
- int dcsr;
-
- dcsr = DCSR(dma_ch);
- DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN;
-
- if (dcsr & DCSR_ENDINTR) {
- snd_pcm_period_elapsed(substream);
- } else {
- printk( KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
- rtd->params->name, dma_ch, dcsr );
- snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
- }
-}
-
-static snd_pcm_uframes_t pxa2xx_pcm_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct pxa2xx_runtime_data *rtd = runtime->private_data;
- dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
- DSADR(rtd->dma_ch) : DTADR(rtd->dma_ch);
- snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr);
- if (x == runtime->buffer_size)
- x = 0;
- return x;
-}
-
-static int
-pxa2xx_pcm_hw_rule_mult32(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
-{
- struct snd_interval *i = hw_param_interval(params, rule->var);
- int changed = 0;
-
- if (i->min & 31) {
- i->min = (i->min & ~31) + 32;
- i->openmin = 0;
- changed = 1;
- }
-
- if (i->max & 31) {
- i->max &= ~31;
- i->openmax = 0;
- changed = 1;
- }
-
- return changed;
-}
-
static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
{
struct pxa2xx_pcm_client *client = substream->private_data;
@@ -194,33 +31,11 @@ static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
struct pxa2xx_runtime_data *rtd;
int ret;
- runtime->hw = pxa2xx_pcm_hardware;
-
- /*
- * For mysterious reasons (and despite what the manual says)
- * playback samples are lost if the DMA count is not a multiple
- * of the DMA burst size. Let's add a rule to enforce that.
- */
- ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
- pxa2xx_pcm_hw_rule_mult32, NULL,
- SNDRV_PCM_HW_PARAM_PERIOD_BYTES, -1);
- if (ret)
- goto out;
- ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
- pxa2xx_pcm_hw_rule_mult32, NULL,
- SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1);
+ ret = __pxa2xx_pcm_open(substream);
if (ret)
goto out;
- ret = -ENOMEM;
- rtd = kmalloc(sizeof(*rtd), GFP_KERNEL);
- if (!rtd)
- goto out;
- rtd->dma_desc_array =
- dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE,
- &rtd->dma_desc_array_phys, GFP_KERNEL);
- if (!rtd->dma_desc_array)
- goto err1;
+ rtd = runtime->private_data;
rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
client->playback_params : client->capture_params;
@@ -230,17 +45,13 @@ static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
goto err2;
rtd->dma_ch = ret;
- runtime->private_data = rtd;
ret = client->startup(substream);
if (!ret)
goto out;
pxa_free_dma(rtd->dma_ch);
err2:
- dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE,
- rtd->dma_desc_array, rtd->dma_desc_array_phys);
- err1:
- kfree(rtd);
+ __pxa2xx_pcm_close(substream);
out:
return ret;
}
@@ -252,69 +63,22 @@ static int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
pxa_free_dma(rtd->dma_ch);
client->shutdown(substream);
- dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE,
- rtd->dma_desc_array, rtd->dma_desc_array_phys);
- kfree(rtd);
- return 0;
-}
-static int
-pxa2xx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- return dma_mmap_writecombine(substream->pcm->card->dev, vma,
- runtime->dma_area,
- runtime->dma_addr,
- runtime->dma_bytes);
+ return __pxa2xx_pcm_close(substream);
}
static struct snd_pcm_ops pxa2xx_pcm_ops = {
.open = pxa2xx_pcm_open,
.close = pxa2xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
- .hw_params = pxa2xx_pcm_hw_params,
- .hw_free = pxa2xx_pcm_hw_free,
+ .hw_params = __pxa2xx_pcm_hw_params,
+ .hw_free = __pxa2xx_pcm_hw_free,
.prepare = pxa2xx_pcm_prepare,
.trigger = pxa2xx_pcm_trigger,
.pointer = pxa2xx_pcm_pointer,
.mmap = pxa2xx_pcm_mmap,
};
-static int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
- size_t size = pxa2xx_pcm_hardware.buffer_bytes_max;
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
- buf->area = dma_alloc_writecombine(pcm->card->dev, size,
- &buf->addr, GFP_KERNEL);
- if (!buf->area)
- return -ENOMEM;
- buf->bytes = size;
- return 0;
-}
-
-static void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
- dma_free_writecombine(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
-}
-
static u64 pxa2xx_pcm_dmamask = 0xffffffff;
int pxa2xx_pcm_new(struct snd_card *card, struct pxa2xx_pcm_client *client,
diff --git a/sound/arm/pxa2xx-pcm.h b/sound/arm/pxa2xx-pcm.h
index b79f1e803780..5c4a4d38a083 100644
--- a/sound/arm/pxa2xx-pcm.h
+++ b/sound/arm/pxa2xx-pcm.h
@@ -9,14 +9,15 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include
-struct pxa2xx_pcm_dma_params {
- char *name; /* stream identifier */
- u32 dcmd; /* DMA descriptor dcmd field */
- volatile u32 *drcmr; /* the DMA request channel to use */
- u32 dev_addr; /* device physical address for DMA */
+struct pxa2xx_runtime_data {
+ int dma_ch;
+ struct pxa2xx_pcm_dma_params *params;
+ pxa_dma_desc *dma_desc_array;
+ dma_addr_t dma_desc_array_phys;
};
-
+
struct pxa2xx_pcm_client {
struct pxa2xx_pcm_dma_params *playback_params;
struct pxa2xx_pcm_dma_params *capture_params;
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
index b9c51bf8cd71..1dcd51d81d10 100644
--- a/sound/arm/sa11xx-uda1341.c
+++ b/sound/arm/sa11xx-uda1341.c
@@ -442,7 +442,8 @@ static void audio_process_dma(struct audio_stream *s)
/* we are requested to process synchronization DMA transfer */
if (s->tx_spin) {
- snd_assert(s->stream_id == SNDRV_PCM_STREAM_PLAYBACK, return);
+ if (snd_BUG_ON(s->stream_id != SNDRV_PCM_STREAM_PLAYBACK))
+ return;
/* fill the xmit dma buffers and return */
#ifdef HH_VERSION
sa1100_dma_set_spin(s->dmach, FORCE_CLOCK_ADDR, FORCE_CLOCK_SIZE);
@@ -472,7 +473,7 @@ static void audio_process_dma(struct audio_stream *s)
continue; /* special case */
} else {
offset = dma_size * s->period;
- snd_assert(dma_size <= DMA_BUF_SIZE, );
+ snd_BUG_ON(dma_size > DMA_BUF_SIZE);
}
#ifdef HH_VERSION
ret = sa1100_dma_queue_buffer(s->dmach, s, runtime->dma_addr + offset, dma_size);
@@ -879,7 +880,7 @@ void snd_sa11xx_uda1341_free(struct snd_card *card)
audio_dma_free(&chip->s[SNDRV_PCM_STREAM_CAPTURE]);
}
-static int __init sa11xx_uda1341_probe(struct platform_device *devptr)
+static int __devinit sa11xx_uda1341_probe(struct platform_device *devptr)
{
int err;
struct snd_card *card;
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 335d45ecde6a..66348c92f88d 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -12,6 +12,12 @@ config SND_HWDEP
config SND_RAWMIDI
tristate
+# To be effective this also requires INPUT - users should say:
+# select SND_JACK if INPUT=y || INPUT=SND
+# to avoid having to force INPUT on.
+config SND_JACK
+ bool
+
config SND_SEQUENCER
tristate "Sequencer support"
select SND_TIMER
@@ -38,6 +44,7 @@ config SND_SEQ_DUMMY
will be called snd-seq-dummy.
config SND_OSSEMUL
+ select SOUND_OSS_CORE
bool
config SND_MIXER_OSS
@@ -101,6 +108,9 @@ config SND_RTCTIMER
To compile this driver as a module, choose M here: the module
will be called snd-rtctimer.
+ Note that this option is exclusive with the new RTC drivers
+ (CONFIG_RTC_CLASS) since this requires the old API.
+
config SND_SEQ_RTCTIMER_DEFAULT
bool "Use RTC as default sequencer timer"
depends on SND_RTCTIMER && SND_SEQUENCER
diff --git a/sound/core/Makefile b/sound/core/Makefile
index da8e685eef9c..d57125a5687d 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -7,6 +7,7 @@ snd-y := sound.o init.o memory.o info.o control.o misc.o device.o
snd-$(CONFIG_ISA_DMA_API) += isadma.o
snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o
snd-$(CONFIG_SND_VMASTER) += vmaster.o
+snd-$(CONFIG_SND_JACK) += jack.o
snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
pcm_memory.o
diff --git a/sound/core/control.c b/sound/core/control.c
index 281b2e2ef0ea..6d71f9a7ccbb 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -139,7 +139,8 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
struct snd_ctl_file *ctl;
struct snd_kctl_event *ev;
- snd_assert(card != NULL && id != NULL, return);
+ if (snd_BUG_ON(!card || !id))
+ return;
read_lock(&card->ctl_files_rwlock);
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
card->mixer_oss_change_count++;
@@ -188,8 +189,8 @@ static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control,
struct snd_kcontrol *kctl;
unsigned int idx;
- snd_assert(control != NULL, return NULL);
- snd_assert(control->count > 0, return NULL);
+ if (snd_BUG_ON(!control || !control->count))
+ return NULL;
kctl = kzalloc(sizeof(*kctl) + sizeof(struct snd_kcontrol_volatile) * control->count, GFP_KERNEL);
if (kctl == NULL) {
snd_printk(KERN_ERR "Cannot allocate control instance\n");
@@ -218,8 +219,8 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
struct snd_kcontrol kctl;
unsigned int access;
- snd_assert(ncontrol != NULL, return NULL);
- snd_assert(ncontrol->info != NULL, return NULL);
+ if (snd_BUG_ON(!ncontrol || !ncontrol->info))
+ return NULL;
memset(&kctl, 0, sizeof(kctl));
kctl.id.iface = ncontrol->iface;
kctl.id.device = ncontrol->device;
@@ -315,8 +316,8 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
if (! kcontrol)
return err;
- snd_assert(card != NULL, goto error);
- snd_assert(kcontrol->info != NULL, goto error);
+ if (snd_BUG_ON(!card || !kcontrol->info))
+ goto error;
id = kcontrol->id;
down_write(&card->controls_rwsem);
if (snd_ctl_find_id(card, &id)) {
@@ -367,7 +368,8 @@ int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol)
struct snd_ctl_elem_id id;
unsigned int idx;
- snd_assert(card != NULL && kcontrol != NULL, return -EINVAL);
+ if (snd_BUG_ON(!card || !kcontrol))
+ return -EINVAL;
list_del(&kcontrol->list);
card->controls_count -= kcontrol->count;
id = kcontrol->id;
@@ -487,7 +489,8 @@ struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numi
{
struct snd_kcontrol *kctl;
- snd_assert(card != NULL && numid != 0, return NULL);
+ if (snd_BUG_ON(!card || !numid))
+ return NULL;
list_for_each_entry(kctl, &card->controls, list) {
if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid)
return kctl;
@@ -514,7 +517,8 @@ struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
{
struct snd_kcontrol *kctl;
- snd_assert(card != NULL && id != NULL, return NULL);
+ if (snd_BUG_ON(!card || !id))
+ return NULL;
if (id->numid != 0)
return snd_ctl_find_numid(card, id->numid);
list_for_each_entry(kctl, &card->controls, list) {
@@ -647,7 +651,7 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
#endif
result = kctl->info(kctl, info);
if (result >= 0) {
- snd_assert(info->access == 0, );
+ snd_BUG_ON(info->access);
index_offset = snd_ctl_get_ioff(kctl, &info->id);
vd = &kctl->vd[index_offset];
snd_ctl_build_ioff(&info->id, kctl, index_offset);
@@ -1160,7 +1164,8 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
ctl = file->private_data;
card = ctl->card;
- snd_assert(card != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card))
+ return -ENXIO;
switch (cmd) {
case SNDRV_CTL_IOCTL_PVERSION:
return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0;
@@ -1222,7 +1227,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer,
ssize_t result = 0;
ctl = file->private_data;
- snd_assert(ctl != NULL && ctl->card != NULL, return -ENXIO);
+ if (snd_BUG_ON(!ctl || !ctl->card))
+ return -ENXIO;
if (!ctl->subscribed)
return -EBADFD;
if (count < sizeof(struct snd_ctl_event))
@@ -1328,7 +1334,8 @@ static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn,
{
struct snd_kctl_ioctl *p;
- snd_assert(fcn != NULL, return -EINVAL);
+ if (snd_BUG_ON(!fcn))
+ return -EINVAL;
down_write(&snd_ioctl_rwsem);
list_for_each_entry(p, lists, list) {
if (p->fioctl == fcn) {
@@ -1404,9 +1411,11 @@ static int snd_ctl_dev_register(struct snd_device *device)
int err, cardnum;
char name[16];
- snd_assert(card != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card))
+ return -ENXIO;
cardnum = card->number;
- snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
+ if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS))
+ return -ENXIO;
sprintf(name, "controlC%i", cardnum);
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
&snd_ctl_f_ops, card, name)) < 0)
@@ -1423,16 +1432,18 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
struct snd_ctl_file *ctl;
int err, cardnum;
- snd_assert(card != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card))
+ return -ENXIO;
cardnum = card->number;
- snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
+ if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS))
+ return -ENXIO;
- down_read(&card->controls_rwsem);
+ read_lock(&card->ctl_files_rwlock);
list_for_each_entry(ctl, &card->ctl_files, list) {
wake_up(&ctl->change_sleep);
kill_fasync(&ctl->fasync, SIGIO, POLL_ERR);
}
- up_read(&card->controls_rwsem);
+ read_unlock(&card->ctl_files_rwlock);
if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL,
card, -1)) < 0)
@@ -1469,7 +1480,8 @@ int snd_ctl_create(struct snd_card *card)
.dev_disconnect = snd_ctl_dev_disconnect,
};
- snd_assert(card != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card))
+ return -ENXIO;
return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);
}
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 6101259ad860..368dc9c4aef8 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -398,7 +398,8 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns
int err;
ctl = file->private_data;
- snd_assert(ctl && ctl->card, return -ENXIO);
+ if (snd_BUG_ON(!ctl || !ctl->card))
+ return -ENXIO;
switch (cmd) {
case SNDRV_CTL_IOCTL_PVERSION:
diff --git a/sound/core/device.c b/sound/core/device.c
index 202dac0e4d89..c58d8227254c 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -45,9 +45,8 @@ int snd_device_new(struct snd_card *card, snd_device_type_t type,
{
struct snd_device *dev;
- snd_assert(card != NULL, return -ENXIO);
- snd_assert(device_data != NULL, return -ENXIO);
- snd_assert(ops != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card || !device_data || !ops))
+ return -ENXIO;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
snd_printk(KERN_ERR "Cannot allocate device\n");
@@ -80,8 +79,8 @@ int snd_device_free(struct snd_card *card, void *device_data)
{
struct snd_device *dev;
- snd_assert(card != NULL, return -ENXIO);
- snd_assert(device_data != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card || !device_data))
+ return -ENXIO;
list_for_each_entry(dev, &card->devices, list) {
if (dev->device_data != device_data)
continue;
@@ -123,8 +122,8 @@ int snd_device_disconnect(struct snd_card *card, void *device_data)
{
struct snd_device *dev;
- snd_assert(card != NULL, return -ENXIO);
- snd_assert(device_data != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card || !device_data))
+ return -ENXIO;
list_for_each_entry(dev, &card->devices, list) {
if (dev->device_data != device_data)
continue;
@@ -159,8 +158,8 @@ int snd_device_register(struct snd_card *card, void *device_data)
struct snd_device *dev;
int err;
- snd_assert(card != NULL, return -ENXIO);
- snd_assert(device_data != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card || !device_data))
+ return -ENXIO;
list_for_each_entry(dev, &card->devices, list) {
if (dev->device_data != device_data)
continue;
@@ -188,7 +187,8 @@ int snd_device_register_all(struct snd_card *card)
struct snd_device *dev;
int err;
- snd_assert(card != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card))
+ return -ENXIO;
list_for_each_entry(dev, &card->devices, list) {
if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) {
if ((err = dev->ops->dev_register(dev)) < 0)
@@ -208,7 +208,8 @@ int snd_device_disconnect_all(struct snd_card *card)
struct snd_device *dev;
int err = 0;
- snd_assert(card != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card))
+ return -ENXIO;
list_for_each_entry(dev, &card->devices, list) {
if (snd_device_disconnect(card, dev->device_data) < 0)
err = -ENXIO;
@@ -226,7 +227,8 @@ int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd)
int err;
unsigned int range_low, range_high;
- snd_assert(card != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card))
+ return -ENXIO;
range_low = cmd * SNDRV_DEV_TYPE_RANGE_SIZE;
range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1;
__again:
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 6d6589f93899..195cafc5a553 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -353,9 +353,10 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device,
.dev_disconnect = snd_hwdep_dev_disconnect,
};
- snd_assert(rhwdep != NULL, return -EINVAL);
- *rhwdep = NULL;
- snd_assert(card != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card))
+ return -ENXIO;
+ if (rhwdep)
+ *rhwdep = NULL;
hwdep = kzalloc(sizeof(*hwdep), GFP_KERNEL);
if (hwdep == NULL) {
snd_printk(KERN_ERR "hwdep: cannot allocate\n");
@@ -374,13 +375,15 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device,
}
init_waitqueue_head(&hwdep->open_wait);
mutex_init(&hwdep->open_mutex);
- *rhwdep = hwdep;
+ if (rhwdep)
+ *rhwdep = hwdep;
return 0;
}
static int snd_hwdep_free(struct snd_hwdep *hwdep)
{
- snd_assert(hwdep != NULL, return -ENXIO);
+ if (!hwdep)
+ return 0;
if (hwdep->private_free)
hwdep->private_free(hwdep);
kfree(hwdep);
@@ -440,7 +443,8 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device)
{
struct snd_hwdep *hwdep = device->device_data;
- snd_assert(hwdep != NULL, return -ENXIO);
+ if (snd_BUG_ON(!hwdep))
+ return -ENXIO;
mutex_lock(®ister_mutex);
if (snd_hwdep_search(hwdep->card, hwdep->device) != hwdep) {
mutex_unlock(®ister_mutex);
diff --git a/sound/core/info.c b/sound/core/info.c
index c67773ad9298..527b207462b0 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -217,7 +217,8 @@ static ssize_t snd_info_entry_read(struct file *file, char __user *buffer,
loff_t pos;
data = file->private_data;
- snd_assert(data != NULL, return -ENXIO);
+ if (snd_BUG_ON(!data))
+ return -ENXIO;
pos = *offset;
if (pos < 0 || (long) pos != pos || (ssize_t) count < 0)
return -EIO;
@@ -258,7 +259,8 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer
loff_t pos;
data = file->private_data;
- snd_assert(data != NULL, return -ENXIO);
+ if (snd_BUG_ON(!data))
+ return -ENXIO;
entry = data->entry;
pos = *offset;
if (pos < 0 || (long) pos != pos || (ssize_t) count < 0)
@@ -614,7 +616,8 @@ int snd_info_card_create(struct snd_card *card)
char str[8];
struct snd_info_entry *entry;
- snd_assert(card != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card))
+ return -ENXIO;
sprintf(str, "card%i", card->number);
if ((entry = snd_info_create_module_entry(card->module, str, NULL)) == NULL)
@@ -636,7 +639,8 @@ int snd_info_card_register(struct snd_card *card)
{
struct proc_dir_entry *p;
- snd_assert(card != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card))
+ return -ENXIO;
if (!strcmp(card->id, card->proc_root->name))
return 0;
@@ -654,7 +658,8 @@ int snd_info_card_register(struct snd_card *card)
*/
void snd_info_card_disconnect(struct snd_card *card)
{
- snd_assert(card != NULL, return);
+ if (!card)
+ return;
mutex_lock(&info_mutex);
if (card->proc_root_link) {
snd_remove_proc_entry(snd_proc_root, card->proc_root_link);
@@ -671,7 +676,8 @@ void snd_info_card_disconnect(struct snd_card *card)
*/
int snd_info_card_free(struct snd_card *card)
{
- snd_assert(card != NULL, return -ENXIO);
+ if (!card)
+ return 0;
snd_info_free_entry(card->proc_root);
card->proc_root = NULL;
return 0;
@@ -849,7 +855,7 @@ static void snd_info_disconnect(struct snd_info_entry *entry)
return;
list_del_init(&entry->list);
root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
- snd_assert(root, return);
+ snd_BUG_ON(!root);
snd_remove_proc_entry(root, entry->p);
entry->p = NULL;
}
@@ -947,7 +953,8 @@ int snd_info_register(struct snd_info_entry * entry)
{
struct proc_dir_entry *root, *p = NULL;
- snd_assert(entry != NULL, return -ENXIO);
+ if (snd_BUG_ON(!entry))
+ return -ENXIO;
root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
mutex_lock(&info_mutex);
p = snd_create_proc_entry(entry->name, entry->mode, root);
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c
index e35789a92752..e4af138d651a 100644
--- a/sound/core/info_oss.c
+++ b/sound/core/info_oss.c
@@ -43,8 +43,10 @@ int snd_oss_info_register(int dev, int num, char *string)
{
char *x;
- snd_assert(dev >= 0 && dev < SNDRV_OSS_INFO_DEV_COUNT, return -ENXIO);
- snd_assert(num >= 0 && num < SNDRV_CARDS, return -ENXIO);
+ if (snd_BUG_ON(dev < 0 || dev >= SNDRV_OSS_INFO_DEV_COUNT))
+ return -ENXIO;
+ if (snd_BUG_ON(num < 0 || num >= SNDRV_CARDS))
+ return -ENXIO;
mutex_lock(&strings);
if (string == NULL) {
if ((x = snd_sndstat_strings[num][dev]) != NULL) {
diff --git a/sound/core/init.c b/sound/core/init.c
index df46bbc25dc2..8af467df9245 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -545,7 +545,8 @@ int snd_card_register(struct snd_card *card)
{
int err;
- snd_assert(card != NULL, return -EINVAL);
+ if (snd_BUG_ON(!card))
+ return -EINVAL;
#ifndef CONFIG_SYSFS_DEPRECATED
if (!card->card_dev) {
card->card_dev = device_create_drvdata(sound_class, card->dev,
diff --git a/sound/core/jack.c b/sound/core/jack.c
new file mode 100644
index 000000000000..8133a2b173a5
--- /dev/null
+++ b/sound/core/jack.c
@@ -0,0 +1,163 @@
+/*
+ * Jack abstraction layer
+ *
+ * Copyright 2008 Wolfson Microelectronics
+ *
+ * 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
+
+static int snd_jack_dev_free(struct snd_device *device)
+{
+ struct snd_jack *jack = device->device_data;
+
+ /* If the input device is registered with the input subsystem
+ * then we need to use a different deallocator. */
+ if (jack->registered)
+ input_unregister_device(jack->input_dev);
+ else
+ input_free_device(jack->input_dev);
+
+ kfree(jack);
+
+ return 0;
+}
+
+static int snd_jack_dev_register(struct snd_device *device)
+{
+ struct snd_jack *jack = device->device_data;
+ struct snd_card *card = device->card;
+ int err;
+
+ snprintf(jack->name, sizeof(jack->name), "%s %s",
+ card->longname, jack->id);
+ jack->input_dev->name = jack->name;
+
+ /* Default to the sound card device. */
+ if (!jack->input_dev->dev.parent)
+ jack->input_dev->dev.parent = card->dev;
+
+ err = input_register_device(jack->input_dev);
+ if (err == 0)
+ jack->registered = 1;
+
+ return err;
+}
+
+/**
+ * snd_jack_new - Create a new jack
+ * @card: the card instance
+ * @id: an identifying string for this jack
+ * @type: a bitmask of enum snd_jack_type values that can be detected by
+ * this jack
+ * @jjack: Used to provide the allocated jack object to the caller.
+ *
+ * Creates a new jack object.
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ * On success jjack will be initialised.
+ */
+int snd_jack_new(struct snd_card *card, const char *id, int type,
+ struct snd_jack **jjack)
+{
+ struct snd_jack *jack;
+ int err;
+ static struct snd_device_ops ops = {
+ .dev_free = snd_jack_dev_free,
+ .dev_register = snd_jack_dev_register,
+ };
+
+ jack = kzalloc(sizeof(struct snd_jack), GFP_KERNEL);
+ if (jack == NULL)
+ return -ENOMEM;
+
+ jack->id = id;
+
+ jack->input_dev = input_allocate_device();
+ if (jack->input_dev == NULL) {
+ err = -ENOMEM;
+ goto fail_input;
+ }
+
+ jack->input_dev->phys = "ALSA";
+
+ jack->type = type;
+
+ if (type & SND_JACK_HEADPHONE)
+ input_set_capability(jack->input_dev, EV_SW,
+ SW_HEADPHONE_INSERT);
+ if (type & SND_JACK_MICROPHONE)
+ input_set_capability(jack->input_dev, EV_SW,
+ SW_MICROPHONE_INSERT);
+
+ err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
+ if (err < 0)
+ goto fail_input;
+
+ *jjack = jack;
+
+ return 0;
+
+fail_input:
+ input_free_device(jack->input_dev);
+ kfree(jack);
+ return err;
+}
+EXPORT_SYMBOL(snd_jack_new);
+
+/**
+ * snd_jack_set_parent - Set the parent device for a jack
+ *
+ * @jack: The jack to configure
+ * @parent: The device to set as parent for the jack.
+ *
+ * Set the parent for the jack input device in the device tree. This
+ * function is only valid prior to registration of the jack. If no
+ * parent is configured then the parent device will be the sound card.
+ */
+void snd_jack_set_parent(struct snd_jack *jack, struct device *parent)
+{
+ WARN_ON(jack->registered);
+
+ jack->input_dev->dev.parent = parent;
+}
+EXPORT_SYMBOL(snd_jack_set_parent);
+
+/**
+ * snd_jack_report - Report the current status of a jack
+ *
+ * @jack: The jack to report status for
+ * @status: The current status of the jack
+ */
+void snd_jack_report(struct snd_jack *jack, int status)
+{
+ if (jack->type & SND_JACK_HEADPHONE)
+ input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT,
+ status & SND_JACK_HEADPHONE);
+ if (jack->type & SND_JACK_MICROPHONE)
+ input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT,
+ status & SND_JACK_MICROPHONE);
+
+ input_sync(jack->input_dev);
+}
+EXPORT_SYMBOL(snd_jack_report);
+
+MODULE_AUTHOR("Mark Brown ");
+MODULE_DESCRIPTION("Jack detection support for ALSA");
+MODULE_LICENSE("GPL");
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index f5d6d8d12979..a7b46ec72f32 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -43,14 +43,6 @@ MODULE_DESCRIPTION("Memory allocator for ALSA system.");
MODULE_LICENSE("GPL");
-/*
- */
-
-void *snd_malloc_sgbuf_pages(struct device *device,
- size_t size, struct snd_dma_buffer *dmab,
- size_t *res_size);
-int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab);
-
/*
*/
@@ -67,18 +59,6 @@ struct snd_mem_list {
/* id for pre-allocated buffers */
#define SNDRV_DMA_DEVICE_UNUSED (unsigned int)-1
-#ifdef CONFIG_SND_DEBUG
-#define __ASTRING__(x) #x
-#define snd_assert(expr, args...) do {\
- if (!(expr)) {\
- printk(KERN_ERR "snd-malloc: BUG? (%s) (called from %p)\n", __ASTRING__(expr), __builtin_return_address(0));\
- args;\
- }\
-} while (0)
-#else
-#define snd_assert(expr, args...) /**/
-#endif
-
/*
*
* Generic memory allocators
@@ -111,8 +91,10 @@ void *snd_malloc_pages(size_t size, gfp_t gfp_flags)
int pg;
void *res;
- snd_assert(size > 0, return NULL);
- snd_assert(gfp_flags != 0, return NULL);
+ if (WARN_ON(!size))
+ return NULL;
+ if (WARN_ON(!gfp_flags))
+ return NULL;
gfp_flags |= __GFP_COMP; /* compound page lets parts be mapped */
pg = get_order(size);
if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL)
@@ -152,8 +134,8 @@ static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *d
void *res;
gfp_t gfp_flags;
- snd_assert(size > 0, return NULL);
- snd_assert(dma != NULL, return NULL);
+ if (WARN_ON(!dma))
+ return NULL;
pg = get_order(size);
gfp_flags = GFP_KERNEL
| __GFP_COMP /* compound page lets parts be mapped */
@@ -189,8 +171,8 @@ static void *snd_malloc_sbus_pages(struct device *dev, size_t size,
int pg;
void *res;
- snd_assert(size > 0, return NULL);
- snd_assert(dma_addr != NULL, return NULL);
+ if (WARN_ON(!dma_addr))
+ return NULL;
pg = get_order(size);
res = sbus_alloc_consistent(sdev, PAGE_SIZE * (1 << pg), dma_addr);
if (res != NULL)
@@ -236,8 +218,10 @@ static void snd_free_sbus_pages(struct device *dev, size_t size,
int snd_dma_alloc_pages(int type, struct device *device, size_t size,
struct snd_dma_buffer *dmab)
{
- snd_assert(size > 0, return -ENXIO);
- snd_assert(dmab != NULL, return -ENXIO);
+ if (WARN_ON(!size))
+ return -ENXIO;
+ if (WARN_ON(!dmab))
+ return -ENXIO;
dmab->dev.type = type;
dmab->dev.dev = device;
@@ -292,15 +276,17 @@ int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
{
int err;
- snd_assert(size > 0, return -ENXIO);
- snd_assert(dmab != NULL, return -ENXIO);
-
while ((err = snd_dma_alloc_pages(type, device, size, dmab)) < 0) {
+ size_t aligned_size;
if (err != -ENOMEM)
return err;
- size >>= 1;
if (size <= PAGE_SIZE)
return -ENOMEM;
+ aligned_size = PAGE_SIZE << get_order(size);
+ if (size != aligned_size)
+ size = aligned_size;
+ else
+ size >>= 1;
}
if (! dmab->area)
return -ENOMEM;
@@ -353,7 +339,8 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
{
struct snd_mem_list *mem;
- snd_assert(dmab, return 0);
+ if (WARN_ON(!dmab))
+ return 0;
mutex_lock(&list_mutex);
list_for_each_entry(mem, &mem_list_head, list) {
@@ -387,7 +374,8 @@ int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id)
{
struct snd_mem_list *mem;
- snd_assert(dmab, return -EINVAL);
+ if (WARN_ON(!dmab))
+ return -EINVAL;
mem = kmalloc(sizeof(*mem), GFP_KERNEL);
if (! mem)
return -ENOMEM;
diff --git a/sound/core/oss/copy.c b/sound/core/oss/copy.c
index 9ded30d0e97d..05b58d4fc2b7 100644
--- a/sound/core/oss/copy.c
+++ b/sound/core/oss/copy.c
@@ -32,17 +32,18 @@ static snd_pcm_sframes_t copy_transfer(struct snd_pcm_plugin *plugin,
unsigned int channel;
unsigned int nchannels;
- snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO);
+ if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
+ return -ENXIO;
if (frames == 0)
return 0;
nchannels = plugin->src_format.channels;
for (channel = 0; channel < nchannels; channel++) {
- snd_assert(src_channels->area.first % 8 == 0 &&
- src_channels->area.step % 8 == 0,
- return -ENXIO);
- snd_assert(dst_channels->area.first % 8 == 0 &&
- dst_channels->area.step % 8 == 0,
- return -ENXIO);
+ if (snd_BUG_ON(src_channels->area.first % 8 ||
+ src_channels->area.step % 8))
+ return -ENXIO;
+ if (snd_BUG_ON(dst_channels->area.first % 8 ||
+ dst_channels->area.step % 8))
+ return -ENXIO;
if (!src_channels->enabled) {
if (dst_channels->wanted)
snd_pcm_area_silence(&dst_channels->area, 0, frames, plugin->dst_format.format);
@@ -66,15 +67,20 @@ int snd_pcm_plugin_build_copy(struct snd_pcm_substream *plug,
struct snd_pcm_plugin *plugin;
int width;
- snd_assert(r_plugin != NULL, return -ENXIO);
+ if (snd_BUG_ON(!r_plugin))
+ return -ENXIO;
*r_plugin = NULL;
- snd_assert(src_format->format == dst_format->format, return -ENXIO);
- snd_assert(src_format->rate == dst_format->rate, return -ENXIO);
- snd_assert(src_format->channels == dst_format->channels, return -ENXIO);
+ if (snd_BUG_ON(src_format->format != dst_format->format))
+ return -ENXIO;
+ if (snd_BUG_ON(src_format->rate != dst_format->rate))
+ return -ENXIO;
+ if (snd_BUG_ON(src_format->channels != dst_format->channels))
+ return -ENXIO;
width = snd_pcm_format_physical_width(src_format->format);
- snd_assert(width > 0, return -ENXIO);
+ if (snd_BUG_ON(width <= 0))
+ return -ENXIO;
err = snd_pcm_plugin_build(plug, "copy", src_format, dst_format,
0, &plugin);
diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c
index f874f6ca3657..6faa1d719206 100644
--- a/sound/core/oss/io.c
+++ b/sound/core/oss/io.c
@@ -39,14 +39,17 @@ static snd_pcm_sframes_t io_playback_transfer(struct snd_pcm_plugin *plugin,
struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
- snd_assert(plugin != NULL, return -ENXIO);
- snd_assert(src_channels != NULL, return -ENXIO);
+ if (snd_BUG_ON(!plugin))
+ return -ENXIO;
+ if (snd_BUG_ON(!src_channels))
+ return -ENXIO;
if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
return pcm_write(plugin->plug, src_channels->area.addr, frames);
} else {
int channel, channels = plugin->dst_format.channels;
void **bufs = (void**)plugin->extra_data;
- snd_assert(bufs != NULL, return -ENXIO);
+ if (snd_BUG_ON(!bufs))
+ return -ENXIO;
for (channel = 0; channel < channels; channel++) {
if (src_channels[channel].enabled)
bufs[channel] = src_channels[channel].area.addr;
@@ -62,14 +65,17 @@ static snd_pcm_sframes_t io_capture_transfer(struct snd_pcm_plugin *plugin,
struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
- snd_assert(plugin != NULL, return -ENXIO);
- snd_assert(dst_channels != NULL, return -ENXIO);
+ if (snd_BUG_ON(!plugin))
+ return -ENXIO;
+ if (snd_BUG_ON(!dst_channels))
+ return -ENXIO;
if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
return pcm_read(plugin->plug, dst_channels->area.addr, frames);
} else {
int channel, channels = plugin->dst_format.channels;
void **bufs = (void**)plugin->extra_data;
- snd_assert(bufs != NULL, return -ENXIO);
+ if (snd_BUG_ON(!bufs))
+ return -ENXIO;
for (channel = 0; channel < channels; channel++) {
if (dst_channels[channel].enabled)
bufs[channel] = dst_channels[channel].area.addr;
@@ -107,9 +113,11 @@ int snd_pcm_plugin_build_io(struct snd_pcm_substream *plug,
struct snd_pcm_plugin_format format;
struct snd_pcm_plugin *plugin;
- snd_assert(r_plugin != NULL, return -ENXIO);
+ if (snd_BUG_ON(!r_plugin))
+ return -ENXIO;
*r_plugin = NULL;
- snd_assert(plug != NULL && params != NULL, return -ENXIO);
+ if (snd_BUG_ON(!plug || !params))
+ return -ENXIO;
format.format = params_format(params);
format.rate = params_rate(params);
format.channels = params_channels(params);
diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c
index da3dbd41669e..4c1d16827199 100644
--- a/sound/core/oss/linear.c
+++ b/sound/core/oss/linear.c
@@ -92,7 +92,8 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
{
struct linear_priv *data;
- snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO);
+ if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
+ return -ENXIO;
data = (struct linear_priv *)plugin->extra_data;
if (frames == 0)
return 0;
@@ -100,12 +101,12 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
{
unsigned int channel;
for (channel = 0; channel < plugin->src_format.channels; channel++) {
- snd_assert(src_channels[channel].area.first % 8 == 0 &&
- src_channels[channel].area.step % 8 == 0,
- return -ENXIO);
- snd_assert(dst_channels[channel].area.first % 8 == 0 &&
- dst_channels[channel].area.step % 8 == 0,
- return -ENXIO);
+ if (snd_BUG_ON(src_channels[channel].area.first % 8 ||
+ src_channels[channel].area.step % 8))
+ return -ENXIO;
+ if (snd_BUG_ON(dst_channels[channel].area.first % 8 ||
+ dst_channels[channel].area.step % 8))
+ return -ENXIO;
}
}
#endif
@@ -154,13 +155,17 @@ int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug,
struct linear_priv *data;
struct snd_pcm_plugin *plugin;
- snd_assert(r_plugin != NULL, return -ENXIO);
+ if (snd_BUG_ON(!r_plugin))
+ return -ENXIO;
*r_plugin = NULL;
- snd_assert(src_format->rate == dst_format->rate, return -ENXIO);
- snd_assert(src_format->channels == dst_format->channels, return -ENXIO);
- snd_assert(snd_pcm_format_linear(src_format->format) &&
- snd_pcm_format_linear(dst_format->format), return -ENXIO);
+ if (snd_BUG_ON(src_format->rate != dst_format->rate))
+ return -ENXIO;
+ if (snd_BUG_ON(src_format->channels != dst_format->channels))
+ return -ENXIO;
+ if (snd_BUG_ON(!snd_pcm_format_linear(src_format->format) ||
+ !snd_pcm_format_linear(dst_format->format)))
+ return -ENXIO;
err = snd_pcm_plugin_build(plug, "linear format conversion",
src_format, dst_format,
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 581aa2c60e65..4690b8b5681f 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -257,8 +257,10 @@ static int snd_mixer_oss_get_volume(struct snd_mixer_oss_file *fmixer, int slot)
result = pslot->get_volume(fmixer, pslot, &left, &right);
if (!pslot->stereo)
right = left;
- snd_assert(left >= 0 && left <= 100, return -EIO);
- snd_assert(right >= 0 && right <= 100, return -EIO);
+ if (snd_BUG_ON(left < 0 || left > 100))
+ return -EIO;
+ if (snd_BUG_ON(right < 0 || right > 100))
+ return -EIO;
if (result >= 0) {
pslot->volume[0] = left;
pslot->volume[1] = right;
@@ -298,7 +300,8 @@ static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int
int __user *p = argp;
int tmp;
- snd_assert(fmixer != NULL, return -ENXIO);
+ if (snd_BUG_ON(!fmixer))
+ return -ENXIO;
if (((cmd >> 8) & 0xff) == 'M') {
switch (cmd) {
case SOUND_MIXER_INFO:
@@ -368,7 +371,8 @@ int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned l
{
struct snd_mixer_oss_file fmixer;
- snd_assert(card != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card))
+ return -ENXIO;
if (card->mixer_oss == NULL)
return -ENXIO;
memset(&fmixer, 0, sizeof(fmixer));
@@ -1284,9 +1288,11 @@ static int snd_mixer_oss_free1(void *private)
struct snd_card *card;
int idx;
- snd_assert(mixer != NULL, return -ENXIO);
+ if (!mixer)
+ return 0;
card = mixer->card;
- snd_assert(mixer == card->mixer_oss, return -ENXIO);
+ if (snd_BUG_ON(mixer != card->mixer_oss))
+ return -ENXIO;
card->mixer_oss = NULL;
for (idx = 0; idx < SNDRV_OSS_MAX_MIXERS; idx++) {
struct snd_mixer_oss_slot *chn = &mixer->slots[idx];
diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c
index 77f96194a0ed..f7649d4d950b 100644
--- a/sound/core/oss/mulaw.c
+++ b/sound/core/oss/mulaw.c
@@ -252,19 +252,20 @@ static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin,
{
struct mulaw_priv *data;
- snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO);
+ if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
+ return -ENXIO;
if (frames == 0)
return 0;
#ifdef CONFIG_SND_DEBUG
{
unsigned int channel;
for (channel = 0; channel < plugin->src_format.channels; channel++) {
- snd_assert(src_channels[channel].area.first % 8 == 0 &&
- src_channels[channel].area.step % 8 == 0,
- return -ENXIO);
- snd_assert(dst_channels[channel].area.first % 8 == 0 &&
- dst_channels[channel].area.step % 8 == 0,
- return -ENXIO);
+ if (snd_BUG_ON(src_channels[channel].area.first % 8 ||
+ src_channels[channel].area.step % 8))
+ return -ENXIO;
+ if (snd_BUG_ON(dst_channels[channel].area.first % 8 ||
+ dst_channels[channel].area.step % 8))
+ return -ENXIO;
}
}
#endif
@@ -305,11 +306,14 @@ int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug,
struct snd_pcm_plugin_format *format;
mulaw_f func;
- snd_assert(r_plugin != NULL, return -ENXIO);
+ if (snd_BUG_ON(!r_plugin))
+ return -ENXIO;
*r_plugin = NULL;
- snd_assert(src_format->rate == dst_format->rate, return -ENXIO);
- snd_assert(src_format->channels == dst_format->channels, return -ENXIO);
+ if (snd_BUG_ON(src_format->rate != dst_format->rate))
+ return -ENXIO;
+ if (snd_BUG_ON(src_format->channels != dst_format->channels))
+ return -ENXIO;
if (dst_format->format == SNDRV_PCM_FORMAT_MU_LAW) {
format = src_format;
@@ -323,7 +327,8 @@ int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug,
snd_BUG();
return -EINVAL;
}
- snd_assert(snd_pcm_format_linear(format->format) != 0, return -ENXIO);
+ if (snd_BUG_ON(!snd_pcm_format_linear(format->format)))
+ return -ENXIO;
err = snd_pcm_plugin_build(plug, "Mu-Law<->linear conversion",
src_format, dst_format,
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 4c601b192ddf..1af62b8b86c6 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -452,7 +452,8 @@ static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm,
} else {
*params = *save;
max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);
- snd_assert(max >= 0, return -EINVAL);
+ if (max < 0)
+ return max;
last = 1;
}
_end:
@@ -461,7 +462,7 @@ static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm,
v = snd_pcm_hw_param_last(pcm, params, var, dir);
else
v = snd_pcm_hw_param_first(pcm, params, var, dir);
- snd_assert(v >= 0, return -EINVAL);
+ snd_BUG_ON(v < 0);
return v;
}
@@ -778,7 +779,8 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
while (oss_period_size * oss_periods > oss_buffer_size)
oss_period_size /= 2;
- snd_assert(oss_period_size >= 16, return -EINVAL);
+ if (oss_period_size < 16)
+ return -EINVAL;
runtime->oss.period_bytes = oss_period_size;
runtime->oss.period_frames = 1;
runtime->oss.periods = oss_periods;
@@ -895,7 +897,8 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
}
}
err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, sformat, 0);
- snd_assert(err >= 0, goto failure);
+ if (err < 0)
+ goto failure;
if (direct) {
memcpy(params, sparams, sizeof(*params));
@@ -958,11 +961,13 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
n = snd_pcm_plug_slave_size(substream, runtime->oss.period_bytes / oss_frame_size);
err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, n, NULL);
- snd_assert(err >= 0, goto failure);
+ if (err < 0)
+ goto failure;
err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIODS,
runtime->oss.periods, NULL);
- snd_assert(err >= 0, goto failure);
+ if (err < 0)
+ goto failure;
snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
@@ -1006,7 +1011,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
runtime->oss.periods = params_periods(sparams);
oss_period_size = snd_pcm_plug_client_size(substream, params_period_size(sparams));
- snd_assert(oss_period_size >= 0, err = -EINVAL; goto failure);
+ if (oss_period_size < 0) {
+ err = -EINVAL;
+ goto failure;
+ }
#ifdef CONFIG_SND_PCM_OSS_PLUGINS
if (runtime->oss.plugin_first) {
err = snd_pcm_plug_alloc(substream, oss_period_size);
@@ -1017,7 +1025,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
oss_period_size *= oss_frame_size;
oss_buffer_size = oss_period_size * runtime->oss.periods;
- snd_assert(oss_buffer_size >= 0, err = -EINVAL; goto failure);
+ if (oss_buffer_size < 0) {
+ err = -EINVAL;
+ goto failure;
+ }
runtime->oss.period_bytes = oss_period_size;
runtime->oss.buffer_bytes = oss_buffer_size;
@@ -1069,7 +1080,8 @@ static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_fil
return err;
}
}
- snd_assert(asubstream != NULL, return -EIO);
+ if (!asubstream)
+ return -EIO;
if (r_substream)
*r_substream = asubstream;
return 0;
@@ -1764,7 +1776,8 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
err = snd_pcm_hw_refine(substream, params);
format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
kfree(params);
- snd_assert(err >= 0, return err);
+ if (err < 0)
+ return err;
for (fmt = 0; fmt < 32; ++fmt) {
if (snd_mask_test(&format_mask, fmt)) {
int f = snd_pcm_oss_format_to(fmt);
@@ -2250,7 +2263,8 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
{
int cidx;
- snd_assert(pcm_oss_file != NULL, return -ENXIO);
+ if (!pcm_oss_file)
+ return 0;
for (cidx = 0; cidx < 2; ++cidx) {
struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
if (substream)
@@ -2271,8 +2285,8 @@ static int snd_pcm_oss_open_file(struct file *file,
struct snd_pcm_substream *substream;
unsigned int f_mode = file->f_mode;
- snd_assert(rpcm_oss_file != NULL, return -EINVAL);
- *rpcm_oss_file = NULL;
+ if (rpcm_oss_file)
+ *rpcm_oss_file = NULL;
pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL);
if (pcm_oss_file == NULL)
@@ -2312,7 +2326,8 @@ static int snd_pcm_oss_open_file(struct file *file,
}
file->private_data = pcm_oss_file;
- *rpcm_oss_file = pcm_oss_file;
+ if (rpcm_oss_file)
+ *rpcm_oss_file = pcm_oss_file;
return 0;
}
@@ -2321,7 +2336,8 @@ static int snd_task_name(struct task_struct *task, char *name, size_t size)
{
unsigned int idx;
- snd_assert(task != NULL && name != NULL && size >= 2, return -EINVAL);
+ if (snd_BUG_ON(!task || !name || size < 2))
+ return -EINVAL;
for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++)
name[idx] = task->comm[idx];
name[idx] = '\0';
@@ -2415,7 +2431,8 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file)
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
if (substream == NULL)
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
- snd_assert(substream != NULL, return -ENXIO);
+ if (snd_BUG_ON(!substream))
+ return -ENXIO;
pcm = substream->pcm;
if (!pcm->card->shutdown)
snd_pcm_oss_sync(pcm_oss_file);
@@ -2448,7 +2465,8 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long
if (substream != NULL)
break;
}
- snd_assert(substream != NULL, return -ENXIO);
+ if (snd_BUG_ON(idx >= 2))
+ return -ENXIO;
return snd_mixer_oss_ioctl_card(substream->pcm->card, cmd, arg);
}
#endif
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index bec94138205e..6751daa3bb50 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -62,7 +62,8 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t
if ((width = snd_pcm_format_physical_width(format->format)) < 0)
return width;
size = frames * format->channels * width;
- snd_assert((size % 8) == 0, return -ENXIO);
+ if (snd_BUG_ON(size % 8))
+ return -ENXIO;
size /= 8;
if (plugin->buf_frames < frames) {
vfree(plugin->buf);
@@ -84,7 +85,8 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t
c->area.step = format->channels * width;
}
} else if (plugin->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
- snd_assert((size % format->channels) == 0,);
+ if (snd_BUG_ON(size % format->channels))
+ return -EINVAL;
size /= format->channels;
for (channel = 0; channel < format->channels; channel++, c++) {
c->frames = frames;
@@ -102,13 +104,15 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t
int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames)
{
int err;
- snd_assert(snd_pcm_plug_first(plug) != NULL, return -ENXIO);
+ if (snd_BUG_ON(!snd_pcm_plug_first(plug)))
+ return -ENXIO;
if (snd_pcm_plug_stream(plug) == SNDRV_PCM_STREAM_PLAYBACK) {
struct snd_pcm_plugin *plugin = snd_pcm_plug_first(plug);
while (plugin->next) {
if (plugin->dst_frames)
frames = plugin->dst_frames(plugin, frames);
- snd_assert(frames > 0, return -ENXIO);
+ if (snd_BUG_ON(frames <= 0))
+ return -ENXIO;
plugin = plugin->next;
err = snd_pcm_plugin_alloc(plugin, frames);
if (err < 0)
@@ -119,7 +123,8 @@ int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames)
while (plugin->prev) {
if (plugin->src_frames)
frames = plugin->src_frames(plugin, frames);
- snd_assert(frames > 0, return -ENXIO);
+ if (snd_BUG_ON(frames <= 0))
+ return -ENXIO;
plugin = plugin->prev;
err = snd_pcm_plugin_alloc(plugin, frames);
if (err < 0)
@@ -148,8 +153,10 @@ int snd_pcm_plugin_build(struct snd_pcm_substream *plug,
struct snd_pcm_plugin *plugin;
unsigned int channels;
- snd_assert(plug != NULL, return -ENXIO);
- snd_assert(src_format != NULL && dst_format != NULL, return -ENXIO);
+ if (snd_BUG_ON(!plug))
+ return -ENXIO;
+ if (snd_BUG_ON(!src_format || !dst_format))
+ return -ENXIO;
plugin = kzalloc(sizeof(*plugin) + extra, GFP_KERNEL);
if (plugin == NULL)
return -ENOMEM;
@@ -159,10 +166,10 @@ int snd_pcm_plugin_build(struct snd_pcm_substream *plug,
plugin->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
plugin->src_format = *src_format;
plugin->src_width = snd_pcm_format_physical_width(src_format->format);
- snd_assert(plugin->src_width > 0, );
+ snd_BUG_ON(plugin->src_width <= 0);
plugin->dst_format = *dst_format;
plugin->dst_width = snd_pcm_format_physical_width(dst_format->format);
- snd_assert(plugin->dst_width > 0, );
+ snd_BUG_ON(plugin->dst_width <= 0);
if (plugin->stream == SNDRV_PCM_STREAM_PLAYBACK)
channels = src_format->channels;
else
@@ -194,7 +201,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_p
struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
int stream = snd_pcm_plug_stream(plug);
- snd_assert(plug != NULL, return -ENXIO);
+ if (snd_BUG_ON(!plug))
+ return -ENXIO;
if (drv_frames == 0)
return 0;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -224,7 +232,8 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc
snd_pcm_sframes_t frames;
int stream = snd_pcm_plug_stream(plug);
- snd_assert(plug != NULL, return -ENXIO);
+ if (snd_BUG_ON(!plug))
+ return -ENXIO;
if (clt_frames == 0)
return 0;
frames = clt_frames;
@@ -540,7 +549,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plu
int width, nchannels, channel;
int stream = snd_pcm_plug_stream(plug);
- snd_assert(buf != NULL, return -ENXIO);
+ if (snd_BUG_ON(!buf))
+ return -ENXIO;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
plugin = snd_pcm_plug_first(plug);
format = &plugin->src_format;
@@ -553,7 +563,9 @@ snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plu
if ((width = snd_pcm_format_physical_width(format->format)) < 0)
return width;
nchannels = format->channels;
- snd_assert(plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || format->channels <= 1, return -ENXIO);
+ if (snd_BUG_ON(plugin->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
+ format->channels > 1))
+ return -ENXIO;
for (channel = 0; channel < nchannels; channel++, v++) {
v->frames = count;
v->enabled = 1;
diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c
index 14dfb3175d84..a466443c4a26 100644
--- a/sound/core/oss/rate.c
+++ b/sound/core/oss/rate.c
@@ -185,7 +185,8 @@ static snd_pcm_sframes_t rate_src_frames(struct snd_pcm_plugin *plugin, snd_pcm_
struct rate_priv *data;
snd_pcm_sframes_t res;
- snd_assert(plugin != NULL, return -ENXIO);
+ if (snd_BUG_ON(!plugin))
+ return -ENXIO;
if (frames == 0)
return 0;
data = (struct rate_priv *)plugin->extra_data;
@@ -217,7 +218,8 @@ static snd_pcm_sframes_t rate_dst_frames(struct snd_pcm_plugin *plugin, snd_pcm_
struct rate_priv *data;
snd_pcm_sframes_t res;
- snd_assert(plugin != NULL, return -ENXIO);
+ if (snd_BUG_ON(!plugin))
+ return -ENXIO;
if (frames == 0)
return 0;
data = (struct rate_priv *)plugin->extra_data;
@@ -252,19 +254,20 @@ static snd_pcm_sframes_t rate_transfer(struct snd_pcm_plugin *plugin,
snd_pcm_uframes_t dst_frames;
struct rate_priv *data;
- snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO);
+ if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
+ return -ENXIO;
if (frames == 0)
return 0;
#ifdef CONFIG_SND_DEBUG
{
unsigned int channel;
for (channel = 0; channel < plugin->src_format.channels; channel++) {
- snd_assert(src_channels[channel].area.first % 8 == 0 &&
- src_channels[channel].area.step % 8 == 0,
- return -ENXIO);
- snd_assert(dst_channels[channel].area.first % 8 == 0 &&
- dst_channels[channel].area.step % 8 == 0,
- return -ENXIO);
+ if (snd_BUG_ON(src_channels[channel].area.first % 8 ||
+ src_channels[channel].area.step % 8))
+ return -ENXIO;
+ if (snd_BUG_ON(dst_channels[channel].area.first % 8 ||
+ dst_channels[channel].area.step % 8))
+ return -ENXIO;
}
}
#endif
@@ -281,7 +284,8 @@ static int rate_action(struct snd_pcm_plugin *plugin,
enum snd_pcm_plugin_action action,
unsigned long udata)
{
- snd_assert(plugin != NULL, return -ENXIO);
+ if (snd_BUG_ON(!plugin))
+ return -ENXIO;
switch (action) {
case INIT:
case PREPARE:
@@ -302,14 +306,20 @@ int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug,
struct rate_priv *data;
struct snd_pcm_plugin *plugin;
- snd_assert(r_plugin != NULL, return -ENXIO);
+ if (snd_BUG_ON(!r_plugin))
+ return -ENXIO;
*r_plugin = NULL;
- snd_assert(src_format->channels == dst_format->channels, return -ENXIO);
- snd_assert(src_format->channels > 0, return -ENXIO);
- snd_assert(src_format->format == SNDRV_PCM_FORMAT_S16, return -ENXIO);
- snd_assert(dst_format->format == SNDRV_PCM_FORMAT_S16, return -ENXIO);
- snd_assert(src_format->rate != dst_format->rate, return -ENXIO);
+ if (snd_BUG_ON(src_format->channels != dst_format->channels))
+ return -ENXIO;
+ if (snd_BUG_ON(src_format->channels <= 0))
+ return -ENXIO;
+ if (snd_BUG_ON(src_format->format != SNDRV_PCM_FORMAT_S16))
+ return -ENXIO;
+ if (snd_BUG_ON(dst_format->format != SNDRV_PCM_FORMAT_S16))
+ return -ENXIO;
+ if (snd_BUG_ON(src_format->rate == dst_format->rate))
+ return -ENXIO;
err = snd_pcm_plugin_build(plug, "rate conversion",
src_format, dst_format,
diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c
index da7ab7a3e82c..0dcc2870d537 100644
--- a/sound/core/oss/route.c
+++ b/sound/core/oss/route.c
@@ -54,7 +54,8 @@ static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin,
struct snd_pcm_plugin_channel *dvp;
int format;
- snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO);
+ if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
+ return -ENXIO;
if (frames == 0)
return 0;
@@ -90,10 +91,13 @@ int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug,
struct snd_pcm_plugin *plugin;
int err;
- snd_assert(r_plugin != NULL, return -ENXIO);
+ if (snd_BUG_ON(!r_plugin))
+ return -ENXIO;
*r_plugin = NULL;
- snd_assert(src_format->rate == dst_format->rate, return -ENXIO);
- snd_assert(src_format->format == dst_format->format, return -ENXIO);
+ if (snd_BUG_ON(src_format->rate != dst_format->rate))
+ return -ENXIO;
+ if (snd_BUG_ON(src_format->format != dst_format->format))
+ return -ENXIO;
err = snd_pcm_plugin_build(plug, "route conversion",
src_format, dst_format, 0, &plugin);
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index ece25c718e95..192a433a2403 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -42,7 +42,7 @@ static int snd_pcm_dev_free(struct snd_device *device);
static int snd_pcm_dev_register(struct snd_device *device);
static int snd_pcm_dev_disconnect(struct snd_device *device);
-static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device)
+static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device)
{
struct snd_pcm *pcm;
@@ -53,6 +53,37 @@ static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device)
return NULL;
}
+static int snd_pcm_next(struct snd_card *card, int device)
+{
+ struct snd_pcm *pcm;
+
+ list_for_each_entry(pcm, &snd_pcm_devices, list) {
+ if (pcm->card == card && pcm->device > device)
+ return pcm->device;
+ else if (pcm->card->number > card->number)
+ return -1;
+ }
+ return -1;
+}
+
+static int snd_pcm_add(struct snd_pcm *newpcm)
+{
+ struct snd_pcm *pcm;
+
+ list_for_each_entry(pcm, &snd_pcm_devices, list) {
+ if (pcm->card == newpcm->card && pcm->device == newpcm->device)
+ return -EBUSY;
+ if (pcm->card->number > newpcm->card->number ||
+ (pcm->card == newpcm->card &&
+ pcm->device > newpcm->device)) {
+ list_add(&newpcm->list, pcm->list.prev);
+ return 0;
+ }
+ }
+ list_add_tail(&newpcm->list, &snd_pcm_devices);
+ return 0;
+}
+
static int snd_pcm_control_ioctl(struct snd_card *card,
struct snd_ctl_file *control,
unsigned int cmd, unsigned long arg)
@@ -65,14 +96,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
if (get_user(device, (int __user *)arg))
return -EFAULT;
mutex_lock(®ister_mutex);
- device = device < 0 ? 0 : device + 1;
- while (device < SNDRV_PCM_DEVICES) {
- if (snd_pcm_search(card, device))
- break;
- device++;
- }
- if (device == SNDRV_PCM_DEVICES)
- device = -1;
+ device = snd_pcm_next(card, device);
mutex_unlock(®ister_mutex);
if (put_user(device, (int __user *)arg))
return -EFAULT;
@@ -98,7 +122,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
if (get_user(subdevice, &info->subdevice))
return -EFAULT;
mutex_lock(®ister_mutex);
- pcm = snd_pcm_search(card, device);
+ pcm = snd_pcm_get(card, device);
if (pcm == NULL) {
err = -ENXIO;
goto _error;
@@ -232,7 +256,6 @@ static char *snd_pcm_tstamp_mode_names[] = {
static const char *snd_pcm_stream_name(int stream)
{
- snd_assert(stream <= SNDRV_PCM_STREAM_LAST, return NULL);
return snd_pcm_stream_names[stream];
}
@@ -248,7 +271,6 @@ static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat)
static const char *snd_pcm_tstamp_mode_name(int mode)
{
- snd_assert(mode <= SNDRV_PCM_TSTAMP_LAST, return NULL);
return snd_pcm_tstamp_mode_names[mode];
}
@@ -682,9 +704,10 @@ int snd_pcm_new(struct snd_card *card, char *id, int device,
.dev_disconnect = snd_pcm_dev_disconnect,
};
- snd_assert(rpcm != NULL, return -EINVAL);
- *rpcm = NULL;
- snd_assert(card != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card))
+ return -ENXIO;
+ if (rpcm)
+ *rpcm = NULL;
pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
if (pcm == NULL) {
snd_printk(KERN_ERR "Cannot allocate PCM\n");
@@ -708,7 +731,8 @@ int snd_pcm_new(struct snd_card *card, char *id, int device,
snd_pcm_free(pcm);
return err;
}
- *rpcm = pcm;
+ if (rpcm)
+ *rpcm = pcm;
return 0;
}
@@ -742,7 +766,8 @@ static int snd_pcm_free(struct snd_pcm *pcm)
{
struct snd_pcm_notify *notify;
- snd_assert(pcm != NULL, return -ENXIO);
+ if (!pcm)
+ return 0;
list_for_each_entry(notify, &snd_pcm_notify_list, list) {
notify->n_unregister(pcm);
}
@@ -773,9 +798,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
int prefer_subdevice = -1;
size_t size;
- snd_assert(rsubstream != NULL, return -EINVAL);
+ if (snd_BUG_ON(!pcm || !rsubstream))
+ return -ENXIO;
*rsubstream = NULL;
- snd_assert(pcm != NULL, return -ENXIO);
pstr = &pcm->streams[stream];
if (pstr->substream == NULL || pstr->substream_count == 0)
return -ENODEV;
@@ -883,8 +908,9 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime;
+ if (PCM_RUNTIME_CHECK(substream))
+ return;
runtime = substream->runtime;
- snd_assert(runtime != NULL, return);
if (runtime->private_free != NULL)
runtime->private_free(runtime);
snd_free_pages((void*)runtime->status,
@@ -929,13 +955,14 @@ static int snd_pcm_dev_register(struct snd_device *device)
struct snd_pcm *pcm = device->device_data;
struct device *dev;
- snd_assert(pcm != NULL && device != NULL, return -ENXIO);
+ if (snd_BUG_ON(!pcm || !device))
+ return -ENXIO;
mutex_lock(®ister_mutex);
- if (snd_pcm_search(pcm->card, pcm->device)) {
+ err = snd_pcm_add(pcm);
+ if (err) {
mutex_unlock(®ister_mutex);
- return -EBUSY;
+ return err;
}
- list_add_tail(&pcm->list, &snd_pcm_devices);
for (cidx = 0; cidx < 2; cidx++) {
int devtype = -1;
if (pcm->streams[cidx].substream == NULL)
@@ -1019,10 +1046,11 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
{
struct snd_pcm *pcm;
- snd_assert(notify != NULL &&
- notify->n_register != NULL &&
- notify->n_unregister != NULL &&
- notify->n_disconnect, return -EINVAL);
+ if (snd_BUG_ON(!notify ||
+ !notify->n_register ||
+ !notify->n_unregister ||
+ !notify->n_disconnect))
+ return -EINVAL;
mutex_lock(®ister_mutex);
if (nfree) {
list_del(¬ify->list);
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 49aa693fba8a..36d7a5998234 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -397,7 +397,8 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
snd_pcm_uframes_t boundary;
int err;
- snd_assert(runtime, return -EINVAL);
+ if (snd_BUG_ON(!runtime))
+ return -EINVAL;
if (get_user(sflags, &src->flags) ||
get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 1533f0379e9d..6ea5cfb83998 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -85,7 +85,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
}
frames = runtime->buffer_size - runtime->silence_filled;
}
- snd_assert(frames <= runtime->buffer_size, return);
+ if (snd_BUG_ON(frames > runtime->buffer_size))
+ return;
if (frames == 0)
return;
ofs = runtime->silence_start % runtime->buffer_size;
@@ -96,7 +97,7 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
if (substream->ops->silence) {
int err;
err = substream->ops->silence(substream, -1, ofs, transfer);
- snd_assert(err >= 0, );
+ snd_BUG_ON(err < 0);
} else {
char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs);
snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels);
@@ -108,7 +109,7 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
for (c = 0; c < channels; ++c) {
int err;
err = substream->ops->silence(substream, c, ofs, transfer);
- snd_assert(err >= 0, );
+ snd_BUG_ON(err < 0);
}
} else {
size_t dma_csize = runtime->dma_bytes / channels;
@@ -354,7 +355,7 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b,
{
u_int64_t n = (u_int64_t) a * b;
if (c == 0) {
- snd_assert(n > 0, );
+ snd_BUG_ON(!n);
*r = 0;
return UINT_MAX;
}
@@ -380,7 +381,8 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b,
int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v)
{
int changed = 0;
- snd_assert(!snd_interval_empty(i), return -EINVAL);
+ if (snd_BUG_ON(snd_interval_empty(i)))
+ return -EINVAL;
if (i->min < v->min) {
i->min = v->min;
i->openmin = v->openmin;
@@ -423,7 +425,8 @@ EXPORT_SYMBOL(snd_interval_refine);
static int snd_interval_refine_first(struct snd_interval *i)
{
- snd_assert(!snd_interval_empty(i), return -EINVAL);
+ if (snd_BUG_ON(snd_interval_empty(i)))
+ return -EINVAL;
if (snd_interval_single(i))
return 0;
i->max = i->min;
@@ -435,7 +438,8 @@ static int snd_interval_refine_first(struct snd_interval *i)
static int snd_interval_refine_last(struct snd_interval *i)
{
- snd_assert(!snd_interval_empty(i), return -EINVAL);
+ if (snd_BUG_ON(snd_interval_empty(i)))
+ return -EINVAL;
if (snd_interval_single(i))
return 0;
i->min = i->max;
@@ -889,7 +893,8 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
c->private = private;
k = 0;
while (1) {
- snd_assert(k < ARRAY_SIZE(c->deps), return -EINVAL);
+ if (snd_BUG_ON(k >= ARRAY_SIZE(c->deps)))
+ return -EINVAL;
c->deps[k++] = dep;
if (dep < 0)
break;
@@ -1285,7 +1290,8 @@ int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm,
return changed;
if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
- snd_assert(err >= 0, return err);
+ if (snd_BUG_ON(err < 0))
+ return err;
}
return snd_pcm_hw_param_value(params, var, dir);
}
@@ -1330,7 +1336,8 @@ int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
return changed;
if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
- snd_assert(err >= 0, return err);
+ if (snd_BUG_ON(err < 0))
+ return err;
}
return snd_pcm_hw_param_value(params, var, dir);
}
@@ -1368,7 +1375,8 @@ int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
err = snd_pcm_hw_param_first(pcm, params, *v, NULL);
else
err = snd_pcm_hw_param_last(pcm, params, *v, NULL);
- snd_assert(err >= 0, return err);
+ if (snd_BUG_ON(err < 0))
+ return err;
}
return 0;
}
@@ -1466,9 +1474,9 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime;
unsigned long flags;
- snd_assert(substream != NULL, return);
+ if (PCM_RUNTIME_CHECK(substream))
+ return;
runtime = substream->runtime;
- snd_assert(runtime != NULL, return);
if (runtime->transfer_ack_begin)
runtime->transfer_ack_begin(substream);
@@ -1567,7 +1575,6 @@ static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
return err;
} else {
char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
- snd_assert(runtime->dma_area, return -EFAULT);
if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames)))
return -EFAULT;
}
@@ -1629,7 +1636,10 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
if (frames > cont)
frames = cont;
- snd_assert(frames != 0, snd_pcm_stream_unlock_irq(substream); return -EINVAL);
+ if (snd_BUG_ON(!frames)) {
+ snd_pcm_stream_unlock_irq(substream);
+ return -EINVAL;
+ }
appl_ptr = runtime->control->appl_ptr;
appl_ofs = appl_ptr % runtime->buffer_size;
snd_pcm_stream_unlock_irq(substream);
@@ -1669,18 +1679,30 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
}
+/* sanity-check for read/write methods */
+static int pcm_sanity_check(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime;
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
+ runtime = substream->runtime;
+ if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area))
+ return -EINVAL;
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
+ return 0;
+}
+
snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const void __user *buf, snd_pcm_uframes_t size)
{
struct snd_pcm_runtime *runtime;
int nonblock;
+ int err;
- snd_assert(substream != NULL, return -ENXIO);
+ err = pcm_sanity_check(substream);
+ if (err < 0)
+ return err;
runtime = substream->runtime;
- snd_assert(runtime != NULL, return -ENXIO);
- snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL);
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
-
nonblock = !!(substream->f_flags & O_NONBLOCK);
if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
@@ -1703,7 +1725,8 @@ static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
int channels = runtime->channels;
int c;
if (substream->ops->copy) {
- snd_assert(substream->ops->silence != NULL, return -EINVAL);
+ if (snd_BUG_ON(!substream->ops->silence))
+ return -EINVAL;
for (c = 0; c < channels; ++c, ++bufs) {
if (*bufs == NULL) {
if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0)
@@ -1717,7 +1740,6 @@ static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
} else {
/* default transfer behaviour */
size_t dma_csize = runtime->dma_bytes / channels;
- snd_assert(runtime->dma_area, return -EFAULT);
for (c = 0; c < channels; ++c, ++bufs) {
char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
if (*bufs == NULL) {
@@ -1738,14 +1760,12 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
{
struct snd_pcm_runtime *runtime;
int nonblock;
+ int err;
- snd_assert(substream != NULL, return -ENXIO);
+ err = pcm_sanity_check(substream);
+ if (err < 0)
+ return err;
runtime = substream->runtime;
- snd_assert(runtime != NULL, return -ENXIO);
- snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL);
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
-
nonblock = !!(substream->f_flags & O_NONBLOCK);
if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
@@ -1769,7 +1789,6 @@ static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream,
return err;
} else {
char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
- snd_assert(runtime->dma_area, return -EFAULT);
if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames)))
return -EFAULT;
}
@@ -1841,7 +1860,10 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
if (frames > cont)
frames = cont;
- snd_assert(frames != 0, snd_pcm_stream_unlock_irq(substream); return -EINVAL);
+ if (snd_BUG_ON(!frames)) {
+ snd_pcm_stream_unlock_irq(substream);
+ return -EINVAL;
+ }
appl_ptr = runtime->control->appl_ptr;
appl_ofs = appl_ptr % runtime->buffer_size;
snd_pcm_stream_unlock_irq(substream);
@@ -1879,14 +1901,12 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u
{
struct snd_pcm_runtime *runtime;
int nonblock;
+ int err;
- snd_assert(substream != NULL, return -ENXIO);
+ err = pcm_sanity_check(substream);
+ if (err < 0)
+ return err;
runtime = substream->runtime;
- snd_assert(runtime != NULL, return -ENXIO);
- snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL);
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
-
nonblock = !!(substream->f_flags & O_NONBLOCK);
if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
return -EINVAL;
@@ -1916,7 +1936,6 @@ static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
}
} else {
snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels;
- snd_assert(runtime->dma_area, return -EFAULT);
for (c = 0; c < channels; ++c, ++bufs) {
char *hwbuf;
char __user *buf;
@@ -1938,11 +1957,12 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
{
struct snd_pcm_runtime *runtime;
int nonblock;
+ int err;
- snd_assert(substream != NULL, return -ENXIO);
+ err = pcm_sanity_check(substream);
+ if (err < 0)
+ return err;
runtime = substream->runtime;
- snd_assert(runtime != NULL, return -ENXIO);
- snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL);
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index ff07b4a9992e..a6d42808828c 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -50,8 +50,6 @@ static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t siz
struct snd_dma_buffer *dmab = &substream->dma_buffer;
int err;
- snd_assert(size > 0, return -EINVAL);
-
/* already reserved? */
if (snd_dma_get_reserved_buf(dmab, substream->dma_buf_id) > 0) {
if (dmab->bytes >= size)
@@ -326,6 +324,32 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne
EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
+/*
+ * compute the max chunk size with continuous pages on sg-buffer
+ */
+unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream,
+ unsigned int ofs, unsigned int size)
+{
+ struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream);
+ unsigned int start, end, pg;
+
+ start = ofs >> PAGE_SHIFT;
+ end = (ofs + size - 1) >> PAGE_SHIFT;
+ /* check page continuity */
+ pg = sg->table[start].addr >> PAGE_SHIFT;
+ for (;;) {
+ start++;
+ if (start > end)
+ break;
+ pg++;
+ if ((sg->table[start].addr >> PAGE_SHIFT) != pg)
+ return (start << PAGE_SHIFT) - ofs;
+ }
+ /* ok, all on continuous pages */
+ return size;
+}
+EXPORT_SYMBOL(snd_pcm_sgbuf_get_chunk_size);
+
/**
* snd_pcm_lib_malloc_pages - allocate the DMA buffer
* @substream: the substream to allocate the DMA buffer to
@@ -342,10 +366,12 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
struct snd_pcm_runtime *runtime;
struct snd_dma_buffer *dmab = NULL;
- snd_assert(substream->dma_buffer.dev.type != SNDRV_DMA_TYPE_UNKNOWN, return -EINVAL);
- snd_assert(substream != NULL, return -EINVAL);
+ if (PCM_RUNTIME_CHECK(substream))
+ return -EINVAL;
+ if (snd_BUG_ON(substream->dma_buffer.dev.type ==
+ SNDRV_DMA_TYPE_UNKNOWN))
+ return -EINVAL;
runtime = substream->runtime;
- snd_assert(runtime != NULL, return -EINVAL);
if (runtime->dma_buffer_p) {
/* perphaps, we might free the large DMA memory region
@@ -391,9 +417,9 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime;
- snd_assert(substream != NULL, return -EINVAL);
+ if (PCM_RUNTIME_CHECK(substream))
+ return -EINVAL;
runtime = substream->runtime;
- snd_assert(runtime != NULL, return -EINVAL);
if (runtime->dma_area == NULL)
return 0;
if (runtime->dma_buffer_p != &substream->dma_buffer) {
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index c487025d3457..e61e12506ded 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -95,7 +95,6 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
struct snd_pcm *pcm = substream->pcm;
struct snd_pcm_str *pstr = substream->pstr;
- snd_assert(substream != NULL, return -ENXIO);
memset(info, 0, sizeof(*info));
info->card = pcm->card->number;
info->device = pcm->device;
@@ -370,9 +369,9 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
unsigned int bits;
snd_pcm_uframes_t frames;
- snd_assert(substream != NULL, return -ENXIO);
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
runtime = substream->runtime;
- snd_assert(runtime != NULL, return -ENXIO);
snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_OPEN:
@@ -490,9 +489,9 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime;
int result = 0;
- snd_assert(substream != NULL, return -ENXIO);
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
runtime = substream->runtime;
- snd_assert(runtime != NULL, return -ENXIO);
snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_SETUP:
@@ -518,9 +517,9 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
{
struct snd_pcm_runtime *runtime;
- snd_assert(substream != NULL, return -ENXIO);
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
runtime = substream->runtime;
- snd_assert(runtime != NULL, return -ENXIO);
snd_pcm_stream_lock_irq(substream);
if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
snd_pcm_stream_unlock_irq(substream);
@@ -622,11 +621,8 @@ static int snd_pcm_status_user(struct snd_pcm_substream *substream,
struct snd_pcm_status __user * _status)
{
struct snd_pcm_status status;
- struct snd_pcm_runtime *runtime;
int res;
- snd_assert(substream != NULL, return -ENXIO);
- runtime = substream->runtime;
memset(&status, 0, sizeof(status));
res = snd_pcm_status(substream, &status);
if (res < 0)
@@ -642,7 +638,6 @@ static int snd_pcm_channel_info(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime;
unsigned int channel;
- snd_assert(substream != NULL, return -ENXIO);
channel = info->channel;
runtime = substream->runtime;
snd_pcm_stream_lock_irq(substream);
@@ -1250,7 +1245,6 @@ static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state)
int err = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL);
if (err < 0)
return err;
- // snd_assert(runtime->status->hw_ptr < runtime->buffer_size, );
runtime->hw_ptr_base = 0;
runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
runtime->status->hw_ptr % runtime->period_size;
@@ -1421,7 +1415,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
int i, num_drecs;
struct drain_rec *drec, drec_tmp, *d;
- snd_assert(substream != NULL, return -ENXIO);
card = substream->pcm->card;
runtime = substream->runtime;
@@ -1541,7 +1534,8 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
struct snd_card *card;
int result = 0;
- snd_assert(substream != NULL, return -ENXIO);
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
runtime = substream->runtime;
card = substream->pcm->card;
@@ -1934,33 +1928,41 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
mask |= 1 << SNDRV_PCM_ACCESS_MMAP_COMPLEX;
}
err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_ACCESS, mask);
- snd_assert(err >= 0, return -EINVAL);
+ if (err < 0)
+ return err;
err = snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats);
- snd_assert(err >= 0, return -EINVAL);
+ if (err < 0)
+ return err;
err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD);
- snd_assert(err >= 0, return -EINVAL);
+ if (err < 0)
+ return err;
err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS,
hw->channels_min, hw->channels_max);
- snd_assert(err >= 0, return -EINVAL);
+ if (err < 0)
+ return err;
err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
hw->rate_min, hw->rate_max);
- snd_assert(err >= 0, return -EINVAL);
+ if (err < 0)
+ return err;
err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
hw->period_bytes_min, hw->period_bytes_max);
- snd_assert(err >= 0, return -EINVAL);
+ if (err < 0)
+ return err;
err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS,
hw->periods_min, hw->periods_max);
- snd_assert(err >= 0, return -EINVAL);
+ if (err < 0)
+ return err;
err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
hw->period_bytes_min, hw->buffer_bytes_max);
- snd_assert(err >= 0, return -EINVAL);
+ if (err < 0)
+ return err;
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
snd_pcm_hw_rule_buffer_bytes_max, substream,
@@ -1971,7 +1973,8 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
/* FIXME: remove */
if (runtime->dma_bytes) {
err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, runtime->dma_bytes);
- snd_assert(err >= 0, return -EINVAL);
+ if (err < 0)
+ return -EINVAL;
}
if (!(hw->rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))) {
@@ -2067,8 +2070,8 @@ static int snd_pcm_open_file(struct file *file,
struct snd_pcm_str *str;
int err;
- snd_assert(rpcm_file != NULL, return -EINVAL);
- *rpcm_file = NULL;
+ if (rpcm_file)
+ *rpcm_file = NULL;
err = snd_pcm_open_substream(pcm, stream, file, &substream);
if (err < 0)
@@ -2086,7 +2089,8 @@ static int snd_pcm_open_file(struct file *file,
substream->pcm_release = pcm_release_private;
}
file->private_data = pcm_file;
- *rpcm_file = pcm_file;
+ if (rpcm_file)
+ *rpcm_file = pcm_file;
return 0;
}
@@ -2170,7 +2174,8 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
pcm_file = file->private_data;
substream = pcm_file->substream;
- snd_assert(substream != NULL, return -ENXIO);
+ if (snd_BUG_ON(!substream))
+ return -ENXIO;
pcm = substream->pcm;
fasync_helper(-1, file, 0, &substream->runtime->fasync);
mutex_lock(&pcm->open_mutex);
@@ -2493,8 +2498,6 @@ static int snd_pcm_common_ioctl1(struct file *file,
struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg)
{
- snd_assert(substream != NULL, return -ENXIO);
-
switch (cmd) {
case SNDRV_PCM_IOCTL_PVERSION:
return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
@@ -2563,8 +2566,10 @@ static int snd_pcm_playback_ioctl1(struct file *file,
struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg)
{
- snd_assert(substream != NULL, return -ENXIO);
- snd_assert(substream->stream == SNDRV_PCM_STREAM_PLAYBACK, return -EINVAL);
+ if (snd_BUG_ON(!substream))
+ return -ENXIO;
+ if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
+ return -EINVAL;
switch (cmd) {
case SNDRV_PCM_IOCTL_WRITEI_FRAMES:
{
@@ -2643,8 +2648,10 @@ static int snd_pcm_capture_ioctl1(struct file *file,
struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg)
{
- snd_assert(substream != NULL, return -ENXIO);
- snd_assert(substream->stream == SNDRV_PCM_STREAM_CAPTURE, return -EINVAL);
+ if (snd_BUG_ON(!substream))
+ return -ENXIO;
+ if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE))
+ return -EINVAL;
switch (cmd) {
case SNDRV_PCM_IOCTL_READI_FRAMES:
{
@@ -2783,7 +2790,8 @@ static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
pcm_file = file->private_data;
substream = pcm_file->substream;
- snd_assert(substream != NULL, return -ENXIO);
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
@@ -2806,21 +2814,17 @@ static ssize_t snd_pcm_write(struct file *file, const char __user *buf,
pcm_file = file->private_data;
substream = pcm_file->substream;
- snd_assert(substream != NULL, result = -ENXIO; goto end);
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
runtime = substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
- result = -EBADFD;
- goto end;
- }
- if (!frame_aligned(runtime, count)) {
- result = -EINVAL;
- goto end;
- }
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
+ if (!frame_aligned(runtime, count))
+ return -EINVAL;
count = bytes_to_frames(runtime, count);
result = snd_pcm_lib_write(substream, buf, count);
if (result > 0)
result = frames_to_bytes(runtime, result);
- end:
return result;
}
@@ -2838,7 +2842,8 @@ static ssize_t snd_pcm_aio_read(struct kiocb *iocb, const struct iovec *iov,
pcm_file = iocb->ki_filp->private_data;
substream = pcm_file->substream;
- snd_assert(substream != NULL, return -ENXIO);
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
@@ -2872,17 +2877,14 @@ static ssize_t snd_pcm_aio_write(struct kiocb *iocb, const struct iovec *iov,
pcm_file = iocb->ki_filp->private_data;
substream = pcm_file->substream;
- snd_assert(substream != NULL, result = -ENXIO; goto end);
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
runtime = substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
- result = -EBADFD;
- goto end;
- }
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
if (nr_segs > 128 || nr_segs != runtime->channels ||
- !frame_aligned(runtime, iov->iov_len)) {
- result = -EINVAL;
- goto end;
- }
+ !frame_aligned(runtime, iov->iov_len))
+ return -EINVAL;
frames = bytes_to_samples(runtime, iov->iov_len);
bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL);
if (bufs == NULL)
@@ -2893,7 +2895,6 @@ static ssize_t snd_pcm_aio_write(struct kiocb *iocb, const struct iovec *iov,
if (result > 0)
result = frames_to_bytes(runtime, result);
kfree(bufs);
- end:
return result;
}
@@ -2908,7 +2909,8 @@ static unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
pcm_file = file->private_data;
substream = pcm_file->substream;
- snd_assert(substream != NULL, return -ENXIO);
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
runtime = substream->runtime;
poll_wait(file, &runtime->sleep, wait);
@@ -2946,7 +2948,8 @@ static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
pcm_file = file->private_data;
substream = pcm_file->substream;
- snd_assert(substream != NULL, return -ENXIO);
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
runtime = substream->runtime;
poll_wait(file, &runtime->sleep, wait);
@@ -3016,7 +3019,6 @@ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file
if (!(area->vm_flags & VM_READ))
return -EINVAL;
runtime = substream->runtime;
- snd_assert(runtime != NULL, return -EAGAIN);
size = area->vm_end - area->vm_start;
if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)))
return -EINVAL;
@@ -3056,7 +3058,6 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
if (!(area->vm_flags & VM_READ))
return -EINVAL;
runtime = substream->runtime;
- snd_assert(runtime != NULL, return -EAGAIN);
size = area->vm_end - area->vm_start;
if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)))
return -EINVAL;
@@ -3188,7 +3189,6 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
return -EINVAL;
}
runtime = substream->runtime;
- snd_assert(runtime != NULL, return -EAGAIN);
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (!(runtime->info & SNDRV_PCM_INFO_MMAP))
@@ -3220,7 +3220,8 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
pcm_file = file->private_data;
substream = pcm_file->substream;
- snd_assert(substream != NULL, return -ENXIO);
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
offset = area->vm_pgoff << PAGE_SHIFT;
switch (offset) {
@@ -3248,9 +3249,9 @@ static int snd_pcm_fasync(int fd, struct file * file, int on)
lock_kernel();
pcm_file = file->private_data;
substream = pcm_file->substream;
- snd_assert(substream != NULL, goto out);
+ if (PCM_RUNTIME_CHECK(substream))
+ goto out;
runtime = substream->runtime;
-
err = fasync_helper(fd, file, on, &runtime->fasync);
out:
unlock_kernel();
@@ -3384,6 +3385,17 @@ out:
}
#endif /* CONFIG_SND_SUPPORT_OLD_API */
+#ifndef CONFIG_MMU
+unsigned long dummy_get_unmapped_area(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags)
+{
+ return 0;
+}
+#else
+# define dummy_get_unmapped_area NULL
+#endif
+
/*
* Register section
*/
@@ -3400,6 +3412,7 @@ const struct file_operations snd_pcm_f_ops[2] = {
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
.fasync = snd_pcm_fasync,
+ .get_unmapped_area = dummy_get_unmapped_area,
},
{
.owner = THIS_MODULE,
@@ -3412,5 +3425,6 @@ const struct file_operations snd_pcm_f_ops[2] = {
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
.fasync = snd_pcm_fasync,
+ .get_unmapped_area = dummy_get_unmapped_area,
}
};
diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c
index 033a024d153a..2c89c04f2916 100644
--- a/sound/core/pcm_timer.c
+++ b/sound/core/pcm_timer.c
@@ -51,12 +51,14 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream)
mult = 1000000000;
rate = runtime->rate;
- snd_assert(rate != 0, return);
+ if (snd_BUG_ON(!rate))
+ return;
l = gcd(mult, rate);
mult /= l;
rate /= l;
fsize = runtime->period_size;
- snd_assert(fsize != 0, return);
+ if (snd_BUG_ON(!fsize))
+ return;
l = gcd(rate, fsize);
rate /= l;
fsize /= l;
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index b917a9f981c7..c4995c9f5730 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -470,8 +470,8 @@ int snd_rawmidi_kernel_release(struct snd_rawmidi_file * rfile)
struct snd_rawmidi_substream *substream;
struct snd_rawmidi_runtime *runtime;
- snd_assert(rfile != NULL, return -ENXIO);
- snd_assert(rfile->input != NULL || rfile->output != NULL, return -ENXIO);
+ if (snd_BUG_ON(!rfile))
+ return -ENXIO;
rmidi = rfile->rmidi;
mutex_lock(&rmidi->open_mutex);
if (rfile->input != NULL) {
@@ -1100,7 +1100,7 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
return -EINVAL;
}
spin_lock_irqsave(&runtime->lock, flags);
- snd_assert(runtime->avail + count <= runtime->buffer_size, );
+ snd_BUG_ON(runtime->avail + count > runtime->buffer_size);
runtime->hw_ptr += count;
runtime->hw_ptr %= runtime->buffer_size;
runtime->avail += count;
@@ -1141,8 +1141,10 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
long count1, result;
struct snd_rawmidi_runtime *runtime = substream->runtime;
- snd_assert(kernelbuf != NULL || userbuf != NULL, return -EINVAL);
- snd_assert(runtime->buffer != NULL, return -EINVAL);
+ if (snd_BUG_ON(!kernelbuf && !userbuf))
+ return -EINVAL;
+ if (snd_BUG_ON(!runtime->buffer))
+ return -EINVAL;
result = 0;
spin_lock_irqsave(&runtime->lock, flags);
@@ -1420,9 +1422,10 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,
.dev_disconnect = snd_rawmidi_dev_disconnect,
};
- snd_assert(rrawmidi != NULL, return -EINVAL);
- *rrawmidi = NULL;
- snd_assert(card != NULL, return -ENXIO);
+ if (snd_BUG_ON(!card))
+ return -ENXIO;
+ if (rrawmidi)
+ *rrawmidi = NULL;
rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL);
if (rmidi == NULL) {
snd_printk(KERN_ERR "rawmidi: cannot allocate\n");
@@ -1455,7 +1458,8 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,
snd_rawmidi_free(rmidi);
return err;
}
- *rrawmidi = rmidi;
+ if (rrawmidi)
+ *rrawmidi = rmidi;
return 0;
}
@@ -1472,7 +1476,8 @@ static void snd_rawmidi_free_substreams(struct snd_rawmidi_str *stream)
static int snd_rawmidi_free(struct snd_rawmidi *rmidi)
{
- snd_assert(rmidi != NULL, return -ENXIO);
+ if (!rmidi)
+ return 0;
snd_info_free_entry(rmidi->proc_entry);
rmidi->proc_entry = NULL;
diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c
index 97b30fb4c361..51e64e30dd3b 100644
--- a/sound/core/rtctimer.c
+++ b/sound/core/rtctimer.c
@@ -91,7 +91,8 @@ static int
rtctimer_start(struct snd_timer *timer)
{
rtc_task_t *rtc = timer->private_data;
- snd_assert(rtc != NULL, return -EINVAL);
+ if (snd_BUG_ON(!rtc))
+ return -EINVAL;
rtc_control(rtc, RTC_IRQP_SET, rtctimer_freq);
rtc_control(rtc, RTC_PIE_ON, 0);
return 0;
@@ -101,7 +102,8 @@ static int
rtctimer_stop(struct snd_timer *timer)
{
rtc_task_t *rtc = timer->private_data;
- snd_assert(rtc != NULL, return -EINVAL);
+ if (snd_BUG_ON(!rtc))
+ return -EINVAL;
rtc_control(rtc, RTC_PIE_OFF, 0);
return 0;
}
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index 777796e94490..f25e3cc7ddfa 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -164,7 +164,8 @@ odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
struct seq_oss_devinfo *dp;
dp = file->private_data;
- snd_assert(dp != NULL, return -EIO);
+ if (snd_BUG_ON(!dp))
+ return -ENXIO;
return snd_seq_oss_read(dp, buf, count);
}
@@ -174,7 +175,8 @@ odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offs
{
struct seq_oss_devinfo *dp;
dp = file->private_data;
- snd_assert(dp != NULL, return -EIO);
+ if (snd_BUG_ON(!dp))
+ return -ENXIO;
return snd_seq_oss_write(dp, buf, count, file);
}
@@ -183,7 +185,8 @@ odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct seq_oss_devinfo *dp;
dp = file->private_data;
- snd_assert(dp != NULL, return -EIO);
+ if (snd_BUG_ON(!dp))
+ return -ENXIO;
return snd_seq_oss_ioctl(dp, cmd, arg);
}
@@ -198,7 +201,8 @@ odev_poll(struct file *file, poll_table * wait)
{
struct seq_oss_devinfo *dp;
dp = file->private_data;
- snd_assert(dp != NULL, return 0);
+ if (snd_BUG_ON(!dp))
+ return -ENXIO;
return snd_seq_oss_poll(dp, file, wait);
}
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index e024e4588b82..945a27c34a9d 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -308,7 +308,8 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info;
- snd_assert(dp->max_synthdev <= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS, return);
+ if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
+ return;
for (i = 0; i < dp->max_synthdev; i++) {
info = &dp->synths[i];
if (! info->opened)
@@ -402,7 +403,8 @@ snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info;
- snd_assert(dev >= 0 && dev < dp->max_synthdev, return);
+ if (snd_BUG_ON(dev < 0 || dev >= dp->max_synthdev))
+ return;
info = &dp->synths[dev];
if (! info->opened)
return;
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 7a1545d2d953..8ca2be339f3b 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -266,7 +266,8 @@ static int seq_free_client1(struct snd_seq_client *client)
{
unsigned long flags;
- snd_assert(client != NULL, return -EINVAL);
+ if (!client)
+ return 0;
snd_seq_delete_all_ports(client);
snd_seq_queue_client_leave(client->number);
spin_lock_irqsave(&clients_lock, flags);
@@ -403,7 +404,8 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,
return -EFAULT;
/* check client structures are in place */
- snd_assert(client != NULL, return -ENXIO);
+ if (snd_BUG_ON(!client))
+ return -ENXIO;
if (!client->accept_input || (fifo = client->data.user.fifo) == NULL)
return -ENXIO;
@@ -825,7 +827,8 @@ int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop)
struct snd_seq_client *client;
int result;
- snd_assert(cell != NULL, return -EINVAL);
+ if (snd_BUG_ON(!cell))
+ return -EINVAL;
client = snd_seq_client_use_ptr(cell->event.source.client);
if (client == NULL) {
@@ -994,7 +997,8 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf,
return -ENXIO;
/* check client structures are in place */
- snd_assert(client != NULL, return -ENXIO);
+ if (snd_BUG_ON(!client))
+ return -ENXIO;
if (!client->accept_output || client->pool == NULL)
return -ENXIO;
@@ -1076,7 +1080,8 @@ static unsigned int snd_seq_poll(struct file *file, poll_table * wait)
unsigned int mask = 0;
/* check client structures are in place */
- snd_assert(client != NULL, return -ENXIO);
+ if (snd_BUG_ON(!client))
+ return -ENXIO;
if ((snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_INPUT) &&
client->data.user.fifo) {
@@ -2195,7 +2200,8 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg
{
struct snd_seq_client *client = file->private_data;
- snd_assert(client != NULL, return -ENXIO);
+ if (snd_BUG_ON(!client))
+ return -ENXIO;
return snd_seq_do_ioctl(client, cmd, (void __user *) arg);
}
@@ -2216,7 +2222,8 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index,
struct snd_seq_client *client;
va_list args;
- snd_assert(! in_interrupt(), return -EBUSY);
+ if (snd_BUG_ON(in_interrupt()))
+ return -EBUSY;
if (card && client_index >= SNDRV_SEQ_CLIENTS_PER_CARD)
return -EINVAL;
@@ -2265,7 +2272,8 @@ int snd_seq_delete_kernel_client(int client)
{
struct snd_seq_client *ptr;
- snd_assert(! in_interrupt(), return -EBUSY);
+ if (snd_BUG_ON(in_interrupt()))
+ return -EBUSY;
ptr = clientptr(client);
if (ptr == NULL)
@@ -2288,7 +2296,8 @@ static int kernel_client_enqueue(int client, struct snd_seq_event *ev,
struct snd_seq_client *cptr;
int result;
- snd_assert(ev != NULL, return -EINVAL);
+ if (snd_BUG_ON(!ev))
+ return -EINVAL;
if (ev->type == SNDRV_SEQ_EVENT_NONE)
return 0; /* ignore this */
@@ -2354,7 +2363,8 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
struct snd_seq_client *cptr;
int result;
- snd_assert(ev != NULL, return -EINVAL);
+ if (snd_BUG_ON(!ev))
+ return -EINVAL;
/* fill in client number */
ev->queue = SNDRV_SEQ_QUEUE_DIRECT;
diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c
index 9628c06e4eab..38693f47c262 100644
--- a/sound/core/seq/seq_compat.c
+++ b/sound/core/seq/seq_compat.c
@@ -92,7 +92,8 @@ static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
struct snd_seq_client *client = file->private_data;
void __user *argp = compat_ptr(arg);
- snd_assert(client != NULL, return -ENXIO);
+ if (snd_BUG_ON(!client))
+ return -ENXIO;
switch (cmd) {
case SNDRV_SEQ_IOCTL_PVERSION:
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 05410e536a4f..1f997675c893 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -187,7 +187,8 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
if (result)
*result = NULL;
- snd_assert(id != NULL, return -EINVAL);
+ if (snd_BUG_ON(!id))
+ return -EINVAL;
ops = find_driver(id, 1);
if (ops == NULL)
@@ -232,7 +233,8 @@ static int snd_seq_device_free(struct snd_seq_device *dev)
{
struct ops_list *ops;
- snd_assert(dev != NULL, return -EINVAL);
+ if (snd_BUG_ON(!dev))
+ return -EINVAL;
ops = find_driver(dev->id, 0);
if (ops == NULL)
diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c
index 3a94ed021bd9..0d75afa786bc 100644
--- a/sound/core/seq/seq_fifo.c
+++ b/sound/core/seq/seq_fifo.c
@@ -65,9 +65,11 @@ void snd_seq_fifo_delete(struct snd_seq_fifo **fifo)
{
struct snd_seq_fifo *f;
- snd_assert(fifo != NULL, return);
+ if (snd_BUG_ON(!fifo))
+ return;
f = *fifo;
- snd_assert(f != NULL, return);
+ if (snd_BUG_ON(!f))
+ return;
*fifo = NULL;
snd_seq_fifo_clear(f);
@@ -116,7 +118,8 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f,
unsigned long flags;
int err;
- snd_assert(f != NULL, return -EINVAL);
+ if (snd_BUG_ON(!f))
+ return -EINVAL;
snd_use_lock_use(&f->use_lock);
err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL); /* always non-blocking */
@@ -174,7 +177,8 @@ int snd_seq_fifo_cell_out(struct snd_seq_fifo *f,
unsigned long flags;
wait_queue_t wait;
- snd_assert(f != NULL, return -EINVAL);
+ if (snd_BUG_ON(!f))
+ return -EINVAL;
*cellp = NULL;
init_waitqueue_entry(&wait, current);
@@ -233,7 +237,8 @@ int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize)
struct snd_seq_pool *newpool, *oldpool;
struct snd_seq_event_cell *cell, *next, *oldhead;
- snd_assert(f != NULL && f->pool != NULL, return -EINVAL);
+ if (snd_BUG_ON(!f || !f->pool))
+ return -EINVAL;
/* allocate new pool */
newpool = snd_seq_pool_new(poolsize);
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index 0cf6ac477318..7fb55436287f 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -187,9 +187,11 @@ void snd_seq_cell_free(struct snd_seq_event_cell * cell)
unsigned long flags;
struct snd_seq_pool *pool;
- snd_assert(cell != NULL, return);
+ if (snd_BUG_ON(!cell))
+ return;
pool = cell->pool;
- snd_assert(pool != NULL, return);
+ if (snd_BUG_ON(!pool))
+ return;
spin_lock_irqsave(&pool->lock, flags);
free_cell(pool, cell);
@@ -378,7 +380,8 @@ int snd_seq_pool_init(struct snd_seq_pool *pool)
struct snd_seq_event_cell *cellptr;
unsigned long flags;
- snd_assert(pool != NULL, return -EINVAL);
+ if (snd_BUG_ON(!pool))
+ return -EINVAL;
if (pool->ptr) /* should be atomic? */
return 0;
@@ -414,7 +417,8 @@ int snd_seq_pool_done(struct snd_seq_pool *pool)
struct snd_seq_event_cell *ptr;
int max_count = 5 * HZ;
- snd_assert(pool != NULL, return -EINVAL);
+ if (snd_BUG_ON(!pool))
+ return -EINVAL;
/* wait for closing all threads */
spin_lock_irqsave(&pool->lock, flags);
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index 99b35360c506..4d26146a62cc 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -116,7 +116,8 @@ static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, i
struct snd_rawmidi_runtime *runtime;
int tmp;
- snd_assert(substream != NULL || buf != NULL, return -EINVAL);
+ if (snd_BUG_ON(!substream || !buf))
+ return -EINVAL;
runtime = substream->runtime;
if ((tmp = runtime->avail) < count) {
snd_printd("warning, output event was lost (count = %i, available = %i)\n", count, tmp);
@@ -135,7 +136,8 @@ static int event_process_midi(struct snd_seq_event *ev, int direct,
struct snd_rawmidi_substream *substream;
int len;
- snd_assert(msynth != NULL, return -EINVAL);
+ if (snd_BUG_ON(!msynth))
+ return -EINVAL;
substream = msynth->output_rfile.output;
if (substream == NULL)
return -ENODEV;
@@ -210,7 +212,8 @@ static int midisynth_unsubscribe(void *private_data, struct snd_seq_port_subscri
int err;
struct seq_midisynth *msynth = private_data;
- snd_assert(msynth->input_rfile.input != NULL, return -EINVAL);
+ if (snd_BUG_ON(!msynth->input_rfile.input))
+ return -EINVAL;
err = snd_rawmidi_kernel_release(&msynth->input_rfile);
return err;
}
@@ -247,7 +250,8 @@ static int midisynth_unuse(void *private_data, struct snd_seq_port_subscribe *in
struct seq_midisynth *msynth = private_data;
unsigned char buf = 0xff; /* MIDI reset */
- snd_assert(msynth->output_rfile.output != NULL, return -EINVAL);
+ if (snd_BUG_ON(!msynth->output_rfile.output))
+ return -EINVAL;
/* sending single MIDI reset message to shut the device up */
snd_rawmidi_kernel_write(msynth->output_rfile.output, &buf, 1);
snd_rawmidi_drain_output(msynth->output_rfile.output);
@@ -285,7 +289,8 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev)
int device = dev->device;
unsigned int input_count = 0, output_count = 0;
- snd_assert(card != NULL && device >= 0 && device < SNDRV_RAWMIDI_DEVICES, return -EINVAL);
+ if (snd_BUG_ON(!card || device < 0 || device >= SNDRV_RAWMIDI_DEVICES))
+ return -EINVAL;
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (! info)
return -ENOMEM;
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 1c32a53d6bd8..3bf7d73ac52e 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -130,7 +130,8 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
int num = -1;
/* sanity check */
- snd_assert(client, return NULL);
+ if (snd_BUG_ON(!client))
+ return NULL;
if (client->num_ports >= SNDRV_SEQ_MAX_PORTS - 1) {
snd_printk(KERN_WARNING "too many ports for client %d\n", client->number);
@@ -268,8 +269,8 @@ static int port_delete(struct snd_seq_client *client,
if (port->private_free)
port->private_free(port->private_data);
- snd_assert(port->c_src.count == 0,);
- snd_assert(port->c_dest.count == 0,);
+ snd_BUG_ON(port->c_src.count != 0);
+ snd_BUG_ON(port->c_dest.count != 0);
kfree(port);
return 0;
@@ -336,7 +337,8 @@ int snd_seq_delete_all_ports(struct snd_seq_client *client)
int snd_seq_set_port_info(struct snd_seq_client_port * port,
struct snd_seq_port_info * info)
{
- snd_assert(port && info, return -EINVAL);
+ if (snd_BUG_ON(!port || !info))
+ return -EINVAL;
/* set port name */
if (info->name[0])
@@ -365,7 +367,8 @@ int snd_seq_set_port_info(struct snd_seq_client_port * port,
int snd_seq_get_port_info(struct snd_seq_client_port * port,
struct snd_seq_port_info * info)
{
- snd_assert(port && info, return -EINVAL);
+ if (snd_BUG_ON(!port || !info))
+ return -EINVAL;
/* get port name */
strlcpy(info->name, port->name, sizeof(info->name));
diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c
index 85969db576c9..0101a8b99b73 100644
--- a/sound/core/seq/seq_prioq.c
+++ b/sound/core/seq/seq_prioq.c
@@ -153,8 +153,8 @@ int snd_seq_prioq_cell_in(struct snd_seq_prioq * f,
int count;
int prior;
- snd_assert(f, return -EINVAL);
- snd_assert(cell, return -EINVAL);
+ if (snd_BUG_ON(!f || !cell))
+ return -EINVAL;
/* check flags */
prior = (cell->event.flags & SNDRV_SEQ_PRIORITY_MASK);
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 4a48c6ee8ee8..e7a8e9e4edb2 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -315,7 +315,8 @@ int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop)
int dest, err;
struct snd_seq_queue *q;
- snd_assert(cell != NULL, return -EINVAL);
+ if (snd_BUG_ON(!cell))
+ return -EINVAL;
dest = cell->event.queue; /* destination queue */
q = queueptr(dest);
if (q == NULL)
@@ -734,7 +735,8 @@ int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop)
{
struct snd_seq_queue *q;
- snd_assert(ev != NULL, return -EINVAL);
+ if (snd_BUG_ON(!ev))
+ return -EINVAL;
q = queueptr(ev->data.queue.queue);
if (q == NULL)
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index d8fcd62e400f..f745c317d6af 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -173,7 +173,8 @@ int snd_seq_timer_set_tempo(struct snd_seq_timer * tmr, int tempo)
{
unsigned long flags;
- snd_assert(tmr, return -EINVAL);
+ if (snd_BUG_ON(!tmr))
+ return -EINVAL;
if (tempo <= 0)
return -EINVAL;
spin_lock_irqsave(&tmr->lock, flags);
@@ -190,7 +191,8 @@ int snd_seq_timer_set_ppq(struct snd_seq_timer * tmr, int ppq)
{
unsigned long flags;
- snd_assert(tmr, return -EINVAL);
+ if (snd_BUG_ON(!tmr))
+ return -EINVAL;
if (ppq <= 0)
return -EINVAL;
spin_lock_irqsave(&tmr->lock, flags);
@@ -214,7 +216,8 @@ int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr,
{
unsigned long flags;
- snd_assert(tmr, return -EINVAL);
+ if (snd_BUG_ON(!tmr))
+ return -EINVAL;
spin_lock_irqsave(&tmr->lock, flags);
tmr->tick.cur_tick = position;
@@ -229,7 +232,8 @@ int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr,
{
unsigned long flags;
- snd_assert(tmr, return -EINVAL);
+ if (snd_BUG_ON(!tmr))
+ return -EINVAL;
snd_seq_sanity_real_time(&position);
spin_lock_irqsave(&tmr->lock, flags);
@@ -244,7 +248,8 @@ int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew,
{
unsigned long flags;
- snd_assert(tmr, return -EINVAL);
+ if (snd_BUG_ON(!tmr))
+ return -EINVAL;
/* FIXME */
if (base != SKEW_BASE) {
@@ -265,7 +270,8 @@ int snd_seq_timer_open(struct snd_seq_queue *q)
int err;
tmr = q->timer;
- snd_assert(tmr != NULL, return -EINVAL);
+ if (snd_BUG_ON(!tmr))
+ return -EINVAL;
if (tmr->timeri)
return -EBUSY;
sprintf(str, "sequencer queue %i", q->queue);
@@ -302,7 +308,8 @@ int snd_seq_timer_close(struct snd_seq_queue *q)
struct snd_seq_timer *tmr;
tmr = q->timer;
- snd_assert(tmr != NULL, return -EINVAL);
+ if (snd_BUG_ON(!tmr))
+ return -EINVAL;
if (tmr->timeri) {
snd_timer_stop(tmr->timeri);
snd_timer_close(tmr->timeri);
@@ -328,7 +335,8 @@ static int initialize_timer(struct snd_seq_timer *tmr)
unsigned long freq;
t = tmr->timeri->timer;
- snd_assert(t, return -EINVAL);
+ if (snd_BUG_ON(!t))
+ return -EINVAL;
freq = tmr->preferred_resolution;
if (!freq)
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c
index cefd228cd2aa..d4564edd61d7 100644
--- a/sound/core/sgbuf.c
+++ b/sound/core/sgbuf.c
@@ -41,9 +41,11 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab)
tmpb.dev.type = SNDRV_DMA_TYPE_DEV;
tmpb.dev.dev = sgbuf->dev;
for (i = 0; i < sgbuf->pages; i++) {
+ if (!(sgbuf->table[i].addr & ~PAGE_MASK))
+ continue; /* continuous pages */
tmpb.area = sgbuf->table[i].buf;
- tmpb.addr = sgbuf->table[i].addr;
- tmpb.bytes = PAGE_SIZE;
+ tmpb.addr = sgbuf->table[i].addr & PAGE_MASK;
+ tmpb.bytes = (sgbuf->table[i].addr & ~PAGE_MASK) << PAGE_SHIFT;
snd_dma_free_pages(&tmpb);
}
if (dmab->area)
@@ -58,13 +60,17 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab)
return 0;
}
+#define MAX_ALLOC_PAGES 32
+
void *snd_malloc_sgbuf_pages(struct device *device,
size_t size, struct snd_dma_buffer *dmab,
size_t *res_size)
{
struct snd_sg_buf *sgbuf;
- unsigned int i, pages;
+ unsigned int i, pages, chunk, maxpages;
struct snd_dma_buffer tmpb;
+ struct snd_sg_page *table;
+ struct page **pgtable;
dmab->area = NULL;
dmab->addr = 0;
@@ -74,31 +80,55 @@ void *snd_malloc_sgbuf_pages(struct device *device,
sgbuf->dev = device;
pages = snd_sgbuf_aligned_pages(size);
sgbuf->tblsize = sgbuf_align_table(pages);
- sgbuf->table = kcalloc(sgbuf->tblsize, sizeof(*sgbuf->table), GFP_KERNEL);
- if (! sgbuf->table)
+ table = kcalloc(sgbuf->tblsize, sizeof(*table), GFP_KERNEL);
+ if (!table)
goto _failed;
- sgbuf->page_table = kcalloc(sgbuf->tblsize, sizeof(*sgbuf->page_table), GFP_KERNEL);
- if (! sgbuf->page_table)
+ sgbuf->table = table;
+ pgtable = kcalloc(sgbuf->tblsize, sizeof(*pgtable), GFP_KERNEL);
+ if (!pgtable)
goto _failed;
+ sgbuf->page_table = pgtable;
- /* allocate each page */
- for (i = 0; i < pages; i++) {
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, device, PAGE_SIZE, &tmpb) < 0) {
- if (res_size == NULL)
+ /* allocate pages */
+ maxpages = MAX_ALLOC_PAGES;
+ while (pages > 0) {
+ chunk = pages;
+ /* don't be too eager to take a huge chunk */
+ if (chunk > maxpages)
+ chunk = maxpages;
+ chunk <<= PAGE_SHIFT;
+ if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, device,
+ chunk, &tmpb) < 0) {
+ if (!sgbuf->pages)
+ return NULL;
+ if (!res_size)
goto _failed;
- *res_size = size = sgbuf->pages * PAGE_SIZE;
+ size = sgbuf->pages * PAGE_SIZE;
break;
}
- sgbuf->table[i].buf = tmpb.area;
- sgbuf->table[i].addr = tmpb.addr;
- sgbuf->page_table[i] = virt_to_page(tmpb.area);
- sgbuf->pages++;
+ chunk = tmpb.bytes >> PAGE_SHIFT;
+ for (i = 0; i < chunk; i++) {
+ table->buf = tmpb.area;
+ table->addr = tmpb.addr;
+ if (!i)
+ table->addr |= chunk; /* mark head */
+ table++;
+ *pgtable++ = virt_to_page(tmpb.area);
+ tmpb.area += PAGE_SIZE;
+ tmpb.addr += PAGE_SIZE;
+ }
+ sgbuf->pages += chunk;
+ pages -= chunk;
+ if (chunk < maxpages)
+ maxpages = chunk;
}
sgbuf->size = size;
dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, PAGE_KERNEL);
if (! dmab->area)
goto _failed;
+ if (res_size)
+ *res_size = sgbuf->size;
return dmab->area;
_failed:
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 1003ae375d47..c0685e2f0afa 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -34,8 +34,6 @@
#include
#include
-#define SNDRV_OS_MINORS 256
-
static int major = CONFIG_SND_MAJOR;
int snd_major;
EXPORT_SYMBOL(snd_major);
@@ -208,20 +206,23 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
minor = type;
break;
case SNDRV_DEVICE_TYPE_CONTROL:
- snd_assert(card != NULL, return -EINVAL);
+ if (snd_BUG_ON(!card))
+ return -EINVAL;
minor = SNDRV_MINOR(card->number, type);
break;
case SNDRV_DEVICE_TYPE_HWDEP:
case SNDRV_DEVICE_TYPE_RAWMIDI:
case SNDRV_DEVICE_TYPE_PCM_PLAYBACK:
case SNDRV_DEVICE_TYPE_PCM_CAPTURE:
- snd_assert(card != NULL, return -EINVAL);
+ if (snd_BUG_ON(!card))
+ return -EINVAL;
minor = SNDRV_MINOR(card->number, type + dev);
break;
default:
return -EINVAL;
}
- snd_assert(minor >= 0 && minor < SNDRV_OS_MINORS, return -EINVAL);
+ if (snd_BUG_ON(minor < 0 || minor >= SNDRV_OS_MINORS))
+ return -EINVAL;
return minor;
}
#endif
@@ -249,7 +250,8 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
int minor;
struct snd_minor *preg;
- snd_assert(name, return -EINVAL);
+ if (snd_BUG_ON(!name))
+ return -EINVAL;
preg = kmalloc(sizeof *preg, GFP_KERNEL);
if (preg == NULL)
return -ENOMEM;
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index 7be51546eb9e..7fe12264ff80 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -64,7 +64,8 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
switch (type) {
case SNDRV_OSS_DEVICE_TYPE_MIXER:
- snd_assert(card != NULL && dev <= 1, return -EINVAL);
+ if (snd_BUG_ON(!card || dev < 0 || dev > 1))
+ return -EINVAL;
minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_MIXER1 : SNDRV_MINOR_OSS_MIXER));
break;
case SNDRV_OSS_DEVICE_TYPE_SEQUENCER:
@@ -74,11 +75,13 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
minor = SNDRV_MINOR_OSS_MUSIC;
break;
case SNDRV_OSS_DEVICE_TYPE_PCM:
- snd_assert(card != NULL && dev <= 1, return -EINVAL);
+ if (snd_BUG_ON(!card || dev < 0 || dev > 1))
+ return -EINVAL;
minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_PCM1 : SNDRV_MINOR_OSS_PCM));
break;
case SNDRV_OSS_DEVICE_TYPE_MIDI:
- snd_assert(card != NULL && dev <= 1, return -EINVAL);
+ if (snd_BUG_ON(!card || dev < 0 || dev > 1))
+ return -EINVAL;
minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_MIDI1 : SNDRV_MINOR_OSS_MIDI));
break;
case SNDRV_OSS_DEVICE_TYPE_DMFM:
@@ -90,7 +93,8 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
default:
return -EINVAL;
}
- snd_assert(minor >= 0 && minor < SNDRV_OSS_MINORS, return -EINVAL);
+ if (snd_BUG_ON(minor < 0 || minor >= SNDRV_OSS_MINORS))
+ return -EINVAL;
return minor;
}
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 0af337efc64e..e582face89d2 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -306,7 +306,8 @@ int snd_timer_close(struct snd_timer_instance *timeri)
struct snd_timer *timer = NULL;
struct snd_timer_instance *slave, *tmp;
- snd_assert(timeri != NULL, return -ENXIO);
+ if (snd_BUG_ON(!timeri))
+ return -ENXIO;
/* force to stop the timer */
snd_timer_stop(timeri);
@@ -385,8 +386,9 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
do_posix_clock_monotonic_gettime(&tstamp);
else
getnstimeofday(&tstamp);
- snd_assert(event >= SNDRV_TIMER_EVENT_START &&
- event <= SNDRV_TIMER_EVENT_PAUSE, return);
+ if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START ||
+ event > SNDRV_TIMER_EVENT_PAUSE))
+ return;
if (event == SNDRV_TIMER_EVENT_START ||
event == SNDRV_TIMER_EVENT_CONTINUE)
resolution = snd_timer_resolution(ti);
@@ -474,7 +476,8 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri,
struct snd_timer *timer;
unsigned long flags;
- snd_assert(timeri != NULL, return -ENXIO);
+ if (snd_BUG_ON(!timeri))
+ return -ENXIO;
if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
if (!keep_flag) {
@@ -758,9 +761,10 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
.dev_disconnect = snd_timer_dev_disconnect,
};
- snd_assert(tid != NULL, return -EINVAL);
- snd_assert(rtimer != NULL, return -EINVAL);
- *rtimer = NULL;
+ if (snd_BUG_ON(!tid))
+ return -EINVAL;
+ if (rtimer)
+ *rtimer = NULL;
timer = kzalloc(sizeof(*timer), GFP_KERNEL);
if (timer == NULL) {
snd_printk(KERN_ERR "timer: cannot allocate\n");
@@ -788,13 +792,15 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
return err;
}
}
- *rtimer = timer;
+ if (rtimer)
+ *rtimer = timer;
return 0;
}
static int snd_timer_free(struct snd_timer *timer)
{
- snd_assert(timer != NULL, return -ENXIO);
+ if (!timer)
+ return 0;
mutex_lock(®ister_mutex);
if (! list_empty(&timer->open_list_head)) {
@@ -827,8 +833,8 @@ static int snd_timer_dev_register(struct snd_device *dev)
struct snd_timer *timer = dev->device_data;
struct snd_timer *timer1;
- snd_assert(timer != NULL && timer->hw.start != NULL &&
- timer->hw.stop != NULL, return -ENXIO);
+ if (snd_BUG_ON(!timer || !timer->hw.start || !timer->hw.stop))
+ return -ENXIO;
if (!(timer->hw.flags & SNDRV_TIMER_HW_SLAVE) &&
!timer->hw.resolution && timer->hw.c_resolution == NULL)
return -EINVAL;
@@ -879,8 +885,9 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam
if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE))
return;
- snd_assert(event >= SNDRV_TIMER_EVENT_MSTART &&
- event <= SNDRV_TIMER_EVENT_MRESUME, return);
+ if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_MSTART ||
+ event > SNDRV_TIMER_EVENT_MRESUME))
+ return;
spin_lock_irqsave(&timer->lock, flags);
if (event == SNDRV_TIMER_EVENT_MSTART ||
event == SNDRV_TIMER_EVENT_MCONTINUE ||
diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c
index 5512f5373c52..e05802ae6e1b 100644
--- a/sound/core/timer_compat.c
+++ b/sound/core/timer_compat.c
@@ -40,9 +40,11 @@ static int snd_timer_user_info_compat(struct file *file,
struct snd_timer *t;
tu = file->private_data;
- snd_assert(tu->timeri != NULL, return -ENXIO);
+ if (snd_BUG_ON(!tu->timeri))
+ return -ENXIO;
t = tu->timeri->timer;
- snd_assert(t != NULL, return -ENXIO);
+ if (snd_BUG_ON(!t))
+ return -ENXIO;
memset(&info, 0, sizeof(info));
info.card = t->card ? t->card->number : -1;
if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
@@ -71,7 +73,8 @@ static int snd_timer_user_status_compat(struct file *file,
struct snd_timer_status status;
tu = file->private_data;
- snd_assert(tu->timeri != NULL, return -ENXIO);
+ if (snd_BUG_ON(!tu->timeri))
+ return -ENXIO;
memset(&status, 0, sizeof(status));
status.tstamp = tu->tstamp;
status.resolution = snd_timer_resolution(tu->timeri);
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 4e4c69e6cb4c..e5e749f3e0ef 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -47,9 +47,11 @@ MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}");
static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime)
{
int err;
- if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+ err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ if (err < 0)
return err;
- if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0)
+ err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX);
+ if (err) < 0)
return err;
return 0;
}
@@ -354,6 +356,7 @@ static int snd_card_dummy_playback_open(struct snd_pcm_substream *substream)
if ((dpcm = new_pcm_stream(substream)) == NULL)
return -ENOMEM;
runtime->private_data = dpcm;
+ /* makes the infrastructure responsible for freeing dpcm */
runtime->private_free = snd_card_dummy_runtime_free;
runtime->hw = snd_card_dummy_playback;
if (substream->pcm->device & 1) {
@@ -362,10 +365,9 @@ static int snd_card_dummy_playback_open(struct snd_pcm_substream *substream)
}
if (substream->pcm->device & 2)
runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID);
- if ((err = add_playback_constraints(runtime)) < 0) {
- kfree(dpcm);
+ err = add_playback_constraints(runtime);
+ if (err < 0)
return err;
- }
return 0;
}
@@ -379,6 +381,7 @@ static int snd_card_dummy_capture_open(struct snd_pcm_substream *substream)
if ((dpcm = new_pcm_stream(substream)) == NULL)
return -ENOMEM;
runtime->private_data = dpcm;
+ /* makes the infrastructure responsible for freeing dpcm */
runtime->private_free = snd_card_dummy_runtime_free;
runtime->hw = snd_card_dummy_capture;
if (substream->pcm->device == 1) {
@@ -387,10 +390,9 @@ static int snd_card_dummy_capture_open(struct snd_pcm_substream *substream)
}
if (substream->pcm->device & 2)
runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID);
- if ((err = add_capture_constraints(runtime)) < 0) {
- kfree(dpcm);
+ err = add_capture_constraints(runtime);
+ if (err < 0)
return err;
- }
return 0;
}
@@ -433,8 +435,9 @@ static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
struct snd_pcm *pcm;
int err;
- if ((err = snd_pcm_new(dummy->card, "Dummy PCM", device,
- substreams, substreams, &pcm)) < 0)
+ err = snd_pcm_new(dummy->card, "Dummy PCM", device,
+ substreams, substreams, &pcm);
+ if (err < 0)
return err;
dummy->pcm = pcm;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_dummy_playback_ops);
@@ -565,12 +568,14 @@ static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy)
unsigned int idx;
int err;
- snd_assert(dummy != NULL, return -EINVAL);
+ if (snd_BUG_ON(!dummy))
+ return -EINVAL;
spin_lock_init(&dummy->mixer_lock);
strcpy(card->mixername, "Dummy Mixer");
for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) {
- if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy))) < 0)
+ err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy));
+ if (err < 0)
return err;
}
return 0;
@@ -594,10 +599,12 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr)
pcm_substreams[dev] = 1;
if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS)
pcm_substreams[dev] = MAX_PCM_SUBSTREAMS;
- if ((err = snd_card_dummy_pcm(dummy, idx, pcm_substreams[dev])) < 0)
+ err = snd_card_dummy_pcm(dummy, idx, pcm_substreams[dev]);
+ if (err < 0)
goto __nodev;
}
- if ((err = snd_card_dummy_new_mixer(dummy)) < 0)
+ err = snd_card_dummy_new_mixer(dummy);
+ if (err < 0)
goto __nodev;
strcpy(card->driver, "Dummy");
strcpy(card->shortname, "Dummy");
@@ -605,7 +612,8 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr)
snd_card_set_dev(card, &devptr->dev);
- if ((err = snd_card_register(card)) == 0) {
+ err = snd_card_register(card);
+ if (err == 0) {
platform_set_drvdata(devptr, card);
return 0;
}
@@ -668,7 +676,8 @@ static int __init alsa_card_dummy_init(void)
{
int i, cards, err;
- if ((err = platform_driver_register(&snd_dummy_driver)) < 0)
+ err = platform_driver_register(&snd_dummy_driver);
+ if (err < 0)
return err;
cards = 0;
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index b5e1a71bb64b..5b89c0883d60 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -715,6 +715,10 @@ static int __devinit snd_mtpav_probe(struct platform_device *dev)
card->private_free = snd_mtpav_free;
+ err = snd_mtpav_get_RAWMIDI(mtp_card);
+ if (err < 0)
+ goto __error;
+
err = snd_mtpav_get_ISA(mtp_card);
if (err < 0)
goto __error;
@@ -724,10 +728,6 @@ static int __devinit snd_mtpav_probe(struct platform_device *dev)
snprintf(card->longname, sizeof(card->longname),
"MTPAV on parallel port at 0x%lx", port);
- err = snd_mtpav_get_RAWMIDI(mtp_card);
- if (err < 0)
- goto __error;
-
snd_mtpav_portscan(mtp_card);
snd_card_set_dev(card, &dev->dev);
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
index ebe4359047cb..780582340fef 100644
--- a/sound/drivers/opl3/opl3_lib.c
+++ b/sound/drivers/opl3/opl3_lib.c
@@ -139,7 +139,8 @@ static int snd_opl3_detect(struct snd_opl3 * opl3)
* If we had an OPL4 chip, opl3->hardware would have been set
* by the OPL4 driver; so we can assume OPL3 here.
*/
- snd_assert(opl3->r_port != 0, return -ENODEV);
+ if (snd_BUG_ON(!opl3->r_port))
+ return -ENODEV;
opl3->hardware = OPL3_HW_OPL3;
}
return 0;
@@ -324,7 +325,8 @@ EXPORT_SYMBOL(snd_opl3_interrupt);
static int snd_opl3_free(struct snd_opl3 *opl3)
{
- snd_assert(opl3 != NULL, return -ENXIO);
+ if (snd_BUG_ON(!opl3))
+ return -ENXIO;
if (opl3->private_free)
opl3->private_free(opl3);
snd_opl3_clear_patches(opl3);
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c
index cebcb8b78acb..16feafa2c51e 100644
--- a/sound/drivers/opl3/opl3_midi.c
+++ b/sound/drivers/opl3/opl3_midi.c
@@ -617,7 +617,8 @@ static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice)
struct snd_opl3_voice *vp, *vp2;
- snd_assert(voice < MAX_OPL3_VOICES, return);
+ if (snd_BUG_ON(voice >= MAX_OPL3_VOICES))
+ return;
vp = &opl3->voices[voice];
if (voice < MAX_OPL2_VOICES) {
@@ -737,7 +738,8 @@ static void snd_opl3_update_pitch(struct snd_opl3 *opl3, int voice)
struct snd_opl3_voice *vp;
- snd_assert(voice < MAX_OPL3_VOICES, return);
+ if (snd_BUG_ON(voice >= MAX_OPL3_VOICES))
+ return;
vp = &opl3->voices[voice];
if (vp->chan == NULL)
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c
index 239347f26154..9a2271dc046a 100644
--- a/sound/drivers/opl3/opl3_oss.c
+++ b/sound/drivers/opl3/opl3_oss.c
@@ -162,7 +162,8 @@ static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
struct snd_opl3 *opl3 = closure;
int err;
- snd_assert(arg != NULL, return -ENXIO);
+ if (snd_BUG_ON(!arg))
+ return -ENXIO;
if ((err = snd_opl3_synth_setup(opl3)) < 0)
return err;
@@ -184,7 +185,8 @@ static int snd_opl3_close_seq_oss(struct snd_seq_oss_arg *arg)
{
struct snd_opl3 *opl3;
- snd_assert(arg != NULL, return -ENXIO);
+ if (snd_BUG_ON(!arg))
+ return -ENXIO;
opl3 = arg->private_data;
snd_opl3_synth_cleanup(opl3);
@@ -206,7 +208,8 @@ static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format,
char name[32];
int err, type;
- snd_assert(arg != NULL, return -ENXIO);
+ if (snd_BUG_ON(!arg))
+ return -ENXIO;
opl3 = arg->private_data;
if (format == FM_PATCH)
@@ -246,7 +249,8 @@ static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd,
{
struct snd_opl3 *opl3;
- snd_assert(arg != NULL, return -ENXIO);
+ if (snd_BUG_ON(!arg))
+ return -ENXIO;
opl3 = arg->private_data;
switch (cmd) {
case SNDCTL_FM_LOAD_INSTR:
@@ -271,7 +275,8 @@ static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg)
{
struct snd_opl3 *opl3;
- snd_assert(arg != NULL, return -ENXIO);
+ if (snd_BUG_ON(!arg))
+ return -ENXIO;
opl3 = arg->private_data;
return 0;
diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c
index fb64c890109b..962bb9c8b9c8 100644
--- a/sound/drivers/opl3/opl3_synth.c
+++ b/sound/drivers/opl3/opl3_synth.c
@@ -92,7 +92,8 @@ int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file,
struct snd_opl3 *opl3 = hw->private_data;
void __user *argp = (void __user *)arg;
- snd_assert(opl3 != NULL, return -EINVAL);
+ if (snd_BUG_ON(!opl3))
+ return -EINVAL;
switch (cmd) {
/* get information */
diff --git a/sound/drivers/opl4/opl4_synth.c b/sound/drivers/opl4/opl4_synth.c
index 74f6e53eae0d..49b9e240915c 100644
--- a/sound/drivers/opl4/opl4_synth.c
+++ b/sound/drivers/opl4/opl4_synth.c
@@ -467,7 +467,7 @@ static struct opl4_voice *snd_opl4_get_voice(struct snd_opl4 *opl4)
if (!list_empty(&opl4->off_voices))
return list_entry(opl4->off_voices.next, struct opl4_voice, list);
/* then get the oldest key-on voice */
- snd_assert(!list_empty(&opl4->on_voices), );
+ snd_BUG_ON(list_empty(&opl4->on_voices));
return list_entry(opl4->on_voices.next, struct opl4_voice, list);
}
diff --git a/sound/drivers/vx/vx_cmd.c b/sound/drivers/vx/vx_cmd.c
index 9529e3bf2866..23f4857f02c8 100644
--- a/sound/drivers/vx/vx_cmd.c
+++ b/sound/drivers/vx/vx_cmd.c
@@ -99,7 +99,8 @@ static struct vx_cmd_info vx_dsp_cmds[] = {
*/
void vx_init_rmh(struct vx_rmh *rmh, unsigned int cmd)
{
- snd_assert(cmd < CMD_LAST_INDEX, return);
+ if (snd_BUG_ON(cmd >= CMD_LAST_INDEX))
+ return;
rmh->LgCmd = vx_dsp_cmds[cmd].length;
rmh->LgStat = vx_dsp_cmds[cmd].st_length;
rmh->DspStat = vx_dsp_cmds[cmd].st_type;
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index 585af2eb1438..473b07f6ae85 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -205,7 +205,8 @@ static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh)
if (size < 1)
return 0;
- snd_assert(size <= SIZE_MAX_STATUS, return -EINVAL);
+ if (snd_BUG_ON(size > SIZE_MAX_STATUS))
+ return -EINVAL;
for (i = 1; i <= size; i++) {
/* trigger an irq MESS_WRITE_NEXT */
@@ -425,13 +426,16 @@ int snd_vx_load_boot_image(struct vx_core *chip, const struct firmware *boot)
int no_fillup = vx_has_new_dsp(chip);
/* check the length of boot image */
- snd_assert(boot->size > 0, return -EINVAL);
- snd_assert(boot->size % 3 == 0, return -EINVAL);
+ if (boot->size <= 0)
+ return -EINVAL;
+ if (boot->size % 3)
+ return -EINVAL;
#if 0
{
/* more strict check */
unsigned int c = ((u32)boot->data[0] << 16) | ((u32)boot->data[1] << 8) | boot->data[2];
- snd_assert(boot->size == (c + 2) * 3, return -EINVAL);
+ if (boot->size != (c + 2) * 3)
+ return -EINVAL;
}
#endif
@@ -554,7 +558,8 @@ EXPORT_SYMBOL(snd_vx_irq_handler);
*/
static void vx_reset_board(struct vx_core *chip, int cold_reset)
{
- snd_assert(chip->ops->reset_board, return);
+ if (snd_BUG_ON(!chip->ops->reset_board))
+ return;
/* current source, later sync'ed with target */
chip->audio_source = VX_AUDIO_SRC_LINE;
@@ -673,7 +678,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp)
unsigned int csum = 0;
const unsigned char *image, *cptr;
- snd_assert(dsp->size % 3 == 0, return -EINVAL);
+ if (dsp->size % 3)
+ return -EINVAL;
vx_toggle_dac_mute(chip, 1);
@@ -775,7 +781,8 @@ struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw,
{
struct vx_core *chip;
- snd_assert(card && hw && ops, return NULL);
+ if (snd_BUG_ON(!card || !hw || !ops))
+ return NULL;
chip = kzalloc(sizeof(*chip) + extra_size, GFP_KERNEL);
if (! chip) {
diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c
index efd22e92bced..8d6362e2d4c9 100644
--- a/sound/drivers/vx/vx_hwdep.c
+++ b/sound/drivers/vx/vx_hwdep.c
@@ -141,7 +141,8 @@ static int vx_hwdep_dsp_status(struct snd_hwdep *hw,
};
struct vx_core *vx = hw->private_data;
- snd_assert(type_ids[vx->type], return -EINVAL);
+ if (snd_BUG_ON(!type_ids[vx->type]))
+ return -EINVAL;
strcpy(info->id, type_ids[vx->type]);
if (vx_is_pcmcia(vx))
info->num_dsps = 4;
@@ -168,7 +169,8 @@ static int vx_hwdep_dsp_load(struct snd_hwdep *hw,
int index, err;
struct firmware *fw;
- snd_assert(vx->ops->load_dsp, return -ENXIO);
+ if (snd_BUG_ON(!vx->ops->load_dsp))
+ return -ENXIO;
fw = kmalloc(sizeof(*fw), GFP_KERNEL);
if (! fw) {
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
index 5a347321f8c0..c71b8d148d7f 100644
--- a/sound/drivers/vx/vx_mixer.c
+++ b/sound/drivers/vx/vx_mixer.c
@@ -34,7 +34,8 @@ static void vx_write_codec_reg(struct vx_core *chip, int codec, unsigned int dat
{
unsigned long flags;
- snd_assert(chip->ops->write_codec, return);
+ if (snd_BUG_ON(!chip->ops->write_codec))
+ return;
if (chip->chip_status & VX_STAT_IS_STALE)
return;
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index fdbf86571b1f..27de574c08f7 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -587,7 +587,8 @@ static int vx_pcm_playback_open(struct snd_pcm_substream *subs)
return -EBUSY;
audio = subs->pcm->device * 2;
- snd_assert(audio < chip->audio_outs, return -EINVAL);
+ if (snd_BUG_ON(audio >= chip->audio_outs))
+ return -EINVAL;
/* playback pipe may have been already allocated for monitoring */
pipe = chip->playback_pipes[audio];
@@ -996,7 +997,8 @@ static int vx_pcm_capture_open(struct snd_pcm_substream *subs)
return -EBUSY;
audio = subs->pcm->device * 2;
- snd_assert(audio < chip->audio_ins, return -EINVAL);
+ if (snd_BUG_ON(audio >= chip->audio_ins))
+ return -EINVAL;
err = vx_alloc_pipe(chip, 1, audio, 2, &pipe);
if (err < 0)
return err;
@@ -1214,7 +1216,8 @@ void vx_pcm_update_intr(struct vx_core *chip, unsigned int events)
}
if (capture)
continue;
- snd_assert(p >= 0 && (unsigned int)p < chip->audio_outs,);
+ if (snd_BUG_ON(p < 0 || p >= chip->audio_outs))
+ continue;
pipe = chip->playback_pipes[p];
if (pipe && pipe->substream) {
vx_pcm_playback_update(chip, pipe->substream, pipe);
diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c
index fb8932af888d..0e1ba9b47904 100644
--- a/sound/drivers/vx/vx_uer.c
+++ b/sound/drivers/vx/vx_uer.c
@@ -163,13 +163,15 @@ static int vx_calc_clock_from_freq(struct vx_core *chip, int freq)
{
int hexfreq;
- snd_assert(freq > 0, return 0);
+ if (snd_BUG_ON(freq <= 0))
+ return 0;
hexfreq = (28224000 * 10) / freq;
hexfreq = (hexfreq + 5) / 10;
/* max freq = 55125 Hz */
- snd_assert(hexfreq > 0x00000200, return 0);
+ if (snd_BUG_ON(hexfreq <= 0x00000200))
+ return 0;
if (hexfreq <= 0x03ff)
return hexfreq - 0x00000201;
diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c
index 9c3d361accfb..020a5d512472 100644
--- a/sound/i2c/cs8427.c
+++ b/sound/i2c/cs8427.c
@@ -314,7 +314,8 @@ static void snd_cs8427_reset(struct snd_i2c_device *cs8427)
unsigned long end_time;
int data, aes3input = 0;
- snd_assert(cs8427, return);
+ if (snd_BUG_ON(!cs8427))
+ return;
chip = cs8427->private_data;
snd_i2c_lock(cs8427->bus);
if ((chip->regmap[CS8427_REG_CLOCKSOURCE] & CS8427_RXDAES3INPUT) ==
@@ -526,7 +527,8 @@ int snd_cs8427_iec958_build(struct snd_i2c_device *cs8427,
unsigned int idx;
int err;
- snd_assert(play_substream && cap_substream, return -EINVAL);
+ if (snd_BUG_ON(!play_substream || !cap_substream))
+ return -EINVAL;
for (idx = 0; idx < ARRAY_SIZE(snd_cs8427_iec958_controls); idx++) {
kctl = snd_ctl_new1(&snd_cs8427_iec958_controls[idx], cs8427);
if (kctl == NULL)
@@ -543,7 +545,8 @@ int snd_cs8427_iec958_build(struct snd_i2c_device *cs8427,
chip->playback.substream = play_substream;
chip->capture.substream = cap_substream;
- snd_assert(chip->playback.pcm_ctl, return -EIO);
+ if (snd_BUG_ON(!chip->playback.pcm_ctl))
+ return -EIO;
return 0;
}
@@ -553,7 +556,8 @@ int snd_cs8427_iec958_active(struct snd_i2c_device *cs8427, int active)
{
struct cs8427 *chip;
- snd_assert(cs8427, return -ENXIO);
+ if (snd_BUG_ON(!cs8427))
+ return -ENXIO;
chip = cs8427->private_data;
if (active)
memcpy(chip->playback.pcm_status,
@@ -573,7 +577,8 @@ int snd_cs8427_iec958_pcm(struct snd_i2c_device *cs8427, unsigned int rate)
char *status;
int err, reset;
- snd_assert(cs8427, return -ENXIO);
+ if (snd_BUG_ON(!cs8427))
+ return -ENXIO;
chip = cs8427->private_data;
status = chip->playback.pcm_status;
snd_i2c_lock(cs8427->bus);
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c
index b1e74e40cba0..5c0c77dd01c3 100644
--- a/sound/i2c/i2c.c
+++ b/sound/i2c/i2c.c
@@ -49,7 +49,8 @@ static int snd_i2c_bus_free(struct snd_i2c_bus *bus)
struct snd_i2c_bus *slave;
struct snd_i2c_device *device;
- snd_assert(bus != NULL, return -EINVAL);
+ if (snd_BUG_ON(!bus))
+ return -EINVAL;
while (!list_empty(&bus->devices)) {
device = snd_i2c_device(bus->devices.next);
snd_i2c_device_free(device);
@@ -113,7 +114,8 @@ int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name,
struct snd_i2c_device *device;
*rdevice = NULL;
- snd_assert(bus != NULL, return -EINVAL);
+ if (snd_BUG_ON(!bus))
+ return -EINVAL;
device = kzalloc(sizeof(*device), GFP_KERNEL);
if (device == NULL)
return -ENOMEM;
diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c
index 1f4942ea1414..9840eb43648d 100644
--- a/sound/i2c/l3/uda1341.c
+++ b/sound/i2c/l3/uda1341.c
@@ -771,7 +771,8 @@ int __init snd_chip_uda1341_mixer_new(struct snd_card *card, struct l3_client **
struct l3_client *clnt;
int idx, err;
- snd_assert(card != NULL, return -EINVAL);
+ if (snd_BUG_ON(!card))
+ return -EINVAL;
clnt = kzalloc(sizeof(*clnt), GFP_KERNEL);
if (clnt == NULL)
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index d20d893b3b60..0341451f814c 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -475,7 +475,8 @@ int snd_ak4114_build(struct ak4114 *ak4114,
unsigned int idx;
int err;
- snd_assert(cap_substream, return -EINVAL);
+ if (snd_BUG_ON(!cap_substream))
+ return -EINVAL;
ak4114->playback_substream = ply_substream;
ak4114->capture_substream = cap_substream;
for (idx = 0; idx < AK4114_CONTROLS; idx++) {
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c
index f350835ade96..2cad2d612518 100644
--- a/sound/i2c/other/ak4117.c
+++ b/sound/i2c/other/ak4117.c
@@ -431,7 +431,8 @@ int snd_ak4117_build(struct ak4117 *ak4117, struct snd_pcm_substream *cap_substr
unsigned int idx;
int err;
- snd_assert(cap_substream, return -EINVAL);
+ if (snd_BUG_ON(!cap_substream))
+ return -EINVAL;
ak4117->substream = cap_substream;
for (idx = 0; idx < AK4117_CONTROLS; idx++) {
kctl = snd_ctl_new1(&snd_ak4117_iec958_controls[idx], ak4117);
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 288926d2e205..ee47abab764e 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -233,8 +233,8 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
0x01, 0x02, /* 1: reset and soft-mute */
0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect,
* disable DZF, sharp roll-off, RSTN#=0 */
- 0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */
- // 0x02, 0x2e, /* quad speed */
+ 0x02, 0x4e, /* 2: DA's power up, normal speed, RSTN#=0 */
+ /* 0x02, 0x6e,*/ /* quad speed */
0x03, 0x01, /* 3: de-emphasis off */
0x04, 0x00, /* 4: LOUT1 volume muted */
0x05, 0x00, /* 5: ROUT1 volume muted */
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 5769a13c1d95..660beb41f767 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -1,10 +1,6 @@
# ALSA ISA drivers
-config SND_AD1848_LIB
- tristate
- select SND_PCM
-
-config SND_CS4231_LIB
+config SND_WSS_LIB
tristate
select SND_PCM
@@ -55,7 +51,7 @@ config SND_AD1816A
config SND_AD1848
tristate "Generic AD1848/CS4248 driver"
- select SND_AD1848_LIB
+ select SND_WSS_LIB
help
Say Y here to include support for AD1848 (Analog Devices) or
CS4248 (Cirrus Logic - Crystal Semiconductors) chips.
@@ -86,7 +82,7 @@ config SND_AZT2320
select ISAPNP
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_CS4231_LIB
+ select SND_WSS_LIB
help
Say Y here to include support for soundcards based on the
Aztech Systems AZT2320 chip.
@@ -96,7 +92,7 @@ config SND_AZT2320
config SND_CMI8330
tristate "C-Media CMI8330"
- select SND_AD1848_LIB
+ select SND_WSS_LIB
select SND_SB16_DSP
help
Say Y here to include support for soundcards based on the
@@ -108,7 +104,7 @@ config SND_CMI8330
config SND_CS4231
tristate "Generic Cirrus Logic CS4231 driver"
select SND_MPU401_UART
- select SND_CS4231_LIB
+ select SND_WSS_LIB
help
Say Y here to include support for CS4231 chips from Cirrus
Logic - Crystal Semiconductors.
@@ -120,7 +116,7 @@ config SND_CS4232
tristate "Generic Cirrus Logic CS4232 driver"
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_CS4231_LIB
+ select SND_WSS_LIB
help
Say Y here to include support for CS4232 chips from Cirrus
Logic - Crystal Semiconductors.
@@ -132,7 +128,7 @@ config SND_CS4236
tristate "Generic Cirrus Logic CS4236+ driver"
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_CS4231_LIB
+ select SND_WSS_LIB
help
Say Y to include support for CS4235,CS4236,CS4237B,CS4238B,
CS4239 chips from Cirrus Logic - Crystal Semiconductors.
@@ -192,7 +188,7 @@ config SND_ES18XX
config SND_SC6000
tristate "Gallant SC-6000, Audio Excel DSP 16"
depends on HAS_IOPORT
- select SND_AD1848_LIB
+ select SND_WSS_LIB
select SND_OPL3_LIB
select SND_MPU401_UART
help
@@ -228,7 +224,7 @@ config SND_GUSEXTREME
config SND_GUSMAX
tristate "Gravis UltraSound MAX"
select SND_RAWMIDI
- select SND_CS4231_LIB
+ select SND_WSS_LIB
help
Say Y here to include support for Gravis UltraSound MAX
soundcards.
@@ -240,7 +236,7 @@ config SND_INTERWAVE
tristate "AMD InterWave, Gravis UltraSound PnP"
depends on PNP
select SND_RAWMIDI
- select SND_CS4231_LIB
+ select SND_WSS_LIB
help
Say Y here to include support for AMD InterWave based
soundcards (Gravis UltraSound Plug & Play, STB SoundRage32,
@@ -253,7 +249,7 @@ config SND_INTERWAVE_STB
tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)"
depends on PNP
select SND_RAWMIDI
- select SND_CS4231_LIB
+ select SND_WSS_LIB
help
Say Y here to include support for AMD InterWave based
soundcards with a TEA6330T bass and treble regulator
@@ -266,7 +262,7 @@ config SND_OPL3SA2
tristate "Yamaha OPL3-SA2/SA3"
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_CS4231_LIB
+ select SND_WSS_LIB
help
Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3
chips.
@@ -279,7 +275,7 @@ config SND_OPTI92X_AD1848
select SND_OPL3_LIB
select SND_OPL4_LIB
select SND_MPU401_UART
- select SND_AD1848_LIB
+ select SND_WSS_LIB
help
Say Y here to include support for soundcards based on Opti
82C92x or OTI-601 chips and using an AD1848 codec.
@@ -292,7 +288,7 @@ config SND_OPTI92X_CS4231
select SND_OPL3_LIB
select SND_OPL4_LIB
select SND_MPU401_UART
- select SND_CS4231_LIB
+ select SND_WSS_LIB
help
Say Y here to include support for soundcards based on Opti
82C92x chips and using a CS4231 codec.
@@ -304,7 +300,7 @@ config SND_OPTI93X
tristate "OPTi 82C93x"
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_CS4231_LIB
+ select SND_WSS_LIB
help
Say Y here to include support for soundcards based on Opti
82C93x chips.
@@ -315,7 +311,7 @@ config SND_OPTI93X
config SND_MIRO
tristate "Miro miroSOUND PCM1pro/PCM12/PCM20radio driver"
select SND_OPL4_LIB
- select SND_CS4231_LIB
+ select SND_WSS_LIB
select SND_MPU401_UART
select SND_PCM
help
@@ -364,7 +360,7 @@ config SND_SBAWE
config SND_SB16_CSP
bool "Sound Blaster 16/AWE CSP support"
depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC)
- select FW_LOADER if !SND_SB16_CSP_FIRMWARE_IN_KERNEL
+ select FW_LOADER
help
Say Y here to include support for the CSP core. This special
coprocessor can do variable tasks like various compression and
@@ -372,7 +368,7 @@ config SND_SB16_CSP
config SND_SGALAXY
tristate "Aztech Sound Galaxy"
- select SND_AD1848_LIB
+ select SND_WSS_LIB
help
Say Y here to include support for Aztech Sound Galaxy
soundcards.
@@ -384,7 +380,7 @@ config SND_SSCAPE
tristate "Ensoniq SoundScape PnP driver"
select SND_HWDEP
select SND_MPU401_UART
- select SND_CS4231_LIB
+ select SND_WSS_LIB
help
Say Y here to include support for Ensoniq SoundScape PnP
soundcards.
@@ -397,7 +393,7 @@ config SND_WAVEFRONT
select FW_LOADER
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_CS4231_LIB
+ select SND_WSS_LIB
help
Say Y here to include support for Turtle Beach Maui, Tropez
and Tropez+ soundcards based on the Wavefront chip.
diff --git a/sound/isa/Makefile b/sound/isa/Makefile
index c0ce7db2a1b5..63af13d901a5 100644
--- a/sound/isa/Makefile
+++ b/sound/isa/Makefile
@@ -27,4 +27,4 @@ obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o
obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o
obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ opti9xx/ \
- sb/ wavefront/
+ sb/ wavefront/ wss/
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index 68f1260b5602..77524244a846 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -83,8 +83,10 @@ static struct pnp_card_device_id snd_ad1816a_pnpids[] = {
{ .id = "MDK1605", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
/* Shark Predator ISA - added by Ken Arromdee */
{ .id = "SMM7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
- /* Analog Devices AD1816A - Terratec AudioSystem EWS64S */
+ /* Analog Devices AD1816A - Terratec AudioSystem EWS64 S */
{ .id = "TER1112", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
+ /* Analog Devices AD1816A - Terratec AudioSystem EWS64 S */
+ { .id = "TER1112", .devs = { { .id = "TER1100" }, { .id = "TER1101" } } },
/* Analog Devices AD1816A - Terratec Base 64 */
{ .id = "TER1411", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
/* end */
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index 4b8dfe2e3dcb..3bfca7c59baf 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -394,7 +394,8 @@ static int snd_ad1816a_timer_open(struct snd_timer *timer)
static unsigned long snd_ad1816a_timer_resolution(struct snd_timer *timer)
{
- snd_assert(timer != NULL, return 0);
+ if (snd_BUG_ON(!timer))
+ return 0;
return 10000;
}
@@ -961,7 +962,8 @@ int __devinit snd_ad1816a_mixer(struct snd_ad1816a *chip)
unsigned int idx;
int err;
- snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
+ if (snd_BUG_ON(!chip || !chip->card))
+ return -EINVAL;
card = chip->card;
diff --git a/sound/isa/ad1848/Makefile b/sound/isa/ad1848/Makefile
index ae23331e9200..3d6dea3ff927 100644
--- a/sound/isa/ad1848/Makefile
+++ b/sound/isa/ad1848/Makefile
@@ -3,10 +3,8 @@
# Copyright (c) 2001 by Jaroslav Kysela
#
-snd-ad1848-lib-objs := ad1848_lib.o
snd-ad1848-objs := ad1848.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_AD1848) += snd-ad1848.o
-obj-$(CONFIG_SND_AD1848_LIB) += snd-ad1848-lib.o
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 5f5271efdc59..b68d20edc20f 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -28,7 +28,7 @@
#include
#include
#include
-#include
+#include
#include
#define CRD_NAME "Generic AD1848/AD1847/CS4248"
@@ -87,7 +87,7 @@ static int __devinit snd_ad1848_match(struct device *dev, unsigned int n)
static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n)
{
struct snd_card *card;
- struct snd_ad1848 *chip;
+ struct snd_wss *chip;
struct snd_pcm *pcm;
int error;
@@ -95,18 +95,19 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n)
if (!card)
return -EINVAL;
- error = snd_ad1848_create(card, port[n], irq[n], dma1[n],
- thinkpad[n] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT, &chip);
+ error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], -1,
+ thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT,
+ 0, &chip);
if (error < 0)
goto out;
card->private_data = chip;
- error = snd_ad1848_pcm(chip, 0, &pcm);
+ error = snd_wss_pcm(chip, 0, &pcm);
if (error < 0)
goto out;
- error = snd_ad1848_mixer(chip);
+ error = snd_wss_mixer(chip);
if (error < 0)
goto out;
@@ -142,7 +143,7 @@ static int __devexit snd_ad1848_remove(struct device *dev, unsigned int n)
static int snd_ad1848_suspend(struct device *dev, unsigned int n, pm_message_t state)
{
struct snd_card *card = dev_get_drvdata(dev);
- struct snd_ad1848 *chip = card->private_data;
+ struct snd_wss *chip = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
chip->suspend(chip);
@@ -152,7 +153,7 @@ static int snd_ad1848_suspend(struct device *dev, unsigned int n, pm_message_t s
static int snd_ad1848_resume(struct device *dev, unsigned int n)
{
struct snd_card *card = dev_get_drvdata(dev);
- struct snd_ad1848 *chip = card->private_data;
+ struct snd_wss *chip = card->private_data;
chip->resume(chip);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
deleted file mode 100644
index 630c90f9ee50..000000000000
--- a/sound/isa/ad1848/ad1848_lib.c
+++ /dev/null
@@ -1,1267 +0,0 @@
-/*
- * Copyright (c) by Jaroslav Kysela
- * Routines for control of AD1848/AD1847/CS4248
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#define SNDRV_MAIN_OBJECT_FILE
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-MODULE_AUTHOR("Jaroslav Kysela ");
-MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248");
-MODULE_LICENSE("GPL");
-
-#if 0
-#define SNDRV_DEBUG_MCE
-#endif
-
-/*
- * Some variables
- */
-
-static unsigned char freq_bits[14] = {
- /* 5510 */ 0x00 | AD1848_XTAL2,
- /* 6620 */ 0x0E | AD1848_XTAL2,
- /* 8000 */ 0x00 | AD1848_XTAL1,
- /* 9600 */ 0x0E | AD1848_XTAL1,
- /* 11025 */ 0x02 | AD1848_XTAL2,
- /* 16000 */ 0x02 | AD1848_XTAL1,
- /* 18900 */ 0x04 | AD1848_XTAL2,
- /* 22050 */ 0x06 | AD1848_XTAL2,
- /* 27042 */ 0x04 | AD1848_XTAL1,
- /* 32000 */ 0x06 | AD1848_XTAL1,
- /* 33075 */ 0x0C | AD1848_XTAL2,
- /* 37800 */ 0x08 | AD1848_XTAL2,
- /* 44100 */ 0x0A | AD1848_XTAL2,
- /* 48000 */ 0x0C | AD1848_XTAL1
-};
-
-static unsigned int rates[14] = {
- 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,
- 27042, 32000, 33075, 37800, 44100, 48000
-};
-
-static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
- .count = ARRAY_SIZE(rates),
- .list = rates,
- .mask = 0,
-};
-
-static unsigned char snd_ad1848_original_image[16] =
-{
- 0x00, /* 00 - lic */
- 0x00, /* 01 - ric */
- 0x9f, /* 02 - la1ic */
- 0x9f, /* 03 - ra1ic */
- 0x9f, /* 04 - la2ic */
- 0x9f, /* 05 - ra2ic */
- 0xbf, /* 06 - loc */
- 0xbf, /* 07 - roc */
- 0x20, /* 08 - dfr */
- AD1848_AUTOCALIB, /* 09 - ic */
- 0x00, /* 0a - pc */
- 0x00, /* 0b - ti */
- 0x00, /* 0c - mi */
- 0x00, /* 0d - lbc */
- 0x00, /* 0e - dru */
- 0x00, /* 0f - drl */
-};
-
-/*
- * Basic I/O functions
- */
-
-static void snd_ad1848_wait(struct snd_ad1848 *chip)
-{
- int timeout;
-
- for (timeout = 250; timeout > 0; timeout--) {
- if ((inb(AD1848P(chip, REGSEL)) & AD1848_INIT) == 0)
- break;
- udelay(100);
- }
-}
-
-void snd_ad1848_out(struct snd_ad1848 *chip,
- unsigned char reg,
- unsigned char value)
-{
- snd_ad1848_wait(chip);
-#ifdef CONFIG_SND_DEBUG
- if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
- snd_printk(KERN_WARNING "auto calibration time out - "
- "reg = 0x%x, value = 0x%x\n", reg, value);
-#endif
- outb(chip->mce_bit | reg, AD1848P(chip, REGSEL));
- outb(chip->image[reg] = value, AD1848P(chip, REG));
- mb();
- snd_printdd("codec out - reg 0x%x = 0x%x\n",
- chip->mce_bit | reg, value);
-}
-
-EXPORT_SYMBOL(snd_ad1848_out);
-
-static void snd_ad1848_dout(struct snd_ad1848 *chip,
- unsigned char reg, unsigned char value)
-{
- snd_ad1848_wait(chip);
- outb(chip->mce_bit | reg, AD1848P(chip, REGSEL));
- outb(value, AD1848P(chip, REG));
- mb();
-}
-
-static unsigned char snd_ad1848_in(struct snd_ad1848 *chip, unsigned char reg)
-{
- snd_ad1848_wait(chip);
-#ifdef CONFIG_SND_DEBUG
- if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
- snd_printk(KERN_WARNING "auto calibration time out - "
- "reg = 0x%x\n", reg);
-#endif
- outb(chip->mce_bit | reg, AD1848P(chip, REGSEL));
- mb();
- return inb(AD1848P(chip, REG));
-}
-
-#if 0
-
-static void snd_ad1848_debug(struct snd_ad1848 *chip)
-{
- printk("AD1848 REGS: INDEX = 0x%02x ", inb(AD1848P(chip, REGSEL)));
- printk(" STATUS = 0x%02x\n", inb(AD1848P(chip, STATUS)));
- printk(" 0x00: left input = 0x%02x ", snd_ad1848_in(chip, 0x00));
- printk(" 0x08: playback format = 0x%02x\n", snd_ad1848_in(chip, 0x08));
- printk(" 0x01: right input = 0x%02x ", snd_ad1848_in(chip, 0x01));
- printk(" 0x09: iface (CFIG 1) = 0x%02x\n", snd_ad1848_in(chip, 0x09));
- printk(" 0x02: AUXA left = 0x%02x ", snd_ad1848_in(chip, 0x02));
- printk(" 0x0a: pin control = 0x%02x\n", snd_ad1848_in(chip, 0x0a));
- printk(" 0x03: AUXA right = 0x%02x ", snd_ad1848_in(chip, 0x03));
- printk(" 0x0b: init & status = 0x%02x\n", snd_ad1848_in(chip, 0x0b));
- printk(" 0x04: AUXB left = 0x%02x ", snd_ad1848_in(chip, 0x04));
- printk(" 0x0c: revision & mode = 0x%02x\n", snd_ad1848_in(chip, 0x0c));
- printk(" 0x05: AUXB right = 0x%02x ", snd_ad1848_in(chip, 0x05));
- printk(" 0x0d: loopback = 0x%02x\n", snd_ad1848_in(chip, 0x0d));
- printk(" 0x06: left output = 0x%02x ", snd_ad1848_in(chip, 0x06));
- printk(" 0x0e: data upr count = 0x%02x\n", snd_ad1848_in(chip, 0x0e));
- printk(" 0x07: right output = 0x%02x ", snd_ad1848_in(chip, 0x07));
- printk(" 0x0f: data lwr count = 0x%02x\n", snd_ad1848_in(chip, 0x0f));
-}
-
-#endif
-
-/*
- * AD1848 detection / MCE routines
- */
-
-static void snd_ad1848_mce_up(struct snd_ad1848 *chip)
-{
- unsigned long flags;
- int timeout;
-
- snd_ad1848_wait(chip);
-#ifdef CONFIG_SND_DEBUG
- if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
- snd_printk(KERN_WARNING "mce_up - auto calibration time out (0)\n");
-#endif
- spin_lock_irqsave(&chip->reg_lock, flags);
- chip->mce_bit |= AD1848_MCE;
- timeout = inb(AD1848P(chip, REGSEL));
- if (timeout == 0x80)
- snd_printk(KERN_WARNING "mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
- if (!(timeout & AD1848_MCE))
- outb(chip->mce_bit | (timeout & 0x1f), AD1848P(chip, REGSEL));
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-}
-
-static void snd_ad1848_mce_down(struct snd_ad1848 *chip)
-{
- unsigned long flags, timeout;
- int reg;
-
- spin_lock_irqsave(&chip->reg_lock, flags);
- for (timeout = 5; timeout > 0; timeout--)
- inb(AD1848P(chip, REGSEL));
- /* end of cleanup sequence */
- for (timeout = 12000; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--)
- udelay(100);
-
- snd_printdd("(1) timeout = %ld\n", timeout);
-
-#ifdef CONFIG_SND_DEBUG
- if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
- snd_printk(KERN_WARNING "mce_down [0x%lx] - auto calibration time out (0)\n", AD1848P(chip, REGSEL));
-#endif
-
- chip->mce_bit &= ~AD1848_MCE;
- reg = inb(AD1848P(chip, REGSEL));
- outb(chip->mce_bit | (reg & 0x1f), AD1848P(chip, REGSEL));
- if (reg == 0x80)
- snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
- if ((reg & AD1848_MCE) == 0) {
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return;
- }
-
- /*
- * Wait for auto-calibration (AC) process to finish, i.e. ACI to go low.
- * It may take up to 5 sample periods (at most 907 us @ 5.5125 kHz) for
- * the process to _start_, so it is important to wait at least that long
- * before checking. Otherwise we might think AC has finished when it
- * has in fact not begun. It could take 128 (no AC) or 384 (AC) cycles
- * for ACI to drop. This gives a wait of at most 70 ms with a more
- * typical value of 3-9 ms.
- */
- timeout = jiffies + msecs_to_jiffies(250);
- do {
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- msleep(1);
- spin_lock_irqsave(&chip->reg_lock, flags);
- reg = snd_ad1848_in(chip, AD1848_TEST_INIT) &
- AD1848_CALIB_IN_PROGRESS;
- } while (reg && time_before(jiffies, timeout));
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- if (reg)
- snd_printk(KERN_ERR
- "mce_down - auto calibration time out (2)\n");
-
- snd_printdd("(4) jiffies = %lu\n", jiffies);
- snd_printd("mce_down - exit = 0x%x\n", inb(AD1848P(chip, REGSEL)));
-}
-
-static unsigned int snd_ad1848_get_count(unsigned char format,
- unsigned int size)
-{
- switch (format & 0xe0) {
- case AD1848_LINEAR_16:
- size >>= 1;
- break;
- }
- if (format & AD1848_STEREO)
- size >>= 1;
- return size;
-}
-
-static int snd_ad1848_trigger(struct snd_ad1848 *chip, unsigned char what,
- int channel, int cmd)
-{
- int result = 0;
-
-#if 0
- printk("codec trigger!!! - what = %i, enable = %i, status = 0x%x\n", what, enable, inb(AD1848P(card, STATUS)));
-#endif
- spin_lock(&chip->reg_lock);
- if (cmd == SNDRV_PCM_TRIGGER_START) {
- if (chip->image[AD1848_IFACE_CTRL] & what) {
- spin_unlock(&chip->reg_lock);
- return 0;
- }
- snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL] |= what);
- chip->mode |= AD1848_MODE_RUNNING;
- } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
- if (!(chip->image[AD1848_IFACE_CTRL] & what)) {
- spin_unlock(&chip->reg_lock);
- return 0;
- }
- snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL] &= ~what);
- chip->mode &= ~AD1848_MODE_RUNNING;
- } else {
- result = -EINVAL;
- }
- spin_unlock(&chip->reg_lock);
- return result;
-}
-
-/*
- * CODEC I/O
- */
-
-static unsigned char snd_ad1848_get_rate(unsigned int rate)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(rates); i++)
- if (rate == rates[i])
- return freq_bits[i];
- snd_BUG();
- return freq_bits[ARRAY_SIZE(rates) - 1];
-}
-
-static int snd_ad1848_ioctl(struct snd_pcm_substream *substream,
- unsigned int cmd, void *arg)
-{
- return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-
-static unsigned char snd_ad1848_get_format(int format, int channels)
-{
- unsigned char rformat;
-
- rformat = AD1848_LINEAR_8;
- switch (format) {
- case SNDRV_PCM_FORMAT_A_LAW: rformat = AD1848_ALAW_8; break;
- case SNDRV_PCM_FORMAT_MU_LAW: rformat = AD1848_ULAW_8; break;
- case SNDRV_PCM_FORMAT_S16_LE: rformat = AD1848_LINEAR_16; break;
- }
- if (channels > 1)
- rformat |= AD1848_STEREO;
-#if 0
- snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
-#endif
- return rformat;
-}
-
-static void snd_ad1848_calibrate_mute(struct snd_ad1848 *chip, int mute)
-{
- unsigned long flags;
-
- mute = mute ? 1 : 0;
- spin_lock_irqsave(&chip->reg_lock, flags);
- if (chip->calibrate_mute == mute) {
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return;
- }
- if (!mute) {
- snd_ad1848_dout(chip, AD1848_LEFT_INPUT, chip->image[AD1848_LEFT_INPUT]);
- snd_ad1848_dout(chip, AD1848_RIGHT_INPUT, chip->image[AD1848_RIGHT_INPUT]);
- }
- snd_ad1848_dout(chip, AD1848_AUX1_LEFT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX1_LEFT_INPUT]);
- snd_ad1848_dout(chip, AD1848_AUX1_RIGHT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX1_RIGHT_INPUT]);
- snd_ad1848_dout(chip, AD1848_AUX2_LEFT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX2_LEFT_INPUT]);
- snd_ad1848_dout(chip, AD1848_AUX2_RIGHT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX2_RIGHT_INPUT]);
- snd_ad1848_dout(chip, AD1848_LEFT_OUTPUT, mute ? 0x80 : chip->image[AD1848_LEFT_OUTPUT]);
- snd_ad1848_dout(chip, AD1848_RIGHT_OUTPUT, mute ? 0x80 : chip->image[AD1848_RIGHT_OUTPUT]);
- chip->calibrate_mute = mute;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-}
-
-static void snd_ad1848_set_data_format(struct snd_ad1848 *chip, struct snd_pcm_hw_params *hw_params)
-{
- if (hw_params == NULL) {
- chip->image[AD1848_DATA_FORMAT] = 0x20;
- } else {
- chip->image[AD1848_DATA_FORMAT] =
- snd_ad1848_get_format(params_format(hw_params), params_channels(hw_params)) |
- snd_ad1848_get_rate(params_rate(hw_params));
- }
- // snd_printk(">>> pmode = 0x%x, dfr = 0x%x\n", pstr->mode, chip->image[AD1848_DATA_FORMAT]);
-}
-
-static int snd_ad1848_open(struct snd_ad1848 *chip, unsigned int mode)
-{
- unsigned long flags;
-
- if (chip->mode & AD1848_MODE_OPEN)
- return -EAGAIN;
-
- snd_ad1848_mce_down(chip);
-
-#ifdef SNDRV_DEBUG_MCE
- snd_printk("open: (1)\n");
-#endif
- snd_ad1848_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO |
- AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO |
- AD1848_CALIB_MODE);
- chip->image[AD1848_IFACE_CTRL] |= AD1848_AUTOCALIB;
- snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_ad1848_mce_down(chip);
-
-#ifdef SNDRV_DEBUG_MCE
- snd_printk("open: (2)\n");
-#endif
-
- snd_ad1848_set_data_format(chip, NULL);
-
- snd_ad1848_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_ad1848_mce_down(chip);
-
-#ifdef SNDRV_DEBUG_MCE
- snd_printk("open: (3)\n");
-#endif
-
- /* ok. now enable and ack CODEC IRQ */
- spin_lock_irqsave(&chip->reg_lock, flags);
- outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
- outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
- chip->image[AD1848_PIN_CTRL] |= AD1848_IRQ_ENABLE;
- snd_ad1848_out(chip, AD1848_PIN_CTRL, chip->image[AD1848_PIN_CTRL]);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-
- chip->mode = mode;
-
- return 0;
-}
-
-static void snd_ad1848_close(struct snd_ad1848 *chip)
-{
- unsigned long flags;
-
- if (!chip->mode)
- return;
- /* disable IRQ */
- spin_lock_irqsave(&chip->reg_lock, flags);
- outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
- outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
- chip->image[AD1848_PIN_CTRL] &= ~AD1848_IRQ_ENABLE;
- snd_ad1848_out(chip, AD1848_PIN_CTRL, chip->image[AD1848_PIN_CTRL]);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-
- /* now disable capture & playback */
-
- snd_ad1848_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO |
- AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO);
- snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_ad1848_mce_down(chip);
-
- /* clear IRQ again */
- spin_lock_irqsave(&chip->reg_lock, flags);
- outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
- outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-
- chip->mode = 0;
-}
-
-/*
- * ok.. exported functions..
- */
-
-static int snd_ad1848_playback_trigger(struct snd_pcm_substream *substream,
- int cmd)
-{
- struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
- return snd_ad1848_trigger(chip, AD1848_PLAYBACK_ENABLE, SNDRV_PCM_STREAM_PLAYBACK, cmd);
-}
-
-static int snd_ad1848_capture_trigger(struct snd_pcm_substream *substream,
- int cmd)
-{
- struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
- return snd_ad1848_trigger(chip, AD1848_CAPTURE_ENABLE, SNDRV_PCM_STREAM_CAPTURE, cmd);
-}
-
-static int snd_ad1848_playback_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
- unsigned long flags;
- int err;
-
- if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
- return err;
- snd_ad1848_calibrate_mute(chip, 1);
- snd_ad1848_set_data_format(chip, hw_params);
- snd_ad1848_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_ad1848_mce_down(chip);
- snd_ad1848_calibrate_mute(chip, 0);
- return 0;
-}
-
-static int snd_ad1848_playback_hw_free(struct snd_pcm_substream *substream)
-{
- return snd_pcm_lib_free_pages(substream);
-}
-
-static int snd_ad1848_playback_prepare(struct snd_pcm_substream *substream)
-{
- struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned long flags;
- unsigned int size = snd_pcm_lib_buffer_bytes(substream);
- unsigned int count = snd_pcm_lib_period_bytes(substream);
-
- chip->dma_size = size;
- chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO);
- snd_dma_program(chip->dma, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
- count = snd_ad1848_get_count(chip->image[AD1848_DATA_FORMAT], count) - 1;
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_ad1848_out(chip, AD1848_DATA_LWR_CNT, (unsigned char) count);
- snd_ad1848_out(chip, AD1848_DATA_UPR_CNT, (unsigned char) (count >> 8));
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return 0;
-}
-
-static int snd_ad1848_capture_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
- unsigned long flags;
- int err;
-
- if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
- return err;
- snd_ad1848_calibrate_mute(chip, 1);
- snd_ad1848_set_data_format(chip, hw_params);
- snd_ad1848_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_ad1848_mce_down(chip);
- snd_ad1848_calibrate_mute(chip, 0);
- return 0;
-}
-
-static int snd_ad1848_capture_hw_free(struct snd_pcm_substream *substream)
-{
- return snd_pcm_lib_free_pages(substream);
-}
-
-static int snd_ad1848_capture_prepare(struct snd_pcm_substream *substream)
-{
- struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned long flags;
- unsigned int size = snd_pcm_lib_buffer_bytes(substream);
- unsigned int count = snd_pcm_lib_period_bytes(substream);
-
- chip->dma_size = size;
- chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO);
- snd_dma_program(chip->dma, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
- count = snd_ad1848_get_count(chip->image[AD1848_DATA_FORMAT], count) - 1;
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_ad1848_out(chip, AD1848_DATA_LWR_CNT, (unsigned char) count);
- snd_ad1848_out(chip, AD1848_DATA_UPR_CNT, (unsigned char) (count >> 8));
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return 0;
-}
-
-static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id)
-{
- struct snd_ad1848 *chip = dev_id;
-
- if ((chip->mode & AD1848_MODE_PLAY) && chip->playback_substream &&
- (chip->mode & AD1848_MODE_RUNNING))
- snd_pcm_period_elapsed(chip->playback_substream);
- if ((chip->mode & AD1848_MODE_CAPTURE) && chip->capture_substream &&
- (chip->mode & AD1848_MODE_RUNNING))
- snd_pcm_period_elapsed(chip->capture_substream);
- outb(0, AD1848P(chip, STATUS)); /* clear global interrupt bit */
- return IRQ_HANDLED;
-}
-
-static snd_pcm_uframes_t snd_ad1848_playback_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
- size_t ptr;
-
- if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_PLAYBACK_ENABLE))
- return 0;
- ptr = snd_dma_pointer(chip->dma, chip->dma_size);
- return bytes_to_frames(substream->runtime, ptr);
-}
-
-static snd_pcm_uframes_t snd_ad1848_capture_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
- size_t ptr;
-
- if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_CAPTURE_ENABLE))
- return 0;
- ptr = snd_dma_pointer(chip->dma, chip->dma_size);
- return bytes_to_frames(substream->runtime, ptr);
-}
-
-/*
-
- */
-
-static void snd_ad1848_thinkpad_twiddle(struct snd_ad1848 *chip, int on) {
-
- int tmp;
-
- if (!chip->thinkpad_flag) return;
-
- outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
- tmp = inb(AD1848_THINKPAD_CTL_PORT2);
-
- if (on)
- /* turn it on */
- tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
- else
- /* turn it off */
- tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
-
- outb(tmp, AD1848_THINKPAD_CTL_PORT2);
-
-}
-
-#ifdef CONFIG_PM
-static void snd_ad1848_suspend(struct snd_ad1848 *chip)
-{
- snd_pcm_suspend_all(chip->pcm);
- if (chip->thinkpad_flag)
- snd_ad1848_thinkpad_twiddle(chip, 0);
-}
-
-static void snd_ad1848_resume(struct snd_ad1848 *chip)
-{
- int i;
-
- if (chip->thinkpad_flag)
- snd_ad1848_thinkpad_twiddle(chip, 1);
-
- /* clear any pendings IRQ */
- inb(AD1848P(chip, STATUS));
- outb(0, AD1848P(chip, STATUS));
- mb();
-
- snd_ad1848_mce_down(chip);
- for (i = 0; i < 16; i++)
- snd_ad1848_out(chip, i, chip->image[i]);
- snd_ad1848_mce_up(chip);
- snd_ad1848_mce_down(chip);
-}
-#endif /* CONFIG_PM */
-
-static int snd_ad1848_probe(struct snd_ad1848 * chip)
-{
- unsigned long flags;
- int i, id, rev, ad1847;
- unsigned char *ptr;
-
-#if 0
- snd_ad1848_debug(chip);
-#endif
- id = ad1847 = 0;
- for (i = 0; i < 1000; i++) {
- mb();
- if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
- udelay(500);
- else {
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00);
- snd_ad1848_out(chip, AD1848_LEFT_INPUT, 0xaa);
- snd_ad1848_out(chip, AD1848_RIGHT_INPUT, 0x45);
- rev = snd_ad1848_in(chip, AD1848_RIGHT_INPUT);
- if (rev == 0x65) {
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- id = 1;
- ad1847 = 1;
- break;
- }
- if (snd_ad1848_in(chip, AD1848_LEFT_INPUT) == 0xaa && rev == 0x45) {
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- id = 1;
- break;
- }
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- }
- }
- if (id != 1)
- return -ENODEV; /* no valid device found */
- if (chip->hardware == AD1848_HW_DETECT) {
- if (ad1847) {
- chip->hardware = AD1848_HW_AD1847;
- } else {
- chip->hardware = AD1848_HW_AD1848;
- rev = snd_ad1848_in(chip, AD1848_MISC_INFO);
- if (rev & 0x80) {
- chip->hardware = AD1848_HW_CS4248;
- } else if ((rev & 0x0f) == 0x0a) {
- snd_ad1848_out(chip, AD1848_MISC_INFO, 0x40);
- for (i = 0; i < 16; ++i) {
- if (snd_ad1848_in(chip, i) != snd_ad1848_in(chip, i + 16)) {
- chip->hardware = AD1848_HW_CMI8330;
- break;
- }
- }
- snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00);
- }
- }
- }
- spin_lock_irqsave(&chip->reg_lock, flags);
- inb(AD1848P(chip, STATUS)); /* clear any pendings IRQ */
- outb(0, AD1848P(chip, STATUS));
- mb();
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-
- chip->image[AD1848_MISC_INFO] = 0x00;
- chip->image[AD1848_IFACE_CTRL] =
- (chip->image[AD1848_IFACE_CTRL] & ~AD1848_SINGLE_DMA) | AD1848_SINGLE_DMA;
- ptr = (unsigned char *) &chip->image;
- snd_ad1848_mce_down(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- for (i = 0; i < 16; i++) /* ok.. fill all AD1848 registers */
- snd_ad1848_out(chip, i, *ptr++);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_ad1848_mce_up(chip);
- snd_ad1848_mce_down(chip);
- return 0; /* all things are ok.. */
-}
-
-/*
-
- */
-
-static struct snd_pcm_hardware snd_ad1848_playback =
-{
- .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID),
- .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
- SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE),
- .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
- .rate_min = 5510,
- .rate_max = 48000,
- .channels_min = 1,
- .channels_max = 2,
- .buffer_bytes_max = (128*1024),
- .period_bytes_min = 64,
- .period_bytes_max = (128*1024),
- .periods_min = 1,
- .periods_max = 1024,
- .fifo_size = 0,
-};
-
-static struct snd_pcm_hardware snd_ad1848_capture =
-{
- .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID),
- .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
- SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE),
- .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
- .rate_min = 5510,
- .rate_max = 48000,
- .channels_min = 1,
- .channels_max = 2,
- .buffer_bytes_max = (128*1024),
- .period_bytes_min = 64,
- .period_bytes_max = (128*1024),
- .periods_min = 1,
- .periods_max = 1024,
- .fifo_size = 0,
-};
-
-/*
-
- */
-
-static int snd_ad1848_playback_open(struct snd_pcm_substream *substream)
-{
- struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
-
- if ((err = snd_ad1848_open(chip, AD1848_MODE_PLAY)) < 0)
- return err;
- chip->playback_substream = substream;
- runtime->hw = snd_ad1848_playback;
- snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.buffer_bytes_max);
- snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.period_bytes_max);
- snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
- return 0;
-}
-
-static int snd_ad1848_capture_open(struct snd_pcm_substream *substream)
-{
- struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
-
- if ((err = snd_ad1848_open(chip, AD1848_MODE_CAPTURE)) < 0)
- return err;
- chip->capture_substream = substream;
- runtime->hw = snd_ad1848_capture;
- snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.buffer_bytes_max);
- snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.period_bytes_max);
- snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
- return 0;
-}
-
-static int snd_ad1848_playback_close(struct snd_pcm_substream *substream)
-{
- struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
-
- chip->mode &= ~AD1848_MODE_PLAY;
- chip->playback_substream = NULL;
- snd_ad1848_close(chip);
- return 0;
-}
-
-static int snd_ad1848_capture_close(struct snd_pcm_substream *substream)
-{
- struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
-
- chip->mode &= ~AD1848_MODE_CAPTURE;
- chip->capture_substream = NULL;
- snd_ad1848_close(chip);
- return 0;
-}
-
-static int snd_ad1848_free(struct snd_ad1848 *chip)
-{
- release_and_free_resource(chip->res_port);
- if (chip->irq >= 0)
- free_irq(chip->irq, (void *) chip);
- if (chip->dma >= 0) {
- snd_dma_disable(chip->dma);
- free_dma(chip->dma);
- }
- kfree(chip);
- return 0;
-}
-
-static int snd_ad1848_dev_free(struct snd_device *device)
-{
- struct snd_ad1848 *chip = device->device_data;
- return snd_ad1848_free(chip);
-}
-
-static const char *snd_ad1848_chip_id(struct snd_ad1848 *chip)
-{
- switch (chip->hardware) {
- case AD1848_HW_AD1847: return "AD1847";
- case AD1848_HW_AD1848: return "AD1848";
- case AD1848_HW_CS4248: return "CS4248";
- case AD1848_HW_CMI8330: return "CMI8330/C3D";
- default: return "???";
- }
-}
-
-int snd_ad1848_create(struct snd_card *card,
- unsigned long port,
- int irq, int dma,
- unsigned short hardware,
- struct snd_ad1848 ** rchip)
-{
- static struct snd_device_ops ops = {
- .dev_free = snd_ad1848_dev_free,
- };
- struct snd_ad1848 *chip;
- int err;
-
- *rchip = NULL;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL)
- return -ENOMEM;
- spin_lock_init(&chip->reg_lock);
- chip->card = card;
- chip->port = port;
- chip->irq = -1;
- chip->dma = -1;
- chip->hardware = hardware;
- memcpy(&chip->image, &snd_ad1848_original_image, sizeof(snd_ad1848_original_image));
-
- if ((chip->res_port = request_region(port, 4, "AD1848")) == NULL) {
- snd_printk(KERN_ERR "ad1848: can't grab port 0x%lx\n", port);
- snd_ad1848_free(chip);
- return -EBUSY;
- }
- if (request_irq(irq, snd_ad1848_interrupt, IRQF_DISABLED, "AD1848", (void *) chip)) {
- snd_printk(KERN_ERR "ad1848: can't grab IRQ %d\n", irq);
- snd_ad1848_free(chip);
- return -EBUSY;
- }
- chip->irq = irq;
- if (request_dma(dma, "AD1848")) {
- snd_printk(KERN_ERR "ad1848: can't grab DMA %d\n", dma);
- snd_ad1848_free(chip);
- return -EBUSY;
- }
- chip->dma = dma;
-
- if (hardware == AD1848_HW_THINKPAD) {
- chip->thinkpad_flag = 1;
- chip->hardware = AD1848_HW_DETECT; /* reset */
- snd_ad1848_thinkpad_twiddle(chip, 1);
- }
-
- if (snd_ad1848_probe(chip) < 0) {
- snd_ad1848_free(chip);
- return -ENODEV;
- }
-
- /* Register device */
- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
- snd_ad1848_free(chip);
- return err;
- }
-
-#ifdef CONFIG_PM
- chip->suspend = snd_ad1848_suspend;
- chip->resume = snd_ad1848_resume;
-#endif
-
- *rchip = chip;
- return 0;
-}
-
-EXPORT_SYMBOL(snd_ad1848_create);
-
-static struct snd_pcm_ops snd_ad1848_playback_ops = {
- .open = snd_ad1848_playback_open,
- .close = snd_ad1848_playback_close,
- .ioctl = snd_ad1848_ioctl,
- .hw_params = snd_ad1848_playback_hw_params,
- .hw_free = snd_ad1848_playback_hw_free,
- .prepare = snd_ad1848_playback_prepare,
- .trigger = snd_ad1848_playback_trigger,
- .pointer = snd_ad1848_playback_pointer,
-};
-
-static struct snd_pcm_ops snd_ad1848_capture_ops = {
- .open = snd_ad1848_capture_open,
- .close = snd_ad1848_capture_close,
- .ioctl = snd_ad1848_ioctl,
- .hw_params = snd_ad1848_capture_hw_params,
- .hw_free = snd_ad1848_capture_hw_free,
- .prepare = snd_ad1848_capture_prepare,
- .trigger = snd_ad1848_capture_trigger,
- .pointer = snd_ad1848_capture_pointer,
-};
-
-int snd_ad1848_pcm(struct snd_ad1848 *chip, int device, struct snd_pcm **rpcm)
-{
- struct snd_pcm *pcm;
- int err;
-
- if ((err = snd_pcm_new(chip->card, "AD1848", device, 1, 1, &pcm)) < 0)
- return err;
-
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ad1848_playback_ops);
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ad1848_capture_ops);
-
- pcm->private_data = chip;
- pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
- strcpy(pcm->name, snd_ad1848_chip_id(chip));
-
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_isa_data(),
- 64*1024, chip->dma > 3 ? 128*1024 : 64*1024);
-
- chip->pcm = pcm;
- if (rpcm)
- *rpcm = pcm;
- return 0;
-}
-
-EXPORT_SYMBOL(snd_ad1848_pcm);
-
-const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction)
-{
- return direction == SNDRV_PCM_STREAM_PLAYBACK ?
- &snd_ad1848_playback_ops : &snd_ad1848_capture_ops;
-}
-
-EXPORT_SYMBOL(snd_ad1848_get_pcm_ops);
-
-/*
- * MIXER part
- */
-
-static int snd_ad1848_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- static char *texts[4] = {
- "Line", "Aux", "Mic", "Mix"
- };
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 2;
- 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_ad1848_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
-
- spin_lock_irqsave(&chip->reg_lock, flags);
- ucontrol->value.enumerated.item[0] = (chip->image[AD1848_LEFT_INPUT] & AD1848_MIXS_ALL) >> 6;
- ucontrol->value.enumerated.item[1] = (chip->image[AD1848_RIGHT_INPUT] & AD1848_MIXS_ALL) >> 6;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return 0;
-}
-
-static int snd_ad1848_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
- unsigned short left, right;
- int change;
-
- if (ucontrol->value.enumerated.item[0] > 3 ||
- ucontrol->value.enumerated.item[1] > 3)
- return -EINVAL;
- left = ucontrol->value.enumerated.item[0] << 6;
- right = ucontrol->value.enumerated.item[1] << 6;
- spin_lock_irqsave(&chip->reg_lock, flags);
- left = (chip->image[AD1848_LEFT_INPUT] & ~AD1848_MIXS_ALL) | left;
- right = (chip->image[AD1848_RIGHT_INPUT] & ~AD1848_MIXS_ALL) | right;
- change = left != chip->image[AD1848_LEFT_INPUT] ||
- right != chip->image[AD1848_RIGHT_INPUT];
- snd_ad1848_out(chip, AD1848_LEFT_INPUT, left);
- snd_ad1848_out(chip, AD1848_RIGHT_INPUT, right);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return change;
-}
-
-static int snd_ad1848_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- int mask = (kcontrol->private_value >> 16) & 0xff;
-
- 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 = mask;
- return 0;
-}
-
-static int snd_ad1848_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
- int reg = kcontrol->private_value & 0xff;
- int shift = (kcontrol->private_value >> 8) & 0xff;
- int mask = (kcontrol->private_value >> 16) & 0xff;
- int invert = (kcontrol->private_value >> 24) & 0xff;
-
- spin_lock_irqsave(&chip->reg_lock, flags);
- ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- if (invert)
- ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
- return 0;
-}
-
-static int snd_ad1848_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
- int reg = kcontrol->private_value & 0xff;
- int shift = (kcontrol->private_value >> 8) & 0xff;
- int mask = (kcontrol->private_value >> 16) & 0xff;
- int invert = (kcontrol->private_value >> 24) & 0xff;
- int change;
- unsigned short val;
-
- val = (ucontrol->value.integer.value[0] & mask);
- if (invert)
- val = mask - val;
- val <<= shift;
- spin_lock_irqsave(&chip->reg_lock, flags);
- val = (chip->image[reg] & ~(mask << shift)) | val;
- change = val != chip->image[reg];
- snd_ad1848_out(chip, reg, val);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return change;
-}
-
-static int snd_ad1848_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- int mask = (kcontrol->private_value >> 24) & 0xff;
-
- 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 = mask;
- return 0;
-}
-
-static int snd_ad1848_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
- int left_reg = kcontrol->private_value & 0xff;
- int right_reg = (kcontrol->private_value >> 8) & 0xff;
- int shift_left = (kcontrol->private_value >> 16) & 0x07;
- int shift_right = (kcontrol->private_value >> 19) & 0x07;
- int mask = (kcontrol->private_value >> 24) & 0xff;
- int invert = (kcontrol->private_value >> 22) & 1;
-
- spin_lock_irqsave(&chip->reg_lock, flags);
- ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
- ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- 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;
-}
-
-static int snd_ad1848_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
- int left_reg = kcontrol->private_value & 0xff;
- int right_reg = (kcontrol->private_value >> 8) & 0xff;
- int shift_left = (kcontrol->private_value >> 16) & 0x07;
- int shift_right = (kcontrol->private_value >> 19) & 0x07;
- int mask = (kcontrol->private_value >> 24) & 0xff;
- int invert = (kcontrol->private_value >> 22) & 1;
- int change;
- unsigned short val1, val2;
-
- 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_irqsave(&chip->reg_lock, flags);
- if (left_reg != right_reg) {
- val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
- val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
- change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg];
- snd_ad1848_out(chip, left_reg, val1);
- snd_ad1848_out(chip, right_reg, val2);
- } else {
- val1 = (chip->image[left_reg] & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
- change = val1 != chip->image[left_reg];
- snd_ad1848_out(chip, left_reg, val1);
- }
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return change;
-}
-
-/*
- */
-int snd_ad1848_add_ctl_elem(struct snd_ad1848 *chip,
- const struct ad1848_mix_elem *c)
-{
- static struct snd_kcontrol_new newctls[] = {
- [AD1848_MIX_SINGLE] = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .info = snd_ad1848_info_single,
- .get = snd_ad1848_get_single,
- .put = snd_ad1848_put_single,
- },
- [AD1848_MIX_DOUBLE] = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .info = snd_ad1848_info_double,
- .get = snd_ad1848_get_double,
- .put = snd_ad1848_put_double,
- },
- [AD1848_MIX_CAPTURE] = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .info = snd_ad1848_info_mux,
- .get = snd_ad1848_get_mux,
- .put = snd_ad1848_put_mux,
- },
- };
- struct snd_kcontrol *ctl;
- int err;
-
- ctl = snd_ctl_new1(&newctls[c->type], chip);
- if (! ctl)
- return -ENOMEM;
- strlcpy(ctl->id.name, c->name, sizeof(ctl->id.name));
- ctl->id.index = c->index;
- ctl->private_value = c->private_value;
- if (c->tlv) {
- ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
- ctl->tlv.p = c->tlv;
- }
- if ((err = snd_ctl_add(chip->card, ctl)) < 0)
- return err;
- return 0;
-}
-
-EXPORT_SYMBOL(snd_ad1848_add_ctl_elem);
-
-static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
-static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
-static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
-
-static struct ad1848_mix_elem snd_ad1848_controls[] = {
-AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1),
-AD1848_DOUBLE_TLV("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1,
- db_scale_6bit),
-AD1848_DOUBLE("Aux Playback Switch", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
-AD1848_DOUBLE_TLV("Aux Playback Volume", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
- db_scale_5bit_12db_max),
-AD1848_DOUBLE("Aux Playback Switch", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
-AD1848_DOUBLE_TLV("Aux Playback Volume", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
- db_scale_5bit_12db_max),
-AD1848_DOUBLE_TLV("Capture Volume", 0, AD1848_LEFT_INPUT, AD1848_RIGHT_INPUT, 0, 0, 15, 0,
- db_scale_rec_gain),
-{
- .name = "Capture Source",
- .type = AD1848_MIX_CAPTURE,
-},
-AD1848_SINGLE("Loopback Capture Switch", 0, AD1848_LOOPBACK, 0, 1, 0),
-AD1848_SINGLE_TLV("Loopback Capture Volume", 0, AD1848_LOOPBACK, 1, 63, 0,
- db_scale_6bit),
-};
-
-int snd_ad1848_mixer(struct snd_ad1848 *chip)
-{
- struct snd_card *card;
- struct snd_pcm *pcm;
- unsigned int idx;
- int err;
-
- snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL);
-
- pcm = chip->pcm;
- card = chip->card;
-
- strcpy(card->mixername, pcm->name);
-
- for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++)
- if ((err = snd_ad1848_add_ctl_elem(chip, &snd_ad1848_controls[idx])) < 0)
- return err;
-
- return 0;
-}
-
-EXPORT_SYMBOL(snd_ad1848_mixer);
-
-/*
- * INIT part
- */
-
-static int __init alsa_ad1848_init(void)
-{
- return 0;
-}
-
-static void __exit alsa_ad1848_exit(void)
-{
-}
-
-module_init(alsa_ad1848_init)
-module_exit(alsa_ad1848_exit)
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
index 154e728f592d..3e74d1a3928e 100644
--- a/sound/isa/azt2320.c
+++ b/sound/isa/azt2320.c
@@ -38,7 +38,7 @@
#include
#include
#include
-#include
+#include
#include
#include
@@ -76,7 +76,7 @@ struct snd_card_azt2320 {
int dev_no;
struct pnp_dev *dev;
struct pnp_dev *devmpu;
- struct snd_cs4231 *chip;
+ struct snd_wss *chip;
};
static struct pnp_card_device_id snd_azt2320_pnpids[] = {
@@ -181,7 +181,7 @@ static int __devinit snd_card_azt2320_probe(int dev,
int error;
struct snd_card *card;
struct snd_card_azt2320 *acard;
- struct snd_cs4231 *chip;
+ struct snd_wss *chip;
struct snd_opl3 *opl3;
if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
@@ -200,11 +200,11 @@ static int __devinit snd_card_azt2320_probe(int dev,
return error;
}
- if ((error = snd_cs4231_create(card, wss_port[dev], -1,
- irq[dev],
- dma1[dev],
- dma2[dev],
- CS4231_HW_DETECT, 0, &chip)) < 0) {
+ error = snd_wss_create(card, wss_port[dev], -1,
+ irq[dev],
+ dma1[dev], dma2[dev],
+ WSS_HW_DETECT, 0, &chip);
+ if (error < 0) {
snd_card_free(card);
return error;
}
@@ -214,15 +214,18 @@ static int __devinit snd_card_azt2320_probe(int dev,
sprintf(card->longname, "%s, WSS at 0x%lx, irq %i, dma %i&%i",
card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
- if ((error = snd_cs4231_pcm(chip, 0, NULL)) < 0) {
+ error = snd_wss_pcm(chip, 0, NULL);
+ if (error < 0) {
snd_card_free(card);
return error;
}
- if ((error = snd_cs4231_mixer(chip)) < 0) {
+ error = snd_wss_mixer(chip);
+ if (error < 0) {
snd_card_free(card);
return error;
}
- if ((error = snd_cs4231_timer(chip, 0, NULL)) < 0) {
+ error = snd_wss_timer(chip, 0, NULL);
+ if (error < 0) {
snd_card_free(card);
return error;
}
@@ -293,7 +296,7 @@ static int snd_azt2320_pnp_suspend(struct pnp_card_link *pcard, pm_message_t sta
{
struct snd_card *card = pnp_get_card_drvdata(pcard);
struct snd_card_azt2320 *acard = card->private_data;
- struct snd_cs4231 *chip = acard->chip;
+ struct snd_wss *chip = acard->chip;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
chip->suspend(chip);
@@ -304,7 +307,7 @@ static int snd_azt2320_pnp_resume(struct pnp_card_link *pcard)
{
struct snd_card *card = pnp_get_card_drvdata(pcard);
struct snd_card_azt2320 *acard = card->private_data;
- struct snd_cs4231 *chip = acard->chip;
+ struct snd_wss *chip = acard->chip;
chip->resume(chip);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 4d198ec71e9b..e49aec700a55 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -50,7 +50,7 @@
#include
#include
#include
-#include
+#include
#include
#include
@@ -151,7 +151,7 @@ struct snd_cmi8330 {
struct pnp_dev *play;
#endif
struct snd_card *card;
- struct snd_ad1848 *wss;
+ struct snd_wss *wss;
struct snd_sb *sb;
struct snd_pcm *pcm;
@@ -174,32 +174,57 @@ MODULE_DEVICE_TABLE(pnp_card, snd_cmi8330_pnpids);
#endif
-static struct ad1848_mix_elem snd_cmi8330_controls[] __devinitdata = {
-AD1848_DOUBLE("Master Playback Volume", 0, CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0),
-AD1848_SINGLE("Loud Playback Switch", 0, CMI8330_MUTEMUX, 6, 1, 1),
-AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1),
-AD1848_DOUBLE("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1),
-AD1848_DOUBLE("Line Playback Switch", 0, CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0),
-AD1848_DOUBLE("Line Playback Volume", 0, CMI8330_LINVOL, CMI8330_LINVOL, 4, 0, 15, 0),
-AD1848_DOUBLE("Line Capture Switch", 0, CMI8330_RMUX3D, CMI8330_RMUX3D, 2, 1, 1, 0),
-AD1848_DOUBLE("Line Capture Volume", 0, CMI8330_LINGAIN, CMI8330_LINGAIN, 4, 0, 15, 0),
-AD1848_DOUBLE("CD Playback Switch", 0, CMI8330_MUTEMUX, CMI8330_MUTEMUX, 2, 1, 1, 0),
-AD1848_DOUBLE("CD Capture Switch", 0, CMI8330_RMUX3D, CMI8330_RMUX3D, 4, 3, 1, 0),
-AD1848_DOUBLE("CD Playback Volume", 0, CMI8330_CDINVOL, CMI8330_CDINVOL, 4, 0, 15, 0),
-AD1848_DOUBLE("CD Capture Volume", 0, CMI8330_CDINGAIN, CMI8330_CDINGAIN, 4, 0, 15, 0),
-AD1848_SINGLE("Mic Playback Switch", 0, CMI8330_MUTEMUX, 0, 1, 0),
-AD1848_SINGLE("Mic Playback Volume", 0, CMI8330_OUTPUTVOL, 0, 7, 0),
-AD1848_SINGLE("Mic Capture Switch", 0, CMI8330_RMUX3D, 0, 1, 0),
-AD1848_SINGLE("Mic Capture Volume", 0, CMI8330_OUTPUTVOL, 5, 7, 0),
-AD1848_DOUBLE("Wavetable Playback Switch", 0, CMI8330_RECMUX, CMI8330_RECMUX, 1, 0, 1, 0),
-AD1848_DOUBLE("Wavetable Playback Volume", 0, CMI8330_WAVVOL, CMI8330_WAVVOL, 4, 0, 15, 0),
-AD1848_DOUBLE("Wavetable Capture Switch", 0, CMI8330_RECMUX, CMI8330_RECMUX, 5, 4, 1, 0),
-AD1848_DOUBLE("Wavetable Capture Volume", 0, CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0),
-AD1848_SINGLE("3D Control - Switch", 0, CMI8330_RMUX3D, 5, 1, 1),
-AD1848_SINGLE("PC Speaker Playback Volume", 0, CMI8330_OUTPUTVOL, 3, 3, 0),
-AD1848_SINGLE("FM Playback Switch", 0, CMI8330_RECMUX, 3, 1, 1),
-AD1848_SINGLE(SNDRV_CTL_NAME_IEC958("Input ",CAPTURE,SWITCH), 0, CMI8330_RMUX3D, 7, 1, 1),
-AD1848_SINGLE(SNDRV_CTL_NAME_IEC958("Input ",PLAYBACK,SWITCH), 0, CMI8330_MUTEMUX, 7, 1, 1),
+static struct snd_kcontrol_new snd_cmi8330_controls[] __devinitdata = {
+WSS_DOUBLE("Master Playback Volume", 0,
+ CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0),
+WSS_SINGLE("Loud Playback Switch", 0,
+ CMI8330_MUTEMUX, 6, 1, 1),
+WSS_DOUBLE("PCM Playback Switch", 0,
+ CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
+WSS_DOUBLE("PCM Playback Volume", 0,
+ CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
+WSS_DOUBLE("Line Playback Switch", 0,
+ CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0),
+WSS_DOUBLE("Line Playback Volume", 0,
+ CMI8330_LINVOL, CMI8330_LINVOL, 4, 0, 15, 0),
+WSS_DOUBLE("Line Capture Switch", 0,
+ CMI8330_RMUX3D, CMI8330_RMUX3D, 2, 1, 1, 0),
+WSS_DOUBLE("Line Capture Volume", 0,
+ CMI8330_LINGAIN, CMI8330_LINGAIN, 4, 0, 15, 0),
+WSS_DOUBLE("CD Playback Switch", 0,
+ CMI8330_MUTEMUX, CMI8330_MUTEMUX, 2, 1, 1, 0),
+WSS_DOUBLE("CD Capture Switch", 0,
+ CMI8330_RMUX3D, CMI8330_RMUX3D, 4, 3, 1, 0),
+WSS_DOUBLE("CD Playback Volume", 0,
+ CMI8330_CDINVOL, CMI8330_CDINVOL, 4, 0, 15, 0),
+WSS_DOUBLE("CD Capture Volume", 0,
+ CMI8330_CDINGAIN, CMI8330_CDINGAIN, 4, 0, 15, 0),
+WSS_SINGLE("Mic Playback Switch", 0,
+ CMI8330_MUTEMUX, 0, 1, 0),
+WSS_SINGLE("Mic Playback Volume", 0,
+ CMI8330_OUTPUTVOL, 0, 7, 0),
+WSS_SINGLE("Mic Capture Switch", 0,
+ CMI8330_RMUX3D, 0, 1, 0),
+WSS_SINGLE("Mic Capture Volume", 0,
+ CMI8330_OUTPUTVOL, 5, 7, 0),
+WSS_DOUBLE("Wavetable Playback Switch", 0,
+ CMI8330_RECMUX, CMI8330_RECMUX, 1, 0, 1, 0),
+WSS_DOUBLE("Wavetable Playback Volume", 0,
+ CMI8330_WAVVOL, CMI8330_WAVVOL, 4, 0, 15, 0),
+WSS_DOUBLE("Wavetable Capture Switch", 0,
+ CMI8330_RECMUX, CMI8330_RECMUX, 5, 4, 1, 0),
+WSS_DOUBLE("Wavetable Capture Volume", 0,
+ CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0),
+WSS_SINGLE("3D Control - Switch", 0,
+ CMI8330_RMUX3D, 5, 1, 1),
+WSS_SINGLE("PC Speaker Playback Volume", 0,
+ CMI8330_OUTPUTVOL, 3, 3, 0),
+WSS_SINGLE("FM Playback Switch", 0,
+ CMI8330_RECMUX, 3, 1, 1),
+WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", CAPTURE, SWITCH), 0,
+ CMI8330_RMUX3D, 7, 1, 1),
+WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", PLAYBACK, SWITCH), 0,
+ CMI8330_MUTEMUX, 7, 1, 1),
};
#ifdef ENABLE_SB_MIXER
@@ -268,7 +293,10 @@ static int __devinit snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330
strcpy(card->mixername, "CMI8330/C3D");
for (idx = 0; idx < ARRAY_SIZE(snd_cmi8330_controls); idx++) {
- if ((err = snd_ad1848_add_ctl_elem(acard->wss, &snd_cmi8330_controls[idx])) < 0)
+ err = snd_ctl_add(card,
+ snd_ctl_new1(&snd_cmi8330_controls[idx],
+ acard->wss));
+ if (err < 0)
return err;
}
@@ -385,7 +413,7 @@ static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *
chip->streams[CMI_SB_STREAM].private_data = chip->sb;
/* AD1848 */
- ops = snd_ad1848_get_pcm_ops(CMI_AD_STREAM);
+ ops = snd_wss_get_pcm_ops(CMI_AD_STREAM);
chip->streams[CMI_AD_STREAM].ops = *ops;
chip->streams[CMI_AD_STREAM].open = ops->open;
chip->streams[CMI_AD_STREAM].ops.open = cmi_open_callbacks[CMI_AD_STREAM];
@@ -461,16 +489,15 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
int i, err;
acard = card->private_data;
- if ((err = snd_ad1848_create(card,
- wssport[dev] + 4,
- wssirq[dev],
- wssdma[dev],
- AD1848_HW_DETECT,
- &acard->wss)) < 0) {
+ err = snd_wss_create(card, wssport[dev] + 4, -1,
+ wssirq[dev],
+ wssdma[dev], -1,
+ WSS_HW_DETECT, 0, &acard->wss);
+ if (err < 0) {
snd_printk(KERN_ERR PFX "(AD1848) device busy??\n");
return err;
}
- if (acard->wss->hardware != AD1848_HW_CMI8330) {
+ if (acard->wss->hardware != WSS_HW_CMI8330) {
snd_printk(KERN_ERR PFX "(AD1848) not found during probe\n");
return -ENODEV;
}
@@ -489,9 +516,10 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
return err;
}
- snd_ad1848_out(acard->wss, AD1848_MISC_INFO, 0x40); /* switch on MODE2 */
+ snd_wss_out(acard->wss, CS4231_MISC_INFO, 0x40); /* switch on MODE2 */
for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++)
- snd_ad1848_out(acard->wss, i, snd_cmi8330_image[i - CMI8330_RMUX3D]);
+ snd_wss_out(acard->wss, i,
+ snd_cmi8330_image[i - CMI8330_RMUX3D]);
if ((err = snd_cmi8330_mixer(card, acard)) < 0) {
snd_printk(KERN_ERR PFX "failed to create mixers\n");
diff --git a/sound/isa/cs423x/Makefile b/sound/isa/cs423x/Makefile
index 5067ee001933..5870ca21ab59 100644
--- a/sound/isa/cs423x/Makefile
+++ b/sound/isa/cs423x/Makefile
@@ -3,14 +3,12 @@
# Copyright (c) 2001 by Jaroslav Kysela
#
-snd-cs4231-lib-objs := cs4231_lib.o
snd-cs4236-lib-objs := cs4236_lib.o
snd-cs4231-objs := cs4231.o
snd-cs4232-objs := cs4232.o
snd-cs4236-objs := cs4236.o
# Toplevel Module Dependency
-obj-$(CONFIG_SND_CS4231_LIB) += snd-cs4231-lib.o
obj-$(CONFIG_SND_CS4231) += snd-cs4231.o
obj-$(CONFIG_SND_CS4232) += snd-cs4232.o
obj-$(CONFIG_SND_CS4236) += snd-cs4236.o snd-cs4236-lib.o
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index e9462b9944be..ddd289120aa8 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -27,7 +27,7 @@
#include
#include
#include
-#include
+#include
#include
#include
@@ -91,7 +91,7 @@ static int __devinit snd_cs4231_match(struct device *dev, unsigned int n)
static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n)
{
struct snd_card *card;
- struct snd_cs4231 *chip;
+ struct snd_wss *chip;
struct snd_pcm *pcm;
int error;
@@ -99,14 +99,14 @@ static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n)
if (!card)
return -EINVAL;
- error = snd_cs4231_create(card, port[n], -1, irq[n], dma1[n], dma2[n],
- CS4231_HW_DETECT, 0, &chip);
+ error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], dma2[n],
+ WSS_HW_DETECT, 0, &chip);
if (error < 0)
goto out;
card->private_data = chip;
- error = snd_cs4231_pcm(chip, 0, &pcm);
+ error = snd_wss_pcm(chip, 0, &pcm);
if (error < 0)
goto out;
@@ -118,11 +118,11 @@ static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n)
if (dma2[n] >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", dma2[n]);
- error = snd_cs4231_mixer(chip);
+ error = snd_wss_mixer(chip);
if (error < 0)
goto out;
- error = snd_cs4231_timer(chip, 0, NULL);
+ error = snd_wss_timer(chip, 0, NULL);
if (error < 0)
goto out;
@@ -160,7 +160,7 @@ static int __devexit snd_cs4231_remove(struct device *dev, unsigned int n)
static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t state)
{
struct snd_card *card = dev_get_drvdata(dev);
- struct snd_cs4231 *chip = card->private_data;
+ struct snd_wss *chip = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
chip->suspend(chip);
@@ -170,7 +170,7 @@ static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t s
static int snd_cs4231_resume(struct device *dev, unsigned int n)
{
struct snd_card *card = dev_get_drvdata(dev);
- struct snd_cs4231 *chip = card->private_data;
+ struct snd_wss *chip = card->private_data;
chip->resume(chip);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
deleted file mode 100644
index 521db705d179..000000000000
--- a/sound/isa/cs423x/cs4231_lib.c
+++ /dev/null
@@ -1,1945 +0,0 @@
-/*
- * Copyright (c) by Jaroslav Kysela
- * Routines for control of CS4231(A)/CS4232/InterWave & compatible chips
- *
- * Bugs:
- * - sometimes record brokes playback with WSS portion of
- * Yamaha OPL3-SA3 chip
- * - CS4231 (GUS MAX) - still trouble with occasional noises
- * - broken initialization?
- *
- * 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
-
-MODULE_AUTHOR("Jaroslav Kysela ");
-MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips");
-MODULE_LICENSE("GPL");
-
-#if 0
-#define SNDRV_DEBUG_MCE
-#endif
-
-/*
- * Some variables
- */
-
-static unsigned char freq_bits[14] = {
- /* 5510 */ 0x00 | CS4231_XTAL2,
- /* 6620 */ 0x0E | CS4231_XTAL2,
- /* 8000 */ 0x00 | CS4231_XTAL1,
- /* 9600 */ 0x0E | CS4231_XTAL1,
- /* 11025 */ 0x02 | CS4231_XTAL2,
- /* 16000 */ 0x02 | CS4231_XTAL1,
- /* 18900 */ 0x04 | CS4231_XTAL2,
- /* 22050 */ 0x06 | CS4231_XTAL2,
- /* 27042 */ 0x04 | CS4231_XTAL1,
- /* 32000 */ 0x06 | CS4231_XTAL1,
- /* 33075 */ 0x0C | CS4231_XTAL2,
- /* 37800 */ 0x08 | CS4231_XTAL2,
- /* 44100 */ 0x0A | CS4231_XTAL2,
- /* 48000 */ 0x0C | CS4231_XTAL1
-};
-
-static unsigned int rates[14] = {
- 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,
- 27042, 32000, 33075, 37800, 44100, 48000
-};
-
-static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
- .count = ARRAY_SIZE(rates),
- .list = rates,
- .mask = 0,
-};
-
-static int snd_cs4231_xrate(struct snd_pcm_runtime *runtime)
-{
- return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
-}
-
-static unsigned char snd_cs4231_original_image[32] =
-{
- 0x00, /* 00/00 - lic */
- 0x00, /* 01/01 - ric */
- 0x9f, /* 02/02 - la1ic */
- 0x9f, /* 03/03 - ra1ic */
- 0x9f, /* 04/04 - la2ic */
- 0x9f, /* 05/05 - ra2ic */
- 0xbf, /* 06/06 - loc */
- 0xbf, /* 07/07 - roc */
- 0x20, /* 08/08 - pdfr */
- CS4231_AUTOCALIB, /* 09/09 - ic */
- 0x00, /* 0a/10 - pc */
- 0x00, /* 0b/11 - ti */
- CS4231_MODE2, /* 0c/12 - mi */
- 0xfc, /* 0d/13 - lbc */
- 0x00, /* 0e/14 - pbru */
- 0x00, /* 0f/15 - pbrl */
- 0x80, /* 10/16 - afei */
- 0x01, /* 11/17 - afeii */
- 0x9f, /* 12/18 - llic */
- 0x9f, /* 13/19 - rlic */
- 0x00, /* 14/20 - tlb */
- 0x00, /* 15/21 - thb */
- 0x00, /* 16/22 - la3mic/reserved */
- 0x00, /* 17/23 - ra3mic/reserved */
- 0x00, /* 18/24 - afs */
- 0x00, /* 19/25 - lamoc/version */
- 0xcf, /* 1a/26 - mioc */
- 0x00, /* 1b/27 - ramoc/reserved */
- 0x20, /* 1c/28 - cdfr */
- 0x00, /* 1d/29 - res4 */
- 0x00, /* 1e/30 - cbru */
- 0x00, /* 1f/31 - cbrl */
-};
-
-static unsigned char snd_opti93x_original_image[32] =
-{
- 0x00, /* 00/00 - l_mixout_outctrl */
- 0x00, /* 01/01 - r_mixout_outctrl */
- 0x88, /* 02/02 - l_cd_inctrl */
- 0x88, /* 03/03 - r_cd_inctrl */
- 0x88, /* 04/04 - l_a1/fm_inctrl */
- 0x88, /* 05/05 - r_a1/fm_inctrl */
- 0x80, /* 06/06 - l_dac_inctrl */
- 0x80, /* 07/07 - r_dac_inctrl */
- 0x00, /* 08/08 - ply_dataform_reg */
- 0x00, /* 09/09 - if_conf */
- 0x00, /* 0a/10 - pin_ctrl */
- 0x00, /* 0b/11 - err_init_reg */
- 0x0a, /* 0c/12 - id_reg */
- 0x00, /* 0d/13 - reserved */
- 0x00, /* 0e/14 - ply_upcount_reg */
- 0x00, /* 0f/15 - ply_lowcount_reg */
- 0x88, /* 10/16 - reserved/l_a1_inctrl */
- 0x88, /* 11/17 - reserved/r_a1_inctrl */
- 0x88, /* 12/18 - l_line_inctrl */
- 0x88, /* 13/19 - r_line_inctrl */
- 0x88, /* 14/20 - l_mic_inctrl */
- 0x88, /* 15/21 - r_mic_inctrl */
- 0x80, /* 16/22 - l_out_outctrl */
- 0x80, /* 17/23 - r_out_outctrl */
- 0x00, /* 18/24 - reserved */
- 0x00, /* 19/25 - reserved */
- 0x00, /* 1a/26 - reserved */
- 0x00, /* 1b/27 - reserved */
- 0x00, /* 1c/28 - cap_dataform_reg */
- 0x00, /* 1d/29 - reserved */
- 0x00, /* 1e/30 - cap_upcount_reg */
- 0x00 /* 1f/31 - cap_lowcount_reg */
-};
-
-/*
- * Basic I/O functions
- */
-
-static inline void cs4231_outb(struct snd_cs4231 *chip, u8 offset, u8 val)
-{
- outb(val, chip->port + offset);
-}
-
-static inline u8 cs4231_inb(struct snd_cs4231 *chip, u8 offset)
-{
- return inb(chip->port + offset);
-}
-
-static void snd_cs4231_wait(struct snd_cs4231 *chip)
-{
- int timeout;
-
- for (timeout = 250;
- timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
- timeout--)
- udelay(100);
-}
-
-static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg,
- unsigned char mask, unsigned char value)
-{
- unsigned char tmp = (chip->image[reg] & mask) | value;
-
- snd_cs4231_wait(chip);
-#ifdef CONFIG_SND_DEBUG
- if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
- snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
-#endif
- chip->image[reg] = tmp;
- if (!chip->calibrate_mute) {
- cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
- wmb();
- cs4231_outb(chip, CS4231P(REG), tmp);
- mb();
- }
-}
-
-static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, unsigned char value)
-{
- int timeout;
-
- for (timeout = 250;
- timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
- timeout--)
- udelay(10);
- cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
- cs4231_outb(chip, CS4231P(REG), value);
- mb();
-}
-
-void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value)
-{
- snd_cs4231_wait(chip);
-#ifdef CONFIG_SND_DEBUG
- if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
- snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
-#endif
- cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
- cs4231_outb(chip, CS4231P(REG), value);
- chip->image[reg] = value;
- mb();
- snd_printdd("codec out - reg 0x%x = 0x%x\n",
- chip->mce_bit | reg, value);
-}
-
-unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg)
-{
- snd_cs4231_wait(chip);
-#ifdef CONFIG_SND_DEBUG
- if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
- snd_printk("in: auto calibration time out - reg = 0x%x\n", reg);
-#endif
- cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
- mb();
- return cs4231_inb(chip, CS4231P(REG));
-}
-
-void snd_cs4236_ext_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val)
-{
- cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
- cs4231_outb(chip, CS4231P(REG), reg | (chip->image[CS4236_EXT_REG] & 0x01));
- cs4231_outb(chip, CS4231P(REG), val);
- chip->eimage[CS4236_REG(reg)] = val;
-#if 0
- printk("ext out : reg = 0x%x, val = 0x%x\n", reg, val);
-#endif
-}
-
-unsigned char snd_cs4236_ext_in(struct snd_cs4231 *chip, unsigned char reg)
-{
- cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
- cs4231_outb(chip, CS4231P(REG), reg | (chip->image[CS4236_EXT_REG] & 0x01));
-#if 1
- return cs4231_inb(chip, CS4231P(REG));
-#else
- {
- unsigned char res;
- res = cs4231_inb(chip, CS4231P(REG));
- printk("ext in : reg = 0x%x, val = 0x%x\n", reg, res);
- return res;
- }
-#endif
-}
-
-#if 0
-
-static void snd_cs4231_debug(struct snd_cs4231 *chip)
-{
- printk("CS4231 REGS: INDEX = 0x%02x ", cs4231_inb(chip, CS4231P(REGSEL)));
- printk(" STATUS = 0x%02x\n", cs4231_inb(chip, CS4231P(STATUS)));
- printk(" 0x00: left input = 0x%02x ", snd_cs4231_in(chip, 0x00));
- printk(" 0x10: alt 1 (CFIG 2) = 0x%02x\n", snd_cs4231_in(chip, 0x10));
- printk(" 0x01: right input = 0x%02x ", snd_cs4231_in(chip, 0x01));
- printk(" 0x11: alt 2 (CFIG 3) = 0x%02x\n", snd_cs4231_in(chip, 0x11));
- printk(" 0x02: GF1 left input = 0x%02x ", snd_cs4231_in(chip, 0x02));
- printk(" 0x12: left line in = 0x%02x\n", snd_cs4231_in(chip, 0x12));
- printk(" 0x03: GF1 right input = 0x%02x ", snd_cs4231_in(chip, 0x03));
- printk(" 0x13: right line in = 0x%02x\n", snd_cs4231_in(chip, 0x13));
- printk(" 0x04: CD left input = 0x%02x ", snd_cs4231_in(chip, 0x04));
- printk(" 0x14: timer low = 0x%02x\n", snd_cs4231_in(chip, 0x14));
- printk(" 0x05: CD right input = 0x%02x ", snd_cs4231_in(chip, 0x05));
- printk(" 0x15: timer high = 0x%02x\n", snd_cs4231_in(chip, 0x15));
- printk(" 0x06: left output = 0x%02x ", snd_cs4231_in(chip, 0x06));
- printk(" 0x16: left MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x16));
- printk(" 0x07: right output = 0x%02x ", snd_cs4231_in(chip, 0x07));
- printk(" 0x17: right MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x17));
- printk(" 0x08: playback format = 0x%02x ", snd_cs4231_in(chip, 0x08));
- printk(" 0x18: IRQ status = 0x%02x\n", snd_cs4231_in(chip, 0x18));
- printk(" 0x09: iface (CFIG 1) = 0x%02x ", snd_cs4231_in(chip, 0x09));
- printk(" 0x19: left line out = 0x%02x\n", snd_cs4231_in(chip, 0x19));
- printk(" 0x0a: pin control = 0x%02x ", snd_cs4231_in(chip, 0x0a));
- printk(" 0x1a: mono control = 0x%02x\n", snd_cs4231_in(chip, 0x1a));
- printk(" 0x0b: init & status = 0x%02x ", snd_cs4231_in(chip, 0x0b));
- printk(" 0x1b: right line out = 0x%02x\n", snd_cs4231_in(chip, 0x1b));
- printk(" 0x0c: revision & mode = 0x%02x ", snd_cs4231_in(chip, 0x0c));
- printk(" 0x1c: record format = 0x%02x\n", snd_cs4231_in(chip, 0x1c));
- printk(" 0x0d: loopback = 0x%02x ", snd_cs4231_in(chip, 0x0d));
- printk(" 0x1d: var freq (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x1d));
- printk(" 0x0e: ply upr count = 0x%02x ", snd_cs4231_in(chip, 0x0e));
- printk(" 0x1e: ply lwr count = 0x%02x\n", snd_cs4231_in(chip, 0x1e));
- printk(" 0x0f: rec upr count = 0x%02x ", snd_cs4231_in(chip, 0x0f));
- printk(" 0x1f: rec lwr count = 0x%02x\n", snd_cs4231_in(chip, 0x1f));
-}
-
-#endif
-
-/*
- * CS4231 detection / MCE routines
- */
-
-static void snd_cs4231_busy_wait(struct snd_cs4231 *chip)
-{
- int timeout;
-
- /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
- for (timeout = 5; timeout > 0; timeout--)
- cs4231_inb(chip, CS4231P(REGSEL));
- /* end of cleanup sequence */
- for (timeout = 250;
- timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
- timeout--)
- udelay(10);
-}
-
-void snd_cs4231_mce_up(struct snd_cs4231 *chip)
-{
- unsigned long flags;
- int timeout;
-
- snd_cs4231_wait(chip);
-#ifdef CONFIG_SND_DEBUG
- if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
- snd_printk("mce_up - auto calibration time out (0)\n");
-#endif
- spin_lock_irqsave(&chip->reg_lock, flags);
- chip->mce_bit |= CS4231_MCE;
- timeout = cs4231_inb(chip, CS4231P(REGSEL));
- if (timeout == 0x80)
- snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
- if (!(timeout & CS4231_MCE))
- cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-}
-
-void snd_cs4231_mce_down(struct snd_cs4231 *chip)
-{
- unsigned long flags;
- unsigned long end_time;
- int timeout;
-
- snd_cs4231_busy_wait(chip);
-
-#ifdef CONFIG_SND_DEBUG
- if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
- snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL));
-#endif
- spin_lock_irqsave(&chip->reg_lock, flags);
- chip->mce_bit &= ~CS4231_MCE;
- timeout = cs4231_inb(chip, CS4231P(REGSEL));
- cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- if (timeout == 0x80)
- snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
- if ((timeout & CS4231_MCE) == 0 ||
- !(chip->hardware & (CS4231_HW_CS4231_MASK | CS4231_HW_CS4232_MASK))) {
- return;
- }
-
- /*
- * Wait for (possible -- during init auto-calibration may not be set)
- * calibration process to start. Needs upto 5 sample periods on AD1848
- * which at the slowest possible rate of 5.5125 kHz means 907 us.
- */
- msleep(1);
-
- snd_printdd("(1) jiffies = %lu\n", jiffies);
-
- /* check condition up to 250 ms */
- end_time = jiffies + msecs_to_jiffies(250);
- while (snd_cs4231_in(chip, CS4231_TEST_INIT) &
- CS4231_CALIB_IN_PROGRESS) {
-
- if (time_after(jiffies, end_time)) {
- snd_printk(KERN_ERR "mce_down - "
- "auto calibration time out (2)\n");
- return;
- }
- msleep(1);
- }
-
- snd_printdd("(2) jiffies = %lu\n", jiffies);
-
- /* check condition up to 100 ms */
- end_time = jiffies + msecs_to_jiffies(100);
- while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
- if (time_after(jiffies, end_time)) {
- snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
- return;
- }
- msleep(1);
- }
-
- snd_printdd("(3) jiffies = %lu\n", jiffies);
- snd_printd("mce_down - exit = 0x%x\n", cs4231_inb(chip, CS4231P(REGSEL)));
-}
-
-static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size)
-{
- switch (format & 0xe0) {
- case CS4231_LINEAR_16:
- case CS4231_LINEAR_16_BIG:
- size >>= 1;
- break;
- case CS4231_ADPCM_16:
- return size >> 2;
- }
- if (format & CS4231_STEREO)
- size >>= 1;
- return size;
-}
-
-static int snd_cs4231_trigger(struct snd_pcm_substream *substream,
- int cmd)
-{
- struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
- int result = 0;
- unsigned int what;
- struct snd_pcm_substream *s;
- int do_start;
-
-#if 0
- printk("codec trigger!!! - what = %i, enable = %i, status = 0x%x\n", what, enable, cs4231_inb(chip, CS4231P(STATUS)));
-#endif
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- do_start = 1; break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- do_start = 0; break;
- default:
- return -EINVAL;
- }
-
- what = 0;
- snd_pcm_group_for_each_entry(s, substream) {
- if (s == chip->playback_substream) {
- what |= CS4231_PLAYBACK_ENABLE;
- snd_pcm_trigger_done(s, substream);
- } else if (s == chip->capture_substream) {
- what |= CS4231_RECORD_ENABLE;
- snd_pcm_trigger_done(s, substream);
- }
- }
- spin_lock(&chip->reg_lock);
- if (do_start) {
- chip->image[CS4231_IFACE_CTRL] |= what;
- if (chip->trigger)
- chip->trigger(chip, what, 1);
- } else {
- chip->image[CS4231_IFACE_CTRL] &= ~what;
- if (chip->trigger)
- chip->trigger(chip, what, 0);
- }
- snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
- spin_unlock(&chip->reg_lock);
-#if 0
- snd_cs4231_debug(chip);
-#endif
- return result;
-}
-
-/*
- * CODEC I/O
- */
-
-static unsigned char snd_cs4231_get_rate(unsigned int rate)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(rates); i++)
- if (rate == rates[i])
- return freq_bits[i];
- // snd_BUG();
- return freq_bits[ARRAY_SIZE(rates) - 1];
-}
-
-static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip,
- int format,
- int channels)
-{
- unsigned char rformat;
-
- rformat = CS4231_LINEAR_8;
- switch (format) {
- case SNDRV_PCM_FORMAT_MU_LAW: rformat = CS4231_ULAW_8; break;
- case SNDRV_PCM_FORMAT_A_LAW: rformat = CS4231_ALAW_8; break;
- case SNDRV_PCM_FORMAT_S16_LE: rformat = CS4231_LINEAR_16; break;
- case SNDRV_PCM_FORMAT_S16_BE: rformat = CS4231_LINEAR_16_BIG; break;
- case SNDRV_PCM_FORMAT_IMA_ADPCM: rformat = CS4231_ADPCM_16; break;
- }
- if (channels > 1)
- rformat |= CS4231_STEREO;
-#if 0
- snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
-#endif
- return rformat;
-}
-
-static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute)
-{
- unsigned long flags;
-
- mute = mute ? 1 : 0;
- spin_lock_irqsave(&chip->reg_lock, flags);
- if (chip->calibrate_mute == mute) {
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return;
- }
- if (!mute) {
- snd_cs4231_dout(chip, CS4231_LEFT_INPUT, chip->image[CS4231_LEFT_INPUT]);
- snd_cs4231_dout(chip, CS4231_RIGHT_INPUT, chip->image[CS4231_RIGHT_INPUT]);
- snd_cs4231_dout(chip, CS4231_LOOPBACK, chip->image[CS4231_LOOPBACK]);
- }
- snd_cs4231_dout(chip, CS4231_AUX1_LEFT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX1_LEFT_INPUT]);
- snd_cs4231_dout(chip, CS4231_AUX1_RIGHT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX1_RIGHT_INPUT]);
- snd_cs4231_dout(chip, CS4231_AUX2_LEFT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX2_LEFT_INPUT]);
- snd_cs4231_dout(chip, CS4231_AUX2_RIGHT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX2_RIGHT_INPUT]);
- snd_cs4231_dout(chip, CS4231_LEFT_OUTPUT, mute ? 0x80 : chip->image[CS4231_LEFT_OUTPUT]);
- snd_cs4231_dout(chip, CS4231_RIGHT_OUTPUT, mute ? 0x80 : chip->image[CS4231_RIGHT_OUTPUT]);
- snd_cs4231_dout(chip, CS4231_LEFT_LINE_IN, mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]);
- snd_cs4231_dout(chip, CS4231_RIGHT_LINE_IN, mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]);
- snd_cs4231_dout(chip, CS4231_MONO_CTRL, mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);
- if (chip->hardware == CS4231_HW_INTERWAVE) {
- snd_cs4231_dout(chip, CS4231_LEFT_MIC_INPUT, mute ? 0x80 : chip->image[CS4231_LEFT_MIC_INPUT]);
- snd_cs4231_dout(chip, CS4231_RIGHT_MIC_INPUT, mute ? 0x80 : chip->image[CS4231_RIGHT_MIC_INPUT]);
- snd_cs4231_dout(chip, CS4231_LINE_LEFT_OUTPUT, mute ? 0x80 : chip->image[CS4231_LINE_LEFT_OUTPUT]);
- snd_cs4231_dout(chip, CS4231_LINE_RIGHT_OUTPUT, mute ? 0x80 : chip->image[CS4231_LINE_RIGHT_OUTPUT]);
- }
- chip->calibrate_mute = mute;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-}
-
-static void snd_cs4231_playback_format(struct snd_cs4231 *chip,
- struct snd_pcm_hw_params *params,
- unsigned char pdfr)
-{
- unsigned long flags;
- int full_calib = 1;
-
- mutex_lock(&chip->mce_mutex);
- snd_cs4231_calibrate_mute(chip, 1);
- if (chip->hardware == CS4231_HW_CS4231A ||
- (chip->hardware & CS4231_HW_CS4232_MASK)) {
- spin_lock_irqsave(&chip->reg_lock, flags);
- if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (pdfr & 0x0f)) { /* rate is same? */
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x10);
- snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr);
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~0x10);
- udelay(100); /* Fixes audible clicks at least on GUS MAX */
- full_calib = 0;
- }
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- }
- if (full_calib) {
- snd_cs4231_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- if (chip->hardware != CS4231_HW_INTERWAVE && !chip->single_dma) {
- snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT,
- (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) ?
- (pdfr & 0xf0) | (chip->image[CS4231_REC_FORMAT] & 0x0f) :
- pdfr);
- } else {
- snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr);
- }
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- if (chip->hardware == CS4231_HW_OPL3SA2)
- udelay(100); /* this seems to help */
- snd_cs4231_mce_down(chip);
- }
- snd_cs4231_calibrate_mute(chip, 0);
- mutex_unlock(&chip->mce_mutex);
-}
-
-static void snd_cs4231_capture_format(struct snd_cs4231 *chip,
- struct snd_pcm_hw_params *params,
- unsigned char cdfr)
-{
- unsigned long flags;
- int full_calib = 1;
-
- mutex_lock(&chip->mce_mutex);
- snd_cs4231_calibrate_mute(chip, 1);
- if (chip->hardware == CS4231_HW_CS4231A ||
- (chip->hardware & CS4231_HW_CS4232_MASK)) {
- spin_lock_irqsave(&chip->reg_lock, flags);
- if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (cdfr & 0x0f) || /* rate is same? */
- (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x20);
- snd_cs4231_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT] = cdfr);
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~0x20);
- full_calib = 0;
- }
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- }
- if (full_calib) {
- snd_cs4231_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- if (chip->hardware != CS4231_HW_INTERWAVE) {
- if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
- snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT,
- ((chip->single_dma ? cdfr : chip->image[CS4231_PLAYBK_FORMAT]) & 0xf0) |
- (cdfr & 0x0f));
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_cs4231_mce_down(chip);
- snd_cs4231_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- }
- }
- snd_cs4231_out(chip, CS4231_REC_FORMAT, cdfr);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_cs4231_mce_down(chip);
- }
- snd_cs4231_calibrate_mute(chip, 0);
- mutex_unlock(&chip->mce_mutex);
-}
-
-/*
- * Timer interface
- */
-
-static unsigned long snd_cs4231_timer_resolution(struct snd_timer * timer)
-{
- struct snd_cs4231 *chip = snd_timer_chip(timer);
- if (chip->hardware & CS4231_HW_CS4236B_MASK)
- return 14467;
- else
- return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920;
-}
-
-static int snd_cs4231_timer_start(struct snd_timer * timer)
-{
- unsigned long flags;
- unsigned int ticks;
- struct snd_cs4231 *chip = snd_timer_chip(timer);
- spin_lock_irqsave(&chip->reg_lock, flags);
- ticks = timer->sticks;
- if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 ||
- (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] ||
- (unsigned char)ticks != chip->image[CS4231_TIMER_LOW]) {
- snd_cs4231_out(chip, CS4231_TIMER_HIGH, chip->image[CS4231_TIMER_HIGH] = (unsigned char) (ticks >> 8));
- snd_cs4231_out(chip, CS4231_TIMER_LOW, chip->image[CS4231_TIMER_LOW] = (unsigned char) ticks);
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | CS4231_TIMER_ENABLE);
- }
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return 0;
-}
-
-static int snd_cs4231_timer_stop(struct snd_timer * timer)
-{
- unsigned long flags;
- struct snd_cs4231 *chip = snd_timer_chip(timer);
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return 0;
-}
-
-static void snd_cs4231_init(struct snd_cs4231 *chip)
-{
- unsigned long flags;
-
- snd_cs4231_mce_down(chip);
-
-#ifdef SNDRV_DEBUG_MCE
- snd_printk("init: (1)\n");
-#endif
- snd_cs4231_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
- CS4231_RECORD_ENABLE | CS4231_RECORD_PIO |
- CS4231_CALIB_MODE);
- chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB;
- snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_cs4231_mce_down(chip);
-
-#ifdef SNDRV_DEBUG_MCE
- snd_printk("init: (2)\n");
-#endif
-
- snd_cs4231_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_cs4231_mce_down(chip);
-
-#ifdef SNDRV_DEBUG_MCE
- snd_printk("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]);
-#endif
-
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_2, chip->image[CS4231_ALT_FEATURE_2]);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-
- snd_cs4231_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT]);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_cs4231_mce_down(chip);
-
-#ifdef SNDRV_DEBUG_MCE
- snd_printk("init: (4)\n");
-#endif
-
- snd_cs4231_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_cs4231_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT]);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_cs4231_mce_down(chip);
-
-#ifdef SNDRV_DEBUG_MCE
- snd_printk("init: (5)\n");
-#endif
-}
-
-static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode)
-{
- unsigned long flags;
-
- mutex_lock(&chip->open_mutex);
- if ((chip->mode & mode) ||
- ((chip->mode & CS4231_MODE_OPEN) && chip->single_dma)) {
- mutex_unlock(&chip->open_mutex);
- return -EAGAIN;
- }
- if (chip->mode & CS4231_MODE_OPEN) {
- chip->mode |= mode;
- mutex_unlock(&chip->open_mutex);
- return 0;
- }
- /* ok. now enable and ack CODEC IRQ */
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ |
- CS4231_RECORD_IRQ |
- CS4231_TIMER_IRQ);
- snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
- cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
- cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
- chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE;
- snd_cs4231_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
- snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ |
- CS4231_RECORD_IRQ |
- CS4231_TIMER_IRQ);
- snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-
- chip->mode = mode;
- mutex_unlock(&chip->open_mutex);
- return 0;
-}
-
-static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode)
-{
- unsigned long flags;
-
- mutex_lock(&chip->open_mutex);
- chip->mode &= ~mode;
- if (chip->mode & CS4231_MODE_OPEN) {
- mutex_unlock(&chip->open_mutex);
- return;
- }
- snd_cs4231_calibrate_mute(chip, 1);
-
- /* disable IRQ */
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
- cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
- cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
- chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE;
- snd_cs4231_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
-
- /* now disable record & playback */
-
- if (chip->image[CS4231_IFACE_CTRL] & (CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
- CS4231_RECORD_ENABLE | CS4231_RECORD_PIO)) {
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_cs4231_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
- CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
- snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_cs4231_mce_down(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- }
-
- /* clear IRQ again */
- snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
- cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
- cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-
- snd_cs4231_calibrate_mute(chip, 0);
-
- chip->mode = 0;
- mutex_unlock(&chip->open_mutex);
-}
-
-/*
- * timer open/close
- */
-
-static int snd_cs4231_timer_open(struct snd_timer * timer)
-{
- struct snd_cs4231 *chip = snd_timer_chip(timer);
- snd_cs4231_open(chip, CS4231_MODE_TIMER);
- return 0;
-}
-
-static int snd_cs4231_timer_close(struct snd_timer * timer)
-{
- struct snd_cs4231 *chip = snd_timer_chip(timer);
- snd_cs4231_close(chip, CS4231_MODE_TIMER);
- return 0;
-}
-
-static struct snd_timer_hardware snd_cs4231_timer_table =
-{
- .flags = SNDRV_TIMER_HW_AUTO,
- .resolution = 9945,
- .ticks = 65535,
- .open = snd_cs4231_timer_open,
- .close = snd_cs4231_timer_close,
- .c_resolution = snd_cs4231_timer_resolution,
- .start = snd_cs4231_timer_start,
- .stop = snd_cs4231_timer_stop,
-};
-
-/*
- * ok.. exported functions..
- */
-
-static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
- unsigned char new_pdfr;
- int err;
-
- if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
- return err;
- new_pdfr = snd_cs4231_get_format(chip, params_format(hw_params), params_channels(hw_params)) |
- snd_cs4231_get_rate(params_rate(hw_params));
- chip->set_playback_format(chip, hw_params, new_pdfr);
- return 0;
-}
-
-static int snd_cs4231_playback_hw_free(struct snd_pcm_substream *substream)
-{
- return snd_pcm_lib_free_pages(substream);
-}
-
-static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream)
-{
- struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned long flags;
- unsigned int size = snd_pcm_lib_buffer_bytes(substream);
- unsigned int count = snd_pcm_lib_period_bytes(substream);
-
- spin_lock_irqsave(&chip->reg_lock, flags);
- chip->p_dma_size = size;
- chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO);
- snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
- count = snd_cs4231_get_count(chip->image[CS4231_PLAYBK_FORMAT], count) - 1;
- snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
- snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8));
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-#if 0
- snd_cs4231_debug(chip);
-#endif
- return 0;
-}
-
-static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
- unsigned char new_cdfr;
- int err;
-
- if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
- return err;
- new_cdfr = snd_cs4231_get_format(chip, params_format(hw_params), params_channels(hw_params)) |
- snd_cs4231_get_rate(params_rate(hw_params));
- chip->set_capture_format(chip, hw_params, new_cdfr);
- return 0;
-}
-
-static int snd_cs4231_capture_hw_free(struct snd_pcm_substream *substream)
-{
- return snd_pcm_lib_free_pages(substream);
-}
-
-static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream)
-{
- struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned long flags;
- unsigned int size = snd_pcm_lib_buffer_bytes(substream);
- unsigned int count = snd_pcm_lib_period_bytes(substream);
-
- spin_lock_irqsave(&chip->reg_lock, flags);
- chip->c_dma_size = size;
- chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
- snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
- count = snd_cs4231_get_count(chip->image[CS4231_REC_FORMAT], count) - 1;
- if (chip->single_dma && chip->hardware != CS4231_HW_INTERWAVE) {
- snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
- snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8));
- } else {
- snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (unsigned char) count);
- snd_cs4231_out(chip, CS4231_REC_UPR_CNT, (unsigned char) (count >> 8));
- }
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return 0;
-}
-
-void snd_cs4231_overrange(struct snd_cs4231 *chip)
-{
- unsigned long flags;
- unsigned char res;
-
- spin_lock_irqsave(&chip->reg_lock, flags);
- res = snd_cs4231_in(chip, CS4231_TEST_INIT);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- if (res & (0x08 | 0x02)) /* detect overrange only above 0dB; may be user selectable? */
- chip->capture_substream->runtime->overrange++;
-}
-
-irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id)
-{
- struct snd_cs4231 *chip = dev_id;
- unsigned char status;
-
- status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
- if (status & CS4231_TIMER_IRQ) {
- if (chip->timer)
- snd_timer_interrupt(chip->timer, chip->timer->sticks);
- }
- if (chip->single_dma && chip->hardware != CS4231_HW_INTERWAVE) {
- if (status & CS4231_PLAYBACK_IRQ) {
- if (chip->mode & CS4231_MODE_PLAY) {
- if (chip->playback_substream)
- snd_pcm_period_elapsed(chip->playback_substream);
- }
- if (chip->mode & CS4231_MODE_RECORD) {
- if (chip->capture_substream) {
- snd_cs4231_overrange(chip);
- snd_pcm_period_elapsed(chip->capture_substream);
- }
- }
- }
- } else {
- if (status & CS4231_PLAYBACK_IRQ) {
- if (chip->playback_substream)
- snd_pcm_period_elapsed(chip->playback_substream);
- }
- if (status & CS4231_RECORD_IRQ) {
- if (chip->capture_substream) {
- snd_cs4231_overrange(chip);
- snd_pcm_period_elapsed(chip->capture_substream);
- }
- }
- }
-
- spin_lock(&chip->reg_lock);
- snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);
- spin_unlock(&chip->reg_lock);
- return IRQ_HANDLED;
-}
-
-static snd_pcm_uframes_t snd_cs4231_playback_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
- size_t ptr;
-
- if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
- return 0;
- ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);
- return bytes_to_frames(substream->runtime, ptr);
-}
-
-static snd_pcm_uframes_t snd_cs4231_capture_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
- size_t ptr;
-
- if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
- return 0;
- ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
- return bytes_to_frames(substream->runtime, ptr);
-}
-
-/*
-
- */
-
-static int snd_cs4231_probe(struct snd_cs4231 *chip)
-{
- unsigned long flags;
- int i, id, rev;
- unsigned char *ptr;
- unsigned int hw;
-
-#if 0
- snd_cs4231_debug(chip);
-#endif
- id = 0;
- for (i = 0; i < 50; i++) {
- mb();
- if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
- udelay(2000);
- else {
- spin_lock_irqsave(&chip->reg_lock, flags);
- snd_cs4231_out(chip, CS4231_MISC_INFO, CS4231_MODE2);
- id = snd_cs4231_in(chip, CS4231_MISC_INFO) & 0x0f;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- if (id == 0x0a)
- break; /* this is valid value */
- }
- }
- snd_printdd("cs4231: port = 0x%lx, id = 0x%x\n", chip->port, id);
- if (id != 0x0a)
- return -ENODEV; /* no valid device found */
-
- if (((hw = chip->hardware) & CS4231_HW_TYPE_MASK) == CS4231_HW_DETECT) {
- rev = snd_cs4231_in(chip, CS4231_VERSION) & 0xe7;
- snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev);
- if (rev == 0x80) {
- unsigned char tmp = snd_cs4231_in(chip, 23);
- snd_cs4231_out(chip, 23, ~tmp);
- if (snd_cs4231_in(chip, 23) != tmp)
- chip->hardware = CS4231_HW_AD1845;
- else
- chip->hardware = CS4231_HW_CS4231;
- } else if (rev == 0xa0) {
- chip->hardware = CS4231_HW_CS4231A;
- } else if (rev == 0xa2) {
- chip->hardware = CS4231_HW_CS4232;
- } else if (rev == 0xb2) {
- chip->hardware = CS4231_HW_CS4232A;
- } else if (rev == 0x83) {
- chip->hardware = CS4231_HW_CS4236;
- } else if (rev == 0x03) {
- chip->hardware = CS4231_HW_CS4236B;
- } else {
- snd_printk("unknown CS chip with version 0x%x\n", rev);
- return -ENODEV; /* unknown CS4231 chip? */
- }
- }
- spin_lock_irqsave(&chip->reg_lock, flags);
- cs4231_inb(chip, CS4231P(STATUS)); /* clear any pendings IRQ */
- cs4231_outb(chip, CS4231P(STATUS), 0);
- mb();
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-
- chip->image[CS4231_MISC_INFO] = CS4231_MODE2;
- switch (chip->hardware) {
- case CS4231_HW_INTERWAVE:
- chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3;
- break;
- case CS4231_HW_CS4235:
- case CS4231_HW_CS4236B:
- case CS4231_HW_CS4237B:
- case CS4231_HW_CS4238B:
- case CS4231_HW_CS4239:
- if (hw == CS4231_HW_DETECT3)
- chip->image[CS4231_MISC_INFO] = CS4231_4236_MODE3;
- else
- chip->hardware = CS4231_HW_CS4236;
- break;
- }
-
- chip->image[CS4231_IFACE_CTRL] =
- (chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) |
- (chip->single_dma ? CS4231_SINGLE_DMA : 0);
- if (chip->hardware != CS4231_HW_OPTI93X) {
- chip->image[CS4231_ALT_FEATURE_1] = 0x80;
- chip->image[CS4231_ALT_FEATURE_2] =
- chip->hardware == CS4231_HW_INTERWAVE ? 0xc2 : 0x01;
- }
- ptr = (unsigned char *) &chip->image;
- snd_cs4231_mce_down(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- for (i = 0; i < 32; i++) /* ok.. fill all CS4231 registers */
- snd_cs4231_out(chip, i, *ptr++);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_cs4231_mce_up(chip);
- snd_cs4231_mce_down(chip);
-
- mdelay(2);
-
- /* ok.. try check hardware version for CS4236+ chips */
- if ((hw & CS4231_HW_TYPE_MASK) == CS4231_HW_DETECT) {
- if (chip->hardware == CS4231_HW_CS4236B) {
- rev = snd_cs4236_ext_in(chip, CS4236_VERSION);
- snd_cs4236_ext_out(chip, CS4236_VERSION, 0xff);
- id = snd_cs4236_ext_in(chip, CS4236_VERSION);
- snd_cs4236_ext_out(chip, CS4236_VERSION, rev);
- snd_printdd("CS4231: ext version; rev = 0x%x, id = 0x%x\n", rev, id);
- if ((id & 0x1f) == 0x1d) { /* CS4235 */
- chip->hardware = CS4231_HW_CS4235;
- switch (id >> 5) {
- case 4:
- case 5:
- case 6:
- break;
- default:
- snd_printk("unknown CS4235 chip (enhanced version = 0x%x)\n", id);
- }
- } else if ((id & 0x1f) == 0x0b) { /* CS4236/B */
- switch (id >> 5) {
- case 4:
- case 5:
- case 6:
- case 7:
- chip->hardware = CS4231_HW_CS4236B;
- break;
- default:
- snd_printk("unknown CS4236 chip (enhanced version = 0x%x)\n", id);
- }
- } else if ((id & 0x1f) == 0x08) { /* CS4237B */
- chip->hardware = CS4231_HW_CS4237B;
- switch (id >> 5) {
- case 4:
- case 5:
- case 6:
- case 7:
- break;
- default:
- snd_printk("unknown CS4237B chip (enhanced version = 0x%x)\n", id);
- }
- } else if ((id & 0x1f) == 0x09) { /* CS4238B */
- chip->hardware = CS4231_HW_CS4238B;
- switch (id >> 5) {
- case 5:
- case 6:
- case 7:
- break;
- default:
- snd_printk("unknown CS4238B chip (enhanced version = 0x%x)\n", id);
- }
- } else if ((id & 0x1f) == 0x1e) { /* CS4239 */
- chip->hardware = CS4231_HW_CS4239;
- switch (id >> 5) {
- case 4:
- case 5:
- case 6:
- break;
- default:
- snd_printk("unknown CS4239 chip (enhanced version = 0x%x)\n", id);
- }
- } else {
- snd_printk("unknown CS4236/CS423xB chip (enhanced version = 0x%x)\n", id);
- }
- }
- }
- return 0; /* all things are ok.. */
-}
-
-/*
-
- */
-
-static struct snd_pcm_hardware snd_cs4231_playback =
-{
- .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_RESUME |
- SNDRV_PCM_INFO_SYNC_START),
- .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
- SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
- .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
- .rate_min = 5510,
- .rate_max = 48000,
- .channels_min = 1,
- .channels_max = 2,
- .buffer_bytes_max = (128*1024),
- .period_bytes_min = 64,
- .period_bytes_max = (128*1024),
- .periods_min = 1,
- .periods_max = 1024,
- .fifo_size = 0,
-};
-
-static struct snd_pcm_hardware snd_cs4231_capture =
-{
- .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_RESUME |
- SNDRV_PCM_INFO_SYNC_START),
- .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
- SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
- .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
- .rate_min = 5510,
- .rate_max = 48000,
- .channels_min = 1,
- .channels_max = 2,
- .buffer_bytes_max = (128*1024),
- .period_bytes_min = 64,
- .period_bytes_max = (128*1024),
- .periods_min = 1,
- .periods_max = 1024,
- .fifo_size = 0,
-};
-
-/*
-
- */
-
-static int snd_cs4231_playback_open(struct snd_pcm_substream *substream)
-{
- struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
-
- runtime->hw = snd_cs4231_playback;
-
- /* hardware bug in InterWave chipset */
- if (chip->hardware == CS4231_HW_INTERWAVE && chip->dma1 > 3)
- runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW;
-
- /* hardware limitation of cheap chips */
- if (chip->hardware == CS4231_HW_CS4235 ||
- chip->hardware == CS4231_HW_CS4239)
- runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
-
- snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
- snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
-
- if (chip->claim_dma) {
- if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0)
- return err;
- }
-
- if ((err = snd_cs4231_open(chip, CS4231_MODE_PLAY)) < 0) {
- if (chip->release_dma)
- chip->release_dma(chip, chip->dma_private_data, chip->dma1);
- snd_free_pages(runtime->dma_area, runtime->dma_bytes);
- return err;
- }
- chip->playback_substream = substream;
- snd_pcm_set_sync(substream);
- chip->rate_constraint(runtime);
- return 0;
-}
-
-static int snd_cs4231_capture_open(struct snd_pcm_substream *substream)
-{
- struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
-
- runtime->hw = snd_cs4231_capture;
-
- /* hardware limitation of cheap chips */
- if (chip->hardware == CS4231_HW_CS4235 ||
- chip->hardware == CS4231_HW_CS4239)
- runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
-
- snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
- snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
-
- if (chip->claim_dma) {
- if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0)
- return err;
- }
-
- if ((err = snd_cs4231_open(chip, CS4231_MODE_RECORD)) < 0) {
- if (chip->release_dma)
- chip->release_dma(chip, chip->dma_private_data, chip->dma2);
- snd_free_pages(runtime->dma_area, runtime->dma_bytes);
- return err;
- }
- chip->capture_substream = substream;
- snd_pcm_set_sync(substream);
- chip->rate_constraint(runtime);
- return 0;
-}
-
-static int snd_cs4231_playback_close(struct snd_pcm_substream *substream)
-{
- struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
-
- chip->playback_substream = NULL;
- snd_cs4231_close(chip, CS4231_MODE_PLAY);
- return 0;
-}
-
-static int snd_cs4231_capture_close(struct snd_pcm_substream *substream)
-{
- struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
-
- chip->capture_substream = NULL;
- snd_cs4231_close(chip, CS4231_MODE_RECORD);
- return 0;
-}
-
-#ifdef CONFIG_PM
-
-/* lowlevel suspend callback for CS4231 */
-static void snd_cs4231_suspend(struct snd_cs4231 *chip)
-{
- int reg;
- unsigned long flags;
-
- snd_pcm_suspend_all(chip->pcm);
- spin_lock_irqsave(&chip->reg_lock, flags);
- for (reg = 0; reg < 32; reg++)
- chip->image[reg] = snd_cs4231_in(chip, reg);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-}
-
-/* lowlevel resume callback for CS4231 */
-static void snd_cs4231_resume(struct snd_cs4231 *chip)
-{
- int reg;
- unsigned long flags;
- /* int timeout; */
-
- snd_cs4231_mce_up(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- for (reg = 0; reg < 32; reg++) {
- switch (reg) {
- case CS4231_VERSION:
- break;
- default:
- snd_cs4231_out(chip, reg, chip->image[reg]);
- break;
- }
- }
- spin_unlock_irqrestore(&chip->reg_lock, flags);
-#if 1
- snd_cs4231_mce_down(chip);
-#else
- /* The following is a workaround to avoid freeze after resume on TP600E.
- This is the first half of copy of snd_cs4231_mce_down(), but doesn't
- include rescheduling. -- iwai
- */
- snd_cs4231_busy_wait(chip);
- spin_lock_irqsave(&chip->reg_lock, flags);
- chip->mce_bit &= ~CS4231_MCE;
- timeout = cs4231_inb(chip, CS4231P(REGSEL));
- cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- if (timeout == 0x80)
- snd_printk("down [0x%lx]: serious init problem - codec still busy\n", chip->port);
- if ((timeout & CS4231_MCE) == 0 ||
- !(chip->hardware & (CS4231_HW_CS4231_MASK | CS4231_HW_CS4232_MASK))) {
- return;
- }
- snd_cs4231_busy_wait(chip);
-#endif
-}
-#endif /* CONFIG_PM */
-
-static int snd_cs4231_free(struct snd_cs4231 *chip)
-{
- release_and_free_resource(chip->res_port);
- release_and_free_resource(chip->res_cport);
- if (chip->irq >= 0) {
- disable_irq(chip->irq);
- if (!(chip->hwshare & CS4231_HWSHARE_IRQ))
- free_irq(chip->irq, (void *) chip);
- }
- if (!(chip->hwshare & CS4231_HWSHARE_DMA1) && chip->dma1 >= 0) {
- snd_dma_disable(chip->dma1);
- free_dma(chip->dma1);
- }
- if (!(chip->hwshare & CS4231_HWSHARE_DMA2) && chip->dma2 >= 0 && chip->dma2 != chip->dma1) {
- snd_dma_disable(chip->dma2);
- free_dma(chip->dma2);
- }
- if (chip->timer)
- snd_device_free(chip->card, chip->timer);
- kfree(chip);
- return 0;
-}
-
-static int snd_cs4231_dev_free(struct snd_device *device)
-{
- struct snd_cs4231 *chip = device->device_data;
- return snd_cs4231_free(chip);
-}
-
-const char *snd_cs4231_chip_id(struct snd_cs4231 *chip)
-{
- switch (chip->hardware) {
- case CS4231_HW_CS4231: return "CS4231";
- case CS4231_HW_CS4231A: return "CS4231A";
- case CS4231_HW_CS4232: return "CS4232";
- case CS4231_HW_CS4232A: return "CS4232A";
- case CS4231_HW_CS4235: return "CS4235";
- case CS4231_HW_CS4236: return "CS4236";
- case CS4231_HW_CS4236B: return "CS4236B";
- case CS4231_HW_CS4237B: return "CS4237B";
- case CS4231_HW_CS4238B: return "CS4238B";
- case CS4231_HW_CS4239: return "CS4239";
- case CS4231_HW_INTERWAVE: return "AMD InterWave";
- case CS4231_HW_OPL3SA2: return chip->card->shortname;
- case CS4231_HW_AD1845: return "AD1845";
- case CS4231_HW_OPTI93X: return "OPTi 93x";
- default: return "???";
- }
-}
-
-static int snd_cs4231_new(struct snd_card *card,
- unsigned short hardware,
- unsigned short hwshare,
- struct snd_cs4231 ** rchip)
-{
- struct snd_cs4231 *chip;
-
- *rchip = NULL;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL)
- return -ENOMEM;
- chip->hardware = hardware;
- chip->hwshare = hwshare;
-
- spin_lock_init(&chip->reg_lock);
- mutex_init(&chip->mce_mutex);
- mutex_init(&chip->open_mutex);
- chip->card = card;
- chip->rate_constraint = snd_cs4231_xrate;
- chip->set_playback_format = snd_cs4231_playback_format;
- chip->set_capture_format = snd_cs4231_capture_format;
- if (chip->hardware == CS4231_HW_OPTI93X)
- memcpy(&chip->image, &snd_opti93x_original_image,
- sizeof(snd_opti93x_original_image));
- else
- memcpy(&chip->image, &snd_cs4231_original_image,
- sizeof(snd_cs4231_original_image));
-
- *rchip = chip;
- return 0;
-}
-
-int snd_cs4231_create(struct snd_card *card,
- unsigned long port,
- unsigned long cport,
- int irq, int dma1, int dma2,
- unsigned short hardware,
- unsigned short hwshare,
- struct snd_cs4231 ** rchip)
-{
- static struct snd_device_ops ops = {
- .dev_free = snd_cs4231_dev_free,
- };
- struct snd_cs4231 *chip;
- int err;
-
- err = snd_cs4231_new(card, hardware, hwshare, &chip);
- if (err < 0)
- return err;
-
- chip->irq = -1;
- chip->dma1 = -1;
- chip->dma2 = -1;
-
- if ((chip->res_port = request_region(port, 4, "CS4231")) == NULL) {
- snd_printk(KERN_ERR "cs4231: can't grab port 0x%lx\n", port);
- snd_cs4231_free(chip);
- return -EBUSY;
- }
- chip->port = port;
- if ((long)cport >= 0 && (chip->res_cport = request_region(cport, 8, "CS4232 Control")) == NULL) {
- snd_printk(KERN_ERR "cs4231: can't grab control port 0x%lx\n", cport);
- snd_cs4231_free(chip);
- return -ENODEV;
- }
- chip->cport = cport;
- if (!(hwshare & CS4231_HWSHARE_IRQ) && request_irq(irq, snd_cs4231_interrupt, IRQF_DISABLED, "CS4231", (void *) chip)) {
- snd_printk(KERN_ERR "cs4231: can't grab IRQ %d\n", irq);
- snd_cs4231_free(chip);
- return -EBUSY;
- }
- chip->irq = irq;
- if (!(hwshare & CS4231_HWSHARE_DMA1) && request_dma(dma1, "CS4231 - 1")) {
- snd_printk(KERN_ERR "cs4231: can't grab DMA1 %d\n", dma1);
- snd_cs4231_free(chip);
- return -EBUSY;
- }
- chip->dma1 = dma1;
- if (!(hwshare & CS4231_HWSHARE_DMA2) && dma1 != dma2 && dma2 >= 0 && request_dma(dma2, "CS4231 - 2")) {
- snd_printk(KERN_ERR "cs4231: can't grab DMA2 %d\n", dma2);
- snd_cs4231_free(chip);
- return -EBUSY;
- }
- if (dma1 == dma2 || dma2 < 0) {
- chip->single_dma = 1;
- chip->dma2 = chip->dma1;
- } else
- chip->dma2 = dma2;
-
- /* global setup */
- if (snd_cs4231_probe(chip) < 0) {
- snd_cs4231_free(chip);
- return -ENODEV;
- }
- snd_cs4231_init(chip);
-
-#if 0
- if (chip->hardware & CS4231_HW_CS4232_MASK) {
- if (chip->res_cport == NULL)
- snd_printk("CS4232 control port features are not accessible\n");
- }
-#endif
-
- /* Register device */
- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
- snd_cs4231_free(chip);
- return err;
- }
-
-#ifdef CONFIG_PM
- /* Power Management */
- chip->suspend = snd_cs4231_suspend;
- chip->resume = snd_cs4231_resume;
-#endif
-
- *rchip = chip;
- return 0;
-}
-
-static struct snd_pcm_ops snd_cs4231_playback_ops = {
- .open = snd_cs4231_playback_open,
- .close = snd_cs4231_playback_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_cs4231_playback_hw_params,
- .hw_free = snd_cs4231_playback_hw_free,
- .prepare = snd_cs4231_playback_prepare,
- .trigger = snd_cs4231_trigger,
- .pointer = snd_cs4231_playback_pointer,
-};
-
-static struct snd_pcm_ops snd_cs4231_capture_ops = {
- .open = snd_cs4231_capture_open,
- .close = snd_cs4231_capture_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = snd_cs4231_capture_hw_params,
- .hw_free = snd_cs4231_capture_hw_free,
- .prepare = snd_cs4231_capture_prepare,
- .trigger = snd_cs4231_trigger,
- .pointer = snd_cs4231_capture_pointer,
-};
-
-int snd_cs4231_pcm(struct snd_cs4231 *chip, int device, struct snd_pcm **rpcm)
-{
- struct snd_pcm *pcm;
- int err;
-
- if ((err = snd_pcm_new(chip->card, "CS4231", device, 1, 1, &pcm)) < 0)
- return err;
-
- spin_lock_init(&chip->reg_lock);
- mutex_init(&chip->mce_mutex);
- mutex_init(&chip->open_mutex);
-
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs4231_playback_ops);
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4231_capture_ops);
-
- /* global setup */
- pcm->private_data = chip;
- pcm->info_flags = 0;
- if (chip->single_dma)
- pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
- if (chip->hardware != CS4231_HW_INTERWAVE)
- pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
- strcpy(pcm->name, snd_cs4231_chip_id(chip));
-
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_isa_data(),
- 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
-
- chip->pcm = pcm;
- if (rpcm)
- *rpcm = pcm;
- return 0;
-}
-
-static void snd_cs4231_timer_free(struct snd_timer *timer)
-{
- struct snd_cs4231 *chip = timer->private_data;
- chip->timer = NULL;
-}
-
-int snd_cs4231_timer(struct snd_cs4231 *chip, int device, struct snd_timer **rtimer)
-{
- struct snd_timer *timer;
- struct snd_timer_id tid;
- int err;
-
- /* Timer initialization */
- tid.dev_class = SNDRV_TIMER_CLASS_CARD;
- tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
- tid.card = chip->card->number;
- tid.device = device;
- tid.subdevice = 0;
- if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0)
- return err;
- strcpy(timer->name, snd_cs4231_chip_id(chip));
- timer->private_data = chip;
- timer->private_free = snd_cs4231_timer_free;
- timer->hw = snd_cs4231_timer_table;
- chip->timer = timer;
- if (rtimer)
- *rtimer = timer;
- return 0;
-}
-
-/*
- * MIXER part
- */
-
-static int snd_cs4231_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- static char *texts[4] = {
- "Line", "Aux", "Mic", "Mix"
- };
- static char *opl3sa_texts[4] = {
- "Line", "CD", "Mic", "Mix"
- };
- static char *gusmax_texts[4] = {
- "Line", "Synth", "Mic", "Mix"
- };
- char **ptexts = texts;
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
-
- snd_assert(chip->card != NULL, return -EINVAL);
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 2;
- uinfo->value.enumerated.items = 4;
- if (uinfo->value.enumerated.item > 3)
- uinfo->value.enumerated.item = 3;
- if (!strcmp(chip->card->driver, "GUS MAX"))
- ptexts = gusmax_texts;
- switch (chip->hardware) {
- case CS4231_HW_INTERWAVE: ptexts = gusmax_texts; break;
- case CS4231_HW_OPL3SA2: ptexts = opl3sa_texts; break;
- }
- strcpy(uinfo->value.enumerated.name, ptexts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int snd_cs4231_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
-
- spin_lock_irqsave(&chip->reg_lock, flags);
- ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6;
- ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return 0;
-}
-
-static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
- unsigned short left, right;
- int change;
-
- if (ucontrol->value.enumerated.item[0] > 3 ||
- ucontrol->value.enumerated.item[1] > 3)
- return -EINVAL;
- left = ucontrol->value.enumerated.item[0] << 6;
- right = ucontrol->value.enumerated.item[1] << 6;
- spin_lock_irqsave(&chip->reg_lock, flags);
- left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left;
- right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right;
- change = left != chip->image[CS4231_LEFT_INPUT] ||
- right != chip->image[CS4231_RIGHT_INPUT];
- snd_cs4231_out(chip, CS4231_LEFT_INPUT, left);
- snd_cs4231_out(chip, CS4231_RIGHT_INPUT, right);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return change;
-}
-
-int snd_cs4231_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- int mask = (kcontrol->private_value >> 16) & 0xff;
-
- 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 = mask;
- return 0;
-}
-
-int snd_cs4231_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
- int reg = kcontrol->private_value & 0xff;
- int shift = (kcontrol->private_value >> 8) & 0xff;
- int mask = (kcontrol->private_value >> 16) & 0xff;
- int invert = (kcontrol->private_value >> 24) & 0xff;
-
- spin_lock_irqsave(&chip->reg_lock, flags);
- ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- if (invert)
- ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
- return 0;
-}
-
-int snd_cs4231_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
- int reg = kcontrol->private_value & 0xff;
- int shift = (kcontrol->private_value >> 8) & 0xff;
- int mask = (kcontrol->private_value >> 16) & 0xff;
- int invert = (kcontrol->private_value >> 24) & 0xff;
- int change;
- unsigned short val;
-
- val = (ucontrol->value.integer.value[0] & mask);
- if (invert)
- val = mask - val;
- val <<= shift;
- spin_lock_irqsave(&chip->reg_lock, flags);
- val = (chip->image[reg] & ~(mask << shift)) | val;
- change = val != chip->image[reg];
- snd_cs4231_out(chip, reg, val);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return change;
-}
-
-int snd_cs4231_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- int mask = (kcontrol->private_value >> 24) & 0xff;
-
- 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 = mask;
- return 0;
-}
-
-int snd_cs4231_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
- int left_reg = kcontrol->private_value & 0xff;
- int right_reg = (kcontrol->private_value >> 8) & 0xff;
- int shift_left = (kcontrol->private_value >> 16) & 0x07;
- int shift_right = (kcontrol->private_value >> 19) & 0x07;
- int mask = (kcontrol->private_value >> 24) & 0xff;
- int invert = (kcontrol->private_value >> 22) & 1;
-
- spin_lock_irqsave(&chip->reg_lock, flags);
- ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
- ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- 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;
-}
-
-int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
- int left_reg = kcontrol->private_value & 0xff;
- int right_reg = (kcontrol->private_value >> 8) & 0xff;
- int shift_left = (kcontrol->private_value >> 16) & 0x07;
- int shift_right = (kcontrol->private_value >> 19) & 0x07;
- int mask = (kcontrol->private_value >> 24) & 0xff;
- int invert = (kcontrol->private_value >> 22) & 1;
- int change;
- unsigned short val1, val2;
-
- 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_irqsave(&chip->reg_lock, flags);
- val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
- val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
- change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg];
- snd_cs4231_out(chip, left_reg, val1);
- snd_cs4231_out(chip, right_reg, val2);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return change;
-}
-
-static struct snd_kcontrol_new snd_cs4231_controls[] = {
-CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
-CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
-CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
-CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
-CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
-CS4231_SINGLE("Mono Playback Switch", 0, CS4231_MONO_CTRL, 7, 1, 1),
-CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
-CS4231_SINGLE("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, 6, 1, 1),
-CS4231_SINGLE("Mono Output Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0),
-CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .info = snd_cs4231_info_mux,
- .get = snd_cs4231_get_mux,
- .put = snd_cs4231_put_mux,
-},
-CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
-CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
-CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1)
-};
-
-static struct snd_kcontrol_new snd_opti93x_controls[] = {
-CS4231_DOUBLE("Master Playback Switch", 0,
- OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
-CS4231_DOUBLE("Master Playback Volume", 0,
- OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1),
-CS4231_DOUBLE("PCM Playback Switch", 0,
- CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("PCM Playback Volume", 0,
- CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1),
-CS4231_DOUBLE("FM Playback Switch", 0,
- CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("FM Playback Volume", 0,
- CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1),
-CS4231_DOUBLE("Line Playback Switch", 0,
- CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
-CS4231_DOUBLE("Line Playback Volume", 0,
- CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1),
-CS4231_DOUBLE("Mic Playback Switch", 0,
- OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("Mic Playback Volume", 0,
- OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1),
-CS4231_DOUBLE("Mic Boost", 0,
- CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
-CS4231_DOUBLE("CD Playback Switch", 0,
- CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("CD Playback Volume", 0,
- CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1),
-CS4231_DOUBLE("Aux Playback Switch", 0,
- OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("Aux Playback Volume", 0,
- OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1),
-CS4231_DOUBLE("Capture Volume", 0,
- CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .info = snd_cs4231_info_mux,
- .get = snd_cs4231_get_mux,
- .put = snd_cs4231_put_mux,
-}
-};
-
-int snd_cs4231_mixer(struct snd_cs4231 *chip)
-{
- struct snd_card *card;
- unsigned int idx;
- int err;
-
- snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL);
-
- card = chip->card;
-
- strcpy(card->mixername, chip->pcm->name);
-
- if (chip->hardware == CS4231_HW_OPTI93X)
- for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
- err = snd_ctl_add(card,
- snd_ctl_new1(&snd_opti93x_controls[idx],
- chip));
- if (err < 0)
- return err;
- }
- else
- for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {
- err = snd_ctl_add(card,
- snd_ctl_new1(&snd_cs4231_controls[idx],
- chip));
- if (err < 0)
- return err;
- }
- return 0;
-}
-
-EXPORT_SYMBOL(snd_cs4231_out);
-EXPORT_SYMBOL(snd_cs4231_in);
-EXPORT_SYMBOL(snd_cs4236_ext_out);
-EXPORT_SYMBOL(snd_cs4236_ext_in);
-EXPORT_SYMBOL(snd_cs4231_mce_up);
-EXPORT_SYMBOL(snd_cs4231_mce_down);
-EXPORT_SYMBOL(snd_cs4231_overrange);
-EXPORT_SYMBOL(snd_cs4231_interrupt);
-EXPORT_SYMBOL(snd_cs4231_chip_id);
-EXPORT_SYMBOL(snd_cs4231_create);
-EXPORT_SYMBOL(snd_cs4231_pcm);
-EXPORT_SYMBOL(snd_cs4231_mixer);
-EXPORT_SYMBOL(snd_cs4231_timer);
-EXPORT_SYMBOL(snd_cs4231_info_single);
-EXPORT_SYMBOL(snd_cs4231_get_single);
-EXPORT_SYMBOL(snd_cs4231_put_single);
-EXPORT_SYMBOL(snd_cs4231_info_double);
-EXPORT_SYMBOL(snd_cs4231_get_double);
-EXPORT_SYMBOL(snd_cs4231_put_double);
-
-/*
- * INIT part
- */
-
-static int __init alsa_cs4231_init(void)
-{
- return 0;
-}
-
-static void __exit alsa_cs4231_exit(void)
-{
-}
-
-module_init(alsa_cs4231_init)
-module_exit(alsa_cs4231_exit)
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 4d4b8ddc26ba..91f9c15d3e30 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -26,7 +26,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -134,7 +134,7 @@ static int pnp_registered;
#endif /* CONFIG_PNP */
struct snd_card_cs4236 {
- struct snd_cs4231 *chip;
+ struct snd_wss *chip;
struct resource *res_sb_port;
#ifdef CONFIG_PNP
struct pnp_dev *wss;
@@ -239,6 +239,8 @@ static struct pnp_card_device_id snd_cs423x_pnpids[] = {
{ .id = "CSC9836", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
/* Gallant SC-70P */
{ .id = "CSC9837", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
+ /* Techmakers MF-4236PW */
+ { .id = "CSCa736", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
/* TerraTec AudioSystem EWS64XL - CS4236B */
{ .id = "CSCa836", .devs = { { "CSCa800" }, { "CSCa810" }, { "CSCa803" } } },
/* TerraTec AudioSystem EWS64XL - CS4236B */
@@ -396,7 +398,7 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
{
struct snd_card_cs4236 *acard;
struct snd_pcm *pcm;
- struct snd_cs4231 *chip;
+ struct snd_wss *chip;
struct snd_opl3 *opl3;
int err;
@@ -408,41 +410,37 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
}
#ifdef CS4232
- if ((err = snd_cs4231_create(card,
- port[dev],
- cport[dev],
- irq[dev],
- dma1[dev],
- dma2[dev],
- CS4231_HW_DETECT,
- 0,
- &chip)) < 0)
+ err = snd_wss_create(card, port[dev], cport[dev],
+ irq[dev],
+ dma1[dev], dma2[dev],
+ WSS_HW_DETECT, 0, &chip);
+ if (err < 0)
return err;
acard->chip = chip;
- if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0)
+ err = snd_wss_pcm(chip, 0, &pcm);
+ if (err < 0)
return err;
- if ((err = snd_cs4231_mixer(chip)) < 0)
+ err = snd_wss_mixer(chip);
+ if (err < 0)
return err;
#else /* CS4236 */
- if ((err = snd_cs4236_create(card,
- port[dev],
- cport[dev],
- irq[dev],
- dma1[dev],
- dma2[dev],
- CS4231_HW_DETECT,
- 0,
- &chip)) < 0)
+ err = snd_cs4236_create(card,
+ port[dev], cport[dev],
+ irq[dev], dma1[dev], dma2[dev],
+ WSS_HW_DETECT, 0, &chip);
+ if (err < 0)
return err;
acard->chip = chip;
- if ((err = snd_cs4236_pcm(chip, 0, &pcm)) < 0)
+ err = snd_cs4236_pcm(chip, 0, &pcm);
+ if (err < 0)
return err;
- if ((err = snd_cs4236_mixer(chip)) < 0)
+ err = snd_cs4236_mixer(chip);
+ if (err < 0)
return err;
#endif
strcpy(card->driver, pcm->name);
@@ -455,7 +453,8 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
if (dma2[dev] >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
- if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0)
+ err = snd_wss_timer(chip, 0, NULL);
+ if (err < 0)
return err;
if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c
index de71910401ea..6a85fdc53b60 100644
--- a/sound/isa/cs423x/cs4236_lib.c
+++ b/sound/isa/cs423x/cs4236_lib.c
@@ -85,7 +85,7 @@
#include
#include
#include
-#include
+#include
#include
MODULE_AUTHOR("Jaroslav Kysela ");
@@ -121,13 +121,14 @@ static unsigned char snd_cs4236_ext_map[18] = {
*
*/
-static void snd_cs4236_ctrl_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val)
+static void snd_cs4236_ctrl_out(struct snd_wss *chip,
+ unsigned char reg, unsigned char val)
{
outb(reg, chip->cport + 3);
outb(chip->cimage[reg] = val, chip->cport + 4);
}
-static unsigned char snd_cs4236_ctrl_in(struct snd_cs4231 *chip, unsigned char reg)
+static unsigned char snd_cs4236_ctrl_in(struct snd_wss *chip, unsigned char reg)
{
outb(reg, chip->cport + 3);
return inb(chip->cport + 4);
@@ -180,44 +181,52 @@ static unsigned char divisor_to_rate_register(unsigned int divisor)
}
}
-static void snd_cs4236_playback_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, unsigned char pdfr)
+static void snd_cs4236_playback_format(struct snd_wss *chip,
+ struct snd_pcm_hw_params *params,
+ unsigned char pdfr)
{
unsigned long flags;
unsigned char rate = divisor_to_rate_register(params->rate_den);
spin_lock_irqsave(&chip->reg_lock, flags);
/* set fast playback format change and clean playback FIFO */
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x10);
- snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, pdfr & 0xf0);
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] & ~0x10);
+ snd_wss_out(chip, CS4231_ALT_FEATURE_1,
+ chip->image[CS4231_ALT_FEATURE_1] | 0x10);
+ snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr & 0xf0);
+ snd_wss_out(chip, CS4231_ALT_FEATURE_1,
+ chip->image[CS4231_ALT_FEATURE_1] & ~0x10);
snd_cs4236_ext_out(chip, CS4236_DAC_RATE, rate);
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static void snd_cs4236_capture_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, unsigned char cdfr)
+static void snd_cs4236_capture_format(struct snd_wss *chip,
+ struct snd_pcm_hw_params *params,
+ unsigned char cdfr)
{
unsigned long flags;
unsigned char rate = divisor_to_rate_register(params->rate_den);
spin_lock_irqsave(&chip->reg_lock, flags);
/* set fast capture format change and clean capture FIFO */
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x20);
- snd_cs4231_out(chip, CS4231_REC_FORMAT, cdfr & 0xf0);
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] & ~0x20);
+ snd_wss_out(chip, CS4231_ALT_FEATURE_1,
+ chip->image[CS4231_ALT_FEATURE_1] | 0x20);
+ snd_wss_out(chip, CS4231_REC_FORMAT, cdfr & 0xf0);
+ snd_wss_out(chip, CS4231_ALT_FEATURE_1,
+ chip->image[CS4231_ALT_FEATURE_1] & ~0x20);
snd_cs4236_ext_out(chip, CS4236_ADC_RATE, rate);
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
#ifdef CONFIG_PM
-static void snd_cs4236_suspend(struct snd_cs4231 *chip)
+static void snd_cs4236_suspend(struct snd_wss *chip)
{
int reg;
unsigned long flags;
spin_lock_irqsave(&chip->reg_lock, flags);
for (reg = 0; reg < 32; reg++)
- chip->image[reg] = snd_cs4231_in(chip, reg);
+ chip->image[reg] = snd_wss_in(chip, reg);
for (reg = 0; reg < 18; reg++)
chip->eimage[reg] = snd_cs4236_ext_in(chip, CS4236_I23VAL(reg));
for (reg = 2; reg < 9; reg++)
@@ -225,12 +234,12 @@ static void snd_cs4236_suspend(struct snd_cs4231 *chip)
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static void snd_cs4236_resume(struct snd_cs4231 *chip)
+static void snd_cs4236_resume(struct snd_wss *chip)
{
int reg;
unsigned long flags;
- snd_cs4231_mce_up(chip);
+ snd_wss_mce_up(chip);
spin_lock_irqsave(&chip->reg_lock, flags);
for (reg = 0; reg < 32; reg++) {
switch (reg) {
@@ -240,7 +249,7 @@ static void snd_cs4236_resume(struct snd_cs4231 *chip)
case 29: /* why? CS4235 - master right */
break;
default:
- snd_cs4231_out(chip, reg, chip->image[reg]);
+ snd_wss_out(chip, reg, chip->image[reg]);
break;
}
}
@@ -255,7 +264,7 @@ static void snd_cs4236_resume(struct snd_cs4231 *chip)
}
}
spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_cs4231_mce_down(chip);
+ snd_wss_mce_down(chip);
}
#endif /* CONFIG_PM */
@@ -266,24 +275,26 @@ int snd_cs4236_create(struct snd_card *card,
int irq, int dma1, int dma2,
unsigned short hardware,
unsigned short hwshare,
- struct snd_cs4231 ** rchip)
+ struct snd_wss **rchip)
{
- struct snd_cs4231 *chip;
+ struct snd_wss *chip;
unsigned char ver1, ver2;
unsigned int reg;
int err;
*rchip = NULL;
- if (hardware == CS4231_HW_DETECT)
- hardware = CS4231_HW_DETECT3;
+ if (hardware == WSS_HW_DETECT)
+ hardware = WSS_HW_DETECT3;
if (cport < 0x100) {
snd_printk("please, specify control port for CS4236+ chips\n");
return -ENODEV;
}
- if ((err = snd_cs4231_create(card, port, cport, irq, dma1, dma2, hardware, hwshare, &chip)) < 0)
+ err = snd_wss_create(card, port, cport,
+ irq, dma1, dma2, hardware, hwshare, &chip);
+ if (err < 0)
return err;
- if (!(chip->hardware & CS4231_HW_CS4236B_MASK)) {
+ if (!(chip->hardware & WSS_HW_CS4236B_MASK)) {
snd_printk("CS4236+: MODE3 and extended registers not available, hardware=0x%x\n",chip->hardware);
snd_device_free(card, chip);
return -ENODEV;
@@ -330,20 +341,20 @@ int snd_cs4236_create(struct snd_card *card,
snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), snd_cs4236_ext_map[reg]);
/* initialize compatible but more featured registers */
- snd_cs4231_out(chip, CS4231_LEFT_INPUT, 0x40);
- snd_cs4231_out(chip, CS4231_RIGHT_INPUT, 0x40);
- snd_cs4231_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff);
- snd_cs4231_out(chip, CS4231_AUX1_RIGHT_INPUT, 0xff);
- snd_cs4231_out(chip, CS4231_AUX2_LEFT_INPUT, 0xdf);
- snd_cs4231_out(chip, CS4231_AUX2_RIGHT_INPUT, 0xdf);
- snd_cs4231_out(chip, CS4231_RIGHT_LINE_IN, 0xff);
- snd_cs4231_out(chip, CS4231_LEFT_LINE_IN, 0xff);
- snd_cs4231_out(chip, CS4231_RIGHT_LINE_IN, 0xff);
+ snd_wss_out(chip, CS4231_LEFT_INPUT, 0x40);
+ snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x40);
+ snd_wss_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff);
+ snd_wss_out(chip, CS4231_AUX1_RIGHT_INPUT, 0xff);
+ snd_wss_out(chip, CS4231_AUX2_LEFT_INPUT, 0xdf);
+ snd_wss_out(chip, CS4231_AUX2_RIGHT_INPUT, 0xdf);
+ snd_wss_out(chip, CS4231_RIGHT_LINE_IN, 0xff);
+ snd_wss_out(chip, CS4231_LEFT_LINE_IN, 0xff);
+ snd_wss_out(chip, CS4231_RIGHT_LINE_IN, 0xff);
switch (chip->hardware) {
- case CS4231_HW_CS4235:
- case CS4231_HW_CS4239:
- snd_cs4231_out(chip, CS4235_LEFT_MASTER, 0xff);
- snd_cs4231_out(chip, CS4235_RIGHT_MASTER, 0xff);
+ case WSS_HW_CS4235:
+ case WSS_HW_CS4239:
+ snd_wss_out(chip, CS4235_LEFT_MASTER, 0xff);
+ snd_wss_out(chip, CS4235_RIGHT_MASTER, 0xff);
break;
}
@@ -351,12 +362,13 @@ int snd_cs4236_create(struct snd_card *card,
return 0;
}
-int snd_cs4236_pcm(struct snd_cs4231 *chip, int device, struct snd_pcm **rpcm)
+int snd_cs4236_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
- if ((err = snd_cs4231_pcm(chip, device, &pcm)) < 0)
+ err = snd_wss_pcm(chip, device, &pcm);
+ if (err < 0)
return err;
pcm->info_flags &= ~SNDRV_PCM_INFO_JOINT_DUPLEX;
if (rpcm)
@@ -387,7 +399,7 @@ static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_
static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -404,7 +416,7 @@ static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e
static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -433,7 +445,7 @@ static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e
static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -450,7 +462,7 @@ static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_
static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -490,7 +502,7 @@ static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_
static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -512,7 +524,7 @@ static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e
static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -555,7 +567,7 @@ static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e
static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -577,7 +589,7 @@ static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_
static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -600,7 +612,7 @@ static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_
val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2;
change = val1 != chip->image[left_reg] || val2 != chip->eimage[CS4236_REG(right_reg)];
- snd_cs4231_out(chip, left_reg, val1);
+ snd_wss_out(chip, left_reg, val1);
snd_cs4236_ext_out(chip, right_reg, val2);
spin_unlock_irqrestore(&chip->reg_lock, flags);
return change;
@@ -619,7 +631,7 @@ static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol)
static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -631,7 +643,7 @@ static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct s
static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned short val1, val2;
@@ -678,7 +690,7 @@ static inline int snd_cs4235_mixer_output_accu_set_volume(int vol)
static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -690,7 +702,7 @@ static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_
static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned short val1, val2;
@@ -701,108 +713,160 @@ static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_
val1 = (chip->image[CS4235_LEFT_MASTER] & ~(3 << 5)) | val1;
val2 = (chip->image[CS4235_RIGHT_MASTER] & ~(3 << 5)) | val2;
change = val1 != chip->image[CS4235_LEFT_MASTER] || val2 != chip->image[CS4235_RIGHT_MASTER];
- snd_cs4231_out(chip, CS4235_LEFT_MASTER, val1);
- snd_cs4231_out(chip, CS4235_RIGHT_MASTER, val2);
+ snd_wss_out(chip, CS4235_LEFT_MASTER, val1);
+ snd_wss_out(chip, CS4235_RIGHT_MASTER, val2);
spin_unlock_irqrestore(&chip->reg_lock, flags);
return change;
}
static struct snd_kcontrol_new snd_cs4236_controls[] = {
-CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
-CS4236_DOUBLE("Master Digital Capture Switch", 0, CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
+CS4236_DOUBLE("Master Digital Playback Switch", 0,
+ CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
+CS4236_DOUBLE("Master Digital Capture Switch", 0,
+ CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
CS4236_MASTER_DIGITAL("Master Digital Volume", 0),
-CS4236_DOUBLE("Capture Boost Volume", 0, CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1),
+CS4236_DOUBLE("Capture Boost Volume", 0,
+ CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1),
-CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
+WSS_DOUBLE("PCM Playback Switch", 0,
+ CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
+WSS_DOUBLE("PCM Playback Volume", 0,
+ CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
-CS4236_DOUBLE("DSP Playback Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
-CS4236_DOUBLE("DSP Playback Volume", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1),
+CS4236_DOUBLE("DSP Playback Switch", 0,
+ CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
+CS4236_DOUBLE("DSP Playback Volume", 0,
+ CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1),
-CS4236_DOUBLE("FM Playback Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
-CS4236_DOUBLE("FM Playback Volume", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1),
+CS4236_DOUBLE("FM Playback Switch", 0,
+ CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
+CS4236_DOUBLE("FM Playback Volume", 0,
+ CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1),
-CS4236_DOUBLE("Wavetable Playback Switch", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
-CS4236_DOUBLE("Wavetable Playback Volume", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1),
+CS4236_DOUBLE("Wavetable Playback Switch", 0,
+ CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
+CS4236_DOUBLE("Wavetable Playback Volume", 0,
+ CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1),
-CS4231_DOUBLE("Synth Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
-CS4231_DOUBLE("Synth Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
-CS4231_DOUBLE("Synth Capture Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
-CS4231_DOUBLE("Synth Capture Bypass", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1),
+WSS_DOUBLE("Synth Playback Switch", 0,
+ CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
+WSS_DOUBLE("Synth Volume", 0,
+ CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
+WSS_DOUBLE("Synth Capture Switch", 0,
+ CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
+WSS_DOUBLE("Synth Capture Bypass", 0,
+ CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1),
-CS4236_DOUBLE("Mic Playback Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
-CS4236_DOUBLE("Mic Capture Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
+CS4236_DOUBLE("Mic Playback Switch", 0,
+ CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
+CS4236_DOUBLE("Mic Capture Switch", 0,
+ CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
CS4236_DOUBLE("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 0, 0, 31, 1),
-CS4236_DOUBLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0),
+CS4236_DOUBLE("Mic Playback Boost", 0,
+ CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0),
-CS4231_DOUBLE("Line Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("Line Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
-CS4231_DOUBLE("Line Capture Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
-CS4231_DOUBLE("Line Capture Bypass", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1),
+WSS_DOUBLE("Line Playback Switch", 0,
+ CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
+WSS_DOUBLE("Line Volume", 0,
+ CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
+WSS_DOUBLE("Line Capture Switch", 0,
+ CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
+WSS_DOUBLE("Line Capture Bypass", 0,
+ CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1),
-CS4231_DOUBLE("CD Playback Switch", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("CD Volume", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
-CS4231_DOUBLE("CD Capture Switch", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
+WSS_DOUBLE("CD Playback Switch", 0,
+ CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
+WSS_DOUBLE("CD Volume", 0,
+ CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
+WSS_DOUBLE("CD Capture Switch", 0,
+ CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
-CS4236_DOUBLE1("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
-CS4236_DOUBLE1("Mono Playback Switch", 0, CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
-CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
-CS4231_SINGLE("Mono Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0),
+CS4236_DOUBLE1("Mono Output Playback Switch", 0,
+ CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
+CS4236_DOUBLE1("Mono Playback Switch", 0,
+ CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
+WSS_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
+WSS_SINGLE("Mono Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0),
-CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
-CS4231_DOUBLE("Analog Loopback Capture Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
+WSS_DOUBLE("Capture Volume", 0,
+ CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
+WSS_DOUBLE("Analog Loopback Capture Switch", 0,
+ CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
-CS4231_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
-CS4236_DOUBLE1("Digital Loopback Playback Volume", 0, CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1)
+WSS_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
+CS4236_DOUBLE1("Digital Loopback Playback Volume", 0,
+ CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1)
};
static struct snd_kcontrol_new snd_cs4235_controls[] = {
-CS4231_DOUBLE("Master Switch", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
-CS4231_DOUBLE("Master Volume", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1),
+WSS_DOUBLE("Master Switch", 0,
+ CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
+WSS_DOUBLE("Master Volume", 0,
+ CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1),
CS4235_OUTPUT_ACCU("Playback Volume", 0),
-CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
-CS4236_DOUBLE("Master Digital Capture Switch", 0, CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
+CS4236_DOUBLE("Master Digital Playback Switch", 0,
+ CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
+CS4236_DOUBLE("Master Digital Capture Switch", 0,
+ CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
CS4236_MASTER_DIGITAL("Master Digital Volume", 0),
-CS4231_DOUBLE("Master Digital Playback Switch", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
-CS4231_DOUBLE("Master Digital Capture Switch", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
-CS4231_DOUBLE("Master Digital Volume", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
+WSS_DOUBLE("Master Digital Playback Switch", 1,
+ CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
+WSS_DOUBLE("Master Digital Capture Switch", 1,
+ CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
+WSS_DOUBLE("Master Digital Volume", 1,
+ CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
-CS4236_DOUBLE("Capture Volume", 0, CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1),
+CS4236_DOUBLE("Capture Volume", 0,
+ CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1),
-CS4231_DOUBLE("PCM Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("PCM Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
+WSS_DOUBLE("PCM Switch", 0,
+ CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
+WSS_DOUBLE("PCM Volume", 0,
+ CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
CS4236_DOUBLE("FM Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
-CS4236_DOUBLE("Wavetable Switch", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
+CS4236_DOUBLE("Wavetable Switch", 0,
+ CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
-CS4236_DOUBLE("Mic Capture Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
-CS4236_DOUBLE("Mic Playback Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
+CS4236_DOUBLE("Mic Capture Switch", 0,
+ CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
+CS4236_DOUBLE("Mic Playback Switch", 0,
+ CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
CS4236_SINGLE("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1),
CS4236_SINGLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, 5, 1, 0),
-CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("Aux Capture Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
-CS4231_DOUBLE("Aux Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
+WSS_DOUBLE("Aux Playback Switch", 0,
+ CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
+WSS_DOUBLE("Aux Capture Switch", 0,
+ CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
+WSS_DOUBLE("Aux Volume", 0,
+ CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
-CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("Aux Capture Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
-CS4231_DOUBLE("Aux Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
+WSS_DOUBLE("Aux Playback Switch", 1,
+ CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
+WSS_DOUBLE("Aux Capture Switch", 1,
+ CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
+WSS_DOUBLE("Aux Volume", 1,
+ CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
-CS4236_DOUBLE1("Master Mono Switch", 0, CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
+CS4236_DOUBLE1("Master Mono Switch", 0,
+ CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
-CS4236_DOUBLE1("Mono Switch", 0, CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
-CS4231_SINGLE("Mono Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
+CS4236_DOUBLE1("Mono Switch", 0,
+ CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
+WSS_SINGLE("Mono Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
-CS4231_DOUBLE("Analog Loopback Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
+WSS_DOUBLE("Analog Loopback Switch", 0,
+ CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
};
#define CS4236_IEC958_ENABLE(xname, xindex) \
@@ -813,14 +877,14 @@ CS4231_DOUBLE("Analog Loopback Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT
static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&chip->reg_lock, flags);
ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0;
#if 0
printk("get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
- snd_cs4231_in(chip, CS4231_ALT_FEATURE_1),
+ snd_wss_in(chip, CS4231_ALT_FEATURE_1),
snd_cs4236_ctrl_in(chip, 3),
snd_cs4236_ctrl_in(chip, 4),
snd_cs4236_ctrl_in(chip, 5),
@@ -833,7 +897,7 @@ static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct sn
static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned short enable, val;
@@ -841,23 +905,23 @@ static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct sn
enable = ucontrol->value.integer.value[0] & 1;
mutex_lock(&chip->mce_mutex);
- snd_cs4231_mce_up(chip);
+ snd_wss_mce_up(chip);
spin_lock_irqsave(&chip->reg_lock, flags);
val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1);
change = val != chip->image[CS4231_ALT_FEATURE_1];
- snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, val);
+ snd_wss_out(chip, CS4231_ALT_FEATURE_1, val);
val = snd_cs4236_ctrl_in(chip, 4) | 0xc0;
snd_cs4236_ctrl_out(chip, 4, val);
udelay(100);
val &= ~0x40;
snd_cs4236_ctrl_out(chip, 4, val);
spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_cs4231_mce_down(chip);
+ snd_wss_mce_down(chip);
mutex_unlock(&chip->mce_mutex);
#if 0
printk("set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
- snd_cs4231_in(chip, CS4231_ALT_FEATURE_1),
+ snd_wss_in(chip, CS4231_ALT_FEATURE_1),
snd_cs4236_ctrl_in(chip, 3),
snd_cs4236_ctrl_in(chip, 4),
snd_cs4236_ctrl_in(chip, 5),
@@ -896,19 +960,20 @@ CS4236_SINGLEC("3D Control - Volume", 0, 2, 0, 15, 1),
CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
};
-int snd_cs4236_mixer(struct snd_cs4231 *chip)
+int snd_cs4236_mixer(struct snd_wss *chip)
{
struct snd_card *card;
unsigned int idx, count;
int err;
struct snd_kcontrol_new *kcontrol;
- snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
+ if (snd_BUG_ON(!chip || !chip->card))
+ return -EINVAL;
card = chip->card;
- strcpy(card->mixername, snd_cs4231_chip_id(chip));
+ strcpy(card->mixername, snd_wss_chip_id(chip));
- if (chip->hardware == CS4231_HW_CS4235 ||
- chip->hardware == CS4231_HW_CS4239) {
+ if (chip->hardware == WSS_HW_CS4235 ||
+ chip->hardware == WSS_HW_CS4239) {
for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) {
if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0)
return err;
@@ -920,16 +985,16 @@ int snd_cs4236_mixer(struct snd_cs4231 *chip)
}
}
switch (chip->hardware) {
- case CS4231_HW_CS4235:
- case CS4231_HW_CS4239:
+ case WSS_HW_CS4235:
+ case WSS_HW_CS4239:
count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4235);
kcontrol = snd_cs4236_3d_controls_cs4235;
break;
- case CS4231_HW_CS4237B:
+ case WSS_HW_CS4237B:
count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4237);
kcontrol = snd_cs4236_3d_controls_cs4237;
break;
- case CS4231_HW_CS4238B:
+ case WSS_HW_CS4238B:
count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4238);
kcontrol = snd_cs4236_3d_controls_cs4238;
break;
@@ -941,8 +1006,8 @@ int snd_cs4236_mixer(struct snd_cs4231 *chip)
if ((err = snd_ctl_add(card, snd_ctl_new1(kcontrol, chip))) < 0)
return err;
}
- if (chip->hardware == CS4231_HW_CS4237B ||
- chip->hardware == CS4231_HW_CS4238B) {
+ if (chip->hardware == WSS_HW_CS4237B ||
+ chip->hardware == WSS_HW_CS4238B) {
for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) {
if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0)
return err;
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index 1e1e575b1db3..4fbb508a817f 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -1009,7 +1009,8 @@ int snd_es1688_mixer(struct snd_es1688 *chip)
int err;
unsigned char reg, val;
- snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
+ if (snd_BUG_ON(!chip || !chip->card))
+ return -EINVAL;
card = chip->card;
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index cccc16c8113f..12eb98f2f931 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -276,9 +276,11 @@ static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches)
static unsigned char dmas[8] =
{6, 1, 0, 2, 0, 3, 4, 5};
- snd_assert(gus != NULL, return -EINVAL);
+ if (snd_BUG_ON(!gus))
+ return -EINVAL;
card = gus->card;
- snd_assert(card != NULL, return -EINVAL);
+ if (snd_BUG_ON(!card))
+ return -EINVAL;
gus->mix_cntrl_reg &= 0xf8;
gus->mix_cntrl_reg |= 0x01; /* disable MIC, LINE IN, enable LINE OUT */
diff --git a/sound/isa/gus/gus_mixer.c b/sound/isa/gus/gus_mixer.c
index ebdb33469306..0dd43414016e 100644
--- a/sound/isa/gus/gus_mixer.c
+++ b/sound/isa/gus/gus_mixer.c
@@ -161,9 +161,11 @@ int snd_gf1_new_mixer(struct snd_gus_card * gus)
unsigned int idx, max;
int err;
- snd_assert(gus != NULL, return -EINVAL);
+ if (snd_BUG_ON(!gus))
+ return -EINVAL;
card = gus->card;
- snd_assert(card != NULL, return -EINVAL);
+ if (snd_BUG_ON(!card))
+ return -EINVAL;
if (gus->ics_flag)
snd_component_add(card, "ICS2101");
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index 99731dc97325..38510aeb21c6 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -352,8 +352,10 @@ static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream,
bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
len = samples_to_bytes(runtime, count);
- snd_assert(bpos <= pcmp->dma_size, return -EIO);
- snd_assert(bpos + len <= pcmp->dma_size, return -EIO);
+ if (snd_BUG_ON(bpos > pcmp->dma_size))
+ return -EIO;
+ if (snd_BUG_ON(bpos + len > pcmp->dma_size))
+ return -EIO;
if (copy_from_user(runtime->dma_area + bpos, src, len))
return -EFAULT;
if (snd_gf1_pcm_use_dma && len > 32) {
@@ -381,8 +383,10 @@ static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream,
bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
len = samples_to_bytes(runtime, count);
- snd_assert(bpos <= pcmp->dma_size, return -EIO);
- snd_assert(bpos + len <= pcmp->dma_size, return -EIO);
+ if (snd_BUG_ON(bpos > pcmp->dma_size))
+ return -EIO;
+ if (snd_BUG_ON(bpos + len > pcmp->dma_size))
+ return -EIO;
snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos, count);
if (snd_gf1_pcm_use_dma && len > 32) {
return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len);
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index f87c6236661c..f94c1976e632 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -28,7 +28,7 @@
#include
#include
#include
-#include
+#include
#define SNDRV_LEGACY_FIND_FREE_IRQ
#define SNDRV_LEGACY_FIND_FREE_DMA
#include
@@ -75,7 +75,7 @@ struct snd_gusmax {
int irq;
struct snd_card *card;
struct snd_gus_card *gus;
- struct snd_cs4231 *cs4231;
+ struct snd_wss *wss;
unsigned short gus_status_reg;
unsigned short pcm_status_reg;
};
@@ -117,7 +117,7 @@ static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id)
}
if (inb(maxcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */
handled = 1;
- snd_cs4231_interrupt(irq, maxcard->cs4231);
+ snd_wss_interrupt(irq, maxcard->wss);
loop++;
}
} while (loop && --max > 0);
@@ -140,10 +140,7 @@ static void __devinit snd_gusmax_init(int dev, struct snd_card *card,
outb(gus->max_cntrl_val, GUSP(gus, MAXCNTRLPORT));
}
-#define CS4231_PRIVATE( left, right, shift, mute ) \
- ((left << 24)|(right << 16)|(shift<<8)|mute)
-
-static int __devinit snd_gusmax_mixer(struct snd_cs4231 *chip)
+static int __devinit snd_gusmax_mixer(struct snd_wss *chip)
{
struct snd_card *card = chip->card;
struct snd_ctl_elem_id id1, id2;
@@ -214,7 +211,7 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
int xirq, xdma1, xdma2, err;
struct snd_card *card;
struct snd_gus_card *gus = NULL;
- struct snd_cs4231 *cs4231;
+ struct snd_wss *wss;
struct snd_gusmax *maxcard;
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
@@ -301,33 +298,39 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
}
maxcard->irq = xirq;
- if ((err = snd_cs4231_create(card,
- gus->gf1.port + 0x10c, -1, xirq,
- xdma2 < 0 ? xdma1 : xdma2, xdma1,
- CS4231_HW_DETECT,
- CS4231_HWSHARE_IRQ |
- CS4231_HWSHARE_DMA1 |
- CS4231_HWSHARE_DMA2,
- &cs4231)) < 0)
+ err = snd_wss_create(card,
+ gus->gf1.port + 0x10c, -1, xirq,
+ xdma2 < 0 ? xdma1 : xdma2, xdma1,
+ WSS_HW_DETECT,
+ WSS_HWSHARE_IRQ |
+ WSS_HWSHARE_DMA1 |
+ WSS_HWSHARE_DMA2,
+ &wss);
+ if (err < 0)
goto _err;
- if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0)
+ err = snd_wss_pcm(wss, 0, NULL);
+ if (err < 0)
goto _err;
- if ((err = snd_cs4231_mixer(cs4231)) < 0)
+ err = snd_wss_mixer(wss);
+ if (err < 0)
goto _err;
- if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0)
+ err = snd_wss_timer(wss, 2, NULL);
+ if (err < 0)
goto _err;
if (pcm_channels[dev] > 0) {
if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0)
goto _err;
}
- if ((err = snd_gusmax_mixer(cs4231)) < 0)
+ err = snd_gusmax_mixer(wss);
+ if (err < 0)
goto _err;
- if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0)
+ err = snd_gf1_rawmidi_new(gus, 0, NULL);
+ if (err < 0)
goto _err;
sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %i, dma %i", gus->gf1.port, xirq, xdma1);
@@ -336,11 +339,12 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
snd_card_set_dev(card, pdev);
- if ((err = snd_card_register(card)) < 0)
+ err = snd_card_register(card);
+ if (err < 0)
goto _err;
maxcard->gus = gus;
- maxcard->cs4231 = cs4231;
+ maxcard->wss = wss;
dev_set_drvdata(pdev, card);
return 0;
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index ca0d7ace0c75..5faecfb602d3 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -32,7 +32,7 @@
#include
#include
#include
-#include
+#include
#ifdef SNDRV_STB
#include
#endif
@@ -118,7 +118,7 @@ struct snd_interwave {
int irq;
struct snd_card *card;
struct snd_gus_card *gus;
- struct snd_cs4231 *cs4231;
+ struct snd_wss *wss;
#ifdef SNDRV_STB
struct resource *i2c_res;
#endif
@@ -312,7 +312,7 @@ static irqreturn_t snd_interwave_interrupt(int irq, void *dev_id)
}
if (inb(iwcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */
handled = 1;
- snd_cs4231_interrupt(irq, iwcard->cs4231);
+ snd_wss_interrupt(irq, iwcard->wss);
loop++;
}
} while (loop && --max > 0);
@@ -498,13 +498,17 @@ static void __devinit snd_interwave_init(int dev, struct snd_gus_card * gus)
}
static struct snd_kcontrol_new snd_interwave_controls[] = {
-CS4231_DOUBLE("Master Playback Switch", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("Master Playback Volume", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1),
-CS4231_DOUBLE("Mic Playback Switch", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1),
-CS4231_DOUBLE("Mic Playback Volume", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1)
+WSS_DOUBLE("Master Playback Switch", 0,
+ CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1),
+WSS_DOUBLE("Master Playback Volume", 0,
+ CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1),
+WSS_DOUBLE("Mic Playback Switch", 0,
+ CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1),
+WSS_DOUBLE("Mic Playback Volume", 0,
+ CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1)
};
-static int __devinit snd_interwave_mixer(struct snd_cs4231 *chip)
+static int __devinit snd_interwave_mixer(struct snd_wss *chip)
{
struct snd_card *card = chip->card;
struct snd_ctl_elem_id id1, id2;
@@ -527,10 +531,10 @@ static int __devinit snd_interwave_mixer(struct snd_cs4231 *chip)
for (idx = 0; idx < ARRAY_SIZE(snd_interwave_controls); idx++)
if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_interwave_controls[idx], chip))) < 0)
return err;
- snd_cs4231_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f);
- snd_cs4231_out(chip, CS4231_LINE_RIGHT_OUTPUT, 0x9f);
- snd_cs4231_out(chip, CS4231_LEFT_MIC_INPUT, 0x9f);
- snd_cs4231_out(chip, CS4231_RIGHT_MIC_INPUT, 0x9f);
+ snd_wss_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f);
+ snd_wss_out(chip, CS4231_LINE_RIGHT_OUTPUT, 0x9f);
+ snd_wss_out(chip, CS4231_LEFT_MIC_INPUT, 0x9f);
+ snd_wss_out(chip, CS4231_RIGHT_MIC_INPUT, 0x9f);
/* reassign AUXA to SYNTHESIZER */
strcpy(id1.name, "Aux Playback Switch");
strcpy(id2.name, "Synth Playback Switch");
@@ -642,7 +646,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
{
int xirq, xdma1, xdma2;
struct snd_interwave *iwcard = card->private_data;
- struct snd_cs4231 *cs4231;
+ struct snd_wss *wss;
struct snd_gus_card *gus;
#ifdef SNDRV_STB
struct snd_i2c_bus *i2c_bus;
@@ -684,33 +688,39 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
}
iwcard->irq = xirq;
- if ((err = snd_cs4231_create(card,
- gus->gf1.port + 0x10c, -1, xirq,
- xdma2 < 0 ? xdma1 : xdma2, xdma1,
- CS4231_HW_INTERWAVE,
- CS4231_HWSHARE_IRQ |
- CS4231_HWSHARE_DMA1 |
- CS4231_HWSHARE_DMA2,
- &cs4231)) < 0)
+ err = snd_wss_create(card,
+ gus->gf1.port + 0x10c, -1, xirq,
+ xdma2 < 0 ? xdma1 : xdma2, xdma1,
+ WSS_HW_INTERWAVE,
+ WSS_HWSHARE_IRQ |
+ WSS_HWSHARE_DMA1 |
+ WSS_HWSHARE_DMA2,
+ &wss);
+ if (err < 0)
return err;
- if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0)
+ err = snd_wss_pcm(wss, 0, &pcm);
+ if (err < 0)
return err;
sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A');
strcat(pcm->name, " (codec)");
- if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0)
+ err = snd_wss_timer(wss, 2, NULL);
+ if (err < 0)
return err;
- if ((err = snd_cs4231_mixer(cs4231)) < 0)
+ err = snd_wss_mixer(wss);
+ if (err < 0)
return err;
if (pcm_channels[dev] > 0) {
- if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0)
+ err = snd_gf1_pcm_new(gus, 1, 1, NULL);
+ if (err < 0)
return err;
}
- if ((err = snd_interwave_mixer(cs4231)) < 0)
+ err = snd_interwave_mixer(wss);
+ if (err < 0)
return err;
#ifdef SNDRV_STB
@@ -754,10 +764,11 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
if (xdma2 >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
- if ((err = snd_card_register(card)) < 0)
+ err = snd_card_register(card);
+ if (err < 0)
return err;
- iwcard->cs4231 = cs4231;
+ iwcard->wss = wss;
iwcard->gus = gus;
return 0;
}
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 854a9f74b466..58c972b2af03 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -28,7 +28,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -124,7 +124,6 @@ static int pnpc_registered;
#define OPL3SA2_PM_D3 (OPL3SA2_PM_ADOWN|OPL3SA2_PM_PSV|OPL3SA2_PM_PDN|OPL3SA2_PM_PDX)
struct snd_opl3sa2 {
- struct snd_card *card;
int version; /* 2 or 3 */
unsigned long port; /* control port */
struct resource *res_port; /* control port resource */
@@ -133,7 +132,7 @@ struct snd_opl3sa2 {
spinlock_t reg_lock;
struct snd_hwdep *synth;
struct snd_rawmidi *rmidi;
- struct snd_cs4231 *cs4231;
+ struct snd_wss *wss;
unsigned char ctlregs[0x20];
int ymode; /* SL added */
struct snd_kcontrol *master_switch;
@@ -222,14 +221,13 @@ static void snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsig
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip)
+static int __devinit snd_opl3sa2_detect(struct snd_card *card)
{
- struct snd_card *card;
+ struct snd_opl3sa2 *chip = card->private_data;
unsigned long port;
unsigned char tmp, tmp1;
char str[2];
- card = chip->card;
port = chip->port;
if ((chip->res_port = request_region(port, 2, "OPL3-SA control")) == NULL) {
snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port);
@@ -298,12 +296,14 @@ static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip)
static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id)
{
unsigned short status;
- struct snd_opl3sa2 *chip = dev_id;
+ struct snd_card *card = dev_id;
+ struct snd_opl3sa2 *chip;
int handled = 0;
- if (chip == NULL || chip->card == NULL)
+ if (card == NULL)
return IRQ_NONE;
+ chip = card->private_data;
status = snd_opl3sa2_read(chip, OPL3SA2_IRQ_STATUS);
if (status & 0x20) {
@@ -318,7 +318,7 @@ static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id)
if (status & 0x07) { /* TI,CI,PI */
handled = 1;
- snd_cs4231_interrupt(irq, chip->cs4231);
+ snd_wss_interrupt(irq, chip->wss);
}
if (status & 0x40) { /* hardware volume change */
@@ -327,8 +327,10 @@ static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id)
snd_opl3sa2_read(chip, OPL3SA2_MASTER_RIGHT);
snd_opl3sa2_read(chip, OPL3SA2_MASTER_LEFT);
if (chip->master_switch && chip->master_volume) {
- snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_switch->id);
- snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_volume->id);
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &chip->master_switch->id);
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &chip->master_volume->id);
}
}
return IRQ_RETVAL(handled);
@@ -336,29 +338,18 @@ static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id)
#define OPL3SA2_SINGLE(xname, xindex, reg, shift, mask, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
- .info = snd_opl3sa2_info_single, \
+ .info = snd_wss_info_single, \
.get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
#define OPL3SA2_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
.name = xname, .index = xindex, \
- .info = snd_opl3sa2_info_single, \
+ .info = snd_wss_info_single, \
.get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
.tlv = { .p = (xtlv) } }
-static int snd_opl3sa2_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- int mask = (kcontrol->private_value >> 16) & 0xff;
-
- 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 = mask;
- return 0;
-}
-
static int snd_opl3sa2_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol);
@@ -402,29 +393,18 @@ static int snd_opl3sa2_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_
#define OPL3SA2_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
- .info = snd_opl3sa2_info_double, \
+ .info = snd_wss_info_double, \
.get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
#define OPL3SA2_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
.name = xname, .index = xindex, \
- .info = snd_opl3sa2_info_double, \
+ .info = snd_wss_info_double, \
.get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22), \
.tlv = { .p = (xtlv) } }
-static int snd_opl3sa2_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
- int mask = (kcontrol->private_value >> 24) & 0xff;
-
- 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 = mask;
- return 0;
-}
-
static int snd_opl3sa2_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol);
@@ -512,9 +492,9 @@ static void snd_opl3sa2_master_free(struct snd_kcontrol *kcontrol)
chip->master_volume = NULL;
}
-static int __devinit snd_opl3sa2_mixer(struct snd_opl3sa2 *chip)
+static int __devinit snd_opl3sa2_mixer(struct snd_card *card)
{
- struct snd_card *card = chip->card;
+ struct snd_opl3sa2 *chip = card->private_data;
struct snd_ctl_elem_id id1, id2;
struct snd_kcontrol *kctl;
unsigned int idx;
@@ -573,7 +553,7 @@ static int snd_opl3sa2_suspend(struct snd_card *card, pm_message_t state)
struct snd_opl3sa2 *chip = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- chip->cs4231->suspend(chip->cs4231);
+ chip->wss->suspend(chip->wss);
/* power down */
snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3);
@@ -597,8 +577,8 @@ static int snd_opl3sa2_resume(struct snd_card *card)
for (i = 0x12; i <= 0x16; i++)
snd_opl3sa2_write(chip, i, chip->ctlregs[i]);
}
- /* restore cs4231 */
- chip->cs4231->resume(chip->cs4231);
+ /* restore wss */
+ chip->wss->resume(chip->wss);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
@@ -650,7 +630,6 @@ static struct snd_card *snd_opl3sa2_card_new(int dev)
chip = card->private_data;
spin_lock_init(&chip->reg_lock);
chip->irq = -1;
- chip->card = card;
card->private_free = snd_opl3sa2_free;
return card;
}
@@ -659,7 +638,7 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
{
int xirq, xdma1, xdma2;
struct snd_opl3sa2 *chip;
- struct snd_cs4231 *cs4231;
+ struct snd_wss *wss;
struct snd_opl3 *opl3;
int err;
@@ -672,30 +651,36 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
xdma2 = dma2[dev];
if (xdma2 < 0)
chip->single_dma = 1;
- if ((err = snd_opl3sa2_detect(chip)) < 0)
+ err = snd_opl3sa2_detect(card);
+ if (err < 0)
return err;
- if (request_irq(xirq, snd_opl3sa2_interrupt, IRQF_DISABLED, "OPL3-SA2", chip)) {
+ err = request_irq(xirq, snd_opl3sa2_interrupt, IRQF_DISABLED,
+ "OPL3-SA2", card);
+ if (err) {
snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq);
return -ENODEV;
}
chip->irq = xirq;
- if ((err = snd_cs4231_create(card,
- wss_port[dev] + 4, -1,
- xirq, xdma1, xdma2,
- CS4231_HW_OPL3SA2,
- CS4231_HWSHARE_IRQ,
- &cs4231)) < 0) {
+ err = snd_wss_create(card,
+ wss_port[dev] + 4, -1,
+ xirq, xdma1, xdma2,
+ WSS_HW_OPL3SA2, WSS_HWSHARE_IRQ, &wss);
+ if (err < 0) {
snd_printd("Oops, WSS not detected at 0x%lx\n", wss_port[dev] + 4);
return err;
}
- chip->cs4231 = cs4231;
- if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0)
+ chip->wss = wss;
+ err = snd_wss_pcm(wss, 0, NULL);
+ if (err < 0)
return err;
- if ((err = snd_cs4231_mixer(cs4231)) < 0)
+ err = snd_wss_mixer(wss);
+ if (err < 0)
return err;
- if ((err = snd_opl3sa2_mixer(chip)) < 0)
+ err = snd_opl3sa2_mixer(card);
+ if (err < 0)
return err;
- if ((err = snd_cs4231_timer(cs4231, 0, NULL)) < 0)
+ err = snd_wss_timer(wss, 0, NULL);
+ if (err < 0)
return err;
if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) {
if ((err = snd_opl3_create(card, fm_port[dev],
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index 2a1e2f5d12c2..440755cc0013 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -32,7 +32,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -675,7 +675,8 @@ static int __devinit snd_miro_mixer(struct snd_miro *miro)
unsigned int idx;
int err;
- snd_assert(miro != NULL && miro->card != NULL, return -EINVAL);
+ if (snd_BUG_ON(!miro || !miro->card))
+ return -EINVAL;
card = miro->card;
@@ -1221,7 +1222,7 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
int error;
struct snd_miro *miro;
- struct snd_cs4231 *codec;
+ struct snd_wss *codec;
struct snd_timer *timer;
struct snd_card *card;
struct snd_pcm *pcm;
@@ -1310,29 +1311,32 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
}
}
- if ((error = snd_miro_configure(miro))) {
+ error = snd_miro_configure(miro);
+ if (error) {
snd_card_free(card);
return error;
}
- if ((error = snd_cs4231_create(card, miro->wss_base + 4, -1,
- miro->irq, miro->dma1, miro->dma2,
- CS4231_HW_AD1845,
- 0,
- &codec)) < 0) {
+ error = snd_wss_create(card, miro->wss_base + 4, -1,
+ miro->irq, miro->dma1, miro->dma2,
+ WSS_HW_AD1845, 0, &codec);
+ if (error < 0) {
snd_card_free(card);
return error;
}
- if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0) {
+ error = snd_wss_pcm(codec, 0, &pcm);
+ if (error < 0) {
snd_card_free(card);
return error;
}
- if ((error = snd_cs4231_mixer(codec)) < 0) {
+ error = snd_wss_mixer(codec);
+ if (error < 0) {
snd_card_free(card);
return error;
}
- if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0) {
+ error = snd_wss_timer(codec, 0, &timer);
+ if (error < 0) {
snd_card_free(card);
return error;
}
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 0797ca441a37..19706b0d8497 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -33,11 +33,7 @@
#include
#include
#include
-#if defined(CS4231) || defined(OPTi93X)
-#include
-#else
-#include
-#endif /* CS4231 */
+#include
#include
#include
#ifndef OPTi93X
@@ -139,7 +135,7 @@ struct snd_opti9xx {
unsigned long mc_base_size;
#ifdef OPTi93X
unsigned long mc_indir_index;
- struct snd_cs4231 *codec;
+ struct snd_wss *codec;
#endif /* OPTi93X */
unsigned long pwd_reg;
@@ -148,9 +144,7 @@ struct snd_opti9xx {
long wss_base;
int irq;
int dma1;
-#if defined(CS4231) || defined(OPTi93X)
int dma2;
-#endif /* CS4231 || OPTi93X */
long fm_port;
@@ -225,9 +219,7 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
chip->wss_base = -1;
chip->irq = -1;
chip->dma1 = -1;
-#if defined(CS4231) || defined (OPTi93X)
chip->dma2 = -1;
-#endif /* CS4231 || OPTi93X */
chip->fm_port = -1;
chip->mpu_port = -1;
chip->mpu_irq = -1;
@@ -562,7 +554,7 @@ __skip_mpu:
static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
{
- struct snd_cs4231 *codec = dev_id;
+ struct snd_wss *codec = dev_id;
struct snd_opti9xx *chip = codec->card->private_data;
unsigned char status;
@@ -570,7 +562,7 @@ static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream)
snd_pcm_period_elapsed(codec->playback_substream);
if ((status & OPTi93X_IRQ_CAPTURE) && codec->capture_substream) {
- snd_cs4231_overrange(codec);
+ snd_wss_overrange(codec);
snd_pcm_period_elapsed(codec->capture_substream);
}
outb(0x00, OPTi93X_PORT(codec, STATUS));
@@ -691,7 +683,7 @@ static void snd_card_opti9xx_free(struct snd_card *card)
if (chip) {
#ifdef OPTi93X
- struct snd_cs4231 *codec = chip->codec;
+ struct snd_wss *codec = chip->codec;
if (codec && codec->irq > 0) {
disable_irq(codec->irq);
free_irq(codec->irq, codec);
@@ -706,13 +698,9 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
int error;
struct snd_opti9xx *chip = card->private_data;
-#if defined(CS4231) || defined(OPTi93X)
- struct snd_cs4231 *codec;
+ struct snd_wss *codec;
#ifdef CS4231
struct snd_timer *timer;
-#endif
-#else
- struct snd_ad1848 *codec;
#endif
struct snd_pcm *pcm;
struct snd_rawmidi *rmidi;
@@ -731,54 +719,52 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
chip->dma1 = dma1;
#if defined(CS4231) || defined(OPTi93X)
chip->dma2 = dma2;
+#else
+ chip->dma2 = -1;
#endif
if (chip->wss_base == SNDRV_AUTO_PORT) {
- if ((chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) {
+ chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4);
+ if (chip->wss_base < 0) {
snd_printk("unable to find a free WSS port\n");
return -EBUSY;
}
}
- if ((error = snd_opti9xx_configure(chip)))
+ error = snd_opti9xx_configure(chip);
+ if (error)
return error;
-#if defined(CS4231) || defined(OPTi93X)
- if ((error = snd_cs4231_create(card, chip->wss_base + 4, -1,
- chip->irq, chip->dma1, chip->dma2,
-#ifdef CS4231
- CS4231_HW_DETECT, 0,
-#else /* OPTi93x */
- CS4231_HW_OPTI93X, CS4231_HWSHARE_IRQ,
+ error = snd_wss_create(card, chip->wss_base + 4, -1,
+ chip->irq, chip->dma1, chip->dma2,
+#ifdef OPTi93X
+ WSS_HW_OPTI93X, WSS_HWSHARE_IRQ,
+#else
+ WSS_HW_DETECT, 0,
#endif
- &codec)) < 0)
+ &codec);
+ if (error < 0)
return error;
#ifdef OPTi93X
chip->codec = codec;
#endif
- if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0)
+ error = snd_wss_pcm(codec, 0, &pcm);
+ if (error < 0)
return error;
- if ((error = snd_cs4231_mixer(codec)) < 0)
+ error = snd_wss_mixer(codec);
+ if (error < 0)
return error;
#ifdef CS4231
- if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0)
+ error = snd_wss_timer(codec, 0, &timer);
+ if (error < 0)
return error;
-#else /* OPTI93X */
+#endif
+#ifdef OPTi93X
error = request_irq(chip->irq, snd_opti93x_interrupt,
IRQF_DISABLED, DEV_NAME" - WSS", codec);
if (error < 0) {
snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq);
return error;
}
-#endif
-#else
- if ((error = snd_ad1848_create(card, chip->wss_base + 4,
- chip->irq, chip->dma1,
- AD1848_HW_DETECT, &codec)) < 0)
- return error;
- if ((error = snd_ad1848_pcm(codec, 0, &pcm)) < 0)
- return error;
- if ((error = snd_ad1848_mixer(codec)) < 0)
- return error;
#endif
strcpy(card->driver, chip->name);
sprintf(card->shortname, "OPTi %s", card->driver);
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index b35be7d9a9fa..96678d5d3834 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -1023,7 +1023,8 @@ snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
{
int i, err = 0;
- snd_assert(emu != NULL && card != NULL, return -EINVAL);
+ if (snd_BUG_ON(!emu || !card))
+ return -EINVAL;
spin_lock_init(&emu->control_lock);
diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c
index 1be16c9700f0..c99c6078be33 100644
--- a/sound/isa/sb/emu8000_patch.c
+++ b/sound/isa/sb/emu8000_patch.c
@@ -156,7 +156,8 @@ snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
struct snd_emu8000 *emu;
emu = rec->hw;
- snd_assert(sp != NULL, return -EINVAL);
+ if (snd_BUG_ON(!sp))
+ return -EINVAL;
if (sp->v.size == 0)
return 0;
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index 35f3d7b16536..49037d074c71 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -198,7 +198,8 @@ static int snd_sb_csp_ioctl(struct snd_hwdep * hw, struct file *file, unsigned i
struct snd_sb_csp_start start_info;
int err;
- snd_assert(p != NULL, return -EINVAL);
+ if (snd_BUG_ON(!p))
+ return -EINVAL;
if (snd_sb_csp_check_version(p))
return -ENODEV;
@@ -1046,7 +1047,8 @@ static int snd_sb_qsound_build(struct snd_sb_csp * p)
struct snd_card *card;
int err;
- snd_assert(p != NULL, return -EINVAL);
+ if (snd_BUG_ON(!p))
+ return -EINVAL;
card = p->chip->card;
p->qpos_left = p->qpos_right = SNDRV_SB_CSP_QSOUND_MAX_RIGHT / 2;
@@ -1071,7 +1073,8 @@ static void snd_sb_qsound_destroy(struct snd_sb_csp * p)
struct snd_card *card;
unsigned long flags;
- snd_assert(p != NULL, return);
+ if (snd_BUG_ON(!p))
+ return;
card = p->chip->card;
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c
index f7e8192270ae..2a6cc1cfe945 100644
--- a/sound/isa/sb/sb16_main.c
+++ b/sound/isa/sb/sb16_main.c
@@ -669,7 +669,8 @@ static int snd_sb16_capture_close(struct snd_pcm_substream *substream)
static int snd_sb16_set_dma_mode(struct snd_sb *chip, int what)
{
if (chip->dma8 < 0 || chip->dma16 < 0) {
- snd_assert(what == 0, return -EINVAL);
+ if (snd_BUG_ON(what))
+ return -EINVAL;
return 0;
}
if (what == 0) {
diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c
index fe03bb820532..658d55769c9c 100644
--- a/sound/isa/sb/sb8_main.c
+++ b/sound/isa/sb/sb8_main.c
@@ -111,7 +111,9 @@ static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream)
switch (chip->hardware) {
case SB_HW_PRO:
if (runtime->channels > 1) {
- snd_assert(rate == SB8_RATE(11025) || rate == SB8_RATE(22050), return -EINVAL);
+ if (snd_BUG_ON(rate != SB8_RATE(11025) &&
+ rate != SB8_RATE(22050)))
+ return -EINVAL;
chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
break;
}
@@ -237,7 +239,9 @@ static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream)
switch (chip->hardware) {
case SB_HW_PRO:
if (runtime->channels > 1) {
- snd_assert(rate == SB8_RATE(11025) || rate == SB8_RATE(22050), return -EINVAL);
+ if (snd_BUG_ON(rate != SB8_RATE(11025) &&
+ rate != SB8_RATE(22050)))
+ return -EINVAL;
chip->capture_format = SB_DSP_HI_INPUT_AUTO;
break;
}
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index b432d9ae874b..27a651502251 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -219,7 +219,8 @@ int snd_sbdsp_create(struct snd_card *card,
.dev_free = snd_sbdsp_dev_free,
};
- snd_assert(r_chip != NULL, return -EINVAL);
+ if (snd_BUG_ON(!r_chip))
+ return -EINVAL;
*r_chip = NULL;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c
index 73d4572d136b..406a431af91e 100644
--- a/sound/isa/sb/sb_mixer.c
+++ b/sound/isa/sb/sb_mixer.c
@@ -792,7 +792,8 @@ int snd_sbmixer_new(struct snd_sb *chip)
struct snd_card *card;
int err;
- snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
+ if (snd_BUG_ON(!chip || !chip->card))
+ return -EINVAL;
card = chip->card;
@@ -925,7 +926,8 @@ static unsigned char als4000_saved_regs[] = {
static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs)
{
unsigned char *val = chip->saved_regs;
- snd_assert(num_regs <= ARRAY_SIZE(chip->saved_regs), return);
+ if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs)))
+ return;
for (; num_regs; num_regs--)
*val++ = snd_sbmixer_read(chip, *regs++);
}
@@ -933,7 +935,8 @@ static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs)
static void restore_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs)
{
unsigned char *val = chip->saved_regs;
- snd_assert(num_regs <= ARRAY_SIZE(chip->saved_regs), return);
+ if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs)))
+ return;
for (; num_regs; num_regs--)
snd_sbmixer_write(chip, *regs++, *val++);
}
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
index da3d152bcad4..ca35924dc3b3 100644
--- a/sound/isa/sc6000.c
+++ b/sound/isa/sc6000.c
@@ -29,7 +29,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -397,7 +397,7 @@ static int __devinit sc6000_init_board(char __iomem *vport, int irq, int dma,
return 0;
}
-static int __devinit snd_sc6000_mixer(struct snd_ad1848 *chip)
+static int __devinit snd_sc6000_mixer(struct snd_wss *chip)
{
struct snd_card *card = chip->card;
struct snd_ctl_elem_id id1, id2;
@@ -483,7 +483,7 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
int xirq = irq[dev];
int xdma = dma[dev];
struct snd_card *card;
- struct snd_ad1848 *chip;
+ struct snd_wss *chip;
struct snd_opl3 *opl3;
char __iomem *vport;
char __iomem *vmss_port;
@@ -548,21 +548,21 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
if (err < 0)
goto err_unmap2;
- err = snd_ad1848_create(card, mss_port[dev] + 4, xirq, xdma,
- AD1848_HW_DETECT, &chip);
+ err = snd_wss_create(card, mss_port[dev] + 4, -1, xirq, xdma, -1,
+ WSS_HW_DETECT, 0, &chip);
if (err < 0)
goto err_unmap2;
card->private_data = chip;
- err = snd_ad1848_pcm(chip, 0, NULL);
+ err = snd_wss_pcm(chip, 0, NULL);
if (err < 0) {
snd_printk(KERN_ERR PFX
- "error creating new ad1848 PCM device\n");
+ "error creating new WSS PCM device\n");
goto err_unmap2;
}
- err = snd_ad1848_mixer(chip);
+ err = snd_wss_mixer(chip);
if (err < 0) {
- snd_printk(KERN_ERR PFX "error creating new ad1848 mixer\n");
+ snd_printk(KERN_ERR PFX "error creating new WSS mixer\n");
goto err_unmap2;
}
err = snd_sc6000_mixer(chip);
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
index a07274ecb149..2c7503bf1271 100644
--- a/sound/isa/sgalaxy.c
+++ b/sound/isa/sgalaxy.c
@@ -31,7 +31,7 @@
#include
#include
#include
-#include
+#include
#include
#define SNDRV_LEGACY_FIND_FREE_IRQ
#define SNDRV_LEGACY_FIND_FREE_DMA
@@ -175,12 +175,14 @@ static int __devinit snd_sgalaxy_detect(int dev, int irq, int dma)
return snd_sgalaxy_setup_wss(wssport[dev], irq, dma);
}
-static struct ad1848_mix_elem snd_sgalaxy_controls[] = {
-AD1848_DOUBLE("Aux Playback Switch", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7, 7, 1, 1),
-AD1848_DOUBLE("Aux Playback Volume", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0)
+static struct snd_kcontrol_new snd_sgalaxy_controls[] = {
+WSS_DOUBLE("Aux Playback Switch", 0,
+ SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7, 7, 1, 1),
+WSS_DOUBLE("Aux Playback Volume", 0,
+ SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0)
};
-static int __devinit snd_sgalaxy_mixer(struct snd_ad1848 *chip)
+static int __devinit snd_sgalaxy_mixer(struct snd_wss *chip)
{
struct snd_card *card = chip->card;
struct snd_ctl_elem_id id1, id2;
@@ -210,7 +212,9 @@ static int __devinit snd_sgalaxy_mixer(struct snd_ad1848 *chip)
return err;
/* build AUX2 input */
for (idx = 0; idx < ARRAY_SIZE(snd_sgalaxy_controls); idx++) {
- if ((err = snd_ad1848_add_ctl_elem(chip, &snd_sgalaxy_controls[idx])) < 0)
+ err = snd_ctl_add(card,
+ snd_ctl_new1(&snd_sgalaxy_controls[idx], chip));
+ if (err < 0)
return err;
}
return 0;
@@ -237,7 +241,7 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev)
static int possible_dmas[] = {1, 3, 0, -1};
int err, xirq, xdma1;
struct snd_card *card;
- struct snd_ad1848 *chip;
+ struct snd_wss *chip;
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
if (card == NULL)
@@ -263,18 +267,21 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev)
if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0)
goto _err;
- if ((err = snd_ad1848_create(card, wssport[dev] + 4,
- xirq, xdma1,
- AD1848_HW_DETECT, &chip)) < 0)
+ err = snd_wss_create(card, wssport[dev] + 4, -1,
+ xirq, xdma1, -1,
+ WSS_HW_DETECT, 0, &chip);
+ if (err < 0)
goto _err;
card->private_data = chip;
- if ((err = snd_ad1848_pcm(chip, 0, NULL)) < 0) {
- snd_printdd(PFX "error creating new ad1848 PCM device\n");
+ err = snd_wss_pcm(chip, 0, NULL);
+ if (err < 0) {
+ snd_printdd(PFX "error creating new WSS PCM device\n");
goto _err;
}
- if ((err = snd_ad1848_mixer(chip)) < 0) {
- snd_printdd(PFX "error creating new ad1848 mixer\n");
+ err = snd_wss_mixer(chip);
+ if (err < 0) {
+ snd_printdd(PFX "error creating new WSS mixer\n");
goto _err;
}
if ((err = snd_sgalaxy_mixer(chip)) < 0) {
@@ -312,7 +319,7 @@ static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n,
pm_message_t state)
{
struct snd_card *card = dev_get_drvdata(pdev);
- struct snd_ad1848 *chip = card->private_data;
+ struct snd_wss *chip = card->private_data;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
chip->suspend(chip);
@@ -322,11 +329,11 @@ static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n,
static int snd_sgalaxy_resume(struct device *pdev, unsigned int n)
{
struct snd_card *card = dev_get_drvdata(pdev);
- struct snd_ad1848 *chip = card->private_data;
+ struct snd_wss *chip = card->private_data;
chip->resume(chip);
- snd_ad1848_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]);
- snd_ad1848_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]);
+ snd_wss_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]);
+ snd_wss_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 06ad7863dff5..48a16d865834 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -31,7 +31,7 @@
#include
#include
#include
-#include
+#include
#include
#include
@@ -147,7 +147,7 @@ struct soundscape {
enum card_type type;
struct resource *io_res;
struct resource *wss_res;
- struct snd_cs4231 *chip;
+ struct snd_wss *chip;
struct snd_mpu401 *mpu;
struct snd_hwdep *hw;
@@ -726,7 +726,7 @@ static int sscape_midi_info(struct snd_kcontrol *ctl,
static int sscape_midi_get(struct snd_kcontrol *kctl,
struct snd_ctl_elem_value *uctl)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kctl);
+ struct snd_wss *chip = snd_kcontrol_chip(kctl);
struct snd_card *card = chip->card;
register struct soundscape *s = get_card_soundscape(card);
unsigned long flags;
@@ -746,7 +746,7 @@ static int sscape_midi_get(struct snd_kcontrol *kctl,
static int sscape_midi_put(struct snd_kcontrol *kctl,
struct snd_ctl_elem_value *uctl)
{
- struct snd_cs4231 *chip = snd_kcontrol_chip(kctl);
+ struct snd_wss *chip = snd_kcontrol_chip(kctl);
struct snd_card *card = chip->card;
register struct soundscape *s = get_card_soundscape(card);
unsigned long flags;
@@ -958,7 +958,9 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned l
* Override for the CS4231 playback format function.
* The AD1845 has much simpler format and rate selection.
*/
-static void ad1845_playback_format(struct snd_cs4231 * chip, struct snd_pcm_hw_params *params, unsigned char format)
+static void ad1845_playback_format(struct snd_wss *chip,
+ struct snd_pcm_hw_params *params,
+ unsigned char format)
{
unsigned long flags;
unsigned rate = params_rate(params);
@@ -983,9 +985,9 @@ static void ad1845_playback_format(struct snd_cs4231 * chip, struct snd_pcm_hw_p
* NOTE: We seem to need to write to the MSB before the LSB
* to get the correct sample frequency.
*/
- snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, (format & 0xf0));
- snd_cs4231_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
- snd_cs4231_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);
+ snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (format & 0xf0));
+ snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
+ snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
@@ -994,7 +996,9 @@ static void ad1845_playback_format(struct snd_cs4231 * chip, struct snd_pcm_hw_p
* Override for the CS4231 capture format function.
* The AD1845 has much simpler format and rate selection.
*/
-static void ad1845_capture_format(struct snd_cs4231 * chip, struct snd_pcm_hw_params *params, unsigned char format)
+static void ad1845_capture_format(struct snd_wss *chip,
+ struct snd_pcm_hw_params *params,
+ unsigned char format)
{
unsigned long flags;
unsigned rate = params_rate(params);
@@ -1019,9 +1023,9 @@ static void ad1845_capture_format(struct snd_cs4231 * chip, struct snd_pcm_hw_pa
* NOTE: We seem to need to write to the MSB before the LSB
* to get the correct sample frequency.
*/
- snd_cs4231_out(chip, CS4231_REC_FORMAT, (format & 0xf0));
- snd_cs4231_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
- snd_cs4231_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);
+ snd_wss_out(chip, CS4231_REC_FORMAT, (format & 0xf0));
+ snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
+ snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
@@ -1036,7 +1040,7 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
int irq, int dma1, int dma2)
{
register struct soundscape *sscape = get_card_soundscape(card);
- struct snd_cs4231 *chip;
+ struct snd_wss *chip;
int err;
if (sscape->type == SSCAPE_VIVO)
@@ -1045,9 +1049,8 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
if (dma1 == dma2)
dma2 = -1;
- err = snd_cs4231_create(card,
- port, -1, irq, dma1, dma2,
- CS4231_HW_DETECT, CS4231_HWSHARE_DMA1, &chip);
+ err = snd_wss_create(card, port, -1, irq, dma1, dma2,
+ WSS_HW_DETECT, WSS_HWSHARE_DMA1, &chip);
if (!err) {
unsigned long flags;
struct snd_pcm *pcm;
@@ -1063,11 +1066,11 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
*
#define AD1845_IFACE_CONFIG \
(CS4231_AUTOCALIB | CS4231_RECORD_ENABLE | CS4231_PLAYBACK_ENABLE)
- snd_cs4231_mce_up(chip);
+ snd_wss_mce_up(chip);
spin_lock_irqsave(&chip->reg_lock, flags);
- snd_cs4231_out(chip, CS4231_IFACE_CTRL, AD1845_IFACE_CONFIG);
+ snd_wss_out(chip, CS4231_IFACE_CTRL, AD1845_IFACE_CONFIG);
spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_cs4231_mce_down(chip);
+ snd_wss_mce_down(chip);
*/
if (sscape->type != SSCAPE_VIVO) {
@@ -1077,11 +1080,11 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
* be 14.31818 MHz, because we must set this register
* to get the playback to sound correct ...
*/
- snd_cs4231_mce_up(chip);
+ snd_wss_mce_up(chip);
spin_lock_irqsave(&chip->reg_lock, flags);
- snd_cs4231_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20);
+ snd_wss_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20);
spin_unlock_irqrestore(&chip->reg_lock, flags);
- snd_cs4231_mce_down(chip);
+ snd_wss_mce_down(chip);
/*
* More custom configuration:
@@ -1089,28 +1092,28 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
* b) enable frequency selection (for capture/playback)
*/
spin_lock_irqsave(&chip->reg_lock, flags);
- snd_cs4231_out(chip, CS4231_MISC_INFO,
- CS4231_MODE2 | 0x10);
- val = snd_cs4231_in(chip, AD1845_PWR_DOWN_CTRL);
- snd_cs4231_out(chip, AD1845_PWR_DOWN_CTRL,
- val | AD1845_FREQ_SEL_ENABLE);
+ snd_wss_out(chip, CS4231_MISC_INFO,
+ CS4231_MODE2 | 0x10);
+ val = snd_wss_in(chip, AD1845_PWR_DOWN_CTRL);
+ snd_wss_out(chip, AD1845_PWR_DOWN_CTRL,
+ val | AD1845_FREQ_SEL_ENABLE);
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
- err = snd_cs4231_pcm(chip, 0, &pcm);
+ err = snd_wss_pcm(chip, 0, &pcm);
if (err < 0) {
snd_printk(KERN_ERR "sscape: No PCM device "
"for AD1845 chip\n");
goto _error;
}
- err = snd_cs4231_mixer(chip);
+ err = snd_wss_mixer(chip);
if (err < 0) {
snd_printk(KERN_ERR "sscape: No mixer device "
"for AD1845 chip\n");
goto _error;
}
- err = snd_cs4231_timer(chip, 0, NULL);
+ err = snd_wss_timer(chip, 0, NULL);
if (err < 0) {
snd_printk(KERN_ERR "sscape: No timer device "
"for AD1845 chip\n");
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 3a6c6fe1ec4d..4c095bc7c729 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -1,6 +1,6 @@
/*
* ALSA card-level driver for Turtle Beach Wavefront cards
- * (Maui,Tropez,Tropez+)
+ * (Maui,Tropez,Tropez+)
*
* Copyright (c) 1997-1999 by Paul Barton-Davis
*
@@ -29,6 +29,7 @@
#include
#include
#include
+#include
#include
MODULE_AUTHOR("Paul Barton-Davis ");
@@ -319,8 +320,8 @@ snd_wavefront_new_midi (struct snd_card *card,
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_wavefront_midi_input);
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
- SNDRV_RAWMIDI_INFO_INPUT |
- SNDRV_RAWMIDI_INFO_DUPLEX;
+ SNDRV_RAWMIDI_INFO_INPUT |
+ SNDRV_RAWMIDI_INFO_DUPLEX;
return rmidi;
}
@@ -363,7 +364,7 @@ static int __devinit
snd_wavefront_probe (struct snd_card *card, int dev)
{
snd_wavefront_card_t *acard = card->private_data;
- struct snd_cs4231 *chip;
+ struct snd_wss *chip;
struct snd_hwdep *wavefront_synth;
struct snd_rawmidi *ics2115_internal_rmidi = NULL;
struct snd_rawmidi *ics2115_external_rmidi = NULL;
@@ -372,21 +373,20 @@ snd_wavefront_probe (struct snd_card *card, int dev)
/* --------- PCM --------------- */
- if ((err = snd_cs4231_create (card,
- cs4232_pcm_port[dev],
- -1,
- cs4232_pcm_irq[dev],
- dma1[dev],
- dma2[dev],
- CS4231_HW_DETECT, 0, &chip)) < 0) {
- snd_printk (KERN_ERR "can't allocate CS4231 device\n");
+ err = snd_wss_create(card, cs4232_pcm_port[dev], -1,
+ cs4232_pcm_irq[dev], dma1[dev], dma2[dev],
+ WSS_HW_DETECT, 0, &chip);
+ if (err < 0) {
+ snd_printk(KERN_ERR "can't allocate WSS device\n");
return err;
}
- if ((err = snd_cs4231_pcm (chip, 0, NULL)) < 0)
+ err = snd_wss_pcm(chip, 0, NULL);
+ if (err < 0)
return err;
- if ((err = snd_cs4231_timer (chip, 0, NULL)) < 0)
+ err = snd_wss_timer(chip, 0, NULL);
+ if (err < 0)
return err;
/* ---------- OPL3 synth --------- */
@@ -394,24 +394,24 @@ snd_wavefront_probe (struct snd_card *card, int dev)
if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
struct snd_opl3 *opl3;
- if ((err = snd_opl3_create(card,
- fm_port[dev],
- fm_port[dev] + 2,
- OPL3_HW_OPL3_CS,
- 0, &opl3)) < 0) {
+ err = snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2,
+ OPL3_HW_OPL3_CS, 0, &opl3);
+ if (err < 0) {
snd_printk (KERN_ERR "can't allocate or detect OPL3 synth\n");
return err;
}
- if ((err = snd_opl3_hwdep_new(opl3, hw_dev, 1, NULL)) < 0)
+ err = snd_opl3_hwdep_new(opl3, hw_dev, 1, NULL);
+ if (err < 0)
return err;
hw_dev++;
}
/* ------- ICS2115 Wavetable synth ------- */
- if ((acard->wavefront.res_base = request_region(ics2115_port[dev], 16,
- "ICS2115")) == NULL) {
+ acard->wavefront.res_base = request_region(ics2115_port[dev], 16,
+ "ICS2115");
+ if (acard->wavefront.res_base == NULL) {
snd_printk(KERN_ERR "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n",
ics2115_port[dev], ics2115_port[dev] + 16 - 1);
return -EBUSY;
@@ -425,7 +425,8 @@ snd_wavefront_probe (struct snd_card *card, int dev)
acard->wavefront.irq = ics2115_irq[dev];
acard->wavefront.base = ics2115_port[dev];
- if ((wavefront_synth = snd_wavefront_new_synth (card, hw_dev, acard)) == NULL) {
+ wavefront_synth = snd_wavefront_new_synth(card, hw_dev, acard);
+ if (wavefront_synth == NULL) {
snd_printk (KERN_ERR "can't create WaveFront synth device\n");
return -ENOMEM;
}
@@ -436,7 +437,8 @@ snd_wavefront_probe (struct snd_card *card, int dev)
/* --------- Mixer ------------ */
- if ((err = snd_cs4231_mixer(chip)) < 0) {
+ err = snd_wss_mixer(chip);
+ if (err < 0) {
snd_printk (KERN_ERR "can't allocate mixer device\n");
return err;
}
@@ -444,11 +446,11 @@ snd_wavefront_probe (struct snd_card *card, int dev)
/* -------- CS4232 MPU-401 interface -------- */
if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) {
- if ((err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232,
- cs4232_mpu_port[dev], 0,
- cs4232_mpu_irq[dev],
- IRQF_DISABLED,
- NULL)) < 0) {
+ err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232,
+ cs4232_mpu_port[dev], 0,
+ cs4232_mpu_irq[dev], IRQF_DISABLED,
+ NULL);
+ if (err < 0) {
snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n");
return err;
}
@@ -601,7 +603,7 @@ static struct isa_driver snd_wavefront_driver = {
#ifdef CONFIG_PNP
static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+ const struct pnp_card_device_id *pid)
{
static int dev;
struct snd_card *card;
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
index 2efaa7f205aa..dfc449a2194e 100644
--- a/sound/isa/wavefront/wavefront_fx.c
+++ b/sound/isa/wavefront/wavefront_fx.c
@@ -180,11 +180,11 @@ snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file,
unsigned short *pd;
int err = 0;
- snd_assert(sdev->card != NULL, return -ENODEV);
-
card = sdev->card;
-
- snd_assert(card->private_data != NULL, return -ENODEV);
+ if (snd_BUG_ON(!card))
+ return -ENODEV;
+ if (snd_BUG_ON(!card->private_data))
+ return -ENODEV;
acard = card->private_data;
dev = &acard->wavefront;
diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c
index a33384a55b0f..f14a7c0b6998 100644
--- a/sound/isa/wavefront/wavefront_midi.c
+++ b/sound/isa/wavefront/wavefront_midi.c
@@ -235,8 +235,10 @@ static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream
snd_wavefront_midi_t *midi;
snd_wavefront_mpu_id mpu;
- snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
- snd_assert(substream->rmidi->private_data != NULL, return -EIO);
+ if (snd_BUG_ON(!substream || !substream->rmidi))
+ return -ENXIO;
+ if (snd_BUG_ON(!substream->rmidi->private_data))
+ return -ENXIO;
mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
@@ -257,8 +259,10 @@ static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substrea
snd_wavefront_midi_t *midi;
snd_wavefront_mpu_id mpu;
- snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
- snd_assert(substream->rmidi->private_data != NULL, return -EIO);
+ if (snd_BUG_ON(!substream || !substream->rmidi))
+ return -ENXIO;
+ if (snd_BUG_ON(!substream->rmidi->private_data))
+ return -ENXIO;
mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
@@ -279,8 +283,10 @@ static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substrea
snd_wavefront_midi_t *midi;
snd_wavefront_mpu_id mpu;
- snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
- snd_assert(substream->rmidi->private_data != NULL, return -EIO);
+ if (snd_BUG_ON(!substream || !substream->rmidi))
+ return -ENXIO;
+ if (snd_BUG_ON(!substream->rmidi->private_data))
+ return -ENXIO;
mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
@@ -300,8 +306,10 @@ static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substre
snd_wavefront_midi_t *midi;
snd_wavefront_mpu_id mpu;
- snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO);
- snd_assert(substream->rmidi->private_data != NULL, return -EIO);
+ if (snd_BUG_ON(!substream || !substream->rmidi))
+ return -ENXIO;
+ if (snd_BUG_ON(!substream->rmidi->private_data))
+ return -ENXIO;
mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index 0bb9b9256601..4c410820a994 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -1648,9 +1648,10 @@ snd_wavefront_synth_ioctl (struct snd_hwdep *hw, struct file *file,
card = (struct snd_card *) hw->card;
- snd_assert(card != NULL, return -ENODEV);
-
- snd_assert(card->private_data != NULL, return -ENODEV);
+ if (snd_BUG_ON(!card))
+ return -ENODEV;
+ if (snd_BUG_ON(!card->private_data))
+ return -ENODEV;
acard = card->private_data;
dev = &acard->wavefront;
diff --git a/sound/isa/wss/Makefile b/sound/isa/wss/Makefile
new file mode 100644
index 000000000000..454fee769a31
--- /dev/null
+++ b/sound/isa/wss/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for ALSA
+# Copyright (c) 2008 by Jaroslav Kysela
+#
+
+snd-wss-lib-objs := wss_lib.o
+
+# Toplevel Module Dependency
+obj-$(CONFIG_SND_WSS_LIB) += snd-wss-lib.o
+
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
new file mode 100644
index 000000000000..3d6c5f2838af
--- /dev/null
+++ b/sound/isa/wss/wss_lib.c
@@ -0,0 +1,2322 @@
+/*
+ * Copyright (c) by Jaroslav Kysela
+ * Routines for control of CS4231(A)/CS4232/InterWave & compatible chips
+ *
+ * Bugs:
+ * - sometimes record brokes playback with WSS portion of
+ * Yamaha OPL3-SA3 chip
+ * - CS4231 (GUS MAX) - still trouble with occasional noises
+ * - broken initialization?
+ *
+ * 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
+
+MODULE_AUTHOR("Jaroslav Kysela ");
+MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips");
+MODULE_LICENSE("GPL");
+
+#if 0
+#define SNDRV_DEBUG_MCE
+#endif
+
+/*
+ * Some variables
+ */
+
+static unsigned char freq_bits[14] = {
+ /* 5510 */ 0x00 | CS4231_XTAL2,
+ /* 6620 */ 0x0E | CS4231_XTAL2,
+ /* 8000 */ 0x00 | CS4231_XTAL1,
+ /* 9600 */ 0x0E | CS4231_XTAL1,
+ /* 11025 */ 0x02 | CS4231_XTAL2,
+ /* 16000 */ 0x02 | CS4231_XTAL1,
+ /* 18900 */ 0x04 | CS4231_XTAL2,
+ /* 22050 */ 0x06 | CS4231_XTAL2,
+ /* 27042 */ 0x04 | CS4231_XTAL1,
+ /* 32000 */ 0x06 | CS4231_XTAL1,
+ /* 33075 */ 0x0C | CS4231_XTAL2,
+ /* 37800 */ 0x08 | CS4231_XTAL2,
+ /* 44100 */ 0x0A | CS4231_XTAL2,
+ /* 48000 */ 0x0C | CS4231_XTAL1
+};
+
+static unsigned int rates[14] = {
+ 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,
+ 27042, 32000, 33075, 37800, 44100, 48000
+};
+
+static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+};
+
+static int snd_wss_xrate(struct snd_pcm_runtime *runtime)
+{
+ return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ &hw_constraints_rates);
+}
+
+static unsigned char snd_wss_original_image[32] =
+{
+ 0x00, /* 00/00 - lic */
+ 0x00, /* 01/01 - ric */
+ 0x9f, /* 02/02 - la1ic */
+ 0x9f, /* 03/03 - ra1ic */
+ 0x9f, /* 04/04 - la2ic */
+ 0x9f, /* 05/05 - ra2ic */
+ 0xbf, /* 06/06 - loc */
+ 0xbf, /* 07/07 - roc */
+ 0x20, /* 08/08 - pdfr */
+ CS4231_AUTOCALIB, /* 09/09 - ic */
+ 0x00, /* 0a/10 - pc */
+ 0x00, /* 0b/11 - ti */
+ CS4231_MODE2, /* 0c/12 - mi */
+ 0xfc, /* 0d/13 - lbc */
+ 0x00, /* 0e/14 - pbru */
+ 0x00, /* 0f/15 - pbrl */
+ 0x80, /* 10/16 - afei */
+ 0x01, /* 11/17 - afeii */
+ 0x9f, /* 12/18 - llic */
+ 0x9f, /* 13/19 - rlic */
+ 0x00, /* 14/20 - tlb */
+ 0x00, /* 15/21 - thb */
+ 0x00, /* 16/22 - la3mic/reserved */
+ 0x00, /* 17/23 - ra3mic/reserved */
+ 0x00, /* 18/24 - afs */
+ 0x00, /* 19/25 - lamoc/version */
+ 0xcf, /* 1a/26 - mioc */
+ 0x00, /* 1b/27 - ramoc/reserved */
+ 0x20, /* 1c/28 - cdfr */
+ 0x00, /* 1d/29 - res4 */
+ 0x00, /* 1e/30 - cbru */
+ 0x00, /* 1f/31 - cbrl */
+};
+
+static unsigned char snd_opti93x_original_image[32] =
+{
+ 0x00, /* 00/00 - l_mixout_outctrl */
+ 0x00, /* 01/01 - r_mixout_outctrl */
+ 0x88, /* 02/02 - l_cd_inctrl */
+ 0x88, /* 03/03 - r_cd_inctrl */
+ 0x88, /* 04/04 - l_a1/fm_inctrl */
+ 0x88, /* 05/05 - r_a1/fm_inctrl */
+ 0x80, /* 06/06 - l_dac_inctrl */
+ 0x80, /* 07/07 - r_dac_inctrl */
+ 0x00, /* 08/08 - ply_dataform_reg */
+ 0x00, /* 09/09 - if_conf */
+ 0x00, /* 0a/10 - pin_ctrl */
+ 0x00, /* 0b/11 - err_init_reg */
+ 0x0a, /* 0c/12 - id_reg */
+ 0x00, /* 0d/13 - reserved */
+ 0x00, /* 0e/14 - ply_upcount_reg */
+ 0x00, /* 0f/15 - ply_lowcount_reg */
+ 0x88, /* 10/16 - reserved/l_a1_inctrl */
+ 0x88, /* 11/17 - reserved/r_a1_inctrl */
+ 0x88, /* 12/18 - l_line_inctrl */
+ 0x88, /* 13/19 - r_line_inctrl */
+ 0x88, /* 14/20 - l_mic_inctrl */
+ 0x88, /* 15/21 - r_mic_inctrl */
+ 0x80, /* 16/22 - l_out_outctrl */
+ 0x80, /* 17/23 - r_out_outctrl */
+ 0x00, /* 18/24 - reserved */
+ 0x00, /* 19/25 - reserved */
+ 0x00, /* 1a/26 - reserved */
+ 0x00, /* 1b/27 - reserved */
+ 0x00, /* 1c/28 - cap_dataform_reg */
+ 0x00, /* 1d/29 - reserved */
+ 0x00, /* 1e/30 - cap_upcount_reg */
+ 0x00 /* 1f/31 - cap_lowcount_reg */
+};
+
+/*
+ * Basic I/O functions
+ */
+
+static inline void wss_outb(struct snd_wss *chip, u8 offset, u8 val)
+{
+ outb(val, chip->port + offset);
+}
+
+static inline u8 wss_inb(struct snd_wss *chip, u8 offset)
+{
+ return inb(chip->port + offset);
+}
+
+static void snd_wss_wait(struct snd_wss *chip)
+{
+ int timeout;
+
+ for (timeout = 250;
+ timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
+ timeout--)
+ udelay(100);
+}
+
+static void snd_wss_outm(struct snd_wss *chip, unsigned char reg,
+ unsigned char mask, unsigned char value)
+{
+ unsigned char tmp = (chip->image[reg] & mask) | value;
+
+ snd_wss_wait(chip);
+#ifdef CONFIG_SND_DEBUG
+ if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
+ snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
+#endif
+ chip->image[reg] = tmp;
+ if (!chip->calibrate_mute) {
+ wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
+ wmb();
+ wss_outb(chip, CS4231P(REG), tmp);
+ mb();
+ }
+}
+
+static void snd_wss_dout(struct snd_wss *chip, unsigned char reg,
+ unsigned char value)
+{
+ int timeout;
+
+ for (timeout = 250;
+ timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
+ timeout--)
+ udelay(10);
+ wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
+ wss_outb(chip, CS4231P(REG), value);
+ mb();
+}
+
+void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char value)
+{
+ snd_wss_wait(chip);
+#ifdef CONFIG_SND_DEBUG
+ if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
+ snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
+#endif
+ wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
+ wss_outb(chip, CS4231P(REG), value);
+ chip->image[reg] = value;
+ mb();
+ snd_printdd("codec out - reg 0x%x = 0x%x\n",
+ chip->mce_bit | reg, value);
+}
+EXPORT_SYMBOL(snd_wss_out);
+
+unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg)
+{
+ snd_wss_wait(chip);
+#ifdef CONFIG_SND_DEBUG
+ if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
+ snd_printk("in: auto calibration time out - reg = 0x%x\n", reg);
+#endif
+ wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
+ mb();
+ return wss_inb(chip, CS4231P(REG));
+}
+EXPORT_SYMBOL(snd_wss_in);
+
+void snd_cs4236_ext_out(struct snd_wss *chip, unsigned char reg,
+ unsigned char val)
+{
+ wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
+ wss_outb(chip, CS4231P(REG),
+ reg | (chip->image[CS4236_EXT_REG] & 0x01));
+ wss_outb(chip, CS4231P(REG), val);
+ chip->eimage[CS4236_REG(reg)] = val;
+#if 0
+ printk("ext out : reg = 0x%x, val = 0x%x\n", reg, val);
+#endif
+}
+EXPORT_SYMBOL(snd_cs4236_ext_out);
+
+unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg)
+{
+ wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
+ wss_outb(chip, CS4231P(REG),
+ reg | (chip->image[CS4236_EXT_REG] & 0x01));
+#if 1
+ return wss_inb(chip, CS4231P(REG));
+#else
+ {
+ unsigned char res;
+ res = wss_inb(chip, CS4231P(REG));
+ printk("ext in : reg = 0x%x, val = 0x%x\n", reg, res);
+ return res;
+ }
+#endif
+}
+EXPORT_SYMBOL(snd_cs4236_ext_in);
+
+#if 0
+
+static void snd_wss_debug(struct snd_wss *chip)
+{
+ printk(KERN_DEBUG
+ "CS4231 REGS: INDEX = 0x%02x "
+ " STATUS = 0x%02x\n",
+ wss_inb(chip, CS4231P(REGSEL)),
+ wss_inb(chip, CS4231P(STATUS)));
+ printk(KERN_DEBUG
+ " 0x00: left input = 0x%02x "
+ " 0x10: alt 1 (CFIG 2) = 0x%02x\n",
+ snd_wss_in(chip, 0x00),
+ snd_wss_in(chip, 0x10));
+ printk(KERN_DEBUG
+ " 0x01: right input = 0x%02x "
+ " 0x11: alt 2 (CFIG 3) = 0x%02x\n",
+ snd_wss_in(chip, 0x01),
+ snd_wss_in(chip, 0x11));
+ printk(KERN_DEBUG
+ " 0x02: GF1 left input = 0x%02x "
+ " 0x12: left line in = 0x%02x\n",
+ snd_wss_in(chip, 0x02),
+ snd_wss_in(chip, 0x12));
+ printk(KERN_DEBUG
+ " 0x03: GF1 right input = 0x%02x "
+ " 0x13: right line in = 0x%02x\n",
+ snd_wss_in(chip, 0x03),
+ snd_wss_in(chip, 0x13));
+ printk(KERN_DEBUG
+ " 0x04: CD left input = 0x%02x "
+ " 0x14: timer low = 0x%02x\n",
+ snd_wss_in(chip, 0x04),
+ snd_wss_in(chip, 0x14));
+ printk(KERN_DEBUG
+ " 0x05: CD right input = 0x%02x "
+ " 0x15: timer high = 0x%02x\n",
+ snd_wss_in(chip, 0x05),
+ snd_wss_in(chip, 0x15));
+ printk(KERN_DEBUG
+ " 0x06: left output = 0x%02x "
+ " 0x16: left MIC (PnP) = 0x%02x\n",
+ snd_wss_in(chip, 0x06),
+ snd_wss_in(chip, 0x16));
+ printk(KERN_DEBUG
+ " 0x07: right output = 0x%02x "
+ " 0x17: right MIC (PnP) = 0x%02x\n",
+ snd_wss_in(chip, 0x07),
+ snd_wss_in(chip, 0x17));
+ printk(KERN_DEBUG
+ " 0x08: playback format = 0x%02x "
+ " 0x18: IRQ status = 0x%02x\n",
+ snd_wss_in(chip, 0x08),
+ snd_wss_in(chip, 0x18));
+ printk(KERN_DEBUG
+ " 0x09: iface (CFIG 1) = 0x%02x "
+ " 0x19: left line out = 0x%02x\n",
+ snd_wss_in(chip, 0x09),
+ snd_wss_in(chip, 0x19));
+ printk(KERN_DEBUG
+ " 0x0a: pin control = 0x%02x "
+ " 0x1a: mono control = 0x%02x\n",
+ snd_wss_in(chip, 0x0a),
+ snd_wss_in(chip, 0x1a));
+ printk(KERN_DEBUG
+ " 0x0b: init & status = 0x%02x "
+ " 0x1b: right line out = 0x%02x\n",
+ snd_wss_in(chip, 0x0b),
+ snd_wss_in(chip, 0x1b));
+ printk(KERN_DEBUG
+ " 0x0c: revision & mode = 0x%02x "
+ " 0x1c: record format = 0x%02x\n",
+ snd_wss_in(chip, 0x0c),
+ snd_wss_in(chip, 0x1c));
+ printk(KERN_DEBUG
+ " 0x0d: loopback = 0x%02x "
+ " 0x1d: var freq (PnP) = 0x%02x\n",
+ snd_wss_in(chip, 0x0d),
+ snd_wss_in(chip, 0x1d));
+ printk(KERN_DEBUG
+ " 0x0e: ply upr count = 0x%02x "
+ " 0x1e: ply lwr count = 0x%02x\n",
+ snd_wss_in(chip, 0x0e),
+ snd_wss_in(chip, 0x1e));
+ printk(KERN_DEBUG
+ " 0x0f: rec upr count = 0x%02x "
+ " 0x1f: rec lwr count = 0x%02x\n",
+ snd_wss_in(chip, 0x0f),
+ snd_wss_in(chip, 0x1f));
+}
+
+#endif
+
+/*
+ * CS4231 detection / MCE routines
+ */
+
+static void snd_wss_busy_wait(struct snd_wss *chip)
+{
+ int timeout;
+
+ /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
+ for (timeout = 5; timeout > 0; timeout--)
+ wss_inb(chip, CS4231P(REGSEL));
+ /* end of cleanup sequence */
+ for (timeout = 25000;
+ timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
+ timeout--)
+ udelay(10);
+}
+
+void snd_wss_mce_up(struct snd_wss *chip)
+{
+ unsigned long flags;
+ int timeout;
+
+ snd_wss_wait(chip);
+#ifdef CONFIG_SND_DEBUG
+ if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
+ snd_printk("mce_up - auto calibration time out (0)\n");
+#endif
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ chip->mce_bit |= CS4231_MCE;
+ timeout = wss_inb(chip, CS4231P(REGSEL));
+ if (timeout == 0x80)
+ snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
+ if (!(timeout & CS4231_MCE))
+ wss_outb(chip, CS4231P(REGSEL),
+ chip->mce_bit | (timeout & 0x1f));
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+}
+EXPORT_SYMBOL(snd_wss_mce_up);
+
+void snd_wss_mce_down(struct snd_wss *chip)
+{
+ unsigned long flags;
+ unsigned long end_time;
+ int timeout;
+ int hw_mask = WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK | WSS_HW_AD1848;
+
+ snd_wss_busy_wait(chip);
+
+#ifdef CONFIG_SND_DEBUG
+ if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
+ snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL));
+#endif
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ chip->mce_bit &= ~CS4231_MCE;
+ timeout = wss_inb(chip, CS4231P(REGSEL));
+ wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ if (timeout == 0x80)
+ snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
+ if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask))
+ return;
+
+ /*
+ * Wait for (possible -- during init auto-calibration may not be set)
+ * calibration process to start. Needs upto 5 sample periods on AD1848
+ * which at the slowest possible rate of 5.5125 kHz means 907 us.
+ */
+ msleep(1);
+
+ snd_printdd("(1) jiffies = %lu\n", jiffies);
+
+ /* check condition up to 250 ms */
+ end_time = jiffies + msecs_to_jiffies(250);
+ while (snd_wss_in(chip, CS4231_TEST_INIT) &
+ CS4231_CALIB_IN_PROGRESS) {
+
+ if (time_after(jiffies, end_time)) {
+ snd_printk(KERN_ERR "mce_down - "
+ "auto calibration time out (2)\n");
+ return;
+ }
+ msleep(1);
+ }
+
+ snd_printdd("(2) jiffies = %lu\n", jiffies);
+
+ /* check condition up to 100 ms */
+ end_time = jiffies + msecs_to_jiffies(100);
+ while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
+ if (time_after(jiffies, end_time)) {
+ snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
+ return;
+ }
+ msleep(1);
+ }
+
+ snd_printdd("(3) jiffies = %lu\n", jiffies);
+ snd_printd("mce_down - exit = 0x%x\n", wss_inb(chip, CS4231P(REGSEL)));
+}
+EXPORT_SYMBOL(snd_wss_mce_down);
+
+static unsigned int snd_wss_get_count(unsigned char format, unsigned int size)
+{
+ switch (format & 0xe0) {
+ case CS4231_LINEAR_16:
+ case CS4231_LINEAR_16_BIG:
+ size >>= 1;
+ break;
+ case CS4231_ADPCM_16:
+ return size >> 2;
+ }
+ if (format & CS4231_STEREO)
+ size >>= 1;
+ return size;
+}
+
+static int snd_wss_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+{
+ struct snd_wss *chip = snd_pcm_substream_chip(substream);
+ int result = 0;
+ unsigned int what;
+ struct snd_pcm_substream *s;
+ int do_start;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ do_start = 1; break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ do_start = 0; break;
+ default:
+ return -EINVAL;
+ }
+
+ what = 0;
+ snd_pcm_group_for_each_entry(s, substream) {
+ if (s == chip->playback_substream) {
+ what |= CS4231_PLAYBACK_ENABLE;
+ snd_pcm_trigger_done(s, substream);
+ } else if (s == chip->capture_substream) {
+ what |= CS4231_RECORD_ENABLE;
+ snd_pcm_trigger_done(s, substream);
+ }
+ }
+ spin_lock(&chip->reg_lock);
+ if (do_start) {
+ chip->image[CS4231_IFACE_CTRL] |= what;
+ if (chip->trigger)
+ chip->trigger(chip, what, 1);
+ } else {
+ chip->image[CS4231_IFACE_CTRL] &= ~what;
+ if (chip->trigger)
+ chip->trigger(chip, what, 0);
+ }
+ snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
+ spin_unlock(&chip->reg_lock);
+#if 0
+ snd_wss_debug(chip);
+#endif
+ return result;
+}
+
+/*
+ * CODEC I/O
+ */
+
+static unsigned char snd_wss_get_rate(unsigned int rate)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rates); i++)
+ if (rate == rates[i])
+ return freq_bits[i];
+ // snd_BUG();
+ return freq_bits[ARRAY_SIZE(rates) - 1];
+}
+
+static unsigned char snd_wss_get_format(struct snd_wss *chip,
+ int format,
+ int channels)
+{
+ unsigned char rformat;
+
+ rformat = CS4231_LINEAR_8;
+ switch (format) {
+ case SNDRV_PCM_FORMAT_MU_LAW: rformat = CS4231_ULAW_8; break;
+ case SNDRV_PCM_FORMAT_A_LAW: rformat = CS4231_ALAW_8; break;
+ case SNDRV_PCM_FORMAT_S16_LE: rformat = CS4231_LINEAR_16; break;
+ case SNDRV_PCM_FORMAT_S16_BE: rformat = CS4231_LINEAR_16_BIG; break;
+ case SNDRV_PCM_FORMAT_IMA_ADPCM: rformat = CS4231_ADPCM_16; break;
+ }
+ if (channels > 1)
+ rformat |= CS4231_STEREO;
+#if 0
+ snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
+#endif
+ return rformat;
+}
+
+static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute)
+{
+ unsigned long flags;
+
+ mute = mute ? 0x80 : 0;
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ if (chip->calibrate_mute == mute) {
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ return;
+ }
+ if (!mute) {
+ snd_wss_dout(chip, CS4231_LEFT_INPUT,
+ chip->image[CS4231_LEFT_INPUT]);
+ snd_wss_dout(chip, CS4231_RIGHT_INPUT,
+ chip->image[CS4231_RIGHT_INPUT]);
+ snd_wss_dout(chip, CS4231_LOOPBACK,
+ chip->image[CS4231_LOOPBACK]);
+ }
+ snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT,
+ mute | chip->image[CS4231_AUX1_LEFT_INPUT]);
+ snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT,
+ mute | chip->image[CS4231_AUX1_RIGHT_INPUT]);
+ snd_wss_dout(chip, CS4231_AUX2_LEFT_INPUT,
+ mute | chip->image[CS4231_AUX2_LEFT_INPUT]);
+ snd_wss_dout(chip, CS4231_AUX2_RIGHT_INPUT,
+ mute | chip->image[CS4231_AUX2_RIGHT_INPUT]);
+ snd_wss_dout(chip, CS4231_LEFT_OUTPUT,
+ mute | chip->image[CS4231_LEFT_OUTPUT]);
+ snd_wss_dout(chip, CS4231_RIGHT_OUTPUT,
+ mute | chip->image[CS4231_RIGHT_OUTPUT]);
+ if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
+ snd_wss_dout(chip, CS4231_LEFT_LINE_IN,
+ mute | chip->image[CS4231_LEFT_LINE_IN]);
+ snd_wss_dout(chip, CS4231_RIGHT_LINE_IN,
+ mute | chip->image[CS4231_RIGHT_LINE_IN]);
+ snd_wss_dout(chip, CS4231_MONO_CTRL,
+ mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);
+ }
+ if (chip->hardware == WSS_HW_INTERWAVE) {
+ snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT,
+ mute | chip->image[CS4231_LEFT_MIC_INPUT]);
+ snd_wss_dout(chip, CS4231_RIGHT_MIC_INPUT,
+ mute | chip->image[CS4231_RIGHT_MIC_INPUT]);
+ snd_wss_dout(chip, CS4231_LINE_LEFT_OUTPUT,
+ mute | chip->image[CS4231_LINE_LEFT_OUTPUT]);
+ snd_wss_dout(chip, CS4231_LINE_RIGHT_OUTPUT,
+ mute | chip->image[CS4231_LINE_RIGHT_OUTPUT]);
+ }
+ chip->calibrate_mute = mute;
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+}
+
+static void snd_wss_playback_format(struct snd_wss *chip,
+ struct snd_pcm_hw_params *params,
+ unsigned char pdfr)
+{
+ unsigned long flags;
+ int full_calib = 1;
+
+ mutex_lock(&chip->mce_mutex);
+ snd_wss_calibrate_mute(chip, 1);
+ if (chip->hardware == WSS_HW_CS4231A ||
+ (chip->hardware & WSS_HW_CS4232_MASK)) {
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (pdfr & 0x0f)) { /* rate is same? */
+ snd_wss_out(chip, CS4231_ALT_FEATURE_1,
+ chip->image[CS4231_ALT_FEATURE_1] | 0x10);
+ chip->image[CS4231_PLAYBK_FORMAT] = pdfr;
+ snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
+ chip->image[CS4231_PLAYBK_FORMAT]);
+ snd_wss_out(chip, CS4231_ALT_FEATURE_1,
+ chip->image[CS4231_ALT_FEATURE_1] &= ~0x10);
+ udelay(100); /* Fixes audible clicks at least on GUS MAX */
+ full_calib = 0;
+ }
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ }
+ if (full_calib) {
+ snd_wss_mce_up(chip);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ if (chip->hardware != WSS_HW_INTERWAVE && !chip->single_dma) {
+ if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)
+ pdfr = (pdfr & 0xf0) |
+ (chip->image[CS4231_REC_FORMAT] & 0x0f);
+ } else {
+ chip->image[CS4231_PLAYBK_FORMAT] = pdfr;
+ }
+ snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ if (chip->hardware == WSS_HW_OPL3SA2)
+ udelay(100); /* this seems to help */
+ snd_wss_mce_down(chip);
+ }
+ snd_wss_calibrate_mute(chip, 0);
+ mutex_unlock(&chip->mce_mutex);
+}
+
+static void snd_wss_capture_format(struct snd_wss *chip,
+ struct snd_pcm_hw_params *params,
+ unsigned char cdfr)
+{
+ unsigned long flags;
+ int full_calib = 1;
+
+ mutex_lock(&chip->mce_mutex);
+ snd_wss_calibrate_mute(chip, 1);
+ if (chip->hardware == WSS_HW_CS4231A ||
+ (chip->hardware & WSS_HW_CS4232_MASK)) {
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (cdfr & 0x0f) || /* rate is same? */
+ (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
+ snd_wss_out(chip, CS4231_ALT_FEATURE_1,
+ chip->image[CS4231_ALT_FEATURE_1] | 0x20);
+ snd_wss_out(chip, CS4231_REC_FORMAT,
+ chip->image[CS4231_REC_FORMAT] = cdfr);
+ snd_wss_out(chip, CS4231_ALT_FEATURE_1,
+ chip->image[CS4231_ALT_FEATURE_1] &= ~0x20);
+ full_calib = 0;
+ }
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ }
+ if (full_calib) {
+ snd_wss_mce_up(chip);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ if (chip->hardware != WSS_HW_INTERWAVE &&
+ !(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
+ if (chip->single_dma)
+ snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr);
+ else
+ snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
+ (chip->image[CS4231_PLAYBK_FORMAT] & 0xf0) |
+ (cdfr & 0x0f));
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ snd_wss_mce_down(chip);
+ snd_wss_mce_up(chip);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ }
+ if (chip->hardware & WSS_HW_AD1848_MASK)
+ snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr);
+ else
+ snd_wss_out(chip, CS4231_REC_FORMAT, cdfr);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ snd_wss_mce_down(chip);
+ }
+ snd_wss_calibrate_mute(chip, 0);
+ mutex_unlock(&chip->mce_mutex);
+}
+
+/*
+ * Timer interface
+ */
+
+static unsigned long snd_wss_timer_resolution(struct snd_timer *timer)
+{
+ struct snd_wss *chip = snd_timer_chip(timer);
+ if (chip->hardware & WSS_HW_CS4236B_MASK)
+ return 14467;
+ else
+ return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920;
+}
+
+static int snd_wss_timer_start(struct snd_timer *timer)
+{
+ unsigned long flags;
+ unsigned int ticks;
+ struct snd_wss *chip = snd_timer_chip(timer);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ ticks = timer->sticks;
+ if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 ||
+ (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] ||
+ (unsigned char)ticks != chip->image[CS4231_TIMER_LOW]) {
+ chip->image[CS4231_TIMER_HIGH] = (unsigned char) (ticks >> 8);
+ snd_wss_out(chip, CS4231_TIMER_HIGH,
+ chip->image[CS4231_TIMER_HIGH]);
+ chip->image[CS4231_TIMER_LOW] = (unsigned char) ticks;
+ snd_wss_out(chip, CS4231_TIMER_LOW,
+ chip->image[CS4231_TIMER_LOW]);
+ snd_wss_out(chip, CS4231_ALT_FEATURE_1,
+ chip->image[CS4231_ALT_FEATURE_1] |
+ CS4231_TIMER_ENABLE);
+ }
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ return 0;
+}
+
+static int snd_wss_timer_stop(struct snd_timer *timer)
+{
+ unsigned long flags;
+ struct snd_wss *chip = snd_timer_chip(timer);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE;
+ snd_wss_out(chip, CS4231_ALT_FEATURE_1,
+ chip->image[CS4231_ALT_FEATURE_1]);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ return 0;
+}
+
+static void snd_wss_init(struct snd_wss *chip)
+{
+ unsigned long flags;
+
+ snd_wss_mce_down(chip);
+
+#ifdef SNDRV_DEBUG_MCE
+ snd_printk("init: (1)\n");
+#endif
+ snd_wss_mce_up(chip);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |
+ CS4231_PLAYBACK_PIO |
+ CS4231_RECORD_ENABLE |
+ CS4231_RECORD_PIO |
+ CS4231_CALIB_MODE);
+ chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB;
+ snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ snd_wss_mce_down(chip);
+
+#ifdef SNDRV_DEBUG_MCE
+ snd_printk("init: (2)\n");
+#endif
+
+ snd_wss_mce_up(chip);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ snd_wss_out(chip,
+ CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ snd_wss_mce_down(chip);
+
+#ifdef SNDRV_DEBUG_MCE
+ snd_printk("init: (3) - afei = 0x%x\n",
+ chip->image[CS4231_ALT_FEATURE_1]);
+#endif
+
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ snd_wss_out(chip, CS4231_ALT_FEATURE_2,
+ chip->image[CS4231_ALT_FEATURE_2]);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+
+ snd_wss_mce_up(chip);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
+ chip->image[CS4231_PLAYBK_FORMAT]);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ snd_wss_mce_down(chip);
+
+#ifdef SNDRV_DEBUG_MCE
+ snd_printk("init: (4)\n");
+#endif
+
+ snd_wss_mce_up(chip);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ if (!(chip->hardware & WSS_HW_AD1848_MASK))
+ snd_wss_out(chip, CS4231_REC_FORMAT,
+ chip->image[CS4231_REC_FORMAT]);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ snd_wss_mce_down(chip);
+
+#ifdef SNDRV_DEBUG_MCE
+ snd_printk("init: (5)\n");
+#endif
+}
+
+static int snd_wss_open(struct snd_wss *chip, unsigned int mode)
+{
+ unsigned long flags;
+
+ mutex_lock(&chip->open_mutex);
+ if ((chip->mode & mode) ||
+ ((chip->mode & WSS_MODE_OPEN) && chip->single_dma)) {
+ mutex_unlock(&chip->open_mutex);
+ return -EAGAIN;
+ }
+ if (chip->mode & WSS_MODE_OPEN) {
+ chip->mode |= mode;
+ mutex_unlock(&chip->open_mutex);
+ return 0;
+ }
+ /* ok. now enable and ack CODEC IRQ */
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
+ snd_wss_out(chip, CS4231_IRQ_STATUS,
+ CS4231_PLAYBACK_IRQ |
+ CS4231_RECORD_IRQ |
+ CS4231_TIMER_IRQ);
+ snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
+ }
+ wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
+ wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
+ chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE;
+ snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
+ if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
+ snd_wss_out(chip, CS4231_IRQ_STATUS,
+ CS4231_PLAYBACK_IRQ |
+ CS4231_RECORD_IRQ |
+ CS4231_TIMER_IRQ);
+ snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
+ }
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+
+ chip->mode = mode;
+ mutex_unlock(&chip->open_mutex);
+ return 0;
+}
+
+static void snd_wss_close(struct snd_wss *chip, unsigned int mode)
+{
+ unsigned long flags;
+
+ mutex_lock(&chip->open_mutex);
+ chip->mode &= ~mode;
+ if (chip->mode & WSS_MODE_OPEN) {
+ mutex_unlock(&chip->open_mutex);
+ return;
+ }
+ snd_wss_calibrate_mute(chip, 1);
+
+ /* disable IRQ */
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ if (!(chip->hardware & WSS_HW_AD1848_MASK))
+ snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
+ wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
+ wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
+ chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE;
+ snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
+
+ /* now disable record & playback */
+
+ if (chip->image[CS4231_IFACE_CTRL] & (CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
+ CS4231_RECORD_ENABLE | CS4231_RECORD_PIO)) {
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ snd_wss_mce_up(chip);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
+ CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
+ snd_wss_out(chip, CS4231_IFACE_CTRL,
+ chip->image[CS4231_IFACE_CTRL]);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ snd_wss_mce_down(chip);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ }
+
+ /* clear IRQ again */
+ if (!(chip->hardware & WSS_HW_AD1848_MASK))
+ snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
+ wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
+ wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+
+ snd_wss_calibrate_mute(chip, 0);
+
+ chip->mode = 0;
+ mutex_unlock(&chip->open_mutex);
+}
+
+/*
+ * timer open/close
+ */
+
+static int snd_wss_timer_open(struct snd_timer *timer)
+{
+ struct snd_wss *chip = snd_timer_chip(timer);
+ snd_wss_open(chip, WSS_MODE_TIMER);
+ return 0;
+}
+
+static int snd_wss_timer_close(struct snd_timer *timer)
+{
+ struct snd_wss *chip = snd_timer_chip(timer);
+ snd_wss_close(chip, WSS_MODE_TIMER);
+ return 0;
+}
+
+static struct snd_timer_hardware snd_wss_timer_table =
+{
+ .flags = SNDRV_TIMER_HW_AUTO,
+ .resolution = 9945,
+ .ticks = 65535,
+ .open = snd_wss_timer_open,
+ .close = snd_wss_timer_close,
+ .c_resolution = snd_wss_timer_resolution,
+ .start = snd_wss_timer_start,
+ .stop = snd_wss_timer_stop,
+};
+
+/*
+ * ok.. exported functions..
+ */
+
+static int snd_wss_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ struct snd_wss *chip = snd_pcm_substream_chip(substream);
+ unsigned char new_pdfr;
+ int err;
+
+ if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
+ return err;
+ new_pdfr = snd_wss_get_format(chip, params_format(hw_params),
+ params_channels(hw_params)) |
+ snd_wss_get_rate(params_rate(hw_params));
+ chip->set_playback_format(chip, hw_params, new_pdfr);
+ return 0;
+}
+
+static int snd_wss_playback_hw_free(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static int snd_wss_playback_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_wss *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned long flags;
+ unsigned int size = snd_pcm_lib_buffer_bytes(substream);
+ unsigned int count = snd_pcm_lib_period_bytes(substream);
+
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ chip->p_dma_size = size;
+ chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO);
+ snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
+ count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT], count) - 1;
+ snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
+ snd_wss_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8));
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+#if 0
+ snd_wss_debug(chip);
+#endif
+ return 0;
+}
+
+static int snd_wss_capture_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ struct snd_wss *chip = snd_pcm_substream_chip(substream);
+ unsigned char new_cdfr;
+ int err;
+
+ if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
+ return err;
+ new_cdfr = snd_wss_get_format(chip, params_format(hw_params),
+ params_channels(hw_params)) |
+ snd_wss_get_rate(params_rate(hw_params));
+ chip->set_capture_format(chip, hw_params, new_cdfr);
+ return 0;
+}
+
+static int snd_wss_capture_hw_free(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static int snd_wss_capture_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_wss *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned long flags;
+ unsigned int size = snd_pcm_lib_buffer_bytes(substream);
+ unsigned int count = snd_pcm_lib_period_bytes(substream);
+
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ chip->c_dma_size = size;
+ chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
+ snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
+ if (chip->hardware & WSS_HW_AD1848_MASK)
+ count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT],
+ count);
+ else
+ count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT],
+ count);
+ count--;
+ if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) {
+ snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
+ snd_wss_out(chip, CS4231_PLY_UPR_CNT,
+ (unsigned char) (count >> 8));
+ } else {
+ snd_wss_out(chip, CS4231_REC_LWR_CNT, (unsigned char) count);
+ snd_wss_out(chip, CS4231_REC_UPR_CNT,
+ (unsigned char) (count >> 8));
+ }
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ return 0;
+}
+
+void snd_wss_overrange(struct snd_wss *chip)
+{
+ unsigned long flags;
+ unsigned char res;
+
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ res = snd_wss_in(chip, CS4231_TEST_INIT);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ if (res & (0x08 | 0x02)) /* detect overrange only above 0dB; may be user selectable? */
+ chip->capture_substream->runtime->overrange++;
+}
+EXPORT_SYMBOL(snd_wss_overrange);
+
+irqreturn_t snd_wss_interrupt(int irq, void *dev_id)
+{
+ struct snd_wss *chip = dev_id;
+ unsigned char status;
+
+ if (chip->hardware & WSS_HW_AD1848_MASK)
+ /* pretend it was the only possible irq for AD1848 */
+ status = CS4231_PLAYBACK_IRQ;
+ else
+ status = snd_wss_in(chip, CS4231_IRQ_STATUS);
+ if (status & CS4231_TIMER_IRQ) {
+ if (chip->timer)
+ snd_timer_interrupt(chip->timer, chip->timer->sticks);
+ }
+ if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) {
+ if (status & CS4231_PLAYBACK_IRQ) {
+ if (chip->mode & WSS_MODE_PLAY) {
+ if (chip->playback_substream)
+ snd_pcm_period_elapsed(chip->playback_substream);
+ }
+ if (chip->mode & WSS_MODE_RECORD) {
+ if (chip->capture_substream) {
+ snd_wss_overrange(chip);
+ snd_pcm_period_elapsed(chip->capture_substream);
+ }
+ }
+ }
+ } else {
+ if (status & CS4231_PLAYBACK_IRQ) {
+ if (chip->playback_substream)
+ snd_pcm_period_elapsed(chip->playback_substream);
+ }
+ if (status & CS4231_RECORD_IRQ) {
+ if (chip->capture_substream) {
+ snd_wss_overrange(chip);
+ snd_pcm_period_elapsed(chip->capture_substream);
+ }
+ }
+ }
+
+ spin_lock(&chip->reg_lock);
+ status = ~CS4231_ALL_IRQS | ~status;
+ if (chip->hardware & WSS_HW_AD1848_MASK)
+ wss_outb(chip, CS4231P(STATUS), 0);
+ else
+ snd_wss_outm(chip, CS4231_IRQ_STATUS, status, 0);
+ spin_unlock(&chip->reg_lock);
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(snd_wss_interrupt);
+
+static snd_pcm_uframes_t snd_wss_playback_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_wss *chip = snd_pcm_substream_chip(substream);
+ size_t ptr;
+
+ if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
+ return 0;
+ ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);
+ return bytes_to_frames(substream->runtime, ptr);
+}
+
+static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_wss *chip = snd_pcm_substream_chip(substream);
+ size_t ptr;
+
+ if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
+ return 0;
+ ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
+ return bytes_to_frames(substream->runtime, ptr);
+}
+
+/*
+
+ */
+
+static int snd_ad1848_probe(struct snd_wss *chip)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+ unsigned long flags;
+ unsigned char r;
+ unsigned short hardware = 0;
+ int err = 0;
+ int i;
+
+ while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
+ if (time_after(jiffies, timeout))
+ return -ENODEV;
+ cond_resched();
+ }
+ spin_lock_irqsave(&chip->reg_lock, flags);
+
+ /* set CS423x MODE 1 */
+ snd_wss_dout(chip, CS4231_MISC_INFO, 0);
+
+ snd_wss_dout(chip, CS4231_RIGHT_INPUT, 0x45); /* 0x55 & ~0x10 */
+ r = snd_wss_in(chip, CS4231_RIGHT_INPUT);
+ if (r != 0x45) {
+ /* RMGE always high on AD1847 */
+ if ((r & ~CS4231_ENABLE_MIC_GAIN) != 0x45) {
+ err = -ENODEV;
+ goto out;
+ }
+ hardware = WSS_HW_AD1847;
+ } else {
+ snd_wss_dout(chip, CS4231_LEFT_INPUT, 0xaa);
+ r = snd_wss_in(chip, CS4231_LEFT_INPUT);
+ /* L/RMGE always low on AT2320 */
+ if ((r | CS4231_ENABLE_MIC_GAIN) != 0xaa) {
+ err = -ENODEV;
+ goto out;
+ }
+ }
+
+ /* clear pending IRQ */
+ wss_inb(chip, CS4231P(STATUS));
+ wss_outb(chip, CS4231P(STATUS), 0);
+ mb();
+
+ if ((chip->hardware & WSS_HW_TYPE_MASK) != WSS_HW_DETECT)
+ goto out;
+
+ if (hardware) {
+ chip->hardware = hardware;
+ goto out;
+ }
+
+ r = snd_wss_in(chip, CS4231_MISC_INFO);
+
+ /* set CS423x MODE 2 */
+ snd_wss_dout(chip, CS4231_MISC_INFO, CS4231_MODE2);
+ for (i = 0; i < 16; i++) {
+ if (snd_wss_in(chip, i) != snd_wss_in(chip, 16 + i)) {
+ /* we have more than 16 registers: check ID */
+ if ((r & 0xf) != 0xa)
+ goto out_mode;
+ /*
+ * on CMI8330, CS4231_VERSION is volume control and
+ * can be set to 0
+ */
+ snd_wss_dout(chip, CS4231_VERSION, 0);
+ r = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
+ if (!r)
+ chip->hardware = WSS_HW_CMI8330;
+ goto out_mode;
+ }
+ }
+ if (r & 0x80)
+ chip->hardware = WSS_HW_CS4248;
+ else
+ chip->hardware = WSS_HW_AD1848;
+out_mode:
+ snd_wss_dout(chip, CS4231_MISC_INFO, 0);
+out:
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ return err;
+}
+
+static int snd_wss_probe(struct snd_wss *chip)
+{
+ unsigned long flags;
+ int i, id, rev, regnum;
+ unsigned char *ptr;
+ unsigned int hw;
+
+ id = snd_ad1848_probe(chip);
+ if (id < 0)
+ return id;
+
+ hw = chip->hardware;
+ if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) {
+ for (i = 0; i < 50; i++) {
+ mb();
+ if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
+ msleep(2);
+ else {
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ snd_wss_out(chip, CS4231_MISC_INFO,
+ CS4231_MODE2);
+ id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f;
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ if (id == 0x0a)
+ break; /* this is valid value */
+ }
+ }
+ snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id);
+ if (id != 0x0a)
+ return -ENODEV; /* no valid device found */
+
+ rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
+ snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev);
+ if (rev == 0x80) {
+ unsigned char tmp = snd_wss_in(chip, 23);
+ snd_wss_out(chip, 23, ~tmp);
+ if (snd_wss_in(chip, 23) != tmp)
+ chip->hardware = WSS_HW_AD1845;
+ else
+ chip->hardware = WSS_HW_CS4231;
+ } else if (rev == 0xa0) {
+ chip->hardware = WSS_HW_CS4231A;
+ } else if (rev == 0xa2) {
+ chip->hardware = WSS_HW_CS4232;
+ } else if (rev == 0xb2) {
+ chip->hardware = WSS_HW_CS4232A;
+ } else if (rev == 0x83) {
+ chip->hardware = WSS_HW_CS4236;
+ } else if (rev == 0x03) {
+ chip->hardware = WSS_HW_CS4236B;
+ } else {
+ snd_printk("unknown CS chip with version 0x%x\n", rev);
+ return -ENODEV; /* unknown CS4231 chip? */
+ }
+ }
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ wss_inb(chip, CS4231P(STATUS)); /* clear any pendings IRQ */
+ wss_outb(chip, CS4231P(STATUS), 0);
+ mb();
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+
+ if (!(chip->hardware & WSS_HW_AD1848_MASK))
+ chip->image[CS4231_MISC_INFO] = CS4231_MODE2;
+ switch (chip->hardware) {
+ case WSS_HW_INTERWAVE:
+ chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3;
+ break;
+ case WSS_HW_CS4235:
+ case WSS_HW_CS4236B:
+ case WSS_HW_CS4237B:
+ case WSS_HW_CS4238B:
+ case WSS_HW_CS4239:
+ if (hw == WSS_HW_DETECT3)
+ chip->image[CS4231_MISC_INFO] = CS4231_4236_MODE3;
+ else
+ chip->hardware = WSS_HW_CS4236;
+ break;
+ }
+
+ chip->image[CS4231_IFACE_CTRL] =
+ (chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) |
+ (chip->single_dma ? CS4231_SINGLE_DMA : 0);
+ if (chip->hardware != WSS_HW_OPTI93X) {
+ chip->image[CS4231_ALT_FEATURE_1] = 0x80;
+ chip->image[CS4231_ALT_FEATURE_2] =
+ chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01;
+ }
+ ptr = (unsigned char *) &chip->image;
+ regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32;
+ snd_wss_mce_down(chip);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ for (i = 0; i < regnum; i++) /* ok.. fill all registers */
+ snd_wss_out(chip, i, *ptr++);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ snd_wss_mce_up(chip);
+ snd_wss_mce_down(chip);
+
+ mdelay(2);
+
+ /* ok.. try check hardware version for CS4236+ chips */
+ if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) {
+ if (chip->hardware == WSS_HW_CS4236B) {
+ rev = snd_cs4236_ext_in(chip, CS4236_VERSION);
+ snd_cs4236_ext_out(chip, CS4236_VERSION, 0xff);
+ id = snd_cs4236_ext_in(chip, CS4236_VERSION);
+ snd_cs4236_ext_out(chip, CS4236_VERSION, rev);
+ snd_printdd("CS4231: ext version; rev = 0x%x, id = 0x%x\n", rev, id);
+ if ((id & 0x1f) == 0x1d) { /* CS4235 */
+ chip->hardware = WSS_HW_CS4235;
+ switch (id >> 5) {
+ case 4:
+ case 5:
+ case 6:
+ break;
+ default:
+ snd_printk("unknown CS4235 chip (enhanced version = 0x%x)\n", id);
+ }
+ } else if ((id & 0x1f) == 0x0b) { /* CS4236/B */
+ switch (id >> 5) {
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ chip->hardware = WSS_HW_CS4236B;
+ break;
+ default:
+ snd_printk("unknown CS4236 chip (enhanced version = 0x%x)\n", id);
+ }
+ } else if ((id & 0x1f) == 0x08) { /* CS4237B */
+ chip->hardware = WSS_HW_CS4237B;
+ switch (id >> 5) {
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ break;
+ default:
+ snd_printk("unknown CS4237B chip (enhanced version = 0x%x)\n", id);
+ }
+ } else if ((id & 0x1f) == 0x09) { /* CS4238B */
+ chip->hardware = WSS_HW_CS4238B;
+ switch (id >> 5) {
+ case 5:
+ case 6:
+ case 7:
+ break;
+ default:
+ snd_printk("unknown CS4238B chip (enhanced version = 0x%x)\n", id);
+ }
+ } else if ((id & 0x1f) == 0x1e) { /* CS4239 */
+ chip->hardware = WSS_HW_CS4239;
+ switch (id >> 5) {
+ case 4:
+ case 5:
+ case 6:
+ break;
+ default:
+ snd_printk("unknown CS4239 chip (enhanced version = 0x%x)\n", id);
+ }
+ } else {
+ snd_printk("unknown CS4236/CS423xB chip (enhanced version = 0x%x)\n", id);
+ }
+ }
+ }
+ return 0; /* all things are ok.. */
+}
+
+/*
+
+ */
+
+static struct snd_pcm_hardware snd_wss_playback =
+{
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_RESUME |
+ SNDRV_PCM_INFO_SYNC_START),
+ .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
+ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
+ .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 5510,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = (128*1024),
+ .period_bytes_min = 64,
+ .period_bytes_max = (128*1024),
+ .periods_min = 1,
+ .periods_max = 1024,
+ .fifo_size = 0,
+};
+
+static struct snd_pcm_hardware snd_wss_capture =
+{
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_RESUME |
+ SNDRV_PCM_INFO_SYNC_START),
+ .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
+ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
+ .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 5510,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = (128*1024),
+ .period_bytes_min = 64,
+ .period_bytes_max = (128*1024),
+ .periods_min = 1,
+ .periods_max = 1024,
+ .fifo_size = 0,
+};
+
+/*
+
+ */
+
+static int snd_wss_playback_open(struct snd_pcm_substream *substream)
+{
+ struct snd_wss *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int err;
+
+ runtime->hw = snd_wss_playback;
+
+ /* hardware limitation of older chipsets */
+ if (chip->hardware & WSS_HW_AD1848_MASK)
+ runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
+ SNDRV_PCM_FMTBIT_S16_BE);
+
+ /* hardware bug in InterWave chipset */
+ if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3)
+ runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW;
+
+ /* hardware limitation of cheap chips */
+ if (chip->hardware == WSS_HW_CS4235 ||
+ chip->hardware == WSS_HW_CS4239)
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
+
+ snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
+ snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
+
+ if (chip->claim_dma) {
+ if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0)
+ return err;
+ }
+
+ err = snd_wss_open(chip, WSS_MODE_PLAY);
+ if (err < 0) {
+ if (chip->release_dma)
+ chip->release_dma(chip, chip->dma_private_data, chip->dma1);
+ snd_free_pages(runtime->dma_area, runtime->dma_bytes);
+ return err;
+ }
+ chip->playback_substream = substream;
+ snd_pcm_set_sync(substream);
+ chip->rate_constraint(runtime);
+ return 0;
+}
+
+static int snd_wss_capture_open(struct snd_pcm_substream *substream)
+{
+ struct snd_wss *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int err;
+
+ runtime->hw = snd_wss_capture;
+
+ /* hardware limitation of older chipsets */
+ if (chip->hardware & WSS_HW_AD1848_MASK)
+ runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
+ SNDRV_PCM_FMTBIT_S16_BE);
+
+ /* hardware limitation of cheap chips */
+ if (chip->hardware == WSS_HW_CS4235 ||
+ chip->hardware == WSS_HW_CS4239 ||
+ chip->hardware == WSS_HW_OPTI93X)
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 |
+ SNDRV_PCM_FMTBIT_S16_LE;
+
+ snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
+ snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
+
+ if (chip->claim_dma) {
+ if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0)
+ return err;
+ }
+
+ err = snd_wss_open(chip, WSS_MODE_RECORD);
+ if (err < 0) {
+ if (chip->release_dma)
+ chip->release_dma(chip, chip->dma_private_data, chip->dma2);
+ snd_free_pages(runtime->dma_area, runtime->dma_bytes);
+ return err;
+ }
+ chip->capture_substream = substream;
+ snd_pcm_set_sync(substream);
+ chip->rate_constraint(runtime);
+ return 0;
+}
+
+static int snd_wss_playback_close(struct snd_pcm_substream *substream)
+{
+ struct snd_wss *chip = snd_pcm_substream_chip(substream);
+
+ chip->playback_substream = NULL;
+ snd_wss_close(chip, WSS_MODE_PLAY);
+ return 0;
+}
+
+static int snd_wss_capture_close(struct snd_pcm_substream *substream)
+{
+ struct snd_wss *chip = snd_pcm_substream_chip(substream);
+
+ chip->capture_substream = NULL;
+ snd_wss_close(chip, WSS_MODE_RECORD);
+ return 0;
+}
+
+static void snd_wss_thinkpad_twiddle(struct snd_wss *chip, int on)
+{
+ int tmp;
+
+ if (!chip->thinkpad_flag)
+ return;
+
+ outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
+ tmp = inb(AD1848_THINKPAD_CTL_PORT2);
+
+ if (on)
+ /* turn it on */
+ tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
+ else
+ /* turn it off */
+ tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
+
+ outb(tmp, AD1848_THINKPAD_CTL_PORT2);
+}
+
+#ifdef CONFIG_PM
+
+/* lowlevel suspend callback for CS4231 */
+static void snd_wss_suspend(struct snd_wss *chip)
+{
+ int reg;
+ unsigned long flags;
+
+ snd_pcm_suspend_all(chip->pcm);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ for (reg = 0; reg < 32; reg++)
+ chip->image[reg] = snd_wss_in(chip, reg);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ if (chip->thinkpad_flag)
+ snd_wss_thinkpad_twiddle(chip, 0);
+}
+
+/* lowlevel resume callback for CS4231 */
+static void snd_wss_resume(struct snd_wss *chip)
+{
+ int reg;
+ unsigned long flags;
+ /* int timeout; */
+
+ if (chip->thinkpad_flag)
+ snd_wss_thinkpad_twiddle(chip, 1);
+ snd_wss_mce_up(chip);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ for (reg = 0; reg < 32; reg++) {
+ switch (reg) {
+ case CS4231_VERSION:
+ break;
+ default:
+ snd_wss_out(chip, reg, chip->image[reg]);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+#if 1
+ snd_wss_mce_down(chip);
+#else
+ /* The following is a workaround to avoid freeze after resume on TP600E.
+ This is the first half of copy of snd_wss_mce_down(), but doesn't
+ include rescheduling. -- iwai
+ */
+ snd_wss_busy_wait(chip);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ chip->mce_bit &= ~CS4231_MCE;
+ timeout = wss_inb(chip, CS4231P(REGSEL));
+ wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ if (timeout == 0x80)
+ snd_printk("down [0x%lx]: serious init problem - codec still busy\n", chip->port);
+ if ((timeout & CS4231_MCE) == 0 ||
+ !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) {
+ return;
+ }
+ snd_wss_busy_wait(chip);
+#endif
+}
+#endif /* CONFIG_PM */
+
+static int snd_wss_free(struct snd_wss *chip)
+{
+ release_and_free_resource(chip->res_port);
+ release_and_free_resource(chip->res_cport);
+ if (chip->irq >= 0) {
+ disable_irq(chip->irq);
+ if (!(chip->hwshare & WSS_HWSHARE_IRQ))
+ free_irq(chip->irq, (void *) chip);
+ }
+ if (!(chip->hwshare & WSS_HWSHARE_DMA1) && chip->dma1 >= 0) {
+ snd_dma_disable(chip->dma1);
+ free_dma(chip->dma1);
+ }
+ if (!(chip->hwshare & WSS_HWSHARE_DMA2) &&
+ chip->dma2 >= 0 && chip->dma2 != chip->dma1) {
+ snd_dma_disable(chip->dma2);
+ free_dma(chip->dma2);
+ }
+ if (chip->timer)
+ snd_device_free(chip->card, chip->timer);
+ kfree(chip);
+ return 0;
+}
+
+static int snd_wss_dev_free(struct snd_device *device)
+{
+ struct snd_wss *chip = device->device_data;
+ return snd_wss_free(chip);
+}
+
+const char *snd_wss_chip_id(struct snd_wss *chip)
+{
+ switch (chip->hardware) {
+ case WSS_HW_CS4231:
+ return "CS4231";
+ case WSS_HW_CS4231A:
+ return "CS4231A";
+ case WSS_HW_CS4232:
+ return "CS4232";
+ case WSS_HW_CS4232A:
+ return "CS4232A";
+ case WSS_HW_CS4235:
+ return "CS4235";
+ case WSS_HW_CS4236:
+ return "CS4236";
+ case WSS_HW_CS4236B:
+ return "CS4236B";
+ case WSS_HW_CS4237B:
+ return "CS4237B";
+ case WSS_HW_CS4238B:
+ return "CS4238B";
+ case WSS_HW_CS4239:
+ return "CS4239";
+ case WSS_HW_INTERWAVE:
+ return "AMD InterWave";
+ case WSS_HW_OPL3SA2:
+ return chip->card->shortname;
+ case WSS_HW_AD1845:
+ return "AD1845";
+ case WSS_HW_OPTI93X:
+ return "OPTi 93x";
+ case WSS_HW_AD1847:
+ return "AD1847";
+ case WSS_HW_AD1848:
+ return "AD1848";
+ case WSS_HW_CS4248:
+ return "CS4248";
+ case WSS_HW_CMI8330:
+ return "CMI8330/C3D";
+ default:
+ return "???";
+ }
+}
+EXPORT_SYMBOL(snd_wss_chip_id);
+
+static int snd_wss_new(struct snd_card *card,
+ unsigned short hardware,
+ unsigned short hwshare,
+ struct snd_wss **rchip)
+{
+ struct snd_wss *chip;
+
+ *rchip = NULL;
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+ chip->hardware = hardware;
+ chip->hwshare = hwshare;
+
+ spin_lock_init(&chip->reg_lock);
+ mutex_init(&chip->mce_mutex);
+ mutex_init(&chip->open_mutex);
+ chip->card = card;
+ chip->rate_constraint = snd_wss_xrate;
+ chip->set_playback_format = snd_wss_playback_format;
+ chip->set_capture_format = snd_wss_capture_format;
+ if (chip->hardware == WSS_HW_OPTI93X)
+ memcpy(&chip->image, &snd_opti93x_original_image,
+ sizeof(snd_opti93x_original_image));
+ else
+ memcpy(&chip->image, &snd_wss_original_image,
+ sizeof(snd_wss_original_image));
+ if (chip->hardware & WSS_HW_AD1848_MASK) {
+ chip->image[CS4231_PIN_CTRL] = 0;
+ chip->image[CS4231_TEST_INIT] = 0;
+ }
+
+ *rchip = chip;
+ return 0;
+}
+
+int snd_wss_create(struct snd_card *card,
+ unsigned long port,
+ unsigned long cport,
+ int irq, int dma1, int dma2,
+ unsigned short hardware,
+ unsigned short hwshare,
+ struct snd_wss **rchip)
+{
+ static struct snd_device_ops ops = {
+ .dev_free = snd_wss_dev_free,
+ };
+ struct snd_wss *chip;
+ int err;
+
+ err = snd_wss_new(card, hardware, hwshare, &chip);
+ if (err < 0)
+ return err;
+
+ chip->irq = -1;
+ chip->dma1 = -1;
+ chip->dma2 = -1;
+
+ chip->res_port = request_region(port, 4, "WSS");
+ if (!chip->res_port) {
+ snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port);
+ snd_wss_free(chip);
+ return -EBUSY;
+ }
+ chip->port = port;
+ if ((long)cport >= 0) {
+ chip->res_cport = request_region(cport, 8, "CS4232 Control");
+ if (!chip->res_cport) {
+ snd_printk(KERN_ERR
+ "wss: can't grab control port 0x%lx\n", cport);
+ snd_wss_free(chip);
+ return -ENODEV;
+ }
+ }
+ chip->cport = cport;
+ if (!(hwshare & WSS_HWSHARE_IRQ))
+ if (request_irq(irq, snd_wss_interrupt, IRQF_DISABLED,
+ "WSS", (void *) chip)) {
+ snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq);
+ snd_wss_free(chip);
+ return -EBUSY;
+ }
+ chip->irq = irq;
+ if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) {
+ snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1);
+ snd_wss_free(chip);
+ return -EBUSY;
+ }
+ chip->dma1 = dma1;
+ if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 &&
+ dma2 >= 0 && request_dma(dma2, "WSS - 2")) {
+ snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2);
+ snd_wss_free(chip);
+ return -EBUSY;
+ }
+ if (dma1 == dma2 || dma2 < 0) {
+ chip->single_dma = 1;
+ chip->dma2 = chip->dma1;
+ } else
+ chip->dma2 = dma2;
+
+ if (hardware == WSS_HW_THINKPAD) {
+ chip->thinkpad_flag = 1;
+ chip->hardware = WSS_HW_DETECT; /* reset */
+ snd_wss_thinkpad_twiddle(chip, 1);
+ }
+
+ /* global setup */
+ if (snd_wss_probe(chip) < 0) {
+ snd_wss_free(chip);
+ return -ENODEV;
+ }
+ snd_wss_init(chip);
+
+#if 0
+ if (chip->hardware & WSS_HW_CS4232_MASK) {
+ if (chip->res_cport == NULL)
+ snd_printk("CS4232 control port features are not accessible\n");
+ }
+#endif
+
+ /* Register device */
+ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+ if (err < 0) {
+ snd_wss_free(chip);
+ return err;
+ }
+
+#ifdef CONFIG_PM
+ /* Power Management */
+ chip->suspend = snd_wss_suspend;
+ chip->resume = snd_wss_resume;
+#endif
+
+ *rchip = chip;
+ return 0;
+}
+EXPORT_SYMBOL(snd_wss_create);
+
+static struct snd_pcm_ops snd_wss_playback_ops = {
+ .open = snd_wss_playback_open,
+ .close = snd_wss_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_wss_playback_hw_params,
+ .hw_free = snd_wss_playback_hw_free,
+ .prepare = snd_wss_playback_prepare,
+ .trigger = snd_wss_trigger,
+ .pointer = snd_wss_playback_pointer,
+};
+
+static struct snd_pcm_ops snd_wss_capture_ops = {
+ .open = snd_wss_capture_open,
+ .close = snd_wss_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_wss_capture_hw_params,
+ .hw_free = snd_wss_capture_hw_free,
+ .prepare = snd_wss_capture_prepare,
+ .trigger = snd_wss_trigger,
+ .pointer = snd_wss_capture_pointer,
+};
+
+int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
+{
+ struct snd_pcm *pcm;
+ int err;
+
+ err = snd_pcm_new(chip->card, "WSS", device, 1, 1, &pcm);
+ if (err < 0)
+ return err;
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops);
+
+ /* global setup */
+ pcm->private_data = chip;
+ pcm->info_flags = 0;
+ if (chip->single_dma)
+ pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
+ if (chip->hardware != WSS_HW_INTERWAVE)
+ pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
+ strcpy(pcm->name, snd_wss_chip_id(chip));
+
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_isa_data(),
+ 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
+
+ chip->pcm = pcm;
+ if (rpcm)
+ *rpcm = pcm;
+ return 0;
+}
+EXPORT_SYMBOL(snd_wss_pcm);
+
+static void snd_wss_timer_free(struct snd_timer *timer)
+{
+ struct snd_wss *chip = timer->private_data;
+ chip->timer = NULL;
+}
+
+int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer)
+{
+ struct snd_timer *timer;
+ struct snd_timer_id tid;
+ int err;
+
+ /* Timer initialization */
+ tid.dev_class = SNDRV_TIMER_CLASS_CARD;
+ tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
+ tid.card = chip->card->number;
+ tid.device = device;
+ tid.subdevice = 0;
+ if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0)
+ return err;
+ strcpy(timer->name, snd_wss_chip_id(chip));
+ timer->private_data = chip;
+ timer->private_free = snd_wss_timer_free;
+ timer->hw = snd_wss_timer_table;
+ chip->timer = timer;
+ if (rtimer)
+ *rtimer = timer;
+ return 0;
+}
+EXPORT_SYMBOL(snd_wss_timer);
+
+/*
+ * MIXER part
+ */
+
+static int snd_wss_info_mux(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static char *texts[4] = {
+ "Line", "Aux", "Mic", "Mix"
+ };
+ static char *opl3sa_texts[4] = {
+ "Line", "CD", "Mic", "Mix"
+ };
+ static char *gusmax_texts[4] = {
+ "Line", "Synth", "Mic", "Mix"
+ };
+ char **ptexts = texts;
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
+
+ if (snd_BUG_ON(!chip->card))
+ return -EINVAL;
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 2;
+ uinfo->value.enumerated.items = 4;
+ if (uinfo->value.enumerated.item > 3)
+ uinfo->value.enumerated.item = 3;
+ if (!strcmp(chip->card->driver, "GUS MAX"))
+ ptexts = gusmax_texts;
+ switch (chip->hardware) {
+ case WSS_HW_INTERWAVE:
+ ptexts = gusmax_texts;
+ break;
+ case WSS_HW_OPL3SA2:
+ ptexts = opl3sa_texts;
+ break;
+ }
+ strcpy(uinfo->value.enumerated.name, ptexts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_wss_get_mux(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6;
+ ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6;
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ return 0;
+}
+
+static int snd_wss_put_mux(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
+ unsigned long flags;
+ unsigned short left, right;
+ int change;
+
+ if (ucontrol->value.enumerated.item[0] > 3 ||
+ ucontrol->value.enumerated.item[1] > 3)
+ return -EINVAL;
+ left = ucontrol->value.enumerated.item[0] << 6;
+ right = ucontrol->value.enumerated.item[1] << 6;
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left;
+ right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right;
+ change = left != chip->image[CS4231_LEFT_INPUT] ||
+ right != chip->image[CS4231_RIGHT_INPUT];
+ snd_wss_out(chip, CS4231_LEFT_INPUT, left);
+ snd_wss_out(chip, CS4231_RIGHT_INPUT, right);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ return change;
+}
+
+int snd_wss_info_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ int mask = (kcontrol->private_value >> 16) & 0xff;
+
+ 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 = mask;
+ return 0;
+}
+EXPORT_SYMBOL(snd_wss_info_single);
+
+int snd_wss_get_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
+ unsigned long flags;
+ int reg = kcontrol->private_value & 0xff;
+ int shift = (kcontrol->private_value >> 8) & 0xff;
+ int mask = (kcontrol->private_value >> 16) & 0xff;
+ int invert = (kcontrol->private_value >> 24) & 0xff;
+
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ if (invert)
+ ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
+ return 0;
+}
+EXPORT_SYMBOL(snd_wss_get_single);
+
+int snd_wss_put_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
+ unsigned long flags;
+ int reg = kcontrol->private_value & 0xff;
+ int shift = (kcontrol->private_value >> 8) & 0xff;
+ int mask = (kcontrol->private_value >> 16) & 0xff;
+ int invert = (kcontrol->private_value >> 24) & 0xff;
+ int change;
+ unsigned short val;
+
+ val = (ucontrol->value.integer.value[0] & mask);
+ if (invert)
+ val = mask - val;
+ val <<= shift;
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ val = (chip->image[reg] & ~(mask << shift)) | val;
+ change = val != chip->image[reg];
+ snd_wss_out(chip, reg, val);
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ return change;
+}
+EXPORT_SYMBOL(snd_wss_put_single);
+
+int snd_wss_info_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ int mask = (kcontrol->private_value >> 24) & 0xff;
+
+ 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 = mask;
+ return 0;
+}
+EXPORT_SYMBOL(snd_wss_info_double);
+
+int snd_wss_get_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
+ unsigned long flags;
+ int left_reg = kcontrol->private_value & 0xff;
+ int right_reg = (kcontrol->private_value >> 8) & 0xff;
+ int shift_left = (kcontrol->private_value >> 16) & 0x07;
+ int shift_right = (kcontrol->private_value >> 19) & 0x07;
+ int mask = (kcontrol->private_value >> 24) & 0xff;
+ int invert = (kcontrol->private_value >> 22) & 1;
+
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
+ ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ 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;
+}
+EXPORT_SYMBOL(snd_wss_get_double);
+
+int snd_wss_put_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
+ unsigned long flags;
+ int left_reg = kcontrol->private_value & 0xff;
+ int right_reg = (kcontrol->private_value >> 8) & 0xff;
+ int shift_left = (kcontrol->private_value >> 16) & 0x07;
+ int shift_right = (kcontrol->private_value >> 19) & 0x07;
+ int mask = (kcontrol->private_value >> 24) & 0xff;
+ int invert = (kcontrol->private_value >> 22) & 1;
+ int change;
+ unsigned short val1, val2;
+
+ 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_irqsave(&chip->reg_lock, flags);
+ if (left_reg != right_reg) {
+ val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
+ val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
+ change = val1 != chip->image[left_reg] ||
+ val2 != chip->image[right_reg];
+ snd_wss_out(chip, left_reg, val1);
+ snd_wss_out(chip, right_reg, val2);
+ } else {
+ mask = (mask << shift_left) | (mask << shift_right);
+ val1 = (chip->image[left_reg] & ~mask) | val1 | val2;
+ change = val1 != chip->image[left_reg];
+ snd_wss_out(chip, left_reg, val1);
+ }
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ return change;
+}
+EXPORT_SYMBOL(snd_wss_put_double);
+
+static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
+
+static struct snd_kcontrol_new snd_ad1848_controls[] = {
+WSS_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT,
+ 7, 7, 1, 1),
+WSS_DOUBLE_TLV("PCM Playback Volume", 0,
+ CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
+ db_scale_6bit),
+WSS_DOUBLE("Aux Playback Switch", 0,
+ CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
+WSS_DOUBLE_TLV("Aux Playback Volume", 0,
+ CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
+ db_scale_5bit_12db_max),
+WSS_DOUBLE("Aux Playback Switch", 1,
+ CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
+WSS_DOUBLE_TLV("Aux Playback Volume", 1,
+ CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
+ db_scale_5bit_12db_max),
+WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
+ 0, 0, 15, 0, db_scale_rec_gain),
+{
+ .name = "Capture Source",
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .info = snd_wss_info_mux,
+ .get = snd_wss_get_mux,
+ .put = snd_wss_put_mux,
+},
+WSS_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
+WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 1, 63, 0,
+ db_scale_6bit),
+};
+
+static struct snd_kcontrol_new snd_wss_controls[] = {
+WSS_DOUBLE("PCM Playback Switch", 0,
+ CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
+WSS_DOUBLE("PCM Playback Volume", 0,
+ CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
+WSS_DOUBLE("Line Playback Switch", 0,
+ CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
+WSS_DOUBLE("Line Playback Volume", 0,
+ CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
+WSS_DOUBLE("Aux Playback Switch", 0,
+ CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
+WSS_DOUBLE("Aux Playback Volume", 0,
+ CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
+WSS_DOUBLE("Aux Playback Switch", 1,
+ CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
+WSS_DOUBLE("Aux Playback Volume", 1,
+ CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
+WSS_SINGLE("Mono Playback Switch", 0,
+ CS4231_MONO_CTRL, 7, 1, 1),
+WSS_SINGLE("Mono Playback Volume", 0,
+ CS4231_MONO_CTRL, 0, 15, 1),
+WSS_SINGLE("Mono Output Playback Switch", 0,
+ CS4231_MONO_CTRL, 6, 1, 1),
+WSS_SINGLE("Mono Output Playback Bypass", 0,
+ CS4231_MONO_CTRL, 5, 1, 0),
+WSS_DOUBLE("Capture Volume", 0,
+ CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .info = snd_wss_info_mux,
+ .get = snd_wss_get_mux,
+ .put = snd_wss_put_mux,
+},
+WSS_DOUBLE("Mic Boost", 0,
+ CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
+WSS_SINGLE("Loopback Capture Switch", 0,
+ CS4231_LOOPBACK, 0, 1, 0),
+WSS_SINGLE("Loopback Capture Volume", 0,
+ CS4231_LOOPBACK, 2, 63, 1)
+};
+
+static struct snd_kcontrol_new snd_opti93x_controls[] = {
+WSS_DOUBLE("Master Playback Switch", 0,
+ OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
+WSS_DOUBLE("Master Playback Volume", 0,
+ OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1),
+WSS_DOUBLE("PCM Playback Switch", 0,
+ CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
+WSS_DOUBLE("PCM Playback Volume", 0,
+ CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1),
+WSS_DOUBLE("FM Playback Switch", 0,
+ CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
+WSS_DOUBLE("FM Playback Volume", 0,
+ CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1),
+WSS_DOUBLE("Line Playback Switch", 0,
+ CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
+WSS_DOUBLE("Line Playback Volume", 0,
+ CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1),
+WSS_DOUBLE("Mic Playback Switch", 0,
+ OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
+WSS_DOUBLE("Mic Playback Volume", 0,
+ OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1),
+WSS_DOUBLE("Mic Boost", 0,
+ CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
+WSS_DOUBLE("CD Playback Switch", 0,
+ CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
+WSS_DOUBLE("CD Playback Volume", 0,
+ CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1),
+WSS_DOUBLE("Aux Playback Switch", 0,
+ OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
+WSS_DOUBLE("Aux Playback Volume", 0,
+ OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1),
+WSS_DOUBLE("Capture Volume", 0,
+ CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .info = snd_wss_info_mux,
+ .get = snd_wss_get_mux,
+ .put = snd_wss_put_mux,
+}
+};
+
+int snd_wss_mixer(struct snd_wss *chip)
+{
+ struct snd_card *card;
+ unsigned int idx;
+ int err;
+
+ if (snd_BUG_ON(!chip || !chip->pcm))
+ return -EINVAL;
+
+ card = chip->card;
+
+ strcpy(card->mixername, chip->pcm->name);
+
+ if (chip->hardware == WSS_HW_OPTI93X)
+ for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
+ err = snd_ctl_add(card,
+ snd_ctl_new1(&snd_opti93x_controls[idx],
+ chip));
+ if (err < 0)
+ return err;
+ }
+ else if (chip->hardware & WSS_HW_AD1848_MASK)
+ for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++) {
+ err = snd_ctl_add(card,
+ snd_ctl_new1(&snd_ad1848_controls[idx],
+ chip));
+ if (err < 0)
+ return err;
+ }
+ else
+ for (idx = 0; idx < ARRAY_SIZE(snd_wss_controls); idx++) {
+ err = snd_ctl_add(card,
+ snd_ctl_new1(&snd_wss_controls[idx],
+ chip));
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(snd_wss_mixer);
+
+const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction)
+{
+ return direction == SNDRV_PCM_STREAM_PLAYBACK ?
+ &snd_wss_playback_ops : &snd_wss_capture_ops;
+}
+EXPORT_SYMBOL(snd_wss_get_pcm_ops);
+
+/*
+ * INIT part
+ */
+
+static int __init alsa_wss_init(void)
+{
+ return 0;
+}
+
+static void __exit alsa_wss_exit(void)
+{
+}
+
+module_init(alsa_wss_init);
+module_exit(alsa_wss_exit);
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c
index fbef38a9604a..1881cec11e78 100644
--- a/sound/mips/au1x00.c
+++ b/sound/mips/au1x00.c
@@ -190,14 +190,16 @@ au1000_setup_dma_link(struct audio_stream *stream, unsigned int period_bytes,
static void
au1000_dma_stop(struct audio_stream *stream)
{
- snd_assert(stream->buffer, return);
+ if (snd_BUG_ON(!stream->buffer))
+ return;
disable_dma(stream->dma);
}
static void
au1000_dma_start(struct audio_stream *stream)
{
- snd_assert(stream->buffer, return);
+ if (snd_BUG_ON(!stream->buffer))
+ return;
init_dma(stream->dma);
if (get_dma_active_buffer(stream->dma) == 0) {
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index d4fafb6eec6c..1ca7427c4b6d 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -24,13 +24,6 @@ config SOUND_VWSND
for more info on this driver's
capabilities.
-config SOUND_HAL2
- tristate "SGI HAL2 sound (EXPERIMENTAL)"
- depends on SGI_IP22 && EXPERIMENTAL
- help
- Say Y or M if you have an SGI Indy or Indigo2 system and want to be able to
- use its on-board A2 audio system.
-
config SOUND_AU1550_AC97
tristate "Au1550/Au1200 AC97 Sound"
depends on SOC_AU1550 || SOC_AU1200
@@ -546,34 +539,6 @@ config SC6600_CDROMBASE
Base I/O port address for the CD-ROM interface of the Audio Excel
DSP 16 card.
-choice
- prompt "Audio Excel DSP 16"
- optional
- depends on SOUND_AEDSP16
-
-config AEDSP16_MSS
- bool "MSS emulation"
- depends on SOUND_MSS
- help
- Answer Y if you want your audio card to emulate Microsoft Sound
- System. You should then say Y to "Microsoft Sound System support"
- and say N to "Audio Excel DSP 16 (SBPro emulation)".
-
-config AEDSP16_SBPRO
- bool "SBPro emulation"
- depends on SOUND_SB
- help
- Answer Y if you want your audio card to emulate Sound Blaster Pro.
- You should then say Y to "100% Sound Blaster compatibles
- (SB16/32/64, ESS, Jazz16) support" and N to "Audio Excel DSP 16 (MSS
- emulation)".
-
- If you compile the driver into the kernel, you have to add
- "aedsp16=,,,,," to the kernel
- command line.
-
-endchoice
-
config SOUND_VIDC
tristate "VIDC 16-bit sound"
depends on ARM && (ARCH_ACORN || ARCH_CLPS7500)
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index c611514f7ff1..e0ae4d4d6a5c 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -10,7 +10,6 @@ obj-$(CONFIG_SOUND_OSS) += sound.o
# Please leave it as is, cause the link order is significant !
obj-$(CONFIG_SOUND_SH_DAC_AUDIO) += sh_dac_audio.o
-obj-$(CONFIG_SOUND_HAL2) += hal2.o
obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o
obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o
obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb_lib.o uart401.o
diff --git a/sound/oss/aedsp16.c b/sound/oss/aedsp16.c
index 51e1fde62e8d..a0274f3dac08 100644
--- a/sound/oss/aedsp16.c
+++ b/sound/oss/aedsp16.c
@@ -28,14 +28,6 @@
#include
#include "sound_config.h"
-/*
- * Sanity checks
- */
-
-#if defined(CONFIG_SOUND_AEDSP16_SBPRO) && defined(CONFIG_SOUND_AEDSP16_MSS)
-#error You have to enable only one of the MSS and SBPRO emulations.
-#endif
-
/*
READ THIS
diff --git a/sound/oss/dmasound/Kconfig b/sound/oss/dmasound/Kconfig
index 3eb782720e58..f456574a964d 100644
--- a/sound/oss/dmasound/Kconfig
+++ b/sound/oss/dmasound/Kconfig
@@ -42,3 +42,4 @@ config DMASOUND_Q40
config DMASOUND
tristate
+ select SOUND_OSS_CORE
diff --git a/sound/oss/hal2.c b/sound/oss/hal2.c
deleted file mode 100644
index a94b9df489dc..000000000000
--- a/sound/oss/hal2.c
+++ /dev/null
@@ -1,1558 +0,0 @@
-/*
- * Driver for A2 audio system used in SGI machines
- * Copyright (c) 2001, 2002, 2003 Ladislav Michl
- *
- * Based on Ulf Carlsson's code.
- *
- * 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.
- *
- * 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.
- *
- * Supported devices:
- * /dev/dsp standard dsp device, (mostly) OSS compatible
- * /dev/mixer standard mixer device, (mostly) OSS compatible
- *
- */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-#include