/* * 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), §ion_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), §ion_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; }