📄 es1370.c
字号:
} s->mix.recsrc = val; wrcodec(s, 0x12, j & 0xd5); wrcodec(s, 0x13, j & 0xaa); wrcodec(s, 0x14, (j >> 8) & 0x17); wrcodec(s, 0x15, (j >> 8) & 0x0f); i = (j & 0x37f) | ((j << 1) & 0x3000) | 0xc60; if (!s->mix.imix) { i &= 0xff60; /* mute record and line monitor */ } wrcodec(s, 0x10, i); wrcodec(s, 0x11, i >> 8);}static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long arg){ unsigned long flags; int i, val; unsigned char l, r, rl, rr; VALIDATE_STATE(s); if (cmd == SOUND_MIXER_PRIVATE1) { /* enable/disable/query mixer preamp */ if (get_user(val, (int *)arg)) return -EFAULT; if (val != -1) { s->mix.micpreamp = !!val; wrcodec(s, 0x19, s->mix.micpreamp); } return put_user(s->mix.micpreamp, (int *)arg); } if (cmd == SOUND_MIXER_PRIVATE2) { /* enable/disable/query use of linein as second lineout */ if (get_user(val, (int *)arg)) return -EFAULT; if (val != -1) { spin_lock_irqsave(&s->lock, flags); if (val) s->ctrl |= CTRL_XCTL0; else s->ctrl &= ~CTRL_XCTL0; outl(s->ctrl, s->io+ES1370_REG_CONTROL); spin_unlock_irqrestore(&s->lock, flags); } return put_user((s->ctrl & CTRL_XCTL0) ? 1 : 0, (int *)arg); } if (cmd == SOUND_MIXER_PRIVATE3) { /* enable/disable/query microphone impedance setting */ if (get_user(val, (int *)arg)) return -EFAULT; if (val != -1) { spin_lock_irqsave(&s->lock, flags); if (val) s->ctrl |= CTRL_XCTL1; else s->ctrl &= ~CTRL_XCTL1; outl(s->ctrl, s->io+ES1370_REG_CONTROL); spin_unlock_irqrestore(&s->lock, flags); } return put_user((s->ctrl & CTRL_XCTL1) ? 1 : 0, (int *)arg); } if (cmd == SOUND_MIXER_INFO) { mixer_info info; strncpy(info.id, "ES1370", sizeof(info.id)); strncpy(info.name, "Ensoniq ES1370", sizeof(info.name)); info.modify_counter = s->mix.modcnt; if (copy_to_user((void *)arg, &info, sizeof(info))) return -EFAULT; return 0; } if (cmd == SOUND_OLD_MIXER_INFO) { _old_mixer_info info; strncpy(info.id, "ES1370", sizeof(info.id)); strncpy(info.name, "Ensoniq ES1370", sizeof(info.name)); if (copy_to_user((void *)arg, &info, sizeof(info))) return -EFAULT; return 0; } if (cmd == OSS_GETVERSION) return put_user(SOUND_VERSION, (int *)arg); if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int)) return -EINVAL; if (_SIOC_DIR(cmd) == _SIOC_READ) { switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ return put_user(s->mix.recsrc, (int *)arg); case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */ val = SOUND_MASK_IMIX; for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) if (mixtable[i].avail) val |= 1 << i; return put_user(val, (int *)arg); case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */ for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++) if (mixtable[i].recmask) val |= 1 << i; return put_user(val, (int *)arg); case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */ for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++) if (mixtable[i].stereo) val |= 1 << i; return put_user(val, (int *)arg); case SOUND_MIXER_CAPS: return put_user(0, (int *)arg); case SOUND_MIXER_IMIX: return put_user(s->mix.imix, (int *)arg); default: i = _IOC_NR(cmd); if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].avail) return -EINVAL; return put_user(s->mix.vol[mixtable[i].volidx], (int *)arg); } } if (_SIOC_DIR(cmd) != (_SIOC_READ|_SIOC_WRITE)) return -EINVAL; s->mix.modcnt++; switch (_IOC_NR(cmd)) { case SOUND_MIXER_IMIX: if (get_user(s->mix.imix, (int *)arg)) return -EFAULT; set_recsrc(s, s->mix.recsrc); return 0; case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ if (get_user(val, (int *)arg)) return -EFAULT; set_recsrc(s, val); return 0; default: i = _IOC_NR(cmd); if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].avail) return -EINVAL; if (get_user(val, (int *)arg)) return -EFAULT; l = val & 0xff; if (l > 100) l = 100; if (mixtable[i].stereo) { r = (val >> 8) & 0xff; if (r > 100) r = 100; if (l < 7) { rl = 0x80; l = 0; } else { rl = 31 - ((l - 7) / 3); l = (31 - rl) * 3 + 7; } if (r < 7) { rr = 0x80; r = 0; } else { rr = 31 - ((r - 7) / 3); r = (31 - rr) * 3 + 7; } wrcodec(s, mixtable[i].right, rr); } else { if (mixtable[i].left == 15) { if (l < 2) { rr = rl = 0x80; r = l = 0; } else { rl = 7 - ((l - 2) / 14); r = l = (7 - rl) * 14 + 2; } } else { if (l < 7) { rl = 0x80; r = l = 0; } else { rl = 31 - ((l - 7) / 3); r = l = (31 - rl) * 3 + 7; } } } wrcodec(s, mixtable[i].left, rl);#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS s->mix.vol[mixtable[i].volidx] = ((unsigned int)r << 8) | l;#else s->mix.vol[mixtable[i].volidx] = val;#endif return put_user(s->mix.vol[mixtable[i].volidx], (int *)arg); }}/* --------------------------------------------------------------------- */static int es1370_open_mixdev(struct inode *inode, struct file *file){ int minor = MINOR(inode->i_rdev); 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_mixer == minor) break; } VALIDATE_STATE(s); file->private_data = s; return 0;}static int es1370_release_mixdev(struct inode *inode, struct file *file){ struct es1370_state *s = (struct es1370_state *)file->private_data; VALIDATE_STATE(s); return 0;}static int es1370_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ return mixer_ioctl((struct es1370_state *)file->private_data, cmd, arg);}static /*const*/ struct file_operations es1370_mixer_fops = { owner: THIS_MODULE, llseek: no_llseek, ioctl: es1370_ioctl_mixdev, open: es1370_open_mixdev, release: es1370_release_mixdev,};/* --------------------------------------------------------------------- */static int drain_dac1(struct es1370_state *s, int nonblock){ DECLARE_WAITQUEUE(wait, current); unsigned long flags; int count, tmo; if (s->dma_dac1.mapped || !s->dma_dac1.ready) return 0; add_wait_queue(&s->dma_dac1.wait, &wait); for (;;) { __set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&s->lock, flags); count = s->dma_dac1.count; spin_unlock_irqrestore(&s->lock, flags); if (count <= 0) break; if (signal_pending(current)) break; if (nonblock) { remove_wait_queue(&s->dma_dac1.wait, &wait); set_current_state(TASK_RUNNING); return -EBUSY; } tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2 / dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL]; tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT]; if (!schedule_timeout(tmo + 1)) DBG(printk(KERN_DEBUG "es1370: dma timed out??\n");) } remove_wait_queue(&s->dma_dac1.wait, &wait); set_current_state(TASK_RUNNING); if (signal_pending(current)) return -ERESTARTSYS; return 0;}static int drain_dac2(struct es1370_state *s, int nonblock){ DECLARE_WAITQUEUE(wait, current); unsigned long flags; int count, tmo; if (s->dma_dac2.mapped || !s->dma_dac2.ready) return 0; add_wait_queue(&s->dma_dac2.wait, &wait); for (;;) { __set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&s->lock, flags); count = s->dma_dac2.count; spin_unlock_irqrestore(&s->lock, flags); if (count <= 0) break; if (signal_pending(current)) break; if (nonblock) { remove_wait_queue(&s->dma_dac2.wait, &wait); set_current_state(TASK_RUNNING); return -EBUSY; } tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2 / DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV); tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT]; if (!schedule_timeout(tmo + 1)) DBG(printk(KERN_DEBUG "es1370: dma timed out??\n");) } remove_wait_queue(&s->dma_dac2.wait, &wait); set_current_state(TASK_RUNNING); if (signal_pending(current)) return -ERESTARTSYS; return 0;}/* --------------------------------------------------------------------- */static ssize_t es1370_read(struct file *file, 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_adc.mapped) return -ENXIO; if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; down(&s->sem); if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) goto out; add_wait_queue(&s->dma_adc.wait, &wait); while (count > 0) { spin_lock_irqsave(&s->lock, flags); swptr = s->dma_adc.swptr; cnt = s->dma_adc.dmasize-swptr; if (s->dma_adc.count < cnt) cnt = s->dma_adc.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_adc.enabled) start_adc(s); if (file->f_flags & O_NONBLOCK) { if (!ret) ret = -EAGAIN; goto out; } up(&s->sem); schedule(); if (signal_pending(current)) { if (!ret) ret = -ERESTARTSYS; goto out; } down(&s->sem); if (s->dma_adc.mapped) { ret = -ENXIO; goto out; } continue; } if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) { if (!ret) ret = -EFAULT; goto out; } swptr = (swptr + cnt) % s->dma_adc.dmasize; spin_lock_irqsave(&s->lock, flags); s->dma_adc.swptr = swptr; s->dma_adc.count -= cnt; spin_unlock_irqrestore(&s->lock, flags); count -= cnt; buffer += cnt; ret += cnt; if (s->dma_adc.enabled) start_adc(s); }out: up(&s->sem); remove_wait_queue(&s->dma_adc.wait, &wait); set_current_state(TASK_RUNNING); return ret;}static ssize_t es1370_write(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_dac2.mapped) return -ENXIO; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; down(&s->sem); if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s))) goto out; ret = 0; add_wait_queue(&s->dma_dac2.wait, &wait); while (count > 0) { spin_lock_irqsave(&s->lock, flags); if (s->dma_dac2.count < 0) { s->dma_dac2.count = 0; s->dma_dac2.swptr = s->dma_dac2.hwptr; } swptr = s->dma_dac2.swptr; cnt = s->dma_dac2.dmasize-swptr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -