204 lines
5.4 KiB
C
204 lines
5.4 KiB
C
/***************************************************************************
|
|
*
|
|
* Copyright 2015-2019 BES.
|
|
* All rights reserved. All unpublished rights reserved.
|
|
*
|
|
* No part of this work may be used or reproduced in any form or by any
|
|
* means, or stored in a database or retrieval system, without prior written
|
|
* permission of BES.
|
|
*
|
|
* Use of this work is governed by a license granted by BES.
|
|
* This work contains confidential and proprietary information of
|
|
* BES. which is protected by copyright, trade secret,
|
|
* trademark and other intellectual property rights.
|
|
*
|
|
****************************************************************************/
|
|
#include "plat_addr_map.h"
|
|
|
|
#ifdef BTPCM_BASE
|
|
|
|
#include "hal_btpcm.h"
|
|
#include "hal_btpcmip.h"
|
|
#include "hal_cmu.h"
|
|
#include "hal_timer.h"
|
|
#include "hal_trace.h"
|
|
#include "hal_uart.h"
|
|
#include "plat_types.h"
|
|
#include "reg_btpcmip.h"
|
|
|
|
//#define BTPCM_CLOCK_SOURCE 240000000
|
|
#define BTPCM_CLOCK_SOURCE 22579200
|
|
//#define BTPCM_CLOCK_SOURCE 48000000
|
|
//#define BTPCM_CLOCK_SOURCE 3072000
|
|
|
|
//#define BTPCM_CLOCK_SOURCE 76800000
|
|
//#define BTPCM_CLOCK_SOURCE 84672000
|
|
|
|
//#define HAL_BTPCM_TX_FIFO_TRIGGER_LEVEL (BTPCMIP_FIFO_DEPTH/2)
|
|
//#define HAL_BTPCM_RX_FIFO_TRIGGER_LEVEL (BTPCMIP_FIFO_DEPTH/2)
|
|
|
|
#define HAL_BTPCM_TX_FIFO_TRIGGER_LEVEL (1)
|
|
#define HAL_BTPCM_RX_FIFO_TRIGGER_LEVEL (0)
|
|
|
|
#define HAL_BTPCM_YES 1
|
|
#define HAL_BTPCM_NO 0
|
|
|
|
static const char *const invalid_id = "Invalid BTPCM ID: %d\n";
|
|
// static const char * const invalid_ch = "Invalid BTPCM CH: %d\n";
|
|
|
|
static bool btpcm_opened[HAL_BTPCM_ID_NUM][AUD_STREAM_NUM];
|
|
|
|
static inline POSSIBLY_UNUSED unsigned char reverse(unsigned char in) {
|
|
uint8_t out = 0;
|
|
uint32_t i = 0;
|
|
for (i = 0; i < 8; ++i) {
|
|
if ((1 << i & in))
|
|
out = out | (1 << (7 - i));
|
|
else
|
|
out = out & (~(1 << (7 - i)));
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
static inline uint32_t _btpcm_get_reg_base(enum HAL_BTPCM_ID_T id) {
|
|
ASSERT(id < HAL_BTPCM_ID_NUM, invalid_id, id);
|
|
|
|
switch (id) {
|
|
case HAL_BTPCM_ID_0:
|
|
default:
|
|
return BTPCM_BASE;
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int hal_btpcm_open(enum HAL_BTPCM_ID_T id, enum AUD_STREAM_T stream) {
|
|
uint32_t reg_base;
|
|
|
|
reg_base = _btpcm_get_reg_base(id);
|
|
|
|
if (!btpcm_opened[id][AUD_STREAM_PLAYBACK] &&
|
|
!btpcm_opened[id][AUD_STREAM_CAPTURE]) {
|
|
// Init to slave mode before enabling module clock
|
|
// Make sure the clock mux is switched when there is no clock active
|
|
hal_cmu_pcm_set_slave_mode(true);
|
|
hal_cmu_pcm_clock_enable();
|
|
|
|
hal_cmu_clock_enable(HAL_CMU_MOD_O_PCM);
|
|
hal_cmu_clock_enable(HAL_CMU_MOD_P_PCM);
|
|
hal_cmu_reset_clear(HAL_CMU_MOD_O_PCM);
|
|
hal_cmu_reset_clear(HAL_CMU_MOD_P_PCM);
|
|
|
|
// After release pclk reset, need delay 2 tick to access any pcm reg.
|
|
hal_sys_timer_delay(2);
|
|
btpcmip_pcm_clk_open_en(reg_base, 0);
|
|
|
|
btpcmip_w_enable_rx_dma(reg_base, HAL_BTPCM_NO);
|
|
btpcmip_w_enable_tx_dma(reg_base, HAL_BTPCM_NO);
|
|
|
|
btpcmip_flush_tx_fifo(reg_base);
|
|
btpcmip_flush_rx_fifo(reg_base);
|
|
|
|
btpcmip_w_slot_sel(reg_base, 0);
|
|
btpcmip_w_shortsync(reg_base, HAL_BTPCM_YES);
|
|
btpcmip_w_signin(reg_base, HAL_BTPCM_YES);
|
|
btpcmip_w_mask1mask2(reg_base, 0);
|
|
btpcmip_w_enable_btpcmip(reg_base, HAL_BTPCM_YES);
|
|
|
|
// Generate 10 clock cycles for BTPCM module to initialize its states
|
|
for (int i = 0; i < 10; i++) {
|
|
hal_cmu_pcm_set_slave_mode(false);
|
|
hal_cmu_pcm_set_slave_mode(true);
|
|
}
|
|
|
|
// btpcmip_w_length(reg_base, 0x05); //16 bit
|
|
}
|
|
|
|
btpcm_opened[id][stream] = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int hal_btpcm_close(enum HAL_BTPCM_ID_T id, enum AUD_STREAM_T stream) {
|
|
uint32_t reg_base;
|
|
|
|
reg_base = _btpcm_get_reg_base(id);
|
|
|
|
btpcm_opened[id][stream] = false;
|
|
|
|
if (!btpcm_opened[id][AUD_STREAM_PLAYBACK] &&
|
|
!btpcm_opened[id][AUD_STREAM_CAPTURE]) {
|
|
btpcmip_w_enable_btpcmip(reg_base, HAL_BTPCM_NO);
|
|
|
|
// don't need flush rx and tx fifo
|
|
|
|
hal_cmu_reset_set(HAL_CMU_MOD_P_PCM);
|
|
hal_cmu_reset_set(HAL_CMU_MOD_O_PCM);
|
|
hal_cmu_clock_disable(HAL_CMU_MOD_P_PCM);
|
|
hal_cmu_clock_disable(HAL_CMU_MOD_O_PCM);
|
|
hal_cmu_pcm_clock_disable();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int hal_btpcm_start_stream(enum HAL_BTPCM_ID_T id, enum AUD_STREAM_T stream) {
|
|
return 0;
|
|
}
|
|
|
|
int hal_btpcm_stop_stream(enum HAL_BTPCM_ID_T id, enum AUD_STREAM_T stream) {
|
|
return 0;
|
|
}
|
|
|
|
int hal_btpcm_setup_stream(enum HAL_BTPCM_ID_T id, enum AUD_STREAM_T stream,
|
|
struct HAL_BTPCM_CONFIG_T *cfg) {
|
|
uint32_t reg_base;
|
|
|
|
reg_base = _btpcm_get_reg_base(id);
|
|
|
|
if (!btpcm_opened[id][stream]) {
|
|
return 1;
|
|
}
|
|
|
|
if (stream == AUD_STREAM_PLAYBACK) {
|
|
// dma config
|
|
btpcmip_w_tx_fifo_threshold(reg_base, HAL_BTPCM_TX_FIFO_TRIGGER_LEVEL);
|
|
btpcmip_w_enable_tx_dma(reg_base, HAL_BTPCM_YES);
|
|
} else {
|
|
// dma config
|
|
btpcmip_w_rx_fifo_threshold(reg_base, HAL_BTPCM_RX_FIFO_TRIGGER_LEVEL);
|
|
btpcmip_w_enable_rx_dma(reg_base, HAL_BTPCM_YES);
|
|
}
|
|
|
|
// hal_sys_timer_delay(2);
|
|
|
|
btpcmip_pcm_clk_open_en(reg_base, 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int hal_btpcm_send(enum HAL_BTPCM_ID_T id, uint8_t *value, uint32_t value_len) {
|
|
uint32_t i = 0;
|
|
uint32_t reg_base;
|
|
|
|
reg_base = _btpcm_get_reg_base(id);
|
|
|
|
for (i = 0; i < value_len; i += 4) {
|
|
while (!(btpcmip_r_int_status(reg_base) &
|
|
BTPCMIP_INT_STATUS_TX_FIFO_EMPTY_MASK))
|
|
;
|
|
|
|
btpcmip_w_tx_fifo(reg_base, value[i + 1] << 8 | value[i]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
uint8_t hal_btpcm_recv(enum HAL_BTPCM_ID_T id, uint8_t *value,
|
|
uint32_t value_len) {
|
|
ASSERT(id < HAL_BTPCM_ID_NUM, invalid_id, id);
|
|
return 0;
|
|
}
|
|
|
|
#endif
|