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