Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
908
sdk/driver/i2s/hgi2s_v0.c
Normal file
908
sdk/driver/i2s/hgi2s_v0.c
Normal file
@@ -0,0 +1,908 @@
|
||||
/**
|
||||
* @file hgi2s_v0.c
|
||||
* @author bxd
|
||||
* @brief iis
|
||||
* @version
|
||||
* TXW80X; TXW81X
|
||||
* @date 2023-08-02
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*/
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "errno.h"
|
||||
#include "dev.h"
|
||||
#include "osal/irq.h"
|
||||
#include "osal/string.h"
|
||||
#include "osal/semaphore.h"
|
||||
#include "osal/mutex.h"
|
||||
#include "hal/i2s.h"
|
||||
#include "dev/i2s/hgi2s_v0.h"
|
||||
#include "hgi2s_v0_hw.h"
|
||||
|
||||
|
||||
#define __OVER_SAMPPLE_RATE (512)
|
||||
|
||||
struct __iis_cfg {
|
||||
uint32 mclk_div;
|
||||
uint32 baud_div;
|
||||
uint32 wscon_div;
|
||||
};
|
||||
|
||||
const struct __iis_cfg iis_cfg_8k[] = {
|
||||
|
||||
/*!
|
||||
* over_sample: 512.000
|
||||
* sample_rate: 8000.000
|
||||
* 8 bit
|
||||
*/
|
||||
//mclk_rate:4.103MHz, bclk_rate:128.205KHz, sample_rate:8012.821Hz, error_rate:1602.56ppm,mclk = 116, baud = 15, wscon = 7
|
||||
{
|
||||
.mclk_div = 116,
|
||||
.baud_div = 15,
|
||||
.wscon_div = 7,
|
||||
},
|
||||
|
||||
/*!
|
||||
* over_sample: 512.000
|
||||
* sample_rate: 8000.000
|
||||
* 16 bit
|
||||
*/
|
||||
//mclk_rate:4.103MHz, bclk_rate:256.410KHz, sample_rate:8012.821Hz, error_rate:1602.56ppm,mclk = 116, baud = 7, wscon = 15
|
||||
{
|
||||
.mclk_div = 116,
|
||||
.baud_div = 7,
|
||||
.wscon_div = 15,
|
||||
},
|
||||
|
||||
/*!
|
||||
* over_sample: 768.000
|
||||
* sample_rate: 8000.000
|
||||
* 24 bit
|
||||
*/
|
||||
//mclk_rate:6.154MHz, bclk_rate:384.615KHz, sample_rate:8012.821Hz, error_rate:1602.56ppm,mclk = 77, baud = 7, wscon = 23
|
||||
{
|
||||
.mclk_div = 77,
|
||||
.baud_div = 7,
|
||||
.wscon_div = 23,
|
||||
}
|
||||
};
|
||||
|
||||
const struct __iis_cfg iis_cfg_16k[] = {
|
||||
|
||||
/*!
|
||||
* over_sample: 256.000
|
||||
* sample_rate: 16000.000
|
||||
* 8 bit
|
||||
*/
|
||||
//mclk_rate:4.103MHz, bclk_rate:256.410KHz, sample_rate:16025.641Hz, error_rate:1602.56ppm,mclk = 116, baud = 7, wscon = 7
|
||||
{
|
||||
.mclk_div = 116,
|
||||
.baud_div = 7,
|
||||
.wscon_div = 7,
|
||||
},
|
||||
|
||||
/*!
|
||||
* over_sample: 256.000
|
||||
* sample_rate: 16000.000
|
||||
* 16 bit
|
||||
*/
|
||||
//mclk_rate:4.103MHz, bclk_rate:512.821KHz, sample_rate:16025.641Hz, error_rate:1602.56ppm,mclk = 116, baud = 3, wscon = 15
|
||||
{
|
||||
.mclk_div = 116,
|
||||
.baud_div = 3,
|
||||
.wscon_div = 15,
|
||||
},
|
||||
|
||||
/*!
|
||||
* over_sample: 384.000
|
||||
* sample_rate: 16000.000
|
||||
* 24 bit
|
||||
*/
|
||||
//mclk_rate:6.154MHz, bclk_rate:769.231KHz, sample_rate:16025.641Hz, error_rate:1602.56ppm,mclk = 77, baud = 3, wscon = 23
|
||||
{
|
||||
.mclk_div = 77,
|
||||
.baud_div = 3,
|
||||
.wscon_div = 23,
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const struct __iis_cfg iis_cfg_44_1k[] = {
|
||||
|
||||
/*!
|
||||
* over_sample: 128.000
|
||||
* sample_rate: 44100.000
|
||||
* 16 bit
|
||||
*/
|
||||
//mclk_rate:5.647MHz, bclk_rate:705.882KHz, sample_rate:44117.647Hz, error_rate:400.16ppm,mclk = 84, baud = 3, wscon = 7
|
||||
{
|
||||
.mclk_div = 84,
|
||||
.baud_div = 3,
|
||||
.wscon_div = 7,
|
||||
},
|
||||
|
||||
/*!
|
||||
* over_sample: 128.000
|
||||
* sample_rate: 44100.000
|
||||
* 16 bit
|
||||
*/
|
||||
//mclk_rate:5.647MHz, bclk_rate:1411.765KHz, sample_rate:44117.647Hz, error_rate:400.16ppm,mclk = 84, baud = 1, wscon = 15
|
||||
{
|
||||
.mclk_div = 84,
|
||||
.baud_div = 1,
|
||||
.wscon_div = 15,
|
||||
},
|
||||
|
||||
/*!
|
||||
* over_sample: 128.000
|
||||
* sample_rate: 44100.000
|
||||
* 24 bit
|
||||
*/
|
||||
//no support
|
||||
|
||||
};
|
||||
|
||||
const struct __iis_cfg iis_cfg_48k[] = {
|
||||
|
||||
/*!
|
||||
* over_sample: 256.000
|
||||
* sample_rate: 48000.000
|
||||
* 8 bit
|
||||
*/
|
||||
//mclk_rate:12.308MHz, bclk_rate:769.231KHz, sample_rate:48076.923Hz, error_rate:1602.56ppm,mclk = 38, baud = 7, wscon = 7
|
||||
{
|
||||
.mclk_div = 38,
|
||||
.baud_div = 7,
|
||||
.wscon_div = 7,
|
||||
},
|
||||
|
||||
|
||||
/*!
|
||||
* over_sample: 768.000
|
||||
* sample_rate: 48000.000
|
||||
* 16 bit
|
||||
*/
|
||||
//mclk_rate:36.923MHz, bclk_rate:1538.462KHz, sample_rate:48076.923Hz, error_rate:1602.56ppm,mclk = 12, baud = 11, wscon = 15
|
||||
{
|
||||
.mclk_div = 12,
|
||||
.baud_div = 11,
|
||||
.wscon_div = 15,
|
||||
},
|
||||
|
||||
/*!
|
||||
* over_sample: 768.000
|
||||
* sample_rate: 48000.000
|
||||
* 16 bit
|
||||
*/
|
||||
//mclk_rate:36.923MHz, bclk_rate:2307.692KHz, sample_rate:48076.923Hz, error_rate:1602.56ppm,mclk = 12, baud = 7, wscon = 23
|
||||
{
|
||||
.mclk_div = 12,
|
||||
.baud_div = 7,
|
||||
.wscon_div = 23,
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**********************************************************************************/
|
||||
/* I2S LOW LAYER FUNCTION */
|
||||
/**********************************************************************************/
|
||||
static int32 hgi2s_v0_switch_hal_i2s_mode(enum i2s_mode mode) {
|
||||
|
||||
switch (mode) {
|
||||
case (I2S_MODE_MASTER ):
|
||||
return 0;
|
||||
break;
|
||||
case (I2S_MODE_SLAVE ):
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int32 hgi2s_v0_switch_hal_i2s_channel(enum i2s_channel channel) {
|
||||
|
||||
switch (channel) {
|
||||
case (I2S_CHANNEL_MONO ):
|
||||
return 1;
|
||||
break;
|
||||
case (I2S_CHANNEL_STEREO):
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int32 hgi2s_v0_switch_hal_i2s_sample_bits(enum i2s_sample_bits bits) {
|
||||
|
||||
switch (bits) {
|
||||
case (I2S_SAMPLE_BITS_8BITS ):
|
||||
return 8;
|
||||
break;
|
||||
case (I2S_SAMPLE_BITS_16BITS):
|
||||
return 16;
|
||||
break;
|
||||
case (I2S_SAMPLE_BITS_24BITS):
|
||||
return 24;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int32 hgi2s_v0_switch_hal_i2s_data_fmt(enum i2s_data_fmt data_fmt) {
|
||||
|
||||
switch (data_fmt) {
|
||||
case (I2S_DATA_FMT_I2S):
|
||||
return 0;
|
||||
break;
|
||||
case (I2S_DATA_FMT_LSB):
|
||||
return 1;
|
||||
break;
|
||||
case (I2S_DATA_FMT_MSB):
|
||||
return 2;
|
||||
break;
|
||||
case (I2S_DATA_FMT_PCM):
|
||||
return 3;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct __iis_cfg* hgi2s_v0_switch_hal_i2s_sample_freq(enum i2s_sample_freq frequency, enum i2s_sample_bits bits)
|
||||
{
|
||||
const struct __iis_cfg *p_iis_cfg = NULL;
|
||||
int8 index = -1;
|
||||
|
||||
if (I2S_SAMPLE_BITS_8BITS ==bits) {index=0;}
|
||||
if (I2S_SAMPLE_BITS_16BITS==bits) {index=1;}
|
||||
if (I2S_SAMPLE_BITS_24BITS==bits) {index=2;}
|
||||
|
||||
switch (frequency) {
|
||||
case (I2S_SAMPLE_FREQ_8K):
|
||||
p_iis_cfg = iis_cfg_8k;
|
||||
break;
|
||||
case (I2S_SAMPLE_FREQ_16K):
|
||||
p_iis_cfg = iis_cfg_16k;
|
||||
break;
|
||||
case (I2S_SAMPLE_FREQ_44_1K):
|
||||
p_iis_cfg = iis_cfg_44_1k;
|
||||
if (I2S_SAMPLE_BITS_24BITS==bits) {
|
||||
index=-1; p_iis_cfg=NULL;
|
||||
os_printf("iis info: no support 44.1k, 24bit\r\n");
|
||||
}
|
||||
break;
|
||||
case (I2S_SAMPLE_FREQ_48K ):
|
||||
p_iis_cfg = iis_cfg_48k;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((index==-1) || (p_iis_cfg==NULL)) {
|
||||
return NULL;
|
||||
} else {
|
||||
return &p_iis_cfg[index];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static inline void hgi2s_v0_set_mclk(struct hgi2s_v0_hw *p_i2s, uint32 mclk_div) {
|
||||
//uint32 mclk_div = 0;
|
||||
|
||||
//IIS0
|
||||
if (IIS0_BASE == (uint32)p_i2s) {
|
||||
SYSCTRL_REG_OPT(
|
||||
SYSCTRL->SYS_CON3 = (SYSCTRL->SYS_CON3 & ~(0x01 << 28)) | (0 << 28);
|
||||
);
|
||||
|
||||
#if 0
|
||||
/* i2s module clk use pll0 & pll1 */
|
||||
os_printf("iis0 pll clk:%d\r\n", peripheral_clock_get(HG_APB0_PT_IIS0));
|
||||
os_printf("iis1 pll clk:%d\r\n", peripheral_clock_get(HG_APB0_PT_IIS0));
|
||||
mclk_div = ((peripheral_clock_get(HG_APB0_PT_IIS0)+((freq*__OVER_SAMPPLE_RATE)/2)) / (freq*__OVER_SAMPPLE_RATE));
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* FPGA: 96MHz */
|
||||
mclk_div = (96000000 / (freq*256));
|
||||
#endif
|
||||
|
||||
SYSCTRL_REG_OPT(
|
||||
SYSCTRL->CLK_CON0 = (SYSCTRL->CLK_CON0 & ~(0x7f << 16)) | ((mclk_div) << 16);
|
||||
);
|
||||
}
|
||||
//IIS1
|
||||
else if(IIS1_BASE == (uint32)p_i2s){
|
||||
SYSCTRL_REG_OPT(
|
||||
SYSCTRL->SYS_CON3 = (SYSCTRL->SYS_CON3 & ~(0x01 << 29)) | (0 << 29);
|
||||
);
|
||||
|
||||
#if 0
|
||||
/* i2s module clk use pll0 & pll1 */
|
||||
mclk_div = (peripheral_clock_get(HG_APB0_PT_IIS1) / (freq*256));
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* FPGA: 96MHz */
|
||||
mclk_div = (96000000 / (freq*256));
|
||||
#endif
|
||||
|
||||
SYSCTRL_REG_OPT(
|
||||
SYSCTRL->CLK_CON0 = (SYSCTRL->CLK_CON0 & ~(0x7f << 23)) | ((mclk_div) << 23);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void hgi2s_v0_enable(struct hgi2s_v0_hw *p_i2s) {
|
||||
p_i2s->CON |= LL_I2S_CON_ENABLE(1);
|
||||
}
|
||||
|
||||
static inline void hgi2s_v0_disable(struct hgi2s_v0_hw *p_i2s) {
|
||||
p_i2s->CON &= ~ LL_I2S_CON_ENABLE(1);
|
||||
}
|
||||
|
||||
static inline void hgi2s_v0_set_tx(struct hgi2s_v0_hw *p_i2s) {
|
||||
p_i2s->CON |= LL_I2S_CON_WORKMODE(1);
|
||||
}
|
||||
|
||||
static inline void hgi2s_v0_set_rx(struct hgi2s_v0_hw *p_i2s) {
|
||||
p_i2s->CON &= ~ LL_I2S_CON_WORKMODE(1);
|
||||
}
|
||||
|
||||
static int32 hgi2s_v0_set_wsclk_pol(struct hgi2s_v0_hw *p_i2s, uint32 value) {
|
||||
|
||||
hgi2s_v0_disable(p_i2s);
|
||||
|
||||
if (value) {
|
||||
p_i2s->CON |= LL_I2S_CON_WSPOL(1);
|
||||
} else {
|
||||
p_i2s->CON &= ~ LL_I2S_CON_WSPOL(1);
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static int32 hgi2s_v0_set_sample_bits(struct hgi2s_v0_hw *p_i2s, enum i2s_sample_bits bits) {
|
||||
|
||||
int32 i2s_sample_bits_to_reg = 0;
|
||||
|
||||
i2s_sample_bits_to_reg = hgi2s_v0_switch_hal_i2s_sample_bits(bits);
|
||||
|
||||
if ((-1) == i2s_sample_bits_to_reg) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
hgi2s_v0_disable(p_i2s);
|
||||
|
||||
p_i2s->BIT_SET = i2s_sample_bits_to_reg;
|
||||
p_i2s->WS_CON = i2s_sample_bits_to_reg;
|
||||
p_i2s->BAUD = (64 / i2s_sample_bits_to_reg) - 1;
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static int32 hgi2s_v0_set_channel(struct hgi2s_v0_hw *p_i2s, enum i2s_channel channel) {
|
||||
|
||||
int32 i2s_channel_to_reg = 0;
|
||||
|
||||
i2s_channel_to_reg = hgi2s_v0_switch_hal_i2s_channel(channel);
|
||||
|
||||
if ((-1) == i2s_channel_to_reg) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
hgi2s_v0_disable(p_i2s);
|
||||
|
||||
p_i2s->CON = (p_i2s->CON &~ LL_I2S_CON_MONO(0x3)) | LL_I2S_CON_MONO(i2s_channel_to_reg);
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static int32 hgi2s_v0_set_data_fmt(struct hgi2s_v0_hw *p_i2s, enum i2s_data_fmt data_fmt) {
|
||||
|
||||
int32 i2s_data_fmt_to_reg = 0;
|
||||
|
||||
i2s_data_fmt_to_reg = hgi2s_v0_switch_hal_i2s_data_fmt(data_fmt);
|
||||
|
||||
if ((-1) == i2s_data_fmt_to_reg) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
hgi2s_v0_disable(p_i2s);
|
||||
|
||||
p_i2s->CON = (p_i2s->CON &~ LL_I2S_CON_FRMT(0x3)) | LL_I2S_CON_FRMT(i2s_data_fmt_to_reg);
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static int32 hgi2s_v0_set_debounce(struct hgi2s_v0_hw *p_i2s, uint32 enable) {
|
||||
|
||||
hgi2s_v0_disable(p_i2s);
|
||||
|
||||
if (!enable) {
|
||||
p_i2s->CON |= LL_I2S_CON_BCLKDBSBPS(1) | LL_I2S_CON_RXDBSBPS(1) | LL_I2S_CON_WSCLKDBSBPS(1);
|
||||
} else {
|
||||
p_i2s->CON &= ~(LL_I2S_CON_BCLKDBSBPS(1) | LL_I2S_CON_RXDBSBPS(1) | LL_I2S_CON_WSCLKDBSBPS(1));
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static int32 hgi2s_v0_set_duplex(struct hgi2s_v0 *dev, uint32 enable) {
|
||||
|
||||
if (enable) {
|
||||
dev->duplex_en = 1;
|
||||
} else {
|
||||
dev->duplex_en = 0;
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
/**********************************************************************************/
|
||||
/* I2S ATTCH FUNCTION */
|
||||
/**********************************************************************************/
|
||||
int32 hgi2s_v0_open(struct i2s_device *i2s, enum i2s_mode mode, enum i2s_sample_freq frequency, enum i2s_sample_bits bits)
|
||||
{
|
||||
|
||||
struct hgi2s_v0 *dev = (struct hgi2s_v0*)i2s;
|
||||
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
|
||||
const struct __iis_cfg *p_iis_cfg = NULL;
|
||||
uint32 i2s_reg_con = 0;
|
||||
int32 i2s_mode_to_reg = 0;
|
||||
int32 i2s_channel_to_reg = 0;
|
||||
int32 i2s_sample_bits_to_reg = 0;
|
||||
int32 i2s_data_fmt_to_reg = 0;
|
||||
//int32 i2s_sample_freq_to_reg = 0;
|
||||
|
||||
if (dev->opened) {
|
||||
if (!dev->dsleep) {
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/* hal enum */
|
||||
i2s_mode_to_reg = hgi2s_v0_switch_hal_i2s_mode(mode );
|
||||
i2s_channel_to_reg = hgi2s_v0_switch_hal_i2s_channel(I2S_CHANNEL_STEREO);
|
||||
i2s_data_fmt_to_reg = hgi2s_v0_switch_hal_i2s_data_fmt(I2S_DATA_FMT_I2S );
|
||||
i2s_sample_bits_to_reg = hgi2s_v0_switch_hal_i2s_sample_bits(bits );
|
||||
p_iis_cfg = hgi2s_v0_switch_hal_i2s_sample_freq(frequency,bits);
|
||||
|
||||
if (((-1) == i2s_mode_to_reg ) || \
|
||||
((-1) == i2s_channel_to_reg ) || \
|
||||
((-1) == i2s_data_fmt_to_reg ) || \
|
||||
((-1) == i2s_sample_bits_to_reg) || \
|
||||
((NULL) == p_iis_cfg)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* make sure the sys_clk */
|
||||
if (0 != ((peripheral_clock_get(HG_APB0_PT_IIS0)*2) % (i2s_sample_freq_to_reg * 256))) {
|
||||
return RET_ERR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* pin config */
|
||||
if (pin_func(dev->dev.dev.dev_id , 1) != RET_OK) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
/*
|
||||
* open I2S clk
|
||||
*/
|
||||
if (IIS0_BASE == (uint32)hw) {
|
||||
sysctrl_iis0_clk_open();
|
||||
} else if (IIS1_BASE == (uint32)hw) {
|
||||
sysctrl_iis1_clk_open();
|
||||
}
|
||||
|
||||
/*
|
||||
* clear the regs
|
||||
*/
|
||||
hw->BAUD = 0;
|
||||
hw->BIT_SET = 0;
|
||||
hw->CON = 0;
|
||||
hw->DMA_LEN = 0;
|
||||
hw->DMA_STADR = 0;
|
||||
hw->WS_CON = 0;
|
||||
hw->STA = 0xFFFF;
|
||||
|
||||
/* reg config */
|
||||
i2s_reg_con = hw->CON;
|
||||
|
||||
i2s_reg_con = LL_I2S_CON_MODE(i2s_mode_to_reg ) |
|
||||
LL_I2S_CON_MONO(i2s_channel_to_reg ) |
|
||||
LL_I2S_CON_MCLK_OE(1 ) | /* open mclk to io */
|
||||
LL_I2S_CON_WSPOL(0 ) |
|
||||
LL_I2S_CON_BCKPOL(0 ) |
|
||||
LL_I2S_CON_FRMT(i2s_data_fmt_to_reg) ;
|
||||
|
||||
if (mode == I2S_MODE_SLAVE) {
|
||||
i2s_reg_con |= (LL_I2S_CON_BCLKDBSBPS(0) | LL_I2S_CON_RXDBSBPS(0) | LL_I2S_CON_WSCLKDBSBPS(0));
|
||||
} else {
|
||||
//close debounce
|
||||
i2s_reg_con |= (LL_I2S_CON_BCLKDBSBPS(1) | LL_I2S_CON_RXDBSBPS(1) | LL_I2S_CON_WSCLKDBSBPS(1));
|
||||
}
|
||||
|
||||
hw->CON = i2s_reg_con;
|
||||
hw->WS_CON = p_iis_cfg->wscon_div;
|
||||
hw->BAUD = p_iis_cfg->baud_div;
|
||||
hw->BIT_SET = i2s_sample_bits_to_reg - 1;
|
||||
|
||||
if (mode == I2S_MODE_SLAVE) {
|
||||
hgi2s_v0_set_mclk(hw, 5);
|
||||
} else {
|
||||
hgi2s_v0_set_mclk(hw, p_iis_cfg->mclk_div);
|
||||
}
|
||||
|
||||
|
||||
dev->opened = 1;
|
||||
dev->duplex_en = 0;
|
||||
dev->dsleep = 0;
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32 hgi2s_v0_close(struct i2s_device *i2s) {
|
||||
|
||||
struct hgi2s_v0 *dev = (struct hgi2s_v0*)i2s;
|
||||
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
|
||||
|
||||
if (!dev->opened) {
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* close IIS clk
|
||||
*/
|
||||
if (IIS0_BASE == (uint32)hw) {
|
||||
sysctrl_iis0_clk_close();
|
||||
} else if (IIS1_BASE == (uint32)hw) {
|
||||
sysctrl_iis1_clk_close();
|
||||
}
|
||||
|
||||
|
||||
irq_disable(dev->irq_num );
|
||||
pin_func(dev->dev.dev.dev_id, 0);
|
||||
hgi2s_v0_disable(hw );
|
||||
|
||||
dev->opened = 0;
|
||||
dev->duplex_en = 0;
|
||||
dev->dsleep = 0;
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32 hgi2s_v0_write(struct i2s_device *i2s, const void* buf, uint32 len) {
|
||||
|
||||
struct hgi2s_v0 *dev = (struct hgi2s_v0*)i2s;
|
||||
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
|
||||
uint32 len_to_reg = 0;
|
||||
|
||||
if ((!dev->opened) || (dev->dsleep)) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
len_to_reg = len;
|
||||
|
||||
hw->DMA_STADR = (uint32)buf;
|
||||
hw->DMA_LEN = len_to_reg;
|
||||
|
||||
hgi2s_v0_set_tx(hw);
|
||||
|
||||
if (!dev->duplex_en) {
|
||||
hgi2s_v0_enable(hw);
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32 hgi2s_v0_read(struct i2s_device *i2s, void* buf, uint32 len) {
|
||||
|
||||
struct hgi2s_v0 *dev = (struct hgi2s_v0*)i2s;
|
||||
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
|
||||
uint32 len_to_reg = 0;
|
||||
|
||||
if ((!dev->opened) || (dev->dsleep)) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
len_to_reg = len;
|
||||
|
||||
hw->DMA_STADR = (uint32)buf;
|
||||
hw->DMA_LEN = len_to_reg;
|
||||
|
||||
hgi2s_v0_set_rx(hw);
|
||||
|
||||
if (!dev->duplex_en) {
|
||||
hgi2s_v0_enable(hw);
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32 hgi2s_v0_ioctl(struct i2s_device *i2s, uint32 cmd, uint32 param) {
|
||||
|
||||
int32 ret_val = RET_OK;
|
||||
struct hgi2s_v0 *dev = (struct hgi2s_v0*)i2s;
|
||||
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
|
||||
|
||||
if ((!dev->opened) || (dev->dsleep)) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
switch(cmd) {
|
||||
case (I2S_IOCTL_CMD_SET_WSCLK_POL):
|
||||
ret_val = hgi2s_v0_set_wsclk_pol(hw , param);
|
||||
break;
|
||||
case (I2S_IOCTL_CMD_SET_SAMPLE_BITS):
|
||||
ret_val = hgi2s_v0_set_sample_bits(hw, param);
|
||||
break;
|
||||
case (I2S_IOCTL_CMD_SET_CHANNEL):
|
||||
ret_val = hgi2s_v0_set_channel(hw , param);
|
||||
break;
|
||||
case (I2S_IOCTL_CMD_SET_DATA_FMT):
|
||||
ret_val = hgi2s_v0_set_data_fmt(hw , param);
|
||||
break;
|
||||
case (I2S_IOCTL_CMD_SET_DEBOUNCE):
|
||||
ret_val = hgi2s_v0_set_debounce(hw , param);
|
||||
break;
|
||||
case (I2S_IOCTL_CMD_SET_DUPLEX):
|
||||
ret_val = hgi2s_v0_set_duplex(dev , param);
|
||||
break;
|
||||
default:
|
||||
ret_val = -ENOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SLEEP
|
||||
static int32 hgi2s_v0_suspend(struct dev_obj *obj)
|
||||
{
|
||||
struct hgi2s_v0 *dev = (struct hgi2s_v0*)obj;
|
||||
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
|
||||
|
||||
if ((!dev->opened) || (dev->dsleep)) {
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
if (0 > os_mutex_lock(&dev->bp_suspend_lock, 10000)) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* Close the IIS
|
||||
*/
|
||||
hw->CON &= ~ BIT(0);
|
||||
|
||||
|
||||
pin_func(dev->dev.dev.dev_id , 0);
|
||||
|
||||
|
||||
/*
|
||||
* close irq
|
||||
*/
|
||||
irq_disable(dev->irq_num);
|
||||
|
||||
/*
|
||||
* clear pending
|
||||
*/
|
||||
hw->STA = 0xFFFFFFFF;
|
||||
|
||||
os_memset((void *)&dev->bp_regs, 0, sizeof(dev->bp_regs));
|
||||
|
||||
/*
|
||||
* save the reglist
|
||||
*/
|
||||
dev->bp_regs.con = hw->CON;
|
||||
dev->bp_regs.bit_set = hw->BIT_SET;
|
||||
dev->bp_regs.baud = hw->BAUD;
|
||||
dev->bp_regs.ws_con = hw->WS_CON;
|
||||
dev->bp_regs.dma_stadr = hw->DMA_STADR;
|
||||
dev->bp_regs.dma_len = hw->DMA_LEN;
|
||||
|
||||
/*
|
||||
* save the irq_hdl created by user
|
||||
*/
|
||||
dev->bp_irq_hdl = dev->irq_hdl;
|
||||
dev->bp_irq_data = dev->irq_data;
|
||||
|
||||
/*
|
||||
* close IIS clk
|
||||
*/
|
||||
if (IIS0_BASE == (uint32)hw) {
|
||||
sysctrl_iis0_clk_close();
|
||||
} else if (IIS1_BASE == (uint32)hw) {
|
||||
sysctrl_iis1_clk_close();
|
||||
}
|
||||
|
||||
dev->dsleep = 1;
|
||||
|
||||
os_mutex_unlock(&dev->bp_suspend_lock);
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static int32 hgi2s_v0_resume(struct dev_obj *obj)
|
||||
{
|
||||
struct hgi2s_v0 *dev = (struct hgi2s_v0*)obj;
|
||||
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
|
||||
|
||||
if ((!dev->opened) || (!dev->dsleep)) {
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
if (0 > os_mutex_lock(&dev->bp_resume_lock, 10000)) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
/* pin config */
|
||||
if (pin_func(dev->dev.dev.dev_id , 1) != RET_OK) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* open I2S clk
|
||||
*/
|
||||
if (IIS0_BASE == (uint32)hw) {
|
||||
sysctrl_iis0_clk_open();
|
||||
} else if (IIS1_BASE == (uint32)hw) {
|
||||
sysctrl_iis1_clk_open();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* recovery the reglist from sram
|
||||
*/
|
||||
hw->BIT_SET = dev->bp_regs.bit_set;
|
||||
hw->BAUD = dev->bp_regs.baud;
|
||||
hw->WS_CON = dev->bp_regs.ws_con;
|
||||
hw->DMA_STADR = dev->bp_regs.dma_stadr;
|
||||
hw->DMA_LEN = dev->bp_regs.dma_len;
|
||||
hw->CON = dev->bp_regs.con;
|
||||
|
||||
/*
|
||||
* recovery the irq handle and data
|
||||
*/
|
||||
dev->irq_hdl = dev->bp_irq_hdl;
|
||||
dev->irq_data = dev->bp_irq_data;
|
||||
|
||||
os_memset((void *)&dev->bp_regs, 0, sizeof(dev->bp_regs));
|
||||
|
||||
|
||||
/*!
|
||||
* Open the IIS
|
||||
*/
|
||||
hw->CON |= BIT(0);
|
||||
|
||||
|
||||
/*
|
||||
* open irq
|
||||
*/
|
||||
irq_enable(dev->irq_num);
|
||||
|
||||
dev->dsleep = 0;
|
||||
|
||||
os_mutex_unlock(&dev->bp_resume_lock);
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* interrupt handler */
|
||||
static void hgi2s_v0_irq_handler(void *data) {
|
||||
|
||||
struct hgi2s_v0 *dev = (struct hgi2s_v0 *)data;
|
||||
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
|
||||
|
||||
if ((hw->CON & LL_I2S_CON_HF_PEND_IE(1)) && (hw->STA & LL_I2S_STA_DMA_HF_PENGING(1))) {
|
||||
hw->STA = LL_I2S_STA_DMA_HF_PENGING(1);
|
||||
if (dev->irq_hdl) {
|
||||
dev->irq_hdl(I2S_IRQ_FLAG_HALF, dev->irq_data);
|
||||
}
|
||||
}
|
||||
|
||||
if ((hw->CON & LL_I2S_CON_OV_PEND_IE(1)) && (hw->STA & LL_I2S_STA_DMA_OV_PENGING(1))) {
|
||||
hw->STA = LL_I2S_STA_DMA_OV_PENGING(1);
|
||||
if (dev->irq_hdl) {
|
||||
dev->irq_hdl(I2S_IRQ_FLAG_FULL, dev->irq_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* request interrupt */
|
||||
int32 hgi2s_v0_request_irq(struct i2s_device *i2s, uint32 irq_flag, i2s_irq_hdl irqhdl, uint32 irq_data) {
|
||||
|
||||
struct hgi2s_v0 *dev = (struct hgi2s_v0 *)i2s;
|
||||
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
|
||||
|
||||
if ((!dev->opened) || (dev->dsleep)) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
dev->irq_hdl = irqhdl;
|
||||
dev->irq_data = irq_data;
|
||||
request_irq(dev->irq_num, hgi2s_v0_irq_handler, dev);
|
||||
|
||||
|
||||
if (irq_flag & I2S_IRQ_FLAG_HALF) {
|
||||
hw->CON |= LL_I2S_CON_HF_PEND_IE(1);
|
||||
}
|
||||
|
||||
if (irq_flag & I2S_IRQ_FLAG_FULL) {
|
||||
hw->CON |= LL_I2S_CON_OV_PEND_IE(1);
|
||||
}
|
||||
|
||||
irq_enable(dev->irq_num);
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int32 hgi2s_v0_release_irq(struct i2s_device *i2s, uint32 irq_flag) {
|
||||
|
||||
struct hgi2s_v0 *dev = (struct hgi2s_v0 *)i2s;
|
||||
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
|
||||
|
||||
if ((!dev->opened) || (dev->dsleep)) {
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
if (irq_flag & I2S_IRQ_FLAG_HALF) {
|
||||
hw->CON &= ~ LL_I2S_CON_HF_PEND_IE(1);
|
||||
}
|
||||
|
||||
if (irq_flag & I2S_IRQ_FLAG_FULL) {
|
||||
hw->CON &= ~ LL_I2S_CON_OV_PEND_IE(1);
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static const struct i2s_hal_ops i2s_v0_ops = {
|
||||
.open = hgi2s_v0_open,
|
||||
.close = hgi2s_v0_close,
|
||||
.write = hgi2s_v0_write,
|
||||
.read = hgi2s_v0_read,
|
||||
.request_irq = hgi2s_v0_request_irq,
|
||||
.release_irq = hgi2s_v0_release_irq,
|
||||
.ioctl = hgi2s_v0_ioctl,
|
||||
#ifdef CONFIG_SLEEP
|
||||
.ops.suspend = hgi2s_v0_suspend,
|
||||
.ops.resume = hgi2s_v0_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
int32 hgi2s_v0_attach(uint32 dev_id, struct hgi2s_v0 *i2s) {
|
||||
i2s->opened = 0;
|
||||
i2s->dsleep = 0;
|
||||
i2s->irq_hdl = NULL;
|
||||
i2s->irq_data = 0;
|
||||
i2s->duplex_en = 0;
|
||||
i2s->dev.dev.ops = (const struct devobj_ops *)&i2s_v0_ops;
|
||||
#ifdef CONFIG_SLEEP
|
||||
os_mutex_init(&i2s->bp_suspend_lock);
|
||||
os_mutex_init(&i2s->bp_resume_lock);
|
||||
#endif
|
||||
irq_disable(i2s->irq_num);
|
||||
dev_register(dev_id, (struct dev_obj *)i2s);
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
|
||||
124
sdk/driver/i2s/hgi2s_v0_hw.h
Normal file
124
sdk/driver/i2s/hgi2s_v0_hw.h
Normal file
@@ -0,0 +1,124 @@
|
||||
#ifndef _HGI2S_V0_HW_H
|
||||
#define _HGI2S_V0_HW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @addtogroup IIS MODULE REGISTER
|
||||
* @{
|
||||
*/
|
||||
|
||||
/***** CON Register *****/
|
||||
/*! Filter the RX data from IO
|
||||
*/
|
||||
#define LL_I2S_CON_RXDBSBPS(n) (((n)&0x01) << 14)
|
||||
/*! Filter the WSCLK clock from IO
|
||||
*/
|
||||
#define LL_I2S_CON_WSCLKDBSBPS(n) (((n)&0x01) << 13)
|
||||
/*! Filter the BCLK clock from IO
|
||||
*/
|
||||
#define LL_I2S_CON_BCLKDBSBPS(n) (((n)&0x01) << 12)
|
||||
/*! I2S work mode select
|
||||
*/
|
||||
#define LL_I2S_CON_MCLK_OE(n) (((n)&0x01) << 11)
|
||||
/*! I2S channel mode select
|
||||
*/
|
||||
#define LL_I2S_CON_OV_PEND_IE(n) (((n)&0x01) << 10)
|
||||
/*! I2S BCK clock polarity
|
||||
*/
|
||||
#define LL_I2S_CON_HF_PEND_IE(n) (((n)&0x01) << 9)
|
||||
/*! I2S WS clock polarity
|
||||
*/
|
||||
#define LL_I2S_CON_WORKMODE(n) (((n)&0x01) << 8)
|
||||
/*! sign extension function
|
||||
*/
|
||||
#define LL_I2S_CON_MONO(n) (((n)&0x03) << 6)
|
||||
/*! I2S mode select
|
||||
*/
|
||||
#define LL_I2S_CON_BCKPOL(n) (((n)&0x01) << 5)
|
||||
/*! I2S serial data format
|
||||
*/
|
||||
#define LL_I2S_CON_WSPOL(n) (((n)&0x01) << 4)
|
||||
/*! Receive channel select
|
||||
*/
|
||||
#define LL_I2S_CON_MODE(n) (((n)&0x01) << 3)
|
||||
/*! Transmit channel select
|
||||
*/
|
||||
#define LL_I2S_CON_FRMT(n) (((n)&0x03) << 1)
|
||||
/*! I2S enable
|
||||
*/
|
||||
#define LL_I2S_CON_ENABLE(n) (((n)&0x01) << 0)
|
||||
|
||||
|
||||
|
||||
/***** BIT_SET Register *****/
|
||||
/*! I2S bit set
|
||||
*/
|
||||
#define LL_I2S_BIT_SET_IISBIT(n) (((n)&0x1F) << 0)
|
||||
|
||||
|
||||
/***** BUAD Register *****/
|
||||
/*! I2S baud set
|
||||
*/
|
||||
#define LL_I2S_BAUD_SET_BUAD(n) (((n)&0x3F) << 0)
|
||||
|
||||
|
||||
/***** WSCON Register *****/
|
||||
/*! I2S wscon set
|
||||
*/
|
||||
#define LL_I2S_WSCON_SET_WSCON(n) (((n)&0x3F) << 0)
|
||||
|
||||
|
||||
/***** STA Register *****/
|
||||
/*! I2S DMA data over pending
|
||||
*/
|
||||
#define LL_I2S_STA_DMA_OV_PENGING(n) (((n)&0x01) << 5)
|
||||
/*! I2S DMA data half pending
|
||||
*/
|
||||
#define LL_I2S_STA_DMA_HF_PENGING(n) (((n)&0x01) << 4)
|
||||
/*! I2S transmit done pending
|
||||
*/
|
||||
#define LL_I2S_STA_DONE_PENGING(n) (((n)&0x01) << 3)
|
||||
/*! I2S work state pending
|
||||
*/
|
||||
#define LL_I2S_STA_WORK_STATE_PENGING(n) (((n)&0x01) << 2)
|
||||
/*! I2S fifo write full pending
|
||||
*/
|
||||
#define LL_I2S_STA_FIFO_WFULL_PENGING(n) (((n)&0x01) << 1)
|
||||
/*! I2S fifo read empty pending
|
||||
*/
|
||||
#define LL_I2S_STA_FIFO_REMPTY_PENGING(n) (((n)&0x01) << 0)
|
||||
|
||||
/***** STADR0 Register *****/
|
||||
/*! I2S DMA address config
|
||||
*/
|
||||
#define LL_I2S_STADR_DMA_ADDR0(n) (((n)&0xFFFFFFFF) << 0)
|
||||
|
||||
/***** DMALEN Register *****/
|
||||
/*! I2S DMA len config
|
||||
*/
|
||||
#define LL_I2S_DMALEN_LEN(n) (((n)&0xFFFF) << 0)
|
||||
|
||||
|
||||
|
||||
/** @brief I2S register structure
|
||||
* @{
|
||||
*/
|
||||
struct hgi2s_v0_hw {
|
||||
__IO uint32_t CON;
|
||||
__IO uint32_t BIT_SET;
|
||||
__IO uint32_t BAUD;
|
||||
__IO uint32_t WS_CON;
|
||||
__IO uint32_t STA;
|
||||
__IO uint32_t DMA_STADR;
|
||||
__IO uint32_t RESERVE;
|
||||
__IO uint32_t DMA_LEN;
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _HGI2S_V0_HW_H */
|
||||
Reference in New Issue
Block a user