diff --git a/boards/arm/stm32/olimex-stm32-p407/configs/audio/defconfig b/boards/arm/stm32/olimex-stm32-p407/configs/audio/defconfig new file mode 100644 index 00000000000..8dbdbd03a55 --- /dev/null +++ b/boards/arm/stm32/olimex-stm32-p407/configs/audio/defconfig @@ -0,0 +1,78 @@ +# +# 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="arm" +CONFIG_ARCH_BOARD="olimex-stm32-p407" +CONFIG_ARCH_BOARD_OLIMEX_STM32P407=y +CONFIG_ARCH_BUTTONS=y +CONFIG_ARCH_CHIP="stm32" +CONFIG_ARCH_CHIP_STM32=y +CONFIG_ARCH_CHIP_STM32F407ZG=y +CONFIG_ARCH_IRQBUTTONS=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_AUDIO=y +CONFIG_AUDIO_CS4344=y +CONFIG_AUDIO_EXCLUDE_TONE=y +CONFIG_AUDIO_EXCLUDE_VOLUME=y +CONFIG_AUDIO_I2S=y +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DRIVERS_AUDIO=y +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FS_FAT=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_INTELHEX_BINARY=y +CONFIG_MAX_TASKS=16 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NFILE_STREAMS=8 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_GET=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_DISABLE_PUT=y +CONFIG_NSH_DISABLE_WGET=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_NXPLAYER_DEFAULT_MEDIADIR="/mnt/music" +CONFIG_PREALLOC_MQ_MSGS=4 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PREALLOC_WDOGS=8 +CONFIG_RAM_SIZE=131072 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=192 +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_START_YEAR=2013 +CONFIG_STM32_DISABLE_IDLE_SLEEP_DURING_DEBUG=y +CONFIG_STM32_DMA1=y +CONFIG_STM32_I2S3=y +CONFIG_STM32_I2S3_TX=y +CONFIG_STM32_I2S_MCK=y +CONFIG_STM32_JTAG_SW_ENABLE=y +CONFIG_STM32_OTGFS=y +CONFIG_STM32_PWR=y +CONFIG_STM32_SPI3=y +CONFIG_STM32_SPI3_DMA=y +CONFIG_STM32_SPI_DMA=y +CONFIG_STM32_USART3=y +CONFIG_STM32_USBHOST=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_NSH_CXXINITIALIZE=y +CONFIG_SYSTEM_NXPLAYER=y +CONFIG_TASK_NAME_SIZE=32 +CONFIG_USART3_SERIAL_CONSOLE=y +CONFIG_USBHOST_MSC=y +CONFIG_USER_ENTRYPOINT="nsh_main" +CONFIG_WDOG_INTRESERVE=1 diff --git a/boards/arm/stm32/olimex-stm32-p407/include/board.h b/boards/arm/stm32/olimex-stm32-p407/include/board.h index e906dd5611a..e5f5992e70f 100644 --- a/boards/arm/stm32/olimex-stm32-p407/include/board.h +++ b/boards/arm/stm32/olimex-stm32-p407/include/board.h @@ -341,4 +341,22 @@ #define BOARD_DHTXX_GPIO_OUTPUT GPIO_DHTXX_PIN_OUTPUT #define BOARD_DHTXX_FRTIMER 1 /* Free-run timer 1 */ +/* SPI3 DMA -- As used for I2S DMA transfer with the audio configuration */ + +#define GPIO_SPI3_MISO GPIO_SPI3_MISO_1 +#define GPIO_SPI3_MOSI GPIO_SPI3_MOSI_1 +#define GPIO_SPI3_SCK GPIO_SPI3_SCK_1 + +#define DMACHAN_SPI3_RX DMAMAP_SPI3_RX_1 +#define DMACHAN_SPI3_TX DMAMAP_SPI3_TX_1 + +/* I2S3 - CS4344 configuration uses I2S3 */ + +#define GPIO_I2S3_SD GPIO_I2S3_SD_1 +#define GPIO_I2S3_CK GPIO_I2S3_CK_1 +#define GPIO_I2S3_WS GPIO_I2S3_WS_2 + +#define DMACHAN_I2S3_RX DMAMAP_SPI3_RX_2 +#define DMACHAN_I2S3_TX DMAMAP_SPI3_TX_2 + #endif /* __BOARDS_ARM_STM32_OLIMEX_STM32_P407_INCLUDE_BOARD_H */ diff --git a/boards/arm/stm32/olimex-stm32-p407/src/Make.defs b/boards/arm/stm32/olimex-stm32-p407/src/Make.defs index 7272d4be0f2..7274cc9e1b1 100644 --- a/boards/arm/stm32/olimex-stm32-p407/src/Make.defs +++ b/boards/arm/stm32/olimex-stm32-p407/src/Make.defs @@ -67,6 +67,10 @@ ifeq ($(CONFIG_CAN),y) CSRCS += stm32_can.c endif +ifeq ($(CONFIG_AUDIO_CS4344),y) + CSRCS += stm32_cs4344.c +endif + DEPPATH += --dep-path board VPATH += :board CFLAGS += $(shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board) diff --git a/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h b/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h index f3abd4a97c4..c5e380aacd7 100644 --- a/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h +++ b/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h @@ -48,6 +48,7 @@ #include #include #include +#include /**************************************************************************** * Pre-processor Definitions @@ -187,6 +188,18 @@ # define GPIO_OTGFS_OVER (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN10) #endif +/* The CS4344 depends on the CS4344 driver and I2S3 support */ + +#if defined(CONFIG_AUDIO_CS4344) && defined(CONFIG_STM32_I2S3) +# define HAVE_CS4344 +#endif + +#ifdef HAVE_CS4344 + /* The CS4344 transfers data on I2S3 */ + +# define CS4344_I2S_BUS 3 +#endif + #ifndef __ASSEMBLY__ /**************************************************************************** @@ -290,5 +303,26 @@ int stm32_adc_setup(void); int stm32_can_setup(void); #endif +/**************************************************************************** + * Name: stm32_cs4344_initialize + * + * Description: + * This function is called by platform-specific, setup logic to configure + * and register the CS4344 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. + * + ****************************************************************************/ + +#ifdef CONFIG_AUDIO_CS4344 +int stm32_cs4344_initialize(int minor); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __BOARDS_ARM_STM32_OLIMEX_STM32_P407_SRC_H */ diff --git a/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c b/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c index 8ba3ae8b105..7431d87e85c 100644 --- a/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c +++ b/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c @@ -213,6 +213,16 @@ int stm32_bringup(void) } #endif +#ifdef HAVE_CS4344 + /* Configure CS4344 audio */ + + ret = stm32_cs4344_initialize(1); + if (ret != OK) + { + serr("Failed to initialize CS43L22 audio: %d\n", ret); + } +#endif + UNUSED(ret); return OK; } diff --git a/boards/arm/stm32/olimex-stm32-p407/src/stm32_cs4344.c b/boards/arm/stm32/olimex-stm32-p407/src/stm32_cs4344.c new file mode 100644 index 00000000000..9ddac4439b7 --- /dev/null +++ b/boards/arm/stm32/olimex-stm32-p407/src/stm32_cs4344.c @@ -0,0 +1,169 @@ +/**************************************************************************** + * boards/arm/stm32/stm32f4discovery/src/stm32_cs4344.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 + +#include + +#include "stm32.h" +#include "olimex-stm32-p407.h" + +#ifdef HAVE_CS4344 + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_cs4344_initialize + * + * Description: + * This function is called by platform-specific, setup logic to configure + * and register the CS4344 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_cs4344_initialize(int minor) +{ + FAR struct audio_lowerhalf_s *cs4344; + FAR struct audio_lowerhalf_s *pcm; + 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) + { + /* Get an instance of the I2S interface for the CS4344 data channel */ + + i2s = stm32_i2sbus_initialize(CS4344_I2S_BUS); + if (!i2s) + { + auderr("ERROR: Failed to initialize I2S%d\n", CS4344_I2S_BUS); + ret = -ENODEV; + goto errout; + } + + /* Now we can use this I2S interface to initialize the CS4344 which + * will return an audio interface. + */ + + cs4344 = cs4344_initialize(i2s); + if (!cs4344) + { + auderr("ERROR: Failed to initialize the CS4344\n"); + ret = -ENODEV; + goto errout; + } + + /* No we can embed the CS4344/I2S conglomerate into a PCM decoder + * instance so that we will have a PCM front end for the the CS4344 + * driver. + */ + + pcm = pcm_decode_initialize(cs4344); + if (!pcm) + { + auderr("ERROR: Failed create the PCM decoder\n"); + ret = -ENODEV; + goto errout; + } + + /* Create a device name */ + + snprintf(devname, 12, "pcm%d", minor); + + /* Finally, we can register the PCM/CS4344/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; + } + + /* Now we are initialized */ + + initialized = true; + } + + return OK; + +errout: + return ret; +} + +#endif /* HAVE_CS4344 */