📄 2410audio_rec.c
字号:
}static int smdk2410_mixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ int ret; long val = 0; switch (cmd) { case SOUND_MIXER_INFO: { mixer_info info; strncpy(info.id, "UDA1380", sizeof(info.id)); strncpy(info.name,"Philips UDA1380", sizeof(info.name)); info.modify_counter = audio_mix_modcnt; return copy_to_user((void *)arg, &info, sizeof(info)); } case SOUND_OLD_MIXER_INFO: { _old_mixer_info info; strncpy(info.id, "UDA1380", sizeof(info.id)); strncpy(info.name,"Philips UDA1380", sizeof(info.name)); return copy_to_user((void *)arg, &info, sizeof(info)); } case SOUND_MIXER_READ_STEREODEVS: return put_user(0, (long *) arg); case SOUND_MIXER_READ_CAPS: val = SOUND_CAP_EXCL_INPUT; return put_user(val, (long *) arg); case SOUND_MIXER_WRITE_VOLUME: ret = get_user(val, (long *) arg); if (ret) return ret; val &= 0xFF; uda1380_volume = (val << 8) | val; _Wr24C080(0x30,0x10,(unsigned int)uda1380_volume); break; case SOUND_MIXER_READ_VOLUME: val = uda1380_volume; val &= 0xFF; 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; 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 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 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_mixer_open(struct inode *inode, struct file *file){ MOD_INC_USE_COUNT; return 0;}static int smdk2410_mixer_release(struct inode *inode, struct file *file){ MOD_DEC_USE_COUNT; return 0;}static struct file_operations smdk2410_mixer_fops = { ioctl: smdk2410_mixer_ioctl, open: smdk2410_mixer_open, read: smdk2410_mixer_read, release: smdk2410_mixer_release};static void init_s3c2410_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){ return s3c2410_request_dma("I2SSDI", s->dma_ch, NULL, audio_dmain_done_callback);}static int audio_clear_dma(audio_stream_t * s){ s3c2410_free_dma(s->dma_ch); return 0;}int init_module(void){ unsigned long 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_s3c2410_iis_bus(); input_stream.dma_ch = DMA_CH1; 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_mixer = register_sound_mixer(&smdk2410_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_mixer(audio_dev_mixer); audio_clear_dma(&input_stream); printk(AUDIO_NAME_VERBOSE " unloaded\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -