Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / AHI / Drivers / EMU10kx / voicemgr.c
blob54a44fc305d206cc81dd44e705d44ca20f8161fa
1 /*
2 **********************************************************************
3 * voicemgr.c - Voice manager for emu10k1 driver
4 * Copyright 1999, 2000 Creative Labs, Inc.
6 **********************************************************************
8 * Date Author Summary of changes
9 * ---- ------ ------------------
10 * October 20, 1999 Bertrand Lee base code release
12 **********************************************************************
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.
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.
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.
29 **********************************************************************
32 #ifdef AHI
33 #include <config.h>
35 #include "voicemgr.h"
36 #include "8010.h"
37 #include "pci_wrapper.h"
38 #endif
40 #define PITCH_48000 0x00004000
41 #define PITCH_96000 0x00008000
42 #define PITCH_85000 0x00007155
43 #define PITCH_80726 0x00006ba2
44 #define PITCH_67882 0x00005a82
45 #define PITCH_57081 0x00004c1c
47 u32 emu10k1_select_interprom(struct emu10k1_card *card, struct emu_voice *voice)
49 if(voice->pitch_target==PITCH_48000)
50 return CCCA_INTERPROM_0;
51 else if(voice->pitch_target<PITCH_48000)
52 return CCCA_INTERPROM_1;
53 else if(voice->pitch_target>=PITCH_96000)
54 return CCCA_INTERPROM_0;
55 else if(voice->pitch_target>=PITCH_85000)
56 return CCCA_INTERPROM_6;
57 else if(voice->pitch_target>=PITCH_80726)
58 return CCCA_INTERPROM_5;
59 else if(voice->pitch_target>=PITCH_67882)
60 return CCCA_INTERPROM_4;
61 else if(voice->pitch_target>=PITCH_57081)
62 return CCCA_INTERPROM_3;
63 else
64 return CCCA_INTERPROM_2;
68 /**
69 * emu10k1_voice_alloc_buffer -
71 * allocates the memory buffer for a voice. Two page tables are kept for each buffer.
72 * One (dma_handle) keeps track of the host memory pages used and the other (virtualpagetable)
73 * is passed to the device so that it can do DMA to host memory.
76 int emu10k1_voice_alloc_buffer(struct emu10k1_card *card, struct voice_mem *mem, u32 pages)
78 u32 pageindex, pagecount;
79 u32 busaddx;
80 int i;
82 DPD(2, "requested pages is: %d\n", pages);
84 if ((mem->emupageindex = emu10k1_addxmgr_alloc(pages * PAGE_SIZE, card)) < 0)
86 DPF(1, "couldn't allocate emu10k1 address space\n");
87 return -1;
90 #ifdef AHI
91 if ((mem->addr = pci_alloc_consistent(card->pci_dev, pages * PAGE_SIZE, &mem->dma_handle))
92 == NULL) {
93 mem->pages = 0;
94 DPF(1, "couldn't allocate dma memory\n");
95 return -1;
97 // KPrintF("Got addr %08lx, dma handler %08lx\n", mem->addr, mem->dma_handle);
98 #endif
100 /* Fill in virtual memory table */
101 for (pagecount = 0; pagecount < pages; pagecount++) {
102 #ifndef AHI
103 if ((mem->addr[pagecount] = pci_alloc_consistent(card->pci_dev, PAGE_SIZE, &mem->dma_handle[pagecount]))
104 == NULL) {
105 mem->pages = pagecount;
106 DPF(1, "couldn't allocate dma memory\n");
107 return -1;
110 DPD(2, "Virtual Addx: %p\n", mem->addr[pagecount]);
111 #endif
112 for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
113 #ifdef AHI
114 busaddx = (u32) ahi_pci_logic_to_physic_addr(
115 mem->addr + pagecount * PAGE_SIZE, card->pci_dev )
116 + i * EMUPAGESIZE;
117 #else
118 busaddx = (u32) mem->dma_handle[pagecount] + i * EMUPAGESIZE;
119 #endif
120 // KPrintF("Got bus addr %08lx for address %08lx\n", busaddx, mem->addr + pagecount * PAGE_SIZE);
122 DPD(3, "Bus Addx: %#x\n", busaddx);
124 pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
126 ((u32 *) card->virtualpagetable.addr)[pageindex] = cpu_to_le32((busaddx * 2) | pageindex);
130 mem->pages = pagecount;
132 return 0;
136 * emu10k1_voice_free_buffer -
138 * frees the memory buffer for a voice.
140 void emu10k1_voice_free_buffer(struct emu10k1_card *card, struct voice_mem *mem)
142 u32 pagecount, pageindex;
143 int i;
145 if (mem->emupageindex < 0)
146 return;
148 #ifdef AHI
149 pci_free_consistent(card->pci_dev, mem->pages * PAGE_SIZE,
150 mem->addr,
151 mem->dma_handle);
152 #endif
153 for (pagecount = 0; pagecount < mem->pages; pagecount++) {
154 #ifndef AHI
155 pci_free_consistent(card->pci_dev, PAGE_SIZE,
156 mem->addr[pagecount],
157 mem->dma_handle[pagecount]);
158 #endif
160 for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
161 pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
162 ((u32 *) card->virtualpagetable.addr)[pageindex] =
163 cpu_to_le32(((u32) card->silentpage.dma_handle * 2) | pageindex);
167 emu10k1_addxmgr_free(card, mem->emupageindex);
168 mem->emupageindex = -1;
171 int emu10k1_voice_alloc(struct emu10k1_card *card, struct emu_voice *voice)
173 u8 *voicetable = card->voicetable;
174 int i;
175 #ifndef AHI
176 unsigned long flags;
177 #endif
179 DPF(2, "emu10k1_voice_alloc()\n");
181 spin_lock_irqsave(&card->lock, flags);
183 if (voice->flags & VOICE_FLAGS_STEREO) {
184 for (i = 0; i < NUM_G; i += 2)
185 if ((voicetable[i] == VOICE_USAGE_FREE) && (voicetable[i + 1] == VOICE_USAGE_FREE)) {
186 voicetable[i] = voice->usage;
187 voicetable[i + 1] = voice->usage;
188 break;
190 } else {
191 for (i = 0; i < NUM_G; i++)
192 if (voicetable[i] == VOICE_USAGE_FREE) {
193 voicetable[i] = voice->usage;
194 break;
198 spin_unlock_irqrestore(&card->lock, flags);
200 if (i >= NUM_G)
201 return -1;
203 voice->card = card;
204 voice->num = i;
206 for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
207 DPD(2, " voice allocated -> %d\n", voice->num + i);
209 sblive_writeptr_tag(card, voice->num + i, IFATN, 0xffff,
210 DCYSUSV, 0,
211 VTFT, 0x0000ffff,
212 PTRX, 0,
213 TAGLIST_END);
216 return 0;
219 void emu10k1_voice_free(struct emu_voice *voice)
221 struct emu10k1_card *card = voice->card;
222 int i;
223 #ifndef AHI
224 unsigned long flags;
225 #endif
227 DPF(2, "emu10k1_voice_free()\n");
229 if (voice->usage == VOICE_USAGE_FREE)
230 return;
232 for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
233 DPD(2, " voice released -> %d\n", voice->num + i);
235 sblive_writeptr_tag(card, voice->num + i, DCYSUSV, 0,
236 VTFT, 0x0000ffff,
237 PTRX_PITCHTARGET, 0,
238 CVCF, 0x0000ffff,
239 //CPF, 0,
240 TAGLIST_END);
242 sblive_writeptr(card, CPF, voice->num + i, 0);
245 voice->usage = VOICE_USAGE_FREE;
247 spin_lock_irqsave(&card->lock, flags);
249 card->voicetable[voice->num] = VOICE_USAGE_FREE;
251 if (voice->flags & VOICE_FLAGS_STEREO)
252 card->voicetable[voice->num + 1] = VOICE_USAGE_FREE;
254 spin_unlock_irqrestore(&card->lock, flags);
257 void emu10k1_voice_playback_setup(struct emu_voice *voice)
259 struct emu10k1_card *card = voice->card;
260 u32 start;
261 int i;
263 DPF(2, "emu10k1_voice_playback_setup()\n");
265 if (voice->flags & VOICE_FLAGS_STEREO) {
266 /* Set stereo bit */
267 start = 28;
268 sblive_writeptr(card, CPF, voice->num, CPF_STEREO_MASK);
269 sblive_writeptr(card, CPF, voice->num + 1, CPF_STEREO_MASK);
270 } else {
271 start = 30;
272 sblive_writeptr(card, CPF, voice->num, 0);
275 if(!(voice->flags & VOICE_FLAGS_16BIT))
276 start *= 2;
278 voice->start += start;
280 for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
281 if (card->is_audigy) {
282 sblive_writeptr(card, A_FXRT1, voice->num + i, voice->params[i].send_routing);
283 sblive_writeptr(card, A_FXRT2, voice->num + i, voice->params[i].send_routing2);
284 sblive_writeptr(card, A_SENDAMOUNTS, voice->num + i, voice->params[i].send_hgfe);
285 } else {
286 sblive_writeptr(card, FXRT, voice->num + i, voice->params[i].send_routing << 16);
289 /* Stop CA */
290 /* Assumption that PT is already 0 so no harm overwriting */
291 sblive_writeptr(card, PTRX, voice->num + i, ((voice->params[i].send_dcba & 0xff) << 8)
292 | ((voice->params[i].send_dcba & 0xff00) >> 8));
294 sblive_writeptr_tag(card, voice->num + i,
295 /* CSL, ST, CA */
296 DSL, voice->endloop | (voice->params[i].send_dcba & 0xff000000),
297 PSST, voice->startloop | ((voice->params[i].send_dcba & 0x00ff0000) << 8),
298 CCCA, (voice->start) | emu10k1_select_interprom(card,voice) |
299 ((voice->flags & VOICE_FLAGS_16BIT) ? 0 : CCCA_8BITSELECT),
300 /* Clear filter delay memory */
301 Z1, 0,
302 Z2, 0,
303 /* Invalidate maps */
304 MAPA, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
305 MAPB, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
306 /* modulation envelope */
307 CVCF, 0x0000ffff,
308 VTFT, 0x0000ffff,
309 ATKHLDM, 0,
310 DCYSUSM, 0x007f,
311 LFOVAL1, 0x8000,
312 LFOVAL2, 0x8000,
313 FMMOD, 0,
314 TREMFRQ, 0,
315 FM2FRQ2, 0,
316 ENVVAL, 0x8000,
317 /* volume envelope */
318 ATKHLDV, 0x7f7f,
319 ENVVOL, 0x8000,
320 /* filter envelope */
321 PEFE_FILTERAMOUNT, 0x7f,
322 /* pitch envelope */
323 PEFE_PITCHAMOUNT, 0, TAGLIST_END);
325 voice->params[i].fc_target = 0xffff;
329 void emu10k1_voices_start(struct emu_voice *first_voice, unsigned int num_voices, int set)
331 struct emu10k1_card *card = first_voice->card;
332 struct emu_voice *voice;
333 unsigned int voicenum;
334 int j;
336 DPF(2, "emu10k1_voices_start()\n");
338 for (voicenum = 0; voicenum < num_voices; voicenum++)
340 voice = first_voice + voicenum;
342 if (!set) {
343 u32 cra, ccis, cs, sample;
344 if (voice->flags & VOICE_FLAGS_STEREO) {
345 cra = 64;
346 ccis = 28;
347 cs = 4;
348 } else {
349 cra = 64;
350 ccis = 30;
351 cs = 2;
354 if(voice->flags & VOICE_FLAGS_16BIT) {
355 sample = 0x00000000;
356 } else {
357 sample = 0x80808080;
358 ccis *= 2;
361 for(j = 0; j < cs; j++)
362 sblive_writeptr(card, CD0 + j, voice->num, sample);
364 /* Reset cache */
365 sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num, 0);
366 if (voice->flags & VOICE_FLAGS_STEREO)
367 sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num + 1, 0);
369 sblive_writeptr(card, CCR_READADDRESS, voice->num, cra);
371 if (voice->flags & VOICE_FLAGS_STEREO)
372 sblive_writeptr(card, CCR_READADDRESS, voice->num + 1, cra);
374 /* Fill cache */
375 sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num, ccis);
378 for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
379 sblive_writeptr_tag(card, voice->num + j,
380 IFATN, (voice->params[j].initial_fc << 8) | voice->params[j].initial_attn,
381 VTFT, (voice->params[j].volume_target << 16) | voice->params[j].fc_target,
382 CVCF, (voice->params[j].volume_target << 16) | voice->params[j].fc_target,
383 DCYSUSV, (voice->params[j].byampl_env_sustain << 8) | voice->params[j].byampl_env_decay,
384 TAGLIST_END);
386 emu10k1_clear_stop_on_loop(card, voice->num + j);
391 for (voicenum = 0; voicenum < num_voices; voicenum++)
393 voice = first_voice + voicenum;
395 for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
396 sblive_writeptr(card, PTRX_PITCHTARGET, voice->num + j, voice->pitch_target);
398 if (j == 0)
399 sblive_writeptr(card, CPF_CURRENTPITCH, voice->num, voice->pitch_target);
401 sblive_writeptr(card, IP, voice->num + j, voice->initial_pitch);
406 void emu10k1_voices_stop(struct emu_voice *first_voice, int num_voices)
408 struct emu10k1_card *card = first_voice->card;
409 struct emu_voice *voice;
410 unsigned int voice_num;
411 int j;
413 DPF(2, "emu10k1_voice_stop()\n");
415 for (voice_num = 0; voice_num < num_voices; voice_num++)
417 voice = first_voice + voice_num;
419 for (j = 0; j < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); j++) {
420 sblive_writeptr_tag(card, voice->num + j,
421 PTRX_PITCHTARGET, 0,
422 CPF_CURRENTPITCH, 0,
423 IFATN, 0xffff,
424 VTFT, 0x0000ffff,
425 CVCF, 0x0000ffff,
426 IP, 0,
427 TAGLIST_END);