~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/pci/au88x0/au88x0_eq.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 */
 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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php