📄 es1370.c
字号:
return put_user(s->dma_adc.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: if (get_user(val, (int *)arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { s->dma_adc.ossfragshift = val & 0xffff; s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; if (s->dma_adc.ossfragshift < 4) s->dma_adc.ossfragshift = 4; if (s->dma_adc.ossfragshift > 15) s->dma_adc.ossfragshift = 15; if (s->dma_adc.ossmaxfrags < 4) s->dma_adc.ossmaxfrags = 4; } if (file->f_mode & FMODE_WRITE) { s->dma_dac2.ossfragshift = val & 0xffff; s->dma_dac2.ossmaxfrags = (val >> 16) & 0xffff; if (s->dma_dac2.ossfragshift < 4) s->dma_dac2.ossfragshift = 4; if (s->dma_dac2.ossfragshift > 15) s->dma_dac2.ossfragshift = 15; if (s->dma_dac2.ossmaxfrags < 4) s->dma_dac2.ossmaxfrags = 4; } return 0; case SNDCTL_DSP_SUBDIVIDE: if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || (file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision)) return -EINVAL; if (get_user(val, (int *)arg)) return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) s->dma_adc.subdivision = val; if (file->f_mode & FMODE_WRITE) s->dma_dac2.subdivision = val; return 0; case SOUND_PCM_READ_RATE: return put_user(DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV), (int *)arg); case SOUND_PCM_READ_CHANNELS: return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ? 2 : 1, (int *)arg); case SOUND_PCM_READ_BITS: return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ? 16 : 8, (int *)arg); case SOUND_PCM_WRITE_FILTER: case SNDCTL_DSP_SETSYNCRO: case SOUND_PCM_READ_FILTER: return -EINVAL; } return mixer_ioctl(s, cmd, arg);}static int es1370_open(struct inode *inode, struct file *file){ int minor = MINOR(inode->i_rdev); DECLARE_WAITQUEUE(wait, current); unsigned long flags; struct list_head *list; struct es1370_state *s; for (list = devs.next; ; list = list->next) { if (list == &devs) return -ENODEV; s = list_entry(list, struct es1370_state, devs); if (!((s->dev_audio ^ minor) & ~0xf)) break; } VALIDATE_STATE(s); file->private_data = s; /* wait for device to become free */ down(&s->open_sem); while (s->open_mode & file->f_mode) { if (file->f_flags & O_NONBLOCK) { up(&s->open_sem); return -EBUSY; } add_wait_queue(&s->open_wait, &wait); __set_current_state(TASK_INTERRUPTIBLE); up(&s->open_sem); schedule(); remove_wait_queue(&s->open_wait, &wait); set_current_state(TASK_RUNNING); if (signal_pending(current)) return -ERESTARTSYS; down(&s->open_sem); } spin_lock_irqsave(&s->lock, flags); if (!(s->open_mode & (FMODE_READ|FMODE_WRITE))) s->ctrl = (s->ctrl & ~CTRL_PCLKDIV) | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV); if (file->f_mode & FMODE_READ) { s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0; s->dma_adc.enabled = 1; s->sctrl &= ~SCTRL_R1FMT; if ((minor & 0xf) == SND_DEV_DSP16) s->sctrl |= ES1370_FMT_S16_MONO << SCTRL_SH_R1FMT; else s->sctrl |= ES1370_FMT_U8_MONO << SCTRL_SH_R1FMT; } if (file->f_mode & FMODE_WRITE) { s->dma_dac2.ossfragshift = s->dma_dac2.ossmaxfrags = s->dma_dac2.subdivision = 0; s->dma_dac2.enabled = 1; s->sctrl &= ~SCTRL_P2FMT; if ((minor & 0xf) == SND_DEV_DSP16) s->sctrl |= ES1370_FMT_S16_MONO << SCTRL_SH_P2FMT; else s->sctrl |= ES1370_FMT_U8_MONO << SCTRL_SH_P2FMT; } outl(s->sctrl, s->io+ES1370_REG_SERIAL_CONTROL); outl(s->ctrl, s->io+ES1370_REG_CONTROL); spin_unlock_irqrestore(&s->lock, flags); s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); up(&s->open_sem); init_MUTEX(&s->sem); return 0;}static int es1370_release(struct inode *inode, struct file *file){ struct es1370_state *s = (struct es1370_state *)file->private_data; VALIDATE_STATE(s); lock_kernel(); if (file->f_mode & FMODE_WRITE) drain_dac2(s, file->f_flags & O_NONBLOCK); down(&s->open_sem); if (file->f_mode & FMODE_WRITE) { stop_dac2(s); synchronize_irq(); dealloc_dmabuf(s, &s->dma_dac2); } if (file->f_mode & FMODE_READ) { stop_adc(s); dealloc_dmabuf(s, &s->dma_adc); } s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); wake_up(&s->open_wait); up(&s->open_sem); unlock_kernel(); return 0;}static /*const*/ struct file_operations es1370_audio_fops = { owner: THIS_MODULE, llseek: no_llseek, read: es1370_read, write: es1370_write, poll: es1370_poll, ioctl: es1370_ioctl, mmap: es1370_mmap, open: es1370_open, release: es1370_release,};/* --------------------------------------------------------------------- */static ssize_t es1370_write_dac(struct file *file, const char *buffer, size_t count, loff_t *ppos){ struct es1370_state *s = (struct es1370_state *)file->private_data; DECLARE_WAITQUEUE(wait, current); ssize_t ret = 0; unsigned long flags; unsigned swptr; int cnt; VALIDATE_STATE(s); if (ppos != &file->f_pos) return -ESPIPE; if (s->dma_dac1.mapped) return -ENXIO; if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s))) return ret; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; add_wait_queue(&s->dma_dac1.wait, &wait); while (count > 0) { spin_lock_irqsave(&s->lock, flags); if (s->dma_dac1.count < 0) { s->dma_dac1.count = 0; s->dma_dac1.swptr = s->dma_dac1.hwptr; } swptr = s->dma_dac1.swptr; cnt = s->dma_dac1.dmasize-swptr; if (s->dma_dac1.count + cnt > s->dma_dac1.dmasize) cnt = s->dma_dac1.dmasize - s->dma_dac1.count; if (cnt <= 0) __set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irqrestore(&s->lock, flags); if (cnt > count) cnt = count; if (cnt <= 0) { if (s->dma_dac1.enabled) start_dac1(s); if (file->f_flags & O_NONBLOCK) { if (!ret) ret = -EAGAIN; break; } schedule(); if (signal_pending(current)) { if (!ret) ret = -ERESTARTSYS; break; } continue; } if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt)) { if (!ret) ret = -EFAULT; break; } swptr = (swptr + cnt) % s->dma_dac1.dmasize; spin_lock_irqsave(&s->lock, flags); s->dma_dac1.swptr = swptr; s->dma_dac1.count += cnt; s->dma_dac1.endcleared = 0; spin_unlock_irqrestore(&s->lock, flags); count -= cnt; buffer += cnt; ret += cnt; if (s->dma_dac1.enabled) start_dac1(s); } remove_wait_queue(&s->dma_dac1.wait, &wait); set_current_state(TASK_RUNNING); return ret;}/* No kernel lock - we have our own spinlock */static unsigned int es1370_poll_dac(struct file *file, struct poll_table_struct *wait){ struct es1370_state *s = (struct es1370_state *)file->private_data; unsigned long flags; unsigned int mask = 0; VALIDATE_STATE(s); if (!s->dma_dac1.ready && prog_dmabuf_dac1(s)) return 0; poll_wait(file, &s->dma_dac1.wait, wait); spin_lock_irqsave(&s->lock, flags); es1370_update_ptr(s); if (s->dma_dac1.mapped) { if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize) mask |= POLLOUT | POLLWRNORM; } else { if ((signed)s->dma_dac1.dmasize >= s->dma_dac1.count + (signed)s->dma_dac1.fragsize) mask |= POLLOUT | POLLWRNORM; } spin_unlock_irqrestore(&s->lock, flags); return mask;}static int es1370_mmap_dac(struct file *file, struct vm_area_struct *vma){ struct es1370_state *s = (struct es1370_state *)file->private_data; int ret; unsigned long size; VALIDATE_STATE(s); if (!(vma->vm_flags & VM_WRITE)) return -EINVAL; lock_kernel(); if ((ret = prog_dmabuf_dac1(s)) != 0) goto out; ret = -EINVAL; if (vma->vm_pgoff != 0) goto out; size = vma->vm_end - vma->vm_start; if (size > (PAGE_SIZE << s->dma_dac1.buforder)) goto out; ret = -EAGAIN; if (remap_page_range(vma->vm_start, virt_to_phys(s->dma_dac1.rawbuf), size, vma->vm_page_prot)) goto out; s->dma_dac1.mapped = 1; ret = 0;out: unlock_kernel(); return ret;}static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct es1370_state *s = (struct es1370_state *)file->private_data; unsigned long flags; audio_buf_info abinfo; count_info cinfo; int count; unsigned ctrl; int val, ret; VALIDATE_STATE(s); switch (cmd) { case OSS_GETVERSION: return put_user(SOUND_VERSION, (int *)arg); case SNDCTL_DSP_SYNC: return drain_dac1(s, 0/*file->f_flags & O_NONBLOCK*/); case SNDCTL_DSP_SETDUPLEX: return -EINVAL; case SNDCTL_DSP_GETCAPS: return put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg); case SNDCTL_DSP_RESET: stop_dac1(s); synchronize_irq(); s->dma_dac1.swptr = s->dma_dac1.hwptr = s->dma_dac1.count = s->dma_dac1.total_bytes = 0; return 0; case SNDCTL_DSP_SPEED: if (get_user(val, (int *)arg)) return -EFAULT; if (val >= 0) { stop_dac1(s); s->dma_dac1.ready = 0; for (ctrl = 0; ctrl <= 2; ctrl++) if (val < (dac1_samplerate[ctrl] + dac1_samplerate[ctrl+1]) / 2) break; spin_lock_irqsave(&s->lock, flags); s->ctrl = (s->ctrl & ~CTRL_WTSRSEL) | (ctrl << CTRL_SH_WTSRSEL); outl(s->ctrl, s->io+ES1370_REG_CONTROL); spin_unlock_irqrestore(&s->lock, flags); } return put_user(dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL], (int *)arg); case SNDCTL_DSP_STEREO: if (get_user(val, (int *)arg)) return -EFAULT; stop_dac1(s); s->dma_dac1.ready = 0; spin_lock_irqsave(&s->lock, flags); if (val) s->sctrl |= SCTRL_P1SMB; else s->sctrl &= ~SCTRL_P1SMB; outl(s->sctrl, s->io+ES1370_REG_SERIAL_CONTROL); spin_unlock_irqrestore(&s->lock, flags); return 0; case SNDCTL_DSP_CHANNELS: if (get_user(val, (int *)arg)) return -EFAULT; if (val != 0) { if (s->dma_dac1.mapped) return -EINVAL; stop_dac1(s); s->dma_dac1.ready = 0; spin_lock_irqsave(&s->lock, flags); if (val >= 2) s->sctrl |= SCTRL_P1SMB; else s->sctrl &= ~SCTRL_P1SMB; outl(s->sctrl, s->io+ES1370_REG_SERIAL_CONTROL); spin_unlock_irqrestore(&s->lock, flags); } return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, (int *)arg); case SNDCTL_DSP_GETFMTS: /* Returns a mask */ return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ if (get_user(val, (int *)arg)) return -EFAULT; if (val != AFMT_QUERY) { stop_dac1(s); s->dma_dac1.ready = 0; spin_lock_irqsave(&s->lock, flags); if (val == AFMT_S16_LE) s->sctrl |= SCTRL_P1SEB; else s->sctrl &= ~SCTRL_P1SEB; outl(s->sctrl, s->io+ES1370_REG_SERIAL_CONTROL); spin_unlock_irqrestore(&s->lock, flags); } return put_user((s->sctrl & SCTRL_P1SEB) ? AFMT_S16_LE : AFMT_U8, (int *)arg); case SNDCTL_DSP_POST: return 0; case SNDCTL_DSP_GETTRIGGER: return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, (int *)arg); case SNDCTL_DSP_SETTRIGGER: if (get_user(val, (int *)arg)) return -EFAULT; if (val & PCM_ENABLE_OUTPUT) { if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s))) return ret; s->dma_dac1.enabled = 1; start_dac1(s); } else { s->dma_dac1.enabled = 0; stop_dac1(s); } return 0; case SNDCTL_DSP_GETOSPACE: if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); es1370_update_ptr(s); abinfo.fragsize = s->dma_dac1.fragsize; count = s->dma_dac1.count; if (count < 0) count = 0; abinfo.bytes = s->dma_dac1.dmasize - count; abinfo.fragstotal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -