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 + -
显示快捷键?