⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 es1968.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  Driver for ESS Maestro 1/2/2E Sound Card (started 21.8.99) *  Copyright (c) by Matze Braun <MatzeBraun@gmx.de>. *                   Takashi Iwai <tiwai@suse.de> *                   *  Most of the driver code comes from Zach Brown(zab@redhat.com) *	Alan Cox OSS Driver *  Rewritted from card-es1938.c source. * *  TODO: *   Perhaps Synth * *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * * *  Notes from Zach Brown about the driver code * *  Hardware Description * *	A working Maestro setup contains the Maestro chip wired to a  *	codec or 2.  In the Maestro we have the APUs, the ASSP, and the *	Wavecache.  The APUs can be though of as virtual audio routing *	channels.  They can take data from a number of sources and perform *	basic encodings of the data.  The wavecache is a storehouse for *	PCM data.  Typically it deals with PCI and interracts with the *	APUs.  The ASSP is a wacky DSP like device that ESS is loth *	to release docs on.  Thankfully it isn't required on the Maestro *	until you start doing insane things like FM emulation and surround *	encoding.  The codecs are almost always AC-97 compliant codecs,  *	but it appears that early Maestros may have had PT101 (an ESS *	part?) wired to them.  The only real difference in the Maestro *	families is external goop like docking capability, memory for *	the ASSP, and initialization differences. * *  Driver Operation * *	We only drive the APU/Wavecache as typical DACs and drive the *	mixers in the codecs.  There are 64 APUs.  We assign 6 to each *	/dev/dsp? device.  2 channels for output, and 4 channels for *	input. * *	Each APU can do a number of things, but we only really use *	3 basic functions.  For playback we use them to convert PCM *	data fetched over PCI by the wavecahche into analog data that *	is handed to the codec.  One APU for mono, and a pair for stereo. *	When in stereo, the combination of smarts in the APU and Wavecache *	decide which wavecache gets the left or right channel. * *	For record we still use the old overly mono system.  For each in *	coming channel the data comes in from the codec, through a 'input' *	APU, through another rate converter APU, and then into memory via *	the wavecache and PCI.  If its stereo, we mash it back into LRLR in *	software.  The pass between the 2 APUs is supposedly what requires us *	to have a 512 byte buffer sitting around in wavecache/memory. * *	The wavecache makes our life even more fun.  First off, it can *	only address the first 28 bits of PCI address space, making it *	useless on quite a few architectures.  Secondly, its insane. *	It claims to fetch from 4 regions of PCI space, each 4 meg in length. *	But that doesn't really work.  You can only use 1 region.  So all our *	allocations have to be in 4meg of each other.  Booo.  Hiss. *	So we have a module parameter, dsps_order, that is the order of *	the number of dsps to provide.  All their buffer space is allocated *	on open time.  The sonicvibes OSS routines we inherited really want *	power of 2 buffers, so we have all those next to each other, then *	512 byte regions for the recording wavecaches.  This ends up *	wasting quite a bit of memory.  The only fixes I can see would be  *	getting a kernel allocator that could work in zones, or figuring out *	just how to coerce the WP into doing what we want. * *	The indirection of the various registers means we have to spinlock *	nearly all register accesses.  We have the main register indirection *	like the wave cache, maestro registers, etc.  Then we have beasts *	like the APU interface that is indirect registers gotten at through *	the main maestro indirection.  Ouch.  We spinlock around the actual *	ports on a per card basis.  This means spinlock activity at each IO *	operation, but the only IO operation clusters are in non critical  *	paths and it makes the code far easier to follow.  Interrupts are *	blocked while holding the locks because the int handler has to *	get at some of them :(.  The mixer interface doesn't, however. *	We also have an OSS state lock that is thrown around in a few *	places. */#include <sound/driver.h>#include <asm/io.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/dma-mapping.h>#include <linux/slab.h>#include <linux/gameport.h>#include <linux/moduleparam.h>#include <linux/mutex.h>#include <sound/core.h>#include <sound/pcm.h>#include <sound/mpu401.h>#include <sound/ac97_codec.h>#include <sound/initval.h>#define CARD_NAME "ESS Maestro1/2"#define DRIVER_NAME "ES1968"MODULE_DESCRIPTION("ESS Maestro");MODULE_LICENSE("GPL");MODULE_SUPPORTED_DEVICE("{{ESS,Maestro 2e},"		"{ESS,Maestro 2},"		"{ESS,Maestro 1},"		"{TerraTec,DMX}}");#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))#define SUPPORT_JOYSTICK 1#endifstatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 1-MAX */static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */static int total_bufsize[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1024 };static int pcm_substreams_p[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4 };static int pcm_substreams_c[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1 };static int clock[SNDRV_CARDS];static int use_pm[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};static int enable_mpu[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};#ifdef SUPPORT_JOYSTICKstatic int joystick[SNDRV_CARDS];#endifmodule_param_array(index, int, NULL, 0444);MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");module_param_array(id, charp, NULL, 0444);MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");module_param_array(enable, bool, NULL, 0444);MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");module_param_array(total_bufsize, int, NULL, 0444);MODULE_PARM_DESC(total_bufsize, "Total buffer size in kB.");module_param_array(pcm_substreams_p, int, NULL, 0444);MODULE_PARM_DESC(pcm_substreams_p, "PCM Playback substreams for " CARD_NAME " soundcard.");module_param_array(pcm_substreams_c, int, NULL, 0444);MODULE_PARM_DESC(pcm_substreams_c, "PCM Capture substreams for " CARD_NAME " soundcard.");module_param_array(clock, int, NULL, 0444);MODULE_PARM_DESC(clock, "Clock on " CARD_NAME " soundcard.  (0 = auto-detect)");module_param_array(use_pm, int, NULL, 0444);MODULE_PARM_DESC(use_pm, "Toggle power-management.  (0 = off, 1 = on, 2 = auto)");module_param_array(enable_mpu, int, NULL, 0444);MODULE_PARM_DESC(enable_mpu, "Enable MPU401.  (0 = off, 1 = on, 2 = auto)");#ifdef SUPPORT_JOYSTICKmodule_param_array(joystick, bool, NULL, 0444);MODULE_PARM_DESC(joystick, "Enable joystick.");#endif#define NR_APUS			64#define NR_APU_REGS		16/* NEC Versas ? */#define NEC_VERSA_SUBID1	0x80581033#define NEC_VERSA_SUBID2	0x803c1033/* Mode Flags */#define ESS_FMT_STEREO     	0x01#define ESS_FMT_16BIT      	0x02#define DAC_RUNNING		1#define ADC_RUNNING		2/* Values for the ESM_LEGACY_AUDIO_CONTROL */#define ESS_DISABLE_AUDIO	0x8000#define ESS_ENABLE_SERIAL_IRQ	0x4000#define IO_ADRESS_ALIAS		0x0020#define MPU401_IRQ_ENABLE	0x0010#define MPU401_IO_ENABLE	0x0008#define GAME_IO_ENABLE		0x0004#define FM_IO_ENABLE		0x0002#define SB_IO_ENABLE		0x0001/* Values for the ESM_CONFIG_A */#define PIC_SNOOP1		0x4000#define PIC_SNOOP2		0x2000#define SAFEGUARD		0x0800#define DMA_CLEAR		0x0700#define DMA_DDMA		0x0000#define DMA_TDMA		0x0100#define DMA_PCPCI		0x0200#define POST_WRITE		0x0080#define PCI_TIMING		0x0040#define SWAP_LR			0x0020#define SUBTR_DECODE		0x0002/* Values for the ESM_CONFIG_B */#define SPDIF_CONFB		0x0100#define HWV_CONFB		0x0080#define DEBOUNCE		0x0040#define GPIO_CONFB		0x0020#define CHI_CONFB		0x0010#define IDMA_CONFB		0x0008	/*undoc */#define MIDI_FIX		0x0004	/*undoc */#define IRQ_TO_ISA		0x0001	/*undoc *//* Values for Ring Bus Control B */#define	RINGB_2CODEC_ID_MASK	0x0003#define RINGB_DIS_VALIDATION	0x0008#define RINGB_EN_SPDIF		0x0010#define	RINGB_EN_2CODEC		0x0020#define RINGB_SING_BIT_DUAL	0x0040/* ****Port Adresses**** *//*   Write & Read */#define ESM_INDEX		0x02#define ESM_DATA		0x00/*   AC97 + RingBus */#define ESM_AC97_INDEX		0x30#define	ESM_AC97_DATA		0x32#define ESM_RING_BUS_DEST	0x34#define ESM_RING_BUS_CONTR_A	0x36#define ESM_RING_BUS_CONTR_B	0x38#define ESM_RING_BUS_SDO	0x3A/*   WaveCache*/#define WC_INDEX		0x10#define WC_DATA			0x12#define WC_CONTROL		0x14/*   ASSP*/#define ASSP_INDEX		0x80#define ASSP_MEMORY		0x82#define ASSP_DATA		0x84#define ASSP_CONTROL_A		0xA2#define ASSP_CONTROL_B		0xA4#define ASSP_CONTROL_C		0xA6#define ASSP_HOSTW_INDEX	0xA8#define ASSP_HOSTW_DATA		0xAA#define ASSP_HOSTW_IRQ		0xAC/* Midi */#define ESM_MPU401_PORT		0x98/* Others */#define ESM_PORT_HOST_IRQ	0x18#define IDR0_DATA_PORT		0x00#define IDR1_CRAM_POINTER	0x01#define IDR2_CRAM_DATA		0x02#define IDR3_WAVE_DATA		0x03#define IDR4_WAVE_PTR_LOW	0x04#define IDR5_WAVE_PTR_HI	0x05#define IDR6_TIMER_CTRL		0x06#define IDR7_WAVE_ROMRAM	0x07#define WRITEABLE_MAP		0xEFFFFF#define READABLE_MAP		0x64003F/* PCI Register */#define ESM_LEGACY_AUDIO_CONTROL 0x40#define ESM_ACPI_COMMAND	0x54#define ESM_CONFIG_A		0x50#define ESM_CONFIG_B		0x52#define ESM_DDMA		0x60/* Bob Bits */#define ESM_BOB_ENABLE		0x0001#define ESM_BOB_START		0x0001/* Host IRQ Control Bits */#define ESM_RESET_MAESTRO	0x8000#define ESM_RESET_DIRECTSOUND   0x4000#define ESM_HIRQ_ClkRun		0x0100#define ESM_HIRQ_HW_VOLUME	0x0040#define ESM_HIRQ_HARPO		0x0030	/* What's that? */#define ESM_HIRQ_ASSP		0x0010#define	ESM_HIRQ_DSIE		0x0004#define ESM_HIRQ_MPU401		0x0002#define ESM_HIRQ_SB		0x0001/* Host IRQ Status Bits */#define ESM_MPU401_IRQ		0x02#define ESM_SB_IRQ		0x01#define ESM_SOUND_IRQ		0x04#define	ESM_ASSP_IRQ		0x10#define ESM_HWVOL_IRQ		0x40#define ESS_SYSCLK		50000000#define ESM_BOB_FREQ 		200#define ESM_BOB_FREQ_MAX	800#define ESM_FREQ_ESM1  		(49152000L / 1024L)	/* default rate 48000 */#define ESM_FREQ_ESM2  		(50000000L / 1024L)/* APU Modes: reg 0x00, bit 4-7 */#define ESM_APU_MODE_SHIFT	4#define ESM_APU_MODE_MASK	(0xf << 4)#define	ESM_APU_OFF		0x00#define	ESM_APU_16BITLINEAR	0x01	/* 16-Bit Linear Sample Player */#define	ESM_APU_16BITSTEREO	0x02	/* 16-Bit Stereo Sample Player */#define	ESM_APU_8BITLINEAR	0x03	/* 8-Bit Linear Sample Player */#define	ESM_APU_8BITSTEREO	0x04	/* 8-Bit Stereo Sample Player */#define	ESM_APU_8BITDIFF	0x05	/* 8-Bit Differential Sample Playrer */#define	ESM_APU_DIGITALDELAY	0x06	/* Digital Delay Line */#define	ESM_APU_DUALTAP		0x07	/* Dual Tap Reader */#define	ESM_APU_CORRELATOR	0x08	/* Correlator */#define	ESM_APU_INPUTMIXER	0x09	/* Input Mixer */#define	ESM_APU_WAVETABLE	0x0A	/* Wave Table Mode */#define	ESM_APU_SRCONVERTOR	0x0B	/* Sample Rate Convertor */#define	ESM_APU_16BITPINGPONG	0x0C	/* 16-Bit Ping-Pong Sample Player */#define	ESM_APU_RESERVED1	0x0D	/* Reserved 1 */#define	ESM_APU_RESERVED2	0x0E	/* Reserved 2 */#define	ESM_APU_RESERVED3	0x0F	/* Reserved 3 *//* reg 0x00 */#define ESM_APU_FILTER_Q_SHIFT		0#define ESM_APU_FILTER_Q_MASK		(3 << 0)/* APU Filtey Q Control */#define ESM_APU_FILTER_LESSQ	0x00#define ESM_APU_FILTER_MOREQ	0x03#define ESM_APU_FILTER_TYPE_SHIFT	2#define ESM_APU_FILTER_TYPE_MASK	(3 << 2)#define ESM_APU_ENV_TYPE_SHIFT		8#define ESM_APU_ENV_TYPE_MASK		(3 << 8)#define ESM_APU_ENV_STATE_SHIFT		10#define ESM_APU_ENV_STATE_MASK		(3 << 10)#define ESM_APU_END_CURVE		(1 << 12)#define ESM_APU_INT_ON_LOOP		(1 << 13)#define ESM_APU_DMA_ENABLE		(1 << 14)/* reg 0x02 */#define ESM_APU_SUBMIX_GROUP_SHIRT	0#define ESM_APU_SUBMIX_GROUP_MASK	(7 << 0)#define ESM_APU_SUBMIX_MODE		(1 << 3)#define ESM_APU_6dB			(1 << 4)#define ESM_APU_DUAL_EFFECT		(1 << 5)#define ESM_APU_EFFECT_CHANNELS_SHIFT	6#define ESM_APU_EFFECT_CHANNELS_MASK	(3 << 6)/* reg 0x03 */#define ESM_APU_STEP_SIZE_MASK		0x0fff/* reg 0x04 */#define ESM_APU_PHASE_SHIFT		0#define ESM_APU_PHASE_MASK		(0xff << 0)#define ESM_APU_WAVE64K_PAGE_SHIFT	8	/* most 8bit of wave start offset */#define ESM_APU_WAVE64K_PAGE_MASK	(0xff << 8)/* reg 0x05 - wave start offset *//* reg 0x06 - wave end offset *//* reg 0x07 - wave loop length *//* reg 0x08 */#define ESM_APU_EFFECT_GAIN_SHIFT	0#define ESM_APU_EFFECT_GAIN_MASK	(0xff << 0)#define ESM_APU_TREMOLO_DEPTH_SHIFT	8#define ESM_APU_TREMOLO_DEPTH_MASK	(0xf << 8)#define ESM_APU_TREMOLO_RATE_SHIFT	12#define ESM_APU_TREMOLO_RATE_MASK	(0xf << 12)/* reg 0x09 *//* bit 0-7 amplitude dest? */#define ESM_APU_AMPLITUDE_NOW_SHIFT	8#define ESM_APU_AMPLITUDE_NOW_MASK	(0xff << 8)/* reg 0x0a */#define ESM_APU_POLAR_PAN_SHIFT		0#define ESM_APU_POLAR_PAN_MASK		(0x3f << 0)/* Polar Pan Control */#define	ESM_APU_PAN_CENTER_CIRCLE		0x00#define	ESM_APU_PAN_MIDDLE_RADIUS		0x01#define	ESM_APU_PAN_OUTSIDE_RADIUS		0x02#define ESM_APU_FILTER_TUNING_SHIFT	8#define ESM_APU_FILTER_TUNING_MASK	(0xff << 8)/* reg 0x0b */#define ESM_APU_DATA_SRC_A_SHIFT	0#define ESM_APU_DATA_SRC_A_MASK		(0x7f << 0)#define ESM_APU_INV_POL_A		(1 << 7)#define ESM_APU_DATA_SRC_B_SHIFT	8#define ESM_APU_DATA_SRC_B_MASK		(0x7f << 8)#define ESM_APU_INV_POL_B		(1 << 15)#define ESM_APU_VIBRATO_RATE_SHIFT	0#define ESM_APU_VIBRATO_RATE_MASK	(0xf << 0)#define ESM_APU_VIBRATO_DEPTH_SHIFT	4#define ESM_APU_VIBRATO_DEPTH_MASK	(0xf << 4)#define ESM_APU_VIBRATO_PHASE_SHIFT	8#define ESM_APU_VIBRATO_PHASE_MASK	(0xff << 8)/* reg 0x0c */#define ESM_APU_RADIUS_SELECT		(1 << 6)/* APU Filter Control */#define	ESM_APU_FILTER_2POLE_LOPASS	0x00#define	ESM_APU_FILTER_2POLE_BANDPASS	0x01#define	ESM_APU_FILTER_2POLE_HIPASS	0x02#define	ESM_APU_FILTER_1POLE_LOPASS	0x03#define	ESM_APU_FILTER_1POLE_HIPASS	0x04#define	ESM_APU_FILTER_OFF		0x05/* APU ATFP Type */#define	ESM_APU_ATFP_AMPLITUDE			0x00#define	ESM_APU_ATFP_TREMELO			0x01#define	ESM_APU_ATFP_FILTER			0x02#define	ESM_APU_ATFP_PAN			0x03/* APU ATFP Flags */#define	ESM_APU_ATFP_FLG_OFF			0x00#define	ESM_APU_ATFP_FLG_WAIT			0x01#define	ESM_APU_ATFP_FLG_DONE			0x02#define	ESM_APU_ATFP_FLG_INPROCESS		0x03/* capture mixing buffer size */#define ESM_MEM_ALIGN		0x1000#define ESM_MIXBUF_SIZE		0x400#define ESM_MODE_PLAY		0#define ESM_MODE_CAPTURE	1/* APU use in the driver */enum snd_enum_apu_type {	ESM_APU_PCM_PLAY,	ESM_APU_PCM_CAPTURE,	ESM_APU_PCM_RATECONV,	ESM_APU_FREE};/* chip type */enum {	TYPE_MAESTRO, TYPE_MAESTRO2, TYPE_MAESTRO2E};/* DMA Hack! */struct esm_memory {	struct snd_dma_buffer buf;	int empty;	/* status */	struct list_head list;};/* Playback Channel */struct esschan {	int running;	u8 apu[4];	u8 apu_mode[4];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -