📄 cmpci.c
字号:
case SNDCTL_DSP_SETDUPLEX: return 0; case SNDCTL_DSP_GETCAPS: return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_BIND, (int *)arg); case SNDCTL_DSP_RESET: if (file->f_mode & FMODE_WRITE) { stop_dac(s); synchronize_irq(); s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = s->dma_dac.total_bytes = 0; if (s->status & DO_DUAL_DAC) s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0; } if (file->f_mode & FMODE_READ) { stop_adc(s); synchronize_irq(); s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0; } return 0; case SNDCTL_DSP_SPEED: if (get_user(val, (int *)arg)) return -EFAULT; if (val >= 0) { if (file->f_mode & FMODE_READ) { spin_lock_irqsave(&s->lock, flags); stop_adc_unlocked(s); s->dma_adc.ready = 0; set_adc_rate_unlocked(s, val); spin_unlock_irqrestore(&s->lock, flags); } if (file->f_mode & FMODE_WRITE) { stop_dac(s); s->dma_dac.ready = 0; if (s->status & DO_DUAL_DAC) s->dma_adc.ready = 0; set_dac_rate(s, val); } } return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg); case SNDCTL_DSP_STEREO: if (get_user(val, (int *)arg)) return -EFAULT; fmtd = 0; fmtm = ~0; if (file->f_mode & FMODE_READ) { stop_adc(s); s->dma_adc.ready = 0; if (val) fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; else fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT); } if (file->f_mode & FMODE_WRITE) { stop_dac(s); s->dma_dac.ready = 0; if (val) fmtd |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT; else fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_DACSHIFT); if (s->status & DO_DUAL_DAC) { s->dma_adc.ready = 0; if (val) fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; else fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT); } } set_fmt(s, fmtm, fmtd); return 0; case SNDCTL_DSP_CHANNELS: if (get_user(val, (int *)arg)) return -EFAULT; if (val != 0) { fmtd = 0; fmtm = ~0; if (file->f_mode & FMODE_READ) { stop_adc(s); s->dma_adc.ready = 0; if (val >= 2) fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; else fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT); } if (file->f_mode & FMODE_WRITE) { stop_dac(s); s->dma_dac.ready = 0; if (val >= 2) fmtd |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT; else fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_DACSHIFT); if (s->status & DO_DUAL_DAC) { s->dma_adc.ready = 0; if (val >= 2) fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; else fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT); } } set_fmt(s, fmtm, fmtd); if ((s->capability & CAN_MULTI_CH) && (file->f_mode & FMODE_WRITE)) { val = set_dac_channels(s, val); return put_user(val, (int *)arg); } } return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_STEREO << CM_CFMT_ADCSHIFT) : (CM_CFMT_STEREO << CM_CFMT_DACSHIFT))) ? 2 : 1, (int *)arg); case SNDCTL_DSP_GETFMTS: /* Returns a mask */ return put_user(AFMT_S16_LE|AFMT_U8|AFMT_AC3, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ if (get_user(val, (int *)arg)) return -EFAULT; if (val != AFMT_QUERY) { fmtd = 0; fmtm = ~0; if (file->f_mode & FMODE_READ) { stop_adc(s); s->dma_adc.ready = 0; if (val == AFMT_S16_LE) fmtd |= CM_CFMT_16BIT << CM_CFMT_ADCSHIFT; else fmtm &= ~(CM_CFMT_16BIT << CM_CFMT_ADCSHIFT); } if (file->f_mode & FMODE_WRITE) { stop_dac(s); s->dma_dac.ready = 0; if (val == AFMT_S16_LE || val == AFMT_AC3) fmtd |= CM_CFMT_16BIT << CM_CFMT_DACSHIFT; else fmtm &= ~(CM_CFMT_16BIT << CM_CFMT_DACSHIFT); if (val == AFMT_AC3) { fmtd |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT; set_ac3(s, s->ratedac); } else set_ac3(s, 0); if (s->status & DO_DUAL_DAC) { s->dma_adc.ready = 0; if (val == AFMT_S16_LE) fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT; else fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT); } } set_fmt(s, fmtm, fmtd); } if (s->status & DO_AC3) return put_user(AFMT_AC3, (int *)arg); return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_16BIT << CM_CFMT_ADCSHIFT) : (CM_CFMT_16BIT << CM_CFMT_DACSHIFT))) ? AFMT_S16_LE : AFMT_U8, (int *)arg); case SNDCTL_DSP_POST: return 0; case SNDCTL_DSP_GETTRIGGER: val = 0; if (s->status & DO_DUAL_DAC) { if (file->f_mode & FMODE_WRITE && (s->enable & CM_ENABLE_CH1) && (s->enable & CM_ENABLE_CH0)) val |= PCM_ENABLE_OUTPUT; return put_user(val, (int *)arg); } if (file->f_mode & FMODE_READ && s->enable & CM_ENABLE_CH0) val |= PCM_ENABLE_INPUT; if (file->f_mode & FMODE_WRITE && s->enable & CM_ENABLE_CH1) 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(s, 1))) return ret; start_adc(s); } else stop_adc(s); } if (file->f_mode & FMODE_WRITE) { if (val & PCM_ENABLE_OUTPUT) { if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) return ret; if (s->status & DO_DUAL_DAC) { if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) return ret; } start_dac(s); } else stop_dac(s); } return 0; case SNDCTL_DSP_GETOSPACE: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; if (!(s->enable & CM_ENABLE_CH1) && (val = prog_dmabuf(s, 0)) != 0) return val; spin_lock_irqsave(&s->lock, flags); cm_update_ptr(s); abinfo.fragsize = s->dma_dac.fragsize; abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count; abinfo.fragstotal = s->dma_dac.numfrag; abinfo.fragments = abinfo.bytes >> s->dma_dac.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->enable & CM_ENABLE_CH0) && (val = prog_dmabuf(s, 1)) != 0) return val; spin_lock_irqsave(&s->lock, flags); cm_update_ptr(s); abinfo.fragsize = s->dma_adc.fragsize; abinfo.bytes = s->dma_adc.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; spin_lock_irqsave(&s->lock, flags); cm_update_ptr(s); val = s->dma_dac.count; spin_unlock_irqrestore(&s->lock, flags); return put_user(val, (int *)arg); case SNDCTL_DSP_GETIPTR: if (!(file->f_mode & FMODE_READ)) return -EINVAL; spin_lock_irqsave(&s->lock, flags); cm_update_ptr(s); cinfo.bytes = s->dma_adc.total_bytes; cinfo.blocks = s->dma_adc.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; spin_lock_irqsave(&s->lock, flags); cm_update_ptr(s); cinfo.bytes = s->dma_dac.total_bytes; cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift; cinfo.ptr = s->dma_dac.hwptr; if (s->dma_dac.mapped) s->dma_dac.count &= s->dma_dac.fragsize-1; if (s->status & DO_DUAL_DAC) { 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_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) { if ((val = prog_dmabuf(s, 0))) return val; if (s->status & DO_DUAL_DAC) { if ((val = prog_dmabuf(s, 1))) return val; return put_user(2 * s->dma_dac.fragsize, (int *)arg); } return put_user(s->dma_dac.fragsize, (int *)arg); } if ((val = prog_dmabuf(s, 1))) 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_dac.ossfragshift = val & 0xffff; s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff; if (s->dma_dac.ossfragshift < 4) s->dma_dac.ossfragshift = 4; if (s->dma_dac.ossfragshift > 15) s->dma_dac.ossfragshift = 15; if (s->dma_dac.ossmaxfrags < 4) s->dma_dac.ossmaxfrags = 4; if (s->status & DO_DUAL_DAC) { s->dma_adc.ossfragshift = s->dma_dac.ossfragshift; s->dma_adc.ossmaxfrags = s->dma_dac.ossmaxfrags; } } return 0; case SNDCTL_DSP_SUBDIVIDE: if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || (file->f_mode & FMODE_WRITE && s->dma_dac.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_dac.subdivision = val; if (s->status & DO_DUAL_DAC) s->dma_adc.subdivision = val; } return 0; case SOUND_PCM_READ_RATE: return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg); case SOUND_PCM_READ_CHANNELS: return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_STEREO << CM_CFMT_ADCSHIFT) : (CM_CFMT_STEREO << CM_CFMT_DACSHIFT))) ? 2 : 1, (int *)arg); case SOUND_PCM_READ_BITS: return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_16BIT << CM_CFMT_ADCSHIFT) : (CM_CFMT_16BIT << CM_CFMT_DACSHIFT))) ? 16 : 8, (int *)arg); case SOUND_PCM_READ_FILTER: return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg); case SNDCTL_DSP_GETCHANNELMASK: return put_user(DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE|DSP_BIND_SPDIF, (int *)arg); case SNDCTL_DSP_BIND_CHANNEL: if (get_user(val, (int *)arg)) return -EFAULT; if (val == DSP_BIND_QUERY) { val = DSP_BIND_FRONT; if (s->status & DO_SPDIF_OUT) val |= DSP_BIND_SPDIF; else { if (s->curr_channels == 4) val |= DSP_BIND_SURR; if (s->curr_channels > 4) val |= DSP_BIND_CENTER_LFE; } } else { if (file->f_mode & FMODE_READ) { stop_adc(s); s->dma_adc.ready = 0; } if (file->f_mode & FMODE_WRITE) { stop_dac(s); s->dma_dac.ready = 0; if (val & DSP_BIND_SPDIF) { set_spdifout(s, s->ratedac); set_dac_channels(s, s->fmt & (CM_CFMT_STEREO << CM_CFMT_DACSHIFT) ? 2 : 1); if (!(s->status & DO_SPDIF_OUT)) val &= ~DSP_BIND_SPDIF; } else { int channels; int mask; mask = val & (DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE); switch (mask) { case DSP_BIND_FRONT: channels = 2; break; case DSP_BIND_FRONT|DSP_BIND_SURR: channels = 4; break; case DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE: channels = 6; break; default: channels = s->fmt & (CM_CFMT_STEREO << CM_CFMT_DACSHIFT) ? 2 : 1; break; } set_dac_channels(s, channels); } } } return put_user(val, (int *)arg); case SOUND_PCM_WRITE_FILTER: case SNDCTL_DSP_MAPINBUF: case SNDCTL_DSP_MAPOUTBUF: case SNDCTL_DSP_SETSYNCRO: return -EINVAL; } return mixer_ioctl(s, cmd, arg);}static int cm_open(struct inode *inode, struct file *file){ int minor = MINOR(inode->i_rdev); struct cm_state *s = devs; unsigned char fmtm = ~0, fmts = 0; while (s && ((s->dev_audio ^ minor) & ~0xf)) s = s->next; if (!s) return -ENODEV; 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; } up(&s->open_sem); interruptible_sleep_on(&s->open_wait); if (signal_pending(current)) return -ERESTARTSYS; down(&s->open_sem); } if (file->f_mode & FMODE_READ) { fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_ADCSHIFT); if ((minor & 0xf) == SND_DEV_DSP16) fmts |= CM_CFMT_16BIT << CM_CFMT_ADCSHIFT; s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0; set_adc_rate(s, 8000); } if (file->f_mode & FMODE_WRITE) { fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_DACSHIFT); if ((minor & 0xf) == SND_DEV_DSP16) fmts |= CM_CFMT_16BIT << CM_CFMT_DACSHIFT; s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0; set_dac_rate(s, 8000); // clear previous multichannel, spdif, ac3 state se
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -