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 */
43int 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 */
89void 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
113int 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
159void 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
195void 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
259void 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
336void 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