⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 maestro3.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 5 页
字号:
                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->enable & ADC_RUNNING))            val |= PCM_ENABLE_INPUT;        if ((file->f_mode & FMODE_WRITE) && (s->enable & DAC_RUNNING))             val |= PCM_ENABLE_OUTPUT;        return put_user(val, (int *)arg);            case SNDCTL_DSP_SETTRIGGER:        get_user_ret(val, (int *)arg, -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;                start_dac(s);            } else                stop_dac(s);        }        return 0;    case SNDCTL_DSP_GETOSPACE:        if (!(file->f_mode & FMODE_WRITE))            return -EINVAL;        if (!(s->enable & DAC_RUNNING) && (val = prog_dmabuf(s, 0)) != 0)            return val;        spin_lock_irqsave(&s->lock, flags);        m3_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 & ADC_RUNNING) && (val = prog_dmabuf(s, 1)) != 0)            return val;        spin_lock_irqsave(&s->lock, flags);        m3_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);        m3_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);        m3_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);        m3_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;        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;            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:        get_user_ret(val, (int *)arg, -EFAULT);        spin_lock_irqsave(&s->lock, flags);        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;        }        spin_unlock_irqrestore(&s->lock, flags);        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;                get_user_ret(val, (int *)arg, -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;        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) ? (ESS_FMT_STEREO << ESS_ADC_SHIFT)                        : (ESS_FMT_STEREO << ESS_DAC_SHIFT))) ? 2 : 1, (int *)arg);    case SOUND_PCM_READ_BITS:        return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (ESS_FMT_16BIT << ESS_ADC_SHIFT)                        : (ESS_FMT_16BIT << ESS_DAC_SHIFT))) ? 16 : 8, (int *)arg);    case SOUND_PCM_WRITE_FILTER:    case SNDCTL_DSP_SETSYNCRO:    case SOUND_PCM_READ_FILTER:        return -EINVAL;            }    return -EINVAL;}static intallocate_dmabuf(struct pci_dev *pci_dev, struct dmabuf *db){    int order;    DPRINTK(DPSTR,"allocating for dmabuf %p\n", db);    /*      * alloc as big a chunk as we can, start with      * 64k 'cause we're insane.  based on order cause     * the amazingly complicated prog_dmabuf wants it.     *     * pci_alloc_sonsistent guarantees that it won't cross a natural     * boundry; the m3 hardware can't have dma cross a 64k bus     * address boundry.     */    for (order = 16-PAGE_SHIFT; order >= 1; order--) {        db->rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order,                        &(db->handle));        if(db->rawbuf)            break;    }    if (!db->rawbuf)        return 1;    DPRINTK(DPSTR,"allocated %ld (%d) bytes at %p\n",            PAGE_SIZE<<order, order, db->rawbuf);    {        struct page *page, *pend;        pend = virt_to_page(db->rawbuf + (PAGE_SIZE << order) - 1);        for (page = virt_to_page(db->rawbuf); page <= pend; page++)            mem_map_reserve(page);    }    db->buforder = order;    db->ready = 0;    db->mapped = 0;    return 0;}static voidnuke_lists(struct m3_card *card, struct dmabuf *db){    m3_remove_list(card, &(card->dma_list), db->dma_index);    m3_remove_list(card, &(card->msrc_list), db->msrc_index);    db->in_lists = 0;}static voidfree_dmabuf(struct pci_dev *pci_dev, struct dmabuf *db){    if(db->rawbuf == NULL)        return;    DPRINTK(DPSTR,"freeing %p from dmabuf %p\n",db->rawbuf, db);    {        struct page *page, *pend;        pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);        for (page = virt_to_page(db->rawbuf); page <= pend; page++)            mem_map_unreserve(page);    }    pci_free_consistent(pci_dev, PAGE_SIZE << db->buforder,            db->rawbuf, db->handle);    db->rawbuf = NULL;    db->buforder = 0;    db->mapped = 0;    db->ready = 0;}static int m3_open(struct inode *inode, struct file *file){    int minor = MINOR(inode->i_rdev);    struct m3_card *c;    struct m3_state *s = NULL;    int i;    unsigned char fmtm = ~0, fmts = 0;    unsigned long flags;    /*     *    Scan the cards and find the channel. We only     *    do this at open time so it is ok     */    for(c = devs ; c != NULL ; c = c->next) {        for(i=0;i<NR_DSPS;i++) {            if(c->channels[i].dev_audio < 0)                continue;            if((c->channels[i].dev_audio ^ minor) & ~0xf)                continue;            s = &c->channels[i];            break;        }    }            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 -EWOULDBLOCK;        }        up(&s->open_sem);        interruptible_sleep_on(&s->open_wait);        if (signal_pending(current))            return -ERESTARTSYS;        down(&s->open_sem);    }        spin_lock_irqsave(&s->lock, flags);    if (file->f_mode & FMODE_READ) {        fmtm &= ~((ESS_FMT_STEREO | ESS_FMT_16BIT) << ESS_ADC_SHIFT);        if ((minor & 0xf) == SND_DEV_DSP16)            fmts |= ESS_FMT_16BIT << ESS_ADC_SHIFT;         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 &= ~((ESS_FMT_STEREO | ESS_FMT_16BIT) << ESS_DAC_SHIFT);        if ((minor & 0xf) == SND_DEV_DSP16)            fmts |= ESS_FMT_16BIT << ESS_DAC_SHIFT;        s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0;        set_dac_rate(s, 8000);    }    set_fmt(s, fmtm, fmts);    s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);    MOD_INC_USE_COUNT;    up(&s->open_sem);    spin_unlock_irqrestore(&s->lock, flags);    return 0;}static int m3_release(struct inode *inode, struct file *file){    struct m3_state *s = (struct m3_state *)file->private_data;    unsigned long flags;    VALIDATE_STATE(s);    if (file->f_mode & FMODE_WRITE)        drain_dac(s, file->f_flags & O_NONBLOCK);    down(&s->open_sem);    spin_lock_irqsave(&s->lock, flags);    if (file->f_mode & FMODE_WRITE) {        stop_dac(s);        if(s->dma_dac.in_lists) {            m3_remove_list(s->card, &(s->card->mixer_list), s->dma_dac.mixer_index);            nuke_lists(s->card, &(s->dma_dac));        }    }    if (file->f_mode & FMODE_READ) {        stop_adc(s);        if(s->dma_adc.in_lists) {            m3_remove_list(s->card, &(s->card->adc1_list), s->dma_adc.adc1_index);            nuke_lists(s->card, &(s->dma_adc));        }    }            s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);    spin_unlock_irqrestore(&s->lock, flags);    up(&s->open_sem);    wake_up(&s->open_wait);    MOD_DEC_USE_COUNT;    return 0;}/* * Wait for the ac97 serial bus to be free. * return nonzero if the bus is still busy. */static int m3_ac97_wait(struct m3_card *card){    int i = 10000;    while( (m3_inb(card, 0x30) & 1) && i--) ;    return i == 0;}u16 m3_ac97_read(struct ac97_codec *codec, u8 reg){    u16 ret = 0;    struct m3_card *card = codec->private_data;    spin_lock(&card->ac97_lock);    if(m3_ac97_wait(card)) {        printk(KERN_ERR PFX "serial bus busy reading reg 0x%x\n",reg);        goto out;    }    m3_outb(card, 0x80 | (reg & 0x7f), 0x30);    if(m3_ac97_wait(card)) {        printk(KERN_ERR PFX "serial bus busy finishing read reg 0x%x\n",reg);        goto out;    }    ret =  m3_inw(card, 0x32);    DPRINTK(DPCRAP,"reading 0x%04x from 0x%02x\n",ret, reg);out:    spin_unlock(&card->ac97_lock);    return ret;}void m3_ac97_write(struct ac97_codec *codec, u8 reg, u16 val){    struct m3_card *card = codec->private_data;    spin_lock(&card->ac97_lock);    if(m3_ac97_wait(card)) {        printk(KERN_ERR PFX "serial bus busy writing 0x%x to 0x%x\n",val, reg);        goto out;    }    DPRINTK(DPCRAP,"writing 0x%04x  to  0x%02x\n", val, reg);    m3_outw(card, val, 0x32);    m3_outb(card, reg & 0x7f, 0x30);out:    spin_unlock(&card->ac97_lock);}/* OSS /dev/mixer file operation methods */static int m3_open_mixdev(struct inode *inode, struct file *file){    int minor = MINOR(inode->i_rdev);    struct m3_card *card = devs;    MOD_INC_USE_COUNT;    for (card = devs; card != NULL; card = card->next

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -