Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
au88x0_eq.c
Go to the documentation of this file.
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 ([email protected])
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 */
51 static 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 
57 static 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 
66 static 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 
88 static 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 
111 static 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 
128 static 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
146 static 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 
152 static void vortex_EqHw_GetLeftCoefs(vortex_t * vortex, u16 a[])
153 {
154 
155 }
156 
157 static void vortex_EqHw_GetRightCoefs(vortex_t * vortex, u16 a[])
158 {
159 
160 }
161 
162 static void vortex_EqHw_GetLeftStates(vortex_t * vortex, u16 * a, u16 b[])
163 {
164 
165 }
166 
167 static void vortex_EqHw_GetRightStates(vortex_t * vortex, u16 * a, u16 b[])
168 {
169 
170 }
171 
172 #endif
173 /* Mix Gains */
174 static 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 
186 static 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
194 static 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 
201 static 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
209 static void
210 vortex_EqHw_SetLeftGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
211 {
212  hwwrite(vortex->mmio, 0x2b02c + (index * 0x30), b);
213 }
214 
215 static void
216 vortex_EqHw_SetRightGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
217 {
218  hwwrite(vortex->mmio, 0x2b20c + (index * 0x30), b);
219 }
220 
221 static 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 
231 static 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 
241 static 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 
251 static 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
262 static 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 
277 static 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 
292 static 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 
307 static 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 */
324 static 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
348 static 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 */
380 static void vortex_EqHw_SetControlReg(vortex_t * vortex, u32 reg)
381 {
382  hwwrite(vortex->mmio, 0x2b440, reg);
383 }
384 
385 static void vortex_EqHw_SetSampleRate(vortex_t * vortex, u32 sr)
386 {
387  hwwrite(vortex->mmio, 0x2b440, ((sr & 0x1f) << 3) | 0xb800);
388 }
389 
390 #if 0
391 static void vortex_EqHw_GetControlReg(vortex_t * vortex, u32 *reg)
392 {
393  *reg = hwread(vortex->mmio, 0x2b440);
394 }
395 
396 static void vortex_EqHw_GetSampleRate(vortex_t * vortex, u32 *sr)
397 {
398  *sr = (hwread(vortex->mmio, 0x2b440) >> 3) & 0x1f;
399 }
400 
401 #endif
402 static void vortex_EqHw_Enable(vortex_t * vortex)
403 {
404  hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf001);
405 }
406 
407 static void vortex_EqHw_Disable(vortex_t * vortex)
408 {
409  hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf000);
410 }
411 
412 /* Reset (zero) buffers */
413 static 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 
422 static 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 
429 static 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 */
456 static 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 */
470 static void
471 vortex_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) */
488 static 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 
505 static 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 
516 static 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 
530 static 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 
541 static 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
556 static int
557 vortex_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
578 static 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 
588 static int
589 vortex_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 
606 static void
607 vortex_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 
623 static 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 
637 static void vortex_Eqlzr_ShutDownA3d(vortex_t * vortex)
638 {
639  if (vortex != NULL)
640  vortex_EqHw_ZeroA3DIO(vortex);
641 }
642 
643 static 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 
660 static 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 
670 static 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
682 static auxxEqCoeffSet_t *vortex_Eqlzr_GetActiveCoefSet(vortex_t * vortex)
683 {
684  eqlzr_t *eq = &(vortex->eq);
685 
686  return (&(eq->coefset));
687 }
688 #endif
689 static 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 
721 static 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 
733 static int
734 snd_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 
746 static int
747 snd_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 
760 static struct snd_kcontrol_new vortex_eqtoggle_kcontrol __devinitdata = {
762  .name = "EQ Enable",
763  .index = 0,
765  .private_value = 0,
766  .info = snd_vortex_eqtoggle_info,
767  .get = snd_vortex_eqtoggle_get,
768  .put = snd_vortex_eqtoggle_put
769 };
770 
771 static int
772 snd_vortex_eq_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
773 {
775  uinfo->count = 2;
776  uinfo->value.integer.min = 0x0000;
777  uinfo->value.integer.max = 0x7fff;
778  return 0;
779 }
780 
781 static int
782 snd_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 
795 static int
796 snd_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 
818 static struct snd_kcontrol_new vortex_eq_kcontrol __devinitdata = {
820  .name = " .",
821  .index = 0,
823  .private_value = 0,
824  .info = snd_vortex_eq_info,
825  .get = snd_vortex_eq_get,
826  .put = snd_vortex_eq_put
827 };
828 
829 static int
830 snd_vortex_peaks_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
831 {
833  uinfo->count = 20;
834  uinfo->value.integer.min = 0x0000;
835  uinfo->value.integer.max = 0x7fff;
836  return 0;
837 }
838 
839 static int
840 snd_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  printk(KERN_ERR "vortex: peak count error 20 != %d \n", count);
849  return -1;
850  }
851  for (i = 0; i < 20; i++)
852  ucontrol->value.integer.value[i] = peaks[i];
853 
854  return 0;
855 }
856 
857 static struct snd_kcontrol_new vortex_levels_kcontrol __devinitdata = {
859  .name = "EQ Peaks",
861  .info = snd_vortex_peaks_info,
862  .get = snd_vortex_peaks_get,
863 };
864 
865 /* EQ band gain labels. */
866 static char *EqBandLabels[10] __devinitdata = {
867  "EQ0 31Hz\0",
868  "EQ1 63Hz\0",
869  "EQ2 125Hz\0",
870  "EQ3 250Hz\0",
871  "EQ4 500Hz\0",
872  "EQ5 1KHz\0",
873  "EQ6 2KHz\0",
874  "EQ7 4KHz\0",
875  "EQ8 8KHz\0",
876  "EQ9 16KHz\0",
877 };
878 
879 /* ALSA driver entry points. Init and exit. */
880 static int __devinit vortex_eq_init(vortex_t * vortex)
881 {
882  struct snd_kcontrol *kcontrol;
883  int err, i;
884 
885  vortex_Eqlzr_init(vortex);
886 
887  if ((kcontrol =
888  snd_ctl_new1(&vortex_eqtoggle_kcontrol, vortex)) == NULL)
889  return -ENOMEM;
890  kcontrol->private_value = 0;
891  if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
892  return err;
893 
894  /* EQ gain controls */
895  for (i = 0; i < 10; i++) {
896  if ((kcontrol =
897  snd_ctl_new1(&vortex_eq_kcontrol, vortex)) == NULL)
898  return -ENOMEM;
899  snprintf(kcontrol->id.name, sizeof(kcontrol->id.name),
900  "%s Playback Volume", EqBandLabels[i]);
901  kcontrol->private_value = i;
902  if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
903  return err;
904  //vortex->eqctrl[i] = kcontrol;
905  }
906  /* EQ band levels */
907  if ((kcontrol = snd_ctl_new1(&vortex_levels_kcontrol, vortex)) == NULL)
908  return -ENOMEM;
909  if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
910  return err;
911 
912  return 0;
913 }
914 
915 static int vortex_eq_free(vortex_t * vortex)
916 {
917  /*
918  //FIXME: segfault because vortex->eqctrl[i] == 4
919  int i;
920  for (i=0; i<10; i++) {
921  if (vortex->eqctrl[i])
922  snd_ctl_remove(vortex->card, vortex->eqctrl[i]);
923  }
924  */
925  vortex_Eqlzr_shutdown(vortex);
926  return 0;
927 }
928 
929 /* End */