You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1169 lines
34 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd.. 2020-2020. All rights reserved.
* Description: baseparam database operation function
* Author: Hisilicon
* Create: 2020-4-6
*/
#include "drv_pdm.h"
#include "drv_pdm_ext.h"
#include "db_ext.h"
#include "osal_ext.h"
#include "drv_mbx_ext.h"
#include "osal_list.h"
#include "drv_sys_ext.h"
#include "soc_errno.h"
#include "securec.h"
typedef enum {
MBX_READ_TRNG = 0x4B3C2D1E,
MBX_LOAD_TEE = 0x4B3C2D2D,
MBX_LOAD_HRF = 0x4B3C2D3C,
MBX_LOAD_TPP = 0x4B3C2D4B,
MBX_LOAD_ADSP = 0x4B3C2D5A,
MBX_UNLOAD_ADSP = 0x4B3C2D6B,
MBX_SET_BL33 = 0x4B352D6B,
MBX_LOAD_LICENSE = 0x4B3C2D69,
MBX_ACK_MSG = 0x4B3CD22F,
} mailbox_cmd;
typedef enum {
MBX_ACK_SUCCESS = 0x4B3CD296,
MBX_ACK_FAILURE = 0xB4C37D5A,
} mailbox_ret;
typedef struct {
td_u32 cmd;
td_u32 len; /* length of struct */
td_u32 low_addr;
td_u32 high_addr;
} mbx_params;
typedef struct {
td_u32 cmd;
td_u32 result;
} mbx_ack;
typedef struct {
td_u32 index;
td_u32 offset;
td_u32 size;
} tcon_check_param;
#define PDM_DISP_BRIGHTNESS_DEFAULT 50
#define PDM_DISP_CONTRAST_DEFAULT 50
#define PDM_DISP_SATURATION_DEFAULT 50
#define PDM_DISP_HUE_PLUS_DEFAULT 50
#define PDM_DISP_SCREEN_WIDTH_DEFAULT 1280
#define PDM_DISP_SCREEN_HEIGHT_DEFAULT 720
#define PDM_DISP_SCREEN_MAX 3840
#define PDM_DISP_SCREEN_MIN 480
#define PDM_DISP_OFFSET_VALUE 3840
#define PDM_VOLUME_MAX_VAL 100
#define PDM_VOLUME_DEFAULT_VAL 50
#define PDM_TAG_MAX_LEN 512
#define PDM_MCE_BASE_KEYNAME_LEN 32
#define PDM_INVALID_INTERFACE 0xffffffff
#define PDM_AUD_SINGLE_PORT_MAX_NUM 4
#define LOW_16_BIT_MASK 0xffff
#define LOW_32_BIT_MASK 0xffffffff
#define PDM_MBX_TIMEOUT 100000
#define PDM_FHD_WIDTH 1920
#define PDM_FHD_HEIGHT 1080
#define PDM_MODULE_MAX_NUM 24
#define PDM_CALL_BACK_MAX_NUM 2
#define PDM_CONFIG_INFO_OFFSET 0x420
#define PDM_TA_REVOKED_LIST_OFFSET (32*1024)
#define PDM_TA_REVOKED_SIZE (32*1024)
#define drv_pdm_lock(mutex) \
do { \
if (osal_sem_down_interruptible(mutex)) \
{ \
soc_log_err("ERR: pdm lock error!\n"); \
} \
} while (0)
#define drv_pdm_unlock(mutex) \
do { \
osal_sem_up(mutex); \
} while (0)
#define PDM_KEYNAME_LEN 32
#define PDM_MUTE_WAKEUP_ENABLE 0xA5A55A5A
#define PDM_MUTE_WAKEUP_DISABLE 0x5A5AA5A5
#define PDM_TMP_NAME_BUF_SIZE 32
static const td_u32 g_polynomial = 0xEDB88320;
pdm_silence_cfg_info g_pdm_ext_modules[PDM_MODULE_MAX_NUM] = {0};
static td_bool g_is_silence_init = TD_FALSE;
td_s32 pdm_get_buf_by_name(const td_char *buf_name, td_u8 **base_phy_addr, td_u32 *len)
{
td_s32 i;
if (strlen(buf_name) == 0) {
soc_log_err("ptr is null!\n");
return TD_FAILURE;
}
for (i = 0; i < g_pdm_global.buf_num; i++) {
if (osal_strncmp(g_pdm_global.buf_info[i].buf_name, buf_name, strlen(buf_name)) == 0) {
break;
}
}
if (i >= g_pdm_global.buf_num) {
return TD_FAILURE;
}
*base_phy_addr = g_pdm_global.buf_info[i].phy_addr;
*len = g_pdm_global.buf_info[i].lenth;
return TD_SUCCESS;
}
static td_s32 pdm_find_buffer_name(const td_char *buf_name, td_u32 *index)
{
td_u32 i;
if (strlen(buf_name) == 0) {
soc_log_err("ptr is null!\n");
return TD_FAILURE;
}
for (i = 0; i < g_pdm_global.buf_num; i++) {
if (osal_strncmp(g_pdm_global.buf_info[i].buf_name, buf_name, strlen(buf_name)) == 0) {
if (g_pdm_global.buf_info[i].release == TD_FALSE)
break;
}
}
if (i >= g_pdm_global.buf_num) {
soc_log_info("can not find buffer:%s\n", buf_name);
return TD_FAILURE;
}
*index = i;
return TD_SUCCESS;
}
td_s32 pdm_set_vir_addr_by_name(const td_char *buf_name, td_u8 *vir_addr)
{
td_u32 i = 0;
td_s32 ret;
drv_pdm_lock(&g_pdm_global.pdm_mutex);
ret = pdm_find_buffer_name(buf_name, &i);
if (ret != TD_SUCCESS) {
drv_pdm_unlock(&g_pdm_global.pdm_mutex);
return ret;
}
g_pdm_global.buf_info[i].vir_addr = vir_addr;
drv_pdm_unlock(&g_pdm_global.pdm_mutex);
return TD_SUCCESS;
}
td_s32 pdm_get_vir_addr_by_name(const td_char *buf_name, td_u8 **vir_addr, td_u32 *len)
{
td_u32 i = 0;
td_s32 ret;
drv_pdm_lock(&g_pdm_global.pdm_mutex);
ret = pdm_find_buffer_name(buf_name, &i);
if (ret != TD_SUCCESS) {
drv_pdm_unlock(&g_pdm_global.pdm_mutex);
return ret;
}
if (g_pdm_global.buf_info[i].vir_addr == TD_NULL) {
*vir_addr = TD_NULL;
*len = 0;
drv_pdm_unlock(&g_pdm_global.pdm_mutex);
return TD_FAILURE;
}
*vir_addr = g_pdm_global.buf_info[i].vir_addr;
*len = g_pdm_global.buf_info[i].lenth;
drv_pdm_unlock(&g_pdm_global.pdm_mutex);
return TD_SUCCESS;
}
td_s32 drv_pdm_get_data(const td_char *buf_name, td_u8 **data_addr, td_u32 *data_len)
{
td_s32 ret;
td_u8 *phy_addr = TD_NULL;
if ((buf_name != TD_NULL) &&
(data_addr != TD_NULL) &&
(data_len != TD_NULL)) {
if ((pdm_get_vir_addr_by_name(buf_name, data_addr, data_len) != TD_SUCCESS) ||
(*data_addr == TD_NULL)) {
ret = pdm_get_buf_by_name(buf_name, &phy_addr, data_len);
if (ret != TD_SUCCESS) {
return ret;
}
*data_addr = osal_blockmem_vmap((td_ulong)(uintptr_t)phy_addr, *data_len);
return pdm_set_vir_addr_by_name(buf_name, *data_addr);
} else {
return TD_SUCCESS;
}
} else {
return TD_FAILURE;
}
}
td_s32 drv_pdm_release_reserve_mem(const td_char *buf_name)
{
td_u32 i = 0;
td_s32 ret;
drv_pdm_lock(&g_pdm_global.pdm_mutex);
ret = pdm_find_buffer_name(buf_name, &i);
if (ret != TD_SUCCESS) {
drv_pdm_unlock(&g_pdm_global.pdm_mutex);
return ret;
}
if (g_pdm_global.buf_info[i].release) {
drv_pdm_unlock(&g_pdm_global.pdm_mutex);
return TD_SUCCESS;
}
g_pdm_global.buf_info[i].release = TD_TRUE;
if (g_pdm_global.buf_info[i].vir_addr != TD_NULL) {
osal_blockmem_vunmap((td_u8 *)(g_pdm_global.buf_info[i].vir_addr));
g_pdm_global.buf_info[i].vir_addr = TD_NULL;
}
drv_pdm_unlock(&g_pdm_global.pdm_mutex);
/*
* this function maybe block, can not lock
* for 64bit system, function first para must be merge to 64 bit, cant td_u32 type
*/
osal_blockmem_free((uintptr_t)g_pdm_global.buf_info[i].phy_addr, g_pdm_global.buf_info[i].lenth);
/* notice:the saved tag info in dts hasn't been updated, still the original one */
return TD_SUCCESS;
}
static td_s32 drv_pdm_get_reserve_mem(const td_char *buf_name, td_u64 *resever_addr,
td_u32 *resever_buf_size)
{
td_u32 buf_index = 0;
td_s32 ret;
drv_pdm_lock(&g_pdm_global.pdm_mutex);
ret = pdm_find_buffer_name(buf_name, &buf_index);
if (ret != TD_SUCCESS) {
drv_pdm_unlock(&g_pdm_global.pdm_mutex);
return ret;
}
if (g_pdm_global.buf_info[buf_index].release) {
drv_pdm_unlock(&g_pdm_global.pdm_mutex);
return TD_SUCCESS;
}
drv_pdm_unlock(&g_pdm_global.pdm_mutex);
*resever_addr = (phys_addr_t)(uintptr_t)g_pdm_global.buf_info[buf_index].phy_addr;
*resever_buf_size = g_pdm_global.buf_info[buf_index].lenth;
return TD_SUCCESS;
}
td_s32 drv_pdm_set_license_data(td_u64 lic_mmz_handle, td_u32 lic_len)
{
td_u8 *lic_dma_addr = TD_NULL;
td_u64 lic_phy_addr;
td_s32 mbx_handle;
td_s32 ret;
mbx_params send_param = {0};
td_u32 tx_len = 0;
td_u32 rx_len = 0;
ext_chip_name_id chip_name_id;
td_u8 rx_buf[20] = {0}; /* 20 bytes makes room enough */
mbx_ack rcv_mbx = {0};
ext_drv_sys_get_chip_name_id(&chip_name_id);
lic_dma_addr = osal_mem_handle_get((long)lic_mmz_handle, SOC_ID_PDM);
if (lic_dma_addr == TD_NULL) {
soc_log_err("cannot get mmz dma addr\n");
return TD_FAILURE;
}
lic_phy_addr = (td_ulong)osal_mem_phys(lic_dma_addr);
if (lic_phy_addr == 0) {
soc_log_err("cannot get mmz phy addr\n");
ret = TD_FAILURE;
goto free_ref;
}
mbx_handle = ext_drv_mbx_open(EXT_MBX_ACPU2HRF_BOOT);
if (mbx_handle < 0) {
soc_log_err("cannot open mbx\n");
ret = TD_FAILURE;
goto free_ref;
}
send_param.cmd = MBX_LOAD_LICENSE;
send_param.high_addr = (td_u32)((lic_phy_addr >> 32) & LOW_32_BIT_MASK); /* R shift 32bits to get high addr */
send_param.low_addr = (td_u32)(lic_phy_addr & LOW_32_BIT_MASK);
send_param.len = lic_len;
ret = ext_drv_mbx_tx(mbx_handle, (td_void *)&send_param, sizeof(send_param), &tx_len, PDM_MBX_TIMEOUT);
if (ret != TD_SUCCESS) {
soc_log_err("cannot send mbx : %x\n", ret);
goto free_ref;
}
ret = ext_drv_mbx_rx(mbx_handle, rx_buf, sizeof(mbx_ack), &rx_len, PDM_MBX_TIMEOUT);
if (ret != TD_SUCCESS) {
soc_log_err("cannot recive mbx : %x\n", ret);
goto free_ref;
}
ret = ext_drv_mbx_close(mbx_handle);
if (ret < 0) {
soc_log_err("cannot close mbx:%x\n", ret);
goto free_ref;
}
ret = memcpy_s(&rcv_mbx, sizeof(rcv_mbx), rx_buf, rx_len);
if (ret != EOK) {
soc_log_err("cannot cpy mbx data: %x\n", ret);
goto free_ref;
}
if (chip_name_id == CHIP_NAME_RESERVED9 || chip_name_id == CHIP_NAME_RESERVED5 ||
chip_name_id == CHIP_NAME_RESERVED2 || chip_name_id == CHIP_NAME_RESERVED17 ||
chip_name_id == CHIP_NAME_RESERVED19 || chip_name_id == CHIP_NAME_RESERVED8 ||
chip_name_id == CHIP_NAME_HI3751V811) {
rcv_mbx.cmd = MBX_ACK_MSG;
rcv_mbx.result = MBX_ACK_SUCCESS;
}
if (rcv_mbx.cmd != MBX_ACK_MSG) {
soc_log_err("recive mbx data invalid :%x\n", rcv_mbx.cmd);
ret = TD_FAILURE;
goto free_ref;
}
osal_mem_ref_put(lic_dma_addr, SOC_ID_PDM);
if (rcv_mbx.result == MBX_ACK_SUCCESS) {
return TD_SUCCESS;
} else {
return rcv_mbx.result;
}
free_ref:
osal_mem_ref_put(lic_dma_addr, SOC_ID_PDM);
return ret;
}
td_s32 ext_drv_pdm_release_reserve_mem(const td_char *buf_name)
{
td_s32 ret;
soc_info_func_enter();
if (buf_name == TD_NULL) {
soc_log_err("buf_name is null!\n");
return SOC_ERR_PDM_PTR_NULL;
}
ret = drv_pdm_release_reserve_mem(buf_name);
if (ret != TD_SUCCESS) {
soc_log_info("drv_pdm_release_reserve_mem fail! buf_name:%s, ret:0x%x\n", buf_name, ret);
return ret;
}
soc_info_func_exit();
return TD_SUCCESS;
}
td_s32 ext_drv_pdm_get_reserve_mem(const td_char *buf_name, td_u64 *resever_addr, td_u32 *resever_buf_size)
{
td_s32 ret;
soc_info_func_enter();
if ((buf_name == NULL) || (resever_addr == NULL) || (resever_buf_size == NULL)) {
soc_log_err("ptr is null!\n");
return TD_FAILURE;
}
ret = drv_pdm_get_reserve_mem(buf_name, resever_addr, resever_buf_size);
if (ret != TD_SUCCESS) {
soc_log_err("get reserve mem fail! buf_name:%s, ret:0x%x\n", buf_name, ret);
return ret;
}
soc_info_func_exit();
return TD_SUCCESS;
}
td_s32 ext_drv_pdm_get_data(const td_char *buf_name, td_u8 **data_addr, td_u32 *data_len)
{
td_s32 ret;
soc_info_func_enter();
if ((data_addr == TD_NULL) || (buf_name == TD_NULL) || (data_len == TD_NULL)) {
soc_log_err("ptr is null!\n");
return TD_FAILURE;
}
ret = drv_pdm_get_data(buf_name, data_addr, data_len);
if (ret != TD_SUCCESS) {
soc_log_err("get data fail! buf_name:%s, ret:0x%x\n", buf_name, ret);
return ret;
}
soc_info_func_exit();
return TD_SUCCESS;
}
td_s32 ext_drv_pdm_set_license_data(td_u64 lic_handle, td_u32 lic_len)
{
td_s32 ret;
soc_info_func_enter();
if (lic_handle == TD_INVALID_HANDLE || lic_len == 0) {
soc_log_err("input param is invalid!\n");
return SOC_ERR_PDM_PARAM_INVALID;
}
ret = drv_pdm_set_license_data(lic_handle, lic_len);
if (ret != TD_SUCCESS) {
soc_log_err("set license data fail! lic_handle:%d, lic_len:%d, ret:0x%x\n", lic_handle, lic_len, ret);
return ret;
}
soc_info_func_exit();
return TD_SUCCESS;
}
static td_s32 pdm_get_tcon_child_bin_num(td_void *tcon_para_viraddr, td_u32 viraddr_len)
{
td_s32 ret;
tcon_bin_head_s tcon_bin_head = {0};
if (viraddr_len < sizeof(tcon_bin_head_s)) {
soc_log_err("offset and it's size is too bigger then viraddr length!\n");
return TD_FAILURE;
}
/* get Tcon Big Bin Head data , for check input param */
ret = memcpy_s(&tcon_bin_head, sizeof(tcon_bin_head),
((td_u8 *)tcon_para_viraddr), sizeof(tcon_bin_head_s));
if (ret != EOK) {
soc_log_err("memcpy tcon_bin_head error\n");
return TD_FAILURE;
}
return tcon_bin_head.total_num;
}
static td_s32 pdm_check_tcon_bin_param(tcon_check_param check_param, td_void *tcon_para_viraddr,
td_u32 viraddr_len)
{
td_s32 ret;
td_u32 child_bin_len;
tcon_bin_info_s small_tcon_bin_info = {0};
if (viraddr_len < sizeof(tcon_bin_info_s)) {
soc_log_err("offset and it's size is too bigger then viraddr length!\n");
return TD_FAILURE;
}
/* get small Tcon bin info : len and offest */
ret = memcpy_s(&small_tcon_bin_info, sizeof(small_tcon_bin_info),
((td_u8 *)tcon_para_viraddr + sizeof(tcon_bin_head_s) +
check_param.index * sizeof(tcon_bin_info_s)), sizeof(tcon_bin_info_s));
if (ret != EOK) {
soc_log_err("memcpy small_tcon_bin_info error\n");
return TD_FAILURE;
}
child_bin_len = small_tcon_bin_info.bin_length;
if (child_bin_len == 0) {
soc_log_err("ERR: TconChildBinLen is 0\n");
return TD_FAILURE;
}
/* check input param offset and u32Size */
if ((check_param.offset >= child_bin_len) || (check_param.size >= child_bin_len) ||
(check_param.offset + check_param.size > child_bin_len)) {
soc_log_err("ERR: size: 0x%x + offset : 0x%x > = child_bin_len : 0x%x\n",
check_param.size, check_param.offset, child_bin_len);
return TD_FAILURE;
}
return TD_SUCCESS;
}
static td_s32 pdm_get_tcon_param(tcon_check_param check_param, td_void *tcon_para_viraddr,
td_u32 viraddr_len, td_void *tcon_param, td_u32 tcon_param_len)
{
td_s32 ret;
td_s32 child_bin_num;
tcon_bin_info_s *small_bin_info = TD_NULL;
if (tcon_para_viraddr == NULL) {
soc_log_err("tcon_para_viraddr is null\n");
return TD_FAILURE;
}
if (pdm_check_tcon_bin_param(check_param, tcon_para_viraddr, viraddr_len) == TD_FAILURE) {
soc_log_err("tcon_bin_param is invalid \n");
return TD_FAILURE;
}
child_bin_num = pdm_get_tcon_child_bin_num(tcon_para_viraddr, viraddr_len);
if (child_bin_num < 0) {
soc_log_err("pdm_get_tcon_child_bin_num failed\n");
return TD_FAILURE;
}
if (tcon_param_len < check_param.size) {
soc_log_err("offset and it's size is too bigger then viraddr length!\n");
return TD_FAILURE;
}
small_bin_info = (tcon_bin_info_s *)(tcon_para_viraddr + sizeof(tcon_bin_head_s) +
check_param.index * sizeof(tcon_bin_info_s));
ret = memcpy_s(tcon_param, tcon_param_len,
((td_u8 *)tcon_para_viraddr + sizeof(tcon_bin_head_s) +
child_bin_num * sizeof(tcon_bin_info_s) + check_param.offset + small_bin_info->file_offset), check_param.size);
if (ret != EOK) {
soc_log_err("secure func call error\n");
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_s32 check_panel_index_valid(td_u32 panel_index, td_u8 *tcon_data_addr)
{
td_u32 panel_max_num;
tcon_bin_head_s *big_bin_info = TD_NULL;
if (tcon_data_addr == NULL) {
soc_log_err("null ptr\n");
return SOC_ERR_PDM_PTR_NULL;
}
big_bin_info = (tcon_bin_head_s *)tcon_data_addr;
panel_max_num = big_bin_info->total_num;
if (panel_max_num == 0) {
soc_log_err("stored panel num is invalid : 0! cur: %d\n", panel_index);
big_bin_info = TD_NULL;
return SOC_ERR_PDM_PARAM_INVALID;
}
if (panel_index > (panel_max_num - 1)) {
soc_log_err("input panel index is invalid, total : %d, cur: %d\n", panel_max_num, panel_index);
big_bin_info = TD_NULL;
return SOC_ERR_PDM_PARAM_INVALID;
}
big_bin_info = TD_NULL;
return TD_SUCCESS;
}
td_s32 ext_drv_pdm_get_tcon_param(td_u32 panel_index, td_u32 offset,
td_u32 size, td_void *tcon_param, td_u32 tcon_param_len)
{
td_s32 ret;
td_u8 *tcon_para_phyaddr = TD_NULL;
td_u32 tcon_para_len = 0;
td_u8 *tcon_para_viraddr = TD_NULL;
tcon_check_param check_param = {0};
soc_info_func_enter();
if (tcon_param == NULL) {
soc_log_err("ERR: null ptr\n");
return TD_FAILURE;
}
if (size == 0) {
soc_log_err("ERR: param invalid\n");
return TD_FAILURE;
}
if ((pdm_get_vir_addr_by_name(PDM_TCONPARAM_BUFNAME, &tcon_para_viraddr, &tcon_para_len) != TD_SUCCESS)
|| (tcon_para_viraddr == TD_NULL)) {
ret = pdm_get_buf_by_name(PDM_TCONPARAM_BUFNAME, &tcon_para_phyaddr, &tcon_para_len);
if (ret != TD_SUCCESS) {
soc_log_err("ERR: call pdm_get_buf_by_name fail\n");
return ret;
}
tcon_para_viraddr = osal_blockmem_vmap((td_ulong)(uintptr_t)tcon_para_phyaddr, tcon_para_len);
pdm_set_vir_addr_by_name(PDM_TCONPARAM_BUFNAME, tcon_para_viraddr);
}
check_param.index = panel_index;
check_param.offset = offset;
check_param.size = size;
ret = check_panel_index_valid(panel_index, tcon_para_viraddr);
if (ret != TD_SUCCESS) {
soc_log_err("call check_panel_index_valid fail\n");
return ret;
}
ret = pdm_get_tcon_param(check_param, tcon_para_viraddr, tcon_para_len, tcon_param, tcon_param_len);
if (ret != TD_SUCCESS) {
soc_log_err("call pdm_get_tcon_param fail\n");
return ret;
}
soc_info_func_exit();
return TD_SUCCESS;
}
td_s32 ext_drv_pdm_get_tcon_module_param(td_u32 panel_index,
td_u32 mod_id, td_void *data_ptr, td_u32 data_len)
{
td_s32 ret;
td_u32 length;
td_u32 data_length = 0;
td_u32 data_offset = 0;
td_u32 sect_length = 0;
td_u32 i;
ext_drv_tcon_bin_header_s tconbin_head = {0};
ext_drv_tcon_section_header section_head = {0};
soc_info_func_enter();
length = sizeof(ext_drv_tcon_bin_header_s);
ret = ext_drv_pdm_get_tcon_param(panel_index, 0, length, &tconbin_head, sizeof(ext_drv_tcon_bin_header_s));
if (ret != TD_SUCCESS) {
soc_log_err("Get Tcon small bin failure!\n");
return TD_FAILURE;
}
for (i = 0; i < tconbin_head.section_num; i++) {
ret = ext_drv_pdm_get_tcon_param(panel_index, length + sect_length, sizeof(ext_drv_tcon_section_header),
&section_head, sizeof(ext_drv_tcon_section_header));
if (ret != TD_SUCCESS) {
soc_log_err("Get Tcon bin section failure!\n");
return TD_FAILURE;
}
if (mod_id == section_head.type_id) {
data_length = section_head.size;
data_offset = section_head.addr_offset;
break;
}
sect_length = sect_length + sizeof(ext_drv_tcon_section_header);
}
if (i >= tconbin_head.section_num) {
soc_log_err("has no this mod_id : 0x%x!\n", mod_id);
return TD_FAILURE;
}
ret = ext_drv_pdm_get_tcon_param(panel_index, data_offset, data_length, data_ptr, data_len);
if (ret != TD_SUCCESS) {
soc_log_err("Get Tcon bin module data failure!\n");
return TD_FAILURE;
}
soc_info_func_exit();
return ret;
}
td_s32 ext_drv_pdm_is_tcon_module_exist(td_u32 panel_index,
td_bool *exist, td_u32 mod_id, td_u32 *len)
{
ext_drv_tcon_bin_header_s tconbin_head = {0};
ext_drv_tcon_section_header section_head = {0};
td_s32 ret;
td_u32 length;
td_u32 i;
td_u32 sect_length = 0;
soc_info_func_enter();
if ((exist == TD_NULL) || (len == TD_NULL)) {
soc_log_err("param is null!\n");
return SOC_ERR_PDM_PTR_NULL;
}
length = sizeof(ext_drv_tcon_bin_header_s);
ret = ext_drv_pdm_get_tcon_param(panel_index, 0, length, &tconbin_head, sizeof(ext_drv_tcon_bin_header_s));
if (ret != TD_SUCCESS) {
*exist = TD_FALSE;
soc_log_err("Get Tcon small bin failure!\n");
return TD_FAILURE;
}
for (i = 0; i < tconbin_head.section_num; i++) {
ret = ext_drv_pdm_get_tcon_param(panel_index, length + sect_length,
sizeof(ext_drv_tcon_section_header), &section_head, sizeof(ext_drv_tcon_section_header));
if (ret != TD_SUCCESS) {
*exist = TD_FALSE;
soc_log_err("Get Tcon bin setcion failure!\n");
return TD_FAILURE;
}
if (mod_id == section_head.type_id) {
*len = section_head.size;
break;
}
sect_length = sect_length + sizeof(ext_drv_tcon_section_header);
}
if (i >= tconbin_head.section_num) {
*exist = TD_FALSE;
soc_log_info("has no this mod_id : 0x%x!\n", mod_id);
return TD_SUCCESS;
}
*exist = TD_TRUE;
soc_info_func_exit();
return TD_SUCCESS;
}
td_s32 ext_drv_pdm_get_tcon_head(td_void *tcon_head, td_u32 tcon_head_len)
{
td_s32 ret;
td_u8 *tcon_para_phyaddr = TD_NULL;
td_u32 tcon_para_len = 0;
td_u8 *tcon_para_viraddr = TD_NULL;
soc_info_func_enter();
if (tcon_head == NULL) {
soc_log_err("ERR: null ptr\n");
return TD_FAILURE;
}
if (tcon_head_len < sizeof(tcon_bin_head_s)) {
soc_log_err("the seze of tcon head is smaller then tcon_bin_head!");
return TD_FAILURE;
}
if ((pdm_get_vir_addr_by_name(PDM_TCONPARAM_BUFNAME, &tcon_para_viraddr, &tcon_para_len) != TD_SUCCESS)
|| (tcon_para_viraddr == TD_NULL)) {
ret = pdm_get_buf_by_name(PDM_TCONPARAM_BUFNAME, &tcon_para_phyaddr, &tcon_para_len);
if (ret != TD_SUCCESS) {
soc_log_err("ERR: call pdm_get_buf_by_name fail\n");
return ret;
}
tcon_para_viraddr = osal_blockmem_vmap((td_ulong)(uintptr_t)tcon_para_phyaddr, tcon_para_len);
if (tcon_para_viraddr == TD_NULL) {
soc_log_err("tcon_para_viraddr is null!\n");
return SOC_ERR_PDM_PTR_NULL;
}
pdm_set_vir_addr_by_name(PDM_TCONPARAM_BUFNAME, tcon_para_viraddr);
}
ret = memcpy_s(tcon_head, tcon_head_len, tcon_para_viraddr, sizeof(tcon_bin_head_s));
if (ret != EOK) {
soc_log_err("secure func call error\n");
return TD_FAILURE;
}
soc_info_func_exit();
return TD_SUCCESS;
}
td_s32 ext_drv_pdm_set_silence_flag(td_bool silence)
{
td_u32 i;
silence_call_back_node *tmp = TD_NULL;
silence_call_back_node *tmp_2 = TD_NULL;
td_u8 *virt_addr = TD_NULL;
soc_info_func_enter();
for (i = 0; i < g_pdm_global.buf_num; i++) {
if (!strcmp("slavedeviceinfo", g_pdm_global.buf_info[i].buf_name)) {
virt_addr = osal_blockmem_vmap((td_ulong)(uintptr_t)g_pdm_global.buf_info[i].phy_addr, sizeof(td_bool));
break;
}
}
if (i >= g_pdm_global.buf_num) {
soc_log_err("call ext_drv_pdm_get_silence_flag fail cannot find silence flag mem\n");
return TD_FAILURE;
}
if (virt_addr == TD_NULL) {
soc_log_err("can nnot map phy addr\n");
return TD_FAILURE;
}
((ext_pdm_config_info *)(virt_addr + PDM_CONFIG_INFO_OFFSET))->silence_flag = silence;
osal_blockmem_vunmap(virt_addr);
for (i = 0; i < ARRAY_SIZE(g_pdm_ext_modules); i++) {
if (g_pdm_ext_modules[i].module_id == 0) {
continue;
}
osal_list_for_each_entry_safe(tmp, tmp_2, &(g_pdm_ext_modules[i].list_head), list) {
if ((tmp != TD_NULL) && (tmp->fn != TD_NULL)) {
tmp->fn(silence, tmp->private_data);
}
}
}
soc_info_func_exit();
return TD_SUCCESS;
}
td_s32 ext_drv_pdm_get_silence_flag(td_bool *silence)
{
td_u32 i;
td_u8 *virt_addr = TD_NULL;
soc_info_func_enter();
if (silence == NULL) {
soc_log_err("null ptr\n");
return SOC_ERR_PDM_PTR_NULL;
}
for (i = 0; i < g_pdm_global.buf_num; i++) {
if (!strcmp("slavedeviceinfo", g_pdm_global.buf_info[i].buf_name)) {
virt_addr = osal_blockmem_vmap((td_ulong)(uintptr_t)g_pdm_global.buf_info[i].phy_addr, sizeof(td_bool));
break;
}
}
if (i >= g_pdm_global.buf_num) {
soc_log_err("call ext_drv_pdm_get_silence_flag fail cannot find silence flag mem\n");
return TD_FAILURE;
}
if (virt_addr == TD_NULL) {
soc_log_err("can nnot map phy addr\n");
return TD_FAILURE;
}
*silence = ((ext_pdm_config_info *)(virt_addr + PDM_CONFIG_INFO_OFFSET))->silence_flag;
soc_log_dbg("get silence flag : %d\n", *silence);
osal_blockmem_vunmap(virt_addr);
soc_info_func_exit();
return TD_SUCCESS;
}
static td_void drv_pdm_init_silence(td_void)
{
td_u32 i;
memset_s(&g_pdm_ext_modules, sizeof(g_pdm_ext_modules), 0, sizeof(g_pdm_ext_modules));
for (i = 0; i < PDM_MODULE_MAX_NUM; i++) {
g_pdm_ext_modules[i].list_head.next = &g_pdm_ext_modules[i].list_head;
g_pdm_ext_modules[i].list_head.prev = &g_pdm_ext_modules[i].list_head;
}
g_is_silence_init = TD_TRUE;
}
td_s32 ext_drv_pdm_register_callback(td_u32 module_id,
ext_pdm_set_silence_callback_func fn, td_void *private_data)
{
td_u32 i;
silence_call_back_node *cb_node = TD_NULL;
soc_info_func_enter();
if (fn == NULL) {
soc_log_err(" there is null pointer.\n");
return SOC_ERR_PDM_PTR_NULL;
}
if (module_id >= SOC_ID_MAX) {
soc_log_err("moudle_id %d is invalid.\n", module_id);
return SOC_ERR_PDM_PARAM_INVALID;
}
if (g_is_silence_init == TD_FALSE) {
drv_pdm_init_silence();
}
for (i = 0; i < PDM_MODULE_MAX_NUM; i++) {
if (g_pdm_ext_modules[i].module_id == 0 || g_pdm_ext_modules[i].module_id == module_id) {
g_pdm_ext_modules[i].module_id = module_id;
cb_node = osal_vmalloc(sizeof(silence_call_back_node));
if (cb_node == TD_NULL) {
soc_log_err("cannot get free space to register new call back func! \n");
return TD_FAILURE;
}
cb_node->fn = fn;
cb_node->private_data = private_data;
osal_list_add(&(cb_node->list), &(g_pdm_ext_modules[i].list_head));
soc_log_info("register callback module id:%d\n", g_pdm_ext_modules[i].module_id);
break;
}
continue;
}
soc_info_func_exit();
return TD_SUCCESS;
}
td_s32 dev_pdm_silence_callback(td_bool silence)
{
td_u32 i;
silence_call_back_node *cb_node = TD_NULL;
silence_call_back_node *cb_node_2 = TD_NULL;
for (i = 0; i < ARRAY_SIZE(g_pdm_ext_modules); i++) {
if (g_pdm_ext_modules[i].module_id != SOC_ID_PANEL) {
osal_list_for_each_entry_safe(cb_node, cb_node_2, &(g_pdm_ext_modules[i].list_head), list) {
if (cb_node != TD_NULL) {
cb_node->fn(silence, cb_node->private_data);
}
}
}
}
return TD_SUCCESS;
}
static td_s32 pdm_resume_reg_mute(td_u32 *tmp)
{
td_s32 ret;
td_u32 addr_tmp = 0;
td_u32 *mapped_addr = TD_NULL;
soc_info_func_enter();
if (tmp == NULL) {
soc_log_err(" there is null pointer.\n");
return SOC_ERR_PDM_PTR_NULL;
}
ret = osal_dts_get_u32_byname("huanglong,pmoc", "reg_mute", &addr_tmp);
if (ret != TD_SUCCESS) {
soc_log_err("cannot get reg_mute from dtb! ret: %d\n", ret);
return ret;
}
mapped_addr = osal_ioremap(addr_tmp, sizeof(td_u32));
if (mapped_addr == TD_NULL) {
soc_log_err("cannot get mapped addr!\n");
return TD_FAILURE;
}
*tmp = *mapped_addr;
osal_iounmap(mapped_addr, sizeof(td_u32));
soc_info_func_exit();
return TD_SUCCESS;
}
td_s32 ext_drv_pdm_resume_handler(td_void)
{
td_s32 ret;
td_u32 i;
td_u32 tmp;
td_bool silence;
td_u8 *virt_addr = TD_NULL;
soc_info_func_enter();
ret = pdm_resume_reg_mute(&tmp);
if (ret != TD_SUCCESS) {
soc_log_err("pdm_resume_reg_mute fai! ret:0x%x\n", ret);
return ret;
}
if ((tmp != PDM_MUTE_WAKEUP_ENABLE) && (tmp != PDM_MUTE_WAKEUP_DISABLE)) {
soc_log_info("get data from dts reg is invalid, use flash data, reg_mute:%d\n", tmp);
return TD_SUCCESS;
} else {
(tmp == PDM_MUTE_WAKEUP_ENABLE) ? (silence = TD_TRUE) : (silence = TD_FALSE);
for (i = 0; i < g_pdm_global.buf_num; i++) {
if (strcmp(g_pdm_global.buf_info[i].buf_name, "slavedeviceinfo")) {
continue;
}
virt_addr = osal_blockmem_vmap((td_ulong)(uintptr_t)g_pdm_global.buf_info[i].phy_addr,
g_pdm_global.buf_info[i].lenth);
if (virt_addr == TD_NULL) {
soc_log_err("cannot get virt addr of silenceflag\n");
return TD_FAILURE;
}
((ext_pdm_config_info *)(virt_addr + PDM_CONFIG_INFO_OFFSET))->silence_flag = silence;
osal_blockmem_vunmap(virt_addr);
}
}
ret = dev_pdm_silence_callback(silence);
if (ret != TD_SUCCESS) {
soc_log_err("dev_pdm_silence_callback fai! silence:%d, ret:0x%x\n", silence, ret);
return ret;
}
soc_info_func_exit();
return TD_SUCCESS;
}
td_s32 ext_drv_pdm_get_ta_revoked_list(td_void *buf, td_u32 buf_size, td_u32 *read_size)
{
td_s32 ret;
td_u8 *base_vir_addr = TD_NULL;
td_u8 *base_phy_addr = TD_NULL;
td_u32 base_len;
td_u32 target_size;
soc_info_func_enter();
if (buf == TD_NULL || read_size == TD_NULL) {
soc_log_err("null ptr\n");
return SOC_ERR_PDM_PTR_NULL;
}
if ((pdm_get_vir_addr_by_name(PDM_DEVICEINFO_BUFNAME, &base_vir_addr, &base_len) != TD_SUCCESS) ||
(base_vir_addr == TD_NULL)) {
ret = pdm_get_buf_by_name(PDM_DEVICEINFO_BUFNAME, &base_phy_addr, &base_len);
if (ret != TD_SUCCESS) {
soc_log_err("pdm_get_buf_by_name fai!ret:0x%x\n", ret);
return ret;
}
base_vir_addr = osal_blockmem_vmap((td_ulong)(uintptr_t)base_phy_addr, base_len);
pdm_set_vir_addr_by_name(PDM_DEVICEINFO_BUFNAME, base_vir_addr);
}
if (buf_size > PDM_TA_REVOKED_SIZE) {
soc_log_info("buf_size is out of range\n");
target_size = PDM_TA_REVOKED_SIZE;
} else {
target_size = buf_size;
}
ret = memcpy_s(buf, buf_size, base_vir_addr + PDM_TA_REVOKED_LIST_OFFSET, target_size);
if (ret != EOK) {
soc_log_err("secure func call error\n");
return TD_FAILURE;
}
*read_size = target_size;
soc_info_func_exit();
return TD_SUCCESS;
}
static td_s32 pdm_check_patrion_info_and_addr(const ext_pdm_partion_info *partion_info, const td_void *addr)
{
if (partion_info == TD_NULL || addr == TD_NULL) {
soc_log_err("invalid param: partion_info 0x%lx addr 0x%lx \n", partion_info, addr);
return SOC_ERR_PDM_PTR_NULL;
}
if (strlen(partion_info->partion_name) == EXT_DB_MAX_NAME_LEN
|| strlen(partion_info->tbl_name) == EXT_DB_MAX_NAME_LEN
|| strlen(partion_info->key_name) == EXT_DB_MAX_NAME_LEN) {
soc_log_err("invalid param (not string): partion_name %s tbl_name %s key_name %s\n",
partion_info->partion_name, partion_info->tbl_name, partion_info->key_name);
return SOC_ERR_PDM_PARAM_INVALID;
}
return TD_SUCCESS;
}
td_s32 ext_drv_pdm_db_get_data(const ext_pdm_partion_info *partion_info, td_void *addr, td_u32 size)
{
td_s32 ret;
ext_db db = {0};
ext_db_table table = {0};
ext_db_key key = {0};
td_u8 *phy_addr = TD_NULL;
td_u8 *vir_addr = TD_NULL;
td_u32 len = 0;
ret = pdm_check_patrion_info_and_addr(partion_info, addr);
if (ret != TD_SUCCESS) {
return ret;
}
if ((pdm_get_vir_addr_by_name(partion_info->partion_name, &vir_addr, &len) != TD_SUCCESS) ||
(vir_addr == TD_NULL)) {
ret = pdm_get_buf_by_name(partion_info->partion_name, &phy_addr, &len);
if (ret != TD_SUCCESS) {
soc_log_err("get buf by_name:%s\n", partion_info->partion_name);
return ret;
}
vir_addr = osal_blockmem_vmap((td_ulong)(uintptr_t)phy_addr, len);
ret = pdm_set_vir_addr_by_name(partion_info->partion_name, vir_addr);
if (ret != TD_SUCCESS) {
soc_log_err("set vir addr by_name:%s, addr:0x%lx\n", partion_info->partion_name, vir_addr);
return TD_FAILURE;
}
}
ret = ext_db_get_db_from_mem((td_u8 *)vir_addr, &db);
if (ret != TD_SUCCESS) {
soc_log_err(" get db fail addr: 0x%lx\n", vir_addr);
return TD_FAILURE;
}
ret = ext_db_get_table_by_name(&db, (td_char *)partion_info->tbl_name, &table);
if (ret != TD_SUCCESS) {
soc_log_err("ERR: unsupport tbl name! %s\n", partion_info->tbl_name);
return TD_FAILURE;
}
ret = ext_db_get_key_by_name(&table, (td_char *)partion_info->key_name, strlen(partion_info->key_name), &key);
if (ret != TD_SUCCESS) {
return SOC_ERR_PDM_KEY_NOT_EXIST;
}
ret = memcpy_s(addr, size, key.value, key.value_size);
if (ret != EOK) {
soc_log_err("ERR: copy failed dst size %u src size %u\n", size, key.value_size);
return TD_FAILURE;
}
return TD_SUCCESS;
}