diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/isa/Kconfig | 15 | ||||
-rw-r--r-- | sound/isa/ad1848/Makefile | 2 | ||||
-rw-r--r-- | sound/isa/ad1848/ad1848.c | 7 | ||||
-rw-r--r-- | sound/isa/ad1848/ad1848_lib.c | 487 | ||||
-rw-r--r-- | sound/isa/cmi8330.c | 22 | ||||
-rw-r--r-- | sound/isa/opti9xx/opti92x-ad1848.c | 15 | ||||
-rw-r--r-- | sound/isa/sc6000.c | 6 | ||||
-rw-r--r-- | sound/isa/sgalaxy.c | 13 | ||||
-rw-r--r-- | sound/isa/wss/wss_lib.c | 150 |
9 files changed, 150 insertions, 567 deletions
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index cca11d5dc33b..ec80444c2a96 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig | |||
@@ -4,11 +4,6 @@ config SND_WSS_LIB | |||
4 | tristate | 4 | tristate |
5 | select SND_PCM | 5 | select SND_PCM |
6 | 6 | ||
7 | config SND_AD1848_LIB | ||
8 | tristate | ||
9 | select SND_PCM | ||
10 | select SND_WSS_LIB | ||
11 | |||
12 | config SND_SB_COMMON | 7 | config SND_SB_COMMON |
13 | tristate | 8 | tristate |
14 | 9 | ||
@@ -56,7 +51,7 @@ config SND_AD1816A | |||
56 | 51 | ||
57 | config SND_AD1848 | 52 | config SND_AD1848 |
58 | tristate "Generic AD1848/CS4248 driver" | 53 | tristate "Generic AD1848/CS4248 driver" |
59 | select SND_AD1848_LIB | 54 | select SND_WSS_LIB |
60 | help | 55 | help |
61 | Say Y here to include support for AD1848 (Analog Devices) or | 56 | Say Y here to include support for AD1848 (Analog Devices) or |
62 | CS4248 (Cirrus Logic - Crystal Semiconductors) chips. | 57 | CS4248 (Cirrus Logic - Crystal Semiconductors) chips. |
@@ -97,7 +92,7 @@ config SND_AZT2320 | |||
97 | 92 | ||
98 | config SND_CMI8330 | 93 | config SND_CMI8330 |
99 | tristate "C-Media CMI8330" | 94 | tristate "C-Media CMI8330" |
100 | select SND_AD1848_LIB | 95 | select SND_WSS_LIB |
101 | select SND_SB16_DSP | 96 | select SND_SB16_DSP |
102 | help | 97 | help |
103 | Say Y here to include support for soundcards based on the | 98 | Say Y here to include support for soundcards based on the |
@@ -193,7 +188,7 @@ config SND_ES18XX | |||
193 | config SND_SC6000 | 188 | config SND_SC6000 |
194 | tristate "Gallant SC-6000, Audio Excel DSP 16" | 189 | tristate "Gallant SC-6000, Audio Excel DSP 16" |
195 | depends on HAS_IOPORT | 190 | depends on HAS_IOPORT |
196 | select SND_AD1848_LIB | 191 | select SND_WSS_LIB |
197 | select SND_OPL3_LIB | 192 | select SND_OPL3_LIB |
198 | select SND_MPU401_UART | 193 | select SND_MPU401_UART |
199 | help | 194 | help |
@@ -280,7 +275,7 @@ config SND_OPTI92X_AD1848 | |||
280 | select SND_OPL3_LIB | 275 | select SND_OPL3_LIB |
281 | select SND_OPL4_LIB | 276 | select SND_OPL4_LIB |
282 | select SND_MPU401_UART | 277 | select SND_MPU401_UART |
283 | select SND_AD1848_LIB | 278 | select SND_WSS_LIB |
284 | help | 279 | help |
285 | Say Y here to include support for soundcards based on Opti | 280 | Say Y here to include support for soundcards based on Opti |
286 | 82C92x or OTI-601 chips and using an AD1848 codec. | 281 | 82C92x or OTI-601 chips and using an AD1848 codec. |
@@ -373,7 +368,7 @@ config SND_SB16_CSP | |||
373 | 368 | ||
374 | config SND_SGALAXY | 369 | config SND_SGALAXY |
375 | tristate "Aztech Sound Galaxy" | 370 | tristate "Aztech Sound Galaxy" |
376 | select SND_AD1848_LIB | 371 | select SND_WSS_LIB |
377 | help | 372 | help |
378 | Say Y here to include support for Aztech Sound Galaxy | 373 | Say Y here to include support for Aztech Sound Galaxy |
379 | soundcards. | 374 | soundcards. |
diff --git a/sound/isa/ad1848/Makefile b/sound/isa/ad1848/Makefile index ae23331e9200..3d6dea3ff927 100644 --- a/sound/isa/ad1848/Makefile +++ b/sound/isa/ad1848/Makefile | |||
@@ -3,10 +3,8 @@ | |||
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ad1848-lib-objs := ad1848_lib.o | ||
7 | snd-ad1848-objs := ad1848.o | 6 | snd-ad1848-objs := ad1848.o |
8 | 7 | ||
9 | # Toplevel Module Dependency | 8 | # Toplevel Module Dependency |
10 | obj-$(CONFIG_SND_AD1848) += snd-ad1848.o | 9 | obj-$(CONFIG_SND_AD1848) += snd-ad1848.o |
11 | obj-$(CONFIG_SND_AD1848_LIB) += snd-ad1848-lib.o | ||
12 | 10 | ||
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c index 17970c2f27e7..b68d20edc20f 100644 --- a/sound/isa/ad1848/ad1848.c +++ b/sound/isa/ad1848/ad1848.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/wait.h> | 28 | #include <linux/wait.h> |
29 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
30 | #include <sound/core.h> | 30 | #include <sound/core.h> |
31 | #include <sound/ad1848.h> | 31 | #include <sound/wss.h> |
32 | #include <sound/initval.h> | 32 | #include <sound/initval.h> |
33 | 33 | ||
34 | #define CRD_NAME "Generic AD1848/AD1847/CS4248" | 34 | #define CRD_NAME "Generic AD1848/AD1847/CS4248" |
@@ -95,8 +95,9 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) | |||
95 | if (!card) | 95 | if (!card) |
96 | return -EINVAL; | 96 | return -EINVAL; |
97 | 97 | ||
98 | error = snd_ad1848_create(card, port[n], irq[n], dma1[n], | 98 | error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], -1, |
99 | thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT, &chip); | 99 | thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT, |
100 | 0, &chip); | ||
100 | if (error < 0) | 101 | if (error < 0) |
101 | goto out; | 102 | goto out; |
102 | 103 | ||
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index aa803d38a8ad..e69de29bb2d1 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c | |||
@@ -1,487 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> | ||
3 | * Routines for control of AD1848/AD1847/CS4248 | ||
4 | * | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #define SNDRV_MAIN_OBJECT_FILE | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/ioport.h> | ||
28 | #include <sound/core.h> | ||
29 | #include <sound/ad1848.h> | ||
30 | #include <sound/control.h> | ||
31 | #include <sound/tlv.h> | ||
32 | #include <sound/pcm_params.h> | ||
33 | |||
34 | #include <asm/io.h> | ||
35 | #include <asm/dma.h> | ||
36 | |||
37 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
38 | MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248"); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | |||
41 | #if 0 | ||
42 | #define SNDRV_DEBUG_MCE | ||
43 | #endif | ||
44 | |||
45 | /* | ||
46 | * Some variables | ||
47 | */ | ||
48 | |||
49 | static unsigned char snd_ad1848_original_image[16] = | ||
50 | { | ||
51 | 0x00, /* 00 - lic */ | ||
52 | 0x00, /* 01 - ric */ | ||
53 | 0x9f, /* 02 - la1ic */ | ||
54 | 0x9f, /* 03 - ra1ic */ | ||
55 | 0x9f, /* 04 - la2ic */ | ||
56 | 0x9f, /* 05 - ra2ic */ | ||
57 | 0xbf, /* 06 - loc */ | ||
58 | 0xbf, /* 07 - roc */ | ||
59 | 0x20, /* 08 - dfr */ | ||
60 | AD1848_AUTOCALIB, /* 09 - ic */ | ||
61 | 0x00, /* 0a - pc */ | ||
62 | 0x00, /* 0b - ti */ | ||
63 | 0x00, /* 0c - mi */ | ||
64 | 0x00, /* 0d - lbc */ | ||
65 | 0x00, /* 0e - dru */ | ||
66 | 0x00, /* 0f - drl */ | ||
67 | }; | ||
68 | |||
69 | /* | ||
70 | * Basic I/O functions | ||
71 | */ | ||
72 | |||
73 | static void snd_ad1848_wait(struct snd_wss *chip) | ||
74 | { | ||
75 | int timeout; | ||
76 | |||
77 | for (timeout = 250; timeout > 0; timeout--) { | ||
78 | if ((inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) == 0) | ||
79 | break; | ||
80 | udelay(100); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | void snd_ad1848_out(struct snd_wss *chip, | ||
85 | unsigned char reg, | ||
86 | unsigned char value) | ||
87 | { | ||
88 | snd_ad1848_wait(chip); | ||
89 | #ifdef CONFIG_SND_DEBUG | ||
90 | if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) | ||
91 | snd_printk(KERN_WARNING "auto calibration time out - " | ||
92 | "reg = 0x%x, value = 0x%x\n", reg, value); | ||
93 | #endif | ||
94 | outb(chip->mce_bit | reg, chip->port + CS4231P(REGSEL)); | ||
95 | outb(chip->image[reg] = value, chip->port + CS4231P(REG)); | ||
96 | mb(); | ||
97 | snd_printdd("codec out - reg 0x%x = 0x%x\n", | ||
98 | chip->mce_bit | reg, value); | ||
99 | } | ||
100 | |||
101 | EXPORT_SYMBOL(snd_ad1848_out); | ||
102 | |||
103 | static unsigned char snd_ad1848_in(struct snd_wss *chip, unsigned char reg) | ||
104 | { | ||
105 | snd_ad1848_wait(chip); | ||
106 | #ifdef CONFIG_SND_DEBUG | ||
107 | if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) | ||
108 | snd_printk(KERN_WARNING "auto calibration time out - " | ||
109 | "reg = 0x%x\n", reg); | ||
110 | #endif | ||
111 | outb(chip->mce_bit | reg, chip->port + CS4231P(REGSEL)); | ||
112 | mb(); | ||
113 | return inb(chip->port + CS4231P(REG)); | ||
114 | } | ||
115 | |||
116 | #if 0 | ||
117 | |||
118 | static void snd_ad1848_debug(struct snd_wss *chip) | ||
119 | { | ||
120 | printk(KERN_DEBUG "AD1848 REGS: INDEX = 0x%02x ", inb(chip->port + CS4231P(REGSEL))); | ||
121 | printk(KERN_DEBUG " STATUS = 0x%02x\n", inb(chip->port + CS4231P(STATUS))); | ||
122 | printk(KERN_DEBUG " 0x00: left input = 0x%02x ", snd_ad1848_in(chip, 0x00)); | ||
123 | printk(KERN_DEBUG " 0x08: playback format = 0x%02x\n", snd_ad1848_in(chip, 0x08)); | ||
124 | printk(KERN_DEBUG " 0x01: right input = 0x%02x ", snd_ad1848_in(chip, 0x01)); | ||
125 | printk(KERN_DEBUG " 0x09: iface (CFIG 1) = 0x%02x\n", snd_ad1848_in(chip, 0x09)); | ||
126 | printk(KERN_DEBUG " 0x02: AUXA left = 0x%02x ", snd_ad1848_in(chip, 0x02)); | ||
127 | printk(KERN_DEBUG " 0x0a: pin control = 0x%02x\n", snd_ad1848_in(chip, 0x0a)); | ||
128 | printk(KERN_DEBUG " 0x03: AUXA right = 0x%02x ", snd_ad1848_in(chip, 0x03)); | ||
129 | printk(KERN_DEBUG " 0x0b: init & status = 0x%02x\n", snd_ad1848_in(chip, 0x0b)); | ||
130 | printk(KERN_DEBUG " 0x04: AUXB left = 0x%02x ", snd_ad1848_in(chip, 0x04)); | ||
131 | printk(KERN_DEBUG " 0x0c: revision & mode = 0x%02x\n", snd_ad1848_in(chip, 0x0c)); | ||
132 | printk(KERN_DEBUG " 0x05: AUXB right = 0x%02x ", snd_ad1848_in(chip, 0x05)); | ||
133 | printk(KERN_DEBUG " 0x0d: loopback = 0x%02x\n", snd_ad1848_in(chip, 0x0d)); | ||
134 | printk(KERN_DEBUG " 0x06: left output = 0x%02x ", snd_ad1848_in(chip, 0x06)); | ||
135 | printk(KERN_DEBUG " 0x0e: data upr count = 0x%02x\n", snd_ad1848_in(chip, 0x0e)); | ||
136 | printk(KERN_DEBUG " 0x07: right output = 0x%02x ", snd_ad1848_in(chip, 0x07)); | ||
137 | printk(KERN_DEBUG " 0x0f: data lwr count = 0x%02x\n", snd_ad1848_in(chip, 0x0f)); | ||
138 | } | ||
139 | |||
140 | #endif | ||
141 | |||
142 | /* | ||
143 | * AD1848 detection / MCE routines | ||
144 | */ | ||
145 | |||
146 | static void snd_ad1848_mce_up(struct snd_wss *chip) | ||
147 | { | ||
148 | unsigned long flags; | ||
149 | int timeout; | ||
150 | |||
151 | snd_ad1848_wait(chip); | ||
152 | #ifdef CONFIG_SND_DEBUG | ||
153 | if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) | ||
154 | snd_printk(KERN_WARNING "mce_up - auto calibration time out (0)\n"); | ||
155 | #endif | ||
156 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
157 | chip->mce_bit |= AD1848_MCE; | ||
158 | timeout = inb(chip->port + CS4231P(REGSEL)); | ||
159 | if (timeout == 0x80) | ||
160 | snd_printk(KERN_WARNING "mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port); | ||
161 | if (!(timeout & AD1848_MCE)) | ||
162 | outb(chip->mce_bit | (timeout & 0x1f), | ||
163 | chip->port + CS4231P(REGSEL)); | ||
164 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
165 | } | ||
166 | |||
167 | static void snd_ad1848_mce_down(struct snd_wss *chip) | ||
168 | { | ||
169 | unsigned long flags, timeout; | ||
170 | int reg; | ||
171 | |||
172 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
173 | for (timeout = 5; timeout > 0; timeout--) | ||
174 | inb(chip->port + CS4231P(REGSEL)); | ||
175 | /* end of cleanup sequence */ | ||
176 | for (timeout = 12000; | ||
177 | timeout > 0 && (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT); | ||
178 | timeout--) | ||
179 | udelay(100); | ||
180 | |||
181 | snd_printdd("(1) timeout = %ld\n", timeout); | ||
182 | |||
183 | #ifdef CONFIG_SND_DEBUG | ||
184 | if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) | ||
185 | snd_printk(KERN_WARNING | ||
186 | "mce_down [0x%lx] - auto calibration time out (0)\n", | ||
187 | chip->port + CS4231P(REGSEL)); | ||
188 | #endif | ||
189 | |||
190 | chip->mce_bit &= ~AD1848_MCE; | ||
191 | reg = inb(chip->port + CS4231P(REGSEL)); | ||
192 | outb(chip->mce_bit | (reg & 0x1f), chip->port + CS4231P(REGSEL)); | ||
193 | if (reg == 0x80) | ||
194 | snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); | ||
195 | if ((reg & AD1848_MCE) == 0) { | ||
196 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
197 | return; | ||
198 | } | ||
199 | |||
200 | /* | ||
201 | * Wait for auto-calibration (AC) process to finish, i.e. ACI to go low. | ||
202 | * It may take up to 5 sample periods (at most 907 us @ 5.5125 kHz) for | ||
203 | * the process to _start_, so it is important to wait at least that long | ||
204 | * before checking. Otherwise we might think AC has finished when it | ||
205 | * has in fact not begun. It could take 128 (no AC) or 384 (AC) cycles | ||
206 | * for ACI to drop. This gives a wait of at most 70 ms with a more | ||
207 | * typical value of 3-9 ms. | ||
208 | */ | ||
209 | timeout = jiffies + msecs_to_jiffies(250); | ||
210 | do { | ||
211 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
212 | msleep(1); | ||
213 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
214 | reg = snd_ad1848_in(chip, AD1848_TEST_INIT) & | ||
215 | AD1848_CALIB_IN_PROGRESS; | ||
216 | } while (reg && time_before(jiffies, timeout)); | ||
217 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
218 | if (reg) | ||
219 | snd_printk(KERN_ERR | ||
220 | "mce_down - auto calibration time out (2)\n"); | ||
221 | |||
222 | snd_printdd("(4) jiffies = %lu\n", jiffies); | ||
223 | snd_printd("mce_down - exit = 0x%x\n", | ||
224 | inb(chip->port + CS4231P(REGSEL))); | ||
225 | } | ||
226 | |||
227 | static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id) | ||
228 | { | ||
229 | struct snd_wss *chip = dev_id; | ||
230 | |||
231 | if ((chip->mode & WSS_MODE_PLAY) && chip->playback_substream) | ||
232 | snd_pcm_period_elapsed(chip->playback_substream); | ||
233 | if ((chip->mode & WSS_MODE_RECORD) && chip->capture_substream) | ||
234 | snd_pcm_period_elapsed(chip->capture_substream); | ||
235 | outb(0, chip->port + CS4231P(STATUS)); /* clear global interrupt bit */ | ||
236 | return IRQ_HANDLED; | ||
237 | } | ||
238 | |||
239 | /* | ||
240 | |||
241 | */ | ||
242 | |||
243 | static void snd_ad1848_thinkpad_twiddle(struct snd_wss *chip, int on) | ||
244 | { | ||
245 | int tmp; | ||
246 | |||
247 | if (!chip->thinkpad_flag) return; | ||
248 | |||
249 | outb(0x1c, AD1848_THINKPAD_CTL_PORT1); | ||
250 | tmp = inb(AD1848_THINKPAD_CTL_PORT2); | ||
251 | |||
252 | if (on) | ||
253 | /* turn it on */ | ||
254 | tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT; | ||
255 | else | ||
256 | /* turn it off */ | ||
257 | tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT; | ||
258 | |||
259 | outb(tmp, AD1848_THINKPAD_CTL_PORT2); | ||
260 | |||
261 | } | ||
262 | |||
263 | #ifdef CONFIG_PM | ||
264 | static void snd_ad1848_suspend(struct snd_wss *chip) | ||
265 | { | ||
266 | snd_pcm_suspend_all(chip->pcm); | ||
267 | if (chip->thinkpad_flag) | ||
268 | snd_ad1848_thinkpad_twiddle(chip, 0); | ||
269 | } | ||
270 | |||
271 | static void snd_ad1848_resume(struct snd_wss *chip) | ||
272 | { | ||
273 | int i; | ||
274 | |||
275 | if (chip->thinkpad_flag) | ||
276 | snd_ad1848_thinkpad_twiddle(chip, 1); | ||
277 | |||
278 | /* clear any pendings IRQ */ | ||
279 | inb(chip->port + CS4231P(STATUS)); | ||
280 | outb(0, chip->port + CS4231P(STATUS)); | ||
281 | mb(); | ||
282 | |||
283 | snd_ad1848_mce_down(chip); | ||
284 | for (i = 0; i < 16; i++) | ||
285 | snd_ad1848_out(chip, i, chip->image[i]); | ||
286 | snd_ad1848_mce_up(chip); | ||
287 | snd_ad1848_mce_down(chip); | ||
288 | } | ||
289 | #endif /* CONFIG_PM */ | ||
290 | |||
291 | static int snd_ad1848_probe(struct snd_wss *chip) | ||
292 | { | ||
293 | unsigned long flags; | ||
294 | int i, id, rev, ad1847; | ||
295 | unsigned char *ptr; | ||
296 | |||
297 | #if 0 | ||
298 | snd_ad1848_debug(chip); | ||
299 | #endif | ||
300 | id = ad1847 = 0; | ||
301 | for (i = 0; i < 1000; i++) { | ||
302 | mb(); | ||
303 | if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) | ||
304 | udelay(500); | ||
305 | else { | ||
306 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
307 | snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00); | ||
308 | snd_ad1848_out(chip, AD1848_LEFT_INPUT, 0xaa); | ||
309 | snd_ad1848_out(chip, AD1848_RIGHT_INPUT, 0x45); | ||
310 | rev = snd_ad1848_in(chip, AD1848_RIGHT_INPUT); | ||
311 | if (rev == 0x65) { | ||
312 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
313 | id = 1; | ||
314 | ad1847 = 1; | ||
315 | break; | ||
316 | } | ||
317 | if (snd_ad1848_in(chip, AD1848_LEFT_INPUT) == 0xaa && rev == 0x45) { | ||
318 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
319 | id = 1; | ||
320 | break; | ||
321 | } | ||
322 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
323 | } | ||
324 | } | ||
325 | if (id != 1) | ||
326 | return -ENODEV; /* no valid device found */ | ||
327 | if (chip->hardware == WSS_HW_DETECT) { | ||
328 | if (ad1847) { | ||
329 | chip->hardware = WSS_HW_AD1847; | ||
330 | } else { | ||
331 | chip->hardware = WSS_HW_AD1848; | ||
332 | rev = snd_ad1848_in(chip, AD1848_MISC_INFO); | ||
333 | if (rev & 0x80) { | ||
334 | chip->hardware = WSS_HW_CS4248; | ||
335 | } else if ((rev & 0x0f) == 0x0a) { | ||
336 | snd_ad1848_out(chip, AD1848_MISC_INFO, 0x40); | ||
337 | for (i = 0; i < 16; ++i) { | ||
338 | if (snd_ad1848_in(chip, i) != snd_ad1848_in(chip, i + 16)) { | ||
339 | chip->hardware = WSS_HW_CMI8330; | ||
340 | break; | ||
341 | } | ||
342 | } | ||
343 | snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00); | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
348 | inb(chip->port + CS4231P(STATUS)); /* clear any pendings IRQ */ | ||
349 | outb(0, chip->port + CS4231P(STATUS)); | ||
350 | mb(); | ||
351 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
352 | |||
353 | chip->image[AD1848_MISC_INFO] = 0x00; | ||
354 | chip->image[AD1848_IFACE_CTRL] = | ||
355 | (chip->image[AD1848_IFACE_CTRL] & ~AD1848_SINGLE_DMA) | AD1848_SINGLE_DMA; | ||
356 | ptr = (unsigned char *) &chip->image; | ||
357 | snd_ad1848_mce_down(chip); | ||
358 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
359 | for (i = 0; i < 16; i++) /* ok.. fill all AD1848 registers */ | ||
360 | snd_ad1848_out(chip, i, *ptr++); | ||
361 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
362 | snd_ad1848_mce_up(chip); | ||
363 | /* init needed for WSS pcm */ | ||
364 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
365 | chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | | ||
366 | AD1848_PLAYBACK_PIO | | ||
367 | AD1848_CAPTURE_ENABLE | | ||
368 | AD1848_CAPTURE_PIO | | ||
369 | AD1848_CALIB_MODE); | ||
370 | chip->image[AD1848_IFACE_CTRL] |= AD1848_AUTOCALIB; | ||
371 | snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]); | ||
372 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
373 | snd_ad1848_mce_down(chip); | ||
374 | return 0; /* all things are ok.. */ | ||
375 | } | ||
376 | |||
377 | /* | ||
378 | |||
379 | */ | ||
380 | |||
381 | static int snd_ad1848_free(struct snd_wss *chip) | ||
382 | { | ||
383 | release_and_free_resource(chip->res_port); | ||
384 | if (chip->irq >= 0) | ||
385 | free_irq(chip->irq, (void *) chip); | ||
386 | if (chip->dma1 >= 0) { | ||
387 | snd_dma_disable(chip->dma1); | ||
388 | free_dma(chip->dma1); | ||
389 | } | ||
390 | kfree(chip); | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static int snd_ad1848_dev_free(struct snd_device *device) | ||
395 | { | ||
396 | struct snd_wss *chip = device->device_data; | ||
397 | return snd_ad1848_free(chip); | ||
398 | } | ||
399 | |||
400 | int snd_ad1848_create(struct snd_card *card, | ||
401 | unsigned long port, | ||
402 | int irq, int dma, | ||
403 | unsigned short hardware, | ||
404 | struct snd_wss **rchip) | ||
405 | { | ||
406 | static struct snd_device_ops ops = { | ||
407 | .dev_free = snd_ad1848_dev_free, | ||
408 | }; | ||
409 | struct snd_wss *chip; | ||
410 | int err; | ||
411 | |||
412 | *rchip = NULL; | ||
413 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
414 | if (chip == NULL) | ||
415 | return -ENOMEM; | ||
416 | spin_lock_init(&chip->reg_lock); | ||
417 | chip->card = card; | ||
418 | chip->port = port; | ||
419 | chip->irq = -1; | ||
420 | chip->dma1 = -1; | ||
421 | chip->dma2 = -1; | ||
422 | chip->single_dma = 1; | ||
423 | chip->hardware = hardware; | ||
424 | memcpy(&chip->image, &snd_ad1848_original_image, sizeof(snd_ad1848_original_image)); | ||
425 | |||
426 | if ((chip->res_port = request_region(port, 4, "AD1848")) == NULL) { | ||
427 | snd_printk(KERN_ERR "ad1848: can't grab port 0x%lx\n", port); | ||
428 | snd_ad1848_free(chip); | ||
429 | return -EBUSY; | ||
430 | } | ||
431 | if (request_irq(irq, snd_ad1848_interrupt, IRQF_DISABLED, "AD1848", (void *) chip)) { | ||
432 | snd_printk(KERN_ERR "ad1848: can't grab IRQ %d\n", irq); | ||
433 | snd_ad1848_free(chip); | ||
434 | return -EBUSY; | ||
435 | } | ||
436 | chip->irq = irq; | ||
437 | if (request_dma(dma, "AD1848")) { | ||
438 | snd_printk(KERN_ERR "ad1848: can't grab DMA %d\n", dma); | ||
439 | snd_ad1848_free(chip); | ||
440 | return -EBUSY; | ||
441 | } | ||
442 | chip->dma1 = dma; | ||
443 | chip->dma2 = dma; | ||
444 | |||
445 | if (hardware == WSS_HW_THINKPAD) { | ||
446 | chip->thinkpad_flag = 1; | ||
447 | chip->hardware = WSS_HW_DETECT; /* reset */ | ||
448 | snd_ad1848_thinkpad_twiddle(chip, 1); | ||
449 | } | ||
450 | |||
451 | if (snd_ad1848_probe(chip) < 0) { | ||
452 | snd_ad1848_free(chip); | ||
453 | return -ENODEV; | ||
454 | } | ||
455 | |||
456 | /* Register device */ | ||
457 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { | ||
458 | snd_ad1848_free(chip); | ||
459 | return err; | ||
460 | } | ||
461 | |||
462 | #ifdef CONFIG_PM | ||
463 | chip->suspend = snd_ad1848_suspend; | ||
464 | chip->resume = snd_ad1848_resume; | ||
465 | #endif | ||
466 | |||
467 | *rchip = chip; | ||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | EXPORT_SYMBOL(snd_ad1848_create); | ||
472 | |||
473 | /* | ||
474 | * INIT part | ||
475 | */ | ||
476 | |||
477 | static int __init alsa_ad1848_init(void) | ||
478 | { | ||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | static void __exit alsa_ad1848_exit(void) | ||
483 | { | ||
484 | } | ||
485 | |||
486 | module_init(alsa_ad1848_init) | ||
487 | module_exit(alsa_ad1848_exit) | ||
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index 6f7e8bb6ae60..e49aec700a55 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c | |||
@@ -50,7 +50,7 @@ | |||
50 | #include <linux/pnp.h> | 50 | #include <linux/pnp.h> |
51 | #include <linux/moduleparam.h> | 51 | #include <linux/moduleparam.h> |
52 | #include <sound/core.h> | 52 | #include <sound/core.h> |
53 | #include <sound/ad1848.h> | 53 | #include <sound/wss.h> |
54 | #include <sound/sb.h> | 54 | #include <sound/sb.h> |
55 | #include <sound/initval.h> | 55 | #include <sound/initval.h> |
56 | 56 | ||
@@ -180,9 +180,9 @@ WSS_DOUBLE("Master Playback Volume", 0, | |||
180 | WSS_SINGLE("Loud Playback Switch", 0, | 180 | WSS_SINGLE("Loud Playback Switch", 0, |
181 | CMI8330_MUTEMUX, 6, 1, 1), | 181 | CMI8330_MUTEMUX, 6, 1, 1), |
182 | WSS_DOUBLE("PCM Playback Switch", 0, | 182 | WSS_DOUBLE("PCM Playback Switch", 0, |
183 | AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), | 183 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), |
184 | WSS_DOUBLE("PCM Playback Volume", 0, | 184 | WSS_DOUBLE("PCM Playback Volume", 0, |
185 | AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1), | 185 | CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), |
186 | WSS_DOUBLE("Line Playback Switch", 0, | 186 | WSS_DOUBLE("Line Playback Switch", 0, |
187 | CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0), | 187 | CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0), |
188 | WSS_DOUBLE("Line Playback Volume", 0, | 188 | WSS_DOUBLE("Line Playback Volume", 0, |
@@ -489,12 +489,11 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) | |||
489 | int i, err; | 489 | int i, err; |
490 | 490 | ||
491 | acard = card->private_data; | 491 | acard = card->private_data; |
492 | if ((err = snd_ad1848_create(card, | 492 | err = snd_wss_create(card, wssport[dev] + 4, -1, |
493 | wssport[dev] + 4, | 493 | wssirq[dev], |
494 | wssirq[dev], | 494 | wssdma[dev], -1, |
495 | wssdma[dev], | 495 | WSS_HW_DETECT, 0, &acard->wss); |
496 | WSS_HW_DETECT, | 496 | if (err < 0) { |
497 | &acard->wss)) < 0) { | ||
498 | snd_printk(KERN_ERR PFX "(AD1848) device busy??\n"); | 497 | snd_printk(KERN_ERR PFX "(AD1848) device busy??\n"); |
499 | return err; | 498 | return err; |
500 | } | 499 | } |
@@ -517,9 +516,10 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) | |||
517 | return err; | 516 | return err; |
518 | } | 517 | } |
519 | 518 | ||
520 | snd_ad1848_out(acard->wss, AD1848_MISC_INFO, 0x40); /* switch on MODE2 */ | 519 | snd_wss_out(acard->wss, CS4231_MISC_INFO, 0x40); /* switch on MODE2 */ |
521 | for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++) | 520 | for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++) |
522 | snd_ad1848_out(acard->wss, i, snd_cmi8330_image[i - CMI8330_RMUX3D]); | 521 | snd_wss_out(acard->wss, i, |
522 | snd_cmi8330_image[i - CMI8330_RMUX3D]); | ||
523 | 523 | ||
524 | if ((err = snd_cmi8330_mixer(card, acard)) < 0) { | 524 | if ((err = snd_cmi8330_mixer(card, acard)) < 0) { |
525 | snd_printk(KERN_ERR PFX "failed to create mixers\n"); | 525 | snd_printk(KERN_ERR PFX "failed to create mixers\n"); |
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 561d4b3ed098..cb5f66bde5d3 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c | |||
@@ -33,11 +33,7 @@ | |||
33 | #include <asm/io.h> | 33 | #include <asm/io.h> |
34 | #include <asm/dma.h> | 34 | #include <asm/dma.h> |
35 | #include <sound/core.h> | 35 | #include <sound/core.h> |
36 | #if defined(CS4231) || defined(OPTi93X) | ||
37 | #include <sound/wss.h> | 36 | #include <sound/wss.h> |
38 | #else | ||
39 | #include <sound/ad1848.h> | ||
40 | #endif /* CS4231 */ | ||
41 | #include <sound/mpu401.h> | 37 | #include <sound/mpu401.h> |
42 | #include <sound/opl3.h> | 38 | #include <sound/opl3.h> |
43 | #ifndef OPTi93X | 39 | #ifndef OPTi93X |
@@ -148,9 +144,7 @@ struct snd_opti9xx { | |||
148 | long wss_base; | 144 | long wss_base; |
149 | int irq; | 145 | int irq; |
150 | int dma1; | 146 | int dma1; |
151 | #if defined(CS4231) || defined(OPTi93X) | ||
152 | int dma2; | 147 | int dma2; |
153 | #endif /* CS4231 || OPTi93X */ | ||
154 | 148 | ||
155 | long fm_port; | 149 | long fm_port; |
156 | 150 | ||
@@ -225,9 +219,7 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, | |||
225 | chip->wss_base = -1; | 219 | chip->wss_base = -1; |
226 | chip->irq = -1; | 220 | chip->irq = -1; |
227 | chip->dma1 = -1; | 221 | chip->dma1 = -1; |
228 | #if defined(CS4231) || defined (OPTi93X) | ||
229 | chip->dma2 = -1; | 222 | chip->dma2 = -1; |
230 | #endif /* CS4231 || OPTi93X */ | ||
231 | chip->fm_port = -1; | 223 | chip->fm_port = -1; |
232 | chip->mpu_port = -1; | 224 | chip->mpu_port = -1; |
233 | chip->mpu_irq = -1; | 225 | chip->mpu_irq = -1; |
@@ -740,7 +732,6 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) | |||
740 | if (error) | 732 | if (error) |
741 | return error; | 733 | return error; |
742 | 734 | ||
743 | #if defined(CS4231) || defined(OPTi93X) | ||
744 | error = snd_wss_create(card, chip->wss_base + 4, -1, | 735 | error = snd_wss_create(card, chip->wss_base + 4, -1, |
745 | chip->irq, chip->dma1, chip->dma2, | 736 | chip->irq, chip->dma1, chip->dma2, |
746 | #ifdef CS4231 | 737 | #ifdef CS4231 |
@@ -754,12 +745,6 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) | |||
754 | #ifdef OPTi93X | 745 | #ifdef OPTi93X |
755 | chip->codec = codec; | 746 | chip->codec = codec; |
756 | #endif | 747 | #endif |
757 | #else | ||
758 | error = snd_ad1848_create(card, chip->wss_base + 4, chip->irq, | ||
759 | chip->dma1, WSS_HW_DETECT, &codec); | ||
760 | if (error < 0) | ||
761 | return error; | ||
762 | #endif | ||
763 | error = snd_wss_pcm(codec, 0, &pcm); | 748 | error = snd_wss_pcm(codec, 0, &pcm); |
764 | if (error < 0) | 749 | if (error < 0) |
765 | return error; | 750 | return error; |
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index 2f89ecb95ded..ca35924dc3b3 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/io.h> | 29 | #include <linux/io.h> |
30 | #include <asm/dma.h> | 30 | #include <asm/dma.h> |
31 | #include <sound/core.h> | 31 | #include <sound/core.h> |
32 | #include <sound/ad1848.h> | 32 | #include <sound/wss.h> |
33 | #include <sound/opl3.h> | 33 | #include <sound/opl3.h> |
34 | #include <sound/mpu401.h> | 34 | #include <sound/mpu401.h> |
35 | #include <sound/control.h> | 35 | #include <sound/control.h> |
@@ -548,8 +548,8 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) | |||
548 | if (err < 0) | 548 | if (err < 0) |
549 | goto err_unmap2; | 549 | goto err_unmap2; |
550 | 550 | ||
551 | err = snd_ad1848_create(card, mss_port[dev] + 4, xirq, xdma, | 551 | err = snd_wss_create(card, mss_port[dev] + 4, -1, xirq, xdma, -1, |
552 | WSS_HW_DETECT, &chip); | 552 | WSS_HW_DETECT, 0, &chip); |
553 | if (err < 0) | 553 | if (err < 0) |
554 | goto err_unmap2; | 554 | goto err_unmap2; |
555 | card->private_data = chip; | 555 | card->private_data = chip; |
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c index b43d6678ba20..2c7503bf1271 100644 --- a/sound/isa/sgalaxy.c +++ b/sound/isa/sgalaxy.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <asm/dma.h> | 31 | #include <asm/dma.h> |
32 | #include <sound/core.h> | 32 | #include <sound/core.h> |
33 | #include <sound/sb.h> | 33 | #include <sound/sb.h> |
34 | #include <sound/ad1848.h> | 34 | #include <sound/wss.h> |
35 | #include <sound/control.h> | 35 | #include <sound/control.h> |
36 | #define SNDRV_LEGACY_FIND_FREE_IRQ | 36 | #define SNDRV_LEGACY_FIND_FREE_IRQ |
37 | #define SNDRV_LEGACY_FIND_FREE_DMA | 37 | #define SNDRV_LEGACY_FIND_FREE_DMA |
@@ -267,9 +267,10 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev) | |||
267 | if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0) | 267 | if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0) |
268 | goto _err; | 268 | goto _err; |
269 | 269 | ||
270 | if ((err = snd_ad1848_create(card, wssport[dev] + 4, | 270 | err = snd_wss_create(card, wssport[dev] + 4, -1, |
271 | xirq, xdma1, | 271 | xirq, xdma1, -1, |
272 | WSS_HW_DETECT, &chip)) < 0) | 272 | WSS_HW_DETECT, 0, &chip); |
273 | if (err < 0) | ||
273 | goto _err; | 274 | goto _err; |
274 | card->private_data = chip; | 275 | card->private_data = chip; |
275 | 276 | ||
@@ -331,8 +332,8 @@ static int snd_sgalaxy_resume(struct device *pdev, unsigned int n) | |||
331 | struct snd_wss *chip = card->private_data; | 332 | struct snd_wss *chip = card->private_data; |
332 | 333 | ||
333 | chip->resume(chip); | 334 | chip->resume(chip); |
334 | snd_ad1848_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]); | 335 | snd_wss_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]); |
335 | snd_ad1848_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]); | 336 | snd_wss_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]); |
336 | 337 | ||
337 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 338 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
338 | return 0; | 339 | return 0; |
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 57d1e8ee6bbb..a5602f515f49 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c | |||
@@ -1073,7 +1073,11 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id) | |||
1073 | struct snd_wss *chip = dev_id; | 1073 | struct snd_wss *chip = dev_id; |
1074 | unsigned char status; | 1074 | unsigned char status; |
1075 | 1075 | ||
1076 | status = snd_wss_in(chip, CS4231_IRQ_STATUS); | 1076 | if (chip->hardware & WSS_HW_AD1848_MASK) |
1077 | /* pretend it was the only possible irq for AD1848 */ | ||
1078 | status = CS4231_PLAYBACK_IRQ; | ||
1079 | else | ||
1080 | status = snd_wss_in(chip, CS4231_IRQ_STATUS); | ||
1077 | if (status & CS4231_TIMER_IRQ) { | 1081 | if (status & CS4231_TIMER_IRQ) { |
1078 | if (chip->timer) | 1082 | if (chip->timer) |
1079 | snd_timer_interrupt(chip->timer, chip->timer->sticks); | 1083 | snd_timer_interrupt(chip->timer, chip->timer->sticks); |
@@ -1105,7 +1109,11 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id) | |||
1105 | } | 1109 | } |
1106 | 1110 | ||
1107 | spin_lock(&chip->reg_lock); | 1111 | spin_lock(&chip->reg_lock); |
1108 | snd_wss_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); | 1112 | status = ~CS4231_ALL_IRQS | ~status; |
1113 | if (chip->hardware & WSS_HW_AD1848_MASK) | ||
1114 | wss_outb(chip, CS4231P(STATUS), 0); | ||
1115 | else | ||
1116 | snd_wss_outm(chip, CS4231_IRQ_STATUS, status, 0); | ||
1109 | spin_unlock(&chip->reg_lock); | 1117 | spin_unlock(&chip->reg_lock); |
1110 | return IRQ_HANDLED; | 1118 | return IRQ_HANDLED; |
1111 | } | 1119 | } |
@@ -1137,36 +1145,112 @@ static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *subst | |||
1137 | 1145 | ||
1138 | */ | 1146 | */ |
1139 | 1147 | ||
1140 | static int snd_wss_probe(struct snd_wss *chip) | 1148 | static int snd_ad1848_probe(struct snd_wss *chip) |
1141 | { | 1149 | { |
1142 | unsigned long flags; | 1150 | unsigned long flags; |
1143 | int i, id, rev; | 1151 | int i, id, rev, ad1847; |
1144 | unsigned char *ptr; | ||
1145 | unsigned int hw; | ||
1146 | 1152 | ||
1147 | #if 0 | ||
1148 | snd_wss_debug(chip); | ||
1149 | #endif | ||
1150 | id = 0; | 1153 | id = 0; |
1151 | for (i = 0; i < 50; i++) { | 1154 | ad1847 = 0; |
1155 | for (i = 0; i < 1000; i++) { | ||
1152 | mb(); | 1156 | mb(); |
1153 | if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | 1157 | if (inb(chip->port + CS4231P(REGSEL)) & CS4231_INIT) |
1154 | udelay(2000); | 1158 | msleep(1); |
1155 | else { | 1159 | else { |
1156 | spin_lock_irqsave(&chip->reg_lock, flags); | 1160 | spin_lock_irqsave(&chip->reg_lock, flags); |
1157 | snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2); | 1161 | snd_wss_out(chip, CS4231_MISC_INFO, 0x00); |
1158 | id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f; | 1162 | snd_wss_out(chip, CS4231_LEFT_INPUT, 0xaa); |
1163 | snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x45); | ||
1164 | rev = snd_wss_in(chip, CS4231_RIGHT_INPUT); | ||
1165 | if (rev == 0x65) { | ||
1166 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1167 | id = 1; | ||
1168 | ad1847 = 1; | ||
1169 | break; | ||
1170 | } | ||
1171 | if (snd_wss_in(chip, CS4231_LEFT_INPUT) == 0xaa && | ||
1172 | rev == 0x45) { | ||
1173 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1174 | id = 1; | ||
1175 | break; | ||
1176 | } | ||
1159 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1177 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
1160 | if (id == 0x0a) | ||
1161 | break; /* this is valid value */ | ||
1162 | } | 1178 | } |
1163 | } | 1179 | } |
1164 | snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id); | 1180 | if (id != 1) |
1165 | if (id != 0x0a) | ||
1166 | return -ENODEV; /* no valid device found */ | 1181 | return -ENODEV; /* no valid device found */ |
1182 | id = 0; | ||
1183 | if (chip->hardware == WSS_HW_DETECT) | ||
1184 | id = ad1847 ? WSS_HW_AD1847 : WSS_HW_AD1848; | ||
1185 | |||
1186 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
1187 | inb(chip->port + CS4231P(STATUS)); /* clear any pendings IRQ */ | ||
1188 | outb(0, chip->port + CS4231P(STATUS)); | ||
1189 | mb(); | ||
1190 | if (id == WSS_HW_AD1848) { | ||
1191 | /* check if there are more than 16 registers */ | ||
1192 | rev = snd_wss_in(chip, CS4231_MISC_INFO); | ||
1193 | snd_wss_out(chip, CS4231_MISC_INFO, 0x40); | ||
1194 | for (i = 0; i < 16; ++i) { | ||
1195 | if (snd_wss_in(chip, i) != snd_wss_in(chip, i + 16)) { | ||
1196 | id = WSS_HW_CMI8330; | ||
1197 | break; | ||
1198 | } | ||
1199 | } | ||
1200 | snd_wss_out(chip, CS4231_MISC_INFO, 0x00); | ||
1201 | if (id != WSS_HW_CMI8330 && (rev & 0x80)) | ||
1202 | id = WSS_HW_CS4248; | ||
1203 | if (id == WSS_HW_CMI8330 && (rev & 0x0f) != 0x0a) | ||
1204 | id = 0; | ||
1205 | } | ||
1206 | if (id == WSS_HW_CMI8330) { | ||
1207 | /* verify it is not CS4231 by changing the version register */ | ||
1208 | /* on CMI8330 it is volume control register and can be set 0 */ | ||
1209 | snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2); | ||
1210 | snd_wss_dout(chip, CS4231_VERSION, 0x00); | ||
1211 | rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7; | ||
1212 | if (rev) | ||
1213 | id = 0; | ||
1214 | snd_wss_out(chip, CS4231_MISC_INFO, 0); | ||
1215 | } | ||
1216 | if (id) | ||
1217 | chip->hardware = id; | ||
1218 | |||
1219 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1220 | return 0; /* all things are ok.. */ | ||
1221 | } | ||
1222 | |||
1223 | static int snd_wss_probe(struct snd_wss *chip) | ||
1224 | { | ||
1225 | unsigned long flags; | ||
1226 | int i, id, rev, regnum; | ||
1227 | unsigned char *ptr; | ||
1228 | unsigned int hw; | ||
1229 | |||
1230 | id = snd_ad1848_probe(chip); | ||
1231 | if (id < 0) | ||
1232 | return id; | ||
1167 | 1233 | ||
1168 | hw = chip->hardware; | 1234 | hw = chip->hardware; |
1169 | if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) { | 1235 | if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) { |
1236 | for (i = 0; i < 50; i++) { | ||
1237 | mb(); | ||
1238 | if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) | ||
1239 | msleep(2); | ||
1240 | else { | ||
1241 | spin_lock_irqsave(&chip->reg_lock, flags); | ||
1242 | snd_wss_out(chip, CS4231_MISC_INFO, | ||
1243 | CS4231_MODE2); | ||
1244 | id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f; | ||
1245 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
1246 | if (id == 0x0a) | ||
1247 | break; /* this is valid value */ | ||
1248 | } | ||
1249 | } | ||
1250 | snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id); | ||
1251 | if (id != 0x0a) | ||
1252 | return -ENODEV; /* no valid device found */ | ||
1253 | |||
1170 | rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7; | 1254 | rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7; |
1171 | snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev); | 1255 | snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev); |
1172 | if (rev == 0x80) { | 1256 | if (rev == 0x80) { |
@@ -1197,7 +1281,8 @@ static int snd_wss_probe(struct snd_wss *chip) | |||
1197 | mb(); | 1281 | mb(); |
1198 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1282 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
1199 | 1283 | ||
1200 | chip->image[CS4231_MISC_INFO] = CS4231_MODE2; | 1284 | if (!(chip->hardware & WSS_HW_AD1848_MASK)) |
1285 | chip->image[CS4231_MISC_INFO] = CS4231_MODE2; | ||
1201 | switch (chip->hardware) { | 1286 | switch (chip->hardware) { |
1202 | case WSS_HW_INTERWAVE: | 1287 | case WSS_HW_INTERWAVE: |
1203 | chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3; | 1288 | chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3; |
@@ -1223,9 +1308,10 @@ static int snd_wss_probe(struct snd_wss *chip) | |||
1223 | chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; | 1308 | chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; |
1224 | } | 1309 | } |
1225 | ptr = (unsigned char *) &chip->image; | 1310 | ptr = (unsigned char *) &chip->image; |
1311 | regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32; | ||
1226 | snd_wss_mce_down(chip); | 1312 | snd_wss_mce_down(chip); |
1227 | spin_lock_irqsave(&chip->reg_lock, flags); | 1313 | spin_lock_irqsave(&chip->reg_lock, flags); |
1228 | for (i = 0; i < 32; i++) /* ok.. fill all CS4231 registers */ | 1314 | for (i = 0; i < regnum; i++) /* ok.. fill all registers */ |
1229 | snd_wss_out(chip, i, *ptr++); | 1315 | snd_wss_out(chip, i, *ptr++); |
1230 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1316 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
1231 | snd_wss_mce_up(chip); | 1317 | snd_wss_mce_up(chip); |
@@ -1635,6 +1721,10 @@ static int snd_wss_new(struct snd_card *card, | |||
1635 | else | 1721 | else |
1636 | memcpy(&chip->image, &snd_wss_original_image, | 1722 | memcpy(&chip->image, &snd_wss_original_image, |
1637 | sizeof(snd_wss_original_image)); | 1723 | sizeof(snd_wss_original_image)); |
1724 | if (chip->hardware & WSS_HW_AD1848_MASK) { | ||
1725 | chip->image[CS4231_PIN_CTRL] = 0; | ||
1726 | chip->image[CS4231_TEST_INIT] = 0; | ||
1727 | } | ||
1638 | 1728 | ||
1639 | *rchip = chip; | 1729 | *rchip = chip; |
1640 | return 0; | 1730 | return 0; |
@@ -1662,7 +1752,7 @@ int snd_wss_create(struct snd_card *card, | |||
1662 | chip->dma1 = -1; | 1752 | chip->dma1 = -1; |
1663 | chip->dma2 = -1; | 1753 | chip->dma2 = -1; |
1664 | 1754 | ||
1665 | chip->res_port = request_region(port, 4, "CS4231"); | 1755 | chip->res_port = request_region(port, 4, "WSS"); |
1666 | if (!chip->res_port) { | 1756 | if (!chip->res_port) { |
1667 | snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port); | 1757 | snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port); |
1668 | snd_wss_free(chip); | 1758 | snd_wss_free(chip); |
@@ -1681,20 +1771,20 @@ int snd_wss_create(struct snd_card *card, | |||
1681 | chip->cport = cport; | 1771 | chip->cport = cport; |
1682 | if (!(hwshare & WSS_HWSHARE_IRQ)) | 1772 | if (!(hwshare & WSS_HWSHARE_IRQ)) |
1683 | if (request_irq(irq, snd_wss_interrupt, IRQF_DISABLED, | 1773 | if (request_irq(irq, snd_wss_interrupt, IRQF_DISABLED, |
1684 | "CS4231", (void *) chip)) { | 1774 | "WSS", (void *) chip)) { |
1685 | snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq); | 1775 | snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq); |
1686 | snd_wss_free(chip); | 1776 | snd_wss_free(chip); |
1687 | return -EBUSY; | 1777 | return -EBUSY; |
1688 | } | 1778 | } |
1689 | chip->irq = irq; | 1779 | chip->irq = irq; |
1690 | if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "CS4231 - 1")) { | 1780 | if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) { |
1691 | snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1); | 1781 | snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1); |
1692 | snd_wss_free(chip); | 1782 | snd_wss_free(chip); |
1693 | return -EBUSY; | 1783 | return -EBUSY; |
1694 | } | 1784 | } |
1695 | chip->dma1 = dma1; | 1785 | chip->dma1 = dma1; |
1696 | if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 && | 1786 | if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 && |
1697 | dma2 >= 0 && request_dma(dma2, "CS4231 - 2")) { | 1787 | dma2 >= 0 && request_dma(dma2, "WSS - 2")) { |
1698 | snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2); | 1788 | snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2); |
1699 | snd_wss_free(chip); | 1789 | snd_wss_free(chip); |
1700 | return -EBUSY; | 1790 | return -EBUSY; |
@@ -1705,6 +1795,12 @@ int snd_wss_create(struct snd_card *card, | |||
1705 | } else | 1795 | } else |
1706 | chip->dma2 = dma2; | 1796 | chip->dma2 = dma2; |
1707 | 1797 | ||
1798 | if (hardware == WSS_HW_THINKPAD) { | ||
1799 | chip->thinkpad_flag = 1; | ||
1800 | chip->hardware = WSS_HW_DETECT; /* reset */ | ||
1801 | snd_wss_thinkpad_twiddle(chip, 1); | ||
1802 | } | ||
1803 | |||
1708 | /* global setup */ | 1804 | /* global setup */ |
1709 | if (snd_wss_probe(chip) < 0) { | 1805 | if (snd_wss_probe(chip) < 0) { |
1710 | snd_wss_free(chip); | 1806 | snd_wss_free(chip); |
@@ -1775,12 +1871,6 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) | |||
1775 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops); | 1871 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops); |
1776 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops); | 1872 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops); |
1777 | 1873 | ||
1778 | /* temporary */ | ||
1779 | if (chip->hardware & WSS_HW_AD1848_MASK) { | ||
1780 | chip->rate_constraint = snd_wss_xrate; | ||
1781 | chip->set_playback_format = snd_wss_playback_format; | ||
1782 | chip->set_capture_format = snd_wss_capture_format; | ||
1783 | } | ||
1784 | /* global setup */ | 1874 | /* global setup */ |
1785 | pcm->private_data = chip; | 1875 | pcm->private_data = chip; |
1786 | pcm->info_flags = 0; | 1876 | pcm->info_flags = 0; |