Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/allwinner capture support
details: https://anonhg.NetBSD.org/src/rev/14ce9409b551
branches: trunk
changeset: 332102:14ce9409b551
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Sat Sep 06 22:48:19 2014 +0000
description:
capture support
diffstat:
sys/arch/arm/allwinner/awin_ac.c | 238 ++++++++++++++++++++++++++++++++++++--
1 files changed, 223 insertions(+), 15 deletions(-)
diffs (truncated from 385 to 300 lines):
diff -r 24e3e030c700 -r 14ce9409b551 sys/arch/arm/allwinner/awin_ac.c
--- a/sys/arch/arm/allwinner/awin_ac.c Sat Sep 06 21:21:36 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_ac.c Sat Sep 06 22:48:19 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_ac.c,v 1.10 2014/09/06 20:54:53 jmcneill Exp $ */
+/* $NetBSD: awin_ac.c,v 1.11 2014/09/06 22:48:19 jmcneill Exp $ */
/*-
* Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -30,7 +30,7 @@
#include "opt_ddb.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: awin_ac.c,v 1.10 2014/09/06 20:54:53 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_ac.c,v 1.11 2014/09/06 22:48:19 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -47,6 +47,7 @@
#include <arm/allwinner/awin_var.h>
#define AWINAC_TX_TRIG_LEVEL 0xf
+#define AWINAC_RX_TRIG_LEVEL 0x7
#define AWINAC_DRQ_CLR_CNT 0x3
#define AWINAC_INIT_VOL 0x3b
@@ -114,10 +115,46 @@
#define DAC_ACTL_PAVOL __BITS(5,0)
#define AC_DAC_TUNE 0x14
#define AC_ADC_FIFOC 0x1c
+#define ADC_FIFOC_FS __BITS(31,29)
+#define ADC_FS_48KHZ 0
+#define ADC_FS_32KHZ 1
+#define ADC_FS_24KHZ 2
+#define ADC_FS_16KHZ 3
+#define ADC_FS_12KHZ 4
+#define DAC_FS_8KHZ 5
+#define ADC_FIFOC_EN_AD __BIT(28)
+#define ADC_FIFOC_RX_FIFO_MODE __BIT(24)
+#define ADC_FIFOC_RX_TRIG_LEVEL __BITS(12,8)
+#define ADC_FIFOC_MONO_EN __BIT(7)
+#define ADC_FIFOC_RX_SAMPLE_BITS __BIT(6)
+#define ADC_FIFOC_DRQ_EN __BIT(4)
+#define ADC_FIFOC_IRQ_EN __BIT(3)
+#define ADC_FIFOC_OVERRUN_IRQ_EN __BIT(2)
+#define ADC_FIFOC_FIFO_FLUSH __BIT(1)
#define AC_ADC_FIFOS 0x20
+#define ADC_FIFOS_RXA __BIT(23)
+#define ADC_FIFOS_RXA_CNT __BITS(13,8)
+#define ADC_FIFOS_RXA_INT __BIT(3)
+#define ADC_FIFOS_RXO_INT __BIT(1)
#define AC_ADC_RXDATA 0x24
#define AC_ADC_ACTL 0x28
+#define ADC_ACTL_ADCREN __BIT(31)
+#define ADC_ACTL_ADCLEN __BIT(30)
+#define ADC_ACTL_PREG1EN __BIT(29)
+#define ADC_ACTL_PREG2EN __BIT(28)
+#define ADC_ACTL_VMICEN __BIT(27)
+#define ADC_ACTL_ADCG __BITS(22,20)
+#define ADC_ACTL_ADCIS __BITS(19,17)
+#define ADC_ACTL_LNRDF __BIT(16)
+#define ADC_ACTL_LNPREG __BIT(15)
+#define ADC_ACTL_LHPOUTN __BIT(11)
+#define ADC_ACTL_RHPOUTN __BIT(10)
+#define ADC_ACTL_DITHER __BIT(8)
+#define ADC_ACTL_DITHER_CLK_SELECT __BITS(7,6)
#define ADC_ACTL_PA_EN __BIT(4)
+#define ADC_ACTL_DDE __BIT(3)
+#define ADC_ACTL_COMPTEN __BIT(2)
+#define ADC_ACTL_PTDBS __BITS(1,0)
#define AC_DAC_CNT 0x30
#define AC_ADC_CNT 0x34
#define AC_DAC_CAL 0x38
@@ -149,9 +186,6 @@
struct audio_encoding_set *sc_encodings;
audio_params_t sc_pparam;
-
- void * sc_ih;
-
struct awin_dma_channel *sc_pdma;
void (*sc_pint)(void *);
void *sc_pintarg;
@@ -160,6 +194,15 @@
bus_addr_t sc_pcur;
int sc_pblksize;
+ audio_params_t sc_rparam;
+ struct awin_dma_channel *sc_rdma;
+ void (*sc_rint)(void *);
+ void *sc_rintarg;
+ bus_addr_t sc_rstart;
+ bus_addr_t sc_rend;
+ bus_addr_t sc_rcur;
+ int sc_rblksize;
+
struct awin_gpio_pindata sc_pactrl_gpio;
bool sc_has_pactrl_gpio;
};
@@ -176,6 +219,8 @@
static void awinac_pint(void *);
static int awinac_play(struct awinac_softc *);
+static void awinac_rint(void *);
+static int awinac_rec(struct awinac_softc *);
#if defined(DDB)
void awinac_dump_regs(void);
@@ -313,7 +358,12 @@
sc->sc_pdma = awin_dma_alloc(AWIN_DMA_TYPE_NDMA, awinac_pint, sc);
if (sc->sc_pdma == NULL) {
- aprint_error_dev(self, "couldn't allocate DMA channel\n");
+ aprint_error_dev(self, "couldn't allocate play DMA channel\n");
+ return;
+ }
+ sc->sc_rdma = awin_dma_alloc(AWIN_DMA_TYPE_NDMA, awinac_rint, sc);
+ if (sc->sc_rdma == NULL) {
+ aprint_error_dev(self, "couldn't allocate rec DMA channel\n");
return;
}
@@ -386,7 +436,14 @@
val &= ~DAC_FIFOC_FIFO_OVERRUN_IRQ_EN;
AC_WRITE(sc, AC_DAC_FIFOC, val);
+ val = AC_READ(sc, AC_ADC_FIFOC);
+ val &= ~ADC_FIFOC_DRQ_EN;
+ val &= ~ADC_FIFOC_IRQ_EN;
+ val &= ~ADC_FIFOC_OVERRUN_IRQ_EN;
+ AC_WRITE(sc, AC_ADC_FIFOC, val);
+
AC_WRITE(sc, AC_DAC_FIFOS, AC_READ(sc, AC_DAC_FIFOS));
+ AC_WRITE(sc, AC_ADC_FIFOS, AC_READ(sc, AC_ADC_FIFOS));
}
static int
@@ -474,15 +531,61 @@
return 0;
}
+static void
+awinac_rint(void *priv)
+{
+ struct awinac_softc *sc = priv;
+
+ mutex_enter(&sc->sc_intr_lock);
+ if (sc->sc_rint == NULL) {
+ mutex_exit(&sc->sc_intr_lock);
+ return;
+ }
+ sc->sc_rint(sc->sc_rintarg);
+ mutex_exit(&sc->sc_intr_lock);
+
+ awinac_rec(sc);
+}
+
+static int
+awinac_rec(struct awinac_softc *sc)
+{
+ int error;
+
+ error = awin_dma_transfer(sc->sc_rdma,
+ AWIN_CORE_PBASE + AWIN_AC_OFFSET + AC_ADC_RXDATA, sc->sc_rcur,
+ sc->sc_rblksize);
+ if (error) {
+ device_printf(sc->sc_dev, "failed to transfer DMA; error %d\n",
+ error);
+ return error;
+ }
+
+ sc->sc_rcur += sc->sc_rblksize;
+ if (sc->sc_rcur >= sc->sc_rend)
+ sc->sc_rcur = sc->sc_rstart;
+
+ return 0;
+}
+
static int
awinac_open(void *priv, int flags)
{
+ struct awinac_softc *sc = priv;
+
+ if (sc->sc_has_pactrl_gpio)
+ awin_gpio_pindata_write(&sc->sc_pactrl_gpio, 1);
+
return 0;
}
static void
awinac_close(void *priv)
{
+ struct awinac_softc *sc = priv;
+
+ if (sc->sc_has_pactrl_gpio)
+ awin_gpio_pindata_write(&sc->sc_pactrl_gpio, 0);
}
static int
@@ -495,6 +598,10 @@
val |= DAC_FIFOC_FIFO_FLUSH;
AC_WRITE(sc, AC_DAC_FIFOC, val);
+ val = AC_READ(sc, AC_ADC_FIFOC);
+ val |= ADC_FIFOC_FIFO_FLUSH;
+ AC_WRITE(sc, AC_ADC_FIFOC, val);
+
return 0;
}
@@ -523,6 +630,15 @@
pfil->filters[0].param :
*play;
}
+ if (rec && (setmode & AUMODE_RECORD)) {
+ index = auconv_set_converter(&sc->sc_format, 1,
+ AUMODE_RECORD, rec, true, rfil);
+ if (index < 0)
+ return EINVAL;
+ sc->sc_rparam = rfil->req_size > 0 ?
+ rfil->filters[0].param :
+ *rec;
+ }
return 0;
}
@@ -537,6 +653,10 @@
return EINVAL;
if (sc->sc_pparam.validbits != 16 && sc->sc_pparam.validbits != 24)
return EINVAL;
+ if (sc->sc_rparam.sample_rate != 48000)
+ return EINVAL;
+ if (sc->sc_rparam.validbits != 16 && sc->sc_rparam.validbits != 24)
+ return EINVAL;
val = AC_READ(sc, AC_DAC_FIFOC);
val &= ~DAC_FIFOC_FIR_VER;
@@ -558,6 +678,21 @@
}
AC_WRITE(sc, AC_DAC_FIFOC, val);
+ val = AC_READ(sc, AC_ADC_FIFOC);
+ val |= ADC_FIFOC_EN_AD;
+ val |= ADC_FIFOC_RX_FIFO_MODE;
+ val &= ~ADC_FIFOC_FS;
+ val |= __SHIFTIN(ADC_FS_48KHZ, ADC_FIFOC_FS);
+ val &= ~ADC_FIFOC_RX_TRIG_LEVEL;
+ val |= __SHIFTIN(AWINAC_RX_TRIG_LEVEL, ADC_FIFOC_RX_TRIG_LEVEL);
+ val &= ~ADC_FIFOC_MONO_EN;
+ if (sc->sc_rparam.validbits == 16) {
+ val &= ~ADC_FIFOC_RX_SAMPLE_BITS;
+ } else {
+ val |= ADC_FIFOC_RX_SAMPLE_BITS;
+ }
+ AC_WRITE(sc, AC_ADC_FIFOC, val);
+
return 0;
}
@@ -569,9 +704,6 @@
awin_dma_halt(sc->sc_pdma);
- if (sc->sc_has_pactrl_gpio)
- awin_gpio_pindata_write(&sc->sc_pactrl_gpio, 0);
-
val = AC_READ(sc, AC_DAC_ACTL);
val &= ~DAC_ACTL_DACAREN;
val &= ~DAC_ACTL_DACALEN;
@@ -591,7 +723,24 @@
static int
awinac_halt_input(void *priv)
{
- return EINVAL;
+ struct awinac_softc *sc = priv;
+ uint32_t val;
+
+ awin_dma_halt(sc->sc_rdma);
+
+ val = AC_READ(sc, AC_ADC_ACTL);
+ val &= ~ADC_ACTL_ADCREN;
+ val &= ~ADC_ACTL_ADCLEN;
+ AC_WRITE(sc, AC_ADC_ACTL, val);
+
+ val = AC_READ(sc, AC_ADC_FIFOC);
+ val &= ~ADC_FIFOC_DRQ_EN;
+ AC_WRITE(sc, AC_ADC_FIFOC, val);
+
+ sc->sc_rint = NULL;
+ sc->sc_rintarg = NULL;
+
+ return 0;
}
static int
@@ -744,7 +893,8 @@
awinac_get_props(void *priv)
{
return AUDIO_PROP_PLAYBACK|AUDIO_PROP_CAPTURE|
- AUDIO_PROP_INDEPENDENT|AUDIO_PROP_MMAP;
Home |
Main Index |
Thread Index |
Old Index