au88x0_eq.c (22449B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/*************************************************************************** 3 * au88x0_eq.c 4 * Aureal Vortex Hardware EQ control/access. 5 * 6 * Sun Jun 8 18:19:19 2003 7 * 2003 Manuel Jander (mjander@users.sourceforge.net) 8 * 9 * 02 July 2003: First time something works :) 10 * November 2003: A3D Bypass code completed but untested. 11 * 12 * TODO: 13 * - Debug (testing) 14 * - Test peak visualization support. 15 * 16 ****************************************************************************/ 17 18/* 19 */ 20 21/* 22 The Aureal Hardware EQ is found on AU8810 and AU8830 chips only. 23 it has 4 inputs (2 for general mix, 2 for A3D) and 2 outputs (supposed 24 to be routed to the codec). 25*/ 26 27#include "au88x0.h" 28#include "au88x0_eq.h" 29#include "au88x0_eqdata.c" 30 31#define VORTEX_EQ_BASE 0x2b000 32#define VORTEX_EQ_DEST (VORTEX_EQ_BASE + 0x410) 33#define VORTEX_EQ_SOURCE (VORTEX_EQ_BASE + 0x430) 34#define VORTEX_EQ_CTRL (VORTEX_EQ_BASE + 0x440) 35 36#define VORTEX_BAND_COEFF_SIZE 0x30 37 38/* CEqHw.s */ 39static void vortex_EqHw_SetTimeConsts(vortex_t * vortex, u16 gain, u16 level) 40{ 41 hwwrite(vortex->mmio, 0x2b3c4, gain); 42 hwwrite(vortex->mmio, 0x2b3c8, level); 43} 44 45static inline u16 sign_invert(u16 a) 46{ 47 /* -(-32768) -> -32768 so we do -(-32768) -> 32767 to make the result positive */ 48 if (a == (u16)-32768) 49 return 32767; 50 else 51 return -a; 52} 53 54static void vortex_EqHw_SetLeftCoefs(vortex_t *vortex, const u16 coefs[]) 55{ 56 eqhw_t *eqhw = &(vortex->eq.this04); 57 int i = 0, n /*esp2c */; 58 59 for (n = 0; n < eqhw->this04; n++) { 60 hwwrite(vortex->mmio, 0x2b000 + n * 0x30, coefs[i + 0]); 61 hwwrite(vortex->mmio, 0x2b004 + n * 0x30, coefs[i + 1]); 62 63 if (eqhw->this08 == 0) { 64 hwwrite(vortex->mmio, 0x2b008 + n * 0x30, coefs[i + 2]); 65 hwwrite(vortex->mmio, 0x2b00c + n * 0x30, coefs[i + 3]); 66 hwwrite(vortex->mmio, 0x2b010 + n * 0x30, coefs[i + 4]); 67 } else { 68 hwwrite(vortex->mmio, 0x2b008 + n * 0x30, sign_invert(coefs[2 + i])); 69 hwwrite(vortex->mmio, 0x2b00c + n * 0x30, sign_invert(coefs[3 + i])); 70 hwwrite(vortex->mmio, 0x2b010 + n * 0x30, sign_invert(coefs[4 + i])); 71 } 72 i += 5; 73 } 74} 75 76static void vortex_EqHw_SetRightCoefs(vortex_t *vortex, const u16 coefs[]) 77{ 78 eqhw_t *eqhw = &(vortex->eq.this04); 79 int i = 0, n /*esp2c */; 80 81 for (n = 0; n < eqhw->this04; n++) { 82 hwwrite(vortex->mmio, 0x2b1e0 + n * 0x30, coefs[0 + i]); 83 hwwrite(vortex->mmio, 0x2b1e4 + n * 0x30, coefs[1 + i]); 84 85 if (eqhw->this08 == 0) { 86 hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, coefs[2 + i]); 87 hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, coefs[3 + i]); 88 hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, coefs[4 + i]); 89 } else { 90 hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, sign_invert(coefs[2 + i])); 91 hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, sign_invert(coefs[3 + i])); 92 hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, sign_invert(coefs[4 + i])); 93 } 94 i += 5; 95 } 96 97} 98 99static void vortex_EqHw_SetLeftStates(vortex_t *vortex, const u16 a[], const u16 b[]) 100{ 101 eqhw_t *eqhw = &(vortex->eq.this04); 102 int i = 0, ebx; 103 104 hwwrite(vortex->mmio, 0x2b3fc, a[0]); 105 hwwrite(vortex->mmio, 0x2b400, a[1]); 106 107 for (ebx = 0; ebx < eqhw->this04; ebx++) { 108 hwwrite(vortex->mmio, 0x2b014 + (i * 0xc), b[i]); 109 hwwrite(vortex->mmio, 0x2b018 + (i * 0xc), b[1 + i]); 110 hwwrite(vortex->mmio, 0x2b01c + (i * 0xc), b[2 + i]); 111 hwwrite(vortex->mmio, 0x2b020 + (i * 0xc), b[3 + i]); 112 i += 4; 113 } 114} 115 116static void vortex_EqHw_SetRightStates(vortex_t *vortex, const u16 a[], const u16 b[]) 117{ 118 eqhw_t *eqhw = &(vortex->eq.this04); 119 int i = 0, ebx; 120 121 hwwrite(vortex->mmio, 0x2b404, a[0]); 122 hwwrite(vortex->mmio, 0x2b408, a[1]); 123 124 for (ebx = 0; ebx < eqhw->this04; ebx++) { 125 hwwrite(vortex->mmio, 0x2b1f4 + (i * 0xc), b[i]); 126 hwwrite(vortex->mmio, 0x2b1f8 + (i * 0xc), b[1 + i]); 127 hwwrite(vortex->mmio, 0x2b1fc + (i * 0xc), b[2 + i]); 128 hwwrite(vortex->mmio, 0x2b200 + (i * 0xc), b[3 + i]); 129 i += 4; 130 } 131} 132 133#if 0 134static void vortex_EqHw_GetTimeConsts(vortex_t * vortex, u16 * a, u16 * b) 135{ 136 *a = hwread(vortex->mmio, 0x2b3c4); 137 *b = hwread(vortex->mmio, 0x2b3c8); 138} 139 140static void vortex_EqHw_GetLeftCoefs(vortex_t * vortex, u16 a[]) 141{ 142 143} 144 145static void vortex_EqHw_GetRightCoefs(vortex_t * vortex, u16 a[]) 146{ 147 148} 149 150static void vortex_EqHw_GetLeftStates(vortex_t * vortex, u16 * a, u16 b[]) 151{ 152 153} 154 155static void vortex_EqHw_GetRightStates(vortex_t * vortex, u16 * a, u16 b[]) 156{ 157 158} 159 160#endif 161/* Mix Gains */ 162static void vortex_EqHw_SetBypassGain(vortex_t * vortex, u16 a, u16 b) 163{ 164 eqhw_t *eqhw = &(vortex->eq.this04); 165 if (eqhw->this08 == 0) { 166 hwwrite(vortex->mmio, 0x2b3d4, a); 167 hwwrite(vortex->mmio, 0x2b3ec, b); 168 } else { 169 hwwrite(vortex->mmio, 0x2b3d4, sign_invert(a)); 170 hwwrite(vortex->mmio, 0x2b3ec, sign_invert(b)); 171 } 172} 173 174static void vortex_EqHw_SetA3DBypassGain(vortex_t * vortex, u16 a, u16 b) 175{ 176 177 hwwrite(vortex->mmio, 0x2b3e0, a); 178 hwwrite(vortex->mmio, 0x2b3f8, b); 179} 180 181#if 0 182static void vortex_EqHw_SetCurrBypassGain(vortex_t * vortex, u16 a, u16 b) 183{ 184 185 hwwrite(vortex->mmio, 0x2b3d0, a); 186 hwwrite(vortex->mmio, 0x2b3e8, b); 187} 188 189static void vortex_EqHw_SetCurrA3DBypassGain(vortex_t * vortex, u16 a, u16 b) 190{ 191 192 hwwrite(vortex->mmio, 0x2b3dc, a); 193 hwwrite(vortex->mmio, 0x2b3f4, b); 194} 195 196#endif 197static void 198vortex_EqHw_SetLeftGainsSingleTarget(vortex_t * vortex, u16 index, u16 b) 199{ 200 hwwrite(vortex->mmio, 0x2b02c + (index * 0x30), b); 201} 202 203static void 204vortex_EqHw_SetRightGainsSingleTarget(vortex_t * vortex, u16 index, u16 b) 205{ 206 hwwrite(vortex->mmio, 0x2b20c + (index * 0x30), b); 207} 208 209static void vortex_EqHw_SetLeftGainsTarget(vortex_t *vortex, const u16 a[]) 210{ 211 eqhw_t *eqhw = &(vortex->eq.this04); 212 int ebx; 213 214 for (ebx = 0; ebx < eqhw->this04; ebx++) { 215 hwwrite(vortex->mmio, 0x2b02c + ebx * 0x30, a[ebx]); 216 } 217} 218 219static void vortex_EqHw_SetRightGainsTarget(vortex_t *vortex, const u16 a[]) 220{ 221 eqhw_t *eqhw = &(vortex->eq.this04); 222 int ebx; 223 224 for (ebx = 0; ebx < eqhw->this04; ebx++) { 225 hwwrite(vortex->mmio, 0x2b20c + ebx * 0x30, a[ebx]); 226 } 227} 228 229static void vortex_EqHw_SetLeftGainsCurrent(vortex_t *vortex, const u16 a[]) 230{ 231 eqhw_t *eqhw = &(vortex->eq.this04); 232 int ebx; 233 234 for (ebx = 0; ebx < eqhw->this04; ebx++) { 235 hwwrite(vortex->mmio, 0x2b028 + ebx * 0x30, a[ebx]); 236 } 237} 238 239static void vortex_EqHw_SetRightGainsCurrent(vortex_t *vortex, const u16 a[]) 240{ 241 eqhw_t *eqhw = &(vortex->eq.this04); 242 int ebx; 243 244 for (ebx = 0; ebx < eqhw->this04; ebx++) { 245 hwwrite(vortex->mmio, 0x2b208 + ebx * 0x30, a[ebx]); 246 } 247} 248 249#if 0 250static void vortex_EqHw_GetLeftGainsTarget(vortex_t * vortex, u16 a[]) 251{ 252 eqhw_t *eqhw = &(vortex->eq.this04); 253 int ebx = 0; 254 255 if (eqhw->this04 < 0) 256 return; 257 258 do { 259 a[ebx] = hwread(vortex->mmio, 0x2b02c + ebx * 0x30); 260 ebx++; 261 } 262 while (ebx < eqhw->this04); 263} 264 265static void vortex_EqHw_GetRightGainsTarget(vortex_t * vortex, u16 a[]) 266{ 267 eqhw_t *eqhw = &(vortex->eq.this04); 268 int ebx = 0; 269 270 if (eqhw->this04 < 0) 271 return; 272 273 do { 274 a[ebx] = hwread(vortex->mmio, 0x2b20c + ebx * 0x30); 275 ebx++; 276 } 277 while (ebx < eqhw->this04); 278} 279 280static void vortex_EqHw_GetLeftGainsCurrent(vortex_t * vortex, u16 a[]) 281{ 282 eqhw_t *eqhw = &(vortex->eq.this04); 283 int ebx = 0; 284 285 if (eqhw->this04 < 0) 286 return; 287 288 do { 289 a[ebx] = hwread(vortex->mmio, 0x2b028 + ebx * 0x30); 290 ebx++; 291 } 292 while (ebx < eqhw->this04); 293} 294 295static void vortex_EqHw_GetRightGainsCurrent(vortex_t * vortex, u16 a[]) 296{ 297 eqhw_t *eqhw = &(vortex->eq.this04); 298 int ebx = 0; 299 300 if (eqhw->this04 < 0) 301 return; 302 303 do { 304 a[ebx] = hwread(vortex->mmio, 0x2b208 + ebx * 0x30); 305 ebx++; 306 } 307 while (ebx < eqhw->this04); 308} 309 310#endif 311/* EQ band levels settings */ 312static void vortex_EqHw_SetLevels(vortex_t *vortex, const u16 peaks[]) 313{ 314 eqhw_t *eqhw = &(vortex->eq.this04); 315 int i; 316 317 /* set left peaks */ 318 for (i = 0; i < eqhw->this04; i++) { 319 hwwrite(vortex->mmio, 0x2b024 + i * VORTEX_BAND_COEFF_SIZE, peaks[i]); 320 } 321 322 hwwrite(vortex->mmio, 0x2b3cc, peaks[eqhw->this04]); 323 hwwrite(vortex->mmio, 0x2b3d8, peaks[eqhw->this04 + 1]); 324 325 /* set right peaks */ 326 for (i = 0; i < eqhw->this04; i++) { 327 hwwrite(vortex->mmio, 0x2b204 + i * VORTEX_BAND_COEFF_SIZE, 328 peaks[i + (eqhw->this04 + 2)]); 329 } 330 331 hwwrite(vortex->mmio, 0x2b3e4, peaks[2 + (eqhw->this04 * 2)]); 332 hwwrite(vortex->mmio, 0x2b3f0, peaks[3 + (eqhw->this04 * 2)]); 333} 334 335#if 0 336static void vortex_EqHw_GetLevels(vortex_t * vortex, u16 a[]) 337{ 338 eqhw_t *eqhw = &(vortex->eq.this04); 339 int ebx; 340 341 if (eqhw->this04 < 0) 342 return; 343 344 ebx = 0; 345 do { 346 a[ebx] = hwread(vortex->mmio, 0x2b024 + ebx * 0x30); 347 ebx++; 348 } 349 while (ebx < eqhw->this04); 350 351 a[eqhw->this04] = hwread(vortex->mmio, 0x2b3cc); 352 a[eqhw->this04 + 1] = hwread(vortex->mmio, 0x2b3d8); 353 354 ebx = 0; 355 do { 356 a[ebx + (eqhw->this04 + 2)] = 357 hwread(vortex->mmio, 0x2b204 + ebx * 0x30); 358 ebx++; 359 } 360 while (ebx < eqhw->this04); 361 362 a[2 + (eqhw->this04 * 2)] = hwread(vortex->mmio, 0x2b3e4); 363 a[3 + (eqhw->this04 * 2)] = hwread(vortex->mmio, 0x2b3f0); 364} 365 366#endif 367/* Global Control */ 368static void vortex_EqHw_SetControlReg(vortex_t * vortex, u32 reg) 369{ 370 hwwrite(vortex->mmio, 0x2b440, reg); 371} 372 373static void vortex_EqHw_SetSampleRate(vortex_t * vortex, u32 sr) 374{ 375 hwwrite(vortex->mmio, 0x2b440, ((sr & 0x1f) << 3) | 0xb800); 376} 377 378#if 0 379static void vortex_EqHw_GetControlReg(vortex_t * vortex, u32 *reg) 380{ 381 *reg = hwread(vortex->mmio, 0x2b440); 382} 383 384static void vortex_EqHw_GetSampleRate(vortex_t * vortex, u32 *sr) 385{ 386 *sr = (hwread(vortex->mmio, 0x2b440) >> 3) & 0x1f; 387} 388 389#endif 390static void vortex_EqHw_Enable(vortex_t * vortex) 391{ 392 hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf001); 393} 394 395static void vortex_EqHw_Disable(vortex_t * vortex) 396{ 397 hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf000); 398} 399 400/* Reset (zero) buffers */ 401static void vortex_EqHw_ZeroIO(vortex_t * vortex) 402{ 403 int i; 404 for (i = 0; i < 0x8; i++) 405 hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0); 406 for (i = 0; i < 0x4; i++) 407 hwwrite(vortex->mmio, VORTEX_EQ_SOURCE + (i << 2), 0x0); 408} 409 410static void vortex_EqHw_ZeroA3DIO(vortex_t * vortex) 411{ 412 int i; 413 for (i = 0; i < 0x4; i++) 414 hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0); 415} 416 417static void vortex_EqHw_ZeroState(vortex_t * vortex) 418{ 419 420 vortex_EqHw_SetControlReg(vortex, 0); 421 vortex_EqHw_ZeroIO(vortex); 422 hwwrite(vortex->mmio, 0x2b3c0, 0); 423 424 vortex_EqHw_SetTimeConsts(vortex, 0, 0); 425 426 vortex_EqHw_SetLeftCoefs(vortex, asEqCoefsZeros); 427 vortex_EqHw_SetRightCoefs(vortex, asEqCoefsZeros); 428 429 vortex_EqHw_SetLeftGainsCurrent(vortex, eq_gains_zero); 430 vortex_EqHw_SetRightGainsCurrent(vortex, eq_gains_zero); 431 vortex_EqHw_SetLeftGainsTarget(vortex, eq_gains_zero); 432 vortex_EqHw_SetRightGainsTarget(vortex, eq_gains_zero); 433 434 vortex_EqHw_SetBypassGain(vortex, 0, 0); 435 //vortex_EqHw_SetCurrBypassGain(vortex, 0, 0); 436 vortex_EqHw_SetA3DBypassGain(vortex, 0, 0); 437 //vortex_EqHw_SetCurrA3DBypassGain(vortex, 0, 0); 438 vortex_EqHw_SetLeftStates(vortex, eq_states_zero, asEqOutStateZeros); 439 vortex_EqHw_SetRightStates(vortex, eq_states_zero, asEqOutStateZeros); 440 vortex_EqHw_SetLevels(vortex, (u16 *) eq_levels); 441} 442 443/* Program coeficients as pass through */ 444static void vortex_EqHw_ProgramPipe(vortex_t * vortex) 445{ 446 vortex_EqHw_SetTimeConsts(vortex, 0, 0); 447 448 vortex_EqHw_SetLeftCoefs(vortex, asEqCoefsPipes); 449 vortex_EqHw_SetRightCoefs(vortex, asEqCoefsPipes); 450 451 vortex_EqHw_SetLeftGainsCurrent(vortex, eq_gains_current); 452 vortex_EqHw_SetRightGainsCurrent(vortex, eq_gains_current); 453 vortex_EqHw_SetLeftGainsTarget(vortex, eq_gains_current); 454 vortex_EqHw_SetRightGainsTarget(vortex, eq_gains_current); 455} 456 457/* Program EQ block as 10 band Equalizer */ 458static void 459vortex_EqHw_Program10Band(vortex_t * vortex, auxxEqCoeffSet_t * coefset) 460{ 461 462 vortex_EqHw_SetTimeConsts(vortex, 0xc, 0x7fe0); 463 464 vortex_EqHw_SetLeftCoefs(vortex, coefset->LeftCoefs); 465 vortex_EqHw_SetRightCoefs(vortex, coefset->RightCoefs); 466 467 vortex_EqHw_SetLeftGainsCurrent(vortex, coefset->LeftGains); 468 469 vortex_EqHw_SetRightGainsTarget(vortex, coefset->RightGains); 470 vortex_EqHw_SetLeftGainsTarget(vortex, coefset->LeftGains); 471 472 vortex_EqHw_SetRightGainsCurrent(vortex, coefset->RightGains); 473} 474 475/* Read all EQ peaks. (think VU meter) */ 476static void vortex_EqHw_GetTenBandLevels(vortex_t * vortex, u16 peaks[]) 477{ 478 eqhw_t *eqhw = &(vortex->eq.this04); 479 int i; 480 481 if (eqhw->this04 <= 0) 482 return; 483 484 for (i = 0; i < eqhw->this04; i++) 485 peaks[i] = hwread(vortex->mmio, 0x2B024 + i * 0x30); 486 for (i = 0; i < eqhw->this04; i++) 487 peaks[i + eqhw->this04] = 488 hwread(vortex->mmio, 0x2B204 + i * 0x30); 489} 490 491/* CEqlzr.s */ 492 493static int vortex_Eqlzr_GetLeftGain(vortex_t * vortex, u16 index, u16 * gain) 494{ 495 eqlzr_t *eq = &(vortex->eq); 496 497 if (eq->this28) { 498 *gain = eq->this130[index]; 499 return 0; 500 } 501 return 1; 502} 503 504static void vortex_Eqlzr_SetLeftGain(vortex_t * vortex, u16 index, u16 gain) 505{ 506 eqlzr_t *eq = &(vortex->eq); 507 508 if (eq->this28 == 0) 509 return; 510 511 eq->this130[index] = gain; 512 if (eq->this54) 513 return; 514 515 vortex_EqHw_SetLeftGainsSingleTarget(vortex, index, gain); 516} 517 518static int vortex_Eqlzr_GetRightGain(vortex_t * vortex, u16 index, u16 * gain) 519{ 520 eqlzr_t *eq = &(vortex->eq); 521 522 if (eq->this28) { 523 *gain = eq->this130[index + eq->this10]; 524 return 0; 525 } 526 return 1; 527} 528 529static void vortex_Eqlzr_SetRightGain(vortex_t * vortex, u16 index, u16 gain) 530{ 531 eqlzr_t *eq = &(vortex->eq); 532 533 if (eq->this28 == 0) 534 return; 535 536 eq->this130[index + eq->this10] = gain; 537 if (eq->this54) 538 return; 539 540 vortex_EqHw_SetRightGainsSingleTarget(vortex, index, gain); 541} 542 543#if 0 544static int 545vortex_Eqlzr_GetAllBands(vortex_t * vortex, u16 * gains, s32 *cnt) 546{ 547 eqlzr_t *eq = &(vortex->eq); 548 int si = 0; 549 550 if (eq->this10 == 0) 551 return 1; 552 553 { 554 if (vortex_Eqlzr_GetLeftGain(vortex, si, &gains[si])) 555 return 1; 556 if (vortex_Eqlzr_GetRightGain 557 (vortex, si, &gains[si + eq->this10])) 558 return 1; 559 si++; 560 } 561 while (eq->this10 > si) ; 562 *cnt = si * 2; 563 return 0; 564} 565#endif 566static int vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex_t * vortex) 567{ 568 eqlzr_t *eq = &(vortex->eq); 569 570 vortex_EqHw_SetLeftGainsTarget(vortex, eq->this130); 571 vortex_EqHw_SetRightGainsTarget(vortex, &(eq->this130[eq->this10])); 572 573 return 0; 574} 575 576static int 577vortex_Eqlzr_SetAllBands(vortex_t *vortex, const u16 gains[], s32 count) 578{ 579 eqlzr_t *eq = &(vortex->eq); 580 int i; 581 582 if (((eq->this10) * 2 != count) || (eq->this28 == 0)) 583 return 1; 584 585 for (i = 0; i < count; i++) { 586 eq->this130[i] = gains[i]; 587 } 588 589 if (eq->this54) 590 return 0; 591 return vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex); 592} 593 594static void 595vortex_Eqlzr_SetA3dBypassGain(vortex_t * vortex, u32 a, u32 b) 596{ 597 eqlzr_t *eq = &(vortex->eq); 598 u32 eax, ebx; 599 600 eq->this58 = a; 601 eq->this5c = b; 602 if (eq->this54) 603 eax = eq->this0e; 604 else 605 eax = eq->this0a; 606 ebx = (eax * eq->this58) >> 0x10; 607 eax = (eax * eq->this5c) >> 0x10; 608 vortex_EqHw_SetA3DBypassGain(vortex, ebx, eax); 609} 610 611static void vortex_Eqlzr_ProgramA3dBypassGain(vortex_t * vortex) 612{ 613 eqlzr_t *eq = &(vortex->eq); 614 u32 eax, ebx; 615 616 if (eq->this54) 617 eax = eq->this0e; 618 else 619 eax = eq->this0a; 620 ebx = (eax * eq->this58) >> 0x10; 621 eax = (eax * eq->this5c) >> 0x10; 622 vortex_EqHw_SetA3DBypassGain(vortex, ebx, eax); 623} 624 625static void vortex_Eqlzr_ShutDownA3d(vortex_t * vortex) 626{ 627 if (vortex != NULL) 628 vortex_EqHw_ZeroA3DIO(vortex); 629} 630 631static void vortex_Eqlzr_SetBypass(vortex_t * vortex, u32 bp) 632{ 633 eqlzr_t *eq = &(vortex->eq); 634 635 if ((eq->this28) && (bp == 0)) { 636 /* EQ enabled */ 637 vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex); 638 vortex_EqHw_SetBypassGain(vortex, eq->this08, eq->this08); 639 } else { 640 /* EQ disabled. */ 641 vortex_EqHw_SetLeftGainsTarget(vortex, eq->this14_array); 642 vortex_EqHw_SetRightGainsTarget(vortex, eq->this14_array); 643 vortex_EqHw_SetBypassGain(vortex, eq->this0c, eq->this0c); 644 } 645 vortex_Eqlzr_ProgramA3dBypassGain(vortex); 646} 647 648static void vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex_t * vortex) 649{ 650 eqlzr_t *eq = &(vortex->eq); 651 652 /* Set EQ BiQuad filter coeficients */ 653 memcpy(&(eq->coefset), &asEqCoefsNormal, sizeof(auxxEqCoeffSet_t)); 654 /* Set EQ Band gain levels and dump into hardware registers. */ 655 vortex_Eqlzr_SetAllBands(vortex, eq_gains_normal, eq->this10 * 2); 656} 657 658static int vortex_Eqlzr_GetAllPeaks(vortex_t * vortex, u16 * peaks, int *count) 659{ 660 eqlzr_t *eq = &(vortex->eq); 661 662 if (eq->this10 == 0) 663 return 1; 664 *count = eq->this10 * 2; 665 vortex_EqHw_GetTenBandLevels(vortex, peaks); 666 return 0; 667} 668 669#if 0 670static auxxEqCoeffSet_t *vortex_Eqlzr_GetActiveCoefSet(vortex_t * vortex) 671{ 672 eqlzr_t *eq = &(vortex->eq); 673 674 return (&(eq->coefset)); 675} 676#endif 677static void vortex_Eqlzr_init(vortex_t * vortex) 678{ 679 eqlzr_t *eq = &(vortex->eq); 680 681 /* Object constructor */ 682 //eq->this04 = 0; 683 eq->this08 = 0; /* Bypass gain with EQ in use. */ 684 eq->this0a = 0x5999; 685 eq->this0c = 0x5999; /* Bypass gain with EQ disabled. */ 686 eq->this0e = 0x5999; 687 688 eq->this10 = 0xa; /* 10 eq frequency bands. */ 689 eq->this04.this04 = eq->this10; 690 eq->this28 = 0x1; /* if 1 => Allow read access to this130 (gains) */ 691 eq->this54 = 0x0; /* if 1 => Dont Allow access to hardware (gains) */ 692 eq->this58 = 0xffff; 693 eq->this5c = 0xffff; 694 695 /* Set gains. */ 696 memset(eq->this14_array, 0, sizeof(eq->this14_array)); 697 698 /* Actual init. */ 699 vortex_EqHw_ZeroState(vortex); 700 vortex_EqHw_SetSampleRate(vortex, 0x11); 701 vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex); 702 703 vortex_EqHw_Program10Band(vortex, &(eq->coefset)); 704 vortex_Eqlzr_SetBypass(vortex, eq->this54); 705 vortex_Eqlzr_SetA3dBypassGain(vortex, 0, 0); 706 vortex_EqHw_Enable(vortex); 707} 708 709static void vortex_Eqlzr_shutdown(vortex_t * vortex) 710{ 711 vortex_Eqlzr_ShutDownA3d(vortex); 712 vortex_EqHw_ProgramPipe(vortex); 713 vortex_EqHw_Disable(vortex); 714} 715 716/* ALSA interface */ 717 718/* Control interface */ 719#define snd_vortex_eqtoggle_info snd_ctl_boolean_mono_info 720 721static int 722snd_vortex_eqtoggle_get(struct snd_kcontrol *kcontrol, 723 struct snd_ctl_elem_value *ucontrol) 724{ 725 vortex_t *vortex = snd_kcontrol_chip(kcontrol); 726 eqlzr_t *eq = &(vortex->eq); 727 //int i = kcontrol->private_value; 728 729 ucontrol->value.integer.value[0] = eq->this54 ? 0 : 1; 730 731 return 0; 732} 733 734static int 735snd_vortex_eqtoggle_put(struct snd_kcontrol *kcontrol, 736 struct snd_ctl_elem_value *ucontrol) 737{ 738 vortex_t *vortex = snd_kcontrol_chip(kcontrol); 739 eqlzr_t *eq = &(vortex->eq); 740 //int i = kcontrol->private_value; 741 742 eq->this54 = ucontrol->value.integer.value[0] ? 0 : 1; 743 vortex_Eqlzr_SetBypass(vortex, eq->this54); 744 745 return 1; /* Allways changes */ 746} 747 748static const struct snd_kcontrol_new vortex_eqtoggle_kcontrol = { 749 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 750 .name = "EQ Enable", 751 .index = 0, 752 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 753 .private_value = 0, 754 .info = snd_vortex_eqtoggle_info, 755 .get = snd_vortex_eqtoggle_get, 756 .put = snd_vortex_eqtoggle_put 757}; 758 759static int 760snd_vortex_eq_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 761{ 762 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 763 uinfo->count = 2; 764 uinfo->value.integer.min = 0x0000; 765 uinfo->value.integer.max = 0x7fff; 766 return 0; 767} 768 769static int 770snd_vortex_eq_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 771{ 772 vortex_t *vortex = snd_kcontrol_chip(kcontrol); 773 int i = kcontrol->private_value; 774 u16 gainL = 0, gainR = 0; 775 776 vortex_Eqlzr_GetLeftGain(vortex, i, &gainL); 777 vortex_Eqlzr_GetRightGain(vortex, i, &gainR); 778 ucontrol->value.integer.value[0] = gainL; 779 ucontrol->value.integer.value[1] = gainR; 780 return 0; 781} 782 783static int 784snd_vortex_eq_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 785{ 786 vortex_t *vortex = snd_kcontrol_chip(kcontrol); 787 int changed = 0, i = kcontrol->private_value; 788 u16 gainL = 0, gainR = 0; 789 790 vortex_Eqlzr_GetLeftGain(vortex, i, &gainL); 791 vortex_Eqlzr_GetRightGain(vortex, i, &gainR); 792 793 if (gainL != ucontrol->value.integer.value[0]) { 794 vortex_Eqlzr_SetLeftGain(vortex, i, 795 ucontrol->value.integer.value[0]); 796 changed = 1; 797 } 798 if (gainR != ucontrol->value.integer.value[1]) { 799 vortex_Eqlzr_SetRightGain(vortex, i, 800 ucontrol->value.integer.value[1]); 801 changed = 1; 802 } 803 return changed; 804} 805 806static const struct snd_kcontrol_new vortex_eq_kcontrol = { 807 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 808 .name = " .", 809 .index = 0, 810 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 811 .private_value = 0, 812 .info = snd_vortex_eq_info, 813 .get = snd_vortex_eq_get, 814 .put = snd_vortex_eq_put 815}; 816 817static int 818snd_vortex_peaks_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 819{ 820 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 821 uinfo->count = 20; 822 uinfo->value.integer.min = 0x0000; 823 uinfo->value.integer.max = 0x7fff; 824 return 0; 825} 826 827static int 828snd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 829{ 830 vortex_t *vortex = snd_kcontrol_chip(kcontrol); 831 int i, count = 0; 832 u16 peaks[20]; 833 834 vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count); 835 if (count != 20) { 836 dev_err(vortex->card->dev, 837 "peak count error 20 != %d\n", count); 838 return -1; 839 } 840 for (i = 0; i < 20; i++) 841 ucontrol->value.integer.value[i] = peaks[i]; 842 843 return 0; 844} 845 846static const struct snd_kcontrol_new vortex_levels_kcontrol = { 847 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 848 .name = "EQ Peaks", 849 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 850 .info = snd_vortex_peaks_info, 851 .get = snd_vortex_peaks_get, 852}; 853 854/* EQ band gain labels. */ 855static const char * const EqBandLabels[10] = { 856 "EQ0 31Hz\0", 857 "EQ1 63Hz\0", 858 "EQ2 125Hz\0", 859 "EQ3 250Hz\0", 860 "EQ4 500Hz\0", 861 "EQ5 1KHz\0", 862 "EQ6 2KHz\0", 863 "EQ7 4KHz\0", 864 "EQ8 8KHz\0", 865 "EQ9 16KHz\0", 866}; 867 868/* ALSA driver entry points. Init and exit. */ 869static int vortex_eq_init(vortex_t *vortex) 870{ 871 struct snd_kcontrol *kcontrol; 872 int err, i; 873 874 vortex_Eqlzr_init(vortex); 875 876 kcontrol = snd_ctl_new1(&vortex_eqtoggle_kcontrol, vortex); 877 if (!kcontrol) 878 return -ENOMEM; 879 kcontrol->private_value = 0; 880 err = snd_ctl_add(vortex->card, kcontrol); 881 if (err < 0) 882 return err; 883 884 /* EQ gain controls */ 885 for (i = 0; i < 10; i++) { 886 kcontrol = snd_ctl_new1(&vortex_eq_kcontrol, vortex); 887 if (!kcontrol) 888 return -ENOMEM; 889 snprintf(kcontrol->id.name, sizeof(kcontrol->id.name), 890 "%s Playback Volume", EqBandLabels[i]); 891 kcontrol->private_value = i; 892 err = snd_ctl_add(vortex->card, kcontrol); 893 if (err < 0) 894 return err; 895 //vortex->eqctrl[i] = kcontrol; 896 } 897 /* EQ band levels */ 898 kcontrol = snd_ctl_new1(&vortex_levels_kcontrol, vortex); 899 if (!kcontrol) 900 return -ENOMEM; 901 err = snd_ctl_add(vortex->card, kcontrol); 902 if (err < 0) 903 return err; 904 905 return 0; 906} 907 908static int vortex_eq_free(vortex_t * vortex) 909{ 910 /* 911 //FIXME: segfault because vortex->eqctrl[i] == 4 912 int i; 913 for (i=0; i<10; i++) { 914 if (vortex->eqctrl[i]) 915 snd_ctl_remove(vortex->card, vortex->eqctrl[i]); 916 } 917 */ 918 vortex_Eqlzr_shutdown(vortex); 919 return 0; 920} 921 922/* End */