[bsp][lpc55sxx] add i2s and wm8904 driver
This commit is contained in:
parent
d6e40f2a24
commit
0822f02606
@ -43,6 +43,12 @@ if GetDepend('BSP_USING_WDT'):
|
||||
if GetDepend('BSP_USING_PWM'):
|
||||
src += ['drv_pwm.c']
|
||||
|
||||
if GetDepend('BSP_USING_I2S'):
|
||||
src += ['drv_i2s.c']
|
||||
|
||||
if GetDepend('BSP_USING_WM8904'):
|
||||
src += ['drv_sound_wm8904.c']
|
||||
|
||||
path = [cwd,cwd + '/config']
|
||||
|
||||
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path)
|
||||
|
301
bsp/lpc55sxx/Libraries/drivers/drv_i2s.c
Normal file
301
bsp/lpc55sxx/Libraries/drivers/drv_i2s.c
Normal file
@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-03-12 Vandoul the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "fsl_i2s.h"
|
||||
#include "fsl_i2s_dma.h"
|
||||
#include "drv_i2s.h"
|
||||
|
||||
#define DBG_TAG "DRVI2S"
|
||||
#include "rtdbg.h"
|
||||
|
||||
#ifdef BSP_USING_I2S
|
||||
|
||||
#if !defined(BSP_USING_I2S0) && \
|
||||
!defined(BSP_USING_I2S1) && \
|
||||
!defined(BSP_USING_I2S2) && \
|
||||
!defined(BSP_USING_I2S3) && \
|
||||
!defined(BSP_USING_I2S4) && \
|
||||
!defined(BSP_USING_I2S5) && \
|
||||
!defined(BSP_USING_I2S6) && \
|
||||
!defined(BSP_USING_I2S7)
|
||||
#error "Please define at least one I2Sx"
|
||||
#endif
|
||||
|
||||
#include <rtdevice.h>
|
||||
|
||||
enum {
|
||||
#ifdef BSP_USING_I2S0
|
||||
I2S0_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S1
|
||||
I2S1_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S2
|
||||
I2S2_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S3
|
||||
I2S3_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S4
|
||||
I2S4_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S5
|
||||
I2S5_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S6
|
||||
I2S6_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S7
|
||||
I2S7_INDEX,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct lpc_i2s_clock_and_irq_param
|
||||
{
|
||||
clock_attach_id_t i2s_clock;
|
||||
reset_ip_name_t i2s_reset_bit;
|
||||
IRQn_Type irq_type;
|
||||
};
|
||||
|
||||
struct lpc_i2s
|
||||
{
|
||||
struct rt_device device;
|
||||
i2s_handle_t i2s_handle;
|
||||
struct lpc_i2s_config config;
|
||||
uint32_t index;
|
||||
I2S_Type *i2s_base;
|
||||
const char *device_name;
|
||||
};
|
||||
|
||||
#define LPC_I2S_CONFIG_MODE_IS_SLAVE(dev) ((dev)->config.mode == LPC_I2S_CONFIG_MODE_SLAVE)
|
||||
#define LPC_I2S_CONFIG_MODE_IS_MASTER(dev) ((dev)->config.mode == LPC_I2S_CONFIG_MODE_MASTER)
|
||||
|
||||
#define LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(index) {.i2s_clock = kPLL0_DIV_to_FLEXCOMM##index, .i2s_reset_bit = kFC##index##_RST_SHIFT_RSTn, .irq_type = FLEXCOMM##index##_IRQn,}
|
||||
const static struct lpc_i2s_clock_and_irq_param lpc_i2s_clock_and_irq_param_table[] =
|
||||
{
|
||||
#ifdef BSP_USING_I2S0
|
||||
// {.i2s_clock = kPLL0_DIV_to_FLEXCOMM0, .i2s_reset_bit = kFC0_RST_SHIFT_RSTn, .irq_type = FLEXCOMM0_IRQn,},
|
||||
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(0),
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S1
|
||||
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(1),
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S2
|
||||
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(2),
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S3
|
||||
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(3),
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S4
|
||||
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(4),
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S5
|
||||
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(5),
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S6
|
||||
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(6),
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S7
|
||||
LPC_I2S_CLOCK_AND_IRQ_PARAM_INIT(7),
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct lpc_i2s lpc_i2s_table[] =
|
||||
{
|
||||
#ifdef BSP_USING_I2S0
|
||||
{.index = I2S0_INDEX,.i2s_base = I2S0,.device_name = "i2s0"},
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S1
|
||||
{.index = I2S1_INDEX,.i2s_base = I2S1,.device_name = "i2s1"},
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S2
|
||||
{.index = I2S2_INDEX,.i2s_base = I2S2,.device_name = "i2s2"},
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S3
|
||||
{.index = I2S3_INDEX,.i2s_base = I2S3,.device_name = "i2s3"},
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S4
|
||||
{.index = I2S4_INDEX,.i2s_base = I2S4,.device_name = "i2s4"},
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S5
|
||||
{.index = I2S5_INDEX,.i2s_base = I2S5,.device_name = "i2s5"},
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S6
|
||||
{.index = I2S6_INDEX,.i2s_base = I2S6,.device_name = "i2s6"},
|
||||
#endif
|
||||
#ifdef BSP_USING_I2S7
|
||||
{.index = I2S7_INDEX,.i2s_base = I2S7,.device_name = "i2s7"},
|
||||
#endif
|
||||
};
|
||||
|
||||
static void transfer_callback(I2S_Type *base, i2s_handle_t *handle, status_t completionStatus, void *userData)
|
||||
{
|
||||
struct lpc_i2s *i2s_dev = rt_container_of(handle, struct lpc_i2s, i2s_handle);
|
||||
if(LPC_I2S_CONFIG_MODE_IS_SLAVE(i2s_dev))
|
||||
{
|
||||
if(i2s_dev->device.rx_indicate != RT_NULL)
|
||||
{
|
||||
i2s_dev->device.rx_indicate(&i2s_dev->device, completionStatus);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i2s_dev->device.tx_complete != RT_NULL)
|
||||
{
|
||||
i2s_dev->device.tx_complete(&i2s_dev->device, RT_NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void i2s_clock_and_irq_config(struct lpc_i2s *dev)
|
||||
{
|
||||
const struct lpc_i2s_clock_and_irq_param *clock_and_irq_param = &lpc_i2s_clock_and_irq_param_table[dev->index];
|
||||
// CLOCK_SetClkDiv(kCLOCK_DivPll0Clk, 0U, true);
|
||||
// CLOCK_SetClkDiv(kCLOCK_DivPll0Clk, 1U, false);
|
||||
CLOCK_AttachClk(clock_and_irq_param->i2s_clock);
|
||||
RESET_PeripheralReset(clock_and_irq_param->i2s_reset_bit);
|
||||
NVIC_ClearPendingIRQ(clock_and_irq_param->irq_type);
|
||||
/* Enable interrupts for I2S */
|
||||
EnableIRQ(clock_and_irq_param->irq_type);
|
||||
}
|
||||
rt_err_t rt_i2s_init(rt_device_t dev)
|
||||
{
|
||||
struct lpc_i2s *i2s_dev = rt_container_of(dev, struct lpc_i2s, device);
|
||||
i2s_clock_and_irq_config(i2s_dev);
|
||||
return RT_EOK;
|
||||
}
|
||||
rt_err_t rt_i2s_open(rt_device_t dev, rt_uint16_t oflag)
|
||||
{
|
||||
struct lpc_i2s *i2s_dev = rt_container_of(dev, struct lpc_i2s, device);
|
||||
i2s_config_t config;
|
||||
if(i2s_dev->config.mode == LPC_I2S_CONFIG_MODE_SLAVE)
|
||||
{
|
||||
RT_ASSERT(i2s_dev->config.is_blocking == 0);
|
||||
I2S_RxGetDefaultConfig(&config);
|
||||
config.divider = CLOCK_GetPll0OutFreq()/i2s_dev->config.sampling_rate/i2s_dev->config.data_bits/i2s_dev->config.channels;
|
||||
config.masterSlave = kI2S_MasterSlaveNormalSlave;
|
||||
I2S_RxInit(i2s_dev->i2s_base, &config);
|
||||
I2S_RxTransferCreateHandle(i2s_dev->i2s_base, &i2s_dev->i2s_handle, transfer_callback, NULL);
|
||||
}
|
||||
else if(i2s_dev->config.mode == LPC_I2S_CONFIG_MODE_MASTER)
|
||||
{
|
||||
RT_ASSERT(i2s_dev->config.is_blocking == 0);
|
||||
I2S_TxGetDefaultConfig(&config);
|
||||
config.divider = CLOCK_GetPll0OutFreq()/i2s_dev->config.sampling_rate/i2s_dev->config.data_bits/i2s_dev->config.channels;
|
||||
config.masterSlave = kI2S_MasterSlaveNormalMaster;
|
||||
I2S_TxInit(i2s_dev->i2s_base, &config);
|
||||
I2S_TxTransferCreateHandle(i2s_dev->i2s_base, &i2s_dev->i2s_handle, transfer_callback, NULL);
|
||||
}
|
||||
return RT_EOK;
|
||||
}
|
||||
rt_err_t rt_i2s_close(rt_device_t dev)
|
||||
{
|
||||
struct lpc_i2s *i2s_dev = rt_container_of(dev, struct lpc_i2s, device);
|
||||
I2S_Deinit(i2s_dev->i2s_base);
|
||||
return RT_EOK;
|
||||
}
|
||||
rt_ssize_t rt_i2s_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
|
||||
{
|
||||
struct lpc_i2s *i2s_dev = rt_container_of(dev, struct lpc_i2s, device);
|
||||
if(!LPC_I2S_CONFIG_MODE_IS_SLAVE(i2s_dev))
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
i2s_transfer_t transfer;
|
||||
transfer.data = buffer;
|
||||
transfer.dataSize = size;
|
||||
if(kStatus_Success == I2S_RxTransferNonBlocking(i2s_dev->i2s_base, &i2s_dev->i2s_handle, transfer))
|
||||
return size;
|
||||
else
|
||||
return -RT_EBUSY;
|
||||
}
|
||||
rt_ssize_t rt_i2s_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
|
||||
{
|
||||
struct lpc_i2s *i2s_dev = rt_container_of(dev, struct lpc_i2s, device);
|
||||
if(!LPC_I2S_CONFIG_MODE_IS_MASTER(i2s_dev))
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
i2s_transfer_t transfer;
|
||||
transfer.data = (uint8_t *)buffer;
|
||||
transfer.dataSize = size;
|
||||
if(kStatus_Success == I2S_TxTransferNonBlocking(i2s_dev->i2s_base, &i2s_dev->i2s_handle, transfer))
|
||||
return size;
|
||||
else
|
||||
return -RT_EBUSY;
|
||||
}
|
||||
rt_err_t rt_i2s_control(rt_device_t dev, int cmd, void *args)
|
||||
{
|
||||
struct lpc_i2s *i2s_dev = rt_container_of(dev, struct lpc_i2s, device);
|
||||
rt_err_t ret = RT_EOK;
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
RT_ASSERT(args != RT_NULL);
|
||||
switch(cmd)
|
||||
{
|
||||
case RT_I2S_CTRL_RESET:
|
||||
i2s_clock_and_irq_config(i2s_dev);
|
||||
break;
|
||||
case RT_I2S_CTRL_SET_CONFIG:
|
||||
{
|
||||
struct lpc_i2s_config *config = (struct lpc_i2s_config *)args;
|
||||
i2s_dev->config = *config;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -RT_ERROR;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
const static struct rt_device_ops i2s_core_ops =
|
||||
{
|
||||
rt_i2s_init,
|
||||
rt_i2s_open,
|
||||
rt_i2s_close,
|
||||
rt_i2s_read,
|
||||
rt_i2s_write,
|
||||
rt_i2s_control,
|
||||
};
|
||||
#endif /* RT_USING_DEVICE_OPS */
|
||||
|
||||
int rt_hw_i2s_init(void)
|
||||
{
|
||||
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(lpc_i2s_table) / sizeof(lpc_i2s_table[0]); i++)
|
||||
{
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
lpc_i2s_table[i].device.ops = &i2s_core_ops;
|
||||
#else
|
||||
lpc_i2s_table[i].device.init = rt_i2s_init;
|
||||
lpc_i2s_table[i].device.open = rt_i2s_open;
|
||||
lpc_i2s_table[i].device.close = rt_i2s_close;
|
||||
lpc_i2s_table[i].device.read = rt_i2s_read;
|
||||
lpc_i2s_table[i].device.write = rt_i2s_write;
|
||||
lpc_i2s_table[i].device.control = rt_i2s_control;
|
||||
#endif
|
||||
|
||||
/* register UART device */
|
||||
rt_device_register(&lpc_i2s_table[i].device,
|
||||
lpc_i2s_table[i].device_name,
|
||||
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INIT_BOARD_EXPORT(rt_hw_i2s_init);
|
||||
|
||||
#endif
|
||||
|
43
bsp/lpc55sxx/Libraries/drivers/drv_i2s.h
Normal file
43
bsp/lpc55sxx/Libraries/drivers/drv_i2s.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-03-12 Vandoul the first version
|
||||
*/
|
||||
|
||||
#ifndef __DRV_I2S_H__
|
||||
#define __DRV_I2S_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#pragma pack(push,1)
|
||||
struct lpc_i2s_config
|
||||
{
|
||||
uint32_t sampling_rate;
|
||||
uint8_t mode;
|
||||
uint8_t data_bits;
|
||||
uint8_t channels;
|
||||
uint8_t is_blocking;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#define LPC_I2S_CONFIG_MODE_NULL 0
|
||||
#define LPC_I2S_CONFIG_MODE_SLAVE 1
|
||||
#define LPC_I2S_CONFIG_MODE_MASTER 2
|
||||
|
||||
#define RT_I2S_CTRL_RESET (RT_DEVICE_CTRL_BASE(Bus) + 1)
|
||||
#define RT_I2S_CTRL_SET_CONFIG (RT_DEVICE_CTRL_BASE(Bus) + 2)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
1123
bsp/lpc55sxx/Libraries/drivers/drv_sound_wm8904.c
Normal file
1123
bsp/lpc55sxx/Libraries/drivers/drv_sound_wm8904.c
Normal file
File diff suppressed because it is too large
Load Diff
214
bsp/lpc55sxx/Libraries/drivers/drv_sound_wm8904.h
Normal file
214
bsp/lpc55sxx/Libraries/drivers/drv_sound_wm8904.h
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-03-12 Vandoul the first version
|
||||
*/
|
||||
|
||||
#ifndef __DRV_SOUND_WM8904_H__
|
||||
#define __DRV_SOUND_WM8904_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WM8904_RESET = 0x00,
|
||||
WM8904_ANALOG_ADC_0 = 0x0A,
|
||||
WM8904_POWER_MGMT_0 = 0x0C,
|
||||
WM8904_POWER_MGMT_2 = 0x0E,
|
||||
WM8904_POWER_MGMT_3 = 0x0F,
|
||||
WM8904_POWER_MGMT_6 = 0x12,
|
||||
WM8904_CLK_RATES_0 = 0x14,
|
||||
WM8904_CLK_RATES_1 = 0x15,
|
||||
WM8904_CLK_RATES_2 = 0x16,
|
||||
WM8904_AUDIO_IF_0 = 0x18,
|
||||
WM8904_AUDIO_IF_1 = 0x19,
|
||||
WM8904_AUDIO_IF_2 = 0x1A,
|
||||
WM8904_AUDIO_IF_3 = 0x1B,
|
||||
WM8904_DAC_DIG_1 = 0x21,
|
||||
WM8904_DAC_DIG_0 = 0x27,
|
||||
WM8904_ANALOG_LEFT_IN_0 = 0x2C,
|
||||
WM8904_ANALOG_RIGHT_IN_0 = 0x2D,
|
||||
WM8904_ANALOG_LEFT_IN_1 = 0x2E,
|
||||
WM8904_ANALOG_RIGHT_IN_1 = 0x2F,
|
||||
WM8904_ANALOG_OUT1_LEFT = 0x39,
|
||||
WM8904_ANALOG_OUT1_RIGHT = 0x3A,
|
||||
WM8904_ANALOG_OUT12_ZC = 0x3D,
|
||||
WM8904_DC_SERVO_0 = 0x43,
|
||||
WM8904_ANALOG_HP_0 = 0x5A,
|
||||
WM8904_CHRG_PUMP_0 = 0x62,
|
||||
WM8904_CLS_W_0 = 0x68,
|
||||
WM8904_WRT_SEQUENCER_0 = 0x6C,
|
||||
WM8904_WRT_SEQUENCER_3 = 0x6F,
|
||||
WM8904_WRT_SEQUENCER_4 = 0x70,
|
||||
WM8904_DAC_DIGITAL_VOLUME_LEFT = 0x1E,
|
||||
WM8904_DAC_DIGITAL_VOLUME_RIGHT = 0x1F,
|
||||
WM8904_ADC_DIGITAL_VOLUME_LEFT = 0x24,
|
||||
WM8904_ADC_DIGITAL_VOLUME_RIGHT = 0x25,
|
||||
WM8904_ANALOG_OUT2_LEFT = 0x3B,
|
||||
WM8904_ANALOG_OUT2_RIGHT = 0x3C,
|
||||
/* FLL control register */
|
||||
WM8904_FLL_CONTROL_1 = 0x74,
|
||||
WM8904_FLL_CONTROL_2 = 0x75,
|
||||
WM8904_FLL_CONTROL_3 = 0x76,
|
||||
WM8904_FLL_CONTROL_4 = 0x77,
|
||||
WM8904_FLL_CONTROL_5 = 0x78,
|
||||
/* GPIO control register */
|
||||
WM8904_GPIO_CONTROL_1 = 0x79,
|
||||
WM8904_GPIO_CONTROL_2 = 0x7A,
|
||||
WM8904_GPIO_CONTROL_3 = 0x7B,
|
||||
WM8904_GPIO_CONTROL_4 = 0x7C,
|
||||
/* FLL nco */
|
||||
WM89004_FLL_NCO_TEST_0 = 0xF7,
|
||||
WM89004_FLL_NCO_TEST_1 = 0xF8,
|
||||
}wm8904_reg_t;
|
||||
|
||||
#define WM8904_LRC_POLARITY_POS (4U)
|
||||
#define WM8904_LRC_POLARITY_NOOMAL (0)
|
||||
#define WM8904_LRC_POLARITY_INVERTED (1U << WM8904_LRC_POLARITY_POS)
|
||||
|
||||
typedef enum _wm8904_module
|
||||
{
|
||||
WM8904_MODULE_ADC = 0, /*!< module ADC */
|
||||
WM8904_MODULE_DAC, /*!< module DAC */
|
||||
WM8904_MODULE_PGA, /*!< module PGA */
|
||||
WM8904_MODULE_HEADPHONE, /*!< module headphone */
|
||||
WM8904_MODULE_LINEOUT, /*!< module line out */
|
||||
}wm8904_module_t;
|
||||
|
||||
enum
|
||||
{
|
||||
WM8904_HEADPHONE_LEFT = 1U,
|
||||
WM8904_HEADPHONE_RIGHT = 2U,
|
||||
WM8904_LINEOUT_LEFT = 4U,
|
||||
WM8904_LINEOUT_RIGHT = 8U,
|
||||
};
|
||||
|
||||
typedef enum _wm8904_timeslot{
|
||||
WM8904_TIMESLOT_0 = 0U,
|
||||
WM8904_TIMESLOT_1,
|
||||
}wm8904_timeslot_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WM8904_PROTOCOL_RIGHT_JUSTIFIED = 0x00,
|
||||
WM8904_PROTOCOL_LEFT_JUSTIFIED = 0x01,
|
||||
WM8904_PROTOCOL_I2S = 0x02,
|
||||
WM8904_PROTOCOL_PCMA = 0x03,
|
||||
WM8904_PROTOCOL_PCMB = 0x13,
|
||||
}wm8904_protocol_t;
|
||||
|
||||
/*! @brief The SYSCLK / fs ratio. */
|
||||
typedef enum _wm8904_fs_ratio
|
||||
{
|
||||
WM8904_FSRATIO_64X = 0x0, /*!< SYSCLK is 64 * sample rate * frame width */
|
||||
WM8904_FSRATIO_128X = 0x1, /*!< SYSCLK is 128 * sample rate * frame width */
|
||||
WM8904_FSRATIO_192X = 0x2, /*!< SYSCLK is 192 * sample rate * frame width */
|
||||
WM8904_FSRATIO_256X = 0x3, /*!< SYSCLK is 256 * sample rate * frame width */
|
||||
WM8904_FSRATIO_384X = 0x4, /*!< SYSCLK is 384 * sample rate * frame width */
|
||||
WM8904_FSRATIO_512X = 0x5, /*!< SYSCLK is 512 * sample rate * frame width */
|
||||
WM8904_FSRATIO_768X = 0x6, /*!< SYSCLK is 768 * sample rate * frame width */
|
||||
WM8904_FSRATIO_1024X = 0x7, /*!< SYSCLK is 1024 * sample rate * frame width */
|
||||
WM8904_FSRATIO_1408X = 0x8, /*!< SYSCLK is 1408 * sample rate * frame width */
|
||||
WM8904_FSRATIO_1536X = 0x9 /*!< SYSCLK is 1536 * sample rate * frame width */
|
||||
} wm8904_fs_ratio_t;
|
||||
|
||||
/*! @brief Sample rate. */
|
||||
typedef enum _wm8904_sample_rate
|
||||
{
|
||||
WM8904_SAMPLERATE_8kHz = 0x0, /*!< 8 kHz */
|
||||
WM8904_SAMPLERATE_12kHz = 0x1, /*!< 12kHz */
|
||||
WM8904_SAMPLERATE_16kHz = 0x2, /*!< 16kHz */
|
||||
WM8904_SAMPLERATE_24kHz = 0x3, /*!< 24kHz */
|
||||
WM8904_SAMPLERATE_32kHz = 0x4, /*!< 32kHz */
|
||||
WM8904_SAMPLERATE_48kHz = 0x5, /*!< 48kHz */
|
||||
WM8904_SAMPLERATE_11025Hz = 0x6, /*!< 11.025kHz */
|
||||
WM8904_SAMPLERATE_22050Hz = 0x7, /*!< 22.05kHz */
|
||||
WM8904_SAMPLERATE_44100Hz = 0x8 /*!< 44.1kHz */
|
||||
} wm8904_sample_rate_t;
|
||||
|
||||
/*! @brief Bit width. */
|
||||
typedef enum _wm8904_bit_width
|
||||
{
|
||||
WM8904_BITWIDTH_16 = 0x0, /*!< 16 bits */
|
||||
WM8904_BITWIDTH_20 = 0x1, /*!< 20 bits */
|
||||
WM8904_BITWIDTH_24 = 0x2, /*!< 24 bits */
|
||||
WM8904_BITWIDTH_32 = 0x3 /*!< 32 bits */
|
||||
} wm8904_bit_width_t;
|
||||
|
||||
enum
|
||||
{
|
||||
WM8904_RECORD_SOURCE_DIFFERENTIAL_LINE = 1U, /*!< record source from differential line */
|
||||
WM8904_RECORD_SOURCE_LINE_INPUT = 2U, /*!< record source from line input */
|
||||
WM8904_RECORD_SOURCE_DIFFERENTIAL_MIC = 4U, /*!< record source from differential mic */
|
||||
WM8904_RECORD_SOURCE_DIGITAL_MIC = 8U, /*!< record source from digital microphone */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
WM8904_RECORD_CHANNEL_LEFT1 = 1U, /*!< left record channel 1 */
|
||||
WM8904_RECORD_CHANNEL_LEFT2 = 2U, /*!< left record channel 2 */
|
||||
WM8904_RECORD_CHANNEL_LEFT3 = 4U, /*!< left record channel 3 */
|
||||
WM8904_RECORD_CHANNEL_RIGHT1 = 1U, /*!< right record channel 1 */
|
||||
WM8904_RECORD_CHANNEL_RIGHT2 = 2U, /*!< right record channel 2 */
|
||||
WM8904_RECORD_CHANNEL_RIGHT3 = 4U, /*!< right record channel 3 */
|
||||
WM8904_RECORD_CHANNEL_DIFFERENTIAL_POSITIVE1 = 1U, /*!< differential positive record channel 1 */
|
||||
WM8904_RECORD_CHANNEL_DIFFERENTIAL_POSITIVE2 = 2U, /*!< differential positive record channel 2 */
|
||||
WM8904_RECORD_CHANNEL_DIFFERENTIAL_POSITIVE3 = 4U, /*!< differential positive record channel 3 */
|
||||
WM8904_RECORD_CHANNEL_DIFFERENTIAL_NEGATIVE1 = 8U, /*!< differential negative record channel 1 */
|
||||
WM8904_RECORD_CHANNEL_DIFFERENTIAL_NEGATIVE2 = 16U, /*!< differential negative record channel 2 */
|
||||
WM8904_RECORD_CHANNEL_DIFFERENTIAL_NEGATIVE3 = 32U, /*!< differential negative record channel 3 */
|
||||
};
|
||||
|
||||
/*! @brief wm8904 play source
|
||||
*
|
||||
*/
|
||||
enum
|
||||
{
|
||||
WM8904_PLAY_SOURCE_PGA = 1U, /*!< play source PGA, bypass ADC */
|
||||
WM8904_PLAY_SOURCE_DAC = 4U, /*!< play source Input3 */
|
||||
};
|
||||
|
||||
/*! @brief wm8904_fll_clk_source */
|
||||
typedef enum _wm8904_fll_clk_source
|
||||
{
|
||||
WM8904_FLL_CLK_SOURCE_MCLK = 0U, /**< wm8904 FLL clock source from MCLK */
|
||||
}wm8904_fll_clk_source_t;
|
||||
|
||||
/*! @brief wm8904 fll configuration */
|
||||
typedef struct _wm8904_fll_config
|
||||
{
|
||||
wm8904_fll_clk_source_t source; /*!< fll reference clock source */
|
||||
rt_uint32_t ref_clock_hz; /*!< fll reference clock frequency */
|
||||
rt_uint32_t output_clock_hz; /*!< fll output clock frequency */
|
||||
}wm8904_fll_config_t;
|
||||
|
||||
/*! @brief Audio format configuration. */
|
||||
typedef struct _wm8904_audio_format
|
||||
{
|
||||
wm8904_fs_ratio_t fsRatio; /*!< SYSCLK / fs ratio */
|
||||
wm8904_sample_rate_t sampleRate; /*!< Sample rate */
|
||||
wm8904_bit_width_t bitWidth; /*!< Bit width */
|
||||
} wm8904_audio_format_t;
|
||||
|
||||
struct wm8904_config
|
||||
{
|
||||
const char *i2c_bus_name;
|
||||
const char *i2s_bus_name;
|
||||
int i2c_addr;
|
||||
wm8904_protocol_t protocol;
|
||||
wm8904_audio_format_t format;
|
||||
};
|
||||
|
||||
#define WM8904_I2C_ADDRESS (0x1A)
|
||||
#define WM8904_I2C_BITRATE (400000U)
|
||||
|
||||
/* WM8904 maximum volume */
|
||||
#define WM8904_MAP_HEADPHONE_LINEOUT_MAX_VOLUME 0x3FU
|
||||
#define WM8904_DAC_MAX_VOLUME 0xC0U
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user