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