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 "simp...
details: https://anonhg.NetBSD.org/src/rev/4e453b25a8c1
branches: trunk
changeset: 318939:4e453b25a8c1
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 60ed08f00606 -r 4e453b25a8c1 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