From 4b3fae2c2d53d27db72bcd5eed8da0ef28f0a779 Mon Sep 17 00:00:00 2001 From: Ruslan Bukin Date: Thu, 8 Dec 2016 16:28:34 +0000 Subject: [PATCH] Add jz4780 internal codec initialization driver. Sponsored by: DARPA, AFRL --- sys/mips/ingenic/jz4780_codec.c | 242 +++++++++++++++++++++++++++++++ sys/mips/ingenic/jz4780_codec.h | 101 +++++++++++++ sys/mips/ingenic/jz4780_common.h | 36 +++++ 3 files changed, 379 insertions(+) create mode 100644 sys/mips/ingenic/jz4780_codec.c create mode 100644 sys/mips/ingenic/jz4780_codec.h create mode 100644 sys/mips/ingenic/jz4780_common.h diff --git a/sys/mips/ingenic/jz4780_codec.c b/sys/mips/ingenic/jz4780_codec.c new file mode 100644 index 000000000000..132d45fafd59 --- /dev/null +++ b/sys/mips/ingenic/jz4780_codec.c @@ -0,0 +1,242 @@ +/*- + * Copyright (c) 2016 Ruslan Bukin + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * 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 AUTHOR 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 AUTHOR 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. + */ + +/* Ingenic JZ4780 CODEC. */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +struct codec_softc { + device_t dev; + struct resource *res[1]; + bus_space_tag_t bst; + bus_space_handle_t bsh; +}; + +static struct resource_spec codec_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int codec_probe(device_t dev); +static int codec_attach(device_t dev); +static int codec_detach(device_t dev); +void codec_print_registers(struct codec_softc *sc); + +static int +codec_write(struct codec_softc *sc, uint32_t reg, uint32_t val) +{ + uint32_t tmp; + + tmp = (reg << RGADW_RGADDR_S); + tmp |= (val << RGADW_RGDIN_S); + tmp |= RGADW_RGWR; + + WRITE4(sc, CODEC_RGADW, tmp); + + while(READ4(sc, CODEC_RGADW) & RGADW_RGWR) + ; + + return (0); +} + +static int +codec_read(struct codec_softc *sc, uint32_t reg) +{ + uint32_t tmp; + + tmp = (reg << RGADW_RGADDR_S); + WRITE4(sc, CODEC_RGADW, tmp); + + tmp = READ4(sc, CODEC_RGDATA); + + return (tmp); +} + +void +codec_print_registers(struct codec_softc *sc) +{ + + printf("codec SR %x\n", codec_read(sc, SR)); + printf("codec SR2 %x\n", codec_read(sc, SR2)); + printf("codec MR %x\n", codec_read(sc, MR)); + printf("codec AICR_DAC %x\n", codec_read(sc, AICR_DAC)); + printf("codec AICR_ADC %x\n", codec_read(sc, AICR_ADC)); + printf("codec CR_LO %x\n", codec_read(sc, CR_LO)); + printf("codec CR_HP %x\n", codec_read(sc, CR_HP)); + printf("codec CR_DMIC %x\n", codec_read(sc, CR_DMIC)); + printf("codec CR_MIC1 %x\n", codec_read(sc, CR_MIC1)); + printf("codec CR_MIC2 %x\n", codec_read(sc, CR_MIC2)); + printf("codec CR_LI1 %x\n", codec_read(sc, CR_LI1)); + printf("codec CR_LI2 %x\n", codec_read(sc, CR_LI2)); + printf("codec CR_DAC %x\n", codec_read(sc, CR_DAC)); + printf("codec CR_ADC %x\n", codec_read(sc, CR_ADC)); + printf("codec CR_MIX %x\n", codec_read(sc, CR_MIX)); + printf("codec DR_MIX %x\n", codec_read(sc, DR_MIX)); + printf("codec CR_VIC %x\n", codec_read(sc, CR_VIC)); + printf("codec CR_CK %x\n", codec_read(sc, CR_CK)); + printf("codec FCR_DAC %x\n", codec_read(sc, FCR_DAC)); + printf("codec FCR_ADC %x\n", codec_read(sc, FCR_ADC)); + printf("codec CR_TIMER_MSB %x\n", codec_read(sc, CR_TIMER_MSB)); + printf("codec CR_TIMER_LSB %x\n", codec_read(sc, CR_TIMER_LSB)); + printf("codec ICR %x\n", codec_read(sc, ICR)); + printf("codec IMR %x\n", codec_read(sc, IMR)); + printf("codec IFR %x\n", codec_read(sc, IFR)); + printf("codec IMR2 %x\n", codec_read(sc, IMR2)); + printf("codec IFR2 %x\n", codec_read(sc, IFR2)); + printf("codec GCR_HPL %x\n", codec_read(sc, GCR_HPL)); + printf("codec GCR_HPR %x\n", codec_read(sc, GCR_HPR)); + printf("codec GCR_LIBYL %x\n", codec_read(sc, GCR_LIBYL)); + printf("codec GCR_LIBYR %x\n", codec_read(sc, GCR_LIBYR)); + printf("codec GCR_DACL %x\n", codec_read(sc, GCR_DACL)); + printf("codec GCR_DACR %x\n", codec_read(sc, GCR_DACR)); + printf("codec GCR_MIC1 %x\n", codec_read(sc, GCR_MIC1)); + printf("codec GCR_MIC2 %x\n", codec_read(sc, GCR_MIC2)); + printf("codec GCR_ADCL %x\n", codec_read(sc, GCR_ADCL)); + printf("codec GCR_ADCR %x\n", codec_read(sc, GCR_ADCR)); + printf("codec GCR_MIXDACL %x\n", codec_read(sc, GCR_MIXDACL)); + printf("codec GCR_MIXDACR %x\n", codec_read(sc, GCR_MIXDACR)); + printf("codec GCR_MIXADCL %x\n", codec_read(sc, GCR_MIXADCL)); + printf("codec GCR_MIXADCR %x\n", codec_read(sc, GCR_MIXADCR)); + printf("codec CR_ADC_AGC %x\n", codec_read(sc, CR_ADC_AGC)); + printf("codec DR_ADC_AGC %x\n", codec_read(sc, DR_ADC_AGC)); +} + +static int +codec_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_is_compatible(dev, "ingenic,jz4780-codec")) + return (ENXIO); + + device_set_desc(dev, "Ingenic JZ4780 CODEC"); + + return (BUS_PROBE_DEFAULT); +} + +static int +codec_attach(device_t dev) +{ + struct codec_softc *sc; + uint8_t reg; + + sc = device_get_softc(dev); + sc->dev = dev; + + if (bus_alloc_resources(dev, codec_spec, sc->res)) { + device_printf(dev, "could not allocate resources for device\n"); + return (ENXIO); + } + + /* Memory interface */ + sc->bst = rman_get_bustag(sc->res[0]); + sc->bsh = rman_get_bushandle(sc->res[0]); + + /* Initialize codec. */ + reg = codec_read(sc, CR_VIC); + reg &= ~(VIC_SB_SLEEP | VIC_SB); + codec_write(sc, CR_VIC, reg); + + reg = codec_read(sc, CR_DAC); + reg &= ~(DAC_SB | DAC_MUTE); + codec_write(sc, CR_DAC, reg); + + /* I2S, 16-bit, 96 kHz. */ + reg = codec_read(sc, AICR_DAC); + reg &= ~(AICR_DAC_SB | DAC_ADWL_M); + reg |= DAC_ADWL_16; + reg &= ~(AUDIOIF_M); + reg |= AUDIOIF_I2S; + codec_write(sc, AICR_DAC, reg); + + reg = FCR_DAC_96; + codec_write(sc, FCR_DAC, reg); + + /* Unmute headphones. */ + reg = codec_read(sc, CR_HP); + reg &= ~(HP_SB | HP_MUTE); + codec_write(sc, CR_HP, 0); + + return (0); +} + +static int +codec_detach(device_t dev) +{ + struct codec_softc *sc; + + sc = device_get_softc(dev); + + bus_release_resources(dev, codec_spec, sc->res); + + return (0); +} + +static device_method_t codec_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, codec_probe), + DEVMETHOD(device_attach, codec_attach), + DEVMETHOD(device_detach, codec_detach), + + DEVMETHOD_END +}; + +static driver_t codec_driver = { + "codec", + codec_methods, + sizeof(struct codec_softc), +}; + +static devclass_t codec_devclass; + +DRIVER_MODULE(codec, simplebus, codec_driver, codec_devclass, 0, 0); diff --git a/sys/mips/ingenic/jz4780_codec.h b/sys/mips/ingenic/jz4780_codec.h new file mode 100644 index 000000000000..6f5f6ffeec07 --- /dev/null +++ b/sys/mips/ingenic/jz4780_codec.h @@ -0,0 +1,101 @@ +/*- + * Copyright (c) 2016 Ruslan Bukin + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#define CODEC_RGADW 0x00 /* Address, data in and write command */ +#define RGADW_ICRST (1 << 31) /* Reset internal CODEC */ +#define RGADW_RGWR (1 << 16) /* Issue a write command to CODEC */ +#define RGADW_RGADDR_S 8 /* CODEC register's address. */ +#define RGADW_RGADDR_M (0x7f << RGADW_RGADDR_S) +#define RGADW_RGDIN_S 0 /* CODEC register data to write */ +#define RGADW_RGDIN_M (0xff << RGADW_RGDIN_S) +#define CODEC_RGDATA 0x04 /* The data read out */ + +#define SR 0x00 /* Status Register */ +#define SR2 0x01 /* Status Register 2 */ +#define MR 0x07 /* Mode status register */ +#define AICR_DAC 0x08 /* DAC Audio Interface Control Register */ +#define DAC_ADWL_S 6 /* Audio Data Word Length for DAC path. */ +#define DAC_ADWL_M (0x3 << DAC_ADWL_S) +#define DAC_ADWL_16 (0 << DAC_ADWL_S) +#define AICR_DAC_SB (1 << 4) /* DAC audio interface in power-down mode */ +#define AUDIOIF_S 0 +#define AUDIOIF_M (0x3 << AUDIOIF_S) +#define AUDIOIF_I2S 0x3 /* I2S interface */ +#define AUDIOIF_DSP 0x2 /* DSP interface */ +#define AUDIOIF_LJ 0x1 /* Left-justified interface */ +#define AUDIOIF_P 0x0 /* Parallel interface */ +#define AICR_ADC 0x09 /* ADC Audio Interface Control Register */ +#define CR_LO 0x0B /* Differential line-out Control Register */ +#define CR_HP 0x0D /* HeadPhone Control Register */ +#define HP_MUTE (1 << 7) /* no signal on headphone outputs */ +#define HP_SB (1 << 4) /* power-down */ +#define CR_DMIC 0x10 /* Digital Microphone register */ +#define CR_MIC1 0x11 /* Microphone1 Control register */ +#define CR_MIC2 0x12 /* Microphone2 Control register */ +#define CR_LI1 0x13 /* Control Register for line1 inputs */ +#define CR_LI2 0x14 /* Control Register for line2 inputs */ +#define CR_DAC 0x17 /* DAC Control Register */ +#define DAC_MUTE (1 << 7) /* puts the DAC in soft mute mode */ +#define DAC_SB (1 << 4) /* power-down */ +#define CR_ADC 0x18 /* ADC Control Register */ +#define CR_MIX 0x19 /* Digital Mixer Control Register */ +#define DR_MIX 0x1A /* Digital Mixer Data Register */ +#define CR_VIC 0x1B /* Control Register for the ViC */ +#define VIC_SB_SLEEP (1 << 1) /* sleep mode */ +#define VIC_SB (1 << 0) /* complete power-down */ +#define CR_CK 0x1C /* Clock Control Register */ +#define FCR_DAC 0x1D /* DAC Frequency Control Register */ +#define FCR_DAC_96 10 /* 96 kHz. */ +#define FCR_ADC 0x20 /* ADC Frequency Control Register */ +#define CR_TIMER_MSB 0x21 /* MSB of programmable counter */ +#define CR_TIMER_LSB 0x22 /* LSB of programmable counter */ +#define ICR 0x23 /* Interrupt Control Register */ +#define IMR 0x24 /* Interrupt Mask Register */ +#define IFR 0x25 /* Interrupt Flag Register */ +#define IMR2 0x26 /* Interrupt Mask Register 2 */ +#define IFR2 0x27 /* Interrupt Flag Register 2 */ +#define GCR_HPL 0x28 /* Left channel headphone Control Gain Register */ +#define GCR_HPR 0x29 /* Right channel headphone Control Gain Register */ +#define GCR_LIBYL 0x2A /* Left channel bypass line Control Gain Register */ +#define GCR_LIBYR 0x2B /* Right channel bypass line Control Gain Register */ +#define GCR_DACL 0x2C /* Left channel DAC Gain Control Register */ +#define GCR_DACR 0x2D /* Right channel DAC Gain Control Register */ +#define GCR_MIC1 0x2E /* Microphone 1 Gain Control Register */ +#define GCR_MIC2 0x2F /* Microphone 2 Gain Control Register */ +#define GCR_ADCL 0x30 /* Left ADC Gain Control Register */ +#define GCR_ADCR 0x31 /* Right ADC Gain Control Register */ +#define GCR_MIXDACL 0x34 /* DAC Digital Mixer Control Register */ +#define GCR_MIXDACR 0x35 /* DAC Digital Mixer Control Register */ +#define GCR_MIXADCL 0x36 /* ADC Digital Mixer Control Register */ +#define GCR_MIXADCR 0x37 /* ADC Digital Mixer Control Register */ +#define CR_ADC_AGC 0x3A /* Automatic Gain Control Register */ +#define DR_ADC_AGC 0x3B /* Automatic Gain Control Data Register */ diff --git a/sys/mips/ingenic/jz4780_common.h b/sys/mips/ingenic/jz4780_common.h new file mode 100644 index 000000000000..fee5faff8c00 --- /dev/null +++ b/sys/mips/ingenic/jz4780_common.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2016 Ruslan Bukin + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#define READ4(_sc, _reg) \ + bus_space_read_4(_sc->bst, _sc->bsh, _reg) +#define WRITE4(_sc, _reg, _val) \ + bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val)