void set_mode (int new_mode) { pas_write (P_M_MV508_ADDRESS | P_M_MV508_MODE, PARALLEL_MIXER); pas_write (new_mode, PARALLEL_MIXER); mode_control = new_mode; }
int pas_remove_intr(int mask) { if (!mask) return 0; pas_intr_mask &= ~mask; pas_write(pas_intr_mask, 0x0B8B); return 0; }
int pas_set_intr(int mask) { if (!mask) return 0; pas_intr_mask |= mask; pas_write(pas_intr_mask, 0x0B8B); return 0; }
int pas_remove_intr(int mask) { if (!mask) return 0; pas_intr_mask &= ~mask; pas_write(pas_intr_mask, INTERRUPT_MASK); return 0; }
int pas_set_intr(int mask) { if (!mask) return 0; pas_intr_mask |= mask; pas_write(pas_intr_mask, INTERRUPT_MASK); return 0; }
/* * This sets aspects of the Mixer that are not volume levels. (Recording * source, filter level, I/O filtering, and stereo.) */ static int mixer_set_params (struct sb_mixer_params *user_p) { struct sb_mixer_params p; S_BYTE val; int src; unsigned long flags; IOCTL_FROM_USER ((char *) &p, (char *) user_p, 0, sizeof (p)); if (p.record_source != SRC_MIC && p.record_source != SRC_CD && p.record_source != SRC_LINE) return (RET_ERROR (EINVAL)); /* * I'm not sure if this is The Right Thing. Should stereo be entirely * under control of DSP? I like being able to toggle it while a sound is * playing, so I do this... because I can. */ DISABLE_INTR (flags); val = (pas_read (PCM_CONTROL) & ~P_C_MIXER_CROSS_FIELD) | P_C_MIXER_CROSS_R_TO_R | P_C_MIXER_CROSS_L_TO_L; if (!p.dsp_stereo) val |= (P_C_MIXER_CROSS_R_TO_L | P_C_MIXER_CROSS_L_TO_R); /* Mono */ pas_write (val, PCM_CONTROL); RESTORE_INTR (flags); switch (p.record_source) { case SRC_CD: src = SOUND_MASK_CD; break; case SRC_LINE: src = SOUND_MASK_LINE; break; default: src = SOUND_MASK_MIC; break; } pas_mixer_set (SOUND_MIXER_RECSRC, src); /* * setmixer (OUT_FILTER, ((dsp_stereo ? STEREO_DAC : MONO_DAC) | * (p.filter_output ? FILT_ON : FILT_OFF))); */ return (0); }
void pasintr(int irq, void *dev_id, struct pt_regs *dummy) { int status; status = pas_read(0x0B89); pas_write(status, 0x0B89); /* Clear interrupt */ if (status & 0x08) { pas_pcm_interrupt(status, 1); status &= ~0x08; } if (status & 0x10) { pas_midi_interrupt(); status &= ~0x10; } }
static irqreturn_t pasintr(int irq, void *dev_id) { int status; status = pas_read(0x0B89); pas_write(status, 0x0B89); /* Clear interrupt */ if (status & 0x08) { pas_pcm_interrupt(status, 1); status &= ~0x08; } if (status & 0x10) { pas_midi_interrupt(); status &= ~0x10; } return IRQ_HANDLED; }
void pasintr(int irq) { int status; status = pas_read(INTERRUPT_STATUS); pas_write(status, INTERRUPT_STATUS); /* Clear interrupt */ if (status & I_S_PCM_SAMPLE_BUFFER_IRQ) { #ifdef CONFIG_AUDIO pas_pcm_interrupt(status, 1); #endif status &= ~I_S_PCM_SAMPLE_BUFFER_IRQ; } if (status & I_S_MIDI_IRQ) { #ifdef CONFIG_MIDI pas_midi_interrupt(); #endif status &= ~I_S_MIDI_IRQ; } }
static int mixer_output (int right_vol, int left_vol, int div, int bits, int mixer /* Input or output mixer */ ) { int left = left_vol * div / 100; int right = right_vol * div / 100; /* * The Revision D cards have a problem with their MVA508 interface. The * kludge-o-rama fix is to make a 16-bit quantity with identical LSB and * MSBs out of the output byte and to do a 16-bit out to the mixer port - * 1. We don't need to do this because the call to pas_write more than * compensates for the timing problems. */ if (bits & P_M_MV508_MIXER) { /* Select input or output mixer */ left |= mixer; right |= mixer; } if (bits == P_M_MV508_BASS || bits == P_M_MV508_TREBLE) { /* Bass and trebble are mono devices */ pas_write (P_M_MV508_ADDRESS | bits, PARALLEL_MIXER); pas_write (left, PARALLEL_MIXER); right_vol = left_vol; } else { pas_write (P_M_MV508_ADDRESS | P_M_MV508_LEFT | bits, PARALLEL_MIXER); pas_write (left, PARALLEL_MIXER); pas_write (P_M_MV508_ADDRESS | P_M_MV508_RIGHT | bits, PARALLEL_MIXER); pas_write (right, PARALLEL_MIXER); } return (left_vol | (right_vol << 8)); }
static int __init config_pas_hw(struct address_info *hw_config) { char ok = 1; unsigned int_ptrs; /* scsi/sound interrupt pointers */ pas_irq = hw_config->irq; pas_write(0x00, 0x0B8B); pas_write(0x36, 0x138B); pas_write(0x36, 0x1388); pas_write(0, 0x1388); pas_write(0x74, 0x138B); pas_write(0x74, 0x1389); pas_write(0, 0x1389); pas_write(0x80 | 0x40 | 0x20 | 1, 0x0B8A); pas_write(0x80 | 0x20 | 0x10 | 0x08 | 0x01, 0xF8A); pas_write(0x01 | 0x02 | 0x04 | 0x10 /* * | * 0x80 */ , 0xB88); pas_write(0x80 | (joystick ? 0x40 : 0), 0xF388); if (pas_irq < 0 || pas_irq > 15) { printk(KERN_ERR "PAS16: Invalid IRQ %d", pas_irq); hw_config->irq=-1; ok = 0; } else { int_ptrs = pas_read(0xF38A); int_ptrs = (int_ptrs & 0xf0) | irq_bits[pas_irq]; pas_write(int_ptrs, 0xF38A); if (!irq_bits[pas_irq]) { printk(KERN_ERR "PAS16: Invalid IRQ %d", pas_irq); hw_config->irq=-1; ok = 0; } else { if (request_irq(pas_irq, pasintr, 0, "PAS16",hw_config) < 0) { printk(KERN_ERR "PAS16: Cannot allocate IRQ %d\n",pas_irq); hw_config->irq=-1; ok = 0; } } } if (hw_config->dma < 0 || hw_config->dma > 7) { printk(KERN_ERR "PAS16: Invalid DMA selection %d", hw_config->dma); hw_config->dma=-1; ok = 0; } else { pas_write(dma_bits[hw_config->dma], 0xF389); if (!dma_bits[hw_config->dma]) { printk(KERN_ERR "PAS16: Invalid DMA selection %d", hw_config->dma); hw_config->dma=-1; ok = 0; } else { if (sound_alloc_dma(hw_config->dma, "PAS16")) { printk(KERN_ERR "pas2_card.c: Can't allocate DMA channel\n"); hw_config->dma=-1; ok = 0; } } } /* * This fixes the timing problems of the PAS due to the Symphony chipset * as per Media Vision. Only define this if your PAS doesn't work correctly. */ if(symphony) { outb((0x05), 0xa8); outb((0x60), 0xa9); } if(broken_bus_clock) pas_write(0x01 | 0x10 | 0x20 | 0x04, 0x8388); else /* * pas_write(0x01, 0x8388); */ pas_write(0x01 | 0x10 | 0x20, 0x8388); pas_write(0x18, 0x838A); /* ??? */ pas_write(0x20 | 0x01, 0x0B8A); /* Mute off, filter = 17.897 kHz */ pas_write(8, 0xBF8A); mix_write(0x80 | 5, 0x078B); mix_write(5, 0x078B); { struct address_info *sb_config; sb_config = &cfg2; if (sb_config->io_base) { unsigned char irq_dma; /* * Turn on Sound Blaster compatibility * bit 1 = SB emulation * bit 0 = MPU401 emulation (CDPC only :-( ) */ pas_write(0x02, 0xF788); /* * "Emulation address" */ pas_write((sb_config->io_base >> 4) & 0x0f, 0xF789); pas_sb_base = sb_config->io_base; if (!sb_dma_bits[sb_config->dma]) printk(KERN_ERR "PAS16 Warning: Invalid SB DMA %d\n\n", sb_config->dma); if (!sb_irq_bits[sb_config->irq]) printk(KERN_ERR "PAS16 Warning: Invalid SB IRQ %d\n\n", sb_config->irq); irq_dma = sb_dma_bits[sb_config->dma] | sb_irq_bits[sb_config->irq]; pas_write(irq_dma, 0xFB8A); } else
static int config_pas_hw(struct address_info * hw_config) { char ok = 1; u_int int_ptrs; /* scsi/sound interrupt pointers */ pas_irq = hw_config->irq; pas_write(0x00, INTERRUPT_MASK); pas_write(0x36, SAMPLE_COUNTER_CONTROL); /* Local timer control * * register */ pas_write(0x36, SAMPLE_RATE_TIMER); /* Sample rate timer (16 bit) */ pas_write(0, SAMPLE_RATE_TIMER); pas_write(0x74, SAMPLE_COUNTER_CONTROL); /* Local timer control * * register */ pas_write(0x74, SAMPLE_BUFFER_COUNTER); /* Sample count register (16 * * bit) */ pas_write(0, SAMPLE_BUFFER_COUNTER); pas_write(F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER | F_F_MIXER_UNMUTE | 1, FILTER_FREQUENCY); 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); 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); pas_write(I_C_1_BOOT_RESET_ENABLE #ifdef PAS_JOYSTICK_ENABLE | I_C_1_JOYSTICK_ENABLE #endif ,IO_CONFIGURATION_1); if (pas_irq < 0 || pas_irq > 15) { printf("PAS2: Invalid IRQ %d", pas_irq); ok = 0; } else { int_ptrs = pas_read(IO_CONFIGURATION_3); int_ptrs |= I_C_3_PCM_IRQ_translate[pas_irq] & 0xf; pas_write(int_ptrs, IO_CONFIGURATION_3); if (!I_C_3_PCM_IRQ_translate[pas_irq]) { printf("PAS2: Invalid IRQ %d", pas_irq); ok = 0; } else { if (snd_set_irq_handler(pas_irq, pasintr, hw_config->osp) < 0) ok = 0; } } if (hw_config->dma < 0 || hw_config->dma > 7) { printf("PAS2: Invalid DMA selection %d", hw_config->dma); ok = 0; } else { pas_write(I_C_2_PCM_DMA_translate[hw_config->dma], IO_CONFIGURATION_2); if (!I_C_2_PCM_DMA_translate[hw_config->dma]) { printf("PAS2: Invalid DMA selection %d", hw_config->dma); ok = 0; } else { if (0) { printf("pas2_card.c: Can't allocate DMA channel\n"); ok = 0; } } } /* * This fixes the timing problems of the PAS due to the Symphony * chipset as per Media Vision. Only define this if your PAS doesn't * work correctly. */ #ifdef SYMPHONY_PAS outb(0xa8, 0x05); outb(0xa9, 0x60); #endif #ifdef BROKEN_BUS_CLOCK 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); #else /* * pas_write(S_C_1_PCS_ENABLE, SYSTEM_CONFIGURATION_1); */ pas_write(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND, SYSTEM_CONFIGURATION_1); #endif pas_write(0x18, SYSTEM_CONFIGURATION_3); /* ??? */ pas_write(F_F_MIXER_UNMUTE | 0x01, FILTER_FREQUENCY); /* Sets mute off and * * selects filter rate * * of 17.897 kHz */ pas_write(8, PRESCALE_DIVIDER); mix_write(P_M_MV508_ADDRESS | 5, PARALLEL_MIXER); mix_write(5, PARALLEL_MIXER); #if defined(CONFIG_SB_EMULATION) && defined(CONFIG_SB) { struct address_info *sb_config; if ((sb_config = sound_getconf(SNDCARD_SB))) { u_char irq_dma; /* * Turn on Sound Blaster compatibility */ /* * bit 1 = SB emulation */ /* * bit 0 = MPU401 emulation (CDPC only :-( ) */ pas_write(0x02, COMPATIBILITY_ENABLE); /* * "Emulation address" */ pas_write((sb_config->io_base >> 4) & 0x0f, EMULATION_ADDRESS); if (!E_C_SB_DMA_translate[sb_config->dma]) printf("\n\nPAS16 Warning: Invalid SB DMA %d\n\n", sb_config->dma); if (!E_C_SB_IRQ_translate[sb_config->irq]) printf("\n\nPAS16 Warning: Invalid SB IRQ %d\n\n", sb_config->irq); irq_dma = E_C_SB_DMA_translate[sb_config->dma] | E_C_SB_IRQ_translate[sb_config->irq]; pas_write(irq_dma, EMULATION_CONFIGURATION); } }