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, loopsize, blocksize;
31 int loopend, sampleend;
32 unsigned int start_addr;
33 struct snd_emu10k1 *emu;
36 if (snd_BUG_ON(!sp || !hdr))
39 if (sp->v.size == 0) {
40 dev_dbg(emu->card->dev,
41 "emu: rom font for sample %d\n", sp->v.sample);
45 /* recalculate address offset */
46 sp->v.end -= sp->v.start;
47 sp->v.loopstart -= sp->v.start;
48 sp->v.loopend -= sp->v.start;
51 /* some samples have invalid data. the addresses are corrected in voice info */
52 sampleend = sp->v.end;
53 if (sampleend > sp->v.size)
54 sampleend = sp->v.size;
55 loopend = sp->v.loopend;
56 if (loopend > sampleend)
59 /* be sure loop points start < end */
60 if (sp->v.loopstart >= sp->v.loopend)
61 swap(sp->v.loopstart, sp->v.loopend);
63 /* compute true data size to be loaded */
64 truesize = sp->v.size + BLANK_HEAD_SIZE;
66 #if 0 /* not supported */
67 if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
68 loopsize = sp->v.loopend - sp->v.loopstart;
71 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK)
72 truesize += BLANK_LOOP_SIZE;
74 /* try to allocate a memory block */
76 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
78 sp->block = snd_emu10k1_synth_alloc(emu, blocksize);
79 if (sp->block == NULL) {
80 dev_dbg(emu->card->dev,
81 "synth malloc failed (size=%d)\n", blocksize);
82 /* not ENOMEM (for compatibility with OSS) */
85 /* set the total size */
86 sp->v.truesize = blocksize;
88 /* write blank samples at head */
90 size = BLANK_HEAD_SIZE;
91 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
93 if (offset + size > blocksize)
95 snd_emu10k1_synth_bzero(emu, sp->block, offset, size);
98 /* copy start->loopend */
100 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
102 if (offset + size > blocksize)
104 if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
105 snd_emu10k1_synth_free(emu, sp->block);
112 #if 0 /* not supported yet */
113 /* handle reverse (or bidirectional) loop */
114 if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) {
115 /* copy loop in reverse */
116 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
118 unsigned short *wblock = (unsigned short*)block;
119 woffset = offset / 2;
120 if (offset + loopsize * 2 > blocksize)
122 for (i = 0; i < loopsize; i++)
123 wblock[woffset + i] = wblock[woffset - i -1];
124 offset += loopsize * 2;
126 if (offset + loopsize > blocksize)
128 for (i = 0; i < loopsize; i++)
129 block[offset + i] = block[offset - i -1];
133 /* modify loop pointers */
134 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) {
135 sp->v.loopend += loopsize;
137 sp->v.loopstart += loopsize;
138 sp->v.loopend += loopsize;
140 /* add sample pointer */
141 sp->v.end += loopsize;
145 /* loopend -> sample end */
146 size = sp->v.size - loopend;
149 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
151 if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
152 snd_emu10k1_synth_free(emu, sp->block);
158 /* clear rest of samples (if any) */
159 if (offset < blocksize)
160 snd_emu10k1_synth_bzero(emu, sp->block, offset, blocksize - offset);
162 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
163 /* if no blank loop is attached in the sample, add it */
164 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
165 sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
166 sp->v.loopend = sp->v.end + BLANK_LOOP_END;
170 #if 0 /* not supported yet */
171 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) {
172 /* unsigned -> signed */
173 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
174 unsigned short *wblock = (unsigned short*)block;
175 for (i = 0; i < truesize; i++)
178 for (i = 0; i < truesize; i++)
184 /* recalculate offset */
185 start_addr = BLANK_HEAD_SIZE * 2;
186 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
188 sp->v.start += start_addr;
189 sp->v.end += start_addr;
190 sp->v.loopstart += start_addr;
191 sp->v.loopend += start_addr;
197 * free a sample block
200 snd_emu10k1_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
201 struct snd_util_memhdr *hdr)
203 struct snd_emu10k1 *emu;
206 if (snd_BUG_ON(!sp || !hdr))
210 snd_emu10k1_synth_free(emu, sp->block);