Commit 8fdee9cf authored by Jaroslav Kysela's avatar Jaroslav Kysela

[ALSA] capture EXTINs with multichannel device

EMU10K1/EMU10K2 driver
This patch changes the emu10k1 multichannel capture device (hw:x,2) to
capture the 16 external inputs by default.  This involves adding DSP
code to route the EXTINs to the FXBUS2 (EFX capture) channels and
setting the corresponding FXWC bits by default.

This allows capturing multiple inputs simultaneously.  It completely
bypasses the capture controls of the mixer.  With my Audigy2 ZS I can
capture LineIn, Line2, and Aux2 at the same time (6 channels).
Signed-off-by: default avatarLee Revell <rlrevell@joe-job.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 02f36592
...@@ -1112,7 +1112,10 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu, ...@@ -1112,7 +1112,10 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
/* GPRs */ /* GPRs */
#define FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x0f */ #define FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x0f */
#define EXTIN(x) (0x10 + (x)) /* x = 0x00 - 0x0f */ #define EXTIN(x) (0x10 + (x)) /* x = 0x00 - 0x0f */
#define EXTOUT(x) (0x20 + (x)) /* x = 0x00 - 0x0f */ #define EXTOUT(x) (0x20 + (x)) /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */
#define FXBUS2(x) (0x30 + (x)) /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */
/* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */
#define C_00000000 0x40 #define C_00000000 0x40
#define C_00000001 0x41 #define C_00000001 0x41
#define C_00000002 0x42 #define C_00000002 0x42
...@@ -1154,9 +1157,13 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu, ...@@ -1154,9 +1157,13 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
#define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */ #define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
#define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */ #define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
#define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f? */ #define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f FX buses */
#define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x1f? */ #define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x0f physical ins */
#define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f? */ #define A_P16VIN(x) (0x50 + (x)) /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */
#define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown */
#define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */
#define A_EMU32OUTH(x) (0xa0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */
#define A_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
#define A_GPR(x) (A_FXGPREGBASE + (x)) #define A_GPR(x) (A_FXGPREGBASE + (x))
/* cc_reg constants */ /* cc_reg constants */
......
...@@ -1358,6 +1358,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) ...@@ -1358,6 +1358,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1); A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1);
#endif #endif
/* EFX capture - capture the 16 EXTINs */
for (z = 0; z < 16; z++) {
A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
}
/* /*
* ok, set up done.. * ok, set up done..
*/ */
...@@ -1930,6 +1935,24 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu) ...@@ -1930,6 +1935,24 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
if (emu->fx8010.extout_mask & (1<<EXTOUT_MIC_CAP)) if (emu->fx8010.extout_mask & (1<<EXTOUT_MIC_CAP))
OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000); OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000);
/* EFX capture - capture the 16 EXTINS */
OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
/* Dont connect anything to FXBUS2 1 and 2. These are shared with
* Center/LFE on the SBLive 5.1. The kX driver only changes the
* routing when it detects an SBLive 5.1.
*
* Since only 14 of the 16 EXTINs are used, this is not a big problem.
* We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture
* 0 and 3, then the rest of the EXTINs to the corresponding FX capture
* channel.
*/
for (z = 4; z < 14; z++) {
OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
}
if (gpr > tmp) { if (gpr > tmp) {
snd_BUG(); snd_BUG();
err = -EIO; err = -EIO;
......
...@@ -1390,8 +1390,18 @@ int __devinit snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm ...@@ -1390,8 +1390,18 @@ int __devinit snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm
if (rpcm) if (rpcm)
*rpcm = pcm; *rpcm = pcm;
emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; /* EFX capture - record the "FXBUS2" channels, by default we connect the EXTINs
emu->efx_voices_mask[1] = 0; * to these
*/
/* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */
if (emu->audigy) {
emu->efx_voices_mask[0] = 0;
emu->efx_voices_mask[1] = 0xffff;
} else {
emu->efx_voices_mask[0] = 0xffff;
emu->efx_voices_mask[1] = 0;
}
snd_ctl_add(emu->card, snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu)); snd_ctl_add(emu->card, snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu));
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment