^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) * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Routines for control of EMU8000 chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <sound/emu8000.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <sound/emu8000_reg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * emu8000 register controls
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * The following routines read and write registers on the emu8000. They
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * should always be called via the EMU8000*READ/WRITE macros and never
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * directly. The macros handle the port number and command word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Write a word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) void snd_emu8000_poke(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) spin_lock_irqsave(&emu->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (reg != emu->last_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) emu->last_reg = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) outw((unsigned short)val, port); /* Send data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) spin_unlock_irqrestore(&emu->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* Read a word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned short snd_emu8000_peek(struct snd_emu8000 *emu, unsigned int port, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) unsigned short res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) spin_lock_irqsave(&emu->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (reg != emu->last_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) emu->last_reg = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) res = inw(port); /* Read data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) spin_unlock_irqrestore(&emu->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* Write a double word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) void snd_emu8000_poke_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) spin_lock_irqsave(&emu->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (reg != emu->last_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) emu->last_reg = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) outw((unsigned short)val, port); /* Send low word of data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) outw((unsigned short)(val>>16), port+2); /* Send high word of data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) spin_unlock_irqrestore(&emu->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* Read a double word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) unsigned int snd_emu8000_peek_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned short low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) unsigned int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) spin_lock_irqsave(&emu->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (reg != emu->last_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) emu->last_reg = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) low = inw(port); /* Read low word of data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) res = low + (inw(port+2) << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) spin_unlock_irqrestore(&emu->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * Set up / close a channel to be used for DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /*exported*/ void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) unsigned right_bit = (mode & EMU8000_RAM_RIGHT) ? 0x01000000 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) mode &= EMU8000_RAM_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (mode == EMU8000_RAM_CLOSE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) EMU8000_CCCA_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) EMU8000_DCYSUSV_WRITE(emu, ch, 0x807F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) EMU8000_DCYSUSV_WRITE(emu, ch, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) EMU8000_VTFT_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) EMU8000_CVCF_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) EMU8000_PTRX_WRITE(emu, ch, 0x40000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) EMU8000_CPF_WRITE(emu, ch, 0x40000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) EMU8000_PSST_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) EMU8000_CSL_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (mode == EMU8000_RAM_WRITE) /* DMA write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) EMU8000_CCCA_WRITE(emu, ch, 0x06000000 | right_bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) else /* DMA read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) EMU8000_CCCA_WRITE(emu, ch, 0x04000000 | right_bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) snd_emu8000_read_wait(struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) schedule_timeout_interruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) snd_emu8000_write_wait(struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) schedule_timeout_interruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * detect a card at the given port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) snd_emu8000_detect(struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* Initialise */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) EMU8000_HWCF1_WRITE(emu, 0x0059);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) EMU8000_HWCF2_WRITE(emu, 0x0020);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) EMU8000_HWCF3_WRITE(emu, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* Check for a recognisable emu8000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if ((EMU8000_U1_READ(emu) & 0x000f) != 0x000c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if ((EMU8000_HWCF1_READ(emu) & 0x007e) != 0x0058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if ((EMU8000_HWCF2_READ(emu) & 0x0003) != 0x0003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) snd_printdd("EMU8000 [0x%lx]: Synth chip found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) emu->port1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * intiailize audio channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) init_audio(struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* turn off envelope engines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) for (ch = 0; ch < EMU8000_CHANNELS; ch++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) EMU8000_DCYSUSV_WRITE(emu, ch, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /* reset all other parameters to zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) for (ch = 0; ch < EMU8000_CHANNELS; ch++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) EMU8000_ENVVOL_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) EMU8000_ENVVAL_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) EMU8000_DCYSUS_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) EMU8000_ATKHLDV_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) EMU8000_LFO1VAL_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) EMU8000_ATKHLD_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) EMU8000_LFO2VAL_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) EMU8000_IP_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) EMU8000_IFATN_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) EMU8000_PEFE_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) EMU8000_FMMOD_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) EMU8000_TREMFRQ_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) EMU8000_FM2FRQ2_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) EMU8000_PTRX_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) EMU8000_VTFT_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) EMU8000_PSST_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) EMU8000_CSL_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) EMU8000_CCCA_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) for (ch = 0; ch < EMU8000_CHANNELS; ch++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) EMU8000_CPF_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) EMU8000_CVCF_WRITE(emu, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * initialize DMA address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) init_dma(struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) EMU8000_SMALR_WRITE(emu, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) EMU8000_SMARR_WRITE(emu, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) EMU8000_SMALW_WRITE(emu, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) EMU8000_SMARW_WRITE(emu, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * initialization arrays; from ADIP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static const unsigned short init1[128] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 0x03ff, 0x0030, 0x07ff, 0x0130, 0x0bff, 0x0230, 0x0fff, 0x0330,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 0x13ff, 0x0430, 0x17ff, 0x0530, 0x1bff, 0x0630, 0x1fff, 0x0730,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 0x23ff, 0x0830, 0x27ff, 0x0930, 0x2bff, 0x0a30, 0x2fff, 0x0b30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 0x33ff, 0x0c30, 0x37ff, 0x0d30, 0x3bff, 0x0e30, 0x3fff, 0x0f30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 0x43ff, 0x0030, 0x47ff, 0x0130, 0x4bff, 0x0230, 0x4fff, 0x0330,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 0x53ff, 0x0430, 0x57ff, 0x0530, 0x5bff, 0x0630, 0x5fff, 0x0730,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 0x63ff, 0x0830, 0x67ff, 0x0930, 0x6bff, 0x0a30, 0x6fff, 0x0b30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 0x73ff, 0x0c30, 0x77ff, 0x0d30, 0x7bff, 0x0e30, 0x7fff, 0x0f30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 0x83ff, 0x0030, 0x87ff, 0x0130, 0x8bff, 0x0230, 0x8fff, 0x0330,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 0x93ff, 0x0430, 0x97ff, 0x0530, 0x9bff, 0x0630, 0x9fff, 0x0730,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 0xa3ff, 0x0830, 0xa7ff, 0x0930, 0xabff, 0x0a30, 0xafff, 0x0b30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 0xb3ff, 0x0c30, 0xb7ff, 0x0d30, 0xbbff, 0x0e30, 0xbfff, 0x0f30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 0xc3ff, 0x0030, 0xc7ff, 0x0130, 0xcbff, 0x0230, 0xcfff, 0x0330,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 0xd3ff, 0x0430, 0xd7ff, 0x0530, 0xdbff, 0x0630, 0xdfff, 0x0730,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 0xe3ff, 0x0830, 0xe7ff, 0x0930, 0xebff, 0x0a30, 0xefff, 0x0b30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 0xf3ff, 0x0c30, 0xf7ff, 0x0d30, 0xfbff, 0x0e30, 0xffff, 0x0f30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static const unsigned short init2[128] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static const unsigned short init3[128] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static const unsigned short init4[128] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /* send an initialization array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * Taken from the oss driver, not obvious from the doc how this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * is meant to work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) send_array(struct snd_emu8000 *emu, const unsigned short *data, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) const unsigned short *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) p = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) for (i = 0; i < size; i++, p++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) EMU8000_INIT1_WRITE(emu, i, *p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) for (i = 0; i < size; i++, p++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) EMU8000_INIT2_WRITE(emu, i, *p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) for (i = 0; i < size; i++, p++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) EMU8000_INIT3_WRITE(emu, i, *p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) for (i = 0; i < size; i++, p++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) EMU8000_INIT4_WRITE(emu, i, *p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * Send initialization arrays to start up, this just follows the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * initialisation sequence in the adip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) init_arrays(struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) send_array(emu, init1, ARRAY_SIZE(init1)/4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) msleep((1024 * 1000) / 44100); /* wait for 1024 clocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) send_array(emu, init2, ARRAY_SIZE(init2)/4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) send_array(emu, init3, ARRAY_SIZE(init3)/4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) EMU8000_HWCF4_WRITE(emu, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) EMU8000_HWCF5_WRITE(emu, 0x83);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) EMU8000_HWCF6_WRITE(emu, 0x8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) send_array(emu, init4, ARRAY_SIZE(init4)/4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) #define UNIQUE_ID1 0xa5b9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) #define UNIQUE_ID2 0x9d53
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * Size the onboard memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * This is written so as not to need arbitrary delays after the write. It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * seems that the only way to do this is to use the one channel and keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * reallocating between read and write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) size_dram(struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) int i, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (emu->dram_checked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* write out a magic number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) EMU8000_SMLD_WRITE(emu, UNIQUE_ID1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) snd_emu8000_init_fm(emu); /* This must really be here and not 2 lines back even */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) snd_emu8000_write_wait(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * Detect first 512 KiB. If a write succeeds at the beginning of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * 512 KiB page we assume that the whole page is there.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) EMU8000_SMLD_READ(emu); /* discard stale data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) goto skip_detect; /* No RAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) snd_emu8000_read_wait(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) for (size = 512 * 1024; size < EMU8000_MAX_DRAM; size += 512 * 1024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) /* Write a unique data on the test address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * if the address is out of range, the data is written on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * 0x200000(=EMU8000_DRAM_OFFSET). Then the id word is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * changed by this data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) EMU8000_SMLD_WRITE(emu, UNIQUE_ID2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) snd_emu8000_write_wait(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * read the data on the just written DRAM address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * if not the same then we have reached the end of ram.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_READ);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /*snd_emu8000_read_wait(emu);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) EMU8000_SMLD_READ(emu); /* discard stale data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) break; /* no memory at this address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) snd_emu8000_read_wait(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * If it is the same it could be that the address just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * wraps back to the beginning; so check to see if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * initial value has been overwritten.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) EMU8000_SMLD_READ(emu); /* discard stale data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) break; /* we must have wrapped around */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) snd_emu8000_read_wait(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /* Otherwise, it's valid memory. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) skip_detect:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /* wait until FULL bit in SMAxW register is false */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) for (i = 0; i < 10000; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if ((EMU8000_SMALW_READ(emu) & 0x80000000) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) schedule_timeout_interruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_CLOSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_CLOSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) pr_info("EMU8000 [0x%lx]: %d KiB on-board DRAM detected\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) emu->port1, size/1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) emu->mem_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) emu->dram_checked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * Initiailise the FM section. You have to do this to use sample RAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * and therefore lose 2 voices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /*exported*/ void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) snd_emu8000_init_fm(struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /* Initialize the last two channels for DRAM refresh and producing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) the reverb and chorus effects for Yamaha OPL-3 synthesizer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /* 31: FM left channel, 0xffffe0-0xffffe8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) EMU8000_DCYSUSV_WRITE(emu, 30, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) EMU8000_PSST_WRITE(emu, 30, 0xFFFFFFE0); /* full left */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) EMU8000_CSL_WRITE(emu, 30, 0x00FFFFE8 | (emu->fm_chorus_depth << 24));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) EMU8000_PTRX_WRITE(emu, 30, (emu->fm_reverb_depth << 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) EMU8000_CPF_WRITE(emu, 30, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) EMU8000_CCCA_WRITE(emu, 30, 0x00FFFFE3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /* 32: FM right channel, 0xfffff0-0xfffff8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) EMU8000_DCYSUSV_WRITE(emu, 31, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) EMU8000_PSST_WRITE(emu, 31, 0x00FFFFF0); /* full right */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) EMU8000_CSL_WRITE(emu, 31, 0x00FFFFF8 | (emu->fm_chorus_depth << 24));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) EMU8000_PTRX_WRITE(emu, 31, (emu->fm_reverb_depth << 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) EMU8000_CPF_WRITE(emu, 31, 0x8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) EMU8000_CCCA_WRITE(emu, 31, 0x00FFFFF3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) spin_lock_irqsave(&emu->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) while (!(inw(EMU8000_PTR(emu)) & 0x1000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) while ((inw(EMU8000_PTR(emu)) & 0x1000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) spin_unlock_irqrestore(&emu->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0x4828);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /* this is really odd part.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) outb(0x3C, EMU8000_PTR(emu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) outb(0, EMU8000_DATA1(emu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* skew volume & cutoff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) EMU8000_VTFT_WRITE(emu, 30, 0x8000FFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) EMU8000_VTFT_WRITE(emu, 31, 0x8000FFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * The main initialization routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) snd_emu8000_init_hw(struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) emu->last_reg = 0xffff; /* reset the last register index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /* initialize hardware configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) EMU8000_HWCF1_WRITE(emu, 0x0059);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) EMU8000_HWCF2_WRITE(emu, 0x0020);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /* disable audio; this seems to reduce a clicking noise a bit.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) EMU8000_HWCF3_WRITE(emu, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /* initialize audio channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) init_audio(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /* initialize DMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) init_dma(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) /* initialize init arrays */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) init_arrays(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * Initialize the FM section of the AWE32, this is needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * for DRAM refresh as well
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) snd_emu8000_init_fm(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) /* terminate all voices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) for (i = 0; i < EMU8000_DRAM_VOICES; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) EMU8000_DCYSUSV_WRITE(emu, 0, 0x807F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* check DRAM memory size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) size_dram(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /* enable audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) EMU8000_HWCF3_WRITE(emu, 0x4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /* set equzlier, chorus and reverb modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) snd_emu8000_update_equalizer(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) snd_emu8000_update_chorus_mode(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) snd_emu8000_update_reverb_mode(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /*----------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * Bass/Treble Equalizer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) *----------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) static const unsigned short bass_parm[12][3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) {0xD26A, 0xD36A, 0x0000}, /* -12 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) {0xD25B, 0xD35B, 0x0000}, /* -8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {0xD24C, 0xD34C, 0x0000}, /* -6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {0xD23D, 0xD33D, 0x0000}, /* -4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) {0xD21F, 0xD31F, 0x0000}, /* -2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {0xC208, 0xC308, 0x0001}, /* 0 (HW default) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) {0xC219, 0xC319, 0x0001}, /* +2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {0xC22A, 0xC32A, 0x0001}, /* +4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) {0xC24C, 0xC34C, 0x0001}, /* +6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {0xC26E, 0xC36E, 0x0001}, /* +8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {0xC248, 0xC384, 0x0002}, /* +10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) {0xC26A, 0xC36A, 0x0002}, /* +12 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) static const unsigned short treble_parm[12][9] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) {0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) {0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) {0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) {0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) {0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) {0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) {0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002} /* +12 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) /*exported*/ void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) snd_emu8000_update_equalizer(struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) unsigned short w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) int bass = emu->bass_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) int treble = emu->treble_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (bass < 0 || bass > 11 || treble < 0 || treble > 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) EMU8000_INIT4_WRITE(emu, 0x01, bass_parm[bass][0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) EMU8000_INIT4_WRITE(emu, 0x11, bass_parm[bass][1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) EMU8000_INIT3_WRITE(emu, 0x11, treble_parm[treble][0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) EMU8000_INIT3_WRITE(emu, 0x13, treble_parm[treble][1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) EMU8000_INIT3_WRITE(emu, 0x1b, treble_parm[treble][2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) EMU8000_INIT4_WRITE(emu, 0x07, treble_parm[treble][3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) EMU8000_INIT4_WRITE(emu, 0x0b, treble_parm[treble][4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) EMU8000_INIT4_WRITE(emu, 0x0d, treble_parm[treble][5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) EMU8000_INIT4_WRITE(emu, 0x17, treble_parm[treble][6]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) EMU8000_INIT4_WRITE(emu, 0x19, treble_parm[treble][7]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) w = bass_parm[bass][2] + treble_parm[treble][8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) EMU8000_INIT4_WRITE(emu, 0x15, (unsigned short)(w + 0x0262));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) EMU8000_INIT4_WRITE(emu, 0x1d, (unsigned short)(w + 0x8362));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /*----------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * Chorus mode control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) *----------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * chorus mode parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) #define SNDRV_EMU8000_CHORUS_1 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) #define SNDRV_EMU8000_CHORUS_2 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) #define SNDRV_EMU8000_CHORUS_3 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) #define SNDRV_EMU8000_CHORUS_4 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) #define SNDRV_EMU8000_CHORUS_FEEDBACK 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) #define SNDRV_EMU8000_CHORUS_FLANGER 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) #define SNDRV_EMU8000_CHORUS_SHORTDELAY 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) #define SNDRV_EMU8000_CHORUS_SHORTDELAY2 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) #define SNDRV_EMU8000_CHORUS_PREDEFINED 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) /* user can define chorus modes up to 32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) #define SNDRV_EMU8000_CHORUS_NUMBERS 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) struct soundfont_chorus_fx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) unsigned short feedback; /* feedback level (0xE600-0xE6FF) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) unsigned short delay_offset; /* delay (0-0x0DA3) [1/44100 sec] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) unsigned short lfo_depth; /* LFO depth (0xBC00-0xBCFF) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) unsigned int delay; /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) unsigned int lfo_freq; /* LFO freq LFO freq (0-0xFFFFFFFF) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) /* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) static char chorus_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) static struct soundfont_chorus_fx chorus_parm[SNDRV_EMU8000_CHORUS_NUMBERS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) {0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) {0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) {0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) {0xE600, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) {0xE6C0, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay + feedback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) /*exported*/ int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) snd_emu8000_load_chorus_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) struct soundfont_chorus_fx rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (mode < SNDRV_EMU8000_CHORUS_PREDEFINED || mode >= SNDRV_EMU8000_CHORUS_NUMBERS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) snd_printk(KERN_WARNING "invalid chorus mode %d for uploading\n", mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) chorus_parm[mode] = rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) chorus_defined[mode] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /*exported*/ void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) snd_emu8000_update_chorus_mode(struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) int effect = emu->chorus_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (effect < 0 || effect >= SNDRV_EMU8000_CHORUS_NUMBERS ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) (effect >= SNDRV_EMU8000_CHORUS_PREDEFINED && !chorus_defined[effect]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) EMU8000_INIT3_WRITE(emu, 0x09, chorus_parm[effect].feedback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) EMU8000_INIT3_WRITE(emu, 0x0c, chorus_parm[effect].delay_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) EMU8000_INIT4_WRITE(emu, 0x03, chorus_parm[effect].lfo_depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) EMU8000_HWCF4_WRITE(emu, chorus_parm[effect].delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) EMU8000_HWCF5_WRITE(emu, chorus_parm[effect].lfo_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) EMU8000_HWCF6_WRITE(emu, 0x8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) EMU8000_HWCF7_WRITE(emu, 0x0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) /*----------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * Reverb mode control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) *----------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * reverb mode parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) #define SNDRV_EMU8000_REVERB_ROOM1 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) #define SNDRV_EMU8000_REVERB_ROOM2 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) #define SNDRV_EMU8000_REVERB_ROOM3 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) #define SNDRV_EMU8000_REVERB_HALL1 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) #define SNDRV_EMU8000_REVERB_HALL2 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) #define SNDRV_EMU8000_REVERB_PLATE 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) #define SNDRV_EMU8000_REVERB_DELAY 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) #define SNDRV_EMU8000_REVERB_PANNINGDELAY 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) #define SNDRV_EMU8000_REVERB_PREDEFINED 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /* user can define reverb modes up to 32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) #define SNDRV_EMU8000_REVERB_NUMBERS 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) struct soundfont_reverb_fx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) unsigned short parms[28];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) /* reverb mode settings; write the following 28 data of 16 bit length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * on the corresponding ports in the reverb_cmds array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) static char reverb_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) static struct soundfont_reverb_fx reverb_parm[SNDRV_EMU8000_REVERB_NUMBERS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) {{ /* room 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) {{ /* room 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {{ /* room 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) {{ /* hall 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) {{ /* hall 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) {{ /* plate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) {{ /* delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) {{ /* panning delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) }},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) enum { DATA1, DATA2 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) #define AWE_INIT1(c) EMU8000_CMD(2,c), DATA1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) #define AWE_INIT2(c) EMU8000_CMD(2,c), DATA2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) #define AWE_INIT3(c) EMU8000_CMD(3,c), DATA1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) #define AWE_INIT4(c) EMU8000_CMD(3,c), DATA2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) static struct reverb_cmd_pair {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) unsigned short cmd, port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) } reverb_cmds[28] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) /*exported*/ int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) snd_emu8000_load_reverb_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) struct soundfont_reverb_fx rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (mode < SNDRV_EMU8000_REVERB_PREDEFINED || mode >= SNDRV_EMU8000_REVERB_NUMBERS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) snd_printk(KERN_WARNING "invalid reverb mode %d for uploading\n", mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) reverb_parm[mode] = rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) reverb_defined[mode] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /*exported*/ void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) snd_emu8000_update_reverb_mode(struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) int effect = emu->reverb_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (effect < 0 || effect >= SNDRV_EMU8000_REVERB_NUMBERS ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) (effect >= SNDRV_EMU8000_REVERB_PREDEFINED && !reverb_defined[effect]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) for (i = 0; i < 28; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) int port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (reverb_cmds[i].port == DATA1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) port = EMU8000_DATA1(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) port = EMU8000_DATA2(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) snd_emu8000_poke(emu, port, reverb_cmds[i].cmd, reverb_parm[effect].parms[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) /*----------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) * mixer interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) *----------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * bass/treble
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) static int mixer_bass_treble_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) uinfo->value.integer.max = 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) static int mixer_bass_treble_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->treble_level : emu->bass_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static int mixer_bass_treble_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) unsigned short val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) val1 = ucontrol->value.integer.value[0] % 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) spin_lock_irqsave(&emu->control_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (kcontrol->private_value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) change = val1 != emu->treble_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) emu->treble_level = val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) change = val1 != emu->bass_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) emu->bass_level = val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) spin_unlock_irqrestore(&emu->control_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) snd_emu8000_update_equalizer(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) static const struct snd_kcontrol_new mixer_bass_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) .name = "Synth Tone Control - Bass",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) .info = mixer_bass_treble_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) .get = mixer_bass_treble_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) .put = mixer_bass_treble_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) .private_value = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) static const struct snd_kcontrol_new mixer_treble_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) .name = "Synth Tone Control - Treble",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) .info = mixer_bass_treble_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) .get = mixer_bass_treble_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) .put = mixer_bass_treble_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) .private_value = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) * chorus/reverb mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static int mixer_chorus_reverb_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) uinfo->value.integer.max = kcontrol->private_value ? (SNDRV_EMU8000_CHORUS_NUMBERS-1) : (SNDRV_EMU8000_REVERB_NUMBERS-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) static int mixer_chorus_reverb_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->chorus_mode : emu->reverb_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) static int mixer_chorus_reverb_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) unsigned short val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) spin_lock_irqsave(&emu->control_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (kcontrol->private_value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_CHORUS_NUMBERS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) change = val1 != emu->chorus_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) emu->chorus_mode = val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_REVERB_NUMBERS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) change = val1 != emu->reverb_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) emu->reverb_mode = val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) spin_unlock_irqrestore(&emu->control_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (kcontrol->private_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) snd_emu8000_update_chorus_mode(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) snd_emu8000_update_reverb_mode(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) static const struct snd_kcontrol_new mixer_chorus_mode_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) .name = "Chorus Mode",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) .info = mixer_chorus_reverb_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) .get = mixer_chorus_reverb_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) .put = mixer_chorus_reverb_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) .private_value = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) static const struct snd_kcontrol_new mixer_reverb_mode_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) .name = "Reverb Mode",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) .info = mixer_chorus_reverb_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) .get = mixer_chorus_reverb_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) .put = mixer_chorus_reverb_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) .private_value = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) * FM OPL3 chorus/reverb depth
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) static int mixer_fm_depth_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) uinfo->value.integer.max = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) static int mixer_fm_depth_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->fm_chorus_depth : emu->fm_reverb_depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) static int mixer_fm_depth_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) unsigned short val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) val1 = ucontrol->value.integer.value[0] % 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) spin_lock_irqsave(&emu->control_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (kcontrol->private_value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) change = val1 != emu->fm_chorus_depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) emu->fm_chorus_depth = val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) change = val1 != emu->fm_reverb_depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) emu->fm_reverb_depth = val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) spin_unlock_irqrestore(&emu->control_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (change)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) snd_emu8000_init_fm(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) static const struct snd_kcontrol_new mixer_fm_chorus_depth_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) .name = "FM Chorus Depth",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) .info = mixer_fm_depth_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) .get = mixer_fm_depth_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) .put = mixer_fm_depth_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) .private_value = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) static const struct snd_kcontrol_new mixer_fm_reverb_depth_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) .name = "FM Reverb Depth",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) .info = mixer_fm_depth_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) .get = mixer_fm_depth_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) .put = mixer_fm_depth_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) .private_value = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) static const struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) &mixer_bass_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) &mixer_treble_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) &mixer_chorus_mode_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) &mixer_reverb_mode_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) &mixer_fm_chorus_depth_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) &mixer_fm_reverb_depth_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) * create and attach mixer elements for WaveTable treble/bass controls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) int i, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (snd_BUG_ON(!emu || !card))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) spin_lock_init(&emu->control_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) memset(emu->controls, 0, sizeof(emu->controls));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) emu->controls[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) goto __error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) __error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) down_write(&card->controls_rwsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if (emu->controls[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) snd_ctl_remove(card, emu->controls[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) up_write(&card->controls_rwsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) * free resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) static int snd_emu8000_free(struct snd_emu8000 *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) release_and_free_resource(hw->res_port1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) release_and_free_resource(hw->res_port2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) release_and_free_resource(hw->res_port3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) kfree(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) static int snd_emu8000_dev_free(struct snd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) struct snd_emu8000 *hw = device->device_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) return snd_emu8000_free(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) * initialize and register emu8000 synth device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) struct snd_seq_device **awe_ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) struct snd_seq_device *awe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) struct snd_emu8000 *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) static const struct snd_device_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) .dev_free = snd_emu8000_dev_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (awe_ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) *awe_ret = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (seq_ports <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) hw = kzalloc(sizeof(*hw), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (hw == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) spin_lock_init(&hw->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) hw->index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) hw->port1 = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) hw->port2 = port + 0x400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) hw->port3 = port + 0x800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (!(hw->res_port1 = request_region(hw->port1, 4, "Emu8000-1")) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) !(hw->res_port2 = request_region(hw->port2, 4, "Emu8000-2")) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) !(hw->res_port3 = request_region(hw->port3, 4, "Emu8000-3"))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) snd_emu8000_free(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) hw->mem_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) hw->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) hw->seq_ports = seq_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) hw->bass_level = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) hw->treble_level = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) hw->chorus_mode = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) hw->reverb_mode = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) hw->fm_chorus_depth = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) hw->fm_reverb_depth = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (snd_emu8000_detect(hw) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) snd_emu8000_free(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) snd_emu8000_init_hw(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if ((err = snd_emu8000_create_mixer(card, hw)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) snd_emu8000_free(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if ((err = snd_device_new(card, SNDRV_DEV_CODEC, hw, &ops)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) snd_emu8000_free(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) #if IS_ENABLED(CONFIG_SND_SEQUENCER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) sizeof(struct snd_emu8000*), &awe) >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) strcpy(awe->name, "EMU-8000");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) *(struct snd_emu8000 **)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) awe = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) if (awe_ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) *awe_ret = awe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) * exported stuff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) EXPORT_SYMBOL(snd_emu8000_poke);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) EXPORT_SYMBOL(snd_emu8000_peek);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) EXPORT_SYMBOL(snd_emu8000_poke_dw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) EXPORT_SYMBOL(snd_emu8000_peek_dw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) EXPORT_SYMBOL(snd_emu8000_dma_chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) EXPORT_SYMBOL(snd_emu8000_init_fm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) EXPORT_SYMBOL(snd_emu8000_load_chorus_fx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) EXPORT_SYMBOL(snd_emu8000_load_reverb_fx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) EXPORT_SYMBOL(snd_emu8000_update_chorus_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) EXPORT_SYMBOL(snd_emu8000_update_reverb_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) EXPORT_SYMBOL(snd_emu8000_update_equalizer);