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

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

Avoid some warnings

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