Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/pci/au88x0/au88x0_eq.c
26451 views
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 ([email protected])
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 */
39
static 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
45
static 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
54
static 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
76
static 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
99
static 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
116
static 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
134
static 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
140
static void vortex_EqHw_GetLeftCoefs(vortex_t * vortex, u16 a[])
141
{
142
143
}
144
145
static void vortex_EqHw_GetRightCoefs(vortex_t * vortex, u16 a[])
146
{
147
148
}
149
150
static void vortex_EqHw_GetLeftStates(vortex_t * vortex, u16 * a, u16 b[])
151
{
152
153
}
154
155
static void vortex_EqHw_GetRightStates(vortex_t * vortex, u16 * a, u16 b[])
156
{
157
158
}
159
160
#endif
161
/* Mix Gains */
162
static 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
174
static 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
182
static 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
189
static 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
197
static void
198
vortex_EqHw_SetLeftGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
199
{
200
hwwrite(vortex->mmio, 0x2b02c + (index * 0x30), b);
201
}
202
203
static void
204
vortex_EqHw_SetRightGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
205
{
206
hwwrite(vortex->mmio, 0x2b20c + (index * 0x30), b);
207
}
208
209
static 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
219
static 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
229
static 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
239
static 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
250
static 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
265
static 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
280
static 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
295
static 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 */
312
static 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
336
static 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 */
368
static void vortex_EqHw_SetControlReg(vortex_t * vortex, u32 reg)
369
{
370
hwwrite(vortex->mmio, 0x2b440, reg);
371
}
372
373
static void vortex_EqHw_SetSampleRate(vortex_t * vortex, u32 sr)
374
{
375
hwwrite(vortex->mmio, 0x2b440, ((sr & 0x1f) << 3) | 0xb800);
376
}
377
378
#if 0
379
static void vortex_EqHw_GetControlReg(vortex_t * vortex, u32 *reg)
380
{
381
*reg = hwread(vortex->mmio, 0x2b440);
382
}
383
384
static void vortex_EqHw_GetSampleRate(vortex_t * vortex, u32 *sr)
385
{
386
*sr = (hwread(vortex->mmio, 0x2b440) >> 3) & 0x1f;
387
}
388
389
#endif
390
static void vortex_EqHw_Enable(vortex_t * vortex)
391
{
392
hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf001);
393
}
394
395
static void vortex_EqHw_Disable(vortex_t * vortex)
396
{
397
hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf000);
398
}
399
400
/* Reset (zero) buffers */
401
static 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
410
static 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
417
static 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 */
444
static 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 */
458
static void
459
vortex_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) */
476
static 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
493
static 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
504
static 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
518
static 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
529
static 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
544
static int
545
vortex_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
566
static 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
576
static int
577
vortex_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
594
static void
595
vortex_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
611
static 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
625
static void vortex_Eqlzr_ShutDownA3d(vortex_t * vortex)
626
{
627
if (vortex != NULL)
628
vortex_EqHw_ZeroA3DIO(vortex);
629
}
630
631
static 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
648
static 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
658
static 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
670
static auxxEqCoeffSet_t *vortex_Eqlzr_GetActiveCoefSet(vortex_t * vortex)
671
{
672
eqlzr_t *eq = &(vortex->eq);
673
674
return (&(eq->coefset));
675
}
676
#endif
677
static 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
709
static 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
721
static int
722
snd_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
734
static int
735
snd_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
748
static 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
759
static int
760
snd_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
769
static int
770
snd_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
783
static int
784
snd_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
806
static 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
817
static int
818
snd_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
827
static int
828
snd_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
846
static 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. */
855
static 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. */
869
static 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
908
static 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 */
923
924