aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-10-11 12:16:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-11 12:16:54 -0400
commitd3570a5a7b8d0604fa012129f92637dc1534f62c (patch)
tree15d290595c363a2bdd4f4d6b3a2f7433e6e48f6d /sound/isa
parent37d9869ed928268409b48f52c57449918c0fd307 (diff)
parent72474be62d6ec2e0337ff01ecbd737f9c5c242c7 (diff)
Merge branch 'for-linus' of git://git.alsa-project.org/alsa-kernel
* 'for-linus' of git://git.alsa-project.org/alsa-kernel: (258 commits) ALSA: hda: VREF powerdown for headphones ALSA: hda: STAC_HP_M4 ALSA: ASoC: Check for machine type in GTA01 machine driver ALSA: mtpav - Fix race in probe ALSA: usb-audio: dynamic detection of MIDI interfaces in uaxx-quirk ALSA: Add a note on dependency of RTC stuff ALSA: ASoC: add new param mux to dapm_mux_update_power ALSA: Increase components array size ALSA: ASoC: Correct inverted Mic PGA Switch control in wm8510 driver ALSA: hda: comment typo fix ALSA: hda: comment typo fix ALSA: hda - Fix PCI SSID for ASROCK K18N78FullHD-hSLI ALSA: snd-usb-audio: support for Edirol UA-4FX device ALSA: usb - Fix possible Oops at USB-MIDI disconnection ALSA: hda - Fix another ALC889A (rev 0x100101) ALSA: hda: add more board-specific information for Realtek ALC662 rev1 ALSA: Correct Vladimir Barinov's e-mail address ALSA: cs46xx: Add PCI IDs for TerraTec and Hercules cards ALSA: hda: SPDIF stream muting support ALSA: hda: appletv support ...
Diffstat (limited to 'sound/isa')
-rw-r--r--sound/isa/Kconfig44
-rw-r--r--sound/isa/Makefile2
-rw-r--r--sound/isa/ad1816a/ad1816a.c4
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c6
-rw-r--r--sound/isa/ad1848/Makefile2
-rw-r--r--sound/isa/ad1848/ad1848.c17
-rw-r--r--sound/isa/ad1848/ad1848_lib.c1267
-rw-r--r--sound/isa/azt2320.c29
-rw-r--r--sound/isa/cmi8330.c106
-rw-r--r--sound/isa/cs423x/Makefile2
-rw-r--r--sound/isa/cs423x/cs4231.c18
-rw-r--r--sound/isa/cs423x/cs4231_lib.c1945
-rw-r--r--sound/isa/cs423x/cs4236.c51
-rw-r--r--sound/isa/cs423x/cs4236_lib.c349
-rw-r--r--sound/isa/es1688/es1688_lib.c3
-rw-r--r--sound/isa/gus/gus_main.c6
-rw-r--r--sound/isa/gus/gus_mixer.c6
-rw-r--r--sound/isa/gus/gus_pcm.c12
-rw-r--r--sound/isa/gus/gusmax.c50
-rw-r--r--sound/isa/gus/interwave.c67
-rw-r--r--sound/isa/opl3sa2.c99
-rw-r--r--sound/isa/opti9xx/miro.c28
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c70
-rw-r--r--sound/isa/sb/emu8000.c3
-rw-r--r--sound/isa/sb/emu8000_patch.c3
-rw-r--r--sound/isa/sb/sb16_csp.c9
-rw-r--r--sound/isa/sb/sb16_main.c3
-rw-r--r--sound/isa/sb/sb8_main.c8
-rw-r--r--sound/isa/sb/sb_common.c3
-rw-r--r--sound/isa/sb/sb_mixer.c9
-rw-r--r--sound/isa/sc6000.c18
-rw-r--r--sound/isa/sgalaxy.c43
-rw-r--r--sound/isa/sscape.c63
-rw-r--r--sound/isa/wavefront/wavefront.c62
-rw-r--r--sound/isa/wavefront/wavefront_fx.c8
-rw-r--r--sound/isa/wavefront/wavefront_midi.c24
-rw-r--r--sound/isa/wavefront/wavefront_synth.c7
-rw-r--r--sound/isa/wss/Makefile10
-rw-r--r--sound/isa/wss/wss_lib.c2322
39 files changed, 3012 insertions, 3766 deletions
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 @@
1# ALSA ISA drivers 1# ALSA ISA drivers
2 2
3config SND_AD1848_LIB 3config SND_WSS_LIB
4 tristate
5 select SND_PCM
6
7config SND_CS4231_LIB
8 tristate 4 tristate
9 select SND_PCM 5 select SND_PCM
10 6
@@ -55,7 +51,7 @@ config SND_AD1816A
55 51
56config SND_AD1848 52config SND_AD1848
57 tristate "Generic AD1848/CS4248 driver" 53 tristate "Generic AD1848/CS4248 driver"
58 select SND_AD1848_LIB 54 select SND_WSS_LIB
59 help 55 help
60 Say Y here to include support for AD1848 (Analog Devices) or 56 Say Y here to include support for AD1848 (Analog Devices) or
61 CS4248 (Cirrus Logic - Crystal Semiconductors) chips. 57 CS4248 (Cirrus Logic - Crystal Semiconductors) chips.
@@ -86,7 +82,7 @@ config SND_AZT2320
86 select ISAPNP 82 select ISAPNP
87 select SND_OPL3_LIB 83 select SND_OPL3_LIB
88 select SND_MPU401_UART 84 select SND_MPU401_UART
89 select SND_CS4231_LIB 85 select SND_WSS_LIB
90 help 86 help
91 Say Y here to include support for soundcards based on the 87 Say Y here to include support for soundcards based on the
92 Aztech Systems AZT2320 chip. 88 Aztech Systems AZT2320 chip.
@@ -96,7 +92,7 @@ config SND_AZT2320
96 92
97config SND_CMI8330 93config SND_CMI8330
98 tristate "C-Media CMI8330" 94 tristate "C-Media CMI8330"
99 select SND_AD1848_LIB 95 select SND_WSS_LIB
100 select SND_SB16_DSP 96 select SND_SB16_DSP
101 help 97 help
102 Say Y here to include support for soundcards based on the 98 Say Y here to include support for soundcards based on the
@@ -108,7 +104,7 @@ config SND_CMI8330
108config SND_CS4231 104config SND_CS4231
109 tristate "Generic Cirrus Logic CS4231 driver" 105 tristate "Generic Cirrus Logic CS4231 driver"
110 select SND_MPU401_UART 106 select SND_MPU401_UART
111 select SND_CS4231_LIB 107 select SND_WSS_LIB
112 help 108 help
113 Say Y here to include support for CS4231 chips from Cirrus 109 Say Y here to include support for CS4231 chips from Cirrus
114 Logic - Crystal Semiconductors. 110 Logic - Crystal Semiconductors.
@@ -120,7 +116,7 @@ config SND_CS4232
120 tristate "Generic Cirrus Logic CS4232 driver" 116 tristate "Generic Cirrus Logic CS4232 driver"
121 select SND_OPL3_LIB 117 select SND_OPL3_LIB
122 select SND_MPU401_UART 118 select SND_MPU401_UART
123 select SND_CS4231_LIB 119 select SND_WSS_LIB
124 help 120 help
125 Say Y here to include support for CS4232 chips from Cirrus 121 Say Y here to include support for CS4232 chips from Cirrus
126 Logic - Crystal Semiconductors. 122 Logic - Crystal Semiconductors.
@@ -132,7 +128,7 @@ config SND_CS4236
132 tristate "Generic Cirrus Logic CS4236+ driver" 128 tristate "Generic Cirrus Logic CS4236+ driver"
133 select SND_OPL3_LIB 129 select SND_OPL3_LIB
134 select SND_MPU401_UART 130 select SND_MPU401_UART
135 select SND_CS4231_LIB 131 select SND_WSS_LIB
136 help 132 help
137 Say Y to include support for CS4235,CS4236,CS4237B,CS4238B, 133 Say Y to include support for CS4235,CS4236,CS4237B,CS4238B,
138 CS4239 chips from Cirrus Logic - Crystal Semiconductors. 134 CS4239 chips from Cirrus Logic - Crystal Semiconductors.
@@ -192,7 +188,7 @@ config SND_ES18XX
192config SND_SC6000 188config SND_SC6000
193 tristate "Gallant SC-6000, Audio Excel DSP 16" 189 tristate "Gallant SC-6000, Audio Excel DSP 16"
194 depends on HAS_IOPORT 190 depends on HAS_IOPORT
195 select SND_AD1848_LIB 191 select SND_WSS_LIB
196 select SND_OPL3_LIB 192 select SND_OPL3_LIB
197 select SND_MPU401_UART 193 select SND_MPU401_UART
198 help 194 help
@@ -228,7 +224,7 @@ config SND_GUSEXTREME
228config SND_GUSMAX 224config SND_GUSMAX
229 tristate "Gravis UltraSound MAX" 225 tristate "Gravis UltraSound MAX"
230 select SND_RAWMIDI 226 select SND_RAWMIDI
231 select SND_CS4231_LIB 227 select SND_WSS_LIB
232 help 228 help
233 Say Y here to include support for Gravis UltraSound MAX 229 Say Y here to include support for Gravis UltraSound MAX
234 soundcards. 230 soundcards.
@@ -240,7 +236,7 @@ config SND_INTERWAVE
240 tristate "AMD InterWave, Gravis UltraSound PnP" 236 tristate "AMD InterWave, Gravis UltraSound PnP"
241 depends on PNP 237 depends on PNP
242 select SND_RAWMIDI 238 select SND_RAWMIDI
243 select SND_CS4231_LIB 239 select SND_WSS_LIB
244 help 240 help
245 Say Y here to include support for AMD InterWave based 241 Say Y here to include support for AMD InterWave based
246 soundcards (Gravis UltraSound Plug & Play, STB SoundRage32, 242 soundcards (Gravis UltraSound Plug & Play, STB SoundRage32,
@@ -253,7 +249,7 @@ config SND_INTERWAVE_STB
253 tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)" 249 tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)"
254 depends on PNP 250 depends on PNP
255 select SND_RAWMIDI 251 select SND_RAWMIDI
256 select SND_CS4231_LIB 252 select SND_WSS_LIB
257 help 253 help
258 Say Y here to include support for AMD InterWave based 254 Say Y here to include support for AMD InterWave based
259 soundcards with a TEA6330T bass and treble regulator 255 soundcards with a TEA6330T bass and treble regulator
@@ -266,7 +262,7 @@ config SND_OPL3SA2
266 tristate "Yamaha OPL3-SA2/SA3" 262 tristate "Yamaha OPL3-SA2/SA3"
267 select SND_OPL3_LIB 263 select SND_OPL3_LIB
268 select SND_MPU401_UART 264 select SND_MPU401_UART
269 select SND_CS4231_LIB 265 select SND_WSS_LIB
270 help 266 help
271 Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3 267 Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3
272 chips. 268 chips.
@@ -279,7 +275,7 @@ config SND_OPTI92X_AD1848
279 select SND_OPL3_LIB 275 select SND_OPL3_LIB
280 select SND_OPL4_LIB 276 select SND_OPL4_LIB
281 select SND_MPU401_UART 277 select SND_MPU401_UART
282 select SND_AD1848_LIB 278 select SND_WSS_LIB
283 help 279 help
284 Say Y here to include support for soundcards based on Opti 280 Say Y here to include support for soundcards based on Opti
285 82C92x or OTI-601 chips and using an AD1848 codec. 281 82C92x or OTI-601 chips and using an AD1848 codec.
@@ -292,7 +288,7 @@ config SND_OPTI92X_CS4231
292 select SND_OPL3_LIB 288 select SND_OPL3_LIB
293 select SND_OPL4_LIB 289 select SND_OPL4_LIB
294 select SND_MPU401_UART 290 select SND_MPU401_UART
295 select SND_CS4231_LIB 291 select SND_WSS_LIB
296 help 292 help
297 Say Y here to include support for soundcards based on Opti 293 Say Y here to include support for soundcards based on Opti
298 82C92x chips and using a CS4231 codec. 294 82C92x chips and using a CS4231 codec.
@@ -304,7 +300,7 @@ config SND_OPTI93X
304 tristate "OPTi 82C93x" 300 tristate "OPTi 82C93x"
305 select SND_OPL3_LIB 301 select SND_OPL3_LIB
306 select SND_MPU401_UART 302 select SND_MPU401_UART
307 select SND_CS4231_LIB 303 select SND_WSS_LIB
308 help 304 help
309 Say Y here to include support for soundcards based on Opti 305 Say Y here to include support for soundcards based on Opti
310 82C93x chips. 306 82C93x chips.
@@ -315,7 +311,7 @@ config SND_OPTI93X
315config SND_MIRO 311config SND_MIRO
316 tristate "Miro miroSOUND PCM1pro/PCM12/PCM20radio driver" 312 tristate "Miro miroSOUND PCM1pro/PCM12/PCM20radio driver"
317 select SND_OPL4_LIB 313 select SND_OPL4_LIB
318 select SND_CS4231_LIB 314 select SND_WSS_LIB
319 select SND_MPU401_UART 315 select SND_MPU401_UART
320 select SND_PCM 316 select SND_PCM
321 help 317 help
@@ -364,7 +360,7 @@ config SND_SBAWE
364config SND_SB16_CSP 360config SND_SB16_CSP
365 bool "Sound Blaster 16/AWE CSP support" 361 bool "Sound Blaster 16/AWE CSP support"
366 depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC) 362 depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC)
367 select FW_LOADER if !SND_SB16_CSP_FIRMWARE_IN_KERNEL 363 select FW_LOADER
368 help 364 help
369 Say Y here to include support for the CSP core. This special 365 Say Y here to include support for the CSP core. This special
370 coprocessor can do variable tasks like various compression and 366 coprocessor can do variable tasks like various compression and
@@ -372,7 +368,7 @@ config SND_SB16_CSP
372 368
373config SND_SGALAXY 369config SND_SGALAXY
374 tristate "Aztech Sound Galaxy" 370 tristate "Aztech Sound Galaxy"
375 select SND_AD1848_LIB 371 select SND_WSS_LIB
376 help 372 help
377 Say Y here to include support for Aztech Sound Galaxy 373 Say Y here to include support for Aztech Sound Galaxy
378 soundcards. 374 soundcards.
@@ -384,7 +380,7 @@ config SND_SSCAPE
384 tristate "Ensoniq SoundScape PnP driver" 380 tristate "Ensoniq SoundScape PnP driver"
385 select SND_HWDEP 381 select SND_HWDEP
386 select SND_MPU401_UART 382 select SND_MPU401_UART
387 select SND_CS4231_LIB 383 select SND_WSS_LIB
388 help 384 help
389 Say Y here to include support for Ensoniq SoundScape PnP 385 Say Y here to include support for Ensoniq SoundScape PnP
390 soundcards. 386 soundcards.
@@ -397,7 +393,7 @@ config SND_WAVEFRONT
397 select FW_LOADER 393 select FW_LOADER
398 select SND_OPL3_LIB 394 select SND_OPL3_LIB
399 select SND_MPU401_UART 395 select SND_MPU401_UART
400 select SND_CS4231_LIB 396 select SND_WSS_LIB
401 help 397 help
402 Say Y here to include support for Turtle Beach Maui, Tropez 398 Say Y here to include support for Turtle Beach Maui, Tropez
403 and Tropez+ soundcards based on the Wavefront chip. 399 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
27obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o 27obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o
28 28
29obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ opti9xx/ \ 29obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ opti9xx/ \
30 sb/ wavefront/ 30 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[] = {
83 { .id = "MDK1605", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, 83 { .id = "MDK1605", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
84 /* Shark Predator ISA - added by Ken Arromdee */ 84 /* Shark Predator ISA - added by Ken Arromdee */
85 { .id = "SMM7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, 85 { .id = "SMM7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
86 /* Analog Devices AD1816A - Terratec AudioSystem EWS64S */ 86 /* Analog Devices AD1816A - Terratec AudioSystem EWS64 S */
87 { .id = "TER1112", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, 87 { .id = "TER1112", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
88 /* Analog Devices AD1816A - Terratec AudioSystem EWS64 S */
89 { .id = "TER1112", .devs = { { .id = "TER1100" }, { .id = "TER1101" } } },
88 /* Analog Devices AD1816A - Terratec Base 64 */ 90 /* Analog Devices AD1816A - Terratec Base 64 */
89 { .id = "TER1411", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, 91 { .id = "TER1411", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
90 /* end */ 92 /* 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)
394 394
395static unsigned long snd_ad1816a_timer_resolution(struct snd_timer *timer) 395static unsigned long snd_ad1816a_timer_resolution(struct snd_timer *timer)
396{ 396{
397 snd_assert(timer != NULL, return 0); 397 if (snd_BUG_ON(!timer))
398 return 0;
398 399
399 return 10000; 400 return 10000;
400} 401}
@@ -961,7 +962,8 @@ int __devinit snd_ad1816a_mixer(struct snd_ad1816a *chip)
961 unsigned int idx; 962 unsigned int idx;
962 int err; 963 int err;
963 964
964 snd_assert(chip != NULL && chip->card != NULL, return -EINVAL); 965 if (snd_BUG_ON(!chip || !chip->card))
966 return -EINVAL;
965 967
966 card = chip->card; 968 card = chip->card;
967 969
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 @@
3# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> 3# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
4# 4#
5 5
6snd-ad1848-lib-objs := ad1848_lib.o
7snd-ad1848-objs := ad1848.o 6snd-ad1848-objs := ad1848.o
8 7
9# Toplevel Module Dependency 8# Toplevel Module Dependency
10obj-$(CONFIG_SND_AD1848) += snd-ad1848.o 9obj-$(CONFIG_SND_AD1848) += snd-ad1848.o
11obj-$(CONFIG_SND_AD1848_LIB) += snd-ad1848-lib.o
12 10
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 @@
28#include <linux/wait.h> 28#include <linux/wait.h>
29#include <linux/moduleparam.h> 29#include <linux/moduleparam.h>
30#include <sound/core.h> 30#include <sound/core.h>
31#include <sound/ad1848.h> 31#include <sound/wss.h>
32#include <sound/initval.h> 32#include <sound/initval.h>
33 33
34#define CRD_NAME "Generic AD1848/AD1847/CS4248" 34#define CRD_NAME "Generic AD1848/AD1847/CS4248"
@@ -87,7 +87,7 @@ static int __devinit snd_ad1848_match(struct device *dev, unsigned int n)
87static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) 87static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n)
88{ 88{
89 struct snd_card *card; 89 struct snd_card *card;
90 struct snd_ad1848 *chip; 90 struct snd_wss *chip;
91 struct snd_pcm *pcm; 91 struct snd_pcm *pcm;
92 int error; 92 int error;
93 93
@@ -95,18 +95,19 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n)
95 if (!card) 95 if (!card)
96 return -EINVAL; 96 return -EINVAL;
97 97
98 error = snd_ad1848_create(card, port[n], irq[n], dma1[n], 98 error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], -1,
99 thinkpad[n] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT, &chip); 99 thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT,
100 0, &chip);
100 if (error < 0) 101 if (error < 0)
101 goto out; 102 goto out;
102 103
103 card->private_data = chip; 104 card->private_data = chip;
104 105
105 error = snd_ad1848_pcm(chip, 0, &pcm); 106 error = snd_wss_pcm(chip, 0, &pcm);
106 if (error < 0) 107 if (error < 0)
107 goto out; 108 goto out;
108 109
109 error = snd_ad1848_mixer(chip); 110 error = snd_wss_mixer(chip);
110 if (error < 0) 111 if (error < 0)
111 goto out; 112 goto out;
112 113
@@ -142,7 +143,7 @@ static int __devexit snd_ad1848_remove(struct device *dev, unsigned int n)
142static int snd_ad1848_suspend(struct device *dev, unsigned int n, pm_message_t state) 143static int snd_ad1848_suspend(struct device *dev, unsigned int n, pm_message_t state)
143{ 144{
144 struct snd_card *card = dev_get_drvdata(dev); 145 struct snd_card *card = dev_get_drvdata(dev);
145 struct snd_ad1848 *chip = card->private_data; 146 struct snd_wss *chip = card->private_data;
146 147
147 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 148 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
148 chip->suspend(chip); 149 chip->suspend(chip);
@@ -152,7 +153,7 @@ static int snd_ad1848_suspend(struct device *dev, unsigned int n, pm_message_t s
152static int snd_ad1848_resume(struct device *dev, unsigned int n) 153static int snd_ad1848_resume(struct device *dev, unsigned int n)
153{ 154{
154 struct snd_card *card = dev_get_drvdata(dev); 155 struct snd_card *card = dev_get_drvdata(dev);
155 struct snd_ad1848 *chip = card->private_data; 156 struct snd_wss *chip = card->private_data;
156 157
157 chip->resume(chip); 158 chip->resume(chip);
158 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 159 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 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
3 * Routines for control of AD1848/AD1847/CS4248
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#define SNDRV_MAIN_OBJECT_FILE
23#include <linux/delay.h>
24#include <linux/init.h>
25#include <linux/interrupt.h>
26#include <linux/slab.h>
27#include <linux/ioport.h>
28#include <sound/core.h>
29#include <sound/ad1848.h>
30#include <sound/control.h>
31#include <sound/tlv.h>
32#include <sound/pcm_params.h>
33
34#include <asm/io.h>
35#include <asm/dma.h>
36
37MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
38MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248");
39MODULE_LICENSE("GPL");
40
41#if 0
42#define SNDRV_DEBUG_MCE
43#endif
44
45/*
46 * Some variables
47 */
48
49static unsigned char freq_bits[14] = {
50 /* 5510 */ 0x00 | AD1848_XTAL2,
51 /* 6620 */ 0x0E | AD1848_XTAL2,
52 /* 8000 */ 0x00 | AD1848_XTAL1,
53 /* 9600 */ 0x0E | AD1848_XTAL1,
54 /* 11025 */ 0x02 | AD1848_XTAL2,
55 /* 16000 */ 0x02 | AD1848_XTAL1,
56 /* 18900 */ 0x04 | AD1848_XTAL2,
57 /* 22050 */ 0x06 | AD1848_XTAL2,
58 /* 27042 */ 0x04 | AD1848_XTAL1,
59 /* 32000 */ 0x06 | AD1848_XTAL1,
60 /* 33075 */ 0x0C | AD1848_XTAL2,
61 /* 37800 */ 0x08 | AD1848_XTAL2,
62 /* 44100 */ 0x0A | AD1848_XTAL2,
63 /* 48000 */ 0x0C | AD1848_XTAL1
64};
65
66static unsigned int rates[14] = {
67 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,
68 27042, 32000, 33075, 37800, 44100, 48000
69};
70
71static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
72 .count = ARRAY_SIZE(rates),
73 .list = rates,
74 .mask = 0,
75};
76
77static unsigned char snd_ad1848_original_image[16] =
78{
79 0x00, /* 00 - lic */
80 0x00, /* 01 - ric */
81 0x9f, /* 02 - la1ic */
82 0x9f, /* 03 - ra1ic */
83 0x9f, /* 04 - la2ic */
84 0x9f, /* 05 - ra2ic */
85 0xbf, /* 06 - loc */
86 0xbf, /* 07 - roc */
87 0x20, /* 08 - dfr */
88 AD1848_AUTOCALIB, /* 09 - ic */
89 0x00, /* 0a - pc */
90 0x00, /* 0b - ti */
91 0x00, /* 0c - mi */
92 0x00, /* 0d - lbc */
93 0x00, /* 0e - dru */
94 0x00, /* 0f - drl */
95};
96
97/*
98 * Basic I/O functions
99 */
100
101static void snd_ad1848_wait(struct snd_ad1848 *chip)
102{
103 int timeout;
104
105 for (timeout = 250; timeout > 0; timeout--) {
106 if ((inb(AD1848P(chip, REGSEL)) & AD1848_INIT) == 0)
107 break;
108 udelay(100);
109 }
110}
111
112void snd_ad1848_out(struct snd_ad1848 *chip,
113 unsigned char reg,
114 unsigned char value)
115{
116 snd_ad1848_wait(chip);
117#ifdef CONFIG_SND_DEBUG
118 if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
119 snd_printk(KERN_WARNING "auto calibration time out - "
120 "reg = 0x%x, value = 0x%x\n", reg, value);
121#endif
122 outb(chip->mce_bit | reg, AD1848P(chip, REGSEL));
123 outb(chip->image[reg] = value, AD1848P(chip, REG));
124 mb();
125 snd_printdd("codec out - reg 0x%x = 0x%x\n",
126 chip->mce_bit | reg, value);
127}
128
129EXPORT_SYMBOL(snd_ad1848_out);
130
131static void snd_ad1848_dout(struct snd_ad1848 *chip,
132 unsigned char reg, unsigned char value)
133{
134 snd_ad1848_wait(chip);
135 outb(chip->mce_bit | reg, AD1848P(chip, REGSEL));
136 outb(value, AD1848P(chip, REG));
137 mb();
138}
139
140static unsigned char snd_ad1848_in(struct snd_ad1848 *chip, unsigned char reg)
141{
142 snd_ad1848_wait(chip);
143#ifdef CONFIG_SND_DEBUG
144 if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
145 snd_printk(KERN_WARNING "auto calibration time out - "
146 "reg = 0x%x\n", reg);
147#endif
148 outb(chip->mce_bit | reg, AD1848P(chip, REGSEL));
149 mb();
150 return inb(AD1848P(chip, REG));
151}
152
153#if 0
154
155static void snd_ad1848_debug(struct snd_ad1848 *chip)
156{
157 printk("AD1848 REGS: INDEX = 0x%02x ", inb(AD1848P(chip, REGSEL)));
158 printk(" STATUS = 0x%02x\n", inb(AD1848P(chip, STATUS)));
159 printk(" 0x00: left input = 0x%02x ", snd_ad1848_in(chip, 0x00));
160 printk(" 0x08: playback format = 0x%02x\n", snd_ad1848_in(chip, 0x08));
161 printk(" 0x01: right input = 0x%02x ", snd_ad1848_in(chip, 0x01));
162 printk(" 0x09: iface (CFIG 1) = 0x%02x\n", snd_ad1848_in(chip, 0x09));
163 printk(" 0x02: AUXA left = 0x%02x ", snd_ad1848_in(chip, 0x02));
164 printk(" 0x0a: pin control = 0x%02x\n", snd_ad1848_in(chip, 0x0a));
165 printk(" 0x03: AUXA right = 0x%02x ", snd_ad1848_in(chip, 0x03));
166 printk(" 0x0b: init & status = 0x%02x\n", snd_ad1848_in(chip, 0x0b));
167 printk(" 0x04: AUXB left = 0x%02x ", snd_ad1848_in(chip, 0x04));
168 printk(" 0x0c: revision & mode = 0x%02x\n", snd_ad1848_in(chip, 0x0c));
169 printk(" 0x05: AUXB right = 0x%02x ", snd_ad1848_in(chip, 0x05));
170 printk(" 0x0d: loopback = 0x%02x\n", snd_ad1848_in(chip, 0x0d));
171 printk(" 0x06: left output = 0x%02x ", snd_ad1848_in(chip, 0x06));
172 printk(" 0x0e: data upr count = 0x%02x\n", snd_ad1848_in(chip, 0x0e));
173 printk(" 0x07: right output = 0x%02x ", snd_ad1848_in(chip, 0x07));
174 printk(" 0x0f: data lwr count = 0x%02x\n", snd_ad1848_in(chip, 0x0f));
175}
176
177#endif
178
179/*
180 * AD1848 detection / MCE routines
181 */
182
183static void snd_ad1848_mce_up(struct snd_ad1848 *chip)
184{
185 unsigned long flags;
186 int timeout;
187
188 snd_ad1848_wait(chip);
189#ifdef CONFIG_SND_DEBUG
190 if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
191 snd_printk(KERN_WARNING "mce_up - auto calibration time out (0)\n");
192#endif
193 spin_lock_irqsave(&chip->reg_lock, flags);
194 chip->mce_bit |= AD1848_MCE;
195 timeout = inb(AD1848P(chip, REGSEL));
196 if (timeout == 0x80)
197 snd_printk(KERN_WARNING "mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
198 if (!(timeout & AD1848_MCE))
199 outb(chip->mce_bit | (timeout & 0x1f), AD1848P(chip, REGSEL));
200 spin_unlock_irqrestore(&chip->reg_lock, flags);
201}
202
203static void snd_ad1848_mce_down(struct snd_ad1848 *chip)
204{
205 unsigned long flags, timeout;
206 int reg;
207
208 spin_lock_irqsave(&chip->reg_lock, flags);
209 for (timeout = 5; timeout > 0; timeout--)
210 inb(AD1848P(chip, REGSEL));
211 /* end of cleanup sequence */
212 for (timeout = 12000; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--)
213 udelay(100);
214
215 snd_printdd("(1) timeout = %ld\n", timeout);
216
217#ifdef CONFIG_SND_DEBUG
218 if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
219 snd_printk(KERN_WARNING "mce_down [0x%lx] - auto calibration time out (0)\n", AD1848P(chip, REGSEL));
220#endif
221
222 chip->mce_bit &= ~AD1848_MCE;
223 reg = inb(AD1848P(chip, REGSEL));
224 outb(chip->mce_bit | (reg & 0x1f), AD1848P(chip, REGSEL));
225 if (reg == 0x80)
226 snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
227 if ((reg & AD1848_MCE) == 0) {
228 spin_unlock_irqrestore(&chip->reg_lock, flags);
229 return;
230 }
231
232 /*
233 * Wait for auto-calibration (AC) process to finish, i.e. ACI to go low.
234 * It may take up to 5 sample periods (at most 907 us @ 5.5125 kHz) for
235 * the process to _start_, so it is important to wait at least that long
236 * before checking. Otherwise we might think AC has finished when it
237 * has in fact not begun. It could take 128 (no AC) or 384 (AC) cycles
238 * for ACI to drop. This gives a wait of at most 70 ms with a more
239 * typical value of 3-9 ms.
240 */
241 timeout = jiffies + msecs_to_jiffies(250);
242 do {
243 spin_unlock_irqrestore(&chip->reg_lock, flags);
244 msleep(1);
245 spin_lock_irqsave(&chip->reg_lock, flags);
246 reg = snd_ad1848_in(chip, AD1848_TEST_INIT) &
247 AD1848_CALIB_IN_PROGRESS;
248 } while (reg && time_before(jiffies, timeout));
249 spin_unlock_irqrestore(&chip->reg_lock, flags);
250 if (reg)
251 snd_printk(KERN_ERR
252 "mce_down - auto calibration time out (2)\n");
253
254 snd_printdd("(4) jiffies = %lu\n", jiffies);
255 snd_printd("mce_down - exit = 0x%x\n", inb(AD1848P(chip, REGSEL)));
256}
257
258static unsigned int snd_ad1848_get_count(unsigned char format,
259 unsigned int size)
260{
261 switch (format & 0xe0) {
262 case AD1848_LINEAR_16:
263 size >>= 1;
264 break;
265 }
266 if (format & AD1848_STEREO)
267 size >>= 1;
268 return size;
269}
270
271static int snd_ad1848_trigger(struct snd_ad1848 *chip, unsigned char what,
272 int channel, int cmd)
273{
274 int result = 0;
275
276#if 0
277 printk("codec trigger!!! - what = %i, enable = %i, status = 0x%x\n", what, enable, inb(AD1848P(card, STATUS)));
278#endif
279 spin_lock(&chip->reg_lock);
280 if (cmd == SNDRV_PCM_TRIGGER_START) {
281 if (chip->image[AD1848_IFACE_CTRL] & what) {
282 spin_unlock(&chip->reg_lock);
283 return 0;
284 }
285 snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL] |= what);
286 chip->mode |= AD1848_MODE_RUNNING;
287 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
288 if (!(chip->image[AD1848_IFACE_CTRL] & what)) {
289 spin_unlock(&chip->reg_lock);
290 return 0;
291 }
292 snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL] &= ~what);
293 chip->mode &= ~AD1848_MODE_RUNNING;
294 } else {
295 result = -EINVAL;
296 }
297 spin_unlock(&chip->reg_lock);
298 return result;
299}
300
301/*
302 * CODEC I/O
303 */
304
305static unsigned char snd_ad1848_get_rate(unsigned int rate)
306{
307 int i;
308
309 for (i = 0; i < ARRAY_SIZE(rates); i++)
310 if (rate == rates[i])
311 return freq_bits[i];
312 snd_BUG();
313 return freq_bits[ARRAY_SIZE(rates) - 1];
314}
315
316static int snd_ad1848_ioctl(struct snd_pcm_substream *substream,
317 unsigned int cmd, void *arg)
318{
319 return snd_pcm_lib_ioctl(substream, cmd, arg);
320}
321
322static unsigned char snd_ad1848_get_format(int format, int channels)
323{
324 unsigned char rformat;
325
326 rformat = AD1848_LINEAR_8;
327 switch (format) {
328 case SNDRV_PCM_FORMAT_A_LAW: rformat = AD1848_ALAW_8; break;
329 case SNDRV_PCM_FORMAT_MU_LAW: rformat = AD1848_ULAW_8; break;
330 case SNDRV_PCM_FORMAT_S16_LE: rformat = AD1848_LINEAR_16; break;
331 }
332 if (channels > 1)
333 rformat |= AD1848_STEREO;
334#if 0
335 snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
336#endif
337 return rformat;
338}
339
340static void snd_ad1848_calibrate_mute(struct snd_ad1848 *chip, int mute)
341{
342 unsigned long flags;
343
344 mute = mute ? 1 : 0;
345 spin_lock_irqsave(&chip->reg_lock, flags);
346 if (chip->calibrate_mute == mute) {
347 spin_unlock_irqrestore(&chip->reg_lock, flags);
348 return;
349 }
350 if (!mute) {
351 snd_ad1848_dout(chip, AD1848_LEFT_INPUT, chip->image[AD1848_LEFT_INPUT]);
352 snd_ad1848_dout(chip, AD1848_RIGHT_INPUT, chip->image[AD1848_RIGHT_INPUT]);
353 }
354 snd_ad1848_dout(chip, AD1848_AUX1_LEFT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX1_LEFT_INPUT]);
355 snd_ad1848_dout(chip, AD1848_AUX1_RIGHT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX1_RIGHT_INPUT]);
356 snd_ad1848_dout(chip, AD1848_AUX2_LEFT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX2_LEFT_INPUT]);
357 snd_ad1848_dout(chip, AD1848_AUX2_RIGHT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX2_RIGHT_INPUT]);
358 snd_ad1848_dout(chip, AD1848_LEFT_OUTPUT, mute ? 0x80 : chip->image[AD1848_LEFT_OUTPUT]);
359 snd_ad1848_dout(chip, AD1848_RIGHT_OUTPUT, mute ? 0x80 : chip->image[AD1848_RIGHT_OUTPUT]);
360 chip->calibrate_mute = mute;
361 spin_unlock_irqrestore(&chip->reg_lock, flags);
362}
363
364static void snd_ad1848_set_data_format(struct snd_ad1848 *chip, struct snd_pcm_hw_params *hw_params)
365{
366 if (hw_params == NULL) {
367 chip->image[AD1848_DATA_FORMAT] = 0x20;
368 } else {
369 chip->image[AD1848_DATA_FORMAT] =
370 snd_ad1848_get_format(params_format(hw_params), params_channels(hw_params)) |
371 snd_ad1848_get_rate(params_rate(hw_params));
372 }
373 // snd_printk(">>> pmode = 0x%x, dfr = 0x%x\n", pstr->mode, chip->image[AD1848_DATA_FORMAT]);
374}
375
376static int snd_ad1848_open(struct snd_ad1848 *chip, unsigned int mode)
377{
378 unsigned long flags;
379
380 if (chip->mode & AD1848_MODE_OPEN)
381 return -EAGAIN;
382
383 snd_ad1848_mce_down(chip);
384
385#ifdef SNDRV_DEBUG_MCE
386 snd_printk("open: (1)\n");
387#endif
388 snd_ad1848_mce_up(chip);
389 spin_lock_irqsave(&chip->reg_lock, flags);
390 chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO |
391 AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO |
392 AD1848_CALIB_MODE);
393 chip->image[AD1848_IFACE_CTRL] |= AD1848_AUTOCALIB;
394 snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]);
395 spin_unlock_irqrestore(&chip->reg_lock, flags);
396 snd_ad1848_mce_down(chip);
397
398#ifdef SNDRV_DEBUG_MCE
399 snd_printk("open: (2)\n");
400#endif
401
402 snd_ad1848_set_data_format(chip, NULL);
403
404 snd_ad1848_mce_up(chip);
405 spin_lock_irqsave(&chip->reg_lock, flags);
406 snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]);
407 spin_unlock_irqrestore(&chip->reg_lock, flags);
408 snd_ad1848_mce_down(chip);
409
410#ifdef SNDRV_DEBUG_MCE
411 snd_printk("open: (3)\n");
412#endif
413
414 /* ok. now enable and ack CODEC IRQ */
415 spin_lock_irqsave(&chip->reg_lock, flags);
416 outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
417 outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
418 chip->image[AD1848_PIN_CTRL] |= AD1848_IRQ_ENABLE;
419 snd_ad1848_out(chip, AD1848_PIN_CTRL, chip->image[AD1848_PIN_CTRL]);
420 spin_unlock_irqrestore(&chip->reg_lock, flags);
421
422 chip->mode = mode;
423
424 return 0;
425}
426
427static void snd_ad1848_close(struct snd_ad1848 *chip)
428{
429 unsigned long flags;
430
431 if (!chip->mode)
432 return;
433 /* disable IRQ */
434 spin_lock_irqsave(&chip->reg_lock, flags);
435 outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
436 outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
437 chip->image[AD1848_PIN_CTRL] &= ~AD1848_IRQ_ENABLE;
438 snd_ad1848_out(chip, AD1848_PIN_CTRL, chip->image[AD1848_PIN_CTRL]);
439 spin_unlock_irqrestore(&chip->reg_lock, flags);
440
441 /* now disable capture & playback */
442
443 snd_ad1848_mce_up(chip);
444 spin_lock_irqsave(&chip->reg_lock, flags);
445 chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO |
446 AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO);
447 snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]);
448 spin_unlock_irqrestore(&chip->reg_lock, flags);
449 snd_ad1848_mce_down(chip);
450
451 /* clear IRQ again */
452 spin_lock_irqsave(&chip->reg_lock, flags);
453 outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
454 outb(0, AD1848P(chip, STATUS)); /* clear IRQ */
455 spin_unlock_irqrestore(&chip->reg_lock, flags);
456
457 chip->mode = 0;
458}
459
460/*
461 * ok.. exported functions..
462 */
463
464static int snd_ad1848_playback_trigger(struct snd_pcm_substream *substream,
465 int cmd)
466{
467 struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
468 return snd_ad1848_trigger(chip, AD1848_PLAYBACK_ENABLE, SNDRV_PCM_STREAM_PLAYBACK, cmd);
469}
470
471static int snd_ad1848_capture_trigger(struct snd_pcm_substream *substream,
472 int cmd)
473{
474 struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
475 return snd_ad1848_trigger(chip, AD1848_CAPTURE_ENABLE, SNDRV_PCM_STREAM_CAPTURE, cmd);
476}
477
478static int snd_ad1848_playback_hw_params(struct snd_pcm_substream *substream,
479 struct snd_pcm_hw_params *hw_params)
480{
481 struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
482 unsigned long flags;
483 int err;
484
485 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
486 return err;
487 snd_ad1848_calibrate_mute(chip, 1);
488 snd_ad1848_set_data_format(chip, hw_params);
489 snd_ad1848_mce_up(chip);
490 spin_lock_irqsave(&chip->reg_lock, flags);
491 snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]);
492 spin_unlock_irqrestore(&chip->reg_lock, flags);
493 snd_ad1848_mce_down(chip);
494 snd_ad1848_calibrate_mute(chip, 0);
495 return 0;
496}
497
498static int snd_ad1848_playback_hw_free(struct snd_pcm_substream *substream)
499{
500 return snd_pcm_lib_free_pages(substream);
501}
502
503static int snd_ad1848_playback_prepare(struct snd_pcm_substream *substream)
504{
505 struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
506 struct snd_pcm_runtime *runtime = substream->runtime;
507 unsigned long flags;
508 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
509 unsigned int count = snd_pcm_lib_period_bytes(substream);
510
511 chip->dma_size = size;
512 chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO);
513 snd_dma_program(chip->dma, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
514 count = snd_ad1848_get_count(chip->image[AD1848_DATA_FORMAT], count) - 1;
515 spin_lock_irqsave(&chip->reg_lock, flags);
516 snd_ad1848_out(chip, AD1848_DATA_LWR_CNT, (unsigned char) count);
517 snd_ad1848_out(chip, AD1848_DATA_UPR_CNT, (unsigned char) (count >> 8));
518 spin_unlock_irqrestore(&chip->reg_lock, flags);
519 return 0;
520}
521
522static int snd_ad1848_capture_hw_params(struct snd_pcm_substream *substream,
523 struct snd_pcm_hw_params *hw_params)
524{
525 struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
526 unsigned long flags;
527 int err;
528
529 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
530 return err;
531 snd_ad1848_calibrate_mute(chip, 1);
532 snd_ad1848_set_data_format(chip, hw_params);
533 snd_ad1848_mce_up(chip);
534 spin_lock_irqsave(&chip->reg_lock, flags);
535 snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]);
536 spin_unlock_irqrestore(&chip->reg_lock, flags);
537 snd_ad1848_mce_down(chip);
538 snd_ad1848_calibrate_mute(chip, 0);
539 return 0;
540}
541
542static int snd_ad1848_capture_hw_free(struct snd_pcm_substream *substream)
543{
544 return snd_pcm_lib_free_pages(substream);
545}
546
547static int snd_ad1848_capture_prepare(struct snd_pcm_substream *substream)
548{
549 struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
550 struct snd_pcm_runtime *runtime = substream->runtime;
551 unsigned long flags;
552 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
553 unsigned int count = snd_pcm_lib_period_bytes(substream);
554
555 chip->dma_size = size;
556 chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO);
557 snd_dma_program(chip->dma, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
558 count = snd_ad1848_get_count(chip->image[AD1848_DATA_FORMAT], count) - 1;
559 spin_lock_irqsave(&chip->reg_lock, flags);
560 snd_ad1848_out(chip, AD1848_DATA_LWR_CNT, (unsigned char) count);
561 snd_ad1848_out(chip, AD1848_DATA_UPR_CNT, (unsigned char) (count >> 8));
562 spin_unlock_irqrestore(&chip->reg_lock, flags);
563 return 0;
564}
565
566static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id)
567{
568 struct snd_ad1848 *chip = dev_id;
569
570 if ((chip->mode & AD1848_MODE_PLAY) && chip->playback_substream &&
571 (chip->mode & AD1848_MODE_RUNNING))
572 snd_pcm_period_elapsed(chip->playback_substream);
573 if ((chip->mode & AD1848_MODE_CAPTURE) && chip->capture_substream &&
574 (chip->mode & AD1848_MODE_RUNNING))
575 snd_pcm_period_elapsed(chip->capture_substream);
576 outb(0, AD1848P(chip, STATUS)); /* clear global interrupt bit */
577 return IRQ_HANDLED;
578}
579
580static snd_pcm_uframes_t snd_ad1848_playback_pointer(struct snd_pcm_substream *substream)
581{
582 struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
583 size_t ptr;
584
585 if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_PLAYBACK_ENABLE))
586 return 0;
587 ptr = snd_dma_pointer(chip->dma, chip->dma_size);
588 return bytes_to_frames(substream->runtime, ptr);
589}
590
591static snd_pcm_uframes_t snd_ad1848_capture_pointer(struct snd_pcm_substream *substream)
592{
593 struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
594 size_t ptr;
595
596 if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_CAPTURE_ENABLE))
597 return 0;
598 ptr = snd_dma_pointer(chip->dma, chip->dma_size);
599 return bytes_to_frames(substream->runtime, ptr);
600}
601
602/*
603
604 */
605
606static void snd_ad1848_thinkpad_twiddle(struct snd_ad1848 *chip, int on) {
607
608 int tmp;
609
610 if (!chip->thinkpad_flag) return;
611
612 outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
613 tmp = inb(AD1848_THINKPAD_CTL_PORT2);
614
615 if (on)
616 /* turn it on */
617 tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
618 else
619 /* turn it off */
620 tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
621
622 outb(tmp, AD1848_THINKPAD_CTL_PORT2);
623
624}
625
626#ifdef CONFIG_PM
627static void snd_ad1848_suspend(struct snd_ad1848 *chip)
628{
629 snd_pcm_suspend_all(chip->pcm);
630 if (chip->thinkpad_flag)
631 snd_ad1848_thinkpad_twiddle(chip, 0);
632}
633
634static void snd_ad1848_resume(struct snd_ad1848 *chip)
635{
636 int i;
637
638 if (chip->thinkpad_flag)
639 snd_ad1848_thinkpad_twiddle(chip, 1);
640
641 /* clear any pendings IRQ */
642 inb(AD1848P(chip, STATUS));
643 outb(0, AD1848P(chip, STATUS));
644 mb();
645
646 snd_ad1848_mce_down(chip);
647 for (i = 0; i < 16; i++)
648 snd_ad1848_out(chip, i, chip->image[i]);
649 snd_ad1848_mce_up(chip);
650 snd_ad1848_mce_down(chip);
651}
652#endif /* CONFIG_PM */
653
654static int snd_ad1848_probe(struct snd_ad1848 * chip)
655{
656 unsigned long flags;
657 int i, id, rev, ad1847;
658 unsigned char *ptr;
659
660#if 0
661 snd_ad1848_debug(chip);
662#endif
663 id = ad1847 = 0;
664 for (i = 0; i < 1000; i++) {
665 mb();
666 if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)
667 udelay(500);
668 else {
669 spin_lock_irqsave(&chip->reg_lock, flags);
670 snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00);
671 snd_ad1848_out(chip, AD1848_LEFT_INPUT, 0xaa);
672 snd_ad1848_out(chip, AD1848_RIGHT_INPUT, 0x45);
673 rev = snd_ad1848_in(chip, AD1848_RIGHT_INPUT);
674 if (rev == 0x65) {
675 spin_unlock_irqrestore(&chip->reg_lock, flags);
676 id = 1;
677 ad1847 = 1;
678 break;
679 }
680 if (snd_ad1848_in(chip, AD1848_LEFT_INPUT) == 0xaa && rev == 0x45) {
681 spin_unlock_irqrestore(&chip->reg_lock, flags);
682 id = 1;
683 break;
684 }
685 spin_unlock_irqrestore(&chip->reg_lock, flags);
686 }
687 }
688 if (id != 1)
689 return -ENODEV; /* no valid device found */
690 if (chip->hardware == AD1848_HW_DETECT) {
691 if (ad1847) {
692 chip->hardware = AD1848_HW_AD1847;
693 } else {
694 chip->hardware = AD1848_HW_AD1848;
695 rev = snd_ad1848_in(chip, AD1848_MISC_INFO);
696 if (rev & 0x80) {
697 chip->hardware = AD1848_HW_CS4248;
698 } else if ((rev & 0x0f) == 0x0a) {
699 snd_ad1848_out(chip, AD1848_MISC_INFO, 0x40);
700 for (i = 0; i < 16; ++i) {
701 if (snd_ad1848_in(chip, i) != snd_ad1848_in(chip, i + 16)) {
702 chip->hardware = AD1848_HW_CMI8330;
703 break;
704 }
705 }
706 snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00);
707 }
708 }
709 }
710 spin_lock_irqsave(&chip->reg_lock, flags);
711 inb(AD1848P(chip, STATUS)); /* clear any pendings IRQ */
712 outb(0, AD1848P(chip, STATUS));
713 mb();
714 spin_unlock_irqrestore(&chip->reg_lock, flags);
715
716 chip->image[AD1848_MISC_INFO] = 0x00;
717 chip->image[AD1848_IFACE_CTRL] =
718 (chip->image[AD1848_IFACE_CTRL] & ~AD1848_SINGLE_DMA) | AD1848_SINGLE_DMA;
719 ptr = (unsigned char *) &chip->image;
720 snd_ad1848_mce_down(chip);
721 spin_lock_irqsave(&chip->reg_lock, flags);
722 for (i = 0; i < 16; i++) /* ok.. fill all AD1848 registers */
723 snd_ad1848_out(chip, i, *ptr++);
724 spin_unlock_irqrestore(&chip->reg_lock, flags);
725 snd_ad1848_mce_up(chip);
726 snd_ad1848_mce_down(chip);
727 return 0; /* all things are ok.. */
728}
729
730/*
731
732 */
733
734static struct snd_pcm_hardware snd_ad1848_playback =
735{
736 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
737 SNDRV_PCM_INFO_MMAP_VALID),
738 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
739 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE),
740 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
741 .rate_min = 5510,
742 .rate_max = 48000,
743 .channels_min = 1,
744 .channels_max = 2,
745 .buffer_bytes_max = (128*1024),
746 .period_bytes_min = 64,
747 .period_bytes_max = (128*1024),
748 .periods_min = 1,
749 .periods_max = 1024,
750 .fifo_size = 0,
751};
752
753static struct snd_pcm_hardware snd_ad1848_capture =
754{
755 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
756 SNDRV_PCM_INFO_MMAP_VALID),
757 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
758 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE),
759 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
760 .rate_min = 5510,
761 .rate_max = 48000,
762 .channels_min = 1,
763 .channels_max = 2,
764 .buffer_bytes_max = (128*1024),
765 .period_bytes_min = 64,
766 .period_bytes_max = (128*1024),
767 .periods_min = 1,
768 .periods_max = 1024,
769 .fifo_size = 0,
770};
771
772/*
773
774 */
775
776static int snd_ad1848_playback_open(struct snd_pcm_substream *substream)
777{
778 struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
779 struct snd_pcm_runtime *runtime = substream->runtime;
780 int err;
781
782 if ((err = snd_ad1848_open(chip, AD1848_MODE_PLAY)) < 0)
783 return err;
784 chip->playback_substream = substream;
785 runtime->hw = snd_ad1848_playback;
786 snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.buffer_bytes_max);
787 snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.period_bytes_max);
788 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
789 return 0;
790}
791
792static int snd_ad1848_capture_open(struct snd_pcm_substream *substream)
793{
794 struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
795 struct snd_pcm_runtime *runtime = substream->runtime;
796 int err;
797
798 if ((err = snd_ad1848_open(chip, AD1848_MODE_CAPTURE)) < 0)
799 return err;
800 chip->capture_substream = substream;
801 runtime->hw = snd_ad1848_capture;
802 snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.buffer_bytes_max);
803 snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.period_bytes_max);
804 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
805 return 0;
806}
807
808static int snd_ad1848_playback_close(struct snd_pcm_substream *substream)
809{
810 struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
811
812 chip->mode &= ~AD1848_MODE_PLAY;
813 chip->playback_substream = NULL;
814 snd_ad1848_close(chip);
815 return 0;
816}
817
818static int snd_ad1848_capture_close(struct snd_pcm_substream *substream)
819{
820 struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
821
822 chip->mode &= ~AD1848_MODE_CAPTURE;
823 chip->capture_substream = NULL;
824 snd_ad1848_close(chip);
825 return 0;
826}
827
828static int snd_ad1848_free(struct snd_ad1848 *chip)
829{
830 release_and_free_resource(chip->res_port);
831 if (chip->irq >= 0)
832 free_irq(chip->irq, (void *) chip);
833 if (chip->dma >= 0) {
834 snd_dma_disable(chip->dma);
835 free_dma(chip->dma);
836 }
837 kfree(chip);
838 return 0;
839}
840
841static int snd_ad1848_dev_free(struct snd_device *device)
842{
843 struct snd_ad1848 *chip = device->device_data;
844 return snd_ad1848_free(chip);
845}
846
847static const char *snd_ad1848_chip_id(struct snd_ad1848 *chip)
848{
849 switch (chip->hardware) {
850 case AD1848_HW_AD1847: return "AD1847";
851 case AD1848_HW_AD1848: return "AD1848";
852 case AD1848_HW_CS4248: return "CS4248";
853 case AD1848_HW_CMI8330: return "CMI8330/C3D";
854 default: return "???";
855 }
856}
857
858int snd_ad1848_create(struct snd_card *card,
859 unsigned long port,
860 int irq, int dma,
861 unsigned short hardware,
862 struct snd_ad1848 ** rchip)
863{
864 static struct snd_device_ops ops = {
865 .dev_free = snd_ad1848_dev_free,
866 };
867 struct snd_ad1848 *chip;
868 int err;
869
870 *rchip = NULL;
871 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
872 if (chip == NULL)
873 return -ENOMEM;
874 spin_lock_init(&chip->reg_lock);
875 chip->card = card;
876 chip->port = port;
877 chip->irq = -1;
878 chip->dma = -1;
879 chip->hardware = hardware;
880 memcpy(&chip->image, &snd_ad1848_original_image, sizeof(snd_ad1848_original_image));
881
882 if ((chip->res_port = request_region(port, 4, "AD1848")) == NULL) {
883 snd_printk(KERN_ERR "ad1848: can't grab port 0x%lx\n", port);
884 snd_ad1848_free(chip);
885 return -EBUSY;
886 }
887 if (request_irq(irq, snd_ad1848_interrupt, IRQF_DISABLED, "AD1848", (void *) chip)) {
888 snd_printk(KERN_ERR "ad1848: can't grab IRQ %d\n", irq);
889 snd_ad1848_free(chip);
890 return -EBUSY;
891 }
892 chip->irq = irq;
893 if (request_dma(dma, "AD1848")) {
894 snd_printk(KERN_ERR "ad1848: can't grab DMA %d\n", dma);
895 snd_ad1848_free(chip);
896 return -EBUSY;
897 }
898 chip->dma = dma;
899
900 if (hardware == AD1848_HW_THINKPAD) {
901 chip->thinkpad_flag = 1;
902 chip->hardware = AD1848_HW_DETECT; /* reset */
903 snd_ad1848_thinkpad_twiddle(chip, 1);
904 }
905
906 if (snd_ad1848_probe(chip) < 0) {
907 snd_ad1848_free(chip);
908 return -ENODEV;
909 }
910
911 /* Register device */
912 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
913 snd_ad1848_free(chip);
914 return err;
915 }
916
917#ifdef CONFIG_PM
918 chip->suspend = snd_ad1848_suspend;
919 chip->resume = snd_ad1848_resume;
920#endif
921
922 *rchip = chip;
923 return 0;
924}
925
926EXPORT_SYMBOL(snd_ad1848_create);
927
928static struct snd_pcm_ops snd_ad1848_playback_ops = {
929 .open = snd_ad1848_playback_open,
930 .close = snd_ad1848_playback_close,
931 .ioctl = snd_ad1848_ioctl,
932 .hw_params = snd_ad1848_playback_hw_params,
933 .hw_free = snd_ad1848_playback_hw_free,
934 .prepare = snd_ad1848_playback_prepare,
935 .trigger = snd_ad1848_playback_trigger,
936 .pointer = snd_ad1848_playback_pointer,
937};
938
939static struct snd_pcm_ops snd_ad1848_capture_ops = {
940 .open = snd_ad1848_capture_open,
941 .close = snd_ad1848_capture_close,
942 .ioctl = snd_ad1848_ioctl,
943 .hw_params = snd_ad1848_capture_hw_params,
944 .hw_free = snd_ad1848_capture_hw_free,
945 .prepare = snd_ad1848_capture_prepare,
946 .trigger = snd_ad1848_capture_trigger,
947 .pointer = snd_ad1848_capture_pointer,
948};
949
950int snd_ad1848_pcm(struct snd_ad1848 *chip, int device, struct snd_pcm **rpcm)
951{
952 struct snd_pcm *pcm;
953 int err;
954
955 if ((err = snd_pcm_new(chip->card, "AD1848", device, 1, 1, &pcm)) < 0)
956 return err;
957
958 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ad1848_playback_ops);
959 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ad1848_capture_ops);
960
961 pcm->private_data = chip;
962 pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
963 strcpy(pcm->name, snd_ad1848_chip_id(chip));
964
965 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
966 snd_dma_isa_data(),
967 64*1024, chip->dma > 3 ? 128*1024 : 64*1024);
968
969 chip->pcm = pcm;
970 if (rpcm)
971 *rpcm = pcm;
972 return 0;
973}
974
975EXPORT_SYMBOL(snd_ad1848_pcm);
976
977const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction)
978{
979 return direction == SNDRV_PCM_STREAM_PLAYBACK ?
980 &snd_ad1848_playback_ops : &snd_ad1848_capture_ops;
981}
982
983EXPORT_SYMBOL(snd_ad1848_get_pcm_ops);
984
985/*
986 * MIXER part
987 */
988
989static int snd_ad1848_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
990{
991 static char *texts[4] = {
992 "Line", "Aux", "Mic", "Mix"
993 };
994
995 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
996 uinfo->count = 2;
997 uinfo->value.enumerated.items = 4;
998 if (uinfo->value.enumerated.item > 3)
999 uinfo->value.enumerated.item = 3;
1000 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1001 return 0;
1002}
1003
1004static int snd_ad1848_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1005{
1006 struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
1007 unsigned long flags;
1008
1009 spin_lock_irqsave(&chip->reg_lock, flags);
1010 ucontrol->value.enumerated.item[0] = (chip->image[AD1848_LEFT_INPUT] & AD1848_MIXS_ALL) >> 6;
1011 ucontrol->value.enumerated.item[1] = (chip->image[AD1848_RIGHT_INPUT] & AD1848_MIXS_ALL) >> 6;
1012 spin_unlock_irqrestore(&chip->reg_lock, flags);
1013 return 0;
1014}
1015
1016static int snd_ad1848_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1017{
1018 struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
1019 unsigned long flags;
1020 unsigned short left, right;
1021 int change;
1022
1023 if (ucontrol->value.enumerated.item[0] > 3 ||
1024 ucontrol->value.enumerated.item[1] > 3)
1025 return -EINVAL;
1026 left = ucontrol->value.enumerated.item[0] << 6;
1027 right = ucontrol->value.enumerated.item[1] << 6;
1028 spin_lock_irqsave(&chip->reg_lock, flags);
1029 left = (chip->image[AD1848_LEFT_INPUT] & ~AD1848_MIXS_ALL) | left;
1030 right = (chip->image[AD1848_RIGHT_INPUT] & ~AD1848_MIXS_ALL) | right;
1031 change = left != chip->image[AD1848_LEFT_INPUT] ||
1032 right != chip->image[AD1848_RIGHT_INPUT];
1033 snd_ad1848_out(chip, AD1848_LEFT_INPUT, left);
1034 snd_ad1848_out(chip, AD1848_RIGHT_INPUT, right);
1035 spin_unlock_irqrestore(&chip->reg_lock, flags);
1036 return change;
1037}
1038
1039static int snd_ad1848_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1040{
1041 int mask = (kcontrol->private_value >> 16) & 0xff;
1042
1043 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1044 uinfo->count = 1;
1045 uinfo->value.integer.min = 0;
1046 uinfo->value.integer.max = mask;
1047 return 0;
1048}
1049
1050static int snd_ad1848_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1051{
1052 struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
1053 unsigned long flags;
1054 int reg = kcontrol->private_value & 0xff;
1055 int shift = (kcontrol->private_value >> 8) & 0xff;
1056 int mask = (kcontrol->private_value >> 16) & 0xff;
1057 int invert = (kcontrol->private_value >> 24) & 0xff;
1058
1059 spin_lock_irqsave(&chip->reg_lock, flags);
1060 ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
1061 spin_unlock_irqrestore(&chip->reg_lock, flags);
1062 if (invert)
1063 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
1064 return 0;
1065}
1066
1067static int snd_ad1848_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1068{
1069 struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
1070 unsigned long flags;
1071 int reg = kcontrol->private_value & 0xff;
1072 int shift = (kcontrol->private_value >> 8) & 0xff;
1073 int mask = (kcontrol->private_value >> 16) & 0xff;
1074 int invert = (kcontrol->private_value >> 24) & 0xff;
1075 int change;
1076 unsigned short val;
1077
1078 val = (ucontrol->value.integer.value[0] & mask);
1079 if (invert)
1080 val = mask - val;
1081 val <<= shift;
1082 spin_lock_irqsave(&chip->reg_lock, flags);
1083 val = (chip->image[reg] & ~(mask << shift)) | val;
1084 change = val != chip->image[reg];
1085 snd_ad1848_out(chip, reg, val);
1086 spin_unlock_irqrestore(&chip->reg_lock, flags);
1087 return change;
1088}
1089
1090static int snd_ad1848_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1091{
1092 int mask = (kcontrol->private_value >> 24) & 0xff;
1093
1094 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1095 uinfo->count = 2;
1096 uinfo->value.integer.min = 0;
1097 uinfo->value.integer.max = mask;
1098 return 0;
1099}
1100
1101static int snd_ad1848_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1102{
1103 struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
1104 unsigned long flags;
1105 int left_reg = kcontrol->private_value & 0xff;
1106 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1107 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1108 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1109 int mask = (kcontrol->private_value >> 24) & 0xff;
1110 int invert = (kcontrol->private_value >> 22) & 1;
1111
1112 spin_lock_irqsave(&chip->reg_lock, flags);
1113 ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
1114 ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
1115 spin_unlock_irqrestore(&chip->reg_lock, flags);
1116 if (invert) {
1117 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
1118 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
1119 }
1120 return 0;
1121}
1122
1123static int snd_ad1848_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1124{
1125 struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
1126 unsigned long flags;
1127 int left_reg = kcontrol->private_value & 0xff;
1128 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1129 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1130 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1131 int mask = (kcontrol->private_value >> 24) & 0xff;
1132 int invert = (kcontrol->private_value >> 22) & 1;
1133 int change;
1134 unsigned short val1, val2;
1135
1136 val1 = ucontrol->value.integer.value[0] & mask;
1137 val2 = ucontrol->value.integer.value[1] & mask;
1138 if (invert) {
1139 val1 = mask - val1;
1140 val2 = mask - val2;
1141 }
1142 val1 <<= shift_left;
1143 val2 <<= shift_right;
1144 spin_lock_irqsave(&chip->reg_lock, flags);
1145 if (left_reg != right_reg) {
1146 val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
1147 val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
1148 change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg];
1149 snd_ad1848_out(chip, left_reg, val1);
1150 snd_ad1848_out(chip, right_reg, val2);
1151 } else {
1152 val1 = (chip->image[left_reg] & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
1153 change = val1 != chip->image[left_reg];
1154 snd_ad1848_out(chip, left_reg, val1);
1155 }
1156 spin_unlock_irqrestore(&chip->reg_lock, flags);
1157 return change;
1158}
1159
1160/*
1161 */
1162int snd_ad1848_add_ctl_elem(struct snd_ad1848 *chip,
1163 const struct ad1848_mix_elem *c)
1164{
1165 static struct snd_kcontrol_new newctls[] = {
1166 [AD1848_MIX_SINGLE] = {
1167 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1168 .info = snd_ad1848_info_single,
1169 .get = snd_ad1848_get_single,
1170 .put = snd_ad1848_put_single,
1171 },
1172 [AD1848_MIX_DOUBLE] = {
1173 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1174 .info = snd_ad1848_info_double,
1175 .get = snd_ad1848_get_double,
1176 .put = snd_ad1848_put_double,
1177 },
1178 [AD1848_MIX_CAPTURE] = {
1179 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1180 .info = snd_ad1848_info_mux,
1181 .get = snd_ad1848_get_mux,
1182 .put = snd_ad1848_put_mux,
1183 },
1184 };
1185 struct snd_kcontrol *ctl;
1186 int err;
1187
1188 ctl = snd_ctl_new1(&newctls[c->type], chip);
1189 if (! ctl)
1190 return -ENOMEM;
1191 strlcpy(ctl->id.name, c->name, sizeof(ctl->id.name));
1192 ctl->id.index = c->index;
1193 ctl->private_value = c->private_value;
1194 if (c->tlv) {
1195 ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
1196 ctl->tlv.p = c->tlv;
1197 }
1198 if ((err = snd_ctl_add(chip->card, ctl)) < 0)
1199 return err;
1200 return 0;
1201}
1202
1203EXPORT_SYMBOL(snd_ad1848_add_ctl_elem);
1204
1205static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
1206static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
1207static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
1208
1209static struct ad1848_mix_elem snd_ad1848_controls[] = {
1210AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1),
1211AD1848_DOUBLE_TLV("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1,
1212 db_scale_6bit),
1213AD1848_DOUBLE("Aux Playback Switch", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
1214AD1848_DOUBLE_TLV("Aux Playback Volume", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
1215 db_scale_5bit_12db_max),
1216AD1848_DOUBLE("Aux Playback Switch", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
1217AD1848_DOUBLE_TLV("Aux Playback Volume", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
1218 db_scale_5bit_12db_max),
1219AD1848_DOUBLE_TLV("Capture Volume", 0, AD1848_LEFT_INPUT, AD1848_RIGHT_INPUT, 0, 0, 15, 0,
1220 db_scale_rec_gain),
1221{
1222 .name = "Capture Source",
1223 .type = AD1848_MIX_CAPTURE,
1224},
1225AD1848_SINGLE("Loopback Capture Switch", 0, AD1848_LOOPBACK, 0, 1, 0),
1226AD1848_SINGLE_TLV("Loopback Capture Volume", 0, AD1848_LOOPBACK, 1, 63, 0,
1227 db_scale_6bit),
1228};
1229
1230int snd_ad1848_mixer(struct snd_ad1848 *chip)
1231{
1232 struct snd_card *card;
1233 struct snd_pcm *pcm;
1234 unsigned int idx;
1235 int err;
1236
1237 snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL);
1238
1239 pcm = chip->pcm;
1240 card = chip->card;
1241
1242 strcpy(card->mixername, pcm->name);
1243
1244 for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++)
1245 if ((err = snd_ad1848_add_ctl_elem(chip, &snd_ad1848_controls[idx])) < 0)
1246 return err;
1247
1248 return 0;
1249}
1250
1251EXPORT_SYMBOL(snd_ad1848_mixer);
1252
1253/*
1254 * INIT part
1255 */
1256
1257static int __init alsa_ad1848_init(void)
1258{
1259 return 0;
1260}
1261
1262static void __exit alsa_ad1848_exit(void)
1263{
1264}
1265
1266module_init(alsa_ad1848_init)
1267module_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 @@
38#include <linux/moduleparam.h> 38#include <linux/moduleparam.h>
39#include <sound/core.h> 39#include <sound/core.h>
40#include <sound/initval.h> 40#include <sound/initval.h>
41#include <sound/cs4231.h> 41#include <sound/wss.h>
42#include <sound/mpu401.h> 42#include <sound/mpu401.h>
43#include <sound/opl3.h> 43#include <sound/opl3.h>
44 44
@@ -76,7 +76,7 @@ struct snd_card_azt2320 {
76 int dev_no; 76 int dev_no;
77 struct pnp_dev *dev; 77 struct pnp_dev *dev;
78 struct pnp_dev *devmpu; 78 struct pnp_dev *devmpu;
79 struct snd_cs4231 *chip; 79 struct snd_wss *chip;
80}; 80};
81 81
82static struct pnp_card_device_id snd_azt2320_pnpids[] = { 82static struct pnp_card_device_id snd_azt2320_pnpids[] = {
@@ -181,7 +181,7 @@ static int __devinit snd_card_azt2320_probe(int dev,
181 int error; 181 int error;
182 struct snd_card *card; 182 struct snd_card *card;
183 struct snd_card_azt2320 *acard; 183 struct snd_card_azt2320 *acard;
184 struct snd_cs4231 *chip; 184 struct snd_wss *chip;
185 struct snd_opl3 *opl3; 185 struct snd_opl3 *opl3;
186 186
187 if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, 187 if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
@@ -200,11 +200,11 @@ static int __devinit snd_card_azt2320_probe(int dev,
200 return error; 200 return error;
201 } 201 }
202 202
203 if ((error = snd_cs4231_create(card, wss_port[dev], -1, 203 error = snd_wss_create(card, wss_port[dev], -1,
204 irq[dev], 204 irq[dev],
205 dma1[dev], 205 dma1[dev], dma2[dev],
206 dma2[dev], 206 WSS_HW_DETECT, 0, &chip);
207 CS4231_HW_DETECT, 0, &chip)) < 0) { 207 if (error < 0) {
208 snd_card_free(card); 208 snd_card_free(card);
209 return error; 209 return error;
210 } 210 }
@@ -214,15 +214,18 @@ static int __devinit snd_card_azt2320_probe(int dev,
214 sprintf(card->longname, "%s, WSS at 0x%lx, irq %i, dma %i&%i", 214 sprintf(card->longname, "%s, WSS at 0x%lx, irq %i, dma %i&%i",
215 card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]); 215 card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
216 216
217 if ((error = snd_cs4231_pcm(chip, 0, NULL)) < 0) { 217 error = snd_wss_pcm(chip, 0, NULL);
218 if (error < 0) {
218 snd_card_free(card); 219 snd_card_free(card);
219 return error; 220 return error;
220 } 221 }
221 if ((error = snd_cs4231_mixer(chip)) < 0) { 222 error = snd_wss_mixer(chip);
223 if (error < 0) {
222 snd_card_free(card); 224 snd_card_free(card);
223 return error; 225 return error;
224 } 226 }
225 if ((error = snd_cs4231_timer(chip, 0, NULL)) < 0) { 227 error = snd_wss_timer(chip, 0, NULL);
228 if (error < 0) {
226 snd_card_free(card); 229 snd_card_free(card);
227 return error; 230 return error;
228 } 231 }
@@ -293,7 +296,7 @@ static int snd_azt2320_pnp_suspend(struct pnp_card_link *pcard, pm_message_t sta
293{ 296{
294 struct snd_card *card = pnp_get_card_drvdata(pcard); 297 struct snd_card *card = pnp_get_card_drvdata(pcard);
295 struct snd_card_azt2320 *acard = card->private_data; 298 struct snd_card_azt2320 *acard = card->private_data;
296 struct snd_cs4231 *chip = acard->chip; 299 struct snd_wss *chip = acard->chip;
297 300
298 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 301 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
299 chip->suspend(chip); 302 chip->suspend(chip);
@@ -304,7 +307,7 @@ static int snd_azt2320_pnp_resume(struct pnp_card_link *pcard)
304{ 307{
305 struct snd_card *card = pnp_get_card_drvdata(pcard); 308 struct snd_card *card = pnp_get_card_drvdata(pcard);
306 struct snd_card_azt2320 *acard = card->private_data; 309 struct snd_card_azt2320 *acard = card->private_data;
307 struct snd_cs4231 *chip = acard->chip; 310 struct snd_wss *chip = acard->chip;
308 311
309 chip->resume(chip); 312 chip->resume(chip);
310 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 313 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 @@
50#include <linux/pnp.h> 50#include <linux/pnp.h>
51#include <linux/moduleparam.h> 51#include <linux/moduleparam.h>
52#include <sound/core.h> 52#include <sound/core.h>
53#include <sound/ad1848.h> 53#include <sound/wss.h>
54#include <sound/sb.h> 54#include <sound/sb.h>
55#include <sound/initval.h> 55#include <sound/initval.h>
56 56
@@ -151,7 +151,7 @@ struct snd_cmi8330 {
151 struct pnp_dev *play; 151 struct pnp_dev *play;
152#endif 152#endif
153 struct snd_card *card; 153 struct snd_card *card;
154 struct snd_ad1848 *wss; 154 struct snd_wss *wss;
155 struct snd_sb *sb; 155 struct snd_sb *sb;
156 156
157 struct snd_pcm *pcm; 157 struct snd_pcm *pcm;
@@ -174,32 +174,57 @@ MODULE_DEVICE_TABLE(pnp_card, snd_cmi8330_pnpids);
174#endif 174#endif
175 175
176 176
177static struct ad1848_mix_elem snd_cmi8330_controls[] __devinitdata = { 177static struct snd_kcontrol_new snd_cmi8330_controls[] __devinitdata = {
178AD1848_DOUBLE("Master Playback Volume", 0, CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0), 178WSS_DOUBLE("Master Playback Volume", 0,
179AD1848_SINGLE("Loud Playback Switch", 0, CMI8330_MUTEMUX, 6, 1, 1), 179 CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0),
180AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), 180WSS_SINGLE("Loud Playback Switch", 0,
181AD1848_DOUBLE("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1), 181 CMI8330_MUTEMUX, 6, 1, 1),
182AD1848_DOUBLE("Line Playback Switch", 0, CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0), 182WSS_DOUBLE("PCM Playback Switch", 0,
183AD1848_DOUBLE("Line Playback Volume", 0, CMI8330_LINVOL, CMI8330_LINVOL, 4, 0, 15, 0), 183 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
184AD1848_DOUBLE("Line Capture Switch", 0, CMI8330_RMUX3D, CMI8330_RMUX3D, 2, 1, 1, 0), 184WSS_DOUBLE("PCM Playback Volume", 0,
185AD1848_DOUBLE("Line Capture Volume", 0, CMI8330_LINGAIN, CMI8330_LINGAIN, 4, 0, 15, 0), 185 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
186AD1848_DOUBLE("CD Playback Switch", 0, CMI8330_MUTEMUX, CMI8330_MUTEMUX, 2, 1, 1, 0), 186WSS_DOUBLE("Line Playback Switch", 0,
187AD1848_DOUBLE("CD Capture Switch", 0, CMI8330_RMUX3D, CMI8330_RMUX3D, 4, 3, 1, 0), 187 CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0),
188AD1848_DOUBLE("CD Playback Volume", 0, CMI8330_CDINVOL, CMI8330_CDINVOL, 4, 0, 15, 0), 188WSS_DOUBLE("Line Playback Volume", 0,
189AD1848_DOUBLE("CD Capture Volume", 0, CMI8330_CDINGAIN, CMI8330_CDINGAIN, 4, 0, 15, 0), 189 CMI8330_LINVOL, CMI8330_LINVOL, 4, 0, 15, 0),
190AD1848_SINGLE("Mic Playback Switch", 0, CMI8330_MUTEMUX, 0, 1, 0), 190WSS_DOUBLE("Line Capture Switch", 0,
191AD1848_SINGLE("Mic Playback Volume", 0, CMI8330_OUTPUTVOL, 0, 7, 0), 191 CMI8330_RMUX3D, CMI8330_RMUX3D, 2, 1, 1, 0),
192AD1848_SINGLE("Mic Capture Switch", 0, CMI8330_RMUX3D, 0, 1, 0), 192WSS_DOUBLE("Line Capture Volume", 0,
193AD1848_SINGLE("Mic Capture Volume", 0, CMI8330_OUTPUTVOL, 5, 7, 0), 193 CMI8330_LINGAIN, CMI8330_LINGAIN, 4, 0, 15, 0),
194AD1848_DOUBLE("Wavetable Playback Switch", 0, CMI8330_RECMUX, CMI8330_RECMUX, 1, 0, 1, 0), 194WSS_DOUBLE("CD Playback Switch", 0,
195AD1848_DOUBLE("Wavetable Playback Volume", 0, CMI8330_WAVVOL, CMI8330_WAVVOL, 4, 0, 15, 0), 195 CMI8330_MUTEMUX, CMI8330_MUTEMUX, 2, 1, 1, 0),
196AD1848_DOUBLE("Wavetable Capture Switch", 0, CMI8330_RECMUX, CMI8330_RECMUX, 5, 4, 1, 0), 196WSS_DOUBLE("CD Capture Switch", 0,
197AD1848_DOUBLE("Wavetable Capture Volume", 0, CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0), 197 CMI8330_RMUX3D, CMI8330_RMUX3D, 4, 3, 1, 0),
198AD1848_SINGLE("3D Control - Switch", 0, CMI8330_RMUX3D, 5, 1, 1), 198WSS_DOUBLE("CD Playback Volume", 0,
199AD1848_SINGLE("PC Speaker Playback Volume", 0, CMI8330_OUTPUTVOL, 3, 3, 0), 199 CMI8330_CDINVOL, CMI8330_CDINVOL, 4, 0, 15, 0),
200AD1848_SINGLE("FM Playback Switch", 0, CMI8330_RECMUX, 3, 1, 1), 200WSS_DOUBLE("CD Capture Volume", 0,
201AD1848_SINGLE(SNDRV_CTL_NAME_IEC958("Input ",CAPTURE,SWITCH), 0, CMI8330_RMUX3D, 7, 1, 1), 201 CMI8330_CDINGAIN, CMI8330_CDINGAIN, 4, 0, 15, 0),
202AD1848_SINGLE(SNDRV_CTL_NAME_IEC958("Input ",PLAYBACK,SWITCH), 0, CMI8330_MUTEMUX, 7, 1, 1), 202WSS_SINGLE("Mic Playback Switch", 0,
203 CMI8330_MUTEMUX, 0, 1, 0),
204WSS_SINGLE("Mic Playback Volume", 0,
205 CMI8330_OUTPUTVOL, 0, 7, 0),
206WSS_SINGLE("Mic Capture Switch", 0,
207 CMI8330_RMUX3D, 0, 1, 0),
208WSS_SINGLE("Mic Capture Volume", 0,
209 CMI8330_OUTPUTVOL, 5, 7, 0),
210WSS_DOUBLE("Wavetable Playback Switch", 0,
211 CMI8330_RECMUX, CMI8330_RECMUX, 1, 0, 1, 0),
212WSS_DOUBLE("Wavetable Playback Volume", 0,
213 CMI8330_WAVVOL, CMI8330_WAVVOL, 4, 0, 15, 0),
214WSS_DOUBLE("Wavetable Capture Switch", 0,
215 CMI8330_RECMUX, CMI8330_RECMUX, 5, 4, 1, 0),
216WSS_DOUBLE("Wavetable Capture Volume", 0,
217 CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0),
218WSS_SINGLE("3D Control - Switch", 0,
219 CMI8330_RMUX3D, 5, 1, 1),
220WSS_SINGLE("PC Speaker Playback Volume", 0,
221 CMI8330_OUTPUTVOL, 3, 3, 0),
222WSS_SINGLE("FM Playback Switch", 0,
223 CMI8330_RECMUX, 3, 1, 1),
224WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", CAPTURE, SWITCH), 0,
225 CMI8330_RMUX3D, 7, 1, 1),
226WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", PLAYBACK, SWITCH), 0,
227 CMI8330_MUTEMUX, 7, 1, 1),
203}; 228};
204 229
205#ifdef ENABLE_SB_MIXER 230#ifdef ENABLE_SB_MIXER
@@ -268,7 +293,10 @@ static int __devinit snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330
268 strcpy(card->mixername, "CMI8330/C3D"); 293 strcpy(card->mixername, "CMI8330/C3D");
269 294
270 for (idx = 0; idx < ARRAY_SIZE(snd_cmi8330_controls); idx++) { 295 for (idx = 0; idx < ARRAY_SIZE(snd_cmi8330_controls); idx++) {
271 if ((err = snd_ad1848_add_ctl_elem(acard->wss, &snd_cmi8330_controls[idx])) < 0) 296 err = snd_ctl_add(card,
297 snd_ctl_new1(&snd_cmi8330_controls[idx],
298 acard->wss));
299 if (err < 0)
272 return err; 300 return err;
273 } 301 }
274 302
@@ -385,7 +413,7 @@ static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *
385 chip->streams[CMI_SB_STREAM].private_data = chip->sb; 413 chip->streams[CMI_SB_STREAM].private_data = chip->sb;
386 414
387 /* AD1848 */ 415 /* AD1848 */
388 ops = snd_ad1848_get_pcm_ops(CMI_AD_STREAM); 416 ops = snd_wss_get_pcm_ops(CMI_AD_STREAM);
389 chip->streams[CMI_AD_STREAM].ops = *ops; 417 chip->streams[CMI_AD_STREAM].ops = *ops;
390 chip->streams[CMI_AD_STREAM].open = ops->open; 418 chip->streams[CMI_AD_STREAM].open = ops->open;
391 chip->streams[CMI_AD_STREAM].ops.open = cmi_open_callbacks[CMI_AD_STREAM]; 419 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)
461 int i, err; 489 int i, err;
462 490
463 acard = card->private_data; 491 acard = card->private_data;
464 if ((err = snd_ad1848_create(card, 492 err = snd_wss_create(card, wssport[dev] + 4, -1,
465 wssport[dev] + 4, 493 wssirq[dev],
466 wssirq[dev], 494 wssdma[dev], -1,
467 wssdma[dev], 495 WSS_HW_DETECT, 0, &acard->wss);
468 AD1848_HW_DETECT, 496 if (err < 0) {
469 &acard->wss)) < 0) {
470 snd_printk(KERN_ERR PFX "(AD1848) device busy??\n"); 497 snd_printk(KERN_ERR PFX "(AD1848) device busy??\n");
471 return err; 498 return err;
472 } 499 }
473 if (acard->wss->hardware != AD1848_HW_CMI8330) { 500 if (acard->wss->hardware != WSS_HW_CMI8330) {
474 snd_printk(KERN_ERR PFX "(AD1848) not found during probe\n"); 501 snd_printk(KERN_ERR PFX "(AD1848) not found during probe\n");
475 return -ENODEV; 502 return -ENODEV;
476 } 503 }
@@ -489,9 +516,10 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
489 return err; 516 return err;
490 } 517 }
491 518
492 snd_ad1848_out(acard->wss, AD1848_MISC_INFO, 0x40); /* switch on MODE2 */ 519 snd_wss_out(acard->wss, CS4231_MISC_INFO, 0x40); /* switch on MODE2 */
493 for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++) 520 for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++)
494 snd_ad1848_out(acard->wss, i, snd_cmi8330_image[i - CMI8330_RMUX3D]); 521 snd_wss_out(acard->wss, i,
522 snd_cmi8330_image[i - CMI8330_RMUX3D]);
495 523
496 if ((err = snd_cmi8330_mixer(card, acard)) < 0) { 524 if ((err = snd_cmi8330_mixer(card, acard)) < 0) {
497 snd_printk(KERN_ERR PFX "failed to create mixers\n"); 525 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 @@
3# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> 3# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
4# 4#
5 5
6snd-cs4231-lib-objs := cs4231_lib.o
7snd-cs4236-lib-objs := cs4236_lib.o 6snd-cs4236-lib-objs := cs4236_lib.o
8snd-cs4231-objs := cs4231.o 7snd-cs4231-objs := cs4231.o
9snd-cs4232-objs := cs4232.o 8snd-cs4232-objs := cs4232.o
10snd-cs4236-objs := cs4236.o 9snd-cs4236-objs := cs4236.o
11 10
12# Toplevel Module Dependency 11# Toplevel Module Dependency
13obj-$(CONFIG_SND_CS4231_LIB) += snd-cs4231-lib.o
14obj-$(CONFIG_SND_CS4231) += snd-cs4231.o 12obj-$(CONFIG_SND_CS4231) += snd-cs4231.o
15obj-$(CONFIG_SND_CS4232) += snd-cs4232.o 13obj-$(CONFIG_SND_CS4232) += snd-cs4232.o
16obj-$(CONFIG_SND_CS4236) += snd-cs4236.o snd-cs4236-lib.o 14obj-$(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 @@
27#include <linux/wait.h> 27#include <linux/wait.h>
28#include <linux/moduleparam.h> 28#include <linux/moduleparam.h>
29#include <sound/core.h> 29#include <sound/core.h>
30#include <sound/cs4231.h> 30#include <sound/wss.h>
31#include <sound/mpu401.h> 31#include <sound/mpu401.h>
32#include <sound/initval.h> 32#include <sound/initval.h>
33 33
@@ -91,7 +91,7 @@ static int __devinit snd_cs4231_match(struct device *dev, unsigned int n)
91static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n) 91static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n)
92{ 92{
93 struct snd_card *card; 93 struct snd_card *card;
94 struct snd_cs4231 *chip; 94 struct snd_wss *chip;
95 struct snd_pcm *pcm; 95 struct snd_pcm *pcm;
96 int error; 96 int error;
97 97
@@ -99,14 +99,14 @@ static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n)
99 if (!card) 99 if (!card)
100 return -EINVAL; 100 return -EINVAL;
101 101
102 error = snd_cs4231_create(card, port[n], -1, irq[n], dma1[n], dma2[n], 102 error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], dma2[n],
103 CS4231_HW_DETECT, 0, &chip); 103 WSS_HW_DETECT, 0, &chip);
104 if (error < 0) 104 if (error < 0)
105 goto out; 105 goto out;
106 106
107 card->private_data = chip; 107 card->private_data = chip;
108 108
109 error = snd_cs4231_pcm(chip, 0, &pcm); 109 error = snd_wss_pcm(chip, 0, &pcm);
110 if (error < 0) 110 if (error < 0)
111 goto out; 111 goto out;
112 112
@@ -118,11 +118,11 @@ static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n)
118 if (dma2[n] >= 0) 118 if (dma2[n] >= 0)
119 sprintf(card->longname + strlen(card->longname), "&%d", dma2[n]); 119 sprintf(card->longname + strlen(card->longname), "&%d", dma2[n]);
120 120
121 error = snd_cs4231_mixer(chip); 121 error = snd_wss_mixer(chip);
122 if (error < 0) 122 if (error < 0)
123 goto out; 123 goto out;
124 124
125 error = snd_cs4231_timer(chip, 0, NULL); 125 error = snd_wss_timer(chip, 0, NULL);
126 if (error < 0) 126 if (error < 0)
127 goto out; 127 goto out;
128 128
@@ -160,7 +160,7 @@ static int __devexit snd_cs4231_remove(struct device *dev, unsigned int n)
160static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t state) 160static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t state)
161{ 161{
162 struct snd_card *card = dev_get_drvdata(dev); 162 struct snd_card *card = dev_get_drvdata(dev);
163 struct snd_cs4231 *chip = card->private_data; 163 struct snd_wss *chip = card->private_data;
164 164
165 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 165 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
166 chip->suspend(chip); 166 chip->suspend(chip);
@@ -170,7 +170,7 @@ static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t s
170static int snd_cs4231_resume(struct device *dev, unsigned int n) 170static int snd_cs4231_resume(struct device *dev, unsigned int n)
171{ 171{
172 struct snd_card *card = dev_get_drvdata(dev); 172 struct snd_card *card = dev_get_drvdata(dev);
173 struct snd_cs4231 *chip = card->private_data; 173 struct snd_wss *chip = card->private_data;
174 174
175 chip->resume(chip); 175 chip->resume(chip);
176 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 176 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 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
3 * Routines for control of CS4231(A)/CS4232/InterWave & compatible chips
4 *
5 * Bugs:
6 * - sometimes record brokes playback with WSS portion of
7 * Yamaha OPL3-SA3 chip
8 * - CS4231 (GUS MAX) - still trouble with occasional noises
9 * - broken initialization?
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27#include <linux/delay.h>
28#include <linux/pm.h>
29#include <linux/init.h>
30#include <linux/interrupt.h>
31#include <linux/slab.h>
32#include <linux/ioport.h>
33#include <sound/core.h>
34#include <sound/cs4231.h>
35#include <sound/pcm_params.h>
36
37#include <asm/io.h>
38#include <asm/dma.h>
39#include <asm/irq.h>
40
41MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
42MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips");
43MODULE_LICENSE("GPL");
44
45#if 0
46#define SNDRV_DEBUG_MCE
47#endif
48
49/*
50 * Some variables
51 */
52
53static unsigned char freq_bits[14] = {
54 /* 5510 */ 0x00 | CS4231_XTAL2,
55 /* 6620 */ 0x0E | CS4231_XTAL2,
56 /* 8000 */ 0x00 | CS4231_XTAL1,
57 /* 9600 */ 0x0E | CS4231_XTAL1,
58 /* 11025 */ 0x02 | CS4231_XTAL2,
59 /* 16000 */ 0x02 | CS4231_XTAL1,
60 /* 18900 */ 0x04 | CS4231_XTAL2,
61 /* 22050 */ 0x06 | CS4231_XTAL2,
62 /* 27042 */ 0x04 | CS4231_XTAL1,
63 /* 32000 */ 0x06 | CS4231_XTAL1,
64 /* 33075 */ 0x0C | CS4231_XTAL2,
65 /* 37800 */ 0x08 | CS4231_XTAL2,
66 /* 44100 */ 0x0A | CS4231_XTAL2,
67 /* 48000 */ 0x0C | CS4231_XTAL1
68};
69
70static unsigned int rates[14] = {
71 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,
72 27042, 32000, 33075, 37800, 44100, 48000
73};
74
75static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
76 .count = ARRAY_SIZE(rates),
77 .list = rates,
78 .mask = 0,
79};
80
81static int snd_cs4231_xrate(struct snd_pcm_runtime *runtime)
82{
83 return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
84}
85
86static unsigned char snd_cs4231_original_image[32] =
87{
88 0x00, /* 00/00 - lic */
89 0x00, /* 01/01 - ric */
90 0x9f, /* 02/02 - la1ic */
91 0x9f, /* 03/03 - ra1ic */
92 0x9f, /* 04/04 - la2ic */
93 0x9f, /* 05/05 - ra2ic */
94 0xbf, /* 06/06 - loc */
95 0xbf, /* 07/07 - roc */
96 0x20, /* 08/08 - pdfr */
97 CS4231_AUTOCALIB, /* 09/09 - ic */
98 0x00, /* 0a/10 - pc */
99 0x00, /* 0b/11 - ti */
100 CS4231_MODE2, /* 0c/12 - mi */
101 0xfc, /* 0d/13 - lbc */
102 0x00, /* 0e/14 - pbru */
103 0x00, /* 0f/15 - pbrl */
104 0x80, /* 10/16 - afei */
105 0x01, /* 11/17 - afeii */
106 0x9f, /* 12/18 - llic */
107 0x9f, /* 13/19 - rlic */
108 0x00, /* 14/20 - tlb */
109 0x00, /* 15/21 - thb */
110 0x00, /* 16/22 - la3mic/reserved */
111 0x00, /* 17/23 - ra3mic/reserved */
112 0x00, /* 18/24 - afs */
113 0x00, /* 19/25 - lamoc/version */
114 0xcf, /* 1a/26 - mioc */
115 0x00, /* 1b/27 - ramoc/reserved */
116 0x20, /* 1c/28 - cdfr */
117 0x00, /* 1d/29 - res4 */
118 0x00, /* 1e/30 - cbru */
119 0x00, /* 1f/31 - cbrl */
120};
121
122static unsigned char snd_opti93x_original_image[32] =
123{
124 0x00, /* 00/00 - l_mixout_outctrl */
125 0x00, /* 01/01 - r_mixout_outctrl */
126 0x88, /* 02/02 - l_cd_inctrl */
127 0x88, /* 03/03 - r_cd_inctrl */
128 0x88, /* 04/04 - l_a1/fm_inctrl */
129 0x88, /* 05/05 - r_a1/fm_inctrl */
130 0x80, /* 06/06 - l_dac_inctrl */
131 0x80, /* 07/07 - r_dac_inctrl */
132 0x00, /* 08/08 - ply_dataform_reg */
133 0x00, /* 09/09 - if_conf */
134 0x00, /* 0a/10 - pin_ctrl */
135 0x00, /* 0b/11 - err_init_reg */
136 0x0a, /* 0c/12 - id_reg */
137 0x00, /* 0d/13 - reserved */
138 0x00, /* 0e/14 - ply_upcount_reg */
139 0x00, /* 0f/15 - ply_lowcount_reg */
140 0x88, /* 10/16 - reserved/l_a1_inctrl */
141 0x88, /* 11/17 - reserved/r_a1_inctrl */
142 0x88, /* 12/18 - l_line_inctrl */
143 0x88, /* 13/19 - r_line_inctrl */
144 0x88, /* 14/20 - l_mic_inctrl */
145 0x88, /* 15/21 - r_mic_inctrl */
146 0x80, /* 16/22 - l_out_outctrl */
147 0x80, /* 17/23 - r_out_outctrl */
148 0x00, /* 18/24 - reserved */
149 0x00, /* 19/25 - reserved */
150 0x00, /* 1a/26 - reserved */
151 0x00, /* 1b/27 - reserved */
152 0x00, /* 1c/28 - cap_dataform_reg */
153 0x00, /* 1d/29 - reserved */
154 0x00, /* 1e/30 - cap_upcount_reg */
155 0x00 /* 1f/31 - cap_lowcount_reg */
156};
157
158/*
159 * Basic I/O functions
160 */
161
162static inline void cs4231_outb(struct snd_cs4231 *chip, u8 offset, u8 val)
163{
164 outb(val, chip->port + offset);
165}
166
167static inline u8 cs4231_inb(struct snd_cs4231 *chip, u8 offset)
168{
169 return inb(chip->port + offset);
170}
171
172static void snd_cs4231_wait(struct snd_cs4231 *chip)
173{
174 int timeout;
175
176 for (timeout = 250;
177 timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
178 timeout--)
179 udelay(100);
180}
181
182static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg,
183 unsigned char mask, unsigned char value)
184{
185 unsigned char tmp = (chip->image[reg] & mask) | value;
186
187 snd_cs4231_wait(chip);
188#ifdef CONFIG_SND_DEBUG
189 if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
190 snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
191#endif
192 chip->image[reg] = tmp;
193 if (!chip->calibrate_mute) {
194 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
195 wmb();
196 cs4231_outb(chip, CS4231P(REG), tmp);
197 mb();
198 }
199}
200
201static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, unsigned char value)
202{
203 int timeout;
204
205 for (timeout = 250;
206 timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
207 timeout--)
208 udelay(10);
209 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
210 cs4231_outb(chip, CS4231P(REG), value);
211 mb();
212}
213
214void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value)
215{
216 snd_cs4231_wait(chip);
217#ifdef CONFIG_SND_DEBUG
218 if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
219 snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
220#endif
221 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
222 cs4231_outb(chip, CS4231P(REG), value);
223 chip->image[reg] = value;
224 mb();
225 snd_printdd("codec out - reg 0x%x = 0x%x\n",
226 chip->mce_bit | reg, value);
227}
228
229unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg)
230{
231 snd_cs4231_wait(chip);
232#ifdef CONFIG_SND_DEBUG
233 if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
234 snd_printk("in: auto calibration time out - reg = 0x%x\n", reg);
235#endif
236 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
237 mb();
238 return cs4231_inb(chip, CS4231P(REG));
239}
240
241void snd_cs4236_ext_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val)
242{
243 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
244 cs4231_outb(chip, CS4231P(REG), reg | (chip->image[CS4236_EXT_REG] & 0x01));
245 cs4231_outb(chip, CS4231P(REG), val);
246 chip->eimage[CS4236_REG(reg)] = val;
247#if 0
248 printk("ext out : reg = 0x%x, val = 0x%x\n", reg, val);
249#endif
250}
251
252unsigned char snd_cs4236_ext_in(struct snd_cs4231 *chip, unsigned char reg)
253{
254 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
255 cs4231_outb(chip, CS4231P(REG), reg | (chip->image[CS4236_EXT_REG] & 0x01));
256#if 1
257 return cs4231_inb(chip, CS4231P(REG));
258#else
259 {
260 unsigned char res;
261 res = cs4231_inb(chip, CS4231P(REG));
262 printk("ext in : reg = 0x%x, val = 0x%x\n", reg, res);
263 return res;
264 }
265#endif
266}
267
268#if 0
269
270static void snd_cs4231_debug(struct snd_cs4231 *chip)
271{
272 printk("CS4231 REGS: INDEX = 0x%02x ", cs4231_inb(chip, CS4231P(REGSEL)));
273 printk(" STATUS = 0x%02x\n", cs4231_inb(chip, CS4231P(STATUS)));
274 printk(" 0x00: left input = 0x%02x ", snd_cs4231_in(chip, 0x00));
275 printk(" 0x10: alt 1 (CFIG 2) = 0x%02x\n", snd_cs4231_in(chip, 0x10));
276 printk(" 0x01: right input = 0x%02x ", snd_cs4231_in(chip, 0x01));
277 printk(" 0x11: alt 2 (CFIG 3) = 0x%02x\n", snd_cs4231_in(chip, 0x11));
278 printk(" 0x02: GF1 left input = 0x%02x ", snd_cs4231_in(chip, 0x02));
279 printk(" 0x12: left line in = 0x%02x\n", snd_cs4231_in(chip, 0x12));
280 printk(" 0x03: GF1 right input = 0x%02x ", snd_cs4231_in(chip, 0x03));
281 printk(" 0x13: right line in = 0x%02x\n", snd_cs4231_in(chip, 0x13));
282 printk(" 0x04: CD left input = 0x%02x ", snd_cs4231_in(chip, 0x04));
283 printk(" 0x14: timer low = 0x%02x\n", snd_cs4231_in(chip, 0x14));
284 printk(" 0x05: CD right input = 0x%02x ", snd_cs4231_in(chip, 0x05));
285 printk(" 0x15: timer high = 0x%02x\n", snd_cs4231_in(chip, 0x15));
286 printk(" 0x06: left output = 0x%02x ", snd_cs4231_in(chip, 0x06));
287 printk(" 0x16: left MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x16));
288 printk(" 0x07: right output = 0x%02x ", snd_cs4231_in(chip, 0x07));
289 printk(" 0x17: right MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x17));
290 printk(" 0x08: playback format = 0x%02x ", snd_cs4231_in(chip, 0x08));
291 printk(" 0x18: IRQ status = 0x%02x\n", snd_cs4231_in(chip, 0x18));
292 printk(" 0x09: iface (CFIG 1) = 0x%02x ", snd_cs4231_in(chip, 0x09));
293 printk(" 0x19: left line out = 0x%02x\n", snd_cs4231_in(chip, 0x19));
294 printk(" 0x0a: pin control = 0x%02x ", snd_cs4231_in(chip, 0x0a));
295 printk(" 0x1a: mono control = 0x%02x\n", snd_cs4231_in(chip, 0x1a));
296 printk(" 0x0b: init & status = 0x%02x ", snd_cs4231_in(chip, 0x0b));
297 printk(" 0x1b: right line out = 0x%02x\n", snd_cs4231_in(chip, 0x1b));
298 printk(" 0x0c: revision & mode = 0x%02x ", snd_cs4231_in(chip, 0x0c));
299 printk(" 0x1c: record format = 0x%02x\n", snd_cs4231_in(chip, 0x1c));
300 printk(" 0x0d: loopback = 0x%02x ", snd_cs4231_in(chip, 0x0d));
301 printk(" 0x1d: var freq (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x1d));
302 printk(" 0x0e: ply upr count = 0x%02x ", snd_cs4231_in(chip, 0x0e));
303 printk(" 0x1e: ply lwr count = 0x%02x\n", snd_cs4231_in(chip, 0x1e));
304 printk(" 0x0f: rec upr count = 0x%02x ", snd_cs4231_in(chip, 0x0f));
305 printk(" 0x1f: rec lwr count = 0x%02x\n", snd_cs4231_in(chip, 0x1f));
306}
307
308#endif
309
310/*
311 * CS4231 detection / MCE routines
312 */
313
314static void snd_cs4231_busy_wait(struct snd_cs4231 *chip)
315{
316 int timeout;
317
318 /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
319 for (timeout = 5; timeout > 0; timeout--)
320 cs4231_inb(chip, CS4231P(REGSEL));
321 /* end of cleanup sequence */
322 for (timeout = 250;
323 timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
324 timeout--)
325 udelay(10);
326}
327
328void snd_cs4231_mce_up(struct snd_cs4231 *chip)
329{
330 unsigned long flags;
331 int timeout;
332
333 snd_cs4231_wait(chip);
334#ifdef CONFIG_SND_DEBUG
335 if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
336 snd_printk("mce_up - auto calibration time out (0)\n");
337#endif
338 spin_lock_irqsave(&chip->reg_lock, flags);
339 chip->mce_bit |= CS4231_MCE;
340 timeout = cs4231_inb(chip, CS4231P(REGSEL));
341 if (timeout == 0x80)
342 snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
343 if (!(timeout & CS4231_MCE))
344 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
345 spin_unlock_irqrestore(&chip->reg_lock, flags);
346}
347
348void snd_cs4231_mce_down(struct snd_cs4231 *chip)
349{
350 unsigned long flags;
351 unsigned long end_time;
352 int timeout;
353
354 snd_cs4231_busy_wait(chip);
355
356#ifdef CONFIG_SND_DEBUG
357 if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
358 snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL));
359#endif
360 spin_lock_irqsave(&chip->reg_lock, flags);
361 chip->mce_bit &= ~CS4231_MCE;
362 timeout = cs4231_inb(chip, CS4231P(REGSEL));
363 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
364 spin_unlock_irqrestore(&chip->reg_lock, flags);
365 if (timeout == 0x80)
366 snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
367 if ((timeout & CS4231_MCE) == 0 ||
368 !(chip->hardware & (CS4231_HW_CS4231_MASK | CS4231_HW_CS4232_MASK))) {
369 return;
370 }
371
372 /*
373 * Wait for (possible -- during init auto-calibration may not be set)
374 * calibration process to start. Needs upto 5 sample periods on AD1848
375 * which at the slowest possible rate of 5.5125 kHz means 907 us.
376 */
377 msleep(1);
378
379 snd_printdd("(1) jiffies = %lu\n", jiffies);
380
381 /* check condition up to 250 ms */
382 end_time = jiffies + msecs_to_jiffies(250);
383 while (snd_cs4231_in(chip, CS4231_TEST_INIT) &
384 CS4231_CALIB_IN_PROGRESS) {
385
386 if (time_after(jiffies, end_time)) {
387 snd_printk(KERN_ERR "mce_down - "
388 "auto calibration time out (2)\n");
389 return;
390 }
391 msleep(1);
392 }
393
394 snd_printdd("(2) jiffies = %lu\n", jiffies);
395
396 /* check condition up to 100 ms */
397 end_time = jiffies + msecs_to_jiffies(100);
398 while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
399 if (time_after(jiffies, end_time)) {
400 snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
401 return;
402 }
403 msleep(1);
404 }
405
406 snd_printdd("(3) jiffies = %lu\n", jiffies);
407 snd_printd("mce_down - exit = 0x%x\n", cs4231_inb(chip, CS4231P(REGSEL)));
408}
409
410static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size)
411{
412 switch (format & 0xe0) {
413 case CS4231_LINEAR_16:
414 case CS4231_LINEAR_16_BIG:
415 size >>= 1;
416 break;
417 case CS4231_ADPCM_16:
418 return size >> 2;
419 }
420 if (format & CS4231_STEREO)
421 size >>= 1;
422 return size;
423}
424
425static int snd_cs4231_trigger(struct snd_pcm_substream *substream,
426 int cmd)
427{
428 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
429 int result = 0;
430 unsigned int what;
431 struct snd_pcm_substream *s;
432 int do_start;
433
434#if 0
435 printk("codec trigger!!! - what = %i, enable = %i, status = 0x%x\n", what, enable, cs4231_inb(chip, CS4231P(STATUS)));
436#endif
437
438 switch (cmd) {
439 case SNDRV_PCM_TRIGGER_START:
440 case SNDRV_PCM_TRIGGER_RESUME:
441 do_start = 1; break;
442 case SNDRV_PCM_TRIGGER_STOP:
443 case SNDRV_PCM_TRIGGER_SUSPEND:
444 do_start = 0; break;
445 default:
446 return -EINVAL;
447 }
448
449 what = 0;
450 snd_pcm_group_for_each_entry(s, substream) {
451 if (s == chip->playback_substream) {
452 what |= CS4231_PLAYBACK_ENABLE;
453 snd_pcm_trigger_done(s, substream);
454 } else if (s == chip->capture_substream) {
455 what |= CS4231_RECORD_ENABLE;
456 snd_pcm_trigger_done(s, substream);
457 }
458 }
459 spin_lock(&chip->reg_lock);
460 if (do_start) {
461 chip->image[CS4231_IFACE_CTRL] |= what;
462 if (chip->trigger)
463 chip->trigger(chip, what, 1);
464 } else {
465 chip->image[CS4231_IFACE_CTRL] &= ~what;
466 if (chip->trigger)
467 chip->trigger(chip, what, 0);
468 }
469 snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
470 spin_unlock(&chip->reg_lock);
471#if 0
472 snd_cs4231_debug(chip);
473#endif
474 return result;
475}
476
477/*
478 * CODEC I/O
479 */
480
481static unsigned char snd_cs4231_get_rate(unsigned int rate)
482{
483 int i;
484
485 for (i = 0; i < ARRAY_SIZE(rates); i++)
486 if (rate == rates[i])
487 return freq_bits[i];
488 // snd_BUG();
489 return freq_bits[ARRAY_SIZE(rates) - 1];
490}
491
492static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip,
493 int format,
494 int channels)
495{
496 unsigned char rformat;
497
498 rformat = CS4231_LINEAR_8;
499 switch (format) {
500 case SNDRV_PCM_FORMAT_MU_LAW: rformat = CS4231_ULAW_8; break;
501 case SNDRV_PCM_FORMAT_A_LAW: rformat = CS4231_ALAW_8; break;
502 case SNDRV_PCM_FORMAT_S16_LE: rformat = CS4231_LINEAR_16; break;
503 case SNDRV_PCM_FORMAT_S16_BE: rformat = CS4231_LINEAR_16_BIG; break;
504 case SNDRV_PCM_FORMAT_IMA_ADPCM: rformat = CS4231_ADPCM_16; break;
505 }
506 if (channels > 1)
507 rformat |= CS4231_STEREO;
508#if 0
509 snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
510#endif
511 return rformat;
512}
513
514static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute)
515{
516 unsigned long flags;
517
518 mute = mute ? 1 : 0;
519 spin_lock_irqsave(&chip->reg_lock, flags);
520 if (chip->calibrate_mute == mute) {
521 spin_unlock_irqrestore(&chip->reg_lock, flags);
522 return;
523 }
524 if (!mute) {
525 snd_cs4231_dout(chip, CS4231_LEFT_INPUT, chip->image[CS4231_LEFT_INPUT]);
526 snd_cs4231_dout(chip, CS4231_RIGHT_INPUT, chip->image[CS4231_RIGHT_INPUT]);
527 snd_cs4231_dout(chip, CS4231_LOOPBACK, chip->image[CS4231_LOOPBACK]);
528 }
529 snd_cs4231_dout(chip, CS4231_AUX1_LEFT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX1_LEFT_INPUT]);
530 snd_cs4231_dout(chip, CS4231_AUX1_RIGHT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX1_RIGHT_INPUT]);
531 snd_cs4231_dout(chip, CS4231_AUX2_LEFT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX2_LEFT_INPUT]);
532 snd_cs4231_dout(chip, CS4231_AUX2_RIGHT_INPUT, mute ? 0x80 : chip->image[CS4231_AUX2_RIGHT_INPUT]);
533 snd_cs4231_dout(chip, CS4231_LEFT_OUTPUT, mute ? 0x80 : chip->image[CS4231_LEFT_OUTPUT]);
534 snd_cs4231_dout(chip, CS4231_RIGHT_OUTPUT, mute ? 0x80 : chip->image[CS4231_RIGHT_OUTPUT]);
535 snd_cs4231_dout(chip, CS4231_LEFT_LINE_IN, mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]);
536 snd_cs4231_dout(chip, CS4231_RIGHT_LINE_IN, mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]);
537 snd_cs4231_dout(chip, CS4231_MONO_CTRL, mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);
538 if (chip->hardware == CS4231_HW_INTERWAVE) {
539 snd_cs4231_dout(chip, CS4231_LEFT_MIC_INPUT, mute ? 0x80 : chip->image[CS4231_LEFT_MIC_INPUT]);
540 snd_cs4231_dout(chip, CS4231_RIGHT_MIC_INPUT, mute ? 0x80 : chip->image[CS4231_RIGHT_MIC_INPUT]);
541 snd_cs4231_dout(chip, CS4231_LINE_LEFT_OUTPUT, mute ? 0x80 : chip->image[CS4231_LINE_LEFT_OUTPUT]);
542 snd_cs4231_dout(chip, CS4231_LINE_RIGHT_OUTPUT, mute ? 0x80 : chip->image[CS4231_LINE_RIGHT_OUTPUT]);
543 }
544 chip->calibrate_mute = mute;
545 spin_unlock_irqrestore(&chip->reg_lock, flags);
546}
547
548static void snd_cs4231_playback_format(struct snd_cs4231 *chip,
549 struct snd_pcm_hw_params *params,
550 unsigned char pdfr)
551{
552 unsigned long flags;
553 int full_calib = 1;
554
555 mutex_lock(&chip->mce_mutex);
556 snd_cs4231_calibrate_mute(chip, 1);
557 if (chip->hardware == CS4231_HW_CS4231A ||
558 (chip->hardware & CS4231_HW_CS4232_MASK)) {
559 spin_lock_irqsave(&chip->reg_lock, flags);
560 if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (pdfr & 0x0f)) { /* rate is same? */
561 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x10);
562 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr);
563 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~0x10);
564 udelay(100); /* Fixes audible clicks at least on GUS MAX */
565 full_calib = 0;
566 }
567 spin_unlock_irqrestore(&chip->reg_lock, flags);
568 }
569 if (full_calib) {
570 snd_cs4231_mce_up(chip);
571 spin_lock_irqsave(&chip->reg_lock, flags);
572 if (chip->hardware != CS4231_HW_INTERWAVE && !chip->single_dma) {
573 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT,
574 (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) ?
575 (pdfr & 0xf0) | (chip->image[CS4231_REC_FORMAT] & 0x0f) :
576 pdfr);
577 } else {
578 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr);
579 }
580 spin_unlock_irqrestore(&chip->reg_lock, flags);
581 if (chip->hardware == CS4231_HW_OPL3SA2)
582 udelay(100); /* this seems to help */
583 snd_cs4231_mce_down(chip);
584 }
585 snd_cs4231_calibrate_mute(chip, 0);
586 mutex_unlock(&chip->mce_mutex);
587}
588
589static void snd_cs4231_capture_format(struct snd_cs4231 *chip,
590 struct snd_pcm_hw_params *params,
591 unsigned char cdfr)
592{
593 unsigned long flags;
594 int full_calib = 1;
595
596 mutex_lock(&chip->mce_mutex);
597 snd_cs4231_calibrate_mute(chip, 1);
598 if (chip->hardware == CS4231_HW_CS4231A ||
599 (chip->hardware & CS4231_HW_CS4232_MASK)) {
600 spin_lock_irqsave(&chip->reg_lock, flags);
601 if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (cdfr & 0x0f) || /* rate is same? */
602 (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
603 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x20);
604 snd_cs4231_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT] = cdfr);
605 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~0x20);
606 full_calib = 0;
607 }
608 spin_unlock_irqrestore(&chip->reg_lock, flags);
609 }
610 if (full_calib) {
611 snd_cs4231_mce_up(chip);
612 spin_lock_irqsave(&chip->reg_lock, flags);
613 if (chip->hardware != CS4231_HW_INTERWAVE) {
614 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
615 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT,
616 ((chip->single_dma ? cdfr : chip->image[CS4231_PLAYBK_FORMAT]) & 0xf0) |
617 (cdfr & 0x0f));
618 spin_unlock_irqrestore(&chip->reg_lock, flags);
619 snd_cs4231_mce_down(chip);
620 snd_cs4231_mce_up(chip);
621 spin_lock_irqsave(&chip->reg_lock, flags);
622 }
623 }
624 snd_cs4231_out(chip, CS4231_REC_FORMAT, cdfr);
625 spin_unlock_irqrestore(&chip->reg_lock, flags);
626 snd_cs4231_mce_down(chip);
627 }
628 snd_cs4231_calibrate_mute(chip, 0);
629 mutex_unlock(&chip->mce_mutex);
630}
631
632/*
633 * Timer interface
634 */
635
636static unsigned long snd_cs4231_timer_resolution(struct snd_timer * timer)
637{
638 struct snd_cs4231 *chip = snd_timer_chip(timer);
639 if (chip->hardware & CS4231_HW_CS4236B_MASK)
640 return 14467;
641 else
642 return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920;
643}
644
645static int snd_cs4231_timer_start(struct snd_timer * timer)
646{
647 unsigned long flags;
648 unsigned int ticks;
649 struct snd_cs4231 *chip = snd_timer_chip(timer);
650 spin_lock_irqsave(&chip->reg_lock, flags);
651 ticks = timer->sticks;
652 if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 ||
653 (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] ||
654 (unsigned char)ticks != chip->image[CS4231_TIMER_LOW]) {
655 snd_cs4231_out(chip, CS4231_TIMER_HIGH, chip->image[CS4231_TIMER_HIGH] = (unsigned char) (ticks >> 8));
656 snd_cs4231_out(chip, CS4231_TIMER_LOW, chip->image[CS4231_TIMER_LOW] = (unsigned char) ticks);
657 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | CS4231_TIMER_ENABLE);
658 }
659 spin_unlock_irqrestore(&chip->reg_lock, flags);
660 return 0;
661}
662
663static int snd_cs4231_timer_stop(struct snd_timer * timer)
664{
665 unsigned long flags;
666 struct snd_cs4231 *chip = snd_timer_chip(timer);
667 spin_lock_irqsave(&chip->reg_lock, flags);
668 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE);
669 spin_unlock_irqrestore(&chip->reg_lock, flags);
670 return 0;
671}
672
673static void snd_cs4231_init(struct snd_cs4231 *chip)
674{
675 unsigned long flags;
676
677 snd_cs4231_mce_down(chip);
678
679#ifdef SNDRV_DEBUG_MCE
680 snd_printk("init: (1)\n");
681#endif
682 snd_cs4231_mce_up(chip);
683 spin_lock_irqsave(&chip->reg_lock, flags);
684 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
685 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO |
686 CS4231_CALIB_MODE);
687 chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB;
688 snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
689 spin_unlock_irqrestore(&chip->reg_lock, flags);
690 snd_cs4231_mce_down(chip);
691
692#ifdef SNDRV_DEBUG_MCE
693 snd_printk("init: (2)\n");
694#endif
695
696 snd_cs4231_mce_up(chip);
697 spin_lock_irqsave(&chip->reg_lock, flags);
698 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]);
699 spin_unlock_irqrestore(&chip->reg_lock, flags);
700 snd_cs4231_mce_down(chip);
701
702#ifdef SNDRV_DEBUG_MCE
703 snd_printk("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]);
704#endif
705
706 spin_lock_irqsave(&chip->reg_lock, flags);
707 snd_cs4231_out(chip, CS4231_ALT_FEATURE_2, chip->image[CS4231_ALT_FEATURE_2]);
708 spin_unlock_irqrestore(&chip->reg_lock, flags);
709
710 snd_cs4231_mce_up(chip);
711 spin_lock_irqsave(&chip->reg_lock, flags);
712 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT]);
713 spin_unlock_irqrestore(&chip->reg_lock, flags);
714 snd_cs4231_mce_down(chip);
715
716#ifdef SNDRV_DEBUG_MCE
717 snd_printk("init: (4)\n");
718#endif
719
720 snd_cs4231_mce_up(chip);
721 spin_lock_irqsave(&chip->reg_lock, flags);
722 snd_cs4231_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT]);
723 spin_unlock_irqrestore(&chip->reg_lock, flags);
724 snd_cs4231_mce_down(chip);
725
726#ifdef SNDRV_DEBUG_MCE
727 snd_printk("init: (5)\n");
728#endif
729}
730
731static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode)
732{
733 unsigned long flags;
734
735 mutex_lock(&chip->open_mutex);
736 if ((chip->mode & mode) ||
737 ((chip->mode & CS4231_MODE_OPEN) && chip->single_dma)) {
738 mutex_unlock(&chip->open_mutex);
739 return -EAGAIN;
740 }
741 if (chip->mode & CS4231_MODE_OPEN) {
742 chip->mode |= mode;
743 mutex_unlock(&chip->open_mutex);
744 return 0;
745 }
746 /* ok. now enable and ack CODEC IRQ */
747 spin_lock_irqsave(&chip->reg_lock, flags);
748 snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ |
749 CS4231_RECORD_IRQ |
750 CS4231_TIMER_IRQ);
751 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
752 cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
753 cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
754 chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE;
755 snd_cs4231_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
756 snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ |
757 CS4231_RECORD_IRQ |
758 CS4231_TIMER_IRQ);
759 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
760 spin_unlock_irqrestore(&chip->reg_lock, flags);
761
762 chip->mode = mode;
763 mutex_unlock(&chip->open_mutex);
764 return 0;
765}
766
767static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode)
768{
769 unsigned long flags;
770
771 mutex_lock(&chip->open_mutex);
772 chip->mode &= ~mode;
773 if (chip->mode & CS4231_MODE_OPEN) {
774 mutex_unlock(&chip->open_mutex);
775 return;
776 }
777 snd_cs4231_calibrate_mute(chip, 1);
778
779 /* disable IRQ */
780 spin_lock_irqsave(&chip->reg_lock, flags);
781 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
782 cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
783 cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
784 chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE;
785 snd_cs4231_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
786
787 /* now disable record & playback */
788
789 if (chip->image[CS4231_IFACE_CTRL] & (CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
790 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO)) {
791 spin_unlock_irqrestore(&chip->reg_lock, flags);
792 snd_cs4231_mce_up(chip);
793 spin_lock_irqsave(&chip->reg_lock, flags);
794 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
795 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
796 snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
797 spin_unlock_irqrestore(&chip->reg_lock, flags);
798 snd_cs4231_mce_down(chip);
799 spin_lock_irqsave(&chip->reg_lock, flags);
800 }
801
802 /* clear IRQ again */
803 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
804 cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
805 cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
806 spin_unlock_irqrestore(&chip->reg_lock, flags);
807
808 snd_cs4231_calibrate_mute(chip, 0);
809
810 chip->mode = 0;
811 mutex_unlock(&chip->open_mutex);
812}
813
814/*
815 * timer open/close
816 */
817
818static int snd_cs4231_timer_open(struct snd_timer * timer)
819{
820 struct snd_cs4231 *chip = snd_timer_chip(timer);
821 snd_cs4231_open(chip, CS4231_MODE_TIMER);
822 return 0;
823}
824
825static int snd_cs4231_timer_close(struct snd_timer * timer)
826{
827 struct snd_cs4231 *chip = snd_timer_chip(timer);
828 snd_cs4231_close(chip, CS4231_MODE_TIMER);
829 return 0;
830}
831
832static struct snd_timer_hardware snd_cs4231_timer_table =
833{
834 .flags = SNDRV_TIMER_HW_AUTO,
835 .resolution = 9945,
836 .ticks = 65535,
837 .open = snd_cs4231_timer_open,
838 .close = snd_cs4231_timer_close,
839 .c_resolution = snd_cs4231_timer_resolution,
840 .start = snd_cs4231_timer_start,
841 .stop = snd_cs4231_timer_stop,
842};
843
844/*
845 * ok.. exported functions..
846 */
847
848static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream,
849 struct snd_pcm_hw_params *hw_params)
850{
851 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
852 unsigned char new_pdfr;
853 int err;
854
855 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
856 return err;
857 new_pdfr = snd_cs4231_get_format(chip, params_format(hw_params), params_channels(hw_params)) |
858 snd_cs4231_get_rate(params_rate(hw_params));
859 chip->set_playback_format(chip, hw_params, new_pdfr);
860 return 0;
861}
862
863static int snd_cs4231_playback_hw_free(struct snd_pcm_substream *substream)
864{
865 return snd_pcm_lib_free_pages(substream);
866}
867
868static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream)
869{
870 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
871 struct snd_pcm_runtime *runtime = substream->runtime;
872 unsigned long flags;
873 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
874 unsigned int count = snd_pcm_lib_period_bytes(substream);
875
876 spin_lock_irqsave(&chip->reg_lock, flags);
877 chip->p_dma_size = size;
878 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO);
879 snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
880 count = snd_cs4231_get_count(chip->image[CS4231_PLAYBK_FORMAT], count) - 1;
881 snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
882 snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8));
883 spin_unlock_irqrestore(&chip->reg_lock, flags);
884#if 0
885 snd_cs4231_debug(chip);
886#endif
887 return 0;
888}
889
890static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream,
891 struct snd_pcm_hw_params *hw_params)
892{
893 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
894 unsigned char new_cdfr;
895 int err;
896
897 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
898 return err;
899 new_cdfr = snd_cs4231_get_format(chip, params_format(hw_params), params_channels(hw_params)) |
900 snd_cs4231_get_rate(params_rate(hw_params));
901 chip->set_capture_format(chip, hw_params, new_cdfr);
902 return 0;
903}
904
905static int snd_cs4231_capture_hw_free(struct snd_pcm_substream *substream)
906{
907 return snd_pcm_lib_free_pages(substream);
908}
909
910static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream)
911{
912 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
913 struct snd_pcm_runtime *runtime = substream->runtime;
914 unsigned long flags;
915 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
916 unsigned int count = snd_pcm_lib_period_bytes(substream);
917
918 spin_lock_irqsave(&chip->reg_lock, flags);
919 chip->c_dma_size = size;
920 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
921 snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
922 count = snd_cs4231_get_count(chip->image[CS4231_REC_FORMAT], count) - 1;
923 if (chip->single_dma && chip->hardware != CS4231_HW_INTERWAVE) {
924 snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
925 snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8));
926 } else {
927 snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (unsigned char) count);
928 snd_cs4231_out(chip, CS4231_REC_UPR_CNT, (unsigned char) (count >> 8));
929 }
930 spin_unlock_irqrestore(&chip->reg_lock, flags);
931 return 0;
932}
933
934void snd_cs4231_overrange(struct snd_cs4231 *chip)
935{
936 unsigned long flags;
937 unsigned char res;
938
939 spin_lock_irqsave(&chip->reg_lock, flags);
940 res = snd_cs4231_in(chip, CS4231_TEST_INIT);
941 spin_unlock_irqrestore(&chip->reg_lock, flags);
942 if (res & (0x08 | 0x02)) /* detect overrange only above 0dB; may be user selectable? */
943 chip->capture_substream->runtime->overrange++;
944}
945
946irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id)
947{
948 struct snd_cs4231 *chip = dev_id;
949 unsigned char status;
950
951 status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
952 if (status & CS4231_TIMER_IRQ) {
953 if (chip->timer)
954 snd_timer_interrupt(chip->timer, chip->timer->sticks);
955 }
956 if (chip->single_dma && chip->hardware != CS4231_HW_INTERWAVE) {
957 if (status & CS4231_PLAYBACK_IRQ) {
958 if (chip->mode & CS4231_MODE_PLAY) {
959 if (chip->playback_substream)
960 snd_pcm_period_elapsed(chip->playback_substream);
961 }
962 if (chip->mode & CS4231_MODE_RECORD) {
963 if (chip->capture_substream) {
964 snd_cs4231_overrange(chip);
965 snd_pcm_period_elapsed(chip->capture_substream);
966 }
967 }
968 }
969 } else {
970 if (status & CS4231_PLAYBACK_IRQ) {
971 if (chip->playback_substream)
972 snd_pcm_period_elapsed(chip->playback_substream);
973 }
974 if (status & CS4231_RECORD_IRQ) {
975 if (chip->capture_substream) {
976 snd_cs4231_overrange(chip);
977 snd_pcm_period_elapsed(chip->capture_substream);
978 }
979 }
980 }
981
982 spin_lock(&chip->reg_lock);
983 snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);
984 spin_unlock(&chip->reg_lock);
985 return IRQ_HANDLED;
986}
987
988static snd_pcm_uframes_t snd_cs4231_playback_pointer(struct snd_pcm_substream *substream)
989{
990 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
991 size_t ptr;
992
993 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
994 return 0;
995 ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);
996 return bytes_to_frames(substream->runtime, ptr);
997}
998
999static snd_pcm_uframes_t snd_cs4231_capture_pointer(struct snd_pcm_substream *substream)
1000{
1001 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
1002 size_t ptr;
1003
1004 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
1005 return 0;
1006 ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
1007 return bytes_to_frames(substream->runtime, ptr);
1008}
1009
1010/*
1011
1012 */
1013
1014static int snd_cs4231_probe(struct snd_cs4231 *chip)
1015{
1016 unsigned long flags;
1017 int i, id, rev;
1018 unsigned char *ptr;
1019 unsigned int hw;
1020
1021#if 0
1022 snd_cs4231_debug(chip);
1023#endif
1024 id = 0;
1025 for (i = 0; i < 50; i++) {
1026 mb();
1027 if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
1028 udelay(2000);
1029 else {
1030 spin_lock_irqsave(&chip->reg_lock, flags);
1031 snd_cs4231_out(chip, CS4231_MISC_INFO, CS4231_MODE2);
1032 id = snd_cs4231_in(chip, CS4231_MISC_INFO) & 0x0f;
1033 spin_unlock_irqrestore(&chip->reg_lock, flags);
1034 if (id == 0x0a)
1035 break; /* this is valid value */
1036 }
1037 }
1038 snd_printdd("cs4231: port = 0x%lx, id = 0x%x\n", chip->port, id);
1039 if (id != 0x0a)
1040 return -ENODEV; /* no valid device found */
1041
1042 if (((hw = chip->hardware) & CS4231_HW_TYPE_MASK) == CS4231_HW_DETECT) {
1043 rev = snd_cs4231_in(chip, CS4231_VERSION) & 0xe7;
1044 snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev);
1045 if (rev == 0x80) {
1046 unsigned char tmp = snd_cs4231_in(chip, 23);
1047 snd_cs4231_out(chip, 23, ~tmp);
1048 if (snd_cs4231_in(chip, 23) != tmp)
1049 chip->hardware = CS4231_HW_AD1845;
1050 else
1051 chip->hardware = CS4231_HW_CS4231;
1052 } else if (rev == 0xa0) {
1053 chip->hardware = CS4231_HW_CS4231A;
1054 } else if (rev == 0xa2) {
1055 chip->hardware = CS4231_HW_CS4232;
1056 } else if (rev == 0xb2) {
1057 chip->hardware = CS4231_HW_CS4232A;
1058 } else if (rev == 0x83) {
1059 chip->hardware = CS4231_HW_CS4236;
1060 } else if (rev == 0x03) {
1061 chip->hardware = CS4231_HW_CS4236B;
1062 } else {
1063 snd_printk("unknown CS chip with version 0x%x\n", rev);
1064 return -ENODEV; /* unknown CS4231 chip? */
1065 }
1066 }
1067 spin_lock_irqsave(&chip->reg_lock, flags);
1068 cs4231_inb(chip, CS4231P(STATUS)); /* clear any pendings IRQ */
1069 cs4231_outb(chip, CS4231P(STATUS), 0);
1070 mb();
1071 spin_unlock_irqrestore(&chip->reg_lock, flags);
1072
1073 chip->image[CS4231_MISC_INFO] = CS4231_MODE2;
1074 switch (chip->hardware) {
1075 case CS4231_HW_INTERWAVE:
1076 chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3;
1077 break;
1078 case CS4231_HW_CS4235:
1079 case CS4231_HW_CS4236B:
1080 case CS4231_HW_CS4237B:
1081 case CS4231_HW_CS4238B:
1082 case CS4231_HW_CS4239:
1083 if (hw == CS4231_HW_DETECT3)
1084 chip->image[CS4231_MISC_INFO] = CS4231_4236_MODE3;
1085 else
1086 chip->hardware = CS4231_HW_CS4236;
1087 break;
1088 }
1089
1090 chip->image[CS4231_IFACE_CTRL] =
1091 (chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) |
1092 (chip->single_dma ? CS4231_SINGLE_DMA : 0);
1093 if (chip->hardware != CS4231_HW_OPTI93X) {
1094 chip->image[CS4231_ALT_FEATURE_1] = 0x80;
1095 chip->image[CS4231_ALT_FEATURE_2] =
1096 chip->hardware == CS4231_HW_INTERWAVE ? 0xc2 : 0x01;
1097 }
1098 ptr = (unsigned char *) &chip->image;
1099 snd_cs4231_mce_down(chip);
1100 spin_lock_irqsave(&chip->reg_lock, flags);
1101 for (i = 0; i < 32; i++) /* ok.. fill all CS4231 registers */
1102 snd_cs4231_out(chip, i, *ptr++);
1103 spin_unlock_irqrestore(&chip->reg_lock, flags);
1104 snd_cs4231_mce_up(chip);
1105 snd_cs4231_mce_down(chip);
1106
1107 mdelay(2);
1108
1109 /* ok.. try check hardware version for CS4236+ chips */
1110 if ((hw & CS4231_HW_TYPE_MASK) == CS4231_HW_DETECT) {
1111 if (chip->hardware == CS4231_HW_CS4236B) {
1112 rev = snd_cs4236_ext_in(chip, CS4236_VERSION);
1113 snd_cs4236_ext_out(chip, CS4236_VERSION, 0xff);
1114 id = snd_cs4236_ext_in(chip, CS4236_VERSION);
1115 snd_cs4236_ext_out(chip, CS4236_VERSION, rev);
1116 snd_printdd("CS4231: ext version; rev = 0x%x, id = 0x%x\n", rev, id);
1117 if ((id & 0x1f) == 0x1d) { /* CS4235 */
1118 chip->hardware = CS4231_HW_CS4235;
1119 switch (id >> 5) {
1120 case 4:
1121 case 5:
1122 case 6:
1123 break;
1124 default:
1125 snd_printk("unknown CS4235 chip (enhanced version = 0x%x)\n", id);
1126 }
1127 } else if ((id & 0x1f) == 0x0b) { /* CS4236/B */
1128 switch (id >> 5) {
1129 case 4:
1130 case 5:
1131 case 6:
1132 case 7:
1133 chip->hardware = CS4231_HW_CS4236B;
1134 break;
1135 default:
1136 snd_printk("unknown CS4236 chip (enhanced version = 0x%x)\n", id);
1137 }
1138 } else if ((id & 0x1f) == 0x08) { /* CS4237B */
1139 chip->hardware = CS4231_HW_CS4237B;
1140 switch (id >> 5) {
1141 case 4:
1142 case 5:
1143 case 6:
1144 case 7:
1145 break;
1146 default:
1147 snd_printk("unknown CS4237B chip (enhanced version = 0x%x)\n", id);
1148 }
1149 } else if ((id & 0x1f) == 0x09) { /* CS4238B */
1150 chip->hardware = CS4231_HW_CS4238B;
1151 switch (id >> 5) {
1152 case 5:
1153 case 6:
1154 case 7:
1155 break;
1156 default:
1157 snd_printk("unknown CS4238B chip (enhanced version = 0x%x)\n", id);
1158 }
1159 } else if ((id & 0x1f) == 0x1e) { /* CS4239 */
1160 chip->hardware = CS4231_HW_CS4239;
1161 switch (id >> 5) {
1162 case 4:
1163 case 5:
1164 case 6:
1165 break;
1166 default:
1167 snd_printk("unknown CS4239 chip (enhanced version = 0x%x)\n", id);
1168 }
1169 } else {
1170 snd_printk("unknown CS4236/CS423xB chip (enhanced version = 0x%x)\n", id);
1171 }
1172 }
1173 }
1174 return 0; /* all things are ok.. */
1175}
1176
1177/*
1178
1179 */
1180
1181static struct snd_pcm_hardware snd_cs4231_playback =
1182{
1183 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1184 SNDRV_PCM_INFO_MMAP_VALID |
1185 SNDRV_PCM_INFO_RESUME |
1186 SNDRV_PCM_INFO_SYNC_START),
1187 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
1188 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
1189 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1190 .rate_min = 5510,
1191 .rate_max = 48000,
1192 .channels_min = 1,
1193 .channels_max = 2,
1194 .buffer_bytes_max = (128*1024),
1195 .period_bytes_min = 64,
1196 .period_bytes_max = (128*1024),
1197 .periods_min = 1,
1198 .periods_max = 1024,
1199 .fifo_size = 0,
1200};
1201
1202static struct snd_pcm_hardware snd_cs4231_capture =
1203{
1204 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1205 SNDRV_PCM_INFO_MMAP_VALID |
1206 SNDRV_PCM_INFO_RESUME |
1207 SNDRV_PCM_INFO_SYNC_START),
1208 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
1209 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
1210 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1211 .rate_min = 5510,
1212 .rate_max = 48000,
1213 .channels_min = 1,
1214 .channels_max = 2,
1215 .buffer_bytes_max = (128*1024),
1216 .period_bytes_min = 64,
1217 .period_bytes_max = (128*1024),
1218 .periods_min = 1,
1219 .periods_max = 1024,
1220 .fifo_size = 0,
1221};
1222
1223/*
1224
1225 */
1226
1227static int snd_cs4231_playback_open(struct snd_pcm_substream *substream)
1228{
1229 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
1230 struct snd_pcm_runtime *runtime = substream->runtime;
1231 int err;
1232
1233 runtime->hw = snd_cs4231_playback;
1234
1235 /* hardware bug in InterWave chipset */
1236 if (chip->hardware == CS4231_HW_INTERWAVE && chip->dma1 > 3)
1237 runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW;
1238
1239 /* hardware limitation of cheap chips */
1240 if (chip->hardware == CS4231_HW_CS4235 ||
1241 chip->hardware == CS4231_HW_CS4239)
1242 runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
1243
1244 snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
1245 snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
1246
1247 if (chip->claim_dma) {
1248 if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0)
1249 return err;
1250 }
1251
1252 if ((err = snd_cs4231_open(chip, CS4231_MODE_PLAY)) < 0) {
1253 if (chip->release_dma)
1254 chip->release_dma(chip, chip->dma_private_data, chip->dma1);
1255 snd_free_pages(runtime->dma_area, runtime->dma_bytes);
1256 return err;
1257 }
1258 chip->playback_substream = substream;
1259 snd_pcm_set_sync(substream);
1260 chip->rate_constraint(runtime);
1261 return 0;
1262}
1263
1264static int snd_cs4231_capture_open(struct snd_pcm_substream *substream)
1265{
1266 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
1267 struct snd_pcm_runtime *runtime = substream->runtime;
1268 int err;
1269
1270 runtime->hw = snd_cs4231_capture;
1271
1272 /* hardware limitation of cheap chips */
1273 if (chip->hardware == CS4231_HW_CS4235 ||
1274 chip->hardware == CS4231_HW_CS4239)
1275 runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
1276
1277 snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
1278 snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
1279
1280 if (chip->claim_dma) {
1281 if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0)
1282 return err;
1283 }
1284
1285 if ((err = snd_cs4231_open(chip, CS4231_MODE_RECORD)) < 0) {
1286 if (chip->release_dma)
1287 chip->release_dma(chip, chip->dma_private_data, chip->dma2);
1288 snd_free_pages(runtime->dma_area, runtime->dma_bytes);
1289 return err;
1290 }
1291 chip->capture_substream = substream;
1292 snd_pcm_set_sync(substream);
1293 chip->rate_constraint(runtime);
1294 return 0;
1295}
1296
1297static int snd_cs4231_playback_close(struct snd_pcm_substream *substream)
1298{
1299 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
1300
1301 chip->playback_substream = NULL;
1302 snd_cs4231_close(chip, CS4231_MODE_PLAY);
1303 return 0;
1304}
1305
1306static int snd_cs4231_capture_close(struct snd_pcm_substream *substream)
1307{
1308 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
1309
1310 chip->capture_substream = NULL;
1311 snd_cs4231_close(chip, CS4231_MODE_RECORD);
1312 return 0;
1313}
1314
1315#ifdef CONFIG_PM
1316
1317/* lowlevel suspend callback for CS4231 */
1318static void snd_cs4231_suspend(struct snd_cs4231 *chip)
1319{
1320 int reg;
1321 unsigned long flags;
1322
1323 snd_pcm_suspend_all(chip->pcm);
1324 spin_lock_irqsave(&chip->reg_lock, flags);
1325 for (reg = 0; reg < 32; reg++)
1326 chip->image[reg] = snd_cs4231_in(chip, reg);
1327 spin_unlock_irqrestore(&chip->reg_lock, flags);
1328}
1329
1330/* lowlevel resume callback for CS4231 */
1331static void snd_cs4231_resume(struct snd_cs4231 *chip)
1332{
1333 int reg;
1334 unsigned long flags;
1335 /* int timeout; */
1336
1337 snd_cs4231_mce_up(chip);
1338 spin_lock_irqsave(&chip->reg_lock, flags);
1339 for (reg = 0; reg < 32; reg++) {
1340 switch (reg) {
1341 case CS4231_VERSION:
1342 break;
1343 default:
1344 snd_cs4231_out(chip, reg, chip->image[reg]);
1345 break;
1346 }
1347 }
1348 spin_unlock_irqrestore(&chip->reg_lock, flags);
1349#if 1
1350 snd_cs4231_mce_down(chip);
1351#else
1352 /* The following is a workaround to avoid freeze after resume on TP600E.
1353 This is the first half of copy of snd_cs4231_mce_down(), but doesn't
1354 include rescheduling. -- iwai
1355 */
1356 snd_cs4231_busy_wait(chip);
1357 spin_lock_irqsave(&chip->reg_lock, flags);
1358 chip->mce_bit &= ~CS4231_MCE;
1359 timeout = cs4231_inb(chip, CS4231P(REGSEL));
1360 cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
1361 spin_unlock_irqrestore(&chip->reg_lock, flags);
1362 if (timeout == 0x80)
1363 snd_printk("down [0x%lx]: serious init problem - codec still busy\n", chip->port);
1364 if ((timeout & CS4231_MCE) == 0 ||
1365 !(chip->hardware & (CS4231_HW_CS4231_MASK | CS4231_HW_CS4232_MASK))) {
1366 return;
1367 }
1368 snd_cs4231_busy_wait(chip);
1369#endif
1370}
1371#endif /* CONFIG_PM */
1372
1373static int snd_cs4231_free(struct snd_cs4231 *chip)
1374{
1375 release_and_free_resource(chip->res_port);
1376 release_and_free_resource(chip->res_cport);
1377 if (chip->irq >= 0) {
1378 disable_irq(chip->irq);
1379 if (!(chip->hwshare & CS4231_HWSHARE_IRQ))
1380 free_irq(chip->irq, (void *) chip);
1381 }
1382 if (!(chip->hwshare & CS4231_HWSHARE_DMA1) && chip->dma1 >= 0) {
1383 snd_dma_disable(chip->dma1);
1384 free_dma(chip->dma1);
1385 }
1386 if (!(chip->hwshare & CS4231_HWSHARE_DMA2) && chip->dma2 >= 0 && chip->dma2 != chip->dma1) {
1387 snd_dma_disable(chip->dma2);
1388 free_dma(chip->dma2);
1389 }
1390 if (chip->timer)
1391 snd_device_free(chip->card, chip->timer);
1392 kfree(chip);
1393 return 0;
1394}
1395
1396static int snd_cs4231_dev_free(struct snd_device *device)
1397{
1398 struct snd_cs4231 *chip = device->device_data;
1399 return snd_cs4231_free(chip);
1400}
1401
1402const char *snd_cs4231_chip_id(struct snd_cs4231 *chip)
1403{
1404 switch (chip->hardware) {
1405 case CS4231_HW_CS4231: return "CS4231";
1406 case CS4231_HW_CS4231A: return "CS4231A";
1407 case CS4231_HW_CS4232: return "CS4232";
1408 case CS4231_HW_CS4232A: return "CS4232A";
1409 case CS4231_HW_CS4235: return "CS4235";
1410 case CS4231_HW_CS4236: return "CS4236";
1411 case CS4231_HW_CS4236B: return "CS4236B";
1412 case CS4231_HW_CS4237B: return "CS4237B";
1413 case CS4231_HW_CS4238B: return "CS4238B";
1414 case CS4231_HW_CS4239: return "CS4239";
1415 case CS4231_HW_INTERWAVE: return "AMD InterWave";
1416 case CS4231_HW_OPL3SA2: return chip->card->shortname;
1417 case CS4231_HW_AD1845: return "AD1845";
1418 case CS4231_HW_OPTI93X: return "OPTi 93x";
1419 default: return "???";
1420 }
1421}
1422
1423static int snd_cs4231_new(struct snd_card *card,
1424 unsigned short hardware,
1425 unsigned short hwshare,
1426 struct snd_cs4231 ** rchip)
1427{
1428 struct snd_cs4231 *chip;
1429
1430 *rchip = NULL;
1431 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
1432 if (chip == NULL)
1433 return -ENOMEM;
1434 chip->hardware = hardware;
1435 chip->hwshare = hwshare;
1436
1437 spin_lock_init(&chip->reg_lock);
1438 mutex_init(&chip->mce_mutex);
1439 mutex_init(&chip->open_mutex);
1440 chip->card = card;
1441 chip->rate_constraint = snd_cs4231_xrate;
1442 chip->set_playback_format = snd_cs4231_playback_format;
1443 chip->set_capture_format = snd_cs4231_capture_format;
1444 if (chip->hardware == CS4231_HW_OPTI93X)
1445 memcpy(&chip->image, &snd_opti93x_original_image,
1446 sizeof(snd_opti93x_original_image));
1447 else
1448 memcpy(&chip->image, &snd_cs4231_original_image,
1449 sizeof(snd_cs4231_original_image));
1450
1451 *rchip = chip;
1452 return 0;
1453}
1454
1455int snd_cs4231_create(struct snd_card *card,
1456 unsigned long port,
1457 unsigned long cport,
1458 int irq, int dma1, int dma2,
1459 unsigned short hardware,
1460 unsigned short hwshare,
1461 struct snd_cs4231 ** rchip)
1462{
1463 static struct snd_device_ops ops = {
1464 .dev_free = snd_cs4231_dev_free,
1465 };
1466 struct snd_cs4231 *chip;
1467 int err;
1468
1469 err = snd_cs4231_new(card, hardware, hwshare, &chip);
1470 if (err < 0)
1471 return err;
1472
1473 chip->irq = -1;
1474 chip->dma1 = -1;
1475 chip->dma2 = -1;
1476
1477 if ((chip->res_port = request_region(port, 4, "CS4231")) == NULL) {
1478 snd_printk(KERN_ERR "cs4231: can't grab port 0x%lx\n", port);
1479 snd_cs4231_free(chip);
1480 return -EBUSY;
1481 }
1482 chip->port = port;
1483 if ((long)cport >= 0 && (chip->res_cport = request_region(cport, 8, "CS4232 Control")) == NULL) {
1484 snd_printk(KERN_ERR "cs4231: can't grab control port 0x%lx\n", cport);
1485 snd_cs4231_free(chip);
1486 return -ENODEV;
1487 }
1488 chip->cport = cport;
1489 if (!(hwshare & CS4231_HWSHARE_IRQ) && request_irq(irq, snd_cs4231_interrupt, IRQF_DISABLED, "CS4231", (void *) chip)) {
1490 snd_printk(KERN_ERR "cs4231: can't grab IRQ %d\n", irq);
1491 snd_cs4231_free(chip);
1492 return -EBUSY;
1493 }
1494 chip->irq = irq;
1495 if (!(hwshare & CS4231_HWSHARE_DMA1) && request_dma(dma1, "CS4231 - 1")) {
1496 snd_printk(KERN_ERR "cs4231: can't grab DMA1 %d\n", dma1);
1497 snd_cs4231_free(chip);
1498 return -EBUSY;
1499 }
1500 chip->dma1 = dma1;
1501 if (!(hwshare & CS4231_HWSHARE_DMA2) && dma1 != dma2 && dma2 >= 0 && request_dma(dma2, "CS4231 - 2")) {
1502 snd_printk(KERN_ERR "cs4231: can't grab DMA2 %d\n", dma2);
1503 snd_cs4231_free(chip);
1504 return -EBUSY;
1505 }
1506 if (dma1 == dma2 || dma2 < 0) {
1507 chip->single_dma = 1;
1508 chip->dma2 = chip->dma1;
1509 } else
1510 chip->dma2 = dma2;
1511
1512 /* global setup */
1513 if (snd_cs4231_probe(chip) < 0) {
1514 snd_cs4231_free(chip);
1515 return -ENODEV;
1516 }
1517 snd_cs4231_init(chip);
1518
1519#if 0
1520 if (chip->hardware & CS4231_HW_CS4232_MASK) {
1521 if (chip->res_cport == NULL)
1522 snd_printk("CS4232 control port features are not accessible\n");
1523 }
1524#endif
1525
1526 /* Register device */
1527 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
1528 snd_cs4231_free(chip);
1529 return err;
1530 }
1531
1532#ifdef CONFIG_PM
1533 /* Power Management */
1534 chip->suspend = snd_cs4231_suspend;
1535 chip->resume = snd_cs4231_resume;
1536#endif
1537
1538 *rchip = chip;
1539 return 0;
1540}
1541
1542static struct snd_pcm_ops snd_cs4231_playback_ops = {
1543 .open = snd_cs4231_playback_open,
1544 .close = snd_cs4231_playback_close,
1545 .ioctl = snd_pcm_lib_ioctl,
1546 .hw_params = snd_cs4231_playback_hw_params,
1547 .hw_free = snd_cs4231_playback_hw_free,
1548 .prepare = snd_cs4231_playback_prepare,
1549 .trigger = snd_cs4231_trigger,
1550 .pointer = snd_cs4231_playback_pointer,
1551};
1552
1553static struct snd_pcm_ops snd_cs4231_capture_ops = {
1554 .open = snd_cs4231_capture_open,
1555 .close = snd_cs4231_capture_close,
1556 .ioctl = snd_pcm_lib_ioctl,
1557 .hw_params = snd_cs4231_capture_hw_params,
1558 .hw_free = snd_cs4231_capture_hw_free,
1559 .prepare = snd_cs4231_capture_prepare,
1560 .trigger = snd_cs4231_trigger,
1561 .pointer = snd_cs4231_capture_pointer,
1562};
1563
1564int snd_cs4231_pcm(struct snd_cs4231 *chip, int device, struct snd_pcm **rpcm)
1565{
1566 struct snd_pcm *pcm;
1567 int err;
1568
1569 if ((err = snd_pcm_new(chip->card, "CS4231", device, 1, 1, &pcm)) < 0)
1570 return err;
1571
1572 spin_lock_init(&chip->reg_lock);
1573 mutex_init(&chip->mce_mutex);
1574 mutex_init(&chip->open_mutex);
1575
1576 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs4231_playback_ops);
1577 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4231_capture_ops);
1578
1579 /* global setup */
1580 pcm->private_data = chip;
1581 pcm->info_flags = 0;
1582 if (chip->single_dma)
1583 pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
1584 if (chip->hardware != CS4231_HW_INTERWAVE)
1585 pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
1586 strcpy(pcm->name, snd_cs4231_chip_id(chip));
1587
1588 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1589 snd_dma_isa_data(),
1590 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
1591
1592 chip->pcm = pcm;
1593 if (rpcm)
1594 *rpcm = pcm;
1595 return 0;
1596}
1597
1598static void snd_cs4231_timer_free(struct snd_timer *timer)
1599{
1600 struct snd_cs4231 *chip = timer->private_data;
1601 chip->timer = NULL;
1602}
1603
1604int snd_cs4231_timer(struct snd_cs4231 *chip, int device, struct snd_timer **rtimer)
1605{
1606 struct snd_timer *timer;
1607 struct snd_timer_id tid;
1608 int err;
1609
1610 /* Timer initialization */
1611 tid.dev_class = SNDRV_TIMER_CLASS_CARD;
1612 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
1613 tid.card = chip->card->number;
1614 tid.device = device;
1615 tid.subdevice = 0;
1616 if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0)
1617 return err;
1618 strcpy(timer->name, snd_cs4231_chip_id(chip));
1619 timer->private_data = chip;
1620 timer->private_free = snd_cs4231_timer_free;
1621 timer->hw = snd_cs4231_timer_table;
1622 chip->timer = timer;
1623 if (rtimer)
1624 *rtimer = timer;
1625 return 0;
1626}
1627
1628/*
1629 * MIXER part
1630 */
1631
1632static int snd_cs4231_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1633{
1634 static char *texts[4] = {
1635 "Line", "Aux", "Mic", "Mix"
1636 };
1637 static char *opl3sa_texts[4] = {
1638 "Line", "CD", "Mic", "Mix"
1639 };
1640 static char *gusmax_texts[4] = {
1641 "Line", "Synth", "Mic", "Mix"
1642 };
1643 char **ptexts = texts;
1644 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
1645
1646 snd_assert(chip->card != NULL, return -EINVAL);
1647 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1648 uinfo->count = 2;
1649 uinfo->value.enumerated.items = 4;
1650 if (uinfo->value.enumerated.item > 3)
1651 uinfo->value.enumerated.item = 3;
1652 if (!strcmp(chip->card->driver, "GUS MAX"))
1653 ptexts = gusmax_texts;
1654 switch (chip->hardware) {
1655 case CS4231_HW_INTERWAVE: ptexts = gusmax_texts; break;
1656 case CS4231_HW_OPL3SA2: ptexts = opl3sa_texts; break;
1657 }
1658 strcpy(uinfo->value.enumerated.name, ptexts[uinfo->value.enumerated.item]);
1659 return 0;
1660}
1661
1662static int snd_cs4231_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1663{
1664 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
1665 unsigned long flags;
1666
1667 spin_lock_irqsave(&chip->reg_lock, flags);
1668 ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6;
1669 ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6;
1670 spin_unlock_irqrestore(&chip->reg_lock, flags);
1671 return 0;
1672}
1673
1674static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1675{
1676 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
1677 unsigned long flags;
1678 unsigned short left, right;
1679 int change;
1680
1681 if (ucontrol->value.enumerated.item[0] > 3 ||
1682 ucontrol->value.enumerated.item[1] > 3)
1683 return -EINVAL;
1684 left = ucontrol->value.enumerated.item[0] << 6;
1685 right = ucontrol->value.enumerated.item[1] << 6;
1686 spin_lock_irqsave(&chip->reg_lock, flags);
1687 left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left;
1688 right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right;
1689 change = left != chip->image[CS4231_LEFT_INPUT] ||
1690 right != chip->image[CS4231_RIGHT_INPUT];
1691 snd_cs4231_out(chip, CS4231_LEFT_INPUT, left);
1692 snd_cs4231_out(chip, CS4231_RIGHT_INPUT, right);
1693 spin_unlock_irqrestore(&chip->reg_lock, flags);
1694 return change;
1695}
1696
1697int snd_cs4231_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1698{
1699 int mask = (kcontrol->private_value >> 16) & 0xff;
1700
1701 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1702 uinfo->count = 1;
1703 uinfo->value.integer.min = 0;
1704 uinfo->value.integer.max = mask;
1705 return 0;
1706}
1707
1708int snd_cs4231_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1709{
1710 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
1711 unsigned long flags;
1712 int reg = kcontrol->private_value & 0xff;
1713 int shift = (kcontrol->private_value >> 8) & 0xff;
1714 int mask = (kcontrol->private_value >> 16) & 0xff;
1715 int invert = (kcontrol->private_value >> 24) & 0xff;
1716
1717 spin_lock_irqsave(&chip->reg_lock, flags);
1718 ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
1719 spin_unlock_irqrestore(&chip->reg_lock, flags);
1720 if (invert)
1721 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
1722 return 0;
1723}
1724
1725int snd_cs4231_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1726{
1727 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
1728 unsigned long flags;
1729 int reg = kcontrol->private_value & 0xff;
1730 int shift = (kcontrol->private_value >> 8) & 0xff;
1731 int mask = (kcontrol->private_value >> 16) & 0xff;
1732 int invert = (kcontrol->private_value >> 24) & 0xff;
1733 int change;
1734 unsigned short val;
1735
1736 val = (ucontrol->value.integer.value[0] & mask);
1737 if (invert)
1738 val = mask - val;
1739 val <<= shift;
1740 spin_lock_irqsave(&chip->reg_lock, flags);
1741 val = (chip->image[reg] & ~(mask << shift)) | val;
1742 change = val != chip->image[reg];
1743 snd_cs4231_out(chip, reg, val);
1744 spin_unlock_irqrestore(&chip->reg_lock, flags);
1745 return change;
1746}
1747
1748int snd_cs4231_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1749{
1750 int mask = (kcontrol->private_value >> 24) & 0xff;
1751
1752 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1753 uinfo->count = 2;
1754 uinfo->value.integer.min = 0;
1755 uinfo->value.integer.max = mask;
1756 return 0;
1757}
1758
1759int snd_cs4231_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1760{
1761 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
1762 unsigned long flags;
1763 int left_reg = kcontrol->private_value & 0xff;
1764 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1765 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1766 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1767 int mask = (kcontrol->private_value >> 24) & 0xff;
1768 int invert = (kcontrol->private_value >> 22) & 1;
1769
1770 spin_lock_irqsave(&chip->reg_lock, flags);
1771 ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
1772 ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
1773 spin_unlock_irqrestore(&chip->reg_lock, flags);
1774 if (invert) {
1775 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
1776 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
1777 }
1778 return 0;
1779}
1780
1781int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1782{
1783 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
1784 unsigned long flags;
1785 int left_reg = kcontrol->private_value & 0xff;
1786 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1787 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1788 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1789 int mask = (kcontrol->private_value >> 24) & 0xff;
1790 int invert = (kcontrol->private_value >> 22) & 1;
1791 int change;
1792 unsigned short val1, val2;
1793
1794 val1 = ucontrol->value.integer.value[0] & mask;
1795 val2 = ucontrol->value.integer.value[1] & mask;
1796 if (invert) {
1797 val1 = mask - val1;
1798 val2 = mask - val2;
1799 }
1800 val1 <<= shift_left;
1801 val2 <<= shift_right;
1802 spin_lock_irqsave(&chip->reg_lock, flags);
1803 val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
1804 val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
1805 change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg];
1806 snd_cs4231_out(chip, left_reg, val1);
1807 snd_cs4231_out(chip, right_reg, val2);
1808 spin_unlock_irqrestore(&chip->reg_lock, flags);
1809 return change;
1810}
1811
1812static struct snd_kcontrol_new snd_cs4231_controls[] = {
1813CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
1814CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
1815CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
1816CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
1817CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
1818CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
1819CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
1820CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
1821CS4231_SINGLE("Mono Playback Switch", 0, CS4231_MONO_CTRL, 7, 1, 1),
1822CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
1823CS4231_SINGLE("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, 6, 1, 1),
1824CS4231_SINGLE("Mono Output Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0),
1825CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
1826{
1827 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1828 .name = "Capture Source",
1829 .info = snd_cs4231_info_mux,
1830 .get = snd_cs4231_get_mux,
1831 .put = snd_cs4231_put_mux,
1832},
1833CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
1834CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
1835CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1)
1836};
1837
1838static struct snd_kcontrol_new snd_opti93x_controls[] = {
1839CS4231_DOUBLE("Master Playback Switch", 0,
1840 OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
1841CS4231_DOUBLE("Master Playback Volume", 0,
1842 OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1),
1843CS4231_DOUBLE("PCM Playback Switch", 0,
1844 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
1845CS4231_DOUBLE("PCM Playback Volume", 0,
1846 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1),
1847CS4231_DOUBLE("FM Playback Switch", 0,
1848 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
1849CS4231_DOUBLE("FM Playback Volume", 0,
1850 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1),
1851CS4231_DOUBLE("Line Playback Switch", 0,
1852 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
1853CS4231_DOUBLE("Line Playback Volume", 0,
1854 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1),
1855CS4231_DOUBLE("Mic Playback Switch", 0,
1856 OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
1857CS4231_DOUBLE("Mic Playback Volume", 0,
1858 OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1),
1859CS4231_DOUBLE("Mic Boost", 0,
1860 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
1861CS4231_DOUBLE("CD Playback Switch", 0,
1862 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
1863CS4231_DOUBLE("CD Playback Volume", 0,
1864 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1),
1865CS4231_DOUBLE("Aux Playback Switch", 0,
1866 OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
1867CS4231_DOUBLE("Aux Playback Volume", 0,
1868 OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1),
1869CS4231_DOUBLE("Capture Volume", 0,
1870 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
1871{
1872 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1873 .name = "Capture Source",
1874 .info = snd_cs4231_info_mux,
1875 .get = snd_cs4231_get_mux,
1876 .put = snd_cs4231_put_mux,
1877}
1878};
1879
1880int snd_cs4231_mixer(struct snd_cs4231 *chip)
1881{
1882 struct snd_card *card;
1883 unsigned int idx;
1884 int err;
1885
1886 snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL);
1887
1888 card = chip->card;
1889
1890 strcpy(card->mixername, chip->pcm->name);
1891
1892 if (chip->hardware == CS4231_HW_OPTI93X)
1893 for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
1894 err = snd_ctl_add(card,
1895 snd_ctl_new1(&snd_opti93x_controls[idx],
1896 chip));
1897 if (err < 0)
1898 return err;
1899 }
1900 else
1901 for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {
1902 err = snd_ctl_add(card,
1903 snd_ctl_new1(&snd_cs4231_controls[idx],
1904 chip));
1905 if (err < 0)
1906 return err;
1907 }
1908 return 0;
1909}
1910
1911EXPORT_SYMBOL(snd_cs4231_out);
1912EXPORT_SYMBOL(snd_cs4231_in);
1913EXPORT_SYMBOL(snd_cs4236_ext_out);
1914EXPORT_SYMBOL(snd_cs4236_ext_in);
1915EXPORT_SYMBOL(snd_cs4231_mce_up);
1916EXPORT_SYMBOL(snd_cs4231_mce_down);
1917EXPORT_SYMBOL(snd_cs4231_overrange);
1918EXPORT_SYMBOL(snd_cs4231_interrupt);
1919EXPORT_SYMBOL(snd_cs4231_chip_id);
1920EXPORT_SYMBOL(snd_cs4231_create);
1921EXPORT_SYMBOL(snd_cs4231_pcm);
1922EXPORT_SYMBOL(snd_cs4231_mixer);
1923EXPORT_SYMBOL(snd_cs4231_timer);
1924EXPORT_SYMBOL(snd_cs4231_info_single);
1925EXPORT_SYMBOL(snd_cs4231_get_single);
1926EXPORT_SYMBOL(snd_cs4231_put_single);
1927EXPORT_SYMBOL(snd_cs4231_info_double);
1928EXPORT_SYMBOL(snd_cs4231_get_double);
1929EXPORT_SYMBOL(snd_cs4231_put_double);
1930
1931/*
1932 * INIT part
1933 */
1934
1935static int __init alsa_cs4231_init(void)
1936{
1937 return 0;
1938}
1939
1940static void __exit alsa_cs4231_exit(void)
1941{
1942}
1943
1944module_init(alsa_cs4231_init)
1945module_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 @@
26#include <linux/pnp.h> 26#include <linux/pnp.h>
27#include <linux/moduleparam.h> 27#include <linux/moduleparam.h>
28#include <sound/core.h> 28#include <sound/core.h>
29#include <sound/cs4231.h> 29#include <sound/wss.h>
30#include <sound/mpu401.h> 30#include <sound/mpu401.h>
31#include <sound/opl3.h> 31#include <sound/opl3.h>
32#include <sound/initval.h> 32#include <sound/initval.h>
@@ -134,7 +134,7 @@ static int pnp_registered;
134#endif /* CONFIG_PNP */ 134#endif /* CONFIG_PNP */
135 135
136struct snd_card_cs4236 { 136struct snd_card_cs4236 {
137 struct snd_cs4231 *chip; 137 struct snd_wss *chip;
138 struct resource *res_sb_port; 138 struct resource *res_sb_port;
139#ifdef CONFIG_PNP 139#ifdef CONFIG_PNP
140 struct pnp_dev *wss; 140 struct pnp_dev *wss;
@@ -239,6 +239,8 @@ static struct pnp_card_device_id snd_cs423x_pnpids[] = {
239 { .id = "CSC9836", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, 239 { .id = "CSC9836", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
240 /* Gallant SC-70P */ 240 /* Gallant SC-70P */
241 { .id = "CSC9837", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, 241 { .id = "CSC9837", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
242 /* Techmakers MF-4236PW */
243 { .id = "CSCa736", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
242 /* TerraTec AudioSystem EWS64XL - CS4236B */ 244 /* TerraTec AudioSystem EWS64XL - CS4236B */
243 { .id = "CSCa836", .devs = { { "CSCa800" }, { "CSCa810" }, { "CSCa803" } } }, 245 { .id = "CSCa836", .devs = { { "CSCa800" }, { "CSCa810" }, { "CSCa803" } } },
244 /* TerraTec AudioSystem EWS64XL - CS4236B */ 246 /* TerraTec AudioSystem EWS64XL - CS4236B */
@@ -396,7 +398,7 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
396{ 398{
397 struct snd_card_cs4236 *acard; 399 struct snd_card_cs4236 *acard;
398 struct snd_pcm *pcm; 400 struct snd_pcm *pcm;
399 struct snd_cs4231 *chip; 401 struct snd_wss *chip;
400 struct snd_opl3 *opl3; 402 struct snd_opl3 *opl3;
401 int err; 403 int err;
402 404
@@ -408,41 +410,37 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
408 } 410 }
409 411
410#ifdef CS4232 412#ifdef CS4232
411 if ((err = snd_cs4231_create(card, 413 err = snd_wss_create(card, port[dev], cport[dev],
412 port[dev], 414 irq[dev],
413 cport[dev], 415 dma1[dev], dma2[dev],
414 irq[dev], 416 WSS_HW_DETECT, 0, &chip);
415 dma1[dev], 417 if (err < 0)
416 dma2[dev],
417 CS4231_HW_DETECT,
418 0,
419 &chip)) < 0)
420 return err; 418 return err;
421 acard->chip = chip; 419 acard->chip = chip;
422 420
423 if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) 421 err = snd_wss_pcm(chip, 0, &pcm);
422 if (err < 0)
424 return err; 423 return err;
425 424
426 if ((err = snd_cs4231_mixer(chip)) < 0) 425 err = snd_wss_mixer(chip);
426 if (err < 0)
427 return err; 427 return err;
428 428
429#else /* CS4236 */ 429#else /* CS4236 */
430 if ((err = snd_cs4236_create(card, 430 err = snd_cs4236_create(card,
431 port[dev], 431 port[dev], cport[dev],
432 cport[dev], 432 irq[dev], dma1[dev], dma2[dev],
433 irq[dev], 433 WSS_HW_DETECT, 0, &chip);
434 dma1[dev], 434 if (err < 0)
435 dma2[dev],
436 CS4231_HW_DETECT,
437 0,
438 &chip)) < 0)
439 return err; 435 return err;
440 acard->chip = chip; 436 acard->chip = chip;
441 437
442 if ((err = snd_cs4236_pcm(chip, 0, &pcm)) < 0) 438 err = snd_cs4236_pcm(chip, 0, &pcm);
439 if (err < 0)
443 return err; 440 return err;
444 441
445 if ((err = snd_cs4236_mixer(chip)) < 0) 442 err = snd_cs4236_mixer(chip);
443 if (err < 0)
446 return err; 444 return err;
447#endif 445#endif
448 strcpy(card->driver, pcm->name); 446 strcpy(card->driver, pcm->name);
@@ -455,7 +453,8 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
455 if (dma2[dev] >= 0) 453 if (dma2[dev] >= 0)
456 sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]); 454 sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
457 455
458 if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) 456 err = snd_wss_timer(chip, 0, NULL);
457 if (err < 0)
459 return err; 458 return err;
460 459
461 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { 460 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 @@
85#include <linux/time.h> 85#include <linux/time.h>
86#include <linux/wait.h> 86#include <linux/wait.h>
87#include <sound/core.h> 87#include <sound/core.h>
88#include <sound/cs4231.h> 88#include <sound/wss.h>
89#include <sound/asoundef.h> 89#include <sound/asoundef.h>
90 90
91MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); 91MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
@@ -121,13 +121,14 @@ static unsigned char snd_cs4236_ext_map[18] = {
121 * 121 *
122 */ 122 */
123 123
124static void snd_cs4236_ctrl_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val) 124static void snd_cs4236_ctrl_out(struct snd_wss *chip,
125 unsigned char reg, unsigned char val)
125{ 126{
126 outb(reg, chip->cport + 3); 127 outb(reg, chip->cport + 3);
127 outb(chip->cimage[reg] = val, chip->cport + 4); 128 outb(chip->cimage[reg] = val, chip->cport + 4);
128} 129}
129 130
130static unsigned char snd_cs4236_ctrl_in(struct snd_cs4231 *chip, unsigned char reg) 131static unsigned char snd_cs4236_ctrl_in(struct snd_wss *chip, unsigned char reg)
131{ 132{
132 outb(reg, chip->cport + 3); 133 outb(reg, chip->cport + 3);
133 return inb(chip->cport + 4); 134 return inb(chip->cport + 4);
@@ -180,44 +181,52 @@ static unsigned char divisor_to_rate_register(unsigned int divisor)
180 } 181 }
181} 182}
182 183
183static void snd_cs4236_playback_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, unsigned char pdfr) 184static void snd_cs4236_playback_format(struct snd_wss *chip,
185 struct snd_pcm_hw_params *params,
186 unsigned char pdfr)
184{ 187{
185 unsigned long flags; 188 unsigned long flags;
186 unsigned char rate = divisor_to_rate_register(params->rate_den); 189 unsigned char rate = divisor_to_rate_register(params->rate_den);
187 190
188 spin_lock_irqsave(&chip->reg_lock, flags); 191 spin_lock_irqsave(&chip->reg_lock, flags);
189 /* set fast playback format change and clean playback FIFO */ 192 /* set fast playback format change and clean playback FIFO */
190 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x10); 193 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
191 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, pdfr & 0xf0); 194 chip->image[CS4231_ALT_FEATURE_1] | 0x10);
192 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] & ~0x10); 195 snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr & 0xf0);
196 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
197 chip->image[CS4231_ALT_FEATURE_1] & ~0x10);
193 snd_cs4236_ext_out(chip, CS4236_DAC_RATE, rate); 198 snd_cs4236_ext_out(chip, CS4236_DAC_RATE, rate);
194 spin_unlock_irqrestore(&chip->reg_lock, flags); 199 spin_unlock_irqrestore(&chip->reg_lock, flags);
195} 200}
196 201
197static void snd_cs4236_capture_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, unsigned char cdfr) 202static void snd_cs4236_capture_format(struct snd_wss *chip,
203 struct snd_pcm_hw_params *params,
204 unsigned char cdfr)
198{ 205{
199 unsigned long flags; 206 unsigned long flags;
200 unsigned char rate = divisor_to_rate_register(params->rate_den); 207 unsigned char rate = divisor_to_rate_register(params->rate_den);
201 208
202 spin_lock_irqsave(&chip->reg_lock, flags); 209 spin_lock_irqsave(&chip->reg_lock, flags);
203 /* set fast capture format change and clean capture FIFO */ 210 /* set fast capture format change and clean capture FIFO */
204 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x20); 211 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
205 snd_cs4231_out(chip, CS4231_REC_FORMAT, cdfr & 0xf0); 212 chip->image[CS4231_ALT_FEATURE_1] | 0x20);
206 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] & ~0x20); 213 snd_wss_out(chip, CS4231_REC_FORMAT, cdfr & 0xf0);
214 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
215 chip->image[CS4231_ALT_FEATURE_1] & ~0x20);
207 snd_cs4236_ext_out(chip, CS4236_ADC_RATE, rate); 216 snd_cs4236_ext_out(chip, CS4236_ADC_RATE, rate);
208 spin_unlock_irqrestore(&chip->reg_lock, flags); 217 spin_unlock_irqrestore(&chip->reg_lock, flags);
209} 218}
210 219
211#ifdef CONFIG_PM 220#ifdef CONFIG_PM
212 221
213static void snd_cs4236_suspend(struct snd_cs4231 *chip) 222static void snd_cs4236_suspend(struct snd_wss *chip)
214{ 223{
215 int reg; 224 int reg;
216 unsigned long flags; 225 unsigned long flags;
217 226
218 spin_lock_irqsave(&chip->reg_lock, flags); 227 spin_lock_irqsave(&chip->reg_lock, flags);
219 for (reg = 0; reg < 32; reg++) 228 for (reg = 0; reg < 32; reg++)
220 chip->image[reg] = snd_cs4231_in(chip, reg); 229 chip->image[reg] = snd_wss_in(chip, reg);
221 for (reg = 0; reg < 18; reg++) 230 for (reg = 0; reg < 18; reg++)
222 chip->eimage[reg] = snd_cs4236_ext_in(chip, CS4236_I23VAL(reg)); 231 chip->eimage[reg] = snd_cs4236_ext_in(chip, CS4236_I23VAL(reg));
223 for (reg = 2; reg < 9; reg++) 232 for (reg = 2; reg < 9; reg++)
@@ -225,12 +234,12 @@ static void snd_cs4236_suspend(struct snd_cs4231 *chip)
225 spin_unlock_irqrestore(&chip->reg_lock, flags); 234 spin_unlock_irqrestore(&chip->reg_lock, flags);
226} 235}
227 236
228static void snd_cs4236_resume(struct snd_cs4231 *chip) 237static void snd_cs4236_resume(struct snd_wss *chip)
229{ 238{
230 int reg; 239 int reg;
231 unsigned long flags; 240 unsigned long flags;
232 241
233 snd_cs4231_mce_up(chip); 242 snd_wss_mce_up(chip);
234 spin_lock_irqsave(&chip->reg_lock, flags); 243 spin_lock_irqsave(&chip->reg_lock, flags);
235 for (reg = 0; reg < 32; reg++) { 244 for (reg = 0; reg < 32; reg++) {
236 switch (reg) { 245 switch (reg) {
@@ -240,7 +249,7 @@ static void snd_cs4236_resume(struct snd_cs4231 *chip)
240 case 29: /* why? CS4235 - master right */ 249 case 29: /* why? CS4235 - master right */
241 break; 250 break;
242 default: 251 default:
243 snd_cs4231_out(chip, reg, chip->image[reg]); 252 snd_wss_out(chip, reg, chip->image[reg]);
244 break; 253 break;
245 } 254 }
246 } 255 }
@@ -255,7 +264,7 @@ static void snd_cs4236_resume(struct snd_cs4231 *chip)
255 } 264 }
256 } 265 }
257 spin_unlock_irqrestore(&chip->reg_lock, flags); 266 spin_unlock_irqrestore(&chip->reg_lock, flags);
258 snd_cs4231_mce_down(chip); 267 snd_wss_mce_down(chip);
259} 268}
260 269
261#endif /* CONFIG_PM */ 270#endif /* CONFIG_PM */
@@ -266,24 +275,26 @@ int snd_cs4236_create(struct snd_card *card,
266 int irq, int dma1, int dma2, 275 int irq, int dma1, int dma2,
267 unsigned short hardware, 276 unsigned short hardware,
268 unsigned short hwshare, 277 unsigned short hwshare,
269 struct snd_cs4231 ** rchip) 278 struct snd_wss **rchip)
270{ 279{
271 struct snd_cs4231 *chip; 280 struct snd_wss *chip;
272 unsigned char ver1, ver2; 281 unsigned char ver1, ver2;
273 unsigned int reg; 282 unsigned int reg;
274 int err; 283 int err;
275 284
276 *rchip = NULL; 285 *rchip = NULL;
277 if (hardware == CS4231_HW_DETECT) 286 if (hardware == WSS_HW_DETECT)
278 hardware = CS4231_HW_DETECT3; 287 hardware = WSS_HW_DETECT3;
279 if (cport < 0x100) { 288 if (cport < 0x100) {
280 snd_printk("please, specify control port for CS4236+ chips\n"); 289 snd_printk("please, specify control port for CS4236+ chips\n");
281 return -ENODEV; 290 return -ENODEV;
282 } 291 }
283 if ((err = snd_cs4231_create(card, port, cport, irq, dma1, dma2, hardware, hwshare, &chip)) < 0) 292 err = snd_wss_create(card, port, cport,
293 irq, dma1, dma2, hardware, hwshare, &chip);
294 if (err < 0)
284 return err; 295 return err;
285 296
286 if (!(chip->hardware & CS4231_HW_CS4236B_MASK)) { 297 if (!(chip->hardware & WSS_HW_CS4236B_MASK)) {
287 snd_printk("CS4236+: MODE3 and extended registers not available, hardware=0x%x\n",chip->hardware); 298 snd_printk("CS4236+: MODE3 and extended registers not available, hardware=0x%x\n",chip->hardware);
288 snd_device_free(card, chip); 299 snd_device_free(card, chip);
289 return -ENODEV; 300 return -ENODEV;
@@ -330,20 +341,20 @@ int snd_cs4236_create(struct snd_card *card,
330 snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), snd_cs4236_ext_map[reg]); 341 snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), snd_cs4236_ext_map[reg]);
331 342
332 /* initialize compatible but more featured registers */ 343 /* initialize compatible but more featured registers */
333 snd_cs4231_out(chip, CS4231_LEFT_INPUT, 0x40); 344 snd_wss_out(chip, CS4231_LEFT_INPUT, 0x40);
334 snd_cs4231_out(chip, CS4231_RIGHT_INPUT, 0x40); 345 snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x40);
335 snd_cs4231_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff); 346 snd_wss_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff);
336 snd_cs4231_out(chip, CS4231_AUX1_RIGHT_INPUT, 0xff); 347 snd_wss_out(chip, CS4231_AUX1_RIGHT_INPUT, 0xff);
337 snd_cs4231_out(chip, CS4231_AUX2_LEFT_INPUT, 0xdf); 348 snd_wss_out(chip, CS4231_AUX2_LEFT_INPUT, 0xdf);
338 snd_cs4231_out(chip, CS4231_AUX2_RIGHT_INPUT, 0xdf); 349 snd_wss_out(chip, CS4231_AUX2_RIGHT_INPUT, 0xdf);
339 snd_cs4231_out(chip, CS4231_RIGHT_LINE_IN, 0xff); 350 snd_wss_out(chip, CS4231_RIGHT_LINE_IN, 0xff);
340 snd_cs4231_out(chip, CS4231_LEFT_LINE_IN, 0xff); 351 snd_wss_out(chip, CS4231_LEFT_LINE_IN, 0xff);
341 snd_cs4231_out(chip, CS4231_RIGHT_LINE_IN, 0xff); 352 snd_wss_out(chip, CS4231_RIGHT_LINE_IN, 0xff);
342 switch (chip->hardware) { 353 switch (chip->hardware) {
343 case CS4231_HW_CS4235: 354 case WSS_HW_CS4235:
344 case CS4231_HW_CS4239: 355 case WSS_HW_CS4239:
345 snd_cs4231_out(chip, CS4235_LEFT_MASTER, 0xff); 356 snd_wss_out(chip, CS4235_LEFT_MASTER, 0xff);
346 snd_cs4231_out(chip, CS4235_RIGHT_MASTER, 0xff); 357 snd_wss_out(chip, CS4235_RIGHT_MASTER, 0xff);
347 break; 358 break;
348 } 359 }
349 360
@@ -351,12 +362,13 @@ int snd_cs4236_create(struct snd_card *card,
351 return 0; 362 return 0;
352} 363}
353 364
354int snd_cs4236_pcm(struct snd_cs4231 *chip, int device, struct snd_pcm **rpcm) 365int snd_cs4236_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
355{ 366{
356 struct snd_pcm *pcm; 367 struct snd_pcm *pcm;
357 int err; 368 int err;
358 369
359 if ((err = snd_cs4231_pcm(chip, device, &pcm)) < 0) 370 err = snd_wss_pcm(chip, device, &pcm);
371 if (err < 0)
360 return err; 372 return err;
361 pcm->info_flags &= ~SNDRV_PCM_INFO_JOINT_DUPLEX; 373 pcm->info_flags &= ~SNDRV_PCM_INFO_JOINT_DUPLEX;
362 if (rpcm) 374 if (rpcm)
@@ -387,7 +399,7 @@ static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_
387 399
388static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 400static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
389{ 401{
390 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); 402 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
391 unsigned long flags; 403 unsigned long flags;
392 int reg = kcontrol->private_value & 0xff; 404 int reg = kcontrol->private_value & 0xff;
393 int shift = (kcontrol->private_value >> 8) & 0xff; 405 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
404 416
405static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 417static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
406{ 418{
407 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); 419 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
408 unsigned long flags; 420 unsigned long flags;
409 int reg = kcontrol->private_value & 0xff; 421 int reg = kcontrol->private_value & 0xff;
410 int shift = (kcontrol->private_value >> 8) & 0xff; 422 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
433 445
434static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 446static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
435{ 447{
436 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); 448 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
437 unsigned long flags; 449 unsigned long flags;
438 int reg = kcontrol->private_value & 0xff; 450 int reg = kcontrol->private_value & 0xff;
439 int shift = (kcontrol->private_value >> 8) & 0xff; 451 int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -450,7 +462,7 @@ static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_
450 462
451static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 463static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
452{ 464{
453 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); 465 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
454 unsigned long flags; 466 unsigned long flags;
455 int reg = kcontrol->private_value & 0xff; 467 int reg = kcontrol->private_value & 0xff;
456 int shift = (kcontrol->private_value >> 8) & 0xff; 468 int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -490,7 +502,7 @@ static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_
490 502
491static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 503static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
492{ 504{
493 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); 505 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
494 unsigned long flags; 506 unsigned long flags;
495 int left_reg = kcontrol->private_value & 0xff; 507 int left_reg = kcontrol->private_value & 0xff;
496 int right_reg = (kcontrol->private_value >> 8) & 0xff; 508 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
512 524
513static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 525static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
514{ 526{
515 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); 527 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
516 unsigned long flags; 528 unsigned long flags;
517 int left_reg = kcontrol->private_value & 0xff; 529 int left_reg = kcontrol->private_value & 0xff;
518 int right_reg = (kcontrol->private_value >> 8) & 0xff; 530 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
555 567
556static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 568static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
557{ 569{
558 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); 570 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
559 unsigned long flags; 571 unsigned long flags;
560 int left_reg = kcontrol->private_value & 0xff; 572 int left_reg = kcontrol->private_value & 0xff;
561 int right_reg = (kcontrol->private_value >> 8) & 0xff; 573 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_
577 589
578static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 590static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
579{ 591{
580 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); 592 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
581 unsigned long flags; 593 unsigned long flags;
582 int left_reg = kcontrol->private_value & 0xff; 594 int left_reg = kcontrol->private_value & 0xff;
583 int right_reg = (kcontrol->private_value >> 8) & 0xff; 595 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_
600 val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; 612 val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
601 val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2; 613 val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2;
602 change = val1 != chip->image[left_reg] || val2 != chip->eimage[CS4236_REG(right_reg)]; 614 change = val1 != chip->image[left_reg] || val2 != chip->eimage[CS4236_REG(right_reg)];
603 snd_cs4231_out(chip, left_reg, val1); 615 snd_wss_out(chip, left_reg, val1);
604 snd_cs4236_ext_out(chip, right_reg, val2); 616 snd_cs4236_ext_out(chip, right_reg, val2);
605 spin_unlock_irqrestore(&chip->reg_lock, flags); 617 spin_unlock_irqrestore(&chip->reg_lock, flags);
606 return change; 618 return change;
@@ -619,7 +631,7 @@ static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol)
619 631
620static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 632static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
621{ 633{
622 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); 634 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
623 unsigned long flags; 635 unsigned long flags;
624 636
625 spin_lock_irqsave(&chip->reg_lock, flags); 637 spin_lock_irqsave(&chip->reg_lock, flags);
@@ -631,7 +643,7 @@ static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct s
631 643
632static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 644static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
633{ 645{
634 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); 646 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
635 unsigned long flags; 647 unsigned long flags;
636 int change; 648 int change;
637 unsigned short val1, val2; 649 unsigned short val1, val2;
@@ -678,7 +690,7 @@ static inline int snd_cs4235_mixer_output_accu_set_volume(int vol)
678 690
679static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 691static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
680{ 692{
681 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); 693 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
682 unsigned long flags; 694 unsigned long flags;
683 695
684 spin_lock_irqsave(&chip->reg_lock, flags); 696 spin_lock_irqsave(&chip->reg_lock, flags);
@@ -690,7 +702,7 @@ static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_
690 702
691static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 703static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
692{ 704{
693 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); 705 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
694 unsigned long flags; 706 unsigned long flags;
695 int change; 707 int change;
696 unsigned short val1, val2; 708 unsigned short val1, val2;
@@ -701,108 +713,160 @@ static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_
701 val1 = (chip->image[CS4235_LEFT_MASTER] & ~(3 << 5)) | val1; 713 val1 = (chip->image[CS4235_LEFT_MASTER] & ~(3 << 5)) | val1;
702 val2 = (chip->image[CS4235_RIGHT_MASTER] & ~(3 << 5)) | val2; 714 val2 = (chip->image[CS4235_RIGHT_MASTER] & ~(3 << 5)) | val2;
703 change = val1 != chip->image[CS4235_LEFT_MASTER] || val2 != chip->image[CS4235_RIGHT_MASTER]; 715 change = val1 != chip->image[CS4235_LEFT_MASTER] || val2 != chip->image[CS4235_RIGHT_MASTER];
704 snd_cs4231_out(chip, CS4235_LEFT_MASTER, val1); 716 snd_wss_out(chip, CS4235_LEFT_MASTER, val1);
705 snd_cs4231_out(chip, CS4235_RIGHT_MASTER, val2); 717 snd_wss_out(chip, CS4235_RIGHT_MASTER, val2);
706 spin_unlock_irqrestore(&chip->reg_lock, flags); 718 spin_unlock_irqrestore(&chip->reg_lock, flags);
707 return change; 719 return change;
708} 720}
709 721
710static struct snd_kcontrol_new snd_cs4236_controls[] = { 722static struct snd_kcontrol_new snd_cs4236_controls[] = {
711 723
712CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1), 724CS4236_DOUBLE("Master Digital Playback Switch", 0,
713CS4236_DOUBLE("Master Digital Capture Switch", 0, CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1), 725 CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
726CS4236_DOUBLE("Master Digital Capture Switch", 0,
727 CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
714CS4236_MASTER_DIGITAL("Master Digital Volume", 0), 728CS4236_MASTER_DIGITAL("Master Digital Volume", 0),
715 729
716CS4236_DOUBLE("Capture Boost Volume", 0, CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1), 730CS4236_DOUBLE("Capture Boost Volume", 0,
717 731 CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1),
718CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), 732
719CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), 733WSS_DOUBLE("PCM Playback Switch", 0,
720 734 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
721CS4236_DOUBLE("DSP Playback Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), 735WSS_DOUBLE("PCM Playback Volume", 0,
722CS4236_DOUBLE("DSP Playback Volume", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1), 736 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
723 737
724CS4236_DOUBLE("FM Playback Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1), 738CS4236_DOUBLE("DSP Playback Switch", 0,
725CS4236_DOUBLE("FM Playback Volume", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1), 739 CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
726 740CS4236_DOUBLE("DSP Playback Volume", 0,
727CS4236_DOUBLE("Wavetable Playback Switch", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1), 741 CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1),
728CS4236_DOUBLE("Wavetable Playback Volume", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1), 742
729 743CS4236_DOUBLE("FM Playback Switch", 0,
730CS4231_DOUBLE("Synth Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), 744 CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
731CS4231_DOUBLE("Synth Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), 745CS4236_DOUBLE("FM Playback Volume", 0,
732CS4231_DOUBLE("Synth Capture Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), 746 CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1),
733CS4231_DOUBLE("Synth Capture Bypass", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1), 747
734 748CS4236_DOUBLE("Wavetable Playback Switch", 0,
735CS4236_DOUBLE("Mic Playback Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), 749 CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
736CS4236_DOUBLE("Mic Capture Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), 750CS4236_DOUBLE("Wavetable Playback Volume", 0,
751 CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1),
752
753WSS_DOUBLE("Synth Playback Switch", 0,
754 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
755WSS_DOUBLE("Synth Volume", 0,
756 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
757WSS_DOUBLE("Synth Capture Switch", 0,
758 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
759WSS_DOUBLE("Synth Capture Bypass", 0,
760 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1),
761
762CS4236_DOUBLE("Mic Playback Switch", 0,
763 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
764CS4236_DOUBLE("Mic Capture Switch", 0,
765 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
737CS4236_DOUBLE("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 0, 0, 31, 1), 766CS4236_DOUBLE("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 0, 0, 31, 1),
738CS4236_DOUBLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0), 767CS4236_DOUBLE("Mic Playback Boost", 0,
739 768 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0),
740CS4231_DOUBLE("Line Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), 769
741CS4231_DOUBLE("Line Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), 770WSS_DOUBLE("Line Playback Switch", 0,
742CS4231_DOUBLE("Line Capture Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), 771 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
743CS4231_DOUBLE("Line Capture Bypass", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1), 772WSS_DOUBLE("Line Volume", 0,
744 773 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
745CS4231_DOUBLE("CD Playback Switch", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), 774WSS_DOUBLE("Line Capture Switch", 0,
746CS4231_DOUBLE("CD Volume", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), 775 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
747CS4231_DOUBLE("CD Capture Switch", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), 776WSS_DOUBLE("Line Capture Bypass", 0,
748 777 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1),
749CS4236_DOUBLE1("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1), 778
750CS4236_DOUBLE1("Mono Playback Switch", 0, CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), 779WSS_DOUBLE("CD Playback Switch", 0,
751CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), 780 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
752CS4231_SINGLE("Mono Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0), 781WSS_DOUBLE("CD Volume", 0,
753 782 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
754CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), 783WSS_DOUBLE("CD Capture Switch", 0,
755CS4231_DOUBLE("Analog Loopback Capture Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), 784 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
756 785
757CS4231_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0), 786CS4236_DOUBLE1("Mono Output Playback Switch", 0,
758CS4236_DOUBLE1("Digital Loopback Playback Volume", 0, CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1) 787 CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
788CS4236_DOUBLE1("Mono Playback Switch", 0,
789 CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
790WSS_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
791WSS_SINGLE("Mono Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0),
792
793WSS_DOUBLE("Capture Volume", 0,
794 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
795WSS_DOUBLE("Analog Loopback Capture Switch", 0,
796 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
797
798WSS_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
799CS4236_DOUBLE1("Digital Loopback Playback Volume", 0,
800 CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1)
759}; 801};
760 802
761static struct snd_kcontrol_new snd_cs4235_controls[] = { 803static struct snd_kcontrol_new snd_cs4235_controls[] = {
762 804
763CS4231_DOUBLE("Master Switch", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1), 805WSS_DOUBLE("Master Switch", 0,
764CS4231_DOUBLE("Master Volume", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1), 806 CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
807WSS_DOUBLE("Master Volume", 0,
808 CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1),
765 809
766CS4235_OUTPUT_ACCU("Playback Volume", 0), 810CS4235_OUTPUT_ACCU("Playback Volume", 0),
767 811
768CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1), 812CS4236_DOUBLE("Master Digital Playback Switch", 0,
769CS4236_DOUBLE("Master Digital Capture Switch", 0, CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1), 813 CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
814CS4236_DOUBLE("Master Digital Capture Switch", 0,
815 CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
770CS4236_MASTER_DIGITAL("Master Digital Volume", 0), 816CS4236_MASTER_DIGITAL("Master Digital Volume", 0),
771 817
772CS4231_DOUBLE("Master Digital Playback Switch", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), 818WSS_DOUBLE("Master Digital Playback Switch", 1,
773CS4231_DOUBLE("Master Digital Capture Switch", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), 819 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
774CS4231_DOUBLE("Master Digital Volume", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), 820WSS_DOUBLE("Master Digital Capture Switch", 1,
821 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
822WSS_DOUBLE("Master Digital Volume", 1,
823 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
775 824
776CS4236_DOUBLE("Capture Volume", 0, CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1), 825CS4236_DOUBLE("Capture Volume", 0,
826 CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1),
777 827
778CS4231_DOUBLE("PCM Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), 828WSS_DOUBLE("PCM Switch", 0,
779CS4231_DOUBLE("PCM Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), 829 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
830WSS_DOUBLE("PCM Volume", 0,
831 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
780 832
781CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), 833CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
782 834
783CS4236_DOUBLE("FM Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1), 835CS4236_DOUBLE("FM Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
784 836
785CS4236_DOUBLE("Wavetable Switch", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1), 837CS4236_DOUBLE("Wavetable Switch", 0,
838 CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
786 839
787CS4236_DOUBLE("Mic Capture Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), 840CS4236_DOUBLE("Mic Capture Switch", 0,
788CS4236_DOUBLE("Mic Playback Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), 841 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
842CS4236_DOUBLE("Mic Playback Switch", 0,
843 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
789CS4236_SINGLE("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1), 844CS4236_SINGLE("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1),
790CS4236_SINGLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, 5, 1, 0), 845CS4236_SINGLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, 5, 1, 0),
791 846
792CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), 847WSS_DOUBLE("Aux Playback Switch", 0,
793CS4231_DOUBLE("Aux Capture Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), 848 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
794CS4231_DOUBLE("Aux Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), 849WSS_DOUBLE("Aux Capture Switch", 0,
795 850 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
796CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), 851WSS_DOUBLE("Aux Volume", 0,
797CS4231_DOUBLE("Aux Capture Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), 852 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
798CS4231_DOUBLE("Aux Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), 853
799 854WSS_DOUBLE("Aux Playback Switch", 1,
800CS4236_DOUBLE1("Master Mono Switch", 0, CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1), 855 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
801 856WSS_DOUBLE("Aux Capture Switch", 1,
802CS4236_DOUBLE1("Mono Switch", 0, CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), 857 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
803CS4231_SINGLE("Mono Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), 858WSS_DOUBLE("Aux Volume", 1,
804 859 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
805CS4231_DOUBLE("Analog Loopback Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), 860
861CS4236_DOUBLE1("Master Mono Switch", 0,
862 CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
863
864CS4236_DOUBLE1("Mono Switch", 0,
865 CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
866WSS_SINGLE("Mono Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
867
868WSS_DOUBLE("Analog Loopback Switch", 0,
869 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
806}; 870};
807 871
808#define CS4236_IEC958_ENABLE(xname, xindex) \ 872#define CS4236_IEC958_ENABLE(xname, xindex) \
@@ -813,14 +877,14 @@ CS4231_DOUBLE("Analog Loopback Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT
813 877
814static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 878static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
815{ 879{
816 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); 880 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
817 unsigned long flags; 881 unsigned long flags;
818 882
819 spin_lock_irqsave(&chip->reg_lock, flags); 883 spin_lock_irqsave(&chip->reg_lock, flags);
820 ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0; 884 ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0;
821#if 0 885#if 0
822 printk("get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", 886 printk("get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
823 snd_cs4231_in(chip, CS4231_ALT_FEATURE_1), 887 snd_wss_in(chip, CS4231_ALT_FEATURE_1),
824 snd_cs4236_ctrl_in(chip, 3), 888 snd_cs4236_ctrl_in(chip, 3),
825 snd_cs4236_ctrl_in(chip, 4), 889 snd_cs4236_ctrl_in(chip, 4),
826 snd_cs4236_ctrl_in(chip, 5), 890 snd_cs4236_ctrl_in(chip, 5),
@@ -833,7 +897,7 @@ static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct sn
833 897
834static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 898static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
835{ 899{
836 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); 900 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
837 unsigned long flags; 901 unsigned long flags;
838 int change; 902 int change;
839 unsigned short enable, val; 903 unsigned short enable, val;
@@ -841,23 +905,23 @@ static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct sn
841 enable = ucontrol->value.integer.value[0] & 1; 905 enable = ucontrol->value.integer.value[0] & 1;
842 906
843 mutex_lock(&chip->mce_mutex); 907 mutex_lock(&chip->mce_mutex);
844 snd_cs4231_mce_up(chip); 908 snd_wss_mce_up(chip);
845 spin_lock_irqsave(&chip->reg_lock, flags); 909 spin_lock_irqsave(&chip->reg_lock, flags);
846 val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1); 910 val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1);
847 change = val != chip->image[CS4231_ALT_FEATURE_1]; 911 change = val != chip->image[CS4231_ALT_FEATURE_1];
848 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, val); 912 snd_wss_out(chip, CS4231_ALT_FEATURE_1, val);
849 val = snd_cs4236_ctrl_in(chip, 4) | 0xc0; 913 val = snd_cs4236_ctrl_in(chip, 4) | 0xc0;
850 snd_cs4236_ctrl_out(chip, 4, val); 914 snd_cs4236_ctrl_out(chip, 4, val);
851 udelay(100); 915 udelay(100);
852 val &= ~0x40; 916 val &= ~0x40;
853 snd_cs4236_ctrl_out(chip, 4, val); 917 snd_cs4236_ctrl_out(chip, 4, val);
854 spin_unlock_irqrestore(&chip->reg_lock, flags); 918 spin_unlock_irqrestore(&chip->reg_lock, flags);
855 snd_cs4231_mce_down(chip); 919 snd_wss_mce_down(chip);
856 mutex_unlock(&chip->mce_mutex); 920 mutex_unlock(&chip->mce_mutex);
857 921
858#if 0 922#if 0
859 printk("set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", 923 printk("set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
860 snd_cs4231_in(chip, CS4231_ALT_FEATURE_1), 924 snd_wss_in(chip, CS4231_ALT_FEATURE_1),
861 snd_cs4236_ctrl_in(chip, 3), 925 snd_cs4236_ctrl_in(chip, 3),
862 snd_cs4236_ctrl_in(chip, 4), 926 snd_cs4236_ctrl_in(chip, 4),
863 snd_cs4236_ctrl_in(chip, 5), 927 snd_cs4236_ctrl_in(chip, 5),
@@ -896,19 +960,20 @@ CS4236_SINGLEC("3D Control - Volume", 0, 2, 0, 15, 1),
896CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0) 960CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
897}; 961};
898 962
899int snd_cs4236_mixer(struct snd_cs4231 *chip) 963int snd_cs4236_mixer(struct snd_wss *chip)
900{ 964{
901 struct snd_card *card; 965 struct snd_card *card;
902 unsigned int idx, count; 966 unsigned int idx, count;
903 int err; 967 int err;
904 struct snd_kcontrol_new *kcontrol; 968 struct snd_kcontrol_new *kcontrol;
905 969
906 snd_assert(chip != NULL && chip->card != NULL, return -EINVAL); 970 if (snd_BUG_ON(!chip || !chip->card))
971 return -EINVAL;
907 card = chip->card; 972 card = chip->card;
908 strcpy(card->mixername, snd_cs4231_chip_id(chip)); 973 strcpy(card->mixername, snd_wss_chip_id(chip));
909 974
910 if (chip->hardware == CS4231_HW_CS4235 || 975 if (chip->hardware == WSS_HW_CS4235 ||
911 chip->hardware == CS4231_HW_CS4239) { 976 chip->hardware == WSS_HW_CS4239) {
912 for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) { 977 for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) {
913 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0) 978 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0)
914 return err; 979 return err;
@@ -920,16 +985,16 @@ int snd_cs4236_mixer(struct snd_cs4231 *chip)
920 } 985 }
921 } 986 }
922 switch (chip->hardware) { 987 switch (chip->hardware) {
923 case CS4231_HW_CS4235: 988 case WSS_HW_CS4235:
924 case CS4231_HW_CS4239: 989 case WSS_HW_CS4239:
925 count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4235); 990 count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4235);
926 kcontrol = snd_cs4236_3d_controls_cs4235; 991 kcontrol = snd_cs4236_3d_controls_cs4235;
927 break; 992 break;
928 case CS4231_HW_CS4237B: 993 case WSS_HW_CS4237B:
929 count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4237); 994 count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4237);
930 kcontrol = snd_cs4236_3d_controls_cs4237; 995 kcontrol = snd_cs4236_3d_controls_cs4237;
931 break; 996 break;
932 case CS4231_HW_CS4238B: 997 case WSS_HW_CS4238B:
933 count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4238); 998 count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4238);
934 kcontrol = snd_cs4236_3d_controls_cs4238; 999 kcontrol = snd_cs4236_3d_controls_cs4238;
935 break; 1000 break;
@@ -941,8 +1006,8 @@ int snd_cs4236_mixer(struct snd_cs4231 *chip)
941 if ((err = snd_ctl_add(card, snd_ctl_new1(kcontrol, chip))) < 0) 1006 if ((err = snd_ctl_add(card, snd_ctl_new1(kcontrol, chip))) < 0)
942 return err; 1007 return err;
943 } 1008 }
944 if (chip->hardware == CS4231_HW_CS4237B || 1009 if (chip->hardware == WSS_HW_CS4237B ||
945 chip->hardware == CS4231_HW_CS4238B) { 1010 chip->hardware == WSS_HW_CS4238B) {
946 for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) { 1011 for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) {
947 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0) 1012 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0)
948 return err; 1013 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)
1009 int err; 1009 int err;
1010 unsigned char reg, val; 1010 unsigned char reg, val;
1011 1011
1012 snd_assert(chip != NULL && chip->card != NULL, return -EINVAL); 1012 if (snd_BUG_ON(!chip || !chip->card))
1013 return -EINVAL;
1013 1014
1014 card = chip->card; 1015 card = chip->card;
1015 1016
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)
276 static unsigned char dmas[8] = 276 static unsigned char dmas[8] =
277 {6, 1, 0, 2, 0, 3, 4, 5}; 277 {6, 1, 0, 2, 0, 3, 4, 5};
278 278
279 snd_assert(gus != NULL, return -EINVAL); 279 if (snd_BUG_ON(!gus))
280 return -EINVAL;
280 card = gus->card; 281 card = gus->card;
281 snd_assert(card != NULL, return -EINVAL); 282 if (snd_BUG_ON(!card))
283 return -EINVAL;
282 284
283 gus->mix_cntrl_reg &= 0xf8; 285 gus->mix_cntrl_reg &= 0xf8;
284 gus->mix_cntrl_reg |= 0x01; /* disable MIC, LINE IN, enable LINE OUT */ 286 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)
161 unsigned int idx, max; 161 unsigned int idx, max;
162 int err; 162 int err;
163 163
164 snd_assert(gus != NULL, return -EINVAL); 164 if (snd_BUG_ON(!gus))
165 return -EINVAL;
165 card = gus->card; 166 card = gus->card;
166 snd_assert(card != NULL, return -EINVAL); 167 if (snd_BUG_ON(!card))
168 return -EINVAL;
167 169
168 if (gus->ics_flag) 170 if (gus->ics_flag)
169 snd_component_add(card, "ICS2101"); 171 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,
352 352
353 bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2)); 353 bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
354 len = samples_to_bytes(runtime, count); 354 len = samples_to_bytes(runtime, count);
355 snd_assert(bpos <= pcmp->dma_size, return -EIO); 355 if (snd_BUG_ON(bpos > pcmp->dma_size))
356 snd_assert(bpos + len <= pcmp->dma_size, return -EIO); 356 return -EIO;
357 if (snd_BUG_ON(bpos + len > pcmp->dma_size))
358 return -EIO;
357 if (copy_from_user(runtime->dma_area + bpos, src, len)) 359 if (copy_from_user(runtime->dma_area + bpos, src, len))
358 return -EFAULT; 360 return -EFAULT;
359 if (snd_gf1_pcm_use_dma && len > 32) { 361 if (snd_gf1_pcm_use_dma && len > 32) {
@@ -381,8 +383,10 @@ static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream,
381 383
382 bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2)); 384 bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
383 len = samples_to_bytes(runtime, count); 385 len = samples_to_bytes(runtime, count);
384 snd_assert(bpos <= pcmp->dma_size, return -EIO); 386 if (snd_BUG_ON(bpos > pcmp->dma_size))
385 snd_assert(bpos + len <= pcmp->dma_size, return -EIO); 387 return -EIO;
388 if (snd_BUG_ON(bpos + len > pcmp->dma_size))
389 return -EIO;
386 snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos, count); 390 snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos, count);
387 if (snd_gf1_pcm_use_dma && len > 32) { 391 if (snd_gf1_pcm_use_dma && len > 32) {
388 return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len); 392 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 @@
28#include <asm/dma.h> 28#include <asm/dma.h>
29#include <sound/core.h> 29#include <sound/core.h>
30#include <sound/gus.h> 30#include <sound/gus.h>
31#include <sound/cs4231.h> 31#include <sound/wss.h>
32#define SNDRV_LEGACY_FIND_FREE_IRQ 32#define SNDRV_LEGACY_FIND_FREE_IRQ
33#define SNDRV_LEGACY_FIND_FREE_DMA 33#define SNDRV_LEGACY_FIND_FREE_DMA
34#include <sound/initval.h> 34#include <sound/initval.h>
@@ -75,7 +75,7 @@ struct snd_gusmax {
75 int irq; 75 int irq;
76 struct snd_card *card; 76 struct snd_card *card;
77 struct snd_gus_card *gus; 77 struct snd_gus_card *gus;
78 struct snd_cs4231 *cs4231; 78 struct snd_wss *wss;
79 unsigned short gus_status_reg; 79 unsigned short gus_status_reg;
80 unsigned short pcm_status_reg; 80 unsigned short pcm_status_reg;
81}; 81};
@@ -117,7 +117,7 @@ static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id)
117 } 117 }
118 if (inb(maxcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */ 118 if (inb(maxcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */
119 handled = 1; 119 handled = 1;
120 snd_cs4231_interrupt(irq, maxcard->cs4231); 120 snd_wss_interrupt(irq, maxcard->wss);
121 loop++; 121 loop++;
122 } 122 }
123 } while (loop && --max > 0); 123 } while (loop && --max > 0);
@@ -140,10 +140,7 @@ static void __devinit snd_gusmax_init(int dev, struct snd_card *card,
140 outb(gus->max_cntrl_val, GUSP(gus, MAXCNTRLPORT)); 140 outb(gus->max_cntrl_val, GUSP(gus, MAXCNTRLPORT));
141} 141}
142 142
143#define CS4231_PRIVATE( left, right, shift, mute ) \ 143static int __devinit snd_gusmax_mixer(struct snd_wss *chip)
144 ((left << 24)|(right << 16)|(shift<<8)|mute)
145
146static int __devinit snd_gusmax_mixer(struct snd_cs4231 *chip)
147{ 144{
148 struct snd_card *card = chip->card; 145 struct snd_card *card = chip->card;
149 struct snd_ctl_elem_id id1, id2; 146 struct snd_ctl_elem_id id1, id2;
@@ -214,7 +211,7 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
214 int xirq, xdma1, xdma2, err; 211 int xirq, xdma1, xdma2, err;
215 struct snd_card *card; 212 struct snd_card *card;
216 struct snd_gus_card *gus = NULL; 213 struct snd_gus_card *gus = NULL;
217 struct snd_cs4231 *cs4231; 214 struct snd_wss *wss;
218 struct snd_gusmax *maxcard; 215 struct snd_gusmax *maxcard;
219 216
220 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 217 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)
301 } 298 }
302 maxcard->irq = xirq; 299 maxcard->irq = xirq;
303 300
304 if ((err = snd_cs4231_create(card, 301 err = snd_wss_create(card,
305 gus->gf1.port + 0x10c, -1, xirq, 302 gus->gf1.port + 0x10c, -1, xirq,
306 xdma2 < 0 ? xdma1 : xdma2, xdma1, 303 xdma2 < 0 ? xdma1 : xdma2, xdma1,
307 CS4231_HW_DETECT, 304 WSS_HW_DETECT,
308 CS4231_HWSHARE_IRQ | 305 WSS_HWSHARE_IRQ |
309 CS4231_HWSHARE_DMA1 | 306 WSS_HWSHARE_DMA1 |
310 CS4231_HWSHARE_DMA2, 307 WSS_HWSHARE_DMA2,
311 &cs4231)) < 0) 308 &wss);
309 if (err < 0)
312 goto _err; 310 goto _err;
313 311
314 if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0) 312 err = snd_wss_pcm(wss, 0, NULL);
313 if (err < 0)
315 goto _err; 314 goto _err;
316 315
317 if ((err = snd_cs4231_mixer(cs4231)) < 0) 316 err = snd_wss_mixer(wss);
317 if (err < 0)
318 goto _err; 318 goto _err;
319 319
320 if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) 320 err = snd_wss_timer(wss, 2, NULL);
321 if (err < 0)
321 goto _err; 322 goto _err;
322 323
323 if (pcm_channels[dev] > 0) { 324 if (pcm_channels[dev] > 0) {
324 if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) 325 if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0)
325 goto _err; 326 goto _err;
326 } 327 }
327 if ((err = snd_gusmax_mixer(cs4231)) < 0) 328 err = snd_gusmax_mixer(wss);
329 if (err < 0)
328 goto _err; 330 goto _err;
329 331
330 if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) 332 err = snd_gf1_rawmidi_new(gus, 0, NULL);
333 if (err < 0)
331 goto _err; 334 goto _err;
332 335
333 sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %i, dma %i", gus->gf1.port, xirq, xdma1); 336 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)
336 339
337 snd_card_set_dev(card, pdev); 340 snd_card_set_dev(card, pdev);
338 341
339 if ((err = snd_card_register(card)) < 0) 342 err = snd_card_register(card);
343 if (err < 0)
340 goto _err; 344 goto _err;
341 345
342 maxcard->gus = gus; 346 maxcard->gus = gus;
343 maxcard->cs4231 = cs4231; 347 maxcard->wss = wss;
344 348
345 dev_set_drvdata(pdev, card); 349 dev_set_drvdata(pdev, card);
346 return 0; 350 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 @@
32#include <asm/dma.h> 32#include <asm/dma.h>
33#include <sound/core.h> 33#include <sound/core.h>
34#include <sound/gus.h> 34#include <sound/gus.h>
35#include <sound/cs4231.h> 35#include <sound/wss.h>
36#ifdef SNDRV_STB 36#ifdef SNDRV_STB
37#include <sound/tea6330t.h> 37#include <sound/tea6330t.h>
38#endif 38#endif
@@ -118,7 +118,7 @@ struct snd_interwave {
118 int irq; 118 int irq;
119 struct snd_card *card; 119 struct snd_card *card;
120 struct snd_gus_card *gus; 120 struct snd_gus_card *gus;
121 struct snd_cs4231 *cs4231; 121 struct snd_wss *wss;
122#ifdef SNDRV_STB 122#ifdef SNDRV_STB
123 struct resource *i2c_res; 123 struct resource *i2c_res;
124#endif 124#endif
@@ -312,7 +312,7 @@ static irqreturn_t snd_interwave_interrupt(int irq, void *dev_id)
312 } 312 }
313 if (inb(iwcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */ 313 if (inb(iwcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */
314 handled = 1; 314 handled = 1;
315 snd_cs4231_interrupt(irq, iwcard->cs4231); 315 snd_wss_interrupt(irq, iwcard->wss);
316 loop++; 316 loop++;
317 } 317 }
318 } while (loop && --max > 0); 318 } while (loop && --max > 0);
@@ -498,13 +498,17 @@ static void __devinit snd_interwave_init(int dev, struct snd_gus_card * gus)
498} 498}
499 499
500static struct snd_kcontrol_new snd_interwave_controls[] = { 500static struct snd_kcontrol_new snd_interwave_controls[] = {
501CS4231_DOUBLE("Master Playback Switch", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1), 501WSS_DOUBLE("Master Playback Switch", 0,
502CS4231_DOUBLE("Master Playback Volume", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1), 502 CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1),
503CS4231_DOUBLE("Mic Playback Switch", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1), 503WSS_DOUBLE("Master Playback Volume", 0,
504CS4231_DOUBLE("Mic Playback Volume", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1) 504 CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1),
505WSS_DOUBLE("Mic Playback Switch", 0,
506 CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1),
507WSS_DOUBLE("Mic Playback Volume", 0,
508 CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1)
505}; 509};
506 510
507static int __devinit snd_interwave_mixer(struct snd_cs4231 *chip) 511static int __devinit snd_interwave_mixer(struct snd_wss *chip)
508{ 512{
509 struct snd_card *card = chip->card; 513 struct snd_card *card = chip->card;
510 struct snd_ctl_elem_id id1, id2; 514 struct snd_ctl_elem_id id1, id2;
@@ -527,10 +531,10 @@ static int __devinit snd_interwave_mixer(struct snd_cs4231 *chip)
527 for (idx = 0; idx < ARRAY_SIZE(snd_interwave_controls); idx++) 531 for (idx = 0; idx < ARRAY_SIZE(snd_interwave_controls); idx++)
528 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_interwave_controls[idx], chip))) < 0) 532 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_interwave_controls[idx], chip))) < 0)
529 return err; 533 return err;
530 snd_cs4231_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f); 534 snd_wss_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f);
531 snd_cs4231_out(chip, CS4231_LINE_RIGHT_OUTPUT, 0x9f); 535 snd_wss_out(chip, CS4231_LINE_RIGHT_OUTPUT, 0x9f);
532 snd_cs4231_out(chip, CS4231_LEFT_MIC_INPUT, 0x9f); 536 snd_wss_out(chip, CS4231_LEFT_MIC_INPUT, 0x9f);
533 snd_cs4231_out(chip, CS4231_RIGHT_MIC_INPUT, 0x9f); 537 snd_wss_out(chip, CS4231_RIGHT_MIC_INPUT, 0x9f);
534 /* reassign AUXA to SYNTHESIZER */ 538 /* reassign AUXA to SYNTHESIZER */
535 strcpy(id1.name, "Aux Playback Switch"); 539 strcpy(id1.name, "Aux Playback Switch");
536 strcpy(id2.name, "Synth Playback Switch"); 540 strcpy(id2.name, "Synth Playback Switch");
@@ -642,7 +646,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
642{ 646{
643 int xirq, xdma1, xdma2; 647 int xirq, xdma1, xdma2;
644 struct snd_interwave *iwcard = card->private_data; 648 struct snd_interwave *iwcard = card->private_data;
645 struct snd_cs4231 *cs4231; 649 struct snd_wss *wss;
646 struct snd_gus_card *gus; 650 struct snd_gus_card *gus;
647#ifdef SNDRV_STB 651#ifdef SNDRV_STB
648 struct snd_i2c_bus *i2c_bus; 652 struct snd_i2c_bus *i2c_bus;
@@ -684,33 +688,39 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
684 } 688 }
685 iwcard->irq = xirq; 689 iwcard->irq = xirq;
686 690
687 if ((err = snd_cs4231_create(card, 691 err = snd_wss_create(card,
688 gus->gf1.port + 0x10c, -1, xirq, 692 gus->gf1.port + 0x10c, -1, xirq,
689 xdma2 < 0 ? xdma1 : xdma2, xdma1, 693 xdma2 < 0 ? xdma1 : xdma2, xdma1,
690 CS4231_HW_INTERWAVE, 694 WSS_HW_INTERWAVE,
691 CS4231_HWSHARE_IRQ | 695 WSS_HWSHARE_IRQ |
692 CS4231_HWSHARE_DMA1 | 696 WSS_HWSHARE_DMA1 |
693 CS4231_HWSHARE_DMA2, 697 WSS_HWSHARE_DMA2,
694 &cs4231)) < 0) 698 &wss);
699 if (err < 0)
695 return err; 700 return err;
696 701
697 if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0) 702 err = snd_wss_pcm(wss, 0, &pcm);
703 if (err < 0)
698 return err; 704 return err;
699 705
700 sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A'); 706 sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A');
701 strcat(pcm->name, " (codec)"); 707 strcat(pcm->name, " (codec)");
702 708
703 if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) 709 err = snd_wss_timer(wss, 2, NULL);
710 if (err < 0)
704 return err; 711 return err;
705 712
706 if ((err = snd_cs4231_mixer(cs4231)) < 0) 713 err = snd_wss_mixer(wss);
714 if (err < 0)
707 return err; 715 return err;
708 716
709 if (pcm_channels[dev] > 0) { 717 if (pcm_channels[dev] > 0) {
710 if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) 718 err = snd_gf1_pcm_new(gus, 1, 1, NULL);
719 if (err < 0)
711 return err; 720 return err;
712 } 721 }
713 if ((err = snd_interwave_mixer(cs4231)) < 0) 722 err = snd_interwave_mixer(wss);
723 if (err < 0)
714 return err; 724 return err;
715 725
716#ifdef SNDRV_STB 726#ifdef SNDRV_STB
@@ -754,10 +764,11 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
754 if (xdma2 >= 0) 764 if (xdma2 >= 0)
755 sprintf(card->longname + strlen(card->longname), "&%d", xdma2); 765 sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
756 766
757 if ((err = snd_card_register(card)) < 0) 767 err = snd_card_register(card);
768 if (err < 0)
758 return err; 769 return err;
759 770
760 iwcard->cs4231 = cs4231; 771 iwcard->wss = wss;
761 iwcard->gus = gus; 772 iwcard->gus = gus;
762 return 0; 773 return 0;
763} 774}
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 @@
28#include <linux/pnp.h> 28#include <linux/pnp.h>
29#include <linux/moduleparam.h> 29#include <linux/moduleparam.h>
30#include <sound/core.h> 30#include <sound/core.h>
31#include <sound/cs4231.h> 31#include <sound/wss.h>
32#include <sound/mpu401.h> 32#include <sound/mpu401.h>
33#include <sound/opl3.h> 33#include <sound/opl3.h>
34#include <sound/initval.h> 34#include <sound/initval.h>
@@ -124,7 +124,6 @@ static int pnpc_registered;
124#define OPL3SA2_PM_D3 (OPL3SA2_PM_ADOWN|OPL3SA2_PM_PSV|OPL3SA2_PM_PDN|OPL3SA2_PM_PDX) 124#define OPL3SA2_PM_D3 (OPL3SA2_PM_ADOWN|OPL3SA2_PM_PSV|OPL3SA2_PM_PDN|OPL3SA2_PM_PDX)
125 125
126struct snd_opl3sa2 { 126struct snd_opl3sa2 {
127 struct snd_card *card;
128 int version; /* 2 or 3 */ 127 int version; /* 2 or 3 */
129 unsigned long port; /* control port */ 128 unsigned long port; /* control port */
130 struct resource *res_port; /* control port resource */ 129 struct resource *res_port; /* control port resource */
@@ -133,7 +132,7 @@ struct snd_opl3sa2 {
133 spinlock_t reg_lock; 132 spinlock_t reg_lock;
134 struct snd_hwdep *synth; 133 struct snd_hwdep *synth;
135 struct snd_rawmidi *rmidi; 134 struct snd_rawmidi *rmidi;
136 struct snd_cs4231 *cs4231; 135 struct snd_wss *wss;
137 unsigned char ctlregs[0x20]; 136 unsigned char ctlregs[0x20];
138 int ymode; /* SL added */ 137 int ymode; /* SL added */
139 struct snd_kcontrol *master_switch; 138 struct snd_kcontrol *master_switch;
@@ -222,14 +221,13 @@ static void snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsig
222 spin_unlock_irqrestore(&chip->reg_lock, flags); 221 spin_unlock_irqrestore(&chip->reg_lock, flags);
223} 222}
224 223
225static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip) 224static int __devinit snd_opl3sa2_detect(struct snd_card *card)
226{ 225{
227 struct snd_card *card; 226 struct snd_opl3sa2 *chip = card->private_data;
228 unsigned long port; 227 unsigned long port;
229 unsigned char tmp, tmp1; 228 unsigned char tmp, tmp1;
230 char str[2]; 229 char str[2];
231 230
232 card = chip->card;
233 port = chip->port; 231 port = chip->port;
234 if ((chip->res_port = request_region(port, 2, "OPL3-SA control")) == NULL) { 232 if ((chip->res_port = request_region(port, 2, "OPL3-SA control")) == NULL) {
235 snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port); 233 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)
298static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id) 296static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id)
299{ 297{
300 unsigned short status; 298 unsigned short status;
301 struct snd_opl3sa2 *chip = dev_id; 299 struct snd_card *card = dev_id;
300 struct snd_opl3sa2 *chip;
302 int handled = 0; 301 int handled = 0;
303 302
304 if (chip == NULL || chip->card == NULL) 303 if (card == NULL)
305 return IRQ_NONE; 304 return IRQ_NONE;
306 305
306 chip = card->private_data;
307 status = snd_opl3sa2_read(chip, OPL3SA2_IRQ_STATUS); 307 status = snd_opl3sa2_read(chip, OPL3SA2_IRQ_STATUS);
308 308
309 if (status & 0x20) { 309 if (status & 0x20) {
@@ -318,7 +318,7 @@ static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id)
318 318
319 if (status & 0x07) { /* TI,CI,PI */ 319 if (status & 0x07) { /* TI,CI,PI */
320 handled = 1; 320 handled = 1;
321 snd_cs4231_interrupt(irq, chip->cs4231); 321 snd_wss_interrupt(irq, chip->wss);
322 } 322 }
323 323
324 if (status & 0x40) { /* hardware volume change */ 324 if (status & 0x40) { /* hardware volume change */
@@ -327,8 +327,10 @@ static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id)
327 snd_opl3sa2_read(chip, OPL3SA2_MASTER_RIGHT); 327 snd_opl3sa2_read(chip, OPL3SA2_MASTER_RIGHT);
328 snd_opl3sa2_read(chip, OPL3SA2_MASTER_LEFT); 328 snd_opl3sa2_read(chip, OPL3SA2_MASTER_LEFT);
329 if (chip->master_switch && chip->master_volume) { 329 if (chip->master_switch && chip->master_volume) {
330 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_switch->id); 330 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
331 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_volume->id); 331 &chip->master_switch->id);
332 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
333 &chip->master_volume->id);
332 } 334 }
333 } 335 }
334 return IRQ_RETVAL(handled); 336 return IRQ_RETVAL(handled);
@@ -336,29 +338,18 @@ static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id)
336 338
337#define OPL3SA2_SINGLE(xname, xindex, reg, shift, mask, invert) \ 339#define OPL3SA2_SINGLE(xname, xindex, reg, shift, mask, invert) \
338{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 340{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
339 .info = snd_opl3sa2_info_single, \ 341 .info = snd_wss_info_single, \
340 .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \ 342 .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \
341 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } 343 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
342#define OPL3SA2_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ 344#define OPL3SA2_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
343{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 345{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
344 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ 346 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
345 .name = xname, .index = xindex, \ 347 .name = xname, .index = xindex, \
346 .info = snd_opl3sa2_info_single, \ 348 .info = snd_wss_info_single, \
347 .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \ 349 .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \
348 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ 350 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
349 .tlv = { .p = (xtlv) } } 351 .tlv = { .p = (xtlv) } }
350 352
351static int snd_opl3sa2_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
352{
353 int mask = (kcontrol->private_value >> 16) & 0xff;
354
355 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
356 uinfo->count = 1;
357 uinfo->value.integer.min = 0;
358 uinfo->value.integer.max = mask;
359 return 0;
360}
361
362static int snd_opl3sa2_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 353static int snd_opl3sa2_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
363{ 354{
364 struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); 355 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_
402 393
403#define OPL3SA2_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ 394#define OPL3SA2_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
404{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 395{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
405 .info = snd_opl3sa2_info_double, \ 396 .info = snd_wss_info_double, \
406 .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \ 397 .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \
407 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } 398 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
408#define OPL3SA2_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ 399#define OPL3SA2_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \
409{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 400{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
410 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ 401 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
411 .name = xname, .index = xindex, \ 402 .name = xname, .index = xindex, \
412 .info = snd_opl3sa2_info_double, \ 403 .info = snd_wss_info_double, \
413 .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \ 404 .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \
414 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22), \ 405 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22), \
415 .tlv = { .p = (xtlv) } } 406 .tlv = { .p = (xtlv) } }
416 407
417static int snd_opl3sa2_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
418{
419 int mask = (kcontrol->private_value >> 24) & 0xff;
420
421 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
422 uinfo->count = 2;
423 uinfo->value.integer.min = 0;
424 uinfo->value.integer.max = mask;
425 return 0;
426}
427
428static int snd_opl3sa2_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 408static int snd_opl3sa2_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
429{ 409{
430 struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); 410 struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol);
@@ -512,9 +492,9 @@ static void snd_opl3sa2_master_free(struct snd_kcontrol *kcontrol)
512 chip->master_volume = NULL; 492 chip->master_volume = NULL;
513} 493}
514 494
515static int __devinit snd_opl3sa2_mixer(struct snd_opl3sa2 *chip) 495static int __devinit snd_opl3sa2_mixer(struct snd_card *card)
516{ 496{
517 struct snd_card *card = chip->card; 497 struct snd_opl3sa2 *chip = card->private_data;
518 struct snd_ctl_elem_id id1, id2; 498 struct snd_ctl_elem_id id1, id2;
519 struct snd_kcontrol *kctl; 499 struct snd_kcontrol *kctl;
520 unsigned int idx; 500 unsigned int idx;
@@ -573,7 +553,7 @@ static int snd_opl3sa2_suspend(struct snd_card *card, pm_message_t state)
573 struct snd_opl3sa2 *chip = card->private_data; 553 struct snd_opl3sa2 *chip = card->private_data;
574 554
575 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 555 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
576 chip->cs4231->suspend(chip->cs4231); 556 chip->wss->suspend(chip->wss);
577 /* power down */ 557 /* power down */
578 snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3); 558 snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3);
579 559
@@ -597,8 +577,8 @@ static int snd_opl3sa2_resume(struct snd_card *card)
597 for (i = 0x12; i <= 0x16; i++) 577 for (i = 0x12; i <= 0x16; i++)
598 snd_opl3sa2_write(chip, i, chip->ctlregs[i]); 578 snd_opl3sa2_write(chip, i, chip->ctlregs[i]);
599 } 579 }
600 /* restore cs4231 */ 580 /* restore wss */
601 chip->cs4231->resume(chip->cs4231); 581 chip->wss->resume(chip->wss);
602 582
603 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 583 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
604 return 0; 584 return 0;
@@ -650,7 +630,6 @@ static struct snd_card *snd_opl3sa2_card_new(int dev)
650 chip = card->private_data; 630 chip = card->private_data;
651 spin_lock_init(&chip->reg_lock); 631 spin_lock_init(&chip->reg_lock);
652 chip->irq = -1; 632 chip->irq = -1;
653 chip->card = card;
654 card->private_free = snd_opl3sa2_free; 633 card->private_free = snd_opl3sa2_free;
655 return card; 634 return card;
656} 635}
@@ -659,7 +638,7 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
659{ 638{
660 int xirq, xdma1, xdma2; 639 int xirq, xdma1, xdma2;
661 struct snd_opl3sa2 *chip; 640 struct snd_opl3sa2 *chip;
662 struct snd_cs4231 *cs4231; 641 struct snd_wss *wss;
663 struct snd_opl3 *opl3; 642 struct snd_opl3 *opl3;
664 int err; 643 int err;
665 644
@@ -672,30 +651,36 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
672 xdma2 = dma2[dev]; 651 xdma2 = dma2[dev];
673 if (xdma2 < 0) 652 if (xdma2 < 0)
674 chip->single_dma = 1; 653 chip->single_dma = 1;
675 if ((err = snd_opl3sa2_detect(chip)) < 0) 654 err = snd_opl3sa2_detect(card);
655 if (err < 0)
676 return err; 656 return err;
677 if (request_irq(xirq, snd_opl3sa2_interrupt, IRQF_DISABLED, "OPL3-SA2", chip)) { 657 err = request_irq(xirq, snd_opl3sa2_interrupt, IRQF_DISABLED,
658 "OPL3-SA2", card);
659 if (err) {
678 snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq); 660 snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq);
679 return -ENODEV; 661 return -ENODEV;
680 } 662 }
681 chip->irq = xirq; 663 chip->irq = xirq;
682 if ((err = snd_cs4231_create(card, 664 err = snd_wss_create(card,
683 wss_port[dev] + 4, -1, 665 wss_port[dev] + 4, -1,
684 xirq, xdma1, xdma2, 666 xirq, xdma1, xdma2,
685 CS4231_HW_OPL3SA2, 667 WSS_HW_OPL3SA2, WSS_HWSHARE_IRQ, &wss);
686 CS4231_HWSHARE_IRQ, 668 if (err < 0) {
687 &cs4231)) < 0) {
688 snd_printd("Oops, WSS not detected at 0x%lx\n", wss_port[dev] + 4); 669 snd_printd("Oops, WSS not detected at 0x%lx\n", wss_port[dev] + 4);
689 return err; 670 return err;
690 } 671 }
691 chip->cs4231 = cs4231; 672 chip->wss = wss;
692 if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0) 673 err = snd_wss_pcm(wss, 0, NULL);
674 if (err < 0)
693 return err; 675 return err;
694 if ((err = snd_cs4231_mixer(cs4231)) < 0) 676 err = snd_wss_mixer(wss);
677 if (err < 0)
695 return err; 678 return err;
696 if ((err = snd_opl3sa2_mixer(chip)) < 0) 679 err = snd_opl3sa2_mixer(card);
680 if (err < 0)
697 return err; 681 return err;
698 if ((err = snd_cs4231_timer(cs4231, 0, NULL)) < 0) 682 err = snd_wss_timer(wss, 0, NULL);
683 if (err < 0)
699 return err; 684 return err;
700 if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) { 685 if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) {
701 if ((err = snd_opl3_create(card, fm_port[dev], 686 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 @@
32#include <asm/io.h> 32#include <asm/io.h>
33#include <asm/dma.h> 33#include <asm/dma.h>
34#include <sound/core.h> 34#include <sound/core.h>
35#include <sound/cs4231.h> 35#include <sound/wss.h>
36#include <sound/mpu401.h> 36#include <sound/mpu401.h>
37#include <sound/opl4.h> 37#include <sound/opl4.h>
38#include <sound/control.h> 38#include <sound/control.h>
@@ -675,7 +675,8 @@ static int __devinit snd_miro_mixer(struct snd_miro *miro)
675 unsigned int idx; 675 unsigned int idx;
676 int err; 676 int err;
677 677
678 snd_assert(miro != NULL && miro->card != NULL, return -EINVAL); 678 if (snd_BUG_ON(!miro || !miro->card))
679 return -EINVAL;
679 680
680 card = miro->card; 681 card = miro->card;
681 682
@@ -1221,7 +1222,7 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
1221 1222
1222 int error; 1223 int error;
1223 struct snd_miro *miro; 1224 struct snd_miro *miro;
1224 struct snd_cs4231 *codec; 1225 struct snd_wss *codec;
1225 struct snd_timer *timer; 1226 struct snd_timer *timer;
1226 struct snd_card *card; 1227 struct snd_card *card;
1227 struct snd_pcm *pcm; 1228 struct snd_pcm *pcm;
@@ -1310,29 +1311,32 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
1310 } 1311 }
1311 } 1312 }
1312 1313
1313 if ((error = snd_miro_configure(miro))) { 1314 error = snd_miro_configure(miro);
1315 if (error) {
1314 snd_card_free(card); 1316 snd_card_free(card);
1315 return error; 1317 return error;
1316 } 1318 }
1317 1319
1318 if ((error = snd_cs4231_create(card, miro->wss_base + 4, -1, 1320 error = snd_wss_create(card, miro->wss_base + 4, -1,
1319 miro->irq, miro->dma1, miro->dma2, 1321 miro->irq, miro->dma1, miro->dma2,
1320 CS4231_HW_AD1845, 1322 WSS_HW_AD1845, 0, &codec);
1321 0, 1323 if (error < 0) {
1322 &codec)) < 0) {
1323 snd_card_free(card); 1324 snd_card_free(card);
1324 return error; 1325 return error;
1325 } 1326 }
1326 1327
1327 if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0) { 1328 error = snd_wss_pcm(codec, 0, &pcm);
1329 if (error < 0) {
1328 snd_card_free(card); 1330 snd_card_free(card);
1329 return error; 1331 return error;
1330 } 1332 }
1331 if ((error = snd_cs4231_mixer(codec)) < 0) { 1333 error = snd_wss_mixer(codec);
1334 if (error < 0) {
1332 snd_card_free(card); 1335 snd_card_free(card);
1333 return error; 1336 return error;
1334 } 1337 }
1335 if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0) { 1338 error = snd_wss_timer(codec, 0, &timer);
1339 if (error < 0) {
1336 snd_card_free(card); 1340 snd_card_free(card);
1337 return error; 1341 return error;
1338 } 1342 }
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 @@
33#include <asm/io.h> 33#include <asm/io.h>
34#include <asm/dma.h> 34#include <asm/dma.h>
35#include <sound/core.h> 35#include <sound/core.h>
36#if defined(CS4231) || defined(OPTi93X) 36#include <sound/wss.h>
37#include <sound/cs4231.h>
38#else
39#include <sound/ad1848.h>
40#endif /* CS4231 */
41#include <sound/mpu401.h> 37#include <sound/mpu401.h>
42#include <sound/opl3.h> 38#include <sound/opl3.h>
43#ifndef OPTi93X 39#ifndef OPTi93X
@@ -139,7 +135,7 @@ struct snd_opti9xx {
139 unsigned long mc_base_size; 135 unsigned long mc_base_size;
140#ifdef OPTi93X 136#ifdef OPTi93X
141 unsigned long mc_indir_index; 137 unsigned long mc_indir_index;
142 struct snd_cs4231 *codec; 138 struct snd_wss *codec;
143#endif /* OPTi93X */ 139#endif /* OPTi93X */
144 unsigned long pwd_reg; 140 unsigned long pwd_reg;
145 141
@@ -148,9 +144,7 @@ struct snd_opti9xx {
148 long wss_base; 144 long wss_base;
149 int irq; 145 int irq;
150 int dma1; 146 int dma1;
151#if defined(CS4231) || defined(OPTi93X)
152 int dma2; 147 int dma2;
153#endif /* CS4231 || OPTi93X */
154 148
155 long fm_port; 149 long fm_port;
156 150
@@ -225,9 +219,7 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
225 chip->wss_base = -1; 219 chip->wss_base = -1;
226 chip->irq = -1; 220 chip->irq = -1;
227 chip->dma1 = -1; 221 chip->dma1 = -1;
228#if defined(CS4231) || defined (OPTi93X)
229 chip->dma2 = -1; 222 chip->dma2 = -1;
230#endif /* CS4231 || OPTi93X */
231 chip->fm_port = -1; 223 chip->fm_port = -1;
232 chip->mpu_port = -1; 224 chip->mpu_port = -1;
233 chip->mpu_irq = -1; 225 chip->mpu_irq = -1;
@@ -562,7 +554,7 @@ __skip_mpu:
562 554
563static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id) 555static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
564{ 556{
565 struct snd_cs4231 *codec = dev_id; 557 struct snd_wss *codec = dev_id;
566 struct snd_opti9xx *chip = codec->card->private_data; 558 struct snd_opti9xx *chip = codec->card->private_data;
567 unsigned char status; 559 unsigned char status;
568 560
@@ -570,7 +562,7 @@ static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
570 if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream) 562 if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream)
571 snd_pcm_period_elapsed(codec->playback_substream); 563 snd_pcm_period_elapsed(codec->playback_substream);
572 if ((status & OPTi93X_IRQ_CAPTURE) && codec->capture_substream) { 564 if ((status & OPTi93X_IRQ_CAPTURE) && codec->capture_substream) {
573 snd_cs4231_overrange(codec); 565 snd_wss_overrange(codec);
574 snd_pcm_period_elapsed(codec->capture_substream); 566 snd_pcm_period_elapsed(codec->capture_substream);
575 } 567 }
576 outb(0x00, OPTi93X_PORT(codec, STATUS)); 568 outb(0x00, OPTi93X_PORT(codec, STATUS));
@@ -691,7 +683,7 @@ static void snd_card_opti9xx_free(struct snd_card *card)
691 683
692 if (chip) { 684 if (chip) {
693#ifdef OPTi93X 685#ifdef OPTi93X
694 struct snd_cs4231 *codec = chip->codec; 686 struct snd_wss *codec = chip->codec;
695 if (codec && codec->irq > 0) { 687 if (codec && codec->irq > 0) {
696 disable_irq(codec->irq); 688 disable_irq(codec->irq);
697 free_irq(codec->irq, codec); 689 free_irq(codec->irq, codec);
@@ -706,14 +698,10 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
706 static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; 698 static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
707 int error; 699 int error;
708 struct snd_opti9xx *chip = card->private_data; 700 struct snd_opti9xx *chip = card->private_data;
709#if defined(CS4231) || defined(OPTi93X) 701 struct snd_wss *codec;
710 struct snd_cs4231 *codec;
711#ifdef CS4231 702#ifdef CS4231
712 struct snd_timer *timer; 703 struct snd_timer *timer;
713#endif 704#endif
714#else
715 struct snd_ad1848 *codec;
716#endif
717 struct snd_pcm *pcm; 705 struct snd_pcm *pcm;
718 struct snd_rawmidi *rmidi; 706 struct snd_rawmidi *rmidi;
719 struct snd_hwdep *synth; 707 struct snd_hwdep *synth;
@@ -731,38 +719,46 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
731 chip->dma1 = dma1; 719 chip->dma1 = dma1;
732#if defined(CS4231) || defined(OPTi93X) 720#if defined(CS4231) || defined(OPTi93X)
733 chip->dma2 = dma2; 721 chip->dma2 = dma2;
722#else
723 chip->dma2 = -1;
734#endif 724#endif
735 725
736 if (chip->wss_base == SNDRV_AUTO_PORT) { 726 if (chip->wss_base == SNDRV_AUTO_PORT) {
737 if ((chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) { 727 chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4);
728 if (chip->wss_base < 0) {
738 snd_printk("unable to find a free WSS port\n"); 729 snd_printk("unable to find a free WSS port\n");
739 return -EBUSY; 730 return -EBUSY;
740 } 731 }
741 } 732 }
742 if ((error = snd_opti9xx_configure(chip))) 733 error = snd_opti9xx_configure(chip);
734 if (error)
743 return error; 735 return error;
744 736
745#if defined(CS4231) || defined(OPTi93X) 737 error = snd_wss_create(card, chip->wss_base + 4, -1,
746 if ((error = snd_cs4231_create(card, chip->wss_base + 4, -1, 738 chip->irq, chip->dma1, chip->dma2,
747 chip->irq, chip->dma1, chip->dma2, 739#ifdef OPTi93X
748#ifdef CS4231 740 WSS_HW_OPTI93X, WSS_HWSHARE_IRQ,
749 CS4231_HW_DETECT, 0, 741#else
750#else /* OPTi93x */ 742 WSS_HW_DETECT, 0,
751 CS4231_HW_OPTI93X, CS4231_HWSHARE_IRQ,
752#endif 743#endif
753 &codec)) < 0) 744 &codec);
745 if (error < 0)
754 return error; 746 return error;
755#ifdef OPTi93X 747#ifdef OPTi93X
756 chip->codec = codec; 748 chip->codec = codec;
757#endif 749#endif
758 if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0) 750 error = snd_wss_pcm(codec, 0, &pcm);
751 if (error < 0)
759 return error; 752 return error;
760 if ((error = snd_cs4231_mixer(codec)) < 0) 753 error = snd_wss_mixer(codec);
754 if (error < 0)
761 return error; 755 return error;
762#ifdef CS4231 756#ifdef CS4231
763 if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0) 757 error = snd_wss_timer(codec, 0, &timer);
758 if (error < 0)
764 return error; 759 return error;
765#else /* OPTI93X */ 760#endif
761#ifdef OPTi93X
766 error = request_irq(chip->irq, snd_opti93x_interrupt, 762 error = request_irq(chip->irq, snd_opti93x_interrupt,
767 IRQF_DISABLED, DEV_NAME" - WSS", codec); 763 IRQF_DISABLED, DEV_NAME" - WSS", codec);
768 if (error < 0) { 764 if (error < 0) {
@@ -770,16 +766,6 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
770 return error; 766 return error;
771 } 767 }
772#endif 768#endif
773#else
774 if ((error = snd_ad1848_create(card, chip->wss_base + 4,
775 chip->irq, chip->dma1,
776 AD1848_HW_DETECT, &codec)) < 0)
777 return error;
778 if ((error = snd_ad1848_pcm(codec, 0, &pcm)) < 0)
779 return error;
780 if ((error = snd_ad1848_mixer(codec)) < 0)
781 return error;
782#endif
783 strcpy(card->driver, chip->name); 769 strcpy(card->driver, chip->name);
784 sprintf(card->shortname, "OPTi %s", card->driver); 770 sprintf(card->shortname, "OPTi %s", card->driver);
785#if defined(CS4231) || defined(OPTi93X) 771#if defined(CS4231) || defined(OPTi93X)
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)
1023{ 1023{
1024 int i, err = 0; 1024 int i, err = 0;
1025 1025
1026 snd_assert(emu != NULL && card != NULL, return -EINVAL); 1026 if (snd_BUG_ON(!emu || !card))
1027 return -EINVAL;
1027 1028
1028 spin_lock_init(&emu->control_lock); 1029 spin_lock_init(&emu->control_lock);
1029 1030
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,
156 struct snd_emu8000 *emu; 156 struct snd_emu8000 *emu;
157 157
158 emu = rec->hw; 158 emu = rec->hw;
159 snd_assert(sp != NULL, return -EINVAL); 159 if (snd_BUG_ON(!sp))
160 return -EINVAL;
160 161
161 if (sp->v.size == 0) 162 if (sp->v.size == 0)
162 return 0; 163 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
198 struct snd_sb_csp_start start_info; 198 struct snd_sb_csp_start start_info;
199 int err; 199 int err;
200 200
201 snd_assert(p != NULL, return -EINVAL); 201 if (snd_BUG_ON(!p))
202 return -EINVAL;
202 203
203 if (snd_sb_csp_check_version(p)) 204 if (snd_sb_csp_check_version(p))
204 return -ENODEV; 205 return -ENODEV;
@@ -1046,7 +1047,8 @@ static int snd_sb_qsound_build(struct snd_sb_csp * p)
1046 struct snd_card *card; 1047 struct snd_card *card;
1047 int err; 1048 int err;
1048 1049
1049 snd_assert(p != NULL, return -EINVAL); 1050 if (snd_BUG_ON(!p))
1051 return -EINVAL;
1050 1052
1051 card = p->chip->card; 1053 card = p->chip->card;
1052 p->qpos_left = p->qpos_right = SNDRV_SB_CSP_QSOUND_MAX_RIGHT / 2; 1054 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)
1071 struct snd_card *card; 1073 struct snd_card *card;
1072 unsigned long flags; 1074 unsigned long flags;
1073 1075
1074 snd_assert(p != NULL, return); 1076 if (snd_BUG_ON(!p))
1077 return;
1075 1078
1076 card = p->chip->card; 1079 card = p->chip->card;
1077 1080
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)
669static int snd_sb16_set_dma_mode(struct snd_sb *chip, int what) 669static int snd_sb16_set_dma_mode(struct snd_sb *chip, int what)
670{ 670{
671 if (chip->dma8 < 0 || chip->dma16 < 0) { 671 if (chip->dma8 < 0 || chip->dma16 < 0) {
672 snd_assert(what == 0, return -EINVAL); 672 if (snd_BUG_ON(what))
673 return -EINVAL;
673 return 0; 674 return 0;
674 } 675 }
675 if (what == 0) { 676 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)
111 switch (chip->hardware) { 111 switch (chip->hardware) {
112 case SB_HW_PRO: 112 case SB_HW_PRO:
113 if (runtime->channels > 1) { 113 if (runtime->channels > 1) {
114 snd_assert(rate == SB8_RATE(11025) || rate == SB8_RATE(22050), return -EINVAL); 114 if (snd_BUG_ON(rate != SB8_RATE(11025) &&
115 rate != SB8_RATE(22050)))
116 return -EINVAL;
115 chip->playback_format = SB_DSP_HI_OUTPUT_AUTO; 117 chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
116 break; 118 break;
117 } 119 }
@@ -237,7 +239,9 @@ static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream)
237 switch (chip->hardware) { 239 switch (chip->hardware) {
238 case SB_HW_PRO: 240 case SB_HW_PRO:
239 if (runtime->channels > 1) { 241 if (runtime->channels > 1) {
240 snd_assert(rate == SB8_RATE(11025) || rate == SB8_RATE(22050), return -EINVAL); 242 if (snd_BUG_ON(rate != SB8_RATE(11025) &&
243 rate != SB8_RATE(22050)))
244 return -EINVAL;
241 chip->capture_format = SB_DSP_HI_INPUT_AUTO; 245 chip->capture_format = SB_DSP_HI_INPUT_AUTO;
242 break; 246 break;
243 } 247 }
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,
219 .dev_free = snd_sbdsp_dev_free, 219 .dev_free = snd_sbdsp_dev_free,
220 }; 220 };
221 221
222 snd_assert(r_chip != NULL, return -EINVAL); 222 if (snd_BUG_ON(!r_chip))
223 return -EINVAL;
223 *r_chip = NULL; 224 *r_chip = NULL;
224 chip = kzalloc(sizeof(*chip), GFP_KERNEL); 225 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
225 if (chip == NULL) 226 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)
792 struct snd_card *card; 792 struct snd_card *card;
793 int err; 793 int err;
794 794
795 snd_assert(chip != NULL && chip->card != NULL, return -EINVAL); 795 if (snd_BUG_ON(!chip || !chip->card))
796 return -EINVAL;
796 797
797 card = chip->card; 798 card = chip->card;
798 799
@@ -925,7 +926,8 @@ static unsigned char als4000_saved_regs[] = {
925static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) 926static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs)
926{ 927{
927 unsigned char *val = chip->saved_regs; 928 unsigned char *val = chip->saved_regs;
928 snd_assert(num_regs <= ARRAY_SIZE(chip->saved_regs), return); 929 if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs)))
930 return;
929 for (; num_regs; num_regs--) 931 for (; num_regs; num_regs--)
930 *val++ = snd_sbmixer_read(chip, *regs++); 932 *val++ = snd_sbmixer_read(chip, *regs++);
931} 933}
@@ -933,7 +935,8 @@ static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs)
933static void restore_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) 935static void restore_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs)
934{ 936{
935 unsigned char *val = chip->saved_regs; 937 unsigned char *val = chip->saved_regs;
936 snd_assert(num_regs <= ARRAY_SIZE(chip->saved_regs), return); 938 if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs)))
939 return;
937 for (; num_regs; num_regs--) 940 for (; num_regs; num_regs--)
938 snd_sbmixer_write(chip, *regs++, *val++); 941 snd_sbmixer_write(chip, *regs++, *val++);
939} 942}
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 @@
29#include <linux/io.h> 29#include <linux/io.h>
30#include <asm/dma.h> 30#include <asm/dma.h>
31#include <sound/core.h> 31#include <sound/core.h>
32#include <sound/ad1848.h> 32#include <sound/wss.h>
33#include <sound/opl3.h> 33#include <sound/opl3.h>
34#include <sound/mpu401.h> 34#include <sound/mpu401.h>
35#include <sound/control.h> 35#include <sound/control.h>
@@ -397,7 +397,7 @@ static int __devinit sc6000_init_board(char __iomem *vport, int irq, int dma,
397 return 0; 397 return 0;
398} 398}
399 399
400static int __devinit snd_sc6000_mixer(struct snd_ad1848 *chip) 400static int __devinit snd_sc6000_mixer(struct snd_wss *chip)
401{ 401{
402 struct snd_card *card = chip->card; 402 struct snd_card *card = chip->card;
403 struct snd_ctl_elem_id id1, id2; 403 struct snd_ctl_elem_id id1, id2;
@@ -483,7 +483,7 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
483 int xirq = irq[dev]; 483 int xirq = irq[dev];
484 int xdma = dma[dev]; 484 int xdma = dma[dev];
485 struct snd_card *card; 485 struct snd_card *card;
486 struct snd_ad1848 *chip; 486 struct snd_wss *chip;
487 struct snd_opl3 *opl3; 487 struct snd_opl3 *opl3;
488 char __iomem *vport; 488 char __iomem *vport;
489 char __iomem *vmss_port; 489 char __iomem *vmss_port;
@@ -548,21 +548,21 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
548 if (err < 0) 548 if (err < 0)
549 goto err_unmap2; 549 goto err_unmap2;
550 550
551 err = snd_ad1848_create(card, mss_port[dev] + 4, xirq, xdma, 551 err = snd_wss_create(card, mss_port[dev] + 4, -1, xirq, xdma, -1,
552 AD1848_HW_DETECT, &chip); 552 WSS_HW_DETECT, 0, &chip);
553 if (err < 0) 553 if (err < 0)
554 goto err_unmap2; 554 goto err_unmap2;
555 card->private_data = chip; 555 card->private_data = chip;
556 556
557 err = snd_ad1848_pcm(chip, 0, NULL); 557 err = snd_wss_pcm(chip, 0, NULL);
558 if (err < 0) { 558 if (err < 0) {
559 snd_printk(KERN_ERR PFX 559 snd_printk(KERN_ERR PFX
560 "error creating new ad1848 PCM device\n"); 560 "error creating new WSS PCM device\n");
561 goto err_unmap2; 561 goto err_unmap2;
562 } 562 }
563 err = snd_ad1848_mixer(chip); 563 err = snd_wss_mixer(chip);
564 if (err < 0) { 564 if (err < 0) {
565 snd_printk(KERN_ERR PFX "error creating new ad1848 mixer\n"); 565 snd_printk(KERN_ERR PFX "error creating new WSS mixer\n");
566 goto err_unmap2; 566 goto err_unmap2;
567 } 567 }
568 err = snd_sc6000_mixer(chip); 568 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 @@
31#include <asm/dma.h> 31#include <asm/dma.h>
32#include <sound/core.h> 32#include <sound/core.h>
33#include <sound/sb.h> 33#include <sound/sb.h>
34#include <sound/ad1848.h> 34#include <sound/wss.h>
35#include <sound/control.h> 35#include <sound/control.h>
36#define SNDRV_LEGACY_FIND_FREE_IRQ 36#define SNDRV_LEGACY_FIND_FREE_IRQ
37#define SNDRV_LEGACY_FIND_FREE_DMA 37#define SNDRV_LEGACY_FIND_FREE_DMA
@@ -175,12 +175,14 @@ static int __devinit snd_sgalaxy_detect(int dev, int irq, int dma)
175 return snd_sgalaxy_setup_wss(wssport[dev], irq, dma); 175 return snd_sgalaxy_setup_wss(wssport[dev], irq, dma);
176} 176}
177 177
178static struct ad1848_mix_elem snd_sgalaxy_controls[] = { 178static struct snd_kcontrol_new snd_sgalaxy_controls[] = {
179AD1848_DOUBLE("Aux Playback Switch", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7, 7, 1, 1), 179WSS_DOUBLE("Aux Playback Switch", 0,
180AD1848_DOUBLE("Aux Playback Volume", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0) 180 SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7, 7, 1, 1),
181WSS_DOUBLE("Aux Playback Volume", 0,
182 SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0)
181}; 183};
182 184
183static int __devinit snd_sgalaxy_mixer(struct snd_ad1848 *chip) 185static int __devinit snd_sgalaxy_mixer(struct snd_wss *chip)
184{ 186{
185 struct snd_card *card = chip->card; 187 struct snd_card *card = chip->card;
186 struct snd_ctl_elem_id id1, id2; 188 struct snd_ctl_elem_id id1, id2;
@@ -210,7 +212,9 @@ static int __devinit snd_sgalaxy_mixer(struct snd_ad1848 *chip)
210 return err; 212 return err;
211 /* build AUX2 input */ 213 /* build AUX2 input */
212 for (idx = 0; idx < ARRAY_SIZE(snd_sgalaxy_controls); idx++) { 214 for (idx = 0; idx < ARRAY_SIZE(snd_sgalaxy_controls); idx++) {
213 if ((err = snd_ad1848_add_ctl_elem(chip, &snd_sgalaxy_controls[idx])) < 0) 215 err = snd_ctl_add(card,
216 snd_ctl_new1(&snd_sgalaxy_controls[idx], chip));
217 if (err < 0)
214 return err; 218 return err;
215 } 219 }
216 return 0; 220 return 0;
@@ -237,7 +241,7 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev)
237 static int possible_dmas[] = {1, 3, 0, -1}; 241 static int possible_dmas[] = {1, 3, 0, -1};
238 int err, xirq, xdma1; 242 int err, xirq, xdma1;
239 struct snd_card *card; 243 struct snd_card *card;
240 struct snd_ad1848 *chip; 244 struct snd_wss *chip;
241 245
242 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); 246 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
243 if (card == NULL) 247 if (card == NULL)
@@ -263,18 +267,21 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev)
263 if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0) 267 if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0)
264 goto _err; 268 goto _err;
265 269
266 if ((err = snd_ad1848_create(card, wssport[dev] + 4, 270 err = snd_wss_create(card, wssport[dev] + 4, -1,
267 xirq, xdma1, 271 xirq, xdma1, -1,
268 AD1848_HW_DETECT, &chip)) < 0) 272 WSS_HW_DETECT, 0, &chip);
273 if (err < 0)
269 goto _err; 274 goto _err;
270 card->private_data = chip; 275 card->private_data = chip;
271 276
272 if ((err = snd_ad1848_pcm(chip, 0, NULL)) < 0) { 277 err = snd_wss_pcm(chip, 0, NULL);
273 snd_printdd(PFX "error creating new ad1848 PCM device\n"); 278 if (err < 0) {
279 snd_printdd(PFX "error creating new WSS PCM device\n");
274 goto _err; 280 goto _err;
275 } 281 }
276 if ((err = snd_ad1848_mixer(chip)) < 0) { 282 err = snd_wss_mixer(chip);
277 snd_printdd(PFX "error creating new ad1848 mixer\n"); 283 if (err < 0) {
284 snd_printdd(PFX "error creating new WSS mixer\n");
278 goto _err; 285 goto _err;
279 } 286 }
280 if ((err = snd_sgalaxy_mixer(chip)) < 0) { 287 if ((err = snd_sgalaxy_mixer(chip)) < 0) {
@@ -312,7 +319,7 @@ static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n,
312 pm_message_t state) 319 pm_message_t state)
313{ 320{
314 struct snd_card *card = dev_get_drvdata(pdev); 321 struct snd_card *card = dev_get_drvdata(pdev);
315 struct snd_ad1848 *chip = card->private_data; 322 struct snd_wss *chip = card->private_data;
316 323
317 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 324 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
318 chip->suspend(chip); 325 chip->suspend(chip);
@@ -322,11 +329,11 @@ static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n,
322static int snd_sgalaxy_resume(struct device *pdev, unsigned int n) 329static int snd_sgalaxy_resume(struct device *pdev, unsigned int n)
323{ 330{
324 struct snd_card *card = dev_get_drvdata(pdev); 331 struct snd_card *card = dev_get_drvdata(pdev);
325 struct snd_ad1848 *chip = card->private_data; 332 struct snd_wss *chip = card->private_data;
326 333
327 chip->resume(chip); 334 chip->resume(chip);
328 snd_ad1848_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]); 335 snd_wss_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]);
329 snd_ad1848_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]); 336 snd_wss_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]);
330 337
331 snd_power_change_state(card, SNDRV_CTL_POWER_D0); 338 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
332 return 0; 339 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 @@
31#include <asm/dma.h> 31#include <asm/dma.h>
32#include <sound/core.h> 32#include <sound/core.h>
33#include <sound/hwdep.h> 33#include <sound/hwdep.h>
34#include <sound/cs4231.h> 34#include <sound/wss.h>
35#include <sound/mpu401.h> 35#include <sound/mpu401.h>
36#include <sound/initval.h> 36#include <sound/initval.h>
37 37
@@ -147,7 +147,7 @@ struct soundscape {
147 enum card_type type; 147 enum card_type type;
148 struct resource *io_res; 148 struct resource *io_res;
149 struct resource *wss_res; 149 struct resource *wss_res;
150 struct snd_cs4231 *chip; 150 struct snd_wss *chip;
151 struct snd_mpu401 *mpu; 151 struct snd_mpu401 *mpu;
152 struct snd_hwdep *hw; 152 struct snd_hwdep *hw;
153 153
@@ -726,7 +726,7 @@ static int sscape_midi_info(struct snd_kcontrol *ctl,
726static int sscape_midi_get(struct snd_kcontrol *kctl, 726static int sscape_midi_get(struct snd_kcontrol *kctl,
727 struct snd_ctl_elem_value *uctl) 727 struct snd_ctl_elem_value *uctl)
728{ 728{
729 struct snd_cs4231 *chip = snd_kcontrol_chip(kctl); 729 struct snd_wss *chip = snd_kcontrol_chip(kctl);
730 struct snd_card *card = chip->card; 730 struct snd_card *card = chip->card;
731 register struct soundscape *s = get_card_soundscape(card); 731 register struct soundscape *s = get_card_soundscape(card);
732 unsigned long flags; 732 unsigned long flags;
@@ -746,7 +746,7 @@ static int sscape_midi_get(struct snd_kcontrol *kctl,
746static int sscape_midi_put(struct snd_kcontrol *kctl, 746static int sscape_midi_put(struct snd_kcontrol *kctl,
747 struct snd_ctl_elem_value *uctl) 747 struct snd_ctl_elem_value *uctl)
748{ 748{
749 struct snd_cs4231 *chip = snd_kcontrol_chip(kctl); 749 struct snd_wss *chip = snd_kcontrol_chip(kctl);
750 struct snd_card *card = chip->card; 750 struct snd_card *card = chip->card;
751 register struct soundscape *s = get_card_soundscape(card); 751 register struct soundscape *s = get_card_soundscape(card);
752 unsigned long flags; 752 unsigned long flags;
@@ -958,7 +958,9 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned l
958 * Override for the CS4231 playback format function. 958 * Override for the CS4231 playback format function.
959 * The AD1845 has much simpler format and rate selection. 959 * The AD1845 has much simpler format and rate selection.
960 */ 960 */
961static void ad1845_playback_format(struct snd_cs4231 * chip, struct snd_pcm_hw_params *params, unsigned char format) 961static void ad1845_playback_format(struct snd_wss *chip,
962 struct snd_pcm_hw_params *params,
963 unsigned char format)
962{ 964{
963 unsigned long flags; 965 unsigned long flags;
964 unsigned rate = params_rate(params); 966 unsigned rate = params_rate(params);
@@ -983,9 +985,9 @@ static void ad1845_playback_format(struct snd_cs4231 * chip, struct snd_pcm_hw_p
983 * NOTE: We seem to need to write to the MSB before the LSB 985 * NOTE: We seem to need to write to the MSB before the LSB
984 * to get the correct sample frequency. 986 * to get the correct sample frequency.
985 */ 987 */
986 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, (format & 0xf0)); 988 snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (format & 0xf0));
987 snd_cs4231_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8)); 989 snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
988 snd_cs4231_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate); 990 snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);
989 991
990 spin_unlock_irqrestore(&chip->reg_lock, flags); 992 spin_unlock_irqrestore(&chip->reg_lock, flags);
991} 993}
@@ -994,7 +996,9 @@ static void ad1845_playback_format(struct snd_cs4231 * chip, struct snd_pcm_hw_p
994 * Override for the CS4231 capture format function. 996 * Override for the CS4231 capture format function.
995 * The AD1845 has much simpler format and rate selection. 997 * The AD1845 has much simpler format and rate selection.
996 */ 998 */
997static void ad1845_capture_format(struct snd_cs4231 * chip, struct snd_pcm_hw_params *params, unsigned char format) 999static void ad1845_capture_format(struct snd_wss *chip,
1000 struct snd_pcm_hw_params *params,
1001 unsigned char format)
998{ 1002{
999 unsigned long flags; 1003 unsigned long flags;
1000 unsigned rate = params_rate(params); 1004 unsigned rate = params_rate(params);
@@ -1019,9 +1023,9 @@ static void ad1845_capture_format(struct snd_cs4231 * chip, struct snd_pcm_hw_pa
1019 * NOTE: We seem to need to write to the MSB before the LSB 1023 * NOTE: We seem to need to write to the MSB before the LSB
1020 * to get the correct sample frequency. 1024 * to get the correct sample frequency.
1021 */ 1025 */
1022 snd_cs4231_out(chip, CS4231_REC_FORMAT, (format & 0xf0)); 1026 snd_wss_out(chip, CS4231_REC_FORMAT, (format & 0xf0));
1023 snd_cs4231_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8)); 1027 snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
1024 snd_cs4231_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate); 1028 snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);
1025 1029
1026 spin_unlock_irqrestore(&chip->reg_lock, flags); 1030 spin_unlock_irqrestore(&chip->reg_lock, flags);
1027} 1031}
@@ -1036,7 +1040,7 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
1036 int irq, int dma1, int dma2) 1040 int irq, int dma1, int dma2)
1037{ 1041{
1038 register struct soundscape *sscape = get_card_soundscape(card); 1042 register struct soundscape *sscape = get_card_soundscape(card);
1039 struct snd_cs4231 *chip; 1043 struct snd_wss *chip;
1040 int err; 1044 int err;
1041 1045
1042 if (sscape->type == SSCAPE_VIVO) 1046 if (sscape->type == SSCAPE_VIVO)
@@ -1045,9 +1049,8 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
1045 if (dma1 == dma2) 1049 if (dma1 == dma2)
1046 dma2 = -1; 1050 dma2 = -1;
1047 1051
1048 err = snd_cs4231_create(card, 1052 err = snd_wss_create(card, port, -1, irq, dma1, dma2,
1049 port, -1, irq, dma1, dma2, 1053 WSS_HW_DETECT, WSS_HWSHARE_DMA1, &chip);
1050 CS4231_HW_DETECT, CS4231_HWSHARE_DMA1, &chip);
1051 if (!err) { 1054 if (!err) {
1052 unsigned long flags; 1055 unsigned long flags;
1053 struct snd_pcm *pcm; 1056 struct snd_pcm *pcm;
@@ -1063,11 +1066,11 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
1063 * 1066 *
1064#define AD1845_IFACE_CONFIG \ 1067#define AD1845_IFACE_CONFIG \
1065 (CS4231_AUTOCALIB | CS4231_RECORD_ENABLE | CS4231_PLAYBACK_ENABLE) 1068 (CS4231_AUTOCALIB | CS4231_RECORD_ENABLE | CS4231_PLAYBACK_ENABLE)
1066 snd_cs4231_mce_up(chip); 1069 snd_wss_mce_up(chip);
1067 spin_lock_irqsave(&chip->reg_lock, flags); 1070 spin_lock_irqsave(&chip->reg_lock, flags);
1068 snd_cs4231_out(chip, CS4231_IFACE_CTRL, AD1845_IFACE_CONFIG); 1071 snd_wss_out(chip, CS4231_IFACE_CTRL, AD1845_IFACE_CONFIG);
1069 spin_unlock_irqrestore(&chip->reg_lock, flags); 1072 spin_unlock_irqrestore(&chip->reg_lock, flags);
1070 snd_cs4231_mce_down(chip); 1073 snd_wss_mce_down(chip);
1071 */ 1074 */
1072 1075
1073 if (sscape->type != SSCAPE_VIVO) { 1076 if (sscape->type != SSCAPE_VIVO) {
@@ -1077,11 +1080,11 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
1077 * be 14.31818 MHz, because we must set this register 1080 * be 14.31818 MHz, because we must set this register
1078 * to get the playback to sound correct ... 1081 * to get the playback to sound correct ...
1079 */ 1082 */
1080 snd_cs4231_mce_up(chip); 1083 snd_wss_mce_up(chip);
1081 spin_lock_irqsave(&chip->reg_lock, flags); 1084 spin_lock_irqsave(&chip->reg_lock, flags);
1082 snd_cs4231_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20); 1085 snd_wss_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20);
1083 spin_unlock_irqrestore(&chip->reg_lock, flags); 1086 spin_unlock_irqrestore(&chip->reg_lock, flags);
1084 snd_cs4231_mce_down(chip); 1087 snd_wss_mce_down(chip);
1085 1088
1086 /* 1089 /*
1087 * More custom configuration: 1090 * More custom configuration:
@@ -1089,28 +1092,28 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
1089 * b) enable frequency selection (for capture/playback) 1092 * b) enable frequency selection (for capture/playback)
1090 */ 1093 */
1091 spin_lock_irqsave(&chip->reg_lock, flags); 1094 spin_lock_irqsave(&chip->reg_lock, flags);
1092 snd_cs4231_out(chip, CS4231_MISC_INFO, 1095 snd_wss_out(chip, CS4231_MISC_INFO,
1093 CS4231_MODE2 | 0x10); 1096 CS4231_MODE2 | 0x10);
1094 val = snd_cs4231_in(chip, AD1845_PWR_DOWN_CTRL); 1097 val = snd_wss_in(chip, AD1845_PWR_DOWN_CTRL);
1095 snd_cs4231_out(chip, AD1845_PWR_DOWN_CTRL, 1098 snd_wss_out(chip, AD1845_PWR_DOWN_CTRL,
1096 val | AD1845_FREQ_SEL_ENABLE); 1099 val | AD1845_FREQ_SEL_ENABLE);
1097 spin_unlock_irqrestore(&chip->reg_lock, flags); 1100 spin_unlock_irqrestore(&chip->reg_lock, flags);
1098 } 1101 }
1099 1102
1100 err = snd_cs4231_pcm(chip, 0, &pcm); 1103 err = snd_wss_pcm(chip, 0, &pcm);
1101 if (err < 0) { 1104 if (err < 0) {
1102 snd_printk(KERN_ERR "sscape: No PCM device " 1105 snd_printk(KERN_ERR "sscape: No PCM device "
1103 "for AD1845 chip\n"); 1106 "for AD1845 chip\n");
1104 goto _error; 1107 goto _error;
1105 } 1108 }
1106 1109
1107 err = snd_cs4231_mixer(chip); 1110 err = snd_wss_mixer(chip);
1108 if (err < 0) { 1111 if (err < 0) {
1109 snd_printk(KERN_ERR "sscape: No mixer device " 1112 snd_printk(KERN_ERR "sscape: No mixer device "
1110 "for AD1845 chip\n"); 1113 "for AD1845 chip\n");
1111 goto _error; 1114 goto _error;
1112 } 1115 }
1113 err = snd_cs4231_timer(chip, 0, NULL); 1116 err = snd_wss_timer(chip, 0, NULL);
1114 if (err < 0) { 1117 if (err < 0) {
1115 snd_printk(KERN_ERR "sscape: No timer device " 1118 snd_printk(KERN_ERR "sscape: No timer device "
1116 "for AD1845 chip\n"); 1119 "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 @@
1/* 1/*
2 * ALSA card-level driver for Turtle Beach Wavefront cards 2 * ALSA card-level driver for Turtle Beach Wavefront cards
3 * (Maui,Tropez,Tropez+) 3 * (Maui,Tropez,Tropez+)
4 * 4 *
5 * Copyright (c) 1997-1999 by Paul Barton-Davis <pbd@op.net> 5 * Copyright (c) 1997-1999 by Paul Barton-Davis <pbd@op.net>
6 * 6 *
@@ -29,6 +29,7 @@
29#include <sound/core.h> 29#include <sound/core.h>
30#include <sound/initval.h> 30#include <sound/initval.h>
31#include <sound/opl3.h> 31#include <sound/opl3.h>
32#include <sound/wss.h>
32#include <sound/snd_wavefront.h> 33#include <sound/snd_wavefront.h>
33 34
34MODULE_AUTHOR("Paul Barton-Davis <pbd@op.net>"); 35MODULE_AUTHOR("Paul Barton-Davis <pbd@op.net>");
@@ -319,8 +320,8 @@ snd_wavefront_new_midi (struct snd_card *card,
319 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_wavefront_midi_input); 320 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_wavefront_midi_input);
320 321
321 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | 322 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
322 SNDRV_RAWMIDI_INFO_INPUT | 323 SNDRV_RAWMIDI_INFO_INPUT |
323 SNDRV_RAWMIDI_INFO_DUPLEX; 324 SNDRV_RAWMIDI_INFO_DUPLEX;
324 325
325 return rmidi; 326 return rmidi;
326} 327}
@@ -363,7 +364,7 @@ static int __devinit
363snd_wavefront_probe (struct snd_card *card, int dev) 364snd_wavefront_probe (struct snd_card *card, int dev)
364{ 365{
365 snd_wavefront_card_t *acard = card->private_data; 366 snd_wavefront_card_t *acard = card->private_data;
366 struct snd_cs4231 *chip; 367 struct snd_wss *chip;
367 struct snd_hwdep *wavefront_synth; 368 struct snd_hwdep *wavefront_synth;
368 struct snd_rawmidi *ics2115_internal_rmidi = NULL; 369 struct snd_rawmidi *ics2115_internal_rmidi = NULL;
369 struct snd_rawmidi *ics2115_external_rmidi = NULL; 370 struct snd_rawmidi *ics2115_external_rmidi = NULL;
@@ -372,21 +373,20 @@ snd_wavefront_probe (struct snd_card *card, int dev)
372 373
373 /* --------- PCM --------------- */ 374 /* --------- PCM --------------- */
374 375
375 if ((err = snd_cs4231_create (card, 376 err = snd_wss_create(card, cs4232_pcm_port[dev], -1,
376 cs4232_pcm_port[dev], 377 cs4232_pcm_irq[dev], dma1[dev], dma2[dev],
377 -1, 378 WSS_HW_DETECT, 0, &chip);
378 cs4232_pcm_irq[dev], 379 if (err < 0) {
379 dma1[dev], 380 snd_printk(KERN_ERR "can't allocate WSS device\n");
380 dma2[dev],
381 CS4231_HW_DETECT, 0, &chip)) < 0) {
382 snd_printk (KERN_ERR "can't allocate CS4231 device\n");
383 return err; 381 return err;
384 } 382 }
385 383
386 if ((err = snd_cs4231_pcm (chip, 0, NULL)) < 0) 384 err = snd_wss_pcm(chip, 0, NULL);
385 if (err < 0)
387 return err; 386 return err;
388 387
389 if ((err = snd_cs4231_timer (chip, 0, NULL)) < 0) 388 err = snd_wss_timer(chip, 0, NULL);
389 if (err < 0)
390 return err; 390 return err;
391 391
392 /* ---------- OPL3 synth --------- */ 392 /* ---------- OPL3 synth --------- */
@@ -394,24 +394,24 @@ snd_wavefront_probe (struct snd_card *card, int dev)
394 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { 394 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
395 struct snd_opl3 *opl3; 395 struct snd_opl3 *opl3;
396 396
397 if ((err = snd_opl3_create(card, 397 err = snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2,
398 fm_port[dev], 398 OPL3_HW_OPL3_CS, 0, &opl3);
399 fm_port[dev] + 2, 399 if (err < 0) {
400 OPL3_HW_OPL3_CS,
401 0, &opl3)) < 0) {
402 snd_printk (KERN_ERR "can't allocate or detect OPL3 synth\n"); 400 snd_printk (KERN_ERR "can't allocate or detect OPL3 synth\n");
403 return err; 401 return err;
404 } 402 }
405 403
406 if ((err = snd_opl3_hwdep_new(opl3, hw_dev, 1, NULL)) < 0) 404 err = snd_opl3_hwdep_new(opl3, hw_dev, 1, NULL);
405 if (err < 0)
407 return err; 406 return err;
408 hw_dev++; 407 hw_dev++;
409 } 408 }
410 409
411 /* ------- ICS2115 Wavetable synth ------- */ 410 /* ------- ICS2115 Wavetable synth ------- */
412 411
413 if ((acard->wavefront.res_base = request_region(ics2115_port[dev], 16, 412 acard->wavefront.res_base = request_region(ics2115_port[dev], 16,
414 "ICS2115")) == NULL) { 413 "ICS2115");
414 if (acard->wavefront.res_base == NULL) {
415 snd_printk(KERN_ERR "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n", 415 snd_printk(KERN_ERR "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n",
416 ics2115_port[dev], ics2115_port[dev] + 16 - 1); 416 ics2115_port[dev], ics2115_port[dev] + 16 - 1);
417 return -EBUSY; 417 return -EBUSY;
@@ -425,7 +425,8 @@ snd_wavefront_probe (struct snd_card *card, int dev)
425 acard->wavefront.irq = ics2115_irq[dev]; 425 acard->wavefront.irq = ics2115_irq[dev];
426 acard->wavefront.base = ics2115_port[dev]; 426 acard->wavefront.base = ics2115_port[dev];
427 427
428 if ((wavefront_synth = snd_wavefront_new_synth (card, hw_dev, acard)) == NULL) { 428 wavefront_synth = snd_wavefront_new_synth(card, hw_dev, acard);
429 if (wavefront_synth == NULL) {
429 snd_printk (KERN_ERR "can't create WaveFront synth device\n"); 430 snd_printk (KERN_ERR "can't create WaveFront synth device\n");
430 return -ENOMEM; 431 return -ENOMEM;
431 } 432 }
@@ -436,7 +437,8 @@ snd_wavefront_probe (struct snd_card *card, int dev)
436 437
437 /* --------- Mixer ------------ */ 438 /* --------- Mixer ------------ */
438 439
439 if ((err = snd_cs4231_mixer(chip)) < 0) { 440 err = snd_wss_mixer(chip);
441 if (err < 0) {
440 snd_printk (KERN_ERR "can't allocate mixer device\n"); 442 snd_printk (KERN_ERR "can't allocate mixer device\n");
441 return err; 443 return err;
442 } 444 }
@@ -444,11 +446,11 @@ snd_wavefront_probe (struct snd_card *card, int dev)
444 /* -------- CS4232 MPU-401 interface -------- */ 446 /* -------- CS4232 MPU-401 interface -------- */
445 447
446 if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) { 448 if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) {
447 if ((err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232, 449 err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232,
448 cs4232_mpu_port[dev], 0, 450 cs4232_mpu_port[dev], 0,
449 cs4232_mpu_irq[dev], 451 cs4232_mpu_irq[dev], IRQF_DISABLED,
450 IRQF_DISABLED, 452 NULL);
451 NULL)) < 0) { 453 if (err < 0) {
452 snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n"); 454 snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n");
453 return err; 455 return err;
454 } 456 }
@@ -601,7 +603,7 @@ static struct isa_driver snd_wavefront_driver = {
601 603
602#ifdef CONFIG_PNP 604#ifdef CONFIG_PNP
603static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard, 605static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
604 const struct pnp_card_device_id *pid) 606 const struct pnp_card_device_id *pid)
605{ 607{
606 static int dev; 608 static int dev;
607 struct snd_card *card; 609 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,
180 unsigned short *pd; 180 unsigned short *pd;
181 int err = 0; 181 int err = 0;
182 182
183 snd_assert(sdev->card != NULL, return -ENODEV);
184
185 card = sdev->card; 183 card = sdev->card;
186 184 if (snd_BUG_ON(!card))
187 snd_assert(card->private_data != NULL, return -ENODEV); 185 return -ENODEV;
186 if (snd_BUG_ON(!card->private_data))
187 return -ENODEV;
188 188
189 acard = card->private_data; 189 acard = card->private_data;
190 dev = &acard->wavefront; 190 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
235 snd_wavefront_midi_t *midi; 235 snd_wavefront_midi_t *midi;
236 snd_wavefront_mpu_id mpu; 236 snd_wavefront_mpu_id mpu;
237 237
238 snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO); 238 if (snd_BUG_ON(!substream || !substream->rmidi))
239 snd_assert(substream->rmidi->private_data != NULL, return -EIO); 239 return -ENXIO;
240 if (snd_BUG_ON(!substream->rmidi->private_data))
241 return -ENXIO;
240 242
241 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 243 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
242 244
@@ -257,8 +259,10 @@ static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substrea
257 snd_wavefront_midi_t *midi; 259 snd_wavefront_midi_t *midi;
258 snd_wavefront_mpu_id mpu; 260 snd_wavefront_mpu_id mpu;
259 261
260 snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO); 262 if (snd_BUG_ON(!substream || !substream->rmidi))
261 snd_assert(substream->rmidi->private_data != NULL, return -EIO); 263 return -ENXIO;
264 if (snd_BUG_ON(!substream->rmidi->private_data))
265 return -ENXIO;
262 266
263 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 267 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
264 268
@@ -279,8 +283,10 @@ static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substrea
279 snd_wavefront_midi_t *midi; 283 snd_wavefront_midi_t *midi;
280 snd_wavefront_mpu_id mpu; 284 snd_wavefront_mpu_id mpu;
281 285
282 snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO); 286 if (snd_BUG_ON(!substream || !substream->rmidi))
283 snd_assert(substream->rmidi->private_data != NULL, return -EIO); 287 return -ENXIO;
288 if (snd_BUG_ON(!substream->rmidi->private_data))
289 return -ENXIO;
284 290
285 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 291 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
286 292
@@ -300,8 +306,10 @@ static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substre
300 snd_wavefront_midi_t *midi; 306 snd_wavefront_midi_t *midi;
301 snd_wavefront_mpu_id mpu; 307 snd_wavefront_mpu_id mpu;
302 308
303 snd_assert(substream != NULL && substream->rmidi != NULL, return -EIO); 309 if (snd_BUG_ON(!substream || !substream->rmidi))
304 snd_assert(substream->rmidi->private_data != NULL, return -EIO); 310 return -ENXIO;
311 if (snd_BUG_ON(!substream->rmidi->private_data))
312 return -ENXIO;
305 313
306 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); 314 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
307 315
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,
1648 1648
1649 card = (struct snd_card *) hw->card; 1649 card = (struct snd_card *) hw->card;
1650 1650
1651 snd_assert(card != NULL, return -ENODEV); 1651 if (snd_BUG_ON(!card))
1652 1652 return -ENODEV;
1653 snd_assert(card->private_data != NULL, return -ENODEV); 1653 if (snd_BUG_ON(!card->private_data))
1654 return -ENODEV;
1654 1655
1655 acard = card->private_data; 1656 acard = card->private_data;
1656 dev = &acard->wavefront; 1657 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 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2008 by Jaroslav Kysela <perex@perex.cz>
4#
5
6snd-wss-lib-objs := wss_lib.o
7
8# Toplevel Module Dependency
9obj-$(CONFIG_SND_WSS_LIB) += snd-wss-lib.o
10
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 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
3 * Routines for control of CS4231(A)/CS4232/InterWave & compatible chips
4 *
5 * Bugs:
6 * - sometimes record brokes playback with WSS portion of
7 * Yamaha OPL3-SA3 chip
8 * - CS4231 (GUS MAX) - still trouble with occasional noises
9 * - broken initialization?
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27#include <linux/delay.h>
28#include <linux/pm.h>
29#include <linux/init.h>
30#include <linux/interrupt.h>
31#include <linux/slab.h>
32#include <linux/ioport.h>
33#include <sound/core.h>
34#include <sound/wss.h>
35#include <sound/pcm_params.h>
36#include <sound/tlv.h>
37
38#include <asm/io.h>
39#include <asm/dma.h>
40#include <asm/irq.h>
41
42MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
43MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips");
44MODULE_LICENSE("GPL");
45
46#if 0
47#define SNDRV_DEBUG_MCE
48#endif
49
50/*
51 * Some variables
52 */
53
54static unsigned char freq_bits[14] = {
55 /* 5510 */ 0x00 | CS4231_XTAL2,
56 /* 6620 */ 0x0E | CS4231_XTAL2,
57 /* 8000 */ 0x00 | CS4231_XTAL1,
58 /* 9600 */ 0x0E | CS4231_XTAL1,
59 /* 11025 */ 0x02 | CS4231_XTAL2,
60 /* 16000 */ 0x02 | CS4231_XTAL1,
61 /* 18900 */ 0x04 | CS4231_XTAL2,
62 /* 22050 */ 0x06 | CS4231_XTAL2,
63 /* 27042 */ 0x04 | CS4231_XTAL1,
64 /* 32000 */ 0x06 | CS4231_XTAL1,
65 /* 33075 */ 0x0C | CS4231_XTAL2,
66 /* 37800 */ 0x08 | CS4231_XTAL2,
67 /* 44100 */ 0x0A | CS4231_XTAL2,
68 /* 48000 */ 0x0C | CS4231_XTAL1
69};
70
71static unsigned int rates[14] = {
72 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,
73 27042, 32000, 33075, 37800, 44100, 48000
74};
75
76static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
77 .count = ARRAY_SIZE(rates),
78 .list = rates,
79 .mask = 0,
80};
81
82static int snd_wss_xrate(struct snd_pcm_runtime *runtime)
83{
84 return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
85 &hw_constraints_rates);
86}
87
88static unsigned char snd_wss_original_image[32] =
89{
90 0x00, /* 00/00 - lic */
91 0x00, /* 01/01 - ric */
92 0x9f, /* 02/02 - la1ic */
93 0x9f, /* 03/03 - ra1ic */
94 0x9f, /* 04/04 - la2ic */
95 0x9f, /* 05/05 - ra2ic */
96 0xbf, /* 06/06 - loc */
97 0xbf, /* 07/07 - roc */
98 0x20, /* 08/08 - pdfr */
99 CS4231_AUTOCALIB, /* 09/09 - ic */
100 0x00, /* 0a/10 - pc */
101 0x00, /* 0b/11 - ti */
102 CS4231_MODE2, /* 0c/12 - mi */
103 0xfc, /* 0d/13 - lbc */
104 0x00, /* 0e/14 - pbru */
105 0x00, /* 0f/15 - pbrl */
106 0x80, /* 10/16 - afei */
107 0x01, /* 11/17 - afeii */
108 0x9f, /* 12/18 - llic */
109 0x9f, /* 13/19 - rlic */
110 0x00, /* 14/20 - tlb */
111 0x00, /* 15/21 - thb */
112 0x00, /* 16/22 - la3mic/reserved */
113 0x00, /* 17/23 - ra3mic/reserved */
114 0x00, /* 18/24 - afs */
115 0x00, /* 19/25 - lamoc/version */
116 0xcf, /* 1a/26 - mioc */
117 0x00, /* 1b/27 - ramoc/reserved */
118 0x20, /* 1c/28 - cdfr */
119 0x00, /* 1d/29 - res4 */
120 0x00, /* 1e/30 - cbru */
121 0x00, /* 1f/31 - cbrl */
122};
123
124static unsigned char snd_opti93x_original_image[32] =
125{
126 0x00, /* 00/00 - l_mixout_outctrl */
127 0x00, /* 01/01 - r_mixout_outctrl */
128 0x88, /* 02/02 - l_cd_inctrl */
129 0x88, /* 03/03 - r_cd_inctrl */
130 0x88, /* 04/04 - l_a1/fm_inctrl */
131 0x88, /* 05/05 - r_a1/fm_inctrl */
132 0x80, /* 06/06 - l_dac_inctrl */
133 0x80, /* 07/07 - r_dac_inctrl */
134 0x00, /* 08/08 - ply_dataform_reg */
135 0x00, /* 09/09 - if_conf */
136 0x00, /* 0a/10 - pin_ctrl */
137 0x00, /* 0b/11 - err_init_reg */
138 0x0a, /* 0c/12 - id_reg */
139 0x00, /* 0d/13 - reserved */
140 0x00, /* 0e/14 - ply_upcount_reg */
141 0x00, /* 0f/15 - ply_lowcount_reg */
142 0x88, /* 10/16 - reserved/l_a1_inctrl */
143 0x88, /* 11/17 - reserved/r_a1_inctrl */
144 0x88, /* 12/18 - l_line_inctrl */
145 0x88, /* 13/19 - r_line_inctrl */
146 0x88, /* 14/20 - l_mic_inctrl */
147 0x88, /* 15/21 - r_mic_inctrl */
148 0x80, /* 16/22 - l_out_outctrl */
149 0x80, /* 17/23 - r_out_outctrl */
150 0x00, /* 18/24 - reserved */
151 0x00, /* 19/25 - reserved */
152 0x00, /* 1a/26 - reserved */
153 0x00, /* 1b/27 - reserved */
154 0x00, /* 1c/28 - cap_dataform_reg */
155 0x00, /* 1d/29 - reserved */
156 0x00, /* 1e/30 - cap_upcount_reg */
157 0x00 /* 1f/31 - cap_lowcount_reg */
158};
159
160/*
161 * Basic I/O functions
162 */
163
164static inline void wss_outb(struct snd_wss *chip, u8 offset, u8 val)
165{
166 outb(val, chip->port + offset);
167}
168
169static inline u8 wss_inb(struct snd_wss *chip, u8 offset)
170{
171 return inb(chip->port + offset);
172}
173
174static void snd_wss_wait(struct snd_wss *chip)
175{
176 int timeout;
177
178 for (timeout = 250;
179 timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
180 timeout--)
181 udelay(100);
182}
183
184static void snd_wss_outm(struct snd_wss *chip, unsigned char reg,
185 unsigned char mask, unsigned char value)
186{
187 unsigned char tmp = (chip->image[reg] & mask) | value;
188
189 snd_wss_wait(chip);
190#ifdef CONFIG_SND_DEBUG
191 if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
192 snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
193#endif
194 chip->image[reg] = tmp;
195 if (!chip->calibrate_mute) {
196 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
197 wmb();
198 wss_outb(chip, CS4231P(REG), tmp);
199 mb();
200 }
201}
202
203static void snd_wss_dout(struct snd_wss *chip, unsigned char reg,
204 unsigned char value)
205{
206 int timeout;
207
208 for (timeout = 250;
209 timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
210 timeout--)
211 udelay(10);
212 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
213 wss_outb(chip, CS4231P(REG), value);
214 mb();
215}
216
217void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char value)
218{
219 snd_wss_wait(chip);
220#ifdef CONFIG_SND_DEBUG
221 if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
222 snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
223#endif
224 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
225 wss_outb(chip, CS4231P(REG), value);
226 chip->image[reg] = value;
227 mb();
228 snd_printdd("codec out - reg 0x%x = 0x%x\n",
229 chip->mce_bit | reg, value);
230}
231EXPORT_SYMBOL(snd_wss_out);
232
233unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg)
234{
235 snd_wss_wait(chip);
236#ifdef CONFIG_SND_DEBUG
237 if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
238 snd_printk("in: auto calibration time out - reg = 0x%x\n", reg);
239#endif
240 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
241 mb();
242 return wss_inb(chip, CS4231P(REG));
243}
244EXPORT_SYMBOL(snd_wss_in);
245
246void snd_cs4236_ext_out(struct snd_wss *chip, unsigned char reg,
247 unsigned char val)
248{
249 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
250 wss_outb(chip, CS4231P(REG),
251 reg | (chip->image[CS4236_EXT_REG] & 0x01));
252 wss_outb(chip, CS4231P(REG), val);
253 chip->eimage[CS4236_REG(reg)] = val;
254#if 0
255 printk("ext out : reg = 0x%x, val = 0x%x\n", reg, val);
256#endif
257}
258EXPORT_SYMBOL(snd_cs4236_ext_out);
259
260unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg)
261{
262 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
263 wss_outb(chip, CS4231P(REG),
264 reg | (chip->image[CS4236_EXT_REG] & 0x01));
265#if 1
266 return wss_inb(chip, CS4231P(REG));
267#else
268 {
269 unsigned char res;
270 res = wss_inb(chip, CS4231P(REG));
271 printk("ext in : reg = 0x%x, val = 0x%x\n", reg, res);
272 return res;
273 }
274#endif
275}
276EXPORT_SYMBOL(snd_cs4236_ext_in);
277
278#if 0
279
280static void snd_wss_debug(struct snd_wss *chip)
281{
282 printk(KERN_DEBUG
283 "CS4231 REGS: INDEX = 0x%02x "
284 " STATUS = 0x%02x\n",
285 wss_inb(chip, CS4231P(REGSEL)),
286 wss_inb(chip, CS4231P(STATUS)));
287 printk(KERN_DEBUG
288 " 0x00: left input = 0x%02x "
289 " 0x10: alt 1 (CFIG 2) = 0x%02x\n",
290 snd_wss_in(chip, 0x00),
291 snd_wss_in(chip, 0x10));
292 printk(KERN_DEBUG
293 " 0x01: right input = 0x%02x "
294 " 0x11: alt 2 (CFIG 3) = 0x%02x\n",
295 snd_wss_in(chip, 0x01),
296 snd_wss_in(chip, 0x11));
297 printk(KERN_DEBUG
298 " 0x02: GF1 left input = 0x%02x "
299 " 0x12: left line in = 0x%02x\n",
300 snd_wss_in(chip, 0x02),
301 snd_wss_in(chip, 0x12));
302 printk(KERN_DEBUG
303 " 0x03: GF1 right input = 0x%02x "
304 " 0x13: right line in = 0x%02x\n",
305 snd_wss_in(chip, 0x03),
306 snd_wss_in(chip, 0x13));
307 printk(KERN_DEBUG
308 " 0x04: CD left input = 0x%02x "
309 " 0x14: timer low = 0x%02x\n",
310 snd_wss_in(chip, 0x04),
311 snd_wss_in(chip, 0x14));
312 printk(KERN_DEBUG
313 " 0x05: CD right input = 0x%02x "
314 " 0x15: timer high = 0x%02x\n",
315 snd_wss_in(chip, 0x05),
316 snd_wss_in(chip, 0x15));
317 printk(KERN_DEBUG
318 " 0x06: left output = 0x%02x "
319 " 0x16: left MIC (PnP) = 0x%02x\n",
320 snd_wss_in(chip, 0x06),
321 snd_wss_in(chip, 0x16));
322 printk(KERN_DEBUG
323 " 0x07: right output = 0x%02x "
324 " 0x17: right MIC (PnP) = 0x%02x\n",
325 snd_wss_in(chip, 0x07),
326 snd_wss_in(chip, 0x17));
327 printk(KERN_DEBUG
328 " 0x08: playback format = 0x%02x "
329 " 0x18: IRQ status = 0x%02x\n",
330 snd_wss_in(chip, 0x08),
331 snd_wss_in(chip, 0x18));
332 printk(KERN_DEBUG
333 " 0x09: iface (CFIG 1) = 0x%02x "
334 " 0x19: left line out = 0x%02x\n",
335 snd_wss_in(chip, 0x09),
336 snd_wss_in(chip, 0x19));
337 printk(KERN_DEBUG
338 " 0x0a: pin control = 0x%02x "
339 " 0x1a: mono control = 0x%02x\n",
340 snd_wss_in(chip, 0x0a),
341 snd_wss_in(chip, 0x1a));
342 printk(KERN_DEBUG
343 " 0x0b: init & status = 0x%02x "
344 " 0x1b: right line out = 0x%02x\n",
345 snd_wss_in(chip, 0x0b),
346 snd_wss_in(chip, 0x1b));
347 printk(KERN_DEBUG
348 " 0x0c: revision & mode = 0x%02x "
349 " 0x1c: record format = 0x%02x\n",
350 snd_wss_in(chip, 0x0c),
351 snd_wss_in(chip, 0x1c));
352 printk(KERN_DEBUG
353 " 0x0d: loopback = 0x%02x "
354 " 0x1d: var freq (PnP) = 0x%02x\n",
355 snd_wss_in(chip, 0x0d),
356 snd_wss_in(chip, 0x1d));
357 printk(KERN_DEBUG
358 " 0x0e: ply upr count = 0x%02x "
359 " 0x1e: ply lwr count = 0x%02x\n",
360 snd_wss_in(chip, 0x0e),
361 snd_wss_in(chip, 0x1e));
362 printk(KERN_DEBUG
363 " 0x0f: rec upr count = 0x%02x "
364 " 0x1f: rec lwr count = 0x%02x\n",
365 snd_wss_in(chip, 0x0f),
366 snd_wss_in(chip, 0x1f));
367}
368
369#endif
370
371/*
372 * CS4231 detection / MCE routines
373 */
374
375static void snd_wss_busy_wait(struct snd_wss *chip)
376{
377 int timeout;
378
379 /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
380 for (timeout = 5; timeout > 0; timeout--)
381 wss_inb(chip, CS4231P(REGSEL));
382 /* end of cleanup sequence */
383 for (timeout = 25000;
384 timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
385 timeout--)
386 udelay(10);
387}
388
389void snd_wss_mce_up(struct snd_wss *chip)
390{
391 unsigned long flags;
392 int timeout;
393
394 snd_wss_wait(chip);
395#ifdef CONFIG_SND_DEBUG
396 if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
397 snd_printk("mce_up - auto calibration time out (0)\n");
398#endif
399 spin_lock_irqsave(&chip->reg_lock, flags);
400 chip->mce_bit |= CS4231_MCE;
401 timeout = wss_inb(chip, CS4231P(REGSEL));
402 if (timeout == 0x80)
403 snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
404 if (!(timeout & CS4231_MCE))
405 wss_outb(chip, CS4231P(REGSEL),
406 chip->mce_bit | (timeout & 0x1f));
407 spin_unlock_irqrestore(&chip->reg_lock, flags);
408}
409EXPORT_SYMBOL(snd_wss_mce_up);
410
411void snd_wss_mce_down(struct snd_wss *chip)
412{
413 unsigned long flags;
414 unsigned long end_time;
415 int timeout;
416 int hw_mask = WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK | WSS_HW_AD1848;
417
418 snd_wss_busy_wait(chip);
419
420#ifdef CONFIG_SND_DEBUG
421 if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
422 snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL));
423#endif
424 spin_lock_irqsave(&chip->reg_lock, flags);
425 chip->mce_bit &= ~CS4231_MCE;
426 timeout = wss_inb(chip, CS4231P(REGSEL));
427 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
428 spin_unlock_irqrestore(&chip->reg_lock, flags);
429 if (timeout == 0x80)
430 snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
431 if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask))
432 return;
433
434 /*
435 * Wait for (possible -- during init auto-calibration may not be set)
436 * calibration process to start. Needs upto 5 sample periods on AD1848
437 * which at the slowest possible rate of 5.5125 kHz means 907 us.
438 */
439 msleep(1);
440
441 snd_printdd("(1) jiffies = %lu\n", jiffies);
442
443 /* check condition up to 250 ms */
444 end_time = jiffies + msecs_to_jiffies(250);
445 while (snd_wss_in(chip, CS4231_TEST_INIT) &
446 CS4231_CALIB_IN_PROGRESS) {
447
448 if (time_after(jiffies, end_time)) {
449 snd_printk(KERN_ERR "mce_down - "
450 "auto calibration time out (2)\n");
451 return;
452 }
453 msleep(1);
454 }
455
456 snd_printdd("(2) jiffies = %lu\n", jiffies);
457
458 /* check condition up to 100 ms */
459 end_time = jiffies + msecs_to_jiffies(100);
460 while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
461 if (time_after(jiffies, end_time)) {
462 snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
463 return;
464 }
465 msleep(1);
466 }
467
468 snd_printdd("(3) jiffies = %lu\n", jiffies);
469 snd_printd("mce_down - exit = 0x%x\n", wss_inb(chip, CS4231P(REGSEL)));
470}
471EXPORT_SYMBOL(snd_wss_mce_down);
472
473static unsigned int snd_wss_get_count(unsigned char format, unsigned int size)
474{
475 switch (format & 0xe0) {
476 case CS4231_LINEAR_16:
477 case CS4231_LINEAR_16_BIG:
478 size >>= 1;
479 break;
480 case CS4231_ADPCM_16:
481 return size >> 2;
482 }
483 if (format & CS4231_STEREO)
484 size >>= 1;
485 return size;
486}
487
488static int snd_wss_trigger(struct snd_pcm_substream *substream,
489 int cmd)
490{
491 struct snd_wss *chip = snd_pcm_substream_chip(substream);
492 int result = 0;
493 unsigned int what;
494 struct snd_pcm_substream *s;
495 int do_start;
496
497 switch (cmd) {
498 case SNDRV_PCM_TRIGGER_START:
499 case SNDRV_PCM_TRIGGER_RESUME:
500 do_start = 1; break;
501 case SNDRV_PCM_TRIGGER_STOP:
502 case SNDRV_PCM_TRIGGER_SUSPEND:
503 do_start = 0; break;
504 default:
505 return -EINVAL;
506 }
507
508 what = 0;
509 snd_pcm_group_for_each_entry(s, substream) {
510 if (s == chip->playback_substream) {
511 what |= CS4231_PLAYBACK_ENABLE;
512 snd_pcm_trigger_done(s, substream);
513 } else if (s == chip->capture_substream) {
514 what |= CS4231_RECORD_ENABLE;
515 snd_pcm_trigger_done(s, substream);
516 }
517 }
518 spin_lock(&chip->reg_lock);
519 if (do_start) {
520 chip->image[CS4231_IFACE_CTRL] |= what;
521 if (chip->trigger)
522 chip->trigger(chip, what, 1);
523 } else {
524 chip->image[CS4231_IFACE_CTRL] &= ~what;
525 if (chip->trigger)
526 chip->trigger(chip, what, 0);
527 }
528 snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
529 spin_unlock(&chip->reg_lock);
530#if 0
531 snd_wss_debug(chip);
532#endif
533 return result;
534}
535
536/*
537 * CODEC I/O
538 */
539
540static unsigned char snd_wss_get_rate(unsigned int rate)
541{
542 int i;
543
544 for (i = 0; i < ARRAY_SIZE(rates); i++)
545 if (rate == rates[i])
546 return freq_bits[i];
547 // snd_BUG();
548 return freq_bits[ARRAY_SIZE(rates) - 1];
549}
550
551static unsigned char snd_wss_get_format(struct snd_wss *chip,
552 int format,
553 int channels)
554{
555 unsigned char rformat;
556
557 rformat = CS4231_LINEAR_8;
558 switch (format) {
559 case SNDRV_PCM_FORMAT_MU_LAW: rformat = CS4231_ULAW_8; break;
560 case SNDRV_PCM_FORMAT_A_LAW: rformat = CS4231_ALAW_8; break;
561 case SNDRV_PCM_FORMAT_S16_LE: rformat = CS4231_LINEAR_16; break;
562 case SNDRV_PCM_FORMAT_S16_BE: rformat = CS4231_LINEAR_16_BIG; break;
563 case SNDRV_PCM_FORMAT_IMA_ADPCM: rformat = CS4231_ADPCM_16; break;
564 }
565 if (channels > 1)
566 rformat |= CS4231_STEREO;
567#if 0
568 snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
569#endif
570 return rformat;
571}
572
573static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute)
574{
575 unsigned long flags;
576
577 mute = mute ? 0x80 : 0;
578 spin_lock_irqsave(&chip->reg_lock, flags);
579 if (chip->calibrate_mute == mute) {
580 spin_unlock_irqrestore(&chip->reg_lock, flags);
581 return;
582 }
583 if (!mute) {
584 snd_wss_dout(chip, CS4231_LEFT_INPUT,
585 chip->image[CS4231_LEFT_INPUT]);
586 snd_wss_dout(chip, CS4231_RIGHT_INPUT,
587 chip->image[CS4231_RIGHT_INPUT]);
588 snd_wss_dout(chip, CS4231_LOOPBACK,
589 chip->image[CS4231_LOOPBACK]);
590 }
591 snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT,
592 mute | chip->image[CS4231_AUX1_LEFT_INPUT]);
593 snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT,
594 mute | chip->image[CS4231_AUX1_RIGHT_INPUT]);
595 snd_wss_dout(chip, CS4231_AUX2_LEFT_INPUT,
596 mute | chip->image[CS4231_AUX2_LEFT_INPUT]);
597 snd_wss_dout(chip, CS4231_AUX2_RIGHT_INPUT,
598 mute | chip->image[CS4231_AUX2_RIGHT_INPUT]);
599 snd_wss_dout(chip, CS4231_LEFT_OUTPUT,
600 mute | chip->image[CS4231_LEFT_OUTPUT]);
601 snd_wss_dout(chip, CS4231_RIGHT_OUTPUT,
602 mute | chip->image[CS4231_RIGHT_OUTPUT]);
603 if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
604 snd_wss_dout(chip, CS4231_LEFT_LINE_IN,
605 mute | chip->image[CS4231_LEFT_LINE_IN]);
606 snd_wss_dout(chip, CS4231_RIGHT_LINE_IN,
607 mute | chip->image[CS4231_RIGHT_LINE_IN]);
608 snd_wss_dout(chip, CS4231_MONO_CTRL,
609 mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);
610 }
611 if (chip->hardware == WSS_HW_INTERWAVE) {
612 snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT,
613 mute | chip->image[CS4231_LEFT_MIC_INPUT]);
614 snd_wss_dout(chip, CS4231_RIGHT_MIC_INPUT,
615 mute | chip->image[CS4231_RIGHT_MIC_INPUT]);
616 snd_wss_dout(chip, CS4231_LINE_LEFT_OUTPUT,
617 mute | chip->image[CS4231_LINE_LEFT_OUTPUT]);
618 snd_wss_dout(chip, CS4231_LINE_RIGHT_OUTPUT,
619 mute | chip->image[CS4231_LINE_RIGHT_OUTPUT]);
620 }
621 chip->calibrate_mute = mute;
622 spin_unlock_irqrestore(&chip->reg_lock, flags);
623}
624
625static void snd_wss_playback_format(struct snd_wss *chip,
626 struct snd_pcm_hw_params *params,
627 unsigned char pdfr)
628{
629 unsigned long flags;
630 int full_calib = 1;
631
632 mutex_lock(&chip->mce_mutex);
633 snd_wss_calibrate_mute(chip, 1);
634 if (chip->hardware == WSS_HW_CS4231A ||
635 (chip->hardware & WSS_HW_CS4232_MASK)) {
636 spin_lock_irqsave(&chip->reg_lock, flags);
637 if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (pdfr & 0x0f)) { /* rate is same? */
638 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
639 chip->image[CS4231_ALT_FEATURE_1] | 0x10);
640 chip->image[CS4231_PLAYBK_FORMAT] = pdfr;
641 snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
642 chip->image[CS4231_PLAYBK_FORMAT]);
643 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
644 chip->image[CS4231_ALT_FEATURE_1] &= ~0x10);
645 udelay(100); /* Fixes audible clicks at least on GUS MAX */
646 full_calib = 0;
647 }
648 spin_unlock_irqrestore(&chip->reg_lock, flags);
649 }
650 if (full_calib) {
651 snd_wss_mce_up(chip);
652 spin_lock_irqsave(&chip->reg_lock, flags);
653 if (chip->hardware != WSS_HW_INTERWAVE && !chip->single_dma) {
654 if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)
655 pdfr = (pdfr & 0xf0) |
656 (chip->image[CS4231_REC_FORMAT] & 0x0f);
657 } else {
658 chip->image[CS4231_PLAYBK_FORMAT] = pdfr;
659 }
660 snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr);
661 spin_unlock_irqrestore(&chip->reg_lock, flags);
662 if (chip->hardware == WSS_HW_OPL3SA2)
663 udelay(100); /* this seems to help */
664 snd_wss_mce_down(chip);
665 }
666 snd_wss_calibrate_mute(chip, 0);
667 mutex_unlock(&chip->mce_mutex);
668}
669
670static void snd_wss_capture_format(struct snd_wss *chip,
671 struct snd_pcm_hw_params *params,
672 unsigned char cdfr)
673{
674 unsigned long flags;
675 int full_calib = 1;
676
677 mutex_lock(&chip->mce_mutex);
678 snd_wss_calibrate_mute(chip, 1);
679 if (chip->hardware == WSS_HW_CS4231A ||
680 (chip->hardware & WSS_HW_CS4232_MASK)) {
681 spin_lock_irqsave(&chip->reg_lock, flags);
682 if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (cdfr & 0x0f) || /* rate is same? */
683 (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
684 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
685 chip->image[CS4231_ALT_FEATURE_1] | 0x20);
686 snd_wss_out(chip, CS4231_REC_FORMAT,
687 chip->image[CS4231_REC_FORMAT] = cdfr);
688 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
689 chip->image[CS4231_ALT_FEATURE_1] &= ~0x20);
690 full_calib = 0;
691 }
692 spin_unlock_irqrestore(&chip->reg_lock, flags);
693 }
694 if (full_calib) {
695 snd_wss_mce_up(chip);
696 spin_lock_irqsave(&chip->reg_lock, flags);
697 if (chip->hardware != WSS_HW_INTERWAVE &&
698 !(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
699 if (chip->single_dma)
700 snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr);
701 else
702 snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
703 (chip->image[CS4231_PLAYBK_FORMAT] & 0xf0) |
704 (cdfr & 0x0f));
705 spin_unlock_irqrestore(&chip->reg_lock, flags);
706 snd_wss_mce_down(chip);
707 snd_wss_mce_up(chip);
708 spin_lock_irqsave(&chip->reg_lock, flags);
709 }
710 if (chip->hardware & WSS_HW_AD1848_MASK)
711 snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr);
712 else
713 snd_wss_out(chip, CS4231_REC_FORMAT, cdfr);
714 spin_unlock_irqrestore(&chip->reg_lock, flags);
715 snd_wss_mce_down(chip);
716 }
717 snd_wss_calibrate_mute(chip, 0);
718 mutex_unlock(&chip->mce_mutex);
719}
720
721/*
722 * Timer interface
723 */
724
725static unsigned long snd_wss_timer_resolution(struct snd_timer *timer)
726{
727 struct snd_wss *chip = snd_timer_chip(timer);
728 if (chip->hardware & WSS_HW_CS4236B_MASK)
729 return 14467;
730 else
731 return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920;
732}
733
734static int snd_wss_timer_start(struct snd_timer *timer)
735{
736 unsigned long flags;
737 unsigned int ticks;
738 struct snd_wss *chip = snd_timer_chip(timer);
739 spin_lock_irqsave(&chip->reg_lock, flags);
740 ticks = timer->sticks;
741 if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 ||
742 (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] ||
743 (unsigned char)ticks != chip->image[CS4231_TIMER_LOW]) {
744 chip->image[CS4231_TIMER_HIGH] = (unsigned char) (ticks >> 8);
745 snd_wss_out(chip, CS4231_TIMER_HIGH,
746 chip->image[CS4231_TIMER_HIGH]);
747 chip->image[CS4231_TIMER_LOW] = (unsigned char) ticks;
748 snd_wss_out(chip, CS4231_TIMER_LOW,
749 chip->image[CS4231_TIMER_LOW]);
750 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
751 chip->image[CS4231_ALT_FEATURE_1] |
752 CS4231_TIMER_ENABLE);
753 }
754 spin_unlock_irqrestore(&chip->reg_lock, flags);
755 return 0;
756}
757
758static int snd_wss_timer_stop(struct snd_timer *timer)
759{
760 unsigned long flags;
761 struct snd_wss *chip = snd_timer_chip(timer);
762 spin_lock_irqsave(&chip->reg_lock, flags);
763 chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE;
764 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
765 chip->image[CS4231_ALT_FEATURE_1]);
766 spin_unlock_irqrestore(&chip->reg_lock, flags);
767 return 0;
768}
769
770static void snd_wss_init(struct snd_wss *chip)
771{
772 unsigned long flags;
773
774 snd_wss_mce_down(chip);
775
776#ifdef SNDRV_DEBUG_MCE
777 snd_printk("init: (1)\n");
778#endif
779 snd_wss_mce_up(chip);
780 spin_lock_irqsave(&chip->reg_lock, flags);
781 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |
782 CS4231_PLAYBACK_PIO |
783 CS4231_RECORD_ENABLE |
784 CS4231_RECORD_PIO |
785 CS4231_CALIB_MODE);
786 chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB;
787 snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
788 spin_unlock_irqrestore(&chip->reg_lock, flags);
789 snd_wss_mce_down(chip);
790
791#ifdef SNDRV_DEBUG_MCE
792 snd_printk("init: (2)\n");
793#endif
794
795 snd_wss_mce_up(chip);
796 spin_lock_irqsave(&chip->reg_lock, flags);
797 snd_wss_out(chip,
798 CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]);
799 spin_unlock_irqrestore(&chip->reg_lock, flags);
800 snd_wss_mce_down(chip);
801
802#ifdef SNDRV_DEBUG_MCE
803 snd_printk("init: (3) - afei = 0x%x\n",
804 chip->image[CS4231_ALT_FEATURE_1]);
805#endif
806
807 spin_lock_irqsave(&chip->reg_lock, flags);
808 snd_wss_out(chip, CS4231_ALT_FEATURE_2,
809 chip->image[CS4231_ALT_FEATURE_2]);
810 spin_unlock_irqrestore(&chip->reg_lock, flags);
811
812 snd_wss_mce_up(chip);
813 spin_lock_irqsave(&chip->reg_lock, flags);
814 snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
815 chip->image[CS4231_PLAYBK_FORMAT]);
816 spin_unlock_irqrestore(&chip->reg_lock, flags);
817 snd_wss_mce_down(chip);
818
819#ifdef SNDRV_DEBUG_MCE
820 snd_printk("init: (4)\n");
821#endif
822
823 snd_wss_mce_up(chip);
824 spin_lock_irqsave(&chip->reg_lock, flags);
825 if (!(chip->hardware & WSS_HW_AD1848_MASK))
826 snd_wss_out(chip, CS4231_REC_FORMAT,
827 chip->image[CS4231_REC_FORMAT]);
828 spin_unlock_irqrestore(&chip->reg_lock, flags);
829 snd_wss_mce_down(chip);
830
831#ifdef SNDRV_DEBUG_MCE
832 snd_printk("init: (5)\n");
833#endif
834}
835
836static int snd_wss_open(struct snd_wss *chip, unsigned int mode)
837{
838 unsigned long flags;
839
840 mutex_lock(&chip->open_mutex);
841 if ((chip->mode & mode) ||
842 ((chip->mode & WSS_MODE_OPEN) && chip->single_dma)) {
843 mutex_unlock(&chip->open_mutex);
844 return -EAGAIN;
845 }
846 if (chip->mode & WSS_MODE_OPEN) {
847 chip->mode |= mode;
848 mutex_unlock(&chip->open_mutex);
849 return 0;
850 }
851 /* ok. now enable and ack CODEC IRQ */
852 spin_lock_irqsave(&chip->reg_lock, flags);
853 if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
854 snd_wss_out(chip, CS4231_IRQ_STATUS,
855 CS4231_PLAYBACK_IRQ |
856 CS4231_RECORD_IRQ |
857 CS4231_TIMER_IRQ);
858 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
859 }
860 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
861 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
862 chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE;
863 snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
864 if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
865 snd_wss_out(chip, CS4231_IRQ_STATUS,
866 CS4231_PLAYBACK_IRQ |
867 CS4231_RECORD_IRQ |
868 CS4231_TIMER_IRQ);
869 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
870 }
871 spin_unlock_irqrestore(&chip->reg_lock, flags);
872
873 chip->mode = mode;
874 mutex_unlock(&chip->open_mutex);
875 return 0;
876}
877
878static void snd_wss_close(struct snd_wss *chip, unsigned int mode)
879{
880 unsigned long flags;
881
882 mutex_lock(&chip->open_mutex);
883 chip->mode &= ~mode;
884 if (chip->mode & WSS_MODE_OPEN) {
885 mutex_unlock(&chip->open_mutex);
886 return;
887 }
888 snd_wss_calibrate_mute(chip, 1);
889
890 /* disable IRQ */
891 spin_lock_irqsave(&chip->reg_lock, flags);
892 if (!(chip->hardware & WSS_HW_AD1848_MASK))
893 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
894 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
895 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
896 chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE;
897 snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
898
899 /* now disable record & playback */
900
901 if (chip->image[CS4231_IFACE_CTRL] & (CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
902 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO)) {
903 spin_unlock_irqrestore(&chip->reg_lock, flags);
904 snd_wss_mce_up(chip);
905 spin_lock_irqsave(&chip->reg_lock, flags);
906 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
907 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
908 snd_wss_out(chip, CS4231_IFACE_CTRL,
909 chip->image[CS4231_IFACE_CTRL]);
910 spin_unlock_irqrestore(&chip->reg_lock, flags);
911 snd_wss_mce_down(chip);
912 spin_lock_irqsave(&chip->reg_lock, flags);
913 }
914
915 /* clear IRQ again */
916 if (!(chip->hardware & WSS_HW_AD1848_MASK))
917 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
918 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
919 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
920 spin_unlock_irqrestore(&chip->reg_lock, flags);
921
922 snd_wss_calibrate_mute(chip, 0);
923
924 chip->mode = 0;
925 mutex_unlock(&chip->open_mutex);
926}
927
928/*
929 * timer open/close
930 */
931
932static int snd_wss_timer_open(struct snd_timer *timer)
933{
934 struct snd_wss *chip = snd_timer_chip(timer);
935 snd_wss_open(chip, WSS_MODE_TIMER);
936 return 0;
937}
938
939static int snd_wss_timer_close(struct snd_timer *timer)
940{
941 struct snd_wss *chip = snd_timer_chip(timer);
942 snd_wss_close(chip, WSS_MODE_TIMER);
943 return 0;
944}
945
946static struct snd_timer_hardware snd_wss_timer_table =
947{
948 .flags = SNDRV_TIMER_HW_AUTO,
949 .resolution = 9945,
950 .ticks = 65535,
951 .open = snd_wss_timer_open,
952 .close = snd_wss_timer_close,
953 .c_resolution = snd_wss_timer_resolution,
954 .start = snd_wss_timer_start,
955 .stop = snd_wss_timer_stop,
956};
957
958/*
959 * ok.. exported functions..
960 */
961
962static int snd_wss_playback_hw_params(struct snd_pcm_substream *substream,
963 struct snd_pcm_hw_params *hw_params)
964{
965 struct snd_wss *chip = snd_pcm_substream_chip(substream);
966 unsigned char new_pdfr;
967 int err;
968
969 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
970 return err;
971 new_pdfr = snd_wss_get_format(chip, params_format(hw_params),
972 params_channels(hw_params)) |
973 snd_wss_get_rate(params_rate(hw_params));
974 chip->set_playback_format(chip, hw_params, new_pdfr);
975 return 0;
976}
977
978static int snd_wss_playback_hw_free(struct snd_pcm_substream *substream)
979{
980 return snd_pcm_lib_free_pages(substream);
981}
982
983static int snd_wss_playback_prepare(struct snd_pcm_substream *substream)
984{
985 struct snd_wss *chip = snd_pcm_substream_chip(substream);
986 struct snd_pcm_runtime *runtime = substream->runtime;
987 unsigned long flags;
988 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
989 unsigned int count = snd_pcm_lib_period_bytes(substream);
990
991 spin_lock_irqsave(&chip->reg_lock, flags);
992 chip->p_dma_size = size;
993 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO);
994 snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
995 count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT], count) - 1;
996 snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
997 snd_wss_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8));
998 spin_unlock_irqrestore(&chip->reg_lock, flags);
999#if 0
1000 snd_wss_debug(chip);
1001#endif
1002 return 0;
1003}
1004
1005static int snd_wss_capture_hw_params(struct snd_pcm_substream *substream,
1006 struct snd_pcm_hw_params *hw_params)
1007{
1008 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1009 unsigned char new_cdfr;
1010 int err;
1011
1012 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
1013 return err;
1014 new_cdfr = snd_wss_get_format(chip, params_format(hw_params),
1015 params_channels(hw_params)) |
1016 snd_wss_get_rate(params_rate(hw_params));
1017 chip->set_capture_format(chip, hw_params, new_cdfr);
1018 return 0;
1019}
1020
1021static int snd_wss_capture_hw_free(struct snd_pcm_substream *substream)
1022{
1023 return snd_pcm_lib_free_pages(substream);
1024}
1025
1026static int snd_wss_capture_prepare(struct snd_pcm_substream *substream)
1027{
1028 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1029 struct snd_pcm_runtime *runtime = substream->runtime;
1030 unsigned long flags;
1031 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
1032 unsigned int count = snd_pcm_lib_period_bytes(substream);
1033
1034 spin_lock_irqsave(&chip->reg_lock, flags);
1035 chip->c_dma_size = size;
1036 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
1037 snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
1038 if (chip->hardware & WSS_HW_AD1848_MASK)
1039 count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT],
1040 count);
1041 else
1042 count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT],
1043 count);
1044 count--;
1045 if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) {
1046 snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
1047 snd_wss_out(chip, CS4231_PLY_UPR_CNT,
1048 (unsigned char) (count >> 8));
1049 } else {
1050 snd_wss_out(chip, CS4231_REC_LWR_CNT, (unsigned char) count);
1051 snd_wss_out(chip, CS4231_REC_UPR_CNT,
1052 (unsigned char) (count >> 8));
1053 }
1054 spin_unlock_irqrestore(&chip->reg_lock, flags);
1055 return 0;
1056}
1057
1058void snd_wss_overrange(struct snd_wss *chip)
1059{
1060 unsigned long flags;
1061 unsigned char res;
1062
1063 spin_lock_irqsave(&chip->reg_lock, flags);
1064 res = snd_wss_in(chip, CS4231_TEST_INIT);
1065 spin_unlock_irqrestore(&chip->reg_lock, flags);
1066 if (res & (0x08 | 0x02)) /* detect overrange only above 0dB; may be user selectable? */
1067 chip->capture_substream->runtime->overrange++;
1068}
1069EXPORT_SYMBOL(snd_wss_overrange);
1070
1071irqreturn_t snd_wss_interrupt(int irq, void *dev_id)
1072{
1073 struct snd_wss *chip = dev_id;
1074 unsigned char status;
1075
1076 if (chip->hardware & WSS_HW_AD1848_MASK)
1077 /* pretend it was the only possible irq for AD1848 */
1078 status = CS4231_PLAYBACK_IRQ;
1079 else
1080 status = snd_wss_in(chip, CS4231_IRQ_STATUS);
1081 if (status & CS4231_TIMER_IRQ) {
1082 if (chip->timer)
1083 snd_timer_interrupt(chip->timer, chip->timer->sticks);
1084 }
1085 if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) {
1086 if (status & CS4231_PLAYBACK_IRQ) {
1087 if (chip->mode & WSS_MODE_PLAY) {
1088 if (chip->playback_substream)
1089 snd_pcm_period_elapsed(chip->playback_substream);
1090 }
1091 if (chip->mode & WSS_MODE_RECORD) {
1092 if (chip->capture_substream) {
1093 snd_wss_overrange(chip);
1094 snd_pcm_period_elapsed(chip->capture_substream);
1095 }
1096 }
1097 }
1098 } else {
1099 if (status & CS4231_PLAYBACK_IRQ) {
1100 if (chip->playback_substream)
1101 snd_pcm_period_elapsed(chip->playback_substream);
1102 }
1103 if (status & CS4231_RECORD_IRQ) {
1104 if (chip->capture_substream) {
1105 snd_wss_overrange(chip);
1106 snd_pcm_period_elapsed(chip->capture_substream);
1107 }
1108 }
1109 }
1110
1111 spin_lock(&chip->reg_lock);
1112 status = ~CS4231_ALL_IRQS | ~status;
1113 if (chip->hardware & WSS_HW_AD1848_MASK)
1114 wss_outb(chip, CS4231P(STATUS), 0);
1115 else
1116 snd_wss_outm(chip, CS4231_IRQ_STATUS, status, 0);
1117 spin_unlock(&chip->reg_lock);
1118 return IRQ_HANDLED;
1119}
1120EXPORT_SYMBOL(snd_wss_interrupt);
1121
1122static snd_pcm_uframes_t snd_wss_playback_pointer(struct snd_pcm_substream *substream)
1123{
1124 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1125 size_t ptr;
1126
1127 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
1128 return 0;
1129 ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);
1130 return bytes_to_frames(substream->runtime, ptr);
1131}
1132
1133static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *substream)
1134{
1135 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1136 size_t ptr;
1137
1138 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
1139 return 0;
1140 ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
1141 return bytes_to_frames(substream->runtime, ptr);
1142}
1143
1144/*
1145
1146 */
1147
1148static int snd_ad1848_probe(struct snd_wss *chip)
1149{
1150 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
1151 unsigned long flags;
1152 unsigned char r;
1153 unsigned short hardware = 0;
1154 int err = 0;
1155 int i;
1156
1157 while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
1158 if (time_after(jiffies, timeout))
1159 return -ENODEV;
1160 cond_resched();
1161 }
1162 spin_lock_irqsave(&chip->reg_lock, flags);
1163
1164 /* set CS423x MODE 1 */
1165 snd_wss_dout(chip, CS4231_MISC_INFO, 0);
1166
1167 snd_wss_dout(chip, CS4231_RIGHT_INPUT, 0x45); /* 0x55 & ~0x10 */
1168 r = snd_wss_in(chip, CS4231_RIGHT_INPUT);
1169 if (r != 0x45) {
1170 /* RMGE always high on AD1847 */
1171 if ((r & ~CS4231_ENABLE_MIC_GAIN) != 0x45) {
1172 err = -ENODEV;
1173 goto out;
1174 }
1175 hardware = WSS_HW_AD1847;
1176 } else {
1177 snd_wss_dout(chip, CS4231_LEFT_INPUT, 0xaa);
1178 r = snd_wss_in(chip, CS4231_LEFT_INPUT);
1179 /* L/RMGE always low on AT2320 */
1180 if ((r | CS4231_ENABLE_MIC_GAIN) != 0xaa) {
1181 err = -ENODEV;
1182 goto out;
1183 }
1184 }
1185
1186 /* clear pending IRQ */
1187 wss_inb(chip, CS4231P(STATUS));
1188 wss_outb(chip, CS4231P(STATUS), 0);
1189 mb();
1190
1191 if ((chip->hardware & WSS_HW_TYPE_MASK) != WSS_HW_DETECT)
1192 goto out;
1193
1194 if (hardware) {
1195 chip->hardware = hardware;
1196 goto out;
1197 }
1198
1199 r = snd_wss_in(chip, CS4231_MISC_INFO);
1200
1201 /* set CS423x MODE 2 */
1202 snd_wss_dout(chip, CS4231_MISC_INFO, CS4231_MODE2);
1203 for (i = 0; i < 16; i++) {
1204 if (snd_wss_in(chip, i) != snd_wss_in(chip, 16 + i)) {
1205 /* we have more than 16 registers: check ID */
1206 if ((r & 0xf) != 0xa)
1207 goto out_mode;
1208 /*
1209 * on CMI8330, CS4231_VERSION is volume control and
1210 * can be set to 0
1211 */
1212 snd_wss_dout(chip, CS4231_VERSION, 0);
1213 r = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
1214 if (!r)
1215 chip->hardware = WSS_HW_CMI8330;
1216 goto out_mode;
1217 }
1218 }
1219 if (r & 0x80)
1220 chip->hardware = WSS_HW_CS4248;
1221 else
1222 chip->hardware = WSS_HW_AD1848;
1223out_mode:
1224 snd_wss_dout(chip, CS4231_MISC_INFO, 0);
1225out:
1226 spin_unlock_irqrestore(&chip->reg_lock, flags);
1227 return err;
1228}
1229
1230static int snd_wss_probe(struct snd_wss *chip)
1231{
1232 unsigned long flags;
1233 int i, id, rev, regnum;
1234 unsigned char *ptr;
1235 unsigned int hw;
1236
1237 id = snd_ad1848_probe(chip);
1238 if (id < 0)
1239 return id;
1240
1241 hw = chip->hardware;
1242 if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) {
1243 for (i = 0; i < 50; i++) {
1244 mb();
1245 if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
1246 msleep(2);
1247 else {
1248 spin_lock_irqsave(&chip->reg_lock, flags);
1249 snd_wss_out(chip, CS4231_MISC_INFO,
1250 CS4231_MODE2);
1251 id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f;
1252 spin_unlock_irqrestore(&chip->reg_lock, flags);
1253 if (id == 0x0a)
1254 break; /* this is valid value */
1255 }
1256 }
1257 snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id);
1258 if (id != 0x0a)
1259 return -ENODEV; /* no valid device found */
1260
1261 rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
1262 snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev);
1263 if (rev == 0x80) {
1264 unsigned char tmp = snd_wss_in(chip, 23);
1265 snd_wss_out(chip, 23, ~tmp);
1266 if (snd_wss_in(chip, 23) != tmp)
1267 chip->hardware = WSS_HW_AD1845;
1268 else
1269 chip->hardware = WSS_HW_CS4231;
1270 } else if (rev == 0xa0) {
1271 chip->hardware = WSS_HW_CS4231A;
1272 } else if (rev == 0xa2) {
1273 chip->hardware = WSS_HW_CS4232;
1274 } else if (rev == 0xb2) {
1275 chip->hardware = WSS_HW_CS4232A;
1276 } else if (rev == 0x83) {
1277 chip->hardware = WSS_HW_CS4236;
1278 } else if (rev == 0x03) {
1279 chip->hardware = WSS_HW_CS4236B;
1280 } else {
1281 snd_printk("unknown CS chip with version 0x%x\n", rev);
1282 return -ENODEV; /* unknown CS4231 chip? */
1283 }
1284 }
1285 spin_lock_irqsave(&chip->reg_lock, flags);
1286 wss_inb(chip, CS4231P(STATUS)); /* clear any pendings IRQ */
1287 wss_outb(chip, CS4231P(STATUS), 0);
1288 mb();
1289 spin_unlock_irqrestore(&chip->reg_lock, flags);
1290
1291 if (!(chip->hardware & WSS_HW_AD1848_MASK))
1292 chip->image[CS4231_MISC_INFO] = CS4231_MODE2;
1293 switch (chip->hardware) {
1294 case WSS_HW_INTERWAVE:
1295 chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3;
1296 break;
1297 case WSS_HW_CS4235:
1298 case WSS_HW_CS4236B:
1299 case WSS_HW_CS4237B:
1300 case WSS_HW_CS4238B:
1301 case WSS_HW_CS4239:
1302 if (hw == WSS_HW_DETECT3)
1303 chip->image[CS4231_MISC_INFO] = CS4231_4236_MODE3;
1304 else
1305 chip->hardware = WSS_HW_CS4236;
1306 break;
1307 }
1308
1309 chip->image[CS4231_IFACE_CTRL] =
1310 (chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) |
1311 (chip->single_dma ? CS4231_SINGLE_DMA : 0);
1312 if (chip->hardware != WSS_HW_OPTI93X) {
1313 chip->image[CS4231_ALT_FEATURE_1] = 0x80;
1314 chip->image[CS4231_ALT_FEATURE_2] =
1315 chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01;
1316 }
1317 ptr = (unsigned char *) &chip->image;
1318 regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32;
1319 snd_wss_mce_down(chip);
1320 spin_lock_irqsave(&chip->reg_lock, flags);
1321 for (i = 0; i < regnum; i++) /* ok.. fill all registers */
1322 snd_wss_out(chip, i, *ptr++);
1323 spin_unlock_irqrestore(&chip->reg_lock, flags);
1324 snd_wss_mce_up(chip);
1325 snd_wss_mce_down(chip);
1326
1327 mdelay(2);
1328
1329 /* ok.. try check hardware version for CS4236+ chips */
1330 if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) {
1331 if (chip->hardware == WSS_HW_CS4236B) {
1332 rev = snd_cs4236_ext_in(chip, CS4236_VERSION);
1333 snd_cs4236_ext_out(chip, CS4236_VERSION, 0xff);
1334 id = snd_cs4236_ext_in(chip, CS4236_VERSION);
1335 snd_cs4236_ext_out(chip, CS4236_VERSION, rev);
1336 snd_printdd("CS4231: ext version; rev = 0x%x, id = 0x%x\n", rev, id);
1337 if ((id & 0x1f) == 0x1d) { /* CS4235 */
1338 chip->hardware = WSS_HW_CS4235;
1339 switch (id >> 5) {
1340 case 4:
1341 case 5:
1342 case 6:
1343 break;
1344 default:
1345 snd_printk("unknown CS4235 chip (enhanced version = 0x%x)\n", id);
1346 }
1347 } else if ((id & 0x1f) == 0x0b) { /* CS4236/B */
1348 switch (id >> 5) {
1349 case 4:
1350 case 5:
1351 case 6:
1352 case 7:
1353 chip->hardware = WSS_HW_CS4236B;
1354 break;
1355 default:
1356 snd_printk("unknown CS4236 chip (enhanced version = 0x%x)\n", id);
1357 }
1358 } else if ((id & 0x1f) == 0x08) { /* CS4237B */
1359 chip->hardware = WSS_HW_CS4237B;
1360 switch (id >> 5) {
1361 case 4:
1362 case 5:
1363 case 6:
1364 case 7:
1365 break;
1366 default:
1367 snd_printk("unknown CS4237B chip (enhanced version = 0x%x)\n", id);
1368 }
1369 } else if ((id & 0x1f) == 0x09) { /* CS4238B */
1370 chip->hardware = WSS_HW_CS4238B;
1371 switch (id >> 5) {
1372 case 5:
1373 case 6:
1374 case 7:
1375 break;
1376 default:
1377 snd_printk("unknown CS4238B chip (enhanced version = 0x%x)\n", id);
1378 }
1379 } else if ((id & 0x1f) == 0x1e) { /* CS4239 */
1380 chip->hardware = WSS_HW_CS4239;
1381 switch (id >> 5) {
1382 case 4:
1383 case 5:
1384 case 6:
1385 break;
1386 default:
1387 snd_printk("unknown CS4239 chip (enhanced version = 0x%x)\n", id);
1388 }
1389 } else {
1390 snd_printk("unknown CS4236/CS423xB chip (enhanced version = 0x%x)\n", id);
1391 }
1392 }
1393 }
1394 return 0; /* all things are ok.. */
1395}
1396
1397/*
1398
1399 */
1400
1401static struct snd_pcm_hardware snd_wss_playback =
1402{
1403 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1404 SNDRV_PCM_INFO_MMAP_VALID |
1405 SNDRV_PCM_INFO_RESUME |
1406 SNDRV_PCM_INFO_SYNC_START),
1407 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
1408 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
1409 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1410 .rate_min = 5510,
1411 .rate_max = 48000,
1412 .channels_min = 1,
1413 .channels_max = 2,
1414 .buffer_bytes_max = (128*1024),
1415 .period_bytes_min = 64,
1416 .period_bytes_max = (128*1024),
1417 .periods_min = 1,
1418 .periods_max = 1024,
1419 .fifo_size = 0,
1420};
1421
1422static struct snd_pcm_hardware snd_wss_capture =
1423{
1424 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1425 SNDRV_PCM_INFO_MMAP_VALID |
1426 SNDRV_PCM_INFO_RESUME |
1427 SNDRV_PCM_INFO_SYNC_START),
1428 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
1429 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
1430 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1431 .rate_min = 5510,
1432 .rate_max = 48000,
1433 .channels_min = 1,
1434 .channels_max = 2,
1435 .buffer_bytes_max = (128*1024),
1436 .period_bytes_min = 64,
1437 .period_bytes_max = (128*1024),
1438 .periods_min = 1,
1439 .periods_max = 1024,
1440 .fifo_size = 0,
1441};
1442
1443/*
1444
1445 */
1446
1447static int snd_wss_playback_open(struct snd_pcm_substream *substream)
1448{
1449 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1450 struct snd_pcm_runtime *runtime = substream->runtime;
1451 int err;
1452
1453 runtime->hw = snd_wss_playback;
1454
1455 /* hardware limitation of older chipsets */
1456 if (chip->hardware & WSS_HW_AD1848_MASK)
1457 runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
1458 SNDRV_PCM_FMTBIT_S16_BE);
1459
1460 /* hardware bug in InterWave chipset */
1461 if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3)
1462 runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW;
1463
1464 /* hardware limitation of cheap chips */
1465 if (chip->hardware == WSS_HW_CS4235 ||
1466 chip->hardware == WSS_HW_CS4239)
1467 runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
1468
1469 snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
1470 snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
1471
1472 if (chip->claim_dma) {
1473 if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0)
1474 return err;
1475 }
1476
1477 err = snd_wss_open(chip, WSS_MODE_PLAY);
1478 if (err < 0) {
1479 if (chip->release_dma)
1480 chip->release_dma(chip, chip->dma_private_data, chip->dma1);
1481 snd_free_pages(runtime->dma_area, runtime->dma_bytes);
1482 return err;
1483 }
1484 chip->playback_substream = substream;
1485 snd_pcm_set_sync(substream);
1486 chip->rate_constraint(runtime);
1487 return 0;
1488}
1489
1490static int snd_wss_capture_open(struct snd_pcm_substream *substream)
1491{
1492 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1493 struct snd_pcm_runtime *runtime = substream->runtime;
1494 int err;
1495
1496 runtime->hw = snd_wss_capture;
1497
1498 /* hardware limitation of older chipsets */
1499 if (chip->hardware & WSS_HW_AD1848_MASK)
1500 runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
1501 SNDRV_PCM_FMTBIT_S16_BE);
1502
1503 /* hardware limitation of cheap chips */
1504 if (chip->hardware == WSS_HW_CS4235 ||
1505 chip->hardware == WSS_HW_CS4239 ||
1506 chip->hardware == WSS_HW_OPTI93X)
1507 runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 |
1508 SNDRV_PCM_FMTBIT_S16_LE;
1509
1510 snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
1511 snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
1512
1513 if (chip->claim_dma) {
1514 if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0)
1515 return err;
1516 }
1517
1518 err = snd_wss_open(chip, WSS_MODE_RECORD);
1519 if (err < 0) {
1520 if (chip->release_dma)
1521 chip->release_dma(chip, chip->dma_private_data, chip->dma2);
1522 snd_free_pages(runtime->dma_area, runtime->dma_bytes);
1523 return err;
1524 }
1525 chip->capture_substream = substream;
1526 snd_pcm_set_sync(substream);
1527 chip->rate_constraint(runtime);
1528 return 0;
1529}
1530
1531static int snd_wss_playback_close(struct snd_pcm_substream *substream)
1532{
1533 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1534
1535 chip->playback_substream = NULL;
1536 snd_wss_close(chip, WSS_MODE_PLAY);
1537 return 0;
1538}
1539
1540static int snd_wss_capture_close(struct snd_pcm_substream *substream)
1541{
1542 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1543
1544 chip->capture_substream = NULL;
1545 snd_wss_close(chip, WSS_MODE_RECORD);
1546 return 0;
1547}
1548
1549static void snd_wss_thinkpad_twiddle(struct snd_wss *chip, int on)
1550{
1551 int tmp;
1552
1553 if (!chip->thinkpad_flag)
1554 return;
1555
1556 outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
1557 tmp = inb(AD1848_THINKPAD_CTL_PORT2);
1558
1559 if (on)
1560 /* turn it on */
1561 tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
1562 else
1563 /* turn it off */
1564 tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
1565
1566 outb(tmp, AD1848_THINKPAD_CTL_PORT2);
1567}
1568
1569#ifdef CONFIG_PM
1570
1571/* lowlevel suspend callback for CS4231 */
1572static void snd_wss_suspend(struct snd_wss *chip)
1573{
1574 int reg;
1575 unsigned long flags;
1576
1577 snd_pcm_suspend_all(chip->pcm);
1578 spin_lock_irqsave(&chip->reg_lock, flags);
1579 for (reg = 0; reg < 32; reg++)
1580 chip->image[reg] = snd_wss_in(chip, reg);
1581 spin_unlock_irqrestore(&chip->reg_lock, flags);
1582 if (chip->thinkpad_flag)
1583 snd_wss_thinkpad_twiddle(chip, 0);
1584}
1585
1586/* lowlevel resume callback for CS4231 */
1587static void snd_wss_resume(struct snd_wss *chip)
1588{
1589 int reg;
1590 unsigned long flags;
1591 /* int timeout; */
1592
1593 if (chip->thinkpad_flag)
1594 snd_wss_thinkpad_twiddle(chip, 1);
1595 snd_wss_mce_up(chip);
1596 spin_lock_irqsave(&chip->reg_lock, flags);
1597 for (reg = 0; reg < 32; reg++) {
1598 switch (reg) {
1599 case CS4231_VERSION:
1600 break;
1601 default:
1602 snd_wss_out(chip, reg, chip->image[reg]);
1603 break;
1604 }
1605 }
1606 spin_unlock_irqrestore(&chip->reg_lock, flags);
1607#if 1
1608 snd_wss_mce_down(chip);
1609#else
1610 /* The following is a workaround to avoid freeze after resume on TP600E.
1611 This is the first half of copy of snd_wss_mce_down(), but doesn't
1612 include rescheduling. -- iwai
1613 */
1614 snd_wss_busy_wait(chip);
1615 spin_lock_irqsave(&chip->reg_lock, flags);
1616 chip->mce_bit &= ~CS4231_MCE;
1617 timeout = wss_inb(chip, CS4231P(REGSEL));
1618 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
1619 spin_unlock_irqrestore(&chip->reg_lock, flags);
1620 if (timeout == 0x80)
1621 snd_printk("down [0x%lx]: serious init problem - codec still busy\n", chip->port);
1622 if ((timeout & CS4231_MCE) == 0 ||
1623 !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) {
1624 return;
1625 }
1626 snd_wss_busy_wait(chip);
1627#endif
1628}
1629#endif /* CONFIG_PM */
1630
1631static int snd_wss_free(struct snd_wss *chip)
1632{
1633 release_and_free_resource(chip->res_port);
1634 release_and_free_resource(chip->res_cport);
1635 if (chip->irq >= 0) {
1636 disable_irq(chip->irq);
1637 if (!(chip->hwshare & WSS_HWSHARE_IRQ))
1638 free_irq(chip->irq, (void *) chip);
1639 }
1640 if (!(chip->hwshare & WSS_HWSHARE_DMA1) && chip->dma1 >= 0) {
1641 snd_dma_disable(chip->dma1);
1642 free_dma(chip->dma1);
1643 }
1644 if (!(chip->hwshare & WSS_HWSHARE_DMA2) &&
1645 chip->dma2 >= 0 && chip->dma2 != chip->dma1) {
1646 snd_dma_disable(chip->dma2);
1647 free_dma(chip->dma2);
1648 }
1649 if (chip->timer)
1650 snd_device_free(chip->card, chip->timer);
1651 kfree(chip);
1652 return 0;
1653}
1654
1655static int snd_wss_dev_free(struct snd_device *device)
1656{
1657 struct snd_wss *chip = device->device_data;
1658 return snd_wss_free(chip);
1659}
1660
1661const char *snd_wss_chip_id(struct snd_wss *chip)
1662{
1663 switch (chip->hardware) {
1664 case WSS_HW_CS4231:
1665 return "CS4231";
1666 case WSS_HW_CS4231A:
1667 return "CS4231A";
1668 case WSS_HW_CS4232:
1669 return "CS4232";
1670 case WSS_HW_CS4232A:
1671 return "CS4232A";
1672 case WSS_HW_CS4235:
1673 return "CS4235";
1674 case WSS_HW_CS4236:
1675 return "CS4236";
1676 case WSS_HW_CS4236B:
1677 return "CS4236B";
1678 case WSS_HW_CS4237B:
1679 return "CS4237B";
1680 case WSS_HW_CS4238B:
1681 return "CS4238B";
1682 case WSS_HW_CS4239:
1683 return "CS4239";
1684 case WSS_HW_INTERWAVE:
1685 return "AMD InterWave";
1686 case WSS_HW_OPL3SA2:
1687 return chip->card->shortname;
1688 case WSS_HW_AD1845:
1689 return "AD1845";
1690 case WSS_HW_OPTI93X:
1691 return "OPTi 93x";
1692 case WSS_HW_AD1847:
1693 return "AD1847";
1694 case WSS_HW_AD1848:
1695 return "AD1848";
1696 case WSS_HW_CS4248:
1697 return "CS4248";
1698 case WSS_HW_CMI8330:
1699 return "CMI8330/C3D";
1700 default:
1701 return "???";
1702 }
1703}
1704EXPORT_SYMBOL(snd_wss_chip_id);
1705
1706static int snd_wss_new(struct snd_card *card,
1707 unsigned short hardware,
1708 unsigned short hwshare,
1709 struct snd_wss **rchip)
1710{
1711 struct snd_wss *chip;
1712
1713 *rchip = NULL;
1714 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
1715 if (chip == NULL)
1716 return -ENOMEM;
1717 chip->hardware = hardware;
1718 chip->hwshare = hwshare;
1719
1720 spin_lock_init(&chip->reg_lock);
1721 mutex_init(&chip->mce_mutex);
1722 mutex_init(&chip->open_mutex);
1723 chip->card = card;
1724 chip->rate_constraint = snd_wss_xrate;
1725 chip->set_playback_format = snd_wss_playback_format;
1726 chip->set_capture_format = snd_wss_capture_format;
1727 if (chip->hardware == WSS_HW_OPTI93X)
1728 memcpy(&chip->image, &snd_opti93x_original_image,
1729 sizeof(snd_opti93x_original_image));
1730 else
1731 memcpy(&chip->image, &snd_wss_original_image,
1732 sizeof(snd_wss_original_image));
1733 if (chip->hardware & WSS_HW_AD1848_MASK) {
1734 chip->image[CS4231_PIN_CTRL] = 0;
1735 chip->image[CS4231_TEST_INIT] = 0;
1736 }
1737
1738 *rchip = chip;
1739 return 0;
1740}
1741
1742int snd_wss_create(struct snd_card *card,
1743 unsigned long port,
1744 unsigned long cport,
1745 int irq, int dma1, int dma2,
1746 unsigned short hardware,
1747 unsigned short hwshare,
1748 struct snd_wss **rchip)
1749{
1750 static struct snd_device_ops ops = {
1751 .dev_free = snd_wss_dev_free,
1752 };
1753 struct snd_wss *chip;
1754 int err;
1755
1756 err = snd_wss_new(card, hardware, hwshare, &chip);
1757 if (err < 0)
1758 return err;
1759
1760 chip->irq = -1;
1761 chip->dma1 = -1;
1762 chip->dma2 = -1;
1763
1764 chip->res_port = request_region(port, 4, "WSS");
1765 if (!chip->res_port) {
1766 snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port);
1767 snd_wss_free(chip);
1768 return -EBUSY;
1769 }
1770 chip->port = port;
1771 if ((long)cport >= 0) {
1772 chip->res_cport = request_region(cport, 8, "CS4232 Control");
1773 if (!chip->res_cport) {
1774 snd_printk(KERN_ERR
1775 "wss: can't grab control port 0x%lx\n", cport);
1776 snd_wss_free(chip);
1777 return -ENODEV;
1778 }
1779 }
1780 chip->cport = cport;
1781 if (!(hwshare & WSS_HWSHARE_IRQ))
1782 if (request_irq(irq, snd_wss_interrupt, IRQF_DISABLED,
1783 "WSS", (void *) chip)) {
1784 snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq);
1785 snd_wss_free(chip);
1786 return -EBUSY;
1787 }
1788 chip->irq = irq;
1789 if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) {
1790 snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1);
1791 snd_wss_free(chip);
1792 return -EBUSY;
1793 }
1794 chip->dma1 = dma1;
1795 if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 &&
1796 dma2 >= 0 && request_dma(dma2, "WSS - 2")) {
1797 snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2);
1798 snd_wss_free(chip);
1799 return -EBUSY;
1800 }
1801 if (dma1 == dma2 || dma2 < 0) {
1802 chip->single_dma = 1;
1803 chip->dma2 = chip->dma1;
1804 } else
1805 chip->dma2 = dma2;
1806
1807 if (hardware == WSS_HW_THINKPAD) {
1808 chip->thinkpad_flag = 1;
1809 chip->hardware = WSS_HW_DETECT; /* reset */
1810 snd_wss_thinkpad_twiddle(chip, 1);
1811 }
1812
1813 /* global setup */
1814 if (snd_wss_probe(chip) < 0) {
1815 snd_wss_free(chip);
1816 return -ENODEV;
1817 }
1818 snd_wss_init(chip);
1819
1820#if 0
1821 if (chip->hardware & WSS_HW_CS4232_MASK) {
1822 if (chip->res_cport == NULL)
1823 snd_printk("CS4232 control port features are not accessible\n");
1824 }
1825#endif
1826
1827 /* Register device */
1828 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
1829 if (err < 0) {
1830 snd_wss_free(chip);
1831 return err;
1832 }
1833
1834#ifdef CONFIG_PM
1835 /* Power Management */
1836 chip->suspend = snd_wss_suspend;
1837 chip->resume = snd_wss_resume;
1838#endif
1839
1840 *rchip = chip;
1841 return 0;
1842}
1843EXPORT_SYMBOL(snd_wss_create);
1844
1845static struct snd_pcm_ops snd_wss_playback_ops = {
1846 .open = snd_wss_playback_open,
1847 .close = snd_wss_playback_close,
1848 .ioctl = snd_pcm_lib_ioctl,
1849 .hw_params = snd_wss_playback_hw_params,
1850 .hw_free = snd_wss_playback_hw_free,
1851 .prepare = snd_wss_playback_prepare,
1852 .trigger = snd_wss_trigger,
1853 .pointer = snd_wss_playback_pointer,
1854};
1855
1856static struct snd_pcm_ops snd_wss_capture_ops = {
1857 .open = snd_wss_capture_open,
1858 .close = snd_wss_capture_close,
1859 .ioctl = snd_pcm_lib_ioctl,
1860 .hw_params = snd_wss_capture_hw_params,
1861 .hw_free = snd_wss_capture_hw_free,
1862 .prepare = snd_wss_capture_prepare,
1863 .trigger = snd_wss_trigger,
1864 .pointer = snd_wss_capture_pointer,
1865};
1866
1867int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
1868{
1869 struct snd_pcm *pcm;
1870 int err;
1871
1872 err = snd_pcm_new(chip->card, "WSS", device, 1, 1, &pcm);
1873 if (err < 0)
1874 return err;
1875
1876 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops);
1877 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops);
1878
1879 /* global setup */
1880 pcm->private_data = chip;
1881 pcm->info_flags = 0;
1882 if (chip->single_dma)
1883 pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
1884 if (chip->hardware != WSS_HW_INTERWAVE)
1885 pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
1886 strcpy(pcm->name, snd_wss_chip_id(chip));
1887
1888 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1889 snd_dma_isa_data(),
1890 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
1891
1892 chip->pcm = pcm;
1893 if (rpcm)
1894 *rpcm = pcm;
1895 return 0;
1896}
1897EXPORT_SYMBOL(snd_wss_pcm);
1898
1899static void snd_wss_timer_free(struct snd_timer *timer)
1900{
1901 struct snd_wss *chip = timer->private_data;
1902 chip->timer = NULL;
1903}
1904
1905int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer)
1906{
1907 struct snd_timer *timer;
1908 struct snd_timer_id tid;
1909 int err;
1910
1911 /* Timer initialization */
1912 tid.dev_class = SNDRV_TIMER_CLASS_CARD;
1913 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
1914 tid.card = chip->card->number;
1915 tid.device = device;
1916 tid.subdevice = 0;
1917 if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0)
1918 return err;
1919 strcpy(timer->name, snd_wss_chip_id(chip));
1920 timer->private_data = chip;
1921 timer->private_free = snd_wss_timer_free;
1922 timer->hw = snd_wss_timer_table;
1923 chip->timer = timer;
1924 if (rtimer)
1925 *rtimer = timer;
1926 return 0;
1927}
1928EXPORT_SYMBOL(snd_wss_timer);
1929
1930/*
1931 * MIXER part
1932 */
1933
1934static int snd_wss_info_mux(struct snd_kcontrol *kcontrol,
1935 struct snd_ctl_elem_info *uinfo)
1936{
1937 static char *texts[4] = {
1938 "Line", "Aux", "Mic", "Mix"
1939 };
1940 static char *opl3sa_texts[4] = {
1941 "Line", "CD", "Mic", "Mix"
1942 };
1943 static char *gusmax_texts[4] = {
1944 "Line", "Synth", "Mic", "Mix"
1945 };
1946 char **ptexts = texts;
1947 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
1948
1949 if (snd_BUG_ON(!chip->card))
1950 return -EINVAL;
1951 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1952 uinfo->count = 2;
1953 uinfo->value.enumerated.items = 4;
1954 if (uinfo->value.enumerated.item > 3)
1955 uinfo->value.enumerated.item = 3;
1956 if (!strcmp(chip->card->driver, "GUS MAX"))
1957 ptexts = gusmax_texts;
1958 switch (chip->hardware) {
1959 case WSS_HW_INTERWAVE:
1960 ptexts = gusmax_texts;
1961 break;
1962 case WSS_HW_OPL3SA2:
1963 ptexts = opl3sa_texts;
1964 break;
1965 }
1966 strcpy(uinfo->value.enumerated.name, ptexts[uinfo->value.enumerated.item]);
1967 return 0;
1968}
1969
1970static int snd_wss_get_mux(struct snd_kcontrol *kcontrol,
1971 struct snd_ctl_elem_value *ucontrol)
1972{
1973 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
1974 unsigned long flags;
1975
1976 spin_lock_irqsave(&chip->reg_lock, flags);
1977 ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6;
1978 ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6;
1979 spin_unlock_irqrestore(&chip->reg_lock, flags);
1980 return 0;
1981}
1982
1983static int snd_wss_put_mux(struct snd_kcontrol *kcontrol,
1984 struct snd_ctl_elem_value *ucontrol)
1985{
1986 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
1987 unsigned long flags;
1988 unsigned short left, right;
1989 int change;
1990
1991 if (ucontrol->value.enumerated.item[0] > 3 ||
1992 ucontrol->value.enumerated.item[1] > 3)
1993 return -EINVAL;
1994 left = ucontrol->value.enumerated.item[0] << 6;
1995 right = ucontrol->value.enumerated.item[1] << 6;
1996 spin_lock_irqsave(&chip->reg_lock, flags);
1997 left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left;
1998 right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right;
1999 change = left != chip->image[CS4231_LEFT_INPUT] ||
2000 right != chip->image[CS4231_RIGHT_INPUT];
2001 snd_wss_out(chip, CS4231_LEFT_INPUT, left);
2002 snd_wss_out(chip, CS4231_RIGHT_INPUT, right);
2003 spin_unlock_irqrestore(&chip->reg_lock, flags);
2004 return change;
2005}
2006
2007int snd_wss_info_single(struct snd_kcontrol *kcontrol,
2008 struct snd_ctl_elem_info *uinfo)
2009{
2010 int mask = (kcontrol->private_value >> 16) & 0xff;
2011
2012 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
2013 uinfo->count = 1;
2014 uinfo->value.integer.min = 0;
2015 uinfo->value.integer.max = mask;
2016 return 0;
2017}
2018EXPORT_SYMBOL(snd_wss_info_single);
2019
2020int snd_wss_get_single(struct snd_kcontrol *kcontrol,
2021 struct snd_ctl_elem_value *ucontrol)
2022{
2023 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2024 unsigned long flags;
2025 int reg = kcontrol->private_value & 0xff;
2026 int shift = (kcontrol->private_value >> 8) & 0xff;
2027 int mask = (kcontrol->private_value >> 16) & 0xff;
2028 int invert = (kcontrol->private_value >> 24) & 0xff;
2029
2030 spin_lock_irqsave(&chip->reg_lock, flags);
2031 ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
2032 spin_unlock_irqrestore(&chip->reg_lock, flags);
2033 if (invert)
2034 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
2035 return 0;
2036}
2037EXPORT_SYMBOL(snd_wss_get_single);
2038
2039int snd_wss_put_single(struct snd_kcontrol *kcontrol,
2040 struct snd_ctl_elem_value *ucontrol)
2041{
2042 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2043 unsigned long flags;
2044 int reg = kcontrol->private_value & 0xff;
2045 int shift = (kcontrol->private_value >> 8) & 0xff;
2046 int mask = (kcontrol->private_value >> 16) & 0xff;
2047 int invert = (kcontrol->private_value >> 24) & 0xff;
2048 int change;
2049 unsigned short val;
2050
2051 val = (ucontrol->value.integer.value[0] & mask);
2052 if (invert)
2053 val = mask - val;
2054 val <<= shift;
2055 spin_lock_irqsave(&chip->reg_lock, flags);
2056 val = (chip->image[reg] & ~(mask << shift)) | val;
2057 change = val != chip->image[reg];
2058 snd_wss_out(chip, reg, val);
2059 spin_unlock_irqrestore(&chip->reg_lock, flags);
2060 return change;
2061}
2062EXPORT_SYMBOL(snd_wss_put_single);
2063
2064int snd_wss_info_double(struct snd_kcontrol *kcontrol,
2065 struct snd_ctl_elem_info *uinfo)
2066{
2067 int mask = (kcontrol->private_value >> 24) & 0xff;
2068
2069 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
2070 uinfo->count = 2;
2071 uinfo->value.integer.min = 0;
2072 uinfo->value.integer.max = mask;
2073 return 0;
2074}
2075EXPORT_SYMBOL(snd_wss_info_double);
2076
2077int snd_wss_get_double(struct snd_kcontrol *kcontrol,
2078 struct snd_ctl_elem_value *ucontrol)
2079{
2080 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2081 unsigned long flags;
2082 int left_reg = kcontrol->private_value & 0xff;
2083 int right_reg = (kcontrol->private_value >> 8) & 0xff;
2084 int shift_left = (kcontrol->private_value >> 16) & 0x07;
2085 int shift_right = (kcontrol->private_value >> 19) & 0x07;
2086 int mask = (kcontrol->private_value >> 24) & 0xff;
2087 int invert = (kcontrol->private_value >> 22) & 1;
2088
2089 spin_lock_irqsave(&chip->reg_lock, flags);
2090 ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
2091 ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
2092 spin_unlock_irqrestore(&chip->reg_lock, flags);
2093 if (invert) {
2094 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
2095 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
2096 }
2097 return 0;
2098}
2099EXPORT_SYMBOL(snd_wss_get_double);
2100
2101int snd_wss_put_double(struct snd_kcontrol *kcontrol,
2102 struct snd_ctl_elem_value *ucontrol)
2103{
2104 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2105 unsigned long flags;
2106 int left_reg = kcontrol->private_value & 0xff;
2107 int right_reg = (kcontrol->private_value >> 8) & 0xff;
2108 int shift_left = (kcontrol->private_value >> 16) & 0x07;
2109 int shift_right = (kcontrol->private_value >> 19) & 0x07;
2110 int mask = (kcontrol->private_value >> 24) & 0xff;
2111 int invert = (kcontrol->private_value >> 22) & 1;
2112 int change;
2113 unsigned short val1, val2;
2114
2115 val1 = ucontrol->value.integer.value[0] & mask;
2116 val2 = ucontrol->value.integer.value[1] & mask;
2117 if (invert) {
2118 val1 = mask - val1;
2119 val2 = mask - val2;
2120 }
2121 val1 <<= shift_left;
2122 val2 <<= shift_right;
2123 spin_lock_irqsave(&chip->reg_lock, flags);
2124 if (left_reg != right_reg) {
2125 val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
2126 val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
2127 change = val1 != chip->image[left_reg] ||
2128 val2 != chip->image[right_reg];
2129 snd_wss_out(chip, left_reg, val1);
2130 snd_wss_out(chip, right_reg, val2);
2131 } else {
2132 mask = (mask << shift_left) | (mask << shift_right);
2133 val1 = (chip->image[left_reg] & ~mask) | val1 | val2;
2134 change = val1 != chip->image[left_reg];
2135 snd_wss_out(chip, left_reg, val1);
2136 }
2137 spin_unlock_irqrestore(&chip->reg_lock, flags);
2138 return change;
2139}
2140EXPORT_SYMBOL(snd_wss_put_double);
2141
2142static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
2143static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
2144static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
2145
2146static struct snd_kcontrol_new snd_ad1848_controls[] = {
2147WSS_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT,
2148 7, 7, 1, 1),
2149WSS_DOUBLE_TLV("PCM Playback Volume", 0,
2150 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
2151 db_scale_6bit),
2152WSS_DOUBLE("Aux Playback Switch", 0,
2153 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
2154WSS_DOUBLE_TLV("Aux Playback Volume", 0,
2155 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
2156 db_scale_5bit_12db_max),
2157WSS_DOUBLE("Aux Playback Switch", 1,
2158 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
2159WSS_DOUBLE_TLV("Aux Playback Volume", 1,
2160 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
2161 db_scale_5bit_12db_max),
2162WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
2163 0, 0, 15, 0, db_scale_rec_gain),
2164{
2165 .name = "Capture Source",
2166 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2167 .info = snd_wss_info_mux,
2168 .get = snd_wss_get_mux,
2169 .put = snd_wss_put_mux,
2170},
2171WSS_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
2172WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 1, 63, 0,
2173 db_scale_6bit),
2174};
2175
2176static struct snd_kcontrol_new snd_wss_controls[] = {
2177WSS_DOUBLE("PCM Playback Switch", 0,
2178 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
2179WSS_DOUBLE("PCM Playback Volume", 0,
2180 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
2181WSS_DOUBLE("Line Playback Switch", 0,
2182 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
2183WSS_DOUBLE("Line Playback Volume", 0,
2184 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
2185WSS_DOUBLE("Aux Playback Switch", 0,
2186 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
2187WSS_DOUBLE("Aux Playback Volume", 0,
2188 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
2189WSS_DOUBLE("Aux Playback Switch", 1,
2190 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
2191WSS_DOUBLE("Aux Playback Volume", 1,
2192 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
2193WSS_SINGLE("Mono Playback Switch", 0,
2194 CS4231_MONO_CTRL, 7, 1, 1),
2195WSS_SINGLE("Mono Playback Volume", 0,
2196 CS4231_MONO_CTRL, 0, 15, 1),
2197WSS_SINGLE("Mono Output Playback Switch", 0,
2198 CS4231_MONO_CTRL, 6, 1, 1),
2199WSS_SINGLE("Mono Output Playback Bypass", 0,
2200 CS4231_MONO_CTRL, 5, 1, 0),
2201WSS_DOUBLE("Capture Volume", 0,
2202 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
2203{
2204 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2205 .name = "Capture Source",
2206 .info = snd_wss_info_mux,
2207 .get = snd_wss_get_mux,
2208 .put = snd_wss_put_mux,
2209},
2210WSS_DOUBLE("Mic Boost", 0,
2211 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
2212WSS_SINGLE("Loopback Capture Switch", 0,
2213 CS4231_LOOPBACK, 0, 1, 0),
2214WSS_SINGLE("Loopback Capture Volume", 0,
2215 CS4231_LOOPBACK, 2, 63, 1)
2216};
2217
2218static struct snd_kcontrol_new snd_opti93x_controls[] = {
2219WSS_DOUBLE("Master Playback Switch", 0,
2220 OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
2221WSS_DOUBLE("Master Playback Volume", 0,
2222 OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1),
2223WSS_DOUBLE("PCM Playback Switch", 0,
2224 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
2225WSS_DOUBLE("PCM Playback Volume", 0,
2226 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1),
2227WSS_DOUBLE("FM Playback Switch", 0,
2228 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
2229WSS_DOUBLE("FM Playback Volume", 0,
2230 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1),
2231WSS_DOUBLE("Line Playback Switch", 0,
2232 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
2233WSS_DOUBLE("Line Playback Volume", 0,
2234 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1),
2235WSS_DOUBLE("Mic Playback Switch", 0,
2236 OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
2237WSS_DOUBLE("Mic Playback Volume", 0,
2238 OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1),
2239WSS_DOUBLE("Mic Boost", 0,
2240 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
2241WSS_DOUBLE("CD Playback Switch", 0,
2242 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
2243WSS_DOUBLE("CD Playback Volume", 0,
2244 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1),
2245WSS_DOUBLE("Aux Playback Switch", 0,
2246 OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
2247WSS_DOUBLE("Aux Playback Volume", 0,
2248 OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1),
2249WSS_DOUBLE("Capture Volume", 0,
2250 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
2251{
2252 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2253 .name = "Capture Source",
2254 .info = snd_wss_info_mux,
2255 .get = snd_wss_get_mux,
2256 .put = snd_wss_put_mux,
2257}
2258};
2259
2260int snd_wss_mixer(struct snd_wss *chip)
2261{
2262 struct snd_card *card;
2263 unsigned int idx;
2264 int err;
2265
2266 if (snd_BUG_ON(!chip || !chip->pcm))
2267 return -EINVAL;
2268
2269 card = chip->card;
2270
2271 strcpy(card->mixername, chip->pcm->name);
2272
2273 if (chip->hardware == WSS_HW_OPTI93X)
2274 for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
2275 err = snd_ctl_add(card,
2276 snd_ctl_new1(&snd_opti93x_controls[idx],
2277 chip));
2278 if (err < 0)
2279 return err;
2280 }
2281 else if (chip->hardware & WSS_HW_AD1848_MASK)
2282 for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++) {
2283 err = snd_ctl_add(card,
2284 snd_ctl_new1(&snd_ad1848_controls[idx],
2285 chip));
2286 if (err < 0)
2287 return err;
2288 }
2289 else
2290 for (idx = 0; idx < ARRAY_SIZE(snd_wss_controls); idx++) {
2291 err = snd_ctl_add(card,
2292 snd_ctl_new1(&snd_wss_controls[idx],
2293 chip));
2294 if (err < 0)
2295 return err;
2296 }
2297 return 0;
2298}
2299EXPORT_SYMBOL(snd_wss_mixer);
2300
2301const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction)
2302{
2303 return direction == SNDRV_PCM_STREAM_PLAYBACK ?
2304 &snd_wss_playback_ops : &snd_wss_capture_ops;
2305}
2306EXPORT_SYMBOL(snd_wss_get_pcm_ops);
2307
2308/*
2309 * INIT part
2310 */
2311
2312static int __init alsa_wss_init(void)
2313{
2314 return 0;
2315}
2316
2317static void __exit alsa_wss_exit(void)
2318{
2319}
2320
2321module_init(alsa_wss_init);
2322module_exit(alsa_wss_exit);