|
|
/*
|
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2014-2019. All rights reserved.
|
|
|
* Description : vfe part
|
|
|
* Author : sdk
|
|
|
* Create : 2014-12-27
|
|
|
*/
|
|
|
#include "drv_vfe.h"
|
|
|
#include "soc_log.h"
|
|
|
#include "osal_ext.h"
|
|
|
#include "drv_hddec_ext.h"
|
|
|
#include "drv_vfe_offline.h"
|
|
|
#include "drv_vfe_hal.h"
|
|
|
#include "drv_vfe_platform.h"
|
|
|
#include "linux/huanglong/securec.h"
|
|
|
#include "drv_sys_ext.h"
|
|
|
|
|
|
/************************** macro definition start***************************/
|
|
|
/* function moudle definition */
|
|
|
/* 同时支持TVD和HDDEC通路,同时需要修改TVD_SAMPLE_RATE_FROM_VFE为75000000 */
|
|
|
#define TVD_SAMPLE_RATE_FROM_VFE_TWO_ROUTE 75000000
|
|
|
|
|
|
/* macro definition for constant value */
|
|
|
#define VFE_CRYSTAL_FREQ 24000 /* k_hz */
|
|
|
#define VFE_U32_MAX 0xFFFFFFFF
|
|
|
|
|
|
#define VFE_CHAN_MAX 4
|
|
|
#define VFE_CLAMP_LEVEL_MAX 0x10
|
|
|
#define VFE_SLICER_LEVEL_DEF 8 // 23 // 10 // 0x15 // 0x17 // 0x10
|
|
|
|
|
|
#define VFE_APLL_CLK_MIN 1300000
|
|
|
#define VFE_APLL_CLK_MAX 2600000 // 单位为k_hz, APLL最佳工作时钟范围时1300M到2600M
|
|
|
#define VFE_APLL_CLK_BEST 1900000 /* 单位为k_hz, APLL最佳工作时钟为1600M */
|
|
|
|
|
|
#define VFE_APLL_POST_DIV_MAX 7 // postdiv1和postdiv2范围为1到7倍
|
|
|
|
|
|
#define VFE_DEF_REF_DIV 1
|
|
|
|
|
|
#define VFE_PHASE_DEF 28
|
|
|
#define VFE_PHASE_MAX 0x20
|
|
|
|
|
|
#define VFE_HTOTAL_DEF 1650
|
|
|
#define VFE_CLOCK_DEF 74250 /* 720p@60_hz */
|
|
|
|
|
|
#define VFE_GAIN_DEF 0
|
|
|
#define VFE_OFFSET_DEF 0x80
|
|
|
|
|
|
#define VFE_GAIN_MAX 0x20
|
|
|
#define VFE_OFFSET_MAX 0xFF
|
|
|
#define VFE_SIF_GAIN_MAX 32 /* 单独sif输入的增益调整0到31db */
|
|
|
#define VFE_SIF_OFFSET_MAX 0x100
|
|
|
|
|
|
#define VFE_PRE_CAL_PIN 0x03
|
|
|
#define VFE_PRE_GAIN_CNT 0x30
|
|
|
|
|
|
#define VFE_CVBS_PIN_N 0
|
|
|
#define VFE_RF_PIN_N 0
|
|
|
|
|
|
#define VFE_VDAC_GAIN_MAX 0x7F /* 0xFF, modified from new equator data sheet */
|
|
|
#define VFE_VDAC_GAIN_ADDR 0x49d /* OTP VDAC1 GAIN ADDR */
|
|
|
#define VFE_VDAC_GAIN_I 0xc4 /* 通过电流调节的GAIN值 */
|
|
|
#define VFE_PLL_PHASE_LOCK_THR 0x10
|
|
|
|
|
|
#define INVALID_PRECAL_GAIN 0x7FFFFF00
|
|
|
#define BASE_PRECAL_GAIN 0x40000000
|
|
|
#define INVALID_PRECAL_OFFSET 0xFFFFFFC0
|
|
|
#define BASE_PRECAL_OFFSET 0
|
|
|
|
|
|
#define VFE_DAC_GAIN_DEF 0x33 // 0x3F // 0x20
|
|
|
|
|
|
/*************************** macro definition end****************************/
|
|
|
/************************** static declaration start*************************/
|
|
|
vfe_drv_ctx g_vfe_drv_ctx[VFE_WORKMODE_MAX];
|
|
|
|
|
|
static td_u32 g_get_pass_dpll_div[VFE_DPLL_DIV_BUTT] = {
|
|
|
16, // VFE_DPLL_DIV_16
|
|
|
32, // VFE_DPLL_DIV_32
|
|
|
64, // VFE_DPLL_DIV_64
|
|
|
128, // VFE_DPLL_DIV_128
|
|
|
};
|
|
|
|
|
|
/*************************** static declaration end**************************/
|
|
|
|
|
|
static td_void vfe_get_rgb_chn_mux1_val(const ext_drv_vfe_source_attr *source,
|
|
|
td_u32 *r_mux1_val, td_u32 *g_mux1_val, td_u32 *b_mux1_val)
|
|
|
{
|
|
|
*r_mux1_val = INVLIAD_MUX_VAL;
|
|
|
*g_mux1_val = INVLIAD_MUX_VAL;
|
|
|
*b_mux1_val = INVLIAD_MUX_VAL;
|
|
|
|
|
|
vfe_platform_get_rgb_mux1_val(source, r_mux1_val, g_mux1_val, b_mux1_val);
|
|
|
if (*r_mux1_val == INVLIAD_MUX_VAL || *g_mux1_val == INVLIAD_MUX_VAL || *b_mux1_val == INVLIAD_MUX_VAL) {
|
|
|
*r_mux1_val = 0;
|
|
|
*g_mux1_val = 0;
|
|
|
*b_mux1_val = 0;
|
|
|
soc_log_err("invalid input RGB channel:\n");
|
|
|
soc_err_print_u32(source->r_chn_mux);
|
|
|
soc_err_print_u32(source->g_chn_mux);
|
|
|
soc_err_print_u32(source->b_chn_mux);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
static td_void vfe_get_cvbs_chn_mux1_val(ext_drv_input_mux cvbs_chn_mux, td_u32 *cvbs_mux1_val)
|
|
|
{
|
|
|
*cvbs_mux1_val = 0;
|
|
|
|
|
|
if (cvbs_chn_mux == EXT_DRV_INPUT_MUX_CVBS0) {
|
|
|
*cvbs_mux1_val = 0;
|
|
|
} else if (cvbs_chn_mux == EXT_DRV_INPUT_MUX_CVBS1) {
|
|
|
*cvbs_mux1_val = 1;
|
|
|
} else if (cvbs_chn_mux == EXT_DRV_INPUT_MUX_CVBS2) {
|
|
|
*cvbs_mux1_val = 2; // set value to 2
|
|
|
} else if (cvbs_chn_mux == EXT_DRV_INPUT_MUX_CVBS3) {
|
|
|
*cvbs_mux1_val = 3; // set value to 3
|
|
|
} else {
|
|
|
soc_log_err("invalid input CVBS channel: \n");
|
|
|
soc_err_print_u32(cvbs_chn_mux);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
td_void drv_vfe_check_r_chn_mux(const ext_drv_vfe_source_attr *source, td_bool *adc_chan_r_used,
|
|
|
td_bool *adc_chan_g_used, td_bool *adc_chan_b_used)
|
|
|
{
|
|
|
if (source == TD_NULL || adc_chan_r_used == TD_NULL || adc_chan_g_used == TD_NULL ||
|
|
|
adc_chan_b_used == TD_NULL) {
|
|
|
soc_log_err("input null pointer!\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (is_chan_r_in(source->r_chn_mux)) {
|
|
|
*adc_chan_r_used = TD_TRUE;
|
|
|
}
|
|
|
|
|
|
if (is_chan_g_in(source->r_chn_mux)) {
|
|
|
*adc_chan_g_used = TD_TRUE;
|
|
|
}
|
|
|
|
|
|
if (is_chan_b_in(source->r_chn_mux)) {
|
|
|
*adc_chan_b_used = TD_TRUE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
td_s32 drv_vfe_check_g_chn_mux(const ext_drv_vfe_source_attr *source, td_bool *adc_chan_r_used,
|
|
|
td_bool *adc_chan_g_used, td_bool *adc_chan_b_used)
|
|
|
{
|
|
|
if (source == TD_NULL || adc_chan_r_used == TD_NULL || adc_chan_g_used == TD_NULL ||
|
|
|
adc_chan_b_used == TD_NULL) {
|
|
|
soc_log_err("input null pointer!\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (is_chan_r_in(source->g_chn_mux)) {
|
|
|
if (*adc_chan_r_used == TD_TRUE) {
|
|
|
return TD_FAILURE;
|
|
|
} else {
|
|
|
*adc_chan_r_used = TD_TRUE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (is_chan_g_in(source->g_chn_mux)) {
|
|
|
if (*adc_chan_g_used == TD_TRUE) {
|
|
|
return TD_FAILURE;
|
|
|
} else {
|
|
|
*adc_chan_g_used = TD_TRUE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (is_chan_b_in(source->g_chn_mux)) {
|
|
|
if (*adc_chan_b_used == TD_TRUE) {
|
|
|
return TD_FAILURE;
|
|
|
} else {
|
|
|
*adc_chan_b_used = TD_TRUE;
|
|
|
}
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 drv_vfe_check_b_chn_mux(const ext_drv_vfe_source_attr *source, td_bool *adc_chan_r_used,
|
|
|
td_bool *adc_chan_g_used, td_bool *adc_chan_b_used)
|
|
|
{
|
|
|
if (source == TD_NULL || adc_chan_r_used == TD_NULL || adc_chan_g_used == TD_NULL ||
|
|
|
adc_chan_b_used == TD_NULL) {
|
|
|
soc_log_err("input null pointer!\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (is_chan_r_in(source->b_chn_mux)) {
|
|
|
if (*adc_chan_r_used == TD_TRUE) {
|
|
|
return TD_FAILURE;
|
|
|
} else {
|
|
|
*adc_chan_r_used = TD_TRUE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (is_chan_g_in(source->b_chn_mux)) {
|
|
|
if (*adc_chan_g_used == TD_TRUE) {
|
|
|
return TD_FAILURE;
|
|
|
} else {
|
|
|
*adc_chan_g_used = TD_TRUE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (is_chan_b_in(source->b_chn_mux)) {
|
|
|
if (*adc_chan_b_used == TD_TRUE) {
|
|
|
return TD_FAILURE;
|
|
|
} else {
|
|
|
*adc_chan_b_used = TD_TRUE;
|
|
|
}
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 drv_vfe_check_rgb_chn_mux(const ext_drv_vfe_source_attr *source)
|
|
|
{
|
|
|
td_s32 ret;
|
|
|
td_bool adc_chan_r_used = TD_FALSE;
|
|
|
td_bool adc_chan_g_used = TD_FALSE;
|
|
|
td_bool adc_chan_b_used = TD_FALSE;
|
|
|
|
|
|
drv_vfe_check_r_chn_mux(source, &adc_chan_r_used, &adc_chan_g_used, &adc_chan_b_used);
|
|
|
|
|
|
ret = drv_vfe_check_g_chn_mux(source, &adc_chan_r_used, &adc_chan_g_used, &adc_chan_b_used);
|
|
|
if (ret == TD_FAILURE) {
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
ret = drv_vfe_check_b_chn_mux(source, &adc_chan_r_used, &adc_chan_g_used, &adc_chan_b_used);
|
|
|
if (ret == TD_FAILURE) {
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (adc_chan_r_used == TD_FALSE || adc_chan_g_used == TD_FALSE || adc_chan_b_used == TD_FALSE) {
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_void drv_vfe_print_rgb_chn_mux(const ext_drv_vfe_source_attr *source)
|
|
|
{
|
|
|
soc_log_err("invalid input RGB channel:\n");
|
|
|
if (source != TD_NULL) {
|
|
|
soc_err_print_u32(source->r_chn_mux);
|
|
|
soc_err_print_u32(source->g_chn_mux);
|
|
|
soc_err_print_u32(source->b_chn_mux);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static td_s32 vfe_check_input_attr(const ext_drv_vfe_source_attr *source)
|
|
|
{
|
|
|
td_s32 ret;
|
|
|
switch (source->work_mode) {
|
|
|
case EXT_DRV_VFE_WORK_MODE_HDDEC: {
|
|
|
ret = drv_vfe_check_rgb_chn_mux(source);
|
|
|
if (ret == TD_FAILURE) {
|
|
|
drv_vfe_print_rgb_chn_mux(source);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_WORK_MODE_TVD: {
|
|
|
if (!is_cvbs_in(source->cvbs_chn_mux)) {
|
|
|
soc_log_err("invalid input CVBS channel:\n");
|
|
|
soc_err_print_u32(source->cvbs_chn_mux);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_WORK_MODE_TVD_SVIDEO: {
|
|
|
if (!is_cvbs_in(source->sy_chn_mux) || (!is_cvbs_in(source->sc_chn_mux))) {
|
|
|
soc_log_err("invalid input sy_chn_mux or sc_chn_mux channel:\n");
|
|
|
soc_err_print_u32(source->cvbs_chn_mux);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
default: {
|
|
|
soc_log_err("invalid input work mode:\n");
|
|
|
soc_err_print_u32(source->work_mode);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (source->sog_chn_mux >= EXT_DRV_INPUT_MUX_SOG_MAX) {
|
|
|
soc_log_err(" invalid input com channel:\n");
|
|
|
soc_err_print_u32(source->sog_chn_mux);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (source->sync_chn_mux >= EXT_DRV_INPUT_MUX_SYNC_MAX) {
|
|
|
soc_log_err(" invalid input slicer1 channel:\n");
|
|
|
soc_err_print_u32(source->sync_chn_mux);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
static td_s32 vfe_check_pll_attr(const ext_drv_vfe_pll_attr *pll_attr)
|
|
|
{
|
|
|
if (pll_attr == NULL) {
|
|
|
soc_log_err("NULL point \n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if ((pll_attr->bypass_dpll != TD_TRUE) && (pll_attr->bypass_dpll != TD_FALSE)) {
|
|
|
soc_log_err("invalid pll bypass dpll value:\n");
|
|
|
soc_err_print_u32(pll_attr->bypass_dpll);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (pll_attr->sample_clk <= 0) {
|
|
|
soc_log_err("invalid pll sample clk value:\n");
|
|
|
soc_err_print_u32(pll_attr->sample_clk);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (pll_attr->h_total <= 0) {
|
|
|
soc_log_err("invalid pll htotal value:\n");
|
|
|
soc_err_print_u32(pll_attr->h_total);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
static td_s32 vfe_check_clamp_attr(const ext_drv_vfe_clamp_attr *clamp)
|
|
|
{
|
|
|
const ext_drv_vfe_vclamp_attr *vclamp_attr = NULL;
|
|
|
const ext_drv_vfe_iclamp_attr *iclamp_attr = NULL;
|
|
|
|
|
|
if (clamp->clamp_type >= EXT_DRV_VFE_CLAMP_MAX) {
|
|
|
soc_log_err("invalid clamp type :\n");
|
|
|
soc_err_print_u32(clamp->clamp_type);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (clamp->clamp_type != EXT_DRV_VFE_CLAMP_I) {
|
|
|
vclamp_attr = &clamp->vclamp_attr;
|
|
|
|
|
|
if (vclamp_attr->vclamp_type >= EXT_DRV_VFE_VCLAMP_ON_MAX) {
|
|
|
soc_log_err("invalid v clamp type :\n");
|
|
|
soc_err_print_u32(vclamp_attr->vclamp_type);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (vclamp_attr->blk_level >= EXT_DRV_VFE_VCLAMP_BLK_MAX) {
|
|
|
soc_log_err("invalid v clamp blank value :\n");
|
|
|
soc_err_print_u32(vclamp_attr->blk_level);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (vclamp_attr->mid_level >= EXT_DRV_VFE_VCLAMP_MID_MAX) {
|
|
|
soc_log_err("invalid v clamp middle value :\n");
|
|
|
soc_err_print_u32(vclamp_attr->mid_level);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (clamp->clamp_type != EXT_DRV_VFE_CLAMP_V) {
|
|
|
iclamp_attr = &clamp->iclamp_attr;
|
|
|
|
|
|
if (iclamp_attr->imax_type >= EXT_DRV_VFE_IMAX_TYPE_MAX) {
|
|
|
soc_log_err("invalid i clamp imax type :\n");
|
|
|
soc_err_print_u32(iclamp_attr->imax_type);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (iclamp_attr->iclamp_level >= VFE_CLAMP_LEVEL_MAX) {
|
|
|
soc_log_err("invalid i clamp level value :\n");
|
|
|
soc_err_print_u32(iclamp_attr->iclamp_level);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
static td_s32 vfe_check_lpf_attr(const ext_drv_vfe_lpf_filter_attr *lpf_attr)
|
|
|
{
|
|
|
if (lpf_attr->rgb_chn_lpf_mode >= EXT_DRV_VFE_LPF_MODE_MAX) {
|
|
|
soc_log_err("invalid rg_bchn lpf mode :\n");
|
|
|
soc_err_print_u32(lpf_attr->rgb_chn_lpf_mode);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if ((lpf_attr->com_chn_filter.filter_en != TD_FALSE)
|
|
|
&& (lpf_attr->com_chn_filter.filter_en != TD_TRUE)) {
|
|
|
soc_log_err("invalid comchn filter enable value :\n");
|
|
|
soc_err_print_u32(lpf_attr->com_chn_filter.filter_en);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (lpf_attr->com_chn_filter.filter_ib >= EXT_DRV_VFE_FILTER_IB_MAX) {
|
|
|
soc_log_err("invalid comchn filter ib value :\n");
|
|
|
soc_err_print_u32(lpf_attr->com_chn_filter.filter_ib);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (lpf_attr->com_chn_filter.filter_r >= EXT_DRV_VFE_FILTER_R_MAX) {
|
|
|
soc_log_err("invalid comchn filter r value :\n");
|
|
|
soc_err_print_u32(lpf_attr->com_chn_filter.filter_r);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
static td_s32 vfe_calcu_pass_dpll_cfg(td_u32 sample_clk, vfe_dpll_div_sel *dpll_div,
|
|
|
td_u32 *int_mult, td_u32 *frac_mult)
|
|
|
{
|
|
|
vfe_dpll_div_sel dpll_div_sel, best_dpll_div;
|
|
|
td_u32 temp_div, temp_diff, min_diff, temp_apll_clk, best_apll_clk;
|
|
|
td_u32 inter_mult;
|
|
|
td_u32 fra_mult;
|
|
|
td_u64 tmep;
|
|
|
|
|
|
min_diff = VFE_U32_MAX;
|
|
|
best_dpll_div = VFE_DPLL_DIV_16;
|
|
|
best_apll_clk = VFE_APLL_CLK_BEST;
|
|
|
|
|
|
soc_dbg_print_u32(sample_clk);
|
|
|
|
|
|
/* APLL的VCO时钟从小到大遍历 */
|
|
|
for (dpll_div_sel = VFE_DPLL_DIV_16; dpll_div_sel < VFE_DPLL_DIV_BUTT; dpll_div_sel++) {
|
|
|
temp_div = g_get_pass_dpll_div[dpll_div_sel];
|
|
|
temp_apll_clk = sample_clk * temp_div;
|
|
|
soc_dbg_print_u32(temp_apll_clk);
|
|
|
if ((temp_apll_clk < VFE_APLL_CLK_MIN) || (temp_apll_clk > VFE_APLL_CLK_MAX)) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
temp_diff = abs(VFE_APLL_CLK_BEST - temp_apll_clk);
|
|
|
soc_dbg_print_u32(dpll_div_sel);
|
|
|
soc_dbg_print_u32(temp_diff);
|
|
|
|
|
|
if (temp_diff < min_diff) {
|
|
|
min_diff = temp_diff;
|
|
|
best_dpll_div = dpll_div_sel;
|
|
|
best_apll_clk = temp_apll_clk;
|
|
|
soc_dbg_print_u32(temp_diff);
|
|
|
soc_dbg_print_u32(min_diff);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
*dpll_div = best_dpll_div;
|
|
|
inter_mult = best_apll_clk / VFE_CRYSTAL_FREQ;
|
|
|
tmep = best_apll_clk % VFE_CRYSTAL_FREQ;
|
|
|
tmep <<= 24; // mv left 24 bits
|
|
|
do_div(tmep, VFE_CRYSTAL_FREQ);
|
|
|
fra_mult = tmep & 0xFFFFFF;
|
|
|
*int_mult = inter_mult & 0xFFF;
|
|
|
*frac_mult = fra_mult & 0xFFFFFF;
|
|
|
soc_dbg_print_u32(*dpll_div);
|
|
|
soc_dbg_print_u32(*int_mult);
|
|
|
soc_dbg_print_u32(*frac_mult);
|
|
|
soc_dbg_print_u32(best_apll_clk);
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
static td_void vfe_calcu_bypass_dpll_cfg1(td_u32 sample_clk, td_u32 *int_mult,
|
|
|
td_u32 *post_div1, td_u32 *post_div2)
|
|
|
{
|
|
|
td_u32 post_div_index1, post_div_index2;
|
|
|
td_u32 best_post_div1 = 0;
|
|
|
td_u32 best_post_div2 = 0;
|
|
|
td_u32 temp_diff, temp_apll_clk, temp_frac;
|
|
|
td_u32 int_min_diff;
|
|
|
td_u32 best_int_apll_clk = 0;
|
|
|
|
|
|
int_min_diff = VFE_U32_MAX;
|
|
|
|
|
|
for (post_div_index1 = 1; post_div_index1 <= VFE_APLL_POST_DIV_MAX; post_div_index1++) {
|
|
|
for (post_div_index2 = 1; post_div_index2 <= VFE_APLL_POST_DIV_MAX; post_div_index2++) {
|
|
|
temp_apll_clk = sample_clk * post_div_index1 * post_div_index2;
|
|
|
if ((temp_apll_clk < VFE_APLL_CLK_MIN) || (temp_apll_clk > VFE_APLL_CLK_MAX)) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
temp_frac = temp_apll_clk % VFE_CRYSTAL_FREQ;
|
|
|
temp_diff = abs(VFE_APLL_CLK_BEST - temp_apll_clk);
|
|
|
if (temp_frac == 0 && temp_diff < int_min_diff) {
|
|
|
int_min_diff = temp_diff;
|
|
|
best_int_apll_clk = temp_apll_clk;
|
|
|
best_post_div1 = post_div_index1;
|
|
|
best_post_div2 = post_div_index2;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
*int_mult = best_int_apll_clk / VFE_CRYSTAL_FREQ;
|
|
|
*post_div1 = best_post_div1;
|
|
|
*post_div2 = best_post_div2;
|
|
|
soc_dbg_print_u32(*int_mult);
|
|
|
soc_dbg_print_u32(*post_div1);
|
|
|
soc_dbg_print_u32(*post_div2);
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
td_void vfe_hal_set_fnpll(td_void)
|
|
|
{
|
|
|
vfe_hal_reg_write(0xDC0, 0x1);
|
|
|
vfe_hal_reg_write(0xDD0, 0x40430022);
|
|
|
vfe_hal_reg_write(0xDE0, 0x5F);
|
|
|
vfe_hal_reg_write(0xDF0, 0x800180A6);
|
|
|
vfe_hal_reg_write(0xE00, 0x0028A285);
|
|
|
}
|
|
|
|
|
|
static td_void vfe_calcu_bypass_dpll_cfg2(td_u32 sample_clk, td_u32 *int_mult,
|
|
|
td_u32 *post_div1, td_u32 *post_div2)
|
|
|
{
|
|
|
td_u32 div_index1, div_index2;
|
|
|
td_u32 best_post_div1 = 0;
|
|
|
td_u32 best_post_div2 = 0;
|
|
|
td_u32 temp_diff, temp_apll_clk, temp_frac;
|
|
|
td_u32 min_diff = VFE_U32_MAX;
|
|
|
td_u32 best_int_apll_clk = 0;
|
|
|
|
|
|
for (div_index1 = 1; div_index1 <= VFE_APLL_POST_DIV_MAX; div_index1++) {
|
|
|
for (div_index2 = 1; div_index2 <= VFE_APLL_POST_DIV_MAX; div_index2++) {
|
|
|
temp_apll_clk = sample_clk * div_index1 * div_index2;
|
|
|
if ((temp_apll_clk < 1500000) || (temp_apll_clk > 2800000)) { /* clock min value 1500000, max 2800000 */
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
temp_frac = temp_apll_clk % VFE_CRYSTAL_FREQ;
|
|
|
temp_diff = 2800000 - temp_apll_clk; /* max clock value 2800000 */
|
|
|
if (temp_frac == 0 && temp_diff < min_diff) {
|
|
|
min_diff = temp_diff;
|
|
|
best_int_apll_clk = temp_apll_clk;
|
|
|
best_post_div1 = div_index1;
|
|
|
best_post_div2 = div_index2;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
*int_mult = best_int_apll_clk / VFE_CRYSTAL_FREQ;
|
|
|
*post_div1 = best_post_div1 - 1;
|
|
|
*post_div2 = best_post_div2 - 1;
|
|
|
soc_dbg_print_u32(*int_mult);
|
|
|
soc_dbg_print_u32(*post_div1);
|
|
|
soc_dbg_print_u32(*post_div2);
|
|
|
vfe_hal_set_fnpll();
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
static td_void vfe_calcu_bypass_dpll_cfg(td_u32 sample_clk, td_u32 *int_mult,
|
|
|
td_u32 *post_div1, td_u32 *post_div2)
|
|
|
{
|
|
|
ext_chip_name_id name_id = CHIP_NAME_RESERVED13;
|
|
|
ext_chip_revision chip_revision = CHIP_REVISION_MAX;
|
|
|
|
|
|
td_s32 ret = ext_drv_sys_get_chip_name_id(&name_id);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
soc_log_err("ext_drv_sys_get_chip_name_id error \n");
|
|
|
return;
|
|
|
}
|
|
|
ret = ext_drv_sys_get_chip_revision(&chip_revision);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
soc_err_print_call_fun_err(ext_drv_sys_get_chip_revision, ret);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if ((name_id == CHIP_NAME_RESERVED17 || name_id == CHIP_NAME_RESERVED19 ||
|
|
|
name_id == CHIP_NAME_HI3751V811) && chip_revision == CHIP_REVISION_C) {
|
|
|
vfe_calcu_bypass_dpll_cfg2(sample_clk, int_mult, post_div1, post_div2);
|
|
|
} else {
|
|
|
vfe_calcu_bypass_dpll_cfg1(sample_clk, int_mult, post_div1, post_div2);
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
td_s32 vfe_set_no_sig_pll_attr(ext_drv_vfe_pll_attr *pll_attr)
|
|
|
{
|
|
|
td_s32 ret;
|
|
|
td_u32 int_mult = 0;
|
|
|
const td_u32 frac_mult = 0;
|
|
|
td_u32 post_div1 = 0;
|
|
|
td_u32 post_div2 = 0;
|
|
|
td_bool dpll_fp_reset, dpll_lpf_reset, apll_coeff_en;
|
|
|
td_u32 temp_h_freq;
|
|
|
const td_u32 max_h_total = 4095; /* h_total寄存器为12bit最大为4095 */
|
|
|
|
|
|
ret = vfe_check_pll_attr(pll_attr);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
soc_log_err(" some attr of pll attr is invalid\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
temp_h_freq = pll_attr->sample_clk / pll_attr->h_total;
|
|
|
|
|
|
if (pll_attr->h_total > max_h_total) {
|
|
|
pll_attr->sample_clk = pll_attr->sample_clk * max_h_total / pll_attr->h_total;
|
|
|
pll_attr->h_total = max_h_total;
|
|
|
}
|
|
|
|
|
|
vfe_hal_set_apll_bypass(TD_FALSE);
|
|
|
/* 复位MPG */
|
|
|
vfe_hal_set_mpg_reset(TD_TRUE);
|
|
|
|
|
|
/* pll启动时序要求 */
|
|
|
vfe_hal_set_apll_coeff_en(TD_FALSE); /* DPLL环路处于断开状态,为SDP模式,闭合为CP模式 */
|
|
|
vfe_hal_set_dpll_ff_reset(TD_FALSE); /* ff_rst_n复位 */
|
|
|
vfe_hal_set_apll_power(TD_FALSE, TD_FALSE); /* apll power down */
|
|
|
vfe_hal_set_dpll_lpf_fbdiv_reset(TD_FALSE); /* lpf_fbdiv_rst_n 复位 */
|
|
|
vfe_hal_set_apll_post_out_en(pll_attr->bypass_dpll); /* 选择是否时钟输出是否bypass DPLL,直接通过APLL的POSTDIV输出 */
|
|
|
|
|
|
vfe_calcu_bypass_dpll_cfg(pll_attr->sample_clk, &int_mult, &post_div1, &post_div2);
|
|
|
vfe_hal_set_apll_int_cfg(int_mult);
|
|
|
vfe_hal_set_apll_frac_cfg(frac_mult);
|
|
|
vfe_hal_set_apll_post_div(post_div1, post_div2);
|
|
|
|
|
|
vfe_hal_set_dpll_htotal_cfg(VFE_DPLL_DIV_32, pll_attr->h_total);
|
|
|
vfe_hal_set_dpll_pdiv_cfg(VFE_DPLL_DIV_64);
|
|
|
dpll_fp_reset = TD_TRUE;
|
|
|
dpll_lpf_reset = TD_TRUE;
|
|
|
apll_coeff_en = TD_FALSE;
|
|
|
|
|
|
vfe_hal_set_dpll_ff_reset(dpll_fp_reset); /* ff_rst_n撤销复位 */
|
|
|
vfe_hal_set_apll_power(TD_TRUE, TD_TRUE); /* apll power on */
|
|
|
osal_msleep(5); // sleep for 5 ms
|
|
|
vfe_hal_set_apll_coeff_en(apll_coeff_en); /* DPLL环路处于闭合状态则表示为pass dpll */
|
|
|
vfe_hal_set_dpll_lpf_fbdiv_reset(dpll_lpf_reset); /* lpf_fbdiv_rst_n 撤销复位 */
|
|
|
osal_msleep(10); // sleep for 10 ms
|
|
|
/* 撤销复位MPG */
|
|
|
vfe_hal_set_mpg_reset(TD_FALSE);
|
|
|
osal_msleep(10); // sleep for 10 ms
|
|
|
vfe_hal_set_adc_clk_sel(VFE_ADCCHN_CLK_SEL_DPLL);
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_void drv_vfe_pll_reset(const ext_drv_vfe_pll_attr *pll_attr)
|
|
|
{
|
|
|
vfe_hal_set_apll_bypass(TD_FALSE);
|
|
|
/* 复位MPG */
|
|
|
vfe_hal_set_mpg_reset(TD_TRUE);
|
|
|
/* pll启动时序要求 */
|
|
|
vfe_hal_set_apll_coeff_en(TD_FALSE); /* DPLL环路处于断开状态,为SDP模式,闭合为CP模式 */
|
|
|
vfe_hal_set_dpll_ff_reset(TD_FALSE); /* ff_rst_n复位 */
|
|
|
vfe_hal_set_apll_power(TD_FALSE, TD_FALSE); /* apll power down */
|
|
|
vfe_hal_set_dpll_lpf_fbdiv_reset(TD_FALSE); /* lpf_fbdiv_rst_n 复位 */
|
|
|
/* 选择是否时钟输出是否bypass DPLL,直接通过APLL的POSTDIV输出 */
|
|
|
if (pll_attr != TD_NULL) {
|
|
|
vfe_hal_set_apll_post_out_en(pll_attr->bypass_dpll);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
td_void drv_vfe_pll_de_reset(td_bool dpll_fp_reset, td_bool dpll_lpf_reset, td_bool apll_coeff_en)
|
|
|
{
|
|
|
vfe_hal_set_dpll_ff_reset(dpll_fp_reset); /* ff_rst_n撤销复位 */
|
|
|
vfe_hal_set_apll_power(TD_TRUE, TD_TRUE); /* apll power on */
|
|
|
|
|
|
osal_msleep(5); // sleep for 5 ms
|
|
|
|
|
|
vfe_hal_set_apll_coeff_en(apll_coeff_en); /* DPLL环路处于闭合状态则表示为pass dpll */
|
|
|
vfe_hal_set_dpll_lpf_fbdiv_reset(dpll_lpf_reset); /* lpf_fbdiv_rst_n 撤销复位 */
|
|
|
vfe_platform_set_rgb_com_chn_adc_reset();
|
|
|
|
|
|
osal_msleep(10); // sleep for 10 ms
|
|
|
|
|
|
/* 撤销复位MPG */
|
|
|
vfe_hal_set_mpg_reset(TD_FALSE);
|
|
|
osal_msleep(10); // sleep for 10 ms
|
|
|
vfe_hal_set_adc_clk_sel(VFE_ADCCHN_CLK_SEL_DPLL);
|
|
|
}
|
|
|
|
|
|
td_void drv_vfe_set_pll_cfg(td_bool *dpll_fp_reset, td_bool *dpll_lpf_reset,
|
|
|
td_bool *apll_coeff_en, td_bool flag)
|
|
|
{
|
|
|
if (dpll_fp_reset == TD_NULL || dpll_lpf_reset == TD_NULL || apll_coeff_en == TD_NULL) {
|
|
|
soc_log_err("input null point.\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (flag == TD_FALSE) {
|
|
|
*dpll_fp_reset = TD_FALSE;
|
|
|
*dpll_lpf_reset = TD_FALSE;
|
|
|
*apll_coeff_en = TD_FALSE;
|
|
|
} else if (flag == TD_TRUE) {
|
|
|
*dpll_fp_reset = TD_TRUE;
|
|
|
*dpll_lpf_reset = TD_TRUE;
|
|
|
*apll_coeff_en = TD_TRUE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
td_s32 vfe_set_pll_attr(ext_drv_vfe_pll_attr *pll_attr, td_u32 phase)
|
|
|
{
|
|
|
td_s32 ret;
|
|
|
td_u32 int_mult = 0;
|
|
|
td_u32 frac_mult = 0;
|
|
|
td_u32 post_div1 = 0;
|
|
|
td_u32 post_div2 = 0;
|
|
|
td_bool dpll_fp_reset = TD_FALSE;
|
|
|
td_bool dpll_lpf_reset = TD_FALSE;
|
|
|
td_bool apll_coeff_en = TD_FALSE;
|
|
|
vfe_dpll_div_sel dpll_div = VFE_DPLL_DIV_64;
|
|
|
td_u32 temp_h_freq;
|
|
|
const td_u32 max_h_total = 4095; /* h_total寄存器为12bit最大为4095 */
|
|
|
|
|
|
ret = vfe_check_pll_attr(pll_attr);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
soc_log_err(" some attr of pll attr is invalid\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
temp_h_freq = pll_attr->sample_clk / pll_attr->h_total;
|
|
|
if (pll_attr->h_total > max_h_total) {
|
|
|
pll_attr->sample_clk = pll_attr->sample_clk * max_h_total / pll_attr->h_total;
|
|
|
pll_attr->h_total = max_h_total;
|
|
|
}
|
|
|
|
|
|
drv_vfe_pll_reset(pll_attr);
|
|
|
|
|
|
if (pll_attr->bypass_dpll) {
|
|
|
soc_log_dbg("PLL set bypass dpll [CVBS MODE]\n");
|
|
|
vfe_calcu_bypass_dpll_cfg(pll_attr->sample_clk, &int_mult, &post_div1, &post_div2);
|
|
|
vfe_hal_set_apll_int_cfg(int_mult);
|
|
|
vfe_hal_set_apll_frac_cfg(frac_mult);
|
|
|
vfe_hal_set_apll_post_div(post_div1, post_div2);
|
|
|
|
|
|
drv_vfe_set_pll_cfg(&dpll_fp_reset, &dpll_lpf_reset, &apll_coeff_en, TD_FALSE);
|
|
|
} else {
|
|
|
soc_log_dbg("PLL set dpll [HDDEC MODE]\n");
|
|
|
vfe_calcu_pass_dpll_cfg(pll_attr->sample_clk, &dpll_div, &int_mult, &frac_mult);
|
|
|
vfe_hal_set_apll_int_cfg(int_mult);
|
|
|
vfe_hal_set_apll_frac_cfg(frac_mult);
|
|
|
if (dpll_div == VFE_DPLL_DIV_32) {
|
|
|
dpll_div = VFE_DPLL_DIV_64;
|
|
|
} else if (dpll_div == VFE_DPLL_DIV_64) {
|
|
|
dpll_div = VFE_DPLL_DIV_32;
|
|
|
}
|
|
|
vfe_hal_set_dpll_htotal_cfg(dpll_div, pll_attr->h_total);
|
|
|
vfe_hal_set_dpll_pdiv_cfg(dpll_div);
|
|
|
vfe_hal_platform_set_rg_pll_cfg();
|
|
|
vfe_hal_platform_set_rg_offset_cfg();
|
|
|
/* pll配置会影响相位,需要重新配置一下 */
|
|
|
drv_vfe_set_pll_cfg(&dpll_fp_reset, &dpll_lpf_reset, &apll_coeff_en, TD_TRUE);
|
|
|
}
|
|
|
|
|
|
drv_vfe_pll_de_reset(dpll_fp_reset, dpll_lpf_reset, apll_coeff_en);
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
static td_void vfe_sync_slicer_init(td_void)
|
|
|
{
|
|
|
vfe_syncslicer_attr slicer_attr = { 0 };
|
|
|
|
|
|
slicer_attr.sync_clamp = VFE_SYNC_CLAMP_ANALOG;
|
|
|
slicer_attr.clamp_level = VFE_SYNC_CLAMP_LEVEL_1_25V; // VFE_SYNC_CLAMP_LEVEL_1_25V, VFE_SYNC_CLAMP_LEVEL_0_95V
|
|
|
slicer_attr.slicer_lpf = VFE_SLICER_LPF_OFF;
|
|
|
slicer_attr.slicer_ilkg = VFE_SLICER_ILKG_800N_A; // VFE_SLICER_ILKG_0N_A
|
|
|
slicer_attr.deglitch = TD_TRUE; // TD_FALSE
|
|
|
|
|
|
vfe_hal_set_sync1_slicer(&slicer_attr);
|
|
|
vfe_hal_set_slicer1_level(VFE_SLICER_LEVEL_DEF);
|
|
|
|
|
|
vfe_hal_set_sync2_slicer(&slicer_attr);
|
|
|
vfe_hal_set_slicer2_level(VFE_SLICER_LEVEL_DEF);
|
|
|
|
|
|
vfe_hal_set_slicer_power(TD_TRUE, TD_TRUE);
|
|
|
|
|
|
vfe_hal_set_hs0_in_cfg(VFE_HS_ROUTE_SEL_SMMIT_TRIGGER, TD_TRUE);
|
|
|
vfe_hal_set_hs1_in_cfg(VFE_HS_ROUTE_SEL_SMMIT_TRIGGER, TD_TRUE);
|
|
|
vfe_hal_set_vs0_in_cfg(VFE_VS_ROUTE_HDDEC);
|
|
|
vfe_hal_set_vs1_in_cfg(VFE_VS_ROUTE_HDDEC);
|
|
|
#ifdef CONFIG_SOCT_FPGA_SUPPORT
|
|
|
vfe_hal_set_dpll_fre_div_reset(VFE_FRE_DIV_RST_SEL_ASYNC_CTRL, TD_FALSE);
|
|
|
#else
|
|
|
vfe_hal_set_dpll_fre_div_reset(VFE_FRE_DIV_RST_SEL_VCOAST_CTRL, TD_FALSE);
|
|
|
#endif
|
|
|
|
|
|
/* equator 时钟正反向 */
|
|
|
vfe_hal_set_cvbs_rgb_pctrl(TD_TRUE, TD_TRUE);
|
|
|
vfe_hal_set_polar_out(TD_FALSE, TD_TRUE, TD_FALSE, TD_FALSE);
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
static td_void vfe_power_init(td_void)
|
|
|
{
|
|
|
vfe_hal_set_v_clamp_power(TD_FALSE, TD_FALSE, TD_FALSE, TD_FALSE);
|
|
|
vfe_hal_set_i_clamp_power(TD_FALSE, TD_FALSE, TD_FALSE, TD_FALSE);
|
|
|
|
|
|
vfe_hal_set_pga_power(TD_FALSE, TD_FALSE, TD_FALSE, TD_TRUE);
|
|
|
vfe_hal_set_adc_power(TD_FALSE, TD_FALSE, TD_FALSE, TD_FALSE); // adc powerdown
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
static td_void vfe_pll_init(td_void)
|
|
|
{
|
|
|
vfe_hal_set_apll_ref_div(VFE_DEF_REF_DIV); /* APLL输出24_m_hz时钟默认不分频 */
|
|
|
vfe_hal_set_dpll_lock_phase_cfg(VFE_PLL_PHASE_LOCK_THR); /* DPLL 锁定阈值配置信号 */
|
|
|
vfe_hal_set_pll_reserv_init(); /* PLL预留寄存器初始化 */
|
|
|
|
|
|
vfe_hal_set_apll_bypass(TD_TRUE); /* APLL 旁路控制信号为bypass */
|
|
|
vfe_hal_set_apll_post_out_en(TD_TRUE); /* bypass DPLL */
|
|
|
vfe_hal_set_adc_clk_sel(VFE_ADCCHN_CLK_SEL_APLL);
|
|
|
vfe_hal_set_rgb_chn_clk_sel(VFE_CHN_CLK_APLL_OUT, VFE_CHN_CLK_APLL_OUT, VFE_CHN_CLK_APLL_OUT);
|
|
|
vfe_hal_set_com_chn_clk_sel(VFE_CHN_CLK_APLL_OUT);
|
|
|
vfe_hal_set_dpll_lock_sel();
|
|
|
vfe_hal_set_dpll_pdiv_cfg(VFE_DPLL_DIV_64);
|
|
|
vfe_hal_set_apll_four_phase_power(TD_FALSE); /* 不进行四相分频输出 */
|
|
|
vfe_hal_set_sdp_clk_sel(VFE_SDP_CLK_SEL_EXTER);
|
|
|
vfe_hal_rgb_clock_sel(TD_FALSE);
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
static td_void vfe_pga_init(td_void)
|
|
|
{
|
|
|
/* 初始增益 */
|
|
|
vfe_hal_set_r_chn_gain(VFE_GAIN_DEF);
|
|
|
vfe_hal_set_g_chn_gain(VFE_GAIN_DEF);
|
|
|
vfe_hal_set_b_chn_gain(VFE_GAIN_DEF);
|
|
|
vfe_hal_set_com_chn_gain(VFE_GAIN_DEF);
|
|
|
vfe_hal_set_sif_chn_gain(VFE_GAIN_DEF);
|
|
|
vfe_platform_set_rgb_chn_offset();
|
|
|
|
|
|
/* 初始偏移 */
|
|
|
vfe_hal_set_com_chn_offset(VFE_OFFSET_DEF);
|
|
|
vfe_hal_set_sif_chn_offset(VFE_OFFSET_DEF);
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
static td_void vfe_adc_init(td_void)
|
|
|
{
|
|
|
/* ADC上电复位时序要求 */
|
|
|
vfe_hal_set_adc_ldo_en(TD_TRUE, VFE_LDO_OUT_VOL_SEL_1_2V);
|
|
|
vfe_hal_set_band_gap_power(TD_FALSE); /* bandgap总电源关闭 */
|
|
|
vfe_hal_set_dac_ip_pd(TD_TRUE);
|
|
|
vfe_hal_set_adc_power(TD_FALSE, TD_FALSE, TD_FALSE, TD_FALSE); /* 4个通道的电源关闭 */
|
|
|
|
|
|
osal_msleep(1);
|
|
|
|
|
|
vfe_hal_set_adc_power(TD_TRUE, TD_TRUE, TD_TRUE, TD_TRUE); /* 4个通道的电源打开 */
|
|
|
vfe_hal_set_dac_ip_pd(TD_FALSE);
|
|
|
vfe_hal_set_band_gap_power(TD_TRUE); /* bandgap总电源关闭 */
|
|
|
|
|
|
vfe_platform_set_sync_slicer_delay();
|
|
|
|
|
|
vfe_hal_set_rgb_com_chn_adc_reset(TD_FALSE); /* RGB通道复位,撤销复位 */
|
|
|
osal_msleep(1);
|
|
|
vfe_hal_set_rgb_com_chn_adc_reset(TD_TRUE);
|
|
|
osal_msleep(10); // sleep for 10 ms
|
|
|
vfe_hal_set_adc_t(2); /* 模拟部推荐值 2 */
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
td_void vfe_hal_set_apll_cfg(td_void)
|
|
|
{
|
|
|
// move from vfe_set_pll_attr
|
|
|
/* 由于HDDEC能够较准确的获取到行频h_freq计算出clk,对频率的锁定不需要太多约束 */
|
|
|
vfe_hal_set_apll_cfg1(0x00);
|
|
|
vfe_hal_set_apll_cfg2(0xc0);
|
|
|
vfe_hal_set_apll_cfg3(0x0);
|
|
|
vfe_hal_set_apll_cfg4(0x20);
|
|
|
vfe_hal_set_apll_cfg5(0x05);
|
|
|
vfe_hal_set_apll_cfg6(0xc4);
|
|
|
vfe_hal_set_apll_cfg7(0x0, 0x4);
|
|
|
}
|
|
|
td_void ext_drv_vfe_hal_set_apll(td_void)
|
|
|
{
|
|
|
vfe_hal_apb_reset(TD_FALSE);
|
|
|
vfe_hal_cvbs_srst_req(TD_FALSE);
|
|
|
vfe_hal_rgb_srst_req(TD_FALSE);
|
|
|
|
|
|
vfe_hal_set_rgb_com_chn_adc_reset(TD_FALSE);
|
|
|
vfe_hal_set_dpll_ff_reset(TD_FALSE);
|
|
|
vfe_power_init();
|
|
|
vfe_adc_init();
|
|
|
vfe_pll_init();
|
|
|
vfe_sync_slicer_init();
|
|
|
vfe_pga_init();
|
|
|
|
|
|
vfe_hal_set_clamp_init();
|
|
|
vfe_hal_platform_set_pll_tmux1_sel();
|
|
|
|
|
|
vfe_platform_set_vdac_out_chan_sel();
|
|
|
vfe_hal_set_hs_delay();
|
|
|
vfe_hal_set_apll_cfg();
|
|
|
vfe_hal_set_rgb_com_chn_adc_reset(TD_TRUE);
|
|
|
|
|
|
vfe_hal_set_adc_res(VFE_ADC_RST_OFF);
|
|
|
vfe_hal_set_dac_power();
|
|
|
vfe_hal_set_offset_dac_pd();
|
|
|
|
|
|
vfe_hal_platform_set_chn_fe_cal();
|
|
|
vfe_hal_set_dpll_ff_reset(TD_TRUE);
|
|
|
#ifndef CONFIG_SOCT_FPGA_SUPPORT
|
|
|
vfe_hal_set_power_down();
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
td_s32 drv_vfe_ctx_init(td_void)
|
|
|
{
|
|
|
td_u32 h_idx;
|
|
|
td_u32 idx;
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
errno_t err_ret;
|
|
|
|
|
|
for (h_idx = 0; h_idx < VFE_WORKMODE_MAX; h_idx++) {
|
|
|
idx = (h_idx & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", h_idx);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
err_ret = memset_s(vfe_ctx, sizeof(vfe_drv_ctx), 0, sizeof(vfe_drv_ctx));
|
|
|
if (err_ret != EOK) {
|
|
|
soc_log_err("secure func call error\n");
|
|
|
return err_ret;
|
|
|
}
|
|
|
|
|
|
vfe_ctx->source_attr.src_type = EXT_DRV_HDDEC_SRC_MAX;
|
|
|
vfe_ctx->source_attr.work_mode = EXT_DRV_VFE_WORK_MODE_MAX;
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_init(td_void)
|
|
|
{
|
|
|
td_s32 ret = TD_SUCCESS;
|
|
|
errno_t err_ret;
|
|
|
soc_dbg_func_enter();
|
|
|
|
|
|
#ifdef CONFIG_SOCT_FPGA_SUPPORT
|
|
|
ret = vfe_hal_fpga_init();
|
|
|
#else
|
|
|
ret = vfe_hal_init();
|
|
|
#endif
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
soc_log_info("call vfe init hailed\n");
|
|
|
return ret;
|
|
|
}
|
|
|
vfe_platform_init_config();
|
|
|
|
|
|
err_ret = drv_vfe_ctx_init();
|
|
|
if (err_ret != TD_SUCCESS) {
|
|
|
return err_ret;
|
|
|
}
|
|
|
ext_drv_vfe_hal_set_apll();
|
|
|
soc_dbg_func_exit();
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_adc_cal(td_void)
|
|
|
{
|
|
|
vfe_hal_platform_set_chn_fe_cal();
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_apll_cfg7(td_u32 apll_cfg1, td_u32 apll_cfg2)
|
|
|
{
|
|
|
vfe_hal_set_apll_cfg7(apll_cfg1, apll_cfg2);
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_de_init(td_void)
|
|
|
{
|
|
|
td_u32 h_idx;
|
|
|
td_u32 idx;
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
errno_t err_ret;
|
|
|
|
|
|
soc_dbg_func_enter();
|
|
|
|
|
|
for (h_idx = 0; h_idx < VFE_WORKMODE_MAX; h_idx++) {
|
|
|
idx = (h_idx & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", h_idx);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
err_ret = memset_s(vfe_ctx, sizeof(vfe_drv_ctx), 0, sizeof(vfe_drv_ctx));
|
|
|
if (err_ret != EOK) {
|
|
|
soc_log_err("secure func call error\n");
|
|
|
return err_ret;
|
|
|
}
|
|
|
|
|
|
vfe_ctx->source_attr.work_mode = EXT_DRV_VFE_WORK_MODE_MAX;
|
|
|
}
|
|
|
|
|
|
vfe_power_init();
|
|
|
vfe_hal_set_rgb_com_chn_adc_reset(TD_FALSE);
|
|
|
|
|
|
vfe_hal_apb_reset(TD_TRUE);
|
|
|
vfe_hal_cvbs_srst_req(TD_TRUE);
|
|
|
vfe_hal_rgb_srst_req(TD_TRUE);
|
|
|
|
|
|
vfe_hal_set_low_power();
|
|
|
|
|
|
#ifdef CONFIG_SOCT_FPGA_SUPPORT
|
|
|
vfe_hal_fpga_deinit();
|
|
|
#else
|
|
|
vfe_hal_de_init();
|
|
|
#endif
|
|
|
vfe_hal_comm_reg_deinit_cs();
|
|
|
soc_dbg_func_exit();
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
#ifndef CONFIG_SOCT_FPGA_SUPPORT
|
|
|
td_void ext_drv_vfe_re_open_init(td_void)
|
|
|
{
|
|
|
vfe_power_init();
|
|
|
|
|
|
vfe_pll_init();
|
|
|
vfe_sync_slicer_init();
|
|
|
vfe_hal_set_dac_power();
|
|
|
vfe_hal_set_power_on();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
td_s8 ext_drv_vfe_set_power_down(td_void)
|
|
|
{
|
|
|
vfe_hal_set_power_down();
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
td_void drv_vfe_set_chn_mux(vfe_drv_ctx_s_ptr vfe_ctx, vfe_chn_mux_sel** mux_param_ptr_array,
|
|
|
const ext_drv_vfe_source_attr *source)
|
|
|
{
|
|
|
td_u32 r_mux1_val = 0;
|
|
|
td_u32 g_mux1_val = 0;
|
|
|
td_u32 b_mux1_val = 0;
|
|
|
vfe_chn_mux_sel *r_chn_mux = TD_NULL;
|
|
|
vfe_chn_mux_sel *g_chn_mux = TD_NULL;
|
|
|
vfe_chn_mux_sel *b_chn_mux = TD_NULL;
|
|
|
if (source == TD_NULL || mux_param_ptr_array == TD_NULL) {
|
|
|
soc_log_info("input para invalid at line %d.\n", __LINE__);
|
|
|
return;
|
|
|
}
|
|
|
r_chn_mux = mux_param_ptr_array[0];
|
|
|
g_chn_mux = mux_param_ptr_array[1];
|
|
|
b_chn_mux = mux_param_ptr_array[2]; // array index is 2
|
|
|
vfe_get_rgb_chn_mux1_val(source, &r_mux1_val, &g_mux1_val, &b_mux1_val);
|
|
|
|
|
|
r_chn_mux->chn_mux1_p = r_mux1_val;
|
|
|
g_chn_mux->chn_mux1_p = g_mux1_val;
|
|
|
b_chn_mux->chn_mux1_p = b_mux1_val;
|
|
|
|
|
|
r_chn_mux->chn_mux1_n = r_mux1_val;
|
|
|
g_chn_mux->chn_mux1_n = g_mux1_val;
|
|
|
b_chn_mux->chn_mux1_n = b_mux1_val;
|
|
|
|
|
|
vfe_platform_config_chn_mux_n(r_chn_mux, g_chn_mux, b_chn_mux);
|
|
|
|
|
|
r_chn_mux->chn_mux2_p = VFE_RCHN_MUX2_NOLPF;
|
|
|
r_chn_mux->chn_mux2_n = VFE_RCHN_MUX2_NOLPF;
|
|
|
|
|
|
g_chn_mux->chn_mux2_p = VFE_GCHN_MUX2_NOLPF;
|
|
|
g_chn_mux->chn_mux2_n = VFE_GCHN_MUX2_NOLPF;
|
|
|
|
|
|
b_chn_mux->chn_mux2_p = VFE_BCHN_MUX2_NOLPF;
|
|
|
b_chn_mux->chn_mux2_n = VFE_BCHN_MUX2_NOLPF;
|
|
|
|
|
|
vfe_platform_check_chn_lpf_mode(vfe_ctx, r_chn_mux, g_chn_mux, b_chn_mux);
|
|
|
|
|
|
vfe_hal_set_r_chn_mux(r_chn_mux);
|
|
|
vfe_hal_set_g_chn_mux(g_chn_mux);
|
|
|
vfe_hal_set_b_chn_mux(b_chn_mux);
|
|
|
|
|
|
vfe_hal_set_sog_chn_mux(source->sog_chn_mux);
|
|
|
vfe_hal_set_sync_chn_mux(source->sync_chn_mux);
|
|
|
vfe_hal_platform_set_mux_4_sdp_selb();
|
|
|
}
|
|
|
|
|
|
td_void drv_vfe_update_hddec_cfg(vfe_drv_ctx_s_ptr vfe_ctx, vfe_chn_mux_sel** mux_param_ptr_array,
|
|
|
const ext_drv_vfe_source_attr *source, const ext_drv_vfe_pll_mode *pll_mode)
|
|
|
{
|
|
|
soc_log_dbg("EXT_DRV_VFE_WORK_MODE_HDDEC\n");
|
|
|
|
|
|
if (source == TD_NULL || vfe_ctx == TD_NULL || pll_mode == TD_NULL) {
|
|
|
soc_log_info("input para invalid at line %d.\n", __LINE__);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
vfe_hal_set_adc_res(VFE_ADC_RST_RGB);
|
|
|
/* step 1 : confirgure MUX1/MUX2/CLAMP */
|
|
|
vfe_hal_peri_equator_sel(TD_TRUE);
|
|
|
vfe_hal_peri_vfe_agc_sel(TD_TRUE);
|
|
|
|
|
|
drv_vfe_set_chn_mux(vfe_ctx, mux_param_ptr_array, source);
|
|
|
|
|
|
vfe_hal_set_v_clamp_power(TD_FALSE, TD_FALSE, TD_FALSE, TD_FALSE);
|
|
|
vfe_hal_set_i_clamp_power(TD_TRUE, TD_TRUE, TD_TRUE, TD_FALSE);
|
|
|
/* step 2 : confirgure PLL */
|
|
|
vfe_hal_set_pll_refresh_mode(VFE_REFRESH_BYVS_MODE_DIRECT);
|
|
|
vfe_hal_set_phase_refresh_mode(VFE_REFRESH_BYVS_MODE_DIRECT);
|
|
|
vfe_hal_set_clock_sel_refresh_mode(VFE_REFRESH_BYVS_MODE_DIRECT);
|
|
|
|
|
|
vfe_hal_set_apll_power(TD_TRUE, TD_TRUE); /* POWER ON */
|
|
|
vfe_hal_set_dpll_ff_reset(TD_TRUE);
|
|
|
vfe_hal_set_dpll_lpf_fbdiv_reset(TD_TRUE); /* 复位撤销 */
|
|
|
|
|
|
if (*pll_mode == EXT_DRV_VFE_PLL_MODE_HDDEC) {
|
|
|
vfe_platform_set_apll_four_phase_power();
|
|
|
vfe_hal_set_sdp_clk_sel(VFE_SDP_CLK_SEL_EXTER);
|
|
|
vfe_hal_set_adc_ofcal_en(TD_FALSE, TD_FALSE, TD_FALSE, TD_TRUE);
|
|
|
|
|
|
vfe_hal_set_rgb_chn_clk_sel(VFE_CHN_CLK_DPLL_OUT, VFE_CHN_CLK_DPLL_OUT, VFE_CHN_CLK_DPLL_OUT);
|
|
|
vfe_hal_set_com_chn_clk_sel(VFE_CHN_CLK_DPLL_OUT);
|
|
|
|
|
|
/* VFE_ADCCHN_CLK_SEL_DPLL, vfe_set_pll_attr will set again. */
|
|
|
vfe_hal_set_adc_clk_sel(VFE_ADCCHN_CLK_SEL_APLL);
|
|
|
} else if (*pll_mode == EXT_DRV_VFE_PLL_MODE_HDDEC_A_TVD) {
|
|
|
vfe_hal_set_adc_ofcal_en(TD_FALSE, TD_FALSE, TD_FALSE, TD_FALSE);
|
|
|
|
|
|
vfe_hal_set_rgb_chn_clk_sel(VFE_CHN_CLK_DPLL_OUT, VFE_CHN_CLK_DPLL_OUT, VFE_CHN_CLK_DPLL_OUT);
|
|
|
vfe_hal_set_com_chn_clk_sel(VFE_CHN_CLK_APLL_OUT);
|
|
|
/* VFE_ADCCHN_CLK_SEL_DPLL, vfe_set_pll_attr will set again. */
|
|
|
vfe_hal_set_adc_clk_sel(VFE_ADCCHN_CLK_SEL_DPLL);
|
|
|
}
|
|
|
|
|
|
/* step 3 : confirgure output */
|
|
|
vfe_hal_set_out_put_mode(VFE_OUT_MODE_RGB);
|
|
|
|
|
|
/* step 4 : confirgure calibration */
|
|
|
vfe_platform_config_calibration(vfe_ctx->source_attr.work_mode);
|
|
|
/* step 5 : store the CTX */
|
|
|
vfe_ctx->source_attr.r_chn_mux = source->r_chn_mux;
|
|
|
vfe_ctx->source_attr.g_chn_mux = source->g_chn_mux;
|
|
|
vfe_ctx->source_attr.b_chn_mux = source->b_chn_mux;
|
|
|
vfe_ctx->source_attr.sog_chn_mux = source->sog_chn_mux;
|
|
|
vfe_ctx->source_attr.sync_chn_mux = source->sync_chn_mux;
|
|
|
}
|
|
|
|
|
|
td_void drv_vfe_tvd_config_pll(const ext_drv_vfe_pll_mode *pll_mode)
|
|
|
{
|
|
|
td_u32 vfe_two_route;
|
|
|
if (pll_mode == TD_NULL) {
|
|
|
soc_log_err("input pll_mode is null pointer.\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
vfe_platform_config_tvd_pll();
|
|
|
|
|
|
vfe_two_route = CFG_VFE_TWO_ROUTE_SUPPORT;
|
|
|
if (vfe_two_route) {
|
|
|
vfe_hal_set_sdp_clk_sel(VFE_SDP_CLK_SEL_EXTER);
|
|
|
} else {
|
|
|
vfe_hal_set_sdp_clk_sel(VFE_SDP_CLK_SEL_INTER);
|
|
|
}
|
|
|
|
|
|
if (*pll_mode == EXT_DRV_VFE_PLL_MODE_TVD_CVBS) {
|
|
|
vfe_hal_set_adc_ofcal_en(TD_TRUE, TD_TRUE, TD_TRUE, TD_FALSE);
|
|
|
vfe_platform_set_rgb_chn_clk_sel();
|
|
|
vfe_hal_set_com_chn_clk_sel(VFE_CHN_CLK_APLL_OUT);
|
|
|
vfe_hal_set_adc_clk_sel(VFE_ADCCHN_CLK_SEL_APLL);
|
|
|
} else if (*pll_mode == EXT_DRV_VFE_PLL_MODE_HDDEC_A_TVD) {
|
|
|
vfe_hal_set_adc_ofcal_en(TD_FALSE, TD_FALSE, TD_FALSE, TD_FALSE);
|
|
|
vfe_hal_set_rgb_chn_clk_sel(VFE_CHN_CLK_DPLL_OUT, VFE_CHN_CLK_DPLL_OUT, VFE_CHN_CLK_DPLL_OUT);
|
|
|
vfe_hal_set_com_chn_clk_sel(VFE_CHN_CLK_APLL_OUT);
|
|
|
vfe_hal_set_adc_clk_sel(VFE_ADCCHN_CLK_SEL_DPLL);
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
td_void drv_vfe_update_tvd_cfg(vfe_drv_ctx_s_ptr vfe_ctx, vfe_chn_mux_sel** mux_param_ptr_array,
|
|
|
const ext_drv_vfe_source_attr *source, const ext_drv_vfe_pll_mode *pll_mode)
|
|
|
{
|
|
|
td_u32 cvbs_mux1_val;
|
|
|
vfe_chn_mux_sel *com_chn_mux = TD_NULL;
|
|
|
|
|
|
if ((vfe_ctx == TD_NULL) || (mux_param_ptr_array == TD_NULL) ||
|
|
|
(source == TD_NULL) || (pll_mode == TD_NULL)) {
|
|
|
soc_log_err("input null pointer.\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
com_chn_mux = mux_param_ptr_array[3]; // array index is 3
|
|
|
soc_log_dbg("EXT_DRV_VFE_WORK_MODE_TVD\n");
|
|
|
vfe_hal_set_adc_res(VFE_ADC_RST_CVBS);
|
|
|
/* step 1 : confirgure MUX1/MUX2/CLAMP */
|
|
|
vfe_hal_peri_equator_sel(TD_FALSE);
|
|
|
vfe_hal_peri_vfe_agc_sel(TD_TRUE);
|
|
|
vfe_hal_sys_vfe_apb_rst_req(TD_FALSE);
|
|
|
vfe_hal_sys_vfe_cvbs_mode(TD_FALSE);
|
|
|
vfe_hal_fir_bypass(0);
|
|
|
vfe_get_cvbs_chn_mux1_val(source->cvbs_chn_mux, &cvbs_mux1_val);
|
|
|
|
|
|
com_chn_mux->chn_mux1_p = cvbs_mux1_val;
|
|
|
vfe_platform_set_com_chn_mux_cfg(com_chn_mux);
|
|
|
vfe_hal_set_com_chn_mux(com_chn_mux);
|
|
|
// add this since for reserved9
|
|
|
vfe_hal_platform_set_dig_ana2_and_ana7();
|
|
|
vfe_hal_set_i_clamp_power(TD_FALSE, TD_FALSE, TD_FALSE, TD_TRUE);
|
|
|
|
|
|
/* step 2 : confirgure PLL */
|
|
|
drv_vfe_tvd_config_pll(pll_mode);
|
|
|
|
|
|
/* step 3 : confirgure output */
|
|
|
vfe_hal_set_out_put_mode(VFE_OUT_MODE_G_CVBS);
|
|
|
|
|
|
vfe_platform_adc_dig_calib(vfe_ctx->source_attr.work_mode);
|
|
|
/* step 4 : store the CTX */
|
|
|
vfe_ctx->source_attr.cvbs_chn_mux = source->cvbs_chn_mux;
|
|
|
}
|
|
|
|
|
|
td_void drv_vfe_update_tvd_rf_cfg(vfe_drv_ctx_s_ptr vfe_ctx, vfe_chn_mux_sel** mux_param_ptr_array,
|
|
|
const ext_drv_vfe_source_attr *source, const ext_drv_vfe_pll_mode *pll_mode)
|
|
|
{
|
|
|
/* step 1 : confirgure MUX1/MUX2/CLAMP */
|
|
|
td_u32 mux1_val;
|
|
|
td_u32 vfe_two_route;
|
|
|
vfe_sif_mux_p_sel chn_mux_p;
|
|
|
vfe_sif_mux_n_sel chn_mux_n;
|
|
|
vfe_chn_mux_sel *r_chn_mux = TD_NULL;
|
|
|
vfe_chn_mux_sel *com_chn_mux = TD_NULL;
|
|
|
|
|
|
if ((vfe_ctx == TD_NULL) || (mux_param_ptr_array == TD_NULL) ||
|
|
|
(source == TD_NULL) || (pll_mode == TD_NULL)) {
|
|
|
soc_log_err("input null pointer.\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
r_chn_mux = mux_param_ptr_array[0];
|
|
|
com_chn_mux = mux_param_ptr_array[3]; // array index is 3
|
|
|
soc_log_dbg("EXT_DRV_VFE_WORK_MODE_TVD_RF\n");
|
|
|
|
|
|
vfe_hal_peri_equator_sel(TD_FALSE);
|
|
|
vfe_hal_peri_vfe_agc_sel(TD_TRUE);
|
|
|
|
|
|
vfe_get_cvbs_chn_mux1_val(source->r_chn_mux, &mux1_val);
|
|
|
|
|
|
chn_mux_p = (vfe_sif_mux_p_sel)mux1_val;
|
|
|
chn_mux_n = VFE_SIF_MUX_N_SEL_CVBS_VCOM;
|
|
|
|
|
|
vfe_get_cvbs_chn_mux1_val(source->r_chn_mux, &mux1_val);
|
|
|
|
|
|
com_chn_mux->chn_mux1_p = mux1_val;
|
|
|
com_chn_mux->chn_mux2_p = VFE_COMCHN_MUX2_TEST2;
|
|
|
com_chn_mux->chn_mux2_n = VFE_COMCHN_MUX2_TEST2;
|
|
|
|
|
|
com_chn_mux->chn_mux1_n = VFE_RF_PIN_N;
|
|
|
r_chn_mux->chn_mux2_p = VFE_RCHN_MUX2_SIF;
|
|
|
r_chn_mux->chn_mux2_n = VFE_RCHN_MUX2_SIF;
|
|
|
|
|
|
vfe_hal_set_com_chn_mux(com_chn_mux);
|
|
|
vfe_hal_set_sif_chn_mux(chn_mux_p, chn_mux_n, TD_TRUE);
|
|
|
|
|
|
vfe_hal_platform_set_dig_ana2_and_ana7();
|
|
|
vfe_hal_set_i_clamp_power(TD_FALSE, TD_FALSE, TD_FALSE, TD_TRUE);
|
|
|
|
|
|
/* step 2 : confirgure PLL */
|
|
|
vfe_two_route = CFG_VFE_TWO_ROUTE_SUPPORT;
|
|
|
if (vfe_two_route) {
|
|
|
vfe_hal_set_sdp_clk_sel(VFE_SDP_CLK_SEL_EXTER);
|
|
|
} else {
|
|
|
vfe_hal_set_sdp_clk_sel(VFE_SDP_CLK_SEL_INTER);
|
|
|
}
|
|
|
|
|
|
if (*pll_mode == EXT_DRV_VFE_PLL_MODE_TVD_CVBS) {
|
|
|
vfe_hal_set_adc_ofcal_en(TD_FALSE, TD_TRUE, TD_TRUE, TD_FALSE);
|
|
|
|
|
|
vfe_hal_set_rgb_chn_clk_sel(VFE_CHN_CLK_SIF_IN, VFE_CHN_CLK_TIEL, VFE_CHN_CLK_SIF_IN);
|
|
|
vfe_hal_set_com_chn_clk_sel(VFE_CHN_CLK_APLL_OUT);
|
|
|
vfe_hal_set_adc_clk_sel(VFE_ADCCHN_CLK_SEL_SIF);
|
|
|
}
|
|
|
|
|
|
/* step 3 : confirgure output */
|
|
|
vfe_hal_set_out_put_mode(VFE_OUT_MODE_RGB); // VFE_OUT_MODE_G_CVBS
|
|
|
|
|
|
/* step 4 : store the CTX */
|
|
|
vfe_ctx->source_attr.cvbs_chn_mux = source->cvbs_chn_mux;
|
|
|
}
|
|
|
|
|
|
td_void drv_vfe_tvd_svideo_config_pll(const ext_drv_vfe_pll_mode *pll_mode)
|
|
|
{
|
|
|
td_u32 vfe_two_route;
|
|
|
if (pll_mode == TD_NULL) {
|
|
|
soc_log_err("input null pointer.\n");
|
|
|
return;
|
|
|
}
|
|
|
vfe_hal_set_apll_four_phase_power(TD_TRUE);
|
|
|
vfe_hal_set_pll_dsm_pd(TD_TRUE);
|
|
|
|
|
|
vfe_two_route = CFG_VFE_TWO_ROUTE_SUPPORT;
|
|
|
if (vfe_two_route) {
|
|
|
vfe_hal_set_sdp_clk_sel(VFE_SDP_CLK_SEL_EXTER);
|
|
|
} else {
|
|
|
vfe_hal_set_sdp_clk_sel(VFE_SDP_CLK_SEL_INTER);
|
|
|
}
|
|
|
|
|
|
if (*pll_mode == EXT_DRV_VFE_PLL_MODE_TVD_CVBS) {
|
|
|
vfe_hal_set_adc_ofcal_en(TD_TRUE, TD_TRUE, TD_TRUE, TD_FALSE);
|
|
|
vfe_hal_set_rgb_chn_clk_sel(VFE_CHN_CLK_APLL_OUT, VFE_CHN_CLK_APLL_OUT, VFE_CHN_CLK_APLL_OUT);
|
|
|
vfe_hal_set_com_chn_clk_sel(VFE_CHN_CLK_APLL_OUT);
|
|
|
vfe_hal_set_adc_clk_sel(VFE_ADCCHN_CLK_SEL_APLL);
|
|
|
} else if (*pll_mode == EXT_DRV_VFE_PLL_MODE_HDDEC_A_TVD) {
|
|
|
vfe_hal_set_adc_ofcal_en(TD_FALSE, TD_FALSE, TD_FALSE, TD_FALSE);
|
|
|
|
|
|
vfe_hal_set_rgb_chn_clk_sel(VFE_CHN_CLK_DPLL_OUT, VFE_CHN_CLK_DPLL_OUT, VFE_CHN_CLK_DPLL_OUT);
|
|
|
vfe_hal_set_com_chn_clk_sel(VFE_CHN_CLK_APLL_OUT);
|
|
|
vfe_hal_set_adc_clk_sel(VFE_ADCCHN_CLK_SEL_DPLL);
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
td_void drv_vfe_update_tvd_svideo_cfg(vfe_drv_ctx_s_ptr vfe_ctx, vfe_chn_mux_sel** mux_param_ptr_array,
|
|
|
const ext_drv_vfe_source_attr *source, const ext_drv_vfe_pll_mode *pll_mode)
|
|
|
{
|
|
|
td_u32 cvbs_mux1_val;
|
|
|
vfe_chn_mux_sel *r_chn_mux = TD_NULL;
|
|
|
vfe_chn_mux_sel *com_chn_mux = TD_NULL;
|
|
|
|
|
|
if ((mux_param_ptr_array == TD_NULL) || (source == TD_NULL) || (pll_mode == TD_NULL)) {
|
|
|
soc_log_err("input null pointer.\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
r_chn_mux = mux_param_ptr_array[0];
|
|
|
com_chn_mux = mux_param_ptr_array[3]; // array index is 3
|
|
|
soc_log_dbg("EXT_DRV_VFE_WORK_MODE_TVD\n");
|
|
|
vfe_hal_platform_set_svideo_adc_res();
|
|
|
/* step 1 : confirgure MUX1/MUX2/CLAMP */
|
|
|
vfe_hal_peri_equator_sel(TD_FALSE);
|
|
|
vfe_hal_peri_vfe_agc_sel(TD_TRUE);
|
|
|
vfe_hal_sys_vfe_apb_rst_req(TD_FALSE);
|
|
|
vfe_hal_sys_vfe_cvbs_mode(TD_FALSE);
|
|
|
|
|
|
vfe_hal_fir_bypass(0);
|
|
|
vfe_get_cvbs_chn_mux1_val(source->cvbs_chn_mux, &cvbs_mux1_val);
|
|
|
|
|
|
com_chn_mux->chn_mux1_p = cvbs_mux1_val;
|
|
|
com_chn_mux->chn_mux1_n = VFE_CVBS_PIN_N;
|
|
|
|
|
|
vfe_hal_platform_set_chn_mux2_value(com_chn_mux);
|
|
|
vfe_hal_set_com_chn_mux(com_chn_mux);
|
|
|
|
|
|
vfe_hal_set_i_clamp_power(TD_FALSE, TD_FALSE, TD_FALSE, TD_TRUE);
|
|
|
|
|
|
/* step 2 : confirgure PLL */
|
|
|
drv_vfe_tvd_svideo_config_pll(pll_mode);
|
|
|
|
|
|
/* step 3 : confirgure output */
|
|
|
vfe_hal_set_out_put_mode(VFE_OUT_MODE_G_CVBS);
|
|
|
|
|
|
vfe_hal_set_sc_mux(SC_P_SEL_CVBS1, SC_N_SEL_CVBS_VCOM);
|
|
|
vfe_hal_sc_mux_clamp_sel(TD_TRUE);
|
|
|
|
|
|
r_chn_mux->chn_mux1_p = VFE_RCHN_MUX3_HANG;
|
|
|
r_chn_mux->chn_mux1_n = VFE_RCHN_MUX3_HANG;
|
|
|
r_chn_mux->chn_mux2_p = VFE_RCHN_RC_MUX3_SOURCEFFILTER;
|
|
|
r_chn_mux->chn_mux2_n = VFE_RCHN_RC_MUX3_SOURCEFFILTER;
|
|
|
|
|
|
vfe_hal_set_r_chn_mux(r_chn_mux);
|
|
|
vfe_hal_set_com_chn_pga_cap(VFE_PGA_FEEDBACK_CAP_MAX);
|
|
|
vfe_hal_set_r_chn_pga_power(TD_TRUE);
|
|
|
vfe_hal_set_r_chn_pga_cap(VFE_PGA_FEEDBACK_CAP_MAX);
|
|
|
vfe_hal_platform_set_r_chn_gain();
|
|
|
}
|
|
|
|
|
|
td_s32 vfe_connect(vfe_drv_ctx_s_ptr vfe_ctx, vfe_chn_mux_sel** mux_param_ptr_array,
|
|
|
const ext_drv_vfe_source_attr *source, const ext_drv_vfe_pll_mode *pll_mode)
|
|
|
{
|
|
|
if (source == TD_NULL || vfe_ctx == TD_NULL) {
|
|
|
soc_log_err("input null point.\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
switch (vfe_ctx->source_attr.work_mode) {
|
|
|
case EXT_DRV_VFE_WORK_MODE_HDDEC: {
|
|
|
drv_vfe_update_hddec_cfg(vfe_ctx, mux_param_ptr_array, source, pll_mode);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_WORK_MODE_TVD: {
|
|
|
drv_vfe_update_tvd_cfg(vfe_ctx, mux_param_ptr_array, source, pll_mode);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_WORK_MODE_TVD_RF: {
|
|
|
drv_vfe_update_tvd_rf_cfg(vfe_ctx, mux_param_ptr_array, source, pll_mode);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_WORK_MODE_TVD_SVIDEO: {
|
|
|
drv_vfe_update_tvd_svideo_cfg(vfe_ctx, mux_param_ptr_array, source, pll_mode);
|
|
|
/* step 4 : confirgure calibration */
|
|
|
vfe_platform_adc_dig_calib(vfe_ctx->source_attr.work_mode);
|
|
|
/* step 4 : store the CTX */
|
|
|
vfe_ctx->source_attr.cvbs_chn_mux = source->cvbs_chn_mux;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
default: {
|
|
|
soc_log_err("VFE vfe_ctx->source_attr.work_mode = %d error. \n", vfe_ctx->source_attr.work_mode);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_void ext_drv_vfe_invalid_work_mode(const ext_drv_vfe_source_attr *source, ext_drv_vfe_pll_mode *pll_mode,
|
|
|
td_u32 h_idx, td_u32 *free_idx)
|
|
|
{
|
|
|
if (source == TD_NULL || pll_mode == TD_NULL || free_idx == TD_NULL) {
|
|
|
soc_log_err("input invalid.\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
soc_dbg_print_u32(*free_idx);
|
|
|
if (*free_idx == VFE_WORKMODE_MAX) {
|
|
|
*free_idx = h_idx;
|
|
|
}
|
|
|
|
|
|
if (*pll_mode == EXT_DRV_VFE_PLL_MODE_BUTT) {
|
|
|
switch (source->work_mode) {
|
|
|
case EXT_DRV_VFE_WORK_MODE_HDDEC: {
|
|
|
soc_log_dbg("set pll mode HDDEC\n");
|
|
|
*pll_mode = EXT_DRV_VFE_PLL_MODE_HDDEC;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_WORK_MODE_TVD: {
|
|
|
soc_log_dbg("set pll mode TVD_CVBS\n");
|
|
|
*pll_mode = EXT_DRV_VFE_PLL_MODE_TVD_CVBS;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_WORK_MODE_TVD_RF: {
|
|
|
soc_log_dbg("set pll mode TVD_RF\n");
|
|
|
*pll_mode = EXT_DRV_VFE_PLL_MODE_TVD_RF;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_WORK_MODE_TVD_SVIDEO: {
|
|
|
soc_log_dbg("set pll mode TVD_SVIDEO\n");
|
|
|
*pll_mode = EXT_DRV_VFE_PLL_MODE_TVD_SVIDEO;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
default: {
|
|
|
soc_log_err("work_mode set error:\n");
|
|
|
soc_err_print_u32(source->work_mode);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_valid_work_mode(vfe_drv_ctx_s_ptr vfe_ctx, const ext_drv_vfe_source_attr *source,
|
|
|
ext_drv_vfe_pll_mode *pll_mode, td_u32 h_idx)
|
|
|
{
|
|
|
if (vfe_ctx == TD_NULL || source == TD_NULL || pll_mode == TD_NULL) {
|
|
|
soc_log_info("input para invalid at line %d.\n", __LINE__);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
soc_dbg_print_u32(h_idx);
|
|
|
soc_dbg_print_u32(source->work_mode);
|
|
|
if (source->work_mode == EXT_DRV_VFE_WORK_MODE_HDDEC) {
|
|
|
if (vfe_ctx->source_attr.work_mode == EXT_DRV_VFE_WORK_MODE_TVD) {
|
|
|
soc_log_dbg("VFE work mode set as EXT_DRV_VFE_PLL_MODE_HDDEC_A_TVD!\n");
|
|
|
*pll_mode = EXT_DRV_VFE_PLL_MODE_HDDEC_A_TVD;
|
|
|
} else {
|
|
|
soc_log_err("VFE work mode overrun!\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
} else if (source->work_mode == EXT_DRV_VFE_WORK_MODE_TVD) {
|
|
|
if (vfe_ctx->source_attr.work_mode == EXT_DRV_VFE_WORK_MODE_HDDEC) {
|
|
|
soc_log_dbg("VFE work mode set as EXT_DRV_VFE_PLL_MODE_HDDEC_A_TVD!\n");
|
|
|
*pll_mode = EXT_DRV_VFE_PLL_MODE_HDDEC_A_TVD;
|
|
|
} else {
|
|
|
soc_log_err("VFE work mode overrun!\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
} else if (source->work_mode == EXT_DRV_VFE_WORK_MODE_TVD_SVIDEO) {
|
|
|
td_s32 ret;
|
|
|
ret = vfe_platform_set_tvd_rf_work_mode(vfe_ctx, pll_mode);
|
|
|
return ret;
|
|
|
} else if (source->work_mode == EXT_DRV_VFE_WORK_MODE_TVD_RF) {
|
|
|
soc_log_err("VFE work mode overrun!\n");
|
|
|
return TD_FAILURE;
|
|
|
} else {
|
|
|
soc_log_err("invalid source->work_mode = %d!\n", source->work_mode);
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_check_work_mode(vfe_drv_ctx_s_ptr vfe_ctx, const ext_drv_vfe_source_attr *source,
|
|
|
ext_drv_vfe_pll_mode *pll_mode, td_u32 *free_idx)
|
|
|
{
|
|
|
td_u32 h_idx;
|
|
|
td_u32 idx;
|
|
|
td_s32 ret;
|
|
|
|
|
|
for (h_idx = 0; h_idx < VFE_WORKMODE_MAX; h_idx++) {
|
|
|
idx = (h_idx & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", h_idx);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
if (vfe_ctx == TD_NULL) {
|
|
|
soc_log_err("null point vfe_ctx.\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
if (vfe_ctx->source_attr.work_mode >= EXT_DRV_VFE_WORK_MODE_MAX) {
|
|
|
ext_drv_vfe_invalid_work_mode(source, pll_mode, h_idx, free_idx);
|
|
|
} else {
|
|
|
ret = ext_drv_vfe_valid_work_mode(vfe_ctx, source, pll_mode, h_idx);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_check_validation(td_u32 free_idx, ext_drv_vfe_pll_mode pll_mode)
|
|
|
{
|
|
|
if (free_idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE connected work mode over flow!\n");
|
|
|
soc_err_print_u32(free_idx);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
if (pll_mode >= EXT_DRV_VFE_PLL_MODE_BUTT) {
|
|
|
soc_log_err("pll_mode set error\n");
|
|
|
soc_err_print_u32(pll_mode);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_do_connect(const ext_drv_vfe_source_attr *source, vfe_drv_ctx_s_ptr vfe_ctx,
|
|
|
td_u32 free_idx, ext_drv_vfe_pll_mode pll_mode, vfe_chn_mux_sel** mux_param_ptr_array)
|
|
|
{
|
|
|
td_s32 ret;
|
|
|
td_u32 idx;
|
|
|
td_u32 custom_hddec_set_vclamp;
|
|
|
vfe_chn_mux_sel *b_chn_mux = TD_NULL;
|
|
|
|
|
|
idx = (free_idx & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", free_idx);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
if (source == TD_NULL || vfe_ctx == TD_NULL) {
|
|
|
soc_log_err("input source or vfe_ctx is invalid.\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
vfe_ctx->source_attr.src_type = source->src_type;
|
|
|
vfe_ctx->source_attr.work_mode = source->work_mode;
|
|
|
ret = vfe_connect(vfe_ctx, mux_param_ptr_array, source, &pll_mode);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
soc_log_err("VFE connect failure.\n");
|
|
|
}
|
|
|
vfe_hal_set_rgb_com_chn_adc_reset(TD_FALSE);
|
|
|
osal_msleep(1);
|
|
|
vfe_hal_set_rgb_com_chn_adc_reset(TD_TRUE);
|
|
|
|
|
|
custom_hddec_set_vclamp = CFG_CUSTOM_HDDEC_SET_VCLAMP_SUPPORT;
|
|
|
if (custom_hddec_set_vclamp) {
|
|
|
b_chn_mux = mux_param_ptr_array[2]; // 2: array 2
|
|
|
if (source->work_mode == EXT_DRV_VFE_WORK_MODE_TVD) {
|
|
|
/* modify start av black dot */
|
|
|
/* mm 0xf8a22198 0xf */
|
|
|
ext_drv_vfe_cfg_hddec_crg_reg(TD_TRUE);
|
|
|
|
|
|
/* mm 0xff2601d8 0x75 */
|
|
|
vfe_hal_set_vs0_in_cfg(VFE_VS_ROUTE_SCT_FB);
|
|
|
vfe_hal_set_vs1_in_cfg(VFE_VS_ROUTE_SCT_FB);
|
|
|
|
|
|
/* mm 0xff260000 0xf */
|
|
|
b_chn_mux->chn_mux1_p = 0;
|
|
|
b_chn_mux->chn_mux1_n = 0;
|
|
|
b_chn_mux->chn_mux2_p = VFE_BCHN_MUX2_TESTINP;
|
|
|
b_chn_mux->chn_mux2_n = VFE_BCHN_MUX2_TESTINP;
|
|
|
vfe_hal_set_b_chn_mux(b_chn_mux);
|
|
|
|
|
|
/* mm 0xff260004 0x03 */
|
|
|
vfe_hal_set_bchan_mux(0);
|
|
|
|
|
|
/* mm 0xff240080 0x00FF0001 */
|
|
|
ext_drv_hddec_set_vclamp();
|
|
|
/* modify end av black dot */
|
|
|
}
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_connect(td_handle *vfe, const ext_drv_vfe_source_attr *source)
|
|
|
{
|
|
|
td_s32 ret;
|
|
|
vfe_chn_mux_sel r_chn_mux = { 0 };
|
|
|
vfe_chn_mux_sel g_chn_mux = { 0 };
|
|
|
vfe_chn_mux_sel b_chn_mux = { 0 };
|
|
|
vfe_chn_mux_sel com_chn_mux = { 0 };
|
|
|
vfe_chn_mux_sel* mux_param_ptr_array[4] = { // size 4
|
|
|
(vfe_chn_mux_sel*)&r_chn_mux, (vfe_chn_mux_sel*)&g_chn_mux,
|
|
|
(vfe_chn_mux_sel*)&b_chn_mux, (vfe_chn_mux_sel*)&com_chn_mux
|
|
|
};
|
|
|
td_u32 free_idx;
|
|
|
ext_drv_vfe_pll_mode pll_mode = EXT_DRV_VFE_PLL_MODE_BUTT;
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
soc_dbg_func_enter();
|
|
|
|
|
|
if (vfe == NULL) {
|
|
|
soc_log_err("NULL point \n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
if (source == NULL) {
|
|
|
soc_log_err("NULL point \n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
#ifndef CONFIG_SOCT_FPGA_SUPPORT
|
|
|
ext_drv_vfe_re_open_init();
|
|
|
#endif
|
|
|
|
|
|
*vfe = TD_INVALID_HANDLE;
|
|
|
|
|
|
if (vfe_check_input_attr(source) != TD_SUCCESS) {
|
|
|
soc_log_err("some attr of vfe input attr is invalid\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
free_idx = VFE_WORKMODE_MAX;
|
|
|
ret = ext_drv_vfe_check_work_mode(vfe_ctx, source, &pll_mode, &free_idx);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
ret = ext_drv_vfe_check_validation(free_idx, pll_mode);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
soc_log_dbg("find the vfe index and PLL work mode :\n");
|
|
|
soc_dbg_print_u32(free_idx);
|
|
|
soc_dbg_print_u32(pll_mode);
|
|
|
|
|
|
*vfe = ((SOC_ID_VFE << 16) | (SOC_ID_VFE << 8) | free_idx); // 16: mv left 16 bits, 8: mv left 8 bits
|
|
|
soc_dbg_print_u32(*vfe);
|
|
|
|
|
|
ret = ext_drv_vfe_do_connect(source, vfe_ctx, free_idx, pll_mode, mux_param_ptr_array);
|
|
|
soc_dbg_func_exit();
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_void ext_drv_vfe_set_power(td_void)
|
|
|
{
|
|
|
soc_log_dbg("EXT_DRV_VFE_WORK_MODE_HDDEC\n");
|
|
|
vfe_hal_set_i_clamp_power(TD_FALSE, TD_FALSE, TD_FALSE, TD_FALSE);
|
|
|
vfe_hal_set_r_chn_adc_power(TD_FALSE);
|
|
|
vfe_hal_set_r_chn_pga_power(TD_FALSE);
|
|
|
vfe_hal_set_g_chn_adc_power(TD_FALSE);
|
|
|
vfe_hal_set_g_chn_pga_power(TD_FALSE);
|
|
|
vfe_hal_set_b_chn_adc_power(TD_FALSE);
|
|
|
vfe_hal_set_b_chn_pga_power(TD_FALSE);
|
|
|
|
|
|
vfe_hal_set_pll_refresh_mode(VFE_REFRESH_BYVS_MODE_DIRECT);
|
|
|
vfe_hal_set_phase_refresh_mode(VFE_REFRESH_BYVS_MODE_DIRECT);
|
|
|
vfe_hal_set_clock_sel_refresh_mode(VFE_REFRESH_BYVS_MODE_DIRECT);
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_set_power_by_mode(vfe_drv_ctx_s_ptr vfe_ctx)
|
|
|
{
|
|
|
switch (vfe_ctx->source_attr.work_mode) {
|
|
|
case EXT_DRV_VFE_WORK_MODE_HDDEC: {
|
|
|
ext_drv_vfe_set_power();
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_WORK_MODE_TVD: {
|
|
|
soc_log_dbg("EXT_DRV_VFE_WORK_MODE_TVD\n");
|
|
|
vfe_hal_set_i_clamp_power(TD_FALSE, TD_FALSE, TD_FALSE, TD_FALSE);
|
|
|
vfe_hal_set_com_chn_adc_power(TD_FALSE);
|
|
|
vfe_hal_set_com_chn_pga_power(TD_FALSE);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_WORK_MODE_TVD_SVIDEO: {
|
|
|
soc_log_dbg("EXT_DRV_VFE_WORK_MODE_TVD\n");
|
|
|
vfe_hal_set_i_clamp_power(TD_FALSE, TD_FALSE, TD_FALSE, TD_FALSE);
|
|
|
vfe_hal_set_com_chn_adc_power(TD_FALSE);
|
|
|
vfe_hal_set_com_chn_pga_power(TD_FALSE);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_WORK_MODE_TVD_RF: {
|
|
|
soc_log_dbg("EXT_DRV_VFE_WORK_MODE_TVD_RF\n");
|
|
|
vfe_hal_set_i_clamp_power(TD_FALSE, TD_FALSE, TD_FALSE, TD_FALSE);
|
|
|
vfe_hal_set_com_chn_adc_power(TD_FALSE);
|
|
|
vfe_hal_set_com_chn_pga_power(TD_FALSE);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
default: {
|
|
|
soc_log_err("VFE vfe_ctx->source_attr.work_mode = %d error. \n", vfe_ctx->source_attr.work_mode);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_disconnect(td_handle vfe)
|
|
|
{
|
|
|
td_u32 idx;
|
|
|
td_u32 custom_hddec_set_vclamp;
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
td_s32 ret;
|
|
|
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
if (vfe_ctx->source_attr.work_mode >= EXT_DRV_VFE_WORK_MODE_MAX) {
|
|
|
soc_log_err("work mode is not SIF\n");
|
|
|
soc_err_print_u32(vfe_ctx->source_attr.work_mode);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
ret = ext_drv_vfe_set_power_by_mode(vfe_ctx);
|
|
|
if (ret == TD_FAILURE) {
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
vfe_hal_platform_reset_part_cfg_by_mode(vfe_ctx->source_attr.work_mode);
|
|
|
custom_hddec_set_vclamp = CFG_CUSTOM_HDDEC_SET_VCLAMP_SUPPORT;
|
|
|
if (custom_hddec_set_vclamp) {
|
|
|
soc_log_dbg("custom_hddec_set_vclamp\n");
|
|
|
if (vfe_ctx->source_attr.work_mode == EXT_DRV_VFE_WORK_MODE_TVD) {
|
|
|
/* mm 0xf8a22198 0x70 */
|
|
|
ext_drv_vfe_cfg_hddec_crg_reg(TD_FALSE);
|
|
|
/* mm 0xff2601d8 0x70 */
|
|
|
vfe_hal_set_vs0_in_cfg(VFE_VS_ROUTE_HDDEC);
|
|
|
vfe_hal_set_vs1_in_cfg(VFE_VS_ROUTE_HDDEC);
|
|
|
/* mm 0xff260004 0x33 */
|
|
|
vfe_hal_set_bchan_mux(0x3);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
ret = memset_s(vfe_ctx, sizeof(vfe_drv_ctx), 0, sizeof(vfe_drv_ctx));
|
|
|
if (ret != EOK) {
|
|
|
soc_log_err("secure func call error\n");
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
vfe_ctx->source_attr.work_mode = EXT_DRV_VFE_WORK_MODE_MAX;
|
|
|
|
|
|
#ifndef CONFIG_SOCT_FPGA_SUPPORT
|
|
|
vfe_hal_set_power_down();
|
|
|
vfe_hal_set_adc_res(VFE_ADC_RST_OFF);
|
|
|
#endif
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
/* 设置PLL的时钟 */
|
|
|
td_s32 ext_drv_vfe_set_pll_attr(td_handle vfe, ext_drv_vfe_pll_attr *pll_attr)
|
|
|
{
|
|
|
td_s32 ret;
|
|
|
td_u32 idx;
|
|
|
td_u32 vfe_two_route;
|
|
|
errno_t err_ret;
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
|
|
|
vfe_two_route = CFG_VFE_TWO_ROUTE_SUPPORT;
|
|
|
if (vfe_two_route) {
|
|
|
if (vfe_ctx->source_attr.work_mode != EXT_DRV_VFE_WORK_MODE_HDDEC) {
|
|
|
soc_log_dbg("VFE_SUPPORT_TWO_ROUTE: work_mode != EXT_DRV_VFE_WORK_MODE_HDDEC\n");
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
ret = vfe_set_pll_attr(pll_attr, vfe_ctx->phase);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
soc_log_err("VFE set pll attr failure.\n");
|
|
|
}
|
|
|
err_ret = memcpy_s(&vfe_ctx->pll_attr, sizeof(vfe_ctx->pll_attr), pll_attr, sizeof(ext_drv_vfe_pll_attr));
|
|
|
if (err_ret != EOK) {
|
|
|
soc_log_err("secure func call error\n");
|
|
|
return err_ret;
|
|
|
}
|
|
|
|
|
|
if (vfe_ctx->source_attr.work_mode == EXT_DRV_VFE_WORK_MODE_HDDEC) {
|
|
|
#ifndef CONFIG_SOCT_FPGA_SUPPORT
|
|
|
soc_log_dbg("EXT_VFE_EXTERNAL:set pll refresh mode VFE_REFRESH_BYVS_MODE_VBI\n");
|
|
|
vfe_hal_set_pll_refresh_mode(VFE_REFRESH_BYVS_MODE_VBI);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
/* 同步类型选择以及外同步和复合同步是否极性反向 */
|
|
|
td_s32 ext_drv_vfe_set_sync_type(td_handle vfe, ext_drv_vfe_sync_type sync_type, td_bool sep_sync_inv)
|
|
|
{
|
|
|
vfe_pll_sync_sel en_pll_sync_sel;
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
td_u32 idx;
|
|
|
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
if (sync_type >= EXT_DRV_VFE_SYNC_MAX) {
|
|
|
soc_log_err("invalid sync type :\n");
|
|
|
soc_err_print_u32(sync_type);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (vfe_ctx->source_attr.work_mode >= EXT_DRV_VFE_WORK_MODE_MAX) {
|
|
|
soc_log_err(" can't set sync type when vfe not connected !\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
en_pll_sync_sel = VFE_PLL_SYNC_SEL_SLICER0;
|
|
|
if (sync_type == EXT_DRV_VFE_SYNC_SEP) {
|
|
|
if (vfe_ctx->source_attr.sync_chn_mux == EXT_DRV_INPUT_MUX_SYNC_HVS0) {
|
|
|
soc_func_trace_low_freq_cnt_begin(1000); // 1000: input freq value
|
|
|
soc_log_dbg("pll_sync_sel set as VFE_PLL_SYNC_SEL_HS0\n");
|
|
|
soc_func_trace_low_freq_cnt_end();
|
|
|
en_pll_sync_sel = VFE_PLL_SYNC_SEL_HS0;
|
|
|
} else {
|
|
|
soc_func_trace_low_freq_cnt_begin(1000); // 1000: input freq value
|
|
|
soc_log_dbg("pll_sync_sel set as VFE_PLL_SYNC_SEL_HS1\n");
|
|
|
soc_func_trace_low_freq_cnt_end();
|
|
|
en_pll_sync_sel = VFE_PLL_SYNC_SEL_HS1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
vfe_hal_set_sync_type(en_pll_sync_sel, vfe_ctx->source_attr.src_type);
|
|
|
|
|
|
vfe_hal_set_polar_out(TD_TRUE, sep_sync_inv, TD_TRUE, TD_FALSE);
|
|
|
|
|
|
vfe_ctx->dpll_sync_sel = sync_type;
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_set_gain(td_handle vfe, ext_drv_vfe_data_chn_type data_chn, td_u32 gain)
|
|
|
{
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
td_u32 idx;
|
|
|
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
if (gain >= VFE_GAIN_MAX) {
|
|
|
soc_log_err("invalid gain value :\n");
|
|
|
soc_err_print_u32(gain);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (vfe_ctx->source_attr.work_mode >= EXT_DRV_VFE_WORK_MODE_MAX) {
|
|
|
soc_log_err(" can't set gain when vfe not connected !\n");
|
|
|
soc_err_print_u32(vfe_ctx->source_attr.work_mode);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
switch (data_chn) {
|
|
|
case EXT_DRV_VFE_DATA_CHN_R: {
|
|
|
vfe_hal_set_r_chn_gain(gain);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_G: {
|
|
|
vfe_hal_set_g_chn_gain(gain);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_B: {
|
|
|
vfe_hal_set_b_chn_gain(gain);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_COM: {
|
|
|
vfe_hal_set_com_chn_gain(gain);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
default: {
|
|
|
soc_log_err("invalid data channel value :\n");
|
|
|
soc_err_print_u32(data_chn);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_get_gain(td_handle vfe, ext_drv_vfe_data_chn_type data_chn, td_u32 *gain)
|
|
|
{
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
td_u32 idx;
|
|
|
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
if (gain == NULL) {
|
|
|
soc_log_err("NULL point \n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
switch (data_chn) {
|
|
|
case EXT_DRV_VFE_DATA_CHN_R: {
|
|
|
vfe_hal_get_r_chn_gain(gain);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_G: {
|
|
|
vfe_hal_get_g_chn_gain(gain);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_B: {
|
|
|
vfe_hal_get_b_chn_gain(gain);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_COM: {
|
|
|
vfe_hal_get_com_chn_gain(gain);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
default: {
|
|
|
soc_log_err("invalid data channel value :\n");
|
|
|
soc_err_print_u32(data_chn);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_set_offset(td_handle vfe, ext_drv_vfe_data_chn_type data_chn, td_u32 offset)
|
|
|
{
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
td_u32 idx;
|
|
|
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
if (offset > VFE_OFFSET_MAX) {
|
|
|
soc_log_err("invalid offset value :\n");
|
|
|
soc_err_print_u32(offset);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (vfe_ctx->source_attr.work_mode >= EXT_DRV_VFE_WORK_MODE_MAX) {
|
|
|
soc_log_err(" can't set offset when vfe not connected !\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
switch (data_chn) {
|
|
|
case EXT_DRV_VFE_DATA_CHN_R: {
|
|
|
vfe_hal_set_r_chn_offset(offset);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_G: {
|
|
|
vfe_hal_set_g_chn_offset(offset);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_B: {
|
|
|
vfe_hal_set_b_chn_offset(offset);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_COM: {
|
|
|
vfe_hal_set_com_chn_offset(offset);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
default: {
|
|
|
soc_log_err("invalid data channel value :\n");
|
|
|
soc_err_print_u32(data_chn);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_get_offset(td_handle vfe, ext_drv_vfe_data_chn_type data_chn, td_u32 *offset)
|
|
|
{
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
td_u32 idx;
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
if (offset == NULL) {
|
|
|
soc_log_err("NULL point \n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
switch (data_chn) {
|
|
|
case EXT_DRV_VFE_DATA_CHN_R: {
|
|
|
vfe_hal_get_r_chn_offset(offset);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_G: {
|
|
|
vfe_hal_get_g_chn_offset(offset);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_B: {
|
|
|
vfe_hal_get_b_chn_offset(offset);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_COM: {
|
|
|
vfe_hal_get_com_chn_offset(offset);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
default: {
|
|
|
soc_log_err("invalid data channel value :\n");
|
|
|
soc_err_print_u32(data_chn);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_get_sif_gain(td_handle vfe, td_u32 *sif_gain)
|
|
|
{
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
td_u32 idx;
|
|
|
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
if (sif_gain == NULL) {
|
|
|
soc_log_err("NULL point \n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
if (vfe_ctx->source_attr.work_mode != EXT_DRV_VFE_WORK_MODE_TVD_RF) {
|
|
|
soc_log_err("work mode = %d is not SIF\n", vfe_ctx->source_attr.work_mode);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
vfe_hal_get_sif_chn_gain(sif_gain);
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
/* 设置htotal(采样时钟) */
|
|
|
td_s32 ext_drv_vfe_set_htotal(td_handle vfe, td_u32 htotal)
|
|
|
{
|
|
|
vfe_dpll_div_sel dpll_div;
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
td_u32 idx;
|
|
|
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
vfe_hal_set_apll_cfg7(0, 0);
|
|
|
|
|
|
vfe_hal_get_dpll_pdiv_cfg(&dpll_div);
|
|
|
vfe_hal_set_dpll_htotal_cfg(dpll_div, htotal);
|
|
|
|
|
|
osal_msleep(20); // sleep for 20 ms
|
|
|
|
|
|
vfe_ctx->pll_attr.h_total = htotal;
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_set_phase(td_handle vfe, td_u32 phase)
|
|
|
{
|
|
|
vfe_dpll_div_sel dpll_div;
|
|
|
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
td_u32 idx;
|
|
|
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
if (phase >= VFE_PHASE_MAX) {
|
|
|
soc_log_err("invalid phase value :\n");
|
|
|
soc_err_print_u32(phase);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (vfe_ctx->source_attr.work_mode >= EXT_DRV_VFE_WORK_MODE_MAX) {
|
|
|
soc_log_err(" can't set phase when vfe not connected !\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
vfe_hal_get_dpll_pdiv_cfg(&dpll_div);
|
|
|
vfe_hal_set_phase(dpll_div, phase);
|
|
|
|
|
|
vfe_ctx->phase = phase;
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_void ext_drv_vfe_set_r_chn_clamp(const ext_drv_vfe_clamp_attr *clamp)
|
|
|
{
|
|
|
if (clamp == TD_NULL) {
|
|
|
soc_log_err("input clamp is null!\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (clamp->clamp_type == EXT_DRV_VFE_CLAMP_V) {
|
|
|
vfe_hal_set_r_chn_v_clamp(&clamp->vclamp_attr);
|
|
|
} else {
|
|
|
vfe_hal_set_r_chn_i_clamp(&clamp->iclamp_attr);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
td_void ext_drv_vfe_set_g_chn_clamp(const ext_drv_vfe_clamp_attr *clamp)
|
|
|
{
|
|
|
if (clamp == TD_NULL) {
|
|
|
soc_log_err("input clamp is null!\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (clamp->clamp_type == EXT_DRV_VFE_CLAMP_V) {
|
|
|
vfe_hal_set_g_chn_v_clamp(&clamp->vclamp_attr);
|
|
|
} else {
|
|
|
vfe_hal_set_g_chn_i_clamp(&clamp->iclamp_attr);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
td_void ext_drv_vfe_set_b_chn_clamp(const ext_drv_vfe_clamp_attr *clamp)
|
|
|
{
|
|
|
if (clamp == TD_NULL) {
|
|
|
soc_log_err("input clamp is null!\n");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (clamp->clamp_type == EXT_DRV_VFE_CLAMP_V) {
|
|
|
vfe_hal_set_b_chn_v_clamp(&clamp->vclamp_attr);
|
|
|
} else {
|
|
|
vfe_hal_set_b_chn_i_clamp(&clamp->iclamp_attr);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_set_cvbs_clamp(const ext_drv_vfe_clamp_attr *clamp)
|
|
|
{
|
|
|
if (clamp == TD_NULL) {
|
|
|
soc_log_err("clamp is invalid!\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (clamp->clamp_type == EXT_DRV_VFE_CLAMP_V) {
|
|
|
soc_log_err("please chose i clamp!\n");
|
|
|
return TD_FAILURE;
|
|
|
} else {
|
|
|
vfe_hal_set_com_chn_i_clamp(&clamp->iclamp_attr);
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_set_clamp_by_chn(vfe_drv_ctx_s_ptr vfe_ctx, const ext_drv_vfe_clamp_attr *clamp,
|
|
|
ext_drv_vfe_data_chn_type data_chn)
|
|
|
{
|
|
|
td_s32 ret;
|
|
|
|
|
|
if (vfe_ctx == TD_NULL) {
|
|
|
soc_log_err("invaliad para vfe_ctx\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (data_chn == EXT_DRV_VFE_DATA_CHN_R) {
|
|
|
ext_drv_vfe_set_r_chn_clamp(clamp);
|
|
|
ret = memcpy_s(&vfe_ctx->r_chn_clamp, sizeof(vfe_ctx->r_chn_clamp),
|
|
|
clamp, sizeof(ext_drv_vfe_clamp_attr));
|
|
|
if (ret != EOK) {
|
|
|
soc_log_err("secure func call error\n");
|
|
|
return ret;
|
|
|
}
|
|
|
} else if (data_chn == EXT_DRV_VFE_DATA_CHN_G) {
|
|
|
ext_drv_vfe_set_g_chn_clamp(clamp);
|
|
|
ret = memcpy_s(&vfe_ctx->g_chn_clamp, sizeof(vfe_ctx->g_chn_clamp),
|
|
|
clamp, sizeof(ext_drv_vfe_clamp_attr));
|
|
|
if (ret != EOK) {
|
|
|
soc_log_err("secure func call error\n");
|
|
|
return ret;
|
|
|
}
|
|
|
} else if (data_chn == EXT_DRV_VFE_DATA_CHN_B) {
|
|
|
ext_drv_vfe_set_b_chn_clamp(clamp);
|
|
|
ret = memcpy_s(&vfe_ctx->b_chn_clamp, sizeof(vfe_ctx->b_chn_clamp),
|
|
|
clamp, sizeof(ext_drv_vfe_clamp_attr));
|
|
|
if (ret != EOK) {
|
|
|
soc_log_err("secure func call error\n");
|
|
|
return ret;
|
|
|
}
|
|
|
} else if (data_chn == EXT_DRV_VFE_DATA_CHN_COM) {
|
|
|
ret = ext_drv_vfe_set_cvbs_clamp(clamp);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
ret = memcpy_s(&vfe_ctx->com_chn_clamp, sizeof(vfe_ctx->com_chn_clamp),
|
|
|
clamp, sizeof(ext_drv_vfe_clamp_attr));
|
|
|
if (ret != EOK) {
|
|
|
soc_log_err("secure func call error\n");
|
|
|
return ret;
|
|
|
}
|
|
|
} else {
|
|
|
soc_log_err("invalid data channel value :\n");
|
|
|
soc_err_print_u32(data_chn);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
/* iclamp和vclamp */
|
|
|
td_s32 ext_drv_vfe_set_clamp(td_handle vfe, ext_drv_vfe_data_chn_type data_chn, const ext_drv_vfe_clamp_attr *clamp)
|
|
|
{
|
|
|
td_s32 ret;
|
|
|
td_u32 idx;
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
|
|
|
if (clamp == TD_NULL) {
|
|
|
soc_log_err("NULL point \n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
ret = vfe_check_clamp_attr(clamp);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
soc_log_err(" some attr of clamp attr is invalid\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (vfe_ctx->source_attr.work_mode >= EXT_DRV_VFE_WORK_MODE_MAX) {
|
|
|
soc_log_err(" can't set clamp attr when vfe not connected !\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
ret = ext_drv_vfe_set_clamp_by_chn(vfe_ctx, clamp, data_chn);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
return ret;
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
/* 在标准信号时保持默认值,非标讯号可微调slicer level,一共16档范围为0-32,目前只能使用通道0 */
|
|
|
td_s32 ext_drv_vfe_set_slicer_level(td_handle vfe, ext_drv_vfe_sync_chn_type sync_chn, td_u32 level)
|
|
|
{
|
|
|
td_u32 temp_lev;
|
|
|
td_u32 idx;
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
if (level > VFE_SLICER_LEVEL_MAX) {
|
|
|
soc_log_err("invalid slicer level value :\n");
|
|
|
soc_err_print_u32(level);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (vfe_ctx->source_attr.work_mode >= EXT_DRV_VFE_WORK_MODE_MAX) {
|
|
|
soc_log_err(" can't set slicer level when vfe not connected !\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
temp_lev = VFE_SLICER_LEVEL_MAX - level;
|
|
|
|
|
|
switch (sync_chn) {
|
|
|
case EXT_DRV_VFE_SYNC_CHN_1: {
|
|
|
vfe_hal_set_slicer1_level(temp_lev);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_SYNC_CHN_2: {
|
|
|
vfe_hal_set_slicer2_level(temp_lev);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
default: {
|
|
|
soc_log_err("invalid sync channel value :\n");
|
|
|
soc_err_print_u32(sync_chn);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_get_slicer_level(td_handle vfe, ext_drv_vfe_sync_chn_type sync_chn, td_u32 *level)
|
|
|
{
|
|
|
td_u32 temp_lev = 0;
|
|
|
td_u32 idx;
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
if (level == NULL) {
|
|
|
soc_log_err("NULL point \n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
switch (sync_chn) {
|
|
|
case EXT_DRV_VFE_SYNC_CHN_1: {
|
|
|
vfe_hal_get_slicer1_level(&temp_lev);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case EXT_DRV_VFE_SYNC_CHN_2: {
|
|
|
vfe_hal_get_slicer2_level(&temp_lev);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
default: {
|
|
|
soc_log_err("invalid sync channel value :\n");
|
|
|
soc_err_print_u32(sync_chn);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
*level = VFE_SLICER_LEVEL_MAX - temp_lev;
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_set_lpf_by_chan(vfe_drv_ctx_s_ptr vfe_ctx, ext_drv_vfe_data_chn_type data_chn,
|
|
|
const ext_drv_vfe_lpf_filter_attr *lpf_attr)
|
|
|
{
|
|
|
td_s32 ret;
|
|
|
|
|
|
if (vfe_ctx == TD_NULL || lpf_attr == TD_NULL) {
|
|
|
soc_log_err("input null pointer.\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
switch (data_chn) {
|
|
|
case EXT_DRV_VFE_DATA_CHN_R:
|
|
|
if (vfe_ctx->source_attr.work_mode == EXT_DRV_VFE_WORK_MODE_TVD_RF) {
|
|
|
soc_log_err(" EXT_DRV_VFE_WORK_MODE_TVD_RF can't set LPF!\n");
|
|
|
} else {
|
|
|
vfe_hal_set_r_chn_lpf(lpf_attr->rgb_chn_lpf_mode); // SIF通道不能调整滤波系数
|
|
|
vfe_ctx->r_chn_lpf_mode = lpf_attr->rgb_chn_lpf_mode;
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_G:
|
|
|
vfe_hal_set_g_chn_lpf(lpf_attr->rgb_chn_lpf_mode);
|
|
|
vfe_ctx->g_chn_lpf_mode = lpf_attr->rgb_chn_lpf_mode;
|
|
|
break;
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_B:
|
|
|
vfe_hal_set_b_chn_lpf(lpf_attr->rgb_chn_lpf_mode);
|
|
|
vfe_ctx->b_chn_lpf_mode = lpf_attr->rgb_chn_lpf_mode;
|
|
|
break;
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_COM:
|
|
|
vfe_hal_set_com_chn_filter(&lpf_attr->com_chn_filter);
|
|
|
ret = memcpy_s(&vfe_ctx->com_chn_filter, sizeof(vfe_ctx->com_chn_filter),
|
|
|
&lpf_attr->com_chn_filter, sizeof(ext_drv_vfe_filter_attr));
|
|
|
if (ret != EOK) {
|
|
|
soc_log_err("secure func call error\n");
|
|
|
return ret;
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
soc_err_print_u32(data_chn);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
/* 调整各个通道的滤波的工作模式 */
|
|
|
td_s32 ext_drv_vfe_set_lpf_attr(td_handle vfe, ext_drv_vfe_data_chn_type data_chn,
|
|
|
const ext_drv_vfe_lpf_filter_attr *lpf_attr)
|
|
|
{
|
|
|
td_s32 ret;
|
|
|
td_u32 idx;
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
if (lpf_attr == NULL) {
|
|
|
soc_log_err("NULL point \n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
if (vfe_ctx->source_attr.work_mode >= EXT_DRV_VFE_WORK_MODE_MAX) {
|
|
|
soc_log_err(" can't set lpf attr when vfe not connected !\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
ret = vfe_check_lpf_attr(lpf_attr);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
soc_log_err("some attr of lpf attr is invalid \n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
ret = ext_drv_vfe_set_lpf_by_chan(vfe_ctx, data_chn, lpf_attr);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 drv_vfe_check_ctx_workmode(td_handle vfe)
|
|
|
{
|
|
|
vfe_drv_ctx_s_ptr vfe_ctx = TD_NULL;
|
|
|
td_u32 idx;
|
|
|
|
|
|
idx = (vfe & 0xFF);
|
|
|
if (idx >= VFE_WORKMODE_MAX) {
|
|
|
soc_log_err("VFE handle(%#x) is invalid, vi_id error.\n", vfe);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
vfe_ctx = &g_vfe_drv_ctx[idx];
|
|
|
|
|
|
if (vfe_ctx->source_attr.work_mode >= EXT_DRV_VFE_WORK_MODE_MAX) {
|
|
|
soc_log_err("vfe not connected !\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_power_ctrl(td_handle vfe, ext_drv_vfe_data_chn_type data_chn, td_bool enable)
|
|
|
{
|
|
|
ext_drv_vfe_pll_attr pll_attr;
|
|
|
td_s32 ret;
|
|
|
|
|
|
if (data_chn == EXT_DRV_VFE_DATA_CHN_DAC) {
|
|
|
vfe_hal_set_vdac2_power(enable);
|
|
|
soc_log_info("set AVOUT %s\n", enable ? "enable" : "disable");
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
ret = drv_vfe_check_ctx_workmode(vfe);
|
|
|
if (ret != TD_SUCCESS) {
|
|
|
soc_log_err(" can't set power ctrl when vfe not connected !\n");
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
pll_attr.bypass_dpll = TD_TRUE;
|
|
|
pll_attr.h_total = 856; // set h_total to 856
|
|
|
|
|
|
pll_attr.sample_clk = vfe_platform_get_sample_clk(TD_FALSE);
|
|
|
switch (data_chn) {
|
|
|
case EXT_DRV_VFE_DATA_CHN_R:
|
|
|
vfe_hal_set_r_chn_pga_power(enable);
|
|
|
vfe_hal_set_r_chn_adc_power(enable);
|
|
|
break;
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_G:
|
|
|
vfe_hal_set_g_chn_pga_power(enable);
|
|
|
vfe_hal_set_g_chn_adc_power(enable);
|
|
|
break;
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_B:
|
|
|
vfe_hal_set_b_chn_pga_power(enable);
|
|
|
vfe_hal_set_b_chn_adc_power(enable);
|
|
|
break;
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_COM:
|
|
|
vfe_hal_set_com_chn_pga_power(enable);
|
|
|
vfe_hal_set_com_chn_adc_power(enable);
|
|
|
break;
|
|
|
|
|
|
case EXT_DRV_VFE_DATA_CHN_APLL:
|
|
|
vfe_set_no_sig_pll_attr(&pll_attr);
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
soc_err_print_u32(data_chn);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_set_video_out_gain(td_u32 r_gain, td_u32 i_gain)
|
|
|
{
|
|
|
soc_func_trace_low_freq_cnt_begin(1000); // 1000: input freq value
|
|
|
soc_dbg_print_u32(r_gain);
|
|
|
soc_dbg_print_u32(i_gain);
|
|
|
soc_func_trace_low_freq_cnt_end();
|
|
|
|
|
|
vfe_hal_set_vdac_gain(r_gain, i_gain);
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_s32 ext_drv_vfe_cfg_video_out(ext_drv_vfe_video_out_chn video_out_chn,
|
|
|
td_bool enable, ext_drv_source ensource)
|
|
|
{
|
|
|
switch (video_out_chn) {
|
|
|
case EXT_DRV_VFE_VIDEO_OUT_CHN_1: {
|
|
|
vfe_hal_set_vdac1_chan_sel(VFE_VDAC1_CHAN_SEL_EXTVDAC1);
|
|
|
vfe_hal_set_dac0_clk_en(enable, TD_TRUE);
|
|
|
if (ensource == EXT_DRV_SOURCE_ATV) {
|
|
|
vfe_hal_set_dac0_cvbs_out(TD_FALSE);
|
|
|
} else if (ensource == EXT_DRV_SOURCE_CVBS) {
|
|
|
vfe_hal_set_dac0_cvbs_out(TD_TRUE);
|
|
|
}
|
|
|
vfe_hal_set_vdac2_power(enable);
|
|
|
vfe_hal_set_vdac1_power(TD_TRUE);
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
case EXT_DRV_VFE_VIDEO_OUT_CHN_2: {
|
|
|
vfe_hal_set_dac1_clk_en(enable, TD_TRUE);
|
|
|
vfe_hal_set_vdac2_power(enable);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
default: {
|
|
|
soc_err_print_u32(video_out_chn);
|
|
|
return TD_FAILURE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return TD_SUCCESS;
|
|
|
}
|
|
|
|
|
|
td_u32 ext_drv_vfe_get_cvbs_sample_rate(td_void)
|
|
|
{
|
|
|
return vfe_platform_get_sample_clk(TD_TRUE);
|
|
|
}
|
|
|
|
|
|
td_void ext_vfe_drv_pm_lowpower_enter(td_void)
|
|
|
{
|
|
|
vfe_hal_pm_lowpower_enter();
|
|
|
}
|
|
|
|
|
|
td_void ext_vfe_drv_pm_lowpower_exit(td_void)
|
|
|
{
|
|
|
vfe_hal_pm_lowpower_exit();
|
|
|
}
|
|
|
|
|
|
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_init);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_de_init);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_adc_cal);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_apll_cfg7);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_connect);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_disconnect);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_set_pll_attr);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_set_sync_type);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_set_gain);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_get_gain);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_set_offset);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_get_offset);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_get_sif_gain);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_set_htotal);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_set_phase);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_set_clamp);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_set_slicer_level);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_get_slicer_level);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_set_lpf_attr);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_power_ctrl);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_set_video_out_gain);
|
|
|
EXPORT_SYMBOL(ext_drv_vfe_cfg_video_out);
|
|
|
|