1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Patch transfer callback for Emu10k1
5 * Copyright (C) 2000 Takashi iwai <tiwai@suse.de>
8 * All the code for loading in a patch. There is very little that is
9 * chip specific here. Just the actual writing to the board.
12 #include "emu10k1_synth_local.h"
16 #define BLANK_LOOP_START 4
17 #define BLANK_LOOP_END 8
18 #define BLANK_LOOP_SIZE 12
19 #define BLANK_HEAD_SIZE 32
22 * allocate a sample block and copy data from userspace
25 snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
26 struct snd_util_memhdr *hdr,
27 const void __user *data, long count)
30 int truesize, size, blocksize;
31 __maybe_unused int loopsize;
32 int loopend, sampleend;
33 unsigned int start_addr;
34 struct snd_emu10k1 *emu;
37 if (snd_BUG_ON(!sp || !hdr))
40 if (sp->v.size == 0) {
41 dev_dbg(emu->card->dev,
42 "emu: rom font for sample %d\n", sp->v.sample);
46 /* recalculate address offset */
47 sp->v.end -= sp->v.start;
48 sp->v.loopstart -= sp->v.start;
49 sp->v.loopend -= sp->v.start;
52 /* some samples have invalid data. the addresses are corrected in voice info */
53 sampleend = sp->v.end;
54 if (sampleend > sp->v.size)
55 sampleend = sp->v.size;
56 loopend = sp->v.loopend;
57 if (loopend > sampleend)
60 /* be sure loop points start < end */
61 if (sp->v.loopstart >= sp->v.loopend)
62 swap(sp->v.loopstart, sp->v.loopend);
64 /* compute true data size to be loaded */
65 truesize = sp->v.size + BLANK_HEAD_SIZE;
67 #if 0 /* not supported */
68 if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
69 loopsize = sp->v.loopend - sp->v.loopstart;
72 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK)
73 truesize += BLANK_LOOP_SIZE;
75 /* try to allocate a memory block */
77 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
79 sp->block = snd_emu10k1_synth_alloc(emu, blocksize);
80 if (sp->block == NULL) {
81 dev_dbg(emu->card->dev,
82 "synth malloc failed (size=%d)\n", blocksize);
83 /* not ENOMEM (for compatibility with OSS) */
86 /* set the total size */
87 sp->v.truesize = blocksize;
89 /* write blank samples at head */
91 size = BLANK_HEAD_SIZE;
92 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
94 if (offset + size > blocksize)
96 snd_emu10k1_synth_bzero(emu, sp->block, offset, size);
99 /* copy start->loopend */
101 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
103 if (offset + size > blocksize)
105 if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
106 snd_emu10k1_synth_free(emu, sp->block);
113 #if 0 /* not supported yet */
114 /* handle reverse (or bidirectional) loop */
115 if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) {
116 /* copy loop in reverse */
117 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
119 unsigned short *wblock = (unsigned short*)block;
120 woffset = offset / 2;
121 if (offset + loopsize * 2 > blocksize)
123 for (i = 0; i < loopsize; i++)
124 wblock[woffset + i] = wblock[woffset - i -1];
125 offset += loopsize * 2;
127 if (offset + loopsize > blocksize)
129 for (i = 0; i < loopsize; i++)
130 block[offset + i] = block[offset - i -1];
134 /* modify loop pointers */
135 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) {
136 sp->v.loopend += loopsize;
138 sp->v.loopstart += loopsize;
139 sp->v.loopend += loopsize;
141 /* add sample pointer */
142 sp->v.end += loopsize;
146 /* loopend -> sample end */
147 size = sp->v.size - loopend;
150 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
152 if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
153 snd_emu10k1_synth_free(emu, sp->block);
159 /* clear rest of samples (if any) */
160 if (offset < blocksize)
161 snd_emu10k1_synth_bzero(emu, sp->block, offset, blocksize - offset);
163 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
164 /* if no blank loop is attached in the sample, add it */
165 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
166 sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
167 sp->v.loopend = sp->v.end + BLANK_LOOP_END;
171 #if 0 /* not supported yet */
172 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) {
173 /* unsigned -> signed */
174 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
175 unsigned short *wblock = (unsigned short*)block;
176 for (i = 0; i < truesize; i++)
179 for (i = 0; i < truesize; i++)
185 /* recalculate offset */
186 start_addr = BLANK_HEAD_SIZE * 2;
187 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
189 sp->v.start += start_addr;
190 sp->v.end += start_addr;
191 sp->v.loopstart += start_addr;
192 sp->v.loopend += start_addr;
198 * free a sample block
201 snd_emu10k1_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
202 struct snd_util_memhdr *hdr)
204 struct snd_emu10k1 *emu;
207 if (snd_BUG_ON(!sp || !hdr))
211 snd_emu10k1_synth_free(emu, sp->block);