SAMA5D4-EK: Add WM8904 initialization logic
This commit is contained in:
parent
17fdc797ed
commit
414fb2b154
@ -198,43 +198,17 @@ config SAMA5D4EK_CHANNEL
|
|||||||
Selects the PWM channel number that will be used to perform the PWM
|
Selects the PWM channel number that will be used to perform the PWM
|
||||||
test. See apps/examples/pwm.
|
test. See apps/examples/pwm.
|
||||||
|
|
||||||
if AUDIO_I2SCHAR && (SAMA5_SSC0 || SAMA5_SSC1)
|
if AUDIO_WM8904
|
||||||
|
|
||||||
if SAMA5_SSC0 && SAMA5_SSC1
|
config SAMA5D4EK_WM8904_I2CFREQUENCY
|
||||||
|
int "WM8904 I2C Frequency"
|
||||||
config SAMA5D4EK_SSC_PORT
|
default 400000
|
||||||
int "SSC port number"
|
range 1 400000
|
||||||
default 0
|
|
||||||
range 0 1
|
|
||||||
---help---
|
---help---
|
||||||
Specify the I2S port to use, i.e., 0 for SSC0 or 1 for SSC1
|
This option selects the I2C frequency to use when communicating with
|
||||||
|
the WM8904 device. The default, 400KHz, is the maximum supported by
|
||||||
endif # SAMA5_SSC0 && SAMA5_SSC1
|
the WM8904. If you have problems communicating with the WM8904,
|
||||||
|
then you might want to try lowering this rate.
|
||||||
if SAMA5_SSC0 && !SAMA5_SSC1
|
|
||||||
|
|
||||||
config SAMA5D4EK_SSC_PORT
|
|
||||||
int
|
|
||||||
default 0
|
|
||||||
|
|
||||||
endif # SAMA5_SSC0 && !SAMA5_SSC1
|
|
||||||
|
|
||||||
if !SAMA5_SSC0 && SAMA5_SSC1
|
|
||||||
|
|
||||||
config SAMA5D4EK_SSC_PORT
|
|
||||||
int
|
|
||||||
default 1
|
|
||||||
|
|
||||||
endif # SAMA5_SSC0 && !SAMA5_SSC1
|
|
||||||
|
|
||||||
config SAMA5D4EK_I2SCHAR_MINOR
|
|
||||||
int "I2S character driver minor number"
|
|
||||||
default 0
|
|
||||||
---help---
|
|
||||||
The minor device number to use when registering the I2S character
|
|
||||||
device. The driver will be registered at /dev/is2charN where N is
|
|
||||||
the value provided by this setting.
|
|
||||||
|
|
||||||
endif # AUDIO_I2SCHAR && (SAMA5_SSC0 || SAMA5_SSC1)
|
|
||||||
|
|
||||||
|
endif # AUDIO_WM8904
|
||||||
endif # ARCH_BOARD_SAMA5D4_EK
|
endif # ARCH_BOARD_SAMA5D4_EK
|
||||||
|
@ -91,8 +91,7 @@ Contents
|
|||||||
- RTC
|
- RTC
|
||||||
- Watchdog Timer
|
- Watchdog Timer
|
||||||
- TRNG and /dev/random
|
- TRNG and /dev/random
|
||||||
- I2S Audio Support
|
- Audio Support
|
||||||
- WM8904 Support
|
|
||||||
- TM7000 LCD/Touchscreen
|
- TM7000 LCD/Touchscreen
|
||||||
- SAMA4D4-EK Configuration Options
|
- SAMA4D4-EK Configuration Options
|
||||||
- Configurations
|
- Configurations
|
||||||
@ -2709,116 +2708,84 @@ TRNG and /dev/random
|
|||||||
CONFIG_EXAMPLES_MAXSAMPLES=64 : Default settings are probably OK
|
CONFIG_EXAMPLES_MAXSAMPLES=64 : Default settings are probably OK
|
||||||
CONFIG_EXAMPLES_NSAMPLES=8
|
CONFIG_EXAMPLES_NSAMPLES=8
|
||||||
|
|
||||||
I2S Audio Support
|
Audio Support
|
||||||
=================
|
==============
|
||||||
|
|
||||||
|
WM8904 CODEC
|
||||||
|
------------
|
||||||
The SAMA4D4-EK has two devices on-board that can be used for verification
|
The SAMA4D4-EK has two devices on-board that can be used for verification
|
||||||
of I2S functionality: HDMI and a WM8904 audio CODEC. As of this writing,
|
of I2S functionality: HDMI and a WM8904 audio CODEC. As of this writing,
|
||||||
the I2S driver is present, but there are not drivers for either the HDMI
|
the I2S driver is present, but there are not drivers for either the HDMI
|
||||||
or the WM8904.
|
or the WM8904.
|
||||||
|
|
||||||
WM8904 Audio CODEC Interface
|
WM8904 Audio CODEC Interface:
|
||||||
----------------------------
|
---- ------------------ ---------------- ------------- ---------------------------------------
|
||||||
|
PIO USAGE BOARD SIGNAL WM8904 PIN NOTE
|
||||||
|
---- ------------------ ---------------- ------------- ---------------------------------------
|
||||||
|
PA30 TWD0 AUDIO_TWD0_PA30 3 SDA Pulled up, See J23 note below
|
||||||
|
PA31 TWCK0 AUDIO_TWCK0_PA31 2 SCLK Pulled up
|
||||||
|
PB10 AUDIO_PCK2/EXP AUDIO_PCK2_PB10 28 MCLK
|
||||||
|
PB27 AUDIO/HDMI_TK0/EXP AUDIO_TK0_PB27 29 BCLK/GPIO4 Note TK0 and RK0 are mutually exclusive
|
||||||
|
PB26 AUDIO_RK0 AUDIO_RK0_PB26 29 " "/" " " " " " " " " " " " " " " "
|
||||||
|
PB30 AUDIO_RF/ZIG_TWCK2 AUDIO_RF0_PB30 30 LRCLK Note TF0 and RF0 are mutually exclusive
|
||||||
|
PB31 AUDIO/HDMI_TF0/EXP AUDIO_TF0_PB31 30 " " " " " " " " " " " " " " " "
|
||||||
|
PB29 AUDIO_RD0/ZIG_TWD2 AUDIO_RD0_PB29 31 ADCDAT
|
||||||
|
PB28 AUDIO/HDMI_TD0/EXP AUDIO_TD0_PB28 32 ACDAT
|
||||||
|
PE4 AUDIO_IRQ AUDIO_IRQ_PE4 1 IRQ/GPIO1 Audio interrupt
|
||||||
|
---- ------------------ ---------------- ------------- ---------------------------------------
|
||||||
|
Note that jumper J23 must be closed to connect AUDIO_TWD0_PA30
|
||||||
|
|
||||||
------------- ---------------- -----------------
|
WM8904 Configuration
|
||||||
WM8904 SAMA5D4 NuttX Pin Name
|
--------------------
|
||||||
------------- ---------------- -----------------
|
System Type -> SAMA5 Peripheral Support
|
||||||
3 SDA PA30 TWD0 PIO_TWI0_D
|
CONFIG_SAMA5_TWI0=y : Enable TWI0 driver support
|
||||||
2 SCLK PA31 TWCK0 PIO_TWI0_CK
|
CONFIG_SAMA5_SSCO=y : Enable SSC0 driver support
|
||||||
28 MCLK PD30 PCK0 PIO_PMC_PCK0
|
CONFIG_SAMA5_XDMAC1=y : XDMAC0 required by SSC0
|
||||||
29 BCLK/GPIO4 PC16 TK PIO_SSC0_TK
|
|
||||||
"" " " PC19 RK PIO_SSC0_RK
|
System Type -> SSC0 Configuration
|
||||||
30 LRCLK PC17 TF PIO_SSC0_TF
|
CONFIG_SAMA5_SSC_MAXINFLIGHT=16
|
||||||
"" " " PC20 RF PIO_SSC0_RF
|
CONFIG_SAMA5_SSC0_DATALEN=16
|
||||||
31 ADCDAT PC21 RD PIO_SSC0_RD
|
|
||||||
32 DACDAT PC18 TD PIO_SSC0_TD
|
Device Drivers -> SPI Driver Support
|
||||||
1 IRQ/GPIO1 PD16 INT_AUDIO N/A
|
CONFIG_SPI=y : Enable SPI support
|
||||||
------------- ---------------- -----------------
|
CONFIG_SPI_EXCHANGE=y : Support the exchange method
|
||||||
|
|
||||||
|
System Type -> SSC Configuration
|
||||||
|
CONFIG_SAMA5_SSC_MAXINFLIGHT=16 : Up to 16 pending DMA transfers
|
||||||
|
CONFIG_SAMA5_SSC0_MASTER=y : Master mode
|
||||||
|
CONFIG_SAMA5_SSC0_DATALEN=16 : 16-bit data
|
||||||
|
CONFIG_SAMA5_SSC0_RX=n : No receiver
|
||||||
|
CONFIG_SAMA5_SSC0_TX=y : Support a transmitter
|
||||||
|
CONFIG_SAMA5_SSC0_TX_MCKDIV=y : Transmitter gets clock from MCK/2
|
||||||
|
CONFIG_SAMA5_SSC0_MCKDIV_SAMPLERATE=48000 : Sampling at 48K samples/sec
|
||||||
|
CONFIG_SAMA5_SSC0_TX_TKOUTPUT_XFR=y : Outputs clock on TK when transferring data
|
||||||
|
|
||||||
|
Audio
|
||||||
|
CONFIG_AUDIO=y : Audio support needed
|
||||||
|
CONFIG_AUDIO_FORMAT_PCM=y : Only PCM files are supported
|
||||||
|
|
||||||
|
Drivers -> Audio
|
||||||
|
CONFIG_I2S=y : General I2S support
|
||||||
|
CONFIG_AUDIO_DEVICES=y : Audio device support
|
||||||
|
CONFIG_AUDIO_NUM_BUFFERS=8 : Number of audio buffers
|
||||||
|
CONFIG_AUDIO_BUFFER_NUMBYTES=8192 : Audio buffer size
|
||||||
|
CONFIG_AUDIO_WM8904=y : Build WM8904 driver character driver
|
||||||
|
|
||||||
|
Board Selection
|
||||||
|
CONFIG_SAMA5D4EK_WM8904_I2CFREQUENCY=400000
|
||||||
|
|
||||||
|
Library Routines
|
||||||
|
CONFIG_SCHED_WORKQUEUE=y : MW8904 driver needs work queue support
|
||||||
|
|
||||||
I2S Loopback Test
|
I2S Loopback Test
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
The I2S driver was verified using a special I2C character driver (at
|
The I2S driver was verified using a special I2C character driver (at
|
||||||
nuttx/drivers/audio/i2schar.c) and a test driver at apps/examples/i2schar.
|
nuttx/drivers/audio/i2schar.c) and a test driver at apps/examples/i2schar.
|
||||||
The I2S driver was verified in loopback mode with no audio device.
|
The I2S driver was verified in loopback mode with no audio device. That
|
||||||
|
test case has never been exercised on the SAMA454-EK. See the README.txt
|
||||||
[NOTE: The above statement is anticipatory: As of this writing I2S driver
|
file at SAMA5D4-EK for information about how you might implement this test
|
||||||
verification is underway and still not complete].
|
for the SAMA5D4-EK.
|
||||||
|
|
||||||
This section describes the modifications to the NSH configuration that were
|
|
||||||
used to perform the I2S testing:
|
|
||||||
|
|
||||||
System Type -> SAMA5 Peripheral Support
|
|
||||||
CONFIG_SAMA5_SSCO=y : Enable SSC0 driver support
|
|
||||||
CONFIG_SAMA5_DMAC0=y : DMAC0 required by SSC0
|
|
||||||
|
|
||||||
Alternatively, SSC1 could have be used:
|
|
||||||
|
|
||||||
System Type -> SAMA5 Peripheral Support
|
|
||||||
CONFIG_SAMA5_SSC1=y : Enable SSC0 driver support
|
|
||||||
CONFIG_SAMA5_DMAC1=y : DMAC0 required by SSC0
|
|
||||||
|
|
||||||
System Type -> SSC Configuration
|
|
||||||
CONFIG_SAMA5_SSC_MAXINFLIGHT=16 : Up to 16 pending DMA transfers
|
|
||||||
CONFIG_SAMA5_SSC0_MASTER=y : Master mode
|
|
||||||
CONFIG_SAMA5_SSC0_DATALEN=16 : 16-bit data
|
|
||||||
CONFIG_SAMA5_SSC0_RX=y : Support a receiver
|
|
||||||
CONFIG_SAMA5_SSC0_RX_RKINPUT=y : Receiver gets clock from RK input
|
|
||||||
CONFIG_SAMA5_SSC0_TX=y : Support a transmitter
|
|
||||||
CONFIG_SAMA5_SSC0_TX_MCKDIV=y : Transmitter gets clock from MCK/2
|
|
||||||
CONFIG_SAMA5_SSC0_MCKDIV_SAMPLERATE=48000 : Sampling at 48K samples/sec
|
|
||||||
CONFIG_SAMA5_SSC0_TX_TKOUTPUT_XFR=y : Outputs clock on TK when transferring data
|
|
||||||
CONFIG_SAMA5_SSC0_LOOPBACK=y : Loopmode mode connects RD/TD and RK/TK
|
|
||||||
|
|
||||||
Audio
|
|
||||||
CONFIG_AUDIO=y : Audio support needed
|
|
||||||
: Defaults should be okay
|
|
||||||
|
|
||||||
Drivers -> Audio
|
|
||||||
CONFIG_I2S=y : General I2S support
|
|
||||||
CONFIG_AUDIO_DEVICES=y : Audio device support
|
|
||||||
CONFIG_AUDIO_I2SCHAR=y : Build I2S character driver
|
|
||||||
|
|
||||||
The following describes how I have the test application at
|
|
||||||
apps/examples/i2schar configured:
|
|
||||||
|
|
||||||
CONFIG_EXAMPLES_I2SCHAR=y
|
|
||||||
CONFIG_EXAMPLES_I2SCHAR_DEVPATH="/dev/i2schar0"
|
|
||||||
CONFIG_EXAMPLES_I2SCHAR_TX=y
|
|
||||||
CONFIG_EXAMPLES_I2SCHAR_TXBUFFERS=4
|
|
||||||
CONFIG_EXAMPLES_I2SCHAR_TXSTACKSIZE=1536
|
|
||||||
CONFIG_EXAMPLES_I2SCHAR_RX=y
|
|
||||||
CONFIG_EXAMPLES_I2SCHAR_RXBUFFERS=4
|
|
||||||
CONFIG_EXAMPLES_I2SCHAR_RXSTACKSIZE=1536
|
|
||||||
CONFIG_EXAMPLES_I2SCHAR_BUFSIZE=256
|
|
||||||
CONFIG_EXAMPLES_I2SCHAR_DEVINIT=y
|
|
||||||
|
|
||||||
Board Selection
|
|
||||||
CONFIG_SAMA5D4EK_I2SCHAR_MINOR=0
|
|
||||||
CONFIG_SAMA5D4EK_SSC_PORT=0 : 0 or SSC0, 1 for SSC1
|
|
||||||
|
|
||||||
Library Routines
|
|
||||||
CONFIG_SCHED_WORKQUEUE=y : Driver needs work queue support
|
|
||||||
|
|
||||||
WM8904 Support
|
|
||||||
==============
|
|
||||||
|
|
||||||
SAMA5D4 Interface
|
|
||||||
---- ------------------ ---------------- ---------- ---------------------------------------
|
|
||||||
PIO USAGE BOARD SIGNAL WM8904 PIN NOTE
|
|
||||||
---- ------------------ ---------------- ---------- ---------------------------------------
|
|
||||||
PA30 TWD0 AUDIO_TWD0_PA30 SDA Pulled up, See J23 note below
|
|
||||||
PA31 TWCK0 AUDIO_TWCK0_PA31 SCLK Pulled up
|
|
||||||
PB10 AUDIO_PCK2/EXP AUDIO_PCK2_PB10 MCLK
|
|
||||||
PB27 AUDIO/HDMI_TK0/EXP AUDIO_TK0_PB27 BCLK/GPIO4 Note TK0 and RK0 are mutually exclusive
|
|
||||||
PB26 AUDIO_RK0 AUDIO_RK0_PB26 " "/" " " " " " " " " " " " " " " "
|
|
||||||
PB30 AUDIO_RF/ZIG_TWCK2 AUDIO_RF0_PB30 LRCLK Note TF0 and RF0 are mutually exclusive
|
|
||||||
PB31 AUDIO/HDMI_TF0/EXP AUDIO_TF0_PB31 " " " " " " " " " " " " " " " "
|
|
||||||
PB29 AUDIO_RD0/ZIG_TWD2 AUDIO_RD0_PB29 ADCDAT
|
|
||||||
PB28 AUDIO/HDMI_TD0/EXP AUDIO_TD0_PB28 ACDAT
|
|
||||||
PE4 AUDIO_IRQ AUDIO_IRQ_PE4 IRQ/GPIO1 Audio interrupt
|
|
||||||
---- ------------------ ---------------- ---------- ---------------------------------------
|
|
||||||
Note that jumper J23 must be closed to connect AUDIO_TWD0_PA30
|
|
||||||
|
|
||||||
TM7000 LCD/Touchscreen
|
TM7000 LCD/Touchscreen
|
||||||
======================
|
======================
|
||||||
|
@ -76,6 +76,14 @@ CSRCS += sam_at25.c
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_AUDIO_WM8904),y)
|
||||||
|
ifeq ($(CONFIG_SAMA5_TWI0),y)
|
||||||
|
ifeq ($(CONFIG_SAMA5_SSC0),y)
|
||||||
|
CSRCS += sam_wm8904.c
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_SAMA5_HSMCI0),y)
|
ifeq ($(CONFIG_SAMA5_HSMCI0),y)
|
||||||
CSRCS += sam_hsmci.c
|
CSRCS += sam_hsmci.c
|
||||||
else
|
else
|
||||||
|
316
configs/sama5d4-ek/src/sam_wm8904.c
Normal file
316
configs/sama5d4-ek/src/sam_wm8904.c
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
/************************************************************************************
|
||||||
|
* configs/sama5d4-ek/src/sam_wm8904.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 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.
|
||||||
|
*
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <nuttx/i2c.h>
|
||||||
|
#include <nuttx/audio/i2s.h>
|
||||||
|
#include <nuttx/audio/wm8904.h>
|
||||||
|
|
||||||
|
#include "up_arch.h"
|
||||||
|
#include "sam_pio.h"
|
||||||
|
#include "sam_twi.h"
|
||||||
|
#include "sam_ssc.h"
|
||||||
|
|
||||||
|
#include "sama5d4-ek.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_WM8904
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-Processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct sama5d4ek_mwinfo_s
|
||||||
|
{
|
||||||
|
/* Standard MW8904 interface */
|
||||||
|
|
||||||
|
struct wm8904_lower_s lower;
|
||||||
|
|
||||||
|
/* Extensions for the sama5d4ek board */
|
||||||
|
|
||||||
|
wm8904_handler_t handler;
|
||||||
|
FAR void *arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Function Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* IRQ/PIO access callbacks. These operations all hidden behind
|
||||||
|
* callbacks to isolate the WM8904 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 WM8904 interrupt handler to the PIO interrupt
|
||||||
|
* enable - Enable or disable the PIO interrupt
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int wm8904_attach(FAR const struct wm8904_lower_s *lower,
|
||||||
|
wm8904_handler_t isr, FAR void *arg);
|
||||||
|
static void wm8904_enable(FAR const struct wm8904_lower_s *lower,
|
||||||
|
bool enable);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* A reference to a structure of this type must be passed to the WM8904
|
||||||
|
* driver. This structure provides information about the configuration
|
||||||
|
* of the WM8904 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct sama5d4ek_mwinfo_s g_mxtinfo =
|
||||||
|
{
|
||||||
|
.lower =
|
||||||
|
{
|
||||||
|
.address = WM8904_I2C_ADDRESS,
|
||||||
|
.frequency = CONFIG_SAMA5D4EK_WM8904_I2CFREQUENCY,
|
||||||
|
|
||||||
|
.attach = wm8904_attach,
|
||||||
|
.enable = wm8904_enable,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* IRQ/PIO access callbacks. These operations all hidden behind
|
||||||
|
* callbacks to isolate the WM8904 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 WM8904 interrupt handler to the PIO interrupt
|
||||||
|
* enable - Enable or disable the PIO interrupt
|
||||||
|
* clear - Acknowledge/clear any pending PIO interrupt
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int wm8904_attach(FAR const struct wm8904_lower_s *lower,
|
||||||
|
wm8904_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 wm8904_interrupt() when the interrupt occurs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ivdbg("Attaching %p\n", isr);
|
||||||
|
g_mxtinfo.handler = isr;
|
||||||
|
g_mxtinfo.arg = arg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ivdbg("Detaching %p\n", g_mxtinfo.handler);
|
||||||
|
wm8904_enable(lower, false);
|
||||||
|
g_mxtinfo.handler = NULL;
|
||||||
|
g_mxtinfo.arg = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wm8904_enable(FAR const struct wm8904_lower_s *lower, bool enable)
|
||||||
|
{
|
||||||
|
/* Enable or disable interrupts */
|
||||||
|
|
||||||
|
if (enable && g_mxtinfo.handler)
|
||||||
|
{
|
||||||
|
sam_pioirqenable(IRQ_INT_WM8904);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sam_pioirqdisable(IRQ_INT_WM8904);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wm8904_interrupt(int irq, FAR void *context)
|
||||||
|
{
|
||||||
|
/* Just forward the interrupt to the WM8904 driver */
|
||||||
|
|
||||||
|
if (g_mxtinfo.handler)
|
||||||
|
{
|
||||||
|
return g_mxtinfo.handler(&g_mxtinfo.lower, g_mxtinfo.arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We got an interrupt with no handler. This should not
|
||||||
|
* happen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sam_pioirqdisable(IRQ_INT_WM8904);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: sam_wm8904_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function is called by platform-specific, setup logic to configure
|
||||||
|
* and register the WM8904 device. This function will register the driver
|
||||||
|
* as /dev/wm8904[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 sam_wm8904_initialize(int minor)
|
||||||
|
{
|
||||||
|
FAR struct audio_lowerhalf_s *audio;
|
||||||
|
FAR struct i2c_dev_s *i2c;
|
||||||
|
FAR struct i2s_dev_s *i2s;
|
||||||
|
static bool initialized = false;
|
||||||
|
char devname[8];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
auddbg("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)
|
||||||
|
{
|
||||||
|
/* Configure the WM8904 interrupt pin */
|
||||||
|
|
||||||
|
(void)sam_configpio(PIO_INT_WM8904);
|
||||||
|
|
||||||
|
/* Get an instance of the I2C interface for the WM8904 chip select */
|
||||||
|
|
||||||
|
i2c = up_i2cinitialize(WM8904_TWI_BUS);
|
||||||
|
if (!i2c)
|
||||||
|
{
|
||||||
|
auddbg("Failed to initialize TWI%d\n", WM8904_TWI_BUS);
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get an instance of the I2S interface for the WM8904 data channel */
|
||||||
|
|
||||||
|
i2s = sam_ssc_initialize(WM8904_SSC_BUS);
|
||||||
|
if (!i2s)
|
||||||
|
{
|
||||||
|
auddbg("Failed to initialize SSC%d\n", WM8904_SSC_BUS);
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto errout_with_i2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we can use these I2C and I2S interfaces to initialize the
|
||||||
|
* MW8904 which will return an audio interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
audio = wm8904_initialize(i2c, i2s, &g_mxtinfo.lower, minor);
|
||||||
|
if (!audio)
|
||||||
|
{
|
||||||
|
auddbg("Failed to initialize the WM8904\n");
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto errout_with_i2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure WM8904 interrupts */
|
||||||
|
|
||||||
|
sam_pioirq(PIO_INT_WM8904);
|
||||||
|
ret = irq_attach(IRQ_INT_WM8904, wm8904_interrupt);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
auddbg("ERROR: Failed to register WM8904 device: %d\n", ret);
|
||||||
|
goto errout_with_audio;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a device name */
|
||||||
|
|
||||||
|
snprintf(devname, 8, "wm8904%c", 'a' + minor);
|
||||||
|
|
||||||
|
/* Register the WM8904 audio device */
|
||||||
|
|
||||||
|
ret = audio_register(devname, audio);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
auddbg("ERROR: Failed to register /dev/%s device: %d\n", devname, ret);
|
||||||
|
goto errout_with_irq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we are initialized */
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
/* Error exits. Unfortunately there is no mechanism in place now to
|
||||||
|
* recover errors on initialization failures.
|
||||||
|
*/
|
||||||
|
|
||||||
|
errout_with_irq:
|
||||||
|
irq_detach(IRQ_INT_WM8904);
|
||||||
|
errout_with_audio:
|
||||||
|
errout_with_i2s:
|
||||||
|
errout_with_i2c:
|
||||||
|
errout:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_WM8904 */
|
@ -64,6 +64,7 @@
|
|||||||
#define HAVE_USBMONITOR 1
|
#define HAVE_USBMONITOR 1
|
||||||
#define HAVE_NETWORK 1
|
#define HAVE_NETWORK 1
|
||||||
#define HAVE_MAXTOUCH 1
|
#define HAVE_MAXTOUCH 1
|
||||||
|
#define HAVE_WM8904 1
|
||||||
|
|
||||||
/* HSMCI */
|
/* HSMCI */
|
||||||
/* Can't support MMC/SD if the card interface(s) are not enable */
|
/* Can't support MMC/SD if the card interface(s) are not enable */
|
||||||
@ -315,6 +316,36 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Audio */
|
||||||
|
/* Default configuration values */
|
||||||
|
|
||||||
|
#ifndef CONFIG_AUDIO_WM8904
|
||||||
|
# undef HAVE_WM8904
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_WM8904
|
||||||
|
# ifndef CONFIG_SAMA5_TWI0
|
||||||
|
# warning CONFIG_SAMA5_TWI0 is required for audio support
|
||||||
|
# undef HAVE_WM8904
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifndef CONFIG_SAMA5_SSC0
|
||||||
|
# warning CONFIG_SAMA5_SSC0 is required for audio support
|
||||||
|
# undef HAVE_WM8904
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifndef CONFIG_SAMA5D4EK_WM8904_I2CFREQUENCY
|
||||||
|
# warning Defaulting to maximum WM8904 I2C frequency
|
||||||
|
# define CONFIG_SAMA5D4EK_WM8904_I2CFREQUENCY 400000
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if CONFIG_SAMA5D4EK_WM8904_I2CFREQUENCY > 400000
|
||||||
|
# warning WM8904 I2C frequency cannot exceed 400KHz
|
||||||
|
# undef CONFIG_SAMA5D4EK_WM8904_I2CFREQUENCY
|
||||||
|
# define CONFIG_SAMA5D4EK_WM8904_I2CFREQUENCY 400000
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* LEDs *****************************************************************************/
|
/* LEDs *****************************************************************************/
|
||||||
/* There are 3 LEDs on the SAMA5D4-EK:
|
/* There are 3 LEDs on the SAMA5D4-EK:
|
||||||
*
|
*
|
||||||
@ -649,6 +680,15 @@
|
|||||||
PIO_INT_BOTHEDGES | PIO_PORT_PIOE | PIO_PIN4)
|
PIO_INT_BOTHEDGES | PIO_PORT_PIOE | PIO_PIN4)
|
||||||
#define IRQ_INT_WM8904 SAM_IRQ_PE4
|
#define IRQ_INT_WM8904 SAM_IRQ_PE4
|
||||||
|
|
||||||
|
/* The MW8904 communicates on TWI0, I2C address 0x1a for control operations */
|
||||||
|
|
||||||
|
#define WM8904_TWI_BUS 0
|
||||||
|
#define WM8904_I2C_ADDRESS 0x1a
|
||||||
|
|
||||||
|
/* The MW8904 transfers data on SSC0 */
|
||||||
|
|
||||||
|
#define WM8904_SSC_BUS 0
|
||||||
|
|
||||||
/* SPI Chip Selects *****************************************************************/
|
/* SPI Chip Selects *****************************************************************/
|
||||||
/* The SAMA5D4-EK includes an Atmel AT25DF321A, 32-megabit, 2.7-volt SPI serial
|
/* The SAMA5D4-EK includes an Atmel AT25DF321A, 32-megabit, 2.7-volt SPI serial
|
||||||
* FLASH on board. The connection is as follows:
|
* FLASH on board. The connection is as follows:
|
||||||
@ -859,6 +899,27 @@ void board_led_initialize(void);
|
|||||||
int nsh_archinitialize(void);
|
int nsh_archinitialize(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: sam_wm8904_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function is called by platform-specific, setup logic to configure
|
||||||
|
* and register the WM8904 device. This function will register the driver
|
||||||
|
* as /dev/wm8904[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_WM8904
|
||||||
|
int sam_wm8904_initialize(int minor);
|
||||||
|
#endif /* HAVE_WM8904 */
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
#endif /* __CONFIGS_SAMA5D4_EK_SRC_SAMA5D4_EK_H */
|
#endif /* __CONFIGS_SAMA5D4_EK_SRC_SAMA5D4_EK_H */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user