File: /usr/src/linux/drivers/sound/pas2_card.c

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