diff options
Diffstat (limited to 'sound/isa')
58 files changed, 1189 insertions, 498 deletions
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index ea5084abe60f..2639a6ab8f2e 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig | |||
@@ -191,6 +191,19 @@ config SND_ES18XX | |||
191 | To compile this driver as a module, choose M here: the module | 191 | To compile this driver as a module, choose M here: the module |
192 | will be called snd-es18xx. | 192 | will be called snd-es18xx. |
193 | 193 | ||
194 | config SND_SC6000 | ||
195 | tristate "Gallant SC-6000, Audio Excel DSP 16" | ||
196 | depends on SND && HAS_IOPORT | ||
197 | select SND_AD1848_LIB | ||
198 | select SND_OPL3_LIB | ||
199 | select SND_MPU401_UART | ||
200 | help | ||
201 | Say Y here to include support for Gallant SC-6000 card and clones: | ||
202 | Audio Excel DSP 16 and Zoltrix AV302. | ||
203 | |||
204 | To compile this driver as a module, choose M here: the module | ||
205 | will be called snd-sc6000. | ||
206 | |||
194 | config SND_GUS_SYNTH | 207 | config SND_GUS_SYNTH |
195 | tristate | 208 | tristate |
196 | 209 | ||
@@ -414,7 +427,7 @@ config SND_SSCAPE | |||
414 | config SND_WAVEFRONT | 427 | config SND_WAVEFRONT |
415 | tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)" | 428 | tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)" |
416 | depends on SND | 429 | depends on SND |
417 | select FW_LOADER if !SND_WAVEFRONT_FIRMWARE_IN_KERNEL | 430 | select FW_LOADER |
418 | select SND_OPL3_LIB | 431 | select SND_OPL3_LIB |
419 | select SND_MPU401_UART | 432 | select SND_MPU401_UART |
420 | select SND_CS4231_LIB | 433 | select SND_CS4231_LIB |
@@ -430,8 +443,9 @@ config SND_WAVEFRONT_FIRMWARE_IN_KERNEL | |||
430 | depends on SND_WAVEFRONT | 443 | depends on SND_WAVEFRONT |
431 | default y | 444 | default y |
432 | help | 445 | help |
433 | Say Y here to include the static firmware built in the kernel | 446 | Say Y here to include the static firmware for FX DSP built in |
434 | for the Wavefront driver. If you choose N here, you need to | 447 | the kernel for the Wavefront driver. If you choose N here, |
435 | install the firmware files from the alsa-firmware package. | 448 | you need to install the firmware files from the |
449 | alsa-firmware package. | ||
436 | 450 | ||
437 | endmenu | 451 | endmenu |
diff --git a/sound/isa/Makefile b/sound/isa/Makefile index bb317ccc170f..c0ce7db2a1b5 100644 --- a/sound/isa/Makefile +++ b/sound/isa/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-adlib-objs := adlib.o | 6 | snd-adlib-objs := adlib.o |
@@ -10,6 +10,7 @@ snd-cmi8330-objs := cmi8330.o | |||
10 | snd-dt019x-objs := dt019x.o | 10 | snd-dt019x-objs := dt019x.o |
11 | snd-es18xx-objs := es18xx.o | 11 | snd-es18xx-objs := es18xx.o |
12 | snd-opl3sa2-objs := opl3sa2.o | 12 | snd-opl3sa2-objs := opl3sa2.o |
13 | snd-sc6000-objs := sc6000.o | ||
13 | snd-sgalaxy-objs := sgalaxy.o | 14 | snd-sgalaxy-objs := sgalaxy.o |
14 | snd-sscape-objs := sscape.o | 15 | snd-sscape-objs := sscape.o |
15 | 16 | ||
@@ -21,6 +22,7 @@ obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o | |||
21 | obj-$(CONFIG_SND_DT019X) += snd-dt019x.o | 22 | obj-$(CONFIG_SND_DT019X) += snd-dt019x.o |
22 | obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o | 23 | obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o |
23 | obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o | 24 | obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o |
25 | obj-$(CONFIG_SND_SC6000) += snd-sc6000.o | ||
24 | obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o | 26 | obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o |
25 | obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o | 27 | obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o |
26 | 28 | ||
diff --git a/sound/isa/ad1816a/Makefile b/sound/isa/ad1816a/Makefile index 90e00e842e49..487ab23860e3 100644 --- a/sound/isa/ad1816a/Makefile +++ b/sound/isa/ad1816a/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ad1816a-objs := ad1816a.o ad1816a_lib.o | 6 | snd-ad1816a-objs := ad1816a.o ad1816a_lib.o |
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index ec9209cd5177..cf18fe4617a1 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c | |||
@@ -453,7 +453,6 @@ static int snd_ad1816a_playback_open(struct snd_pcm_substream *substream) | |||
453 | 453 | ||
454 | if ((error = snd_ad1816a_open(chip, AD1816A_MODE_PLAYBACK)) < 0) | 454 | if ((error = snd_ad1816a_open(chip, AD1816A_MODE_PLAYBACK)) < 0) |
455 | return error; | 455 | return error; |
456 | snd_pcm_set_sync(substream); | ||
457 | runtime->hw = snd_ad1816a_playback; | 456 | runtime->hw = snd_ad1816a_playback; |
458 | snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max); | 457 | snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max); |
459 | snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max); | 458 | snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max); |
@@ -469,7 +468,6 @@ static int snd_ad1816a_capture_open(struct snd_pcm_substream *substream) | |||
469 | 468 | ||
470 | if ((error = snd_ad1816a_open(chip, AD1816A_MODE_CAPTURE)) < 0) | 469 | if ((error = snd_ad1816a_open(chip, AD1816A_MODE_CAPTURE)) < 0) |
471 | return error; | 470 | return error; |
472 | snd_pcm_set_sync(substream); | ||
473 | runtime->hw = snd_ad1816a_capture; | 471 | runtime->hw = snd_ad1816a_capture; |
474 | snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max); | 472 | snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max); |
475 | snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max); | 473 | snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max); |
diff --git a/sound/isa/ad1848/Makefile b/sound/isa/ad1848/Makefile index 45d59998aa69..ae23331e9200 100644 --- a/sound/isa/ad1848/Makefile +++ b/sound/isa/ad1848/Makefile | |||
@@ -1,15 +1,12 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ad1848-lib-objs := ad1848_lib.o | 6 | snd-ad1848-lib-objs := ad1848_lib.o |
7 | snd-ad1848-objs := ad1848.o | 7 | snd-ad1848-objs := ad1848.o |
8 | 8 | ||
9 | # Toplevel Module Dependency | 9 | # Toplevel Module Dependency |
10 | obj-$(CONFIG_SND_CMI8330) += snd-ad1848-lib.o | 10 | obj-$(CONFIG_SND_AD1848) += snd-ad1848.o |
11 | obj-$(CONFIG_SND_SGALAXY) += snd-ad1848-lib.o | 11 | obj-$(CONFIG_SND_AD1848_LIB) += snd-ad1848-lib.o |
12 | obj-$(CONFIG_SND_AD1848) += snd-ad1848.o snd-ad1848-lib.o | ||
13 | obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-ad1848-lib.o | ||
14 | 12 | ||
15 | obj-m := $(sort $(obj-m)) | ||
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index d09a7fa86545..a4710b5e214c 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Generic driver for AD1848/AD1847/CS4248 chips (0.1 Alpha) | 2 | * Generic driver for AD1848/AD1847/CS4248 chips (0.1 Alpha) |
3 | * Copyright (c) by Tugrul Galatali <galatalt@stuy.edu>, | 3 | * Copyright (c) by Tugrul Galatali <galatalt@stuy.edu>, |
4 | * Jaroslav Kysela <perex@suse.cz> | 4 | * Jaroslav Kysela <perex@perex.cz> |
5 | * Based on card-4232.c by Jaroslav Kysela <perex@suse.cz> | 5 | * Based on card-4232.c by Jaroslav Kysela <perex@perex.cz> |
6 | * | 6 | * |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
@@ -36,7 +36,7 @@ | |||
36 | #define DEV_NAME "ad1848" | 36 | #define DEV_NAME "ad1848" |
37 | 37 | ||
38 | MODULE_DESCRIPTION(CRD_NAME); | 38 | MODULE_DESCRIPTION(CRD_NAME); |
39 | MODULE_AUTHOR("Tugrul Galatali <galatalt@stuy.edu>, Jaroslav Kysela <perex@suse.cz>"); | 39 | MODULE_AUTHOR("Tugrul Galatali <galatalt@stuy.edu>, Jaroslav Kysela <perex@perex.cz>"); |
40 | MODULE_LICENSE("GPL"); | 40 | MODULE_LICENSE("GPL"); |
41 | MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848}," | 41 | MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848}," |
42 | "{Analog Devices,AD1847}," | 42 | "{Analog Devices,AD1847}," |
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index 1bc2e3fd5721..a901cd1ee692 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of AD1848/AD1847/CS4248 | 3 | * Routines for control of AD1848/AD1847/CS4248 |
4 | * | 4 | * |
5 | * | 5 | * |
@@ -35,7 +35,7 @@ | |||
35 | #include <asm/io.h> | 35 | #include <asm/io.h> |
36 | #include <asm/dma.h> | 36 | #include <asm/dma.h> |
37 | 37 | ||
38 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 38 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
39 | MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248"); | 39 | MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248"); |
40 | MODULE_LICENSE("GPL"); | 40 | MODULE_LICENSE("GPL"); |
41 | 41 | ||
@@ -70,7 +70,7 @@ static unsigned int rates[14] = { | |||
70 | }; | 70 | }; |
71 | 71 | ||
72 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 72 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
73 | .count = 14, | 73 | .count = ARRAY_SIZE(rates), |
74 | .list = rates, | 74 | .list = rates, |
75 | .mask = 0, | 75 | .mask = 0, |
76 | }; | 76 | }; |
@@ -99,24 +99,32 @@ static unsigned char snd_ad1848_original_image[16] = | |||
99 | * Basic I/O functions | 99 | * Basic I/O functions |
100 | */ | 100 | */ |
101 | 101 | ||
102 | void snd_ad1848_out(struct snd_ad1848 *chip, | 102 | static void snd_ad1848_wait(struct snd_ad1848 *chip) |
103 | unsigned char reg, | ||
104 | unsigned char value) | ||
105 | { | 103 | { |
106 | int timeout; | 104 | int timeout; |
107 | 105 | ||
108 | for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--) | 106 | for (timeout = 250; timeout > 0; timeout--) { |
107 | if ((inb(AD1848P(chip, REGSEL)) & AD1848_INIT) == 0) | ||
108 | break; | ||
109 | udelay(100); | 109 | udelay(100); |
110 | } | ||
111 | } | ||
112 | |||
113 | void snd_ad1848_out(struct snd_ad1848 *chip, | ||
114 | unsigned char reg, | ||
115 | unsigned char value) | ||
116 | { | ||
117 | snd_ad1848_wait(chip); | ||
110 | #ifdef CONFIG_SND_DEBUG | 118 | #ifdef CONFIG_SND_DEBUG |
111 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) | 119 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) |
112 | snd_printk(KERN_WARNING "auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | 120 | snd_printk(KERN_WARNING "auto calibration time out - " |
121 | "reg = 0x%x, value = 0x%x\n", reg, value); | ||
113 | #endif | 122 | #endif |
114 | outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); | 123 | outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); |
115 | outb(chip->image[reg] = value, AD1848P(chip, REG)); | 124 | outb(chip->image[reg] = value, AD1848P(chip, REG)); |
116 | mb(); | 125 | mb(); |
117 | #if 0 | 126 | snd_printdd("codec out - reg 0x%x = 0x%x\n", |
118 | printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value); | 127 | chip->mce_bit | reg, value); |
119 | #endif | ||
120 | } | 128 | } |
121 | 129 | ||
122 | EXPORT_SYMBOL(snd_ad1848_out); | 130 | EXPORT_SYMBOL(snd_ad1848_out); |
@@ -124,10 +132,7 @@ EXPORT_SYMBOL(snd_ad1848_out); | |||
124 | static void snd_ad1848_dout(struct snd_ad1848 *chip, | 132 | static void snd_ad1848_dout(struct snd_ad1848 *chip, |
125 | unsigned char reg, unsigned char value) | 133 | unsigned char reg, unsigned char value) |
126 | { | 134 | { |
127 | int timeout; | 135 | snd_ad1848_wait(chip); |
128 | |||
129 | for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--) | ||
130 | udelay(100); | ||
131 | outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); | 136 | outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); |
132 | outb(value, AD1848P(chip, REG)); | 137 | outb(value, AD1848P(chip, REG)); |
133 | mb(); | 138 | mb(); |
@@ -135,13 +140,11 @@ static void snd_ad1848_dout(struct snd_ad1848 *chip, | |||
135 | 140 | ||
136 | static unsigned char snd_ad1848_in(struct snd_ad1848 *chip, unsigned char reg) | 141 | static unsigned char snd_ad1848_in(struct snd_ad1848 *chip, unsigned char reg) |
137 | { | 142 | { |
138 | int timeout; | 143 | snd_ad1848_wait(chip); |
139 | |||
140 | for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--) | ||
141 | udelay(100); | ||
142 | #ifdef CONFIG_SND_DEBUG | 144 | #ifdef CONFIG_SND_DEBUG |
143 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) | 145 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) |
144 | snd_printk(KERN_WARNING "auto calibration time out - reg = 0x%x\n", reg); | 146 | snd_printk(KERN_WARNING "auto calibration time out - " |
147 | "reg = 0x%x\n", reg); | ||
145 | #endif | 148 | #endif |
146 | outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); | 149 | outb(chip->mce_bit | reg, AD1848P(chip, REGSEL)); |
147 | mb(); | 150 | mb(); |
@@ -183,8 +186,7 @@ static void snd_ad1848_mce_up(struct snd_ad1848 *chip) | |||
183 | unsigned long flags; | 186 | unsigned long flags; |
184 | int timeout; | 187 | int timeout; |
185 | 188 | ||
186 | for (timeout = 250; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--) | 189 | snd_ad1848_wait(chip); |
187 | udelay(100); | ||
188 | #ifdef CONFIG_SND_DEBUG | 190 | #ifdef CONFIG_SND_DEBUG |
189 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) | 191 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) |
190 | snd_printk(KERN_WARNING "mce_up - auto calibration time out (0)\n"); | 192 | snd_printk(KERN_WARNING "mce_up - auto calibration time out (0)\n"); |
@@ -201,9 +203,8 @@ static void snd_ad1848_mce_up(struct snd_ad1848 *chip) | |||
201 | 203 | ||
202 | static void snd_ad1848_mce_down(struct snd_ad1848 *chip) | 204 | static void snd_ad1848_mce_down(struct snd_ad1848 *chip) |
203 | { | 205 | { |
204 | unsigned long flags; | 206 | unsigned long flags, timeout; |
205 | int timeout; | 207 | int reg; |
206 | signed long time; | ||
207 | 208 | ||
208 | spin_lock_irqsave(&chip->reg_lock, flags); | 209 | spin_lock_irqsave(&chip->reg_lock, flags); |
209 | for (timeout = 5; timeout > 0; timeout--) | 210 | for (timeout = 5; timeout > 0; timeout--) |
@@ -211,61 +212,48 @@ static void snd_ad1848_mce_down(struct snd_ad1848 *chip) | |||
211 | /* end of cleanup sequence */ | 212 | /* end of cleanup sequence */ |
212 | for (timeout = 12000; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--) | 213 | for (timeout = 12000; timeout > 0 && (inb(AD1848P(chip, REGSEL)) & AD1848_INIT); timeout--) |
213 | udelay(100); | 214 | udelay(100); |
214 | #if 0 | 215 | |
215 | printk("(1) timeout = %i\n", timeout); | 216 | snd_printdd("(1) timeout = %d\n", timeout); |
216 | #endif | 217 | |
217 | #ifdef CONFIG_SND_DEBUG | 218 | #ifdef CONFIG_SND_DEBUG |
218 | if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) | 219 | 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 | snd_printk(KERN_WARNING "mce_down [0x%lx] - auto calibration time out (0)\n", AD1848P(chip, REGSEL)); |
220 | #endif | 221 | #endif |
222 | |||
221 | chip->mce_bit &= ~AD1848_MCE; | 223 | chip->mce_bit &= ~AD1848_MCE; |
222 | timeout = inb(AD1848P(chip, REGSEL)); | 224 | reg = inb(AD1848P(chip, REGSEL)); |
223 | outb(chip->mce_bit | (timeout & 0x1f), AD1848P(chip, REGSEL)); | 225 | outb(chip->mce_bit | (reg & 0x1f), AD1848P(chip, REGSEL)); |
224 | if (timeout == 0x80) | 226 | if (reg == 0x80) |
225 | snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); | 227 | snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); |
226 | if ((timeout & AD1848_MCE) == 0) { | 228 | if ((reg & AD1848_MCE) == 0) { |
227 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 229 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
228 | return; | 230 | return; |
229 | } | 231 | } |
230 | /* calibration process */ | ||
231 | 232 | ||
232 | for (timeout = 500; timeout > 0 && (snd_ad1848_in(chip, AD1848_TEST_INIT) & AD1848_CALIB_IN_PROGRESS) == 0; timeout--); | 233 | /* |
233 | if ((snd_ad1848_in(chip, AD1848_TEST_INIT) & AD1848_CALIB_IN_PROGRESS) == 0) { | 234 | * Wait for auto-calibration (AC) process to finish, i.e. ACI to go low. |
234 | snd_printd("mce_down - auto calibration time out (1)\n"); | 235 | * It may take up to 5 sample periods (at most 907 us @ 5.5125 kHz) for |
235 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 236 | * the process to _start_, so it is important to wait at least that long |
236 | return; | 237 | * before checking. Otherwise we might think AC has finished when it |
237 | } | 238 | * has in fact not begun. It could take 128 (no AC) or 384 (AC) cycles |
238 | #if 0 | 239 | * for ACI to drop. This gives a wait of at most 70 ms with a more |
239 | printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies); | 240 | * typical value of 3-9 ms. |
240 | #endif | 241 | */ |
241 | time = HZ / 4; | 242 | timeout = jiffies + msecs_to_jiffies(250); |
242 | while (snd_ad1848_in(chip, AD1848_TEST_INIT) & AD1848_CALIB_IN_PROGRESS) { | 243 | do { |
243 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 244 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
244 | if (time <= 0) { | 245 | msleep(1); |
245 | snd_printk(KERN_ERR "mce_down - auto calibration time out (2)\n"); | ||
246 | return; | ||
247 | } | ||
248 | time = schedule_timeout(time); | ||
249 | spin_lock_irqsave(&chip->reg_lock, flags); | 246 | spin_lock_irqsave(&chip->reg_lock, flags); |
250 | } | 247 | reg = snd_ad1848_in(chip, AD1848_TEST_INIT) & |
251 | #if 0 | 248 | AD1848_CALIB_IN_PROGRESS; |
252 | printk("(3) jiffies = %li\n", jiffies); | 249 | } while (reg && time_before(jiffies, timeout)); |
253 | #endif | ||
254 | time = HZ / 10; | ||
255 | while (inb(AD1848P(chip, REGSEL)) & AD1848_INIT) { | ||
256 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
257 | if (time <= 0) { | ||
258 | snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); | ||
259 | return; | ||
260 | } | ||
261 | time = schedule_timeout(time); | ||
262 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
263 | } | ||
264 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 250 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
265 | #if 0 | 251 | if (reg) |
266 | printk("(4) jiffies = %li\n", jiffies); | 252 | snd_printk(KERN_ERR |
267 | snd_printk("mce_down - exit = 0x%x\n", inb(AD1848P(chip, REGSEL))); | 253 | "mce_down - auto calibration time out (2)\n"); |
268 | #endif | 254 | |
255 | snd_printdd("(4) jiffies = %lu\n", jiffies); | ||
256 | snd_printd("mce_down - exit = 0x%x\n", inb(AD1848P(chip, REGSEL))); | ||
269 | } | 257 | } |
270 | 258 | ||
271 | static unsigned int snd_ad1848_get_count(unsigned char format, | 259 | static unsigned int snd_ad1848_get_count(unsigned char format, |
@@ -319,11 +307,11 @@ static unsigned char snd_ad1848_get_rate(unsigned int rate) | |||
319 | { | 307 | { |
320 | int i; | 308 | int i; |
321 | 309 | ||
322 | for (i = 0; i < 14; i++) | 310 | for (i = 0; i < ARRAY_SIZE(rates); i++) |
323 | if (rate == rates[i]) | 311 | if (rate == rates[i]) |
324 | return freq_bits[i]; | 312 | return freq_bits[i]; |
325 | snd_BUG(); | 313 | snd_BUG(); |
326 | return freq_bits[13]; | 314 | return freq_bits[ARRAY_SIZE(rates) - 1]; |
327 | } | 315 | } |
328 | 316 | ||
329 | static int snd_ad1848_ioctl(struct snd_pcm_substream *substream, | 317 | static int snd_ad1848_ioctl(struct snd_pcm_substream *substream, |
@@ -390,11 +378,9 @@ static int snd_ad1848_open(struct snd_ad1848 *chip, unsigned int mode) | |||
390 | { | 378 | { |
391 | unsigned long flags; | 379 | unsigned long flags; |
392 | 380 | ||
393 | mutex_lock(&chip->open_mutex); | 381 | if (chip->mode & AD1848_MODE_OPEN) |
394 | if (chip->mode & AD1848_MODE_OPEN) { | ||
395 | mutex_unlock(&chip->open_mutex); | ||
396 | return -EAGAIN; | 382 | return -EAGAIN; |
397 | } | 383 | |
398 | snd_ad1848_mce_down(chip); | 384 | snd_ad1848_mce_down(chip); |
399 | 385 | ||
400 | #ifdef SNDRV_DEBUG_MCE | 386 | #ifdef SNDRV_DEBUG_MCE |
@@ -435,7 +421,6 @@ static int snd_ad1848_open(struct snd_ad1848 *chip, unsigned int mode) | |||
435 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 421 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
436 | 422 | ||
437 | chip->mode = mode; | 423 | chip->mode = mode; |
438 | mutex_unlock(&chip->open_mutex); | ||
439 | 424 | ||
440 | return 0; | 425 | return 0; |
441 | } | 426 | } |
@@ -444,11 +429,8 @@ static void snd_ad1848_close(struct snd_ad1848 *chip) | |||
444 | { | 429 | { |
445 | unsigned long flags; | 430 | unsigned long flags; |
446 | 431 | ||
447 | mutex_lock(&chip->open_mutex); | 432 | if (!chip->mode) |
448 | if (!chip->mode) { | ||
449 | mutex_unlock(&chip->open_mutex); | ||
450 | return; | 433 | return; |
451 | } | ||
452 | /* disable IRQ */ | 434 | /* disable IRQ */ |
453 | spin_lock_irqsave(&chip->reg_lock, flags); | 435 | spin_lock_irqsave(&chip->reg_lock, flags); |
454 | outb(0, AD1848P(chip, STATUS)); /* clear IRQ */ | 436 | outb(0, AD1848P(chip, STATUS)); /* clear IRQ */ |
@@ -474,7 +456,6 @@ static void snd_ad1848_close(struct snd_ad1848 *chip) | |||
474 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 456 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
475 | 457 | ||
476 | chip->mode = 0; | 458 | chip->mode = 0; |
477 | mutex_unlock(&chip->open_mutex); | ||
478 | } | 459 | } |
479 | 460 | ||
480 | /* | 461 | /* |
@@ -892,7 +873,6 @@ int snd_ad1848_create(struct snd_card *card, | |||
892 | if (chip == NULL) | 873 | if (chip == NULL) |
893 | return -ENOMEM; | 874 | return -ENOMEM; |
894 | spin_lock_init(&chip->reg_lock); | 875 | spin_lock_init(&chip->reg_lock); |
895 | mutex_init(&chip->open_mutex); | ||
896 | chip->card = card; | 876 | chip->card = card; |
897 | chip->port = port; | 877 | chip->port = port; |
898 | chip->irq = -1; | 878 | chip->irq = -1; |
diff --git a/sound/isa/cs423x/Makefile b/sound/isa/cs423x/Makefile index 2fb4f7409d7c..5067ee001933 100644 --- a/sound/isa/cs423x/Makefile +++ b/sound/isa/cs423x/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-cs4231-lib-objs := cs4231_lib.o | 6 | snd-cs4231-lib-objs := cs4231_lib.o |
@@ -10,17 +10,8 @@ snd-cs4232-objs := cs4232.o | |||
10 | snd-cs4236-objs := cs4236.o | 10 | snd-cs4236-objs := cs4236.o |
11 | 11 | ||
12 | # Toplevel Module Dependency | 12 | # Toplevel Module Dependency |
13 | obj-$(CONFIG_SND_AZT2320) += snd-cs4231-lib.o | 13 | obj-$(CONFIG_SND_CS4231_LIB) += snd-cs4231-lib.o |
14 | obj-$(CONFIG_SND_MIRO) += snd-cs4231-lib.o | 14 | obj-$(CONFIG_SND_CS4231) += snd-cs4231.o |
15 | obj-$(CONFIG_SND_OPL3SA2) += snd-cs4231-lib.o | 15 | obj-$(CONFIG_SND_CS4232) += snd-cs4232.o |
16 | obj-$(CONFIG_SND_CS4231) += snd-cs4231.o snd-cs4231-lib.o | 16 | obj-$(CONFIG_SND_CS4236) += snd-cs4236.o snd-cs4236-lib.o |
17 | obj-$(CONFIG_SND_CS4232) += snd-cs4232.o snd-cs4231-lib.o | ||
18 | obj-$(CONFIG_SND_CS4236) += snd-cs4236.o snd-cs4236-lib.o snd-cs4231-lib.o | ||
19 | obj-$(CONFIG_SND_GUSMAX) += snd-cs4231-lib.o | ||
20 | obj-$(CONFIG_SND_INTERWAVE) += snd-cs4231-lib.o | ||
21 | obj-$(CONFIG_SND_INTERWAVE_STB) += snd-cs4231-lib.o | ||
22 | obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-cs4231-lib.o | ||
23 | obj-$(CONFIG_SND_WAVEFRONT) += snd-cs4231-lib.o | ||
24 | obj-$(CONFIG_SND_SSCAPE) += snd-cs4231-lib.o | ||
25 | 17 | ||
26 | obj-m := $(sort $(obj-m)) | ||
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index ac4041134150..13db6842eaaa 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Generic driver for CS4231 chips | 2 | * Generic driver for CS4231 chips |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * Originally the CS4232/CS4232A driver, modified for use on CS4231 by | 4 | * Originally the CS4232/CS4232A driver, modified for use on CS4231 by |
5 | * Tugrul Galatali <galatalt@stuy.edu> | 5 | * Tugrul Galatali <galatalt@stuy.edu> |
6 | * | 6 | * |
@@ -36,7 +36,7 @@ | |||
36 | #define DEV_NAME "cs4231" | 36 | #define DEV_NAME "cs4231" |
37 | 37 | ||
38 | MODULE_DESCRIPTION(CRD_NAME); | 38 | MODULE_DESCRIPTION(CRD_NAME); |
39 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 39 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
40 | MODULE_LICENSE("GPL"); | 40 | MODULE_LICENSE("GPL"); |
41 | MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}"); | 41 | MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}"); |
42 | 42 | ||
diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c index 914d77b61b0c..a5eb9659b519 100644 --- a/sound/isa/cs423x/cs4231_lib.c +++ b/sound/isa/cs423x/cs4231_lib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of CS4231(A)/CS4232/InterWave & compatible chips | 3 | * Routines for control of CS4231(A)/CS4232/InterWave & compatible chips |
4 | * | 4 | * |
5 | * Bugs: | 5 | * Bugs: |
@@ -39,7 +39,7 @@ | |||
39 | #include <asm/dma.h> | 39 | #include <asm/dma.h> |
40 | #include <asm/irq.h> | 40 | #include <asm/irq.h> |
41 | 41 | ||
42 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 42 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
43 | MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips"); | 43 | MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips"); |
44 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
45 | 45 | ||
@@ -74,7 +74,7 @@ static unsigned int rates[14] = { | |||
74 | }; | 74 | }; |
75 | 75 | ||
76 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 76 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
77 | .count = 14, | 77 | .count = ARRAY_SIZE(rates), |
78 | .list = rates, | 78 | .list = rates, |
79 | .mask = 0, | 79 | .mask = 0, |
80 | }; | 80 | }; |
@@ -134,29 +134,31 @@ static inline u8 cs4231_inb(struct snd_cs4231 *chip, u8 offset) | |||
134 | return inb(chip->port + offset); | 134 | return inb(chip->port + offset); |
135 | } | 135 | } |
136 | 136 | ||
137 | static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg, | 137 | static void snd_cs4231_wait(struct snd_cs4231 *chip) |
138 | unsigned char mask, unsigned char value) | ||
139 | { | 138 | { |
140 | int timeout; | 139 | int timeout; |
141 | unsigned char tmp; | ||
142 | 140 | ||
143 | for (timeout = 250; | 141 | for (timeout = 250; |
144 | timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); | 142 | timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); |
145 | timeout--) | 143 | timeout--) |
146 | udelay(100); | 144 | udelay(100); |
145 | } | ||
146 | |||
147 | static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg, | ||
148 | unsigned char mask, unsigned char value) | ||
149 | { | ||
150 | unsigned char tmp = (chip->image[reg] & mask) | value; | ||
151 | |||
152 | snd_cs4231_wait(chip); | ||
147 | #ifdef CONFIG_SND_DEBUG | 153 | #ifdef CONFIG_SND_DEBUG |
148 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 154 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) |
149 | snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | 155 | snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); |
150 | #endif | 156 | #endif |
151 | if (chip->calibrate_mute) { | 157 | chip->image[reg] = tmp; |
152 | chip->image[reg] &= mask; | 158 | if (!chip->calibrate_mute) { |
153 | chip->image[reg] |= value; | ||
154 | } else { | ||
155 | cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); | 159 | cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); |
156 | mb(); | 160 | wmb(); |
157 | tmp = (chip->image[reg] & mask) | value; | ||
158 | cs4231_outb(chip, CS4231P(REG), tmp); | 161 | cs4231_outb(chip, CS4231P(REG), tmp); |
159 | chip->image[reg] = tmp; | ||
160 | mb(); | 162 | mb(); |
161 | } | 163 | } |
162 | } | 164 | } |
@@ -176,12 +178,7 @@ static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, unsigned | |||
176 | 178 | ||
177 | void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value) | 179 | void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value) |
178 | { | 180 | { |
179 | int timeout; | 181 | snd_cs4231_wait(chip); |
180 | |||
181 | for (timeout = 250; | ||
182 | timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); | ||
183 | timeout--) | ||
184 | udelay(100); | ||
185 | #ifdef CONFIG_SND_DEBUG | 182 | #ifdef CONFIG_SND_DEBUG |
186 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 183 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) |
187 | snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | 184 | snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); |
@@ -190,19 +187,13 @@ void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char va | |||
190 | cs4231_outb(chip, CS4231P(REG), value); | 187 | cs4231_outb(chip, CS4231P(REG), value); |
191 | chip->image[reg] = value; | 188 | chip->image[reg] = value; |
192 | mb(); | 189 | mb(); |
193 | #if 0 | 190 | snd_printdd("codec out - reg 0x%x = 0x%x\n", |
194 | printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value); | 191 | chip->mce_bit | reg, value); |
195 | #endif | ||
196 | } | 192 | } |
197 | 193 | ||
198 | unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg) | 194 | unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg) |
199 | { | 195 | { |
200 | int timeout; | 196 | snd_cs4231_wait(chip); |
201 | |||
202 | for (timeout = 250; | ||
203 | timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); | ||
204 | timeout--) | ||
205 | udelay(100); | ||
206 | #ifdef CONFIG_SND_DEBUG | 197 | #ifdef CONFIG_SND_DEBUG |
207 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 198 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) |
208 | snd_printk("in: auto calibration time out - reg = 0x%x\n", reg); | 199 | snd_printk("in: auto calibration time out - reg = 0x%x\n", reg); |
@@ -304,8 +295,7 @@ void snd_cs4231_mce_up(struct snd_cs4231 *chip) | |||
304 | unsigned long flags; | 295 | unsigned long flags; |
305 | int timeout; | 296 | int timeout; |
306 | 297 | ||
307 | for (timeout = 250; timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); timeout--) | 298 | snd_cs4231_wait(chip); |
308 | udelay(100); | ||
309 | #ifdef CONFIG_SND_DEBUG | 299 | #ifdef CONFIG_SND_DEBUG |
310 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 300 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) |
311 | snd_printk("mce_up - auto calibration time out (0)\n"); | 301 | snd_printk("mce_up - auto calibration time out (0)\n"); |
@@ -323,12 +313,11 @@ void snd_cs4231_mce_up(struct snd_cs4231 *chip) | |||
323 | void snd_cs4231_mce_down(struct snd_cs4231 *chip) | 313 | void snd_cs4231_mce_down(struct snd_cs4231 *chip) |
324 | { | 314 | { |
325 | unsigned long flags; | 315 | unsigned long flags; |
316 | unsigned long end_time; | ||
326 | int timeout; | 317 | int timeout; |
327 | 318 | ||
328 | snd_cs4231_busy_wait(chip); | 319 | snd_cs4231_busy_wait(chip); |
329 | #if 0 | 320 | |
330 | printk("(1) timeout = %i\n", timeout); | ||
331 | #endif | ||
332 | #ifdef CONFIG_SND_DEBUG | 321 | #ifdef CONFIG_SND_DEBUG |
333 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 322 | if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) |
334 | snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL)); | 323 | snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL)); |
@@ -346,42 +335,42 @@ void snd_cs4231_mce_down(struct snd_cs4231 *chip) | |||
346 | } | 335 | } |
347 | snd_cs4231_busy_wait(chip); | 336 | snd_cs4231_busy_wait(chip); |
348 | 337 | ||
349 | /* calibration process */ | 338 | /* |
339 | * Wait for (possible -- during init auto-calibration may not be set) | ||
340 | * calibration process to start. Needs upto 5 sample periods on AD1848 | ||
341 | * which at the slowest possible rate of 5.5125 kHz means 907 us. | ||
342 | */ | ||
343 | msleep(1); | ||
350 | 344 | ||
351 | for (timeout = 500; timeout > 0 && (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0; timeout--) | 345 | snd_printdd("(1) jiffies = %lu\n", jiffies); |
352 | udelay(10); | 346 | |
353 | if ((snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0) { | 347 | /* check condition up to 250 ms */ |
354 | snd_printd("cs4231_mce_down - auto calibration time out (1)\n"); | 348 | end_time = jiffies + msecs_to_jiffies(250); |
355 | return; | 349 | while (snd_cs4231_in(chip, CS4231_TEST_INIT) & |
356 | } | 350 | CS4231_CALIB_IN_PROGRESS) { |
357 | #if 0 | 351 | |
358 | printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies); | 352 | if (time_after(jiffies, end_time)) { |
359 | #endif | 353 | snd_printk(KERN_ERR "mce_down - " |
360 | /* in 10 ms increments, check condition, up to 250 ms */ | 354 | "auto calibration time out (2)\n"); |
361 | timeout = 25; | ||
362 | while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) { | ||
363 | if (--timeout < 0) { | ||
364 | snd_printk("mce_down - auto calibration time out (2)\n"); | ||
365 | return; | 355 | return; |
366 | } | 356 | } |
367 | msleep(10); | 357 | msleep(1); |
368 | } | 358 | } |
369 | #if 0 | 359 | |
370 | printk("(3) jiffies = %li\n", jiffies); | 360 | snd_printdd("(2) jiffies = %lu\n", jiffies); |
371 | #endif | 361 | |
372 | /* in 10 ms increments, check condition, up to 100 ms */ | 362 | /* check condition up to 100 ms */ |
373 | timeout = 10; | 363 | end_time = jiffies + msecs_to_jiffies(100); |
374 | while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { | 364 | while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { |
375 | if (--timeout < 0) { | 365 | if (time_after(jiffies, end_time)) { |
376 | snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); | 366 | snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); |
377 | return; | 367 | return; |
378 | } | 368 | } |
379 | msleep(10); | 369 | msleep(1); |
380 | } | 370 | } |
381 | #if 0 | 371 | |
382 | printk("(4) jiffies = %li\n", jiffies); | 372 | snd_printdd("(3) jiffies = %lu\n", jiffies); |
383 | snd_printk("mce_down - exit = 0x%x\n", cs4231_inb(chip, CS4231P(REGSEL))); | 373 | snd_printd("mce_down - exit = 0x%x\n", cs4231_inb(chip, CS4231P(REGSEL))); |
384 | #endif | ||
385 | } | 374 | } |
386 | 375 | ||
387 | static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size) | 376 | static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size) |
@@ -459,11 +448,11 @@ static unsigned char snd_cs4231_get_rate(unsigned int rate) | |||
459 | { | 448 | { |
460 | int i; | 449 | int i; |
461 | 450 | ||
462 | for (i = 0; i < 14; i++) | 451 | for (i = 0; i < ARRAY_SIZE(rates); i++) |
463 | if (rate == rates[i]) | 452 | if (rate == rates[i]) |
464 | return freq_bits[i]; | 453 | return freq_bits[i]; |
465 | // snd_BUG(); | 454 | // snd_BUG(); |
466 | return freq_bits[13]; | 455 | return freq_bits[ARRAY_SIZE(rates) - 1]; |
467 | } | 456 | } |
468 | 457 | ||
469 | static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, | 458 | static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, |
@@ -555,6 +544,8 @@ static void snd_cs4231_playback_format(struct snd_cs4231 *chip, | |||
555 | snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr); | 544 | snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr); |
556 | } | 545 | } |
557 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 546 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
547 | if (chip->hardware == CS4231_HW_OPL3SA2) | ||
548 | udelay(100); /* this seems to help */ | ||
558 | snd_cs4231_mce_down(chip); | 549 | snd_cs4231_mce_down(chip); |
559 | } | 550 | } |
560 | snd_cs4231_calibrate_mute(chip, 0); | 551 | snd_cs4231_calibrate_mute(chip, 0); |
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 1a14f33b6ab0..5784b43f4123 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for generic CS4232/CS4235/CS4236/CS4236B/CS4237B/CS4238B/CS4239 chips | 2 | * Driver for generic CS4232/CS4235/CS4236/CS4236B/CS4237B/CS4238B/CS4239 chips |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -32,7 +32,7 @@ | |||
32 | #include <sound/opl3.h> | 32 | #include <sound/opl3.h> |
33 | #include <sound/initval.h> | 33 | #include <sound/initval.h> |
34 | 34 | ||
35 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 35 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
36 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
37 | #ifdef CS4232 | 37 | #ifdef CS4232 |
38 | MODULE_DESCRIPTION("Cirrus Logic CS4232"); | 38 | MODULE_DESCRIPTION("Cirrus Logic CS4232"); |
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index 7a5a6c71f5e4..6bd064470d4c 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of CS4235/4236B/4237B/4238B/4239 chips | 3 | * Routines for control of CS4235/4236B/4237B/4238B/4239 chips |
4 | * | 4 | * |
5 | * Note: | 5 | * Note: |
@@ -89,7 +89,7 @@ | |||
89 | #include <sound/cs4231.h> | 89 | #include <sound/cs4231.h> |
90 | #include <sound/asoundef.h> | 90 | #include <sound/asoundef.h> |
91 | 91 | ||
92 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 92 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
93 | MODULE_DESCRIPTION("Routines for control of CS4235/4236B/4237B/4238B/4239 chips"); | 93 | MODULE_DESCRIPTION("Routines for control of CS4235/4236B/4237B/4238B/4239 chips"); |
94 | MODULE_LICENSE("GPL"); | 94 | MODULE_LICENSE("GPL"); |
95 | 95 | ||
diff --git a/sound/isa/es1688/Makefile b/sound/isa/es1688/Makefile index 501c8bf903af..aee1e4ddb22a 100644 --- a/sound/isa/es1688/Makefile +++ b/sound/isa/es1688/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-es1688-lib-objs := es1688_lib.o | 6 | snd-es1688-lib-objs := es1688_lib.o |
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c index edc398712e8b..74bbc92f2e7c 100644 --- a/sound/isa/es1688/es1688.c +++ b/sound/isa/es1688/es1688.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for generic ESS AudioDrive ESx688 soundcards | 2 | * Driver for generic ESS AudioDrive ESx688 soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -39,7 +39,7 @@ | |||
39 | #define DEV_NAME "es1688" | 39 | #define DEV_NAME "es1688" |
40 | 40 | ||
41 | MODULE_DESCRIPTION(CRD_NAME); | 41 | MODULE_DESCRIPTION(CRD_NAME); |
42 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 42 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
44 | MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100}," | 44 | MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100}," |
45 | "{ESS,ES1688 PnP AudioDrive,pnp:ESS0102}," | 45 | "{ESS,ES1688 PnP AudioDrive,pnp:ESS0102}," |
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index a2ab99f2ac35..5c26d495daa8 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of ESS ES1688/688/488 chip | 3 | * Routines for control of ESS ES1688/688/488 chip |
4 | * | 4 | * |
5 | * | 5 | * |
@@ -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 | 34 | ||
35 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 35 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
36 | MODULE_DESCRIPTION("ESS ESx688 lowlevel module"); | 36 | MODULE_DESCRIPTION("ESS ESx688 lowlevel module"); |
37 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL"); |
38 | 38 | ||
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index f7732bf90be3..4a7367a8ff9d 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c | |||
@@ -1071,14 +1071,7 @@ static int snd_es18xx_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
1071 | return (snd_es18xx_mixer_bits(chip, 0x1c, 0x07, val) != val) || retVal; | 1071 | return (snd_es18xx_mixer_bits(chip, 0x1c, 0x07, val) != val) || retVal; |
1072 | } | 1072 | } |
1073 | 1073 | ||
1074 | static int snd_es18xx_info_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1074 | #define snd_es18xx_info_spatializer_enable snd_ctl_boolean_mono_info |
1075 | { | ||
1076 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1077 | uinfo->count = 1; | ||
1078 | uinfo->value.integer.min = 0; | ||
1079 | uinfo->value.integer.max = 1; | ||
1080 | return 0; | ||
1081 | } | ||
1082 | 1075 | ||
1083 | static int snd_es18xx_get_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1076 | static int snd_es18xx_get_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1084 | { | 1077 | { |
@@ -1120,14 +1113,7 @@ static int snd_es18xx_get_hw_volume(struct snd_kcontrol *kcontrol, struct snd_ct | |||
1120 | return 0; | 1113 | return 0; |
1121 | } | 1114 | } |
1122 | 1115 | ||
1123 | static int snd_es18xx_info_hw_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1116 | #define snd_es18xx_info_hw_switch snd_ctl_boolean_stereo_info |
1124 | { | ||
1125 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1126 | uinfo->count = 2; | ||
1127 | uinfo->value.integer.min = 0; | ||
1128 | uinfo->value.integer.max = 1; | ||
1129 | return 0; | ||
1130 | } | ||
1131 | 1117 | ||
1132 | static int snd_es18xx_get_hw_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1118 | static int snd_es18xx_get_hw_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1133 | { | 1119 | { |
@@ -2042,6 +2028,7 @@ static int pnpc_registered; | |||
2042 | 2028 | ||
2043 | static struct pnp_device_id snd_audiodrive_pnpbiosids[] = { | 2029 | static struct pnp_device_id snd_audiodrive_pnpbiosids[] = { |
2044 | { .id = "ESS1869" }, | 2030 | { .id = "ESS1869" }, |
2031 | { .id = "ESS1879" }, | ||
2045 | { .id = "" } /* end */ | 2032 | { .id = "" } /* end */ |
2046 | }; | 2033 | }; |
2047 | 2034 | ||
diff --git a/sound/isa/gus/Makefile b/sound/isa/gus/Makefile index bae5dbd6c8e5..df3d59f25f5e 100644 --- a/sound/isa/gus/Makefile +++ b/sound/isa/gus/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-gus-lib-objs := gus_main.o \ | 6 | snd-gus-lib-objs := gus_main.o \ |
diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c index 44ee5d3674a1..fc905141e8a5 100644 --- a/sound/isa/gus/gus_dma.c +++ b/sound/isa/gus/gus_dma.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for GF1 DMA control | 2 | * Routines for GF1 DMA control |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/gus/gus_dram.c b/sound/isa/gus/gus_dram.c index f22fe7967fcc..9eaa932f6efe 100644 --- a/sound/isa/gus/gus_dram.c +++ b/sound/isa/gus/gus_dram.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * DRAM access routines | 3 | * DRAM access routines |
4 | * | 4 | * |
5 | * | 5 | * |
diff --git a/sound/isa/gus/gus_instr.c b/sound/isa/gus/gus_instr.c index d0c38e1856ef..bf137ea72329 100644 --- a/sound/isa/gus/gus_instr.c +++ b/sound/isa/gus/gus_instr.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for Gravis UltraSound soundcards - Synthesizer | 2 | * Routines for Gravis UltraSound soundcards - Synthesizer |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/gus/gus_io.c b/sound/isa/gus/gus_io.c index 9b1fe292de4d..3d4f899285ef 100644 --- a/sound/isa/gus/gus_io.c +++ b/sound/isa/gus/gus_io.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * I/O routines for GF1/InterWave synthesizer chips | 3 | * I/O routines for GF1/InterWave synthesizer chips |
4 | * | 4 | * |
5 | * | 5 | * |
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c index 537d3cfe41f3..cd9a6f1c99e6 100644 --- a/sound/isa/gus/gus_irq.c +++ b/sound/isa/gus/gus_irq.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routine for IRQ handling from GF1/InterWave chip | 2 | * Routine for IRQ handling from GF1/InterWave chip |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -45,11 +45,13 @@ __again: | |||
45 | // snd_printk("IRQ: status = 0x%x\n", status); | 45 | // snd_printk("IRQ: status = 0x%x\n", status); |
46 | if (status & 0x02) { | 46 | if (status & 0x02) { |
47 | STAT_ADD(gus->gf1.interrupt_stat_midi_in); | 47 | STAT_ADD(gus->gf1.interrupt_stat_midi_in); |
48 | gus->gf1.interrupt_handler_midi_in(gus); | 48 | if (gus->gf1.interrupt_handler_midi_in) |
49 | gus->gf1.interrupt_handler_midi_in(gus); | ||
49 | } | 50 | } |
50 | if (status & 0x01) { | 51 | if (status & 0x01) { |
51 | STAT_ADD(gus->gf1.interrupt_stat_midi_out); | 52 | STAT_ADD(gus->gf1.interrupt_stat_midi_out); |
52 | gus->gf1.interrupt_handler_midi_out(gus); | 53 | if (gus->gf1.interrupt_handler_midi_out) |
54 | gus->gf1.interrupt_handler_midi_out(gus); | ||
53 | } | 55 | } |
54 | if (status & (0x20 | 0x40)) { | 56 | if (status & (0x20 | 0x40)) { |
55 | unsigned int already, _current_; | 57 | unsigned int already, _current_; |
@@ -85,20 +87,24 @@ __again: | |||
85 | } | 87 | } |
86 | if (status & 0x04) { | 88 | if (status & 0x04) { |
87 | STAT_ADD(gus->gf1.interrupt_stat_timer1); | 89 | STAT_ADD(gus->gf1.interrupt_stat_timer1); |
88 | gus->gf1.interrupt_handler_timer1(gus); | 90 | if (gus->gf1.interrupt_handler_timer1) |
91 | gus->gf1.interrupt_handler_timer1(gus); | ||
89 | } | 92 | } |
90 | if (status & 0x08) { | 93 | if (status & 0x08) { |
91 | STAT_ADD(gus->gf1.interrupt_stat_timer2); | 94 | STAT_ADD(gus->gf1.interrupt_stat_timer2); |
92 | gus->gf1.interrupt_handler_timer2(gus); | 95 | if (gus->gf1.interrupt_handler_timer2) |
96 | gus->gf1.interrupt_handler_timer2(gus); | ||
93 | } | 97 | } |
94 | if (status & 0x80) { | 98 | if (status & 0x80) { |
95 | if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) { | 99 | if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) { |
96 | STAT_ADD(gus->gf1.interrupt_stat_dma_write); | 100 | STAT_ADD(gus->gf1.interrupt_stat_dma_write); |
97 | gus->gf1.interrupt_handler_dma_write(gus); | 101 | if (gus->gf1.interrupt_handler_dma_write) |
102 | gus->gf1.interrupt_handler_dma_write(gus); | ||
98 | } | 103 | } |
99 | if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) { | 104 | if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) { |
100 | STAT_ADD(gus->gf1.interrupt_stat_dma_read); | 105 | STAT_ADD(gus->gf1.interrupt_stat_dma_read); |
101 | gus->gf1.interrupt_handler_dma_read(gus); | 106 | if (gus->gf1.interrupt_handler_dma_read) |
107 | gus->gf1.interrupt_handler_dma_read(gus); | ||
102 | } | 108 | } |
103 | } | 109 | } |
104 | if (--loop > 0) | 110 | if (--loop > 0) |
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 8ced5e81b9a7..b14d5d6d9a32 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for Gravis UltraSound soundcards | 2 | * Routines for Gravis UltraSound soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -31,7 +31,7 @@ | |||
31 | 31 | ||
32 | #include <asm/dma.h> | 32 | #include <asm/dma.h> |
33 | 33 | ||
34 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 34 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
35 | MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards"); | 35 | MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards"); |
36 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
37 | 37 | ||
@@ -154,6 +154,14 @@ int snd_gus_create(struct snd_card *card, | |||
154 | gus = kzalloc(sizeof(*gus), GFP_KERNEL); | 154 | gus = kzalloc(sizeof(*gus), GFP_KERNEL); |
155 | if (gus == NULL) | 155 | if (gus == NULL) |
156 | return -ENOMEM; | 156 | return -ENOMEM; |
157 | spin_lock_init(&gus->reg_lock); | ||
158 | spin_lock_init(&gus->voice_alloc); | ||
159 | spin_lock_init(&gus->active_voice_lock); | ||
160 | spin_lock_init(&gus->event_lock); | ||
161 | spin_lock_init(&gus->dma_lock); | ||
162 | spin_lock_init(&gus->pcm_volume_level_lock); | ||
163 | spin_lock_init(&gus->uart_cmd_lock); | ||
164 | mutex_init(&gus->dma_mutex); | ||
157 | gus->gf1.irq = -1; | 165 | gus->gf1.irq = -1; |
158 | gus->gf1.dma1 = -1; | 166 | gus->gf1.dma1 = -1; |
159 | gus->gf1.dma2 = -1; | 167 | gus->gf1.dma2 = -1; |
@@ -218,14 +226,6 @@ int snd_gus_create(struct snd_card *card, | |||
218 | gus->gf1.pcm_channels = pcm_channels; | 226 | gus->gf1.pcm_channels = pcm_channels; |
219 | gus->gf1.volume_ramp = 25; | 227 | gus->gf1.volume_ramp = 25; |
220 | gus->gf1.smooth_pan = 1; | 228 | gus->gf1.smooth_pan = 1; |
221 | spin_lock_init(&gus->reg_lock); | ||
222 | spin_lock_init(&gus->voice_alloc); | ||
223 | spin_lock_init(&gus->active_voice_lock); | ||
224 | spin_lock_init(&gus->event_lock); | ||
225 | spin_lock_init(&gus->dma_lock); | ||
226 | spin_lock_init(&gus->pcm_volume_level_lock); | ||
227 | spin_lock_init(&gus->uart_cmd_lock); | ||
228 | mutex_init(&gus->dma_mutex); | ||
229 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops)) < 0) { | 229 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops)) < 0) { |
230 | snd_gus_free(gus); | 230 | snd_gus_free(gus); |
231 | return err; | 231 | return err; |
@@ -398,7 +398,7 @@ static int snd_gus_check_version(struct snd_gus_card * gus) | |||
398 | gus->ess_flag = 1; | 398 | gus->ess_flag = 1; |
399 | } else { | 399 | } else { |
400 | snd_printk(KERN_ERR "unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus->gf1.port, rev, val); | 400 | snd_printk(KERN_ERR "unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus->gf1.port, rev, val); |
401 | snd_printk(KERN_ERR " please - report to <perex@suse.cz>\n"); | 401 | snd_printk(KERN_ERR " please - report to <perex@perex.cz>\n"); |
402 | } | 402 | } |
403 | } | 403 | } |
404 | } | 404 | } |
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c index 7107753b85b5..bcf4656853c4 100644 --- a/sound/isa/gus/gus_mem.c +++ b/sound/isa/gus/gus_mem.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * GUS's memory allocation routines / bottom layer | 3 | * GUS's memory allocation routines / bottom layer |
4 | * | 4 | * |
5 | * | 5 | * |
diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c index 80f0a83818b2..f69a44728ebf 100644 --- a/sound/isa/gus/gus_mem_proc.c +++ b/sound/isa/gus/gus_mem_proc.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * GUS's memory access via proc filesystem | 3 | * GUS's memory access via proc filesystem |
4 | * | 4 | * |
5 | * | 5 | * |
diff --git a/sound/isa/gus/gus_mixer.c b/sound/isa/gus/gus_mixer.c index acc25a297200..a96253e16654 100644 --- a/sound/isa/gus/gus_mixer.c +++ b/sound/isa/gus/gus_mixer.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of ICS 2101 chip and "mixer" in GF1 chip | 3 | * Routines for control of ICS 2101 chip and "mixer" in GF1 chip |
4 | * | 4 | * |
5 | * | 5 | * |
@@ -36,14 +36,7 @@ | |||
36 | .get = snd_gf1_get_single, .put = snd_gf1_put_single, \ | 36 | .get = snd_gf1_get_single, .put = snd_gf1_put_single, \ |
37 | .private_value = shift | (invert << 8) } | 37 | .private_value = shift | (invert << 8) } |
38 | 38 | ||
39 | static int snd_gf1_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 39 | #define snd_gf1_info_single snd_ctl_boolean_mono_info |
40 | { | ||
41 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
42 | uinfo->count = 1; | ||
43 | uinfo->value.integer.min = 0; | ||
44 | uinfo->value.integer.max = 1; | ||
45 | return 0; | ||
46 | } | ||
47 | 40 | ||
48 | static int snd_gf1_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 41 | static int snd_gf1_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
49 | { | 42 | { |
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index c7f95e7aa018..a7971f5ffe63 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of GF1 chip (PCM things) | 3 | * Routines for control of GF1 chip (PCM things) |
4 | * | 4 | * |
5 | * InterWave chips supports interleaved DMA, but this feature isn't used in | 5 | * InterWave chips supports interleaved DMA, but this feature isn't used in |
diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c index b263655c4116..20cfdb87f84a 100644 --- a/sound/isa/gus/gus_reset.c +++ b/sound/isa/gus/gus_reset.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * | 3 | * |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/gus/gus_sample.c b/sound/isa/gus/gus_sample.c index 9e0c55ab25b2..cba0829a7106 100644 --- a/sound/isa/gus/gus_sample.c +++ b/sound/isa/gus/gus_sample.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for Gravis UltraSound soundcards - Sample support | 2 | * Routines for Gravis UltraSound soundcards - Sample support |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/gus/gus_simple.c b/sound/isa/gus/gus_simple.c index dcad6ed0198c..39d121e2c8c4 100644 --- a/sound/isa/gus/gus_simple.c +++ b/sound/isa/gus/gus_simple.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for Gravis UltraSound soundcards - Simple instrument handlers | 2 | * Routines for Gravis UltraSound soundcards - Simple instrument handlers |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c index 3e4d4d6edd8b..2c2051782aa2 100644 --- a/sound/isa/gus/gus_synth.c +++ b/sound/isa/gus/gus_synth.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for Gravis UltraSound soundcards - Synthesizer | 2 | * Routines for Gravis UltraSound soundcards - Synthesizer |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -26,7 +26,7 @@ | |||
26 | #include <sound/gus.h> | 26 | #include <sound/gus.h> |
27 | #include <sound/seq_device.h> | 27 | #include <sound/seq_device.h> |
28 | 28 | ||
29 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
30 | MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards - Synthesizer"); | 30 | MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards - Synthesizer"); |
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
32 | 32 | ||
diff --git a/sound/isa/gus/gus_tables.h b/sound/isa/gus/gus_tables.h index 4adf098d3269..42a4ca0d622b 100644 --- a/sound/isa/gus/gus_tables.h +++ b/sound/isa/gus/gus_tables.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * | 3 | * |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/gus/gus_timer.c b/sound/isa/gus/gus_timer.c index a43b662f17c7..99eac573c414 100644 --- a/sound/isa/gus/gus_timer.c +++ b/sound/isa/gus/gus_timer.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Routines for Gravis UltraSound soundcards - Timers | 2 | * Routines for Gravis UltraSound soundcards - Timers |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * GUS have similar timers as AdLib (OPL2/OPL3 chips). | 5 | * GUS have similar timers as AdLib (OPL2/OPL3 chips). |
6 | * | 6 | * |
diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c index 654290a8b21c..e6fd9b01c492 100644 --- a/sound/isa/gus/gus_uart.c +++ b/sound/isa/gus/gus_uart.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for the GF1 MIDI interface - like UART 6850 | 3 | * Routines for the GF1 MIDI interface - like UART 6850 |
4 | * | 4 | * |
5 | * | 5 | * |
diff --git a/sound/isa/gus/gus_volume.c b/sound/isa/gus/gus_volume.c index dbbc0a6d7659..71a67744a14b 100644 --- a/sound/isa/gus/gus_volume.c +++ b/sound/isa/gus/gus_volume.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * | 3 | * |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index 8f23f433d491..29e422b00b58 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Gravis UltraSound Classic soundcard | 2 | * Driver for Gravis UltraSound Classic soundcard |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -37,7 +37,7 @@ | |||
37 | #define DEV_NAME "gusclassic" | 37 | #define DEV_NAME "gusclassic" |
38 | 38 | ||
39 | MODULE_DESCRIPTION(CRD_NAME); | 39 | MODULE_DESCRIPTION(CRD_NAME); |
40 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 40 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
41 | MODULE_LICENSE("GPL"); | 41 | MODULE_LICENSE("GPL"); |
42 | MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}"); | 42 | MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}"); |
43 | 43 | ||
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index 0aeaa6cf6cf0..fc59536c918e 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Gravis UltraSound Extreme soundcards | 2 | * Driver for Gravis UltraSound Extreme soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -41,7 +41,7 @@ | |||
41 | #define DEV_NAME "gusextreme" | 41 | #define DEV_NAME "gusextreme" |
42 | 42 | ||
43 | MODULE_DESCRIPTION(CRD_NAME); | 43 | MODULE_DESCRIPTION(CRD_NAME); |
44 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 44 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
45 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
46 | MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}"); | 46 | MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}"); |
47 | 47 | ||
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index 708783d4351f..4922f5da08f9 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Gravis UltraSound MAX soundcard | 2 | * Driver for Gravis UltraSound MAX soundcard |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -34,7 +34,7 @@ | |||
34 | #define SNDRV_LEGACY_FIND_FREE_DMA | 34 | #define SNDRV_LEGACY_FIND_FREE_DMA |
35 | #include <sound/initval.h> | 35 | #include <sound/initval.h> |
36 | 36 | ||
37 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 37 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
38 | MODULE_DESCRIPTION("Gravis UltraSound MAX"); | 38 | MODULE_DESCRIPTION("Gravis UltraSound MAX"); |
39 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound MAX}}"); | 40 | MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound MAX}}"); |
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 0220cdbe1a2a..2091c50b2e3e 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for AMD InterWave soundcard | 2 | * Driver for AMD InterWave soundcard |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -41,7 +41,7 @@ | |||
41 | #define SNDRV_LEGACY_FIND_FREE_DMA | 41 | #define SNDRV_LEGACY_FIND_FREE_DMA |
42 | #include <sound/initval.h> | 42 | #include <sound/initval.h> |
43 | 43 | ||
44 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 44 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
45 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
46 | #ifndef SNDRV_STB | 46 | #ifndef SNDRV_STB |
47 | MODULE_DESCRIPTION("AMD InterWave"); | 47 | MODULE_DESCRIPTION("AMD InterWave"); |
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index e70db32991d9..59af9ab7191f 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Yamaha OPL3-SA[2,3] soundcards | 2 | * Driver for Yamaha OPL3-SA[2,3] soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -37,7 +37,7 @@ | |||
37 | 37 | ||
38 | #include <asm/io.h> | 38 | #include <asm/io.h> |
39 | 39 | ||
40 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 40 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
41 | MODULE_DESCRIPTION("Yamaha OPL3SA2+"); | 41 | MODULE_DESCRIPTION("Yamaha OPL3SA2+"); |
42 | MODULE_LICENSE("GPL"); | 42 | MODULE_LICENSE("GPL"); |
43 | MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF719E-S}," | 43 | MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF719E-S}," |
@@ -253,6 +253,7 @@ static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip) | |||
253 | /* 0x03 - YM715B */ | 253 | /* 0x03 - YM715B */ |
254 | /* 0x04 - YM719 - OPL-SA4? */ | 254 | /* 0x04 - YM719 - OPL-SA4? */ |
255 | /* 0x05 - OPL3-SA3 - Libretto 100 */ | 255 | /* 0x05 - OPL3-SA3 - Libretto 100 */ |
256 | /* 0x07 - unknown - Neomagic MagicWave 3D */ | ||
256 | break; | 257 | break; |
257 | } | 258 | } |
258 | str[0] = chip->version + '0'; | 259 | str[0] = chip->version + '0'; |
diff --git a/sound/isa/opti9xx/Makefile b/sound/isa/opti9xx/Makefile index 0e41bfd5a403..b4d894db257a 100644 --- a/sound/isa/opti9xx/Makefile +++ b/sound/isa/opti9xx/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-opti92x-ad1848-objs := opti92x-ad1848.o | 6 | snd-opti92x-ad1848-objs := opti92x-ad1848.o |
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index cd29b30b362e..d295936611f8 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c | |||
@@ -242,14 +242,7 @@ static int aci_setvalue(struct snd_miro * miro, unsigned char index, int value) | |||
242 | * MIXER part | 242 | * MIXER part |
243 | */ | 243 | */ |
244 | 244 | ||
245 | static int snd_miro_info_capture(struct snd_kcontrol *kcontrol, | 245 | #define snd_miro_info_capture snd_ctl_boolean_mono_info |
246 | struct snd_ctl_elem_info *uinfo) | ||
247 | { | ||
248 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
249 | uinfo->count = 1; | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | 246 | ||
254 | static int snd_miro_get_capture(struct snd_kcontrol *kcontrol, | 247 | static int snd_miro_get_capture(struct snd_kcontrol *kcontrol, |
255 | struct snd_ctl_elem_value *ucontrol) | 248 | struct snd_ctl_elem_value *ucontrol) |
@@ -344,14 +337,7 @@ static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol, | |||
344 | return change; | 337 | return change; |
345 | } | 338 | } |
346 | 339 | ||
347 | static int snd_miro_info_amp(struct snd_kcontrol *kcontrol, | 340 | #define snd_miro_info_amp snd_ctl_boolean_mono_info |
348 | struct snd_ctl_elem_info *uinfo) | ||
349 | { | ||
350 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
351 | uinfo->count = 1; | ||
352 | |||
353 | return 0; | ||
354 | } | ||
355 | 341 | ||
356 | static int snd_miro_get_amp(struct snd_kcontrol *kcontrol, | 342 | static int snd_miro_get_amp(struct snd_kcontrol *kcontrol, |
357 | struct snd_ctl_elem_value *ucontrol) | 343 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 049d479ce2b3..ee1a824d8fc0 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c | |||
@@ -501,6 +501,16 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip) | |||
501 | (chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04), | 501 | (chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04), |
502 | 0x34); | 502 | 0x34); |
503 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf); | 503 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf); |
504 | /* | ||
505 | * The BTC 1817DW has QS1000 wavetable which is connected | ||
506 | * to the serial digital input of the OPTI931. | ||
507 | */ | ||
508 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(21), 0x82, 0xff); | ||
509 | /* | ||
510 | * This bit sets OPTI931 to automaticaly select FM | ||
511 | * or digital input signal. | ||
512 | */ | ||
513 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(26), 0x01, 0x01); | ||
504 | break; | 514 | break; |
505 | #endif /* OPTi93X */ | 515 | #endif /* OPTi93X */ |
506 | 516 | ||
@@ -1732,11 +1742,11 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, | |||
1732 | 1742 | ||
1733 | #ifdef OPTi93X | 1743 | #ifdef OPTi93X |
1734 | port = pnp_port_start(pdev, 0) - 4; | 1744 | port = pnp_port_start(pdev, 0) - 4; |
1735 | fm_port = pnp_port_start(pdev, 1); | 1745 | fm_port = pnp_port_start(pdev, 1) + 8; |
1736 | #else | 1746 | #else |
1737 | if (pid->driver_data != 0x0924) | 1747 | if (pid->driver_data != 0x0924) |
1738 | port = pnp_port_start(pdev, 1); | 1748 | port = pnp_port_start(pdev, 1); |
1739 | fm_port = pnp_port_start(pdev, 2); | 1749 | fm_port = pnp_port_start(pdev, 2) + 8; |
1740 | #endif /* OPTi93X */ | 1750 | #endif /* OPTi93X */ |
1741 | irq = pnp_irq(pdev, 0); | 1751 | irq = pnp_irq(pdev, 0); |
1742 | dma1 = pnp_dma(pdev, 0); | 1752 | dma1 = pnp_dma(pdev, 0); |
diff --git a/sound/isa/sb/Makefile b/sound/isa/sb/Makefile index 556e66928029..c9d1c986d70e 100644 --- a/sound/isa/sb/Makefile +++ b/sound/isa/sb/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-sb-common-objs := sb_common.o sb_mixer.o | 6 | snd-sb-common-objs := sb_common.o sb_mixer.o |
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index 658179e86142..4eea84cfd4f4 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk> | 3 | * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk> |
4 | * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de> | 4 | * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de> |
5 | * | 5 | * |
diff --git a/sound/isa/sb/emu8000_synth.c b/sound/isa/sb/emu8000_synth.c index 3d72742b342f..0c7905c85b76 100644 --- a/sound/isa/sb/emu8000_synth.c +++ b/sound/isa/sb/emu8000_synth.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk> | 3 | * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk> |
4 | * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de> | 4 | * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de> |
5 | * | 5 | * |
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index c4ba24bfd27c..e7f9edd92626 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for SoundBlaster 16/AWE32/AWE64 soundcards | 2 | * Driver for SoundBlaster 16/AWE32/AWE64 soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -44,7 +44,7 @@ | |||
44 | #define PFX "sb16: " | 44 | #define PFX "sb16: " |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 47 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
48 | MODULE_LICENSE("GPL"); | 48 | MODULE_LICENSE("GPL"); |
49 | #ifndef SNDRV_SBAWE | 49 | #ifndef SNDRV_SBAWE |
50 | MODULE_DESCRIPTION("Sound Blaster 16"); | 50 | MODULE_DESCRIPTION("Sound Blaster 16"); |
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index b279f2308aef..3682059787ab 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c | |||
@@ -979,14 +979,7 @@ static int snd_sb_csp_restart(struct snd_sb_csp * p) | |||
979 | * QSound mixer control for PCM | 979 | * QSound mixer control for PCM |
980 | */ | 980 | */ |
981 | 981 | ||
982 | static int snd_sb_qsound_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 982 | #define snd_sb_qsound_switch_info snd_ctl_boolean_mono_info |
983 | { | ||
984 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
985 | uinfo->count = 1; | ||
986 | uinfo->value.integer.min = 0; | ||
987 | uinfo->value.integer.max = 1; | ||
988 | return 0; | ||
989 | } | ||
990 | 983 | ||
991 | static int snd_sb_qsound_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 984 | static int snd_sb_qsound_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
992 | { | 985 | { |
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c index 5d4d3aafe2d5..c06754f7ee5d 100644 --- a/sound/isa/sb/sb16_main.c +++ b/sound/isa/sb/sb16_main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of 16-bit SoundBlaster cards and clones | 3 | * Routines for control of 16-bit SoundBlaster cards and clones |
4 | * Note: This is very ugly hardware which uses one 8-bit DMA channel and | 4 | * Note: This is very ugly hardware which uses one 8-bit DMA channel and |
5 | * second 16-bit DMA channel. Unfortunately 8-bit DMA channel can't | 5 | * second 16-bit DMA channel. Unfortunately 8-bit DMA channel can't |
@@ -45,7 +45,7 @@ | |||
45 | #include <sound/control.h> | 45 | #include <sound/control.h> |
46 | #include <sound/info.h> | 46 | #include <sound/info.h> |
47 | 47 | ||
48 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 48 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
49 | MODULE_DESCRIPTION("Routines for control of 16-bit SoundBlaster cards and clones"); | 49 | MODULE_DESCRIPTION("Routines for control of 16-bit SoundBlaster cards and clones"); |
50 | MODULE_LICENSE("GPL"); | 50 | MODULE_LICENSE("GPL"); |
51 | 51 | ||
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index a1b3786b391e..f933aef7d8a9 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for SoundBlaster 1.0/2.0/Pro soundcards and compatible | 2 | * Driver for SoundBlaster 1.0/2.0/Pro soundcards and compatible |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -31,7 +31,7 @@ | |||
31 | #include <sound/opl3.h> | 31 | #include <sound/opl3.h> |
32 | #include <sound/initval.h> | 32 | #include <sound/initval.h> |
33 | 33 | ||
34 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 34 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
35 | MODULE_DESCRIPTION("Sound Blaster 1.0/2.0/Pro"); | 35 | MODULE_DESCRIPTION("Sound Blaster 1.0/2.0/Pro"); |
36 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
37 | MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}"); | 37 | MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}"); |
diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c index aea9e5ec7b36..bee894b3f5c7 100644 --- a/sound/isa/sb/sb8_main.c +++ b/sound/isa/sb/sb8_main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Uros Bizjak <uros@kss-loka.si> | 3 | * Uros Bizjak <uros@kss-loka.si> |
4 | * | 4 | * |
5 | * Routines for control of 8-bit SoundBlaster cards and clones | 5 | * Routines for control of 8-bit SoundBlaster cards and clones |
@@ -38,7 +38,7 @@ | |||
38 | #include <sound/core.h> | 38 | #include <sound/core.h> |
39 | #include <sound/sb.h> | 39 | #include <sound/sb.h> |
40 | 40 | ||
41 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Uros Bizjak <uros@kss-loka.si>"); | 41 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Uros Bizjak <uros@kss-loka.si>"); |
42 | MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones"); | 42 | MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones"); |
43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
44 | 44 | ||
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c index 0b67edd7ac6e..e56e5633411c 100644 --- a/sound/isa/sb/sb8_midi.c +++ b/sound/isa/sb/sb8_midi.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of SoundBlaster cards - MIDI interface | 3 | * Routines for control of SoundBlaster cards - MIDI interface |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c index efa9d5c2558a..176193c05101 100644 --- a/sound/isa/sb/sb_common.c +++ b/sound/isa/sb/sb_common.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Uros Bizjak <uros@kss-loka.si> | 3 | * Uros Bizjak <uros@kss-loka.si> |
4 | * | 4 | * |
5 | * Lowlevel routines for control of Sound Blaster cards | 5 | * Lowlevel routines for control of Sound Blaster cards |
@@ -33,7 +33,7 @@ | |||
33 | #include <asm/io.h> | 33 | #include <asm/io.h> |
34 | #include <asm/dma.h> | 34 | #include <asm/dma.h> |
35 | 35 | ||
36 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 36 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
37 | MODULE_DESCRIPTION("ALSA lowlevel driver for Sound Blaster cards"); | 37 | MODULE_DESCRIPTION("ALSA lowlevel driver for Sound Blaster cards"); |
38 | MODULE_LICENSE("GPL"); | 38 | MODULE_LICENSE("GPL"); |
39 | 39 | ||
@@ -234,7 +234,9 @@ int snd_sbdsp_create(struct snd_card *card, | |||
234 | chip->dma16 = -1; | 234 | chip->dma16 = -1; |
235 | chip->port = port; | 235 | chip->port = port; |
236 | 236 | ||
237 | if (request_irq(irq, irq_handler, hardware == SB_HW_ALS4000 ? | 237 | if (request_irq(irq, irq_handler, |
238 | (hardware == SB_HW_ALS4000 || | ||
239 | hardware == SB_HW_CS5530) ? | ||
238 | IRQF_SHARED : IRQF_DISABLED, | 240 | IRQF_SHARED : IRQF_DISABLED, |
239 | "SoundBlaster", (void *) chip)) { | 241 | "SoundBlaster", (void *) chip)) { |
240 | snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq); | 242 | snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq); |
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index 3d4befcff28e..03241cd5aaef 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for Sound Blaster mixer control | 3 | * Routines for Sound Blaster mixer control |
4 | * | 4 | * |
5 | * | 5 | * |
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c new file mode 100644 index 000000000000..94daf8399994 --- /dev/null +++ b/sound/isa/sc6000.c | |||
@@ -0,0 +1,656 @@ | |||
1 | /* | ||
2 | * Driver for Gallant SC-6000 soundcard. This card is also known as | ||
3 | * Audio Excel DSP 16 or Zoltrix AV302. | ||
4 | * These cards use CompuMedia ASC-9308 chip + AD1848 codec. | ||
5 | * | ||
6 | * Copyright (C) 2007 Krzysztof Helt <krzysztof.h1@wp.pl> | ||
7 | * | ||
8 | * I don't have documentation for this card. I used the driver | ||
9 | * for OSS/Free included in the kernel source as reference. | ||
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 | #include <sound/driver.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/isa.h> | ||
30 | #include <linux/io.h> | ||
31 | #include <asm/dma.h> | ||
32 | #include <sound/core.h> | ||
33 | #include <sound/ad1848.h> | ||
34 | #include <sound/opl3.h> | ||
35 | #include <sound/mpu401.h> | ||
36 | #include <sound/control.h> | ||
37 | #define SNDRV_LEGACY_FIND_FREE_IRQ | ||
38 | #define SNDRV_LEGACY_FIND_FREE_DMA | ||
39 | #include <sound/initval.h> | ||
40 | |||
41 | MODULE_AUTHOR("Krzysztof Helt"); | ||
42 | MODULE_DESCRIPTION("Gallant SC-6000"); | ||
43 | MODULE_LICENSE("GPL"); | ||
44 | MODULE_SUPPORTED_DEVICE("{{Gallant, SC-6000}," | ||
45 | "{AudioExcel, Audio Excel DSP 16}," | ||
46 | "{Zoltrix, AV302}}"); | ||
47 | |||
48 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | ||
49 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | ||
50 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ | ||
51 | static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220, 0x240 */ | ||
52 | static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5, 7, 9, 10, 11 */ | ||
53 | static long mss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530, 0xe80 */ | ||
54 | static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; | ||
55 | /* 0x300, 0x310, 0x320, 0x330 */ | ||
56 | static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5, 7, 9, 10, 0 */ | ||
57 | static int dma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0, 1, 3 */ | ||
58 | |||
59 | module_param_array(index, int, NULL, 0444); | ||
60 | MODULE_PARM_DESC(index, "Index value for sc-6000 based soundcard."); | ||
61 | module_param_array(id, charp, NULL, 0444); | ||
62 | MODULE_PARM_DESC(id, "ID string for sc-6000 based soundcard."); | ||
63 | module_param_array(enable, bool, NULL, 0444); | ||
64 | MODULE_PARM_DESC(enable, "Enable sc-6000 based soundcard."); | ||
65 | module_param_array(port, long, NULL, 0444); | ||
66 | MODULE_PARM_DESC(port, "Port # for sc-6000 driver."); | ||
67 | module_param_array(mss_port, long, NULL, 0444); | ||
68 | MODULE_PARM_DESC(mss_port, "MSS Port # for sc-6000 driver."); | ||
69 | module_param_array(mpu_port, long, NULL, 0444); | ||
70 | MODULE_PARM_DESC(mpu_port, "MPU-401 port # for sc-6000 driver."); | ||
71 | module_param_array(irq, int, NULL, 0444); | ||
72 | MODULE_PARM_DESC(irq, "IRQ # for sc-6000 driver."); | ||
73 | module_param_array(mpu_irq, int, NULL, 0444); | ||
74 | MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for sc-6000 driver."); | ||
75 | module_param_array(dma, int, NULL, 0444); | ||
76 | MODULE_PARM_DESC(dma, "DMA # for sc-6000 driver."); | ||
77 | |||
78 | /* | ||
79 | * Commands of SC6000's DSP (SBPRO+special). | ||
80 | * Some of them are COMMAND_xx, in the future they may change. | ||
81 | */ | ||
82 | #define WRITE_MDIRQ_CFG 0x50 /* Set M&I&DRQ mask (the real config) */ | ||
83 | #define COMMAND_52 0x52 /* */ | ||
84 | #define READ_HARD_CFG 0x58 /* Read Hardware Config (I/O base etc) */ | ||
85 | #define COMMAND_5C 0x5c /* */ | ||
86 | #define COMMAND_60 0x60 /* */ | ||
87 | #define COMMAND_66 0x66 /* */ | ||
88 | #define COMMAND_6C 0x6c /* */ | ||
89 | #define COMMAND_6E 0x6e /* */ | ||
90 | #define COMMAND_88 0x88 /* Unknown command */ | ||
91 | #define DSP_INIT_MSS 0x8c /* Enable Microsoft Sound System mode */ | ||
92 | #define COMMAND_C5 0xc5 /* */ | ||
93 | #define GET_DSP_VERSION 0xe1 /* Get DSP Version */ | ||
94 | #define GET_DSP_COPYRIGHT 0xe3 /* Get DSP Copyright */ | ||
95 | |||
96 | /* | ||
97 | * Offsets of SC6000 DSP I/O ports. The offset is added to base I/O port | ||
98 | * to have the actual I/O port. | ||
99 | * Register permissions are: | ||
100 | * (wo) == Write Only | ||
101 | * (ro) == Read Only | ||
102 | * (w-) == Write | ||
103 | * (r-) == Read | ||
104 | */ | ||
105 | #define DSP_RESET 0x06 /* offset of DSP RESET (wo) */ | ||
106 | #define DSP_READ 0x0a /* offset of DSP READ (ro) */ | ||
107 | #define DSP_WRITE 0x0c /* offset of DSP WRITE (w-) */ | ||
108 | #define DSP_COMMAND 0x0c /* offset of DSP COMMAND (w-) */ | ||
109 | #define DSP_STATUS 0x0c /* offset of DSP STATUS (r-) */ | ||
110 | #define DSP_DATAVAIL 0x0e /* offset of DSP DATA AVAILABLE (ro) */ | ||
111 | |||
112 | #define PFX "sc6000: " | ||
113 | #define DRV_NAME "SC-6000" | ||
114 | |||
115 | /* hardware dependent functions */ | ||
116 | |||
117 | /* | ||
118 | * sc6000_irq_to_softcfg - Decode irq number into cfg code. | ||
119 | */ | ||
120 | static __devinit unsigned char sc6000_irq_to_softcfg(int irq) | ||
121 | { | ||
122 | unsigned char val = 0; | ||
123 | |||
124 | switch (irq) { | ||
125 | case 5: | ||
126 | val = 0x28; | ||
127 | break; | ||
128 | case 7: | ||
129 | val = 0x8; | ||
130 | break; | ||
131 | case 9: | ||
132 | val = 0x10; | ||
133 | break; | ||
134 | case 10: | ||
135 | val = 0x18; | ||
136 | break; | ||
137 | case 11: | ||
138 | val = 0x20; | ||
139 | break; | ||
140 | default: | ||
141 | break; | ||
142 | } | ||
143 | return val; | ||
144 | } | ||
145 | |||
146 | /* | ||
147 | * sc6000_dma_to_softcfg - Decode dma number into cfg code. | ||
148 | */ | ||
149 | static __devinit unsigned char sc6000_dma_to_softcfg(int dma) | ||
150 | { | ||
151 | unsigned char val = 0; | ||
152 | |||
153 | switch (dma) { | ||
154 | case 0: | ||
155 | val = 1; | ||
156 | break; | ||
157 | case 1: | ||
158 | val = 2; | ||
159 | break; | ||
160 | case 3: | ||
161 | val = 3; | ||
162 | break; | ||
163 | default: | ||
164 | break; | ||
165 | } | ||
166 | return val; | ||
167 | } | ||
168 | |||
169 | /* | ||
170 | * sc6000_mpu_irq_to_softcfg - Decode MPU-401 irq number into cfg code. | ||
171 | */ | ||
172 | static __devinit unsigned char sc6000_mpu_irq_to_softcfg(int mpu_irq) | ||
173 | { | ||
174 | unsigned char val = 0; | ||
175 | |||
176 | switch (mpu_irq) { | ||
177 | case 5: | ||
178 | val = 4; | ||
179 | break; | ||
180 | case 7: | ||
181 | val = 0x44; | ||
182 | break; | ||
183 | case 9: | ||
184 | val = 0x84; | ||
185 | break; | ||
186 | case 10: | ||
187 | val = 0xc4; | ||
188 | break; | ||
189 | default: | ||
190 | break; | ||
191 | } | ||
192 | return val; | ||
193 | } | ||
194 | |||
195 | static __devinit int sc6000_wait_data(char __iomem *vport) | ||
196 | { | ||
197 | int loop = 1000; | ||
198 | unsigned char val = 0; | ||
199 | |||
200 | do { | ||
201 | val = ioread8(vport + DSP_DATAVAIL); | ||
202 | if (val & 0x80) | ||
203 | return 0; | ||
204 | cpu_relax(); | ||
205 | } while (loop--); | ||
206 | |||
207 | return -EAGAIN; | ||
208 | } | ||
209 | |||
210 | static __devinit int sc6000_read(char __iomem *vport) | ||
211 | { | ||
212 | if (sc6000_wait_data(vport)) | ||
213 | return -EBUSY; | ||
214 | |||
215 | return ioread8(vport + DSP_READ); | ||
216 | |||
217 | } | ||
218 | |||
219 | static __devinit int sc6000_write(char __iomem *vport, int cmd) | ||
220 | { | ||
221 | unsigned char val; | ||
222 | int loop = 500000; | ||
223 | |||
224 | do { | ||
225 | val = ioread8(vport + DSP_STATUS); | ||
226 | /* | ||
227 | * DSP ready to receive data if bit 7 of val == 0 | ||
228 | */ | ||
229 | if (!(val & 0x80)) { | ||
230 | iowrite8(cmd, vport + DSP_COMMAND); | ||
231 | return 0; | ||
232 | } | ||
233 | cpu_relax(); | ||
234 | } while (loop--); | ||
235 | |||
236 | snd_printk(KERN_ERR "DSP Command (0x%x) timeout.\n", cmd); | ||
237 | |||
238 | return -EIO; | ||
239 | } | ||
240 | |||
241 | static int __devinit sc6000_dsp_get_answer(char __iomem *vport, int command, | ||
242 | char *data, int data_len) | ||
243 | { | ||
244 | int len = 0; | ||
245 | |||
246 | if (sc6000_write(vport, command)) { | ||
247 | snd_printk(KERN_ERR "CMD 0x%x: failed!\n", command); | ||
248 | return -EIO; | ||
249 | } | ||
250 | |||
251 | do { | ||
252 | int val = sc6000_read(vport); | ||
253 | |||
254 | if (val < 0) | ||
255 | break; | ||
256 | |||
257 | data[len++] = val; | ||
258 | |||
259 | } while (len < data_len); | ||
260 | |||
261 | /* | ||
262 | * If no more data available, return to the caller, no error if len>0. | ||
263 | * We have no other way to know when the string is finished. | ||
264 | */ | ||
265 | return len ? len : -EIO; | ||
266 | } | ||
267 | |||
268 | static int __devinit sc6000_dsp_reset(char __iomem *vport) | ||
269 | { | ||
270 | iowrite8(1, vport + DSP_RESET); | ||
271 | udelay(10); | ||
272 | iowrite8(0, vport + DSP_RESET); | ||
273 | udelay(20); | ||
274 | if (sc6000_read(vport) == 0xaa) | ||
275 | return 0; | ||
276 | return -ENODEV; | ||
277 | } | ||
278 | |||
279 | /* detection and initialization */ | ||
280 | static int __devinit sc6000_cfg_write(char __iomem *vport, | ||
281 | unsigned char softcfg) | ||
282 | { | ||
283 | |||
284 | if (sc6000_write(vport, WRITE_MDIRQ_CFG)) { | ||
285 | snd_printk(KERN_ERR "CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG); | ||
286 | return -EIO; | ||
287 | } | ||
288 | if (sc6000_write(vport, softcfg)) { | ||
289 | snd_printk(KERN_ERR "sc6000_cfg_write: failed!\n"); | ||
290 | return -EIO; | ||
291 | } | ||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static int __devinit sc6000_setup_board(char __iomem *vport, int config) | ||
296 | { | ||
297 | int loop = 10; | ||
298 | |||
299 | do { | ||
300 | if (sc6000_write(vport, COMMAND_88)) { | ||
301 | snd_printk(KERN_ERR "CMD 0x%x: failed!\n", | ||
302 | COMMAND_88); | ||
303 | return -EIO; | ||
304 | } | ||
305 | } while ((sc6000_wait_data(vport) < 0) && loop--); | ||
306 | |||
307 | if (sc6000_read(vport) < 0) { | ||
308 | snd_printk(KERN_ERR "sc6000_read after CMD 0x%x: failed\n", | ||
309 | COMMAND_88); | ||
310 | return -EIO; | ||
311 | } | ||
312 | |||
313 | if (sc6000_cfg_write(vport, config)) | ||
314 | return -ENODEV; | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static int __devinit sc6000_init_mss(char __iomem *vport, int config, | ||
320 | char __iomem *vmss_port, int mss_config) | ||
321 | { | ||
322 | if (sc6000_write(vport, DSP_INIT_MSS)) { | ||
323 | snd_printk(KERN_ERR "sc6000_init_mss [0x%x]: failed!\n", | ||
324 | DSP_INIT_MSS); | ||
325 | return -EIO; | ||
326 | } | ||
327 | |||
328 | msleep(10); | ||
329 | |||
330 | if (sc6000_cfg_write(vport, config)) | ||
331 | return -EIO; | ||
332 | |||
333 | iowrite8(mss_config, vmss_port); | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static int __devinit sc6000_init_board(char __iomem *vport, int irq, int dma, | ||
339 | char __iomem *vmss_port, int mpu_irq) | ||
340 | { | ||
341 | char answer[15]; | ||
342 | char version[2]; | ||
343 | int mss_config = sc6000_irq_to_softcfg(irq) | | ||
344 | sc6000_dma_to_softcfg(dma); | ||
345 | int config = mss_config | | ||
346 | sc6000_mpu_irq_to_softcfg(mpu_irq); | ||
347 | int err; | ||
348 | |||
349 | err = sc6000_dsp_reset(vport); | ||
350 | if (err < 0) { | ||
351 | snd_printk(KERN_ERR "sc6000_dsp_reset: failed!\n"); | ||
352 | return err; | ||
353 | } | ||
354 | |||
355 | memset(answer, 0, sizeof(answer)); | ||
356 | err = sc6000_dsp_get_answer(vport, GET_DSP_COPYRIGHT, answer, 15); | ||
357 | if (err <= 0) { | ||
358 | snd_printk(KERN_ERR "sc6000_dsp_copyright: failed!\n"); | ||
359 | return -ENODEV; | ||
360 | } | ||
361 | /* | ||
362 | * My SC-6000 card return "SC-6000" in DSPCopyright, so | ||
363 | * if we have something different, we have to be warned. | ||
364 | * Mine returns "SC-6000A " - KH | ||
365 | */ | ||
366 | if (strncmp("SC-6000", answer, 7)) | ||
367 | snd_printk(KERN_WARNING "Warning: non SC-6000 audio card!\n"); | ||
368 | |||
369 | if (sc6000_dsp_get_answer(vport, GET_DSP_VERSION, version, 2) < 2) { | ||
370 | snd_printk(KERN_ERR "sc6000_dsp_version: failed!\n"); | ||
371 | return -ENODEV; | ||
372 | } | ||
373 | printk(KERN_INFO PFX "Detected model: %s, DSP version %d.%d\n", | ||
374 | answer, version[0], version[1]); | ||
375 | |||
376 | /* | ||
377 | * 0x0A == (IRQ 7, DMA 1, MIRQ 0) | ||
378 | */ | ||
379 | err = sc6000_cfg_write(vport, 0x0a); | ||
380 | if (err < 0) { | ||
381 | snd_printk(KERN_ERR "sc6000_cfg_write: failed!\n"); | ||
382 | return -EFAULT; | ||
383 | } | ||
384 | |||
385 | err = sc6000_setup_board(vport, config); | ||
386 | if (err < 0) { | ||
387 | snd_printk(KERN_ERR "sc6000_setup_board: failed!\n"); | ||
388 | return -ENODEV; | ||
389 | } | ||
390 | |||
391 | err = sc6000_init_mss(vport, config, vmss_port, mss_config); | ||
392 | if (err < 0) { | ||
393 | snd_printk(KERN_ERR "Can not initialize" | ||
394 | "Microsoft Sound System mode.\n"); | ||
395 | return -ENODEV; | ||
396 | } | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static int __devinit snd_sc6000_mixer(struct snd_ad1848 *chip) | ||
402 | { | ||
403 | struct snd_card *card = chip->card; | ||
404 | struct snd_ctl_elem_id id1, id2; | ||
405 | int err; | ||
406 | |||
407 | memset(&id1, 0, sizeof(id1)); | ||
408 | memset(&id2, 0, sizeof(id2)); | ||
409 | id1.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
410 | id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
411 | /* reassign AUX0 to FM */ | ||
412 | strcpy(id1.name, "Aux Playback Switch"); | ||
413 | strcpy(id2.name, "FM Playback Switch"); | ||
414 | err = snd_ctl_rename_id(card, &id1, &id2); | ||
415 | if (err < 0) | ||
416 | return err; | ||
417 | strcpy(id1.name, "Aux Playback Volume"); | ||
418 | strcpy(id2.name, "FM Playback Volume"); | ||
419 | err = snd_ctl_rename_id(card, &id1, &id2); | ||
420 | if (err < 0) | ||
421 | return err; | ||
422 | /* reassign AUX1 to CD */ | ||
423 | strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; | ||
424 | strcpy(id2.name, "CD Playback Switch"); | ||
425 | err = snd_ctl_rename_id(card, &id1, &id2); | ||
426 | if (err < 0) | ||
427 | return err; | ||
428 | strcpy(id1.name, "Aux Playback Volume"); | ||
429 | strcpy(id2.name, "CD Playback Volume"); | ||
430 | err = snd_ctl_rename_id(card, &id1, &id2); | ||
431 | if (err < 0) | ||
432 | return err; | ||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static int __devinit snd_sc6000_match(struct device *devptr, unsigned int dev) | ||
437 | { | ||
438 | if (!enable[dev]) | ||
439 | return 0; | ||
440 | if (port[dev] == SNDRV_AUTO_PORT) { | ||
441 | printk(KERN_ERR PFX "specify IO port\n"); | ||
442 | return 0; | ||
443 | } | ||
444 | if (mss_port[dev] == SNDRV_AUTO_PORT) { | ||
445 | printk(KERN_ERR PFX "specify MSS port\n"); | ||
446 | return 0; | ||
447 | } | ||
448 | if (port[dev] != 0x220 && port[dev] != 0x240) { | ||
449 | printk(KERN_ERR PFX "Port must be 0x220 or 0x240\n"); | ||
450 | return 0; | ||
451 | } | ||
452 | if (mss_port[dev] != 0x530 && mss_port[dev] != 0xe80) { | ||
453 | printk(KERN_ERR PFX "MSS port must be 0x530 or 0xe80\n"); | ||
454 | return 0; | ||
455 | } | ||
456 | if (irq[dev] != SNDRV_AUTO_IRQ && !sc6000_irq_to_softcfg(irq[dev])) { | ||
457 | printk(KERN_ERR PFX "invalid IRQ %d\n", irq[dev]); | ||
458 | return 0; | ||
459 | } | ||
460 | if (dma[dev] != SNDRV_AUTO_DMA && !sc6000_dma_to_softcfg(dma[dev])) { | ||
461 | printk(KERN_ERR PFX "invalid DMA %d\n", dma[dev]); | ||
462 | return 0; | ||
463 | } | ||
464 | if (mpu_port[dev] != SNDRV_AUTO_PORT && | ||
465 | (mpu_port[dev] & ~0x30L) != 0x300) { | ||
466 | printk(KERN_ERR PFX "invalid MPU-401 port %lx\n", | ||
467 | mpu_port[dev]); | ||
468 | return 0; | ||
469 | } | ||
470 | if (mpu_port[dev] != SNDRV_AUTO_PORT && | ||
471 | mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] != 0 && | ||
472 | !sc6000_mpu_irq_to_softcfg(mpu_irq[dev])) { | ||
473 | printk(KERN_ERR PFX "invalid MPU-401 IRQ %d\n", mpu_irq[dev]); | ||
474 | return 0; | ||
475 | } | ||
476 | return 1; | ||
477 | } | ||
478 | |||
479 | static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) | ||
480 | { | ||
481 | static int possible_irqs[] = { 5, 7, 9, 10, 11, -1 }; | ||
482 | static int possible_dmas[] = { 1, 3, 0, -1 }; | ||
483 | int err; | ||
484 | int xirq = irq[dev]; | ||
485 | int xdma = dma[dev]; | ||
486 | struct snd_card *card; | ||
487 | struct snd_ad1848 *chip; | ||
488 | struct snd_opl3 *opl3; | ||
489 | char __iomem *vport; | ||
490 | char __iomem *vmss_port; | ||
491 | |||
492 | |||
493 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | ||
494 | if (!card) | ||
495 | return -ENOMEM; | ||
496 | |||
497 | if (xirq == SNDRV_AUTO_IRQ) { | ||
498 | xirq = snd_legacy_find_free_irq(possible_irqs); | ||
499 | if (xirq < 0) { | ||
500 | snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); | ||
501 | err = -EBUSY; | ||
502 | goto err_exit; | ||
503 | } | ||
504 | } | ||
505 | |||
506 | if (xdma == SNDRV_AUTO_DMA) { | ||
507 | xdma = snd_legacy_find_free_dma(possible_dmas); | ||
508 | if (xdma < 0) { | ||
509 | snd_printk(KERN_ERR PFX "unable to find a free DMA\n"); | ||
510 | err = -EBUSY; | ||
511 | goto err_exit; | ||
512 | } | ||
513 | } | ||
514 | |||
515 | if (!request_region(port[dev], 0x10, DRV_NAME)) { | ||
516 | snd_printk(KERN_ERR PFX | ||
517 | "I/O port region is already in use.\n"); | ||
518 | err = -EBUSY; | ||
519 | goto err_exit; | ||
520 | } | ||
521 | vport = devm_ioport_map(devptr, port[dev], 0x10); | ||
522 | if (!vport) { | ||
523 | snd_printk(KERN_ERR PFX | ||
524 | "I/O port cannot be iomaped.\n"); | ||
525 | err = -EBUSY; | ||
526 | goto err_unmap1; | ||
527 | } | ||
528 | |||
529 | /* to make it marked as used */ | ||
530 | if (!request_region(mss_port[dev], 4, DRV_NAME)) { | ||
531 | snd_printk(KERN_ERR PFX | ||
532 | "SC-6000 port I/O port region is already in use.\n"); | ||
533 | err = -EBUSY; | ||
534 | goto err_unmap1; | ||
535 | } | ||
536 | vmss_port = devm_ioport_map(devptr, mss_port[dev], 4); | ||
537 | if (!vport) { | ||
538 | snd_printk(KERN_ERR PFX | ||
539 | "MSS port I/O cannot be iomaped.\n"); | ||
540 | err = -EBUSY; | ||
541 | goto err_unmap2; | ||
542 | } | ||
543 | |||
544 | snd_printd("Initializing BASE[0x%lx] IRQ[%d] DMA[%d] MIRQ[%d]\n", | ||
545 | port[dev], xirq, xdma, | ||
546 | mpu_irq[dev] == SNDRV_AUTO_IRQ ? 0 : mpu_irq[dev]); | ||
547 | |||
548 | err = sc6000_init_board(vport, xirq, xdma, vmss_port, mpu_irq[dev]); | ||
549 | if (err < 0) | ||
550 | goto err_unmap2; | ||
551 | |||
552 | err = snd_ad1848_create(card, mss_port[dev] + 4, xirq, xdma, | ||
553 | AD1848_HW_DETECT, &chip); | ||
554 | if (err < 0) | ||
555 | goto err_unmap2; | ||
556 | card->private_data = chip; | ||
557 | |||
558 | err = snd_ad1848_pcm(chip, 0, NULL); | ||
559 | if (err < 0) { | ||
560 | snd_printk(KERN_ERR PFX | ||
561 | "error creating new ad1848 PCM device\n"); | ||
562 | goto err_unmap2; | ||
563 | } | ||
564 | err = snd_ad1848_mixer(chip); | ||
565 | if (err < 0) { | ||
566 | snd_printk(KERN_ERR PFX "error creating new ad1848 mixer\n"); | ||
567 | goto err_unmap2; | ||
568 | } | ||
569 | err = snd_sc6000_mixer(chip); | ||
570 | if (err < 0) { | ||
571 | snd_printk(KERN_ERR PFX "the mixer rewrite failed\n"); | ||
572 | goto err_unmap2; | ||
573 | } | ||
574 | if (snd_opl3_create(card, | ||
575 | 0x388, 0x388 + 2, | ||
576 | OPL3_HW_AUTO, 0, &opl3) < 0) { | ||
577 | snd_printk(KERN_ERR PFX "no OPL device at 0x%x-0x%x ?\n", | ||
578 | 0x388, 0x388 + 2); | ||
579 | } else { | ||
580 | err = snd_opl3_timer_new(opl3, 0, 1); | ||
581 | if (err < 0) | ||
582 | goto err_unmap2; | ||
583 | |||
584 | err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); | ||
585 | if (err < 0) | ||
586 | goto err_unmap2; | ||
587 | } | ||
588 | |||
589 | if (mpu_port[dev] != SNDRV_AUTO_PORT) { | ||
590 | if (mpu_irq[dev] == SNDRV_AUTO_IRQ) | ||
591 | mpu_irq[dev] = -1; | ||
592 | if (snd_mpu401_uart_new(card, 0, | ||
593 | MPU401_HW_MPU401, | ||
594 | mpu_port[dev], 0, | ||
595 | mpu_irq[dev], IRQF_DISABLED, | ||
596 | NULL) < 0) | ||
597 | snd_printk(KERN_ERR "no MPU-401 device at 0x%lx ?\n", | ||
598 | mpu_port[dev]); | ||
599 | } | ||
600 | |||
601 | strcpy(card->driver, DRV_NAME); | ||
602 | strcpy(card->shortname, "SC-6000"); | ||
603 | sprintf(card->longname, "Gallant SC-6000 at 0x%lx, irq %d, dma %d", | ||
604 | mss_port[dev], xirq, xdma); | ||
605 | |||
606 | snd_card_set_dev(card, devptr); | ||
607 | |||
608 | err = snd_card_register(card); | ||
609 | if (err < 0) | ||
610 | goto err_unmap2; | ||
611 | |||
612 | dev_set_drvdata(devptr, card); | ||
613 | return 0; | ||
614 | |||
615 | err_unmap2: | ||
616 | release_region(mss_port[dev], 4); | ||
617 | err_unmap1: | ||
618 | release_region(port[dev], 0x10); | ||
619 | err_exit: | ||
620 | snd_card_free(card); | ||
621 | return err; | ||
622 | } | ||
623 | |||
624 | static int __devexit snd_sc6000_remove(struct device *devptr, unsigned int dev) | ||
625 | { | ||
626 | release_region(port[dev], 0x10); | ||
627 | release_region(mss_port[dev], 4); | ||
628 | |||
629 | snd_card_free(dev_get_drvdata(devptr)); | ||
630 | dev_set_drvdata(devptr, NULL); | ||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | static struct isa_driver snd_sc6000_driver = { | ||
635 | .match = snd_sc6000_match, | ||
636 | .probe = snd_sc6000_probe, | ||
637 | .remove = __devexit_p(snd_sc6000_remove), | ||
638 | /* FIXME: suspend/resume */ | ||
639 | .driver = { | ||
640 | .name = DRV_NAME, | ||
641 | }, | ||
642 | }; | ||
643 | |||
644 | |||
645 | static int __init alsa_card_sc6000_init(void) | ||
646 | { | ||
647 | return isa_register_driver(&snd_sc6000_driver, SNDRV_CARDS); | ||
648 | } | ||
649 | |||
650 | static void __exit alsa_card_sc6000_exit(void) | ||
651 | { | ||
652 | isa_unregister_driver(&snd_sc6000_driver); | ||
653 | } | ||
654 | |||
655 | module_init(alsa_card_sc6000_init) | ||
656 | module_exit(alsa_card_sc6000_exit) | ||
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index cbad2a51cbaa..1cb921d6137e 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c | |||
@@ -45,10 +45,12 @@ MODULE_LICENSE("GPL"); | |||
45 | 45 | ||
46 | static int index[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IDX; | 46 | static int index[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IDX; |
47 | static char* id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_STR; | 47 | static char* id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_STR; |
48 | static long port[SNDRV_CARDS] __devinitdata = { [0 ... (SNDRV_CARDS-1)] = SNDRV_AUTO_PORT }; | 48 | static long port[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PORT; |
49 | static long wss_port[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PORT; | ||
49 | static int irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ; | 50 | static int irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ; |
50 | static int mpu_irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ; | 51 | static int mpu_irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ; |
51 | static int dma[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA; | 52 | static int dma[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA; |
53 | static int dma2[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA; | ||
52 | 54 | ||
53 | module_param_array(index, int, NULL, 0444); | 55 | module_param_array(index, int, NULL, 0444); |
54 | MODULE_PARM_DESC(index, "Index number for SoundScape soundcard"); | 56 | MODULE_PARM_DESC(index, "Index number for SoundScape soundcard"); |
@@ -59,6 +61,9 @@ MODULE_PARM_DESC(id, "Description for SoundScape card"); | |||
59 | module_param_array(port, long, NULL, 0444); | 61 | module_param_array(port, long, NULL, 0444); |
60 | MODULE_PARM_DESC(port, "Port # for SoundScape driver."); | 62 | MODULE_PARM_DESC(port, "Port # for SoundScape driver."); |
61 | 63 | ||
64 | module_param_array(wss_port, long, NULL, 0444); | ||
65 | MODULE_PARM_DESC(wss_port, "WSS Port # for SoundScape driver."); | ||
66 | |||
62 | module_param_array(irq, int, NULL, 0444); | 67 | module_param_array(irq, int, NULL, 0444); |
63 | MODULE_PARM_DESC(irq, "IRQ # for SoundScape driver."); | 68 | MODULE_PARM_DESC(irq, "IRQ # for SoundScape driver."); |
64 | 69 | ||
@@ -68,12 +73,16 @@ MODULE_PARM_DESC(mpu_irq, "MPU401 IRQ # for SoundScape driver."); | |||
68 | module_param_array(dma, int, NULL, 0444); | 73 | module_param_array(dma, int, NULL, 0444); |
69 | MODULE_PARM_DESC(dma, "DMA # for SoundScape driver."); | 74 | MODULE_PARM_DESC(dma, "DMA # for SoundScape driver."); |
70 | 75 | ||
76 | module_param_array(dma2, int, NULL, 0444); | ||
77 | MODULE_PARM_DESC(dma2, "DMA2 # for SoundScape driver."); | ||
78 | |||
71 | #ifdef CONFIG_PNP | 79 | #ifdef CONFIG_PNP |
72 | static int isa_registered; | 80 | static int isa_registered; |
73 | static int pnp_registered; | 81 | static int pnp_registered; |
74 | 82 | ||
75 | static struct pnp_card_device_id sscape_pnpids[] = { | 83 | static struct pnp_card_device_id sscape_pnpids[] = { |
76 | { .id = "ENS3081", .devs = { { "ENS0000" } } }, | 84 | { .id = "ENS3081", .devs = { { "ENS0000" } } }, /* Soundscape PnP */ |
85 | { .id = "ENS4081", .devs = { { "ENS1011" } } }, /* VIVO90 */ | ||
77 | { .id = "" } /* end */ | 86 | { .id = "" } /* end */ |
78 | }; | 87 | }; |
79 | 88 | ||
@@ -124,12 +133,21 @@ enum GA_REG { | |||
124 | #define AD1845_FREQ_SEL_MSB 0x16 | 133 | #define AD1845_FREQ_SEL_MSB 0x16 |
125 | #define AD1845_FREQ_SEL_LSB 0x17 | 134 | #define AD1845_FREQ_SEL_LSB 0x17 |
126 | 135 | ||
136 | enum card_type { | ||
137 | SSCAPE, | ||
138 | SSCAPE_PNP, | ||
139 | SSCAPE_VIVO, | ||
140 | }; | ||
141 | |||
127 | struct soundscape { | 142 | struct soundscape { |
128 | spinlock_t lock; | 143 | spinlock_t lock; |
129 | unsigned io_base; | 144 | unsigned io_base; |
145 | unsigned wss_base; | ||
130 | int codec_type; | 146 | int codec_type; |
131 | int ic_type; | 147 | int ic_type; |
148 | enum card_type type; | ||
132 | struct resource *io_res; | 149 | struct resource *io_res; |
150 | struct resource *wss_res; | ||
133 | struct snd_cs4231 *chip; | 151 | struct snd_cs4231 *chip; |
134 | struct snd_mpu401 *mpu; | 152 | struct snd_mpu401 *mpu; |
135 | struct snd_hwdep *hw; | 153 | struct snd_hwdep *hw; |
@@ -340,8 +358,9 @@ static inline void activate_ad1845_unsafe(unsigned io_base) | |||
340 | */ | 358 | */ |
341 | static void soundscape_free(struct snd_card *c) | 359 | static void soundscape_free(struct snd_card *c) |
342 | { | 360 | { |
343 | register struct soundscape *sscape = get_card_soundscape(c); | 361 | struct soundscape *sscape = get_card_soundscape(c); |
344 | release_and_free_resource(sscape->io_res); | 362 | release_and_free_resource(sscape->io_res); |
363 | release_and_free_resource(sscape->wss_res); | ||
345 | free_dma(sscape->chip->dma1); | 364 | free_dma(sscape->chip->dma1); |
346 | } | 365 | } |
347 | 366 | ||
@@ -382,7 +401,7 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout) | |||
382 | unsigned long flags; | 401 | unsigned long flags; |
383 | unsigned char x; | 402 | unsigned char x; |
384 | 403 | ||
385 | schedule_timeout(1); | 404 | schedule_timeout_uninterruptible(1); |
386 | 405 | ||
387 | spin_lock_irqsave(&s->lock, flags); | 406 | spin_lock_irqsave(&s->lock, flags); |
388 | x = inb(HOST_DATA_IO(s->io_base)); | 407 | x = inb(HOST_DATA_IO(s->io_base)); |
@@ -409,7 +428,7 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout) | |||
409 | unsigned long flags; | 428 | unsigned long flags; |
410 | unsigned char x; | 429 | unsigned char x; |
411 | 430 | ||
412 | schedule_timeout(1); | 431 | schedule_timeout_uninterruptible(1); |
413 | 432 | ||
414 | spin_lock_irqsave(&s->lock, flags); | 433 | spin_lock_irqsave(&s->lock, flags); |
415 | x = inb(HOST_DATA_IO(s->io_base)); | 434 | x = inb(HOST_DATA_IO(s->io_base)); |
@@ -522,7 +541,7 @@ static int upload_dma_data(struct soundscape *s, | |||
522 | ret = -EAGAIN; | 541 | ret = -EAGAIN; |
523 | } | 542 | } |
524 | 543 | ||
525 | _release_dma: | 544 | _release_dma: |
526 | /* | 545 | /* |
527 | * NOTE!!! We are NOT holding any spinlocks at this point !!! | 546 | * NOTE!!! We are NOT holding any spinlocks at this point !!! |
528 | */ | 547 | */ |
@@ -802,6 +821,7 @@ static int __devinit detect_sscape(struct soundscape *s) | |||
802 | unsigned long flags; | 821 | unsigned long flags; |
803 | unsigned d; | 822 | unsigned d; |
804 | int retval = 0; | 823 | int retval = 0; |
824 | int codec = s->wss_base; | ||
805 | 825 | ||
806 | spin_lock_irqsave(&s->lock, flags); | 826 | spin_lock_irqsave(&s->lock, flags); |
807 | 827 | ||
@@ -833,9 +853,27 @@ static int __devinit detect_sscape(struct soundscape *s) | |||
833 | outb(0xfe, ODIE_ADDR_IO(s->io_base)); | 853 | outb(0xfe, ODIE_ADDR_IO(s->io_base)); |
834 | if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0e) | 854 | if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0e) |
835 | goto _done; | 855 | goto _done; |
836 | if ((inb(ODIE_DATA_IO(s->io_base)) & 0x9f) != 0x0e) | 856 | |
857 | outb(0xfe, ODIE_ADDR_IO(s->io_base)); | ||
858 | d = inb(ODIE_DATA_IO(s->io_base)); | ||
859 | if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e) | ||
837 | goto _done; | 860 | goto _done; |
838 | 861 | ||
862 | d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f; | ||
863 | sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); | ||
864 | |||
865 | if (s->type == SSCAPE_VIVO) | ||
866 | codec += 4; | ||
867 | /* wait for WSS codec */ | ||
868 | for (d = 0; d < 500; d++) { | ||
869 | if ((inb(codec) & 0x80) == 0) | ||
870 | break; | ||
871 | spin_unlock_irqrestore(&s->lock, flags); | ||
872 | msleep(1); | ||
873 | spin_lock_irqsave(&s->lock, flags); | ||
874 | } | ||
875 | snd_printd(KERN_INFO "init delay = %d ms\n", d); | ||
876 | |||
839 | /* | 877 | /* |
840 | * SoundScape successfully detected! | 878 | * SoundScape successfully detected! |
841 | */ | 879 | */ |
@@ -995,21 +1033,23 @@ static void ad1845_capture_format(struct snd_cs4231 * chip, struct snd_pcm_hw_pa | |||
995 | * try to support at least some of the extra bits by overriding | 1033 | * try to support at least some of the extra bits by overriding |
996 | * some of the CS4231 callback. | 1034 | * some of the CS4231 callback. |
997 | */ | 1035 | */ |
998 | static int __devinit create_ad1845(struct snd_card *card, unsigned port, int irq, int dma1) | 1036 | static int __devinit create_ad1845(struct snd_card *card, unsigned port, |
1037 | int irq, int dma1, int dma2) | ||
999 | { | 1038 | { |
1000 | register struct soundscape *sscape = get_card_soundscape(card); | 1039 | register struct soundscape *sscape = get_card_soundscape(card); |
1001 | struct snd_cs4231 *chip; | 1040 | struct snd_cs4231 *chip; |
1002 | int err; | 1041 | int err; |
1003 | 1042 | ||
1004 | #define CS4231_SHARE_HARDWARE (CS4231_HWSHARE_DMA1 | CS4231_HWSHARE_DMA2) | 1043 | if (sscape->type == SSCAPE_VIVO) |
1005 | /* | 1044 | port += 4; |
1006 | * The AD1845 PCM device is only half-duplex, and so | 1045 | |
1007 | * we only give it one DMA channel ... | 1046 | if (dma1 == dma2) |
1008 | */ | 1047 | dma2 = -1; |
1009 | if ((err = snd_cs4231_create(card, | 1048 | |
1010 | port, -1, irq, dma1, dma1, | 1049 | err = snd_cs4231_create(card, |
1011 | CS4231_HW_DETECT, | 1050 | port, -1, irq, dma1, dma2, |
1012 | CS4231_HWSHARE_DMA1, &chip)) == 0) { | 1051 | CS4231_HW_DETECT, CS4231_HWSHARE_DMA1, &chip); |
1052 | if (!err) { | ||
1013 | unsigned long flags; | 1053 | unsigned long flags; |
1014 | struct snd_pcm *pcm; | 1054 | struct snd_pcm *pcm; |
1015 | 1055 | ||
@@ -1031,49 +1071,72 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, int irq | |||
1031 | snd_cs4231_mce_down(chip); | 1071 | snd_cs4231_mce_down(chip); |
1032 | */ | 1072 | */ |
1033 | 1073 | ||
1034 | /* | 1074 | if (sscape->type != SSCAPE_VIVO) { |
1035 | * The input clock frequency on the SoundScape must | 1075 | int val; |
1036 | * be 14.31818 MHz, because we must set this register | 1076 | /* |
1037 | * to get the playback to sound correct ... | 1077 | * The input clock frequency on the SoundScape must |
1038 | */ | 1078 | * be 14.31818 MHz, because we must set this register |
1039 | snd_cs4231_mce_up(chip); | 1079 | * to get the playback to sound correct ... |
1040 | spin_lock_irqsave(&chip->reg_lock, flags); | 1080 | */ |
1041 | snd_cs4231_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20); | 1081 | snd_cs4231_mce_up(chip); |
1042 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1082 | spin_lock_irqsave(&chip->reg_lock, flags); |
1043 | snd_cs4231_mce_down(chip); | 1083 | snd_cs4231_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20); |
1084 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1085 | snd_cs4231_mce_down(chip); | ||
1044 | 1086 | ||
1045 | /* | 1087 | /* |
1046 | * More custom configuration: | 1088 | * More custom configuration: |
1047 | * a) select "mode 2", and provide a current drive of 8 mA | 1089 | * a) select "mode 2" and provide a current drive of 8mA |
1048 | * b) enable frequency selection (for capture/playback) | 1090 | * b) enable frequency selection (for capture/playback) |
1049 | */ | 1091 | */ |
1050 | spin_lock_irqsave(&chip->reg_lock, flags); | 1092 | spin_lock_irqsave(&chip->reg_lock, flags); |
1051 | snd_cs4231_out(chip, CS4231_MISC_INFO, (CS4231_MODE2 | 0x10)); | 1093 | snd_cs4231_out(chip, CS4231_MISC_INFO, |
1052 | snd_cs4231_out(chip, AD1845_PWR_DOWN_CTRL, snd_cs4231_in(chip, AD1845_PWR_DOWN_CTRL) | AD1845_FREQ_SEL_ENABLE); | 1094 | CS4231_MODE2 | 0x10); |
1053 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1095 | val = snd_cs4231_in(chip, AD1845_PWR_DOWN_CTRL); |
1096 | snd_cs4231_out(chip, AD1845_PWR_DOWN_CTRL, | ||
1097 | val | AD1845_FREQ_SEL_ENABLE); | ||
1098 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1099 | } | ||
1054 | 1100 | ||
1055 | if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) { | 1101 | err = snd_cs4231_pcm(chip, 0, &pcm); |
1056 | snd_printk(KERN_ERR "sscape: No PCM device for AD1845 chip\n"); | 1102 | if (err < 0) { |
1103 | snd_printk(KERN_ERR "sscape: No PCM device " | ||
1104 | "for AD1845 chip\n"); | ||
1057 | goto _error; | 1105 | goto _error; |
1058 | } | 1106 | } |
1059 | 1107 | ||
1060 | if ((err = snd_cs4231_mixer(chip)) < 0) { | 1108 | err = snd_cs4231_mixer(chip); |
1061 | snd_printk(KERN_ERR "sscape: No mixer device for AD1845 chip\n"); | 1109 | if (err < 0) { |
1110 | snd_printk(KERN_ERR "sscape: No mixer device " | ||
1111 | "for AD1845 chip\n"); | ||
1062 | goto _error; | 1112 | goto _error; |
1063 | } | 1113 | } |
1064 | 1114 | err = snd_cs4231_timer(chip, 0, NULL); | |
1065 | if ((err = snd_ctl_add(card, snd_ctl_new1(&midi_mixer_ctl, chip))) < 0) { | 1115 | if (err < 0) { |
1066 | snd_printk(KERN_ERR "sscape: Could not create MIDI mixer control\n"); | 1116 | snd_printk(KERN_ERR "sscape: No timer device " |
1117 | "for AD1845 chip\n"); | ||
1067 | goto _error; | 1118 | goto _error; |
1068 | } | 1119 | } |
1069 | 1120 | ||
1121 | if (sscape->type != SSCAPE_VIVO) { | ||
1122 | err = snd_ctl_add(card, | ||
1123 | snd_ctl_new1(&midi_mixer_ctl, chip)); | ||
1124 | if (err < 0) { | ||
1125 | snd_printk(KERN_ERR "sscape: Could not create " | ||
1126 | "MIDI mixer control\n"); | ||
1127 | goto _error; | ||
1128 | } | ||
1129 | chip->set_playback_format = ad1845_playback_format; | ||
1130 | chip->set_capture_format = ad1845_capture_format; | ||
1131 | } | ||
1132 | |||
1070 | strcpy(card->driver, "SoundScape"); | 1133 | strcpy(card->driver, "SoundScape"); |
1071 | strcpy(card->shortname, pcm->name); | 1134 | strcpy(card->shortname, pcm->name); |
1072 | snprintf(card->longname, sizeof(card->longname), | 1135 | snprintf(card->longname, sizeof(card->longname), |
1073 | "%s at 0x%lx, IRQ %d, DMA %d\n", | 1136 | "%s at 0x%lx, IRQ %d, DMA1 %d, DMA2 %d\n", |
1074 | pcm->name, chip->port, chip->irq, chip->dma1); | 1137 | pcm->name, chip->port, chip->irq, |
1075 | chip->set_playback_format = ad1845_playback_format; | 1138 | chip->dma1, chip->dma2); |
1076 | chip->set_capture_format = ad1845_capture_format; | 1139 | |
1077 | sscape->chip = chip; | 1140 | sscape->chip = chip; |
1078 | } | 1141 | } |
1079 | 1142 | ||
@@ -1086,15 +1149,15 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, int irq | |||
1086 | * Create an ALSA soundcard entry for the SoundScape, using | 1149 | * Create an ALSA soundcard entry for the SoundScape, using |
1087 | * the given list of port, IRQ and DMA resources. | 1150 | * the given list of port, IRQ and DMA resources. |
1088 | */ | 1151 | */ |
1089 | static int __devinit create_sscape(int dev, struct snd_card **rcardp) | 1152 | static int __devinit create_sscape(int dev, struct snd_card *card) |
1090 | { | 1153 | { |
1091 | struct snd_card *card; | 1154 | struct soundscape *sscape = get_card_soundscape(card); |
1092 | register struct soundscape *sscape; | 1155 | unsigned dma_cfg; |
1093 | register unsigned dma_cfg; | ||
1094 | unsigned irq_cfg; | 1156 | unsigned irq_cfg; |
1095 | unsigned mpu_irq_cfg; | 1157 | unsigned mpu_irq_cfg; |
1096 | unsigned xport; | 1158 | unsigned xport; |
1097 | struct resource *io_res; | 1159 | struct resource *io_res; |
1160 | struct resource *wss_res; | ||
1098 | unsigned long flags; | 1161 | unsigned long flags; |
1099 | int err; | 1162 | int err; |
1100 | 1163 | ||
@@ -1118,61 +1181,69 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp) | |||
1118 | * Grab IO ports that we will need to probe so that we | 1181 | * Grab IO ports that we will need to probe so that we |
1119 | * can detect and control this hardware ... | 1182 | * can detect and control this hardware ... |
1120 | */ | 1183 | */ |
1121 | if ((io_res = request_region(xport, 8, "SoundScape")) == NULL) { | 1184 | io_res = request_region(xport, 8, "SoundScape"); |
1185 | if (!io_res) { | ||
1122 | snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport); | 1186 | snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport); |
1123 | return -EBUSY; | 1187 | return -EBUSY; |
1124 | } | 1188 | } |
1189 | wss_res = NULL; | ||
1190 | if (sscape->type == SSCAPE_VIVO) { | ||
1191 | wss_res = request_region(wss_port[dev], 4, "SoundScape"); | ||
1192 | if (!wss_res) { | ||
1193 | snd_printk(KERN_ERR "sscape: can't grab port 0x%lx\n", | ||
1194 | wss_port[dev]); | ||
1195 | err = -EBUSY; | ||
1196 | goto _release_region; | ||
1197 | } | ||
1198 | } | ||
1125 | 1199 | ||
1126 | /* | 1200 | /* |
1127 | * Grab both DMA channels (OK, only one for now) ... | 1201 | * Grab one DMA channel ... |
1128 | */ | 1202 | */ |
1129 | if ((err = request_dma(dma[dev], "SoundScape")) < 0) { | 1203 | err = request_dma(dma[dev], "SoundScape"); |
1204 | if (err < 0) { | ||
1130 | snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]); | 1205 | snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]); |
1131 | goto _release_region; | 1206 | goto _release_region; |
1132 | } | 1207 | } |
1133 | 1208 | ||
1134 | /* | ||
1135 | * Create a new ALSA sound card entry, in anticipation | ||
1136 | * of detecting our hardware ... | ||
1137 | */ | ||
1138 | if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, | ||
1139 | sizeof(struct soundscape))) == NULL) { | ||
1140 | err = -ENOMEM; | ||
1141 | goto _release_dma; | ||
1142 | } | ||
1143 | |||
1144 | sscape = get_card_soundscape(card); | ||
1145 | spin_lock_init(&sscape->lock); | 1209 | spin_lock_init(&sscape->lock); |
1146 | spin_lock_init(&sscape->fwlock); | 1210 | spin_lock_init(&sscape->fwlock); |
1147 | sscape->io_res = io_res; | 1211 | sscape->io_res = io_res; |
1212 | sscape->wss_res = wss_res; | ||
1148 | sscape->io_base = xport; | 1213 | sscape->io_base = xport; |
1214 | sscape->wss_base = wss_port[dev]; | ||
1149 | 1215 | ||
1150 | if (!detect_sscape(sscape)) { | 1216 | if (!detect_sscape(sscape)) { |
1151 | printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base); | 1217 | printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base); |
1152 | err = -ENODEV; | 1218 | err = -ENODEV; |
1153 | goto _release_card; | 1219 | goto _release_dma; |
1154 | } | 1220 | } |
1155 | 1221 | ||
1156 | printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n", | 1222 | printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n", |
1157 | sscape->io_base, irq[dev], dma[dev]); | 1223 | sscape->io_base, irq[dev], dma[dev]); |
1158 | 1224 | ||
1159 | /* | 1225 | if (sscape->type != SSCAPE_VIVO) { |
1160 | * Now create the hardware-specific device so that we can | 1226 | /* |
1161 | * load the microcode into the on-board processor. | 1227 | * Now create the hardware-specific device so that we can |
1162 | * We cannot use the MPU-401 MIDI system until this firmware | 1228 | * load the microcode into the on-board processor. |
1163 | * has been loaded into the card. | 1229 | * We cannot use the MPU-401 MIDI system until this firmware |
1164 | */ | 1230 | * has been loaded into the card. |
1165 | if ((err = snd_hwdep_new(card, "MC68EC000", 0, &(sscape->hw))) < 0) { | 1231 | */ |
1166 | printk(KERN_ERR "sscape: Failed to create firmware device\n"); | 1232 | err = snd_hwdep_new(card, "MC68EC000", 0, &(sscape->hw)); |
1167 | goto _release_card; | 1233 | if (err < 0) { |
1234 | printk(KERN_ERR "sscape: Failed to create " | ||
1235 | "firmware device\n"); | ||
1236 | goto _release_dma; | ||
1237 | } | ||
1238 | strlcpy(sscape->hw->name, "SoundScape M68K", | ||
1239 | sizeof(sscape->hw->name)); | ||
1240 | sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0'; | ||
1241 | sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE; | ||
1242 | sscape->hw->ops.open = sscape_hw_open; | ||
1243 | sscape->hw->ops.release = sscape_hw_release; | ||
1244 | sscape->hw->ops.ioctl = sscape_hw_ioctl; | ||
1245 | sscape->hw->private_data = sscape; | ||
1168 | } | 1246 | } |
1169 | strlcpy(sscape->hw->name, "SoundScape M68K", sizeof(sscape->hw->name)); | ||
1170 | sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0'; | ||
1171 | sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE; | ||
1172 | sscape->hw->ops.open = sscape_hw_open; | ||
1173 | sscape->hw->ops.release = sscape_hw_release; | ||
1174 | sscape->hw->ops.ioctl = sscape_hw_ioctl; | ||
1175 | sscape->hw->private_data = sscape; | ||
1176 | 1247 | ||
1177 | /* | 1248 | /* |
1178 | * Tell the on-board devices where their resources are (I think - | 1249 | * Tell the on-board devices where their resources are (I think - |
@@ -1197,7 +1268,8 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp) | |||
1197 | sscape_write_unsafe(sscape->io_base, | 1268 | sscape_write_unsafe(sscape->io_base, |
1198 | GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg); | 1269 | GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg); |
1199 | sscape_write_unsafe(sscape->io_base, | 1270 | sscape_write_unsafe(sscape->io_base, |
1200 | GA_CDCFG_REG, 0x09 | DMA_8BIT | (dma[dev] << 4) | (irq_cfg << 1)); | 1271 | GA_CDCFG_REG, 0x09 | DMA_8BIT |
1272 | | (dma[dev] << 4) | (irq_cfg << 1)); | ||
1201 | 1273 | ||
1202 | spin_unlock_irqrestore(&sscape->lock, flags); | 1274 | spin_unlock_irqrestore(&sscape->lock, flags); |
1203 | 1275 | ||
@@ -1205,30 +1277,37 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp) | |||
1205 | * We have now enabled the codec chip, and so we should | 1277 | * We have now enabled the codec chip, and so we should |
1206 | * detect the AD1845 device ... | 1278 | * detect the AD1845 device ... |
1207 | */ | 1279 | */ |
1208 | if ((err = create_ad1845(card, CODEC_IO(xport), irq[dev], dma[dev])) < 0) { | 1280 | err = create_ad1845(card, wss_port[dev], irq[dev], |
1209 | printk(KERN_ERR "sscape: No AD1845 device at 0x%x, IRQ %d\n", | 1281 | dma[dev], dma2[dev]); |
1210 | CODEC_IO(xport), irq[dev]); | 1282 | if (err < 0) { |
1211 | goto _release_card; | 1283 | printk(KERN_ERR "sscape: No AD1845 device at 0x%lx, IRQ %d\n", |
1284 | wss_port[dev], irq[dev]); | ||
1285 | goto _release_dma; | ||
1212 | } | 1286 | } |
1213 | #define MIDI_DEVNUM 0 | 1287 | #define MIDI_DEVNUM 0 |
1214 | if ((err = create_mpu401(card, MIDI_DEVNUM, MPU401_IO(xport), mpu_irq[dev])) < 0) { | 1288 | if (sscape->type != SSCAPE_VIVO) { |
1215 | printk(KERN_ERR "sscape: Failed to create MPU-401 device at 0x%x\n", | 1289 | err = create_mpu401(card, MIDI_DEVNUM, |
1216 | MPU401_IO(xport)); | 1290 | MPU401_IO(xport), mpu_irq[dev]); |
1217 | goto _release_card; | 1291 | if (err < 0) { |
1218 | } | 1292 | printk(KERN_ERR "sscape: Failed to create " |
1293 | "MPU-401 device at 0x%x\n", | ||
1294 | MPU401_IO(xport)); | ||
1295 | goto _release_dma; | ||
1296 | } | ||
1219 | 1297 | ||
1220 | /* | 1298 | /* |
1221 | * Enable the master IRQ ... | 1299 | * Enable the master IRQ ... |
1222 | */ | 1300 | */ |
1223 | sscape_write(sscape, GA_INTENA_REG, 0x80); | 1301 | sscape_write(sscape, GA_INTENA_REG, 0x80); |
1224 | 1302 | ||
1225 | /* | 1303 | /* |
1226 | * Initialize mixer | 1304 | * Initialize mixer |
1227 | */ | 1305 | */ |
1228 | sscape->midi_vol = 0; | 1306 | sscape->midi_vol = 0; |
1229 | host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100); | 1307 | host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100); |
1230 | host_write_ctrl_unsafe(sscape->io_base, 0, 100); | 1308 | host_write_ctrl_unsafe(sscape->io_base, 0, 100); |
1231 | host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100); | 1309 | host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100); |
1310 | } | ||
1232 | 1311 | ||
1233 | /* | 1312 | /* |
1234 | * Now that we have successfully created this sound card, | 1313 | * Now that we have successfully created this sound card, |
@@ -1237,17 +1316,14 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp) | |||
1237 | * function now that our "constructor" has completed. | 1316 | * function now that our "constructor" has completed. |
1238 | */ | 1317 | */ |
1239 | card->private_free = soundscape_free; | 1318 | card->private_free = soundscape_free; |
1240 | *rcardp = card; | ||
1241 | 1319 | ||
1242 | return 0; | 1320 | return 0; |
1243 | 1321 | ||
1244 | _release_card: | 1322 | _release_dma: |
1245 | snd_card_free(card); | ||
1246 | |||
1247 | _release_dma: | ||
1248 | free_dma(dma[dev]); | 1323 | free_dma(dma[dev]); |
1249 | 1324 | ||
1250 | _release_region: | 1325 | _release_region: |
1326 | release_and_free_resource(wss_res); | ||
1251 | release_and_free_resource(io_res); | 1327 | release_and_free_resource(io_res); |
1252 | 1328 | ||
1253 | return err; | 1329 | return err; |
@@ -1276,19 +1352,33 @@ static int __devinit snd_sscape_match(struct device *pdev, unsigned int i) | |||
1276 | static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev) | 1352 | static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev) |
1277 | { | 1353 | { |
1278 | struct snd_card *card; | 1354 | struct snd_card *card; |
1355 | struct soundscape *sscape; | ||
1279 | int ret; | 1356 | int ret; |
1280 | 1357 | ||
1358 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | ||
1359 | sizeof(struct soundscape)); | ||
1360 | if (!card) | ||
1361 | return -ENOMEM; | ||
1362 | |||
1363 | sscape = get_card_soundscape(card); | ||
1364 | sscape->type = SSCAPE; | ||
1365 | |||
1281 | dma[dev] &= 0x03; | 1366 | dma[dev] &= 0x03; |
1282 | ret = create_sscape(dev, &card); | 1367 | ret = create_sscape(dev, card); |
1283 | if (ret < 0) | 1368 | if (ret < 0) |
1284 | return ret; | 1369 | goto _release_card; |
1370 | |||
1285 | snd_card_set_dev(card, pdev); | 1371 | snd_card_set_dev(card, pdev); |
1286 | if ((ret = snd_card_register(card)) < 0) { | 1372 | if ((ret = snd_card_register(card)) < 0) { |
1287 | printk(KERN_ERR "sscape: Failed to register sound card\n"); | 1373 | printk(KERN_ERR "sscape: Failed to register sound card\n"); |
1288 | return ret; | 1374 | goto _release_card; |
1289 | } | 1375 | } |
1290 | dev_set_drvdata(pdev, card); | 1376 | dev_set_drvdata(pdev, card); |
1291 | return 0; | 1377 | return 0; |
1378 | |||
1379 | _release_card: | ||
1380 | snd_card_free(card); | ||
1381 | return ret; | ||
1292 | } | 1382 | } |
1293 | 1383 | ||
1294 | static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev) | 1384 | static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev) |
@@ -1325,6 +1415,7 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard, | |||
1325 | static int idx = 0; | 1415 | static int idx = 0; |
1326 | struct pnp_dev *dev; | 1416 | struct pnp_dev *dev; |
1327 | struct snd_card *card; | 1417 | struct snd_card *card; |
1418 | struct soundscape *sscape; | ||
1328 | int ret; | 1419 | int ret; |
1329 | 1420 | ||
1330 | /* | 1421 | /* |
@@ -1366,26 +1457,55 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard, | |||
1366 | } | 1457 | } |
1367 | 1458 | ||
1368 | /* | 1459 | /* |
1460 | * Create a new ALSA sound card entry, in anticipation | ||
1461 | * of detecting our hardware ... | ||
1462 | */ | ||
1463 | card = snd_card_new(index[idx], id[idx], THIS_MODULE, | ||
1464 | sizeof(struct soundscape)); | ||
1465 | if (!card) | ||
1466 | return -ENOMEM; | ||
1467 | |||
1468 | sscape = get_card_soundscape(card); | ||
1469 | |||
1470 | /* | ||
1471 | * Identify card model ... | ||
1472 | */ | ||
1473 | if (!strncmp("ENS4081", pid->id, 7)) | ||
1474 | sscape->type = SSCAPE_VIVO; | ||
1475 | else | ||
1476 | sscape->type = SSCAPE_PNP; | ||
1477 | |||
1478 | /* | ||
1369 | * Read the correct parameters off the ISA PnP bus ... | 1479 | * Read the correct parameters off the ISA PnP bus ... |
1370 | */ | 1480 | */ |
1371 | port[idx] = pnp_port_start(dev, 0); | 1481 | port[idx] = pnp_port_start(dev, 0); |
1372 | irq[idx] = pnp_irq(dev, 0); | 1482 | irq[idx] = pnp_irq(dev, 0); |
1373 | mpu_irq[idx] = pnp_irq(dev, 1); | 1483 | mpu_irq[idx] = pnp_irq(dev, 1); |
1374 | dma[idx] = pnp_dma(dev, 0) & 0x03; | 1484 | dma[idx] = pnp_dma(dev, 0) & 0x03; |
1485 | if (sscape->type == SSCAPE_PNP) { | ||
1486 | dma2[idx] = dma[idx]; | ||
1487 | wss_port[idx] = CODEC_IO(port[idx]); | ||
1488 | } else { | ||
1489 | wss_port[idx] = pnp_port_start(dev, 1); | ||
1490 | dma2[idx] = pnp_dma(dev, 1); | ||
1491 | } | ||
1375 | 1492 | ||
1376 | ret = create_sscape(idx, &card); | 1493 | ret = create_sscape(idx, card); |
1377 | if (ret < 0) | 1494 | if (ret < 0) |
1378 | return ret; | 1495 | goto _release_card; |
1496 | |||
1379 | snd_card_set_dev(card, &pcard->card->dev); | 1497 | snd_card_set_dev(card, &pcard->card->dev); |
1380 | if ((ret = snd_card_register(card)) < 0) { | 1498 | if ((ret = snd_card_register(card)) < 0) { |
1381 | printk(KERN_ERR "sscape: Failed to register sound card\n"); | 1499 | printk(KERN_ERR "sscape: Failed to register sound card\n"); |
1382 | snd_card_free(card); | 1500 | goto _release_card; |
1383 | return ret; | ||
1384 | } | 1501 | } |
1385 | 1502 | ||
1386 | pnp_set_card_drvdata(pcard, card); | 1503 | pnp_set_card_drvdata(pcard, card); |
1387 | ++idx; | 1504 | ++idx; |
1505 | return 0; | ||
1388 | 1506 | ||
1507 | _release_card: | ||
1508 | snd_card_free(card); | ||
1389 | return ret; | 1509 | return ret; |
1390 | } | 1510 | } |
1391 | 1511 | ||
diff --git a/sound/isa/wavefront/Makefile b/sound/isa/wavefront/Makefile index b4cb28422db0..601bdddd44d0 100644 --- a/sound/isa/wavefront/Makefile +++ b/sound/isa/wavefront/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-wavefront-objs := wavefront.o wavefront_fx.o wavefront_synth.o wavefront_midi.o | 6 | snd-wavefront-objs := wavefront.o wavefront_fx.o wavefront_synth.o wavefront_midi.o |
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index bacc51c86587..a1ebb7c5c684 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/time.h> | 28 | #include <linux/time.h> |
29 | #include <linux/wait.h> | 29 | #include <linux/wait.h> |
30 | #include <linux/firmware.h> | ||
30 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
31 | #include <sound/core.h> | 32 | #include <sound/core.h> |
32 | #include <sound/snd_wavefront.h> | 33 | #include <sound/snd_wavefront.h> |
@@ -53,9 +54,8 @@ static int debug_default = 0; /* you can set this to control debugging | |||
53 | 54 | ||
54 | /* XXX this needs to be made firmware and hardware version dependent */ | 55 | /* XXX this needs to be made firmware and hardware version dependent */ |
55 | 56 | ||
56 | static char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed | 57 | #define DEFAULT_OSPATH "wavefront.os" |
57 | version of the WaveFront OS | 58 | static char *ospath = DEFAULT_OSPATH; /* the firmware file name */ |
58 | */ | ||
59 | 59 | ||
60 | static int wait_usecs = 150; /* This magic number seems to give pretty optimal | 60 | static int wait_usecs = 150; /* This magic number seems to give pretty optimal |
61 | throughput based on my limited experimentation. | 61 | throughput based on my limited experimentation. |
@@ -97,7 +97,7 @@ MODULE_PARM_DESC(sleep_interval, "how long to sleep when waiting for reply"); | |||
97 | module_param(sleep_tries, int, 0444); | 97 | module_param(sleep_tries, int, 0444); |
98 | MODULE_PARM_DESC(sleep_tries, "how many times to try sleeping during a wait"); | 98 | MODULE_PARM_DESC(sleep_tries, "how many times to try sleeping during a wait"); |
99 | module_param(ospath, charp, 0444); | 99 | module_param(ospath, charp, 0444); |
100 | MODULE_PARM_DESC(ospath, "full pathname to processed ICS2115 OS firmware"); | 100 | MODULE_PARM_DESC(ospath, "pathname to processed ICS2115 OS firmware"); |
101 | module_param(reset_time, int, 0444); | 101 | module_param(reset_time, int, 0444); |
102 | MODULE_PARM_DESC(reset_time, "how long to wait for a reset to take effect"); | 102 | MODULE_PARM_DESC(reset_time, "how long to wait for a reset to take effect"); |
103 | module_param(ramcheck_time, int, 0444); | 103 | module_param(ramcheck_time, int, 0444); |
@@ -1768,7 +1768,7 @@ snd_wavefront_interrupt_bits (int irq) | |||
1768 | 1768 | ||
1769 | static void __devinit | 1769 | static void __devinit |
1770 | wavefront_should_cause_interrupt (snd_wavefront_t *dev, | 1770 | wavefront_should_cause_interrupt (snd_wavefront_t *dev, |
1771 | int val, int port, int timeout) | 1771 | int val, int port, unsigned long timeout) |
1772 | 1772 | ||
1773 | { | 1773 | { |
1774 | wait_queue_t wait; | 1774 | wait_queue_t wait; |
@@ -1779,11 +1779,9 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev, | |||
1779 | dev->irq_ok = 0; | 1779 | dev->irq_ok = 0; |
1780 | outb (val,port); | 1780 | outb (val,port); |
1781 | spin_unlock_irq(&dev->irq_lock); | 1781 | spin_unlock_irq(&dev->irq_lock); |
1782 | while (1) { | 1782 | while (!dev->irq_ok && time_before(jiffies, timeout)) { |
1783 | if ((timeout = schedule_timeout(timeout)) == 0) | 1783 | schedule_timeout_uninterruptible(1); |
1784 | return; | 1784 | barrier(); |
1785 | if (dev->irq_ok) | ||
1786 | return; | ||
1787 | } | 1785 | } |
1788 | } | 1786 | } |
1789 | 1787 | ||
@@ -1938,111 +1936,75 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev) | |||
1938 | return (1); | 1936 | return (1); |
1939 | } | 1937 | } |
1940 | 1938 | ||
1941 | #include <linux/fs.h> | ||
1942 | #include <linux/mm.h> | ||
1943 | #include <linux/slab.h> | ||
1944 | #include <linux/unistd.h> | ||
1945 | #include <linux/syscalls.h> | ||
1946 | #include <asm/uaccess.h> | ||
1947 | |||
1948 | |||
1949 | static int __devinit | 1939 | static int __devinit |
1950 | wavefront_download_firmware (snd_wavefront_t *dev, char *path) | 1940 | wavefront_download_firmware (snd_wavefront_t *dev, char *path) |
1951 | 1941 | ||
1952 | { | 1942 | { |
1953 | unsigned char section[WF_SECTION_MAX]; | 1943 | unsigned char *buf; |
1954 | signed char section_length; /* yes, just a char; max value is WF_SECTION_MAX */ | 1944 | int len, err; |
1955 | int section_cnt_downloaded = 0; | 1945 | int section_cnt_downloaded = 0; |
1956 | int fd; | 1946 | const struct firmware *firmware; |
1957 | int c; | ||
1958 | int i; | ||
1959 | mm_segment_t fs; | ||
1960 | |||
1961 | /* This tries to be a bit cleverer than the stuff Alan Cox did for | ||
1962 | the generic sound firmware, in that it actually knows | ||
1963 | something about the structure of the Motorola firmware. In | ||
1964 | particular, it uses a version that has been stripped of the | ||
1965 | 20K of useless header information, and had section lengths | ||
1966 | added, making it possible to load the entire OS without any | ||
1967 | [kv]malloc() activity, since the longest entity we ever read is | ||
1968 | 42 bytes (well, WF_SECTION_MAX) long. | ||
1969 | */ | ||
1970 | |||
1971 | fs = get_fs(); | ||
1972 | set_fs (get_ds()); | ||
1973 | 1947 | ||
1974 | if ((fd = sys_open ((char __user *) path, 0, 0)) < 0) { | 1948 | err = request_firmware(&firmware, path, dev->card->dev); |
1975 | snd_printk ("Unable to load \"%s\".\n", | 1949 | if (err < 0) { |
1976 | path); | 1950 | snd_printk(KERN_ERR "firmware (%s) download failed!!!\n", path); |
1977 | return 1; | 1951 | return 1; |
1978 | } | 1952 | } |
1979 | 1953 | ||
1980 | while (1) { | 1954 | len = 0; |
1981 | int x; | 1955 | buf = firmware->data; |
1982 | 1956 | for (;;) { | |
1983 | if ((x = sys_read (fd, (char __user *) §ion_length, sizeof (section_length))) != | 1957 | int section_length = *(signed char *)buf; |
1984 | sizeof (section_length)) { | 1958 | if (section_length == 0) |
1985 | snd_printk ("firmware read error.\n"); | ||
1986 | goto failure; | ||
1987 | } | ||
1988 | |||
1989 | if (section_length == 0) { | ||
1990 | break; | 1959 | break; |
1991 | } | ||
1992 | |||
1993 | if (section_length < 0 || section_length > WF_SECTION_MAX) { | 1960 | if (section_length < 0 || section_length > WF_SECTION_MAX) { |
1994 | snd_printk ("invalid firmware section length %d\n", | 1961 | snd_printk(KERN_ERR |
1995 | section_length); | 1962 | "invalid firmware section length %d\n", |
1963 | section_length); | ||
1996 | goto failure; | 1964 | goto failure; |
1997 | } | 1965 | } |
1966 | buf++; | ||
1967 | len++; | ||
1998 | 1968 | ||
1999 | if (sys_read (fd, (char __user *) section, section_length) != section_length) { | 1969 | if (firmware->size < len + section_length) { |
2000 | snd_printk ("firmware section " | 1970 | snd_printk(KERN_ERR "firmware section read error.\n"); |
2001 | "read error.\n"); | ||
2002 | goto failure; | 1971 | goto failure; |
2003 | } | 1972 | } |
2004 | 1973 | ||
2005 | /* Send command */ | 1974 | /* Send command */ |
2006 | 1975 | if (wavefront_write(dev, WFC_DOWNLOAD_OS)) | |
2007 | if (wavefront_write (dev, WFC_DOWNLOAD_OS)) { | ||
2008 | goto failure; | 1976 | goto failure; |
2009 | } | ||
2010 | 1977 | ||
2011 | for (i = 0; i < section_length; i++) { | 1978 | for (; section_length; section_length--) { |
2012 | if (wavefront_write (dev, section[i])) { | 1979 | if (wavefront_write(dev, *buf)) |
2013 | goto failure; | 1980 | goto failure; |
2014 | } | 1981 | buf++; |
1982 | len++; | ||
2015 | } | 1983 | } |
2016 | 1984 | ||
2017 | /* get ACK */ | 1985 | /* get ACK */ |
2018 | 1986 | if (!wavefront_wait(dev, STAT_CAN_READ)) { | |
2019 | if (wavefront_wait (dev, STAT_CAN_READ)) { | 1987 | snd_printk(KERN_ERR "time out for firmware ACK.\n"); |
2020 | 1988 | goto failure; | |
2021 | if ((c = inb (dev->data_port)) != WF_ACK) { | 1989 | } |
2022 | 1990 | err = inb(dev->data_port); | |
2023 | snd_printk ("download " | 1991 | if (err != WF_ACK) { |
2024 | "of section #%d not " | 1992 | snd_printk(KERN_ERR |
2025 | "acknowledged, ack = 0x%x\n", | 1993 | "download of section #%d not " |
2026 | section_cnt_downloaded + 1, c); | 1994 | "acknowledged, ack = 0x%x\n", |
2027 | goto failure; | 1995 | section_cnt_downloaded + 1, err); |
2028 | |||
2029 | } | ||
2030 | |||
2031 | } else { | ||
2032 | snd_printk ("time out for firmware ACK.\n"); | ||
2033 | goto failure; | 1996 | goto failure; |
2034 | } | 1997 | } |
2035 | 1998 | ||
1999 | section_cnt_downloaded++; | ||
2036 | } | 2000 | } |
2037 | 2001 | ||
2038 | sys_close (fd); | 2002 | release_firmware(firmware); |
2039 | set_fs (fs); | ||
2040 | return 0; | 2003 | return 0; |
2041 | 2004 | ||
2042 | failure: | 2005 | failure: |
2043 | sys_close (fd); | 2006 | release_firmware(firmware); |
2044 | set_fs (fs); | 2007 | snd_printk(KERN_ERR "firmware download failed!!!\n"); |
2045 | snd_printk ("firmware download failed!!!\n"); | ||
2046 | return 1; | 2008 | return 1; |
2047 | } | 2009 | } |
2048 | 2010 | ||
@@ -2232,3 +2194,5 @@ snd_wavefront_detect (snd_wavefront_card_t *card) | |||
2232 | 2194 | ||
2233 | return 0; | 2195 | return 0; |
2234 | } | 2196 | } |
2197 | |||
2198 | MODULE_FIRMWARE(DEFAULT_OSPATH); | ||