Source-Changes-HG archive

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

[src/netbsd-1-5]: src/sys/dev/pci Pull up revisions 1.1-1.6, 1.8 (new, reques...



details:   https://anonhg.NetBSD.org/src/rev/ccee4bc3adc1
branches:  netbsd-1-5
changeset: 491634:ccee4bc3adc1
user:      he <he%NetBSD.org@localhost>
date:      Sun May 06 14:39:36 2001 +0000

description:
Pull up revisions 1.1-1.6, 1.8 (new, requested by sommerfeld):
  Add a driver for the NeoMagic 256 AC'97 chip.

diffstat:

 sys/dev/pci/neo.c |  1044 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1044 insertions(+), 0 deletions(-)

diffs (truncated from 1048 to 300 lines):

diff -r 95716f9bca7c -r ccee4bc3adc1 sys/dev/pci/neo.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/pci/neo.c Sun May 06 14:39:36 2001 +0000
@@ -0,0 +1,1044 @@
+/*     $NetBSD: neo.c,v 1.8.2.2 2001/05/06 14:39:36 he Exp $   */
+
+/*
+ * Copyright (c) 1999 Cameron Grant <gandalf%vilnya.demon.co.uk@localhost>
+ * All rights reserved.
+ *
+ * Derived from the public domain Linux driver
+ *
+ * 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, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * FreeBSD: src/sys/dev/sound/pci/neomagic.c,v 1.8 2000/03/20 15:30:50 cg Exp
+ * OpenBSD: neo.c,v 1.4 2000/07/19 09:04:37 csapuntz Exp
+ */
+
+#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 <dev/pci/pcidevs.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/pci/neoreg.h>
+#include <dev/pci/neo-coeff.h>
+
+#include <sys/audioio.h>
+#include <dev/audio_if.h>
+#include <dev/mulaw.h>
+#include <dev/auconv.h>
+
+#include <dev/ic/ac97var.h>
+
+
+/* -------------------------------------------------------------------- */
+/* 
+ * As of 04/13/00, public documentation on the Neomagic 256 is not available.
+ * These comments were gleaned by looking at the driver carefully.
+ *
+ * The Neomagic 256 AV/ZX chips provide both video and audio capabilities
+ * on one chip. About 2-6 megabytes of memory are associated with
+ * the chip. Most of this goes to video frame buffers, but some is used for
+ * audio buffering
+ *
+ * Unlike most PCI audio chips, the Neomagic chip does not rely on DMA.
+ * Instead, the chip allows you to carve out two ring buffers out of its
+ * memory. However you carve this and how much you can carve seems to be
+ * voodoo. The algorithm is in nm_init.
+ *
+ * Most Neomagic audio chips use the AC-97 codec interface. However, there 
+ * seem to be a select few chips 256AV chips that do not support AC-97.
+ * This driver does not support them but there are rumors that it
+ * mgiht work with wss isa drivers. This might require some playing around
+ * with your BIOS.
+ *
+ * The Neomagic 256 AV/ZX have 2 PCI I/O region descriptors. Both of
+ * them describe a memory region. The frame buffer is the first region
+ * and the register set is the secodn region.
+ *
+ * The register manipulation logic is taken from the Linux driver,
+ * which is in the public domain.
+ *
+ * The Neomagic is even nice enough to map the AC-97 codec registers into
+ * the register space to allow direct manipulation. Watch out, accessing
+ * AC-97 registers on the Neomagic requires great delicateness, otherwise
+ * the thing will hang the PCI bus, rendering your system frozen.
+ *
+ * For one, it seems the Neomagic status register that reports AC-97
+ * readiness should NOT be polled more often than once each 1ms.
+ *
+ * Also, writes to the AC-97 register space may take order 40us to
+ * complete.
+ *
+ * Unlike many sound engines, the Neomagic does not support (as fas as
+ * we know :) the notion of interrupting every n bytes transferred,
+ * unlike many DMA engines.  Instead, it allows you to specify one
+ * location in each ring buffer (called the watermark). When the chip
+ * passes that location while playing, it signals an interrupt.
+ * 
+ * The ring buffer size is currently 16k. That is about 100ms of audio
+ * at 44.1khz/stero/16 bit. However, to keep the buffer full, interrupts
+ * are generated more often than that, so 20-40 interrupts per second
+ * should not be unexpected. Increasing BUFFSIZE should help minimize
+ * of glitches due to drivers that spend to much time looping at high
+ * privelege levels as well as the impact of badly written audio
+ * interface clients.
+ *
+ * TO-DO list:
+ *    Figure out interaction with video stuff (look at Xfree86 driver?)
+ *
+ *    Figure out how to shrink that huge table neo-coeff.h
+ */
+
+#define        NM_BUFFSIZE     16384
+
+/* device private data */
+struct neo_softc {
+       struct          device dev;
+
+       bus_space_tag_t bufiot;
+       bus_space_handle_t  bufioh;
+
+       bus_space_tag_t regiot;
+       bus_space_handle_t  regioh;
+
+       u_int32_t       type;
+       void            *ih;
+
+       void    (*pintr)(void *);       /* dma completion intr handler */
+       void    *parg;          /* arg for intr() */
+
+       void    (*rintr)(void *);       /* dma completion intr handler */
+       void    *rarg;          /* arg for intr() */
+
+       vaddr_t buf_vaddr;
+       vaddr_t rbuf_vaddr;
+       vaddr_t pbuf_vaddr;
+       int     pbuf_allocated;
+       int     rbuf_allocated;
+
+       bus_addr_t buf_pciaddr;
+       bus_addr_t rbuf_pciaddr;
+       bus_addr_t pbuf_pciaddr;
+
+       u_int32_t       ac97_base, ac97_status, ac97_busy;
+       u_int32_t       buftop, pbuf, rbuf, cbuf, acbuf;
+       u_int32_t       playint, recint, misc1int, misc2int;
+       u_int32_t       irsz, badintr;
+
+        u_int32_t       pbufsize;
+        u_int32_t       rbufsize;
+
+       u_int32_t       pblksize;
+       u_int32_t       rblksize;
+
+        u_int32_t       pwmark;
+        u_int32_t       rwmark;
+
+       struct ac97_codec_if *codec_if;
+       struct ac97_host_if host_if;
+
+       void            *powerhook;
+};
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * prototypes
+ */
+
+static int     nm_waitcd(struct neo_softc *sc);
+static int     nm_loadcoeff(struct neo_softc *sc, int dir, int num);
+static int     nm_init(struct neo_softc *);
+
+int    neo_match(struct device *, struct cfdata *, void *);
+void   neo_attach(struct device *, struct device *, void *);
+int    neo_intr(void *);
+
+int    neo_open(void *, int);
+void   neo_close(void *);
+int    neo_query_encoding(void *, struct audio_encoding *);
+int    neo_set_params(void *, int, int, struct audio_params *,
+           struct audio_params *);
+int    neo_round_blocksize(void *, int);
+int    neo_trigger_output(void *, void *, void *, int, void (*)(void *),
+           void *, struct audio_params *);
+int    neo_trigger_input(void *, void *, void *, int, void (*)(void *),
+           void *, struct audio_params *);
+int    neo_halt_output(void *);
+int    neo_halt_input(void *);
+int    neo_getdev(void *, struct audio_device *);
+int    neo_mixer_set_port(void *, mixer_ctrl_t *);
+int    neo_mixer_get_port(void *, mixer_ctrl_t *);
+int     neo_attach_codec(void *sc, struct ac97_codec_if *);
+int    neo_read_codec(void *sc, u_int8_t a, u_int16_t *d);
+int    neo_write_codec(void *sc, u_int8_t a, u_int16_t d);
+void    neo_reset_codec(void *sc);
+enum ac97_host_flags neo_flags_codec(void *sc);
+int    neo_query_devinfo(void *, mixer_devinfo_t *);
+void   *neo_malloc(void *, int, size_t, int, int);
+void   neo_free(void *, void *, int);
+size_t neo_round_buffersize(void *, int, size_t);
+paddr_t        neo_mappage(void *, void *, off_t, int);
+int    neo_get_props(void *);
+void   neo_set_mixer(struct neo_softc *sc, int a, int d);
+void   neo_power(int why, void *arg);
+
+struct cfattach neo_ca = {
+       sizeof(struct neo_softc), neo_match, neo_attach
+};
+
+struct audio_device neo_device = {
+       "NeoMagic 256",
+       "",
+       "neo"
+};
+
+/* The actual rates supported by the card. */
+static const int samplerates[9] = {
+       8000,
+       11025,
+       16000,
+       22050,
+       24000,
+       32000,
+       44100,
+       48000,
+       99999999
+};
+
+/* -------------------------------------------------------------------- */
+
+struct audio_hw_if neo_hw_if = {
+       neo_open,
+       neo_close,
+       NULL,                           /* drain */
+       neo_query_encoding,
+       neo_set_params,
+       neo_round_blocksize,
+       NULL,                           /* commit_setting */
+       NULL,                           /* init_output */
+       NULL,                           /* init_input */
+       NULL,                           /* start_output */
+       NULL,                           /* start_input */
+       neo_halt_output,
+       neo_halt_input,
+       NULL,                           /* speaker_ctl */
+       neo_getdev,
+       NULL,                           /* getfd */
+       neo_mixer_set_port,
+       neo_mixer_get_port,
+       neo_query_devinfo,
+       neo_malloc,
+       neo_free,
+       neo_round_buffersize,
+       neo_mappage,
+       neo_get_props,
+       neo_trigger_output,
+       neo_trigger_input,
+};
+
+/* -------------------------------------------------------------------- */
+
+#define        nm_rd_1(sc, regno)                                              \
+       bus_space_read_1((sc)->regiot, (sc)->regioh, (regno))
+
+#define        nm_rd_2(sc, regno)                                              \
+       bus_space_read_2((sc)->regiot, (sc)->regioh, (regno))
+
+#define        nm_rd_4(sc, regno)                                              \
+       bus_space_read_4((sc)->regiot, (sc)->regioh, (regno))
+
+#define        nm_wr_1(sc, regno, val)                                         \
+       bus_space_write_1((sc)->regiot, (sc)->regioh, (regno), (val))
+
+#define        nm_wr_2(sc, regno, val)                                         \
+       bus_space_write_2((sc)->regiot, (sc)->regioh, (regno), (val))
+
+#define        nm_wr_4(sc, regno, val)                                         \
+       bus_space_write_4((sc)->regiot, (sc)->regioh, (regno), (val))
+
+#define        nm_rdbuf_4(sc, regno)                                           \
+       bus_space_read_4((sc)->bufiot, (sc)->bufioh, (regno))
+
+#define        nm_wrbuf_1(sc, regno, val)                                      \
+       bus_space_write_1((sc)->bufiot, (sc)->bufioh, (regno), (val))
+
+/* ac97 codec */
+static int
+nm_waitcd(struct neo_softc *sc)
+{
+       int cnt = 10;
+       int fail = 1;
+
+       while (cnt-- > 0) {



Home | Main Index | Thread Index | Old Index