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