📄 es1371.c
字号:
s->sctrl |= SCTRL_R1SMB; else s->sctrl &= ~SCTRL_R1SMB; outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); spin_unlock_irqrestore(&s->lock, flags); } if (file->f_mode & FMODE_WRITE) { stop_dac2(s); s->dma_dac2.ready = 0; spin_lock_irqsave(&s->lock, flags); if (val) s->sctrl |= SCTRL_P2SMB; else s->sctrl &= ~SCTRL_P2SMB; outl(s->sctrl, s->io+ES1371_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 (file->f_mode & FMODE_READ) { stop_adc(s); s->dma_adc.ready = 0; spin_lock_irqsave(&s->lock, flags); if (val >= 2) s->sctrl |= SCTRL_R1SMB; else s->sctrl &= ~SCTRL_R1SMB; outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); spin_unlock_irqrestore(&s->lock, flags); } if (file->f_mode & FMODE_WRITE) { stop_dac2(s); s->dma_dac2.ready = 0; spin_lock_irqsave(&s->lock, flags); if (val >= 2) s->sctrl |= SCTRL_P2SMB; else s->sctrl &= ~SCTRL_P2SMB; outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); spin_unlock_irqrestore(&s->lock, flags); } } return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ? 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) { if (file->f_mode & FMODE_READ) { stop_adc(s); s->dma_adc.ready = 0; spin_lock_irqsave(&s->lock, flags); if (val == AFMT_S16_LE) s->sctrl |= SCTRL_R1SEB; else s->sctrl &= ~SCTRL_R1SEB; outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); spin_unlock_irqrestore(&s->lock, flags); } if (file->f_mode & FMODE_WRITE) { stop_dac2(s); s->dma_dac2.ready = 0; spin_lock_irqsave(&s->lock, flags); if (val == AFMT_S16_LE) s->sctrl |= SCTRL_P2SEB; else s->sctrl &= ~SCTRL_P2SEB; outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); spin_unlock_irqrestore(&s->lock, flags); } } return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ? AFMT_S16_LE : AFMT_U8, (int *)arg); case SNDCTL_DSP_POST: return 0; case SNDCTL_DSP_GETTRIGGER: val = 0; if (file->f_mode & FMODE_READ && s->ctrl & CTRL_ADC_EN) val |= PCM_ENABLE_INPUT; if (file->f_mode & FMODE_WRITE && s->ctrl & CTRL_DAC2_EN) 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 (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) return ret; s->dma_adc.enabled = 1; start_adc(s); } else { s->dma_adc.enabled = 0; stop_adc(s); } } if (file->f_mode & FMODE_WRITE) { if (val & PCM_ENABLE_OUTPUT) { if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s))) return ret; s->dma_dac2.enabled = 1; start_dac2(s); } else { s->dma_dac2.enabled = 0; stop_dac2(s); } } return 0; case SNDCTL_DSP_GETOSPACE: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); abinfo.fragsize = s->dma_dac2.fragsize; count = s->dma_dac2.count; if (count < 0) count = 0; abinfo.bytes = s->dma_dac2.dmasize - count; abinfo.fragstotal = s->dma_dac2.numfrag; abinfo.fragments = abinfo.bytes >> s->dma_dac2.fragshift; spin_unlock_irqrestore(&s->lock, flags); return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETISPACE: if (!(file->f_mode & FMODE_READ)) return -EINVAL; if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); abinfo.fragsize = s->dma_adc.fragsize; count = s->dma_adc.count; if (count < 0) count = 0; abinfo.bytes = count; abinfo.fragstotal = s->dma_adc.numfrag; abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift; spin_unlock_irqrestore(&s->lock, flags); return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_NONBLOCK: file->f_flags |= O_NONBLOCK; return 0; case SNDCTL_DSP_GETODELAY: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); count = s->dma_dac2.count; spin_unlock_irqrestore(&s->lock, flags); if (count < 0) count = 0; return put_user(count, (int *)arg); case SNDCTL_DSP_GETIPTR: if (!(file->f_mode & FMODE_READ)) return -EINVAL; if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); cinfo.bytes = s->dma_adc.total_bytes; count = s->dma_adc.count; if (count < 0) count = 0; cinfo.blocks = count >> s->dma_adc.fragshift; cinfo.ptr = s->dma_adc.hwptr; if (s->dma_adc.mapped) s->dma_adc.count &= s->dma_adc.fragsize-1; spin_unlock_irqrestore(&s->lock, flags); return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); cinfo.bytes = s->dma_dac2.total_bytes; count = s->dma_dac2.count; if (count < 0) count = 0; cinfo.blocks = count >> s->dma_dac2.fragshift; cinfo.ptr = s->dma_dac2.hwptr; if (s->dma_dac2.mapped) s->dma_dac2.count &= s->dma_dac2.fragsize-1; spin_unlock_irqrestore(&s->lock, flags); return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) { if ((val = prog_dmabuf_dac2(s))) return val; return put_user(s->dma_dac2.fragsize, (int *)arg); } if ((val = prog_dmabuf_adc(s))) return val; 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((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, (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 mixdev_ioctl(&s->codec, cmd, arg);}static int es1371_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 es1371_state *s; for (list = devs.next; ; list = list->next) { if (list == &devs) return -ENODEV; s = list_entry(list, struct es1371_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); } if (file->f_mode & FMODE_READ) { s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0; s->dma_adc.enabled = 1; set_adc_rate(s, 8000); } if (file->f_mode & FMODE_WRITE) { s->dma_dac2.ossfragshift = s->dma_dac2.ossmaxfrags = s->dma_dac2.subdivision = 0; s->dma_dac2.enabled = 1; set_dac2_rate(s, 8000); } spin_lock_irqsave(&s->lock, flags); if (file->f_mode & FMODE_READ) { s->sctrl &= ~SCTRL_R1FMT; if ((minor & 0xf) == SND_DEV_DSP16) s->sctrl |= ES1371_FMT_S16_MONO << SCTRL_SH_R1FMT; else s->sctrl |= ES1371_FMT_U8_MONO << SCTRL_SH_R1FMT; } if (file->f_mode & FMODE_WRITE) { s->sctrl &= ~SCTRL_P2FMT; if ((minor & 0xf) == SND_DEV_DSP16) s->sctrl |= ES1371_FMT_S16_MONO << SCTRL_SH_P2FMT; else s->sctrl |= ES1371_FMT_U8_MONO << SCTRL_SH_P2FMT; } outl(s->sctrl, s->io+ES1371_REG_SERIAL_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 es1371_release(struct inode *inode, struct file *file){ struct es1371_state *s = (struct es1371_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); 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); up(&s->open_sem); wake_up(&s->open_wait); unlock_kernel(); return 0;}static /*const*/ struct file_operations es1371_audio_fops = { owner: THIS_MODULE, llseek: no_llseek, read: es1371_read, write: es1371_write, poll: es1371_poll, ioctl: es1371_ioctl, mmap: es1371_mmap, open: es1371_open, release: es1371_release,};/* --------------------------------------------------------------------- */static ssize_t es1371_write_dac(struct file *file, const char *buffer, size_t count, loff_t *ppos){ struct es1371_state *s = (struct es1371_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 -
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -