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

📄 maestro3.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 5 页
字号:
static struct rec_vals {    u16 addr, val;} rv[] = {    {CDATA_LEFT_VOLUME, ARB_VOLUME},    {CDATA_RIGHT_VOLUME, ARB_VOLUME},    {SRC3_DIRECTION_OFFSET, 1} ,    /* +1, +2 are stereo/16 bit */    {SRC3_DIRECTION_OFFSET + 3, 0x0000}, /* fraction? */    {SRC3_DIRECTION_OFFSET + 4, 0}, /* first l */    {SRC3_DIRECTION_OFFSET + 5, 0}, /* first r */    {SRC3_DIRECTION_OFFSET + 6, 0}, /* second l */    {SRC3_DIRECTION_OFFSET + 7, 0}, /* second r */    {SRC3_DIRECTION_OFFSET + 8, 0}, /* delta l */    {SRC3_DIRECTION_OFFSET + 9, 0}, /* delta r */    {SRC3_DIRECTION_OFFSET + 10, 0x8000}, /* round */    {SRC3_DIRECTION_OFFSET + 11, 0xFF00}, /* higher bute mark */    {SRC3_DIRECTION_OFFSET + 13, 0}, /* temp0 */    {SRC3_DIRECTION_OFFSET + 14, 0}, /* c fraction */    {SRC3_DIRECTION_OFFSET + 15, 0}, /* counter */    {SRC3_DIRECTION_OFFSET + 16, 50},/* numin */    {SRC3_DIRECTION_OFFSET + 17, 8}, /* numout */    {SRC3_DIRECTION_OFFSET + 18, 0}, /* numstage */    {SRC3_DIRECTION_OFFSET + 19, 0}, /* coef */    {SRC3_DIRECTION_OFFSET + 20, 0}, /* filtertap */    {SRC3_DIRECTION_OFFSET + 21, 0}, /* booster */    {SRC3_DIRECTION_OFFSET + 22, 0xff} /* skip lpf */};/* again, passed mode is alrady shifted/masked */static void m3_rec_setup(struct m3_state *s, int mode, u32 rate, void *buffer, int size){    int dsp_in_size = MINISRC_IN_BUFFER_SIZE + (0x10 * 2);    int dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x10 * 2);    int dsp_in_buffer = s->adc_inst.data + (MINISRC_TMP_BUFFER_SIZE / 2);    int dsp_out_buffer = dsp_in_buffer + (dsp_in_size / 2) + 1;    struct dmabuf *db = &s->dma_adc;    int i;    DPRINTK(DPSTR, "rec_setup mode=%d rate=%d buf=%p len=%d.\n",        mode, rate, buffer, size);#define LO(x) ((x) & 0xffff)#define HI(x) LO((x) >> 16)    /* host dma buffer pointers */    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_HOST_SRC_ADDRL,        LO(virt_to_bus(buffer)));    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_HOST_SRC_ADDRH,        HI(virt_to_bus(buffer)));    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_HOST_SRC_END_PLUS_1L,        LO(virt_to_bus(buffer) + size));    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_HOST_SRC_END_PLUS_1H,        HI(virt_to_bus(buffer) + size));    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_HOST_SRC_CURRENTL,        LO(virt_to_bus(buffer)));    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_HOST_SRC_CURRENTH,        HI(virt_to_bus(buffer)));#undef LO#undef HI    /* dsp buffers */    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_IN_BUF_BEGIN,        dsp_in_buffer);    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_IN_BUF_END_PLUS_1,        dsp_in_buffer + (dsp_in_size / 2));    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_IN_BUF_HEAD,        dsp_in_buffer);        m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_IN_BUF_TAIL,        dsp_in_buffer);    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_OUT_BUF_BEGIN,        dsp_out_buffer);    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_OUT_BUF_END_PLUS_1,        dsp_out_buffer + (dsp_out_size / 2));    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_OUT_BUF_HEAD,        dsp_out_buffer);    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_OUT_BUF_TAIL,        dsp_out_buffer);    /*     * some per client initializers     */    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + SRC3_DIRECTION_OFFSET + 12,        s->adc_inst.data + 40 + 8);    /* tell it which way dma is going? */    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,        s->adc_inst.data + CDATA_DMA_CONTROL,        DMACONTROL_DIRECTION + DMACONTROL_AUTOREPEAT +         DMAC_PAGE3_SELECTOR + DMAC_BLOCKF_SELECTOR);    /*     * set an armload of static initializers     */    for(i = 0 ; i < (sizeof(rv) / sizeof(rv[0])) ; i++)         m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,            s->adc_inst.data + rv[i].addr, rv[i].val);    /*      * put us in the lists if we're not already there     */    if(db->in_lists == 0) {        db->adc1_index = m3_add_list(s->card, &s->card->adc1_list,                 s->adc_inst.data >> DP_SHIFT_COUNT);        db->dma_index = m3_add_list(s->card, &s->card->dma_list,                 s->adc_inst.data >> DP_SHIFT_COUNT);        db->msrc_index = m3_add_list(s->card, &s->card->msrc_list,                 s->adc_inst.data >> DP_SHIFT_COUNT);        db->in_lists = 1;    }    set_adc_rate(s,rate);    start_adc(s);}/* --------------------------------------------------------------------- */static void set_dmaa(struct m3_state *s, unsigned int addr, unsigned int count){    DPRINTK(DPINT,"set_dmaa??\n");}static void set_dmac(struct m3_state *s, unsigned int addr, unsigned int count){    DPRINTK(DPINT,"set_dmac??\n");}u32 get_dma_pos(struct m3_card *card,        int instance_addr){    u16 hi = 0, lo = 0;    int retry = 10;    /*     * try and get a valid answer     */    while(retry--) {        hi =  m3_assp_read(card, MEMTYPE_INTERNAL_DATA,                instance_addr + CDATA_HOST_SRC_CURRENTH);        lo = m3_assp_read(card, MEMTYPE_INTERNAL_DATA,                instance_addr + CDATA_HOST_SRC_CURRENTL);        if(hi == m3_assp_read(card, MEMTYPE_INTERNAL_DATA,                instance_addr + CDATA_HOST_SRC_CURRENTH))            break;    }    return lo | (hi<<16);}u32 get_dmaa(struct m3_state *s){    u32 offset;    offset = get_dma_pos(s->card, s->dac_inst.data) -         virt_to_bus(s->dma_dac.rawbuf);    DPRINTK(DPINT,"get_dmaa: 0x%08x\n",offset);    return offset;}u32 get_dmac(struct m3_state *s){    u32 offset;    offset = get_dma_pos(s->card, s->adc_inst.data) -        virt_to_bus(s->dma_adc.rawbuf);    DPRINTK(DPINT,"get_dmac: 0x%08x\n",offset);    return offset;}static void m3_interrupt(int irq, void *dev_id, struct pt_regs *regs);static int prog_dmabuf(struct m3_state *s, unsigned rec){    struct dmabuf *db = rec ? &s->dma_adc : &s->dma_dac;    unsigned rate = rec ? s->rateadc : s->ratedac;    unsigned bytepersec;    unsigned bufs;    unsigned char fmt;    unsigned long flags;    spin_lock_irqsave(&s->lock, flags);    fmt = s->fmt;    if (rec) {        stop_adc(s);        fmt >>= ESS_ADC_SHIFT;    } else {        stop_dac(s);        fmt >>= ESS_DAC_SHIFT;    }    fmt &= ESS_FMT_MASK;    db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;    bytepersec = rate << sample_shift[fmt];    bufs = PAGE_SIZE << db->buforder;    if (db->ossfragshift) {        if ((1000 << db->ossfragshift) < bytepersec)            db->fragshift = ld2(bytepersec/1000);        else            db->fragshift = db->ossfragshift;    } else {        db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1));        if (db->fragshift < 3)            db->fragshift = 3;     }    db->numfrag = bufs >> db->fragshift;    while (db->numfrag < 4 && db->fragshift > 3) {        db->fragshift--;        db->numfrag = bufs >> db->fragshift;    }    db->fragsize = 1 << db->fragshift;    if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag)        db->numfrag = db->ossmaxfrags;    db->fragsamples = db->fragsize >> sample_shift[fmt];    db->dmasize = db->numfrag << db->fragshift;    DPRINTK(DPSTR,"prog_dmabuf: numfrag: %d fragsize: %d dmasize: %d\n",db->numfrag,db->fragsize,db->dmasize);    memset(db->rawbuf, (fmt & ESS_FMT_16BIT) ? 0 : 0x80, db->dmasize);    if (rec)         m3_rec_setup(s, fmt, s->rateadc, db->rawbuf, db->dmasize);    else         m3_play_setup(s, fmt, s->ratedac, db->rawbuf, db->dmasize);    db->ready = 1;    spin_unlock_irqrestore(&s->lock, flags);    return 0;}static void clear_advance(struct m3_state *s){    unsigned char c = ((s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_16BIT) ? 0 : 0x80;        unsigned char *buf = s->dma_dac.rawbuf;    unsigned bsize = s->dma_dac.dmasize;    unsigned bptr = s->dma_dac.swptr;    unsigned len = s->dma_dac.fragsize;        if (bptr + len > bsize) {        unsigned x = bsize - bptr;        memset(buf + bptr, c, x);        /* account for wrapping? */        bptr = 0;        len -= x;    }    memset(buf + bptr, c, len);}/* call with spinlock held! */static void m3_update_ptr(struct m3_state *s){    unsigned hwptr;    int diff;    /* update ADC pointer */    if (s->dma_adc.ready) {        hwptr = get_dmac(s) % s->dma_adc.dmasize;        diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize;        s->dma_adc.hwptr = hwptr;        s->dma_adc.total_bytes += diff;        s->dma_adc.count += diff;        if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)             wake_up(&s->dma_adc.wait);        if (!s->dma_adc.mapped) {            if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {                stop_adc(s);                 /* brute force everyone back in sync, sigh */                s->dma_adc.count = 0;                s->dma_adc.swptr = 0;                s->dma_adc.hwptr = 0;                s->dma_adc.error++;            }        }    }    /* update DAC pointer */    if (s->dma_dac.ready) {        hwptr = get_dmaa(s) % s->dma_dac.dmasize;         diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize;        DPRINTK(DPINT,"updating dac: hwptr: %6d diff: %6d count: %6d\n",                hwptr,diff,s->dma_dac.count);        s->dma_dac.hwptr = hwptr;        s->dma_dac.total_bytes += diff;        if (s->dma_dac.mapped) {                        s->dma_dac.count += diff;            if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) {                wake_up(&s->dma_dac.wait);            }        } else {            s->dma_dac.count -= diff;                        if (s->dma_dac.count <= 0) {                DPRINTK(DPCRAP,"underflow! diff: %d (0x%x) count: %d (0x%x) hw: %d (0x%x) sw: %d (0x%x)\n",                         diff, diff,                         s->dma_dac.count,                         s->dma_dac.count,                     hwptr, hwptr,                    s->dma_dac.swptr,                    s->dma_dac.swptr);                stop_dac(s);                /* brute force everyone back in sync, sigh */                s->dma_dac.count = 0;                 s->dma_dac.swptr = hwptr;                 s->dma_dac.error++;            } else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize && !s->dma_dac.endcleared) {                clear_advance(s);                s->dma_dac.endcleared = 1;            }            if (s->dma_dac.count + (signed)s->dma_dac.fragsize <= (signed)s->dma_dac.dmasize) {                wake_up(&s->dma_dac.wait);                DPRINTK(DPINT,"waking up DAC count: %d sw: %d hw: %d\n",                        s->dma_dac.count, s->dma_dac.swptr, hwptr);            }        }    }}static void m3_interrupt(int irq, void *dev_id, struct pt_regs *regs){    struct m3_card *c = (struct m3_card *)dev_id;    struct m3_state *s = &c->channels[0];    u8 status;    status = inb(c->iobase+0x1A);    if(status == 0xff) return;       /* presumably acking the ints? */    outw(status, c->iobase+0x1A);     if(c->in_suspend)        return;    /*     * ack an assp int if its running     * and has an int pending     */    if( status & ASSP_INT_PENDING) {        u8 ctl = inb(c->iobase + ASSP_CONTROL_B);        if( !(ctl & STOP_ASSP_CLOCK)) {            ctl = inb(c->iobase + ASSP_HOST_INT_STATUS );            if(ctl & DSP2HOST_REQ_TIMER) {                outb( DSP2HOST_REQ_TIMER, c->iobase + ASSP_HOST_INT_STATUS);                /* update adc/dac info if it was a timer int */                spin_lock(&s->lock);                m3_update_ptr(s);                spin_unlock(&s->lock);            }        }    }    /* XXX is this needed? */    if(status & 0x40)         outb(0x40, c->iobase+0x1A);}/* --------------------------------------------------------------------- */static const char invalid_magic[] = KERN_CRIT PFX "invalid magic value in %s\n";#define VALIDATE_MAGIC(FOO,MAG)                         \({                                                \    if (!(FOO) || (FOO)->magic != MAG) { \        printk(invalid_magic,__FUNCTION__);            \        return -ENXIO;                    \    }                                         \})#define VALIDATE_STATE(a) VALIDATE_MAGIC(a,M3_STATE_MAGIC)#define VALIDATE_CARD(a) VALIDATE_MAGIC(a,M3_CARD_MAGIC)/* --------------------------------------------------------------------- */static int drain_dac(struct m3_state *s, int nonblock){    DECLARE_WAITQUEUE(wait,current);    unsigned long flags;    int count;    signed long tmo;    if (s->dma_dac.mapped || !s->dma_dac.ready)

⌨️ 快捷键说明

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