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

📄 s3c2410-uda1341.c

📁 2410开发板上的声卡驱动!网上收集!很全的啊!1341型号
💻 C
📖 第 1 页 / 共 4 页
字号:
}     从file->f_mode 中判断文件是否可读可写,根据设备文件的打开模式,分别调用了init_s3c2410_iis_bus_tx 和init_s3c2410_iis_bus_rx 函数来进行对IIS 总线读写的初始化配置,在这两个函数中对S3C2410 芯片的IIS 相关寄存器进行了相应的配置,会在后面说明。然后又调用了audio_clear_buf 函数来分别对音频输入和输出两个DMA 缓冲区进行了清空,该函数也会在后面说明。    因为读写操作控制必须用f_mode 来进行判断,    所以这里要根据f_mode 为可读或可写的标识来进行    读写模式的硬件设置。而read,write 函数不需要检查    f_mode 因为读写权限的检查是由内核在调用他们之    前进行的。    MOD_INC_USE_COUNT;     最后调用MOD_INC_USE_COUNT;     来对设备文件计数器加一计数,并返回。 */static int smdk2410_audio_open(struct inode *inode, struct file *file){	int cold = !audio_active;	DPRINTK("audio_open\n");	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {	//GDLC	if (audio_rd_refcount || audio_wr_refcount)		if (audio_rd_refcount)				return -EBUSY;		audio_rd_refcount++;	} else if ((file->f_flags & O_ACCMODE) == O_WRONLY) {		if (audio_wr_refcount)			return -EBUSY;		audio_wr_refcount++;	} else if ((file->f_flags & O_ACCMODE) == O_RDWR) {		if (audio_rd_refcount || audio_wr_refcount)			return -EBUSY;		audio_rd_refcount++;		audio_wr_refcount++;	} else		return -EINVAL;	if (cold) {		audio_rate = AUDIO_RATE_DEFAULT;		audio_channels = AUDIO_CHANNELS_DEFAULT;		audio_fragsize = AUDIO_FRAGSIZE_DEFAULT;		audio_nbfrags = AUDIO_NBFRAGS_DEFAULT;		init_s3c2410_iis_bus_txrx();//GDLC		if ((file->f_mode & FMODE_WRITE)){		//GDLC		init_s3c2410_iis_bus_tx();				audio_clear_buf(&output_stream);		}		if ((file->f_mode & FMODE_READ)){		//GDLC		init_s3c2410_iis_bus_rx();				audio_clear_buf(&input_stream);		}	}	return 0;}static int smdk2410_mixer_open(struct inode *inode, struct file *file){	return 0;}static int smdk2410_audio_release(struct inode *inode, struct file *file){	DPRINTK("audio_release\n");	if (file->f_mode & FMODE_READ) {		  	if (audio_rd_refcount == 1)				audio_clear_buf(&input_stream);			  	audio_rd_refcount = 0;	}	if(file->f_mode & FMODE_WRITE) {		  	if (audio_wr_refcount == 1) {			    	audio_sync(file);			    	audio_clear_buf(&output_stream);			    	audio_wr_refcount = 0;		    	}	  	}	return 0;}static int smdk2410_mixer_release(struct inode *inode, struct file *file){	return 0;}/*音频驱动的file_operations 结构定义如下:这里定义了两种类型设备的file_operations 结构,这个是DSP 设备*/static struct file_operations smdk2410_audio_fops = {	.llseek = smdk2410_audio_llseek,	.write  = smdk2410_audio_write,	.read	= smdk2410_audio_read,	.poll	= smdk2410_audio_poll,	.ioctl	= smdk2410_audio_ioctl,	.open	= smdk2410_audio_open,	.release = smdk2410_audio_release};/*音频驱动的file_operations 结构定义如下:这里定义了两种类型设备的file_operations 结构,这个是混频器设备。*/static struct file_operations smdk2410_mixer_fops = {	.ioctl	= smdk2410_mixer_ioctl,	.open	= smdk2410_mixer_open,	.release = smdk2410_mixer_release};static void init_uda1341(void){	unsigned long flags;  	uda1341_volume = 62 - ((DEF_VOLUME * 61) / 100);/*62 表示音量设置表  	中有效音量的总档数,61 表示音量总共有61 档,  	DEF_VOLUME%表示所要调的音量的百分比大小,这样  	61*DEF_VOLUME%所得出的就是所要调的音量是音量总  	档数的第几档,由于音量设置表中列出值的是按  	衰减量递增的,所以刚才得到的音量档数需要在  	总档数下衰减多少才能得到呢?显然只要将音量  	总档数减去所要调到的音量档数即可,  	即62-61*DEF_VOLUME%。  	*/  		uda1341_boost = 0;  	uda_sampling = DATA2_DEEMP_NONE;	uda_sampling &= ~(DATA2_MUTE);		local_irq_save(flags);//调用该宏函数来保存IRQ 中断使能状态,	//并禁止IRQ 中断	/* To Set Bit 2 of GPBDAT to be 1 (GPIO_L3MODE=0x01010102)*/	s3c2410_gpio_setpin(S3C2410_GPB2,1);	/* To Set Bit 4 of GPBDAT to be 1 (GPIO_L3CLOCK=0x01010104)*/	s3c2410_gpio_setpin(S3C2410_GPB4,1);	local_irq_restore(flags);		uda1341_l3_address(UDA1341_REG_STATUS);        /* set 384 system clock,MSB */	uda1341_l3_data(STAT0_SC_384FS | STAT0_IF_MSB);     	/* reset uda1341*/        uda1341_l3_data(0x40 | STAT0_SC_384FS | STAT0_IF_MSB);         uda1341_l3_data(STAT1 | STAT1_DAC_GAIN | STAT1_ADC_GAIN | STAT1_ADC_ON | STAT1_DAC_ON);        uda1341_l3_address(UDA1341_REG_DATA0);	/* maximum volume */	uda1341_l3_data(DATA0 |DATA0_VOLUME(uda1341_volume)); 	uda1341_l3_data(DATA1 |DATA1_BASS(uda1341_boost)| DATA1_TREBLE(0));        uda1341_l3_data(uda_sampling); 	uda1341_l3_data(EXTADDR(EXT2));	uda1341_l3_data(EXTDATA(EXT2_MIC_GAIN(0x6)) | EXT2_MIXMODE_CH1);}static void init_s3c2410_iis_bus_rx(void){	unsigned long tmp_read;	__raw_writel(0,S3C2410_SBC_IISCON);//初始化IIS 控制寄存器为0	__raw_writel(0,S3C2410_SBC_IISMOD);//初始化IIS模式寄存器为0	__raw_writel(0,S3C2410_SBC_IISFCON);//初始化IISFIFO 控制寄存器为0        /* 44 KHz , 384fs */	__raw_writel((IISPSR_A(iispsr_value(S_CLOCK_FREQ, 44100)) 		   | IISPSR_B(iispsr_value(S_CLOCK_FREQ, 44100)))		   ,S3C2410_SBC_IISPSR);//设置IIS 预分频寄存器,其中调用了iispsr_value 		   //函数来计算预分频值		__raw_writel(S3C2410_IISCON_RXDMAEN    		/* Transmit DMA service request */		   | S3C2410_IISCON_TXIDLE 		/* Receive Channel idle */		   | (1<<1)				/* IIS Prescaler Enable预分频器使能选择,		   设为1 表示使能IIS 预分频器 */		   ,S3C2410_SBC_IISCON);	 	__raw_writel((0<<8) 				/* Master mode */		   |S3C2410_IISMOD_RXMODE 		/* Transmit */		   | S3C2410_IISMOD_LR_LLOW 		/* Low for left channel */		   | S3C2410_IISMOD_MSB 		/* MSB-justified format */		   | S3C2410_IISMOD_16BIT 		/* Serial data bit/channel is 16 bit */		   |(1<<2) 				/* Master clock freq = 384 fs */		   | S3C2410_IISMOD_32FS 		/* 32 fs */		   ,S3C2410_SBC_IISMOD);	 	__raw_writel(S3C2410_IISFCON_RXDMA 		/* Transmit FIFO access mode:DMA */		   | S3C2410_IISFCON_RXENABLE		/* Transmit FIFO enable */		   ,S3C2410_SBC_IISFCON);			tmp_read=__raw_readl(S3C2410_SBC_IISCON);	tmp_read=tmp_read | S3C2410_IISCON_IISEN;	/* IIS enable(start) */	__raw_writel(tmp_read,S3C2410_SBC_IISCON);}static void init_s3c2410_iis_bus_tx(void){	unsigned long tmp_read;   	__raw_writel(0,S3C2410_SBC_IISCON);	__raw_writel(0,S3C2410_SBC_IISMOD);	__raw_writel(0,S3C2410_SBC_IISFCON);    	/* 44 KHz , 384fs */	 __raw_writel( (IISPSR_A(iispsr_value(S_CLOCK_FREQ, 44100)) \				 | IISPSR_B(iispsr_value(S_CLOCK_FREQ, 44100))),S3C2410_SBC_IISPSR);	 	__raw_writel(S3C2410_IISCON_TXDMAEN 		/* Transmit DMA service request */	           | S3C2410_IISCON_RXIDLE 		/* Receive Channel idle接收通道空闲命令,	           设为1 表示接收通道空闲 */		   | (1<<1)				/* IIS Prescaler Enable */		   ,S3C2410_SBC_IISCON);	 	__raw_writel((0<<8) 				/* Master mode */		   |S3C2410_IISMOD_TXMODE 		/* Transmit */		   | S3C2410_IISMOD_LR_LLOW 		/* Low for left channel */		   | S3C2410_IISMOD_MSB 		/* MSB-justified format */		   | S3C2410_IISMOD_16BIT  		/* Serial data bit/channel is 16 bit */		   |(1<<2) 				/* Master clock freq = 384 fs */		   | S3C2410_IISMOD_32FS 		/* 32 fs */		   ,S3C2410_SBC_IISMOD);	 	__raw_writel(S3C2410_IISFCON_TXDMA		/* Transmit FIFO access mode : DMA */		   | S3C2410_IISFCON_TXENABLE 		/*Transmit FIFO enable */		   ,S3C2410_SBC_IISFCON);		tmp_read=__raw_readl(S3C2410_SBC_IISCON);	tmp_read=tmp_read | S3C2410_IISCON_IISEN;	/* IIS enable (start) */	__raw_writel(tmp_read,S3C2410_SBC_IISCON);}static int __init audio_init_dma(audio_stream_t * s){	s3c2410_dmasrc_t source; 	if(s->dma_ch== 2) {		/* UDA1341,........MEM */		source=S3C2410_DMASRC_MEM;		s3c2410_dma_devconfig(s->dma_ch,source, 3, 0x55000010); 		s3c2410_dma_config(s->dma_ch, 2,0xa0900000/* 0xa0d00000*/);		s3c2410_dma_set_buffdone_fn(s->dma_ch, audio_dmaout_done_callback);		s3c2410_dma_setflags(s->dma_ch,S3C2410_DMAF_AUTOSTART);		return s3c2410_dma_request(s->dma_ch,&s3c2410_dma_client_out,NULL);		}	else if(s->dma_ch == 1) {		source=S3C2410_DMASRC_HW;		s3c2410_dma_devconfig(s->dma_ch,source,3,0x55000010);		s3c2410_dma_config(s->dma_ch, 2,0xa2900000);		s3c2410_dma_set_buffdone_fn(s->dma_ch, audio_dmain_done_callback);		s3c2410_dma_setflags(s->dma_ch,S3C2410_DMAF_AUTOSTART);		return s3c2410_dma_request(s->dma_ch,&s3c2410_dma_client_in,NULL);		}	else		return 1;}static int audio_clear_dma(audio_stream_t * s,s3c2410_dma_client_t *client){	s3c2410_dma_free(s->dma_ch,client);	return 0;}/*加载驱动模块时的初始化函数:int __init s3c2410_uda1341_init(void)该函数首先会初始化I/O 和UDA1341 芯片,然后申请2个DMA 通道用于音频传输。*/int __init s3c2410_uda1341_init(void){	unsigned long flags;	local_irq_save(flags);/*调用该宏函数来保存IRQ 中断使能状态,	并禁止IRQ 中断。*/	/*设置与UDA1341 芯片相关GPIO 引脚。	这里首先将GPB4,GPB3,GPB2 这3个GPIO 引脚设置	为输出模式,参考原理图后,得知这3个引脚	分别连接UDA1341 芯片的L3CLOCK,L3DATA,L3MODE 这3个	引脚,作为这3个信号的输入。	 * GPB 4: L3CLOCK, OUTPUT ,Pull up disable	 * To set Bit 8 & Bit 9 of GPBCON to be 01(GPIO_L3CLOCK=0x01010104)	 * To set Bit 4 of GPBUP to be 1	 */ 	s3c2410_gpio_cfgpin(S3C2410_GPB4,S3C2410_GPB4_OUTP);	s3c2410_gpio_pullup(S3C2410_GPB4,1);	/* GPB 3: L3DATA, OUTPUT ,Pull up disable	 * To set Bit 6 & Bit 7 of GPBCON to be 01	 * To set Bit 3 of GPBUP to be 1	 */	s3c2410_gpio_cfgpin(S3C2410_GPB3,S3C2410_GPB3_OUTP);	s3c2410_gpio_pullup(S3C2410_GPB3,1);	/* GPB 2: L3MODE, OUTPUT ,Pull up disable	 * To set Bit 4 & Bit 5 of GPBCON to be 01	 * To set Bit 2 of GPBUP to be 1	 */	s3c2410_gpio_cfgpin(S3C2410_GPB2,S3C2410_GPB2_OUTP);	s3c2410_gpio_pullup(S3C2410_GPB2,1);	/*设置与IIS 控制器输出信号相关GPIO 引脚。	将GPE0~GPE4 这5个引脚设置为IIS 接口的信号模式。	需要通过配置GPECON 寄存器来设定该端口管脚的	输出模式,对应位如下: [9:8]  [7:6]  [5:4]  [3:2]  [1:0]GPE4   GPE3   GPE2   GPE1   GPE0参考S3C2410 芯片datasheet 的I/O口章节,都要设为10(二进制)。  local_irq_restore(flags);     设置完GPIO 口的工作模式,就可以前面已经分析过的local_irq_restore 宏函数来恢复IRQ 和FIQ 的中断使能状态。  init_uda1341();     这里调用了init_uda1341 函数来初始化UDA1341 芯片,该函数会在后面说明。  output_stream.dma_ch = DMA_CH2;	GPE 3: I2SSDI ,Pull up enable	 * To set Bit 6 & Bit 7 of GPECON to be 02	 * To set Bit 3 of GPEUP to be 0	 */	s3c2410_gpio_cfgpin(S3C2410_GPE3,S3C2410_GPE3_I2SSDI);	s3c2410_gpio_pullup(S3C2410_GPE3,0);		/* GPE 0: I2SLRCK,Pull up enable 	 * To Set Bit 0 & Bit 1 of GPECON to be 02	 * To set Bit 0 of GPEUP to be 0	 */	s3c2410_gpio_cfgpin(S3C2410_GPE0,S3C2410_GPE0_I2SLRCK);	s3c2410_gpio_pullup(S3C2410_GPE0,0);		/* GPE 1: I2SSCLK,Pull up enable 	 * To set Bit 2 & Bit 3 of GPECON to be 02	 * To set Bit 1 of GPEUP  to be 0	 */	s3c2410_gpio_cfgpin(S3C2410_GPE1,S3C2410_GPE1_I2SSCLK);	s3c2410_gpio_pullup(S3C2410_GPE1,0);		/* GPE 2: CDCLK,Pull up enable 	 * To set Bit 4 & Bit 5 of GPECON to be 02	 * To set Bit 2 of GPEUP to be 0	 */	s3c2410_gpio_cfgpin(S3C2410_GPE2,S3C2410_GPE2_CDCLK);	s3c2410_gpio_pullup(S3C2410_GPE2,0);		/* GPE 4: I2SSDO,Pull up enable 	 * To set Bit 8 &bit 9 of GPECON to be 02	 * To set Bit 4 of GPEUP to be 0	 */	s3c2410_gpio_cfgpin(S3C2410_GPE4,S3C2410_GPE4_I2SSDO);	s3c2410_gpio_pullup(S3C2410_GPE4,0);		local_irq_restore(flags);	init_uda1341();		//输出音频缓冲区的DMA 通道进行初始化设置。	output_stream.dma_ch=DMA_CH2;  	if (audio_init_dma(&output_stream)) {		audio_clear_dma(&output_stream,&s3c2410_dma_client_out);		printk( KERN_WARNING AUDIO_NAME_VERBOSE 			": unable to get DMA channels for output\n" );		return -EBUSY;	}//输入音频缓冲区的DMA 通道进行初始化设置。	input_stream.dma_ch=DMA_CH1;  	if (audio_init_dma(&input_stream)) {                audio_clear_dma(&input_stream,&s3c2410_dma_client_in);                printk( KERN_WARNING AUDIO_NAME_VERBOSE                        ": unable to get DMA channels for input\n" );                return -EBUSY;        }	//这两个函数的参数一样,fops 为传给内核的//file_operations 结构中的接口函数,dev 为分配的设备序号,//设为-1 表示由内核自动分配一个空闲的序号。 	audio_dev_dsp = register_sound_dsp(&smdk2410_audio_fops, -1);//注册为DSP 设备	audio_dev_mixer = register_sound_mixer(&smdk2410_mixer_fops, -1);//注册为混频器设备。	printk(AUDIO_NAME_VERBOSE " initialized\n");	return 0;}void __exit s3c2410_uda1341_exit(void){	unregister_sound_dsp(audio_dev_dsp);	unregister_sound_mixer(audio_dev_mixer);	audio_clear_dma(&output_stream,&s3c2410_dma_client_out);	audio_clear_dma(&input_stream,&s3c2410_dma_client_in); /* input */	printk(AUDIO_NAME_VERBOSE " unloaded\n");}module_init(s3c2410_uda1341_init);module_exit(s3c2410_uda1341_exit);

⌨️ 快捷键说明

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