Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2345VOR
rt-thread
提交
e0314e63
R
rt-thread
项目概览
2345VOR
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rt-thread
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e0314e63
编写于
3月 28, 2018
作者:
X
xx
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
添加iis驱动
上级
5e477ae0
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
1669 addition
and
4 deletion
+1669
-4
bsp/imxrt1052-evk/SConstruct
bsp/imxrt1052-evk/SConstruct
+4
-4
bsp/imxrt1052-evk/drivers/SConscript
bsp/imxrt1052-evk/drivers/SConscript
+3
-0
bsp/imxrt1052-evk/drivers/drv_codec.c
bsp/imxrt1052-evk/drivers/drv_codec.c
+387
-0
bsp/imxrt1052-evk/drivers/drv_codec.h
bsp/imxrt1052-evk/drivers/drv_codec.h
+228
-0
bsp/imxrt1052-evk/drivers/fsl_wm8960.c
bsp/imxrt1052-evk/drivers/fsl_wm8960.c
+621
-0
bsp/imxrt1052-evk/drivers/fsl_wm8960.h
bsp/imxrt1052-evk/drivers/fsl_wm8960.h
+426
-0
未找到文件。
bsp/imxrt1052-evk/SConstruct
浏览文件 @
e0314e63
...
...
@@ -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
*
...
...
bsp/imxrt1052-evk/drivers/SConscript
浏览文件 @
e0314e63
...
...
@@ -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'
)
bsp/imxrt1052-evk/drivers/drv_codec.c
0 → 100644
浏览文件 @
e0314e63
#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
);
bsp/imxrt1052-evk/drivers/drv_codec.h
0 → 100644
浏览文件 @
e0314e63
#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
bsp/imxrt1052-evk/drivers/fsl_wm8960.c
0 → 100644
浏览文件 @
e0314e63
/*
* Copyright (c) 2016, 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.
*/
#include "fsl_wm8960.h"
#include "fsl_common.h"
/*******************************************************************************
* Definitations
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*
* wm8960 register cache
* We can't read the WM8960 register space when we are
* using 2 wire for device control, so we cache them instead.
*/
static
const
uint16_t
wm8960_reg
[
WM8960_CACHEREGNUM
]
=
{
0x0097
,
0x0097
,
0x0000
,
0x0000
,
0x0000
,
0x0008
,
0x0000
,
0x000a
,
0x01c0
,
0x0000
,
0x00ff
,
0x00ff
,
0x0000
,
0x0000
,
0x0000
,
0x0000
,
0x0000
,
0x007b
,
0x0100
,
0x0032
,
0x0000
,
0x00c3
,
0x00c3
,
0x01c0
,
0x0000
,
0x0000
,
0x0000
,
0x0000
,
0x0000
,
0x0000
,
0x0000
,
0x0000
,
0x0100
,
0x0100
,
0x0050
,
0x0050
,
0x0050
,
0x0050
,
0x0000
,
0x0000
,
0x0000
,
0x0000
,
0x0040
,
0x0000
,
0x0000
,
0x0050
,
0x0050
,
0x0000
,
0x0002
,
0x0037
,
0x004d
,
0x0080
,
0x0008
,
0x0031
,
0x0026
,
0x00e9
,
};
static
uint16_t
reg_cache
[
WM8960_CACHEREGNUM
];
/*******************************************************************************
* Code
******************************************************************************/
void
WM8960_Init
(
wm8960_handle_t
*
handle
,
wm8960_config_t
*
config
)
{
uint32_t
i
=
4000000
;
memcpy
(
reg_cache
,
wm8960_reg
,
sizeof
(
wm8960_reg
));
/* Set WM8960 I2C address */
handle
->
xfer
.
slaveAddress
=
WM8960_I2C_ADDR
;
/* NULL pointer means default setting. */
if
(
config
==
NULL
)
{
/*
* Reset all registers
*/
WM8960_WriteReg
(
handle
,
WM8960_RESET
,
0x00
);
WM8960_WriteReg
(
handle
,
WM8960_IFACE2
,
0x40
);
/*
* VMID=50K, Enable VREF, AINL, AINR, ADCL and ADCR
* I2S_IN (bit 0), I2S_OUT (bit 1), DAP (bit 4), DAC (bit 5), ADC (bit 6) are powered on
*/
WM8960_WriteReg
(
handle
,
WM8960_POWER1
,
0xCA
);
/*
* Enable DACL, DACR, LOUT1, ROUT1, PLL down
*/
WM8960_WriteReg
(
handle
,
WM8960_POWER2
,
0x1E0
);
/*
* Enable left and right channel input PGA, left and right output mixer
*/
WM8960_WriteReg
(
handle
,
WM8960_POWER3
,
0xC
);
/* Configure SYS_FS clock to 44.1kHz, MCLK_FREQ to 256*Fs, SYSCLK derived from MCLK input */
WM8960_WriteReg
(
handle
,
WM8960_CLOCK1
,
0x00
);
/*
* Audio data length = 32bit, Left justified data format
*/
WM8960_WriteReg
(
handle
,
WM8960_IFACE1
,
0x0D
);
/*
* LMICBOOST = 0dB, Connect left and right PGA to left and right Input Boost Mixer
*/
WM8960_WriteReg
(
handle
,
WM8960_LINPATH
,
0x18
);
WM8960_WriteReg
(
handle
,
WM8960_RINPATH
,
0x18
);
/*
* Left and right input boost, LIN3BOOST and RIN3BOOST = 0dB
*/
WM8960_WriteReg
(
handle
,
WM8960_INBMIX1
,
0x70
);
WM8960_WriteReg
(
handle
,
WM8960_INBMIX2
,
0x70
);
/*
* Left DAC and LINPUT3 to left output mixer, LINPUT3 left output mixer volume = 0dB
*/
WM8960_WriteReg
(
handle
,
WM8960_LOUTMIX
,
0x100
);
/*
* Right DAC and RINPUT3 to right output mixer, RINPUT3 right output mixer volume = 0dB
*/
WM8960_WriteReg
(
handle
,
WM8960_ROUTMIX
,
0x100
);
WM8960_WriteReg
(
handle
,
WM8960_BYPASS1
,
0x0
);
WM8960_WriteReg
(
handle
,
WM8960_BYPASS2
,
0x0
);
WM8960_WriteReg
(
handle
,
WM8960_MONOMIX1
,
0x00
);
WM8960_WriteReg
(
handle
,
WM8960_MONOMIX2
,
0x00
);
}
else
{
WM8960_SetDataRoute
(
handle
,
config
->
route
);
WM8960_SetProtocol
(
handle
,
config
->
bus
);
WM8960_SetMasterSlave
(
handle
,
config
->
master_slave
);
}
WM8960_WriteReg
(
handle
,
WM8960_ADDCTL1
,
0x0C4
);
WM8960_WriteReg
(
handle
,
WM8960_ADDCTL4
,
0x40
);
/*
* ADC volume, 0dB
*/
WM8960_WriteReg
(
handle
,
WM8960_LADC
,
0x1F3
);
WM8960_WriteReg
(
handle
,
WM8960_RADC
,
0x1F3
);
/*
* Digital DAC volume, 0dB
*/
WM8960_WriteReg
(
handle
,
WM8960_LDAC
,
0x1E0
);
WM8960_WriteReg
(
handle
,
WM8960_RDAC
,
0x1E0
);
/*
* Headphone volume, LOUT1 and ROUT1, 0dB
*/
WM8960_WriteReg
(
handle
,
WM8960_LOUT1
,
0x16F
);
WM8960_WriteReg
(
handle
,
WM8960_ROUT1
,
0x16F
);
/* Delay for some while */
while
(
i
)
{
__ASM
(
"nop"
);
i
--
;
}
/* Unmute DAC. */
WM8960_WriteReg
(
handle
,
WM8960_DACCTL1
,
0x0000
);
}
void
WM8960_Deinit
(
wm8960_handle_t
*
handle
)
{
WM8960_SetModule
(
handle
,
kWM8960_ModuleADC
,
false
);
WM8960_SetModule
(
handle
,
kWM8960_ModuleDAC
,
false
);
WM8960_SetModule
(
handle
,
kWM8960_ModuleVREF
,
false
);
WM8960_SetModule
(
handle
,
kWM8960_ModuleLineIn
,
false
);
WM8960_SetModule
(
handle
,
kWM8960_ModuleLineOut
,
false
);
WM8960_SetModule
(
handle
,
kWM8960_ModuleSpeaker
,
false
);
}
void
WM8960_SetMasterSlave
(
wm8960_handle_t
*
handle
,
bool
master
)
{
if
(
master
==
1
)
{
WM8960_ModifyReg
(
handle
,
WM8960_IFACE1
,
WM8960_IFACE1_MS_MASK
,
WM8960_IFACE1_MS
(
WM8960_IFACE1_MASTER
));
}
else
{
WM8960_ModifyReg
(
handle
,
WM8960_IFACE1
,
WM8960_IFACE1_MS_MASK
,
WM8960_IFACE1_MS
(
WM8960_IFACE1_SLAVE
));
}
}
status_t
WM8960_SetModule
(
wm8960_handle_t
*
handle
,
wm8960_module_t
module
,
bool
isEnabled
)
{
status_t
ret
=
kStatus_Success
;
switch
(
module
)
{
case
kWM8960_ModuleADC
:
WM8960_ModifyReg
(
handle
,
WM8960_POWER1
,
WM8960_POWER1_ADCL_MASK
,
((
uint16_t
)
isEnabled
<<
WM8960_POWER1_ADCL_SHIFT
));
WM8960_ModifyReg
(
handle
,
WM8960_POWER1
,
WM8960_POWER1_ADCR_MASK
,
((
uint16_t
)
isEnabled
<<
WM8960_POWER1_ADCR_SHIFT
));
break
;
case
kWM8960_ModuleDAC
:
WM8960_ModifyReg
(
handle
,
WM8960_POWER2
,
WM8960_POWER2_DACL_MASK
,
((
uint16_t
)
isEnabled
<<
WM8960_POWER2_DACL_SHIFT
));
WM8960_ModifyReg
(
handle
,
WM8960_POWER2
,
WM8960_POWER2_DACR_MASK
,
((
uint16_t
)
isEnabled
<<
WM8960_POWER2_DACR_SHIFT
));
break
;
case
kWM8960_ModuleVREF
:
WM8960_ModifyReg
(
handle
,
WM8960_POWER1
,
WM8960_POWER1_VREF_MASK
,
((
uint16_t
)
isEnabled
<<
WM8960_POWER1_VREF_SHIFT
));
break
;
case
kWM8960_ModuleLineIn
:
WM8960_ModifyReg
(
handle
,
WM8960_POWER1
,
WM8960_POWER1_AINL_MASK
,
((
uint16_t
)
isEnabled
<<
WM8960_POWER1_AINL_SHIFT
));
WM8960_ModifyReg
(
handle
,
WM8960_POWER1
,
WM8960_POWER1_AINR_MASK
,
((
uint16_t
)
isEnabled
<<
WM8960_POWER1_AINR_SHIFT
));
break
;
case
kWM8960_ModuleLineOut
:
WM8960_ModifyReg
(
handle
,
WM8960_POWER2
,
WM8960_POWER2_LOUT1_MASK
,
((
uint16_t
)
isEnabled
<<
WM8960_POWER2_LOUT1_SHIFT
));
WM8960_ModifyReg
(
handle
,
WM8960_POWER2
,
WM8960_POWER2_ROUT1_MASK
,
((
uint16_t
)
isEnabled
<<
WM8960_POWER2_ROUT1_SHIFT
));
break
;
case
kWM8960_ModuleSpeaker
:
WM8960_ModifyReg
(
handle
,
WM8960_POWER2
,
WM8960_POWER2_SPKL_MASK
,
((
uint16_t
)
isEnabled
<<
WM8960_POWER2_SPKL_SHIFT
));
WM8960_ModifyReg
(
handle
,
WM8960_POWER2
,
WM8960_POWER2_SPKR_MASK
,
((
uint16_t
)
isEnabled
<<
WM8960_POWER2_SPKR_SHIFT
));
WM8960_WriteReg
(
handle
,
WM8960_CLASSD1
,
0xF7
);
break
;
default:
ret
=
kStatus_InvalidArgument
;
break
;
}
return
ret
;
}
status_t
WM8960_SetDataRoute
(
wm8960_handle_t
*
handle
,
wm8960_route_t
route
)
{
status_t
ret
=
kStatus_Success
;
switch
(
route
)
{
case
kWM8960_RouteBypass
:
/* Bypass means from line-in to HP*/
/*
* Left LINPUT3 to left output mixer, LINPUT3 left output mixer volume = 0dB
*/
WM8960_WriteReg
(
handle
,
WM8960_LOUTMIX
,
0x80
);
/*
* Right RINPUT3 to right output mixer, RINPUT3 right output mixer volume = 0dB
*/
WM8960_WriteReg
(
handle
,
WM8960_ROUTMIX
,
0x80
);
break
;
case
kWM8960_RoutePlayback
:
/* Data route I2S_IN-> DAC-> HP */
/*
* Left DAC to left output mixer, LINPUT3 left output mixer volume = 0dB
*/
WM8960_WriteReg
(
handle
,
WM8960_LOUTMIX
,
0x100
);
/*
* Right DAC to right output mixer, RINPUT3 right output mixer volume = 0dB
*/
WM8960_WriteReg
(
handle
,
WM8960_ROUTMIX
,
0x100
);
break
;
case
kWM8960_RoutePlaybackandRecord
:
/* I2S IN->DAC->HP LINE_IN->ADC->I2S_OUT */
/*
* Left and right input boost, LIN3BOOST and RIN3BOOST = 0dB
*/
WM8960_WriteReg
(
handle
,
WM8960_INBMIX1
,
0x50
);
WM8960_WriteReg
(
handle
,
WM8960_INBMIX2
,
0x50
);
/*
* Left DAC to left output mixer, LINPUT3 left output mixer volume = 0dB
*/
WM8960_WriteReg
(
handle
,
WM8960_LOUTMIX
,
0x100
);
/*
* Right DAC to right output mixer, RINPUT3 right output mixer volume = 0dB
*/
WM8960_WriteReg
(
handle
,
WM8960_ROUTMIX
,
0x100
);
break
;
case
kWM8960_RoutePlaybackwithDAP
:
/* I2S_IN->DAP->DAC->HP */
break
;
case
kWM8960_RoutePlaybackwithDAPandRecord
:
/* I2S_IN->DAP->DAC->HP, LINE_IN->ADC->I2S_OUT */
break
;
case
kWM8960_RouteRecord
:
/* LINE_IN->ADC->I2S_OUT */
/*
* Left and right input boost, LIN3BOOST and RIN3BOOST = 0dB
*/
WM8960_WriteReg
(
handle
,
WM8960_INBMIX1
,
0x50
);
WM8960_WriteReg
(
handle
,
WM8960_INBMIX2
,
0x50
);
break
;
default:
ret
=
kStatus_InvalidArgument
;
break
;
}
return
ret
;
}
status_t
WM8960_SetProtocol
(
wm8960_handle_t
*
handle
,
wm8960_protocol_t
protocol
)
{
status_t
ret
=
kStatus_Success
;
switch
(
protocol
)
{
case
kWM8960_BusI2S
:
WM8960_ModifyReg
(
handle
,
WM8960_IFACE1
,
WM8960_IFACE1_FORMAT_MASK
,
WM8960_IFACE1_FORMAT
(
WM8960_IFACE1_FORMAT_I2S
));
break
;
case
kWM8960_BusLeftJustified
:
WM8960_ModifyReg
(
handle
,
WM8960_IFACE1
,
WM8960_IFACE1_FORMAT_MASK
,
WM8960_IFACE1_FORMAT
(
WM8960_IFACE1_FORMAT_LJ
));
break
;
case
kWM8960_BusRightJustified
:
WM8960_ModifyReg
(
handle
,
WM8960_IFACE1
,
WM8960_IFACE1_FORMAT_MASK
,
WM8960_IFACE1_FORMAT
(
WM8960_IFACE1_FORMAT_RJ
));
break
;
case
kWM8960_BusPCMA
:
WM8960_ModifyReg
(
handle
,
WM8960_IFACE1
,
WM8960_IFACE1_FORMAT_MASK
,
WM8960_IFACE1_FORMAT
(
WM8960_IFACE1_FORMAT_DSP
));
WM8960_ModifyReg
(
handle
,
WM8960_IFACE1
,
WM8960_IFACE1_LRP_MASK
,
WM8960_IFACE1_LRP
(
WM8960_IFACE1_DSP_MODEA
));
break
;
case
kWM8960_BusPCMB
:
WM8960_ModifyReg
(
handle
,
WM8960_IFACE1
,
WM8960_IFACE1_FORMAT_MASK
,
WM8960_IFACE1_FORMAT
(
WM8960_IFACE1_FORMAT_DSP
));
WM8960_ModifyReg
(
handle
,
WM8960_IFACE1
,
WM8960_IFACE1_LRP_MASK
,
WM8960_IFACE1_LRP
(
WM8960_IFACE1_DSP_MODEB
));
break
;
default:
ret
=
kStatus_InvalidArgument
;
break
;
}
WM8960_ModifyReg
(
handle
,
WM8960_IFACE1
,
WM8960_IFACE1_WL_MASK
,
WM8960_IFACE1_WL
(
WM8960_IFACE1_WL_32BITS
));
return
ret
;
}
status_t
WM8960_SetVolume
(
wm8960_handle_t
*
handle
,
wm8960_module_t
module
,
uint32_t
volume
)
{
uint16_t
vol
=
0
;
status_t
ret
=
kStatus_Success
;
switch
(
module
)
{
case
kWM8960_ModuleADC
:
vol
=
0x100
|
volume
;
ret
=
WM8960_WriteReg
(
handle
,
WM8960_LADC
,
vol
);
ret
=
WM8960_WriteReg
(
handle
,
WM8960_RADC
,
vol
);
break
;
case
kWM8960_ModuleDAC
:
vol
=
0x100
|
volume
;
ret
=
WM8960_WriteReg
(
handle
,
WM8960_LDAC
,
vol
);
ret
=
WM8960_WriteReg
(
handle
,
WM8960_RDAC
,
vol
);
break
;
case
kWM8960_ModuleHP
:
vol
=
0x100
|
volume
;
ret
=
WM8960_WriteReg
(
handle
,
WM8960_LOUT1
,
vol
);
ret
=
WM8960_WriteReg
(
handle
,
WM8960_ROUT1
,
vol
);
break
;
case
kWM8960_ModuleLineIn
:
vol
=
0x100
|
volume
;
ret
=
WM8960_WriteReg
(
handle
,
WM8960_LINVOL
,
vol
);
ret
=
WM8960_WriteReg
(
handle
,
WM8960_RINVOL
,
vol
);
break
;
case
kWM8960_ModuleSpeaker
:
vol
=
0x100
|
volume
;
ret
=
WM8960_WriteReg
(
handle
,
WM8960_LOUT2
,
vol
);
ret
=
WM8960_WriteReg
(
handle
,
WM8960_ROUT2
,
vol
);
break
;
default:
ret
=
kStatus_InvalidArgument
;
break
;
}
return
ret
;
}
uint32_t
WM8960_GetVolume
(
wm8960_handle_t
*
handle
,
wm8960_module_t
module
)
{
uint16_t
vol
=
0
;
switch
(
module
)
{
case
kWM8960_ModuleADC
:
WM8960_ReadReg
(
WM8960_LADC
,
&
vol
);
vol
&=
0xFF
;
break
;
case
kWM8960_ModuleDAC
:
WM8960_ReadReg
(
WM8960_LDAC
,
&
vol
);
vol
&=
0xFF
;
break
;
case
kWM8960_ModuleHP
:
WM8960_ReadReg
(
WM8960_LOUT1
,
&
vol
);
vol
&=
0x7F
;
break
;
case
kWM8960_ModuleLineOut
:
WM8960_ReadReg
(
WM8960_LINVOL
,
&
vol
);
vol
&=
0x3F
;
break
;
default:
vol
=
0
;
break
;
}
return
vol
;
}
status_t
WM8960_SetMute
(
wm8960_handle_t
*
handle
,
wm8960_module_t
module
,
bool
isEnabled
)
{
status_t
ret
=
kStatus_Success
;
switch
(
module
)
{
case
kWM8960_ModuleADC
:
/*
* Digital Mute
*/
if
(
isEnabled
)
{
ret
=
WM8960_WriteReg
(
handle
,
WM8960_LADC
,
0x100
);
ret
=
WM8960_WriteReg
(
handle
,
WM8960_RADC
,
0x100
);
}
else
{
ret
=
WM8960_WriteReg
(
handle
,
WM8960_LADC
,
0x1C3
);
ret
=
WM8960_WriteReg
(
handle
,
WM8960_RADC
,
0x1C3
);
}
break
;
case
kWM8960_ModuleDAC
:
/*
* Digital mute
*/
if
(
isEnabled
)
{
ret
=
WM8960_WriteReg
(
handle
,
WM8960_LDAC
,
0x100
);
ret
=
WM8960_WriteReg
(
handle
,
WM8960_RDAC
,
0x100
);
}
else
{
ret
=
WM8960_WriteReg
(
handle
,
WM8960_LDAC
,
0x1FF
);
ret
=
WM8960_WriteReg
(
handle
,
WM8960_RDAC
,
0x1FF
);
}
break
;
case
kWM8960_ModuleHP
:
/*
* Analog mute
*/
if
(
isEnabled
)
{
ret
=
WM8960_WriteReg
(
handle
,
WM8960_LOUT1
,
0x100
);
ret
=
WM8960_WriteReg
(
handle
,
WM8960_ROUT1
,
0x100
);
}
else
{
ret
=
WM8960_WriteReg
(
handle
,
WM8960_LOUT1
,
0x179
);
ret
=
WM8960_WriteReg
(
handle
,
WM8960_ROUT1
,
0x179
);
}
break
;
case
kWM8960_ModuleLineOut
:
break
;
default:
ret
=
kStatus_InvalidArgument
;
break
;
}
return
ret
;
}
status_t
WM8960_ConfigDataFormat
(
wm8960_handle_t
*
handle
,
uint32_t
mclk
,
uint32_t
sample_rate
,
uint8_t
bits
)
{
status_t
retval
=
kStatus_Success
;
switch
(
sample_rate
)
{
case
8000
:
retval
=
WM8960_WriteReg
(
handle
,
WM8960_CLOCK1
,
0x1B0
);
break
;
case
11025
:
retval
=
WM8960_WriteReg
(
handle
,
WM8960_CLOCK1
,
0xD8
);
break
;
case
12000
:
retval
=
WM8960_WriteReg
(
handle
,
WM8960_CLOCK1
,
0x120
);
break
;
case
16000
:
retval
=
WM8960_WriteReg
(
handle
,
WM8960_CLOCK1
,
0xD8
);
break
;
case
22050
:
retval
=
WM8960_WriteReg
(
handle
,
WM8960_CLOCK1
,
0xD8
);
break
;
case
24000
:
retval
=
WM8960_WriteReg
(
handle
,
WM8960_CLOCK1
,
0x90
);
break
;
case
32000
:
retval
=
WM8960_WriteReg
(
handle
,
WM8960_CLOCK1
,
0x48
);
break
;
case
44100
:
retval
=
WM8960_WriteReg
(
handle
,
WM8960_CLOCK1
,
0xD8
);
break
;
case
48000
:
retval
=
WM8960_WriteReg
(
handle
,
WM8960_CLOCK1
,
0x00
);
break
;
default:
retval
=
kStatus_InvalidArgument
;
break
;
}
/*
* Slave mode (MS = 0), LRP = 0, 32bit WL, left justified (FORMAT[1:0]=0b01)
*/
switch
(
bits
)
{
case
16
:
retval
=
WM8960_ModifyReg
(
handle
,
WM8960_IFACE1
,
WM8960_IFACE1_WL_MASK
,
WM8960_IFACE1_WL
(
WM8960_IFACE1_WL_16BITS
));
break
;
case
20
:
retval
=
WM8960_ModifyReg
(
handle
,
WM8960_IFACE1
,
WM8960_IFACE1_WL_MASK
,
WM8960_IFACE1_WL
(
WM8960_IFACE1_WL_20BITS
));
break
;
case
24
:
retval
=
WM8960_ModifyReg
(
handle
,
WM8960_IFACE1
,
WM8960_IFACE1_WL_MASK
,
WM8960_IFACE1_WL
(
WM8960_IFACE1_WL_24BITS
));
break
;
case
32
:
retval
=
WM8960_ModifyReg
(
handle
,
WM8960_IFACE1
,
WM8960_IFACE1_WL_MASK
,
WM8960_IFACE1_WL
(
WM8960_IFACE1_WL_32BITS
));
break
;
default:
retval
=
kStatus_InvalidArgument
;
break
;
}
return
retval
;
}
status_t
WM8960_SetJackDetect
(
wm8960_handle_t
*
handle
,
bool
isEnabled
)
{
uint8_t
retval
=
0
;
uint16_t
val
=
0
;
WM8960_ReadReg
(
WM8960_ADDCTL2
,
&
val
);
if
(
isEnabled
)
{
val
|=
0x40U
;
}
else
{
val
&=
0xCF
;
}
retval
=
WM8960_WriteReg
(
handle
,
WM8960_ADDCTL2
,
val
);
return
retval
;
}
status_t
WM8960_WriteReg
(
wm8960_handle_t
*
handle
,
uint8_t
reg
,
uint16_t
val
)
{
uint8_t
cmd
,
buff
;
uint8_t
retval
=
0
;
/* The register address */
cmd
=
(
reg
<<
1
)
|
((
val
>>
8U
)
&
0x0001U
);
/* Data */
buff
=
val
&
0xFF
;
/* Copy data to cache */
reg_cache
[
reg
]
=
val
;
#if defined(FSL_FEATURE_SOC_LPI2C_COUNT) && (FSL_FEATURE_SOC_LPI2C_COUNT)
uint8_t
data
[
2
];
data
[
0
]
=
cmd
;
data
[
1
]
=
buff
;
retval
=
LPI2C_MasterStart
(
handle
->
base
,
WM8960_I2C_ADDR
,
kLPI2C_Write
);
retval
=
LPI2C_MasterSend
(
handle
->
base
,
data
,
2
);
retval
=
LPI2C_MasterStop
(
handle
->
base
);
#else
/* Config the I2C xfer */
handle
->
xfer
.
direction
=
kI2C_Write
;
handle
->
xfer
.
subaddress
=
cmd
;
handle
->
xfer
.
subaddressSize
=
1U
;
handle
->
xfer
.
data
=
&
buff
;
handle
->
xfer
.
dataSize
=
1U
;
retval
=
I2C_MasterTransferBlocking
(
handle
->
base
,
&
handle
->
xfer
);
#endif
if
(
retval
!=
kStatus_Success
)
{
return
kStatus_Fail
;
}
return
kStatus_Success
;
}
status_t
WM8960_ReadReg
(
uint8_t
reg
,
uint16_t
*
val
)
{
if
(
reg
>=
WM8960_CACHEREGNUM
)
{
return
kStatus_InvalidArgument
;
}
*
val
=
reg_cache
[
reg
];
return
kStatus_Success
;
}
status_t
WM8960_ModifyReg
(
wm8960_handle_t
*
handle
,
uint8_t
reg
,
uint16_t
mask
,
uint16_t
val
)
{
uint8_t
retval
=
0
;
uint16_t
reg_val
=
0
;
retval
=
WM8960_ReadReg
(
reg
,
&
reg_val
);
if
(
retval
!=
kStatus_Success
)
{
return
kStatus_Fail
;
}
reg_val
&=
(
uint16_t
)
~
mask
;
reg_val
|=
val
;
retval
=
WM8960_WriteReg
(
handle
,
reg
,
reg_val
);
if
(
retval
!=
kStatus_Success
)
{
return
kStatus_Fail
;
}
return
kStatus_Success
;
}
bsp/imxrt1052-evk/drivers/fsl_wm8960.h
0 → 100644
浏览文件 @
e0314e63
/*
* 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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录