📄 2410audio.c
字号:
return put_user(val, (long *) arg); case SOUND_MIXER_VOLUME: ret = get_user(val, (long *) arg); if (ret) return ret; _Wr24C080(0x30,0x10,(unsigned int)val); break; default: DPRINTK("mixer ioctl %u unknown\n", cmd); return -ENOSYS; } audio_mix_modcnt++; return 0;}static int iispsr_value(int s_bit_clock, int sample_rate){ int i, prescaler = 0; U32 tmpval; U32 tmpval384; U32 tmpval384min = 0xffff; tmpval384 = s3c2440_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 long audio_set_dsp_speed(long val){ printk("val = %ld\n",val); switch (val) { case 48000: case 44100: 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 smdk2440_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 smdk2440_mixer_ioctl(inode, file, cmd, arg); } return 0;}static int smdk2440_audio_open(struct inode *inode, struct file *file){#if 0 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); audio_clear_buf(&input_stream); // audio_power_on(); }#endif MOD_INC_USE_COUNT; return 0;}static int smdk2440_mixer_open(struct inode *inode, struct file *file){ MOD_INC_USE_COUNT; return 0;}static int smdk2440_audio_release(struct inode *inode, struct file *file){ DPRINTK("audio_release\n"); switch (file->f_flags & O_ACCMODE) { case O_RDONLY: case O_RDWR: if (audio_rd_refcount == 1) audio_rd_refcount = 0; } switch (file->f_flags & O_ACCMODE) { case O_WRONLY: case O_RDWR: if (audio_wr_refcount == 1) { audio_sync(file); audio_clear_buf(&output_stream); audio_wr_refcount = 0; } }#if 0 if (!audio_active) audio_power_off();#endif MOD_DEC_USE_COUNT; return 0;}static int smdk2440_mixer_release(struct inode *inode, struct file *file){ MOD_DEC_USE_COUNT; return 0;}static struct file_operations smdk2440_audio_fops = { llseek: smdk2440_audio_llseek, write: smdk2440_audio_write, poll: smdk2440_audio_poll, ioctl: smdk2440_audio_ioctl, open: smdk2440_audio_open, release: smdk2440_audio_release};static struct file_operations smdk2440_mixer_fops = { ioctl: smdk2440_mixer_ioctl, open: smdk2440_mixer_open, read: smdk2440_mixer_read, release: smdk2440_mixer_release};static void init_s3c2440_iis_bus(void){ IISCON = 0; IISMOD = 0; IISFIFOC = 0; /* 44 KHz , 384fs */ IISPSR = (IISPSR_A(iispsr_value(S_CLOCK_FREQ, 44100)) | IISPSR_B(iispsr_value(S_CLOCK_FREQ, 44100))); IISCON = (IISCON_TX_DMA /* Transmit DMA service request */ |IISCON_RX_DMA /* Receive Channel idle */ |IISCON_PRESCALE); /* IIS Prescaler Enable */ IISMOD = (IISMOD_SEL_MA /* Master mode */ | IISMOD_SEL_TX /* Transmit */ | IISMOD_SEL_RX /* Transmit */ | IISMOD_CH_RIGHT /* Low for left channel */ | IISMOD_FMT_IIS /* 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 | IISFCON_RX_DMA | IISFCON_RX_EN ); /* Transmit FIFO enable */ IISCON |= IISCON_EN; /* IIS enable(start) */}static int __init audio_init_dma(audio_stream_t * s, char *desc){ if(s->dma_ch == 1) { // printk("s->dma_ch = %d\n",s->dma_ch); return s3c2440_request_dma("I2SSDI", s->dma_ch, NULL, audio_dmain_done_callback); } else { // printk("s->dma_ch = %d\n",s->dma_ch); return s3c2440_request_dma("I2SSDO", s->dma_ch, audio_dmaout_done_callback, NULL); }}static int audio_clear_dma(audio_stream_t * s){ s3c2440_free_dma(s->dma_ch); return 0;}int init_module1380(void){ U32 flags; int cold = !audio_active; local_irq_save(flags); /* GPE 3: I2SSDI */ set_gpio_ctrl(GPIO_E3 | GPIO_PULLUP_EN | GPIO_MODE_I2SSDI); /* GPE 0: I2SLRCK */ set_gpio_ctrl(GPIO_E0 | GPIO_PULLUP_EN | GPIO_MODE_I2SSDI); /* GPE 1: I2SSCLK */ set_gpio_ctrl(GPIO_E1 | GPIO_PULLUP_EN | GPIO_MODE_I2SSCLK); /* GPE 2: CDCLK */ set_gpio_ctrl(GPIO_E2 | GPIO_PULLUP_EN | GPIO_MODE_CDCLK); /* GPE 4: I2SSDO */ set_gpio_ctrl(GPIO_E4 | GPIO_PULLUP_EN | GPIO_MODE_I2SSDO); local_irq_restore(flags); uda1380_init(); init_s3c2440_iis_bus(); output_stream.dma_ch = DMA_CH2; input_stream.dma_ch = DMA_CH1; 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; } if (audio_init_dma(&input_stream, "UDA1380 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(&smdk2440_audio_fops, -1); audio_dev_mixer = register_sound_mixer(&smdk2440_mixer_fops, -1); printk(AUDIO_NAME_VERBOSE " initialized\n"); 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); audio_clear_buf(&input_stream); } return 0;}void cleanup_module(void){ unregister_sound_dsp(audio_dev_dsp); unregister_sound_mixer(audio_dev_mixer); audio_clear_dma(&input_stream); audio_clear_dma(&output_stream); printk(AUDIO_NAME_VERBOSE " unloaded\n");}module_init(init_module1380);module_exit(cleanup_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -