📄 au88x0_core.c
字号:
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_WTDMA_BUFBASE + (wtdma << 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_WTDMA_BUFBASE + (wtdma << 4) + 0x8, snd_sgbuf_get_addr(sgbuf, psize * 2)); /* 2 pages */ case 2: dma->cfg0 |= 0x88000000 | 0x44000000 | 0x10000000 | (psize-1); hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0x4, snd_sgbuf_get_addr(sgbuf, psize)); /* 1 page */ case 1: dma->cfg0 |= 0x80000000 | 0x40000000 | ((psize-1) << 0xc); hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4), snd_sgbuf_get_addr(sgbuf, 0)); break; } hwwrite(vortex->mmio, VORTEX_WTDMA_BUFCFG0 + (wtdma << 3), dma->cfg0); hwwrite(vortex->mmio, VORTEX_WTDMA_BUFCFG1 + (wtdma << 3), dma->cfg1); vortex_wtdma_setfirstbuffer(vortex, wtdma); vortex_wtdma_setstartbuffer(vortex, wtdma, 0);}static voidvortex_wtdma_setmode(vortex_t * vortex, int wtdma, int ie, int fmt, int d, /*int e, */ unsigned long offset){ stream_t *dma = &vortex->dma_wt[wtdma]; //dma->this_08 = e; dma->dma_unknown = d; dma->dma_ctrl = 0; dma->dma_ctrl = ((offset & OFFSET_MASK) | (dma->dma_ctrl & ~OFFSET_MASK)); /* PCMOUT interrupt */ dma->dma_ctrl = (dma->dma_ctrl & ~IE_MASK) | ((ie << IE_SHIFT) & IE_MASK); /* Always playback. */ dma->dma_ctrl |= (1 << DIR_SHIFT); /* Audio Format */ dma->dma_ctrl = (dma->dma_ctrl & FMT_MASK) | ((fmt << FMT_SHIFT) & FMT_MASK); /* Write into hardware */ hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), dma->dma_ctrl);}static int vortex_wtdma_bufshift(vortex_t * vortex, int wtdma){ stream_t *dma = &vortex->dma_wt[wtdma]; int page, p, pp, delta, i; page = (hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)) & WT_SUBBUF_MASK) >> WT_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_WTDMA_BUFBASE + (((wtdma << 2) + pp) << 2), snd_sgbuf_get_addr(dma->sgbuf, dma->period_bytes * p)); /* Force write thru cache. */ hwread(vortex->mmio, VORTEX_WTDMA_BUFBASE + (((wtdma << 2) + pp) << 2)); } } dma->period_virt += delta; if (dma->period_virt >= dma->nr_periods) dma->period_virt -= dma->nr_periods; dma->period_real = page; if (delta != 1) printk(KERN_WARNING "vortex: wt virt = %d, delta = %d\n", dma->period_virt, delta); return delta;}#if 0static voidvortex_wtdma_getposition(vortex_t * vortex, int wtdma, int *subbuf, int *pos){ int temp; temp = hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)); *subbuf = (temp >> WT_SUBBUF_SHIFT) & WT_SUBBUF_MASK; *pos = temp & POS_MASK;}static int vortex_wtdma_getcursubuffer(vortex_t * vortex, int wtdma){ return ((hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)) >> POS_SHIFT) & POS_MASK);}#endifstatic int inline vortex_wtdma_getlinearpos(vortex_t * vortex, int wtdma){ stream_t *dma = &vortex->dma_wt[wtdma]; int temp; temp = hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)); //temp = (temp & POS_MASK) + (((temp>>WT_SUBBUF_SHIFT) & WT_SUBBUF_MASK)*(dma->cfg0&POS_MASK)); temp = (temp & POS_MASK) + ((dma->period_virt) * (dma->period_bytes)); return temp;}static void vortex_wtdma_startfifo(vortex_t * vortex, int wtdma){ stream_t *dma = &vortex->dma_wt[wtdma]; int this_8 = 0, this_4 = 0; switch (dma->fifo_status) { case FIFO_START: vortex_fifo_setwtvalid(vortex, wtdma, dma->fifo_enabled ? 1 : 0); break; case FIFO_STOP: this_8 = 1; hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), dma->dma_ctrl); vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, this_4, this_8, dma->fifo_enabled ? 1 : 0, 0); break; case FIFO_PAUSE: vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, this_4, this_8, dma->fifo_enabled ? 1 : 0, 0); break; } dma->fifo_status = FIFO_START;}static void vortex_wtdma_resumefifo(vortex_t * vortex, int wtdma){ stream_t *dma = &vortex->dma_wt[wtdma]; int this_8 = 0, this_4 = 0; switch (dma->fifo_status) { case FIFO_STOP: hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), dma->dma_ctrl); vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, this_4, this_8, dma->fifo_enabled ? 1 : 0, 0); break; case FIFO_PAUSE: vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, this_4, this_8, dma->fifo_enabled ? 1 : 0, 0); break; } dma->fifo_status = FIFO_START;}static void vortex_wtdma_pausefifo(vortex_t * vortex, int wtdma){ stream_t *dma = &vortex->dma_wt[wtdma]; int this_8 = 0, this_4 = 0; switch (dma->fifo_status) { case FIFO_START: vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, this_4, this_8, 0, 0); break; case FIFO_STOP: hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), dma->dma_ctrl); vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, this_4, this_8, 0, 0); break; } dma->fifo_status = FIFO_PAUSE;}static void vortex_wtdma_stopfifo(vortex_t * vortex, int wtdma){ stream_t *dma = &vortex->dma_wt[wtdma]; int this_4 = 0, this_8 = 0; if (dma->fifo_status == FIFO_START) vortex_fifo_setwtctrl(vortex, wtdma, 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/* ADB Routes */typedef int ADBRamLink;static void vortex_adb_init(vortex_t * vortex){ int i; /* it looks like we are writing more than we need to... * if we write what we are supposed to it breaks things... */ hwwrite(vortex->mmio, VORTEX_ADB_SR, 0); for (i = 0; i < VORTEX_ADB_RTBASE_COUNT; i++) hwwrite(vortex->mmio, VORTEX_ADB_RTBASE + (i << 2), hwread(vortex->mmio, VORTEX_ADB_RTBASE + (i << 2)) | ROUTE_MASK); for (i = 0; i < VORTEX_ADB_CHNBASE_COUNT; i++) { hwwrite(vortex->mmio, VORTEX_ADB_CHNBASE + (i << 2), hwread(vortex->mmio, VORTEX_ADB_CHNBASE + (i << 2)) | ROUTE_MASK); }}static void vortex_adb_en_sr(vortex_t * vortex, int channel){ hwwrite(vortex->mmio, VORTEX_ADB_SR, hwread(vortex->mmio, VORTEX_ADB_SR) | (0x1 << channel));}static void vortex_adb_dis_sr(vortex_t * vortex, int channel){ hwwrite(vortex->mmio, VORTEX_ADB_SR, hwread(vortex->mmio, VORTEX_ADB_SR) & ~(0x1 << channel));}static voidvortex_adb_addroutes(vortex_t * vortex, unsigned char channel, ADBRamLink * route, int rnum){ int temp, prev, lifeboat = 0; if ((rnum <= 0) || (route == NULL)) return; /* Write last routes. */ rnum--; hwwrite(vortex->mmio, VORTEX_ADB_RTBASE + ((route[rnum] & ADB_MASK) << 2), ROUTE_MASK); while (rnum > 0) { hwwrite(vortex->mmio, VORTEX_ADB_RTBASE + ((route[rnum - 1] & ADB_MASK) << 2), route[rnum]); rnum--; } /* Write first route. */ temp = hwread(vortex->mmio, VORTEX_ADB_CHNBASE + (channel << 2)) & ADB_MASK; if (temp == ADB_MASK) { /* First entry on this channel. */ hwwrite(vortex->mmio, VORTEX_ADB_CHNBASE + (channel << 2), route[0]); vortex_adb_en_sr(vortex, channel); return; } /* Not first entry on this channel. Need to link. */ do { prev = temp; temp = hwread(vortex->mmio, VORTEX_ADB_RTBASE + (temp << 2)) & ADB_MASK; if ((lifeboat++) > ADB_MASK) { printk(KERN_ERR "vortex_adb_addroutes: unending route! 0x%x\n", *route); return; } } while (temp != ADB_MASK); hwwrite(vortex->mmio, VORTEX_ADB_RTBASE + (prev << 2), route[0]);}static voidvortex_adb_delroutes(vortex_t * vortex, unsigned char channel, ADBRamLink route0, ADBRamLink route1){ int temp, lifeboat = 0, prev; /* Find route. */ temp = hwread(vortex->mmio, VORTEX_ADB_CHNBASE + (channel << 2)) & ADB_MASK; if (temp == (route0 & ADB_MASK)) { temp = hwread(vortex->mmio, VORTEX_ADB_RTBASE + ((route1 & ADB_MASK) << 2)); if ((temp & ADB_MASK) == ADB_MASK) vortex_adb_dis_sr(vortex, channel); hwwrite(vortex->mmio, VORTEX_ADB_CHNBASE + (channel << 2), temp); return; } do { prev = temp; temp = hwread(vortex->mmio, VORTEX_ADB_RTBASE + (prev << 2)) & ADB_MASK; if (((lifeboat++) > ADB_MASK) || (temp == ADB_MASK)) { printk(KERN_ERR "vortex_adb_delroutes: route not found! 0x%x\n", route0); return; } } while (temp != (route0 & ADB_MASK)); temp = hwread(vortex->mmio, VORTEX_ADB_RTBASE + (temp << 2)); if ((temp & ADB_MASK) == route1) temp = hwread(vortex->mmio, VORTEX_ADB_RTBASE + (temp << 2)); /* Make bridge over deleted route. */ hwwrite(vortex->mmio, VORTEX_ADB_RTBASE + (prev << 2), temp);}static voidvortex_route(vortex_t * vortex, int en, unsigned char channel, unsigned char source, unsigned char dest){ ADBRamLink route; route = ((source & ADB_MASK) << ADB_SHIFT) | (dest & ADB_MASK); if (en) { vortex_adb_addroutes(vortex, channel, &route, 1); if ((source < (OFFSET_SRCOUT + NR_SRC)) && (source >= OFFSET_SRCOUT)) vortex_src_addWTD(vortex, (source - OFFSET_SRCOUT), channel); else if ((source < (OFFSET_MIXOUT + NR_MIXOUT)) && (source >= OFFSET_MIXOUT)) vortex_mixer_addWTD(vortex, (source - OFFSET_MIXOUT), channel); } else { vortex_adb_delroutes(vortex, channel, route, route); if ((source < (OFFSET_SRCOUT + NR_SRC)) && (source >= OFFSET_SRCOUT)) vortex_src_delWTD(vortex, (source - OFFSET_SRCOUT), channel); else if ((source < (OFFSET_MIXOUT + NR_MIXOUT)) && (source >= OFFSET_MIXOUT)) vortex_mixer_delWTD(vortex, (source - OFFSET_MIXOUT), channel); }}#if 0static voidvortex_routes(vortex_t * vortex, int en, unsigned char channel, unsigned char source, unsigned char dest0, unsigned char dest1){ ADBRamLink route[2]; route[0] = ((source & ADB_MASK) << ADB_SHIFT) | (dest0 & ADB_MASK); route[1] = ((source & ADB_MASK) << ADB_SHIFT) | (dest1 & ADB_MASK); if (en) { vortex_adb_addroutes(vortex, channel, route, 2); if ((source < (OFFSET_SRCOUT + NR_SRC)) && (source >= (OFFSET_SRCOUT))) vortex_src_addWTD(vortex, (source - OFFSET_SRCOUT), channel); else if ((source < (OFFSET_MIXOUT + NR_MIXOUT)) && (source >= (OFFSET_MIXOUT))) vortex_mixer_addWTD(vortex, (source - OFFSET_MIXOUT), channel); } else { vortex_adb_delroutes(vortex, channel, route[0], route[1]); if ((source < (OFFSET_SRCOUT + NR_SRC)) && (source >= (OFFSET_SRCOUT))) vortex_src_delWTD(vortex, (source - OFFSET_SRCOUT), channel); else if ((source < (OFFSET_MIXOUT + NR_MIXOUT)) && (source >= (OFFSET_MIXOUT))) vortex_mixer_delWTD(vortex, (source - OFFSET_MIXOUT), channel); }}#endif/* Route two sources to same target. Sources must be of same class !!! */static voidvortex_routeLRT(vortex_t * vortex, int en, unsigned char ch, unsigned char source0, unsigned char source1, unsigned char dest){ ADBRamLink route[2]; route[0] = ((source0 & ADB_MASK) << ADB_SHIFT) | (dest & ADB_MASK); route[1] = ((source1 & ADB_MASK) << ADB_SHIFT) | (dest & ADB_MASK); if (dest < 0x10) route[1] = (route[1] & ~ADB_MASK) | (dest + 0x20); /* fifo A */ if (en) { vortex_adb_addroutes(vortex, ch, route, 2); if ((source0 < (OFFSET_SRCOUT + NR_SRC)) && (source0 >= OFFSET_SRCOUT)) { vortex_src_addWTD(vortex, (source0 - OFFSET_SRCOUT), ch); vortex_src_addWTD(vortex, (source1 - OFFSET_SRCOUT), ch); } else if ((source0 < (OFFSET_MIXOUT + NR_MIXOUT)) && (source0 >= OFFSET_MIXOUT)) { vortex_mixer_addWTD(vortex, (source0 - OFFSET_MIXOUT), ch); vortex_mixer_addWTD(vortex, (source1 - OFFSET_MIXOUT), ch); } } else { vortex_adb_delroutes(vortex, ch, route[0], route[1]); if ((source0 < (OFFSET_SRCOUT + NR_SRC)) && (source0 >= OFFSET_SRCOUT)) { vortex_src_delWTD(vortex, (source0 - OFFSET_SRCOUT), ch); vortex_src_delWTD(vortex, (source1 - OFFSET_SRCOUT), ch); } else if ((source0 < (OFFSET_MIXOUT + NR_MIXOUT)) && (source0 >= OFFSET_MIXOUT)) { vortex_mixer_delWTD(vortex, (source0 - OFFSET_MIXOUT), ch); vortex_mixer_delWTD(vortex, (source1 - OFFSET_MIXOUT), ch); } }}/* Connection stuff */// Connect adbdma to src('s).static voidvortex_connection_adbdma_src(vortex_t * vortex, int en, unsigned char ch, unsigned char adbdma, unsigned char src){ vortex_route(vortex, en, ch, ADB_DMA(adbdma), ADB_SRCIN(src));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -