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