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 absorption. */ 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(KERN_DEBUG "vortex: ZeroState slice: %d, source %d\n", 467 a->slice, a->source); 468 */ 469 a3dsrc_SetAtmosState(a, 0, 0, 0, 0); 470 a3dsrc_SetHrtfState(a, A3dHrirZeros, A3dHrirZeros); 471 a3dsrc_SetItdDline(a, A3dItdDlineZeros); 472 a3dsrc_SetHrtfOutput(a, 0, 0); 473 a3dsrc_SetTimeConsts(a, 0, 0, 0, 0); 474 475 a3dsrc_SetAtmosCurrent(a, 0, 0, 0, 0, 0); 476 a3dsrc_SetAtmosTarget(a, 0, 0, 0, 0, 0); 477 a3dsrc_SetItdCurrent(a, 0, 0); 478 a3dsrc_SetItdTarget(a, 0, 0); 479 a3dsrc_SetGainCurrent(a, 0, 0); 480 a3dsrc_SetGainTarget(a, 0, 0); 481 482 a3dsrc_SetHrtfCurrent(a, A3dHrirZeros, A3dHrirZeros); 483 a3dsrc_SetHrtfTarget(a, A3dHrirZeros, A3dHrirZeros); 484 } 485 486 /* Reset entire A3D engine */ 487 static void a3dsrc_ZeroStateA3D(a3dsrc_t * a) 488 { 489 int i, var, var2; 490 491 if ((a->vortex) == NULL) { 492 printk(KERN_ERR "vortex: ZeroStateA3D: ERROR: a->vortex is NULL\n"); 493 return; 494 } 495 496 a3dsrc_SetA3DControlReg(a, 0); 497 a3dsrc_SetA3DPointerReg(a, 0); 498 499 var = a->slice; 500 var2 = a->source; 501 for (i = 0; i < 4; i++) { 502 a->slice = i; 503 a3dsrc_ZeroSliceIO(a); 504 //a3dsrc_ZeroState(a); 505 } 506 a->source = var2; 507 a->slice = var; 508 } 509 510 /* Program A3D block as pass through */ 511 static void a3dsrc_ProgramPipe(a3dsrc_t * a) 512 { 513 a3dsrc_SetTimeConsts(a, 0, 0, 0, 0); 514 a3dsrc_SetAtmosCurrent(a, 0, 0x4000, 0, 0, 0); 515 a3dsrc_SetAtmosTarget(a, 0x4000, 0, 0, 0, 0); 516 a3dsrc_SetItdCurrent(a, 0, 0); 517 a3dsrc_SetItdTarget(a, 0, 0); 518 a3dsrc_SetGainCurrent(a, 0x7fff, 0x7fff); 519 a3dsrc_SetGainTarget(a, 0x7fff, 0x7fff); 520 521 /* SET HRTF HERE */ 522 523 /* Single spike leads to identity transfer function. */ 524 a3dsrc_SetHrtfCurrent(a, A3dHrirImpulse, A3dHrirImpulse); 525 a3dsrc_SetHrtfTarget(a, A3dHrirImpulse, A3dHrirImpulse); 526 527 /* Test: Sounds saturated. */ 528 //a3dsrc_SetHrtfCurrent(a, A3dHrirSatTest, A3dHrirSatTest); 529 //a3dsrc_SetHrtfTarget(a, A3dHrirSatTest, A3dHrirSatTest); 530 } 531 532 /* VDB = Vortex audio Dataflow Bus */ 533 #if 0 534 static void a3dsrc_ClearVDBData(a3dsrc_t * a, unsigned long aa) 535 { 536 vortex_t *vortex = (vortex_t *) (a->vortex); 537 538 // ((aa >> 2) << 8) - (aa >> 2) 539 hwwrite(vortex->mmio, 540 a3d_addrS(a->slice, A3D_SLICE_VDBDest) + (a->source << 2), 0); 541 hwwrite(vortex->mmio, 542 a3d_addrS(a->slice, 543 A3D_SLICE_VDBDest + 4) + (a->source << 2), 0); 544 /* 545 hwwrite(vortex->mmio, 0x19c00 + (((aa>>2)*255*4)+aa)*8, 0); 546 hwwrite(vortex->mmio, 0x19c04 + (((aa>>2)*255*4)+aa)*8, 0); 547 */ 548 } 549 #endif 550 551 /* A3D HwSource stuff. */ 552 553 static void vortex_A3dSourceHw_Initialize(vortex_t * v, int source, int slice) 554 { 555 a3dsrc_t *a3dsrc = &(v->a3d[source + (slice * 4)]); 556 //a3dsrc_t *a3dsrc = &(v->a3d[source + (slice*4)]); 557 558 a3dsrc->vortex = (void *)v; 559 a3dsrc->source = source; /* source */ 560 a3dsrc->slice = slice; /* slice */ 561 a3dsrc_ZeroState(a3dsrc); 562 /* Added by me. */ 563 a3dsrc_SetA3DSampleRate(a3dsrc, 0x11); 564 } 565 566 static int Vort3DRend_Initialize(vortex_t * v, unsigned short mode) 567 { 568 v->xt_mode = mode; /* this_14 */ 569 570 vortex_XtalkHw_init(v); 571 vortex_XtalkHw_SetGainsAllChan(v); 572 switch (v->xt_mode) { 573 case XT_SPEAKER0: 574 vortex_XtalkHw_ProgramXtalkNarrow(v); 575 break; 576 case XT_SPEAKER1: 577 vortex_XtalkHw_ProgramXtalkWide(v); 578 break; 579 default: 580 case XT_HEADPHONE: 581 vortex_XtalkHw_ProgramPipe(v); 582 break; 583 case XT_DIAMOND: 584 vortex_XtalkHw_ProgramDiamondXtalk(v); 585 break; 586 } 587 vortex_XtalkHw_SetSampleRate(v, 0x11); 588 vortex_XtalkHw_Enable(v); 589 return 0; 590 } 591 592 /* 3D Sound entry points. */ 593 594 static int vortex_a3d_register_controls(vortex_t * vortex); 595 static void vortex_a3d_unregister_controls(vortex_t * vortex); 596 /* A3D base support init/shudown */ 597 static void vortex_Vort3D_enable(vortex_t *v) 598 { 599 int i; 600 601 Vort3DRend_Initialize(v, XT_HEADPHONE); 602 for (i = 0; i < NR_A3D; i++) { 603 vortex_A3dSourceHw_Initialize(v, i % 4, i >> 2); 604 a3dsrc_ZeroStateA3D(&(v->a3d[0])); 605 } 606 /* Register ALSA controls */ 607 vortex_a3d_register_controls(v); 608 } 609 610 static void vortex_Vort3D_disable(vortex_t * v) 611 { 612 vortex_XtalkHw_Disable(v); 613 vortex_a3d_unregister_controls(v); 614 } 615 616 /* Make A3D subsystem connections. */ 617 static void vortex_Vort3D_connect(vortex_t * v, int en) 618 { 619 int i; 620 621 // Disable AU8810 routes, since they seem to be wrong (in au8810.h). 622 #ifdef CHIP_AU8810 623 return; 624 #endif 625 626 #if 1 627 /* Alloc Xtalk mixin resources */ 628 v->mixxtlk[0] = 629 vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN); 630 if (v->mixxtlk[0] < 0) { 631 printk 632 ("vortex: vortex_Vort3D: ERROR: not enough free mixer resources.\n"); 633 return; 634 } 635 v->mixxtlk[1] = 636 vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN); 637 if (v->mixxtlk[1] < 0) { 638 printk 639 ("vortex: vortex_Vort3D: ERROR: not enough free mixer resources.\n"); 640 return; 641 } 642 #endif 643 644 /* Connect A3D -> XTALK */ 645 for (i = 0; i < 4; i++) { 646 // 2 outputs per each A3D slice. 647 vortex_route(v, en, 0x11, ADB_A3DOUT(i * 2), ADB_XTALKIN(i)); 648 vortex_route(v, en, 0x11, ADB_A3DOUT(i * 2) + 1, ADB_XTALKIN(5 + i)); 649 } 650 #if 0 651 vortex_route(v, en, 0x11, ADB_XTALKOUT(0), ADB_EQIN(2)); 652 vortex_route(v, en, 0x11, ADB_XTALKOUT(1), ADB_EQIN(3)); 653 #else 654 /* Connect XTalk -> mixer */ 655 vortex_route(v, en, 0x11, ADB_XTALKOUT(0), ADB_MIXIN(v->mixxtlk[0])); 656 vortex_route(v, en, 0x11, ADB_XTALKOUT(1), ADB_MIXIN(v->mixxtlk[1])); 657 vortex_connection_mixin_mix(v, en, v->mixxtlk[0], v->mixplayb[0], 0); 658 vortex_connection_mixin_mix(v, en, v->mixxtlk[1], v->mixplayb[1], 0); 659 vortex_mix_setinputvolumebyte(v, v->mixplayb[0], v->mixxtlk[0], 660 en ? MIX_DEFIGAIN : VOL_MIN); 661 vortex_mix_setinputvolumebyte(v, v->mixplayb[1], v->mixxtlk[1], 662 en ? MIX_DEFIGAIN : VOL_MIN); 663 if (VORTEX_IS_QUAD(v)) { 664 vortex_connection_mixin_mix(v, en, v->mixxtlk[0], 665 v->mixplayb[2], 0); 666 vortex_connection_mixin_mix(v, en, v->mixxtlk[1], 667 v->mixplayb[3], 0); 668 vortex_mix_setinputvolumebyte(v, v->mixplayb[2], 669 v->mixxtlk[0], 670 en ? MIX_DEFIGAIN : VOL_MIN); 671 vortex_mix_setinputvolumebyte(v, v->mixplayb[3], 672 v->mixxtlk[1], 673 en ? MIX_DEFIGAIN : VOL_MIN); 674 } 675 #endif 676 } 677 678 /* Initialize one single A3D source. */ 679 static void vortex_Vort3D_InitializeSource(a3dsrc_t * a, int en) 680 { 681 if (a->vortex == NULL) { 682 printk 683 ("vortex: Vort3D_InitializeSource: A3D source not initialized\n"); 684 return; 685 } 686 if (en) { 687 a3dsrc_ProgramPipe(a); 688 a3dsrc_SetA3DSampleRate(a, 0x11); 689 a3dsrc_SetTimeConsts(a, HrtfTCDefault, 690 ItdTCDefault, GainTCDefault, 691 CoefTCDefault); 692 /* Remark: zero gain is muted. */ 693 //a3dsrc_SetGainTarget(a,0,0); 694 //a3dsrc_SetGainCurrent(a,0,0); 695 a3dsrc_EnableA3D(a); 696 } else { 697 a3dsrc_DisableA3D(a); 698 a3dsrc_ZeroState(a); 699 } 700 } 701 702 /* Conversion of coordinates into 3D parameters. */ 703 704 static void vortex_a3d_coord2hrtf(a3d_Hrtf_t hrtf, int *coord) 705 { 706 /* FIXME: implement this. */ 707 708 } 709 static void vortex_a3d_coord2itd(a3d_Itd_t itd, int *coord) 710 { 711 /* FIXME: implement this. */ 712 713 } 714 static void vortex_a3d_coord2ild(a3d_LRGains_t ild, int left, int right) 715 { 716 /* FIXME: implement this. */ 717 718 } 719 static void vortex_a3d_translate_filter(a3d_atmos_t filter, int *params) 720 { 721 /* FIXME: implement this. */ 722 723 } 724 725 /* ALSA control interface. */ 726 727 static int 728 snd_vortex_a3d_hrtf_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 729 { 730 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 731 uinfo->count = 6; 732 uinfo->value.integer.min = 0x00000000; 733 uinfo->value.integer.max = 0xffffffff; 734 return 0; 735 } 736 static int 737 snd_vortex_a3d_itd_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 738 { 739 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 740 uinfo->count = 2; 741 uinfo->value.integer.min = 0x00000000; 742 uinfo->value.integer.max = 0xffffffff; 743 return 0; 744 } 745 static int 746 snd_vortex_a3d_ild_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 747 { 748 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 749 uinfo->count = 2; 750 uinfo->value.integer.min = 0x00000000; 751 uinfo->value.integer.max = 0xffffffff; 752 return 0; 753 } 754 static int 755 snd_vortex_a3d_filter_info(struct snd_kcontrol *kcontrol, 756 struct snd_ctl_elem_info *uinfo) 757 { 758 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 759 uinfo->count = 4; 760 uinfo->value.integer.min = 0x00000000; 761 uinfo->value.integer.max = 0xffffffff; 762 return 0; 763 } 764 765 static int 766 snd_vortex_a3d_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 767 { 768 //a3dsrc_t *a = kcontrol->private_data; 769 /* No read yet. Would this be really useable/needed ? */ 770 771 return 0; 772 } 773 774 static int 775 snd_vortex_a3d_hrtf_put(struct snd_kcontrol *kcontrol, 776 struct snd_ctl_elem_value *ucontrol) 777 { 778 a3dsrc_t *a = kcontrol->private_data; 779 int changed = 1, i; 780 int coord[6]; 781 for (i = 0; i < 6; i++) 782 coord[i] = ucontrol->value.integer.value[i]; 783 /* Translate orientation coordinates to a3d params. */ 784 vortex_a3d_coord2hrtf(a->hrtf[0], coord); 785 vortex_a3d_coord2hrtf(a->hrtf[1], coord); 786 a3dsrc_SetHrtfTarget(a, a->hrtf[0], a->hrtf[1]); 787 a3dsrc_SetHrtfCurrent(a, a->hrtf[0], a->hrtf[1]); 788 return changed; 789 } 790 791 static int 792 snd_vortex_a3d_itd_put(struct snd_kcontrol *kcontrol, 793 struct snd_ctl_elem_value *ucontrol) 794 { 795 a3dsrc_t *a = kcontrol->private_data; 796 int coord[6]; 797 int i, changed = 1; 798 for (i = 0; i < 6; i++) 799 coord[i] = ucontrol->value.integer.value[i]; 800 /* Translate orientation coordinates to a3d params. */ 801 vortex_a3d_coord2itd(a->hrtf[0], coord); 802 vortex_a3d_coord2itd(a->hrtf[1], coord); 803 /* Inter aural time difference. */ 804 a3dsrc_SetItdTarget(a, a->itd[0], a->itd[1]); 805 a3dsrc_SetItdCurrent(a, a->itd[0], a->itd[1]); 806 a3dsrc_SetItdDline(a, a->dline); 807 return changed; 808 } 809 810 static int 811 snd_vortex_a3d_ild_put(struct snd_kcontrol *kcontrol, 812 struct snd_ctl_elem_value *ucontrol) 813 { 814 a3dsrc_t *a = kcontrol->private_data; 815 int changed = 1; 816 int l, r; 817 /* There may be some scale tranlation needed here. */ 818 l = ucontrol->value.integer.value[0]; 819 r = ucontrol->value.integer.value[1]; 820 vortex_a3d_coord2ild(a->ild, l, r); 821 /* Left Right panning. */ 822 a3dsrc_SetGainTarget(a, l, r); 823 a3dsrc_SetGainCurrent(a, l, r); 824 return changed; 825 } 826 827 static int 828 snd_vortex_a3d_filter_put(struct snd_kcontrol *kcontrol, 829 struct snd_ctl_elem_value *ucontrol) 830 { 831 a3dsrc_t *a = kcontrol->private_data; 832 int i, changed = 1; 833 int params[6]; 834 for (i = 0; i < 6; i++) 835 params[i] = ucontrol->value.integer.value[i]; 836 /* Translate generic filter params to a3d filter params. */ 837 vortex_a3d_translate_filter(a->filter, params); 838 /* Atmospheric absorption and filtering. */ 839 a3dsrc_SetAtmosTarget(a, a->filter[0], 840 a->filter[1], a->filter[2], 841 a->filter[3], a->filter[4]); 842 a3dsrc_SetAtmosCurrent(a, a->filter[0], 843 a->filter[1], a->filter[2], 844 a->filter[3], a->filter[4]); 845 return changed; 846 } 847 848 static struct snd_kcontrol_new vortex_a3d_kcontrol = { 849 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 850 .name = "Playback PCM advanced processing", 851 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 852 .info = snd_vortex_a3d_hrtf_info, 853 .get = snd_vortex_a3d_get, 854 .put = snd_vortex_a3d_hrtf_put, 855 }; 856 857 /* Control (un)registration. */ 858 static int vortex_a3d_register_controls(vortex_t *vortex) 859 { 860 struct snd_kcontrol *kcontrol; 861 int err, i; 862 /* HRTF controls. */ 863 for (i = 0; i < NR_A3D; i++) { 864 if ((kcontrol = 865 snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) 866 return -ENOMEM; 867 kcontrol->id.numid = CTRLID_HRTF; 868 kcontrol->info = snd_vortex_a3d_hrtf_info; 869 kcontrol->put = snd_vortex_a3d_hrtf_put; 870 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) 871 return err; 872 } 873 /* ITD controls. */ 874 for (i = 0; i < NR_A3D; i++) { 875 if ((kcontrol = 876 snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) 877 return -ENOMEM; 878 kcontrol->id.numid = CTRLID_ITD; 879 kcontrol->info = snd_vortex_a3d_itd_info; 880 kcontrol->put = snd_vortex_a3d_itd_put; 881 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) 882 return err; 883 } 884 /* ILD (gains) controls. */ 885 for (i = 0; i < NR_A3D; i++) { 886 if ((kcontrol = 887 snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) 888 return -ENOMEM; 889 kcontrol->id.numid = CTRLID_GAINS; 890 kcontrol->info = snd_vortex_a3d_ild_info; 891 kcontrol->put = snd_vortex_a3d_ild_put; 892 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) 893 return err; 894 } 895 /* Filter controls. */ 896 for (i = 0; i < NR_A3D; i++) { 897 if ((kcontrol = 898 snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) 899 return -ENOMEM; 900 kcontrol->id.numid = CTRLID_FILTER; 901 kcontrol->info = snd_vortex_a3d_filter_info; 902 kcontrol->put = snd_vortex_a3d_filter_put; 903 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) 904 return err; 905 } 906 return 0; 907 } 908 909 static void vortex_a3d_unregister_controls(vortex_t * vortex) 910 { 911 912 } 913 914 /* End of File*/ 915