Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/imx From Petri Laakso <petri.laakso%asd.fi@localhost>:
details: https://anonhg.NetBSD.org/src/rev/9eb16dba3487
branches: trunk
changeset: 335498:9eb16dba3487
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Sat Jan 10 12:16:28 2015 +0000
description:
>From Petri Laakso <petri.laakso%asd.fi@localhost>:
- Audio output driver for imx23
- Supporting code for audio driver
diffstat:
sys/arch/arm/imx/imx23_digfilt.c | 1130 +++++++++++++++++++++++++++++++++++
sys/arch/arm/imx/imx23_digfiltreg.h | 382 +++++++++++
sys/arch/arm/imx/imx23_digfiltvar.h | 35 +
sys/arch/arm/imx/imx23_rtc.c | 199 ++++++
sys/arch/arm/imx/imx23_rtcreg.h | 3 +-
sys/arch/arm/imx/imx23_rtcvar.h | 37 +
6 files changed, 1785 insertions(+), 1 deletions(-)
diffs (truncated from 1820 to 300 lines):
diff -r aab760eb2d0c -r 9eb16dba3487 sys/arch/arm/imx/imx23_digfilt.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/imx/imx23_digfilt.c Sat Jan 10 12:16:28 2015 +0000
@@ -0,0 +1,1130 @@
+/* $Id: imx23_digfilt.c,v 1.1 2015/01/10 12:16:28 jmcneill Exp $ */
+
+/*
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Petri Laakso.
+ *
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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/param.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/device.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/mutex.h>
+#include <sys/audioio.h>
+#include <dev/audio_if.h>
+#include <dev/auconv.h>
+#include <sys/mallocvar.h>
+#include <arm/imx/imx23_digfiltreg.h>
+#include <arm/imx/imx23_rtcvar.h>
+#include <arm/imx/imx23_clkctrlvar.h>
+#include <arm/imx/imx23_apbdmavar.h>
+#include <arm/imx/imx23_icollreg.h>
+#include <arm/imx/imx23var.h>
+
+#include <arm/pic/picvar.h>
+
+/* Autoconf. */
+static int digfilt_match(device_t, cfdata_t, void *);
+static void digfilt_attach(device_t, device_t, void *);
+static int digfilt_activate(device_t, enum devact);
+
+/* Audio driver interface. */
+static int digfilt_drain(void *);
+static int digfilt_query_encoding(void *, struct audio_encoding *);
+static int digfilt_set_params(void *, int, int, audio_params_t *,
+ audio_params_t *, stream_filter_list_t *,
+ stream_filter_list_t *);
+static int digfilt_round_blocksize(void *, int, int, const audio_params_t *);
+static int digfilt_init_output(void *, void *, int );
+static int digfilt_start_output(void *, void *, int, void (*)(void *), void *);
+static int digfilt_halt_output(void *);
+static int digfilt_getdev(void *, struct audio_device *);
+static int digfilt_set_port(void *, mixer_ctrl_t *);
+static int digfilt_get_port(void *, mixer_ctrl_t *);
+static int digfilt_query_devinfo(void *, mixer_devinfo_t *);
+static void *digfilt_allocm(void *, int, size_t);
+static void digfilt_freem(void *, void *, size_t);
+static size_t digfilt_round_buffersize(void *, int, size_t);
+static int digfilt_get_props(void *);
+static void digfilt_get_locks(void *, kmutex_t **, kmutex_t **);
+
+/* IRQs */
+static int dac_error_intr(void *);
+static int dac_dma_intr(void *);
+
+struct digfilt_softc;
+
+/* Audio out. */
+static void *digfilt_ao_alloc_dmachain(void *, size_t);
+static void digfilt_ao_apply_mutes(struct digfilt_softc *);
+static void digfilt_ao_init(struct digfilt_softc *);
+static void digfilt_ao_reset(struct digfilt_softc *);
+static void digfilt_ao_set_rate(struct digfilt_softc *, int);
+
+/* Audio in. */
+#if 0
+static void digfilt_ai_reset(struct digfilt_softc *);
+#endif
+
+#define DIGFILT_DMA_NSEGS 1
+#define DIGFILT_BLOCKSIZE_MAX 4096
+#define DIGFILT_BLOCKSIZE_ROUND 512
+#define DIGFILT_DMA_CHAIN_LENGTH 3
+#define DIGFILT_DMA_CHANNEL 1
+#define DIGFILT_MUTE_DAC 1
+#define DIGFILT_MUTE_HP 2
+#define DIGFILT_MUTE_LINE 4
+#define DIGFILT_SOFT_RST_LOOP 455 /* At least 1 us. */
+
+#define AO_RD(sc, reg) \
+ bus_space_read_4(sc->sc_iot, sc->sc_aohdl, (reg))
+#define AO_WR(sc, reg, val) \
+ bus_space_write_4(sc->sc_iot, sc->sc_aohdl, (reg), (val))
+#define AI_RD(sc, reg) \
+ bus_space_read_4(sc->sc_iot, sc->sc_aihdl, (reg))
+#define AI_WR(sc, reg, val) \
+ bus_space_write_4(sc->sc_iot, sc->sc_aihdl, (reg), (val))
+
+struct digfilt_softc {
+ device_t sc_dev;
+ device_t sc_audiodev;
+ struct audio_format sc_format;
+ struct audio_encoding_set *sc_encodings;
+ bus_space_handle_t sc_aihdl;
+ bus_space_handle_t sc_aohdl;
+ apbdma_softc_t sc_dmac;
+ bus_dma_tag_t sc_dmat;
+ bus_dmamap_t sc_dmamp;
+ bus_dmamap_t sc_c_dmamp;
+ bus_dma_segment_t sc_ds[DIGFILT_DMA_NSEGS];
+ bus_dma_segment_t sc_c_ds[DIGFILT_DMA_NSEGS];
+ bus_space_handle_t sc_hdl;
+ kmutex_t sc_intr_lock;
+ bus_space_tag_t sc_iot;
+ kmutex_t sc_lock;
+ audio_params_t sc_pparam;
+ void *sc_buffer;
+ void *sc_dmachain;
+ void *sc_intarg;
+ void (*sc_intr)(void*);
+ uint8_t sc_mute;
+ uint8_t sc_cmd_index;
+};
+
+CFATTACH_DECL3_NEW(digfilt,
+ sizeof(struct digfilt_softc),
+ digfilt_match,
+ digfilt_attach,
+ NULL,
+ digfilt_activate,
+ NULL,
+ NULL,
+ 0);
+
+static const struct audio_hw_if digfilt_hw_if = {
+ .open = NULL,
+ .close = NULL,
+ .drain = digfilt_drain,
+ .query_encoding = digfilt_query_encoding,
+ .set_params = digfilt_set_params,
+ .round_blocksize = digfilt_round_blocksize,
+ .commit_settings = NULL,
+ .init_output = digfilt_init_output,
+ .init_input = NULL,
+ .start_output = digfilt_start_output,
+ .start_input = NULL,
+ .halt_output = digfilt_halt_output,
+ .speaker_ctl = NULL,
+ .getdev = digfilt_getdev,
+ .setfd = NULL,
+ .set_port = digfilt_set_port,
+ .get_port = digfilt_get_port,
+ .query_devinfo = digfilt_query_devinfo,
+ .allocm = digfilt_allocm,
+ .freem = digfilt_freem,
+ .round_buffersize = digfilt_round_buffersize,
+ .mappage = NULL,
+ .get_props = digfilt_get_props,
+ .trigger_output = NULL,
+ .trigger_input = NULL,
+ .dev_ioctl = NULL,
+ .get_locks = digfilt_get_locks
+};
+
+enum {
+ DIGFILT_OUTPUT_CLASS,
+ DIGFILT_OUTPUT_DAC_VOLUME,
+ DIGFILT_OUTPUT_DAC_MUTE,
+ DIGFILT_OUTPUT_HP_VOLUME,
+ DIGFILT_OUTPUT_HP_MUTE,
+ DIGFILT_OUTPUT_LINE_VOLUME,
+ DIGFILT_OUTPUT_LINE_MUTE,
+ DIGFILT_ENUM_LAST
+};
+
+static int
+digfilt_match(device_t parent, cfdata_t match, void *aux)
+{
+ struct apb_attach_args *aa = aux;
+
+ if (aa->aa_addr == HW_DIGFILT_BASE && aa->aa_size == HW_DIGFILT_SIZE)
+ return 1;
+ else
+ return 0;
+}
+
+static void
+digfilt_attach(device_t parent, device_t self, void *aux)
+{
+ struct apb_softc *sc_parent = device_private(parent);
+ struct digfilt_softc *sc = device_private(self);
+ struct apb_attach_args *aa = aux;
+ static int digfilt_attached = 0;
+ int error;
+ uint32_t v;
+ void *intr;
+
+ sc->sc_dev = self;
+ sc->sc_iot = aa->aa_iot;
+ sc->sc_dmat = aa->aa_dmat;
+
+ /* This driver requires DMA functionality from the bus.
+ * Parent bus passes handle to the DMA controller instance. */
+ if (sc_parent->dmac == NULL) {
+ aprint_error_dev(sc->sc_dev, "DMA functionality missing\n");
+ return;
+ }
+ sc->sc_dmac = device_private(sc_parent->dmac);
+
+ if (aa->aa_addr == HW_DIGFILT_BASE && digfilt_attached) {
+ aprint_error_dev(sc->sc_dev, "DIGFILT already attached\n");
+ return;
+ }
+
+ /* Allocate DMA for audio buffer. */
+ error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, DIGFILT_DMA_NSEGS,
+ MAXPHYS, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_dmamp);
+ if (error) {
+ aprint_error_dev(sc->sc_dev,
+ "Unable to allocate DMA handle\n");
+ return;
+ }
+
+ /* Allocate for DMA chain. */
+ error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, DIGFILT_DMA_NSEGS,
+ MAXPHYS, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_c_dmamp);
+ if (error) {
+ aprint_error_dev(sc->sc_dev,
+ "Unable to allocate DMA handle\n");
+ return;
+ }
+
+ /* Map DIGFILT bus space. */
+ if (bus_space_map(sc->sc_iot, HW_DIGFILT_BASE, HW_DIGFILT_SIZE, 0,
+ &sc->sc_hdl)) {
+ aprint_error_dev(sc->sc_dev,
+ "Unable to map DIGFILT bus space\n");
+ return;
+ }
+
+ /* Map AUDIOOUT subregion from parent bus space. */
+ if (bus_space_subregion(sc->sc_iot, sc->sc_hdl,
+ (HW_AUDIOOUT_BASE - HW_DIGFILT_BASE), HW_AUDIOOUT_SIZE,
+ &sc->sc_aohdl)) {
+ aprint_error_dev(sc->sc_dev,
+ "Unable to submap AUDIOOUT bus space\n");
+ return;
+ }
+
+ /* Map AUDIOIN subregion from parent bus space. */
+ if (bus_space_subregion(sc->sc_iot, sc->sc_hdl,
+ (HW_AUDIOIN_BASE - HW_DIGFILT_BASE), HW_AUDIOIN_SIZE,
+ &sc->sc_aihdl)) {
+ aprint_error_dev(sc->sc_dev,
+ "Unable to submap AUDIOIN bus space\n");
+ return;
+ }
+
+ /* Enable clocks to the DIGFILT block. */
+ clkctrl_en_filtclk();
+ delay(10);
+
+ digfilt_ao_reset(sc); /* Reset AUDIOOUT. */
+ /* Not yet: digfilt_ai_reset(sc); */
+
+ v = AO_RD(sc, HW_AUDIOOUT_VERSION);
+ aprint_normal(": DIGFILT Block v%" __PRIuBIT ".%" __PRIuBIT
+ ".%" __PRIuBIT "\n",
+ __SHIFTOUT(v, HW_AUDIOOUT_VERSION_MAJOR),
+ __SHIFTOUT(v, HW_AUDIOOUT_VERSION_MINOR),
+ __SHIFTOUT(v, HW_AUDIOOUT_VERSION_STEP));
+
+ digfilt_ao_init(sc);
+ digfilt_ao_set_rate(sc, 44100); /* Default sample rate 44.1 kHz. */
+
+ mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+ mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
+
+ /* HW supported formats. */
+ sc->sc_format.mode = AUMODE_PLAY|AUMODE_RECORD;
Home |
Main Index |
Thread Index |
Old Index