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

📄 cmpci.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
static void set_fmt(struct cm_state *s, unsigned char mask, unsigned char data){	unsigned long flags;	spin_lock_irqsave(&s->lock, flags);	set_fmt_unlocked(s,mask,data);	spin_unlock_irqrestore(&s->lock, flags);}static void frobindir(struct cm_state *s, unsigned char idx, unsigned char mask, unsigned char data){	outb(idx, s->iobase + CODEC_SB16_ADDR);	udelay(10);	outb((inb(s->iobase + CODEC_SB16_DATA) & mask) | data, s->iobase + CODEC_SB16_DATA);	udelay(10);}static struct {	unsigned	rate;	unsigned	lower;	unsigned	upper;	unsigned char	freq;} rate_lookup[] ={	{ 5512,		(0 + 5512) / 2,		(5512 + 8000) / 2,	0 },	{ 8000,		(5512 + 8000) / 2,	(8000 + 11025) / 2,	4 },	{ 11025,	(8000 + 11025) / 2,	(11025 + 16000) / 2,	1 },	{ 16000,	(11025 + 16000) / 2,	(16000 + 22050) / 2,	5 },	{ 22050,	(16000 + 22050) / 2,	(22050 + 32000) / 2,	2 },	{ 32000,	(22050 + 32000) / 2,	(32000 + 44100) / 2,	6 },	{ 44100,	(32000 + 44100) / 2,	(44100 + 48000) / 2,	3 },	{ 48000,	(44100 + 48000) / 2,	48000,			7 }};static void set_spdifout_unlocked(struct cm_state *s, unsigned rate){	if (rate == 48000 || rate == 44100) {		// SPDIFI48K SPDF_ACc97		maskl(s->iobase + CODEC_CMI_MISC_CTRL, ~0x01008000, rate == 48000 ? 0x01008000 : 0);		// ENSPDOUT		maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 2, ~0, 0x80);		// SPDF_1 SPD2DAC		maskw(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x240);		// CDPLAY		if (s->chip_version >= 39)			maskb(s->iobase + CODEC_CMI_MIXER1, ~0, 1);		s->status |= DO_SPDIF_OUT;	} else {		maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 2, ~0x80, 0);		maskw(s->iobase + CODEC_CMI_FUNCTRL1, ~0x240, 0);		if (s->chip_version >= 39)			maskb(s->iobase + CODEC_CMI_MIXER1, ~1, 0);		s->status &= ~DO_SPDIF_OUT;	}}static void set_spdifout(struct cm_state *s, unsigned rate){	unsigned long flags;	spin_lock_irqsave(&s->lock, flags);	set_spdifout_unlocked(s,rate);	spin_unlock_irqrestore(&s->lock, flags);}/* find parity for bit 4~30 */static unsigned parity(unsigned data){	unsigned parity = 0;	int counter = 4;	data >>= 4;	// start from bit 4	while (counter <= 30) {		if (data & 1)			parity++;		data >>= 1;		counter++;	}	return parity & 1;}static void set_ac3_unlocked(struct cm_state *s, unsigned rate){	/* enable AC3 */	if (rate == 48000 || rate == 44100) {		// mute DAC		maskb(s->iobase + CODEC_CMI_MIXER1, ~0, 0x40);		// AC3EN for 037, 0x10		maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0, 0x10);		// AC3EN for 039, 0x04		maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, 0x04);		if (s->capability & CAN_AC3_HW) {			// SPD24SEL for 037, 0x02			// SPD24SEL for 039, 0x20, but cannot be set			maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0, 0x02);			s->status |= DO_AC3_HW;			if (s->chip_version >= 39)				maskb(s->iobase + CODEC_CMI_MIXER1, ~1, 0);		 } else {			// SPD32SEL for 037 & 039, 0x20			maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, 0x20);			// set 176K sample rate to fix 033 HW bug			if (s->chip_version == 33) {				if (rate == 48000)					maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0, 0x08);				else					maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0x08, 0);			}			s->status |= DO_AC3_SW;		}	} else {		maskb(s->iobase + CODEC_CMI_MIXER1, ~0x40, 0);		maskb(s->iobase + CODEC_CMI_CHFORMAT + 2, ~0x32, 0);		maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0x24, 0);		maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0x08, 0);		if (s->chip_version == 33)			maskb(s->iobase + CODEC_CMI_CHFORMAT + 1, ~0x08, 0);		if (s->chip_version >= 39)			maskb(s->iobase + CODEC_CMI_MIXER1, ~0, 1);		s->status &= ~DO_AC3;	}	s->spdif_counter = 0;}static void set_ac3(struct cm_state *s, unsigned rate){	unsigned long flags;	spin_lock_irqsave(&s->lock, flags);	set_spdifout_unlocked(s, rate);	set_ac3_unlocked(s,rate);	spin_unlock_irqrestore(&s->lock, flags);}static void trans_ac3(struct cm_state *s, void *dest, const char *source, int size){	int   i = size / 2;	unsigned long data;	unsigned long *dst = (unsigned long *) dest;	unsigned short *src = (unsigned short *)source;	do {		data = (unsigned long) *src++;		data <<= 12;			// ok for 16-bit data		if (s->spdif_counter == 2 || s->spdif_counter == 3)			data |= 0x40000000;	// indicate AC-3 raw data		if (parity(data))			data |= 0x80000000;	// parity		if (s->spdif_counter == 0)			data |= 3;		// preamble 'M'		else if (s->spdif_counter & 1)			data |= 5;		// odd, 'W'		else			data |= 9;		// even, 'M'		*dst++ = data;		s->spdif_counter++;		if (s->spdif_counter == 384)			s->spdif_counter = 0;	} while (--i);}static void set_adc_rate_unlocked(struct cm_state *s, unsigned rate){	unsigned char freq = 4;	int	i;	if (rate > 48000)		rate = 48000;	if (rate < 8000)		rate = 8000;	for (i = 0; i < sizeof(rate_lookup) / sizeof(rate_lookup[0]); i++) {		if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper) {			rate = rate_lookup[i].rate;			freq = rate_lookup[i].freq;			break;	    	}	}	s->rateadc = rate;	freq <<= 2;	maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~0x1c, freq);}static void set_adc_rate(struct cm_state *s, unsigned rate){	unsigned long flags;	unsigned char freq = 4;	int	i;	if (rate > 48000)		rate = 48000;	if (rate < 8000)		rate = 8000;	for (i = 0; i < sizeof(rate_lookup) / sizeof(rate_lookup[0]); i++) {		if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper) {			rate = rate_lookup[i].rate;			freq = rate_lookup[i].freq;			break;	    	}	}	s->rateadc = rate;	freq <<= 2;	spin_lock_irqsave(&s->lock, flags);	maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~0x1c, freq);	spin_unlock_irqrestore(&s->lock, flags);}static void set_dac_rate(struct cm_state *s, unsigned rate){	unsigned long flags;	unsigned char freq = 4;	int	i;	if (rate > 48000)		rate = 48000;	if (rate < 8000)		rate = 8000;	for (i = 0; i < sizeof(rate_lookup) / sizeof(rate_lookup[0]); i++) {		if (rate > rate_lookup[i].lower && rate <= rate_lookup[i].upper) {			rate = rate_lookup[i].rate;			freq = rate_lookup[i].freq;			break;	    	}	}	s->ratedac = rate;	freq <<= 5;	spin_lock_irqsave(&s->lock, flags);	maskb(s->iobase + CODEC_CMI_FUNCTRL1 + 1, ~0xe0, freq);	if (s->curr_channels <=  2)		set_spdifout_unlocked(s, rate);	if (s->status & DO_DUAL_DAC)		set_adc_rate_unlocked(s, rate);	spin_unlock_irqrestore(&s->lock, flags);}/* --------------------------------------------------------------------- */static inline void reset_adc(struct cm_state *s){	/* reset bus master */	outb(s->enable | CM_CH0_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2);	udelay(10);	outb(s->enable & ~CM_CH0_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2);}static inline void reset_dac(struct cm_state *s){	/* reset bus master */	outb(s->enable | CM_CH1_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2);	outb(s->enable & ~CM_CH1_RESET, s->iobase + CODEC_CMI_FUNCTRL0 + 2);	if (s->status & DO_DUAL_DAC)		reset_adc(s);}static inline void pause_adc(struct cm_state *s){	maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~0, 4);}static inline void pause_dac(struct cm_state *s){	maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~0, 8);	if (s->status & DO_DUAL_DAC)		pause_adc(s);}static inline void disable_adc(struct cm_state *s){	/* disable channel */	s->enable &= ~CM_ENABLE_CH0;	outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);	reset_adc(s);}static inline void disable_dac(struct cm_state *s){	/* disable channel */	s->enable &= ~CM_ENABLE_CH1;	outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);	reset_dac(s);	if (s->status & DO_DUAL_DAC)		disable_adc(s);}static inline void enable_adc(struct cm_state *s){	if (!(s->enable & CM_ENABLE_CH0)) {		/* enable channel */		s->enable |= CM_ENABLE_CH0;		outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);	}	maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~4, 0);}static inline void enable_dac_unlocked(struct cm_state *s){	if (!(s->enable & CM_ENABLE_CH1)) {		/* enable channel */		s->enable |= CM_ENABLE_CH1;		outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);	}	maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~8, 0);	if (s->status & DO_DUAL_DAC)		enable_adc(s);}static inline void enable_dac(struct cm_state *s){	unsigned long flags;	spin_lock_irqsave(&s->lock, flags);	enable_dac_unlocked(s);	spin_unlock_irqrestore(&s->lock, flags);}static inline void stop_adc_unlocked(struct cm_state *s){	if (s->enable & CM_ENABLE_CH0) {		/* disable interrupt */		maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~1, 0);		disable_adc(s);	}}static inline void stop_adc(struct cm_state *s){	unsigned long flags;	spin_lock_irqsave(&s->lock, flags);	stop_adc_unlocked(s);	spin_unlock_irqrestore(&s->lock, flags);}static inline void stop_dac_unlocked(struct cm_state *s){	if (s->enable & CM_ENABLE_CH1) {		/* disable interrupt */		maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~2, 0);		disable_dac(s);	}	if (s->status & DO_DUAL_DAC)		stop_adc_unlocked(s);}static inline void stop_dac(struct cm_state *s){	unsigned long flags;	spin_lock_irqsave(&s->lock, flags);	stop_dac_unlocked(s);	spin_unlock_irqrestore(&s->lock, flags);}static void start_adc_unlocked(struct cm_state *s){	if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize))	    && s->dma_adc.ready) {		/* enable interrupt */		maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~0, 1);		enable_adc(s);	}}static void start_adc(struct cm_state *s){	unsigned long flags;	spin_lock_irqsave(&s->lock, flags);	start_adc_unlocked(s);	spin_unlock_irqrestore(&s->lock, flags);}	static void start_dac1_unlocked(struct cm_state *s){	if ((s->dma_adc.mapped || s->dma_adc.count > 0) && s->dma_adc.ready) {		/* enable interrupt *///		maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~0, 1); 		enable_dac_unlocked(s);	}}static void start_dac_unlocked(struct cm_state *s){	if ((s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) {		/* enable interrupt */		maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~0, 2);		enable_dac_unlocked(s);	}		if (s->status & DO_DUAL_DAC)			start_dac1_unlocked(s);}static void start_dac(struct cm_state *s){	unsigned long flags;	spin_lock_irqsave(&s->lock, flags);	start_dac_unlocked(s);	spin_unlock_irqrestore(&s->lock, flags);}	static int prog_dmabuf(struct cm_state *s, unsigned rec);static int set_dac_channels(struct cm_state *s, int channels){	unsigned long flags;	spin_lock_irqsave(&s->lock, flags);	if ((channels > 2) && (channels <= s->max_channels)	 && (((s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK) == (CM_CFMT_STEREO | CM_CFMT_16BIT))) {	    set_spdifout_unlocked(s, 0);	    if (s->capability & CAN_MULTI_CH_HW) {		// NXCHG		maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0, 0x80);		// CHB3D or CHB3D5C	       	maskb(s->iobase + CODEC_CMI_CHFORMAT + 3, ~0xa0, channels > 4 ? 0x80 : 0x20);		// CHB3D6C		maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 1, ~0x80, channels == 6 ? 0x80 : 0);		// ENCENTER 		maskb(s->iobase + CODEC_CMI_MISC_CTRL, ~0x80, channels == 6 ? 0x80 : 0);		s->status |= DO_MULTI_CH_HW;	    } else if (s->capability & CAN_DUAL_DAC) {		unsigned char fmtm = ~0, fmts = 0;		ssize_t ret;		// ENDBDAC, turn on double DAC mode		// XCHGDAC, CH0 -> back, CH1->front		maskb(s->iobase + CODEC_CMI_MISC_CTRL + 2, ~0, 0xC0);		s->status |= DO_DUAL_DAC;		// prepare secondary buffer		spin_unlock_irqrestore(&s->lock, flags);		ret = prog_dmabuf(s, 1);		if (ret) return ret;		spin_lock_irqsave(&s->lock, flags);		// copy the hw state		fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_DACSHIFT);		fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_ADCSHIFT);

⌨️ 快捷键说明

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