diff -Naur alsa-orig/pci/au88x0/au8810.h alsa-resman/pci/au88x0/au8810.h --- alsa-orig/pci/au88x0/au8810.h 2003-07-03 00:40:02.000000000 -0400 +++ alsa-resman/pci/au88x0/au8810.h 2003-07-09 17:22:55.000000000 -0400 @@ -152,6 +152,11 @@ /* CODEC */ #define VORTEX_CODEC_CTRL 0x29184 #define VORTEX_CODEC_EN 0x29190 +#define EN_CODEC0 0x00000300 +#define EN_CODEC1 0x00003000 +#define EN_CODEC (EN_CODEC0 | EN_CODEC1) +#define EN_SPORT 0x00030000 +#define EN_SPDIF 0x000c0000 #define VORTEX_CODEC_CHN 0x29080 #define VORTEX_CODEC_WRITE 0x00800000 #define VORTEX_CODEC_ADDSHIFT 16 diff -Naur alsa-orig/pci/au88x0/au8820.h alsa-resman/pci/au88x0/au8820.h --- alsa-orig/pci/au88x0/au8820.h 2003-07-03 23:33:02.000000000 -0400 +++ alsa-resman/pci/au88x0/au8820.h 2003-07-09 17:22:55.000000000 -0400 @@ -157,6 +157,9 @@ /* CODEC */ #define VORTEX_CODEC_CTRL 0x11984 #define VORTEX_CODEC_EN 0x11990 +#define EN_CODEC 0x00000300 +#define EN_SPORT 0x00030000 +#define EN_SPDIF 0x000c0000 #define VORTEX_CODEC_CHN 0x11880 #define VORTEX_CODEC_WRITE 0x00800000 #define VORTEX_CODEC_ADDSHIFT 16 diff -Naur alsa-orig/pci/au88x0/au8830.h alsa-resman/pci/au88x0/au8830.h --- alsa-orig/pci/au88x0/au8830.h 2003-07-03 00:40:02.000000000 -0400 +++ alsa-resman/pci/au88x0/au8830.h 2003-07-09 17:22:55.000000000 -0400 @@ -102,10 +102,6 @@ #define ADB_A3DOUT(x) (x + 0x50) /* 0x10 A3D blocks */ #define ADB_A3DIN(x) (x + 0x70) -#define MIX_OUTL 0xe -#define MIX_OUTR 0xf -#define MIX_INL 0x1e -#define MIX_INR 0x1f #define MIX_DEFIGAIN 0x00 #define MIX_DEFOGAIN 0x00 /* 0x8->6dB (6dB = x4) 16 to 18 bit conversion? */ @@ -153,8 +149,6 @@ #define FIFO_SIZE_BITS 6 #define FIFO_SIZE (1<<(FIFO_SIZE_BITS)) // 0x40 #define FIFO_MASK (FIFO_SIZE-1) //0x3f /* at shift left 0xc */ -//#define FIFO_MASK 0x3f /* at shift left 0xc */ -//#define FIFO_SIZE 0x40 #define FIFO_BITS 0x1c400000 #define VORTEX_FIFO_ADBDATA 0x14000 #define VORTEX_FIFO_WTDATA 0x10000 @@ -162,10 +156,12 @@ /* CODEC */ #define VORTEX_CODEC_CTRL 0x29184 #define VORTEX_CODEC_EN 0x29190 -#define EN_CODEC 0x00000300 -#define EN_CODEC2 0x00003000 -#define EN_SPORT 0x00030000 -#define EN_SPDIF 0x000c0000 +#define EN_CODEC_AUDIO0 0x00000300 +#define EN_CODEC_MODEM 0x00000c00 +#define EN_CODEC_AUDIO1 0x00003000 +#define EN_SPORT 0x00030000 +#define EN_SPDIF 0x000c0000 +#define EN_CODEC 0x00003300 #define VORTEX_CODEC_CHN 0x29080 #define VORTEX_CODEC_WRITE 0x00800000 #define VORTEX_CODEC_ADDSHIFT 16 diff -Naur alsa-orig/pci/au88x0/au88x0.c alsa-resman/pci/au88x0/au88x0.c --- alsa-orig/pci/au88x0/au88x0.c 2003-07-04 19:28:55.000000000 -0400 +++ alsa-resman/pci/au88x0/au88x0.c 2003-07-09 17:22:50.000000000 -0400 @@ -318,6 +318,4 @@ module_exit(alsa_card_vortex_exit) // for old kernels only -#ifdef EXPORT_NO_SYMBOLS EXPORT_NO_SYMBOLS; -#endif diff -Naur alsa-orig/pci/au88x0/au88x0.h alsa-resman/pci/au88x0/au88x0.h --- alsa-orig/pci/au88x0/au88x0.h 2003-07-04 19:28:55.000000000 -0400 +++ alsa-resman/pci/au88x0/au88x0.h 2003-07-09 17:22:55.000000000 -0400 @@ -61,6 +61,16 @@ #define FIFO_START 1 #define FIFO_PAUSE 2 +/* ADB Resource */ +#define VORTEX_RESOURCE_DMA 0x00000000 +#define VORTEX_RESOURCE_SRC 0x00000001 +#define VORTEX_RESOURCE_MIXIN 0x00000002 +#define VORTEX_RESOURCE_MIXOUT 0x00000003 +#define VORTEX_RESOURCE_A3D 0x00000004 +#define VORTEX_RESOURCE_LAST 0x00000005 + +#define MIX_CAPT(x) (NR_MIXIN - x - 1) +#define MIX_PLAYB(x) (NR_MIXOUT - x - 1) /* Structs */ @@ -72,9 +82,11 @@ int cfg0; int cfg1; - int nr_ch; /* Used channel bitmap */ - int dma; /* dma channel */ - + int nr_ch; /* Nr of PCM channels */ + int dma; /* Hardware Stream index. */ + int dir; /* Stream Direction. */ + u32 resources[5]; + /* Virtual page extender stuff */ int nr_periods; int period_bytes; @@ -83,7 +95,7 @@ int period_virt; snd_pcm_substream_t *substream; -} dma_t; +} stream_t; typedef struct snd_vortex vortex_t; struct snd_vortex { @@ -94,9 +106,9 @@ snd_rawmidi_t *rmidi; /* Legacy Midi interface. */ ac97_t *codec; - // DMA structs. - dma_t dma_adb[NR_ADB]; - dma_t dma_wt[NR_WT]; + // Stream structs. + stream_t dma_adb[NR_ADB]; + stream_t dma_wt[NR_WT]; /* Hardware equalizer structs */ eqlzr_t eq; @@ -165,11 +177,11 @@ int vortex_alsafmt_aspfmt(int alsafmt); /* Connection stuff. */ -int vortex_adb_waveroute(vortex_t *vortex, int adbdma, int nch); -int vortex_wt_waveroute(vortex_t *vortex, int adbdma, int nch); +int vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir); +int vortex_wt_allocroute(vortex_t *vortex, int dma, int nr_ch); -/* Driver stuff. */ +/* Driver stuff. */ int __devinit vortex_gameport_register(vortex_t *card); int __devexit vortex_gameport_unregister(vortex_t *card); int __devinit vortex_eq_init(vortex_t *vortex); diff -Naur alsa-orig/pci/au88x0/au88x0_core.c alsa-resman/pci/au88x0/au88x0_core.c --- alsa-orig/pci/au88x0/au88x0_core.c 2003-07-03 23:33:02.000000000 -0400 +++ alsa-resman/pci/au88x0/au88x0_core.c 2003-07-09 17:22:50.000000000 -0400 @@ -685,12 +685,20 @@ void vortex_fifo_adbinitialize(vortex_t *vortex, int fifo, int j) { vortex_fifo_clearadbdata(vortex, fifo, FIFO_SIZE); +#ifdef CHIP_AU8820 hwwrite(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2), (FIFO_U1 | ((j & FIFO_MASK) << 0xb))); +#else + hwwrite(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2), (FIFO_U1 | ((j & FIFO_MASK) << 0xc))); +#endif } void vortex_fifo_wtinitialize(vortex_t *vortex, int fifo, int j) { vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); +#ifdef CHIP_AU8820 hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), (FIFO_U1 | ((j & FIFO_MASK) << 0xb))); +#else + hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), (FIFO_U1 | ((j & FIFO_MASK) << 0xc))); +#endif } void vortex_fifo_setadbvalid(vortex_t *vortex, int fifo, int en) { @@ -706,7 +714,7 @@ void vortex_fifo_setadbctrl(vortex_t *vortex, int fifo, int b, int priority, int empty, int valid, int f) { int temp, lifeboat=0; //int this_8[NR_ADB] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* position */ - int this_4=0x0; + int this_4=0x2; /* f seems priority related. * CAsp4AdbDma::SetPriority is the only place that calls SetAdbCtrl with f set to 1 * every where else it is set to 0. It seems, however, that CAsp4AdbDma::SetPriority @@ -714,7 +722,7 @@ */ do { temp = hwread(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2)); - if (lifeboat++ > 0xff) { + if (lifeboat++ > 0xbb8) { printk(KERN_ERR "Vortex: vortex_fifo_setadbctrl fail\n"); break; } @@ -725,7 +733,7 @@ if (valid) { if (!(temp & FIFO_VALID)) { //this_8[fifo] = 0; - vortex_fifo_clearadbdata(vortex, fifo, this_4); + vortex_fifo_clearadbdata(vortex, fifo, FIFO_SIZE); // this_4 #ifdef CHIP_AU8820 temp = (this_4 & 0x1f) << 0xb; #else @@ -763,6 +771,7 @@ /*if (this_8[fifo])*/ vortex_fifo_clearadbdata(vortex, fifo, FIFO_SIZE); } hwwrite(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2), temp); + hwread(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2)); } void vortex_fifo_setwtctrl(vortex_t *vortex, int fifo, int b, int priority, int empty, int valid, int f) { @@ -793,7 +802,7 @@ // if "c" is 0, then DMA stops when reaching that buffer. int offset, shift, mask; - dma_t *dma = &vortex->dma_adb[adbdma]; + stream_t *dma = &vortex->dma_adb[adbdma]; int *cfg; if (sb_next == -1) { @@ -830,19 +839,19 @@ } void vortex_adbdma_setfirstbuffer(vortex_t *vortex, int adbdma) { - dma_t *dma = &vortex->dma_adb[adbdma]; + stream_t *dma = &vortex->dma_adb[adbdma]; hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), dma->dma_ctrl); } void vortex_adbdma_setstartbuffer(vortex_t *vortex, int adbdma, int sb) { - dma_t *dma = &vortex->dma_adb[adbdma]; + stream_t *dma = &vortex->dma_adb[adbdma]; hwwrite(vortex->mmio, VORTEX_ADBDMA_START + (adbdma << 2), (sb << ((NR_ADB-adbdma)*2))); dma->period_real = dma->period_virt = sb; } void vortex_adbdma_setbuffers(vortex_t *vortex, int adbdma, unsigned int addr, int size, int count) { - dma_t *dma = &vortex->dma_adb[adbdma]; + stream_t *dma = &vortex->dma_adb[adbdma]; dma->period_bytes = size; dma->nr_periods = count; @@ -882,7 +891,7 @@ } void vortex_adbdma_setmode(vortex_t *vortex, int adbdma, int ie, int dir, int fmt, int d, unsigned long offset) { - dma_t *dma = &vortex->dma_adb[adbdma]; + stream_t *dma = &vortex->dma_adb[adbdma]; dma->dma_unknown = d; dma->dma_ctrl = ((offset & OFFSET_MASK) | (dma->dma_ctrl & ~OFFSET_MASK)); @@ -896,7 +905,7 @@ } void vortex_adbdma_bufshift(vortex_t *vortex, int adbdma) { - dma_t *dma = &vortex->dma_adb[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; @@ -931,7 +940,7 @@ if (dma->period_virt >= dma->nr_periods) dma->period_virt -= dma->nr_periods; if ((delta != 1) || (delta < 0)) - printk(KERN_INFO "vortex: % d virt=0x%d, real=0x%x, delta = %d\n", dma->dma, dma->period_virt, dma->period_real, delta); + printk(KERN_INFO "vortex: % d virt=0x%d, real=0x%x, delta = %d\n", adbdma, dma->period_virt, dma->period_real, delta); } void vortex_adbdma_setctrl(vortex_t *vortex, int a, int b, int c, int d, int e, int f) { @@ -940,7 +949,7 @@ void vortex_adbdma_getposition(vortex_t *vortex, int adbdma, int *subbuf, int *pos) { int temp, edi, eax, ecx, esp10, edx; - dma_t *dma = &vortex->dma_adb[adbdma]; + stream_t *dma = &vortex->dma_adb[adbdma]; // dma->cfg0: this_7c, dma->cfg1: this_80. @@ -1046,7 +1055,7 @@ } int inline vortex_adbdma_getlinearpos(vortex_t *vortex, int adbdma) { - dma_t *dma = &vortex->dma_adb[adbdma]; + stream_t *dma = &vortex->dma_adb[adbdma]; int temp; temp = hwread(vortex->mmio, VORTEX_ADBDMA_STAT + (adbdma << 2)); @@ -1059,7 +1068,7 @@ void vortex_adbdma_startfifo(vortex_t *vortex, int adbdma) { int this_8=0/*empty*/, this_4=0/*priority*/; - dma_t *dma = &vortex->dma_adb[adbdma]; + stream_t *dma = &vortex->dma_adb[adbdma]; switch (dma->fifo_status) { case FIFO_START: @@ -1079,7 +1088,7 @@ } void vortex_adbdma_resumefifo(vortex_t *vortex, int adbdma) { - dma_t *dma = &vortex->dma_adb[adbdma]; + stream_t *dma = &vortex->dma_adb[adbdma]; int this_8=1, this_4=0; switch (dma->fifo_status) { @@ -1097,7 +1106,7 @@ } void vortex_adbdma_pausefifo(vortex_t *vortex, int adbdma) { - dma_t *dma = &vortex->dma_adb[adbdma]; + stream_t *dma = &vortex->dma_adb[adbdma]; int this_8=0, this_4=0; switch (dma->fifo_status) { @@ -1113,7 +1122,7 @@ } void vortex_adbdma_stopfifo(vortex_t *vortex, int adbdma) { - dma_t *dma = &vortex->dma_adb[adbdma]; + stream_t *dma = &vortex->dma_adb[adbdma]; int this_4=0, this_8=0; if (dma->fifo_status == FIFO_START) @@ -1131,7 +1140,7 @@ void vortex_wtdma_setupbuffer(vortex_t *vortex, int wtdma, int sb, u32 addr, u32 size, int sb_next, int c) { int offset, shift, mask; - dma_t *dma = &vortex->dma_wt[wtdma]; + stream_t *dma = &vortex->dma_wt[wtdma]; int *cfg; if (sb_next == -1) { @@ -1169,19 +1178,19 @@ void vortex_wtdma_setfirstbuffer(vortex_t *vortex, int wtdma) { //int this_7c=dma_ctrl; - dma_t *dma = &vortex->dma_wt[wtdma]; + stream_t *dma = &vortex->dma_wt[wtdma]; hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), dma->dma_ctrl); } void vortex_wtdma_setstartbuffer(vortex_t *vortex, int wtdma, int sb) { - dma_t *dma = &vortex->dma_wt[wtdma]; + stream_t *dma = &vortex->dma_wt[wtdma]; hwwrite(vortex->mmio, VORTEX_WTDMA_START + (wtdma << 2), (sb << ((~wtdma)&0xf)*2)); dma->period_real = dma->period_virt = sb; } void vortex_wtdma_setbuffers(vortex_t *vortex, int wtdma, unsigned int addr, int size, int count) { - dma_t *dma = &vortex->dma_wt[wtdma]; + stream_t *dma = &vortex->dma_wt[wtdma]; /* Wt buffer. */ hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4), addr); @@ -1220,7 +1229,7 @@ } void vortex_wtdma_setmode(vortex_t *vortex, int wtdma, int ie, int dir, int fmt, int d, unsigned long offset) { - dma_t *dma = &vortex->dma_wt[wtdma]; + stream_t *dma = &vortex->dma_wt[wtdma]; dma->dma_unknown = d; dma->dma_ctrl = ((offset & OFFSET_MASK) | (dma->dma_ctrl & ~OFFSET_MASK)); @@ -1234,7 +1243,7 @@ } void vortex_wtdma_bufshift(vortex_t *vortex, int wtdma) { - dma_t *dma = &vortex->dma_wt[wtdma]; + stream_t *dma = &vortex->dma_wt[wtdma]; int page, p, delta, i; page = (hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)) >> 0xc) & 0x3; @@ -1270,7 +1279,7 @@ } int inline vortex_wtdma_getlinearpos(vortex_t *vortex, int wtdma) { - dma_t *dma = &vortex->dma_wt[wtdma]; + stream_t *dma = &vortex->dma_wt[wtdma]; int temp; temp = hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)); @@ -1280,7 +1289,7 @@ } void vortex_wtdma_startfifo(vortex_t *vortex, int wtdma) { - dma_t *dma = &vortex->dma_wt[wtdma]; + stream_t *dma = &vortex->dma_wt[wtdma]; int this_8=0, this_4=0; switch (dma->fifo_status) { @@ -1301,7 +1310,7 @@ } void vortex_wtdma_resumefifo(vortex_t *vortex, int wtdma) { - dma_t *dma = &vortex->dma_wt[wtdma]; + stream_t *dma = &vortex->dma_wt[wtdma]; int this_8=0, this_4=0; switch (dma->fifo_status) { @@ -1319,7 +1328,7 @@ } void vortex_wtdma_pausefifo(vortex_t *vortex, int wtdma) { - dma_t *dma = &vortex->dma_wt[wtdma]; + stream_t *dma = &vortex->dma_wt[wtdma]; int this_8=0, this_4=0; switch (dma->fifo_status) { @@ -1335,7 +1344,7 @@ } void vortex_wtdma_stopfifo(vortex_t *vortex, int wtdma) { - dma_t *dma = &vortex->dma_wt[wtdma]; + stream_t *dma = &vortex->dma_wt[wtdma]; int this_4=0, this_8=0; if (dma->fifo_status == FIFO_START) @@ -1347,7 +1356,7 @@ } void vortex_wtdma_chain(vortex_t *vortex, int wtdma, char sb1, char sb0) { - dma_t *dma = &vortex->dma_wt[wtdma]; + stream_t *dma = &vortex->dma_wt[wtdma]; int *cfg; int offset; @@ -1659,17 +1668,25 @@ vortex_connection_mix_adb(vortex, en, 0x11, mix1, ADB_CODECOUT(1)); #else #if 1 - //Connect EQ. + // Connect front channels through EQ. vortex_connection_mix_adb(vortex, en, 0x11, mix0, ADB_EQIN(0)); vortex_connection_mix_adb(vortex, en, 0x11, mix1, ADB_EQIN(1)); + /* Check if reg 0x28 has SDAC bit set. */ + if (vortex->codec->ext_id | 0x80) { + /* Rear channel. Note: ADB_CODECOUT(0+2) and (1+2) is for AC97 modem */ + vortex_route(vortex, en, 0x11, mix0-2, ADB_CODECOUT(0+4)); + vortex_route(vortex, en, 0x11, mix1-2, ADB_CODECOUT(1+4)); + printk("SDAC detected "); + } vortex_route(vortex, en, 0x11, ADB_EQOUT(0), ADB_CODECOUT(0)); vortex_route(vortex, en, 0x11, ADB_EQOUT(1), ADB_CODECOUT(1)); + #else - // Use plain direct output to codec, since EQ still doesnt work. + // Use plain direct output to codec. vortex_connection_mix_adb(vortex, en, 0x11, mix0, ADB_CODECOUT(0)); vortex_connection_mix_adb(vortex, en, 0x11, mix1, ADB_CODECOUT(1)); #endif -#endif +#endif } void vortex_connect_codecrec(vortex_t *vortex, int en, unsigned char mixin0, unsigned char mixin1) { @@ -1687,115 +1704,168 @@ void vortex_connect_default(vortex_t *vortex, int en) { // Connect codec. - vortex_connect_codecplay(vortex, en, MIX_OUTL, MIX_OUTR); - vortex_connect_codecrec(vortex, en, MIX_INL, MIX_INR); + vortex_connect_codecplay(vortex, en, MIX_PLAYB(0), MIX_PLAYB(1)); + vortex_connect_codecrec(vortex, en, MIX_CAPT(0), MIX_CAPT(1)); } -int vortex_getadb(vortex_t *vortex) { - int adb = 1; /* FIXME why do we get chip'n dale bug if setting this to 0???*/ - while (vortex->dma_adb[adb].nr_ch) { - adb++; - if (adb >= NR_ADB) - return -EBUSY; - } - vortex->dma_adb[adb].nr_ch = -1; - vortex->dma_adb[adb].dma = adb; - return adb; -} +/* Resource manager */ +static int resnum[VORTEX_RESOURCE_LAST] = {NR_ADB, NR_SRC, NR_MIXIN, NR_MIXOUT, NR_A3D}; -int vortex_getwt(vortex_t *vortex) { - int wt = 0; - while (vortex->dma_wt[wt].nr_ch) { - wt++; - if (wt >= NR_WT) - return -EBUSY; +/* + Checkout/Checkin resource of given type. + stream: stream/dma to be used. If -1 means that we want to allocate + the DMA (root of all other resources). + out: Mean checkout if != 0. Else mean Checkin resource. + restype: Indicates type of resource to be checked in or out. +*/ +int vortex_adb_checkinout(vortex_t *vortex, int stream, int out, int restype) { + int i, qty = resnum[restype], resmap=0; + + if (out) { + /* Gather used resources by all streams. */ + for (i=0; idma_adb[i].resources[restype]; + } + /* Find and take free resource. */ + for (i=0; i= 0) + vortex->dma_adb[stream].resources[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 { + /* Checkin first resource of type restype. */ + for (i=0; idma_adb[stream].resources[restype] & (1 << i)) { + vortex->dma_adb[stream].resources[restype] &= ~(1 << i); + //printk("vortex: ResManager: type %d in %d\n",restype, i); + return i; + } + } } - vortex->dma_wt[wt].nr_ch = -1; - vortex->dma_adb[wt].dma = wt; - return wt; + printk("vortex: ResManager: type %d FATAL\n", restype); + return -EBUSY; } /* - Allocate nr_ch pcm audio routes. If nr_ch is 0, existing routes + Allocate nr_ch pcm audio routesif 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. + Return: Return allocated DMA or same DMA passed as "dma" when dma >= 0. */ -int vortex_adb_waveroute(vortex_t *vortex, int adbdma, int nr_ch) { - dma_t *dma = &vortex->dma_adb[adbdma]; +int vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir) { + stream_t *stream; int n, en; - - n = adbdma*2; - if (nr_ch == 0) { - if (dma->nr_ch <= 0) - return -EBUSY; - printk(KERN_INFO "vortex: de alloc %d\n", adbdma); + + if ((nr_ch == 3) || ((dir == SNDRV_PCM_STREAM_CAPTURE)&&(nr_ch > 2))) + return -EBUSY; + + spin_lock(vortex->lock); + if (dma >= 0) { en = 0; - nr_ch = dma->nr_ch; - dma->nr_ch = -1; - vortex_fifo_setadbvalid(vortex, adbdma, 0); + vortex_adb_checkinout(vortex, dma, en, VORTEX_RESOURCE_DMA); } else { - if (dma->nr_ch > 0) - return -EBUSY; - printk(KERN_INFO "vortex: alloc %d\n", adbdma); en = 1; - dma->nr_ch = nr_ch; - vortex_fifo_adbinitialize(vortex, adbdma, FIFO_SIZE-1); + if ((dma = vortex_adb_checkinout(vortex, -1, en, VORTEX_RESOURCE_DMA)) < 0) + return -EBUSY; + } - if (dma->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - vortex_connection_src_mixin(vortex, en, 0x11, n, n); - vortex_connection_mixin_mix(vortex, en, n, MIX_OUTL, 0); + stream = &vortex->dma_adb[dma]; + stream->dma = dma; + stream->dir = dir; + + // FIXME: check for success of checkout or checkin. + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + int src, mix=0; + + for (n=0; nsubstream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - vortex_connection_adbdma_src(vortex, en, n, adbdma, n); - vortex_connection_mixin_mix(vortex, en, n, MIX_OUTR, 0); + int src0, src1, mix; + + mix = vortex_adb_checkinout(vortex, dma, en, VORTEX_RESOURCE_MIXOUT); + src0 = vortex_adb_checkinout(vortex, dma, en, VORTEX_RESOURCE_SRC); + vortex_connection_mixin_mix(vortex, en, MIX_CAPT(0), mix, 0); + vortex_connection_mix_src(vortex, en, 0x11, mix, src0); + + if (nr_ch == 1) { + vortex_connection_mixin_mix(vortex, en, MIX_CAPT(1), mix, 0); + vortex_connection_src_adbdma(vortex, en, dma*2, src0, dma); } else { - vortex_connection_src_adbdma(vortex, en, n, n, adbdma); - vortex_connection_mixin_mix(vortex, en, MIX_INR, n, 0); + mix = vortex_adb_checkinout(vortex, dma, en, VORTEX_RESOURCE_MIXOUT); + src1 = vortex_adb_checkinout(vortex, dma, en, VORTEX_RESOURCE_SRC); + vortex_connection_mixin_mix(vortex, en, MIX_CAPT(1), mix, 0); + vortex_connection_mix_src(vortex, en, 0x11, mix, src1); + vortex_connection_src_src_adbdma(vortex, en, dma*2, src0, src1, dma); } } - if (nr_ch == 2) { - if (dma->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - vortex_connection_src_mixin(vortex, en, 0x11, n+1, n+1); - vortex_connection_mixin_mix(vortex, en, n+1, MIX_OUTR, 0); - vortex_connection_adbdma_src_src(vortex, en, n, adbdma, n, n+1); - } else { - vortex_connection_mixin_mix(vortex, en, MIX_INR, n+1, 0); - vortex_mix_setvolumebyte(vortex, n+1, MIX_DEFOGAIN); - vortex_mix_setinputvolumebyte(vortex, n+1, MIX_INR, MIX_DEFIGAIN); - vortex_connection_mix_src(vortex, en, 0x11, n+1, n+1); - vortex_connection_src_src_adbdma(vortex, en, n, n, n+1, adbdma); - } + vortex->dma_adb[dma].nr_ch = nr_ch; + spin_unlock(vortex->lock); + + if (en) { + printk(KERN_INFO "vortex: alloc %d\n", dma); + //vortex_fifo_adbinitialize(vortex, dma, 0); + udelay(2000); + } else { + printk(KERN_INFO "vortex: de alloc %d\n", dma); + //vortex_fifo_setadbvalid(vortex, dma, 0); } - return 0; + /* AC97 Codec channel setup. FIXME: this has no effect !! */ + if (nr_ch < 4) { + /* Copy stereo to rear channel (surround) */ + snd_ac97_write_cache(vortex->codec, AC97_SIGMATEL_DAC2INVERT, snd_ac97_read(vortex->codec, AC97_SIGMATEL_DAC2INVERT) | 4); + } else { + /* Allow separate front a rear channels. */ + snd_ac97_write_cache(vortex->codec, AC97_SIGMATEL_DAC2INVERT, snd_ac97_read(vortex->codec, AC97_SIGMATEL_DAC2INVERT) & ~((u32)4)); + } + + return dma; } - +/* + Set the SampleRate of the SRC's attached to the given DMA engine. + */ void vortex_adb_setsrc(vortex_t *vortex, int adbdma, unsigned int rate, int dir) { - dma_t *dma = &(vortex->dma_adb[adbdma]); + stream_t *stream = &(vortex->dma_adb[adbdma]); int i, cvrt; /* dir=1:play ; dir=0:rec*/ if (dir) cvrt = SRC_RATIO(rate); else - cvrt = SRC_RATIO2(rate); - for (i=0; i<(dma->nr_ch); i++) { - vortex_src_setupchannel(vortex, i+((dma->dma)*2),cvrt,0,0,((dma->dma)*2)+(dma->nr_ch)-1, + cvrt = SRC_RATIO2(rate); + for (i=0; iresources[VORTEX_RESOURCE_SRC] & (1<nr_ch); i++) { + vortex_src_setupchannel(vortex, i+((adbdma)*2),cvrt,0,0,((adbdma)*2)+(dma->nr_ch)-1, dir, 0, cvrt, dir); } + */ } // WT routing is still a mistery. -int vortex_wt_waveroute(vortex_t *vortex, int wtdma, int nr_ch) { +int vortex_wt_allocroute(vortex_t *vortex, int dma, int nr_ch) { //FIXME: WT audio routing. if (nr_ch) { - vortex_fifo_wtinitialize(vortex, wtdma, 1); - vortex_wt_setstereo(vortex, wtdma, nr_ch-1); + vortex_fifo_wtinitialize(vortex, dma, 1); + vortex_wt_setstereo(vortex, dma, nr_ch-1); } else - vortex_fifo_setwtvalid(vortex, wtdma, 0); + vortex_fifo_setwtvalid(vortex, dma, 0); return 0; } @@ -1898,7 +1968,7 @@ for(i =0; i<32; i++){ hwwrite(vortex->mmio,(VORTEX_CODEC_CHN+(i<<2)),0); - udelay(5000); + udelay(2000); } if (0) { hwwrite(vortex->mmio,VORTEX_CODEC_CTRL,0x8068); @@ -1925,7 +1995,7 @@ hwwrite(vortex->mmio,VORTEX_CODEC_CTRL,0xe8); udelay(1000); /* Enable codec channels 0 and 1. */ - hwwrite(vortex->mmio,VORTEX_CODEC_EN, hwread(vortex->mmio,VORTEX_CODEC_EN) | 0x300); + hwwrite(vortex->mmio,VORTEX_CODEC_EN, hwread(vortex->mmio,VORTEX_CODEC_EN) | EN_CODEC); } void vortex_codec_write(ac97_t *codec, unsigned short addr, unsigned short data){ @@ -1941,26 +2011,26 @@ udelay(100); if (lifeboat++ > POLL_COUNT) { printk(KERN_ERR "vortex: ac97 codec stuck busy\n"); + spin_unlock_irqrestore(&card->lock, flags); return; } } - /* write register */ hwwrite(card->mmio, VORTEX_CODEC_IO, ((addr << VORTEX_CODEC_ADDSHIFT) & VORTEX_CODEC_ADDMASK) | - ((data << VORTEX_CODEC_DATSHIFT) & VORTEX_CODEC_DATMASK) | - VORTEX_CODEC_WRITE); - + ((data << VORTEX_CODEC_DATSHIFT) & VORTEX_CODEC_DATMASK) | VORTEX_CODEC_WRITE); + /* this is necessary to flush the write */ + lifeboat = 0; while (!(hwread(card->mmio, VORTEX_CODEC_CTRL) & 0x100)) { udelay(100); if (lifeboat++ > POLL_COUNT) { printk(KERN_ERR "vortex: ac97 codec stuck busy\n"); + spin_unlock_irqrestore(&card->lock, flags); return; } } read_addr = ((addr << VORTEX_CODEC_ADDSHIFT) & VORTEX_CODEC_ADDMASK); hwwrite(card->mmio, VORTEX_CODEC_IO, read_addr); - spin_unlock_irqrestore(&card->lock, flags); } @@ -1979,10 +2049,10 @@ udelay(100); if (lifeboat++ > POLL_COUNT) { printk(KERN_ERR "vortex: ac97 codec stuck busy\n"); + spin_unlock_irqrestore(&card->lock, flags); return 0xffff; } - } - + } /* set up read address */ read_addr = ((addr << VORTEX_CODEC_ADDSHIFT) & VORTEX_CODEC_ADDMASK); hwwrite(card->mmio, VORTEX_CODEC_IO, read_addr); @@ -1993,14 +2063,14 @@ udelay(100); if (lifeboat++ > POLL_COUNT) { printk(KERN_ERR "vortex: ac97 address never arrived\n"); + spin_unlock_irqrestore(&card->lock, flags); return 0xffff; } } - /* read codec */ x = hwread(card->mmio, VORTEX_CODEC_IO) & VORTEX_CODEC_DATMASK; - spin_unlock_irqrestore(&card->lock, flags); + return x; } @@ -2053,7 +2123,6 @@ #ifndef CHIP_AU8820 vortex_eq_free(vortex); #endif - printk(KERN_INFO "eq down..."); vortex_disable_timer_int(vortex); vortex_disable_int(vortex); vortex_connect_default(vortex, 0); diff -Naur alsa-orig/pci/au88x0/au88x0_mixer.c alsa-resman/pci/au88x0/au88x0_mixer.c --- alsa-orig/pci/au88x0/au88x0_mixer.c 2003-06-15 21:39:00.000000000 -0400 +++ alsa-resman/pci/au88x0/au88x0_mixer.c 2003-07-09 17:22:50.000000000 -0400 @@ -13,11 +13,12 @@ int __devinit snd_vortex_mixer(vortex_t *vortex) { ac97_t ac97; + memset(&ac97, 0, sizeof(ac97)); // Intialize AC97 codec stuff. ac97.write = vortex_codec_write; ac97.read = vortex_codec_read; ac97.private_data = vortex; - - return snd_ac97_mixer(vortex->card, &ac97, &vortex->codec); + + return snd_ac97_mixer(vortex->card, &ac97, &vortex->codec); } diff -Naur alsa-orig/pci/au88x0/au88x0_pcm.c alsa-resman/pci/au88x0/au88x0_pcm.c --- alsa-orig/pci/au88x0/au88x0_pcm.c 2003-07-03 00:40:02.000000000 -0400 +++ alsa-resman/pci/au88x0/au88x0_pcm.c 2003-07-09 17:22:50.000000000 -0400 @@ -27,9 +27,9 @@ .rate_min = 5000, .rate_max = 48000, .channels_min = 1, - .channels_max = 2, + .channels_max = 4, .buffer_bytes_max = 0x10000, - .period_bytes_min = 0x0100, + .period_bytes_min = 0x0080, .period_bytes_max = 0x1000, .periods_min = 1, .periods_max = 64, @@ -56,7 +56,7 @@ static int snd_vortex_pcm_open(snd_pcm_substream_t *substream) { chip_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; - int dma, err; + int err; /* Force equal size periods */ if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) @@ -67,18 +67,10 @@ if (substream->pcm == chip->pcm_adb) { runtime->hw = snd_vortex_playback_hw_adb; - dma = vortex_getadb(chip); - if (dma < 0) - return -EBUSY; - substream->runtime->private_data = &chip->dma_adb[dma]; - chip->dma_adb[dma].substream = substream; + substream->runtime->private_data = NULL; } else { runtime->hw = snd_vortex_playback_hw_wt; - dma = vortex_getwt(chip); - if (dma < 0) - return -EBUSY; - substream->runtime->private_data = &chip->dma_wt[dma]; - chip->dma_wt[dma].substream = substream; + substream->runtime->private_data = NULL; } return 0; } @@ -86,12 +78,13 @@ /* close callback */ static int snd_vortex_pcm_close(snd_pcm_substream_t *substream) { //vortex_t *chip = snd_pcm_substream_chip(substream); - dma_t *dma = (dma_t*)substream->runtime->private_data; - + stream_t *stream = (stream_t*)substream->runtime->private_data; + // the hardware-specific codes will be here - // Dealloc DMA and remove audio route. - dma->substream = NULL; - dma->nr_ch = 0; + if (stream != NULL) { + stream->substream = NULL; + stream->nr_ch = 0; + } substream->runtime->private_data = NULL; return 0; } @@ -100,8 +93,7 @@ static int snd_vortex_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *hw_params) { chip_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; - dma_t *dma = (dma_t*)substream->runtime->private_data; - + stream_t *stream = (stream_t*)(substream->runtime->private_data); int err; // Alloc buffer memory. @@ -113,23 +105,26 @@ printk(KERN_INFO "Vortex: periods %d, period_bytes %d, channels = %d\n", params_periods(hw_params), params_period_bytes(hw_params), params_channels(hw_params)); - - if (params_buffer_bytes(hw_params) != (params_periods(hw_params)*params_period_bytes(hw_params))) - printk(KERN_INFO "vortex: Warning: Click condition (non integer period count).\n"); // Make audio routes and config buffer DMA. if (substream->pcm == chip->pcm_adb) { - vortex_adbdma_setbuffers(chip, dma->dma, (u32)(runtime->dma_addr), params_period_bytes(hw_params), params_periods(hw_params)); - //if (dma->nr_ch != 0) - vortex_adb_waveroute(chip, dma->dma, 0); - //if (params_channels(hw_params) != 0) - vortex_adb_waveroute(chip, dma->dma, params_channels(hw_params)); + int dma; + /* Dealloc any routes. */ + if (stream != NULL) + vortex_adb_allocroute(chip, stream->dma, stream->nr_ch, stream->dir); + /* Alloc routes. */ + dma = vortex_adb_allocroute(chip, -1, params_channels(hw_params), substream->stream); + stream = substream->runtime->private_data = &chip->dma_adb[dma]; + stream->substream = substream; + /* Setup Buffers. */ + vortex_adbdma_setbuffers(chip, dma, (u32)(runtime->dma_addr), params_period_bytes(hw_params), params_periods(hw_params)); } else { - vortex_wtdma_setbuffers(chip, dma->dma, (u32)(runtime->dma_addr), params_period_bytes(hw_params), params_periods(hw_params)); - if (dma->nr_ch) - vortex_wt_waveroute(chip, dma->dma, 0); - if (params_channels(hw_params)) - vortex_wt_waveroute(chip, dma->dma, params_channels(hw_params)); + if (stream != NULL) + vortex_wt_allocroute(chip, substream->number, 0); + vortex_wt_allocroute(chip, substream->number, params_channels(hw_params)); + stream = substream->runtime->private_data = &chip->dma_wt[substream->number]; + stream->substream = substream; + vortex_wtdma_setbuffers(chip, substream->number, (u32)(runtime->dma_addr), params_period_bytes(hw_params), params_periods(hw_params)); } return 0; } @@ -137,13 +132,17 @@ /* hw_free callback */ static int snd_vortex_pcm_hw_free(snd_pcm_substream_t *substream) { chip_t *chip = snd_pcm_substream_chip(substream); - dma_t *dma = (dma_t*)substream->runtime->private_data; - + stream_t *stream = (stream_t*)(substream->runtime->private_data); + // Delete audio routes. - if (substream->pcm == chip->pcm_adb) - vortex_adb_waveroute(chip, dma->dma, 0); - else - vortex_wt_waveroute(chip, dma->dma, 0); + if (substream->pcm == chip->pcm_adb) { + if (stream != NULL) + vortex_adb_allocroute(chip, stream->dma, stream->nr_ch, stream->dir); + } else { + if (stream != NULL) + vortex_wt_allocroute(chip, stream->dma, 0); + } + substream->runtime->private_data = NULL; return snd_pcm_lib_free_pages(substream); } @@ -152,8 +151,8 @@ static int snd_vortex_pcm_prepare(snd_pcm_substream_t *substream) { vortex_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; - dma_t *dma = (dma_t*)substream->runtime->private_data; - int fmt, dir; + stream_t *stream = (stream_t*)substream->runtime->private_data; + int dma = stream->dma, fmt, dir; // set up the hardware with the current configuration. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -162,13 +161,13 @@ dir = 0; fmt = vortex_alsafmt_aspfmt(runtime->format); if (substream->pcm == chip->pcm_adb) { - vortex_adbdma_setmode(chip, dma->dma, 1, dir, fmt, 0/*?*/, 0); - vortex_adbdma_setstartbuffer(chip, dma->dma, 0); - vortex_adb_setsrc(chip, dma->dma, runtime->rate, dir); + vortex_adbdma_setmode(chip, dma, 1, dir, fmt, 0/*?*/, 0); + vortex_adbdma_setstartbuffer(chip, dma, 0); + vortex_adb_setsrc(chip, dma, runtime->rate, dir); } else { - vortex_wtdma_setmode(chip, dma->dma, 1, dir, fmt, 0, 0); + vortex_wtdma_setmode(chip, dma, 1, dir, fmt, 0, 0); // FIXME: Set rate (i guess using vortex_wt_writereg() somehow). - vortex_wtdma_setstartbuffer(chip, dma->dma, 0); + vortex_wtdma_setstartbuffer(chip, dma, 0); } return 0; } @@ -176,45 +175,46 @@ /* trigger callback */ static int snd_vortex_pcm_trigger(snd_pcm_substream_t *substream, int cmd) { chip_t *chip = snd_pcm_substream_chip(substream); - dma_t *dma = (dma_t*)substream->runtime->private_data; - + stream_t *stream = (stream_t*)substream->runtime->private_data; + int dma = stream->dma; + switch (cmd) { case SNDRV_PCM_TRIGGER_START: // do something to start the PCM engine - printk(KERN_INFO "vortex: start %d\n", dma->dma); + printk(KERN_INFO "vortex: start %d\n", dma); if (substream->pcm == chip->pcm_adb) { - dma->fifo_enabled = 1; - vortex_adbdma_startfifo(chip, dma->dma); + stream->fifo_enabled = 1; + vortex_adbdma_startfifo(chip, dma); } else { - dma->fifo_enabled = 1; - vortex_wtdma_startfifo(chip, dma->dma); + stream->fifo_enabled = 1; + vortex_wtdma_startfifo(chip, dma); } break; case SNDRV_PCM_TRIGGER_STOP: // do something to stop the PCM engine - printk(KERN_INFO "vortex: stop %d\n", dma->dma); + printk(KERN_INFO "vortex: stop %d\n", dma); if (substream->pcm == chip->pcm_adb) { - dma->fifo_enabled = 0; - vortex_adbdma_stopfifo(chip, dma->dma); + stream->fifo_enabled = 0; + vortex_adbdma_stopfifo(chip, dma); } else { - dma->fifo_enabled = 0; - vortex_wtdma_stopfifo(chip, dma->dma); + stream->fifo_enabled = 0; + vortex_wtdma_stopfifo(chip, dma); } break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - printk(KERN_INFO "vortex: pause %d\n", dma->dma); + printk(KERN_INFO "vortex: pause %d\n", dma); if (substream->pcm == chip->pcm_adb) - vortex_adbdma_pausefifo(chip, dma->dma); + vortex_adbdma_pausefifo(chip, dma); else - vortex_wtdma_pausefifo(chip, dma->dma); + vortex_wtdma_pausefifo(chip, dma); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - printk(KERN_INFO "vortex: resume %d\n", dma->dma); + printk(KERN_INFO "vortex: resume %d\n", dma); if (substream->pcm == chip->pcm_adb) - vortex_adbdma_resumefifo(chip, dma->dma); + vortex_adbdma_resumefifo(chip, dma); else - vortex_wtdma_resumefifo(chip, dma->dma); + vortex_wtdma_resumefifo(chip, dma); break; default: return -EINVAL; @@ -225,14 +225,15 @@ /* pointer callback */ static snd_pcm_uframes_t snd_vortex_pcm_pointer(snd_pcm_substream_t *substream) { vortex_t *chip = snd_pcm_substream_chip(substream); + stream_t *stream = (stream_t*)substream->runtime->private_data; + int dma = stream->dma; snd_pcm_uframes_t current_ptr = 0; - dma_t *dma = (dma_t*)substream->runtime->private_data; spin_lock(chip->lock); if (substream->pcm == chip->pcm_adb) - current_ptr = vortex_adbdma_getlinearpos(chip, dma->dma); + current_ptr = vortex_adbdma_getlinearpos(chip, dma); else - current_ptr = vortex_wtdma_getlinearpos(chip, dma->dma); + current_ptr = vortex_wtdma_getlinearpos(chip, dma); //printk(KERN_INFO "vortex: pointer = 0x%x\n", current_ptr); spin_unlock(chip->lock); return (bytes_to_frames(substream->runtime, current_ptr));