Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/sunxi Add A64 HDMI audio support.
details: https://anonhg.NetBSD.org/src/rev/e0f40642fa26
branches: trunk
changeset: 461168:e0f40642fa26
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Sun Nov 17 17:33:34 2019 +0000
description:
Add A64 HDMI audio support.
diffstat:
sys/arch/arm/sunxi/sunxi_dwhdmi.c | 21 +-
sys/arch/arm/sunxi/sunxi_i2s.c | 375 +++++++++++++++++++++++++++++--------
2 files changed, 312 insertions(+), 84 deletions(-)
diffs (truncated from 649 to 300 lines):
diff -r 58100ff5364b -r e0f40642fa26 sys/arch/arm/sunxi/sunxi_dwhdmi.c
--- a/sys/arch/arm/sunxi/sunxi_dwhdmi.c Sun Nov 17 17:33:17 2019 +0000
+++ b/sys/arch/arm/sunxi/sunxi_dwhdmi.c Sun Nov 17 17:33:34 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_dwhdmi.c,v 1.3 2019/02/02 17:35:16 jmcneill Exp $ */
+/* $NetBSD: sunxi_dwhdmi.c,v 1.4 2019/11/17 17:33:34 jmcneill Exp $ */
/*-
* Copyright (c) 2019 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_dwhdmi.c,v 1.3 2019/02/02 17:35:16 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_dwhdmi.c,v 1.4 2019/11/17 17:33:34 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -197,6 +197,21 @@
sc->sc_curmode = *adjusted_mode;
}
+static audio_dai_tag_t
+sunxi_dwhdmi_dai_get_tag(device_t dev, const void *data, size_t len)
+{
+ struct sunxi_dwhdmi_softc * const sc = device_private(dev);
+
+ if (len != 4)
+ return NULL;
+
+ return &sc->sc_base.sc_dai;
+}
+
+static struct fdtbus_dai_controller_func sunxi_dwhdmi_dai_funcs = {
+ .get_tag = sunxi_dwhdmi_dai_get_tag
+};
+
static int
sunxi_dwhdmi_match(device_t parent, cfdata_t cf, void *aux)
{
@@ -263,6 +278,8 @@
sc->sc_ports.dp_ep_activate = sunxi_dwhdmi_ep_activate;
sc->sc_ports.dp_ep_get_data = sunxi_dwhdmi_ep_get_data;
fdt_ports_register(&sc->sc_ports, self, phandle, EP_DRM_BRIDGE);
+
+ fdtbus_register_dai_controller(self, phandle, &sunxi_dwhdmi_dai_funcs);
}
CFATTACH_DECL_NEW(sunxi_dwhdmi, sizeof(struct sunxi_dwhdmi_softc),
diff -r 58100ff5364b -r e0f40642fa26 sys/arch/arm/sunxi/sunxi_i2s.c
--- a/sys/arch/arm/sunxi/sunxi_i2s.c Sun Nov 17 17:33:17 2019 +0000
+++ b/sys/arch/arm/sunxi/sunxi_i2s.c Sun Nov 17 17:33:34 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_i2s.c,v 1.6 2019/06/08 08:02:37 isaki Exp $ */
+/* $NetBSD: sunxi_i2s.c,v 1.7 2019/11/17 17:33:34 jmcneill Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_i2s.c,v 1.6 2019/06/08 08:02:37 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_i2s.c,v 1.7 2019/11/17 17:33:34 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -42,16 +42,24 @@
#include <dev/fdt/fdtvar.h>
-#define SUNXI_I2S_CLK_RATE 24576000
+#define SUNXI_I2S_CLK_RATE 24576000
+#define SUNXI_I2S_SAMPLE_RATE 48000
#define DA_CTL 0x00
+#define DA_CTL_BCLK_OUT __BIT(18) /* sun8i */
+#define DA_CLK_LRCK_OUT __BIT(17) /* sun8i */
#define DA_CTL_SDO_EN __BIT(8)
-#define DA_CTL_MS __BIT(5)
-#define DA_CTL_PCM __BIT(4)
+#define DA_CTL_MS __BIT(5) /* sun4i */
+#define DA_CTL_PCM __BIT(4) /* sun4i */
+#define DA_CTL_MODE_SEL __BITS(5,4) /* sun8i */
+#define DA_CTL_MODE_SEL_PCM 0
+#define DA_CTL_MODE_SEL_LJ 1
+#define DA_CTL_MODE_SEL_RJ 2
#define DA_CTL_TXEN __BIT(2)
#define DA_CTL_RXEN __BIT(1)
#define DA_CTL_GEN __BIT(0)
#define DA_FAT0 0x04
+#define DA_FAT0_LRCK_PERIOD __BITS(17,8) /* sun8i */
#define DA_FAT0_LRCP __BIT(7)
#define DA_LRCP_NORMAL 0
#define DA_LRCP_INVERTED 1
@@ -79,20 +87,34 @@
#define DA_INT_RX_DRQ __BIT(3)
#define DA_TXFIFO 0x20
#define DA_CLKD 0x24
-#define DA_CLKD_MCLKO_EN __BIT(7)
-#define DA_CLKD_BCLKDIV __BITS(6,4)
+#define DA_CLKD_MCLKO_EN_SUN8I __BIT(8)
+#define DA_CLKD_MCLKO_EN_SUN4I __BIT(7)
+#define DA_CLKD_BCLKDIV_SUN8I __BITS(7,4)
+#define DA_CLKD_BCLKDIV_SUN4I __BITS(6,4)
#define DA_CLKD_BCLKDIV_8 3
#define DA_CLKD_BCLKDIV_16 5
#define DA_CLKD_MCLKDIV __BITS(3,0)
#define DA_CLKD_MCLKDIV_1 0
#define DA_TXCNT 0x28
#define DA_RXCNT 0x2c
+#define DA_CHCFG 0x30 /* sun8i */
+#define DA_CHCFG_TX_SLOT_HIZ __BIT(9)
+#define DA_CHCFG_TXN_STATE __BIT(8)
+#define DA_CHCFG_RX_SLOT_NUM __BITS(6,4)
+#define DA_CHCFG_TX_SLOT_NUM __BITS(2,0)
+#define DA_CHSEL_OFFSET __BITS(13,12) /* sun8i */
#define DA_CHSEL_EN __BITS(11,4)
#define DA_CHSEL_SEL __BITS(2,0)
+enum sunxi_i2s_type {
+ SUNXI_I2S_SUN4I,
+ SUNXI_I2S_SUN8I,
+};
+
struct sunxi_i2s_config {
const char *name;
+ enum sunxi_i2s_type type;
bus_size_t txchsel;
bus_size_t txchmap;
bus_size_t rxchsel;
@@ -101,15 +123,27 @@
static const struct sunxi_i2s_config sun50i_a64_codec_config = {
.name = "Audio Codec (digital part)",
+ .type = SUNXI_I2S_SUN4I,
.txchsel = 0x30,
.txchmap = 0x34,
.rxchsel = 0x38,
.rxchmap = 0x3c,
};
+static const struct sunxi_i2s_config sun8i_h3_config = {
+ .name = "I2S/PCM controller",
+ .type = SUNXI_I2S_SUN8I,
+ .txchsel = 0x34,
+ .txchmap = 0x44,
+ .rxchsel = 0x54,
+ .rxchmap = 0x58,
+};
+
static const struct of_compat_data compat_data[] = {
{ "allwinner,sun50i-a64-codec-i2s",
(uintptr_t)&sun50i_a64_codec_config },
+ { "allwinner,sun8i-h3-i2s",
+ (uintptr_t)&sun8i_h3_config },
{ NULL }
};
@@ -150,6 +184,7 @@
bus_dma_tag_t sc_dmat;
int sc_phandle;
bus_addr_t sc_baseaddr;
+ struct clk *sc_clk;
struct sunxi_i2s_config *sc_cfg;
@@ -166,11 +201,63 @@
struct audio_dai_device sc_dai;
};
+#define I2S_TYPE(sc) ((sc)->sc_cfg->type)
+
#define I2S_READ(sc, reg) \
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
#define I2S_WRITE(sc, reg, val) \
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+static const u_int sun4i_i2s_bclk_divmap[] = {
+ [0] = 2,
+ [1] = 4,
+ [2] = 6,
+ [3] = 8,
+ [4] = 12,
+ [5] = 16,
+};
+
+static const u_int sun4i_i2s_mclk_divmap[] = {
+ [0] = 1,
+ [1] = 2,
+ [2] = 4,
+ [3] = 6,
+ [4] = 8,
+ [5] = 12,
+ [6] = 16,
+ [7] = 24,
+};
+
+static const u_int sun8i_i2s_divmap[] = {
+ [1] = 1,
+ [2] = 2,
+ [3] = 4,
+ [4] = 6,
+ [5] = 8,
+ [6] = 12,
+ [7] = 16,
+ [8] = 24,
+ [9] = 32,
+ [10] = 48,
+ [11] = 64,
+ [12] = 96,
+ [13] = 128,
+ [14] = 176,
+ [15] = 192,
+};
+
+static u_int
+sunxi_i2s_div_to_regval(const u_int *divmap, u_int divmaplen, u_int div)
+{
+ u_int n;
+
+ for (n = 0; n < divmaplen; n++)
+ if (divmap[n] == div)
+ return n;
+
+ return -1;
+}
+
static int
sunxi_i2s_allocdma(struct sunxi_i2s_softc *sc, size_t size,
size_t align, struct sunxi_i2s_dma *dma)
@@ -246,13 +333,6 @@
audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
{
- if ((setmode & AUMODE_PLAY)) {
- pfil->codec = audio_internal_to_linear32;
- }
- if ((setmode & AUMODE_RECORD)) {
- rfil->codec = audio_linear32_to_internal;
- }
-
return 0;
}
@@ -296,9 +376,17 @@
static int
sunxi_i2s_get_props(void *priv)
{
+ struct sunxi_i2s_softc * const sc = priv;
+ int props = 0;
- return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE |
- AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT;
+ if (sc->sc_pchan.ch_dma != NULL)
+ props |= AUDIO_PROP_PLAYBACK;
+ if (sc->sc_rchan.ch_dma != NULL)
+ props |= AUDIO_PROP_CAPTURE;
+ if (sc->sc_pchan.ch_dma != NULL && sc->sc_rchan.ch_dma != NULL)
+ props |= AUDIO_PROP_FULLDUPLEX;
+
+ return props;
}
static int
@@ -323,6 +411,9 @@
uint32_t val;
int error;
+ if (ch->ch_dma == NULL)
+ return EIO;
+
pstart = 0;
psize = (uintptr_t)end - (uintptr_t)start;
@@ -381,6 +472,9 @@
uint32_t val;
int error;
+ if (ch->ch_dma == NULL)
+ return EIO;
+
pstart = 0;
psize = (uintptr_t)end - (uintptr_t)start;
@@ -434,6 +528,9 @@
struct sunxi_i2s_chan *ch = &sc->sc_pchan;
uint32_t val;
+ if (ch->ch_dma == NULL)
+ return EIO;
+
/* Disable DMA channel */
fdtbus_dma_halt(ch->ch_dma);
@@ -458,6 +555,9 @@
struct sunxi_i2s_chan *ch = &sc->sc_rchan;
uint32_t val;
Home |
Main Index |
Thread Index |
Old Index