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

📄 ite8172.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *      ite8172.c  --  ITE IT8172G Sound Driver. * * Copyright 2001 MontaVista Software Inc. * Author: MontaVista Software, Inc. *         	stevel@mvista.com or source@mvista.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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT, *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *  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. * * * Module command line parameters: * *  Supported devices: *  /dev/dsp    standard OSS /dev/dsp device *  /dev/mixer  standard OSS /dev/mixer device * * Notes: * *  1. Much of the OSS buffer allocation, ioctl's, and mmap'ing are *     taken, slightly modified or not at all, from the ES1371 driver, *     so refer to the credits in es1371.c for those. The rest of the *     code (probe, open, read, write, the ISR, etc.) is new. *  2. The following support is untested: *      * Memory mapping the audio buffers, and the ioctl controls that go *        with it. *      * S/PDIF output. *  3. The following is not supported: *      * I2S input. *      * legacy audio mode. *  4. Support for volume button interrupts is implemented but doesn't *     work yet. * *  Revision history *    02.08.2001  0.1   Initial release */#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/init.h>#include <linux/poll.h>#include <linux/bitops.h>#include <linux/proc_fs.h>#include <linux/spinlock.h>#include <linux/smp_lock.h>#include <linux/ac97_codec.h>#include <linux/wrapper.h>#include <asm/io.h>#include <asm/dma.h>#include <asm/uaccess.h>#include <asm/hardirq.h>#include <asm/it8172/it8172.h>/* --------------------------------------------------------------------- */#undef OSS_DOCUMENTED_MIXER_SEMANTICS#define IT8172_DEBUG#undef IT8172_VERBOSE_DEBUG#define DBG(x) {}static const unsigned sample_shift[] = { 0, 1, 1, 2 };/* * Audio Controller register bit definitions follow. See * include/asm/it8172/it8172.h for register offsets. *//* PCM Out Volume Reg */#define PCMOV_PCMOM	(1<<15)	/* PCM Out Mute default 1: mute */#define	PCMOV_PCMRCG_BIT 8	/* PCM Right channel Gain */#define	PCMOV_PCMRCG_MASK (0x1f<<PCMOV_PCMRCG_BIT)#define PCMOV_PCMLCG_BIT 0	/* PCM Left channel gain  */#define PCMOV_PCMLCG_MASK 0x1f/* FM Out Volume Reg */#define FMOV_FMOM       (1<<15)	/* FM Out Mute default 1: mute */#define	FMOV_FMRCG_BIT	8	/* FM Right channel Gain */#define	FMOV_FMRCG_MASK (0x1f<<FMOV_FMRCG_BIT)#define FMOV_FMLCG_BIT	0	/* FM Left channel gain  */#define FMOV_FMLCG_MASK 0x1f/* I2S Out Volume Reg */#define I2SV_I2SOM	 (1<<15) /* I2S Out Mute default 1: mute */#define	I2SV_I2SRCG_BIT	 8	 /* I2S Right channel Gain */#define	I2SV_I2SRCG_MASK (0x1f<<I2SV_I2SRCG_BIT)#define I2SV_I2SLCG_BIT	 0	 /* I2S Left channel gain  */#define I2SV_I2SLCG_MASK 0x1f/* Digital Recording Source Select Reg */#define	DRSS_BIT   0#define	DRSS_MASK  0x07#define   DRSS_AC97_PRIM 0#define   DRSS_FM        1#define   DRSS_I2S       2#define   DRSS_PCM       3#define   DRSS_AC97_SEC  4/* Playback/Capture Channel Control Registers */#define	CC_SM	        (1<<15)	/* Stereo, Mone 0: mono 1: stereo */#define	CC_DF	        (1<<14)	/* Data Format 0: 8 bit 1: 16 bit */#define CC_FMT_BIT      14#define CC_FMT_MASK     (0x03<<CC_FMT_BIT)#define CC_CF_BIT       12      /* Channel format (Playback only) */#define CC_CF_MASK      (0x03<<CC_CF_BIT)#define	  CC_CF_2	0#define   CC_CF_4	(1<<CC_CF_BIT)#define   CC_CF_6	(2<<CC_CF_BIT)#define CC_SR_BIT       8       /* sample Rate */#define CC_SR_MASK      (0x0f<<CC_SR_BIT)#define	  CC_SR_5500	0#define	  CC_SR_8000	(1<<CC_SR_BIT)#define	  CC_SR_9600	(2<<CC_SR_BIT)#define	  CC_SR_11025	(3<<CC_SR_BIT)#define	  CC_SR_16000	(4<<CC_SR_BIT)#define	  CC_SR_19200	(5<<CC_SR_BIT)#define	  CC_SR_22050	(6<<CC_SR_BIT)#define	  CC_SR_32000	(7<<CC_SR_BIT)#define	  CC_SR_38400	(8<<CC_SR_BIT)#define	  CC_SR_44100	(9<<CC_SR_BIT)#define	  CC_SR_48000	(10<<CC_SR_BIT)#define	CC_CSP	        (1<<7)	/* Channel stop 				 * 0: End of Current buffer				 * 1: Immediately stop when rec stop */#define CC_CP	        (1<<6)	/* Channel pause 0: normal, 1: pause */#define	CC_CA	        (1<<5)	/* Channel Action 0: Stop , 1: start */#define	CC_CB2L         (1<<2)	/* Cur. buf. 2 xfr is last 0: No, 1: Yes */#define CC_CB1L         (1<<1)	/* Cur. buf. 1 xfr is last 0: No, 1: Yes */#define CC_DE	        1	/* DFC/DFIFO Data Empty 1: empty, 0: not empty				 * (Playback only)				 *//* Codec Control Reg */#define CODECC_GME	(1<<9)	/* AC97 GPIO Mode enable */#define	CODECC_ATM	(1<<8)	/* AC97 ATE test mode 0: test 1: normal */#define	CODECC_WR	(1<<6)	/* AC97 Warn reset 1: warm reset , 0: Normal */#define	CODECC_CR	(1<<5)	/* AC97 Cold reset 1: Cold reset , 0: Normal *//* I2S Control Reg	*/#define	I2SMC_SR_BIT	 6	/* I2S Sampling rate 				 * 00: 48KHz, 01: 44.1 KHz, 10: 32 32 KHz */#define	I2SMC_SR_MASK    (0x03<<I2SMC_SR_BIT)#define	  I2SMC_SR_48000 0#define	  I2SMC_SR_44100 (1<<I2SMC_SR_BIT)#define	  I2SMC_SR_32000 (2<<I2SMC_SR_BIT)#define	I2SMC_SRSS	 (1<<5)	/* Sample Rate Source Select 1:S/W, 0: H/W */#define I2SMC_I2SF_BIT	 0	/* I2S Format */#define I2SMC_I2SF_MASK  0x03#define   I2SMC_I2SF_DAC 0#define   I2SMC_I2SF_ADC 2#define   I2SMC_I2SF_I2S 3/* Volume up, Down, Mute */#define	VS_VMP	(1<<2)	/* Volume mute 1: pushed, 0: not */#define	VS_VDP	(1<<1)	/* Volume Down 1: pushed, 0: not */#define VS_VUP	1	/* Volime Up 1: pushed, 0: not *//* SRC, Mixer test control/DFC status reg */#define SRCS_DPUSC      (1<<5)	/* DFC Playback underrun Status/clear */#define	SRCS_DCOSC	(1<<4)	/* DFC Capture Overrun Status/clear */#define SRCS_SIS	(1<<3)	/* SRC input select 1: Mixer, 0: Codec I/F */#define SRCS_CDIS_BIT	0	/* Codec Data Input Select */#define SRCS_CDIS_MASK  0x07#define   SRCS_CDIS_MIXER 0#define   SRCS_CDIS_PCM   1#define   SRCS_CDIS_I2S   2#define   SRCS_CDIS_FM    3#define   SRCS_CDIS_DFC   4/* Codec Index Reg command Port */#define CIRCP_CID_BIT   10#define CIRCP_CID_MASK  (0x03<<CIRCP_CID_BIT)#define CIRCP_CPS	(1<<9)	/* Command Port Status 0: ready, 1: busy */#define	CIRCP_DPVF	(1<<8)	/* Data Port Valid Flag 0: invalis, 1: valid */#define CIRCP_RWC	(1<<7)	/* Read/write command */#define CIRCP_CIA_BIT   0#define CIRCP_CIA_MASK  0x007F	/* Codec Index Address *//* Test Mode Control/Test group Select Control *//* General Control Reg */#define GC_VDC_BIT	6	/* Volume Division Control */#define GC_VDC_MASK     (0x03<<GC_VDC_BIT)#define   GC_VDC_NONE   0#define   GC_VDC_DIV2   (1<<GC_VDC_BIT)#define   GC_VDC_DIV4   (2<<GC_VDC_BIT)#define	GC_SOE	        (1<<2)	/* S/PDIF Output enable */#define	GC_SWR	        1	/* Software warn reset *//* Interrupt mask Control Reg */#define	IMC_VCIM	(1<<6)	/* Volume CNTL interrupt mask */#define	IMC_CCIM	(1<<1)	/* Capture Chan. iterrupt mask */#define	IMC_PCIM	1	/* Playback Chan. interrupt mask *//* Interrupt status/clear reg */#define	ISC_VCI	        (1<<6)	/* Volume CNTL interrupt 1: clears */#define	ISC_CCI	        (1<<1)	/* Capture Chan. interrupt 1: clears  */#define	ISC_PCI	        1	/* Playback Chan. interrupt 1: clears *//* misc stuff */#define POLL_COUNT   0x5000#define IT8172_MODULE_NAME "IT8172 audio"#define PFX IT8172_MODULE_NAME ": "/* --------------------------------------------------------------------- */struct it8172_state {    /* list of it8172 devices */    struct list_head devs;    /* the corresponding pci_dev structure */    struct pci_dev *dev;    /* soundcore stuff */    int dev_audio;    /* hardware resources */    unsigned long io;    unsigned int irq;    /* PCI ID's */    u16 vendor;    u16 device;    u8 rev; /* the chip revision */    /* options */    int spdif_volume; /* S/PDIF output is enabled if != -1 */#ifdef IT8172_DEBUG    /* debug /proc entry */    struct proc_dir_entry *ps;    struct proc_dir_entry *ac97_ps;#endif /* IT8172_DEBUG */    struct ac97_codec codec;    unsigned short pcc, capcc;    unsigned dacrate, adcrate;    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;	void* nextIn;	void* nextOut;	int count;	int curBufPtr;	unsigned total_bytes;	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 stopped:1;	unsigned ossfragshift;	int ossmaxfrags;	unsigned subdivision;    } dma_dac, dma_adc;};/* --------------------------------------------------------------------- */static LIST_HEAD(devs);/* --------------------------------------------------------------------- */extern 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++;    return r;}/* --------------------------------------------------------------------- */static void it8172_delay(int msec){    unsigned long tmo;    signed long tmo2;    if (in_interrupt())	return;        tmo = jiffies + (msec*HZ)/1000;    for (;;) {	tmo2 = tmo - jiffies;	if (tmo2 <= 0)	    break;	schedule_timeout(tmo2);    }}static unsigned shortget_compat_rate(unsigned* rate){    unsigned rate_out = *rate;    unsigned short sr;        if (rate_out >= 46050) {	sr = CC_SR_48000; rate_out = 48000;    } else if (rate_out >= 41250) {	sr = CC_SR_44100; rate_out = 44100;    } else if (rate_out >= 35200) {	sr = CC_SR_38400; rate_out = 38400;    } else if (rate_out >= 27025) {	sr = CC_SR_32000; rate_out = 32000;    } else if (rate_out >= 20625) {	sr = CC_SR_22050; rate_out = 22050;    } else if (rate_out >= 17600) {	sr = CC_SR_19200; rate_out = 19200;    } else if (rate_out >= 13513) {	sr = CC_SR_16000; rate_out = 16000;    } else if (rate_out >= 10313) {	sr = CC_SR_11025; rate_out = 11025;    } else if (rate_out >= 8800) {	sr = CC_SR_9600; rate_out = 9600;    } else if (rate_out >= 6750) {	sr = CC_SR_8000; rate_out = 8000;    } else {	sr = CC_SR_5500; rate_out = 5500;    }    *rate = rate_out;    return sr;}static void set_adc_rate(struct it8172_state *s, unsigned rate){    unsigned long flags;    unsigned short sr;        sr = get_compat_rate(&rate);    spin_lock_irqsave(&s->lock, flags);    s->capcc &= ~CC_SR_MASK;    s->capcc |= sr;    outw(s->capcc, s->io+IT_AC_CAPCC);    spin_unlock_irqrestore(&s->lock, flags);    s->adcrate = rate;}static void set_dac_rate(struct it8172_state *s, unsigned rate){    unsigned long flags;    unsigned short sr;        sr = get_compat_rate(&rate);    spin_lock_irqsave(&s->lock, flags);    s->pcc &= ~CC_SR_MASK;    s->pcc |= sr;    outw(s->pcc, s->io+IT_AC_PCC);    spin_unlock_irqrestore(&s->lock, flags);    s->dacrate = rate;}/* --------------------------------------------------------------------- */static u16 rdcodec(struct ac97_codec *codec, u8 addr){    struct it8172_state *s = (struct it8172_state *)codec->private_data;    unsigned long flags;    unsigned short circp, data;    int i;        spin_lock_irqsave(&s->lock, flags);    for (i = 0; i < POLL_COUNT; i++)	if (!(inw(s->io+IT_AC_CIRCP) & CIRCP_CPS))	    break;    if (i == POLL_COUNT)	printk(KERN_INFO PFX "rdcodec: codec ready poll expired!\n");    circp = addr & CIRCP_CIA_MASK;    circp |= (codec->id << CIRCP_CID_BIT);    circp |= CIRCP_RWC; // read command    outw(circp, s->io+IT_AC_CIRCP);    /* now wait for the data */    for (i = 0; i < POLL_COUNT; i++)	if (inw(s->io+IT_AC_CIRCP) & CIRCP_DPVF)	    break;    if (i == POLL_COUNT)	printk(KERN_INFO PFX "rdcodec: read poll expired!\n");    data = inw(s->io+IT_AC_CIRDP);    spin_unlock_irqrestore(&s->lock, flags);    return data;}static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data){    struct it8172_state *s = (struct it8172_state *)codec->private_data;    unsigned long flags;    unsigned short circp;    int i;        spin_lock_irqsave(&s->lock, flags);    for (i = 0; i < POLL_COUNT; i++)	if (!(inw(s->io+IT_AC_CIRCP) & CIRCP_CPS))	    break;    if (i == POLL_COUNT)	printk(KERN_INFO PFX "wrcodec: codec ready poll expired!\n");    circp = addr & CIRCP_CIA_MASK;    circp |= (codec->id << CIRCP_CID_BIT);    circp &= ~CIRCP_RWC; // write command    outw(data,  s->io+IT_AC_CIRDP);  // send data first    outw(circp, s->io+IT_AC_CIRCP);    spin_unlock_irqrestore(&s->lock, flags);}static void waitcodec(struct ac97_codec *codec){    unsigned short temp;    /* codec_wait is used to wait for a ready state after       an AC97_RESET. */    it8172_delay(10);

⌨️ 快捷键说明

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