Source-Changes-HG archive

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

[src/trunk]: src/sys vs(4) became to able to play audio again.



details:   https://anonhg.NetBSD.org/src/rev/89950bb06b9f
branches:  trunk
changeset: 825897:89950bb06b9f
user:      isaki <isaki%NetBSD.org@localhost>
date:      Sat Aug 05 05:53:26 2017 +0000

description:
vs(4) became to able to play audio again.
At the moment the encoding conversion using set_params() does
not seem to work for me.  So vs(4) uses local conversion to/from
ADPCM instead of it.  But this should be a temporary work.
XXX The playback quality is very poor compared to before...
XXX Recording is not tested.

diffstat:

 sys/arch/x68k/dev/vs.c    |  222 ++++++++++++++++++++++++++-------------------
 sys/arch/x68k/dev/vsvar.h |   11 ++-
 sys/dev/ic/msm6258.c      |  112 ++++++++++++++++++++++-
 sys/dev/ic/msm6258var.h   |   10 +-
 4 files changed, 257 insertions(+), 98 deletions(-)

diffs (truncated from 563 to 300 lines):

diff -r 6e7688be1602 -r 89950bb06b9f sys/arch/x68k/dev/vs.c
--- a/sys/arch/x68k/dev/vs.c    Sat Aug 05 05:22:55 2017 +0000
+++ b/sys/arch/x68k/dev/vs.c    Sat Aug 05 05:53:26 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vs.c,v 1.42 2017/08/05 05:22:55 isaki Exp $    */
+/*     $NetBSD: vs.c,v 1.43 2017/08/05 05:53:27 isaki Exp $    */
 
 /*
  * Copyright (c) 2001 Tetsuya Isaki. All rights reserved.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vs.c,v 1.42 2017/08/05 05:22:55 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vs.c,v 1.43 2017/08/05 05:53:27 isaki Exp $");
 
 #include "audio.h"
 #include "vs.h"
@@ -78,10 +78,10 @@
 static int  vs_query_encoding(void *, struct audio_encoding *);
 static int  vs_set_params(void *, int, int, audio_params_t *,
        audio_params_t *, stream_filter_list_t *, stream_filter_list_t *);
-static int  vs_trigger_output(void *, void *, void *, int,
-       void (*)(void *), void *, const audio_params_t *);
-static int  vs_trigger_input(void *, void *, void *, int,
-       void (*)(void *), void *, const audio_params_t *);
+static int  vs_init_output(void *, void *, int);
+static int  vs_init_input(void *, void *, int);
+static int  vs_start_input(void *, void *, int, void (*)(void *), void *);
+static int  vs_start_output(void *, void *, int, void (*)(void *), void *);
 static int  vs_halt_output(void *);
 static int  vs_halt_input(void *);
 static int  vs_allocmem(struct vs_softc *, size_t, size_t, size_t,
@@ -101,6 +101,7 @@
 static int vs_round_sr(u_long);
 static void vs_set_sr(struct vs_softc *, int);
 static inline void vs_set_po(struct vs_softc *, u_long);
+static void *vs_realloc_hwbuf(struct vs_softc *, int);
 
 extern struct cfdriver vs_cd;
 
@@ -117,10 +118,10 @@
        vs_set_params,
        NULL,                   /* round_blocksize */
        NULL,                   /* commit_settings */
-       NULL,                   /* init_output */
-       NULL,                   /* init_input */
-       NULL,                   /* start_output */
-       NULL,                   /* start_input */
+       vs_init_output,
+       vs_init_input,
+       vs_start_output,
+       vs_start_input,
        vs_halt_output,
        vs_halt_input,
        NULL,                   /* speaker_ctl */
@@ -129,13 +130,13 @@
        vs_set_port,
        vs_get_port,
        vs_query_devinfo,
-       vs_allocm,
-       vs_freem,
+       NULL,                   /* allocm */
+       NULL,                   /* freem */
        vs_round_buffersize,
        NULL,                   /* mappage */
        vs_get_props,
-       vs_trigger_output,
-       vs_trigger_input,
+       NULL,                   /* trigger_output */
+       NULL,                   /* trigger_input */
        NULL,
        vs_get_locks,
 };
@@ -160,8 +161,6 @@
 
 #define NUM_RATE       (sizeof(vs_l2r)/sizeof(vs_l2r[0]))
 
-extern stream_filter_factory_t null_filter;
-
 static int
 vs_match(device_t parent, cfdata_t cf, void *aux)
 {
@@ -222,6 +221,9 @@
        sc->sc_addr = (void *) ia->ia_addr;
        sc->sc_dmas = NULL;
        sc->sc_active = 0;
+       sc->sc_hwbuf = NULL;
+       sc->sc_hwbufsize = 0;
+       sc->sc_codec = vs_alloc_msm6258codec();
        mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
        mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
 
@@ -253,27 +255,13 @@
 
        mutex_spin_enter(&sc->sc_intr_lock);
 
+       sc->sc_active = 0;
        if (sc->sc_pintr) {
-               /* start next transfer */
-               sc->sc_current.dmap += sc->sc_current.blksize;
-               if (sc->sc_current.dmap + sc->sc_current.blksize
-                   > sc->sc_current.bufsize)
-                       sc->sc_current.dmap -= sc->sc_current.bufsize;
-               dmac_start_xfer_offset(sc->sc_dma_ch->ch_softc,
-                                       sc->sc_current.xfer,
-                                       sc->sc_current.dmap,
-                                       sc->sc_current.blksize);
                sc->sc_pintr(sc->sc_parg);
        } else if (sc->sc_rintr) {
-               /* start next transfer */
-               sc->sc_current.dmap += sc->sc_current.blksize;
-               if (sc->sc_current.dmap + sc->sc_current.blksize
-                   > sc->sc_current.bufsize)
-                       sc->sc_current.dmap -= sc->sc_current.bufsize;
-               dmac_start_xfer_offset(sc->sc_dma_ch->ch_softc,
-                                       sc->sc_current.xfer,
-                                       sc->sc_current.dmap,
-                                       sc->sc_current.blksize);
+               /* convert ADPCM to slinear */
+               sc->sc_rconv(sc->sc_codec, sc->sc_current.rblock,
+                   sc->sc_current.blksize, sc->sc_hwbuf);
                sc->sc_rintr(sc->sc_rarg);
        } else {
                printf("vs_dmaintr: spurious interrupt\n");
@@ -379,8 +367,6 @@
        stream_filter_list_t *pfil, stream_filter_list_t *rfil)
 {
        struct vs_softc *sc;
-       stream_filter_factory_t *pconv;
-       stream_filter_factory_t *rconv;
        int rate;
 
        sc = hdl;
@@ -403,12 +389,16 @@
        }
 
        if (play->precision == 8 && play->encoding == AUDIO_ENCODING_SLINEAR) {
-               pconv = msm6258_linear8_to_adpcm;
-               rconv = msm6258_adpcm_to_linear8;
+               sc->sc_current.precision = 8;
+               sc->sc_pconv = vs_slinear8_to_adpcm;
+               sc->sc_rconv = vs_adpcm_to_slinear8;
+
        } else if (play->precision == 16 &&
                   play->encoding == AUDIO_ENCODING_SLINEAR_BE) {
-               pconv = msm6258_slinear16_to_adpcm;
-               rconv = msm6258_adpcm_to_slinear16;
+               sc->sc_current.precision = 16;
+               sc->sc_pconv = vs_slinear16be_to_adpcm;
+               sc->sc_rconv = vs_adpcm_to_slinear16be;
+
        } else {
                DPRINTF(1, ("prec/enc not matched\n"));
                return EINVAL;
@@ -419,20 +409,11 @@
 
        /* pfil and rfil are independent even if !AUDIO_PROP_INDEPENDENT */
 
-       if ((setmode & AUMODE_PLAY) != 0) {
-               pfil->append(pfil, null_filter, play);
-               play->encoding = AUDIO_ENCODING_ADPCM;
-               play->validbits = 4;
-               play->precision = 4;
-               pfil->append(pfil, pconv, play);
-       }
-       if ((setmode & AUMODE_RECORD) != 0) {
-               rfil->append(rfil, null_filter, rec);
-               rec->encoding = AUDIO_ENCODING_ADPCM;
-               rec->validbits = 4;
-               rec->precision = 4;
-               rfil->append(rfil, rconv, rec);
-       }
+       /*
+        * XXX MI audio(4) layer does not seem to support non SLINEAR devices.
+        * So vs(4) behaves as SLINEAR device completely against MI layer
+        * and converts SLINEAR <-> ADPCM by myself.
+        */
 
        DPRINTF(1, ("accepted\n"));
        return 0;
@@ -460,38 +441,84 @@
 }
 
 static int
-vs_trigger_output(void *hdl, void *start, void *end, int bsize,
-                 void (*intr)(void *), void *arg,
-                 const audio_params_t *p)
+vs_init_output(void *hdl, void *buffer, int size)
+{
+       struct vs_softc *sc;
+
+       DPRINTF(1, ("%s\n", __func__));
+       sc = hdl;
+
+       /* Set rate and pan */
+       vs_set_sr(sc, sc->sc_current.prate);
+       vs_set_po(sc, VS_PANOUT_LR);
+
+       return 0;
+}
+
+static int
+vs_init_input(void *hdl, void *buffer, int size)
+{
+       struct vs_softc *sc;
+
+       DPRINTF(1, ("%s\n", __func__));
+       sc = hdl;
+
+       /* Set rate */
+       vs_set_sr(sc, sc->sc_current.rrate);
+
+       return 0;
+}
+
+/* (re)allocate sc_hwbuf with hwbufsize */
+static void *
+vs_realloc_hwbuf(struct vs_softc *sc, int hwbufsize)
+{
+       if (sc->sc_hwbuf != NULL) {
+               vs_freem(sc, sc->sc_hwbuf, sc->sc_hwbufsize);
+       }
+       sc->sc_hwbufsize = hwbufsize;
+       sc->sc_hwbuf = vs_allocm(sc, 0, sc->sc_hwbufsize);
+       if (sc->sc_hwbuf == NULL) {
+               sc->sc_hwbufsize = 0;
+               return NULL;
+       }
+       return sc->sc_hwbuf;
+}
+
+static int
+vs_start_output(void *hdl, void *block, int blksize, void (*intr)(void *),
+       void *arg)
 {
        struct vs_softc *sc;
        struct vs_dma *vd;
        struct dmac_dma_xfer *xf;
        struct dmac_channel_stat *chan;
+       int hwblksize;
 
-       DPRINTF(2, ("vs_trigger_output: start=%p, bsize=%d, intr=%p, arg=%p\n",
-                start, bsize, intr, arg));
+       DPRINTF(2, ("%s: block=%p blksize=%d\n", __func__, block, blksize));
        sc = hdl;
-       chan = sc->sc_dma_ch;
+
+       hwblksize = blksize / (sc->sc_current.precision / 4);
+       if (hwblksize > sc->sc_hwbufsize) {
+               if (vs_realloc_hwbuf(sc, hwblksize) == NULL) {
+                       DPRINTF(1, ("%s: alloc hwbuf failed\n", __func__));
+                       return ENOMEM;
+               }
+       }
+
+       /* Convert slinear to ADPCM */
+       sc->sc_pconv(sc->sc_codec, sc->sc_hwbuf, block, blksize);
+
        sc->sc_pintr = intr;
        sc->sc_parg  = arg;
-       sc->sc_current.blksize = bsize;
-       sc->sc_current.bufsize = (char *)end - (char *)start;
+       sc->sc_current.blksize = hwblksize;
+       sc->sc_current.bufsize = hwblksize;
        sc->sc_current.dmap = 0;
 
-       /* Find DMA buffer. */
-       for (vd = sc->sc_dmas; vd != NULL && KVADDR(vd) != start;
-            vd = vd->vd_next)
-               continue;
-       if (vd == NULL) {
-               printf("%s: trigger_output: bad addr %p\n",
-                   device_xname(sc->sc_dev), start);
-               return EINVAL;
-       }
+       /* vd is always first of sc_dmas */
+       vd = sc->sc_dmas;
 
-       vs_set_sr(sc, sc->sc_current.prate);
-       vs_set_po(sc, VS_PANOUT_LR);
-
+       chan = sc->sc_dma_ch;
        xf = dmac_alloc_xfer(chan, sc->sc_dmat, vd->vd_map);
        sc->sc_current.xfer = xf;
        chan->ch_dcr = (DMAC_DCR_XRM_CSWOH | DMAC_DCR_OTYP_EASYNC |
@@ -499,7 +526,7 @@
        chan->ch_ocr = DMAC_OCR_REQG_EXTERNAL;
        xf->dx_ocr = DMAC_OCR_DIR_MTD;
        xf->dx_scr = DMAC_SCR_MAC_COUNT_UP | DMAC_SCR_DAC_NO_COUNT;
-       xf->dx_device = sc->sc_addr + MSM6258_DATA*2 + 1;
+       xf->dx_device = sc->sc_addr + MSM6258_DATA * 2 + 1;
 
        dmac_load_xfer(chan->ch_softc, xf);
        dmac_start_xfer_offset(chan->ch_softc, xf, 0, sc->sc_current.blksize);
@@ -510,36 +537,37 @@
 }
 
 static int
-vs_trigger_input(void *hdl, void *start, void *end, int bsize,



Home | Main Index | Thread Index | Old Index