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

📄 es1371.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct proc_dir_entry *ps;#endif /* ES1371_DEBUG */	struct ac97_codec codec;	/* wave stuff */	unsigned ctrl;	unsigned sctrl;	unsigned dac1rate, dac2rate, 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;		unsigned hwptr, swptr;		unsigned total_bytes;		int count;		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 endcleared:1;		unsigned enabled:1;		unsigned ossfragshift;		int ossmaxfrags;		unsigned subdivision;	} dma_dac1, dma_dac2, dma_adc;	/* midi stuff */	struct {		unsigned ird, iwr, icnt;		unsigned ord, owr, ocnt;		wait_queue_head_t iwait;		wait_queue_head_t owait;		unsigned char ibuf[MIDIINBUF];		unsigned char obuf[MIDIOUTBUF];	} midi;	struct gameport gameport;	struct semaphore sem;};/* --------------------------------------------------------------------- */static LIST_HEAD(devs);/* --------------------------------------------------------------------- */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++;	return r;}/* --------------------------------------------------------------------- */static unsigned wait_src_ready(struct es1371_state *s){	unsigned int t, r;	for (t = 0; t < POLL_COUNT; t++) {		if (!((r = inl(s->io + ES1371_REG_SRCONV)) & SRC_BUSY))			return r;		udelay(1);	}	printk(KERN_DEBUG PFX "sample rate converter timeout r = 0x%08x\n", r);	return r;}static unsigned src_read(struct es1371_state *s, unsigned reg){        unsigned int temp,i,orig;        /* wait for ready */        temp = wait_src_ready (s);        /* we can only access the SRC at certain times, make sure           we're allowed to before we read */                   orig = temp;        /* expose the SRC state bits */        outl ( (temp & SRC_CTLMASK) | (reg << SRC_RAMADDR_SHIFT) | 0x10000UL,               s->io + ES1371_REG_SRCONV);        /* now, wait for busy and the correct time to read */        temp = wait_src_ready (s);        if ( (temp & 0x00870000UL ) != ( SRC_OKSTATE << 16 )){                /* wait for the right state */                for (i=0; i<POLL_COUNT; i++){                        temp = inl (s->io + ES1371_REG_SRCONV);                        if ( (temp & 0x00870000UL ) == ( SRC_OKSTATE << 16 ))                                break;                }        }        /* hide the state bits */        outl ((orig & SRC_CTLMASK) | (reg << SRC_RAMADDR_SHIFT), s->io + ES1371_REG_SRCONV);        return temp;                                        }static void src_write(struct es1371_state *s, unsigned reg, unsigned data){      	unsigned int r;	r = wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC);	r |= (reg << SRC_RAMADDR_SHIFT) & SRC_RAMADDR_MASK;	r |= (data << SRC_RAMDATA_SHIFT) & SRC_RAMDATA_MASK;	outl(r | SRC_WE, s->io + ES1371_REG_SRCONV);}/* --------------------------------------------------------------------- *//* most of the following here is black magic */static void set_adc_rate(struct es1371_state *s, unsigned rate){	unsigned long flags;	unsigned int n, truncm, freq;	if (rate > 48000)		rate = 48000;	if (rate < 4000)		rate = 4000;	n = rate / 3000;	if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9)))		n--;	truncm = (21 * n - 1) | 1;        freq = ((48000UL << 15) / rate) * n;	s->adcrate = (48000UL << 15) / (freq / n);	spin_lock_irqsave(&s->lock, flags);	if (rate >= 24000) {		if (truncm > 239)			truncm = 239;		src_write(s, SRCREG_ADC+SRCREG_TRUNC_N, 			  (((239 - truncm) >> 1) << 9) | (n << 4));	} else {		if (truncm > 119)			truncm = 119;		src_write(s, SRCREG_ADC+SRCREG_TRUNC_N, 			  0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4));	}			src_write(s, SRCREG_ADC+SRCREG_INT_REGS, 		  (src_read(s, SRCREG_ADC+SRCREG_INT_REGS) & 0x00ff) |		  ((freq >> 5) & 0xfc00));	src_write(s, SRCREG_ADC+SRCREG_VFREQ_FRAC, freq & 0x7fff);	src_write(s, SRCREG_VOL_ADC, n << 8);	src_write(s, SRCREG_VOL_ADC+1, n << 8);	spin_unlock_irqrestore(&s->lock, flags);}static void set_dac1_rate(struct es1371_state *s, unsigned rate){	unsigned long flags;	unsigned int freq, r;	if (rate > 48000)		rate = 48000;	if (rate < 4000)		rate = 4000;        freq = ((rate << 15) + 1500) / 3000;	s->dac1rate = (freq * 3000 + 16384) >> 15;	spin_lock_irqsave(&s->lock, flags);	r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC2 | SRC_DADC)) | SRC_DDAC1;	outl(r, s->io + ES1371_REG_SRCONV);	src_write(s, SRCREG_DAC1+SRCREG_INT_REGS, 		  (src_read(s, SRCREG_DAC1+SRCREG_INT_REGS) & 0x00ff) |		  ((freq >> 5) & 0xfc00));	src_write(s, SRCREG_DAC1+SRCREG_VFREQ_FRAC, freq & 0x7fff);	r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC2 | SRC_DADC));	outl(r, s->io + ES1371_REG_SRCONV);	spin_unlock_irqrestore(&s->lock, flags);}static void set_dac2_rate(struct es1371_state *s, unsigned rate){	unsigned long flags;	unsigned int freq, r;	if (rate > 48000)		rate = 48000;	if (rate < 4000)		rate = 4000;        freq = ((rate << 15) + 1500) / 3000;	s->dac2rate = (freq * 3000 + 16384) >> 15;	spin_lock_irqsave(&s->lock, flags);	r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DADC)) | SRC_DDAC2;	outl(r, s->io + ES1371_REG_SRCONV);	src_write(s, SRCREG_DAC2+SRCREG_INT_REGS, 		  (src_read(s, SRCREG_DAC2+SRCREG_INT_REGS) & 0x00ff) |		  ((freq >> 5) & 0xfc00));	src_write(s, SRCREG_DAC2+SRCREG_VFREQ_FRAC, freq & 0x7fff);	r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DADC));	outl(r, s->io + ES1371_REG_SRCONV);	spin_unlock_irqrestore(&s->lock, flags);}/* --------------------------------------------------------------------- */static void __init src_init(struct es1371_state *s){        unsigned int i;        /* before we enable or disable the SRC we need           to wait for it to become ready */        wait_src_ready(s);        outl(SRC_DIS, s->io + ES1371_REG_SRCONV);        for (i = 0; i < 0x80; i++)                src_write(s, i, 0);        src_write(s, SRCREG_DAC1+SRCREG_TRUNC_N, 16 << 4);        src_write(s, SRCREG_DAC1+SRCREG_INT_REGS, 16 << 10);        src_write(s, SRCREG_DAC2+SRCREG_TRUNC_N, 16 << 4);        src_write(s, SRCREG_DAC2+SRCREG_INT_REGS, 16 << 10);        src_write(s, SRCREG_VOL_ADC, 1 << 12);        src_write(s, SRCREG_VOL_ADC+1, 1 << 12);        src_write(s, SRCREG_VOL_DAC1, 1 << 12);        src_write(s, SRCREG_VOL_DAC1+1, 1 << 12);        src_write(s, SRCREG_VOL_DAC2, 1 << 12);        src_write(s, SRCREG_VOL_DAC2+1, 1 << 12);        set_adc_rate(s, 22050);        set_dac1_rate(s, 22050);        set_dac2_rate(s, 22050);        /* WARNING:         * enabling the sample rate converter without properly programming         * its parameters causes the chip to lock up (the SRC busy bit will         * be stuck high, and I've found no way to rectify this other than         * power cycle)         */        wait_src_ready(s);        outl(0, s->io+ES1371_REG_SRCONV);}/* --------------------------------------------------------------------- */static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data){	struct es1371_state *s = (struct es1371_state *)codec->private_data;	unsigned long flags;	unsigned t, x;        	for (t = 0; t < POLL_COUNT; t++)		if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP))			break;	spin_lock_irqsave(&s->lock, flags);        /* save the current state for later */        x = wait_src_ready(s);        /* enable SRC state data in SRC mux */	outl((x & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC)) | 0x00010000,	     s->io+ES1371_REG_SRCONV);        /* wait for not busy (state 0) first to avoid           transition states */        for (t=0; t<POLL_COUNT; t++){                if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0 )                    break;                udelay(1);        }                /* wait for a SAFE time to write addr/data and then do it, dammit */        for (t=0; t<POLL_COUNT; t++){                if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0x00010000)                    break;                udelay(1);        }	outl(((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) |	     ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK), s->io+ES1371_REG_CODEC);	/* restore SRC reg */	wait_src_ready(s);	outl(x, s->io+ES1371_REG_SRCONV);	spin_unlock_irqrestore(&s->lock, flags);}static u16 rdcodec(struct ac97_codec *codec, u8 addr){	struct es1371_state *s = (struct es1371_state *)codec->private_data;	unsigned long flags;	unsigned t, x;        /* wait for WIP to go away */	for (t = 0; t < 0x1000; t++)		if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP))			break;	spin_lock_irqsave(&s->lock, flags);	/* save the current state for later */	x = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC));	/* enable SRC state data in SRC mux */	outl( x | 0x00010000,              s->io+ES1371_REG_SRCONV);        /* wait for not busy (state 0) first to avoid           transition states */        for (t=0; t<POLL_COUNT; t++){                if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0 )                    break;                udelay(1);        }                /* wait for a SAFE time to write addr/data and then do it, dammit */        for (t=0; t<POLL_COUNT; t++){                if((inl(s->io+ES1371_REG_SRCONV) & 0x00870000) ==0x00010000)                    break;                udelay(1);        }	outl(((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | CODEC_PORD, s->io+ES1371_REG_CODEC);	/* restore SRC reg */	wait_src_ready(s);	outl(x, s->io+ES1371_REG_SRCONV);	spin_unlock_irqrestore(&s->lock, flags);        /* wait for WIP again */	for (t = 0; t < 0x1000; t++)		if (!(inl(s->io+ES1371_REG_CODEC) & CODEC_WIP))			break;        	/* now wait for the stinkin' data (RDY) */	for (t = 0; t < POLL_COUNT; t++)		if ((x = inl(s->io+ES1371_REG_CODEC)) & CODEC_RDY)			break;        	return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT);}/* --------------------------------------------------------------------- */static inline void stop_adc(struct es1371_state *s){	unsigned long flags;	spin_lock_irqsave(&s->lock, flags);	s->ctrl &= ~CTRL_ADC_EN;	outl(s->ctrl, s->io+ES1371_REG_CONTROL);	spin_unlock_irqrestore(&s->lock, flags);}	static inline void stop_dac1(struct es1371_state *s){	unsigned long flags;	spin_lock_irqsave(&s->lock, flags);	s->ctrl &= ~CTRL_DAC1_EN;	outl(s->ctrl, s->io+ES1371_REG_CONTROL);	spin_unlock_irqrestore(&s->lock, flags);}	static inline void stop_dac2(struct es1371_state *s){	unsigned long flags;	spin_lock_irqsave(&s->lock, flags);	s->ctrl &= ~CTRL_DAC2_EN;	outl(s->ctrl, s->io+ES1371_REG_CONTROL);	spin_unlock_irqrestore(&s->lock, flags);}	static void start_dac1(struct es1371_state *s){	unsigned long flags;	unsigned fragremain, fshift;	spin_lock_irqsave(&s->lock, flags);	if (!(s->ctrl & CTRL_DAC1_EN) && (s->dma_dac1.mapped || s->dma_dac1.count > 0)	    && s->dma_dac1.ready) {		s->ctrl |= CTRL_DAC1_EN;		s->sctrl = (s->sctrl & ~(SCTRL_P1LOOPSEL | SCTRL_P1PAUSE | SCTRL_P1SCTRLD)) | SCTRL_P1INTEN;

⌨️ 快捷键说明

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