From 18c715ba9283dda403aeeb73db2b299e081e3bfa Mon Sep 17 00:00:00 2001 From: Tiago Medicci Serrano Date: Wed, 28 Sep 2022 15:01:53 -0300 Subject: [PATCH] xtensa/esp32: add initial support for I2S Add initial support for the I2S peripheral on ESP32. Add I2S character driver and generic I2S audio driver. Include i2schar defconfig for ESP32-DevKitC board. --- arch/xtensa/src/esp32/Kconfig | 291 ++- arch/xtensa/src/esp32/Make.defs | 4 + arch/xtensa/src/esp32/esp32_dma.c | 79 + arch/xtensa/src/esp32/esp32_dma.h | 26 + arch/xtensa/src/esp32/esp32_i2s.c | 1647 +++++++++++++ arch/xtensa/src/esp32/esp32_i2s.h | 80 + arch/xtensa/src/esp32/hardware/esp32_i2s.h | 2039 ++++++++++++++++- boards/xtensa/esp32/common/src/Make.defs | 4 + .../esp32/common/src/esp32_board_i2sdev.c | 109 + .../esp32-devkitc/configs/i2schar/defconfig | 62 + .../esp32/esp32-devkitc/src/esp32-devkitc.h | 22 + .../esp32/esp32-devkitc/src/esp32_bringup.c | 34 + 12 files changed, 4368 insertions(+), 29 deletions(-) create mode 100644 arch/xtensa/src/esp32/esp32_i2s.c create mode 100644 arch/xtensa/src/esp32/esp32_i2s.h create mode 100644 boards/xtensa/esp32/common/src/esp32_board_i2sdev.c create mode 100644 boards/xtensa/esp32/esp32-devkitc/configs/i2schar/defconfig diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig index 426f188b8c..dd34818a57 100644 --- a/arch/xtensa/src/esp32/Kconfig +++ b/arch/xtensa/src/esp32/Kconfig @@ -276,20 +276,6 @@ config ESP32_TWAI default n select CAN -config ESP32_I2S0 - bool "I2S 0" - default n - depends on EXPERIMENTAL - ---help--- - No yet implemented - -config ESP32_I2S1 - bool "I2S 2" - default n - depends on EXPERIMENTAL - ---help--- - No yet implemented - config ESP32_LEDC bool "LEDC (PWM)" default n @@ -333,6 +319,283 @@ config ESP32_SDMMC ---help--- No yet implemented +config ESP32_I2S + bool "I2S" + select I2S + ---help--- + See the Board Selection menu to configure the pins used by I2S. + +if ESP32_I2S + +config ESP32_I2S0 + bool "I2S 0" + default n + select ARCH_DMA + select ESP32_GPIO_IRQ + +if ESP32_I2S0 + +config ESP32_I2S0_RX + bool "Enable I2S receiver" + default y + ---help--- + Enable I2S receive logic + +config ESP32_I2S0_TX + bool "Enable I2S transmitter" + default y + ---help--- + Enable I2S transmit logic + +choice + prompt "I2S0 role" + default ESP32_I2S0_ROLE_MASTER + ---help--- + Selects the operation role of the I2S0. + +config ESP32_I2S0_ROLE_MASTER + bool "Master" + +config ESP32_I2S0_ROLE_SLAVE + bool "Slave" + +endchoice + +choice + prompt "Bit width" + ---help--- + Selects the valid data bits per sample. + Note that this option may be overwritten by the audio + according to the bit width of the file being played + +config ESP32_I2S0_DATA_BIT_WIDTH_8BIT + bool "8 bits" + +config ESP32_I2S0_DATA_BIT_WIDTH_16BIT + bool "16 bits" + +config ESP32_I2S0_DATA_BIT_WIDTH_24BIT + bool "24 bits" + +config ESP32_I2S0_DATA_BIT_WIDTH_32BIT + bool "32 bits" + +endchoice + +config ESP32_I2S0_DATA_BIT_WIDTH + int + default 8 if ESP32_I2S0_DATA_BIT_WIDTH_8BIT + default 16 if ESP32_I2S0_DATA_BIT_WIDTH_16BIT + default 24 if ESP32_I2S0_DATA_BIT_WIDTH_24BIT + default 32 if ESP32_I2S0_DATA_BIT_WIDTH_32BIT + +config ESP32_I2S0_SAMPLE_RATE + int "I2S0 sample rate" + default 44100 + range 8000 48000 + ---help--- + Selects the sample rate. + Note that this option may be overwritten by the audio + according to the bit width of the file being played + +config ESP32_I2S0_BCLKPIN + int "I2S0 BCLK pin" + default 4 + range 0 33 if ESP32_I2S0_ROLE_MASTER + range 0 39 if ESP32_I2S0_ROLE_SLAVE + +config ESP32_I2S0_WSPIN + int "I2S0 WS pin" + default 5 + range 0 33 if ESP32_I2S0_ROLE_MASTER + range 0 39 if ESP32_I2S0_ROLE_SLAVE + +config ESP32_I2S0_DINPIN + int "I2S0 DOUT pin" + depends on ESP32_I2S0_RX + default 12 + range 0 39 + +config ESP32_I2S0_DOUTPIN + int "I2S0 DOUT pin" + depends on ESP32_I2S0_TX + default 18 + range 0 33 + +config ESP32_I2S0_MCLK + bool "Enable I2S Master Clock" + depends on ESP32_I2S0_ROLE_MASTER + default n + ---help--- + Enable I2S master clock + +choice + prompt "I2S0 MCLK pin" + depends on ESP32_I2S0_MCLK + default ESP32_I2S0_MCLKPIN_GPIO0 + ---help--- + Selects the pin to output master clock. + +config ESP32_I2S0_MCLKPIN_GPIO0 + bool "GPIO0" + +config ESP32_I2S0_MCLKPIN_GPIO1 + bool "GPIO1 (U0TXD)" + +config ESP32_I2S0_MCLKPIN_GPIO3 + bool "GPIO3 [U0RXD]" + +endchoice + +config ESP32_I2S0_MCLKPIN + int + default 0 + default 0 if ESP32_I2S0_MCLKPIN_GPIO0 + default 1 if ESP32_I2S0_MCLKPIN_GPIO1 + default 3 if ESP32_I2S0_MCLKPIN_GPIO3 + +endif #ESP32_I2S0 + +config ESP32_I2S1 + bool "I2S 1" + default n + select ARCH_DMA + select ESP32_GPIO_IRQ + +if ESP32_I2S1 + +config ESP32_I2S1_RX + bool "Enable I2S receiver" + default y + ---help--- + Enable I2S receive logic + +config ESP32_I2S1_TX + bool "Enable I2S transmitter" + default y + ---help--- + Enable I2S transmit logic + +choice + prompt "I2S1 role" + default ESP32_I2S1_ROLE_MASTER + ---help--- + Selects the operation role of the I2S1. + +config ESP32_I2S1_ROLE_MASTER + bool "Master" + +config ESP32_I2S1_ROLE_SLAVE + bool "Slave" + +endchoice + +choice + prompt "Bit width" + ---help--- + Selects the valid data bits per sample. + Note that this option may be overwritten by the audio + according to the bit width of the file being played + +config ESP32_I2S1_DATA_BIT_WIDTH_8BIT + bool "8 bits" + +config ESP32_I2S1_DATA_BIT_WIDTH_16BIT + bool "16 bits" + +config ESP32_I2S1_DATA_BIT_WIDTH_24BIT + bool "24 bits" + +config ESP32_I2S1_DATA_BIT_WIDTH_32BIT + bool "32 bits" + +endchoice + +config ESP32_I2S1_DATA_BIT_WIDTH + int + default 16 + default 8 if ESP32_I2S1_DATA_BIT_WIDTH_8BIT + default 16 if ESP32_I2S1_DATA_BIT_WIDTH_16BIT + default 24 if ESP32_I2S1_DATA_BIT_WIDTH_24BIT + default 32 if ESP32_I2S1_DATA_BIT_WIDTH_32BIT + +config ESP32_I2S1_SAMPLE_RATE + int "I2S1 sample rate" + default 44100 + range 8000 48000 + ---help--- + Selects the sample rate. + Note that this option may be overwritten by the audio + according to the bit width of the file being played + +config ESP32_I2S1_BCLKPIN + int "I2S1 BCLK pin" + default 19 + range 0 33 if ESP32_I2S1_ROLE_MASTER + range 0 39 if ESP32_I2S1_ROLE_SLAVE + +config ESP32_I2S1_WSPIN + int "I2S1 WS pin" + default 18 + range 0 33 if ESP32_I2S1_ROLE_MASTER + range 0 39 if ESP32_I2S1_ROLE_SLAVE + +config ESP32_I2S1_DOUTPIN + int "I2S1 DOUT pin" + depends on ESP32_I2S1_RX + default 17 + range 0 39 + +config ESP32_I2S1_DOUTPIN + int "I2S1 DOUT pin" + depends on ESP32_I2S1_TX + default 16 + range 0 33 + +config ESP32_I2S1_MCLK + bool "Enable I2S Master Clock" + depends on ESP32_I2S1_ROLE_MASTER + default n + ---help--- + Enable I2S master clock + +choice + prompt "I2S1 MCLK pin" + depends on ESP32_I2S1_MCLK + default ESP32_I2S1_MCLKPIN_GPIO0 + ---help--- + Selects the pin to output master clock. + +config ESP32_I2S1_MCLKPIN_GPIO0 + bool "GPIO0" + +config ESP32_I2S1_MCLKPIN_GPIO1 + bool "GPIO1 (U0TXD)" + +config ESP32_I2S1_MCLKPIN_GPIO3 + bool "GPIO3 [U0RXD]" + +endchoice + +config ESP32_I2S1_MCLKPIN + int + default 0 + default 0 if ESP32_I2S1_MCLKPIN_GPIO0 + default 1 if ESP32_I2S1_MCLKPIN_GPIO1 + default 3 if ESP32_I2S1_MCLKPIN_GPIO3 + +endif #ESP32_I2S1 + +config I2S_DMADESC_NUM + int "I2S DMA maximum number of descriptors" + default 2 + ---help--- + Configure the maximum number of out-link/in-link descriptors to + be chained for a I2S DMA transfer. + +endif #ESP32_I2S + + config ESP32_SPI bool default n diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs index dfb47c46ec..14c5dbc7e0 100644 --- a/arch/xtensa/src/esp32/Make.defs +++ b/arch/xtensa/src/esp32/Make.defs @@ -70,6 +70,10 @@ ifeq ($(CONFIG_ESP32_I2C),y) CHIP_CSRCS += esp32_i2c.c endif +ifeq ($(CONFIG_ESP32_I2S),y) +CHIP_CSRCS += esp32_i2s.c +endif + ifeq ($(CONFIG_ESP32_TWAI),y) CHIP_CSRCS += esp32_twai.c endif diff --git a/arch/xtensa/src/esp32/esp32_dma.c b/arch/xtensa/src/esp32/esp32_dma.c index d398f5bf4e..532ce0bd4b 100644 --- a/arch/xtensa/src/esp32/esp32_dma.c +++ b/arch/xtensa/src/esp32/esp32_dma.c @@ -105,3 +105,82 @@ uint32_t esp32_dma_init(struct esp32_dmadesc_s *dmadesc, uint32_t num, return len - bytes; } + +/**************************************************************************** + * Name: esp32_dma_init_with_padding + * + * Description: + * Initialize DMA outlink descriptors and bind the target buffer to + * these DMA descriptors. If len is not word-aligned, add a new descriptor + * containing a 4-byte variable to make the outlink data world-aligned. + * + * Input Parameters: + * dmadesc - DMA descriptions pointer + * num - DMA descriptions number + * pbuf - RX/TX buffer pointer + * len - RX/TX buffer length + * stuff - Value to be padded with the buffer + * + * Returned Value: + * Binded pbuf data bytes + * + ****************************************************************************/ + +uint32_t esp32_dma_init_with_padding(struct esp32_dmadesc_s *dmadesc, + uint32_t num, + uint8_t *pbuf, + uint32_t len, + uint32_t *stuff) +{ + int i; + uint32_t bytes = len; + uint8_t *pdata = pbuf; + uint32_t data_len = 0; + uint32_t buf_len = 0; + + DEBUGASSERT(dmadesc != NULL); + DEBUGASSERT(pbuf != NULL); + DEBUGASSERT(len > 0); + + for (i = 0; i < num - 1; i++) + { + data_len = MIN(bytes, ESP32_DMA_DATALEN_MAX); + + /* Buffer length must be rounded to next 32-bit boundary. */ + + buf_len = ALIGN_UP(data_len, sizeof(uintptr_t)); + + dmadesc[i].ctrl = (data_len << DMA_CTRL_DATALEN_S) | + (buf_len << DMA_CTRL_BUFLEN_S) | + DMA_CTRL_OWN; + dmadesc[i].pbuf = pdata; + dmadesc[i].next = &dmadesc[i + 1]; + + bytes -= data_len; + if (bytes == 0) + { + break; + } + + pdata += data_len; + } + + /* Check if the data_len of the last descriptor is different from buf_len. + * If so, it's necessary to add the padding bytes to a new descriptor on + * outlink. + */ + + if (data_len != buf_len) + { + i++; + dmadesc[i].ctrl = ((buf_len - data_len) << DMA_CTRL_DATALEN_S) | + (4 << DMA_CTRL_BUFLEN_S) | + DMA_CTRL_OWN; + dmadesc[i].pbuf = (uint8_t *)stuff; + } + + dmadesc[i].ctrl |= DMA_CTRL_EOF; + dmadesc[i].next = NULL; + + return len - bytes; +} diff --git a/arch/xtensa/src/esp32/esp32_dma.h b/arch/xtensa/src/esp32/esp32_dma.h index 1768da02b3..dfebd3e92b 100644 --- a/arch/xtensa/src/esp32/esp32_dma.h +++ b/arch/xtensa/src/esp32/esp32_dma.h @@ -89,6 +89,32 @@ struct esp32_dmadesc_s uint32_t esp32_dma_init(struct esp32_dmadesc_s *dmadesc, uint32_t num, uint8_t *pbuf, uint32_t len); +/**************************************************************************** + * Name: esp32_dma_init_with_padding + * + * Description: + * Initialize DMA outlink descriptors and bind the target buffer to + * these DMA descriptors. If len is not word-aligned, add a new descriptor + * containing a 4-byte variable to make the outlink data world-aligned. + * + * Input Parameters: + * dmadesc - DMA descriptions pointer + * num - DMA descriptions number + * pbuf - RX/TX buffer pointer + * len - RX/TX buffer length + * stuff - Value to be padded with the buffer + * + * Returned Value: + * Binded pbuf data bytes + * + ****************************************************************************/ + +uint32_t esp32_dma_init_with_padding(struct esp32_dmadesc_s *dmadesc, + uint32_t num, + uint8_t *pbuf, + uint32_t len, + uint32_t *stuff); + #ifdef __cplusplus } #endif diff --git a/arch/xtensa/src/esp32/esp32_i2s.c b/arch/xtensa/src/esp32/esp32_i2s.c new file mode 100644 index 0000000000..34507d565b --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_i2s.c @@ -0,0 +1,1647 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_i2s.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_ESP32_I2S + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "esp32_i2s.h" +#include "esp32_gpio.h" +#include "esp32_irq.h" +#include "esp32_dma.h" + +#include "xtensa.h" +#include "hardware/esp32_gpio_sigmap.h" +#include "hardware/esp32_dport.h" +#include "hardware/esp32_i2s.h" +#include "hardware/esp32_soc.h" +#include "hardware/esp32_iomux.h" +#include "hardware/esp32_pinmap.h" +#include "hardware/esp32_dma.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* I2S DMA RX/TX description number */ + +#define I2S_DMADESC_NUM (CONFIG_I2S_DMADESC_NUM) + +/* I2S Clock */ + +#define I2S_LL_BASE_CLK (2 * APB_CLK_FREQ) +#define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (6) +#define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1) + +/* I2S DMA channel number */ + +#define I2S_DMA_CHANNEL_MAX (2) + +#ifdef CONFIG_ESP32_I2S0_TX + #define I2S0_TX_ENABLED 1 + #define I2S_HAVE_TX 1 +#else + #define I2S0_TX_ENABLED 0 +#endif + +#ifdef CONFIG_ESP32_I2S0_RX + #define I2S0_RX_ENABLED 1 +#else + #define I2S0_RX_ENABLED 0 +#endif + +#ifdef CONFIG_ESP32_I2S1_TX + #define I2S1_TX_ENABLED 1 + #define I2S_HAVE_TX 1 +#else + #define I2S1_TX_ENABLED 0 +#endif + +#ifdef CONFIG_ESP32_I2S1_RX + #define I2S1_RX_ENABLED 1 +#else + #define I2S1_RX_ENABLED 0 +#endif + +/* Debug ********************************************************************/ + +#ifdef CONFIG_DEBUG_I2S_INFO +# define CONFIG_ESP32_I2S_DUMPBUFFERS +#else +# undef CONFIG_ESP32_I2S_DUMPBUFFERS +#endif + +#ifndef CONFIG_ESP32_I2S_MAXINFLIGHT +# define CONFIG_ESP32_I2S_MAXINFLIGHT 4 +#endif + +#define I2S_GPIO_UNUSED -1 /* For signals which are not used */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Role of the I2S port */ + +typedef enum +{ + I2S_ROLE_MASTER, /* I2S controller master role, bclk and ws signal will be set to output */ + I2S_ROLE_SLAVE /* I2S controller slave role, bclk and ws signal will be set to input */ +} i2s_role_t; + +/* Data width of the I2S channel */ + +typedef enum +{ + I2S_DATA_BIT_WIDTH_8BIT = 8, /* I2S channel data bit-width: 8 */ + I2S_DATA_BIT_WIDTH_16BIT = 16, /* I2S channel data bit-width: 16 */ + I2S_DATA_BIT_WIDTH_24BIT = 24, /* I2S channel data bit-width: 24 */ + I2S_DATA_BIT_WIDTH_32BIT = 32, /* I2S channel data bit-width: 32 */ +} i2s_data_bit_width_t; + +/* Multiplier of MCLK to sample rate */ + +typedef enum +{ + I2S_MCLK_MULTIPLE_128 = 128, /* mclk = sample_rate * 128 */ + I2S_MCLK_MULTIPLE_256 = 256, /* mclk = sample_rate * 256 */ + I2S_MCLK_MULTIPLE_384 = 384, /* mclk = sample_rate * 384 */ + I2S_MCLK_MULTIPLE_512 = 512, /* mclk = sample_rate * 512 */ +} i2s_mclk_multiple_t; + +/* I2S Device hardware configuration */ + +struct esp32_i2s_config_s +{ + uint32_t port; /* I2S port */ + uint32_t role; /* I2S port role (master or slave) */ + uint8_t data_width; /* I2S sample data width */ + uint32_t rate; /* I2S sample-rate */ + uint32_t total_slot; /* Total slot number */ + + bool is_apll; /* Select APLL as the source clock */ + uint32_t mclk_multiple; /* The multiple of mclk to the sample rate */ + + bool tx_en; /* Is TX enabled? */ + bool rx_en; /* Is RX enabled? */ + int8_t mclk_pin; /* MCLK pin, output */ + + /* BCLK pin, input in slave role, output in master role */ + + int8_t bclk_pin; + + /* WS pin, input in slave role, output in master role */ + + int8_t ws_pin; + + int8_t dout_pin; /* DATA pin, output */ + int8_t din_pin; /* DATA pin, input */ + + uint8_t periph; /* peripher ID */ + uint8_t irq; /* Interrupt ID */ + + uint32_t bclk_in_insig; /* RX channel BCK signal (slave mode) index */ + uint32_t bclk_in_outsig; /* RX channel BCK signal (master mode) index */ + uint32_t bclk_out_insig; /* TX channel BCK signal (slave mode) index */ + uint32_t bclk_out_outsig; /* TX channel BCK signal (master mode) index */ + uint32_t ws_in_insig; /* RX channel WS signal (slave mode) index */ + uint32_t ws_in_outsig; /* RX channel WS signal (master mode) index */ + uint32_t ws_out_insig; /* TX channel WS signal (slave mode) index */ + uint32_t ws_out_outsig; /* TX channel WS signal (master mode) index */ + uint32_t din_insig; /* RX channel Data Input signal index */ + uint32_t dout_outsig; /* TX channel Data Output signal index */ + + bool bit_shift; /* Set to enable bit shift in Philips mode */ + bool mono_en; /* Set to enable mono mode on slot */ + + /* WS signal width (the number of bclk ticks that ws signal is high) */ + + uint32_t ws_width; + + /* WS signal polarity, set true to enable high lever first */ + + bool ws_pol; +}; + +struct esp32_buffer_s +{ + struct esp32_buffer_s *flink; /* Supports a singly linked list */ + + /* The associated DMA outlink */ + + struct esp32_dmadesc_s dma_outlink[I2S_DMADESC_NUM]; + + i2s_callback_t callback; /* DMA completion callback */ + uint32_t timeout; /* Timeout value of the DMA transfers */ + void *arg; /* Callback's argument */ + struct ap_buffer_s *apb; /* The audio buffer */ + int result; /* The result of the transfer */ +}; + +/* This structure describes the state of one receiver or transmitter + * transport. + */ + +struct esp32_transport_s +{ + sq_queue_t pend; /* A queue of pending transfers */ + sq_queue_t act; /* A queue of active transfers */ + sq_queue_t done; /* A queue of completed transfers */ + struct work_s work; /* Supports worker thread operations */ +}; + +/* The state of the one I2S peripheral */ + +struct esp32_i2s_s +{ + struct i2s_dev_s dev; /* Externally visible I2S interface */ + sem_t exclsem; /* Assures mutually exclusive access */ + uint32_t rate; /* I2S actual configured sample-rate */ + uint32_t data_width; /* I2S actual configured data_width */ + int cpuint; /* I2S interrupt ID */ + uint8_t cpu; /* CPU ID */ + spinlock_t lock; /* Device specific lock. */ + + /* Port configuration */ + + const struct esp32_i2s_config_s *config; + +#ifdef I2S_HAVE_TX + struct esp32_transport_s tx; /* TX transport state */ + + /* Stuff var to fill DMA buffer if not word-aligned */ + + uint32_t stuff; +#endif /* I2S_HAVE_TX */ + + /* Pre-allocated pool of buffer containers */ + + sem_t bufsem; /* Buffer wait semaphore */ + struct esp32_buffer_s *bf_freelist; /* A list a free buffer containers */ + struct esp32_buffer_s containers[CONFIG_ESP32_I2S_MAXINFLIGHT]; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Register helpers */ + +#ifdef CONFIG_ESP32_I2S_DUMPBUFFERS +# define i2s_dump_buffer(m,b,s) lib_dumpbuffer(m,b,s) +#else +# define i2s_dump_buffer(m,b,s) +#endif + +/* Semaphore helpers */ + +static int i2s_exclsem_take(struct esp32_i2s_s *priv); +#define i2s_exclsem_give(priv) nxsem_post(&priv->exclsem) + +static int i2s_bufsem_take(struct esp32_i2s_s *priv); +#define i2s_bufsem_give(priv) nxsem_post(&priv->bufsem) + +/* Buffer container helpers */ + +static struct esp32_buffer_s * + i2s_buf_allocate(struct esp32_i2s_s *priv); +static void i2s_buf_free(struct esp32_i2s_s *priv, + struct esp32_buffer_s *bfcontainer); +static int i2s_buf_initialize(struct esp32_i2s_s *priv); + +/* DMA support */ + +#ifdef I2S_HAVE_TX +static int i2s_txdma_setup(struct esp32_i2s_s *priv, + struct esp32_buffer_s *bfcontainer); +static void i2s_tx_worker(void *arg); +static void i2s_tx_schedule(struct esp32_i2s_s *priv, + struct esp32_dmadesc_s *outlink); +#endif /* I2S_HAVE_TX */ + +/* I2S methods (and close friends) */ + +static uint32_t esp32_i2s_txsamplerate(struct i2s_dev_s *dev, + uint32_t rate); +static uint32_t esp32_i2s_txdatawidth(struct i2s_dev_s *dev, int bits); +static int esp32_i2s_send(struct i2s_dev_s *dev, + struct ap_buffer_s *apb, + i2s_callback_t callback, void *arg, + uint32_t timeout); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct i2s_ops_s g_i2sops = +{ + .i2s_txsamplerate = esp32_i2s_txsamplerate, + .i2s_txdatawidth = esp32_i2s_txdatawidth, + .i2s_send = esp32_i2s_send, +}; + +#ifdef CONFIG_ESP32_I2S0 +static const struct esp32_i2s_config_s esp32_i2s0_config = +{ + .port = 0, +#ifdef CONFIG_ESP32_I2S0_ROLE_MASTER + .role = I2S_ROLE_MASTER, +#else + .role = I2S_ROLE_SLAVE, +#endif /* CONFIG_ESP32_I2S0_ROLE_MASTER */ + .data_width = CONFIG_ESP32_I2S0_DATA_BIT_WIDTH, + .rate = CONFIG_ESP32_I2S0_SAMPLE_RATE, + .total_slot = 2, + .mclk_multiple = I2S_MCLK_MULTIPLE_384, + .tx_en = I2S0_TX_ENABLED, + .rx_en = I2S0_RX_ENABLED, +#ifdef CONFIG_ESP32_I2S0_MCLK + .mclk_pin = CONFIG_ESP32_I2S0_MCLKPIN, +#else + .mclk_pin = I2S_GPIO_UNUSED, +#endif /* CONFIG_ESP32_I2S0_MCLK */ + .bclk_pin = CONFIG_ESP32_I2S0_BCLKPIN, + .ws_pin = CONFIG_ESP32_I2S0_WSPIN, +#ifdef CONFIG_ESP32_I2S0_DOUTPIN + .dout_pin = CONFIG_ESP32_I2S0_DOUTPIN, +#else + .dout_pin = I2S_GPIO_UNUSED, +#endif /* CONFIG_ESP32_I2S0_DOUTPIN */ +#ifdef CONFIG_ESP32_I2S0_DINPIN + .din_pin = CONFIG_ESP32_I2S0_DINPIN, +#else + .din_pin = I2S_GPIO_UNUSED, +#endif /* CONFIG_ESP32_I2S0_DINPIN */ + .periph = ESP32_PERIPH_I2S0, + .irq = ESP32_IRQ_I2S0, + .bclk_in_insig = I2S0I_BCK_IN_IDX, + .bclk_in_outsig = I2S0I_BCK_OUT_IDX, + .bclk_out_insig = I2S0O_BCK_IN_IDX, + .bclk_out_outsig = I2S0O_BCK_OUT_IDX, + .ws_in_insig = I2S0I_WS_IN_IDX, + .ws_in_outsig = I2S0I_WS_OUT_IDX, + .ws_out_insig = I2S0O_WS_IN_IDX, + .ws_out_outsig = I2S0O_WS_OUT_IDX, + .din_insig = I2S0I_DATA_IN15_IDX, + .dout_outsig = I2S0O_DATA_OUT23_IDX, + .bit_shift = true, + .mono_en = false, + .ws_width = CONFIG_ESP32_I2S0_DATA_BIT_WIDTH, +}; + +static struct esp32_i2s_s esp32_i2s0_priv = +{ + .dev = + { + .ops = &g_i2sops + }, + .config = &esp32_i2s0_config +}; +#endif /* CONFIG_ESP32_I2S0 */ + +#ifdef CONFIG_ESP32_I2S1 +static const struct esp32_i2s_config_s esp32_i2s1_config = +{ + .port = 1, +#ifdef CONFIG_ESP32_I2S1_ROLE_MASTER + .role = I2S_ROLE_MASTER, +#else + .role = I2S_ROLE_SLAVE, +#endif /* CONFIG_ESP32_I2S1_ROLE_MASTER */ + .data_width = CONFIG_ESP32_I2S1_DATA_BIT_WIDTH, + .rate = CONFIG_ESP32_I2S1_SAMPLE_RATE, + .total_slot = 2, + .mclk_multiple = I2S_MCLK_MULTIPLE_384, + .tx_en = I2S1_TX_ENABLED, + .rx_en = I2S1_RX_ENABLED, +#ifdef CONFIG_ESP32_I2S1_MCLK + .mclk_pin = CONFIG_ESP32_I2S1_MCLKPIN, +#else + .mclk_pin = I2S_GPIO_UNUSED, +#endif /* CONFIG_ESP32_I2S1_MCLK */ + .bclk_pin = CONFIG_ESP32_I2S1_BCLKPIN, + .ws_pin = CONFIG_ESP32_I2S1_WSPIN, +#ifdef CONFIG_ESP32_I2S1_DOUTPIN + .dout_pin = CONFIG_ESP32_I2S1_DOUTPIN, +#else + .dout_pin = I2S_GPIO_UNUSED, +#endif /* CONFIG_ESP32_I2S1_DOUTPIN */ +#ifdef CONFIG_ESP32_I2S1_DINPIN + .din_pin = CONFIG_ESP32_I2S1_DINPIN, +#else + .din_pin = I2S_GPIO_UNUSED, +#endif /* CONFIG_ESP32_I2S1_DINPIN */ + .periph = ESP32_PERIPH_I2S1, + .irq = ESP32_IRQ_I2S1, + .bclk_in_insig = I2S1I_BCK_IN_IDX, + .bclk_in_outsig = I2S1I_BCK_OUT_IDX, + .bclk_out_insig = I2S1O_BCK_IN_IDX, + .bclk_out_outsig = I2S1O_BCK_OUT_IDX, + .ws_in_insig = I2S1I_WS_IN_IDX, + .ws_in_outsig = I2S1I_WS_OUT_IDX, + .ws_out_insig = I2S1O_WS_IN_IDX, + .ws_out_outsig = I2S1O_WS_OUT_IDX, + .din_insig = I2S1I_DATA_IN15_IDX, + .dout_outsig = I2S1O_DATA_OUT23_IDX, + .bit_shift = true, + .mono_en = false, + .ws_width = CONFIG_ESP32_I2S1_DATA_BIT_WIDTH, +}; + +static struct esp32_i2s_s esp32_i2s1_priv = +{ + .dev = + { + .ops = &g_i2sops + }, + .config = &esp32_i2s1_config +}; +#endif /* CONFIG_ESP32_I2S1 */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i2s_exclsem_take + * + * Description: + * Take the exclusive access semaphore handling any exceptional conditions + * + * Input Parameters: + * priv - A reference to the i2s peripheral state + * + * Returned Value: + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. + * + ****************************************************************************/ + +static int i2s_exclsem_take(struct esp32_i2s_s *priv) +{ + return nxsem_wait_uninterruptible(&priv->exclsem); +} + +/**************************************************************************** + * Name: i2s_bufsem_take + * + * Description: + * Take the buffer semaphore handling any exceptional conditions + * + * Input Parameters: + * priv - A reference to the i2s peripheral state + * + * Returned Value: + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. + * + ****************************************************************************/ + +static int i2s_bufsem_take(struct esp32_i2s_s *priv) +{ + return nxsem_wait_uninterruptible(&priv->bufsem); +} + +/**************************************************************************** + * Name: i2s_buf_allocate + * + * Description: + * Allocate a buffer container by removing the one at the head of the + * free list + * + * Input Parameters: + * priv - I2S state instance + * + * Returned Value: + * A non-NULL pointer to the allocate buffer container on success; NULL if + * there are no available buffer containers. + * + * Assumptions: + * The caller does NOT have exclusive access to the I2S state structure. + * That would result in a deadlock! + * + ****************************************************************************/ + +static struct esp32_buffer_s *i2s_buf_allocate(struct esp32_i2s_s *priv) +{ + struct esp32_buffer_s *bfcontainer; + irqstate_t flags; + int ret; + + /* Set aside a buffer container. By doing this, we guarantee that we will + * have at least one free buffer container. + */ + + ret = i2s_bufsem_take(priv); + if (ret < 0) + { + return NULL; + } + + /* Get the buffer from the head of the free list */ + + flags = spin_lock_irqsave(&priv->lock); + bfcontainer = priv->bf_freelist; + DEBUGASSERT(bfcontainer); + + /* Unlink the buffer from the freelist */ + + priv->bf_freelist = bfcontainer->flink; + spin_unlock_irqrestore(&priv->lock, flags); + return bfcontainer; +} + +/**************************************************************************** + * Name: i2s_buf_free + * + * Description: + * Free buffer container by adding it to the head of the free list + * + * Input Parameters: + * priv - I2S state instance + * bfcontainer - The buffer container to be freed + * + * Returned Value: + * None + * + * Assumptions: + * The caller has exclusive access to the I2S state structure + * + ****************************************************************************/ + +static void i2s_buf_free(struct esp32_i2s_s *priv, + struct esp32_buffer_s *bfcontainer) +{ + irqstate_t flags; + + /* Put the buffer container back on the free list (circbuf) */ + + flags = spin_lock_irqsave(&priv->lock); + + bfcontainer->apb = NULL; + bfcontainer->flink = priv->bf_freelist; + priv->bf_freelist = bfcontainer; + + spin_unlock_irqrestore(&priv->lock, flags); + + /* Wake up any threads waiting for a buffer container */ + + i2s_bufsem_give(priv); +} + +/**************************************************************************** + * Name: i2s_buf_initialize + * + * Description: + * Initialize the buffer container allocator by adding all of the + * pre-allocated buffer containers to the free list + * + * Input Parameters: + * priv - I2S state instance + * + * Returned Value: + * OK on success; A negated errno value on failure. + * + * Assumptions: + * Called early in I2S initialization so that there are no issues with + * concurrency. + * + ****************************************************************************/ + +static int i2s_buf_initialize(struct esp32_i2s_s *priv) +{ + int ret; + + priv->bf_freelist = NULL; + ret = nxsem_init(&priv->bufsem, 0, 0); + + if (ret < 0) + { + i2serr("ERROR: nxsem_init failed: %d\n", ret); + return ret; + } + + for (int i = 0; i < CONFIG_ESP32_I2S_MAXINFLIGHT; i++) + { + i2s_buf_free(priv, &priv->containers[i]); + } + + return OK; +} + +/**************************************************************************** + * Name: i2s_txdma_start + * + * Description: + * Initiate the next TX DMA transfer. The DMA outlink was previously bound + * so it is safe to start the next DMA transfer at interruption level. + * + * Input Parameters: + * priv - I2S state instance + * + * Returned Value: + * OK on success; a negated errno value on failure + * + * Assumptions: + * Interrupts are disabled + * + ****************************************************************************/ + +#ifdef I2S_HAVE_TX +static int i2s_txdma_start(struct esp32_i2s_s *priv) +{ + struct esp32_buffer_s *bfcontainer; + + /* If there is already an active transmission in progress, then bail + * returning success. + */ + + if (!sq_empty(&priv->tx.act)) + { + return OK; + } + + /* If there are no pending transfer, then bail returning success */ + + if (sq_empty(&priv->tx.pend)) + { + return OK; + } + + bfcontainer = (struct esp32_buffer_s *)sq_remfirst(&priv->tx.pend); + + /* If there isn't already an active transmission in progress, + * then start it. + */ + + modifyreg32(I2S_OUT_LINK_REG(priv->config->port), I2S_OUTLINK_ADDR_M, + FIELD_TO_VALUE(I2S_OUTLINK_ADDR, + (uintptr_t) bfcontainer->dma_outlink)); + + modifyreg32(I2S_OUT_LINK_REG(priv->config->port), I2S_OUTLINK_STOP, + I2S_OUTLINK_START); + + modifyreg32(I2S_CONF_REG(priv->config->port), 0, I2S_TX_START); + + sq_addlast((sq_entry_t *)bfcontainer, &priv->tx.act); + + return OK; +} +#endif /* I2S_HAVE_TX */ + +/**************************************************************************** + * Name: i2s_txdma_setup + * + * Description: + * Setup the next TX DMA transfer + * + * Input Parameters: + * priv - I2S state instance + * + * Returned Value: + * OK on success; a negated errno value on failure + * + * Assumptions: + * Interrupts are disabled + * + ****************************************************************************/ + +#ifdef I2S_HAVE_TX +static int i2s_txdma_setup(struct esp32_i2s_s *priv, + struct esp32_buffer_s *bfcontainer) +{ + struct ap_buffer_s *apb; + struct esp32_dmadesc_s *outlink; + uintptr_t samp; + apb_samp_t nbytes; + uint32_t bytes_queued; + + DEBUGASSERT(bfcontainer && bfcontainer->apb); + + apb = bfcontainer->apb; + outlink = bfcontainer->dma_outlink; + + /* Get the transfer information, accounting for any data offset */ + + samp = (uintptr_t)&apb->samp[apb->curbyte]; + nbytes = apb->nbytes - apb->curbyte; + + /* Configure DMA stream */ + + bytes_queued = esp32_dma_init_with_padding(outlink, I2S_DMADESC_NUM, + (uint8_t *)samp, nbytes, + &priv->stuff); + + if (bytes_queued != nbytes) + { + i2serr("Failed to enqueue I2S buffer (%d bytes of %d)\n", + bytes_queued, (uint32_t)nbytes); + return bytes_queued; + } + + /* Add the buffer container to the end of the TX pending queue */ + + sq_addlast((sq_entry_t *)bfcontainer, &priv->tx.pend); + + return OK; +} +#endif /* I2S_HAVE_TX */ + +/**************************************************************************** + * Name: i2s_tx_schedule + * + * Description: + * An TX DMA completion has occurred. Schedule processing on + * the working thread. + * + * Input Parameters: + * handle - The DMA handler + * arg - A pointer to the chip select struction + * result - The result of the DMA transfer + * + * Returned Value: + * None + * + * Assumptions: + * - Interrupts are disabled + * - The TX timeout has been canceled. + * + ****************************************************************************/ + +#ifdef I2S_HAVE_TX +static void i2s_tx_schedule(struct esp32_i2s_s *priv, + struct esp32_dmadesc_s *outlink) +{ + struct esp32_buffer_s *bfcontainer; + struct esp32_dmadesc_s *bfdesc; + int ret; + + /* Upon entry, the transfer(s) that just completed are the ones in the + * priv->tx.act queue. + */ + + /* Move all entries from the tx.act queue to the tx.done queue */ + + if (!sq_empty(&priv->tx.act)) + { + /* Remove the next buffer container from the tx.act list */ + + bfcontainer = (struct esp32_buffer_s *)sq_peek(&priv->tx.act); + + /* Check if the DMA descriptor that generated an EOF interrupt is the + * last descriptor of the current buffer container's DMA outlink. + * REVISIT: what to do if we miss syncronization and the descriptor + * that generated the interrupt is different from the expected (the + * oldest of the list containing active transmissions)? + */ + + /* Find the last descriptor of the current buffer container */ + + bfdesc = bfcontainer->dma_outlink; + while (!(bfdesc->ctrl & DMA_CTRL_EOF)) + { + DEBUGASSERT(bfdesc->next); + bfdesc = bfdesc->next; + } + + if (bfdesc == outlink) + { + sq_remfirst(&priv->tx.act); + + /* Report the result of the transfer */ + + bfcontainer->result = OK; + + /* Add the completed buffer container to the tail of the tx.done + * queue + */ + + sq_addlast((sq_entry_t *)bfcontainer, &priv->tx.done); + + /* Check if the DMA is IDLE */ + + if (sq_empty(&priv->tx.act)) + { + /* Then start the next DMA. */ + + i2s_txdma_start(priv); + } + } + + /* If the worker has completed running, then reschedule the working + * thread. + */ + + if (work_available(&priv->tx.work)) + { + /* Schedule the TX DMA done processing to occur on the worker + * thread. + */ + + ret = work_queue(HPWORK, &priv->tx.work, i2s_tx_worker, priv, 0); + if (ret != 0) + { + i2serr("ERROR: Failed to queue TX work: %d\n", ret); + } + } + } +} +#endif /* I2S_HAVE_TX */ + +/**************************************************************************** + * Name: i2s_tx_worker + * + * Description: + * TX transfer done worker + * + * Input Parameters: + * arg - the I2S device instance cast to void* + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef I2S_HAVE_TX +static void i2s_tx_worker(void *arg) +{ + struct esp32_i2s_s *priv = (struct esp32_i2s_s *)arg; + struct esp32_buffer_s *bfcontainer; + irqstate_t flags; + + DEBUGASSERT(priv); + + /* When the transfer was started, the active buffer containers were removed + * from the tx.pend queue and saved in the tx.act queue. We get here when + * the DMA is finished. + * + * In any case, the buffer containers in tx.act will be moved to the end + * of the tx.done queue and tx.act will be emptied before this worker is + * started. + * + */ + + i2sinfo("tx.act.head=%p tx.done.head=%p\n", + priv->tx.act.head, priv->tx.done.head); + + /* Process each buffer in the tx.done queue */ + + while (sq_peek(&priv->tx.done) != NULL) + { + /* Remove the buffer container from the tx.done queue. NOTE that + * interrupts must be disabled to do this because the tx.done queue is + * also modified from the interrupt level. + */ + + flags = spin_lock_irqsave(&priv->lock); + bfcontainer = (struct esp32_buffer_s *)sq_remfirst(&priv->tx.done); + spin_unlock_irqrestore(&priv->lock, flags); + + /* Perform the TX transfer done callback */ + + DEBUGASSERT(bfcontainer && bfcontainer->callback); + bfcontainer->callback(&priv->dev, bfcontainer->apb, + bfcontainer->arg, bfcontainer->result); + + /* Release our reference on the audio buffer. This may very likely + * cause the audio buffer to be freed. + */ + + apb_free(bfcontainer->apb); + + /* And release the buffer container */ + + i2s_buf_free(priv, bfcontainer); + } +} +#endif /* I2S_HAVE_TX */ + +/**************************************************************************** + * Name: i2s_configure + * + * Description: + * Configure I2S + * + * Input Parameters: + * priv - Partially initialized I2S device structure. This function + * will complete the I2S specific portions of the initialization + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void i2s_configure(struct esp32_i2s_s *priv) +{ + /* Set peripheral clock and clear reset */ + + modifyreg32(DPORT_PERIP_CLK_EN_REG, 0, DPORT_I2S0_CLK_EN); + modifyreg32(DPORT_PERIP_RST_EN_REG, 0, DPORT_I2S0_RST); + modifyreg32(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST, 0); + + /* I2S module general init, enable I2S clock */ + + if (!(getreg32(I2S_CLKM_CONF_REG(priv->config->port)) & I2S_CLK_ENA)) + { + i2sinfo("Enabling I2S port clock...\n"); + modifyreg32(I2S_CLKM_CONF_REG(priv->config->port), 0, I2S_CLK_ENA); + putreg32(0, I2S_CONF2_REG(priv->config->port)); + } + + /* Configure multiplexed pins as connected on the board */ + + /* TODO: check for loopback mode */ + + /* Enable TX channel */ + + if (priv->config->dout_pin != I2S_GPIO_UNUSED) + { + esp32_gpiowrite(priv->config->dout_pin, 1); + esp32_configgpio(priv->config->dout_pin, OUTPUT_FUNCTION_3); + esp32_gpio_matrix_out(priv->config->dout_pin, + priv->config->dout_outsig, 0, 0); + } + + /* TODO: repeat above function for RX channel */ + + if (priv->config->role == I2S_ROLE_SLAVE) + { + if (priv->config->tx_en && !priv->config->rx_en) + { + /* For "tx + slave" mode, select TX signal index for ws and bck */ + + esp32_gpiowrite(priv->config->ws_pin, 1); + esp32_configgpio(priv->config->ws_pin, INPUT_FUNCTION_3); + esp32_gpio_matrix_out(priv->config->ws_pin, + priv->config->ws_out_insig, 0, 0); + + esp32_gpiowrite(priv->config->bclk_pin, 1); + esp32_configgpio(priv->config->bclk_pin, INPUT_FUNCTION_3); + esp32_gpio_matrix_out(priv->config->bclk_pin, + priv->config->bclk_out_insig, 0, 0); + } + else + { + /* For "tx + rx + slave" or "rx + slave" mode, select RX signal + * index for ws and bck. + */ + + esp32_gpiowrite(priv->config->ws_pin, 1); + esp32_configgpio(priv->config->ws_pin, INPUT_FUNCTION_3); + esp32_gpio_matrix_out(priv->config->ws_pin, + priv->config->ws_in_insig, 0, 0); + + esp32_gpiowrite(priv->config->bclk_pin, 1); + esp32_configgpio(priv->config->bclk_pin, INPUT_FUNCTION_3); + esp32_gpio_matrix_out(priv->config->bclk_pin, + priv->config->bclk_in_insig, 0, 0); + } + } + else + { + /* Considering master role for the I2S port */ + + /* Set MCLK pin */ + + if (priv->config->mclk_pin != I2S_GPIO_UNUSED) + { + bool is_i2s0 = priv->config->port == ESP32_I2S0 ? true : false; + + i2sinfo("Configuring GPIO%" PRIu8 " to output master clock\n", + priv->config->mclk_pin); + + esp32_configgpio(priv->config->mclk_pin, OUTPUT_FUNCTION_2); + esp32_gpio_matrix_out(priv->config->mclk_pin, + SIG_GPIO_OUT_IDX, 0, 0); + + if (priv->config->mclk_pin == 0) + { + putreg32(priv->config->is_apll ? + 0xfff6 : (is_i2s0 ? 0xfff0 : 0xffff), PIN_CTRL); + } + else if (priv->config->mclk_pin == 1) + { + putreg32(priv->config->is_apll ? + 0xf6f6 : (is_i2s0 ? 0xf0f0 : 0xf0ff), PIN_CTRL); + } + else + { + putreg32(priv->config->is_apll ? + 0xff66 : (is_i2s0 ? 0xff00 : 0xff0f), PIN_CTRL); + } + } + + if (priv->config->rx_en && !priv->config->tx_en) + { + /* For "rx + master" mode, select RX signal index for ws and bck */ + + esp32_gpiowrite(priv->config->ws_pin, 1); + esp32_configgpio(priv->config->ws_pin, OUTPUT_FUNCTION_3); + esp32_gpio_matrix_out(priv->config->ws_pin, + priv->config->ws_in_outsig, 0, 0); + + esp32_gpiowrite(priv->config->bclk_pin, 1); + esp32_configgpio(priv->config->bclk_pin, OUTPUT_FUNCTION_3); + esp32_gpio_matrix_out(priv->config->bclk_pin, + priv->config->bclk_in_outsig, 0, 0); + } + else + { + /* For "tx + rx + master" or "tx + master" mode, select TX signal + * index for ws and bck. + */ + + esp32_gpiowrite(priv->config->ws_pin, 1); + esp32_configgpio(priv->config->ws_pin, OUTPUT_FUNCTION_3); + esp32_gpio_matrix_out(priv->config->ws_pin, + priv->config->ws_out_outsig, 0, 0); + + esp32_gpiowrite(priv->config->bclk_pin, 1); + esp32_configgpio(priv->config->bclk_pin, OUTPUT_FUNCTION_3); + esp32_gpio_matrix_out(priv->config->bclk_pin, + priv->config->bclk_out_outsig, 0, 0); + } + } + + /* TODO: share BCLK and WS if in full-duplex mode */ + + /* Configure the hardware to apply STD format */ + + if (priv->config->tx_en) + { + /* Reset I2S TX module */ + + modifyreg32(I2S_CONF_REG(priv->config->port), 0, I2S_TX_RESET); + modifyreg32(I2S_CONF_REG(priv->config->port), I2S_TX_RESET, 0); + modifyreg32(I2S_LC_CONF_REG(priv->config->port), 0, I2S_OUT_RST); + modifyreg32(I2S_LC_CONF_REG(priv->config->port), I2S_OUT_RST, 0); + + /* Enable/disable I2S TX slave mode */ + + if (priv->config->role == I2S_ROLE_SLAVE) + { + modifyreg32(I2S_CONF_REG(priv->config->port), 0, I2S_TX_SLAVE_MOD); + } + else + { + modifyreg32(I2S_CONF_REG(priv->config->port), I2S_TX_SLAVE_MOD, 0); + } + + /* Congfigure TX chan bit, audio data bit and mono mode. + * On ESP32, sample_bit should equals to data_bit + */ + + /* Set TX data width */ + + esp32_i2s_txdatawidth((struct i2s_dev_s *)priv, + priv->config->data_width); + + /* Set I2S tx chan mode */ + + modifyreg32(I2S_CONF_CHAN_REG(priv->config->port), I2S_TX_CHAN_MOD_M, + FIELD_TO_VALUE(I2S_TX_CHAN_MOD, priv->config->mono_en ? + 4 : 0)); + + /* Enable/disable TX MSB shift, the data will be launch at the first + * BCK clock. + */ + + if (priv->config->bit_shift) + { + modifyreg32(I2S_CONF_REG(priv->config->port), 0, I2S_TX_MSB_SHIFT); + } + else + { + modifyreg32(I2S_CONF_REG(priv->config->port), I2S_TX_MSB_SHIFT, 0); + } + + /* Configure TX WS signal width. Set to to enable transmitter in PCM + * standard mode. + */ + + if (priv->config->ws_width == 1) + { + modifyreg32(I2S_CONF_REG(priv->config->port), 0, + I2S_TX_SHORT_SYNC); + } + else + { + modifyreg32(I2S_CONF_REG(priv->config->port), + I2S_TX_SHORT_SYNC, 0); + } + + /* Set I2S tx right channel first */ + + if (priv->config->ws_pol == 1) + { + modifyreg32(I2S_CONF_REG(priv->config->port), 0, + I2S_TX_RIGHT_FIRST); + } + else + { + modifyreg32(I2S_CONF_REG(priv->config->port), + I2S_TX_RIGHT_FIRST, 0); + } + + /* I2S tx fifo module force enable */ + + modifyreg32(I2S_FIFO_CONF_REG(priv->config->port), 0, + I2S_TX_FIFO_MOD_FORCE_EN); + + esp32_i2s_txsamplerate((struct i2s_dev_s *)priv, priv->config->rate); + } + + /* TODO: check for rx enabled flag */ +} + +/**************************************************************************** + * Name: i2s_tx_channel_start + * + * Description: + * Start TX channel for the I2S port + * + * Input Parameters: + * priv - Initialized I2S device structure. + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef I2S_HAVE_TX +static void i2s_tx_channel_start(struct esp32_i2s_s *priv) +{ + /* Reset the TX channel */ + + modifyreg32(I2S_CONF_REG(priv->config->port), 0, I2S_TX_RESET); + modifyreg32(I2S_CONF_REG(priv->config->port), I2S_TX_RESET, 0); + + /* Reset the DMA operation */ + + modifyreg32(I2S_LC_CONF_REG(priv->config->port), 0, I2S_OUT_RST); + modifyreg32(I2S_LC_CONF_REG(priv->config->port), I2S_OUT_RST, 0); + + /* Reset TX FIFO */ + + modifyreg32(I2S_CONF_REG(priv->config->port), 0, I2S_TX_FIFO_RESET); + modifyreg32(I2S_CONF_REG(priv->config->port), I2S_TX_FIFO_RESET, 0); + + /* Enable DMA interruption */ + + up_enable_irq(priv->config->irq); + + modifyreg32(I2S_INT_ENA_REG(priv->config->port), UINT32_MAX, + I2S_OUT_EOF_INT_ENA); + + /* Enable DMA operation mode */ + + modifyreg32(I2S_FIFO_CONF_REG(priv->config->port), 0, I2S_DSCR_EN); + + /* Unset the DMA outlink */ + + putreg32(0, I2S_OUT_LINK_REG(priv->config->port)); + + i2sinfo("Started TX channel of port %d\n", priv->config->port); +} +#endif /* I2S_HAVE_TX */ + +/**************************************************************************** + * Name: esp32_i2s_interrupt + * + * Description: + * Common I2S DMA interrupt handler + * + * Input Parameters: + * arg - i2s controller private data + * + * Returned Value: + * Standard interrupt return value. + * + ****************************************************************************/ + +static int esp32_i2s_interrupt(int irq, void *context, void *arg) +{ + struct esp32_i2s_s *priv = (struct esp32_i2s_s *)arg; + struct esp32_dmadesc_s *cur = NULL; + + uint32_t status = getreg32(I2S_INT_ST_REG(priv->config->port)); + + putreg32(UINT32_MAX, I2S_INT_CLR_REG(priv->config->port)); + + if (status & I2S_OUT_EOF_INT_ST) + { + cur = (struct esp32_dmadesc_s *) + getreg32(I2S_OUT_EOF_DES_ADDR_REG(priv->config->port)); + + /* Schedule completion of the transfer to occur on the worker thread */ + + i2s_tx_schedule(priv, cur); + } + + return 0; +} + +/**************************************************************************** + * Name: esp32_i2s_txsamplerate + * + * Description: + * Set the I2S TX sample rate. NOTE: This will have no effect if (1) the + * driver does not support an I2S transmitter or if (2) the sample rate is + * driven by the I2S frame clock. This may also have unexpected side- + * effects of the TX sample is coupled with the RX sample rate. + * + * Input Parameters: + * dev - Device-specific state data + * rate - The I2S sample rate in samples (not bits) per second + * + * Returned Value: + * Returns the resulting bitrate + * + ****************************************************************************/ + +static uint32_t esp32_i2s_txsamplerate(struct i2s_dev_s *dev, uint32_t rate) +{ + struct esp32_i2s_s *priv = (struct esp32_i2s_s *)dev; + uint32_t bclk; + uint32_t mclk; + uint16_t bclk_div; + uint32_t sclk; + uint32_t mclk_div; + int ma; + int mb; + int denominator; + int numerator; + uint32_t regval; + uint32_t freq_diff; + + /* TODO: provide APLL clock support */ + + /* Disable APLL clock, I2S module will using PLL_D2_CLK(160M) as source + * clock. + */ + + modifyreg32(I2S_CLKM_CONF_REG(priv->config->port), I2S_CLKA_ENA, 0); + sclk = I2S_LL_BASE_CLK; + + /* fmclk = bck_div * fbclk = fsclk / (mclk_div + b / a) + * mclk_div is the I2S clock divider's integral value + * b is the fraction clock divider's numerator value + * a is the fraction clock divider's denominator value + */ + + if (priv->config->role == I2S_ROLE_MASTER) + { + bclk = rate * priv->config->total_slot * priv->data_width; + mclk = rate * priv->config->mclk_multiple; + bclk_div = mclk / bclk; + } + else + { + /* For slave mode, mclk >= bclk * 8, so fix bclk_div to 2 first */ + + bclk_div = 8; + bclk = rate * priv->config->total_slot * priv->data_width; + mclk = bclk * bclk_div; + } + + /* Calculate the nearest integer value of the I2S clock divider */ + + mclk_div = sclk / mclk; + + i2sinfo("Clock division info: [sclk]%"PRIu32" Hz [mdiv] %d " + "[mclk] %"PRIu32" Hz [bdiv] %d [bclk] %"PRIu32" Hz\n", + sclk, mclk_div, mclk, bclk_div, bclk); + + freq_diff = abs((int)sclk - (int)(mclk * mclk_div)); + + ma = 0; + mb = 0; + denominator = 1; + numerator = 0; + + if (freq_diff) + { + float decimal = freq_diff / (float)mclk; + + /* Carry bit if the decimal is greater than + * 1.0 - 1.0 / (63.0 * 2) = 125.0 / 126.0 + */ + + if (decimal > 125.0 / 126.0) + { + mclk_div++; + } + else + { + uint32_t min = ~0; + + for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) + { + int b = (int)(a * (freq_diff / (double)mclk) + 0.5); + ma = freq_diff * a; + mb = mclk * b; + if (ma == mb) + { + denominator = a; + numerator = b; + break; + } + + if (abs((mb - ma)) < min) + { + denominator = a; + numerator = b; + min = abs(mb - ma); + } + } + } + } + + i2sinfo("Clock register: [mclk] %"PRIu32" Hz [numerator] %d " + "[denominator] %d\n", mclk, numerator, denominator); + + regval = getreg32(I2S_CLKM_CONF_REG(priv->config->port)); + regval &= ~I2S_CLKM_DIV_NUM_M; + regval |= FIELD_TO_VALUE(I2S_CLKM_DIV_NUM, mclk_div); + regval &= ~I2S_CLKM_DIV_B_M; + regval |= FIELD_TO_VALUE(I2S_CLKM_DIV_B, numerator); + regval &= ~I2S_CLKM_DIV_A_M; + regval |= FIELD_TO_VALUE(I2S_CLKM_DIV_A, denominator); + putreg32(regval, I2S_CLKM_CONF_REG(priv->config->port)); + + /* Set I2S tx bck div num */ + + modifyreg32(I2S_SAMPLE_RATE_CONF_REG(priv->config->port), + I2S_TX_BCK_DIV_NUM_M, + FIELD_TO_VALUE(I2S_TX_BCK_DIV_NUM, bclk_div)); + + /* Returns the actual sample rate */ + + bclk = sclk / (float)((mclk_div + numerator / (float)denominator) * + bclk_div); + rate = bclk / (float)(priv->config->total_slot * priv->data_width); + + priv->rate = rate; + + return rate; +} + +/**************************************************************************** + * Name: esp32_i2s_txdatawidth + * + * Description: + * Set the I2S TX data width. The TX bitrate is determined by + * sample_rate * data_width. + * + * Input Parameters: + * dev - Device-specific state data + * width - The I2S data with in bits. + * + * Returned Value: + * Returns the resulting bitrate + * + ****************************************************************************/ + +static uint32_t esp32_i2s_txdatawidth(struct i2s_dev_s *dev, int bits) +{ + struct esp32_i2s_s *priv = (struct esp32_i2s_s *)dev; + + modifyreg32(I2S_SAMPLE_RATE_CONF_REG(priv->config->port), + I2S_TX_BITS_MOD_M, FIELD_TO_VALUE(I2S_TX_BITS_MOD, bits)); + + priv->data_width = bits; + + /* Set TX FIFO operation mode */ + + modifyreg32(I2S_FIFO_CONF_REG(priv->config->port), I2S_TX_FIFO_MOD_M, + priv->data_width <= I2S_DATA_BIT_WIDTH_16BIT ? + FIELD_TO_VALUE(I2S_TX_FIFO_MOD, 0 + priv->config->mono_en) : + FIELD_TO_VALUE(I2S_TX_FIFO_MOD, 2 + priv->config->mono_en)); + + /* I2S TX MSB right enable */ + + if (priv->data_width <= I2S_DATA_BIT_WIDTH_16BIT) + { + modifyreg32(I2S_CONF_REG(priv->config->port), 0, I2S_TX_MSB_RIGHT); + } + else + { + modifyreg32(I2S_CONF_REG(priv->config->port), I2S_TX_MSB_RIGHT, 0); + } + + return bits; +} + +/**************************************************************************** + * Name: esp32_i2s_send + * + * Description: + * Send a block of data on I2S. + * + * Input Parameters: + * dev - Device-specific state data + * apb - A pointer to the audio buffer from which to send data + * callback - A user provided callback function that will be called at + * the completion of the transfer. + * arg - An opaque argument that will be provided to the callback + * when the transfer complete + * timeout - The timeout value to use. The transfer will be cancelled + * and an ETIMEDOUT error will be reported if this timeout + * elapsed without completion of the DMA transfer. Units + * are system clock ticks. Zero means no timeout. + * + * Returned Value: + * OK on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int esp32_i2s_send(struct i2s_dev_s *dev, struct ap_buffer_s *apb, + i2s_callback_t callback, void *arg, + uint32_t timeout) +{ + struct esp32_i2s_s *priv = (struct esp32_i2s_s *)dev; + struct esp32_buffer_s *bfcontainer; + irqstate_t flags; + int ret = OK; + + /* Check audio buffer data size */ + + if ((apb->nbytes - apb->curbyte) > + (ESP32_DMA_DATALEN_MAX * (I2S_DMADESC_NUM - 1))) + { + return -EFBIG; + } + + /* Allocate a buffer container in advance */ + + bfcontainer = i2s_buf_allocate(priv); + DEBUGASSERT(bfcontainer); + + /* Get exclusive access to the I2S driver data */ + + ret = i2s_exclsem_take(priv); + if (ret < 0) + { + goto errout_with_buf; + } + + /* Add a reference to the audio buffer */ + + apb_reference(apb); + + /* Initialize the buffer container structure */ + + bfcontainer->callback = (void *)callback; + bfcontainer->timeout = timeout; + bfcontainer->arg = arg; + bfcontainer->apb = apb; + bfcontainer->result = -EBUSY; + + flags = spin_lock_irqsave(&priv->lock); + + ret = i2s_txdma_setup(priv, bfcontainer); + + if (ret != OK) + { + goto errout_with_buf; + } + + ret = i2s_txdma_start(priv); + + if (ret != OK) + { + goto errout_with_buf; + } + + i2sinfo("Queued %d bytes into DMA buffers\n", apb->nbytes); + i2s_dump_buffer("Audio pipeline buffer:", &apb->samp[apb->curbyte], + apb->nbytes - apb->curbyte); + + /* Trigger DMA transfer */ + + spin_unlock_irqrestore(&priv->lock, flags); + i2s_exclsem_give(priv); + + return OK; + +errout_with_buf: + i2s_exclsem_give(priv); + i2s_buf_free(priv, bfcontainer); + return ret; +} + +/**************************************************************************** + * Name: esp32_i2sdma_setup + * + * Description: + * Configure the DMA for the I2S peripheral + * + * Input Parameters: + * priv - Partially initialized I2S device structure. This function + * will complete the I2S specific portions of the initialization + * regarding the DMA operation. + * + * Returned Value: + * OK on success; A negated errno value on failure. + * + ****************************************************************************/ + +static int esp32_i2sdma_setup(struct esp32_i2s_s *priv) +{ + int ret; + + /* Clear the interrupts */ + + putreg32(UINT32_MAX, I2S_INT_CLR_REG(priv->config->port)); + + /* Set up to receive peripheral interrupts on the current CPU */ + + priv->cpu = up_cpu_index(); + priv->cpuint = esp32_setup_irq(priv->cpu, priv->config->periph, + 1, ESP32_CPUINT_LEVEL); + if (priv->cpuint < 0) + { + i2serr("Failed to allocate a CPU interrupt.\n"); + return priv->cpuint; + } + + ret = irq_attach(priv->config->irq, esp32_i2s_interrupt, priv); + if (ret != OK) + { + i2serr("Couldn't attach IRQ to handler.\n"); + esp32_teardown_irq(priv->cpu, + priv->config->periph, + priv->cpuint); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: esp32_i2sbus_initialize + * + * Description: + * Initialize the selected I2S port + * + * Input Parameters: + * Port number (for hardware that has multiple I2S interfaces) + * + * Returned Value: + * Valid I2S device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct i2s_dev_s *esp32_i2sbus_initialize(int port) +{ + int ret; + struct esp32_i2s_s *priv = NULL; + irqstate_t flags; + + i2sinfo("port: %d\n", port); + + /* Statically allocated I2S' device strucuture */ + + switch (port) + { +#ifdef CONFIG_ESP32_I2S0 + case ESP32_I2S0: + priv = &esp32_i2s0_priv; + break; +#endif +#ifdef CONFIG_ESP32_I2S1 + case ESP32_I2S1: + priv = &esp32_i2s1_priv; + break; +#endif + default: + return NULL; + } + + flags = spin_lock_irqsave(&priv->lock); + + nxsem_init(&priv->exclsem, 0, 1); + + i2s_configure(priv); + + /* Allocate buffer containers */ + + ret = i2s_buf_initialize(priv); + if (ret < 0) + { + goto err; + } + + ret = esp32_i2sdma_setup(priv); + if (ret < 0) + { + goto err; + } + +#ifdef I2S_HAVE_TX + /* Start TX channel */ + + i2s_tx_channel_start(priv); +#endif /* I2S_HAVE_TX */ + + spin_unlock_irqrestore(&priv->lock, flags); + + /* Success exit */ + + i2sinfo("I2S%d was successfully initialized\n", priv->config->port); + + return &priv->dev; + + /* Failure exit */ + +err: + spin_unlock_irqrestore(&priv->lock, flags); + nxsem_destroy(&priv->exclsem); + return NULL; +} + +#endif /* CONFIG_ESP32_I2S */ diff --git a/arch/xtensa/src/esp32/esp32_i2s.h b/arch/xtensa/src/esp32/esp32_i2s.h new file mode 100644 index 0000000000..6ee13bb279 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_i2s.h @@ -0,0 +1,80 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_i2s.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32_ESP32_I2S_H +#define __ARCH_XTENSA_SRC_ESP32_ESP32_I2S_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#ifdef CONFIG_ESP32_I2S + +#ifdef CONFIG_ESP32_I2S0 + #define ESP32_I2S0 0 +#endif /* CONFIG_ESP32_I2S0 */ + +#ifdef CONFIG_ESP32_I2S1 + #define ESP32_I2S1 1 +#endif /* CONFIG_ESP32_I2S1 */ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32_i2sbus_initialize + * + * Description: + * Initialize the selected I2S port + * + * Input Parameters: + * Port number (for hardware that has multiple I2S interfaces) + * + * Returned Value: + * Valid I2S device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct i2s_dev_s *esp32_i2sbus_initialize(int port); + +#endif /* CONFIG_ESP32_I2S */ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_I2S_H */ diff --git a/arch/xtensa/src/esp32/hardware/esp32_i2s.h b/arch/xtensa/src/esp32/hardware/esp32_i2s.h index 4acb1cef53..ca3d67cfc7 100644 --- a/arch/xtensa/src/esp32/hardware/esp32_i2s.h +++ b/arch/xtensa/src/esp32/hardware/esp32_i2s.h @@ -18,30 +18,2039 @@ * ****************************************************************************/ -/**************************************************************************** - * Included Files - ****************************************************************************/ - #ifndef __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_I2S_H #define __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_I2S_H -#include "esp32_soc.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ -#define REG_I2S_BASE( i ) (DR_REG_I2S_BASE + ((i)*0x1e000)) -#define I2S_PD_CONF_REG(i) (REG_I2S_BASE(i) + 0x00a4) +#define REG_I2S_BASE(i) (DR_REG_I2S_BASE + ((i)*0x1e000)) -/* I2S_PLC_MEM_FORCE_PU : R/W ;bitpos:[3] ;default: 1'h1 ; */ +/* I2S_CONF_REG register + * I2S Configure register + */ + +#define I2S_CONF_REG(i) (REG_I2S_BASE(i) + 0x8) + +/* I2S_SIG_LOOPBACK : R/W; bitpos: [18]; default: 0; + * Enable signal loopback mode with transmitter module and receiver module + * sharing the same WS and BCK signals. + */ + +#define I2S_SIG_LOOPBACK (BIT(18)) +#define I2S_SIG_LOOPBACK_M (I2S_SIG_LOOPBACK_V << I2S_SIG_LOOPBACK_S) +#define I2S_SIG_LOOPBACK_V 0x00000001 +#define I2S_SIG_LOOPBACK_S 18 + +/* I2S_RX_MSB_RIGHT : R/W; bitpos: [17]; default: 0; + * Set this bit to place right channel data at the MSB in the receive FIFO. + */ + +#define I2S_RX_MSB_RIGHT (BIT(17)) +#define I2S_RX_MSB_RIGHT_M (I2S_RX_MSB_RIGHT_V << I2S_RX_MSB_RIGHT_S) +#define I2S_RX_MSB_RIGHT_V 0x00000001 +#define I2S_RX_MSB_RIGHT_S 17 + +/* I2S_TX_MSB_RIGHT : R/W; bitpos: [16]; default: 0; + * Set this bit to place right channel data at the MSB in the transmit FIFO. + */ + +#define I2S_TX_MSB_RIGHT (BIT(16)) +#define I2S_TX_MSB_RIGHT_M (I2S_TX_MSB_RIGHT_V << I2S_TX_MSB_RIGHT_S) +#define I2S_TX_MSB_RIGHT_V 0x00000001 +#define I2S_TX_MSB_RIGHT_S 16 + +/* I2S_RX_MONO : R/W; bitpos: [15]; default: 0; + * Set this bit to enable receiver in mono mode + */ + +#define I2S_RX_MONO (BIT(15)) +#define I2S_RX_MONO_M (I2S_RX_MONO_V << I2S_RX_MONO_S) +#define I2S_RX_MONO_V 0x00000001 +#define I2S_RX_MONO_S 15 + +/* I2S_TX_MONO : R/W; bitpos: [14]; default: 0; + * Set this bit to enable transmitter in mono mode + */ + +#define I2S_TX_MONO (BIT(14)) +#define I2S_TX_MONO_M (I2S_TX_MONO_V << I2S_TX_MONO_S) +#define I2S_TX_MONO_V 0x00000001 +#define I2S_TX_MONO_S 14 + +/* I2S_RX_SHORT_SYNC : R/W; bitpos: [13]; default: 0; + * Set this bit to enable receiver in PCM standard mode + */ + +#define I2S_RX_SHORT_SYNC (BIT(13)) +#define I2S_RX_SHORT_SYNC_M (I2S_RX_SHORT_SYNC_V << I2S_RX_SHORT_SYNC_S) +#define I2S_RX_SHORT_SYNC_V 0x00000001 +#define I2S_RX_SHORT_SYNC_S 13 + +/* I2S_TX_SHORT_SYNC : R/W; bitpos: [12]; default: 0; + * Set this bit to enable transmitter in PCM standard mode + */ + +#define I2S_TX_SHORT_SYNC (BIT(12)) +#define I2S_TX_SHORT_SYNC_M (I2S_TX_SHORT_SYNC_V << I2S_TX_SHORT_SYNC_S) +#define I2S_TX_SHORT_SYNC_V 0x00000001 +#define I2S_TX_SHORT_SYNC_S 12 + +/* I2S_RX_MSB_SHIFT : R/W; bitpos: [11]; default: 0; + * Set this bit to enable receiver in Phillips standard mode + */ + +#define I2S_RX_MSB_SHIFT (BIT(11)) +#define I2S_RX_MSB_SHIFT_M (I2S_RX_MSB_SHIFT_V << I2S_RX_MSB_SHIFT_S) +#define I2S_RX_MSB_SHIFT_V 0x00000001 +#define I2S_RX_MSB_SHIFT_S 11 + +/* I2S_TX_MSB_SHIFT : R/W; bitpos: [10]; default: 0; + * Set this bit to enable transmitter in Phillips standard mode + */ + +#define I2S_TX_MSB_SHIFT (BIT(10)) +#define I2S_TX_MSB_SHIFT_M (I2S_TX_MSB_SHIFT_V << I2S_TX_MSB_SHIFT_S) +#define I2S_TX_MSB_SHIFT_V 0x00000001 +#define I2S_TX_MSB_SHIFT_S 10 + +/* I2S_RX_RIGHT_FIRST : R/W; bitpos: [9]; default: 1; + * Set this bit to receive right channel data first + */ + +#define I2S_RX_RIGHT_FIRST (BIT(9)) +#define I2S_RX_RIGHT_FIRST_M (I2S_RX_RIGHT_FIRST_V << I2S_RX_RIGHT_FIRST_S) +#define I2S_RX_RIGHT_FIRST_V 0x00000001 +#define I2S_RX_RIGHT_FIRST_S 9 + +/* I2S_TX_RIGHT_FIRST : R/W; bitpos: [8]; default: 1; + * Set this bit to transmit right channel data first + */ + +#define I2S_TX_RIGHT_FIRST (BIT(8)) +#define I2S_TX_RIGHT_FIRST_M (I2S_TX_RIGHT_FIRST_V << I2S_TX_RIGHT_FIRST_S) +#define I2S_TX_RIGHT_FIRST_V 0x00000001 +#define I2S_TX_RIGHT_FIRST_S 8 + +/* I2S_RX_SLAVE_MOD : R/W; bitpos: [7]; default: 0; + * Set this bit to enable slave receiver mode + */ + +#define I2S_RX_SLAVE_MOD (BIT(7)) +#define I2S_RX_SLAVE_MOD_M (I2S_RX_SLAVE_MOD_V << I2S_RX_SLAVE_MOD_S) +#define I2S_RX_SLAVE_MOD_V 0x00000001 +#define I2S_RX_SLAVE_MOD_S 7 + +/* I2S_TX_SLAVE_MOD : R/W; bitpos: [6]; default: 0; + * Set this bit to enable slave transmitter mode + */ + +#define I2S_TX_SLAVE_MOD (BIT(6)) +#define I2S_TX_SLAVE_MOD_M (I2S_TX_SLAVE_MOD_V << I2S_TX_SLAVE_MOD_S) +#define I2S_TX_SLAVE_MOD_V 0x00000001 +#define I2S_TX_SLAVE_MOD_S 6 + +/* I2S_RX_START : R/W; bitpos: [5]; default: 0; + * Set this bit to start receiving data + */ + +#define I2S_RX_START (BIT(5)) +#define I2S_RX_START_M (I2S_RX_START_V << I2S_RX_START_S) +#define I2S_RX_START_V 0x00000001 +#define I2S_RX_START_S 5 + +/* I2S_TX_START : R/W; bitpos: [4]; default: 0; + * Set this bit to start transmitting data + */ + +#define I2S_TX_START (BIT(4)) +#define I2S_TX_START_M (I2S_TX_START_V << I2S_TX_START_S) +#define I2S_TX_START_V 0x00000001 +#define I2S_TX_START_S 4 + +/* I2S_RX_FIFO_RESET : WO; bitpos: [3]; default: 0; + * Set this bit to reset rxFIFO + */ + +#define I2S_RX_FIFO_RESET (BIT(3)) +#define I2S_RX_FIFO_RESET_M (I2S_RX_FIFO_RESET_V << I2S_RX_FIFO_RESET_S) +#define I2S_RX_FIFO_RESET_V 0x00000001 +#define I2S_RX_FIFO_RESET_S 3 + +/* I2S_TX_FIFO_RESET : WO; bitpos: [2]; default: 0; + * Set this bit to reset txFIFO + */ + +#define I2S_TX_FIFO_RESET (BIT(2)) +#define I2S_TX_FIFO_RESET_M (I2S_TX_FIFO_RESET_V << I2S_TX_FIFO_RESET_S) +#define I2S_TX_FIFO_RESET_V 0x00000001 +#define I2S_TX_FIFO_RESET_S 2 + +/* I2S_RX_RESET : WO; bitpos: [1]; default: 0; + * Set this bit to reset receiver + */ + +#define I2S_RX_RESET (BIT(1)) +#define I2S_RX_RESET_M (I2S_RX_RESET_V << I2S_RX_RESET_S) +#define I2S_RX_RESET_V 0x00000001 +#define I2S_RX_RESET_S 1 + +/* I2S_TX_RESET : WO; bitpos: [0]; default: 0; + * Set this bit to reset transmitter + */ + +#define I2S_TX_RESET (BIT(0)) +#define I2S_TX_RESET_M (I2S_TX_RESET_V << I2S_TX_RESET_S) +#define I2S_TX_RESET_V 0x00000001 +#define I2S_TX_RESET_S 0 + +/* I2S_INT_RAW_REG register + * Raw interrupt status + */ + +#define I2S_INT_RAW_REG(i) (REG_I2S_BASE(i) + 0xc) + +/* I2S_OUT_TOTAL_EOF_INT_RAW : RO; bitpos: [16]; default: 0; + * The raw interrupt status bit for the i2s_out_total_eof_int interrupt + */ + +#define I2S_OUT_TOTAL_EOF_INT_RAW (BIT(16)) +#define I2S_OUT_TOTAL_EOF_INT_RAW_M (I2S_OUT_TOTAL_EOF_INT_RAW_V << I2S_OUT_TOTAL_EOF_INT_RAW_S) +#define I2S_OUT_TOTAL_EOF_INT_RAW_V 0x00000001 +#define I2S_OUT_TOTAL_EOF_INT_RAW_S 16 + +/* I2S_IN_DSCR_EMPTY_INT_RAW : RO; bitpos: [15]; default: 0; + * The raw interrupt status bit for the i2s_in_dscr_empty_int interrupt + */ + +#define I2S_IN_DSCR_EMPTY_INT_RAW (BIT(15)) +#define I2S_IN_DSCR_EMPTY_INT_RAW_M (I2S_IN_DSCR_EMPTY_INT_RAW_V << I2S_IN_DSCR_EMPTY_INT_RAW_S) +#define I2S_IN_DSCR_EMPTY_INT_RAW_V 0x00000001 +#define I2S_IN_DSCR_EMPTY_INT_RAW_S 15 + +/* I2S_OUT_DSCR_ERR_INT_RAW : RO; bitpos: [14]; default: 0; + * The raw interrupt status bit for the i2s_out_dscr_err_int interrupt + */ + +#define I2S_OUT_DSCR_ERR_INT_RAW (BIT(14)) +#define I2S_OUT_DSCR_ERR_INT_RAW_M (I2S_OUT_DSCR_ERR_INT_RAW_V << I2S_OUT_DSCR_ERR_INT_RAW_S) +#define I2S_OUT_DSCR_ERR_INT_RAW_V 0x00000001 +#define I2S_OUT_DSCR_ERR_INT_RAW_S 14 + +/* I2S_IN_DSCR_ERR_INT_RAW : RO; bitpos: [13]; default: 0; + * The raw interrupt status bit for the i2s_in_dscr_err_int interrupt + */ + +#define I2S_IN_DSCR_ERR_INT_RAW (BIT(13)) +#define I2S_IN_DSCR_ERR_INT_RAW_M (I2S_IN_DSCR_ERR_INT_RAW_V << I2S_IN_DSCR_ERR_INT_RAW_S) +#define I2S_IN_DSCR_ERR_INT_RAW_V 0x00000001 +#define I2S_IN_DSCR_ERR_INT_RAW_S 13 + +/* I2S_OUT_EOF_INT_RAW : RO; bitpos: [12]; default: 0; + * The raw interrupt status bit for the i2s_out_eof_int interrupt + */ + +#define I2S_OUT_EOF_INT_RAW (BIT(12)) +#define I2S_OUT_EOF_INT_RAW_M (I2S_OUT_EOF_INT_RAW_V << I2S_OUT_EOF_INT_RAW_S) +#define I2S_OUT_EOF_INT_RAW_V 0x00000001 +#define I2S_OUT_EOF_INT_RAW_S 12 + +/* I2S_OUT_DONE_INT_RAW : RO; bitpos: [11]; default: 0; + * The raw interrupt status bit for the i2s_out_done_int interrupt + */ + +#define I2S_OUT_DONE_INT_RAW (BIT(11)) +#define I2S_OUT_DONE_INT_RAW_M (I2S_OUT_DONE_INT_RAW_V << I2S_OUT_DONE_INT_RAW_S) +#define I2S_OUT_DONE_INT_RAW_V 0x00000001 +#define I2S_OUT_DONE_INT_RAW_S 11 + +/* I2S_IN_ERR_EOF_INT_RAW : RO; bitpos: [10]; default: 0; + * don't use + */ + +#define I2S_IN_ERR_EOF_INT_RAW (BIT(10)) +#define I2S_IN_ERR_EOF_INT_RAW_M (I2S_IN_ERR_EOF_INT_RAW_V << I2S_IN_ERR_EOF_INT_RAW_S) +#define I2S_IN_ERR_EOF_INT_RAW_V 0x00000001 +#define I2S_IN_ERR_EOF_INT_RAW_S 10 + +/* I2S_IN_SUC_EOF_INT_RAW : RO; bitpos: [9]; default: 0; + * The raw interrupt status bit for the i2s_in_suc_eof_int interrupt + */ + +#define I2S_IN_SUC_EOF_INT_RAW (BIT(9)) +#define I2S_IN_SUC_EOF_INT_RAW_M (I2S_IN_SUC_EOF_INT_RAW_V << I2S_IN_SUC_EOF_INT_RAW_S) +#define I2S_IN_SUC_EOF_INT_RAW_V 0x00000001 +#define I2S_IN_SUC_EOF_INT_RAW_S 9 + +/* I2S_IN_DONE_INT_RAW : RO; bitpos: [8]; default: 0; + * The raw interrupt status bit for the i2s_in_done_int interrupt + */ + +#define I2S_IN_DONE_INT_RAW (BIT(8)) +#define I2S_IN_DONE_INT_RAW_M (I2S_IN_DONE_INT_RAW_V << I2S_IN_DONE_INT_RAW_S) +#define I2S_IN_DONE_INT_RAW_V 0x00000001 +#define I2S_IN_DONE_INT_RAW_S 8 + +/* I2S_TX_HUNG_INT_RAW : RO; bitpos: [7]; default: 0; + * The raw interrupt status bit for the i2s_tx_hung_int interrupt + */ + +#define I2S_TX_HUNG_INT_RAW (BIT(7)) +#define I2S_TX_HUNG_INT_RAW_M (I2S_TX_HUNG_INT_RAW_V << I2S_TX_HUNG_INT_RAW_S) +#define I2S_TX_HUNG_INT_RAW_V 0x00000001 +#define I2S_TX_HUNG_INT_RAW_S 7 + +/* I2S_RX_HUNG_INT_RAW : RO; bitpos: [6]; default: 0; + * The raw interrupt status bit for the i2s_rx_hung_int interrupt + */ + +#define I2S_RX_HUNG_INT_RAW (BIT(6)) +#define I2S_RX_HUNG_INT_RAW_M (I2S_RX_HUNG_INT_RAW_V << I2S_RX_HUNG_INT_RAW_S) +#define I2S_RX_HUNG_INT_RAW_V 0x00000001 +#define I2S_RX_HUNG_INT_RAW_S 6 + +/* I2S_TX_REMPTY_INT_RAW : RO; bitpos: [5]; default: 0; + * The raw interrupt status bit for the i2s_tx_rempty_int interrupt + */ + +#define I2S_TX_REMPTY_INT_RAW (BIT(5)) +#define I2S_TX_REMPTY_INT_RAW_M (I2S_TX_REMPTY_INT_RAW_V << I2S_TX_REMPTY_INT_RAW_S) +#define I2S_TX_REMPTY_INT_RAW_V 0x00000001 +#define I2S_TX_REMPTY_INT_RAW_S 5 + +/* I2S_TX_WFULL_INT_RAW : RO; bitpos: [4]; default: 0; + * The raw interrupt status bit for the i2s_tx_wfull_int interrupt + */ + +#define I2S_TX_WFULL_INT_RAW (BIT(4)) +#define I2S_TX_WFULL_INT_RAW_M (I2S_TX_WFULL_INT_RAW_V << I2S_TX_WFULL_INT_RAW_S) +#define I2S_TX_WFULL_INT_RAW_V 0x00000001 +#define I2S_TX_WFULL_INT_RAW_S 4 + +/* I2S_RX_REMPTY_INT_RAW : RO; bitpos: [3]; default: 0; + * The raw interrupt status bit for the i2s_rx_rempty_int interrupt + */ + +#define I2S_RX_REMPTY_INT_RAW (BIT(3)) +#define I2S_RX_REMPTY_INT_RAW_M (I2S_RX_REMPTY_INT_RAW_V << I2S_RX_REMPTY_INT_RAW_S) +#define I2S_RX_REMPTY_INT_RAW_V 0x00000001 +#define I2S_RX_REMPTY_INT_RAW_S 3 + +/* I2S_RX_WFULL_INT_RAW : RO; bitpos: [2]; default: 0; + * The raw interrupt status bit for the i2s_rx_wfull_int interrupt + */ + +#define I2S_RX_WFULL_INT_RAW (BIT(2)) +#define I2S_RX_WFULL_INT_RAW_M (I2S_RX_WFULL_INT_RAW_V << I2S_RX_WFULL_INT_RAW_S) +#define I2S_RX_WFULL_INT_RAW_V 0x00000001 +#define I2S_RX_WFULL_INT_RAW_S 2 + +/* I2S_TX_PUT_DATA_INT_RAW : RO; bitpos: [1]; default: 0; + * The raw interrupt status bit for the i2s_tx_put_data_int interrupt + */ + +#define I2S_TX_PUT_DATA_INT_RAW (BIT(1)) +#define I2S_TX_PUT_DATA_INT_RAW_M (I2S_TX_PUT_DATA_INT_RAW_V << I2S_TX_PUT_DATA_INT_RAW_S) +#define I2S_TX_PUT_DATA_INT_RAW_V 0x00000001 +#define I2S_TX_PUT_DATA_INT_RAW_S 1 + +/* I2S_RX_TAKE_DATA_INT_RAW : RO; bitpos: [0]; default: 0; + * The raw interrupt status bit for the i2s_rx_take_data_int interrupt + */ + +#define I2S_RX_TAKE_DATA_INT_RAW (BIT(0)) +#define I2S_RX_TAKE_DATA_INT_RAW_M (I2S_RX_TAKE_DATA_INT_RAW_V << I2S_RX_TAKE_DATA_INT_RAW_S) +#define I2S_RX_TAKE_DATA_INT_RAW_V 0x00000001 +#define I2S_RX_TAKE_DATA_INT_RAW_S 0 + +/* I2S_INT_ST_REG register + * Masked interrupt status + */ + +#define I2S_INT_ST_REG(i) (REG_I2S_BASE(i) + 0x10) + +/* I2S_OUT_TOTAL_EOF_INT_ST : RO; bitpos: [16]; default: 0; + * The masked interrupt status bit for the i2s_out_total_eof_int interrupt + */ + +#define I2S_OUT_TOTAL_EOF_INT_ST (BIT(16)) +#define I2S_OUT_TOTAL_EOF_INT_ST_M (I2S_OUT_TOTAL_EOF_INT_ST_V << I2S_OUT_TOTAL_EOF_INT_ST_S) +#define I2S_OUT_TOTAL_EOF_INT_ST_V 0x00000001 +#define I2S_OUT_TOTAL_EOF_INT_ST_S 16 + +/* I2S_IN_DSCR_EMPTY_INT_ST : RO; bitpos: [15]; default: 0; + * The masked interrupt status bit for the i2s_in_dscr_empty_int interrupt + */ + +#define I2S_IN_DSCR_EMPTY_INT_ST (BIT(15)) +#define I2S_IN_DSCR_EMPTY_INT_ST_M (I2S_IN_DSCR_EMPTY_INT_ST_V << I2S_IN_DSCR_EMPTY_INT_ST_S) +#define I2S_IN_DSCR_EMPTY_INT_ST_V 0x00000001 +#define I2S_IN_DSCR_EMPTY_INT_ST_S 15 + +/* I2S_OUT_DSCR_ERR_INT_ST : RO; bitpos: [14]; default: 0; + * The masked interrupt status bit for the i2s_out_dscr_err_int interrupt + */ + +#define I2S_OUT_DSCR_ERR_INT_ST (BIT(14)) +#define I2S_OUT_DSCR_ERR_INT_ST_M (I2S_OUT_DSCR_ERR_INT_ST_V << I2S_OUT_DSCR_ERR_INT_ST_S) +#define I2S_OUT_DSCR_ERR_INT_ST_V 0x00000001 +#define I2S_OUT_DSCR_ERR_INT_ST_S 14 + +/* I2S_IN_DSCR_ERR_INT_ST : RO; bitpos: [13]; default: 0; + * The masked interrupt status bit for the i2s_in_dscr_err_int interrupt + */ + +#define I2S_IN_DSCR_ERR_INT_ST (BIT(13)) +#define I2S_IN_DSCR_ERR_INT_ST_M (I2S_IN_DSCR_ERR_INT_ST_V << I2S_IN_DSCR_ERR_INT_ST_S) +#define I2S_IN_DSCR_ERR_INT_ST_V 0x00000001 +#define I2S_IN_DSCR_ERR_INT_ST_S 13 + +/* I2S_OUT_EOF_INT_ST : RO; bitpos: [12]; default: 0; + * The masked interrupt status bit for the i2s_out_eof_int interrupt + */ + +#define I2S_OUT_EOF_INT_ST (BIT(12)) +#define I2S_OUT_EOF_INT_ST_M (I2S_OUT_EOF_INT_ST_V << I2S_OUT_EOF_INT_ST_S) +#define I2S_OUT_EOF_INT_ST_V 0x00000001 +#define I2S_OUT_EOF_INT_ST_S 12 + +/* I2S_OUT_DONE_INT_ST : RO; bitpos: [11]; default: 0; + * The masked interrupt status bit for the i2s_out_done_int interrupt + */ + +#define I2S_OUT_DONE_INT_ST (BIT(11)) +#define I2S_OUT_DONE_INT_ST_M (I2S_OUT_DONE_INT_ST_V << I2S_OUT_DONE_INT_ST_S) +#define I2S_OUT_DONE_INT_ST_V 0x00000001 +#define I2S_OUT_DONE_INT_ST_S 11 + +/* I2S_IN_ERR_EOF_INT_ST : RO; bitpos: [10]; default: 0; + * don't use + */ + +#define I2S_IN_ERR_EOF_INT_ST (BIT(10)) +#define I2S_IN_ERR_EOF_INT_ST_M (I2S_IN_ERR_EOF_INT_ST_V << I2S_IN_ERR_EOF_INT_ST_S) +#define I2S_IN_ERR_EOF_INT_ST_V 0x00000001 +#define I2S_IN_ERR_EOF_INT_ST_S 10 + +/* I2S_IN_SUC_EOF_INT_ST : RO; bitpos: [9]; default: 0; + * The masked interrupt status bit for the i2s_in_suc_eof_int interrupt + */ + +#define I2S_IN_SUC_EOF_INT_ST (BIT(9)) +#define I2S_IN_SUC_EOF_INT_ST_M (I2S_IN_SUC_EOF_INT_ST_V << I2S_IN_SUC_EOF_INT_ST_S) +#define I2S_IN_SUC_EOF_INT_ST_V 0x00000001 +#define I2S_IN_SUC_EOF_INT_ST_S 9 + +/* I2S_IN_DONE_INT_ST : RO; bitpos: [8]; default: 0; + * The masked interrupt status bit for the i2s_in_done_int interrupt + */ + +#define I2S_IN_DONE_INT_ST (BIT(8)) +#define I2S_IN_DONE_INT_ST_M (I2S_IN_DONE_INT_ST_V << I2S_IN_DONE_INT_ST_S) +#define I2S_IN_DONE_INT_ST_V 0x00000001 +#define I2S_IN_DONE_INT_ST_S 8 + +/* I2S_TX_HUNG_INT_ST : RO; bitpos: [7]; default: 0; + * The masked interrupt status bit for the i2s_tx_hung_int interrupt + */ + +#define I2S_TX_HUNG_INT_ST (BIT(7)) +#define I2S_TX_HUNG_INT_ST_M (I2S_TX_HUNG_INT_ST_V << I2S_TX_HUNG_INT_ST_S) +#define I2S_TX_HUNG_INT_ST_V 0x00000001 +#define I2S_TX_HUNG_INT_ST_S 7 + +/* I2S_RX_HUNG_INT_ST : RO; bitpos: [6]; default: 0; + * The masked interrupt status bit for the i2s_rx_hung_int interrupt + */ + +#define I2S_RX_HUNG_INT_ST (BIT(6)) +#define I2S_RX_HUNG_INT_ST_M (I2S_RX_HUNG_INT_ST_V << I2S_RX_HUNG_INT_ST_S) +#define I2S_RX_HUNG_INT_ST_V 0x00000001 +#define I2S_RX_HUNG_INT_ST_S 6 + +/* I2S_TX_REMPTY_INT_ST : RO; bitpos: [5]; default: 0; + * The masked interrupt status bit for the i2s_tx_rempty_int interrupt + */ + +#define I2S_TX_REMPTY_INT_ST (BIT(5)) +#define I2S_TX_REMPTY_INT_ST_M (I2S_TX_REMPTY_INT_ST_V << I2S_TX_REMPTY_INT_ST_S) +#define I2S_TX_REMPTY_INT_ST_V 0x00000001 +#define I2S_TX_REMPTY_INT_ST_S 5 + +/* I2S_TX_WFULL_INT_ST : RO; bitpos: [4]; default: 0; + * The masked interrupt status bit for the i2s_tx_wfull_int interrupt + */ + +#define I2S_TX_WFULL_INT_ST (BIT(4)) +#define I2S_TX_WFULL_INT_ST_M (I2S_TX_WFULL_INT_ST_V << I2S_TX_WFULL_INT_ST_S) +#define I2S_TX_WFULL_INT_ST_V 0x00000001 +#define I2S_TX_WFULL_INT_ST_S 4 + +/* I2S_RX_REMPTY_INT_ST : RO; bitpos: [3]; default: 0; + * The masked interrupt status bit for the i2s_rx_rempty_int interrupt + */ + +#define I2S_RX_REMPTY_INT_ST (BIT(3)) +#define I2S_RX_REMPTY_INT_ST_M (I2S_RX_REMPTY_INT_ST_V << I2S_RX_REMPTY_INT_ST_S) +#define I2S_RX_REMPTY_INT_ST_V 0x00000001 +#define I2S_RX_REMPTY_INT_ST_S 3 + +/* I2S_RX_WFULL_INT_ST : RO; bitpos: [2]; default: 0; + * The masked interrupt status bit for the i2s_rx_wfull_int interrupt + */ + +#define I2S_RX_WFULL_INT_ST (BIT(2)) +#define I2S_RX_WFULL_INT_ST_M (I2S_RX_WFULL_INT_ST_V << I2S_RX_WFULL_INT_ST_S) +#define I2S_RX_WFULL_INT_ST_V 0x00000001 +#define I2S_RX_WFULL_INT_ST_S 2 + +/* I2S_TX_PUT_DATA_INT_ST : RO; bitpos: [1]; default: 0; + * The masked interrupt status bit for the i2s_tx_put_data_int interrupt + */ + +#define I2S_TX_PUT_DATA_INT_ST (BIT(1)) +#define I2S_TX_PUT_DATA_INT_ST_M (I2S_TX_PUT_DATA_INT_ST_V << I2S_TX_PUT_DATA_INT_ST_S) +#define I2S_TX_PUT_DATA_INT_ST_V 0x00000001 +#define I2S_TX_PUT_DATA_INT_ST_S 1 + +/* I2S_RX_TAKE_DATA_INT_ST : RO; bitpos: [0]; default: 0; + * The masked interrupt status bit for the i2s_rx_take_data_int interrupt + */ + +#define I2S_RX_TAKE_DATA_INT_ST (BIT(0)) +#define I2S_RX_TAKE_DATA_INT_ST_M (I2S_RX_TAKE_DATA_INT_ST_V << I2S_RX_TAKE_DATA_INT_ST_S) +#define I2S_RX_TAKE_DATA_INT_ST_V 0x00000001 +#define I2S_RX_TAKE_DATA_INT_ST_S 0 + +/* I2S_INT_ENA_REG register + * Interrupt enable bits + */ + +#define I2S_INT_ENA_REG(i) (REG_I2S_BASE(i) + 0x14) + +/* I2S_OUT_TOTAL_EOF_INT_ENA : R/W; bitpos: [16]; default: 0; + * The interrupt enable bit for the i2s_out_total_eof_int interrupt + */ + +#define I2S_OUT_TOTAL_EOF_INT_ENA (BIT(16)) +#define I2S_OUT_TOTAL_EOF_INT_ENA_M (I2S_OUT_TOTAL_EOF_INT_ENA_V << I2S_OUT_TOTAL_EOF_INT_ENA_S) +#define I2S_OUT_TOTAL_EOF_INT_ENA_V 0x00000001 +#define I2S_OUT_TOTAL_EOF_INT_ENA_S 16 + +/* I2S_IN_DSCR_EMPTY_INT_ENA : R/W; bitpos: [15]; default: 0; + * The interrupt enable bit for the i2s_in_dscr_empty_int interrupt + */ + +#define I2S_IN_DSCR_EMPTY_INT_ENA (BIT(15)) +#define I2S_IN_DSCR_EMPTY_INT_ENA_M (I2S_IN_DSCR_EMPTY_INT_ENA_V << I2S_IN_DSCR_EMPTY_INT_ENA_S) +#define I2S_IN_DSCR_EMPTY_INT_ENA_V 0x00000001 +#define I2S_IN_DSCR_EMPTY_INT_ENA_S 15 + +/* I2S_OUT_DSCR_ERR_INT_ENA : R/W; bitpos: [14]; default: 0; + * The interrupt enable bit for the i2s_out_dscr_err_int interrupt + */ + +#define I2S_OUT_DSCR_ERR_INT_ENA (BIT(14)) +#define I2S_OUT_DSCR_ERR_INT_ENA_M (I2S_OUT_DSCR_ERR_INT_ENA_V << I2S_OUT_DSCR_ERR_INT_ENA_S) +#define I2S_OUT_DSCR_ERR_INT_ENA_V 0x00000001 +#define I2S_OUT_DSCR_ERR_INT_ENA_S 14 + +/* I2S_IN_DSCR_ERR_INT_ENA : R/W; bitpos: [13]; default: 0; + * The interrupt enable bit for the i2s_in_dscr_err_int interrupt + */ + +#define I2S_IN_DSCR_ERR_INT_ENA (BIT(13)) +#define I2S_IN_DSCR_ERR_INT_ENA_M (I2S_IN_DSCR_ERR_INT_ENA_V << I2S_IN_DSCR_ERR_INT_ENA_S) +#define I2S_IN_DSCR_ERR_INT_ENA_V 0x00000001 +#define I2S_IN_DSCR_ERR_INT_ENA_S 13 + +/* I2S_OUT_EOF_INT_ENA : R/W; bitpos: [12]; default: 0; + * The interrupt enable bit for the i2s_out_eof_int interrupt + */ + +#define I2S_OUT_EOF_INT_ENA (BIT(12)) +#define I2S_OUT_EOF_INT_ENA_M (I2S_OUT_EOF_INT_ENA_V << I2S_OUT_EOF_INT_ENA_S) +#define I2S_OUT_EOF_INT_ENA_V 0x00000001 +#define I2S_OUT_EOF_INT_ENA_S 12 + +/* I2S_OUT_DONE_INT_ENA : R/W; bitpos: [11]; default: 0; + * The interrupt enable bit for the i2s_out_done_int interrupt + */ + +#define I2S_OUT_DONE_INT_ENA (BIT(11)) +#define I2S_OUT_DONE_INT_ENA_M (I2S_OUT_DONE_INT_ENA_V << I2S_OUT_DONE_INT_ENA_S) +#define I2S_OUT_DONE_INT_ENA_V 0x00000001 +#define I2S_OUT_DONE_INT_ENA_S 11 + +/* I2S_IN_ERR_EOF_INT_ENA : R/W; bitpos: [10]; default: 0; + * don't use + */ + +#define I2S_IN_ERR_EOF_INT_ENA (BIT(10)) +#define I2S_IN_ERR_EOF_INT_ENA_M (I2S_IN_ERR_EOF_INT_ENA_V << I2S_IN_ERR_EOF_INT_ENA_S) +#define I2S_IN_ERR_EOF_INT_ENA_V 0x00000001 +#define I2S_IN_ERR_EOF_INT_ENA_S 10 + +/* I2S_IN_SUC_EOF_INT_ENA : R/W; bitpos: [9]; default: 0; + * The interrupt enable bit for the i2s_in_suc_eof_int interrupt + */ + +#define I2S_IN_SUC_EOF_INT_ENA (BIT(9)) +#define I2S_IN_SUC_EOF_INT_ENA_M (I2S_IN_SUC_EOF_INT_ENA_V << I2S_IN_SUC_EOF_INT_ENA_S) +#define I2S_IN_SUC_EOF_INT_ENA_V 0x00000001 +#define I2S_IN_SUC_EOF_INT_ENA_S 9 + +/* I2S_IN_DONE_INT_ENA : R/W; bitpos: [8]; default: 0; + * The interrupt enable bit for the i2s_in_done_int interrupt + */ + +#define I2S_IN_DONE_INT_ENA (BIT(8)) +#define I2S_IN_DONE_INT_ENA_M (I2S_IN_DONE_INT_ENA_V << I2S_IN_DONE_INT_ENA_S) +#define I2S_IN_DONE_INT_ENA_V 0x00000001 +#define I2S_IN_DONE_INT_ENA_S 8 + +/* I2S_TX_HUNG_INT_ENA : R/W; bitpos: [7]; default: 0; + * The interrupt enable bit for the i2s_tx_hung_int interrupt + */ + +#define I2S_TX_HUNG_INT_ENA (BIT(7)) +#define I2S_TX_HUNG_INT_ENA_M (I2S_TX_HUNG_INT_ENA_V << I2S_TX_HUNG_INT_ENA_S) +#define I2S_TX_HUNG_INT_ENA_V 0x00000001 +#define I2S_TX_HUNG_INT_ENA_S 7 + +/* I2S_RX_HUNG_INT_ENA : R/W; bitpos: [6]; default: 0; + * The interrupt enable bit for the i2s_rx_hung_int interrupt + */ + +#define I2S_RX_HUNG_INT_ENA (BIT(6)) +#define I2S_RX_HUNG_INT_ENA_M (I2S_RX_HUNG_INT_ENA_V << I2S_RX_HUNG_INT_ENA_S) +#define I2S_RX_HUNG_INT_ENA_V 0x00000001 +#define I2S_RX_HUNG_INT_ENA_S 6 + +/* I2S_TX_REMPTY_INT_ENA : R/W; bitpos: [5]; default: 0; + * The interrupt enable bit for the i2s_tx_rempty_int interrupt + */ + +#define I2S_TX_REMPTY_INT_ENA (BIT(5)) +#define I2S_TX_REMPTY_INT_ENA_M (I2S_TX_REMPTY_INT_ENA_V << I2S_TX_REMPTY_INT_ENA_S) +#define I2S_TX_REMPTY_INT_ENA_V 0x00000001 +#define I2S_TX_REMPTY_INT_ENA_S 5 + +/* I2S_TX_WFULL_INT_ENA : R/W; bitpos: [4]; default: 0; + * The interrupt enable bit for the i2s_tx_wfull_int interrupt + */ + +#define I2S_TX_WFULL_INT_ENA (BIT(4)) +#define I2S_TX_WFULL_INT_ENA_M (I2S_TX_WFULL_INT_ENA_V << I2S_TX_WFULL_INT_ENA_S) +#define I2S_TX_WFULL_INT_ENA_V 0x00000001 +#define I2S_TX_WFULL_INT_ENA_S 4 + +/* I2S_RX_REMPTY_INT_ENA : R/W; bitpos: [3]; default: 0; + * The interrupt enable bit for the i2s_rx_rempty_int interrupt + */ + +#define I2S_RX_REMPTY_INT_ENA (BIT(3)) +#define I2S_RX_REMPTY_INT_ENA_M (I2S_RX_REMPTY_INT_ENA_V << I2S_RX_REMPTY_INT_ENA_S) +#define I2S_RX_REMPTY_INT_ENA_V 0x00000001 +#define I2S_RX_REMPTY_INT_ENA_S 3 + +/* I2S_RX_WFULL_INT_ENA : R/W; bitpos: [2]; default: 0; + * The interrupt enable bit for the i2s_rx_wfull_int interrupt + */ + +#define I2S_RX_WFULL_INT_ENA (BIT(2)) +#define I2S_RX_WFULL_INT_ENA_M (I2S_RX_WFULL_INT_ENA_V << I2S_RX_WFULL_INT_ENA_S) +#define I2S_RX_WFULL_INT_ENA_V 0x00000001 +#define I2S_RX_WFULL_INT_ENA_S 2 + +/* I2S_TX_PUT_DATA_INT_ENA : R/W; bitpos: [1]; default: 0; + * The interrupt enable bit for the i2s_tx_put_data_int interrupt + */ + +#define I2S_TX_PUT_DATA_INT_ENA (BIT(1)) +#define I2S_TX_PUT_DATA_INT_ENA_M (I2S_TX_PUT_DATA_INT_ENA_V << I2S_TX_PUT_DATA_INT_ENA_S) +#define I2S_TX_PUT_DATA_INT_ENA_V 0x00000001 +#define I2S_TX_PUT_DATA_INT_ENA_S 1 + +/* I2S_RX_TAKE_DATA_INT_ENA : R/W; bitpos: [0]; default: 0; + * The interrupt enable bit for the i2s_rx_take_data_int interrupt + */ + +#define I2S_RX_TAKE_DATA_INT_ENA (BIT(0)) +#define I2S_RX_TAKE_DATA_INT_ENA_M (I2S_RX_TAKE_DATA_INT_ENA_V << I2S_RX_TAKE_DATA_INT_ENA_S) +#define I2S_RX_TAKE_DATA_INT_ENA_V 0x00000001 +#define I2S_RX_TAKE_DATA_INT_ENA_S 0 + +/* I2S_INT_CLR_REG register + * Interrupt clear bits + */ + +#define I2S_INT_CLR_REG(i) (REG_I2S_BASE(i) + 0x18) + +/* I2S_OUT_TOTAL_EOF_INT_CLR : WO; bitpos: [16]; default: 0; + * Set this bit to clear the i2s_out_total_eof_int interrupt + */ + +#define I2S_OUT_TOTAL_EOF_INT_CLR (BIT(16)) +#define I2S_OUT_TOTAL_EOF_INT_CLR_M (I2S_OUT_TOTAL_EOF_INT_CLR_V << I2S_OUT_TOTAL_EOF_INT_CLR_S) +#define I2S_OUT_TOTAL_EOF_INT_CLR_V 0x00000001 +#define I2S_OUT_TOTAL_EOF_INT_CLR_S 16 + +/* I2S_IN_DSCR_EMPTY_INT_CLR : WO; bitpos: [15]; default: 0; + * Set this bit to clear the i2s_in_dscr_empty_int interrupt + */ + +#define I2S_IN_DSCR_EMPTY_INT_CLR (BIT(15)) +#define I2S_IN_DSCR_EMPTY_INT_CLR_M (I2S_IN_DSCR_EMPTY_INT_CLR_V << I2S_IN_DSCR_EMPTY_INT_CLR_S) +#define I2S_IN_DSCR_EMPTY_INT_CLR_V 0x00000001 +#define I2S_IN_DSCR_EMPTY_INT_CLR_S 15 + +/* I2S_OUT_DSCR_ERR_INT_CLR : WO; bitpos: [14]; default: 0; + * Set this bit to clear the i2s_out_dscr_err_int interrupt + */ + +#define I2S_OUT_DSCR_ERR_INT_CLR (BIT(14)) +#define I2S_OUT_DSCR_ERR_INT_CLR_M (I2S_OUT_DSCR_ERR_INT_CLR_V << I2S_OUT_DSCR_ERR_INT_CLR_S) +#define I2S_OUT_DSCR_ERR_INT_CLR_V 0x00000001 +#define I2S_OUT_DSCR_ERR_INT_CLR_S 14 + +/* I2S_IN_DSCR_ERR_INT_CLR : WO; bitpos: [13]; default: 0; + * Set this bit to clear the i2s_in_dscr_err_int interrupt + */ + +#define I2S_IN_DSCR_ERR_INT_CLR (BIT(13)) +#define I2S_IN_DSCR_ERR_INT_CLR_M (I2S_IN_DSCR_ERR_INT_CLR_V << I2S_IN_DSCR_ERR_INT_CLR_S) +#define I2S_IN_DSCR_ERR_INT_CLR_V 0x00000001 +#define I2S_IN_DSCR_ERR_INT_CLR_S 13 + +/* I2S_OUT_EOF_INT_CLR : WO; bitpos: [12]; default: 0; + * Set this bit to clear the i2s_out_eof_int interrupt + */ + +#define I2S_OUT_EOF_INT_CLR (BIT(12)) +#define I2S_OUT_EOF_INT_CLR_M (I2S_OUT_EOF_INT_CLR_V << I2S_OUT_EOF_INT_CLR_S) +#define I2S_OUT_EOF_INT_CLR_V 0x00000001 +#define I2S_OUT_EOF_INT_CLR_S 12 + +/* I2S_OUT_DONE_INT_CLR : WO; bitpos: [11]; default: 0; + * Set this bit to clear the i2s_out_done_int interrupt + */ + +#define I2S_OUT_DONE_INT_CLR (BIT(11)) +#define I2S_OUT_DONE_INT_CLR_M (I2S_OUT_DONE_INT_CLR_V << I2S_OUT_DONE_INT_CLR_S) +#define I2S_OUT_DONE_INT_CLR_V 0x00000001 +#define I2S_OUT_DONE_INT_CLR_S 11 + +/* I2S_IN_ERR_EOF_INT_CLR : WO; bitpos: [10]; default: 0; + * don't use + */ + +#define I2S_IN_ERR_EOF_INT_CLR (BIT(10)) +#define I2S_IN_ERR_EOF_INT_CLR_M (I2S_IN_ERR_EOF_INT_CLR_V << I2S_IN_ERR_EOF_INT_CLR_S) +#define I2S_IN_ERR_EOF_INT_CLR_V 0x00000001 +#define I2S_IN_ERR_EOF_INT_CLR_S 10 + +/* I2S_IN_SUC_EOF_INT_CLR : WO; bitpos: [9]; default: 0; + * Set this bit to clear the i2s_in_suc_eof_int interrupt + */ + +#define I2S_IN_SUC_EOF_INT_CLR (BIT(9)) +#define I2S_IN_SUC_EOF_INT_CLR_M (I2S_IN_SUC_EOF_INT_CLR_V << I2S_IN_SUC_EOF_INT_CLR_S) +#define I2S_IN_SUC_EOF_INT_CLR_V 0x00000001 +#define I2S_IN_SUC_EOF_INT_CLR_S 9 + +/* I2S_IN_DONE_INT_CLR : WO; bitpos: [8]; default: 0; + * Set this bit to clear the i2s_in_done_int interrupt + */ + +#define I2S_IN_DONE_INT_CLR (BIT(8)) +#define I2S_IN_DONE_INT_CLR_M (I2S_IN_DONE_INT_CLR_V << I2S_IN_DONE_INT_CLR_S) +#define I2S_IN_DONE_INT_CLR_V 0x00000001 +#define I2S_IN_DONE_INT_CLR_S 8 + +/* I2S_TX_HUNG_INT_CLR : WO; bitpos: [7]; default: 0; + * Set this bit to clear the i2s_tx_hung_int interrupt + */ + +#define I2S_TX_HUNG_INT_CLR (BIT(7)) +#define I2S_TX_HUNG_INT_CLR_M (I2S_TX_HUNG_INT_CLR_V << I2S_TX_HUNG_INT_CLR_S) +#define I2S_TX_HUNG_INT_CLR_V 0x00000001 +#define I2S_TX_HUNG_INT_CLR_S 7 + +/* I2S_RX_HUNG_INT_CLR : WO; bitpos: [6]; default: 0; + * Set this bit to clear the i2s_rx_hung_int interrupt + */ + +#define I2S_RX_HUNG_INT_CLR (BIT(6)) +#define I2S_RX_HUNG_INT_CLR_M (I2S_RX_HUNG_INT_CLR_V << I2S_RX_HUNG_INT_CLR_S) +#define I2S_RX_HUNG_INT_CLR_V 0x00000001 +#define I2S_RX_HUNG_INT_CLR_S 6 + +/* I2S_TX_REMPTY_INT_CLR : WO; bitpos: [5]; default: 0; + * Set this bit to clear the i2s_tx_rempty_int interrupt + */ + +#define I2S_TX_REMPTY_INT_CLR (BIT(5)) +#define I2S_TX_REMPTY_INT_CLR_M (I2S_TX_REMPTY_INT_CLR_V << I2S_TX_REMPTY_INT_CLR_S) +#define I2S_TX_REMPTY_INT_CLR_V 0x00000001 +#define I2S_TX_REMPTY_INT_CLR_S 5 + +/* I2S_TX_WFULL_INT_CLR : WO; bitpos: [4]; default: 0; + * Set this bit to clear the i2s_tx_wfull_int interrupt + */ + +#define I2S_TX_WFULL_INT_CLR (BIT(4)) +#define I2S_TX_WFULL_INT_CLR_M (I2S_TX_WFULL_INT_CLR_V << I2S_TX_WFULL_INT_CLR_S) +#define I2S_TX_WFULL_INT_CLR_V 0x00000001 +#define I2S_TX_WFULL_INT_CLR_S 4 + +/* I2S_RX_REMPTY_INT_CLR : WO; bitpos: [3]; default: 0; + * Set this bit to clear the i2s_rx_rempty_int interrupt + */ + +#define I2S_RX_REMPTY_INT_CLR (BIT(3)) +#define I2S_RX_REMPTY_INT_CLR_M (I2S_RX_REMPTY_INT_CLR_V << I2S_RX_REMPTY_INT_CLR_S) +#define I2S_RX_REMPTY_INT_CLR_V 0x00000001 +#define I2S_RX_REMPTY_INT_CLR_S 3 + +/* I2S_RX_WFULL_INT_CLR : WO; bitpos: [2]; default: 0; + * Set this bit to clear the i2s_rx_wfull_int interrupt + */ + +#define I2S_RX_WFULL_INT_CLR (BIT(2)) +#define I2S_RX_WFULL_INT_CLR_M (I2S_RX_WFULL_INT_CLR_V << I2S_RX_WFULL_INT_CLR_S) +#define I2S_RX_WFULL_INT_CLR_V 0x00000001 +#define I2S_RX_WFULL_INT_CLR_S 2 + +/* I2S_TX_PUT_DATA_INT_CLR : WO; bitpos: [1]; default: 0; + * Set this bit to clear the i2s_tx_put_data_int interrupt + */ + +#define I2S_TX_PUT_DATA_INT_CLR (BIT(1)) +#define I2S_TX_PUT_DATA_INT_CLR_M (I2S_TX_PUT_DATA_INT_CLR_V << I2S_TX_PUT_DATA_INT_CLR_S) +#define I2S_TX_PUT_DATA_INT_CLR_V 0x00000001 +#define I2S_TX_PUT_DATA_INT_CLR_S 1 + +/* I2S_RX_TAKE_DATA_INT_CLR : WO; bitpos: [0]; default: 0; + * Set this bit to clear the i2s_rx_take_data_int interrupt + */ + +#define I2S_RX_TAKE_DATA_INT_CLR (BIT(0)) +#define I2S_RX_TAKE_DATA_INT_CLR_M (I2S_RX_TAKE_DATA_INT_CLR_V << I2S_RX_TAKE_DATA_INT_CLR_S) +#define I2S_RX_TAKE_DATA_INT_CLR_V 0x00000001 +#define I2S_RX_TAKE_DATA_INT_CLR_S 0 + +/* I2S_TIMING_REG register + * I2S timing register + */ + +#define I2S_TIMING_REG(i) (REG_I2S_BASE(i) + 0x1c) + +/* I2S_TX_BCK_IN_INV : R/W; bitpos: [24]; default: 0; + * Set this bit to invert BCK signal input to the slave transmitter + */ + +#define I2S_TX_BCK_IN_INV (BIT(24)) +#define I2S_TX_BCK_IN_INV_M (I2S_TX_BCK_IN_INV_V << I2S_TX_BCK_IN_INV_S) +#define I2S_TX_BCK_IN_INV_V 0x00000001 +#define I2S_TX_BCK_IN_INV_S 24 + +/* I2S_DATA_ENABLE_DELAY : R/W; bitpos: [23:22]; default: 0; + * Number of delay cycles for data valid flag. + */ + +#define I2S_DATA_ENABLE_DELAY 0x00000003 +#define I2S_DATA_ENABLE_DELAY_M (I2S_DATA_ENABLE_DELAY_V << I2S_DATA_ENABLE_DELAY_S) +#define I2S_DATA_ENABLE_DELAY_V 0x00000003 +#define I2S_DATA_ENABLE_DELAY_S 22 + +/* I2S_RX_DSYNC_SW : R/W; bitpos: [21]; default: 0; + * Set this bit to synchronize signals with the double sync method into the + * receiver + */ + +#define I2S_RX_DSYNC_SW (BIT(21)) +#define I2S_RX_DSYNC_SW_M (I2S_RX_DSYNC_SW_V << I2S_RX_DSYNC_SW_S) +#define I2S_RX_DSYNC_SW_V 0x00000001 +#define I2S_RX_DSYNC_SW_S 21 + +/* I2S_TX_DSYNC_SW : R/W; bitpos: [20]; default: 0; + * Set this bit to synchronize signals with the double sync method into the + * transmitter + */ + +#define I2S_TX_DSYNC_SW (BIT(20)) +#define I2S_TX_DSYNC_SW_M (I2S_TX_DSYNC_SW_V << I2S_TX_DSYNC_SW_S) +#define I2S_TX_DSYNC_SW_V 0x00000001 +#define I2S_TX_DSYNC_SW_S 20 + +/* I2S_RX_BCK_OUT_DELAY : R/W; bitpos: [19:18]; default: 0; + * Number of delay cycles for BCK out of the receiver + */ + +#define I2S_RX_BCK_OUT_DELAY 0x00000003 +#define I2S_RX_BCK_OUT_DELAY_M (I2S_RX_BCK_OUT_DELAY_V << I2S_RX_BCK_OUT_DELAY_S) +#define I2S_RX_BCK_OUT_DELAY_V 0x00000003 +#define I2S_RX_BCK_OUT_DELAY_S 18 + +/* I2S_RX_WS_OUT_DELAY : R/W; bitpos: [17:16]; default: 0; + * Number of delay cycles for WS out of the receiver + */ + +#define I2S_RX_WS_OUT_DELAY 0x00000003 +#define I2S_RX_WS_OUT_DELAY_M (I2S_RX_WS_OUT_DELAY_V << I2S_RX_WS_OUT_DELAY_S) +#define I2S_RX_WS_OUT_DELAY_V 0x00000003 +#define I2S_RX_WS_OUT_DELAY_S 16 + +/* I2S_TX_SD_OUT_DELAY : R/W; bitpos: [15:14]; default: 0; + * Number of delay cycles for SD out of the transmitter + */ + +#define I2S_TX_SD_OUT_DELAY 0x00000003 +#define I2S_TX_SD_OUT_DELAY_M (I2S_TX_SD_OUT_DELAY_V << I2S_TX_SD_OUT_DELAY_S) +#define I2S_TX_SD_OUT_DELAY_V 0x00000003 +#define I2S_TX_SD_OUT_DELAY_S 14 + +/* I2S_TX_WS_OUT_DELAY : R/W; bitpos: [13:12]; default: 0; + * Number of delay cycles for WS out of the transmitter + */ + +#define I2S_TX_WS_OUT_DELAY 0x00000003 +#define I2S_TX_WS_OUT_DELAY_M (I2S_TX_WS_OUT_DELAY_V << I2S_TX_WS_OUT_DELAY_S) +#define I2S_TX_WS_OUT_DELAY_V 0x00000003 +#define I2S_TX_WS_OUT_DELAY_S 12 + +/* I2S_TX_BCK_OUT_DELAY : R/W; bitpos: [11:10]; default: 0; + * Number of delay cycles for BCK out of the transmitter + */ + +#define I2S_TX_BCK_OUT_DELAY 0x00000003 +#define I2S_TX_BCK_OUT_DELAY_M (I2S_TX_BCK_OUT_DELAY_V << I2S_TX_BCK_OUT_DELAY_S) +#define I2S_TX_BCK_OUT_DELAY_V 0x00000003 +#define I2S_TX_BCK_OUT_DELAY_S 10 + +/* I2S_RX_SD_IN_DELAY : R/W; bitpos: [9:8]; default: 0; + * Number of delay cycles for SD into the receiver + */ + +#define I2S_RX_SD_IN_DELAY 0x00000003 +#define I2S_RX_SD_IN_DELAY_M (I2S_RX_SD_IN_DELAY_V << I2S_RX_SD_IN_DELAY_S) +#define I2S_RX_SD_IN_DELAY_V 0x00000003 +#define I2S_RX_SD_IN_DELAY_S 8 + +/* I2S_RX_WS_IN_DELAY : R/W; bitpos: [7:6]; default: 0; + * Number of delay cycles for WS into the receiver + */ + +#define I2S_RX_WS_IN_DELAY 0x00000003 +#define I2S_RX_WS_IN_DELAY_M (I2S_RX_WS_IN_DELAY_V << I2S_RX_WS_IN_DELAY_S) +#define I2S_RX_WS_IN_DELAY_V 0x00000003 +#define I2S_RX_WS_IN_DELAY_S 6 + +/* I2S_RX_BCK_IN_DELAY : R/W; bitpos: [5:4]; default: 0; + * Number of delay cycles for BCK into the receiver + */ + +#define I2S_RX_BCK_IN_DELAY 0x00000003 +#define I2S_RX_BCK_IN_DELAY_M (I2S_RX_BCK_IN_DELAY_V << I2S_RX_BCK_IN_DELAY_S) +#define I2S_RX_BCK_IN_DELAY_V 0x00000003 +#define I2S_RX_BCK_IN_DELAY_S 4 + +/* I2S_TX_WS_IN_DELAY : R/W; bitpos: [3:2]; default: 0; + * Number of delay cycles for WS into the transmitter + */ + +#define I2S_TX_WS_IN_DELAY 0x00000003 +#define I2S_TX_WS_IN_DELAY_M (I2S_TX_WS_IN_DELAY_V << I2S_TX_WS_IN_DELAY_S) +#define I2S_TX_WS_IN_DELAY_V 0x00000003 +#define I2S_TX_WS_IN_DELAY_S 2 + +/* I2S_TX_BCK_IN_DELAY : R/W; bitpos: [1:0]; default: 0; + * Number of delay cycles for BCK into the transmitter + */ + +#define I2S_TX_BCK_IN_DELAY 0x00000003 +#define I2S_TX_BCK_IN_DELAY_M (I2S_TX_BCK_IN_DELAY_V << I2S_TX_BCK_IN_DELAY_S) +#define I2S_TX_BCK_IN_DELAY_V 0x00000003 +#define I2S_TX_BCK_IN_DELAY_S 0 + +/* I2S_FIFO_CONF_REG register + * I2S FIFO configure register + */ + +#define I2S_FIFO_CONF_REG(i) (REG_I2S_BASE(i) + 0x20) + +/* I2S_RX_FIFO_MOD_FORCE_EN : R/W; bitpos: [20]; default: 0; + * The bit should always be set to 1 + */ + +#define I2S_RX_FIFO_MOD_FORCE_EN (BIT(20)) +#define I2S_RX_FIFO_MOD_FORCE_EN_M (I2S_RX_FIFO_MOD_FORCE_EN_V << I2S_RX_FIFO_MOD_FORCE_EN_S) +#define I2S_RX_FIFO_MOD_FORCE_EN_V 0x00000001 +#define I2S_RX_FIFO_MOD_FORCE_EN_S 20 + +/* I2S_TX_FIFO_MOD_FORCE_EN : R/W; bitpos: [19]; default: 0; + * The bit should always be set to 1 + */ + +#define I2S_TX_FIFO_MOD_FORCE_EN (BIT(19)) +#define I2S_TX_FIFO_MOD_FORCE_EN_M (I2S_TX_FIFO_MOD_FORCE_EN_V << I2S_TX_FIFO_MOD_FORCE_EN_S) +#define I2S_TX_FIFO_MOD_FORCE_EN_V 0x00000001 +#define I2S_TX_FIFO_MOD_FORCE_EN_S 19 + +/* I2S_RX_FIFO_MOD : R/W; bitpos: [18:16]; default: 0; + * Receiver FIFO mode configuration bits + */ + +#define I2S_RX_FIFO_MOD 0x00000007 +#define I2S_RX_FIFO_MOD_M (I2S_RX_FIFO_MOD_V << I2S_RX_FIFO_MOD_S) +#define I2S_RX_FIFO_MOD_V 0x00000007 +#define I2S_RX_FIFO_MOD_S 16 + +/* I2S_TX_FIFO_MOD : R/W; bitpos: [15:13]; default: 0; + * Transmitter FIFO mode configuration bits + */ + +#define I2S_TX_FIFO_MOD 0x00000007 +#define I2S_TX_FIFO_MOD_M (I2S_TX_FIFO_MOD_V << I2S_TX_FIFO_MOD_S) +#define I2S_TX_FIFO_MOD_V 0x00000007 +#define I2S_TX_FIFO_MOD_S 13 + +/* I2S_DSCR_EN : R/W; bitpos: [12]; default: 1; + * Set this bit to enable I2S DMA mode + */ + +#define I2S_DSCR_EN (BIT(12)) +#define I2S_DSCR_EN_M (I2S_DSCR_EN_V << I2S_DSCR_EN_S) +#define I2S_DSCR_EN_V 0x00000001 +#define I2S_DSCR_EN_S 12 + +/* I2S_TX_DATA_NUM : R/W; bitpos: [11:6]; default: 32; + * Threshold of data length in transmitter FIFO + */ + +#define I2S_TX_DATA_NUM 0x0000003F +#define I2S_TX_DATA_NUM_M (I2S_TX_DATA_NUM_V << I2S_TX_DATA_NUM_S) +#define I2S_TX_DATA_NUM_V 0x0000003F +#define I2S_TX_DATA_NUM_S 6 + +/* I2S_RX_DATA_NUM : R/W; bitpos: [5:0]; default: 32; + * Threshold of data length in receiver FIFO + */ + +#define I2S_RX_DATA_NUM 0x0000003F +#define I2S_RX_DATA_NUM_M (I2S_RX_DATA_NUM_V << I2S_RX_DATA_NUM_S) +#define I2S_RX_DATA_NUM_V 0x0000003F +#define I2S_RX_DATA_NUM_S 0 + +/* I2S_RXEOF_NUM_REG register + * I2S DMA RX EOF data length + */ + +#define I2S_RXEOF_NUM_REG(i) (REG_I2S_BASE(i) + 0x24) + +/* I2S_RX_EOF_NUM : R/W; bitpos: [31:0]; default: 64; + * the length of data to be received. It will trigger i2s_in_suc_eof_int. + */ + +#define I2S_RX_EOF_NUM 0xFFFFFFFF +#define I2S_RX_EOF_NUM_M (I2S_RX_EOF_NUM_V << I2S_RX_EOF_NUM_S) +#define I2S_RX_EOF_NUM_V 0xFFFFFFFF +#define I2S_RX_EOF_NUM_S 0 + +/* I2S_CONF_SIGLE_DATA_REG register + * Constant single channel data + */ + +#define I2S_CONF_SINGLE_DATA_REG(i) (REG_I2S_BASE(i) + 0x28) + +/* I2S_SIGLE_DATA : R/W; bitpos: [31:0]; default: 0; + * the right channel or left channel put out constant value stored in this + * register according to tx_chan_mod and reg_tx_msb_right + */ + +#define I2S_SIGLE_DATA 0xFFFFFFFF +#define I2S_SIGLE_DATA_M (I2S_SIGLE_DATA_V << I2S_SIGLE_DATA_S) +#define I2S_SIGLE_DATA_V 0xFFFFFFFF +#define I2S_SIGLE_DATA_S 0 + +/* I2S_CONF_CHAN_REG register + * I2S channel configure register + */ + +#define I2S_CONF_CHAN_REG(i) (REG_I2S_BASE(i) + 0x2c) + +/* I2S_RX_CHAN_MOD : R/W; bitpos: [4:3]; default: 0; + * I2S receiver channel mode configuration bits. + */ + +#define I2S_RX_CHAN_MOD 0x00000003 +#define I2S_RX_CHAN_MOD_M (I2S_RX_CHAN_MOD_V << I2S_RX_CHAN_MOD_S) +#define I2S_RX_CHAN_MOD_V 0x00000003 +#define I2S_RX_CHAN_MOD_S 3 + +/* I2S_TX_CHAN_MOD : R/W; bitpos: [2:0]; default: 0; + * I2S transmitter channel mode configuration bits. + */ + +#define I2S_TX_CHAN_MOD 0x00000007 +#define I2S_TX_CHAN_MOD_M (I2S_TX_CHAN_MOD_V << I2S_TX_CHAN_MOD_S) +#define I2S_TX_CHAN_MOD_V 0x00000007 +#define I2S_TX_CHAN_MOD_S 0 + +/* I2S_OUT_LINK_REG register + * I2S DMA TX configure register + */ + +#define I2S_OUT_LINK_REG(i) (REG_I2S_BASE(i) + 0x30) + +/* I2S_OUTLINK_RESTART : R/W; bitpos: [30]; default: 0; + * Set this bit to restart outlink descriptor + */ + +#define I2S_OUTLINK_RESTART (BIT(30)) +#define I2S_OUTLINK_RESTART_M (I2S_OUTLINK_RESTART_V << I2S_OUTLINK_RESTART_S) +#define I2S_OUTLINK_RESTART_V 0x00000001 +#define I2S_OUTLINK_RESTART_S 30 + +/* I2S_OUTLINK_START : R/W; bitpos: [29]; default: 0; + * Set this bit to start outlink descriptor + */ + +#define I2S_OUTLINK_START (BIT(29)) +#define I2S_OUTLINK_START_M (I2S_OUTLINK_START_V << I2S_OUTLINK_START_S) +#define I2S_OUTLINK_START_V 0x00000001 +#define I2S_OUTLINK_START_S 29 + +/* I2S_OUTLINK_STOP : R/W; bitpos: [28]; default: 0; + * Set this bit to stop outlink descriptor + */ + +#define I2S_OUTLINK_STOP (BIT(28)) +#define I2S_OUTLINK_STOP_M (I2S_OUTLINK_STOP_V << I2S_OUTLINK_STOP_S) +#define I2S_OUTLINK_STOP_V 0x00000001 +#define I2S_OUTLINK_STOP_S 28 + +/* I2S_OUTLINK_ADDR : R/W; bitpos: [19:0]; default: 0; + * The address of first outlink descriptor + */ + +#define I2S_OUTLINK_ADDR 0x000FFFFF +#define I2S_OUTLINK_ADDR_M (I2S_OUTLINK_ADDR_V << I2S_OUTLINK_ADDR_S) +#define I2S_OUTLINK_ADDR_V 0x000FFFFF +#define I2S_OUTLINK_ADDR_S 0 + +/* I2S_IN_LINK_REG register + * I2S DMA RX configure register + */ + +#define I2S_IN_LINK_REG(i) (REG_I2S_BASE(i) + 0x34) + +/* I2S_INLINK_RESTART : R/W; bitpos: [30]; default: 0; + * Set this bit to restart inlink descriptor + */ + +#define I2S_INLINK_RESTART (BIT(30)) +#define I2S_INLINK_RESTART_M (I2S_INLINK_RESTART_V << I2S_INLINK_RESTART_S) +#define I2S_INLINK_RESTART_V 0x00000001 +#define I2S_INLINK_RESTART_S 30 + +/* I2S_INLINK_START : R/W; bitpos: [29]; default: 0; + * Set this bit to start inlink descriptor + */ + +#define I2S_INLINK_START (BIT(29)) +#define I2S_INLINK_START_M (I2S_INLINK_START_V << I2S_INLINK_START_S) +#define I2S_INLINK_START_V 0x00000001 +#define I2S_INLINK_START_S 29 + +/* I2S_INLINK_STOP : R/W; bitpos: [28]; default: 0; + * Set this bit to stop inlink descriptor + */ + +#define I2S_INLINK_STOP (BIT(28)) +#define I2S_INLINK_STOP_M (I2S_INLINK_STOP_V << I2S_INLINK_STOP_S) +#define I2S_INLINK_STOP_V 0x00000001 +#define I2S_INLINK_STOP_S 28 + +/* I2S_INLINK_ADDR : R/W; bitpos: [19:0]; default: 0; + * The address of first inlink descriptor + */ + +#define I2S_INLINK_ADDR 0x000FFFFF +#define I2S_INLINK_ADDR_M (I2S_INLINK_ADDR_V << I2S_INLINK_ADDR_S) +#define I2S_INLINK_ADDR_V 0x000FFFFF +#define I2S_INLINK_ADDR_S 0 + +/* I2S_OUT_EOF_DES_ADDR_REG register + * The address of outlink descriptor that produces EOF + */ + +#define I2S_OUT_EOF_DES_ADDR_REG(i) (REG_I2S_BASE(i) + 0x38) + +/* I2S_OUT_EOF_DES_ADDR : RO; bitpos: [31:0]; default: 0; + * The address of outlink descriptor that produces EOF + */ + +#define I2S_OUT_EOF_DES_ADDR 0xFFFFFFFF +#define I2S_OUT_EOF_DES_ADDR_M (I2S_OUT_EOF_DES_ADDR_V << I2S_OUT_EOF_DES_ADDR_S) +#define I2S_OUT_EOF_DES_ADDR_V 0xFFFFFFFF +#define I2S_OUT_EOF_DES_ADDR_S 0 + +/* I2S_IN_EOF_DES_ADDR_REG register + * The address of inlink descriptor that produces EOF + */ + +#define I2S_IN_EOF_DES_ADDR_REG(i) (REG_I2S_BASE(i) + 0x3c) + +/* I2S_IN_EOF_DES_ADDR_REG : RO; bitpos: [31:0]; default: 0; + * The address of inlink descriptor that produces EOF + */ + +#define I2S_IN_EOF_DES_ADDR 0xFFFFFFFF +#define I2S_IN_EOF_DES_ADDR_M (I2S_IN_EOF_DES_ADDR_V << I2S_IN_EOF_DES_ADDR_S) +#define I2S_IN_EOF_DES_ADDR_V 0xFFFFFFFF +#define I2S_IN_EOF_DES_ADDR_S 0 + +/* I2S_OUT_EOF_BFR_DES_ADDR_REG register + * The address of buffer relative to the outlink descriptor that produces EOF + */ + +#define I2S_OUT_EOF_BFR_DES_ADDR_REG(i) (REG_I2S_BASE(i) + 0x40) + +/* I2S_OUT_EOF_BFR_DES_ADDR : RO; bitpos: [31:0]; default: 0; + * The address of buffer relative to the outlink descriptor that produces EOF + */ + +#define I2S_OUT_EOF_BFR_DES_ADDR 0xFFFFFFFF +#define I2S_OUT_EOF_BFR_DES_ADDR_M (I2S_OUT_EOF_BFR_DES_ADDR_V << I2S_OUT_EOF_BFR_DES_ADDR_S) +#define I2S_OUT_EOF_BFR_DES_ADDR_V 0xFFFFFFFF +#define I2S_OUT_EOF_BFR_DES_ADDR_S 0 + +/* I2S_INLINK_DSCR_REG register + * The address of current inlink descriptor + */ + +#define I2S_INLINK_DSCR_REG(i) (REG_I2S_BASE(i) + 0x48) + +/* I2S_INLINK_DSCR : RO; bitpos: [31:0]; default: 0; + * The address of current inlink descriptor + */ + +#define I2S_INLINK_DSCR 0xFFFFFFFF +#define I2S_INLINK_DSCR_M (I2S_INLINK_DSCR_V << I2S_INLINK_DSCR_S) +#define I2S_INLINK_DSCR_V 0xFFFFFFFF +#define I2S_INLINK_DSCR_S 0 + +/* I2S_INLINK_DSCR_BF0_REG register + * The address of next inlink descriptor + */ + +#define I2S_INLINK_DSCR_BF0_REG(i) (REG_I2S_BASE(i) + 0x4c) + +/* I2S_INLINK_DSCR_BF0 : RO; bitpos: [31:0]; default: 0; + * The address of next inlink descriptor + */ + +#define I2S_INLINK_DSCR_BF0 0xFFFFFFFF +#define I2S_INLINK_DSCR_BF0_M (I2S_INLINK_DSCR_BF0_V << I2S_INLINK_DSCR_BF0_S) +#define I2S_INLINK_DSCR_BF0_V 0xFFFFFFFF +#define I2S_INLINK_DSCR_BF0_S 0 + +/* I2S_INLINK_DSCR_BF1_REG register + * The address of next inlink data buffer + */ + +#define I2S_INLINK_DSCR_BF1_REG(i) (REG_I2S_BASE(i) + 0x50) + +/* I2S_INLINK_DSCR_BF1 : RO; bitpos: [31:0]; default: 0; + * The address of next inlink data buffer + */ + +#define I2S_INLINK_DSCR_BF1 0xFFFFFFFF +#define I2S_INLINK_DSCR_BF1_M (I2S_INLINK_DSCR_BF1_V << I2S_INLINK_DSCR_BF1_S) +#define I2S_INLINK_DSCR_BF1_V 0xFFFFFFFF +#define I2S_INLINK_DSCR_BF1_S 0 + +/* I2S_OUTLINK_DSCR_REG register + * The address of current outlink descriptor + */ + +#define I2S_OUTLINK_DSCR_REG(i) (REG_I2S_BASE(i) + 0x54) + +/* I2S_OUTLINK_DSCR : RO; bitpos: [31:0]; default: 0; + * The address of current outlink descriptor + */ + +#define I2S_OUTLINK_DSCR 0xFFFFFFFF +#define I2S_OUTLINK_DSCR_M (I2S_OUTLINK_DSCR_V << I2S_OUTLINK_DSCR_S) +#define I2S_OUTLINK_DSCR_V 0xFFFFFFFF +#define I2S_OUTLINK_DSCR_S 0 + +/* I2S_OUTLINK_DSCR_BF0_REG register + * The address of next outlink descriptor + */ + +#define I2S_OUTLINK_DSCR_BF0_REG(i) (REG_I2S_BASE(i) + 0x58) + +/* I2S_OUTLINK_DSCR_BF0 : RO; bitpos: [31:0]; default: 0; + * The address of next outlink descriptor + */ + +#define I2S_OUTLINK_DSCR_BF0 0xFFFFFFFF +#define I2S_OUTLINK_DSCR_BF0_M (I2S_OUTLINK_DSCR_BF0_V << I2S_OUTLINK_DSCR_BF0_S) +#define I2S_OUTLINK_DSCR_BF0_V 0xFFFFFFFF +#define I2S_OUTLINK_DSCR_BF0_S 0 + +/* I2S_OUTLINK_DSCR_BF1_REG register + * The address of next outlink data buffer + */ + +#define I2S_OUTLINK_DSCR_BF1_REG(i) (REG_I2S_BASE(i) + 0x5c) + +/* I2S_OUTLINK_DSCR_BF1 : RO; bitpos: [31:0]; default: 0; + * The address of next outlink data buffer + */ + +#define I2S_OUTLINK_DSCR_BF1 0xFFFFFFFF +#define I2S_OUTLINK_DSCR_BF1_M (I2S_OUTLINK_DSCR_BF1_V << I2S_OUTLINK_DSCR_BF1_S) +#define I2S_OUTLINK_DSCR_BF1_V 0xFFFFFFFF +#define I2S_OUTLINK_DSCR_BF1_S 0 + +/* I2S_LC_CONF_REG register + * I2S DMA configuration register + */ + +#define I2S_LC_CONF_REG(i) (REG_I2S_BASE(i) + 0x60) + +/* I2S_EXT_MEM_BK_SIZE : R/W; bitpos: [15:14]; default: 0; + * DMA access external memory block size. 0: 16 bytes 1: 32 bytes + * 2:64 bytes 3:reserved + */ + +#define I2S_EXT_MEM_BK_SIZE 0x00000003 +#define I2S_EXT_MEM_BK_SIZE_M (I2S_EXT_MEM_BK_SIZE_V << I2S_EXT_MEM_BK_SIZE_S) +#define I2S_EXT_MEM_BK_SIZE_V 0x00000003 +#define I2S_EXT_MEM_BK_SIZE_S 14 + +/* I2S_MEM_TRANS_EN : R/W; bitpos: [13]; default: 0; + * don't use + */ + +#define I2S_MEM_TRANS_EN (BIT(13)) +#define I2S_MEM_TRANS_EN_M (I2S_MEM_TRANS_EN_V << I2S_MEM_TRANS_EN_S) +#define I2S_MEM_TRANS_EN_V 0x00000001 +#define I2S_MEM_TRANS_EN_S 13 + +/* I2S_CHECK_OWNER : R/W; bitpos: [12]; default: 0; + * Set this bit to enable check owner bit by hardware + */ + +#define I2S_CHECK_OWNER (BIT(12)) +#define I2S_CHECK_OWNER_M (I2S_CHECK_OWNER_V << I2S_CHECK_OWNER_S) +#define I2S_CHECK_OWNER_V 0x00000001 +#define I2S_CHECK_OWNER_S 12 + +/* I2S_OUT_DATA_BURST_EN : R/W; bitpos: [11]; default: 0; + * Transmitter data transfer mode configuration bit. 1: to prepare out data + * with burst mode 0: to prepare out data with byte mode + */ + +#define I2S_OUT_DATA_BURST_EN (BIT(11)) +#define I2S_OUT_DATA_BURST_EN_M (I2S_OUT_DATA_BURST_EN_V << I2S_OUT_DATA_BURST_EN_S) +#define I2S_OUT_DATA_BURST_EN_V 0x00000001 +#define I2S_OUT_DATA_BURST_EN_S 11 + +/* I2S_INDSCR_BURST_EN : R/W; bitpos: [10]; default: 0; + * DMA inlink descriptor transfer mode configuration bit. 1: to prepare + * inlink descriptor with burst mode 0: to prepare inlink descriptor with + * byte mode + */ + +#define I2S_INDSCR_BURST_EN (BIT(10)) +#define I2S_INDSCR_BURST_EN_M (I2S_INDSCR_BURST_EN_V << I2S_INDSCR_BURST_EN_S) +#define I2S_INDSCR_BURST_EN_V 0x00000001 +#define I2S_INDSCR_BURST_EN_S 10 + +/* I2S_OUTDSCR_BURST_EN : R/W; bitpos: [9]; default: 0; + * DMA outlink descriptor transfer mode configuration bit. 1: to prepare + * outlink descriptor with burst mode 0: to prepare outlink descriptor + * with byte mode + */ + +#define I2S_OUTDSCR_BURST_EN (BIT(9)) +#define I2S_OUTDSCR_BURST_EN_M (I2S_OUTDSCR_BURST_EN_V << I2S_OUTDSCR_BURST_EN_S) +#define I2S_OUTDSCR_BURST_EN_V 0x00000001 +#define I2S_OUTDSCR_BURST_EN_S 9 + +/* I2S_OUT_EOF_MODE : R/W; bitpos: [8]; default: 1; + * DMA out EOF flag generation mode . 1: when dma has popped all data from + * the FIFO 0:when ahb has pushed all data to the FIFO + */ + +#define I2S_OUT_EOF_MODE (BIT(8)) +#define I2S_OUT_EOF_MODE_M (I2S_OUT_EOF_MODE_V << I2S_OUT_EOF_MODE_S) +#define I2S_OUT_EOF_MODE_V 0x00000001 +#define I2S_OUT_EOF_MODE_S 8 + +/* I2S_OUT_NO_RESTART_CLR : R/W; bitpos: [7]; default: 0; + * don't use + */ + +#define I2S_OUT_NO_RESTART_CLR (BIT(7)) +#define I2S_OUT_NO_RESTART_CLR_M (I2S_OUT_NO_RESTART_CLR_V << I2S_OUT_NO_RESTART_CLR_S) +#define I2S_OUT_NO_RESTART_CLR_V 0x00000001 +#define I2S_OUT_NO_RESTART_CLR_S 7 + +/* I2S_OUT_AUTO_WRBACK : R/W; bitpos: [6]; default: 0; + * Set this bit to enable outlink-written-back automatically when out buffer + * is transmitted done. + */ + +#define I2S_OUT_AUTO_WRBACK (BIT(6)) +#define I2S_OUT_AUTO_WRBACK_M (I2S_OUT_AUTO_WRBACK_V << I2S_OUT_AUTO_WRBACK_S) +#define I2S_OUT_AUTO_WRBACK_V 0x00000001 +#define I2S_OUT_AUTO_WRBACK_S 6 + +/* I2S_OUT_LOOP_TEST : R/W; bitpos: [5]; default: 0; + * Set this bit to loop test outlink + */ + +#define I2S_OUT_LOOP_TEST (BIT(5)) +#define I2S_OUT_LOOP_TEST_M (I2S_OUT_LOOP_TEST_V << I2S_OUT_LOOP_TEST_S) +#define I2S_OUT_LOOP_TEST_V 0x00000001 +#define I2S_OUT_LOOP_TEST_S 5 + +/* I2S_IN_LOOP_TEST : R/W; bitpos: [4]; default: 0; + * Set this bit to loop test inlink + */ + +#define I2S_IN_LOOP_TEST (BIT(4)) +#define I2S_IN_LOOP_TEST_M (I2S_IN_LOOP_TEST_V << I2S_IN_LOOP_TEST_S) +#define I2S_IN_LOOP_TEST_V 0x00000001 +#define I2S_IN_LOOP_TEST_S 4 + +/* I2S_AHBM_RST : R/W; bitpos: [3]; default: 0; + * Set this bit to reset ahb interface of DMA + */ + +#define I2S_AHBM_RST (BIT(3)) +#define I2S_AHBM_RST_M (I2S_AHBM_RST_V << I2S_AHBM_RST_S) +#define I2S_AHBM_RST_V 0x00000001 +#define I2S_AHBM_RST_S 3 + +/* I2S_AHBM_FIFO_RST : R/W; bitpos: [2]; default: 0; + * Set this bit to reset ahb interface cmdFIFO of DMA + */ + +#define I2S_AHBM_FIFO_RST (BIT(2)) +#define I2S_AHBM_FIFO_RST_M (I2S_AHBM_FIFO_RST_V << I2S_AHBM_FIFO_RST_S) +#define I2S_AHBM_FIFO_RST_V 0x00000001 +#define I2S_AHBM_FIFO_RST_S 2 + +/* I2S_OUT_RST : R/W; bitpos: [1]; default: 0; + * Set this bit to reset out dma FSM + */ + +#define I2S_OUT_RST (BIT(1)) +#define I2S_OUT_RST_M (I2S_OUT_RST_V << I2S_OUT_RST_S) +#define I2S_OUT_RST_V 0x00000001 +#define I2S_OUT_RST_S 1 + +/* I2S_IN_RST : R/W; bitpos: [0]; default: 0; + * Set this bit to reset in dma FSM + */ + +#define I2S_IN_RST (BIT(0)) +#define I2S_IN_RST_M (I2S_IN_RST_V << I2S_IN_RST_S) +#define I2S_IN_RST_V 0x00000001 +#define I2S_IN_RST_S 0 + +/* I2S_LC_STATE0_REG register + * I2S DMA TX status + */ + +#define I2S_LC_STATE0_REG(i) (REG_I2S_BASE(i) + 0x6c) + +/* I2S_OUT_EMPTY : RO; bitpos: [31]; default: 0; + * I2S DMA outfifo is empty. + */ + +#define I2S_OUT_EMPTY (BIT(31)) +#define I2S_OUT_EMPTY_M (I2S_OUT_EMPTY_V << I2S_OUT_EMPTY_S) +#define I2S_OUT_EMPTY_V 0x00000001 +#define I2S_OUT_EMPTY_S 31 + +/* I2S_OUT_FULL : RO; bitpos: [30]; default: 0; + * I2S DMA outfifo is full. + */ + +#define I2S_OUT_FULL (BIT(30)) +#define I2S_OUT_FULL_M (I2S_OUT_FULL_V << I2S_OUT_FULL_S) +#define I2S_OUT_FULL_V 0x00000001 +#define I2S_OUT_FULL_S 30 + +/* I2S_OUTFIFO_CNT : RO; bitpos: [29:23]; default: 0; + * The remains of I2S DMA outfifo data. + */ + +#define I2S_OUTFIFO_CNT 0x0000007F +#define I2S_OUTFIFO_CNT_M (I2S_OUTFIFO_CNT_V << I2S_OUTFIFO_CNT_S) +#define I2S_OUTFIFO_CNT_V 0x0000007F +#define I2S_OUTFIFO_CNT_S 23 + +/* I2S_OUT_STATE : RO; bitpos: [22:20]; default: 0; + * I2S DMA out data state. + */ + +#define I2S_OUT_STATE 0x00000007 +#define I2S_OUT_STATE_M (I2S_OUT_STATE_V << I2S_OUT_STATE_S) +#define I2S_OUT_STATE_V 0x00000007 +#define I2S_OUT_STATE_S 20 + +/* I2S_OUT_DSCR_STATE : RO; bitpos: [19:18]; default: 0; + * I2S DMA out descriptor state. + */ + +#define I2S_OUT_DSCR_STATE 0x00000003 +#define I2S_OUT_DSCR_STATE_M (I2S_OUT_DSCR_STATE_V << I2S_OUT_DSCR_STATE_S) +#define I2S_OUT_DSCR_STATE_V 0x00000003 +#define I2S_OUT_DSCR_STATE_S 18 + +/* I2S_OUTLINK_DSCR_ADDR : RO; bitpos: [17:0]; default: 0; + * I2S DMA out descriptor address. + */ + +#define I2S_OUTLINK_DSCR_ADDR 0x0003FFFF +#define I2S_OUTLINK_DSCR_ADDR_M (I2S_OUTLINK_DSCR_ADDR_V << I2S_OUTLINK_DSCR_ADDR_S) +#define I2S_OUTLINK_DSCR_ADDR_V 0x0003FFFF +#define I2S_OUTLINK_DSCR_ADDR_S 0 + +/* I2S_LC_STATE1_REG register + * I2S DMA RX status + */ + +#define I2S_LC_STATE1_REG(i) (REG_I2S_BASE(i) + 0x70) + +/* I2S_IN_EMPTY : RO; bitpos: [31]; default: 0; + * I2S DMA infifo is empty. + */ + +#define I2S_IN_EMPTY (BIT(31)) +#define I2S_IN_EMPTY_M (I2S_IN_EMPTY_V << I2S_IN_EMPTY_S) +#define I2S_IN_EMPTY_V 0x00000001 +#define I2S_IN_EMPTY_S 31 + +/* I2S_IN_FULL : RO; bitpos: [30]; default: 0; + * I2S DMA infifo is full. + */ + +#define I2S_IN_FULL (BIT(30)) +#define I2S_IN_FULL_M (I2S_IN_FULL_V << I2S_IN_FULL_S) +#define I2S_IN_FULL_V 0x00000001 +#define I2S_IN_FULL_S 30 + +/* I2S_INFIFO_CNT_DEBUG : RO; bitpos: [29:23]; default: 0; + * The remains of I2S DMA infifo data. + */ + +#define I2S_INFIFO_CNT_DEBUG 0x0000007F +#define I2S_INFIFO_CNT_DEBUG_M (I2S_INFIFO_CNT_DEBUG_V << I2S_INFIFO_CNT_DEBUG_S) +#define I2S_INFIFO_CNT_DEBUG_V 0x0000007F +#define I2S_INFIFO_CNT_DEBUG_S 23 + +/* I2S_IN_STATE : RO; bitpos: [22:20]; default: 0; + * I2S DMA in data state. + */ + +#define I2S_IN_STATE 0x00000007 +#define I2S_IN_STATE_M (I2S_IN_STATE_V << I2S_IN_STATE_S) +#define I2S_IN_STATE_V 0x00000007 +#define I2S_IN_STATE_S 20 + +/* I2S_IN_DSCR_STATE : RO; bitpos: [19:18]; default: 0; + * I2S DMA in descriptor state. + */ + +#define I2S_IN_DSCR_STATE 0x00000003 +#define I2S_IN_DSCR_STATE_M (I2S_IN_DSCR_STATE_V << I2S_IN_DSCR_STATE_S) +#define I2S_IN_DSCR_STATE_V 0x00000003 +#define I2S_IN_DSCR_STATE_S 18 + +/* I2S_INLINK_DSCR_ADDR : RO; bitpos: [17:0]; default: 0; + * I2S DMA in descriptor address. + */ + +#define I2S_INLINK_DSCR_ADDR 0x0003FFFF +#define I2S_INLINK_DSCR_ADDR_M (I2S_INLINK_DSCR_ADDR_V << I2S_INLINK_DSCR_ADDR_S) +#define I2S_INLINK_DSCR_ADDR_V 0x0003FFFF +#define I2S_INLINK_DSCR_ADDR_S 0 + +/* I2S_LC_HUNG_CONF_REG register + * I2S Hung configure register + */ + +#define I2S_LC_HUNG_CONF_REG(i) (REG_I2S_BASE(i) + 0x74) + +/* I2S_LC_FIFO_TIMEOUT_ENA : R/W; bitpos: [11]; default: 1; + * The enable bit for FIFO timeout + */ + +#define I2S_LC_FIFO_TIMEOUT_ENA (BIT(11)) +#define I2S_LC_FIFO_TIMEOUT_ENA_M (I2S_LC_FIFO_TIMEOUT_ENA_V << I2S_LC_FIFO_TIMEOUT_ENA_S) +#define I2S_LC_FIFO_TIMEOUT_ENA_V 0x00000001 +#define I2S_LC_FIFO_TIMEOUT_ENA_S 11 + +/* I2S_LC_FIFO_TIMEOUT_SHIFT : R/W; bitpos: [10:8]; default: 0; + * The bits are used to scale tick counter threshold. The tick counter is + * reset when counter value >= 88000/2^i2s_lc_fifo_timeout_shift + */ + +#define I2S_LC_FIFO_TIMEOUT_SHIFT 0x00000007 +#define I2S_LC_FIFO_TIMEOUT_SHIFT_M (I2S_LC_FIFO_TIMEOUT_SHIFT_V << I2S_LC_FIFO_TIMEOUT_SHIFT_S) +#define I2S_LC_FIFO_TIMEOUT_SHIFT_V 0x00000007 +#define I2S_LC_FIFO_TIMEOUT_SHIFT_S 8 + +/* I2S_LC_FIFO_TIMEOUT : R/W; bitpos: [7:0]; default: 16; + * the i2s_tx_hung_int interrupt or the i2s_rx_hung_int interrupt will be + * triggered when fifo hung counter is equal to this value + */ + +#define I2S_LC_FIFO_TIMEOUT 0x000000FF +#define I2S_LC_FIFO_TIMEOUT_M (I2S_LC_FIFO_TIMEOUT_V << I2S_LC_FIFO_TIMEOUT_S) +#define I2S_LC_FIFO_TIMEOUT_V 0x000000FF +#define I2S_LC_FIFO_TIMEOUT_S 0 + +/* I2S_CONF1_REG register + * I2S configure1 register + */ + +#define I2S_CONF1_REG(i) (REG_I2S_BASE(i) + 0xa0) + +/* I2S_TX_ZEROS_RM_EN : R/W; bitpos: [9]; default: 0; + * don't use + */ + +#define I2S_TX_ZEROS_RM_EN (BIT(9)) +#define I2S_TX_ZEROS_RM_EN_M (I2S_TX_ZEROS_RM_EN_V << I2S_TX_ZEROS_RM_EN_S) +#define I2S_TX_ZEROS_RM_EN_V 0x00000001 +#define I2S_TX_ZEROS_RM_EN_S 9 + +/* I2S_TX_STOP_EN : R/W; bitpos: [8]; default: 0; + * Set this bit to stop disable output BCK signal and WS signal when tx FIFO + * is emtpy + */ + +#define I2S_TX_STOP_EN (BIT(8)) +#define I2S_TX_STOP_EN_M (I2S_TX_STOP_EN_V << I2S_TX_STOP_EN_S) +#define I2S_TX_STOP_EN_V 0x00000001 +#define I2S_TX_STOP_EN_S 8 + +/* I2S_RX_PCM_BYPASS : R/W; bitpos: [7]; default: 1; + * Set this bit to bypass Compress/Decompress module for received data. + */ + +#define I2S_RX_PCM_BYPASS (BIT(7)) +#define I2S_RX_PCM_BYPASS_M (I2S_RX_PCM_BYPASS_V << I2S_RX_PCM_BYPASS_S) +#define I2S_RX_PCM_BYPASS_V 0x00000001 +#define I2S_RX_PCM_BYPASS_S 7 + +/* I2S_RX_PCM_CONF : R/W; bitpos: [6:4]; default: 0; + * Compress/Decompress module configuration bits. 0: decompress received + * data 1:compress received data + */ + +#define I2S_RX_PCM_CONF 0x00000007 +#define I2S_RX_PCM_CONF_M (I2S_RX_PCM_CONF_V << I2S_RX_PCM_CONF_S) +#define I2S_RX_PCM_CONF_V 0x00000007 +#define I2S_RX_PCM_CONF_S 4 + +/* I2S_TX_PCM_BYPASS : R/W; bitpos: [3]; default: 1; + * Set this bit to bypass Compress/Decompress module for transmitted data. + */ + +#define I2S_TX_PCM_BYPASS (BIT(3)) +#define I2S_TX_PCM_BYPASS_M (I2S_TX_PCM_BYPASS_V << I2S_TX_PCM_BYPASS_S) +#define I2S_TX_PCM_BYPASS_V 0x00000001 +#define I2S_TX_PCM_BYPASS_S 3 + +/* I2S_TX_PCM_CONF : R/W; bitpos: [2:0]; default: 1; + * Compress/Decompress module configuration bits. 0: decompress transmitted + * data 1:compress transmitted data + */ + +#define I2S_TX_PCM_CONF 0x00000007 +#define I2S_TX_PCM_CONF_M (I2S_TX_PCM_CONF_V << I2S_TX_PCM_CONF_S) +#define I2S_TX_PCM_CONF_V 0x00000007 +#define I2S_TX_PCM_CONF_S 0 + +/* I2S_PD_CONF_REG register + * I2S power down configure register + */ + +#define I2S_PD_CONF_REG(i) (REG_I2S_BASE(i) + 0xa4) + +/* I2S_PLC_MEM_FORCE_PU : R/W; bitpos: [3]; default: 1; + * Force I2S memory power-up + */ #define I2S_PLC_MEM_FORCE_PU (BIT(3)) -#define I2S_PLC_MEM_FORCE_PU_M (BIT(3)) -#define I2S_PLC_MEM_FORCE_PU_V 0x1 +#define I2S_PLC_MEM_FORCE_PU_M (I2S_PLC_MEM_FORCE_PU_V << I2S_PLC_MEM_FORCE_PU_S) +#define I2S_PLC_MEM_FORCE_PU_V 0x00000001 #define I2S_PLC_MEM_FORCE_PU_S 3 -/* I2S_FIFO_FORCE_PU : R/W ;bitpos:[1] ;default: 1'h1 ; */ +/* I2S_PLC_MEM_FORCE_PD : R/W; bitpos: [2]; default: 0; + * Force I2S memory power-down + */ -#define I2S_FIFO_FORCE_PU (BIT(1)) -#define I2S_FIFO_FORCE_PU_M (BIT(1)) -#define I2S_FIFO_FORCE_PU_V 0x1 -#define I2S_FIFO_FORCE_PU_S 1 +#define I2S_PLC_MEM_FORCE_PD (BIT(2)) +#define I2S_PLC_MEM_FORCE_PD_M (I2S_PLC_MEM_FORCE_PD_V << I2S_PLC_MEM_FORCE_PD_S) +#define I2S_PLC_MEM_FORCE_PD_V 0x00000001 +#define I2S_PLC_MEM_FORCE_PD_S 2 + +/* I2S_FIFO_FORCE_PU : R/W; bitpos: [1]; default: 1; + * Force FIFO power-up + */ + +#define I2S_FIFO_FORCE_PU (BIT(1)) +#define I2S_FIFO_FORCE_PU_M (I2S_FIFO_FORCE_PU_V << I2S_FIFO_FORCE_PU_S) +#define I2S_FIFO_FORCE_PU_V 0x00000001 +#define I2S_FIFO_FORCE_PU_S 1 + +/* I2S_FIFO_FORCE_PD : R/W; bitpos: [0]; default: 0; + * Force FIFO power-down + */ + +#define I2S_FIFO_FORCE_PD (BIT(0)) +#define I2S_FIFO_FORCE_PD_M (I2S_FIFO_FORCE_PD_V << I2S_FIFO_FORCE_PD_S) +#define I2S_FIFO_FORCE_PD_V 0x00000001 +#define I2S_FIFO_FORCE_PD_S 0 + +/* I2S_CONF2_REG register + * I2S configure2 register + */ + +#define I2S_CONF2_REG(i) (REG_I2S_BASE(i) + 0xa8) + +/* I2S_INTER_VALID_EN : R/W; bitpos: [7]; default: 0; + * Set this bit to enable camera internal valid + */ + +#define I2S_INTER_VALID_EN (BIT(7)) +#define I2S_INTER_VALID_EN_M (I2S_INTER_VALID_EN_V << I2S_INTER_VALID_EN_S) +#define I2S_INTER_VALID_EN_V 0x00000001 +#define I2S_INTER_VALID_EN_S 7 + +/* I2S_EXT_ADC_START_EN : R/W; bitpos: [6]; default: 0; + * Set this bit to enable the function that ADC mode is triggered by + * external signal. + */ + +#define I2S_EXT_ADC_START_EN (BIT(6)) +#define I2S_EXT_ADC_START_EN_M (I2S_EXT_ADC_START_EN_V << I2S_EXT_ADC_START_EN_S) +#define I2S_EXT_ADC_START_EN_V 0x00000001 +#define I2S_EXT_ADC_START_EN_S 6 + +/* I2S_LCD_EN : R/W; bitpos: [5]; default: 0; + * Set this bit to enable LCD mode + */ + +#define I2S_LCD_EN (BIT(5)) +#define I2S_LCD_EN_M (I2S_LCD_EN_V << I2S_LCD_EN_S) +#define I2S_LCD_EN_V 0x00000001 +#define I2S_LCD_EN_S 5 + +/* I2S_LCD_TX_SDX2_EN : R/W; bitpos: [2]; default: 0; + * Set this bit to duplicate data pairs (Frame Form 2) in LCD mode. + */ + +#define I2S_LCD_TX_SDX2_EN (BIT(2)) +#define I2S_LCD_TX_SDX2_EN_M (I2S_LCD_TX_SDX2_EN_V << I2S_LCD_TX_SDX2_EN_S) +#define I2S_LCD_TX_SDX2_EN_V 0x00000001 +#define I2S_LCD_TX_SDX2_EN_S 2 + +/* I2S_LCD_TX_WRX2_EN : R/W; bitpos: [1]; default: 0; + * LCD WR double for one datum. + */ + +#define I2S_LCD_TX_WRX2_EN (BIT(1)) +#define I2S_LCD_TX_WRX2_EN_M (I2S_LCD_TX_WRX2_EN_V << I2S_LCD_TX_WRX2_EN_S) +#define I2S_LCD_TX_WRX2_EN_V 0x00000001 +#define I2S_LCD_TX_WRX2_EN_S 1 + +/* I2S_CAMERA_EN : R/W; bitpos: [0]; default: 0; + * Set this bit to enable camera mode + */ + +#define I2S_CAMERA_EN (BIT(0)) +#define I2S_CAMERA_EN_M (I2S_CAMERA_EN_V << I2S_CAMERA_EN_S) +#define I2S_CAMERA_EN_V 0x00000001 +#define I2S_CAMERA_EN_S 0 + +/* I2S_CLKM_CONF_REG register + * I2S module clock configure register + */ + +#define I2S_CLKM_CONF_REG(i) (REG_I2S_BASE(i) + 0xac) + +/* I2S_CLKA_ENA : R/W; bitpos: [21]; default: 0; + * Set this bit to enable clk_apll. + */ + +#define I2S_CLKA_ENA (BIT(21)) +#define I2S_CLKA_ENA_M (I2S_CLKA_ENA_V << I2S_CLKA_ENA_S) +#define I2S_CLKA_ENA_V 0x00000001 +#define I2S_CLKA_ENA_S 21 + +/* I2S_CLK_ENA : R/W; bitpos: [21]; default: 0; + * Set this bit to enable clk_apll. + */ + +#define I2S_CLK_ENA (BIT(20)) +#define I2S_CLK_ENA_M (I2S_CLK_ENA_V << I2S_CLK_ENA_S) +#define I2S_CLK_ENA_V 0x00000001 +#define I2S_CLK_ENA_S 20 + +/* I2S_CLKM_DIV_A : R/W; bitpos: [19:14]; default: 0; + * Fractional clock divider denominator value + */ + +#define I2S_CLKM_DIV_A 0x0000003F +#define I2S_CLKM_DIV_A_M (I2S_CLKM_DIV_A_V << I2S_CLKM_DIV_A_S) +#define I2S_CLKM_DIV_A_V 0x0000003F +#define I2S_CLKM_DIV_A_S 14 + +/* I2S_CLKM_DIV_B : R/W; bitpos: [13:8]; default: 0; + * Fractional clock divider numerator value + */ + +#define I2S_CLKM_DIV_B 0x0000003F +#define I2S_CLKM_DIV_B_M (I2S_CLKM_DIV_B_V << I2S_CLKM_DIV_B_S) +#define I2S_CLKM_DIV_B_V 0x0000003F +#define I2S_CLKM_DIV_B_S 8 + +/* I2S_CLKM_DIV_NUM : R/W; bitpos: [7:0]; default: 4; + * Integral I2S clock divider value + */ + +#define I2S_CLKM_DIV_NUM 0x000000FF +#define I2S_CLKM_DIV_NUM_M (I2S_CLKM_DIV_NUM_V << I2S_CLKM_DIV_NUM_S) +#define I2S_CLKM_DIV_NUM_V 0x000000FF +#define I2S_CLKM_DIV_NUM_S 0 + +/* I2S_SAMPLE_RATE_CONF_REG register + * I2S sample rate register + */ + +#define I2S_SAMPLE_RATE_CONF_REG(i) (REG_I2S_BASE(i) + 0xb0) + +/* I2S_RX_BITS_MOD : R/W; bitpos: [23:18]; default: 16; + * Set the bits to configure bit length of I2S receiver channel. + */ + +#define I2S_RX_BITS_MOD 0x0000003F +#define I2S_RX_BITS_MOD_M (I2S_RX_BITS_MOD_V << I2S_RX_BITS_MOD_S) +#define I2S_RX_BITS_MOD_V 0x0000003F +#define I2S_RX_BITS_MOD_S 18 + +/* I2S_TX_BITS_MOD : R/W; bitpos: [17:12]; default: 16; + * Set the bits to configure bit length of I2S transmitter channel. + */ + +#define I2S_TX_BITS_MOD 0x0000003F +#define I2S_TX_BITS_MOD_M (I2S_TX_BITS_MOD_V << I2S_TX_BITS_MOD_S) +#define I2S_TX_BITS_MOD_V 0x0000003F +#define I2S_TX_BITS_MOD_S 12 + +/* I2S_RX_BCK_DIV_NUM : R/W; bitpos: [11:6]; default: 6; + * Bit clock configuration bits in receiver mode. + */ + +#define I2S_RX_BCK_DIV_NUM 0x0000003F +#define I2S_RX_BCK_DIV_NUM_M (I2S_RX_BCK_DIV_NUM_V << I2S_RX_BCK_DIV_NUM_S) +#define I2S_RX_BCK_DIV_NUM_V 0x0000003F +#define I2S_RX_BCK_DIV_NUM_S 6 + +/* I2S_TX_BCK_DIV_NUM : R/W; bitpos: [5:0]; default: 6; + * Bit clock configuration bits in transmitter mode. + */ + +#define I2S_TX_BCK_DIV_NUM 0x0000003F +#define I2S_TX_BCK_DIV_NUM_M (I2S_TX_BCK_DIV_NUM_V << I2S_TX_BCK_DIV_NUM_S) +#define I2S_TX_BCK_DIV_NUM_V 0x0000003F +#define I2S_TX_BCK_DIV_NUM_S 0 + +/* I2S_PDM_CONF_REG register + * I2S PDM configuration register + */ + +#define I2S_PDM_CONF_REG(i) (REG_I2S_BASE(i) + 0xb4) + +/* I2S_TX_PDM_HP_BYPASS : R/W; bitpos: [25]; default: 0; + * Set this bit to bypass the transmitter's PDM HP filter. + */ + +#define I2S_TX_PDM_HP_BYPASS BIT(25) +#define I2S_TX_PDM_HP_BYPASS_M (I2S_TX_PDM_HP_BYPASS_V << I2S_TX_PDM_HP_BYPASS_S) +#define I2S_TX_PDM_HP_BYPASS_V 0x00000001 +#define I2S_TX_PDM_HP_BYPASS_S 25 + +/* I2S_RX_PDM_SINC_DSR_16_EN : R/W; bitpos: [24]; default: 1; + * PDM downsampling rate for filter group 1 in receiver mode. + * 1: downsampling rate = 128; 0: downsampling rate = 64 + */ + +#define I2S_RX_PDM_SINC_DSR_16_EN BIT(24) +#define I2S_RX_PDM_SINC_DSR_16_EN_M (I2S_RX_PDM_SINC_DSR_16_EN_V << I2S_RX_PDM_SINC_DSR_16_EN_S) +#define I2S_RX_PDM_SINC_DSR_16_EN_V 0x00000001 +#define I2S_RX_PDM_SINC_DSR_16_EN_S 24 + +/* I2S_TX_PDM_SIGMADELTA_IN_SHIFT : R/W; bitpos: [23:22]; default: 1; + * Adjust the size of the input signal into filter module. + * 0: divided by 2; 1: multiplied by 1; + * 2: multiplied by 2; 3: multiplied by 4. + */ + +#define I2S_TX_PDM_SIGMADELTA_IN_SHIFT 0x00000003 +#define I2S_TX_PDM_SIGMADELTA_IN_SHIFT_M (I2S_TX_PDM_SIGMADELTA_IN_SHIFT_V << I2S_TX_PDM_SIGMADELTA_IN_SHIFT_S) +#define I2S_TX_PDM_SIGMADELTA_IN_SHIFT_V 0x00000003 +#define I2S_TX_PDM_SIGMADELTA_IN_SHIFT_S 22 + +/* I2S_TX_PDM_SINC_IN_SHIFT : R/W; bitpos: [21:20]; default: 1; + * Adjust the size of the input signal into filter module. + * 0: divided by 2; 1: multiplied by 1; + * 2: multiplied by 2; 3: multiplied by 4. + */ + +#define I2S_TX_PDM_SINC_IN_SHIFT 0x00000003 +#define I2S_TX_PDM_SINC_IN_SHIFT_M (I2S_TX_PDM_SINC_IN_SHIFT_V << I2S_TX_PDM_SINC_IN_SHIFT_S) +#define I2S_TX_PDM_SINC_IN_SHIFT_V 0x00000003 +#define I2S_TX_PDM_SINC_IN_SHIFT_S 20 + +/* I2S_TX_PDM_LP_IN_SHIFT : R/W; bitpos: [19:18]; default: 1; + * Adjust the size of the input signal into filter module. + * 0: divided by 2; 1: multiplied by 1; + * 2: multiplied by 2; 3: multiplied by 4. + */ + +#define I2S_TX_PDM_LP_IN_SHIFT 0x00000003 +#define I2S_TX_PDM_LP_IN_SHIFT_M (I2S_TX_PDM_LP_IN_SHIFT_V << I2S_TX_PDM_LP_IN_SHIFT_S) +#define I2S_TX_PDM_LP_IN_SHIFT_V 0x00000003 +#define I2S_TX_PDM_LP_IN_SHIFT_S 18 + +/* I2S_TX_PDM_HP_IN_SHIFT : R/W; bitpos: [17:16]; default: 1; + * Adjust the size of the input signal into filter module. + * 0: divided by 2; 1: multiplied by 1; + * 2: multiplied by 2; 3: multiplied by 4. + */ + +#define I2S_TX_PDM_HP_IN_SHIFT 0x00000003 +#define I2S_TX_PDM_HP_IN_SHIFT_M (I2S_TX_PDM_HP_IN_SHIFT_V << I2S_TX_PDM_HP_IN_SHIFT_S) +#define I2S_TX_PDM_HP_IN_SHIFT_V 0x00000003 +#define I2S_TX_PDM_HP_IN_SHIFT_S 16 + +/* I2S_TX_PDM_SINC_OSR2 : R/W; bitpos: [7:4]; default: 2; + * Upsampling rate = 64×i2s_tx_pdm_sinc_osr2 + */ + +#define I2S_TX_PDM_SINC_OSR2 0x0000000F +#define I2S_TX_PDM_SINC_OSR2_M (I2S_TX_PDM_SINC_OSR2_V << I2S_TX_PDM_SINC_OSR2_S) +#define I2S_TX_PDM_SINC_OSR2_V 0x0000000F +#define I2S_TX_PDM_SINC_OSR2_S 4 + +/* I2S_PDM2PCM_CONV_EN : R/W; bitpos: [3]; default: 1; + * Set this bit to enable PDM-to-PCM converter. + */ + +#define I2S_PDM2PCM_CONV_EN BIT(3) +#define I2S_PDM2PCM_CONV_EN_M (I2S_PDM2PCM_CONV_EN_V << I2S_PDM2PCM_CONV_EN_S) +#define I2S_PDM2PCM_CONV_EN_V 0x00000001 +#define I2S_PDM2PCM_CONV_EN_S 3 + +/* I2S_PCM2PDM_CONV_EN : R/W; bitpos: [2]; default: 1; + * Set this bit to enable PCM-to-PDM converter. + */ + +#define I2S_PCM2PDM_CONV_EN BIT(2) +#define I2S_PCM2PDM_CONV_EN_M (I2S_PCM2PDM_CONV_EN_V << I2S_PCM2PDM_CONV_EN_S) +#define I2S_PCM2PDM_CONV_EN_V 0x00000001 +#define I2S_PCM2PDM_CONV_EN_S 2 + +/* I2S_RX_PDM_EN : R/W; bitpos: [1]; default: 0; + * Set this bit to enable receiver’s PDM mode. + */ + +#define I2S_RX_PDM_EN BIT(1) +#define I2S_RX_PDM_EN_M (I2S_RX_PDM_EN_V << I2S_RX_PDM_EN_S) +#define I2S_RX_PDM_EN_V 0x00000001 +#define I2S_RX_PDM_EN_S 1 + +/* I2S_TX_PDM_EN : R/W; bitpos: [0]; default: 0; + * Set this bit to enable transmitter’s PDM mode. + */ + +#define I2S_TX_PDM_EN BIT(0) +#define I2S_TX_PDM_EN_M (I2S_TX_PDM_EN_V << I2S_TX_PDM_EN_S) +#define I2S_TX_PDM_EN_V 0x00000001 +#define I2S_TX_PDM_EN_S 0 + +/* I2S_PDM_FREQ_CONF_REG register + * I2S PDM frequencies register + */ + +#define I2S_PDM_FREQ_CONF_REG(i) (REG_I2S_BASE(i) + 0xb8) + +/* I2S_TX_PDM_FP : R/W; bitpos: [19:10]; default: 960; + * PCM-to-PDM converter’s PDM frequency parameter. + */ + +#define I2S_TX_PDM_FP 0x000003FF +#define I2S_TX_PDM_FP_M (I2S_TX_PDM_FP_V << I2S_TX_PDM_FP_S) +#define I2S_TX_PDM_FP_V 0x000003FF +#define I2S_TX_PDM_FP_S 10 + +/* I2S_TX_PDM_FS : R/W; bitpos: [9:0]; default: 441; + * PCM-to-PDM converter’s PCM frequency parameter. + */ + +#define I2S_TX_PDM_FS 0x000003FF +#define I2S_TX_PDM_FS_M (I2S_TX_PDM_FS_V << I2S_TX_PDM_FS_S) +#define I2S_TX_PDM_FS_V 0x000003FF +#define I2S_TX_PDM_FS_S 0 + +/* I2S_STATE_REG register + * I2S TX status register + */ + +#define I2S_STATE_REG(i) (REG_I2S_BASE(i) + 0xbc) + +/* I2S_RX_FIFO_RESET_BACK : RO; bitpos: [2]; default: 0; + * This bit is used to confirm if the Rx FIFO reset is done. + * 1: reset is not ready; 0: reset is ready. + */ + +#define I2S_RX_FIFO_RESET_BACK (BIT(2)) +#define I2S_RX_FIFO_RESET_BACK_M (I2S_RX_FIFO_RESET_BACK_V << I2S_RX_FIFO_RESET_BACK_S) +#define I2S_RX_FIFO_RESET_BACK_V 0x00000001 +#define I2S_RX_FIFO_RESET_BACK_S 2 + +/* I2S_TX_FIFO_RESET_BACK : RO; bitpos: [1]; default: 0; + * 1: I2S TX is in idle state. 0: I2S TX is busy. + */ + +#define I2S_TX_FIFO_RESET_BACK (BIT(1)) +#define I2S_TX_FIFO_RESET_BACK_M (I2S_TX_FIFO_RESET_BACK_V << I2S_TX_FIFO_RESET_BACK_S) +#define I2S_TX_FIFO_RESET_BACK_V 0x00000001 +#define I2S_TX_FIFO_RESET_BACK_S 1 + +/* I2S_TX_IDLE : RO; bitpos: [0]; default: 1; + * 1: I2S TX is in idle state. 0: I2S TX is busy. + */ + +#define I2S_TX_IDLE (BIT(0)) +#define I2S_TX_IDLE_M (I2S_TX_IDLE_V << I2S_TX_IDLE_S) +#define I2S_TX_IDLE_V 0x00000001 +#define I2S_TX_IDLE_S 0 #endif /* __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_I2S_H */ diff --git a/boards/xtensa/esp32/common/src/Make.defs b/boards/xtensa/esp32/common/src/Make.defs index a6f53e6476..fdfde999db 100644 --- a/boards/xtensa/esp32/common/src/Make.defs +++ b/boards/xtensa/esp32/common/src/Make.defs @@ -32,6 +32,10 @@ ifeq ($(CONFIG_I2C_DRIVER),y) CSRCS += esp32_board_i2c.c endif +ifeq ($(CONFIG_ESP32_I2S),y) + CSRCS += esp32_board_i2sdev.c +endif + ifeq ($(CONFIG_I2CMULTIPLEXER_TCA9548A),y) CSRCS += esp32_tca9548a.c endif diff --git a/boards/xtensa/esp32/common/src/esp32_board_i2sdev.c b/boards/xtensa/esp32/common/src/esp32_board_i2sdev.c new file mode 100644 index 0000000000..4ac9555a9b --- /dev/null +++ b/boards/xtensa/esp32/common/src/esp32_board_i2sdev.c @@ -0,0 +1,109 @@ +/**************************************************************************** + * boards/xtensa/esp32/common/src/esp32_board_i2sdev.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "esp32_i2s.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_i2sdev_initialize + * + * Description: + * This function is called by platform-specific, setup logic to configure + * and register the generic I2S audio driver. This function will register + * the driver as /dev/audio/pcm[x] where x is determined by the I2S port + * number. + * + * Input Parameters: + * port - The I2S port used for the device + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int board_i2sdev_initialize(int port) +{ + struct audio_lowerhalf_s *audio_i2s; + struct audio_lowerhalf_s *pcm; + struct i2s_dev_s *i2s; + char devname[12]; + int ret; + + ainfo("Initializing I2S\n"); + + i2s = esp32_i2sbus_initialize(port); + +#ifdef CONFIG_AUDIO_I2SCHAR + ret = i2schar_register(i2s, 0); + if (ret < 0) + { + aerr("ERROR: i2schar_register failed: %d\n", ret); + return ret; + } +#endif + + audio_i2s = audio_i2s_initialize(i2s, true); + + if (!audio_i2s) + { + auderr("ERROR: Failed to initialize I2S\n"); + return -ENODEV; + } + + pcm = pcm_decode_initialize(audio_i2s); + + if (!pcm) + { + auderr("ERROR: Failed create the PCM decoder\n"); + return -ENODEV; + } + + snprintf(devname, 12, "pcm%d", port); + + ret = audio_register(devname, pcm); + + if (ret < 0) + { + auderr("ERROR: Failed to register /dev/%s device: %d\n", devname, ret); + } + + return ret; +} diff --git a/boards/xtensa/esp32/esp32-devkitc/configs/i2schar/defconfig b/boards/xtensa/esp32/esp32-devkitc/configs/i2schar/defconfig new file mode 100644 index 0000000000..dcf9c709fa --- /dev/null +++ b/boards/xtensa/esp32/esp32-devkitc/configs/i2schar/defconfig @@ -0,0 +1,62 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_ESP32_I2S0_RX is not set +# CONFIG_NDEBUG is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +# CONFIG_NSH_CMDPARMS is not set +CONFIG_ARCH="xtensa" +CONFIG_ARCH_BOARD="esp32-devkitc" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32_DEVKITC=y +CONFIG_ARCH_CHIP="esp32" +CONFIG_ARCH_CHIP_ESP32=y +CONFIG_ARCH_CHIP_ESP32WROVER=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_XTENSA=y +CONFIG_AUDIO=y +CONFIG_AUDIO_I2S=y +CONFIG_AUDIO_I2SCHAR=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DRIVERS_AUDIO=y +CONFIG_ESP32_I2S0=y +CONFIG_ESP32_I2S0_MCLK=y +CONFIG_ESP32_I2S=y +CONFIG_ESP32_UART0=y +CONFIG_EXAMPLES_I2SCHAR=y +CONFIG_EXAMPLES_I2SCHAR_TX=y +CONFIG_EXAMPLES_I2SCHAR_TXBUFFERS=2 +CONFIG_EXAMPLES_I2SCHAR_TXSTACKSIZE=4096 +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=4096 +CONFIG_INTELHEX_BINARY=y +CONFIG_MM_REGIONS=3 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_NSH=y +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/xtensa/esp32/esp32-devkitc/src/esp32-devkitc.h b/boards/xtensa/esp32/esp32-devkitc/src/esp32-devkitc.h index b919197eae..6f64f0d3d5 100644 --- a/boards/xtensa/esp32/esp32-devkitc/src/esp32-devkitc.h +++ b/boards/xtensa/esp32/esp32-devkitc/src/esp32-devkitc.h @@ -151,5 +151,27 @@ int board_spidev_initialize(int bus); int esp32_twai_setup(void); #endif +/**************************************************************************** + * Name: board_i2sdev_initialize + * + * Description: + * This function is called by platform-specific, setup logic to configure + * and register the generic I2S audio driver. This function will register + * the driver as /dev/audio/pcm[x] where x is determined by the I2S port + * number. + * + * Input Parameters: + * port - The I2S port used for the device + * + * Returned Value: + * Zero is returned on success. Otherwise, a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +#if defined CONFIG_ESP32_I2S0 || defined CONFIG_ESP32_I2S1 +int board_i2sdev_initialize(int port); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __BOARDS_XTENSA_ESP32_ESP32_DEVKITC_SRC_ESP32_DEVKITC_H */ diff --git a/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c index 766c5d9cd1..a5849946b4 100644 --- a/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c +++ b/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c @@ -87,6 +87,10 @@ # include "esp32_board_i2c.h" #endif +#ifdef CONFIG_ESP32_I2S +# include "esp32_i2s.h" +#endif + #ifdef CONFIG_I2CMULTIPLEXER_TCA9548A # include "esp32_tca9548a.h" #endif @@ -453,6 +457,36 @@ int esp32_bringup(void) } #endif +#ifdef CONFIG_ESP32_I2S + +#ifdef CONFIG_ESP32_I2S0 + + /* Configure I2S generic audio on I2S0 */ + + ret = board_i2sdev_initialize(ESP32_I2S0); + if (ret < 0) + { + syslog(LOG_ERR, "Failed to initialize I2S%d driver: %d\n", + CONFIG_ESP32_I2S0, ret); + } + +#endif /* CONFIG_ESP32_I2S0 */ + +#ifdef CONFIG_ESP32_I2S1 + + /* Configure I2S generic audio on I2S1 */ + + ret = board_i2sdev_initialize(ESP32_I2S1); + if (ret < 0) + { + syslog(LOG_ERR, "Failed to initialize I2S%d driver: %d\n", + CONFIG_ESP32_I2S0, ret); + } + +#endif /* CONFIG_ESP32_I2S1 */ + +#endif /* CONFIG_ESP32_I2S */ + #ifdef CONFIG_SENSORS_SHT3X /* Try to register SHT3x device in I2C0 */