📄 au88x0_core.c
字号:
// Connect SRC to mixin.static voidvortex_connection_src_mixin(vortex_t * vortex, int en, unsigned char channel, unsigned char src, unsigned char mixin){ vortex_route(vortex, en, channel, ADB_SRCOUT(src), ADB_MIXIN(mixin));}// Connect mixin with mix output.static voidvortex_connection_mixin_mix(vortex_t * vortex, int en, unsigned char mixin, unsigned char mix, int a){ if (en) { vortex_mix_enableinput(vortex, mix, mixin); vortex_mix_setinputvolumebyte(vortex, mix, mixin, MIX_DEFIGAIN); // added to original code. } else vortex_mix_disableinput(vortex, mix, mixin, a);}// Connect absolut address to mixin.static voidvortex_connection_adb_mixin(vortex_t * vortex, int en, unsigned char channel, unsigned char source, unsigned char mixin){ vortex_route(vortex, en, channel, source, ADB_MIXIN(mixin));}static voidvortex_connection_src_adbdma(vortex_t * vortex, int en, unsigned char ch, unsigned char src, unsigned char adbdma){ vortex_route(vortex, en, ch, ADB_SRCOUT(src), ADB_DMA(adbdma));}static voidvortex_connection_src_src_adbdma(vortex_t * vortex, int en, unsigned char ch, unsigned char src0, unsigned char src1, unsigned char adbdma){ vortex_routeLRT(vortex, en, ch, ADB_SRCOUT(src0), ADB_SRCOUT(src1), ADB_DMA(adbdma));}// mix to absolut address.static voidvortex_connection_mix_adb(vortex_t * vortex, int en, unsigned char ch, unsigned char mix, unsigned char dest){ vortex_route(vortex, en, ch, ADB_MIXOUT(mix), dest); vortex_mix_setvolumebyte(vortex, mix, MIX_DEFOGAIN); // added to original code.}// mixer to src.static voidvortex_connection_mix_src(vortex_t * vortex, int en, unsigned char ch, unsigned char mix, unsigned char src){ vortex_route(vortex, en, ch, ADB_MIXOUT(mix), ADB_SRCIN(src)); vortex_mix_setvolumebyte(vortex, mix, MIX_DEFOGAIN); // added to original code.}#if 0static voidvortex_connection_adbdma_src_src(vortex_t * vortex, int en, unsigned char channel, unsigned char adbdma, unsigned char src0, unsigned char src1){ vortex_routes(vortex, en, channel, ADB_DMA(adbdma), ADB_SRCIN(src0), ADB_SRCIN(src1));}// Connect two mix to AdbDma.static voidvortex_connection_mix_mix_adbdma(vortex_t * vortex, int en, unsigned char ch, unsigned char mix0, unsigned char mix1, unsigned char adbdma){ ADBRamLink routes[2]; routes[0] = (((mix0 + OFFSET_MIXOUT) & ADB_MASK) << ADB_SHIFT) | (adbdma & ADB_MASK); routes[1] = (((mix1 + OFFSET_MIXOUT) & ADB_MASK) << ADB_SHIFT) | ((adbdma + 0x20) & ADB_MASK); if (en) { vortex_adb_addroutes(vortex, ch, routes, 0x2); vortex_mixer_addWTD(vortex, mix0, ch); vortex_mixer_addWTD(vortex, mix1, ch); } else { vortex_adb_delroutes(vortex, ch, routes[0], routes[1]); vortex_mixer_delWTD(vortex, mix0, ch); vortex_mixer_delWTD(vortex, mix1, ch); }}#endif/* CODEC connect. */static voidvortex_connect_codecplay(vortex_t * vortex, int en, unsigned char mixers[]){#ifdef CHIP_AU8820 vortex_connection_mix_adb(vortex, en, 0x11, mixers[0], ADB_CODECOUT(0)); vortex_connection_mix_adb(vortex, en, 0x11, mixers[1], ADB_CODECOUT(1));#else#if 1 // Connect front channels through EQ. vortex_connection_mix_adb(vortex, en, 0x11, mixers[0], ADB_EQIN(0)); vortex_connection_mix_adb(vortex, en, 0x11, mixers[1], ADB_EQIN(1)); /* Lower volume, since EQ has some gain. */ vortex_mix_setvolumebyte(vortex, mixers[0], 0); vortex_mix_setvolumebyte(vortex, mixers[1], 0); vortex_route(vortex, en, 0x11, ADB_EQOUT(0), ADB_CODECOUT(0)); vortex_route(vortex, en, 0x11, ADB_EQOUT(1), ADB_CODECOUT(1)); /* Check if reg 0x28 has SDAC bit set. */ if (VORTEX_IS_QUAD(vortex)) { /* Rear channel. Note: ADB_CODECOUT(0+2) and (1+2) is for AC97 modem */ vortex_connection_mix_adb(vortex, en, 0x11, mixers[2], ADB_CODECOUT(0 + 4)); vortex_connection_mix_adb(vortex, en, 0x11, mixers[3], ADB_CODECOUT(1 + 4)); //printk("SDAC detected "); }#else // Use plain direct output to codec. vortex_connection_mix_adb(vortex, en, 0x11, mixers[0], ADB_CODECOUT(0)); vortex_connection_mix_adb(vortex, en, 0x11, mixers[1], ADB_CODECOUT(1));#endif#endif}static voidvortex_connect_codecrec(vortex_t * vortex, int en, unsigned char mixin0, unsigned char mixin1){ /* Enable: 0x1, 0x1 Channel: 0x11, 0x11 ADB Source address: 0x48, 0x49 Destination Asp4Topology_0x9c,0x98 */ vortex_connection_adb_mixin(vortex, en, 0x11, ADB_CODECIN(0), mixin0); vortex_connection_adb_mixin(vortex, en, 0x11, ADB_CODECIN(1), mixin1);}// Higher level ADB audio path (de)allocator./* Resource manager */static int resnum[VORTEX_RESOURCE_LAST] = { NR_ADB, NR_SRC, NR_MIXIN, NR_MIXOUT, NR_A3D };/* Checkout/Checkin resource of given type. resmap: resource map to be used. If NULL means that we want to allocate a DMA resource (root of all other resources of a dma channel). out: Mean checkout if != 0. Else mean Checkin resource. restype: Indicates type of resource to be checked in or out.*/static charvortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype){ int i, qty = resnum[restype], resinuse = 0; if (out) { /* Gather used resources by all streams. */ for (i = 0; i < NR_ADB; i++) { resinuse |= vortex->dma_adb[i].resources[restype]; } resinuse |= vortex->fixed_res[restype]; /* Find and take free resource. */ for (i = 0; i < qty; i++) { if ((resinuse & (1 << i)) == 0) { if (resmap != NULL) resmap[restype] |= (1 << i); else vortex->dma_adb[i].resources[restype] |= (1 << i); //printk("vortex: ResManager: type %d out %d\n", restype, i); return i; } } } else { if (resmap == NULL) return -EINVAL; /* Checkin first resource of type restype. */ for (i = 0; i < qty; i++) { if (resmap[restype] & (1 << i)) { resmap[restype] &= ~(1 << i); //printk("vortex: ResManager: type %d in %d\n",restype, i); return i; } } } printk("vortex: FATAL: ResManager: resource type %d exhausted.\n", restype); return -ENOMEM;}/* Default Connections */static intvortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type);static void vortex_connect_default(vortex_t * vortex, int en){ // Connect AC97 codec. vortex->mixplayb[0] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, VORTEX_RESOURCE_MIXOUT); vortex->mixplayb[1] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, VORTEX_RESOURCE_MIXOUT); if (VORTEX_IS_QUAD(vortex)) { vortex->mixplayb[2] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, VORTEX_RESOURCE_MIXOUT); vortex->mixplayb[3] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, VORTEX_RESOURCE_MIXOUT); } vortex_connect_codecplay(vortex, en, vortex->mixplayb); vortex->mixcapt[0] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, VORTEX_RESOURCE_MIXIN); vortex->mixcapt[1] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, VORTEX_RESOURCE_MIXIN); vortex_connect_codecrec(vortex, en, MIX_CAPT(0), MIX_CAPT(1)); // Connect SPDIF#ifndef CHIP_AU8820 vortex->mixspdif[0] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, VORTEX_RESOURCE_MIXOUT); vortex->mixspdif[1] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, VORTEX_RESOURCE_MIXOUT); vortex_connection_mix_adb(vortex, en, 0x14, vortex->mixspdif[0], ADB_SPDIFOUT(0)); vortex_connection_mix_adb(vortex, en, 0x14, vortex->mixspdif[1], ADB_SPDIFOUT(1));#endif // Connect WT#ifndef CHIP_AU8810 vortex_wt_connect(vortex, en);#endif // A3D (crosstalk canceler and A3D slices). AU8810 disabled for now.#ifndef CHIP_AU8820 vortex_Vort3D_connect(vortex, en);#endif // Connect I2S // Connect DSP interface for SQ3500 turbo (not here i think...) // Connect AC98 modem codec }/* Allocate nr_ch pcm audio routes if dma < 0. If dma >= 0, existing routes are deallocated. dma: DMA engine routes to be deallocated when dma >= 0. nr_ch: Number of channels to be de/allocated. dir: direction of stream. Uses same values as substream->stream. type: Type of audio output/source (codec, spdif, i2s, dsp, etc) Return: Return allocated DMA or same DMA passed as "dma" when dma >= 0.*/static intvortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type){ stream_t *stream; int i, en; if ((nr_ch == 3) || ((dir == SNDRV_PCM_STREAM_CAPTURE) && (nr_ch > 2))) return -EBUSY; if (dma >= 0) { en = 0; vortex_adb_checkinout(vortex, vortex->dma_adb[dma].resources, en, VORTEX_RESOURCE_DMA); } else { en = 1; if ((dma = vortex_adb_checkinout(vortex, NULL, en, VORTEX_RESOURCE_DMA)) < 0) return -EBUSY; } stream = &vortex->dma_adb[dma]; stream->dma = dma; stream->dir = dir; stream->type = type; /* PLAYBACK ROUTES. */ if (dir == SNDRV_PCM_STREAM_PLAYBACK) { int src[4], mix[4], ch_top;#ifndef CHIP_AU8820 int a3d = 0;#endif /* Get SRC and MIXER hardware resources. */ if (stream->type != VORTEX_PCM_SPDIF) { for (i = 0; i < nr_ch; i++) { if ((src[i] = vortex_adb_checkinout(vortex, stream->resources, en, VORTEX_RESOURCE_SRC)) < 0) { memset(stream->resources, 0, sizeof(unsigned char) * VORTEX_RESOURCE_LAST); return -EBUSY; } if (stream->type != VORTEX_PCM_A3D) { if ((mix[i] = vortex_adb_checkinout(vortex, stream->resources, en, VORTEX_RESOURCE_MIXIN)) < 0) { memset(stream->resources, 0, sizeof(unsigned char) * VORTEX_RESOURCE_LAST); return -EBUSY; } } } }#ifndef CHIP_AU8820 if (stream->type == VORTEX_PCM_A3D) { if ((a3d = vortex_adb_checkinout(vortex, stream->resources, en, VORTEX_RESOURCE_A3D)) < 0) { memset(stream->resources, 0, sizeof(unsigned char) * VORTEX_RESOURCE_LAST); printk("vortex: out of A3D sources. Sorry\n"); return -EBUSY; } /* (De)Initialize A3D hardware source. */ vortex_Vort3D_InitializeSource(&(vortex->a3d[a3d]), en); } /* Make SPDIF out exclusive to "spdif" device when in use. */ if ((stream->type == VORTEX_PCM_SPDIF) && (en)) { vortex_route(vortex, 0, 0x14, ADB_MIXOUT(vortex->mixspdif[0]), ADB_SPDIFOUT(0)); vortex_route(vortex, 0, 0x14, ADB_MIXOUT(vortex->mixspdif[1]), ADB_SPDIFOUT(1)); }#endif /* Make playback routes. */ for (i = 0; i < nr_ch; i++) { if (stream->type == VORTEX_PCM_ADB) { vortex_connection_adbdma_src(vortex, en, src[nr_ch - 1], dma, src[i]); vortex_connection_src_mixin(vortex, en, 0x11, src[i], mix[i]); vortex_connection_mixin_mix(vortex, en, mix[i], MIX_PLAYB(i), 0);#ifndef CHIP_AU8820 vortex_connection_mixin_mix(vortex, en, mix[i], MIX_SPDIF(i % 2), 0); vortex_mix_setinputvolumebyte(vortex, MIX_SPDIF(i % 2), mix[i], MIX_DEFIGAIN);#endif }#ifndef CHIP_AU8820 if (stream->type == VORTEX_PCM_A3D) { vortex_connection_adbdma_src(vortex, en, src[nr_ch - 1], dma, src[i]); vortex_route(vortex, en, 0x11, ADB_SRCOUT(src[i]), ADB_A3DIN(a3d)); /* XTalk test. */ //vortex_route(vortex, en, 0x11, dma, ADB_XTALKIN(i?9:4)); //vortex_route(vortex, en, 0x11, ADB_SRCOUT(src[i]), ADB_XTALKIN(i?4:9)); } if (stream->type == VORTEX_PCM_SPDIF) vortex_route(vortex, en, 0x14, ADB_DMA(stream->dma), ADB_SPDIFOUT(i));#endif } if (stream->type != VORTEX_PCM_SPDIF && stream->type != VORTEX_PCM_A3D) { ch_top = (VORTEX_IS_QUAD(vortex) ? 4 : 2); for (i = nr_ch; i < ch_top; i++) { vortex_connection_mixin_mix(vortex, en, mix[i % nr_ch], MIX_PLAYB(i), 0);#ifndef CHIP_AU8820 vortex_connection_mixin_mix(vortex, en, mix[i % nr_ch], MIX_SPDIF(i % 2), 0); vortex_mix_setinputvolumebyte(vortex, MIX_SPDIF(i % 2), mix[i % nr_ch], MIX_DEFIGAIN);#endif } }#ifndef CHIP_AU8820 else { if (nr_ch == 1 && stream->type == VORTEX_PCM_SPDIF) vortex_route(vortex, en, 0x14, ADB_DMA(stream->dma), ADB_SPDIFOUT(1)); } /* Reconnect SPDIF out when "spdif" device is down. */ if ((stream->type == VORTEX_PCM_SPDIF) && (!en)) { vortex_route(vortex, 1, 0x14, ADB_MIXOUT(vortex->mixspdif[0]), ADB_SPDIFOUT(0)); vortex_route(vortex, 1, 0x14, ADB_MIXOUT(vortex->mixspdif[1]), ADB_SPDIFOUT(1)); }#endif /* CAPTURE ROUTES. */ } else { int src[2], mix[2]; /* Get SRC and MIXER hardware resources. */ for (i = 0; i < nr_ch; i++) { if ((mix[i] = vortex_adb_checkinout(vortex, stream->resources, en, VORTEX_RESOURCE_MIXOUT)) < 0) { memset(stream->resources, 0, sizeof(unsigned char) * VORTEX_RESOURCE_LAST); return -EBUSY; } if ((src[i] = vortex_adb_checkinout(vortex, stream->resources, en, VORTEX_RESOURCE_SRC)) < 0) { memset(stream->resources, 0, sizeof(unsigned char) * VORTEX_RESOURCE_LAST); return -EBUSY; } } /* Make capture routes. */ vortex_connection_mixin_mix(vortex, en, MIX_CAPT(0), mix[0], 0); vortex_connection_mix_src(vortex, en, 0x11, mix[0], src[0]); if (nr_ch == 1) { vortex_connection_mixin_mix(vortex, en, MIX_CAPT(1), mix[0], 0); vortex_connection_src_adbdma(vorte
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -