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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [sound/] [oss/] [pas2_card.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * sound/oss/pas2_card.c
3
 *
4
 * Detection routine for the Pro Audio Spectrum cards.
5
 */
6
 
7
#include <linux/init.h>
8
#include <linux/interrupt.h>
9
#include <linux/module.h>
10
#include <linux/spinlock.h>
11
#include "sound_config.h"
12
 
13
#include "pas2.h"
14
#include "sb.h"
15
 
16
static unsigned char dma_bits[] = {
17
        4, 1, 2, 3, 0, 5, 6, 7
18
};
19
 
20
static unsigned char irq_bits[] = {
21
        0, 0, 1, 2, 3, 4, 5, 6, 0, 1, 7, 8, 9, 0, 10, 11
22
};
23
 
24
static unsigned char sb_irq_bits[] = {
25
        0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x00, 0x20,
26
        0x00, 0x08, 0x28, 0x30, 0x38, 0, 0
27
};
28
 
29
static unsigned char sb_dma_bits[] = {
30
        0x00, 0x40, 0x80, 0xC0, 0, 0, 0, 0
31
};
32
 
33
/*
34
 * The Address Translation code is used to convert I/O register addresses to
35
 * be relative to the given base -register
36
 */
37
 
38
int             pas_translate_code = 0;
39
static int      pas_intr_mask;
40
static int      pas_irq;
41
static int      pas_sb_base;
42
DEFINE_SPINLOCK(pas_lock);
43
#ifndef CONFIG_PAS_JOYSTICK
44
static int      joystick;
45
#else
46
static int      joystick = 1;
47
#endif
48
#ifdef SYMPHONY_PAS
49
static int      symphony = 1;
50
#else
51
static int      symphony;
52
#endif
53
#ifdef BROKEN_BUS_CLOCK
54
static int      broken_bus_clock = 1;
55
#else
56
static int      broken_bus_clock;
57
#endif
58
 
59
static struct address_info cfg;
60
static struct address_info cfg2;
61
 
62
char            pas_model = 0;
63
static char    *pas_model_names[] = {
64
        "",
65
        "Pro AudioSpectrum+",
66
        "CDPC",
67
        "Pro AudioSpectrum 16",
68
        "Pro AudioSpectrum 16D"
69
};
70
 
71
/*
72
 * pas_read() and pas_write() are equivalents of inb and outb
73
 * These routines perform the I/O address translation required
74
 * to support other than the default base address
75
 */
76
 
77
extern void     mix_write(unsigned char data, int ioaddr);
78
 
79
unsigned char pas_read(int ioaddr)
80
{
81
        return inb(ioaddr + pas_translate_code);
82
}
83
 
84
void pas_write(unsigned char data, int ioaddr)
85
{
86
        outb((data), ioaddr + pas_translate_code);
87
}
88
 
89
/******************* Begin of the Interrupt Handler ********************/
90
 
91
static irqreturn_t pasintr(int irq, void *dev_id)
92
{
93
        int             status;
94
 
95
        status = pas_read(0x0B89);
96
        pas_write(status, 0x0B89);      /* Clear interrupt */
97
 
98
        if (status & 0x08)
99
        {
100
                  pas_pcm_interrupt(status, 1);
101
                  status &= ~0x08;
102
        }
103
        if (status & 0x10)
104
        {
105
                  pas_midi_interrupt();
106
                  status &= ~0x10;
107
        }
108
        return IRQ_HANDLED;
109
}
110
 
111
int pas_set_intr(int mask)
112
{
113
        if (!mask)
114
                return 0;
115
 
116
        pas_intr_mask |= mask;
117
 
118
        pas_write(pas_intr_mask, 0x0B8B);
119
        return 0;
120
}
121
 
122
int pas_remove_intr(int mask)
123
{
124
        if (!mask)
125
                return 0;
126
 
127
        pas_intr_mask &= ~mask;
128
        pas_write(pas_intr_mask, 0x0B8B);
129
 
130
        return 0;
131
}
132
 
133
/******************* End of the Interrupt handler **********************/
134
 
135
/******************* Begin of the Initialization Code ******************/
136
 
137
static int __init config_pas_hw(struct address_info *hw_config)
138
{
139
        char            ok = 1;
140
        unsigned        int_ptrs;       /* scsi/sound interrupt pointers */
141
 
142
        pas_irq = hw_config->irq;
143
 
144
        pas_write(0x00, 0x0B8B);
145
        pas_write(0x36, 0x138B);
146
        pas_write(0x36, 0x1388);
147
        pas_write(0, 0x1388);
148
        pas_write(0x74, 0x138B);
149
        pas_write(0x74, 0x1389);
150
        pas_write(0, 0x1389);
151
 
152
        pas_write(0x80 | 0x40 | 0x20 | 1, 0x0B8A);
153
        pas_write(0x80 | 0x20 | 0x10 | 0x08 | 0x01, 0xF8A);
154
        pas_write(0x01 | 0x02 | 0x04 | 0x10     /*
155
                                                 * |
156
                                                 * 0x80
157
                                                 */ , 0xB88);
158
 
159
        pas_write(0x80
160
                  | joystick?0x40:0
161
                  ,0xF388);
162
 
163
        if (pas_irq < 0 || pas_irq > 15)
164
        {
165
                printk(KERN_ERR "PAS16: Invalid IRQ %d", pas_irq);
166
                hw_config->irq=-1;
167
                ok = 0;
168
        }
169
        else
170
        {
171
                int_ptrs = pas_read(0xF38A);
172
                int_ptrs = (int_ptrs & 0xf0) | irq_bits[pas_irq];
173
                pas_write(int_ptrs, 0xF38A);
174
                if (!irq_bits[pas_irq])
175
                {
176
                        printk(KERN_ERR "PAS16: Invalid IRQ %d", pas_irq);
177
                        hw_config->irq=-1;
178
                        ok = 0;
179
                }
180
                else
181
                {
182
                        if (request_irq(pas_irq, pasintr, 0, "PAS16",hw_config) < 0) {
183
                                printk(KERN_ERR "PAS16: Cannot allocate IRQ %d\n",pas_irq);
184
                                hw_config->irq=-1;
185
                                ok = 0;
186
                        }
187
                }
188
        }
189
 
190
        if (hw_config->dma < 0 || hw_config->dma > 7)
191
        {
192
                printk(KERN_ERR "PAS16: Invalid DMA selection %d", hw_config->dma);
193
                hw_config->dma=-1;
194
                ok = 0;
195
        }
196
        else
197
        {
198
                pas_write(dma_bits[hw_config->dma], 0xF389);
199
                if (!dma_bits[hw_config->dma])
200
                {
201
                        printk(KERN_ERR "PAS16: Invalid DMA selection %d", hw_config->dma);
202
                        hw_config->dma=-1;
203
                        ok = 0;
204
                }
205
                else
206
                {
207
                        if (sound_alloc_dma(hw_config->dma, "PAS16"))
208
                        {
209
                                printk(KERN_ERR "pas2_card.c: Can't allocate DMA channel\n");
210
                                hw_config->dma=-1;
211
                                ok = 0;
212
                        }
213
                }
214
        }
215
 
216
        /*
217
         * This fixes the timing problems of the PAS due to the Symphony chipset
218
         * as per Media Vision.  Only define this if your PAS doesn't work correctly.
219
         */
220
 
221
        if(symphony)
222
        {
223
                outb((0x05), 0xa8);
224
                outb((0x60), 0xa9);
225
        }
226
 
227
        if(broken_bus_clock)
228
                pas_write(0x01 | 0x10 | 0x20 | 0x04, 0x8388);
229
        else
230
                /*
231
                 * pas_write(0x01, 0x8388);
232
                 */
233
                pas_write(0x01 | 0x10 | 0x20, 0x8388);
234
 
235
        pas_write(0x18, 0x838A);        /* ??? */
236
        pas_write(0x20 | 0x01, 0x0B8A);         /* Mute off, filter = 17.897 kHz */
237
        pas_write(8, 0xBF8A);
238
 
239
        mix_write(0x80 | 5, 0x078B);
240
        mix_write(5, 0x078B);
241
 
242
        {
243
                struct address_info *sb_config;
244
 
245
                sb_config = &cfg2;
246
                if (sb_config->io_base)
247
                {
248
                        unsigned char   irq_dma;
249
 
250
                        /*
251
                         * Turn on Sound Blaster compatibility
252
                         * bit 1 = SB emulation
253
                         * bit 0 = MPU401 emulation (CDPC only :-( )
254
                         */
255
 
256
                        pas_write(0x02, 0xF788);
257
 
258
                        /*
259
                         * "Emulation address"
260
                         */
261
 
262
                        pas_write((sb_config->io_base >> 4) & 0x0f, 0xF789);
263
                        pas_sb_base = sb_config->io_base;
264
 
265
                        if (!sb_dma_bits[sb_config->dma])
266
                                printk(KERN_ERR "PAS16 Warning: Invalid SB DMA %d\n\n", sb_config->dma);
267
 
268
                        if (!sb_irq_bits[sb_config->irq])
269
                                printk(KERN_ERR "PAS16 Warning: Invalid SB IRQ %d\n\n", sb_config->irq);
270
 
271
                        irq_dma = sb_dma_bits[sb_config->dma] |
272
                                sb_irq_bits[sb_config->irq];
273
 
274
                        pas_write(irq_dma, 0xFB8A);
275
                }
276
                else
277
                        pas_write(0x00, 0xF788);
278
        }
279
 
280
        if (!ok)
281
                printk(KERN_WARNING "PAS16: Driver not enabled\n");
282
 
283
        return ok;
284
}
285
 
286
static int __init detect_pas_hw(struct address_info *hw_config)
287
{
288
        unsigned char   board_id, foo;
289
 
290
        /*
291
         * WARNING: Setting an option like W:1 or so that disables warm boot reset
292
         * of the card will screw up this detect code something fierce. Adding code
293
         * to handle this means possibly interfering with other cards on the bus if
294
         * you have something on base port 0x388. SO be forewarned.
295
         */
296
 
297
        outb((0xBC), 0x9A01);   /* Activate first board */
298
        outb((hw_config->io_base >> 2), 0x9A01);        /* Set base address */
299
        pas_translate_code = hw_config->io_base - 0x388;
300
        pas_write(1, 0xBF88);   /* Select one wait states */
301
 
302
        board_id = pas_read(0x0B8B);
303
 
304
        if (board_id == 0xff)
305
                return 0;
306
 
307
        /*
308
         * We probably have a PAS-series board, now check for a PAS16-series board
309
         * by trying to change the board revision bits. PAS16-series hardware won't
310
         * let you do this - the bits are read-only.
311
         */
312
 
313
        foo = board_id ^ 0xe0;
314
 
315
        pas_write(foo, 0x0B8B);
316
        foo = pas_read(0x0B8B);
317
        pas_write(board_id, 0x0B8B);
318
 
319
        if (board_id != foo)
320
                return 0;
321
 
322
        pas_model = pas_read(0xFF88);
323
 
324
        return pas_model;
325
}
326
 
327
static void __init attach_pas_card(struct address_info *hw_config)
328
{
329
        pas_irq = hw_config->irq;
330
 
331
        if (detect_pas_hw(hw_config))
332
        {
333
 
334
                if ((pas_model = pas_read(0xFF88)))
335
                {
336
                        char            temp[100];
337
 
338
                        sprintf(temp,
339
                            "%s rev %d", pas_model_names[(int) pas_model],
340
                                    pas_read(0x2789));
341
                        conf_printf(temp, hw_config);
342
                }
343
                if (config_pas_hw(hw_config))
344
                {
345
                        pas_pcm_init(hw_config);
346
                        pas_midi_init();
347
                        pas_init_mixer();
348
                }
349
        }
350
}
351
 
352
static inline int __init probe_pas(struct address_info *hw_config)
353
{
354
        return detect_pas_hw(hw_config);
355
}
356
 
357
static void __exit unload_pas(struct address_info *hw_config)
358
{
359
        extern int pas_audiodev;
360
        extern int pas2_mididev;
361
 
362
        if (hw_config->dma>0)
363
                sound_free_dma(hw_config->dma);
364
        if (hw_config->irq>0)
365
                free_irq(hw_config->irq, hw_config);
366
 
367
        if(pas_audiodev!=-1)
368
                sound_unload_mixerdev(audio_devs[pas_audiodev]->mixer_dev);
369
        if(pas2_mididev!=-1)
370
                sound_unload_mididev(pas2_mididev);
371
        if(pas_audiodev!=-1)
372
                sound_unload_audiodev(pas_audiodev);
373
}
374
 
375
static int __initdata io        = -1;
376
static int __initdata irq       = -1;
377
static int __initdata dma       = -1;
378
static int __initdata dma16     = -1;   /* Set this for modules that need it */
379
 
380
static int __initdata sb_io     = 0;
381
static int __initdata sb_irq    = -1;
382
static int __initdata sb_dma    = -1;
383
static int __initdata sb_dma16  = -1;
384
 
385
module_param(io, int, 0);
386
module_param(irq, int, 0);
387
module_param(dma, int, 0);
388
module_param(dma16, int, 0);
389
 
390
module_param(sb_io, int, 0);
391
module_param(sb_irq, int, 0);
392
module_param(sb_dma, int, 0);
393
module_param(sb_dma16, int, 0);
394
 
395
module_param(joystick, bool, 0);
396
module_param(symphony, bool, 0);
397
module_param(broken_bus_clock, bool, 0);
398
 
399
MODULE_LICENSE("GPL");
400
 
401
static int __init init_pas2(void)
402
{
403
        printk(KERN_INFO "Pro Audio Spectrum driver Copyright (C) by Hannu Savolainen 1993-1996\n");
404
 
405
        cfg.io_base = io;
406
        cfg.irq = irq;
407
        cfg.dma = dma;
408
        cfg.dma2 = dma16;
409
 
410
        cfg2.io_base = sb_io;
411
        cfg2.irq = sb_irq;
412
        cfg2.dma = sb_dma;
413
        cfg2.dma2 = sb_dma16;
414
 
415
        if (cfg.io_base == -1 || cfg.dma == -1 || cfg.irq == -1) {
416
                printk(KERN_INFO "I/O, IRQ, DMA and type are mandatory\n");
417
                return -EINVAL;
418
        }
419
 
420
        if (!probe_pas(&cfg))
421
                return -ENODEV;
422
        attach_pas_card(&cfg);
423
 
424
        return 0;
425
}
426
 
427
static void __exit cleanup_pas2(void)
428
{
429
        unload_pas(&cfg);
430
}
431
 
432
module_init(init_pas2);
433
module_exit(cleanup_pas2);
434
 
435
#ifndef MODULE
436
static int __init setup_pas2(char *str)
437
{
438
        /* io, irq, dma, dma2, sb_io, sb_irq, sb_dma, sb_dma2 */
439
        int ints[9];
440
 
441
        str = get_options(str, ARRAY_SIZE(ints), ints);
442
 
443
        io      = ints[1];
444
        irq     = ints[2];
445
        dma     = ints[3];
446
        dma16   = ints[4];
447
 
448
        sb_io   = ints[5];
449
        sb_irq  = ints[6];
450
        sb_dma  = ints[7];
451
        sb_dma16 = ints[8];
452
 
453
        return 1;
454
}
455
 
456
__setup("pas2=", setup_pas2);
457
#endif

powered by: WebSVN 2.1.0

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