📄 es1370.c
字号:
/*****************************************************************************//* * es1370.c -- Ensoniq ES1370/Asahi Kasei AK4531 audio driver. * * Copyright (C) 1998-2001 Thomas Sailer (t.sailer@alumni.ethz.ch) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Special thanks to David C. Niemi * * * Module command line parameters: * joystick if 1 enables the joystick interface on the card; but it still * needs a driver for joysticks connected to a standard IBM-PC * joyport. It is tested with the joy-analog driver. This * module must be loaded before the joystick driver. Kmod will * not ensure that. * lineout if 1 the LINE jack is used as an output instead of an input. * LINE then contains the unmixed dsp output. This can be used * to make the card a four channel one: use dsp to output two * channels to LINE and dac to output the other two channels to * SPKR. Set the mixer to only output synth to SPKR. * micbias sets the +5V bias to the mic if using an electretmic. * * * Note: sync mode is not yet supported (i.e. running dsp and dac from the same * clock source) * * Supported devices: * /dev/dsp standard /dev/dsp device, (mostly) OSS compatible * /dev/mixer standard /dev/mixer device, (mostly) OSS compatible * /dev/dsp1 additional DAC, like /dev/dsp, but output only, * only 5512, 11025, 22050 and 44100 samples/s, * outputs to mixer "SYNTH" setting * /dev/midi simple MIDI UART interface, no ioctl * * NOTE: the card does not have any FM/Wavetable synthesizer, it is supposed * to be done in software. That is what /dev/dac is for. By now (Q2 1998) * there are several MIDI to PCM (WAV) packages, one of them is timidity. * * Revision history * 26.03.1998 0.1 Initial release * 31.03.1998 0.2 Fix bug in GETOSPACE * 04.04.1998 0.3 Make it work (again) under 2.0.33 * Fix mixer write operation not returning the actual * settings * 05.04.1998 0.4 First attempt at using the new PCI stuff * 29.04.1998 0.5 Fix hang when ^C is pressed on amp * 07.05.1998 0.6 Don't double lock around stop_*() in *_release() * 10.05.1998 0.7 First stab at a simple midi interface (no bells&whistles) * 14.05.1998 0.8 Don't allow excessive interrupt rates * 08.06.1998 0.9 First release using Alan Cox' soundcore instead of * miscdevice * 05.07.1998 0.10 Fixed the driver to correctly maintin OSS style volume * settings (not sure if this should be standard) * Fixed many references: f_flags should be f_mode * -- Gerald Britton <gbritton@mit.edu> * 03.08.1998 0.11 Now mixer behaviour can basically be selected between * "OSS documented" and "OSS actual" behaviour * Fixed mixer table thanks to Hakan.Lennestal@lu.erisoft.se * On module startup, set DAC2 to 11kSPS instead of 5.5kSPS, * as it produces an annoying ssssh in the lower sampling rate * Do not include modversions.h * 22.08.1998 0.12 Mixer registers actually have 5 instead of 4 bits * pointed out by Itai Nahshon * 31.08.1998 0.13 Fix realplayer problems - dac.count issues * 08.10.1998 0.14 Joystick support fixed * -- Oliver Neukum <c188@org.chemie.uni-muenchen.de> * 10.12.1998 0.15 Fix drain_dac trying to wait on not yet initialized DMA * 16.12.1998 0.16 Don't wake up app until there are fragsize bytes to read/write * 06.01.1999 0.17 remove the silly SA_INTERRUPT flag. * hopefully killed the egcs section type conflict * 12.03.1999 0.18 cinfo.blocks should be reset after GETxPTR ioctl. * reported by Johan Maes <joma@telindus.be> * 22.03.1999 0.19 return EAGAIN instead of EBUSY when O_NONBLOCK * read/write cannot be executed * 07.04.1999 0.20 implemented the following ioctl's: SOUND_PCM_READ_RATE, * SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; * Alpha fixes reported by Peter Jones <pjones@redhat.com> * Note: joystick address handling might still be wrong on archs * other than i386 * 10.05.1999 0.21 Added support for an electret mic for SB PCI64 * to the Linux kernel sound driver. This mod also straighten * out the question marks around the mic impedance setting * (micz). From Kim.Berts@fisub.mail.abb.com * 11.05.1999 0.22 Implemented the IMIX call to mute recording monitor. * Guenter Geiger <geiger@epy.co.at> * 15.06.1999 0.23 Fix bad allocation bug. * Thanks to Deti Fliegl <fliegl@in.tum.de> * 28.06.1999 0.24 Add pci_set_master * 02.08.1999 0.25 Added workaround for the "phantom write" bug first * documented by Dave Sharpless from Anchor Games * 03.08.1999 0.26 adapt to Linus' new __setup/__initcall * added kernel command line option "es1370=joystick[,lineout[,micbias]]" * removed CONFIG_SOUND_ES1370_JOYPORT_BOOT kludge * 12.08.1999 0.27 module_init/__setup fixes * 19.08.1999 0.28 SOUND_MIXER_IMIX fixes, reported by Gianluca <gialluca@mail.tiscalinet.it> * 31.08.1999 0.29 add spin_lock_init * replaced current->state = x with set_current_state(x) * 03.09.1999 0.30 change read semantics for MIDI to match * OSS more closely; remove possible wakeup race * 28.10.1999 0.31 More waitqueue races fixed * 08.01.2000 0.32 Prevent some ioctl's from returning bad count values on underrun/overrun; * Tim Janik's BSE (Bedevilled Sound Engine) found this * 07.02.2000 0.33 Use pci_alloc_consistent and pci_register_driver * 21.11.2000 0.34 Initialize dma buffers in poll, otherwise poll may return a bogus mask * 12.12.2000 0.35 More dma buffer initializations, patch from * Tjeerd Mulder <tjeerd.mulder@fujitsu-siemens.com> * 07.01.2001 0.36 Timeout change in wrcodec as requested by Frank Klemm <pfk@fuchs.offl.uni-jena.de> * 31.01.2001 0.37 Register/Unregister gameport * Fix SETTRIGGER non OSS API conformity * * some important things missing in Ensoniq documentation: * * Experimental PCLKDIV results: play the same waveforms on both DAC1 and DAC2 * and vary PCLKDIV to obtain zero beat. * 5512sps: 254 * 44100sps: 30 * seems to be fs = 1411200/(PCLKDIV+2) * * should find out when curr_sample_ct is cleared and * where exactly the CCB fetches data * * The card uses a 22.5792 MHz crystal. * The LINEIN jack may be converted to an AOUT jack by * setting pin 47 (XCTL0) of the ES1370 to high. * Pin 48 (XCTL1) of the ES1370 sets the +5V bias for an electretmic * * *//*****************************************************************************/ #include <linux/version.h>#include <linux/module.h>#include <linux/string.h>#include <linux/ioport.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/sound.h>#include <linux/slab.h>#include <linux/soundcard.h>#include <linux/pci.h>#include <linux/smp_lock.h>#include <linux/wrapper.h>#include <asm/io.h>#include <asm/dma.h>#include <linux/init.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <asm/uaccess.h>#include <asm/hardirq.h>#include <linux/gameport.h>/* --------------------------------------------------------------------- */#undef OSS_DOCUMENTED_MIXER_SEMANTICS#define DBG(x) {}/*#define DBG(x) {x}*//* --------------------------------------------------------------------- */#ifndef PCI_VENDOR_ID_ENSONIQ#define PCI_VENDOR_ID_ENSONIQ 0x1274 #endif#ifndef PCI_DEVICE_ID_ENSONIQ_ES1370#define PCI_DEVICE_ID_ENSONIQ_ES1370 0x5000#endif#define ES1370_MAGIC ((PCI_VENDOR_ID_ENSONIQ<<16)|PCI_DEVICE_ID_ENSONIQ_ES1370)#define ES1370_EXTENT 0x40#define JOY_EXTENT 8#define ES1370_REG_CONTROL 0x00#define ES1370_REG_STATUS 0x04#define ES1370_REG_UART_DATA 0x08#define ES1370_REG_UART_STATUS 0x09#define ES1370_REG_UART_CONTROL 0x09#define ES1370_REG_UART_TEST 0x0a#define ES1370_REG_MEMPAGE 0x0c#define ES1370_REG_CODEC 0x10#define ES1370_REG_SERIAL_CONTROL 0x20#define ES1370_REG_DAC1_SCOUNT 0x24#define ES1370_REG_DAC2_SCOUNT 0x28#define ES1370_REG_ADC_SCOUNT 0x2c#define ES1370_REG_DAC1_FRAMEADR 0xc30#define ES1370_REG_DAC1_FRAMECNT 0xc34#define ES1370_REG_DAC2_FRAMEADR 0xc38#define ES1370_REG_DAC2_FRAMECNT 0xc3c#define ES1370_REG_ADC_FRAMEADR 0xd30#define ES1370_REG_ADC_FRAMECNT 0xd34#define ES1370_REG_PHANTOM_FRAMEADR 0xd38#define ES1370_REG_PHANTOM_FRAMECNT 0xd3c#define ES1370_FMT_U8_MONO 0#define ES1370_FMT_U8_STEREO 1#define ES1370_FMT_S16_MONO 2#define ES1370_FMT_S16_STEREO 3#define ES1370_FMT_STEREO 1#define ES1370_FMT_S16 2#define ES1370_FMT_MASK 3static const unsigned sample_size[] = { 1, 2, 2, 4 };static const unsigned sample_shift[] = { 0, 1, 1, 2 };static const unsigned dac1_samplerate[] = { 5512, 11025, 22050, 44100 };#define DAC2_SRTODIV(x) (((1411200+(x)/2)/(x))-2)#define DAC2_DIVTOSR(x) (1411200/((x)+2))#define CTRL_ADC_STOP 0x80000000 /* 1 = ADC stopped */#define CTRL_XCTL1 0x40000000 /* electret mic bias */#define CTRL_OPEN 0x20000000 /* no function, can be read and written */#define CTRL_PCLKDIV 0x1fff0000 /* ADC/DAC2 clock divider */#define CTRL_SH_PCLKDIV 16#define CTRL_MSFMTSEL 0x00008000 /* MPEG serial data fmt: 0 = Sony, 1 = I2S */#define CTRL_M_SBB 0x00004000 /* DAC2 clock: 0 = PCLKDIV, 1 = MPEG */#define CTRL_WTSRSEL 0x00003000 /* DAC1 clock freq: 0=5512, 1=11025, 2=22050, 3=44100 */#define CTRL_SH_WTSRSEL 12#define CTRL_DAC_SYNC 0x00000800 /* 1 = DAC2 runs off DAC1 clock */#define CTRL_CCB_INTRM 0x00000400 /* 1 = CCB "voice" ints enabled */#define CTRL_M_CB 0x00000200 /* recording source: 0 = ADC, 1 = MPEG */#define CTRL_XCTL0 0x00000100 /* 0 = Line in, 1 = Line out */#define CTRL_BREQ 0x00000080 /* 1 = test mode (internal mem test) */#define CTRL_DAC1_EN 0x00000040 /* enable DAC1 */#define CTRL_DAC2_EN 0x00000020 /* enable DAC2 */#define CTRL_ADC_EN 0x00000010 /* enable ADC */#define CTRL_UART_EN 0x00000008 /* enable MIDI uart */#define CTRL_JYSTK_EN 0x00000004 /* enable Joystick port (presumably at address 0x200) */#define CTRL_CDC_EN 0x00000002 /* enable serial (CODEC) interface */#define CTRL_SERR_DIS 0x00000001 /* 1 = disable PCI SERR signal */#define STAT_INTR 0x80000000 /* wired or of all interrupt bits */#define STAT_CSTAT 0x00000400 /* 1 = codec busy or codec write in progress */#define STAT_CBUSY 0x00000200 /* 1 = codec busy */#define STAT_CWRIP 0x00000100 /* 1 = codec write in progress */#define STAT_VC 0x00000060 /* CCB int source, 0=DAC1, 1=DAC2, 2=ADC, 3=undef */#define STAT_SH_VC 5#define STAT_MCCB 0x00000010 /* CCB int pending */#define STAT_UART 0x00000008 /* UART int pending */#define STAT_DAC1 0x00000004 /* DAC1 int pending */#define STAT_DAC2 0x00000002 /* DAC2 int pending */#define STAT_ADC 0x00000001 /* ADC int pending */#define USTAT_RXINT 0x80 /* UART rx int pending */#define USTAT_TXINT 0x04 /* UART tx int pending */#define USTAT_TXRDY 0x02 /* UART tx ready */#define USTAT_RXRDY 0x01 /* UART rx ready */#define UCTRL_RXINTEN 0x80 /* 1 = enable RX ints */#define UCTRL_TXINTEN 0x60 /* TX int enable field mask */#define UCTRL_ENA_TXINT 0x20 /* enable TX int */#define UCTRL_CNTRL 0x03 /* control field */#define UCTRL_CNTRL_SWR 0x03 /* software reset command */#define SCTRL_P2ENDINC 0x00380000 /* */#define SCTRL_SH_P2ENDINC 19#define SCTRL_P2STINC 0x00070000 /* */#define SCTRL_SH_P2STINC 16#define SCTRL_R1LOOPSEL 0x00008000 /* 0 = loop mode */#define SCTRL_P2LOOPSEL 0x00004000 /* 0 = loop mode */#define SCTRL_P1LOOPSEL 0x00002000 /* 0 = loop mode */#define SCTRL_P2PAUSE 0x00001000 /* 1 = pause mode */#define SCTRL_P1PAUSE 0x00000800 /* 1 = pause mode */#define SCTRL_R1INTEN 0x00000400 /* enable interrupt */#define SCTRL_P2INTEN 0x00000200 /* enable interrupt */#define SCTRL_P1INTEN 0x00000100 /* enable interrupt */#define SCTRL_P1SCTRLD 0x00000080 /* reload sample count register for DAC1 */#define SCTRL_P2DACSEN 0x00000040 /* 1 = DAC2 play back last sample when disabled */#define SCTRL_R1SEB 0x00000020 /* 1 = 16bit */#define SCTRL_R1SMB 0x00000010 /* 1 = stereo */#define SCTRL_R1FMT 0x00000030 /* format mask */#define SCTRL_SH_R1FMT 4#define SCTRL_P2SEB 0x00000008 /* 1 = 16bit */#define SCTRL_P2SMB 0x00000004 /* 1 = stereo */#define SCTRL_P2FMT 0x0000000c /* format mask */#define SCTRL_SH_P2FMT 2#define SCTRL_P1SEB 0x00000002 /* 1 = 16bit */#define SCTRL_P1SMB 0x00000001 /* 1 = stereo */#define SCTRL_P1FMT 0x00000003 /* format mask */#define SCTRL_SH_P1FMT 0/* misc stuff */#define FMODE_DAC 4 /* slight misuse of mode_t *//* MIDI buffer sizes */#define MIDIINBUF 256#define MIDIOUTBUF 256#define FMODE_MIDI_SHIFT 3#define FMODE_MIDI_READ (FMODE_READ << FMODE_MIDI_SHIFT)#define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT)/* --------------------------------------------------------------------- */struct es1370_state { /* magic */ unsigned int magic; /* list of es1370 devices */ struct list_head devs; /* the corresponding pci_dev structure */ struct pci_dev *dev; /* soundcore stuff */ int dev_audio; int dev_mixer; int dev_dac; int dev_midi; /* hardware resources */ unsigned long io; /* long for SPARC */ unsigned int irq; /* mixer registers; there is no HW readback */ struct { unsigned short vol[10]; unsigned int recsrc; unsigned int modcnt; unsigned short micpreamp; unsigned int imix; } mix; /* wave stuff */ unsigned ctrl; unsigned sctrl; spinlock_t lock; struct semaphore open_sem; mode_t open_mode; wait_queue_head_t open_wait; struct dmabuf { void *rawbuf; dma_addr_t dmaaddr; unsigned buforder; unsigned numfrag; unsigned fragshift; unsigned hwptr, swptr; unsigned total_bytes; int count; unsigned error; /* over/underrun */ wait_queue_head_t wait; /* redundant, but makes calculations easier */ unsigned fragsize; unsigned dmasize; unsigned fragsamples; /* OSS stuff */ unsigned mapped:1; unsigned ready:1; unsigned endcleared:1; unsigned enabled:1; unsigned ossfragshift; int ossmaxfrags; unsigned subdivision; } dma_dac1, dma_dac2, dma_adc; /* midi stuff */ struct { unsigned ird, iwr, icnt; unsigned ord, owr, ocnt; wait_queue_head_t iwait; wait_queue_head_t owait; unsigned char ibuf[MIDIINBUF]; unsigned char obuf[MIDIOUTBUF]; } midi; struct gameport gameport; struct semaphore sem;};/* --------------------------------------------------------------------- */static LIST_HEAD(devs);/* * The following buffer is used to point the phantom write channel to, * so that it cannot wreak havoc. The attribute makes sure it doesn't * cross a page boundary and ensures dword alignment for the DMA engine */static unsigned char bugbuf[16] __attribute__ ((aligned (16)));/* --------------------------------------------------------------------- */static inline unsigned ld2(unsigned int x){ unsigned r = 0; if (x >= 0x10000) { x >>= 16; r += 16; } if (x >= 0x100) { x >>= 8; r += 8; } if (x >= 0x10) { x >>= 4;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -