814 lines
16 KiB
C
Executable File
814 lines
16 KiB
C
Executable File
#include <common/bk_include.h>
|
|
#include "bk_arm_arch.h"
|
|
#include <common/bk_typedef.h>
|
|
#include "i2s.h"
|
|
#include "bk_i2s.h"
|
|
#include "bk_gpio.h"
|
|
#include "bk_drv_model.h"
|
|
#include <driver/int.h>
|
|
#include "bk_icu.h"
|
|
#include "bk_music_msg.h"
|
|
#include "bk_driver_audio.h"
|
|
#include "bk_uart.h"
|
|
#include <common/sys_config.h>
|
|
#include <common/bk_kernel_err.h>
|
|
#include <os/os.h>
|
|
#include <os/mem.h>
|
|
#include "bk_misc.h"
|
|
#include "bk_sys_ctrl.h"
|
|
#include "sys_ctrl.h"
|
|
#include "sys_driver.h"
|
|
#include <common/bk_generic.h>
|
|
|
|
#if CONFIG_I2S
|
|
|
|
#define RT_I2S_BIT_DEBUG
|
|
#ifdef RT_I2S_BIT_DEBUG
|
|
#define bit_dbg(fmt, ...) BK_LOG_RAW(fmt, ##__VA_ARGS__)
|
|
#else
|
|
#define bit_dbg(fmt, ...)
|
|
#endif
|
|
|
|
struct bk_i2s_dev {
|
|
UINT8 *tx_ptr;
|
|
UINT32 tx_len;
|
|
beken_semaphore_t tx_sem;
|
|
|
|
UINT8 *rx_ptr;
|
|
UINT32 rx_len;
|
|
UINT32 rx_offset;
|
|
UINT32 rx_drop;
|
|
|
|
UINT32 total_len;
|
|
UINT32 flag;
|
|
|
|
beken_mutex_t mutex;
|
|
};
|
|
|
|
volatile i2s_trans_t i2s_trans;
|
|
i2s_level_t i2s_fifo_level;
|
|
|
|
#if (!CONFIG_SOC_BK7271)
|
|
static UINT32 i2s_ctrl(UINT32 cmd, void *param);
|
|
|
|
static const DD_OPERATIONS i2s_op = {
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
i2s_ctrl
|
|
};
|
|
|
|
static void i2s_active(UINT8 enable)
|
|
{
|
|
UINT32 value_ctrl;
|
|
|
|
value_ctrl = REG_READ(PCM_CTRL);
|
|
|
|
if (enable)
|
|
value_ctrl |= I2S_PCM_EN;
|
|
else
|
|
value_ctrl &= ~I2S_PCM_EN;
|
|
|
|
REG_WRITE(PCM_CTRL, value_ctrl);
|
|
}
|
|
|
|
static void i2s_set_msten(UINT8 enable)
|
|
{
|
|
UINT32 value_ctrl;
|
|
|
|
value_ctrl = REG_READ(PCM_CTRL);
|
|
|
|
if (enable)
|
|
value_ctrl |= MSTEN;
|
|
else
|
|
value_ctrl &= (~MSTEN);
|
|
|
|
REG_WRITE(PCM_CTRL, value_ctrl);
|
|
}
|
|
|
|
static void i2s_select_mode(UINT8 val)
|
|
{
|
|
UINT32 value;
|
|
|
|
if (val == 3 || val > 7)
|
|
return;
|
|
|
|
value = REG_READ(PCM_CTRL);
|
|
value &= ~(MODE_SEL_MASK << MODE_SEL_POSI);
|
|
value |= (val << MODE_SEL_POSI);
|
|
REG_WRITE(PCM_CTRL, value);
|
|
}
|
|
|
|
static void i2s_set_lrck(UINT8 val)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_CTRL);
|
|
if (val)
|
|
value |= LRCK_RP;
|
|
else
|
|
value &= ~LRCK_RP;
|
|
REG_WRITE(PCM_CTRL, value);
|
|
}
|
|
|
|
static void i2s_set_sck_inv(UINT8 val)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_CTRL);
|
|
|
|
if (val)
|
|
value |= SCK_INV;
|
|
else
|
|
value &= ~SCK_INV;
|
|
|
|
REG_WRITE(PCM_CTRL, value);
|
|
}
|
|
|
|
static void i2s_set_sck_lsb(UINT8 val)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_CTRL);
|
|
if (val)
|
|
value |= LSB_FIRST;
|
|
else
|
|
value &= ~LSB_FIRST;
|
|
REG_WRITE(PCM_CTRL, value);
|
|
}
|
|
|
|
static void i2s_set_sck_synclen(UINT8 val)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_CTRL);
|
|
value &= ~ SYNCLEN_MASK;
|
|
value |= (val << SYNCLEN_POSI);
|
|
REG_WRITE(PCM_CTRL, value);
|
|
}
|
|
|
|
static void i2s_set_pcm_dlen(UINT8 val)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_CTRL);
|
|
value &= ~ PCM_DLEN_MASK;
|
|
value |= (val << PCM_DLEN_POSI);
|
|
REG_WRITE(PCM_CTRL, value);
|
|
}
|
|
|
|
static void i2s_set_freq_datawidth(i2s_rate_t *p_rate)
|
|
{
|
|
UINT32 bitratio, value = 0, lrck_div, sys_clk = 0;
|
|
|
|
if ((p_rate->freq != 8000) && (p_rate->freq != 16000) &&
|
|
(p_rate->freq != 24000) && (p_rate->freq != 32000) && (p_rate->freq != 48000) &&
|
|
(p_rate->freq != 11025) && (p_rate->freq != 22050) && (p_rate->freq != 44100))
|
|
return;
|
|
|
|
/*set irck div*/
|
|
if (p_rate->datawidth == 8)
|
|
lrck_div = 7;
|
|
else if (p_rate->datawidth == 16)
|
|
lrck_div = 15;
|
|
else if (p_rate->datawidth == 24)
|
|
lrck_div = 23;
|
|
else
|
|
lrck_div = 31;
|
|
|
|
/*set system clock*/
|
|
if (p_rate->freq == 8000) {
|
|
if (p_rate->datawidth == 24) {
|
|
sys_clk = 48384000;
|
|
sddev_control(DD_DEV_TYPE_SCTRL, CMD_SCTRL_AUDIO_PLL, &sys_clk);
|
|
} else {
|
|
sys_clk = 48128000;
|
|
sddev_control(DD_DEV_TYPE_SCTRL, CMD_SCTRL_AUDIO_PLL, &sys_clk);
|
|
}
|
|
} else if (p_rate->freq == 16000) {
|
|
if ((p_rate->datawidth == 16) || (p_rate->datawidth == 8)) {
|
|
sys_clk = 48128000;
|
|
sddev_control(DD_DEV_TYPE_SCTRL, CMD_SCTRL_AUDIO_PLL, &sys_clk);
|
|
} else {
|
|
sys_clk = 49152000;
|
|
sddev_control(DD_DEV_TYPE_SCTRL, CMD_SCTRL_AUDIO_PLL, &sys_clk);
|
|
}
|
|
} else if (p_rate->freq == 44100) {
|
|
sys_clk = 50803200;
|
|
sddev_control(DD_DEV_TYPE_SCTRL, CMD_SCTRL_AUDIO_PLL, &sys_clk);
|
|
} else {
|
|
if (p_rate->datawidth == 24) {
|
|
sys_clk = 50688000;
|
|
sddev_control(DD_DEV_TYPE_SCTRL, CMD_SCTRL_AUDIO_PLL, &sys_clk);
|
|
} else {
|
|
sys_clk = 49152000;
|
|
sddev_control(DD_DEV_TYPE_SCTRL, CMD_SCTRL_AUDIO_PLL, &sys_clk);
|
|
}
|
|
}
|
|
|
|
/*set bit clock divd*/
|
|
bitratio = MAX((NUMBER_ROUND_UP((sys_clk / 2), (p_rate->freq * 2 * (lrck_div + 1))) - 1), 5);
|
|
value = value | ((p_rate->datawidth - 1) << DATALEN_POSI)
|
|
| (lrck_div << SMPRATIO_POSI)
|
|
| (bitratio << BITRATIO_POSI);//this value is unused in slave mode
|
|
|
|
REG_WRITE(PCM_CTRL, value);
|
|
}
|
|
|
|
static void i2s_rxint_enable(UINT8 val)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_CN);
|
|
if (val)
|
|
value |= RX_INT_EN;
|
|
else
|
|
value &= ~RX_INT_EN;
|
|
REG_WRITE(PCM_CN, value);
|
|
}
|
|
|
|
static void i2s_txint_enable(UINT8 val)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_CN);
|
|
if (val)
|
|
value |= TX_INT0_EN;
|
|
else
|
|
value &= ~TX_INT0_EN;
|
|
REG_WRITE(PCM_CN, value);
|
|
}
|
|
|
|
static void i2s_rxovr_enable(UINT8 val)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_CN);
|
|
if (val)
|
|
value |= RX_OVF_EN;
|
|
else
|
|
value &= ~RX_OVF_EN;
|
|
REG_WRITE(PCM_CN, value);
|
|
}
|
|
|
|
static void i2s_txovr_enable(UINT8 val)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_CN);
|
|
if (val)
|
|
value |= TX_UDF0_EN;
|
|
else
|
|
value &= ~TX_UDF0_EN;
|
|
REG_WRITE(PCM_CN, value);
|
|
}
|
|
|
|
|
|
static void i2s_rxint_mode(UINT8 val)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_CN);
|
|
|
|
value &= ~(RX_FIFO_LEVEL_MASK << RX_FIFO_LEVEL_POSI) ;
|
|
value |= ((val & RX_FIFO_LEVEL_MASK) << RX_FIFO_LEVEL_POSI);
|
|
|
|
REG_WRITE(PCM_CN, value);
|
|
}
|
|
|
|
static void i2s_txint_mode(UINT8 val)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_CN);
|
|
|
|
value &= ~(RX_FIFO_LEVEL_MASK << TX_FIFO0_LEVEL_POSI) ;
|
|
value |= ((val & RX_FIFO_LEVEL_MASK) << TX_FIFO0_LEVEL_POSI);
|
|
|
|
REG_WRITE(PCM_CN, value);
|
|
}
|
|
|
|
static void i2s_rxfifo_clr_enable(void)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_CN);
|
|
value |= RX_FIFO_CLR;
|
|
|
|
REG_WRITE(PCM_CN, value);
|
|
}
|
|
|
|
static void i2s_txfifo_clr_enable(void)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_CN);
|
|
value = value | TX_FIFO0_CLR | TX_FIFO1_CLR | TX_FIFO2_CLR;
|
|
|
|
REG_WRITE(PCM_CN, value);
|
|
}
|
|
|
|
static void i2s_icu_configuration(UINT32 enable)
|
|
{
|
|
UINT32 param;
|
|
|
|
if (enable) {
|
|
param = PWD_I2S_PCM_CLK_BIT;
|
|
sddev_control(DD_DEV_TYPE_ICU, CMD_CLK_PWR_UP, ¶m);
|
|
|
|
param = (IRQ_I2S_PCM_BIT);
|
|
// sddev_control(DD_DEV_TYPE_ICU, CMD_ICU_INT_ENABLE, ¶m);
|
|
(void)sys_drv_int_enable(param);
|
|
} else {
|
|
param = (IRQ_I2S_PCM_BIT);
|
|
// sddev_control(DD_DEV_TYPE_ICU, CMD_ICU_INT_DISABLE, ¶m);
|
|
(void)sys_drv_int_disable(param);
|
|
|
|
param = PWD_I2S_PCM_CLK_BIT;
|
|
sddev_control(DD_DEV_TYPE_ICU, CMD_CLK_PWR_DOWN, ¶m);
|
|
}
|
|
}
|
|
|
|
static void i2s_gpio_configuration()
|
|
{
|
|
uint32_t val;
|
|
val = GFUNC_MODE_I2S; /*gpio 2-5*/
|
|
sddev_control(DD_DEV_TYPE_GPIO, CMD_GPIO_ENABLE_SECOND, &val);
|
|
}
|
|
|
|
static UINT8 i2s_get_busy(void)
|
|
{
|
|
//TODO
|
|
return 0;
|
|
}
|
|
|
|
static void i2s_master_enable(UINT32 enable)
|
|
{
|
|
UINT32 value, ultemp;
|
|
|
|
ultemp = 1;
|
|
|
|
value = REG_READ(PCM_CN);
|
|
value = value | (RX_INT_EN | TX_INT0_EN);
|
|
REG_WRITE(PCM_CN, value);
|
|
|
|
/* enable i2s unit */
|
|
i2s_ctrl(I2S_CMD_UNIT_ENABLE, (void *) &ultemp);
|
|
|
|
/* 1:MASTER 0:SLAVE */
|
|
if (enable)
|
|
i2s_ctrl(I2S_CMD_SET_MSTEN, (void *) &enable);
|
|
else
|
|
i2s_ctrl(I2S_CMD_SET_MSTEN, (void *)& enable);
|
|
|
|
bit_dbg("[-ISR-]I2S_DEBUG: pcm_ctrl=0x%X,pcm_cn =0x%08X,pcm_stat =0x%X\r\n", REG_READ(PCM_CTRL), REG_READ(PCM_CN), REG_READ(PCM_STAT));
|
|
|
|
i2s_icu_configuration(1); //enable clock;
|
|
}
|
|
|
|
static void i2s_dma_master_enable(UINT32 enable)
|
|
{
|
|
UINT32 value, ultemp;
|
|
|
|
ultemp = 1;
|
|
|
|
value = REG_READ(PCM_CN);
|
|
value = value | (RX_INT_EN | TX_INT0_EN);
|
|
REG_WRITE(PCM_CN, value);
|
|
|
|
/* enable i2s unit */
|
|
i2s_ctrl(I2S_CMD_UNIT_ENABLE, (void *) &ultemp);
|
|
|
|
/* 1:MASTER 0:SLAVE */
|
|
if (enable)
|
|
i2s_ctrl(I2S_CMD_SET_MSTEN, (void *) &enable);
|
|
else
|
|
i2s_ctrl(I2S_CMD_SET_MSTEN, (void *)& enable);
|
|
|
|
bit_dbg("[-DMA-]I2S_DEBUG: pcm_ctrl=0x%X,pcm_cn =0x%08X,pcm_stat =0x%X\r\n", REG_READ(PCM_CTRL), REG_READ(PCM_CN), REG_READ(PCM_STAT));
|
|
|
|
{
|
|
UINT32 param = PWD_I2S_PCM_CLK_BIT;
|
|
sddev_control(DD_DEV_TYPE_ICU, CMD_CLK_PWR_UP, ¶m);
|
|
}
|
|
}
|
|
|
|
static UINT8 i2s_disable_i2s(void)
|
|
{
|
|
UINT8 param;
|
|
UINT32 status;
|
|
|
|
param = 0;
|
|
i2s_ctrl(I2S_CMD_UNIT_ENABLE, (void *)¶m);
|
|
|
|
status = REG_READ(PCM_STAT);
|
|
|
|
REG_WRITE(PCM_CTRL, 0);
|
|
REG_WRITE(PCM_CN, 0);
|
|
REG_WRITE(PCM_STAT, status);
|
|
|
|
i2s_icu_configuration(0); //disable clock;
|
|
return 0;
|
|
}
|
|
|
|
__maybe_unused static UINT32 i2s_read_rxfifo(UINT8 *data);
|
|
static UINT32 i2s_read_rxfifo(UINT8 *data)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_STAT);
|
|
|
|
if ((value & RX_FIFO0_EMPTY) == 0) {
|
|
value = REG_READ(PCM_STAT);
|
|
if (data)
|
|
*data = value;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
__maybe_unused static void i2s_txfifo_fill(void);
|
|
static void i2s_txfifo_fill(void)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_STAT);
|
|
|
|
while ((value & TX_FIFO0_FULL) == 0)
|
|
REG_WRITE(PCM_STAT, 0xff);
|
|
}
|
|
|
|
UINT32 i2s_write_txfifo(UINT8 data)
|
|
{
|
|
UINT32 value;
|
|
|
|
value = REG_READ(PCM_STAT);
|
|
|
|
if ((value & TX_FIFO0_FULL) == 0) {
|
|
REG_WRITE(PCM_STAT, data);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
void i2s_init(int register_isr)
|
|
{
|
|
if (register_isr)
|
|
bk_int_isr_register(INT_SRC_I2S, i2s_isr, NULL);
|
|
sddev_register_dev(DD_DEV_TYPE_I2S, (DD_OPERATIONS *)&i2s_op);
|
|
}
|
|
|
|
|
|
void i2s_exit(void)
|
|
{
|
|
sddev_unregister_dev(DD_DEV_TYPE_I2S);
|
|
}
|
|
|
|
static void i2s_enable_interrupt(void)
|
|
{
|
|
UINT32 param;
|
|
param = (IRQ_I2S_PCM_BIT);
|
|
// sddev_control(DD_DEV_TYPE_ICU, CMD_ICU_INT_ENABLE, ¶m);
|
|
(void)sys_drv_int_enable(param);
|
|
}
|
|
|
|
static void i2s_disable_interrupt(void)
|
|
{
|
|
UINT32 param;
|
|
param = (IRQ_I2S_PCM_BIT);
|
|
// sddev_control(DD_DEV_TYPE_ICU, CMD_ICU_INT_DISABLE, ¶m);
|
|
(void)sys_drv_int_disable(param);
|
|
}
|
|
|
|
|
|
|
|
static UINT32 i2s_ctrl(UINT32 cmd, void *param)
|
|
{
|
|
UINT8 ret = I2S_SUCCESS;
|
|
|
|
//peri_busy_count_add();
|
|
|
|
|
|
switch (cmd) {
|
|
case I2S_CMD_UNIT_ENABLE:
|
|
i2s_active(*(UINT8 *)param);
|
|
break;
|
|
case I2S_CMD_SET_MSTEN:
|
|
i2s_set_msten(*(UINT8 *)param);
|
|
break;
|
|
case I2S_CMD_SELECT_MODE:
|
|
i2s_select_mode(*(UINT8 *)param);
|
|
break;
|
|
case I2S_CMD_SET_LRCK:
|
|
i2s_set_lrck(*(UINT8 *)param);
|
|
break;
|
|
case I2S_CMD_SET_SCK_INV:
|
|
i2s_set_sck_inv(*(UINT8 *)param);
|
|
break;
|
|
case I2S_CMD_SET_SCK_LSB:
|
|
i2s_set_sck_lsb(*(UINT8 *)param);
|
|
break;
|
|
case I2S_CMD_SET_SCK_SYNCLEN:
|
|
i2s_set_sck_synclen(*(UINT8 *)param);
|
|
break;
|
|
case I2S_CMD_SET_PCM_DLEN:
|
|
i2s_set_pcm_dlen(*(UINT8 *)param);
|
|
break;
|
|
case I2S_CMD_SET_FREQ_DATAWIDTH:
|
|
i2s_set_freq_datawidth((i2s_rate_t *)param);
|
|
break;
|
|
case I2S_CMD_RXINT_EN:
|
|
i2s_rxint_enable(*(UINT8 *)param);
|
|
break;
|
|
case I2S_CMD_TXINT_EN:
|
|
i2s_txint_enable(*(UINT8 *)param);
|
|
break;
|
|
case I2S_CMD_RXOVR_EN:
|
|
i2s_rxovr_enable(*(UINT8 *)param);
|
|
break;
|
|
case I2S_CMD_TXOVR_EN:
|
|
i2s_txovr_enable(*(UINT8 *)param);
|
|
break;
|
|
case I2S_CMD_RXFIFO_CLR_EN:
|
|
i2s_rxfifo_clr_enable();
|
|
break;
|
|
case I2S_CMD_TXFIFO_CLR_EN:
|
|
i2s_txfifo_clr_enable();
|
|
break;
|
|
case I2S_CMD_RXINT_MODE:
|
|
i2s_rxint_mode(*(UINT8 *)param);
|
|
break;
|
|
case I2S_CMD_TXINT_MODE:
|
|
i2s_txint_mode(*(UINT8 *)param);
|
|
break;
|
|
case I2S_CMD_GET_BUSY:
|
|
i2s_get_busy();
|
|
break;
|
|
case I2S_CMD_ENABLE_INTERRUPT:
|
|
i2s_enable_interrupt();
|
|
break;
|
|
case I2S_CMD_DISABLE_INTERRUPT:
|
|
i2s_disable_interrupt();
|
|
break;
|
|
case I2S_CMD_MASTER_ENABLE:
|
|
i2s_master_enable(*(UINT32 *)param);
|
|
break;
|
|
case I2S_CMD_DISABLE_I2S:
|
|
i2s_disable_i2s();
|
|
break;
|
|
case I2S_CMD_DMA_MASTER_ENABLE:
|
|
i2s_dma_master_enable(*(UINT32 *)param);
|
|
break;
|
|
case I2S_CMD_DMA_ISR:
|
|
bk_int_isr_register(INT_SRC_I2S, (FUNCPTR)param, NULL);
|
|
break;
|
|
|
|
default:
|
|
ret = I2S_FAILURE;
|
|
break;
|
|
}
|
|
|
|
// peri_busy_count_dec();
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
UINT32 i2s_configure(UINT32 fifo_level, UINT32 sample_rate, UINT32 bits_per_sample, UINT32 mode)
|
|
{
|
|
UINT32 param;
|
|
i2s_rate_t rate;
|
|
rate.datawidth = bits_per_sample;
|
|
rate.freq = sample_rate;
|
|
/*
|
|
mode:
|
|
bit0~2: mode & 0x7 000:I2S
|
|
001:Left Justified
|
|
010:Right Justified
|
|
011:reserve
|
|
100:Short Frame Sync
|
|
101:Long Frame Sync
|
|
110:Normal 2B+D
|
|
111:Delay 2B+D
|
|
|
|
bit3: mode & 0x08 0:LRCK no turn
|
|
1:LRCK turn
|
|
|
|
bit4: mode & 0x10 0:SCK no turn
|
|
1:SCK turn
|
|
|
|
bit5: mode & 0x20 0:MSB first send/receive
|
|
1:LSB first send/receive
|
|
|
|
bit8~10: mode & 0x700 0~7:Sync length only Long Frame Sync effective
|
|
|
|
bit12~14: mode & 0x7000 0~7: 2B+D PCM :D length
|
|
|
|
*/
|
|
/* set work mode */
|
|
param = (mode & 0x7) ;
|
|
i2s_ctrl(I2S_CMD_SELECT_MODE, (void *)¶m); // i2s mode set
|
|
|
|
/* set lrckrp */
|
|
param = (mode & 0x8);
|
|
i2s_ctrl(I2S_CMD_SET_LRCK, (void *)¶m);
|
|
|
|
/* set sclkinv */
|
|
param = (mode & 0x10);
|
|
i2s_ctrl(I2S_CMD_SET_SCK_INV, (void *)¶m);
|
|
|
|
/* set lsbfirst */
|
|
param = (mode & 0x20);
|
|
i2s_ctrl(I2S_CMD_SET_SCK_LSB, (void *)¶m);
|
|
|
|
/* set synclen */
|
|
param = (mode & 0x700);
|
|
param = param >> 8;
|
|
i2s_ctrl(I2S_CMD_SET_SCK_SYNCLEN, (void *)¶m);
|
|
|
|
/* set pcm_dlen */
|
|
param = (mode & 0x7000);
|
|
param = param >> 12;
|
|
i2s_ctrl(I2S_CMD_SET_PCM_DLEN, (void *)¶m);
|
|
|
|
/* set txfifo level */
|
|
param = fifo_level;
|
|
i2s_ctrl(I2S_CMD_TXINT_MODE, (void *)¶m);
|
|
|
|
/* set rxfifo level */
|
|
param = fifo_level;
|
|
i2s_ctrl(I2S_CMD_RXINT_MODE, (void *)¶m);
|
|
|
|
/* enable txover int */
|
|
param = 1;
|
|
i2s_ctrl(I2S_CMD_TXOVR_EN, (void *)¶m);
|
|
|
|
/* enable rxover int */
|
|
param = 1;
|
|
i2s_ctrl(I2S_CMD_RXOVR_EN, (void *)¶m);
|
|
|
|
i2s_gpio_configuration(); //set gpio
|
|
|
|
param = REG_READ(SCTRL_BLOCK_EN_CFG);
|
|
param = (param & (~(0x0FFFUL << 20))) | (BLOCK_EN_WORD_PWD << 20) | (1 << 16) | (1 << 17);
|
|
REG_WRITE(SCTRL_BLOCK_EN_CFG, param); // audio pll audio enable
|
|
|
|
#if (CONFIG_SOC_BK7256XX)
|
|
//sys_drv_analog_reg6_set(param);// to do,need remove old interface after all adaption is finished
|
|
sys_drv_set_dpll_for_i2s();
|
|
#else
|
|
sddev_control(DD_DEV_TYPE_SCTRL, CMD_SCTRL_SET_ANALOG6, NULL);// DPLL AUDIO OPEN, DPLL divider
|
|
#endif
|
|
|
|
/* set freq_datawidth */
|
|
i2s_ctrl(I2S_CMD_SET_FREQ_DATAWIDTH, (void *)&rate);
|
|
|
|
/* clear state */
|
|
REG_WRITE(PCM_STAT, 0x0000FFFF);
|
|
|
|
bit_dbg("[---]I2S_CONF:PCM_CTRL = 0x%x\n", REG_READ(PCM_CTRL));
|
|
bit_dbg("[---]I2S_CONF:PCM_CN = 0x%x\n", REG_READ(PCM_CN));
|
|
|
|
return I2S_SUCCESS;
|
|
}
|
|
|
|
UINT32 i2s_close(void)
|
|
{
|
|
UINT32 param = 0;
|
|
|
|
i2s_icu_configuration(0); //close clock;
|
|
|
|
i2s_ctrl(I2S_CMD_DISABLE_INTERRUPT, (void *)¶m);
|
|
i2s_ctrl(I2S_CMD_UNIT_ENABLE, (void *)¶m);
|
|
|
|
|
|
return I2S_SUCCESS;
|
|
}
|
|
|
|
|
|
UINT32 i2s_transfer(UINT32 *i2s_send_buf, UINT32 *i2s_recv_buf, UINT32 count, UINT32 param)
|
|
{
|
|
GLOBAL_INT_DECLARATION();
|
|
|
|
GLOBAL_INT_DISABLE();
|
|
i2s_trans.trans_done = 0;
|
|
i2s_trans.tx_remain_data_cnt = count;
|
|
i2s_trans.rx_remain_data_cnt = count;
|
|
i2s_trans.p_tx_buf = (UINT32 *) i2s_send_buf;
|
|
i2s_trans.p_rx_buf = (UINT32 *) i2s_recv_buf;
|
|
i2s_fifo_level.tx_level = FIFO_LEVEL_32;
|
|
i2s_fifo_level.rx_level = FIFO_LEVEL_32;
|
|
GLOBAL_INT_RESTORE();
|
|
|
|
if (param)
|
|
delay_ms(1000);
|
|
|
|
/* rxfifo clear enable*/
|
|
//i2s_ctrl(I2S_CMD_RXFIFO_CLR_EN, NULL);
|
|
|
|
/* enable */
|
|
i2s_ctrl(I2S_CMD_MASTER_ENABLE, (void *)¶m);
|
|
|
|
while (!i2s_trans.trans_done) {
|
|
}
|
|
|
|
delay_ms(1000);
|
|
i2s_trans.trans_done = 0;
|
|
|
|
i2s_ctrl(I2S_CMD_DISABLE_I2S, NULL);
|
|
|
|
return i2s_trans.trans_done;
|
|
}
|
|
|
|
void i2s_isr(void)
|
|
{
|
|
uint16_t i, rxint, txint0, ultemp;
|
|
uint32_t i2s_status;
|
|
volatile uint16_t data_num ;
|
|
|
|
i2s_status = REG_READ(PCM_STAT);
|
|
rxint = i2s_status & 0x01;
|
|
txint0 = i2s_status & 0x02;
|
|
|
|
if (txint0) {
|
|
switch (i2s_fifo_level.tx_level) {
|
|
case 0 :
|
|
data_num = 8;
|
|
break;
|
|
case 1 :
|
|
data_num = 16;
|
|
break;
|
|
case 2 :
|
|
data_num = 32;
|
|
break;
|
|
default :
|
|
data_num = 48;
|
|
break;
|
|
}
|
|
|
|
if (i2s_trans.p_tx_buf == NULL) {
|
|
for (i = 0; i < data_num; i++)
|
|
REG_WRITE(PCM_DAT0, 0xEEEEEEEE);
|
|
} else {
|
|
for (i = 0; i < data_num; i ++) {
|
|
REG_WRITE(PCM_DAT0, *i2s_trans.p_tx_buf);
|
|
i2s_trans.p_tx_buf ++;
|
|
}
|
|
}
|
|
i2s_status |= 0x2;
|
|
}
|
|
|
|
if (rxint) {
|
|
switch (i2s_fifo_level.rx_level) {
|
|
case 0 :
|
|
data_num = 8;
|
|
break;
|
|
case 1 :
|
|
data_num = 16;
|
|
break;
|
|
case 2 :
|
|
data_num = 32;
|
|
break;
|
|
default :
|
|
data_num = 48;
|
|
break;
|
|
}
|
|
|
|
if (data_num > i2s_trans.rx_remain_data_cnt)
|
|
data_num = i2s_trans.rx_remain_data_cnt;
|
|
|
|
if ((i2s_trans.p_rx_buf == NULL) || (i2s_status & RX_FIFO0_EMPTY)) {
|
|
for (i = 0; i < data_num; i++) {
|
|
ultemp = REG_READ(PCM_DAT0);
|
|
(void) ultemp;
|
|
}
|
|
} else {
|
|
for (i = 0; i < data_num; i++) {
|
|
*i2s_trans.p_rx_buf = REG_READ(PCM_DAT0);
|
|
i2s_trans.p_rx_buf++;
|
|
}
|
|
|
|
i2s_trans.rx_remain_data_cnt -= data_num;
|
|
|
|
if (i2s_trans.rx_remain_data_cnt <= 0) {
|
|
i = 0;
|
|
i2s_trans.trans_done = 1;
|
|
i2s_ctrl(I2S_CMD_TXINT_EN, (void *)&i);
|
|
i2s_ctrl(I2S_CMD_RXINT_EN, (void *)&i);
|
|
}
|
|
}
|
|
i2s_status |= 0x1;
|
|
}
|
|
|
|
REG_WRITE(PCM_STAT, i2s_status);
|
|
|
|
}
|
|
#endif
|
|
#endif
|
|
// eof
|
|
|