utu2440-audio.c

来自「UDA1431 语音芯片的驱动源码及测试程序。在s3c2440开发板linux2」· C语言 代码 · 共 1,585 行 · 第 1/3 页

C
1,585
字号
    /*     * 44 KHz , 384fs      */    IISPSR = (IISPSR_A(iispsr_value(AUDIO_RATE_DEFAULT)) | IISPSR_B(iispsr_value(AUDIO_RATE_DEFAULT)));    printk("\n RRRR IISPSR=%d----",IISPSR);    IISCON = (IISCON_RX_DMA     /* Transmit DMA service request */              | IISCON_TX_IDLE  /* Receive Channel idle */              | IISCON_PRESCALE);   /* IIS Prescaler Enable */    printk("\n RRRR IISCON=%d----",IISCON);    IISMOD = (IISMOD_SEL_MA     /* Master mode */              | IISMOD_SEL_RX | IISMOD_CH_RIGHT /* Low for left channel */              | IISMOD_FMT_MSB  /* MSB-justified format */              | IISMOD_BIT_16   /* Serial data bit/channel is 16 bit */#if (S_CLOCK_FREQ == 384)              | IISMOD_FREQ_384 /* Master clock freq = 384 fs */#else              | IISMOD_FREQ_256 /* Master clock freq = 256 fs */#endif              | IISMOD_SFREQ_32);   /* 32 fs */    printk("\n RRRR IISMOD=%d----",IISMOD);        IISFIFOC = (IISFCON_RX_DMA  /* Transmit FIFO access mode: DMA */                | IISFCON_RX_EN);   /* Transmit FIFO enable */    printk("\n RRRR IISFIFOC=%d----",IISFIFOC);    IISCON |= IISCON_EN;        /* IIS enable(start) */    printk("\n RRRR2222 IISCON=%d----",IISCON);}/////////////////////////////////////////////////////////////////////////////////////////////////static void init_s3c2410_iis_bus_txrx(void){        unsigned long tmp_read;            //__raw_writel(0,S3C2410_SBC_IISCON);        IISCON = 0;            //__raw_writel(0,S3C2410_SBC_IISMOD);        IISMOD = 0;           // __raw_writel(0,S3C2410_SBC_IISFCON);         IISFIFOC = 0;   	IISPSR = (IISPSR_A(iispsr_value(AUDIO_RATE_DEFAULT)) | IISPSR_B(iispsr_value(AUDIO_RATE_DEFAULT)));	//IISPSR=66;        	//iispsr_value(S_CLOCK_FREQ, 8000)    //iispsr_value(S_CLOCK_FREQ, 8000)        //__raw_writel(IISPSR  ,S3C2410_SBC_IISPSR);//	      __raw_writel(S3C2410_IISCON_RXDMAEN              /* (1 << 4):Receive DMA service request *///       	            | S3C2410_IISCON_TXDMAEN              /* (1 << 5):Transmit DMA service request *///             	     | (1<<1)                              /* (1 << 1):IIS Prescaler Enable *///              	     	,S3C2410_SBC_IISCON);	IISCON=S3C2410_IISCON_RXDMAEN| S3C2410_IISCON_TXDMAEN| (1<<1);	//IISCON=50;	 printk("\n &&&& ****++++IISCON=%d----",IISCON);	 //  	      __raw_writel((0<<8)                             /* (0 << 8):Master mode *///      	            | S3C2410_IISMOD_RXMODE              /* (1 << 6):Receive mode *///              	     |  S3C2410_IISMOD_TXMODE             /* (2 << 6):Transmit mode */// 	                   | S3C2410_IISMOD_LR_LLOW             /* (0 << 5):Low for left channel *///        	            | S3C2410_IISMOD_MSB                 /* (1 << 4):MSB-justified format *///               	     | S3C2410_IISMOD_16BIT               /* (1 << 3):Serial data bit/channel is 16 bit *///           	            | (1<<2)                             /* (1 << 2):Master clock freq = 384 fs *///                          | S3C2410_IISMOD_32FS                /* (1 << 0):32 fs *///                         ,S3C2410_SBC_IISMOD);        IISMOD=(0<<8)| S3C2410_IISMOD_RXMODE|  S3C2410_IISMOD_TXMODE| S3C2410_IISMOD_LR_LLOW| S3C2410_IISMOD_MSB| S3C2410_IISMOD_16BIT | (1<<2)| S3C2410_IISMOD_32FS;      	//IISMOD=221;	printk("\n &&&&IISMOD=%d----",IISMOD);//   	       __raw_writel(S3C2410_IISFCON_TXDMA              /* (1 << 15):Transmit FIFO access mode:DMA *///  	                   | S3C2410_IISFCON_RXDMA              /* (1 << 14):Receive FIFO access mode:DMA *///	                   | S3C2410_IISFCON_TXENABLE           /* (1 << 13):Transmit FIFO enable *///	                   | S3C2410_IISFCON_RXENABLE           /* (1 << 12):Receive FIFO access enable *///	                   ,S3C2410_SBC_IISFCON);               IISFIFOC=S3C2410_IISFCON_TXDMA| S3C2410_IISFCON_RXDMA| S3C2410_IISFCON_TXENABLE| S3C2410_IISFCON_RXENABLE;	//IISFIFOC=61440;        printk("\n &&&&IISFIFOC=%d----",IISFIFOC);       // tmp_read=__raw_readl(S3C2410_SBC_IISCON);       // tmp_read=tmp_read | S3C2410_IISCON_IISEN;       /* IIS enable(start) */       // __raw_writel(tmp_read,S3C2410_SBC_IISCON); 	    IISCON |= IISCON_EN;    	    //IISCON=S3C2410_IISCON_RXDMAEN| S3C2410_IISCON_TXDMAEN| (1<<1)|S3C2410_IISCON_IISEN;	    //IISCON=51;	   printk("\n &&&&&&&&&&**** ------------IISCON=%d----",IISCON);}//////////////////////////////////////////////////////////////////////////////////////////////////////////****static int iispsr_value_gao(int s_bit_clock, int sample_rate){        int i, prescaler = 0;        unsigned long tmpval;        unsigned long tmpval384;        unsigned long tmpval384min = 0xffff; 	tmpval384 = s3c2410_get_bus_clk(GET_PCLK) / s_bit_clock;        for (i = 0; i < 32; i++) {                tmpval = tmpval384/(i+1);                if (PCM_ABS((sample_rate - tmpval)) < tmpval384min) {                        tmpval384min = PCM_ABS((sample_rate - tmpval));                        prescaler = i;                }        }        dprintk("prescaler = %d\n", prescaler);        return prescaler;}/////////////////////////////////////////////////////////////////////////////////////////////////////////static int iispsr_value_gao(int s_bit_clock, int sample_rate){        int i, prescaler = 0;        unsigned long tmpval;        unsigned long tmpval384;        unsigned long tmpval384min = 0xffff; 	tmpval384 = s3c2410_get_bus_clk(GET_PCLK) / s_bit_clock;        for (i = 0; i < 32; i++) {                tmpval = tmpval384/(i+1);                if (PCM_ABS((sample_rate - tmpval)) < tmpval384min) {                        tmpval384min = PCM_ABS((sample_rate - tmpval));                        prescaler = i;                }        }        dprintk("prescaler = %d\n", prescaler);        return prescaler;}unsigned longs3c2410_get_bus_clk(int who){	unsigned long cpu_clk = s3c2410_get_cpu_clk();	unsigned long ratio = CLKDIVN;	return (cal_bus_clk(cpu_clk, ratio, who));}unsigned longs3c2410_get_cpu_clk(void){	unsigned long val = MPLLCON;	return (((GET_MDIV(val) + 8) * FIN) / \		((GET_PDIV(val) + 2) * (1 << GET_SDIV(val))));}static inline unsigned longcal_bus_clk(unsigned long cpu_clk, unsigned long ratio, int who){	if (!who) {			switch (ratio) {			case 0:				return (cpu_clk);			case 1:			case 2:				return (cpu_clk/2);			case 3:				return (cpu_clk/4);			default:				return 0;		}	} else {			switch (ratio) {			case 0:			case 1:				return (cpu_clk);			case 2:			case 3:				return (cpu_clk/2);			default:				return 0;		}	}}///////////////////////////////////////////////////////////////////////////////////////////////////////****/voidstart_utu2440_iis_bus_tx(void){    IISCON = 0;    IISMOD = 0;    IISFIFOC = 0;    IISPSR = (IISPSR_A(iispsr_value(AUDIO_RATE_DEFAULT)) | IISPSR_B(iispsr_value(AUDIO_RATE_DEFAULT)));     printk("\n $$$$IISPSR=%d----",IISPSR);    IISCON = (IISCON_TX_DMA     /* Transmit DMA service request */              | IISCON_RX_IDLE  /* Receive Channel idle */              | IISCON_PRESCALE);   /* IIS Prescaler Enable */    printk("\n $$$$IISCON=%d----",IISCON);    IISMOD = (IISMOD_SEL_MA     /* Master mode */              | IISMOD_SEL_TX   /* Transmit */              | IISMOD_CH_RIGHT /* Low for left channel */              | IISMOD_FMT_MSB  /* MSB-justified format */              | IISMOD_BIT_16   /* Serial data bit/channel is 16 bit */#if (S_CLOCK_FREQ == 384)              | IISMOD_FREQ_384 /* Master clock freq = 384 fs */#else              | IISMOD_FREQ_256 /* Master clock freq = 256 fs */#endif              | IISMOD_SFREQ_32);   /* 32 fs */    printk("\n $$$$IISMOD=%d----",IISMOD);    IISFIFOC = (IISFCON_TX_DMA  /* Transmit FIFO access mode: DMA */                | IISFCON_TX_EN);   /* Transmit FIFO enable */    printk("\n $$$$IISFIFOC=%d----",IISFIFOC);    IISCON |= IISCON_EN;        /* IIS enable(start) */    printk("\n $$$$IISCON=%d----",IISCON);}#ifdef USE_SYSFS // sysfs荤侩且 版快.static int audio_init_dma(audio_stream_t * s, char *desc)#elsestatic int __init audio_init_dma(audio_stream_t * s, char *desc)#endif{	int ret;	    if (s->dma_ch == S3C2410_DMA_CH2)    {        ret = s3c2410_dma_request(s->dma_ch, &(s->dmaclient), NULL);        if( ret )        {        	dprintk("%s: dma request err\n", __FUNCTION__ );        	return ret;        }	ao_dcon =0xa0800000;        //ao_dcon = S3C2410_DCON_HANDSHAKE|S3C2410_DCON_SYNC_PCLK|S3C2410_DCON_TSZUNIT|S3C2410_DCON_SSERVE|S3C2410_DCON_CH2_I2SSDO|S3C2410_DCON_NORELOAD|        s3c2410_dma_config(s->dma_ch, 2, ao_dcon); // a out, halfword        s3c2410_dma_setflags(s->dma_ch, S3C2410_DMAF_AUTOSTART); // a out        s3c2410_dma_set_buffdone_fn(s->dma_ch, audio_dmaout_done_callback);        s3c2410_dma_devconfig(s->dma_ch, S3C2410_DMASRC_MEM, BUF_ON_APB, 0x55000010);                dprintk("%s: dma request done audio out channel\n", __FUNCTION__ );                                return 0;    }    else if (s->dma_ch == S3C2410_DMA_CH1)    {        ret = s3c2410_dma_request(s->dma_ch, &(s->dmaclient), NULL);        if( ret )        {        	dprintk("%s: dma request err\n", __FUNCTION__ );        	return ret;        }	ai_dcon =0xa2900000;         //ai_dcon = S3C2410_DCON_HANDSHAKE|S3C2410_DCON_SYNC_PCLK|S3C2410_DCON_TSZUNIT|S3C2410_DCON_SSERVE|S3C2410_DCON_CH1_I2SSDI|S3C2410_DCON_NORELOAD|        s3c2410_dma_config(s->dma_ch, 2, ai_dcon); // a in, halfword        s3c2410_dma_setflags(s->dma_ch, S3C2410_DMAF_AUTOSTART); // a in                s3c2410_dma_set_buffdone_fn(s->dma_ch, audio_dmain_done_callback);        s3c2410_dma_devconfig(s->dma_ch, S3C2410_DMASRC_HW, BUF_ON_APB, 0x55000010);                          dprintk("%s: dma request done audio in channel\n", __FUNCTION__ );        return 0;    }    else        return 1;}static intaudio_clear_dma(audio_stream_t * s){	//extern int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *);	s3c2410_dma_free(s->dma_ch, &(s->dmaclient) );    //utu2440_free_dma(s->dma_ch);    return 0;}// ghcstop: audio driver common routine ==> device driver register routine ===================static struct file_operations utu2440_audio_fops = {  llseek:  utu2440_audio_llseek,  write:   utu2440_audio_write,  read:    utu2440_audio_read,  poll:    utu2440_audio_poll,  ioctl:   utu2440_audio_ioctl,  open:    utu2440_audio_open,  release: utu2440_audio_release,  owner:	THIS_MODULE};static struct file_operations utu2440_mixer_fops = {  ioctl: utu2440_mixer_ioctl,  owner: THIS_MODULE};#if 0 // if use sa1100-audio driver style, todo thisstatic int h3600_audio_open(struct inode *inode, struct file *file){	return sa1100_audio_attach(inode, file, &audio_state);}/* * Missing fields of this structure will be patched with the call * to sa1100_audio_attach(). */static struct file_operations h3600_audio_fops = {	open:		h3600_audio_open,	owner:		THIS_MODULE};#endifstatic inline voidutu2440_uda1341_enable(void){    start_uda1341();    start_utu2440_iis_bus_tx();}#ifdef CONFIG_PMstatic intutu2440_audio_suspend(struct device *dev, u32 state, u32 level){    switch (level)    {    case SUSPEND_POWER_DOWN:        break;    }    return 0;}static intutu2440_audio_resume(struct device *dev, u32 level){    switch (level)    {    case RESUME_POWER_ON:        printk("%s\n", __FUNCTION__);        utu2440_uda1341_enable();        break;    }    return 0;}#else#define utu2440_audio_suspend	NULL#define utu2440_audio_resume	NULL#endifstatic int      audio_dev_dsp, audio_dev_mixer;static int utu2440_audio_probe(struct device *_dev){    int             ret = 0;    printk("UTU2440 SOUND driver probe!\n");    ret = l3_attach_client(&uda1341, "l3-bit-24x0-gpio", "uda1341");    if (ret)    {        printk("l3_attach_client() failed.\n");        return ret;    }    l3_open(&uda1341);    start_uda1341();    output_stream.dma_ch = S3C2410_DMA_CH2;    output_stream.dmaclient.name = "audio_out";    if (audio_init_dma(&output_stream, "UDA1341 out"))    {        audio_clear_dma(&output_stream);        printk(KERN_WARNING AUDIO_NAME_VERBOSE ": unable to get DMA channels\n");        return -EBUSY;    }    input_stream.dma_ch = S3C2410_DMA_CH1;    input_stream.dmaclient.name = "audio_in";    if (audio_init_dma(&input_stream, "UDA1341 in"))    {        audio_clear_dma(&input_stream);        printk(KERN_WARNING AUDIO_NAME_VERBOSE ": unable to get DMA channels\n");        return -EBUSY;    }    audio_dev_dsp = register_sound_dsp(&utu2440_audio_fops, -1);    audio_dev_mixer = register_sound_mixer(&utu2440_mixer_fops, -1);    printk(AUDIO_NAME_VERBOSE " initialized\n");    return 0;}static int utu2440_audio_remove(struct device *_dev){    unregister_sound_dsp(audio_dev_dsp);    unregister_sound_mixer(audio_dev_mixer);    audio_clear_dma(&output_stream);    audio_clear_dma(&input_stream);    l3_close(&uda1341);    l3_detach_client(&uda1341);    printk(AUDIO_NAME_VERBOSE " unloaded\n");        return 0;}static struct device_driver utu2440_audio_driver = {	.name		= "s3c2440-sound",	.bus		= &platform_bus_type,	.probe		= utu2440_audio_probe,	.remove		= utu2440_audio_remove,	.suspend	= utu2440_audio_suspend,	.resume		= utu2440_audio_resume,};#ifdef USE_SYSFSstatic int __init utu2440_uda1341_init(void){	int ret = -ENODEV;printk("UTU2440 SOUND driver register\n");	//if (!machine_is_h3600() || machine_is_h3100() || machine_is_h3800())	ret = driver_register(&utu2440_audio_driver);	if( ret )	{		printk("S3C2440 SOUND driver un registered, %d\n", ret);	}	return ret;}static void __exit utu2440_uda1341_exit(void){	driver_unregister(&utu2440_audio_driver);}#elseint __init utu2440_uda1341_init(void){    int             ret = 0;//printk("ghcstop.........probe\n");    ret = l3_attach_client(&uda1341, "l3-bit-24x0-gpio", "uda1341");    if (ret)    {        printk("l3_attach_client() failed.\n");        return ret;    }    l3_open(&uda1341);    start_uda1341();    output_stream.dma_ch = S3C2410_DMA_CH2;    output_stream.dmaclient.name = "audio_out";    if (audio_init_dma(&output_stream, "UDA1341 out"))    {        audio_clear_dma(&output_stream);        printk(KERN_WARNING AUDIO_NAME_VERBOSE ": unable to get DMA channels\n");        return -EBUSY;    }    input_stream.dma_ch = S3C2410_DMA_CH1;    input_stream.dmaclient.name = "audio_in";    if (audio_init_dma(&input_stream, "UDA1341 in"))    {        audio_clear_dma(&input_stream);        printk(KERN_WARNING AUDIO_NAME_VERBOSE ": unable to get DMA channels\n");        return -EBUSY;    }    audio_dev_dsp = register_sound_dsp(&utu2440_audio_fops, -1);    audio_dev_mixer = register_sound_mixer(&utu2440_mixer_fops, -1);    printk(AUDIO_NAME_VERBOSE " initialized\n");    return 0;}void __exit utu2440_uda1341_exit(void){    unregister_sound_dsp(audio_dev_dsp);    unregister_sound_mixer(audio_dev_mixer);    audio_clear_dma(&output_stream);    audio_clear_dma(&input_stream);    l3_close(&uda1341);    l3_detach_client(&uda1341);    printk(AUDIO_NAME_VERBOSE " unloaded\n");        //return 0;}#endifmodule_init(utu2440_uda1341_init);module_exit(utu2440_uda1341_exit);MODULE_AUTHOR("Kwanghyun La <nala.la@samsung.com>");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("IIS sound driver for S3C2440");

⌨️ 快捷键说明

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