STM32F4: add cs43l22 audio driver and i2s driver

This commit is contained in:
Taras Drozdovsky 2017-05-21 14:14:09 -06:00 committed by Gregory Nutt
parent 679a08e371
commit 4ab2a3661e
16 changed files with 6211 additions and 5 deletions

@ -1530,6 +1530,7 @@ config STM32_STM32F40XX
select STM32_HAVE_TIM4
select STM32_HAVE_SPI2
select STM32_HAVE_SPI3
select STM32_HAVE_I2S3
select STM32_HAVE_I2C2
select STM32_HAVE_I2C3
@ -1542,6 +1543,9 @@ config STM32_STM32F401
select STM32_HAVE_TIM9
select STM32_HAVE_TIM10
select STM32_HAVE_TIM11
select STM32_HAVE_SPI2
select STM32_HAVE_SPI3
select STM32_HAVE_I2S3
config STM32_STM32F410
bool
@ -1563,6 +1567,9 @@ config STM32_STM32F411
select STM32_HAVE_TIM9
select STM32_HAVE_TIM10
select STM32_HAVE_TIM11
select STM32_HAVE_SPI2
select STM32_HAVE_SPI3
select STM32_HAVE_I2S3
select STM32_HAVE_SPI4
select STM32_HAVE_SPI5
@ -1655,6 +1662,9 @@ config STM32_STM32F427
select STM32_HAVE_DAC2
select STM32_HAVE_RNG
select STM32_HAVE_ETHMAC
select STM32_HAVE_SPI2
select STM32_HAVE_SPI3
select STM32_HAVE_I2S3
select STM32_HAVE_SPI4
select STM32_HAVE_SPI5
select STM32_HAVE_SPI6
@ -1691,6 +1701,9 @@ config STM32_STM32F429
select STM32_HAVE_DAC2
select STM32_HAVE_RNG
select STM32_HAVE_ETHMAC
select STM32_HAVE_SPI2
select STM32_HAVE_SPI3
select STM32_HAVE_I2S3
select STM32_HAVE_SPI4
select STM32_HAVE_SPI5
select STM32_HAVE_SPI6
@ -2016,6 +2029,10 @@ config STM32_HAVE_SPI3
bool
default n
config STM32_HAVE_I2S3
bool
default n
config STM32_HAVE_SPI4
bool
default n
@ -2353,6 +2370,13 @@ config STM32_SPI3
select SPI
select STM32_SPI
config STM32_I2S3
bool "I2S3"
default n
depends on STM32_HAVE_I2S3
select I2S
select STM32_I2S
config STM32_SPI4
bool "SPI4"
default n
@ -2610,6 +2634,11 @@ config STM32_SPI3_REMAP
default n
depends on STM32_STM32F10XX && STM32_SPI3 && !STM32_VALUELINE
config STM32_I2S3_REMAP
bool "I2S3 Alternate Pin Mapping"
default n
depends on STM32_STM32F10XX && STM32_I2S3 && !STM32_VALUELINE
choice
prompt "TIM1 Alternate Pin Mappings"
depends on STM32_STM32F10XX && STM32_TIM1
@ -6270,6 +6299,66 @@ config STM32_SPI_DMA
endmenu
menu "I2S Configuration"
depends on STM32_I2S3
config STM32_I2S_MCK
bool "I2S_MCK"
default n
---help---
TBD.
config STM32_I2S_MAXINFLIGHT
int "I2S queue size"
default 16
---help---
This is the total number of transfers, both RX and TX, that can be
enqueue before the caller is required to wait. This setting
determines the number certain queue data structures that will be
pre-allocated.
comment "I2S3 Configuration"
config STM32_I2S3_DATALEN
int "Data width (bits)"
default 16
---help---
Data width in bits. This is a default value and may be change
via the I2S interface
#if STM32_I2S
config STM32_I2S3_RX
bool "Enable I2C receiver"
default n
---help---
Enable I2S receipt logic
config STM32_I2S3_TX
bool "Enable I2C transmitter"
default n
---help---
Enable I2S transmission logic
config STM32_I2S_DMADEBUG
bool "I2S DMA transfer debug"
depends on DEBUG_DMA
default n
---help---
Enable special debug instrumentation analyze I2S DMA data transfers.
This logic is as non-invasive as possible: It samples DMA
registers at key points in the data transfer and then dumps all of
the registers at the end of the transfer.
config STM32_I2S_REGDEBUG
bool "SSC Register level debug"
depends on DEBUG
default n
---help---
Output detailed register-level SSC device debug information.
Very invasive! Requires also DEBUG.
endmenu # I2S Configuration
menu "I2C Configuration"
depends on STM32_I2C

@ -101,7 +101,7 @@ CHIP_ASRCS =
CHIP_CSRCS = stm32_allocateheap.c stm32_start.c stm32_rcc.c stm32_lse.c
CHIP_CSRCS += stm32_lsi.c stm32_gpio.c stm32_exti_gpio.c stm32_flash.c
CHIP_CSRCS += stm32_irq.c stm32_dma.c stm32_lowputc.c
CHIP_CSRCS += stm32_serial.c stm32_spi.c stm32_sdio.c stm32_tim.c
CHIP_CSRCS += stm32_serial.c stm32_spi.c stm32_i2s.c stm32_sdio.c stm32_tim.c
CHIP_CSRCS += stm32_waste.c stm32_ccm.c stm32_uid.c stm32_capture.c
ifeq ($(CONFIG_TIMER),y)

@ -615,7 +615,7 @@
#endif
#define GPIO_SPI3_MISO_1 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN4)
#define GPIO_SPI3_MISO_2 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTC|GPIO_PIN11)
#define GPIO_SPI3_MISO_2 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTC|GPIO_PIN7)
#define GPIO_SPI3_MOSI_1 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN5)
#define GPIO_SPI3_MOSI_2 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTC|GPIO_PIN12)
#define GPIO_SPI3_NSS_1 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTA|GPIO_PIN15)

File diff suppressed because it is too large Load Diff

@ -0,0 +1,90 @@
/************************************************************************************
* arch/arm/src/stm32/stm32_i2s.h
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************************************/
#ifndef __ARCH_ARM_SRC_STM32_I2S_H
#define __ARCH_ARM_SRC_STM32_I2S_H
/************************************************************************************
* Included Files
************************************************************************************/
#include <nuttx/config.h>
#include <nuttx/audio/i2s.h>
#include "chip.h"
#include "chip/stm32_i2s.h"
#ifndef __ASSEMBLY__
/************************************************************************************
* Public Data
************************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/************************************************************************************
* Public Function Prototypes
************************************************************************************/
/************************************************************************************
* Name: stm32_i2sdev_initialize
*
* Description:
* Initialize the selected I2S port
*
* Input Parameter:
* Port number (for hardware that has mutiple I2S interfaces)
*
* Returned Value:
* Valid I2S device structure reference on succcess; a NULL on failure
*
************************************************************************************/
FAR struct i2s_dev_s *stm32_i2sdev_initialize(int port);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_ARM_SRC_STM32_I2S_H */

@ -300,9 +300,9 @@
/* SPI - There is a MEMS device on SPI1 using these pins: */
#define GPIO_SPI1_MISO GPIO_SPI1_MISO_1
#define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_1
#define GPIO_SPI1_SCK GPIO_SPI1_SCK_1
#define GPIO_SPI1_MISO GPIO_SPI1_MISO_1
#define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_1
#define GPIO_SPI1_SCK GPIO_SPI1_SCK_1
/* SPI2 - Test MAX31855 on SPI2 PB10 = SCK, PB14 = MISO */
@ -310,10 +310,38 @@
#define GPIO_SPI2_MOSI GPIO_SPI2_MOSI_1
#define GPIO_SPI2_SCK GPIO_SPI2_SCK_1
/* SPI3 - Onboard devices use SPI3 */
#define GPIO_SPI3_MISO GPIO_SPI3_MISO_2
#define GPIO_SPI3_MOSI GPIO_SPI3_MOSI_2
#define GPIO_SPI3_SCK GPIO_SPI3_SCK_2
#define GPIO_SPI3_NSS GPIO_SPI3_NSS_2
/* I2S3 - Onboard devices use I2S3 */
#define GPIO_I2S3_SD GPIO_I2S3_SD_2
#define GPIO_I2S3_CK GPIO_I2S3_CK_2
#define GPIO_I2S3_WS GPIO_I2S3_WS_1
#define DMACHAN_SPI3_RX DMAMAP_SPI3_RX_2
#define DMACHAN_SPI3_TX DMAMAP_SPI3_TX_2
/* I2C config to use with Nunchuk PB7 (SDA) and PB8 (SCL) */
#if 0
#define GPIO_I2C1_SCL GPIO_I2C1_SCL_2
#define GPIO_I2C1_SDA GPIO_I2C1_SDA_1
#endif
/* I2C. Only I2C1 is available on the stm32f4discovery. I2C1_SCL and I2C1_SDA are
* available on the following pins:
*
* - PB6 is I2C1_SCL
* - PB9 is I2C1_SDA
*/
#define GPIO_I2C1_SCL GPIO_I2C1_SCL_1
#define GPIO_I2C1_SDA GPIO_I2C1_SDA_2
/* Timer Inputs/Outputs (see the README.txt file for options) */

@ -44,6 +44,10 @@ else
CSRCS += stm32_userleds.c
endif
ifeq ($(CONFIG_AUDIO_CS43L22),y)
CSRCS += stm32_cs43l22.c
endif
ifeq ($(CONFIG_ARCH_BUTTONS),y)
CSRCS += stm32_buttons.c
endif

@ -216,6 +216,16 @@ int stm32_bringup(void)
}
#endif
#ifdef HAVE_CS43L22
/* Configure CS43L22 audio */
ret = stm32_cs43l22_initialize(1);
if (ret != OK)
{
serr("Failed to initialize CS43L22 audio: %d\n", ret);
}
#endif
#ifdef HAVE_ELF
/* Initialize the ELF binary loader */

@ -0,0 +1,389 @@
/************************************************************************************
* configs/stm32f4discovery/src/stm32_cs43l22.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Taras Drozdovskiy <t.drozdovskiy@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
************************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdbool.h>
#include <stdio.h>
#include <debug.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/irq.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/audio/i2s.h>
#include <nuttx/audio/pcm.h>
#include <nuttx/audio/cs43l22.h>
#include <arch/board/board.h>
#include "stm32.h"
#include "stm32f4discovery.h"
#ifdef HAVE_CS43L22
/****************************************************************************
* Pre-Processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
struct stm32_mwinfo_s
{
/* Standard CS43L22 interface */
struct cs43l22_lower_s lower;
/* Extensions for the stm32f4discovery board */
cs43l22_handler_t handler;
FAR void *arg;
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* IRQ/PIO access callbacks. These operations all hidden behind
* callbacks to isolate the CS43L22 driver from differences in PIO
* interrupt handling by varying boards and MCUs. If possible,
* interrupts should be configured on both rising and falling edges
* so that contact and loss-of-contact events can be detected.
*
* attach - Attach the CS43L22 interrupt handler to the PIO interrupt
* enable - Enable or disable the PIO interrupt
*/
static int cs43l22_attach(FAR const struct cs43l22_lower_s *lower,
cs43l22_handler_t isr, FAR void *arg);
static bool cs43l22_enable(FAR const struct cs43l22_lower_s *lower,
bool enable);
static void cs43l22_hw_reset(FAR const struct cs43l22_lower_s *lower);
/****************************************************************************
* Private Data
****************************************************************************/
/* A reference to a structure of this type must be passed to the CS43L22
* driver. This structure provides information about the configuration
* of the CS43L22 and provides some board-specific hooks.
*
* Memory for this structure is provided by the caller. It is not copied
* by the driver and is presumed to persist while the driver is active.
*/
#define CONFIG_STM32_CS43L22_I2CFREQUENCY 100000
#define BOARD_MAINCK_FREQUENCY 8000000
static struct stm32_mwinfo_s g_cs43l22info =
{
.lower =
{
.address = CS43L22_I2C_ADDRESS,
.frequency = CONFIG_STM32_CS43L22_I2CFREQUENCY,
#ifdef CONFIG_STM32_CS43L22_SRCSCK
.mclk = BOARD_SLOWCLK_FREQUENCY,
#else
.mclk = BOARD_MAINCK_FREQUENCY,
#endif
.attach = cs43l22_attach,
.enable = cs43l22_enable,
.reset = cs43l22_hw_reset,
},
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* IRQ/PIO access callbacks. These operations all hidden behind
* callbacks to isolate the CS43L22 driver from differences in PIO
* interrupt handling by varying boards and MCUs. If possible,
* interrupts should be configured on both rising and falling edges
* so that contact and loss-of-contact events can be detected.
*
* attach - Attach the CS43L22 interrupt handler to the PIO interrupt
* enable - Enable or disable the PIO interrupt
* clear - Acknowledge/clear any pending PIO interrupt
*
****************************************************************************/
static int cs43l22_attach(FAR const struct cs43l22_lower_s *lower,
cs43l22_handler_t isr, FAR void *arg)
{
if (isr)
{
/* Just save the address of the handler and its argument for now. The
* new handler will called via cs43l22_interrupt() when the interrupt occurs.
*/
audinfo("Attaching %p\n", isr);
g_cs43l22info.handler = isr;
g_cs43l22info.arg = arg;
}
else
{
audinfo("Detaching %p\n", g_cs43l22info.handler);
(void)cs43l22_enable(lower, false);
g_cs43l22info.handler = NULL;
g_cs43l22info.arg = NULL;
}
return OK;
}
static bool cs43l22_enable(FAR const struct cs43l22_lower_s *lower, bool enable)
{
static bool enabled;
irqstate_t flags;
bool ret;
/* Has the interrupt state changed */
flags = enter_critical_section();
if (enable != enabled)
{
/* Enable or disable interrupts */
if (enable && g_cs43l22info.handler)
{
audinfo("Enabling\n");
/* TODO: stm32_pioirqenable(IRQ_INT_CS43L22); */
enabled = true;
}
else
{
audinfo("Disabling\n");
/* TODO: stm32_pioirqdisable(IRQ_INT_CS43L22); */
enabled = false;
}
}
ret = enabled;
leave_critical_section(flags);
return ret;
}
#if 0
static int cs43l22_interrupt(int irq, FAR void *context)
{
Just forward the interrupt to the CS43L22 driver
audinfo("handler %p\n", g_cs43l22info.handler);
if (g_cs43l22info.handler)
{
return g_cs43l22info.handler(&g_cs43l22info.lower, g_cs43l22info.arg);
}
We got an interrupt with no handler. This should not
happen.
TODO: stm32_pioirqdisable(IRQ_INT_CS43L22);
return OK;
}
#endif
static void cs43l22_hw_reset(FAR const struct cs43l22_lower_s *lower)
{
int i;
/* Reset the codec */
stm32_gpiowrite(GPIO_CS43L22_RESET, false);
for (i = 0; i < 0x4fff; i++)
{
__asm__ volatile("nop");
}
stm32_gpiowrite(GPIO_CS43L22_RESET, true);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: stm32_cs43l22_initialize
*
* Description:
* This function is called by platform-specific, setup logic to configure
* and register the CS43L22 device. This function will register the driver
* as /dev/audio/pcm[x] where x is determined by the minor device number.
*
* Input Parameters:
* minor - The input device minor number
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
int stm32_cs43l22_initialize(int minor)
{
FAR struct audio_lowerhalf_s *cs43l22;
FAR struct audio_lowerhalf_s *pcm;
FAR struct i2c_master_s *i2c;
FAR struct i2s_dev_s *i2s;
static bool initialized = false;
char devname[12];
int ret;
audinfo("minor %d\n", minor);
DEBUGASSERT(minor >= 0 && minor <= 25);
/* Have we already initialized? Since we never uninitialize we must prevent
* multiple initializations. This is necessary, for example, when the
* touchscreen example is used as a built-in application in NSH and can be
* called numerous time. It will attempt to initialize each time.
*/
if (!initialized)
{
stm32_configgpio(GPIO_CS43L22_RESET);
/* Configure the CS43L22 interrupt pin */
/* TODO: (void)stm32_configgpio(PIO_INT_CS43L22); */
/* Get an instance of the I2C interface for the CS43L22 chip select */
i2c = stm32_i2cbus_initialize(CS43L22_I2C_BUS);
if (!i2c)
{
auderr("ERROR: Failed to initialize TWI%d\n", CS43L22_I2C_BUS);
ret = -ENODEV;
goto errout;
}
/* Get an instance of the I2S interface for the CS43L22 data channel */
i2s = stm32_i2sdev_initialize(CS43L22_I2S_BUS);
if (!i2s)
{
auderr("ERROR: Failed to initialize I2S%d\n", CS43L22_I2S_BUS);
ret = -ENODEV;
goto errout_with_i2c;
}
/* Configure the DAC master clock. This clock is provided by PCK2 (PB10)
* that is connected to the CS43L22 MCLK.
*/
/* Configure CS43L22 interrupts */
#if 0 /* TODO: */
stm32_pioirq(PIO_INT_CS43L22);
ret = irq_attach(IRQ_INT_CS43L22, cs43l22_interrupt);
if (ret < 0)
{
auderr("ERROR: Failed to attach CS43L22 interrupt: %d\n", ret);
goto errout_with_i2s;
}
#endif
/* Now we can use these I2C and I2S interfaces to initialize the
* CS43L22 which will return an audio interface.
*/
cs43l22 = cs43l22_initialize(i2c, i2s, &g_cs43l22info.lower);
if (!cs43l22)
{
auderr("ERROR: Failed to initialize the CS43L22\n");
ret = -ENODEV;
goto errout_with_irq;
}
/* No we can embed the CS43L22/I2C/I2S conglomerate into a PCM decoder
* instance so that we will have a PCM front end for the the CS43L22
* driver.
*/
pcm = pcm_decode_initialize(cs43l22);
if (!pcm)
{
auderr("ERROR: Failed create the PCM decoder\n");
ret = -ENODEV;
goto errout_with_cs43l22;
}
/* Create a device name */
snprintf(devname, 12, "pcm%d", minor);
/* Finally, we can register the PCM/CS43L22/I2C/I2S audio device.
*
* Is anyone young enough to remember Rube Goldberg?
*/
ret = audio_register(devname, pcm);
if (ret < 0)
{
auderr("ERROR: Failed to register /dev/%s device: %d\n",
devname, ret);
goto errout_with_pcm;
}
/* Now we are initialized */
initialized = true;
}
return OK;
/* Error exits. Unfortunately there is no mechanism in place now to
* recover resources from most errors on initialization failures.
*/
errout_with_pcm:
errout_with_cs43l22:
errout_with_irq:
#if 0
irq_detach(IRQ_INT_CS43L22);
errout_with_i2s:
#endif
errout_with_i2c:
errout:
return ret;
}
#endif /* HAVE_CS43L22 */

@ -77,6 +77,7 @@
#define HAVE_USBHOST 1
#define HAVE_USBMONITOR 1
#define HAVE_SDIO 1
#define HAVE_CS43L22 1
#define HAVE_RTC_DRIVER 1
#define HAVE_ELF 1
#define HAVE_NETMONITOR 1
@ -148,6 +149,26 @@
# endif
#endif
/* The CS43L22 depends on the CS43L22 driver, I2C1, and I2S3 support */
#if !defiend(CONFIG_AUDIO_CS43L22) || !defined(CONFIG_STM32_I2C1) || \
!defined(CONFIG_STM32_I2S3)
# undef HAVE_CS43L22
#endif
#ifdef HAVE_CS43L22
/* The CS43L22 communicates on I2C1, I2C address 0x1a for control
* operations
*/
# define CS43L22_I2C_BUS 1
# define CS43L22_I2C_ADDRESS (0x94 >> 1)
/* The CS43L22 transfers data on I2S3 */
# define CS43L22_I2S_BUS 3
#endif
/* Check if we can support the RTC driver */
#if !defined(CONFIG_RTC) || !defined(CONFIG_RTC_DRIVER)
@ -216,6 +237,8 @@
#define GPIO_ZEROCROSS (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTD|GPIO_PIN0)
#define GPIO_CS43L22_RESET (GPIO_OUTPUT|GPIO_SPEED_50MHz|GPIO_PORTD|GPIO_PIN4)
/* PWM
*
* The STM32F4 Discovery has no real on-board PWM devices, but the board can be
@ -369,6 +392,17 @@
void weak_function stm32_spidev_initialize(void);
/****************************************************************************
* Name: stm32_i2sdev_initialize
*
* Description:
* Called to configure I2S chip select GPIO pins for the stm32f4discovery
* board.
*
****************************************************************************/
FAR struct i2s_dev_s *stm32_i2sdev_initialize(int port);
/****************************************************************************
* Name: stm32_bh1750initialize
*
@ -608,6 +642,27 @@ int stm32_zerocross_initialize(void);
int stm32_max6675initialize(FAR const char *devpath);
#endif
/****************************************************************************
* Name: stm32_cs43l22_initialize
*
* Description:
* This function is called by platform-specific, setup logic to configure
* and register the CS43L22 device. This function will register the driver
* as /dev/cs43l22[x] where x is determined by the minor device number.
*
* Input Parameters:
* minor - The input device minor number
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
#ifdef HAVE_CS43L22
int stm32_cs43l22_initialize(int minor);
#endif /* HAVE_CS43L22 */
/****************************************************************************
* Name: stm32_pca9635_initialize
*

@ -95,6 +95,67 @@ endif # AUDIO_DRIVER_SPECIFIC_BUFFERS
endif # VS1053
config AUDIO_CS43L22
bool "CS43L22 audio chip"
default n
depends on AUDIO
---help---
Select to enable support for the CS43L22 Audio codec by Cirrus Logic.
This chip is a lower level audio chip.. basically
an exotic D-to-A. It includes no built-in support for audio CODECS
The CS43L22 provides:
- Low power consumption
- High SNR
- Stereo digital microphone input
- Digital Dynamic Range Controller (compressor / limiter)
- Digital sidetone mixing
- Ground-referenced headphone driver
- Ground-referenced line outputs
NOTE: This driver also depends on both I2C and I2S support although
that dependency is not explicit here.
if AUDIO_CS43L22
config CS43L22_INITVOLUME
int "CS43L22 initial volume setting"
default 250
config CS43L22_INFLIGHT
int "CS43L22 maximum in-flight audio buffers"
default 2
config CS43L22_MSG_PRIO
int "CS43L22 message priority"
default 1
config CS43L22_BUFFER_SIZE
int "CS43L22 preferred buffer size"
default 8192
config CS43L22_NUM_BUFFERS
int "CS43L22 preferred number of buffers"
default 4
config CS43L22_WORKER_STACKSIZE
int "CS43L22 worker thread stack size"
default 768
config CS43L22_REGDUMP
bool "CS43L22 register dump"
default n
---help---
Enable logic to dump the contents of all CS43L22 registers.
config CS43L22_CLKDEBUG
bool "CS43L22 clock analysis"
default n
---help---
Enable logic to analyze CS43L22 clock configuation.
endif # AUDIO_CS43L22
config AUDIO_WM8904
bool "WM8904 audio chip"
default n

@ -43,6 +43,17 @@ ifeq ($(CONFIG_VS1053),y)
CSRCS += vs1053.c
endif
ifeq ($(CONFIG_AUDIO_CS43L22),y)
CSRCS += cs43l22.c
ifeq ($(CONFIG_CS43L22_REGDUMP),y)
CSRCS += cs43l22_debug.c
else
ifeq ($(CONFIG_CS43L22_CLKDEBUG),y)
CSRCS += cs43l22_debug.c
endif
endif
endif
ifeq ($(CONFIG_AUDIO_WM8904),y)
CSRCS += wm8904.c
ifeq ($(CONFIG_WM8904_REGDUMP),y)

1959
drivers/audio/cs43l22.c Normal file

File diff suppressed because it is too large Load Diff

388
drivers/audio/cs43l22.h Normal file

@ -0,0 +1,388 @@
/****************************************************************************
* drivers/audio/cs43l22.h
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Reference:
* "CS43L22 Ultra Low Power CODEC for Portable Audio Applications, Pre-
* Production", September 2012, Rev 3.3, Wolfson Microelectronics
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __DRIVERS_AUDIO_CS43L22_H
#define __DRIVERS_AUDIO_CS43L22_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/compiler.h>
#include <pthread.h>
#include <mqueue.h>
#include <nuttx/wqueue.h>
#include <nuttx/fs/ioctl.h>
#define getreg32(a) (*(volatile uint32_t *)(a))
#define putreg32(v,a) (*(volatile uint32_t *)(a) = (v))
#define getreg16(a) (*(volatile uint16_t *)(a))
#define putreg16(v,a) (*(volatile uint16_t *)(a) = (v))
#ifdef CONFIG_AUDIO
/****************************************************************************
* Pre-Processor Definitions
****************************************************************************/
/* So far, I have not been able to get FLL lock interrupts. Worse, I have
* been able to get the FLL to claim that it is locked at all even when
* polling. What am I doing wrong?
*
* Hmmm.. seems unnecessary anyway
*/
#undef CS43L22_USE_FFLOCK_INT
#undef CS43L22_USE_FFLOCK_POLL
/* Registers Addresses ******************************************************/
#define CS43L22_ID_REV 0x01 /* Chip I.D. and Revision */
#define CS43L22_POWER_CTRL1 0x02 /* Power Control 1 */
#define CS43L22_POWER_CTRL2 0x04 /* Power Control 2 */
#define CS43L22_CLOCK_CTRL 0x05 /* Clocking Control */
#define CS43L22_INTERFACE_CTRL1 0x06 /* Interface Control 1 */
#define CS43L22_INTERFACE_CTRL2 0x07 /* Interface Control 2 */
#define CS43L22_PASS_SEL_A 0x08 /* Passthrough x Select: PassA */
#define CS43L22_PASS_SEL_B 0x09 /* Passthrough x Select: PassB */
#define CS43L22_ANLG_ZC_SR_SEL 0x0A /* Analog ZC and SR Settings */
#define CS43L22_PASS_GANG_CTRL 0x0C /* Passthrough Gang Control */
#define CS43L22_PLAYBACK_CTRL1 0x0D /* Playback Control 1 */
#define CS43L22_MISCLLNS_CTRL 0x0E /* Miscellaneous Controls */
#define CS43L22_PLAYBACK_CTRL2 0x0F /* Playback Control 2 */
#define CS43L22_PASS_VOL_A 0x14 /* Passthrough x Volume: PASSAVOL */
#define CS43L22_PASS_VOL_B 0x15 /* Passthrough x Volume: PASSBVOL */
#define CS43L22_PCM_VOL_A 0x1A /* PCMx Volume: PCMA */
#define CS43L22_PCM_VOL_B 0x1B /* PCMx Volume: PCMB */
#define CS43L22_BP_FREQ_ON_TIME 0x1C /* Beep Frequency & On Time */
#define CS43L22_BP_VOL_OFF_TIME 0x1D /* Beep Volume & Off Time */
#define CS43L22_BP_TONE_CFG 0x1E /* Beep & Tone Configuration */
#define CS43L22_TONE_CTRL 0x1F /* Tone Control */
#define CS43L22_MS_VOL_CTRL_A 0x20 /* Master Volume Control: MSTA */
#define CS43L22_MS_VOL_CTRL_B 0x21 /* Master Volume Control: MSTB */
#define CS43L22_HP_VOL_CTRL_A 0x22 /* Headphone Volume Control: HPA */
#define CS43L22_HP_VOL_CTRL_B 0x23 /* Headphone Volume Control: HPB */
#define CS43L22_SPK_VOL_CTRL_A 0x24 /* Speaker Volume Control: SPKA */
#define CS43L22_SPK_VOL_CTRL_B 0x25 /* Speaker Volume Control: SPKB */
#define CS43L22_PCM_CH_SWAP 0x26 /* PCM Channel Swap */
#define CS43L22_LIM_CTRL1 0x27 /* Limiter Control 1, Min/Max Thresholds */
#define CS43L22_LIM_CTRL2 0x28 /* Limiter Control 2, Release Rate */
#define CS43L22_LIM_ATTACK_RATE 0x29 /* Limiter Attack Rate */
#define CS43L22_STATUS 0x2E /* Status */
#define CS43L22_BAT_COMP 0x2F /* Battery Compensation */
#define CS43L22_VP_BAT_LEVEL 0x30 /* VP Battery Level */
#define CS43L22_SPK_STATUS 0x31 /* Speaker Status */
#define CS43L22_TEMP_MON_CTRL 0x32 /* Temperature Monitor Control */
#define CS43L22_THERMAL_FOLDBACK 0x33 /* Thermal Foldback */
#define CS43L22_CHRG_PUMP_FREQ 0x34 /* Charge Pump Frequency */
#define CS43L22_HPBMUTE (1 << 7)
#define CS43L22_HPAMUTE (1 << 6)
#define CS43L22_SPKBMUTE (1 << 5)
#define CS43L22_SPKAMUTE (1 << 4)
/* Register Default Values **************************************************/
/* Registers have some undocumented bits set on power up. These probably
* should be retained on writes (?).
*/
#define CS43L22_ID_REV_DEFAULT 0xe3 /* Chip I.D. and Revision */
#define CS43L22_POWER_CTRL1_DEFAULT 0x01 /* Power Control 1 */
#define CS43L22_POWER_CTRL2_DEFAULT 0x05 /* Power Control 2 */
#define CS43L22_CLOCK_CTRL_DEFAULT 0xa0 /* Clocking Control */
#define CS43L22_INTERFACE_CTRL1_DEFAULT 0x00 /* Interface Control 1 */
#define CS43L22_INTERFACE_CTRL2_DEFAULT 0x00 /* Interface Control 2 */
#define CS43L22_PASS_SEL_A_DEFAULT 0x81 /* Passthrough x Select: PassA */
#define CS43L22_PASS_SEL_B_DEFAULT 0x81 /* Passthrough x Select: PassB */
#define CS43L22_ANLG_ZC_SR_SEL_DEFAULT 0xa5 /* Analog ZC and SR Settings */
#define CS43L22_PASS_GANG_CTRL_DEFAULT 0x00 /* Passthrough Gang Control */
#define CS43L22_PLAYBACK_CTRL1_DEFAULT 0x60 /* Playback Control 1 */
#define CS43L22_MISCLLNS_CTRL_DEFAULT 0x02 /* Miscellaneous Controls */
#define CS43L22_PLAYBACK_CTRL2_DEFAULT 0x00 /* Playback Control 2 */
#define CS43L22_PASS_VOL_A_DEFAULT 0x00 /* Passthrough x Volume: PASSAVOL */
#define CS43L22_PASS_VOL_B_DEFAULT 0x00 /* Passthrough x Volume: PASSBVOL */
#define CS43L22_PCM_VOL_A_DEFAULT 0x00 /* PCMx Volume: PCMA */
#define CS43L22_PCM_VOL_B_DEFAULT 0x00 /* PCMx Volume: PCMB */
#define CS43L22_BP_FREQ_ON_TIME_DEFAULT 0x00 /* Beep Frequency & On Time */
#define CS43L22_BP_VOL_OFF_TIME_DEFAULT 0x00 /* Beep Volume & Off Time */
#define CS43L22_BP_TONE_CFG_DEFAULT 0x00 /* Beep & Tone Configuration */
#define CS43L22_TONE_CTRL_DEFAULT 0x88 /* Tone Control */
#define CS43L22_MS_VOL_CTRL_A_DEFAULT 0x00 /* Master Volume Control: MSTA */
#define CS43L22_MS_VOL_CTRL_B_DEFAULT 0x00 /* Master Volume Control: MSTB */
#define CS43L22_HP_VOL_CTRL_A_DEFAULT 0x00 /* Headphone Volume Control: HPA */
#define CS43L22_HP_VOL_CTRL_B_DEFAULT 0x00 /* Headphone Volume Control: HPB */
#define CS43L22_SPK_VOL_CTRL_A_DEFAULT 0x00 /* Speaker Volume Control: SPKA */
#define CS43L22_SPK_VOL_CTRL_B_DEFAULT 0x00 /* Speaker Volume Control: SPKB */
#define CS43L22_PCM_CH_SWAP_DEFAULT 0x00 /* PCM Channel Swap */
#define CS43L22_LIM_CTRL1_DEFAULT 0x00 /* Limiter Control 1, Min/Max Thresholds */
#define CS43L22_LIM_CTRL2_DEFAULT 0x7f /* Limiter Control 2, Release Rate */
#define CS43L22_LIM_ATTACK_RATE_DEFAULT 0xc0 /* Limiter Attack Rate */
#define CS43L22_STATUS_DEFAULT 0x00 /* Status */
#define CS43L22_BAT_COMP_DEFAULT 0x00 /* Battery Compensation */
#define CS43L22_VP_BAT_LEVEL_DEFAULT 0x00 /* VP Battery Level */
#define CS43L22_SPK_STATUS_DEFAULT 0x00 /* Speaker Status */
#define CS43L22_TEMP_MON_CTRL_DEFAULT 0x3b /* Temperature Monitor Control */
#define CS43L22_THERMAL_FOLDBACK_DEFAULT 0x00 /* Thermal Foldback */
#define CS43L22_CHRG_PUMP_FREQ_DEFAULT 0x5f /* Charge Pump Frequency */
/* Register Bit Definitions *************************************************/
/* 0x01 Chip I.D. and Revision (Read Only) */
#define CS43L22_DEV_ID_REV (0xe3)
#define CS43L22_ID_SHIFT (3)
#define CS43L22_ID_MASK (0x1f << CS43L22_ID_SHIFT)
#define CS43L22_REV_SHIFT (0)
#define CS43L22_REV_MASK (0x07 << CS43L22_REV_SHIFT)
/* 0x02 Power Control 1 */
#define CS43L22_POWER_DOWN (0x01) /* Powered Down */
#define CS43L22_POWER_UP (0x9e) /* Powered Up */
/* 0x04 Power Control 2 */
#define CS43L22_PDN_HPB_SHIFT (6) /* Bits 6-7: Headphone channel B Control */
#define CS43L22_PDN_HPB_ON_HW_PIN_LO (0 << CS43L22_PDN_HPB_SHIFT) /* PDN_HPx[1:0] 00 Headphone channel is ON when the SPK/HP_SW pin, 6, is LO
Headphone channel is OFF when the SPK/HP_SW pin, 6, is HI */
#define CS43L22_PDN_HPB_ON_HW_PIN_HI (1 << CS43L22_PDN_HPB_SHIFT) /* PDN_HPx[1:0] 01 Headphone channel is ON when the SPK/HP_SW pin, 6, is HI
Headphone channel is OFF when the SPK/HP_SW pin, 6, is LO */
#define CS43L22_PDN_HPB_ON (2 << CS43L22_PDN_HPB_SHIFT) /* PDN_HPx[1:0] 10 Headphone channel is always ON */
#define CS43L22_PDN_HPB_OFF (3 << CS43L22_PDN_HPB_SHIFT) /* PDN_HPx[1:0] 11 Headphone channel is always OFF */
#define CS43L22_PDN_HPA_SHIFT (4) /* Bits 4-5: Headphone channel A Control */
#define CS43L22_PDN_HPA_ON_HW_PIN_LO (0 << CS43L22_PDN_HPA_SHIFT) /* PDN_HPx[1:0] 00 Headphone channel is ON when the SPK/HP_SW pin, 6, is LO
Headphone channel is OFF when the SPK/HP_SW pin, 6, is HI */
#define CS43L22_PDN_HPA_ON_HW_PIN_HI (1 << CS43L22_PDN_HPA_SHIFT) /* PDN_HPx[1:0] 01 Headphone channel is ON when the SPK/HP_SW pin, 6, is HI
Headphone channel is OFF when the SPK/HP_SW pin, 6, is LO */
#define CS43L22_PDN_HPA_ON (2 << CS43L22_PDN_HPA_SHIFT) /* PDN_HPx[1:0] 10 Headphone channel is always ON */
#define CS43L22_PDN_HPA_OFF (3 << CS43L22_PDN_HPA_SHIFT) /* PDN_HPx[1:0] 11 Headphone channel is always OFF */
#define CS43L22_PDN_SPKB_SHIFT (2) /* Bits 2-3: Speaker channel B Control */
#define CS43L22_PDN_SPKB_ON_HW_PIN_LO (0 << CS43L22_PDN_SPKB_SHIFT) /* PDN_HPx[1:0] 00 Speaker channel is ON when the SPK/HP_SW pin, 6, is LO
Speaker channel is OFF when the SPK/HP_SW pin, 6, is HI */
#define CS43L22_PDN_SPKB_ON_HW_PIN_HI (1 << CS43L22_PDN_SPKB_SHIFT) /* PDN_HPx[1:0] 01 Speaker channel is ON when the SPK/HP_SW pin, 6, is HI
Speaker channel is OFF when the SPK/HP_SW pin, 6, is LO */
#define CS43L22_PDN_SPKB_ON (2 << CS43L22_PDN_SPKB_SHIFT) /* PDN_HPx[1:0] 10 Speaker channel is always ON */
#define CS43L22_PDN_SPKB_OFF (3 << CS43L22_PDN_SPKB_SHIFT) /* PDN_HPx[1:0] 11 Speaker channel is always OFF */
#define CS43L22_PDN_SPKA_SHIFT (0) /* Bits 0-1: Speaker channel A Control */
#define CS43L22_PDN_SPKA_ON_HW_PIN_LO (0 << CS43L22_PDN_SPKA_SHIFT) /* PDN_HPx[1:0] 00 Speaker channel is ON when the SPK/HP_SW pin, 6, is LO
Speaker channel is OFF when the SPK/HP_SW pin, 6, is HI */
#define CS43L22_PDN_SPKA_ON_HW_PIN_HI (1 << CS43L22_PDN_SPKA_SHIFT) /* PDN_HPx[1:0] 01 Speaker channel is ON when the SPK/HP_SW pin, 6, is HI
Speaker channel is OFF when the SPK/HP_SW pin, 6, is LO */
#define CS43L22_PDN_SPKA_ON (2 << CS43L22_PDN_SPKA_SHIFT) /* PDN_HPx[1:0] 10 Speaker channel is always ON */
#define CS43L22_PDN_SPKA_OFF (3 << CS43L22_PDN_SPKA_SHIFT) /* PDN_HPx[1:0] 11 Speaker channel is always OFF */
/* 0x05 Clocking Control */
#define CS43L22_AUTO_DETECT_ENABLE (1 << 7) /* Auto-detection of speed mode enable */
#define CS43L22_SPEED_SHIFT (5) /* Bits 5-6: Speed mode */
#define CS43L22_SPEED_DOUBLE (0 << CS43L22_SPEED_SHIFT) /* Slave: Double-Speed Mode (DSM - 50 kHz -100 kHz Fs) Master: MCLK=512 SCLK=64*/
#define CS43L22_SPEED_SINGLE (1 << CS43L22_SPEED_SHIFT) /* Slave: Single-Speed Mode (SSM - 4 kHz -50 kHz Fs) Master: MCLK=256 SCLK=64*/
#define CS43L22_SPEED_HALF (2 << CS43L22_SPEED_SHIFT) /* Slave: Half-Speed Mode (HSM - 12.5kHz -25 kHz Fs) Master: MCLK=128 SCLK=64*/
#define CS43L22_SPEED_QUARTER (3 << CS43L22_SPEED_SHIFT) /* Slave: Quarter-Speed Mode (QSM - 4 kHz -12.5 kHz Fs)Master: MCLK=128 SCLK=64*/
#define CS43L22_32k_GROUP_ENABLE (1 << 4) /* Bit 4: Specifies whether or not the input/output sample rate is 8 kHz, 16 kHz or 32 kHz */
#define CS43L22_VIDEOCLK_ENABLE (1 << 3) /* Bit 3: Specifies whether or not the external MCLK frequency is 27 MHz */
#define CS43L22_MCLK_LRCK_RATIO_SHIFT (1) /* Bits 1-2: Internal MCLK/LRCK Ratio */
#define CS43L22_RATIO_128_64 (0 << CS43L22_MCLK_LRCK_RATIO_SHIFT) /* RATIO[1:0] Internal MCLK Cycles per LRCK=128, SCLK/LRCK=64 Ratio in Master Mode */
#define CS43L22_RATIO_125_62 (1 << CS43L22_MCLK_LRCK_RATIO_SHIFT) /* RATIO[1:0] Internal MCLK Cycles per LRCK=125, SCLK/LRCK=62 Ratio in Master Mode */
#define CS43L22_RATIO_132_66 (2 << CS43L22_MCLK_LRCK_RATIO_SHIFT) /* RATIO[1:0] Internal MCLK Cycles per LRCK=132, SCLK/LRCK=66 Ratio in Master Mode */
#define CS43L22_RATIO_136_68 (3 << CS43L22_MCLK_LRCK_RATIO_SHIFT) /* RATIO[1:0] Internal MCLK Cycles per LRCK=136, SCLK/LRCK=68 Ratio in Master Mode */
#define CS43L22_CLKDIV2_ENABLE (1 << 0) /* Bit 0: Divided by 2 */
/* 0x06 Interface Control 1 */
#define CS43L22_MODE_MASTER (1 << 7) /* Configures the serial port I/O clocking */
#define CS43L22_SCLK_POLARITY_INVERT (1 << 6) /* Configures the polarity of the SCLK signal */
#define CS43L22_DSP_MODE_ENABLE (1 << 4) /* Configures a data-packed interface format for the DAC */
#define CS43L22_DAC_IF_FORMAT_SHIFT (2) /* Bits 2-3: Configures the digital interface format for data on SDIN */
#define CS43L22_DAC_IF_LEFT_JUSTIFIED (0 << CS43L22_DAC_IF_FORMAT_SHIFT) /* DACDIF[1:0] Left Justified, up to 24-bit data */
#define CS43L22_DAC_IF_I2S (1 << CS43L22_DAC_IF_FORMAT_SHIFT) /* DACDIF[1:0] I2S, up to 24-bit data */
#define CS43L22_DAC_IF_RIGHT_JUSTIFIED (2 << CS43L22_DAC_IF_FORMAT_SHIFT) /* DACDIF[1:0] Right Justified */
#define CS43L22_DAC_IF_RESERVED (3 << CS43L22_DAC_IF_FORMAT_SHIFT) /* DACDIF[1:0] Reserved */
#define CS43L22_AUDIO_WORD_LENGHT_SHIFT (0) /* Bits 0-1: Configures the audio sample word length used for the data into SDIN */
#define CS43L22_AWL_DSP_32_RJ_24 (0 << CS43L22_AUDIO_WORD_LENGHT_SHIFT)/* AWL[1:0] DSP Mode: 32-bit data, Right Justified: 24-bit data */
#define CS43L22_AWL_DSP_24_RJ_20 (1 << CS43L22_AUDIO_WORD_LENGHT_SHIFT)/* AWL[1:0] DSP Mode: 24-bit data, Right Justified: 20-bit data */
#define CS43L22_AWL_DSP_20_RJ_18 (2 << CS43L22_AUDIO_WORD_LENGHT_SHIFT)/* AWL[1:0] DSP Mode: 20-bit data, Right Justified: 18-bit data */
#define CS43L22_AWL_DSP_16_RJ_16 (3 << CS43L22_AUDIO_WORD_LENGHT_SHIFT)/* AWL[1:0] DSP Mode: 16 bit data, Right Justified: 16-bit data */
/* 0x0E Miscellaneous Controls */
#define CS43L22_FREEZE (1 << 3) /* Configures a hold on all register settings */
#define CS43L22_DEEMPHASIS_ENABLE (1 << 2) /* Configures a 15μs/50μs digital de-emphasis filter response on the headphone/line and speaker outputs */
/* 0x1F Tone Control */
#define CS43L22_TREB_GAIN_SHIFT (4) /* Sets the gain of the treble shelving filter */
#define CS43L22_TREB_GAIN(a) ((a) << CS43L22_TREB_GAIN_SHIFT)
/* TREB[3:0] Gain Setting:*/
/* 0000 +12.0 dB */
/* ··· ··· */
/* 0111 +1.5 dB */
/* 1000 0 dB */
/* 1001 -1.5 dB */
/* 1111 -10.5 dB */
/* Step Size: 1.5 dB */
#define CS43L22_BASS_GAIN_SHIFT (0) /* Sets the gain of the bass shelving filter */
#define CS43L22_BASS_GAIN(a) ((a) << CS43L22_BASS_GAIN_SHIFT)
/* BASS[3:0] Gain Setting:*/
/* 0000 +12.0 dB */
/* ··· ··· */
/* 0111 +1.5 dB */
/* 1000 0 dB */
/* 1001 -1.5 dB */
/* 1111 -10.5 dB */
/* Step Size: 1.5 dB */
/* FLL Configuration *********************************************************/
/* Default FLL configuration */
#define CS43L22_DEFAULT_SAMPRATE 11025 /* Initial sample rate */
#define CS43L22_DEFAULT_NCHANNELS 1 /* Initial number of channels */
#define CS43L22_DEFAULT_BPSAMP 16 /* Initial bits per sample */
#define CS43L22_NFLLRATIO 5 /* Number of FLL_RATIO values */
#define CS43L22_MINOUTDIV 4 /* Minimum FLL_OUTDIV divider */
#define CS43L22_MAXOUTDIV 64 /* Maximum FLL_OUTDIV divider */
#define CS43L22_BCLK_MAXDIV 20 /* Maximum BCLK divider */
#define CS43L22_FRAMELEN8 14 /* Bits per frame for 8-bit data */
#define CS43L22_FRAMELEN16 32 /* Bits per frame for 16-bit data */
/* Commonly defined and redefined macros */
#ifndef MIN
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
# define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
/****************************************************************************
* Public Types
****************************************************************************/
struct cs43l22_dev_s
{
/* We are an audio lower half driver (We are also the upper "half" of
* the CS43L22 driver with respect to the board lower half driver).
*
* Terminology: Our "lower" half audio instances will be called dev for the
* publicly visible version and "priv" for the version that only this driver
* knows. From the point of view of this driver, it is the board lower
* "half" that is referred to as "lower".
*/
struct audio_lowerhalf_s dev; /* CS43L22 audio lower half (this device) */
/* Our specific driver data goes here */
const FAR struct cs43l22_lower_s *lower; /* Pointer to the board lower functions */
FAR struct i2c_master_s *i2c; /* I2C driver to use */
FAR struct i2s_dev_s *i2s; /* I2S driver to use */
struct dq_queue_s pendq; /* Queue of pending buffers to be sent */
struct dq_queue_s doneq; /* Queue of sent buffers to be returned */
mqd_t mq; /* Message queue for receiving messages */
char mqname[16]; /* Our message queue name */
pthread_t threadid; /* ID of our thread */
uint32_t bitrate; /* Actual programmed bit rate */
sem_t pendsem; /* Protect pendq */
#ifdef CS43L22_USE_FFLOCK_INT
struct work_s work; /* Interrupt work */
#endif
uint16_t samprate; /* Configured samprate (samples/sec) */
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
#ifndef CONFIG_AUDIO_EXCLUDE_BALANCE
uint16_t balance; /* Current balance level (b16) */
#endif /* CONFIG_AUDIO_EXCLUDE_BALANCE */
uint8_t volume; /* Current volume level {0..63} */
#endif /* CONFIG_AUDIO_EXCLUDE_VOLUME */
uint8_t nchannels; /* Number of channels (1 or 2) */
uint8_t bpsamp; /* Bits per sample (8 or 16) */
volatile uint8_t inflight; /* Number of audio buffers in-flight */
#ifdef CS43L22_USE_FFLOCK_INT
volatile bool locked; /* FLL is locked */
#endif
bool running; /* True: Worker thread is running */
bool paused; /* True: Playing is paused */
bool mute; /* True: Output is muted */
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
bool terminating; /* True: Stop requested */
#endif
bool reserved; /* True: Device is reserved */
volatile int result; /* The result of the last transfer */
};
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef CONFIG_CS43L22_CLKDEBUG
extern const uint8_t g_sysclk_scaleb1[CS43L22_BCLK_MAXDIV+1];
extern const uint8_t g_fllratio[CS43L22_NFLLRATIO];
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: cs43l22_readreg
*
* Description
* Read the specified 8-bit register from the CS43L22 device.
*
****************************************************************************/
#if defined(CONFIG_CS43L22_REGDUMP) || defined(CONFIG_CS43L22_CLKDEBUG)
struct cs43l22_dev_s;
uint8_t cs43l22_readreg(FAR struct cs43l22_dev_s *priv, uint8_t regaddr);
#endif
#endif /* CONFIG_AUDIO */
#endif /* __DRIVERS_AUDIO_CS43L22_H */

@ -0,0 +1,184 @@
/****************************************************************************
* drivers/audio/cs43l22_debug.c
* Audio device driver for Cirrus Logic CS43L22 Audio codec.
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Taras Drozdovsky <t.drozdovskiy@gmail.comnuttx.org>
*
* References:
* - "CS43L22 Ultra Low Power CODEC for Portable Audio Applications, Pre-
* Production", September 2012, Rev b1, Cirrus Logic
* - The framework for this driver is based on Ken Pettit's VS1053 driver.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <assert.h>
#include <fixedmath.h>
#include <syslog.h>
#include <nuttx/audio/audio.h>
#include <nuttx/audio/cs43l22.h>
#include "cs43l22.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
#ifdef CONFIG_CS43L22_REGDUMP
struct cs43l22_regdump_s
{
FAR const char *regname;
uint8_t regaddr;
};
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
#ifdef CONFIG_CS43L22_REGDUMP
static const struct cs43l22_regdump_s g_cs43l22_debug[] =
{
{"CHIP_ID_REV", CS43L22_ID_REV },
{"POWER_CTRL1", CS43L22_POWER_CTRL1 },
{"POWER_CTRL2", CS43L22_POWER_CTRL2 },
{"CLOCK_CTRL", CS43L22_CLOCK_CTRL },
{"INTERFACE_CTRL1", CS43L22_INTERFACE_CTRL1 },
{"INTERFACE_CTRL2", CS43L22_INTERFACE_CTRL2 },
{"PASS_SEL_A", CS43L22_PASS_SEL_A },
{"PASS_SEL_B", CS43L22_PASS_SEL_B },
{"ANLG_ZC_SR_SEL", CS43L22_ANLG_ZC_SR_SEL },
{"PASS_GANG_CTRL", CS43L22_PASS_GANG_CTRL },
{"PLAYBACK_CTRL1", CS43L22_PLAYBACK_CTRL1 },
{"MISCLLNS_CTRL", CS43L22_MISCLLNS_CTRL },
{"PLAYBACK_CTRL2", CS43L22_PLAYBACK_CTRL2 },
{"PASS_VOL_A", CS43L22_PASS_VOL_A },
{"PASS_VOL_B", CS43L22_PASS_VOL_B },
{"PCM_VOL_A", CS43L22_PCM_VOL_A },
{"PCM_VOL_B", CS43L22_PCM_VOL_B },
{"BP_FREQ_ON_T", CS43L22_BP_FREQ_ON_TIME },
{"BP_VOL_OFF_T", CS43L22_BP_VOL_OFF_TIME },
{"BP_TONE_CFG", CS43L22_BP_TONE_CFG },
{"TONE_CTRL", CS43L22_TONE_CTRL },
{"MS_VOL_CTRL_A", CS43L22_MS_VOL_CTRL_A },
{"MS_VOL_CTRL_B", CS43L22_MS_VOL_CTRL_B },
{"HP_VOL_CTRL_A", CS43L22_HP_VOL_CTRL_A },
{"HP_VOL_CTRL_B", CS43L22_HP_VOL_CTRL_B },
{"SPK_VOL_CTRL_A", CS43L22_SPK_VOL_CTRL_A },
{"SPK_VOL_CTRL_B", CS43L22_SPK_VOL_CTRL_B },
{"PCM_CH_SWAP", CS43L22_PCM_CH_SWAP },
{"LIM_CTRL1", CS43L22_LIM_CTRL1 },
{"LIM_CTRL2", CS43L22_LIM_CTRL2 },
{"LIM_ATTACK_RATE", CS43L22_LIM_ATTACK_RATE },
{"STATUS", CS43L22_STATUS },
{"BAT_COMP", CS43L22_BAT_COMP },
{"VP_BAT_LEVEL", CS43L22_VP_BAT_LEVEL },
{"SPK_STATUS", CS43L22_SPK_STATUS },
{"TEMP_MON_CTRL", CS43L22_TEMP_MON_CTRL },
{"THERMAL_FOLDBACK",CS43L22_THERMAL_FOLDBACK},
{"CHRG_PUMP_FREQ", CS43L22_CHRG_PUMP_FREQ }
};
# define CS43L22_NREGISTERS (sizeof(g_cs43l22_debug)/sizeof(struct cs43l22_regdump_s))
#endif /* CONFIG_CS43L22_REGDUMP */
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: cs43l22_dump_registers
*
* Description:
* Dump the contents of all CS43L22 registers to the syslog device
*
* Input Parameters:
* dev - The device instance returned by cs43l22_initialize
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_CS43L22_REGDUMP
void cs43l22_dump_registers(FAR struct audio_lowerhalf_s *dev,
FAR const char *msg)
{
int i;
syslog(LOG_INFO, "CS43L22 Registers: %s\n", msg);
for (i = 0; i < CS43L22_NREGISTERS; i++)
{
syslog(LOG_INFO, "%16s[%02x]: %02x\n",
g_cs43l22_debug[i].regname, g_cs43l22_debug[i].regaddr,
cs43l22_readreg((FAR struct cs43l22_dev_s *)dev,
g_cs43l22_debug[i].regaddr));
}
}
#endif /* CONFIG_CS43L22_REGDUMP */
/****************************************************************************
* Name: cs43l22_clock_analysis
*
* Description:
* Analyze the settings in the clock chain and dump to syslog.
*
* Input Parameters:
* dev - The device instance returned by cs43l22_initialize
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_CS43L22_CLKDEBUG
void cs43l22_clock_analysis(FAR struct audio_lowerhalf_s *dev,
FAR const char *msg)
{
#warning Missing logic
/* TODO */
}
#endif /* CONFIG_CS43L22_CLKDEBUG */

@ -0,0 +1,280 @@
/****************************************************************************
* include/nuttx/audio/cs43l22.h
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Reference:
* "CS43L22 Ultra Low Power CODEC for Portable Audio Applications, Pre-
* Production", September 2012, Rev 3.3, Wolfson Microelectronics
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_AUDIO_CS43L22_H
#define __INCLUDE_NUTTX_AUDIO_CS43L22_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include <nuttx/irq.h>
#ifdef CONFIG_AUDIO_CS43L22
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************
*
* CONFIG_AUDIO_CS43L22 - Enables CS43L22 support
* CONFIG_CS43L22_INITVOLUME - The initial volume level in the range {0..1000}
* CONFIG_CS43L22_INFLIGHT - Maximum number of buffers that the CS43L22 driver
* will send to the I2S driver before any have completed.
* CONFIG_CS43L22_MSG_PRIO - Priority of messages sent to the CS43L22 worker
* thread.
* CONFIG_CS43L22_BUFFER_SIZE - Preferred buffer size
* CONFIG_CS43L22_NUM_BUFFERS - Preferred number of buffers
* CONFIG_CS43L22_WORKER_STACKSIZE - Stack size to use when creating the the
* CS43L22 worker thread.
* CONFIG_CS43L22_REGDUMP - Enable logic to dump all CS43L22 registers to
* the SYSLOG device.
*/
/* Pre-requisites */
#ifndef CONFIG_AUDIO
# error CONFIG_AUDIO is required for audio subsystem support
#endif
#ifndef CONFIG_I2S
# error CONFIG_I2S is required by the CS43L22 driver
#endif
#ifndef CONFIG_I2C
# error CONFIG_I2C is required by the CS43L22 driver
#endif
#ifndef CONFIG_SCHED_WORKQUEUE
# error CONFIG_SCHED_WORKQUEUE is required by the CS43L22 driver
#endif
/* Default configuration values */
#ifndef CONFIG_CS43L22_INITVOLUME
# define CONFIG_CS43L22_INITVOLUME 400
#endif
#ifndef CONFIG_CS43L22_INFLIGHT
# define CONFIG_CS43L22_INFLIGHT 2
#endif
#if CONFIG_CS43L22_INFLIGHT > 255
# error CONFIG_CS43L22_INFLIGHT must fit in a uint8_t
#endif
#ifndef CONFIG_CS43L22_MSG_PRIO
# define CONFIG_CS43L22_MSG_PRIO 1
#endif
#ifndef CONFIG_CS43L22_BUFFER_SIZE
# define CONFIG_CS43L22_BUFFER_SIZE 8192
#endif
#ifndef CONFIG_CS43L22_NUM_BUFFERS
# define CONFIG_CS43L22_NUM_BUFFERS 4
#endif
#ifndef CONFIG_CS43L22_WORKER_STACKSIZE
# define CONFIG_CS43L22_WORKER_STACKSIZE 768
#endif
/* Helper macros ************************************************************/
#define CS43L22_ATTACH(s,isr,arg) ((s)->attach(s,isr,arg))
#define CS43L22_DETACH(s) ((s)->attach(s,NULL,NULL))
#define CS43L22_ENABLE(s) ((s)->enable(s,true))
#define CS43L22_DISABLE(s) ((s)->enable(s,false))
#define CS43L22_RESTORE(s,e) ((s)->enable(s,e))
#define CS43L22_HW_RESET(s) ((s)->reset(s))
/****************************************************************************
* Public Types
****************************************************************************/
/* This is the type of the CS43L22 interrupt handler. The lower level code
* will intercept the interrupt and provide the upper level with the private
* data that was provided when the interrupt was attached.
*/
struct cs43l22_lower_s; /* Forward reference. Defined below */
typedef CODE int (*cs43l22_handler_t)(FAR const struct cs43l22_lower_s *lower,
FAR void *arg);
/* A reference to a structure of this type must be passed to the CS43L22
* driver. This structure provides information about the configuration
* of the CS43L22 and provides some board-specific hooks.
*
* Memory for this structure is provided by the caller. It is not copied
* by the driver and is presumed to persist while the driver is active.
*/
struct cs43l22_lower_s
{
/* I2C characterization */
uint32_t frequency; /* Initial I2C frequency */
uint8_t address; /* 7-bit I2C address (only bits 0-6 used) */
/* Clocking is provided via MCLK. The CS43L22 driver will need to know
* the frequency of MCLK in order to generate the correct bitrates.
*/
uint32_t mclk; /* CS43L22 Master clock frequency */
/* IRQ/GPIO access callbacks. These operations all hidden behind
* callbacks to isolate the CS43L22 driver from differences in GPIO
* interrupt handling by varying boards and MCUs. If possible,
* interrupts should be configured on both rising and falling edges
* so that contact and loss-of-contact events can be detected.
*
* attach - Attach or detach the CS43L22 interrupt handler to the GPIO
* interrupt
* enable - Enable or disable the GPIO interrupt. Returns the
* previous interrupt state.
* reset - HW reset of the CS43L22 chip
*/
CODE int (*attach)(FAR const struct cs43l22_lower_s *lower,
cs43l22_handler_t isr, FAR void *arg);
CODE bool (*enable)(FAR const struct cs43l22_lower_s *lower, bool enable);
CODE void (*reset)(FAR const struct cs43l22_lower_s *lower);
};
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: cs43l22_initialize
*
* Description:
* Initialize the CS43L22 device.
*
* Input Parameters:
* i2c - An I2C driver instance
* i2s - An I2S driver instance
* lower - Persistent board configuration data
*
* Returned Value:
* A new lower half audio interface for the CS43L22 device is returned on
* success; NULL is returned on failure.
*
****************************************************************************/
struct i2c_master_s; /* Forward reference. Defined in include/nuttx/i2c/i2c_master.h */
struct i2s_dev_s; /* Forward reference. Defined in include/nuttx/audio/i2s.h */
struct audio_lowerhalf_s; /* Forward reference. Defined in nuttx/audio/audio.h */
FAR struct audio_lowerhalf_s *
cs43l22_initialize(FAR struct i2c_master_s *i2c, FAR struct i2s_dev_s *i2s,
FAR const struct cs43l22_lower_s *lower);
/****************************************************************************
* Name: cs43l22_dump_registers
*
* Description:
* Dump the contents of all CS43L22 registers to the syslog device
*
* Input Parameters:
* dev - The device instance returned by cs43l22_initialize
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_CS43L22_REGDUMP
void cs43l22_dump_registers(FAR struct audio_lowerhalf_s *dev,
FAR const char *msg);
#else
/* This eliminates the need for any conditional compilation in the
* including file.
*/
# define cs43l22_dump_registers(d,m)
#endif
/****************************************************************************
* Name: cs43l22_clock_analysis
*
* Description:
* Analyze the settings in the clock chain and dump to syslog.
*
* Input Parameters:
* dev - The device instance returned by cs43l22_initialize
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_CS43L22_CLKDEBUG
void cs43l22_clock_analysis(FAR struct audio_lowerhalf_s *dev,
FAR const char *msg);
#else
/* This eliminates the need for any conditional compilation in the
* including file.
*/
# define cs43l22_clock_analysis(d,m)
#endif
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* CONFIG_AUDIO_CS43L22 */
#endif /* __INCLUDE_NUTTX_AUDIO_CS43L22_H */