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