提交 e0314e63 编写于 作者: X xx

添加iis驱动

上级 5e477ae0
......@@ -3,10 +3,10 @@ import sys
import rtconfig
if os.getenv('RTT_ROOT'):
RTT_ROOT = os.getenv('RTT_ROOT')
else:
RTT_ROOT = os.path.normpath(os.getcwd() + '/../..')
#if os.getenv('RTT_ROOT'):
# RTT_ROOT = os.getenv('RTT_ROOT')
#else:
RTT_ROOT = os.path.normpath(os.getcwd() + '/../..')
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
from building import *
......
......@@ -38,6 +38,9 @@ if GetDepend('RT_USING_USB_DEVICE'):
if GetDepend('RT_USING_RTGUI') or GetDepend('PKG_USING_GUIENGINE'):
src += ['drv_lcd.c', 'drv_ft5406.c', 'drv_i2c.c']
if GetDepend('RT_USING_AUDIO'):
src += ['drv_codec.c', 'fsl_wm8960.c']
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES=CPPDEFINES)
Return('group')
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#include "drv_codec.h"
#include "fsl_wm8960.h"
#include <fsl_sai.h>
#include <fsl_sai_edma.h>
#include <fsl_lpi2c.h>
#include <fsl_dmamux.h>
#define DEMO_CODEC_WM8960
#define DEMO_SAI SAI1
#define DEMO_SAI_IRQ SAI1_IRQn
#define SAI_TxIRQHandler SAI1_IRQHandler
/* Select Audio/Video PLL (786.48 MHz) as sai1 clock source */
#define DEMO_SAI1_CLOCK_SOURCE_SELECT (2U)
/* Clock pre divider for sai1 clock source */
#define DEMO_SAI1_CLOCK_SOURCE_PRE_DIVIDER (1U)
/* Clock divider for sai1 clock source */
#define DEMO_SAI1_CLOCK_SOURCE_DIVIDER (63U)
/* Get frequency of sai1 clock */
#define DEMO_SAI_CLK_FREQ (CLOCK_GetFreq(kCLOCK_AudioPllClk) / (DEMO_SAI1_CLOCK_SOURCE_DIVIDER + 1U) / (DEMO_SAI1_CLOCK_SOURCE_PRE_DIVIDER + 1U))
/* I2C instance and clock */
#define DEMO_I2C LPI2C1
/* Select USB1 PLL (480 MHz) as master lpi2c clock source */
#define DEMO_LPI2C_CLOCK_SOURCE_SELECT (0U)
/* Clock divider for master lpi2c clock source */
#define DEMO_LPI2C_CLOCK_SOURCE_DIVIDER (5U)
/* Get frequency of lpi2c clock */
#define DEMO_I2C_CLK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (DEMO_LPI2C_CLOCK_SOURCE_DIVIDER + 1U))
/* DMA */
#define DMAMUX0 DMAMUX
#define EXAMPLE_DMA DMA0
#define EXAMPLE_CHANNEL (0U)
#define EXAMPLE_SAI_TX_SOURCE kDmaRequestMuxSai1Tx
struct imxcodec
{
I2S_Type *sai;
sai_edma_handle_t txHandle;
wm8960_handle_t codecHandle;
edma_handle_t dmaHandle;
lpi2c_master_handle_t i2cHandle;
sai_transfer_format_t format;
};
static void _InitPins(void)
{
CLOCK_EnableClock(kCLOCK_Iomuxc);
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_00_LPI2C1_SCL, 1);
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_01_LPI2C1_SDA, 1);
IOMUXC_SetPinConfig( IOMUXC_GPIO_AD_B1_00_LPI2C1_SCL, 0xD8B0u);
IOMUXC_SetPinConfig( IOMUXC_GPIO_AD_B1_01_LPI2C1_SDA, 0xD8B0u);
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_09_SAI1_MCLK, 1U);
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_13_SAI1_TX_DATA00, 1U);
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_14_SAI1_TX_BCLK, 1U);
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_15_SAI1_TX_SYNC, 1U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_09_SAI1_MCLK, 0x10B0u);
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_13_SAI1_TX_DATA00, 0x10B0u);
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_14_SAI1_TX_BCLK, 0x10B0u);
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_15_SAI1_TX_SYNC, 0x10B0u);
}
static void BOARD_EnableSaiMclkOutput(bool enable)
{
if (enable)
{
IOMUXC_GPR->GPR1 |= IOMUXC_GPR_GPR1_SAI1_MCLK_DIR_MASK;
}
else
{
IOMUXC_GPR->GPR1 &= (~IOMUXC_GPR_GPR1_SAI1_MCLK_DIR_MASK);
}
}
static void saidma_callback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData)
{
int ind = 0;
rt_uint8_t *saddr;
ind = handle->queueDriver;
saddr = (rt_uint8_t*)handle->saiQueue[ind].data;
rt_audio_tx_complete(userData, saddr);
}
/*********************************************************************************************************
** Audio device
*********************************************************************************************************/
static rt_err_t icodec_getcaps(struct rt_audio_device *audio,struct rt_audio_caps *caps)
{
rt_err_t result = RT_EOK;
struct imxcodec *icodec = (struct imxcodec *)audio->parent.user_data;
switch (caps->main_type)
{
case AUDIO_TYPE_QUERY: /* qurey the types of hw_codec device */
{
switch (caps->sub_type)
{
case AUDIO_TYPE_QUERY:
caps->udata.mask = AUDIO_TYPE_OUTPUT | AUDIO_TYPE_MIXER;
break;
default:
result = -RT_ERROR;
break;
}
break;
}
case AUDIO_TYPE_OUTPUT: /* Provide capabilities of OUTPUT unit */
switch (caps->sub_type)
{
case AUDIO_DSP_PARAM:
if (audio->replay == NULL)
{
result = -RT_ERROR;
break;
}
caps->udata.config.channels = 1;
caps->udata.config.samplefmt = 1;
caps->udata.config.samplerate = 1;
caps->udata.config.samplefmts = 1;
break;
default:
result = -RT_ERROR;
break;
}
break;
case AUDIO_TYPE_MIXER: /* report the Mixer Units */
switch (caps->sub_type)
{
case AUDIO_MIXER_QUERY:
caps->udata.mask = AUDIO_MIXER_VOLUME | AUDIO_MIXER_DIGITAL | AUDIO_MIXER_LINE;
break;
case AUDIO_MIXER_VOLUME:
caps->udata.value = WM8960_GetVolume(&icodec->codecHandle, kWM8960_ModuleDAC);
break;
case AUDIO_MIXER_DIGITAL:
break;
case AUDIO_MIXER_LINE:
break;
default:
result = -RT_ERROR;
break;
}
break;
default:
result = -RT_ERROR;
break;
}
return result;
}
static rt_err_t icodec_configure(struct rt_audio_device *audio,struct rt_audio_caps *caps)
{
rt_err_t result = RT_EOK;
struct imxcodec *icodec = (struct imxcodec *)audio->parent.user_data;
switch (caps->main_type)
{
case AUDIO_TYPE_MIXER:
{
switch (caps->sub_type)
{
case AUDIO_MIXER_VOLUME:
{
WM8960_SetVolume(&icodec->codecHandle, kWM8960_ModuleDAC,
caps->udata.value);
}
break;
default:
{
result = -RT_ERROR;
}
break;
}
}
break;
case AUDIO_TYPE_OUTPUT:
{
switch (caps->sub_type)
{
case AUDIO_DSP_PARAM:
{
} break;
case AUDIO_DSP_SAMPLERATE:
{
int rate = caps->udata.value;
icodec->format.sampleRate_Hz = rate;
SAI_TxSetFormat(icodec->sai, &icodec->format, icodec->format.masterClockHz, icodec->format.masterClockHz);
}
break;
default:
{
result = -RT_ERROR;
}
break;
}
}
break;
default:
result = -RT_ERROR;
break;
}
return result;
}
static rt_err_t icodec_init(struct rt_audio_device *audio)
{
sai_config_t config;
uint32_t mclkSourceClockHz = 0U;
edma_config_t dmaConfig = {0};
lpi2c_master_config_t i2cConfig = {0};
uint32_t i2cSourceClock;
clock_audio_pll_config_t audioPllConfig = {32, 1, 77, 100};
struct imxcodec *icodec = audio->parent.user_data;
sai_transfer_format_t *format;
icodec->sai = DEMO_SAI;
format = &icodec->format;
_InitPins();
CLOCK_InitAudioPll(&audioPllConfig);
/*Clock setting for LPI2C*/
CLOCK_SetMux(kCLOCK_Lpi2cMux, DEMO_LPI2C_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_Lpi2cDiv, DEMO_LPI2C_CLOCK_SOURCE_DIVIDER);
/*Clock setting for SAI1*/
CLOCK_SetMux(kCLOCK_Sai1Mux, DEMO_SAI1_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_Sai1PreDiv, DEMO_SAI1_CLOCK_SOURCE_PRE_DIVIDER);
CLOCK_SetDiv(kCLOCK_Sai1Div, DEMO_SAI1_CLOCK_SOURCE_DIVIDER);
/*Enable MCLK clock*/
BOARD_EnableSaiMclkOutput(true);
/* Create EDMA handle */
EDMA_GetDefaultConfig(&dmaConfig);
EDMA_Init(EXAMPLE_DMA, &dmaConfig);
EDMA_CreateHandle(&icodec->dmaHandle, EXAMPLE_DMA, EXAMPLE_CHANNEL);
DMAMUX_Init(DMAMUX0);
DMAMUX_SetSource(DMAMUX0, EXAMPLE_CHANNEL, EXAMPLE_SAI_TX_SOURCE);
DMAMUX_EnableChannel(DMAMUX0, EXAMPLE_CHANNEL);
/* Init SAI module */
SAI_TxGetDefaultConfig(&config);
SAI_TxInit(DEMO_SAI, &config);
/* Configure the audio format */
format->bitWidth = kSAI_WordWidth16bits;
format->channel = 0U;
format->sampleRate_Hz = kSAI_SampleRate48KHz;
format->masterClockHz = DEMO_SAI_CLK_FREQ;
format->protocol = config.protocol;
format->stereo = kSAI_Stereo;
format->isFrameSyncCompact = 0;
format->watermark = FSL_FEATURE_SAI_FIFO_COUNT / 2U;
/* Configure Sgtl5000 I2C */
icodec->codecHandle.base = DEMO_I2C;
icodec->codecHandle.i2cHandle = &icodec->i2cHandle;
i2cSourceClock = DEMO_I2C_CLK_FREQ;
LPI2C_MasterGetDefaultConfig(&i2cConfig);
LPI2C_MasterInit(DEMO_I2C, &i2cConfig, i2cSourceClock);
LPI2C_MasterTransferCreateHandle(DEMO_I2C, &icodec->i2cHandle, NULL, NULL);
WM8960_Init(&icodec->codecHandle, NULL);
WM8960_ConfigDataFormat(&icodec->codecHandle, format->masterClockHz, format->sampleRate_Hz, format->bitWidth);
SAI_TransferTxCreateHandleEDMA(icodec->sai, &icodec->txHandle, saidma_callback, audio, &icodec->dmaHandle);
mclkSourceClockHz = DEMO_SAI_CLK_FREQ;
SAI_TransferTxSetFormatEDMA(icodec->sai, &icodec->txHandle, format, mclkSourceClockHz, format->masterClockHz);
return RT_EOK;
}
static rt_err_t icodec_shutdown(struct rt_audio_device *audio)
{
return RT_EOK;
}
rt_err_t icodec_start(struct rt_audio_device *audio,int stream)
{
return RT_EOK;
}
rt_err_t icodec_stop(struct rt_audio_device *audio,int stream)
{
return RT_EOK;
}
static rt_err_t icodec_suspend(struct rt_audio_device *audio,int stream)
{
return RT_EOK;
}
static rt_err_t icodec_resume(struct rt_audio_device *audio,int stream)
{
return RT_EOK;
}
static rt_err_t icodec_control (struct rt_audio_device *audio, int cmd, void *args)
{
rt_err_t result = RT_EOK;
switch (cmd)
{
case AUDIO_CTL_HWRESET:
break;
default:
result = -RT_ERROR;
break;
}
return result;
}
static rt_size_t icodec_transmit(struct rt_audio_device *audio, const void *writeBuf, void *readBuf, rt_size_t size)
{
struct imxcodec *icodec = (struct imxcodec *)audio->parent.user_data;
if(writeBuf != RT_NULL)
{
sai_transfer_t xfer;
xfer.data = (uint8_t *)writeBuf;
xfer.dataSize = size;
SAI_TransferSendEDMA(icodec->sai, &icodec->txHandle, &xfer);
return size;
}
return 0;
}
static struct imxcodec _g_imxcodec;
static struct rt_audio_device _g_audio_device;
const struct rt_audio_ops _g_audio_ops =
{
.getcaps = icodec_getcaps,
.configure = icodec_configure,
.init = icodec_init,
.shutdown = icodec_shutdown,
.start = icodec_start,
.stop = icodec_stop,
.suspend = icodec_suspend,
.resume = icodec_resume,
.control = icodec_control,
.transmit = icodec_transmit,
};
int rt_hw_codec_init(void)
{
int result;
struct rt_audio_device *audio = &_g_audio_device;
audio->ops = (struct rt_audio_ops*)&_g_audio_ops;
_g_imxcodec.sai = DEMO_SAI;
result = rt_audio_register(audio,"sound0", RT_DEVICE_FLAG_WRONLY, &_g_imxcodec);
return result;
}
INIT_DEVICE_EXPORT(rt_hw_codec_init);
#ifndef __DRV_CODEC_H__
#define __DRV_CODEC_H__
#define SUNXI_DAC_DPC 0x00
#define SUNXI_DAC_FIFOC 0x04
#define SUNXI_DAC_FIFOS 0x08
#define SUNXI_DAC_TXDATA 0x0c
#define SUNXI_ADC_FIFOC 0x10
#define SUNXI_ADC_FIFOS 0x14
#define SUNXI_ADC_RXDATA 0x18
#define DAC_MIXER_CTRL 0x20
#define ADC_MIXER_CTRL 0x24
#define ADDA_TUNE 0x28
#define BIAS_DA16_CAL_CTRL0 0x2C
#define BIAS_DA16_CAL_CTRL1 0x34
#define SUNXI_DAC_CNT 0x40
#define SUNXI_ADC_CNT 0x44
#define SUNXI_DAC_DG 0x48
#define SUNXI_ADC_DG 0x4c
#define AC_PR_CFG 0x400
/*AC_DAC_DPC:0x00*/
#define EN_DAC 31
#define MODQU 25
#define DWA 24
#define HPF_EN 18
#define DVOL 12
/*#define HUB_EN 0 */
/*AC_DAC_FIFOC:0x04*/
#define DAC_FS 29
#define FIR_VER 28
#define SEND_LASAT 26
#define FIFO_MODE 24
#define DAC_DRQ_CLR_CNT 21
#define TX_TRIG_LEVEL 8
#define ADDA_LOOP_EN 7
#define DAC_MONO_EN 6
#define TX_SAMPLE_BITS 5
#define DAC_DRQ_EN 4
#define DAC_IRQ_EN 3
#define FIFO_UNDERRUN_IRQ_EN 2
#define FIFO_OVERRUN_IRQ_EN 1
#define FIFO_FLUSH 0
/*AC_ADC_FIFOC:0x10*/
#define ADFS 29
#define EN_AD 28
#define RX_FIFO_MODE 24
#define ADCDFEN 16
#define RX_FIFO_TRG_LEVEL 8
#define ADC_MONO_EN 7
#define RX_SAMPLE_BITS 6
#define ADC_DRQ_EN 4
#define ADC_IRQ_EN 3
#define ADC_OVERRUN_IRQ_EN 1
#define ADC_FIFO_FLUSH 0
/*DAC_MIXER_CTRL: 0x20*/
#define DAC_AG_R_EN 31 /* dac right enable bit */
#define DAC_AG_L_EN 30 /* dac left enable bit */
#define R_MIXER_EN 29 /* right output mixer */
#define L_MIXER_EN 28 /* left output mixer */
#define PH_R_MUTE 27 /* headphone right mute */
#define PH_L_MUTE 26 /* headphone left mute */
#define PH_R_PWR_SLT 25
#define PH_L_PWR_SLT 24
#define PH_COM_FC 22
#define PH_COM_PROTEC 21
#define R_MIXER_MUTE_MIC 20
#define R_MIXER_MUTE_LINEIN 19
#define R_MIXER_MUTE_FM 18
#define R_MIXER_MUTE_R_DAC 17
#define R_MIXER_MUTE_L_DAC 16
#define R_MIXER_MUTE 16
#define HP_POWER_EN 15
#define L_MIXER_MUTE_MIC 12
#define L_MIXER_MUTE_LINEIN 11
#define L_MIXER_MUTE_FM 10
#define L_MIXER_MUTE_R_DAC 9
#define L_MIXER_MUTE_L_DAC 8
#define L_MIXER_MUTE 8
#define L_HP_TO_R_HP_MUTE 7
#define R_HP_TO_L_HP_MUTE 6
#define HP_VOL 0
/*ADC_MIXER_CTRL: 0x24*/
#define ADC_EN 31 /* adc enable bit */
/* mic in boost stage to L or R output mixer gain control */
#define MIC_GAIN_CTL 24
#define LINEIN_VOL 21 /* right output mixer */
#define ADC_IN_GAIN_CTL 16 /* adc input gain control */
#define COS_SLOP_TM 14 /* COS slop time control for Anti-pop */
#define ADC_MIX_MUTE_MIC 13
#define ADC_MIX_MUTE_FML 12
#define ADC_MIX_MUTE_FMR 11
#define ADC_MIX_MUTE_LINEIN 10
#define ADC_MIX_MUTE_L 9
#define ADC_MIX_MUTE_R 8
#define ADC_MIX_MUTE 8 /* ADC mixer mute control */
#define PA_SPEED_SLT 7 /* PA speed select->0: normal 1: fast */
#define FM_TO_MIX_GAIN 4 /* FMin to mixer gain control */
#define MIC_BST_AMP_EN 3 /* MIC boost AMP enable */
#define MIC_BOST_GAIN 0 /* MIC boast AMP gain control */
/*AC_ADC_TXDATA:0x20*/
#define TX_DATA 0
/*AC_DAC_CNT:0x40*/
#define TX_CNT 0
/*AC_ADC_CNT:0x44*/
#define RX_CNT 0
/*AC_DAC_DG:0x48*/
/*
* DAC Modulator Debug
* 0:DAC Modulator Normal Mode
* 1:DAC Modulator Debug Mode
*/
#define DAC_MODU_SELECT 11
/*
* DAC Pattern Select
* 00:Normal(Audio sample from TX fifo)
* 01: -6 dB sin wave
* 10: -60 dB sin wave
* 11: silent wave
*/
#define DAC_PATTERN_SELECT 9
/*
* CODEC Clock Source Select
* 0:codec clock from PLL
* 1:codec clock from OSC(for debug)
*/
#define CODEC_CLK_SELECT 8
/*
* DAC output channel swap enable
* 0:disable
* 1:enable
*/
#define DA_SWP 6
/*AC_ADC_DG:0x4c*/
#define AD_SWP 24
/*AC_PR_CFG:0x400*/
#define AC_PR_RST 28
#define AC_PR_RW 24
#define AC_PR_ADDR 16
#define ADDA_PR_WDAT 8
#define ADDA_PR_RDAT 0
/* 时钟配置相关寄存器 */
#define R6_REG_CCU_BASE 0x01c20000
#define R6_REG_PLL_AUDIO_CTRL (R6_REG_CCU_BASE + 0x008)
#define R6_REG_BUS_CLK_GATING_0 (R6_REG_CCU_BASE + 0x060)
#define R6_REG_BUS_CLK_GATING_1 (R6_REG_CCU_BASE + 0x064)
#define R6_REG_BUS_CLK_GATING_2 (R6_REG_CCU_BASE + 0x068)
#define R6_REG_AUDIO_CODEC_CLK (R6_REG_CCU_BASE + 0x140)
#define R6_REG_BUS_SOFT_RST_0 (R6_REG_CCU_BASE + 0x02C0)
#define R6_REG_BUS_SOFT_RST_1 (R6_REG_CCU_BASE + 0x02C4)
#define R6_REG_BUS_SOFT_RST_2 (R6_REG_CCU_BASE + 0x02D0)
/* GPIO配置相关寄存器 */
#define R6_REG_PIO_BASE 0x01c20800
#define R6_REG_PD_CFG0 (R6_REG_PIO_BASE + (3 * 0x24 + 0X00))
#define R6_REG_PD_CFG1 (R6_REG_PIO_BASE + (3 * 0x24 + 0X04))
#define R6_REG_PD_CFG2 (R6_REG_PIO_BASE + (3 * 0x24 + 0X08))
#define R6_REG_PD_CFG3 (R6_REG_PIO_BASE + (3 * 0x24 + 0X0c))
#define R6_REG_PD_DATA (R6_REG_PIO_BASE + (3 * 0x24 + 0X10))
#define R6_REG_PD_DRV0 (R6_REG_PIO_BASE + (3 * 0x24 + 0X14))
#define R6_REG_PD_DRV1 (R6_REG_PIO_BASE + (3 * 0x24 + 0X18))
#define R6_REG_PD_PUL0 (R6_REG_PIO_BASE + (3 * 0x24 + 0X1c))
#define R6_REG_PD_PUL1 (R6_REG_PIO_BASE + (3 * 0x24 + 0X20))
/* AUDIO配置相关寄存器 */
#define R6_REG_AC_BASE 0x01c23c00
#define R6_REG_AC_DAC_DPC (R6_REG_AC_BASE + 0x00)
#define R6_REG_AC_DAC_FIFOC (R6_REG_AC_BASE + 0x04)
#define R6_REG_AC_DAC_FIFOS (R6_REG_AC_BASE + 0x08)
#define R6_REG_AC_DAC_TXDADA (R6_REG_AC_BASE + 0x0c)
#define R6_REG_AC_ADC_FIFOC (R6_REG_AC_BASE + 0x10)
#define R6_REG_AC_ADC_FIFOS (R6_REG_AC_BASE + 0x14)
#define R6_REG_AC_ADC_RXDADA (R6_REG_AC_BASE + 0x18)
#define R6_REG_DAC_MIXER_CTRL (R6_REG_AC_BASE + 0x20)
#define R6_REG_ADC_MIXER_CTRL (R6_REG_AC_BASE + 0x24)
#define R6_REG_AC_DAC_CNT (R6_REG_AC_BASE + 0x40)
/* DMA配置相关寄存器 */
#define R6_REG_NDMA_0_BASE (0x01c02000 + 0x100 + 0 * 0x20)
#define R6_REG_DMA_INT_CTRL (0x01c02000 + 0x00)
#define R6_REG_DMA_INT_STA (0x01c02000 + 0x04)
#define R6_REG_DMA_PTY_CFG (0x01c02000 + 0x08)
#define REG_NDMA_CFG (0x0)
#define REG_NDMA_SRC_ADR (0x4)
#define REG_NDMA_DES_ADR (0x8)
#define REG_NDMA_BYTE_CNT (0xc)
// #define REG_NDMA_PAR (0x300 + 0x1c)
#define NDMA_CFG_SRC_DRQ_IR_RX (0x00 << 0)
#define NDMA_CFG_SRC_DRQ_NONE (0x01 << 0)
#define NDMA_CFG_SRC_DRQ_SDRAM (0x11 << 0)
#define NDMA_CFG_DST_LINEAR (0x00 << 21)
#define NDMA_CFG_DST_DRQ_IR_RX (0x00 << 16)
#define NDMA_CFG_DST_DRQ_NONE (0x01 << 16)
#define NDMA_CFG_DST_DRQ_SRAM (0x10 << 16)
#define NDMA_CFG_DST_DRQ_SDRAM (0x11 << 16)
#define NDMA_CFG_SRC_DRQ_SRAM (0x10 << 0)
#define NDMA_CFG_SRC_LINEAR (0x00 << 5)
#define NDMA_CFG_SRC_BST4_WIDTH32 ((0x1 << 7) | (0x2 << 8))
#define NDMA_CFG_DST_DRQ_CODEC (0x0c << 16)
#define NDMA_CFG_DST_IO (0x1 << 21)
#define NDMA_CFG_DST_BST4_WIDTH32 ((0x1 << 23) | (0x2 << 24))
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
此差异已折叠。
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of the copyright holder 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 HOLDER 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 _FSL_WM8960_H_
#define _FSL_WM8960_H_
#include "fsl_common.h"
#if defined(FSL_FEATURE_SOC_LPI2C_COUNT) && (FSL_FEATURE_SOC_LPI2C_COUNT)
#include "fsl_lpi2c.h"
#else
#include "fsl_i2c.h"
#endif
/*!
* @addtogroup wm8960
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Define the register address of WM8960. */
#define WM8960_LINVOL 0x0
#define WM8960_RINVOL 0x1
#define WM8960_LOUT1 0x2
#define WM8960_ROUT1 0x3
#define WM8960_CLOCK1 0x4
#define WM8960_DACCTL1 0x5
#define WM8960_DACCTL2 0x6
#define WM8960_IFACE1 0x7
#define WM8960_CLOCK2 0x8
#define WM8960_IFACE2 0x9
#define WM8960_LDAC 0xa
#define WM8960_RDAC 0xb
#define WM8960_RESET 0xf
#define WM8960_3D 0x10
#define WM8960_ALC1 0x11
#define WM8960_ALC2 0x12
#define WM8960_ALC3 0x13
#define WM8960_NOISEG 0x14
#define WM8960_LADC 0x15
#define WM8960_RADC 0x16
#define WM8960_ADDCTL1 0x17
#define WM8960_ADDCTL2 0x18
#define WM8960_POWER1 0x19
#define WM8960_POWER2 0x1a
#define WM8960_ADDCTL3 0x1b
#define WM8960_APOP1 0x1c
#define WM8960_APOP2 0x1d
#define WM8960_LINPATH 0x20
#define WM8960_RINPATH 0x21
#define WM8960_LOUTMIX 0x22
#define WM8960_ROUTMIX 0x25
#define WM8960_MONOMIX1 0x26
#define WM8960_MONOMIX2 0x27
#define WM8960_LOUT2 0x28
#define WM8960_ROUT2 0x29
#define WM8960_MONO 0x2a
#define WM8960_INBMIX1 0x2b
#define WM8960_INBMIX2 0x2c
#define WM8960_BYPASS1 0x2d
#define WM8960_BYPASS2 0x2e
#define WM8960_POWER3 0x2f
#define WM8960_ADDCTL4 0x30
#define WM8960_CLASSD1 0x31
#define WM8960_CLASSD3 0x33
#define WM8960_PLL1 0x34
#define WM8960_PLL2 0x35
#define WM8960_PLL3 0x36
#define WM8960_PLL4 0x37
/*! @brief Cache register number */
#define WM8960_CACHEREGNUM 56
/*! @brief WM8960_IFACE1 FORMAT bits */
#define WM8960_IFACE1_FORMAT_MASK 0x03
#define WM8960_IFACE1_FORMAT_SHIFT 0x00
#define WM8960_IFACE1_FORMAT_RJ 0x00
#define WM8960_IFACE1_FORMAT_LJ 0x01
#define WM8960_IFACE1_FORMAT_I2S 0x02
#define WM8960_IFACE1_FORMAT_DSP 0x03
#define WM8960_IFACE1_FORMAT(x) ((x << WM8960_IFACE1_FORMAT_SHIFT) & WM8960_IFACE1_FORMAT_MASK)
/*! @brief WM8960_IFACE1 WL bits */
#define WM8960_IFACE1_WL_MASK 0x0C
#define WM8960_IFACE1_WL_SHIFT 0x02
#define WM8960_IFACE1_WL_16BITS 0x00
#define WM8960_IFACE1_WL_20BITS 0x01
#define WM8960_IFACE1_WL_24BITS 0x02
#define WM8960_IFACE1_WL_32BITS 0x03
#define WM8960_IFACE1_WL(x) ((x << WM8960_IFACE1_WL_SHIFT) & WM8960_IFACE1_WL_MASK)
/*! @brief WM8960_IFACE1 LRP bit */
#define WM8960_IFACE1_LRP_MASK 0x10
#define WM8960_IFACE1_LRP_SHIFT 0x04
#define WM8960_IFACE1_LRCLK_NORMAL_POL 0x00
#define WM8960_IFACE1_LRCLK_INVERT_POL 0x01
#define WM8960_IFACE1_DSP_MODEA 0x00
#define WM8960_IFACE1_DSP_MODEB 0x01
#define WM8960_IFACE1_LRP(x) ((x << WM8960_IFACE1_LRP_SHIFT) & WM8960_IFACE1_LRP_MASK)
/*! @brief WM8960_IFACE1 DLRSWAP bit */
#define WM8960_IFACE1_DLRSWAP_MASK 0x20
#define WM8960_IFACE1_DLRSWAP_SHIFT 0x05
#define WM8960_IFACE1_DACCH_NORMAL 0x00
#define WM8960_IFACE1_DACCH_SWAP 0x01
#define WM8960_IFACE1_DLRSWAP(x) ((x << WM8960_IFACE1_DLRSWAP_SHIFT) & WM8960_IFACE1_DLRSWAP_MASK)
/*! @brief WM8960_IFACE1 MS bit */
#define WM8960_IFACE1_MS_MASK 0x40
#define WM8960_IFACE1_MS_SHIFT 0x06
#define WM8960_IFACE1_SLAVE 0x00
#define WM8960_IFACE1_MASTER 0x01
#define WM8960_IFACE1_MS(x) ((x << WM8960_IFACE1_MS_SHIFT) & WM8960_IFACE1_MS_MASK)
/*! @brief WM8960_IFACE1 BCLKINV bit */
#define WM8960_IFACE1_BCLKINV_MASK 0x80
#define WM8960_IFACE1_BCLKINV_SHIFT 0x07
#define WM8960_IFACE1_BCLK_NONINVERT 0x00
#define WM8960_IFACE1_BCLK_INVERT 0x01
#define WM8960_IFACE1_BCLKINV(x) ((x << WM8960_IFACE1_BCLKINV_SHIFT) & WM8960_IFACE1_BCLKINV_MASK)
/*! @brief WM8960_IFACE1 ALRSWAP bit */
#define WM8960_IFACE1_ALRSWAP_MASK 0x100
#define WM8960_IFACE1_ALRSWAP_SHIFT 0x08
#define WM8960_IFACE1_ADCCH_NORMAL 0x00
#define WM8960_IFACE1_ADCCH_SWAP 0x01
#define WM8960_IFACE1_ALRSWAP(x) ((x << WM8960_IFACE1_ALRSWAP_SHIFT) & WM8960_IFACE1_ALRSWAP_MASK)
/*! @brief WM8960_POWER1 */
#define WM8960_POWER1_VREF_MASK 0x40
#define WM8960_POWER1_VREF_SHIFT 0x06
#define WM8960_POWER1_AINL_MASK 0x20
#define WM8960_POWER1_AINL_SHIFT 0x05
#define WM8960_POWER1_AINR_MASK 0x10
#define WM8960_POWER1_AINR_SHIFT 0x04
#define WM8960_POWER1_ADCL_MASK 0x08
#define WM8960_POWER1_ADCL_SHIFT 0x03
#define WM8960_POWER1_ADCR_MASK 0x04
#define WM8960_POWER1_ADCR_SHIFT 0x02
/*! @brief WM8960_POWER2 */
#define WM8960_POWER2_DACL_MASK 0x100
#define WM8960_POWER2_DACL_SHIFT 0x08
#define WM8960_POWER2_DACR_MASK 0x80
#define WM8960_POWER2_DACR_SHIFT 0x07
#define WM8960_POWER2_LOUT1_MASK 0x40
#define WM8960_POWER2_LOUT1_SHIFT 0x06
#define WM8960_POWER2_ROUT1_MASK 0x20
#define WM8960_POWER2_ROUT1_SHIFT 0x05
#define WM8960_POWER2_SPKL_MASK 0x10
#define WM8960_POWER2_SPKL_SHIFT 0x04
#define WM8960_POWER2_SPKR_MASK 0x08
#define WM8960_POWER2_SPKR_SHIFT 0x03
/*! @brief WM8960 I2C address. */
#define WM8960_I2C_ADDR 0x1A
/*! @brief Modules in WM8960 board. */
typedef enum _WM8960_module
{
kWM8960_ModuleADC = 0x0, /*!< ADC module in WM8960 */
kWM8960_ModuleDAC = 0x1, /*!< DAC module in WM8960 */
kWM8960_ModuleVREF = 0x2, /*!< VREF module */
kWM8960_ModuleHP = 0x03, /*!< Headphone module */
kWM8960_ModuleLineIn = 0x6, /*!< Line-in module */
kWM8960_ModuleLineOut = 0x7, /*!< Line out module */
kWM8960_ModuleSpeaker = 0x8 /*!< Speaker module */
} wm8960_module_t;
/*!
* @brief WM8960 data route.
* Only provide some typical data route, not all route listed.
* Note: Users cannot combine any routes, once a new route is set, the previous one would be replaced.
*/
typedef enum _wm8960_route
{
kWM8960_RouteBypass = 0x0, /*!< LINEIN->Headphone. */
kWM8960_RoutePlayback = 0x1, /*!< I2SIN->DAC->Headphone. */
kWM8960_RoutePlaybackandRecord = 0x2, /*!< I2SIN->DAC->Headphone, LINEIN->ADC->I2SOUT. */
kWM8960_RoutePlaybackwithDAP = 0x3, /*!< I2SIN->DAP->DAC->Headphone. */
kWM8960_RoutePlaybackwithDAPandRecord = 0x4, /*!< I2SIN->DAP->DAC->HP, LINEIN->ADC->I2SOUT. */
kWM8960_RouteRecord = 0x5 /*!< LINEIN->ADC->I2SOUT. */
} wm8960_route_t;
/*!
* @brief The audio data transfer protocol choice.
* WM8960 only supports I2S format and PCM format.
*/
typedef enum _wm8960_protocol
{
kWM8960_BusI2S = 0x0, /*!< I2S type */
kWM8960_BusLeftJustified = 0x1, /*!< Left justified mode */
kWM8960_BusRightJustified = 0x2, /*!< Right justified mode */
kWM8960_BusPCMA = 0x3, /*!< PCM A mode */
kWM8960_BusPCMB = 0x4 /*!< PCM B mode */
} wm8960_protocol_t;
/*! @brief WM8960 configure definition. */
typedef struct wm8960_handle
{
#if defined(FSL_FEATURE_SOC_LPI2C_COUNT) && (FSL_FEATURE_SOC_LPI2C_COUNT)
LPI2C_Type *base;
lpi2c_master_transfer_t xfer;
lpi2c_master_handle_t *i2cHandle;
#else
/* I2C relevant definition. */
I2C_Type *base; /*!< I2C instance. */
i2c_master_transfer_t xfer; /*!< I2C device setting */
i2c_master_handle_t *i2cHandle; /*!< I2C internal state space. */
#endif
} wm8960_handle_t;
/*! @brief Initialize structure of WM8960 */
typedef struct wm8960_config
{
wm8960_route_t route; /*!< Audio data route.*/
wm8960_protocol_t bus; /*!< Audio transfer protocol */
bool master_slave; /*!< Master or slave. */
} wm8960_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief WM8960 initialize function.
*
* The second parameter is NULL to WM8960 in this version. If users want
* to change the settings, they have to use wm8960_write_reg() or wm8960_modify_reg()
* to set the register value of WM8960.
* Note: If the codec_config is NULL, it would initialize WM8960 using default settings.
* The default setting:
* codec_config->route = kWM8960_RoutePlaybackandRecord
* codec_config->bus = kWM8960_BusI2S
* codec_config->master = slave
*
* @param handle WM8960 handle structure.
* @param codec_config WM8960 configuration structure.
*/
void WM8960_Init(wm8960_handle_t *handle, wm8960_config_t *config);
/*!
* @brief Deinit the WM8960 codec.
*
* This function close all modules in WM8960 to save power.
*
* @param handle WM8960 handle structure pointer.
*/
void WM8960_Deinit(wm8960_handle_t *handle);
/*!
* @brief Set audio data route in WM8960.
*
* This function would set the data route according to route. The route cannot be combined,
* as all route would enable different modules.
* Note: If a new route is set, the previous route would not work.
*
* @param handle WM8960 handle structure.
* @param route Audio data route in WM8960.
*/
status_t WM8960_SetDataRoute(wm8960_handle_t *handle, wm8960_route_t route);
/*!
* @brief Set the audio transfer protocol.
*
* WM8960 only supports I2S, left justified, right justified, PCM A, PCM B format.
*
* @param handle WM8960 handle structure.
* @param bus Audio data transfer protocol.
*/
status_t WM8960_SetProtocol(wm8960_handle_t *handle, wm8960_protocol_t protocol);
/*!
* @brief Set WM8960 as master or slave.
*
* @param handle WM8960 handle structure.
* @param master 1 represent master, 0 represent slave.
*/
void WM8960_SetMasterSlave(wm8960_handle_t *handle, bool master);
/*!
* @brief Set the volume of different modules in WM8960.
*
* This function would set the volume of WM8960 modules. Uses need to appoint the module.
* The function assume that left channel and right channel has the same volume.
*
* @param handle WM8960 handle structure.
* @param module Module to set volume, it can be ADC, DAC, Headphone and so on.
* @param volume Volume value need to be set.
*/
status_t WM8960_SetVolume(wm8960_handle_t *handle, wm8960_module_t module, uint32_t volume);
/*!
* @brief Get the volume of different modules in WM8960.
*
* This function gets the volume of WM8960 modules. Uses need to appoint the module.
* The function assume that left channel and right channel has the same volume.
*
* @param handle WM8960 handle structure.
* @param module Module to set volume, it can be ADC, DAC, Headphone and so on.
* @return Volume value of the module.
*/
uint32_t WM8960_GetVolume(wm8960_handle_t *handle, wm8960_module_t module);
/*!
* @brief Mute modules in WM8960.
*
* @param handle WM8960 handle structure.
* @param module Modules need to be mute.
* @param isEnabled Mute or unmute, 1 represent mute.
*/
status_t WM8960_SetMute(wm8960_handle_t *handle, wm8960_module_t module, bool isEnabled);
/*!
* @brief Enable/disable expected devices.
*
* @param handle WM8960 handle structure.
* @param module Module expected to enable.
* @param isEnabled Enable or disable moudles.
*/
status_t WM8960_SetModule(wm8960_handle_t *handle, wm8960_module_t module, bool isEnabled);
/*!
* @brief Configure the data format of audio data.
*
* This function would configure the registers about the sample rate, bit depths.
*
* @param handle WM8960 handle structure pointer.
* @param mclk Master clock frequency of I2S.
* @param sample_rate Sample rate of audio file running in WM8960. WM8960 now
* supports 8k, 11.025k, 12k, 16k, 22.05k, 24k, 32k, 44.1k, 48k and 96k sample rate.
* @param bits Bit depth of audio file (WM8960 only supports 16bit, 20bit, 24bit
* and 32 bit in HW).
*/
status_t WM8960_ConfigDataFormat(wm8960_handle_t *handle, uint32_t mclk, uint32_t sample_rate, uint8_t bits);
/*!
* @brief Enable/disable jack detect feature.
*
* @param handle WM8960 handle structure.
* @param isEnabled Enable or disable moudles.
*/
status_t WM8960_SetJackDetect(wm8960_handle_t *handle, bool isEnabled);
/*!
* @brief Write register to WM8960 using I2C.
*
* @param handle WM8960 handle structure.
* @param reg The register address in WM8960.
* @param val Value needs to write into the register.
*/
status_t WM8960_WriteReg(wm8960_handle_t *handle, uint8_t reg, uint16_t val);
/*!
* @brief Read register from WM8960 using I2C.
* @param handle WM8960 handle structure.
* @param reg The register address in WM8960.
* @param val Value written to.
*/
status_t WM8960_ReadReg(uint8_t reg, uint16_t *val);
/*!
* @brief Modify some bits in the register using I2C.
* @param handle WM8960 handle structure.
* @param reg The register address in WM8960.
* @param mask The mask code for the bits want to write. The bit you want to write should be 0.
* @param val Value needs to write into the register.
*/
status_t WM8960_ModifyReg(wm8960_handle_t *handle, uint8_t reg, uint16_t mask, uint16_t val);
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_WM8960_H_ */
/*******************************************************************************
* API
******************************************************************************/
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册