Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci Support for 4ch/6ch audio playback.



details:   https://anonhg.NetBSD.org/src/rev/27ab41dfd78d
branches:  trunk
changeset: 552621:27ab41dfd78d
user:      kent <kent%NetBSD.org@localhost>
date:      Sun Sep 28 13:37:19 2003 +0000

description:
Support for 4ch/6ch audio playback.

diffstat:

 sys/dev/pci/auich.c |  87 ++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 64 insertions(+), 23 deletions(-)

diffs (174 lines):

diff -r 0d7733ea631f -r 27ab41dfd78d sys/dev/pci/auich.c
--- a/sys/dev/pci/auich.c       Sun Sep 28 13:24:48 2003 +0000
+++ b/sys/dev/pci/auich.c       Sun Sep 28 13:37:19 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: auich.c,v 1.40 2003/08/19 21:04:22 erh Exp $   */
+/*     $NetBSD: auich.c,v 1.41 2003/09/28 13:37:19 kent Exp $  */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -103,10 +103,10 @@
  *     http://developer.intel.com/design/chipsets/manuals/298028.htm
  * ICH3:http://www.intel.com/design/chipsets/datashts/290716.htm
  * ICH4:http://www.intel.com/design/chipsets/datashts/290744.htm
+ * ICH5:http://www.intel.com/design/chipsets/datashts/252516.htm
  *
  * TODO:
  *     - Add support for the dedicated microphone input.
- *     - 4ch/6ch support.
  *
  * NOTE:
  *      - The 440MX B-stepping at running 100MHz has a hardware erratum.
@@ -115,7 +115,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: auich.c,v 1.40 2003/08/19 21:04:22 erh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: auich.c,v 1.41 2003/09/28 13:37:19 kent Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -227,7 +227,13 @@
 };
 
 #define IS_FIXED_RATE(codec)   !((codec)->vtbl->get_extcaps(codec) \
-                                 & AC97_EXT_AUDIO_VRA)
+                               & AC97_EXT_AUDIO_VRA)
+#define SUPPORTS_4CH(codec)    ((codec)->vtbl->get_extcaps(codec) \
+                               & AC97_EXT_AUDIO_SDAC)
+#define AC97_6CH_DACS          (AC97_EXT_AUDIO_SDAC | AC97_EXT_AUDIO_CDAC \
+                               | AC97_EXT_AUDIO_LDAC)
+#define SUPPORTS_6CH(codec)    (((codec)->vtbl->get_extcaps(codec) \
+                               & AC97_6CH_DACS) == AC97_6CH_DACS)
 
 /* Debug */
 #ifdef AUDIO_DEBUG
@@ -328,19 +334,19 @@
            "i82801AA (ICH) AC-97 Audio",       "ICH" },
        { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_ACA,
            "i82801AB (ICH0) AC-97 Audio",      "ICH0",
-           QUIRK_IGNORE_CODEC_READY_MAYBE }, /* i810-L */
+           QUIRK_IGNORE_CODEC_READY_MAYBE },
        { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_ACA,
            "i82801BA (ICH2) AC-97 Audio",      "ICH2",
            QUIRK_IGNORE_CODEC_READY_MAYBE },
        { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82440MX_ACA,
            "i82440MX AC-97 Audio",             "440MX" },
        { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CA_AC,
-           "i82801CA (ICH3) AC-97 Audio",      "ICH3" }, /* i830Mx i845MP/MZ*/
+           "i82801CA (ICH3) AC-97 Audio",      "ICH3" },
        { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DB_AC,
-           "i82801DB (ICH4) AC-97 Audio",      "ICH4",
+           "i82801DB/DBM (ICH4/ICH4M) AC-97 Audio",    "ICH4",
            QUIRK_IGNORE_CODEC_READY_MAYBE },
        { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801EB_AC,
-               "i82801EB (ICH5) AC-97 Audio",   "ICH5",
+           "i82801EB (ICH5) AC-97 Audio",   "ICH5",
            QUIRK_IGNORE_CODEC_READY },
        { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7012_AC,
            "SiS 7012 AC-97 Audio",             "SiS7012" },
@@ -488,16 +494,6 @@
                        return;
                }
        }
-       /* Print capabilities though there are no supports for now */
-       if ((status & ICH_SAMPLE_CAP) == ICH_POM20)
-               aprint_normal("%s: 20 bit precision support\n",
-                   sc->sc_dev.dv_xname);
-       if ((status & ICH_CHAN_CAP) == ICH_PCM4)
-               aprint_normal("%s: 4ch PCM output support\n",
-                   sc->sc_dev.dv_xname);
-       if ((status & ICH_CHAN_CAP) == ICH_PCM6)
-               aprint_normal("%s: 6ch PCM output support\n",
-                   sc->sc_dev.dv_xname);
 
        sc->host_if.arg = sc;
        sc->host_if.attach = auich_attach_codec;
@@ -690,13 +686,26 @@
 int
 auich_set_rate(struct auich_softc *sc, int mode, u_long srate)
 {
-       int reg;
+       int ret;
        u_long ratetmp;
 
        ratetmp = srate;
-       reg = mode == AUMODE_PLAY
-               ? AC97_REG_PCM_FRONT_DAC_RATE : AC97_REG_PCM_LR_ADC_RATE;
-       return sc->codec_if->vtbl->set_rate(sc->codec_if, reg, &ratetmp);
+       if (mode == AUMODE_RECORD)
+               return sc->codec_if->vtbl->set_rate(sc->codec_if,
+                   AC97_REG_PCM_LR_ADC_RATE, &ratetmp);
+       ret = sc->codec_if->vtbl->set_rate(sc->codec_if,
+           AC97_REG_PCM_FRONT_DAC_RATE, &ratetmp);
+       if (ret)
+               return ret;
+       ratetmp = srate;
+       ret = sc->codec_if->vtbl->set_rate(sc->codec_if,
+           AC97_REG_PCM_SURR_DAC_RATE, &ratetmp);
+       if (ret)
+               return ret;
+       ratetmp = srate;
+       ret = sc->codec_if->vtbl->set_rate(sc->codec_if,
+           AC97_REG_PCM_LFE_DAC_RATE, &ratetmp);
+       return ret;
 }
 
 int
@@ -706,6 +715,7 @@
        struct auich_softc *sc = v;
        struct audio_params *p;
        int mode;
+       u_int32_t control;
 
        for (mode = AUMODE_RECORD; mode != -1;
             mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
@@ -734,9 +744,30 @@
                p->hw_encoding = AUDIO_ENCODING_SLINEAR_LE;
                p->hw_precision = 16;
 
+               if (mode == AUMODE_RECORD) {
+                       if (p->channels < 1 || p->channels > 2)
+                               return EINVAL;
+               } else {
+                       switch (p->channels) {
+                       case 1:
+                               break;
+                       case 2:
+                               break;
+                       case 4:
+                               if (!SUPPORTS_4CH(sc->codec_if))
+                                       return EINVAL;
+                               break;
+                       case 6:
+                               if (!SUPPORTS_6CH(sc->codec_if))
+                                       return EINVAL;
+                               break;
+                       default:
+                               return EINVAL;
+                       }
+               }
                /* If monaural is requested, aurateconv expands a monaural
                 * stream to stereo. */
-               if (p->channels < 2)
+               if (p->channels == 1)
                        p->hw_channels = 2;
 
                switch (p->encoding) {
@@ -818,6 +849,16 @@
                        if (auich_set_rate(sc, mode, p->sample_rate))
                                return EINVAL;
                }
+               if (mode == AUMODE_PLAY) {
+                       control = bus_space_read_4(sc->iot, sc->aud_ioh, ICH_GCTRL);
+                       control &= ~ICH_PCM246_MASK;
+                       if (p->channels == 4) {
+                               control |= ICH_PCM4;
+                       } else if (p->channels == 6) {
+                               control |= ICH_PCM6;
+                       }
+                       bus_space_write_4(sc->iot, sc->aud_ioh, ICH_GCTRL, control);
+               }
        }
 
        return (0);



Home | Main Index | Thread Index | Old Index