Commit 6f3609f8 authored by Oswald Buddenhagen's avatar Oswald Buddenhagen Committed by Takashi Iwai

ALSA: emu10k1: add explicit support for E-MU 0404

Unlike the other models, this is actually a distinct card, rather than
an E-MU 1010 with different "dongles". It is stereo only, and supports
no ADAT (there is no trace of ADAT in the manual, switching the output
mode to ADAT has no effect, and switching the input mode to ADAT just
breaks input (presumably ... my only ADAT source is the card's output)).
Signed-off-by: default avatarOswald Buddenhagen <oswald.buddenhagen@gmx.de>
Link: https://lore.kernel.org/r/20230516093612.3536508-10-oswald.buddenhagen@gmx.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent f69d705d
...@@ -1621,7 +1621,9 @@ struct snd_emu_chip_details { ...@@ -1621,7 +1621,9 @@ struct snd_emu_chip_details {
unsigned int ca0108_chip:1; /* Audigy 2 Value */ unsigned int ca0108_chip:1; /* Audigy 2 Value */
unsigned int ca_cardbus_chip:1; /* Audigy 2 ZS Notebook */ unsigned int ca_cardbus_chip:1; /* Audigy 2 ZS Notebook */
unsigned int ca0151_chip:1; /* P16V */ unsigned int ca0151_chip:1; /* P16V */
unsigned int spk20:1; /* Stereo only */
unsigned int spk71:1; /* Has 7.1 speakers */ unsigned int spk71:1; /* Has 7.1 speakers */
unsigned int no_adat:1; /* Has no ADAT, only SPDIF */
unsigned int sblive51:1; /* SBLive! 5.1 - extout 0x11 -> center, 0x12 -> lfe */ unsigned int sblive51:1; /* SBLive! 5.1 - extout 0x11 -> center, 0x12 -> lfe */
unsigned int spdif_bug:1; /* Has Spdif phasing bug */ unsigned int spdif_bug:1; /* Has Spdif phasing bug */
unsigned int ac97_chip:2; /* Has an AC97 chip: 1 = mandatory, 2 = optional */ unsigned int ac97_chip:2; /* Has an AC97 chip: 1 = mandatory, 2 = optional */
......
...@@ -852,9 +852,14 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) ...@@ -852,9 +852,14 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg); dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg);
/* Optical -> ADAT I/O */ if (emu->card_capabilities->no_adat) {
emu->emu1010.optical_in = 1; /* IN_ADAT */ emu->emu1010.optical_in = 0; /* IN_SPDIF */
emu->emu1010.optical_out = 1; /* OUT_ADAT */ emu->emu1010.optical_out = 0; /* OUT_SPDIF */
} else {
/* Optical -> ADAT I/O */
emu->emu1010.optical_in = 1; /* IN_ADAT */
emu->emu1010.optical_out = 1; /* OUT_ADAT */
}
tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) | tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) |
(emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF); (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF);
snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp); snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
...@@ -1117,7 +1122,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = { ...@@ -1117,7 +1122,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = {
.id = "EMU0404", .id = "EMU0404",
.emu10k2_chip = 1, .emu10k2_chip = 1,
.ca0108_chip = 1, .ca0108_chip = 1,
.spk71 = 1, .spk20 = 1,
.no_adat = 1,
.emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 new revision */ .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 new revision */
/* This is MAEM8850 "HanaLite" */ /* This is MAEM8850 "HanaLite" */
/* Supports sync daughter card. */ /* Supports sync daughter card. */
...@@ -1127,7 +1133,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = { ...@@ -1127,7 +1133,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = {
.id = "EMU0404", .id = "EMU0404",
.emu10k2_chip = 1, .emu10k2_chip = 1,
.ca0102_chip = 1, .ca0102_chip = 1,
.spk71 = 1, .spk20 = 1,
.no_adat = 1,
.emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */
/* EMU0404 PCIe */ /* EMU0404 PCIe */
/* Does NOT support sync daughter card. */ /* Does NOT support sync daughter card. */
...@@ -1136,7 +1143,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = { ...@@ -1136,7 +1143,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = {
.id = "EMU0404", .id = "EMU0404",
.emu10k2_chip = 1, .emu10k2_chip = 1,
.ca0108_chip = 1, .ca0108_chip = 1,
.spk71 = 1, .spk20 = 1,
.no_adat = 1,
.emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 PCIe ver_03 */ .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 PCIe ver_03 */
{.vendor = 0x1102, .device = 0x0008, {.vendor = 0x1102, .device = 0x0008,
.driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]", .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]",
......
...@@ -144,6 +144,8 @@ static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol, ...@@ -144,6 +144,8 @@ static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
EMU_SRC_ALICE_EMU32B+0xe, \ EMU_SRC_ALICE_EMU32B+0xe, \
EMU_SRC_ALICE_EMU32B+0xf EMU_SRC_ALICE_EMU32B+0xf
/* 1010 rev1 */
#define EMU1010_COMMON_TEXTS \ #define EMU1010_COMMON_TEXTS \
"Silence", \ "Silence", \
PAIR_TEXTS("Dock Mic", "A", "B"), \ PAIR_TEXTS("Dock Mic", "A", "B"), \
...@@ -230,6 +232,26 @@ static const unsigned short emu1616_src_regs[] = { ...@@ -230,6 +232,26 @@ static const unsigned short emu1616_src_regs[] = {
}; };
static_assert(ARRAY_SIZE(emu1616_src_regs) == ARRAY_SIZE(emu1616_src_texts)); static_assert(ARRAY_SIZE(emu1616_src_regs) == ARRAY_SIZE(emu1616_src_texts));
/* 0404 rev1 & rev2 */
#define EMU0404_COMMON_TEXTS \
"Silence", \
LR_TEXTS("ADC"), \
LR_TEXTS("SPDIF")
static const char * const emu0404_src_texts[] = {
EMU0404_COMMON_TEXTS,
DSP_TEXTS,
};
static const unsigned short emu0404_src_regs[] = {
EMU_SRC_SILENCE,
LR_REGS(EMU_SRC_HAMOA_ADC),
LR_REGS(EMU_SRC_HANA_SPDIF),
EMU32_SRC_REGS,
};
static_assert(ARRAY_SIZE(emu0404_src_regs) == ARRAY_SIZE(emu0404_src_texts));
/* /*
* Data destinations - physical EMU outputs. * Data destinations - physical EMU outputs.
* Each destination has an enum mixer control to choose a data source * Each destination has an enum mixer control to choose a data source
...@@ -238,6 +260,8 @@ static_assert(ARRAY_SIZE(emu1616_src_regs) == ARRAY_SIZE(emu1616_src_texts)); ...@@ -238,6 +260,8 @@ static_assert(ARRAY_SIZE(emu1616_src_regs) == ARRAY_SIZE(emu1616_src_texts));
#define LR_CTLS(base) LR_PS(base, " Playback Enum") #define LR_CTLS(base) LR_PS(base, " Playback Enum")
#define ADAT_CTLS(pfx) ADAT_PS(pfx, " Playback Enum") #define ADAT_CTLS(pfx) ADAT_PS(pfx, " Playback Enum")
/* 1010 rev1 */
static const char * const emu1010_output_texts[] = { static const char * const emu1010_output_texts[] = {
LR_CTLS("Dock DAC1"), LR_CTLS("Dock DAC1"),
LR_CTLS("Dock DAC2"), LR_CTLS("Dock DAC2"),
...@@ -347,6 +371,25 @@ static const unsigned short emu1616_output_dflt[] = { ...@@ -347,6 +371,25 @@ static const unsigned short emu1616_output_dflt[] = {
}; };
static_assert(ARRAY_SIZE(emu1616_output_dflt) == ARRAY_SIZE(emu1616_output_dst)); static_assert(ARRAY_SIZE(emu1616_output_dflt) == ARRAY_SIZE(emu1616_output_dst));
/* 0404 rev1 & rev2 */
static const char * const snd_emu0404_output_texts[] = {
LR_CTLS("DAC"),
LR_CTLS("SPDIF"),
};
static const unsigned short emu0404_output_dst[] = {
LR_REGS(EMU_DST_HAMOA_DAC),
LR_REGS(EMU_DST_HANA_SPDIF),
};
static_assert(ARRAY_SIZE(emu0404_output_dst) == ARRAY_SIZE(snd_emu0404_output_texts));
static const unsigned short emu0404_output_dflt[] = {
EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
};
static_assert(ARRAY_SIZE(emu0404_output_dflt) == ARRAY_SIZE(emu0404_output_dst));
/* /*
* Data destinations - FPGA outputs going to Alice2 (Audigy) for * Data destinations - FPGA outputs going to Alice2 (Audigy) for
* capture (EMU32 + I2S links) * capture (EMU32 + I2S links)
...@@ -436,6 +479,25 @@ static const unsigned short emu1010_input_dflt[] = { ...@@ -436,6 +479,25 @@ static const unsigned short emu1010_input_dflt[] = {
}; };
static_assert(ARRAY_SIZE(emu1010_input_dflt) == ARRAY_SIZE(emu1010_input_dst)); static_assert(ARRAY_SIZE(emu1010_input_dflt) == ARRAY_SIZE(emu1010_input_dst));
static const unsigned short emu0404_input_dflt[] = {
EMU_SRC_HAMOA_ADC_LEFT1,
EMU_SRC_HAMOA_ADC_RIGHT1,
EMU_SRC_SILENCE,
EMU_SRC_SILENCE,
EMU_SRC_SILENCE,
EMU_SRC_SILENCE,
EMU_SRC_SILENCE,
EMU_SRC_SILENCE,
EMU_SRC_HANA_SPDIF_LEFT1,
EMU_SRC_HANA_SPDIF_RIGHT1,
EMU_SRC_SILENCE,
EMU_SRC_SILENCE,
EMU_SRC_SILENCE,
EMU_SRC_SILENCE,
EMU_SRC_SILENCE,
EMU_SRC_SILENCE,
};
struct snd_emu1010_routing_info { struct snd_emu1010_routing_info {
const char * const *src_texts; const char * const *src_texts;
const char * const *out_texts; const char * const *out_texts;
...@@ -451,6 +513,7 @@ struct snd_emu1010_routing_info { ...@@ -451,6 +513,7 @@ struct snd_emu1010_routing_info {
const struct snd_emu1010_routing_info emu1010_routing_info[] = { const struct snd_emu1010_routing_info emu1010_routing_info[] = {
{ {
/* rev1 1010 */
.src_regs = emu1010_src_regs, .src_regs = emu1010_src_regs,
.src_texts = emu1010_src_texts, .src_texts = emu1010_src_texts,
.n_srcs = ARRAY_SIZE(emu1010_src_texts), .n_srcs = ARRAY_SIZE(emu1010_src_texts),
...@@ -494,16 +557,26 @@ const struct snd_emu1010_routing_info emu1010_routing_info[] = { ...@@ -494,16 +557,26 @@ const struct snd_emu1010_routing_info emu1010_routing_info[] = {
.in_regs = emu1010_input_dst, .in_regs = emu1010_input_dst,
.n_ins = ARRAY_SIZE(emu1010_input_dst) - 6, .n_ins = ARRAY_SIZE(emu1010_input_dst) - 6,
}, },
{
/* 0404 */
.src_regs = emu0404_src_regs,
.src_texts = emu0404_src_texts,
.n_srcs = ARRAY_SIZE(emu0404_src_texts),
.out_dflts = emu0404_output_dflt,
.out_regs = emu0404_output_dst,
.out_texts = snd_emu0404_output_texts,
.n_outs = ARRAY_SIZE(emu0404_output_dflt),
.in_dflts = emu0404_input_dflt,
.in_regs = emu1010_input_dst,
.n_ins = ARRAY_SIZE(emu1010_input_dst) - 6,
},
}; };
static unsigned emu1010_idx(struct snd_emu10k1 *emu) static unsigned emu1010_idx(struct snd_emu10k1 *emu)
{ {
if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) return emu->card_capabilities->emu_model - 1;
return 2;
else if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010B)
return 1;
else
return 0;
} }
static void snd_emu1010_output_source_apply(struct snd_emu10k1 *emu, static void snd_emu1010_output_source_apply(struct snd_emu10k1 *emu,
...@@ -780,7 +853,7 @@ struct snd_emu1010_pads_info { ...@@ -780,7 +853,7 @@ struct snd_emu1010_pads_info {
const struct snd_emu1010_pads_info emu1010_pads_info[] = { const struct snd_emu1010_pads_info emu1010_pads_info[] = {
{ {
/* all other e-mu cards for now */ /* rev1 1010 */
.adc_ctls = snd_emu1010_adc_pads, .adc_ctls = snd_emu1010_adc_pads,
.n_adc_ctls = ARRAY_SIZE(snd_emu1010_adc_pads), .n_adc_ctls = ARRAY_SIZE(snd_emu1010_adc_pads),
.dac_ctls = snd_emu1010_dac_pads, .dac_ctls = snd_emu1010_dac_pads,
...@@ -800,6 +873,13 @@ const struct snd_emu1010_pads_info emu1010_pads_info[] = { ...@@ -800,6 +873,13 @@ const struct snd_emu1010_pads_info emu1010_pads_info[] = {
.dac_ctls = snd_emu1010_dac_pads + 1, .dac_ctls = snd_emu1010_dac_pads + 1,
.n_dac_ctls = ARRAY_SIZE(snd_emu1010_dac_pads) - 2, .n_dac_ctls = ARRAY_SIZE(snd_emu1010_dac_pads) - 2,
}, },
{
/* 0404 */
.adc_ctls = NULL,
.n_adc_ctls = 0,
.dac_ctls = NULL,
.n_dac_ctls = 0,
},
}; };
...@@ -2225,14 +2305,16 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, ...@@ -2225,14 +2305,16 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
if (err < 0) if (err < 0)
return err; return err;
err = snd_ctl_add(card, if (!emu->card_capabilities->no_adat) {
snd_ctl_new1(&snd_emu1010_optical_out, emu)); err = snd_ctl_add(card,
if (err < 0) snd_ctl_new1(&snd_emu1010_optical_out, emu));
return err; if (err < 0)
err = snd_ctl_add(card, return err;
snd_ctl_new1(&snd_emu1010_optical_in, emu)); err = snd_ctl_add(card,
if (err < 0) snd_ctl_new1(&snd_emu1010_optical_in, emu));
return err; if (err < 0)
return err;
}
err = add_emu1010_source_mixers(emu); err = add_emu1010_source_mixers(emu);
if (err < 0) if (err < 0)
......
...@@ -229,14 +229,16 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry, ...@@ -229,14 +229,16 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
u32 rate; u32 rate;
if (emu->card_capabilities->emu_model) { if (emu->card_capabilities->emu_model) {
snd_emu1010_fpga_read(emu, 0x38, &value); if (!emu->card_capabilities->no_adat) {
if ((value & 0x1) == 0) { snd_emu1010_fpga_read(emu, 0x38, &value);
snd_emu1010_fpga_read(emu, 0x2a, &value); if ((value & 0x1) == 0) {
snd_emu1010_fpga_read(emu, 0x2b, &value2); snd_emu1010_fpga_read(emu, 0x2a, &value);
rate = 0x1770000 / (((value << 5) | value2)+1); snd_emu1010_fpga_read(emu, 0x2b, &value2);
snd_iprintf(buffer, "ADAT Locked : %u\n", rate); rate = 0x1770000 / (((value << 5) | value2)+1);
} else { snd_iprintf(buffer, "ADAT Locked : %u\n", rate);
snd_iprintf(buffer, "ADAT Unlocked\n"); } else {
snd_iprintf(buffer, "ADAT Unlocked\n");
}
} }
snd_emu1010_fpga_read(emu, 0x20, &value); snd_emu1010_fpga_read(emu, 0x20, &value);
if ((value & 0x4) == 0) { if ((value & 0x4) == 0) {
......
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