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

📄 i810_audio.c

📁 宋宝华的《Linux设备驱动开发详解》第一版的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *	Intel i810 and friends ICH driver for Linux *	Alan Cox <alan@redhat.com> * *  Built from: *	Low level code:  Zach Brown (original nonworking i810 OSS driver) *			 Jaroslav Kysela <perex@suse.cz> (working ALSA driver) * *	Framework: Thomas Sailer <sailer@ife.ee.ethz.ch> *	Extended by: Zach Brown <zab@redhat.com>   *			and others.. * *  Hardware Provided By: *	Analog Devices (A major AC97 codec maker) *	Intel Corp  (you've probably heard of them already) * *  AC97 clues and assistance provided by *	Analog Devices *	Zach 'Fufu' Brown *	Jeff Garzik * *	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. * * *	Intel 810 theory of operation * *	The chipset provides three DMA channels that talk to an AC97 *	CODEC (AC97 is a digital/analog mixer standard). At its simplest *	you get 48Khz audio with basic volume and mixer controls. At the *	best you get rate adaption in the codec. We set the card up so *	that we never take completion interrupts but instead keep the card *	chasing its tail around a ring buffer. This is needed for mmap *	mode audio and happens to work rather well for non-mmap modes too. * *	The board has one output channel for PCM audio (supported) and *	a stereo line in and mono microphone input. Again these are normally *	locked to 48Khz only. Right now recording is not finished. * *	There is no midi support, no synth support. Use timidity. To get *	esd working you need to use esd -r 48000 as it won't probe 48KHz *	by default. mpg123 can't handle 48Khz only audio so use xmms. * *	Fix The Sound On Dell * *	Not everyone uses 48KHz. We know of no way to detect this reliably *	and certainly not to get the right data. If your i810 audio sounds *	stupid you may need to investigate other speeds. According to Analog *	they tend to use a 14.318MHz clock which gives you a base rate of *	41194Hz. * *	This is available via the 'ftsodell=1' option.  * *	If you need to force a specific rate set the clocking= option * *	This driver is cursed. (Ben LaHaise) * *  ICH 3 caveats *	Intel errata #7 for ICH3 IO. We need to disable SMI stuff *	when codec probing. [Not Yet Done] * *  ICH 4 caveats * *	The ICH4 has the feature, that the codec ID doesn't have to be  *	congruent with the IO connection. *  *	Therefore, from driver version 0.23 on, there is a "codec ID" <-> *	"IO register base offset" mapping (card->ac97_id_map) field. *    *	Juergen "George" Sawinski (jsaw)  */ #include <linux/module.h>#include <linux/string.h>#include <linux/ctype.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/interrupt.h>#include <asm/io.h>#include <asm/dma.h>#include <linux/init.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <linux/smp_lock.h>#include <linux/ac97_codec.h>#include <linux/bitops.h>#include <asm/uaccess.h>#define DRIVER_VERSION "1.01"#define MODULOP2(a, b) ((a) & ((b) - 1))#define MASKP2(a, b) ((a) & ~((b) - 1))static int ftsodell;static int strict_clocking;static unsigned int clocking;static int spdif_locked;static int ac97_quirk = AC97_TUNE_DEFAULT;//#define DEBUG//#define DEBUG2//#define DEBUG_INTERRUPTS//#define DEBUG_MMAP//#define DEBUG_MMIO#define ADC_RUNNING	1#define DAC_RUNNING	2#define I810_FMT_16BIT	1#define I810_FMT_STEREO	2#define I810_FMT_MASK	3#define SPDIF_ON	0x0004#define SURR_ON		0x0010#define CENTER_LFE_ON	0x0020#define VOL_MUTED	0x8000/* the 810's array of pointers to data buffers */struct sg_item {#define BUSADDR_MASK	0xFFFFFFFE	u32 busaddr;	#define CON_IOC 	0x80000000 /* interrupt on completion */#define CON_BUFPAD	0x40000000 /* pad underrun with last sample, else 0 */#define CON_BUFLEN_MASK	0x0000ffff /* buffer length in samples */	u32 control;};/* an instance of the i810 channel */#define SG_LEN 32struct i810_channel {	/* these sg guys should probably be allocated	   separately as nocache. Must be 8 byte aligned */	struct sg_item sg[SG_LEN];	/* 32*8 */	u32 offset;			/* 4 */	u32 port;			/* 4 */	u32 used;	u32 num;};/* * we have 3 separate dma engines.  pcm in, pcm out, and mic. * each dma engine has controlling registers.  These goofy * names are from the datasheet, but make it easy to write * code while leafing through it. * * ICH4 has 6 dma engines, pcm in, pcm out, mic, pcm in 2,  * mic in 2, s/pdif.   Of special interest is the fact that * the upper 3 DMA engines on the ICH4 *must* be accessed * via mmio access instead of pio access. */#define ENUM_ENGINE(PRE,DIG) 									\enum {												\	PRE##_BASE =	0x##DIG##0,		/* Base Address */				\	PRE##_BDBAR =	0x##DIG##0,		/* Buffer Descriptor list Base Address */	\	PRE##_CIV =	0x##DIG##4,		/* Current Index Value */			\	PRE##_LVI =	0x##DIG##5,		/* Last Valid Index */				\	PRE##_SR =	0x##DIG##6,		/* Status Register */				\	PRE##_PICB =	0x##DIG##8,		/* Position In Current Buffer */		\	PRE##_PIV =	0x##DIG##a,		/* Prefetched Index Value */			\	PRE##_CR =	0x##DIG##b		/* Control Register */				\}ENUM_ENGINE(OFF,0);	/* Offsets */ENUM_ENGINE(PI,0);	/* PCM In */ENUM_ENGINE(PO,1);	/* PCM Out */ENUM_ENGINE(MC,2);	/* Mic In */enum {	GLOB_CNT =	0x2c,			/* Global Control */	GLOB_STA = 	0x30,			/* Global Status */	CAS	 = 	0x34			/* Codec Write Semaphore Register */};ENUM_ENGINE(MC2,4);     /* Mic In 2 */ENUM_ENGINE(PI2,5);     /* PCM In 2 */ENUM_ENGINE(SP,6);      /* S/PDIF */enum {	SDM =           0x80                    /* SDATA_IN Map Register */};/* interrupts for a dma engine */#define DMA_INT_FIFO		(1<<4)  /* fifo under/over flow */#define DMA_INT_COMPLETE	(1<<3)  /* buffer read/write complete and ioc set */#define DMA_INT_LVI		(1<<2)  /* last valid done */#define DMA_INT_CELV		(1<<1)  /* last valid is current */#define DMA_INT_DCH		(1)	/* DMA Controller Halted (happens on LVI interrupts) */#define DMA_INT_MASK (DMA_INT_FIFO|DMA_INT_COMPLETE|DMA_INT_LVI)/* interrupts for the whole chip */#define INT_SEC		(1<<11)#define INT_PRI		(1<<10)#define INT_MC		(1<<7)#define INT_PO		(1<<6)#define INT_PI		(1<<5)#define INT_MO		(1<<2)#define INT_NI		(1<<1)#define INT_GPI		(1<<0)#define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI)/* magic numbers to protect our data structures */#define I810_CARD_MAGIC		0x5072696E /* "Prin" */#define I810_STATE_MAGIC	0x63657373 /* "cess" */#define I810_DMA_MASK		0xffffffff /* DMA buffer mask for pci_alloc_consist */#define NR_HW_CH		3/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */#define NR_AC97                 4/* Please note that an 8bit mono stream is not valid on this card, you must have a 16bit *//* stream at a minimum for this card to be happy */static const unsigned sample_size[] = { 1, 2, 2, 4 };/* Samples are 16bit values, so we are shifting to a word, not to a byte, hence shift *//* values are one less than might be expected */static const unsigned sample_shift[] = { -1, 0, 0, 1 };enum {	ICH82801AA = 0,	ICH82901AB,	INTEL440MX,	INTELICH2,	INTELICH3,	INTELICH4,	INTELICH5,	SI7012,	NVIDIA_NFORCE,	AMD768,	AMD8111};static char * card_names[] = {	"Intel ICH 82801AA",	"Intel ICH 82901AB",	"Intel 440MX",	"Intel ICH2",	"Intel ICH3",	"Intel ICH4",	"Intel ICH5",	"SiS 7012",	"NVIDIA nForce Audio",	"AMD 768",	"AMD-8111 IOHub"};/* These are capabilities (and bugs) the chipsets _can_ have */static struct {	int16_t      nr_ac97;#define CAP_MMIO                 0x0001#define CAP_20BIT_AUDIO_SUPPORT  0x0002	u_int16_t flags;} card_cap[] = {	{  1, 0x0000 }, /* ICH82801AA */	{  1, 0x0000 }, /* ICH82901AB */	{  1, 0x0000 }, /* INTEL440MX */	{  1, 0x0000 }, /* INTELICH2 */	{  2, 0x0000 }, /* INTELICH3 */ 	{  3, 0x0003 }, /* INTELICH4 */	{  3, 0x0003 }, /* INTELICH5 */	/*@FIXME to be verified*/	{  2, 0x0000 }, /* SI7012 */	/*@FIXME to be verified*/	{  2, 0x0000 }, /* NVIDIA_NFORCE */	/*@FIXME to be verified*/	{  2, 0x0000 }, /* AMD768 */	/*@FIXME to be verified*/	{  3, 0x0001 }, /* AMD8111 */};static struct pci_device_id i810_pci_tbl [] = {	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_5,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82801AA},	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_5,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82901AB},	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_440MX,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTEL440MX},	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_4,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH2},	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_5,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH3},	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_5,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_5,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH5},	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7012,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, SI7012},	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7445,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768},	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AUDIO,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111},	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_5,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_18,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},	{PCI_VENDOR_ID_NVIDIA,  PCI_DEVICE_ID_NVIDIA_CK804_AUDIO,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},	{0,}};MODULE_DEVICE_TABLE (pci, i810_pci_tbl);#ifdef CONFIG_PM#define PM_SUSPENDED(card) (card->pm_suspended)#else#define PM_SUSPENDED(card) (0)#endif/* "software" or virtual channel, an instance of opened /dev/dsp */struct i810_state {	unsigned int magic;	struct i810_card *card;	/* Card info */	/* single open lock mechanism, only used for recording */	struct semaphore open_sem;	wait_queue_head_t open_wait;	/* file mode */	mode_t open_mode;	/* virtual channel number */	int virt;#ifdef CONFIG_PM	unsigned int pm_saved_dac_rate,pm_saved_adc_rate;#endif	struct dmabuf {		/* wave sample stuff */		unsigned int rate;		unsigned char fmt, enable, trigger;		/* hardware channel */		struct i810_channel *read_channel;		struct i810_channel *write_channel;		/* OSS buffer management stuff */		void *rawbuf;		dma_addr_t dma_handle;		unsigned buforder;		unsigned numfrag;		unsigned fragshift;		/* our buffer acts like a circular ring */		unsigned hwptr;		/* where dma last started, updated by update_ptr */		unsigned swptr;		/* where driver last clear/filled, updated by read/write */		int count;		/* bytes to be consumed or been generated by dma machine */		unsigned total_bytes;	/* total bytes dmaed by hardware */		unsigned error;		/* number of over/underruns */		wait_queue_head_t wait;	/* put process on wait queue when no more space in buffer */		/* redundant, but makes calculations easier */		/* what the hardware uses */		unsigned dmasize;		unsigned fragsize;		unsigned fragsamples;		/* what we tell the user to expect */		unsigned userfrags;		unsigned userfragsize;		/* OSS stuff */		unsigned mapped:1;		unsigned ready:1;		unsigned update_flag;		unsigned ossfragsize;		unsigned ossmaxfrags;		unsigned subdivision;	} dmabuf;};struct i810_card {	unsigned int magic;	/* We keep i810 cards in a linked list */	struct i810_card *next;	/* The i810 has a certain amount of cross channel interaction	   so we use a single per card lock */	spinlock_t lock;		/* Control AC97 access serialization */	spinlock_t ac97_lock;	/* PCI device stuff */	struct pci_dev * pci_dev;	u16 pci_id;	u16 pci_id_internal; /* used to access card_cap[] */#ifdef CONFIG_PM		u16 pm_suspended;	int pm_saved_mixer_settings[SOUND_MIXER_NRDEVICES][NR_AC97];#endif	/* soundcore stuff */	int dev_audio;	/* structures for abstraction of hardware facilities, codecs, banks and channels*/	u16    ac97_id_map[NR_AC97];	struct ac97_codec *ac97_codec[NR_AC97];	struct i810_state *states[NR_HW_CH];	struct i810_channel *channel;	/* 1:1 to states[] but diff. lifetime */	dma_addr_t chandma;	u16 ac97_features;	u16 ac97_status;	u16 channels;		/* hardware resources */	unsigned long ac97base;	unsigned long iobase;	u32 irq;	unsigned long ac97base_mmio_phys;	unsigned long iobase_mmio_phys;	u_int8_t __iomem *ac97base_mmio;	u_int8_t __iomem *iobase_mmio;	int           use_mmio;		/* Function support */	struct i810_channel *(*alloc_pcm_channel)(struct i810_card *);	struct i810_channel *(*alloc_rec_pcm_channel)(struct i810_card *);	struct i810_channel *(*alloc_rec_mic_channel)(struct i810_card *);	void (*free_pcm_channel)(struct i810_card *, int chan);	/* We have a *very* long init time possibly, so use this to block */	/* attempts to open our devices before we are ready (stops oops'es) */	int initializing;};/* extract register offset from codec struct */#define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id])#define I810_IOREAD(size, type, card, off)				\({									\

⌨️ 快捷键说明

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