^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 transfer callback for Emu10k1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * All the code for loading in a patch. There is very little that is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * chip specific here. Just the actual writing to the board.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "emu10k1_synth_local.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define BLANK_LOOP_START 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define BLANK_LOOP_END 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define BLANK_LOOP_SIZE 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define BLANK_HEAD_SIZE 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * allocate a sample block and copy data from userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct snd_util_memhdr *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) const void __user *data, long count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int truesize, size, blocksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) __maybe_unused int loopsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int loopend, sampleend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) unsigned int start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct snd_emu10k1 *emu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) emu = rec->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (snd_BUG_ON(!sp || !hdr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (sp->v.size == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) dev_dbg(emu->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) "emu: rom font for sample %d\n", sp->v.sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* recalculate address offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) sp->v.end -= sp->v.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) sp->v.loopstart -= sp->v.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) sp->v.loopend -= sp->v.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) sp->v.start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /* some samples have invalid data. the addresses are corrected in voice info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) sampleend = sp->v.end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (sampleend > sp->v.size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) sampleend = sp->v.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) loopend = sp->v.loopend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (loopend > sampleend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) loopend = sampleend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* be sure loop points start < end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (sp->v.loopstart >= sp->v.loopend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) swap(sp->v.loopstart, sp->v.loopend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* compute true data size to be loaded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) truesize = sp->v.size + BLANK_HEAD_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) loopsize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #if 0 /* not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) loopsize = sp->v.loopend - sp->v.loopstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) truesize += loopsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) truesize += BLANK_LOOP_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* try to allocate a memory block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) blocksize = truesize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) blocksize *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) sp->block = snd_emu10k1_synth_alloc(emu, blocksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (sp->block == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) dev_dbg(emu->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) "synth malloc failed (size=%d)\n", blocksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* not ENOMEM (for compatibility with OSS) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* set the total size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) sp->v.truesize = blocksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* write blank samples at head */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) size = BLANK_HEAD_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) size *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (offset + size > blocksize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) snd_emu10k1_synth_bzero(emu, sp->block, offset, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) offset += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* copy start->loopend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) size = loopend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) size *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (offset + size > blocksize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) snd_emu10k1_synth_free(emu, sp->block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) sp->block = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) offset += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) data += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #if 0 /* not supported yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* handle reverse (or bidirectional) loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* copy loop in reverse */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int woffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) unsigned short *wblock = (unsigned short*)block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) woffset = offset / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (offset + loopsize * 2 > blocksize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) for (i = 0; i < loopsize; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) wblock[woffset + i] = wblock[woffset - i -1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) offset += loopsize * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (offset + loopsize > blocksize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) for (i = 0; i < loopsize; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) block[offset + i] = block[offset - i -1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) offset += loopsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* modify loop pointers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) sp->v.loopend += loopsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) sp->v.loopstart += loopsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) sp->v.loopend += loopsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* add sample pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) sp->v.end += loopsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* loopend -> sample end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) size = sp->v.size - loopend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (size < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) size *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) snd_emu10k1_synth_free(emu, sp->block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) sp->block = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) offset += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* clear rest of samples (if any) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (offset < blocksize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) snd_emu10k1_synth_bzero(emu, sp->block, offset, blocksize - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* if no blank loop is attached in the sample, add it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) sp->v.loopend = sp->v.end + BLANK_LOOP_END;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #if 0 /* not supported yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* unsigned -> signed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) unsigned short *wblock = (unsigned short*)block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) for (i = 0; i < truesize; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) wblock[i] ^= 0x8000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) for (i = 0; i < truesize; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) block[i] ^= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* recalculate offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) start_addr = BLANK_HEAD_SIZE * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) start_addr >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) sp->v.start += start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) sp->v.end += start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) sp->v.loopstart += start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) sp->v.loopend += start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * free a sample block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) snd_emu10k1_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct snd_util_memhdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct snd_emu10k1 *emu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) emu = rec->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (snd_BUG_ON(!sp || !hdr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (sp->block) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) snd_emu10k1_synth_free(emu, sp->block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) sp->block = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)