SmartAudio/lichee/linux-4.9/drivers/media/platform/sunxi-tvd/bsp_tvd.c

751 lines
26 KiB
C
Executable File

/*
* drivers/media/platform/sunxi-tvd/bsp_tvd/bsp_tvd.c
*
* Copyright (c) 2007-2018 Allwinnertech Co., Ltd.
* Author: zhengxiaobin <zhengxiaobin@allwinnertech.com>
*
* tvd lowlevel
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "bsp_tvd.h"
static volatile __tvd_top_dev_t *tvd_top_dev;
static volatile __tvd_dev_t *tvd_device[4];
s32 tvd_top_set_reg_base(unsigned long base)
{
tvd_top_dev = (__tvd_top_dev_t *)base;
return 0;
}
s32 tvd_set_reg_base(u32 sel, unsigned long base)
{
if (sel > 3)
return -1;
tvd_device[sel] = (__tvd_dev_t *)base;
return 0;
}
void tvd_3d_mode(u32 _3d_sel, u32 _3d_en, u32 _3d_addr)
{
tvd_top_dev->tvd_3d_ctl3.bits.comb_3d_addr0 = _3d_addr;
tvd_top_dev->tvd_3d_ctl4.bits.comb_3d_addr1 = _3d_addr+0x200000;
tvd_top_dev->tvd_3d_ctl5.bits.comb_3d_size = 0x200000;
tvd_top_dev->tvd_3d_ctl1.bits.comb_3d_sel = _3d_sel;
tvd_top_dev->tvd_3d_ctl1.bits.comb_3d_en = _3d_en;
tvd_top_dev->tvd_3d_ctl1.bits.tvd_en_3d_dma = _3d_en;
tvd_device[_3d_sel]->tvd_yc_sep1.bits._3d_comb_filter_dis =
_3d_en ? 0 : 1;
}
void tvd_enable_chanel(u32 sel, u32 en)
{
tvd_device[sel]->tvd_en.bits.tvd_en_ch = en;
}
s32 tvd_init(u32 sel, u32 interface)
{
if (sel == 0 && interface != CVBS_INTERFACE) {
tvd_adc_config(0, 1);
tvd_adc_config(1, 1);
tvd_adc_config(2, 1);
} else if (interface == CVBS_INTERFACE || sel == 3) {
tvd_adc_config(sel, 1);
}
if (tvd_top_dev->tvd_top_map.bits.tvd_adc_map != 2) {
tvd_top_dev->tvd_top_map.bits.tvd_adc_map = (interface ? 2 : 1);
/*
(sel == 0) ? (interface ? 2 : 1) :
(sel == 1) ? (interface ? 0 : 1) :
(sel == 2) ? (interface ? 0 : 1) :
(interface ? 0 : 1);
*/
}
/*
if(sel==0)
{
tvd_top_dev->tvd_top_map.bits.tvd_adc_map = interface ?
2 : 1;
}
*/
tvd_enable_chanel(sel, 1);
return 0;
}
s32 tvd_deinit(u32 sel, u32 interface)
{
tvd_enable_chanel(sel, 0);
if (sel == 0 && interface != CVBS_INTERFACE) {
tvd_adc_config(0, 0);
tvd_adc_config(1, 0);
tvd_adc_config(2, 0);
} else if (interface == CVBS_INTERFACE || sel == 3) {
tvd_adc_config(sel, 0);
}
return 0;
}
s32 tvd_get_lock(u32 sel)
{
u32 reg_val;
u32 lock;
u32 irq_status;
tvd_irq_status_get(sel, TVD_IRQ_UNLOCK, &irq_status);
tvd_irq_status_clear(sel, TVD_IRQ_UNLOCK);
reg_val = tvd_device[sel]->tvd_status4.dwval;
if (0xe != (reg_val & 0xf) || (0x1 == irq_status))
lock = 0;
else
lock = 1;
return lock;
}
void tvd_reset(u32 sel)
{
volatile u32 delay = 100;
tvd_device[sel]->tvd_en.bits.tvd_en_ch = 0;
while (delay--)
;
tvd_device[sel]->tvd_en.bits.tvd_en_ch = 1;
}
void tvd_blue_display_mode(u32 sel, u32 mode)
{
tvd_device[sel]->tvd_mode.bits.blue_display_mode = mode;
}
s32 tvd_get_status(u32 sel, u32 *locked, u32 *system)
{
if (tvd_device[sel]->tvd_status4.bits.no_signal_detected == 0 &&
tvd_device[sel]->tvd_status4.bits.h_locked == 1 &&
tvd_device[sel]->tvd_status4.bits.v_locked == 1)
*locked = 1;
else
*locked = 0;
if (tvd_device[sel]->tvd_status4.bits._625lines_detected == 1)
*system = 1;
else
*system = 0;
return 0;
}
/*system: 1:pal; 0:NTSC*/
s32 tvd_config(u32 sel, u32 interface, u32 system)
{
tvd_device[sel]->tvd_wb1.bits.wb_en = 0; /*wb dma disable*/
tvd_device[sel]->tvd_en.bits.tvd_en_ch = 0; /*tvd module disable*/
tvd_device[sel]->tvd_en.bits.en_lock_disable_write_back1only_start_wb_when_locked = 0;
tvd_device[sel]->tvd_en.bits.en_lock_disable_write_back2when_unlocked = 0;
tvd_device[sel]->tvd_en.bits.clr_rsmp_fifo = 0;
tvd_device[sel]->tvd_mode.bits.blue_display_mode = 2; /*auto*/
tvd_device[sel]->tvd_mode.bits.blue_color = 1; /*black*/
tvd_device[sel]->tvd_clamp_agc1.bits.agc_en = 1;
tvd_device[sel]->tvd_clamp_agc1.bits.agc_frequence = 1;
tvd_device[sel]->tvd_clamp_agc1.bits.cagc_en = interface ? 0 : 1;
tvd_device[sel]->tvd_clamp_agc2.bits.agc_gate_width = 64;
tvd_device[sel]->tvd_clamp_agc2.bits.agc_backporch_delay = 100;
tvd_device[sel]->tvd_clamp_agc2.bits.agc_gate_begin = 1666;
tvd_device[sel]->tvd_hlock1.bits.h_sample_step = 0x20000000;
tvd_device[sel]->tvd_hlock2.bits.hsync_filter_gate_start_time = 214;
tvd_device[sel]->tvd_hlock2.bits.hsync_filter_gate_end_time = 78;
tvd_device[sel]->tvd_hlock3.bits.hsync_rising_detect_window_start_time =
45;
tvd_device[sel]->tvd_hlock3.bits.hsync_rising_detect_window_end_time =
80;
tvd_device[sel]->tvd_hlock3.bits.hsync_tip_detect_window_start_time =
233;
tvd_device[sel]->tvd_hlock3.bits.hsync_tip_detect_window_end_time = 15;
tvd_device[sel]
->tvd_hlock4.bits
.hsync_detect_window_start_time_for_coarse_detection = 0;
tvd_device[sel]->tvd_hlock4.bits.hsync_detect_window_end_time_for_corase_detect = 128;
tvd_device[sel]->tvd_hlock4.bits.hsync_rising_time_for_fine_detect = 62;
tvd_device[sel]->tvd_hlock4.bits.hsync_fine_to_coarse_offset = 62;
tvd_device[sel]->tvd_mode.bits.ypbpr_mode = interface ? 1 : 0;
tvd_device[sel]->tvd_mode.bits.svideo_mode = 0;
tvd_device[sel]->tvd_mode.bits.progressive_mode =
(interface == 2) ? 1 : 0;
tvd_device[sel]->tvd_clamp_agc1.bits.agc_target = interface ? 0 :
(system == 0) ? 221 : 220;
tvd_device[sel]->tvd_clamp_agc1.bits.cagc_target = interface ?
0 : (system == 0) ?
160 : 144;
tvd_device[sel]->tvd_clamp_agc2.bits.black_level_clamp =
(interface == 0 || system == 0) ? 1 : 0;
tvd_device[sel]->tvd_hlock2.bits.htol = system;
tvd_device[sel]->tvd_vlock1.bits.vtol = system;
tvd_device[sel]->tvd_hlock5.bits.hactive_start = (system ? 137 : 130) -
(interface ? 20 : 0);
tvd_device[sel]->tvd_hlock5.bits.hactive_width = 80;
tvd_device[sel]->tvd_vlock1.bits.vactive_start = system?42:34;
tvd_device[sel]->tvd_vlock1.bits.vactive_height = system?193:97;
tvd_device[sel]->tvd_hlock5.bits.backporch_detect_window_start_time = 34;
tvd_device[sel]->tvd_hlock5.bits.backporch_detect_window_end_time = 66;
tvd_device[sel]->tvd_vlock2.bits.hsync_dectector_disable_start_line = 112;
tvd_device[sel]->tvd_vlock2.bits.hsync_detector_disable_end_line = 14;
tvd_device[sel]->tvd_clock1.bits.color_kill_en = 1;
tvd_device[sel]->tvd_clock1.bits.color_std = system;
tvd_device[sel]->tvd_clock1.bits.color_std_ntsc = 0;
tvd_device[sel]->tvd_clock1.bits.burst_gate_start_time = 50;
tvd_device[sel]->tvd_clock1.bits.burst_gate_end_time = 70;
tvd_device[sel]->tvd_clock1.bits.wide_burst_gate = 0;
tvd_device[sel]->tvd_clock1.bits.chroma_lpf = 1;
tvd_device[sel]->tvd_clock2.bits.c_sample_step = interface ? 0x0 :
system ? 0x2a098acb : 0x21f07c1f;
tvd_device[sel]->tvd_yc_sep1.bits._3d_comb_filter_mode = system ? 4 : 1;
tvd_device[sel]->tvd_yc_sep1.bits._3d_comb_filter_dis = 1;
tvd_device[sel]->tvd_yc_sep1.bits._2d_comb_filter_mode = system?6:0;
tvd_device[sel]->tvd_yc_sep1.bits.secam_notch_wide = 0;
tvd_device[sel]->tvd_yc_sep1.bits.chroma_bandpass_filter_en = 1;
tvd_device[sel]->tvd_yc_sep1.bits.pal_chroma_level = 16;
tvd_device[sel]->tvd_yc_sep1.bits.comb_filter_buffer_clear = 0;
tvd_device[sel]->tvd_yc_sep1.bits.notch_factor = 0;
tvd_device[sel]->tvd_yc_sep1.bits._2d_comb_factor = 2;
tvd_device[sel]->tvd_yc_sep1.bits._3d_comb_factor = system ? 0 : 1;
tvd_device[sel]->tvd_yc_sep1.bits.chroma_coring_enable = 0;
tvd_device[sel]->tvd_yc_sep2.bits.horizontal_luma_filter_gain = 2;
tvd_device[sel]->tvd_yc_sep2.bits.horizontal_chroma_filter_gain = 2;
tvd_device[sel]->tvd_yc_sep2.bits.luma_vertical_filter_gain = 3;
tvd_device[sel]->tvd_yc_sep2.bits.chroma_vertical_filter_gain = 3;
tvd_device[sel]->tvd_yc_sep2.bits.motion_detect_noise_detect_en = 1;
tvd_device[sel]->tvd_yc_sep2.bits.motion_detect_noise_threshold =
system ? 32 : 33;
tvd_device[sel]->tvd_yc_sep2.bits.noise_detect_en = system ? 0 : 1;
/* default value:50 */
tvd_device[sel]->tvd_yc_sep2.bits.noise_threshold = 10;
tvd_device[sel]->tvd_yc_sep2.bits.luma_noise_factor = 3;
tvd_device[sel]->tvd_yc_sep2.bits.chroma_noise_factor = 2;
tvd_device[sel]->tvd_yc_sep2.bits.burst_noise_factor = 0;
tvd_device[sel]->tvd_yc_sep2.bits.vertical_noise_factor = 0;
tvd_device[sel]->tvd_enhance1.bits.yc_delay = 0;
tvd_device[sel]->tvd_enhance1.bits.contrast_gain =
tvd_get_contrast(sel);
tvd_device[sel]->tvd_enhance1.bits.bright_offset = tvd_get_luma(sel);
if (system == 0) {
tvd_device[sel]->tvd_enhance1.bits.sharp_en = 1;
tvd_device[sel]->tvd_enhance1.bits.sharp_coef1 = 5;
tvd_device[sel]->tvd_enhance1.bits.sharp_coef2 = 2;
tvd_device[sel]->tvd_enhance3.bits.cbcr_gain_en = 1;
} else if (system == 1) {
tvd_device[sel]->tvd_enhance1.bits.sharp_en = 0;
tvd_device[sel]->tvd_enhance1.bits.sharp_coef1 = 2;
tvd_device[sel]->tvd_enhance1.bits.sharp_coef2 = 1;
tvd_device[sel]->tvd_enhance3.bits.cbcr_gain_en = 0;
}
tvd_device[sel]->tvd_enhance1.bits.sharp_en = 0;
tvd_device[sel]->tvd_enhance1.bits.sharp_coef1 = 2;
tvd_device[sel]->tvd_enhance1.bits.sharp_coef2 = 1;
tvd_device[sel]->tvd_enhance2.bits.saturation_gain =
tvd_get_saturation(sel);
tvd_device[sel]->tvd_enhance2.bits.chroma_enhance_en = 1;
tvd_device[sel]->tvd_enhance2.bits.chroma_enhance_strength = 3;
tvd_device[sel]->tvd_enhance3.bits.cb_gain = 2055;
tvd_device[sel]->tvd_enhance3.bits.cr_gain = 1457;
if (interface == 0) {
tvd_device[sel]->tvd_enhance3.bits.cb_gain = 0x811;
tvd_device[sel]->tvd_enhance3.bits.cr_gain = 0x5b8;
tvd_device[sel]->tvd_enhance3.bits.cbcr_gain_en =
system ? 0 : 1;
} else {
tvd_device[sel]->tvd_enhance3.bits.cb_gain = 1460;
tvd_device[sel]->tvd_enhance3.bits.cr_gain = 1460;
tvd_device[sel]->tvd_enhance3.bits.cbcr_gain_en = 1;
}
tvd_device[sel]->tvd_debug1.bits.afe_gain_value = 64;
tvd_device[sel]->tvd_debug1.bits.tvin_lock_debug = 0;
tvd_device[sel]->tvd_debug1.bits.tvin_lock_high = 0;
tvd_device[sel]->tvd_debug1.bits.truncation2_reset_gain_enable = 0;
tvd_device[sel]->tvd_debug1.bits.truncation_reset_gain_enable = 0;
tvd_device[sel]->tvd_debug1.bits.unlock_reset_gain_enable = 1;
tvd_device[sel]->tvd_debug1.bits.afe_gain_mode = 0;
tvd_device[sel]->tvd_debug1.bits.clamp_mode = 0;
tvd_device[sel]->tvd_debug1.bits.clamp_up_start = 0;
tvd_device[sel]->tvd_debug1.bits.clamp_dn_start = 0;
tvd_device[sel]->tvd_debug1.bits.clamp_updn_cycles = 0;
tvd_device[sel]->tvd_debug2.bits.agc_gate_thresh = 10;
tvd_device[sel]->tvd_debug2.bits.ccir656_en = 0;
tvd_device[sel]->tvd_debug2.bits.adc_cbcr_pump_swap = 0;
tvd_device[sel]->tvd_debug2.bits.adc_updn_swap = 1;
tvd_device[sel]->tvd_debug2.bits.adc_input_swap = 0;
tvd_device[sel]->tvd_debug2.bits.hv_dely = 0;
tvd_device[sel]->tvd_debug2.bits.cv_inv = 0;
tvd_device[sel]->tvd_debug2.bits.tvd_src = 0;
tvd_device[sel]->tvd_debug2.bits.adc_wb_mode = 0;
tvd_device[sel]->tvd_debug2.bits.hue = 0;
tvd_device[sel]->tvd_debug3.bits.noise_thresh = 50;
tvd_device[sel]->tvd_debug3.bits.ccir656_cbcr_write_back_sequence = 0;
tvd_device[sel]->tvd_debug3.bits.cbcr_swap = 0;
tvd_device[sel]->tvd_debug3.bits.nstd_hysis = 0;
tvd_device[sel]->tvd_debug4.bits.fixed_burstgate = 1;
tvd_device[sel]->tvd_debug4.bits.cautopos = 12;
tvd_device[sel]->tvd_debug4.bits.vnon_std_threshold = 0;
tvd_device[sel]->tvd_debug4.bits.hnon_std_threshold = 6;
tvd_device[sel]->tvd_debug4.bits.user_ckill_mode = 0;
tvd_device[sel]->tvd_debug4.bits.hlock_ckill = 0;
tvd_device[sel]->tvd_debug4.bits.vbi_ckill = 0;
tvd_device[sel]->tvd_debug4.bits.chroma_kill = 7;
tvd_device[sel]->tvd_debug4.bits.agc_gate_vsync_stip = 0;
tvd_device[sel]->tvd_debug4.bits.agc_gate_vsync_coarse = 1;
tvd_device[sel]->tvd_debug4.bits.agc_gate_kill_mode = 0;
tvd_device[sel]->tvd_debug4.bits.agc_peak_en = system ? 1 : 0;
tvd_device[sel]->tvd_debug4.bits.hstate_unlocked = 1;
tvd_device[sel]->tvd_debug4.bits.disable_hfine = 0;
tvd_device[sel]->tvd_debug4.bits.hstate_fixed = 0;
tvd_device[sel]->tvd_debug4.bits.hlock_vsync_mode = 3;
tvd_device[sel]->tvd_debug5.bits.vsync_clamp_mode = 0;
tvd_device[sel]->tvd_debug5.bits.vsync_vbi_lockout_start = 112;
tvd_device[sel]->tvd_debug5.bits.vsync_vbi_max = 14;
tvd_device[sel]->tvd_debug5.bits.vlock_wide_range = 0;
tvd_device[sel]->tvd_debug5.bits.locked_count_clean_max = 4;
tvd_device[sel]->tvd_debug5.bits.locked_count_noisy_max = 7;
tvd_device[sel]->tvd_debug5.bits.hstate_max = (system == 0) ? 3 : 5;
tvd_device[sel]->tvd_debug5.bits.fixed_cstate = 0;
tvd_device[sel]->tvd_debug5.bits.vodd_delayed = 0;
tvd_device[sel]->tvd_debug5.bits.veven_delayed = 0;
tvd_device[sel]->tvd_debug5.bits.field_polarity = 0;
tvd_device[sel]->tvd_debug6.bits.cstate = 5;
tvd_device[sel]->tvd_debug6.bits.lose_chromalock_level = 7;
tvd_device[sel]->tvd_debug6.bits.lose_chromalock_count = 6;
tvd_device[sel]->tvd_debug6.bits.palsw_level = 2;
tvd_device[sel]->tvd_debug6.bits.vsync_thresh = 44;
tvd_device[sel]->tvd_debug6.bits.vsync_cntl = 2;
tvd_device[sel]->tvd_debug6.bits.vloop_tc = 2;
tvd_device[sel]->tvd_debug6.bits.field_detect_mode = 2;
tvd_device[sel]->tvd_debug6.bits.cpump_delay = 185;
tvd_device[sel]->tvd_debug7.bits.hresampler_2up = 1;
tvd_device[sel]->tvd_debug7.bits.cpump_adjust_polarity = 0;
tvd_device[sel]->tvd_debug7.bits.cpump_adjust_delay = 10;
tvd_device[sel]->tvd_debug7.bits.cpump_adjust = 200;
tvd_device[sel]->tvd_debug7.bits.cpump_delay_en = 0;
tvd_device[sel]->tvd_debug7.bits.vf_nstd_en = 1;
tvd_device[sel]->tvd_debug7.bits.vcr_auto_switch_en = 1;
tvd_device[sel]->tvd_debug7.bits.mv_hagc = 1;
tvd_device[sel]->tvd_debug7.bits.dagc_en = 1;
tvd_device[sel]->tvd_debug7.bits.agc_half_en = 0;
tvd_device[sel]->tvd_debug7.bits.dc_clamp_mode = 1;
tvd_device[sel]->tvd_debug7.bits.ldpause_threshold = 0;
tvd_device[sel]->tvd_debug8.bits.chroma_step_ntsc = 0x21f07c1f;
tvd_device[sel]->tvd_debug9.bits.chroma_step_paln = 0x21f69446;
tvd_device[sel]->tvd_debug10.bits.chroma_step_palm = 0x21e6efe3;
tvd_device[sel]->tvd_debug11.bits.chroma_step_pal = 0x2a098acb;
tvd_device[sel]->tvd_debug12.bits.y_wb_protect = 0xffffffff;
tvd_device[sel]->tvd_debug13.bits.uv_wb_protect = 0xffffffff;
tvd_device[sel]->tvd_debug14.bits.agc_peak_nominal = system ? 12 : 10;
tvd_device[sel]->tvd_debug14.bits.agc_peak_cntl = 1;
tvd_device[sel]->tvd_debug14.bits.vsync_agc_lockout_start = 108;
tvd_device[sel]->tvd_debug14.bits.vsync_agc_max = 16;
tvd_device[sel]->tvd_debug14.bits.noise_line = 0;
tvd_device[sel]->tvd_en.bits.tvd_en_ch = 1;
/*tvd_device[sel]->tvd_debug15.bits.adc_lock_interval_period=0x40;*/
/*tvd_device[sel]->tvd_debug15.bits.adc_lock_interval_low=30;*/
/*tvd_device[sel]->tvd_debug15.bits.adc_lock_mode=1;*/
return 0;
}
s32 tvd_set_wb_width(u32 sel, u32 width)
{
tvd_device[sel]->tvd_wb2.bits.hactive_num = width;
return 0;
}
s32 tvd_set_wb_width_jump(u32 sel, u32 width_jump)
{
tvd_device[sel]->tvd_wb1.bits.hactive_stride = width_jump;
return 0;
}
s32 tvd_set_wb_height(u32 sel, u32 height)
{
tvd_device[sel]->tvd_wb2.bits.vactive_num = height;
return 0;
}
/**
* @name tvd_set_wb_addr
* @brief set dma y and c(uv) channel addre
* @param[IN]
* @param[OUT]
* @return
*/
s32 tvd_set_wb_addr(u32 sel, u32 addr_y, u32 addr_c)
{
//make sure 1 frame change 1 buffer,no need to detect this bit
//while(tvd_device[sel]->tvd_wb1.bits.wb_addr_valid);
tvd_device[sel]->tvd_wb3.bits.ch1_y_addr = addr_y;
tvd_device[sel]->tvd_wb4.bits.ch1_c_addr = addr_c;
tvd_device[sel]->tvd_wb1.bits.wb_addr_valid = 1;
return 0;
}
s32 tvd_set_wb_fmt(u32 sel, TVD_FMT_T fmt)
{
tvd_device[sel]->tvd_wb1.bits.wb_mb_mode =
(fmt == TVD_MB_YUV420) ? 1 : 0;
tvd_device[sel]->tvd_wb1.bits.wb_format =
(fmt == TVD_PL_YUV422) ? 1 : 0;
tvd_device[sel]->tvd_wb1.bits.yuv420_fil_en =
(fmt == TVD_PL_YUV422) ? 0 : 1;
return 0;
}
s32 tvd_set_wb_uv_swap(u32 sel, u32 swap)
{
tvd_device[sel]->tvd_wb1.bits.wb_uv_swap = swap ? 1 : 0;
return 0;
}
s32 tvd_set_wb_field(u32 sel, u32 is_field_mode, u32 is_field_even)
{
tvd_device[sel]->tvd_wb1.bits.wb_frame_mode = is_field_mode ? 0 : 1 ;
tvd_device[sel]->tvd_wb1.bits.hyscale_en = is_field_mode ? 1 : 0 ;
return 0;
}
s32 tvd_capture_on(u32 sel)
{
tvd_device[sel]->tvd_wb1.bits.wb_en = 1;
return 0;
}
s32 tvd_capture_off(u32 sel)
{
tvd_device[sel]->tvd_wb1.bits.wb_en = 0;
return 0;
}
s32 tvd_irq_enable(u32 sel, TVD_IRQ_T irq_id)
{
tvd_device[sel]->tvd_irq_ctl.dwval |= (1<<irq_id);
return 0;
}
s32 tvd_irq_disable(u32 sel, TVD_IRQ_T irq_id)
{
tvd_device[sel]->tvd_irq_ctl.dwval &= ~(1<<irq_id);
return 0;
}
s32 tvd_irq_status_get(u32 sel, TVD_IRQ_T irq_id, u32 *irq_status)
{
*irq_status = (tvd_device[sel]->tvd_irq_status.dwval >> irq_id) & 0x1;
return 0;
}
s32 tvd_irq_status_clear(u32 sel, TVD_IRQ_T irq_id)
{
tvd_device[sel]->tvd_irq_status.dwval = (1<<irq_id);
return 0;
}
s32 tvd_dma_irq_status_get(u32 sel, u32 *irq_status)
{
*irq_status = tvd_device[sel]->tvd_irq_status.dwval;
return 0;
}
s32 tvd_dma_irq_status_clear_err_flag(u32 sel, u32 irq_status)
{
tvd_device[sel]->tvd_irq_status.dwval = irq_status;
return 0;
}
s32 tvd_set_saturation(u32 sel, u32 saturation)
{
tvd_device[sel]->tvd_enhance2.bits.saturation_gain = saturation;
return 0;
}
s32 tvd_set_luma(u32 sel, u32 luma)
{
tvd_device[sel]->tvd_enhance1.bits.bright_offset = luma;
return 0;
}
s32 tvd_set_contrast(u32 sel, u32 contrast)
{
tvd_device[sel]->tvd_enhance1.bits.contrast_gain = contrast;
return 0;
}
u32 tvd_get_saturation(u32 sel)
{
return tvd_device[sel]->tvd_enhance2.bits.saturation_gain;
}
u32 tvd_get_luma(u32 sel)
{
return tvd_device[sel]->tvd_enhance1.bits.bright_offset;
}
u32 tvd_get_contrast(u32 sel)
{
return tvd_device[sel]->tvd_enhance1.bits.contrast_gain;
}
/**
* @name tvd_adc_config
* @brief config tvd adc and enable it
* @param[IN] adc: the index of tvd module
* @param[IN] en: 1: enable; 0: disable
* @return 0 if success
*/
s32 tvd_adc_config(u32 adc, u32 en)
{
volatile tvd_adc_cfg_reg_t *adc_cfg_p;
volatile tvd_adc_ctl_reg_t *adc_ctl_p;
volatile tvd_adc_dig_reg_t *adc_dig_p;
if (adc > 3 || en > 1)
return -1;
adc_cfg_p = (adc == 0) ? &tvd_top_dev->tvd_adc0_cfg :
(adc == 1) ? &tvd_top_dev->tvd_adc1_cfg :
(adc == 2) ? &tvd_top_dev->tvd_adc2_cfg :
&tvd_top_dev->tvd_adc3_cfg;
adc_ctl_p = (adc == 0) ? &tvd_top_dev->tvd_adc0_ctl :
(adc == 1) ? &tvd_top_dev->tvd_adc1_ctl :
(adc == 2) ? &tvd_top_dev->tvd_adc2_ctl :
&tvd_top_dev->tvd_adc3_ctl;
adc_dig_p = (adc == 0) ? &tvd_top_dev->tvd_adc0_dig :
(adc == 1) ? &tvd_top_dev->tvd_adc1_dig :
(adc == 2) ? &tvd_top_dev->tvd_adc2_dig :
&tvd_top_dev->tvd_adc3_dig;
adc_cfg_p->bits.stage1_ibias = 2;
adc_cfg_p->bits.stage2_ibias = 2;
adc_cfg_p->bits.stage3_ibias = 2;
adc_cfg_p->bits.stage4_ibias = 2;
adc_cfg_p->bits.stage5_ibias = 2;
adc_cfg_p->bits.stage6_ibias = 2;
adc_cfg_p->bits.stage7_ibias = 2;
adc_cfg_p->bits.stage8_ibias = 2;
adc_cfg_p->bits.clp_step = 7;
adc_cfg_p->bits.data_dly = 1;
adc_dig_p->bits.lpf_dig_sel = 0;
adc_dig_p->bits.lpf_dig_en = en;
adc_ctl_p->bits.afe_en = en;
adc_ctl_p->bits.adc_en = en;
return 0;
}
/**
* tvd_dbgmode_dump_data
* Enable tvd debug mode, and dump a specified size section of memory,
* and then work back on normal state.
* @chan_sel : the index of tvd
* @mode : ADC dump mode, 0: dump inmediately,
* 1: dump start from the next vsync
* @dump_dst_addr: the address of the section memory
* @data_length : the length of memory,unit half word, must be divisible by 4.
*
* Return: 0
* author : liangyd
* date : 2016-02-03
* time:
* version :
* history :
*/
u32 tvd_dbgmode_dump_data(u32 chan_sel, u32 mode, uintptr_t dump_dst_addr,
u32 data_length)
{
u32 i = 0;
/* tvd configuration backup */
__tvd_dev_t *tvd_dev_bak = kmalloc(sizeof(__tvd_dev_t),
GFP_KERNEL | __GFP_ZERO);
__tvd_top_dev_t *tvd_top_bak = kmalloc(sizeof(__tvd_top_dev_t),
GFP_KERNEL | __GFP_ZERO);
if (!tvd_dev_bak || !tvd_top_bak) {
pr_warn("%s(), malloc memroy fail\n", __func__);
kfree(tvd_top_bak);
kfree(tvd_dev_bak);
return -1;
}
tvd_dev_bak->tvd_debug7.bits.agc_half_en =
tvd_device[chan_sel]->tvd_debug7.bits.agc_half_en;
tvd_dev_bak->tvd_debug4.bits.agc_peak_en =
tvd_device[chan_sel]->tvd_debug4.bits.agc_peak_en;
tvd_dev_bak->tvd_debug7.bits.dagc_en =
tvd_device[chan_sel]->tvd_debug7.bits.dagc_en;
tvd_dev_bak->tvd_clamp_agc1.bits.agc_en =
tvd_device[chan_sel]->tvd_clamp_agc1.bits.agc_en;
tvd_dev_bak->tvd_debug1.bits.afe_gain_value =
tvd_device[chan_sel]->tvd_debug1.bits.afe_gain_value;
tvd_dev_bak->tvd_debug1.bits.afe_gain_mode =
tvd_device[chan_sel]->tvd_debug1.bits.afe_gain_mode;
tvd_dev_bak->tvd_debug1.bits.clamp_mode =
tvd_device[chan_sel]->tvd_debug1.bits.clamp_mode;
tvd_dev_bak->tvd_debug1.bits.tvin_lock_debug =
tvd_device[chan_sel]->tvd_debug1.bits.tvin_lock_debug;
tvd_dev_bak->tvd_debug1.bits.tvin_lock_high =
tvd_device[chan_sel]->tvd_debug1.bits.tvin_lock_high;
tvd_dev_bak->tvd_en.bits.tvd_en_ch =
tvd_device[chan_sel]->tvd_en.bits.tvd_en_ch;
tvd_top_bak->tvd_adc_dump.bits.adc_test_mode =
tvd_top_dev->tvd_adc_dump.bits.adc_test_mode;
tvd_top_bak->tvd_3d_ctl1.bits.tvd_en_3d_dma =
tvd_top_dev->tvd_3d_ctl1.bits.tvd_en_3d_dma;
tvd_top_bak->tvd_3d_ctl1.bits.comb_3d_en =
tvd_top_dev->tvd_3d_ctl1.bits.comb_3d_en;
tvd_top_bak->tvd_3d_ctl4.bits.comb_3d_addr1 =
tvd_top_dev->tvd_3d_ctl4.bits.comb_3d_addr1;
tvd_top_bak->tvd_3d_ctl5.bits.comb_3d_size =
tvd_top_dev->tvd_3d_ctl5.bits.comb_3d_size;
tvd_top_bak->tvd_3d_ctl2.bits.dram_trig =
tvd_top_dev->tvd_3d_ctl2.bits.dram_trig;
tvd_top_bak->tvd_3d_ctl1.bits.comb_3d_sel =
tvd_top_dev->tvd_3d_ctl1.bits.comb_3d_sel;
tvd_top_bak->tvd_3d_ctl1.bits.comb_3d_sel =
tvd_device[chan_sel]->tvd_en.bits.tvd_en_ch;
tvd_top_bak->tvd_adc_dump.bits.adc_dump_mode =
tvd_top_dev->tvd_adc_dump.bits.adc_dump_mode;
tvd_top_bak->tvd_adc_dump.bits.adc_wb_length =
tvd_top_dev->tvd_adc_dump.bits.adc_wb_length;
/* tvd device agc configuration */
tvd_device[chan_sel]->tvd_debug7.bits.agc_half_en = 0;
tvd_device[chan_sel]->tvd_debug4.bits.agc_peak_en = 0;
tvd_device[chan_sel]->tvd_debug7.bits.dagc_en = 0;
tvd_device[chan_sel]->tvd_clamp_agc1.bits.agc_en = 0;
tvd_device[chan_sel]->tvd_debug1.bits.afe_gain_value = 64;
tvd_device[chan_sel]->tvd_debug1.bits.afe_gain_mode = 1;
/* tvd clamp mode configuration */
tvd_device[chan_sel]->tvd_debug1.bits.clamp_mode = 1;
/* tvd lock configuration */
tvd_device[chan_sel]->tvd_debug1.bits.tvin_lock_debug = 1;
tvd_device[chan_sel]->tvd_debug1.bits.tvin_lock_high = 0;
/* delay for lock finish */
msleep(50);
while (tvd_top_dev->tvd_adc_dump.bits.adc_wb_start)
;
tvd_top_dev->tvd_adc_dump.bits.adc_test_mode = 1;
tvd_top_dev->tvd_3d_ctl1.bits.tvd_en_3d_dma = 0;
tvd_top_dev->tvd_3d_ctl1.bits.comb_3d_en = 0;
tvd_top_dev->tvd_3d_ctl4.bits.comb_3d_addr1 = dump_dst_addr;
tvd_top_dev->tvd_3d_ctl5.bits.comb_3d_size = 0x800000 * 2;
tvd_top_dev->tvd_3d_ctl2.bits.dram_trig = 0x1000;
tvd_top_dev->tvd_3d_ctl1.bits.comb_3d_sel = chan_sel;
tvd_top_dev->tvd_3d_ctl1.bits.tvd_en_3d_dma = 1;
tvd_top_dev->tvd_3d_ctl1.bits.comb_3d_en = 1;
tvd_device[chan_sel]->tvd_en.bits.tvd_en_ch = 1;
tvd_top_dev->tvd_adc_dump.bits.adc_dump_mode = mode;
tvd_top_dev->tvd_adc_dump.bits.adc_wb_length = data_length & (~0xff);
tvd_top_dev->tvd_adc_dump.bits.adc_wb_buffer_reset = 1;
/* delay for buffer reset */
for (i = 0; i < 20; i++)
;
tvd_top_dev->tvd_adc_dump.bits.adc_wb_buffer_reset = 0;
tvd_top_dev->tvd_adc_dump.bits.adc_wb_start = 1;
/* wait for dump finish */
while (tvd_top_dev->tvd_adc_dump.bits.adc_wb_start)
;
/* reset tvd configuration */
tvd_device[chan_sel]->tvd_debug7.bits.agc_half_en =
tvd_dev_bak->tvd_debug7.bits.agc_half_en;
tvd_device[chan_sel]->tvd_debug4.bits.agc_peak_en =
tvd_dev_bak->tvd_debug4.bits.agc_peak_en;
tvd_device[chan_sel]->tvd_debug7.bits.dagc_en =
tvd_dev_bak->tvd_debug7.bits.dagc_en;
tvd_device[chan_sel]->tvd_clamp_agc1.bits.agc_en =
tvd_dev_bak->tvd_clamp_agc1.bits.agc_en;
tvd_device[chan_sel]->tvd_debug1.bits.afe_gain_value =
tvd_dev_bak->tvd_debug1.bits.afe_gain_value;
tvd_device[chan_sel]->tvd_debug1.bits.afe_gain_mode =
tvd_dev_bak->tvd_debug1.bits.afe_gain_mode;
tvd_device[chan_sel]->tvd_debug1.bits.clamp_mode =
tvd_dev_bak->tvd_debug1.bits.clamp_mode;
tvd_device[chan_sel]->tvd_debug1.bits.tvin_lock_debug =
tvd_dev_bak->tvd_debug1.bits.tvin_lock_debug;
tvd_device[chan_sel]->tvd_debug1.bits.tvin_lock_high =
tvd_dev_bak->tvd_debug1.bits.tvin_lock_high;
tvd_device[chan_sel]->tvd_en.bits.tvd_en_ch =
tvd_dev_bak->tvd_en.bits.tvd_en_ch;
tvd_top_dev->tvd_adc_dump.bits.adc_test_mode =
tvd_top_bak->tvd_adc_dump.bits.adc_test_mode;
tvd_top_dev->tvd_3d_ctl4.bits.comb_3d_addr1 =
tvd_top_bak->tvd_3d_ctl4.bits.comb_3d_addr1;
tvd_top_dev->tvd_3d_ctl5.bits.comb_3d_size =
tvd_top_bak->tvd_3d_ctl5.bits.comb_3d_size;
tvd_top_dev->tvd_3d_ctl2.bits.dram_trig =
tvd_top_bak->tvd_3d_ctl2.bits.dram_trig;
tvd_top_dev->tvd_3d_ctl1.bits.comb_3d_sel =
tvd_top_bak->tvd_3d_ctl1.bits.comb_3d_sel;
tvd_top_dev->tvd_3d_ctl1.bits.comb_3d_sel =
tvd_dev_bak->tvd_en.bits.tvd_en_ch;
tvd_top_dev->tvd_adc_dump.bits.adc_dump_mode =
tvd_top_bak->tvd_adc_dump.bits.adc_dump_mode;
tvd_top_dev->tvd_adc_dump.bits.adc_wb_length =
tvd_top_bak->tvd_adc_dump.bits.adc_wb_length;
tvd_top_dev->tvd_3d_ctl1.bits.tvd_en_3d_dma =
tvd_top_bak->tvd_3d_ctl1.bits.tvd_en_3d_dma;
tvd_top_dev->tvd_3d_ctl1.bits.comb_3d_en =
tvd_top_bak->tvd_3d_ctl1.bits.comb_3d_en;
kfree(tvd_top_bak);
kfree(tvd_dev_bak);
return 0;
}
void tvd_agc_auto_config(u32 sel)
{
tvd_device[sel]->tvd_debug7.bits.agc_half_en = 1;
tvd_device[sel]->tvd_debug4.bits.agc_peak_en = 1;
tvd_device[sel]->tvd_debug7.bits.dagc_en = 1;
tvd_device[sel]->tvd_clamp_agc1.bits.agc_en = 1;
tvd_device[sel]->tvd_debug1.bits.afe_gain_mode = 0;
}
void tvd_agc_manual_config(u32 sel, u32 agc_manual_val)
{
tvd_device[sel]->tvd_debug7.bits.agc_half_en = 0;
tvd_device[sel]->tvd_debug4.bits.agc_peak_en = 0;
tvd_device[sel]->tvd_debug7.bits.dagc_en = 0;
tvd_device[sel]->tvd_clamp_agc1.bits.agc_en = 0;
tvd_device[sel]->tvd_debug1.bits.afe_gain_mode = 1;
tvd_device[sel]->tvd_debug1.bits.afe_gain_value = agc_manual_val;
}
void tvd_cagc_config(u32 sel, u32 enable)
{
tvd_device[sel]->tvd_clamp_agc1.bits.cagc_en = enable;
}