Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Initial import of the Maestro 2/2e 'esm' PCI aud...
details: https://anonhg.NetBSD.org/src/rev/6f58d1ceede0
branches: trunk
changeset: 501875:6f58d1ceede0
user: rh <rh%NetBSD.org@localhost>
date: Mon Jan 08 19:54:31 2001 +0000
description:
Initial import of the Maestro 2/2e 'esm' PCI audio driver. This driver
is based on the FreeBSD 'maestro' driver by Taku YAMAMOTO
<taku%cent.saitama-u.ac.jp@localhost>
diffstat:
sys/dev/pci/esm.c | 1417 ++++++++++++++++++++++++++++++++++++++++++++++++++
sys/dev/pci/esmreg.h | 352 ++++++++++++
sys/dev/pci/esmvar.h | 158 +++++
3 files changed, 1927 insertions(+), 0 deletions(-)
diffs (truncated from 1939 to 300 lines):
diff -r edb57d9f3cf6 -r 6f58d1ceede0 sys/dev/pci/esm.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/pci/esm.c Mon Jan 08 19:54:31 2001 +0000
@@ -0,0 +1,1417 @@
+/* $NetBSD: esm.c,v 1.1 2001/01/08 19:54:31 rh Exp $ */
+
+/*-
+ * Copyright (c) 2000, 2001 Rene Hexel <rh%netbsd.org@localhost>
+ * All rights reserved.
+ *
+ * Copyright (c) 2000 Taku YAMAMOTO <taku%cent.saitama-u.ac.jp@localhost>
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Taku Id: maestro.c,v 1.12 2000/09/06 03:32:34 taku Exp
+ * FreeBSD: /c/ncvs/src/sys/dev/sound/pci/maestro.c,v 1.4 2000/12/18 01:36:35 cg Exp
+ */
+
+/*
+ * TODO:
+ * - hardware volume support
+ * - recording
+ * - MIDI support
+ * - joystick support
+ * - power management hooks
+ *
+ *
+ * Credits:
+ *
+ * This code is based on the FreeBSD driver written by Taku YAMAMOTO
+ *
+ *
+ * Original credits from the FreeBSD driver:
+ *
+ * Part of this code (especially in many magic numbers) was heavily inspired
+ * by the Linux driver originally written by
+ * Alan Cox <alan.cox%linux.org@localhost>, modified heavily by
+ * Zach Brown <zab%zabbo.net@localhost>.
+ *
+ * busdma()-ize and buffer size reduction were suggested by
+ * Cameron Grant <gandalf%vilnya.demon.co.uk@localhost>.
+ * Also he showed me the way to use busdma() suite.
+ *
+ * Internal speaker problems on NEC VersaPro's and Dell Inspiron 7500
+ * were looked at by
+ * Munehiro Matsuda <haro%tk.kubota.co.jp@localhost>,
+ * who brought patches based on the Linux driver with some simplification.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+
+#include <sys/audioio.h>
+#include <dev/audio_if.h>
+#include <dev/mulaw.h>
+#include <dev/auconv.h>
+#include <dev/ic/ac97var.h>
+
+#include <dev/pci/pcidevs.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/pci/esmreg.h>
+#include <dev/pci/esmvar.h>
+
+#define PCI_CBIO 0x10 /* Configuration Base I/O Address */
+
+/* Debug */
+#ifdef AUDIO_DEBUG
+#define DPRINTF(l,x) do { if (esm_debug & (l)) printf x; } while(0)
+#define DUMPREG(x) do { if (esm_debug & ESM_DEBUG_REG) \
+ esm_dump_regs(x); } while(0)
+int esm_debug = 0xfffc;
+#define ESM_DEBUG_CODECIO 0x0001
+#define ESM_DEBUG_IRQ 0x0002
+#define ESM_DEBUG_DMA 0x0004
+#define ESM_DEBUG_TIMER 0x0008
+#define ESM_DEBUG_REG 0x0010
+#define ESM_DEBUG_PARAM 0x0020
+#define ESM_DEBUG_APU 0x0040
+#define ESM_DEBUG_CODEC 0x0080
+#else
+#define DPRINTF(x,y) /* nothing */
+#define DUMPREG(x) /* nothing */
+#endif
+
+#ifdef DIAGNOSTIC
+#define RANGE(n, l, h) if ((n) < (l) || (n) >= (h)) \
+ printf (#n "=%d out of range (%d, %d) in " \
+ __FILE__ ", line %d\n", (n), (l), (h), __LINE__)
+#else
+#define RANGE(x,y,z) /* nothing */
+#endif
+
+#define inline __inline
+
+static inline void ringbus_setdest(struct esm_softc *, int, int);
+
+static inline u_int16_t wp_rdreg(struct esm_softc *, u_int16_t);
+static inline void wp_wrreg(struct esm_softc *, u_int16_t, u_int16_t);
+static inline u_int16_t wp_rdapu(struct esm_softc *, int, u_int16_t);
+static inline void wp_wrapu(struct esm_softc *, int, u_int16_t,
+ u_int16_t);
+static inline void wp_settimer(struct esm_softc *, u_int);
+static inline void wp_starttimer(struct esm_softc *);
+static inline void wp_stoptimer(struct esm_softc *);
+
+static inline u_int16_t wc_rdreg(struct esm_softc *, u_int16_t);
+static inline void wc_wrreg(struct esm_softc *, u_int16_t, u_int16_t);
+static inline u_int16_t wc_rdchctl(struct esm_softc *, int);
+static inline void wc_wrchctl(struct esm_softc *, int, u_int16_t);
+
+static inline u_int calc_timer_freq(struct esm_chinfo*);
+static void set_timer(struct esm_softc *);
+
+static void esmch_set_format(struct esm_chinfo *,
+ struct audio_params *p);
+
+struct cfattach esm_ca = {
+ sizeof(struct esm_softc), esm_match, esm_attach
+};
+
+struct audio_hw_if esm_hw_if = {
+ esm_open,
+ esm_close,
+ NULL, /* drain */
+ esm_query_encoding,
+ esm_set_params,
+ esm_round_blocksize,
+ NULL, /* commit_settings */
+ esm_init_output,
+ NULL, /* init_input */
+ NULL, /* start_output */
+ NULL, /* start_input */
+ esm_halt_output,
+ esm_halt_input,
+ NULL, /* speaker_ctl */
+ esm_getdev,
+ NULL, /* getfd */
+ esm_set_port,
+ esm_get_port,
+ esm_query_devinfo,
+ esm_malloc,
+ esm_free,
+ esm_round_buffersize,
+ esm_mappage,
+ esm_get_props,
+ esm_trigger_output,
+ esm_trigger_input
+};
+
+struct audio_device esm_device = {
+ "ESS Maestro",
+ "",
+ "esm"
+};
+
+
+static audio_encoding_t esm_encoding[] = {
+ { 0, AudioEulinear, AUDIO_ENCODING_ULINEAR, 8, 0 },
+ { 1, AudioEmulaw, AUDIO_ENCODING_ULAW, 8,
+ AUDIO_ENCODINGFLAG_EMULATED },
+ { 2, AudioEalaw, AUDIO_ENCODING_ALAW, 8, AUDIO_ENCODINGFLAG_EMULATED },
+ { 3, AudioEslinear, AUDIO_ENCODING_SLINEAR, 8, 0 },
+ { 4, AudioEslinear_le, AUDIO_ENCODING_SLINEAR_LE, 16, 0 },
+ { 5, AudioEulinear_le, AUDIO_ENCODING_ULINEAR_LE, 16,
+ AUDIO_ENCODINGFLAG_EMULATED },
+ { 6, AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16,
+ AUDIO_ENCODINGFLAG_EMULATED },
+ { 7, AudioEulinear_be, AUDIO_ENCODING_ULINEAR_BE, 16,
+ AUDIO_ENCODINGFLAG_EMULATED },
+};
+
+#define MAESTRO_NENCODINGS 8
+
+#ifdef AUDIO_DEBUG
+struct esm_reg_info {
+ int offset; /* register offset */
+ int width; /* 1/2/4 bytes */
+} dump_regs[] = {
+ { PORT_WAVCACHE_CTRL, 2 },
+ { PORT_HOSTINT_CTRL, 2 },
+ { PORT_HOSTINT_STAT, 2 },
+ { PORT_HWVOL_VOICE_SHADOW, 1 },
+ { PORT_HWVOL_VOICE, 1 },
+ { PORT_HWVOL_MASTER_SHADOW, 1 },
+ { PORT_HWVOL_MASTER, 1 },
+ { PORT_RINGBUS_CTRL, 4 },
+ { PORT_GPIO_DATA, 2 },
+ { PORT_GPIO_MASK, 2 },
+ { PORT_GPIO_DIR, 2 },
+ { PORT_ASSP_CTRL_A, 1 },
+ { PORT_ASSP_CTRL_B, 1 },
+ { PORT_ASSP_CTRL_C, 1 },
+ { PORT_ASSP_INT_STAT, 1 },
+ { -1, -1 }
+};
+
+static
+void esm_dump_regs(struct esm_softc *ess)
+{
+ int i = 0;
+
+ printf("%s registers:", ess->sc_dev.dv_xname);
+ while (dump_regs[i].offset != -1) {
+ if (i % 5 == 0)
+ printf("\n");
+ printf("0x%2.2x: ", dump_regs[i].offset);
+ switch(dump_regs[i].width) {
+ case 4:
+ printf("%8.8x, ", bus_space_read_4(ess->st, ess->sh,
+ dump_regs[i].offset));
+ break;
+ case 2:
+ printf("%4.4x, ", bus_space_read_2(ess->st, ess->sh,
+ dump_regs[i].offset));
+ break;
+ default:
+ printf("%2.2x, ",
+ bus_space_read_1(ess->st, ess->sh,
+ dump_regs[i].offset));
+ }
+ i++;
+ }
+ printf("\n");
+}
+#endif
+
+/* -----------------------------
+ * Subsystems.
+ */
+
+/* Codec/Ringbus */
+
+/* -------------------------------------------------------------------- */
+
+int
+esm_read_codec(void *sc, u_int8_t regno, u_int16_t *result)
+{
+ struct esm_softc *ess = sc;
+ unsigned t;
+
+ /* We have to wait for a SAFE time to write addr/data */
+ for (t = 0; t < 20; t++) {
+ if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT)
+ & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS)
+ break;
+ delay(2); /* 20.8us / 13 */
+ }
+ if (t == 20)
+ printf("%s: esm_read_codec() PROGLESS timed out.\n",
+ ess->sc_dev.dv_xname);
+
+ bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD,
+ CODEC_CMD_READ | regno);
+ delay(21); /* AC97 cycle = 20.8usec */
+
+ /* Wait for data retrieve */
+ for (t = 0; t < 20; t++) {
+ if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT)
+ & CODEC_STAT_MASK) == CODEC_STAT_RW_DONE)
+ break;
+ delay(2); /* 20.8us / 13 */
+ }
+ if (t == 20)
+ /* Timed out, but perform dummy read. */
+ printf("%s: esm_read_codec() RW_DONE timed out.\n",
+ ess->sc_dev.dv_xname);
+
+ *result = bus_space_read_2(ess->st, ess->sh, PORT_CODEC_REG);
+
+ return 0;
+}
+
+int
+esm_write_codec(void *sc, u_int8_t regno, u_int16_t data)
Home |
Main Index |
Thread Index |
Old Index