diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-11 12:16:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-11 12:16:54 -0400 |
commit | d3570a5a7b8d0604fa012129f92637dc1534f62c (patch) | |
tree | 15d290595c363a2bdd4f4d6b3a2f7433e6e48f6d /sound/isa | |
parent | 37d9869ed928268409b48f52c57449918c0fd307 (diff) | |
parent | 72474be62d6ec2e0337ff01ecbd737f9c5c242c7 (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')
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 | ||
3 | config SND_AD1848_LIB | 3 | config SND_WSS_LIB |
4 | tristate | ||
5 | select SND_PCM | ||
6 | |||
7 | config 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 | ||
56 | config SND_AD1848 | 52 | config 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 | ||
97 | config SND_CMI8330 | 93 | config 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 | |||
108 | config SND_CS4231 | 104 | config 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 | |||
192 | config SND_SC6000 | 188 | config 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 | |||
228 | config SND_GUSMAX | 224 | config 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 | |||
315 | config SND_MIRO | 311 | config 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 | |||
364 | config SND_SB16_CSP | 360 | config 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 | ||
373 | config SND_SGALAXY | 369 | config 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 | |||
27 | obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o | 27 | obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o |
28 | 28 | ||
29 | obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ opti9xx/ \ | 29 | obj-$(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 | ||
395 | static unsigned long snd_ad1816a_timer_resolution(struct snd_timer *timer) | 395 | static 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 | ||
6 | snd-ad1848-lib-objs := ad1848_lib.o | ||
7 | snd-ad1848-objs := ad1848.o | 6 | snd-ad1848-objs := ad1848.o |
8 | 7 | ||
9 | # Toplevel Module Dependency | 8 | # Toplevel Module Dependency |
10 | obj-$(CONFIG_SND_AD1848) += snd-ad1848.o | 9 | obj-$(CONFIG_SND_AD1848) += snd-ad1848.o |
11 | obj-$(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) | |||
87 | static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) | 87 | static 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) | |||
142 | static int snd_ad1848_suspend(struct device *dev, unsigned int n, pm_message_t state) | 143 | static 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 | |||
152 | static int snd_ad1848_resume(struct device *dev, unsigned int n) | 153 | static 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 | |||
37 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
38 | MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248"); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | |||
41 | #if 0 | ||
42 | #define SNDRV_DEBUG_MCE | ||
43 | #endif | ||
44 | |||
45 | /* | ||
46 | * Some variables | ||
47 | */ | ||
48 | |||
49 | static 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 | |||
66 | static unsigned int rates[14] = { | ||
67 | 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050, | ||
68 | 27042, 32000, 33075, 37800, 44100, 48000 | ||
69 | }; | ||
70 | |||
71 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | ||
72 | .count = ARRAY_SIZE(rates), | ||
73 | .list = rates, | ||
74 | .mask = 0, | ||
75 | }; | ||
76 | |||
77 | static 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 | |||
101 | static 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 | |||
112 | void 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 | |||
129 | EXPORT_SYMBOL(snd_ad1848_out); | ||
130 | |||
131 | static 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 | |||
140 | static 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 | |||
155 | static 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 | |||
183 | static 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 | |||
203 | static 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 | |||
258 | static 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 | |||
271 | static 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 | |||
305 | static 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 | |||
316 | static 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 | |||
322 | static 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 | |||
340 | static 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 | |||
364 | static 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 | |||
376 | static 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 | |||
427 | static 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 | |||
464 | static 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 | |||
471 | static 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 | |||
478 | static 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 | |||
498 | static int snd_ad1848_playback_hw_free(struct snd_pcm_substream *substream) | ||
499 | { | ||
500 | return snd_pcm_lib_free_pages(substream); | ||
501 | } | ||
502 | |||
503 | static 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 | |||
522 | static 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 | |||
542 | static int snd_ad1848_capture_hw_free(struct snd_pcm_substream *substream) | ||
543 | { | ||
544 | return snd_pcm_lib_free_pages(substream); | ||
545 | } | ||
546 | |||
547 | static 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 | |||
566 | static 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 | |||
580 | static 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 | |||
591 | static 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 | |||
606 | static 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 | ||
627 | static 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 | |||
634 | static 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 | |||
654 | static 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 | |||
734 | static 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 | |||
753 | static 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 | |||
776 | static 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 | |||
792 | static 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 | |||
808 | static 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 | |||
818 | static 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 | |||
828 | static 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 | |||
841 | static 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 | |||
847 | static 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 | |||
858 | int 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 | |||
926 | EXPORT_SYMBOL(snd_ad1848_create); | ||
927 | |||
928 | static 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 | |||
939 | static 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 | |||
950 | int 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 | |||
975 | EXPORT_SYMBOL(snd_ad1848_pcm); | ||
976 | |||
977 | const 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 | |||
983 | EXPORT_SYMBOL(snd_ad1848_get_pcm_ops); | ||
984 | |||
985 | /* | ||
986 | * MIXER part | ||
987 | */ | ||
988 | |||
989 | static 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 | |||
1004 | static 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 | |||
1016 | static 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 | |||
1039 | static 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 | |||
1050 | static 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 | |||
1067 | static 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 | |||
1090 | static 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 | |||
1101 | static 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 | |||
1123 | static 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 | */ | ||
1162 | int 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 | |||
1203 | EXPORT_SYMBOL(snd_ad1848_add_ctl_elem); | ||
1204 | |||
1205 | static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); | ||
1206 | static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); | ||
1207 | static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); | ||
1208 | |||
1209 | static struct ad1848_mix_elem snd_ad1848_controls[] = { | ||
1210 | AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), | ||
1211 | AD1848_DOUBLE_TLV("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1, | ||
1212 | db_scale_6bit), | ||
1213 | AD1848_DOUBLE("Aux Playback Switch", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 7, 7, 1, 1), | ||
1214 | AD1848_DOUBLE_TLV("Aux Playback Volume", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 0, 0, 31, 1, | ||
1215 | db_scale_5bit_12db_max), | ||
1216 | AD1848_DOUBLE("Aux Playback Switch", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 7, 7, 1, 1), | ||
1217 | AD1848_DOUBLE_TLV("Aux Playback Volume", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 0, 0, 31, 1, | ||
1218 | db_scale_5bit_12db_max), | ||
1219 | AD1848_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 | }, | ||
1225 | AD1848_SINGLE("Loopback Capture Switch", 0, AD1848_LOOPBACK, 0, 1, 0), | ||
1226 | AD1848_SINGLE_TLV("Loopback Capture Volume", 0, AD1848_LOOPBACK, 1, 63, 0, | ||
1227 | db_scale_6bit), | ||
1228 | }; | ||
1229 | |||
1230 | int 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 | |||
1251 | EXPORT_SYMBOL(snd_ad1848_mixer); | ||
1252 | |||
1253 | /* | ||
1254 | * INIT part | ||
1255 | */ | ||
1256 | |||
1257 | static int __init alsa_ad1848_init(void) | ||
1258 | { | ||
1259 | return 0; | ||
1260 | } | ||
1261 | |||
1262 | static void __exit alsa_ad1848_exit(void) | ||
1263 | { | ||
1264 | } | ||
1265 | |||
1266 | module_init(alsa_ad1848_init) | ||
1267 | module_exit(alsa_ad1848_exit) | ||
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c index 154e728f592d..3e74d1a3928e 100644 --- a/sound/isa/azt2320.c +++ b/sound/isa/azt2320.c | |||
@@ -38,7 +38,7 @@ | |||
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 | ||
82 | static struct pnp_card_device_id snd_azt2320_pnpids[] = { | 82 | static 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 | ||
177 | static struct ad1848_mix_elem snd_cmi8330_controls[] __devinitdata = { | 177 | static struct snd_kcontrol_new snd_cmi8330_controls[] __devinitdata = { |
178 | AD1848_DOUBLE("Master Playback Volume", 0, CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0), | 178 | WSS_DOUBLE("Master Playback Volume", 0, |
179 | AD1848_SINGLE("Loud Playback Switch", 0, CMI8330_MUTEMUX, 6, 1, 1), | 179 | CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0), |
180 | AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), | 180 | WSS_SINGLE("Loud Playback Switch", 0, |
181 | AD1848_DOUBLE("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1), | 181 | CMI8330_MUTEMUX, 6, 1, 1), |
182 | AD1848_DOUBLE("Line Playback Switch", 0, CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0), | 182 | WSS_DOUBLE("PCM Playback Switch", 0, |
183 | AD1848_DOUBLE("Line Playback Volume", 0, CMI8330_LINVOL, CMI8330_LINVOL, 4, 0, 15, 0), | 183 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), |
184 | AD1848_DOUBLE("Line Capture Switch", 0, CMI8330_RMUX3D, CMI8330_RMUX3D, 2, 1, 1, 0), | 184 | WSS_DOUBLE("PCM Playback Volume", 0, |
185 | AD1848_DOUBLE("Line Capture Volume", 0, CMI8330_LINGAIN, CMI8330_LINGAIN, 4, 0, 15, 0), | 185 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), |
186 | AD1848_DOUBLE("CD Playback Switch", 0, CMI8330_MUTEMUX, CMI8330_MUTEMUX, 2, 1, 1, 0), | 186 | WSS_DOUBLE("Line Playback Switch", 0, |
187 | AD1848_DOUBLE("CD Capture Switch", 0, CMI8330_RMUX3D, CMI8330_RMUX3D, 4, 3, 1, 0), | 187 | CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0), |
188 | AD1848_DOUBLE("CD Playback Volume", 0, CMI8330_CDINVOL, CMI8330_CDINVOL, 4, 0, 15, 0), | 188 | WSS_DOUBLE("Line Playback Volume", 0, |
189 | AD1848_DOUBLE("CD Capture Volume", 0, CMI8330_CDINGAIN, CMI8330_CDINGAIN, 4, 0, 15, 0), | 189 | CMI8330_LINVOL, CMI8330_LINVOL, 4, 0, 15, 0), |
190 | AD1848_SINGLE("Mic Playback Switch", 0, CMI8330_MUTEMUX, 0, 1, 0), | 190 | WSS_DOUBLE("Line Capture Switch", 0, |
191 | AD1848_SINGLE("Mic Playback Volume", 0, CMI8330_OUTPUTVOL, 0, 7, 0), | 191 | CMI8330_RMUX3D, CMI8330_RMUX3D, 2, 1, 1, 0), |
192 | AD1848_SINGLE("Mic Capture Switch", 0, CMI8330_RMUX3D, 0, 1, 0), | 192 | WSS_DOUBLE("Line Capture Volume", 0, |
193 | AD1848_SINGLE("Mic Capture Volume", 0, CMI8330_OUTPUTVOL, 5, 7, 0), | 193 | CMI8330_LINGAIN, CMI8330_LINGAIN, 4, 0, 15, 0), |
194 | AD1848_DOUBLE("Wavetable Playback Switch", 0, CMI8330_RECMUX, CMI8330_RECMUX, 1, 0, 1, 0), | 194 | WSS_DOUBLE("CD Playback Switch", 0, |
195 | AD1848_DOUBLE("Wavetable Playback Volume", 0, CMI8330_WAVVOL, CMI8330_WAVVOL, 4, 0, 15, 0), | 195 | CMI8330_MUTEMUX, CMI8330_MUTEMUX, 2, 1, 1, 0), |
196 | AD1848_DOUBLE("Wavetable Capture Switch", 0, CMI8330_RECMUX, CMI8330_RECMUX, 5, 4, 1, 0), | 196 | WSS_DOUBLE("CD Capture Switch", 0, |
197 | AD1848_DOUBLE("Wavetable Capture Volume", 0, CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0), | 197 | CMI8330_RMUX3D, CMI8330_RMUX3D, 4, 3, 1, 0), |
198 | AD1848_SINGLE("3D Control - Switch", 0, CMI8330_RMUX3D, 5, 1, 1), | 198 | WSS_DOUBLE("CD Playback Volume", 0, |
199 | AD1848_SINGLE("PC Speaker Playback Volume", 0, CMI8330_OUTPUTVOL, 3, 3, 0), | 199 | CMI8330_CDINVOL, CMI8330_CDINVOL, 4, 0, 15, 0), |
200 | AD1848_SINGLE("FM Playback Switch", 0, CMI8330_RECMUX, 3, 1, 1), | 200 | WSS_DOUBLE("CD Capture Volume", 0, |
201 | AD1848_SINGLE(SNDRV_CTL_NAME_IEC958("Input ",CAPTURE,SWITCH), 0, CMI8330_RMUX3D, 7, 1, 1), | 201 | CMI8330_CDINGAIN, CMI8330_CDINGAIN, 4, 0, 15, 0), |
202 | AD1848_SINGLE(SNDRV_CTL_NAME_IEC958("Input ",PLAYBACK,SWITCH), 0, CMI8330_MUTEMUX, 7, 1, 1), | 202 | WSS_SINGLE("Mic Playback Switch", 0, |
203 | CMI8330_MUTEMUX, 0, 1, 0), | ||
204 | WSS_SINGLE("Mic Playback Volume", 0, | ||
205 | CMI8330_OUTPUTVOL, 0, 7, 0), | ||
206 | WSS_SINGLE("Mic Capture Switch", 0, | ||
207 | CMI8330_RMUX3D, 0, 1, 0), | ||
208 | WSS_SINGLE("Mic Capture Volume", 0, | ||
209 | CMI8330_OUTPUTVOL, 5, 7, 0), | ||
210 | WSS_DOUBLE("Wavetable Playback Switch", 0, | ||
211 | CMI8330_RECMUX, CMI8330_RECMUX, 1, 0, 1, 0), | ||
212 | WSS_DOUBLE("Wavetable Playback Volume", 0, | ||
213 | CMI8330_WAVVOL, CMI8330_WAVVOL, 4, 0, 15, 0), | ||
214 | WSS_DOUBLE("Wavetable Capture Switch", 0, | ||
215 | CMI8330_RECMUX, CMI8330_RECMUX, 5, 4, 1, 0), | ||
216 | WSS_DOUBLE("Wavetable Capture Volume", 0, | ||
217 | CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0), | ||
218 | WSS_SINGLE("3D Control - Switch", 0, | ||
219 | CMI8330_RMUX3D, 5, 1, 1), | ||
220 | WSS_SINGLE("PC Speaker Playback Volume", 0, | ||
221 | CMI8330_OUTPUTVOL, 3, 3, 0), | ||
222 | WSS_SINGLE("FM Playback Switch", 0, | ||
223 | CMI8330_RECMUX, 3, 1, 1), | ||
224 | WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", CAPTURE, SWITCH), 0, | ||
225 | CMI8330_RMUX3D, 7, 1, 1), | ||
226 | WSS_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 | ||
6 | snd-cs4231-lib-objs := cs4231_lib.o | ||
7 | snd-cs4236-lib-objs := cs4236_lib.o | 6 | snd-cs4236-lib-objs := cs4236_lib.o |
8 | snd-cs4231-objs := cs4231.o | 7 | snd-cs4231-objs := cs4231.o |
9 | snd-cs4232-objs := cs4232.o | 8 | snd-cs4232-objs := cs4232.o |
10 | snd-cs4236-objs := cs4236.o | 9 | snd-cs4236-objs := cs4236.o |
11 | 10 | ||
12 | # Toplevel Module Dependency | 11 | # Toplevel Module Dependency |
13 | obj-$(CONFIG_SND_CS4231_LIB) += snd-cs4231-lib.o | ||
14 | obj-$(CONFIG_SND_CS4231) += snd-cs4231.o | 12 | obj-$(CONFIG_SND_CS4231) += snd-cs4231.o |
15 | obj-$(CONFIG_SND_CS4232) += snd-cs4232.o | 13 | obj-$(CONFIG_SND_CS4232) += snd-cs4232.o |
16 | obj-$(CONFIG_SND_CS4236) += snd-cs4236.o snd-cs4236-lib.o | 14 | obj-$(CONFIG_SND_CS4236) += snd-cs4236.o snd-cs4236-lib.o |
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index e9462b9944be..ddd289120aa8 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c | |||
@@ -27,7 +27,7 @@ | |||
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) | |||
91 | static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n) | 91 | static 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) | |||
160 | static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t state) | 160 | static 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 | |||
170 | static int snd_cs4231_resume(struct device *dev, unsigned int n) | 170 | static 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 | |||
41 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
42 | MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips"); | ||
43 | MODULE_LICENSE("GPL"); | ||
44 | |||
45 | #if 0 | ||
46 | #define SNDRV_DEBUG_MCE | ||
47 | #endif | ||
48 | |||
49 | /* | ||
50 | * Some variables | ||
51 | */ | ||
52 | |||
53 | static 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 | |||
70 | static unsigned int rates[14] = { | ||
71 | 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050, | ||
72 | 27042, 32000, 33075, 37800, 44100, 48000 | ||
73 | }; | ||
74 | |||
75 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | ||
76 | .count = ARRAY_SIZE(rates), | ||
77 | .list = rates, | ||
78 | .mask = 0, | ||
79 | }; | ||
80 | |||
81 | static 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 | |||
86 | static 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 | |||
122 | static 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 | |||
162 | static inline void cs4231_outb(struct snd_cs4231 *chip, u8 offset, u8 val) | ||
163 | { | ||
164 | outb(val, chip->port + offset); | ||
165 | } | ||
166 | |||
167 | static inline u8 cs4231_inb(struct snd_cs4231 *chip, u8 offset) | ||
168 | { | ||
169 | return inb(chip->port + offset); | ||
170 | } | ||
171 | |||
172 | static 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 | |||
182 | static 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 | |||
201 | static 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 | |||
214 | void 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 | |||
229 | unsigned 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 | |||
241 | void 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 | |||
252 | unsigned 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 | |||
270 | static 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 | |||
314 | static 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 | |||
328 | void 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 | |||
348 | void 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 | |||
410 | static 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 | |||
425 | static 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 | |||
481 | static 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 | |||
492 | static 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 | |||
514 | static 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 | |||
548 | static 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 | |||
589 | static 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 | |||
636 | static 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 | |||
645 | static 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 | |||
663 | static 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 | |||
673 | static 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 | |||
731 | static 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 | |||
767 | static 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 | |||
818 | static 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 | |||
825 | static 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 | |||
832 | static 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 | |||
848 | static 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 | |||
863 | static int snd_cs4231_playback_hw_free(struct snd_pcm_substream *substream) | ||
864 | { | ||
865 | return snd_pcm_lib_free_pages(substream); | ||
866 | } | ||
867 | |||
868 | static 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 | |||
890 | static 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 | |||
905 | static int snd_cs4231_capture_hw_free(struct snd_pcm_substream *substream) | ||
906 | { | ||
907 | return snd_pcm_lib_free_pages(substream); | ||
908 | } | ||
909 | |||
910 | static 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 | |||
934 | void 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 | |||
946 | irqreturn_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 | |||
988 | static 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 | |||
999 | static 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 | |||
1014 | static 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 | |||
1181 | static 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 | |||
1202 | static 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 | |||
1227 | static 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 | |||
1264 | static 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 | |||
1297 | static 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 | |||
1306 | static 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 */ | ||
1318 | static 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 */ | ||
1331 | static 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 | |||
1373 | static 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 | |||
1396 | static 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 | |||
1402 | const 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 | |||
1423 | static 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 | |||
1455 | int 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 | |||
1542 | static 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 | |||
1553 | static 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 | |||
1564 | int 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 | |||
1598 | static void snd_cs4231_timer_free(struct snd_timer *timer) | ||
1599 | { | ||
1600 | struct snd_cs4231 *chip = timer->private_data; | ||
1601 | chip->timer = NULL; | ||
1602 | } | ||
1603 | |||
1604 | int 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 | |||
1632 | static 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 | |||
1662 | static 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 | |||
1674 | static 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 | |||
1697 | int 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 | |||
1708 | int 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 | |||
1725 | int 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 | |||
1748 | int 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 | |||
1759 | int 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 | |||
1781 | int 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 | |||
1812 | static struct snd_kcontrol_new snd_cs4231_controls[] = { | ||
1813 | CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), | ||
1814 | CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), | ||
1815 | CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), | ||
1816 | CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), | ||
1817 | CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), | ||
1818 | CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), | ||
1819 | CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), | ||
1820 | CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), | ||
1821 | CS4231_SINGLE("Mono Playback Switch", 0, CS4231_MONO_CTRL, 7, 1, 1), | ||
1822 | CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), | ||
1823 | CS4231_SINGLE("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, 6, 1, 1), | ||
1824 | CS4231_SINGLE("Mono Output Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0), | ||
1825 | CS4231_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 | }, | ||
1833 | CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0), | ||
1834 | CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0), | ||
1835 | CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1) | ||
1836 | }; | ||
1837 | |||
1838 | static struct snd_kcontrol_new snd_opti93x_controls[] = { | ||
1839 | CS4231_DOUBLE("Master Playback Switch", 0, | ||
1840 | OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1), | ||
1841 | CS4231_DOUBLE("Master Playback Volume", 0, | ||
1842 | OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1), | ||
1843 | CS4231_DOUBLE("PCM Playback Switch", 0, | ||
1844 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), | ||
1845 | CS4231_DOUBLE("PCM Playback Volume", 0, | ||
1846 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1), | ||
1847 | CS4231_DOUBLE("FM Playback Switch", 0, | ||
1848 | CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), | ||
1849 | CS4231_DOUBLE("FM Playback Volume", 0, | ||
1850 | CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1), | ||
1851 | CS4231_DOUBLE("Line Playback Switch", 0, | ||
1852 | CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), | ||
1853 | CS4231_DOUBLE("Line Playback Volume", 0, | ||
1854 | CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1), | ||
1855 | CS4231_DOUBLE("Mic Playback Switch", 0, | ||
1856 | OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1), | ||
1857 | CS4231_DOUBLE("Mic Playback Volume", 0, | ||
1858 | OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1), | ||
1859 | CS4231_DOUBLE("Mic Boost", 0, | ||
1860 | CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0), | ||
1861 | CS4231_DOUBLE("CD Playback Switch", 0, | ||
1862 | CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), | ||
1863 | CS4231_DOUBLE("CD Playback Volume", 0, | ||
1864 | CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1), | ||
1865 | CS4231_DOUBLE("Aux Playback Switch", 0, | ||
1866 | OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1), | ||
1867 | CS4231_DOUBLE("Aux Playback Volume", 0, | ||
1868 | OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1), | ||
1869 | CS4231_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 | |||
1880 | int 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 | |||
1911 | EXPORT_SYMBOL(snd_cs4231_out); | ||
1912 | EXPORT_SYMBOL(snd_cs4231_in); | ||
1913 | EXPORT_SYMBOL(snd_cs4236_ext_out); | ||
1914 | EXPORT_SYMBOL(snd_cs4236_ext_in); | ||
1915 | EXPORT_SYMBOL(snd_cs4231_mce_up); | ||
1916 | EXPORT_SYMBOL(snd_cs4231_mce_down); | ||
1917 | EXPORT_SYMBOL(snd_cs4231_overrange); | ||
1918 | EXPORT_SYMBOL(snd_cs4231_interrupt); | ||
1919 | EXPORT_SYMBOL(snd_cs4231_chip_id); | ||
1920 | EXPORT_SYMBOL(snd_cs4231_create); | ||
1921 | EXPORT_SYMBOL(snd_cs4231_pcm); | ||
1922 | EXPORT_SYMBOL(snd_cs4231_mixer); | ||
1923 | EXPORT_SYMBOL(snd_cs4231_timer); | ||
1924 | EXPORT_SYMBOL(snd_cs4231_info_single); | ||
1925 | EXPORT_SYMBOL(snd_cs4231_get_single); | ||
1926 | EXPORT_SYMBOL(snd_cs4231_put_single); | ||
1927 | EXPORT_SYMBOL(snd_cs4231_info_double); | ||
1928 | EXPORT_SYMBOL(snd_cs4231_get_double); | ||
1929 | EXPORT_SYMBOL(snd_cs4231_put_double); | ||
1930 | |||
1931 | /* | ||
1932 | * INIT part | ||
1933 | */ | ||
1934 | |||
1935 | static int __init alsa_cs4231_init(void) | ||
1936 | { | ||
1937 | return 0; | ||
1938 | } | ||
1939 | |||
1940 | static void __exit alsa_cs4231_exit(void) | ||
1941 | { | ||
1942 | } | ||
1943 | |||
1944 | module_init(alsa_cs4231_init) | ||
1945 | module_exit(alsa_cs4231_exit) | ||
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 4d4b8ddc26ba..91f9c15d3e30 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c | |||
@@ -26,7 +26,7 @@ | |||
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 | ||
136 | struct snd_card_cs4236 { | 136 | struct 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 | ||
91 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 91 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
@@ -121,13 +121,14 @@ static unsigned char snd_cs4236_ext_map[18] = { | |||
121 | * | 121 | * |
122 | */ | 122 | */ |
123 | 123 | ||
124 | static void snd_cs4236_ctrl_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val) | 124 | static 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 | ||
130 | static unsigned char snd_cs4236_ctrl_in(struct snd_cs4231 *chip, unsigned char reg) | 131 | static 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 | ||
183 | static void snd_cs4236_playback_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, unsigned char pdfr) | 184 | static 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 | ||
197 | static void snd_cs4236_capture_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, unsigned char cdfr) | 202 | static 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 | ||
213 | static void snd_cs4236_suspend(struct snd_cs4231 *chip) | 222 | static 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 | ||
228 | static void snd_cs4236_resume(struct snd_cs4231 *chip) | 237 | static 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 | ||
354 | int snd_cs4236_pcm(struct snd_cs4231 *chip, int device, struct snd_pcm **rpcm) | 365 | int 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 | ||
388 | static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 400 | static 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 | ||
405 | static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 417 | static 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 | ||
434 | static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 446 | static 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 | ||
451 | static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 463 | static 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 | ||
491 | static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 503 | static 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 | ||
513 | static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 525 | static 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 | ||
556 | static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 568 | static 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 | ||
578 | static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 590 | static 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 | ||
620 | static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 632 | static 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 | ||
632 | static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 644 | static 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 | ||
679 | static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 691 | static 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 | ||
691 | static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 703 | static 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 | ||
710 | static struct snd_kcontrol_new snd_cs4236_controls[] = { | 722 | static struct snd_kcontrol_new snd_cs4236_controls[] = { |
711 | 723 | ||
712 | CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1), | 724 | CS4236_DOUBLE("Master Digital Playback Switch", 0, |
713 | CS4236_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), |
726 | CS4236_DOUBLE("Master Digital Capture Switch", 0, | ||
727 | CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1), | ||
714 | CS4236_MASTER_DIGITAL("Master Digital Volume", 0), | 728 | CS4236_MASTER_DIGITAL("Master Digital Volume", 0), |
715 | 729 | ||
716 | CS4236_DOUBLE("Capture Boost Volume", 0, CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1), | 730 | CS4236_DOUBLE("Capture Boost Volume", 0, |
717 | 731 | CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1), | |
718 | CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), | 732 | |
719 | CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), | 733 | WSS_DOUBLE("PCM Playback Switch", 0, |
720 | 734 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), | |
721 | CS4236_DOUBLE("DSP Playback Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), | 735 | WSS_DOUBLE("PCM Playback Volume", 0, |
722 | CS4236_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 | ||
724 | CS4236_DOUBLE("FM Playback Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1), | 738 | CS4236_DOUBLE("DSP Playback Switch", 0, |
725 | CS4236_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 | 740 | CS4236_DOUBLE("DSP Playback Volume", 0, | |
727 | CS4236_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), |
728 | CS4236_DOUBLE("Wavetable Playback Volume", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1), | 742 | |
729 | 743 | CS4236_DOUBLE("FM Playback Switch", 0, | |
730 | CS4231_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), |
731 | CS4231_DOUBLE("Synth Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), | 745 | CS4236_DOUBLE("FM Playback Volume", 0, |
732 | CS4231_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), |
733 | CS4231_DOUBLE("Synth Capture Bypass", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1), | 747 | |
734 | 748 | CS4236_DOUBLE("Wavetable Playback Switch", 0, | |
735 | CS4236_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), |
736 | CS4236_DOUBLE("Mic Capture Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), | 750 | CS4236_DOUBLE("Wavetable Playback Volume", 0, |
751 | CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1), | ||
752 | |||
753 | WSS_DOUBLE("Synth Playback Switch", 0, | ||
754 | CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), | ||
755 | WSS_DOUBLE("Synth Volume", 0, | ||
756 | CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), | ||
757 | WSS_DOUBLE("Synth Capture Switch", 0, | ||
758 | CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), | ||
759 | WSS_DOUBLE("Synth Capture Bypass", 0, | ||
760 | CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1), | ||
761 | |||
762 | CS4236_DOUBLE("Mic Playback Switch", 0, | ||
763 | CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), | ||
764 | CS4236_DOUBLE("Mic Capture Switch", 0, | ||
765 | CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), | ||
737 | CS4236_DOUBLE("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 0, 0, 31, 1), | 766 | CS4236_DOUBLE("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 0, 0, 31, 1), |
738 | CS4236_DOUBLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0), | 767 | CS4236_DOUBLE("Mic Playback Boost", 0, |
739 | 768 | CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0), | |
740 | CS4231_DOUBLE("Line Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), | 769 | |
741 | CS4231_DOUBLE("Line Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), | 770 | WSS_DOUBLE("Line Playback Switch", 0, |
742 | CS4231_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), |
743 | CS4231_DOUBLE("Line Capture Bypass", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1), | 772 | WSS_DOUBLE("Line Volume", 0, |
744 | 773 | CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), | |
745 | CS4231_DOUBLE("CD Playback Switch", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), | 774 | WSS_DOUBLE("Line Capture Switch", 0, |
746 | CS4231_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), |
747 | CS4231_DOUBLE("CD Capture Switch", 0, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), | 776 | WSS_DOUBLE("Line Capture Bypass", 0, |
748 | 777 | CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1), | |
749 | CS4236_DOUBLE1("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1), | 778 | |
750 | CS4236_DOUBLE1("Mono Playback Switch", 0, CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), | 779 | WSS_DOUBLE("CD Playback Switch", 0, |
751 | CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), | 780 | CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), |
752 | CS4231_SINGLE("Mono Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0), | 781 | WSS_DOUBLE("CD Volume", 0, |
753 | 782 | CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), | |
754 | CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), | 783 | WSS_DOUBLE("CD Capture Switch", 0, |
755 | CS4231_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 | ||
757 | CS4231_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0), | 786 | CS4236_DOUBLE1("Mono Output Playback Switch", 0, |
758 | CS4236_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), |
788 | CS4236_DOUBLE1("Mono Playback Switch", 0, | ||
789 | CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), | ||
790 | WSS_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), | ||
791 | WSS_SINGLE("Mono Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0), | ||
792 | |||
793 | WSS_DOUBLE("Capture Volume", 0, | ||
794 | CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), | ||
795 | WSS_DOUBLE("Analog Loopback Capture Switch", 0, | ||
796 | CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), | ||
797 | |||
798 | WSS_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0), | ||
799 | CS4236_DOUBLE1("Digital Loopback Playback Volume", 0, | ||
800 | CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1) | ||
759 | }; | 801 | }; |
760 | 802 | ||
761 | static struct snd_kcontrol_new snd_cs4235_controls[] = { | 803 | static struct snd_kcontrol_new snd_cs4235_controls[] = { |
762 | 804 | ||
763 | CS4231_DOUBLE("Master Switch", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1), | 805 | WSS_DOUBLE("Master Switch", 0, |
764 | CS4231_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), |
807 | WSS_DOUBLE("Master Volume", 0, | ||
808 | CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1), | ||
765 | 809 | ||
766 | CS4235_OUTPUT_ACCU("Playback Volume", 0), | 810 | CS4235_OUTPUT_ACCU("Playback Volume", 0), |
767 | 811 | ||
768 | CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1), | 812 | CS4236_DOUBLE("Master Digital Playback Switch", 0, |
769 | CS4236_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), |
814 | CS4236_DOUBLE("Master Digital Capture Switch", 0, | ||
815 | CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1), | ||
770 | CS4236_MASTER_DIGITAL("Master Digital Volume", 0), | 816 | CS4236_MASTER_DIGITAL("Master Digital Volume", 0), |
771 | 817 | ||
772 | CS4231_DOUBLE("Master Digital Playback Switch", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), | 818 | WSS_DOUBLE("Master Digital Playback Switch", 1, |
773 | CS4231_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), |
774 | CS4231_DOUBLE("Master Digital Volume", 1, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), | 820 | WSS_DOUBLE("Master Digital Capture Switch", 1, |
821 | CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), | ||
822 | WSS_DOUBLE("Master Digital Volume", 1, | ||
823 | CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), | ||
775 | 824 | ||
776 | CS4236_DOUBLE("Capture Volume", 0, CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1), | 825 | CS4236_DOUBLE("Capture Volume", 0, |
826 | CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1), | ||
777 | 827 | ||
778 | CS4231_DOUBLE("PCM Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), | 828 | WSS_DOUBLE("PCM Switch", 0, |
779 | CS4231_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), |
830 | WSS_DOUBLE("PCM Volume", 0, | ||
831 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), | ||
780 | 832 | ||
781 | CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), | 833 | CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), |
782 | 834 | ||
783 | CS4236_DOUBLE("FM Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1), | 835 | CS4236_DOUBLE("FM Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1), |
784 | 836 | ||
785 | CS4236_DOUBLE("Wavetable Switch", 0, CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1), | 837 | CS4236_DOUBLE("Wavetable Switch", 0, |
838 | CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1), | ||
786 | 839 | ||
787 | CS4236_DOUBLE("Mic Capture Switch", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), | 840 | CS4236_DOUBLE("Mic Capture Switch", 0, |
788 | CS4236_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), |
842 | CS4236_DOUBLE("Mic Playback Switch", 0, | ||
843 | CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), | ||
789 | CS4236_SINGLE("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1), | 844 | CS4236_SINGLE("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1), |
790 | CS4236_SINGLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, 5, 1, 0), | 845 | CS4236_SINGLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, 5, 1, 0), |
791 | 846 | ||
792 | CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), | 847 | WSS_DOUBLE("Aux Playback Switch", 0, |
793 | CS4231_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), |
794 | CS4231_DOUBLE("Aux Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), | 849 | WSS_DOUBLE("Aux Capture Switch", 0, |
795 | 850 | CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), | |
796 | CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), | 851 | WSS_DOUBLE("Aux Volume", 0, |
797 | CS4231_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), |
798 | CS4231_DOUBLE("Aux Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), | 853 | |
799 | 854 | WSS_DOUBLE("Aux Playback Switch", 1, | |
800 | CS4236_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 | 856 | WSS_DOUBLE("Aux Capture Switch", 1, | |
802 | CS4236_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), |
803 | CS4231_SINGLE("Mono Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), | 858 | WSS_DOUBLE("Aux Volume", 1, |
804 | 859 | CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), | |
805 | CS4231_DOUBLE("Analog Loopback Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), | 860 | |
861 | CS4236_DOUBLE1("Master Mono Switch", 0, | ||
862 | CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1), | ||
863 | |||
864 | CS4236_DOUBLE1("Mono Switch", 0, | ||
865 | CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), | ||
866 | WSS_SINGLE("Mono Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), | ||
867 | |||
868 | WSS_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 | ||
814 | static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 878 | static 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 | ||
834 | static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 898 | static 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), | |||
896 | CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0) | 960 | CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0) |
897 | }; | 961 | }; |
898 | 962 | ||
899 | int snd_cs4236_mixer(struct snd_cs4231 *chip) | 963 | int 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 ) \ | 143 | static int __devinit snd_gusmax_mixer(struct snd_wss *chip) |
144 | ((left << 24)|(right << 16)|(shift<<8)|mute) | ||
145 | |||
146 | static 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 | ||
500 | static struct snd_kcontrol_new snd_interwave_controls[] = { | 500 | static struct snd_kcontrol_new snd_interwave_controls[] = { |
501 | CS4231_DOUBLE("Master Playback Switch", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1), | 501 | WSS_DOUBLE("Master Playback Switch", 0, |
502 | CS4231_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), |
503 | CS4231_DOUBLE("Mic Playback Switch", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1), | 503 | WSS_DOUBLE("Master Playback Volume", 0, |
504 | CS4231_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), |
505 | WSS_DOUBLE("Mic Playback Switch", 0, | ||
506 | CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1), | ||
507 | WSS_DOUBLE("Mic Playback Volume", 0, | ||
508 | CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1) | ||
505 | }; | 509 | }; |
506 | 510 | ||
507 | static int __devinit snd_interwave_mixer(struct snd_cs4231 *chip) | 511 | static 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 | ||
126 | struct snd_opl3sa2 { | 126 | struct 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 | ||
225 | static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip) | 224 | static 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) | |||
298 | static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id) | 296 | static 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 | ||
351 | static 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 | |||
362 | static int snd_opl3sa2_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 353 | static 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 | ||
417 | static 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 | |||
428 | static int snd_opl3sa2_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 408 | static 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 | ||
515 | static int __devinit snd_opl3sa2_mixer(struct snd_opl3sa2 *chip) | 495 | static 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 | ||
563 | static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id) | 555 | static 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) | |||
669 | static int snd_sb16_set_dma_mode(struct snd_sb *chip, int what) | 669 | static 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[] = { | |||
925 | static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) | 926 | static 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) | |||
933 | static void restore_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) | 935 | static 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 | ||
400 | static int __devinit snd_sc6000_mixer(struct snd_ad1848 *chip) | 400 | static 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 | ||
178 | static struct ad1848_mix_elem snd_sgalaxy_controls[] = { | 178 | static struct snd_kcontrol_new snd_sgalaxy_controls[] = { |
179 | AD1848_DOUBLE("Aux Playback Switch", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7, 7, 1, 1), | 179 | WSS_DOUBLE("Aux Playback Switch", 0, |
180 | AD1848_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), |
181 | WSS_DOUBLE("Aux Playback Volume", 0, | ||
182 | SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0) | ||
181 | }; | 183 | }; |
182 | 184 | ||
183 | static int __devinit snd_sgalaxy_mixer(struct snd_ad1848 *chip) | 185 | static 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, | |||
322 | static int snd_sgalaxy_resume(struct device *pdev, unsigned int n) | 329 | static 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, | |||
726 | static int sscape_midi_get(struct snd_kcontrol *kctl, | 726 | static 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, | |||
746 | static int sscape_midi_put(struct snd_kcontrol *kctl, | 746 | static 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 | */ |
961 | static void ad1845_playback_format(struct snd_cs4231 * chip, struct snd_pcm_hw_params *params, unsigned char format) | 961 | static 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 | */ |
997 | static void ad1845_capture_format(struct snd_cs4231 * chip, struct snd_pcm_hw_params *params, unsigned char format) | 999 | static 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 | ||
34 | MODULE_AUTHOR("Paul Barton-Davis <pbd@op.net>"); | 35 | MODULE_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 | |||
363 | snd_wavefront_probe (struct snd_card *card, int dev) | 364 | snd_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 |
603 | static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard, | 605 | static 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 | |||
6 | snd-wss-lib-objs := wss_lib.o | ||
7 | |||
8 | # Toplevel Module Dependency | ||
9 | obj-$(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 | |||
42 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
43 | MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips"); | ||
44 | MODULE_LICENSE("GPL"); | ||
45 | |||
46 | #if 0 | ||
47 | #define SNDRV_DEBUG_MCE | ||
48 | #endif | ||
49 | |||
50 | /* | ||
51 | * Some variables | ||
52 | */ | ||
53 | |||
54 | static 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 | |||
71 | static unsigned int rates[14] = { | ||
72 | 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050, | ||
73 | 27042, 32000, 33075, 37800, 44100, 48000 | ||
74 | }; | ||
75 | |||
76 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | ||
77 | .count = ARRAY_SIZE(rates), | ||
78 | .list = rates, | ||
79 | .mask = 0, | ||
80 | }; | ||
81 | |||
82 | static 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 | |||
88 | static 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 | |||
124 | static 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 | |||
164 | static inline void wss_outb(struct snd_wss *chip, u8 offset, u8 val) | ||
165 | { | ||
166 | outb(val, chip->port + offset); | ||
167 | } | ||
168 | |||
169 | static inline u8 wss_inb(struct snd_wss *chip, u8 offset) | ||
170 | { | ||
171 | return inb(chip->port + offset); | ||
172 | } | ||
173 | |||
174 | static 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 | |||
184 | static 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 | |||
203 | static 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 | |||
217 | void 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 | } | ||
231 | EXPORT_SYMBOL(snd_wss_out); | ||
232 | |||
233 | unsigned 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 | } | ||
244 | EXPORT_SYMBOL(snd_wss_in); | ||
245 | |||
246 | void 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 | } | ||
258 | EXPORT_SYMBOL(snd_cs4236_ext_out); | ||
259 | |||
260 | unsigned 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 | } | ||
276 | EXPORT_SYMBOL(snd_cs4236_ext_in); | ||
277 | |||
278 | #if 0 | ||
279 | |||
280 | static 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 | |||
375 | static 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 | |||
389 | void 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 | } | ||
409 | EXPORT_SYMBOL(snd_wss_mce_up); | ||
410 | |||
411 | void 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 | } | ||
471 | EXPORT_SYMBOL(snd_wss_mce_down); | ||
472 | |||
473 | static 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 | |||
488 | static 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 | |||
540 | static 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 | |||
551 | static 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 | |||
573 | static 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 | |||
625 | static 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 | |||
670 | static 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 | |||
725 | static 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 | |||
734 | static 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 | |||
758 | static 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 | |||
770 | static 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 | |||
836 | static 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 | |||
878 | static 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 | |||
932 | static 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 | |||
939 | static 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 | |||
946 | static 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 | |||
962 | static 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 | |||
978 | static int snd_wss_playback_hw_free(struct snd_pcm_substream *substream) | ||
979 | { | ||
980 | return snd_pcm_lib_free_pages(substream); | ||
981 | } | ||
982 | |||
983 | static 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 | |||
1005 | static 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 | |||
1021 | static int snd_wss_capture_hw_free(struct snd_pcm_substream *substream) | ||
1022 | { | ||
1023 | return snd_pcm_lib_free_pages(substream); | ||
1024 | } | ||
1025 | |||
1026 | static 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 | |||
1058 | void 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 | } | ||
1069 | EXPORT_SYMBOL(snd_wss_overrange); | ||
1070 | |||
1071 | irqreturn_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 | } | ||
1120 | EXPORT_SYMBOL(snd_wss_interrupt); | ||
1121 | |||
1122 | static 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 | |||
1133 | static 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 | |||
1148 | static 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; | ||
1223 | out_mode: | ||
1224 | snd_wss_dout(chip, CS4231_MISC_INFO, 0); | ||
1225 | out: | ||
1226 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1227 | return err; | ||
1228 | } | ||
1229 | |||
1230 | static 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 | |||
1401 | static 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 | |||
1422 | static 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 | |||
1447 | static 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 | |||
1490 | static 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 | |||
1531 | static 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 | |||
1540 | static 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 | |||
1549 | static 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 */ | ||
1572 | static 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 */ | ||
1587 | static 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 | |||
1631 | static 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 | |||
1655 | static 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 | |||
1661 | const 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 | } | ||
1704 | EXPORT_SYMBOL(snd_wss_chip_id); | ||
1705 | |||
1706 | static 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 | |||
1742 | int 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 | } | ||
1843 | EXPORT_SYMBOL(snd_wss_create); | ||
1844 | |||
1845 | static 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 | |||
1856 | static 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 | |||
1867 | int 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 | } | ||
1897 | EXPORT_SYMBOL(snd_wss_pcm); | ||
1898 | |||
1899 | static void snd_wss_timer_free(struct snd_timer *timer) | ||
1900 | { | ||
1901 | struct snd_wss *chip = timer->private_data; | ||
1902 | chip->timer = NULL; | ||
1903 | } | ||
1904 | |||
1905 | int 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 | } | ||
1928 | EXPORT_SYMBOL(snd_wss_timer); | ||
1929 | |||
1930 | /* | ||
1931 | * MIXER part | ||
1932 | */ | ||
1933 | |||
1934 | static 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 | |||
1970 | static 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 | |||
1983 | static 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 | |||
2007 | int 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 | } | ||
2018 | EXPORT_SYMBOL(snd_wss_info_single); | ||
2019 | |||
2020 | int 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 | } | ||
2037 | EXPORT_SYMBOL(snd_wss_get_single); | ||
2038 | |||
2039 | int 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 | } | ||
2062 | EXPORT_SYMBOL(snd_wss_put_single); | ||
2063 | |||
2064 | int 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 | } | ||
2075 | EXPORT_SYMBOL(snd_wss_info_double); | ||
2076 | |||
2077 | int 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 | } | ||
2099 | EXPORT_SYMBOL(snd_wss_get_double); | ||
2100 | |||
2101 | int 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 | } | ||
2140 | EXPORT_SYMBOL(snd_wss_put_double); | ||
2141 | |||
2142 | static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); | ||
2143 | static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); | ||
2144 | static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); | ||
2145 | |||
2146 | static struct snd_kcontrol_new snd_ad1848_controls[] = { | ||
2147 | WSS_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, | ||
2148 | 7, 7, 1, 1), | ||
2149 | WSS_DOUBLE_TLV("PCM Playback Volume", 0, | ||
2150 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1, | ||
2151 | db_scale_6bit), | ||
2152 | WSS_DOUBLE("Aux Playback Switch", 0, | ||
2153 | CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), | ||
2154 | WSS_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), | ||
2157 | WSS_DOUBLE("Aux Playback Switch", 1, | ||
2158 | CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), | ||
2159 | WSS_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), | ||
2162 | WSS_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 | }, | ||
2171 | WSS_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0), | ||
2172 | WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 1, 63, 0, | ||
2173 | db_scale_6bit), | ||
2174 | }; | ||
2175 | |||
2176 | static struct snd_kcontrol_new snd_wss_controls[] = { | ||
2177 | WSS_DOUBLE("PCM Playback Switch", 0, | ||
2178 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), | ||
2179 | WSS_DOUBLE("PCM Playback Volume", 0, | ||
2180 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), | ||
2181 | WSS_DOUBLE("Line Playback Switch", 0, | ||
2182 | CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), | ||
2183 | WSS_DOUBLE("Line Playback Volume", 0, | ||
2184 | CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), | ||
2185 | WSS_DOUBLE("Aux Playback Switch", 0, | ||
2186 | CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), | ||
2187 | WSS_DOUBLE("Aux Playback Volume", 0, | ||
2188 | CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), | ||
2189 | WSS_DOUBLE("Aux Playback Switch", 1, | ||
2190 | CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), | ||
2191 | WSS_DOUBLE("Aux Playback Volume", 1, | ||
2192 | CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), | ||
2193 | WSS_SINGLE("Mono Playback Switch", 0, | ||
2194 | CS4231_MONO_CTRL, 7, 1, 1), | ||
2195 | WSS_SINGLE("Mono Playback Volume", 0, | ||
2196 | CS4231_MONO_CTRL, 0, 15, 1), | ||
2197 | WSS_SINGLE("Mono Output Playback Switch", 0, | ||
2198 | CS4231_MONO_CTRL, 6, 1, 1), | ||
2199 | WSS_SINGLE("Mono Output Playback Bypass", 0, | ||
2200 | CS4231_MONO_CTRL, 5, 1, 0), | ||
2201 | WSS_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 | }, | ||
2210 | WSS_DOUBLE("Mic Boost", 0, | ||
2211 | CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0), | ||
2212 | WSS_SINGLE("Loopback Capture Switch", 0, | ||
2213 | CS4231_LOOPBACK, 0, 1, 0), | ||
2214 | WSS_SINGLE("Loopback Capture Volume", 0, | ||
2215 | CS4231_LOOPBACK, 2, 63, 1) | ||
2216 | }; | ||
2217 | |||
2218 | static struct snd_kcontrol_new snd_opti93x_controls[] = { | ||
2219 | WSS_DOUBLE("Master Playback Switch", 0, | ||
2220 | OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1), | ||
2221 | WSS_DOUBLE("Master Playback Volume", 0, | ||
2222 | OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1), | ||
2223 | WSS_DOUBLE("PCM Playback Switch", 0, | ||
2224 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), | ||
2225 | WSS_DOUBLE("PCM Playback Volume", 0, | ||
2226 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1), | ||
2227 | WSS_DOUBLE("FM Playback Switch", 0, | ||
2228 | CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), | ||
2229 | WSS_DOUBLE("FM Playback Volume", 0, | ||
2230 | CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1), | ||
2231 | WSS_DOUBLE("Line Playback Switch", 0, | ||
2232 | CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), | ||
2233 | WSS_DOUBLE("Line Playback Volume", 0, | ||
2234 | CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1), | ||
2235 | WSS_DOUBLE("Mic Playback Switch", 0, | ||
2236 | OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1), | ||
2237 | WSS_DOUBLE("Mic Playback Volume", 0, | ||
2238 | OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1), | ||
2239 | WSS_DOUBLE("Mic Boost", 0, | ||
2240 | CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0), | ||
2241 | WSS_DOUBLE("CD Playback Switch", 0, | ||
2242 | CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), | ||
2243 | WSS_DOUBLE("CD Playback Volume", 0, | ||
2244 | CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1), | ||
2245 | WSS_DOUBLE("Aux Playback Switch", 0, | ||
2246 | OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1), | ||
2247 | WSS_DOUBLE("Aux Playback Volume", 0, | ||
2248 | OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1), | ||
2249 | WSS_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 | |||
2260 | int 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 | } | ||
2299 | EXPORT_SYMBOL(snd_wss_mixer); | ||
2300 | |||
2301 | const 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 | } | ||
2306 | EXPORT_SYMBOL(snd_wss_get_pcm_ops); | ||
2307 | |||
2308 | /* | ||
2309 | * INIT part | ||
2310 | */ | ||
2311 | |||
2312 | static int __init alsa_wss_init(void) | ||
2313 | { | ||
2314 | return 0; | ||
2315 | } | ||
2316 | |||
2317 | static void __exit alsa_wss_exit(void) | ||
2318 | { | ||
2319 | } | ||
2320 | |||
2321 | module_init(alsa_wss_init); | ||
2322 | module_exit(alsa_wss_exit); | ||