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

📄 sonicvibes.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  Driver for S3 SonicVibes soundcard *  Copyright (c) by Jaroslav Kysela <perex@perex.cz> * *  BUGS: *    It looks like 86c617 rev 3 doesn't supports DDMA buffers above 16MB? *    Driver sometimes hangs... Nobody knows why at this moment... * *   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 * */#include <sound/driver.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/slab.h>#include <linux/gameport.h>#include <linux/moduleparam.h>#include <linux/dma-mapping.h>#include <sound/core.h>#include <sound/pcm.h>#include <sound/info.h>#include <sound/control.h>#include <sound/mpu401.h>#include <sound/opl3.h>#include <sound/initval.h>#include <asm/io.h>MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");MODULE_DESCRIPTION("S3 SonicVibes PCI");MODULE_LICENSE("GPL");MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}");#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))#define SUPPORT_JOYSTICK 1#endifstatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-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 reverb[SNDRV_CARDS];static int mge[SNDRV_CARDS];static unsigned int dmaio = 0x7a00;	/* DDMA i/o address */module_param_array(index, int, NULL, 0444);MODULE_PARM_DESC(index, "Index value for S3 SonicVibes soundcard.");module_param_array(id, charp, NULL, 0444);MODULE_PARM_DESC(id, "ID string for S3 SonicVibes soundcard.");module_param_array(enable, bool, NULL, 0444);MODULE_PARM_DESC(enable, "Enable S3 SonicVibes soundcard.");module_param_array(reverb, bool, NULL, 0444);MODULE_PARM_DESC(reverb, "Enable reverb (SRAM is present) for S3 SonicVibes soundcard.");module_param_array(mge, bool, NULL, 0444);MODULE_PARM_DESC(mge, "MIC Gain Enable for S3 SonicVibes soundcard.");module_param(dmaio, uint, 0444);MODULE_PARM_DESC(dmaio, "DDMA i/o base address for S3 SonicVibes soundcard.");/* * Enhanced port direct registers */#define SV_REG(sonic, x) ((sonic)->enh_port + SV_REG_##x)#define SV_REG_CONTROL	0x00	/* R/W: CODEC/Mixer control register */#define   SV_ENHANCED	  0x01	/* audio mode select - enhanced mode */#define   SV_TEST	  0x02	/* test bit */#define   SV_REVERB	  0x04	/* reverb enable */#define   SV_WAVETABLE	  0x08	/* wavetable active / FM active if not set */#define   SV_INTA	  0x20	/* INTA driving - should be always 1 */#define   SV_RESET	  0x80	/* reset chip */#define SV_REG_IRQMASK	0x01	/* R/W: CODEC/Mixer interrupt mask register */#define   SV_DMAA_MASK	  0x01	/* mask DMA-A interrupt */#define   SV_DMAC_MASK	  0x04	/* mask DMA-C interrupt */#define   SV_SPEC_MASK	  0x08	/* special interrupt mask - should be always masked */#define   SV_UD_MASK	  0x40	/* Up/Down button interrupt mask */#define   SV_MIDI_MASK	  0x80	/* mask MIDI interrupt */#define SV_REG_STATUS	0x02	/* R/O: CODEC/Mixer status register */#define   SV_DMAA_IRQ	  0x01	/* DMA-A interrupt */#define   SV_DMAC_IRQ	  0x04	/* DMA-C interrupt */#define   SV_SPEC_IRQ	  0x08	/* special interrupt */#define   SV_UD_IRQ	  0x40	/* Up/Down interrupt */#define   SV_MIDI_IRQ	  0x80	/* MIDI interrupt */#define SV_REG_INDEX	0x04	/* R/W: CODEC/Mixer index address register */#define   SV_MCE          0x40	/* mode change enable */#define   SV_TRD	  0x80	/* DMA transfer request disabled */#define SV_REG_DATA	0x05	/* R/W: CODEC/Mixer index data register *//* * Enhanced port indirect registers */#define SV_IREG_LEFT_ADC	0x00	/* Left ADC Input Control */#define SV_IREG_RIGHT_ADC	0x01	/* Right ADC Input Control */#define SV_IREG_LEFT_AUX1	0x02	/* Left AUX1 Input Control */#define SV_IREG_RIGHT_AUX1	0x03	/* Right AUX1 Input Control */#define SV_IREG_LEFT_CD		0x04	/* Left CD Input Control */#define SV_IREG_RIGHT_CD	0x05	/* Right CD Input Control */#define SV_IREG_LEFT_LINE	0x06	/* Left Line Input Control */#define SV_IREG_RIGHT_LINE	0x07	/* Right Line Input Control */#define SV_IREG_MIC		0x08	/* MIC Input Control */#define SV_IREG_GAME_PORT	0x09	/* Game Port Control */#define SV_IREG_LEFT_SYNTH	0x0a	/* Left Synth Input Control */#define SV_IREG_RIGHT_SYNTH	0x0b	/* Right Synth Input Control */#define SV_IREG_LEFT_AUX2	0x0c	/* Left AUX2 Input Control */#define SV_IREG_RIGHT_AUX2	0x0d	/* Right AUX2 Input Control */#define SV_IREG_LEFT_ANALOG	0x0e	/* Left Analog Mixer Output Control */#define SV_IREG_RIGHT_ANALOG	0x0f	/* Right Analog Mixer Output Control */#define SV_IREG_LEFT_PCM	0x10	/* Left PCM Input Control */#define SV_IREG_RIGHT_PCM	0x11	/* Right PCM Input Control */#define SV_IREG_DMA_DATA_FMT	0x12	/* DMA Data Format */#define SV_IREG_PC_ENABLE	0x13	/* Playback/Capture Enable Register */#define SV_IREG_UD_BUTTON	0x14	/* Up/Down Button Register */#define SV_IREG_REVISION	0x15	/* Revision */#define SV_IREG_ADC_OUTPUT_CTRL	0x16	/* ADC Output Control */#define SV_IREG_DMA_A_UPPER	0x18	/* DMA A Upper Base Count */#define SV_IREG_DMA_A_LOWER	0x19	/* DMA A Lower Base Count */#define SV_IREG_DMA_C_UPPER	0x1c	/* DMA C Upper Base Count */#define SV_IREG_DMA_C_LOWER	0x1d	/* DMA C Lower Base Count */#define SV_IREG_PCM_RATE_LOW	0x1e	/* PCM Sampling Rate Low Byte */#define SV_IREG_PCM_RATE_HIGH	0x1f	/* PCM Sampling Rate High Byte */#define SV_IREG_SYNTH_RATE_LOW	0x20	/* Synthesizer Sampling Rate Low Byte */#define SV_IREG_SYNTH_RATE_HIGH 0x21	/* Synthesizer Sampling Rate High Byte */#define SV_IREG_ADC_CLOCK	0x22	/* ADC Clock Source Selection */#define SV_IREG_ADC_ALT_RATE	0x23	/* ADC Alternative Sampling Rate Selection */#define SV_IREG_ADC_PLL_M	0x24	/* ADC PLL M Register */#define SV_IREG_ADC_PLL_N	0x25	/* ADC PLL N Register */#define SV_IREG_SYNTH_PLL_M	0x26	/* Synthesizer PLL M Register */#define SV_IREG_SYNTH_PLL_N	0x27	/* Synthesizer PLL N Register */#define SV_IREG_MPU401		0x2a	/* MPU-401 UART Operation */#define SV_IREG_DRIVE_CTRL	0x2b	/* Drive Control */#define SV_IREG_SRS_SPACE	0x2c	/* SRS Space Control */#define SV_IREG_SRS_CENTER	0x2d	/* SRS Center Control */#define SV_IREG_WAVE_SOURCE	0x2e	/* Wavetable Sample Source Select */#define SV_IREG_ANALOG_POWER	0x30	/* Analog Power Down Control */#define SV_IREG_DIGITAL_POWER	0x31	/* Digital Power Down Control */#define SV_IREG_ADC_PLL		SV_IREG_ADC_PLL_M#define SV_IREG_SYNTH_PLL	SV_IREG_SYNTH_PLL_M/* *  DMA registers */#define SV_DMA_ADDR0		0x00#define SV_DMA_ADDR1		0x01#define SV_DMA_ADDR2		0x02#define SV_DMA_ADDR3		0x03#define SV_DMA_COUNT0		0x04#define SV_DMA_COUNT1		0x05#define SV_DMA_COUNT2		0x06#define SV_DMA_MODE		0x0b#define SV_DMA_RESET		0x0d#define SV_DMA_MASK		0x0f/* *  Record sources */#define SV_RECSRC_RESERVED	(0x00<<5)#define SV_RECSRC_CD		(0x01<<5)#define SV_RECSRC_DAC		(0x02<<5)#define SV_RECSRC_AUX2		(0x03<<5)#define SV_RECSRC_LINE		(0x04<<5)#define SV_RECSRC_AUX1		(0x05<<5)#define SV_RECSRC_MIC		(0x06<<5)#define SV_RECSRC_OUT		(0x07<<5)/* *  constants */#define SV_FULLRATE		48000#define SV_REFFREQUENCY		24576000#define SV_ADCMULT		512#define SV_MODE_PLAY		1#define SV_MODE_CAPTURE		2/* */struct sonicvibes {	unsigned long dma1size;	unsigned long dma2size;	int irq;	unsigned long sb_port;	unsigned long enh_port;	unsigned long synth_port;	unsigned long midi_port;	unsigned long game_port;	unsigned int dmaa_port;	struct resource *res_dmaa;	unsigned int dmac_port;	struct resource *res_dmac;	unsigned char enable;	unsigned char irqmask;	unsigned char revision;	unsigned char format;	unsigned char srs_space;	unsigned char srs_center;	unsigned char mpu_switch;	unsigned char wave_source;	unsigned int mode;	struct pci_dev *pci;	struct snd_card *card;	struct snd_pcm *pcm;	struct snd_pcm_substream *playback_substream;	struct snd_pcm_substream *capture_substream;	struct snd_rawmidi *rmidi;	struct snd_hwdep *fmsynth;	/* S3FM */	spinlock_t reg_lock;	unsigned int p_dma_size;	unsigned int c_dma_size;	struct snd_kcontrol *master_mute;	struct snd_kcontrol *master_volume;#ifdef SUPPORT_JOYSTICK	struct gameport *gameport;#endif};static struct pci_device_id snd_sonic_ids[] = {	{ 0x5333, 0xca00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },        { 0, }};MODULE_DEVICE_TABLE(pci, snd_sonic_ids);static struct snd_ratden sonicvibes_adc_clock = {	.num_min = 4000 * 65536,	.num_max = 48000UL * 65536,	.num_step = 1,	.den = 65536,};static struct snd_pcm_hw_constraint_ratdens snd_sonicvibes_hw_constraints_adc_clock = {	.nrats = 1,	.rats = &sonicvibes_adc_clock,};/* *  common I/O routines */static inline void snd_sonicvibes_setdmaa(struct sonicvibes * sonic,					  unsigned int addr,					  unsigned int count){	count--;	outl(addr, sonic->dmaa_port + SV_DMA_ADDR0);	outl(count, sonic->dmaa_port + SV_DMA_COUNT0);	outb(0x18, sonic->dmaa_port + SV_DMA_MODE);#if 0	printk("program dmaa: addr = 0x%x, paddr = 0x%x\n", addr, inl(sonic->dmaa_port + SV_DMA_ADDR0));#endif}static inline void snd_sonicvibes_setdmac(struct sonicvibes * sonic,					  unsigned int addr,					  unsigned int count){	/* note: dmac is working in word mode!!! */	count >>= 1;	count--;	outl(addr, sonic->dmac_port + SV_DMA_ADDR0);	outl(count, sonic->dmac_port + SV_DMA_COUNT0);	outb(0x14, sonic->dmac_port + SV_DMA_MODE);#if 0	printk("program dmac: addr = 0x%x, paddr = 0x%x\n", addr, inl(sonic->dmac_port + SV_DMA_ADDR0));#endif}static inline unsigned int snd_sonicvibes_getdmaa(struct sonicvibes * sonic){	return (inl(sonic->dmaa_port + SV_DMA_COUNT0) & 0xffffff) + 1;}static inline unsigned int snd_sonicvibes_getdmac(struct sonicvibes * sonic){	/* note: dmac is working in word mode!!! */	return ((inl(sonic->dmac_port + SV_DMA_COUNT0) & 0xffffff) + 1) << 1;}static void snd_sonicvibes_out1(struct sonicvibes * sonic,				unsigned char reg,				unsigned char value){	outb(reg, SV_REG(sonic, INDEX));	udelay(10);	outb(value, SV_REG(sonic, DATA));	udelay(10);}static void snd_sonicvibes_out(struct sonicvibes * sonic,			       unsigned char reg,			       unsigned char value){	unsigned long flags;	spin_lock_irqsave(&sonic->reg_lock, flags);	outb(reg, SV_REG(sonic, INDEX));	udelay(10);	outb(value, SV_REG(sonic, DATA));	udelay(10);	spin_unlock_irqrestore(&sonic->reg_lock, flags);}static unsigned char snd_sonicvibes_in1(struct sonicvibes * sonic, unsigned char reg){	unsigned char value;	outb(reg, SV_REG(sonic, INDEX));	udelay(10);	value = inb(SV_REG(sonic, DATA));	udelay(10);	return value;}static unsigned char snd_sonicvibes_in(struct sonicvibes * sonic, unsigned char reg){	unsigned long flags;	unsigned char value;	spin_lock_irqsave(&sonic->reg_lock, flags);	outb(reg, SV_REG(sonic, INDEX));	udelay(10);	value = inb(SV_REG(sonic, DATA));	udelay(10);	spin_unlock_irqrestore(&sonic->reg_lock, flags);	return value;}#if 0static void snd_sonicvibes_debug(struct sonicvibes * sonic){	printk("SV REGS:          INDEX = 0x%02x  ", inb(SV_REG(sonic, INDEX)));	printk("                 STATUS = 0x%02x\n", inb(SV_REG(sonic, STATUS)));	printk("  0x00: left input      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x00));	printk("  0x20: synth rate low  = 0x%02x\n", snd_sonicvibes_in(sonic, 0x20));	printk("  0x01: right input     = 0x%02x  ", snd_sonicvibes_in(sonic, 0x01));	printk("  0x21: synth rate high = 0x%02x\n", snd_sonicvibes_in(sonic, 0x21));	printk("  0x02: left AUX1       = 0x%02x  ", snd_sonicvibes_in(sonic, 0x02));	printk("  0x22: ADC clock       = 0x%02x\n", snd_sonicvibes_in(sonic, 0x22));	printk("  0x03: right AUX1      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x03));	printk("  0x23: ADC alt rate    = 0x%02x\n", snd_sonicvibes_in(sonic, 0x23));	printk("  0x04: left CD         = 0x%02x  ", snd_sonicvibes_in(sonic, 0x04));	printk("  0x24: ADC pll M       = 0x%02x\n", snd_sonicvibes_in(sonic, 0x24));	printk("  0x05: right CD        = 0x%02x  ", snd_sonicvibes_in(sonic, 0x05));	printk("  0x25: ADC pll N       = 0x%02x\n", snd_sonicvibes_in(sonic, 0x25));	printk("  0x06: left line       = 0x%02x  ", snd_sonicvibes_in(sonic, 0x06));	printk("  0x26: Synth pll M     = 0x%02x\n", snd_sonicvibes_in(sonic, 0x26));	printk("  0x07: right line      = 0x%02x  ", snd_sonicvibes_in(sonic, 0x07));	printk("  0x27: Synth pll N     = 0x%02x\n", snd_sonicvibes_in(sonic, 0x27));	printk("  0x08: MIC             = 0x%02x  ", snd_sonicvibes_in(sonic, 0x08));	printk("  0x28: ---             = 0x%02x\n", snd_sonicvibes_in(sonic, 0x28));	printk("  0x09: Game port       = 0x%02x  ", snd_sonicvibes_in(sonic, 0x09));

⌨️ 快捷键说明

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