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