📄 emufx.c
字号:
kfree(icode->gpr_map); kfree(icode); } return err;}/* * initial DSP configuration for Emu10k1 *//* when volume = max, then copy only to avoid volume modification *//* with iMAC0 (negative values) */static void __devinit _volume(emu10k1_fx8010_code_t *icode, u32 *ptr, u32 dst, u32 src, u32 vol){ OP(icode, ptr, iMAC0, dst, C_00000000, src, vol); OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff); OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000001); OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000);}static void __devinit _volume_add(emu10k1_fx8010_code_t *icode, u32 *ptr, u32 dst, u32 src, u32 vol){ OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff); OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002); OP(icode, ptr, iMACINT0, dst, dst, src, C_00000001); OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001); OP(icode, ptr, iMAC0, dst, dst, src, vol);}static void __devinit _volume_out(emu10k1_fx8010_code_t *icode, u32 *ptr, u32 dst, u32 src, u32 vol){ OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff); OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002); OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000); OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001); OP(icode, ptr, iMAC0, dst, C_00000000, src, vol);}#define VOLUME(icode, ptr, dst, src, vol) \ _volume(icode, ptr, GPR(dst), GPR(src), GPR(vol))#define VOLUME_IN(icode, ptr, dst, src, vol) \ _volume(icode, ptr, GPR(dst), EXTIN(src), GPR(vol))#define VOLUME_ADD(icode, ptr, dst, src, vol) \ _volume_add(icode, ptr, GPR(dst), GPR(src), GPR(vol))#define VOLUME_ADDIN(icode, ptr, dst, src, vol) \ _volume_add(icode, ptr, GPR(dst), EXTIN(src), GPR(vol))#define VOLUME_OUT(icode, ptr, dst, src, vol) \ _volume_out(icode, ptr, EXTOUT(dst), GPR(src), GPR(vol))#define _SWITCH(icode, ptr, dst, src, sw) \ OP((icode), ptr, iMACINT0, dst, C_00000000, src, sw);#define SWITCH(icode, ptr, dst, src, sw) \ _SWITCH(icode, ptr, GPR(dst), GPR(src), GPR(sw))#define SWITCH_IN(icode, ptr, dst, src, sw) \ _SWITCH(icode, ptr, GPR(dst), EXTIN(src), GPR(sw))#define _SWITCH_NEG(icode, ptr, dst, src) \ OP((icode), ptr, iANDXOR, dst, src, C_00000001, C_00000001);#define SWITCH_NEG(icode, ptr, dst, src) \ _SWITCH_NEG(icode, ptr, GPR(dst), GPR(src))static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu){ int err, i, z, gpr, tmp, playback, capture; u32 ptr; emu10k1_fx8010_code_t *icode; emu10k1_fx8010_pcm_t *ipcm = NULL; emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl; mm_segment_t seg; spin_lock_init(&emu->fx8010.irq_lock); INIT_LIST_HEAD(&emu->fx8010.gpr_ctl); if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL) return -ENOMEM; if ((icode->gpr_map = kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t), GFP_KERNEL)) == NULL || (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(emu10k1_fx8010_control_gpr_t), GFP_KERNEL)) == NULL || (ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL)) == NULL) { err = -ENOMEM; goto __err; } icode->tram_data_map = icode->gpr_map + 256; icode->tram_addr_map = icode->tram_data_map + 160; icode->code = icode->tram_addr_map + 160; /* clear free GPRs */ for (i = 0; i < 256; i++) set_bit(i, icode->gpr_valid); /* clear TRAM data & address lines */ for (i = 0; i < 160; i++) set_bit(i, icode->tram_valid); strcpy(icode->name, "SB Live! FX8010 code for ALSA v1.2 by Jaroslav Kysela"); ptr = 0; i = 0; /* we have 10 inputs */ playback = SND_EMU10K1_INPUTS; /* we have 6 playback channels and tone control doubles */ capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); gpr = capture + SND_EMU10K1_CAPTURE_CHANNELS; tmp = 0x88; /* we need 4 temporary GPR */ /* from 0x8c to 0xff is the area for tone control */ /* stop FX processor */ snd_emu10k1_ptr_write(emu, DBG, 0, (emu->fx8010.dbg = 0) | EMU10K1_DBG_SINGLE_STEP); /* * Process FX Buses */ OP(icode, &ptr, iMACINT0, GPR(0), C_00000000, FXBUS(FXBUS_PCM_LEFT), C_00000004); OP(icode, &ptr, iMACINT0, GPR(1), C_00000000, FXBUS(FXBUS_PCM_RIGHT), C_00000004); OP(icode, &ptr, iMACINT0, GPR(2), C_00000000, FXBUS(FXBUS_MIDI_LEFT), C_00000004); OP(icode, &ptr, iMACINT0, GPR(3), C_00000000, FXBUS(FXBUS_MIDI_RIGHT), C_00000004); OP(icode, &ptr, iMACINT0, GPR(4), C_00000000, FXBUS(FXBUS_PCM_LEFT_REAR), C_00000004); OP(icode, &ptr, iMACINT0, GPR(5), C_00000000, FXBUS(FXBUS_PCM_RIGHT_REAR), C_00000004); OP(icode, &ptr, iMACINT0, GPR(6), C_00000000, FXBUS(FXBUS_PCM_CENTER), C_00000004); OP(icode, &ptr, iMACINT0, GPR(7), C_00000000, FXBUS(FXBUS_PCM_LFE), C_00000004); OP(icode, &ptr, iMACINT0, GPR(8), C_00000000, C_00000000, C_00000000); /* S/PDIF left */ OP(icode, &ptr, iMACINT0, GPR(9), C_00000000, C_00000000, C_00000000); /* S/PDIF right */ /* Raw S/PDIF PCM */ ipcm->substream = 0; ipcm->channels = 2; ipcm->tram_start = 0; ipcm->buffer_size = (64 * 1024) / 2; ipcm->gpr_size = gpr++; ipcm->gpr_ptr = gpr++; ipcm->gpr_count = gpr++; ipcm->gpr_tmpcount = gpr++; ipcm->gpr_trigger = gpr++; ipcm->gpr_running = gpr++; ipcm->etram[0] = 0; ipcm->etram[1] = 1; icode->gpr_map[gpr + 0] = 0xfffff000; icode->gpr_map[gpr + 1] = 0xffff0000; icode->gpr_map[gpr + 2] = 0x70000000; icode->gpr_map[gpr + 3] = 0x00000007; icode->gpr_map[gpr + 4] = 0x001f << 11; icode->gpr_map[gpr + 5] = 0x001c << 11; icode->gpr_map[gpr + 6] = (0x22 - 0x01) - 1; /* skip at 01 to 22 */ icode->gpr_map[gpr + 7] = (0x22 - 0x06) - 1; /* skip at 06 to 22 */ icode->gpr_map[gpr + 8] = 0x2000000 + (2<<11); icode->gpr_map[gpr + 9] = 0x4000000 + (2<<11); icode->gpr_map[gpr + 10] = 1<<11; icode->gpr_map[gpr + 11] = (0x24 - 0x0a) - 1; /* skip at 0a to 24 */ icode->gpr_map[gpr + 12] = 0; /* if the trigger flag is not set, skip */ /* 00: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_trigger), C_00000000, C_00000000); /* 01: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_ZERO, GPR(gpr + 6)); /* if the running flag is set, we're running */ /* 02: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_running), C_00000000, C_00000000); /* 03: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000004); /* wait until ((GPR_DBAC>>11) & 0x1f) == 0x1c) */ /* 04: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), GPR_DBAC, GPR(gpr + 4), C_00000000); /* 05: */ OP(icode, &ptr, iMACINT0, C_00000000, GPR(tmp + 0), C_ffffffff, GPR(gpr + 5)); /* 06: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, GPR(gpr + 7)); /* 07: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), C_00000010, C_00000001, C_00000000); /* 08: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00000000, C_00000001); /* 09: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), GPR(gpr + 12), C_ffffffff, C_00000000); /* 0a: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, GPR(gpr + 11)); /* 0b: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), C_00000001, C_00000000, C_00000000); /* 0c: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), ETRAM_DATA(ipcm->etram[0]), GPR(gpr + 0), C_00000000); /* 0d: */ OP(icode, &ptr, iLOG, GPR(tmp + 0), GPR(tmp + 0), GPR(gpr + 3), C_00000000); /* 0e: */ OP(icode, &ptr, iANDXOR, GPR(8), GPR(tmp + 0), GPR(gpr + 1), GPR(gpr + 2)); /* 0f: */ OP(icode, &ptr, iSKIP, C_00000000, GPR_COND, CC_REG_MINUS, C_00000001); /* 10: */ OP(icode, &ptr, iANDXOR, GPR(8), GPR(8), GPR(gpr + 1), GPR(gpr + 2)); /* 11: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), ETRAM_DATA(ipcm->etram[1]), GPR(gpr + 0), C_00000000); /* 12: */ OP(icode, &ptr, iLOG, GPR(tmp + 0), GPR(tmp + 0), GPR(gpr + 3), C_00000000); /* 13: */ OP(icode, &ptr, iANDXOR, GPR(9), GPR(tmp + 0), GPR(gpr + 1), GPR(gpr + 2)); /* 14: */ OP(icode, &ptr, iSKIP, C_00000000, GPR_COND, CC_REG_MINUS, C_00000001); /* 15: */ OP(icode, &ptr, iANDXOR, GPR(9), GPR(9), GPR(gpr + 1), GPR(gpr + 2)); /* 16: */ OP(icode, &ptr, iACC3, GPR(tmp + 0), GPR(ipcm->gpr_ptr), C_00000001, C_00000000); /* 17: */ OP(icode, &ptr, iMACINT0, C_00000000, GPR(tmp + 0), C_ffffffff, GPR(ipcm->gpr_size)); /* 18: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_MINUS, C_00000001); /* 19: */ OP(icode, &ptr, iACC3, GPR(tmp + 0), C_00000000, C_00000000, C_00000000); /* 1a: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_ptr), GPR(tmp + 0), C_00000000, C_00000000); /* 1b: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_tmpcount), GPR(ipcm->gpr_tmpcount), C_ffffffff, C_00000000); /* 1c: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002); /* 1d: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_tmpcount), GPR(ipcm->gpr_count), C_00000000, C_00000000); /* 1e: */ OP(icode, &ptr, iACC3, GPR_IRQ, C_80000000, C_00000000, C_00000000); /* 1f: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00000001, C_00010000); /* 20: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00010000, C_00000001); /* 21: */ OP(icode, &ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000002); /* 22: */ OP(icode, &ptr, iMACINT1, ETRAM_ADDR(ipcm->etram[0]), GPR(gpr + 8), GPR_DBAC, C_ffffffff); /* 23: */ OP(icode, &ptr, iMACINT1, ETRAM_ADDR(ipcm->etram[1]), GPR(gpr + 9), GPR_DBAC, C_ffffffff); /* 24: */ gpr += 13; /* Wave Playback Volume */ for (z = 0; z < 2; z++) VOLUME(icode, &ptr, playback + z, z, gpr + z); snd_emu10k1_init_stereo_control(controls + i++, "Wave Playback Volume", gpr, 100); gpr += 2; /* Wave Surround Playback Volume */ for (z = 0; z < 2; z++) VOLUME(icode, &ptr, playback + 2 + z, z, gpr + z); snd_emu10k1_init_stereo_control(controls + i++, "Wave Surround Playback Volume", gpr, 0); gpr += 2; /* Wave Center/LFE Playback Volume */ OP(icode, &ptr, iACC3, GPR(tmp + 0), FXBUS(FXBUS_PCM_LEFT), FXBUS(FXBUS_PCM_RIGHT), C_00000000); OP(icode, &ptr, iMACINT0, GPR(tmp + 0), C_00000000, GPR(tmp + 0), C_00000002); VOLUME(icode, &ptr, playback + 4, tmp + 0, gpr); snd_emu10k1_init_mono_control(controls + i++, "Wave Center Playback Volume", gpr++, 0); VOLUME(icode, &ptr, playback + 5, tmp + 0, gpr); snd_emu10k1_init_mono_control(controls + i++, "Wave LFE Playback Volume", gpr++, 0); /* Wave Capture Volume + Switch */ for (z = 0; z < 2; z++) { SWITCH(icode, &ptr, tmp + 0, z, gpr + 2 + z); VOLUME(icode, &ptr, capture + z, tmp + 0, gpr + z); } snd_emu10k1_init_stereo_control(controls + i++, "Wave Capture Volume", gpr, 0); snd_emu10k1_init_stereo_onoff_control(controls + i++, "Wave Capture Switch", gpr + 2, 0); gpr += 4; /* Music Playback Volume */ for (z = 0; z < 2; z++) VOLUME_ADD(icode, &ptr, playback + z, 2 + z, gpr + z); snd_emu10k1_init_stereo_control(controls + i++, "Music Playback Volume", gpr, 100); gpr += 2; /* Music Capture Volume + Switch */ for (z = 0; z < 2; z++) { SWITCH(icode, &ptr, tmp + 0, 2 + z, gpr + 2 + z); VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); } snd_emu10k1_init_stereo_control(controls + i++, "Music Capture Volume", gpr, 0); snd_emu10k1_init_stereo_onoff_control(controls + i++, "Music Capture Switch", gpr + 2, 0); gpr += 4; /* Surround Digital Playback Volume (renamed later without Digital) */ for (z = 0; z < 2; z++) VOLUME_ADD(icode, &ptr, playback + 2 + z, 4 + z, gpr + z); snd_emu10k1_init_stereo_control(controls + i++, "Surround Digital Playback Volume", gpr, 100); gpr += 2; /* Surround Capture Volume + Switch */ for (z = 0; z < 2; z++) { SWITCH(icode, &ptr, tmp + 0, 4 + z, gpr + 2 + z); VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); } snd_emu10k1_init_stereo_control(controls + i++, "Surround Capture Volume", gpr, 0); snd_emu10k1_init_stereo_onoff_control(controls + i++, "Surround Capture Switch", gpr + 2, 0); gpr += 4; /* Center Playback Volume (renamed later without Digital) */ VOLUME_ADD(icode, &ptr, playback + 4, 6, gpr); snd_emu10k1_init_mono_control(controls + i++, "Center Digital Playback Volume", gpr++, 100); /* LFE Playback Volume + Switch (renamed later without Digital) */ VOLUME_ADD(icode, &ptr, playback + 5, 7, gpr); snd_emu10k1_init_mono_control(controls + i++, "LFE Digital Playback Volume", gpr++, 100); /* * Process inputs */ if (emu->fx8010.extin_mask & ((1<<EXTIN_AC97_L)|(1<<EXTIN_AC97_R))) { /* AC'97 Playback Volume */ VOLUME_ADDIN(icode, &ptr, playback + 0, EXTIN_AC97_L, gpr); gpr++; VOLUME_ADDIN(icode, &ptr, playback + 1, EXTIN_AC97_R, gpr); gpr++; snd_emu10k1_init_stereo_control(controls + i++, "AC97 Playback Volume", gpr-2, 0); /* AC'97 Capture Volume */ VOLUME_ADDIN(icode, &ptr, capture + 0, EXTIN_AC97_L, gpr); gpr++; VOLUME_ADDIN(icode, &ptr, capture + 1, EXTIN_AC97_R, gpr); gpr++; snd_emu10k1_init_stereo_control(controls + i++, "AC97 Capture Volume", gpr-2, 100); } if (emu->fx8010.extin_mask & ((1<<EXTIN_SPDIF_CD_L)|(1<<EXTIN_SPDIF_CD_R))) { /* IEC958 TTL Playback Volume */ for (z = 0; z < 2; z++) VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_SPDIF_CD_L + z, gpr + z); snd_emu10k1_init_stereo_control(controls + i++, "IEC958 TTL Playback Volume", gpr, 0); gpr += 2; /* IEC958 TTL Capture Volume + Switch */ for (z = 0; z < 2; z++) { SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_SPDIF_CD_L + z, gpr + 2 + z); VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); } snd_emu10k1_init_stereo_control(controls + i++, "IEC958 TTL Capture Volume", gpr, 0); snd_emu10k1_init_stereo_onoff_control(controls + i++, "IEC958 TTL Capture Switch", gpr + 2, 0); gpr += 4; } if (emu->fx8010.extin_mask & ((1<<EXTIN_ZOOM_L)|(1<<EXTIN_ZOOM_R))) { /* Zoom Video Playback Volume */ for (z = 0; z < 2; z++) VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_ZOOM_L + z, gpr + z); snd_emu10k1_init_stereo_control(controls + i++, "Zoom Video Playback Volume", gpr, 0); gpr += 2; /* Zoom Video Capture Volume + Switch */ for (z = 0; z < 2; z++) { SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_ZOOM_L + z, gpr + 2 + z); VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); } snd_emu10k1_init_stereo_control(controls + i++, "Zoom Video Capture Volume", gpr, 0); snd_emu10k1_init_stereo_onoff_control(controls + i++, "Zoom Video Capture Switch", gpr + 2, 0); gpr += 4; } if (emu->fx8010.extin_mask & ((1<<EXTIN_TOSLINK_L)|(1<<EXTIN_TOSLINK_R))) { /* IEC958 Optical Playback Volume */ for (z = 0; z < 2; z++) VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_TOSLINK_L + z, gpr + z); snd_emu10k1_init_stereo_control(controls + i++, "IEC958 LiveDrive Playback Volume", gpr, 0); gpr += 2; /* IEC958 Optical Capture Volume */ for (z = 0; z < 2; z++) { SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_TOSLINK_L + z, gpr + 2 + z); VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); } snd_emu10k1_init_stereo_control(controls + i++, "IEC958 LiveDrive Capture Volume", gpr, 0); snd_emu10k1_init_stereo_onoff_control(controls + i++, "IEC958 LiveDrive Capture Switch", gpr + 2, 0); gpr += 4; } if (emu->fx8010.extin_mask & ((1<<EXTIN_LINE1_L)|(1<<EXTIN_LINE1_R))) { /* Line LiveDrive Playback Volume */ for (z = 0; z < 2; z++) VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_LINE1_L + z, gpr + z); snd_emu10k1_init_stereo_control(controls + i++, "Line LiveDrive Playback Volume", gpr, 0); gpr += 2; /* Line LiveDrive Capture Volume + Switch */ for (z = 0; z < 2; z++) { SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_LINE1_L + z, gpr + 2 + z); VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); } snd_emu10k1_init_stereo_control(controls + i++, "Line LiveDrive Capture Volume", gpr, 0); snd_emu10k1_init_stereo_onoff_control(controls + i++, "Line LiveDrive
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -