Commit | Line | Data |
---|---|---|
005fdd53 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4 LT |
2 | /*************************************************************************** |
3 | * au88x0_a3d.c | |
4 | * | |
5 | * Fri Jul 18 14:16:22 2003 | |
6 | * Copyright 2003 mjander | |
7 | * mjander@users.sourceforge.net | |
8 | * | |
9 | * A3D. You may think i'm crazy, but this may work someday. Who knows... | |
10 | ****************************************************************************/ | |
11 | ||
12 | /* | |
1da177e4 LT |
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 | |
25985edc | 44 | /* Atmospheric absorption. */ |
1da177e4 LT |
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 | { | |
ee419653 | 453 | /* |
e7e69265 | 454 | pr_debug( "vortex: ZeroState slice: %d, source %d\n", |
ee419653 TI |
455 | a->slice, a->source); |
456 | */ | |
1da177e4 LT |
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 */ | |
6a40dc5a | 475 | static void a3dsrc_ZeroStateA3D(a3dsrc_t *a, vortex_t *v) |
1da177e4 LT |
476 | { |
477 | int i, var, var2; | |
478 | ||
479 | if ((a->vortex) == NULL) { | |
70c84418 SM |
480 | dev_err(v->card->dev, |
481 | "ZeroStateA3D: ERROR: a->vortex is NULL\n"); | |
1da177e4 LT |
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 */ | |
e23e7a14 | 586 | static void vortex_Vort3D_enable(vortex_t *v) |
1da177e4 LT |
587 | { |
588 | int i; | |
f40b6890 TI |
589 | |
590 | Vort3DRend_Initialize(v, XT_HEADPHONE); | |
591 | for (i = 0; i < NR_A3D; i++) { | |
592 | vortex_A3dSourceHw_Initialize(v, i % 4, i >> 2); | |
6a40dc5a | 593 | a3dsrc_ZeroStateA3D(&v->a3d[0], v); |
1da177e4 LT |
594 | } |
595 | /* Register ALSA controls */ | |
f40b6890 TI |
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); | |
1da177e4 LT |
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) { | |
70c84418 SM |
620 | dev_warn(v->card->dev, |
621 | "vortex_Vort3D: ERROR: not enough free mixer resources.\n"); | |
1da177e4 LT |
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) { | |
70c84418 SM |
627 | dev_warn(v->card->dev, |
628 | "vortex_Vort3D: ERROR: not enough free mixer resources.\n"); | |
1da177e4 LT |
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. */ | |
6a40dc5a | 668 | static void vortex_Vort3D_InitializeSource(a3dsrc_t *a, int en, vortex_t *v) |
1da177e4 LT |
669 | { |
670 | if (a->vortex == NULL) { | |
70c84418 SM |
671 | dev_warn(v->card->dev, |
672 | "Vort3D_InitializeSource: A3D source not initialized\n"); | |
1da177e4 LT |
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 | |
2fd16874 | 717 | snd_vortex_a3d_hrtf_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
1da177e4 LT |
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 | |
2fd16874 | 726 | snd_vortex_a3d_itd_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
1da177e4 LT |
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 | |
2fd16874 | 735 | snd_vortex_a3d_ild_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
1da177e4 LT |
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 | |
2fd16874 TI |
744 | snd_vortex_a3d_filter_info(struct snd_kcontrol *kcontrol, |
745 | struct snd_ctl_elem_info *uinfo) | |
1da177e4 LT |
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 | |
2fd16874 | 755 | snd_vortex_a3d_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1da177e4 LT |
756 | { |
757 | //a3dsrc_t *a = kcontrol->private_data; | |
758 | /* No read yet. Would this be really useable/needed ? */ | |
759 | ||
760 | return 0; | |
761 | } | |
762 | ||
763 | static int | |
2fd16874 TI |
764 | snd_vortex_a3d_hrtf_put(struct snd_kcontrol *kcontrol, |
765 | struct snd_ctl_elem_value *ucontrol) | |
1da177e4 LT |
766 | { |
767 | a3dsrc_t *a = kcontrol->private_data; | |
5e19cad5 | 768 | int i; |
1da177e4 LT |
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]); | |
5e19cad5 | 777 | return 1; |
1da177e4 LT |
778 | } |
779 | ||
780 | static int | |
2fd16874 TI |
781 | snd_vortex_a3d_itd_put(struct snd_kcontrol *kcontrol, |
782 | struct snd_ctl_elem_value *ucontrol) | |
1da177e4 LT |
783 | { |
784 | a3dsrc_t *a = kcontrol->private_data; | |
785 | int coord[6]; | |
5e19cad5 | 786 | int i; |
1da177e4 LT |
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); | |
5e19cad5 | 796 | return 1; |
1da177e4 LT |
797 | } |
798 | ||
799 | static int | |
2fd16874 TI |
800 | snd_vortex_a3d_ild_put(struct snd_kcontrol *kcontrol, |
801 | struct snd_ctl_elem_value *ucontrol) | |
1da177e4 LT |
802 | { |
803 | a3dsrc_t *a = kcontrol->private_data; | |
1da177e4 LT |
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); | |
5e19cad5 | 812 | return 1; |
1da177e4 LT |
813 | } |
814 | ||
815 | static int | |
2fd16874 TI |
816 | snd_vortex_a3d_filter_put(struct snd_kcontrol *kcontrol, |
817 | struct snd_ctl_elem_value *ucontrol) | |
1da177e4 LT |
818 | { |
819 | a3dsrc_t *a = kcontrol->private_data; | |
5e19cad5 | 820 | int i; |
1da177e4 LT |
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); | |
25985edc | 826 | /* Atmospheric absorption and filtering. */ |
1da177e4 LT |
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]); | |
5e19cad5 | 833 | return 1; |
1da177e4 LT |
834 | } |
835 | ||
f3b827e0 | 836 | static const struct snd_kcontrol_new vortex_a3d_kcontrol = { |
1da177e4 LT |
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. */ | |
e23e7a14 | 846 | static int vortex_a3d_register_controls(vortex_t *vortex) |
1da177e4 | 847 | { |
2fd16874 | 848 | struct snd_kcontrol *kcontrol; |
1da177e4 LT |
849 | int err, i; |
850 | /* HRTF controls. */ | |
851 | for (i = 0; i < NR_A3D; i++) { | |
c2b0718f TI |
852 | kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]); |
853 | if (!kcontrol) | |
1da177e4 LT |
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; | |
c2b0718f TI |
858 | err = snd_ctl_add(vortex->card, kcontrol); |
859 | if (err < 0) | |
1da177e4 LT |
860 | return err; |
861 | } | |
862 | /* ITD controls. */ | |
863 | for (i = 0; i < NR_A3D; i++) { | |
c2b0718f TI |
864 | kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]); |
865 | if (!kcontrol) | |
1da177e4 LT |
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; | |
c2b0718f TI |
870 | err = snd_ctl_add(vortex->card, kcontrol); |
871 | if (err < 0) | |
1da177e4 LT |
872 | return err; |
873 | } | |
874 | /* ILD (gains) controls. */ | |
875 | for (i = 0; i < NR_A3D; i++) { | |
c2b0718f TI |
876 | kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]); |
877 | if (!kcontrol) | |
1da177e4 LT |
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; | |
c2b0718f TI |
882 | err = snd_ctl_add(vortex->card, kcontrol); |
883 | if (err < 0) | |
1da177e4 LT |
884 | return err; |
885 | } | |
886 | /* Filter controls. */ | |
887 | for (i = 0; i < NR_A3D; i++) { | |
c2b0718f TI |
888 | kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]); |
889 | if (!kcontrol) | |
1da177e4 LT |
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; | |
c2b0718f TI |
894 | err = snd_ctl_add(vortex->card, kcontrol); |
895 | if (err < 0) | |
1da177e4 LT |
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*/ |