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_core.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_core.c')
-rw-r--r-- | sound/pci/au88x0/au88x0_core.c | 2837 |
1 files changed, 2837 insertions, 0 deletions
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c new file mode 100644 index 000000000000..f0eda4bbbb39 --- /dev/null +++ b/sound/pci/au88x0/au88x0_core.c | |||
@@ -0,0 +1,2837 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License as published by | ||
4 | * the Free Software Foundation; either version 2 of the License, or | ||
5 | * (at your option) any later version. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU Library General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
15 | */ | ||
16 | |||
17 | /* | ||
18 | Vortex core low level functions. | ||
19 | |||
20 | Author: Manuel Jander (mjander@users.sourceforge.cl) | ||
21 | These functions are mainly the result of translations made | ||
22 | from the original disassembly of the au88x0 binary drivers, | ||
23 | written by Aureal before they went down. | ||
24 | Many thanks to the Jeff Muizelaar, Kester Maddock, and whoever | ||
25 | contributed to the OpenVortex project. | ||
26 | The author of this file, put the few available pieces together | ||
27 | and translated the rest of the riddle (Mix, Src and connection stuff). | ||
28 | Some things are still to be discovered, and their meanings are unclear. | ||
29 | |||
30 | Some of these functions aren't intended to be really used, rather | ||
31 | to help to understand how does the AU88X0 chips work. Keep them in, because | ||
32 | they could be used somewhere in the future. | ||
33 | |||
34 | This code hasn't been tested or proof read thoroughly. If you wanna help, | ||
35 | take a look at the AU88X0 assembly and check if this matches. | ||
36 | Functions tested ok so far are (they show the desired effect | ||
37 | at least): | ||
38 | vortex_routes(); (1 bug fixed). | ||
39 | vortex_adb_addroute(); | ||
40 | vortex_adb_addroutes(); | ||
41 | vortex_connect_codecplay(); | ||
42 | vortex_src_flushbuffers(); | ||
43 | vortex_adbdma_setmode(); note: still some unknown arguments! | ||
44 | vortex_adbdma_startfifo(); | ||
45 | vortex_adbdma_stopfifo(); | ||
46 | vortex_fifo_setadbctrl(); note: still some unknown arguments! | ||
47 | vortex_mix_setinputvolumebyte(); | ||
48 | vortex_mix_enableinput(); | ||
49 | vortex_mixer_addWTD(); (fixed) | ||
50 | vortex_connection_adbdma_src_src(); | ||
51 | vortex_connection_adbdma_src(); | ||
52 | vortex_src_change_convratio(); | ||
53 | vortex_src_addWTD(); (fixed) | ||
54 | |||
55 | History: | ||
56 | |||
57 | 01-03-2003 First revision. | ||
58 | 01-21-2003 Some bug fixes. | ||
59 | 17-02-2003 many bugfixes after a big versioning mess. | ||
60 | 18-02-2003 JAAAAAHHHUUUUUU!!!! The mixer works !! I'm just so happy ! | ||
61 | (2 hours later...) I cant believe it! Im really lucky today. | ||
62 | Now the SRC is working too! Yeah! XMMS works ! | ||
63 | 20-02-2003 First steps into the ALSA world. | ||
64 | 28-02-2003 As my birthday present, i discovered how the DMA buffer pages really | ||
65 | work :-). It was all wrong. | ||
66 | 12-03-2003 ALSA driver starts working (2 channels). | ||
67 | 16-03-2003 More srcblock_setupchannel discoveries. | ||
68 | 12-04-2003 AU8830 playback support. Recording in the works. | ||
69 | 17-04-2003 vortex_route() and vortex_routes() bug fixes. AU8830 recording | ||
70 | works now, but chipn' dale effect is still there. | ||
71 | 16-05-2003 SrcSetupChannel cleanup. Moved the Src setup stuff entirely | ||
72 | into au88x0_pcm.c . | ||
73 | 06-06-2003 Buffer shifter bugfix. Mixer volume fix. | ||
74 | 07-12-2003 A3D routing finally fixed. Believed to be OK. | ||
75 | 25-03-2004 Many thanks to Claudia, for such valuable bug reports. | ||
76 | |||
77 | */ | ||
78 | |||
79 | #include "au88x0.h" | ||
80 | #include "au88x0_a3d.h" | ||
81 | #include <linux/delay.h> | ||
82 | |||
83 | /* MIXER (CAsp4Mix.s and CAsp4Mixer.s) */ | ||
84 | |||
85 | // FIXME: get rid of this. | ||
86 | static int mchannels[NR_MIXIN]; | ||
87 | static int rampchs[NR_MIXIN]; | ||
88 | |||
89 | static void vortex_mixer_en_sr(vortex_t * vortex, int channel) | ||
90 | { | ||
91 | hwwrite(vortex->mmio, VORTEX_MIXER_SR, | ||
92 | hwread(vortex->mmio, VORTEX_MIXER_SR) | (0x1 << channel)); | ||
93 | } | ||
94 | static void vortex_mixer_dis_sr(vortex_t * vortex, int channel) | ||
95 | { | ||
96 | hwwrite(vortex->mmio, VORTEX_MIXER_SR, | ||
97 | hwread(vortex->mmio, VORTEX_MIXER_SR) & ~(0x1 << channel)); | ||
98 | } | ||
99 | |||
100 | #if 0 | ||
101 | static void | ||
102 | vortex_mix_muteinputgain(vortex_t * vortex, unsigned char mix, | ||
103 | unsigned char channel) | ||
104 | { | ||
105 | hwwrite(vortex->mmio, VORTEX_MIX_INVOL_A + ((mix << 5) + channel), | ||
106 | 0x80); | ||
107 | hwwrite(vortex->mmio, VORTEX_MIX_INVOL_B + ((mix << 5) + channel), | ||
108 | 0x80); | ||
109 | } | ||
110 | |||
111 | static int vortex_mix_getvolume(vortex_t * vortex, unsigned char mix) | ||
112 | { | ||
113 | int a; | ||
114 | a = hwread(vortex->mmio, VORTEX_MIX_VOL_A + (mix << 2)) & 0xff; | ||
115 | //FP2LinearFrac(a); | ||
116 | return (a); | ||
117 | } | ||
118 | |||
119 | static int | ||
120 | vortex_mix_getinputvolume(vortex_t * vortex, unsigned char mix, | ||
121 | int channel, int *vol) | ||
122 | { | ||
123 | int a; | ||
124 | if (!(mchannels[mix] & (1 << channel))) | ||
125 | return 0; | ||
126 | a = hwread(vortex->mmio, | ||
127 | VORTEX_MIX_INVOL_A + (((mix << 5) + channel) << 2)); | ||
128 | /* | ||
129 | if (rampchs[mix] == 0) | ||
130 | a = FP2LinearFrac(a); | ||
131 | else | ||
132 | a = FP2LinearFracWT(a); | ||
133 | */ | ||
134 | *vol = a; | ||
135 | return (0); | ||
136 | } | ||
137 | |||
138 | static unsigned int vortex_mix_boost6db(unsigned char vol) | ||
139 | { | ||
140 | return (vol + 8); /* WOW! what a complex function! */ | ||
141 | } | ||
142 | |||
143 | static void vortex_mix_rampvolume(vortex_t * vortex, int mix) | ||
144 | { | ||
145 | int ch; | ||
146 | char a; | ||
147 | // This function is intended for ramping down only (see vortex_disableinput()). | ||
148 | for (ch = 0; ch < 0x20; ch++) { | ||
149 | if (((1 << ch) & rampchs[mix]) == 0) | ||
150 | continue; | ||
151 | a = hwread(vortex->mmio, | ||
152 | VORTEX_MIX_INVOL_B + (((mix << 5) + ch) << 2)); | ||
153 | if (a > -126) { | ||
154 | a -= 2; | ||
155 | hwwrite(vortex->mmio, | ||
156 | VORTEX_MIX_INVOL_A + | ||
157 | (((mix << 5) + ch) << 2), a); | ||
158 | hwwrite(vortex->mmio, | ||
159 | VORTEX_MIX_INVOL_B + | ||
160 | (((mix << 5) + ch) << 2), a); | ||
161 | } else | ||
162 | vortex_mix_killinput(vortex, mix, ch); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | static int | ||
167 | vortex_mix_getenablebit(vortex_t * vortex, unsigned char mix, int mixin) | ||
168 | { | ||
169 | int addr, temp; | ||
170 | if (mixin >= 0) | ||
171 | addr = mixin; | ||
172 | else | ||
173 | addr = mixin + 3; | ||
174 | addr = ((mix << 3) + (addr >> 2)) << 2; | ||
175 | temp = hwread(vortex->mmio, VORTEX_MIX_ENIN + addr); | ||
176 | return ((temp >> (mixin & 3)) & 1); | ||
177 | } | ||
178 | #endif | ||
179 | static void | ||
180 | vortex_mix_setvolumebyte(vortex_t * vortex, unsigned char mix, | ||
181 | unsigned char vol) | ||
182 | { | ||
183 | int temp; | ||
184 | hwwrite(vortex->mmio, VORTEX_MIX_VOL_A + (mix << 2), vol); | ||
185 | if (1) { /*if (this_10) */ | ||
186 | temp = hwread(vortex->mmio, VORTEX_MIX_VOL_B + (mix << 2)); | ||
187 | if ((temp != 0x80) || (vol == 0x80)) | ||
188 | return; | ||
189 | } | ||
190 | hwwrite(vortex->mmio, VORTEX_MIX_VOL_B + (mix << 2), vol); | ||
191 | } | ||
192 | |||
193 | static void | ||
194 | vortex_mix_setinputvolumebyte(vortex_t * vortex, unsigned char mix, | ||
195 | int mixin, unsigned char vol) | ||
196 | { | ||
197 | int temp; | ||
198 | |||
199 | hwwrite(vortex->mmio, | ||
200 | VORTEX_MIX_INVOL_A + (((mix << 5) + mixin) << 2), vol); | ||
201 | if (1) { /* this_10, initialized to 1. */ | ||
202 | temp = | ||
203 | hwread(vortex->mmio, | ||
204 | VORTEX_MIX_INVOL_B + (((mix << 5) + mixin) << 2)); | ||
205 | if ((temp != 0x80) || (vol == 0x80)) | ||
206 | return; | ||
207 | } | ||
208 | hwwrite(vortex->mmio, | ||
209 | VORTEX_MIX_INVOL_B + (((mix << 5) + mixin) << 2), vol); | ||
210 | } | ||
211 | |||
212 | static void | ||
213 | vortex_mix_setenablebit(vortex_t * vortex, unsigned char mix, int mixin, int en) | ||
214 | { | ||
215 | int temp, addr; | ||
216 | |||
217 | if (mixin < 0) | ||
218 | addr = (mixin + 3); | ||
219 | else | ||
220 | addr = mixin; | ||
221 | addr = ((mix << 3) + (addr >> 2)) << 2; | ||
222 | temp = hwread(vortex->mmio, VORTEX_MIX_ENIN + addr); | ||
223 | if (en) | ||
224 | temp |= (1 << (mixin & 3)); | ||
225 | else | ||
226 | temp &= ~(1 << (mixin & 3)); | ||
227 | /* Mute input. Astatic void crackling? */ | ||
228 | hwwrite(vortex->mmio, | ||
229 | VORTEX_MIX_INVOL_B + (((mix << 5) + mixin) << 2), 0x80); | ||
230 | /* Looks like clear buffer. */ | ||
231 | hwwrite(vortex->mmio, VORTEX_MIX_SMP + (mixin << 2), 0x0); | ||
232 | hwwrite(vortex->mmio, VORTEX_MIX_SMP + 4 + (mixin << 2), 0x0); | ||
233 | /* Write enable bit. */ | ||
234 | hwwrite(vortex->mmio, VORTEX_MIX_ENIN + addr, temp); | ||
235 | } | ||
236 | |||
237 | static void | ||
238 | vortex_mix_killinput(vortex_t * vortex, unsigned char mix, int mixin) | ||
239 | { | ||
240 | rampchs[mix] &= ~(1 << mixin); | ||
241 | vortex_mix_setinputvolumebyte(vortex, mix, mixin, 0x80); | ||
242 | mchannels[mix] &= ~(1 << mixin); | ||
243 | vortex_mix_setenablebit(vortex, mix, mixin, 0); | ||
244 | } | ||
245 | |||
246 | static void | ||
247 | vortex_mix_enableinput(vortex_t * vortex, unsigned char mix, int mixin) | ||
248 | { | ||
249 | vortex_mix_killinput(vortex, mix, mixin); | ||
250 | if ((mchannels[mix] & (1 << mixin)) == 0) { | ||
251 | vortex_mix_setinputvolumebyte(vortex, mix, mixin, 0x80); /*0x80 : mute */ | ||
252 | mchannels[mix] |= (1 << mixin); | ||
253 | } | ||
254 | vortex_mix_setenablebit(vortex, mix, mixin, 1); | ||
255 | } | ||
256 | |||
257 | static void | ||
258 | vortex_mix_disableinput(vortex_t * vortex, unsigned char mix, int channel, | ||
259 | int ramp) | ||
260 | { | ||
261 | if (ramp) { | ||
262 | rampchs[mix] |= (1 << channel); | ||
263 | // Register callback. | ||
264 | //vortex_mix_startrampvolume(vortex); | ||
265 | vortex_mix_killinput(vortex, mix, channel); | ||
266 | } else | ||
267 | vortex_mix_killinput(vortex, mix, channel); | ||
268 | } | ||
269 | |||
270 | static int | ||
271 | vortex_mixer_addWTD(vortex_t * vortex, unsigned char mix, unsigned char ch) | ||
272 | { | ||
273 | int temp, lifeboat = 0, prev; | ||
274 | |||
275 | temp = hwread(vortex->mmio, VORTEX_MIXER_SR); | ||
276 | if ((temp & (1 << ch)) == 0) { | ||
277 | hwwrite(vortex->mmio, VORTEX_MIXER_CHNBASE + (ch << 2), mix); | ||
278 | vortex_mixer_en_sr(vortex, ch); | ||
279 | return 1; | ||
280 | } | ||
281 | prev = VORTEX_MIXER_CHNBASE + (ch << 2); | ||
282 | temp = hwread(vortex->mmio, prev); | ||
283 | while (temp & 0x10) { | ||
284 | prev = VORTEX_MIXER_RTBASE + ((temp & 0xf) << 2); | ||
285 | temp = hwread(vortex->mmio, prev); | ||
286 | //printk(KERN_INFO "vortex: mixAddWTD: while addr=%x, val=%x\n", prev, temp); | ||
287 | if ((++lifeboat) > 0xf) { | ||
288 | printk(KERN_ERR | ||
289 | "vortex_mixer_addWTD: lifeboat overflow\n"); | ||
290 | return 0; | ||
291 | } | ||
292 | } | ||
293 | hwwrite(vortex->mmio, VORTEX_MIXER_RTBASE + ((temp & 0xf) << 2), mix); | ||
294 | hwwrite(vortex->mmio, prev, (temp & 0xf) | 0x10); | ||
295 | return 1; | ||
296 | } | ||
297 | |||
298 | static int | ||
299 | vortex_mixer_delWTD(vortex_t * vortex, unsigned char mix, unsigned char ch) | ||
300 | { | ||
301 | int esp14 = -1, esp18, eax, ebx, edx, ebp, esi = 0; | ||
302 | //int esp1f=edi(while)=src, esp10=ch; | ||
303 | |||
304 | eax = hwread(vortex->mmio, VORTEX_MIXER_SR); | ||
305 | if (((1 << ch) & eax) == 0) { | ||
306 | printk(KERN_ERR "mix ALARM %x\n", eax); | ||
307 | return 0; | ||
308 | } | ||
309 | ebp = VORTEX_MIXER_CHNBASE + (ch << 2); | ||
310 | esp18 = hwread(vortex->mmio, ebp); | ||
311 | if (esp18 & 0x10) { | ||
312 | ebx = (esp18 & 0xf); | ||
313 | if (mix == ebx) { | ||
314 | ebx = VORTEX_MIXER_RTBASE + (mix << 2); | ||
315 | edx = hwread(vortex->mmio, ebx); | ||
316 | //7b60 | ||
317 | hwwrite(vortex->mmio, ebp, edx); | ||
318 | hwwrite(vortex->mmio, ebx, 0); | ||
319 | } else { | ||
320 | //7ad3 | ||
321 | edx = | ||
322 | hwread(vortex->mmio, | ||
323 | VORTEX_MIXER_RTBASE + (ebx << 2)); | ||
324 | //printk(KERN_INFO "vortex: mixdelWTD: 1 addr=%x, val=%x, src=%x\n", ebx, edx, src); | ||
325 | while ((edx & 0xf) != mix) { | ||
326 | if ((esi) > 0xf) { | ||
327 | printk(KERN_ERR | ||
328 | "vortex: mixdelWTD: error lifeboat overflow\n"); | ||
329 | return 0; | ||
330 | } | ||
331 | esp14 = ebx; | ||
332 | ebx = edx & 0xf; | ||
333 | ebp = ebx << 2; | ||
334 | edx = | ||
335 | hwread(vortex->mmio, | ||
336 | VORTEX_MIXER_RTBASE + ebp); | ||
337 | //printk(KERN_INFO "vortex: mixdelWTD: while addr=%x, val=%x\n", ebp, edx); | ||
338 | esi++; | ||
339 | } | ||
340 | //7b30 | ||
341 | ebp = ebx << 2; | ||
342 | if (edx & 0x10) { /* Delete entry in between others */ | ||
343 | ebx = VORTEX_MIXER_RTBASE + ((edx & 0xf) << 2); | ||
344 | edx = hwread(vortex->mmio, ebx); | ||
345 | //7b60 | ||
346 | hwwrite(vortex->mmio, | ||
347 | VORTEX_MIXER_RTBASE + ebp, edx); | ||
348 | hwwrite(vortex->mmio, ebx, 0); | ||
349 | //printk(KERN_INFO "vortex mixdelWTD between addr= 0x%x, val= 0x%x\n", ebp, edx); | ||
350 | } else { /* Delete last entry */ | ||
351 | //7b83 | ||
352 | if (esp14 == -1) | ||
353 | hwwrite(vortex->mmio, | ||
354 | VORTEX_MIXER_CHNBASE + | ||
355 | (ch << 2), esp18 & 0xef); | ||
356 | else { | ||
357 | ebx = (0xffffffe0 & edx) | (0xf & ebx); | ||
358 | hwwrite(vortex->mmio, | ||
359 | VORTEX_MIXER_RTBASE + | ||
360 | (esp14 << 2), ebx); | ||
361 | //printk(KERN_INFO "vortex mixdelWTD last addr= 0x%x, val= 0x%x\n", esp14, ebx); | ||
362 | } | ||
363 | hwwrite(vortex->mmio, | ||
364 | VORTEX_MIXER_RTBASE + ebp, 0); | ||
365 | return 1; | ||
366 | } | ||
367 | } | ||
368 | } else { | ||
369 | //printk(KERN_INFO "removed last mix\n"); | ||
370 | //7be0 | ||
371 | vortex_mixer_dis_sr(vortex, ch); | ||
372 | hwwrite(vortex->mmio, ebp, 0); | ||
373 | } | ||
374 | return 1; | ||
375 | } | ||
376 | |||
377 | static void vortex_mixer_init(vortex_t * vortex) | ||
378 | { | ||
379 | unsigned long addr; | ||
380 | int x; | ||
381 | |||
382 | // FIXME: get rid of this crap. | ||
383 | memset(mchannels, 0, NR_MIXOUT * sizeof(int)); | ||
384 | memset(rampchs, 0, NR_MIXOUT * sizeof(int)); | ||
385 | |||
386 | addr = VORTEX_MIX_SMP + 0x17c; | ||
387 | for (x = 0x5f; x >= 0; x--) { | ||
388 | hwwrite(vortex->mmio, addr, 0); | ||
389 | addr -= 4; | ||
390 | } | ||
391 | addr = VORTEX_MIX_ENIN + 0x1fc; | ||
392 | for (x = 0x7f; x >= 0; x--) { | ||
393 | hwwrite(vortex->mmio, addr, 0); | ||
394 | addr -= 4; | ||
395 | } | ||
396 | addr = VORTEX_MIX_SMP + 0x17c; | ||
397 | for (x = 0x5f; x >= 0; x--) { | ||
398 | hwwrite(vortex->mmio, addr, 0); | ||
399 | addr -= 4; | ||
400 | } | ||
401 | addr = VORTEX_MIX_INVOL_A + 0x7fc; | ||
402 | for (x = 0x1ff; x >= 0; x--) { | ||
403 | hwwrite(vortex->mmio, addr, 0x80); | ||
404 | addr -= 4; | ||
405 | } | ||
406 | addr = VORTEX_MIX_VOL_A + 0x3c; | ||
407 | for (x = 0xf; x >= 0; x--) { | ||
408 | hwwrite(vortex->mmio, addr, 0x80); | ||
409 | addr -= 4; | ||
410 | } | ||
411 | addr = VORTEX_MIX_INVOL_B + 0x7fc; | ||
412 | for (x = 0x1ff; x >= 0; x--) { | ||
413 | hwwrite(vortex->mmio, addr, 0x80); | ||
414 | addr -= 4; | ||
415 | } | ||
416 | addr = VORTEX_MIX_VOL_B + 0x3c; | ||
417 | for (x = 0xf; x >= 0; x--) { | ||
418 | hwwrite(vortex->mmio, addr, 0x80); | ||
419 | addr -= 4; | ||
420 | } | ||
421 | addr = VORTEX_MIXER_RTBASE + (MIXER_RTBASE_SIZE - 1) * 4; | ||
422 | for (x = (MIXER_RTBASE_SIZE - 1); x >= 0; x--) { | ||
423 | hwwrite(vortex->mmio, addr, 0x0); | ||
424 | addr -= 4; | ||
425 | } | ||
426 | hwwrite(vortex->mmio, VORTEX_MIXER_SR, 0); | ||
427 | |||
428 | /* Set clipping ceiling (this may be all wrong). */ | ||
429 | /* | ||
430 | for (x = 0; x > 0x80; x++) { | ||
431 | hwwrite(vortex->mmio, VORTEX_MIXER_CLIP + (x << 2), 0x3ffff); | ||
432 | } | ||
433 | */ | ||
434 | /* | ||
435 | call CAsp4Mix__Initialize_CAsp4HwIO____CAsp4Mixer____ | ||
436 | Register ISR callback for volume smooth fade out. | ||
437 | Maybe this avoids clicks when press "stop" ? | ||
438 | */ | ||
439 | } | ||
440 | |||
441 | /* SRC (CAsp4Src.s and CAsp4SrcBlock) */ | ||
442 | |||
443 | static void vortex_src_en_sr(vortex_t * vortex, int channel) | ||
444 | { | ||
445 | hwwrite(vortex->mmio, VORTEX_SRCBLOCK_SR, | ||
446 | hwread(vortex->mmio, VORTEX_SRCBLOCK_SR) | (0x1 << channel)); | ||
447 | } | ||
448 | |||
449 | static void vortex_src_dis_sr(vortex_t * vortex, int channel) | ||
450 | { | ||
451 | hwwrite(vortex->mmio, VORTEX_SRCBLOCK_SR, | ||
452 | hwread(vortex->mmio, VORTEX_SRCBLOCK_SR) & ~(0x1 << channel)); | ||
453 | } | ||
454 | |||
455 | static void vortex_src_flushbuffers(vortex_t * vortex, unsigned char src) | ||
456 | { | ||
457 | int i; | ||
458 | |||
459 | for (i = 0x1f; i >= 0; i--) | ||
460 | hwwrite(vortex->mmio, | ||
461 | VORTEX_SRC_DATA0 + (src << 7) + (i << 2), 0); | ||
462 | hwwrite(vortex->mmio, VORTEX_SRC_DATA + (src << 3), 0); | ||
463 | hwwrite(vortex->mmio, VORTEX_SRC_DATA + (src << 3) + 4, 0); | ||
464 | } | ||
465 | |||
466 | static void vortex_src_cleardrift(vortex_t * vortex, unsigned char src) | ||
467 | { | ||
468 | hwwrite(vortex->mmio, VORTEX_SRC_DRIFT0 + (src << 2), 0); | ||
469 | hwwrite(vortex->mmio, VORTEX_SRC_DRIFT1 + (src << 2), 0); | ||
470 | hwwrite(vortex->mmio, VORTEX_SRC_DRIFT2 + (src << 2), 1); | ||
471 | } | ||
472 | |||
473 | static void | ||
474 | vortex_src_set_throttlesource(vortex_t * vortex, unsigned char src, int en) | ||
475 | { | ||
476 | int temp; | ||
477 | |||
478 | temp = hwread(vortex->mmio, VORTEX_SRC_SOURCE); | ||
479 | if (en) | ||
480 | temp |= 1 << src; | ||
481 | else | ||
482 | temp &= ~(1 << src); | ||
483 | hwwrite(vortex->mmio, VORTEX_SRC_SOURCE, temp); | ||
484 | } | ||
485 | |||
486 | static int | ||
487 | vortex_src_persist_convratio(vortex_t * vortex, unsigned char src, int ratio) | ||
488 | { | ||
489 | int temp, lifeboat = 0; | ||
490 | |||
491 | do { | ||
492 | hwwrite(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2), ratio); | ||
493 | temp = hwread(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2)); | ||
494 | if ((++lifeboat) > 0x9) { | ||
495 | printk(KERN_ERR "Vortex: Src cvr fail\n"); | ||
496 | break; | ||
497 | } | ||
498 | } | ||
499 | while (temp != ratio); | ||
500 | return temp; | ||
501 | } | ||
502 | |||
503 | #if 0 | ||
504 | static void vortex_src_slowlock(vortex_t * vortex, unsigned char src) | ||
505 | { | ||
506 | int temp; | ||
507 | |||
508 | hwwrite(vortex->mmio, VORTEX_SRC_DRIFT2 + (src << 2), 1); | ||
509 | hwwrite(vortex->mmio, VORTEX_SRC_DRIFT0 + (src << 2), 0); | ||
510 | temp = hwread(vortex->mmio, VORTEX_SRC_U0 + (src << 2)); | ||
511 | if (temp & 0x200) | ||
512 | hwwrite(vortex->mmio, VORTEX_SRC_U0 + (src << 2), | ||
513 | temp & ~0x200L); | ||
514 | } | ||
515 | |||
516 | static void | ||
517 | vortex_src_change_convratio(vortex_t * vortex, unsigned char src, int ratio) | ||
518 | { | ||
519 | int temp, a; | ||
520 | |||
521 | if ((ratio & 0x10000) && (ratio != 0x10000)) { | ||
522 | if (ratio & 0x3fff) | ||
523 | a = (0x11 - ((ratio >> 0xe) & 0x3)) - 1; | ||
524 | else | ||
525 | a = (0x11 - ((ratio >> 0xe) & 0x3)) - 2; | ||
526 | } else | ||
527 | a = 0xc; | ||
528 | temp = hwread(vortex->mmio, VORTEX_SRC_U0 + (src << 2)); | ||
529 | if (((temp >> 4) & 0xf) != a) | ||
530 | hwwrite(vortex->mmio, VORTEX_SRC_U0 + (src << 2), | ||
531 | (temp & 0xf) | ((a & 0xf) << 4)); | ||
532 | |||
533 | vortex_src_persist_convratio(vortex, src, ratio); | ||
534 | } | ||
535 | |||
536 | static int | ||
537 | vortex_src_checkratio(vortex_t * vortex, unsigned char src, | ||
538 | unsigned int desired_ratio) | ||
539 | { | ||
540 | int hw_ratio, lifeboat = 0; | ||
541 | |||
542 | hw_ratio = hwread(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2)); | ||
543 | |||
544 | while (hw_ratio != desired_ratio) { | ||
545 | hwwrite(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2), desired_ratio); | ||
546 | |||
547 | if ((lifeboat++) > 15) { | ||
548 | printk(KERN_ERR "Vortex: could not set src-%d from %d to %d\n", | ||
549 | src, hw_ratio, desired_ratio); | ||
550 | break; | ||
551 | } | ||
552 | } | ||
553 | |||
554 | return hw_ratio; | ||
555 | } | ||
556 | |||
557 | #endif | ||
558 | /* | ||
559 | Objective: Set samplerate for given SRC module. | ||
560 | Arguments: | ||
561 | card: pointer to vortex_t strcut. | ||
562 | src: Integer index of the SRC module. | ||
563 | cr: Current sample rate conversion factor. | ||
564 | b: unknown 16 bit value. | ||
565 | sweep: Enable Samplerate fade from cr toward tr flag. | ||
566 | dirplay: 1: playback, 0: recording. | ||
567 | sl: Slow Lock flag. | ||
568 | tr: Target samplerate conversion. | ||
569 | thsource: Throttle source flag (no idea what that means). | ||
570 | */ | ||
571 | static void vortex_src_setupchannel(vortex_t * card, unsigned char src, | ||
572 | unsigned int cr, unsigned int b, int sweep, int d, | ||
573 | int dirplay, int sl, unsigned int tr, int thsource) | ||
574 | { | ||
575 | // noplayback: d=2,4,7,0xa,0xb when using first 2 src's. | ||
576 | // c: enables pitch sweep. | ||
577 | // looks like g is c related. Maybe g is a sweep parameter ? | ||
578 | // g = cvr | ||
579 | // dirplay: 0 = recording, 1 = playback | ||
580 | // d = src hw index. | ||
581 | |||
582 | int esi, ebp = 0, esp10; | ||
583 | |||
584 | vortex_src_flushbuffers(card, src); | ||
585 | |||
586 | if (sweep) { | ||
587 | if ((tr & 0x10000) && (tr != 0x10000)) { | ||
588 | tr = 0; | ||
589 | esi = 0x7; | ||
590 | } else { | ||
591 | if ((((short)tr) < 0) && (tr != 0x8000)) { | ||
592 | tr = 0; | ||
593 | esi = 0x8; | ||
594 | } else { | ||
595 | tr = 1; | ||
596 | esi = 0xc; | ||
597 | } | ||
598 | } | ||
599 | } else { | ||
600 | if ((cr & 0x10000) && (cr != 0x10000)) { | ||
601 | tr = 0; /*ebx = 0 */ | ||
602 | esi = 0x11 - ((cr >> 0xe) & 7); | ||
603 | if (cr & 0x3fff) | ||
604 | esi -= 1; | ||
605 | else | ||
606 | esi -= 2; | ||
607 | } else { | ||
608 | tr = 1; | ||
609 | esi = 0xc; | ||
610 | } | ||
611 | } | ||
612 | vortex_src_cleardrift(card, src); | ||
613 | vortex_src_set_throttlesource(card, src, thsource); | ||
614 | |||
615 | if ((dirplay == 0) && (sweep == 0)) { | ||
616 | if (tr) | ||
617 | esp10 = 0xf; | ||
618 | else | ||
619 | esp10 = 0xc; | ||
620 | ebp = 0; | ||
621 | } else { | ||
622 | if (tr) | ||
623 | ebp = 0xf; | ||
624 | else | ||
625 | ebp = 0xc; | ||
626 | esp10 = 0; | ||
627 | } | ||
628 | hwwrite(card->mmio, VORTEX_SRC_U0 + (src << 2), | ||
629 | (sl << 0x9) | (sweep << 0x8) | ((esi & 0xf) << 4) | d); | ||
630 | /* 0xc0 esi=0xc c=f=0 d=0 */ | ||
631 | vortex_src_persist_convratio(card, src, cr); | ||
632 | hwwrite(card->mmio, VORTEX_SRC_U1 + (src << 2), b & 0xffff); | ||
633 | /* 0 b=0 */ | ||
634 | hwwrite(card->mmio, VORTEX_SRC_U2 + (src << 2), | ||
635 | (tr << 0x11) | (dirplay << 0x10) | (ebp << 0x8) | esp10); | ||
636 | /* 0x30f00 e=g=1 esp10=0 ebp=f */ | ||
637 | //printk(KERN_INFO "vortex: SRC %d, d=0x%x, esi=0x%x, esp10=0x%x, ebp=0x%x\n", src, d, esi, esp10, ebp); | ||
638 | } | ||
639 | |||
640 | static void vortex_srcblock_init(vortex_t * vortex) | ||
641 | { | ||
642 | unsigned long addr; | ||
643 | int x; | ||
644 | hwwrite(vortex->mmio, VORTEX_SRC_SOURCESIZE, 0x1ff); | ||
645 | /* | ||
646 | for (x=0; x<0x10; x++) { | ||
647 | vortex_src_init(&vortex_src[x], x); | ||
648 | } | ||
649 | */ | ||
650 | //addr = 0xcc3c; | ||
651 | //addr = 0x26c3c; | ||
652 | addr = VORTEX_SRC_RTBASE + 0x3c; | ||
653 | for (x = 0xf; x >= 0; x--) { | ||
654 | hwwrite(vortex->mmio, addr, 0); | ||
655 | addr -= 4; | ||
656 | } | ||
657 | //addr = 0xcc94; | ||
658 | //addr = 0x26c94; | ||
659 | addr = VORTEX_SRC_CHNBASE + 0x54; | ||
660 | for (x = 0x15; x >= 0; x--) { | ||
661 | hwwrite(vortex->mmio, addr, 0); | ||
662 | addr -= 4; | ||
663 | } | ||
664 | } | ||
665 | |||
666 | static int | ||
667 | vortex_src_addWTD(vortex_t * vortex, unsigned char src, unsigned char ch) | ||
668 | { | ||
669 | int temp, lifeboat = 0, prev; | ||
670 | // esp13 = src | ||
671 | |||
672 | temp = hwread(vortex->mmio, VORTEX_SRCBLOCK_SR); | ||
673 | if ((temp & (1 << ch)) == 0) { | ||
674 | hwwrite(vortex->mmio, VORTEX_SRC_CHNBASE + (ch << 2), src); | ||
675 | vortex_src_en_sr(vortex, ch); | ||
676 | return 1; | ||
677 | } | ||
678 | prev = VORTEX_SRC_CHNBASE + (ch << 2); /*ebp */ | ||
679 | temp = hwread(vortex->mmio, prev); | ||
680 | //while (temp & NR_SRC) { | ||
681 | while (temp & 0x10) { | ||
682 | prev = VORTEX_SRC_RTBASE + ((temp & 0xf) << 2); /*esp12 */ | ||
683 | //prev = VORTEX_SRC_RTBASE + ((temp & (NR_SRC-1)) << 2); /*esp12*/ | ||
684 | temp = hwread(vortex->mmio, prev); | ||
685 | //printk(KERN_INFO "vortex: srcAddWTD: while addr=%x, val=%x\n", prev, temp); | ||
686 | if ((++lifeboat) > 0xf) { | ||
687 | printk(KERN_ERR | ||
688 | "vortex_src_addWTD: lifeboat overflow\n"); | ||
689 | return 0; | ||
690 | } | ||
691 | } | ||
692 | hwwrite(vortex->mmio, VORTEX_SRC_RTBASE + ((temp & 0xf) << 2), src); | ||
693 | //hwwrite(vortex->mmio, prev, (temp & (NR_SRC-1)) | NR_SRC); | ||
694 | hwwrite(vortex->mmio, prev, (temp & 0xf) | 0x10); | ||
695 | return 1; | ||
696 | } | ||
697 | |||
698 | static int | ||
699 | vortex_src_delWTD(vortex_t * vortex, unsigned char src, unsigned char ch) | ||
700 | { | ||
701 | int esp14 = -1, esp18, eax, ebx, edx, ebp, esi = 0; | ||
702 | //int esp1f=edi(while)=src, esp10=ch; | ||
703 | |||
704 | eax = hwread(vortex->mmio, VORTEX_SRCBLOCK_SR); | ||
705 | if (((1 << ch) & eax) == 0) { | ||
706 | printk(KERN_ERR "src alarm\n"); | ||
707 | return 0; | ||
708 | } | ||
709 | ebp = VORTEX_SRC_CHNBASE + (ch << 2); | ||
710 | esp18 = hwread(vortex->mmio, ebp); | ||
711 | if (esp18 & 0x10) { | ||
712 | ebx = (esp18 & 0xf); | ||
713 | if (src == ebx) { | ||
714 | ebx = VORTEX_SRC_RTBASE + (src << 2); | ||
715 | edx = hwread(vortex->mmio, ebx); | ||
716 | //7b60 | ||
717 | hwwrite(vortex->mmio, ebp, edx); | ||
718 | hwwrite(vortex->mmio, ebx, 0); | ||
719 | } else { | ||
720 | //7ad3 | ||
721 | edx = | ||
722 | hwread(vortex->mmio, | ||
723 | VORTEX_SRC_RTBASE + (ebx << 2)); | ||
724 | //printk(KERN_INFO "vortex: srcdelWTD: 1 addr=%x, val=%x, src=%x\n", ebx, edx, src); | ||
725 | while ((edx & 0xf) != src) { | ||
726 | if ((esi) > 0xf) { | ||
727 | printk | ||
728 | ("vortex: srcdelWTD: error, lifeboat overflow\n"); | ||
729 | return 0; | ||
730 | } | ||
731 | esp14 = ebx; | ||
732 | ebx = edx & 0xf; | ||
733 | ebp = ebx << 2; | ||
734 | edx = | ||
735 | hwread(vortex->mmio, | ||
736 | VORTEX_SRC_RTBASE + ebp); | ||
737 | //printk(KERN_INFO "vortex: srcdelWTD: while addr=%x, val=%x\n", ebp, edx); | ||
738 | esi++; | ||
739 | } | ||
740 | //7b30 | ||
741 | ebp = ebx << 2; | ||
742 | if (edx & 0x10) { /* Delete entry in between others */ | ||
743 | ebx = VORTEX_SRC_RTBASE + ((edx & 0xf) << 2); | ||
744 | edx = hwread(vortex->mmio, ebx); | ||
745 | //7b60 | ||
746 | hwwrite(vortex->mmio, | ||
747 | VORTEX_SRC_RTBASE + ebp, edx); | ||
748 | hwwrite(vortex->mmio, ebx, 0); | ||
749 | //printk(KERN_INFO "vortex srcdelWTD between addr= 0x%x, val= 0x%x\n", ebp, edx); | ||
750 | } else { /* Delete last entry */ | ||
751 | //7b83 | ||
752 | if (esp14 == -1) | ||
753 | hwwrite(vortex->mmio, | ||
754 | VORTEX_SRC_CHNBASE + | ||
755 | (ch << 2), esp18 & 0xef); | ||
756 | else { | ||
757 | ebx = (0xffffffe0 & edx) | (0xf & ebx); | ||
758 | hwwrite(vortex->mmio, | ||
759 | VORTEX_SRC_RTBASE + | ||
760 | (esp14 << 2), ebx); | ||
761 | //printk(KERN_INFO"vortex srcdelWTD last addr= 0x%x, val= 0x%x\n", esp14, ebx); | ||
762 | } | ||
763 | hwwrite(vortex->mmio, | ||
764 | VORTEX_SRC_RTBASE + ebp, 0); | ||
765 | return 1; | ||
766 | } | ||
767 | } | ||
768 | } else { | ||
769 | //7be0 | ||
770 | vortex_src_dis_sr(vortex, ch); | ||
771 | hwwrite(vortex->mmio, ebp, 0); | ||
772 | } | ||
773 | return 1; | ||
774 | } | ||
775 | |||
776 | /*FIFO*/ | ||
777 | |||
778 | static void | ||
779 | vortex_fifo_clearadbdata(vortex_t * vortex, int fifo, int x) | ||
780 | { | ||
781 | for (x--; x >= 0; x--) | ||
782 | hwwrite(vortex->mmio, | ||
783 | VORTEX_FIFO_ADBDATA + | ||
784 | (((fifo << FIFO_SIZE_BITS) + x) << 2), 0); | ||
785 | } | ||
786 | |||
787 | #if 0 | ||
788 | static void vortex_fifo_adbinitialize(vortex_t * vortex, int fifo, int j) | ||
789 | { | ||
790 | vortex_fifo_clearadbdata(vortex, fifo, FIFO_SIZE); | ||
791 | #ifdef CHIP_AU8820 | ||
792 | hwwrite(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2), | ||
793 | (FIFO_U1 | ((j & FIFO_MASK) << 0xb))); | ||
794 | #else | ||
795 | hwwrite(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2), | ||
796 | (FIFO_U1 | ((j & FIFO_MASK) << 0xc))); | ||
797 | #endif | ||
798 | } | ||
799 | #endif | ||
800 | static void vortex_fifo_setadbvalid(vortex_t * vortex, int fifo, int en) | ||
801 | { | ||
802 | hwwrite(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2), | ||
803 | (hwread(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2)) & | ||
804 | 0xffffffef) | ((1 & en) << 4) | FIFO_U1); | ||
805 | } | ||
806 | |||
807 | static void | ||
808 | vortex_fifo_setadbctrl(vortex_t * vortex, int fifo, int b, int priority, | ||
809 | int empty, int valid, int f) | ||
810 | { | ||
811 | int temp, lifeboat = 0; | ||
812 | //int this_8[NR_ADB] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* position */ | ||
813 | int this_4 = 0x2; | ||
814 | /* f seems priority related. | ||
815 | * CAsp4AdbDma::SetPriority is the only place that calls SetAdbCtrl with f set to 1 | ||
816 | * every where else it is set to 0. It seems, however, that CAsp4AdbDma::SetPriority | ||
817 | * is never called, thus the f related bits remain a mystery for now. | ||
818 | */ | ||
819 | do { | ||
820 | temp = hwread(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2)); | ||
821 | if (lifeboat++ > 0xbb8) { | ||
822 | printk(KERN_ERR | ||
823 | "Vortex: vortex_fifo_setadbctrl fail\n"); | ||
824 | break; | ||
825 | } | ||
826 | } | ||
827 | while (temp & FIFO_RDONLY); | ||
828 | |||
829 | // AU8830 semes to take some special care about fifo content (data). | ||
830 | // But i'm just to lazy to translate that :) | ||
831 | if (valid) { | ||
832 | if ((temp & FIFO_VALID) == 0) { | ||
833 | //this_8[fifo] = 0; | ||
834 | vortex_fifo_clearadbdata(vortex, fifo, FIFO_SIZE); // this_4 | ||
835 | #ifdef CHIP_AU8820 | ||
836 | temp = (this_4 & 0x1f) << 0xb; | ||
837 | #else | ||
838 | temp = (this_4 & 0x3f) << 0xc; | ||
839 | #endif | ||
840 | temp = (temp & 0xfffffffd) | ((b & 1) << 1); | ||
841 | temp = (temp & 0xfffffff3) | ((priority & 3) << 2); | ||
842 | temp = (temp & 0xffffffef) | ((valid & 1) << 4); | ||
843 | temp |= FIFO_U1; | ||
844 | temp = (temp & 0xffffffdf) | ((empty & 1) << 5); | ||
845 | #ifdef CHIP_AU8820 | ||
846 | temp = (temp & 0xfffbffff) | ((f & 1) << 0x12); | ||
847 | #endif | ||
848 | #ifdef CHIP_AU8830 | ||
849 | temp = (temp & 0xf7ffffff) | ((f & 1) << 0x1b); | ||
850 | temp = (temp & 0xefffffff) | ((f & 1) << 0x1c); | ||
851 | #endif | ||
852 | #ifdef CHIP_AU8810 | ||
853 | temp = (temp & 0xfeffffff) | ((f & 1) << 0x18); | ||
854 | temp = (temp & 0xfdffffff) | ((f & 1) << 0x19); | ||
855 | #endif | ||
856 | } | ||
857 | } else { | ||
858 | if (temp & FIFO_VALID) { | ||
859 | #ifdef CHIP_AU8820 | ||
860 | temp = ((f & 1) << 0x12) | (temp & 0xfffbffef); | ||
861 | #endif | ||
862 | #ifdef CHIP_AU8830 | ||
863 | temp = | ||
864 | ((f & 1) << 0x1b) | (temp & 0xe7ffffef) | FIFO_BITS; | ||
865 | #endif | ||
866 | #ifdef CHIP_AU8810 | ||
867 | temp = | ||
868 | ((f & 1) << 0x18) | (temp & 0xfcffffef) | FIFO_BITS; | ||
869 | #endif | ||
870 | } else | ||
871 | /*if (this_8[fifo]) */ | ||
872 | vortex_fifo_clearadbdata(vortex, fifo, FIFO_SIZE); | ||
873 | } | ||
874 | hwwrite(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2), temp); | ||
875 | hwread(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2)); | ||
876 | } | ||
877 | |||
878 | #ifndef CHIP_AU8810 | ||
879 | static void vortex_fifo_clearwtdata(vortex_t * vortex, int fifo, int x) | ||
880 | { | ||
881 | if (x < 1) | ||
882 | return; | ||
883 | for (x--; x >= 0; x--) | ||
884 | hwwrite(vortex->mmio, | ||
885 | VORTEX_FIFO_WTDATA + | ||
886 | (((fifo << FIFO_SIZE_BITS) + x) << 2), 0); | ||
887 | } | ||
888 | |||
889 | static void vortex_fifo_wtinitialize(vortex_t * vortex, int fifo, int j) | ||
890 | { | ||
891 | vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); | ||
892 | #ifdef CHIP_AU8820 | ||
893 | hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), | ||
894 | (FIFO_U1 | ((j & FIFO_MASK) << 0xb))); | ||
895 | #else | ||
896 | hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), | ||
897 | (FIFO_U1 | ((j & FIFO_MASK) << 0xc))); | ||
898 | #endif | ||
899 | } | ||
900 | |||
901 | static void vortex_fifo_setwtvalid(vortex_t * vortex, int fifo, int en) | ||
902 | { | ||
903 | hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), | ||
904 | (hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)) & | ||
905 | 0xffffffef) | ((en & 1) << 4) | FIFO_U1); | ||
906 | } | ||
907 | |||
908 | static void | ||
909 | vortex_fifo_setwtctrl(vortex_t * vortex, int fifo, int ctrl, int priority, | ||
910 | int empty, int valid, int f) | ||
911 | { | ||
912 | int temp = 0, lifeboat = 0; | ||
913 | int this_4 = 2; | ||
914 | |||
915 | do { | ||
916 | temp = hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)); | ||
917 | if (lifeboat++ > 0xbb8) { | ||
918 | printk(KERN_ERR "Vortex: vortex_fifo_setwtctrl fail\n"); | ||
919 | break; | ||
920 | } | ||
921 | } | ||
922 | while (temp & FIFO_RDONLY); | ||
923 | |||
924 | if (valid) { | ||
925 | if ((temp & FIFO_VALID) == 0) { | ||
926 | vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); // this_4 | ||
927 | #ifdef CHIP_AU8820 | ||
928 | temp = (this_4 & 0x1f) << 0xb; | ||
929 | #else | ||
930 | temp = (this_4 & 0x3f) << 0xc; | ||
931 | #endif | ||
932 | temp = (temp & 0xfffffffd) | ((ctrl & 1) << 1); | ||
933 | temp = (temp & 0xfffffff3) | ((priority & 3) << 2); | ||
934 | temp = (temp & 0xffffffef) | ((valid & 1) << 4); | ||
935 | temp |= FIFO_U1; | ||
936 | temp = (temp & 0xffffffdf) | ((empty & 1) << 5); | ||
937 | #ifdef CHIP_AU8820 | ||
938 | temp = (temp & 0xfffbffff) | ((f & 1) << 0x12); | ||
939 | #endif | ||
940 | #ifdef CHIP_AU8830 | ||
941 | temp = (temp & 0xf7ffffff) | ((f & 1) << 0x1b); | ||
942 | temp = (temp & 0xefffffff) | ((f & 1) << 0x1c); | ||
943 | #endif | ||
944 | #ifdef CHIP_AU8810 | ||
945 | temp = (temp & 0xfeffffff) | ((f & 1) << 0x18); | ||
946 | temp = (temp & 0xfdffffff) | ((f & 1) << 0x19); | ||
947 | #endif | ||
948 | } | ||
949 | } else { | ||
950 | if (temp & FIFO_VALID) { | ||
951 | #ifdef CHIP_AU8820 | ||
952 | temp = ((f & 1) << 0x12) | (temp & 0xfffbffef); | ||
953 | #endif | ||
954 | #ifdef CHIP_AU8830 | ||
955 | temp = | ||
956 | ((f & 1) << 0x1b) | (temp & 0xe7ffffef) | FIFO_BITS; | ||
957 | #endif | ||
958 | #ifdef CHIP_AU8810 | ||
959 | temp = | ||
960 | ((f & 1) << 0x18) | (temp & 0xfcffffef) | FIFO_BITS; | ||
961 | #endif | ||
962 | } else | ||
963 | /*if (this_8[fifo]) */ | ||
964 | vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); | ||
965 | } | ||
966 | hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); | ||
967 | hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)); | ||
968 | |||
969 | /* | ||
970 | do { | ||
971 | temp = hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)); | ||
972 | if (lifeboat++ > 0xbb8) { | ||
973 | printk(KERN_ERR "Vortex: vortex_fifo_setwtctrl fail (hanging)\n"); | ||
974 | break; | ||
975 | } | ||
976 | } while ((temp & FIFO_RDONLY)&&(temp & FIFO_VALID)&&(temp != 0xFFFFFFFF)); | ||
977 | |||
978 | |||
979 | if (valid) { | ||
980 | if (temp & FIFO_VALID) { | ||
981 | temp = 0x40000; | ||
982 | //temp |= 0x08000000; | ||
983 | //temp |= 0x10000000; | ||
984 | //temp |= 0x04000000; | ||
985 | //temp |= 0x00400000; | ||
986 | temp |= 0x1c400000; | ||
987 | temp &= 0xFFFFFFF3; | ||
988 | temp &= 0xFFFFFFEF; | ||
989 | temp |= (valid & 1) << 4; | ||
990 | hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); | ||
991 | return; | ||
992 | } else { | ||
993 | vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); | ||
994 | return; | ||
995 | } | ||
996 | } else { | ||
997 | temp &= 0xffffffef; | ||
998 | temp |= 0x08000000; | ||
999 | temp |= 0x10000000; | ||
1000 | temp |= 0x04000000; | ||
1001 | temp |= 0x00400000; | ||
1002 | hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); | ||
1003 | temp = hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)); | ||
1004 | //((temp >> 6) & 0x3f) | ||
1005 | |||
1006 | priority = 0; | ||
1007 | if (((temp & 0x0fc0) ^ ((temp >> 6) & 0x0fc0)) & 0FFFFFFC0) | ||
1008 | vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); | ||
1009 | valid = 0xfb; | ||
1010 | temp = (temp & 0xfffffffd) | ((ctrl & 1) << 1); | ||
1011 | temp = (temp & 0xfffdffff) | ((f & 1) << 0x11); | ||
1012 | temp = (temp & 0xfffffff3) | ((priority & 3) << 2); | ||
1013 | temp = (temp & 0xffffffef) | ((valid & 1) << 4); | ||
1014 | temp = (temp & 0xffffffdf) | ((empty & 1) << 5); | ||
1015 | hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); | ||
1016 | } | ||
1017 | |||
1018 | */ | ||
1019 | |||
1020 | /* | ||
1021 | temp = (temp & 0xfffffffd) | ((ctrl & 1) << 1); | ||
1022 | temp = (temp & 0xfffdffff) | ((f & 1) << 0x11); | ||
1023 | temp = (temp & 0xfffffff3) | ((priority & 3) << 2); | ||
1024 | temp = (temp & 0xffffffef) | ((valid & 1) << 4); | ||
1025 | temp = (temp & 0xffffffdf) | ((empty & 1) << 5); | ||
1026 | #ifdef FIFO_BITS | ||
1027 | temp = temp | FIFO_BITS | 40000; | ||
1028 | #endif | ||
1029 | // 0x1c440010, 0x1c400000 | ||
1030 | hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); | ||
1031 | */ | ||
1032 | } | ||
1033 | |||
1034 | #endif | ||
1035 | static void vortex_fifo_init(vortex_t * vortex) | ||
1036 | { | ||
1037 | int x; | ||
1038 | unsigned long addr; | ||
1039 | |||
1040 | /* ADB DMA channels fifos. */ | ||
1041 | addr = VORTEX_FIFO_ADBCTRL + ((NR_ADB - 1) * 4); | ||
1042 | for (x = NR_ADB - 1; x >= 0; x--) { | ||
1043 | hwwrite(vortex->mmio, addr, (FIFO_U0 | FIFO_U1)); | ||
1044 | if (hwread(vortex->mmio, addr) != (FIFO_U0 | FIFO_U1)) | ||
1045 | printk(KERN_ERR "bad adb fifo reset!"); | ||
1046 | vortex_fifo_clearadbdata(vortex, x, FIFO_SIZE); | ||
1047 | addr -= 4; | ||
1048 | } | ||
1049 | |||
1050 | #ifndef CHIP_AU8810 | ||
1051 | /* WT DMA channels fifos. */ | ||
1052 | addr = VORTEX_FIFO_WTCTRL + ((NR_WT - 1) * 4); | ||
1053 | for (x = NR_WT - 1; x >= 0; x--) { | ||
1054 | hwwrite(vortex->mmio, addr, FIFO_U0); | ||
1055 | if (hwread(vortex->mmio, addr) != FIFO_U0) | ||
1056 | printk(KERN_ERR | ||
1057 | "bad wt fifo reset (0x%08lx, 0x%08x)!\n", | ||
1058 | addr, hwread(vortex->mmio, addr)); | ||
1059 | vortex_fifo_clearwtdata(vortex, x, FIFO_SIZE); | ||
1060 | addr -= 4; | ||
1061 | } | ||
1062 | #endif | ||
1063 | /* trigger... */ | ||
1064 | #ifdef CHIP_AU8820 | ||
1065 | hwwrite(vortex->mmio, 0xf8c0, 0xd03); //0x0843 0xd6b | ||
1066 | #else | ||
1067 | #ifdef CHIP_AU8830 | ||
1068 | hwwrite(vortex->mmio, 0x17000, 0x61); /* wt a */ | ||
1069 | hwwrite(vortex->mmio, 0x17004, 0x61); /* wt b */ | ||
1070 | #endif | ||
1071 | hwwrite(vortex->mmio, 0x17008, 0x61); /* adb */ | ||
1072 | #endif | ||
1073 | } | ||
1074 | |||
1075 | /* ADBDMA */ | ||
1076 | |||
1077 | static void vortex_adbdma_init(vortex_t * vortex) | ||
1078 | { | ||
1079 | } | ||
1080 | |||
1081 | static void vortex_adbdma_setfirstbuffer(vortex_t * vortex, int adbdma) | ||
1082 | { | ||
1083 | stream_t *dma = &vortex->dma_adb[adbdma]; | ||
1084 | |||
1085 | hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), | ||
1086 | dma->dma_ctrl); | ||
1087 | } | ||
1088 | |||
1089 | static void vortex_adbdma_setstartbuffer(vortex_t * vortex, int adbdma, int sb) | ||
1090 | { | ||
1091 | stream_t *dma = &vortex->dma_adb[adbdma]; | ||
1092 | //hwwrite(vortex->mmio, VORTEX_ADBDMA_START + (adbdma << 2), sb << (((NR_ADB-1)-((adbdma&0xf)*2)))); | ||
1093 | hwwrite(vortex->mmio, VORTEX_ADBDMA_START + (adbdma << 2), | ||
1094 | sb << ((0xf - (adbdma & 0xf)) * 2)); | ||
1095 | dma->period_real = dma->period_virt = sb; | ||
1096 | } | ||
1097 | |||
1098 | static void | ||
1099 | vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma, | ||
1100 | snd_pcm_sgbuf_t * sgbuf, int psize, int count) | ||
1101 | { | ||
1102 | stream_t *dma = &vortex->dma_adb[adbdma]; | ||
1103 | |||
1104 | if (sgbuf == NULL) { | ||
1105 | printk(KERN_INFO "vortex: FATAL: sgbuf is NULL!\n"); | ||
1106 | return; | ||
1107 | } | ||
1108 | //printk(KERN_INFO "vortex: page count = %d, tblcount = %d\n", count, sgbuf->tblsize); | ||
1109 | |||
1110 | dma->period_bytes = psize; | ||
1111 | dma->nr_periods = count; | ||
1112 | dma->sgbuf = sgbuf; | ||
1113 | |||
1114 | dma->cfg0 = 0; | ||
1115 | dma->cfg1 = 0; | ||
1116 | switch (count) { | ||
1117 | /* Four or more pages */ | ||
1118 | default: | ||
1119 | case 4: | ||
1120 | dma->cfg1 |= 0x88000000 | 0x44000000 | 0x30000000 | (psize - 1); | ||
1121 | hwwrite(vortex->mmio, | ||
1122 | VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0xc, | ||
1123 | snd_sgbuf_get_addr(sgbuf, psize * 3)); | ||
1124 | /* 3 pages */ | ||
1125 | case 3: | ||
1126 | dma->cfg0 |= 0x12000000; | ||
1127 | dma->cfg1 |= 0x80000000 | 0x40000000 | ((psize - 1) << 0xc); | ||
1128 | hwwrite(vortex->mmio, | ||
1129 | VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0x8, | ||
1130 | snd_sgbuf_get_addr(sgbuf, psize * 2)); | ||
1131 | /* 2 pages */ | ||
1132 | case 2: | ||
1133 | dma->cfg0 |= 0x88000000 | 0x44000000 | 0x10000000 | (psize - 1); | ||
1134 | hwwrite(vortex->mmio, | ||
1135 | VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0x4, | ||
1136 | snd_sgbuf_get_addr(sgbuf, psize)); | ||
1137 | /* 1 page */ | ||
1138 | case 1: | ||
1139 | dma->cfg0 |= 0x80000000 | 0x40000000 | ((psize - 1) << 0xc); | ||
1140 | hwwrite(vortex->mmio, | ||
1141 | VORTEX_ADBDMA_BUFBASE + (adbdma << 4), | ||
1142 | snd_sgbuf_get_addr(sgbuf, 0)); | ||
1143 | break; | ||
1144 | } | ||
1145 | //printk("vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n", dma->cfg0, dma->cfg1); | ||
1146 | hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG0 + (adbdma << 3), dma->cfg0); | ||
1147 | hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG1 + (adbdma << 3), dma->cfg1); | ||
1148 | |||
1149 | vortex_adbdma_setfirstbuffer(vortex, adbdma); | ||
1150 | vortex_adbdma_setstartbuffer(vortex, adbdma, 0); | ||
1151 | } | ||
1152 | |||
1153 | static void | ||
1154 | vortex_adbdma_setmode(vortex_t * vortex, int adbdma, int ie, int dir, | ||
1155 | int fmt, int d, unsigned long offset) | ||
1156 | { | ||
1157 | stream_t *dma = &vortex->dma_adb[adbdma]; | ||
1158 | |||
1159 | dma->dma_unknown = d; | ||
1160 | dma->dma_ctrl = | ||
1161 | ((offset & OFFSET_MASK) | (dma->dma_ctrl & ~OFFSET_MASK)); | ||
1162 | /* Enable PCMOUT interrupts. */ | ||
1163 | dma->dma_ctrl = | ||
1164 | (dma->dma_ctrl & ~IE_MASK) | ((ie << IE_SHIFT) & IE_MASK); | ||
1165 | |||
1166 | dma->dma_ctrl = | ||
1167 | (dma->dma_ctrl & ~DIR_MASK) | ((dir << DIR_SHIFT) & DIR_MASK); | ||
1168 | dma->dma_ctrl = | ||
1169 | (dma->dma_ctrl & ~FMT_MASK) | ((fmt << FMT_SHIFT) & FMT_MASK); | ||
1170 | |||
1171 | hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), | ||
1172 | dma->dma_ctrl); | ||
1173 | hwread(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2)); | ||
1174 | } | ||
1175 | |||
1176 | static int vortex_adbdma_bufshift(vortex_t * vortex, int adbdma) | ||
1177 | { | ||
1178 | stream_t *dma = &vortex->dma_adb[adbdma]; | ||
1179 | int page, p, pp, delta, i; | ||
1180 | |||
1181 | page = | ||
1182 | (hwread(vortex->mmio, VORTEX_ADBDMA_STAT + (adbdma << 2)) & | ||
1183 | ADB_SUBBUF_MASK) >> ADB_SUBBUF_SHIFT; | ||
1184 | if (dma->nr_periods >= 4) | ||
1185 | delta = (page - dma->period_real) & 3; | ||
1186 | else { | ||
1187 | delta = (page - dma->period_real); | ||
1188 | if (delta < 0) | ||
1189 | delta += dma->nr_periods; | ||
1190 | } | ||
1191 | if (delta == 0) | ||
1192 | return 0; | ||
1193 | |||
1194 | /* refresh hw page table */ | ||
1195 | if (dma->nr_periods > 4) { | ||
1196 | for (i = 0; i < delta; i++) { | ||
1197 | /* p: audio buffer page index */ | ||
1198 | p = dma->period_virt + i + 4; | ||
1199 | if (p >= dma->nr_periods) | ||
1200 | p -= dma->nr_periods; | ||
1201 | /* pp: hardware DMA page index. */ | ||
1202 | pp = dma->period_real + i; | ||
1203 | if (pp >= 4) | ||
1204 | pp -= 4; | ||
1205 | //hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE+(((adbdma << 2)+pp) << 2), dma->table[p].addr); | ||
1206 | hwwrite(vortex->mmio, | ||
1207 | VORTEX_ADBDMA_BUFBASE + (((adbdma << 2) + pp) << 2), | ||
1208 | snd_sgbuf_get_addr(dma->sgbuf, | ||
1209 | dma->period_bytes * p)); | ||
1210 | /* Force write thru cache. */ | ||
1211 | hwread(vortex->mmio, VORTEX_ADBDMA_BUFBASE + | ||
1212 | (((adbdma << 2) + pp) << 2)); | ||
1213 | } | ||
1214 | } | ||
1215 | dma->period_virt += delta; | ||
1216 | dma->period_real = page; | ||
1217 | if (dma->period_virt >= dma->nr_periods) | ||
1218 | dma->period_virt -= dma->nr_periods; | ||
1219 | if (delta != 1) | ||
1220 | printk(KERN_INFO "vortex: %d virt=%d, real=%d, delta=%d\n", | ||
1221 | adbdma, dma->period_virt, dma->period_real, delta); | ||
1222 | |||
1223 | return delta; | ||
1224 | } | ||
1225 | |||
1226 | |||
1227 | static void vortex_adbdma_resetup(vortex_t *vortex, int adbdma) { | ||
1228 | stream_t *dma = &vortex->dma_adb[adbdma]; | ||
1229 | int p, pp, i; | ||
1230 | |||
1231 | /* refresh hw page table */ | ||
1232 | for (i=0 ; i < 4 && i < dma->nr_periods; i++) { | ||
1233 | /* p: audio buffer page index */ | ||
1234 | p = dma->period_virt + i; | ||
1235 | if (p >= dma->nr_periods) | ||
1236 | p -= dma->nr_periods; | ||
1237 | /* pp: hardware DMA page index. */ | ||
1238 | pp = dma->period_real + i; | ||
1239 | if (dma->nr_periods < 4) { | ||
1240 | if (pp >= dma->nr_periods) | ||
1241 | pp -= dma->nr_periods; | ||
1242 | } | ||
1243 | else { | ||
1244 | if (pp >= 4) | ||
1245 | pp -= 4; | ||
1246 | } | ||
1247 | hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE+(((adbdma << 2)+pp) << 2), snd_sgbuf_get_addr(dma->sgbuf, dma->period_bytes * p)); | ||
1248 | /* Force write thru cache. */ | ||
1249 | hwread(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (((adbdma << 2)+pp) << 2)); | ||
1250 | } | ||
1251 | } | ||
1252 | |||
1253 | static int inline vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma) | ||
1254 | { | ||
1255 | stream_t *dma = &vortex->dma_adb[adbdma]; | ||
1256 | int temp; | ||
1257 | |||
1258 | temp = hwread(vortex->mmio, VORTEX_ADBDMA_STAT + (adbdma << 2)); | ||
1259 | temp = (dma->period_virt * dma->period_bytes) + (temp & POS_MASK); | ||
1260 | return (temp); | ||
1261 | } | ||
1262 | |||
1263 | static void vortex_adbdma_startfifo(vortex_t * vortex, int adbdma) | ||
1264 | { | ||
1265 | int this_8 = 0 /*empty */ , this_4 = 0 /*priority */ ; | ||
1266 | stream_t *dma = &vortex->dma_adb[adbdma]; | ||
1267 | |||
1268 | switch (dma->fifo_status) { | ||
1269 | case FIFO_START: | ||
1270 | vortex_fifo_setadbvalid(vortex, adbdma, | ||
1271 | dma->fifo_enabled ? 1 : 0); | ||
1272 | break; | ||
1273 | case FIFO_STOP: | ||
1274 | this_8 = 1; | ||
1275 | hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), | ||
1276 | dma->dma_ctrl); | ||
1277 | vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, | ||
1278 | this_4, this_8, | ||
1279 | dma->fifo_enabled ? 1 : 0, 0); | ||
1280 | break; | ||
1281 | case FIFO_PAUSE: | ||
1282 | vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, | ||
1283 | this_4, this_8, | ||
1284 | dma->fifo_enabled ? 1 : 0, 0); | ||
1285 | break; | ||
1286 | } | ||
1287 | dma->fifo_status = FIFO_START; | ||
1288 | } | ||
1289 | |||
1290 | static void vortex_adbdma_resumefifo(vortex_t * vortex, int adbdma) | ||
1291 | { | ||
1292 | stream_t *dma = &vortex->dma_adb[adbdma]; | ||
1293 | |||
1294 | int this_8 = 1, this_4 = 0; | ||
1295 | switch (dma->fifo_status) { | ||
1296 | case FIFO_STOP: | ||
1297 | hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), | ||
1298 | dma->dma_ctrl); | ||
1299 | vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, | ||
1300 | this_4, this_8, | ||
1301 | dma->fifo_enabled ? 1 : 0, 0); | ||
1302 | break; | ||
1303 | case FIFO_PAUSE: | ||
1304 | vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, | ||
1305 | this_4, this_8, | ||
1306 | dma->fifo_enabled ? 1 : 0, 0); | ||
1307 | break; | ||
1308 | } | ||
1309 | dma->fifo_status = FIFO_START; | ||
1310 | } | ||
1311 | |||
1312 | static void vortex_adbdma_pausefifo(vortex_t * vortex, int adbdma) | ||
1313 | { | ||
1314 | stream_t *dma = &vortex->dma_adb[adbdma]; | ||
1315 | |||
1316 | int this_8 = 0, this_4 = 0; | ||
1317 | switch (dma->fifo_status) { | ||
1318 | case FIFO_START: | ||
1319 | vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, | ||
1320 | this_4, this_8, 0, 0); | ||
1321 | break; | ||
1322 | case FIFO_STOP: | ||
1323 | hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), | ||
1324 | dma->dma_ctrl); | ||
1325 | vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, | ||
1326 | this_4, this_8, 0, 0); | ||
1327 | break; | ||
1328 | } | ||
1329 | dma->fifo_status = FIFO_PAUSE; | ||
1330 | } | ||
1331 | |||
1332 | #if 0 // Using pause instead | ||
1333 | static void vortex_adbdma_stopfifo(vortex_t * vortex, int adbdma) | ||
1334 | { | ||
1335 | stream_t *dma = &vortex->dma_adb[adbdma]; | ||
1336 | |||
1337 | int this_4 = 0, this_8 = 0; | ||
1338 | if (dma->fifo_status == FIFO_START) | ||
1339 | vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, | ||
1340 | this_4, this_8, 0, 0); | ||
1341 | else if (dma->fifo_status == FIFO_STOP) | ||
1342 | return; | ||
1343 | dma->fifo_status = FIFO_STOP; | ||
1344 | dma->fifo_enabled = 0; | ||
1345 | } | ||
1346 | |||
1347 | #endif | ||
1348 | /* WTDMA */ | ||
1349 | |||
1350 | #ifndef CHIP_AU8810 | ||
1351 | static void vortex_wtdma_setfirstbuffer(vortex_t * vortex, int wtdma) | ||
1352 | { | ||
1353 | //int this_7c=dma_ctrl; | ||
1354 | stream_t *dma = &vortex->dma_wt[wtdma]; | ||
1355 | |||
1356 | hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), dma->dma_ctrl); | ||
1357 | } | ||
1358 | |||
1359 | static void vortex_wtdma_setstartbuffer(vortex_t * vortex, int wtdma, int sb) | ||
1360 | { | ||
1361 | stream_t *dma = &vortex->dma_wt[wtdma]; | ||
1362 | //hwwrite(vortex->mmio, VORTEX_WTDMA_START + (wtdma << 2), sb << ((0x1f-(wtdma&0xf)*2))); | ||
1363 | hwwrite(vortex->mmio, VORTEX_WTDMA_START + (wtdma << 2), | ||
1364 | sb << ((0xf - (wtdma & 0xf)) * 2)); | ||
1365 | dma->period_real = dma->period_virt = sb; | ||
1366 | } | ||
1367 | |||
1368 | static void | ||
1369 | vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma, | ||
1370 | snd_pcm_sgbuf_t * sgbuf, int psize, int count) | ||
1371 | { | ||
1372 | stream_t *dma = &vortex->dma_wt[wtdma]; | ||
1373 | |||
1374 | dma->period_bytes = psize; | ||
1375 | dma->nr_periods = count; | ||
1376 | dma->sgbuf = sgbuf; | ||
1377 | |||
1378 | dma->cfg0 = 0; | ||
1379 | dma->cfg1 = 0; | ||
1380 | switch (count) { | ||
1381 | /* Four or more pages */ | ||
1382 | default: | ||
1383 | case 4: | ||
1384 | dma->cfg1 |= 0x88000000 | 0x44000000 | 0x30000000 | (psize-1); | ||
1385 | hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0xc, | ||
1386 | snd_sgbuf_get_addr(sgbuf, psize * 3)); | ||
1387 | /* 3 pages */ | ||
1388 | case 3: | ||
1389 | dma->cfg0 |= 0x12000000; | ||
1390 | dma->cfg1 |= 0x80000000 | 0x40000000 | ((psize-1) << 0xc); | ||
1391 | hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0x8, | ||
1392 | snd_sgbuf_get_addr(sgbuf, psize * 2)); | ||
1393 | /* 2 pages */ | ||
1394 | case 2: | ||
1395 | dma->cfg0 |= 0x88000000 | 0x44000000 | 0x10000000 | (psize-1); | ||
1396 | hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0x4, | ||
1397 | snd_sgbuf_get_addr(sgbuf, psize)); | ||
1398 | /* 1 page */ | ||
1399 | case 1: | ||
1400 | dma->cfg0 |= 0x80000000 | 0x40000000 | ((psize-1) << 0xc); | ||
1401 | hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4), | ||
1402 | snd_sgbuf_get_addr(sgbuf, 0)); | ||
1403 | break; | ||
1404 | } | ||
1405 | hwwrite(vortex->mmio, VORTEX_WTDMA_BUFCFG0 + (wtdma << 3), dma->cfg0); | ||
1406 | hwwrite(vortex->mmio, VORTEX_WTDMA_BUFCFG1 + (wtdma << 3), dma->cfg1); | ||
1407 | |||
1408 | vortex_wtdma_setfirstbuffer(vortex, wtdma); | ||
1409 | vortex_wtdma_setstartbuffer(vortex, wtdma, 0); | ||
1410 | } | ||
1411 | |||
1412 | static void | ||
1413 | vortex_wtdma_setmode(vortex_t * vortex, int wtdma, int ie, int fmt, int d, | ||
1414 | /*int e, */ unsigned long offset) | ||
1415 | { | ||
1416 | stream_t *dma = &vortex->dma_wt[wtdma]; | ||
1417 | |||
1418 | //dma->this_08 = e; | ||
1419 | dma->dma_unknown = d; | ||
1420 | dma->dma_ctrl = 0; | ||
1421 | dma->dma_ctrl = | ||
1422 | ((offset & OFFSET_MASK) | (dma->dma_ctrl & ~OFFSET_MASK)); | ||
1423 | /* PCMOUT interrupt */ | ||
1424 | dma->dma_ctrl = | ||
1425 | (dma->dma_ctrl & ~IE_MASK) | ((ie << IE_SHIFT) & IE_MASK); | ||
1426 | /* Always playback. */ | ||
1427 | dma->dma_ctrl |= (1 << DIR_SHIFT); | ||
1428 | /* Audio Format */ | ||
1429 | dma->dma_ctrl = | ||
1430 | (dma->dma_ctrl & FMT_MASK) | ((fmt << FMT_SHIFT) & FMT_MASK); | ||
1431 | /* Write into hardware */ | ||
1432 | hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), dma->dma_ctrl); | ||
1433 | } | ||
1434 | |||
1435 | static int vortex_wtdma_bufshift(vortex_t * vortex, int wtdma) | ||
1436 | { | ||
1437 | stream_t *dma = &vortex->dma_wt[wtdma]; | ||
1438 | int page, p, pp, delta, i; | ||
1439 | |||
1440 | page = | ||
1441 | (hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)) & | ||
1442 | WT_SUBBUF_MASK) | ||
1443 | >> WT_SUBBUF_SHIFT; | ||
1444 | if (dma->nr_periods >= 4) | ||
1445 | delta = (page - dma->period_real) & 3; | ||
1446 | else { | ||
1447 | delta = (page - dma->period_real); | ||
1448 | if (delta < 0) | ||
1449 | delta += dma->nr_periods; | ||
1450 | } | ||
1451 | if (delta == 0) | ||
1452 | return 0; | ||
1453 | |||
1454 | /* refresh hw page table */ | ||
1455 | if (dma->nr_periods > 4) { | ||
1456 | for (i = 0; i < delta; i++) { | ||
1457 | /* p: audio buffer page index */ | ||
1458 | p = dma->period_virt + i + 4; | ||
1459 | if (p >= dma->nr_periods) | ||
1460 | p -= dma->nr_periods; | ||
1461 | /* pp: hardware DMA page index. */ | ||
1462 | pp = dma->period_real + i; | ||
1463 | if (pp >= 4) | ||
1464 | pp -= 4; | ||
1465 | hwwrite(vortex->mmio, | ||
1466 | VORTEX_WTDMA_BUFBASE + | ||
1467 | (((wtdma << 2) + pp) << 2), | ||
1468 | snd_sgbuf_get_addr(dma->sgbuf, dma->period_bytes * p)); | ||
1469 | /* Force write thru cache. */ | ||
1470 | hwread(vortex->mmio, VORTEX_WTDMA_BUFBASE + | ||
1471 | (((wtdma << 2) + pp) << 2)); | ||
1472 | } | ||
1473 | } | ||
1474 | dma->period_virt += delta; | ||
1475 | if (dma->period_virt >= dma->nr_periods) | ||
1476 | dma->period_virt -= dma->nr_periods; | ||
1477 | dma->period_real = page; | ||
1478 | |||
1479 | if (delta != 1) | ||
1480 | printk(KERN_WARNING "vortex: wt virt = %d, delta = %d\n", | ||
1481 | dma->period_virt, delta); | ||
1482 | |||
1483 | return delta; | ||
1484 | } | ||
1485 | |||
1486 | #if 0 | ||
1487 | static void | ||
1488 | vortex_wtdma_getposition(vortex_t * vortex, int wtdma, int *subbuf, int *pos) | ||
1489 | { | ||
1490 | int temp; | ||
1491 | temp = hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)); | ||
1492 | *subbuf = (temp >> WT_SUBBUF_SHIFT) & WT_SUBBUF_MASK; | ||
1493 | *pos = temp & POS_MASK; | ||
1494 | } | ||
1495 | |||
1496 | static int vortex_wtdma_getcursubuffer(vortex_t * vortex, int wtdma) | ||
1497 | { | ||
1498 | return ((hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)) >> | ||
1499 | POS_SHIFT) & POS_MASK); | ||
1500 | } | ||
1501 | #endif | ||
1502 | static int inline vortex_wtdma_getlinearpos(vortex_t * vortex, int wtdma) | ||
1503 | { | ||
1504 | stream_t *dma = &vortex->dma_wt[wtdma]; | ||
1505 | int temp; | ||
1506 | |||
1507 | temp = hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)); | ||
1508 | //temp = (temp & POS_MASK) + (((temp>>WT_SUBBUF_SHIFT) & WT_SUBBUF_MASK)*(dma->cfg0&POS_MASK)); | ||
1509 | temp = (temp & POS_MASK) + ((dma->period_virt) * (dma->period_bytes)); | ||
1510 | return temp; | ||
1511 | } | ||
1512 | |||
1513 | static void vortex_wtdma_startfifo(vortex_t * vortex, int wtdma) | ||
1514 | { | ||
1515 | stream_t *dma = &vortex->dma_wt[wtdma]; | ||
1516 | int this_8 = 0, this_4 = 0; | ||
1517 | |||
1518 | switch (dma->fifo_status) { | ||
1519 | case FIFO_START: | ||
1520 | vortex_fifo_setwtvalid(vortex, wtdma, | ||
1521 | dma->fifo_enabled ? 1 : 0); | ||
1522 | break; | ||
1523 | case FIFO_STOP: | ||
1524 | this_8 = 1; | ||
1525 | hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), | ||
1526 | dma->dma_ctrl); | ||
1527 | vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, | ||
1528 | this_4, this_8, | ||
1529 | dma->fifo_enabled ? 1 : 0, 0); | ||
1530 | break; | ||
1531 | case FIFO_PAUSE: | ||
1532 | vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, | ||
1533 | this_4, this_8, | ||
1534 | dma->fifo_enabled ? 1 : 0, 0); | ||
1535 | break; | ||
1536 | } | ||
1537 | dma->fifo_status = FIFO_START; | ||
1538 | } | ||
1539 | |||
1540 | static void vortex_wtdma_resumefifo(vortex_t * vortex, int wtdma) | ||
1541 | { | ||
1542 | stream_t *dma = &vortex->dma_wt[wtdma]; | ||
1543 | |||
1544 | int this_8 = 0, this_4 = 0; | ||
1545 | switch (dma->fifo_status) { | ||
1546 | case FIFO_STOP: | ||
1547 | hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), | ||
1548 | dma->dma_ctrl); | ||
1549 | vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, | ||
1550 | this_4, this_8, | ||
1551 | dma->fifo_enabled ? 1 : 0, 0); | ||
1552 | break; | ||
1553 | case FIFO_PAUSE: | ||
1554 | vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, | ||
1555 | this_4, this_8, | ||
1556 | dma->fifo_enabled ? 1 : 0, 0); | ||
1557 | break; | ||
1558 | } | ||
1559 | dma->fifo_status = FIFO_START; | ||
1560 | } | ||
1561 | |||
1562 | static void vortex_wtdma_pausefifo(vortex_t * vortex, int wtdma) | ||
1563 | { | ||
1564 | stream_t *dma = &vortex->dma_wt[wtdma]; | ||
1565 | |||
1566 | int this_8 = 0, this_4 = 0; | ||
1567 | switch (dma->fifo_status) { | ||
1568 | case FIFO_START: | ||
1569 | vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, | ||
1570 | this_4, this_8, 0, 0); | ||
1571 | break; | ||
1572 | case FIFO_STOP: | ||
1573 | hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), | ||
1574 | dma->dma_ctrl); | ||
1575 | vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, | ||
1576 | this_4, this_8, 0, 0); | ||
1577 | break; | ||
1578 | } | ||
1579 | dma->fifo_status = FIFO_PAUSE; | ||
1580 | } | ||
1581 | |||
1582 | static void vortex_wtdma_stopfifo(vortex_t * vortex, int wtdma) | ||
1583 | { | ||
1584 | stream_t *dma = &vortex->dma_wt[wtdma]; | ||
1585 | |||
1586 | int this_4 = 0, this_8 = 0; | ||
1587 | if (dma->fifo_status == FIFO_START) | ||
1588 | vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, | ||
1589 | this_4, this_8, 0, 0); | ||
1590 | else if (dma->fifo_status == FIFO_STOP) | ||
1591 | return; | ||
1592 | dma->fifo_status = FIFO_STOP; | ||
1593 | dma->fifo_enabled = 0; | ||
1594 | } | ||
1595 | |||
1596 | #endif | ||
1597 | /* ADB Routes */ | ||
1598 | |||
1599 | typedef int ADBRamLink; | ||
1600 | static void vortex_adb_init(vortex_t * vortex) | ||
1601 | { | ||
1602 | int i; | ||
1603 | /* it looks like we are writing more than we need to... | ||
1604 | * if we write what we are supposed to it breaks things... */ | ||
1605 | hwwrite(vortex->mmio, VORTEX_ADB_SR, 0); | ||
1606 | for (i = 0; i < VORTEX_ADB_RTBASE_COUNT; i++) | ||
1607 | hwwrite(vortex->mmio, VORTEX_ADB_RTBASE + (i << 2), | ||
1608 | hwread(vortex->mmio, | ||
1609 | VORTEX_ADB_RTBASE + (i << 2)) | ROUTE_MASK); | ||
1610 | for (i = 0; i < VORTEX_ADB_CHNBASE_COUNT; i++) { | ||
1611 | hwwrite(vortex->mmio, VORTEX_ADB_CHNBASE + (i << 2), | ||
1612 | hwread(vortex->mmio, | ||
1613 | VORTEX_ADB_CHNBASE + (i << 2)) | ROUTE_MASK); | ||
1614 | } | ||
1615 | } | ||
1616 | |||
1617 | static void vortex_adb_en_sr(vortex_t * vortex, int channel) | ||
1618 | { | ||
1619 | hwwrite(vortex->mmio, VORTEX_ADB_SR, | ||
1620 | hwread(vortex->mmio, VORTEX_ADB_SR) | (0x1 << channel)); | ||
1621 | } | ||
1622 | |||
1623 | static void vortex_adb_dis_sr(vortex_t * vortex, int channel) | ||
1624 | { | ||
1625 | hwwrite(vortex->mmio, VORTEX_ADB_SR, | ||
1626 | hwread(vortex->mmio, VORTEX_ADB_SR) & ~(0x1 << channel)); | ||
1627 | } | ||
1628 | |||
1629 | static void | ||
1630 | vortex_adb_addroutes(vortex_t * vortex, unsigned char channel, | ||
1631 | ADBRamLink * route, int rnum) | ||
1632 | { | ||
1633 | int temp, prev, lifeboat = 0; | ||
1634 | |||
1635 | if ((rnum <= 0) || (route == NULL)) | ||
1636 | return; | ||
1637 | /* Write last routes. */ | ||
1638 | rnum--; | ||
1639 | hwwrite(vortex->mmio, | ||
1640 | VORTEX_ADB_RTBASE + ((route[rnum] & ADB_MASK) << 2), | ||
1641 | ROUTE_MASK); | ||
1642 | while (rnum > 0) { | ||
1643 | hwwrite(vortex->mmio, | ||
1644 | VORTEX_ADB_RTBASE + | ||
1645 | ((route[rnum - 1] & ADB_MASK) << 2), route[rnum]); | ||
1646 | rnum--; | ||
1647 | } | ||
1648 | /* Write first route. */ | ||
1649 | temp = | ||
1650 | hwread(vortex->mmio, | ||
1651 | VORTEX_ADB_CHNBASE + (channel << 2)) & ADB_MASK; | ||
1652 | if (temp == ADB_MASK) { | ||
1653 | /* First entry on this channel. */ | ||
1654 | hwwrite(vortex->mmio, VORTEX_ADB_CHNBASE + (channel << 2), | ||
1655 | route[0]); | ||
1656 | vortex_adb_en_sr(vortex, channel); | ||
1657 | return; | ||
1658 | } | ||
1659 | /* Not first entry on this channel. Need to link. */ | ||
1660 | do { | ||
1661 | prev = temp; | ||
1662 | temp = | ||
1663 | hwread(vortex->mmio, | ||
1664 | VORTEX_ADB_RTBASE + (temp << 2)) & ADB_MASK; | ||
1665 | if ((lifeboat++) > ADB_MASK) { | ||
1666 | printk(KERN_ERR | ||
1667 | "vortex_adb_addroutes: unending route! 0x%x\n", | ||
1668 | *route); | ||
1669 | return; | ||
1670 | } | ||
1671 | } | ||
1672 | while (temp != ADB_MASK); | ||
1673 | hwwrite(vortex->mmio, VORTEX_ADB_RTBASE + (prev << 2), route[0]); | ||
1674 | } | ||
1675 | |||
1676 | static void | ||
1677 | vortex_adb_delroutes(vortex_t * vortex, unsigned char channel, | ||
1678 | ADBRamLink route0, ADBRamLink route1) | ||
1679 | { | ||
1680 | int temp, lifeboat = 0, prev; | ||
1681 | |||
1682 | /* Find route. */ | ||
1683 | temp = | ||
1684 | hwread(vortex->mmio, | ||
1685 | VORTEX_ADB_CHNBASE + (channel << 2)) & ADB_MASK; | ||
1686 | if (temp == (route0 & ADB_MASK)) { | ||
1687 | temp = | ||
1688 | hwread(vortex->mmio, | ||
1689 | VORTEX_ADB_RTBASE + ((route1 & ADB_MASK) << 2)); | ||
1690 | if ((temp & ADB_MASK) == ADB_MASK) | ||
1691 | vortex_adb_dis_sr(vortex, channel); | ||
1692 | hwwrite(vortex->mmio, VORTEX_ADB_CHNBASE + (channel << 2), | ||
1693 | temp); | ||
1694 | return; | ||
1695 | } | ||
1696 | do { | ||
1697 | prev = temp; | ||
1698 | temp = | ||
1699 | hwread(vortex->mmio, | ||
1700 | VORTEX_ADB_RTBASE + (prev << 2)) & ADB_MASK; | ||
1701 | if (((lifeboat++) > ADB_MASK) || (temp == ADB_MASK)) { | ||
1702 | printk(KERN_ERR | ||
1703 | "vortex_adb_delroutes: route not found! 0x%x\n", | ||
1704 | route0); | ||
1705 | return; | ||
1706 | } | ||
1707 | } | ||
1708 | while (temp != (route0 & ADB_MASK)); | ||
1709 | temp = hwread(vortex->mmio, VORTEX_ADB_RTBASE + (temp << 2)); | ||
1710 | if ((temp & ADB_MASK) == route1) | ||
1711 | temp = hwread(vortex->mmio, VORTEX_ADB_RTBASE + (temp << 2)); | ||
1712 | /* Make bridge over deleted route. */ | ||
1713 | hwwrite(vortex->mmio, VORTEX_ADB_RTBASE + (prev << 2), temp); | ||
1714 | } | ||
1715 | |||
1716 | static void | ||
1717 | vortex_route(vortex_t * vortex, int en, unsigned char channel, | ||
1718 | unsigned char source, unsigned char dest) | ||
1719 | { | ||
1720 | ADBRamLink route; | ||
1721 | |||
1722 | route = ((source & ADB_MASK) << ADB_SHIFT) | (dest & ADB_MASK); | ||
1723 | if (en) { | ||
1724 | vortex_adb_addroutes(vortex, channel, &route, 1); | ||
1725 | if ((source < (OFFSET_SRCOUT + NR_SRC)) | ||
1726 | && (source >= OFFSET_SRCOUT)) | ||
1727 | vortex_src_addWTD(vortex, (source - OFFSET_SRCOUT), | ||
1728 | channel); | ||
1729 | else if ((source < (OFFSET_MIXOUT + NR_MIXOUT)) | ||
1730 | && (source >= OFFSET_MIXOUT)) | ||
1731 | vortex_mixer_addWTD(vortex, | ||
1732 | (source - OFFSET_MIXOUT), channel); | ||
1733 | } else { | ||
1734 | vortex_adb_delroutes(vortex, channel, route, route); | ||
1735 | if ((source < (OFFSET_SRCOUT + NR_SRC)) | ||
1736 | && (source >= OFFSET_SRCOUT)) | ||
1737 | vortex_src_delWTD(vortex, (source - OFFSET_SRCOUT), | ||
1738 | channel); | ||
1739 | else if ((source < (OFFSET_MIXOUT + NR_MIXOUT)) | ||
1740 | && (source >= OFFSET_MIXOUT)) | ||
1741 | vortex_mixer_delWTD(vortex, | ||
1742 | (source - OFFSET_MIXOUT), channel); | ||
1743 | } | ||
1744 | } | ||
1745 | |||
1746 | #if 0 | ||
1747 | static void | ||
1748 | vortex_routes(vortex_t * vortex, int en, unsigned char channel, | ||
1749 | unsigned char source, unsigned char dest0, unsigned char dest1) | ||
1750 | { | ||
1751 | ADBRamLink route[2]; | ||
1752 | |||
1753 | route[0] = ((source & ADB_MASK) << ADB_SHIFT) | (dest0 & ADB_MASK); | ||
1754 | route[1] = ((source & ADB_MASK) << ADB_SHIFT) | (dest1 & ADB_MASK); | ||
1755 | |||
1756 | if (en) { | ||
1757 | vortex_adb_addroutes(vortex, channel, route, 2); | ||
1758 | if ((source < (OFFSET_SRCOUT + NR_SRC)) | ||
1759 | && (source >= (OFFSET_SRCOUT))) | ||
1760 | vortex_src_addWTD(vortex, (source - OFFSET_SRCOUT), | ||
1761 | channel); | ||
1762 | else if ((source < (OFFSET_MIXOUT + NR_MIXOUT)) | ||
1763 | && (source >= (OFFSET_MIXOUT))) | ||
1764 | vortex_mixer_addWTD(vortex, | ||
1765 | (source - OFFSET_MIXOUT), channel); | ||
1766 | } else { | ||
1767 | vortex_adb_delroutes(vortex, channel, route[0], route[1]); | ||
1768 | if ((source < (OFFSET_SRCOUT + NR_SRC)) | ||
1769 | && (source >= (OFFSET_SRCOUT))) | ||
1770 | vortex_src_delWTD(vortex, (source - OFFSET_SRCOUT), | ||
1771 | channel); | ||
1772 | else if ((source < (OFFSET_MIXOUT + NR_MIXOUT)) | ||
1773 | && (source >= (OFFSET_MIXOUT))) | ||
1774 | vortex_mixer_delWTD(vortex, | ||
1775 | (source - OFFSET_MIXOUT), channel); | ||
1776 | } | ||
1777 | } | ||
1778 | |||
1779 | #endif | ||
1780 | /* Route two sources to same target. Sources must be of same class !!! */ | ||
1781 | static void | ||
1782 | vortex_routeLRT(vortex_t * vortex, int en, unsigned char ch, | ||
1783 | unsigned char source0, unsigned char source1, | ||
1784 | unsigned char dest) | ||
1785 | { | ||
1786 | ADBRamLink route[2]; | ||
1787 | |||
1788 | route[0] = ((source0 & ADB_MASK) << ADB_SHIFT) | (dest & ADB_MASK); | ||
1789 | route[1] = ((source1 & ADB_MASK) << ADB_SHIFT) | (dest & ADB_MASK); | ||
1790 | |||
1791 | if (dest < 0x10) | ||
1792 | route[1] = (route[1] & ~ADB_MASK) | (dest + 0x20); /* fifo A */ | ||
1793 | |||
1794 | if (en) { | ||
1795 | vortex_adb_addroutes(vortex, ch, route, 2); | ||
1796 | if ((source0 < (OFFSET_SRCOUT + NR_SRC)) | ||
1797 | && (source0 >= OFFSET_SRCOUT)) { | ||
1798 | vortex_src_addWTD(vortex, | ||
1799 | (source0 - OFFSET_SRCOUT), ch); | ||
1800 | vortex_src_addWTD(vortex, | ||
1801 | (source1 - OFFSET_SRCOUT), ch); | ||
1802 | } else if ((source0 < (OFFSET_MIXOUT + NR_MIXOUT)) | ||
1803 | && (source0 >= OFFSET_MIXOUT)) { | ||
1804 | vortex_mixer_addWTD(vortex, | ||
1805 | (source0 - OFFSET_MIXOUT), ch); | ||
1806 | vortex_mixer_addWTD(vortex, | ||
1807 | (source1 - OFFSET_MIXOUT), ch); | ||
1808 | } | ||
1809 | } else { | ||
1810 | vortex_adb_delroutes(vortex, ch, route[0], route[1]); | ||
1811 | if ((source0 < (OFFSET_SRCOUT + NR_SRC)) | ||
1812 | && (source0 >= OFFSET_SRCOUT)) { | ||
1813 | vortex_src_delWTD(vortex, | ||
1814 | (source0 - OFFSET_SRCOUT), ch); | ||
1815 | vortex_src_delWTD(vortex, | ||
1816 | (source1 - OFFSET_SRCOUT), ch); | ||
1817 | } else if ((source0 < (OFFSET_MIXOUT + NR_MIXOUT)) | ||
1818 | && (source0 >= OFFSET_MIXOUT)) { | ||
1819 | vortex_mixer_delWTD(vortex, | ||
1820 | (source0 - OFFSET_MIXOUT), ch); | ||
1821 | vortex_mixer_delWTD(vortex, | ||
1822 | (source1 - OFFSET_MIXOUT), ch); | ||
1823 | } | ||
1824 | } | ||
1825 | } | ||
1826 | |||
1827 | /* Connection stuff */ | ||
1828 | |||
1829 | // Connect adbdma to src('s). | ||
1830 | static void | ||
1831 | vortex_connection_adbdma_src(vortex_t * vortex, int en, unsigned char ch, | ||
1832 | unsigned char adbdma, unsigned char src) | ||
1833 | { | ||
1834 | vortex_route(vortex, en, ch, ADB_DMA(adbdma), ADB_SRCIN(src)); | ||
1835 | } | ||
1836 | |||
1837 | // Connect SRC to mixin. | ||
1838 | static void | ||
1839 | vortex_connection_src_mixin(vortex_t * vortex, int en, | ||
1840 | unsigned char channel, unsigned char src, | ||
1841 | unsigned char mixin) | ||
1842 | { | ||
1843 | vortex_route(vortex, en, channel, ADB_SRCOUT(src), ADB_MIXIN(mixin)); | ||
1844 | } | ||
1845 | |||
1846 | // Connect mixin with mix output. | ||
1847 | static void | ||
1848 | vortex_connection_mixin_mix(vortex_t * vortex, int en, unsigned char mixin, | ||
1849 | unsigned char mix, int a) | ||
1850 | { | ||
1851 | if (en) { | ||
1852 | vortex_mix_enableinput(vortex, mix, mixin); | ||
1853 | vortex_mix_setinputvolumebyte(vortex, mix, mixin, MIX_DEFIGAIN); // added to original code. | ||
1854 | } else | ||
1855 | vortex_mix_disableinput(vortex, mix, mixin, a); | ||
1856 | } | ||
1857 | |||
1858 | // Connect absolut address to mixin. | ||
1859 | static void | ||
1860 | vortex_connection_adb_mixin(vortex_t * vortex, int en, | ||
1861 | unsigned char channel, unsigned char source, | ||
1862 | unsigned char mixin) | ||
1863 | { | ||
1864 | vortex_route(vortex, en, channel, source, ADB_MIXIN(mixin)); | ||
1865 | } | ||
1866 | |||
1867 | static void | ||
1868 | vortex_connection_src_adbdma(vortex_t * vortex, int en, unsigned char ch, | ||
1869 | unsigned char src, unsigned char adbdma) | ||
1870 | { | ||
1871 | vortex_route(vortex, en, ch, ADB_SRCOUT(src), ADB_DMA(adbdma)); | ||
1872 | } | ||
1873 | |||
1874 | static void | ||
1875 | vortex_connection_src_src_adbdma(vortex_t * vortex, int en, | ||
1876 | unsigned char ch, unsigned char src0, | ||
1877 | unsigned char src1, unsigned char adbdma) | ||
1878 | { | ||
1879 | |||
1880 | vortex_routeLRT(vortex, en, ch, ADB_SRCOUT(src0), ADB_SRCOUT(src1), | ||
1881 | ADB_DMA(adbdma)); | ||
1882 | } | ||
1883 | |||
1884 | // mix to absolut address. | ||
1885 | static void | ||
1886 | vortex_connection_mix_adb(vortex_t * vortex, int en, unsigned char ch, | ||
1887 | unsigned char mix, unsigned char dest) | ||
1888 | { | ||
1889 | vortex_route(vortex, en, ch, ADB_MIXOUT(mix), dest); | ||
1890 | vortex_mix_setvolumebyte(vortex, mix, MIX_DEFOGAIN); // added to original code. | ||
1891 | } | ||
1892 | |||
1893 | // mixer to src. | ||
1894 | static void | ||
1895 | vortex_connection_mix_src(vortex_t * vortex, int en, unsigned char ch, | ||
1896 | unsigned char mix, unsigned char src) | ||
1897 | { | ||
1898 | vortex_route(vortex, en, ch, ADB_MIXOUT(mix), ADB_SRCIN(src)); | ||
1899 | vortex_mix_setvolumebyte(vortex, mix, MIX_DEFOGAIN); // added to original code. | ||
1900 | } | ||
1901 | |||
1902 | #if 0 | ||
1903 | static void | ||
1904 | vortex_connection_adbdma_src_src(vortex_t * vortex, int en, | ||
1905 | unsigned char channel, | ||
1906 | unsigned char adbdma, unsigned char src0, | ||
1907 | unsigned char src1) | ||
1908 | { | ||
1909 | vortex_routes(vortex, en, channel, ADB_DMA(adbdma), | ||
1910 | ADB_SRCIN(src0), ADB_SRCIN(src1)); | ||
1911 | } | ||
1912 | |||
1913 | // Connect two mix to AdbDma. | ||
1914 | static void | ||
1915 | vortex_connection_mix_mix_adbdma(vortex_t * vortex, int en, | ||
1916 | unsigned char ch, unsigned char mix0, | ||
1917 | unsigned char mix1, unsigned char adbdma) | ||
1918 | { | ||
1919 | |||
1920 | ADBRamLink routes[2]; | ||
1921 | routes[0] = | ||
1922 | (((mix0 + | ||
1923 | OFFSET_MIXOUT) & ADB_MASK) << ADB_SHIFT) | (adbdma & ADB_MASK); | ||
1924 | routes[1] = | ||
1925 | (((mix1 + OFFSET_MIXOUT) & ADB_MASK) << ADB_SHIFT) | ((adbdma + | ||
1926 | 0x20) & | ||
1927 | ADB_MASK); | ||
1928 | if (en) { | ||
1929 | vortex_adb_addroutes(vortex, ch, routes, 0x2); | ||
1930 | vortex_mixer_addWTD(vortex, mix0, ch); | ||
1931 | vortex_mixer_addWTD(vortex, mix1, ch); | ||
1932 | } else { | ||
1933 | vortex_adb_delroutes(vortex, ch, routes[0], routes[1]); | ||
1934 | vortex_mixer_delWTD(vortex, mix0, ch); | ||
1935 | vortex_mixer_delWTD(vortex, mix1, ch); | ||
1936 | } | ||
1937 | } | ||
1938 | #endif | ||
1939 | |||
1940 | /* CODEC connect. */ | ||
1941 | |||
1942 | static void | ||
1943 | vortex_connect_codecplay(vortex_t * vortex, int en, unsigned char mixers[]) | ||
1944 | { | ||
1945 | #ifdef CHIP_AU8820 | ||
1946 | vortex_connection_mix_adb(vortex, en, 0x11, mixers[0], ADB_CODECOUT(0)); | ||
1947 | vortex_connection_mix_adb(vortex, en, 0x11, mixers[1], ADB_CODECOUT(1)); | ||
1948 | #else | ||
1949 | #if 1 | ||
1950 | // Connect front channels through EQ. | ||
1951 | vortex_connection_mix_adb(vortex, en, 0x11, mixers[0], ADB_EQIN(0)); | ||
1952 | vortex_connection_mix_adb(vortex, en, 0x11, mixers[1], ADB_EQIN(1)); | ||
1953 | /* Lower volume, since EQ has some gain. */ | ||
1954 | vortex_mix_setvolumebyte(vortex, mixers[0], 0); | ||
1955 | vortex_mix_setvolumebyte(vortex, mixers[1], 0); | ||
1956 | vortex_route(vortex, en, 0x11, ADB_EQOUT(0), ADB_CODECOUT(0)); | ||
1957 | vortex_route(vortex, en, 0x11, ADB_EQOUT(1), ADB_CODECOUT(1)); | ||
1958 | |||
1959 | /* Check if reg 0x28 has SDAC bit set. */ | ||
1960 | if (VORTEX_IS_QUAD(vortex)) { | ||
1961 | /* Rear channel. Note: ADB_CODECOUT(0+2) and (1+2) is for AC97 modem */ | ||
1962 | vortex_connection_mix_adb(vortex, en, 0x11, mixers[2], | ||
1963 | ADB_CODECOUT(0 + 4)); | ||
1964 | vortex_connection_mix_adb(vortex, en, 0x11, mixers[3], | ||
1965 | ADB_CODECOUT(1 + 4)); | ||
1966 | //printk("SDAC detected "); | ||
1967 | } | ||
1968 | #else | ||
1969 | // Use plain direct output to codec. | ||
1970 | vortex_connection_mix_adb(vortex, en, 0x11, mixers[0], ADB_CODECOUT(0)); | ||
1971 | vortex_connection_mix_adb(vortex, en, 0x11, mixers[1], ADB_CODECOUT(1)); | ||
1972 | #endif | ||
1973 | #endif | ||
1974 | } | ||
1975 | |||
1976 | static void | ||
1977 | vortex_connect_codecrec(vortex_t * vortex, int en, unsigned char mixin0, | ||
1978 | unsigned char mixin1) | ||
1979 | { | ||
1980 | /* | ||
1981 | Enable: 0x1, 0x1 | ||
1982 | Channel: 0x11, 0x11 | ||
1983 | ADB Source address: 0x48, 0x49 | ||
1984 | Destination Asp4Topology_0x9c,0x98 | ||
1985 | */ | ||
1986 | vortex_connection_adb_mixin(vortex, en, 0x11, ADB_CODECIN(0), mixin0); | ||
1987 | vortex_connection_adb_mixin(vortex, en, 0x11, ADB_CODECIN(1), mixin1); | ||
1988 | } | ||
1989 | |||
1990 | // Higher level ADB audio path (de)allocator. | ||
1991 | |||
1992 | /* Resource manager */ | ||
1993 | static int resnum[VORTEX_RESOURCE_LAST] = | ||
1994 | { NR_ADB, NR_SRC, NR_MIXIN, NR_MIXOUT, NR_A3D }; | ||
1995 | /* | ||
1996 | Checkout/Checkin resource of given type. | ||
1997 | resmap: resource map to be used. If NULL means that we want to allocate | ||
1998 | a DMA resource (root of all other resources of a dma channel). | ||
1999 | out: Mean checkout if != 0. Else mean Checkin resource. | ||
2000 | restype: Indicates type of resource to be checked in or out. | ||
2001 | */ | ||
2002 | static char | ||
2003 | vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype) | ||
2004 | { | ||
2005 | int i, qty = resnum[restype], resinuse = 0; | ||
2006 | |||
2007 | if (out) { | ||
2008 | /* Gather used resources by all streams. */ | ||
2009 | for (i = 0; i < NR_ADB; i++) { | ||
2010 | resinuse |= vortex->dma_adb[i].resources[restype]; | ||
2011 | } | ||
2012 | resinuse |= vortex->fixed_res[restype]; | ||
2013 | /* Find and take free resource. */ | ||
2014 | for (i = 0; i < qty; i++) { | ||
2015 | if ((resinuse & (1 << i)) == 0) { | ||
2016 | if (resmap != NULL) | ||
2017 | resmap[restype] |= (1 << i); | ||
2018 | else | ||
2019 | vortex->dma_adb[i].resources[restype] |= (1 << i); | ||
2020 | //printk("vortex: ResManager: type %d out %d\n", restype, i); | ||
2021 | return i; | ||
2022 | } | ||
2023 | } | ||
2024 | } else { | ||
2025 | if (resmap == NULL) | ||
2026 | return -EINVAL; | ||
2027 | /* Checkin first resource of type restype. */ | ||
2028 | for (i = 0; i < qty; i++) { | ||
2029 | if (resmap[restype] & (1 << i)) { | ||
2030 | resmap[restype] &= ~(1 << i); | ||
2031 | //printk("vortex: ResManager: type %d in %d\n",restype, i); | ||
2032 | return i; | ||
2033 | } | ||
2034 | } | ||
2035 | } | ||
2036 | printk("vortex: FATAL: ResManager: resource type %d exhausted.\n", restype); | ||
2037 | return -ENOMEM; | ||
2038 | } | ||
2039 | |||
2040 | /* Default Connections */ | ||
2041 | static int | ||
2042 | vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type); | ||
2043 | |||
2044 | static void vortex_connect_default(vortex_t * vortex, int en) | ||
2045 | { | ||
2046 | // Connect AC97 codec. | ||
2047 | vortex->mixplayb[0] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, | ||
2048 | VORTEX_RESOURCE_MIXOUT); | ||
2049 | vortex->mixplayb[1] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, | ||
2050 | VORTEX_RESOURCE_MIXOUT); | ||
2051 | if (VORTEX_IS_QUAD(vortex)) { | ||
2052 | vortex->mixplayb[2] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, | ||
2053 | VORTEX_RESOURCE_MIXOUT); | ||
2054 | vortex->mixplayb[3] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, | ||
2055 | VORTEX_RESOURCE_MIXOUT); | ||
2056 | } | ||
2057 | vortex_connect_codecplay(vortex, en, vortex->mixplayb); | ||
2058 | |||
2059 | vortex->mixcapt[0] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, | ||
2060 | VORTEX_RESOURCE_MIXIN); | ||
2061 | vortex->mixcapt[1] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, | ||
2062 | VORTEX_RESOURCE_MIXIN); | ||
2063 | vortex_connect_codecrec(vortex, en, MIX_CAPT(0), MIX_CAPT(1)); | ||
2064 | |||
2065 | // Connect SPDIF | ||
2066 | #ifndef CHIP_AU8820 | ||
2067 | vortex->mixspdif[0] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, | ||
2068 | VORTEX_RESOURCE_MIXOUT); | ||
2069 | vortex->mixspdif[1] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, | ||
2070 | VORTEX_RESOURCE_MIXOUT); | ||
2071 | vortex_connection_mix_adb(vortex, en, 0x14, vortex->mixspdif[0], | ||
2072 | ADB_SPDIFOUT(0)); | ||
2073 | vortex_connection_mix_adb(vortex, en, 0x14, vortex->mixspdif[1], | ||
2074 | ADB_SPDIFOUT(1)); | ||
2075 | #endif | ||
2076 | // Connect WT | ||
2077 | #ifndef CHIP_AU8810 | ||
2078 | vortex_wt_connect(vortex, en); | ||
2079 | #endif | ||
2080 | // A3D (crosstalk canceler and A3D slices). AU8810 disabled for now. | ||
2081 | #ifndef CHIP_AU8820 | ||
2082 | vortex_Vort3D_connect(vortex, en); | ||
2083 | #endif | ||
2084 | // Connect I2S | ||
2085 | |||
2086 | // Connect DSP interface for SQ3500 turbo (not here i think...) | ||
2087 | |||
2088 | // Connect AC98 modem codec | ||
2089 | |||
2090 | } | ||
2091 | |||
2092 | /* | ||
2093 | Allocate nr_ch pcm audio routes if dma < 0. If dma >= 0, existing routes | ||
2094 | are deallocated. | ||
2095 | dma: DMA engine routes to be deallocated when dma >= 0. | ||
2096 | nr_ch: Number of channels to be de/allocated. | ||
2097 | dir: direction of stream. Uses same values as substream->stream. | ||
2098 | type: Type of audio output/source (codec, spdif, i2s, dsp, etc) | ||
2099 | Return: Return allocated DMA or same DMA passed as "dma" when dma >= 0. | ||
2100 | */ | ||
2101 | static int | ||
2102 | vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type) | ||
2103 | { | ||
2104 | stream_t *stream; | ||
2105 | int i, en; | ||
2106 | |||
2107 | if ((nr_ch == 3) | ||
2108 | || ((dir == SNDRV_PCM_STREAM_CAPTURE) && (nr_ch > 2))) | ||
2109 | return -EBUSY; | ||
2110 | |||
2111 | if (dma >= 0) { | ||
2112 | en = 0; | ||
2113 | vortex_adb_checkinout(vortex, | ||
2114 | vortex->dma_adb[dma].resources, en, | ||
2115 | VORTEX_RESOURCE_DMA); | ||
2116 | } else { | ||
2117 | en = 1; | ||
2118 | if ((dma = | ||
2119 | vortex_adb_checkinout(vortex, NULL, en, | ||
2120 | VORTEX_RESOURCE_DMA)) < 0) | ||
2121 | return -EBUSY; | ||
2122 | } | ||
2123 | |||
2124 | stream = &vortex->dma_adb[dma]; | ||
2125 | stream->dma = dma; | ||
2126 | stream->dir = dir; | ||
2127 | stream->type = type; | ||
2128 | |||
2129 | /* PLAYBACK ROUTES. */ | ||
2130 | if (dir == SNDRV_PCM_STREAM_PLAYBACK) { | ||
2131 | int src[4], mix[4], ch_top; | ||
2132 | #ifndef CHIP_AU8820 | ||
2133 | int a3d = 0; | ||
2134 | #endif | ||
2135 | /* Get SRC and MIXER hardware resources. */ | ||
2136 | if (stream->type != VORTEX_PCM_SPDIF) { | ||
2137 | for (i = 0; i < nr_ch; i++) { | ||
2138 | if ((src[i] = vortex_adb_checkinout(vortex, | ||
2139 | stream->resources, en, | ||
2140 | VORTEX_RESOURCE_SRC)) < 0) { | ||
2141 | memset(stream->resources, 0, | ||
2142 | sizeof(unsigned char) * | ||
2143 | VORTEX_RESOURCE_LAST); | ||
2144 | return -EBUSY; | ||
2145 | } | ||
2146 | if (stream->type != VORTEX_PCM_A3D) { | ||
2147 | if ((mix[i] = vortex_adb_checkinout(vortex, | ||
2148 | stream->resources, | ||
2149 | en, | ||
2150 | VORTEX_RESOURCE_MIXIN)) < 0) { | ||
2151 | memset(stream->resources, | ||
2152 | 0, | ||
2153 | sizeof(unsigned char) * VORTEX_RESOURCE_LAST); | ||
2154 | return -EBUSY; | ||
2155 | } | ||
2156 | } | ||
2157 | } | ||
2158 | } | ||
2159 | #ifndef CHIP_AU8820 | ||
2160 | if (stream->type == VORTEX_PCM_A3D) { | ||
2161 | if ((a3d = | ||
2162 | vortex_adb_checkinout(vortex, | ||
2163 | stream->resources, en, | ||
2164 | VORTEX_RESOURCE_A3D)) < 0) { | ||
2165 | memset(stream->resources, 0, | ||
2166 | sizeof(unsigned char) * | ||
2167 | VORTEX_RESOURCE_LAST); | ||
2168 | printk("vortex: out of A3D sources. Sorry\n"); | ||
2169 | return -EBUSY; | ||
2170 | } | ||
2171 | /* (De)Initialize A3D hardware source. */ | ||
2172 | vortex_Vort3D_InitializeSource(&(vortex->a3d[a3d]), en); | ||
2173 | } | ||
2174 | /* Make SPDIF out exclusive to "spdif" device when in use. */ | ||
2175 | if ((stream->type == VORTEX_PCM_SPDIF) && (en)) { | ||
2176 | vortex_route(vortex, 0, 0x14, | ||
2177 | ADB_MIXOUT(vortex->mixspdif[0]), | ||
2178 | ADB_SPDIFOUT(0)); | ||
2179 | vortex_route(vortex, 0, 0x14, | ||
2180 | ADB_MIXOUT(vortex->mixspdif[1]), | ||
2181 | ADB_SPDIFOUT(1)); | ||
2182 | } | ||
2183 | #endif | ||
2184 | /* Make playback routes. */ | ||
2185 | for (i = 0; i < nr_ch; i++) { | ||
2186 | if (stream->type == VORTEX_PCM_ADB) { | ||
2187 | vortex_connection_adbdma_src(vortex, en, | ||
2188 | src[nr_ch - 1], | ||
2189 | dma, | ||
2190 | src[i]); | ||
2191 | vortex_connection_src_mixin(vortex, en, | ||
2192 | 0x11, src[i], | ||
2193 | mix[i]); | ||
2194 | vortex_connection_mixin_mix(vortex, en, | ||
2195 | mix[i], | ||
2196 | MIX_PLAYB(i), 0); | ||
2197 | #ifndef CHIP_AU8820 | ||
2198 | vortex_connection_mixin_mix(vortex, en, | ||
2199 | mix[i], | ||
2200 | MIX_SPDIF(i % 2), 0); | ||
2201 | vortex_mix_setinputvolumebyte(vortex, | ||
2202 | MIX_SPDIF(i % 2), | ||
2203 | mix[i], | ||
2204 | MIX_DEFIGAIN); | ||
2205 | #endif | ||
2206 | } | ||
2207 | #ifndef CHIP_AU8820 | ||
2208 | if (stream->type == VORTEX_PCM_A3D) { | ||
2209 | vortex_connection_adbdma_src(vortex, en, | ||
2210 | src[nr_ch - 1], | ||
2211 | dma, | ||
2212 | src[i]); | ||
2213 | vortex_route(vortex, en, 0x11, ADB_SRCOUT(src[i]), ADB_A3DIN(a3d)); | ||
2214 | /* XTalk test. */ | ||
2215 | //vortex_route(vortex, en, 0x11, dma, ADB_XTALKIN(i?9:4)); | ||
2216 | //vortex_route(vortex, en, 0x11, ADB_SRCOUT(src[i]), ADB_XTALKIN(i?4:9)); | ||
2217 | } | ||
2218 | if (stream->type == VORTEX_PCM_SPDIF) | ||
2219 | vortex_route(vortex, en, 0x14, | ||
2220 | ADB_DMA(stream->dma), | ||
2221 | ADB_SPDIFOUT(i)); | ||
2222 | #endif | ||
2223 | } | ||
2224 | if (stream->type != VORTEX_PCM_SPDIF && stream->type != VORTEX_PCM_A3D) { | ||
2225 | ch_top = (VORTEX_IS_QUAD(vortex) ? 4 : 2); | ||
2226 | for (i = nr_ch; i < ch_top; i++) { | ||
2227 | vortex_connection_mixin_mix(vortex, en, | ||
2228 | mix[i % nr_ch], | ||
2229 | MIX_PLAYB(i), 0); | ||
2230 | #ifndef CHIP_AU8820 | ||
2231 | vortex_connection_mixin_mix(vortex, en, | ||
2232 | mix[i % nr_ch], | ||
2233 | MIX_SPDIF(i % 2), | ||
2234 | 0); | ||
2235 | vortex_mix_setinputvolumebyte(vortex, | ||
2236 | MIX_SPDIF(i % 2), | ||
2237 | mix[i % nr_ch], | ||
2238 | MIX_DEFIGAIN); | ||
2239 | #endif | ||
2240 | } | ||
2241 | } | ||
2242 | #ifndef CHIP_AU8820 | ||
2243 | else { | ||
2244 | if (nr_ch == 1 && stream->type == VORTEX_PCM_SPDIF) | ||
2245 | vortex_route(vortex, en, 0x14, | ||
2246 | ADB_DMA(stream->dma), | ||
2247 | ADB_SPDIFOUT(1)); | ||
2248 | } | ||
2249 | /* Reconnect SPDIF out when "spdif" device is down. */ | ||
2250 | if ((stream->type == VORTEX_PCM_SPDIF) && (!en)) { | ||
2251 | vortex_route(vortex, 1, 0x14, | ||
2252 | ADB_MIXOUT(vortex->mixspdif[0]), | ||
2253 | ADB_SPDIFOUT(0)); | ||
2254 | vortex_route(vortex, 1, 0x14, | ||
2255 | ADB_MIXOUT(vortex->mixspdif[1]), | ||
2256 | ADB_SPDIFOUT(1)); | ||
2257 | } | ||
2258 | #endif | ||
2259 | /* CAPTURE ROUTES. */ | ||
2260 | } else { | ||
2261 | int src[2], mix[2]; | ||
2262 | |||
2263 | /* Get SRC and MIXER hardware resources. */ | ||
2264 | for (i = 0; i < nr_ch; i++) { | ||
2265 | if ((mix[i] = | ||
2266 | vortex_adb_checkinout(vortex, | ||
2267 | stream->resources, en, | ||
2268 | VORTEX_RESOURCE_MIXOUT)) | ||
2269 | < 0) { | ||
2270 | memset(stream->resources, 0, | ||
2271 | sizeof(unsigned char) * | ||
2272 | VORTEX_RESOURCE_LAST); | ||
2273 | return -EBUSY; | ||
2274 | } | ||
2275 | if ((src[i] = | ||
2276 | vortex_adb_checkinout(vortex, | ||
2277 | stream->resources, en, | ||
2278 | VORTEX_RESOURCE_SRC)) < 0) { | ||
2279 | memset(stream->resources, 0, | ||
2280 | sizeof(unsigned char) * | ||
2281 | VORTEX_RESOURCE_LAST); | ||
2282 | return -EBUSY; | ||
2283 | } | ||
2284 | } | ||
2285 | |||
2286 | /* Make capture routes. */ | ||
2287 | vortex_connection_mixin_mix(vortex, en, MIX_CAPT(0), mix[0], 0); | ||
2288 | vortex_connection_mix_src(vortex, en, 0x11, mix[0], src[0]); | ||
2289 | if (nr_ch == 1) { | ||
2290 | vortex_connection_mixin_mix(vortex, en, | ||
2291 | MIX_CAPT(1), mix[0], 0); | ||
2292 | vortex_connection_src_adbdma(vortex, en, | ||
2293 | src[0], | ||
2294 | src[0], dma); | ||
2295 | } else { | ||
2296 | vortex_connection_mixin_mix(vortex, en, | ||
2297 | MIX_CAPT(1), mix[1], 0); | ||
2298 | vortex_connection_mix_src(vortex, en, 0x11, mix[1], | ||
2299 | src[1]); | ||
2300 | vortex_connection_src_src_adbdma(vortex, en, | ||
2301 | src[1], src[0], | ||
2302 | src[1], dma); | ||
2303 | } | ||
2304 | } | ||
2305 | vortex->dma_adb[dma].nr_ch = nr_ch; | ||
2306 | |||
2307 | #if 0 | ||
2308 | /* AC97 Codec channel setup. FIXME: this has no effect on some cards !! */ | ||
2309 | if (nr_ch < 4) { | ||
2310 | /* Copy stereo to rear channel (surround) */ | ||
2311 | snd_ac97_write_cache(vortex->codec, | ||
2312 | AC97_SIGMATEL_DAC2INVERT, | ||
2313 | snd_ac97_read(vortex->codec, | ||
2314 | AC97_SIGMATEL_DAC2INVERT) | ||
2315 | | 4); | ||
2316 | } else { | ||
2317 | /* Allow separate front and rear channels. */ | ||
2318 | snd_ac97_write_cache(vortex->codec, | ||
2319 | AC97_SIGMATEL_DAC2INVERT, | ||
2320 | snd_ac97_read(vortex->codec, | ||
2321 | AC97_SIGMATEL_DAC2INVERT) | ||
2322 | & ~((u32) | ||
2323 | 4)); | ||
2324 | } | ||
2325 | #endif | ||
2326 | return dma; | ||
2327 | } | ||
2328 | |||
2329 | /* | ||
2330 | Set the SampleRate of the SRC's attached to the given DMA engine. | ||
2331 | */ | ||
2332 | static void | ||
2333 | vortex_adb_setsrc(vortex_t * vortex, int adbdma, unsigned int rate, int dir) | ||
2334 | { | ||
2335 | stream_t *stream = &(vortex->dma_adb[adbdma]); | ||
2336 | int i, cvrt; | ||
2337 | |||
2338 | /* dir=1:play ; dir=0:rec */ | ||
2339 | if (dir) | ||
2340 | cvrt = SRC_RATIO(rate, 48000); | ||
2341 | else | ||
2342 | cvrt = SRC_RATIO(48000, rate); | ||
2343 | |||
2344 | /* Setup SRC's */ | ||
2345 | for (i = 0; i < NR_SRC; i++) { | ||
2346 | if (stream->resources[VORTEX_RESOURCE_SRC] & (1 << i)) | ||
2347 | vortex_src_setupchannel(vortex, i, cvrt, 0, 0, i, dir, 1, cvrt, dir); | ||
2348 | } | ||
2349 | } | ||
2350 | |||
2351 | // Timer and ISR functions. | ||
2352 | |||
2353 | static void vortex_settimer(vortex_t * vortex, int period) | ||
2354 | { | ||
2355 | //set the timer period to <period> 48000ths of a second. | ||
2356 | hwwrite(vortex->mmio, VORTEX_IRQ_STAT, period); | ||
2357 | } | ||
2358 | |||
2359 | #if 0 | ||
2360 | static void vortex_enable_timer_int(vortex_t * card) | ||
2361 | { | ||
2362 | hwwrite(card->mmio, VORTEX_IRQ_CTRL, | ||
2363 | hwread(card->mmio, VORTEX_IRQ_CTRL) | IRQ_TIMER | 0x60); | ||
2364 | } | ||
2365 | |||
2366 | static void vortex_disable_timer_int(vortex_t * card) | ||
2367 | { | ||
2368 | hwwrite(card->mmio, VORTEX_IRQ_CTRL, | ||
2369 | hwread(card->mmio, VORTEX_IRQ_CTRL) & ~IRQ_TIMER); | ||
2370 | } | ||
2371 | |||
2372 | #endif | ||
2373 | static void vortex_enable_int(vortex_t * card) | ||
2374 | { | ||
2375 | // CAsp4ISR__EnableVortexInt_void_ | ||
2376 | hwwrite(card->mmio, VORTEX_CTRL, | ||
2377 | hwread(card->mmio, VORTEX_CTRL) | CTRL_IRQ_ENABLE); | ||
2378 | hwwrite(card->mmio, VORTEX_IRQ_CTRL, | ||
2379 | (hwread(card->mmio, VORTEX_IRQ_CTRL) & 0xffffefc0) | 0x24); | ||
2380 | } | ||
2381 | |||
2382 | static void vortex_disable_int(vortex_t * card) | ||
2383 | { | ||
2384 | hwwrite(card->mmio, VORTEX_CTRL, | ||
2385 | hwread(card->mmio, VORTEX_CTRL) & ~CTRL_IRQ_ENABLE); | ||
2386 | } | ||
2387 | |||
2388 | static irqreturn_t vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
2389 | { | ||
2390 | vortex_t *vortex = dev_id; | ||
2391 | int i, handled; | ||
2392 | u32 source; | ||
2393 | |||
2394 | //check if the interrupt is ours. | ||
2395 | if (!(hwread(vortex->mmio, VORTEX_STAT) & 0x1)) | ||
2396 | return IRQ_NONE; | ||
2397 | |||
2398 | // This is the Interrrupt Enable flag we set before (consistency check). | ||
2399 | if (!(hwread(vortex->mmio, VORTEX_CTRL) & CTRL_IRQ_ENABLE)) | ||
2400 | return IRQ_NONE; | ||
2401 | |||
2402 | source = hwread(vortex->mmio, VORTEX_IRQ_SOURCE); | ||
2403 | // Reset IRQ flags. | ||
2404 | hwwrite(vortex->mmio, VORTEX_IRQ_SOURCE, source); | ||
2405 | hwread(vortex->mmio, VORTEX_IRQ_SOURCE); | ||
2406 | // Is at least one IRQ flag set? | ||
2407 | if (source == 0) { | ||
2408 | printk(KERN_ERR "vortex: missing irq source\n"); | ||
2409 | return IRQ_NONE; | ||
2410 | } | ||
2411 | |||
2412 | handled = 0; | ||
2413 | // Attend every interrupt source. | ||
2414 | if (unlikely(source & IRQ_ERR_MASK)) { | ||
2415 | if (source & IRQ_FATAL) { | ||
2416 | printk(KERN_ERR "vortex: IRQ fatal error\n"); | ||
2417 | } | ||
2418 | if (source & IRQ_PARITY) { | ||
2419 | printk(KERN_ERR "vortex: IRQ parity error\n"); | ||
2420 | } | ||
2421 | if (source & IRQ_REG) { | ||
2422 | printk(KERN_ERR "vortex: IRQ reg error\n"); | ||
2423 | } | ||
2424 | if (source & IRQ_FIFO) { | ||
2425 | printk(KERN_ERR "vortex: IRQ fifo error\n"); | ||
2426 | } | ||
2427 | if (source & IRQ_DMA) { | ||
2428 | printk(KERN_ERR "vortex: IRQ dma error\n"); | ||
2429 | } | ||
2430 | handled = 1; | ||
2431 | } | ||
2432 | if (source & IRQ_PCMOUT) { | ||
2433 | /* ALSA period acknowledge. */ | ||
2434 | spin_lock(&vortex->lock); | ||
2435 | for (i = 0; i < NR_ADB; i++) { | ||
2436 | if (vortex->dma_adb[i].fifo_status == FIFO_START) { | ||
2437 | if (vortex_adbdma_bufshift(vortex, i)) ; | ||
2438 | spin_unlock(&vortex->lock); | ||
2439 | snd_pcm_period_elapsed(vortex->dma_adb[i]. | ||
2440 | substream); | ||
2441 | spin_lock(&vortex->lock); | ||
2442 | } | ||
2443 | } | ||
2444 | #ifndef CHIP_AU8810 | ||
2445 | for (i = 0; i < NR_WT; i++) { | ||
2446 | if (vortex->dma_wt[i].fifo_status == FIFO_START) { | ||
2447 | if (vortex_wtdma_bufshift(vortex, i)) ; | ||
2448 | spin_unlock(&vortex->lock); | ||
2449 | snd_pcm_period_elapsed(vortex->dma_wt[i]. | ||
2450 | substream); | ||
2451 | spin_lock(&vortex->lock); | ||
2452 | } | ||
2453 | } | ||
2454 | #endif | ||
2455 | spin_unlock(&vortex->lock); | ||
2456 | handled = 1; | ||
2457 | } | ||
2458 | //Acknowledge the Timer interrupt | ||
2459 | if (source & IRQ_TIMER) { | ||
2460 | hwread(vortex->mmio, VORTEX_IRQ_STAT); | ||
2461 | handled = 1; | ||
2462 | } | ||
2463 | if (source & IRQ_MIDI) { | ||
2464 | snd_mpu401_uart_interrupt(vortex->irq, | ||
2465 | vortex->rmidi->private_data, regs); | ||
2466 | handled = 1; | ||
2467 | } | ||
2468 | |||
2469 | if (!handled) { | ||
2470 | printk(KERN_ERR "vortex: unknown irq source %x\n", source); | ||
2471 | } | ||
2472 | return IRQ_RETVAL(handled); | ||
2473 | } | ||
2474 | |||
2475 | /* Codec */ | ||
2476 | |||
2477 | #define POLL_COUNT 1000 | ||
2478 | static void vortex_codec_init(vortex_t * vortex) | ||
2479 | { | ||
2480 | int i; | ||
2481 | |||
2482 | for (i = 0; i < 32; i++) { | ||
2483 | /* the windows driver writes -i, so we write -i */ | ||
2484 | hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), -i); | ||
2485 | msleep(2); | ||
2486 | } | ||
2487 | if (0) { | ||
2488 | hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x8068); | ||
2489 | msleep(1); | ||
2490 | hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00e8); | ||
2491 | msleep(1); | ||
2492 | } else { | ||
2493 | hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00a8); | ||
2494 | msleep(2); | ||
2495 | hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x80a8); | ||
2496 | msleep(2); | ||
2497 | hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x80e8); | ||
2498 | msleep(2); | ||
2499 | hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x80a8); | ||
2500 | msleep(2); | ||
2501 | hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00a8); | ||
2502 | msleep(2); | ||
2503 | hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00e8); | ||
2504 | } | ||
2505 | for (i = 0; i < 32; i++) { | ||
2506 | hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), -i); | ||
2507 | msleep(5); | ||
2508 | } | ||
2509 | hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0xe8); | ||
2510 | msleep(1); | ||
2511 | /* Enable codec channels 0 and 1. */ | ||
2512 | hwwrite(vortex->mmio, VORTEX_CODEC_EN, | ||
2513 | hwread(vortex->mmio, VORTEX_CODEC_EN) | EN_CODEC); | ||
2514 | } | ||
2515 | |||
2516 | static void | ||
2517 | vortex_codec_write(ac97_t * codec, unsigned short addr, unsigned short data) | ||
2518 | { | ||
2519 | |||
2520 | vortex_t *card = (vortex_t *) codec->private_data; | ||
2521 | unsigned int lifeboat = 0; | ||
2522 | |||
2523 | /* wait for transactions to clear */ | ||
2524 | while (!(hwread(card->mmio, VORTEX_CODEC_CTRL) & 0x100)) { | ||
2525 | udelay(100); | ||
2526 | if (lifeboat++ > POLL_COUNT) { | ||
2527 | printk(KERN_ERR "vortex: ac97 codec stuck busy\n"); | ||
2528 | return; | ||
2529 | } | ||
2530 | } | ||
2531 | /* write register */ | ||
2532 | hwwrite(card->mmio, VORTEX_CODEC_IO, | ||
2533 | ((addr << VORTEX_CODEC_ADDSHIFT) & VORTEX_CODEC_ADDMASK) | | ||
2534 | ((data << VORTEX_CODEC_DATSHIFT) & VORTEX_CODEC_DATMASK) | | ||
2535 | VORTEX_CODEC_WRITE); | ||
2536 | |||
2537 | /* Flush Caches. */ | ||
2538 | hwread(card->mmio, VORTEX_CODEC_IO); | ||
2539 | } | ||
2540 | |||
2541 | static unsigned short vortex_codec_read(ac97_t * codec, unsigned short addr) | ||
2542 | { | ||
2543 | |||
2544 | vortex_t *card = (vortex_t *) codec->private_data; | ||
2545 | u32 read_addr, data; | ||
2546 | unsigned lifeboat = 0; | ||
2547 | |||
2548 | /* wait for transactions to clear */ | ||
2549 | while (!(hwread(card->mmio, VORTEX_CODEC_CTRL) & 0x100)) { | ||
2550 | udelay(100); | ||
2551 | if (lifeboat++ > POLL_COUNT) { | ||
2552 | printk(KERN_ERR "vortex: ac97 codec stuck busy\n"); | ||
2553 | return 0xffff; | ||
2554 | } | ||
2555 | } | ||
2556 | /* set up read address */ | ||
2557 | read_addr = ((addr << VORTEX_CODEC_ADDSHIFT) & VORTEX_CODEC_ADDMASK); | ||
2558 | hwwrite(card->mmio, VORTEX_CODEC_IO, read_addr); | ||
2559 | |||
2560 | /* wait for address */ | ||
2561 | do { | ||
2562 | udelay(100); | ||
2563 | data = hwread(card->mmio, VORTEX_CODEC_IO); | ||
2564 | if (lifeboat++ > POLL_COUNT) { | ||
2565 | printk(KERN_ERR "vortex: ac97 address never arrived\n"); | ||
2566 | return 0xffff; | ||
2567 | } | ||
2568 | } while ((data & VORTEX_CODEC_ADDMASK) != | ||
2569 | (addr << VORTEX_CODEC_ADDSHIFT)); | ||
2570 | |||
2571 | /* return data. */ | ||
2572 | return (u16) (data & VORTEX_CODEC_DATMASK); | ||
2573 | } | ||
2574 | |||
2575 | /* SPDIF support */ | ||
2576 | |||
2577 | static void vortex_spdif_init(vortex_t * vortex, int spdif_sr, int spdif_mode) | ||
2578 | { | ||
2579 | int i, this_38 = 0, this_04 = 0, this_08 = 0, this_0c = 0; | ||
2580 | |||
2581 | /* CAsp4Spdif::InitializeSpdifHardware(void) */ | ||
2582 | hwwrite(vortex->mmio, VORTEX_SPDIF_FLAGS, | ||
2583 | hwread(vortex->mmio, VORTEX_SPDIF_FLAGS) & 0xfff3fffd); | ||
2584 | //for (i=0x291D4; i<0x29200; i+=4) | ||
2585 | for (i = 0; i < 11; i++) | ||
2586 | hwwrite(vortex->mmio, VORTEX_SPDIF_CFG1 + (i << 2), 0); | ||
2587 | //hwwrite(vortex->mmio, 0x29190, hwread(vortex->mmio, 0x29190) | 0xc0000); | ||
2588 | hwwrite(vortex->mmio, VORTEX_CODEC_EN, | ||
2589 | hwread(vortex->mmio, VORTEX_CODEC_EN) | EN_SPDIF); | ||
2590 | |||
2591 | /* CAsp4Spdif::ProgramSRCInHardware(enum SPDIF_SR,enum SPDIFMODE) */ | ||
2592 | if (this_04 && this_08) { | ||
2593 | int edi; | ||
2594 | |||
2595 | i = (((0x5DC00000 / spdif_sr) + 1) >> 1); | ||
2596 | if (i > 0x800) { | ||
2597 | if (i < 0x1ffff) | ||
2598 | edi = (i >> 1); | ||
2599 | else | ||
2600 | edi = 0x1ffff; | ||
2601 | } else { | ||
2602 | i = edi = 0x800; | ||
2603 | } | ||
2604 | /* this_04 and this_08 are the CASp4Src's (samplerate converters) */ | ||
2605 | vortex_src_setupchannel(vortex, this_04, edi, 0, 1, | ||
2606 | this_0c, 1, 0, edi, 1); | ||
2607 | vortex_src_setupchannel(vortex, this_08, edi, 0, 1, | ||
2608 | this_0c, 1, 0, edi, 1); | ||
2609 | } | ||
2610 | |||
2611 | i = spdif_sr; | ||
2612 | spdif_sr |= 0x8c; | ||
2613 | switch (i) { | ||
2614 | case 32000: | ||
2615 | this_38 &= 0xFFFFFFFE; | ||
2616 | this_38 &= 0xFFFFFFFD; | ||
2617 | this_38 &= 0xF3FFFFFF; | ||
2618 | this_38 |= 0x03000000; /* set 32khz samplerate */ | ||
2619 | this_38 &= 0xFFFFFF3F; | ||
2620 | spdif_sr &= 0xFFFFFFFD; | ||
2621 | spdif_sr |= 1; | ||
2622 | break; | ||
2623 | case 44100: | ||
2624 | this_38 &= 0xFFFFFFFE; | ||
2625 | this_38 &= 0xFFFFFFFD; | ||
2626 | this_38 &= 0xF0FFFFFF; | ||
2627 | this_38 |= 0x03000000; | ||
2628 | this_38 &= 0xFFFFFF3F; | ||
2629 | spdif_sr &= 0xFFFFFFFC; | ||
2630 | break; | ||
2631 | case 48000: | ||
2632 | if (spdif_mode == 1) { | ||
2633 | this_38 &= 0xFFFFFFFE; | ||
2634 | this_38 &= 0xFFFFFFFD; | ||
2635 | this_38 &= 0xF2FFFFFF; | ||
2636 | this_38 |= 0x02000000; /* set 48khz samplerate */ | ||
2637 | this_38 &= 0xFFFFFF3F; | ||
2638 | } else { | ||
2639 | /* J. Gordon Wolfe: I think this stuff is for AC3 */ | ||
2640 | this_38 |= 0x00000003; | ||
2641 | this_38 &= 0xFFFFFFBF; | ||
2642 | this_38 |= 0x80; | ||
2643 | } | ||
2644 | spdif_sr |= 2; | ||
2645 | spdif_sr &= 0xFFFFFFFE; | ||
2646 | break; | ||
2647 | |||
2648 | } | ||
2649 | /* looks like the next 2 lines transfer a 16-bit value into 2 8-bit | ||
2650 | registers. seems to be for the standard IEC/SPDIF initialization | ||
2651 | stuff */ | ||
2652 | hwwrite(vortex->mmio, VORTEX_SPDIF_CFG0, this_38 & 0xffff); | ||
2653 | hwwrite(vortex->mmio, VORTEX_SPDIF_CFG1, this_38 >> 0x10); | ||
2654 | hwwrite(vortex->mmio, VORTEX_SPDIF_SMPRATE, spdif_sr); | ||
2655 | } | ||
2656 | |||
2657 | /* Initialization */ | ||
2658 | |||
2659 | static int vortex_core_init(vortex_t * vortex) | ||
2660 | { | ||
2661 | |||
2662 | printk(KERN_INFO "Vortex: init.... "); | ||
2663 | /* Hardware Init. */ | ||
2664 | hwwrite(vortex->mmio, VORTEX_CTRL, 0xffffffff); | ||
2665 | msleep(5); | ||
2666 | hwwrite(vortex->mmio, VORTEX_CTRL, | ||
2667 | hwread(vortex->mmio, VORTEX_CTRL) & 0xffdfffff); | ||
2668 | msleep(5); | ||
2669 | /* Reset IRQ flags */ | ||
2670 | hwwrite(vortex->mmio, VORTEX_IRQ_SOURCE, 0xffffffff); | ||
2671 | hwread(vortex->mmio, VORTEX_IRQ_STAT); | ||
2672 | |||
2673 | vortex_codec_init(vortex); | ||
2674 | |||
2675 | #ifdef CHIP_AU8830 | ||
2676 | hwwrite(vortex->mmio, VORTEX_CTRL, | ||
2677 | hwread(vortex->mmio, VORTEX_CTRL) | 0x1000000); | ||
2678 | #endif | ||
2679 | |||
2680 | /* Init audio engine. */ | ||
2681 | vortex_adbdma_init(vortex); | ||
2682 | hwwrite(vortex->mmio, VORTEX_ENGINE_CTRL, 0x0); //, 0xc83c7e58, 0xc5f93e58 | ||
2683 | vortex_adb_init(vortex); | ||
2684 | /* Init processing blocks. */ | ||
2685 | vortex_fifo_init(vortex); | ||
2686 | vortex_mixer_init(vortex); | ||
2687 | vortex_srcblock_init(vortex); | ||
2688 | #ifndef CHIP_AU8820 | ||
2689 | vortex_eq_init(vortex); | ||
2690 | vortex_spdif_init(vortex, 48000, 1); | ||
2691 | vortex_Vort3D(vortex, 1); | ||
2692 | #endif | ||
2693 | #ifndef CHIP_AU8810 | ||
2694 | vortex_wt_init(vortex); | ||
2695 | #endif | ||
2696 | // Moved to au88x0.c | ||
2697 | //vortex_connect_default(vortex, 1); | ||
2698 | |||
2699 | vortex_settimer(vortex, 0x90); | ||
2700 | // Enable Interrupts. | ||
2701 | // vortex_enable_int() must be first !! | ||
2702 | // hwwrite(vortex->mmio, VORTEX_IRQ_CTRL, 0); | ||
2703 | // vortex_enable_int(vortex); | ||
2704 | //vortex_enable_timer_int(vortex); | ||
2705 | //vortex_disable_timer_int(vortex); | ||
2706 | |||
2707 | printk(KERN_INFO "done.\n"); | ||
2708 | spin_lock_init(&vortex->lock); | ||
2709 | |||
2710 | return 0; | ||
2711 | } | ||
2712 | |||
2713 | static int vortex_core_shutdown(vortex_t * vortex) | ||
2714 | { | ||
2715 | |||
2716 | printk(KERN_INFO "Vortex: shutdown..."); | ||
2717 | #ifndef CHIP_AU8820 | ||
2718 | vortex_eq_free(vortex); | ||
2719 | vortex_Vort3D(vortex, 0); | ||
2720 | #endif | ||
2721 | //vortex_disable_timer_int(vortex); | ||
2722 | vortex_disable_int(vortex); | ||
2723 | vortex_connect_default(vortex, 0); | ||
2724 | /* Reset all DMA fifos. */ | ||
2725 | vortex_fifo_init(vortex); | ||
2726 | /* Erase all audio routes. */ | ||
2727 | vortex_adb_init(vortex); | ||
2728 | |||
2729 | /* Disable MPU401 */ | ||
2730 | //hwwrite(vortex->mmio, VORTEX_IRQ_CTRL, hwread(vortex->mmio, VORTEX_IRQ_CTRL) & ~IRQ_MIDI); | ||
2731 | //hwwrite(vortex->mmio, VORTEX_CTRL, hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_EN); | ||
2732 | |||
2733 | hwwrite(vortex->mmio, VORTEX_IRQ_CTRL, 0); | ||
2734 | hwwrite(vortex->mmio, VORTEX_CTRL, 0); | ||
2735 | msleep(5); | ||
2736 | hwwrite(vortex->mmio, VORTEX_IRQ_SOURCE, 0xffff); | ||
2737 | |||
2738 | printk(KERN_INFO "done.\n"); | ||
2739 | return 0; | ||
2740 | } | ||
2741 | |||
2742 | /* Alsa support. */ | ||
2743 | |||
2744 | static int vortex_alsafmt_aspfmt(int alsafmt) | ||
2745 | { | ||
2746 | int fmt; | ||
2747 | |||
2748 | switch (alsafmt) { | ||
2749 | case SNDRV_PCM_FORMAT_U8: | ||
2750 | fmt = 0x1; | ||
2751 | break; | ||
2752 | case SNDRV_PCM_FORMAT_MU_LAW: | ||
2753 | fmt = 0x2; | ||
2754 | break; | ||
2755 | case SNDRV_PCM_FORMAT_A_LAW: | ||
2756 | fmt = 0x3; | ||
2757 | break; | ||
2758 | case SNDRV_PCM_FORMAT_SPECIAL: | ||
2759 | fmt = 0x4; /* guess. */ | ||
2760 | break; | ||
2761 | case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE: | ||
2762 | fmt = 0x5; /* guess. */ | ||
2763 | break; | ||
2764 | case SNDRV_PCM_FORMAT_S16_LE: | ||
2765 | fmt = 0x8; | ||
2766 | break; | ||
2767 | case SNDRV_PCM_FORMAT_S16_BE: | ||
2768 | fmt = 0x9; /* check this... */ | ||
2769 | break; | ||
2770 | default: | ||
2771 | fmt = 0x8; | ||
2772 | printk(KERN_ERR "vortex: format unsupported %d\n", alsafmt); | ||
2773 | break; | ||
2774 | } | ||
2775 | return fmt; | ||
2776 | } | ||
2777 | |||
2778 | /* Some not yet useful translations. */ | ||
2779 | #if 0 | ||
2780 | typedef enum { | ||
2781 | ASPFMTLINEAR16 = 0, /* 0x8 */ | ||
2782 | ASPFMTLINEAR8, /* 0x1 */ | ||
2783 | ASPFMTULAW, /* 0x2 */ | ||
2784 | ASPFMTALAW, /* 0x3 */ | ||
2785 | ASPFMTSPORT, /* ? */ | ||
2786 | ASPFMTSPDIF, /* ? */ | ||
2787 | } ASPENCODING; | ||
2788 | |||
2789 | static int | ||
2790 | vortex_translateformat(vortex_t * vortex, char bits, char nch, int encod) | ||
2791 | { | ||
2792 | int a, this_194; | ||
2793 | |||
2794 | if ((bits != 8) || (bits != 16)) | ||
2795 | return -1; | ||
2796 | |||
2797 | switch (encod) { | ||
2798 | case 0: | ||
2799 | if (bits == 0x10) | ||
2800 | a = 8; // 16 bit | ||
2801 | break; | ||
2802 | case 1: | ||
2803 | if (bits == 8) | ||
2804 | a = 1; // 8 bit | ||
2805 | break; | ||
2806 | case 2: | ||
2807 | a = 2; // U_LAW | ||
2808 | break; | ||
2809 | case 3: | ||
2810 | a = 3; // A_LAW | ||
2811 | break; | ||
2812 | } | ||
2813 | switch (nch) { | ||
2814 | case 1: | ||
2815 | this_194 = 0; | ||
2816 | break; | ||
2817 | case 2: | ||
2818 | this_194 = 1; | ||
2819 | break; | ||
2820 | case 4: | ||
2821 | this_194 = 1; | ||
2822 | break; | ||
2823 | case 6: | ||
2824 | this_194 = 1; | ||
2825 | break; | ||
2826 | } | ||
2827 | return (a); | ||
2828 | } | ||
2829 | |||
2830 | static void vortex_cdmacore_setformat(vortex_t * vortex, int bits, int nch) | ||
2831 | { | ||
2832 | short int d, this_148; | ||
2833 | |||
2834 | d = ((bits >> 3) * nch); | ||
2835 | this_148 = 0xbb80 / d; | ||
2836 | } | ||
2837 | #endif | ||