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 b263c762c01a27d8d37c34f7c180ae2f6b207ac5..aab45a23320eac15c23f6b1c8dfd38cd6c7f0b3c 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 6a3476de74e66bef4bfdabb43d4e1f0c7b7d14b1..da7c988b5c97c6b2ac32936f0f8370120f91535d 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 0e3007120fb87e8d3a112e46016d9c282a6fce90..41a1cf10c6d88e219d1d2d2a5ce5dc5a2352b07b 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 c92253de881e9e9f8d965e283b929ebe1f02fb9d..708aff6cf09a72c5947864925cc7909ff0efba54 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) {