4 * Detection routine for the Pro Audio Spectrum cards.
6 * Copyright by Hannu Savolainen 1993
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met: 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 2.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <i386/isa/sound/sound_config.h>
31 #if defined(CONFIG_PAS)
34 #define DEFINE_TRANSLATIONS
35 #include <i386/isa/sound/pas_hw.h>
38 * The Address Translation code is used to convert I/O register addresses to
39 * be relative to the given base -register
43 static int pas_intr_mask = 0;
44 static int pas_irq = 0;
46 static sound_os_info *pas_osp;
49 static char *pas_model_names[] =
50 {"", "Pro AudioSpectrum+", "CDPC", "Pro AudioSpectrum 16", "Pro AudioSpectrum 16D"};
53 * pas_read() and pas_write() are equivalents of inb and outb
56 * These routines perform the I/O address translation required
59 * to support other than the default base address
61 extern void mix_write(u_char data, int ioaddr);
66 return inb(ioaddr ^ translat_code);
70 pas_write(u_char data, int ioaddr)
72 outb(ioaddr ^ translat_code, data);
78 printf(" PAS2: %s.\n", foo);
81 /******************* Begin of the Interrupt Handler ********************/
88 status = pas_read(INTERRUPT_STATUS);
89 pas_write(status, INTERRUPT_STATUS); /* Clear interrupt */
91 if (status & I_S_PCM_SAMPLE_BUFFER_IRQ) {
93 pas_pcm_interrupt(status, 1);
95 status &= ~I_S_PCM_SAMPLE_BUFFER_IRQ;
97 if (status & I_S_MIDI_IRQ) {
101 status &= ~I_S_MIDI_IRQ;
106 pas_set_intr(int mask)
111 pas_intr_mask |= mask;
113 pas_write(pas_intr_mask, INTERRUPT_MASK);
118 pas_remove_intr(int mask)
123 pas_intr_mask &= ~mask;
124 pas_write(pas_intr_mask, INTERRUPT_MASK);
129 /******************* End of the Interrupt handler **********************/
131 /******************* Begin of the Initialization Code ******************/
134 config_pas_hw(struct address_info * hw_config)
137 u_int int_ptrs; /* scsi/sound interrupt pointers */
139 pas_irq = hw_config->irq;
141 pas_write(0x00, INTERRUPT_MASK);
143 pas_write(0x36, SAMPLE_COUNTER_CONTROL); /* Local timer control *
146 pas_write(0x36, SAMPLE_RATE_TIMER); /* Sample rate timer (16 bit) */
147 pas_write(0, SAMPLE_RATE_TIMER);
149 pas_write(0x74, SAMPLE_COUNTER_CONTROL); /* Local timer control *
152 pas_write(0x74, SAMPLE_BUFFER_COUNTER); /* Sample count register (16 *
154 pas_write(0, SAMPLE_BUFFER_COUNTER);
156 pas_write(F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER | F_F_MIXER_UNMUTE | 1, FILTER_FREQUENCY);
157 pas_write(P_C_PCM_DMA_ENABLE | P_C_PCM_MONO | P_C_PCM_DAC_MODE | P_C_MIXER_CROSS_L_TO_L | P_C_MIXER_CROSS_R_TO_R, PCM_CONTROL);
158 pas_write(S_M_PCM_RESET | S_M_FM_RESET | S_M_SB_RESET | S_M_MIXER_RESET /* | S_M_OPL3_DUAL_MONO */ , SERIAL_MIXER);
160 pas_write(I_C_1_BOOT_RESET_ENABLE
161 #ifdef PAS_JOYSTICK_ENABLE
162 | I_C_1_JOYSTICK_ENABLE
164 ,IO_CONFIGURATION_1);
166 if (pas_irq < 0 || pas_irq > 15) {
167 printf("PAS2: Invalid IRQ %d", pas_irq);
170 int_ptrs = pas_read(IO_CONFIGURATION_3);
171 int_ptrs |= I_C_3_PCM_IRQ_translate[pas_irq] & 0xf;
172 pas_write(int_ptrs, IO_CONFIGURATION_3);
173 if (!I_C_3_PCM_IRQ_translate[pas_irq]) {
174 printf("PAS2: Invalid IRQ %d", pas_irq);
177 if (snd_set_irq_handler(pas_irq, pasintr, hw_config->osp) < 0)
182 if (hw_config->dma < 0 || hw_config->dma > 7) {
183 printf("PAS2: Invalid DMA selection %d", hw_config->dma);
186 pas_write(I_C_2_PCM_DMA_translate[hw_config->dma], IO_CONFIGURATION_2);
187 if (!I_C_2_PCM_DMA_translate[hw_config->dma]) {
188 printf("PAS2: Invalid DMA selection %d", hw_config->dma);
192 printf("pas2_card.c: Can't allocate DMA channel\n");
199 * This fixes the timing problems of the PAS due to the Symphony
200 * chipset as per Media Vision. Only define this if your PAS doesn't
208 #ifdef BROKEN_BUS_CLOCK
209 pas_write(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND | S_C_1_FM_EMULATE_CLOCK, SYSTEM_CONFIGURATION_1);
212 * pas_write(S_C_1_PCS_ENABLE, SYSTEM_CONFIGURATION_1);
214 pas_write(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND, SYSTEM_CONFIGURATION_1);
216 pas_write(0x18, SYSTEM_CONFIGURATION_3); /* ??? */
218 pas_write(F_F_MIXER_UNMUTE | 0x01, FILTER_FREQUENCY); /* Sets mute off and *
219 * selects filter rate *
221 pas_write(8, PRESCALE_DIVIDER);
223 mix_write(P_M_MV508_ADDRESS | 5, PARALLEL_MIXER);
224 mix_write(5, PARALLEL_MIXER);
226 #if defined(CONFIG_SB_EMULATION) && defined(CONFIG_SB)
229 struct address_info *sb_config;
231 if ((sb_config = sound_getconf(SNDCARD_SB))) {
235 * Turn on Sound Blaster compatibility
238 * bit 1 = SB emulation
241 * bit 0 = MPU401 emulation (CDPC only :-( )
243 pas_write(0x02, COMPATIBILITY_ENABLE);
246 * "Emulation address"
248 pas_write((sb_config->io_base >> 4) & 0x0f, EMULATION_ADDRESS);
250 if (!E_C_SB_DMA_translate[sb_config->dma])
251 printf("\n\nPAS16 Warning: Invalid SB DMA %d\n\n",
254 if (!E_C_SB_IRQ_translate[sb_config->irq])
255 printf("\n\nPAS16 Warning: Invalid SB IRQ %d\n\n",
258 irq_dma = E_C_SB_DMA_translate[sb_config->dma] |
259 E_C_SB_IRQ_translate[sb_config->irq];
261 pas_write(irq_dma, EMULATION_CONFIGURATION);
265 pas_write(0x00, COMPATIBILITY_ENABLE);
269 pas2_msg("Driver not enabled");
275 detect_pas_hw(struct address_info * hw_config)
277 u_char board_id, foo;
280 * WARNING: Setting an option like W:1 or so that disables warm boot
281 * reset of the card will screw up this detect code something fierce.
282 * Adding code to handle this means possibly interfering with other
283 * cards on the bus if you have something on base port 0x388. SO be
287 outb(MASTER_DECODE, 0xBC); /* Talk to first board */
288 outb(MASTER_DECODE, hw_config->io_base >> 2); /* Set base address */
289 translat_code = PAS_DEFAULT_BASE ^ hw_config->io_base;
290 pas_write(1, WAIT_STATE); /* One wait-state */
292 board_id = pas_read(INTERRUPT_MASK);
294 if (board_id == 0xff)
298 * We probably have a PAS-series board, now check for a PAS2-series
299 * board by trying to change the board revision bits. PAS2-series
300 * hardware won't let you do this - the bits are read-only.
303 foo = board_id ^ 0xe0;
305 pas_write(foo, INTERRUPT_MASK);
306 foo = inb(INTERRUPT_MASK);
307 pas_write(board_id, INTERRUPT_MASK);
309 if (board_id != foo) /* Not a PAS2 */
312 pas_model = pas_read(CHIP_REV);
318 attach_pas_card(struct address_info * hw_config)
320 pas_irq = hw_config->irq;
321 pas_osp = hw_config->osp;
323 if (detect_pas_hw(hw_config)) {
325 if ((pas_model = pas_read(CHIP_REV))) {
328 snprintf(temp, sizeof(temp),
329 "%s rev %d", pas_model_names[(int) pas_model],
330 pas_read(BOARD_REV_ID));
331 conf_printf(temp, hw_config);
333 if (config_pas_hw(hw_config)) {
336 pas_pcm_init(hw_config);
339 #if defined(CONFIG_SB_EMULATION) && defined(CONFIG_SB)
341 sb_dsp_disable_midi(); /* The SB emulation don't
355 probe_pas(struct address_info * hw_config)
357 pas_osp = hw_config->osp;
358 return detect_pas_hw(hw_config);