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.
243 lines
7.4 KiB
243 lines
7.4 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2017-2021. All rights reserved.
|
|
* Description: CAB IAPI interface
|
|
* Author: Hisilicon
|
|
* Created: 2017-06-30
|
|
*/
|
|
|
|
#include "iapi_cab.h"
|
|
#include <math.h>
|
|
#include "soc_log.h"
|
|
#include "td_type.h"
|
|
#include "soc_errno.h"
|
|
#include "iapi_frontend.h"
|
|
#include "mpi_frontend_ext.h"
|
|
|
|
#ifdef __cplusplus
|
|
#if __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
#endif /* __cplusplus */
|
|
|
|
static td_s32 cab_connect_config(td_u32 port,
|
|
const uapi_frontend_connect_para *connect_para, fe_ioctrl_signal *signal)
|
|
{
|
|
frontend_acc_qam_params tuner_para = {0};
|
|
|
|
tuner_para.frequency = connect_para->connect_para.cab.freq;
|
|
tuner_para.srbw.symbol_rate = connect_para->connect_para.cab.symbol_rate;
|
|
tuner_para.si = connect_para->connect_para.cab.reverse;
|
|
tuner_para.sync_lock_status = EXT_DRV_FRONTEND_LOCK_STATUS_MAX;
|
|
tuner_para.dvbt_mode = 0;
|
|
tuner_para.scramble_code = 0;
|
|
|
|
switch (connect_para->connect_para.cab.mod_type) {
|
|
case UAPI_MOD_TYPE_QAM_16:
|
|
tuner_para.modpol.qam_type = QAM_TYPE_16;
|
|
break;
|
|
case UAPI_MOD_TYPE_QAM_32:
|
|
tuner_para.modpol.qam_type = QAM_TYPE_32;
|
|
break;
|
|
case UAPI_MOD_TYPE_QAM_64:
|
|
case UAPI_MOD_TYPE_DEFAULT:
|
|
tuner_para.modpol.qam_type = QAM_TYPE_64;
|
|
break;
|
|
case UAPI_MOD_TYPE_QAM_128:
|
|
tuner_para.modpol.qam_type = QAM_TYPE_128;
|
|
break;
|
|
case UAPI_MOD_TYPE_QAM_256:
|
|
tuner_para.modpol.qam_type = QAM_TYPE_256;
|
|
break;
|
|
case UAPI_MOD_TYPE_AUTO:
|
|
tuner_para.modpol.qam_type = QAM_TYPE_AUTO;
|
|
break;
|
|
default:
|
|
soc_err_print_u32(connect_para->connect_para.cab.mod_type);
|
|
return SOC_ERR_FRONTEND_INVALID_PARA;
|
|
}
|
|
|
|
signal->sig_type = (ext_drv_frontend_sig_type)connect_para->sig_type;
|
|
signal->port = port;
|
|
signal->signal = tuner_para;
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 cab_connect_execute(td_u32 port, td_u32 time_out, fe_ioctrl_signal *fe_signal)
|
|
{
|
|
td_s32 ret;
|
|
td_u32 time_span = 0;
|
|
fe_ioctrl_status fe_status;
|
|
|
|
fe_status.port = port;
|
|
fe_status.lock_status = EXT_DRV_FRONTEND_LOCK_STATUS_DROPPED;
|
|
|
|
ret = ext_mpi_frontend_connect(fe_signal);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(ext_mpi_frontend_connect, ret);
|
|
return ret;
|
|
}
|
|
|
|
if (time_out == 0) {
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
/* if demod sync is not ok,do not need to get fec status */
|
|
soc_dbg_print_u32(fe_signal->signal.sync_lock_status);
|
|
if (fe_signal->signal.sync_lock_status == EXT_DRV_FRONTEND_LOCK_STATUS_DROPPED) {
|
|
soc_log_dbg("Sync is not ok,so tell the locked status immediately.\n");
|
|
return SOC_ERR_FRONTEND_CONNECT_FAIL;
|
|
}
|
|
|
|
while (time_span < time_out) {
|
|
ret = ext_mpi_frontend_get_status(&fe_status);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(ext_mpi_frontend_get_status, ret);
|
|
return ret;
|
|
}
|
|
|
|
if (fe_status.lock_status == EXT_DRV_FRONTEND_LOCK_STATUS_LOCKED) {
|
|
return TD_SUCCESS;
|
|
} else {
|
|
fe_usleep(10 * 1000); /* 10:sleep;1000:us */
|
|
time_span += 10; /* step:10 */
|
|
}
|
|
}
|
|
|
|
/* Timeout return Failed */
|
|
return SOC_ERR_FRONTEND_CONNECT_FAIL;
|
|
}
|
|
|
|
td_s32 cab_connect(td_u32 tuner_id, const uapi_frontend_connect_para *connect_para, td_u32 time_out)
|
|
{
|
|
td_s32 ret;
|
|
static fe_ioctrl_signal signal = {0};
|
|
|
|
if (connect_para == TD_NULL) {
|
|
soc_log_err("Input parameter(connect_para) is TD_NULL.\n");
|
|
return SOC_ERR_FRONTEND_INVALID_POINT;
|
|
}
|
|
|
|
soc_log_dbg("cab_connect.\n");
|
|
|
|
if ((connect_para->connect_para.cab.freq < QAM_RF_MIN) ||
|
|
(connect_para->connect_para.cab.freq > QAM_RF_MAX)) {
|
|
soc_log_err("Input parameter(tuner_para.u32Frequency) invalid.\n");
|
|
soc_err_print_u32(connect_para->connect_para.cab.freq);
|
|
return SOC_ERR_FRONTEND_INVALID_PARA;
|
|
}
|
|
|
|
if (connect_para->connect_para.cab.mod_type != UAPI_MOD_TYPE_AUTO) {
|
|
if ((connect_para->connect_para.cab.symbol_rate < 900000) || /* 900000:min */
|
|
(connect_para->connect_para.cab.symbol_rate > 7200000)) { /* 7200000:max */
|
|
soc_log_err("Input parameter(tuner_para.srbw.symbol_rate) invalid.\n");
|
|
soc_err_print_u32(connect_para->connect_para.cab.symbol_rate);
|
|
return SOC_ERR_FRONTEND_INVALID_PARA;
|
|
}
|
|
}
|
|
|
|
ret = cab_connect_config(tuner_id, connect_para, &signal);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("cab_connect_config failed.\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = cab_connect_execute(tuner_id, time_out, &signal);
|
|
if ((ret != TD_SUCCESS)) {
|
|
return ret;
|
|
} else {
|
|
return TD_SUCCESS;
|
|
}
|
|
}
|
|
|
|
static td_s32 cab_get_signal_quality_snr_sqi(td_u32 port, td_double snr, td_double *snr_sqi)
|
|
{
|
|
td_s32 ret;
|
|
td_double cn_nordig = 0;
|
|
fe_ioctrl_status fe_status = {0};
|
|
|
|
fe_status.port = port;
|
|
ret = ext_mpi_frontend_get_status(&fe_status);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(ext_mpi_frontend_get_status, ret);
|
|
return ret;
|
|
}
|
|
|
|
soc_log_info("sig_type:%u\n", fe_status.connect_para.sig_type);
|
|
soc_log_info("mod_type:%u\n", fe_status.connect_para.connect_para.cab.mod_type);
|
|
|
|
if (fe_status.connect_para.sig_type == EXT_DRV_FRONTEND_SIG_TYPE_DVB_C) {
|
|
switch (fe_status.connect_para.connect_para.cab.mod_type) {
|
|
case EXT_DRV_MOD_TYPE_QAM_64:
|
|
cn_nordig = 23.5; /* 23.5: cn_nordig */
|
|
break;
|
|
case EXT_DRV_MOD_TYPE_QAM_256:
|
|
cn_nordig = 29.5; /* 29.5: cn_nordig */
|
|
break;
|
|
default:
|
|
cn_nordig = 23.5; /* 23.5: cn_nordig */
|
|
break;
|
|
}
|
|
} else if (fe_status.connect_para.sig_type == EXT_DRV_FRONTEND_SIG_TYPE_J83B) {
|
|
switch (fe_status.connect_para.connect_para.cab.mod_type) {
|
|
case EXT_DRV_MOD_TYPE_QAM_64:
|
|
cn_nordig = 24; /* 24: cn_nordig */
|
|
break;
|
|
case EXT_DRV_MOD_TYPE_QAM_256:
|
|
cn_nordig = 30; /* 30: cn_nordig */
|
|
break;
|
|
default:
|
|
cn_nordig = 24; /* 24: cn_nordig */
|
|
break;
|
|
}
|
|
}
|
|
|
|
*snr_sqi = snr - cn_nordig;
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 cab_get_signal_quality(td_u32 tuner_id, td_double snr, td_double ber, td_u32 *signal_quality)
|
|
{
|
|
td_s32 ret;
|
|
td_double snr_sqi = 0;
|
|
td_double sqi;
|
|
td_double temp_ber = ber;
|
|
td_double temp_ber_sqi;
|
|
|
|
if (signal_quality == TD_NULL) {
|
|
soc_log_err("Input parameter(signal_quality) is TD_NULL.\n");
|
|
return SOC_ERR_FRONTEND_INVALID_POINT;
|
|
}
|
|
|
|
ret = cab_get_signal_quality_snr_sqi(tuner_id, snr, &snr_sqi);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(cab_get_signal_quality_snr_sqi, ret);
|
|
return TD_FAILURE;
|
|
}
|
|
soc_dbg_print_u32(snr_sqi);
|
|
|
|
if (fabs(temp_ber) > 1e-6) { /* 1e-6:value */
|
|
temp_ber_sqi = 20 * log10(1 / temp_ber) - 40; /* 20:multi;40:sub */
|
|
/* SQI */
|
|
sqi = ((snr_sqi - 3) / 10 + 1) * temp_ber_sqi + 30; /* 3:sub;10:div;30:plus */
|
|
if (sqi >= 100) { /* 100:value */
|
|
sqi = 100; /* 100:value */
|
|
}
|
|
} else {
|
|
sqi = 100; /* 100:value */
|
|
}
|
|
|
|
*signal_quality = (td_u32)sqi;
|
|
soc_dbg_print_u32(*signal_quality);
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
|
|
#ifdef __cplusplus
|
|
#if __cplusplus
|
|
}
|
|
#endif
|
|
#endif /* __cplusplus */
|
|
|