1 /*************************************************************************** 2 * au88x0_a3d.c 3 * 4 * Fri Jul 18 14:16:22 2003 5 * Copyright 2003 mjander 6 * mjander@users.sourceforge.net 7 * 8 * A3D. You may think i'm crazy, but this may work someday. Who knows... 9 ****************************************************************************/ 10 11 /* 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU Library General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 25 */ 26 27 #include "au88x0_a3d.h" 28 #include "au88x0_a3ddata.c" 29 #include "au88x0_xtalk.h" 30 #include "au88x0.h" 31 32 static void 33 a3dsrc_SetTimeConsts(a3dsrc_t * a, short HrtfTrack, short ItdTrack, 34 short GTrack, short CTrack) 35 { 36 vortex_t *vortex = (vortex_t *) (a->vortex); 37 hwwrite(vortex->mmio, 38 a3d_addrA(a->slice, a->source, A3D_A_HrtfTrackTC), HrtfTrack); 39 hwwrite(vortex->mmio, 40 a3d_addrA(a->slice, a->source, A3D_A_ITDTrackTC), ItdTrack); 41 hwwrite(vortex->mmio, 42 a3d_addrA(a->slice, a->source, A3D_A_GainTrackTC), GTrack); 43 hwwrite(vortex->mmio, 44 a3d_addrA(a->slice, a->source, A3D_A_CoeffTrackTC), CTrack); 45 } 46 47 #if 0 48 static void 49 a3dsrc_GetTimeConsts(a3dsrc_t * a, short *HrtfTrack, short *ItdTrack, 50 short *GTrack, short *CTrack) 51 { 52 // stub! 53 } 54 55 #endif 56 /* Atmospheric absorbtion. */ 57 58 static void 59 a3dsrc_SetAtmosTarget(a3dsrc_t * a, short aa, short b, short c, short d, 60 short e) 61 { 62 vortex_t *vortex = (vortex_t *) (a->vortex); 63 hwwrite(vortex->mmio, 64 a3d_addrB(a->slice, a->source, A3D_B_A21Target), 65 (e << 0x10) | d); 66 hwwrite(vortex->mmio, 67 a3d_addrB(a->slice, a->source, A3D_B_B10Target), 68 (b << 0x10) | aa); 69 hwwrite(vortex->mmio, 70 a3d_addrB(a->slice, a->source, A3D_B_B2Target), c); 71 } 72 73 static void 74 a3dsrc_SetAtmosCurrent(a3dsrc_t * a, short aa, short b, short c, short d, 75 short e) 76 { 77 vortex_t *vortex = (vortex_t *) (a->vortex); 78 hwwrite(vortex->mmio, 79 a3d_addrB(a->slice, a->source, A3D_B_A12Current), 80 (e << 0x10) | d); 81 hwwrite(vortex->mmio, 82 a3d_addrB(a->slice, a->source, A3D_B_B01Current), 83 (b << 0x10) | aa); 84 hwwrite(vortex->mmio, 85 a3d_addrB(a->slice, a->source, A3D_B_B2Current), c); 86 } 87 88 static void 89 a3dsrc_SetAtmosState(a3dsrc_t * a, short x1, short x2, short y1, short y2) 90 { 91 vortex_t *vortex = (vortex_t *) (a->vortex); 92 hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_x1), x1); 93 hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_x2), x2); 94 hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_y1), y1); 95 hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_y2), y2); 96 } 97 98 #if 0 99 static void 100 a3dsrc_GetAtmosTarget(a3dsrc_t * a, short *aa, short *b, short *c, 101 short *d, short *e) 102 { 103 } 104 static void 105 a3dsrc_GetAtmosCurrent(a3dsrc_t * a, short *bb01, short *ab01, short *b2, 106 short *aa12, short *ba12) 107 { 108 vortex_t *vortex = (vortex_t *) (a->vortex); 109 *aa12 = 110 hwread(vortex->mmio, 111 a3d_addrA(a->slice, a->source, A3D_A_A12Current)); 112 *ba12 = 113 hwread(vortex->mmio, 114 a3d_addrB(a->slice, a->source, A3D_B_A12Current)); 115 *ab01 = 116 hwread(vortex->mmio, 117 a3d_addrA(a->slice, a->source, A3D_A_B01Current)); 118 *bb01 = 119 hwread(vortex->mmio, 120 a3d_addrB(a->slice, a->source, A3D_B_B01Current)); 121 *b2 = 122 hwread(vortex->mmio, 123 a3d_addrA(a->slice, a->source, A3D_A_B2Current)); 124 } 125 126 static void 127 a3dsrc_GetAtmosState(a3dsrc_t * a, short *x1, short *x2, short *y1, short *y2) 128 { 129 130 } 131 132 #endif 133 /* HRTF */ 134 135 static void 136 a3dsrc_SetHrtfTarget(a3dsrc_t * a, a3d_Hrtf_t const aa, a3d_Hrtf_t const b) 137 { 138 vortex_t *vortex = (vortex_t *) (a->vortex); 139 int i; 140 141 for (i = 0; i < HRTF_SZ; i++) 142 hwwrite(vortex->mmio, 143 a3d_addrB(a->slice, a->source, 144 A3D_B_HrtfTarget) + (i << 2), 145 (b[i] << 0x10) | aa[i]); 146 } 147 148 static void 149 a3dsrc_SetHrtfCurrent(a3dsrc_t * a, a3d_Hrtf_t const aa, a3d_Hrtf_t const b) 150 { 151 vortex_t *vortex = (vortex_t *) (a->vortex); 152 int i; 153 154 for (i = 0; i < HRTF_SZ; i++) 155 hwwrite(vortex->mmio, 156 a3d_addrB(a->slice, a->source, 157 A3D_B_HrtfCurrent) + (i << 2), 158 (b[i] << 0x10) | aa[i]); 159 } 160 161 static void 162 a3dsrc_SetHrtfState(a3dsrc_t * a, a3d_Hrtf_t const aa, a3d_Hrtf_t const b) 163 { 164 vortex_t *vortex = (vortex_t *) (a->vortex); 165 int i; 166 167 for (i = 0; i < HRTF_SZ; i++) 168 hwwrite(vortex->mmio, 169 a3d_addrB(a->slice, a->source, 170 A3D_B_HrtfDelayLine) + (i << 2), 171 (b[i] << 0x10) | aa[i]); 172 } 173 174 static void a3dsrc_SetHrtfOutput(a3dsrc_t * a, short left, short right) 175 { 176 vortex_t *vortex = (vortex_t *) (a->vortex); 177 hwwrite(vortex->mmio, 178 a3d_addrA(a->slice, a->source, A3D_A_HrtfOutL), left); 179 hwwrite(vortex->mmio, 180 a3d_addrA(a->slice, a->source, A3D_A_HrtfOutR), right); 181 } 182 183 #if 0 184 static void a3dsrc_GetHrtfTarget(a3dsrc_t * a, a3d_Hrtf_t aa, a3d_Hrtf_t b) 185 { 186 vortex_t *vortex = (vortex_t *) (a->vortex); 187 int i; 188 189 for (i = 0; i < HRTF_SZ; i++) 190 aa[i] = 191 hwread(vortex->mmio, 192 a3d_addrA(a->slice, a->source, 193 A3D_A_HrtfTarget + (i << 2))); 194 for (i = 0; i < HRTF_SZ; i++) 195 b[i] = 196 hwread(vortex->mmio, 197 a3d_addrB(a->slice, a->source, 198 A3D_B_HrtfTarget + (i << 2))); 199 } 200 201 static void a3dsrc_GetHrtfCurrent(a3dsrc_t * a, a3d_Hrtf_t aa, a3d_Hrtf_t b) 202 { 203 vortex_t *vortex = (vortex_t *) (a->vortex); 204 int i; 205 206 for (i = 0; i < HRTF_SZ; i++) 207 aa[i] = 208 hwread(vortex->mmio, 209 a3d_addrA(a->slice, a->source, 210 A3D_A_HrtfCurrent + (i << 2))); 211 for (i = 0; i < HRTF_SZ; i++) 212 b[i] = 213 hwread(vortex->mmio, 214 a3d_addrB(a->slice, a->source, 215 A3D_B_HrtfCurrent + (i << 2))); 216 } 217 218 static void a3dsrc_GetHrtfState(a3dsrc_t * a, a3d_Hrtf_t aa, a3d_Hrtf_t b) 219 { 220 vortex_t *vortex = (vortex_t *) (a->vortex); 221 int i; 222 // FIXME: verify this! 223 for (i = 0; i < HRTF_SZ; i++) 224 aa[i] = 225 hwread(vortex->mmio, 226 a3d_addrA(a->slice, a->source, 227 A3D_A_HrtfDelayLine + (i << 2))); 228 for (i = 0; i < HRTF_SZ; i++) 229 b[i] = 230 hwread(vortex->mmio, 231 a3d_addrB(a->slice, a->source, 232 A3D_B_HrtfDelayLine + (i << 2))); 233 } 234 235 static void a3dsrc_GetHrtfOutput(a3dsrc_t * a, short *left, short *right) 236 { 237 vortex_t *vortex = (vortex_t *) (a->vortex); 238 *left = 239 hwread(vortex->mmio, 240 a3d_addrA(a->slice, a->source, A3D_A_HrtfOutL)); 241 *right = 242 hwread(vortex->mmio, 243 a3d_addrA(a->slice, a->source, A3D_A_HrtfOutR)); 244 } 245 246 #endif 247 248 /* Interaural Time Difference. 249 * "The other main clue that humans use to locate sounds, is called 250 * Interaural Time Difference (ITD). The differences in distance from 251 * the sound source to a listeners ears means that the sound will 252 * reach one ear slightly before the other....", found somewhere with google.*/ 253 static void a3dsrc_SetItdTarget(a3dsrc_t * a, short litd, short ritd) 254 { 255 vortex_t *vortex = (vortex_t *) (a->vortex); 256 257 if (litd < 0) 258 litd = 0; 259 if (litd > 0x57FF) 260 litd = 0x57FF; 261 if (ritd < 0) 262 ritd = 0; 263 if (ritd > 0x57FF) 264 ritd = 0x57FF; 265 hwwrite(vortex->mmio, 266 a3d_addrB(a->slice, a->source, A3D_B_ITDTarget), 267 (ritd << 0x10) | litd); 268 //hwwrite(vortex->mmio, addr(0x191DF+5, this04, this08), (ritd<<0x10)|litd); 269 } 270 271 static void a3dsrc_SetItdCurrent(a3dsrc_t * a, short litd, short ritd) 272 { 273 vortex_t *vortex = (vortex_t *) (a->vortex); 274 275 if (litd < 0) 276 litd = 0; 277 if (litd > 0x57FF) 278 litd = 0x57FF; 279 if (ritd < 0) 280 ritd = 0; 281 if (ritd > 0x57FF) 282 ritd = 0x57FF; 283 hwwrite(vortex->mmio, 284 a3d_addrB(a->slice, a->source, A3D_B_ITDCurrent), 285 (ritd << 0x10) | litd); 286 //hwwrite(vortex->mmio, addr(0x191DF+1, this04, this08), (ritd<<0x10)|litd); 287 } 288 289 static void a3dsrc_SetItdDline(a3dsrc_t * a, a3d_ItdDline_t const dline) 290 { 291 vortex_t *vortex = (vortex_t *) (a->vortex); 292 int i; 293 /* 45 != 40 -> Check this ! */ 294 for (i = 0; i < DLINE_SZ; i++) 295 hwwrite(vortex->mmio, 296 a3d_addrA(a->slice, a->source, 297 A3D_A_ITDDelayLine) + (i << 2), dline[i]); 298 } 299 300 #if 0 301 static void a3dsrc_GetItdTarget(a3dsrc_t * a, short *litd, short *ritd) 302 { 303 vortex_t *vortex = (vortex_t *) (a->vortex); 304 *ritd = 305 hwread(vortex->mmio, 306 a3d_addrA(a->slice, a->source, A3D_A_ITDTarget)); 307 *litd = 308 hwread(vortex->mmio, 309 a3d_addrB(a->slice, a->source, A3D_B_ITDTarget)); 310 } 311 312 static void a3dsrc_GetItdCurrent(a3dsrc_t * a, short *litd, short *ritd) 313 { 314 vortex_t *vortex = (vortex_t *) (a->vortex); 315 316 *ritd = 317 hwread(vortex->mmio, 318 a3d_addrA(a->slice, a->source, A3D_A_ITDCurrent)); 319 *litd = 320 hwread(vortex->mmio, 321 a3d_addrB(a->slice, a->source, A3D_B_ITDCurrent)); 322 } 323 324 static void a3dsrc_GetItdDline(a3dsrc_t * a, a3d_ItdDline_t dline) 325 { 326 vortex_t *vortex = (vortex_t *) (a->vortex); 327 int i; 328 329 for (i = 0; i < DLINE_SZ; i++) 330 dline[i] = 331 hwread(vortex->mmio, 332 a3d_addrA(a->slice, a->source, 333 A3D_A_ITDDelayLine + (i << 2))); 334 } 335 336 #endif 337 /* This is may be used for ILD Interaural Level Difference. */ 338 339 static void a3dsrc_SetGainTarget(a3dsrc_t * a, short left, short right) 340 { 341 vortex_t *vortex = (vortex_t *) (a->vortex); 342 hwwrite(vortex->mmio, 343 a3d_addrB(a->slice, a->source, A3D_B_GainTarget), 344 (right << 0x10) | left); 345 } 346 347 static void a3dsrc_SetGainCurrent(a3dsrc_t * a, short left, short right) 348 { 349 vortex_t *vortex = (vortex_t *) (a->vortex); 350 hwwrite(vortex->mmio, 351 a3d_addrB(a->slice, a->source, A3D_B_GainCurrent), 352 (right << 0x10) | left); 353 } 354 355 #if 0 356 static void a3dsrc_GetGainTarget(a3dsrc_t * a, short *left, short *right) 357 { 358 vortex_t *vortex = (vortex_t *) (a->vortex); 359 *right = 360 hwread(vortex->mmio, 361 a3d_addrA(a->slice, a->source, A3D_A_GainTarget)); 362 *left = 363 hwread(vortex->mmio, 364 a3d_addrB(a->slice, a->source, A3D_B_GainTarget)); 365 } 366 367 static void a3dsrc_GetGainCurrent(a3dsrc_t * a, short *left, short *right) 368 { 369 vortex_t *vortex = (vortex_t *) (a->vortex); 370 *right = 371 hwread(vortex->mmio, 372 a3d_addrA(a->slice, a->source, A3D_A_GainCurrent)); 373 *left = 374 hwread(vortex->mmio, 375 a3d_addrB(a->slice, a->source, A3D_B_GainCurrent)); 376 } 377 378 /* CA3dIO this func seems to be inlined all over this place. */ 379 static void CA3dIO_WriteReg(a3dsrc_t * a, unsigned long addr, short aa, short b) 380 { 381 vortex_t *vortex = (vortex_t *) (a->vortex); 382 hwwrite(vortex->mmio, addr, (aa << 0x10) | b); 383 } 384 385 #endif 386 /* Generic A3D stuff */ 387 388 static void a3dsrc_SetA3DSampleRate(a3dsrc_t * a, int sr) 389 { 390 vortex_t *vortex = (vortex_t *) (a->vortex); 391 int esp0 = 0; 392 393 esp0 = (((esp0 & 0x7fffffff) | 0xB8000000) & 0x7) | ((sr & 0x1f) << 3); 394 hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd), esp0); 395 //hwwrite(vortex->mmio, 0x19C38 + (this08<<0xd), esp0); 396 } 397 398 static void a3dsrc_EnableA3D(a3dsrc_t * a) 399 { 400 vortex_t *vortex = (vortex_t *) (a->vortex); 401 hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd), 402 0xF0000001); 403 //hwwrite(vortex->mmio, 0x19C38 + (this08<<0xd), 0xF0000001); 404 } 405 406 static void a3dsrc_DisableA3D(a3dsrc_t * a) 407 { 408 vortex_t *vortex = (vortex_t *) (a->vortex); 409 hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd), 410 0xF0000000); 411 } 412 413 static void a3dsrc_SetA3DControlReg(a3dsrc_t * a, unsigned long ctrl) 414 { 415 vortex_t *vortex = (vortex_t *) (a->vortex); 416 hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd), ctrl); 417 } 418 419 static void a3dsrc_SetA3DPointerReg(a3dsrc_t * a, unsigned long ptr) 420 { 421 vortex_t *vortex = (vortex_t *) (a->vortex); 422 hwwrite(vortex->mmio, A3D_SLICE_Pointers + ((a->slice) << 0xd), ptr); 423 } 424 425 #if 0 426 static void a3dsrc_GetA3DSampleRate(a3dsrc_t * a, int *sr) 427 { 428 vortex_t *vortex = (vortex_t *) (a->vortex); 429 *sr = ((hwread(vortex->mmio, A3D_SLICE_Control + (a->slice << 0xd)) 430 >> 3) & 0x1f); 431 //*sr = ((hwread(vortex->mmio, 0x19C38 + (this08<<0xd))>>3)&0x1f); 432 } 433 434 static void a3dsrc_GetA3DControlReg(a3dsrc_t * a, unsigned long *ctrl) 435 { 436 vortex_t *vortex = (vortex_t *) (a->vortex); 437 *ctrl = hwread(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd)); 438 } 439 440 static void a3dsrc_GetA3DPointerReg(a3dsrc_t * a, unsigned long *ptr) 441 { 442 vortex_t *vortex = (vortex_t *) (a->vortex); 443 *ptr = hwread(vortex->mmio, A3D_SLICE_Pointers + ((a->slice) << 0xd)); 444 } 445 446 #endif 447 static void a3dsrc_ZeroSliceIO(a3dsrc_t * a) 448 { 449 vortex_t *vortex = (vortex_t *) (a->vortex); 450 int i; 451 452 for (i = 0; i < 8; i++) 453 hwwrite(vortex->mmio, 454 A3D_SLICE_VDBDest + 455 ((((a->slice) << 0xb) + i) << 2), 0); 456 for (i = 0; i < 4; i++) 457 hwwrite(vortex->mmio, 458 A3D_SLICE_VDBSource + 459 ((((a->slice) << 0xb) + i) << 2), 0); 460 } 461 462 /* Reset Single A3D source. */ 463 static void a3dsrc_ZeroState(a3dsrc_t * a) 464 { 465 466 //printk("vortex: ZeroState slice: %d, source %d\n", a->slice, a->source); 467 468 a3dsrc_SetAtmosState(a, 0, 0, 0, 0); 469 a3dsrc_SetHrtfState(a, A3dHrirZeros, A3dHrirZeros); 470 a3dsrc_SetItdDline(a, A3dItdDlineZeros); 471 a3dsrc_SetHrtfOutput(a, 0, 0); 472 a3dsrc_SetTimeConsts(a, 0, 0, 0, 0); 473 474 a3dsrc_SetAtmosCurrent(a, 0, 0, 0, 0, 0); 475 a3dsrc_SetAtmosTarget(a, 0, 0, 0, 0, 0); 476 a3dsrc_SetItdCurrent(a, 0, 0); 477 a3dsrc_SetItdTarget(a, 0, 0); 478 a3dsrc_SetGainCurrent(a, 0, 0); 479 a3dsrc_SetGainTarget(a, 0, 0); 480 481 a3dsrc_SetHrtfCurrent(a, A3dHrirZeros, A3dHrirZeros); 482 a3dsrc_SetHrtfTarget(a, A3dHrirZeros, A3dHrirZeros); 483 } 484 485 /* Reset entire A3D engine */ 486 static void a3dsrc_ZeroStateA3D(a3dsrc_t * a) 487 { 488 int i, var, var2; 489 490 if ((a->vortex) == NULL) { 491 printk(KERN_ERR "vortex: ZeroStateA3D: ERROR: a->vortex is NULL\n"); 492 return; 493 } 494 495 a3dsrc_SetA3DControlReg(a, 0); 496 a3dsrc_SetA3DPointerReg(a, 0); 497 498 var = a->slice; 499 var2 = a->source; 500 for (i = 0; i < 4; i++) { 501 a->slice = i; 502 a3dsrc_ZeroSliceIO(a); 503 //a3dsrc_ZeroState(a); 504 } 505 a->source = var2; 506 a->slice = var; 507 } 508 509 /* Program A3D block as pass through */ 510 static void a3dsrc_ProgramPipe(a3dsrc_t * a) 511 { 512 a3dsrc_SetTimeConsts(a, 0, 0, 0, 0); 513 a3dsrc_SetAtmosCurrent(a, 0, 0x4000, 0, 0, 0); 514 a3dsrc_SetAtmosTarget(a, 0x4000, 0, 0, 0, 0); 515 a3dsrc_SetItdCurrent(a, 0, 0); 516 a3dsrc_SetItdTarget(a, 0, 0); 517 a3dsrc_SetGainCurrent(a, 0x7fff, 0x7fff); 518 a3dsrc_SetGainTarget(a, 0x7fff, 0x7fff); 519 520 /* SET HRTF HERE */ 521 522 /* Single spike leads to identity transfer function. */ 523 a3dsrc_SetHrtfCurrent(a, A3dHrirImpulse, A3dHrirImpulse); 524 a3dsrc_SetHrtfTarget(a, A3dHrirImpulse, A3dHrirImpulse); 525 526 /* Test: Sounds saturated. */ 527 //a3dsrc_SetHrtfCurrent(a, A3dHrirSatTest, A3dHrirSatTest); 528 //a3dsrc_SetHrtfTarget(a, A3dHrirSatTest, A3dHrirSatTest); 529 } 530 531 /* VDB = Vortex audio Dataflow Bus */ 532 #if 0 533 static void a3dsrc_ClearVDBData(a3dsrc_t * a, unsigned long aa) 534 { 535 vortex_t *vortex = (vortex_t *) (a->vortex); 536 537 // ((aa >> 2) << 8) - (aa >> 2) 538 hwwrite(vortex->mmio, 539 a3d_addrS(a->slice, A3D_SLICE_VDBDest) + (a->source << 2), 0); 540 hwwrite(vortex->mmio, 541 a3d_addrS(a->slice, 542 A3D_SLICE_VDBDest + 4) + (a->source << 2), 0); 543 /* 544 hwwrite(vortex->mmio, 0x19c00 + (((aa>>2)*255*4)+aa)*8, 0); 545 hwwrite(vortex->mmio, 0x19c04 + (((aa>>2)*255*4)+aa)*8, 0); 546 */ 547 } 548 #endif 549 550 /* A3D HwSource stuff. */ 551 552 static void vortex_A3dSourceHw_Initialize(vortex_t * v, int source, int slice) 553 { 554 a3dsrc_t *a3dsrc = &(v->a3d[source + (slice * 4)]); 555 //a3dsrc_t *a3dsrc = &(v->a3d[source + (slice*4)]); 556 557 a3dsrc->vortex = (void *)v; 558 a3dsrc->source = source; /* source */ 559 a3dsrc->slice = slice; /* slice */ 560 a3dsrc_ZeroState(a3dsrc); 561 /* Added by me. */ 562 a3dsrc_SetA3DSampleRate(a3dsrc, 0x11); 563 } 564 565 static int Vort3DRend_Initialize(vortex_t * v, unsigned short mode) 566 { 567 v->xt_mode = mode; /* this_14 */ 568 569 vortex_XtalkHw_init(v); 570 vortex_XtalkHw_SetGainsAllChan(v); 571 switch (v->xt_mode) { 572 case XT_SPEAKER0: 573 vortex_XtalkHw_ProgramXtalkNarrow(v); 574 break; 575 case XT_SPEAKER1: 576 vortex_XtalkHw_ProgramXtalkWide(v); 577 break; 578 default: 579 case XT_HEADPHONE: 580 vortex_XtalkHw_ProgramPipe(v); 581 break; 582 case XT_DIAMOND: 583 vortex_XtalkHw_ProgramDiamondXtalk(v); 584 break; 585 } 586 vortex_XtalkHw_SetSampleRate(v, 0x11); 587 vortex_XtalkHw_Enable(v); 588 return 0; 589 } 590 591 /* 3D Sound entry points. */ 592 593 static int vortex_a3d_register_controls(vortex_t * vortex); 594 static void vortex_a3d_unregister_controls(vortex_t * vortex); 595 /* A3D base support init/shudown */ 596 static void __devinit vortex_Vort3D_enable(vortex_t * v) 597 { 598 int i; 599 600 Vort3DRend_Initialize(v, XT_HEADPHONE); 601 for (i = 0; i < NR_A3D; i++) { 602 vortex_A3dSourceHw_Initialize(v, i % 4, i >> 2); 603 a3dsrc_ZeroStateA3D(&(v->a3d[0])); 604 } 605 /* Register ALSA controls */ 606 vortex_a3d_register_controls(v); 607 } 608 609 static void vortex_Vort3D_disable(vortex_t * v) 610 { 611 vortex_XtalkHw_Disable(v); 612 vortex_a3d_unregister_controls(v); 613 } 614 615 /* Make A3D subsystem connections. */ 616 static void vortex_Vort3D_connect(vortex_t * v, int en) 617 { 618 int i; 619 620 // Disable AU8810 routes, since they seem to be wrong (in au8810.h). 621 #ifdef CHIP_AU8810 622 return; 623 #endif 624 625 #if 1 626 /* Alloc Xtalk mixin resources */ 627 v->mixxtlk[0] = 628 vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN); 629 if (v->mixxtlk[0] < 0) { 630 printk 631 ("vortex: vortex_Vort3D: ERROR: not enough free mixer resources.\n"); 632 return; 633 } 634 v->mixxtlk[1] = 635 vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN); 636 if (v->mixxtlk[1] < 0) { 637 printk 638 ("vortex: vortex_Vort3D: ERROR: not enough free mixer resources.\n"); 639 return; 640 } 641 #endif 642 643 /* Connect A3D -> XTALK */ 644 for (i = 0; i < 4; i++) { 645 // 2 outputs per each A3D slice. 646 vortex_route(v, en, 0x11, ADB_A3DOUT(i * 2), ADB_XTALKIN(i)); 647 vortex_route(v, en, 0x11, ADB_A3DOUT(i * 2) + 1, ADB_XTALKIN(5 + i)); 648 } 649 #if 0 650 vortex_route(v, en, 0x11, ADB_XTALKOUT(0), ADB_EQIN(2)); 651 vortex_route(v, en, 0x11, ADB_XTALKOUT(1), ADB_EQIN(3)); 652 #else 653 /* Connect XTalk -> mixer */ 654 vortex_route(v, en, 0x11, ADB_XTALKOUT(0), ADB_MIXIN(v->mixxtlk[0])); 655 vortex_route(v, en, 0x11, ADB_XTALKOUT(1), ADB_MIXIN(v->mixxtlk[1])); 656 vortex_connection_mixin_mix(v, en, v->mixxtlk[0], v->mixplayb[0], 0); 657 vortex_connection_mixin_mix(v, en, v->mixxtlk[1], v->mixplayb[1], 0); 658 vortex_mix_setinputvolumebyte(v, v->mixplayb[0], v->mixxtlk[0], 659 en ? MIX_DEFIGAIN : VOL_MIN); 660 vortex_mix_setinputvolumebyte(v, v->mixplayb[1], v->mixxtlk[1], 661 en ? MIX_DEFIGAIN : VOL_MIN); 662 if (VORTEX_IS_QUAD(v)) { 663 vortex_connection_mixin_mix(v, en, v->mixxtlk[0], 664 v->mixplayb[2], 0); 665 vortex_connection_mixin_mix(v, en, v->mixxtlk[1], 666 v->mixplayb[3], 0); 667 vortex_mix_setinputvolumebyte(v, v->mixplayb[2], 668 v->mixxtlk[0], 669 en ? MIX_DEFIGAIN : VOL_MIN); 670 vortex_mix_setinputvolumebyte(v, v->mixplayb[3], 671 v->mixxtlk[1], 672 en ? MIX_DEFIGAIN : VOL_MIN); 673 } 674 #endif 675 } 676 677 /* Initialize one single A3D source. */ 678 static void vortex_Vort3D_InitializeSource(a3dsrc_t * a, int en) 679 { 680 if (a->vortex == NULL) { 681 printk 682 ("vortex: Vort3D_InitializeSource: A3D source not initialized\n"); 683 return; 684 } 685 if (en) { 686 a3dsrc_ProgramPipe(a); 687 a3dsrc_SetA3DSampleRate(a, 0x11); 688 a3dsrc_SetTimeConsts(a, HrtfTCDefault, 689 ItdTCDefault, GainTCDefault, 690 CoefTCDefault); 691 /* Remark: zero gain is muted. */ 692 //a3dsrc_SetGainTarget(a,0,0); 693 //a3dsrc_SetGainCurrent(a,0,0); 694 a3dsrc_EnableA3D(a); 695 } else { 696 a3dsrc_DisableA3D(a); 697 a3dsrc_ZeroState(a); 698 } 699 } 700 701 /* Conversion of coordinates into 3D parameters. */ 702 703 static void vortex_a3d_coord2hrtf(a3d_Hrtf_t hrtf, int *coord) 704 { 705 /* FIXME: implement this. */ 706 707 } 708 static void vortex_a3d_coord2itd(a3d_Itd_t itd, int *coord) 709 { 710 /* FIXME: implement this. */ 711 712 } 713 static void vortex_a3d_coord2ild(a3d_LRGains_t ild, int left, int right) 714 { 715 /* FIXME: implement this. */ 716 717 } 718 static void vortex_a3d_translate_filter(a3d_atmos_t filter, int *params) 719 { 720 /* FIXME: implement this. */ 721 722 } 723 724 /* ALSA control interface. */ 725 726 static int 727 snd_vortex_a3d_hrtf_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 728 { 729 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 730 uinfo->count = 6; 731 uinfo->value.integer.min = 0x00000000; 732 uinfo->value.integer.max = 0xffffffff; 733 return 0; 734 } 735 static int 736 snd_vortex_a3d_itd_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 737 { 738 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 739 uinfo->count = 2; 740 uinfo->value.integer.min = 0x00000000; 741 uinfo->value.integer.max = 0xffffffff; 742 return 0; 743 } 744 static int 745 snd_vortex_a3d_ild_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 746 { 747 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 748 uinfo->count = 2; 749 uinfo->value.integer.min = 0x00000000; 750 uinfo->value.integer.max = 0xffffffff; 751 return 0; 752 } 753 static int 754 snd_vortex_a3d_filter_info(struct snd_kcontrol *kcontrol, 755 struct snd_ctl_elem_info *uinfo) 756 { 757 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 758 uinfo->count = 4; 759 uinfo->value.integer.min = 0x00000000; 760 uinfo->value.integer.max = 0xffffffff; 761 return 0; 762 } 763 764 static int 765 snd_vortex_a3d_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 766 { 767 //a3dsrc_t *a = kcontrol->private_data; 768 /* No read yet. Would this be really useable/needed ? */ 769 770 return 0; 771 } 772 773 static int 774 snd_vortex_a3d_hrtf_put(struct snd_kcontrol *kcontrol, 775 struct snd_ctl_elem_value *ucontrol) 776 { 777 a3dsrc_t *a = kcontrol->private_data; 778 int changed = 1, i; 779 int coord[6]; 780 for (i = 0; i < 6; i++) 781 coord[i] = ucontrol->value.integer.value[i]; 782 /* Translate orientation coordinates to a3d params. */ 783 vortex_a3d_coord2hrtf(a->hrtf[0], coord); 784 vortex_a3d_coord2hrtf(a->hrtf[1], coord); 785 a3dsrc_SetHrtfTarget(a, a->hrtf[0], a->hrtf[1]); 786 a3dsrc_SetHrtfCurrent(a, a->hrtf[0], a->hrtf[1]); 787 return changed; 788 } 789 790 static int 791 snd_vortex_a3d_itd_put(struct snd_kcontrol *kcontrol, 792 struct snd_ctl_elem_value *ucontrol) 793 { 794 a3dsrc_t *a = kcontrol->private_data; 795 int coord[6]; 796 int i, changed = 1; 797 for (i = 0; i < 6; i++) 798 coord[i] = ucontrol->value.integer.value[i]; 799 /* Translate orientation coordinates to a3d params. */ 800 vortex_a3d_coord2itd(a->hrtf[0], coord); 801 vortex_a3d_coord2itd(a->hrtf[1], coord); 802 /* Inter aural time difference. */ 803 a3dsrc_SetItdTarget(a, a->itd[0], a->itd[1]); 804 a3dsrc_SetItdCurrent(a, a->itd[0], a->itd[1]); 805 a3dsrc_SetItdDline(a, a->dline); 806 return changed; 807 } 808 809 static int 810 snd_vortex_a3d_ild_put(struct snd_kcontrol *kcontrol, 811 struct snd_ctl_elem_value *ucontrol) 812 { 813 a3dsrc_t *a = kcontrol->private_data; 814 int changed = 1; 815 int l, r; 816 /* There may be some scale tranlation needed here. */ 817 l = ucontrol->value.integer.value[0]; 818 r = ucontrol->value.integer.value[1]; 819 vortex_a3d_coord2ild(a->ild, l, r); 820 /* Left Right panning. */ 821 a3dsrc_SetGainTarget(a, l, r); 822 a3dsrc_SetGainCurrent(a, l, r); 823 return changed; 824 } 825 826 static int 827 snd_vortex_a3d_filter_put(struct snd_kcontrol *kcontrol, 828 struct snd_ctl_elem_value *ucontrol) 829 { 830 a3dsrc_t *a = kcontrol->private_data; 831 int i, changed = 1; 832 int params[6]; 833 for (i = 0; i < 6; i++) 834 params[i] = ucontrol->value.integer.value[i]; 835 /* Translate generic filter params to a3d filter params. */ 836 vortex_a3d_translate_filter(a->filter, params); 837 /* Atmospheric absorbtion and filtering. */ 838 a3dsrc_SetAtmosTarget(a, a->filter[0], 839 a->filter[1], a->filter[2], 840 a->filter[3], a->filter[4]); 841 a3dsrc_SetAtmosCurrent(a, a->filter[0], 842 a->filter[1], a->filter[2], 843 a->filter[3], a->filter[4]); 844 return changed; 845 } 846 847 static struct snd_kcontrol_new vortex_a3d_kcontrol __devinitdata = { 848 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 849 .name = "Playback PCM advanced processing", 850 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 851 .info = snd_vortex_a3d_hrtf_info, 852 .get = snd_vortex_a3d_get, 853 .put = snd_vortex_a3d_hrtf_put, 854 }; 855 856 /* Control (un)registration. */ 857 static int __devinit vortex_a3d_register_controls(vortex_t * vortex) 858 { 859 struct snd_kcontrol *kcontrol; 860 int err, i; 861 /* HRTF controls. */ 862 for (i = 0; i < NR_A3D; i++) { 863 if ((kcontrol = 864 snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) 865 return -ENOMEM; 866 kcontrol->id.numid = CTRLID_HRTF; 867 kcontrol->info = snd_vortex_a3d_hrtf_info; 868 kcontrol->put = snd_vortex_a3d_hrtf_put; 869 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) 870 return err; 871 } 872 /* ITD controls. */ 873 for (i = 0; i < NR_A3D; i++) { 874 if ((kcontrol = 875 snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) 876 return -ENOMEM; 877 kcontrol->id.numid = CTRLID_ITD; 878 kcontrol->info = snd_vortex_a3d_itd_info; 879 kcontrol->put = snd_vortex_a3d_itd_put; 880 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) 881 return err; 882 } 883 /* ILD (gains) controls. */ 884 for (i = 0; i < NR_A3D; i++) { 885 if ((kcontrol = 886 snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) 887 return -ENOMEM; 888 kcontrol->id.numid = CTRLID_GAINS; 889 kcontrol->info = snd_vortex_a3d_ild_info; 890 kcontrol->put = snd_vortex_a3d_ild_put; 891 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) 892 return err; 893 } 894 /* Filter controls. */ 895 for (i = 0; i < NR_A3D; i++) { 896 if ((kcontrol = 897 snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) 898 return -ENOMEM; 899 kcontrol->id.numid = CTRLID_FILTER; 900 kcontrol->info = snd_vortex_a3d_filter_info; 901 kcontrol->put = snd_vortex_a3d_filter_put; 902 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) 903 return err; 904 } 905 return 0; 906 } 907 908 static void vortex_a3d_unregister_controls(vortex_t * vortex) 909 { 910 911 } 912 913 /* End of File*/ 914