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 driver for C-Media CMI8x38 Audio Chip. From ...



details:   https://anonhg.NetBSD.org/src/rev/1983f8676b83
branches:  trunk
changeset: 485551:1983f8676b83
user:      augustss <augustss%NetBSD.org@localhost>
date:      Sun Apr 30 21:59:58 2000 +0000

description:
Add driver for C-Media CMI8x38 Audio Chip. From Takuya SHIOZAKI <AoiMoe%imou.to@localhost>

diffstat:

 sys/dev/pci/cmpci.c    |  1616 ++++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/pci/cmpcireg.h |   196 +++++
 sys/dev/pci/cmpcivar.h |   144 ++++
 sys/dev/pci/eap.c      |   439 +++++++-----
 sys/dev/pci/eapreg.h   |    21 +-
 sys/dev/pci/files.pci  |     7 +-
 6 files changed, 2246 insertions(+), 177 deletions(-)

diffs (truncated from 2703 to 300 lines):

diff -r 1488345f13de -r 1983f8676b83 sys/dev/pci/cmpci.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/pci/cmpci.c       Sun Apr 30 21:59:58 2000 +0000
@@ -0,0 +1,1616 @@
+/*     $NetBSD: cmpci.c,v 1.1 2000/04/30 21:59:58 augustss Exp $       */
+
+/*
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Takuya SHIOZAKI <AoiMoe%imou.to@localhost> .
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * C-Media CMI8x38 Audio Chip Support.
+ *
+ * TODO:
+ *   - Legacy MPU, OPL and Joystick support (but, I have no interest...)
+ *   - SPDIF support.
+ *
+ * ACKNOWLEDGEMENT:
+ *   - Lennart Augustsson : He touched up this code.
+ *
+ */
+
+#undef CMPCI_SPDIF_SUPPORT  /* XXX: not working */
+
+#if defined(AUDIO_DEBUG) || defined(DEBUG)
+#define DPRINTF(x) printf x
+#else
+#define DPRINTF(x)
+#endif
+
+#include "mpu.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+
+#include <dev/pci/pcidevs.h>
+#include <dev/pci/pcivar.h>
+
+#include <sys/audioio.h>
+#include <dev/audio_if.h>
+#include <dev/midi_if.h>
+
+#include <dev/mulaw.h>
+#include <dev/auconv.h>
+#include <dev/pci/cmpcireg.h>
+#include <dev/pci/cmpcivar.h>
+
+#include <dev/ic/mpuvar.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+/*
+ * Low-level HW interface
+ */
+static __inline uint8_t cmpci_mixerreg_read __P((struct cmpci_softc *,
+                                                 uint8_t));
+static __inline void cmpci_mixerreg_write __P((struct cmpci_softc *,
+                                               uint8_t, uint8_t));
+static __inline void cmpci_reg_partial_write_4 __P((struct cmpci_softc *,
+                                                    int, int,
+                                                    uint32_t, uint32_t));
+static __inline void cmpci_reg_set_4 __P((struct cmpci_softc *,
+                                          int, uint32_t));
+static __inline void cmpci_reg_clear_4 __P((struct cmpci_softc *,
+                                            int, uint32_t));
+static int cmpci_rate_to_index __P((int));
+static __inline int cmpci_index_to_rate __P((int));
+static __inline int cmpci_index_to_divider __P((int));
+
+static int cmpci_adjust __P((int, int));
+static void cmpci_set_mixer_gain __P((struct cmpci_softc *, int));
+static int cmpci_set_in_ports __P((struct cmpci_softc *, int));
+
+
+/*
+ * autoconf interface
+ */
+static int cmpci_match __P((struct device *, struct cfdata *, void *));
+static void cmpci_attach __P((struct device *, struct device *, void *));
+
+struct cfattach cmpci_ca = {
+       sizeof (struct cmpci_softc), cmpci_match, cmpci_attach
+};
+
+/* interrupt */
+static int cmpci_intr __P((void *));
+
+
+/*
+ * DMA stuffs
+ */
+static int cmpci_alloc_dmamem __P((struct cmpci_softc *,
+                                   size_t, int, int, caddr_t *));
+static int cmpci_free_dmamem __P((struct cmpci_softc *, caddr_t, int));
+static struct cmpci_dmanode * cmpci_find_dmamem __P((struct cmpci_softc *,
+                                                     caddr_t));
+
+
+/*
+ * interface to machine independent layer
+ */
+static int cmpci_open __P((void *, int));
+static void cmpci_close __P((void *));
+static int cmpci_query_encoding __P((void *, struct audio_encoding *));
+static int cmpci_set_params __P((void *, int, int,
+                                 struct audio_params *,
+                                 struct audio_params *));
+static int cmpci_round_blocksize __P((void *, int));
+static int cmpci_halt_output __P((void *));
+static int cmpci_halt_input __P((void *));
+static int cmpci_getdev __P((void *, struct audio_device *));
+static int cmpci_set_port __P((void *, mixer_ctrl_t *));
+static int cmpci_get_port __P((void *, mixer_ctrl_t *));
+static int cmpci_query_devinfo __P((void *, mixer_devinfo_t *));
+static void *cmpci_allocm __P((void *, int, size_t, int, int));
+static void cmpci_freem __P((void *, void *, int));
+static size_t cmpci_round_buffersize __P((void *, int, size_t));
+static int cmpci_mappage __P((void *, void *, int, int));
+static int cmpci_get_props __P((void *));
+static int cmpci_trigger_output __P((void *, void *, void *, int,
+                                     void (*)(void *), void *,
+                                     struct audio_params *));
+static int cmpci_trigger_input __P((void *, void *, void *, int,
+                                    void (*)(void *), void *,
+                                    struct audio_params *));
+
+static struct audio_hw_if cmpci_hw_if = {
+       &cmpci_open,            /* open */
+       &cmpci_close,           /* close */
+       NULL,                   /* drain */
+       &cmpci_query_encoding,  /* query_encoding */
+       &cmpci_set_params,      /* set_params */
+       &cmpci_round_blocksize, /* round_blocksize */
+       NULL,                   /* commit_settings */
+       NULL,                   /* init_output */
+       NULL,                   /* init_input */
+       NULL,                   /* start_output */
+       NULL,                   /* start_input */
+       &cmpci_halt_output,     /* halt_output */
+       &cmpci_halt_input,      /* halt_input */
+       NULL,                   /* speaker_ctl */
+       &cmpci_getdev,          /* getdev */
+       NULL,                   /* setfd */
+       &cmpci_set_port,        /* set_port */
+       &cmpci_get_port,        /* get_port */
+       &cmpci_query_devinfo,   /* query_devinfo */
+       &cmpci_allocm,          /* allocm */
+       &cmpci_freem,           /* freem */
+       &cmpci_round_buffersize,/* round_buffersize */
+       &cmpci_mappage,         /* mappage */
+       &cmpci_get_props,       /* get_props */
+       &cmpci_trigger_output,  /* trigger_output */
+       &cmpci_trigger_input    /* trigger_input */
+};
+
+
+/*
+ * Low-level HW interface
+ */
+
+/* mixer register read/write */
+static __inline uint8_t
+cmpci_mixerreg_read(sc, no)
+       struct cmpci_softc *sc;
+       uint8_t no;
+{
+       uint8_t ret;
+
+       bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
+       delay(10);
+       ret = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA);
+       delay(10);
+       return ret;
+}
+
+static __inline void
+cmpci_mixerreg_write(sc, no, val)
+       struct cmpci_softc *sc;
+       uint8_t no, val;
+{
+       bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
+       delay(10);
+       bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA, val);
+       delay(10);
+}
+
+
+/* register partial write */
+static __inline void
+cmpci_reg_partial_write_4(sc, no, shift, mask, val)
+       struct cmpci_softc *sc;
+       int no, shift;
+       uint32_t mask, val;
+{
+       bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
+           (val<<shift) |
+           (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift)));
+       delay(10);
+}
+
+/* register set/clear bit */
+static __inline void
+cmpci_reg_set_4(sc, no, mask)
+       struct cmpci_softc *sc;
+       int no;
+       uint32_t mask;
+{
+       bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
+            (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask));
+       delay(10);
+}
+
+static __inline void
+cmpci_reg_clear_4(sc, no, mask)
+       struct cmpci_softc *sc;
+       int no;
+       uint32_t mask;
+{
+       bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
+            (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask));
+       delay(10);
+}
+
+
+/* rate */
+static struct {
+       int rate;
+       int divider;
+} cmpci_rate_table[CMPCI_REG_NUMRATE] = {
+#define _RATE(n) { n, CMPCI_REG_RATE_ ## n }
+       _RATE(5512),
+       _RATE(8000),
+       _RATE(11025),
+       _RATE(16000),
+       _RATE(22050),
+       _RATE(32000),
+       _RATE(44100),
+       _RATE(48000)
+#undef  _RATE
+};
+
+static int
+cmpci_rate_to_index(rate)
+       int rate;
+{
+       int i;
+
+       for (i = 0; i < CMPCI_REG_NUMRATE - 2; i++)
+               if (rate <=
+                   (cmpci_rate_table[i].rate+cmpci_rate_table[i+1].rate) / 2)
+                       return i;
+       return i;  /* 48000 */
+}
+
+static __inline int
+cmpci_index_to_rate(index)
+       int index;
+{
+       return cmpci_rate_table[index].rate;
+}
+
+static __inline int
+cmpci_index_to_divider(index)
+       int index;
+{
+       return cmpci_rate_table[index].divider;
+}
+
+
+/*



Home | Main Index | Thread Index | Old Index