aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2008-07-31 15:10:47 -0400
committerJaroslav Kysela <perex@perex.cz>2008-08-06 09:40:02 -0400
commit760fc6b838d8c783c363e8bdb3714bd92a8945c4 (patch)
treebe50fd4d3e3c3d561d62a369066f9ea62d348fbc
parentead893c0deeec165524cc8a06e7e739d7d84b4c4 (diff)
ALSA: wss_lib: use wss detection code instead of ad1848 one
Use the wss detection code and kill the ad1848 library. The library is fully assimilated into the new wss library. This required reworking of the AD1848 family code so the code is changed to correctly detect chips from the AD1848 and CS4231 families. I have tested it on following cards: Gallant SC-6600 (codec: AD1848, driver: snd-sc6600) SoundScape VIVO/90 (codec: AD1845, driver: snd-sscape) SG Waverider (codec: CS4231A, driver: Rene Herman's snd-galaxy) Opti930 (codec: built-in - CS4231 compatible, driver: snd-opti93x) Opti931 (codec: built-in - CS4231 compatible, driver: snd-opti93x) Gallant SC-70P (chip/codec: CS4237B, driver: snd-cs4236) Audio Plus 3D (chip/codec: CMI8330A, driver: snd-cmi8330) Dell Latitude CP (chip/codec: cs4236, driver snd-cs4232) Sound playback and recording works on all these cards. Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Reviewed-by: Rene Herman <rene.herman@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-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;