Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }