提交 9f4bd5dd 编写于 作者: J James Courtier-Dutton 提交者: Jaroslav Kysela

[ALSA] snd-emu10k1: Added support for emu1010, including E-Mu 1212m and E-Mu 1820m

Signed-off-by: NJames Courtier-Dutton <James@superbug.co.uk>
Signed-off-by: NJaroslav Kysela <perex@suse.cz>
上级 5986a2ec
此差异已折叠。
此差异已折叠。
......@@ -460,7 +460,7 @@ static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream)
u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
int i;
for(i=0; i < runtime->periods; i++) {
for(i = 0; i < runtime->periods; i++) {
*table_base++=runtime->dma_addr+(i*period_size_bytes);
*table_base++=period_size_bytes<<16;
}
......@@ -1042,8 +1042,8 @@ static void snd_emu10k1x_proc_reg_write(struct snd_info_entry *entry,
if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
continue;
if ((reg < 0x49) && (reg >=0) && (val <= 0xffffffff)
&& (channel_id >=0) && (channel_id <= 2) )
if ((reg < 0x49) && (reg >= 0) && (val <= 0xffffffff)
&& (channel_id >= 0) && (channel_id <= 2) )
snd_emu10k1x_ptr_write(emu, reg, channel_id, val);
}
}
......
......@@ -3,6 +3,9 @@
* Creative Labs, Inc.
* Routines for effect processor FX8010
*
* Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
* Added EMU 1010 support.
*
* BUGS:
* --
*
......@@ -1069,6 +1072,21 @@ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl
ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
}
static int snd_emu10k1_audigy_dsp_convert_32_to_2x16(
struct snd_emu10k1_fx8010_code *icode,
u32 *ptr, int tmp, int bit_shifter16,
int reg_in, int reg_out)
{
A_OP(icode, ptr, iACC3, A_GPR(tmp + 1), reg_in, A_C_00000000, A_C_00000000);
A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp + 1), A_GPR(bit_shifter16 - 1), A_C_00000000);
A_OP(icode, ptr, iTSTNEG, A_GPR(tmp + 2), A_GPR(tmp), A_C_80000000, A_GPR(bit_shifter16 - 2));
A_OP(icode, ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_C_80000000, A_C_00000000);
A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp), A_GPR(bit_shifter16 - 3), A_C_00000000);
A_OP(icode, ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A_GPR(tmp), A_C_00010000);
A_OP(icode, ptr, iANDXOR, reg_out, A_GPR(tmp), A_C_ffffffff, A_GPR(tmp + 2));
A_OP(icode, ptr, iACC3, reg_out + 1, A_GPR(tmp + 1), A_C_00000000, A_C_00000000);
return 1;
}
/*
* initial DSP configuration for Audigy
......@@ -1077,6 +1095,7 @@ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl
static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
{
int err, i, z, gpr, nctl;
int bit_shifter16;
const int playback = 10;
const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
const int stereo_mix = capture + 2;
......@@ -1114,17 +1133,14 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
ptr = 0;
nctl = 0;
gpr = stereo_mix + 10;
gpr_map[gpr++] = 0x00007fff;
gpr_map[gpr++] = 0x00008000;
gpr_map[gpr++] = 0x0000ffff;
bit_shifter16 = gpr;
/* stop FX processor */
snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
#if 0
/* FIX: jcd test */
for (z = 0; z < 80; z=z+2) {
A_OP(icode, &ptr, iACC3, A_EXTOUT(z), A_FXBUS(FXBUS_PCM_LEFT_FRONT), A_C_00000000, A_C_00000000); /* left */
A_OP(icode, &ptr, iACC3, A_EXTOUT(z+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT), A_C_00000000, A_C_00000000); /* right */
}
#endif /* jcd test */
#if 1
/* PCM front Playback Volume (independent from stereo mix) */
A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT));
......@@ -1189,6 +1205,13 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
#define A_ADD_VOLUME_IN(var,vol,input) \
A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
/* emu1212 DSP 0 and DSP 1 Capture */
if (emu->card_capabilities->emu1010) {
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);
gpr += 2;
}
/* AC'97 Playback Volume - used only for mic (renamed later) */
A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AC97_L);
A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AC97_R);
......@@ -1429,6 +1452,13 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
/* digital outputs */
/* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */
if (emu->card_capabilities->emu1010) {
/* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */
snd_printk("EMU outputs on\n");
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);
}
}
/* IEC958 Optical Raw Playback Switch */
gpr_map[gpr++] = 0;
......@@ -1466,10 +1496,58 @@ 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);
#endif
if (emu->card_capabilities->emu1010) {
snd_printk("EMU inputs on\n");
/* Capture 8 channels of S32_LE sound */
/* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */
/* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */
/* A_P16VIN(0) is delayed by one sample,
* so all other A_P16VIN channels will need to also be delayed
*/
/* Left ADC in. 1 of 2 */
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) );
/* Right ADC in 1 of 2 */
gpr_map[gpr++] = 0x00000000;
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) );
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), 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(4) );
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), 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(6) );
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000);
/* For 96kHz mode */
/* Left ADC in. 2 of 2 */
gpr_map[gpr++] = 0x00000000;
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) );
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000);
/* Right ADC in 2 of 2 */
gpr_map[gpr++] = 0x00000000;
snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) );
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), 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(0xc) );
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), 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(0xe) );
A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000);
#if 0
for (z = 4; z < 8; z++) {
A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000);
}
for (z = 0xc; z < 0x10; z++) {
A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000);
}
#endif
} else {
/* EFX capture - capture the 16 EXTINs */
/* Capture 16 channels of S16_LE sound */
for (z = 0; z < 16; z++) {
A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
}
}
#endif /* JCD test */
/*
......@@ -2138,7 +2216,7 @@ void snd_emu10k1_free_efx(struct snd_emu10k1 *emu)
snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = EMU10K1_DBG_SINGLE_STEP);
}
#if 0 // FIXME: who use them?
#if 0 /* FIXME: who use them? */
int snd_emu10k1_fx8010_tone_control_activate(struct snd_emu10k1 *emu, int output)
{
if (output < 0 || output >= 6)
......
......@@ -5,6 +5,9 @@
* Routines for control of EMU10K1 chips / mixer routines
* Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com>
*
* Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
* Added EMU 1010 support.
*
* BUGS:
* --
*
......@@ -68,6 +71,311 @@ static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
return 0;
}
static char *emu1010_src_texts[] = {
"Silence",
"Dock Mic A",
"Dock Mic B",
"Dock ADC1 Left",
"Dock ADC1 Right",
"Dock ADC2 Left",
"Dock ADC2 Right",
"Dock ADC3 Left",
"Dock ADC3 Right",
"0202 ADC Left",
"0202 ADC Right",
"0202 SPDIF Left",
"0202 SPDIF Right",
"ADAT 0",
"ADAT 1",
"ADAT 2",
"ADAT 3",
"ADAT 4",
"ADAT 5",
"ADAT 6",
"ADAT 7",
"DSP 0",
"DSP 1",
"DSP 2",
"DSP 3",
"DSP 4",
"DSP 5",
"DSP 6",
"DSP 7",
"DSP 8",
"DSP 9",
"DSP 10",
"DSP 11",
"DSP 12",
"DSP 13",
"DSP 14",
"DSP 15",
"DSP 16",
"DSP 17",
"DSP 18",
"DSP 19",
"DSP 20",
"DSP 21",
"DSP 22",
"DSP 23",
"DSP 24",
"DSP 25",
"DSP 26",
"DSP 27",
"DSP 28",
"DSP 29",
"DSP 30",
"DSP 31",
};
static unsigned int emu1010_src_regs[] = {
EMU_SRC_SILENCE,/* 0 */
EMU_SRC_DOCK_MIC_A1, /* 1 */
EMU_SRC_DOCK_MIC_B1, /* 2 */
EMU_SRC_DOCK_ADC1_LEFT1, /* 3 */
EMU_SRC_DOCK_ADC1_RIGHT1, /* 4 */
EMU_SRC_DOCK_ADC2_LEFT1, /* 5 */
EMU_SRC_DOCK_ADC2_RIGHT1, /* 6 */
EMU_SRC_DOCK_ADC3_LEFT1, /* 7 */
EMU_SRC_DOCK_ADC3_RIGHT1, /* 8 */
EMU_SRC_HAMOA_ADC_LEFT1, /* 9 */
EMU_SRC_HAMOA_ADC_RIGHT1, /* 10 */
EMU_SRC_HANA_SPDIF_LEFT1, /* 11 */
EMU_SRC_HANA_SPDIF_RIGHT1, /* 12 */
EMU_SRC_HANA_ADAT, /* 13 */
EMU_SRC_HANA_ADAT+1, /* 14 */
EMU_SRC_HANA_ADAT+2, /* 15 */
EMU_SRC_HANA_ADAT+3, /* 16 */
EMU_SRC_HANA_ADAT+4, /* 17 */
EMU_SRC_HANA_ADAT+5, /* 18 */
EMU_SRC_HANA_ADAT+6, /* 19 */
EMU_SRC_HANA_ADAT+7, /* 20 */
EMU_SRC_ALICE_EMU32A, /* 21 */
EMU_SRC_ALICE_EMU32A+1, /* 22 */
EMU_SRC_ALICE_EMU32A+2, /* 23 */
EMU_SRC_ALICE_EMU32A+3, /* 24 */
EMU_SRC_ALICE_EMU32A+4, /* 25 */
EMU_SRC_ALICE_EMU32A+5, /* 26 */
EMU_SRC_ALICE_EMU32A+6, /* 27 */
EMU_SRC_ALICE_EMU32A+7, /* 28 */
EMU_SRC_ALICE_EMU32A+8, /* 29 */
EMU_SRC_ALICE_EMU32A+9, /* 30 */
EMU_SRC_ALICE_EMU32A+0xa, /* 31 */
EMU_SRC_ALICE_EMU32A+0xb, /* 32 */
EMU_SRC_ALICE_EMU32A+0xc, /* 33 */
EMU_SRC_ALICE_EMU32A+0xd, /* 34 */
EMU_SRC_ALICE_EMU32A+0xe, /* 35 */
EMU_SRC_ALICE_EMU32A+0xf, /* 36 */
EMU_SRC_ALICE_EMU32B, /* 37 */
EMU_SRC_ALICE_EMU32B+1, /* 38 */
EMU_SRC_ALICE_EMU32B+2, /* 39 */
EMU_SRC_ALICE_EMU32B+3, /* 40 */
EMU_SRC_ALICE_EMU32B+4, /* 41 */
EMU_SRC_ALICE_EMU32B+5, /* 42 */
EMU_SRC_ALICE_EMU32B+6, /* 43 */
EMU_SRC_ALICE_EMU32B+7, /* 44 */
EMU_SRC_ALICE_EMU32B+8, /* 45 */
EMU_SRC_ALICE_EMU32B+9, /* 46 */
EMU_SRC_ALICE_EMU32B+0xa, /* 47 */
EMU_SRC_ALICE_EMU32B+0xb, /* 48 */
EMU_SRC_ALICE_EMU32B+0xc, /* 49 */
EMU_SRC_ALICE_EMU32B+0xd, /* 50 */
EMU_SRC_ALICE_EMU32B+0xe, /* 51 */
EMU_SRC_ALICE_EMU32B+0xf, /* 52 */
};
static unsigned int emu1010_output_dst[] = {
EMU_DST_DOCK_DAC1_LEFT1, /* 0 */
EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */
EMU_DST_DOCK_DAC2_LEFT1, /* 2 */
EMU_DST_DOCK_DAC2_RIGHT1, /* 3 */
EMU_DST_DOCK_DAC3_LEFT1, /* 4 */
EMU_DST_DOCK_DAC3_RIGHT1, /* 5 */
EMU_DST_DOCK_DAC4_LEFT1, /* 6 */
EMU_DST_DOCK_DAC4_RIGHT1, /* 7 */
EMU_DST_DOCK_PHONES_LEFT1, /* 8 */
EMU_DST_DOCK_PHONES_RIGHT1, /* 9 */
EMU_DST_DOCK_SPDIF_LEFT1, /* 10 */
EMU_DST_DOCK_SPDIF_RIGHT1, /* 11 */
EMU_DST_HANA_SPDIF_LEFT1, /* 12 */
EMU_DST_HANA_SPDIF_RIGHT1, /* 13 */
EMU_DST_HAMOA_DAC_LEFT1, /* 14 */
EMU_DST_HAMOA_DAC_RIGHT1, /* 15 */
EMU_DST_HANA_ADAT, /* 16 */
EMU_DST_HANA_ADAT+1, /* 17 */
EMU_DST_HANA_ADAT+2, /* 18 */
EMU_DST_HANA_ADAT+3, /* 19 */
EMU_DST_HANA_ADAT+4, /* 20 */
EMU_DST_HANA_ADAT+5, /* 21 */
EMU_DST_HANA_ADAT+6, /* 22 */
EMU_DST_HANA_ADAT+7, /* 23 */
};
static unsigned int emu1010_input_dst[] = {
EMU_DST_ALICE2_EMU32_0,
EMU_DST_ALICE2_EMU32_1,
EMU_DST_ALICE2_EMU32_2,
EMU_DST_ALICE2_EMU32_3,
EMU_DST_ALICE2_EMU32_4,
EMU_DST_ALICE2_EMU32_5,
EMU_DST_ALICE2_EMU32_6,
EMU_DST_ALICE2_EMU32_7,
EMU_DST_ALICE2_EMU32_8,
EMU_DST_ALICE2_EMU32_9,
EMU_DST_ALICE2_EMU32_A,
EMU_DST_ALICE2_EMU32_B,
EMU_DST_ALICE2_EMU32_C,
EMU_DST_ALICE2_EMU32_D,
EMU_DST_ALICE2_EMU32_E,
EMU_DST_ALICE2_EMU32_F,
EMU_DST_ALICE_I2S0_LEFT,
EMU_DST_ALICE_I2S0_RIGHT,
EMU_DST_ALICE_I2S1_LEFT,
EMU_DST_ALICE_I2S1_RIGHT,
EMU_DST_ALICE_I2S2_LEFT,
EMU_DST_ALICE_I2S2_RIGHT,
};
static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = 53;
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
strcpy(uinfo->value.enumerated.name, emu1010_src_texts[uinfo->value.enumerated.item]);
return 0;
}
static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int channel;
channel = (kcontrol->private_value) & 0xff;
ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel];
return 0;
}
static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int change = 0;
unsigned int val;
int channel;
channel = (kcontrol->private_value) & 0xff;
if (emu->emu1010.output_source[channel] != ucontrol->value.enumerated.item[0]) {
val = emu->emu1010.output_source[channel] = ucontrol->value.enumerated.item[0];
change = 1;
snd_emu1010_fpga_link_dst_src_write(emu,
emu1010_output_dst[channel], emu1010_src_regs[val]);
}
return change;
}
static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int channel;
channel = (kcontrol->private_value) & 0xff;
ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];
return 0;
}
static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int change = 0;
unsigned int val;
int channel;
channel = (kcontrol->private_value) & 0xff;
if (emu->emu1010.input_source[channel] != ucontrol->value.enumerated.item[0]) {
val = emu->emu1010.input_source[channel] = ucontrol->value.enumerated.item[0];
change = 1;
snd_emu1010_fpga_link_dst_src_write(emu,
emu1010_input_dst[channel], emu1010_src_regs[val]);
}
return change;
}
#define EMU1010_SOURCE_OUTPUT(xname,chid) \
{ \
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.info = snd_emu1010_input_output_source_info, \
.get = snd_emu1010_output_source_get, \
.put = snd_emu1010_output_source_put, \
.private_value = chid \
}
static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
EMU1010_SOURCE_OUTPUT("Playback Dock DAC1 Left", 0),
EMU1010_SOURCE_OUTPUT("Playback Dock DAC1 Right", 1),
EMU1010_SOURCE_OUTPUT("Playback Dock DAC2 Left", 2),
EMU1010_SOURCE_OUTPUT("Playback Dock DAC2 Right", 3),
EMU1010_SOURCE_OUTPUT("Playback Dock DAC3 Left", 4),
EMU1010_SOURCE_OUTPUT("Playback Dock DAC3 Right", 5),
EMU1010_SOURCE_OUTPUT("Playback Dock DAC4 Left", 6),
EMU1010_SOURCE_OUTPUT("Playback Dock DAC4 Right", 7),
EMU1010_SOURCE_OUTPUT("Playback Dock Phones Left", 8),
EMU1010_SOURCE_OUTPUT("Playback Dock Phones Right", 9),
EMU1010_SOURCE_OUTPUT("Playback Dock SPDIF Left", 0xa),
EMU1010_SOURCE_OUTPUT("Playback Dock SPDIF Right", 0xb),
EMU1010_SOURCE_OUTPUT("Playback 1010 SPDIF Left", 0xc),
EMU1010_SOURCE_OUTPUT("Playback 1010 SPDIF Right", 0xd),
EMU1010_SOURCE_OUTPUT("Playback 0202 DAC Left", 0xe),
EMU1010_SOURCE_OUTPUT("Playback 0202 DAC Right", 0xf),
EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 0", 0x10),
EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 1", 0x11),
EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 2", 0x12),
EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 3", 0x13),
EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 4", 0x14),
EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 5", 0x15),
EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 6", 0x16),
EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 7", 0x17),
};
#define EMU1010_SOURCE_INPUT(xname,chid) \
{ \
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.info = snd_emu1010_input_output_source_info, \
.get = snd_emu1010_input_source_get, \
.put = snd_emu1010_input_source_put, \
.private_value = chid \
}
static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {
EMU1010_SOURCE_INPUT("DSP 0 CAPTURE ENUM", 0),
EMU1010_SOURCE_INPUT("DSP 1 CAPTURE ENUM", 1),
EMU1010_SOURCE_INPUT("DSP 2 CAPTURE ENUM", 2),
EMU1010_SOURCE_INPUT("DSP 3 CAPTURE ENUM", 3),
EMU1010_SOURCE_INPUT("DSP 4 CAPTURE ENUM", 4),
EMU1010_SOURCE_INPUT("DSP 5 CAPTURE ENUM", 5),
EMU1010_SOURCE_INPUT("DSP 6 CAPTURE ENUM", 6),
EMU1010_SOURCE_INPUT("DSP 7 CAPTURE ENUM", 7),
EMU1010_SOURCE_INPUT("DSP 8 CAPTURE ENUM", 8),
EMU1010_SOURCE_INPUT("DSP 9 CAPTURE ENUM", 9),
EMU1010_SOURCE_INPUT("DSP A CAPTURE ENUM", 0xa),
EMU1010_SOURCE_INPUT("DSP B CAPTURE ENUM", 0xb),
EMU1010_SOURCE_INPUT("DSP C CAPTURE ENUM", 0xc),
EMU1010_SOURCE_INPUT("DSP D CAPTURE ENUM", 0xd),
EMU1010_SOURCE_INPUT("DSP E CAPTURE ENUM", 0xe),
EMU1010_SOURCE_INPUT("DSP F CAPTURE ENUM", 0xf),
EMU1010_SOURCE_INPUT("DSP 10 CAPTURE ENUM", 0x10),
EMU1010_SOURCE_INPUT("DSP 11 CAPTURE ENUM", 0x11),
EMU1010_SOURCE_INPUT("DSP 12 CAPTURE ENUM", 0x12),
EMU1010_SOURCE_INPUT("DSP 13 CAPTURE ENUM", 0x13),
EMU1010_SOURCE_INPUT("DSP 14 CAPTURE ENUM", 0x14),
EMU1010_SOURCE_INPUT("DSP 15 CAPTURE ENUM", 0x15),
};
#if 0
static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
......@@ -1021,7 +1329,7 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
return err;
}
if ( emu->card_capabilities->emu1212m) {
if ( emu->card_capabilities->emu1010) {
; /* Disable the snd_audigy_spdif_shared_spdif */
} else if (emu->audigy) {
if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
......@@ -1046,5 +1354,20 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
return err;
}
if ( emu->card_capabilities->emu1010) {
int i;
for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu));
if (err < 0)
return err;
}
for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu));
if (err < 0)
return err;
}
}
return 0;
}
......@@ -147,7 +147,7 @@ static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voic
1,
&epcm->extra);
if (err < 0) {
// printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame);
/* printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame); */
for (i = 0; i < voices; i++) {
snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
epcm->voices[i] = NULL;
......@@ -339,7 +339,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
}
}
// setup routing
/* setup routing */
if (emu->audigy) {
snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
snd_emu10k1_compose_audigy_fxrt1(send_routing));
......@@ -353,8 +353,8 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
} else
snd_emu10k1_ptr_write(emu, FXRT, voice,
snd_emu10k1_compose_send_routing(send_routing));
// Stop CA
// Assumption that PT is already 0 so no harm overwriting
/* Stop CA */
/* Assumption that PT is already 0 so no harm overwriting */
snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]);
snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24));
snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24));
......@@ -367,14 +367,14 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
snd_emu10k1_ptr_write(emu, CCCA, voice, (start_addr + ccis) |
emu10k1_select_interprom(pitch_target) |
(w_16 ? 0 : CCCA_8BITSELECT));
// Clear filter delay memory
/* Clear filter delay memory */
snd_emu10k1_ptr_write(emu, Z1, voice, 0);
snd_emu10k1_ptr_write(emu, Z2, voice, 0);
// invalidate maps
/* invalidate maps */
silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK;
snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page);
snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page);
// modulation envelope
/* modulation envelope */
snd_emu10k1_ptr_write(emu, CVCF, voice, 0xffff);
snd_emu10k1_ptr_write(emu, VTFT, voice, 0xffff);
snd_emu10k1_ptr_write(emu, ATKHLDM, voice, 0);
......@@ -385,12 +385,12 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
snd_emu10k1_ptr_write(emu, TREMFRQ, voice, 0);
snd_emu10k1_ptr_write(emu, FM2FRQ2, voice, 0);
snd_emu10k1_ptr_write(emu, ENVVAL, voice, 0x8000);
// volume envelope
/* volume envelope */
snd_emu10k1_ptr_write(emu, ATKHLDV, voice, 0x7f7f);
snd_emu10k1_ptr_write(emu, ENVVOL, voice, 0x0000);
// filter envelope
/* filter envelope */
snd_emu10k1_ptr_write(emu, PEFE_FILTERAMOUNT, voice, 0x7f);
// pitch envelope
/* pitch envelope */
snd_emu10k1_ptr_write(emu, PEFE_PITCHAMOUNT, voice, 0);
spin_unlock_irqrestore(&emu->reg_lock, flags);
......@@ -468,7 +468,7 @@ static int snd_emu10k1_efx_playback_hw_free(struct snd_pcm_substream *substream)
snd_emu10k1_voice_free(epcm->emu, epcm->extra);
epcm->extra = NULL;
}
for (i=0; i < NUM_EFX_PLAYBACK; i++) {
for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
if (epcm->voices[i]) {
snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
epcm->voices[i] = NULL;
......@@ -637,7 +637,7 @@ static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int e
stereo = (!extra && runtime->channels == 2);
sample = snd_pcm_format_width(runtime->format) == 16 ? 0 : 0x80808080;
ccis = emu10k1_ccis(stereo, sample == 0);
// set cs to 2 * number of cache registers beside the invalidated
/* set cs to 2 * number of cache registers beside the invalidated */
cs = (sample == 0) ? (32-ccis) : (64-ccis+1) >> 1;
if (cs > 16) cs = 16;
for (i = 0; i < cs; i++) {
......@@ -646,14 +646,14 @@ static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int e
snd_emu10k1_ptr_write(emu, CD0 + i, voice + 1, sample);
}
}
// reset cache
/* reset cache */
snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, 0);
snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra);
if (stereo) {
snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0);
snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra);
}
// fill cache
/* fill cache */
snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis);
if (stereo) {
snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice+1, ccis);
......@@ -732,7 +732,7 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream,
struct snd_emu10k1_pcm_mixer *mix;
int result = 0;
// printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream));
/* printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream)); */
spin_lock(&emu->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
......@@ -778,10 +778,10 @@ static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream,
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
// hmm this should cause full and half full interrupt to be raised?
/* hmm this should cause full and half full interrupt to be raised? */
outl(epcm->capture_ipr, emu->port + IPR);
snd_emu10k1_intr_enable(emu, epcm->capture_inte);
// printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs);
/* printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs); */
switch (epcm->type) {
case CAPTURE_AC97ADC:
snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val);
......@@ -790,6 +790,7 @@ static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream,
if (emu->audigy) {
snd_emu10k1_ptr_write(emu, A_FXWC1, 0, epcm->capture_cr_val);
snd_emu10k1_ptr_write(emu, A_FXWC2, 0, epcm->capture_cr_val2);
snd_printdd("cr_val=0x%x, cr_val2=0x%x\n", epcm->capture_cr_val, epcm->capture_cr_val2);
} else
snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
break;
......@@ -851,7 +852,7 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream *
ptr -= runtime->buffer_size;
}
#endif
// printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size);
/* printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size); */
return ptr;
}
......@@ -868,7 +869,7 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream,
spin_lock(&emu->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
// prepare voices
/* prepare voices */
for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[i]);
}
......@@ -917,7 +918,7 @@ static snd_pcm_uframes_t snd_emu10k1_capture_pointer(struct snd_pcm_substream *s
if (!epcm->running)
return 0;
if (epcm->first_ptr) {
udelay(50); // hack, it takes awhile until capture is started
udelay(50); /* hack, it takes awhile until capture is started */
epcm->first_ptr = 0;
}
ptr = snd_emu10k1_ptr_read(emu, epcm->capture_idx_reg, 0) & 0x0000ffff;
......@@ -972,6 +973,28 @@ static struct snd_pcm_hardware snd_emu10k1_capture =
.fifo_size = 0,
};
static struct snd_pcm_hardware snd_emu10k1_capture_efx =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
.rate_min = 44100,
.rate_max = 192000,
.channels_min = 8,
.channels_max = 8,
.buffer_bytes_max = (64*1024),
.period_bytes_min = 384,
.period_bytes_max = (64*1024),
.periods_min = 2,
.periods_max = 2,
.fifo_size = 0,
};
/*
*
*/
......@@ -1016,7 +1039,7 @@ static int snd_emu10k1_efx_playback_close(struct snd_pcm_substream *substream)
struct snd_emu10k1_pcm_mixer *mix;
int i;
for (i=0; i < NUM_EFX_PLAYBACK; i++) {
for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
mix = &emu->efx_pcm_mixer[i];
mix->epcm = NULL;
snd_emu10k1_pcm_efx_mixer_notify(emu, i, 0);
......@@ -1045,7 +1068,7 @@ static int snd_emu10k1_efx_playback_open(struct snd_pcm_substream *substream)
runtime->private_free = snd_emu10k1_pcm_free_substream;
runtime->hw = snd_emu10k1_efx_playback;
for (i=0; i < NUM_EFX_PLAYBACK; i++) {
for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
mix = &emu->efx_pcm_mixer[i];
mix->send_routing[0][0] = i;
memset(&mix->send_volume, 0, sizeof(mix->send_volume));
......@@ -1199,10 +1222,53 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream)
epcm->capture_idx_reg = FXIDX;
substream->runtime->private_data = epcm;
substream->runtime->private_free = snd_emu10k1_pcm_free_substream;
runtime->hw = snd_emu10k1_capture;
runtime->hw = snd_emu10k1_capture_efx;
runtime->hw.rates = SNDRV_PCM_RATE_48000;
runtime->hw.rate_min = runtime->hw.rate_max = 48000;
spin_lock_irq(&emu->reg_lock);
if (emu->card_capabilities->emu1010) {
/* TODO
* SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE
* SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
* SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
* SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000
* rate_min = 44100,
* rate_max = 192000,
* channels_min = 8,
* channels_max = 8,
* Need to add mixer control to fix sample rate
*
* There are 16 mono channels of 16bits each.
* 24bit Audio uses 2x channels over 16bit
* 96kHz uses 2x channels over 48kHz
* 192kHz uses 4x channels over 48kHz
* So, for 48kHz 24bit, one has 8 channels
* for 96kHz 24bit, one has 4 channels
* for 192kHz 24bit, one has 2 channels
*/
#if 1
/* For 48kHz */
runtime->hw.rates = SNDRV_PCM_RATE_48000;
runtime->hw.rate_min = runtime->hw.rate_max = 48000;
runtime->hw.channels_min = runtime->hw.channels_max = 8;
#endif
#if 0
/* For 96kHz */
runtime->hw.rates = SNDRV_PCM_RATE_96000;
runtime->hw.rate_min = runtime->hw.rate_max = 96000;
runtime->hw.channels_min = runtime->hw.channels_max = 4;
#endif
#if 0
/* For 192kHz */
runtime->hw.rates = SNDRV_PCM_RATE_192000;
runtime->hw.rate_min = runtime->hw.rate_max = 192000;
runtime->hw.channels_min = runtime->hw.channels_max = 2;
#endif
runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
/* efx_voices_mask[0] is expected to be zero
* efx_voices_mask[1] is expected to have 16bits set
*/
} else {
runtime->hw.channels_min = runtime->hw.channels_max = 0;
for (idx = 0; idx < nefx; idx++) {
if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) {
......@@ -1210,6 +1276,7 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream)
runtime->hw.channels_max++;
}
}
}
epcm->capture_cr_val = emu->efx_voices_mask[0];
epcm->capture_cr_val2 = emu->efx_voices_mask[1];
spin_unlock_irq(&emu->reg_lock);
......@@ -1460,7 +1527,7 @@ static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
unsigned int count,
unsigned int tram_shift)
{
// printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count);
/* printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count); */
if ((tram_shift & 1) == 0) {
while (count--) {
*dst_left-- = *src++;
......@@ -1537,7 +1604,7 @@ static int snd_emu10k1_fx8010_playback_prepare(struct snd_pcm_substream *substre
struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
unsigned int i;
// printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2);
/* printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2); */
memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec));
pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */
pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
......
......@@ -3,6 +3,9 @@
* Creative Labs, Inc.
* Routines for control of EMU10K1 chips / proc interface routines
*
* Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
* Added EMU 1010 support.
*
* BUGS:
* --
*
......@@ -255,7 +258,7 @@ static void snd_emu10k1_proc_rates_read(struct snd_info_entry *entry,
unsigned int val, tmp, n;
val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0);
tmp = (val >> 16) & 0x8;
for (n=0;n<4;n++) {
for (n = 0; n < 4; n++) {
tmp = val >> (16 + (n*4));
if (tmp & 0x8) snd_iprintf(buffer, "Channel %d: Rate=%d\n", n, samplerate[tmp & 0x7]);
else snd_iprintf(buffer, "Channel %d: No input\n", n);
......@@ -372,6 +375,27 @@ static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry,
}
#ifdef CONFIG_SND_DEBUG
static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_emu10k1 *emu = entry->private_data;
unsigned long value;
unsigned long flags;
unsigned long regs;
int i;
snd_iprintf(buffer, "EMU1010 Registers:\n\n");
for(i = 0; i < 0x30; i+=1) {
spin_lock_irqsave(&emu->emu_lock, flags);
regs=i+0x40; /* 0x40 upwards are registers. */
outl(regs, emu->port + A_IOCFG);
outl(regs | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */
value = inl(emu->port + A_IOCFG);
spin_unlock_irqrestore(&emu->emu_lock, flags);
snd_iprintf(buffer, "%02X: %08lX, %02lX\n", i, value, (value >> 8) & 0x7f);
}
}
static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
......@@ -398,7 +422,7 @@ static void snd_emu_proc_io_reg_write(struct snd_info_entry *entry,
while (!snd_info_get_line(buffer, line, sizeof(line))) {
if (sscanf(line, "%x %x", &reg, &val) != 2)
continue;
if ((reg < 0x40) && (reg >=0) && (val <= 0xffffffff) ) {
if ((reg < 0x40) && (reg >= 0) && (val <= 0xffffffff) ) {
spin_lock_irqsave(&emu->emu_lock, flags);
outl(val, emu->port + (reg & 0xfffffffc));
spin_unlock_irqrestore(&emu->emu_lock, flags);
......@@ -474,7 +498,7 @@ static void snd_emu_proc_ptr_reg_write(struct snd_info_entry *entry,
while (!snd_info_get_line(buffer, line, sizeof(line))) {
if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
continue;
if ((reg < 0xa0) && (reg >=0) && (val <= 0xffffffff) && (channel_id >=0) && (channel_id <= 3) )
if ((reg < 0xa0) && (reg >= 0) && (val <= 0xffffffff) && (channel_id >= 0) && (channel_id <= 3) )
snd_ptr_write(emu, iobase, reg, channel_id, val);
}
}
......@@ -531,6 +555,10 @@ int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu)
{
struct snd_info_entry *entry;
#ifdef CONFIG_SND_DEBUG
if ((emu->card_capabilities->emu1010) &&
snd_card_proc_new(emu->card, "emu1010_regs", &entry)) {
snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read);
}
if (! snd_card_proc_new(emu->card, "io_regs", &entry)) {
snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read);
entry->c.text.write = snd_emu_proc_io_reg_write;
......
......@@ -167,6 +167,51 @@ int snd_emu10k1_spi_write(struct snd_emu10k1 * emu,
return 0;
}
int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value)
{
if (reg < 0 || reg > 0x3f)
return 1;
reg += 0x40; /* 0x40 upwards are registers. */
if (value < 0 || value > 0x3f) /* 0 to 0x3f are values */
return 1;
outl(reg, emu->port + A_IOCFG);
udelay(10);
outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */
udelay(10);
outl(value, emu->port + A_IOCFG);
udelay(10);
outl(value | 0x80 , emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */
return 0;
}
int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value)
{
if (reg < 0 || reg > 0x3f)
return 1;
reg += 0x40; /* 0x40 upwards are registers. */
outl(reg, emu->port + A_IOCFG);
udelay(10);
outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */
udelay(10);
*value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f);
return 0;
}
/* Each Destination has one and only one Source,
* but one Source can feed any number of Destinations simultaneously.
*/
int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, int dst, int src)
{
snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) );
snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) );
snd_emu1010_fpga_write(emu, 0x02, ((src >> 8) & 0x3f) );
snd_emu1010_fpga_write(emu, 0x03, (src & 0x3f) );
return 0;
}
void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
{
unsigned long flags;
......
......@@ -253,7 +253,7 @@ static int snd_p16v_pcm_close_playback(struct snd_pcm_substream *substream)
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
//struct snd_pcm_runtime *runtime = substream->runtime;
//struct snd_emu10k1_pcm *epcm = runtime->private_data;
emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use = 0;
/* FIXME: maybe zero others */
return 0;
}
......@@ -264,7 +264,7 @@ static int snd_p16v_pcm_close_capture(struct snd_pcm_substream *substream)
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
//struct snd_pcm_runtime *runtime = substream->runtime;
//struct snd_emu10k1_pcm *epcm = runtime->private_data;
emu->p16v_capture_voice.use=0;
emu->p16v_capture_voice.use = 0;
/* FIXME: maybe zero others */
return 0;
}
......@@ -349,7 +349,7 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
break;
}
/* FIXME: Check emu->buffer.size before actually writing to it. */
for(i=0; i < runtime->periods; i++) {
for(i = 0; i < runtime->periods; i++) {
table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
table_base[(i*2)+1]=period_size_bytes<<16;
}
......@@ -394,7 +394,7 @@ static int snd_p16v_pcm_prepare_capture(struct snd_pcm_substream *substream)
/* FIXME: Check emu->buffer.size before actually writing to it. */
snd_emu10k1_ptr20_write(emu, 0x13, channel, 0);
snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size) << 16); // buffer size in bytes
snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0);
//snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */
//snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
......@@ -437,7 +437,7 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream,
struct snd_pcm_substream *s;
u32 basic = 0;
u32 inte = 0;
int running=0;
int running = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
......@@ -445,7 +445,7 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream,
break;
case SNDRV_PCM_TRIGGER_STOP:
default:
running=0;
running = 0;
break;
}
snd_pcm_group_for_each(pos, substream) {
......
......@@ -83,7 +83,7 @@ static int voice_alloc(struct snd_emu10k1 *emu, int type, int number,
if (first_voice == last_voice)
return -ENOMEM;
for (i=0; i < number; i++) {
for (i = 0; i < number; i++) {
voice = &emu->voices[(first_voice + i) % NUM_G];
// printk("voice alloc - %i, %i of %i\n", voice->number, idx-first_voice+1, number);
voice->use = 1;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册