/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2022-2022. All rights reserved. * Description: MPI function file for Huanglong sif * Author: audio * Create: 2022-11-02 */ #include #include #include #include #include #include #include #include "td_type.h" #include "mpi_sif_ext.h" #include "drv_ioctl_sif.h" #include "soc_module.h" #include "securec.h" #include "soc_errno.h" #include "mpi_sif_debug.h" #ifdef __cplusplus #if __cplusplus extern "C" { #endif #endif /* __cplusplus */ #define SOC_DEV_SIF_NAME "soc_sif" static td_s32 g_sif_dev_fd = -1; static const td_char g_sif_dev_name[] = "/dev/" SOC_DEV_SIF_NAME; static pthread_mutex_t g_sif_mutex = PTHREAD_MUTEX_INITIALIZER; #define ext_sif_lock(sif_mutex) (td_void)pthread_mutex_lock(&(sif_mutex)) #define ext_sif_unlock(sif_mutex) (td_void)pthread_mutex_unlock(&(sif_mutex)) #define REG_MAX_8BITS 0xff #define REG_MAX_16BITS 0xffff static td_s32 check_sif_init(ext_sif_id sif) { if (g_sif_dev_fd < 0) { soc_log_err("Please Init firstly.\n"); return SOC_ERR_SIF_NOT_INIT; } if (sif != EXT_SIF_ID_0) { soc_log_err("Please Input Valid id.\n"); return SOC_ERR_SIF_INVALID_ID; } return TD_SUCCESS; } td_s32 ext_mpi_sif_map_basic_audio_standard(ext_sif_standard_type original_standard, ext_sif_standard_type *standard) { if (g_sif_dev_fd < 0) { soc_log_err("Please Init firstly.\n"); return SOC_ERR_SIF_NOT_INIT; } if (standard == TD_NULL) { soc_log_err("standard is null!\n"); return SOC_ERR_SIF_NULL_PTR; } switch (original_standard) { case EXT_SIF_STANDARD_BG: case EXT_SIF_STANDARD_BG_A2: case EXT_SIF_STANDARD_BG_NICAM: *standard = EXT_SIF_STANDARD_BG; return TD_SUCCESS; case EXT_SIF_STANDARD_I: *standard = EXT_SIF_STANDARD_I; return TD_SUCCESS; case EXT_SIF_STANDARD_DK: case EXT_SIF_STANDARD_DK1_A2: case EXT_SIF_STANDARD_DK2_A2: case EXT_SIF_STANDARD_DK3_A2: case EXT_SIF_STANDARD_DK_NICAM: *standard = EXT_SIF_STANDARD_DK; return TD_SUCCESS; case EXT_SIF_STANDARD_L: *standard = EXT_SIF_STANDARD_L; return TD_SUCCESS; case EXT_SIF_STANDARD_M: case EXT_SIF_STANDARD_M_BTSC: case EXT_SIF_STANDARD_M_A2: case EXT_SIF_STANDARD_M_EIA_J: *standard = EXT_SIF_STANDARD_M; return TD_SUCCESS; default: soc_log_err("Invalid basic standard: \n"); soc_err_print_u32(original_standard); *standard = EXT_SIF_STANDARD_UNKNOW; return SOC_ERR_SIF_INVALID_PARA; } } td_s32 ext_mpi_sif_init(td_void) { soc_info_func_enter(); ext_sif_lock(g_sif_mutex); if (g_sif_dev_fd < 0) { g_sif_dev_fd = open(g_sif_dev_name, O_RDWR, 0); if (g_sif_dev_fd < 0) { soc_log_fatal("open sif device err\n"); g_sif_dev_fd = -1; ext_sif_unlock(g_sif_mutex); return SOC_ERR_SIF_DEV_OPENED; } } ext_sif_unlock(g_sif_mutex); soc_info_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_deinit(td_void) { soc_info_func_enter(); ext_sif_lock(g_sif_mutex); if (g_sif_dev_fd < 0) { soc_log_warn("SIF device is closed, can not close again\n"); ext_sif_unlock(g_sif_mutex); return TD_SUCCESS; } close(g_sif_dev_fd); g_sif_dev_fd = -1; ext_sif_unlock(g_sif_mutex); soc_info_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_open(ext_sif_id sif) { td_s32 ret; soc_info_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } ret = ioctl(g_sif_dev_fd, CMD_SIF_OPEN, &sif); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_OPEN err.\n"); soc_err_print_err_code(ret); return ret; } soc_info_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_close(ext_sif_id sif) { td_s32 ret; soc_info_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } ret = ioctl(g_sif_dev_fd, CMD_SIF_CLOSE, &sif); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_CLOSE err.\n"); soc_err_print_err_code(ret); return ret; } soc_info_func_exit(); return TD_SUCCESS; } static td_s32 check_sif_param(const ext_sif_attr *set_attr) { if ((set_attr->auto_mute != TD_FALSE) && (set_attr->auto_mute) != TD_TRUE) { soc_log_err("Invalid parameter:\n"); soc_err_print_bool(set_attr->auto_mute); return SOC_ERR_SIF_INVALID_PARA; } if ((set_attr->out_mode >= EXT_SIF_OUT_MODE_MAX)) { soc_log_err("Invalid parameter:\n"); soc_err_print_u32(set_attr->out_mode); return SOC_ERR_SIF_INVALID_PARA; } if ((set_attr->freq_threshold >= EXT_SIF_FREQ_ERR_THRESHOLD_MAX)) { soc_log_err("Invalid parameter:\n"); soc_err_print_u32(set_attr->freq_threshold); return SOC_ERR_SIF_INVALID_PARA; } if ((set_attr->prescale_level > REG_MAX_8BITS) || (set_attr->carri_mgntude_threshold > REG_MAX_8BITS) || (set_attr->carri_fm_qual_threshold > REG_MAX_8BITS) || (set_attr->carri_am_noise_threshold > REG_MAX_8BITS) || (set_attr->carri_nicam_noise_threshold > REG_MAX_8BITS)) { soc_log_err("Invalid parameter:\n"); soc_err_print_u32(set_attr->prescale_level); soc_err_print_u32(set_attr->carri_mgntude_threshold); soc_err_print_u32(set_attr->carri_fm_qual_threshold); soc_err_print_u32(set_attr->carri_am_noise_threshold); soc_err_print_u32(set_attr->freq_threshold); return SOC_ERR_SIF_INVALID_PARA; } return TD_SUCCESS; } td_s32 ext_mpi_sif_set_attr(ext_sif_id sif, const ext_sif_attr *attr) { td_s32 ret; sif_attr_param attr_param = { 0 }; ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } if (attr == TD_NULL) { soc_log_err("attr is null!\n"); return SOC_ERR_SIF_NULL_PTR; } ret = check_sif_param(attr); if (ret != TD_SUCCESS) { return ret; } attr_param.id = sif; ret = memcpy_s(&attr_param.sif_attr, sizeof(attr_param.sif_attr), attr, sizeof(ext_sif_attr)); if (ret != TD_SUCCESS) { soc_log_err("memcpy_s failed"); return ret; } ret = ioctl(g_sif_dev_fd, CMD_SIF_SET_ATTR, &attr_param); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_SET_ATTR err.\n"); soc_err_print_err_code(ret); return ret; } return TD_SUCCESS; } td_s32 ext_mpi_sif_get_default_attr(ext_sif_id sif, ext_sif_attr *attr) { td_s32 ret; ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } if (attr == TD_NULL) { soc_log_err("attr is null!\n"); return SOC_ERR_SIF_NULL_PTR; } attr->auto_mute = TD_FALSE; attr->prescale_level = 0; attr->out_mode = EXT_SIF_OUT_MODE_NICAM_FORCED_MONO; attr->freq_threshold = EXT_SIF_FREQ_ERR_THRESHOLD_50K; attr->carri_mgntude_threshold = 0x19; // set default carrier magnitude detect threshold attr->carri_fm_qual_threshold = 0x1a; // set default FM carrier quality detect threshold attr->carri_am_noise_threshold = 0x09; // set default AM carrier Noise detect threshold attr->carri_nicam_noise_threshold = 0x1e; // set default NICAM AM carrier Noise detect threshold return TD_SUCCESS; } td_s32 ext_mpi_sif_get_attr(ext_sif_id sif, ext_sif_attr *attr) { td_s32 ret; sif_attr_param param = { 0 }; ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } if (attr == TD_NULL) { soc_log_err("attr is null!\n"); return SOC_ERR_SIF_NULL_PTR; } param.id = sif; ret = ioctl(g_sif_dev_fd, CMD_SIF_GET_ATTR, ¶m); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_GET_ATTR err.\n"); soc_err_print_err_code(ret); return ret; } ret = memcpy_s(attr, sizeof(ext_sif_attr), ¶m.sif_attr, sizeof(param.sif_attr)); if (ret != TD_SUCCESS) { soc_log_err("memcpy_s failed"); return ret; } return TD_SUCCESS; } td_s32 ext_mpi_sif_start(ext_sif_id sif) { td_s32 ret; soc_info_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } ret = ioctl(g_sif_dev_fd, CMD_SIF_SET_START, &sif); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_SET_START err.\n"); soc_err_print_err_code(ret); return ret; } soc_info_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_stop(ext_sif_id sif) { td_s32 ret; soc_info_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } ret = ioctl(g_sif_dev_fd, CMD_SIF_SET_STOP, &sif); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_SET_STOP err.\n"); soc_err_print_err_code(ret); return ret; } soc_info_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_set_standard(ext_sif_id sif, ext_sif_standard_type standard) { td_s32 ret; sif_standard_type_param standard_param = { 0 }; soc_info_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } if (standard > EXT_SIF_STANDARD_NOTSTANDARD) { soc_log_err("The SifStandard is not valid.\n"); soc_err_print_u32(standard); return SOC_ERR_SIF_INVALID_PARA; } standard_param.id = sif; standard_param.stand = standard; ret = ioctl(g_sif_dev_fd, CMD_SIF_SET_STANDDARD, &standard_param); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_SET_STANDDARD err.\n"); soc_err_print_err_code(ret); return ret; } soc_info_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_start_asd(ext_sif_id sif, ext_sif_ctl ctl) { td_s32 ret; sif_sysctl_param sys_ctl = { 0 }; soc_info_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } if (ctl >= EXT_SIF_CTL_MAX) { soc_log_err("The SifDetCtl is not valid.\n"); soc_err_print_u32(ctl); return SOC_ERR_SIF_INVALID_PARA; } sys_ctl.id = sif; sys_ctl.sys_ctl = ctl; ret = ioctl(g_sif_dev_fd, CMD_SIF_START_ASD, &sys_ctl); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_START_ASD err.\n"); soc_err_print_err_code(ret); return ret; } soc_info_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_get_asd_complete(ext_sif_id sif, td_bool *asd_complete) { td_s32 ret; sif_asd_complete_param get_asd_complete = { 0 }; soc_dbg_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } if (asd_complete == TD_NULL) { soc_log_err("asd_complete is null!\n"); return SOC_ERR_SIF_NULL_PTR; } get_asd_complete.id = sif; ret = ioctl(g_sif_dev_fd, CMD_SIF_GET_ASD_CMPL, &get_asd_complete); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_GET_ASD_CMPL err.\n"); soc_err_print_err_code(ret); return ret; } *asd_complete = get_asd_complete.asd_complete; soc_dbg_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_get_standard(ext_sif_id sif, ext_sif_standard_type *standard) { sif_standard_type_param standard_param = { 0 }; td_s32 ret; ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } if (standard == TD_NULL) { soc_log_err("asd_complete is null!\n"); return SOC_ERR_SIF_NULL_PTR; } standard_param.id = sif; ret = ioctl(g_sif_dev_fd, CMD_SIF_GET_STANDARD, &standard_param); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_GET_STANDARD err.\n"); soc_err_print_err_code(ret); return ret; } *standard = standard_param.stand; return TD_SUCCESS; } td_s32 ext_mpi_sif_get_asd_result(ext_sif_id sif, ext_sif_standard_type *standard) { sif_standard_type_param standard_param = { 0 }; td_s32 ret; soc_info_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } if (standard == TD_NULL) { soc_log_err("asd_complete is null!\n"); return SOC_ERR_SIF_NULL_PTR; } standard_param.id = sif; ret = ioctl(g_sif_dev_fd, CMD_SIF_GET_ASD_RESULT, &standard_param); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_GET_ASD_RESULT err.\n"); soc_err_print_err_code(ret); return ret; } *standard = standard_param.stand; soc_info_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_set_sound_mode(ext_sif_id sif, ext_sif_out_mode out_mode) { td_s32 ret; sif_out_mode_param out_mode_param = { 0 }; soc_dbg_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } if (out_mode >= EXT_SIF_OUT_MODE_MAX) { soc_log_err("The SifOutmode is not valid.\n"); soc_err_print_u32(out_mode); return SOC_ERR_SIF_INVALID_PARA; } out_mode_param.id = sif; out_mode_param.out_mode = out_mode; ret = ioctl(g_sif_dev_fd, CMD_SIF_SET_OUTMODE, &out_mode_param); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_SET_OUTMODE err.\n"); soc_err_print_err_code(ret); return ret; } soc_dbg_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_get_aaos_mode(ext_sif_id sif, ext_sif_aaos_mode *aaos_mode) { td_s32 ret; sif_aaos_mode_param aaos_mode_param = { 0 }; soc_dbg_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } if (aaos_mode == TD_NULL) { soc_log_err("aaos_mode is null!\n"); return SOC_ERR_SIF_NULL_PTR; } aaos_mode_param.id = sif; ret = ioctl(g_sif_dev_fd, CMD_SIF_GET_OUTMODE, &aaos_mode_param); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_GET_OUTMODE err.\n"); soc_err_print_err_code(ret); return ret; } *aaos_mode = aaos_mode_param.aaos_mode; soc_dbg_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_set_over_deviation(ext_sif_id sif, ext_sif_over_deviation over_deviation) { td_s32 ret; sif_over_deviation_param over_mod = { 0 }; soc_info_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } over_mod.id = sif; switch (over_deviation) { case EXT_SIF_OVER_DEVIATION_50K: over_mod.over_mode = EXT_SIF_OVER_DEVIATION_50K; break; case EXT_SIF_OVER_DEVIATION_100K: over_mod.over_mode = EXT_SIF_OVER_DEVIATION_100K; break; case EXT_SIF_OVER_DEVIATION_200K: over_mod.over_mode = EXT_SIF_OVER_DEVIATION_200K; break; case EXT_SIF_OVER_DEVIATION_384K: over_mod.over_mode = EXT_SIF_OVER_DEVIATION_384K; break; case EXT_SIF_OVER_DEVIATION_540K: over_mod.over_mode = EXT_SIF_OVER_DEVIATION_540K; break; default: soc_log_err("The OverDeviation is not valid.\n"); soc_err_print_u32(over_deviation); /* Illegal parameter should not set any legal value. */ over_mod.over_mode = EXT_SIF_OVER_DEVIATION_MAX; return SOC_ERR_SIF_INVALID_PARA; } ret = ioctl(g_sif_dev_fd, CMD_SIF_SET_OVER_DEV, &over_mod); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_SET_OVER_DEV err.\n"); soc_err_print_err_code(ret); return ret; } soc_info_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_get_over_deviation(ext_sif_id sif, ext_sif_over_deviation *over_deviation) { td_s32 ret; sif_over_deviation_param over_mod = { 0 }; soc_info_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } if (over_deviation == TD_NULL) { soc_log_err("over_deviation is null!\n"); return SOC_ERR_SIF_NULL_PTR; } over_mod.id = sif; ret = ioctl(g_sif_dev_fd, CMD_SIF_GET_OVER_DEV, &over_mod); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_SET_OVER_DEV err.\n"); soc_err_print_err_code(ret); return ret; } switch (over_mod.over_mode) { case EXT_SIF_OVER_DEVIATION_50K: *over_deviation = EXT_SIF_OVER_DEVIATION_50K; break; case EXT_SIF_OVER_DEVIATION_100K: *over_deviation = EXT_SIF_OVER_DEVIATION_100K; break; case EXT_SIF_OVER_DEVIATION_200K: *over_deviation = EXT_SIF_OVER_DEVIATION_200K; break; case EXT_SIF_OVER_DEVIATION_384K: *over_deviation = EXT_SIF_OVER_DEVIATION_384K; break; case EXT_SIF_OVER_DEVIATION_540K: *over_deviation = EXT_SIF_OVER_DEVIATION_540K; break; default: soc_log_err("The OverDeviation is not valid.\n"); soc_err_print_u32(over_mod.over_mode); *over_deviation = EXT_SIF_OVER_DEVIATION_MAX; return SOC_ERR_SIF_INVALID_PARA; } soc_info_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_set_carri_shift(ext_sif_id sif, td_u32 carri_shift) { td_s32 ret; sif_carri_shift_param st_carri_shift = { 0 }; soc_info_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } st_carri_shift.id = sif; st_carri_shift.carri_shift = carri_shift; if (carri_shift > REG_MAX_16BITS) { soc_log_err("The CarriShift is not valid.\n"); soc_err_print_u32(carri_shift); return SOC_ERR_SIF_INVALID_PARA; } ret = ioctl(g_sif_dev_fd, CMD_SIF_SET_CARRI_SHIFT, &st_carri_shift); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_SET_CARRI_SHIFT err.\n"); soc_err_print_err_code(ret); return ret; } soc_info_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_get_carrier_attr(ext_sif_id sif, ext_sif_carrier_attr *carrier_attr) { td_s32 ret; sif_carrier_attr_param get_carrier_attr = { 0 }; soc_info_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } if (carrier_attr == TD_NULL) { soc_log_err("carrier_attr is null!\n"); return SOC_ERR_SIF_NULL_PTR; } get_carrier_attr.id = sif; ret = ioctl(g_sif_dev_fd, CMD_SIF_TRY_STANDARD, &get_carrier_attr); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_TRY_STANDARD err.\n"); soc_err_print_err_code(ret); return ret; } ret = memcpy_s(carrier_attr, sizeof(ext_sif_carrier_attr), &get_carrier_attr.carrier_attr, sizeof(get_carrier_attr.carrier_attr)); if (ret != TD_SUCCESS) { soc_log_err("memcpy_s failed!\n"); return ret; } soc_info_func_exit(); return TD_SUCCESS; } td_s32 ext_mpi_sif_set_standard_try_priority_list(ext_sif_id sif, const ext_sif_standard_priority_list *priority_list) { td_u32 i = 0; td_s32 ret; sif_standard_list_param standard_list_param = { 0 }; soc_info_func_enter(); ret = check_sif_init(sif); if (ret != TD_SUCCESS) { return ret; } if (priority_list == TD_NULL) { soc_log_err("priority_list is null!\n"); return SOC_ERR_SIF_NULL_PTR; } if (priority_list->list_len > EXT_SIF_STANDARD_UNKNOW) { soc_log_err("The list length is over max list length.\n"); soc_err_print_u32(priority_list->list_len); return SOC_ERR_SIF_INVALID_PARA; } for (i = 0; i < priority_list->list_len; i++) { if (priority_list->priority_list[i] > EXT_SIF_STANDARD_NOTSTANDARD) { soc_log_err("The SifStandard is not valid.\n"); soc_err_print_u32(priority_list->priority_list[i]); return SOC_ERR_SIF_INVALID_PARA; } } standard_list_param.id = sif; ret = memcpy_s(&standard_list_param.priority_list, sizeof(standard_list_param.priority_list), priority_list, sizeof(ext_sif_standard_priority_list)); if (ret != TD_SUCCESS) { soc_log_err("memcpy_s failed"); return ret; } ret = ioctl(g_sif_dev_fd, CMD_SIF_SET_STANDARD_LIST, &standard_list_param); if (ret != TD_SUCCESS) { soc_log_err("CMD_SIF_SET_STANDARD_LIST err.\n"); soc_err_print_err_code(ret); return ret; } soc_info_func_exit(); return TD_SUCCESS; } #ifdef __cplusplus #if __cplusplus } #endif #endif /* __cplusplus */