[ALSA] snd-emu10k1: Add support for E-Mu 1616 PCI, 1616M PCI, 0404 PCI, E-Mu

Notebook.
Description: The .device=0x0008 chips have new, but different EMU32 in/out
channels. Driver updated to make use of these EMU32 channels.

Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
This commit is contained in:
James Courtier-Dutton 2007-07-23 14:01:46 +01:00 committed by Jaroslav Kysela
parent 25765c4e5d
commit 90fd5ce5f6
3 changed files with 132 additions and 108 deletions

View File

@ -1746,6 +1746,8 @@ int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu,
#define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */ #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_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_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
#define A3_EMU32IN(x) (0x160 + (x)) /* x = 0x00 - 0x3f "EMU32_IN_00 - _3F" - Only when .device = 0x0008 */
#define A3_EMU32OUT(x) (0x1E0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_00 - _3F" - Only when .device = 0x0008 */
#define A_GPR(x) (A_FXGPREGBASE + (x)) #define A_GPR(x) (A_FXGPREGBASE + (x))
/* cc_reg constants */ /* cc_reg constants */

View File

@ -1207,7 +1207,7 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT)); A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT));
snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100); snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100);
gpr += 2; gpr += 2;
/* PCM Surround Playback (independent from stereo mix) */ /* PCM Surround Playback (independent from stereo mix) */
A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR)); A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR));
A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR)); A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR));
@ -1267,8 +1267,16 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
/* emu1212 DSP 0 and DSP 1 Capture */ /* emu1212 DSP 0 and DSP 1 Capture */
if (emu->card_capabilities->emu1010) { if (emu->card_capabilities->emu1010) {
A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0)); if (emu->card_capabilities->ca0108_chip) {
A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1)); /* Note:JCD:No longer bit shift lower 16bits to upper 16bits of 32bit value. */
A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x0), A_C_00000001);
A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_GPR(tmp));
A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x1), A_C_00000001);
A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr), A_GPR(tmp));
} else {
A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0));
A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1));
}
snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0); snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0);
gpr += 2; gpr += 2;
} }
@ -1516,7 +1524,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
/* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */ /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */
snd_printk("EMU outputs on\n"); snd_printk("EMU outputs on\n");
for (z = 0; z < 8; z++) { for (z = 0; z < 8; z++) {
A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); if (emu->card_capabilities->ca0108_chip) {
A_OP(icode, &ptr, iACC3, A3_EMU32OUT(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000);
} else {
A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000);
}
} }
} }
@ -1557,106 +1569,116 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
#endif #endif
if (emu->card_capabilities->emu1010) { if (emu->card_capabilities->emu1010) {
snd_printk("EMU inputs on\n"); if (emu->card_capabilities->ca0108_chip) {
/* Capture 16 (originally 8) channels of S32_LE sound */ snd_printk("EMU2 inputs on\n");
for (z = 0; z < 0x10; z++) {
/* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp,
/* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ bit_shifter16,
/* A_P16VIN(0) is delayed by one sample, A3_EMU32IN(z),
* so all other A_P16VIN channels will need to also be delayed A_FXBUS2(z*2) );
*/ }
/* Left ADC in. 1 of 2 */ } else {
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) ); snd_printk("EMU inputs on\n");
/* Right ADC in 1 of 2 */ /* Capture 16 (originally 8) channels of S32_LE sound */
gpr_map[gpr++] = 0x00000000;
/* Delaying by one sample: instead of copying the input /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */
* value A_P16VIN to output A_FXBUS2 as in the first channel, /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */
* we use an auxiliary register, delaying the value by one /* A_P16VIN(0) is delayed by one sample,
* sample * so all other A_P16VIN channels will need to also be delayed
*/ */
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) ); /* Left ADC in. 1 of 2 */
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000); snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) );
gpr_map[gpr++] = 0x00000000; /* Right ADC in 1 of 2 */
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) ); gpr_map[gpr++] = 0x00000000;
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000); /* Delaying by one sample: instead of copying the input
gpr_map[gpr++] = 0x00000000; * value A_P16VIN to output A_FXBUS2 as in the first channel,
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) ); * we use an auxiliary register, delaying the value by one
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000); * sample
/* For 96kHz mode */ */
/* Left ADC in. 2 of 2 */ snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) );
gpr_map[gpr++] = 0x00000000; A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000);
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) ); gpr_map[gpr++] = 0x00000000;
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000); snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) );
/* Right ADC in 2 of 2 */ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000);
gpr_map[gpr++] = 0x00000000; gpr_map[gpr++] = 0x00000000;
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) ); snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) );
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000); A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000);
gpr_map[gpr++] = 0x00000000; /* For 96kHz mode */
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) ); /* Left ADC in. 2 of 2 */
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000); gpr_map[gpr++] = 0x00000000;
gpr_map[gpr++] = 0x00000000; snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) );
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) ); A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000);
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000); /* Right ADC in 2 of 2 */
/* Pavel Hofman - we still have voices, A_FXBUS2s, and gpr_map[gpr++] = 0x00000000;
* A_P16VINs available - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) );
* let's add 8 more capture channels - total of 16 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000);
*/ gpr_map[gpr++] = 0x00000000;
gpr_map[gpr++] = 0x00000000; snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) );
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000);
bit_shifter16, gpr_map[gpr++] = 0x00000000;
A_GPR(gpr - 1), snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) );
A_FXBUS2(0x10)); A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000);
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8), /* Pavel Hofman - we still have voices, A_FXBUS2s, and
A_C_00000000, A_C_00000000); * A_P16VINs available -
gpr_map[gpr++] = 0x00000000; * let's add 8 more capture channels - total of 16
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, */
bit_shifter16, gpr_map[gpr++] = 0x00000000;
A_GPR(gpr - 1), snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
A_FXBUS2(0x12)); bit_shifter16,
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9), A_GPR(gpr - 1),
A_C_00000000, A_C_00000000); A_FXBUS2(0x10));
gpr_map[gpr++] = 0x00000000; A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8),
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, A_C_00000000, A_C_00000000);
bit_shifter16, gpr_map[gpr++] = 0x00000000;
A_GPR(gpr - 1), snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
A_FXBUS2(0x14)); bit_shifter16,
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa), A_GPR(gpr - 1),
A_C_00000000, A_C_00000000); A_FXBUS2(0x12));
gpr_map[gpr++] = 0x00000000; A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9),
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, A_C_00000000, A_C_00000000);
bit_shifter16, gpr_map[gpr++] = 0x00000000;
A_GPR(gpr - 1), snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
A_FXBUS2(0x16)); bit_shifter16,
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb), A_GPR(gpr - 1),
A_C_00000000, A_C_00000000); A_FXBUS2(0x14));
gpr_map[gpr++] = 0x00000000; A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa),
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, A_C_00000000, A_C_00000000);
bit_shifter16, gpr_map[gpr++] = 0x00000000;
A_GPR(gpr - 1), snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
A_FXBUS2(0x18)); bit_shifter16,
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc), A_GPR(gpr - 1),
A_C_00000000, A_C_00000000); A_FXBUS2(0x16));
gpr_map[gpr++] = 0x00000000; A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb),
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, A_C_00000000, A_C_00000000);
bit_shifter16, gpr_map[gpr++] = 0x00000000;
A_GPR(gpr - 1), snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
A_FXBUS2(0x1a)); bit_shifter16,
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd), A_GPR(gpr - 1),
A_C_00000000, A_C_00000000); A_FXBUS2(0x18));
gpr_map[gpr++] = 0x00000000; A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc),
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, A_C_00000000, A_C_00000000);
bit_shifter16, gpr_map[gpr++] = 0x00000000;
A_GPR(gpr - 1), snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
A_FXBUS2(0x1c)); bit_shifter16,
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe), A_GPR(gpr - 1),
A_C_00000000, A_C_00000000); A_FXBUS2(0x1a));
gpr_map[gpr++] = 0x00000000; A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd),
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, A_C_00000000, A_C_00000000);
bit_shifter16, gpr_map[gpr++] = 0x00000000;
A_GPR(gpr - 1), snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
A_FXBUS2(0x1e)); bit_shifter16,
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf), A_GPR(gpr - 1),
A_C_00000000, A_C_00000000); A_FXBUS2(0x1c));
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe),
A_C_00000000, A_C_00000000);
gpr_map[gpr++] = 0x00000000;
snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
bit_shifter16,
A_GPR(gpr - 1),
A_FXBUS2(0x1e));
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf),
A_C_00000000, A_C_00000000);
}
#if 0 #if 0
for (z = 4; z < 8; z++) { for (z = 4; z < 8; z++) {

View File

@ -385,7 +385,7 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
int i; int i;
snd_iprintf(buffer, "EMU1010 Registers:\n\n"); snd_iprintf(buffer, "EMU1010 Registers:\n\n");
for(i = 0; i < 0x30; i+=1) { for(i = 0; i < 0x40; i+=1) {
spin_lock_irqsave(&emu->emu_lock, flags); spin_lock_irqsave(&emu->emu_lock, flags);
regs=i+0x40; /* 0x40 upwards are registers. */ regs=i+0x40; /* 0x40 upwards are registers. */
outl(regs, emu->port + A_IOCFG); outl(regs, emu->port + A_IOCFG);
@ -555,9 +555,9 @@ int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu)
{ {
struct snd_info_entry *entry; struct snd_info_entry *entry;
#ifdef CONFIG_SND_DEBUG #ifdef CONFIG_SND_DEBUG
if ((emu->card_capabilities->emu1010) && if (emu->card_capabilities->emu1010) {
snd_card_proc_new(emu->card, "emu1010_regs", &entry)) { if (! snd_card_proc_new(emu->card, "emu1010_regs", &entry))
snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read); snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read);
} }
if (! snd_card_proc_new(emu->card, "io_regs", &entry)) { if (! snd_card_proc_new(emu->card, "io_regs", &entry)) {
snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read); snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read);