📄 au88x0_core.c
字号:
break; } } while (temp & FIFO_RDONLY); if (valid) { if ((temp & FIFO_VALID) == 0) { vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); // this_4#ifdef CHIP_AU8820 temp = (this_4 & 0x1f) << 0xb;#else temp = (this_4 & 0x3f) << 0xc;#endif temp = (temp & 0xfffffffd) | ((ctrl & 1) << 1); temp = (temp & 0xfffffff3) | ((priority & 3) << 2); temp = (temp & 0xffffffef) | ((valid & 1) << 4); temp |= FIFO_U1; temp = (temp & 0xffffffdf) | ((empty & 1) << 5);#ifdef CHIP_AU8820 temp = (temp & 0xfffbffff) | ((f & 1) << 0x12);#endif#ifdef CHIP_AU8830 temp = (temp & 0xf7ffffff) | ((f & 1) << 0x1b); temp = (temp & 0xefffffff) | ((f & 1) << 0x1c);#endif#ifdef CHIP_AU8810 temp = (temp & 0xfeffffff) | ((f & 1) << 0x18); temp = (temp & 0xfdffffff) | ((f & 1) << 0x19);#endif } } else { if (temp & FIFO_VALID) {#ifdef CHIP_AU8820 temp = ((f & 1) << 0x12) | (temp & 0xfffbffef);#endif#ifdef CHIP_AU8830 temp = ((f & 1) << 0x1b) | (temp & 0xe7ffffef) | FIFO_BITS;#endif#ifdef CHIP_AU8810 temp = ((f & 1) << 0x18) | (temp & 0xfcffffef) | FIFO_BITS;#endif } else /*if (this_8[fifo]) */ vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); } hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2));/* do { temp = hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)); if (lifeboat++ > 0xbb8) { printk(KERN_ERR "Vortex: vortex_fifo_setwtctrl fail (hanging)\n"); break; } } while ((temp & FIFO_RDONLY)&&(temp & FIFO_VALID)&&(temp != 0xFFFFFFFF)); if (valid) { if (temp & FIFO_VALID) { temp = 0x40000; //temp |= 0x08000000; //temp |= 0x10000000; //temp |= 0x04000000; //temp |= 0x00400000; temp |= 0x1c400000; temp &= 0xFFFFFFF3; temp &= 0xFFFFFFEF; temp |= (valid & 1) << 4; hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); return; } else { vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); return; } } else { temp &= 0xffffffef; temp |= 0x08000000; temp |= 0x10000000; temp |= 0x04000000; temp |= 0x00400000; hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); temp = hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)); //((temp >> 6) & 0x3f) priority = 0; if (((temp & 0x0fc0) ^ ((temp >> 6) & 0x0fc0)) & 0FFFFFFC0) vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); valid = 0xfb; temp = (temp & 0xfffffffd) | ((ctrl & 1) << 1); temp = (temp & 0xfffdffff) | ((f & 1) << 0x11); temp = (temp & 0xfffffff3) | ((priority & 3) << 2); temp = (temp & 0xffffffef) | ((valid & 1) << 4); temp = (temp & 0xffffffdf) | ((empty & 1) << 5); hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); } */ /* temp = (temp & 0xfffffffd) | ((ctrl & 1) << 1); temp = (temp & 0xfffdffff) | ((f & 1) << 0x11); temp = (temp & 0xfffffff3) | ((priority & 3) << 2); temp = (temp & 0xffffffef) | ((valid & 1) << 4); temp = (temp & 0xffffffdf) | ((empty & 1) << 5); #ifdef FIFO_BITS temp = temp | FIFO_BITS | 40000; #endif // 0x1c440010, 0x1c400000 hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); */}#endifstatic void vortex_fifo_init(vortex_t * vortex){ int x; unsigned long addr; /* ADB DMA channels fifos. */ addr = VORTEX_FIFO_ADBCTRL + ((NR_ADB - 1) * 4); for (x = NR_ADB - 1; x >= 0; x--) { hwwrite(vortex->mmio, addr, (FIFO_U0 | FIFO_U1)); if (hwread(vortex->mmio, addr) != (FIFO_U0 | FIFO_U1)) printk(KERN_ERR "bad adb fifo reset!"); vortex_fifo_clearadbdata(vortex, x, FIFO_SIZE); addr -= 4; }#ifndef CHIP_AU8810 /* WT DMA channels fifos. */ addr = VORTEX_FIFO_WTCTRL + ((NR_WT - 1) * 4); for (x = NR_WT - 1; x >= 0; x--) { hwwrite(vortex->mmio, addr, FIFO_U0); if (hwread(vortex->mmio, addr) != FIFO_U0) printk(KERN_ERR "bad wt fifo reset (0x%08lx, 0x%08x)!\n", addr, hwread(vortex->mmio, addr)); vortex_fifo_clearwtdata(vortex, x, FIFO_SIZE); addr -= 4; }#endif /* trigger... */#ifdef CHIP_AU8820 hwwrite(vortex->mmio, 0xf8c0, 0xd03); //0x0843 0xd6b#else#ifdef CHIP_AU8830 hwwrite(vortex->mmio, 0x17000, 0x61); /* wt a */ hwwrite(vortex->mmio, 0x17004, 0x61); /* wt b */#endif hwwrite(vortex->mmio, 0x17008, 0x61); /* adb */#endif}/* ADBDMA */static void vortex_adbdma_init(vortex_t * vortex){}static void vortex_adbdma_setfirstbuffer(vortex_t * vortex, int adbdma){ stream_t *dma = &vortex->dma_adb[adbdma]; hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), dma->dma_ctrl);}static void vortex_adbdma_setstartbuffer(vortex_t * vortex, int adbdma, int sb){ stream_t *dma = &vortex->dma_adb[adbdma]; //hwwrite(vortex->mmio, VORTEX_ADBDMA_START + (adbdma << 2), sb << (((NR_ADB-1)-((adbdma&0xf)*2)))); hwwrite(vortex->mmio, VORTEX_ADBDMA_START + (adbdma << 2), sb << ((0xf - (adbdma & 0xf)) * 2)); dma->period_real = dma->period_virt = sb;}static voidvortex_adbdma_setbuffers(vortex_t * vortex, int adbdma, snd_pcm_sgbuf_t * sgbuf, int psize, int count){ stream_t *dma = &vortex->dma_adb[adbdma]; if (sgbuf == NULL) { printk(KERN_INFO "vortex: FATAL: sgbuf is NULL!\n"); return; } //printk(KERN_INFO "vortex: page count = %d, tblcount = %d\n", count, sgbuf->tblsize); dma->period_bytes = psize; dma->nr_periods = count; dma->sgbuf = sgbuf; dma->cfg0 = 0; dma->cfg1 = 0; switch (count) { /* Four or more pages */ default: case 4: dma->cfg1 |= 0x88000000 | 0x44000000 | 0x30000000 | (psize - 1); hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0xc, snd_sgbuf_get_addr(sgbuf, psize * 3)); /* 3 pages */ case 3: dma->cfg0 |= 0x12000000; dma->cfg1 |= 0x80000000 | 0x40000000 | ((psize - 1) << 0xc); hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0x8, snd_sgbuf_get_addr(sgbuf, psize * 2)); /* 2 pages */ case 2: dma->cfg0 |= 0x88000000 | 0x44000000 | 0x10000000 | (psize - 1); hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0x4, snd_sgbuf_get_addr(sgbuf, psize)); /* 1 page */ case 1: dma->cfg0 |= 0x80000000 | 0x40000000 | ((psize - 1) << 0xc); hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (adbdma << 4), snd_sgbuf_get_addr(sgbuf, 0)); break; } //printk("vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n", dma->cfg0, dma->cfg1); hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG0 + (adbdma << 3), dma->cfg0); hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG1 + (adbdma << 3), dma->cfg1); vortex_adbdma_setfirstbuffer(vortex, adbdma); vortex_adbdma_setstartbuffer(vortex, adbdma, 0);}static voidvortex_adbdma_setmode(vortex_t * vortex, int adbdma, int ie, int dir, int fmt, int d, unsigned long offset){ stream_t *dma = &vortex->dma_adb[adbdma]; dma->dma_unknown = d; dma->dma_ctrl = ((offset & OFFSET_MASK) | (dma->dma_ctrl & ~OFFSET_MASK)); /* Enable PCMOUT interrupts. */ dma->dma_ctrl = (dma->dma_ctrl & ~IE_MASK) | ((ie << IE_SHIFT) & IE_MASK); dma->dma_ctrl = (dma->dma_ctrl & ~DIR_MASK) | ((dir << DIR_SHIFT) & DIR_MASK); dma->dma_ctrl = (dma->dma_ctrl & ~FMT_MASK) | ((fmt << FMT_SHIFT) & FMT_MASK); hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), dma->dma_ctrl); hwread(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2));}static int vortex_adbdma_bufshift(vortex_t * vortex, int adbdma){ stream_t *dma = &vortex->dma_adb[adbdma]; int page, p, pp, delta, i; page = (hwread(vortex->mmio, VORTEX_ADBDMA_STAT + (adbdma << 2)) & ADB_SUBBUF_MASK) >> ADB_SUBBUF_SHIFT; if (dma->nr_periods >= 4) delta = (page - dma->period_real) & 3; else { delta = (page - dma->period_real); if (delta < 0) delta += dma->nr_periods; } if (delta == 0) return 0; /* refresh hw page table */ if (dma->nr_periods > 4) { for (i = 0; i < delta; i++) { /* p: audio buffer page index */ p = dma->period_virt + i + 4; if (p >= dma->nr_periods) p -= dma->nr_periods; /* pp: hardware DMA page index. */ pp = dma->period_real + i; if (pp >= 4) pp -= 4; //hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE+(((adbdma << 2)+pp) << 2), dma->table[p].addr); hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (((adbdma << 2) + pp) << 2), snd_sgbuf_get_addr(dma->sgbuf, dma->period_bytes * p)); /* Force write thru cache. */ hwread(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (((adbdma << 2) + pp) << 2)); } } dma->period_virt += delta; dma->period_real = page; if (dma->period_virt >= dma->nr_periods) dma->period_virt -= dma->nr_periods; if (delta != 1) printk(KERN_INFO "vortex: %d virt=%d, real=%d, delta=%d\n", adbdma, dma->period_virt, dma->period_real, delta); return delta;}static void vortex_adbdma_resetup(vortex_t *vortex, int adbdma) { stream_t *dma = &vortex->dma_adb[adbdma]; int p, pp, i; /* refresh hw page table */ for (i=0 ; i < 4 && i < dma->nr_periods; i++) { /* p: audio buffer page index */ p = dma->period_virt + i; if (p >= dma->nr_periods) p -= dma->nr_periods; /* pp: hardware DMA page index. */ pp = dma->period_real + i; if (dma->nr_periods < 4) { if (pp >= dma->nr_periods) pp -= dma->nr_periods; } else { if (pp >= 4) pp -= 4; } hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE+(((adbdma << 2)+pp) << 2), snd_sgbuf_get_addr(dma->sgbuf, dma->period_bytes * p)); /* Force write thru cache. */ hwread(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (((adbdma << 2)+pp) << 2)); }}static int inline vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma){ stream_t *dma = &vortex->dma_adb[adbdma]; int temp; temp = hwread(vortex->mmio, VORTEX_ADBDMA_STAT + (adbdma << 2)); temp = (dma->period_virt * dma->period_bytes) + (temp & POS_MASK); return (temp);}static void vortex_adbdma_startfifo(vortex_t * vortex, int adbdma){ int this_8 = 0 /*empty */ , this_4 = 0 /*priority */ ; stream_t *dma = &vortex->dma_adb[adbdma]; switch (dma->fifo_status) { case FIFO_START: vortex_fifo_setadbvalid(vortex, adbdma, dma->fifo_enabled ? 1 : 0); break; case FIFO_STOP: this_8 = 1; hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), dma->dma_ctrl); vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, this_4, this_8, dma->fifo_enabled ? 1 : 0, 0); break; case FIFO_PAUSE: vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, this_4, this_8, dma->fifo_enabled ? 1 : 0, 0); break; } dma->fifo_status = FIFO_START;}static void vortex_adbdma_resumefifo(vortex_t * vortex, int adbdma){ stream_t *dma = &vortex->dma_adb[adbdma]; int this_8 = 1, this_4 = 0; switch (dma->fifo_status) { case FIFO_STOP: hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), dma->dma_ctrl); vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, this_4, this_8, dma->fifo_enabled ? 1 : 0, 0); break; case FIFO_PAUSE: vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, this_4, this_8, dma->fifo_enabled ? 1 : 0, 0); break; } dma->fifo_status = FIFO_START;}static void vortex_adbdma_pausefifo(vortex_t * vortex, int adbdma){ stream_t *dma = &vortex->dma_adb[adbdma]; int this_8 = 0, this_4 = 0; switch (dma->fifo_status) { case FIFO_START: vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, this_4, this_8, 0, 0); break; case FIFO_STOP: hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), dma->dma_ctrl); vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, this_4, this_8, 0, 0); break; } dma->fifo_status = FIFO_PAUSE;}#if 0 // Using pause insteadstatic void vortex_adbdma_stopfifo(vortex_t * vortex, int adbdma){ stream_t *dma = &vortex->dma_adb[adbdma]; int this_4 = 0, this_8 = 0; if (dma->fifo_status == FIFO_START) vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, this_4, this_8, 0, 0); else if (dma->fifo_status == FIFO_STOP) return; dma->fifo_status = FIFO_STOP; dma->fifo_enabled = 0;}#endif/* WTDMA */#ifndef CHIP_AU8810static void vortex_wtdma_setfirstbuffer(vortex_t * vortex, int wtdma){ //int this_7c=dma_ctrl; stream_t *dma = &vortex->dma_wt[wtdma]; hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), dma->dma_ctrl);}static void vortex_wtdma_setstartbuffer(vortex_t * vortex, int wtdma, int sb){ stream_t *dma = &vortex->dma_wt[wtdma]; //hwwrite(vortex->mmio, VORTEX_WTDMA_START + (wtdma << 2), sb << ((0x1f-(wtdma&0xf)*2))); hwwrite(vortex->mmio, VORTEX_WTDMA_START + (wtdma << 2), sb << ((0xf - (wtdma & 0xf)) * 2)); dma->period_real = dma->period_virt = sb;}static voidvortex_wtdma_setbuffers(vortex_t * vortex, int wtdma, snd_pcm_sgbuf_t * sgbuf, int psize, int count){ stream_t *dma = &vortex->dma_wt[wtdma]; dma->period_bytes = psize; dma->nr_periods = count; dma->sgbuf = sgbuf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -