static int audio_release(struct inode *inode, struct file *file) { audio_state_t *state = file->private_data; audio_stream_t *os = state->output_stream; audio_stream_t *is = state->input_stream; DPRINTK("audio_release\n"); down(&state->sem); if (file->f_mode & FMODE_READ) { audio_discard_buf(is); s3c2410_dma_free(is->dma,&s3c_rec_dma_client); state->rd_ref = 0; } if (file->f_mode & FMODE_WRITE) { audio_sync(file); audio_discard_buf(os); s3c2410_dma_free(os->dma,&s3c_play_dma_client); state->wr_ref = 0; } if (!AUDIO_ACTIVE(state)) { if (state->hw_shutdown) state->hw_shutdown(state->data); } up(&state->sem); return 0; }
int main(int argc, char *argv[]) { int sfd; int dfd; sfd = open("sound.raw", O_RDONLY); dfd = open("/dev/dsp", O_WRONLY); audio_setfmt(dfd, 16, 44100, 2); char *buf = malloc(44100 * 2 * 2 * 60 * 5); if(read(sfd, buf, 44100 * 2 * 2 * 60 * 5) < 0) perror("read()"); write(dfd, buf, 44100 * 2 * 2 * 60 * 5); audio_sync(dfd); close(sfd); close(dfd); return 0; }
static int audio_release(struct inode *inode, struct file *file) { audio_state_t *state = file->private_data; audio_stream_t *os = state->output_stream; audio_stream_t *is = state->input_stream; DPRINTK("audio_release\n"); down(&state->sem); if (file->f_mode & FMODE_READ) { audio_discard_buf(is); DMA_FREE(is); is->dma_spinref = 0; if (state->need_tx_for_rx) { os->spin_idle = 0; if (!state->wr_ref) { DMA_FREE(os); os->dma_spinref = 0; } } state->rd_ref = 0; } if (file->f_mode & FMODE_WRITE) { audio_sync(file); audio_discard_buf(os); if (!state->need_tx_for_rx || !state->rd_ref) { DMA_FREE(os); os->dma_spinref = 0; } state->wr_ref = 0; } if (!AUDIO_ACTIVE(state)) { if (state->hw_shutdown) state->hw_shutdown(state->data); #ifdef CONFIG_PM pm_unregister(state->pm_dev); #endif } up(&state->sem); return 0; }
static int audio_release(struct inode *inode, struct file *file) { audio_state_t *state = (audio_state_t *)file->private_data; DPRINTK("audio_release\n"); down(&state->sem); if (file->f_mode & FMODE_READ) { if (state->tx_spinning) { sa1100_dma_set_spin(state->output_stream->dma_ch, 0, 0); state->tx_spinning = 0; } audio_clear_buf(state->input_stream); if (!state->skip_dma_init) { sa1100_free_dma(state->input_stream->dma_ch); if (state->need_tx_for_rx && !state->wr_ref) sa1100_free_dma(state->output_stream->dma_ch); } state->rd_ref = 0; } if (file->f_mode & FMODE_WRITE) { audio_sync(file); audio_clear_buf(state->output_stream); if (!state->skip_dma_init) if (!state->need_tx_for_rx || !state->rd_ref) sa1100_free_dma(state->output_stream->dma_ch); state->wr_ref = 0; } if (!AUDIO_ACTIVE(state)) { if (state->hw_shutdown) state->hw_shutdown(state->data); #ifdef CONFIG_PM pm_unregister(state->pm_dev); #endif } up(&state->sem); return 0; }
static int audio_release(struct inode *inode, struct file *file) { audio_state_t *state = file->private_data; down(&state->sem); if (file->f_mode & FMODE_READ) { audio_clear_buf(state->input_stream); DRCMRRXPCDR = 0; pxa_free_dma(state->input_stream->dma_ch); state->rd_ref = 0; } if (file->f_mode & FMODE_WRITE) { audio_sync(file); audio_clear_buf(state->output_stream); DRCMRTXPCDR = 0; pxa_free_dma(state->output_stream->dma_ch); state->wr_ref = 0; } up(&state->sem); return 0; }
static int audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) { audio_state_t *state = file->private_data; audio_stream_t *os = state->output_stream; audio_stream_t *is = state->input_stream; long val; DPRINTK(__FILE__ " audio_ioctl 0x%08x\n", cmd); /* dispatch based on command */ switch (cmd) { case OSS_GETVERSION: return put_user(SOUND_VERSION, (int *)arg); case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) return put_user(os->fragsize, (int *)arg); else return put_user(is->fragsize, (int *)arg); case SNDCTL_DSP_GETCAPS: val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP; if (is && os) val |= DSP_CAP_DUPLEX; return put_user(val, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: if (get_user(val, (long *) arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { int ret = audio_set_fragments(is, val); if (ret < 0) return ret; ret = put_user(ret, (int *)arg); if (ret) return ret; } if (file->f_mode & FMODE_WRITE) { int ret = audio_set_fragments(os, val); if (ret < 0) return ret; ret = put_user(ret, (int *)arg); if (ret) return ret; } return 0; case SNDCTL_DSP_SYNC: return audio_sync(file); case SNDCTL_DSP_SETDUPLEX: return 0; case SNDCTL_DSP_POST: return 0; case SNDCTL_DSP_GETTRIGGER: val = 0; if (file->f_mode & FMODE_READ && is->active && !is->stopped) val |= PCM_ENABLE_INPUT; if (file->f_mode & FMODE_WRITE && os->active && !os->stopped) val |= PCM_ENABLE_OUTPUT; return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: if (get_user(val, (int *)arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { unsigned long flags; if (!is->active) { if (!is->buffers && audio_setup_buf(is)) return -ENOMEM; audio_prime_rx(state); } local_irq_save(flags); is->stopped = 0; audio_process_dma(is); local_irq_restore(flags); } else { audio_stop_dma(is); } } if (file->f_mode & FMODE_WRITE) { if (val & PCM_ENABLE_OUTPUT) { unsigned long flags; if (!os->buffers && audio_setup_buf(os)) return -ENOMEM; local_irq_save(flags); if (os->mapped && !os->pending_frags) { os->pending_frags = os->nbfrags; sema_init(&os->sem, 0); os->active = 1; } os->stopped = 0; audio_process_dma(os); local_irq_restore(flags); } else { audio_stop_dma(os); } } return 0; case SNDCTL_DSP_GETOPTR: case SNDCTL_DSP_GETIPTR: { count_info inf = { 0, }; audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is; int bytecount, offset; unsigned long flags; if ((s == is && !(file->f_mode & FMODE_READ)) || (s == os && !(file->f_mode & FMODE_WRITE))) return -EINVAL; if (s->active) { local_irq_save(flags); offset = audio_get_dma_pos(s); inf.ptr = s->dma_tail * s->fragsize + offset; bytecount = s->bytecount + offset; s->bytecount = -offset; inf.blocks = s->fragcount; s->fragcount = 0; local_irq_restore(flags); if (bytecount < 0) bytecount = 0; inf.bytes = bytecount; } return copy_to_user((void *)arg, &inf, sizeof(inf)); } case SNDCTL_DSP_GETOSPACE: case SNDCTL_DSP_GETISPACE: { audio_buf_info inf = { 0, }; audio_stream_t *s = (cmd == SNDCTL_DSP_GETOSPACE) ? os : is; if ((s == is && !(file->f_mode & FMODE_READ)) || (s == os && !(file->f_mode & FMODE_WRITE))) return -EINVAL; if (!s->buffers && audio_setup_buf(s)) return -ENOMEM; inf.bytes = atomic_read(&s->sem.count) * s->fragsize; /* inf.bytes -= s->buffers[s->usr_head].offset; */ inf.fragments = inf.bytes / s->fragsize; inf.fragsize = s->fragsize; inf.fragstotal = s->nbfrags; return copy_to_user((void *)arg, &inf, sizeof(inf)); } case SNDCTL_DSP_NONBLOCK: file->f_flags |= O_NONBLOCK; return 0; case SNDCTL_DSP_RESET: if (file->f_mode & FMODE_READ) { audio_reset(is); if (state->need_tx_for_rx) { unsigned long flags; local_irq_save(flags); os->spin_idle = 0; local_irq_restore(flags); } } if (file->f_mode & FMODE_WRITE) { audio_reset(os); } return 0; default: /* * Let the client of this module handle the * non generic ioctls */ return state->client_ioctl(inode, file, cmd, arg); } return 0; }
static int audio_ioctl( struct inode *inode, struct file *file, uint cmd, ulong arg) { audio_state_t *state = file->private_data; audio_stream_t *os = state->output_stream; audio_stream_t *is = state->input_stream; long val; switch (cmd) { case OSS_GETVERSION: return put_user(SOUND_VERSION, (int *)arg); case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) return put_user(os->fragsize, (int *)arg); else return put_user(is->fragsize, (int *)arg); case SNDCTL_DSP_GETCAPS: val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP; if (is && os) val |= DSP_CAP_DUPLEX; return put_user(val, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: if (get_user(val, (long *) arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { int ret = audio_set_fragments(is, val); if (ret < 0) return ret; ret = put_user(ret, (int *)arg); if (ret) return ret; } if (file->f_mode & FMODE_WRITE) { int ret = audio_set_fragments(os, val); if (ret < 0) return ret; ret = put_user(ret, (int *)arg); if (ret) return ret; } return 0; case SNDCTL_DSP_SYNC: return audio_sync(file); case SNDCTL_DSP_SETDUPLEX: return 0; case SNDCTL_DSP_POST: return 0; case SNDCTL_DSP_GETTRIGGER: val = 0; if (file->f_mode & FMODE_READ && DCSR(is->dma_ch) & DCSR_RUN) val |= PCM_ENABLE_INPUT; if (file->f_mode & FMODE_WRITE && DCSR(os->dma_ch) & DCSR_RUN) val |= PCM_ENABLE_OUTPUT; return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: if (get_user(val, (int *)arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { if (!is->buffers && audio_setup_buf(is)) return -ENOMEM; if (!(DCSR(is->dma_ch) & DCSR_RUN)) { audio_buf_t *b = &is->buffers[is->dma_frag]; DDADR(is->dma_ch) = b->dma_desc->ddadr; DCSR(is->dma_ch) = DCSR_RUN; } } else { DCSR(is->dma_ch) = 0; } } if (file->f_mode & FMODE_WRITE) { if (val & PCM_ENABLE_OUTPUT) { if (!os->buffers && audio_setup_buf(os)) return -ENOMEM; if (!(DCSR(os->dma_ch) & DCSR_RUN)) { audio_buf_t *b = &os->buffers[os->dma_frag]; DDADR(os->dma_ch) = b->dma_desc->ddadr; DCSR(os->dma_ch) = DCSR_RUN; } } else { DCSR(os->dma_ch) = 0; } } return 0; case SNDCTL_DSP_GETOSPACE: case SNDCTL_DSP_GETISPACE: { audio_buf_info inf = { 0, }; audio_stream_t *s = (cmd == SNDCTL_DSP_GETOSPACE) ? os : is; if ((s == is && !(file->f_mode & FMODE_READ)) || (s == os && !(file->f_mode & FMODE_WRITE))) return -EINVAL; if (!s->buffers && audio_setup_buf(s)) return -ENOMEM; inf.bytes = atomic_read(&s->sem.count) * s->fragsize; inf.bytes -= s->buffers[s->usr_frag].offset; inf.fragments = inf.bytes / s->fragsize; inf.fragsize = s->fragsize; inf.fragstotal = s->nbfrags; return copy_to_user((void *)arg, &inf, sizeof(inf)); } case SNDCTL_DSP_GETOPTR: case SNDCTL_DSP_GETIPTR: { count_info inf = { 0, }; audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is; dma_addr_t ptr; int bytecount, offset, flags; if ((s == is && !(file->f_mode & FMODE_READ)) || (s == os && !(file->f_mode & FMODE_WRITE))) return -EINVAL; if (DCSR(s->dma_ch) & DCSR_RUN) { audio_buf_t *b; save_flags_cli(flags); ptr = (s->output) ? DSADR(s->dma_ch) : DTADR(s->dma_ch); b = &s->buffers[s->dma_frag]; offset = ptr - b->dma_desc->dsadr; if (offset >= s->fragsize) offset = s->fragsize - 4; } else { save_flags(flags); offset = 0; } inf.ptr = s->dma_frag * s->fragsize + offset; bytecount = s->bytecount + offset; s->bytecount = -offset; inf.blocks = s->fragcount; s->fragcount = 0; restore_flags(flags); if (bytecount < 0) bytecount = 0; inf.bytes = bytecount; return copy_to_user((void *)arg, &inf, sizeof(inf)); } case SNDCTL_DSP_NONBLOCK: file->f_flags |= O_NONBLOCK; return 0; case SNDCTL_DSP_RESET: if (file->f_mode & FMODE_WRITE) audio_clear_buf(os); if (file->f_mode & FMODE_READ) audio_clear_buf(is); return 0; default: return state->client_ioctl(inode, file, cmd, arg); } return 0; }
static int audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) { audio_state_t *state = (audio_state_t *)file->private_data; audio_stream_t *os = state->output_stream; audio_stream_t *is = state->input_stream; long val; /* dispatch based on command */ switch (cmd) { case OSS_GETVERSION: return put_user(SOUND_VERSION, (int *)arg); case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) return put_user(os->fragsize, (int *)arg); else return put_user(is->fragsize, (int *)arg); case SNDCTL_DSP_GETCAPS: val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP; if (is && os) val |= DSP_CAP_DUPLEX; return put_user(val, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: if (get_user(val, (long *) arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { int ret = audio_set_fragments(is, val); if (ret < 0) return ret; ret = put_user(ret, (int *)arg); if (ret) return ret; } if (file->f_mode & FMODE_WRITE) { int ret = audio_set_fragments(os, val); if (ret < 0) return ret; ret = put_user(ret, (int *)arg); if (ret) return ret; } return 0; case SNDCTL_DSP_SYNC: return audio_sync(file); case SNDCTL_DSP_SETDUPLEX: return 0; case SNDCTL_DSP_POST: return 0; case SNDCTL_DSP_GETTRIGGER: val = 0; if (file->f_mode & FMODE_READ && is->active && !is->stopped) val |= PCM_ENABLE_INPUT; if (file->f_mode & FMODE_WRITE && os->active && !os->stopped) val |= PCM_ENABLE_OUTPUT; return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: if (get_user(val, (int *)arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { if (!is->active) { if (!is->buffers && audio_setup_buf(is)) return -ENOMEM; audio_prime_dma(is); } audio_check_tx_spin(state); if (is->stopped) { is->stopped = 0; sa1100_dma_resume(is->dma_ch); } } else { sa1100_dma_stop(is->dma_ch); is->stopped = 1; } } if (file->f_mode & FMODE_WRITE) { if (val & PCM_ENABLE_OUTPUT) { if (!os->active) { if (!os->buffers && audio_setup_buf(os)) return -ENOMEM; if (os->mapped) audio_prime_dma(os); } if (os->stopped) { os->stopped = 0; sa1100_dma_resume(os->dma_ch); } } else { sa1100_dma_stop(os->dma_ch); os->stopped = 1; } } return 0; case SNDCTL_DSP_GETOPTR: case SNDCTL_DSP_GETIPTR: { count_info inf = { 0, }; audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is; audio_buf_t *b; dma_addr_t ptr; int bytecount, offset, flags; if ((s == is && !(file->f_mode & FMODE_READ)) || (s == os && !(file->f_mode & FMODE_WRITE))) return -EINVAL; if (s->active) { save_flags_cli(flags); if (sa1100_dma_get_current(s->dma_ch, (void *)&b, &ptr) == 0) { offset = ptr - b->dma_addr; inf.ptr = (b - s->buffers) * s->fragsize + offset; } else offset = 0; bytecount = s->bytecount + offset; s->bytecount = -offset; inf.blocks = s->fragcount; s->fragcount = 0; restore_flags(flags); if (bytecount < 0) bytecount = 0; inf.bytes = bytecount; } return copy_to_user((void *)arg, &inf, sizeof(inf)); } case SNDCTL_DSP_GETOSPACE: { audio_buf_info inf = { 0, }; int i; if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; if (!os->buffers && audio_setup_buf(os)) return -ENOMEM; for (i = 0; i < os->nbfrags; i++) { if (atomic_read(&os->buffers[i].sem.count) > 0) { if (os->buffers[i].size == 0) inf.fragments++; inf.bytes += os->fragsize - os->buffers[i].size; } } inf.fragstotal = os->nbfrags; inf.fragsize = os->fragsize; return copy_to_user((void *)arg, &inf, sizeof(inf)); } case SNDCTL_DSP_GETISPACE: { audio_buf_info inf = { 0, }; int i; if (!(file->f_mode & FMODE_READ)) return -EINVAL; if (!is->buffers && audio_setup_buf(is)) return -ENOMEM; for (i = 0; i < is->nbfrags; i++) { if (atomic_read(&is->buffers[i].sem.count) > 0) { if (is->buffers[i].size == is->fragsize) inf.fragments++; inf.bytes += is->buffers[i].size; } } inf.fragstotal = is->nbfrags; inf.fragsize = is->fragsize; return copy_to_user((void *)arg, &inf, sizeof(inf)); } case SNDCTL_DSP_NONBLOCK: file->f_flags |= O_NONBLOCK; return 0; case SNDCTL_DSP_GETODELAY: { int count = 0; int i; int flags; audio_buf_t *b; dma_addr_t ptr; if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; if (!os->buffers && audio_setup_buf(os)) return -ENOMEM; save_flags_cli(flags); for (i = 0; i < os->nbfrags; i++) { /* if contains data */ if (atomic_read(&os->buffers[i].sem.count) <= 0) { count += os->fragsize; } } if (sa1100_dma_get_current(os->dma_ch, (void *)&b, &ptr) == 0) count -= ptr - b->dma_addr; restore_flags(flags); return put_user(count, (int *)arg); } case SNDCTL_DSP_RESET: if (file->f_mode & FMODE_READ) { if (state->tx_spinning) { sa1100_dma_set_spin(os->dma_ch, 0, 0); state->tx_spinning = 0; } audio_reset_buf(is); } if (file->f_mode & FMODE_WRITE) { audio_reset_buf(os); } return 0; default: /* * Let the client of this module handle the * non generic ioctls */ return state->client_ioctl(inode, file, cmd, arg); } return 0; }