Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch Add sun4i DMA and audio codec support.
details: https://anonhg.NetBSD.org/src/rev/a56f22b8f670
branches: trunk
changeset: 356004:a56f22b8f670
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Sun Aug 27 16:05:26 2017 +0000
description:
Add sun4i DMA and audio codec support.
diffstat:
sys/arch/arm/sunxi/files.sunxi | 12 +-
sys/arch/arm/sunxi/sun4i_a10_codec.c | 256 +++++++++++++++++++++
sys/arch/arm/sunxi/sun4i_dma.c | 413 +++++++++++++++++++++++++++++++++++
sys/arch/arm/sunxi/sunxi_codec.c | 19 +-
sys/arch/arm/sunxi/sunxi_codec.h | 6 +-
sys/arch/evbarm/conf/SUNXI | 5 +-
6 files changed, 695 insertions(+), 16 deletions(-)
diffs (truncated from 796 to 300 lines):
diff -r e7632c3dbdc6 -r a56f22b8f670 sys/arch/arm/sunxi/files.sunxi
--- a/sys/arch/arm/sunxi/files.sunxi Sun Aug 27 16:05:08 2017 +0000
+++ b/sys/arch/arm/sunxi/files.sunxi Sun Aug 27 16:05:26 2017 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.sunxi,v 1.19 2017/08/27 02:19:46 jmcneill Exp $
+# $NetBSD: files.sunxi,v 1.20 2017/08/27 16:05:26 jmcneill Exp $
#
# Configuration info for Allwinner sunxi family SoCs
#
@@ -124,7 +124,12 @@
attach sunxiwdt at fdt with sunxi_wdt
file arch/arm/sunxi/sunxi_wdt.c sunxi_wdt
-# DMA controller
+# DMA controller (sun4i)
+device sun4idma
+attach sun4idma at fdt with sun4i_dma
+file arch/arm/sunxi/sun4i_dma.c sun4i_dma
+
+# DMA controller (sun6i)
device sun6idma
attach sun6idma at fdt with sun6i_dma
file arch/arm/sunxi/sun6i_dma.c sun6i_dma
@@ -133,8 +138,9 @@
device sunxicodec: audiobus, auconv, mulaw, aurateconv
attach sunxicodec at fdt with sunxi_codec
file arch/arm/sunxi/sunxi_codec.c sunxi_codec
+file arch/arm/sunxi/sun4i_a10_codec.c sunxi_codec
-# Audio codec (analog part)
+# H3 Audio codec (analog part)
device h3codec
attach h3codec at fdt with h3_codec
file arch/arm/sunxi/sun8i_h3_codec.c h3_codec needs-flag
diff -r e7632c3dbdc6 -r a56f22b8f670 sys/arch/arm/sunxi/sun4i_a10_codec.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/sunxi/sun4i_a10_codec.c Sun Aug 27 16:05:26 2017 +0000
@@ -0,0 +1,256 @@
+/* $NetBSD: sun4i_a10_codec.c,v 1.1 2017/08/27 16:05:26 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2014-2017 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: sun4i_a10_codec.c,v 1.1 2017/08/27 16:05:26 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/device.h>
+#include <sys/kmem.h>
+#include <sys/bitops.h>
+
+#include <sys/audioio.h>
+#include <dev/audio_if.h>
+
+#include <arm/sunxi/sunxi_codec.h>
+
+#define A10_DEFAULT_PAVOL 0x20
+
+#define A10_DAC_ACTRL 0x10
+#define A10_DACAREN __BIT(31)
+#define A10_DACALEN __BIT(30)
+#define A10_MIXEN __BIT(29)
+#define A10_LNG __BIT(26)
+#define A10_FMG __BITS(25,23)
+#define A10_MICG __BITS(22,20)
+#define A10_LLNS __BIT(19)
+#define A10_RLNS __BIT(18)
+#define A10_LFMS __BIT(17)
+#define A10_RFMS __BIT(16)
+#define A10_LDACLMIXS __BIT(15)
+#define A10_RDACRMIXS __BIT(14)
+#define A10_LDACRMIXS __BIT(13)
+#define A10_MICLS __BIT(12)
+#define A10_MICRS __BIT(11)
+#define A10_DACPAS __BIT(8)
+#define A10_MIXPAS __BIT(7)
+#define A10_PAMUTE __BIT(6)
+#define A10_PAVOL __BITS(5,0)
+
+#define A10_ADC_ACTRL 0x28
+#define A10_ADCREN __BIT(31)
+#define A10_ADCLEN __BIT(30)
+#define A10_PREG1EN __BIT(29)
+#define A10_PREG2EN __BIT(28)
+#define A10_VMICEN __BIT(27)
+#define A10_PREG1 __BITS(26,25)
+#define A10_PREG2 __BITS(24,23)
+#define A10_ADCG __BITS(22,20)
+#define A10_ADCIS __BITS(19,17)
+#define A10_LNRDF __BIT(16)
+#define A10_LNPREG __BITS(15,13)
+#define A10_MIC1NEN __BIT(12)
+#define A10_DITHER __BIT(8)
+#define A10_PA_EN __BIT(4)
+#define A10_DDE __BIT(3)
+#define A10_COMPTEN __BIT(2)
+#define A10_PTDBS __BITS(1,0)
+
+enum a10_codec_mixer_ctrl {
+ A10_CODEC_OUTPUT_CLASS,
+ A10_CODEC_INPUT_CLASS,
+
+ A10_CODEC_OUTPUT_MASTER_VOLUME,
+ A10_CODEC_INPUT_DAC_VOLUME,
+
+ A10_CODEC_MIXER_CTRL_LAST
+};
+
+static const struct a10_codec_mixer {
+ const char * name;
+ enum a10_codec_mixer_ctrl mixer_class;
+ u_int reg;
+ u_int mask;
+} a10_codec_mixers[A10_CODEC_MIXER_CTRL_LAST] = {
+ [A10_CODEC_OUTPUT_MASTER_VOLUME] = { AudioNmaster,
+ A10_CODEC_OUTPUT_CLASS, A10_DAC_ACTRL, A10_PAVOL },
+ [A10_CODEC_INPUT_DAC_VOLUME] = { AudioNdac,
+ A10_CODEC_INPUT_CLASS, A10_DAC_ACTRL, A10_PAVOL },
+};
+
+#define RD4(sc, reg) \
+ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+#define WR4(sc, reg, val) \
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+#define SET4(sc, reg, mask) \
+ WR4((sc), (reg), RD4((sc), (reg)) | (mask))
+#define CLR4(sc, reg, mask) \
+ WR4((sc), (reg), RD4((sc), (reg)) & ~(mask))
+
+static int
+a10_codec_init(struct sunxi_codec_softc *sc)
+{
+
+ /* Unmute PA */
+ SET4(sc, A10_DAC_ACTRL, A10_PAMUTE);
+ /* Set initial volume */
+ CLR4(sc, A10_DAC_ACTRL, A10_PAVOL);
+ SET4(sc, A10_DAC_ACTRL, __SHIFTIN(A10_DEFAULT_PAVOL, A10_PAVOL));
+ /* Enable PA */
+ SET4(sc, A10_ADC_ACTRL, A10_PA_EN);
+
+ return 0;
+}
+
+static void
+a10_codec_mute(struct sunxi_codec_softc *sc, int mute, u_int mode)
+{
+ if (mode == AUMODE_PLAY) {
+ const uint32_t pmask = A10_DACAREN|A10_DACALEN|A10_DACPAS;
+ if (mute) {
+ /* Mute DAC l/r channels to output mixer */
+ CLR4(sc, A10_DAC_ACTRL, pmask);
+ } else {
+ /* Enable DAC analog l/r channels and output mixer */
+ SET4(sc, A10_DAC_ACTRL, pmask);
+ }
+ } else {
+ const uint32_t rmask = A10_ADCREN|A10_ADCLEN;
+ if (mute) {
+ /* Disable ADC analog l/r channels */
+ CLR4(sc, A10_ADC_ACTRL, rmask);
+ } else {
+ /* Enable ADC analog l/r channels */
+ SET4(sc, A10_ADC_ACTRL, rmask);
+ }
+ }
+}
+
+static int
+a10_codec_set_port(struct sunxi_codec_softc *sc, mixer_ctrl_t *mc)
+{
+ const struct a10_codec_mixer *mix;
+ u_int val, shift;
+ int nvol;
+
+ switch (mc->dev) {
+ case A10_CODEC_OUTPUT_MASTER_VOLUME:
+ case A10_CODEC_INPUT_DAC_VOLUME:
+ mix = &a10_codec_mixers[mc->dev];
+ val = RD4(sc, mix->reg);
+ shift = 8 - fls32(__SHIFTOUT_MASK(mix->mask));
+ nvol = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] >> shift;
+ val &= ~mix->mask;
+ val |= __SHIFTIN(nvol, mix->mask);
+ WR4(sc, mix->reg, val);
+ return 0;
+ }
+
+ return ENXIO;
+}
+
+static int
+a10_codec_get_port(struct sunxi_codec_softc *sc, mixer_ctrl_t *mc)
+{
+ const struct a10_codec_mixer *mix;
+ u_int val, shift;
+ int nvol;
+
+ switch (mc->dev) {
+ case A10_CODEC_OUTPUT_MASTER_VOLUME:
+ case A10_CODEC_INPUT_DAC_VOLUME:
+ mix = &a10_codec_mixers[mc->dev];
+ val = RD4(sc, mix->reg);
+ shift = 8 - fls32(__SHIFTOUT_MASK(mix->mask));
+ nvol = __SHIFTOUT(val, mix->mask) << shift;
+ mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = nvol;
+ mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = nvol;
+ return 0;
+ }
+
+ return ENXIO;
+}
+
+static int
+a10_codec_query_devinfo(struct sunxi_codec_softc *sc, mixer_devinfo_t *di)
+{
+ const struct a10_codec_mixer *mix;
+
+ switch (di->index) {
+ case A10_CODEC_OUTPUT_CLASS:
+ di->mixer_class = di->index;
+ strcpy(di->label.name, AudioCoutputs);
+ di->type = AUDIO_MIXER_CLASS;
+ di->next = di->prev = AUDIO_MIXER_LAST;
+ return 0;
+
+ case A10_CODEC_INPUT_CLASS:
+ di->mixer_class = di->index;
+ strcpy(di->label.name, AudioCinputs);
+ di->type = AUDIO_MIXER_CLASS;
+ di->next = di->prev = AUDIO_MIXER_LAST;
+ return 0;
+
+ case A10_CODEC_OUTPUT_MASTER_VOLUME:
+ case A10_CODEC_INPUT_DAC_VOLUME:
+ mix = &a10_codec_mixers[di->index];
+ di->mixer_class = mix->mixer_class;
+ strcpy(di->label.name, mix->name);
+ di->un.v.delta =
+ 256 / (__SHIFTOUT_MASK(mix->mask) + 1);
+ di->type = AUDIO_MIXER_VALUE;
+ di->next = di->prev = AUDIO_MIXER_LAST;
+ di->un.v.num_channels = 2;
+ strcpy(di->un.v.units.name, AudioNvolume);
+ return 0;
+ }
+
+ return ENXIO;
+}
+
+const struct sunxi_codec_conf sun4i_a10_codecconf = {
+ .name = "A10 Audio Codec",
+
+ .init = a10_codec_init,
+ .mute = a10_codec_mute,
+ .set_port = a10_codec_set_port,
+ .get_port = a10_codec_get_port,
+ .query_devinfo = a10_codec_query_devinfo,
+
+ .DPC = 0x00,
+ .DAC_FIFOC = 0x04,
+ .DAC_FIFOS = 0x08,
+ .DAC_TXDATA = 0x0c,
+ .ADC_FIFOC = 0x1c,
+ .ADC_FIFOS = 0x20,
+ .ADC_RXDATA = 0x24,
+ .DAC_CNT = 0x30,
+ .ADC_CNT = 0x34,
+};
diff -r e7632c3dbdc6 -r a56f22b8f670 sys/arch/arm/sunxi/sun4i_dma.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/sunxi/sun4i_dma.c Sun Aug 27 16:05:26 2017 +0000
@@ -0,0 +1,413 @@
+/* $NetBSD: sun4i_dma.c,v 1.1 2017/08/27 16:05:26 jmcneill Exp $ */
+
Home |
Main Index |
Thread Index |
Old Index