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

📄 cs46xx.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *	Crystal SoundFusion CS46xx driver * *	Copyright 1998-2001 Cirrus Logic Corporation <pcaudio@crystal.cirrus.com> *						<twoller@crystal.cirrus.com> *	Copyright 1999-2000 Jaroslav Kysela <perex@suse.cz> *	Copyright 2000 Alan Cox <alan@redhat.com> * *	The core of this code is taken from the ALSA project driver by  *	Jaroslav. Please send Jaroslav the credit for the driver and  *	report bugs in this port to <alan@redhat.com> * *	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. *	Current maintainers: *		Cirrus Logic Corporation, Thomas Woller (tw) *			<twoller@crystal.cirrus.com> *		Nils Faerber (nf) *			<nils@kernelconcepts.de> *		Thanks to David Pollard for testing. * *	Changes: *	20000909-nf	Changed cs_read, cs_write and drain_dac *	20001025-tw	Separate Playback/Capture structs and buffers. *			Added Scatter/Gather support for Playback. *			Added Capture. *	20001027-nf	Port to kernel 2.4.0-test9, some clean-ups *			Start of powermanagement support (CS46XX_PM). *	20001128-tw	Add module parm for default buffer order. *			added DMA_GFP flag to kmalloc dma buffer allocs. *			backfill silence to eliminate stuttering on *			underruns. *	20001201-tw	add resyncing of swptr on underruns. *	20001205-tw-nf	fixed GETOSPACE ioctl() after open() *	20010113-tw	patch from Hans Grobler general cleanup. *	20010117-tw	2.4.0 pci cleanup, wrapper code for 2.2.16-2.4.0 *	20010118-tw	basic PM support for 2.2.16+ and 2.4.0/2.4.2. *	20010228-dh	patch from David Huggins - cs_update_ptr recursion. *	20010409-tw	add hercules game theatre XP amp code. *	20010420-tw	cleanup powerdown/up code. *	20010521-tw	eliminate pops, and fixes for powerdown. *	20010525-tw	added fixes for thinkpads with powerdown logic. *	20010723-sh     patch from Horms (Simon Horman) - *	                SOUND_PCM_READ_BITS returns bits as set in driver *	                rather than a logical or of the possible values. *	                Various ioctls handle the case where the device *	                is open for reading or writing but not both better. * *	Status: *	Playback/Capture supported from 8k-48k. *	16Bit Signed LE & 8Bit Unsigned, with Mono or Stereo supported. * *	APM/PM - 2.2.x APM is enabled and functioning fine. APM can also *	be enabled for 2.4.x by modifying the CS46XX_ACPI_SUPPORT macro *	definition. * *      Hercules Game Theatre XP - the EGPIO2 pin controls the external Amp, *	so, use the drain/polarity to enable.   *	hercules_egpio_disable set to 1, will force a 0 to EGPIODR. * *	VTB Santa Cruz - the GPIO7/GPIO8 on the Secondary Codec control *	the external amplifier for the "back" speakers, since we do not *	support the secondary codec then this external amp is also not *	turned on. */ #include <linux/list.h>#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/bitops.h>#include <asm/io.h>#include <asm/dma.h>#include <linux/init.h>#include <linux/poll.h>#include <linux/smp_lock.h>#include <linux/wrapper.h>#include <asm/uaccess.h>#include <asm/hardirq.h>#include <linux/ac97_codec.h>#include "cs46xxpm-24.h"#include "cs46xx_wrapper-24.h"#include "cs461x.h"/* MIDI buffer sizes */#define CS_MIDIINBUF  500#define CS_MIDIOUTBUF 500#define ADC_RUNNING	1#define DAC_RUNNING	2#define CS_FMT_16BIT	1		/* These are fixed in fact */#define CS_FMT_STEREO	2#define CS_FMT_MASK	3#define CS_TYPE_ADC	1#define CS_TYPE_DAC	2#define CS_TRUE 	1#define CS_FALSE 	0#define CS_INC_USE_COUNT(m) (atomic_inc(m))#define CS_DEC_USE_COUNT(m) (atomic_dec(m))#define CS_DEC_AND_TEST(m) (atomic_dec_and_test(m))#define CS_IN_USE(m) (atomic_read(m) != 0)#define CS_DBGBREAKPOINT {__asm__("INT $3");}/* *	CS461x definitions */ #define CS461X_BA0_SIZE		0x2000#define CS461X_BA1_DATA0_SIZE	0x3000#define CS461X_BA1_DATA1_SIZE	0x3800#define CS461X_BA1_PRG_SIZE	0x7000#define CS461X_BA1_REG_SIZE	0x0100#define GOF_PER_SEC	200#define CSDEBUG_INTERFACE 1#define CSDEBUG 1/* * Turn on/off debugging compilation by using 1/0 respectively for CSDEBUG * * * CSDEBUG is usual mode is set to 1, then use the * cs_debuglevel and cs_debugmask to turn on or off debugging. * Debug level of 1 has been defined to be kernel errors and info * that should be printed on any released driver. */#if CSDEBUG#define CS_DBGOUT(mask,level,x) if((cs_debuglevel >= (level)) && ((mask) & cs_debugmask)) {x;} #else#define CS_DBGOUT(mask,level,x) #endif/* * cs_debugmask areas */#define CS_INIT	 	0x00000001		/* initialization and probe functions */#define CS_ERROR 	0x00000002		/* tmp debugging bit placeholder */#define CS_INTERRUPT	0x00000004		/* interrupt handler (separate from all other) */#define CS_FUNCTION 	0x00000008		/* enter/leave functions */#define CS_WAVE_WRITE 	0x00000010		/* write information for wave */#define CS_WAVE_READ 	0x00000020		/* read information for wave */#define CS_MIDI_WRITE 	0x00000040		/* write information for midi */#define CS_MIDI_READ 	0x00000080		/* read information for midi */#define CS_MPU401_WRITE 0x00000100		/* write information for mpu401 */#define CS_MPU401_READ 	0x00000200		/* read information for mpu401 */#define CS_OPEN		0x00000400		/* all open functions in the driver */#define CS_RELEASE	0x00000800		/* all release functions in the driver */#define CS_PARMS	0x00001000		/* functional and operational parameters */#define CS_IOCTL	0x00002000		/* ioctl (non-mixer) */#define CS_PM		0x00004000		/* PM */#define CS_TMP		0x10000000		/* tmp debug mask bit */#define CS_IOCTL_CMD_SUSPEND	0x1	// suspend#define CS_IOCTL_CMD_RESUME	0x2	// resume#if CSDEBUGstatic unsigned long cs_debuglevel=1;			/* levels range from 1-9 */MODULE_PARM(cs_debuglevel, "i");static unsigned long cs_debugmask=CS_INIT | CS_ERROR;	/* use CS_DBGOUT with various mask values */MODULE_PARM(cs_debugmask, "i");#endifstatic unsigned long hercules_egpio_disable=0;  /* if non-zero set all EGPIO to 0 */MODULE_PARM(hercules_egpio_disable, "i");static unsigned long initdelay=700;  /* PM delay in millisecs */MODULE_PARM(initdelay, "i");static unsigned long powerdown=-1;  /* turn on/off powerdown processing in driver */MODULE_PARM(powerdown, "i");#define DMABUF_DEFAULTORDER 3static unsigned long defaultorder=DMABUF_DEFAULTORDER;MODULE_PARM(defaultorder, "i");static int external_amp;MODULE_PARM(external_amp, "i");static int thinkpad;MODULE_PARM(thinkpad, "i");/** set the powerdown module parm to 0 to disable all * powerdown. also set thinkpad to 1 to disable powerdown, * but also to enable the clkrun functionality.*/static unsigned cs_powerdown=1;static unsigned cs_laptop_wait=1;/* An instance of the 4610 channel */struct cs_channel {	int used;	int num;	void *state;};#define CS46XX_MAJOR_VERSION "1"#define CS46XX_MINOR_VERSION "28"#ifdef __ia64__#define CS46XX_ARCH	     	"64"	//architecture key#else#define CS46XX_ARCH	     	"32"	//architecture key#endifstruct list_head cs46xx_devs = { &cs46xx_devs, &cs46xx_devs };/* magic numbers to protect our data structures */#define CS_CARD_MAGIC		0x43525553 /* "CRUS" */#define CS_STATE_MAGIC		0x4c4f4749 /* "LOGI" */#define NR_HW_CH		3/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */#define NR_AC97		2static const unsigned sample_size[] = { 1, 2, 2, 4 };static const unsigned sample_shift[] = { 0, 1, 1, 2 };/* "software" or virtual channel, an instance of opened /dev/dsp */struct cs_state {	unsigned int magic;	struct cs_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;		struct dmabuf {		/* wave sample stuff */		unsigned int rate;		unsigned char fmt, enable;		/* hardware channel */		struct cs_channel *channel;		int pringbuf;		/* Software ring slot */		void *pbuf;		/* 4K hardware DMA buffer */		/* OSS buffer management stuff */		void *rawbuf;		dma_addr_t dma_handle;		unsigned buforder;		unsigned numfrag;		unsigned fragshift;		unsigned divisor;		unsigned type;		void *tmpbuff;			/* tmp buffer for sample conversions */		dma_addr_t dmaaddr;		dma_addr_t dmaaddr_tmpbuff;		unsigned buforder_tmpbuff;	/* Log base 2 of size in bytes.. */		/* 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 comsumed or been generated by dma machine */		unsigned total_bytes;	/* total bytes dmaed by hardware */		unsigned blocks;	/* total blocks */		unsigned error;		/* number of over/underruns */		unsigned underrun;	/* underrun pending before next write has occurred */		wait_queue_head_t wait;	/* put process on wait queue when no more space in buffer */		/* redundant, but makes calculations easier */		unsigned fragsize;		unsigned dmasize;		unsigned fragsamples;		/* OSS stuff */		unsigned mapped:1;		unsigned ready:1;		unsigned endcleared:1;		unsigned SGok:1;		unsigned update_flag;		unsigned ossfragshift;		int ossmaxfrags;		unsigned subdivision;	} dmabuf;	/* Guard against mmap/write/read races */	struct semaphore sem;};struct cs_card {	struct cs_channel channel[2];	unsigned int magic;	/* We keep cs461x cards in a linked list */	struct cs_card *next;	/* The cs461x has a certain amount of cross channel interaction	   so we use a single per card lock */	spinlock_t lock;	/* mixer use count */	atomic_t mixer_use_cnt;	/* PCI device stuff */	struct pci_dev * pci_dev;	struct list_head list;	unsigned int pctl, cctl;	/* Hardware DMA flag sets */	/* soundcore stuff */	int dev_audio;	int dev_midi;	/* structures for abstraction of hardware facilities, codecs, banks and channels*/	struct ac97_codec *ac97_codec[NR_AC97];	struct cs_state *states[2];	u16 ac97_features;		int amplifier;			/* Amplifier control */	void (*amplifier_ctrl)(struct cs_card *, int);	void (*amp_init)(struct cs_card *);		int active;			/* Active clocking */	void (*active_ctrl)(struct cs_card *, int);		/* hardware resources */	unsigned long ba0_addr;	unsigned long ba1_addr;	u32 irq;		/* mappings */	void *ba0;	union	{		struct		{			u8 *data0;			u8 *data1;			u8 *pmem;			u8 *reg;		} name;		u8 *idx[4];	} ba1;		/* Function support */	struct cs_channel *(*alloc_pcm_channel)(struct cs_card *);	struct cs_channel *(*alloc_rec_pcm_channel)(struct cs_card *);	void (*free_pcm_channel)(struct cs_card *, int chan);	/* /dev/midi stuff */	struct {		unsigned ird, iwr, icnt;		unsigned ord, owr, ocnt;		wait_queue_head_t open_wait;		wait_queue_head_t iwait;		wait_queue_head_t owait;		spinlock_t lock;		unsigned char ibuf[CS_MIDIINBUF];		unsigned char obuf[CS_MIDIOUTBUF];		mode_t open_mode;		struct semaphore open_sem;	} midi;	struct cs46xx_pm pm;};static int cs_open_mixdev(struct inode *inode, struct file *file);static int cs_release_mixdev(struct inode *inode, struct file *file);static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,				unsigned long arg);static int cs_hardware_init(struct cs_card *card);static int cs46xx_powerup(struct cs_card *card, unsigned int type);static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag);static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type);static int cs46xx_suspend_tbl(struct pci_dev *pcidev, u32 state);static int cs46xx_resume_tbl(struct pci_dev *pcidev);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;		r += 4;	}	if (x >= 4) {		x >>= 2;		r += 2;	}	if (x >= 2)		r++;

⌨️ 快捷键说明

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