^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <sound/gus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) extern int snd_gf1_synth_init(struct snd_gus_card * gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) extern void snd_gf1_synth_done(struct snd_gus_card * gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * ok.. default interrupt handlers...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static void snd_gf1_default_interrupt_handler_midi_out(struct snd_gus_card * gus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd &= ~0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static void snd_gf1_default_interrupt_handler_midi_in(struct snd_gus_card * gus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd &= ~0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static void snd_gf1_default_interrupt_handler_timer1(struct snd_gus_card * gus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, gus->gf1.timer_enabled &= ~4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static void snd_gf1_default_interrupt_handler_timer2(struct snd_gus_card * gus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, gus->gf1.timer_enabled &= ~8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void snd_gf1_default_interrupt_handler_wave_and_volume(struct snd_gus_card * gus, struct snd_gus_voice * voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) snd_gf1_i_ctrl_stop(gus, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) snd_gf1_i_ctrl_stop(gus, 0x0d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static void snd_gf1_default_interrupt_handler_dma_write(struct snd_gus_card * gus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) snd_gf1_i_write8(gus, 0x41, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static void snd_gf1_default_interrupt_handler_dma_read(struct snd_gus_card * gus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) snd_gf1_i_write8(gus, 0x49, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) void snd_gf1_set_default_handlers(struct snd_gus_card * gus, unsigned int what)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (what & SNDRV_GF1_HANDLER_MIDI_OUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) gus->gf1.interrupt_handler_midi_out = snd_gf1_default_interrupt_handler_midi_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (what & SNDRV_GF1_HANDLER_MIDI_IN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) gus->gf1.interrupt_handler_midi_in = snd_gf1_default_interrupt_handler_midi_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (what & SNDRV_GF1_HANDLER_TIMER1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) gus->gf1.interrupt_handler_timer1 = snd_gf1_default_interrupt_handler_timer1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (what & SNDRV_GF1_HANDLER_TIMER2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) gus->gf1.interrupt_handler_timer2 = snd_gf1_default_interrupt_handler_timer2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (what & SNDRV_GF1_HANDLER_VOICE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct snd_gus_voice *voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) voice = &gus->gf1.voices[what & 0xffff];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) voice->handler_wave =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) voice->handler_volume = snd_gf1_default_interrupt_handler_wave_and_volume;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) voice->handler_effect = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) voice->volume_change = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (what & SNDRV_GF1_HANDLER_DMA_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) gus->gf1.interrupt_handler_dma_write = snd_gf1_default_interrupt_handler_dma_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (what & SNDRV_GF1_HANDLER_DMA_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) gus->gf1.interrupt_handler_dma_read = snd_gf1_default_interrupt_handler_dma_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static void snd_gf1_clear_regs(struct snd_gus_card * gus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) spin_lock_irqsave(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) inb(GUSP(gus, IRQSTAT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) snd_gf1_write8(gus, 0x41, 0); /* DRAM DMA Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) snd_gf1_write8(gus, 0x45, 0); /* Timer Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) snd_gf1_write8(gus, 0x49, 0); /* Sampling Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) spin_unlock_irqrestore(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static void snd_gf1_look_regs(struct snd_gus_card * gus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) spin_lock_irqsave(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) snd_gf1_look8(gus, 0x41); /* DRAM DMA Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) snd_gf1_look8(gus, 0x49); /* Sampling Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) inb(GUSP(gus, IRQSTAT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) snd_gf1_read8(gus, 0x0f); /* IRQ Source Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) spin_unlock_irqrestore(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * put selected GF1 voices to initial stage...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) void snd_gf1_smart_stop_voice(struct snd_gus_card * gus, unsigned short voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) spin_lock_irqsave(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) snd_gf1_select_voice(gus, voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) printk(KERN_DEBUG " -%i- smart stop voice - volume = 0x%x\n", voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) spin_unlock_irqrestore(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) void snd_gf1_stop_voice(struct snd_gus_card * gus, unsigned short voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) spin_lock_irqsave(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) snd_gf1_select_voice(gus, voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) printk(KERN_DEBUG " -%i- stop voice - volume = 0x%x\n", voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (gus->gf1.enh_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) spin_unlock_irqrestore(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) snd_gf1_lfo_shutdown(gus, voice, ULTRA_LFO_VIBRATO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) snd_gf1_lfo_shutdown(gus, voice, ULTRA_LFO_TREMOLO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static void snd_gf1_clear_voices(struct snd_gus_card * gus, unsigned short v_min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) unsigned short v_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) unsigned int daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) unsigned short i, w_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) daddr = gus->gf1.default_voice_address << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) for (i = v_min; i <= v_max; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (gus->gf1.syn_voices)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) gus->gf1.syn_voices[i].flags = ~VFLG_DYNAMIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) spin_lock_irqsave(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) snd_gf1_select_voice(gus, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); /* Voice Control Register = voice stop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); /* Volume Ramp Control Register = ramp off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (gus->gf1.enh_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) snd_gf1_write8(gus, SNDRV_GF1_VB_MODE, gus->gf1.memory ? 0x02 : 0x82); /* Deactivate voice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) w_16 = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL) & 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, 0x400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, daddr, w_16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, daddr, w_16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, daddr, w_16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (gus->gf1.enh_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME_FINAL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) spin_unlock_irqrestore(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) snd_gf1_lfo_shutdown(gus, i, ULTRA_LFO_VIBRATO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) snd_gf1_lfo_shutdown(gus, i, ULTRA_LFO_TREMOLO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) void snd_gf1_stop_voices(struct snd_gus_card * gus, unsigned short v_min, unsigned short v_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) short i, ramp_ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) unsigned short ramp_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (!in_interrupt()) { /* this can't be done in interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) for (i = v_min, ramp_ok = 0; i <= v_max; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) spin_lock_irqsave(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) snd_gf1_select_voice(gus, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) ramp_end = snd_gf1_read16(gus, 9) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (ramp_end > SNDRV_GF1_MIN_OFFSET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ramp_ok++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 20); /* ramp rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, SNDRV_GF1_MIN_OFFSET); /* ramp start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, ramp_end); /* ramp end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, 0x40); /* ramp down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (gus->gf1.enh_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) snd_gf1_delay(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) spin_unlock_irqrestore(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) msleep_interruptible(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) snd_gf1_clear_voices(gus, v_min, v_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static void snd_gf1_alloc_voice_use(struct snd_gus_card * gus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct snd_gus_voice * pvoice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int type, int client, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) pvoice->use = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) case SNDRV_GF1_VOICE_TYPE_PCM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) gus->gf1.pcm_alloc_voices++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) pvoice->pcm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) case SNDRV_GF1_VOICE_TYPE_SYNTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) pvoice->synth = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) pvoice->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) pvoice->port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) case SNDRV_GF1_VOICE_TYPE_MIDI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) pvoice->midi = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) pvoice->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) pvoice->port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct snd_gus_voice *snd_gf1_alloc_voice(struct snd_gus_card * gus, int type, int client, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct snd_gus_voice *pvoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) spin_lock_irqsave(&gus->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (type == SNDRV_GF1_VOICE_TYPE_PCM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (gus->gf1.pcm_alloc_voices >= gus->gf1.pcm_channels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) spin_unlock_irqrestore(&gus->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) for (idx = 0; idx < 32; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) pvoice = &gus->gf1.voices[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (!pvoice->use) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) snd_gf1_alloc_voice_use(gus, pvoice, type, client, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) spin_unlock_irqrestore(&gus->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return pvoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) for (idx = 0; idx < 32; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) pvoice = &gus->gf1.voices[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (pvoice->midi && !pvoice->client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) snd_gf1_clear_voices(gus, pvoice->number, pvoice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) snd_gf1_alloc_voice_use(gus, pvoice, type, client, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) spin_unlock_irqrestore(&gus->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return pvoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) spin_unlock_irqrestore(&gus->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) void snd_gf1_free_voice(struct snd_gus_card * gus, struct snd_gus_voice *voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) void (*private_free)(struct snd_gus_voice *voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (voice == NULL || !voice->use)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_VOICE | voice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) snd_gf1_clear_voices(gus, voice->number, voice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) spin_lock_irqsave(&gus->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) private_free = voice->private_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) voice->private_free = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) voice->private_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (voice->pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) gus->gf1.pcm_alloc_voices--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) voice->use = voice->pcm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) voice->sample_ops = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) spin_unlock_irqrestore(&gus->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (private_free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) private_free(voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * call this function only by start of driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) int snd_gf1_start(struct snd_gus_card * gus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) udelay(160);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* disable IRQ & DAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) udelay(160);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) snd_gf1_i_write8(gus, SNDRV_GF1_GB_JOYSTICK_DAC_LEVEL, gus->joystick_dac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) for (i = 0; i < 32; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) gus->gf1.voices[i].number = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_VOICE | i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) snd_gf1_uart_cmd(gus, 0x03); /* huh.. this cleanup took me some time... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (gus->gf1.enh_mode) { /* enhanced mode !!!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) snd_gf1_i_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_i_look8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) snd_gf1_i_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) snd_gf1_clear_regs(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) snd_gf1_select_active_voices(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) snd_gf1_delay(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) gus->gf1.default_voice_address = gus->gf1.memory > 0 ? 0 : 512 - 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /* initialize LFOs & clear LFOs memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (gus->gf1.enh_mode && gus->gf1.memory) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) gus->gf1.hw_lfo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) gus->gf1.default_voice_address += 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) gus->gf1.sw_lfo = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) snd_gf1_lfo_init(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (gus->gf1.memory > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) snd_gf1_poke(gus, gus->gf1.default_voice_address + i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) snd_gf1_clear_regs(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) snd_gf1_clear_voices(gus, 0, 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) snd_gf1_look_regs(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) udelay(160);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 7); /* Reset Register = IRQ enable, DAC enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) udelay(160);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 7); /* Reset Register = IRQ enable, DAC enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (gus->gf1.enh_mode) { /* enhanced mode !!!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) snd_gf1_i_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_i_look8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) snd_gf1_i_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) while ((snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ) & 0xc0) != 0xc0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) spin_lock_irqsave(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) outb(gus->gf1.active_voice = 0, GUSP(gus, GF1PAGE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) spin_unlock_irqrestore(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) snd_gf1_timers_init(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) snd_gf1_look_regs(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) snd_gf1_mem_init(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) snd_gf1_mem_proc_init(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) #ifdef CONFIG_SND_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) snd_gus_irq_profile_init(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (gus->pnp_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (gus->chip.playback_fifo_size > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) snd_gf1_i_write16(gus, SNDRV_GF1_GW_FIFO_RECORD_BASE_ADDR, gus->chip.playback_fifo_block->ptr >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (gus->chip.record_fifo_size > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) snd_gf1_i_write16(gus, SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR, gus->chip.record_fifo_block->ptr >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) snd_gf1_i_write16(gus, SNDRV_GF1_GW_FIFO_SIZE, gus->chip.interwave_fifo_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * call this function only by shutdown of driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) int snd_gf1_stop(struct snd_gus_card * gus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, 0); /* stop all timers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) snd_gf1_stop_voices(gus, 0, 31); /* stop all voices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* disable IRQ & DAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) snd_gf1_timers_done(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) snd_gf1_mem_done(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) snd_gf1_lfo_done(gus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }