Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci PR/25731: Adam K kirchhoff: Audigy support with ...



details:   https://anonhg.NetBSD.org/src/rev/19d1d31eaf86
branches:  trunk
changeset: 567012:19d1d31eaf86
user:      christos <christos%NetBSD.org@localhost>
date:      Thu May 27 20:20:52 2004 +0000

description:
PR/25731: Adam K kirchhoff: Audigy support with the emuxki driver.

diffstat:

 sys/dev/pci/emuxki.c    |  473 ++++++++++++++++++++++++++++++++++++-----------
 sys/dev/pci/emuxkireg.h |  124 +++++++++++-
 sys/dev/pci/emuxkivar.h |   11 +-
 sys/dev/pci/pcidevs     |    3 +-
 4 files changed, 484 insertions(+), 127 deletions(-)

diffs (truncated from 1073 to 300 lines):

diff -r 0dd3c5aa3bad -r 19d1d31eaf86 sys/dev/pci/emuxki.c
--- a/sys/dev/pci/emuxki.c      Thu May 27 19:19:00 2004 +0000
+++ b/sys/dev/pci/emuxki.c      Thu May 27 20:20:52 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: emuxki.c,v 1.34 2004/05/23 11:37:25 tsutsui Exp $      */
+/*     $NetBSD: emuxki.c,v 1.35 2004/05/27 20:20:52 christos Exp $     */
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -56,7 +56,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.34 2004/05/23 11:37:25 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.35 2004/05/27 20:20:52 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -114,6 +114,7 @@
 static int emuxki_voice_set_bufparms(struct emuxki_voice *,
                                     void *, u_int32_t, u_int16_t);
 static void emuxki_voice_commit_parms(struct emuxki_voice *);
+static int emuxki_voice_adc_rate(struct emuxki_voice *);
 static u_int32_t emuxki_voice_curaddr(struct emuxki_voice *);
 static void emuxki_voice_start(struct emuxki_voice *,
                               void (*) (void *), void *);
@@ -210,16 +211,12 @@
        NULL,                   /* dev_ioctl */
 };
 
-static const int emuxki_recsrc_adcrates[] =
-    { 48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000, -1 };
 #if 0
 static const int emuxki_recsrc_intrmasks[EMU_NUMRECSRCS] =
     { EMU_INTE_MICBUFENABLE, EMU_INTE_ADCBUFENABLE, EMU_INTE_EFXBUFENABLE };
 #endif
 static const u_int32_t emuxki_recsrc_bufaddrreg[EMU_NUMRECSRCS] =
     { EMU_MICBA, EMU_ADCBA, EMU_FXBA };
-static const u_int32_t emuxki_recsrc_idxreg[EMU_NUMRECSRCS] =
-    { EMU_RECIDX(EMU_MICIDX), EMU_RECIDX(EMU_ADCIDX), EMU_RECIDX(EMU_FXIDX) };
 static const u_int32_t emuxki_recsrc_szreg[EMU_NUMRECSRCS] =
     { EMU_MICBS, EMU_ADCBS, EMU_FXBS };
 static const int emuxki_recbuf_sz[] = {
@@ -335,13 +332,27 @@
        if ((err = emuxki_init(sc)))
                return (err);
 
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
-               EMU_HCFG_AUDIOENABLE | EMU_HCFG_JOYENABLE |
-               EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_AUTOMUTE);
+       if (sc->sc_type & EMUXKI_AUDIGY2) {
+               bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
+                       EMU_HCFG_AUDIOENABLE | EMU_HCFG_AC3ENABLE_CDSPDIF |
+                       EMU_HCFG_AC3ENABLE_GPSPDIF | EMU_HCFG_AUTOMUTE);
+       } else if (sc->sc_type & EMUXKI_AUDIGY) {
+               bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
+                       EMU_HCFG_AUDIOENABLE | EMU_HCFG_AUTOMUTE);
+       } else {
+               bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
+                       EMU_HCFG_AUDIOENABLE |
+                       EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_AUTOMUTE);
+       }
        bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
                bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) |
                EMU_INTE_VOLINCRENABLE | EMU_INTE_VOLDECRENABLE |
                EMU_INTE_MUTEENABLE);
+       if (sc->sc_type & EMUXKI_AUDIGY2) {
+               bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A_IOCFG,
+                       EMU_A_IOCFG_GPOUT0 |
+                       bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_A_IOCFG));
+       }
 
        /* No multiple voice support for now */
        sc->pvoice = sc->rvoice = NULL;
@@ -366,14 +377,17 @@
 {
        struct pci_attach_args *pa = aux;
 
-       if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CREATIVELABS &&
-           (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_SBLIVE ||
-            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_SBLIVE2))
-       {
-               return (1);
+       if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CREATIVELABS)
+               return 0;
+
+       switch (PCI_PRODUCT(pa->pa_id)) {
+       case PCI_PRODUCT_CREATIVELABS_SBLIVE:
+       case PCI_PRODUCT_CREATIVELABS_SBLIVE2:
+       case PCI_PRODUCT_CREATIVELABS_AUDIGY:
+               return 1;
+       default:
+               return 0;
        }
-
-       return (0);
 }
 
 static void
@@ -421,13 +435,34 @@
                bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
                return;
        }
-       aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
+
+ /* XXX it's unknown wheather APS is made from Audigy as well */
+        if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_AUDIGY) {
+                sc->sc_type = EMUXKI_AUDIGY;
+                if (PCI_REVISION(pa->pa_class) == 0x04) {
+                        sc->sc_type |= EMUXKI_AUDIGY2;
+                        strlcpy(sc->sc_audv.name, "Audigy2", sizeof sc->sc_audv.name);
+                } else {
+                        strlcpy(sc->sc_audv.name, "Audigy", sizeof sc->sc_audv.name);
+                }
+        } else if (pci_conf_read(pa->pa_pc, pa->pa_tag,
+            PCI_SUBSYS_ID_REG) == EMU_SUBSYS_APS) {
+                sc->sc_type = EMUXKI_APS;
+                strlcpy(sc->sc_audv.name, "E-mu APS", sizeof sc->sc_audv.name);
+        } else {
+                sc->sc_type = EMUXKI_SBLIVE;
+                strlcpy(sc->sc_audv.name, "SB Live!", sizeof sc->sc_audv.name);
+        }
+        snprintf(sc->sc_audv.version, sizeof sc->sc_audv.version, "0x%02x",
+                 PCI_REVISION(pa->pa_class));
+        strlcpy(sc->sc_audv.config, "emuxki", sizeof sc->sc_audv.config);
 
        if (emuxki_scinit(sc) || emuxki_ac97_init(sc) ||
            (sc->sc_audev = audio_attach_mi(&emuxki_hw_if, sc, self)) == NULL) {
                emuxki_pci_shutdown(sc);
                return;
        }
+       aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
 #if 0
        sc->rsourcectl.dev =
            sc->codecif->vtbl->get_portnum_by_name(sc->codec_if, AudioCrecord,
@@ -530,7 +565,9 @@
        u_int8_t        size, offset = 0;
        int             s;
 
-       ptr = ((((u_int32_t) reg) << 16) & EMU_PTR_ADDR_MASK) |
+       ptr = ((((u_int32_t) reg) << 16) &
+               (sc->sc_type & EMUXKI_AUDIGY ?
+                       EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK)) |
                (chano & EMU_PTR_CHNO_MASK);
        if (reg & 0xff000000) {
                size = (reg >> 24) & 0x3f;
@@ -555,7 +592,9 @@
        u_int8_t        size, offset;
        int             s;
 
-       ptr = ((((u_int32_t) reg) << 16) & EMU_PTR_ADDR_MASK) |
+       ptr = ((((u_int32_t) reg) << 16) &
+               (sc->sc_type & EMUXKI_AUDIGY ?
+                       EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK)) |
                (chano & EMU_PTR_CHNO_MASK);
        if (reg & 0xff000000) {
                size = (reg >> 24) & 0x3f;
@@ -576,21 +615,34 @@
 static void
 emuxki_write_micro(struct emuxki_softc *sc, u_int32_t pc, u_int32_t data)
 {
-       emuxki_write(sc, 0, EMU_MICROCODEBASE + pc, data);
+       emuxki_write(sc, 0,
+               (sc->sc_type & EMUXKI_AUDIGY ?
+                       EMU_A_MICROCODEBASE : EMU_MICROCODEBASE) + pc,
+                data);
 }
 
 static void
 emuxki_dsp_addop(struct emuxki_softc *sc, u_int16_t *pc, u_int8_t op,
                  u_int16_t r, u_int16_t a, u_int16_t x, u_int16_t y)
 {
-       emuxki_write_micro(sc, *pc << 1,
-               ((x << 10) & EMU_DSP_LOWORD_OPX_MASK) |
-               (y & EMU_DSP_LOWORD_OPY_MASK));
-       emuxki_write_micro(sc, (*pc << 1) + 1,
-               ((op << 20) & EMU_DSP_HIWORD_OPCODE_MASK) |
-               ((r << 10) & EMU_DSP_HIWORD_RESULT_MASK) |
-               (a & EMU_DSP_HIWORD_OPA_MASK));
-       (*pc)++;
+       if (sc->sc_type & EMUXKI_AUDIGY) {
+               emuxki_write_micro(sc, *pc << 1,
+                       ((x << 12) & EMU_A_DSP_LOWORD_OPX_MASK) |
+                       (y & EMU_A_DSP_LOWORD_OPY_MASK));
+               emuxki_write_micro(sc, (*pc << 1) + 1,
+                       ((op << 24) & EMU_A_DSP_HIWORD_OPCODE_MASK) |
+                       ((r << 12) & EMU_A_DSP_HIWORD_RESULT_MASK) |
+                       (a & EMU_A_DSP_HIWORD_OPA_MASK));
+       } else {
+               emuxki_write_micro(sc, *pc << 1,
+                       ((x << 10) & EMU_DSP_LOWORD_OPX_MASK) |
+                       (y & EMU_DSP_LOWORD_OPY_MASK));
+               emuxki_write_micro(sc, (*pc << 1) + 1,
+                       ((op << 20) & EMU_DSP_HIWORD_OPCODE_MASK) |
+                       ((r << 10) & EMU_DSP_HIWORD_RESULT_MASK) |
+                       (a & EMU_DSP_HIWORD_OPA_MASK));
+       }
+       (*pc)++;
 }
 
 /* init and shutdown */
@@ -608,43 +660,86 @@
                emuxki_write(sc, 0, EMU_TANKMEMADDRREGBASE + pc, 0);
        }
        pc = 0;
-       /* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
-       emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
-                         EMU_DSP_OUTL(EMU_DSP_OUT_AC97),
-                         EMU_DSP_CST(0),
-                         EMU_DSP_FX(0), EMU_DSP_CST(4));
-       emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
-                         EMU_DSP_OUTR(EMU_DSP_OUT_AC97),
-                         EMU_DSP_CST(0),
-                         EMU_DSP_FX(1), EMU_DSP_CST(4));
 
-       /* Rear channel OUT (l/r) = FX[2/3] * 4 */
+       if (sc->sc_type & EMUXKI_AUDIGY) {
+               /* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
+               emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+                                 EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_FRONT),
+                                 EMU_A_DSP_CST(0),
+                                 EMU_DSP_FX(0), EMU_A_DSP_CST(4));
+               emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+                                 EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_FRONT),
+                                 EMU_A_DSP_CST(0),
+                                 EMU_DSP_FX(1), EMU_A_DSP_CST(4));
+
+               /* Rear channel OUT (l/r) = FX[2/3] * 4 */
 #if 0
-       emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
-                         EMU_DSP_OUTL(EMU_DSP_OUT_RCHAN),
-                         EMU_DSP_OUTL(EMU_DSP_OUT_AC97),
-                         EMU_DSP_FX(0), EMU_DSP_CST(4));
-       emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
-                         EMU_DSP_OUTR(EMU_DSP_OUT_RCHAN),
-                         EMU_DSP_OUTR(EMU_DSP_OUT_AC97),
-                         EMU_DSP_FX(1), EMU_DSP_CST(4));
+               emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+                                 EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_REAR),
+                                 EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_FRONT),
+                                 EMU_DSP_FX(0), EMU_A_DSP_CST(4));
+               emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+                                 EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_REAR),
+                                 EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_FRONT),
+                                 EMU_DSP_FX(1), EMU_A_DSP_CST(4));
 #endif
-       /* ADC recording (l/r) = AC97 In (l/r) */
-       emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
-                         EMU_DSP_OUTL(EMU_DSP_OUT_ADC),
-                         EMU_DSP_INL(EMU_DSP_IN_AC97),
-                         EMU_DSP_CST(0), EMU_DSP_CST(0));
-       emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
-                         EMU_DSP_OUTR(EMU_DSP_OUT_ADC),
-                         EMU_DSP_INR(EMU_DSP_IN_AC97),
-                         EMU_DSP_CST(0), EMU_DSP_CST(0));
-       /* zero out the rest of the microcode */
-       while (pc < 512)
+               /* ADC recording (l/r) = AC97 In (l/r) */
+               emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
+                                 EMU_A_DSP_OUTL(EMU_A_DSP_OUT_ADC),
+                                 EMU_A_DSP_INL(EMU_DSP_IN_AC97),
+                                 EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
                emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
-                                 EMU_DSP_CST(0), EMU_DSP_CST(0),
+                                 EMU_A_DSP_OUTR(EMU_A_DSP_OUT_ADC),
+                                 EMU_A_DSP_INR(EMU_DSP_IN_AC97),
+                                 EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
+
+               /* zero out the rest of the microcode */
+               while (pc < 512)
+                       emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
+                                         EMU_A_DSP_CST(0), EMU_A_DSP_CST(0),
+                                         EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
+
+               emuxki_write(sc, 0, EMU_A_DBG, 0);      /* Is it really necessary ? */
+       } else {
+               /* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
+               emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+                                 EMU_DSP_OUTL(EMU_DSP_OUT_A_FRONT),
+                                 EMU_DSP_CST(0),
+                                 EMU_DSP_FX(0), EMU_DSP_CST(4));
+               emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+                                 EMU_DSP_OUTR(EMU_DSP_OUT_A_FRONT),
+                                 EMU_DSP_CST(0),
+                                 EMU_DSP_FX(1), EMU_DSP_CST(4));
+
+               /* Rear channel OUT (l/r) = FX[2/3] * 4 */
+#if 0
+               emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+                                 EMU_DSP_OUTL(EMU_DSP_OUT_AD_REAR),
+                                 EMU_DSP_OUTL(EMU_DSP_OUT_A_FRONT),
+                                 EMU_DSP_FX(0), EMU_DSP_CST(4));
+               emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
+                                 EMU_DSP_OUTR(EMU_DSP_OUT_AD_REAR),
+                                 EMU_DSP_OUTR(EMU_DSP_OUT_A_FRONT),
+                                 EMU_DSP_FX(1), EMU_DSP_CST(4));
+#endif
+               /* ADC recording (l/r) = AC97 In (l/r) */
+               emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
+                                 EMU_DSP_OUTL(EMU_DSP_OUT_ADC),



Home | Main Index | Thread Index | Old Index