1 /*
2 **********************************************************************
3 * voicemgr.c - Voice manager for emu10k1 driver
4 * Copyright 1999, 2000 Creative Labs, Inc.
5 *
6 **********************************************************************
7 *
8 * Date Author Summary of changes
9 * ---- ------ ------------------
10 * October 20, 1999 Bertrand Lee base code release
11 *
12 **********************************************************************
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of
17 * the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public
25 * License along with this program; if not, write to the Free
26 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
27 * USA.
28 *
29 **********************************************************************
30 */
31
32 #include "voicemgr.h"
33 #include "8010.h"
34
35 /**
36 * emu10k1_voice_alloc_buffer -
37 *
38 * allocates the memory buffer for a voice. Two page tables are kept for each buffer.
39 * One (dma_handle) keeps track of the host memory pages used and the other (virtualpagetable)
40 * is passed to the device so that it can do DMA to host memory.
41 *
42 */
emu10k1_voice_alloc_buffer(struct emu10k1_card * card,struct voice_mem * mem,u32 pages)43 int emu10k1_voice_alloc_buffer(struct emu10k1_card *card, struct voice_mem *mem, u32 pages)
44 {
45 u32 pageindex, pagecount;
46 u32 busaddx;
47 int i;
48
49 DPD(2, "requested pages is: %d\n", pages);
50
51 if ((mem->emupageindex = emu10k1_addxmgr_alloc(pages * PAGE_SIZE, card)) < 0)
52 {
53 DPF(1, "couldn't allocate emu10k1 address space\n");
54 return -1;
55 }
56
57 /* Fill in virtual memory table */
58 for (pagecount = 0; pagecount < pages; pagecount++) {
59 if ((mem->addr[pagecount] = pci_alloc_consistent(card->pci_dev, PAGE_SIZE, &mem->dma_handle[pagecount]))
60 == NULL) {
61 mem->pages = pagecount;
62 DPF(1, "couldn't allocate dma memory\n");
63 return -1;
64 }
65
66 DPD(2, "Virtual Addx: %p\n", mem->addr[pagecount]);
67
68 for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
69 busaddx = (u32) mem->dma_handle[pagecount] + i * EMUPAGESIZE;
70
71 DPD(3, "Bus Addx: %#x\n", busaddx);
72
73 pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
74
75 ((u32 *) card->virtualpagetable.addr)[pageindex] = cpu_to_le32((busaddx * 2) | pageindex);
76 }
77 }
78
79 mem->pages = pagecount;
80
81 return 0;
82 }
83
84 /**
85 * emu10k1_voice_free_buffer -
86 *
87 * frees the memory buffer for a voice.
88 */
emu10k1_voice_free_buffer(struct emu10k1_card * card,struct voice_mem * mem)89 void emu10k1_voice_free_buffer(struct emu10k1_card *card, struct voice_mem *mem)
90 {
91 u32 pagecount, pageindex;
92 int i;
93
94 if (mem->emupageindex < 0)
95 return;
96
97 for (pagecount = 0; pagecount < mem->pages; pagecount++) {
98 pci_free_consistent(card->pci_dev, PAGE_SIZE,
99 mem->addr[pagecount],
100 mem->dma_handle[pagecount]);
101
102 for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
103 pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
104 ((u32 *) card->virtualpagetable.addr)[pageindex] =
105 cpu_to_le32(((u32) card->silentpage.dma_handle * 2) | pageindex);
106 }
107 }
108
109 emu10k1_addxmgr_free(card, mem->emupageindex);
110 mem->emupageindex = -1;
111 }
112
emu10k1_voice_alloc(struct emu10k1_card * card,struct emu_voice * voice)113 int emu10k1_voice_alloc(struct emu10k1_card *card, struct emu_voice *voice)
114 {
115 u8 *voicetable = card->voicetable;
116 int i;
117 unsigned long flags;
118
119 DPF(2, "emu10k1_voice_alloc()\n");
120
121 spin_lock_irqsave(&card->lock, flags);
122
123 if (voice->flags & VOICE_FLAGS_STEREO) {
124 for (i = 0; i < NUM_G; i += 2)
125 if ((voicetable[i] == VOICE_USAGE_FREE) && (voicetable[i + 1] == VOICE_USAGE_FREE)) {
126 voicetable[i] = voice->usage;
127 voicetable[i + 1] = voice->usage;
128 break;
129 }
130 } else {
131 for (i = 0; i < NUM_G; i++)
132 if (voicetable[i] == VOICE_USAGE_FREE) {
133 voicetable[i] = voice->usage;
134 break;
135 }
136 }
137
138 spin_unlock_irqrestore(&card->lock, flags);
139
140 if (i >= NUM_G)
141 return -1;
142
143 voice->card = card;
144 voice->num = i;
145
146 for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
147 DPD(2, " voice allocated -> %d\n", voice->num + i);
148
149 sblive_writeptr_tag(card, voice->num + i, IFATN, 0xffff,
150 DCYSUSV, 0,
151 VTFT, 0x0000ffff,
152 PTRX, 0,
153 TAGLIST_END);
154 }
155
156 return 0;
157 }
158
emu10k1_voice_free(struct emu_voice * voice)159 void emu10k1_voice_free(struct emu_voice *voice)
160 {
161 struct emu10k1_card *card = voice->card;
162 int i;
163 unsigned long flags;
164
165 DPF(2, "emu10k1_voice_free()\n");
166
167 if (voice->usage == VOICE_USAGE_FREE)
168 return;
169
170 for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
171 DPD(2, " voice released -> %d\n", voice->num + i);
172
173 sblive_writeptr_tag(card, voice->num + i, DCYSUSV, 0,
174 VTFT, 0x0000ffff,
175 PTRX_PITCHTARGET, 0,
176 CVCF, 0x0000ffff,
177 //CPF, 0,
178 TAGLIST_END);
179
180 sblive_writeptr(card, CPF, voice->num + i, 0);
181 }
182
183 voice->usage = VOICE_USAGE_FREE;
184
185 spin_lock_irqsave(&card->lock, flags);
186
187 card->voicetable[voice->num] = VOICE_USAGE_FREE;
188
189 if (voice->flags & VOICE_FLAGS_STEREO)
190 card->voicetable[voice->num + 1] = VOICE_USAGE_FREE;
191
192 spin_unlock_irqrestore(&card->lock, flags);
193 }
194
emu10k1_voice_playback_setup(struct emu_voice * voice)195 void emu10k1_voice_playback_setup(struct emu_voice *voice)
196 {
197 struct emu10k1_card *card = voice->card;
198 u32 start;
199 int i;
200
201 DPF(2, "emu10k1_voice_playback_setup()\n");
202
203 if (voice->flags & VOICE_FLAGS_STEREO) {
204 /* Set stereo bit */
205 start = 28;
206 sblive_writeptr(card, CPF, voice->num, CPF_STEREO_MASK);
207 sblive_writeptr(card, CPF, voice->num + 1, CPF_STEREO_MASK);
208 } else {
209 start = 30;
210 sblive_writeptr(card, CPF, voice->num, 0);
211 }
212
213 if(!(voice->flags & VOICE_FLAGS_16BIT))
214 start *= 2;
215
216 voice->start += start;
217
218 for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
219 sblive_writeptr(card, FXRT, voice->num + i, voice->params[i].send_routing << 16);
220
221 /* Stop CA */
222 /* Assumption that PT is already 0 so no harm overwriting */
223 sblive_writeptr(card, PTRX, voice->num + i, (voice->params[i].send_a << 8) | voice->params[i].send_b);
224
225 sblive_writeptr_tag(card, voice->num + i,
226 /* CSL, ST, CA */
227 DSL, voice->endloop | (voice->params[i].send_d << 24),
228 PSST, voice->startloop | (voice->params[i].send_c << 24),
229 CCCA, (voice->start) | CCCA_INTERPROM_0 | ((voice->flags & VOICE_FLAGS_16BIT) ? 0 : CCCA_8BITSELECT),
230 /* Clear filter delay memory */
231 Z1, 0,
232 Z2, 0,
233 /* Invalidate maps */
234 MAPA, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
235 MAPB, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
236 /* modulation envelope */
237 CVCF, 0x0000ffff,
238 VTFT, 0x0000ffff,
239 ATKHLDM, 0,
240 DCYSUSM, 0x007f,
241 LFOVAL1, 0x8000,
242 LFOVAL2, 0x8000,
243 FMMOD, 0,
244 TREMFRQ, 0,
245 FM2FRQ2, 0,
246 ENVVAL, 0x8000,
247 /* volume envelope */
248 ATKHLDV, 0x7f7f,
249 ENVVOL, 0x8000,
250 /* filter envelope */
251 PEFE_FILTERAMOUNT, 0x7f,
252 /* pitch envelope */
253 PEFE_PITCHAMOUNT, 0, TAGLIST_END);
254
255 voice->params[i].fc_target = 0xffff;
256 }
257 }
258
emu10k1_voices_start(struct emu_voice * first_voice,unsigned int num_voices,int set)259 void emu10k1_voices_start(struct emu_voice *first_voice, unsigned int num_voices, int set)
260 {
261 struct emu10k1_card *card = first_voice->card;
262 struct emu_voice *voice;
263 unsigned int voicenum;
264 int j;
265
266 DPF(2, "emu10k1_voices_start()\n");
267
268 for (voicenum = 0; voicenum < num_voices; voicenum++)
269 {
270 voice = first_voice + voicenum;
271
272 if (!set) {
273 u32 cra, ccis, cs, sample;
274 if (voice->flags & VOICE_FLAGS_STEREO) {
275 cra = 64;
276 ccis = 28;
277 cs = 4;
278 } else {
279 cra = 64;
280 ccis = 30;
281 cs = 2;
282 }
283
284 if(voice->flags & VOICE_FLAGS_16BIT) {
285 sample = 0x00000000;
286 } else {
287 sample = 0x80808080;
288 ccis *= 2;
289 }
290
291 for(j = 0; j < cs; j++)
292 sblive_writeptr(card, CD0 + j, voice->num, sample);
293
294 /* Reset cache */
295 sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num, 0);
296 if (voice->flags & VOICE_FLAGS_STEREO)
297 sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num + 1, 0);
298
299 sblive_writeptr(card, CCR_READADDRESS, voice->num, cra);
300
301 if (voice->flags & VOICE_FLAGS_STEREO)
302 sblive_writeptr(card, CCR_READADDRESS, voice->num + 1, cra);
303
304 /* Fill cache */
305 sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num, ccis);
306 }
307
308 for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
309 sblive_writeptr_tag(card, voice->num + j,
310 IFATN, (voice->params[j].initial_fc << 8) | voice->params[j].initial_attn,
311 VTFT, (voice->params[j].volume_target << 16) | voice->params[j].fc_target,
312 CVCF, (voice->params[j].volume_target << 16) | voice->params[j].fc_target,
313 DCYSUSV, (voice->params[j].byampl_env_sustain << 8) | voice->params[j].byampl_env_decay,
314 TAGLIST_END);
315
316 emu10k1_clear_stop_on_loop(card, voice->num + j);
317 }
318 }
319
320
321 for (voicenum = 0; voicenum < num_voices; voicenum++)
322 {
323 voice = first_voice + voicenum;
324
325 for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
326 sblive_writeptr(card, PTRX_PITCHTARGET, voice->num + j, voice->pitch_target);
327
328 if (j == 0)
329 sblive_writeptr(card, CPF_CURRENTPITCH, voice->num, voice->pitch_target);
330
331 sblive_writeptr(card, IP, voice->num + j, voice->initial_pitch);
332 }
333 }
334 }
335
emu10k1_voices_stop(struct emu_voice * first_voice,int num_voices)336 void emu10k1_voices_stop(struct emu_voice *first_voice, int num_voices)
337 {
338 struct emu10k1_card *card = first_voice->card;
339 struct emu_voice *voice;
340 unsigned int voice_num;
341 int j;
342
343 DPF(2, "emu10k1_voice_stop()\n");
344
345 for (voice_num = 0; voice_num < num_voices; voice_num++)
346 {
347 voice = first_voice + voice_num;
348
349 for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
350 sblive_writeptr_tag(card, voice->num + j,
351 PTRX_PITCHTARGET, 0,
352 CPF_CURRENTPITCH, 0,
353 IFATN, 0xffff,
354 VTFT, 0x0000ffff,
355 CVCF, 0x0000ffff,
356 IP, 0,
357 TAGLIST_END);
358 }
359 }
360 }
361
362