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