ALSA: emu10k1: add explicit support for E-MU 0404
authorOswald Buddenhagen <oswald.buddenhagen@gmx.de>
Tue, 16 May 2023 09:36:11 +0000 (11:36 +0200)
committerTakashi Iwai <tiwai@suse.de>
Wed, 17 May 2023 15:07:58 +0000 (17:07 +0200)
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: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Link: https://lore.kernel.org/r/20230516093612.3536508-10-oswald.buddenhagen@gmx.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/sound/emu10k1.h
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/emuproc.c

index b263c76..aab45a2 100644 (file)
@@ -1621,7 +1621,9 @@ struct snd_emu_chip_details {
        unsigned int ca0108_chip:1;     /* Audigy 2 Value */
        unsigned int ca_cardbus_chip:1; /* Audigy 2 ZS Notebook */
        unsigned int ca0151_chip:1;     /* P16V */
+       unsigned int spk20:1;           /* Stereo only */
        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 spdif_bug:1;       /* Has Spdif phasing bug */
        unsigned int ac97_chip:2;       /* Has an AC97 chip: 1 = mandatory, 2 = optional */
index 6a3476d..da7c988 100644 (file)
@@ -852,9 +852,14 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
 
        snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
        dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg);
-       /* Optical -> ADAT I/O  */
-       emu->emu1010.optical_in = 1; /* IN_ADAT */
-       emu->emu1010.optical_out = 1; /* OUT_ADAT */
+       if (emu->card_capabilities->no_adat) {
+               emu->emu1010.optical_in = 0; /* IN_SPDIF */
+               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) |
                (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF);
        snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
@@ -1117,7 +1122,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = {
         .id = "EMU0404",
         .emu10k2_chip = 1,
         .ca0108_chip = 1,
-        .spk71 = 1,
+        .spk20 = 1,
+        .no_adat = 1,
         .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 new revision */
        /* This is MAEM8850 "HanaLite" */
        /* Supports sync daughter card. */
@@ -1127,7 +1133,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = {
         .id = "EMU0404",
         .emu10k2_chip = 1,
         .ca0102_chip = 1,
-        .spk71 = 1,
+        .spk20 = 1,
+        .no_adat = 1,
         .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */
        /* EMU0404 PCIe */
        /* Does NOT support sync daughter card. */
@@ -1136,7 +1143,8 @@ static const struct snd_emu_chip_details emu_chip_details[] = {
         .id = "EMU0404",
         .emu10k2_chip = 1,
         .ca0108_chip = 1,
-        .spk71 = 1,
+        .spk20 = 1,
+        .no_adat = 1,
         .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 PCIe ver_03 */
        {.vendor = 0x1102, .device = 0x0008,
         .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]",
index 0e30071..41a1cf1 100644 (file)
@@ -144,6 +144,8 @@ static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
        EMU_SRC_ALICE_EMU32B+0xe, \
        EMU_SRC_ALICE_EMU32B+0xf
 
+/* 1010 rev1 */
+
 #define EMU1010_COMMON_TEXTS \
        "Silence", \
        PAIR_TEXTS("Dock Mic", "A", "B"), \
@@ -230,6 +232,26 @@ static const unsigned short emu1616_src_regs[] = {
 };
 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.
  * 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));
 #define LR_CTLS(base) LR_PS(base, " Playback Enum")
 #define ADAT_CTLS(pfx) ADAT_PS(pfx, " Playback Enum")
 
+/* 1010 rev1 */
+
 static const char * const emu1010_output_texts[] = {
        LR_CTLS("Dock DAC1"),
        LR_CTLS("Dock DAC2"),
@@ -347,6 +371,25 @@ static const unsigned short emu1616_output_dflt[] = {
 };
 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
  *   capture (EMU32 + I2S links)
@@ -436,6 +479,25 @@ static const unsigned short emu1010_input_dflt[] = {
 };
 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 {
        const char * const *src_texts;
        const char * const *out_texts;
@@ -451,6 +513,7 @@ struct snd_emu1010_routing_info {
 
 const struct snd_emu1010_routing_info emu1010_routing_info[] = {
        {
+               /* rev1 1010 */
                .src_regs = emu1010_src_regs,
                .src_texts = emu1010_src_texts,
                .n_srcs = ARRAY_SIZE(emu1010_src_texts),
@@ -494,16 +557,26 @@ const struct snd_emu1010_routing_info emu1010_routing_info[] = {
                .in_regs = emu1010_input_dst,
                .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)
 {
-       if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616)
-               return 2;
-       else if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010B)
-               return 1;
-       else
-               return 0;
+       return emu->card_capabilities->emu_model - 1;
 }
 
 static void snd_emu1010_output_source_apply(struct snd_emu10k1 *emu,
@@ -780,7 +853,7 @@ struct snd_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,
                .n_adc_ctls = ARRAY_SIZE(snd_emu1010_adc_pads),
                .dac_ctls = snd_emu1010_dac_pads,
@@ -800,6 +873,13 @@ const struct snd_emu1010_pads_info emu1010_pads_info[] = {
                .dac_ctls = snd_emu1010_dac_pads + 1,
                .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,
                if (err < 0)
                        return err;
 
-               err = snd_ctl_add(card,
-                       snd_ctl_new1(&snd_emu1010_optical_out, emu));
-               if (err < 0)
-                       return err;
-               err = snd_ctl_add(card,
-                       snd_ctl_new1(&snd_emu1010_optical_in, emu));
-               if (err < 0)
-                       return err;
+               if (!emu->card_capabilities->no_adat) {
+                       err = snd_ctl_add(card,
+                               snd_ctl_new1(&snd_emu1010_optical_out, emu));
+                       if (err < 0)
+                               return err;
+                       err = snd_ctl_add(card,
+                               snd_ctl_new1(&snd_emu1010_optical_in, emu));
+                       if (err < 0)
+                               return err;
+               }
 
                err = add_emu1010_source_mixers(emu);
                if (err < 0)
index c92253d..708aff6 100644 (file)
@@ -229,14 +229,16 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
        u32 rate;
 
        if (emu->card_capabilities->emu_model) {
-               snd_emu1010_fpga_read(emu, 0x38, &value);
-               if ((value & 0x1) == 0) {
-                       snd_emu1010_fpga_read(emu, 0x2a, &value);
-                       snd_emu1010_fpga_read(emu, 0x2b, &value2);
-                       rate = 0x1770000 / (((value << 5) | value2)+1); 
-                       snd_iprintf(buffer, "ADAT Locked : %u\n", rate);
-               } else {
-                       snd_iprintf(buffer, "ADAT Unlocked\n");
+               if (!emu->card_capabilities->no_adat) {
+                       snd_emu1010_fpga_read(emu, 0x38, &value);
+                       if ((value & 0x1) == 0) {
+                               snd_emu1010_fpga_read(emu, 0x2a, &value);
+                               snd_emu1010_fpga_read(emu, 0x2b, &value2);
+                               rate = 0x1770000 / (((value << 5) | value2)+1);
+                               snd_iprintf(buffer, "ADAT Locked : %u\n", rate);
+                       } else {
+                               snd_iprintf(buffer, "ADAT Unlocked\n");
+                       }
                }
                snd_emu1010_fpga_read(emu, 0x20, &value);
                if ((value & 0x4) == 0) {