Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/isaki-audio2]: src/sys/dev/pci Reimplement emuxki driver.
details: https://anonhg.NetBSD.org/src/rev/8e00f7a65bfc
branches: isaki-audio2
changeset: 450939:8e00f7a65bfc
user: isaki <isaki%NetBSD.org@localhost>
date: Wed May 01 06:34:46 2019 +0000
description:
Reimplement emuxki driver.
- Use single voice per playback and per recording.
- Use fixed format, 2ch/48kHz, to simplify.
- Fix several problems in previous driver.
And now it works even on alpha!
The driver is written by Y.Sugahara. Thanks!
diffstat:
sys/dev/pci/emuxki.c | 2830 +++++++++++++++-------------------------------
sys/dev/pci/emuxkivar.h | 263 ----
2 files changed, 929 insertions(+), 2164 deletions(-)
diffs (truncated from 3518 to 300 lines):
diff -r feb71b09c192 -r 8e00f7a65bfc sys/dev/pci/emuxki.c
--- a/sys/dev/pci/emuxki.c Wed May 01 06:03:14 2019 +0000
+++ b/sys/dev/pci/emuxki.c Wed May 01 06:34:46 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: emuxki.c,v 1.67.2.3 2019/05/01 06:03:14 isaki Exp $ */
+/* $NetBSD: emuxki.c,v 1.67.2.4 2019/05/01 06:34:46 isaki Exp $ */
/*-
* Copyright (c) 2001, 2007 The NetBSD Foundation, Inc.
@@ -30,147 +30,227 @@
*/
/*
- * Driver for Creative Labs SBLive! series and probably PCI512.
- *
- * Known bugs:
- * - inversed stereo at ac97 codec level
- * (XXX jdolecek - don't see the problem? maybe because auvia(4) has
- * it swapped too?)
- * - bass disappear when you plug rear jack-in on Cambridge FPS2000 speakers
- * (and presumably all speakers that support front and rear jack-in)
- *
- * TODO:
- * - Digital Outputs
- * - (midi/mpu),joystick support
- * - Multiple voices play (problem with /dev/audio architecture)
- * - Multiple sources recording (Pb with audio(4))
- * - Independent modification of each channel's parameters (via mixer ?)
- * - DSP FX patches (to make fx like chipmunk)
+ * EMU10K1 single voice driver
+ * o. only 1 voice playback, 1 recording
+ * o. only s16le 2ch 48k
+ * This makes it simple to control buffers and interrupts
+ * while satisfying playback and recording quality.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.67.2.3 2019/05/01 06:03:14 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: emuxki.c,v 1.67.2.4 2019/05/01 06:34:46 isaki Exp $");
#include <sys/param.h>
#include <sys/device.h>
#include <sys/errno.h>
#include <sys/systm.h>
#include <sys/audioio.h>
-#include <sys/select.h>
#include <sys/mutex.h>
#include <sys/kmem.h>
#include <sys/malloc.h>
#include <sys/fcntl.h>
+#include <sys/bus.h>
+#include <sys/intr.h>
+
#include <dev/audio_if.h>
#include <dev/audiovar.h>
#include <dev/ic/ac97reg.h>
#include <dev/ic/ac97var.h>
+#include <dev/pci/pcidevs.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-#include <dev/pci/pcidevs.h>
+
#include <dev/pci/emuxkireg.h>
-#include <dev/pci/emuxkivar.h>
+
+/* #define EMUXKI_DEBUG 1 */
+#ifdef EMUXKI_DEBUG
+#define emudebug EMUXKI_DEBUG
+# define DPRINTF(fmt...) do { if (emudebug) printf(fmt); } while (0)
+# define DPRINTFN(n,fmt...) do { if (emudebug>=(n)) printf(fmt); } while (0)
+#else
+# define DPRINTF(fmt...) do { } while (0)
+# define DPRINTFN(n,fmt...) do { } while (0)
+#endif
+
+/*
+ * PCI
+ * Note: emuxki's page table entry uses only 31bit addressing.
+ * (Maybe, later chip has 32bit mode, but it isn't used now.)
+ */
+
+#define EMU_PCI_CBIO (0x10)
+#define EMU_SUBSYS_APS (0x40011102)
+
+#define EMU_PTESIZE (4096)
+#define EMU_MINPTE (3)
+/*
+ * Hardware limit of PTE is 4096 entry but it's too big for single voice.
+ * Reasonable candidate is:
+ * 48kHz * 2ch * 2byte * 1sec * 3buf/EMU_PTESIZE = 141
+ * and then round it up to 2^n.
+ */
+#define EMU_MAXPTE (256)
+#define EMU_NUMCHAN (64)
+
+/*
+ * Internal recording DMA buffer
+ */
+/* Recommend the same size as EMU_PTESIZE to be symmetrical for play/rec */
+#define EMU_REC_DMABLKSIZE (4096)
+/* must be EMU_REC_DMABLKSIZE * 2 */
+#define EMU_REC_DMASIZE (8192)
+/* must be EMU_RECBS_BUFSIZE_(EMU_REC_DMASIZE) */
+#define EMU_REC_BUFSIZE_RECBS EMU_RECBS_BUFSIZE_8192
+
+/*
+ * DMA memory management
+ */
+
+#define EMU_DMA_ALIGN (4096)
+#define EMU_DMA_NSEGS (1)
+
+struct dmamem {
+ bus_dma_tag_t dmat;
+ bus_size_t size;
+ bus_size_t align;
+ bus_size_t bound;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ int rsegs;
+ void * kaddr;
+ bus_dmamap_t map;
+};
+
+#define KERNADDR(ptr) ((void *)((ptr)->kaddr))
+/*
+ * (ptr)->segs[] is CPU's PA translated by CPU's MMU.
+ * (ptr)->map->dm_segs[] is PCI device's PA translated by PCI's MMU.
+ */
+#define DMASEGADDR(ptr, segno) ((ptr)->map->dm_segs[segno].ds_addr)
+#define DMAADDR(ptr) DMASEGADDR(ptr, 0)
+#define DMASIZE(ptr) ((ptr)->size)
-/* autoconf goo */
+struct emuxki_softc {
+ device_t sc_dev;
+ device_t sc_audev;
+ enum {
+ EMUXKI_SBLIVE = 0x00,
+ EMUXKI_AUDIGY = 0x01,
+ EMUXKI_AUDIGY2 = 0x02,
+ EMUXKI_LIVE_5_1 = 0x04,
+ EMUXKI_APS = 0x08
+ } sc_type;
+ audio_device_t sc_audv; /* for GETDEV */
+
+ /* Autoconfig parameters */
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ bus_addr_t sc_iob;
+ bus_size_t sc_ios;
+ pci_chipset_tag_t sc_pc; /* PCI tag */
+ bus_dma_tag_t sc_dmat;
+ void *sc_ih; /* interrupt handler */
+ kmutex_t sc_intr_lock;
+ kmutex_t sc_lock;
+ kmutex_t sc_index_lock;
+
+ /* register parameters */
+ struct dmamem *ptb; /* page table */
+
+ struct dmamem *pmem; /* play memory */
+ void (*pintr)(void *);
+ void *pintrarg;
+ audio_params_t play;
+ int pframesize;
+ int pblksize;
+ int plength;
+ int poffset;
+
+ struct dmamem *rmem; /* rec internal memory */
+ void (*rintr)(void *);
+ void *rintrarg;
+ audio_params_t rec;
+ void *rptr; /* rec MI ptr */
+ int rcurrent; /* rec software trans count */
+ int rframesize;
+ int rblksize;
+ int rlength;
+ int roffset;
+
+ /* others */
+
+ struct ac97_host_if hostif;
+ struct ac97_codec_if *codecif;
+};
+
+/* blackmagic */
+#define X1(x) ((sc->sc_type & EMUXKI_AUDIGY) ? EMU_A_##x : EMU_##x)
+#define X2(x, y) ((sc->sc_type & EMUXKI_AUDIGY) \
+ ? EMU_A_##x(EMU_A_##y) : EMU_##x(EMU_##y))
+#define EMU_A_DSP_FX EMU_DSP_FX
+#define EMU_A_DSP_IN_AC97 EMU_DSP_IN_AC97
+
+/* prototypes */
+static struct dmamem *dmamem_alloc(struct emuxki_softc *, size_t);
+static void dmamem_free(struct dmamem *);
+static void dmamem_sync(struct dmamem *, int);
+static uint8_t emuxki_readio_1(struct emuxki_softc *, int) __unused;
+static uint16_t emuxki_readio_2(struct emuxki_softc *, int);
+static uint32_t emuxki_readio_4(struct emuxki_softc *, int);
+static void emuxki_writeio_1(struct emuxki_softc *, int, uint8_t);
+static void emuxki_writeio_2(struct emuxki_softc *, int, uint16_t);
+static void emuxki_writeio_4(struct emuxki_softc *, int, uint32_t);
+static uint32_t emuxki_readptr(struct emuxki_softc *, int, int, int);
+static void emuxki_writeptr(struct emuxki_softc *, int, int, int, uint32_t);
+static uint32_t emuxki_read(struct emuxki_softc *, int, int);
+static void emuxki_write(struct emuxki_softc *, int, int, uint32_t);
static int emuxki_match(device_t, cfdata_t, void *);
static void emuxki_attach(device_t, device_t, void *);
static int emuxki_detach(device_t, int);
-
-/* DMA mem mgmt */
-static struct dmamem *dmamem_alloc(bus_dma_tag_t, size_t, bus_size_t,
- int);
-static void dmamem_free(struct dmamem *);
-
-/* Emu10k1 init & shutdown */
static int emuxki_init(struct emuxki_softc *);
-static void emuxki_shutdown(struct emuxki_softc *);
-
-/* Emu10k1 mem mgmt */
-static void *emuxki_pmem_alloc(struct emuxki_softc *, size_t);
-static void *emuxki_rmem_alloc(struct emuxki_softc *, size_t);
-
-/*
- * Emu10k1 channels funcs : There is no direct access to channels, everything
- * is done through voices I will at least provide channel based fx params
- * modification, later...
- */
-
-/* Emu10k1 voice mgmt */
-static struct emuxki_voice *emuxki_voice_new(struct emuxki_softc *,
- uint8_t);
-static void emuxki_voice_delete(struct emuxki_voice *);
-static int emuxki_voice_set_audioparms(struct emuxki_softc *,
- struct emuxki_voice *, uint8_t,
- uint8_t, uint32_t);
-/* emuxki_voice_set_fxparms will come later, it'll need channel distinction */
-static int emuxki_voice_set_bufparms(struct emuxki_voice *,
- void *, uint32_t, uint16_t);
-static void emuxki_voice_commit_parms(struct emuxki_voice *);
-static int emuxki_voice_adc_rate(struct emuxki_voice *);
-static uint32_t emuxki_voice_curaddr(struct emuxki_voice *);
-static void emuxki_voice_start(struct emuxki_voice *,
- void (*) (void *), void *);
-static void emuxki_voice_halt(struct emuxki_voice *);
-
-/*
- * Emu10k1 stream mgmt : not done yet
- */
-#if 0
-static struct emuxki_stream *emuxki_stream_new(struct emu10k1 *);
-static void emuxki_stream_delete(struct emuxki_stream *);
-static int emuxki_stream_set_audio_params(struct emuxki_stream *,
- uint8_t, uint8_t, uint8_t, uint16_t);
-static void emuxki_stream_start(struct emuxki_stream *);
-static void emuxki_stream_halt(struct emuxki_stream *);
-#endif
-
-/* audio interface callbacks */
+static void emuxki_dsp_addop(struct emuxki_softc *, uint16_t *, uint8_t,
+ uint16_t, uint16_t, uint16_t, uint16_t);
+static void emuxki_initfx(struct emuxki_softc *);
+static void emuxki_play_start(struct emuxki_softc *, int, uint32_t,
+ uint32_t);
+static void emuxki_play_stop(struct emuxki_softc *, int);
static int emuxki_open(void *, int);
static void emuxki_close(void *);
-
static int emuxki_query_format(void *, audio_format_query_t *);
static int emuxki_set_format(void *, int,
const audio_params_t *, const audio_params_t *,
audio_filter_reg_t *, audio_filter_reg_t *);
-
-static int emuxki_round_blocksize(void *, int, int, const audio_params_t *);
-static size_t emuxki_round_buffersize(void *, int, size_t);
-
-static int emuxki_trigger_output(void *, void *, void *, int,
- void (*)(void *), void *, const audio_params_t *);
-static int emuxki_trigger_input(void *, void *, void *, int,
- void (*) (void *), void *, const audio_params_t *);
static int emuxki_halt_output(void *);
static int emuxki_halt_input(void *);
-
+static int emuxki_intr(void *);
static int emuxki_getdev(void *, struct audio_device *);
static int emuxki_set_port(void *, mixer_ctrl_t *);
static int emuxki_get_port(void *, mixer_ctrl_t *);
static int emuxki_query_devinfo(void *, mixer_devinfo_t *);
-
-static void *emuxki_allocm(void *, int, size_t);
+static void *emuxki_allocm(void *, int, size_t);
static void emuxki_freem(void *, void *, size_t);
-
+static int emuxki_round_blocksize(void *, int, int,
Home |
Main Index |
Thread Index |
Old Index