Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/pci/au88x0/au88x0_a3d.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/***************************************************************************
3
* au88x0_a3d.c
4
*
5
* Fri Jul 18 14:16:22 2003
6
* Copyright 2003 mjander
7
* [email protected]
8
*
9
* A3D. You may think i'm crazy, but this may work someday. Who knows...
10
****************************************************************************/
11
12
/*
13
*/
14
15
#include "au88x0_a3d.h"
16
#include "au88x0_a3ddata.c"
17
#include "au88x0_xtalk.h"
18
#include "au88x0.h"
19
20
static void
21
a3dsrc_SetTimeConsts(a3dsrc_t * a, short HrtfTrack, short ItdTrack,
22
short GTrack, short CTrack)
23
{
24
vortex_t *vortex = (vortex_t *) (a->vortex);
25
hwwrite(vortex->mmio,
26
a3d_addrA(a->slice, a->source, A3D_A_HrtfTrackTC), HrtfTrack);
27
hwwrite(vortex->mmio,
28
a3d_addrA(a->slice, a->source, A3D_A_ITDTrackTC), ItdTrack);
29
hwwrite(vortex->mmio,
30
a3d_addrA(a->slice, a->source, A3D_A_GainTrackTC), GTrack);
31
hwwrite(vortex->mmio,
32
a3d_addrA(a->slice, a->source, A3D_A_CoeffTrackTC), CTrack);
33
}
34
35
#if 0
36
static void
37
a3dsrc_GetTimeConsts(a3dsrc_t * a, short *HrtfTrack, short *ItdTrack,
38
short *GTrack, short *CTrack)
39
{
40
// stub!
41
}
42
43
#endif
44
/* Atmospheric absorption. */
45
46
static void
47
a3dsrc_SetAtmosTarget(a3dsrc_t * a, short aa, short b, short c, short d,
48
short e)
49
{
50
vortex_t *vortex = (vortex_t *) (a->vortex);
51
hwwrite(vortex->mmio,
52
a3d_addrB(a->slice, a->source, A3D_B_A21Target),
53
(e << 0x10) | d);
54
hwwrite(vortex->mmio,
55
a3d_addrB(a->slice, a->source, A3D_B_B10Target),
56
(b << 0x10) | aa);
57
hwwrite(vortex->mmio,
58
a3d_addrB(a->slice, a->source, A3D_B_B2Target), c);
59
}
60
61
static void
62
a3dsrc_SetAtmosCurrent(a3dsrc_t * a, short aa, short b, short c, short d,
63
short e)
64
{
65
vortex_t *vortex = (vortex_t *) (a->vortex);
66
hwwrite(vortex->mmio,
67
a3d_addrB(a->slice, a->source, A3D_B_A12Current),
68
(e << 0x10) | d);
69
hwwrite(vortex->mmio,
70
a3d_addrB(a->slice, a->source, A3D_B_B01Current),
71
(b << 0x10) | aa);
72
hwwrite(vortex->mmio,
73
a3d_addrB(a->slice, a->source, A3D_B_B2Current), c);
74
}
75
76
static void
77
a3dsrc_SetAtmosState(a3dsrc_t * a, short x1, short x2, short y1, short y2)
78
{
79
vortex_t *vortex = (vortex_t *) (a->vortex);
80
hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_x1), x1);
81
hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_x2), x2);
82
hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_y1), y1);
83
hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_y2), y2);
84
}
85
86
#if 0
87
static void
88
a3dsrc_GetAtmosTarget(a3dsrc_t * a, short *aa, short *b, short *c,
89
short *d, short *e)
90
{
91
}
92
static void
93
a3dsrc_GetAtmosCurrent(a3dsrc_t * a, short *bb01, short *ab01, short *b2,
94
short *aa12, short *ba12)
95
{
96
vortex_t *vortex = (vortex_t *) (a->vortex);
97
*aa12 =
98
hwread(vortex->mmio,
99
a3d_addrA(a->slice, a->source, A3D_A_A12Current));
100
*ba12 =
101
hwread(vortex->mmio,
102
a3d_addrB(a->slice, a->source, A3D_B_A12Current));
103
*ab01 =
104
hwread(vortex->mmio,
105
a3d_addrA(a->slice, a->source, A3D_A_B01Current));
106
*bb01 =
107
hwread(vortex->mmio,
108
a3d_addrB(a->slice, a->source, A3D_B_B01Current));
109
*b2 =
110
hwread(vortex->mmio,
111
a3d_addrA(a->slice, a->source, A3D_A_B2Current));
112
}
113
114
static void
115
a3dsrc_GetAtmosState(a3dsrc_t * a, short *x1, short *x2, short *y1, short *y2)
116
{
117
118
}
119
120
#endif
121
/* HRTF */
122
123
static void
124
a3dsrc_SetHrtfTarget(a3dsrc_t * a, a3d_Hrtf_t const aa, a3d_Hrtf_t const b)
125
{
126
vortex_t *vortex = (vortex_t *) (a->vortex);
127
int i;
128
129
for (i = 0; i < HRTF_SZ; i++)
130
hwwrite(vortex->mmio,
131
a3d_addrB(a->slice, a->source,
132
A3D_B_HrtfTarget) + (i << 2),
133
(b[i] << 0x10) | aa[i]);
134
}
135
136
static void
137
a3dsrc_SetHrtfCurrent(a3dsrc_t * a, a3d_Hrtf_t const aa, a3d_Hrtf_t const b)
138
{
139
vortex_t *vortex = (vortex_t *) (a->vortex);
140
int i;
141
142
for (i = 0; i < HRTF_SZ; i++)
143
hwwrite(vortex->mmio,
144
a3d_addrB(a->slice, a->source,
145
A3D_B_HrtfCurrent) + (i << 2),
146
(b[i] << 0x10) | aa[i]);
147
}
148
149
static void
150
a3dsrc_SetHrtfState(a3dsrc_t * a, a3d_Hrtf_t const aa, a3d_Hrtf_t const b)
151
{
152
vortex_t *vortex = (vortex_t *) (a->vortex);
153
int i;
154
155
for (i = 0; i < HRTF_SZ; i++)
156
hwwrite(vortex->mmio,
157
a3d_addrB(a->slice, a->source,
158
A3D_B_HrtfDelayLine) + (i << 2),
159
(b[i] << 0x10) | aa[i]);
160
}
161
162
static void a3dsrc_SetHrtfOutput(a3dsrc_t * a, short left, short right)
163
{
164
vortex_t *vortex = (vortex_t *) (a->vortex);
165
hwwrite(vortex->mmio,
166
a3d_addrA(a->slice, a->source, A3D_A_HrtfOutL), left);
167
hwwrite(vortex->mmio,
168
a3d_addrA(a->slice, a->source, A3D_A_HrtfOutR), right);
169
}
170
171
#if 0
172
static void a3dsrc_GetHrtfTarget(a3dsrc_t * a, a3d_Hrtf_t aa, a3d_Hrtf_t b)
173
{
174
vortex_t *vortex = (vortex_t *) (a->vortex);
175
int i;
176
177
for (i = 0; i < HRTF_SZ; i++)
178
aa[i] =
179
hwread(vortex->mmio,
180
a3d_addrA(a->slice, a->source,
181
A3D_A_HrtfTarget + (i << 2)));
182
for (i = 0; i < HRTF_SZ; i++)
183
b[i] =
184
hwread(vortex->mmio,
185
a3d_addrB(a->slice, a->source,
186
A3D_B_HrtfTarget + (i << 2)));
187
}
188
189
static void a3dsrc_GetHrtfCurrent(a3dsrc_t * a, a3d_Hrtf_t aa, a3d_Hrtf_t b)
190
{
191
vortex_t *vortex = (vortex_t *) (a->vortex);
192
int i;
193
194
for (i = 0; i < HRTF_SZ; i++)
195
aa[i] =
196
hwread(vortex->mmio,
197
a3d_addrA(a->slice, a->source,
198
A3D_A_HrtfCurrent + (i << 2)));
199
for (i = 0; i < HRTF_SZ; i++)
200
b[i] =
201
hwread(vortex->mmio,
202
a3d_addrB(a->slice, a->source,
203
A3D_B_HrtfCurrent + (i << 2)));
204
}
205
206
static void a3dsrc_GetHrtfState(a3dsrc_t * a, a3d_Hrtf_t aa, a3d_Hrtf_t b)
207
{
208
vortex_t *vortex = (vortex_t *) (a->vortex);
209
int i;
210
// FIXME: verify this!
211
for (i = 0; i < HRTF_SZ; i++)
212
aa[i] =
213
hwread(vortex->mmio,
214
a3d_addrA(a->slice, a->source,
215
A3D_A_HrtfDelayLine + (i << 2)));
216
for (i = 0; i < HRTF_SZ; i++)
217
b[i] =
218
hwread(vortex->mmio,
219
a3d_addrB(a->slice, a->source,
220
A3D_B_HrtfDelayLine + (i << 2)));
221
}
222
223
static void a3dsrc_GetHrtfOutput(a3dsrc_t * a, short *left, short *right)
224
{
225
vortex_t *vortex = (vortex_t *) (a->vortex);
226
*left =
227
hwread(vortex->mmio,
228
a3d_addrA(a->slice, a->source, A3D_A_HrtfOutL));
229
*right =
230
hwread(vortex->mmio,
231
a3d_addrA(a->slice, a->source, A3D_A_HrtfOutR));
232
}
233
234
#endif
235
236
/* Interaural Time Difference.
237
* "The other main clue that humans use to locate sounds, is called
238
* Interaural Time Difference (ITD). The differences in distance from
239
* the sound source to a listeners ears means that the sound will
240
* reach one ear slightly before the other....", found somewhere with google.*/
241
static void a3dsrc_SetItdTarget(a3dsrc_t * a, short litd, short ritd)
242
{
243
vortex_t *vortex = (vortex_t *) (a->vortex);
244
245
if (litd < 0)
246
litd = 0;
247
if (litd > 0x57FF)
248
litd = 0x57FF;
249
if (ritd < 0)
250
ritd = 0;
251
if (ritd > 0x57FF)
252
ritd = 0x57FF;
253
hwwrite(vortex->mmio,
254
a3d_addrB(a->slice, a->source, A3D_B_ITDTarget),
255
(ritd << 0x10) | litd);
256
//hwwrite(vortex->mmio, addr(0x191DF+5, this04, this08), (ritd<<0x10)|litd);
257
}
258
259
static void a3dsrc_SetItdCurrent(a3dsrc_t * a, short litd, short ritd)
260
{
261
vortex_t *vortex = (vortex_t *) (a->vortex);
262
263
if (litd < 0)
264
litd = 0;
265
if (litd > 0x57FF)
266
litd = 0x57FF;
267
if (ritd < 0)
268
ritd = 0;
269
if (ritd > 0x57FF)
270
ritd = 0x57FF;
271
hwwrite(vortex->mmio,
272
a3d_addrB(a->slice, a->source, A3D_B_ITDCurrent),
273
(ritd << 0x10) | litd);
274
//hwwrite(vortex->mmio, addr(0x191DF+1, this04, this08), (ritd<<0x10)|litd);
275
}
276
277
static void a3dsrc_SetItdDline(a3dsrc_t * a, a3d_ItdDline_t const dline)
278
{
279
vortex_t *vortex = (vortex_t *) (a->vortex);
280
int i;
281
/* 45 != 40 -> Check this ! */
282
for (i = 0; i < DLINE_SZ; i++)
283
hwwrite(vortex->mmio,
284
a3d_addrA(a->slice, a->source,
285
A3D_A_ITDDelayLine) + (i << 2), dline[i]);
286
}
287
288
#if 0
289
static void a3dsrc_GetItdTarget(a3dsrc_t * a, short *litd, short *ritd)
290
{
291
vortex_t *vortex = (vortex_t *) (a->vortex);
292
*ritd =
293
hwread(vortex->mmio,
294
a3d_addrA(a->slice, a->source, A3D_A_ITDTarget));
295
*litd =
296
hwread(vortex->mmio,
297
a3d_addrB(a->slice, a->source, A3D_B_ITDTarget));
298
}
299
300
static void a3dsrc_GetItdCurrent(a3dsrc_t * a, short *litd, short *ritd)
301
{
302
vortex_t *vortex = (vortex_t *) (a->vortex);
303
304
*ritd =
305
hwread(vortex->mmio,
306
a3d_addrA(a->slice, a->source, A3D_A_ITDCurrent));
307
*litd =
308
hwread(vortex->mmio,
309
a3d_addrB(a->slice, a->source, A3D_B_ITDCurrent));
310
}
311
312
static void a3dsrc_GetItdDline(a3dsrc_t * a, a3d_ItdDline_t dline)
313
{
314
vortex_t *vortex = (vortex_t *) (a->vortex);
315
int i;
316
317
for (i = 0; i < DLINE_SZ; i++)
318
dline[i] =
319
hwread(vortex->mmio,
320
a3d_addrA(a->slice, a->source,
321
A3D_A_ITDDelayLine + (i << 2)));
322
}
323
324
#endif
325
/* This is may be used for ILD Interaural Level Difference. */
326
327
static void a3dsrc_SetGainTarget(a3dsrc_t * a, short left, short right)
328
{
329
vortex_t *vortex = (vortex_t *) (a->vortex);
330
hwwrite(vortex->mmio,
331
a3d_addrB(a->slice, a->source, A3D_B_GainTarget),
332
(right << 0x10) | left);
333
}
334
335
static void a3dsrc_SetGainCurrent(a3dsrc_t * a, short left, short right)
336
{
337
vortex_t *vortex = (vortex_t *) (a->vortex);
338
hwwrite(vortex->mmio,
339
a3d_addrB(a->slice, a->source, A3D_B_GainCurrent),
340
(right << 0x10) | left);
341
}
342
343
#if 0
344
static void a3dsrc_GetGainTarget(a3dsrc_t * a, short *left, short *right)
345
{
346
vortex_t *vortex = (vortex_t *) (a->vortex);
347
*right =
348
hwread(vortex->mmio,
349
a3d_addrA(a->slice, a->source, A3D_A_GainTarget));
350
*left =
351
hwread(vortex->mmio,
352
a3d_addrB(a->slice, a->source, A3D_B_GainTarget));
353
}
354
355
static void a3dsrc_GetGainCurrent(a3dsrc_t * a, short *left, short *right)
356
{
357
vortex_t *vortex = (vortex_t *) (a->vortex);
358
*right =
359
hwread(vortex->mmio,
360
a3d_addrA(a->slice, a->source, A3D_A_GainCurrent));
361
*left =
362
hwread(vortex->mmio,
363
a3d_addrB(a->slice, a->source, A3D_B_GainCurrent));
364
}
365
366
/* CA3dIO this func seems to be inlined all over this place. */
367
static void CA3dIO_WriteReg(a3dsrc_t * a, unsigned long addr, short aa, short b)
368
{
369
vortex_t *vortex = (vortex_t *) (a->vortex);
370
hwwrite(vortex->mmio, addr, (aa << 0x10) | b);
371
}
372
373
#endif
374
/* Generic A3D stuff */
375
376
static void a3dsrc_SetA3DSampleRate(a3dsrc_t * a, int sr)
377
{
378
vortex_t *vortex = (vortex_t *) (a->vortex);
379
int esp0 = 0;
380
381
esp0 = (((esp0 & 0x7fffffff) | 0xB8000000) & 0x7) | ((sr & 0x1f) << 3);
382
hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd), esp0);
383
//hwwrite(vortex->mmio, 0x19C38 + (this08<<0xd), esp0);
384
}
385
386
static void a3dsrc_EnableA3D(a3dsrc_t * a)
387
{
388
vortex_t *vortex = (vortex_t *) (a->vortex);
389
hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd),
390
0xF0000001);
391
//hwwrite(vortex->mmio, 0x19C38 + (this08<<0xd), 0xF0000001);
392
}
393
394
static void a3dsrc_DisableA3D(a3dsrc_t * a)
395
{
396
vortex_t *vortex = (vortex_t *) (a->vortex);
397
hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd),
398
0xF0000000);
399
}
400
401
static void a3dsrc_SetA3DControlReg(a3dsrc_t * a, unsigned long ctrl)
402
{
403
vortex_t *vortex = (vortex_t *) (a->vortex);
404
hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd), ctrl);
405
}
406
407
static void a3dsrc_SetA3DPointerReg(a3dsrc_t * a, unsigned long ptr)
408
{
409
vortex_t *vortex = (vortex_t *) (a->vortex);
410
hwwrite(vortex->mmio, A3D_SLICE_Pointers + ((a->slice) << 0xd), ptr);
411
}
412
413
#if 0
414
static void a3dsrc_GetA3DSampleRate(a3dsrc_t * a, int *sr)
415
{
416
vortex_t *vortex = (vortex_t *) (a->vortex);
417
*sr = ((hwread(vortex->mmio, A3D_SLICE_Control + (a->slice << 0xd))
418
>> 3) & 0x1f);
419
//*sr = ((hwread(vortex->mmio, 0x19C38 + (this08<<0xd))>>3)&0x1f);
420
}
421
422
static void a3dsrc_GetA3DControlReg(a3dsrc_t * a, unsigned long *ctrl)
423
{
424
vortex_t *vortex = (vortex_t *) (a->vortex);
425
*ctrl = hwread(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd));
426
}
427
428
static void a3dsrc_GetA3DPointerReg(a3dsrc_t * a, unsigned long *ptr)
429
{
430
vortex_t *vortex = (vortex_t *) (a->vortex);
431
*ptr = hwread(vortex->mmio, A3D_SLICE_Pointers + ((a->slice) << 0xd));
432
}
433
434
#endif
435
static void a3dsrc_ZeroSliceIO(a3dsrc_t * a)
436
{
437
vortex_t *vortex = (vortex_t *) (a->vortex);
438
int i;
439
440
for (i = 0; i < 8; i++)
441
hwwrite(vortex->mmio,
442
A3D_SLICE_VDBDest +
443
((((a->slice) << 0xb) + i) << 2), 0);
444
for (i = 0; i < 4; i++)
445
hwwrite(vortex->mmio,
446
A3D_SLICE_VDBSource +
447
((((a->slice) << 0xb) + i) << 2), 0);
448
}
449
450
/* Reset Single A3D source. */
451
static void a3dsrc_ZeroState(a3dsrc_t * a)
452
{
453
/*
454
pr_debug( "vortex: ZeroState slice: %d, source %d\n",
455
a->slice, a->source);
456
*/
457
a3dsrc_SetAtmosState(a, 0, 0, 0, 0);
458
a3dsrc_SetHrtfState(a, A3dHrirZeros, A3dHrirZeros);
459
a3dsrc_SetItdDline(a, A3dItdDlineZeros);
460
a3dsrc_SetHrtfOutput(a, 0, 0);
461
a3dsrc_SetTimeConsts(a, 0, 0, 0, 0);
462
463
a3dsrc_SetAtmosCurrent(a, 0, 0, 0, 0, 0);
464
a3dsrc_SetAtmosTarget(a, 0, 0, 0, 0, 0);
465
a3dsrc_SetItdCurrent(a, 0, 0);
466
a3dsrc_SetItdTarget(a, 0, 0);
467
a3dsrc_SetGainCurrent(a, 0, 0);
468
a3dsrc_SetGainTarget(a, 0, 0);
469
470
a3dsrc_SetHrtfCurrent(a, A3dHrirZeros, A3dHrirZeros);
471
a3dsrc_SetHrtfTarget(a, A3dHrirZeros, A3dHrirZeros);
472
}
473
474
/* Reset entire A3D engine */
475
static void a3dsrc_ZeroStateA3D(a3dsrc_t *a, vortex_t *v)
476
{
477
int i, var, var2;
478
479
if ((a->vortex) == NULL) {
480
dev_err(v->card->dev,
481
"ZeroStateA3D: ERROR: a->vortex is NULL\n");
482
return;
483
}
484
485
a3dsrc_SetA3DControlReg(a, 0);
486
a3dsrc_SetA3DPointerReg(a, 0);
487
488
var = a->slice;
489
var2 = a->source;
490
for (i = 0; i < 4; i++) {
491
a->slice = i;
492
a3dsrc_ZeroSliceIO(a);
493
//a3dsrc_ZeroState(a);
494
}
495
a->source = var2;
496
a->slice = var;
497
}
498
499
/* Program A3D block as pass through */
500
static void a3dsrc_ProgramPipe(a3dsrc_t * a)
501
{
502
a3dsrc_SetTimeConsts(a, 0, 0, 0, 0);
503
a3dsrc_SetAtmosCurrent(a, 0, 0x4000, 0, 0, 0);
504
a3dsrc_SetAtmosTarget(a, 0x4000, 0, 0, 0, 0);
505
a3dsrc_SetItdCurrent(a, 0, 0);
506
a3dsrc_SetItdTarget(a, 0, 0);
507
a3dsrc_SetGainCurrent(a, 0x7fff, 0x7fff);
508
a3dsrc_SetGainTarget(a, 0x7fff, 0x7fff);
509
510
/* SET HRTF HERE */
511
512
/* Single spike leads to identity transfer function. */
513
a3dsrc_SetHrtfCurrent(a, A3dHrirImpulse, A3dHrirImpulse);
514
a3dsrc_SetHrtfTarget(a, A3dHrirImpulse, A3dHrirImpulse);
515
516
/* Test: Sounds saturated. */
517
//a3dsrc_SetHrtfCurrent(a, A3dHrirSatTest, A3dHrirSatTest);
518
//a3dsrc_SetHrtfTarget(a, A3dHrirSatTest, A3dHrirSatTest);
519
}
520
521
/* VDB = Vortex audio Dataflow Bus */
522
#if 0
523
static void a3dsrc_ClearVDBData(a3dsrc_t * a, unsigned long aa)
524
{
525
vortex_t *vortex = (vortex_t *) (a->vortex);
526
527
// ((aa >> 2) << 8) - (aa >> 2)
528
hwwrite(vortex->mmio,
529
a3d_addrS(a->slice, A3D_SLICE_VDBDest) + (a->source << 2), 0);
530
hwwrite(vortex->mmio,
531
a3d_addrS(a->slice,
532
A3D_SLICE_VDBDest + 4) + (a->source << 2), 0);
533
/*
534
hwwrite(vortex->mmio, 0x19c00 + (((aa>>2)*255*4)+aa)*8, 0);
535
hwwrite(vortex->mmio, 0x19c04 + (((aa>>2)*255*4)+aa)*8, 0);
536
*/
537
}
538
#endif
539
540
/* A3D HwSource stuff. */
541
542
static void vortex_A3dSourceHw_Initialize(vortex_t * v, int source, int slice)
543
{
544
a3dsrc_t *a3dsrc = &(v->a3d[source + (slice * 4)]);
545
//a3dsrc_t *a3dsrc = &(v->a3d[source + (slice*4)]);
546
547
a3dsrc->vortex = (void *)v;
548
a3dsrc->source = source; /* source */
549
a3dsrc->slice = slice; /* slice */
550
a3dsrc_ZeroState(a3dsrc);
551
/* Added by me. */
552
a3dsrc_SetA3DSampleRate(a3dsrc, 0x11);
553
}
554
555
static int Vort3DRend_Initialize(vortex_t * v, unsigned short mode)
556
{
557
v->xt_mode = mode; /* this_14 */
558
559
vortex_XtalkHw_init(v);
560
vortex_XtalkHw_SetGainsAllChan(v);
561
switch (v->xt_mode) {
562
case XT_SPEAKER0:
563
vortex_XtalkHw_ProgramXtalkNarrow(v);
564
break;
565
case XT_SPEAKER1:
566
vortex_XtalkHw_ProgramXtalkWide(v);
567
break;
568
default:
569
case XT_HEADPHONE:
570
vortex_XtalkHw_ProgramPipe(v);
571
break;
572
case XT_DIAMOND:
573
vortex_XtalkHw_ProgramDiamondXtalk(v);
574
break;
575
}
576
vortex_XtalkHw_SetSampleRate(v, 0x11);
577
vortex_XtalkHw_Enable(v);
578
return 0;
579
}
580
581
/* 3D Sound entry points. */
582
583
static int vortex_a3d_register_controls(vortex_t * vortex);
584
static void vortex_a3d_unregister_controls(vortex_t * vortex);
585
/* A3D base support init/shudown */
586
static void vortex_Vort3D_enable(vortex_t *v)
587
{
588
int i;
589
590
Vort3DRend_Initialize(v, XT_HEADPHONE);
591
for (i = 0; i < NR_A3D; i++) {
592
vortex_A3dSourceHw_Initialize(v, i % 4, i >> 2);
593
a3dsrc_ZeroStateA3D(&v->a3d[0], v);
594
}
595
/* Register ALSA controls */
596
vortex_a3d_register_controls(v);
597
}
598
599
static void vortex_Vort3D_disable(vortex_t * v)
600
{
601
vortex_XtalkHw_Disable(v);
602
vortex_a3d_unregister_controls(v);
603
}
604
605
/* Make A3D subsystem connections. */
606
static void vortex_Vort3D_connect(vortex_t * v, int en)
607
{
608
int i;
609
610
// Disable AU8810 routes, since they seem to be wrong (in au8810.h).
611
#ifdef CHIP_AU8810
612
return;
613
#endif
614
615
#if 1
616
/* Alloc Xtalk mixin resources */
617
v->mixxtlk[0] =
618
vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN);
619
if (v->mixxtlk[0] < 0) {
620
dev_warn(v->card->dev,
621
"vortex_Vort3D: ERROR: not enough free mixer resources.\n");
622
return;
623
}
624
v->mixxtlk[1] =
625
vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN);
626
if (v->mixxtlk[1] < 0) {
627
dev_warn(v->card->dev,
628
"vortex_Vort3D: ERROR: not enough free mixer resources.\n");
629
return;
630
}
631
#endif
632
633
/* Connect A3D -> XTALK */
634
for (i = 0; i < 4; i++) {
635
// 2 outputs per each A3D slice.
636
vortex_route(v, en, 0x11, ADB_A3DOUT(i * 2), ADB_XTALKIN(i));
637
vortex_route(v, en, 0x11, ADB_A3DOUT(i * 2) + 1, ADB_XTALKIN(5 + i));
638
}
639
#if 0
640
vortex_route(v, en, 0x11, ADB_XTALKOUT(0), ADB_EQIN(2));
641
vortex_route(v, en, 0x11, ADB_XTALKOUT(1), ADB_EQIN(3));
642
#else
643
/* Connect XTalk -> mixer */
644
vortex_route(v, en, 0x11, ADB_XTALKOUT(0), ADB_MIXIN(v->mixxtlk[0]));
645
vortex_route(v, en, 0x11, ADB_XTALKOUT(1), ADB_MIXIN(v->mixxtlk[1]));
646
vortex_connection_mixin_mix(v, en, v->mixxtlk[0], v->mixplayb[0], 0);
647
vortex_connection_mixin_mix(v, en, v->mixxtlk[1], v->mixplayb[1], 0);
648
vortex_mix_setinputvolumebyte(v, v->mixplayb[0], v->mixxtlk[0],
649
en ? MIX_DEFIGAIN : VOL_MIN);
650
vortex_mix_setinputvolumebyte(v, v->mixplayb[1], v->mixxtlk[1],
651
en ? MIX_DEFIGAIN : VOL_MIN);
652
if (VORTEX_IS_QUAD(v)) {
653
vortex_connection_mixin_mix(v, en, v->mixxtlk[0],
654
v->mixplayb[2], 0);
655
vortex_connection_mixin_mix(v, en, v->mixxtlk[1],
656
v->mixplayb[3], 0);
657
vortex_mix_setinputvolumebyte(v, v->mixplayb[2],
658
v->mixxtlk[0],
659
en ? MIX_DEFIGAIN : VOL_MIN);
660
vortex_mix_setinputvolumebyte(v, v->mixplayb[3],
661
v->mixxtlk[1],
662
en ? MIX_DEFIGAIN : VOL_MIN);
663
}
664
#endif
665
}
666
667
/* Initialize one single A3D source. */
668
static void vortex_Vort3D_InitializeSource(a3dsrc_t *a, int en, vortex_t *v)
669
{
670
if (a->vortex == NULL) {
671
dev_warn(v->card->dev,
672
"Vort3D_InitializeSource: A3D source not initialized\n");
673
return;
674
}
675
if (en) {
676
a3dsrc_ProgramPipe(a);
677
a3dsrc_SetA3DSampleRate(a, 0x11);
678
a3dsrc_SetTimeConsts(a, HrtfTCDefault,
679
ItdTCDefault, GainTCDefault,
680
CoefTCDefault);
681
/* Remark: zero gain is muted. */
682
//a3dsrc_SetGainTarget(a,0,0);
683
//a3dsrc_SetGainCurrent(a,0,0);
684
a3dsrc_EnableA3D(a);
685
} else {
686
a3dsrc_DisableA3D(a);
687
a3dsrc_ZeroState(a);
688
}
689
}
690
691
/* Conversion of coordinates into 3D parameters. */
692
693
static void vortex_a3d_coord2hrtf(a3d_Hrtf_t hrtf, int *coord)
694
{
695
/* FIXME: implement this. */
696
697
}
698
static void vortex_a3d_coord2itd(a3d_Itd_t itd, int *coord)
699
{
700
/* FIXME: implement this. */
701
702
}
703
static void vortex_a3d_coord2ild(a3d_LRGains_t ild, int left, int right)
704
{
705
/* FIXME: implement this. */
706
707
}
708
static void vortex_a3d_translate_filter(a3d_atmos_t filter, int *params)
709
{
710
/* FIXME: implement this. */
711
712
}
713
714
/* ALSA control interface. */
715
716
static int
717
snd_vortex_a3d_hrtf_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
718
{
719
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
720
uinfo->count = 6;
721
uinfo->value.integer.min = 0x00000000;
722
uinfo->value.integer.max = 0xffffffff;
723
return 0;
724
}
725
static int
726
snd_vortex_a3d_itd_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
727
{
728
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
729
uinfo->count = 2;
730
uinfo->value.integer.min = 0x00000000;
731
uinfo->value.integer.max = 0xffffffff;
732
return 0;
733
}
734
static int
735
snd_vortex_a3d_ild_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
736
{
737
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
738
uinfo->count = 2;
739
uinfo->value.integer.min = 0x00000000;
740
uinfo->value.integer.max = 0xffffffff;
741
return 0;
742
}
743
static int
744
snd_vortex_a3d_filter_info(struct snd_kcontrol *kcontrol,
745
struct snd_ctl_elem_info *uinfo)
746
{
747
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
748
uinfo->count = 4;
749
uinfo->value.integer.min = 0x00000000;
750
uinfo->value.integer.max = 0xffffffff;
751
return 0;
752
}
753
754
static int
755
snd_vortex_a3d_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
756
{
757
//a3dsrc_t *a = snd_kcontrol_chip(kcontrol);
758
/* No read yet. Would this be really useable/needed ? */
759
760
return 0;
761
}
762
763
static int
764
snd_vortex_a3d_hrtf_put(struct snd_kcontrol *kcontrol,
765
struct snd_ctl_elem_value *ucontrol)
766
{
767
a3dsrc_t *a = snd_kcontrol_chip(kcontrol);
768
int i;
769
int coord[6];
770
for (i = 0; i < 6; i++)
771
coord[i] = ucontrol->value.integer.value[i];
772
/* Translate orientation coordinates to a3d params. */
773
vortex_a3d_coord2hrtf(a->hrtf[0], coord);
774
vortex_a3d_coord2hrtf(a->hrtf[1], coord);
775
a3dsrc_SetHrtfTarget(a, a->hrtf[0], a->hrtf[1]);
776
a3dsrc_SetHrtfCurrent(a, a->hrtf[0], a->hrtf[1]);
777
return 1;
778
}
779
780
static int
781
snd_vortex_a3d_itd_put(struct snd_kcontrol *kcontrol,
782
struct snd_ctl_elem_value *ucontrol)
783
{
784
a3dsrc_t *a = snd_kcontrol_chip(kcontrol);
785
int coord[6];
786
int i;
787
for (i = 0; i < 6; i++)
788
coord[i] = ucontrol->value.integer.value[i];
789
/* Translate orientation coordinates to a3d params. */
790
vortex_a3d_coord2itd(a->hrtf[0], coord);
791
vortex_a3d_coord2itd(a->hrtf[1], coord);
792
/* Inter aural time difference. */
793
a3dsrc_SetItdTarget(a, a->itd[0], a->itd[1]);
794
a3dsrc_SetItdCurrent(a, a->itd[0], a->itd[1]);
795
a3dsrc_SetItdDline(a, a->dline);
796
return 1;
797
}
798
799
static int
800
snd_vortex_a3d_ild_put(struct snd_kcontrol *kcontrol,
801
struct snd_ctl_elem_value *ucontrol)
802
{
803
a3dsrc_t *a = snd_kcontrol_chip(kcontrol);
804
int l, r;
805
/* There may be some scale tranlation needed here. */
806
l = ucontrol->value.integer.value[0];
807
r = ucontrol->value.integer.value[1];
808
vortex_a3d_coord2ild(a->ild, l, r);
809
/* Left Right panning. */
810
a3dsrc_SetGainTarget(a, l, r);
811
a3dsrc_SetGainCurrent(a, l, r);
812
return 1;
813
}
814
815
static int
816
snd_vortex_a3d_filter_put(struct snd_kcontrol *kcontrol,
817
struct snd_ctl_elem_value *ucontrol)
818
{
819
a3dsrc_t *a = snd_kcontrol_chip(kcontrol);
820
int i;
821
int params[6];
822
for (i = 0; i < 6; i++)
823
params[i] = ucontrol->value.integer.value[i];
824
/* Translate generic filter params to a3d filter params. */
825
vortex_a3d_translate_filter(a->filter, params);
826
/* Atmospheric absorption and filtering. */
827
a3dsrc_SetAtmosTarget(a, a->filter[0],
828
a->filter[1], a->filter[2],
829
a->filter[3], a->filter[4]);
830
a3dsrc_SetAtmosCurrent(a, a->filter[0],
831
a->filter[1], a->filter[2],
832
a->filter[3], a->filter[4]);
833
return 1;
834
}
835
836
static const struct snd_kcontrol_new vortex_a3d_kcontrol = {
837
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
838
.name = "Playback PCM advanced processing",
839
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
840
.info = snd_vortex_a3d_hrtf_info,
841
.get = snd_vortex_a3d_get,
842
.put = snd_vortex_a3d_hrtf_put,
843
};
844
845
/* Control (un)registration. */
846
static int vortex_a3d_register_controls(vortex_t *vortex)
847
{
848
struct snd_kcontrol *kcontrol;
849
int err, i;
850
/* HRTF controls. */
851
for (i = 0; i < NR_A3D; i++) {
852
kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]);
853
if (!kcontrol)
854
return -ENOMEM;
855
kcontrol->id.numid = CTRLID_HRTF;
856
kcontrol->info = snd_vortex_a3d_hrtf_info;
857
kcontrol->put = snd_vortex_a3d_hrtf_put;
858
err = snd_ctl_add(vortex->card, kcontrol);
859
if (err < 0)
860
return err;
861
}
862
/* ITD controls. */
863
for (i = 0; i < NR_A3D; i++) {
864
kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]);
865
if (!kcontrol)
866
return -ENOMEM;
867
kcontrol->id.numid = CTRLID_ITD;
868
kcontrol->info = snd_vortex_a3d_itd_info;
869
kcontrol->put = snd_vortex_a3d_itd_put;
870
err = snd_ctl_add(vortex->card, kcontrol);
871
if (err < 0)
872
return err;
873
}
874
/* ILD (gains) controls. */
875
for (i = 0; i < NR_A3D; i++) {
876
kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]);
877
if (!kcontrol)
878
return -ENOMEM;
879
kcontrol->id.numid = CTRLID_GAINS;
880
kcontrol->info = snd_vortex_a3d_ild_info;
881
kcontrol->put = snd_vortex_a3d_ild_put;
882
err = snd_ctl_add(vortex->card, kcontrol);
883
if (err < 0)
884
return err;
885
}
886
/* Filter controls. */
887
for (i = 0; i < NR_A3D; i++) {
888
kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]);
889
if (!kcontrol)
890
return -ENOMEM;
891
kcontrol->id.numid = CTRLID_FILTER;
892
kcontrol->info = snd_vortex_a3d_filter_info;
893
kcontrol->put = snd_vortex_a3d_filter_put;
894
err = snd_ctl_add(vortex->card, kcontrol);
895
if (err < 0)
896
return err;
897
}
898
return 0;
899
}
900
901
static void vortex_a3d_unregister_controls(vortex_t * vortex)
902
{
903
904
}
905
906
/* End of File*/
907
908