1 | /*
|
---|
2 | * Driver for AMD InterWave soundcard
|
---|
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
|
---|
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
19 | *
|
---|
20 | * 1999/07/22 Erik Inge Bolso <knan@mo.himolde.no>
|
---|
21 | * * mixer group handlers
|
---|
22 | *
|
---|
23 | */
|
---|
24 |
|
---|
25 | #define SNDRV_MAIN_OBJECT_FILE
|
---|
26 | #include <sound/driver.h>
|
---|
27 | #include <sound/gus.h>
|
---|
28 | #include <sound/cs4231.h>
|
---|
29 | #ifdef SNDRV_STB
|
---|
30 | #include <sound/tea6330t.h>
|
---|
31 | #endif
|
---|
32 | #define SNDRV_LEGACY_AUTO_PROBE
|
---|
33 | #define SNDRV_LEGACY_FIND_FREE_IRQ
|
---|
34 | #define SNDRV_LEGACY_FIND_FREE_DMA
|
---|
35 | #define SNDRV_GET_ID
|
---|
36 | #include <sound/initval.h>
|
---|
37 |
|
---|
38 | EXPORT_NO_SYMBOLS;
|
---|
39 | #ifndef SNDRV_STB
|
---|
40 | MODULE_DESCRIPTION("AMD InterWave");
|
---|
41 | MODULE_CLASSES("{sound}");
|
---|
42 | MODULE_DEVICES("{{Gravis,UltraSound Plug & Play},"
|
---|
43 | "{STB,SoundRage32},"
|
---|
44 | "{MED,MED3210},"
|
---|
45 | "{Dynasonix,Dynasonix Pro},"
|
---|
46 | "{Panasonic,PCA761AW}}");
|
---|
47 | #else
|
---|
48 | MODULE_DESCRIPTION("AMD InterWave STB with TEA6330T");
|
---|
49 | MODULE_CLASSES("{sound}");
|
---|
50 | MODULE_DEVICES("{{AMD,InterWave STB with TEA6330T}}");
|
---|
51 | #endif
|
---|
52 |
|
---|
53 | static int snd_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
|
---|
54 | static char *snd_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
|
---|
55 | static int snd_enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
|
---|
56 | #ifdef __ISAPNP__
|
---|
57 | #ifdef TARGET_OS2
|
---|
58 | static int snd_isapnp[SNDRV_CARDS] = {1,1,1,1,1,1,1,1};
|
---|
59 | #else
|
---|
60 | static int snd_isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
|
---|
61 | #endif
|
---|
62 | #endif
|
---|
63 | static long snd_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x210,0x220,0x230,0x240,0x250,0x260 */
|
---|
64 | #ifdef SNDRV_STB
|
---|
65 | static long snd_port_tc[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x350,0x360,0x370,0x380 */
|
---|
66 | #endif
|
---|
67 | static int snd_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,3,5,9,11,12,15 */
|
---|
68 | static int snd_dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
|
---|
69 | static int snd_dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
|
---|
70 | #ifdef TARGET_OS2
|
---|
71 | static int snd_joystick_dac[SNDRV_CARDS] = {REPEAT_SNDRV(29)};
|
---|
72 | /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */
|
---|
73 | static int snd_midi[SNDRV_CARDS] = {REPEAT_SNDRV(0)};
|
---|
74 | static int snd_pcm_channels[SNDRV_CARDS] = {REPEAT_SNDRV(2)};
|
---|
75 | static int snd_effect[SNDRV_CARDS] = {REPEAT_SNDRV(0)};
|
---|
76 | #else
|
---|
77 | static int snd_joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29};
|
---|
78 | /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */
|
---|
79 | static int snd_midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
|
---|
80 | static int snd_pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
|
---|
81 | static int snd_effect[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
|
---|
82 | #endif
|
---|
83 |
|
---|
84 | MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
|
---|
85 | MODULE_PARM_DESC(snd_index, "Index value for InterWave soundcard.");
|
---|
86 | MODULE_PARM_SYNTAX(snd_index, SNDRV_INDEX_DESC);
|
---|
87 | MODULE_PARM(snd_id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
|
---|
88 | MODULE_PARM_DESC(snd_id, "ID string for InterWave soundcard.");
|
---|
89 | MODULE_PARM_SYNTAX(snd_id, SNDRV_ID_DESC);
|
---|
90 | MODULE_PARM(snd_enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
|
---|
91 | MODULE_PARM_DESC(snd_enable, "Enable InterWave soundcard.");
|
---|
92 | MODULE_PARM_SYNTAX(snd_enable, SNDRV_ENABLE_DESC);
|
---|
93 | MODULE_PARM(snd_isapnp, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
|
---|
94 | MODULE_PARM_DESC(snd_isapnp, "ISA PnP detection for specified soundcard.");
|
---|
95 | MODULE_PARM_SYNTAX(snd_isapnp, SNDRV_ISAPNP_DESC);
|
---|
96 | MODULE_PARM(snd_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
|
---|
97 | MODULE_PARM_DESC(snd_port, "Port # for InterWave driver.");
|
---|
98 | MODULE_PARM_SYNTAX(snd_port, SNDRV_ENABLED ",allows:{{0x210,0x260,0x10}},dialog:list");
|
---|
99 | #ifdef SNDRV_STB
|
---|
100 | MODULE_PARM(snd_port_tc, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
|
---|
101 | MODULE_PARM_DESC(snd_port_tc, "Tone control (TEA6330T - i2c bus) port # for InterWave driver.");
|
---|
102 | MODULE_PARM_SYNTAX(snd_port_tc, SNDRV_ENABLED ",allows:{{0x350,0x380,0x10}},dialog:list");
|
---|
103 | #endif
|
---|
104 | MODULE_PARM(snd_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
|
---|
105 | MODULE_PARM_DESC(snd_irq, "IRQ # for InterWave driver.");
|
---|
106 | MODULE_PARM_SYNTAX(snd_irq, SNDRV_ENABLED ",allows:{{3},{5},{9},{11},{12},{15}},dialog:list");
|
---|
107 | MODULE_PARM(snd_dma1, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
|
---|
108 | MODULE_PARM_DESC(snd_dma1, "DMA1 # for InterWave driver.");
|
---|
109 | MODULE_PARM_SYNTAX(snd_dma1, SNDRV_DMA_DESC);
|
---|
110 | MODULE_PARM(snd_dma2, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
|
---|
111 | MODULE_PARM_DESC(snd_dma2, "DMA2 # for InterWave driver.");
|
---|
112 | MODULE_PARM_SYNTAX(snd_dma2, SNDRV_DMA_DESC);
|
---|
113 | MODULE_PARM(snd_joystick_dac, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
|
---|
114 | MODULE_PARM_DESC(snd_joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for InterWave driver.");
|
---|
115 | MODULE_PARM_SYNTAX(snd_joystic_dac, SNDRV_ENABLED ",allows:{{0,31}}");
|
---|
116 | MODULE_PARM(snd_midi, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
|
---|
117 | MODULE_PARM_DESC(snd_midi, "MIDI UART enable for InterWave driver.");
|
---|
118 | MODULE_PARM_SYNTAX(snd_midi, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
|
---|
119 | MODULE_PARM(snd_pcm_channels, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
|
---|
120 | MODULE_PARM_DESC(snd_pcm_channels, "Reserved PCM channels for InterWave driver.");
|
---|
121 | MODULE_PARM_SYNTAX(snd_pcm_channels, SNDRV_ENABLED ",allows:{{2,16}}");
|
---|
122 | MODULE_PARM(snd_effect, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
|
---|
123 | MODULE_PARM_DESC(snd_effect, "Effects enable for InterWave driver.");
|
---|
124 | MODULE_PARM_SYNTAX(snd_effect, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
|
---|
125 |
|
---|
126 | struct snd_interwave {
|
---|
127 | int irq;
|
---|
128 | snd_card_t *card;
|
---|
129 | snd_gus_card_t *gus;
|
---|
130 | cs4231_t *cs4231;
|
---|
131 | #ifdef SNDRV_STB
|
---|
132 | struct resource *i2c_res;
|
---|
133 | #endif
|
---|
134 | unsigned short gus_status_reg;
|
---|
135 | unsigned short pcm_status_reg;
|
---|
136 | #ifdef __ISAPNP__
|
---|
137 | struct isapnp_dev *dev;
|
---|
138 | #ifdef SNDRV_STB
|
---|
139 | struct isapnp_dev *devtc;
|
---|
140 | #endif
|
---|
141 | #endif
|
---|
142 | };
|
---|
143 |
|
---|
144 | static snd_card_t *snd_interwave_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
|
---|
145 |
|
---|
146 | #ifdef __ISAPNP__
|
---|
147 |
|
---|
148 | static struct isapnp_card *snd_interwave_isapnp_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
|
---|
149 | static const struct isapnp_card_id *snd_interwave_isapnp_id[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
|
---|
150 |
|
---|
151 | #ifdef TARGET_OS2
|
---|
152 | #define ISAPNP_INTERWAVE(_va, _vb, _vc, _device, _audio) \
|
---|
153 | { \
|
---|
154 | 0, ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
|
---|
155 | { ISAPNP_DEVICE_ID(_va, _vb, _vc, _audio)} \
|
---|
156 | }
|
---|
157 | #define ISAPNP_INTERWAVE_STB(_va, _vb, _vc, _device, _audio, _tone) \
|
---|
158 | { \
|
---|
159 | 0, ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
|
---|
160 | { ISAPNP_DEVICE_ID(_va, _vb, _vc, _audio), \
|
---|
161 | ISAPNP_DEVICE_ID(_va, _vb, _vc, _tone) }\
|
---|
162 | }
|
---|
163 | #else
|
---|
164 | #define ISAPNP_INTERWAVE(_va, _vb, _vc, _device, _audio) \
|
---|
165 | { \
|
---|
166 | ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
|
---|
167 | devs : { ISAPNP_DEVICE_ID(_va, _vb, _vc, _audio), } \
|
---|
168 | }
|
---|
169 | #define ISAPNP_INTERWAVE_STB(_va, _vb, _vc, _device, _audio, _tone) \
|
---|
170 | { \
|
---|
171 | ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
|
---|
172 | devs : { ISAPNP_DEVICE_ID(_va, _vb, _vc, _audio), \
|
---|
173 | ISAPNP_DEVICE_ID(_va, _vb, _vc, _tone), } \
|
---|
174 | }
|
---|
175 | #endif
|
---|
176 |
|
---|
177 | static struct isapnp_card_id snd_interwave_pnpids[] __devinitdata = {
|
---|
178 | #ifndef SNDRV_STB
|
---|
179 | /* Gravis UltraSound Plug & Play */
|
---|
180 | ISAPNP_INTERWAVE('G','R','V',0x0001,0x0000),
|
---|
181 | /* STB SoundRage32 */
|
---|
182 | ISAPNP_INTERWAVE('S','T','B',0x011a,0x0010),
|
---|
183 | /* MED3210 */
|
---|
184 | ISAPNP_INTERWAVE('D','X','P',0x3201,0x0010),
|
---|
185 | /* Dynasonic Pro */
|
---|
186 | /* This device also have CDC1117:DynaSonix Pro Audio Effects Processor */
|
---|
187 | ISAPNP_INTERWAVE('C','D','C',0x1111,0x1112),
|
---|
188 | /* Panasonic PCA761AW Audio Card */
|
---|
189 | ISAPNP_INTERWAVE('A','D','V',0x55ff,0x0010),
|
---|
190 | #else
|
---|
191 | /* InterWave STB with TEA6330T */
|
---|
192 | ISAPNP_INTERWAVE_STB('A','D','V',0x550a,0x0010,0x0015),
|
---|
193 | #endif
|
---|
194 | { ISAPNP_CARD_END, }
|
---|
195 | };
|
---|
196 |
|
---|
197 | ISAPNP_CARD_TABLE(snd_interwave_pnpids);
|
---|
198 |
|
---|
199 | #endif /* __ISAPNP__ */
|
---|
200 |
|
---|
201 |
|
---|
202 | #ifdef SNDRV_STB
|
---|
203 | static void snd_interwave_i2c_setlines(snd_i2c_bus_t *bus, int ctrl, int data)
|
---|
204 | {
|
---|
205 | unsigned long port = bus->private_value;
|
---|
206 |
|
---|
207 | #if 0
|
---|
208 | printk("i2c_setlines - 0x%lx <- %i,%i\n", port, ctrl, data);
|
---|
209 | #endif
|
---|
210 | outb((data << 1) | ctrl, port);
|
---|
211 | udelay(10);
|
---|
212 | }
|
---|
213 |
|
---|
214 | static int snd_interwave_i2c_getdataline(snd_i2c_bus_t *bus)
|
---|
215 | {
|
---|
216 | unsigned long port = bus->private_value;
|
---|
217 | unsigned char res;
|
---|
218 |
|
---|
219 | res = (inb(port) & 2) >> 1;
|
---|
220 | #if 0
|
---|
221 | printk("i2c_getdataline - 0x%lx -> %i\n", port, res);
|
---|
222 | #endif
|
---|
223 | return res;
|
---|
224 | }
|
---|
225 |
|
---|
226 | static int __init snd_interwave_detect_stb(struct snd_interwave *iwcard,
|
---|
227 | snd_gus_card_t * gus, int dev,
|
---|
228 | snd_i2c_bus_t **rbus)
|
---|
229 | {
|
---|
230 | unsigned long port;
|
---|
231 | snd_i2c_bus_t *bus;
|
---|
232 | snd_card_t *card = iwcard->card;
|
---|
233 | unsigned long flags;
|
---|
234 | char name[32];
|
---|
235 | int err;
|
---|
236 |
|
---|
237 | *rbus = NULL;
|
---|
238 | port = snd_port_tc[dev];
|
---|
239 | if (port == SNDRV_AUTO_PORT) {
|
---|
240 | port = 0x350;
|
---|
241 | if (gus->gf1.port == 0x250) {
|
---|
242 | port = 0x360;
|
---|
243 | }
|
---|
244 | while (port <= 0x380) {
|
---|
245 | if ((iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)")) != NULL)
|
---|
246 | break;
|
---|
247 | port += 0x10;
|
---|
248 | }
|
---|
249 | if (port > 0x380)
|
---|
250 | return -ENODEV;
|
---|
251 | } else {
|
---|
252 | if ((iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)")) != NULL)
|
---|
253 | return -ENODEV;
|
---|
254 | }
|
---|
255 | sprintf(name, "InterWave-%i", card->number);
|
---|
256 | if ((err = snd_i2c_bus_create(card, name, &bus)) < 0)
|
---|
257 | return err;
|
---|
258 | bus->private_value = port;
|
---|
259 | bus->i2c_setlines = snd_interwave_i2c_setlines;
|
---|
260 | bus->i2c_getdataline = snd_interwave_i2c_getdataline;
|
---|
261 | SNDRV_LOCK_I2C_BUS(bus);
|
---|
262 | snd_i2c_reset(bus);
|
---|
263 | #if 0
|
---|
264 | {
|
---|
265 | int idx, ack;
|
---|
266 | for (idx = 0; idx < 256; idx += 2) {
|
---|
267 | snd_i2c_start(bus);
|
---|
268 | ack = snd_i2c_sendbyte(bus, idx, 0);
|
---|
269 | snd_i2c_stop(bus);
|
---|
270 | if (!ack) {
|
---|
271 | printk("i2c: scanning bus %s: found device at addr=0x%x\n",
|
---|
272 | bus->name, idx);
|
---|
273 | }
|
---|
274 | }
|
---|
275 | }
|
---|
276 | #endif
|
---|
277 | SNDRV_UNLOCK_I2C_BUS(bus);
|
---|
278 | if ((err = snd_tea6330t_detect(bus, 0)) < 0)
|
---|
279 | return err;
|
---|
280 | *rbus = bus;
|
---|
281 | return 0;
|
---|
282 | }
|
---|
283 | #endif
|
---|
284 |
|
---|
285 | static int __init snd_interwave_detect(struct snd_interwave *iwcard,
|
---|
286 | snd_gus_card_t * gus,
|
---|
287 | int dev
|
---|
288 | #ifdef SNDRV_STB
|
---|
289 | , snd_i2c_bus_t **rbus
|
---|
290 | #endif
|
---|
291 | )
|
---|
292 | {
|
---|
293 | unsigned long flags;
|
---|
294 | unsigned char rev1, rev2;
|
---|
295 |
|
---|
296 | snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
|
---|
297 | #ifdef CONFIG_SND_DEBUG_DETECT
|
---|
298 | {
|
---|
299 | int d;
|
---|
300 |
|
---|
301 | if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
|
---|
302 | snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
|
---|
303 | return -ENODEV;
|
---|
304 | }
|
---|
305 | }
|
---|
306 | #else
|
---|
307 | if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
|
---|
308 | return -ENODEV;
|
---|
309 | #endif
|
---|
310 | udelay(160);
|
---|
311 | snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */
|
---|
312 | udelay(160);
|
---|
313 | #ifdef CONFIG_SND_DEBUG_DETECT
|
---|
314 | {
|
---|
315 | int d;
|
---|
316 |
|
---|
317 | if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
|
---|
318 | snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
|
---|
319 | return -ENODEV;
|
---|
320 | }
|
---|
321 | }
|
---|
322 | #else
|
---|
323 | if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
|
---|
324 | return -ENODEV;
|
---|
325 | #endif
|
---|
326 |
|
---|
327 | spin_lock_irqsave(&gus->reg_lock, flags);
|
---|
328 | rev1 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER);
|
---|
329 | snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, ~rev1);
|
---|
330 | rev2 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER);
|
---|
331 | snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, rev1);
|
---|
332 | spin_unlock_irqrestore(&gus->reg_lock, flags);
|
---|
333 | snd_printdd("[0x%lx] InterWave check - rev1=0x%x, rev2=0x%x\n", gus->gf1.port, rev1, rev2);
|
---|
334 | if ((rev1 & 0xf0) == (rev2 & 0xf0) &&
|
---|
335 | (rev1 & 0x0f) != (rev2 & 0x0f)) {
|
---|
336 | snd_printdd("[0x%lx] InterWave check - passed\n", gus->gf1.port);
|
---|
337 | gus->interwave = 1;
|
---|
338 | strcpy(gus->card->shortname, "AMD InterWave");
|
---|
339 | gus->revision = rev1 >> 4;
|
---|
340 | #ifndef SNDRV_STB
|
---|
341 | return 0; /* ok.. We have an InterWave board */
|
---|
342 | #else
|
---|
343 | return snd_interwave_detect_stb(iwcard, gus, dev, rbus);
|
---|
344 | #endif
|
---|
345 | }
|
---|
346 | snd_printdd("[0x%lx] InterWave check - failed\n", gus->gf1.port);
|
---|
347 | return -ENODEV;
|
---|
348 | }
|
---|
349 |
|
---|
350 | static void snd_interwave_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
---|
351 | {
|
---|
352 | struct snd_interwave *iwcard = (struct snd_interwave *) dev_id;
|
---|
353 | int loop, max = 5;
|
---|
354 |
|
---|
355 | do {
|
---|
356 | loop = 0;
|
---|
357 | if (inb(iwcard->gus_status_reg)) {
|
---|
358 | snd_gus_interrupt(irq, iwcard->gus, regs);
|
---|
359 | loop++;
|
---|
360 | }
|
---|
361 | if (inb(iwcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */
|
---|
362 | snd_cs4231_interrupt(irq, iwcard->cs4231, regs);
|
---|
363 | loop++;
|
---|
364 | }
|
---|
365 | } while (loop && --max > 0);
|
---|
366 | }
|
---|
367 |
|
---|
368 | static void __init snd_interwave_reset(snd_gus_card_t * gus)
|
---|
369 | {
|
---|
370 | snd_gf1_write8(gus, SNDRV_GF1_GB_RESET, 0x00);
|
---|
371 | udelay(160);
|
---|
372 | snd_gf1_write8(gus, SNDRV_GF1_GB_RESET, 0x01);
|
---|
373 | udelay(160);
|
---|
374 | }
|
---|
375 |
|
---|
376 | static void __init snd_interwave_bank_sizes(snd_gus_card_t * gus, int *sizes)
|
---|
377 | {
|
---|
378 | unsigned int idx;
|
---|
379 | unsigned int local;
|
---|
380 | unsigned char d;
|
---|
381 |
|
---|
382 | for (idx = 0; idx < 4; idx++) {
|
---|
383 | sizes[idx] = 0;
|
---|
384 | d = 0x55;
|
---|
385 | for (local = idx << 22;
|
---|
386 | local < (idx << 22) + 0x400000;
|
---|
387 | local += 0x40000, d++) {
|
---|
388 | snd_gf1_poke(gus, local, d);
|
---|
389 | snd_gf1_poke(gus, local + 1, d + 1);
|
---|
390 | #if 0
|
---|
391 | printk("d = 0x%x, local = 0x%x, local + 1 = 0x%x, idx << 22 = 0x%x\n",
|
---|
392 | d,
|
---|
393 | snd_gf1_peek(gus, local),
|
---|
394 | snd_gf1_peek(gus, local + 1),
|
---|
395 | snd_gf1_peek(gus, idx << 22));
|
---|
396 | #endif
|
---|
397 | if (snd_gf1_peek(gus, local) != d ||
|
---|
398 | snd_gf1_peek(gus, local + 1) != d + 1 ||
|
---|
399 | snd_gf1_peek(gus, idx << 22) != 0x55)
|
---|
400 | break;
|
---|
401 | sizes[idx]++;
|
---|
402 | }
|
---|
403 | }
|
---|
404 | #if 0
|
---|
405 | printk("sizes: %i %i %i %i\n", sizes[0], sizes[1], sizes[2], sizes[3]);
|
---|
406 | #endif
|
---|
407 | }
|
---|
408 |
|
---|
409 | struct rom_hdr {
|
---|
410 | /* 000 */ unsigned char iwave[8];
|
---|
411 | /* 008 */ unsigned char rom_hdr_revision;
|
---|
412 | /* 009 */ unsigned char series_number;
|
---|
413 | /* 010 */ unsigned char series_name[16];
|
---|
414 | /* 026 */ unsigned char date[10];
|
---|
415 | /* 036 */ unsigned short vendor_revision_major;
|
---|
416 | /* 038 */ unsigned short vendor_revision_minor;
|
---|
417 | /* 040 */ unsigned int rom_size;
|
---|
418 | /* 044 */ unsigned char copyright[128];
|
---|
419 | /* 172 */ unsigned char vendor_name[64];
|
---|
420 | /* 236 */ unsigned char rom_description[128];
|
---|
421 | /* 364 */ unsigned char pad[147];
|
---|
422 | /* 511 */ unsigned char csum;
|
---|
423 | };
|
---|
424 |
|
---|
425 | static void __init snd_interwave_detect_memory(snd_gus_card_t * gus)
|
---|
426 | {
|
---|
427 | static unsigned int lmc[13] =
|
---|
428 | {
|
---|
429 | 0x00000001, 0x00000101, 0x01010101, 0x00000401,
|
---|
430 | 0x04040401, 0x00040101, 0x04040101, 0x00000004,
|
---|
431 | 0x00000404, 0x04040404, 0x00000010, 0x00001010,
|
---|
432 | 0x10101010
|
---|
433 | };
|
---|
434 |
|
---|
435 | int bank_pos, pages;
|
---|
436 | unsigned int i, lmct;
|
---|
437 | int psizes[4];
|
---|
438 | unsigned char csum;
|
---|
439 | struct rom_hdr romh;
|
---|
440 |
|
---|
441 | snd_interwave_reset(gus);
|
---|
442 | snd_gf1_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_read8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01); /* enhanced mode */
|
---|
443 | snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); /* DRAM I/O cycles selected */
|
---|
444 | snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xff10) | 0x004c);
|
---|
445 | /* ok.. simple test of memory size */
|
---|
446 | pages = 0;
|
---|
447 | snd_gf1_poke(gus, 0, 0x55);
|
---|
448 | snd_gf1_poke(gus, 1, 0xaa);
|
---|
449 | #if 1
|
---|
450 | if (snd_gf1_peek(gus, 0) == 0x55 && snd_gf1_peek(gus, 1) == 0xaa)
|
---|
451 | #else
|
---|
452 | if (0) /* ok.. for testing of 0k RAM */
|
---|
453 | #endif
|
---|
454 | {
|
---|
455 | snd_interwave_bank_sizes(gus, psizes);
|
---|
456 | lmct = (psizes[3] << 24) | (psizes[2] << 16) |
|
---|
457 | (psizes[1] << 8) | psizes[0];
|
---|
458 | #if 0
|
---|
459 | printk("lmct = 0x%08x\n", lmct);
|
---|
460 | #endif
|
---|
461 | for (i = 0; i < sizeof(lmc) / sizeof(unsigned int); i++)
|
---|
462 | if (lmct == lmc[i]) {
|
---|
463 | #if 0
|
---|
464 | printk("found !!! %i\n", i);
|
---|
465 | #endif
|
---|
466 | snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | i);
|
---|
467 | snd_interwave_bank_sizes(gus, psizes);
|
---|
468 | break;
|
---|
469 | }
|
---|
470 | if (i >= sizeof(lmc) / sizeof(unsigned int) && !gus->gf1.enh_mode)
|
---|
471 | snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | 2);
|
---|
472 | for (i = 0; i < 4; i++) {
|
---|
473 | gus->gf1.mem_alloc.banks_8[i].address =
|
---|
474 | gus->gf1.mem_alloc.banks_16[i].address = i << 22;
|
---|
475 | gus->gf1.mem_alloc.banks_8[i].size =
|
---|
476 | gus->gf1.mem_alloc.banks_16[i].size = psizes[i] << 18;
|
---|
477 | pages += psizes[i];
|
---|
478 | }
|
---|
479 | }
|
---|
480 | pages <<= 18;
|
---|
481 | gus->gf1.memory = pages;
|
---|
482 |
|
---|
483 | snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x03); /* select ROM */
|
---|
484 | snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xff1f) | (4 << 5));
|
---|
485 | gus->gf1.rom_banks = 0;
|
---|
486 | gus->gf1.rom_memory = 0;
|
---|
487 | for (bank_pos = 0; bank_pos < 16L * 1024L * 1024L; bank_pos += 4L * 1024L * 1024L) {
|
---|
488 | for (i = 0; i < sizeof(struct rom_hdr); i++)
|
---|
489 | *(((unsigned char *) &romh) + i) = snd_gf1_peek(gus, i + bank_pos);
|
---|
490 | #ifdef CONFIG_SND_DEBUG_ROM
|
---|
491 | printk("ROM at 0x%06x = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", bank_pos,
|
---|
492 | romh.iwave[0], romh.iwave[1], romh.iwave[2], romh.iwave[3],
|
---|
493 | romh.iwave[4], romh.iwave[5], romh.iwave[6], romh.iwave[7]);
|
---|
494 | #endif
|
---|
495 | if (strncmp(romh.iwave, "INTRWAVE", 8))
|
---|
496 | continue; /* first check */
|
---|
497 | csum = 0;
|
---|
498 | for (i = 0; i < sizeof(struct rom_hdr) - 1; i++)
|
---|
499 | csum += *(((unsigned char *) &romh) + i);
|
---|
500 | #ifdef CONFIG_SND_DEBUG_ROM
|
---|
501 | printk("ROM checksum = 0x%x == 0x%x (computed)\n", romh.csum, (unsigned char) (256 - csum));
|
---|
502 | #endif
|
---|
503 | if (256 - csum != romh.csum)
|
---|
504 | continue; /* not valid rom */
|
---|
505 | gus->gf1.rom_banks++;
|
---|
506 | gus->gf1.rom_present |= 1 << (bank_pos >> 22);
|
---|
507 | #ifdef SNDRV_LITTLE_ENDIAN
|
---|
508 | gus->gf1.rom_memory = romh.rom_size;
|
---|
509 | #else
|
---|
510 | gus->gf1.rom_memory = ((romh.rom_size >> 24) & 0x000000ff) |
|
---|
511 | ((romh.rom_size >> 8) & 0x0000ff00) |
|
---|
512 | ((romh.rom_size << 8) & 0x00ff0000) |
|
---|
513 | ((romh.rom_size << 24) & 0xff000000);
|
---|
514 | #endif
|
---|
515 | }
|
---|
516 | #if 0
|
---|
517 | if (gus->gf1.rom_memory > 0) {
|
---|
518 | if (gus->gf1.rom_banks == 1 && gus->gf1.rom_present == 8)
|
---|
519 | gus->card->type = SNDRV_CARD_TYPE_IW_DYNASONIC;
|
---|
520 | }
|
---|
521 | #endif
|
---|
522 | snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x00); /* select RAM */
|
---|
523 |
|
---|
524 | if (!gus->gf1.enh_mode)
|
---|
525 | snd_interwave_reset(gus);
|
---|
526 | }
|
---|
527 |
|
---|
528 | static void __init snd_interwave_init(int dev, snd_gus_card_t * gus)
|
---|
529 | {
|
---|
530 | unsigned long flags;
|
---|
531 |
|
---|
532 | /* ok.. some InterWave specific initialization */
|
---|
533 | spin_lock_irqsave(&gus->reg_lock, flags);
|
---|
534 | snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, 0x00);
|
---|
535 | snd_gf1_write8(gus, SNDRV_GF1_GB_COMPATIBILITY, 0x1f);
|
---|
536 | snd_gf1_write8(gus, SNDRV_GF1_GB_DECODE_CONTROL, 0x49);
|
---|
537 | snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, 0x11);
|
---|
538 | snd_gf1_write8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A, 0x00);
|
---|
539 | snd_gf1_write8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B, 0x30);
|
---|
540 | snd_gf1_write8(gus, SNDRV_GF1_GB_EMULATION_IRQ, 0x00);
|
---|
541 | spin_unlock_irqrestore(&gus->reg_lock, flags);
|
---|
542 | gus->equal_irq = 1;
|
---|
543 | gus->codec_flag = 1;
|
---|
544 | gus->interwave = 1;
|
---|
545 | gus->max_flag = 1;
|
---|
546 | gus->joystick_dac = snd_joystick_dac[dev];
|
---|
547 |
|
---|
548 | }
|
---|
549 |
|
---|
550 | #define INTERWAVE_CONTROLS (sizeof(snd_interwave_controls)/sizeof(snd_kcontrol_new_t))
|
---|
551 |
|
---|
552 | static snd_kcontrol_new_t snd_interwave_controls[] = {
|
---|
553 | CS4231_DOUBLE("Master Playback Switch", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1),
|
---|
554 | CS4231_DOUBLE("Master Playback Volume", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1),
|
---|
555 | CS4231_DOUBLE("Mic Playback Switch", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1),
|
---|
556 | CS4231_DOUBLE("Mic Playback Volume", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1)
|
---|
557 | };
|
---|
558 |
|
---|
559 | static int __init snd_interwave_mixer(cs4231_t *chip)
|
---|
560 | {
|
---|
561 | snd_card_t *card = chip->card;
|
---|
562 | snd_ctl_elem_id_t id1, id2;
|
---|
563 | int idx, err;
|
---|
564 |
|
---|
565 | memset(&id1, 0, sizeof(id1));
|
---|
566 | memset(&id2, 0, sizeof(id2));
|
---|
567 | id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
---|
568 | #if 0
|
---|
569 | /* remove mono microphone controls */
|
---|
570 | strcpy(id1.name, "Mic Playback Switch");
|
---|
571 | if ((err = snd_ctl_remove_id(card, &id1)) < 0)
|
---|
572 | return err;
|
---|
573 | strcpy(id1.name, "Mic Playback Volume");
|
---|
574 | if ((err = snd_ctl_remove_id(card, &id1)) < 0)
|
---|
575 | return err;
|
---|
576 | #endif
|
---|
577 | /* add new master and mic controls */
|
---|
578 | for (idx = 0; idx < INTERWAVE_CONTROLS; idx++)
|
---|
579 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_interwave_controls[idx], chip))) < 0)
|
---|
580 | return err;
|
---|
581 | snd_cs4231_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f);
|
---|
582 | snd_cs4231_out(chip, CS4231_LINE_RIGHT_OUTPUT, 0x9f);
|
---|
583 | snd_cs4231_out(chip, CS4231_LEFT_MIC_INPUT, 0x9f);
|
---|
584 | snd_cs4231_out(chip, CS4231_RIGHT_MIC_INPUT, 0x9f);
|
---|
585 | /* reassign AUXA to SYNTHESIZER */
|
---|
586 | strcpy(id1.name, "Aux Playback Switch");
|
---|
587 | strcpy(id2.name, "Synth Playback Switch");
|
---|
588 | if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
|
---|
589 | return err;
|
---|
590 | strcpy(id1.name, "Aux Playback Volume");
|
---|
591 | strcpy(id2.name, "Synth Playback Volume");
|
---|
592 | if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
|
---|
593 | return err;
|
---|
594 | /* reassign AUXB to CD */
|
---|
595 | strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
|
---|
596 | strcpy(id2.name, "CD Playback Switch");
|
---|
597 | if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
|
---|
598 | return err;
|
---|
599 | strcpy(id1.name, "Aux Playback Volume");
|
---|
600 | strcpy(id2.name, "CD Playback Volume");
|
---|
601 | if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
|
---|
602 | return err;
|
---|
603 | return 0;
|
---|
604 | }
|
---|
605 |
|
---|
606 | #ifdef __ISAPNP__
|
---|
607 |
|
---|
608 | static int __init snd_interwave_isapnp(int dev, struct snd_interwave *iwcard)
|
---|
609 | {
|
---|
610 | const struct isapnp_card_id *id = snd_interwave_isapnp_id[dev];
|
---|
611 | struct isapnp_card *card = snd_interwave_isapnp_cards[dev];
|
---|
612 | struct isapnp_dev *pdev;
|
---|
613 |
|
---|
614 | iwcard->dev = isapnp_find_dev(card, id->devs[0].vendor, id->devs[0].function, NULL);
|
---|
615 | if (iwcard->dev->active) {
|
---|
616 | iwcard->dev = NULL;
|
---|
617 | return -EBUSY;
|
---|
618 | }
|
---|
619 | #ifdef SNDRV_STB
|
---|
620 | iwcard->devtc = isapnp_find_dev(card, id->devs[1].vendor, id->devs[1].function, NULL);
|
---|
621 | if (iwcard->devtc->active) {
|
---|
622 | iwcard->dev = iwcard->devtc = NULL;
|
---|
623 | return -EBUSY;
|
---|
624 | }
|
---|
625 | #endif
|
---|
626 | /* Synth & Codec initialization */
|
---|
627 | pdev = iwcard->dev;
|
---|
628 | if (pdev->prepare(pdev)<0)
|
---|
629 | return -EAGAIN;
|
---|
630 | if (snd_port[dev] != SNDRV_AUTO_PORT) {
|
---|
631 | isapnp_resource_change(&pdev->resource[0], snd_port[dev], 16);
|
---|
632 | isapnp_resource_change(&pdev->resource[1], snd_port[dev] + 0x100, 12);
|
---|
633 | isapnp_resource_change(&pdev->resource[2], snd_port[dev] + 0x10c, 4);
|
---|
634 | }
|
---|
635 | if (snd_dma1[dev] != SNDRV_AUTO_DMA)
|
---|
636 | isapnp_resource_change(&pdev->dma_resource[0], snd_dma1[dev], 1);
|
---|
637 | if (snd_dma2[dev] != SNDRV_AUTO_DMA)
|
---|
638 | isapnp_resource_change(&pdev->dma_resource[1], snd_dma2[dev], 1);
|
---|
639 | if (snd_dma2[dev] < 0)
|
---|
640 | isapnp_resource_change(&pdev->dma_resource[1], 4, 1);
|
---|
641 | if (snd_irq[dev] != SNDRV_AUTO_IRQ)
|
---|
642 | isapnp_resource_change(&pdev->irq_resource[0], snd_irq[dev], 1);
|
---|
643 | if (pdev->activate(pdev)<0) {
|
---|
644 | snd_printk("isapnp configure failure (out of resources?)\n");
|
---|
645 | return -EBUSY;
|
---|
646 | }
|
---|
647 | if (pdev->resource[0].start + 0x100 != pdev->resource[1].start ||
|
---|
648 | pdev->resource[0].start + 0x10c != pdev->resource[2].start) {
|
---|
649 | snd_printk("isapnp configure failure (wrong ports)\n");
|
---|
650 | pdev->deactivate(pdev);
|
---|
651 | return -ENOENT;
|
---|
652 | }
|
---|
653 | snd_port[dev] = pdev->resource[0].start;
|
---|
654 | snd_dma1[dev] = pdev->dma_resource[0].start;
|
---|
655 | if (snd_dma2[dev] >= 0)
|
---|
656 | snd_dma2[dev] = pdev->dma_resource[1].start;
|
---|
657 | snd_irq[dev] = pdev->irq_resource[0].start;
|
---|
658 | snd_printdd("isapnp IW: sb port=0x%lx, gf1 port=0x%lx, codec port=0x%lx\n",
|
---|
659 | pdev->resource[0].start,
|
---|
660 | pdev->resource[1].start,
|
---|
661 | pdev->resource[2].start);
|
---|
662 | snd_printdd("isapnp IW: dma1=%i, dma2=%i, irq=%i\n", snd_dma1[dev], snd_dma2[dev], snd_irq[dev]);
|
---|
663 | #ifdef SNDRV_STB
|
---|
664 | /* Tone Control initialization */
|
---|
665 | pdev = iwcard->devtc;
|
---|
666 | if (pdev->prepare(pdev)<0) {
|
---|
667 | iwcard->dev->deactivate(iwcard->dev);
|
---|
668 | return -EAGAIN;
|
---|
669 | }
|
---|
670 | if (snd_port_tc[dev] != SNDRV_AUTO_PORT)
|
---|
671 | isapnp_resource_change(&pdev->resource[0], snd_port_tc[dev], 1);
|
---|
672 | if (pdev->activate(pdev)<0) {
|
---|
673 | snd_printk("Tone Control isapnp configure failure (out of resources?)\n");
|
---|
674 | iwcard->dev->deactivate(iwcard->dev);
|
---|
675 | return -EBUSY;
|
---|
676 | }
|
---|
677 | snd_port_tc[dev] = pdev->resource[0].start;
|
---|
678 | snd_printdd("isapnp IW: tone control port=0x%lx\n", snd_port_tc[dev]);
|
---|
679 | #endif
|
---|
680 | return 0;
|
---|
681 | }
|
---|
682 |
|
---|
683 | static void snd_interwave_deactivate(struct snd_interwave *iwcard)
|
---|
684 | {
|
---|
685 | if (iwcard->dev) {
|
---|
686 | iwcard->dev->deactivate(iwcard->dev);
|
---|
687 | iwcard->dev = NULL;
|
---|
688 | }
|
---|
689 | #ifdef SNDRV_STB
|
---|
690 | if (iwcard->devtc) {
|
---|
691 | iwcard->devtc->deactivate(iwcard->devtc);
|
---|
692 | iwcard->devtc = NULL;
|
---|
693 | }
|
---|
694 | #endif
|
---|
695 | }
|
---|
696 |
|
---|
697 | #endif /* __ISAPNP__ */
|
---|
698 |
|
---|
699 | static void snd_interwave_free(snd_card_t *card)
|
---|
700 | {
|
---|
701 | struct snd_interwave *iwcard = (struct snd_interwave *)card->private_data;
|
---|
702 |
|
---|
703 | if (iwcard == NULL)
|
---|
704 | return;
|
---|
705 | #ifdef __ISAPNP__
|
---|
706 | snd_interwave_deactivate(iwcard);
|
---|
707 | #endif
|
---|
708 | #ifdef SNDRV_STB
|
---|
709 | if (iwcard->i2c_res)
|
---|
710 | release_resource(iwcard->i2c_res);
|
---|
711 | #endif
|
---|
712 | if (iwcard->irq >= 0)
|
---|
713 | free_irq(iwcard->irq, (void *)iwcard);
|
---|
714 | }
|
---|
715 |
|
---|
716 | static int __init snd_interwave_probe(int dev)
|
---|
717 | {
|
---|
718 | static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
|
---|
719 | static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1};
|
---|
720 | int irq, dma1, dma2;
|
---|
721 | snd_card_t *card;
|
---|
722 | struct snd_interwave *iwcard;
|
---|
723 | cs4231_t *cs4231;
|
---|
724 | snd_gus_card_t *gus;
|
---|
725 | #ifdef SNDRV_STB
|
---|
726 | snd_i2c_bus_t *i2c_bus;
|
---|
727 | #endif
|
---|
728 | snd_pcm_t *pcm;
|
---|
729 | char *str;
|
---|
730 | int err;
|
---|
731 |
|
---|
732 | card = snd_card_new(snd_index[dev], snd_id[dev], THIS_MODULE,
|
---|
733 | sizeof(struct snd_interwave));
|
---|
734 | if (card == NULL)
|
---|
735 | return -ENOMEM;
|
---|
736 | iwcard = (struct snd_interwave *)card->private_data;
|
---|
737 | iwcard->card = card;
|
---|
738 | iwcard->irq = -1;
|
---|
739 | card->private_free = snd_interwave_free;
|
---|
740 | #ifdef __ISAPNP__
|
---|
741 | if (snd_isapnp[dev] && snd_interwave_isapnp(dev, iwcard)) {
|
---|
742 | snd_card_free(card);
|
---|
743 | return -ENODEV;
|
---|
744 | }
|
---|
745 | #endif
|
---|
746 | irq = snd_irq[dev];
|
---|
747 | if (irq == SNDRV_AUTO_IRQ) {
|
---|
748 | if ((irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
|
---|
749 | snd_card_free(card);
|
---|
750 | snd_printk("unable to find a free IRQ\n");
|
---|
751 | return -EBUSY;
|
---|
752 | }
|
---|
753 | }
|
---|
754 | dma1 = snd_dma1[dev];
|
---|
755 | if (dma1 == SNDRV_AUTO_DMA) {
|
---|
756 | if ((dma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
|
---|
757 | snd_card_free(card);
|
---|
758 | snd_printk("unable to find a free DMA1\n");
|
---|
759 | return -EBUSY;
|
---|
760 | }
|
---|
761 | }
|
---|
762 | dma2 = snd_dma2[dev];
|
---|
763 | if (dma2 == SNDRV_AUTO_DMA) {
|
---|
764 | if ((dma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
|
---|
765 | snd_card_free(card);
|
---|
766 | snd_printk("unable to find a free DMA2\n");
|
---|
767 | return -EBUSY;
|
---|
768 | }
|
---|
769 | }
|
---|
770 |
|
---|
771 | if ((err = snd_gus_create(card,
|
---|
772 | snd_port[dev],
|
---|
773 | -irq, dma1, dma2,
|
---|
774 | 0, 32,
|
---|
775 | snd_pcm_channels[dev], snd_effect[dev], &gus)) < 0) {
|
---|
776 | snd_card_free(card);
|
---|
777 | return err;
|
---|
778 | }
|
---|
779 | if ((err = snd_interwave_detect(iwcard, gus, dev
|
---|
780 | #ifdef SNDRV_STB
|
---|
781 | , &i2c_bus
|
---|
782 | #endif
|
---|
783 | )) < 0) {
|
---|
784 | snd_card_free(card);
|
---|
785 | return err;
|
---|
786 | }
|
---|
787 | iwcard->gus_status_reg = gus->gf1.reg_irqstat;
|
---|
788 | iwcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;
|
---|
789 |
|
---|
790 | snd_interwave_init(dev, gus);
|
---|
791 | snd_interwave_detect_memory(gus);
|
---|
792 | if ((err = snd_gus_initialize(gus)) < 0) {
|
---|
793 | snd_card_free(card);
|
---|
794 | return err;
|
---|
795 | }
|
---|
796 |
|
---|
797 | if (request_irq(irq, snd_interwave_interrupt, SA_INTERRUPT, "InterWave", (void *)iwcard)) {
|
---|
798 | snd_card_free(card);
|
---|
799 | snd_printk("unable to grab IRQ %d\n", irq);
|
---|
800 | return -EBUSY;
|
---|
801 | }
|
---|
802 | iwcard->irq = irq;
|
---|
803 |
|
---|
804 | if ((err = snd_cs4231_create(card,
|
---|
805 | gus->gf1.port + 0x10c, -1, irq,
|
---|
806 | dma2 < 0 ? dma1 : dma2, dma1,
|
---|
807 | CS4231_HW_INTERWAVE,
|
---|
808 | CS4231_HWSHARE_IRQ |
|
---|
809 | CS4231_HWSHARE_DMA1 |
|
---|
810 | CS4231_HWSHARE_DMA2,
|
---|
811 | &cs4231)) < 0) {
|
---|
812 | snd_card_free(card);
|
---|
813 | return err;
|
---|
814 | }
|
---|
815 | if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0) {
|
---|
816 | snd_card_free(card);
|
---|
817 | return err;
|
---|
818 | }
|
---|
819 | sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A');
|
---|
820 | strcat(pcm->name, " (chip)");
|
---|
821 | if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) {
|
---|
822 | snd_card_free(card);
|
---|
823 | return err;
|
---|
824 | }
|
---|
825 | if ((err = snd_cs4231_mixer(cs4231)) < 0) {
|
---|
826 | snd_card_free(card);
|
---|
827 | return err;
|
---|
828 | }
|
---|
829 | if (snd_pcm_channels[dev] > 0) {
|
---|
830 | if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) {
|
---|
831 | snd_card_free(card);
|
---|
832 | return err;
|
---|
833 | }
|
---|
834 | }
|
---|
835 | if ((err = snd_interwave_mixer(cs4231)) < 0) {
|
---|
836 | snd_card_free(card);
|
---|
837 | return err;
|
---|
838 | }
|
---|
839 | #ifdef SNDRV_STB
|
---|
840 | {
|
---|
841 | snd_ctl_elem_id_t id1, id2;
|
---|
842 | memset(&id1, 0, sizeof(id1));
|
---|
843 | memset(&id2, 0, sizeof(id2));
|
---|
844 | id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
---|
845 | strcpy(id1.name, "Master Playback Switch");
|
---|
846 | strcpy(id2.name, id1.name);
|
---|
847 | id2.index = 1;
|
---|
848 | if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
|
---|
849 | snd_card_free(card);
|
---|
850 | return err;
|
---|
851 | }
|
---|
852 | strcpy(id1.name, "Master Playback Volume");
|
---|
853 | strcpy(id2.name, id1.name);
|
---|
854 | if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
|
---|
855 | snd_card_free(card);
|
---|
856 | return err;
|
---|
857 | }
|
---|
858 | if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0) {
|
---|
859 | snd_card_free(card);
|
---|
860 | return err;
|
---|
861 | }
|
---|
862 | }
|
---|
863 | #endif
|
---|
864 |
|
---|
865 | gus->uart_enable = snd_midi[dev];
|
---|
866 | if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) {
|
---|
867 | snd_card_free(card);
|
---|
868 | return err;
|
---|
869 | }
|
---|
870 |
|
---|
871 | #ifndef SNDRV_STB
|
---|
872 | str = "AMD InterWave";
|
---|
873 | if (gus->gf1.rom_banks == 1 && gus->gf1.rom_present == 8)
|
---|
874 | str = "Dynasonic 3-D";
|
---|
875 | #else
|
---|
876 | str = "InterWave STB";
|
---|
877 | #endif
|
---|
878 | strcpy(card->driver, str);
|
---|
879 | strcpy(card->shortname, str);
|
---|
880 | sprintf(card->longname, "%s at 0x%lx, irq %i, dma %d",
|
---|
881 | str,
|
---|
882 | gus->gf1.port,
|
---|
883 | irq,
|
---|
884 | dma1);
|
---|
885 | if (dma2 >= 0)
|
---|
886 | sprintf(card->longname + strlen(card->longname), "&%d", dma2);
|
---|
887 |
|
---|
888 | if ((err = snd_card_register(card)) < 0) {
|
---|
889 | snd_card_free(card);
|
---|
890 | return err;
|
---|
891 | }
|
---|
892 |
|
---|
893 | iwcard->cs4231 = cs4231;
|
---|
894 | iwcard->gus = gus;
|
---|
895 | snd_interwave_cards[dev++] = card;
|
---|
896 | return 0;
|
---|
897 | }
|
---|
898 |
|
---|
899 | static int __init snd_interwave_probe_legacy_port(unsigned long port)
|
---|
900 | {
|
---|
901 | static int dev = 0;
|
---|
902 | int res;
|
---|
903 |
|
---|
904 | for ( ; dev < SNDRV_CARDS; dev++) {
|
---|
905 | if (!snd_enable[dev] || snd_port[dev] != SNDRV_AUTO_PORT)
|
---|
906 | continue;
|
---|
907 | #ifdef __ISAPNP__
|
---|
908 | if (snd_isapnp[dev])
|
---|
909 | continue;
|
---|
910 | #endif
|
---|
911 | snd_port[dev] = port;
|
---|
912 | res = snd_interwave_probe(dev);
|
---|
913 | if (res < 0)
|
---|
914 | snd_port[dev] = SNDRV_AUTO_PORT;
|
---|
915 | return res;
|
---|
916 | }
|
---|
917 | return -ENODEV;
|
---|
918 | }
|
---|
919 |
|
---|
920 | #ifdef __ISAPNP__
|
---|
921 |
|
---|
922 | static int __init snd_interwave_isapnp_detect(struct isapnp_card *card,
|
---|
923 | const struct isapnp_card_id *id)
|
---|
924 | {
|
---|
925 | static int dev = 0;
|
---|
926 | int res;
|
---|
927 |
|
---|
928 | for ( ; dev < SNDRV_CARDS; dev++) {
|
---|
929 | if (!snd_enable[dev] || !snd_isapnp[dev])
|
---|
930 | continue;
|
---|
931 | snd_interwave_isapnp_cards[dev] = card;
|
---|
932 | snd_interwave_isapnp_id[dev] = id;
|
---|
933 | res = snd_interwave_probe(dev);
|
---|
934 | if (res < 0)
|
---|
935 | return res;
|
---|
936 | dev++;
|
---|
937 | return 0;
|
---|
938 | }
|
---|
939 |
|
---|
940 | return -ENODEV;
|
---|
941 | }
|
---|
942 |
|
---|
943 | #endif /* __ISAPNP__ */
|
---|
944 |
|
---|
945 | static int __init alsa_card_interwave_init(void)
|
---|
946 | {
|
---|
947 | int cards = 0;
|
---|
948 | static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260, -1};
|
---|
949 | int dev;
|
---|
950 |
|
---|
951 | for (dev = 0; dev < SNDRV_CARDS; dev++) {
|
---|
952 | if (!snd_enable[dev] || snd_port[dev] == SNDRV_AUTO_PORT)
|
---|
953 | continue;
|
---|
954 | #ifdef __ISAPNP__
|
---|
955 | if (snd_isapnp[dev])
|
---|
956 | continue;
|
---|
957 | #endif
|
---|
958 | if (!snd_interwave_probe(dev)) {
|
---|
959 | cards++;
|
---|
960 | continue;
|
---|
961 | }
|
---|
962 | #ifdef MODULE
|
---|
963 | snd_printk("InterWave soundcard #%i not found at 0x%lx or device busy\n", dev, snd_port[dev]);
|
---|
964 | #endif
|
---|
965 | }
|
---|
966 | /* legacy auto configured cards */
|
---|
967 | cards += snd_legacy_auto_probe(possible_ports, snd_interwave_probe_legacy_port);
|
---|
968 | #ifdef __ISAPNP__
|
---|
969 | /* ISA PnP cards */
|
---|
970 | cards += isapnp_probe_cards(snd_interwave_pnpids, snd_interwave_isapnp_detect);
|
---|
971 | #endif
|
---|
972 |
|
---|
973 | if (!cards) {
|
---|
974 | #ifdef MODULE
|
---|
975 | snd_printk("InterWave soundcard not found or device busy\n");
|
---|
976 | #endif
|
---|
977 | return -ENODEV;
|
---|
978 | }
|
---|
979 | return 0;
|
---|
980 | }
|
---|
981 |
|
---|
982 | static void __exit alsa_card_interwave_exit(void)
|
---|
983 | {
|
---|
984 | int dev;
|
---|
985 |
|
---|
986 | for (dev = 0; dev < SNDRV_CARDS; dev++)
|
---|
987 | snd_card_free(snd_interwave_cards[dev]);
|
---|
988 | }
|
---|
989 |
|
---|
990 | module_init(alsa_card_interwave_init)
|
---|
991 | module_exit(alsa_card_interwave_exit)
|
---|
992 |
|
---|
993 | #ifndef MODULE
|
---|
994 |
|
---|
995 | /* format is: snd-card-interwave=snd_enable,snd_index,snd_id,snd_isapnp,
|
---|
996 | snd_port[,snd_port_tc],snd_irq,
|
---|
997 | snd_dma1,snd_dma2,
|
---|
998 | snd_joystick_dac,snd_midi,
|
---|
999 | snd_pcm_channels,snd_effect */
|
---|
1000 |
|
---|
1001 | static int __init alsa_card_interwave_setup(char *str)
|
---|
1002 | {
|
---|
1003 | static unsigned __initdata nr_dev = 0;
|
---|
1004 | int __attribute__ ((__unused__)) pnp = INT_MAX;
|
---|
1005 |
|
---|
1006 | if (nr_dev >= SNDRV_CARDS)
|
---|
1007 | return 0;
|
---|
1008 | (void)(get_option(&str,&snd_enable[nr_dev]) == 2 &&
|
---|
1009 | get_option(&str,&snd_index[nr_dev]) == 2 &&
|
---|
1010 | get_id(&str,&snd_id[nr_dev]) == 2 &&
|
---|
1011 | get_option(&str,&pnp) == 2 &&
|
---|
1012 | get_option(&str,(int *)&snd_port[nr_dev]) == 2 &&
|
---|
1013 | #ifdef SNDRV_STB
|
---|
1014 | get_option(&str,(int *)&snd_port_tc[nr_dev]) == 2 &&
|
---|
1015 | #endif
|
---|
1016 | get_option(&str,&snd_irq[nr_dev]) == 2 &&
|
---|
1017 | get_option(&str,&snd_dma1[nr_dev]) == 2 &&
|
---|
1018 | get_option(&str,&snd_dma2[nr_dev]) == 2 &&
|
---|
1019 | get_option(&str,&snd_joystick_dac[nr_dev]) == 2 &&
|
---|
1020 | get_option(&str,&snd_midi[nr_dev]) == 2 &&
|
---|
1021 | get_option(&str,&snd_pcm_channels[nr_dev]) == 2 &&
|
---|
1022 | get_option(&str,&snd_effect[nr_dev]) == 2);
|
---|
1023 | #ifdef __ISAPNP__
|
---|
1024 | if (pnp != INT_MAX)
|
---|
1025 | snd_isapnp[nr_dev] = pnp;
|
---|
1026 | #endif
|
---|
1027 | nr_dev++;
|
---|
1028 | return 1;
|
---|
1029 | }
|
---|
1030 |
|
---|
1031 | #ifndef SNDRV_STB
|
---|
1032 | __setup("snd-card-interwave=", alsa_card_interwave_setup);
|
---|
1033 | #else
|
---|
1034 | __setup("snd-card-interwave-stb=", alsa_card_interwave_setup);
|
---|
1035 | #endif
|
---|
1036 |
|
---|
1037 | #endif /* ifndef MODULE */
|
---|