📄 uda1380.c
字号:
IISPSR = (IISPSR_A(iispsr_value(S_CLOCK_FREQ, 44100)) | IISPSR_B(iispsr_value(S_CLOCK_FREQ, 44100))); break; // case 22050: // IISPSR = (IISPSR_A(iispsr_value(S_CLOCK_FREQ, 22050)) | IISPSR_B(iispsr_value(S_CLOCK_FREQ, 22050))); break; // case 11025: // IISPSR = (IISPSR_A(iispsr_value(S_CLOCK_FREQ, 11025)) | IISPSR_B(iispsr_value(S_CLOCK_FREQ, 11025))); break; // case 8000: IISPSR = (IISPSR_A(iispsr_value(S_CLOCK_FREQ, 8000)) | IISPSR_B(iispsr_value(S_CLOCK_FREQ, 8000))); break; // default: // return -1; // } audio_rate = val; // return audio_rate; //}static int smdk2410_audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg){ long val; // switch (cmd) { // case SNDCTL_DSP_SETFMT: // get_user(val, (long *) arg); // if (val & AUDIO_FMT_MASK) { // audio_fmt = val; // break; // } else // return -EINVAL; // case SNDCTL_DSP_CHANNELS: // case SNDCTL_DSP_STEREO: // get_user(val, (long *) arg); // if (cmd == SNDCTL_DSP_STEREO) // val = val ? 2 : 1; // if (val != 1 && val != 2) // return -EINVAL; // audio_channels = val; // break; // case SOUND_PCM_READ_CHANNELS: // put_user(audio_channels, (long *) arg); // break; // case SNDCTL_DSP_SPEED: // get_user(val, (long *) arg); // val = audio_set_dsp_speed(val); // if (val < 0) // return -EINVAL; // put_user(val, (long *) arg); // break; // case SOUND_PCM_READ_RATE: // put_user(audio_rate, (long *) arg); // break; // case SNDCTL_DSP_GETFMTS: // put_user(AUDIO_FMT_MASK, (long *) arg); // break; // case SNDCTL_DSP_GETBLKSIZE: // put_user(audio_fragsize, (long *) arg); // break; // case SNDCTL_DSP_SETFRAGMENT: // if (output_stream.buffers) // return -EBUSY; // get_user(val, (long *) arg); // audio_fragsize = 1 << (val & 0xFFFF); // if (audio_fragsize < 16) // audio_fragsize = 16; // if (audio_fragsize > 16384) // audio_fragsize = 16384; // audio_nbfrags = (val >> 16) & 0x7FFF; // if (audio_nbfrags < 2) // audio_nbfrags = 2; // if (audio_nbfrags * audio_fragsize > 128 * 1024) audio_nbfrags = 128 * 1024 / audio_fragsize; if (audio_setup_buf(&output_stream)) // return -ENOMEM; // break; // case SNDCTL_DSP_SYNC: // return audio_sync(file); // case SNDCTL_DSP_GETOSPACE: // { audio_stream_t *s = &output_stream; // audio_buf_info *inf = (audio_buf_info *) arg; int err = verify_area(VERIFY_WRITE, inf, sizeof(*inf)); int i; // int frags = 0, bytes = 0; // if (err) // return err; // for (i = 0; i < s->nbfrags; i++) { // if (atomic_read(&s->buffers[i].sem.count) > 0) { if (s->buffers[i].size == 0) frags++; bytes += s->fragsize - s->buffers[i].size; } } put_user(frags, &inf->fragments); // put_user(s->nbfrags, &inf->fragstotal); // put_user(s->fragsize, &inf->fragsize); // put_user(bytes, &inf->bytes); // break; // } case SNDCTL_DSP_RESET: // switch (file->f_flags & O_ACCMODE) { // case O_RDONLY: // case O_RDWR: // } switch (file->f_flags & O_ACCMODE) { // case O_WRONLY: // case O_RDWR: // audio_clear_buf(&output_stream); // } return 0; // case SNDCTL_DSP_POST: // case SNDCTL_DSP_SUBDIVIDE: // case SNDCTL_DSP_NONBLOCK: // case SNDCTL_DSP_GETCAPS: // case SNDCTL_DSP_GETTRIGGER: // case SNDCTL_DSP_SETTRIGGER: // case SNDCTL_DSP_GETIPTR: // case SNDCTL_DSP_GETOPTR: // case SNDCTL_DSP_MAPINBUF: // case SNDCTL_DSP_MAPOUTBUF: // case SNDCTL_DSP_SETSYNCRO: // case SNDCTL_DSP_SETDUPLEX: // return -ENOSYS; // default: // return smdk2410_mixer_ioctl(inode, file, cmd, arg); } return 0; //}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) { // if (audio_rd_refcount || audio_wr_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; // audio_clear_buf(&output_stream); // } MOD_INC_USE_COUNT; // return 0; //}static int smdk2410_mixer_open(struct inode *inode, struct file *file){ MOD_INC_USE_COUNT; // return 0; //}static int smdk2410_audio_release(struct inode *inode, struct file *file){ DPRINTK("audio_release\n"); // switch (file->f_flags & O_ACCMODE) { // Read buffer operation. case O_RDONLY: // case O_RDWR: // if (audio_rd_refcount == 1) // audio_rd_refcount = 0; // } switch (file->f_flags & O_ACCMODE) { // Write buffer operation. case O_WRONLY: // case O_RDWR: // if (audio_wr_refcount == 1) { // audio_sync(file); // audio_clear_buf(&output_stream); // audio_wr_refcount = 0; // } // } // MOD_DEC_USE_COUNT; // return 0; //}static int smdk2410_mixer_release(struct inode *inode, struct file *file){ MOD_DEC_USE_COUNT; // return 0; //}/* * Philips UDA1380 driver interface description, and initialize operation, * exit operation for module server. ****************************************************************************//** * Philips UDA1380 audio device interface description. */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};static struct file_operations smdk2410_mixer_fops = { ioctl: smdk2410_mixer_ioctl, open: smdk2410_mixer_open, release: smdk2410_mixer_release};/** * Philips UDA1380 audio device initialize. */static void init_uda1380( void ){ int flags; // define value. int i,a; // uda1380_volume = 0; // Master volume. local_irq_save(flags); // keep. write_gpio_bit(GPIO_L3CLOCK, 1); // I/O Port set. write_gpio_bit(GPIO_L3DATA, 1); // local_irq_restore(flags); // restore./***** S.Yin insert program begin 2005-03-20 **********/ _Wr2410Iic( UDA1380_ADDR, 0x7f, 0xFFFF ); // reset operation. Delay(50); // Delay 10ms. a = 0; for ( i = 0; i < ARRAY_SIZE( uda1380_reg_info ); i++ ) {// a += _Wr2410Iic( UDA1380_ADDR, uda1380_reg_info[i].num, uda1380_reg_info[i].default_value ); // Delay(50); // Delay 10ms. } if ( a > 0 ) // printk( "Philips UDA1380 initialization fail ....\n" );/** S.Yin insert program end 2005-03-20 ****//***** S.Yin close program begin 2005-03-20 * uda1341_l3_address(UDA1380_ADDR + UDA1341_REG_STATUS); // uda1341_l3_data(SC_384fs | IF_MSB); // set 384 system clock, MSB uda1341_l3_data(0xC1); // uda1341_l3_address(UDA1380_ADDR + UDA1341_REG_DATA); // uda1341_l3_data(uda1380_volume); // maximum volume uda1341_l3_data(uda_sampling); //NO_DE_EMPHASIS and no muting***** S.Yin insert program end 2005-03-20 ****/}/** * Samsung S3C2410 I2C Bus device initialize. */static void init_iic_bus(void){ unsigned int save_E, save_PE; // define value. rtc_address_map(); // Set I2C Bus control register. save_E = rGPECON; // Keep. save_PE = rGPEUP; // rGPEUP |= 0xc000; // Pull-up disable rGPECON |= 0xa00000; // GPE15:IICSDA , GPE14:IICSCL rIICCON = 0; // Clear rIICSTAT = 0; // rIICADD = 0x10; // S3C2410 slave address=[7:1] rIICCON = 0xe0; // Enable ACK, Prescaler IICCLK=PCLK/512, // Enable interrupt, Transmit clock value // Tx clock=IICCLK/512 rIICSTAT = 0xd0; // to get to a sane state (also generates a STOP condition) rGPEUP = save_PE; // restore rGPECON = save_E; //}/** * Samsung S3C2410 I2S Bus device initialize. */static void init_s3c2410_iis_bus(void){ IISCON = 0; // Clear register. IISMOD = 0; // IISFIFOC = 0; // IISPSR = (IISPSR_A( iispsr_value( S_CLOCK_FREQ,44100 )) | IISPSR_B(iispsr_value(S_CLOCK_FREQ, 44100))); // 44 KHz , 384fs IISCON = (IISCON_TX_DMA // Transmit DMA service request |IISCON_RX_IDLE // Receive Channel idle |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 | IISMOD_FREQ_384 // Master clock freq = 384 fs | 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)}/** * Samsung S3C2410 DMA device initialize for audio server. */static int __init audio_init_dma(audio_stream_t * s, char *desc){ return s3c2410_request_dma("I2SSDO", s->dma_ch, audio_dmaout_done_callback, NULL);}/** * Philips UDA1380 audio device close. */static int s3c2410_uda1380_close(void){ _Wr2410Iic( UDA1380_ADDR, 0x0, 0x0 ); // reset operation. Delay(50); // Delay 10ms. _Wr2410Iic( UDA1380_ADDR, 0x02, 0x0 ); // reset operation. Delay(50); // Delay 10ms. return 0; // return.}/** * Clear Samsung S3C2410 DMA device. */static int audio_clear_dma(audio_stream_t * s){ s3c2410_free_dma(s->dma_ch); // Free DMA device. return 0; // return.}/** * Philips UDA1380 Audio driver initialize. */int __init s3c2410_uda1380_init(void){ unsigned long flags; // Define valuse. local_irq_save(flags); // keep. /***** Initialize Samsung S3C2410 I/O port. *****/ set_gpio_ctrl(GPIO_L3CLOCK); // GPB 4: L3CLOCK, OUTPUT set_gpio_ctrl(GPIO_L3DATA); // GPB 3: L3DATA, OUTPUT set_gpio_ctrl(GPIO_L3MODE); // GPB 2: L3MODE, OUTPUT set_gpio_ctrl(GPIO_E3 | GPIO_PULLUP_EN | GPIO_MODE_I2SSDI); // GPE 3: I2SSDI set_gpio_ctrl(GPIO_E0 | GPIO_PULLUP_EN | GPIO_MODE_I2SSDI); // GPE 0: I2SLRCK set_gpio_ctrl(GPIO_E1 | GPIO_PULLUP_EN | GPIO_MODE_I2SSCLK); // GPE 1: I2SSCLK set_gpio_ctrl(GPIO_E2 | GPIO_PULLUP_EN | GPIO_MODE_CDCLK); // GPE 2: CDCLK set_gpio_ctrl(GPIO_E4 | GPIO_PULLUP_EN | GPIO_MODE_I2SSDO); // GPE 4: I2SSDO local_irq_restore(flags); // restore. /**** Samsung S3C2410 I2C bus and I2S bus, DMA device, UDA1380 Initialize. *****/ int init_iic_bus(); // I2C bus initialization. init_uda1380(); // uda1380 initialization. init_s3c2410_iis_bus(); // I2S bus initialization. output_stream.dma_ch = DMA_CH2; // DMA device initialization. if (audio_init_dma(&output_stream, "UDA1380 out")) { // audio_clear_dma(&output_stream); // printk( KERN_WARNING AUDIO_NAME_VERBOSE ": unable to get DMA channels\n" ); // return -EBUSY; // return busy. } /***** Register Philips UDA1380 Audio device *****/ audio_dev_dsp = register_sound_dsp(&smdk2410_audio_fops, -1); audio_dev_mixer = register_sound_mixer(&smdk2410_mixer_fops, -1); printk(AUDIO_NAME_VERBOSE " device initialized.\n"); // Complete note... return 0; // normal return.}/** * Drive device EXIT oparation. */void __exit s3c2410_uda1380_exit(void){ s3c2410_uda1380_close(); // Clear UDA1380 control register. unregister_sound_dsp(audio_dev_dsp); // Release audio drive interfase. unregister_sound_mixer(audio_dev_mixer); // Release Mixer device interfase. audio_clear_dma(&output_stream); // Release DMA server. printk(AUDIO_NAME_VERBOSE " device unloaded\n"); // Release note...}module_init(s3c2410_uda1380_init);module_exit(s3c2410_uda1380_exit);MODULE_AUTHOR( "Yinshenk" );MODULE_DESCRIPTION( "Philips UDA1380 CODEC driver" );MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -