^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) * Patch routines for the emu8000 (AWE32/64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1999 Steve Ratcliffe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "emu8000_local.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^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/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) static int emu8000_reset_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) module_param(emu8000_reset_addr, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) MODULE_PARM_DESC(emu8000_reset_addr, "reset write address at each time (makes slowdown)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Open up channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) snd_emu8000_open_dma(struct snd_emu8000 *emu, int write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* reserve all 30 voices for loading */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) for (i = 0; i < EMU8000_DRAM_VOICES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) snd_emux_lock_voice(emu->emu, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) snd_emu8000_dma_chan(emu, i, write);
^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) /* assign voice 31 and 32 to ROM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) EMU8000_VTFT_WRITE(emu, 30, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) EMU8000_PSST_WRITE(emu, 30, 0x1d8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) EMU8000_CSL_WRITE(emu, 30, 0x1e0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) EMU8000_CCCA_WRITE(emu, 30, 0x1d8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) EMU8000_VTFT_WRITE(emu, 31, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) EMU8000_PSST_WRITE(emu, 31, 0x1d8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) EMU8000_CSL_WRITE(emu, 31, 0x1e0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) EMU8000_CCCA_WRITE(emu, 31, 0x1d8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return 0;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * Close all dram channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) snd_emu8000_close_dma(struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) for (i = 0; i < EMU8000_DRAM_VOICES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) snd_emu8000_dma_chan(emu, i, EMU8000_RAM_CLOSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) snd_emux_unlock_voice(emu->emu, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^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) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define BLANK_LOOP_START 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define BLANK_LOOP_END 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define BLANK_LOOP_SIZE 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define BLANK_HEAD_SIZE 48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * Read a word from userland, taking care of conversions from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * 8bit samples etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static unsigned short
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) read_word(const void __user *buf, int offset, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) unsigned short c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (mode & SNDRV_SFNT_SAMPLE_8BITS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned char cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) get_user(cc, (unsigned char __user *)buf + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) c = cc << 8; /* convert 8bit -> 16bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #ifdef SNDRV_LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) get_user(c, (unsigned short __user *)buf + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) unsigned short cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) get_user(cc, (unsigned short __user *)buf + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) c = swab16(cc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (mode & SNDRV_SFNT_SAMPLE_UNSIGNED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) c ^= 0x8000; /* unsigned -> signed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^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) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) snd_emu8000_write_wait(struct snd_emu8000 *emu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) schedule_timeout_interruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^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) * write sample word data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * You should not have to keep resetting the address each time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * as the chip is supposed to step on the next address automatically.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * It mostly does, but during writes of some samples at random it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * completely loses words (every one in 16 roughly but with no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * obvious pattern).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * This is therefore much slower than need be, but is at least
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * working.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) write_word(struct snd_emu8000 *emu, int *offset, unsigned short data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (emu8000_reset_addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (emu8000_reset_addr > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) snd_emu8000_write_wait(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) EMU8000_SMALW_WRITE(emu, *offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) EMU8000_SMLD_WRITE(emu, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) *offset += 1;
^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) * Write the sample to EMU800 memory. This routine is invoked out of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * the generic soundfont routines as a callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct snd_util_memhdr *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) const void __user *data, long count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int truesize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int dram_offset, dram_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct snd_emu8000 *emu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) emu = rec->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (snd_BUG_ON(!sp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (sp->v.size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* be sure loop points start < end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (sp->v.loopstart > sp->v.loopend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) swap(sp->v.loopstart, sp->v.loopend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* compute true data size to be loaded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) truesize = sp->v.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) truesize += sp->v.loopend - sp->v.loopstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) truesize += BLANK_LOOP_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) sp->block = snd_util_mem_alloc(hdr, truesize * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (sp->block == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /*snd_printd("EMU8000: out of memory\n");*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /* not ENOMEM (for compatibility) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (!access_ok(data, sp->v.size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (!access_ok(data, sp->v.size * 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* recalculate address offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) sp->v.end -= sp->v.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) sp->v.loopstart -= sp->v.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) sp->v.loopend -= sp->v.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) sp->v.start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* dram position (in word) -- mem_offset is byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) dram_offset = EMU8000_DRAM_OFFSET + (sp->block->offset >> 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) dram_start = dram_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /* set the total size (store onto obsolete checksum value) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) sp->v.truesize = truesize * 2; /* in bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) snd_emux_terminate_all(emu->emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if ((rc = snd_emu8000_open_dma(emu, EMU8000_RAM_WRITE)) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /* Set the address to start writing at */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) snd_emu8000_write_wait(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) EMU8000_SMALW_WRITE(emu, dram_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /*snd_emu8000_init_fm(emu);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* first block - write 48 samples for silence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (! sp->block->offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) for (i = 0; i < BLANK_HEAD_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) write_word(emu, &dram_offset, 0);
^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) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) for (i = 0; i < sp->v.size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) unsigned short s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) s = read_word(data, offset, sp->v.mode_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) offset++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) write_word(emu, &dram_offset, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /* we may take too long time in this loop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * so give controls back to kernel if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (i == sp->v.loopend &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) int looplen = sp->v.loopend - sp->v.loopstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* copy reverse loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) for (k = 1; k <= looplen; k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) s = read_word(data, offset - k, sp->v.mode_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) write_word(emu, &dram_offset, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) sp->v.loopend += looplen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) sp->v.loopstart += looplen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) sp->v.loopend += looplen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) sp->v.end += looplen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /* if no blank loop is attached in the sample, add it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) for (i = 0; i < BLANK_LOOP_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) write_word(emu, &dram_offset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) sp->v.loopend = sp->v.end + BLANK_LOOP_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* add dram offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) sp->v.start += dram_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) sp->v.end += dram_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) sp->v.loopstart += dram_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) sp->v.loopend += dram_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) snd_emu8000_close_dma(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) snd_emu8000_init_fm(emu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return 0;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * free a sample block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) snd_emu8000_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct snd_util_memhdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (sp->block) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) snd_util_mem_free(hdr, sp->block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) sp->block = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * sample_reset callback - terminate voices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) snd_emu8000_sample_reset(struct snd_emux *rec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) snd_emux_terminate_all(rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }