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