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