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