pinebuds/platform/hal/hal_btpcm.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