Port-arm archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
imx23 audio output driver
Hi
I've hacked together audio output driver for imx23 olinuxino
and it has been playing tunes for few days without problems.
I'd be pleased if someone reviews and commits this to the current tree.
Patch can be found also from http://www.asd.fi/~petri/imx23_digfilt.patch
Best regards
Petri Laakso
This patch touches many files. I briefly comment all of those.
Index: sys/arch/arm/imx/files.imx23
- Add new devices rtc and digfilt
Index: sys/arch/arm/imx/imx23_apbdma.c
Index: sys/arch/arm/imx/imx23_apbdmareg.h
Index: sys/arch/arm/imx/imx23_apbdmavar.h
- Fix AHBH => APBH
- Add support for APBX DMA
- Added apbdma_wait() to wait for DMA completion
Index: sys/arch/arm/imx/imx23_clkctrl.c
Index: sys/arch/arm/imx/imx23_clkctrlvar.h
- clkctrl_en_filtclk(): Enable 24MHz clock for the Digital Filter.
Index: sys/arch/arm/imx/imx23_digfilt.c
Index: sys/arch/arm/imx/imx23_digfiltreg.h
Index: sys/arch/arm/imx/imx23_digfiltvar.h
- Audio output driver for imx23
Index: sys/arch/arm/imx/imx23_rtc.c
Index: sys/arch/arm/imx/imx23_rtcreg.h
Index: sys/arch/arm/imx/imx23_rtcvar.h
- Supporting code for audio driver
Index: sys/arch/evbarm/conf/IMX23_OLINUXINO
- New audio driver
Index: sys/arch/evbarm/conf/files.imx23_olinuxino
Index: sys/arch/evbarm/imx23_olinuxino/imx23_olinuxino_machdep.c
- Use BOOT_ARGS if defined
Index: sys/arch/arm/imx/files.imx23
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/imx/files.imx23,v
retrieving revision 1.2
diff -u -r1.2 files.imx23
--- sys/arch/arm/imx/files.imx23 7 Oct 2013 17:36:40 -0000 1.2
+++ sys/arch/arm/imx/files.imx23 27 Dec 2014 17:13:46 -0000
@@ -3,6 +3,8 @@
# Freescale i.MX23 applications processor configuration info.
#
+defflag opt_imx.h IMX23
+
file arch/arm/arm32/irq_dispatch.S icoll
file arch/arm/imx/imx23_space.c ahb|apbh|apbx
file arch/arm/imx/imx23_dma.c ahb|apbh|apbx
@@ -80,3 +82,13 @@
# EHCI
attach ehci at imxusbc with imxehci
file arch/arm/imx/imxusb.c imxehci
+
+# RTC
+device rtc
+attach rtc at apbx
+file arch/arm/imx/imx23_rtc.c rtc
+
+# Digital filter: Audio I/O
+device digfilt: audiobus
+attach digfilt at apbx with digfilt
+file arch/arm/imx/imx23_digfilt.c digfilt
Index: sys/arch/arm/imx/imx23_apbdma.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/imx/imx23_apbdma.c,v
retrieving revision 1.3
diff -u -r1.3 imx23_apbdma.c
--- sys/arch/arm/imx/imx23_apbdma.c 3 Mar 2013 10:33:56 -0000 1.3
+++ sys/arch/arm/imx/imx23_apbdma.c 27 Dec 2014 17:13:46 -0000
@@ -92,10 +92,10 @@
static u_int apbdma_attached = 0;
if ((strncmp(device_xname(parent), "apbh", 4) == 0) &&
- (apbdma_attached & F_AHBH_DMA))
+ (apbdma_attached & F_APBH_DMA))
return;
if ((strncmp(device_xname(parent), "apbx", 4) == 0) &&
- (apbdma_attached & F_AHBX_DMA))
+ (apbdma_attached & F_APBX_DMA))
return;
sc->sc_dev = self;
@@ -109,25 +109,30 @@
}
if (strncmp(device_xname(parent), "apbh", 4) == 0)
- sc->flags = F_AHBH_DMA;
+ sc->flags = F_APBH_DMA;
if (strncmp(device_xname(parent), "apbx", 4) == 0)
- sc->flags = F_AHBX_DMA;
+ sc->flags = F_APBX_DMA;
apbdma_reset(sc);
apbdma_init(sc);
- if (sc->flags & F_AHBH_DMA)
- apbdma_attached |= F_AHBH_DMA;
- if (sc->flags & F_AHBX_DMA)
- apbdma_attached |= F_AHBX_DMA;
+ if (sc->flags & F_APBH_DMA)
+ apbdma_attached |= F_APBH_DMA;
+ if (sc->flags & F_APBX_DMA)
+ apbdma_attached |= F_APBX_DMA;
sc_parent->dmac = self;
/* Initialize mutex to control concurrent access from the drivers. */
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH);
- aprint_normal("\n");
+ if (sc->flags & F_APBH_DMA)
+ aprint_normal(": APBH DMA\n");
+ else if (sc->flags & F_APBX_DMA)
+ aprint_normal(": APBX DMA\n");
+ else
+ panic("dma flag missing!\n");
return;
}
@@ -192,7 +197,7 @@
apbdma_init(struct apbdma_softc *sc)
{
- if (sc->flags & F_AHBH_DMA) {
+ if (sc->flags & F_APBH_DMA) {
DMA_WR(sc, HW_APBH_CTRL0_SET, HW_APBH_CTRL0_AHB_BURST8_EN);
DMA_WR(sc, HW_APBH_CTRL0_SET, HW_APBH_CTRL0_APB_BURST4_EN);
}
@@ -279,7 +284,7 @@
{
uint32_t reg;
- if (sc->flags & F_AHBH_DMA)
+ if (sc->flags & F_APBH_DMA)
reg = HW_APB_CHN_NXTCMDAR(HW_APBH_CH0_NXTCMDAR, channel);
else
reg = HW_APB_CHN_NXTCMDAR(HW_APBX_CH0_NXTCMDAR, channel);
@@ -301,7 +306,7 @@
uint32_t reg;
uint8_t val;
- if (sc->flags & F_AHBH_DMA) {
+ if (sc->flags & F_APBH_DMA) {
reg = HW_APB_CHN_SEMA(HW_APBH_CH0_SEMA, channel);
val = __SHIFTIN(1, HW_APBH_CH0_SEMA_INCREMENT_SEMA);
} else {
@@ -324,7 +329,11 @@
{
mutex_enter(&sc->sc_lock);
- DMA_WR(sc, HW_APB_CTRL1_CLR, (1<<channel));
+ if (sc->flags & F_APBH_DMA) {
+ DMA_WR(sc, HW_APB_CTRL1_CLR, (1<<channel));
+ } else {
+ DMA_WR(sc, HW_APB_CTRL1_CLR, (1<<channel));
+ }
mutex_exit(&sc->sc_lock);
return;
@@ -383,11 +392,34 @@
mutex_enter(&sc->sc_lock);
- DMA_WR(sc, HW_APB_CTRL0_SET,
- __SHIFTIN((1<<channel), HW_APBH_CTRL0_RESET_CHANNEL));
- while(DMA_RD(sc, HW_APB_CTRL0) & HW_APBH_CTRL0_RESET_CHANNEL);
+ if (sc->flags & F_APBH_DMA) {
+ DMA_WR(sc, HW_APB_CTRL0_SET,
+ __SHIFTIN((1<<channel), HW_APBH_CTRL0_RESET_CHANNEL));
+ while(DMA_RD(sc, HW_APB_CTRL0) & HW_APBH_CTRL0_RESET_CHANNEL);
+ } else {
+ DMA_WR(sc, HW_APBX_CHANNEL_CTRL_SET,
+ __SHIFTIN((1<<channel), HW_APBH_CTRL0_RESET_CHANNEL));
+ while(DMA_RD(sc, HW_APBX_CHANNEL_CTRL) & (1<<channel));
+ }
mutex_exit(&sc->sc_lock);
return;
}
+
+void
+apbdma_wait(struct apbdma_softc *sc, unsigned int channel)
+{
+
+ mutex_enter(&sc->sc_lock);
+
+ if (sc->flags & F_APBH_DMA) {
+ while (DMA_RD(sc, HW_APB_CHN_SEMA(HW_APBH_CH0_SEMA, channel)) & HW_APBH_CH0_SEMA_PHORE)
+ ;
+ } else {
+ while (DMA_RD(sc, HW_APB_CHN_SEMA(HW_APBX_CH0_SEMA, channel)) & HW_APBX_CH0_SEMA_PHORE)
+ ;
+ }
+
+ mutex_exit(&sc->sc_lock);
+}
Index: sys/arch/arm/imx/imx23_apbdmareg.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/imx/imx23_apbdmareg.h,v
retrieving revision 1.2
diff -u -r1.2 imx23_apbdmareg.h
--- sys/arch/arm/imx/imx23_apbdmareg.h 3 Mar 2013 10:33:56 -0000 1.2
+++ sys/arch/arm/imx/imx23_apbdmareg.h 27 Dec 2014 17:13:46 -0000
@@ -66,4 +66,6 @@
#define HW_APB_CTRL2_CLR 0x028
#define HW_APB_CTRL2_TOG 0x02C
+#define HW_APBX_CHANNEL_CTRL 0x30
+#define HW_APBX_CHANNEL_CTRL_SET 0x34
#endif /* !_ARM_IMX_IMX23_APBDMAREG_H_ */
Index: sys/arch/arm/imx/imx23_apbdmavar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/imx/imx23_apbdmavar.h,v
retrieving revision 1.1
diff -u -r1.1 imx23_apbdmavar.h
--- sys/arch/arm/imx/imx23_apbdmavar.h 3 Mar 2013 10:33:56 -0000 1.1
+++ sys/arch/arm/imx/imx23_apbdmavar.h 27 Dec 2014 17:13:46 -0000
@@ -58,8 +58,8 @@
#define APBDMA_CMD_DMA_SENSE 3
/* Flags. */
-#define F_AHBH_DMA __BIT(0)
-#define F_AHBX_DMA __BIT(1)
+#define F_APBH_DMA __BIT(0)
+#define F_APBX_DMA __BIT(1)
/* Number of channels. */
#define AHBH_DMA_CHANNELS 8
@@ -133,5 +133,6 @@
void apbdma_ack_error_intr(struct apbdma_softc *, unsigned int);
unsigned int apbdma_intr_status(struct apbdma_softc *, unsigned int);
void apbdma_chan_reset(struct apbdma_softc *, unsigned int);
+void apbdma_wait(struct apbdma_softc *, unsigned int);
#endif /* !_ARM_IMX_IMX23_APBDMAVAR_H_ */
Index: sys/arch/arm/imx/imx23_clkctrl.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/imx/imx23_clkctrl.c,v
retrieving revision 1.1
diff -u -r1.1 imx23_clkctrl.c
--- sys/arch/arm/imx/imx23_clkctrl.c 7 Oct 2013 17:36:40 -0000 1.1
+++ sys/arch/arm/imx/imx23_clkctrl.c 27 Dec 2014 17:13:46 -0000
@@ -149,3 +149,22 @@
return;
}
+
+/*
+ * Enable 24MHz clock for the Digital Filter.
+ *
+ */
+void
+clkctrl_en_filtclk(void)
+{
+ struct clkctrl_softc *sc = _sc;
+
+ if (sc == NULL) {
+ aprint_error("clkctrl is not initalized");
+ return;
+ }
+
+ CLKCTRL_WR(sc, HW_CLKCTRL_XTAL_CLR, HW_CLKCTRL_XTAL_FILT_CLK24M_GATE);
+
+ return;
+}
Index: sys/arch/arm/imx/imx23_clkctrlvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/imx/imx23_clkctrlvar.h,v
retrieving revision 1.1
diff -u -r1.1 imx23_clkctrlvar.h
--- sys/arch/arm/imx/imx23_clkctrlvar.h 7 Oct 2013 17:36:40 -0000 1.1
+++ sys/arch/arm/imx/imx23_clkctrlvar.h 27 Dec 2014 17:13:46 -0000
@@ -33,5 +33,6 @@
#define _ARM_IMX_IMX23_CLKCTRLVAR_H_
void clkctrl_en_usb(void);
+void clkctrl_en_filtclk(void);
#endif /* !_ARM_IMX_IMX23_CLKCTRLVAR_H_ */
Index: sys/arch/arm/imx/imx23_digfilt.c
===================================================================
RCS file: sys/arch/arm/imx/imx23_digfilt.c
diff -N sys/arch/arm/imx/imx23_digfilt.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/arch/arm/imx/imx23_digfilt.c 27 Dec 2014 17:13:46 -0000
@@ -0,0 +1,1136 @@
+/* $Id$ */
+
+/*
+ * 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;
+ sc->sc_format.encoding = AUDIO_ENCODING_SLINEAR_LE;
+ sc->sc_format.validbits = 16;
+ sc->sc_format.precision = 16;
+ sc->sc_format.channels = 2;
+ sc->sc_format.channel_mask = AUFMT_STEREO;
+ sc->sc_format.frequency_type = 8;
+ sc->sc_format.frequency[0] = 8000;
+ sc->sc_format.frequency[1] = 11025;
+ sc->sc_format.frequency[2] = 12000;
+ sc->sc_format.frequency[3] = 16000;
+ sc->sc_format.frequency[4] = 22050;
+ sc->sc_format.frequency[5] = 24000;
+ sc->sc_format.frequency[6] = 32000;
+ sc->sc_format.frequency[7] = 44100;
+
+ if (auconv_create_encodings(&sc->sc_format, 1, &sc->sc_encodings)) {
+ aprint_error_dev(self, "could not create encodings\n");
+ return;
+ }
+
+ sc->sc_audiodev = audio_attach_mi(&digfilt_hw_if, sc, sc->sc_dev);
+
+ /* Default mutes. */
+ sc->sc_mute = DIGFILT_MUTE_LINE;
+ digfilt_ao_apply_mutes(sc);
+
+ /* Allocate DMA safe memory for the DMA chain. */
+ sc->sc_dmachain = digfilt_ao_alloc_dmachain(sc,
+ sizeof(struct apbdma_command) * DIGFILT_DMA_CHAIN_LENGTH);
+ if (sc->sc_dmachain == NULL) {
+ aprint_error_dev(self, "digfilt_ao_alloc_dmachain failed\n");
+ return;
+ }
+
+ intr = intr_establish(IRQ_DAC_DMA, IPL_SCHED, IST_LEVEL, dac_dma_intr,
+ sc);
+ if (intr == NULL) {
+ aprint_error_dev(sc->sc_dev,
+ "Unable to establish IRQ for DAC_DMA\n");
+ return;
+ }
+
+ intr = intr_establish(IRQ_DAC_ERROR, IPL_SCHED, IST_LEVEL,
+ dac_error_intr, sc);
+ if (intr == NULL) {
+ aprint_error_dev(sc->sc_dev,
+ "Unable to establish IRQ for DAC_ERROR\n");
+ return;
+ }
+
+ /* Initialize DMA channel. */
+ apbdma_chan_init(sc->sc_dmac, DIGFILT_DMA_CHANNEL);
+
+ digfilt_attached = 1;
+
+ return;
+}
+
+static int
+digfilt_activate(device_t self, enum devact act)
+{
+ return EOPNOTSUPP;
+}
+
+static int
+digfilt_drain(void *priv)
+{
+
+ struct digfilt_softc *sc = priv;
+
+ //printf("sc->sc_cmd_index = %d\n", sc->sc_cmd_index);
+ //apbdma_print(sc->sc_dmac);
+ apbdma_wait(sc->sc_dmac, 1);
+ sc->sc_cmd_index = 0;
+ //printf("sc->sc_cmd_index = %d\n", sc->sc_cmd_index);
+ //apbdma_print(sc->sc_dmac);
+
+ return 0;
+}
+
+static int
+digfilt_query_encoding(void *priv, struct audio_encoding *ae)
+{
+ struct digfilt_softc *sc = priv;
+ return auconv_query_encoding(sc->sc_encodings, ae);
+}
+
+static int
+digfilt_set_params(void *priv, int setmode, int usemode,
+ audio_params_t *play, audio_params_t *rec,
+ stream_filter_list_t *pfil, stream_filter_list_t *rfil)
+{
+ struct digfilt_softc *sc = priv;
+ int index;
+
+ if (play && (setmode & AUMODE_PLAY)) {
+ index = auconv_set_converter(&sc->sc_format, 1,
+ AUMODE_PLAY, play, true, pfil);
+ if (index < 0)
+ return EINVAL;
+ sc->sc_pparam = pfil->req_size > 0 ?
+ pfil->filters[0].param :
+ *play;
+
+ /* At this point bitrate should be figured out. */
+ digfilt_ao_set_rate(sc, sc->sc_pparam.sample_rate);
+ }
+
+ return 0;
+}
+
+static int
+digfilt_round_blocksize(void *priv, int bs, int mode,
+const audio_params_t *param)
+{
+ int blocksize;
+
+ if (bs > DIGFILT_BLOCKSIZE_MAX)
+ blocksize = DIGFILT_BLOCKSIZE_MAX;
+ else
+ blocksize = bs & ~(DIGFILT_BLOCKSIZE_ROUND-1);
+
+ return blocksize;
+}
+
+static int
+digfilt_init_output(void *priv, void *buffer, int size)
+{
+ struct digfilt_softc *sc = priv;
+ apbdma_command_t dma_cmd;
+ int i;
+ dma_cmd = sc->sc_dmachain;
+ sc->sc_cmd_index = 0;
+
+ /*
+ * Build circular DMA command chain template for later use.
+ */
+ for (i = 0; i < DIGFILT_DMA_CHAIN_LENGTH; i++) {
+ /* Last entry loops back to first. */
+ if (i == DIGFILT_DMA_CHAIN_LENGTH - 1)
+ dma_cmd[i].next = (void *)(sc->sc_c_dmamp->dm_segs[0].ds_addr);
+ else
+ dma_cmd[i].next = (void *)(sc->sc_c_dmamp->dm_segs[0].ds_addr + (sizeof(struct apbdma_command) * (1 + i)));
+
+ dma_cmd[i].control = __SHIFTIN(DIGFILT_BLOCKSIZE_MAX, APBDMA_CMD_XFER_COUNT) |
+ __SHIFTIN(1, APBDMA_CMD_CMDPIOWORDS) |
+ APBDMA_CMD_SEMAPHORE |
+ APBDMA_CMD_IRQONCMPLT |
+ APBDMA_CMD_CHAIN |
+ __SHIFTIN(APBDMA_CMD_DMA_READ, APBDMA_CMD_COMMAND);
+
+ dma_cmd[i].buffer = (void *)(sc->sc_c_dmamp->dm_segs[0].ds_addr);
+
+ dma_cmd[i].pio_words[0] = HW_AUDIOOUT_CTRL_WORD_LENGTH |
+ HW_AUDIOOUT_CTRL_FIFO_ERROR_IRQ_EN |
+ HW_AUDIOOUT_CTRL_RUN;
+
+ }
+
+ apbdma_chan_set_chain(sc->sc_dmac, DIGFILT_DMA_CHANNEL, sc->sc_c_dmamp);
+
+ return 0;
+}
+
+static int
+digfilt_start_output(void *priv, void *start, int bs, void (*intr)(void*), void *intarg)
+{
+ struct digfilt_softc *sc = priv;
+ apbdma_command_t dma_cmd;
+ bus_addr_t offset;
+
+ sc->sc_intr = intr;
+ sc->sc_intarg = intarg;
+ dma_cmd = sc->sc_dmachain;
+
+ offset = (bus_addr_t)start - (bus_addr_t)sc->sc_buffer;
+
+ dma_cmd[sc->sc_cmd_index].buffer =
+ (void *)((bus_addr_t)sc->sc_dmamp->dm_segs[0].ds_addr + offset);
+
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamp, offset, bs, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_c_dmamp,
+ sizeof(struct apbdma_command) * sc->sc_cmd_index, sizeof(struct apbdma_command), BUS_DMASYNC_PREWRITE);
+
+ sc->sc_cmd_index++;
+ if (sc->sc_cmd_index > DIGFILT_DMA_CHAIN_LENGTH - 1)
+ sc->sc_cmd_index = 0;
+
+ apbdma_run(sc->sc_dmac, DIGFILT_DMA_CHANNEL);
+
+ return 0;
+}
+
+static int
+digfilt_halt_output(void *priv)
+{
+ return 0;
+}
+
+static int
+digfilt_getdev(void *priv, struct audio_device *ad)
+{
+ struct digfilt_softc *sc = priv;
+
+ strncpy(ad->name, device_xname(sc->sc_dev), MAX_AUDIO_DEV_LEN);
+ strncpy(ad->version, "", MAX_AUDIO_DEV_LEN);
+ strncpy(ad->config, "", MAX_AUDIO_DEV_LEN);
+
+ return 0;
+}
+
+static int
+digfilt_set_port(void *priv, mixer_ctrl_t *mc)
+{
+ struct digfilt_softc *sc = priv;
+ uint32_t val;
+ uint8_t nvol;
+
+ switch (mc->dev) {
+ case DIGFILT_OUTPUT_DAC_VOLUME:
+ val = AO_RD(sc, HW_AUDIOOUT_DACVOLUME);
+ val &= ~(HW_AUDIOOUT_DACVOLUME_VOLUME_LEFT |
+ HW_AUDIOOUT_DACVOLUME_VOLUME_RIGHT);
+
+ /* DAC volume field is 8 bits. */
+ nvol = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
+ if (nvol > 0xff)
+ nvol = 0xff;
+
+ val |= __SHIFTIN(nvol, HW_AUDIOOUT_DACVOLUME_VOLUME_LEFT);
+
+ nvol = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
+ if (nvol > 0xff)
+ nvol = 0xff;
+
+ val |= __SHIFTIN(nvol, HW_AUDIOOUT_DACVOLUME_VOLUME_RIGHT);
+
+ AO_WR(sc, HW_AUDIOOUT_DACVOLUME, val);
+
+ return 0;
+
+ case DIGFILT_OUTPUT_HP_VOLUME:
+ val = AO_RD(sc, HW_AUDIOOUT_HPVOL);
+ val &= ~(HW_AUDIOOUT_HPVOL_VOL_LEFT |
+ HW_AUDIOOUT_HPVOL_VOL_RIGHT);
+
+ /* HP volume field is 7 bits. */
+ nvol = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
+ if (nvol > 0x7f)
+ nvol = 0x7f;
+
+ nvol = ~nvol;
+ val |= __SHIFTIN(nvol, HW_AUDIOOUT_HPVOL_VOL_LEFT);
+
+ nvol = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
+ if (nvol > 0x7f)
+ nvol = 0x7f;
+
+ nvol = ~nvol;
+ val |= __SHIFTIN(nvol, HW_AUDIOOUT_HPVOL_VOL_RIGHT);
+
+ AO_WR(sc, HW_AUDIOOUT_HPVOL, val);
+
+ return 0;
+
+ case DIGFILT_OUTPUT_LINE_VOLUME:
+ return 1;
+
+ case DIGFILT_OUTPUT_DAC_MUTE:
+ if (mc->un.ord)
+ sc->sc_mute |= DIGFILT_MUTE_DAC;
+ else
+ sc->sc_mute &= ~DIGFILT_MUTE_DAC;
+
+ digfilt_ao_apply_mutes(sc);
+
+ return 0;
+
+ case DIGFILT_OUTPUT_HP_MUTE:
+ if (mc->un.ord)
+ sc->sc_mute |= DIGFILT_MUTE_HP;
+ else
+ sc->sc_mute &= ~DIGFILT_MUTE_HP;
+
+ digfilt_ao_apply_mutes(sc);
+
+ return 0;
+
+ case DIGFILT_OUTPUT_LINE_MUTE:
+ if (mc->un.ord)
+ sc->sc_mute |= DIGFILT_MUTE_LINE;
+ else
+ sc->sc_mute &= ~DIGFILT_MUTE_LINE;
+
+ digfilt_ao_apply_mutes(sc);
+
+ return 0;
+ }
+
+ return ENXIO;
+}
+
+static int
+digfilt_get_port(void *priv, mixer_ctrl_t *mc)
+{
+ struct digfilt_softc *sc = priv;
+ uint32_t val;
+ uint8_t nvol;
+
+ switch (mc->dev) {
+ case DIGFILT_OUTPUT_DAC_VOLUME:
+ val = AO_RD(sc, HW_AUDIOOUT_DACVOLUME);
+
+ nvol = __SHIFTOUT(val, HW_AUDIOOUT_DACVOLUME_VOLUME_LEFT);
+ mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = nvol;
+
+ nvol = __SHIFTOUT(val, HW_AUDIOOUT_DACVOLUME_VOLUME_RIGHT);
+ mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = nvol;
+
+ return 0;
+
+ case DIGFILT_OUTPUT_HP_VOLUME:
+ val = AO_RD(sc, HW_AUDIOOUT_HPVOL);
+
+ nvol = __SHIFTOUT(val, HW_AUDIOOUT_HPVOL_VOL_LEFT);
+ mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = ~nvol & 0x7f;
+
+ nvol = __SHIFTOUT(val, HW_AUDIOOUT_HPVOL_VOL_RIGHT);
+ mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = ~nvol & 0x7f;
+
+ return 0;
+
+ case DIGFILT_OUTPUT_LINE_VOLUME:
+ mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 255;
+ mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 255;
+
+ return 0;
+
+ case DIGFILT_OUTPUT_DAC_MUTE:
+ val = AO_RD(sc, HW_AUDIOOUT_DACVOLUME);
+
+ mc->un.ord = (val & (HW_AUDIOOUT_DACVOLUME_MUTE_LEFT |
+ HW_AUDIOOUT_DACVOLUME_MUTE_RIGHT)) ? 1 : 0;
+
+ return 0;
+
+ case DIGFILT_OUTPUT_HP_MUTE:
+ val = AO_RD(sc, HW_AUDIOOUT_HPVOL);
+
+ mc->un.ord = (val & HW_AUDIOOUT_HPVOL_MUTE) ? 1 : 0;
+
+ return 0;
+
+ case DIGFILT_OUTPUT_LINE_MUTE:
+ val = AO_RD(sc, HW_AUDIOOUT_SPEAKERCTRL);
+
+ mc->un.ord = (val & HW_AUDIOOUT_SPEAKERCTRL_MUTE) ? 1 : 0;
+
+ return 0;
+ }
+
+ return ENXIO;
+}
+
+static int
+digfilt_query_devinfo(void *priv, mixer_devinfo_t *di)
+{
+
+ switch (di->index) {
+ case DIGFILT_OUTPUT_CLASS:
+ di->mixer_class = DIGFILT_OUTPUT_CLASS;
+ strcpy(di->label.name, AudioCoutputs);
+ di->type = AUDIO_MIXER_CLASS;
+ di->next = di->prev = AUDIO_MIXER_LAST;
+ return 0;
+
+ case DIGFILT_OUTPUT_DAC_VOLUME:
+ di->mixer_class = DIGFILT_OUTPUT_CLASS;
+ strcpy(di->label.name, AudioNdac);
+ di->type = AUDIO_MIXER_VALUE;
+ di->prev = AUDIO_MIXER_LAST;
+ di->next = DIGFILT_OUTPUT_DAC_MUTE;
+ di->un.v.num_channels = 2;
+ strcpy(di->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case DIGFILT_OUTPUT_DAC_MUTE:
+ di->mixer_class = DIGFILT_OUTPUT_CLASS;
+ di->type = AUDIO_MIXER_ENUM;
+ di->prev = DIGFILT_OUTPUT_DAC_VOLUME;
+ di->next = AUDIO_MIXER_LAST;
+mute:
+ strlcpy(di->label.name, AudioNmute, sizeof(di->label.name));
+ di->un.e.num_mem = 2;
+ strlcpy(di->un.e.member[0].label.name, AudioNon,
+ sizeof(di->un.e.member[0].label.name));
+ di->un.e.member[0].ord = 1;
+ strlcpy(di->un.e.member[1].label.name, AudioNoff,
+ sizeof(di->un.e.member[1].label.name));
+ di->un.e.member[1].ord = 0;
+ return 0;
+
+ case DIGFILT_OUTPUT_HP_VOLUME:
+ di->mixer_class = DIGFILT_OUTPUT_CLASS;
+ strcpy(di->label.name, AudioNheadphone);
+ di->type = AUDIO_MIXER_VALUE;
+ di->prev = AUDIO_MIXER_LAST;
+ di->next = DIGFILT_OUTPUT_HP_MUTE;
+ di->un.v.num_channels = 2;
+ strcpy(di->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case DIGFILT_OUTPUT_HP_MUTE:
+ di->mixer_class = DIGFILT_OUTPUT_CLASS;
+ di->type = AUDIO_MIXER_ENUM;
+ di->prev = DIGFILT_OUTPUT_HP_VOLUME;
+ di->next = AUDIO_MIXER_LAST;
+ goto mute;
+
+ case DIGFILT_OUTPUT_LINE_VOLUME:
+ di->mixer_class = DIGFILT_OUTPUT_CLASS;
+ strcpy(di->label.name, AudioNline);
+ di->type = AUDIO_MIXER_VALUE;
+ di->prev = AUDIO_MIXER_LAST;
+ di->next = DIGFILT_OUTPUT_LINE_MUTE;
+ di->un.v.num_channels = 2;
+ strcpy(di->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case DIGFILT_OUTPUT_LINE_MUTE:
+ di->mixer_class = DIGFILT_OUTPUT_CLASS;
+ di->type = AUDIO_MIXER_ENUM;
+ di->prev = DIGFILT_OUTPUT_LINE_VOLUME;
+ di->next = AUDIO_MIXER_LAST;
+ goto mute;
+ }
+
+ return ENXIO;
+}
+
+static void *
+digfilt_allocm(void *priv, int direction, size_t size)
+{
+ struct digfilt_softc *sc = priv;
+ int rsegs;
+ int error;
+
+ sc->sc_buffer = NULL;
+
+ /*
+ * AUMODE_PLAY is DMA from memory to device.
+ */
+ if (direction != AUMODE_PLAY)
+ return NULL;
+
+ error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &sc->sc_ds[0], DIGFILT_DMA_NSEGS, &rsegs, BUS_DMA_NOWAIT);
+ if (error) {
+ aprint_error_dev(sc->sc_dev,
+ "bus_dmamem_alloc: %d\n", error);
+ goto out;
+ }
+
+ error = bus_dmamem_map(sc->sc_dmat, sc->sc_ds, DIGFILT_DMA_NSEGS, size, &sc->sc_buffer, BUS_DMA_NOWAIT);
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "bus_dmamem_map: %d\n", error);
+ goto dmamem_free;
+ }
+
+ /* After load sc_dmamp is valid. */
+ error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamp, sc->sc_buffer, size, NULL, BUS_DMA_NOWAIT|BUS_DMA_WRITE);
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "bus_dmamap_load: %d\n", error);
+ goto dmamem_unmap;
+ }
+
+ memset(sc->sc_buffer, 0x00, size);
+
+ return sc->sc_buffer;
+
+dmamem_unmap:
+ bus_dmamem_unmap(sc->sc_dmat, sc->sc_buffer, size);
+dmamem_free:
+ bus_dmamem_free(sc->sc_dmat, sc->sc_ds, DIGFILT_DMA_NSEGS);
+out:
+ return NULL;
+}
+
+static void
+digfilt_freem(void *priv, void *kvap, size_t size)
+{
+ struct digfilt_softc *sc = priv;
+
+ bus_dmamem_unmap(sc->sc_dmat, kvap, size);
+ bus_dmamem_free(sc->sc_dmat, sc->sc_ds, DIGFILT_DMA_NSEGS);
+
+ return;
+}
+
+static size_t
+digfilt_round_buffersize(void *hdl, int direction, size_t bs)
+{
+ int bufsize;
+
+ bufsize = bs & ~(DIGFILT_BLOCKSIZE_MAX-1);
+
+ return bufsize;
+}
+
+static int
+digfilt_get_props(void *sc)
+{
+ return (AUDIO_PROP_PLAYBACK | AUDIO_PROP_INDEPENDENT);
+}
+
+static void
+digfilt_get_locks(void *priv, kmutex_t **intr, kmutex_t **thread)
+{
+ struct digfilt_softc *sc = priv;
+
+ *intr = &sc->sc_intr_lock;
+ *thread = &sc->sc_lock;
+
+ return;
+}
+
+/*
+ * IRQ for DAC error.
+ */
+static int
+dac_error_intr(void *arg)
+{
+ struct digfilt_softc *sc = arg;
+ AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_FIFO_UNDERFLOW_IRQ);
+ return 1;
+}
+
+/*
+ * IRQ from DMA.
+ */
+static int
+dac_dma_intr(void *arg)
+{
+ struct digfilt_softc *sc = arg;
+
+ unsigned int dma_err;
+
+ mutex_enter(&sc->sc_intr_lock);
+
+ dma_err = apbdma_intr_status(sc->sc_dmac, 1);
+
+ if (dma_err) {
+ apbdma_ack_error_intr(sc->sc_dmac, 1);
+ }// else {
+ //apbdma_ack_intr(sc->sc_dmac, 1);
+ //}
+
+ sc->sc_intr(sc->sc_intarg);
+ apbdma_ack_intr(sc->sc_dmac, 1);
+
+ mutex_exit(&sc->sc_intr_lock);
+
+ /* Return 1 to acknowledge IRQ. */
+ return 1;
+}
+
+static void *
+digfilt_ao_alloc_dmachain(void *priv, size_t size)
+{
+ struct digfilt_softc *sc = priv;
+ int rsegs;
+ int error;
+ void *kvap;
+
+ kvap = NULL;
+
+ error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &sc->sc_c_ds[0], DIGFILT_DMA_NSEGS, &rsegs, BUS_DMA_NOWAIT);
+ if (error) {
+ aprint_error_dev(sc->sc_dev,
+ "bus_dmamem_alloc: %d\n", error);
+ goto out;
+ }
+
+ error = bus_dmamem_map(sc->sc_dmat, sc->sc_c_ds, DIGFILT_DMA_NSEGS, size, &kvap, BUS_DMA_NOWAIT);
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "bus_dmamem_map: %d\n", error);
+ goto dmamem_free;
+ }
+
+ /* After load sc_c_dmamp is valid. */
+ error = bus_dmamap_load(sc->sc_dmat, sc->sc_c_dmamp, kvap, size, NULL, BUS_DMA_NOWAIT|BUS_DMA_WRITE);
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "bus_dmamap_load: %d\n", error);
+ goto dmamem_unmap;
+ }
+
+ memset(kvap, 0x00, size);
+
+ return kvap;
+
+dmamem_unmap:
+ bus_dmamem_unmap(sc->sc_dmat, kvap, size);
+dmamem_free:
+ bus_dmamem_free(sc->sc_dmat, sc->sc_c_ds, DIGFILT_DMA_NSEGS);
+out:
+
+ return kvap;
+}
+
+static void
+digfilt_ao_apply_mutes(struct digfilt_softc *sc)
+{
+
+ /* DAC. */
+ if (sc->sc_mute & DIGFILT_MUTE_DAC) {
+ AO_WR(sc, HW_AUDIOOUT_DACVOLUME_SET,
+ HW_AUDIOOUT_DACVOLUME_MUTE_LEFT |
+ HW_AUDIOOUT_DACVOLUME_MUTE_RIGHT
+ );
+
+ } else {
+ AO_WR(sc, HW_AUDIOOUT_DACVOLUME_CLR,
+ HW_AUDIOOUT_DACVOLUME_MUTE_LEFT |
+ HW_AUDIOOUT_DACVOLUME_MUTE_RIGHT
+ );
+ }
+
+ /* HP. */
+ if (sc->sc_mute & DIGFILT_MUTE_HP)
+ AO_WR(sc, HW_AUDIOOUT_HPVOL_SET, HW_AUDIOOUT_HPVOL_MUTE);
+ else
+ AO_WR(sc, HW_AUDIOOUT_HPVOL_CLR, HW_AUDIOOUT_HPVOL_MUTE);
+
+ /* Line. */
+ if (sc->sc_mute & DIGFILT_MUTE_LINE)
+ AO_WR(sc, HW_AUDIOOUT_SPEAKERCTRL_SET,
+ HW_AUDIOOUT_SPEAKERCTRL_MUTE);
+ else
+ AO_WR(sc, HW_AUDIOOUT_SPEAKERCTRL_CLR,
+ HW_AUDIOOUT_SPEAKERCTRL_MUTE);
+
+ return;
+}
+
+/*
+ * Initialize audio system.
+ */
+static void
+digfilt_ao_init(struct digfilt_softc *sc)
+{
+
+ AO_WR(sc, HW_AUDIOOUT_ANACLKCTRL_CLR, HW_AUDIOOUT_ANACLKCTRL_CLKGATE);
+ while ((AO_RD(sc, HW_AUDIOOUT_ANACLKCTRL) &
+ HW_AUDIOOUT_ANACLKCTRL_CLKGATE));
+
+ /* Hold headphones outputs at ground. */
+ AO_WR(sc, HW_AUDIOOUT_ANACTRL_SET, HW_AUDIOOUT_ANACTRL_HP_HOLD_GND);
+
+ /* Remove pulldown resistors on headphone outputs. */
+ rtc_release_gnd(1);
+
+ /* Release pull down */
+ AO_WR(sc, HW_AUDIOOUT_ANACTRL_CLR, HW_AUDIOOUT_ANACTRL_HP_HOLD_GND);
+
+ AO_WR(sc, HW_AUDIOOUT_ANACTRL_SET, HW_AUDIOOUT_ANACTRL_HP_CLASSAB);
+
+ /* Enable Modules. */
+ AO_WR(sc, HW_AUDIOOUT_PWRDN_CLR,
+ HW_AUDIOOUT_PWRDN_RIGHT_ADC |
+ HW_AUDIOOUT_PWRDN_DAC |
+ HW_AUDIOOUT_PWRDN_CAPLESS |
+ HW_AUDIOOUT_PWRDN_HEADPHONE
+ );
+
+ return;
+}
+
+/*
+ * Reset the AUDIOOUT block.
+ *
+ * Inspired by i.MX23 RM "39.3.10 Correct Way to Soft Reset a Block"
+ */
+static void
+digfilt_ao_reset(struct digfilt_softc *sc)
+{
+ unsigned int loop;
+
+ /* Prepare for soft-reset by making sure that SFTRST is not currently
+ * asserted. Also clear CLKGATE so we can wait for its assertion below.
+ */
+ AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_SFTRST);
+
+ /* Wait at least a microsecond for SFTRST to deassert. */
+ loop = 0;
+ while ((AO_RD(sc, HW_AUDIOOUT_CTRL) & HW_AUDIOOUT_CTRL_SFTRST) ||
+ (loop < DIGFILT_SOFT_RST_LOOP))
+ loop++;
+
+ /* Clear CLKGATE so we can wait for its assertion below. */
+ AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_CLKGATE);
+
+ /* Soft-reset the block. */
+ AO_WR(sc, HW_AUDIOOUT_CTRL_SET, HW_AUDIOOUT_CTRL_SFTRST);
+
+ /* Wait until clock is in the gated state. */
+ while (!(AO_RD(sc, HW_AUDIOOUT_CTRL) & HW_AUDIOOUT_CTRL_CLKGATE));
+
+ /* Bring block out of reset. */
+ AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_SFTRST);
+
+ loop = 0;
+ while ((AO_RD(sc, HW_AUDIOOUT_CTRL) & HW_AUDIOOUT_CTRL_SFTRST) ||
+ (loop < DIGFILT_SOFT_RST_LOOP))
+ loop++;
+
+ AO_WR(sc, HW_AUDIOOUT_CTRL_CLR, HW_AUDIOOUT_CTRL_CLKGATE);
+
+ /* Wait until clock is in the NON-gated state. */
+ while (AO_RD(sc, HW_AUDIOOUT_CTRL) & HW_AUDIOOUT_CTRL_CLKGATE);
+
+ return;
+}
+
+static void
+digfilt_ao_set_rate(struct digfilt_softc *sc, int sr)
+{
+ uint32_t val;
+
+
+ val = AO_RD(sc, HW_AUDIOOUT_DACSRR);
+
+
+ val &= ~(HW_AUDIOOUT_DACSRR_BASEMULT | HW_AUDIOOUT_DACSRR_SRC_HOLD |
+ HW_AUDIOOUT_DACSRR_SRC_INT | HW_AUDIOOUT_DACSRR_SRC_FRAC);
+
+ switch(sr) {
+ case 8000:
+ val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
+ __SHIFTIN(0x3, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
+ __SHIFTIN(0x17, HW_AUDIOOUT_DACSRR_SRC_INT) |
+ __SHIFTIN(0x0E00, HW_AUDIOOUT_DACSRR_SRC_FRAC));
+ break;
+ case 11025:
+ val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
+ __SHIFTIN(0x3, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
+ __SHIFTIN(0x11, HW_AUDIOOUT_DACSRR_SRC_INT) |
+ __SHIFTIN(0x0037, HW_AUDIOOUT_DACSRR_SRC_FRAC));
+ break;
+ case 12000:
+ val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
+ __SHIFTIN(0x3, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
+ __SHIFTIN(0x0F, HW_AUDIOOUT_DACSRR_SRC_INT) |
+ __SHIFTIN(0x13FF, HW_AUDIOOUT_DACSRR_SRC_FRAC));
+ break;
+ case 16000:
+ val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
+ __SHIFTIN(0x1, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
+ __SHIFTIN(0x17, HW_AUDIOOUT_DACSRR_SRC_INT) |
+ __SHIFTIN(0x0E00, HW_AUDIOOUT_DACSRR_SRC_FRAC));
+ break;
+ case 22050:
+ val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
+ __SHIFTIN(0x1, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
+ __SHIFTIN(0x11, HW_AUDIOOUT_DACSRR_SRC_INT) |
+ __SHIFTIN(0x0037, HW_AUDIOOUT_DACSRR_SRC_FRAC));
+ break;
+ case 24000:
+ val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
+ __SHIFTIN(0x1, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
+ __SHIFTIN(0x0F, HW_AUDIOOUT_DACSRR_SRC_INT) |
+ __SHIFTIN(0x13FF, HW_AUDIOOUT_DACSRR_SRC_FRAC));
+ break;
+ case 32000:
+ val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
+ __SHIFTIN(0x0, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
+ __SHIFTIN(0x17, HW_AUDIOOUT_DACSRR_SRC_INT) |
+ __SHIFTIN(0x0E00, HW_AUDIOOUT_DACSRR_SRC_FRAC));
+ break;
+ default:
+ aprint_error_dev(sc->sc_dev, "uknown sample rate: %d\n", sr);
+ case 44100:
+ val |= (__SHIFTIN(0x1 ,HW_AUDIOOUT_DACSRR_BASEMULT) |
+ __SHIFTIN(0x0, HW_AUDIOOUT_DACSRR_SRC_HOLD) |
+ __SHIFTIN(0x11, HW_AUDIOOUT_DACSRR_SRC_INT) |
+ __SHIFTIN(0x0037, HW_AUDIOOUT_DACSRR_SRC_FRAC));
+ break;
+ }
+
+ AO_WR(sc, HW_AUDIOOUT_DACSRR, val);
+
+ val = AO_RD(sc, HW_AUDIOOUT_DACSRR);
+
+ return;
+}
+#if 0
+/*
+ * Reset the AUDIOIN block.
+ *
+ * Inspired by i.MX23 RM "39.3.10 Correct Way to Soft Reset a Block"
+ */
+static void
+digfilt_ai_reset(struct digfilt_softc *sc)
+{
+ unsigned int loop;
+
+ /* Prepare for soft-reset by making sure that SFTRST is not currently
+ * asserted. Also clear CLKGATE so we can wait for its assertion below.
+ */
+ AI_WR(sc, HW_AUDIOIN_CTRL_CLR, HW_AUDIOIN_CTRL_SFTRST);
+
+ /* Wait at least a microsecond for SFTRST to deassert. */
+ loop = 0;
+ while ((AI_RD(sc, HW_AUDIOIN_CTRL) & HW_AUDIOIN_CTRL_SFTRST) ||
+ (loop < DIGFILT_SOFT_RST_LOOP))
+ loop++;
+
+ /* Clear CLKGATE so we can wait for its assertion below. */
+ AI_WR(sc, HW_AUDIOIN_CTRL_CLR, HW_AUDIOIN_CTRL_CLKGATE);
+
+ /* Soft-reset the block. */
+ AI_WR(sc, HW_AUDIOIN_CTRL_SET, HW_AUDIOIN_CTRL_SFTRST);
+
+ /* Wait until clock is in the gated state. */
+ while (!(AI_RD(sc, HW_AUDIOIN_CTRL) & HW_AUDIOIN_CTRL_CLKGATE));
+
+ /* Bring block out of reset. */
+ AI_WR(sc, HW_AUDIOIN_CTRL_CLR, HW_AUDIOIN_CTRL_SFTRST);
+
+ loop = 0;
+ while ((AI_RD(sc, HW_AUDIOIN_CTRL) & HW_AUDIOIN_CTRL_SFTRST) ||
+ (loop < DIGFILT_SOFT_RST_LOOP))
+ loop++;
+
+ AI_WR(sc, HW_AUDIOIN_CTRL_CLR, HW_AUDIOIN_CTRL_CLKGATE);
+
+ /* Wait until clock is in the NON-gated state. */
+ while (AI_RD(sc, HW_AUDIOIN_CTRL) & HW_AUDIOIN_CTRL_CLKGATE);
+
+ return;
+}
+#endif
Index: sys/arch/arm/imx/imx23_digfiltreg.h
===================================================================
RCS file: sys/arch/arm/imx/imx23_digfiltreg.h
diff -N sys/arch/arm/imx/imx23_digfiltreg.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/arch/arm/imx/imx23_digfiltreg.h 27 Dec 2014 17:13:46 -0000
@@ -0,0 +1,382 @@
+/* $Id$ */
+
+/*
+ * 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.
+ */
+
+#ifndef _ARM_IMX_IMX23_AUDIOOUTREG_H_
+#define _ARM_IMX_IMX23_AUDIOOUTREG_H_
+
+#include <sys/cdefs.h>
+
+#define HW_DIGFILT_BASE 0x80048000
+#define HW_DIGFILT_SIZE 0x8000 /* 32 kB */
+
+#define HW_AUDIOOUT_BASE 0x80048000
+#define HW_AUDIOOUT_SIZE 0x2000 /* 8 kB */
+
+#define HW_AUDIOIN_BASE 0x8004C000
+#define HW_AUDIOIN_SIZE 0x2000 /* 8 kB */
+
+/*
+ * AUDIOIN Control Register.
+ */
+#define HW_AUDIOIN_CTRL 0x000
+#define HW_AUDIOIN_CTRL_SET 0x004
+#define HW_AUDIOIN_CTRL_CLR 0x008
+#define HW_AUDIOIN_CTRL_TOG 0x00C
+
+#define HW_AUDIOIN_CTRL_SFTRST __BIT(31)
+#define HW_AUDIOIN_CTRL_CLKGATE __BIT(30)
+#define HW_AUDIOIN_CTRL_RSRVD3 __BITS(29, 21)
+#define HW_AUDIOIN_CTRL_DMAWAIT_COUNT __BITS(20, 16)
+#define HW_AUDIOIN_CTRL_RSRVD1 __BITS(15, 11)
+#define HW_AUDIOIN_CTRL_LR_SWAP __BIT(10)
+#define HW_AUDIOIN_CTRL_EDGE_SYNC __BIT(9)
+#define HW_AUDIOIN_CTRL_INVERT_1BIT __BIT(8)
+#define HW_AUDIOIN_CTRL_OFFSET_ENABLE __BIT(7)
+#define HW_AUDIOIN_CTRL_HPF_ENABLE __BIT(6)
+#define HW_AUDIOIN_CTRL_WORD_LENGTH __BIT(5)
+#define HW_AUDIOIN_CTRL_LOOPBACK __BIT(4)
+#define HW_AUDIOIN_CTRL_FIFO_UNDERFLOW_IRQ __BIT(3)
+#define HW_AUDIOIN_CTRL_FIFO_OVERFLOW_IRQ __BIT(2)
+#define HW_AUDIOIN_CTRL_FIFO_ERROR_IRQ_EN __BIT(1)
+#define HW_AUDIOIN_CTRL_RUN __BIT(0)
+
+/*
+ * AUDIOOUT Control Register.
+ */
+#define HW_AUDIOOUT_CTRL 0x000
+#define HW_AUDIOOUT_CTRL_SET 0x004
+#define HW_AUDIOOUT_CTRL_CLR 0x008
+
+#define HW_AUDIOOUT_CTRL_SFTRST __BIT(31)
+#define HW_AUDIOOUT_CTRL_CLKGATE __BIT(30)
+#define HW_AUDIOOUT_CTRL_RSRVD4 __BITS(29, 21)
+#define HW_AUDIOOUT_CTRL_DMAWAIT_COUNT __BITS(20, 16)
+#define HW_AUDIOOUT_CTRL_RSRVD3 __BIT(15)
+#define HW_AUDIOOUT_CTRL_LR_SWAP __BIT(14)
+#define HW_AUDIOOUT_CTRL_EDGE_SYNC __BIT(13)
+#define HW_AUDIOOUT_CTRL_INVERT_1BIT __BIT(12)
+#define HW_AUDIOOUT_CTRL_RSRVD2 __BITS(11, 10)
+#define HW_AUDIOOUT_CTRL_SS3D_EFFECT __BITS(9, 8)
+#define HW_AUDIOOUT_CTRL_RSRVD1 __BIT(7)
+#define HW_AUDIOOUT_CTRL_WORD_LENGTH __BIT(6)
+#define HW_AUDIOOUT_CTRL_DAC_ZERO_ENABLE __BIT(5)
+#define HW_AUDIOOUT_CTRL_LOOPBACK __BIT(4)
+#define HW_AUDIOOUT_CTRL_FIFO_UNDERFLOW_IRQ __BIT(3)
+#define HW_AUDIOOUT_CTRL_FIFO_OVERFLOW_IRQ __BIT(2)
+#define HW_AUDIOOUT_CTRL_FIFO_ERROR_IRQ_EN __BIT(1)
+#define HW_AUDIOOUT_CTRL_RUN __BIT(0)
+
+/*
+ * AUDIOOUT Status Register.
+ */
+#define HW_AUDIOOUT_STAT 0x010
+#define HW_AUDIOOUT_STAT_SET 0x014
+#define HW_AUDIOOUT_STAT_CLR 0x018
+#define HW_AUDIOOUT_STAT_TOG 0x01C
+
+#define HW_AUDIOOUT_STAT_DAC_PRESENT __BIT(31)
+#define HW_AUDIOOUT_STAT_RSRVD1 __BITS(30, 0)
+
+/*
+ * AUDIOOUT Sample Rate Register.
+ */
+#define HW_AUDIOOUT_DACSRR 0x020
+#define HW_AUDIOOUT_DACSRR_SET 0x024
+#define HW_AUDIOOUT_DACSRR_CLR 0x028
+#define HW_AUDIOOUT_DACSRR_TOG 0x02C
+
+#define HW_AUDIOOUT_DACSRR_OSR __BIT(31)
+#define HW_AUDIOOUT_DACSRR_BASEMULT __BITS(30, 28)
+#define HW_AUDIOOUT_DACSRR_RSRVD2 __BIT(27)
+#define HW_AUDIOOUT_DACSRR_SRC_HOLD __BITS(26, 24)
+#define HW_AUDIOOUT_DACSRR_RSRVD1 __BITS(23, 21)
+#define HW_AUDIOOUT_DACSRR_SRC_INT __BITS(20, 16)
+#define HW_AUDIOOUT_DACSRR_RSRVD0 __BITS(15, 13)
+#define HW_AUDIOOUT_DACSRR_SRC_FRAC __BITS(12, 0)
+
+/*
+ * AUDIOOUT Volume Register.
+ */
+#define HW_AUDIOOUT_DACVOLUME 0x030
+#define HW_AUDIOOUT_DACVOLUME_SET 0x034
+#define HW_AUDIOOUT_DACVOLUME_CLR 0x038
+#define HW_AUDIOOUT_DACVOLUME_TOG 0x03C
+
+#define HW_AUDIOOUT_DACVOLUME_RSRVD4 __BITS(31, 29)
+#define HW_AUDIOOUT_DACVOLUME_VOLUME_UPDATE_LEFT __BIT(28)
+#define HW_AUDIOOUT_DACVOLUME_RSRVD3 __BITS(27, 26)
+#define HW_AUDIOOUT_DACVOLUME_EN_ZCD __BIT(25)
+#define HW_AUDIOOUT_DACVOLUME_MUTE_LEFT __BIT(24)
+#define HW_AUDIOOUT_DACVOLUME_VOLUME_LEFT __BITS(23, 16)
+#define HW_AUDIOOUT_DACVOLUME_RSRVD2 __BITS(15, 13)
+#define HW_AUDIOOUT_DACVOLUME_VOLUME_UPDATE_RIGHT __BIT(12)
+#define HW_AUDIOOUT_DACVOLUME_RSRVD1 __BITS(11, 9)
+#define HW_AUDIOOUT_DACVOLUME_MUTE_RIGHT __BIT(8)
+#define HW_AUDIOOUT_DACVOLUME_VOLUME_RIGHT __BITS(7, 0)
+
+/*
+ * AUDIOOUT Debug Register.
+ */
+#define HW_AUDIOOUT_DACDEBUG 0x040
+#define HW_AUDIOOUT_DACDEBUG_SET 0x044
+#define HW_AUDIOOUT_DACDEBUG_CLR 0x048
+#define HW_AUDIOOUT_DACDEBUG_TOG 0x04C
+
+#define HW_AUDIOOUT_DACDEBUG_ENABLE_DACDMA __BIT(31)
+#define HW_AUDIOOUT_DACDEBUG_RSRVD2 __BITS(30, 12)
+#define HW_AUDIOOUT_DACDEBUG_RAM_SS __BITS(11, 8)
+#define HW_AUDIOOUT_DACDEBUG_RSRVD1 __BITS(7, 6)
+#define HW_AUDIOOUT_DACDEBUG_SET_INTERRUPT1_CLK_CROSS __BIT(5)
+#define HW_AUDIOOUT_DACDEBUG_SET_INTERRUPT0_CLK_CROSS __BIT(4)
+#define HW_AUDIOOUT_DACDEBUG_SET_INTERRUPT1_HAND_SHAKE __BIT(3)
+#define HW_AUDIOOUT_DACDEBUG_SET_INTERRUPT0_HAND_SHAKE __BIT(2)
+#define HW_AUDIOOUT_DACDEBUG_DMA_PREQ __BIT(1)
+#define HW_AUDIOOUT_DACDEBUG_FIFO_STATUS __BIT(0)
+
+/*
+ * Headphone Volume and Select Control Register.
+ */
+#define HW_AUDIOOUT_HPVOL 0x050
+#define HW_AUDIOOUT_HPVOL_SET 0x054
+#define HW_AUDIOOUT_HPVOL_CLR 0x058
+#define HW_AUDIOOUT_HPVOL_TOG 0x05C
+
+#define HW_AUDIOOUT_HPVOL_RSRVD5 __BITS(31, 29)
+#define HW_AUDIOOUT_HPVOL_VOLUME_UPDATE_PENDING __BIT(28)
+#define HW_AUDIOOUT_HPVOL_RSRVD4 __BITS(27, 26)
+#define HW_AUDIOOUT_HPVOL_EN_MSTR_ZCD __BIT(25)
+#define HW_AUDIOOUT_HPVOL_MUTE __BIT(24)
+#define HW_AUDIOOUT_HPVOL_RSRVD3 __BITS(23, 17)
+#define HW_AUDIOOUT_HPVOL_SELECT __BIT(16)
+#define HW_AUDIOOUT_HPVOL_RSRVD2 __BIT(15)
+#define HW_AUDIOOUT_HPVOL_VOL_LEFT __BITS(14, 8)
+#define HW_AUDIOOUT_HPVOL_RSRVD1 __BIT(7)
+#define HW_AUDIOOUT_HPVOL_VOL_RIGHT __BITS(6, 0)
+
+/*
+ * Reserved Register.
+ */
+#define HW_AUDIOOUT_RESERVED 0x060
+#define HW_AUDIOOUT_RESERVED_SET 0x064
+#define HW_AUDIOOUT_RESERVED_CLR 0x068
+#define HW_AUDIOOUT_RESERVED_TOG 0x06C
+
+#define HW_AUDIOOUT_RESERVED_RSRVD1 __BITS(31, 0)
+
+/*
+ * Audio Power-Down Control Register.
+ */
+#define HW_AUDIOOUT_PWRDN 0x070
+#define HW_AUDIOOUT_PWRDN_SET 0x074
+#define HW_AUDIOOUT_PWRDN_CLR 0x078
+#define HW_AUDIOOUT_PWRDN_TOG 0x07C
+
+#define HW_AUDIOOUT_PWRDN_RSRVD7 __BITS(31, 25)
+#define HW_AUDIOOUT_PWRDN_SPEAKER __BIT(24)
+#define HW_AUDIOOUT_PWRDN_RSRVD6 __BITS(23, 21)
+#define HW_AUDIOOUT_PWRDN_SELFBIAS __BIT(20)
+#define HW_AUDIOOUT_PWRDN_RSRVD5 __BITS(19, 17)
+#define HW_AUDIOOUT_PWRDN_RIGHT_ADC __BIT(16)
+#define HW_AUDIOOUT_PWRDN_RSRVD4 __BITS(15, 13)
+#define HW_AUDIOOUT_PWRDN_DAC __BIT(12)
+#define HW_AUDIOOUT_PWRDN_RSRVD3 __BITS(11, 9)
+#define HW_AUDIOOUT_PWRDN_ADC __BIT(8)
+#define HW_AUDIOOUT_PWRDN_RSRVD2 __BITS(7, 5)
+#define HW_AUDIOOUT_PWRDN_CAPLESS __BIT(4)
+#define HW_AUDIOOUT_PWRDN_RSRVD1 __BITS(3, 1)
+#define HW_AUDIOOUT_PWRDN_HEADPHONE __BIT(0)
+
+/*
+ * AUDIOOUT Reference Control Register.
+ */
+#define HW_AUDIOOUT_REFCTRL 0x080
+#define HW_AUDIOOUT_REFCTRL_SET 0x084
+#define HW_AUDIOOUT_REFCTRL_CLR 0x088
+#define HW_AUDIOOUT_REFCTRL_TOG 0x08C
+
+#define HW_AUDIOOUT_REFCTRL_RSRVD4 __BITS(31, 27)
+#define HW_AUDIOOUT_REFCTRL_FASTSETTLING __BIT(26)
+#define HW_AUDIOOUT_REFCTRL_RAISE_REF __BIT(25)
+#define HW_AUDIOOUT_REFCTRL_XTAL_BGR_BIAS __BIT(24)
+#define HW_AUDIOOUT_REFCTRL_RSRVD3 __BIT(23)
+#define HW_AUDIOOUT_REFCTRL_VBG_ADJ __BITS(22, 20)
+#define HW_AUDIOOUT_REFCTRL_LOW_PWR __BIT(19)
+#define HW_AUDIOOUT_REFCTRL_LW_REF __BIT(18)
+#define HW_AUDIOOUT_REFCTRL_BIAS_CTRL __BITS(17, 16)
+#define HW_AUDIOOUT_REFCTRL_RSRVD2 __BIT(15)
+#define HW_AUDIOOUT_REFCTRL_VDDXTAL_TO_VDDD __BIT(14)
+#define HW_AUDIOOUT_REFCTRL_ADJ_ADC __BIT(13)
+#define HW_AUDIOOUT_REFCTRL_ADJ_VAG __BIT(12)
+#define HW_AUDIOOUT_REFCTRL_ADC_REFVAL __BITS(11, 8)
+#define HW_AUDIOOUT_REFCTRL_VAG_VAL __BITS(7, 4)
+#define HW_AUDIOOUT_REFCTRL_RSRVD1 __BIT(3)
+#define HW_AUDIOOUT_REFCTRL_DAC_ADJ __BIT(2, 0)
+
+/*
+ * Miscellaneous Audio Controls Register.
+ */
+#define HW_AUDIOOUT_ANACTRL 0x090
+#define HW_AUDIOOUT_ANACTRL_SET 0x094
+#define HW_AUDIOOUT_ANACTRL_CLR 0x098
+#define HW_AUDIOOUT_ANACTRL_TOG 0x09C
+
+#define HW_AUDIOOUT_ANACTRL_RSRVD8 __BITS(31, 29)
+#define HW_AUDIOOUT_ANACTRL_SHORT_CM_STS __BIT(28)
+#define HW_AUDIOOUT_ANACTRL_RSRVD7 __BITS(27, 25)
+#define HW_AUDIOOUT_ANACTRL_SHORT_LR_STS __BIT(24)
+#define HW_AUDIOOUT_ANACTRL_RSRVD6 __BITS(23, 22)
+#define HW_AUDIOOUT_ANACTRL_SHORTMODE_CM __BIT(21, 20)
+#define HW_AUDIOOUT_ANACTRL_RSRVD5 __BIT(19)
+#define HW_AUDIOOUT_ANACTRL_SHORTMODE_LR __BITS(18, 17)
+#define HW_AUDIOOUT_ANACTRL_RSRVD4 __BITS(16, 15)
+#define HW_AUDIOOUT_ANACTRL_SHORT_LVLADJL __BITS(14, 12)
+#define HW_AUDIOOUT_ANACTRL_RSRVD3 __BIT(11)
+#define HW_AUDIOOUT_ANACTRL_SHORT_LVLADJR __BITS(10, 8)
+#define HW_AUDIOOUT_ANACTRL_RSRVD2 __BITS(7, 6)
+#define HW_AUDIOOUT_ANACTRL_HP_HOLD_GND __BIT(5)
+#define HW_AUDIOOUT_ANACTRL_HP_CLASSAB __BIT(4)
+#define HW_AUDIOOUT_ANACTRL_RSRVD1 __BITS(3, 0)
+
+/*
+ * Miscellaneous Test Audio Controls Register.
+ */
+#define HW_AUDIOOUT_TEST 0x0a0
+#define HW_AUDIOOUT_TEST_SET 0x0a4
+#define HW_AUDIOOUT_TEST_CLR 0x0a8
+#define HW_AUDIOOUT_TEST_TOG 0x0aC
+
+#define HW_AUDIOOUT_TEST_RSRVD4 __BIT(31)
+#define HW_AUDIOOUT_TEST_HP_ANTIPOP __BITS(30, 28)
+#define HW_AUDIOOUT_TEST_RSRVD3 __BIT(27)
+#define HW_AUDIOOUT_TEST_TM_ADCIN_TOHP __BIT(26)
+#define HW_AUDIOOUT_TEST_TM_LOOP __BIT(25)
+#define HW_AUDIOOUT_TEST_TM_HPCOMMON __BIT(24)
+#define HW_AUDIOOUT_TEST_HP_I1_ADJ __BITS(23, 22)
+#define HW_AUDIOOUT_TEST_HP_IALL_ADJ __BITS(21, 20)
+#define HW_AUDIOOUT_TEST_RSRVD2 __BITS(19, 14)
+#define HW_AUDIOOUT_TEST_VAG_CLASSA __BIT(13)
+#define HW_AUDIOOUT_TEST_VAG_DOUBLE_I __BIT(12)
+#define HW_AUDIOOUT_TEST_RSRVD1 __BITS(11, 4)
+#define HW_AUDIOOUT_TEST_ADCTODAC_LOOP __BIT(3)
+#define HW_AUDIOOUT_TEST_DAC_CLASSA __BIT(2)
+#define HW_AUDIOOUT_TEST_DAC_DOUBLE_I __BIT(1)
+#define HW_AUDIOOUT_TEST_DAC_DIS_RTZ __BIT(0)
+
+/*
+ * BIST Control and Status Register.
+ */
+#define HW_AUDIOOUT_BISTCTRL 0x0b0
+#define HW_AUDIOOUT_BISTCTRL_SET 0x0b4
+#define HW_AUDIOOUT_BISTCTRL_CLR 0x0b8
+#define HW_AUDIOOUT_BISTCTRL_TOG 0x0bC
+
+#define HW_AUDIOOUT_BISTCTRL_RSVD0 __BITS(31, 4)
+#define HW_AUDIOOUT_BISTCTRL_FAIL __BIT(3)
+#define HW_AUDIOOUT_BISTCTRL_PASS __BIT(2)
+#define HW_AUDIOOUT_BISTCTRL_DONE __BIT(1)
+#define HW_AUDIOOUT_BISTCTRL_START __BIT(0)
+
+/*
+ * Hardware BIST Status 0 Register.
+ */
+#define HW_AUDIOOUT_BISTSTAT0 0x0c0
+#define HW_AUDIOOUT_BISTSTAT0_SET 0x0c4
+#define HW_AUDIOOUT_BISTSTAT0_CLR 0x0c8
+#define HW_AUDIOOUT_BISTSTAT0_TOG 0x0cC
+
+#define HW_AUDIOOUT_BISTSTAT0_RSVD0 __BITS(31, 24)
+#define HW_AUDIOOUT_BISTSTAT0_DATA __BITS(23, 0)
+
+/*
+ * Hardware AUDIOUT BIST Status 1 Register.
+ */
+#define HW_AUDIOOUT_BISTSTAT1 0x0d0
+#define HW_AUDIOOUT_BISTSTAT1_SET 0x0d4
+#define HW_AUDIOOUT_BISTSTAT1_CLR 0x0d8
+#define HW_AUDIOOUT_BISTSTAT1_TOG 0x0dC
+
+#define HW_AUDIOOUT_BISTSTAT1_RSVD1 __BITS(31, 29)
+#define HW_AUDIOOUT_BISTSTAT1_STATE __BITS(28, 24)
+#define HW_AUDIOOUT_BISTSTAT1_RSVD0 __BITS(23, 8)
+#define HW_AUDIOOUT_BISTSTAT1_ADDR __BITS(7, 0)
+
+/*
+ * Analog Clock Control Register.
+ */
+#define HW_AUDIOOUT_ANACLKCTRL 0x0e0
+#define HW_AUDIOOUT_ANACLKCTRL_SET 0x0e4
+#define HW_AUDIOOUT_ANACLKCTRL_CLR 0x0e8
+#define HW_AUDIOOUT_ANACLKCTRL_TOG 0x0eC
+
+#define HW_AUDIOOUT_ANACLKCTRL_CLKGATE __BIT(31)
+#define HW_AUDIOOUT_ANACLKCTRL_RSRVD3 __BITS(30, 5)
+#define HW_AUDIOOUT_ANACLKCTRL_INVERT_DACCLK __BIT(4)
+#define HW_AUDIOOUT_ANACLKCTRL_RSRVD2 __BIT(3)
+#define HW_AUDIOOUT_ANACLKCTRL_DACDIV __BITS(2, 0)
+
+/*
+ * AUDIOOUT Write Data Register.
+ */
+#define HW_AUDIOOUT_DATA 0x0f0
+#define HW_AUDIOOUT_DATA_SET 0x0f4
+#define HW_AUDIOOUT_DATA_CLR 0x0f8
+#define HW_AUDIOOUT_DATA_TOG 0x0fC
+
+#define HW_AUDIOOUT_DATA_HIGH __BITS(31, 16)
+#define HW_AUDIOOUT_DATA_LOW __BITS(15, 0)
+
+/*
+ * AUDIOOUT Speaker Control Register.
+ */
+#define HW_AUDIOOUT_SPEAKERCTRL 0x100
+#define HW_AUDIOOUT_SPEAKERCTRL_SET 0x104
+#define HW_AUDIOOUT_SPEAKERCTRL_CLR 0x108
+#define HW_AUDIOOUT_SPEAKERCTRL_TOG 0x10C
+
+#define HW_AUDIOOUT_SPEAKERCTRL_RSRVD2 __BITS(31, 25)
+#define HW_AUDIOOUT_SPEAKERCTRL_MUTE __BIT(24)
+#define HW_AUDIOOUT_SPEAKERCTRL_I1_ADJ __BITS(23, 22)
+#define HW_AUDIOOUT_SPEAKERCTRL_IALL_ADJ __BITS(21, 20)
+#define HW_AUDIOOUT_SPEAKERCTRL_RSRVD1 __BITS(19, 16)
+#define HW_AUDIOOUT_SPEAKERCTRL_POSDRIVER __BITS(15, 14)
+#define HW_AUDIOOUT_SPEAKERCTRL_NEGDRIVER __BITS(13, 12)
+#define HW_AUDIOOUT_SPEAKERCTRL_RSRVD0 __BITS(11, 0)
+
+/*
+ * AUDIOOUT Version Register.
+ */
+#define HW_AUDIOOUT_VERSION 0x200
+
+#define HW_AUDIOOUT_VERSION_MAJOR __BITS(31, 24)
+#define HW_AUDIOOUT_VERSION_MINOR __BITS(23, 16)
+#define HW_AUDIOOUT_VERSION_STEP __BITS(15, 0)
+
+#endif /* !_ARM_IMX_IMX23_AUDIOOUTREG_H_ */
Index: sys/arch/arm/imx/imx23_digfiltvar.h
===================================================================
RCS file: sys/arch/arm/imx/imx23_digfiltvar.h
diff -N sys/arch/arm/imx/imx23_digfiltvar.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/arch/arm/imx/imx23_digfiltvar.h 27 Dec 2014 17:13:46 -0000
@@ -0,0 +1,35 @@
+/* $Id$ */
+
+/*
+ * 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.
+ */
+
+#ifndef _ARM_IMX_IMX23_AUDIOOUTVAR_H_
+#define _ARM_IMX_IMX23_AUDIOOUTVAR_H_
+
+#endif /* !_ARM_IMX_IMX23_AUDIOOUTVAR_H_ */
Index: sys/arch/arm/imx/imx23_rtc.c
===================================================================
RCS file: sys/arch/arm/imx/imx23_rtc.c
diff -N sys/arch/arm/imx/imx23_rtc.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/arch/arm/imx/imx23_rtc.c 27 Dec 2014 17:13:46 -0000
@@ -0,0 +1,199 @@
+/* $Id$ */
+
+/*
+* 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/types.h>
+#include <sys/bus.h>
+#include <sys/cdefs.h>
+#include <sys/device.h>
+#include <sys/errno.h>
+
+#include <arm/imx/imx23_rtcreg.h>
+#include <arm/imx/imx23_rtcvar.h>
+#include <arm/imx/imx23var.h>
+
+typedef struct rtc_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_hdl;
+} *rtc_softc_t;
+
+static int rtc_match(device_t, cfdata_t, void *);
+static void rtc_attach(device_t, device_t, void *);
+static int rtc_activate(device_t, enum devact);
+
+static void rtc_init(struct rtc_softc *);
+static void rtc_reset(struct rtc_softc *);
+
+static rtc_softc_t _sc = NULL;
+
+CFATTACH_DECL3_NEW(rtc,
+ sizeof(struct rtc_softc),
+ rtc_match,
+ rtc_attach,
+ NULL,
+ rtc_activate,
+ NULL,
+ NULL,
+ 0
+);
+
+#define RTC_RD(sc, reg) \
+ bus_space_read_4(sc->sc_iot, sc->sc_hdl, (reg))
+#define RTC_WR(sc, reg, val) \
+ bus_space_write_4(sc->sc_iot, sc->sc_hdl, (reg), (val))
+
+#define RTC_SOFT_RST_LOOP 455 /* At least 1 us ... */
+
+static int
+rtc_match(device_t parent, cfdata_t match, void *aux)
+{
+ struct apb_attach_args *aa = aux;
+
+ if ((aa->aa_addr == HW_RTC_BASE) &&
+ (aa->aa_size == HW_RTC_BASE_SIZE))
+ return 1;
+
+ return 0;
+}
+
+static void
+rtc_attach(device_t parent, device_t self, void *aux)
+{
+ struct rtc_softc *sc = device_private(self);
+ struct apb_attach_args *aa = aux;
+ static int rtc_attached = 0;
+
+ sc->sc_dev = self;
+ sc->sc_iot = aa->aa_iot;
+
+ if (rtc_attached) {
+ aprint_error_dev(sc->sc_dev, "rtc is already attached\n");
+ return;
+ }
+
+ if (bus_space_map(sc->sc_iot, aa->aa_addr, aa->aa_size, 0,
+ &sc->sc_hdl))
+ {
+ aprint_error_dev(sc->sc_dev, "Unable to map bus space\n");
+ return;
+ }
+
+
+ rtc_init(sc);
+ rtc_reset(sc);
+
+ aprint_normal("\n");
+
+ rtc_attached = 1;
+
+ return;
+}
+
+static int
+rtc_activate(device_t self, enum devact act)
+{
+
+ return EOPNOTSUPP;
+}
+
+static void
+rtc_init(struct rtc_softc *sc)
+{
+ _sc = sc;
+ return;
+}
+
+/*
+ * Remove pulldown resistors on the headphone outputs.
+ */
+void
+rtc_release_gnd(int val)
+{
+ struct rtc_softc *sc = _sc;
+
+ if (sc == NULL) {
+ aprint_error("rtc is not initalized");
+ return;
+ }
+ if(val)
+ RTC_WR(sc, HW_RTC_PERSISTENT0_SET, (1<<19));
+ else
+ RTC_WR(sc, HW_RTC_PERSISTENT0_CLR, (1<<19));
+
+ return;
+}
+
+/*
+ * Reset the SSP block.
+ *
+ * Inspired by i.MX23 RM "39.3.10 Correct Way to Soft Reset a Block"
+ */
+static void
+rtc_reset(struct rtc_softc *sc)
+{
+ unsigned int loop;
+
+ /* Prepare for soft-reset by making sure that SFTRST is not currently
+ * asserted. Also clear CLKGATE so we can wait for its assertion below.
+ */
+ RTC_WR(sc, HW_RTC_CTRL_CLR, HW_RTC_CTRL_SFTRST);
+
+ /* Wait at least a microsecond for SFTRST to deassert. */
+ loop = 0;
+ while ((RTC_RD(sc, HW_RTC_CTRL) & HW_RTC_CTRL_SFTRST) ||
+ (loop < RTC_SOFT_RST_LOOP))
+ loop++;
+
+ /* Clear CLKGATE so we can wait for its assertion below. */
+ RTC_WR(sc, HW_RTC_CTRL_CLR, HW_RTC_CTRL_CLKGATE);
+
+ /* Soft-reset the block. */
+ RTC_WR(sc, HW_RTC_CTRL_SET, HW_RTC_CTRL_SFTRST);
+
+ /* Wait until clock is in the gated state. */
+ while (!(RTC_RD(sc, HW_RTC_CTRL) & HW_RTC_CTRL_CLKGATE));
+
+ /* Bring block out of reset. */
+ RTC_WR(sc, HW_RTC_CTRL_CLR, HW_RTC_CTRL_SFTRST);
+
+ loop = 0;
+ while ((RTC_RD(sc, HW_RTC_CTRL) & HW_RTC_CTRL_SFTRST) ||
+ (loop < RTC_SOFT_RST_LOOP))
+ loop++;
+
+ RTC_WR(sc, HW_RTC_CTRL_CLR, HW_RTC_CTRL_CLKGATE);
+
+ /* Wait until clock is in the NON-gated state. */
+ while (RTC_RD(sc, HW_RTC_CTRL) & HW_RTC_CTRL_CLKGATE);
+
+ return;
+}
Index: sys/arch/arm/imx/imx23_rtcreg.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/imx/imx23_rtcreg.h,v
retrieving revision 1.1
diff -u -r1.1 imx23_rtcreg.h
--- sys/arch/arm/imx/imx23_rtcreg.h 20 Nov 2012 19:06:13 -0000 1.1
+++ sys/arch/arm/imx/imx23_rtcreg.h 27 Dec 2014 17:13:46 -0000
@@ -35,6 +35,7 @@
#include <sys/cdefs.h>
#define HW_RTC_BASE 0x8005C000
+#define HW_RTC_BASE_SIZE 0x2000
/*
* Real-Time Clock Control Register.
Index: sys/arch/arm/imx/imx23_rtcvar.h
===================================================================
RCS file: sys/arch/arm/imx/imx23_rtcvar.h
diff -N sys/arch/arm/imx/imx23_rtcvar.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/arch/arm/imx/imx23_rtcvar.h 27 Dec 2014 17:13:46 -0000
@@ -0,0 +1,37 @@
+/* $Id$ */
+
+/*
+ * 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.
+ */
+
+#ifndef _ARM_IMX_IMX23_RTCVAR_H_
+#define _ARM_IMX_IMX23_RTCVAR_H_
+
+void rtc_release_gnd(int);
+
+#endif /* !_ARM_IMX_IMX23_RTCVAR_H_ */
Index: sys/arch/evbarm/conf/IMX23_OLINUXINO
===================================================================
RCS file: /cvsroot/src/sys/arch/evbarm/conf/IMX23_OLINUXINO,v
retrieving revision 1.10
diff -u -r1.10 IMX23_OLINUXINO
--- sys/arch/evbarm/conf/IMX23_OLINUXINO 11 Oct 2014 11:55:07 -0000 1.10
+++ sys/arch/evbarm/conf/IMX23_OLINUXINO 27 Dec 2014 17:13:47 -0000
@@ -66,6 +66,13 @@
# Clock control
clkctrl0 at apbx? addr 0x80040000 size 0x2000 irq -1
+# RTC
+rtc0 at apbx? addr 0x8005C000 size 0x2000 irq -1
+
+# Digital filter: Audio I/O
+digfilt0 at apbx? addr 0x80048000 size 0x8000 irq -1
+audio0 at digfilt0
+
# USB host
ehci0 at imxusbc0 unit 0 irq 11
# USB OTG
Index: sys/arch/evbarm/conf/files.imx23_olinuxino
===================================================================
RCS file: /cvsroot/src/sys/arch/evbarm/conf/files.imx23_olinuxino,v
retrieving revision 1.2
diff -u -r1.2 files.imx23_olinuxino
--- sys/arch/evbarm/conf/files.imx23_olinuxino 7 Oct 2013 17:36:40 -0000 1.2
+++ sys/arch/evbarm/conf/files.imx23_olinuxino 27 Dec 2014 17:13:47 -0000
@@ -6,6 +6,9 @@
# Pull in SoC support
include "arch/arm/imx/files.imx23"
+# Kernel boot arguments
+defparam opt_machdep.h BOOT_ARGS
+
file arch/evbarm/imx23_olinuxino/imx23_olinuxino_machdep.c
file arch/arm/arm32/arm32_kvminit.c
file arch/arm/arm32/arm32_boot.c
Index: sys/arch/evbarm/imx23_olinuxino/imx23_olinuxino_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbarm/imx23_olinuxino/imx23_olinuxino_machdep.c,v
retrieving revision 1.4
diff -u -r1.4 imx23_olinuxino_machdep.c
--- sys/arch/evbarm/imx23_olinuxino/imx23_olinuxino_machdep.c 29 Oct 2014 11:21:51 -0000 1.4
+++ sys/arch/evbarm/imx23_olinuxino/imx23_olinuxino_machdep.c 27 Dec 2014 17:13:47 -0000
@@ -65,6 +65,7 @@
#endif
#include "opt_evbarm_boardtype.h"
+#include "opt_machdep.h"
#define KERNEL_VM_BASE (KERNEL_BASE + 0x8000000)
#define KERNEL_VM_SIZE 0x20000000
@@ -161,6 +162,9 @@
/* Copy boot arguments passed from bootimx23. */
boot_args = (char *)KERN_PHYSTOV(BOOTIMX23_ARGS);
memcpy(kernel_boot_args, boot_args, MAX_BOOT_STRING);
+#ifdef BOOT_ARGS
+ strcpy(kernel_boot_args, BOOT_ARGS);
+#endif
boot_args = kernel_boot_args;
#ifdef VERBOSE_INIT_ARM
printf("boot_args @ %lx: '%s'\n", KERN_PHYSTOV(BOOTIMX23_ARGS),
Home |
Main Index |
Thread Index |
Old Index