aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/ad1848.h111
-rw-r--r--sound/isa/Kconfig15
-rw-r--r--sound/isa/ad1848/Makefile2
-rw-r--r--sound/isa/ad1848/ad1848.c7
-rw-r--r--sound/isa/ad1848/ad1848_lib.c487
-rw-r--r--sound/isa/cmi8330.c22
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c15
-rw-r--r--sound/isa/sc6000.c6
-rw-r--r--sound/isa/sgalaxy.c13
-rw-r--r--sound/isa/wss/wss_lib.c150
10 files changed, 150 insertions, 678 deletions
diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h
index 7ff484f55b02..e69de29bb2d1 100644
--- a/include/sound/ad1848.h
+++ b/include/sound/ad1848.h
@@ -1,111 +0,0 @@
1#ifndef __SOUND_AD1848_H
2#define __SOUND_AD1848_H
3
4/*
5 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
6 * Definitions for AD1847/AD1848/CS4248 chips
7 *
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24
25#include "pcm.h"
26#include <linux/interrupt.h>
27
28#include "wss.h" /* temporary till the driver is removed */
29
30/* codec registers */
31
32#define AD1848_LEFT_INPUT 0x00 /* left input control */
33#define AD1848_RIGHT_INPUT 0x01 /* right input control */
34#define AD1848_AUX1_LEFT_INPUT 0x02 /* left AUX1 input control */
35#define AD1848_AUX1_RIGHT_INPUT 0x03 /* right AUX1 input control */
36#define AD1848_AUX2_LEFT_INPUT 0x04 /* left AUX2 input control */
37#define AD1848_AUX2_RIGHT_INPUT 0x05 /* right AUX2 input control */
38#define AD1848_LEFT_OUTPUT 0x06 /* left output control register */
39#define AD1848_RIGHT_OUTPUT 0x07 /* right output control register */
40#define AD1848_DATA_FORMAT 0x08 /* clock and data format - playback/capture - bits 7-0 MCE */
41#define AD1848_IFACE_CTRL 0x09 /* interface control - bits 7-2 MCE */
42#define AD1848_PIN_CTRL 0x0a /* pin control */
43#define AD1848_TEST_INIT 0x0b /* test and initialization */
44#define AD1848_MISC_INFO 0x0c /* miscellaneous information */
45#define AD1848_LOOPBACK 0x0d /* loopback control */
46#define AD1848_DATA_UPR_CNT 0x0e /* playback/capture upper base count */
47#define AD1848_DATA_LWR_CNT 0x0f /* playback/capture lower base count */
48
49/* definitions for codec register select port - CODECP( REGSEL ) */
50
51#define AD1848_INIT 0x80 /* CODEC is initializing */
52#define AD1848_MCE 0x40 /* mode change enable */
53#define AD1848_TRD 0x20 /* transfer request disable */
54
55/* definitions for codec status register - CODECP( STATUS ) */
56
57#define AD1848_GLOBALIRQ 0x01 /* IRQ is active */
58
59/* definitions for AD1848_LEFT_INPUT and AD1848_RIGHT_INPUT registers */
60
61#define AD1848_ENABLE_MIC_GAIN 0x20
62
63#define AD1848_MIXS_LINE1 0x00
64#define AD1848_MIXS_AUX1 0x40
65#define AD1848_MIXS_LINE2 0x80
66#define AD1848_MIXS_ALL 0xc0
67
68/* definitions for clock and data format register - AD1848_PLAYBK_FORMAT */
69
70#define AD1848_LINEAR_8 0x00 /* 8-bit unsigned data */
71#define AD1848_ALAW_8 0x60 /* 8-bit A-law companded */
72#define AD1848_ULAW_8 0x20 /* 8-bit U-law companded */
73#define AD1848_LINEAR_16 0x40 /* 16-bit twos complement data - little endian */
74#define AD1848_STEREO 0x10 /* stereo mode */
75/* bits 3-1 define frequency divisor */
76#define AD1848_XTAL1 0x00 /* 24.576 crystal */
77#define AD1848_XTAL2 0x01 /* 16.9344 crystal */
78
79/* definitions for interface control register - AD1848_IFACE_CTRL */
80
81#define AD1848_CAPTURE_PIO 0x80 /* capture PIO enable */
82#define AD1848_PLAYBACK_PIO 0x40 /* playback PIO enable */
83#define AD1848_CALIB_MODE 0x18 /* calibration mode bits */
84#define AD1848_AUTOCALIB 0x08 /* auto calibrate */
85#define AD1848_SINGLE_DMA 0x04 /* use single DMA channel */
86#define AD1848_CAPTURE_ENABLE 0x02 /* capture enable */
87#define AD1848_PLAYBACK_ENABLE 0x01 /* playback enable */
88
89/* definitions for pin control register - AD1848_PIN_CTRL */
90
91#define AD1848_IRQ_ENABLE 0x02 /* enable IRQ */
92#define AD1848_XCTL1 0x40 /* external control #1 */
93#define AD1848_XCTL0 0x80 /* external control #0 */
94
95/* definitions for test and init register - AD1848_TEST_INIT */
96
97#define AD1848_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */
98#define AD1848_DMA_REQUEST 0x10 /* DMA request in progress */
99
100/* exported functions */
101
102void snd_ad1848_out(struct snd_wss *chip, unsigned char reg,
103 unsigned char value);
104
105int snd_ad1848_create(struct snd_card *card,
106 unsigned long port,
107 int irq, int dma,
108 unsigned short hardware,
109 struct snd_wss **chip);
110
111#endif /* __SOUND_AD1848_H */
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
7config SND_AD1848_LIB
8 tristate
9 select SND_PCM
10 select SND_WSS_LIB
11
12config SND_SB_COMMON 7config SND_SB_COMMON
13 tristate 8 tristate
14 9
@@ -56,7 +51,7 @@ config SND_AD1816A
56 51
57config SND_AD1848 52config 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
98config SND_CMI8330 93config 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
193config SND_SC6000 188config 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
374config SND_SGALAXY 369config 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
6snd-ad1848-lib-objs := ad1848_lib.o
7snd-ad1848-objs := ad1848.o 6snd-ad1848-objs := ad1848.o
8 7
9# Toplevel Module Dependency 8# Toplevel Module Dependency
10obj-$(CONFIG_SND_AD1848) += snd-ad1848.o 9obj-$(CONFIG_SND_AD1848) += snd-ad1848.o
11obj-$(CONFIG_SND_AD1848_LIB) += snd-ad1848-lib.o
12 10
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 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
37MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
38MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248");
39MODULE_LICENSE("GPL");
40
41#if 0
42#define SNDRV_DEBUG_MCE
43#endif
44
45/*
46 * Some variables
47 */
48
49static unsigned char 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
73static 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
84void 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
101EXPORT_SYMBOL(snd_ad1848_out);
102
103static 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
118static 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
146static 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
167static 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
227static 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
243static 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
264static 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
271static 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
291static 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
381static 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
394static 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
400int 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
471EXPORT_SYMBOL(snd_ad1848_create);
472
473/*
474 * INIT part
475 */
476
477static int __init alsa_ad1848_init(void)
478{
479 return 0;
480}
481
482static void __exit alsa_ad1848_exit(void)
483{
484}
485
486module_init(alsa_ad1848_init)
487module_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,
180WSS_SINGLE("Loud Playback Switch", 0, 180WSS_SINGLE("Loud Playback Switch", 0,
181 CMI8330_MUTEMUX, 6, 1, 1), 181 CMI8330_MUTEMUX, 6, 1, 1),
182WSS_DOUBLE("PCM Playback Switch", 0, 182WSS_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),
184WSS_DOUBLE("PCM Playback Volume", 0, 184WSS_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),
186WSS_DOUBLE("Line Playback Switch", 0, 186WSS_DOUBLE("Line Playback Switch", 0,
187 CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0), 187 CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0),
188WSS_DOUBLE("Line Playback Volume", 0, 188WSS_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
1140static int snd_wss_probe(struct snd_wss *chip) 1148static 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
1223static 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;