source: cmedia/trunk/Cmpci/cmpci.c@ 577

Last change on this file since 577 was 559, checked in by rudi, 14 years ago

bumped version number to 0.2.4, more cleanup

File size: 127.3 KB
Line 
1/*****************************************************************************/
2
3/*
4 * cmpci.c -- C-Media PCI audio driver.
5 *
6 * Copyright (C) 1999 ChenLi Tien (cltien@cmedia.com.tw)
7 * C-media support (support@cmedia.com.tw)
8 *
9 * Based on the PCI drivers by Thomas Sailer (sailer@ife.ee.ethz.ch)
10 *
11 * For update, visit:
12 * http://members.home.net/puresoft/cmedia.html
13 * http://www.cmedia.com.tw
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 *
29 * Special thanks to David C. Niemi, Jan Pfeifer
30 *
31 *
32 * Module command line parameters:
33 * none so far
34 *
35 *
36 * Supported devices:
37 * /dev/dsp standard /dev/dsp device, (mostly) OSS compatible
38 * /dev/mixer standard /dev/mixer device, (mostly) OSS compatible
39 * /dev/midi simple MIDI UART interface, no ioctl
40 *
41 * The card has both an FM and a Wavetable synth, but I have to figure
42 * out first how to drive them...
43 *
44 * Revision history
45 * 06.05.98 0.1 Initial release
46 * 10.05.98 0.2 Fixed many bugs, esp. ADC rate calculation
47 * First stab at a simple midi interface (no bells&whistles)
48 * 13.05.98 0.3 Fix stupid cut&paste error: set_adc_rate was called instead of
49 * set_dac_rate in the FMODE_WRITE case in cm_open
50 * Fix hwptr out of bounds (now mpg123 works)
51 * 14.05.98 0.4 Don't allow excessive interrupt rates
52 * 08.06.98 0.5 First release using Alan Cox' soundcore instead of miscdevice
53 * 03.08.98 0.6 Do not include modversions.h
54 * Now mixer behaviour can basically be selected between
55 * "OSS documented" and "OSS actual" behaviour
56 * 31.08.98 0.7 Fix realplayer problems - dac.count issues
57 * 10.12.98 0.8 Fix drain_dac trying to wait on not yet initialized DMA
58 * 16.12.98 0.9 Fix a few f_file & FMODE_ bugs
59 * 06.01.99 0.10 remove the silly SA_INTERRUPT flag.
60 * hopefully killed the egcs section type conflict
61 * 12.03.99 0.11 cinfo.blocks should be reset after GETxPTR ioctl.
62 * reported by Johan Maes <joma@telindus.be>
63 * 22.03.99 0.12 return EAGAIN instead of EBUSY when O_NONBLOCK
64 * read/write cannot be executed
65 * 18.08.99 1.5 Only deallocate DMA buffer when unloading.
66 * 02.09.99 1.6 Enable SPDIF LOOP
67 * Change the mixer read back
68 * 21.09.99 2.33 Use RCS version as driver version.
69 * Add support for modem, S/PDIF loop and 4 channels.
70 * (8738 only)
71 * Fix bug cause x11amp cannot play.
72 *
73 */
74
75/*****************************************************************************/
76
77#define EXPORT_SYMTAB
78#include <linux/version.h>
79#ifndef TARGET_OS2
80 #include <linux/config.h>
81#endif
82#include <linux/kernel.h>
83#include <linux/types.h>
84#include <linux/list.h>
85#include <linux/module.h>
86#ifndef TARGET_OS2
87 #include <linux/string.h>
88#endif
89#include <linux/ioport.h>
90#include <linux/sched.h>
91#include <linux/delay.h>
92#include <linux/sound.h>
93#include <linux/malloc.h>
94#include <linux/soundcard.h>
95#include <linux/pci.h>
96#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
97 #include <linux/wrapper.h>
98#endif
99#include <asm/io.h>
100#include <asm/dma.h>
101#include <linux/init.h>
102#include <linux/poll.h>
103
104#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
105 #include <linux/spinlock.h>
106
107 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
108 #include <linux/smp_lock.h>
109 #endif
110
111 #ifdef TARGET_OS2
112 #include <linux/delay.h>
113 #include "cmpcios2.h"
114 #endif
115
116#else
117 #include <asm/spinlock.h>
118 #define AFMT_AC3 0x00000400 /* Dolby Digital AC3 */
119 #define DSP_CAP_BIND 0x00008000 /* channel binding to front/rear/cneter/lfe */
120 #define SNDCTL_DSP_GETCHANNELMASK _SIOWR('P', 64, int)
121 #define SNDCTL_DSP_BIND_CHANNEL _SIOWR('P', 65, int)
122 #define DSP_BIND_QUERY 0x00000000
123 #define DSP_BIND_FRONT 0x00000001
124 #define DSP_BIND_SURR 0x00000002
125 #define DSP_BIND_CENTER_LFE 0x00000004
126 #define DSP_BIND_HANDSET 0x00000008
127 #define DSP_BIND_MIC 0x00000010
128 #define DSP_BIND_MODEM1 0x00000020
129 #define DSP_BIND_MODEM2 0x00000040
130 #define DSP_BIND_I2S 0x00000080
131 #define DSP_BIND_SPDIF 0x00000100
132
133#endif
134
135#include <asm/uaccess.h>
136#include <asm/hardirq.h>
137
138
139// Rudi: allow multiple open requests on OS/2
140#ifdef TARGET_OS2
141 #define AUDIO_DEV_PTR(a) (*(struct cm_state **)(a))
142#else
143 #define AUDIO_DEV_PTR(a) ((struct cm_state *)(a))
144 #include "dm.h"
145#endif
146
147
148/* --------------------------------------------------------------------- */
149
150// Rudi: We do not read back mixer values from hardware...
151#undef OSS_DOCUMENTED_MIXER_SEMANTICS
152
153/* --------------------------------------------------------------------- */
154
155#ifndef PCI_VENDOR_ID_CMEDIA
156#define PCI_VENDOR_ID_CMEDIA 0x13F6
157#endif
158#ifndef PCI_DEVICE_ID_CMEDIA_CM8338A
159#define PCI_DEVICE_ID_CMEDIA_CM8338A 0x0100
160#endif
161#ifndef PCI_DEVICE_ID_CMEDIA_CM8338B
162#define PCI_DEVICE_ID_CMEDIA_CM8338B 0x0101
163#endif
164#ifndef PCI_DEVICE_ID_CMEDIA_CM8738
165#define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111
166#endif
167#ifndef PCI_DEVICE_ID_CMEDIA_CM8738B
168#define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112
169#endif
170
171#define CM_MAGIC ((PCI_VENDOR_ID_CMEDIA<<16)|PCI_DEVICE_ID_CMEDIA_CM8338A)
172
173/*
174 * CM8338 registers definition
175 */
176
177#define CODEC_CMI_FUNCTRL0 (0x00)
178#define CODEC_CMI_FUNCTRL1 (0x04)
179#define CODEC_CMI_CHFORMAT (0x08)
180#define CODEC_CMI_INT_HLDCLR (0x0C)
181#define CODEC_CMI_INT_STATUS (0x10)
182#define CODEC_CMI_LEGACY_CTRL (0x14)
183#define CODEC_CMI_MISC_CTRL (0x18)
184#define CODEC_CMI_TDMA_POS (0x1C)
185#define CODEC_CMI_MIXER (0x20)
186#define CODEC_SB16_DATA (0x22)
187#define CODEC_SB16_ADDR (0x23)
188#define CODEC_CMI_MIXER1 (0x24)
189#define CODEC_CMI_MIXER2 (0x25)
190#define CODEC_CMI_AUX_VOL (0x26)
191#define CODEC_CMI_MISC (0x27)
192#define CODEC_CMI_AC97 (0x28)
193
194#define CODEC_CMI_CH0_FRAME1 (0x80)
195#define CODEC_CMI_CH0_FRAME2 (0x84)
196#define CODEC_CMI_CH1_FRAME1 (0x88)
197#define CODEC_CMI_CH1_FRAME2 (0x8C)
198
199#define CODEC_CMI_EXT_REG (0xF0) // ???
200
201
202/*
203** Mixer registers for SB16
204*/
205
206#define UCHAR unsigned char
207
208#define DSP_MIX_DATARESETIDX ((UCHAR)(0x00))
209
210#define DSP_MIX_MASTERVOLIDX_L ((UCHAR)(0x30))
211#define DSP_MIX_MASTERVOLIDX_R ((UCHAR)(0x31))
212#define DSP_MIX_VOICEVOLIDX_L ((UCHAR)(0x32))
213#define DSP_MIX_VOICEVOLIDX_R ((UCHAR)(0x33))
214#define DSP_MIX_FMVOLIDX_L ((UCHAR)(0x34))
215#define DSP_MIX_FMVOLIDX_R ((UCHAR)(0x35))
216#define DSP_MIX_CDVOLIDX_L ((UCHAR)(0x36))
217#define DSP_MIX_CDVOLIDX_R ((UCHAR)(0x37))
218#define DSP_MIX_LINEVOLIDX_L ((UCHAR)(0x38))
219#define DSP_MIX_LINEVOLIDX_R ((UCHAR)(0x39))
220
221#define DSP_MIX_MICVOLIDX ((UCHAR)(0x3A))
222#define DSP_MIX_SPKRVOLIDX ((UCHAR)(0x3B))
223
224#define DSP_MIX_OUTMIXIDX ((UCHAR)(0x3C))
225
226#define DSP_MIX_ADCMIXIDX_L ((UCHAR)(0x3D))
227#define DSP_MIX_ADCMIXIDX_R ((UCHAR)(0x3E))
228
229#define DSP_MIX_INGAINIDX_L ((UCHAR)(0x3F)) // not present
230#define DSP_MIX_INGAINIDX_R ((UCHAR)(0x40)) // not present
231#define DSP_MIX_OUTGAINIDX_L ((UCHAR)(0x41)) // not present
232#define DSP_MIX_OUTGAINIDX_R ((UCHAR)(0x42)) // not present
233
234#define DSP_MIX_AGCIDX ((UCHAR)(0x43)) // not present
235
236#define DSP_MIX_TREBLEIDX_L ((UCHAR)(0x44)) // not present
237#define DSP_MIX_TREBLEIDX_R ((UCHAR)(0x45)) // not present
238#define DSP_MIX_BASSIDX_L ((UCHAR)(0x46)) // not present
239#define DSP_MIX_BASSIDX_R ((UCHAR)(0x47)) // not present
240
241#define DSP_MIX_EXTENSIONIDX ((UCHAR)(0xf0))
242
243
244#define CM_RESET_CH0 0x04
245#define CM_RESET_CH1 0x08
246
247#define CM_EXTENT_CODEC 0x100
248#define CM_EXTENT_MIDI 0x2
249#define CM_EXTENT_SYNTH 0x4
250
251#define CM_INT_CH0 0x1
252#define CM_INT_CH1 0x2
253
254#define CM_INTR 0x80000000
255#define CM_UARTINT 0x00010000
256#define CM_LTDMAINT 0x00008000
257#define CM_HTDMAINT 0x00004000
258#define CM_CH1BUSY 0x00000008
259#define CM_CH0BUSY 0x00000004
260#define CM_CHINT1 0x00000002
261#define CM_CHINT0 0x00000001
262
263
264#define CM_CFMT_STEREO 0x01
265#define CM_CFMT_16BIT 0x02
266#define CM_CFMT_MASK 0x03
267#define CM_CFMT_SHIFT_CH0 0
268#define CM_CFMT_SHIFT_CH1 2
269
270static const unsigned sample_size[] = { 1, 2, 2, 4 };
271static const unsigned sample_shift[] = { 0, 1, 1, 2 };
272static const unsigned sample_mask[] = { ~0, ~1, ~1, ~3 };
273
274#define CM_ENABLE_CH0 0x1
275#define CM_ENABLE_CH1 0x2
276#define CM_PAUSE_CH0 0x4
277#define CM_PAUSE_CH1 0x8
278
279
280
281/* MIDI buffer sizes */
282
283#define MIDIINBUF 256
284#define MIDIOUTBUF 256
285
286#define FMODE_MIDI_SHIFT 2
287#define FMODE_MIDI_READ (FMODE_READ << FMODE_MIDI_SHIFT)
288#define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT)
289
290#define FMODE_DMFM 0x10
291
292#define SND_DEV_DSP16 5
293
294#define set_dac1_rate set_adc_rate
295#define stop_dac1 stop_adc
296#define get_dmadac1 get_dmaadc
297
298
299// hardware multichannel seems to work exclusively on channel B
300#define FORCE_DUAL_DAC
301
302
303/* --------------------------------------------------------------------- */
304
305struct cm_state {
306 /* magic */
307 unsigned int magic;
308
309 /* we keep cm cards in a linked list */
310 struct cm_state *next;
311
312 /* soundcore stuff */
313 int dev_audio;
314 int dev_mixer;
315 int dev_midi;
316 int dev_dmfm;
317
318 /* hardware resources */
319 unsigned int iosb, iobase, iosynth, iomidi, iogame, irq;
320 unsigned short deviceid;
321
322 /* mixer stuff */
323 struct {
324 unsigned int modcnt;
325#ifndef OSS_DOCUMENTED_MIXER_SEMANTICS
326//Rudi: unsigned short vol[13];
327 unsigned short vol[SOUND_MIXER_NRDEVICES];
328#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
329 } mix;
330
331 /* wave stuff */
332 unsigned int rateadc, ratedac;
333 unsigned char fmt, enable;
334
335 spinlock_t lock;
336 struct semaphore open_sem;
337 mode_t open_mode;
338#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
339 wait_queue_head_t open_wait;
340#else
341 struct wait_queue *open_wait;
342#endif
343
344 struct dmabuf {
345 void *rawbuf;
346 unsigned rawphys;
347 unsigned buforder;
348 unsigned numfrag;
349 unsigned fragshift;
350 unsigned hwptr, swptr;
351 unsigned total_bytes;
352 int count;
353 unsigned error; /* over/underrun */
354#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
355 wait_queue_head_t wait;
356#else
357 struct wait_queue *wait;
358#endif
359 /* redundant, but makes calculations easier */
360 unsigned fragsize;
361 unsigned dmasize;
362 unsigned fragsamples;
363 unsigned dmasamples;
364 /* OSS stuff */
365 unsigned mapped:1;
366 unsigned ready:1;
367 unsigned endcleared:1;
368 unsigned ossfragshift;
369 int ossmaxfrags;
370 unsigned subdivision;
371 } dma_dac, dma_adc;
372
373 /* midi stuff */
374 struct {
375 unsigned ird, iwr, icnt;
376 unsigned ord, owr, ocnt;
377#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
378 wait_queue_head_t iwait;
379 wait_queue_head_t owait;
380#else
381 struct wait_queue *iwait;
382 struct wait_queue *owait;
383#endif
384#ifdef CONFIG_SOUND_CMPCI_MIDI
385 struct timer_list timer;
386#endif
387 unsigned char ibuf[MIDIINBUF];
388 unsigned char obuf[MIDIOUTBUF];
389 } midi;
390
391 /* misc stuff */
392 int modem;
393 int chip_version;
394 int max_channels;
395 int curr_channels;
396 int speakers; // number of speakers
397 int capability; // HW capability, various for chip versions
398 int status; // HW or SW state
399
400 /* spdif frame counter */
401 int spdif_counter;
402
403#ifdef TARGET_OS2
404 int audio_open_count[2]; // [0]: read, [1]: write
405 void *curr_streamid[2]; // [0]: read, [1]: write
406#endif
407};
408
409/* flags used for capability */
410#define CAN_AC3_HW 0x00000001 // 037 or later
411#define CAN_AC3_SW 0x00000002 // 033 or later
412#define CAN_AC3 (CAN_AC3_HW | CAN_AC3_SW)
413#define CAN_DUAL_DAC 0x00000004 // 033 or later
414#define CAN_MULTI_CH_HW 0x00000008 // 039 or later
415#define CAN_MULTI_CH (CAN_MULTI_CH_HW | CAN_DUAL_DAC)
416#define CAN_LINE_AS_REAR 0x00000010 // 033 or later
417#define CAN_LINE_AS_BASS 0x00000020 // 039 or later
418#define CAN_MIC_AS_BASS 0x00000040 // 039 or later
419
420/* flags used for status */
421#define DO_AC3_HW 0x00000001
422#define DO_AC3_SW 0x00000002
423#define DO_AC3 (DO_AC3_HW | DO_AC3_SW)
424#define DO_DUAL_DAC 0x00000004
425#define DO_MULTI_CH_HW 0x00000008
426#define DO_MULTI_CH (DO_MULTI_CH_HW | DO_DUAL_DAC)
427#define DO_LINE_AS_REAR 0x00000010 // 033 or later
428#define DO_LINE_AS_BASS 0x00000020 // 039 or later
429#define DO_MIC_AS_BASS 0x00000040 // 039 or later
430#define DO_SPDIF_OUT 0x00000100
431#define DO_SPDIF_IN 0x00000200
432#define DO_SPDIF_LOOP 0x00000400
433
434/* Rudi's additional status info */
435#define DO_SPDIF_MONITOR 0x00010000
436#define DO_SPDIF_COPYRIGHT 0x00020000
437#define DO_SPDIF_OUT_5V 0x00040000
438#define DO_SPDIF_INPUT2 0x00080000
439#define DO_SPDIF_INVERSE 0x00100000
440#define DO_SPDIF_OUT_ENABLE 0x00200000
441#define DO_POWER_DOWN 0x00400000
442#define DO_MIC_BOOST 0x00800000
443
444
445/* --------------------------------------------------------------------- */
446
447static struct cm_state *devs = NULL;
448static struct cm_state *devaudio = NULL;
449
450#if CONFIG_WAVETABLE
451static unsigned long wavetable_mem = 0;
452#endif
453
454__static__ int prog_dmabuf(struct cm_state *s, unsigned rec);
455__static__ void update_mixer(struct cm_state *s);
456
457
458/* --------------------------------------------------------------------- */
459
460#ifndef TARGET_OS2
461 extern __inline__ unsigned ld2(unsigned int x)
462 {
463 unsigned r = 0;
464 if (x >= 0x10000) {
465 x >>= 16;
466 r += 16;
467 }
468 if (x >= 0x100) {
469 x >>= 8;
470 r += 8;
471 }
472 if (x >= 0x10) {
473 x >>= 4;
474 r += 4;
475 }
476 if (x >= 4) {
477 x >>= 2;
478 r += 2;
479 }
480 if (x >= 2)
481 r++;
482 return r;
483 }
484
485
486 /*
487 * hweightN: returns the hamming weight (i.e. the number
488 * of bits set) of a N-bit word
489 */
490
491 #ifdef hweight32
492 #undef hweight32
493 #endif
494
495 extern __inline__ unsigned int hweight32(unsigned int w)
496 {
497 unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
498 res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
499 res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
500 res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
501 return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
502 }
503
504 /* --------------------------------------------------------------------- */
505
506 /*
507 * Why use byte IO? Nobody knows, but S3 does it also in their Windows driver.
508 */
509
510 #undef DMABYTEIO
511
512 extern __inline__ void maskb(unsigned int addr, unsigned int mask, unsigned int value)
513 {
514 outb((inb(addr) & mask) | value, addr);
515 }
516
517 extern __inline__ void maskw(unsigned int addr, unsigned int mask, unsigned int value)
518 {
519 outw((inw(addr) & mask) | value, addr);
520 }
521
522 extern __inline__ void maskl(unsigned int addr, unsigned int mask, unsigned int value)
523 {
524 outl((inl(addr) & mask) | value, addr);
525 }
526
527#else
528 unsigned ld2(unsigned x);
529 #pragma aux ld2 = \
530 "xor ecx, ecx" \
531 "bsr ecx, eax" \
532 parm nomemory [eax] \
533 modify exact nomemory [ecx] \
534 value [ecx];
535
536 void maskb(unsigned short addr, unsigned mask, unsigned value);
537 #pragma aux maskb = \
538 "in al, dx" \
539 "and al, cl" \
540 "or al, ch" \
541 "out dx, al" \
542 parm nomemory [dx] [cl] [ch] \
543 modify exact nomemory [al];
544
545 void maskw(unsigned short addr, unsigned mask, unsigned value);
546 #pragma aux maskw = \
547 "in ax, dx" \
548 "and eax, ecx" \
549 "or eax, ebx" \
550 "out dx, ax" \
551 parm nomemory [edx] [ecx] [ebx] \
552 modify exact nomemory [eax];
553
554 void maskl(unsigned short addr, unsigned long mask, unsigned long value);
555 #pragma aux maskl = \
556 "in eax, dx" \
557 "and eax, ecx" \
558 "or eax, ebx" \
559 "out dx, eax" \
560 parm nomemory [edx] [ecx] [ebx] \
561 modify exact nomemory [eax];
562
563 unsigned char parity(unsigned value, unsigned mask);
564 #pragma aux parity = \
565 "test eax, ecx" \
566 "setpo cl" \
567 parm nomemory [eax] [ecx] \
568 modify exact nomemory [ecx] \
569 value [cl];
570
571 void set_device_state(struct cm_state *s);
572
573#endif
574
575
576extern __inline__ void set_dmadac1(struct cm_state *s, unsigned int addr, unsigned int count)
577{
578 if (addr) outl(addr, s->iobase + CODEC_CMI_CH1_FRAME1);
579 outw(count - 1, s->iobase + CODEC_CMI_CH1_FRAME2);
580 maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~2, 0); // CH1 = play
581}
582
583extern __inline__ void set_dmaadc(struct cm_state *s, unsigned int addr, unsigned int count)
584{
585 outl(addr, s->iobase + CODEC_CMI_CH1_FRAME1);
586 outw(count - 1, s->iobase + CODEC_CMI_CH1_FRAME2);
587 maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~0, 2); // CH1 = rec
588}
589
590extern __inline__ void set_dmadac(struct cm_state *s, unsigned int addr, unsigned int count)
591{
592 outl(addr, s->iobase + CODEC_CMI_CH0_FRAME1);
593 outw(count - 1, s->iobase + CODEC_CMI_CH0_FRAME2);
594 maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~1, 0); // CH0 = play
595 if (s->status & DO_DUAL_DAC) set_dmadac1(s, 0, count);
596}
597
598extern __inline__ void set_countadc(struct cm_state *s, unsigned count)
599{
600 outw(count - 1, s->iobase + CODEC_CMI_CH1_FRAME2 + 2);
601}
602
603extern __inline__ void set_countdac(struct cm_state *s, unsigned count)
604{
605 outw(count - 1, s->iobase + CODEC_CMI_CH0_FRAME2 + 2);
606 if (s->status & DO_DUAL_DAC) set_countadc(s, count);
607}
608
609extern __inline__ unsigned get_dmadac(struct cm_state *s)
610{
611 unsigned int curr_addr, last_addr;
612
613 curr_addr = inw(s->iobase + CODEC_CMI_CH0_FRAME2);
614 last_addr = ~curr_addr;
615 while( curr_addr != last_addr ) {
616 iodelay32(1);
617 last_addr = curr_addr;
618 curr_addr = inw(s->iobase + CODEC_CMI_CH0_FRAME2);
619 }
620
621 curr_addr = (curr_addr + 1) <<
622 sample_shift[(s->fmt >> CM_CFMT_SHIFT_CH0) & CM_CFMT_MASK];
623 return s->dma_dac.dmasize - curr_addr;
624}
625
626extern __inline__ unsigned get_dmaadc(struct cm_state *s)
627{
628 unsigned int curr_addr, last_addr;
629
630 curr_addr = inw(s->iobase + CODEC_CMI_CH1_FRAME2);
631 last_addr = ~curr_addr;
632 while( curr_addr != last_addr ) {
633 iodelay32(1);
634 last_addr = curr_addr;
635 curr_addr = inw(s->iobase + CODEC_CMI_CH1_FRAME2);
636 }
637
638 curr_addr = (curr_addr + 1) <<
639 sample_shift[(s->fmt >> CM_CFMT_SHIFT_CH1) & CM_CFMT_MASK];
640 return s->dma_adc.dmasize - curr_addr;
641}
642
643extern __inline__ void wrmixer(struct cm_state *s, unsigned char idx, unsigned char data)
644{
645 outb(idx, s->iobase + CODEC_SB16_ADDR);
646 outb(data, s->iobase + CODEC_SB16_DATA);
647}
648
649extern __inline__ unsigned char rdmixer(struct cm_state *s, unsigned char idx)
650{
651 outb(idx, s->iobase + CODEC_SB16_ADDR);
652 return inb(s->iobase + CODEC_SB16_DATA);
653}
654
655extern __inline__ void enable_aux(struct cm_state *s, int enable, int record)
656{
657 unsigned char v = ( record ) ? 0xc0 : 0x30;
658 maskb(s->iobase + CODEC_CMI_MIXER2, ~v, ( enable ) ? v : 0);
659}
660
661extern __inline__ void enable_digital(struct cm_state *s, int enable, int record)
662{
663 unsigned char v = ( record ) ? 0x0c : 0x01;
664 maskb(s->iobase + CODEC_CMI_MIXER1, ~v, ( enable ) ? v : 0);
665
666 if (record) {
667 // SPDF_1
668 maskb(s->iobase + CODEC_CMI_FUNCTRL1+1, ~0x02, ( enable ) ? 0x02 : 0);
669
670// // select input pin
671// maskb(s->iobase + CODEC_CMI_MISC_CTRL+1, ~1, (record >> 1) & 1);
672 }
673}
674
675extern __inline__ void set_fmt(struct cm_state *s,
676 unsigned char mask, unsigned char data)
677{
678 unsigned long flags;
679
680 spin_lock_irqsave(&s->lock, flags);
681 if (mask)
682 s->fmt = inb(s->iobase + CODEC_CMI_CHFORMAT);
683 s->fmt = (s->fmt & mask) | data;
684 outb(s->fmt, s->iobase + CODEC_CMI_CHFORMAT);
685 spin_unlock_irqrestore(&s->lock, flags);
686}
687
688extern __inline__ void frobindir(struct cm_state *s, unsigned char idx,
689 unsigned char mask, unsigned char data)
690{
691 outb(idx, s->iobase + CODEC_SB16_ADDR);
692 maskb(s->iobase + CODEC_SB16_DATA, mask, data);
693}
694
695
696
697__static__ unsigned char match_rate(unsigned *rate)
698{
699 static struct {
700 unsigned rate;
701 unsigned lower;
702 unsigned upper;
703 unsigned char freq;
704 } rate_lookup[] =
705 {
706 { 5512, (0 + 5512) / 2, (5512 + 8000) / 2, 0 },
707 { 8000, (5512 + 8000) / 2, (8000 + 11025) / 2, 4 },
708 { 11025, (8000 + 11025) / 2, (11025 + 16000) / 2, 1 },
709 { 16000, (11025 + 16000) / 2, (16000 + 22050) / 2, 5 },
710 { 22050, (16000 + 22050) / 2, (22050 + 32000) / 2, 2 },
711 { 32000, (22050 + 32000) / 2, (32000 + 44100) / 2, 6 },
712 { 44100, (32000 + 44100) / 2, (44100 + 48000) / 2, 3 },
713 { 48000, (44100 + 48000) / 2, 48000, 7 }
714 };
715
716 int i;
717 unsigned r = *rate;
718
719 if( r > 48000 ) r = 48000;
720 else if( r < 8000 ) r = 8000;
721
722 for (i = 0; i < sizeof(rate_lookup) / sizeof(rate_lookup[0]); i++) {
723 if (r > rate_lookup[i].lower && r <= rate_lookup[i].upper) {
724 *rate = rate_lookup[i].rate;
725 return rate_lookup[i].freq;
726 }
727 }
728
729 return 0; // impossible to get here ...
730}
731
732
733__static__ void set_spdifout(struct cm_state *s, unsigned rate)
734{
735 unsigned long flags;
736
737 spin_lock_irqsave(&s->lock, flags);
738 if (rate >= 44100 && (s->status & DO_SPDIF_OUT_ENABLE)) {
739 // SPDIFI48K SPDF_ACc97
740 maskl(s->iobase + CODEC_CMI_MISC_CTRL,
741 ~0x01008000, rate == 48000 ? 0x01008000 : 0);
742#if 1
743 // ENSPDOUT
744 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 2, ~0, 0x80);
745 // SPDF_0 SPDO2DAC
746 maskw(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x0140);
747
748 // CDPLAY (SPDIF-in monitor)
749 if (s->chip_version >= 39) {
750 maskb(s->iobase + CODEC_CMI_MIXER1, ~0, 0x01);
751 }
752
753 s->status |= DO_SPDIF_OUT;
754
755 } else {
756 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 2, ~0x80, 0);
757 maskw(s->iobase + CODEC_CMI_FUNCTRL1, ~0x0140, 0);
758
759 if (s->chip_version >= 39 && !(s->status & DO_SPDIF_MONITOR)) {
760 maskb(s->iobase + CODEC_CMI_MIXER1, ~0x01, 0);
761 }
762
763 s->status &= ~DO_SPDIF_OUT;
764 }
765#else
766 if ( s->chip_version >= 39) {
767 // ENSPDOUT DAC2SPDO
768 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 2, ~0, 0xa0);
769 } else {
770 // ENSPDOUT
771 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 2, ~0, 0x80);
772 // SPDF_1 SPDO2DAC
773 // maskw(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x0240);
774 // SPDF_0 SPDO2DAC
775 maskw(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x0140);
776 }
777
778 s->status |= DO_SPDIF_OUT;
779
780 } else {
781 if (s->chip_version >= 39) {
782 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 2, ~0xa0, 0);
783 } else {
784 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 2, ~0x80, 0);
785// maskw(s->iobase + CODEC_CMI_FUNCTRL1, ~0x0240, 0);
786 maskw(s->iobase + CODEC_CMI_FUNCTRL1, ~0x0140, 0);
787 }
788
789 s->status &= ~DO_SPDIF_OUT;
790 }
791#endif
792 spin_unlock_irqrestore(&s->lock, flags);
793}
794
795
796#ifndef TARGET_OS2
797 #if 0
798 /* find parity for bit 4~30 */
799 __static__ unsigned _parity(unsigned data)
800 {
801 unsigned parity = 0;
802 int counter = 4;
803
804 data >>= 4; // start from bit 4
805 while (counter <= 30) {
806 if (data & 1)
807 parity++;
808 data >>= 1;
809 counter++;
810 }
811 return parity & 1;
812 }
813
814 #define parity(val, mask) _parity(val)
815 #else
816 #define parity(val, mask) (hweight32((val) & (mask)) & 1)
817 #endif
818#endif
819
820
821__static__ void set_ac3(struct cm_state *s, unsigned rate)
822{
823 unsigned long flags;
824
825 spin_lock_irqsave(&s->lock, flags);
826//Rudi: set_ac3 should NOT include spdif_out
827// set_spdifout(s, rate);
828
829 /* enable AC3 */
830 if (rate >= 44100 && (s->status & DO_SPDIF_OUT)) {
831
832 // mute DAC
833 maskb(s->iobase + CODEC_CMI_MIXER1, ~0, 0x40);
834 // AC3EN for 037, 0x10
835 maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0, 0x10);
836 // AC3EN for 039, 0x04
837 maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, 0x04);
838
839 if (s->capability & CAN_AC3_HW) {
840 // SPD24SEL for 037, 0x02
841 // SPD24SEL for 039, 0x20, but cannot be set
842 maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0, 0x02);
843 s->status |= DO_AC3_HW;
844
845/*Rudi: don't touch CDPLAY here */
846// if (s->chip_version >= 39)
847// maskb(s->iobase + CODEC_CMI_MIXER1, ~1, 0);
848 } else {
849 // SPD32SEL for 037 & 039, 0x20
850 maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, 0x20);
851 // set 176K sample rate to fix 033 HW bug
852 if (s->chip_version == 33) {
853 maskb(s->iobase + CODEC_CMI_CHFORMAT + 1,
854 ~0x08, ( rate == 48000 ) ? 0x08 : 0);
855/*
856 if (rate == 48000)
857 maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0, 0x08);
858 else
859 maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0x08, 0);
860*/
861 }
862
863 s->status |= DO_AC3_SW;
864 }
865 } else {
866 maskb(s->iobase + CODEC_CMI_MIXER1, ~0x40, 0);
867// Bug ? maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0x32, 0);
868 maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0x12, 0);
869 maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0x24, 0);
870 maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0x08, 0);
871
872// Rudi: if (s->chip_version == 33)
873// Why twice ? maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0x08, 0);
874
875/*Rudi: don't touch CDPLAY here */
876// if (s->chip_version >= 39)
877// maskb(s->iobase + CODEC_CMI_MIXER1, ~0, 1);
878
879 s->status &= ~DO_AC3;
880 }
881 s->spdif_counter = 0;
882 spin_unlock_irqrestore(&s->lock, flags);
883}
884
885
886/*
887 * compose 32bit iec958 subframe with non-audio data.
888 * bit 0-3 = preamble
889 * 4-7 = aux (=0)
890 * 8-27 = data (12-27 for 16bit)
891 * 28 = validity (=0)
892 * 29 = user data (=0)
893 * 30 = channel status
894 * 31 = parity
895 *
896 * channel status is assumed as consumer, non-audio
897 * thus all 0 except bit 1
898 */
899
900
901__static__ void trans_ac3(struct cm_state *s, void *dest, const char *source, int size)
902{
903 int i = size / 2;
904 unsigned long data;
905 unsigned long *dst = (unsigned long *) dest;
906 unsigned short *src = (unsigned short *)source;
907
908 while (i--) {
909 data = (unsigned long) *src++;
910 data <<= 12; // ok for 16-bit data
911
912 if (s->spdif_counter == 2 || s->spdif_counter == 3)
913 data |= 0x40000000; // indicate AC-3 raw data
914
915 if (parity(data, 0x7ffffff0))
916 data |= 0x80000000; // parity
917
918 if (s->spdif_counter == 0)
919 data |= 3; // preamble 'B'
920 else if (s->spdif_counter & 1)
921 data |= 5; // odd, 'W'
922 else
923 data |= 9; // even, 'M'
924 *dst++ = data;
925
926 if (++s->spdif_counter == 384) s->spdif_counter = 0;
927 }
928}
929
930__static__ void set_adc_rate(struct cm_state *s, unsigned rate)
931{
932 unsigned long flags;
933 unsigned char freq;
934
935 freq = match_rate(&rate);
936 s->rateadc = rate;
937
938 spin_lock_irqsave(&s->lock, flags);
939 maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~0xe0, freq << 5);
940 spin_unlock_irqrestore(&s->lock, flags);
941}
942
943__static__ void set_dac_rate(struct cm_state *s, unsigned rate)
944{
945 unsigned long flags;
946 unsigned char freq;
947
948 freq = match_rate(&rate);
949 s->ratedac = rate;
950
951 spin_lock_irqsave(&s->lock, flags);
952 maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~0x1c, freq << 2);
953 spin_unlock_irqrestore(&s->lock, flags);
954
955 if (s->curr_channels <= 2) set_spdifout(s, rate);
956 if (s->status & DO_DUAL_DAC) set_dac1_rate(s, rate);
957}
958
959/* --------------------------------------------------------------------- */
960
961extern __inline__ void pause_adc(struct cm_state *s)
962{
963 maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~0, CM_PAUSE_CH1);
964}
965
966extern __inline__ void pause_dac(struct cm_state *s)
967{
968 maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~0, CM_PAUSE_CH0);
969 if (s->status & DO_DUAL_DAC) pause_adc(s);
970}
971
972extern __inline__ void disable_adc(struct cm_state *s)
973{
974 /* disable channel */
975 s->enable &= ~CM_ENABLE_CH1;
976// outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
977
978 /* reset bus master */
979 outb(s->enable | CM_RESET_CH1, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
980 outb(s->enable & ~CM_RESET_CH1, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
981}
982
983extern __inline__ void disable_dac(struct cm_state *s)
984{
985 /* disable channel */
986 s->enable &= ~CM_ENABLE_CH0;
987// outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
988
989 /* reset bus master */
990 outb(s->enable | CM_RESET_CH0, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
991 outb(s->enable & ~CM_RESET_CH0, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
992
993 if (s->status & DO_DUAL_DAC) disable_adc(s);
994}
995
996extern __inline__ void enable_adc(struct cm_state *s)
997{
998 if (!(s->enable & CM_ENABLE_CH1)) {
999 /* enable channel */
1000 s->enable |= CM_ENABLE_CH1;
1001 outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
1002 }
1003 maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~CM_PAUSE_CH1, 0);
1004}
1005
1006extern __inline__ void enable_dac(struct cm_state *s)
1007{
1008 if (!(s->enable & CM_ENABLE_CH0)) {
1009 /* enable channel */
1010 s->enable |= CM_ENABLE_CH0;
1011 outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
1012 }
1013 maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~CM_PAUSE_CH0, 0);
1014
1015 if (s->status & DO_DUAL_DAC) enable_adc(s);
1016}
1017
1018extern __inline__ void stop_adc(struct cm_state *s)
1019{
1020 unsigned long flags;
1021
1022 spin_lock_irqsave(&s->lock, flags);
1023 if (s->enable & CM_ENABLE_CH1) {
1024 /* disable interrupt */
1025 maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~CM_INT_CH1, 0);
1026 disable_adc(s);
1027 }
1028 spin_unlock_irqrestore(&s->lock, flags);
1029}
1030
1031extern __inline__ void stop_dac(struct cm_state *s)
1032{
1033 unsigned long flags;
1034
1035 spin_lock_irqsave(&s->lock, flags);
1036 if (s->enable & CM_ENABLE_CH0) {
1037 /* disable interrupt */
1038 maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~CM_INT_CH0, 0);
1039 disable_dac(s);
1040 }
1041 spin_unlock_irqrestore(&s->lock, flags);
1042
1043// Rudi: disable_dac() already does this !
1044// if (s->status & DO_DUAL_DAC) stop_dac1(s);
1045}
1046
1047extern __inline__ void start_adc(struct cm_state *s)
1048{
1049 unsigned long flags;
1050
1051 spin_lock_irqsave(&s->lock, flags);
1052 if( !(s->enable & CM_ENABLE_CH1) ) {
1053 if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize))
1054 && s->dma_adc.ready) {
1055 /* enable interrupt */
1056 maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~0, CM_INT_CH1);
1057 enable_adc(s);
1058 }
1059 }
1060 spin_unlock_irqrestore(&s->lock, flags);
1061}
1062
1063extern __inline__ void start_dac(struct cm_state *s)
1064{
1065 unsigned long flags;
1066
1067 spin_lock_irqsave(&s->lock, flags);
1068 if( !(s->enable & CM_ENABLE_CH0) ) {
1069 if ((s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) {
1070 /* enable interrupt */
1071 maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~0, CM_INT_CH0);
1072 enable_dac(s);
1073 }
1074 }
1075 spin_unlock_irqrestore(&s->lock, flags);
1076
1077// Rudi: enable_dac() already does this !
1078// if (s->status & DO_DUAL_DAC) start_dac1(s);
1079}
1080
1081
1082
1083__static__ int set_dac_channels(struct cm_state *s, int channels)
1084{
1085 unsigned long flags;
1086 ssize_t ret;
1087
1088 spin_lock_irqsave(&s->lock, flags);
1089 if ((channels > 2) && (channels <= s->max_channels)) {
1090// Rudi: && (((s->fmt >> CM_CFMT_SHIFT_CH0) & CM_CFMT_MASK) == (CM_CFMT_STEREO | CM_CFMT_16BIT))) {
1091 set_spdifout(s, 0);
1092 if (s->capability & CAN_MULTI_CH_HW) {
1093 // NXCHG
1094 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0, 0x80);
1095
1096 // CHB3D or CHB3D5C
1097 maskb(s->iobase + CODEC_CMI_CHFORMAT + 3, ~0xa0, channels > 4 ? 0x80 : 0x20);
1098 // CHB3D6C
1099 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 1, ~0x80, channels == 6 ? 0x80 : 0);
1100 // ENCENTER
1101 maskb(s->iobase + CODEC_CMI_MISC_CTRL, ~0x80, channels == 6 ? 0x80 : 0);
1102
1103 s->status |= DO_MULTI_CH_HW;
1104 } else if (s->capability & CAN_DUAL_DAC) {
1105 // Rudi: turn off SPDF_0 and SPDF_1
1106 maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~0x03, 0);
1107
1108 // ENDBDAC, turn on double DAC mode
1109 // XCHGDAC, CH0 -> back, CH1->front
1110 maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, 0xC0);
1111// Rudi: XCHGDAC seems to be neccessary ...
1112
1113 s->status |= DO_DUAL_DAC;
1114
1115 // prepare secondary buffer
1116 if (ret = prog_dmabuf(s, 1)) {
1117 maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0xC0, 0);
1118 s->status &= ~DO_DUAL_DAC;
1119 spin_unlock_irqrestore(&s->lock, flags);
1120 return ret;
1121 }
1122
1123 // the HW only support 16-bit stereo
1124 set_fmt(s, ~0,
1125 ((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_SHIFT_CH0) |
1126 ((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_SHIFT_CH1));
1127
1128 set_dac1_rate(s, s->ratedac);
1129 }
1130
1131 s->curr_channels = channels;
1132
1133 if (s->speakers > 2) {
1134 // N4SPK3D, disable 4 speaker mode (analog duplicate)
1135 maskb(s->iobase + CODEC_CMI_MISC_CTRL + 3, ~0x04, 0);
1136 update_mixer(s);
1137 }
1138
1139 } else {
1140 if (s->status & DO_MULTI_CH_HW) {
1141 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0x80, 0);
1142 maskb(s->iobase + CODEC_CMI_CHFORMAT + 3, ~0xa0, 0);
1143 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 1, ~0x80, 0);
1144 } else if (s->status & DO_DUAL_DAC) {
1145 maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0xC0, 0);
1146 }
1147
1148 s->status &= ~(DO_MULTI_CH | DO_DUAL_DAC);
1149 s->curr_channels = s->fmt & (CM_CFMT_STEREO << CM_CFMT_SHIFT_CH0) ? 2 : 1;
1150
1151 if (s->speakers > 2) {
1152 // N4SPK3D, enable 4 speaker mode (analog duplicate)
1153 maskb(s->iobase + CODEC_CMI_MISC_CTRL + 3, ~0, 0x04);
1154 update_mixer(s);
1155 }
1156
1157 }
1158 spin_unlock_irqrestore(&s->lock, flags);
1159 return s->curr_channels;
1160}
1161
1162/* --------------------------------------------------------------------- */
1163
1164#ifndef TARGET_OS2
1165 #define DMABUF_DEFAULTORDER (16-PAGE_SHIFT)
1166#else
1167 #define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
1168#endif
1169
1170#define DMABUF_MINORDER 1
1171
1172__static__ void dealloc_dmabuf(struct dmabuf *db)
1173{
1174#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1175 struct page *pstart, *pend;
1176#else
1177 unsigned long map, mapend;
1178#endif
1179
1180 if (db->rawbuf) {
1181#ifndef TARGET_OS2
1182 /* undo marking the pages as reserved */
1183 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1184 pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
1185 for (pstart = virt_to_page(db->rawbuf); pstart <= pend; pstart++)
1186 mem_map_unreserve(pstart);
1187 #else
1188 mapend = MAP_NR((char *)db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
1189 for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
1190 clear_bit(PG_reserved, &mem_map[map].flags);
1191 #endif
1192#endif
1193
1194 free_pages((unsigned long)db->rawbuf, db->buforder);
1195 }
1196 db->rawbuf = NULL;
1197 db->mapped = db->ready = 0;
1198}
1199
1200
1201/* Ch0 is used for playback, Ch1 is used for recording */
1202
1203__static__ int prog_dmabuf(struct cm_state *s, unsigned rec)
1204{
1205 struct dmabuf *db = rec ? &s->dma_adc : &s->dma_dac;
1206 unsigned rate = rec ? s->rateadc : s->ratedac;
1207 int order;
1208 unsigned bytepersec;
1209 unsigned bufs;
1210#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1211 struct page *pstart, *pend;
1212#else
1213 unsigned long map, mapend;
1214#endif
1215 unsigned char fmt;
1216 unsigned long flags;
1217
1218 spin_lock_irqsave(&s->lock, flags);
1219 fmt = s->fmt;
1220 if (rec) {
1221 stop_adc(s);
1222 fmt >>= CM_CFMT_SHIFT_CH1;
1223 } else {
1224 stop_dac(s);
1225 fmt >>= CM_CFMT_SHIFT_CH0;
1226 }
1227 spin_unlock_irqrestore(&s->lock, flags);
1228 fmt &= CM_CFMT_MASK;
1229 db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;
1230 if (!db->rawbuf) {
1231 db->ready = db->mapped = 0;
1232#ifndef TARGET_OS2
1233 for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
1234 if ((db->rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order)))
1235 break;
1236#else
1237 order = DMABUF_DEFAULTORDER;
1238 db->rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order);
1239#endif
1240 if (!db->rawbuf)
1241 return -ENOMEM;
1242 db->buforder = order;
1243 db->rawphys = virt_to_bus(db->rawbuf);
1244
1245#ifndef TARGET_OS2
1246 if ((db->rawphys ^ (db->rawphys + (PAGE_SIZE << db->buforder) - 1)) & ~0xffff)
1247 printk(KERN_DEBUG "cm: DMA buffer crosses 64k boundary: busaddr 0x%lx size %ld\n",
1248 (long) db->rawphys, PAGE_SIZE << db->buforder);
1249 if ((db->rawphys + (PAGE_SIZE << db->buforder) - 1) & ~0xffffff)
1250 printk(KERN_DEBUG "cm: DMA buffer beyond 16MB: busaddr 0x%lx size %ld\n",
1251 (long) db->rawphys, PAGE_SIZE << db->buforder);
1252
1253 /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
1254 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1255 pend = virt_to_page((char *)db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
1256 for (pstart = virt_to_page(db->rawbuf); pstart <= pend; pstart++)
1257 mem_map_reserve(pstart);
1258 #else
1259 mapend = MAP_NR((char *)db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
1260 for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
1261 set_bit(PG_reserved, &mem_map[map].flags);
1262 #endif
1263#endif
1264
1265 }
1266 bytepersec = rate << sample_shift[fmt];
1267 bufs = PAGE_SIZE << db->buforder;
1268 if (db->ossfragshift) {
1269 if ((1000 << db->ossfragshift) < bytepersec)
1270 db->fragshift = ld2(bytepersec/1000);
1271 else
1272 db->fragshift = db->ossfragshift;
1273 } else {
1274 db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1));
1275 if (db->fragshift < 3)
1276 db->fragshift = 3;
1277 }
1278 db->numfrag = bufs >> db->fragshift;
1279 while (db->numfrag < 4 && db->fragshift > 3) {
1280 db->fragshift--;
1281 db->numfrag = bufs >> db->fragshift;
1282 }
1283 db->fragsize = 1 << db->fragshift;
1284 if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag)
1285 db->numfrag = db->ossmaxfrags;
1286 /* to make fragsize >= 4096 */
1287 if (s->modem) {
1288 while (db->fragsize < 4096 && db->numfrag >= 4) {
1289 db->fragsize *= 2;
1290 db->fragshift++;
1291 db->numfrag /= 2;
1292 }
1293 }
1294
1295 db->fragsamples = db->fragsize >> sample_shift[fmt];
1296 db->dmasize = db->numfrag << db->fragshift;
1297 db->dmasamples = db->dmasize >> sample_shift[fmt];
1298 memset(db->rawbuf, (fmt & CM_CFMT_16BIT) ? 0 : 0x80, db->dmasize);
1299
1300 spin_lock_irqsave(&s->lock, flags);
1301 if (rec) {
1302 if (s->status & DO_DUAL_DAC)
1303 set_dmadac1(s, db->rawphys, db->dmasamples);
1304 else
1305 set_dmaadc(s, db->rawphys, db->dmasamples);
1306 /* program sample counts */
1307// Rudi: Bug set_countdac(s, db->fragsamples);
1308 set_countadc(s, db->fragsamples);
1309
1310 } else {
1311 set_dmadac(s, db->rawphys, db->dmasamples);
1312 /* program sample counts */
1313 set_countdac(s, db->fragsamples);
1314 }
1315 spin_unlock_irqrestore(&s->lock, flags);
1316 db->ready = 1;
1317
1318dprintf(("prog_dmabuf(%d): dmasize: %d, fragsize: %d, numfrag: %d",
1319 rec, db->dmasize, db->fragsize, db->numfrag));
1320
1321 return 0;
1322}
1323
1324extern __inline__ void clear_advance(struct cm_state *s)
1325{
1326 unsigned char c = (s->fmt & (CM_CFMT_16BIT << CM_CFMT_SHIFT_CH0)) ? 0 : 0x80;
1327 unsigned char *buf = s->dma_dac.rawbuf;
1328 unsigned char *buf1 = s->dma_adc.rawbuf;
1329 unsigned bsize = s->dma_dac.dmasize;
1330 unsigned bptr = s->dma_dac.swptr;
1331 unsigned len = s->dma_dac.fragsize;
1332
1333 if (bptr + len > bsize) {
1334 unsigned x = bsize - bptr;
1335 memset(buf + bptr, c, x);
1336 if (s->status & DO_DUAL_DAC)
1337 memset(buf1 + bptr, c, x);
1338 bptr = 0;
1339 len -= x;
1340 }
1341 memset(buf + bptr, c, len);
1342 if (s->status & DO_DUAL_DAC)
1343 memset(buf1 + bptr, c, len);
1344}
1345
1346/* call with spinlock held! */
1347__static__ void cm_update_ptr(struct cm_state *s)
1348{
1349 unsigned hwptr;
1350 int diff;
1351
1352 /* update ADC pointer */
1353 if ((s->dma_adc.ready) && !(s->status & DO_DUAL_DAC)) {
1354 hwptr = get_dmaadc(s);
1355 diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize;
1356 s->dma_adc.hwptr = hwptr;
1357 s->dma_adc.total_bytes += diff;
1358 s->dma_adc.count += diff;
1359 if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
1360 wake_up(&s->dma_adc.wait);
1361 if (!s->dma_adc.mapped) {
1362 if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {
1363//dprintf(("dma_adc.count: %d, dmasz: %d, fragsz: %d", s->dma_adc.count, s->dma_adc.dmasize, s->dma_adc.fragsize));
1364#ifndef TARGET_OS2
1365 pause_adc(s);
1366#endif
1367 s->dma_adc.error++;
1368 }
1369 }
1370 }
1371
1372
1373 /* update DAC pointer */
1374 if (s->dma_dac.ready) {
1375 hwptr = get_dmadac(s);
1376 diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize;
1377 s->dma_dac.hwptr = hwptr;
1378 s->dma_dac.total_bytes += diff;
1379 if (s->dma_dac.mapped) {
1380 s->dma_dac.count += diff;
1381 if (s->dma_dac.count >= (signed)s->dma_dac.fragsize)
1382 wake_up(&s->dma_dac.wait);
1383 } else {
1384 s->dma_dac.count -= diff;
1385 if (s->dma_dac.count <= 0) {
1386#ifndef TARGET_OS2
1387 pause_dac(s);
1388#endif
1389 s->dma_dac.error++;
1390 } else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize && !s->dma_dac.endcleared) {
1391 clear_advance(s);
1392 s->dma_dac.endcleared = 1;
1393 }
1394 if (s->dma_dac.count + (signed)s->dma_dac.fragsize <= (signed)s->dma_dac.dmasize)
1395 wake_up(&s->dma_dac.wait);
1396 }
1397 }
1398}
1399
1400#ifdef CONFIG_SOUND_CMPCI_MIDI
1401/* hold spinlock for the following! */
1402__static__ void cm_handle_midi(struct cm_state *s)
1403{
1404 unsigned char ch;
1405 int wake;
1406
1407 wake = 0;
1408 while (!(inb(s->iomidi+1) & 0x80)) {
1409 ch = inb(s->iomidi);
1410 if (s->midi.icnt < MIDIINBUF) {
1411 s->midi.ibuf[s->midi.iwr] = ch;
1412 s->midi.iwr = (s->midi.iwr + 1) % MIDIINBUF;
1413 s->midi.icnt++;
1414 }
1415 wake = 1;
1416 }
1417 if (wake)
1418 wake_up(&s->midi.iwait);
1419 wake = 0;
1420 while (!(inb(s->iomidi+1) & 0x40) && s->midi.ocnt > 0) {
1421 outb(s->midi.obuf[s->midi.ord], s->iomidi);
1422 s->midi.ord = (s->midi.ord + 1) % MIDIOUTBUF;
1423 s->midi.ocnt--;
1424 if (s->midi.ocnt < MIDIOUTBUF-16)
1425 wake = 1;
1426 }
1427 if (wake)
1428 wake_up(&s->midi.owait);
1429}
1430#endif
1431
1432__static__ void cm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1433{
1434 struct cm_state *s = (struct cm_state *)dev_id;
1435 unsigned char intstat, mask;
1436 unsigned int intsrc;
1437
1438 /* fastpath out, to ease interrupt sharing */
1439 intsrc = inl(s->iobase + CODEC_CMI_INT_STATUS);
1440 if( !(intsrc & 0x80000000) ) return;
1441
1442#ifndef TARGET_OS2
1443 spin_lock(&s->lock);
1444 /* acknowledge interrupt */
1445 if (intsrc & CM_INT_CH0)
1446 mask |= 1;
1447 if (intsrc & CM_INT_CH1)
1448 mask |= 2;
1449 outb(intstat & ~mask, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
1450 outb(intstat | mask, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
1451 cm_update_ptr(s);
1452 #ifdef CONFIG_SOUND_CMPCI_MIDI
1453 cm_handle_midi(s);
1454 #endif
1455 spin_unlock(&s->lock);
1456#else
1457 // midi uart
1458 if( intsrc & 0x00010000 ) {
1459 OSS32_ProcessIRQ(OSS_STREAM_MIDIIN, (unsigned long)s);
1460 }
1461
1462 if( (mask = (unsigned char)intsrc & (CM_INT_CH0 | CM_INT_CH1)) != 0 ) {
1463 intstat = inb(s->iobase + CODEC_CMI_INT_HLDCLR + 2);
1464 outb(intstat & ~mask, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
1465 outb(intstat | mask, s->iobase + CODEC_CMI_INT_HLDCLR + 2);
1466 }
1467
1468 // playback
1469 if( (mask & CM_INT_CH0) && s->curr_streamid[1] )
1470 OSS32_ProcessIRQ(OSS_STREAM_WAVEOUT, (unsigned long)s->curr_streamid[1]);
1471
1472 // record
1473 if( (mask & CM_INT_CH1) && s->curr_streamid[0] )
1474 OSS32_ProcessIRQ(OSS_STREAM_WAVEIN, (unsigned long)s->curr_streamid[0]);
1475
1476 eoi_irq(irq);
1477#endif
1478}
1479
1480
1481#ifdef CONFIG_SOUND_CMPCI_MIDI
1482__static__ void cm_midi_timer(unsigned long data)
1483{
1484 struct cm_state *s = (struct cm_state *)data;
1485 unsigned long flags;
1486
1487 spin_lock_irqsave(&s->lock, flags);
1488 cm_handle_midi(s);
1489 spin_unlock_irqrestore(&s->lock, flags);
1490 s->midi.timer.expires = jiffies+1;
1491 add_timer(&s->midi.timer);
1492}
1493#endif
1494
1495/* --------------------------------------------------------------------- */
1496
1497#ifdef CONFIG_SOUND_CMPCI /* support multiple chips */
1498 #define VALIDATE_STATE(s)
1499#else
1500 static const char invalid_magic[] = KERN_CRIT "cm: invalid magic value\n";
1501
1502 #define VALIDATE_STATE(s) \
1503 ({ \
1504 if (!(s) || (s)->magic != CM_MAGIC) { \
1505 printk(invalid_magic); \
1506 return -ENXIO; \
1507 } \
1508 })
1509#endif
1510
1511/* --------------------------------------------------------------------- */
1512
1513#define MT_2 0x01
1514//#define MT_4 0x02
1515#define MT_4AUX 0x03
1516#define MT_5 0x04
1517//#define MT_6 0x05
1518#define MT_MONO 0x40
1519#define MT_MUTE 0x80
1520
1521#define MT_2MONO (MT_2 | MT_MONO)
1522//#define MT_4MUTEMONO (MT_4 | MT_MONO | MT_MUTE)
1523#define MT_5MUTEMONO (MT_5 | MT_MONO | MT_MUTE)
1524
1525
1526static const struct {
1527 unsigned char left; // SB mixer volume index (left channel)
1528 unsigned char right; // SB mixer volume index (right channel)
1529 unsigned char type; // MT_xxx
1530 unsigned char play; // SB register 3c
1531 unsigned short rec; // SB register 3d (left channel only)
1532 // register 3e is derived from 3d
1533} mixtable[SOUND_MIXER_NRDEVICES] = {
1534
1535#ifndef TARGET_OS2
1536 [SOUND_MIXER_CD] = { DSP_MIX_CDVOLIDX_L, DSP_MIX_CDVOLIDX_R, MT_5, 0x02, 0x0004 },
1537 [SOUND_MIXER_LINE] = { DSP_MIX_LINEVOLIDX_L, DSP_MIX_LINEVOLIDX_R, MT_5, 0x08, 0x0010 },
1538 [SOUND_MIXER_MIC] = { DSP_MIX_MICVOLIDX, 0, MT_5MUTEMONO, 0x01, 0x0001 },
1539 [SOUND_MIXER_SYNTH] = { DSP_MIX_FMVOLIDX_L, DSP_MIX_FMVOLIDX_R, MT_5, 0x00, 0x0040 },
1540 [SOUND_MIXER_VOLUME] = { DSP_MIX_MASTERVOLIDX_L, DSP_MIX_MASTERVOLIDX_R, MT_5, 0x00, 0x0000 },
1541 [SOUND_MIXER_PCM] = { DSP_MIX_VOICEVOLIDX_L, DSP_MIX_VOICEVOLIDX_R, MT_5, 0x00, 0x0000 },
1542 [SOUND_MIXER_IGAIN] = { DSP_MIX_INGAINIDX_L, DSP_MIX_INGAINIDX_R, MT_2, 0x00, 0x0000 },
1543 [SOUND_MIXER_OGAIN] = { DSP_MIX_OUTGAINIDX_L, DSP_MIX_OUTGAINIDX_R, MT_2, 0x00, 0x0000 },
1544 [SOUND_MIXER_SPEAKER] = { DSP_MIX_SPKRVOLIDX, 0, MT_2MONO, 0x40, 0x0000 },
1545 // Rudi: AUX and SPDIF/IN support
1546 [SOUND_MIXER_LINE1] = { 0, 0, MT_4AUX, 0x20, 0x0080 },
1547 [SOUND_MIXER_DIGITAL1] = { 0, 0, MT_MUTE, 0x00, 0x0100 }
1548
1549#else
1550
1551/*SOUND_MIXER_VOLUME*/ { DSP_MIX_MASTERVOLIDX_L, DSP_MIX_MASTERVOLIDX_R, MT_5, 0x00, 0x0000 },
1552/*SOUND_MIXER_BASS*/ { 0, 0, 0, 0, 0 },
1553/*SOUND_MIXER_TREBLE*/ { 0, 0, 0, 0, 0 },
1554/*SOUND_MIXER_SYNTH*/ { DSP_MIX_FMVOLIDX_L, DSP_MIX_FMVOLIDX_R, MT_5, 0x00, 0x0040 },
1555/*SOUND_MIXER_PCM*/ { DSP_MIX_VOICEVOLIDX_L, DSP_MIX_VOICEVOLIDX_R, MT_5, 0x00, 0x0000 },
1556/*SOUND_MIXER_SPEAKER*/ { DSP_MIX_SPKRVOLIDX, 0, MT_2MONO, 0x40, 0x0000 },
1557/*SOUND_MIXER_LINE*/ { DSP_MIX_LINEVOLIDX_L, DSP_MIX_LINEVOLIDX_R, MT_5, 0x18, 0x0010 },
1558/*SOUND_MIXER_MIC*/ { DSP_MIX_MICVOLIDX, 0, MT_5MUTEMONO, 0x01, 0x0001 },
1559/*SOUND_MIXER_CD*/ { DSP_MIX_CDVOLIDX_L, DSP_MIX_CDVOLIDX_R, MT_5, 0x06, 0x0004 },
1560/*SOUND_MIXER_IMIX*/ { 0, 0, 0, 0, 0 },
1561/*SOUND_MIXER_ALTPCM*/ { 0, 0, 0, 0, 0 },
1562/*SOUND_MIXER_RECLEV*/ { 0, 0, 0, 0, 0 },
1563/*SOUND_MIXER_IGAIN*/ { DSP_MIX_INGAINIDX_L, DSP_MIX_INGAINIDX_R, MT_2, 0x00, 0x0000 },
1564/*SOUND_MIXER_OGAIN*/ { DSP_MIX_OUTGAINIDX_L, DSP_MIX_OUTGAINIDX_R, MT_2, 0x00, 0x0000 },
1565/*SOUND_MIXER_LINE1*/ { 0, 0, MT_4AUX, 0x20, 0x0080 },
1566/*SOUND_MIXER_LINE2*/ { 0, 0, 0, 0, 0 },
1567/*SOUND_MIXER_LINE3*/ { 0, 0, 0, 0, 0 },
1568/*SOUND_MIXER_DIGITAL1*/{ 0, 0, MT_MUTE, 0x00, 0x0100 }
1569
1570#endif
1571};
1572
1573#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
1574
1575__static__ int return_mixval(struct cm_state *s, unsigned i, int *arg)
1576{
1577 unsigned long flags;
1578 unsigned char l, r, rl, rr;
1579
1580 spin_lock_irqsave(&s->lock, flags);
1581 if( mixtable[i].type == MT_4AUX )
1582 {
1583 l = inb(s->iobase + CODEC_CMI_AUX_VOL);
1584 r = l >> 4;
1585 l &= 0xf;
1586 }
1587 else
1588 {
1589 l = rdmixer(s, mixtable[i].left);
1590 r = rdmixer(s, mixtable[i].right);
1591 }
1592 spin_unlock_irqrestore(&s->lock, flags);
1593
1594 switch (mixtable[i].type) {
1595 case MT_2:
1596 case MT_2MONO:
1597 l >>= 6;
1598 r >>= 6;
1599 rl = (l * 33) + (l != 0);
1600 rr = (r * 33) + (r != 0);
1601 break;
1602
1603 case MT_4:
1604 rl = 10 + 6 * (l & 15);
1605 rr = 10 + 6 * (r & 15);
1606 break;
1607
1608 case MT_4AUX:
1609 rl = 10 + 6 * (l & 15);
1610 rr = 10 + 6 * (r & 15);
1611 break;
1612
1613 case MT_4MUTEMONO:
1614 rl = 55 - 3 * (l & 15);
1615 if (r & 0x10)
1616 rl += 45;
1617 rr = rl;
1618 break;
1619
1620 case MT_5:
1621 rl = 100 - 3 * ((l >> 3) & 31);
1622 rr = 100 - 3 * ((r >> 3) & 31);
1623 break;
1624
1625 case MT_5MUTEMONO:
1626 rl = 100 - 3 * ((l >> 3) & 31);
1627 rr = rl;
1628 break;
1629
1630 case MT_6:
1631 rl = 100 - 3 * (l & 63) / 2;
1632 rr = 100 - 3 * (r & 63) / 2;
1633 break;
1634 }
1635
1636// if (l & 0x80) rl = 0;
1637// if (r & 0x80) rr = 0;
1638
1639 return put_user((rr << 8) | rl, arg);
1640}
1641
1642#else
1643 #define return_mixval(s, i, a) put_user(s->mix.vol[i], (a))
1644
1645#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
1646
1647
1648
1649__static__ void set_mixval(struct cm_state *s, unsigned i, int val)
1650{
1651 unsigned long flags;
1652 unsigned char l, r, rl, rr, mix, enable;
1653
1654 l = (unsigned char)val;
1655 r = (unsigned char)(val >> 8);
1656 rl = 100;
1657 rr = 100;
1658
1659 if( s->chip_version < 68 )
1660 {
1661 // Rudi: emulate master volume which is always set to max
1662 // in multi-channel mode for chip revs < 68
1663 if( s->curr_channels > 2 &&
1664 i != SOUND_MIXER_VOLUME && i != SOUND_MIXER_PCM )
1665 {
1666 rl = (unsigned char)s->mix.vol[SOUND_MIXER_VOLUME];
1667 rr = (unsigned char)(s->mix.vol[SOUND_MIXER_VOLUME] >> 8);
1668 }
1669 }
1670 else
1671 {
1672 //Rudi: emulate PCM volume which doesn't work for chip rev 68
1673 if( i == SOUND_MIXER_PCM )
1674 {
1675 // force PCM to max.
1676 spin_lock_irqsave(&s->lock, flags);
1677 wrmixer(s, mixtable[SOUND_MIXER_PCM].left, 31 << 3);
1678 wrmixer(s, mixtable[SOUND_MIXER_PCM].right, 31 << 3);
1679 spin_unlock_irqrestore(&s->lock, flags);
1680
1681 rl = (unsigned char)s->mix.vol[SOUND_MIXER_VOLUME];
1682 rr = (unsigned char)(s->mix.vol[SOUND_MIXER_VOLUME] >> 8);
1683 i = SOUND_MIXER_VOLUME;
1684 }
1685 else if( i == SOUND_MIXER_VOLUME )
1686 {
1687 rl = (unsigned char)s->mix.vol[SOUND_MIXER_PCM];
1688 rr = (unsigned char)(s->mix.vol[SOUND_MIXER_PCM] >> 8);
1689 }
1690 }
1691
1692 if( l > 100 ) l = 100;
1693 if( r > 100 ) r = 100;
1694 if( rl > 100 ) rl = 100;
1695 if( rr > 100 ) rr = 100;
1696 l = ((l * rl) + 50) / 100;
1697 r = ((r * rr) + 50) / 100;
1698
1699
1700 spin_lock_irqsave(&s->lock, flags);
1701
1702 switch (mixtable[i].type) {
1703#ifdef MT_2
1704 case MT_2:
1705 wrmixer(s, mixtable[i].right, (r >> 5) << 6);
1706 case MT_2MONO:
1707 wrmixer(s, mixtable[i].left, (l >> 5) << 6);
1708 break;
1709#endif
1710
1711#ifdef MT_4
1712 case MT_4:
1713 rl = (l * 40) >> 8;
1714 rr = (r * 40) >> 8;
1715 frobindir(s, mixtable[i].left, ~0xf0, rl << 4);
1716 frobindir(s, mixtable[i].right, ~0xf0, rr << 4);
1717 break;
1718#endif
1719
1720#ifdef MT_4MUTEMONO
1721 case MT_4MUTEMONO:
1722 rl = (l * 40) >> 8;
1723 rr = (rl >> 1) & 7;
1724 wrmixer(s, mixtable[i].left, rl<<4);
1725 maskb(s->iobase + CODEC_CMI_MIXER2, ~0x0e, rr<<1);
1726 break;
1727#endif
1728
1729#ifdef MT_4AUX
1730 case MT_4AUX:
1731 rl = (l * 40) >> 8;
1732 rr = (r * 40) >> 8;
1733 outb((rr << 4) | rl, s->iobase + CODEC_CMI_AUX_VOL);
1734 break;
1735#endif
1736
1737#ifdef MT_5
1738 case MT_5:
1739 rl = (l * 80) >> 8;
1740 rr = (r * 80) >> 8;
1741 wrmixer(s, mixtable[i].left, rl<<3);
1742 wrmixer(s, mixtable[i].right, rr<<3);
1743 break;
1744#endif
1745
1746#ifdef MT_5MUTEMONO
1747 case MT_5MUTEMONO:
1748 rl = (l * 80) >> 8;
1749 rr = (rl >> 2) & 7;
1750 wrmixer(s, mixtable[i].left, rl<<3);
1751 maskb(s->iobase + CODEC_CMI_MIXER2, ~0x0e, rr<<1);
1752 break;
1753#endif
1754
1755#ifdef MT_6
1756 case MT_6:
1757 rl = (l * 160) >> 8;
1758 rr = (r * 160) >> 8;
1759 wrmixer(s, mixtable[i].left, rl);
1760 wrmixer(s, mixtable[i].right, rr);
1761 break;
1762#endif
1763 }
1764
1765#ifdef TARGET_OS2
1766 mix = mixtable[i].play;
1767 enable = l | r;
1768 switch( mix )
1769 {
1770 case 0x20 :
1771 enable_aux(s, enable, 0);
1772 break;
1773
1774 case 0x40 :
1775 frobindir(s, DSP_MIX_EXTENSIONIDX, ~8, ( enable ) ? 8 : 0);
1776 break;
1777
1778 case 0x80 :
1779 case 0x00 :
1780 break;
1781
1782 default :
1783 frobindir(s, DSP_MIX_OUTMIXIDX, ~mix, ( enable ) ? mix : 0);
1784 }
1785#endif
1786
1787 spin_unlock_irqrestore(&s->lock, flags);
1788}
1789
1790
1791// Rudi: support multi-channel mode
1792__static__ void update_mixer(struct cm_state *s)
1793{
1794 int i;
1795
1796 if( s->chip_version < 68 && s->curr_channels > 2 ) {
1797 set_mixval(s, SOUND_MIXER_PCM, s->mix.vol[SOUND_MIXER_VOLUME]);
1798 set_mixval(s, SOUND_MIXER_VOLUME, 0x6464); // maximum = 100%
1799 } else {
1800 set_mixval(s, SOUND_MIXER_PCM, s->mix.vol[SOUND_MIXER_PCM]);
1801 set_mixval(s, SOUND_MIXER_VOLUME, s->mix.vol[SOUND_MIXER_VOLUME]);
1802 }
1803
1804 // emulate master volume control: CD, Line, Aux, Mic, Rear
1805 for( i = 0; i < SOUND_MIXER_NRDEVICES; i++ )
1806 if( mixtable[i].play ) set_mixval(s, i, s->mix.vol[i]);
1807}
1808
1809
1810
1811__static__ unsigned mixer_recmask(struct cm_state *s)
1812{
1813 unsigned long flags;
1814 int i, j, k;
1815
1816 spin_lock_irqsave(&s->lock, flags);
1817 j = rdmixer(s, DSP_MIX_ADCMIXIDX_L);
1818 spin_unlock_irqrestore(&s->lock, flags);
1819 j &= 0x7f;
1820 for (k = i = 0; i < SOUND_MIXER_NRDEVICES; i++)
1821 if (j & mixtable[i].rec)
1822 k |= 1 << i;
1823 return k;
1824}
1825
1826__static__ int mixer_ioctl(struct cm_state *s, unsigned int cmd, unsigned long arg)
1827{
1828 unsigned long flags;
1829 int i, val, j;
1830
1831 VALIDATE_STATE(s);
1832 if (cmd == SOUND_MIXER_INFO) {
1833 mixer_info info;
1834 strncpy(info.id, "cmpci", sizeof(info.id));
1835 strncpy(info.name, "C-Media PCI", sizeof(info.name));
1836 info.modify_counter = s->mix.modcnt;
1837 if (copy_to_user((void *)arg, &info, sizeof(info)))
1838 return -EFAULT;
1839 return 0;
1840 }
1841 if (cmd == SOUND_OLD_MIXER_INFO) {
1842 _old_mixer_info info;
1843 strncpy(info.id, "cmpci", sizeof(info.id));
1844 strncpy(info.name, "C-Media cmpci", sizeof(info.name));
1845 if (copy_to_user((void *)arg, &info, sizeof(info)))
1846 return -EFAULT;
1847 return 0;
1848 }
1849 if (cmd == OSS_GETVERSION)
1850 return put_user(SOUND_VERSION, (int *)arg);
1851 if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
1852 return -EINVAL;
1853 if (_IOC_DIR(cmd) == _IOC_READ) {
1854 switch (_IOC_NR(cmd)) {
1855 case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
1856// Rudi: AUX and SPDIF/IN support
1857 val = ( inb(s->iobase + CODEC_CMI_MIXER2) & 0xc0 ) ?
1858 SOUND_MASK_LINE1 : 0;
1859 if( inb(s->iobase + CODEC_CMI_MIXER1) & 0x0c )
1860 val |= SOUND_MASK_DIGITAL1;
1861
1862 return put_user(val | mixer_recmask(s), (int *)arg);
1863
1864 case SOUND_MIXER_OUTSRC: /* Arg contains a bit for each output source */
1865// Rudi: AUX and SPDIF/IN support @@@
1866 val = ( inb(s->iobase + CODEC_CMI_MIXER2) & 0x30 ) ?
1867 SOUND_MASK_LINE1 : 0;
1868 if ( inb(s->iobase + CODEC_CMI_MIXER1) & 0x01 )
1869 val |= SOUND_MASK_DIGITAL1;
1870
1871 return put_user(val | mixer_recmask(s), (int *)arg);//need fix
1872
1873 case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */
1874 for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)
1875 if (mixtable[i].type)
1876 val |= 1 << i;
1877 return put_user(val, (int *)arg);
1878
1879 case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
1880 for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)
1881 if (mixtable[i].rec)
1882 val |= 1 << i;
1883 return put_user(val, (int *)arg);
1884
1885 case SOUND_MIXER_OUTMASK: /* Arg contains a bit for each supported recording source */
1886 for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)
1887 if (mixtable[i].play)
1888 val |= 1 << i;
1889 return put_user(val, (int *)arg);
1890
1891 case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
1892 for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)
1893 if (mixtable[i].type && !(mixtable[i].type & MT_MONO))
1894 val |= 1 << i;
1895 return put_user(val, (int *)arg);
1896
1897 case SOUND_MIXER_CAPS:
1898 return put_user(0, (int *)arg);
1899
1900 default:
1901 i = _IOC_NR(cmd);
1902 if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type)
1903 return -EINVAL;
1904 return return_mixval(s, i, (int *)arg);
1905 }
1906 }
1907
1908
1909 if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE))
1910 return -EINVAL;
1911 s->mix.modcnt++;
1912 switch (_IOC_NR(cmd)) {
1913 case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
1914#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1915 if (get_user(val, (int *)arg))
1916 return -EFAULT;
1917#else
1918 get_user_ret(val, (int *)arg, -EFAULT);
1919#endif
1920// Rudi: why ? i = hweight32(val);
1921 for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
1922 if (!(val & (1 << i)))
1923 continue;
1924 if (!mixtable[i].rec) {
1925 val &= ~(1 << i);
1926 continue;
1927 }
1928 j |= mixtable[i].rec;
1929 }
1930
1931// Rudi: AUX and SPDIF/IN support
1932 spin_lock_irqsave(&s->lock, flags);
1933 enable_aux(s, j & 0x80, 1);
1934 enable_digital(s, j & 0x0100, 1);
1935 // left -> left, right->right, MIC is mono
1936 j &= 0x7f;
1937 wrmixer(s, DSP_MIX_ADCMIXIDX_L, j);
1938 wrmixer(s, DSP_MIX_ADCMIXIDX_R, (j & 1) | (j>>1));
1939 spin_unlock_irqrestore(&s->lock, flags);
1940 return 0;
1941
1942 case SOUND_MIXER_OUTSRC: /* Arg contains a bit for each output source */
1943#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1944 if (get_user(val, (int *)arg))
1945 return -EFAULT;
1946#else
1947 get_user_ret(val, (int *)arg, -EFAULT);
1948#endif
1949 for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
1950 if (!(val & (1 << i)))
1951 continue;
1952 if (!mixtable[i].play) {
1953 val &= ~(1 << i);
1954 continue;
1955 }
1956 j |= mixtable[i].play;
1957 }
1958
1959// Rudi: AUX and SPDIF/IN support
1960 spin_lock_irqsave(&s->lock, flags);
1961 enable_aux(s, j & 0x20, 0);
1962// enable_digital(s, j & 0x40, 0);
1963
1964// @@@ ist das wirklich korrekt ???
1965 frobindir(s, DSP_MIX_OUTMIXIDX, 0x1f, j & 0x1f);
1966 spin_unlock_irqrestore(&s->lock, flags);
1967 return 0;
1968
1969 default:
1970 i = _IOC_NR(cmd);
1971 if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type)
1972 return -EINVAL;
1973#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1974 if (get_user(val, (int *)arg))
1975 return -EFAULT;
1976#else
1977 get_user_ret(val, (int *)arg, -EFAULT);
1978#endif
1979
1980
1981#ifndef OSS_DOCUMENTED_MIXER_SEMANTICS
1982 // store internally
1983 s->mix.vol[i] = val;
1984#endif
1985
1986 // Rudi: support for 8768
1987 if( s->chip_version < 68 && s->curr_channels > 2 ) {
1988// Rudi: 4 channels (seems to work only on Rev39+)
1989// In this mode, master volume is always set to max.
1990// Wave volume is controlled via SOUND_MIXER_PCM.
1991// For all other sources, master volume is emulated
1992
1993 if( i == SOUND_MIXER_VOLUME ) {
1994 update_mixer(s);
1995 return return_mixval(s, i, (int *)arg);
1996 }
1997
1998 if( i == SOUND_MIXER_PCM ) {
1999 return return_mixval(s, i, (int *)arg);
2000 }
2001 }
2002
2003 set_mixval(s, i, val);
2004 return return_mixval(s, i, (int *)arg);
2005 }
2006}
2007
2008/* --------------------------------------------------------------------- */
2009
2010__static__ loff_t cm_llseek(struct file *file, loff_t offset, int origin)
2011{
2012dprintf(("cm_llseek"));
2013
2014 return -ESPIPE;
2015}
2016
2017/* --------------------------------------------------------------------- */
2018
2019__static__ int cm_open_mixdev(struct inode *inode, struct file *file)
2020{
2021 int minor = MINOR(inode->i_rdev);
2022 struct cm_state *s = devs;
2023
2024dprintf(("cm_open_mixdev"));
2025
2026 while (s && s->dev_mixer != minor)
2027 s = s->next;
2028 if (!s)
2029 return -ENODEV;
2030 VALIDATE_STATE(s);
2031 file->private_data = s;
2032#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
2033 MOD_INC_USE_COUNT;
2034#endif
2035 return 0;
2036}
2037
2038__static__ int cm_release_mixdev(struct inode *inode, struct file *file)
2039{
2040 struct cm_state *s = (struct cm_state *)file->private_data;
2041
2042dprintf(("cm_release_mixdev"));
2043
2044 VALIDATE_STATE(s);
2045#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
2046 MOD_DEC_USE_COUNT;
2047#endif
2048 return 0;
2049}
2050
2051__static__ int cm_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
2052{
2053dprintf(("cm_ioctl_mixdev: %x", cmd));
2054
2055 return mixer_ioctl((struct cm_state *)file->private_data, cmd, arg);
2056}
2057
2058
2059#ifndef TARGET_OS2
2060 static /*const*/ struct file_operations cm_mixer_fops = {
2061 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2062 owner: THIS_MODULE,
2063 #endif
2064 llseek: cm_llseek,
2065 ioctl: cm_ioctl_mixdev,
2066 open: cm_open_mixdev,
2067 release: cm_release_mixdev,
2068 };
2069
2070#else
2071 static /*const*/ struct file_operations cm_mixer_fops = {
2072 cm_llseek, // llseek
2073 NULL, // read
2074 NULL, // write
2075 NULL, // readdir
2076 NULL, // poll
2077 cm_ioctl_mixdev, // ioctl
2078 NULL, // mmap
2079 cm_open_mixdev, // open
2080 NULL, // flush
2081 cm_release_mixdev // release
2082 };
2083
2084#endif
2085
2086
2087
2088/* --------------------------------------------------------------------- */
2089
2090#ifndef TARGET_OS2
2091int IntrOpen(void)
2092{
2093 struct cm_state *s = devs;
2094 unsigned char fmtm = ~0, fmts = 0;
2095
2096 /* Locate the /dev/dsp file descriptor */
2097 while (s && ((s->dev_audio ^ 3) & ~0xf))
2098 s = s->next;
2099
2100 devaudio = s;
2101 down(&s->open_sem);
2102 if (s->open_mode & FMODE_WRITE) {
2103 up(&s->open_sem);
2104 devaudio = NULL;
2105 return -EBUSY;
2106 }
2107
2108 if (!s->dma_dac.ready) {
2109 set_dac_rate(s, 8000);
2110 fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_SHIFT_CH0);
2111 set_fmt(s, fmtm, fmts);
2112 s->modem = 1;
2113 }
2114
2115 s->open_mode |= FMODE_WRITE;
2116 up(&s->open_sem);
2117 MOD_INC_USE_COUNT;
2118 return 0;
2119}
2120EXPORT_SYMBOL(IntrOpen);
2121
2122int IntrClose(void)
2123{
2124 struct cm_state *s = devaudio;
2125
2126 if (!s)
2127 return -ENODEV;
2128 down(&s->open_sem);
2129 stop_dac(s);
2130#ifndef FIXEDDMA
2131 dealloc_dmabuf(&s->dma_dac);
2132#endif
2133
2134 s->open_mode &= ~FMODE_WRITE;
2135 s->modem = 0;
2136 up(&s->open_sem);
2137 wake_up(&s->open_wait);
2138#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
2139 MOD_DEC_USE_COUNT;
2140#endif
2141 devaudio = NULL;
2142 return 0;
2143}
2144EXPORT_SYMBOL(IntrClose);
2145
2146int IntrWrite(const char *buffer, int count)
2147{
2148 struct cm_state *s = devaudio;
2149 ssize_t ret = 0;
2150 unsigned long flags;
2151 unsigned swptr;
2152 int cnt;
2153
2154 if (!s)
2155 return -ENODEV;
2156 VALIDATE_STATE(s);
2157 if (s->dma_dac.mapped)
2158 return -ENXIO;
2159
2160 if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
2161 return ret;
2162
2163 s->dma_dac.ossfragshift = 8;
2164 s->dma_dac.ossmaxfrags = 16;
2165 s->dma_dac.subdivision = 0;
2166
2167 while (count > 0) {
2168 spin_lock_irqsave(&s->lock, flags);
2169 if (s->dma_dac.count < 0) {
2170 s->dma_dac.count = 0;
2171 s->dma_dac.swptr = s->dma_dac.hwptr;
2172 }
2173 swptr = s->dma_dac.swptr;
2174 cnt = s->dma_dac.dmasize-swptr;
2175 if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
2176 cnt = s->dma_dac.dmasize - s->dma_dac.count;
2177 spin_unlock_irqrestore(&s->lock, flags);
2178 if (cnt > count)
2179 cnt = count;
2180 if (cnt <= 0) {
2181 start_dac(s);
2182 return ret;
2183 }
2184 if (__copy_from_user((char *)s->dma_dac.rawbuf + swptr, buffer, cnt))
2185 return ret ? ret : -EFAULT;
2186 swptr = (swptr + cnt) % s->dma_dac.dmasize;
2187 spin_lock_irqsave(&s->lock, flags);
2188 s->dma_dac.swptr = swptr;
2189 s->dma_dac.count += cnt;
2190 s->dma_dac.endcleared = 0;
2191 spin_unlock_irqrestore(&s->lock, flags);
2192 count -= cnt;
2193 buffer += cnt;
2194 ret += cnt;
2195 start_dac(s);
2196 }
2197 return ret;
2198}
2199EXPORT_SYMBOL(IntrWrite);
2200#endif
2201
2202
2203
2204/* --------------------------------------------------------------------- */
2205
2206
2207#ifndef TARGET_OS2
2208 __static__ int drain_dac(struct cm_state *s, int nonblock)
2209 {
2210 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
2211 DECLARE_WAITQUEUE(wait, current);
2212 #else
2213 struct wait_queue wait = { current, NULL };
2214 #endif
2215 unsigned long flags;
2216 int count, tmo;
2217
2218 if (s->dma_dac.mapped || !s->dma_dac.ready)
2219 return 0;
2220 current->state = TASK_INTERRUPTIBLE;
2221 add_wait_queue(&s->dma_dac.wait, &wait);
2222 for (;;) {
2223 spin_lock_irqsave(&s->lock, flags);
2224 count = s->dma_dac.count;
2225 spin_unlock_irqrestore(&s->lock, flags);
2226 if (count <= 0)
2227 break;
2228 if (signal_pending(current))
2229 break;
2230 if (nonblock) {
2231 remove_wait_queue(&s->dma_dac.wait, &wait);
2232 current->state = TASK_RUNNING;
2233 return -EBUSY;
2234 }
2235 tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->ratedac;
2236 tmo >>= sample_shift[(s->fmt >> CM_CFMT_SHIFT_CH0) & CM_CFMT_MASK];
2237
2238 if (!schedule_timeout(tmo + 1))
2239 printk(KERN_DEBUG "cm: dma timed out??\n");
2240 }
2241 remove_wait_queue(&s->dma_dac.wait, &wait);
2242 current->state = TASK_RUNNING;
2243 if (signal_pending(current))
2244 return -ERESTARTSYS;
2245 return 0;
2246 }
2247#endif
2248
2249
2250/* --------------------------------------------------------------------- */
2251
2252__static__ ssize_t cm_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
2253{
2254 struct cm_state *s = AUDIO_DEV_PTR(file->private_data);
2255 ssize_t ret;
2256 unsigned long flags;
2257 unsigned swptr;
2258 int cnt;
2259
2260//dprintf(("cm_read"));
2261
2262 VALIDATE_STATE(s);
2263 if (ppos != &file->f_pos)
2264 return -ESPIPE;
2265 if (s->dma_adc.mapped)
2266 return -ENXIO;
2267 if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))
2268 return ret;
2269 if (!access_ok(VERIFY_WRITE, buffer, count))
2270 return -EFAULT;
2271 ret = 0;
2272#if 0
2273 spin_lock_irqsave(&s->lock, flags);
2274 cm_update_ptr(s);
2275 spin_unlock_irqrestore(&s->lock, flags);
2276#endif
2277
2278#ifdef TARGET_OS2
2279 if( s->curr_streamid[0] != file->private_data ) {
2280 dprintf(("cm_read: wrong streamid: %x", file->private_data));
2281 return -EAGAIN;
2282 }
2283#endif
2284
2285 while (count > 0) {
2286 spin_lock_irqsave(&s->lock, flags);
2287 swptr = s->dma_adc.swptr;
2288 cnt = s->dma_adc.dmasize-swptr;
2289 if (s->dma_adc.count < cnt)
2290 cnt = s->dma_adc.count;
2291 spin_unlock_irqrestore(&s->lock, flags);
2292 if (cnt > count)
2293 cnt = count;
2294#ifdef TARGET_OS2
2295 if (cnt <= 0) { start_adc(s); return ret; };
2296#else
2297 if (cnt <= 0) {
2298 start_adc(s);
2299 if (file->f_flags & O_NONBLOCK)
2300 return ret ? ret : -EAGAIN;
2301
2302 if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) {
2303 printk(KERN_DEBUG "cm: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
2304 s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count,
2305 s->dma_adc.hwptr, s->dma_adc.swptr);
2306 stop_adc(s);
2307 spin_lock_irqsave(&s->lock, flags);
2308 set_dmaadc(s, s->dma_adc.rawphys, s->dma_adc.dmasamples);
2309 /* program sample counts */
2310 set_countadc(s, s->dma_adc.fragsamples);
2311 s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;
2312 spin_unlock_irqrestore(&s->lock, flags);
2313 }
2314
2315 if (signal_pending(current))
2316 return ret ? ret : -ERESTARTSYS;
2317 continue;
2318 }
2319#endif
2320
2321 if (copy_to_user(buffer, (char *)s->dma_adc.rawbuf + swptr, cnt))
2322 return ret ? ret : -EFAULT;
2323 swptr = (swptr + cnt) % s->dma_adc.dmasize;
2324 spin_lock_irqsave(&s->lock, flags);
2325 s->dma_adc.swptr = swptr;
2326 s->dma_adc.count -= cnt;
2327 spin_unlock_irqrestore(&s->lock, flags);
2328 count -= cnt;
2329 buffer += cnt;
2330 ret += cnt;
2331 start_adc(s);
2332 }
2333 return ret;
2334}
2335
2336__static__ ssize_t cm_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
2337{
2338 struct cm_state *s = AUDIO_DEV_PTR(file->private_data);
2339 ssize_t ret;
2340 unsigned long flags;
2341 unsigned swptr;
2342 int cnt, dualshift;
2343
2344//dprintf(("cm_write: %d %d", count, 1));
2345
2346 VALIDATE_STATE(s);
2347 if (ppos != &file->f_pos)
2348 return -ESPIPE;
2349 if (s->dma_dac.mapped)
2350 return -ENXIO;
2351 if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
2352 return ret;
2353 if (!access_ok(VERIFY_READ, buffer, count))
2354 return -EFAULT;
2355 if (s->status & DO_DUAL_DAC) {
2356 if (s->dma_adc.mapped)
2357 return -ENXIO;
2358 if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))
2359 return ret;
2360 if (!access_ok(VERIFY_READ, buffer, count))
2361 return -EFAULT;
2362 }
2363 ret = 0;
2364#if 0
2365 spin_lock_irqsave(&s->lock, flags);
2366 cm_update_ptr(s);
2367 spin_unlock_irqrestore(&s->lock, flags);
2368#endif
2369
2370#ifdef TARGET_OS2
2371 if( s->curr_streamid[1] != file->private_data ) {
2372 dprintf(("cm_write: wrong streamid: %x", file->private_data));
2373 return -EAGAIN;
2374 }
2375#endif
2376
2377 dualshift = ( s->status & DO_DUAL_DAC ) != 0;
2378
2379 while (count > 0) {
2380 spin_lock_irqsave(&s->lock, flags);
2381 if (s->dma_dac.count < 0) {
2382 s->dma_dac.count = 0;
2383 s->dma_dac.swptr = s->dma_dac.hwptr;
2384 }
2385 if( dualshift ) {
2386 s->dma_adc.swptr = s->dma_dac.swptr;
2387 s->dma_adc.count = s->dma_dac.count;
2388 s->dma_adc.endcleared = s->dma_dac.endcleared;
2389 }
2390 swptr = s->dma_dac.swptr;
2391 cnt = s->dma_dac.dmasize-swptr;
2392 if (s->status & DO_AC3_SW) {
2393 if (s->dma_dac.count + 2 * cnt > s->dma_dac.dmasize)
2394 cnt = (s->dma_dac.dmasize - s->dma_dac.count) / 2;
2395 } else {
2396 if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
2397 cnt = s->dma_dac.dmasize - s->dma_dac.count;
2398 }
2399 spin_unlock_irqrestore(&s->lock, flags);
2400
2401 cnt <<= dualshift;
2402 if (cnt > count) cnt = count;
2403
2404#ifdef TARGET_OS2
2405 if (cnt <= 0) { start_dac(s); return ret; }
2406#else
2407 if (cnt <= 0) {
2408 start_dac(s);
2409 if (file->f_flags & O_NONBLOCK)
2410 return ret ? ret : -EAGAIN;
2411
2412 if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) {
2413 printk(KERN_DEBUG "cm: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
2414 s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count,
2415 s->dma_dac.hwptr, s->dma_dac.swptr);
2416 stop_dac(s);
2417 spin_lock_irqsave(&s->lock, flags);
2418 set_dmadac(s, s->dma_dac.rawphys, s->dma_dac.dmasamples);
2419 /* program sample counts */
2420 set_countdac(s, s->dma_dac.fragsamples);
2421 s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0;
2422 if (s->status & DO_DUAL_DAC) {
2423 set_dmadac1(s, s->dma_adc.rawphys, s->dma_adc.dmasamples);
2424 s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;
2425 }
2426 spin_unlock_irqrestore(&s->lock, flags);
2427 }
2428
2429 if (signal_pending(current))
2430 return ret ? ret : -ERESTARTSYS;
2431 continue;
2432 }
2433#endif
2434 if (s->status & DO_AC3_SW) {
2435 // clip exceeded data, caught by 033 and 037
2436 if (swptr + 2 * cnt > s->dma_dac.dmasize)
2437 cnt = (s->dma_dac.dmasize - swptr) / 2;
2438 trans_ac3(s, (char *)s->dma_dac.rawbuf + swptr, buffer, cnt);
2439 swptr = (swptr + 2 * cnt) % s->dma_dac.dmasize;
2440 } else if (s->status & DO_DUAL_DAC) {
2441 int i;
2442 unsigned long *src, *dst0, *dst1;
2443
2444 src = (unsigned long *) buffer;
2445 dst0 = (unsigned long *) ((char *)s->dma_dac.rawbuf + swptr);
2446 dst1 = (unsigned long *) ((char *)s->dma_adc.rawbuf + swptr);
2447
2448 // copy left/right sample at one time
2449 cnt >>= 3;
2450 for (i = 0; i < cnt; i++) {
2451// Rudi: exchange front <-> rear
2452 *dst1++ = *src++;
2453 *dst0++ = *src++;
2454 }
2455 cnt <<= 3;
2456 swptr = (swptr + (cnt >> 1)) % s->dma_dac.dmasize;
2457
2458 } else {
2459 if (copy_from_user((char *)s->dma_dac.rawbuf + swptr, buffer, cnt))
2460 return ret ? ret : -EFAULT;
2461 swptr = (swptr + cnt) % s->dma_dac.dmasize;
2462 }
2463
2464 spin_lock_irqsave(&s->lock, flags);
2465 s->dma_dac.swptr = swptr;
2466 s->dma_dac.count += cnt >> dualshift;
2467 if (s->status & DO_AC3_SW) s->dma_dac.count += cnt;
2468 s->dma_dac.endcleared = 0;
2469 spin_unlock_irqrestore(&s->lock, flags);
2470
2471 count -= cnt;
2472 buffer += cnt;
2473 ret += cnt;
2474 if( dualshift && (count < 8) ) count = 0;
2475
2476 start_dac(s);
2477 }
2478 return ret;
2479}
2480
2481__static__ unsigned int cm_poll(struct file *file, struct poll_table_struct *wait)
2482{
2483 struct cm_state *s = AUDIO_DEV_PTR(file->private_data);
2484 unsigned long flags;
2485 unsigned int mask = 0;
2486
2487dprintf(("cm_poll"));
2488
2489 VALIDATE_STATE(s);
2490 if (file->f_mode & FMODE_WRITE)
2491 poll_wait(file, &s->dma_dac.wait, wait);
2492 if (file->f_mode & FMODE_READ)
2493 poll_wait(file, &s->dma_adc.wait, wait);
2494 spin_lock_irqsave(&s->lock, flags);
2495 cm_update_ptr(s);
2496 if (file->f_mode & FMODE_READ) {
2497 if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
2498 mask |= POLLIN | POLLRDNORM;
2499 }
2500 if (file->f_mode & FMODE_WRITE) {
2501 if (s->dma_dac.mapped) {
2502 if (s->dma_dac.count >= (signed)s->dma_dac.fragsize)
2503 mask |= POLLOUT | POLLWRNORM;
2504 } else {
2505 if ((signed)s->dma_dac.dmasize >= s->dma_dac.count + (signed)s->dma_dac.fragsize)
2506 mask |= POLLOUT | POLLWRNORM;
2507 }
2508 }
2509 spin_unlock_irqrestore(&s->lock, flags);
2510
2511 return mask;
2512}
2513
2514__static__ int cm_mmap(struct file *file, struct vm_area_struct *vma)
2515{
2516 struct cm_state *s = AUDIO_DEV_PTR(file->private_data);
2517 struct dmabuf *db;
2518 int ret = -EINVAL;
2519 unsigned long size;
2520
2521dprintf(("cm_mmap"));
2522
2523 VALIDATE_STATE(s);
2524#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2525 lock_kernel();
2526#endif
2527 if (vma->vm_flags & VM_WRITE) {
2528 if ((ret = prog_dmabuf(s, 0)) != 0)
2529 goto out;
2530 db = &s->dma_dac;
2531 } else if (vma->vm_flags & VM_READ) {
2532 if ((ret = prog_dmabuf(s, 1)) != 0)
2533 goto out;
2534 db = &s->dma_adc;
2535 } else
2536 goto out;
2537 ret = -EINVAL;
2538#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
2539 if (vma->vm_pgoff != 0)
2540#else
2541 if (vma->vm_offset != 0)
2542#endif
2543 goto out;
2544 size = vma->vm_end - vma->vm_start;
2545 if (size > (PAGE_SIZE << db->buforder))
2546 goto out;
2547 ret = -EINVAL;
2548 if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
2549 goto out;
2550 db->mapped = 1;
2551 ret = 0;
2552out:
2553#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2554 unlock_kernel();
2555#endif
2556 return ret;
2557}
2558
2559__static__ int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
2560{
2561 struct cm_state *s = AUDIO_DEV_PTR(file->private_data);
2562 unsigned long flags;
2563 audio_buf_info abinfo;
2564 count_info cinfo;
2565 int val, mapped, ret, temp;
2566 unsigned char fmtm, fmtd;
2567
2568//dprintf(("cm_ioctl: %x, %x", cmd, s));
2569
2570 VALIDATE_STATE(s);
2571 mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||
2572 ((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
2573 switch (cmd) {
2574 case OSS_GETVERSION:
2575 return put_user(SOUND_VERSION, (int *)arg);
2576
2577#ifndef TARGET_OS2
2578 case SNDCTL_DSP_SYNC:
2579 if (file->f_mode & FMODE_WRITE)
2580 return drain_dac(s, 0/*file->f_flags & O_NONBLOCK*/);
2581 return 0;
2582
2583 case SNDCTL_DSP_SETDUPLEX:
2584 return 0;
2585
2586 case SNDCTL_DSP_GETCAPS:
2587 return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME |
2588 DSP_CAP_TRIGGER | DSP_CAP_MMAP |
2589 DSP_CAP_BIND, (int *)arg);
2590#endif
2591
2592 case SNDCTL_DSP_RESET:
2593dprintf(("IOCTL: SNDCTL_DSP_RESET: %x (%x)", file->private_data, s->curr_streamid[1]));
2594
2595 if (file->f_mode & FMODE_WRITE) {
2596#ifdef TARGET_OS2
2597 if( s->curr_streamid[1] == file->private_data ) {
2598#endif
2599 stop_dac(s);
2600 synchronize_irq();
2601
2602 spin_lock_irqsave(&s->lock, flags);
2603 s->dma_dac.ready = 0;
2604 s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = s->dma_dac.total_bytes = 0;
2605 if (s->status & DO_DUAL_DAC) {
2606//Rudi: clear adc.ready as well
2607 s->dma_adc.ready = 0;
2608 s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0;
2609 }
2610 spin_unlock_irqrestore(&s->lock, flags);
2611#ifdef TARGET_OS2
2612 }
2613#endif
2614 }
2615 if (file->f_mode & FMODE_READ) {
2616#ifdef TARGET_OS2
2617 if( s->curr_streamid[0] == file->private_data ) {
2618#endif
2619 stop_adc(s);
2620 synchronize_irq();
2621
2622 spin_lock_irqsave(&s->lock, flags);
2623 s->dma_adc.ready = 0;
2624 s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0;
2625 spin_unlock_irqrestore(&s->lock, flags);
2626#ifdef TARGET_OS2
2627 }
2628#endif
2629 }
2630 return 0;
2631
2632 case SNDCTL_DSP_SPEED:
2633dprintf(("IOCTL: SNDCTL_DSP_SPEED: %x (%x)", file->private_data, s->curr_streamid[1]));
2634
2635#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2636 if (get_user(val, (int *)arg))
2637 return -EFAULT;
2638#else
2639 get_user_ret(val, (int *)arg, -EFAULT);
2640#endif
2641 if (val >= 0) {
2642 if (file->f_mode & FMODE_READ) {
2643 stop_adc(s);
2644 s->dma_adc.ready = 0;
2645 set_adc_rate(s, val);
2646#ifdef TARGET_OS2
2647 s->curr_streamid[0] = file->private_data;
2648#endif
2649 }
2650 if (file->f_mode & FMODE_WRITE) {
2651 stop_dac(s);
2652 s->dma_dac.ready = 0;
2653 if (s->status & DO_DUAL_DAC)
2654 s->dma_adc.ready = 0;
2655 set_dac_rate(s, val);
2656#ifdef TARGET_OS2
2657 s->curr_streamid[1] = file->private_data;
2658#endif
2659 }
2660 }
2661 return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
2662
2663 case SNDCTL_DSP_STEREO:
2664#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2665 if (get_user(val, (int *)arg))
2666 return -EFAULT;
2667#else
2668 get_user_ret(val, (int *)arg, -EFAULT);
2669#endif
2670 fmtd = 0;
2671 fmtm = ~0;
2672 if (file->f_mode & FMODE_READ) {
2673 stop_adc(s);
2674 s->dma_adc.ready = 0;
2675 if (val)
2676 fmtd |= CM_CFMT_STEREO << CM_CFMT_SHIFT_CH1;
2677 else
2678 fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_SHIFT_CH1);
2679 }
2680 if (file->f_mode & FMODE_WRITE) {
2681 stop_dac(s);
2682 s->dma_dac.ready = 0;
2683 if (val)
2684 fmtd |= CM_CFMT_STEREO << CM_CFMT_SHIFT_CH0;
2685 else
2686 fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_SHIFT_CH0);
2687 if (s->status & DO_DUAL_DAC) {
2688 s->dma_adc.ready = 0;
2689 if (val)
2690 fmtd |= CM_CFMT_STEREO << CM_CFMT_SHIFT_CH1;
2691 else
2692 fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_SHIFT_CH1);
2693 }
2694 }
2695 set_fmt(s, fmtm, fmtd);
2696 return 0;
2697
2698 case SNDCTL_DSP_CHANNELS:
2699dprintf(("IOCTL: SNDCTL_DSP_CHANNELS: %x (%x)", file->private_data, s->curr_streamid[1]));
2700
2701#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2702 if (get_user(val, (int *)arg))
2703 return -EFAULT;
2704#else
2705 get_user_ret(val, (int *)arg, -EFAULT);
2706#endif
2707 if (val != 0) {
2708 fmtd = 0;
2709 fmtm = ~0;
2710 if (file->f_mode & FMODE_READ) {
2711 stop_adc(s);
2712 s->dma_adc.ready = 0;
2713 if (val >= 2)
2714 fmtd |= CM_CFMT_STEREO << CM_CFMT_SHIFT_CH1;
2715 else
2716 fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_SHIFT_CH1);
2717 }
2718 if (file->f_mode & FMODE_WRITE) {
2719 stop_dac(s);
2720 s->dma_dac.ready = 0;
2721 if (val >= 2)
2722 fmtd |= CM_CFMT_STEREO << CM_CFMT_SHIFT_CH0;
2723 else
2724 fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_SHIFT_CH0);
2725 if (s->status & DO_DUAL_DAC) {
2726 s->dma_adc.ready = 0;
2727 if (val >= 2)
2728 fmtd |= CM_CFMT_STEREO << CM_CFMT_SHIFT_CH1;
2729 else
2730 fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_SHIFT_CH1);
2731 }
2732 }
2733 set_fmt(s, fmtm, fmtd);
2734 if ((s->capability & CAN_MULTI_CH)
2735 && (file->f_mode & FMODE_WRITE)) {
2736 val = set_dac_channels(s, val);
2737 return put_user(val, (int *)arg);
2738 }
2739 }
2740 return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_STEREO << CM_CFMT_SHIFT_CH1)
2741 : (CM_CFMT_STEREO << CM_CFMT_SHIFT_CH0))) ? 2 : 1, (int *)arg);
2742
2743 case SNDCTL_DSP_GETFMTS: /* Returns a mask */
2744 return put_user(AFMT_S16_LE|AFMT_U8|AFMT_AC3, (int *)arg);
2745
2746 case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
2747dprintf(("IOCTL: SNDCTL_DSP_SETFMT: %x (%x)", file->private_data, s->curr_streamid[1]));
2748
2749#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2750 if (get_user(val, (int *)arg))
2751 return -EFAULT;
2752#else
2753 get_user_ret(val, (int *)arg, -EFAULT);
2754#endif
2755 if (val != AFMT_QUERY) {
2756 fmtd = 0;
2757 fmtm = ~0;
2758 if (file->f_mode & FMODE_READ) {
2759 stop_adc(s);
2760 s->dma_adc.ready = 0;
2761 if (val == AFMT_S16_LE)
2762 fmtd |= CM_CFMT_16BIT << CM_CFMT_SHIFT_CH1;
2763 else
2764 fmtm &= ~(CM_CFMT_16BIT << CM_CFMT_SHIFT_CH1);
2765 }
2766 if (file->f_mode & FMODE_WRITE) {
2767 stop_dac(s);
2768 s->dma_dac.ready = 0;
2769 if (val == AFMT_S16_LE || val == AFMT_AC3)
2770 fmtd |= CM_CFMT_16BIT << CM_CFMT_SHIFT_CH0;
2771 else
2772 fmtm &= ~(CM_CFMT_16BIT << CM_CFMT_SHIFT_CH0);
2773
2774 if (val == AFMT_AC3) {
2775 fmtd |= CM_CFMT_STEREO << CM_CFMT_SHIFT_CH0;
2776// Rudi: enable set_spdifout separately
2777
2778 // AC3HACK
2779 temp = s->status & DO_SPDIF_OUT_ENABLE;
2780 s->status |= DO_SPDIF_OUT_ENABLE;
2781 set_spdifout(s, s->ratedac);
2782 set_ac3(s, s->ratedac);
2783 s->status &= ~temp ^ DO_SPDIF_OUT_ENABLE;
2784
2785 } else {
2786 set_ac3(s, 0);
2787 set_spdifout(s, (s->curr_channels <= 2) ? s->ratedac : 0);
2788 }
2789
2790 if (s->status & DO_DUAL_DAC) {
2791 s->dma_adc.ready = 0;
2792 if (val == AFMT_S16_LE)
2793 fmtd |= CM_CFMT_STEREO << CM_CFMT_SHIFT_CH1;
2794 else
2795 fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_SHIFT_CH1);
2796 }
2797 }
2798 set_fmt(s, fmtm, fmtd);
2799 }
2800 if (s->status & DO_AC3) return put_user(AFMT_AC3, (int *)arg);
2801 return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_16BIT << CM_CFMT_SHIFT_CH1)
2802 : (CM_CFMT_16BIT << CM_CFMT_SHIFT_CH0))) ? AFMT_S16_LE : AFMT_U8, (int *)arg);
2803
2804 case SNDCTL_DSP_POST:
2805 return 0;
2806
2807 case SNDCTL_DSP_GETTRIGGER:
2808 val = 0;
2809 if (s->status & DO_DUAL_DAC) {
2810 if (file->f_mode & FMODE_WRITE &&
2811 (s->enable & CM_ENABLE_CH1) &&
2812 (s->enable & CM_ENABLE_CH0))
2813 val |= PCM_ENABLE_OUTPUT;
2814 return put_user(val, (int *)arg);
2815 }
2816 if (file->f_mode & FMODE_READ && s->enable & CM_ENABLE_CH0)
2817 val |= PCM_ENABLE_INPUT;
2818 if (file->f_mode & FMODE_WRITE && s->enable & CM_ENABLE_CH1)
2819 val |= PCM_ENABLE_OUTPUT;
2820 return put_user(val, (int *)arg);
2821
2822 case SNDCTL_DSP_SETTRIGGER:
2823
2824#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2825 if (get_user(val, (int *)arg))
2826 return -EFAULT;
2827#else
2828 get_user_ret(val, (int *)arg, -EFAULT);
2829#endif
2830
2831dprintf(("IOCTL: SNDCTL_DSP_SETTRIGGER(%d): %x (%x)", val, file->private_data, s->curr_streamid[1]));
2832
2833 if (file->f_mode & FMODE_READ) {
2834 if (val & PCM_ENABLE_INPUT) {
2835 if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))
2836 return ret;
2837#ifdef TARGET_OS2
2838 s->curr_streamid[0] = file->private_data;
2839#endif
2840 start_adc(s);
2841 } else {
2842#ifdef TARGET_OS2
2843 if( s->curr_streamid[0] == file->private_data )
2844#endif
2845 stop_adc(s);
2846 }
2847 }
2848 if (file->f_mode & FMODE_WRITE) {
2849 if (val & PCM_ENABLE_OUTPUT) {
2850 if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
2851 return ret;
2852 if (s->status & DO_DUAL_DAC) {
2853 if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))
2854 return ret;
2855 }
2856#ifdef TARGET_OS2
2857 s->curr_streamid[1] = file->private_data;
2858#endif
2859 start_dac(s);
2860 } else {
2861#ifdef TARGET_OS2
2862 if( s->curr_streamid[1] == file->private_data )
2863#endif
2864 stop_dac(s);
2865 }
2866 }
2867 return 0;
2868
2869 case SNDCTL_DSP_GETOSPACE:
2870 if (!(file->f_mode & FMODE_WRITE))
2871 return -EINVAL;
2872#ifdef TARGET_OS2
2873 if( s->curr_streamid[1] != file->private_data ) return -EINVAL;
2874#endif
2875// if (!(s->enable & CM_ENABLE_CH1) && (val = prog_dmabuf(s, 0)))
2876 if (!s->dma_dac.ready && (val = prog_dmabuf(s, 0)))
2877 return val;
2878 spin_lock_irqsave(&s->lock, flags);
2879 cm_update_ptr(s);
2880 abinfo.fragsize = s->dma_dac.fragsize;
2881//Rudi: round down to full sample size
2882 abinfo.bytes = (s->dma_dac.dmasize - s->dma_dac.count) &
2883 sample_mask[(s->fmt >> CM_CFMT_SHIFT_CH0) & CM_CFMT_MASK];
2884//Rudi: 4 channels
2885 if( s->status & DO_DUAL_DAC ) abinfo.bytes <<= 1;
2886 abinfo.fragstotal = s->dma_dac.numfrag;
2887 abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;
2888 spin_unlock_irqrestore(&s->lock, flags);
2889 return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
2890
2891 case SNDCTL_DSP_GETISPACE:
2892 if (!(file->f_mode & FMODE_READ))
2893 return -EINVAL;
2894#ifdef TARGET_OS2
2895 if( s->curr_streamid[0] != file->private_data ) return -EINVAL;
2896#endif
2897// if (!(s->enable & CM_ENABLE_CH0) && (val = prog_dmabuf(s, 1)) != 0)
2898 if (!s->dma_adc.ready && (val = prog_dmabuf(s, 1)))
2899 return val;
2900 spin_lock_irqsave(&s->lock, flags);
2901 cm_update_ptr(s);
2902 abinfo.fragsize = s->dma_adc.fragsize;
2903//Rudi: round down to full sample size
2904 abinfo.bytes = s->dma_adc.count &
2905 sample_mask[(s->fmt >> CM_CFMT_SHIFT_CH1) & CM_CFMT_MASK];
2906 abinfo.fragstotal = s->dma_adc.numfrag;
2907 abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;
2908 spin_unlock_irqrestore(&s->lock, flags);
2909 return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
2910
2911 case SNDCTL_DSP_NONBLOCK:
2912 file->f_flags |= O_NONBLOCK;
2913 return 0;
2914
2915 case SNDCTL_DSP_GETODELAY:
2916 if (!(file->f_mode & FMODE_WRITE))
2917 return -EINVAL;
2918 spin_lock_irqsave(&s->lock, flags);
2919 cm_update_ptr(s);
2920 val = s->dma_dac.count;
2921 spin_unlock_irqrestore(&s->lock, flags);
2922 return put_user(val, (int *)arg);
2923
2924 case SNDCTL_DSP_GETIPTR:
2925 if (!(file->f_mode & FMODE_READ))
2926 return -EINVAL;
2927#ifdef TARGET_OS2
2928 if( s->curr_streamid[0] != file->private_data ) return -EINVAL;
2929#endif
2930 spin_lock_irqsave(&s->lock, flags);
2931 cm_update_ptr(s);
2932 cinfo.bytes = s->dma_adc.total_bytes;
2933 cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
2934 cinfo.ptr = s->dma_adc.hwptr;
2935 if (s->dma_adc.mapped)
2936 s->dma_adc.count &= s->dma_adc.fragsize-1;
2937 spin_unlock_irqrestore(&s->lock, flags);
2938 return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
2939
2940 case SNDCTL_DSP_GETOPTR:
2941 if (!(file->f_mode & FMODE_WRITE))
2942 return -EINVAL;
2943#ifdef TARGET_OS2
2944 if( s->curr_streamid[1] != file->private_data ) return -EINVAL;
2945#endif
2946 spin_lock_irqsave(&s->lock, flags);
2947 cm_update_ptr(s);
2948 cinfo.bytes = s->dma_dac.total_bytes;
2949//Rudi: 4 channels
2950 if( s->status & DO_DUAL_DAC ) cinfo.bytes <<= 1;
2951
2952 cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;
2953
2954//Rudi: SW_AC3 uses 32bits
2955 if( s->status & DO_AC3_SW ) {
2956 cinfo.bytes >>= 1; cinfo.blocks >>= 1;
2957 }
2958
2959 cinfo.ptr = s->dma_dac.hwptr;
2960 if (s->dma_dac.mapped)
2961 s->dma_dac.count &= s->dma_dac.fragsize-1;
2962 if (s->status & DO_DUAL_DAC) {
2963 if (s->dma_adc.mapped)
2964 s->dma_adc.count &= s->dma_adc.fragsize-1;
2965 }
2966 spin_unlock_irqrestore(&s->lock, flags);
2967 return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
2968
2969 case SNDCTL_DSP_GETBLKSIZE:
2970 if (file->f_mode & FMODE_WRITE) {
2971 if (!s->dma_dac.ready && (val = prog_dmabuf(s, 0)))
2972 return val;
2973 if (s->status & DO_DUAL_DAC) {
2974 if (!s->dma_adc.ready && (val = prog_dmabuf(s, 1)))
2975 return val;
2976 return put_user(2 * s->dma_dac.fragsize, (int *)arg);
2977 }
2978 return put_user(s->dma_dac.fragsize, (int *)arg);
2979 }
2980
2981 if (!s->dma_adc.ready && (val = prog_dmabuf(s, 1)))
2982 return val;
2983 return put_user(s->dma_adc.fragsize, (int *)arg);
2984
2985 case SNDCTL_DSP_SETFRAGMENT:
2986dprintf(("IOCTL: SNDCTL_DSP_SETFRAGMENT:: %x (%x)", file->private_data, s->curr_streamid[1]));
2987
2988#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
2989 if (get_user(val, (int *)arg))
2990 return -EFAULT;
2991#else
2992 get_user_ret(val, (int *)arg, -EFAULT);
2993#endif
2994 if (file->f_mode & FMODE_READ) {
2995 s->dma_adc.ossfragshift = val & 0xffff;
2996 s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
2997 if (s->dma_adc.ossfragshift < 4)
2998 s->dma_adc.ossfragshift = 4;
2999 if (s->dma_adc.ossfragshift > 15)
3000 s->dma_adc.ossfragshift = 15;
3001 if (s->dma_adc.ossmaxfrags < 4)
3002 s->dma_adc.ossmaxfrags = 4;
3003 }
3004 if (file->f_mode & FMODE_WRITE) {
3005 s->dma_dac.ossfragshift = val & 0xffff;
3006 s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff;
3007 if (s->dma_dac.ossfragshift < 4)
3008 s->dma_dac.ossfragshift = 4;
3009 if (s->dma_dac.ossfragshift > 15)
3010 s->dma_dac.ossfragshift = 15;
3011 if (s->dma_dac.ossmaxfrags < 4)
3012 s->dma_dac.ossmaxfrags = 4;
3013 if (s->status & DO_DUAL_DAC) {
3014 s->dma_adc.ossfragshift = s->dma_dac.ossfragshift;
3015 s->dma_adc.ossmaxfrags = s->dma_dac.ossmaxfrags;
3016 }
3017 }
3018 return 0;
3019
3020 case SNDCTL_DSP_SUBDIVIDE:
3021 if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
3022 (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
3023 return -EINVAL;
3024#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3025 if (get_user(val, (int *)arg))
3026 return -EFAULT;
3027#else
3028 get_user_ret(val, (int *)arg, -EFAULT);
3029#endif
3030 if (val != 1 && val != 2 && val != 4)
3031 return -EINVAL;
3032 if (file->f_mode & FMODE_READ)
3033 s->dma_adc.subdivision = val;
3034 if (file->f_mode & FMODE_WRITE) {
3035 s->dma_dac.subdivision = val;
3036 if (s->status & DO_DUAL_DAC)
3037 s->dma_adc.subdivision = val;
3038 }
3039 return 0;
3040
3041 case SOUND_PCM_READ_RATE:
3042 return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
3043
3044 case SOUND_PCM_READ_CHANNELS:
3045 return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_STEREO << CM_CFMT_SHIFT_CH1) : (CM_CFMT_STEREO << CM_CFMT_SHIFT_CH0))) ? 2 : 1, (int *)arg);
3046
3047 case SOUND_PCM_READ_BITS:
3048 return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_16BIT << CM_CFMT_SHIFT_CH1) : (CM_CFMT_16BIT << CM_CFMT_SHIFT_CH0))) ? 16 : 8, (int *)arg);
3049
3050 case SOUND_PCM_READ_FILTER:
3051 return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
3052
3053 case SNDCTL_DSP_GETCHANNELMASK:
3054 return put_user(DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE|DSP_BIND_SPDIF, (int *)arg);
3055
3056 case SNDCTL_DSP_BIND_CHANNEL:
3057#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3058 if (get_user(val, (int *)arg))
3059 return -EFAULT;
3060#else
3061 get_user_ret(val, (int *)arg, -EFAULT);
3062#endif
3063 if (val == DSP_BIND_QUERY) {
3064 val = DSP_BIND_FRONT;
3065 if (s->status & DO_SPDIF_OUT)
3066 val |= DSP_BIND_SPDIF;
3067 else {
3068 if (s->curr_channels == 4)
3069 val |= DSP_BIND_SURR;
3070 if (s->curr_channels > 4)
3071 val |= DSP_BIND_CENTER_LFE;
3072 }
3073 } else {
3074 if (file->f_mode & FMODE_READ) {
3075 stop_adc(s);
3076 s->dma_adc.ready = 0;
3077 }
3078 if (file->f_mode & FMODE_WRITE) {
3079 stop_dac(s);
3080 s->dma_dac.ready = 0;
3081 if (val & DSP_BIND_SPDIF) {
3082 set_spdifout(s, s->ratedac);
3083 set_dac_channels(s, s->fmt & (CM_CFMT_STEREO << CM_CFMT_SHIFT_CH0) ? 2 : 1);
3084 if (!(s->status & DO_SPDIF_OUT))
3085 val &= ~DSP_BIND_SPDIF;
3086 } else {
3087 int channels;
3088 int mask;
3089
3090 mask = val & (DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE);
3091 switch (mask) {
3092 case DSP_BIND_FRONT:
3093 channels = 2;
3094 break;
3095 case DSP_BIND_FRONT|DSP_BIND_SURR:
3096 channels = 4;
3097 break;
3098 case DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE:
3099 channels = 6;
3100 break;
3101 default:
3102 channels = s->fmt & (CM_CFMT_STEREO << CM_CFMT_SHIFT_CH0) ? 2 : 1;
3103 break;
3104 }
3105 set_dac_channels(s, channels);
3106 }
3107 }
3108 }
3109 return put_user(val, (int *)arg);
3110
3111 case SOUND_PCM_WRITE_FILTER:
3112 case SNDCTL_DSP_MAPINBUF:
3113 case SNDCTL_DSP_MAPOUTBUF:
3114 case SNDCTL_DSP_SETSYNCRO:
3115 return -EINVAL;
3116
3117 }
3118 return mixer_ioctl(s, cmd, arg);
3119}
3120
3121__static__ int cm_open(struct inode *inode, struct file *file)
3122{
3123 unsigned long flags;
3124 int minor = MINOR(inode->i_rdev);
3125 struct cm_state *s = devs;
3126 unsigned char fmtm = ~0, fmts = 0;
3127
3128 while (s && ((s->dev_audio ^ minor) & ~0xf))
3129 s = s->next;
3130 if (!s)
3131 return -ENODEV;
3132
3133dprintf(("cm_open(%d, %d): capability=%x, status=%x",
3134 s->audio_open_count[0], s->audio_open_count[1], s->capability, s->status));
3135
3136 VALIDATE_STATE(s);
3137
3138#ifdef TARGET_OS2
3139 down(&s->open_sem);
3140 file->private_data = kmalloc(sizeof(struct cm_state *), GFP_KERNEL);
3141 AUDIO_DEV_PTR(file->private_data) = s;
3142
3143 if( file->f_mode & FMODE_READ ) {
3144 if( s->open_mode & file->f_mode ) stop_adc(s);
3145
3146 spin_lock_irqsave(&s->lock, flags);
3147 s->curr_streamid[0] = file->private_data;
3148 s->audio_open_count[0]++;
3149 spin_unlock_irqrestore(&s->lock, flags);
3150 }
3151
3152 if( file->f_mode & FMODE_WRITE ) {
3153 if( s->open_mode & file->f_mode ) stop_dac(s);
3154
3155 spin_lock_irqsave(&s->lock, flags);
3156 s->curr_streamid[1] = file->private_data;
3157 s->audio_open_count[1]++;
3158 spin_unlock_irqrestore(&s->lock, flags);
3159 }
3160
3161#else
3162 file->private_data = s;
3163
3164 /* wait for device to become free */
3165 down(&s->open_sem);
3166 while (s->open_mode & file->f_mode) {
3167 if (file->f_flags & O_NONBLOCK) {
3168 up(&s->open_sem);
3169 return -EBUSY;
3170 }
3171 up(&s->open_sem);
3172 interruptible_sleep_on(&s->open_wait);
3173 if (signal_pending(current))
3174 return -ERESTARTSYS;
3175 down(&s->open_sem);
3176 }
3177#endif
3178
3179 if (file->f_mode & FMODE_READ) {
3180 fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_SHIFT_CH1);
3181 if ((minor & 0xf) == SND_DEV_DSP16)
3182 fmts |= CM_CFMT_16BIT << CM_CFMT_SHIFT_CH1;
3183 s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0;
3184 set_adc_rate(s, 8000);
3185 }
3186
3187 if (file->f_mode & FMODE_WRITE) {
3188 fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_SHIFT_CH0);
3189 if ((minor & 0xf) == SND_DEV_DSP16)
3190 fmts |= CM_CFMT_16BIT << CM_CFMT_SHIFT_CH0;
3191 s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0;
3192
3193 // clear previous multichannel, spdif, ac3 state
3194 set_spdifout(s, 0);
3195 if (s->deviceid >= PCI_DEVICE_ID_CMEDIA_CM8738) {
3196 set_ac3(s, 0);
3197 set_dac_channels(s, 1);
3198 }
3199 set_dac_rate(s, 8000);
3200 }
3201 set_fmt(s, fmtm, fmts);
3202 s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
3203 up(&s->open_sem);
3204#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
3205 MOD_INC_USE_COUNT;
3206#endif
3207 return 0;
3208}
3209
3210__static__ int cm_release(struct inode *inode, struct file *file)
3211{
3212 unsigned long flags;
3213 struct cm_state *s = AUDIO_DEV_PTR(file->private_data);
3214
3215dprintf(("cm_release(%d, %d)", s->audio_open_count[0], s->audio_open_count[1]));
3216
3217 VALIDATE_STATE(s);
3218#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3219 lock_kernel();
3220#endif
3221
3222
3223#ifdef TARGET_OS2
3224dprintf(("RELEASE(%d): %x (%x)", s->audio_open_count[1], file->private_data, s->curr_streamid[1]));
3225
3226 kfree(file->private_data);
3227 file->private_data = NULL;
3228
3229 spin_lock_irqsave(&s->lock, flags);
3230
3231 if( file->f_mode & FMODE_READ ) {
3232 if( --s->audio_open_count[0] ) {
3233 spin_unlock_irqrestore(&s->lock, flags); return 0;
3234 }
3235
3236 s->curr_streamid[0] = NULL;
3237 }
3238
3239 if( file->f_mode & FMODE_WRITE ) {
3240 if( --s->audio_open_count[1] ) {
3241 spin_unlock_irqrestore(&s->lock, flags); return 0;
3242 }
3243
3244 s->curr_streamid[1] = NULL;
3245 }
3246
3247 spin_unlock_irqrestore(&s->lock, flags);
3248#else
3249 if (file->f_mode & FMODE_WRITE)
3250 drain_dac(s, file->f_flags & O_NONBLOCK);
3251#endif
3252
3253dprintf(("RELEASE: SHUTDOWN"));
3254
3255 down(&s->open_sem);
3256 if (file->f_mode & FMODE_WRITE) {
3257 stop_dac(s);
3258#ifndef FIXEDDMA
3259 dealloc_dmabuf(&s->dma_dac);
3260 if (s->status & DO_DUAL_DAC)
3261 dealloc_dmabuf(&s->dma_adc);
3262#endif
3263 if (s->status & DO_MULTI_CH)
3264 set_dac_channels(s, 0);
3265 if (s->status & DO_AC3)
3266 set_ac3(s, 0);
3267 if (s->status & DO_SPDIF_OUT)
3268 set_spdifout(s, 0);
3269
3270 s->ratedac = 0;
3271 }
3272 if (file->f_mode & FMODE_READ) {
3273 stop_adc(s);
3274#ifndef FIXEDDMA
3275 dealloc_dmabuf(&s->dma_adc);
3276#endif
3277
3278 s->rateadc = 0;
3279 }
3280 s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
3281 up(&s->open_sem);
3282 wake_up(&s->open_wait);
3283#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3284 unlock_kernel();
3285#else
3286 MOD_DEC_USE_COUNT;
3287#endif
3288 return 0;
3289}
3290
3291#ifndef TARGET_OS2
3292 static /*const*/ struct file_operations cm_audio_fops = {
3293 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3294 owner: THIS_MODULE,
3295 #endif
3296 llseek: cm_llseek,
3297 read: cm_read,
3298 write: cm_write,
3299 poll: cm_poll,
3300 ioctl: cm_ioctl,
3301 mmap: cm_mmap,
3302 open: cm_open,
3303 release: cm_release,
3304 };
3305#else
3306 static /*const*/ struct file_operations cm_audio_fops = {
3307 cm_llseek, // llseek
3308 cm_read, // read
3309 cm_write, // write
3310 NULL, // readdir
3311 cm_poll, // poll
3312 cm_ioctl, // ioctl
3313 cm_mmap, // mmap
3314 cm_open, // open
3315 NULL, // flush
3316 cm_release // release
3317 };
3318
3319#endif
3320
3321
3322#ifdef CONFIG_SOUND_CMPCI_MIDI
3323/* --------------------------------------------------------------------- */
3324
3325__static__ ssize_t cm_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
3326{
3327 struct cm_state *s = (struct cm_state *)file->private_data;
3328#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3329 DECLARE_WAITQUEUE(wait, current);
3330#endif
3331 ssize_t ret;
3332 unsigned long flags;
3333 unsigned ptr;
3334 int cnt;
3335
3336dprintf(("cm_midi_read"));
3337
3338 VALIDATE_STATE(s);
3339 if (ppos != &file->f_pos)
3340 return -ESPIPE;
3341 if (!access_ok(VERIFY_WRITE, buffer, count))
3342 return -EFAULT;
3343 ret = 0;
3344#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3345 add_wait_queue(&s->midi.iwait, &wait);
3346#endif
3347 while (count > 0) {
3348 spin_lock_irqsave(&s->lock, flags);
3349 ptr = s->midi.ird;
3350 cnt = MIDIINBUF - ptr;
3351 if (s->midi.icnt < cnt)
3352 cnt = s->midi.icnt;
3353 spin_unlock_irqrestore(&s->lock, flags);
3354 if (cnt > count)
3355 cnt = count;
3356 if (cnt <= 0) {
3357 if (file->f_flags & O_NONBLOCK)
3358#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3359 {
3360 if (!ret)
3361 ret = -EAGAIN;
3362 break;
3363 }
3364 __set_current_state(TASK_INTERRUPTIBLE);
3365 schedule();
3366 if (signal_pending(current))
3367 {
3368 if (!ret)
3369 ret = -ERESTARTSYS;
3370 break;
3371 }
3372#else
3373 return ret ? ret : -EAGAIN;
3374 interruptible_sleep_on(&s->midi.iwait);
3375 if (signal_pending(current))
3376 return ret ? ret : -ERESTARTSYS;
3377#endif
3378 continue;
3379 }
3380 if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt))
3381#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3382 {
3383 if (!ret)
3384 ret = -EFAULT;
3385 break;
3386 }
3387#else
3388 return ret ? ret : -EFAULT;
3389#endif
3390 ptr = (ptr + cnt) % MIDIINBUF;
3391 spin_lock_irqsave(&s->lock, flags);
3392 s->midi.ird = ptr;
3393 s->midi.icnt -= cnt;
3394 spin_unlock_irqrestore(&s->lock, flags);
3395 count -= cnt;
3396 buffer += cnt;
3397 ret += cnt;
3398#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3399 break;
3400#endif
3401 }
3402#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3403 __set_current_state(TASK_RUNNING);
3404 remove_wait_queue(&s->midi.iwait, &wait);
3405#endif
3406 return ret;
3407}
3408
3409__static__ ssize_t cm_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
3410{
3411 struct cm_state *s = (struct cm_state *)file->private_data;
3412#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3413 DECLARE_WAITQUEUE(wait, current);
3414#endif
3415 ssize_t ret;
3416 unsigned long flags;
3417 unsigned ptr;
3418 int cnt;
3419
3420dprintf(("cm_midi_write"));
3421
3422 VALIDATE_STATE(s);
3423 if (ppos != &file->f_pos)
3424 return -ESPIPE;
3425 if (!access_ok(VERIFY_READ, buffer, count))
3426 return -EFAULT;
3427#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3428 if (count == 0)
3429 return 0;
3430#endif
3431 ret = 0;
3432#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3433 add_wait_queue(&s->midi.owait, &wait);
3434#endif
3435 while (count > 0) {
3436 spin_lock_irqsave(&s->lock, flags);
3437 ptr = s->midi.owr;
3438 cnt = MIDIOUTBUF - ptr;
3439 if (s->midi.ocnt + cnt > MIDIOUTBUF)
3440 cnt = MIDIOUTBUF - s->midi.ocnt;
3441 if (cnt <= 0)
3442 cm_handle_midi(s);
3443 spin_unlock_irqrestore(&s->lock, flags);
3444 if (cnt > count)
3445 cnt = count;
3446 if (cnt <= 0) {
3447 if (file->f_flags & O_NONBLOCK)
3448#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3449 {
3450 if (!ret)
3451 ret = -EAGAIN;
3452 break;
3453 }
3454 __set_current_state(TASK_INTERRUPTIBLE);
3455 schedule();
3456 if (signal_pending(current)) {
3457 if (!ret)
3458 ret = -ERESTARTSYS;
3459 break;
3460 }
3461#else
3462 return ret ? ret : -EAGAIN;
3463 interruptible_sleep_on(&s->midi.owait);
3464 if (signal_pending(current))
3465 return ret ? ret : -ERESTARTSYS;
3466#endif
3467 continue;
3468 }
3469 if (copy_from_user(s->midi.obuf + ptr, buffer, cnt))
3470#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3471 {
3472 if (!ret)
3473 ret = -EFAULT;
3474 break;
3475 }
3476#else
3477 return ret ? ret : -EFAULT;
3478#endif
3479 ptr = (ptr + cnt) % MIDIOUTBUF;
3480 spin_lock_irqsave(&s->lock, flags);
3481 s->midi.owr = ptr;
3482 s->midi.ocnt += cnt;
3483 spin_unlock_irqrestore(&s->lock, flags);
3484 count -= cnt;
3485 buffer += cnt;
3486 ret += cnt;
3487 spin_lock_irqsave(&s->lock, flags);
3488 cm_handle_midi(s);
3489 spin_unlock_irqrestore(&s->lock, flags);
3490 }
3491#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3492 __set_current_state(TASK_RUNNING);
3493 remove_wait_queue(&s->midi.owait, &wait);
3494#endif
3495 return ret;
3496}
3497
3498__static__ unsigned int cm_midi_poll(struct file *file, struct poll_table_struct *wait)
3499{
3500 struct cm_state *s = (struct cm_state *)file->private_data;
3501 unsigned long flags;
3502 unsigned int mask = 0;
3503
3504dprintf(("cm_midi_poll"));
3505
3506 VALIDATE_STATE(s);
3507 if (file->f_mode & FMODE_WRITE)
3508 poll_wait(file, &s->midi.owait, wait);
3509 if (file->f_mode & FMODE_READ)
3510 poll_wait(file, &s->midi.iwait, wait);
3511 spin_lock_irqsave(&s->lock, flags);
3512 if (file->f_mode & FMODE_READ) {
3513 if (s->midi.icnt > 0)
3514 mask |= POLLIN | POLLRDNORM;
3515 }
3516 if (file->f_mode & FMODE_WRITE) {
3517 if (s->midi.ocnt < MIDIOUTBUF)
3518 mask |= POLLOUT | POLLWRNORM;
3519 }
3520 spin_unlock_irqrestore(&s->lock, flags);
3521 return mask;
3522}
3523
3524__static__ int cm_midi_open(struct inode *inode, struct file *file)
3525{
3526 int minor = MINOR(inode->i_rdev);
3527 struct cm_state *s = devs;
3528 unsigned long flags;
3529
3530dprintf(("cm_midi_open"));
3531
3532 while (s && s->dev_midi != minor)
3533 s = s->next;
3534 if (!s)
3535 return -ENODEV;
3536 VALIDATE_STATE(s);
3537 file->private_data = s;
3538 /* wait for device to become free */
3539 down(&s->open_sem);
3540 while (s->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) {
3541 if (file->f_flags & O_NONBLOCK) {
3542 up(&s->open_sem);
3543 return -EBUSY;
3544 }
3545 up(&s->open_sem);
3546 interruptible_sleep_on(&s->open_wait);
3547 if (signal_pending(current))
3548 return -ERESTARTSYS;
3549 down(&s->open_sem);
3550 }
3551 spin_lock_irqsave(&s->lock, flags);
3552 if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
3553 s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
3554 s->midi.ord = s->midi.owr = s->midi.ocnt = 0;
3555 /* enable MPU-401 */
3556 maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 4);
3557 outb(0xff, s->iomidi+1); /* reset command */
3558 if (!(inb(s->iomidi+1) & 0x80))
3559 inb(s->iomidi);
3560 outb(0x3f, s->iomidi+1); /* uart command */
3561 if (!(inb(s->iomidi+1) & 0x80))
3562 inb(s->iomidi);
3563 s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
3564 init_timer(&s->midi.timer);
3565 s->midi.timer.expires = jiffies+1;
3566 s->midi.timer.data = (unsigned long)s;
3567 s->midi.timer.function = cm_midi_timer;
3568 add_timer(&s->midi.timer);
3569 }
3570 if (file->f_mode & FMODE_READ) {
3571 s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
3572 }
3573 if (file->f_mode & FMODE_WRITE) {
3574 s->midi.ord = s->midi.owr = s->midi.ocnt = 0;
3575 }
3576 spin_unlock_irqrestore(&s->lock, flags);
3577 s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE);
3578 up(&s->open_sem);
3579 MOD_INC_USE_COUNT;
3580 return 0;
3581}
3582
3583__static__ int cm_midi_release(struct inode *inode, struct file *file)
3584{
3585 struct cm_state *s = (struct cm_state *)file->private_data;
3586#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3587 DECLARE_WAITQUEUE(wait, current);
3588#else
3589 struct wait_queue wait = { current, NULL };
3590#endif
3591 unsigned long flags;
3592 unsigned count, tmo;
3593
3594dprintf(("cm_midi_release"));
3595
3596 VALIDATE_STATE(s);
3597#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3598 lock_kernel();
3599#endif
3600
3601 if (file->f_mode & FMODE_WRITE) {
3602#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3603 __set_current_state(TASK_INTERRUPTIBLE);
3604#else
3605 current->state = TASK_INTERRUPTIBLE;
3606#endif
3607 add_wait_queue(&s->midi.owait, &wait);
3608 for (;;) {
3609 spin_lock_irqsave(&s->lock, flags);
3610 count = s->midi.ocnt;
3611 spin_unlock_irqrestore(&s->lock, flags);
3612 if (count <= 0)
3613 break;
3614 if (signal_pending(current))
3615 break;
3616 if (file->f_flags & O_NONBLOCK) {
3617 remove_wait_queue(&s->midi.owait, &wait);
3618#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3619 __set_current_state(TASK_RUNNING);
3620#else
3621 current->state = TASK_RUNNING;
3622#endif
3623 return -EBUSY;
3624 }
3625 tmo = (count * HZ) / 3100;
3626
3627 if (!schedule_timeout(tmo ? : 1) && tmo)
3628 printk(KERN_DEBUG "cm: midi timed out??\n");
3629 }
3630 remove_wait_queue(&s->midi.owait, &wait);
3631#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
3632 __set_current_state(TASK_RUNNING);
3633#else
3634 current->state = TASK_RUNNING;
3635#endif
3636 }
3637 down(&s->open_sem);
3638 s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE);
3639 spin_lock_irqsave(&s->lock, flags);
3640 if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
3641 del_timer(&s->midi.timer);
3642 outb(0xff, s->iomidi+1); /* reset command */
3643 if (!(inb(s->iomidi+1) & 0x80))
3644 inb(s->iomidi);
3645 /* disable MPU-401 */
3646 maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~4, 0);
3647 }
3648 spin_unlock_irqrestore(&s->lock, flags);
3649 up(&s->open_sem);
3650 wake_up(&s->open_wait);
3651#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3652 unlock_kernel();
3653#else
3654 MOD_DEC_USE_COUNT;
3655#endif
3656 return 0;
3657}
3658
3659#ifndef TARGET_OS2
3660 static /*const*/ struct file_operations cm_midi_fops = {
3661 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3662 owner: THIS_MODULE,
3663 #endif
3664 llseek: cm_llseek,
3665 read: cm_midi_read,
3666 write: cm_midi_write,
3667 poll: cm_midi_poll,
3668 open: cm_midi_open,
3669 release: cm_midi_release,
3670 };
3671#else
3672 static /*const*/ struct file_operations cm_midi_fops = {
3673 cm_llseek, // llseek
3674 cm_midi_read, // read
3675 cm_midi_write, // write
3676 NULL, // readdir
3677 cm_midi_poll, // poll
3678 NULL, // ioctl
3679 NULL, // mmap
3680 cm_midi_open, // open
3681 NULL, // flush
3682 cm_midi_release // release
3683 };
3684#endif
3685
3686#endif
3687
3688/* --------------------------------------------------------------------- */
3689
3690#ifdef CONFIG_SOUND_CMPCI_FM
3691__static__ int cm_dmfm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
3692{
3693 static const unsigned char op_offset[18] = {
3694 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
3695 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
3696 0x10, 0x11, 0x12, 0x13, 0x14, 0x15
3697 };
3698 struct cm_state *s = (struct cm_state *)file->private_data;
3699 struct dm_fm_voice v;
3700 struct dm_fm_note n;
3701 struct dm_fm_params p;
3702 unsigned int io;
3703 unsigned int regb;
3704
3705dprintf(("cm_dmfm_ioctl: %x", cmd));
3706
3707 switch (cmd) {
3708 case FM_IOCTL_RESET:
3709 for (regb = 0xb0; regb < 0xb9; regb++) {
3710 outb(regb, s->iosynth);
3711 outb(0, s->iosynth+1);
3712 outb(regb, s->iosynth+2);
3713 outb(0, s->iosynth+3);
3714 }
3715 return 0;
3716
3717 case FM_IOCTL_PLAY_NOTE:
3718 if (copy_from_user(&n, (void *)arg, sizeof(n)))
3719 return -EFAULT;
3720 if (n.voice >= 18)
3721 return -EINVAL;
3722 if (n.voice >= 9) {
3723 regb = n.voice - 9;
3724 io = s->iosynth+2;
3725 } else {
3726 regb = n.voice;
3727 io = s->iosynth;
3728 }
3729 outb(0xa0 + regb, io);
3730 outb(n.fnum & 0xff, io+1);
3731 outb(0xb0 + regb, io);
3732 outb(((n.fnum >> 8) & 3) | ((n.octave & 7) << 2) | ((n.key_on & 1) << 5), io+1);
3733 return 0;
3734
3735 case FM_IOCTL_SET_VOICE:
3736 if (copy_from_user(&v, (void *)arg, sizeof(v)))
3737 return -EFAULT;
3738 if (v.voice >= 18)
3739 return -EINVAL;
3740 regb = op_offset[v.voice];
3741 io = s->iosynth + ((v.op & 1) << 1);
3742 outb(0x20 + regb, io);
3743 outb(((v.am & 1) << 7) | ((v.vibrato & 1) << 6) | ((v.do_sustain & 1) << 5) |
3744 ((v.kbd_scale & 1) << 4) | (v.harmonic & 0xf), io+1);
3745 outb(0x40 + regb, io);
3746 outb(((v.scale_level & 0x3) << 6) | (v.volume & 0x3f), io+1);
3747 outb(0x60 + regb, io);
3748 outb(((v.attack & 0xf) << 4) | (v.decay & 0xf), io+1);
3749 outb(0x80 + regb, io);
3750 outb(((v.sustain & 0xf) << 4) | (v.release & 0xf), io+1);
3751 outb(0xe0 + regb, io);
3752 outb(v.waveform & 0x7, io+1);
3753 if (n.voice >= 9) {
3754 regb = n.voice - 9;
3755 io = s->iosynth+2;
3756 } else {
3757 regb = n.voice;
3758 io = s->iosynth;
3759 }
3760 outb(0xc0 + regb, io);
3761 outb(((v.right & 1) << 5) | ((v.left & 1) << 4) | ((v.feedback & 7) << 1) |
3762 (v.connection & 1), io+1);
3763 return 0;
3764
3765 case FM_IOCTL_SET_PARAMS:
3766 if (copy_from_user(&p, (void *)arg, sizeof(p)))
3767 return -EFAULT;
3768 outb(0x08, s->iosynth);
3769 outb((p.kbd_split & 1) << 6, s->iosynth+1);
3770 outb(0xbd, s->iosynth);
3771 outb(((p.am_depth & 1) << 7) | ((p.vib_depth & 1) << 6) | ((p.rhythm & 1) << 5) | ((p.bass & 1) << 4) |
3772 ((p.snare & 1) << 3) | ((p.tomtom & 1) << 2) | ((p.cymbal & 1) << 1) | (p.hihat & 1), s->iosynth+1);
3773 return 0;
3774
3775 case FM_IOCTL_SET_OPL:
3776 outb(4, s->iosynth+2);
3777 outb(arg, s->iosynth+3);
3778 return 0;
3779
3780 case FM_IOCTL_SET_MODE:
3781 outb(5, s->iosynth+2);
3782 outb(arg & 1, s->iosynth+3);
3783 return 0;
3784
3785 default:
3786 return -EINVAL;
3787 }
3788}
3789
3790__static__ int cm_dmfm_open(struct inode *inode, struct file *file)
3791{
3792 int minor = MINOR(inode->i_rdev);
3793 struct cm_state *s = devs;
3794
3795dprintf(("cm_dmfm_open"));
3796
3797 while (s && s->dev_dmfm != minor)
3798 s = s->next;
3799 if (!s)
3800 return -ENODEV;
3801 VALIDATE_STATE(s);
3802 file->private_data = s;
3803 /* wait for device to become free */
3804 down(&s->open_sem);
3805 while (s->open_mode & FMODE_DMFM) {
3806 if (file->f_flags & O_NONBLOCK) {
3807 up(&s->open_sem);
3808 return -EBUSY;
3809 }
3810 up(&s->open_sem);
3811 interruptible_sleep_on(&s->open_wait);
3812 if (signal_pending(current))
3813 return -ERESTARTSYS;
3814 down(&s->open_sem);
3815 }
3816 /* init the stuff */
3817 outb(1, s->iosynth);
3818 outb(0x20, s->iosynth+1); /* enable waveforms */
3819 outb(4, s->iosynth+2);
3820 outb(0, s->iosynth+3); /* no 4op enabled */
3821 outb(5, s->iosynth+2);
3822 outb(1, s->iosynth+3); /* enable OPL3 */
3823 s->open_mode |= FMODE_DMFM;
3824 up(&s->open_sem);
3825 MOD_INC_USE_COUNT;
3826 return 0;
3827}
3828
3829__static__ int cm_dmfm_release(struct inode *inode, struct file *file)
3830{
3831 struct cm_state *s = (struct cm_state *)file->private_data;
3832 unsigned int regb;
3833
3834dprintf(("cm_dmfm_release"));
3835
3836 VALIDATE_STATE(s);
3837#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3838 lock_kernel();
3839#endif
3840 down(&s->open_sem);
3841 s->open_mode &= ~FMODE_DMFM;
3842 for (regb = 0xb0; regb < 0xb9; regb++) {
3843 outb(regb, s->iosynth);
3844 outb(0, s->iosynth+1);
3845 outb(regb, s->iosynth+2);
3846 outb(0, s->iosynth+3);
3847 }
3848 up(&s->open_sem);
3849 wake_up(&s->open_wait);
3850#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3851 unlock_kernel();
3852#else
3853 MOD_DEC_USE_COUNT;
3854#endif
3855 return 0;
3856}
3857
3858#ifndef TARGET_OS2
3859 static /*const*/ struct file_operations cm_dmfm_fops = {
3860 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
3861 owner: THIS_MODULE,
3862 #endif
3863 llseek: cm_llseek,
3864 ioctl: cm_dmfm_ioctl,
3865 open: cm_dmfm_open,
3866 release: cm_dmfm_release,
3867 };
3868
3869#else
3870 static /*const*/ struct file_operations cm_mixer_fops = {
3871 cm_llseek, // llseek
3872 NULL, // read
3873 NULL, // write
3874 NULL, // readdir
3875 NULL, // poll
3876 cm_dmfm_ioctl, // ioctl
3877 NULL, // mmap
3878 cm_dmfm_open, // open
3879 NULL, // flush
3880 cm_dmfm_release // release
3881 };
3882
3883#endif
3884
3885#endif /* CONFIG_SOUND_CMPCI_FM */
3886
3887/* --------------------------------------------------------------------- */
3888
3889/* maximum number of devices */
3890
3891//Rudi:
3892//#define NR_DEVICE 5
3893
3894#define NR_DEVICE 1
3895
3896
3897#if 0
3898static int reverb[NR_DEVICE] = { 0, };
3899
3900static int wavetable[NR_DEVICE] = { 0, };
3901#endif
3902
3903/* --------------------------------------------------------------------- */
3904
3905static struct initvol {
3906 int mixch;
3907 int vol;
3908} initvol[] __initdata = {
3909 { SOUND_MIXER_WRITE_CD, 0x0000 },
3910 { SOUND_MIXER_WRITE_LINE, 0x0000 },
3911 { SOUND_MIXER_WRITE_MIC, 0x0000 },
3912 { SOUND_MIXER_WRITE_LINE1, 0x0000 },
3913 { SOUND_MIXER_WRITE_SYNTH, 0x0000 },
3914 { SOUND_MIXER_WRITE_VOLUME, 0x4f4f },
3915 { SOUND_MIXER_WRITE_PCM, 0x0000 },
3916 { SOUND_MIXER_WRITE_SPEAKER, 0x0000 }
3917};
3918
3919/* check chip version and capability */
3920__static__ int query_chip(struct cm_state *s)
3921{
3922 int ChipVersion = -1;
3923 unsigned char RegValue;
3924
3925 // check reg 0Ch, bit 24-31
3926 RegValue = inb(s->iobase + CODEC_CMI_INT_HLDCLR + 3);
3927 if (RegValue == 0) {
3928 // check reg 08h, bit 24-28
3929 RegValue = inb(s->iobase + CODEC_CMI_CHFORMAT + 3) & 0x1f;
3930 if (RegValue == 0) {
3931 ChipVersion = 33;
3932 s->capability |= CAN_DUAL_DAC | CAN_AC3_SW;
3933 } else {
3934 ChipVersion = 37;
3935 s->capability |= CAN_DUAL_DAC | CAN_AC3_HW;
3936 }
3937
3938 s->max_channels = 4;
3939 } else {
3940 // check reg 0Ch, bit 26
3941 if (RegValue & (1 << (26-24))) {
3942 ChipVersion = 39; // 4 or 6 channels
3943 s->max_channels = ( RegValue & (1 << (24-24)) ) ? 6 : 4;
3944 } else if (RegValue & (1 << (29-29))) {
3945 ChipVersion = 68; // 8 channels
3946 s->max_channels = 8;
3947 } else /*if (RegValue & (1 << (27-27)))*/ {
3948 ChipVersion = 55; // 6 channels
3949 s->max_channels = 6;
3950 }
3951
3952
3953 s->capability |= CAN_DUAL_DAC |
3954#ifndef FORCE_DUAL_DAC
3955 CAN_MULTI_CH_HW |
3956#endif
3957 CAN_AC3_HW;
3958 }
3959
3960
3961// AC3HACK
3962s->capability = (s->capability & ~CAN_AC3_HW) | CAN_AC3_SW;
3963
3964
3965
3966 // still limited to number of speakers
3967 if (s->max_channels > s->speakers)
3968 s->max_channels = s->speakers;
3969
3970 return ChipVersion;
3971}
3972
3973#if defined(CONFIG_SOUND_CMPCI_MIDI) || defined(TARGET_OS2)
3974static int mpu_io = CONFIG_SOUND_CMPCI_MPUIO;
3975#else
3976static int mpu_io = 0;
3977#endif
3978
3979#ifdef CONFIG_SOUND_CMPCI_FM
3980static int fm_io = CONFIG_SOUND_CMPCI_FMIO;
3981#else
3982 #ifdef TARGET_OS2
3983 static int fm_io = CONFIG_SOUND_CMPCI_FMIO;
3984 #else
3985 static int fm_io = 0;
3986 #endif
3987#endif
3988
3989#ifdef CONFIG_SOUND_CMPCI_SPDIFINVERSE
3990/*static*/ int spdif_inverse = 1;
3991#else
3992/*static*/ int spdif_inverse = 0;
3993#endif
3994
3995#ifdef CONFIG_SOUND_CMPCI_SPDIFLOOP
3996/*static*/ int spdif_loop = 1;
3997#else
3998/*static*/ int spdif_loop = 0;
3999#endif
4000
4001#ifdef CONFIG_SOUND_CMPCI_SPEAKERS
4002static int speakers = CONFIG_SOUND_CMPCI_SPEAKERS;
4003#else
4004static int speakers = 2;
4005#endif
4006
4007#ifdef CONFIG_SOUND_CMPCI_LINE_REAR
4008/*static*/ int use_line_as_rear = 1;
4009#else
4010/*static*/ int use_line_as_rear = 0;
4011#endif
4012
4013#ifdef CONFIG_SOUND_CMPCI_LINE_BASS
4014/*static*/ int use_line_as_bass = 1;
4015#else
4016/*static*/ int use_line_as_bass = 0;
4017#endif
4018
4019#ifdef CONFIG_SOUND_CMPCI_PCTEL
4020static int modem = 1;
4021#else
4022static int modem = 0;
4023#endif
4024
4025#ifdef CONFIG_SOUND_CMPCI_JOYSTICK
4026/*static*/ int joystick = 1;
4027#else
4028/*static*/ int joystick = 0;
4029#endif
4030
4031#ifdef CONFIG_SOUND_CMPCI_SPDIF5V
4032/*static*/ int spdif_5v = 1;
4033/*static*/ int spdif_src = 0;
4034#else
4035/*static*/ int spdif_5v = 0;
4036/*static*/ int spdif_src = 1;
4037#endif
4038
4039int spdif_copyright = 0;
4040int spdif_enable = 0;
4041int mic_boost = 0;
4042
4043
4044MODULE_PARM(mpu_io, "i");
4045MODULE_PARM(fm_io, "i");
4046MODULE_PARM(spdif_inverse, "i");
4047MODULE_PARM(spdif_loop, "i");
4048MODULE_PARM(speakers, "i");
4049MODULE_PARM(use_line_as_rear, "i");
4050MODULE_PARM(use_line_as_bass, "i");
4051MODULE_PARM(modem, "i");
4052MODULE_PARM(joystick, "i");
4053MODULE_PARM_DESC(mpu_io, "(0x330, 0x320, 0x310, 0x300) Base of MPU-401, 0 to disable");
4054MODULE_PARM_DESC(fm_io, "(0x388, 0x3C8, 0x3E0) Base of OPL3, 0 to disable");
4055MODULE_PARM_DESC(spdif_inverse, "(1/0) Invert S/PDIF-in signal");
4056MODULE_PARM_DESC(spdif_loop, "(1/0) Route S/PDIF-in to S/PDIF-out directly");
4057MODULE_PARM_DESC(speakers, "(2-6) Number of speakers you connect");
4058MODULE_PARM_DESC(use_line_as_rear, "(1/0) Use line-in jack as rear-out");
4059MODULE_PARM_DESC(use_line_as_bass, "(1/0) Use line-in jack as bass/center");
4060MODULE_PARM_DESC(modem, "(1/0) Use HSP modem, still need PCTel modem driver");
4061MODULE_PARM_DESC(joystick, "(1/0) Enable joystick interface, still need joystick driver");
4062
4063
4064void initialize_chip(struct pci_dev *pcidev)
4065{
4066 struct cm_state *s;
4067 int i, val;
4068#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
4069 mm_segment_t fs;
4070#endif
4071#if defined(CONFIG_SOUND_CMPCI_MIDI) || defined(TARGET_OS2)
4072 unsigned char reg_mask = 0;
4073#endif
4074 struct {
4075 unsigned short deviceid;
4076 char *devicename;
4077 } devicetable[] =
4078 {
4079 { PCI_DEVICE_ID_CMEDIA_CM8338A, "CM8338A" },
4080 { PCI_DEVICE_ID_CMEDIA_CM8338B, "CM8338B" },
4081 { PCI_DEVICE_ID_CMEDIA_CM8738, "CM8738" },
4082 { PCI_DEVICE_ID_CMEDIA_CM8738B, "CM8738B" },
4083 };
4084 char *devicename = "unknown";
4085 {
4086#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4087 if (pci_enable_device(pcidev))
4088 return;
4089#endif
4090 if (pcidev->irq == 0)
4091 return;
4092 if (!(s = kmalloc(sizeof(struct cm_state), GFP_KERNEL))) {
4093 printk(KERN_WARNING "cm: out of memory\n");
4094 return;
4095 }
4096 /* search device name */
4097 for (i = 0; i < sizeof(devicetable) / sizeof(devicetable[0]); i++) {
4098 if (devicetable[i].deviceid == pcidev->device)
4099 {
4100 devicename = devicetable[i].devicename;
4101 break;
4102 }
4103 }
4104
4105 memset(s, 0, sizeof(struct cm_state));
4106
4107#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
4108 init_waitqueue_head(&s->dma_adc.wait);
4109 init_waitqueue_head(&s->dma_dac.wait);
4110 init_waitqueue_head(&s->open_wait);
4111 init_waitqueue_head(&s->midi.iwait);
4112 init_waitqueue_head(&s->midi.owait);
4113 init_MUTEX(&s->open_sem);
4114#else
4115 init_waitqueue(&s->dma_adc.wait);
4116 init_waitqueue(&s->dma_dac.wait);
4117 init_waitqueue(&s->open_wait);
4118 init_waitqueue(&s->midi.iwait);
4119 init_waitqueue(&s->midi.owait);
4120 s->open_sem = MUTEX;
4121#endif
4122 spin_lock_init(&s->lock);
4123 s->magic = CM_MAGIC;
4124#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4125 s->iobase = pci_resource_start(pcidev, 0);
4126#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
4127 s->iobase = pcidev->resource[0].start;
4128#else
4129 s->iobase = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
4130#endif
4131
4132#ifndef TARGET_OS2
4133 /* range check */
4134 if (s->iobase == 0)
4135 return;
4136 if (speakers < 2)
4137 speakers = 2;
4138 else if (speakers > 6)
4139 speakers = 6;
4140#endif
4141
4142 s->iosynth = fm_io;
4143 s->iomidi = mpu_io;
4144 s->speakers = speakers;
4145 s->irq = pcidev->irq;
4146
4147#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4148 if (!request_region(s->iobase, CM_EXTENT_CODEC, "cmpci")) {
4149#else
4150 if (check_region(s->iobase, CM_EXTENT_CODEC)) {
4151#endif
4152 printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iobase, s->iobase+CM_EXTENT_CODEC-1);
4153 goto err_region5;
4154 }
4155#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
4156 request_region(s->iobase, CM_EXTENT_CODEC, "cmpci");
4157#endif
4158
4159
4160#if defined(CONFIG_SOUND_CMPCI_MIDI) || defined(TARGET_OS2)
4161 /* disable MPU-401 */
4162 maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x04, 0);
4163 if (s->iomidi) {
4164#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4165 if (!request_region(s->iomidi, CM_EXTENT_MIDI, "cmpci Midi")) {
4166#else
4167 if (check_region(s->iomidi, CM_EXTENT_MIDI)) {
4168#endif
4169 printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iomidi, s->iomidi+CM_EXTENT_MIDI-1);
4170 s->iomidi = 0;
4171 } else {
4172 /* set IO based at 0x330 */
4173 switch (s->iomidi) {
4174 case 0x330:
4175 reg_mask = 0x00;
4176 break;
4177 case 0x320:
4178 reg_mask = 0x20;
4179 break;
4180 case 0x310:
4181 reg_mask = 0x40;
4182 break;
4183 case 0x300:
4184 reg_mask = 0x60;
4185 break;
4186 default:
4187 s->iomidi = 0;
4188 break;
4189 }
4190
4191 /* enable MPU-401 */
4192 if (s->iomidi) {
4193 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0x60, reg_mask);
4194//Rudi: enable on open ! maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04);
4195
4196#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
4197 request_region(s->iomidi, CM_EXTENT_MIDI, "cmpci MPU");
4198#endif
4199 }
4200 }
4201 }
4202#endif
4203
4204
4205#if definded(CONFIG_SOUND_CMPCI_FM) || defined(TARGET_OS2)
4206 /* disable FM */
4207 maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~8, 0);
4208 if (s->iosynth) {
4209#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4210 if (!request_region(s->iosynth, CM_EXTENT_SYNTH, "cmpci FM")) {
4211#else
4212 if (check_region(s->iosynth, CM_EXTENT_SYNTH)) {
4213#endif
4214 printk(KERN_ERR "cm: io ports %#x-%#x in use\n", s->iosynth, s->iosynth+CM_EXTENT_SYNTH-1);
4215 s->iosynth = 0;
4216 } else {
4217 /* set IO based at 0x388 */
4218 switch (s->iosynth) {
4219 case 0x388:
4220 reg_mask = 0;
4221 break;
4222 case 0x3C8:
4223 reg_mask = 0x01;
4224 break;
4225 case 0x3E0:
4226 reg_mask = 0x02;
4227 break;
4228 case 0x3E8:
4229 reg_mask = 0x03;
4230 break;
4231 default:
4232 s->iosynth = 0;
4233 break;
4234 }
4235 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0x03, reg_mask);
4236 /* enable FM */
4237 if (s->iosynth) {
4238 maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, 8);
4239#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
4240 request_region(s->iosynth, CM_EXTENT_SYNTH, "cmpci FM");
4241#endif
4242 }
4243 }
4244 }
4245#endif
4246 /* enable joystick */
4247 maskb(s->iobase + CODEC_CMI_FUNCTRL1,
4248 ~0x02, ( joystick ) ? 0x02 : 0x00);
4249
4250 /* initialize codec registers */
4251 outb(0, s->iobase + CODEC_CMI_INT_HLDCLR + 2); /* disable ints */
4252 outb(0, s->iobase + CODEC_CMI_FUNCTRL0 + 2); /* disable channels */
4253
4254 /* reset mixer */
4255 wrmixer(s, DSP_MIX_DATARESETIDX, 0);
4256
4257 /* request irq */
4258 if (request_irq(s->irq, cm_interrupt, SA_SHIRQ, "cmpci", s)) {
4259 printk(KERN_ERR "cm: irq %u in use\n", s->irq);
4260 goto err_irq;
4261 }
4262 printk(KERN_INFO "cm: found %s adapter at io %#06x irq %u\n",
4263 devicename, s->iobase, s->irq);
4264 /* register devices */
4265 if ((s->dev_audio = register_sound_dsp(&cm_audio_fops, -1)) < 0)
4266 goto err_dev1;
4267 if ((s->dev_mixer = register_sound_mixer(&cm_mixer_fops, -1)) < 0)
4268 goto err_dev2;
4269#ifdef CONFIG_SOUND_CMPCI_MIDI
4270 if ((s->dev_midi = register_sound_midi(&cm_midi_fops, -1)) < 0)
4271 goto err_dev3;
4272#endif
4273#ifdef CONFIG_SOUND_CMPCI_FM
4274 if ((s->dev_dmfm = register_sound_special(&cm_dmfm_fops, 15 /* ?? */)) < 0)
4275 goto err_dev4;
4276#endif
4277
4278 pci_set_master(pcidev); /* enable bus mastering */
4279
4280 /* set mixer output */
4281 frobindir(s, DSP_MIX_OUTMIXIDX, 0x1f, 0x1f);
4282 enable_aux(s, 1, 0); // Rudi: enable aux in
4283 enable_aux(s, 0, 1); // Rudi: disable aux record
4284 enable_digital(s, 0, 0); // Rudi: disable SPDIF in (monitor)
4285 enable_digital(s, 0, 1); // Rudi: disable SPDIF record
4286
4287
4288#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
4289 fs = get_fs();
4290 set_fs(KERNEL_DS);
4291#endif
4292 /* set mixer input */
4293 val = SOUND_MASK_LINE | SOUND_MASK_SYNTH |// SOUND_MASK_PCM |
4294 SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE1;
4295
4296#if !defined(TARGET_OS2) || defined(KEE)
4297 mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
4298#else
4299 mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC,
4300 (unsigned long)__StackToFlat((unsigned long)&val));
4301#endif
4302 for (i = 0; i < sizeof(initvol) / sizeof(initvol[0]); i++) {
4303 val = initvol[i].vol;
4304#if !defined(TARGET_OS2) || defined(KEE)
4305 mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
4306#else
4307 mixer_ioctl(s, initvol[i].mixch,
4308 (unsigned long)__StackToFlat((unsigned long)&val));
4309#endif
4310 }
4311#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
4312 set_fs(fs);
4313#endif
4314
4315 /* use channel 0 for playback, channel 1 for record */
4316 maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~0x01, 0x02);
4317
4318 s->deviceid = pcidev->device;
4319 if (pcidev->device >= PCI_DEVICE_ID_CMEDIA_CM8738) {
4320 /* chip version and hw capability check */
4321 s->chip_version = query_chip(s);
4322 printk(KERN_INFO "cm: chip version = 0%d\n", s->chip_version);
4323
4324#ifdef TARGET_OS2
4325 if( spdif_5v ) s->status |= DO_SPDIF_OUT_5V;
4326 if( spdif_src ) s->status |= DO_SPDIF_INPUT2;
4327 if( spdif_inverse ) s->status |= DO_SPDIF_INVERSE;
4328 if( spdif_copyright ) s->status |= DO_SPDIF_COPYRIGHT;
4329 if( spdif_loop ) s->status |= DO_SPDIF_LOOP;
4330 else if( spdif_enable ) s->status |= DO_SPDIF_OUT_ENABLE;
4331 if( mic_boost ) s->status |= DO_MIC_BOOST;
4332
4333 if( use_line_as_rear ) {
4334 s->capability |= CAN_LINE_AS_REAR;
4335 s->status |= DO_LINE_AS_REAR;
4336 }
4337
4338 if( use_line_as_bass && s->chip_version >= 39 ) {
4339 s->capability |= CAN_LINE_AS_BASS;
4340 s->status |= DO_LINE_AS_BASS;
4341 }
4342
4343 set_device_state(s);
4344
4345#else
4346 s->modem = modem;
4347 if (modem) {
4348 /* enable FLINKON and disable FLINKOFF */
4349 maskb(s->iobase + CODEC_CMI_MISC_CTRL, ~0x40, 0x80);
4350 printk(KERN_INFO "cm: modem function supported\n");
4351 }
4352
4353 /* set SPDIF-in inverse before enable SPDIF loop */
4354 if (spdif_inverse) {
4355 /* turn on spdif-in inverse */
4356 maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0, 1);
4357 printk(KERN_INFO "cm: Inverse SPDIF-in\n");
4358 } else {
4359 /* turn off spdif-in inverse */
4360 maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~1, 0);
4361 }
4362
4363 /* enable SPDIF loop */
4364 if (spdif_loop) {
4365 s->status |= DO_SPDIF_LOOP;
4366 /* turn on spdif-in to spdif-out */
4367 maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x80);
4368 printk(KERN_INFO "cm: Enable SPDIF loop\n");
4369 } else {
4370 s->status &= ~DO_SPDIF_LOOP;
4371 /* turn off spdif-in to spdif-out */
4372 maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x80, 0);
4373 }
4374
4375 if (use_line_as_rear) {
4376 s->capability |= CAN_LINE_AS_REAR;
4377 s->status |= DO_LINE_AS_REAR;
4378 maskb(s->iobase + CODEC_CMI_MIXER1, ~0, 0x20);
4379 } else
4380 maskb(s->iobase + CODEC_CMI_MIXER1, ~0x20, 0);
4381
4382 if (s->chip_version >= 39) {
4383 if (use_line_as_bass) {
4384 s->capability |= CAN_LINE_AS_BASS;
4385 s->status |= DO_LINE_AS_BASS;
4386 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 1, ~0, 0x60);
4387 } else
4388 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 1, ~0x60, 0);
4389 }
4390#endif
4391
4392 // Rudi: enable 4 speaker mode (analog duplicate)
4393 if (s->speakers > 2)
4394 maskb(s->iobase + CODEC_CMI_MISC_CTRL + 3, ~0, 0x04);
4395 } else {
4396 /* 8338 will fall here */
4397 s->max_channels = 2;
4398 }
4399
4400 /* queue it for later freeing */
4401 s->next = devs;
4402 devs = s;
4403 return;
4404
4405#ifdef CONFIG_SOUND_CMPCI_FM
4406 unregister_sound_special(s->dev_dmfm);
4407 err_dev4:
4408#endif
4409#ifdef CONFIG_SOUND_CMPCI_MIDI
4410 unregister_sound_midi(s->dev_midi);
4411 err_dev3:
4412#endif
4413#if defined(CONFIG_SOUND_CMPCI_MIDI) || defined(CONFIG_SOUND_CMPCI_FM)
4414 unregister_sound_mixer(s->dev_mixer);
4415#endif
4416
4417 err_dev2:
4418 unregister_sound_dsp(s->dev_audio);
4419 err_dev1:
4420 printk(KERN_ERR "cm: cannot register misc device\n");
4421 free_irq(s->irq, s);
4422 err_irq:
4423#ifdef CONFIG_SOUND_CMPCI_FM
4424 if (s->iosynth) release_region(s->iosynth, CM_EXTENT_SYNTH);
4425#endif
4426#ifdef CONFIG_SOUND_CMPCI_MIDI
4427 if (s->iomidi) release_region(s->iomidi, CM_EXTENT_MIDI);
4428#endif
4429 release_region(s->iobase, CM_EXTENT_CODEC);
4430 err_region5:
4431#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4432 kfree(s);
4433#else
4434 kfree_s(s, sizeof(struct cm_state));
4435#endif
4436 }
4437
4438#if CONFIG_WAVETABLE
4439 if (!devs) {
4440 if (wavetable_mem)
4441 free_pages(wavetable_mem, 20-PAGE_SHIFT);
4442 return;
4443 }
4444#endif
4445 return;
4446}
4447
4448#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4449__static__ int __init init_cmpci(void)
4450#else
4451#ifdef MODULE
4452int __init init_module(void)
4453#else
4454int __init init_cmpci(void)
4455#endif
4456#endif
4457{
4458 struct pci_dev *pcidev = NULL;
4459 int index = 0;
4460
4461#ifdef CONFIG_PCI
4462 if (!pci_present()) /* No PCI bus in this machine! */
4463#endif
4464 return -ENODEV;
4465 printk(KERN_INFO "cm: version $Revision: 5.64 $ time " __TIME__ " " __DATE__ "\n");
4466#if CONFIG_WAVETABLE
4467 if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
4468 printk(KERN_INFO "cm: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
4469#endif
4470 while (index < NR_DEVICE && (
4471 (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738B, pcidev)))) {
4472 initialize_chip(pcidev);
4473 index++;
4474 }
4475 while (index < NR_DEVICE && (
4476 (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738, pcidev)))) {
4477 initialize_chip(pcidev);
4478 index++;
4479 }
4480 while (index < NR_DEVICE && (
4481 (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B, pcidev)))) {
4482 initialize_chip(pcidev);
4483 index++;
4484 }
4485 while (index < NR_DEVICE && (
4486 (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A, pcidev)))) {
4487 initialize_chip(pcidev);
4488 index++;
4489 }
4490 return 0;
4491}
4492
4493/* --------------------------------------------------------------------- */
4494
4495MODULE_AUTHOR("ChenLi Tien, cltien@cmedia.com.tw");
4496MODULE_DESCRIPTION("CM8x38 Audio Driver");
4497
4498#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4499__static__ void __exit cleanup_cmpci(void)
4500#else
4501void cleanup_module(void)
4502#endif
4503{
4504 struct cm_state *s;
4505
4506 while ((s = devs)) {
4507 devs = devs->next;
4508 outb(0, s->iobase + CODEC_CMI_INT_HLDCLR + 2); /* disable ints */
4509 synchronize_irq();
4510 outb(0, s->iobase + CODEC_CMI_FUNCTRL0 + 2); /* disable channels */
4511 free_irq(s->irq, s);
4512#ifdef FIXEDDMA
4513 dealloc_dmabuf(&s->dma_dac);
4514 dealloc_dmabuf(&s->dma_adc);
4515#endif
4516
4517 /* reset mixer */
4518 wrmixer(s, DSP_MIX_DATARESETIDX, 0);
4519
4520 release_region(s->iobase, CM_EXTENT_CODEC);
4521#ifdef CONFIG_SOUND_CMPCI_MIDI
4522 if (s->iomidi) release_region(s->iomidi, CM_EXTENT_MIDI);
4523#endif
4524#ifdef CONFIG_SOUND_CMPCI_FM
4525 if (s->iosynth) release_region(s->iosynth, CM_EXTENT_SYNTH);
4526#endif
4527 unregister_sound_dsp(s->dev_audio);
4528 unregister_sound_mixer(s->dev_mixer);
4529#ifdef CONFIG_SOUND_CMPCI_MIDI
4530 unregister_sound_midi(s->dev_midi);
4531#endif
4532#ifdef CONFIG_SOUND_CMPCI_FM
4533 unregister_sound_special(s->dev_dmfm);
4534#endif
4535#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4536 kfree(s);
4537#else
4538 kfree_s(s, sizeof(struct cm_state));
4539#endif
4540 }
4541#if CONFIG_WAVETABLE
4542 if (wavetable_mem)
4543 free_pages(wavetable_mem, 20-PAGE_SHIFT);
4544#endif
4545 printk(KERN_INFO "cm: unloading\n");
4546}
4547
4548#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
4549module_init(init_cmpci);
4550module_exit(cleanup_cmpci);
4551#endif
4552
4553
4554
4555#ifdef TARGET_OS2
4556
4557void set_device_state(struct cm_state *s)
4558{
4559 unsigned long val, flags;
4560
4561 spin_lock_irqsave(&s->lock, flags);
4562
4563 // line as rear
4564 if( s->capability & CAN_LINE_AS_REAR ) {
4565 maskb(s->iobase + CODEC_CMI_MIXER1,
4566 ~0x20, ( s->status & DO_LINE_AS_REAR ) ? 0x20 : 0x00);
4567 }
4568
4569 // line as bass
4570 if( s->capability & CAN_LINE_AS_BASS ) {
4571 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 1,
4572 ~0x60, ( s->status & DO_LINE_AS_BASS ) ? 0x60 : 0x00);
4573 }
4574
4575 // S/P DIF inverse
4576 if (s->chip_version >= 39) {
4577 maskb(s->iobase + CODEC_CMI_CHFORMAT,
4578 ~0x80, ( s->status & DO_SPDIF_INVERSE ) ? 0x80 : 0x00);
4579 } else {
4580 maskb(s->iobase + CODEC_CMI_CHFORMAT + 2,
4581 ~0x01, ( s->status & DO_SPDIF_INVERSE ) ? 0x00 : 0x01);
4582 }
4583
4584 // S/P DIF copyright
4585 maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 2,
4586 ~0x40, ( s->status & DO_SPDIF_COPYRIGHT ) ? 0x40 : 0x00);
4587
4588 // S/P DIF loop (external)
4589 maskb(s->iobase + CODEC_CMI_FUNCTRL1,
4590 ~0x80, ( s->status & DO_SPDIF_LOOP ) ? 0x80 : 0x00);
4591
4592 // S/P DIF output level and input source
4593 val = 0;
4594 if( s->status & DO_POWER_DOWN ) val |= 0x80000000;
4595 if( s->status & DO_SPDIF_INPUT2 ) val |= 0x00000100;
4596 if( !(s->status & DO_SPDIF_OUT_5V) ) val |= 0x02000000;
4597 maskl(s->iobase + CODEC_CMI_MISC_CTRL, ~0x82000100, val);
4598
4599 // S/P DIF monitor
4600 if( !(s->status & DO_SPDIF_OUT) ) {
4601 enable_digital(s, s->status & DO_SPDIF_MONITOR, 0);
4602 }
4603
4604 // Mic boost
4605 maskb(s->iobase + CODEC_CMI_MIXER2,
4606 ~0x01, ( s->status & DO_MIC_BOOST ) ? 0x00 : 0x01);
4607 // Mic record boost
4608 frobindir(s, CODEC_CMI_EXT_REG,
4609 ~0x01, ( s->status & DO_MIC_BOOST ) ? 0x01 : 0x00);
4610
4611
4612 spin_unlock_irqrestore(&s->lock, flags);
4613
4614 if( !(s->status & DO_DUAL_DAC) ) set_spdifout(s, s->ratedac);
4615}
4616
4617
4618unsigned long OSS32_DevEscape(unsigned long uChipNo, unsigned long uCommand,
4619 unsigned long uParam1, unsigned long uParam2)
4620{
4621 struct cm_state *s = devs;
4622
4623 while( s ) {
4624 if( uChipNo-- == 0 )
4625 switch( uCommand ) {
4626 case 0x00: return s->deviceid | (PCI_VENDOR_ID_CMEDIA << 16);
4627 case 0x01: return s->iobase;
4628 case 0x02: return s->irq;
4629 case 0x03: return s->chip_version;
4630 case 0x04: return s->capability;
4631 case 0xff: if( uParam1 | uParam2 ) {
4632 s->status = (s->status & ~uParam2) | uParam1;
4633 set_device_state(s);
4634 }
4635 return s->status;
4636
4637 default: return -1;
4638 }
4639 s = s->next;
4640 }
4641
4642 return -1;
4643}
4644
4645unsigned long OSS32_StreamMidiWrite(unsigned long streamid,
4646 unsigned long midiByte)
4647{
4648 struct cm_state *s = (struct cm_state *)streamid;
4649
4650 if( !(inb(s->iomidi+1) & 0x40) )
4651 {
4652 outb((unsigned char)midiByte, s->iomidi); return 1;
4653 }
4654
4655 return 0;
4656}
4657
4658unsigned long OSS32_StreamMidiRead(unsigned long streamid,
4659 char near *buffer, unsigned long bufsize)
4660{
4661 struct cm_state *s = (struct cm_state *)streamid;
4662 unsigned long count = 0;
4663
4664 while( !(inb(s->iomidi+1) & 0x80) && count < bufsize )
4665 {
4666 buffer[count++] = inb(s->iomidi);
4667 }
4668
4669 return count;
4670}
4671
4672//void init_timer(struct timer_list *t) {};
4673
4674//void add_timer(struct timer_list *t) {};
4675
4676//void del_timer(struct timer_list *t) {};
4677
4678#endif
4679
4680
Note: See TracBrowser for help on using the repository browser.