OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [sound/] [trix.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * sound/trix.c
3
 *
4
 * Low level driver for the MediaTrix AudioTrix Pro
5
 * (MT-0002-PC Control Chip)
6
 *
7
 *
8
 * Copyright (C) by Hannu Savolainen 1993-1997
9
 *
10
 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
11
 * Version 2 (June 1991). See the "COPYING" file distributed with this software
12
 * for more info.
13
 *
14
 * Changes
15
 *      Alan Cox                Modularisation, cleanup.
16
 *      Christoph Hellwig       Adapted to module_init/module_exit
17
 *      Arnaldo C. de Melo      Got rid of attach_uart401
18
 */
19
 
20
#include <linux/init.h>
21
#include <linux/module.h>
22
 
23
#include "sound_config.h"
24
#include "sb.h"
25
#include "sound_firmware.h"
26
 
27
#include "ad1848.h"
28
#include "mpu401.h"
29
 
30
#include "trix_boot.h"
31
 
32
static int kilroy_was_here = 0;  /* Don't detect twice */
33
static int sb_initialized = 0;
34
static int mpu_initialized = 0;
35
 
36
static int *trix_osp = NULL;
37
 
38
static int mpu = 0;
39
 
40
static int joystick=0;
41
 
42
static unsigned char trix_read(int addr)
43
{
44
        outb(((unsigned char) addr), 0x390);    /* MT-0002-PC ASIC address */
45
        return inb(0x391);      /* MT-0002-PC ASIC data */
46
}
47
 
48
static void trix_write(int addr, int data)
49
{
50
        outb(((unsigned char) addr), 0x390);    /* MT-0002-PC ASIC address */
51
        outb(((unsigned char) data), 0x391);    /* MT-0002-PC ASIC data */
52
}
53
 
54
static void download_boot(int base)
55
{
56
        int i = 0, n = trix_boot_len;
57
 
58
        if (trix_boot_len == 0)
59
                return;
60
 
61
        trix_write(0xf8, 0x00); /* ??????? */
62
        outb((0x01), base + 6); /* Clear the internal data pointer */
63
        outb((0x00), base + 6); /* Restart */
64
 
65
        /*
66
           *  Write the boot code to the RAM upload/download register.
67
           *  Each write increments the internal data pointer.
68
         */
69
        outb((0x01), base + 6); /* Clear the internal data pointer */
70
        outb((0x1A), 0x390);    /* Select RAM download/upload port */
71
 
72
        for (i = 0; i < n; i++)
73
                outb((trix_boot[i]), 0x391);
74
        for (i = n; i < 10016; i++)     /* Clear up to first 16 bytes of data RAM */
75
                outb((0x00), 0x391);
76
        outb((0x00), base + 6); /* Reset */
77
        outb((0x50), 0x390);    /* ?????? */
78
 
79
}
80
 
81
static int trix_set_wss_port(struct address_info *hw_config)
82
{
83
        unsigned char   addr_bits;
84
 
85
        if (check_region(0x390, 2))
86
        {
87
                printk(KERN_ERR "AudioTrix: Config port I/O conflict\n");
88
                return 0;
89
        }
90
        if (kilroy_was_here)    /* Already initialized */
91
                return 0;
92
 
93
        if (trix_read(0x15) != 0x71)    /* No ASIC signature */
94
        {
95
                MDB(printk(KERN_ERR "No AudioTrix ASIC signature found\n"));
96
                return 0;
97
        }
98
        kilroy_was_here = 1;
99
 
100
        /*
101
         * Reset some registers.
102
         */
103
 
104
        trix_write(0x13, 0);
105
        trix_write(0x14, 0);
106
 
107
        /*
108
         * Configure the ASIC to place the codec to the proper I/O location
109
         */
110
 
111
        switch (hw_config->io_base)
112
        {
113
                case 0x530:
114
                        addr_bits = 0;
115
                        break;
116
                case 0x604:
117
                        addr_bits = 1;
118
                        break;
119
                case 0xE80:
120
                        addr_bits = 2;
121
                        break;
122
                case 0xF40:
123
                        addr_bits = 3;
124
                        break;
125
                default:
126
                        return 0;
127
        }
128
 
129
        trix_write(0x19, (trix_read(0x19) & 0x03) | addr_bits);
130
        return 1;
131
}
132
 
133
/*
134
 *    Probe and attach routines for the Windows Sound System mode of
135
 *      AudioTrix Pro
136
 */
137
 
138
static int __init probe_trix_wss(struct address_info *hw_config)
139
{
140
        int ret;
141
 
142
        /*
143
         * Check if the IO port returns valid signature. The original MS Sound
144
         * system returns 0x04 while some cards (AudioTrix Pro for example)
145
         * return 0x00.
146
         */
147
        if (check_region(hw_config->io_base, 8))
148
        {
149
                printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base);
150
                return 0;
151
        }
152
        trix_osp = hw_config->osp;
153
 
154
        if (!trix_set_wss_port(hw_config))
155
                return 0;
156
 
157
        if ((inb(hw_config->io_base + 3) & 0x3f) != 0x00)
158
        {
159
                MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x\n", hw_config->io_base));
160
                return 0;
161
        }
162
        if (hw_config->irq > 11)
163
        {
164
                printk(KERN_ERR "AudioTrix: Bad WSS IRQ %d\n", hw_config->irq);
165
                return 0;
166
        }
167
        if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
168
        {
169
                printk(KERN_ERR "AudioTrix: Bad WSS DMA %d\n", hw_config->dma);
170
                return 0;
171
        }
172
        if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
173
                if (hw_config->dma2 != 0 && hw_config->dma2 != 1 && hw_config->dma2 != 3)
174
                {
175
                          printk(KERN_ERR "AudioTrix: Bad capture DMA %d\n", hw_config->dma2);
176
                          return 0;
177
                }
178
        /*
179
         * Check that DMA0 is not in use with a 8 bit board.
180
         */
181
 
182
        if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80)
183
        {
184
                printk(KERN_ERR "AudioTrix: Can't use DMA0 with a 8 bit card slot\n");
185
                return 0;
186
        }
187
        if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80)
188
        {
189
                printk(KERN_ERR "AudioTrix: Can't use IRQ%d with a 8 bit card slot\n", hw_config->irq);
190
                return 0;
191
        }
192
        ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
193
 
194
        if (ret)
195
        {
196
                if(joystick==1)
197
                        trix_write(0x15, 0x80);
198
                request_region(0x390, 2, "AudioTrix");
199
        }
200
        return ret;
201
}
202
 
203
static void __init attach_trix_wss(struct address_info *hw_config)
204
{
205
        static unsigned char interrupt_bits[12] = {
206
                0, 0, 0, 0, 0, 0, 0, 0x08, 0, 0x10, 0x18, 0x20
207
        };
208
        char bits;
209
 
210
        static unsigned char dma_bits[4] = {
211
                1, 2, 0, 3
212
        };
213
 
214
        int config_port = hw_config->io_base + 0;
215
        int dma1 = hw_config->dma, dma2 = hw_config->dma2;
216
        int old_num_mixers = num_mixers;
217
 
218
        trix_osp = hw_config->osp;
219
 
220
        if (!kilroy_was_here)
221
        {
222
                DDB(printk("AudioTrix: Attach called but not probed yet???\n"));
223
                return;
224
        }
225
 
226
        /*
227
         * Set the IRQ and DMA addresses.
228
         */
229
 
230
        bits = interrupt_bits[hw_config->irq];
231
        if (bits == 0)
232
        {
233
                printk("AudioTrix: Bad IRQ (%d)\n", hw_config->irq);
234
                return;
235
        }
236
        outb((bits | 0x40), config_port);
237
 
238
        if (hw_config->dma2 == -1 || hw_config->dma2 == hw_config->dma)
239
        {
240
                  bits |= dma_bits[dma1];
241
                  dma2 = dma1;
242
        }
243
        else
244
        {
245
                unsigned char tmp;
246
 
247
                tmp = trix_read(0x13) & ~30;
248
                trix_write(0x13, tmp | 0x80 | (dma1 << 4));
249
 
250
                tmp = trix_read(0x14) & ~30;
251
                trix_write(0x14, tmp | 0x80 | (dma2 << 4));
252
        }
253
 
254
        outb((bits), config_port);      /* Write IRQ+DMA setup */
255
 
256
        hw_config->slots[0] = ad1848_init("AudioTrix Pro", hw_config->io_base + 4,
257
                                          hw_config->irq,
258
                                          dma1,
259
                                          dma2,
260
                                          0,
261
                                          hw_config->osp,
262
                                          THIS_MODULE);
263
        request_region(hw_config->io_base, 4, "MSS config");
264
 
265
        if (num_mixers > old_num_mixers)        /* Mixer got installed */
266
        {
267
                AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE);    /* Line in */
268
                AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD);
269
                AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH);           /* OPL4 */
270
                AD1848_REROUTE(SOUND_MIXER_SPEAKER, SOUND_MIXER_ALTPCM);        /* SB */
271
        }
272
}
273
 
274
static int __init probe_trix_sb(struct address_info *hw_config)
275
{
276
 
277
        int tmp;
278
        unsigned char conf;
279
        static signed char irq_translate[] = {
280
                -1, -1, -1, 0, 1, 2, -1, 3
281
        };
282
 
283
        if (trix_boot_len == 0)
284
                return 0;        /* No boot code -> no fun */
285
 
286
        if (!kilroy_was_here)
287
                return 0;        /* AudioTrix Pro has not been detected earlier */
288
 
289
        if (sb_initialized)
290
                return 0;
291
 
292
        if (check_region(hw_config->io_base, 16))
293
        {
294
                printk(KERN_ERR "AudioTrix: SB I/O port conflict (%x)\n", hw_config->io_base);
295
                return 0;
296
        }
297
        if ((hw_config->io_base & 0xffffff8f) != 0x200)
298
                return 0;
299
 
300
        tmp = hw_config->irq;
301
        if (tmp > 7)
302
                return 0;
303
        if (irq_translate[tmp] == -1)
304
                return 0;
305
 
306
        tmp = hw_config->dma;
307
        if (tmp != 1 && tmp != 3)
308
                return 0;
309
 
310
        conf = 0x84;            /* DMA and IRQ enable */
311
        conf |= hw_config->io_base & 0x70;      /* I/O address bits */
312
        conf |= irq_translate[hw_config->irq];
313
        if (hw_config->dma == 3)
314
                conf |= 0x08;
315
        trix_write(0x1b, conf);
316
 
317
        download_boot(hw_config->io_base);
318
        sb_initialized = 1;
319
 
320
        hw_config->name = "AudioTrix SB";
321
        return sb_dsp_detect(hw_config, 0, 0, NULL);
322
}
323
 
324
static void __init attach_trix_sb(struct address_info *hw_config)
325
{
326
        extern int sb_be_quiet;
327
        int old_quiet;
328
 
329
        hw_config->driver_use_1 = SB_NO_MIDI | SB_NO_MIXER | SB_NO_RECORDING;
330
 
331
        /* Prevent false alarms */
332
        old_quiet = sb_be_quiet;
333
        sb_be_quiet = 1;
334
 
335
        sb_dsp_init(hw_config, THIS_MODULE);
336
 
337
        sb_be_quiet = old_quiet;
338
}
339
 
340
static int __init probe_trix_mpu(struct address_info *hw_config)
341
{
342
        unsigned char conf;
343
        static int irq_bits[] = {
344
                -1, -1, -1, 1, 2, 3, -1, 4, -1, 5
345
        };
346
 
347
        if (!kilroy_was_here)
348
        {
349
                DDB(printk("Trix: WSS and SB modes must be initialized before MPU\n"));
350
                return 0;        /* AudioTrix Pro has not been detected earlier */
351
        }
352
        if (!sb_initialized)
353
        {
354
                DDB(printk("Trix: SB mode must be initialized before MPU\n"));
355
                return 0;
356
        }
357
        if (mpu_initialized)
358
        {
359
                DDB(printk("Trix: MPU mode already initialized\n"));
360
                return 0;
361
        }
362
        if (hw_config->irq > 9)
363
        {
364
                printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq);
365
                return 0;
366
        }
367
        if (irq_bits[hw_config->irq] == -1)
368
        {
369
                printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq);
370
                return 0;
371
        }
372
        switch (hw_config->io_base)
373
        {
374
                case 0x330:
375
                        conf = 0x00;
376
                        break;
377
                case 0x370:
378
                        conf = 0x04;
379
                        break;
380
                case 0x3b0:
381
                        conf = 0x08;
382
                        break;
383
                case 0x3f0:
384
                        conf = 0x0c;
385
                        break;
386
                default:
387
                        return 0;        /* Invalid port */
388
        }
389
 
390
        conf |= irq_bits[hw_config->irq] << 4;
391
        trix_write(0x19, (trix_read(0x19) & 0x83) | conf);
392
        mpu_initialized = 1;
393
        hw_config->name = "AudioTrix Pro";
394
        return probe_uart401(hw_config, THIS_MODULE);
395
}
396
 
397
static void __exit unload_trix_wss(struct address_info *hw_config)
398
{
399
        int dma2 = hw_config->dma2;
400
 
401
        if (dma2 == -1)
402
                dma2 = hw_config->dma;
403
 
404
        release_region(0x390, 2);
405
        release_region(hw_config->io_base, 4);
406
 
407
        ad1848_unload(hw_config->io_base + 4,
408
                      hw_config->irq,
409
                      hw_config->dma,
410
                      dma2,
411
                      0);
412
        sound_unload_audiodev(hw_config->slots[0]);
413
}
414
 
415
static inline void __exit unload_trix_mpu(struct address_info *hw_config)
416
{
417
        unload_uart401(hw_config);
418
}
419
 
420
static inline void __exit unload_trix_sb(struct address_info *hw_config)
421
{
422
        sb_dsp_unload(hw_config, mpu);
423
}
424
 
425
static struct address_info cfg;
426
static struct address_info cfg2;
427
static struct address_info cfg_mpu;
428
 
429
static int sb = 0;
430
static int fw_load;
431
 
432
static int __initdata io        = -1;
433
static int __initdata irq       = -1;
434
static int __initdata dma       = -1;
435
static int __initdata dma2      = -1;   /* Set this for modules that need it */
436
static int __initdata sb_io     = -1;
437
static int __initdata sb_dma    = -1;
438
static int __initdata sb_irq    = -1;
439
static int __initdata mpu_io    = -1;
440
static int __initdata mpu_irq   = -1;
441
 
442
MODULE_PARM(io,"i");
443
MODULE_PARM(irq,"i");
444
MODULE_PARM(dma,"i");
445
MODULE_PARM(dma2,"i");
446
MODULE_PARM(sb_io,"i");
447
MODULE_PARM(sb_dma,"i");
448
MODULE_PARM(sb_irq,"i");
449
MODULE_PARM(mpu_io,"i");
450
MODULE_PARM(mpu_irq,"i");
451
MODULE_PARM(joystick, "i");
452
 
453
static int __init init_trix(void)
454
{
455
        printk(KERN_INFO "MediaTrix audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
456
 
457
        cfg.io_base = io;
458
        cfg.irq = irq;
459
        cfg.dma = dma;
460
        cfg.dma2 = dma2;
461
 
462
        cfg2.io_base = sb_io;
463
        cfg2.irq = sb_irq;
464
        cfg2.dma = sb_dma;
465
 
466
        cfg_mpu.io_base = mpu_io;
467
        cfg_mpu.irq = mpu_irq;
468
 
469
        if (cfg.io_base == -1 || cfg.dma == -1 || cfg.irq == -1) {
470
                printk(KERN_INFO "I/O, IRQ, DMA and type are mandatory\n");
471
                return -EINVAL;
472
        }
473
 
474
        if (cfg2.io_base != -1 && (cfg2.irq == -1 || cfg2.dma == -1)) {
475
                printk(KERN_INFO "CONFIG_SB_IRQ and CONFIG_SB_DMA must be specified if SB_IO is set.\n");
476
                return -EINVAL;
477
        }
478
        if (cfg_mpu.io_base != -1 && cfg_mpu.irq == -1) {
479
                printk(KERN_INFO "CONFIG_MPU_IRQ must be specified if MPU_IO is set.\n");
480
                return -EINVAL;
481
        }
482
        if (!trix_boot)
483
        {
484
                fw_load = 1;
485
                trix_boot_len = mod_firmware_load("/etc/sound/trxpro.bin",
486
                                                    (char **) &trix_boot);
487
        }
488
        if (!probe_trix_wss(&cfg))
489
                return -ENODEV;
490
        attach_trix_wss(&cfg);
491
 
492
        /*
493
         *    We must attach in the right order to get the firmware
494
         *      loaded up in time.
495
         */
496
 
497
        if (cfg2.io_base != -1) {
498
                sb = probe_trix_sb(&cfg2);
499
                if (sb)
500
                        attach_trix_sb(&cfg2);
501
        }
502
 
503
        if (cfg_mpu.io_base != -1)
504
                mpu = probe_trix_mpu(&cfg_mpu);
505
 
506
        return 0;
507
}
508
 
509
static void __exit cleanup_trix(void)
510
{
511
        if (fw_load && trix_boot)
512
                vfree(trix_boot);
513
        if (sb)
514
                unload_trix_sb(&cfg2);
515
        if (mpu)
516
                unload_trix_mpu(&cfg_mpu);
517
        unload_trix_wss(&cfg);
518
}
519
 
520
module_init(init_trix);
521
module_exit(cleanup_trix);
522
 
523
#ifndef MODULE
524
static int __init setup_trix (char *str)
525
{
526
        /* io, irq, dma, dma2, sb_io, sb_irq, sb_dma, mpu_io, mpu_irq */
527
        int ints[9];
528
 
529
        str = get_options(str, ARRAY_SIZE(ints), ints);
530
 
531
        io      = ints[1];
532
        irq     = ints[2];
533
        dma     = ints[3];
534
        dma2    = ints[4];
535
        sb_io   = ints[5];
536
        sb_irq  = ints[6];
537
        sb_dma  = ints[6];
538
        mpu_io  = ints[7];
539
        mpu_irq = ints[8];
540
 
541
        return 1;
542
}
543
 
544
__setup("trix=", setup_trix);
545
#endif
546
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.