ameba-sdk-gcc-make/component/common/mbed/targets/hal/rtl8195a/i2s_api.c

249 lines
8.8 KiB
C
Raw Permalink Normal View History

/* mbed Microcontroller Library
*******************************************************************************
* Copyright (c) 2015, Realtek Semiconductor Corp.
* All rights reserved.
*
* This module is a confidential and proprietary property of RealTek and
* possession or use of this module requires written permission of RealTek.
*******************************************************************************
*/
#include "objects.h"
#include "i2s_api.h"
#include "pinmap.h"
#if CONFIG_I2S_EN
static const PinMap PinMap_I2S_TX[] = {
{PE_2, RTL_PIN_PERI(I2S0, 0, S0), RTL_PIN_FUNC(I2S0, S0)},
{PH_2, RTL_PIN_PERI(I2S0, 0, S1), RTL_PIN_FUNC(I2S0, S1)},
{PD_2, RTL_PIN_PERI(I2S0, 0, S2), RTL_PIN_FUNC(I2S0, S2)},
{PC_7, RTL_PIN_PERI(I2S0, 0, S3), RTL_PIN_FUNC(I2S0, S3)},
{PC_2, RTL_PIN_PERI(I2S1, 1, S0), RTL_PIN_FUNC(I2S1, S0)},
{PD_6, RTL_PIN_PERI(I2S1, 1, S1), RTL_PIN_FUNC(I2S1, S1)},
{PE_6, RTL_PIN_PERI(I2S1, 1, S2), RTL_PIN_FUNC(I2S1, S2)},
{NC, NC, 0}
};
static const PinMap PinMap_I2S_RX[] = {
{PH_5, RTL_PIN_PERI(I2S0, 0, S1), RTL_PIN_FUNC(I2S0, S1)},
{PC_5, RTL_PIN_PERI(I2S0, 0, S3), RTL_PIN_FUNC(I2S0, S3)},
{PC_4, RTL_PIN_PERI(I2S1, 1, S0), RTL_PIN_FUNC(I2S1, S0)},
{PD_3, RTL_PIN_PERI(I2S1, 1, S1), RTL_PIN_FUNC(I2S1, S1)},
{PE_8, RTL_PIN_PERI(I2S1, 1, S2), RTL_PIN_FUNC(I2S1, S1)},
{NC, NC, 0}
};
static const PinMap PinMap_I2S_CLK[] = {
{PE_1, RTL_PIN_PERI(I2S0, 0, S0), RTL_PIN_FUNC(I2S0, S0)},
{PH_1, RTL_PIN_PERI(I2S0, 0, S1), RTL_PIN_FUNC(I2S0, S1)},
{PD_1, RTL_PIN_PERI(I2S0, 0, S2), RTL_PIN_FUNC(I2S0, S2)},
{PC_8, RTL_PIN_PERI(I2S0, 0, S3), RTL_PIN_FUNC(I2S0, S3)},
{PC_1, RTL_PIN_PERI(I2S1, 1, S0), RTL_PIN_FUNC(I2S1, S0)},
{PD_5, RTL_PIN_PERI(I2S1, 1, S1), RTL_PIN_FUNC(I2S1, S1)},
{PE_5, RTL_PIN_PERI(I2S1, 1, S2), RTL_PIN_FUNC(I2S1, S2)},
{NC, NC, 0}
};
static const PinMap PinMap_I2S_WS[] = {
{PE_0, RTL_PIN_PERI(I2S0, 0, S0), RTL_PIN_FUNC(I2S0, S0)},
{PH_0, RTL_PIN_PERI(I2S0, 0, S1), RTL_PIN_FUNC(I2S0, S1)},
{PD_0, RTL_PIN_PERI(I2S0, 0, S2), RTL_PIN_FUNC(I2S0, S2)},
{PC_9, RTL_PIN_PERI(I2S0, 0, S3), RTL_PIN_FUNC(I2S0, S3)},
{PC_0, RTL_PIN_PERI(I2S1, 1, S0), RTL_PIN_FUNC(I2S1, S0)},
{PD_4, RTL_PIN_PERI(I2S1, 1, S1), RTL_PIN_FUNC(I2S1, S1)},
{PE_4, RTL_PIN_PERI(I2S1, 1, S2), RTL_PIN_FUNC(I2S1, S2)},
{NC, NC, 0}
};
static const HAL_I2S_DEF_SETTING I2SDefaultSetting = {
.I2SMaster = I2S_MASTER_MODE, // I2S Function Mode
.DevSts = I2S_STS_UNINITIAL, //I2S device status
.I2SChNum = I2S_CH_STEREO, //I2S Channel number mono or stereo
.I2SPageNum = I2S_4PAGE, //I2S Page number 2~4
.I2STRxAct = I2S_TXRX, //I2S tx rx act, tx only or rx only or tx+rx
.I2SWordLen = I2S_WL_16, //I2S Word length 16bit or 24bit
.I2SPageSize = (768/4)-1, //I2S Page size 1~4096 word
.I2SRate = I2S_SR_48KHZ, //I2S sample rate 8k ~ 96khz
.I2STxIntrMSK = I2S_TX_INT_PAGE0_OK|I2S_TX_INT_PAGE1_OK| \
I2S_TX_INT_PAGE2_OK|I2S_TX_INT_PAGE3_OK, /*I2S Tx Interrupt Mask*/
.I2SRxIntrMSK = I2S_RX_INT_PAGE0_OK|I2S_RX_INT_PAGE1_OK| \
I2S_RX_INT_PAGE2_OK|I2S_RX_INT_PAGE3_OK /*I2S Rx Interrupt Mask*/
};
void i2s_init(i2s_t *obj, PinName sck, PinName ws, PinName sd)
{
uint32_t i2s_sck, i2s_ws, i2s_tx, i2s_rx;
uint32_t i2s_sck_ws, i2s_sel;;
uint8_t i2s_idx;
PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter;
u8 trx_act;
// Determine the UART to use (UART0, UART1, or UART3)
i2s_sck = pinmap_peripheral(sck, PinMap_I2S_CLK);
i2s_ws = pinmap_peripheral(ws, PinMap_I2S_WS);
i2s_tx = pinmap_peripheral(sd, PinMap_I2S_TX);
i2s_rx = pinmap_peripheral(sd, PinMap_I2S_RX);
i2s_sck_ws = pinmap_merge(i2s_sck, i2s_ws);
if (unlikely(i2s_sck_ws == NC)) {
DBG_I2S_ERR("%s: Cannot find matched I2S for given pin\n", __FUNCTION__);
return;
}
trx_act = I2S_TXRX;
i2s_sel = pinmap_merge(i2s_sck_ws, i2s_tx);
if (i2s_sel == NC) {
i2s_sel = pinmap_merge(i2s_sck_ws, i2s_rx);
trx_act = I2S_ONLY_RX;
if (unlikely(i2s_sel == NC)) {
DBG_I2S_ERR("%s: Cannot find matched I2S for given pin\n", __FUNCTION__);
return;
}
}
i2s_idx = RTL_GET_PERI_IDX(i2s_sel);
pI2SAdapter->DevNum = i2s_idx;
pI2SAdapter->PinMux = RTL_GET_PERI_SEL(i2s_sel);;
DBG_I2S_INFO("%s: Use I2S%d Sel%d\r\n", __FUNCTION__, pI2SAdapter->DevNum, pI2SAdapter->PinMux);
pI2SAdapter->pInitDat = &obj->InitDat;
RtkI2SLoadDefault(pI2SAdapter, (VOID*)&I2SDefaultSetting);
pI2SAdapter->pInitDat->I2STRxAct = trx_act;
// Load user defined parameters
pI2SAdapter->pInitDat->I2SChNum = obj->channel_num;
pI2SAdapter->pInitDat->I2SRate = obj->sampling_rate;
pI2SAdapter->pInitDat->I2SWordLen = obj->word_length;
pI2SAdapter->pInitDat->I2STRxAct = obj->direction;
//RtkI2SInit(pI2SAdapter);
HalI2SInit(pI2SAdapter);
}
void i2s_set_dma_buffer(i2s_t *obj, char *tx_buf, char *rx_buf,
uint32_t page_num, uint32_t page_size)
{
PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter;
u32 i;
if ((page_num < 2) || (page_num > 4) || (page_size < 8)) {
DBG_I2S_INFO("%s: PageNum(%d) valid value is 2~4; PageSize(%d must > 8)\r\n", \
__FUNCTION__, page_num, page_size);
return;
}
pI2SAdapter->pInitDat->I2SPageNum = page_num - 1;
pI2SAdapter->pInitDat->I2SPageSize = page_size/4 - 1; // unit is 4-bytes
pI2SAdapter->pInitDat->I2STxData = (u8*)tx_buf;
pI2SAdapter->pInitDat->I2SRxData = (u8*)rx_buf;
HalI2SSetDMABuf(pI2SAdapter->pInitDat);
for (i=0;i<page_num;i++) {
pI2SAdapter->TxPageList[i] = (uint32_t*)(tx_buf + ((page_size) * i));
pI2SAdapter->RxPageList[i] = (uint32_t*)(rx_buf + ((page_size) * i));
}
}
void i2s_tx_irq_handler(i2s_t *obj, i2s_irq_handler handler, uint32_t id)
{
PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter;
pI2SAdapter->UserCB.TxCCB = handler;
pI2SAdapter->UserCB.TxCBId = id;
}
void i2s_rx_irq_handler(i2s_t *obj, i2s_irq_handler handler, uint32_t id)
{
PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter;
pI2SAdapter->UserCB.RxCCB = handler;
pI2SAdapter->UserCB.RxCBId = id;
}
void i2s_set_direction(i2s_t *obj, int trx_type)
{
PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter;
obj->direction = trx_type;
pI2SAdapter->pInitDat->I2STRxAct = trx_type;
HalI2SSetDirection(pI2SAdapter->pInitDat);
}
void i2s_set_param(i2s_t *obj, int channel_num, int rate, int word_len)
{
PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter;
obj->channel_num = channel_num;
obj->sampling_rate = rate;
obj->word_length = word_len;
pI2SAdapter->pInitDat->I2SChNum = channel_num;
pI2SAdapter->pInitDat->I2SRate = rate;
pI2SAdapter->pInitDat->I2SWordLen = word_len;
HalI2SSetChNum(pI2SAdapter->pInitDat);
HalI2SSetRate(pI2SAdapter->pInitDat);
HalI2SSetWordLen(pI2SAdapter->pInitDat);
}
void i2s_deinit(i2s_t *obj)
{
//RtkI2SDeInit((VOID*)&obj->I2SAdapter);
HalI2SDeInit((VOID*)&obj->I2SAdapter);
}
int* i2s_get_tx_page(i2s_t *obj)
{
PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter;
u8 page_idx;
page_idx = HalI2SGetTxPage((VOID*)pI2SAdapter->pInitDat);
if (page_idx <= pI2SAdapter->pInitDat->I2SPageNum) {
return ((int*)pI2SAdapter->TxPageList[page_idx]);
} else {
return NULL;
}
}
void i2s_send_page(i2s_t *obj, uint32_t *pbuf)
{
PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter;
u32 page_num, i;
page_num = pI2SAdapter->pInitDat->I2SPageNum + 1;
for (i=0;i<page_num;i++) {
if (pI2SAdapter->TxPageList[i] == pbuf) {
HalI2SPageSend(pI2SAdapter->pInitDat, i);
break; // break the for loop
}
}
if (i == page_num) {
DBG_I2S_ERR("i2s_send_page: the pbuf(0x%x) is not a DMA buffer\r\n", pbuf);
}
}
void i2s_recv_page(i2s_t *obj)
{
PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter;
HalI2SPageRecv(pI2SAdapter->pInitDat);
}
void i2s_enable(i2s_t *obj)
{
PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter;
//RtkI2SEnable(pI2SAdapter);
HalI2SEnable(pI2SAdapter);
}
void i2s_disable(i2s_t *obj)
{
PHAL_I2S_ADAPTER pI2SAdapter = (PHAL_I2S_ADAPTER) &obj->I2SAdapter;
//RtkI2SDisable(pI2SAdapter);
HalI2SDisable(pI2SAdapter);
}
#endif // end of "#if CONFIG_I2S_EN"