📄 qq2440-audio.c
字号:
if (cold) { audio_rate = AUDIO_RATE_DEFAULT; audio_channels = AUDIO_CHANNELS_DEFAULT; /* * the UDA1341 is stereo only ==> 2 channels */ /* gxf add */ IISCON = 0; IISMOD = 0; IISFIFOC = 0; if ((file->f_mode & FMODE_WRITE)) { output_stream.fragsize = AUDIO_FRAGSIZE_DEFAULT; output_stream.nbfrags = AUDIO_NBFRAGS_DEFAULT; output_stream.channels = audio_channels; start_sbc2440_iis_bus_tx(); audio_clear_buf(&output_stream); if (!output_stream .buffers && audio_setup_buf(&output_stream)) return -ENOMEM; init_waitqueue_head(&output_stream.frag_wq); } if ((file->f_mode & FMODE_READ)) { input_stream.fragsize = AUDIO_FRAGSIZE_DEFAULT; input_stream.nbfrags = AUDIO_NBFRAGS_DEFAULT; input_stream.channels = audio_channels; start_sbc2440_iis_bus_rx(); audio_clear_buf(&input_stream); init_waitqueue_head(&input_stream.frag_wq); } } return 0;}static intsbc2440_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 voidstart_uda1341(void){#if 0 struct uda1341_cfg cfg; cfg.format = FMT_MSB; cfg.fs = S_CLOCK_FREQ; l3_command(&uda1341, L3_UDA1341_CONFIGURE, &cfg);#endif}static voidstart_sbc2440_iis_bus_rx(void){ /* gxf delete IISCON = 0; IISMOD = 0; IISFIFOC = 0; */ /* * 44 KHz , 384fs */ IISPSR = (IISPSR_A(iispsr_value(AUDIO_RATE_DEFAULT)) | IISPSR_B(iispsr_value(AUDIO_RATE_DEFAULT))); dprintk("iis_bus_rx\n");#if 0 IISCON |= (IISCON_RX_DMA /* Transmit DMA service request */ | IISCON_TX_IDLE /* Receive Channel idle */ | IISCON_PRESCALE); /* IIS Prescaler Enable */#endif IISCON |= (IISCON_RX_DMA /* Transmit DMA service request */ | IISCON_PRESCALE); /* IIS Prescaler Enable */ 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 */ IISFIFOC |= (IISFCON_RX_DMA /* Transmit FIFO access mode: DMA */ | IISFCON_RX_EN); /* Transmit FIFO enable */ IISCON |= IISCON_EN; /* IIS enable(start) */}voidstart_sbc2440_iis_bus_tx(void){ /* gxf delete IISCON = 0; IISMOD = 0; IISFIFOC = 0; */ IISPSR = (IISPSR_A(iispsr_value(AUDIO_RATE_DEFAULT)) | IISPSR_B(iispsr_value(AUDIO_RATE_DEFAULT))); dprintk("iis_bus_tx\n");#if 0 IISCON |= (IISCON_TX_DMA /* Transmit DMA service request */ | IISCON_RX_IDLE /* Receive Channel idle */ | IISCON_PRESCALE); /* IIS Prescaler Enable */#endif IISCON |= (IISCON_TX_DMA /* Transmit DMA service request */ | IISCON_PRESCALE); /* IIS Prescaler Enable */ 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 */ IISFIFOC |= (IISFCON_TX_DMA /* Transmit FIFO access mode: DMA */ | IISFCON_TX_EN); /* Transmit FIFO enable */ IISCON |= IISCON_EN; /* IIS enable(start) */}#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 = S3C2410_DCON_HANDSHAKE|S3C2410_DCON_SYNC_PCLK|S3C2410_DCON_TSZUNIT|S3C2410_DCON_SSERVE|S3C2410_DCON_CH2_I2SSDO|S3C2410_DCON_NORELOAD| */ ao_dcon = 0xa0900000; 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 = S3C2410_DCON_HANDSHAKE|S3C2410_DCON_SYNC_PCLK|S3C2410_DCON_TSZUNIT|S3C2410_DCON_SSERVE|S3C2410_DCON_CH1_I2SSDI|S3C2410_DCON_NORELOAD| */ ai_dcon = 0xa2900000; 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) ); //sbc2440_free_dma(s->dma_ch); return 0;}// ghcstop: audio driver common routine ==> device driver register routine ===================static struct file_operations sbc2440_audio_fops = { llseek: sbc2440_audio_llseek, write: sbc2440_audio_write, read: sbc2440_audio_read, poll: sbc2440_audio_poll, ioctl: sbc2440_audio_ioctl, open: sbc2440_audio_open, release: sbc2440_audio_release, owner: THIS_MODULE};static struct file_operations sbc2440_mixer_fops = { ioctl: sbc2440_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 voidsbc2440_uda1341_enable(void){ start_uda1341(); start_sbc2440_iis_bus_tx();}#ifdef CONFIG_PMstatic intsbc2440_audio_suspend(struct device *dev, u32 state, u32 level){ switch (level) { case SUSPEND_POWER_DOWN: break; } return 0;}static intsbc2440_audio_resume(struct device *dev, u32 level){ switch (level) { case RESUME_POWER_ON: printk("%s\n", __FUNCTION__); sbc2440_uda1341_enable(); break; } return 0;}#else#define sbc2440_audio_suspend NULL#define sbc2440_audio_resume NULL#endifstatic int audio_dev_dsp, audio_dev_mixer;static int sbc2440_audio_probe(struct device *_dev){ int ret = 0; printk("SBC2440 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(&sbc2440_audio_fops, -1); audio_dev_mixer = register_sound_mixer(&sbc2440_mixer_fops, -1); printk(AUDIO_NAME_VERBOSE " initialized\n"); return 0;}static int sbc2440_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 sbc2440_audio_driver = { .name = "s3c2440-sound", .bus = &platform_bus_type, .probe = sbc2440_audio_probe, .remove = sbc2440_audio_remove, .suspend = sbc2440_audio_suspend, .resume = sbc2440_audio_resume,};#ifdef USE_SYSFSstatic int __init sbc2440_uda1341_init(void){ int ret = -ENODEV;printk("SBC2440 SOUND driver register\n"); //if (!machine_is_h3600() || machine_is_h3100() || machine_is_h3800()) ret = driver_register(&sbc2440_audio_driver); if( ret ) { printk("S3C2440 SOUND driver un registered, %d\n", ret); } return ret;}static void __exit sbc2440_uda1341_exit(void){ driver_unregister(&sbc2440_audio_driver);}#elseint __init sbc2440_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(&sbc2440_audio_fops, -1); audio_dev_mixer = register_sound_mixer(&sbc2440_mixer_fops, -1); printk(AUDIO_NAME_VERBOSE " initialized\n"); return 0;}void __exit sbc2440_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(sbc2440_uda1341_init);module_exit(sbc2440_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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -