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