Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci Add a quirk table for specific implementations.



details:   https://anonhg.NetBSD.org/src/rev/e92c6b413da6
branches:  trunk
changeset: 501971:e92c6b413da6
user:      rh <rh%NetBSD.org@localhost>
date:      Tue Jan 09 23:27:07 2001 +0000

description:
Add a quirk table for specific implementations.
Change the NEC-specific subvendor test for GPIO initialization into a more
generic quirk table flag.
Add a quirk flag for hardware that has left and right channels reversed
(currently the COMPAL 38W2 a.k.a. Dell Inspiron 5000e)
Clean up PCM channel initialization and add channel swapping option.

diffstat:

 sys/dev/pci/esm.c    |  121 +++++++++++++++++++++++++++++++++++---------------
 sys/dev/pci/esmvar.h |   18 +++++++-
 2 files changed, 102 insertions(+), 37 deletions(-)

diffs (279 lines):

diff -r 66f467fec1c1 -r e92c6b413da6 sys/dev/pci/esm.c
--- a/sys/dev/pci/esm.c Tue Jan 09 23:20:22 2001 +0000
+++ b/sys/dev/pci/esm.c Tue Jan 09 23:27:07 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: esm.c,v 1.2 2001/01/09 06:36:13 lukem Exp $    */
+/*     $NetBSD: esm.c,v 1.3 2001/01/09 23:27:07 rh Exp $       */
 
 /*-
  * Copyright (c) 2000, 2001 Rene Hexel <rh%netbsd.org@localhost>
@@ -99,6 +99,7 @@
 #define ESM_DEBUG_PARAM                0x0020
 #define ESM_DEBUG_APU          0x0040
 #define ESM_DEBUG_CODEC                0x0080
+#define ESM_DEBUG_PCI          0x0100
 #else
 #define DPRINTF(x,y)   /* nothing */
 #define DUMPREG(x)     /* nothing */
@@ -193,6 +194,34 @@
 
 #define MAESTRO_NENCODINGS 8
 
+
+static const struct esm_quirks esm_quirks[] = {
+       /* COMPAL 38W2 OEM Notebook, e.g. Dell INSPIRON 5000e */
+       { PCI_VENDOR_COMPAL, PCI_PRODUCT_COMPAL_38W2, ESM_QUIRKF_SWAPPEDCH },
+
+       /* NEC Versa Pro LX VA26D */
+       { PCI_VENDOR_NEC, PCI_PRODUCT_NEC_VA26D, ESM_QUIRKF_GPIO },
+
+       /* NEC Versa LX */
+       { PCI_VENDOR_NEC, PCI_PRODUCT_NEC_VERSALX, ESM_QUIRKF_GPIO }
+};
+
+enum esm_quirk_flags
+esm_get_quirks(pcireg_t subid)
+{
+       int i;
+
+       for (i = 0; i < (sizeof esm_quirks / sizeof esm_quirks[0]); i++) {
+               if (PCI_VENDOR(subid) == esm_quirks[i].eq_vendor &&
+                   PCI_PRODUCT(subid) == esm_quirks[i].eq_product) {
+                       return esm_quirks[i].eq_quirks;
+               }
+       }
+
+       return 0;
+}
+
+
 #ifdef AUDIO_DEBUG
 struct esm_reg_info {
        int     offset;                 /* register offset */
@@ -212,17 +241,16 @@
        { PORT_ASSP_CTRL_A,             1 },
        { PORT_ASSP_CTRL_B,             1 },
        { PORT_ASSP_CTRL_C,             1 },
-       { PORT_ASSP_INT_STAT,           1 },
-       { -1, -1 }
+       { PORT_ASSP_INT_STAT,           1 }
 };
 
 static void
 esm_dump_regs(struct esm_softc *ess)
 {
-       int i = 0;
+       int i;
 
        printf("%s registers:", ess->sc_dev.dv_xname);
-       while (dump_regs[i].offset != -1) {
+       for (i = 0; i < (sizeof dump_regs / sizeof dump_regs[0]); i++) {
                if (i % 5 == 0)
                        printf("\n");
                printf("0x%2.2x: ", dump_regs[i].offset);
@@ -240,12 +268,12 @@
                            bus_space_read_1(ess->st, ess->sh,
                            dump_regs[i].offset));
                }
-               i++;
        }
        printf("\n");
 }
 #endif
 
+
 /* -----------------------------
  * Subsystems.
  */
@@ -493,6 +521,15 @@
 }
 
 
+enum ac97_host_flags
+esm_flags_codec(void *sc)
+{
+       struct esm_softc *ess = sc;
+
+       return ess->codec_flags;
+}
+
+
 void
 esm_initcodec(struct esm_softc *ess)
 {
@@ -585,23 +622,14 @@
         * Setup GPIO.
         * There seems to be speciality with NEC systems.
         */
-       switch (PCI_VENDOR(ess->subid)) {
-       case PCI_VENDOR_NEC:
-               switch (PCI_PRODUCT(ess->subid)) {
-               case PCI_PRODUCT_NEC_VERSALX:
-               case PCI_PRODUCT_NEC_VA26D:
-                       /* Matthew Braithwaite <matt%braithwaite.net@localhost> reported
-                        * that NEC Versa LX doesn't need GPIO operation. */
-                       bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK,
-                           0x9ff);
-                       bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR,
-                           bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR) |
-                               0x600);
-                       bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA,
-                           0x200);
-                       break;
-               }
-               break;
+       if (esm_get_quirks(ess->subid) & ESM_QUIRKF_GPIO) {
+               bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK,
+                   0x9ff);
+               bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR,
+                   bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR) |
+                       0x600);
+               bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA,
+                   0x200);
        }
 
        DUMPREG(ess);
@@ -646,6 +674,7 @@
        struct esm_chinfo *ch = &ess->pch;
        struct esm_dma *p;
        int pan = 0, choffset;
+       int i, nch = 1;
        unsigned speed = ch->sample_rate, offset, wpwa, dv;
        size_t size;
        u_int16_t apuch = ch->num << 1;
@@ -693,8 +722,11 @@
                offset >>= 1;
                /* FALLTHROUGH */
        case APUTYPE_8BITSTEREO:
-               pan = 8;
-               apuch++;
+               if (ess->codec_flags & AC97_HOST_SWAPPED_CHANNELS)
+                       pan = 8;
+               else
+                       pan = -8;
+               nch++;
                break;
        case APUTYPE_8BITLINEAR:
                ess->pch.apublk <<= 1;
@@ -711,26 +743,27 @@
        dv = (((speed % 48000) << 16) + 24000) / 48000
            + ((speed / 48000) << 16);
 
-       do {
-               wp_wrapu(ess, apuch, APUREG_WAVESPACE, wpwa & 0xff00);
-               wp_wrapu(ess, apuch, APUREG_CURPTR, offset);
-               wp_wrapu(ess, apuch, APUREG_ENDPTR, offset + size);
-               wp_wrapu(ess, apuch, APUREG_LOOPLEN, size - 1);
-               wp_wrapu(ess, apuch, APUREG_AMPLITUDE, 0xe800);
-               wp_wrapu(ess, apuch, APUREG_POSITION, 0x8f00
+       for (i = nch-1; i >= 0; i--) {
+               wp_wrapu(ess, apuch + i, APUREG_WAVESPACE, wpwa & 0xff00);
+               wp_wrapu(ess, apuch + i, APUREG_CURPTR, offset);
+               wp_wrapu(ess, apuch + i, APUREG_ENDPTR, offset + size);
+               wp_wrapu(ess, apuch + i, APUREG_LOOPLEN, size - 1);
+               wp_wrapu(ess, apuch + i, APUREG_AMPLITUDE, 0xe800);
+               wp_wrapu(ess, apuch + i, APUREG_POSITION, 0x8f00
                    | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT)
                    | ((PAN_FRONT + pan) << APU_PAN_SHIFT));
-               wp_wrapu(ess, apuch, APUREG_FREQ_LOBYTE, APU_plus6dB
+               wp_wrapu(ess, apuch + i, APUREG_FREQ_LOBYTE, APU_plus6dB
                    | ((dv & 0xff) << APU_FREQ_LOBYTE_SHIFT));
-               wp_wrapu(ess, apuch, APUREG_FREQ_HIWORD, dv >> 8);
+               wp_wrapu(ess, apuch + i, APUREG_FREQ_HIWORD, dv >> 8);
 
                if (ch->aputype == APUTYPE_16BITSTEREO)
                        wpwa |= APU_STEREO >> 1;
                pan = -pan;
-       } while (pan < 0 && apuch--);
+       }
 
        wc_wrchctl(ess, apuch, ch->wcreg_tpl);
-       wc_wrchctl(ess, apuch + 1, ch->wcreg_tpl);
+       if (nch > 1)
+               wc_wrchctl(ess, apuch + 1, ch->wcreg_tpl);
 
        wp_wrapu(ess, apuch, APUREG_APUTYPE,
            (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
@@ -1289,6 +1322,11 @@
        ess->pc = pc;
        ess->subid = pci_conf_read(pc, tag, PCI_SUBSYS_ID_REG);
 
+       DPRINTF(ESM_DEBUG_PCI,
+           ("%s: sub-system vendor 0x%4.4x, product 0x%4.4x\n",
+           ess->sc_dev.dv_xname,
+           PCI_VENDOR(ess->subid), PCI_PRODUCT(ess->subid)));
+
        /* Map and establish the interrupt. */
        if (pci_intr_map(pa, &ih)) {
                printf("%s: can't map interrupt\n", ess->sc_dev.dv_xname);
@@ -1335,12 +1373,23 @@
                return;
        }
 
+       /*
+        * Some cards and Notebooks appear to have left and right channels
+        * reversed.  Check if there is a corresponding quirk entry for
+        * the subsystem vendor and product and if so, set the appropriate
+        * codec flag.
+        */
+       if (esm_get_quirks(ess->subid) & ESM_QUIRKF_SWAPPEDCH) {
+               ess->codec_flags |= AC97_HOST_SWAPPED_CHANNELS;
+       }
+
        /* initialize AC97 host interface */
        ess->host_if.arg = self;
        ess->host_if.attach = esm_attach_codec;
        ess->host_if.read = esm_read_codec;
        ess->host_if.write = esm_write_codec;
        ess->host_if.reset = esm_reset_codec;
+       ess->host_if.flags = esm_flags_codec;
 
        if (ac97_attach(&ess->host_if) != 0)
                return;
diff -r 66f467fec1c1 -r e92c6b413da6 sys/dev/pci/esmvar.h
--- a/sys/dev/pci/esmvar.h      Tue Jan 09 23:20:22 2001 +0000
+++ b/sys/dev/pci/esmvar.h      Tue Jan 09 23:27:07 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: esmvar.h,v 1.1 2001/01/08 19:54:31 rh Exp $    */
+/*     $NetBSD: esmvar.h,v 1.2 2001/01/09 23:27:07 rh Exp $    */
 
 /*-
  * Copyright (c) 2000, 2001 Rene Hexel <rh%netbsd.org@localhost>
@@ -99,6 +99,7 @@
 
        struct ac97_codec_if    *codec_if;
        struct ac97_host_if     host_if;
+       enum ac97_host_flags    codec_flags;
 
        struct esm_dma          *sc_dmas;
 
@@ -113,10 +114,23 @@
        void *sc_rarg;
 };
 
+struct esm_quirks {
+       pci_vendor_id_t         eq_vendor;      /* subsystem vendor */
+       pci_product_id_t        eq_product;     /* and product */
+
+       enum esm_quirk_flags {
+               ESM_QUIRKF_GPIO = 0x1,          /* needs GPIO operation */
+               ESM_QUIRKF_SWAPPEDCH = 0x2,     /* left/right is reversed */
+       };
+
+       enum esm_quirk_flags    eq_quirks;      /* needed quirks */
+};
+
 int    esm_read_codec(void *, u_int8_t, u_int16_t *);
 int    esm_write_codec(void *, u_int8_t, u_int16_t);
 int    esm_attach_codec(void *, struct ac97_codec_if *);
 void   esm_reset_codec(void *);
+enum ac97_host_flags   esm_flags_codec(void *);
 
 void   esm_power(struct esm_softc *, int);
 void   esm_init(struct esm_softc *);
@@ -156,3 +170,5 @@
 int    esm_suspend(struct esm_softc *);
 int    esm_resume(struct esm_softc *);
 int    esm_shutdown(struct esm_softc *);
+
+enum esm_quirk_flags   esm_get_quirks(pcireg_t);



Home | Main Index | Thread Index | Old Index