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/oss/trident.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/oss/trident.c')
-rw-r--r-- | sound/oss/trident.c | 4628 |
1 files changed, 4628 insertions, 0 deletions
diff --git a/sound/oss/trident.c b/sound/oss/trident.c new file mode 100644 index 000000000000..47537f0a5b05 --- /dev/null +++ b/sound/oss/trident.c | |||
@@ -0,0 +1,4628 @@ | |||
1 | /* | ||
2 | * OSS driver for Linux 2.[46].x for | ||
3 | * | ||
4 | * Trident 4D-Wave | ||
5 | * SiS 7018 | ||
6 | * ALi 5451 | ||
7 | * Tvia/IGST CyberPro 5050 | ||
8 | * | ||
9 | * Driver: Alan Cox <alan@redhat.com> | ||
10 | * | ||
11 | * Built from: | ||
12 | * Low level code: <audio@tridentmicro.com> from ALSA | ||
13 | * Framework: Thomas Sailer <sailer@ife.ee.ethz.ch> | ||
14 | * Extended by: Zach Brown <zab@redhat.com> | ||
15 | * | ||
16 | * Hacked up by: | ||
17 | * Aaron Holtzman <aholtzma@ess.engr.uvic.ca> | ||
18 | * Ollie Lho <ollie@sis.com.tw> SiS 7018 Audio Core Support | ||
19 | * Ching-Ling Lee <cling-li@ali.com.tw> ALi 5451 Audio Core Support | ||
20 | * Matt Wu <mattwu@acersoftech.com.cn> ALi 5451 Audio Core Support | ||
21 | * Peter Wächtler <pwaechtler@loewe-komp.de> CyberPro5050 support | ||
22 | * Muli Ben-Yehuda <mulix@mulix.org> | ||
23 | * | ||
24 | * | ||
25 | * This program is free software; you can redistribute it and/or modify | ||
26 | * it under the terms of the GNU General Public License as published by | ||
27 | * the Free Software Foundation; either version 2 of the License, or | ||
28 | * (at your option) any later version. | ||
29 | * | ||
30 | * This program is distributed in the hope that it will be useful, | ||
31 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
32 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
33 | * GNU General Public License for more details. | ||
34 | * | ||
35 | * You should have received a copy of the GNU General Public License | ||
36 | * along with this program; if not, write to the Free Software | ||
37 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
38 | * | ||
39 | * History | ||
40 | * v0.14.10j | ||
41 | * January 3 2004 Eugene Teo <eugeneteo@eugeneteo.net> | ||
42 | * minor cleanup to use pr_debug instead of TRDBG since it is already | ||
43 | * defined in linux/kernel.h. | ||
44 | * v0.14.10i | ||
45 | * December 29 2003 Muli Ben-Yehuda <mulix@mulix.org> | ||
46 | * major cleanup for 2.6, fix a few error patch buglets | ||
47 | * with returning without properly cleaning up first, | ||
48 | * get rid of lock_kernel(). | ||
49 | * v0.14.10h | ||
50 | * Sept 10 2002 Pascal Schmidt <der.eremit@email.de> | ||
51 | * added support for ALi 5451 joystick port | ||
52 | * v0.14.10g | ||
53 | * Sept 05 2002 Alan Cox <alan@redhat.com> | ||
54 | * adapt to new pci joystick attachment interface | ||
55 | * v0.14.10f | ||
56 | * July 24 2002 Muli Ben-Yehuda <mulix@actcom.co.il> | ||
57 | * patch from Eric Lemar (via Ian Soboroff): in suspend and resume, | ||
58 | * fix wrong cast from pci_dev* to struct trident_card*. | ||
59 | * v0.14.10e | ||
60 | * July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il> | ||
61 | * rewrite the DMA buffer allocation/deallcoation functions, to make it | ||
62 | * modular and fix a bug where we would call free_pages on memory | ||
63 | * obtained with pci_alloc_consistent. Also remove unnecessary #ifdef | ||
64 | * CONFIG_PROC_FS and various other cleanups. | ||
65 | * v0.14.10d | ||
66 | * July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il> | ||
67 | * made several printk(KERN_NOTICE...) into TRDBG(...), to avoid spamming | ||
68 | * my syslog with hundreds of messages. | ||
69 | * v0.14.10c | ||
70 | * July 16 2002 Muli Ben-Yehuda <mulix@actcom.co.il> | ||
71 | * Cleaned up Lei Hu's 0.4.10 driver to conform to Documentation/CodingStyle | ||
72 | * and the coding style used in the rest of the file. | ||
73 | * v0.14.10b | ||
74 | * June 23 2002 Muli Ben-Yehuda <mulix@actcom.co.il> | ||
75 | * add a missing unlock_set_fmt, remove a superflous lock/unlock pair | ||
76 | * with nothing in between. | ||
77 | * v0.14.10a | ||
78 | * June 21 2002 Muli Ben-Yehuda <mulix@actcom.co.il> | ||
79 | * use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns | ||
80 | * per line, use 'do {} while (0)' in statement macros. | ||
81 | * v0.14.10 | ||
82 | * June 6 2002 Lei Hu <Lei_hu@ali.com.tw> | ||
83 | * rewrite the part to read/write registers of audio codec for Ali5451 | ||
84 | * v0.14.9e | ||
85 | * January 2 2002 Vojtech Pavlik <vojtech@ucw.cz> added gameport | ||
86 | * support to avoid resource conflict with pcigame.c | ||
87 | * v0.14.9d | ||
88 | * October 8 2001 Arnaldo Carvalho de Melo <acme@conectiva.com.br> | ||
89 | * use set_current_state, properly release resources on failure in | ||
90 | * trident_probe, get rid of check_region | ||
91 | * v0.14.9c | ||
92 | * August 10 2001 Peter Wächtler <pwaechtler@loewe-komp.de> | ||
93 | * added support for Tvia (formerly Integraphics/IGST) CyberPro5050 | ||
94 | * this chip is often found in settop boxes (combined video+audio) | ||
95 | * v0.14.9b | ||
96 | * Switch to static inline not extern inline (gcc 3) | ||
97 | * v0.14.9a | ||
98 | * Aug 6 2001 Alan Cox | ||
99 | * 0.14.9 crashed on rmmod due to a timer/bh left running. Simplified | ||
100 | * the existing logic (the BH doesn't help as ac97 is lock_irqsave) | ||
101 | * and used del_timer_sync to clean up | ||
102 | * Fixed a problem where the ALi change broke my generic card | ||
103 | * v0.14.9 | ||
104 | * Jul 10 2001 Matt Wu | ||
105 | * Add H/W Volume Control | ||
106 | * v0.14.8a | ||
107 | * July 7 2001 Alan Cox | ||
108 | * Moved Matt Wu's ac97 register cache into the card structure | ||
109 | * v0.14.8 | ||
110 | * Apr 30 2001 Matt Wu | ||
111 | * Set EBUF1 and EBUF2 to still mode | ||
112 | * Add dc97/ac97 reset function | ||
113 | * Fix power management: ali_restore_regs | ||
114 | * unreleased | ||
115 | * Mar 09 2001 Matt Wu | ||
116 | * Add cache for ac97 access | ||
117 | * v0.14.7 | ||
118 | * Feb 06 2001 Matt Wu | ||
119 | * Fix ac97 initialization | ||
120 | * Fix bug: an extra tail will be played when playing | ||
121 | * Jan 05 2001 Matt Wu | ||
122 | * Implement multi-channels and S/PDIF in support for ALi 1535+ | ||
123 | * v0.14.6 | ||
124 | * Nov 1 2000 Ching-Ling Lee | ||
125 | * Fix the bug of memory leak when switching 5.1-channels to 2 channels. | ||
126 | * Add lock protection into dynamic changing format of data. | ||
127 | * Oct 18 2000 Ching-Ling Lee | ||
128 | * 5.1-channels support for ALi | ||
129 | * June 28 2000 Ching-Ling Lee | ||
130 | * S/PDIF out/in(playback/record) support for ALi 1535+, using /proc to be selected by user | ||
131 | * Simple Power Management support for ALi | ||
132 | * v0.14.5 May 23 2000 Ollie Lho | ||
133 | * Misc bug fix from the Net | ||
134 | * v0.14.4 May 20 2000 Aaron Holtzman | ||
135 | * Fix kfree'd memory access in release | ||
136 | * Fix race in open while looking for a free virtual channel slot | ||
137 | * remove open_wait wq (which appears to be unused) | ||
138 | * v0.14.3 May 10 2000 Ollie Lho | ||
139 | * fixed a small bug in trident_update_ptr, xmms 1.0.1 no longer uses 100% CPU | ||
140 | * v0.14.2 Mar 29 2000 Ching-Ling Lee | ||
141 | * Add clear to silence advance in trident_update_ptr | ||
142 | * fix invalid data of the end of the sound | ||
143 | * v0.14.1 Mar 24 2000 Ching-Ling Lee | ||
144 | * ALi 5451 support added, playback and recording O.K. | ||
145 | * ALi 5451 originally developed and structured based on sonicvibes, and | ||
146 | * suggested to merge into this file by Alan Cox. | ||
147 | * v0.14 Mar 15 2000 Ollie Lho | ||
148 | * 5.1 channel output support with channel binding. What's the Matrix ? | ||
149 | * v0.13.1 Mar 10 2000 Ollie Lho | ||
150 | * few minor bugs on dual codec support, needs more testing | ||
151 | * v0.13 Mar 03 2000 Ollie Lho | ||
152 | * new pci_* for 2.4 kernel, back ported to 2.2 | ||
153 | * v0.12 Feb 23 2000 Ollie Lho | ||
154 | * Preliminary Recording support | ||
155 | * v0.11.2 Feb 19 2000 Ollie Lho | ||
156 | * removed incomplete full-dulplex support | ||
157 | * v0.11.1 Jan 28 2000 Ollie Lho | ||
158 | * small bug in setting sample rate for 4d-nx (reported by Aaron) | ||
159 | * v0.11 Jan 27 2000 Ollie Lho | ||
160 | * DMA bug, scheduler latency, second try | ||
161 | * v0.10 Jan 24 2000 Ollie Lho | ||
162 | * DMA bug fixed, found kernel scheduling problem | ||
163 | * v0.09 Jan 20 2000 Ollie Lho | ||
164 | * Clean up of channel register access routine (prepare for channel binding) | ||
165 | * v0.08 Jan 14 2000 Ollie Lho | ||
166 | * Isolation of AC97 codec code | ||
167 | * v0.07 Jan 13 2000 Ollie Lho | ||
168 | * Get rid of ugly old low level access routines (e.g. CHRegs.lp****) | ||
169 | * v0.06 Jan 11 2000 Ollie Lho | ||
170 | * Preliminary support for dual (more ?) AC97 codecs | ||
171 | * v0.05 Jan 08 2000 Luca Montecchiani <m.luca@iname.com> | ||
172 | * adapt to 2.3.x new __setup/__init call | ||
173 | * v0.04 Dec 31 1999 Ollie Lho | ||
174 | * Multiple Open, using Middle Loop Interrupt to smooth playback | ||
175 | * v0.03 Dec 24 1999 Ollie Lho | ||
176 | * mem leak in prog_dmabuf and dealloc_dmabuf removed | ||
177 | * v0.02 Dec 15 1999 Ollie Lho | ||
178 | * SiS 7018 support added, playback O.K. | ||
179 | * v0.01 Alan Cox et. al. | ||
180 | * Initial Release in kernel 2.3.30, does not work | ||
181 | * | ||
182 | * ToDo | ||
183 | * Clean up of low level channel register access code. (done) | ||
184 | * Fix the bug on dma buffer management in update_ptr, read/write, drain_dac (done) | ||
185 | * Dual AC97 codecs support (done) | ||
186 | * Recording support (done) | ||
187 | * Mmap support | ||
188 | * "Channel Binding" ioctl extension (done) | ||
189 | * new pci device driver interface for 2.4 kernel (done) | ||
190 | * | ||
191 | * Lock order (high->low) | ||
192 | * lock - hardware lock | ||
193 | * open_sem - guard opens | ||
194 | * sem - guard dmabuf, write re-entry etc | ||
195 | */ | ||
196 | |||
197 | #include <linux/config.h> | ||
198 | #include <linux/module.h> | ||
199 | #include <linux/string.h> | ||
200 | #include <linux/ctype.h> | ||
201 | #include <linux/ioport.h> | ||
202 | #include <linux/sched.h> | ||
203 | #include <linux/delay.h> | ||
204 | #include <linux/sound.h> | ||
205 | #include <linux/slab.h> | ||
206 | #include <linux/soundcard.h> | ||
207 | #include <linux/pci.h> | ||
208 | #include <linux/init.h> | ||
209 | #include <linux/poll.h> | ||
210 | #include <linux/spinlock.h> | ||
211 | #include <linux/smp_lock.h> | ||
212 | #include <linux/ac97_codec.h> | ||
213 | #include <linux/bitops.h> | ||
214 | #include <linux/proc_fs.h> | ||
215 | #include <linux/interrupt.h> | ||
216 | #include <linux/pm.h> | ||
217 | #include <linux/gameport.h> | ||
218 | #include <linux/kernel.h> | ||
219 | #include <asm/uaccess.h> | ||
220 | #include <asm/io.h> | ||
221 | #include <asm/dma.h> | ||
222 | |||
223 | #if defined(CONFIG_ALPHA_NAUTILUS) || defined(CONFIG_ALPHA_GENERIC) | ||
224 | #include <asm/hwrpb.h> | ||
225 | #endif | ||
226 | |||
227 | #include "trident.h" | ||
228 | |||
229 | #define DRIVER_VERSION "0.14.10j-2.6" | ||
230 | |||
231 | /* magic numbers to protect our data structures */ | ||
232 | #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ | ||
233 | #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ | ||
234 | |||
235 | #define TRIDENT_DMA_MASK 0x3fffffff /* DMA buffer mask for pci_alloc_consist */ | ||
236 | #define ALI_DMA_MASK 0x7fffffff /* ALI Tridents have 31-bit DMA. Wow. */ | ||
237 | |||
238 | #define NR_HW_CH 32 | ||
239 | |||
240 | /* maximum number of AC97 codecs connected, AC97 2.0 defined 4, but 7018 and 4D-NX only | ||
241 | have 2 SDATA_IN lines (currently) */ | ||
242 | #define NR_AC97 2 | ||
243 | |||
244 | /* minor number of /dev/swmodem (temporary, experimental) */ | ||
245 | #define SND_DEV_SWMODEM 7 | ||
246 | |||
247 | static const unsigned ali_multi_channels_5_1[] = { | ||
248 | /*ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL, */ | ||
249 | ALI_CENTER_CHANNEL, | ||
250 | ALI_LEF_CHANNEL, | ||
251 | ALI_SURR_LEFT_CHANNEL, | ||
252 | ALI_SURR_RIGHT_CHANNEL | ||
253 | }; | ||
254 | |||
255 | static const unsigned sample_size[] = { 1, 2, 2, 4 }; | ||
256 | static const unsigned sample_shift[] = { 0, 1, 1, 2 }; | ||
257 | |||
258 | static const char invalid_magic[] = KERN_CRIT "trident: invalid magic value in %s\n"; | ||
259 | |||
260 | enum { | ||
261 | TRIDENT_4D_DX = 0, | ||
262 | TRIDENT_4D_NX, | ||
263 | SIS_7018, | ||
264 | ALI_5451, | ||
265 | CYBER5050 | ||
266 | }; | ||
267 | |||
268 | static char *card_names[] = { | ||
269 | "Trident 4DWave DX", | ||
270 | "Trident 4DWave NX", | ||
271 | "SiS 7018 PCI Audio", | ||
272 | "ALi Audio Accelerator", | ||
273 | "Tvia/IGST CyberPro 5050" | ||
274 | }; | ||
275 | |||
276 | static struct pci_device_id trident_pci_tbl[] = { | ||
277 | {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX, | ||
278 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_DX}, | ||
279 | {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX, | ||
280 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_NX}, | ||
281 | {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018, | ||
282 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018}, | ||
283 | {PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451, | ||
284 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, ALI_5451}, | ||
285 | {PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050, | ||
286 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, CYBER5050}, | ||
287 | {0,} | ||
288 | }; | ||
289 | |||
290 | MODULE_DEVICE_TABLE(pci, trident_pci_tbl); | ||
291 | |||
292 | /* "software" or virtual channel, an instance of opened /dev/dsp */ | ||
293 | struct trident_state { | ||
294 | unsigned int magic; | ||
295 | struct trident_card *card; /* Card info */ | ||
296 | |||
297 | /* file mode */ | ||
298 | mode_t open_mode; | ||
299 | |||
300 | /* virtual channel number */ | ||
301 | int virt; | ||
302 | |||
303 | struct dmabuf { | ||
304 | /* wave sample stuff */ | ||
305 | unsigned int rate; | ||
306 | unsigned char fmt, enable; | ||
307 | |||
308 | /* hardware channel */ | ||
309 | struct trident_channel *channel; | ||
310 | |||
311 | /* OSS buffer management stuff */ | ||
312 | void *rawbuf; | ||
313 | dma_addr_t dma_handle; | ||
314 | unsigned buforder; | ||
315 | unsigned numfrag; | ||
316 | unsigned fragshift; | ||
317 | |||
318 | /* our buffer acts like a circular ring */ | ||
319 | unsigned hwptr; /* where dma last started, updated by update_ptr */ | ||
320 | unsigned swptr; /* where driver last clear/filled, updated by read/write */ | ||
321 | int count; /* bytes to be comsumed or been generated by dma machine */ | ||
322 | unsigned total_bytes; /* total bytes dmaed by hardware */ | ||
323 | |||
324 | unsigned error; /* number of over/underruns */ | ||
325 | /* put process on wait queue when no more space in buffer */ | ||
326 | wait_queue_head_t wait; | ||
327 | |||
328 | /* redundant, but makes calculations easier */ | ||
329 | unsigned fragsize; | ||
330 | unsigned dmasize; | ||
331 | unsigned fragsamples; | ||
332 | |||
333 | /* OSS stuff */ | ||
334 | unsigned mapped:1; | ||
335 | unsigned ready:1; | ||
336 | unsigned endcleared:1; | ||
337 | unsigned update_flag; | ||
338 | unsigned ossfragshift; | ||
339 | int ossmaxfrags; | ||
340 | unsigned subdivision; | ||
341 | |||
342 | } dmabuf; | ||
343 | |||
344 | /* 5.1 channels */ | ||
345 | struct trident_state *other_states[4]; | ||
346 | int multi_channels_adjust_count; | ||
347 | unsigned chans_num; | ||
348 | unsigned long fmt_flag; | ||
349 | /* Guard against mmap/write/read races */ | ||
350 | struct semaphore sem; | ||
351 | |||
352 | }; | ||
353 | |||
354 | /* hardware channels */ | ||
355 | struct trident_channel { | ||
356 | int num; /* channel number */ | ||
357 | u32 lba; /* Loop Begine Address, where dma buffer starts */ | ||
358 | u32 eso; /* End Sample Offset, wehre dma buffer ends */ | ||
359 | /* (in the unit of samples) */ | ||
360 | u32 delta; /* delta value, sample rate / 48k for playback, */ | ||
361 | /* 48k/sample rate for recording */ | ||
362 | u16 attribute; /* control where PCM data go and come */ | ||
363 | u16 fm_vol; | ||
364 | u32 control; /* signed/unsigned, 8/16 bits, mono/stereo */ | ||
365 | }; | ||
366 | |||
367 | struct trident_pcm_bank_address { | ||
368 | u32 start; | ||
369 | u32 stop; | ||
370 | u32 aint; | ||
371 | u32 aint_en; | ||
372 | }; | ||
373 | |||
374 | static struct trident_pcm_bank_address bank_a_addrs = { | ||
375 | T4D_START_A, | ||
376 | T4D_STOP_A, | ||
377 | T4D_AINT_A, | ||
378 | T4D_AINTEN_A | ||
379 | }; | ||
380 | |||
381 | static struct trident_pcm_bank_address bank_b_addrs = { | ||
382 | T4D_START_B, | ||
383 | T4D_STOP_B, | ||
384 | T4D_AINT_B, | ||
385 | T4D_AINTEN_B | ||
386 | }; | ||
387 | |||
388 | struct trident_pcm_bank { | ||
389 | /* register addresses to control bank operations */ | ||
390 | struct trident_pcm_bank_address *addresses; | ||
391 | /* each bank has 32 channels */ | ||
392 | u32 bitmap; /* channel allocation bitmap */ | ||
393 | struct trident_channel channels[32]; | ||
394 | }; | ||
395 | |||
396 | struct trident_card { | ||
397 | unsigned int magic; | ||
398 | |||
399 | /* We keep trident cards in a linked list */ | ||
400 | struct trident_card *next; | ||
401 | |||
402 | /* single open lock mechanism, only used for recording */ | ||
403 | struct semaphore open_sem; | ||
404 | |||
405 | /* The trident has a certain amount of cross channel interaction | ||
406 | so we use a single per card lock */ | ||
407 | spinlock_t lock; | ||
408 | |||
409 | /* PCI device stuff */ | ||
410 | struct pci_dev *pci_dev; | ||
411 | u16 pci_id; | ||
412 | u8 revision; | ||
413 | |||
414 | /* soundcore stuff */ | ||
415 | int dev_audio; | ||
416 | |||
417 | /* structures for abstraction of hardware facilities, codecs, */ | ||
418 | /* banks and channels */ | ||
419 | struct ac97_codec *ac97_codec[NR_AC97]; | ||
420 | struct trident_pcm_bank banks[NR_BANKS]; | ||
421 | struct trident_state *states[NR_HW_CH]; | ||
422 | |||
423 | /* hardware resources */ | ||
424 | unsigned long iobase; | ||
425 | u32 irq; | ||
426 | |||
427 | /* Function support */ | ||
428 | struct trident_channel *(*alloc_pcm_channel) (struct trident_card *); | ||
429 | struct trident_channel *(*alloc_rec_pcm_channel) (struct trident_card *); | ||
430 | void (*free_pcm_channel) (struct trident_card *, unsigned int chan); | ||
431 | void (*address_interrupt) (struct trident_card *); | ||
432 | |||
433 | /* Added by Matt Wu 01-05-2001 for spdif in */ | ||
434 | int multi_channel_use_count; | ||
435 | int rec_channel_use_count; | ||
436 | u16 mixer_regs[64][NR_AC97]; /* Made card local by Alan */ | ||
437 | int mixer_regs_ready; | ||
438 | |||
439 | /* Added for hardware volume control */ | ||
440 | int hwvolctl; | ||
441 | struct timer_list timer; | ||
442 | |||
443 | /* Game port support */ | ||
444 | struct gameport *gameport; | ||
445 | }; | ||
446 | |||
447 | enum dmabuf_mode { | ||
448 | DM_PLAYBACK = 0, | ||
449 | DM_RECORD | ||
450 | }; | ||
451 | |||
452 | /* table to map from CHANNELMASK to channel attribute for SiS 7018 */ | ||
453 | static u16 mask2attr[] = { | ||
454 | PCM_LR, PCM_LR, SURR_LR, CENTER_LFE, | ||
455 | HSET, MIC, MODEM_LINE1, MODEM_LINE2, | ||
456 | I2S_LR, SPDIF_LR | ||
457 | }; | ||
458 | |||
459 | /* table to map from channel attribute to CHANNELMASK for SiS 7018 */ | ||
460 | static int attr2mask[] = { | ||
461 | DSP_BIND_MODEM1, DSP_BIND_MODEM2, DSP_BIND_FRONT, DSP_BIND_HANDSET, | ||
462 | DSP_BIND_I2S, DSP_BIND_CENTER_LFE, DSP_BIND_SURR, DSP_BIND_SPDIF | ||
463 | }; | ||
464 | |||
465 | /* Added by Matt Wu 01-05-2001 for spdif in */ | ||
466 | static int ali_close_multi_channels(void); | ||
467 | static void ali_delay(struct trident_card *card, int interval); | ||
468 | static void ali_detect_spdif_rate(struct trident_card *card); | ||
469 | |||
470 | static void ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val); | ||
471 | static u16 ali_ac97_read(struct ac97_codec *codec, u8 reg); | ||
472 | |||
473 | static struct trident_card *devs; | ||
474 | |||
475 | static void trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val); | ||
476 | static u16 trident_ac97_get(struct ac97_codec *codec, u8 reg); | ||
477 | |||
478 | static int trident_open_mixdev(struct inode *inode, struct file *file); | ||
479 | static int trident_ioctl_mixdev(struct inode *inode, struct file *file, | ||
480 | unsigned int cmd, unsigned long arg); | ||
481 | |||
482 | static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val); | ||
483 | static u16 ali_ac97_get(struct trident_card *card, int secondary, u8 reg); | ||
484 | static void ali_set_spdif_out_rate(struct trident_card *card, unsigned int rate); | ||
485 | static void ali_enable_special_channel(struct trident_state *stat); | ||
486 | static struct trident_channel *ali_alloc_rec_pcm_channel(struct trident_card *card); | ||
487 | static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card); | ||
488 | static void ali_restore_regs(struct trident_card *card); | ||
489 | static void ali_save_regs(struct trident_card *card); | ||
490 | static int trident_suspend(struct pci_dev *dev, pm_message_t unused); | ||
491 | static int trident_resume(struct pci_dev *dev); | ||
492 | static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel); | ||
493 | static int ali_setup_multi_channels(struct trident_card *card, int chan_nums); | ||
494 | static unsigned int ali_get_spdif_in_rate(struct trident_card *card); | ||
495 | static void ali_setup_spdif_in(struct trident_card *card); | ||
496 | static void ali_disable_spdif_in(struct trident_card *card); | ||
497 | static void ali_disable_special_channel(struct trident_card *card, int ch); | ||
498 | static void ali_setup_spdif_out(struct trident_card *card, int flag); | ||
499 | static int ali_write_5_1(struct trident_state *state, | ||
500 | const char __user *buffer, | ||
501 | int cnt_for_multi_channel, unsigned int *copy_count, | ||
502 | unsigned int *state_cnt); | ||
503 | static int ali_allocate_other_states_resources(struct trident_state *state, | ||
504 | int chan_nums); | ||
505 | static void ali_free_other_states_resources(struct trident_state *state); | ||
506 | |||
507 | /* save registers for ALi Power Management */ | ||
508 | static struct ali_saved_registers { | ||
509 | unsigned long global_regs[ALI_GLOBAL_REGS]; | ||
510 | unsigned long channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS]; | ||
511 | unsigned mixer_regs[ALI_MIXER_REGS]; | ||
512 | } ali_registers; | ||
513 | |||
514 | #define seek_offset(dma_ptr, buffer, cnt, offset, copy_count) do { \ | ||
515 | (dma_ptr) += (offset); \ | ||
516 | (buffer) += (offset); \ | ||
517 | (cnt) -= (offset); \ | ||
518 | (copy_count) += (offset); \ | ||
519 | } while (0) | ||
520 | |||
521 | static inline int lock_set_fmt(struct trident_state* state) | ||
522 | { | ||
523 | if (test_and_set_bit(0, &state->fmt_flag)) | ||
524 | return -EFAULT; | ||
525 | |||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | static inline void unlock_set_fmt(struct trident_state* state) | ||
530 | { | ||
531 | clear_bit(0, &state->fmt_flag); | ||
532 | } | ||
533 | |||
534 | static int | ||
535 | trident_enable_loop_interrupts(struct trident_card *card) | ||
536 | { | ||
537 | u32 global_control; | ||
538 | |||
539 | global_control = inl(TRID_REG(card, T4D_LFO_GC_CIR)); | ||
540 | |||
541 | switch (card->pci_id) { | ||
542 | case PCI_DEVICE_ID_SI_7018: | ||
543 | global_control |= (ENDLP_IE | MIDLP_IE | BANK_B_EN); | ||
544 | break; | ||
545 | case PCI_DEVICE_ID_ALI_5451: | ||
546 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: | ||
547 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: | ||
548 | case PCI_DEVICE_ID_INTERG_5050: | ||
549 | global_control |= (ENDLP_IE | MIDLP_IE); | ||
550 | break; | ||
551 | default: | ||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR)); | ||
556 | |||
557 | pr_debug("trident: Enable Loop Interrupts, globctl = 0x%08X\n", | ||
558 | inl(TRID_REG(card, T4D_LFO_GC_CIR))); | ||
559 | |||
560 | return 1; | ||
561 | } | ||
562 | |||
563 | static int | ||
564 | trident_disable_loop_interrupts(struct trident_card *card) | ||
565 | { | ||
566 | u32 global_control; | ||
567 | |||
568 | global_control = inl(TRID_REG(card, T4D_LFO_GC_CIR)); | ||
569 | global_control &= ~(ENDLP_IE | MIDLP_IE); | ||
570 | outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR)); | ||
571 | |||
572 | pr_debug("trident: Disabled Loop Interrupts, globctl = 0x%08X\n", | ||
573 | global_control); | ||
574 | |||
575 | return 1; | ||
576 | } | ||
577 | |||
578 | static void | ||
579 | trident_enable_voice_irq(struct trident_card *card, unsigned int channel) | ||
580 | { | ||
581 | unsigned int mask = 1 << (channel & 0x1f); | ||
582 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; | ||
583 | u32 reg, addr = bank->addresses->aint_en; | ||
584 | |||
585 | reg = inl(TRID_REG(card, addr)); | ||
586 | reg |= mask; | ||
587 | outl(reg, TRID_REG(card, addr)); | ||
588 | |||
589 | #ifdef DEBUG | ||
590 | reg = inl(TRID_REG(card, addr)); | ||
591 | pr_debug("trident: enabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", | ||
592 | channel, addr == T4D_AINTEN_B ? "AINTEN_B" : "AINTEN_A", | ||
593 | reg, addr); | ||
594 | #endif /* DEBUG */ | ||
595 | } | ||
596 | |||
597 | static void | ||
598 | trident_disable_voice_irq(struct trident_card *card, unsigned int channel) | ||
599 | { | ||
600 | unsigned int mask = 1 << (channel & 0x1f); | ||
601 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; | ||
602 | u32 reg, addr = bank->addresses->aint_en; | ||
603 | |||
604 | reg = inl(TRID_REG(card, addr)); | ||
605 | reg &= ~mask; | ||
606 | outl(reg, TRID_REG(card, addr)); | ||
607 | |||
608 | /* Ack the channel in case the interrupt was set before we disable it. */ | ||
609 | outl(mask, TRID_REG(card, bank->addresses->aint)); | ||
610 | |||
611 | #ifdef DEBUG | ||
612 | reg = inl(TRID_REG(card, addr)); | ||
613 | pr_debug("trident: disabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n", | ||
614 | channel, addr == T4D_AINTEN_B ? "AINTEN_B" : "AINTEN_A", | ||
615 | reg, addr); | ||
616 | #endif /* DEBUG */ | ||
617 | } | ||
618 | |||
619 | static void | ||
620 | trident_start_voice(struct trident_card *card, unsigned int channel) | ||
621 | { | ||
622 | unsigned int mask = 1 << (channel & 0x1f); | ||
623 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; | ||
624 | u32 addr = bank->addresses->start; | ||
625 | |||
626 | #ifdef DEBUG | ||
627 | u32 reg; | ||
628 | #endif /* DEBUG */ | ||
629 | |||
630 | outl(mask, TRID_REG(card, addr)); | ||
631 | |||
632 | #ifdef DEBUG | ||
633 | reg = inl(TRID_REG(card, addr)); | ||
634 | pr_debug("trident: start voice on channel %d, %s = 0x%08x(addr:%X)\n", | ||
635 | channel, addr == T4D_START_B ? "START_B" : "START_A", | ||
636 | reg, addr); | ||
637 | #endif /* DEBUG */ | ||
638 | } | ||
639 | |||
640 | static void | ||
641 | trident_stop_voice(struct trident_card *card, unsigned int channel) | ||
642 | { | ||
643 | unsigned int mask = 1 << (channel & 0x1f); | ||
644 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; | ||
645 | u32 addr = bank->addresses->stop; | ||
646 | |||
647 | #ifdef DEBUG | ||
648 | u32 reg; | ||
649 | #endif /* DEBUG */ | ||
650 | |||
651 | outl(mask, TRID_REG(card, addr)); | ||
652 | |||
653 | #ifdef DEBUG | ||
654 | reg = inl(TRID_REG(card, addr)); | ||
655 | pr_debug("trident: stop voice on channel %d, %s = 0x%08x(addr:%X)\n", | ||
656 | channel, addr == T4D_STOP_B ? "STOP_B" : "STOP_A", | ||
657 | reg, addr); | ||
658 | #endif /* DEBUG */ | ||
659 | } | ||
660 | |||
661 | static u32 | ||
662 | trident_get_interrupt_mask(struct trident_card *card, unsigned int channel) | ||
663 | { | ||
664 | struct trident_pcm_bank *bank = &card->banks[channel]; | ||
665 | u32 addr = bank->addresses->aint; | ||
666 | return inl(TRID_REG(card, addr)); | ||
667 | } | ||
668 | |||
669 | static int | ||
670 | trident_check_channel_interrupt(struct trident_card *card, unsigned int channel) | ||
671 | { | ||
672 | unsigned int mask = 1 << (channel & 0x1f); | ||
673 | u32 reg = trident_get_interrupt_mask(card, channel >> 5); | ||
674 | |||
675 | #ifdef DEBUG | ||
676 | if (reg & mask) | ||
677 | pr_debug("trident: channel %d has interrupt, %s = 0x%08x\n", | ||
678 | channel, reg == T4D_AINT_B ? "AINT_B" : "AINT_A", | ||
679 | reg); | ||
680 | #endif /* DEBUG */ | ||
681 | return (reg & mask) ? 1 : 0; | ||
682 | } | ||
683 | |||
684 | static void | ||
685 | trident_ack_channel_interrupt(struct trident_card *card, unsigned int channel) | ||
686 | { | ||
687 | unsigned int mask = 1 << (channel & 0x1f); | ||
688 | struct trident_pcm_bank *bank = &card->banks[channel >> 5]; | ||
689 | u32 reg, addr = bank->addresses->aint; | ||
690 | |||
691 | reg = inl(TRID_REG(card, addr)); | ||
692 | reg &= mask; | ||
693 | outl(reg, TRID_REG(card, addr)); | ||
694 | |||
695 | #ifdef DEBUG | ||
696 | reg = inl(TRID_REG(card, T4D_AINT_B)); | ||
697 | pr_debug("trident: Ack channel %d interrupt, AINT_B = 0x%08x\n", | ||
698 | channel, reg); | ||
699 | #endif /* DEBUG */ | ||
700 | } | ||
701 | |||
702 | static struct trident_channel * | ||
703 | trident_alloc_pcm_channel(struct trident_card *card) | ||
704 | { | ||
705 | struct trident_pcm_bank *bank; | ||
706 | int idx; | ||
707 | |||
708 | bank = &card->banks[BANK_B]; | ||
709 | |||
710 | for (idx = 31; idx >= 0; idx--) { | ||
711 | if (!(bank->bitmap & (1 << idx))) { | ||
712 | struct trident_channel *channel = &bank->channels[idx]; | ||
713 | bank->bitmap |= 1 << idx; | ||
714 | channel->num = idx + 32; | ||
715 | return channel; | ||
716 | } | ||
717 | } | ||
718 | |||
719 | /* no more free channels available */ | ||
720 | printk(KERN_ERR "trident: no more channels available on Bank B.\n"); | ||
721 | return NULL; | ||
722 | } | ||
723 | |||
724 | static void | ||
725 | trident_free_pcm_channel(struct trident_card *card, unsigned int channel) | ||
726 | { | ||
727 | int bank; | ||
728 | unsigned char b; | ||
729 | |||
730 | if (channel < 31 || channel > 63) | ||
731 | return; | ||
732 | |||
733 | if (card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_DX || | ||
734 | card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_NX) { | ||
735 | b = inb(TRID_REG(card, T4D_REC_CH)); | ||
736 | if ((b & ~0x80) == channel) | ||
737 | outb(0x0, TRID_REG(card, T4D_REC_CH)); | ||
738 | } | ||
739 | |||
740 | bank = channel >> 5; | ||
741 | channel = channel & 0x1f; | ||
742 | |||
743 | card->banks[bank].bitmap &= ~(1 << (channel)); | ||
744 | } | ||
745 | |||
746 | static struct trident_channel * | ||
747 | cyber_alloc_pcm_channel(struct trident_card *card) | ||
748 | { | ||
749 | struct trident_pcm_bank *bank; | ||
750 | int idx; | ||
751 | |||
752 | /* The cyberpro 5050 has only 32 voices and one bank */ | ||
753 | /* .. at least they are not documented (if you want to call that | ||
754 | * crap documentation), perhaps broken ? */ | ||
755 | |||
756 | bank = &card->banks[BANK_A]; | ||
757 | |||
758 | for (idx = 31; idx >= 0; idx--) { | ||
759 | if (!(bank->bitmap & (1 << idx))) { | ||
760 | struct trident_channel *channel = &bank->channels[idx]; | ||
761 | bank->bitmap |= 1 << idx; | ||
762 | channel->num = idx; | ||
763 | return channel; | ||
764 | } | ||
765 | } | ||
766 | |||
767 | /* no more free channels available */ | ||
768 | printk(KERN_ERR "cyberpro5050: no more channels available on Bank A.\n"); | ||
769 | return NULL; | ||
770 | } | ||
771 | |||
772 | static void | ||
773 | cyber_free_pcm_channel(struct trident_card *card, unsigned int channel) | ||
774 | { | ||
775 | if (channel > 31) | ||
776 | return; | ||
777 | card->banks[BANK_A].bitmap &= ~(1 << (channel)); | ||
778 | } | ||
779 | |||
780 | static inline void | ||
781 | cyber_outidx(int port, int idx, int data) | ||
782 | { | ||
783 | outb(idx, port); | ||
784 | outb(data, port + 1); | ||
785 | } | ||
786 | |||
787 | static inline int | ||
788 | cyber_inidx(int port, int idx) | ||
789 | { | ||
790 | outb(idx, port); | ||
791 | return inb(port + 1); | ||
792 | } | ||
793 | |||
794 | static int | ||
795 | cyber_init_ritual(struct trident_card *card) | ||
796 | { | ||
797 | /* some black magic, taken from SDK samples */ | ||
798 | /* remove this and nothing will work */ | ||
799 | int portDat; | ||
800 | int ret = 0; | ||
801 | unsigned long flags; | ||
802 | |||
803 | /* | ||
804 | * Keep interrupts off for the configure - we don't want to | ||
805 | * clash with another cyberpro config event | ||
806 | */ | ||
807 | |||
808 | spin_lock_irqsave(&card->lock, flags); | ||
809 | portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE); | ||
810 | /* enable, if it was disabled */ | ||
811 | if ((portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE) { | ||
812 | printk(KERN_INFO "cyberpro5050: enabling audio controller\n"); | ||
813 | cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE, | ||
814 | portDat | CYBER_BMSK_AUENZ_ENABLE); | ||
815 | /* check again if hardware is enabled now */ | ||
816 | portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE); | ||
817 | } | ||
818 | if ((portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE) { | ||
819 | printk(KERN_ERR "cyberpro5050: initAudioAccess: no success\n"); | ||
820 | ret = -1; | ||
821 | } else { | ||
822 | cyber_outidx(CYBER_PORT_AUDIO, CYBER_IDX_IRQ_ENABLE, | ||
823 | CYBER_BMSK_AUDIO_INT_ENABLE); | ||
824 | cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x01); | ||
825 | cyber_outidx(CYBER_PORT_AUDIO, 0xba, 0x20); | ||
826 | cyber_outidx(CYBER_PORT_AUDIO, 0xbb, 0x08); | ||
827 | cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x02); | ||
828 | cyber_outidx(CYBER_PORT_AUDIO, 0xb3, 0x06); | ||
829 | cyber_outidx(CYBER_PORT_AUDIO, 0xbf, 0x00); | ||
830 | } | ||
831 | spin_unlock_irqrestore(&card->lock, flags); | ||
832 | return ret; | ||
833 | } | ||
834 | |||
835 | /* called with spin lock held */ | ||
836 | |||
837 | static int | ||
838 | trident_load_channel_registers(struct trident_card *card, u32 * data, | ||
839 | unsigned int channel) | ||
840 | { | ||
841 | int i; | ||
842 | |||
843 | if (channel > 63) | ||
844 | return 0; | ||
845 | |||
846 | /* select hardware channel to write */ | ||
847 | outb(channel, TRID_REG(card, T4D_LFO_GC_CIR)); | ||
848 | |||
849 | /* Output the channel registers, but don't write register | ||
850 | three to an ALI chip. */ | ||
851 | for (i = 0; i < CHANNEL_REGS; i++) { | ||
852 | if (i == 3 && card->pci_id == PCI_DEVICE_ID_ALI_5451) | ||
853 | continue; | ||
854 | outl(data[i], TRID_REG(card, CHANNEL_START + 4 * i)); | ||
855 | } | ||
856 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451 || | ||
857 | card->pci_id == PCI_DEVICE_ID_INTERG_5050) { | ||
858 | outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF1)); | ||
859 | outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF2)); | ||
860 | } | ||
861 | return 1; | ||
862 | } | ||
863 | |||
864 | /* called with spin lock held */ | ||
865 | static int | ||
866 | trident_write_voice_regs(struct trident_state *state) | ||
867 | { | ||
868 | unsigned int data[CHANNEL_REGS + 1]; | ||
869 | struct trident_channel *channel; | ||
870 | |||
871 | channel = state->dmabuf.channel; | ||
872 | |||
873 | data[1] = channel->lba; | ||
874 | data[4] = channel->control; | ||
875 | |||
876 | switch (state->card->pci_id) { | ||
877 | case PCI_DEVICE_ID_ALI_5451: | ||
878 | data[0] = 0; /* Current Sample Offset */ | ||
879 | data[2] = (channel->eso << 16) | (channel->delta & 0xffff); | ||
880 | data[3] = 0; | ||
881 | break; | ||
882 | case PCI_DEVICE_ID_SI_7018: | ||
883 | case PCI_DEVICE_ID_INTERG_5050: | ||
884 | data[0] = 0; /* Current Sample Offset */ | ||
885 | data[2] = (channel->eso << 16) | (channel->delta & 0xffff); | ||
886 | data[3] = (channel->attribute << 16) | (channel->fm_vol & 0xffff); | ||
887 | break; | ||
888 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: | ||
889 | data[0] = 0; /* Current Sample Offset */ | ||
890 | data[2] = (channel->eso << 16) | (channel->delta & 0xffff); | ||
891 | data[3] = channel->fm_vol & 0xffff; | ||
892 | break; | ||
893 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: | ||
894 | data[0] = (channel->delta << 24); | ||
895 | data[2] = ((channel->delta << 16) & 0xff000000) | | ||
896 | (channel->eso & 0x00ffffff); | ||
897 | data[3] = channel->fm_vol & 0xffff; | ||
898 | break; | ||
899 | default: | ||
900 | return 0; | ||
901 | } | ||
902 | |||
903 | return trident_load_channel_registers(state->card, data, channel->num); | ||
904 | } | ||
905 | |||
906 | static int | ||
907 | compute_rate_play(u32 rate) | ||
908 | { | ||
909 | int delta; | ||
910 | /* We special case 44100 and 8000 since rounding with the equation | ||
911 | does not give us an accurate enough value. For 11025 and 22050 | ||
912 | the equation gives us the best answer. All other frequencies will | ||
913 | also use the equation. JDW */ | ||
914 | if (rate == 44100) | ||
915 | delta = 0xeb3; | ||
916 | else if (rate == 8000) | ||
917 | delta = 0x2ab; | ||
918 | else if (rate == 48000) | ||
919 | delta = 0x1000; | ||
920 | else | ||
921 | delta = (((rate << 12) + rate) / 48000) & 0x0000ffff; | ||
922 | return delta; | ||
923 | } | ||
924 | |||
925 | static int | ||
926 | compute_rate_rec(u32 rate) | ||
927 | { | ||
928 | int delta; | ||
929 | |||
930 | if (rate == 44100) | ||
931 | delta = 0x116a; | ||
932 | else if (rate == 8000) | ||
933 | delta = 0x6000; | ||
934 | else if (rate == 48000) | ||
935 | delta = 0x1000; | ||
936 | else | ||
937 | delta = ((48000 << 12) / rate) & 0x0000ffff; | ||
938 | |||
939 | return delta; | ||
940 | } | ||
941 | |||
942 | /* set playback sample rate */ | ||
943 | static unsigned int | ||
944 | trident_set_dac_rate(struct trident_state *state, unsigned int rate) | ||
945 | { | ||
946 | struct dmabuf *dmabuf = &state->dmabuf; | ||
947 | |||
948 | if (rate > 48000) | ||
949 | rate = 48000; | ||
950 | if (rate < 4000) | ||
951 | rate = 4000; | ||
952 | |||
953 | dmabuf->rate = rate; | ||
954 | dmabuf->channel->delta = compute_rate_play(rate); | ||
955 | |||
956 | trident_write_voice_regs(state); | ||
957 | |||
958 | pr_debug("trident: called trident_set_dac_rate : rate = %d\n", rate); | ||
959 | |||
960 | return rate; | ||
961 | } | ||
962 | |||
963 | /* set recording sample rate */ | ||
964 | static unsigned int | ||
965 | trident_set_adc_rate(struct trident_state *state, unsigned int rate) | ||
966 | { | ||
967 | struct dmabuf *dmabuf = &state->dmabuf; | ||
968 | |||
969 | if (rate > 48000) | ||
970 | rate = 48000; | ||
971 | if (rate < 4000) | ||
972 | rate = 4000; | ||
973 | |||
974 | dmabuf->rate = rate; | ||
975 | dmabuf->channel->delta = compute_rate_rec(rate); | ||
976 | |||
977 | trident_write_voice_regs(state); | ||
978 | |||
979 | pr_debug("trident: called trident_set_adc_rate : rate = %d\n", rate); | ||
980 | |||
981 | return rate; | ||
982 | } | ||
983 | |||
984 | /* prepare channel attributes for playback */ | ||
985 | static void | ||
986 | trident_play_setup(struct trident_state *state) | ||
987 | { | ||
988 | struct dmabuf *dmabuf = &state->dmabuf; | ||
989 | struct trident_channel *channel = dmabuf->channel; | ||
990 | |||
991 | channel->lba = dmabuf->dma_handle; | ||
992 | channel->delta = compute_rate_play(dmabuf->rate); | ||
993 | |||
994 | channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt]; | ||
995 | channel->eso -= 1; | ||
996 | |||
997 | if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) { | ||
998 | channel->attribute = 0; | ||
999 | if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451) { | ||
1000 | if ((channel->num == ALI_SPDIF_IN_CHANNEL) || | ||
1001 | (channel->num == ALI_PCM_IN_CHANNEL)) | ||
1002 | ali_disable_special_channel(state->card, channel->num); | ||
1003 | else if ((inl(TRID_REG(state->card, ALI_GLOBAL_CONTROL)) | ||
1004 | & ALI_SPDIF_OUT_CH_ENABLE) | ||
1005 | && (channel->num == ALI_SPDIF_OUT_CHANNEL)) { | ||
1006 | ali_set_spdif_out_rate(state->card, | ||
1007 | state->dmabuf.rate); | ||
1008 | state->dmabuf.channel->delta = 0x1000; | ||
1009 | } | ||
1010 | } | ||
1011 | } | ||
1012 | |||
1013 | channel->fm_vol = 0x0; | ||
1014 | |||
1015 | channel->control = CHANNEL_LOOP; | ||
1016 | if (dmabuf->fmt & TRIDENT_FMT_16BIT) { | ||
1017 | /* 16-bits */ | ||
1018 | channel->control |= CHANNEL_16BITS; | ||
1019 | /* signed */ | ||
1020 | channel->control |= CHANNEL_SIGNED; | ||
1021 | } | ||
1022 | if (dmabuf->fmt & TRIDENT_FMT_STEREO) | ||
1023 | /* stereo */ | ||
1024 | channel->control |= CHANNEL_STEREO; | ||
1025 | |||
1026 | pr_debug("trident: trident_play_setup, LBA = 0x%08x, Delta = 0x%08x, " | ||
1027 | "ESO = 0x%08x, Control = 0x%08x\n", channel->lba, | ||
1028 | channel->delta, channel->eso, channel->control); | ||
1029 | |||
1030 | trident_write_voice_regs(state); | ||
1031 | } | ||
1032 | |||
1033 | /* prepare channel attributes for recording */ | ||
1034 | static void | ||
1035 | trident_rec_setup(struct trident_state *state) | ||
1036 | { | ||
1037 | u16 w; | ||
1038 | u8 bval; | ||
1039 | |||
1040 | struct trident_card *card = state->card; | ||
1041 | struct dmabuf *dmabuf = &state->dmabuf; | ||
1042 | struct trident_channel *channel = dmabuf->channel; | ||
1043 | unsigned int rate; | ||
1044 | |||
1045 | /* Enable AC-97 ADC (capture) */ | ||
1046 | switch (card->pci_id) { | ||
1047 | case PCI_DEVICE_ID_ALI_5451: | ||
1048 | ali_enable_special_channel(state); | ||
1049 | break; | ||
1050 | case PCI_DEVICE_ID_SI_7018: | ||
1051 | /* for 7018, the ac97 is always in playback/record (duplex) mode */ | ||
1052 | break; | ||
1053 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: | ||
1054 | w = inb(TRID_REG(card, DX_ACR2_AC97_COM_STAT)); | ||
1055 | outb(w | 0x48, TRID_REG(card, DX_ACR2_AC97_COM_STAT)); | ||
1056 | /* enable and set record channel */ | ||
1057 | outb(0x80 | channel->num, TRID_REG(card, T4D_REC_CH)); | ||
1058 | break; | ||
1059 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: | ||
1060 | w = inw(TRID_REG(card, T4D_MISCINT)); | ||
1061 | outw(w | 0x1000, TRID_REG(card, T4D_MISCINT)); | ||
1062 | /* enable and set record channel */ | ||
1063 | outb(0x80 | channel->num, TRID_REG(card, T4D_REC_CH)); | ||
1064 | break; | ||
1065 | case PCI_DEVICE_ID_INTERG_5050: | ||
1066 | /* don't know yet, using special channel 22 in GC1(0xd4)? */ | ||
1067 | break; | ||
1068 | default: | ||
1069 | return; | ||
1070 | } | ||
1071 | |||
1072 | channel->lba = dmabuf->dma_handle; | ||
1073 | channel->delta = compute_rate_rec(dmabuf->rate); | ||
1074 | if ((card->pci_id == PCI_DEVICE_ID_ALI_5451) && | ||
1075 | (channel->num == ALI_SPDIF_IN_CHANNEL)) { | ||
1076 | rate = ali_get_spdif_in_rate(card); | ||
1077 | if (rate == 0) { | ||
1078 | printk(KERN_WARNING "trident: ALi 5451 " | ||
1079 | "S/PDIF input setup error!\n"); | ||
1080 | rate = 48000; | ||
1081 | } | ||
1082 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL)); | ||
1083 | if (bval & 0x10) { | ||
1084 | outb(bval, TRID_REG(card, ALI_SPDIF_CTRL)); | ||
1085 | printk(KERN_WARNING "trident: cleared ALi " | ||
1086 | "5451 S/PDIF parity error flag.\n"); | ||
1087 | } | ||
1088 | |||
1089 | if (rate != 48000) | ||
1090 | channel->delta = ((rate << 12) / dmabuf->rate) & 0x0000ffff; | ||
1091 | } | ||
1092 | |||
1093 | channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt]; | ||
1094 | channel->eso -= 1; | ||
1095 | |||
1096 | if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) { | ||
1097 | channel->attribute = 0; | ||
1098 | } | ||
1099 | |||
1100 | channel->fm_vol = 0x0; | ||
1101 | |||
1102 | channel->control = CHANNEL_LOOP; | ||
1103 | if (dmabuf->fmt & TRIDENT_FMT_16BIT) { | ||
1104 | /* 16-bits */ | ||
1105 | channel->control |= CHANNEL_16BITS; | ||
1106 | /* signed */ | ||
1107 | channel->control |= CHANNEL_SIGNED; | ||
1108 | } | ||
1109 | if (dmabuf->fmt & TRIDENT_FMT_STEREO) | ||
1110 | /* stereo */ | ||
1111 | channel->control |= CHANNEL_STEREO; | ||
1112 | |||
1113 | pr_debug("trident: trident_rec_setup, LBA = 0x%08x, Delat = 0x%08x, " | ||
1114 | "ESO = 0x%08x, Control = 0x%08x\n", channel->lba, | ||
1115 | channel->delta, channel->eso, channel->control); | ||
1116 | |||
1117 | trident_write_voice_regs(state); | ||
1118 | } | ||
1119 | |||
1120 | /* get current playback/recording dma buffer pointer (byte offset from LBA), | ||
1121 | called with spinlock held! */ | ||
1122 | static inline unsigned | ||
1123 | trident_get_dma_addr(struct trident_state *state) | ||
1124 | { | ||
1125 | struct dmabuf *dmabuf = &state->dmabuf; | ||
1126 | u32 cso; | ||
1127 | |||
1128 | if (!dmabuf->enable) | ||
1129 | return 0; | ||
1130 | |||
1131 | outb(dmabuf->channel->num, TRID_REG(state->card, T4D_LFO_GC_CIR)); | ||
1132 | |||
1133 | switch (state->card->pci_id) { | ||
1134 | case PCI_DEVICE_ID_ALI_5451: | ||
1135 | case PCI_DEVICE_ID_SI_7018: | ||
1136 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: | ||
1137 | case PCI_DEVICE_ID_INTERG_5050: | ||
1138 | /* 16 bits ESO, CSO for 7018 and DX */ | ||
1139 | cso = inw(TRID_REG(state->card, CH_DX_CSO_ALPHA_FMS + 2)); | ||
1140 | break; | ||
1141 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: | ||
1142 | /* 24 bits ESO, CSO for NX */ | ||
1143 | cso = inl(TRID_REG(state->card, CH_NX_DELTA_CSO)) & 0x00ffffff; | ||
1144 | break; | ||
1145 | default: | ||
1146 | return 0; | ||
1147 | } | ||
1148 | |||
1149 | pr_debug("trident: trident_get_dma_addr: chip reported channel: %d, " | ||
1150 | "cso = 0x%04x\n", dmabuf->channel->num, cso); | ||
1151 | |||
1152 | /* ESO and CSO are in units of Samples, convert to byte offset */ | ||
1153 | cso <<= sample_shift[dmabuf->fmt]; | ||
1154 | |||
1155 | return (cso % dmabuf->dmasize); | ||
1156 | } | ||
1157 | |||
1158 | /* Stop recording (lock held) */ | ||
1159 | static inline void | ||
1160 | __stop_adc(struct trident_state *state) | ||
1161 | { | ||
1162 | struct dmabuf *dmabuf = &state->dmabuf; | ||
1163 | unsigned int chan_num = dmabuf->channel->num; | ||
1164 | struct trident_card *card = state->card; | ||
1165 | |||
1166 | dmabuf->enable &= ~ADC_RUNNING; | ||
1167 | trident_stop_voice(card, chan_num); | ||
1168 | trident_disable_voice_irq(card, chan_num); | ||
1169 | } | ||
1170 | |||
1171 | static void | ||
1172 | stop_adc(struct trident_state *state) | ||
1173 | { | ||
1174 | struct trident_card *card = state->card; | ||
1175 | unsigned long flags; | ||
1176 | |||
1177 | spin_lock_irqsave(&card->lock, flags); | ||
1178 | __stop_adc(state); | ||
1179 | spin_unlock_irqrestore(&card->lock, flags); | ||
1180 | } | ||
1181 | |||
1182 | static void | ||
1183 | start_adc(struct trident_state *state) | ||
1184 | { | ||
1185 | struct dmabuf *dmabuf = &state->dmabuf; | ||
1186 | unsigned int chan_num = dmabuf->channel->num; | ||
1187 | struct trident_card *card = state->card; | ||
1188 | unsigned long flags; | ||
1189 | |||
1190 | spin_lock_irqsave(&card->lock, flags); | ||
1191 | if ((dmabuf->mapped || | ||
1192 | dmabuf->count < (signed) dmabuf->dmasize) && | ||
1193 | dmabuf->ready) { | ||
1194 | dmabuf->enable |= ADC_RUNNING; | ||
1195 | trident_enable_voice_irq(card, chan_num); | ||
1196 | trident_start_voice(card, chan_num); | ||
1197 | } | ||
1198 | spin_unlock_irqrestore(&card->lock, flags); | ||
1199 | } | ||
1200 | |||
1201 | /* stop playback (lock held) */ | ||
1202 | static inline void | ||
1203 | __stop_dac(struct trident_state *state) | ||
1204 | { | ||
1205 | struct dmabuf *dmabuf = &state->dmabuf; | ||
1206 | unsigned int chan_num = dmabuf->channel->num; | ||
1207 | struct trident_card *card = state->card; | ||
1208 | |||
1209 | dmabuf->enable &= ~DAC_RUNNING; | ||
1210 | trident_stop_voice(card, chan_num); | ||
1211 | if (state->chans_num == 6) { | ||
1212 | trident_stop_voice(card, state->other_states[0]-> | ||
1213 | dmabuf.channel->num); | ||
1214 | trident_stop_voice(card, state->other_states[1]-> | ||
1215 | dmabuf.channel->num); | ||
1216 | trident_stop_voice(card, state->other_states[2]-> | ||
1217 | dmabuf.channel->num); | ||
1218 | trident_stop_voice(card, state->other_states[3]-> | ||
1219 | dmabuf.channel->num); | ||
1220 | } | ||
1221 | trident_disable_voice_irq(card, chan_num); | ||
1222 | } | ||
1223 | |||
1224 | static void | ||
1225 | stop_dac(struct trident_state *state) | ||
1226 | { | ||
1227 | struct trident_card *card = state->card; | ||
1228 | unsigned long flags; | ||
1229 | |||
1230 | spin_lock_irqsave(&card->lock, flags); | ||
1231 | __stop_dac(state); | ||
1232 | spin_unlock_irqrestore(&card->lock, flags); | ||
1233 | } | ||
1234 | |||
1235 | static void | ||
1236 | start_dac(struct trident_state *state) | ||
1237 | { | ||
1238 | struct dmabuf *dmabuf = &state->dmabuf; | ||
1239 | unsigned int chan_num = dmabuf->channel->num; | ||
1240 | struct trident_card *card = state->card; | ||
1241 | unsigned long flags; | ||
1242 | |||
1243 | spin_lock_irqsave(&card->lock, flags); | ||
1244 | if ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) { | ||
1245 | dmabuf->enable |= DAC_RUNNING; | ||
1246 | trident_enable_voice_irq(card, chan_num); | ||
1247 | trident_start_voice(card, chan_num); | ||
1248 | if (state->chans_num == 6) { | ||
1249 | trident_start_voice(card, state->other_states[0]-> | ||
1250 | dmabuf.channel->num); | ||
1251 | trident_start_voice(card, state->other_states[1]-> | ||
1252 | dmabuf.channel->num); | ||
1253 | trident_start_voice(card, state->other_states[2]-> | ||
1254 | dmabuf.channel->num); | ||
1255 | trident_start_voice(card, state->other_states[3]-> | ||
1256 | dmabuf.channel->num); | ||
1257 | } | ||
1258 | } | ||
1259 | spin_unlock_irqrestore(&card->lock, flags); | ||
1260 | } | ||
1261 | |||
1262 | #define DMABUF_DEFAULTORDER (15-PAGE_SHIFT) | ||
1263 | #define DMABUF_MINORDER 1 | ||
1264 | |||
1265 | /* alloc a DMA buffer of with a buffer of this order */ | ||
1266 | static int | ||
1267 | alloc_dmabuf(struct dmabuf *dmabuf, struct pci_dev *pci_dev, int order) | ||
1268 | { | ||
1269 | void *rawbuf = NULL; | ||
1270 | struct page *page, *pend; | ||
1271 | |||
1272 | if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order, | ||
1273 | &dmabuf->dma_handle))) | ||
1274 | return -ENOMEM; | ||
1275 | |||
1276 | pr_debug("trident: allocated %ld (order = %d) bytes at %p\n", | ||
1277 | PAGE_SIZE << order, order, rawbuf); | ||
1278 | |||
1279 | dmabuf->ready = dmabuf->mapped = 0; | ||
1280 | dmabuf->rawbuf = rawbuf; | ||
1281 | dmabuf->buforder = order; | ||
1282 | |||
1283 | /* now mark the pages as reserved; otherwise */ | ||
1284 | /* remap_pfn_range doesn't do what we want */ | ||
1285 | pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1); | ||
1286 | for (page = virt_to_page(rawbuf); page <= pend; page++) | ||
1287 | SetPageReserved(page); | ||
1288 | |||
1289 | return 0; | ||
1290 | } | ||
1291 | |||
1292 | /* allocate the main DMA buffer, playback and recording buffer should be */ | ||
1293 | /* allocated separately */ | ||
1294 | static int | ||
1295 | alloc_main_dmabuf(struct trident_state *state) | ||
1296 | { | ||
1297 | struct dmabuf *dmabuf = &state->dmabuf; | ||
1298 | int order; | ||
1299 | int ret = -ENOMEM; | ||
1300 | |||
1301 | /* alloc as big a chunk as we can, FIXME: is this necessary ?? */ | ||
1302 | for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) { | ||
1303 | if (!(ret = alloc_dmabuf(dmabuf, state->card->pci_dev, order))) | ||
1304 | return 0; | ||
1305 | /* else try again */ | ||
1306 | } | ||
1307 | return ret; | ||
1308 | } | ||
1309 | |||
1310 | /* deallocate a DMA buffer */ | ||
1311 | static void | ||
1312 | dealloc_dmabuf(struct dmabuf *dmabuf, struct pci_dev *pci_dev) | ||
1313 | { | ||
1314 | struct page *page, *pend; | ||
1315 | |||
1316 | if (dmabuf->rawbuf) { | ||
1317 | /* undo marking the pages as reserved */ | ||
1318 | pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); | ||
1319 | for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++) | ||
1320 | ClearPageReserved(page); | ||
1321 | pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder, | ||
1322 | dmabuf->rawbuf, dmabuf->dma_handle); | ||
1323 | dmabuf->rawbuf = NULL; | ||
1324 | } | ||
1325 | dmabuf->mapped = dmabuf->ready = 0; | ||
1326 | } | ||
1327 | |||
1328 | static int | ||
1329 | prog_dmabuf(struct trident_state *state, enum dmabuf_mode rec) | ||
1330 | { | ||
1331 | struct dmabuf *dmabuf = &state->dmabuf; | ||
1332 | unsigned bytepersec; | ||
1333 | struct trident_state *s = state; | ||
1334 | unsigned bufsize, dma_nums; | ||
1335 | unsigned long flags; | ||
1336 | int ret, i, order; | ||
1337 | |||
1338 | if ((ret = lock_set_fmt(state)) < 0) | ||
1339 | return ret; | ||
1340 | |||
1341 | if (state->chans_num == 6) | ||
1342 | dma_nums = 5; | ||
1343 | else | ||
1344 | dma_nums = 1; | ||
1345 | |||
1346 | for (i = 0; i < dma_nums; i++) { | ||
1347 | if (i > 0) { | ||
1348 | s = state->other_states[i - 1]; | ||
1349 | dmabuf = &s->dmabuf; | ||
1350 | dmabuf->fmt = state->dmabuf.fmt; | ||
1351 | dmabuf->rate = state->dmabuf.rate; | ||
1352 | } | ||
1353 | |||
1354 | spin_lock_irqsave(&s->card->lock, flags); | ||
1355 | dmabuf->hwptr = dmabuf->swptr = dmabuf->total_bytes = 0; | ||
1356 | dmabuf->count = dmabuf->error = 0; | ||
1357 | spin_unlock_irqrestore(&s->card->lock, flags); | ||
1358 | |||
1359 | /* allocate DMA buffer if not allocated yet */ | ||
1360 | if (!dmabuf->rawbuf) { | ||
1361 | if (i == 0) { | ||
1362 | if ((ret = alloc_main_dmabuf(state))) { | ||
1363 | unlock_set_fmt(state); | ||
1364 | return ret; | ||
1365 | } | ||
1366 | } else { | ||
1367 | ret = -ENOMEM; | ||
1368 | order = state->dmabuf.buforder - 1; | ||
1369 | if (order >= DMABUF_MINORDER) { | ||
1370 | ret = alloc_dmabuf(dmabuf, | ||
1371 | state->card->pci_dev, | ||
1372 | order); | ||
1373 | } | ||
1374 | if (ret) { | ||
1375 | /* release the main DMA buffer */ | ||
1376 | dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); | ||
1377 | /* release the auxiliary DMA buffers */ | ||
1378 | for (i -= 2; i >= 0; i--) | ||
1379 | dealloc_dmabuf(&state->other_states[i]->dmabuf, | ||
1380 | state->card->pci_dev); | ||
1381 | unlock_set_fmt(state); | ||
1382 | return ret; | ||
1383 | } | ||
1384 | } | ||
1385 | } | ||
1386 | /* FIXME: figure out all this OSS fragment stuff */ | ||
1387 | bytepersec = dmabuf->rate << sample_shift[dmabuf->fmt]; | ||
1388 | bufsize = PAGE_SIZE << dmabuf->buforder; | ||
1389 | if (dmabuf->ossfragshift) { | ||
1390 | if ((1000 << dmabuf->ossfragshift) < bytepersec) | ||
1391 | dmabuf->fragshift = ld2(bytepersec / 1000); | ||
1392 | else | ||
1393 | dmabuf->fragshift = dmabuf->ossfragshift; | ||
1394 | } else { | ||
1395 | /* lets hand out reasonable big ass buffers by default */ | ||
1396 | dmabuf->fragshift = (dmabuf->buforder + PAGE_SHIFT - 2); | ||
1397 | } | ||
1398 | dmabuf->numfrag = bufsize >> dmabuf->fragshift; | ||
1399 | while (dmabuf->numfrag < 4 && dmabuf->fragshift > 3) { | ||
1400 | dmabuf->fragshift--; | ||
1401 | dmabuf->numfrag = bufsize >> dmabuf->fragshift; | ||
1402 | } | ||
1403 | dmabuf->fragsize = 1 << dmabuf->fragshift; | ||
1404 | if (dmabuf->ossmaxfrags >= 4 && dmabuf->ossmaxfrags < dmabuf->numfrag) | ||
1405 | dmabuf->numfrag = dmabuf->ossmaxfrags; | ||
1406 | dmabuf->fragsamples = dmabuf->fragsize >> sample_shift[dmabuf->fmt]; | ||
1407 | dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift; | ||
1408 | |||
1409 | memset(dmabuf->rawbuf, (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80, | ||
1410 | dmabuf->dmasize); | ||
1411 | |||
1412 | spin_lock_irqsave(&s->card->lock, flags); | ||
1413 | if (rec == DM_RECORD) | ||
1414 | trident_rec_setup(s); | ||
1415 | else /* DM_PLAYBACK */ | ||
1416 | trident_play_setup(s); | ||
1417 | |||
1418 | spin_unlock_irqrestore(&s->card->lock, flags); | ||
1419 | |||
1420 | /* set the ready flag for the dma buffer */ | ||
1421 | dmabuf->ready = 1; | ||
1422 | |||
1423 | pr_debug("trident: prog_dmabuf(%d), sample rate = %d, " | ||
1424 | "format = %d, numfrag = %d, fragsize = %d " | ||
1425 | "dmasize = %d\n", dmabuf->channel->num, | ||
1426 | dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, | ||
1427 | dmabuf->fragsize, dmabuf->dmasize); | ||
1428 | } | ||
1429 | unlock_set_fmt(state); | ||
1430 | return 0; | ||
1431 | } | ||
1432 | |||
1433 | |||
1434 | static inline int prog_dmabuf_record(struct trident_state* state) | ||
1435 | { | ||
1436 | return prog_dmabuf(state, DM_RECORD); | ||
1437 | } | ||
1438 | |||
1439 | static inline int prog_dmabuf_playback(struct trident_state* state) | ||
1440 | { | ||
1441 | return prog_dmabuf(state, DM_PLAYBACK); | ||
1442 | } | ||
1443 | |||
1444 | /* we are doing quantum mechanics here, the buffer can only be empty, half or full filled i.e. | ||
1445 | |------------|------------| or |xxxxxxxxxxxx|------------| or |xxxxxxxxxxxx|xxxxxxxxxxxx| | ||
1446 | but we almost always get this | ||
1447 | |xxxxxx------|------------| or |xxxxxxxxxxxx|xxxxx-------| | ||
1448 | so we have to clear the tail space to "silence" | ||
1449 | |xxxxxx000000|------------| or |xxxxxxxxxxxx|xxxxxx000000| | ||
1450 | */ | ||
1451 | static void | ||
1452 | trident_clear_tail(struct trident_state *state) | ||
1453 | { | ||
1454 | struct dmabuf *dmabuf = &state->dmabuf; | ||
1455 | unsigned swptr; | ||
1456 | unsigned char silence = (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80; | ||
1457 | unsigned int len; | ||
1458 | unsigned long flags; | ||
1459 | |||
1460 | spin_lock_irqsave(&state->card->lock, flags); | ||
1461 | swptr = dmabuf->swptr; | ||
1462 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
1463 | |||
1464 | if (swptr == 0 || swptr == dmabuf->dmasize / 2 || | ||
1465 | swptr == dmabuf->dmasize) | ||
1466 | return; | ||
1467 | |||
1468 | if (swptr < dmabuf->dmasize / 2) | ||
1469 | len = dmabuf->dmasize / 2 - swptr; | ||
1470 | else | ||
1471 | len = dmabuf->dmasize - swptr; | ||
1472 | |||
1473 | memset(dmabuf->rawbuf + swptr, silence, len); | ||
1474 | if (state->card->pci_id != PCI_DEVICE_ID_ALI_5451) { | ||
1475 | spin_lock_irqsave(&state->card->lock, flags); | ||
1476 | dmabuf->swptr += len; | ||
1477 | dmabuf->count += len; | ||
1478 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
1479 | } | ||
1480 | |||
1481 | /* restart the dma machine in case it is halted */ | ||
1482 | start_dac(state); | ||
1483 | } | ||
1484 | |||
1485 | static int | ||
1486 | drain_dac(struct trident_state *state, int nonblock) | ||
1487 | { | ||
1488 | DECLARE_WAITQUEUE(wait, current); | ||
1489 | struct dmabuf *dmabuf = &state->dmabuf; | ||
1490 | unsigned long flags; | ||
1491 | unsigned long tmo; | ||
1492 | int count; | ||
1493 | unsigned long diff = 0; | ||
1494 | |||
1495 | if (dmabuf->mapped || !dmabuf->ready) | ||
1496 | return 0; | ||
1497 | |||
1498 | add_wait_queue(&dmabuf->wait, &wait); | ||
1499 | for (;;) { | ||
1500 | /* It seems that we have to set the current state to TASK_INTERRUPTIBLE | ||
1501 | every time to make the process really go to sleep */ | ||
1502 | set_current_state(TASK_INTERRUPTIBLE); | ||
1503 | |||
1504 | spin_lock_irqsave(&state->card->lock, flags); | ||
1505 | count = dmabuf->count; | ||
1506 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
1507 | |||
1508 | if (count <= 0) | ||
1509 | break; | ||
1510 | |||
1511 | if (signal_pending(current)) | ||
1512 | break; | ||
1513 | |||
1514 | if (nonblock) { | ||
1515 | remove_wait_queue(&dmabuf->wait, &wait); | ||
1516 | set_current_state(TASK_RUNNING); | ||
1517 | return -EBUSY; | ||
1518 | } | ||
1519 | |||
1520 | /* No matter how much data is left in the buffer, we have to wait until | ||
1521 | CSO == ESO/2 or CSO == ESO when address engine interrupts */ | ||
1522 | if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451 || | ||
1523 | state->card->pci_id == PCI_DEVICE_ID_INTERG_5050) { | ||
1524 | diff = dmabuf->swptr - trident_get_dma_addr(state) + dmabuf->dmasize; | ||
1525 | diff = diff % (dmabuf->dmasize); | ||
1526 | tmo = (diff * HZ) / dmabuf->rate; | ||
1527 | } else { | ||
1528 | tmo = (dmabuf->dmasize * HZ) / dmabuf->rate; | ||
1529 | } | ||
1530 | tmo >>= sample_shift[dmabuf->fmt]; | ||
1531 | if (!schedule_timeout(tmo ? tmo : 1) && tmo) { | ||
1532 | break; | ||
1533 | } | ||
1534 | } | ||
1535 | remove_wait_queue(&dmabuf->wait, &wait); | ||
1536 | set_current_state(TASK_RUNNING); | ||
1537 | if (signal_pending(current)) | ||
1538 | return -ERESTARTSYS; | ||
1539 | |||
1540 | return 0; | ||
1541 | } | ||
1542 | |||
1543 | /* update buffer manangement pointers, especially, */ | ||
1544 | /* dmabuf->count and dmabuf->hwptr */ | ||
1545 | static void | ||
1546 | trident_update_ptr(struct trident_state *state) | ||
1547 | { | ||
1548 | struct dmabuf *dmabuf = &state->dmabuf; | ||
1549 | unsigned hwptr, swptr; | ||
1550 | int clear_cnt = 0; | ||
1551 | int diff; | ||
1552 | unsigned char silence; | ||
1553 | unsigned half_dmasize; | ||
1554 | |||
1555 | /* update hardware pointer */ | ||
1556 | hwptr = trident_get_dma_addr(state); | ||
1557 | diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; | ||
1558 | dmabuf->hwptr = hwptr; | ||
1559 | dmabuf->total_bytes += diff; | ||
1560 | |||
1561 | /* error handling and process wake up for ADC */ | ||
1562 | if (dmabuf->enable == ADC_RUNNING) { | ||
1563 | if (dmabuf->mapped) { | ||
1564 | dmabuf->count -= diff; | ||
1565 | if (dmabuf->count >= (signed) dmabuf->fragsize) | ||
1566 | wake_up(&dmabuf->wait); | ||
1567 | } else { | ||
1568 | dmabuf->count += diff; | ||
1569 | |||
1570 | if (dmabuf->count < 0 || | ||
1571 | dmabuf->count > dmabuf->dmasize) { | ||
1572 | /* buffer underrun or buffer overrun, */ | ||
1573 | /* we have no way to recover it here, just */ | ||
1574 | /* stop the machine and let the process */ | ||
1575 | /* force hwptr and swptr to sync */ | ||
1576 | __stop_adc(state); | ||
1577 | dmabuf->error++; | ||
1578 | } | ||
1579 | if (dmabuf->count < (signed) dmabuf->dmasize / 2) | ||
1580 | wake_up(&dmabuf->wait); | ||
1581 | } | ||
1582 | } | ||
1583 | |||
1584 | /* error handling and process wake up for DAC */ | ||
1585 | if (dmabuf->enable == DAC_RUNNING) { | ||
1586 | if (dmabuf->mapped) { | ||
1587 | dmabuf->count += diff; | ||
1588 | if (dmabuf->count >= (signed) dmabuf->fragsize) | ||
1589 | wake_up(&dmabuf->wait); | ||
1590 | } else { | ||
1591 | dmabuf->count -= diff; | ||
1592 | |||
1593 | if (dmabuf->count < 0 || | ||
1594 | dmabuf->count > dmabuf->dmasize) { | ||
1595 | /* buffer underrun or buffer overrun, we have no way to recover | ||
1596 | it here, just stop the machine and let the process force hwptr | ||
1597 | and swptr to sync */ | ||
1598 | __stop_dac(state); | ||
1599 | dmabuf->error++; | ||
1600 | } else if (!dmabuf->endcleared) { | ||
1601 | swptr = dmabuf->swptr; | ||
1602 | silence = (dmabuf->fmt & TRIDENT_FMT_16BIT ? 0 : 0x80); | ||
1603 | if (dmabuf->update_flag & ALI_ADDRESS_INT_UPDATE) { | ||
1604 | /* We must clear end data of 1/2 dmabuf if needed. | ||
1605 | According to 1/2 algorithm of Address Engine Interrupt, | ||
1606 | check the validation of the data of half dmasize. */ | ||
1607 | half_dmasize = dmabuf->dmasize / 2; | ||
1608 | if ((diff = hwptr - half_dmasize) < 0) | ||
1609 | diff = hwptr; | ||
1610 | if ((dmabuf->count + diff) < half_dmasize) { | ||
1611 | //there is invalid data in the end of half buffer | ||
1612 | if ((clear_cnt = half_dmasize - swptr) < 0) | ||
1613 | clear_cnt += half_dmasize; | ||
1614 | //clear the invalid data | ||
1615 | memset(dmabuf->rawbuf + swptr, silence, clear_cnt); | ||
1616 | if (state->chans_num == 6) { | ||
1617 | clear_cnt = clear_cnt / 2; | ||
1618 | swptr = swptr / 2; | ||
1619 | memset(state->other_states[0]->dmabuf.rawbuf + swptr, | ||
1620 | silence, clear_cnt); | ||
1621 | memset(state->other_states[1]->dmabuf.rawbuf + swptr, | ||
1622 | silence, clear_cnt); | ||
1623 | memset(state->other_states[2]->dmabuf.rawbuf + swptr, | ||
1624 | silence, clear_cnt); | ||
1625 | memset(state->other_states[3]->dmabuf.rawbuf + swptr, | ||
1626 | silence, clear_cnt); | ||
1627 | } | ||
1628 | dmabuf->endcleared = 1; | ||
1629 | } | ||
1630 | } else if (dmabuf->count < (signed) dmabuf->fragsize) { | ||
1631 | clear_cnt = dmabuf->fragsize; | ||
1632 | if ((swptr + clear_cnt) > dmabuf->dmasize) | ||
1633 | clear_cnt = dmabuf->dmasize - swptr; | ||
1634 | memset(dmabuf->rawbuf + swptr, silence, clear_cnt); | ||
1635 | if (state->chans_num == 6) { | ||
1636 | clear_cnt = clear_cnt / 2; | ||
1637 | swptr = swptr / 2; | ||
1638 | memset(state->other_states[0]->dmabuf.rawbuf + swptr, | ||
1639 | silence, clear_cnt); | ||
1640 | memset(state->other_states[1]->dmabuf.rawbuf + swptr, | ||
1641 | silence, clear_cnt); | ||
1642 | memset(state->other_states[2]->dmabuf.rawbuf + swptr, | ||
1643 | silence, clear_cnt); | ||
1644 | memset(state->other_states[3]->dmabuf.rawbuf + swptr, | ||
1645 | silence, clear_cnt); | ||
1646 | } | ||
1647 | dmabuf->endcleared = 1; | ||
1648 | } | ||
1649 | } | ||
1650 | /* trident_update_ptr is called by interrupt handler or by process via | ||
1651 | ioctl/poll, we only wake up the waiting process when we have more | ||
1652 | than 1/2 buffer free (always true for interrupt handler) */ | ||
1653 | if (dmabuf->count < (signed) dmabuf->dmasize / 2) | ||
1654 | wake_up(&dmabuf->wait); | ||
1655 | } | ||
1656 | } | ||
1657 | dmabuf->update_flag &= ~ALI_ADDRESS_INT_UPDATE; | ||
1658 | } | ||
1659 | |||
1660 | static void | ||
1661 | trident_address_interrupt(struct trident_card *card) | ||
1662 | { | ||
1663 | int i; | ||
1664 | struct trident_state *state; | ||
1665 | unsigned int channel; | ||
1666 | |||
1667 | /* Update the pointers for all channels we are running. */ | ||
1668 | /* FIXME: should read interrupt status only once */ | ||
1669 | for (i = 0; i < NR_HW_CH; i++) { | ||
1670 | channel = 63 - i; | ||
1671 | if (trident_check_channel_interrupt(card, channel)) { | ||
1672 | trident_ack_channel_interrupt(card, channel); | ||
1673 | if ((state = card->states[i]) != NULL) { | ||
1674 | trident_update_ptr(state); | ||
1675 | } else { | ||
1676 | printk(KERN_WARNING "trident: spurious channel " | ||
1677 | "irq %d.\n", channel); | ||
1678 | trident_stop_voice(card, channel); | ||
1679 | trident_disable_voice_irq(card, channel); | ||
1680 | } | ||
1681 | } | ||
1682 | } | ||
1683 | } | ||
1684 | |||
1685 | static void | ||
1686 | ali_hwvol_control(struct trident_card *card, int opt) | ||
1687 | { | ||
1688 | u16 dwTemp, volume[2], mute, diff, *pVol[2]; | ||
1689 | |||
1690 | dwTemp = ali_ac97_read(card->ac97_codec[0], 0x02); | ||
1691 | mute = dwTemp & 0x8000; | ||
1692 | volume[0] = dwTemp & 0x001f; | ||
1693 | volume[1] = (dwTemp & 0x1f00) >> 8; | ||
1694 | if (volume[0] < volume[1]) { | ||
1695 | pVol[0] = &volume[0]; | ||
1696 | pVol[1] = &volume[1]; | ||
1697 | } else { | ||
1698 | pVol[1] = &volume[0]; | ||
1699 | pVol[0] = &volume[1]; | ||
1700 | } | ||
1701 | diff = *(pVol[1]) - *(pVol[0]); | ||
1702 | |||
1703 | if (opt == 1) { // MUTE | ||
1704 | dwTemp ^= 0x8000; | ||
1705 | ali_ac97_write(card->ac97_codec[0], | ||
1706 | 0x02, dwTemp); | ||
1707 | } else if (opt == 2) { // Down | ||
1708 | if (mute) | ||
1709 | return; | ||
1710 | if (*(pVol[1]) < 0x001f) { | ||
1711 | (*pVol[1])++; | ||
1712 | *(pVol[0]) = *(pVol[1]) - diff; | ||
1713 | } | ||
1714 | dwTemp &= 0xe0e0; | ||
1715 | dwTemp |= (volume[0]) | (volume[1] << 8); | ||
1716 | ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp); | ||
1717 | card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) | | ||
1718 | (((32 - volume[1]) * 25 / 8) << 8); | ||
1719 | } else if (opt == 4) { // Up | ||
1720 | if (mute) | ||
1721 | return; | ||
1722 | if (*(pVol[0]) > 0) { | ||
1723 | (*pVol[0])--; | ||
1724 | *(pVol[1]) = *(pVol[0]) + diff; | ||
1725 | } | ||
1726 | dwTemp &= 0xe0e0; | ||
1727 | dwTemp |= (volume[0]) | (volume[1] << 8); | ||
1728 | ali_ac97_write(card->ac97_codec[0], 0x02, dwTemp); | ||
1729 | card->ac97_codec[0]->mixer_state[0] = ((32 - volume[0]) * 25 / 8) | | ||
1730 | (((32 - volume[1]) * 25 / 8) << 8); | ||
1731 | } else { | ||
1732 | /* Nothing needs doing */ | ||
1733 | } | ||
1734 | } | ||
1735 | |||
1736 | /* | ||
1737 | * Re-enable reporting of vol change after 0.1 seconds | ||
1738 | */ | ||
1739 | |||
1740 | static void | ||
1741 | ali_timeout(unsigned long ptr) | ||
1742 | { | ||
1743 | struct trident_card *card = (struct trident_card *) ptr; | ||
1744 | u16 temp = 0; | ||
1745 | |||
1746 | /* Enable GPIO IRQ (MISCINT bit 18h) */ | ||
1747 | temp = inw(TRID_REG(card, T4D_MISCINT + 2)); | ||
1748 | temp |= 0x0004; | ||
1749 | outw(temp, TRID_REG(card, T4D_MISCINT + 2)); | ||
1750 | } | ||
1751 | |||
1752 | /* | ||
1753 | * Set up the timer to clear the vol change notification | ||
1754 | */ | ||
1755 | |||
1756 | static void | ||
1757 | ali_set_timer(struct trident_card *card) | ||
1758 | { | ||
1759 | /* Add Timer Routine to Enable GPIO IRQ */ | ||
1760 | del_timer(&card->timer); /* Never queue twice */ | ||
1761 | card->timer.function = ali_timeout; | ||
1762 | card->timer.data = (unsigned long) card; | ||
1763 | card->timer.expires = jiffies + HZ / 10; | ||
1764 | add_timer(&card->timer); | ||
1765 | } | ||
1766 | |||
1767 | /* | ||
1768 | * Process a GPIO event | ||
1769 | */ | ||
1770 | |||
1771 | static void | ||
1772 | ali_queue_task(struct trident_card *card, int opt) | ||
1773 | { | ||
1774 | u16 temp; | ||
1775 | |||
1776 | /* Disable GPIO IRQ (MISCINT bit 18h) */ | ||
1777 | temp = inw(TRID_REG(card, T4D_MISCINT + 2)); | ||
1778 | temp &= (u16) (~0x0004); | ||
1779 | outw(temp, TRID_REG(card, T4D_MISCINT + 2)); | ||
1780 | |||
1781 | /* Adjust the volume */ | ||
1782 | ali_hwvol_control(card, opt); | ||
1783 | |||
1784 | /* Set the timer for 1/10th sec */ | ||
1785 | ali_set_timer(card); | ||
1786 | } | ||
1787 | |||
1788 | static void | ||
1789 | cyber_address_interrupt(struct trident_card *card) | ||
1790 | { | ||
1791 | int i, irq_status; | ||
1792 | struct trident_state *state; | ||
1793 | unsigned int channel; | ||
1794 | |||
1795 | /* Update the pointers for all channels we are running. */ | ||
1796 | /* FIXED: read interrupt status only once */ | ||
1797 | irq_status = inl(TRID_REG(card, T4D_AINT_A)); | ||
1798 | |||
1799 | pr_debug("cyber_address_interrupt: irq_status 0x%X\n", irq_status); | ||
1800 | |||
1801 | for (i = 0; i < NR_HW_CH; i++) { | ||
1802 | channel = 31 - i; | ||
1803 | if (irq_status & (1 << channel)) { | ||
1804 | /* clear bit by writing a 1, zeroes are ignored */ | ||
1805 | outl((1 << channel), TRID_REG(card, T4D_AINT_A)); | ||
1806 | |||
1807 | pr_debug("cyber_interrupt: channel %d\n", channel); | ||
1808 | |||
1809 | if ((state = card->states[i]) != NULL) { | ||
1810 | trident_update_ptr(state); | ||
1811 | } else { | ||
1812 | printk(KERN_WARNING "cyber5050: spurious " | ||
1813 | "channel irq %d.\n", channel); | ||
1814 | trident_stop_voice(card, channel); | ||
1815 | trident_disable_voice_irq(card, channel); | ||
1816 | } | ||
1817 | } | ||
1818 | } | ||
1819 | } | ||
1820 | |||
1821 | static irqreturn_t | ||
1822 | trident_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
1823 | { | ||
1824 | struct trident_card *card = (struct trident_card *) dev_id; | ||
1825 | u32 event; | ||
1826 | u32 gpio; | ||
1827 | |||
1828 | spin_lock(&card->lock); | ||
1829 | event = inl(TRID_REG(card, T4D_MISCINT)); | ||
1830 | |||
1831 | pr_debug("trident: trident_interrupt called, MISCINT = 0x%08x\n", | ||
1832 | event); | ||
1833 | |||
1834 | if (event & ADDRESS_IRQ) { | ||
1835 | card->address_interrupt(card); | ||
1836 | } | ||
1837 | |||
1838 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | ||
1839 | /* GPIO IRQ (H/W Volume Control) */ | ||
1840 | event = inl(TRID_REG(card, T4D_MISCINT)); | ||
1841 | if (event & (1 << 25)) { | ||
1842 | gpio = inl(TRID_REG(card, ALI_GPIO)); | ||
1843 | if (!timer_pending(&card->timer)) | ||
1844 | ali_queue_task(card, gpio & 0x07); | ||
1845 | } | ||
1846 | event = inl(TRID_REG(card, T4D_MISCINT)); | ||
1847 | outl(event | (ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), | ||
1848 | TRID_REG(card, T4D_MISCINT)); | ||
1849 | spin_unlock(&card->lock); | ||
1850 | return IRQ_HANDLED; | ||
1851 | } | ||
1852 | |||
1853 | /* manually clear interrupt status, bad hardware design, blame T^2 */ | ||
1854 | outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), | ||
1855 | TRID_REG(card, T4D_MISCINT)); | ||
1856 | spin_unlock(&card->lock); | ||
1857 | return IRQ_HANDLED; | ||
1858 | } | ||
1859 | |||
1860 | /* in this loop, dmabuf.count signifies the amount of data that is waiting */ | ||
1861 | /* to be copied to the user's buffer. it is filled by the dma machine and */ | ||
1862 | /* drained by this loop. */ | ||
1863 | static ssize_t | ||
1864 | trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos) | ||
1865 | { | ||
1866 | struct trident_state *state = (struct trident_state *)file->private_data; | ||
1867 | struct dmabuf *dmabuf = &state->dmabuf; | ||
1868 | ssize_t ret = 0; | ||
1869 | unsigned long flags; | ||
1870 | unsigned swptr; | ||
1871 | int cnt; | ||
1872 | |||
1873 | pr_debug("trident: trident_read called, count = %d\n", count); | ||
1874 | |||
1875 | VALIDATE_STATE(state); | ||
1876 | |||
1877 | if (dmabuf->mapped) | ||
1878 | return -ENXIO; | ||
1879 | if (!access_ok(VERIFY_WRITE, buffer, count)) | ||
1880 | return -EFAULT; | ||
1881 | |||
1882 | down(&state->sem); | ||
1883 | if (!dmabuf->ready && (ret = prog_dmabuf_record(state))) | ||
1884 | goto out; | ||
1885 | |||
1886 | while (count > 0) { | ||
1887 | spin_lock_irqsave(&state->card->lock, flags); | ||
1888 | if (dmabuf->count > (signed) dmabuf->dmasize) { | ||
1889 | /* buffer overrun, we are recovering from */ | ||
1890 | /* sleep_on_timeout, resync hwptr and swptr, */ | ||
1891 | /* make process flush the buffer */ | ||
1892 | dmabuf->count = dmabuf->dmasize; | ||
1893 | dmabuf->swptr = dmabuf->hwptr; | ||
1894 | } | ||
1895 | swptr = dmabuf->swptr; | ||
1896 | cnt = dmabuf->dmasize - swptr; | ||
1897 | if (dmabuf->count < cnt) | ||
1898 | cnt = dmabuf->count; | ||
1899 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
1900 | |||
1901 | if (cnt > count) | ||
1902 | cnt = count; | ||
1903 | if (cnt <= 0) { | ||
1904 | unsigned long tmo; | ||
1905 | /* buffer is empty, start the dma machine and */ | ||
1906 | /* wait for data to be recorded */ | ||
1907 | start_adc(state); | ||
1908 | if (file->f_flags & O_NONBLOCK) { | ||
1909 | if (!ret) | ||
1910 | ret = -EAGAIN; | ||
1911 | goto out; | ||
1912 | } | ||
1913 | |||
1914 | up(&state->sem); | ||
1915 | /* No matter how much space left in the buffer, */ | ||
1916 | /* we have to wait until CSO == ESO/2 or CSO == ESO */ | ||
1917 | /* when address engine interrupts */ | ||
1918 | tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); | ||
1919 | tmo >>= sample_shift[dmabuf->fmt]; | ||
1920 | /* There are two situations when sleep_on_timeout returns, one is when | ||
1921 | the interrupt is serviced correctly and the process is waked up by | ||
1922 | ISR ON TIME. Another is when timeout is expired, which means that | ||
1923 | either interrupt is NOT serviced correctly (pending interrupt) or it | ||
1924 | is TOO LATE for the process to be scheduled to run (scheduler latency) | ||
1925 | which results in a (potential) buffer overrun. And worse, there is | ||
1926 | NOTHING we can do to prevent it. */ | ||
1927 | if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { | ||
1928 | pr_debug(KERN_ERR "trident: recording schedule timeout, " | ||
1929 | "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", | ||
1930 | dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, | ||
1931 | dmabuf->hwptr, dmabuf->swptr); | ||
1932 | |||
1933 | /* a buffer overrun, we delay the recovery until next time the | ||
1934 | while loop begin and we REALLY have space to record */ | ||
1935 | } | ||
1936 | if (signal_pending(current)) { | ||
1937 | if (!ret) | ||
1938 | ret = -ERESTARTSYS; | ||
1939 | goto out; | ||
1940 | } | ||
1941 | down(&state->sem); | ||
1942 | if (dmabuf->mapped) { | ||
1943 | if (!ret) | ||
1944 | ret = -ENXIO; | ||
1945 | goto out; | ||
1946 | } | ||
1947 | continue; | ||
1948 | } | ||
1949 | |||
1950 | if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) { | ||
1951 | if (!ret) | ||
1952 | ret = -EFAULT; | ||
1953 | goto out; | ||
1954 | } | ||
1955 | |||
1956 | swptr = (swptr + cnt) % dmabuf->dmasize; | ||
1957 | |||
1958 | spin_lock_irqsave(&state->card->lock, flags); | ||
1959 | dmabuf->swptr = swptr; | ||
1960 | dmabuf->count -= cnt; | ||
1961 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
1962 | |||
1963 | count -= cnt; | ||
1964 | buffer += cnt; | ||
1965 | ret += cnt; | ||
1966 | start_adc(state); | ||
1967 | } | ||
1968 | out: | ||
1969 | up(&state->sem); | ||
1970 | return ret; | ||
1971 | } | ||
1972 | |||
1973 | /* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to | ||
1974 | the soundcard. it is drained by the dma machine and filled by this loop. */ | ||
1975 | |||
1976 | static ssize_t | ||
1977 | trident_write(struct file *file, const char __user *buffer, size_t count, loff_t * ppos) | ||
1978 | { | ||
1979 | struct trident_state *state = (struct trident_state *)file->private_data; | ||
1980 | struct dmabuf *dmabuf = &state->dmabuf; | ||
1981 | ssize_t ret; | ||
1982 | unsigned long flags; | ||
1983 | unsigned swptr; | ||
1984 | int cnt; | ||
1985 | unsigned int state_cnt; | ||
1986 | unsigned int copy_count; | ||
1987 | int lret; /* for lock_set_fmt */ | ||
1988 | |||
1989 | pr_debug("trident: trident_write called, count = %d\n", count); | ||
1990 | |||
1991 | VALIDATE_STATE(state); | ||
1992 | |||
1993 | /* | ||
1994 | * Guard against an mmap or ioctl while writing | ||
1995 | */ | ||
1996 | |||
1997 | down(&state->sem); | ||
1998 | |||
1999 | if (dmabuf->mapped) { | ||
2000 | ret = -ENXIO; | ||
2001 | goto out; | ||
2002 | } | ||
2003 | if (!dmabuf->ready && (ret = prog_dmabuf_playback(state))) | ||
2004 | goto out; | ||
2005 | |||
2006 | if (!access_ok(VERIFY_READ, buffer, count)) { | ||
2007 | ret = -EFAULT; | ||
2008 | goto out; | ||
2009 | } | ||
2010 | |||
2011 | ret = 0; | ||
2012 | |||
2013 | while (count > 0) { | ||
2014 | spin_lock_irqsave(&state->card->lock, flags); | ||
2015 | if (dmabuf->count < 0) { | ||
2016 | /* buffer underrun, we are recovering from */ | ||
2017 | /* sleep_on_timeout, resync hwptr and swptr */ | ||
2018 | dmabuf->count = 0; | ||
2019 | dmabuf->swptr = dmabuf->hwptr; | ||
2020 | } | ||
2021 | swptr = dmabuf->swptr; | ||
2022 | cnt = dmabuf->dmasize - swptr; | ||
2023 | if (dmabuf->count + cnt > dmabuf->dmasize) | ||
2024 | cnt = dmabuf->dmasize - dmabuf->count; | ||
2025 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
2026 | |||
2027 | if (cnt > count) | ||
2028 | cnt = count; | ||
2029 | if (cnt <= 0) { | ||
2030 | unsigned long tmo; | ||
2031 | /* buffer is full, start the dma machine and */ | ||
2032 | /* wait for data to be played */ | ||
2033 | start_dac(state); | ||
2034 | if (file->f_flags & O_NONBLOCK) { | ||
2035 | if (!ret) | ||
2036 | ret = -EAGAIN; | ||
2037 | goto out; | ||
2038 | } | ||
2039 | /* No matter how much data left in the buffer, */ | ||
2040 | /* we have to wait until CSO == ESO/2 or CSO == ESO */ | ||
2041 | /* when address engine interrupts */ | ||
2042 | lock_set_fmt(state); | ||
2043 | tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); | ||
2044 | tmo >>= sample_shift[dmabuf->fmt]; | ||
2045 | unlock_set_fmt(state); | ||
2046 | up(&state->sem); | ||
2047 | |||
2048 | /* There are two situations when sleep_on_timeout */ | ||
2049 | /* returns, one is when the interrupt is serviced */ | ||
2050 | /* correctly and the process is waked up by ISR */ | ||
2051 | /* ON TIME. Another is when timeout is expired, which */ | ||
2052 | /* means that either interrupt is NOT serviced */ | ||
2053 | /* correctly (pending interrupt) or it is TOO LATE */ | ||
2054 | /* for the process to be scheduled to run */ | ||
2055 | /* (scheduler latency) which results in a (potential) */ | ||
2056 | /* buffer underrun. And worse, there is NOTHING we */ | ||
2057 | /* can do to prevent it. */ | ||
2058 | if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { | ||
2059 | pr_debug(KERN_ERR "trident: playback schedule " | ||
2060 | "timeout, dmasz %u fragsz %u count %i " | ||
2061 | "hwptr %u swptr %u\n", dmabuf->dmasize, | ||
2062 | dmabuf->fragsize, dmabuf->count, | ||
2063 | dmabuf->hwptr, dmabuf->swptr); | ||
2064 | |||
2065 | /* a buffer underrun, we delay the recovery */ | ||
2066 | /* until next time the while loop begin and */ | ||
2067 | /* we REALLY have data to play */ | ||
2068 | } | ||
2069 | if (signal_pending(current)) { | ||
2070 | if (!ret) | ||
2071 | ret = -ERESTARTSYS; | ||
2072 | goto out_nolock; | ||
2073 | } | ||
2074 | down(&state->sem); | ||
2075 | if (dmabuf->mapped) { | ||
2076 | if (!ret) | ||
2077 | ret = -ENXIO; | ||
2078 | goto out; | ||
2079 | } | ||
2080 | continue; | ||
2081 | } | ||
2082 | if ((lret = lock_set_fmt(state)) < 0) { | ||
2083 | ret = lret; | ||
2084 | goto out; | ||
2085 | } | ||
2086 | |||
2087 | if (state->chans_num == 6) { | ||
2088 | copy_count = 0; | ||
2089 | state_cnt = 0; | ||
2090 | if (ali_write_5_1(state, buffer, cnt, ©_count, | ||
2091 | &state_cnt) == -EFAULT) { | ||
2092 | if (state_cnt) { | ||
2093 | swptr = (swptr + state_cnt) % dmabuf->dmasize; | ||
2094 | spin_lock_irqsave(&state->card->lock, flags); | ||
2095 | dmabuf->swptr = swptr; | ||
2096 | dmabuf->count += state_cnt; | ||
2097 | dmabuf->endcleared = 0; | ||
2098 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
2099 | } | ||
2100 | ret += copy_count; | ||
2101 | if (!ret) | ||
2102 | ret = -EFAULT; | ||
2103 | unlock_set_fmt(state); | ||
2104 | goto out; | ||
2105 | } | ||
2106 | } else { | ||
2107 | if (copy_from_user(dmabuf->rawbuf + swptr, | ||
2108 | buffer, cnt)) { | ||
2109 | if (!ret) | ||
2110 | ret = -EFAULT; | ||
2111 | unlock_set_fmt(state); | ||
2112 | goto out; | ||
2113 | } | ||
2114 | state_cnt = cnt; | ||
2115 | } | ||
2116 | unlock_set_fmt(state); | ||
2117 | |||
2118 | swptr = (swptr + state_cnt) % dmabuf->dmasize; | ||
2119 | |||
2120 | spin_lock_irqsave(&state->card->lock, flags); | ||
2121 | dmabuf->swptr = swptr; | ||
2122 | dmabuf->count += state_cnt; | ||
2123 | dmabuf->endcleared = 0; | ||
2124 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
2125 | |||
2126 | count -= cnt; | ||
2127 | buffer += cnt; | ||
2128 | ret += cnt; | ||
2129 | start_dac(state); | ||
2130 | } | ||
2131 | out: | ||
2132 | up(&state->sem); | ||
2133 | out_nolock: | ||
2134 | return ret; | ||
2135 | } | ||
2136 | |||
2137 | /* No kernel lock - we have our own spinlock */ | ||
2138 | static unsigned int | ||
2139 | trident_poll(struct file *file, struct poll_table_struct *wait) | ||
2140 | { | ||
2141 | struct trident_state *state = (struct trident_state *)file->private_data; | ||
2142 | struct dmabuf *dmabuf = &state->dmabuf; | ||
2143 | unsigned long flags; | ||
2144 | unsigned int mask = 0; | ||
2145 | |||
2146 | VALIDATE_STATE(state); | ||
2147 | |||
2148 | /* | ||
2149 | * Guard against a parallel poll and write causing multiple | ||
2150 | * prog_dmabuf events | ||
2151 | */ | ||
2152 | |||
2153 | down(&state->sem); | ||
2154 | |||
2155 | if (file->f_mode & FMODE_WRITE) { | ||
2156 | if (!dmabuf->ready && prog_dmabuf_playback(state)) { | ||
2157 | up(&state->sem); | ||
2158 | return 0; | ||
2159 | } | ||
2160 | poll_wait(file, &dmabuf->wait, wait); | ||
2161 | } | ||
2162 | if (file->f_mode & FMODE_READ) { | ||
2163 | if (!dmabuf->ready && prog_dmabuf_record(state)) { | ||
2164 | up(&state->sem); | ||
2165 | return 0; | ||
2166 | } | ||
2167 | poll_wait(file, &dmabuf->wait, wait); | ||
2168 | } | ||
2169 | |||
2170 | up(&state->sem); | ||
2171 | |||
2172 | spin_lock_irqsave(&state->card->lock, flags); | ||
2173 | trident_update_ptr(state); | ||
2174 | if (file->f_mode & FMODE_READ) { | ||
2175 | if (dmabuf->count >= (signed) dmabuf->fragsize) | ||
2176 | mask |= POLLIN | POLLRDNORM; | ||
2177 | } | ||
2178 | if (file->f_mode & FMODE_WRITE) { | ||
2179 | if (dmabuf->mapped) { | ||
2180 | if (dmabuf->count >= (signed) dmabuf->fragsize) | ||
2181 | mask |= POLLOUT | POLLWRNORM; | ||
2182 | } else { | ||
2183 | if ((signed) dmabuf->dmasize >= dmabuf->count + | ||
2184 | (signed) dmabuf->fragsize) | ||
2185 | mask |= POLLOUT | POLLWRNORM; | ||
2186 | } | ||
2187 | } | ||
2188 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
2189 | |||
2190 | return mask; | ||
2191 | } | ||
2192 | |||
2193 | static int | ||
2194 | trident_mmap(struct file *file, struct vm_area_struct *vma) | ||
2195 | { | ||
2196 | struct trident_state *state = (struct trident_state *)file->private_data; | ||
2197 | struct dmabuf *dmabuf = &state->dmabuf; | ||
2198 | int ret = -EINVAL; | ||
2199 | unsigned long size; | ||
2200 | |||
2201 | VALIDATE_STATE(state); | ||
2202 | |||
2203 | /* | ||
2204 | * Lock against poll read write or mmap creating buffers. Also lock | ||
2205 | * a read or write against an mmap. | ||
2206 | */ | ||
2207 | |||
2208 | down(&state->sem); | ||
2209 | |||
2210 | if (vma->vm_flags & VM_WRITE) { | ||
2211 | if ((ret = prog_dmabuf_playback(state)) != 0) | ||
2212 | goto out; | ||
2213 | } else if (vma->vm_flags & VM_READ) { | ||
2214 | if ((ret = prog_dmabuf_record(state)) != 0) | ||
2215 | goto out; | ||
2216 | } else | ||
2217 | goto out; | ||
2218 | |||
2219 | ret = -EINVAL; | ||
2220 | if (vma->vm_pgoff != 0) | ||
2221 | goto out; | ||
2222 | size = vma->vm_end - vma->vm_start; | ||
2223 | if (size > (PAGE_SIZE << dmabuf->buforder)) | ||
2224 | goto out; | ||
2225 | ret = -EAGAIN; | ||
2226 | if (remap_pfn_range(vma, vma->vm_start, | ||
2227 | virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT, | ||
2228 | size, vma->vm_page_prot)) | ||
2229 | goto out; | ||
2230 | dmabuf->mapped = 1; | ||
2231 | ret = 0; | ||
2232 | out: | ||
2233 | up(&state->sem); | ||
2234 | return ret; | ||
2235 | } | ||
2236 | |||
2237 | static int | ||
2238 | trident_ioctl(struct inode *inode, struct file *file, | ||
2239 | unsigned int cmd, unsigned long arg) | ||
2240 | { | ||
2241 | struct trident_state *state = (struct trident_state *)file->private_data; | ||
2242 | struct dmabuf *dmabuf = &state->dmabuf; | ||
2243 | unsigned long flags; | ||
2244 | audio_buf_info abinfo; | ||
2245 | count_info cinfo; | ||
2246 | int val, mapped, ret = 0; | ||
2247 | struct trident_card *card = state->card; | ||
2248 | void __user *argp = (void __user *)arg; | ||
2249 | int __user *p = argp; | ||
2250 | |||
2251 | VALIDATE_STATE(state); | ||
2252 | |||
2253 | |||
2254 | mapped = ((file->f_mode & (FMODE_WRITE | FMODE_READ)) && dmabuf->mapped); | ||
2255 | |||
2256 | pr_debug("trident: trident_ioctl, command = %2d, arg = 0x%08x\n", | ||
2257 | _IOC_NR(cmd), arg ? *p : 0); | ||
2258 | |||
2259 | switch (cmd) { | ||
2260 | case OSS_GETVERSION: | ||
2261 | ret = put_user(SOUND_VERSION, p); | ||
2262 | break; | ||
2263 | |||
2264 | case SNDCTL_DSP_RESET: | ||
2265 | /* FIXME: spin_lock ? */ | ||
2266 | if (file->f_mode & FMODE_WRITE) { | ||
2267 | stop_dac(state); | ||
2268 | synchronize_irq(card->irq); | ||
2269 | dmabuf->ready = 0; | ||
2270 | dmabuf->swptr = dmabuf->hwptr = 0; | ||
2271 | dmabuf->count = dmabuf->total_bytes = 0; | ||
2272 | } | ||
2273 | if (file->f_mode & FMODE_READ) { | ||
2274 | stop_adc(state); | ||
2275 | synchronize_irq(card->irq); | ||
2276 | dmabuf->ready = 0; | ||
2277 | dmabuf->swptr = dmabuf->hwptr = 0; | ||
2278 | dmabuf->count = dmabuf->total_bytes = 0; | ||
2279 | } | ||
2280 | break; | ||
2281 | |||
2282 | case SNDCTL_DSP_SYNC: | ||
2283 | if (file->f_mode & FMODE_WRITE) | ||
2284 | ret = drain_dac(state, file->f_flags & O_NONBLOCK); | ||
2285 | break; | ||
2286 | |||
2287 | case SNDCTL_DSP_SPEED: /* set smaple rate */ | ||
2288 | if (get_user(val, p)) { | ||
2289 | ret = -EFAULT; | ||
2290 | break; | ||
2291 | } | ||
2292 | if (val >= 0) { | ||
2293 | if (file->f_mode & FMODE_WRITE) { | ||
2294 | stop_dac(state); | ||
2295 | dmabuf->ready = 0; | ||
2296 | spin_lock_irqsave(&state->card->lock, flags); | ||
2297 | trident_set_dac_rate(state, val); | ||
2298 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
2299 | } | ||
2300 | if (file->f_mode & FMODE_READ) { | ||
2301 | stop_adc(state); | ||
2302 | dmabuf->ready = 0; | ||
2303 | spin_lock_irqsave(&state->card->lock, flags); | ||
2304 | trident_set_adc_rate(state, val); | ||
2305 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
2306 | } | ||
2307 | } | ||
2308 | ret = put_user(dmabuf->rate, p); | ||
2309 | break; | ||
2310 | |||
2311 | case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ | ||
2312 | if (get_user(val, p)) { | ||
2313 | ret = -EFAULT; | ||
2314 | break; | ||
2315 | } | ||
2316 | if ((ret = lock_set_fmt(state)) < 0) | ||
2317 | return ret; | ||
2318 | |||
2319 | if (file->f_mode & FMODE_WRITE) { | ||
2320 | stop_dac(state); | ||
2321 | dmabuf->ready = 0; | ||
2322 | if (val) | ||
2323 | dmabuf->fmt |= TRIDENT_FMT_STEREO; | ||
2324 | else | ||
2325 | dmabuf->fmt &= ~TRIDENT_FMT_STEREO; | ||
2326 | } | ||
2327 | if (file->f_mode & FMODE_READ) { | ||
2328 | stop_adc(state); | ||
2329 | dmabuf->ready = 0; | ||
2330 | if (val) | ||
2331 | dmabuf->fmt |= TRIDENT_FMT_STEREO; | ||
2332 | else | ||
2333 | dmabuf->fmt &= ~TRIDENT_FMT_STEREO; | ||
2334 | } | ||
2335 | unlock_set_fmt(state); | ||
2336 | break; | ||
2337 | |||
2338 | case SNDCTL_DSP_GETBLKSIZE: | ||
2339 | if (file->f_mode & FMODE_WRITE) { | ||
2340 | if ((val = prog_dmabuf_playback(state))) | ||
2341 | ret = val; | ||
2342 | else | ||
2343 | ret = put_user(dmabuf->fragsize, p); | ||
2344 | break; | ||
2345 | } | ||
2346 | if (file->f_mode & FMODE_READ) { | ||
2347 | if ((val = prog_dmabuf_record(state))) | ||
2348 | ret = val; | ||
2349 | else | ||
2350 | ret = put_user(dmabuf->fragsize, p); | ||
2351 | break; | ||
2352 | } | ||
2353 | /* neither READ nor WRITE? is this even possible? */ | ||
2354 | ret = -EINVAL; | ||
2355 | break; | ||
2356 | |||
2357 | |||
2358 | case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format */ | ||
2359 | ret = put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 | | ||
2360 | AFMT_U8, p); | ||
2361 | break; | ||
2362 | |||
2363 | case SNDCTL_DSP_SETFMT: /* Select sample format */ | ||
2364 | if (get_user(val, p)) { | ||
2365 | ret = -EFAULT; | ||
2366 | break; | ||
2367 | } | ||
2368 | if ((ret = lock_set_fmt(state)) < 0) | ||
2369 | return ret; | ||
2370 | |||
2371 | if (val != AFMT_QUERY) { | ||
2372 | if (file->f_mode & FMODE_WRITE) { | ||
2373 | stop_dac(state); | ||
2374 | dmabuf->ready = 0; | ||
2375 | if (val == AFMT_S16_LE) | ||
2376 | dmabuf->fmt |= TRIDENT_FMT_16BIT; | ||
2377 | else | ||
2378 | dmabuf->fmt &= ~TRIDENT_FMT_16BIT; | ||
2379 | } | ||
2380 | if (file->f_mode & FMODE_READ) { | ||
2381 | stop_adc(state); | ||
2382 | dmabuf->ready = 0; | ||
2383 | if (val == AFMT_S16_LE) | ||
2384 | dmabuf->fmt |= TRIDENT_FMT_16BIT; | ||
2385 | else | ||
2386 | dmabuf->fmt &= ~TRIDENT_FMT_16BIT; | ||
2387 | } | ||
2388 | } | ||
2389 | unlock_set_fmt(state); | ||
2390 | ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE : | ||
2391 | AFMT_U8, p); | ||
2392 | break; | ||
2393 | |||
2394 | case SNDCTL_DSP_CHANNELS: | ||
2395 | if (get_user(val, p)) { | ||
2396 | ret = -EFAULT; | ||
2397 | break; | ||
2398 | } | ||
2399 | if (val != 0) { | ||
2400 | if ((ret = lock_set_fmt(state)) < 0) | ||
2401 | return ret; | ||
2402 | |||
2403 | if (file->f_mode & FMODE_WRITE) { | ||
2404 | stop_dac(state); | ||
2405 | dmabuf->ready = 0; | ||
2406 | |||
2407 | //prevent from memory leak | ||
2408 | if ((state->chans_num > 2) && (state->chans_num != val)) { | ||
2409 | ali_free_other_states_resources(state); | ||
2410 | state->chans_num = 1; | ||
2411 | } | ||
2412 | |||
2413 | if (val >= 2) { | ||
2414 | |||
2415 | dmabuf->fmt |= TRIDENT_FMT_STEREO; | ||
2416 | if ((val == 6) && (state->card->pci_id == PCI_DEVICE_ID_ALI_5451)) { | ||
2417 | if (card->rec_channel_use_count > 0) { | ||
2418 | printk(KERN_ERR "trident: Record is " | ||
2419 | "working on the card!\n"); | ||
2420 | ret = -EBUSY; | ||
2421 | unlock_set_fmt(state); | ||
2422 | break; | ||
2423 | } | ||
2424 | |||
2425 | ret = ali_setup_multi_channels(state->card, 6); | ||
2426 | if (ret < 0) { | ||
2427 | unlock_set_fmt(state); | ||
2428 | break; | ||
2429 | } | ||
2430 | down(&state->card->open_sem); | ||
2431 | ret = ali_allocate_other_states_resources(state, 6); | ||
2432 | if (ret < 0) { | ||
2433 | up(&state->card->open_sem); | ||
2434 | unlock_set_fmt(state); | ||
2435 | break; | ||
2436 | } | ||
2437 | state->card->multi_channel_use_count++; | ||
2438 | up(&state->card->open_sem); | ||
2439 | } else | ||
2440 | val = 2; /*yield to 2-channels */ | ||
2441 | } else | ||
2442 | dmabuf->fmt &= ~TRIDENT_FMT_STEREO; | ||
2443 | state->chans_num = val; | ||
2444 | } | ||
2445 | if (file->f_mode & FMODE_READ) { | ||
2446 | stop_adc(state); | ||
2447 | dmabuf->ready = 0; | ||
2448 | if (val >= 2) { | ||
2449 | if (!((file->f_mode & FMODE_WRITE) && | ||
2450 | (val == 6))) | ||
2451 | val = 2; | ||
2452 | dmabuf->fmt |= TRIDENT_FMT_STEREO; | ||
2453 | } else | ||
2454 | dmabuf->fmt &= ~TRIDENT_FMT_STEREO; | ||
2455 | state->chans_num = val; | ||
2456 | } | ||
2457 | unlock_set_fmt(state); | ||
2458 | } | ||
2459 | ret = put_user(val, p); | ||
2460 | break; | ||
2461 | |||
2462 | case SNDCTL_DSP_POST: | ||
2463 | /* Cause the working fragment to be output */ | ||
2464 | break; | ||
2465 | |||
2466 | case SNDCTL_DSP_SUBDIVIDE: | ||
2467 | if (dmabuf->subdivision) { | ||
2468 | ret = -EINVAL; | ||
2469 | break; | ||
2470 | } | ||
2471 | if (get_user(val, p)) { | ||
2472 | ret = -EFAULT; | ||
2473 | break; | ||
2474 | } | ||
2475 | if (val != 1 && val != 2 && val != 4) { | ||
2476 | ret = -EINVAL; | ||
2477 | break; | ||
2478 | } | ||
2479 | dmabuf->subdivision = val; | ||
2480 | break; | ||
2481 | |||
2482 | case SNDCTL_DSP_SETFRAGMENT: | ||
2483 | if (get_user(val, p)) { | ||
2484 | ret = -EFAULT; | ||
2485 | break; | ||
2486 | } | ||
2487 | |||
2488 | dmabuf->ossfragshift = val & 0xffff; | ||
2489 | dmabuf->ossmaxfrags = (val >> 16) & 0xffff; | ||
2490 | if (dmabuf->ossfragshift < 4) | ||
2491 | dmabuf->ossfragshift = 4; | ||
2492 | if (dmabuf->ossfragshift > 15) | ||
2493 | dmabuf->ossfragshift = 15; | ||
2494 | if (dmabuf->ossmaxfrags < 4) | ||
2495 | dmabuf->ossmaxfrags = 4; | ||
2496 | |||
2497 | break; | ||
2498 | |||
2499 | case SNDCTL_DSP_GETOSPACE: | ||
2500 | if (!(file->f_mode & FMODE_WRITE)) { | ||
2501 | ret = -EINVAL; | ||
2502 | break; | ||
2503 | } | ||
2504 | if (!dmabuf->ready && (val = prog_dmabuf_playback(state)) != 0) { | ||
2505 | ret = val; | ||
2506 | break; | ||
2507 | } | ||
2508 | spin_lock_irqsave(&state->card->lock, flags); | ||
2509 | trident_update_ptr(state); | ||
2510 | abinfo.fragsize = dmabuf->fragsize; | ||
2511 | abinfo.bytes = dmabuf->dmasize - dmabuf->count; | ||
2512 | abinfo.fragstotal = dmabuf->numfrag; | ||
2513 | abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; | ||
2514 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
2515 | ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ? | ||
2516 | -EFAULT : 0; | ||
2517 | break; | ||
2518 | |||
2519 | case SNDCTL_DSP_GETISPACE: | ||
2520 | if (!(file->f_mode & FMODE_READ)) { | ||
2521 | ret = -EINVAL; | ||
2522 | break; | ||
2523 | } | ||
2524 | if (!dmabuf->ready && (val = prog_dmabuf_record(state)) != 0) { | ||
2525 | ret = val; | ||
2526 | break; | ||
2527 | } | ||
2528 | spin_lock_irqsave(&state->card->lock, flags); | ||
2529 | trident_update_ptr(state); | ||
2530 | abinfo.fragsize = dmabuf->fragsize; | ||
2531 | abinfo.bytes = dmabuf->count; | ||
2532 | abinfo.fragstotal = dmabuf->numfrag; | ||
2533 | abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; | ||
2534 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
2535 | ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ? | ||
2536 | -EFAULT : 0; | ||
2537 | break; | ||
2538 | |||
2539 | case SNDCTL_DSP_NONBLOCK: | ||
2540 | file->f_flags |= O_NONBLOCK; | ||
2541 | break; | ||
2542 | |||
2543 | case SNDCTL_DSP_GETCAPS: | ||
2544 | ret = put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER | | ||
2545 | DSP_CAP_MMAP | DSP_CAP_BIND, p); | ||
2546 | break; | ||
2547 | |||
2548 | case SNDCTL_DSP_GETTRIGGER: | ||
2549 | val = 0; | ||
2550 | if ((file->f_mode & FMODE_READ) && dmabuf->enable) | ||
2551 | val |= PCM_ENABLE_INPUT; | ||
2552 | if ((file->f_mode & FMODE_WRITE) && dmabuf->enable) | ||
2553 | val |= PCM_ENABLE_OUTPUT; | ||
2554 | ret = put_user(val, p); | ||
2555 | break; | ||
2556 | |||
2557 | case SNDCTL_DSP_SETTRIGGER: | ||
2558 | if (get_user(val, p)) { | ||
2559 | ret = -EFAULT; | ||
2560 | break; | ||
2561 | } | ||
2562 | if (file->f_mode & FMODE_READ) { | ||
2563 | if (val & PCM_ENABLE_INPUT) { | ||
2564 | if (!dmabuf->ready && | ||
2565 | (ret = prog_dmabuf_record(state))) | ||
2566 | break; | ||
2567 | start_adc(state); | ||
2568 | } else | ||
2569 | stop_adc(state); | ||
2570 | } | ||
2571 | if (file->f_mode & FMODE_WRITE) { | ||
2572 | if (val & PCM_ENABLE_OUTPUT) { | ||
2573 | if (!dmabuf->ready && | ||
2574 | (ret = prog_dmabuf_playback(state))) | ||
2575 | break; | ||
2576 | start_dac(state); | ||
2577 | } else | ||
2578 | stop_dac(state); | ||
2579 | } | ||
2580 | break; | ||
2581 | |||
2582 | case SNDCTL_DSP_GETIPTR: | ||
2583 | if (!(file->f_mode & FMODE_READ)) { | ||
2584 | ret = -EINVAL; | ||
2585 | break; | ||
2586 | } | ||
2587 | if (!dmabuf->ready && (val = prog_dmabuf_record(state)) | ||
2588 | != 0) { | ||
2589 | ret = val; | ||
2590 | break; | ||
2591 | } | ||
2592 | spin_lock_irqsave(&state->card->lock, flags); | ||
2593 | trident_update_ptr(state); | ||
2594 | cinfo.bytes = dmabuf->total_bytes; | ||
2595 | cinfo.blocks = dmabuf->count >> dmabuf->fragshift; | ||
2596 | cinfo.ptr = dmabuf->hwptr; | ||
2597 | if (dmabuf->mapped) | ||
2598 | dmabuf->count &= dmabuf->fragsize - 1; | ||
2599 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
2600 | ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ? | ||
2601 | -EFAULT : 0; | ||
2602 | break; | ||
2603 | |||
2604 | case SNDCTL_DSP_GETOPTR: | ||
2605 | if (!(file->f_mode & FMODE_WRITE)) { | ||
2606 | ret = -EINVAL; | ||
2607 | break; | ||
2608 | } | ||
2609 | if (!dmabuf->ready && (val = prog_dmabuf_playback(state)) | ||
2610 | != 0) { | ||
2611 | ret = val; | ||
2612 | break; | ||
2613 | } | ||
2614 | |||
2615 | spin_lock_irqsave(&state->card->lock, flags); | ||
2616 | trident_update_ptr(state); | ||
2617 | cinfo.bytes = dmabuf->total_bytes; | ||
2618 | cinfo.blocks = dmabuf->count >> dmabuf->fragshift; | ||
2619 | cinfo.ptr = dmabuf->hwptr; | ||
2620 | if (dmabuf->mapped) | ||
2621 | dmabuf->count &= dmabuf->fragsize - 1; | ||
2622 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
2623 | ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ? | ||
2624 | -EFAULT : 0; | ||
2625 | break; | ||
2626 | |||
2627 | case SNDCTL_DSP_SETDUPLEX: | ||
2628 | ret = -EINVAL; | ||
2629 | break; | ||
2630 | |||
2631 | case SNDCTL_DSP_GETODELAY: | ||
2632 | if (!(file->f_mode & FMODE_WRITE)) { | ||
2633 | ret = -EINVAL; | ||
2634 | break; | ||
2635 | } | ||
2636 | if (!dmabuf->ready && (val = prog_dmabuf_playback(state)) != 0) { | ||
2637 | ret = val; | ||
2638 | break; | ||
2639 | } | ||
2640 | spin_lock_irqsave(&state->card->lock, flags); | ||
2641 | trident_update_ptr(state); | ||
2642 | val = dmabuf->count; | ||
2643 | spin_unlock_irqrestore(&state->card->lock, flags); | ||
2644 | ret = put_user(val, p); | ||
2645 | break; | ||
2646 | |||
2647 | case SOUND_PCM_READ_RATE: | ||
2648 | ret = put_user(dmabuf->rate, p); | ||
2649 | break; | ||
2650 | |||
2651 | case SOUND_PCM_READ_CHANNELS: | ||
2652 | ret = put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1, | ||
2653 | p); | ||
2654 | break; | ||
2655 | |||
2656 | case SOUND_PCM_READ_BITS: | ||
2657 | ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE : | ||
2658 | AFMT_U8, p); | ||
2659 | break; | ||
2660 | |||
2661 | case SNDCTL_DSP_GETCHANNELMASK: | ||
2662 | ret = put_user(DSP_BIND_FRONT | DSP_BIND_SURR | | ||
2663 | DSP_BIND_CENTER_LFE, p); | ||
2664 | break; | ||
2665 | |||
2666 | case SNDCTL_DSP_BIND_CHANNEL: | ||
2667 | if (state->card->pci_id != PCI_DEVICE_ID_SI_7018) { | ||
2668 | ret = -EINVAL; | ||
2669 | break; | ||
2670 | } | ||
2671 | |||
2672 | if (get_user(val, p)) { | ||
2673 | ret = -EFAULT; | ||
2674 | break; | ||
2675 | } | ||
2676 | if (val == DSP_BIND_QUERY) { | ||
2677 | val = dmabuf->channel->attribute | 0x3c00; | ||
2678 | val = attr2mask[val >> 8]; | ||
2679 | } else { | ||
2680 | dmabuf->ready = 0; | ||
2681 | if (file->f_mode & FMODE_READ) | ||
2682 | dmabuf->channel->attribute = (CHANNEL_REC | | ||
2683 | SRC_ENABLE); | ||
2684 | if (file->f_mode & FMODE_WRITE) | ||
2685 | dmabuf->channel->attribute = (CHANNEL_SPC_PB | | ||
2686 | SRC_ENABLE); | ||
2687 | dmabuf->channel->attribute |= mask2attr[ffs(val)]; | ||
2688 | } | ||
2689 | ret = put_user(val, p); | ||
2690 | break; | ||
2691 | |||
2692 | case SNDCTL_DSP_MAPINBUF: | ||
2693 | case SNDCTL_DSP_MAPOUTBUF: | ||
2694 | case SNDCTL_DSP_SETSYNCRO: | ||
2695 | case SOUND_PCM_WRITE_FILTER: | ||
2696 | case SOUND_PCM_READ_FILTER: | ||
2697 | default: | ||
2698 | ret = -EINVAL; | ||
2699 | break; | ||
2700 | |||
2701 | } | ||
2702 | return ret; | ||
2703 | } | ||
2704 | |||
2705 | static int | ||
2706 | trident_open(struct inode *inode, struct file *file) | ||
2707 | { | ||
2708 | int i = 0; | ||
2709 | int minor = iminor(inode); | ||
2710 | struct trident_card *card = devs; | ||
2711 | struct trident_state *state = NULL; | ||
2712 | struct dmabuf *dmabuf = NULL; | ||
2713 | |||
2714 | /* Added by Matt Wu 01-05-2001 */ | ||
2715 | /* TODO: there's some redundacy here wrt the check below */ | ||
2716 | /* for multi_use_count > 0. Should we return -EBUSY or find */ | ||
2717 | /* a different card? for now, don't break current behaviour */ | ||
2718 | /* -- mulix */ | ||
2719 | if (file->f_mode & FMODE_READ) { | ||
2720 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | ||
2721 | if (card->multi_channel_use_count > 0) | ||
2722 | return -EBUSY; | ||
2723 | } | ||
2724 | } | ||
2725 | |||
2726 | /* find an available virtual channel (instance of /dev/dsp) */ | ||
2727 | while (card != NULL) { | ||
2728 | down(&card->open_sem); | ||
2729 | if (file->f_mode & FMODE_READ) { | ||
2730 | /* Skip opens on cards that are in 6 channel mode */ | ||
2731 | if (card->multi_channel_use_count > 0) { | ||
2732 | up(&card->open_sem); | ||
2733 | card = card->next; | ||
2734 | continue; | ||
2735 | } | ||
2736 | } | ||
2737 | for (i = 0; i < NR_HW_CH; i++) { | ||
2738 | if (card->states[i] == NULL) { | ||
2739 | state = card->states[i] = kmalloc(sizeof(*state), GFP_KERNEL); | ||
2740 | if (state == NULL) { | ||
2741 | up(&card->open_sem); | ||
2742 | return -ENOMEM; | ||
2743 | } | ||
2744 | memset(state, 0, sizeof(*state)); | ||
2745 | init_MUTEX(&state->sem); | ||
2746 | dmabuf = &state->dmabuf; | ||
2747 | goto found_virt; | ||
2748 | } | ||
2749 | } | ||
2750 | up(&card->open_sem); | ||
2751 | card = card->next; | ||
2752 | } | ||
2753 | /* no more virtual channel avaiable */ | ||
2754 | if (!state) { | ||
2755 | return -ENODEV; | ||
2756 | } | ||
2757 | found_virt: | ||
2758 | /* found a free virtual channel, allocate hardware channels */ | ||
2759 | if (file->f_mode & FMODE_READ) | ||
2760 | dmabuf->channel = card->alloc_rec_pcm_channel(card); | ||
2761 | else | ||
2762 | dmabuf->channel = card->alloc_pcm_channel(card); | ||
2763 | |||
2764 | if (dmabuf->channel == NULL) { | ||
2765 | kfree(card->states[i]); | ||
2766 | card->states[i] = NULL; | ||
2767 | return -ENODEV; | ||
2768 | } | ||
2769 | |||
2770 | /* initialize the virtual channel */ | ||
2771 | state->virt = i; | ||
2772 | state->card = card; | ||
2773 | state->magic = TRIDENT_STATE_MAGIC; | ||
2774 | init_waitqueue_head(&dmabuf->wait); | ||
2775 | file->private_data = state; | ||
2776 | |||
2777 | /* set default sample format. According to OSS Programmer's */ | ||
2778 | /* Guide /dev/dsp should be default to unsigned 8-bits, mono, */ | ||
2779 | /* with sample rate 8kHz and /dev/dspW will accept 16-bits sample */ | ||
2780 | if (file->f_mode & FMODE_WRITE) { | ||
2781 | dmabuf->fmt &= ~TRIDENT_FMT_MASK; | ||
2782 | if ((minor & 0x0f) == SND_DEV_DSP16) | ||
2783 | dmabuf->fmt |= TRIDENT_FMT_16BIT; | ||
2784 | dmabuf->ossfragshift = 0; | ||
2785 | dmabuf->ossmaxfrags = 0; | ||
2786 | dmabuf->subdivision = 0; | ||
2787 | if (card->pci_id == PCI_DEVICE_ID_SI_7018) { | ||
2788 | /* set default channel attribute to normal playback */ | ||
2789 | dmabuf->channel->attribute = CHANNEL_PB; | ||
2790 | } | ||
2791 | trident_set_dac_rate(state, 8000); | ||
2792 | } | ||
2793 | |||
2794 | if (file->f_mode & FMODE_READ) { | ||
2795 | /* FIXME: Trident 4d can only record in signed 16-bits stereo, */ | ||
2796 | /* 48kHz sample, to be dealed with in trident_set_adc_rate() ?? */ | ||
2797 | dmabuf->fmt &= ~TRIDENT_FMT_MASK; | ||
2798 | if ((minor & 0x0f) == SND_DEV_DSP16) | ||
2799 | dmabuf->fmt |= TRIDENT_FMT_16BIT; | ||
2800 | dmabuf->ossfragshift = 0; | ||
2801 | dmabuf->ossmaxfrags = 0; | ||
2802 | dmabuf->subdivision = 0; | ||
2803 | if (card->pci_id == PCI_DEVICE_ID_SI_7018) { | ||
2804 | /* set default channel attribute to 0x8a80, record from | ||
2805 | PCM L/R FIFO and mono = (left + right + 1)/2 */ | ||
2806 | dmabuf->channel->attribute = (CHANNEL_REC | PCM_LR | | ||
2807 | MONO_MIX); | ||
2808 | } | ||
2809 | trident_set_adc_rate(state, 8000); | ||
2810 | |||
2811 | /* Added by Matt Wu 01-05-2001 */ | ||
2812 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) | ||
2813 | card->rec_channel_use_count++; | ||
2814 | } | ||
2815 | |||
2816 | state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); | ||
2817 | up(&card->open_sem); | ||
2818 | |||
2819 | pr_debug("trident: open virtual channel %d, hard channel %d\n", | ||
2820 | state->virt, dmabuf->channel->num); | ||
2821 | |||
2822 | return nonseekable_open(inode, file); | ||
2823 | } | ||
2824 | |||
2825 | static int | ||
2826 | trident_release(struct inode *inode, struct file *file) | ||
2827 | { | ||
2828 | struct trident_state *state = (struct trident_state *)file->private_data; | ||
2829 | struct trident_card *card; | ||
2830 | struct dmabuf *dmabuf; | ||
2831 | |||
2832 | VALIDATE_STATE(state); | ||
2833 | |||
2834 | card = state->card; | ||
2835 | dmabuf = &state->dmabuf; | ||
2836 | |||
2837 | if (file->f_mode & FMODE_WRITE) { | ||
2838 | trident_clear_tail(state); | ||
2839 | drain_dac(state, file->f_flags & O_NONBLOCK); | ||
2840 | } | ||
2841 | |||
2842 | pr_debug("trident: closing virtual channel %d, hard channel %d\n", | ||
2843 | state->virt, dmabuf->channel->num); | ||
2844 | |||
2845 | /* stop DMA state machine and free DMA buffers/channels */ | ||
2846 | down(&card->open_sem); | ||
2847 | |||
2848 | if (file->f_mode & FMODE_WRITE) { | ||
2849 | stop_dac(state); | ||
2850 | dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); | ||
2851 | state->card->free_pcm_channel(state->card, dmabuf->channel->num); | ||
2852 | |||
2853 | /* Added by Matt Wu */ | ||
2854 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | ||
2855 | if (state->chans_num > 2) { | ||
2856 | if (card->multi_channel_use_count-- < 0) | ||
2857 | card->multi_channel_use_count = 0; | ||
2858 | if (card->multi_channel_use_count == 0) | ||
2859 | ali_close_multi_channels(); | ||
2860 | ali_free_other_states_resources(state); | ||
2861 | } | ||
2862 | } | ||
2863 | } | ||
2864 | if (file->f_mode & FMODE_READ) { | ||
2865 | stop_adc(state); | ||
2866 | dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); | ||
2867 | state->card->free_pcm_channel(state->card, dmabuf->channel->num); | ||
2868 | |||
2869 | /* Added by Matt Wu */ | ||
2870 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | ||
2871 | if (card->rec_channel_use_count-- < 0) | ||
2872 | card->rec_channel_use_count = 0; | ||
2873 | } | ||
2874 | } | ||
2875 | |||
2876 | card->states[state->virt] = NULL; | ||
2877 | kfree(state); | ||
2878 | |||
2879 | /* we're covered by the open_sem */ | ||
2880 | up(&card->open_sem); | ||
2881 | |||
2882 | return 0; | ||
2883 | } | ||
2884 | |||
2885 | static /*const */ struct file_operations trident_audio_fops = { | ||
2886 | .owner = THIS_MODULE, | ||
2887 | .llseek = no_llseek, | ||
2888 | .read = trident_read, | ||
2889 | .write = trident_write, | ||
2890 | .poll = trident_poll, | ||
2891 | .ioctl = trident_ioctl, | ||
2892 | .mmap = trident_mmap, | ||
2893 | .open = trident_open, | ||
2894 | .release = trident_release, | ||
2895 | }; | ||
2896 | |||
2897 | /* trident specific AC97 functions */ | ||
2898 | /* Write AC97 codec registers */ | ||
2899 | static void | ||
2900 | trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val) | ||
2901 | { | ||
2902 | struct trident_card *card = (struct trident_card *)codec->private_data; | ||
2903 | unsigned int address, mask, busy; | ||
2904 | unsigned short count = 0xffff; | ||
2905 | unsigned long flags; | ||
2906 | u32 data; | ||
2907 | |||
2908 | data = ((u32) val) << 16; | ||
2909 | |||
2910 | switch (card->pci_id) { | ||
2911 | default: | ||
2912 | case PCI_DEVICE_ID_SI_7018: | ||
2913 | address = SI_AC97_WRITE; | ||
2914 | mask = SI_AC97_BUSY_WRITE | SI_AC97_AUDIO_BUSY; | ||
2915 | if (codec->id) | ||
2916 | mask |= SI_AC97_SECONDARY; | ||
2917 | busy = SI_AC97_BUSY_WRITE; | ||
2918 | break; | ||
2919 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: | ||
2920 | address = DX_ACR0_AC97_W; | ||
2921 | mask = busy = DX_AC97_BUSY_WRITE; | ||
2922 | break; | ||
2923 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: | ||
2924 | address = NX_ACR1_AC97_W; | ||
2925 | mask = NX_AC97_BUSY_WRITE; | ||
2926 | if (codec->id) | ||
2927 | mask |= NX_AC97_WRITE_SECONDARY; | ||
2928 | busy = NX_AC97_BUSY_WRITE; | ||
2929 | break; | ||
2930 | case PCI_DEVICE_ID_INTERG_5050: | ||
2931 | address = SI_AC97_WRITE; | ||
2932 | mask = busy = SI_AC97_BUSY_WRITE; | ||
2933 | if (codec->id) | ||
2934 | mask |= SI_AC97_SECONDARY; | ||
2935 | break; | ||
2936 | } | ||
2937 | |||
2938 | spin_lock_irqsave(&card->lock, flags); | ||
2939 | do { | ||
2940 | if ((inw(TRID_REG(card, address)) & busy) == 0) | ||
2941 | break; | ||
2942 | } while (count--); | ||
2943 | |||
2944 | data |= (mask | (reg & AC97_REG_ADDR)); | ||
2945 | |||
2946 | if (count == 0) { | ||
2947 | printk(KERN_ERR "trident: AC97 CODEC write timed out.\n"); | ||
2948 | spin_unlock_irqrestore(&card->lock, flags); | ||
2949 | return; | ||
2950 | } | ||
2951 | |||
2952 | outl(data, TRID_REG(card, address)); | ||
2953 | spin_unlock_irqrestore(&card->lock, flags); | ||
2954 | } | ||
2955 | |||
2956 | /* Read AC97 codec registers */ | ||
2957 | static u16 | ||
2958 | trident_ac97_get(struct ac97_codec *codec, u8 reg) | ||
2959 | { | ||
2960 | struct trident_card *card = (struct trident_card *)codec->private_data; | ||
2961 | unsigned int address, mask, busy; | ||
2962 | unsigned short count = 0xffff; | ||
2963 | unsigned long flags; | ||
2964 | u32 data; | ||
2965 | |||
2966 | switch (card->pci_id) { | ||
2967 | default: | ||
2968 | case PCI_DEVICE_ID_SI_7018: | ||
2969 | address = SI_AC97_READ; | ||
2970 | mask = SI_AC97_BUSY_READ | SI_AC97_AUDIO_BUSY; | ||
2971 | if (codec->id) | ||
2972 | mask |= SI_AC97_SECONDARY; | ||
2973 | busy = SI_AC97_BUSY_READ; | ||
2974 | break; | ||
2975 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: | ||
2976 | address = DX_ACR1_AC97_R; | ||
2977 | mask = busy = DX_AC97_BUSY_READ; | ||
2978 | break; | ||
2979 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: | ||
2980 | if (codec->id) | ||
2981 | address = NX_ACR3_AC97_R_SECONDARY; | ||
2982 | else | ||
2983 | address = NX_ACR2_AC97_R_PRIMARY; | ||
2984 | mask = NX_AC97_BUSY_READ; | ||
2985 | busy = NX_AC97_BUSY_READ | NX_AC97_BUSY_DATA; | ||
2986 | break; | ||
2987 | case PCI_DEVICE_ID_INTERG_5050: | ||
2988 | address = SI_AC97_READ; | ||
2989 | mask = busy = SI_AC97_BUSY_READ; | ||
2990 | if (codec->id) | ||
2991 | mask |= SI_AC97_SECONDARY; | ||
2992 | break; | ||
2993 | } | ||
2994 | |||
2995 | data = (mask | (reg & AC97_REG_ADDR)); | ||
2996 | |||
2997 | spin_lock_irqsave(&card->lock, flags); | ||
2998 | outl(data, TRID_REG(card, address)); | ||
2999 | do { | ||
3000 | data = inl(TRID_REG(card, address)); | ||
3001 | if ((data & busy) == 0) | ||
3002 | break; | ||
3003 | } while (count--); | ||
3004 | spin_unlock_irqrestore(&card->lock, flags); | ||
3005 | |||
3006 | if (count == 0) { | ||
3007 | printk(KERN_ERR "trident: AC97 CODEC read timed out.\n"); | ||
3008 | data = 0; | ||
3009 | } | ||
3010 | return ((u16) (data >> 16)); | ||
3011 | } | ||
3012 | |||
3013 | /* rewrite ac97 read and write mixer register by hulei for ALI*/ | ||
3014 | static int | ||
3015 | acquirecodecaccess(struct trident_card *card) | ||
3016 | { | ||
3017 | u16 wsemamask = 0x6000; /* bit 14..13 */ | ||
3018 | u16 wsemabits; | ||
3019 | u16 wcontrol; | ||
3020 | int block = 0; | ||
3021 | int ncount = 25; | ||
3022 | while (1) { | ||
3023 | wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); | ||
3024 | wsemabits = wcontrol & wsemamask; | ||
3025 | |||
3026 | if (wsemabits == 0x4000) | ||
3027 | return 1; /* 0x4000 is audio ,then success */ | ||
3028 | if (ncount-- < 0) | ||
3029 | break; | ||
3030 | if (wsemabits == 0) { | ||
3031 | unlock: | ||
3032 | outl(((u32) (wcontrol & 0x1eff) | 0x00004000), | ||
3033 | TRID_REG(card, ALI_AC97_WRITE)); | ||
3034 | continue; | ||
3035 | } | ||
3036 | udelay(20); | ||
3037 | } | ||
3038 | if (!block) { | ||
3039 | pr_debug("accesscodecsemaphore: try unlock\n"); | ||
3040 | block = 1; | ||
3041 | goto unlock; | ||
3042 | } | ||
3043 | return 0; | ||
3044 | } | ||
3045 | |||
3046 | static void | ||
3047 | releasecodecaccess(struct trident_card *card) | ||
3048 | { | ||
3049 | unsigned long wcontrol; | ||
3050 | wcontrol = inl(TRID_REG(card, ALI_AC97_WRITE)); | ||
3051 | outl((wcontrol & 0xffff1eff), TRID_REG(card, ALI_AC97_WRITE)); | ||
3052 | } | ||
3053 | |||
3054 | static int | ||
3055 | waitforstimertick(struct trident_card *card) | ||
3056 | { | ||
3057 | unsigned long chk1, chk2; | ||
3058 | unsigned int wcount = 0xffff; | ||
3059 | chk1 = inl(TRID_REG(card, ALI_STIMER)); | ||
3060 | |||
3061 | while (1) { | ||
3062 | chk2 = inl(TRID_REG(card, ALI_STIMER)); | ||
3063 | if ((wcount > 0) && chk1 != chk2) | ||
3064 | return 1; | ||
3065 | if (wcount <= 0) | ||
3066 | break; | ||
3067 | udelay(50); | ||
3068 | } | ||
3069 | return 0; | ||
3070 | } | ||
3071 | |||
3072 | /* Read AC97 codec registers for ALi*/ | ||
3073 | static u16 | ||
3074 | ali_ac97_get(struct trident_card *card, int secondary, u8 reg) | ||
3075 | { | ||
3076 | unsigned int address, mask; | ||
3077 | unsigned int ncount; | ||
3078 | unsigned long aud_reg; | ||
3079 | u32 data; | ||
3080 | u16 wcontrol; | ||
3081 | unsigned long flags; | ||
3082 | |||
3083 | if (!card) | ||
3084 | BUG(); | ||
3085 | |||
3086 | address = ALI_AC97_READ; | ||
3087 | if (card->revision == ALI_5451_V02) { | ||
3088 | address = ALI_AC97_WRITE; | ||
3089 | } | ||
3090 | mask = ALI_AC97_READ_ACTION | ALI_AC97_AUDIO_BUSY; | ||
3091 | if (secondary) | ||
3092 | mask |= ALI_AC97_SECONDARY; | ||
3093 | |||
3094 | spin_lock_irqsave(&card->lock, flags); | ||
3095 | |||
3096 | if (!acquirecodecaccess(card)) | ||
3097 | printk(KERN_ERR "access codec fail\n"); | ||
3098 | |||
3099 | wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); | ||
3100 | wcontrol &= 0xfe00; | ||
3101 | wcontrol |= (0x8000 | reg); | ||
3102 | outw(wcontrol, TRID_REG(card, ALI_AC97_WRITE)); | ||
3103 | |||
3104 | data = (mask | (reg & AC97_REG_ADDR)); | ||
3105 | |||
3106 | if (!waitforstimertick(card)) { | ||
3107 | printk(KERN_ERR "ali_ac97_read: BIT_CLOCK is dead\n"); | ||
3108 | goto releasecodec; | ||
3109 | } | ||
3110 | |||
3111 | udelay(20); | ||
3112 | |||
3113 | ncount = 10; | ||
3114 | |||
3115 | while (1) { | ||
3116 | if ((inw(TRID_REG(card, ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ) | ||
3117 | != 0) | ||
3118 | break; | ||
3119 | if (ncount <= 0) | ||
3120 | break; | ||
3121 | if (ncount-- == 1) { | ||
3122 | pr_debug("ali_ac97_read :try clear busy flag\n"); | ||
3123 | aud_reg = inl(TRID_REG(card, ALI_AC97_WRITE)); | ||
3124 | outl((aud_reg & 0xffff7fff), | ||
3125 | TRID_REG(card, ALI_AC97_WRITE)); | ||
3126 | } | ||
3127 | udelay(10); | ||
3128 | } | ||
3129 | |||
3130 | data = inl(TRID_REG(card, address)); | ||
3131 | |||
3132 | spin_unlock_irqrestore(&card->lock, flags); | ||
3133 | |||
3134 | return ((u16) (data >> 16)); | ||
3135 | |||
3136 | releasecodec: | ||
3137 | releasecodecaccess(card); | ||
3138 | spin_unlock_irqrestore(&card->lock, flags); | ||
3139 | printk(KERN_ERR "ali_ac97_read: AC97 CODEC read timed out.\n"); | ||
3140 | return 0; | ||
3141 | } | ||
3142 | |||
3143 | /* Write AC97 codec registers for hulei*/ | ||
3144 | static void | ||
3145 | ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val) | ||
3146 | { | ||
3147 | unsigned int address, mask; | ||
3148 | unsigned int ncount; | ||
3149 | u32 data; | ||
3150 | u16 wcontrol; | ||
3151 | unsigned long flags; | ||
3152 | |||
3153 | data = ((u32) val) << 16; | ||
3154 | |||
3155 | if (!card) | ||
3156 | BUG(); | ||
3157 | |||
3158 | address = ALI_AC97_WRITE; | ||
3159 | mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY; | ||
3160 | if (secondary) | ||
3161 | mask |= ALI_AC97_SECONDARY; | ||
3162 | if (card->revision == ALI_5451_V02) | ||
3163 | mask |= ALI_AC97_WRITE_MIXER_REGISTER; | ||
3164 | |||
3165 | spin_lock_irqsave(&card->lock, flags); | ||
3166 | if (!acquirecodecaccess(card)) | ||
3167 | printk(KERN_ERR "ali_ac97_write: access codec fail\n"); | ||
3168 | |||
3169 | wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); | ||
3170 | wcontrol &= 0xff00; | ||
3171 | wcontrol |= (0x8100 | reg); /* bit 8=1: (ali1535 )reserved/ */ | ||
3172 | /* ali1535+ write */ | ||
3173 | outl((data | wcontrol), TRID_REG(card, ALI_AC97_WRITE)); | ||
3174 | |||
3175 | if (!waitforstimertick(card)) { | ||
3176 | printk(KERN_ERR "BIT_CLOCK is dead\n"); | ||
3177 | goto releasecodec; | ||
3178 | } | ||
3179 | |||
3180 | ncount = 10; | ||
3181 | while (1) { | ||
3182 | wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); | ||
3183 | if (!(wcontrol & 0x8000)) | ||
3184 | break; | ||
3185 | if (ncount <= 0) | ||
3186 | break; | ||
3187 | if (ncount-- == 1) { | ||
3188 | pr_debug("ali_ac97_set :try clear busy flag!!\n"); | ||
3189 | outw(wcontrol & 0x7fff, | ||
3190 | TRID_REG(card, ALI_AC97_WRITE)); | ||
3191 | } | ||
3192 | udelay(10); | ||
3193 | } | ||
3194 | |||
3195 | releasecodec: | ||
3196 | releasecodecaccess(card); | ||
3197 | spin_unlock_irqrestore(&card->lock, flags); | ||
3198 | return; | ||
3199 | } | ||
3200 | |||
3201 | static void | ||
3202 | ali_enable_special_channel(struct trident_state *stat) | ||
3203 | { | ||
3204 | struct trident_card *card = stat->card; | ||
3205 | unsigned long s_channels; | ||
3206 | |||
3207 | s_channels = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
3208 | s_channels |= (1 << stat->dmabuf.channel->num); | ||
3209 | outl(s_channels, TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
3210 | } | ||
3211 | |||
3212 | static u16 | ||
3213 | ali_ac97_read(struct ac97_codec *codec, u8 reg) | ||
3214 | { | ||
3215 | int id; | ||
3216 | u16 data; | ||
3217 | struct trident_card *card = NULL; | ||
3218 | |||
3219 | /* Added by Matt Wu */ | ||
3220 | if (!codec) | ||
3221 | BUG(); | ||
3222 | |||
3223 | card = (struct trident_card *) codec->private_data; | ||
3224 | |||
3225 | if (!card->mixer_regs_ready) | ||
3226 | return ali_ac97_get(card, codec->id, reg); | ||
3227 | |||
3228 | /* | ||
3229 | * FIXME: need to stop this caching some registers | ||
3230 | */ | ||
3231 | if (codec->id) | ||
3232 | id = 1; | ||
3233 | else | ||
3234 | id = 0; | ||
3235 | |||
3236 | data = card->mixer_regs[reg / 2][id]; | ||
3237 | return data; | ||
3238 | } | ||
3239 | |||
3240 | static void | ||
3241 | ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val) | ||
3242 | { | ||
3243 | int id; | ||
3244 | struct trident_card *card; | ||
3245 | |||
3246 | /* Added by Matt Wu */ | ||
3247 | if (!codec) | ||
3248 | BUG(); | ||
3249 | |||
3250 | card = (struct trident_card *) codec->private_data; | ||
3251 | |||
3252 | if (!card->mixer_regs_ready) { | ||
3253 | ali_ac97_set(card, codec->id, reg, val); | ||
3254 | return; | ||
3255 | } | ||
3256 | |||
3257 | if (codec->id) | ||
3258 | id = 1; | ||
3259 | else | ||
3260 | id = 0; | ||
3261 | |||
3262 | card->mixer_regs[reg / 2][id] = val; | ||
3263 | ali_ac97_set(card, codec->id, reg, val); | ||
3264 | } | ||
3265 | |||
3266 | /* | ||
3267 | flag: ALI_SPDIF_OUT_TO_SPDIF_OUT | ||
3268 | ALI_PCM_TO_SPDIF_OUT | ||
3269 | */ | ||
3270 | |||
3271 | static void | ||
3272 | ali_setup_spdif_out(struct trident_card *card, int flag) | ||
3273 | { | ||
3274 | unsigned long spdif; | ||
3275 | unsigned char ch; | ||
3276 | |||
3277 | char temp; | ||
3278 | struct pci_dev *pci_dev = NULL; | ||
3279 | |||
3280 | pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, | ||
3281 | pci_dev); | ||
3282 | if (pci_dev == NULL) | ||
3283 | return; | ||
3284 | pci_read_config_byte(pci_dev, 0x61, &temp); | ||
3285 | temp |= 0x40; | ||
3286 | pci_write_config_byte(pci_dev, 0x61, temp); | ||
3287 | pci_read_config_byte(pci_dev, 0x7d, &temp); | ||
3288 | temp |= 0x01; | ||
3289 | pci_write_config_byte(pci_dev, 0x7d, temp); | ||
3290 | pci_read_config_byte(pci_dev, 0x7e, &temp); | ||
3291 | temp &= (~0x20); | ||
3292 | temp |= 0x10; | ||
3293 | pci_write_config_byte(pci_dev, 0x7e, temp); | ||
3294 | |||
3295 | ch = inb(TRID_REG(card, ALI_SCTRL)); | ||
3296 | outb(ch | ALI_SPDIF_OUT_ENABLE, TRID_REG(card, ALI_SCTRL)); | ||
3297 | ch = inb(TRID_REG(card, ALI_SPDIF_CTRL)); | ||
3298 | outb(ch & ALI_SPDIF_OUT_CH_STATUS, TRID_REG(card, ALI_SPDIF_CTRL)); | ||
3299 | |||
3300 | if (flag & ALI_SPDIF_OUT_TO_SPDIF_OUT) { | ||
3301 | spdif = inw(TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
3302 | spdif |= ALI_SPDIF_OUT_CH_ENABLE; | ||
3303 | spdif &= ALI_SPDIF_OUT_SEL_SPDIF; | ||
3304 | outw(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
3305 | spdif = inw(TRID_REG(card, ALI_SPDIF_CS)); | ||
3306 | if (flag & ALI_SPDIF_OUT_NON_PCM) | ||
3307 | spdif |= 0x0002; | ||
3308 | else | ||
3309 | spdif &= (~0x0002); | ||
3310 | outw(spdif, TRID_REG(card, ALI_SPDIF_CS)); | ||
3311 | } else { | ||
3312 | spdif = inw(TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
3313 | spdif |= ALI_SPDIF_OUT_SEL_PCM; | ||
3314 | outw(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
3315 | } | ||
3316 | } | ||
3317 | |||
3318 | static void | ||
3319 | ali_disable_special_channel(struct trident_card *card, int ch) | ||
3320 | { | ||
3321 | unsigned long sc; | ||
3322 | |||
3323 | sc = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
3324 | sc &= ~(1 << ch); | ||
3325 | outl(sc, TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
3326 | } | ||
3327 | |||
3328 | static void | ||
3329 | ali_disable_spdif_in(struct trident_card *card) | ||
3330 | { | ||
3331 | unsigned long spdif; | ||
3332 | |||
3333 | spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
3334 | spdif &= (~ALI_SPDIF_IN_SUPPORT); | ||
3335 | outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
3336 | |||
3337 | ali_disable_special_channel(card, ALI_SPDIF_IN_CHANNEL); | ||
3338 | } | ||
3339 | |||
3340 | static void | ||
3341 | ali_setup_spdif_in(struct trident_card *card) | ||
3342 | { | ||
3343 | unsigned long spdif; | ||
3344 | |||
3345 | //Set SPDIF IN Supported | ||
3346 | spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
3347 | spdif |= ALI_SPDIF_IN_SUPPORT; | ||
3348 | outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
3349 | |||
3350 | //Set SPDIF IN Rec | ||
3351 | spdif = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
3352 | spdif |= ALI_SPDIF_IN_CH_ENABLE; | ||
3353 | outl(spdif, TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
3354 | |||
3355 | spdif = inb(TRID_REG(card, ALI_SPDIF_CTRL)); | ||
3356 | spdif |= ALI_SPDIF_IN_CH_STATUS; | ||
3357 | outb(spdif, TRID_REG(card, ALI_SPDIF_CTRL)); | ||
3358 | /* | ||
3359 | spdif = inb(TRID_REG(card, ALI_SPDIF_CTRL)); | ||
3360 | spdif |= ALI_SPDIF_IN_FUNC_ENABLE; | ||
3361 | outb(spdif, TRID_REG(card, ALI_SPDIF_CTRL)); | ||
3362 | */ | ||
3363 | } | ||
3364 | |||
3365 | static void | ||
3366 | ali_delay(struct trident_card *card, int interval) | ||
3367 | { | ||
3368 | unsigned long begintimer, currenttimer; | ||
3369 | |||
3370 | begintimer = inl(TRID_REG(card, ALI_STIMER)); | ||
3371 | currenttimer = inl(TRID_REG(card, ALI_STIMER)); | ||
3372 | |||
3373 | while (currenttimer < begintimer + interval) | ||
3374 | currenttimer = inl(TRID_REG(card, ALI_STIMER)); | ||
3375 | } | ||
3376 | |||
3377 | static void | ||
3378 | ali_detect_spdif_rate(struct trident_card *card) | ||
3379 | { | ||
3380 | u16 wval = 0; | ||
3381 | u16 count = 0; | ||
3382 | u8 bval = 0, R1 = 0, R2 = 0; | ||
3383 | |||
3384 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL)); | ||
3385 | bval |= 0x02; | ||
3386 | outb(bval, TRID_REG(card, ALI_SPDIF_CTRL)); | ||
3387 | |||
3388 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1)); | ||
3389 | bval |= 0x1F; | ||
3390 | outb(bval, TRID_REG(card, ALI_SPDIF_CTRL + 1)); | ||
3391 | |||
3392 | while (((R1 < 0x0B) || (R1 > 0x0E)) && (R1 != 0x12) && | ||
3393 | count <= 50000) { | ||
3394 | count++; | ||
3395 | |||
3396 | ali_delay(card, 6); | ||
3397 | |||
3398 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1)); | ||
3399 | R1 = bval & 0x1F; | ||
3400 | } | ||
3401 | |||
3402 | if (count > 50000) { | ||
3403 | printk(KERN_WARNING "trident: Error in " | ||
3404 | "ali_detect_spdif_rate!\n"); | ||
3405 | return; | ||
3406 | } | ||
3407 | |||
3408 | count = 0; | ||
3409 | |||
3410 | while (count <= 50000) { | ||
3411 | count++; | ||
3412 | |||
3413 | ali_delay(card, 6); | ||
3414 | |||
3415 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL + 1)); | ||
3416 | R2 = bval & 0x1F; | ||
3417 | |||
3418 | if (R2 != R1) | ||
3419 | R1 = R2; | ||
3420 | else | ||
3421 | break; | ||
3422 | } | ||
3423 | |||
3424 | if (count > 50000) { | ||
3425 | printk(KERN_WARNING "trident: Error in " | ||
3426 | "ali_detect_spdif_rate!\n"); | ||
3427 | return; | ||
3428 | } | ||
3429 | |||
3430 | switch (R2) { | ||
3431 | case 0x0b: | ||
3432 | case 0x0c: | ||
3433 | case 0x0d: | ||
3434 | case 0x0e: | ||
3435 | wval = inw(TRID_REG(card, ALI_SPDIF_CTRL + 2)); | ||
3436 | wval &= 0xE0F0; | ||
3437 | wval |= (u16) 0x09 << 8 | (u16) 0x05; | ||
3438 | outw(wval, TRID_REG(card, ALI_SPDIF_CTRL + 2)); | ||
3439 | |||
3440 | bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3)) & 0xF0; | ||
3441 | outb(bval | 0x02, TRID_REG(card, ALI_SPDIF_CS + 3)); | ||
3442 | break; | ||
3443 | |||
3444 | case 0x12: | ||
3445 | wval = inw(TRID_REG(card, ALI_SPDIF_CTRL + 2)); | ||
3446 | wval &= 0xE0F0; | ||
3447 | wval |= (u16) 0x0E << 8 | (u16) 0x08; | ||
3448 | outw(wval, TRID_REG(card, ALI_SPDIF_CTRL + 2)); | ||
3449 | |||
3450 | bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3)) & 0xF0; | ||
3451 | outb(bval | 0x03, TRID_REG(card, ALI_SPDIF_CS + 3)); | ||
3452 | break; | ||
3453 | |||
3454 | default: | ||
3455 | break; | ||
3456 | } | ||
3457 | |||
3458 | } | ||
3459 | |||
3460 | static unsigned int | ||
3461 | ali_get_spdif_in_rate(struct trident_card *card) | ||
3462 | { | ||
3463 | u32 dwRate = 0; | ||
3464 | u8 bval = 0; | ||
3465 | |||
3466 | ali_detect_spdif_rate(card); | ||
3467 | |||
3468 | bval = inb(TRID_REG(card, ALI_SPDIF_CTRL)); | ||
3469 | bval &= 0x7F; | ||
3470 | bval |= 0x40; | ||
3471 | outb(bval, TRID_REG(card, ALI_SPDIF_CTRL)); | ||
3472 | |||
3473 | bval = inb(TRID_REG(card, ALI_SPDIF_CS + 3)); | ||
3474 | bval &= 0x0F; | ||
3475 | |||
3476 | switch (bval) { | ||
3477 | case 0: | ||
3478 | dwRate = 44100; | ||
3479 | break; | ||
3480 | case 1: | ||
3481 | dwRate = 48000; | ||
3482 | break; | ||
3483 | case 2: | ||
3484 | dwRate = 32000; | ||
3485 | break; | ||
3486 | default: | ||
3487 | // Error occurs | ||
3488 | break; | ||
3489 | } | ||
3490 | |||
3491 | return dwRate; | ||
3492 | |||
3493 | } | ||
3494 | |||
3495 | static int | ||
3496 | ali_close_multi_channels(void) | ||
3497 | { | ||
3498 | char temp = 0; | ||
3499 | struct pci_dev *pci_dev = NULL; | ||
3500 | |||
3501 | pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, | ||
3502 | pci_dev); | ||
3503 | if (pci_dev == NULL) | ||
3504 | return -1; | ||
3505 | pci_read_config_byte(pci_dev, 0x59, &temp); | ||
3506 | temp &= ~0x80; | ||
3507 | pci_write_config_byte(pci_dev, 0x59, temp); | ||
3508 | |||
3509 | pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, | ||
3510 | pci_dev); | ||
3511 | if (pci_dev == NULL) | ||
3512 | return -1; | ||
3513 | |||
3514 | pci_read_config_byte(pci_dev, 0xB8, &temp); | ||
3515 | temp &= ~0x20; | ||
3516 | pci_write_config_byte(pci_dev, 0xB8, temp); | ||
3517 | |||
3518 | return 0; | ||
3519 | } | ||
3520 | |||
3521 | static int | ||
3522 | ali_setup_multi_channels(struct trident_card *card, int chan_nums) | ||
3523 | { | ||
3524 | unsigned long dwValue; | ||
3525 | char temp = 0; | ||
3526 | struct pci_dev *pci_dev = NULL; | ||
3527 | |||
3528 | pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, | ||
3529 | pci_dev); | ||
3530 | if (pci_dev == NULL) | ||
3531 | return -1; | ||
3532 | pci_read_config_byte(pci_dev, 0x59, &temp); | ||
3533 | temp |= 0x80; | ||
3534 | pci_write_config_byte(pci_dev, 0x59, temp); | ||
3535 | |||
3536 | pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, | ||
3537 | pci_dev); | ||
3538 | if (pci_dev == NULL) | ||
3539 | return -1; | ||
3540 | pci_read_config_byte(pci_dev, (int) 0xB8, &temp); | ||
3541 | temp |= 0x20; | ||
3542 | pci_write_config_byte(pci_dev, (int) 0xB8, (u8) temp); | ||
3543 | if (chan_nums == 6) { | ||
3544 | dwValue = inl(TRID_REG(card, ALI_SCTRL)) | 0x000f0000; | ||
3545 | outl(dwValue, TRID_REG(card, ALI_SCTRL)); | ||
3546 | mdelay(4); | ||
3547 | dwValue = inl(TRID_REG(card, ALI_SCTRL)); | ||
3548 | if (dwValue & 0x2000000) { | ||
3549 | ali_ac97_write(card->ac97_codec[0], 0x02, 8080); | ||
3550 | ali_ac97_write(card->ac97_codec[0], 0x36, 0); | ||
3551 | ali_ac97_write(card->ac97_codec[0], 0x38, 0); | ||
3552 | /* | ||
3553 | * On a board with a single codec you won't get the | ||
3554 | * surround. On other boards configure it. | ||
3555 | */ | ||
3556 | if (card->ac97_codec[1] != NULL) { | ||
3557 | ali_ac97_write(card->ac97_codec[1], 0x36, 0); | ||
3558 | ali_ac97_write(card->ac97_codec[1], 0x38, 0); | ||
3559 | ali_ac97_write(card->ac97_codec[1], 0x02, 0x0606); | ||
3560 | ali_ac97_write(card->ac97_codec[1], 0x18, 0x0303); | ||
3561 | ali_ac97_write(card->ac97_codec[1], 0x74, 0x3); | ||
3562 | } | ||
3563 | return 1; | ||
3564 | } | ||
3565 | } | ||
3566 | return -EINVAL; | ||
3567 | } | ||
3568 | |||
3569 | static void | ||
3570 | ali_free_pcm_channel(struct trident_card *card, unsigned int channel) | ||
3571 | { | ||
3572 | int bank; | ||
3573 | |||
3574 | if (channel > 31) | ||
3575 | return; | ||
3576 | |||
3577 | bank = channel >> 5; | ||
3578 | channel = channel & 0x1f; | ||
3579 | |||
3580 | card->banks[bank].bitmap &= ~(1 << (channel)); | ||
3581 | } | ||
3582 | |||
3583 | static int | ||
3584 | ali_allocate_other_states_resources(struct trident_state *state, int chan_nums) | ||
3585 | { | ||
3586 | struct trident_card *card = state->card; | ||
3587 | struct trident_state *s; | ||
3588 | int i, state_count = 0; | ||
3589 | struct trident_pcm_bank *bank; | ||
3590 | struct trident_channel *channel; | ||
3591 | unsigned long num; | ||
3592 | |||
3593 | bank = &card->banks[BANK_A]; | ||
3594 | |||
3595 | if (chan_nums != 6) | ||
3596 | return 0; | ||
3597 | |||
3598 | for (i = 0; (i < ALI_CHANNELS) && (state_count != 4); i++) { | ||
3599 | if (card->states[i]) | ||
3600 | continue; | ||
3601 | |||
3602 | num = ali_multi_channels_5_1[state_count]; | ||
3603 | if (!(bank->bitmap & (1 << num))) { | ||
3604 | bank->bitmap |= 1 << num; | ||
3605 | channel = &bank->channels[num]; | ||
3606 | channel->num = num; | ||
3607 | } else { | ||
3608 | state_count--; | ||
3609 | for (; state_count >= 0; state_count--) { | ||
3610 | kfree(state->other_states[state_count]); | ||
3611 | num = ali_multi_channels_5_1[state_count]; | ||
3612 | ali_free_pcm_channel(card, num); | ||
3613 | } | ||
3614 | return -EBUSY; | ||
3615 | } | ||
3616 | s = card->states[i] = kmalloc(sizeof(*state), GFP_KERNEL); | ||
3617 | if (!s) { | ||
3618 | num = ali_multi_channels_5_1[state_count]; | ||
3619 | ali_free_pcm_channel(card, num); | ||
3620 | state_count--; | ||
3621 | for (; state_count >= 0; state_count--) { | ||
3622 | num = ali_multi_channels_5_1[state_count]; | ||
3623 | ali_free_pcm_channel(card, num); | ||
3624 | kfree(state->other_states[state_count]); | ||
3625 | } | ||
3626 | return -ENOMEM; | ||
3627 | } | ||
3628 | memset(s, 0, sizeof(*state)); | ||
3629 | |||
3630 | s->dmabuf.channel = channel; | ||
3631 | s->dmabuf.ossfragshift = s->dmabuf.ossmaxfrags = | ||
3632 | s->dmabuf.subdivision = 0; | ||
3633 | init_waitqueue_head(&s->dmabuf.wait); | ||
3634 | s->magic = card->magic; | ||
3635 | s->card = card; | ||
3636 | s->virt = i; | ||
3637 | ali_enable_special_channel(s); | ||
3638 | state->other_states[state_count++] = s; | ||
3639 | } | ||
3640 | |||
3641 | if (state_count != 4) { | ||
3642 | state_count--; | ||
3643 | for (; state_count >= 0; state_count--) { | ||
3644 | kfree(state->other_states[state_count]); | ||
3645 | num = ali_multi_channels_5_1[state_count]; | ||
3646 | ali_free_pcm_channel(card, num); | ||
3647 | } | ||
3648 | return -EBUSY; | ||
3649 | } | ||
3650 | return 0; | ||
3651 | } | ||
3652 | |||
3653 | static void | ||
3654 | ali_save_regs(struct trident_card *card) | ||
3655 | { | ||
3656 | unsigned long flags; | ||
3657 | int i, j; | ||
3658 | |||
3659 | spin_lock_irqsave(&card->lock, flags); | ||
3660 | |||
3661 | ali_registers.global_regs[0x2c] = inl(TRID_REG(card, T4D_MISCINT)); | ||
3662 | //ali_registers.global_regs[0x20] = inl(TRID_REG(card,T4D_START_A)); | ||
3663 | ali_registers.global_regs[0x21] = inl(TRID_REG(card, T4D_STOP_A)); | ||
3664 | |||
3665 | //disable all IRQ bits | ||
3666 | outl(ALI_DISABLE_ALL_IRQ, TRID_REG(card, T4D_MISCINT)); | ||
3667 | |||
3668 | for (i = 1; i < ALI_MIXER_REGS; i++) | ||
3669 | ali_registers.mixer_regs[i] = ali_ac97_read(card->ac97_codec[0], | ||
3670 | i * 2); | ||
3671 | |||
3672 | for (i = 0; i < ALI_GLOBAL_REGS; i++) { | ||
3673 | if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A)) | ||
3674 | continue; | ||
3675 | ali_registers.global_regs[i] = inl(TRID_REG(card, i * 4)); | ||
3676 | } | ||
3677 | |||
3678 | for (i = 0; i < ALI_CHANNELS; i++) { | ||
3679 | outb(i, TRID_REG(card, T4D_LFO_GC_CIR)); | ||
3680 | for (j = 0; j < ALI_CHANNEL_REGS; j++) | ||
3681 | ali_registers.channel_regs[i][j] = inl(TRID_REG(card, | ||
3682 | j * 4 + 0xe0)); | ||
3683 | } | ||
3684 | |||
3685 | //Stop all HW channel | ||
3686 | outl(ALI_STOP_ALL_CHANNELS, TRID_REG(card, T4D_STOP_A)); | ||
3687 | |||
3688 | spin_unlock_irqrestore(&card->lock, flags); | ||
3689 | } | ||
3690 | |||
3691 | static void | ||
3692 | ali_restore_regs(struct trident_card *card) | ||
3693 | { | ||
3694 | unsigned long flags; | ||
3695 | int i, j; | ||
3696 | |||
3697 | spin_lock_irqsave(&card->lock, flags); | ||
3698 | |||
3699 | for (i = 1; i < ALI_MIXER_REGS; i++) | ||
3700 | ali_ac97_write(card->ac97_codec[0], i * 2, | ||
3701 | ali_registers.mixer_regs[i]); | ||
3702 | |||
3703 | for (i = 0; i < ALI_CHANNELS; i++) { | ||
3704 | outb(i, TRID_REG(card, T4D_LFO_GC_CIR)); | ||
3705 | for (j = 0; j < ALI_CHANNEL_REGS; j++) | ||
3706 | outl(ali_registers.channel_regs[i][j], | ||
3707 | TRID_REG(card, j * 4 + 0xe0)); | ||
3708 | } | ||
3709 | |||
3710 | for (i = 0; i < ALI_GLOBAL_REGS; i++) { | ||
3711 | if ((i * 4 == T4D_MISCINT) || (i * 4 == T4D_STOP_A) || | ||
3712 | (i * 4 == T4D_START_A)) | ||
3713 | continue; | ||
3714 | outl(ali_registers.global_regs[i], TRID_REG(card, i * 4)); | ||
3715 | } | ||
3716 | |||
3717 | //start HW channel | ||
3718 | outl(ali_registers.global_regs[0x20], TRID_REG(card, T4D_START_A)); | ||
3719 | //restore IRQ enable bits | ||
3720 | outl(ali_registers.global_regs[0x2c], TRID_REG(card, T4D_MISCINT)); | ||
3721 | |||
3722 | spin_unlock_irqrestore(&card->lock, flags); | ||
3723 | } | ||
3724 | |||
3725 | static int | ||
3726 | trident_suspend(struct pci_dev *dev, pm_message_t unused) | ||
3727 | { | ||
3728 | struct trident_card *card = pci_get_drvdata(dev); | ||
3729 | |||
3730 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | ||
3731 | ali_save_regs(card); | ||
3732 | } | ||
3733 | return 0; | ||
3734 | } | ||
3735 | |||
3736 | static int | ||
3737 | trident_resume(struct pci_dev *dev) | ||
3738 | { | ||
3739 | struct trident_card *card = pci_get_drvdata(dev); | ||
3740 | |||
3741 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | ||
3742 | ali_restore_regs(card); | ||
3743 | } | ||
3744 | return 0; | ||
3745 | } | ||
3746 | |||
3747 | static struct trident_channel * | ||
3748 | ali_alloc_pcm_channel(struct trident_card *card) | ||
3749 | { | ||
3750 | struct trident_pcm_bank *bank; | ||
3751 | int idx; | ||
3752 | |||
3753 | bank = &card->banks[BANK_A]; | ||
3754 | |||
3755 | if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) & | ||
3756 | (ALI_SPDIF_OUT_CH_ENABLE)) { | ||
3757 | idx = ALI_SPDIF_OUT_CHANNEL; | ||
3758 | if (!(bank->bitmap & (1 << idx))) { | ||
3759 | struct trident_channel *channel = &bank->channels[idx]; | ||
3760 | bank->bitmap |= 1 << idx; | ||
3761 | channel->num = idx; | ||
3762 | return channel; | ||
3763 | } | ||
3764 | } | ||
3765 | |||
3766 | for (idx = ALI_PCM_OUT_CHANNEL_FIRST; idx <= ALI_PCM_OUT_CHANNEL_LAST; | ||
3767 | idx++) { | ||
3768 | if (!(bank->bitmap & (1 << idx))) { | ||
3769 | struct trident_channel *channel = &bank->channels[idx]; | ||
3770 | bank->bitmap |= 1 << idx; | ||
3771 | channel->num = idx; | ||
3772 | return channel; | ||
3773 | } | ||
3774 | } | ||
3775 | |||
3776 | /* no more free channels avaliable */ | ||
3777 | #if 0 | ||
3778 | printk(KERN_ERR "ali: no more channels available on Bank A.\n"); | ||
3779 | #endif /* 0 */ | ||
3780 | return NULL; | ||
3781 | } | ||
3782 | |||
3783 | static struct trident_channel * | ||
3784 | ali_alloc_rec_pcm_channel(struct trident_card *card) | ||
3785 | { | ||
3786 | struct trident_pcm_bank *bank; | ||
3787 | int idx; | ||
3788 | |||
3789 | if (inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) & ALI_SPDIF_IN_SUPPORT) | ||
3790 | idx = ALI_SPDIF_IN_CHANNEL; | ||
3791 | else | ||
3792 | idx = ALI_PCM_IN_CHANNEL; | ||
3793 | |||
3794 | bank = &card->banks[BANK_A]; | ||
3795 | |||
3796 | if (!(bank->bitmap & (1 << idx))) { | ||
3797 | struct trident_channel *channel = &bank->channels[idx]; | ||
3798 | bank->bitmap |= 1 << idx; | ||
3799 | channel->num = idx; | ||
3800 | return channel; | ||
3801 | } | ||
3802 | |||
3803 | /* no free recordable channels avaliable */ | ||
3804 | #if 0 | ||
3805 | printk(KERN_ERR "ali: no recordable channels available on Bank A.\n"); | ||
3806 | #endif /* 0 */ | ||
3807 | return NULL; | ||
3808 | } | ||
3809 | |||
3810 | static void | ||
3811 | ali_set_spdif_out_rate(struct trident_card *card, unsigned int rate) | ||
3812 | { | ||
3813 | unsigned char ch_st_sel; | ||
3814 | unsigned short status_rate; | ||
3815 | |||
3816 | switch (rate) { | ||
3817 | case 44100: | ||
3818 | status_rate = 0; | ||
3819 | break; | ||
3820 | case 32000: | ||
3821 | status_rate = 0x300; | ||
3822 | break; | ||
3823 | case 48000: | ||
3824 | default: | ||
3825 | status_rate = 0x200; | ||
3826 | break; | ||
3827 | } | ||
3828 | |||
3829 | /* select spdif_out */ | ||
3830 | ch_st_sel = inb(TRID_REG(card, ALI_SPDIF_CTRL)) & ALI_SPDIF_OUT_CH_STATUS; | ||
3831 | |||
3832 | ch_st_sel |= 0x80; /* select right */ | ||
3833 | outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL)); | ||
3834 | outb(status_rate | 0x20, TRID_REG(card, ALI_SPDIF_CS + 2)); | ||
3835 | |||
3836 | ch_st_sel &= (~0x80); /* select left */ | ||
3837 | outb(ch_st_sel, TRID_REG(card, ALI_SPDIF_CTRL)); | ||
3838 | outw(status_rate | 0x10, TRID_REG(card, ALI_SPDIF_CS + 2)); | ||
3839 | } | ||
3840 | |||
3841 | static void | ||
3842 | ali_address_interrupt(struct trident_card *card) | ||
3843 | { | ||
3844 | int i, channel; | ||
3845 | struct trident_state *state; | ||
3846 | u32 mask, channel_mask; | ||
3847 | |||
3848 | mask = trident_get_interrupt_mask(card, 0); | ||
3849 | for (i = 0; i < NR_HW_CH; i++) { | ||
3850 | if ((state = card->states[i]) == NULL) | ||
3851 | continue; | ||
3852 | channel = state->dmabuf.channel->num; | ||
3853 | if ((channel_mask = 1 << channel) & mask) { | ||
3854 | mask &= ~channel_mask; | ||
3855 | trident_ack_channel_interrupt(card, channel); | ||
3856 | udelay(100); | ||
3857 | state->dmabuf.update_flag |= ALI_ADDRESS_INT_UPDATE; | ||
3858 | trident_update_ptr(state); | ||
3859 | } | ||
3860 | } | ||
3861 | if (mask) { | ||
3862 | for (i = 0; i < NR_HW_CH; i++) { | ||
3863 | if (mask & (1 << i)) { | ||
3864 | printk("ali: spurious channel irq %d.\n", i); | ||
3865 | trident_ack_channel_interrupt(card, i); | ||
3866 | trident_stop_voice(card, i); | ||
3867 | trident_disable_voice_irq(card, i); | ||
3868 | } | ||
3869 | } | ||
3870 | } | ||
3871 | } | ||
3872 | |||
3873 | /* Updating the values of counters of other_states' DMAs without lock | ||
3874 | protection is no harm because all DMAs of multi-channels and interrupt | ||
3875 | depend on a master state's DMA, and changing the counters of the master | ||
3876 | state DMA is protected by a spinlock. | ||
3877 | */ | ||
3878 | static int | ||
3879 | ali_write_5_1(struct trident_state *state, const char __user *buf, | ||
3880 | int cnt_for_multi_channel, unsigned int *copy_count, | ||
3881 | unsigned int *state_cnt) | ||
3882 | { | ||
3883 | |||
3884 | struct dmabuf *dmabuf = &state->dmabuf; | ||
3885 | struct dmabuf *dmabuf_temp; | ||
3886 | const char __user *buffer = buf; | ||
3887 | unsigned swptr, other_dma_nums, sample_s; | ||
3888 | unsigned int i, loop; | ||
3889 | |||
3890 | other_dma_nums = 4; | ||
3891 | sample_s = sample_size[dmabuf->fmt] >> 1; | ||
3892 | swptr = dmabuf->swptr; | ||
3893 | |||
3894 | if ((i = state->multi_channels_adjust_count) > 0) { | ||
3895 | if (i == 1) { | ||
3896 | if (copy_from_user(dmabuf->rawbuf + swptr, | ||
3897 | buffer, sample_s)) | ||
3898 | return -EFAULT; | ||
3899 | seek_offset(swptr, buffer, cnt_for_multi_channel, | ||
3900 | sample_s, *copy_count); | ||
3901 | i--; | ||
3902 | (*state_cnt) += sample_s; | ||
3903 | state->multi_channels_adjust_count++; | ||
3904 | } else | ||
3905 | i = i - (state->chans_num - other_dma_nums); | ||
3906 | for (; (i < other_dma_nums) && (cnt_for_multi_channel > 0); i++) { | ||
3907 | dmabuf_temp = &state->other_states[i]->dmabuf; | ||
3908 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, | ||
3909 | buffer, sample_s)) | ||
3910 | return -EFAULT; | ||
3911 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, | ||
3912 | sample_s, *copy_count); | ||
3913 | } | ||
3914 | if (cnt_for_multi_channel == 0) | ||
3915 | state->multi_channels_adjust_count += i; | ||
3916 | } | ||
3917 | if (cnt_for_multi_channel > 0) { | ||
3918 | loop = cnt_for_multi_channel / (state->chans_num * sample_s); | ||
3919 | for (i = 0; i < loop; i++) { | ||
3920 | if (copy_from_user(dmabuf->rawbuf + swptr, buffer, | ||
3921 | sample_s * 2)) | ||
3922 | return -EFAULT; | ||
3923 | seek_offset(swptr, buffer, cnt_for_multi_channel, | ||
3924 | sample_s * 2, *copy_count); | ||
3925 | (*state_cnt) += (sample_s * 2); | ||
3926 | |||
3927 | dmabuf_temp = &state->other_states[0]->dmabuf; | ||
3928 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, | ||
3929 | buffer, sample_s)) | ||
3930 | return -EFAULT; | ||
3931 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, | ||
3932 | sample_s, *copy_count); | ||
3933 | |||
3934 | dmabuf_temp = &state->other_states[1]->dmabuf; | ||
3935 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, | ||
3936 | buffer, sample_s)) | ||
3937 | return -EFAULT; | ||
3938 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, | ||
3939 | sample_s, *copy_count); | ||
3940 | |||
3941 | dmabuf_temp = &state->other_states[2]->dmabuf; | ||
3942 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, | ||
3943 | buffer, sample_s)) | ||
3944 | return -EFAULT; | ||
3945 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, | ||
3946 | sample_s, *copy_count); | ||
3947 | |||
3948 | dmabuf_temp = &state->other_states[3]->dmabuf; | ||
3949 | if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, | ||
3950 | buffer, sample_s)) | ||
3951 | return -EFAULT; | ||
3952 | seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, | ||
3953 | sample_s, *copy_count); | ||
3954 | } | ||
3955 | |||
3956 | if (cnt_for_multi_channel > 0) { | ||
3957 | state->multi_channels_adjust_count = cnt_for_multi_channel / sample_s; | ||
3958 | |||
3959 | if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s)) | ||
3960 | return -EFAULT; | ||
3961 | seek_offset(swptr, buffer, cnt_for_multi_channel, | ||
3962 | sample_s, *copy_count); | ||
3963 | (*state_cnt) += sample_s; | ||
3964 | |||
3965 | if (cnt_for_multi_channel > 0) { | ||
3966 | if (copy_from_user(dmabuf->rawbuf + swptr, | ||
3967 | buffer, sample_s)) | ||
3968 | return -EFAULT; | ||
3969 | seek_offset(swptr, buffer, cnt_for_multi_channel, | ||
3970 | sample_s, *copy_count); | ||
3971 | (*state_cnt) += sample_s; | ||
3972 | |||
3973 | if (cnt_for_multi_channel > 0) { | ||
3974 | int diff = state->chans_num - other_dma_nums; | ||
3975 | loop = state->multi_channels_adjust_count - diff; | ||
3976 | for (i = 0; i < loop; i++) { | ||
3977 | dmabuf_temp = &state->other_states[i]->dmabuf; | ||
3978 | if (copy_from_user(dmabuf_temp->rawbuf + | ||
3979 | dmabuf_temp->swptr, | ||
3980 | buffer, sample_s)) | ||
3981 | return -EFAULT; | ||
3982 | seek_offset(dmabuf_temp->swptr, buffer, | ||
3983 | cnt_for_multi_channel, | ||
3984 | sample_s, *copy_count); | ||
3985 | } | ||
3986 | } | ||
3987 | } | ||
3988 | } else | ||
3989 | state->multi_channels_adjust_count = 0; | ||
3990 | } | ||
3991 | for (i = 0; i < other_dma_nums; i++) { | ||
3992 | dmabuf_temp = &state->other_states[i]->dmabuf; | ||
3993 | dmabuf_temp->swptr = dmabuf_temp->swptr % dmabuf_temp->dmasize; | ||
3994 | } | ||
3995 | return *state_cnt; | ||
3996 | } | ||
3997 | |||
3998 | static void | ||
3999 | ali_free_other_states_resources(struct trident_state *state) | ||
4000 | { | ||
4001 | int i; | ||
4002 | struct trident_card *card = state->card; | ||
4003 | struct trident_state *s; | ||
4004 | unsigned other_states_count; | ||
4005 | |||
4006 | other_states_count = state->chans_num - 2; /* except PCM L/R channels */ | ||
4007 | for (i = 0; i < other_states_count; i++) { | ||
4008 | s = state->other_states[i]; | ||
4009 | dealloc_dmabuf(&s->dmabuf, card->pci_dev); | ||
4010 | ali_disable_special_channel(s->card, s->dmabuf.channel->num); | ||
4011 | state->card->free_pcm_channel(s->card, s->dmabuf.channel->num); | ||
4012 | card->states[s->virt] = NULL; | ||
4013 | kfree(s); | ||
4014 | } | ||
4015 | } | ||
4016 | |||
4017 | static struct proc_dir_entry *res; | ||
4018 | |||
4019 | static int | ||
4020 | ali_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data) | ||
4021 | { | ||
4022 | struct trident_card *card = (struct trident_card *) data; | ||
4023 | unsigned long flags; | ||
4024 | char c; | ||
4025 | |||
4026 | if (count < 0) | ||
4027 | return -EINVAL; | ||
4028 | if (count == 0) | ||
4029 | return 0; | ||
4030 | if (get_user(c, buffer)) | ||
4031 | return -EFAULT; | ||
4032 | |||
4033 | spin_lock_irqsave(&card->lock, flags); | ||
4034 | switch (c) { | ||
4035 | case '0': | ||
4036 | ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT); | ||
4037 | ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL); | ||
4038 | break; | ||
4039 | case '1': | ||
4040 | ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT | | ||
4041 | ALI_SPDIF_OUT_PCM); | ||
4042 | break; | ||
4043 | case '2': | ||
4044 | ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT | | ||
4045 | ALI_SPDIF_OUT_NON_PCM); | ||
4046 | break; | ||
4047 | case '3': | ||
4048 | ali_disable_spdif_in(card); //default | ||
4049 | break; | ||
4050 | case '4': | ||
4051 | ali_setup_spdif_in(card); | ||
4052 | break; | ||
4053 | } | ||
4054 | spin_unlock_irqrestore(&card->lock, flags); | ||
4055 | |||
4056 | return count; | ||
4057 | } | ||
4058 | |||
4059 | /* OSS /dev/mixer file operation methods */ | ||
4060 | static int | ||
4061 | trident_open_mixdev(struct inode *inode, struct file *file) | ||
4062 | { | ||
4063 | int i = 0; | ||
4064 | int minor = iminor(inode); | ||
4065 | struct trident_card *card = devs; | ||
4066 | |||
4067 | for (card = devs; card != NULL; card = card->next) | ||
4068 | for (i = 0; i < NR_AC97; i++) | ||
4069 | if (card->ac97_codec[i] != NULL && | ||
4070 | card->ac97_codec[i]->dev_mixer == minor) | ||
4071 | goto match; | ||
4072 | |||
4073 | if (!card) { | ||
4074 | return -ENODEV; | ||
4075 | } | ||
4076 | match: | ||
4077 | file->private_data = card->ac97_codec[i]; | ||
4078 | |||
4079 | return nonseekable_open(inode, file); | ||
4080 | } | ||
4081 | |||
4082 | static int | ||
4083 | trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, | ||
4084 | unsigned long arg) | ||
4085 | { | ||
4086 | struct ac97_codec *codec = (struct ac97_codec *) file->private_data; | ||
4087 | |||
4088 | return codec->mixer_ioctl(codec, cmd, arg); | ||
4089 | } | ||
4090 | |||
4091 | static /*const */ struct file_operations trident_mixer_fops = { | ||
4092 | .owner = THIS_MODULE, | ||
4093 | .llseek = no_llseek, | ||
4094 | .ioctl = trident_ioctl_mixdev, | ||
4095 | .open = trident_open_mixdev, | ||
4096 | }; | ||
4097 | |||
4098 | static int | ||
4099 | ali_reset_5451(struct trident_card *card) | ||
4100 | { | ||
4101 | struct pci_dev *pci_dev = NULL; | ||
4102 | unsigned int dwVal; | ||
4103 | unsigned short wCount, wReg; | ||
4104 | |||
4105 | pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, | ||
4106 | pci_dev); | ||
4107 | if (pci_dev == NULL) | ||
4108 | return -1; | ||
4109 | |||
4110 | pci_read_config_dword(pci_dev, 0x7c, &dwVal); | ||
4111 | pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000); | ||
4112 | udelay(5000); | ||
4113 | pci_read_config_dword(pci_dev, 0x7c, &dwVal); | ||
4114 | pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff); | ||
4115 | udelay(5000); | ||
4116 | |||
4117 | pci_dev = card->pci_dev; | ||
4118 | if (pci_dev == NULL) | ||
4119 | return -1; | ||
4120 | |||
4121 | pci_read_config_dword(pci_dev, 0x44, &dwVal); | ||
4122 | pci_write_config_dword(pci_dev, 0x44, dwVal | 0x000c0000); | ||
4123 | udelay(500); | ||
4124 | pci_read_config_dword(pci_dev, 0x44, &dwVal); | ||
4125 | pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff); | ||
4126 | udelay(5000); | ||
4127 | |||
4128 | /* TODO: recognize if we have a PM capable codec and only do this */ | ||
4129 | /* if the codec is PM capable */ | ||
4130 | wCount = 2000; | ||
4131 | while (wCount--) { | ||
4132 | wReg = ali_ac97_get(card, 0, AC97_POWER_CONTROL); | ||
4133 | if ((wReg & 0x000f) == 0x000f) | ||
4134 | return 0; | ||
4135 | udelay(5000); | ||
4136 | } | ||
4137 | /* This is non fatal if you have a non PM capable codec.. */ | ||
4138 | return 0; | ||
4139 | } | ||
4140 | |||
4141 | /* AC97 codec initialisation. */ | ||
4142 | static int __devinit | ||
4143 | trident_ac97_init(struct trident_card *card) | ||
4144 | { | ||
4145 | int num_ac97 = 0; | ||
4146 | unsigned long ready_2nd = 0; | ||
4147 | struct ac97_codec *codec; | ||
4148 | int i = 0; | ||
4149 | |||
4150 | /* initialize controller side of AC link, and find out if secondary codes | ||
4151 | really exist */ | ||
4152 | switch (card->pci_id) { | ||
4153 | case PCI_DEVICE_ID_ALI_5451: | ||
4154 | if (ali_reset_5451(card)) { | ||
4155 | printk(KERN_ERR "trident_ac97_init: error " | ||
4156 | "resetting 5451.\n"); | ||
4157 | return -1; | ||
4158 | } | ||
4159 | outl(0x80000001, TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
4160 | outl(0x00000000, TRID_REG(card, T4D_AINTEN_A)); | ||
4161 | outl(0xffffffff, TRID_REG(card, T4D_AINT_A)); | ||
4162 | outl(0x00000000, TRID_REG(card, T4D_MUSICVOL_WAVEVOL)); | ||
4163 | outb(0x10, TRID_REG(card, ALI_MPUR2)); | ||
4164 | ready_2nd = inl(TRID_REG(card, ALI_SCTRL)); | ||
4165 | ready_2nd &= 0x3fff; | ||
4166 | outl(ready_2nd | PCMOUT | 0x8000, TRID_REG(card, ALI_SCTRL)); | ||
4167 | ready_2nd = inl(TRID_REG(card, ALI_SCTRL)); | ||
4168 | ready_2nd &= SI_AC97_SECONDARY_READY; | ||
4169 | if (card->revision < ALI_5451_V02) | ||
4170 | ready_2nd = 0; | ||
4171 | break; | ||
4172 | case PCI_DEVICE_ID_SI_7018: | ||
4173 | /* disable AC97 GPIO interrupt */ | ||
4174 | outl(0x00, TRID_REG(card, SI_AC97_GPIO)); | ||
4175 | /* when power up the AC link is in cold reset mode so stop it */ | ||
4176 | outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT | SECONDARY_ID, | ||
4177 | TRID_REG(card, SI_SERIAL_INTF_CTRL)); | ||
4178 | /* it take a long time to recover from a cold reset */ | ||
4179 | /* (especially when you have more than one codec) */ | ||
4180 | udelay(2000); | ||
4181 | ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL)); | ||
4182 | ready_2nd &= SI_AC97_SECONDARY_READY; | ||
4183 | break; | ||
4184 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: | ||
4185 | /* playback on */ | ||
4186 | outl(DX_AC97_PLAYBACK, TRID_REG(card, DX_ACR2_AC97_COM_STAT)); | ||
4187 | break; | ||
4188 | case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: | ||
4189 | /* enable AC97 Output Slot 3,4 (PCM Left/Right Playback) */ | ||
4190 | outl(NX_AC97_PCM_OUTPUT, TRID_REG(card, NX_ACR0_AC97_COM_STAT)); | ||
4191 | ready_2nd = inl(TRID_REG(card, NX_ACR0_AC97_COM_STAT)); | ||
4192 | ready_2nd &= NX_AC97_SECONDARY_READY; | ||
4193 | break; | ||
4194 | case PCI_DEVICE_ID_INTERG_5050: | ||
4195 | /* disable AC97 GPIO interrupt */ | ||
4196 | outl(0x00, TRID_REG(card, SI_AC97_GPIO)); | ||
4197 | /* when power up, the AC link is in cold reset mode, so stop it */ | ||
4198 | outl(PCMOUT | SURROUT | CENTEROUT | LFEOUT, | ||
4199 | TRID_REG(card, SI_SERIAL_INTF_CTRL)); | ||
4200 | /* it take a long time to recover from a cold reset (especially */ | ||
4201 | /* when you have more than one codec) */ | ||
4202 | udelay(2000); | ||
4203 | ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL)); | ||
4204 | ready_2nd &= SI_AC97_SECONDARY_READY; | ||
4205 | break; | ||
4206 | } | ||
4207 | |||
4208 | for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { | ||
4209 | if ((codec = ac97_alloc_codec()) == NULL) | ||
4210 | return -ENOMEM; | ||
4211 | |||
4212 | /* initialize some basic codec information, other fields */ | ||
4213 | /* will be filled in ac97_probe_codec */ | ||
4214 | codec->private_data = card; | ||
4215 | codec->id = num_ac97; | ||
4216 | |||
4217 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | ||
4218 | codec->codec_read = ali_ac97_read; | ||
4219 | codec->codec_write = ali_ac97_write; | ||
4220 | } else { | ||
4221 | codec->codec_read = trident_ac97_get; | ||
4222 | codec->codec_write = trident_ac97_set; | ||
4223 | } | ||
4224 | |||
4225 | if (ac97_probe_codec(codec) == 0) | ||
4226 | break; | ||
4227 | |||
4228 | codec->dev_mixer = register_sound_mixer(&trident_mixer_fops, -1); | ||
4229 | if (codec->dev_mixer < 0) { | ||
4230 | printk(KERN_ERR "trident: couldn't register mixer!\n"); | ||
4231 | ac97_release_codec(codec); | ||
4232 | break; | ||
4233 | } | ||
4234 | |||
4235 | card->ac97_codec[num_ac97] = codec; | ||
4236 | |||
4237 | /* if there is no secondary codec at all, don't probe any more */ | ||
4238 | if (!ready_2nd) | ||
4239 | break; | ||
4240 | } | ||
4241 | |||
4242 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | ||
4243 | for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { | ||
4244 | if (card->ac97_codec[num_ac97] == NULL) | ||
4245 | break; | ||
4246 | for (i = 0; i < 64; i++) { | ||
4247 | u16 reg = ali_ac97_get(card, num_ac97, i * 2); | ||
4248 | card->mixer_regs[i][num_ac97] = reg; | ||
4249 | } | ||
4250 | } | ||
4251 | } | ||
4252 | return num_ac97 + 1; | ||
4253 | } | ||
4254 | |||
4255 | /* Gameport functions for the cards ADC gameport */ | ||
4256 | |||
4257 | static unsigned char | ||
4258 | trident_game_read(struct gameport *gameport) | ||
4259 | { | ||
4260 | struct trident_card *card = gameport->port_data; | ||
4261 | return inb(TRID_REG(card, T4D_GAME_LEG)); | ||
4262 | } | ||
4263 | |||
4264 | static void | ||
4265 | trident_game_trigger(struct gameport *gameport) | ||
4266 | { | ||
4267 | struct trident_card *card = gameport->port_data; | ||
4268 | outb(0xff, TRID_REG(card, T4D_GAME_LEG)); | ||
4269 | } | ||
4270 | |||
4271 | static int | ||
4272 | trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) | ||
4273 | { | ||
4274 | struct trident_card *card = gameport->port_data; | ||
4275 | int i; | ||
4276 | |||
4277 | *buttons = (~inb(TRID_REG(card, T4D_GAME_LEG)) >> 4) & 0xf; | ||
4278 | |||
4279 | for (i = 0; i < 4; i++) { | ||
4280 | axes[i] = inw(TRID_REG(card, T4D_GAME_AXD) + i * sizeof (u16)); | ||
4281 | if (axes[i] == 0xffff) | ||
4282 | axes[i] = -1; | ||
4283 | } | ||
4284 | |||
4285 | return 0; | ||
4286 | } | ||
4287 | |||
4288 | static int | ||
4289 | trident_game_open(struct gameport *gameport, int mode) | ||
4290 | { | ||
4291 | struct trident_card *card = gameport->port_data; | ||
4292 | |||
4293 | switch (mode) { | ||
4294 | case GAMEPORT_MODE_COOKED: | ||
4295 | outb(0x80, TRID_REG(card, T4D_GAME_CR)); | ||
4296 | msleep(20); | ||
4297 | return 0; | ||
4298 | case GAMEPORT_MODE_RAW: | ||
4299 | outb(0x00, TRID_REG(card, T4D_GAME_CR)); | ||
4300 | return 0; | ||
4301 | default: | ||
4302 | return -1; | ||
4303 | } | ||
4304 | |||
4305 | return 0; | ||
4306 | } | ||
4307 | |||
4308 | static int __devinit | ||
4309 | trident_register_gameport(struct trident_card *card) | ||
4310 | { | ||
4311 | struct gameport *gp; | ||
4312 | |||
4313 | card->gameport = gp = gameport_allocate_port(); | ||
4314 | if (!gp) { | ||
4315 | printk(KERN_ERR "trident: can not allocate memory for gameport\n"); | ||
4316 | return -ENOMEM; | ||
4317 | } | ||
4318 | |||
4319 | gameport_set_name(gp, "Trident 4DWave"); | ||
4320 | gameport_set_phys(gp, "pci%s/gameport0", pci_name(card->pci_dev)); | ||
4321 | gp->read = trident_game_read; | ||
4322 | gp->trigger = trident_game_trigger; | ||
4323 | gp->cooked_read = trident_game_cooked_read; | ||
4324 | gp->open = trident_game_open; | ||
4325 | gp->fuzz = 64; | ||
4326 | gp->port_data = card; | ||
4327 | |||
4328 | gameport_register_port(gp); | ||
4329 | |||
4330 | return 0; | ||
4331 | } | ||
4332 | |||
4333 | /* install the driver, we do not allocate hardware channel nor DMA buffer */ | ||
4334 | /* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ | ||
4335 | /* open/read/write/ioctl/mmap) */ | ||
4336 | static int __devinit | ||
4337 | trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) | ||
4338 | { | ||
4339 | unsigned long iobase; | ||
4340 | struct trident_card *card; | ||
4341 | u8 bits; | ||
4342 | u8 revision; | ||
4343 | int i = 0; | ||
4344 | u16 temp; | ||
4345 | struct pci_dev *pci_dev_m1533 = NULL; | ||
4346 | int rc = -ENODEV; | ||
4347 | u64 dma_mask; | ||
4348 | |||
4349 | if (pci_enable_device(pci_dev)) | ||
4350 | goto out; | ||
4351 | |||
4352 | if (pci_dev->device == PCI_DEVICE_ID_ALI_5451) | ||
4353 | dma_mask = ALI_DMA_MASK; | ||
4354 | else | ||
4355 | dma_mask = TRIDENT_DMA_MASK; | ||
4356 | if (pci_set_dma_mask(pci_dev, dma_mask)) { | ||
4357 | printk(KERN_ERR "trident: architecture does not support" | ||
4358 | " %s PCI busmaster DMA\n", | ||
4359 | pci_dev->device == PCI_DEVICE_ID_ALI_5451 ? | ||
4360 | "32-bit" : "30-bit"); | ||
4361 | goto out; | ||
4362 | } | ||
4363 | pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision); | ||
4364 | |||
4365 | if (pci_id->device == PCI_DEVICE_ID_INTERG_5050) | ||
4366 | iobase = pci_resource_start(pci_dev, 1); | ||
4367 | else | ||
4368 | iobase = pci_resource_start(pci_dev, 0); | ||
4369 | |||
4370 | if (!request_region(iobase, 256, card_names[pci_id->driver_data])) { | ||
4371 | printk(KERN_ERR "trident: can't allocate I/O space at " | ||
4372 | "0x%4.4lx\n", iobase); | ||
4373 | goto out; | ||
4374 | } | ||
4375 | |||
4376 | rc = -ENOMEM; | ||
4377 | if ((card = kmalloc(sizeof(*card), GFP_KERNEL)) == NULL) { | ||
4378 | printk(KERN_ERR "trident: out of memory\n"); | ||
4379 | goto out_release_region; | ||
4380 | } | ||
4381 | memset(card, 0, sizeof (*card)); | ||
4382 | |||
4383 | init_timer(&card->timer); | ||
4384 | card->iobase = iobase; | ||
4385 | card->pci_dev = pci_dev; | ||
4386 | card->pci_id = pci_id->device; | ||
4387 | card->revision = revision; | ||
4388 | card->irq = pci_dev->irq; | ||
4389 | card->next = devs; | ||
4390 | card->magic = TRIDENT_CARD_MAGIC; | ||
4391 | card->banks[BANK_A].addresses = &bank_a_addrs; | ||
4392 | card->banks[BANK_A].bitmap = 0UL; | ||
4393 | card->banks[BANK_B].addresses = &bank_b_addrs; | ||
4394 | card->banks[BANK_B].bitmap = 0UL; | ||
4395 | |||
4396 | init_MUTEX(&card->open_sem); | ||
4397 | spin_lock_init(&card->lock); | ||
4398 | init_timer(&card->timer); | ||
4399 | |||
4400 | devs = card; | ||
4401 | |||
4402 | pci_set_master(pci_dev); | ||
4403 | |||
4404 | printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n", | ||
4405 | card_names[pci_id->driver_data], card->iobase, card->irq); | ||
4406 | |||
4407 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | ||
4408 | /* ALi channel Management */ | ||
4409 | card->alloc_pcm_channel = ali_alloc_pcm_channel; | ||
4410 | card->alloc_rec_pcm_channel = ali_alloc_rec_pcm_channel; | ||
4411 | card->free_pcm_channel = ali_free_pcm_channel; | ||
4412 | |||
4413 | card->address_interrupt = ali_address_interrupt; | ||
4414 | |||
4415 | /* Added by Matt Wu 01-05-2001 for spdif in */ | ||
4416 | card->multi_channel_use_count = 0; | ||
4417 | card->rec_channel_use_count = 0; | ||
4418 | |||
4419 | /* ALi SPDIF OUT function */ | ||
4420 | if (card->revision == ALI_5451_V02) { | ||
4421 | ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT); | ||
4422 | res = create_proc_entry("ALi5451", 0, NULL); | ||
4423 | if (res) { | ||
4424 | res->write_proc = ali_write_proc; | ||
4425 | res->data = card; | ||
4426 | } | ||
4427 | } | ||
4428 | |||
4429 | /* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */ | ||
4430 | card->hwvolctl = 0; | ||
4431 | pci_dev_m1533 = pci_find_device(PCI_VENDOR_ID_AL, | ||
4432 | PCI_DEVICE_ID_AL_M1533, | ||
4433 | pci_dev_m1533); | ||
4434 | rc = -ENODEV; | ||
4435 | if (pci_dev_m1533 == NULL) | ||
4436 | goto out_proc_fs; | ||
4437 | pci_read_config_byte(pci_dev_m1533, 0x63, &bits); | ||
4438 | if (bits & (1 << 5)) | ||
4439 | card->hwvolctl = 1; | ||
4440 | if (card->hwvolctl) { | ||
4441 | /* Clear m1533 pci cfg 78h bit 30 to zero, which makes | ||
4442 | GPIO11/12/13 work as ACGP_UP/DOWN/MUTE. */ | ||
4443 | pci_read_config_byte(pci_dev_m1533, 0x7b, &bits); | ||
4444 | bits &= 0xbf; /*clear bit 6 */ | ||
4445 | pci_write_config_byte(pci_dev_m1533, 0x7b, bits); | ||
4446 | } | ||
4447 | } else if (card->pci_id == PCI_DEVICE_ID_INTERG_5050) { | ||
4448 | card->alloc_pcm_channel = cyber_alloc_pcm_channel; | ||
4449 | card->alloc_rec_pcm_channel = cyber_alloc_pcm_channel; | ||
4450 | card->free_pcm_channel = cyber_free_pcm_channel; | ||
4451 | card->address_interrupt = cyber_address_interrupt; | ||
4452 | cyber_init_ritual(card); | ||
4453 | } else { | ||
4454 | card->alloc_pcm_channel = trident_alloc_pcm_channel; | ||
4455 | card->alloc_rec_pcm_channel = trident_alloc_pcm_channel; | ||
4456 | card->free_pcm_channel = trident_free_pcm_channel; | ||
4457 | card->address_interrupt = trident_address_interrupt; | ||
4458 | } | ||
4459 | |||
4460 | /* claim our irq */ | ||
4461 | rc = -ENODEV; | ||
4462 | if (request_irq(card->irq, &trident_interrupt, SA_SHIRQ, | ||
4463 | card_names[pci_id->driver_data], card)) { | ||
4464 | printk(KERN_ERR "trident: unable to allocate irq %d\n", | ||
4465 | card->irq); | ||
4466 | goto out_proc_fs; | ||
4467 | } | ||
4468 | /* register /dev/dsp */ | ||
4469 | if ((card->dev_audio = register_sound_dsp(&trident_audio_fops, -1)) < 0) { | ||
4470 | printk(KERN_ERR "trident: couldn't register DSP device!\n"); | ||
4471 | goto out_free_irq; | ||
4472 | } | ||
4473 | card->mixer_regs_ready = 0; | ||
4474 | /* initialize AC97 codec and register /dev/mixer */ | ||
4475 | if (trident_ac97_init(card) <= 0) { | ||
4476 | /* unregister audio devices */ | ||
4477 | for (i = 0; i < NR_AC97; i++) { | ||
4478 | if (card->ac97_codec[i] != NULL) { | ||
4479 | struct ac97_codec* codec = card->ac97_codec[i]; | ||
4480 | unregister_sound_mixer(codec->dev_mixer); | ||
4481 | ac97_release_codec(codec); | ||
4482 | } | ||
4483 | } | ||
4484 | goto out_unregister_sound_dsp; | ||
4485 | } | ||
4486 | card->mixer_regs_ready = 1; | ||
4487 | outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL)); | ||
4488 | |||
4489 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | ||
4490 | /* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */ | ||
4491 | if (card->hwvolctl) { | ||
4492 | /* Enable GPIO IRQ (MISCINT bit 18h) */ | ||
4493 | temp = inw(TRID_REG(card, T4D_MISCINT + 2)); | ||
4494 | temp |= 0x0004; | ||
4495 | outw(temp, TRID_REG(card, T4D_MISCINT + 2)); | ||
4496 | |||
4497 | /* Enable H/W Volume Control GLOVAL CONTROL bit 0 */ | ||
4498 | temp = inw(TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
4499 | temp |= 0x0001; | ||
4500 | outw(temp, TRID_REG(card, ALI_GLOBAL_CONTROL)); | ||
4501 | |||
4502 | } | ||
4503 | if (card->revision == ALI_5451_V02) | ||
4504 | ali_close_multi_channels(); | ||
4505 | /* edited by HMSEO for GT sound */ | ||
4506 | #if defined(CONFIG_ALPHA_NAUTILUS) || defined(CONFIG_ALPHA_GENERIC) | ||
4507 | { | ||
4508 | u16 ac97_data; | ||
4509 | extern struct hwrpb_struct *hwrpb; | ||
4510 | |||
4511 | if ((hwrpb->sys_type) == 201) { | ||
4512 | printk(KERN_INFO "trident: Running on Alpha system " | ||
4513 | "type Nautilus\n"); | ||
4514 | ac97_data = ali_ac97_get(card, 0, AC97_POWER_CONTROL); | ||
4515 | ali_ac97_set(card, 0, AC97_POWER_CONTROL, | ||
4516 | ac97_data | ALI_EAPD_POWER_DOWN); | ||
4517 | } | ||
4518 | } | ||
4519 | #endif /* CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC */ | ||
4520 | /* edited by HMSEO for GT sound */ | ||
4521 | } | ||
4522 | rc = 0; | ||
4523 | pci_set_drvdata(pci_dev, card); | ||
4524 | |||
4525 | /* Enable Address Engine Interrupts */ | ||
4526 | trident_enable_loop_interrupts(card); | ||
4527 | |||
4528 | /* Register gameport */ | ||
4529 | trident_register_gameport(card); | ||
4530 | |||
4531 | out: | ||
4532 | return rc; | ||
4533 | |||
4534 | out_unregister_sound_dsp: | ||
4535 | unregister_sound_dsp(card->dev_audio); | ||
4536 | out_free_irq: | ||
4537 | free_irq(card->irq, card); | ||
4538 | out_proc_fs: | ||
4539 | if (res) { | ||
4540 | remove_proc_entry("ALi5451", NULL); | ||
4541 | res = NULL; | ||
4542 | } | ||
4543 | kfree(card); | ||
4544 | devs = NULL; | ||
4545 | out_release_region: | ||
4546 | release_region(iobase, 256); | ||
4547 | return rc; | ||
4548 | } | ||
4549 | |||
4550 | static void __devexit | ||
4551 | trident_remove(struct pci_dev *pci_dev) | ||
4552 | { | ||
4553 | int i; | ||
4554 | struct trident_card *card = pci_get_drvdata(pci_dev); | ||
4555 | |||
4556 | /* | ||
4557 | * Kill running timers before unload. We can't have them | ||
4558 | * going off after rmmod! | ||
4559 | */ | ||
4560 | if (card->hwvolctl) | ||
4561 | del_timer_sync(&card->timer); | ||
4562 | |||
4563 | /* ALi S/PDIF and Power Management */ | ||
4564 | if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { | ||
4565 | ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT); | ||
4566 | ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL); | ||
4567 | ali_disable_spdif_in(card); | ||
4568 | remove_proc_entry("ALi5451", NULL); | ||
4569 | } | ||
4570 | |||
4571 | /* Unregister gameport */ | ||
4572 | if (card->gameport) | ||
4573 | gameport_unregister_port(card->gameport); | ||
4574 | |||
4575 | /* Kill interrupts, and SP/DIF */ | ||
4576 | trident_disable_loop_interrupts(card); | ||
4577 | |||
4578 | /* free hardware resources */ | ||
4579 | free_irq(card->irq, card); | ||
4580 | release_region(card->iobase, 256); | ||
4581 | |||
4582 | /* unregister audio devices */ | ||
4583 | for (i = 0; i < NR_AC97; i++) | ||
4584 | if (card->ac97_codec[i] != NULL) { | ||
4585 | unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); | ||
4586 | ac97_release_codec(card->ac97_codec[i]); | ||
4587 | } | ||
4588 | unregister_sound_dsp(card->dev_audio); | ||
4589 | |||
4590 | kfree(card); | ||
4591 | |||
4592 | pci_set_drvdata(pci_dev, NULL); | ||
4593 | } | ||
4594 | |||
4595 | MODULE_AUTHOR("Alan Cox, Aaron Holtzman, Ollie Lho, Ching Ling Lee, Muli Ben-Yehuda"); | ||
4596 | MODULE_DESCRIPTION("Trident 4DWave/SiS 7018/ALi 5451 and Tvia/IGST CyberPro5050 PCI " | ||
4597 | "Audio Driver"); | ||
4598 | MODULE_LICENSE("GPL"); | ||
4599 | |||
4600 | #define TRIDENT_MODULE_NAME "trident" | ||
4601 | |||
4602 | static struct pci_driver trident_pci_driver = { | ||
4603 | .name = TRIDENT_MODULE_NAME, | ||
4604 | .id_table = trident_pci_tbl, | ||
4605 | .probe = trident_probe, | ||
4606 | .remove = __devexit_p(trident_remove), | ||
4607 | .suspend = trident_suspend, | ||
4608 | .resume = trident_resume | ||
4609 | }; | ||
4610 | |||
4611 | static int __init | ||
4612 | trident_init_module(void) | ||
4613 | { | ||
4614 | printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro " | ||
4615 | "5050 PCI Audio, version " DRIVER_VERSION ", " __TIME__ " " | ||
4616 | __DATE__ "\n"); | ||
4617 | |||
4618 | return pci_register_driver(&trident_pci_driver); | ||
4619 | } | ||
4620 | |||
4621 | static void __exit | ||
4622 | trident_cleanup_module(void) | ||
4623 | { | ||
4624 | pci_unregister_driver(&trident_pci_driver); | ||
4625 | } | ||
4626 | |||
4627 | module_init(trident_init_module); | ||
4628 | module_exit(trident_cleanup_module); | ||