Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci Work-in-progress of AC'97 modem support. Current...



details:   https://anonhg.NetBSD.org/src/rev/ff3f40dcd189
branches:  trunk
changeset: 580013:ff3f40dcd189
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Mon Apr 04 19:41:50 2005 +0000

description:
Work-in-progress of AC'97 modem support. Currently disabled by default
(can be enabled by options AUICH_ATTACH_MODEM), and untested. Shouldn't
have any impact on auich audio capabilities.

diffstat:

 sys/dev/pci/auich.c |  240 ++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 167 insertions(+), 73 deletions(-)

diffs (truncated from 491 to 300 lines):

diff -r b3c8ea192577 -r ff3f40dcd189 sys/dev/pci/auich.c
--- a/sys/dev/pci/auich.c       Mon Apr 04 19:11:18 2005 +0000
+++ b/sys/dev/pci/auich.c       Mon Apr 04 19:41:50 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: auich.c,v 1.90 2005/03/11 22:29:16 mycroft Exp $       */
+/*     $NetBSD: auich.c,v 1.91 2005/04/04 19:41:50 jmcneill Exp $      */
 
 /*-
  * Copyright (c) 2000, 2004, 2005 The NetBSD Foundation, Inc.
@@ -118,7 +118,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: auich.c,v 1.90 2005/03/11 22:29:16 mycroft Exp $");
+__KERNEL_RCSID(0, "$NetBSD: auich.c,v 1.91 2005/04/04 19:41:50 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -186,6 +186,7 @@
 
        struct ac97_codec_if *codec_if;
        struct ac97_host_if host_if;
+       int codecnum;
 
        /* DMA scatter-gather lists. */
        bus_dmamap_t sc_cddmamap;
@@ -222,8 +223,12 @@
        uint32_t sc_ac97_clock;
        int sc_ac97_clock_mib;
 
-#define AUICH_NFORMATS 3
-       struct audio_format sc_formats[AUICH_NFORMATS];
+       int     sc_modem_offset;
+
+#define AUICH_AUDIO_NFORMATS   3
+#define AUICH_MODEM_NFORMATS   1
+       struct audio_format sc_audio_formats[AUICH_AUDIO_NFORMATS];
+       struct audio_format sc_modem_formats[AUICH_MODEM_NFORMATS];
        struct audio_encoding_set *sc_encodings;
 };
 
@@ -287,6 +292,7 @@
 static int     auich_read_codec(void *, uint8_t, uint16_t *);
 static int     auich_write_codec(void *, uint8_t, uint16_t);
 static int     auich_reset_codec(void *);
+static enum ac97_host_flags auich_flags_codec(void *);
 
 const struct audio_hw_if auich_hw_if = {
        NULL,                   /* open */
@@ -318,9 +324,10 @@
        NULL,                   /* dev_ioctl */
 };
 
+#define AUICH_FORMATS_1CH      0
 #define AUICH_FORMATS_4CH      1
 #define AUICH_FORMATS_6CH      2
-static const struct audio_format auich_formats[AUICH_NFORMATS] = {
+static const struct audio_format auich_audio_formats[AUICH_AUDIO_NFORMATS] = {
        {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
         2, AUFMT_STEREO, 0, {8000, 48000}},
        {NULL, AUMODE_PLAY, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
@@ -329,6 +336,11 @@
         6, AUFMT_DOLBY_5_1, 0, {8000, 48000}},
 };
 
+static const struct audio_format auich_modem_formats[AUICH_MODEM_NFORMATS] = {
+       {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16,
+        1, AUFMT_MONAURAL, 0, {8000, 16000}},
+};
+
 #define PCI_ID_CODE0(v, p)     PCI_ID_CODE(PCI_VENDOR_##v, PCI_PRODUCT_##v##_##p)
 #define PCIID_ICH              PCI_ID_CODE0(INTEL, 82801AA_ACA)
 #define PCIID_ICH0             PCI_ID_CODE0(INTEL, 82801AB_ACA)
@@ -348,11 +360,15 @@
 #define PCIID_AMD768           PCI_ID_CODE0(AMD, PBC768_AC)
 #define PCIID_AMD8111          PCI_ID_CODE0(AMD, PBC8111_AC)
 
-static const struct auich_devtype {
+#define PCIID_ICH4MODEM                PCI_ID_CODE0(INTEL, 82801DB_MOD)
+
+struct auich_devtype {
        pcireg_t        id;
        const char      *name;
        const char      *shortname;     /* must be less than 11 characters */
-} auich_devices[] = {
+};
+
+static const struct auich_devtype auich_audio_devices[] = {
        { PCIID_ICH,    "i82801AA (ICH) AC-97 Audio",   "ICH" },
        { PCIID_ICH0,   "i82801AB (ICH0) AC-97 Audio",  "ICH0" },
        { PCIID_ICH2,   "i82801BA (ICH2) AC-97 Audio",  "ICH2" },
@@ -373,8 +389,15 @@
        { 0,            NULL,                           NULL },
 };
 
+static const struct auich_devtype auich_modem_devices[] = {
+#ifdef AUICH_ATTACH_MODEM
+       { PCIID_ICH4MODEM, "i82801DB (ICH4) AC-97 Modem", "ICH4MODEM" },
+#endif
+       { 0,            NULL,                           NULL },
+};
+
 static const struct auich_devtype *
-auich_lookup(struct pci_attach_args *pa)
+auich_lookup(struct pci_attach_args *pa, const struct auich_devtype *auich_devices)
 {
        const struct auich_devtype *d;
 
@@ -392,7 +415,9 @@
        struct pci_attach_args *pa;
 
        pa = aux;
-       if (auich_lookup(pa) != NULL)
+       if (auich_lookup(pa, auich_audio_devices) != NULL)
+               return 1;
+       if (auich_lookup(pa, auich_modem_devices) != NULL)
                return 1;
 
        return 0;
@@ -407,23 +432,31 @@
        pcireg_t v;
        const char *intrstr;
        const struct auich_devtype *d;
-       struct sysctlnode *node;
+       struct sysctlnode *node, *node_ac97clock;
        int err, node_mib, i;
 
        sc = (struct auich_softc *)self;
        pa = aux;
-       aprint_naive(": Audio controller\n");
 
-       d = auich_lookup(pa);
-       if (d == NULL)
+       if ((d = auich_lookup(pa, auich_modem_devices)) != NULL)
+               sc->sc_modem_offset = 0x10;
+       else if ((d = auich_lookup(pa, auich_audio_devices)) != NULL)
+               sc->sc_modem_offset = 0;
+       else
                panic("auich_attach: impossible");
 
+       if (sc->sc_modem_offset == 0)
+               aprint_naive(": Audio controller\n");
+       else
+               aprint_naive(": Modem controller\n");
+
        sc->sc_pc = pa->pa_pc;
        sc->sc_pt = pa->pa_tag;
 
        aprint_normal(": %s\n", d->name);
 
-       if (d->id == PCIID_ICH4 || d->id == PCIID_ICH5 || d->id == PCIID_ICH6) {
+       if (d->id == PCIID_ICH4 || d->id == PCIID_ICH5 || d->id == PCIID_ICH6
+           || d->id == PCIID_ICH4MODEM) {
                /*
                 * Use native mode for ICH4/ICH5/ICH6
                 */
@@ -524,32 +557,41 @@
        DPRINTF(ICH_DEBUG_DMA, ("auich_attach: lists %p %p %p\n",
            sc->pcmo.dmalist, sc->pcmi.dmalist, sc->mici.dmalist));
 
+       sc->codecnum = sc->sc_modem_offset == 0 ? 0 : 1;
+
        sc->host_if.arg = sc;
        sc->host_if.attach = auich_attach_codec;
        sc->host_if.read = auich_read_codec;
        sc->host_if.write = auich_write_codec;
        sc->host_if.reset = auich_reset_codec;
+       sc->host_if.flags = auich_flags_codec;
 
        if (ac97_attach(&sc->host_if, self) != 0)
                return;
 
        /* setup audio_format */
-       memcpy(sc->sc_formats, auich_formats, sizeof(auich_formats));
-       if (!AC97_IS_4CH(sc->codec_if))
-               AUFMT_INVALIDATE(&sc->sc_formats[AUICH_FORMATS_4CH]);
-       if (!AC97_IS_6CH(sc->codec_if))
-               AUFMT_INVALIDATE(&sc->sc_formats[AUICH_FORMATS_6CH]);
-       if (AC97_IS_FIXED_RATE(sc->codec_if)) {
-               for (i = 0; i < AUICH_NFORMATS; i++) {
-                       sc->sc_formats[i].frequency_type = 1;
-                       sc->sc_formats[i].frequency[0] = 48000;
+       if (sc->sc_modem_offset == 0) {
+               memcpy(sc->sc_audio_formats, auich_audio_formats, sizeof(auich_audio_formats));
+               if (!AC97_IS_4CH(sc->codec_if))
+                       AUFMT_INVALIDATE(&sc->sc_audio_formats[AUICH_FORMATS_4CH]);
+               if (!AC97_IS_6CH(sc->codec_if))
+                       AUFMT_INVALIDATE(&sc->sc_audio_formats[AUICH_FORMATS_6CH]);
+               if (AC97_IS_FIXED_RATE(sc->codec_if)) {
+                       for (i = 0; i < AUICH_AUDIO_NFORMATS; i++) {
+                               sc->sc_audio_formats[i].frequency_type = 1;
+                               sc->sc_audio_formats[i].frequency[0] = 48000;
+                       }
                }
+               if (0 != auconv_create_encodings(sc->sc_audio_formats, AUICH_AUDIO_NFORMATS,
+                                                &sc->sc_encodings))
+                       return;
+       } else {
+               memcpy(sc->sc_modem_formats, auich_modem_formats, sizeof(auich_modem_formats));
+               if (0 != auconv_create_encodings(sc->sc_modem_formats, AUICH_MODEM_NFORMATS,
+                                                &sc->sc_encodings))
+                       return;
        }
 
-       if (0 != auconv_create_encodings(sc->sc_formats, AUICH_NFORMATS,
-                                        &sc->sc_encodings)) {
-               return;
-       }
 
        /* Watch for power change */
        sc->sc_suspend = PWR_RESUME;
@@ -558,8 +600,9 @@
        config_interrupts(self, auich_finish_attach);
 
        /* sysctl setup */
-       if (AC97_IS_FIXED_RATE(sc->codec_if))
+       if (AC97_IS_FIXED_RATE(sc->codec_if) && sc->sc_modem_offset == 0)
                return;
+
        err = sysctl_createv(&sc->sc_log, 0, NULL, NULL, 0,
                             CTLTYPE_NODE, "hw", NULL, NULL, 0, NULL, 0,
                             CTL_HW, CTL_EOL);
@@ -571,15 +614,19 @@
        if (err != 0)
                goto sysctl_err;
        node_mib = node->sysctl_num;
-       /* passing the sc address instead of &sc->sc_ac97_clock */
-       err = sysctl_createv(&sc->sc_log, 0, NULL, &node, CTLFLAG_READWRITE,
-                            CTLTYPE_INT, "ac97rate",
-                            SYSCTL_DESCR("AC'97 codec link rate"),
-                            auich_sysctl_verify, 0, sc, 0,
-                            CTL_HW, node_mib, CTL_CREATE, CTL_EOL);
-       if (err != 0)
-               goto sysctl_err;
-       sc->sc_ac97_clock_mib = node->sysctl_num;
+
+       if (!AC97_IS_FIXED_RATE(sc->codec_if)) {
+               /* passing the sc address instead of &sc->sc_ac97_clock */
+               err = sysctl_createv(&sc->sc_log, 0, NULL, &node_ac97clock,
+                                    CTLFLAG_READWRITE,
+                                    CTLTYPE_INT, "ac97rate",
+                                    SYSCTL_DESCR("AC'97 codec link rate"),
+                                    auich_sysctl_verify, 0, sc, 0,
+                                    CTL_HW, node_mib, CTL_CREATE, CTL_EOL);
+               if (err != 0)
+                       goto sysctl_err;
+               sc->sc_ac97_clock_mib = node_ac97clock->sysctl_num;
+       }
 
        return;
 
@@ -648,13 +695,13 @@
 
        node = *rnode;
        sc = rnode->sysctl_data;
-       tmp = sc->sc_ac97_clock;
-       node.sysctl_data = &tmp;
-       error = sysctl_lookup(SYSCTLFN_CALL(&node));
-       if (error || newp == NULL)
-               return error;
+       if (node.sysctl_num == sc->sc_ac97_clock_mib) {
+               tmp = sc->sc_ac97_clock;
+               node.sysctl_data = &tmp;
+               error = sysctl_lookup(SYSCTLFN_CALL(&node));
+               if (error || newp == NULL)
+                       return error;
 
-       if (node.sysctl_num == sc->sc_ac97_clock_mib) {
                if (tmp < 48000 || tmp > 96000)
                        return EINVAL;
                sc->sc_ac97_clock = tmp;
@@ -686,16 +733,19 @@
        sc = v;
        /* wait for an access semaphore */
        for (i = ICH_SEMATIMO / ICH_CODECIO_INTERVAL; i-- &&
-           bus_space_read_1(sc->iot, sc->aud_ioh, ICH_CAS) & 1;
+           bus_space_read_1(sc->iot, sc->aud_ioh,
+               ICH_CAS + sc->sc_modem_offset) & 1;
            DELAY(ICH_CODECIO_INTERVAL));
 
        if (i > 0) {
-               *val = bus_space_read_2(sc->iot, sc->mix_ioh, reg);
+               *val = bus_space_read_2(sc->iot, sc->mix_ioh, reg + (sc->codecnum * 0x80));
                DPRINTF(ICH_DEBUG_CODECIO,
                    ("auich_read_codec(%x, %x)\n", reg, *val));
-               status = bus_space_read_4(sc->iot, sc->aud_ioh, ICH_GSTS);
+               status = bus_space_read_4(sc->iot, sc->aud_ioh,
+                   ICH_GSTS + sc->sc_modem_offset);
                if (status & ICH_RCS) {
-                       bus_space_write_4(sc->iot, sc->aud_ioh, ICH_GSTS,
+                       bus_space_write_4(sc->iot, sc->aud_ioh,
+                                         ICH_GSTS + sc->sc_modem_offset,
                                          status & ~(ICH_SRI|ICH_PRI|ICH_GSCI));
                        *val = 0xffff;
                        DPRINTF(ICH_DEBUG_CODECIO,
@@ -704,8 +754,7 @@
                }
                return 0;
        } else {
-               DPRINTF(ICH_DEBUG_CODECIO,



Home | Main Index | Thread Index | Old Index