Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/oss/aedsp16.c
10814 views
1
/*
2
sound/oss/aedsp16.c
3
4
Audio Excel DSP 16 software configuration routines
5
Copyright (C) 1995,1996,1997,1998 Riccardo Facchetti ([email protected])
6
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
11
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
16
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21
*/
22
/*
23
* Include the main OSS Lite header file. It include all the os, OSS Lite, etc
24
* headers needed by this source.
25
*/
26
#include <linux/delay.h>
27
#include <linux/module.h>
28
#include <linux/init.h>
29
#include "sound_config.h"
30
31
/*
32
33
READ THIS
34
35
This module started to configure the Audio Excel DSP 16 Sound Card.
36
Now works with the SC-6000 (old aedsp16) and new SC-6600 based cards.
37
38
NOTE: I have NO idea about Audio Excel DSP 16 III. If someone owns this
39
audio card and want to see the kernel support for it, please contact me.
40
41
Audio Excel DSP 16 is an SB pro II, Microsoft Sound System and MPU-401
42
compatible card.
43
It is software-only configurable (no jumpers to hard-set irq/dma/mpu-irq),
44
so before this module, the only way to configure the DSP under linux was
45
boot the MS-DOS loading the sound.sys device driver (this driver soft-
46
configure the sound board hardware by massaging someone of its registers),
47
and then ctrl-alt-del to boot linux with the DSP configured by the DOS
48
driver.
49
50
This module works configuring your Audio Excel DSP 16's irq, dma and
51
mpu-401-irq. The OSS Lite routines rely on the fact that if the
52
hardware is there, they can detect it. The problem with AEDSP16 is
53
that no hardware can be found by the probe routines if the sound card
54
is not configured properly. Sometimes the kernel probe routines can find
55
an SBPRO even when the card is not configured (this is the standard setup
56
of the card), but the SBPRO emulation don't work well if the card is not
57
properly initialized. For this reason
58
59
aedsp16_init_board()
60
61
routine is called before the OSS Lite probe routines try to detect the
62
hardware.
63
64
NOTE (READ THE NOTE TOO, IT CONTAIN USEFUL INFORMATIONS)
65
66
NOTE: Now it works with SC-6000 and SC-6600 based audio cards. The new cards
67
have no jumper switch at all. No more WSS or MPU-401 I/O port switches. They
68
have to be configured by software.
69
70
NOTE: The driver is merged with the new OSS Lite sound driver. It works
71
as a lowlevel driver.
72
73
The Audio Excel DSP 16 Sound Card emulates both SBPRO and MSS;
74
the OSS Lite sound driver can be configured for SBPRO and MSS cards
75
at the same time, but the aedsp16 can't be two cards!!
76
When we configure it, we have to choose the SBPRO or the MSS emulation
77
for AEDSP16. We also can install a *REAL* card of the other type (see [1]).
78
79
NOTE: If someone can test the combination AEDSP16+MSS or AEDSP16+SBPRO
80
please let me know if it works.
81
82
The MPU-401 support can be compiled in together with one of the other
83
two operating modes.
84
85
NOTE: This is something like plug-and-play: we have only to plug
86
the AEDSP16 board in the socket, and then configure and compile
87
a kernel that uses the AEDSP16 software configuration capability.
88
No jumper setting is needed!
89
90
For example, if you want AEDSP16 to be an SBPro, on irq 10, dma 3
91
you have just to make config the OSS Lite package, configuring
92
the AEDSP16 sound card, then activating the SBPro emulation mode
93
and at last configuring IRQ and DMA.
94
Compile the kernel and run it.
95
96
NOTE: This means for SC-6000 cards that you can choose irq and dma,
97
but not the I/O addresses. To change I/O addresses you have to set
98
them with jumpers. For SC-6600 cards you have no jumpers so you have
99
to set up your full card configuration in the make config.
100
101
You can change the irq/dma/mirq settings WITHOUT THE NEED to open
102
your computer and massage the jumpers (there are no irq/dma/mirq
103
jumpers to be configured anyway, only I/O BASE values have to be
104
configured with jumpers)
105
106
For some ununderstandable reason, the card default of irq 7, dma 1,
107
don't work for me. Seems to be an IRQ or DMA conflict. Under heavy
108
HDD work, the kernel start to erupt out a lot of messages like:
109
110
'Sound: DMA timed out - IRQ/DRQ config error?'
111
112
For what I can say, I have NOT any conflict at irq 7 (under linux I'm
113
using the lp polling driver), and dma line 1 is unused as stated by
114
/proc/dma. I can suppose this is a bug of AEDSP16. I know my hardware so
115
I'm pretty sure I have not any conflict, but may be I'm wrong. Who knows!
116
Anyway a setting of irq 10, dma 3 works really fine.
117
118
NOTE: if someone can use AEDSP16 with irq 7, dma 1, please let me know
119
the emulation mode, all the installed hardware and the hardware
120
configuration (irq and dma settings of all the hardware).
121
122
This init module should work with SBPRO+MSS, when one of the two is
123
the AEDSP16 emulation and the other the real card. (see [1])
124
For example:
125
126
AEDSP16 (0x220) in SBPRO emu (0x220) + real MSS + other
127
AEDSP16 (0x220) in MSS emu + real SBPRO (0x240) + other
128
129
MPU401 should work. (see [2])
130
131
[1]
132
---
133
Date: Mon, 29 Jul 1997 08:35:40 +0100
134
From: Mr S J Greenaway <[email protected]>
135
136
[...]
137
Just to let you know got my Audio Excel (emulating a MSS) working
138
with my original SB16, thanks for the driver!
139
[...]
140
---
141
142
[2] Not tested by me for lack of hardware.
143
144
TODO, WISHES AND TECH
145
146
- About I/O ports allocation -
147
148
Request the 2x0h region (port base) in any case if we are using this card.
149
150
NOTE: the "aedsp16 (base)" string with which we are requesting the aedsp16
151
port base region (see code) does not mean necessarily that we are emulating
152
sbpro. Even if this region is the sbpro I/O ports region, we use this
153
region to access the control registers of the card, and if emulating
154
sbpro, I/O sbpro registers too. If we are emulating MSS, the sbpro
155
registers are not used, in no way, to emulate an sbpro: they are
156
used only for configuration purposes.
157
158
Started Fri Mar 17 16:13:18 MET 1995
159
160
v0.1 (ALPHA, was a user-level program called AudioExcelDSP16.c)
161
- Initial code.
162
v0.2 (ALPHA)
163
- Cleanups.
164
- Integrated with Linux voxware v 2.90-2 kernel sound driver.
165
- SoundBlaster Pro mode configuration.
166
- Microsoft Sound System mode configuration.
167
- MPU-401 mode configuration.
168
v0.3 (ALPHA)
169
- Cleanups.
170
- Rearranged the code to let aedsp16_init_board be more general.
171
- Erased the REALLY_SLOW_IO. We don't need it. Erased the linux/io.h
172
inclusion too. We rely on os.h
173
- Used the to get a variable
174
len string (we are not sure about the len of Copyright string).
175
This works with any SB and compatible.
176
- Added the code to request_region at device init (should go in
177
the main body of voxware).
178
v0.4 (BETA)
179
- Better configure.c patch for aedsp16 configuration (better
180
logic of inclusion of AEDSP16 support)
181
- Modified the conditional compilation to better support more than
182
one sound card of the emulated type (read the NOTES above)
183
- Moved the sb init routine from the attach to the very first
184
probe in sb_card.c
185
- Rearrangements and cleanups
186
- Wiped out some unnecessary code and variables: this is kernel
187
code so it is better save some TEXT and DATA
188
- Fixed the request_region code. We must allocate the aedsp16 (sbpro)
189
I/O ports in any case because they are used to access the DSP
190
configuration registers and we can not allow anyone to get them.
191
v0.5
192
- cleanups on comments
193
- prep for diffs against v3.0-proto-950402
194
v0.6
195
- removed the request_region()s when compiling the MODULE sound.o
196
because we are not allowed (by the actual voxware structure) to
197
release_region()
198
v0.7 (pre ALPHA, not distributed)
199
- started porting this module to kernel 1.3.84. Dummy probe/attach
200
routines.
201
v0.8 (ALPHA)
202
- attached all the init routines.
203
v0.9 (BETA)
204
- Integrated with linux-pre2.0.7
205
- Integrated with configuration scripts.
206
- Cleaned up and beautyfied the code.
207
v0.9.9 (BETA)
208
- Thanks to Piercarlo Grandi: corrected the conditonal compilation code.
209
Now only the code configured is compiled in, with some memory saving.
210
v0.9.10
211
- Integration into the sound/lowlevel/ section of the sound driver.
212
- Re-organized the code.
213
v0.9.11 (not distributed)
214
- Rewritten the init interface-routines to initialize the AEDSP16 in
215
one shot.
216
- More cosmetics.
217
- SC-6600 support.
218
- More soft/hard configuration.
219
v0.9.12
220
- Refined the v0.9.11 code with conditional compilation to distinguish
221
between SC-6000 and SC-6600 code.
222
v1.0.0
223
- Prep for merging with OSS Lite and Linux kernel 2.1.13
224
- Corrected a bug in request/check/release region calls (thanks to the
225
new kernel exception handling).
226
v1.1
227
- Revamped for integration with new modularized sound drivers: to enhance
228
the flexibility of modular version, I have removed all the conditional
229
compilation for SBPRO, MPU and MSS code. Now it is all managed with
230
the ae_config structure.
231
v1.2
232
- Module informations added.
233
- Removed aedsp16_delay_10msec(), now using mdelay(10)
234
- All data and funcs moved to .*.init section.
235
v1.3
236
Arnaldo Carvalho de Melo <[email protected]> - 2000/09/27
237
- got rid of check_region
238
239
Known Problems:
240
- Audio Excel DSP 16 III don't work with this driver.
241
242
Credits:
243
Many thanks to Gerald Britton <[email protected]>. He helped me a
244
lot in testing the 0.9.11 and 0.9.12 versions of this driver.
245
246
*/
247
248
249
#define VERSION "1.3" /* Version of Audio Excel DSP 16 driver */
250
251
#undef AEDSP16_DEBUG /* Define this to 1 to enable debug code */
252
#undef AEDSP16_DEBUG_MORE /* Define this to 1 to enable more debug */
253
#undef AEDSP16_INFO /* Define this to 1 to enable info code */
254
255
#if defined(AEDSP16_DEBUG)
256
# define DBG(x) printk x
257
# if defined(AEDSP16_DEBUG_MORE)
258
# define DBG1(x) printk x
259
# else
260
# define DBG1(x)
261
# endif
262
#else
263
# define DBG(x)
264
# define DBG1(x)
265
#endif
266
267
/*
268
* Misc definitions
269
*/
270
#define TRUE 1
271
#define FALSE 0
272
273
/*
274
* Region Size for request/check/release region.
275
*/
276
#define IOBASE_REGION_SIZE 0x10
277
278
/*
279
* Hardware related defaults
280
*/
281
#define DEF_AEDSP16_IOB 0x220 /* 0x220(default) 0x240 */
282
#define DEF_AEDSP16_IRQ 7 /* 5 7(default) 9 10 11 */
283
#define DEF_AEDSP16_MRQ 0 /* 5 7 9 10 0(default), 0 means disable */
284
#define DEF_AEDSP16_DMA 1 /* 0 1(default) 3 */
285
286
/*
287
* Commands of AEDSP16's DSP (SBPRO+special).
288
* Some of them are COMMAND_xx, in the future they may change.
289
*/
290
#define WRITE_MDIRQ_CFG 0x50 /* Set M&I&DRQ mask (the real config) */
291
#define COMMAND_52 0x52 /* */
292
#define READ_HARD_CFG 0x58 /* Read Hardware Config (I/O base etc) */
293
#define COMMAND_5C 0x5c /* */
294
#define COMMAND_60 0x60 /* */
295
#define COMMAND_66 0x66 /* */
296
#define COMMAND_6C 0x6c /* */
297
#define COMMAND_6E 0x6e /* */
298
#define COMMAND_88 0x88 /* */
299
#define DSP_INIT_MSS 0x8c /* Enable Microsoft Sound System mode */
300
#define COMMAND_C5 0xc5 /* */
301
#define GET_DSP_VERSION 0xe1 /* Get DSP Version */
302
#define GET_DSP_COPYRIGHT 0xe3 /* Get DSP Copyright */
303
304
/*
305
* Offsets of AEDSP16 DSP I/O ports. The offset is added to base I/O port
306
* to have the actual I/O port.
307
* Register permissions are:
308
* (wo) == Write Only
309
* (ro) == Read Only
310
* (w-) == Write
311
* (r-) == Read
312
*/
313
#define DSP_RESET 0x06 /* offset of DSP RESET (wo) */
314
#define DSP_READ 0x0a /* offset of DSP READ (ro) */
315
#define DSP_WRITE 0x0c /* offset of DSP WRITE (w-) */
316
#define DSP_COMMAND 0x0c /* offset of DSP COMMAND (w-) */
317
#define DSP_STATUS 0x0c /* offset of DSP STATUS (r-) */
318
#define DSP_DATAVAIL 0x0e /* offset of DSP DATA AVAILABLE (ro) */
319
320
321
#define RETRY 10 /* Various retry values on I/O opera- */
322
#define STATUSRETRY 1000 /* tions. Sometimes we have to */
323
#define HARDRETRY 500000 /* wait for previous cmd to complete */
324
325
/*
326
* Size of character arrays that store name and version of sound card
327
*/
328
#define CARDNAMELEN 15 /* Size of the card's name in chars */
329
#define CARDVERLEN 10 /* Size of the card's version in chars */
330
#define CARDVERDIGITS 2 /* Number of digits in the version */
331
332
#if defined(CONFIG_SC6600)
333
/*
334
* Bitmapped flags of hard configuration
335
*/
336
/*
337
* Decode macros (xl == low byte, xh = high byte)
338
*/
339
#define IOBASE(xl) ((xl & 0x01)?0x240:0x220)
340
#define JOY(xl) (xl & 0x02)
341
#define MPUADDR(xl) ( \
342
(xl & 0x0C)?0x330: \
343
(xl & 0x08)?0x320: \
344
(xl & 0x04)?0x310: \
345
0x300)
346
#define WSSADDR(xl) ((xl & 0x10)?0xE80:0x530)
347
#define CDROM(xh) (xh & 0x20)
348
#define CDROMADDR(xh) (((xh & 0x1F) << 4) + 0x200)
349
/*
350
* Encode macros
351
*/
352
#define BLDIOBASE(xl, val) { \
353
xl &= ~0x01; \
354
if (val == 0x240) \
355
xl |= 0x01; \
356
}
357
#define BLDJOY(xl, val) { \
358
xl &= ~0x02; \
359
if (val == 1) \
360
xl |= 0x02; \
361
}
362
#define BLDMPUADDR(xl, val) { \
363
xl &= ~0x0C; \
364
switch (val) { \
365
case 0x330: \
366
xl |= 0x0C; \
367
break; \
368
case 0x320: \
369
xl |= 0x08; \
370
break; \
371
case 0x310: \
372
xl |= 0x04; \
373
break; \
374
case 0x300: \
375
xl |= 0x00; \
376
break; \
377
default: \
378
xl |= 0x00; \
379
break; \
380
} \
381
}
382
#define BLDWSSADDR(xl, val) { \
383
xl &= ~0x10; \
384
if (val == 0xE80) \
385
xl |= 0x10; \
386
}
387
#define BLDCDROM(xh, val) { \
388
xh &= ~0x20; \
389
if (val == 1) \
390
xh |= 0x20; \
391
}
392
#define BLDCDROMADDR(xh, val) { \
393
int tmp = val; \
394
tmp -= 0x200; \
395
tmp >>= 4; \
396
tmp &= 0x1F; \
397
xh |= tmp; \
398
xh &= 0x7F; \
399
xh |= 0x40; \
400
}
401
#endif /* CONFIG_SC6600 */
402
403
/*
404
* Bit mapped flags for calling aedsp16_init_board(), and saving the current
405
* emulation mode.
406
*/
407
#define INIT_NONE (0 )
408
#define INIT_SBPRO (1<<0)
409
#define INIT_MSS (1<<1)
410
#define INIT_MPU401 (1<<2)
411
412
static int soft_cfg __initdata = 0; /* bitmapped config */
413
static int soft_cfg_mss __initdata = 0; /* bitmapped mss config */
414
static int ver[CARDVERDIGITS] __initdata = {0, 0}; /* DSP Ver:
415
hi->ver[0] lo->ver[1] */
416
417
#if defined(CONFIG_SC6600)
418
static int hard_cfg[2] /* lo<-hard_cfg[0] hi<-hard_cfg[1] */
419
__initdata = { 0, 0};
420
#endif /* CONFIG_SC6600 */
421
422
#if defined(CONFIG_SC6600)
423
/* Decoded hard configuration */
424
struct d_hcfg {
425
int iobase;
426
int joystick;
427
int mpubase;
428
int wssbase;
429
int cdrom;
430
int cdrombase;
431
};
432
433
static struct d_hcfg decoded_hcfg __initdata = {0, };
434
435
#endif /* CONFIG_SC6600 */
436
437
/* orVals contain the values to be or'ed */
438
struct orVals {
439
int val; /* irq|mirq|dma */
440
int or; /* soft_cfg |= TheStruct.or */
441
};
442
443
/* aedsp16_info contain the audio card configuration */
444
struct aedsp16_info {
445
int base_io; /* base I/O address for accessing card */
446
int irq; /* irq value for DSP I/O */
447
int mpu_irq; /* irq for mpu401 interface I/O */
448
int dma; /* dma value for DSP I/O */
449
int mss_base; /* base I/O for Microsoft Sound System */
450
int mpu_base; /* base I/O for MPU-401 emulation */
451
int init; /* Initialization status of the card */
452
};
453
454
/*
455
* Magic values that the DSP will eat when configuring irq/mirq/dma
456
*/
457
/* DSP IRQ conversion array */
458
static struct orVals orIRQ[] __initdata = {
459
{0x05, 0x28},
460
{0x07, 0x08},
461
{0x09, 0x10},
462
{0x0a, 0x18},
463
{0x0b, 0x20},
464
{0x00, 0x00}
465
};
466
467
/* MPU-401 IRQ conversion array */
468
static struct orVals orMIRQ[] __initdata = {
469
{0x05, 0x04},
470
{0x07, 0x44},
471
{0x09, 0x84},
472
{0x0a, 0xc4},
473
{0x00, 0x00}
474
};
475
476
/* DMA Channels conversion array */
477
static struct orVals orDMA[] __initdata = {
478
{0x00, 0x01},
479
{0x01, 0x02},
480
{0x03, 0x03},
481
{0x00, 0x00}
482
};
483
484
static struct aedsp16_info ae_config = {
485
DEF_AEDSP16_IOB,
486
DEF_AEDSP16_IRQ,
487
DEF_AEDSP16_MRQ,
488
DEF_AEDSP16_DMA,
489
-1,
490
-1,
491
INIT_NONE
492
};
493
494
/*
495
* Buffers to store audio card informations
496
*/
497
static char DSPCopyright[CARDNAMELEN + 1] __initdata = {0, };
498
static char DSPVersion[CARDVERLEN + 1] __initdata = {0, };
499
500
static int __init aedsp16_wait_data(int port)
501
{
502
int loop = STATUSRETRY;
503
unsigned char ret = 0;
504
505
DBG1(("aedsp16_wait_data (0x%x): ", port));
506
507
do {
508
ret = inb(port + DSP_DATAVAIL);
509
/*
510
* Wait for data available (bit 7 of ret == 1)
511
*/
512
} while (!(ret & 0x80) && loop--);
513
514
if (ret & 0x80) {
515
DBG1(("success.\n"));
516
return TRUE;
517
}
518
519
DBG1(("failure.\n"));
520
return FALSE;
521
}
522
523
static int __init aedsp16_read(int port)
524
{
525
int inbyte;
526
527
DBG((" Read DSP Byte (0x%x): ", port));
528
529
if (aedsp16_wait_data(port) == FALSE) {
530
DBG(("failure.\n"));
531
return -1;
532
}
533
534
inbyte = inb(port + DSP_READ);
535
536
DBG(("read [0x%x]/{%c}.\n", inbyte, inbyte));
537
538
return inbyte;
539
}
540
541
static int __init aedsp16_test_dsp(int port)
542
{
543
return ((aedsp16_read(port) == 0xaa) ? TRUE : FALSE);
544
}
545
546
static int __init aedsp16_dsp_reset(int port)
547
{
548
/*
549
* Reset DSP
550
*/
551
552
DBG(("Reset DSP:\n"));
553
554
outb(1, (port + DSP_RESET));
555
udelay(10);
556
outb(0, (port + DSP_RESET));
557
udelay(10);
558
udelay(10);
559
if (aedsp16_test_dsp(port) == TRUE) {
560
DBG(("success.\n"));
561
return TRUE;
562
} else
563
DBG(("failure.\n"));
564
return FALSE;
565
}
566
567
static int __init aedsp16_write(int port, int cmd)
568
{
569
unsigned char ret;
570
int loop = HARDRETRY;
571
572
DBG((" Write DSP Byte (0x%x) [0x%x]: ", port, cmd));
573
574
do {
575
ret = inb(port + DSP_STATUS);
576
/*
577
* DSP ready to receive data if bit 7 of ret == 0
578
*/
579
if (!(ret & 0x80)) {
580
outb(cmd, port + DSP_COMMAND);
581
DBG(("success.\n"));
582
return 0;
583
}
584
} while (loop--);
585
586
DBG(("timeout.\n"));
587
printk("[AEDSP16] DSP Command (0x%x) timeout.\n", cmd);
588
589
return -1;
590
}
591
592
#if defined(CONFIG_SC6600)
593
594
#if defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG)
595
void __init aedsp16_pinfo(void) {
596
DBG(("\n Base address: %x\n", decoded_hcfg.iobase));
597
DBG((" Joystick : %s present\n", decoded_hcfg.joystick?"":" not"));
598
DBG((" WSS addr : %x\n", decoded_hcfg.wssbase));
599
DBG((" MPU-401 addr: %x\n", decoded_hcfg.mpubase));
600
DBG((" CDROM : %s present\n", (decoded_hcfg.cdrom!=4)?"":" not"));
601
DBG((" CDROMADDR : %x\n\n", decoded_hcfg.cdrombase));
602
}
603
#endif
604
605
static void __init aedsp16_hard_decode(void) {
606
607
DBG((" aedsp16_hard_decode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
608
609
/*
610
* Decode Cfg Bytes.
611
*/
612
decoded_hcfg.iobase = IOBASE(hard_cfg[0]);
613
decoded_hcfg.joystick = JOY(hard_cfg[0]);
614
decoded_hcfg.wssbase = WSSADDR(hard_cfg[0]);
615
decoded_hcfg.mpubase = MPUADDR(hard_cfg[0]);
616
decoded_hcfg.cdrom = CDROM(hard_cfg[1]);
617
decoded_hcfg.cdrombase = CDROMADDR(hard_cfg[1]);
618
619
#if defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG)
620
printk(" Original sound card configuration:\n");
621
aedsp16_pinfo();
622
#endif
623
624
/*
625
* Now set up the real kernel configuration.
626
*/
627
decoded_hcfg.iobase = ae_config.base_io;
628
decoded_hcfg.wssbase = ae_config.mss_base;
629
decoded_hcfg.mpubase = ae_config.mpu_base;
630
631
#if defined(CONFIG_SC6600_JOY)
632
decoded_hcfg.joystick = CONFIG_SC6600_JOY; /* Enable */
633
#endif
634
#if defined(CONFIG_SC6600_CDROM)
635
decoded_hcfg.cdrom = CONFIG_SC6600_CDROM; /* 4:N-3:I-2:G-1:P-0:S */
636
#endif
637
#if defined(CONFIG_SC6600_CDROMBASE)
638
decoded_hcfg.cdrombase = CONFIG_SC6600_CDROMBASE; /* 0 Disable */
639
#endif
640
641
#if defined(AEDSP16_DEBUG)
642
DBG((" New Values:\n"));
643
aedsp16_pinfo();
644
#endif
645
646
DBG(("success.\n"));
647
}
648
649
static void __init aedsp16_hard_encode(void) {
650
651
DBG((" aedsp16_hard_encode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
652
653
hard_cfg[0] = 0;
654
hard_cfg[1] = 0;
655
656
hard_cfg[0] |= 0x20;
657
658
BLDIOBASE (hard_cfg[0], decoded_hcfg.iobase);
659
BLDWSSADDR(hard_cfg[0], decoded_hcfg.wssbase);
660
BLDMPUADDR(hard_cfg[0], decoded_hcfg.mpubase);
661
BLDJOY(hard_cfg[0], decoded_hcfg.joystick);
662
BLDCDROM(hard_cfg[1], decoded_hcfg.cdrom);
663
BLDCDROMADDR(hard_cfg[1], decoded_hcfg.cdrombase);
664
665
#if defined(AEDSP16_DEBUG)
666
aedsp16_pinfo();
667
#endif
668
669
DBG((" aedsp16_hard_encode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
670
DBG(("success.\n"));
671
672
}
673
674
static int __init aedsp16_hard_write(int port) {
675
676
DBG(("aedsp16_hard_write:\n"));
677
678
if (aedsp16_write(port, COMMAND_6C)) {
679
printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_6C);
680
DBG(("failure.\n"));
681
return FALSE;
682
}
683
if (aedsp16_write(port, COMMAND_5C)) {
684
printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C);
685
DBG(("failure.\n"));
686
return FALSE;
687
}
688
if (aedsp16_write(port, hard_cfg[0])) {
689
printk("[AEDSP16] DATA 0x%x: failed!\n", hard_cfg[0]);
690
DBG(("failure.\n"));
691
return FALSE;
692
}
693
if (aedsp16_write(port, hard_cfg[1])) {
694
printk("[AEDSP16] DATA 0x%x: failed!\n", hard_cfg[1]);
695
DBG(("failure.\n"));
696
return FALSE;
697
}
698
if (aedsp16_write(port, COMMAND_C5)) {
699
printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_C5);
700
DBG(("failure.\n"));
701
return FALSE;
702
}
703
704
DBG(("success.\n"));
705
706
return TRUE;
707
}
708
709
static int __init aedsp16_hard_read(int port) {
710
711
DBG(("aedsp16_hard_read:\n"));
712
713
if (aedsp16_write(port, READ_HARD_CFG)) {
714
printk("[AEDSP16] CMD 0x%x: failed!\n", READ_HARD_CFG);
715
DBG(("failure.\n"));
716
return FALSE;
717
}
718
719
if ((hard_cfg[0] = aedsp16_read(port)) == -1) {
720
printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
721
READ_HARD_CFG);
722
DBG(("failure.\n"));
723
return FALSE;
724
}
725
if ((hard_cfg[1] = aedsp16_read(port)) == -1) {
726
printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
727
READ_HARD_CFG);
728
DBG(("failure.\n"));
729
return FALSE;
730
}
731
if (aedsp16_read(port) == -1) {
732
printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
733
READ_HARD_CFG);
734
DBG(("failure.\n"));
735
return FALSE;
736
}
737
738
DBG(("success.\n"));
739
740
return TRUE;
741
}
742
743
static int __init aedsp16_ext_cfg_write(int port) {
744
745
int extcfg, val;
746
747
if (aedsp16_write(port, COMMAND_66)) {
748
printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_66);
749
return FALSE;
750
}
751
752
extcfg = 7;
753
if (decoded_hcfg.cdrom != 2)
754
extcfg = 0x0F;
755
if ((decoded_hcfg.cdrom == 4) ||
756
(decoded_hcfg.cdrom == 3))
757
extcfg &= ~2;
758
if (decoded_hcfg.cdrombase == 0)
759
extcfg &= ~2;
760
if (decoded_hcfg.mpubase == 0)
761
extcfg &= ~1;
762
763
if (aedsp16_write(port, extcfg)) {
764
printk("[AEDSP16] Write extcfg: failed!\n");
765
return FALSE;
766
}
767
if (aedsp16_write(port, 0)) {
768
printk("[AEDSP16] Write extcfg: failed!\n");
769
return FALSE;
770
}
771
if (decoded_hcfg.cdrom == 3) {
772
if (aedsp16_write(port, COMMAND_52)) {
773
printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_52);
774
return FALSE;
775
}
776
if ((val = aedsp16_read(port)) == -1) {
777
printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n"
778
, COMMAND_52);
779
return FALSE;
780
}
781
val &= 0x7F;
782
if (aedsp16_write(port, COMMAND_60)) {
783
printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_60);
784
return FALSE;
785
}
786
if (aedsp16_write(port, val)) {
787
printk("[AEDSP16] Write val: failed!\n");
788
return FALSE;
789
}
790
}
791
792
return TRUE;
793
}
794
795
#endif /* CONFIG_SC6600 */
796
797
static int __init aedsp16_cfg_write(int port) {
798
if (aedsp16_write(port, WRITE_MDIRQ_CFG)) {
799
printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG);
800
return FALSE;
801
}
802
if (aedsp16_write(port, soft_cfg)) {
803
printk("[AEDSP16] Initialization of (M)IRQ and DMA: failed!\n");
804
return FALSE;
805
}
806
return TRUE;
807
}
808
809
static int __init aedsp16_init_mss(int port)
810
{
811
DBG(("aedsp16_init_mss:\n"));
812
813
mdelay(10);
814
815
if (aedsp16_write(port, DSP_INIT_MSS)) {
816
printk("[AEDSP16] aedsp16_init_mss [0x%x]: failed!\n",
817
DSP_INIT_MSS);
818
DBG(("failure.\n"));
819
return FALSE;
820
}
821
822
mdelay(10);
823
824
if (aedsp16_cfg_write(port) == FALSE)
825
return FALSE;
826
827
outb(soft_cfg_mss, ae_config.mss_base);
828
829
DBG(("success.\n"));
830
831
return TRUE;
832
}
833
834
static int __init aedsp16_setup_board(int port) {
835
int loop = RETRY;
836
837
#if defined(CONFIG_SC6600)
838
int val = 0;
839
840
if (aedsp16_hard_read(port) == FALSE) {
841
printk("[AEDSP16] aedsp16_hard_read: failed!\n");
842
return FALSE;
843
}
844
845
if (aedsp16_write(port, COMMAND_52)) {
846
printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_52);
847
return FALSE;
848
}
849
850
if ((val = aedsp16_read(port)) == -1) {
851
printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
852
COMMAND_52);
853
return FALSE;
854
}
855
#endif
856
857
do {
858
if (aedsp16_write(port, COMMAND_88)) {
859
printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_88);
860
return FALSE;
861
}
862
mdelay(10);
863
} while ((aedsp16_wait_data(port) == FALSE) && loop--);
864
865
if (aedsp16_read(port) == -1) {
866
printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
867
COMMAND_88);
868
return FALSE;
869
}
870
871
#if !defined(CONFIG_SC6600)
872
if (aedsp16_write(port, COMMAND_5C)) {
873
printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C);
874
return FALSE;
875
}
876
#endif
877
878
if (aedsp16_cfg_write(port) == FALSE)
879
return FALSE;
880
881
#if defined(CONFIG_SC6600)
882
if (aedsp16_write(port, COMMAND_60)) {
883
printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_60);
884
return FALSE;
885
}
886
if (aedsp16_write(port, val)) {
887
printk("[AEDSP16] DATA 0x%x: failed!\n", val);
888
return FALSE;
889
}
890
if (aedsp16_write(port, COMMAND_6E)) {
891
printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_6E);
892
return FALSE;
893
}
894
if (aedsp16_write(port, ver[0])) {
895
printk("[AEDSP16] DATA 0x%x: failed!\n", ver[0]);
896
return FALSE;
897
}
898
if (aedsp16_write(port, ver[1])) {
899
printk("[AEDSP16] DATA 0x%x: failed!\n", ver[1]);
900
return FALSE;
901
}
902
903
if (aedsp16_hard_write(port) == FALSE) {
904
printk("[AEDSP16] aedsp16_hard_write: failed!\n");
905
return FALSE;
906
}
907
908
if (aedsp16_write(port, COMMAND_5C)) {
909
printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C);
910
return FALSE;
911
}
912
913
#if defined(THIS_IS_A_THING_I_HAVE_NOT_TESTED_YET)
914
if (aedsp16_cfg_write(port) == FALSE)
915
return FALSE;
916
#endif
917
918
#endif
919
920
return TRUE;
921
}
922
923
static int __init aedsp16_stdcfg(int port) {
924
if (aedsp16_write(port, WRITE_MDIRQ_CFG)) {
925
printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG);
926
return FALSE;
927
}
928
/*
929
* 0x0A == (IRQ 7, DMA 1, MIRQ 0)
930
*/
931
if (aedsp16_write(port, 0x0A)) {
932
printk("[AEDSP16] aedsp16_stdcfg: failed!\n");
933
return FALSE;
934
}
935
return TRUE;
936
}
937
938
static int __init aedsp16_dsp_version(int port)
939
{
940
int len = 0;
941
int ret;
942
943
DBG(("Get DSP Version:\n"));
944
945
if (aedsp16_write(ae_config.base_io, GET_DSP_VERSION)) {
946
printk("[AEDSP16] CMD 0x%x: failed!\n", GET_DSP_VERSION);
947
DBG(("failed.\n"));
948
return FALSE;
949
}
950
951
do {
952
if ((ret = aedsp16_read(port)) == -1) {
953
DBG(("failed.\n"));
954
return FALSE;
955
}
956
/*
957
* We already know how many int are stored (2), so we know when the
958
* string is finished.
959
*/
960
ver[len++] = ret;
961
} while (len < CARDVERDIGITS);
962
sprintf(DSPVersion, "%d.%d", ver[0], ver[1]);
963
964
DBG(("success.\n"));
965
966
return TRUE;
967
}
968
969
static int __init aedsp16_dsp_copyright(int port)
970
{
971
int len = 0;
972
int ret;
973
974
DBG(("Get DSP Copyright:\n"));
975
976
if (aedsp16_write(ae_config.base_io, GET_DSP_COPYRIGHT)) {
977
printk("[AEDSP16] CMD 0x%x: failed!\n", GET_DSP_COPYRIGHT);
978
DBG(("failed.\n"));
979
return FALSE;
980
}
981
982
do {
983
if ((ret = aedsp16_read(port)) == -1) {
984
/*
985
* If no more data available, return to the caller, no error if len>0.
986
* We have no other way to know when the string is finished.
987
*/
988
if (len)
989
break;
990
else {
991
DBG(("failed.\n"));
992
return FALSE;
993
}
994
}
995
996
DSPCopyright[len++] = ret;
997
998
} while (len < CARDNAMELEN);
999
1000
DBG(("success.\n"));
1001
1002
return TRUE;
1003
}
1004
1005
static void __init aedsp16_init_tables(void)
1006
{
1007
int i = 0;
1008
1009
memset(DSPCopyright, 0, CARDNAMELEN + 1);
1010
memset(DSPVersion, 0, CARDVERLEN + 1);
1011
1012
for (i = 0; orIRQ[i].or; i++)
1013
if (orIRQ[i].val == ae_config.irq) {
1014
soft_cfg |= orIRQ[i].or;
1015
soft_cfg_mss |= orIRQ[i].or;
1016
}
1017
1018
for (i = 0; orMIRQ[i].or; i++)
1019
if (orMIRQ[i].or == ae_config.mpu_irq)
1020
soft_cfg |= orMIRQ[i].or;
1021
1022
for (i = 0; orDMA[i].or; i++)
1023
if (orDMA[i].val == ae_config.dma) {
1024
soft_cfg |= orDMA[i].or;
1025
soft_cfg_mss |= orDMA[i].or;
1026
}
1027
}
1028
1029
static int __init aedsp16_init_board(void)
1030
{
1031
aedsp16_init_tables();
1032
1033
if (aedsp16_dsp_reset(ae_config.base_io) == FALSE) {
1034
printk("[AEDSP16] aedsp16_dsp_reset: failed!\n");
1035
return FALSE;
1036
}
1037
if (aedsp16_dsp_copyright(ae_config.base_io) == FALSE) {
1038
printk("[AEDSP16] aedsp16_dsp_copyright: failed!\n");
1039
return FALSE;
1040
}
1041
1042
/*
1043
* My AEDSP16 card return SC-6000 in DSPCopyright, so
1044
* if we have something different, we have to be warned.
1045
*/
1046
if (strcmp("SC-6000", DSPCopyright))
1047
printk("[AEDSP16] Warning: non SC-6000 audio card!\n");
1048
1049
if (aedsp16_dsp_version(ae_config.base_io) == FALSE) {
1050
printk("[AEDSP16] aedsp16_dsp_version: failed!\n");
1051
return FALSE;
1052
}
1053
1054
if (aedsp16_stdcfg(ae_config.base_io) == FALSE) {
1055
printk("[AEDSP16] aedsp16_stdcfg: failed!\n");
1056
return FALSE;
1057
}
1058
1059
#if defined(CONFIG_SC6600)
1060
if (aedsp16_hard_read(ae_config.base_io) == FALSE) {
1061
printk("[AEDSP16] aedsp16_hard_read: failed!\n");
1062
return FALSE;
1063
}
1064
1065
aedsp16_hard_decode();
1066
1067
aedsp16_hard_encode();
1068
1069
if (aedsp16_hard_write(ae_config.base_io) == FALSE) {
1070
printk("[AEDSP16] aedsp16_hard_write: failed!\n");
1071
return FALSE;
1072
}
1073
1074
if (aedsp16_ext_cfg_write(ae_config.base_io) == FALSE) {
1075
printk("[AEDSP16] aedsp16_ext_cfg_write: failed!\n");
1076
return FALSE;
1077
}
1078
#endif /* CONFIG_SC6600 */
1079
1080
if (aedsp16_setup_board(ae_config.base_io) == FALSE) {
1081
printk("[AEDSP16] aedsp16_setup_board: failed!\n");
1082
return FALSE;
1083
}
1084
1085
if (ae_config.mss_base != -1) {
1086
if (ae_config.init & INIT_MSS) {
1087
if (aedsp16_init_mss(ae_config.base_io) == FALSE) {
1088
printk("[AEDSP16] Can not initialize"
1089
"Microsoft Sound System mode.\n");
1090
return FALSE;
1091
}
1092
}
1093
}
1094
1095
#if !defined(MODULE) || defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG)
1096
1097
printk("Audio Excel DSP 16 init v%s (%s %s) [",
1098
VERSION, DSPCopyright,
1099
DSPVersion);
1100
1101
if (ae_config.mpu_base != -1) {
1102
if (ae_config.init & INIT_MPU401) {
1103
printk("MPU401");
1104
if ((ae_config.init & INIT_MSS) ||
1105
(ae_config.init & INIT_SBPRO))
1106
printk(" ");
1107
}
1108
}
1109
1110
if (ae_config.mss_base == -1) {
1111
if (ae_config.init & INIT_SBPRO) {
1112
printk("SBPro");
1113
if (ae_config.init & INIT_MSS)
1114
printk(" ");
1115
}
1116
}
1117
1118
if (ae_config.mss_base != -1)
1119
if (ae_config.init & INIT_MSS)
1120
printk("MSS");
1121
1122
printk("]\n");
1123
#endif /* MODULE || AEDSP16_INFO || AEDSP16_DEBUG */
1124
1125
mdelay(10);
1126
1127
return TRUE;
1128
}
1129
1130
static int __init init_aedsp16_sb(void)
1131
{
1132
DBG(("init_aedsp16_sb: "));
1133
1134
/*
1135
* If the card is already init'ed MSS, we can not init it to SBPRO too
1136
* because the board can not emulate simultaneously MSS and SBPRO.
1137
*/
1138
if (ae_config.init & INIT_MSS)
1139
return FALSE;
1140
if (ae_config.init & INIT_SBPRO)
1141
return FALSE;
1142
1143
ae_config.init |= INIT_SBPRO;
1144
1145
DBG(("done.\n"));
1146
1147
return TRUE;
1148
}
1149
1150
static void uninit_aedsp16_sb(void)
1151
{
1152
DBG(("uninit_aedsp16_sb: "));
1153
1154
ae_config.init &= ~INIT_SBPRO;
1155
1156
DBG(("done.\n"));
1157
}
1158
1159
static int __init init_aedsp16_mss(void)
1160
{
1161
DBG(("init_aedsp16_mss: "));
1162
1163
/*
1164
* If the card is already init'ed SBPRO, we can not init it to MSS too
1165
* because the board can not emulate simultaneously MSS and SBPRO.
1166
*/
1167
if (ae_config.init & INIT_SBPRO)
1168
return FALSE;
1169
if (ae_config.init & INIT_MSS)
1170
return FALSE;
1171
/*
1172
* We must allocate the CONFIG_AEDSP16_BASE region too because these are the
1173
* I/O ports to access card's control registers.
1174
*/
1175
if (!(ae_config.init & INIT_MPU401)) {
1176
if (!request_region(ae_config.base_io, IOBASE_REGION_SIZE,
1177
"aedsp16 (base)")) {
1178
printk(
1179
"AEDSP16 BASE I/O port region is already in use.\n");
1180
return FALSE;
1181
}
1182
}
1183
1184
ae_config.init |= INIT_MSS;
1185
1186
DBG(("done.\n"));
1187
1188
return TRUE;
1189
}
1190
1191
static void uninit_aedsp16_mss(void)
1192
{
1193
DBG(("uninit_aedsp16_mss: "));
1194
1195
if ((!(ae_config.init & INIT_MPU401)) &&
1196
(ae_config.init & INIT_MSS)) {
1197
release_region(ae_config.base_io, IOBASE_REGION_SIZE);
1198
DBG(("AEDSP16 base region released.\n"));
1199
}
1200
1201
ae_config.init &= ~INIT_MSS;
1202
DBG(("done.\n"));
1203
}
1204
1205
static int __init init_aedsp16_mpu(void)
1206
{
1207
DBG(("init_aedsp16_mpu: "));
1208
1209
if (ae_config.init & INIT_MPU401)
1210
return FALSE;
1211
1212
/*
1213
* We must request the CONFIG_AEDSP16_BASE region too because these are the I/O
1214
* ports to access card's control registers.
1215
*/
1216
if (!(ae_config.init & (INIT_MSS | INIT_SBPRO))) {
1217
if (!request_region(ae_config.base_io, IOBASE_REGION_SIZE,
1218
"aedsp16 (base)")) {
1219
printk(
1220
"AEDSP16 BASE I/O port region is already in use.\n");
1221
return FALSE;
1222
}
1223
}
1224
1225
ae_config.init |= INIT_MPU401;
1226
1227
DBG(("done.\n"));
1228
1229
return TRUE;
1230
}
1231
1232
static void uninit_aedsp16_mpu(void)
1233
{
1234
DBG(("uninit_aedsp16_mpu: "));
1235
1236
if ((!(ae_config.init & (INIT_MSS | INIT_SBPRO))) &&
1237
(ae_config.init & INIT_MPU401)) {
1238
release_region(ae_config.base_io, IOBASE_REGION_SIZE);
1239
DBG(("AEDSP16 base region released.\n"));
1240
}
1241
1242
ae_config.init &= ~INIT_MPU401;
1243
1244
DBG(("done.\n"));
1245
}
1246
1247
static int __init init_aedsp16(void)
1248
{
1249
int initialized = FALSE;
1250
1251
DBG(("Initializing BASE[0x%x] IRQ[%d] DMA[%d] MIRQ[%d]\n",
1252
ae_config.base_io,ae_config.irq,ae_config.dma,ae_config.mpu_irq));
1253
1254
if (ae_config.mss_base == -1) {
1255
if (init_aedsp16_sb() == FALSE) {
1256
uninit_aedsp16_sb();
1257
} else {
1258
initialized = TRUE;
1259
}
1260
}
1261
1262
if (ae_config.mpu_base != -1) {
1263
if (init_aedsp16_mpu() == FALSE) {
1264
uninit_aedsp16_mpu();
1265
} else {
1266
initialized = TRUE;
1267
}
1268
}
1269
1270
/*
1271
* In the sequence of init routines, the MSS init MUST be the last!
1272
* This because of the special register programming the MSS mode needs.
1273
* A board reset would disable the MSS mode restoring the default SBPRO
1274
* mode.
1275
*/
1276
if (ae_config.mss_base != -1) {
1277
if (init_aedsp16_mss() == FALSE) {
1278
uninit_aedsp16_mss();
1279
} else {
1280
initialized = TRUE;
1281
}
1282
}
1283
1284
if (initialized)
1285
initialized = aedsp16_init_board();
1286
return initialized;
1287
}
1288
1289
static void __exit uninit_aedsp16(void)
1290
{
1291
if (ae_config.mss_base != -1)
1292
uninit_aedsp16_mss();
1293
else
1294
uninit_aedsp16_sb();
1295
if (ae_config.mpu_base != -1)
1296
uninit_aedsp16_mpu();
1297
}
1298
1299
static int __initdata io = -1;
1300
static int __initdata irq = -1;
1301
static int __initdata dma = -1;
1302
static int __initdata mpu_irq = -1;
1303
static int __initdata mss_base = -1;
1304
static int __initdata mpu_base = -1;
1305
1306
module_param(io, int, 0);
1307
MODULE_PARM_DESC(io, "I/O base address (0x220 0x240)");
1308
module_param(irq, int, 0);
1309
MODULE_PARM_DESC(irq, "IRQ line (5 7 9 10 11)");
1310
module_param(dma, int, 0);
1311
MODULE_PARM_DESC(dma, "dma line (0 1 3)");
1312
module_param(mpu_irq, int, 0);
1313
MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ line (5 7 9 10 0)");
1314
module_param(mss_base, int, 0);
1315
MODULE_PARM_DESC(mss_base, "MSS emulation I/O base address (0x530 0xE80)");
1316
module_param(mpu_base, int, 0);
1317
MODULE_PARM_DESC(mpu_base,"MPU-401 I/O base address (0x300 0x310 0x320 0x330)");
1318
MODULE_AUTHOR("Riccardo Facchetti <[email protected]>");
1319
MODULE_DESCRIPTION("Audio Excel DSP 16 Driver Version " VERSION);
1320
MODULE_LICENSE("GPL");
1321
1322
static int __init do_init_aedsp16(void) {
1323
printk("Audio Excel DSP 16 init driver Copyright (C) Riccardo Facchetti 1995-98\n");
1324
if (io == -1 || dma == -1 || irq == -1) {
1325
printk(KERN_INFO "aedsp16: I/O, IRQ and DMA are mandatory\n");
1326
return -EINVAL;
1327
}
1328
1329
ae_config.base_io = io;
1330
ae_config.irq = irq;
1331
ae_config.dma = dma;
1332
1333
ae_config.mss_base = mss_base;
1334
ae_config.mpu_base = mpu_base;
1335
ae_config.mpu_irq = mpu_irq;
1336
1337
if (init_aedsp16() == FALSE) {
1338
printk(KERN_ERR "aedsp16: initialization failed\n");
1339
/*
1340
* XXX
1341
* What error should we return here ?
1342
*/
1343
return -EINVAL;
1344
}
1345
return 0;
1346
}
1347
1348
static void __exit cleanup_aedsp16(void) {
1349
uninit_aedsp16();
1350
}
1351
1352
module_init(do_init_aedsp16);
1353
module_exit(cleanup_aedsp16);
1354
1355
#ifndef MODULE
1356
static int __init setup_aedsp16(char *str)
1357
{
1358
/* io, irq, dma, mss_io, mpu_io, mpu_irq */
1359
int ints[7];
1360
1361
str = get_options(str, ARRAY_SIZE(ints), ints);
1362
1363
io = ints[1];
1364
irq = ints[2];
1365
dma = ints[3];
1366
mss_base = ints[4];
1367
mpu_base = ints[5];
1368
mpu_irq = ints[6];
1369
return 1;
1370
}
1371
1372
__setup("aedsp16=", setup_aedsp16);
1373
#endif
1374
1375