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
|
||||
test. See apps/examples/pwm.
|
||||
|
||||
if AUDIO_I2SCHAR && (SAMA5_SSC0 || SAMA5_SSC1)
|
||||
if AUDIO_WM8904
|
||||
|
||||
if SAMA5_SSC0 && SAMA5_SSC1
|
||||
|
||||
config SAMA5D4EK_SSC_PORT
|
||||
int "SSC port number"
|
||||
default 0
|
||||
range 0 1
|
||||
config SAMA5D4EK_WM8904_I2CFREQUENCY
|
||||
int "WM8904 I2C Frequency"
|
||||
default 400000
|
||||
range 1 400000
|
||||
---help---
|
||||
Specify the I2S port to use, i.e., 0 for SSC0 or 1 for SSC1
|
||||
|
||||
endif # SAMA5_SSC0 && SAMA5_SSC1
|
||||
|
||||
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)
|
||||
This option selects the I2C frequency to use when communicating with
|
||||
the WM8904 device. The default, 400KHz, is the maximum supported by
|
||||
the WM8904. If you have problems communicating with the WM8904,
|
||||
then you might want to try lowering this rate.
|
||||
|
||||
endif # AUDIO_WM8904
|
||||
endif # ARCH_BOARD_SAMA5D4_EK
|
||||
|
@ -91,8 +91,7 @@ Contents
|
||||
- RTC
|
||||
- Watchdog Timer
|
||||
- TRNG and /dev/random
|
||||
- I2S Audio Support
|
||||
- WM8904 Support
|
||||
- Audio Support
|
||||
- TM7000 LCD/Touchscreen
|
||||
- SAMA4D4-EK Configuration Options
|
||||
- Configurations
|
||||
@ -2709,116 +2708,84 @@ TRNG and /dev/random
|
||||
CONFIG_EXAMPLES_MAXSAMPLES=64 : Default settings are probably OK
|
||||
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
|
||||
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
|
||||
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 SAMA5D4 NuttX Pin Name
|
||||
------------- ---------------- -----------------
|
||||
3 SDA PA30 TWD0 PIO_TWI0_D
|
||||
2 SCLK PA31 TWCK0 PIO_TWI0_CK
|
||||
28 MCLK PD30 PCK0 PIO_PMC_PCK0
|
||||
29 BCLK/GPIO4 PC16 TK PIO_SSC0_TK
|
||||
"" " " PC19 RK PIO_SSC0_RK
|
||||
30 LRCLK PC17 TF PIO_SSC0_TF
|
||||
"" " " PC20 RF PIO_SSC0_RF
|
||||
31 ADCDAT PC21 RD PIO_SSC0_RD
|
||||
32 DACDAT PC18 TD PIO_SSC0_TD
|
||||
1 IRQ/GPIO1 PD16 INT_AUDIO N/A
|
||||
------------- ---------------- -----------------
|
||||
WM8904 Configuration
|
||||
--------------------
|
||||
System Type -> SAMA5 Peripheral Support
|
||||
CONFIG_SAMA5_TWI0=y : Enable TWI0 driver support
|
||||
CONFIG_SAMA5_SSCO=y : Enable SSC0 driver support
|
||||
CONFIG_SAMA5_XDMAC1=y : XDMAC0 required by SSC0
|
||||
|
||||
System Type -> SSC0 Configuration
|
||||
CONFIG_SAMA5_SSC_MAXINFLIGHT=16
|
||||
CONFIG_SAMA5_SSC0_DATALEN=16
|
||||
|
||||
Device Drivers -> SPI Driver Support
|
||||
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
|
||||
-----------------
|
||||
|
||||
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.
|
||||
The I2S driver was verified in loopback mode with no audio device.
|
||||
|
||||
[NOTE: The above statement is anticipatory: As of this writing I2S driver
|
||||
verification is underway and still not complete].
|
||||
|
||||
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
|
||||
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
|
||||
file at SAMA5D4-EK for information about how you might implement this test
|
||||
for the SAMA5D4-EK.
|
||||
|
||||
TM7000 LCD/Touchscreen
|
||||
======================
|
||||
|
@ -76,6 +76,14 @@ CSRCS += sam_at25.c
|
||||
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)
|
||||
CSRCS += sam_hsmci.c
|
||||
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_NETWORK 1
|
||||
#define HAVE_MAXTOUCH 1
|
||||
#define HAVE_WM8904 1
|
||||
|
||||
/* HSMCI */
|
||||
/* Can't support MMC/SD if the card interface(s) are not enable */
|
||||
@ -315,6 +316,36 @@
|
||||
# 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 *****************************************************************************/
|
||||
/* There are 3 LEDs on the SAMA5D4-EK:
|
||||
*
|
||||
@ -649,6 +680,15 @@
|
||||
PIO_INT_BOTHEDGES | PIO_PORT_PIOE | PIO_PIN4)
|
||||
#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 *****************************************************************/
|
||||
/* The SAMA5D4-EK includes an Atmel AT25DF321A, 32-megabit, 2.7-volt SPI serial
|
||||
* FLASH on board. The connection is as follows:
|
||||
@ -859,6 +899,27 @@ void board_led_initialize(void);
|
||||
int nsh_archinitialize(void);
|
||||
#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 /* __CONFIGS_SAMA5D4_EK_SRC_SAMA5D4_EK_H */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user