Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/fdt Add SoC sound driver based on "simple-audio-card...



details:   https://anonhg.NetBSD.org/src/rev/888febd6fd90
branches:  trunk
changeset: 322633:888febd6fd90
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Wed May 09 23:59:05 2018 +0000

description:
Add SoC sound driver based on "simple-audio-card" DT binding spec.

diffstat:

 sys/dev/fdt/ausoc.c   |  619 ++++++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/fdt/fdt_dai.c |  118 +++++++++
 sys/dev/fdt/fdtvar.h  |   11 +-
 sys/dev/fdt/files.fdt |    7 +-
 4 files changed, 753 insertions(+), 2 deletions(-)

diffs (truncated from 819 to 300 lines):

diff -r 517db56f9f47 -r 888febd6fd90 sys/dev/fdt/ausoc.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/fdt/ausoc.c       Wed May 09 23:59:05 2018 +0000
@@ -0,0 +1,619 @@
+/* $NetBSD: ausoc.c,v 1.1 2018/05/09 23:59:05 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2018 Jared McNeill <jmcneill%invisible.ca@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 ``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 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.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ausoc.c,v 1.1 2018/05/09 23:59:05 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/device.h>
+#include <sys/kmem.h>
+#include <sys/gpio.h>
+
+#include <sys/audioio.h>
+#include <dev/audio_if.h>
+#include <dev/audio_dai.h>
+
+#include <dev/fdt/fdtvar.h>
+
+static const char *compatible[] = { "simple-audio-card", NULL };
+
+#define        AUSOC_MIXER_DAI(link)   \
+       ((link)->link_naux > 0 ? (link)->link_aux[0] : (link)->link_codec)
+
+struct ausoc_link {
+       const char              *link_name;
+
+       audio_dai_tag_t         link_cpu;
+       audio_dai_tag_t         link_codec;
+       audio_dai_tag_t         *link_aux;
+       u_int                   link_naux;
+
+       u_int                   link_mclk_fs;
+
+       kmutex_t                link_lock;
+       kmutex_t                link_intr_lock;
+};
+
+struct ausoc_softc {
+       device_t                sc_dev;
+       int                     sc_phandle;
+       const char              *sc_name;
+
+       struct ausoc_link       *sc_link;
+       u_int                   sc_nlink;
+};
+
+static void
+ausoc_close(void *priv)
+{
+       struct ausoc_link * const link = priv;
+       u_int aux;
+
+       for (aux = 0; aux < link->link_naux; aux++)
+               audio_dai_close(link->link_aux[aux]);
+       audio_dai_close(link->link_codec);
+       audio_dai_close(link->link_cpu);
+}
+
+static int
+ausoc_open(void *priv, int flags)
+{
+       struct ausoc_link * const link = priv;
+       u_int aux;
+       int error;
+
+       error = audio_dai_open(link->link_cpu, flags);
+       if (error)
+               goto failed;
+
+       error = audio_dai_open(link->link_codec, flags);
+       if (error)
+               goto failed;
+
+       for (aux = 0; aux < link->link_naux; aux++) {
+               error = audio_dai_open(link->link_aux[aux], flags);
+               if (error)
+                       goto failed;
+       }
+
+       return 0;
+
+failed:
+       ausoc_close(priv);
+       return error;
+}
+
+static int
+ausoc_drain(void *priv)
+{
+       struct ausoc_link * const link = priv;
+
+       return audio_dai_drain(link->link_cpu);
+}
+
+static int
+ausoc_query_encoding(void *priv, struct audio_encoding *ae)
+{
+       struct ausoc_link * const link = priv;
+
+       return audio_dai_query_encoding(link->link_cpu, ae);
+}
+
+static int
+ausoc_set_params(void *priv, int setmode, int usemode,
+    audio_params_t *play, audio_params_t *rec,
+    stream_filter_list_t *pfil, stream_filter_list_t *rfil)
+{
+       struct ausoc_link * const link = priv;
+       int error;
+
+       error = audio_dai_set_params(link->link_cpu, setmode,
+           usemode, play, rec, pfil, rfil);
+       if (error)
+               return error;
+
+       return audio_dai_set_params(link->link_codec, setmode,
+           usemode, play, rec, pfil, rfil);
+}
+
+static int
+ausoc_set_port(void *priv, mixer_ctrl_t *mc)
+{
+       struct ausoc_link * const link = priv;
+
+       return audio_dai_set_port(AUSOC_MIXER_DAI(link), mc);
+}
+
+static int
+ausoc_get_port(void *priv, mixer_ctrl_t *mc)
+{
+       struct ausoc_link * const link = priv;
+
+       return audio_dai_get_port(AUSOC_MIXER_DAI(link), mc);
+}
+
+static int
+ausoc_query_devinfo(void *priv, mixer_devinfo_t *di)
+{
+       struct ausoc_link * const link = priv;
+
+       return audio_dai_query_devinfo(AUSOC_MIXER_DAI(link), di);
+}
+
+static void *
+ausoc_allocm(void *priv, int dir, size_t size)
+{
+       struct ausoc_link * const link = priv;
+
+       return audio_dai_allocm(link->link_cpu, dir, size);
+}
+
+static void
+ausoc_freem(void *priv, void *addr, size_t size)
+{
+       struct ausoc_link * const link = priv;
+
+       return audio_dai_freem(link->link_cpu, addr, size);
+}
+
+static paddr_t
+ausoc_mappage(void *priv, void *addr, off_t off, int prot)
+{
+       struct ausoc_link * const link = priv;
+
+       return audio_dai_mappage(link->link_cpu, addr, off, prot);
+}
+
+static int
+ausoc_getdev(void *priv, struct audio_device *adev)
+{
+       struct ausoc_link * const link = priv;
+
+       /* Defaults */
+       snprintf(adev->name, sizeof(adev->name), "%s", link->link_name);
+       snprintf(adev->version, sizeof(adev->version), "");
+       snprintf(adev->config, sizeof(adev->config), "ausoc");
+
+       /* Codec can override */
+       (void)audio_dai_getdev(link->link_codec, adev);
+
+       return 0;
+}
+
+static int
+ausoc_get_props(void *priv)
+{
+       struct ausoc_link * const link = priv;
+
+       return audio_dai_get_props(link->link_cpu);
+}
+
+static int
+ausoc_round_blocksize(void *priv, int bs, int mode,
+    const audio_params_t *params)
+{
+       struct ausoc_link * const link = priv;
+
+       return audio_dai_round_blocksize(link->link_cpu, bs, mode, params);
+}
+
+static size_t
+ausoc_round_buffersize(void *priv, int dir, size_t bufsize)
+{
+       struct ausoc_link * const link = priv;
+
+       return audio_dai_round_buffersize(link->link_cpu, dir, bufsize);
+}
+
+static int
+ausoc_halt_output(void *priv)
+{
+       struct ausoc_link * const link = priv;
+       u_int n;
+
+       for (n = 0; n < link->link_naux; n++)
+               audio_dai_halt(link->link_aux[n], AUMODE_PLAY);
+
+       audio_dai_halt(link->link_codec, AUMODE_PLAY);
+
+       return audio_dai_halt(link->link_cpu, AUMODE_PLAY);
+}
+
+static int
+ausoc_halt_input(void *priv)
+{
+       struct ausoc_link * const link = priv;
+       u_int n;
+
+       for (n = 0; n < link->link_naux; n++)
+               audio_dai_halt(link->link_aux[n], AUMODE_RECORD);
+
+       audio_dai_halt(link->link_codec, AUMODE_RECORD);
+
+       return audio_dai_halt(link->link_cpu, AUMODE_RECORD);
+}
+
+static int
+ausoc_trigger_output(void *priv, void *start, void *end, int blksize,
+    void (*intr)(void *), void *intrarg, const audio_params_t *params)
+{
+       struct ausoc_link * const link = priv;
+       u_int n, rate;
+       int error;
+
+       if (link->link_mclk_fs) {
+               rate = params->sample_rate * link->link_mclk_fs;
+               error = audio_dai_set_sysclk(link->link_codec, rate,
+                   AUDIO_DAI_CLOCK_IN);
+               if (error)
+                       goto failed;
+               error = audio_dai_set_sysclk(link->link_cpu, rate,
+                   AUDIO_DAI_CLOCK_OUT);
+               if (error)
+                       goto failed;
+       }
+
+       for (n = 0; n < link->link_naux; n++) {
+               error = audio_dai_trigger(link->link_aux[n], start, end,
+                   blksize, intr, intrarg, params, AUMODE_PLAY);
+               if (error)
+                       goto failed;
+       }
+       error = audio_dai_trigger(link->link_codec, start, end, blksize,
+           intr, intrarg, params, AUMODE_PLAY);
+       if (error)
+               goto failed;
+
+       return audio_dai_trigger(link->link_cpu, start, end, blksize,
+           intr, intrarg, params, AUMODE_PLAY);
+



Home | Main Index | Thread Index | Old Index