diff --git a/MAINTAINERS b/MAINTAINERS index 6b6c853f96ae..c6f81bb52064 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13650,9 +13650,12 @@ AMLOGIC VRTC DRIVER M: Yun Cai F: drivers/amlogic/vrtc/ -AMLOGIC DEINTERLACE, DNR, Field Detection, VOF DRIVERS -M: Kele Bai -F: drivers/amlogic/deinterlace/* +AMLOGIC DEINTERLACE, NR, CUE, Field Detection, VOF DRIVERS +M: Kele Bai +F: drivers/amlogic/deinterlace/* +F: drivers/amlogic/media/deinterlace/film_mode_fmw/* +F: include/linux/amlogic/media/amvecm/amvecm.h +F: arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts AMLOGIC TVIN M: Dezhi Kong diff --git a/drivers/amlogic/media/deinterlace/Makefile b/drivers/amlogic/media/deinterlace/Makefile index cd5be3ee736c..4ece1445c10c 100644 --- a/drivers/amlogic/media/deinterlace/Makefile +++ b/drivers/amlogic/media/deinterlace/Makefile @@ -1,19 +1,17 @@ -# -# Makefile for the Post Process Manager device -# +# # Makefile for the Post Process Manager device # ifeq ($(TARGET_BUILD_VARIANT),userdebug) ccflags-y := -D DEBUG_SUPPORT endif +CFLAGS_deinterlace.o := -I$(src) +obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += film_mode_fmw/ obj-$(CONFIG_AMLOGIC_MEDIA_DEINTERLACE) += di.o di-objs += deinterlace.o di-objs += deinterlace_hw.o di-objs += deinterlace_mtn.o di-objs += deinterlace_dbg.o -di-objs += nr.o -di-objs += vof_soft_top.o -di-objs += film_fw1.o -di-objs += flm_mod_xx.o +di-objs += nr_drv.o +di-objs += pulldown_drv.o +di-objs += detect3d.o di-objs += detect3d.o -di-objs += tffbff_check.o ccflags-y += -Idrivers/amlogic/media/common/rdma/ diff --git a/drivers/amlogic/media/deinterlace/deinterlace.c b/drivers/amlogic/media/deinterlace/deinterlace.c index 59d0f355eb2b..4bd54827e688 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.c +++ b/drivers/amlogic/media/deinterlace/deinterlace.c @@ -59,66 +59,52 @@ #ifdef CONFIG_AMLOGIC_MEDIA_RDMA #include #endif -#include "film_vof_soft.h" +#include #include "register.h" #include "deinterlace.h" -#include "deinterlace_mtn.h" #include "deinterlace_dbg.h" -#include -#if defined(NEW_DI_TV) -#define ENABLE_SPIN_LOCK_ALWAYS -#endif +#define CREATE_TRACE_POINTS +#include "deinterlace_trace.h" #ifdef DET3D #include "detect3d.h" #endif -#ifdef NEW_DI_V4 -#include "nr.h" -#endif +#define ENABLE_SPIN_LOCK_ALWAYS -#define RUN_DI_PROCESS_IN_IRQ +#define DEVICE_NAME "deinterlace" +#define CLASS_NAME "deinterlace" +#define VFM_NAME "deinterlace" -#ifdef ENABLE_SPIN_LOCK_ALWAYS static DEFINE_SPINLOCK(di_lock2); -#define di_lock_irqfiq_save(irq_flag, fiq_flag) \ - do { fiq_flag = 0; flags = flags; \ - spin_lock_irqsave(&di_lock2, irq_flag); \ - } while (0) -#define di_unlock_irqfiq_restore(irq_flag, fiq_flag) - spin_unlock_irqrestore(&di_lock2, irq_flag); +#define di_lock_irqfiq_save(irq_flag) \ + spin_lock_irqsave(&di_lock2, irq_flag) -#else -#define di_lock_irqfiq_save(irq_flag, fiq_flag) \ - do { flags = irq_flag; \ - irq_flag = fiq_flag; \ - } while (0) -#define di_unlock_irqfiq_restore(irq_flag, fiq_flag) \ - do { flags = irq_flag; \ - irq_flag = fiq_flag; \ - } while (0) +#define di_unlock_irqfiq_restore(irq_flag) \ + spin_unlock_irqrestore(&di_lock2, irq_flag) + +#ifdef SUPPORT_MPEG_TO_VDIN +static int mpeg2vdin_flag; +static int mpeg2vdin_en; #endif -int mpeg2vdin_flag; -int mpeg2vdin_en; - static int queue_print_flag = -1; +static int di_reg_unreg_cnt = 100; static bool overturn; static bool check_start_drop_prog; -bool mcpre_en = true; +static bool mcpre_en = true; + +static bool mc_mem_alloc; -#ifdef NEW_DI_V4 -static bool dnr_en = 1; -#endif static unsigned int di_pre_rdma_enable; + + +static unsigned int di_force_bit_mode = 10; +module_param(di_force_bit_mode, uint, 0664); +MODULE_PARM_DESC(di_force_bit_mode, "force DI bit mode to 8 or 10 bit"); + static bool full_422_pack; -static bool tff_bff_enable; - -#define CHECK_VDIN_BUF_ERROR - -#define DEVICE_NAME "deinterlace" -#define CLASS_NAME "deinterlace" - -char *vf_get_receiver_name(const char *provider_name); +/* destroy unnecessary frames before display */ +static unsigned int hold_video; static DEFINE_SPINLOCK(plist_lock); @@ -126,12 +112,8 @@ static di_dev_t *de_devp; static dev_t di_devno; static struct class *di_clsp; -#define INIT_FLAG_NOT_LOAD 0x80 static const char version_s[] = "2016-09-29a"; -static unsigned char boot_init_flag; -static int receiver_is_amvideo = 1; -static unsigned char new_keep_last_frame_enable; static int bypass_state = 1; static int bypass_all; /*1:enable bypass pre,ei only; @@ -143,22 +125,10 @@ static int bypass_3d = 1; static int invert_top_bot; static int skip_top_bot;/*1or2: may affect atv when bypass di*/ -static int post_hold_line = 17;/* for m8 1080i/50 output */ -static int force_update_post_reg = 0x10; -/* - * bit[4] - * 1 call process_fun every vsync; - * 0 call process_fun when toggle frame (early_process_fun is called) - * bit[3:0] set force_update_post_reg = 1: only update post reg in - * vsync for one time - * set force_update_post_reg = 2: always update post reg in vsync - */ static int bypass_post; -bool post_wr_en; -unsigned int post_wr_surpport; +static bool post_wr_en; +static unsigned int post_wr_support; static int bypass_post_state; -static int vdin_source_flag; -static int update_post_reg_count = 1; static int timeout_miss_policy; /* 0, use di_wr_buf still; * 1, call pre_de_done_buf_clear to clear di_wr_buf; @@ -174,8 +144,8 @@ static int di_blocking; */ static int di_vscale_skip_enable; -/* 0: not surpport nr10bit, 1: surpport nr10bit */ -static unsigned int nr10bit_surpport; +/* 0: not support nr10bit, 1: support nr10bit */ +static unsigned int nr10bit_support; #ifdef RUN_DI_PROCESS_IN_IRQ /* @@ -190,47 +160,24 @@ static unsigned int nr10bit_surpport; * to set input2pre, VFRAME_EVENT_PROVIDER_VFRAME_READY of * vdin should be sent in irq */ -#ifdef NEW_DI_V1 -#undef CHECK_DI_DONE -#else -#define CHECK_DI_DONE -#endif -#ifdef NEW_DI_TV -static int input2pre = 1; +static int input2pre; /*false:process progress by field; * true: process progress by frame with 2 interlace buffer */ -#else -static int input2pre; -#endif -static int use_2_interlace_buff; static int input2pre_buf_miss_count; static int input2pre_proc_miss_count; static int input2pre_throw_count; -static int static_pic_threshold = 10; -#ifdef NEW_DI_V1 -static int input2pre_miss_policy; -/* 0, do not force pre_de_busy to 0, use di_wr_buf after de_irq happen; - * 1, force pre_de_busy to 0 and call pre_de_done_buf_clear to clear di_wr_buf - */ -#else static int input2pre_miss_policy; /* 0, do not force pre_de_busy to 0, use di_wr_buf after de_irq happen; * 1, force pre_de_busy to 0 and call pre_de_done_buf_clear to clear di_wr_buf */ #endif -#else -#ifdef NEW_DI_TV -static int use_2_interlace_buff = 1; /*false:process progress by field; * bit0: process progress by frame with 2 interlace buffer * bit1: temp add debug for 3d process FA,1:bit0 force to 1; */ -#else static int use_2_interlace_buff; -#endif -#endif /* prog_proc_config, * bit[2:1]: when two field buffers are used, * 0 use vpp for blending , @@ -259,30 +206,27 @@ static int prog_proc_config = (1 << 5) | (1 << 1) | 1; (((prog_proc_config & 0x30) == 0x20) && \ ((vframe->type & VIDTYPE_VIU_422) == 0)) -static int skip_wrong_field = 1; static int frame_count; -static int provider_vframe_level; static int disp_frame_count; static int start_frame_drop_count = 2; /* static int start_frame_hold_count = 0; */ -static int force_trig_cnt; -static int di_process_cnt; static int video_peek_cnt; -static int force_bob_flag; -int di_vscale_skip_count; -int di_vscale_skip_count_real; +static unsigned long reg_unreg_timeout_cnt; +static int di_vscale_skip_count; +static int di_vscale_skip_count_real; static int vpp_3d_mode; #ifdef DET3D -bool det3d_en; +static bool det3d_en; static unsigned int det3d_mode; static void set3d_view(enum tvin_trans_fmt trans_fmt, struct vframe_s *vf); #endif +int get_current_vscale_skip_count(struct vframe_s *vf); -static int force_duration_0; +static void di_pq_parm_destroy(struct di_pq_parm_s *pq_ptr); +static struct di_pq_parm_s *di_pq_parm_create(struct am_pq_parm_s *); static uint init_flag;/*flag for di buferr*/ -static uint mem_flag;/*flag for mem alloc*/ static unsigned int reg_flag;/*flag for vframe reg/unreg*/ static unsigned int unreg_cnt;/*cnt for vframe unreg*/ static unsigned int reg_cnt;/*cnt for vframe reg*/ @@ -294,18 +238,15 @@ static unsigned int recovery_log_reason; static unsigned int recovery_log_queue_idx; static struct di_buf_s *recovery_log_di_buf; -#define VFM_NAME "deinterlace" static long same_field_top_count; static long same_field_bot_count; -static long same_w_r_canvas_count; /* bit 0: * 0, keep 3 buffers in pre_ready_list for checking; * 1, keep 4 buffers in pre_ready_list for checking; */ -static int same_field_source_flag_th = 60; - +static int post_hold_line = 17;/* for m8 1080i/50 output */ static int pre_hold_line = 10; static int pre_urgent = 1; static int post_urgent = 1; @@ -314,10 +255,6 @@ static int post_urgent = 1; static int pre_process_time; static int pre_process_time_force; /**/ -#define USED_LOCAL_BUF_MAX 3 -static int used_local_buf_index[USED_LOCAL_BUF_MAX]; -static int used_post_buf_index = -1; - static int di_receiver_event_fun(int type, void *data, void *arg); static void di_uninit_buf(void); static unsigned char is_bypass(vframe_t *vf_in); @@ -341,6 +278,9 @@ static void di_reg_process(void); static void di_reg_process_irq(void); static void di_unreg_process(void); static void di_unreg_process_irq(void); +static struct queue_s *get_queue_by_idx(int idx); +static void dump_state(void); +static void recycle_keep_buffer(void); static const struct vframe_operations_s deinterlace_vf_provider = { @@ -355,7 +295,7 @@ static struct vframe_provider_s di_vf_prov; static int di_sema_init_flag; static struct semaphore di_sema; - +static struct tasklet_struct di_pre_tasklet; void trigger_pre_di_process(unsigned char idx) { if (di_sema_init_flag == 0) @@ -365,34 +305,22 @@ void trigger_pre_di_process(unsigned char idx) log_buffer_state((idx == 'i') ? "irq" : ((idx == 'p') ? "put" : ((idx == 'r') ? "rdy" : "oth"))); -#if (defined RUN_DI_PROCESS_IN_IRQ) - aml_write_cbus(ISA_TIMERC, 1); + /* tasklet_hi_schedule(&di_pre_tasklet); */ + tasklet_schedule(&di_pre_tasklet); + de_devp->jiffy = jiffies_64; /* trigger di_reg_process and di_unreg_process */ if ((idx != 'p') && (idx != 'i')) up(&di_sema); -#endif } -#define DI_PRE_INTERVAL (HZ / 100) - -static struct timer_list di_pre_timer; -static struct work_struct di_pre_work; static unsigned int di_printk_flag; - -static void di_pre_timer_cb(unsigned long arg) -{ - struct timer_list *timer = (struct timer_list *)arg; - - schedule_work(&di_pre_work); - - timer->expires = jiffies + DI_PRE_INTERVAL; - add_timer(timer); -} +#define DI_PRE_INTERVAL (HZ / 100) /************For Write register**********************/ static unsigned int di_stop_reg_flag; static unsigned int num_di_stop_reg_addr = 4; static unsigned int di_stop_reg_addr[4] = {0}; +static unsigned int di_dbg_mask; unsigned int is_need_stop_reg(unsigned int addr) { @@ -444,6 +372,25 @@ void DI_VSYNC_WR_MPEG_REG_BITS(unsigned int addr, unsigned int val, VSYNC_WR_MPEG_REG_BITS(addr, val, start, len); } +unsigned int DI_POST_REG_RD(unsigned int addr) +{ + if (de_devp->flags & DI_SUSPEND_FLAG) { + pr_err("[DI] REG 0x%x access prohibited.\n", addr); + return 0; + } + return VSYNC_RD_MPEG_REG(addr); +} +EXPORT_SYMBOL(DI_POST_REG_RD); + +int DI_POST_WR_REG_BITS(u32 adr, u32 val, u32 start, u32 len) +{ + if (de_devp->flags & DI_SUSPEND_FLAG) { + pr_err("[DI] REG 0x%x access prohibited.\n", adr); + return -1; + } + return VSYNC_WR_MPEG_REG_BITS(adr, val, start, len); +} +EXPORT_SYMBOL(DI_POST_WR_REG_BITS); /**********************************/ /***************************** @@ -466,13 +413,7 @@ static ssize_t store_config(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); -static void dump_state(void); -static struct queue_s *get_queue_by_idx(int idx); -#define DI_RUN_FLAG_RUN 0 -#define DI_RUN_FLAG_PAUSE 1 -#define DI_RUN_FLAG_STEP 2 -#define DI_RUN_FLAG_STEP_DONE 3 static int run_flag = DI_RUN_FLAG_RUN; static int pre_run_flag = DI_RUN_FLAG_RUN; @@ -513,9 +454,6 @@ store_dbg(struct device *dev, init_flag = 1; else init_flag = 0; - } else if (strncmp(buf, "show_osd", 8) == 0) { - DI_Wr(VIU_OSD1_CTRL_STAT, - Rd(VIU_OSD1_CTRL_STAT) | (0xff << 12)); } else if (strncmp(buf, "run", 3) == 0) { /* timestamp_pcrscr_enable(1); */ run_flag = DI_RUN_FLAG_RUN; @@ -537,12 +475,11 @@ store_dbg(struct device *dev, } else if (strncmp(buf, "recycle_buf", 11) == 0) { recycle_keep_buffer(); } else { - pr_info("DI no support cmd!!!\n"); + pr_info("DI no support cmd %s!!!\n", buf); } return count; } -#ifdef NEW_DI_V1 static int __init di_read_canvas_reverse(char *str) { unsigned char *ptr = str; @@ -559,14 +496,13 @@ static int __init di_read_canvas_reverse(char *str) return 0; } __setup("video_reverse=", di_read_canvas_reverse); -#endif -unsigned int di_debug_flag = 0x10;/* enable rdma even di bypassed */ +static unsigned int di_debug_flag;/* enable rdma even di bypassed */ static unsigned char *di_log_buf; static unsigned int di_log_wr_pos; static unsigned int di_log_rd_pos; static unsigned int di_log_buf_size; static unsigned int di_printk_flag; -unsigned int di_log_flag; +static unsigned int di_log_flag; static unsigned int buf_state_log_threshold = 16; static unsigned int buf_state_log_start; /* set to 1 by condition of "post_ready count < buf_state_log_threshold", @@ -605,9 +541,6 @@ int di_print_buf(char *buf, int len) } /* static int log_seq = 0; */ -#if 0 -#define di_print printk -#else int di_print(const char *fmt, ...) { va_list args; @@ -617,7 +550,7 @@ int di_print(const char *fmt, ...) if (di_printk_flag & 1) { if (di_log_flag & DI_LOG_PRECISE_TIMESTAMP) - pr_dbg("%u:", aml_read_cbus(ISA_TIMERE)); + pr_dbg("%llums:", sched_clock()/NSEC_PER_MSEC); va_start(args, fmt); vprintk(fmt, args); va_end(args); @@ -631,9 +564,6 @@ int di_print(const char *fmt, ...) if (di_log_flag & DI_LOG_TIMESTAMP) len += snprintf(buf + len, avail - len, "%u:", jiffies_to_msecs(jiffies_64)); - else if (di_log_flag & DI_LOG_PRECISE_TIMESTAMP) - len += snprintf(buf + len, avail - len, "%u:", - aml_read_cbus(ISA_TIMERE)); va_start(args, fmt); len += vsnprintf(buf + len, avail - len, fmt, args); @@ -646,7 +576,6 @@ int di_print(const char *fmt, ...) /* pr_dbg("di_print:%d %d\n", di_log_wr_pos, di_log_rd_pos); */ return pos; } -#endif static ssize_t read_log(char *buf) { @@ -718,31 +647,6 @@ store_log(struct device *dev, return 16; } -struct di_status_s { - char *name; - uint *status; -}; -#define di_status_t struct di_status_s -di_status_t di_status[] = { - { "active", &init_flag }, - { "", NULL } -}; - -static ssize_t -show_status(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int i = 0; - int len = 0; - - di_print("%s\n", __func__); - for (i = 0; di_status[i].status; i++) - len += sprintf(buf + len, "%s=%08x\n", di_status[i].name, - *(di_status[i].status)); - return len; -} - static ssize_t show_vframe_status(struct device *dev, struct device_attribute *attr, @@ -770,117 +674,6 @@ show_vframe_status(struct device *dev, return ret; } -struct pd_param_s { - char *name; - int *addr; -}; -struct FlmDectRes dectres; -struct sFlmSftPar pd_param; -static struct pd_param_s pd_params[] = { - { "sFrmDifAvgRat", - &(pd_param.sFrmDifAvgRat)}, - { "sFrmDifLgTDif", - &(pd_param.sFrmDifLgTDif) }, - { "sF32StpWgt01", - &(pd_param.sF32StpWgt01) }, - { "sF32StpWgt02", - &(pd_param.sF32StpWgt02) }, - { "sF32DifLgRat", - &(pd_param.sF32DifLgRat) }, - { "sFlm2MinAlpha", - &(pd_param.sFlm2MinAlpha) }, - { "sFlm2MinBelta", - &(pd_param.sFlm2MinBelta) }, - { "sFlm20ftAlpha", - &(pd_param.sFlm20ftAlpha) }, - { "sFlm2LgDifThd", - &(pd_param.sFlm2LgDifThd) }, - { "sFlm2LgFlgThd", - &(pd_param.sFlm2LgFlgThd) }, - { "sF32Dif01A1", - &(pd_param.sF32Dif01A1) }, - { "sF32Dif01T1", - &(pd_param.sF32Dif01T1) }, - { "sF32Dif01A2", - &(pd_param.sF32Dif01A2) }, - { "sF32Dif01T2", - &(pd_param.sF32Dif01T2) }, - { "rCmbRwMinCt0", - &(pd_param.rCmbRwMinCt0) }, - { "rCmbRwMinCt1", - &(pd_param.rCmbRwMinCt1) }, - { "mPstDlyPre", - &(pd_param.mPstDlyPre) }, - { "mNxtDlySft", - &(pd_param.mNxtDlySft) }, - { "sF32Dif02M0", - &(pd_param.sF32Dif02M0) }, /* mpeg-4096, cvbs-8192 */ - { "sF32Dif02M1", - &(pd_param.sF32Dif02M1) }, /* mpeg-4096, cvbs-8192 */ - { "", NULL } -}; - -static ssize_t pd_param_store(struct device *dev, - struct device_attribute *attr, const char *buff, - size_t count) -{ - int i = 0; - int value = 0; - int rc = 0; - char *parm[2] = { NULL }, *buf_orig; - - buf_orig = kstrdup(buff, GFP_KERNEL); - parse_cmd_params(buf_orig, (char **)(&parm)); - for (i = 0; pd_params[i].addr; i++) { - if (!strcmp(parm[0], pd_params[i].name)) { - rc = kstrtoint(parm[1], 10, &value); - *(pd_params[i].addr) = value; - pr_dbg("%s=%d.\n", pd_params[i].name, value); - } - } - - return count; -} - -static ssize_t pd_param_show(struct device *dev, - struct device_attribute *attr, char *buff) -{ - ssize_t len = 0; - int i = 0; - - for (i = 0; pd_params[i].addr; i++) - len += sprintf(buff + len, "%s=%d.\n", - pd_params[i].name, *pd_params[i].addr); - - len += sprintf(buff + len, "\npulldown detection result:\n"); - len += sprintf(buff + len, "rCmb32Spcl=%u.\n", dectres.rCmb32Spcl); - len += sprintf(buff + len, "rPstCYWnd0 s=%u.\n", dectres.rPstCYWnd0[0]); - len += sprintf(buff + len, "rPstCYWnd0 e=%u.\n", dectres.rPstCYWnd0[1]); - len += sprintf(buff + len, "rPstCYWnd0 b=%u.\n", dectres.rPstCYWnd0[2]); - - len += sprintf(buff + len, "rPstCYWnd1 s=%u.\n", dectres.rPstCYWnd1[0]); - len += sprintf(buff + len, "rPstCYWnd1 e=%u.\n", dectres.rPstCYWnd1[1]); - len += sprintf(buff + len, "rPstCYWnd1 b=%u.\n", dectres.rPstCYWnd1[2]); - - len += sprintf(buff + len, "rPstCYWnd2 s=%u.\n", dectres.rPstCYWnd2[0]); - len += sprintf(buff + len, "rPstCYWnd2 e=%u.\n", dectres.rPstCYWnd2[1]); - len += sprintf(buff + len, "rPstCYWnd2 b=%u.\n", dectres.rPstCYWnd2[2]); - - len += sprintf(buff + len, "rPstCYWnd3 s=%u.\n", dectres.rPstCYWnd3[0]); - len += sprintf(buff + len, "rPstCYWnd3 e=%u.\n", dectres.rPstCYWnd3[1]); - len += sprintf(buff + len, "rPstCYWnd3 b=%u.\n", dectres.rPstCYWnd3[2]); - - len += sprintf(buff + len, "rPstCYWnd4 s=%u.\n", dectres.rPstCYWnd4[0]); - len += sprintf(buff + len, "rPstCYWnd4 e=%u.\n", dectres.rPstCYWnd4[1]); - len += sprintf(buff + len, "rPstCYWnd4 b=%u.\n", dectres.rPstCYWnd4[2]); - - len += sprintf(buff + len, "rFlmPstGCm=%u.\n", dectres.rFlmPstGCm); - len += sprintf(buff + len, "rFlmSltPre=%u.\n", dectres.rFlmSltPre); - len += sprintf(buff + len, "rFlmPstMod=%d.\n", dectres.rFlmPstMod); - len += sprintf(buff + len, "rF22Flag=%d.\n", dectres.rF22Flag); - return len; -} - static ssize_t show_tvp_region(struct device *dev, struct device_attribute *attr, char *buff) { @@ -894,7 +687,6 @@ static ssize_t show_tvp_region(struct device *dev, } -static DEVICE_ATTR(pd_param, 0664, pd_param_show, pd_param_store); static ssize_t store_dump_mem(struct device *dev, struct device_attribute *attr, const char *buf, size_t len); @@ -902,33 +694,18 @@ static DEVICE_ATTR(config, 0640, show_config, store_config); static DEVICE_ATTR(debug, 0200, NULL, store_dbg); static DEVICE_ATTR(dump_pic, 0200, NULL, store_dump_mem); static DEVICE_ATTR(log, 0640, show_log, store_log); -static DEVICE_ATTR(status, 0444, show_status, NULL); static DEVICE_ATTR(provider_vframe_status, 0444, show_vframe_status, NULL); static DEVICE_ATTR(tvp_region, 0444, show_tvp_region, NULL); /*************************** * di buffer management ***************************/ -#define MAX_IN_BUF_NUM 20 -#define MAX_LOCAL_BUF_NUM 12 -#define MAX_POST_BUF_NUM 16 - -#define VFRAME_TYPE_IN 1 -#define VFRAME_TYPE_LOCAL 2 -#define VFRAME_TYPE_POST 3 -#define VFRAME_TYPE_NUM 3 static char *vframe_type_name[] = { "", "di_buf_in", "di_buf_loc", "di_buf_post" }; -#if defined(CONFIG_AM_DEINTERLACE_SD_ONLY) -static unsigned int default_width = 720; -static unsigned int default_height = 576; -#else static unsigned int default_width = 1920; static unsigned int default_height = 1080; -#endif -static int local_buf_num; /* * progressive frame process type config: @@ -970,7 +747,7 @@ static struct di_buf_s di_buf_post[MAX_POST_BUF_NUM]; #define queue_t struct queue_s static queue_t queue[QUEUE_NUM]; - +static struct di_buf_pool_s di_buf_pool[VFRAME_TYPE_NUM]; static struct queue_s *get_queue_by_idx(int idx) { if (idx < QUEUE_NUM) @@ -979,10 +756,6 @@ static struct queue_s *get_queue_by_idx(int idx) return NULL; } -struct di_buf_pool_s { - struct di_buf_s *di_buf_ptr; - unsigned int size; -} di_buf_pool[VFRAME_TYPE_NUM]; #define queue_for_each_entry(di_buf, ptm, queue_idx, list) \ for (itmp = 0; ((di_buf = get_di_buf(queue_idx, &itmp)) != NULL); ) @@ -1383,7 +1156,6 @@ static struct di_pre_stru_s di_pre_stru; static struct di_post_stru_s di_post_stru; -#ifdef NEW_DI_V1 static ssize_t store_dump_mem(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) @@ -1438,7 +1210,7 @@ store_dump_mem(struct device *dev, struct device_attribute *attr, } dump_state_flag = 1; if (de_devp->flags && DI_MAP_FLAG) - buff = phys_to_virt(di_buf->nr_adr); + buff = (void *)phys_to_virt(di_buf->nr_adr); else buff = ioremap(di_buf->nr_adr, nr_size); if (buff == NULL) @@ -1471,7 +1243,6 @@ store_dump_mem(struct device *dev, struct device_attribute *attr, pr_info("write buffer %d to %s.\n", di_buf->seq, parm[1]); return len; } -#endif #define is_from_vdin(vframe) (vframe->type & VIDTYPE_VIU_422) static void recycle_vframe_type_pre(struct di_buf_s *di_buf); @@ -1485,16 +1256,16 @@ recycle_vframe_type_post_print(struct di_buf_s *di_buf, static void dis2_di(void) { - ulong flags = 0, fiq_flag = 0, irq_flag2 = 0; + ulong flags = 0, irq_flag2 = 0; init_flag = 0; - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); /* vf_unreg_provider(&di_vf_prov); */ vf_light_unreg_provider(&di_vf_prov); - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); reg_flag = 0; spin_lock_irqsave(&plist_lock, flags); - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); if (di_pre_stru.di_inp_buf) { if (vframe_in[di_pre_stru.di_inp_buf->index]) { vf_put( @@ -1504,28 +1275,28 @@ static void dis2_di(void) vf_notify_provider( VFM_NAME, VFRAME_EVENT_RECEIVER_PUT, NULL); } -/* list_add_tail( - * &(di_pre_stru.di_inp_buf->list), &in_free_list_head); - */ di_pre_stru.di_inp_buf->invert_top_bot_flag = 0; queue_in(di_pre_stru.di_inp_buf, QUEUE_IN_FREE); di_pre_stru.di_inp_buf = NULL; } di_uninit_buf(); - di_set_power_control(0, 0); if (get_blackout_policy()) { - di_set_power_control(1, 0); DI_Wr(DI_CLKG_CTRL, 0x2); + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) { + enable_di_post_mif(GATE_OFF); + di_post_gate_control(false); + di_top_gate_control(false, false); + } } - if (post_wr_en && post_wr_surpport) { + if (post_wr_en && post_wr_support) { diwr_set_power_control(0); #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA enable_rdma(1); #endif } - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); spin_unlock_irqrestore(&plist_lock, flags); } @@ -1534,13 +1305,18 @@ store_config(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + int rc = 0; + char *parm[2] = { NULL }, *buf_orig; + + buf_orig = kstrdup(buf, GFP_KERNEL); + parse_cmd_params(buf_orig, (char **)(&parm)); + if (strncmp(buf, "disable", 7) == 0) { di_print("%s: disable\n", __func__); - if (init_flag && mem_flag) { + if (init_flag) { di_pre_stru.disable_req_flag = 1; - provider_vframe_level = 0; trigger_pre_di_process(TRIGGER_PRE_BY_DEBUG_DISABLE); while (di_pre_stru.disable_req_flag) @@ -1548,7 +1324,11 @@ store_config(struct device *dev, } } else if (strncmp(buf, "dis2", 4) == 0) { dis2_di(); + } else if (strcmp(parm[0], "hold_video") == 0) { + pr_info("%s(%s %s)\n", __func__, parm[0], parm[1]); + rc = kstrtouint(parm[1], 10, &hold_video); } + kfree(buf_orig); return count; } @@ -1626,8 +1406,7 @@ static unsigned char is_bypass(vframe_t *vf_in) if (di_pre_stru.cur_source_type == VFRAME_SOURCE_TYPE_PPMGR) return 1; - if (((bypass_trick_mode) && - (new_keep_last_frame_enable == 0)) || (bypass_trick_mode & 0x2)) { + if (bypass_trick_mode) { int trick_mode_fffb = 0; int trick_mode_i = 0; @@ -1698,10 +1477,8 @@ static unsigned char is_bypass_post(void) static unsigned char is_input2pre(void) { if (input2pre -#ifdef NEW_DI_V3 && di_pre_stru.cur_prog_flag -#endif - && vdin_source_flag + && di_pre_stru.vdin_source && (bypass_state == 0)) return 1; @@ -1712,6 +1489,7 @@ static unsigned char is_input2pre(void) #ifdef DI_USE_FIXED_CANVAS_IDX static int di_post_idx[2][6]; static int di_pre_idx[2][10]; +static int di_wr_idx; #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC static unsigned int di_inp_idx[3]; #endif @@ -1729,47 +1507,35 @@ static int di_get_canvas(void) } if (canvas_pool_alloc_canvas_table("di_pre", &di_pre_idx[0][0], pre_num, CANVAS_MAP_TYPE_1)) { - pr_dbg("%s allocate di pre canvas error.\n", __func__); + pr_err("%s allocate di pre canvas error.\n", __func__); return 1; } if (di_pre_rdma_enable) { if (canvas_pool_alloc_canvas_table("di_pre", &di_pre_idx[1][0], pre_num, CANVAS_MAP_TYPE_1)) { - pr_dbg("%s allocate di pre canvas error.\n", __func__); + pr_err("%s allocate di pre canvas error.\n", __func__); return 1; } } else { - pr_info("DI: pre canvas:"); - for (i = 0; i < pre_num; i++) { + for (i = 0; i < pre_num; i++) di_pre_idx[1][i] = di_pre_idx[0][i]; - pr_info("\t[%d]\t[%d]\n", di_pre_idx[0][i], - di_pre_idx[1][i]); - } - pr_info("\n"); } if (canvas_pool_alloc_canvas_table("di_post", &di_post_idx[0][0], post_num, CANVAS_MAP_TYPE_1)) { - pr_dbg("%s allocate di post canvas error.\n", __func__); + pr_err("%s allocate di post canvas error.\n", __func__); return 1; } #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA if (canvas_pool_alloc_canvas_table("di_post", &di_post_idx[1][0], post_num, CANVAS_MAP_TYPE_1)) { - pr_dbg("%s allocate di post canvas error.\n", __func__); + pr_err("%s allocate di post canvas error.\n", __func__); return 1; } #else - for (i = 0; i < post_num; i++) { - di_post_idx[1][i] = di_post_idx[0][i]; - pr_info("\t[%d]\t[%d]\n", di_post_idx[0][i], di_post_idx[1][i]); - } -#endif - pr_info("DI: post canvas:"); for (i = 0; i < post_num; i++) - pr_info("\t [%d] [%d]", di_post_idx[0][i], di_post_idx[1][i]); - pr_info("\n"); - + di_post_idx[1][i] = di_post_idx[0][i]; +#endif #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC if (canvas_pool_alloc_canvas_table("di_inp", &di_inp_idx[0], 3, CANVAS_MAP_TYPE_1)) { @@ -1779,6 +1545,13 @@ static int di_get_canvas(void) pr_info("DI: support multi decoding %u~%u~%u.\n", di_inp_idx[0], di_inp_idx[1], di_inp_idx[2]); #endif + if (canvas_pool_alloc_canvas_table("di_wr", + &di_wr_idx, 1, CANVAS_MAP_TYPE_1)) { + pr_err("%s allocat di write back canvas error.\n", + __func__); + return 1; + } + pr_info("DI: support post write back %u.\n", di_wr_idx); return 0; } static void config_canvas_idx(struct di_buf_s *di_buf, int nr_canvas_idx, @@ -1819,7 +1592,6 @@ static void config_canvas_idx(struct di_buf_s *di_buf, int nr_canvas_idx, } } -#ifdef NEW_DI_V1 static void config_cnt_canvas_idx(struct di_buf_s *di_buf, unsigned int cnt_canvas_idx) { @@ -1833,7 +1605,6 @@ static void config_cnt_canvas_idx(struct di_buf_s *di_buf, di_buf->canvas_width[MTN_CANVAS], di_buf->canvas_height, 0, 0); } -#endif static void config_mcinfo_canvas_idx(struct di_buf_s *di_buf, int mcinfo_canvas_idx) @@ -1893,117 +1664,187 @@ static void config_canvas(struct di_buf_s *di_buf) #endif #ifdef CONFIG_CMA -void di_cma_alloc(void) +static unsigned int di_cma_alloc_total(struct di_dev_s *de_devp) { - unsigned int i, start_time, end_time, delta_time; - start_time = jiffies_to_msecs(jiffies); - for (i = 0; (i < local_buf_num); i++) { - struct di_buf_s *di_buf = &(di_buf_local[i]); - - int ii = USED_LOCAL_BUF_MAX; - - if ((used_post_buf_index != -1) && - (new_keep_last_frame_enable)) { - for (ii = 0; ii < USED_LOCAL_BUF_MAX; ii++) { - if (i == used_local_buf_index[ii]) { - pr_dbg("%s skip %d,cma_alloc=%d\n", - __func__, i, - de_devp->cma_alloc[i]); - break; - } - } - } - if ((ii >= USED_LOCAL_BUF_MAX) && - (de_devp->cma_alloc[i] == 0)) { - de_devp->pages[i] = - dma_alloc_from_contiguous(&(de_devp->pdev->dev), - de_devp->buffer_size >> PAGE_SHIFT, 0); - if (de_devp->pages[i]) { - de_devp->mem_start = - page_to_phys(de_devp->pages[i]); - de_devp->cma_alloc[i] = 1; - pr_dbg("DI CMA allocate addr:0x%x[%d] ok.\n", - (unsigned int)de_devp->mem_start, i); - } else { - pr_dbg("DI CMA allocate %d fail.\n", i); - } - if (di_pre_stru.buf_alloc_mode) { - di_buf->nr_adr = de_devp->mem_start; - } else { - di_buf->nr_adr = de_devp->mem_start; - di_buf->mtn_adr = de_devp->mem_start + - di_pre_stru.nr_size; -#ifdef NEW_DI_V1 - di_buf->cnt_adr = de_devp->mem_start + - di_pre_stru.nr_size + - di_pre_stru.mtn_size; -#endif - if (mcpre_en) { - di_buf->mcvec_adr = de_devp->mem_start + - di_pre_stru.nr_size + - di_pre_stru.mtn_size + - di_pre_stru.count_size; - di_buf->mcinfo_adr = - de_devp->mem_start + - di_pre_stru.nr_size + - di_pre_stru.mtn_size + - di_pre_stru.count_size + - di_pre_stru.mv_size; - } - } - } + de_devp->total_pages = + dma_alloc_from_contiguous(&(de_devp->pdev->dev), + de_devp->mem_size >> PAGE_SHIFT, 0); + if (de_devp->total_pages) { + de_devp->mem_start = + page_to_phys(de_devp->total_pages); + pr_dbg("%s:DI CMA allocate addr:0x%lx ok.\n", + __func__, de_devp->mem_start); + return 1; } - end_time = jiffies_to_msecs(jiffies); - delta_time = end_time - start_time; - pr_dbg("%s:alloc use %d ms(%d~%d)\n", __func__, delta_time, - start_time, end_time); + pr_err("%s:xxxxxx DI CMA allocate fail.\n", __func__); + return 0; + + } -void di_cma_release(void) + +static bool cma_print; +static unsigned int di_cma_alloc(struct di_dev_s *devp) { - unsigned int i, start_time, end_time, delta_time; + unsigned int start_time, end_time, delta_time; + struct di_buf_s *buf_p = NULL; + int itmp, alloc_cnt = 0; start_time = jiffies_to_msecs(jiffies); - for (i = 0; (i < local_buf_num); i++) { - int ii = USED_LOCAL_BUF_MAX; + queue_for_each_entry(buf_p, ptmp, QUEUE_LOCAL_FREE, list) { - if ((used_post_buf_index != -1) && - (new_keep_last_frame_enable)) { + if (buf_p->pages == NULL) { + buf_p->pages = + dma_alloc_from_contiguous(&(devp->pdev->dev), + devp->buffer_size >> PAGE_SHIFT, 0); + if (IS_ERR_OR_NULL(buf_p->pages)) { + buf_p->pages = NULL; + pr_err("xxxxxxxxx DI CMA allocate %d fail.\n", + buf_p->index); + return 0; + } else { + alloc_cnt++; + if (cma_print) + pr_info("DI CMA allocate buf[%d]page:0x%p\n", + buf_p->index, buf_p->pages); + } + } else { + pr_err("DI buf[%d] page:0x%p cma alloced skip\n", + buf_p->index, buf_p->pages); + } + buf_p->nr_adr = page_to_phys(buf_p->pages); + if (cma_print) + pr_info(" addr 0x%lx ok.\n", buf_p->nr_adr); + if (di_pre_stru.buf_alloc_mode == 0) { + buf_p->mtn_adr = buf_p->nr_adr + + di_pre_stru.nr_size; + buf_p->cnt_adr = buf_p->nr_adr + + di_pre_stru.nr_size + + di_pre_stru.mtn_size; + if (mc_mem_alloc) { + buf_p->mcvec_adr = buf_p->nr_adr + + di_pre_stru.nr_size + + di_pre_stru.mtn_size + + di_pre_stru.count_size; + buf_p->mcinfo_adr = + buf_p->nr_adr + + di_pre_stru.nr_size + + di_pre_stru.mtn_size + + di_pre_stru.count_size + + di_pre_stru.mv_size; + } + } + } + if (post_wr_en && post_wr_support) { + queue_for_each_entry(buf_p, ptmp, QUEUE_POST_FREE, list) { + if (buf_p->pages == NULL) { + buf_p->pages = + dma_alloc_from_contiguous( + &(devp->pdev->dev), + devp->post_buffer_size>>PAGE_SHIFT, + 0); + if (IS_ERR_OR_NULL(buf_p->pages)) { + buf_p->pages = NULL; + pr_err("xxxxxxxxx DI CMA allocate %d fail.\n", + buf_p->index); + return 0; + } + alloc_cnt++; + if (cma_print) + pr_info("DI CMA allocate buf[%d]page:0x%p\n", + buf_p->index, + buf_p->pages); + } else { + pr_err("DI buf[%d] page:0x%p cma alloced skip\n", + buf_p->index, buf_p->pages); + } + buf_p->nr_adr = page_to_phys(buf_p->pages); + if (cma_print) + pr_info(" addr 0x%lx ok.\n", buf_p->nr_adr); + } + } + end_time = jiffies_to_msecs(jiffies); + delta_time = end_time - start_time; + pr_info("%s:alloc %u buffer use %u ms(%u~%u)\n", + __func__, alloc_cnt, delta_time, start_time, end_time); + return 1; +} + +static void di_cma_release(struct di_dev_s *devp) +{ + unsigned int i, ii, rels_cnt = 0, start_time, end_time, delta_time; + struct di_buf_s *buf_p, *keep_buf; + + keep_buf = di_post_stru.keep_buf; + start_time = jiffies_to_msecs(jiffies); + for (i = 0; (i < devp->buf_num_avail); i++) { + buf_p = &(di_buf_local[i]); + ii = USED_LOCAL_BUF_MAX; + if (!IS_ERR_OR_NULL(keep_buf)) { for (ii = 0; ii < USED_LOCAL_BUF_MAX; ii++) { - if (i == used_local_buf_index[ii]) { - pr_dbg("%s skip %d,cma_alloc=%d\n", - __func__, i, - de_devp->cma_alloc[i]); + if (buf_p == keep_buf->di_buf_dup_p[ii]) { + pr_dbg("%s skip buf[%d].\n\n", + __func__, i); break; } } } if ((ii >= USED_LOCAL_BUF_MAX) && - (de_devp->cma_alloc[i] == 1)) { - if (dma_release_from_contiguous(&(de_devp->pdev->dev), - de_devp->pages[i], - de_devp->buffer_size >> PAGE_SHIFT)) { - de_devp->cma_alloc[i] = 0; - pr_dbg("DI CMA release %d ok.\n", i); + (buf_p->pages != NULL)) { + if (dma_release_from_contiguous(&(devp->pdev->dev), + buf_p->pages, + devp->buffer_size >> PAGE_SHIFT)) { + buf_p->pages = NULL; + rels_cnt++; + if (cma_print) + pr_info( + "DI CMA release buf[%d] ok.\n", i); } else { - pr_dbg("DI CMA release %d fail.\n", i); + pr_err("DI CMA release buf[%d] fail.\n", i); + } + } else { + pr_err("DI buf[%d] page:0x%p no release.\n", + buf_p->index, buf_p->pages); + } + } + if (post_wr_en && post_wr_support) { + for (i = 0; i < di_post_stru.di_post_num; i++) { + buf_p = &(di_buf_post[i]); + if (buf_p->pages != NULL) { + if (dma_release_from_contiguous( + &(devp->pdev->dev), + buf_p->pages, + devp->post_buffer_size>> + PAGE_SHIFT)) { + buf_p->pages = NULL; + rels_cnt++; + if (cma_print) + pr_info( + "DI CMA release post buf[%d] ok.\n", i); + } else { + pr_err("DI CMA release post buf[%d] fail.\n", + i); + } } } } end_time = jiffies_to_msecs(jiffies); delta_time = end_time - start_time; - pr_dbg("%s:release use %d ms(%d~%d)\n", __func__, delta_time, - start_time, end_time); + pr_info("%s:release %u buffer use %u ms(%u~%u)\n", + __func__, rels_cnt, delta_time, start_time, end_time); } #endif static int di_init_buf(int width, int height, unsigned char prog_flag) { int i; int canvas_height = height + 8; - + struct page *tmp_page = NULL; unsigned int di_buf_size = 0, di_post_buf_size = 0, mtn_size = 0; unsigned int nr_size = 0, count_size = 0, mv_size = 0, mc_size = 0; unsigned int nr_width = width, mtn_width = width, mv_width = width; + unsigned int nr_canvas_width = width, mtn_canvas_width = width; + unsigned int mv_canvas_width = width; unsigned long di_post_mem = 0; + struct di_buf_s *keep_buf = di_post_stru.keep_buf; frame_count = 0; disp_frame_count = 0; @@ -2017,37 +1858,34 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) } } memset(&di_pre_stru, 0, sizeof(di_pre_stru)); - if (nr10bit_surpport) { + if (nr10bit_support) { if (full_422_pack) - nr_width = (width * 5) / 4;/* 2400 roundup to 2432*/ + nr_width = (width * 5) / 4; else - nr_width = (width * 3) / 2;/* 2880 roundup to 2944*/ + nr_width = (width * 3) / 2; } else { nr_width = width; } - /* make sure canvas width must be divided by 256 */ - if ((nr_width<<1)%256) - nr_width = roundup(nr_width, (256>>1)); - - if ((mtn_width>>1)%256) - mtn_width = roundup(mtn_width, (256<<1)); /* roundup to 2048*/ - - if (((mv_width<<1)/5)%256) - mv_width = roundup(mv_width, ((256*5)>>1)); + /* make sure canvas width must be divided by 256bit|32byte align */ + nr_canvas_width = nr_width << 1; + mtn_canvas_width = mtn_width >> 1; + mv_canvas_width = (mv_width << 1) / 5; + nr_canvas_width = roundup(nr_canvas_width, 32); + mtn_canvas_width = roundup(mtn_canvas_width, 32); + mv_canvas_width = roundup(mv_canvas_width, 32); + nr_width = nr_canvas_width >> 1; + mtn_width = mtn_canvas_width << 1; + mv_width = (mv_canvas_width * 5) >> 1; if (prog_flag) { di_pre_stru.prog_proc_type = 1; di_pre_stru.buf_alloc_mode = 1; di_buf_size = nr_width * canvas_height * 2; di_buf_size = roundup(di_buf_size, PAGE_SIZE); - local_buf_num = de_devp->mem_size / di_buf_size; - if (local_buf_num > (2 * MAX_LOCAL_BUF_NUM)) - local_buf_num = 2 * MAX_LOCAL_BUF_NUM; + de_devp->buf_num_avail = de_devp->mem_size / di_buf_size; + if (de_devp->buf_num_avail > (2 * MAX_LOCAL_BUF_NUM)) + de_devp->buf_num_avail = 2 * MAX_LOCAL_BUF_NUM; - if (local_buf_num >= 6) - new_keep_last_frame_enable = 1; - else - new_keep_last_frame_enable = 0; } else { di_pre_stru.prog_proc_type = 0; di_pre_stru.buf_alloc_mode = 0; @@ -2061,32 +1899,24 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) count_size = (mtn_width * canvas_height)*4/16; mv_size = (mv_width * canvas_height)/5; mc_size = canvas_height; - if (mcpre_en) { + if (mc_mem_alloc) { di_buf_size = nr_size + mtn_size + count_size + mv_size + mc_size; } else { -#ifdef NEW_DI_V1 di_buf_size = nr_size + mtn_size + count_size; -#else - di_buf_size = nr_size + mtn_size; -#endif } di_buf_size = roundup(di_buf_size, PAGE_SIZE); - local_buf_num = de_devp->mem_size / di_buf_size; + de_devp->buf_num_avail = de_devp->mem_size / di_buf_size; - if (post_wr_en && post_wr_surpport) { - local_buf_num = (de_devp->mem_size + + if (post_wr_en && post_wr_support) { + de_devp->buf_num_avail = (de_devp->mem_size + (nr_width*canvas_height<<2)) / (di_buf_size + (nr_width*canvas_height<<1)); } - if (local_buf_num > MAX_LOCAL_BUF_NUM) - local_buf_num = MAX_LOCAL_BUF_NUM; + if (de_devp->buf_num_avail > MAX_LOCAL_BUF_NUM) + de_devp->buf_num_avail = MAX_LOCAL_BUF_NUM; - if (local_buf_num >= 8) - new_keep_last_frame_enable = 1; - else - new_keep_last_frame_enable = 0; } de_devp->buffer_size = di_buf_size; di_pre_stru.nr_size = nr_size; @@ -2094,19 +1924,16 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) di_pre_stru.mtn_size = mtn_size; di_pre_stru.mv_size = mv_size; di_pre_stru.mcinfo_size = mc_size; - same_w_r_canvas_count = 0; same_field_top_count = 0; same_field_bot_count = 0; - queue_init(local_buf_num); - for (i = 0; i < local_buf_num; i++) { + queue_init(de_devp->buf_num_avail); + for (i = 0; i < de_devp->buf_num_avail; i++) { struct di_buf_s *di_buf = &(di_buf_local[i]); int ii = USED_LOCAL_BUF_MAX; - - if ((used_post_buf_index != -1) && - (new_keep_last_frame_enable)) { + if (!IS_ERR_OR_NULL(keep_buf)) { for (ii = 0; ii < USED_LOCAL_BUF_MAX; ii++) { - if (i == used_local_buf_index[ii]) { + if (di_buf == di_buf->di_buf_dup_p[ii]) { di_print("%s skip %d\n", __func__, i); break; } @@ -2114,13 +1941,16 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) } if (ii >= USED_LOCAL_BUF_MAX) { + /* backup cma pages */ + tmp_page = di_buf->pages; memset(di_buf, 0, sizeof(struct di_buf_s)); + di_buf->pages = tmp_page; di_buf->type = VFRAME_TYPE_LOCAL; di_buf->pre_ref_count = 0; di_buf->post_ref_count = 0; - di_buf->canvas_width[NR_CANVAS] = (nr_width<<1); - di_buf->canvas_width[MTN_CANVAS] = (mtn_width>>1); - di_buf->canvas_width[MV_CANVAS] = (mv_width<<1)/5; + di_buf->canvas_width[NR_CANVAS] = nr_canvas_width; + di_buf->canvas_width[MTN_CANVAS] = mtn_canvas_width; + di_buf->canvas_width[MV_CANVAS] = mv_canvas_width; if (prog_flag) { di_buf->canvas_height = canvas_height; di_buf->nr_adr = de_devp->mem_start + @@ -2133,13 +1963,11 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) di_buf->mtn_adr = de_devp->mem_start + di_buf_size * i + nr_size; -#ifdef NEW_DI_V1 di_buf->cnt_adr = de_devp->mem_start + di_buf_size * i + nr_size + mtn_size; -#endif - if (mcpre_en) { + if (mc_mem_alloc) { di_buf->mcvec_adr = de_devp->mem_start + di_buf_size * i + nr_size + mtn_size + count_size; @@ -2164,23 +1992,26 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) if (de_devp->flag_cma == 1) { pr_dbg("%s:cma alloc req time: %d ms\n", __func__, jiffies_to_msecs(jiffies)); + atomic_set(&de_devp->mem_flag, 0); di_pre_stru.cma_alloc_req = 1; up(&di_sema); } #endif - if (post_wr_en && post_wr_surpport) { - di_post_mem = de_devp->mem_start + di_buf_size*local_buf_num; - di_post_buf_size = width * canvas_height*2; + if (post_wr_en && post_wr_support) { + di_post_mem = de_devp->mem_start + + di_buf_size*de_devp->buf_num_avail; + di_post_buf_size = nr_width * canvas_height * 2; /* pre buffer must 2 more than post buffer */ - if ((local_buf_num - 2) > MAX_POST_BUF_NUM) + if ((de_devp->buf_num_avail - 2) > MAX_POST_BUF_NUM) di_post_stru.di_post_num = MAX_POST_BUF_NUM; else - di_post_stru.di_post_num = (local_buf_num - 2); + di_post_stru.di_post_num = (de_devp->buf_num_avail - 2); pr_info("DI: di post buffer size %u byte.\n", di_post_buf_size); } else { di_post_stru.di_post_num = MAX_POST_BUF_NUM; di_post_buf_size = 0; } + de_devp->post_buffer_size = di_post_buf_size; for (i = 0; i < MAX_IN_BUF_NUM; i++) { struct di_buf_s *di_buf = &(di_buf_in[i]); @@ -2202,7 +2033,7 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) struct di_buf_s *di_buf = &(di_buf_post[i]); if (di_buf) { - if (i != used_post_buf_index) { + if (di_buf != keep_buf) { memset(di_buf, 0, sizeof(struct di_buf_s)); di_buf->type = VFRAME_TYPE_POST; di_buf->index = i; @@ -2210,7 +2041,7 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) di_buf->vframe->private_data = di_buf; di_buf->queue_index = -1; di_buf->invert_top_bot_flag = 0; - if (post_wr_en && post_wr_surpport) { + if (post_wr_en && post_wr_support) { di_buf->canvas_width[NR_CANVAS] = (nr_width << 1); di_buf->canvas_height = canvas_height; @@ -2227,29 +2058,22 @@ static int di_init_buf(int width, int height, unsigned char prog_flag) static void di_uninit_buf(void) { - struct di_buf_s *p = NULL;/* , *ptmp; */ - int i, ii = 0; - int itmp; + struct di_buf_s *p = NULL, *keep_buf; + int i = 0, ii = 0, itmp; /* vframe_t* cur_vf = get_cur_dispbuf(); */ - if (!queue_empty(QUEUE_DISPLAY)) { - for (i = 0; i < USED_LOCAL_BUF_MAX; i++) - used_local_buf_index[i] = -1; - - used_post_buf_index = -1; - } + if (!queue_empty(QUEUE_DISPLAY)) + di_post_stru.keep_buf = NULL; queue_for_each_entry(p, ptmp, QUEUE_DISPLAY, list) { if (p->di_buf[0]->type != VFRAME_TYPE_IN && (p->process_fun_index != PROCESS_FUN_NULL) && (ii < USED_LOCAL_BUF_MAX) && (p->index == di_post_stru.cur_disp_index)) { - used_post_buf_index = p->index; + di_post_stru.keep_buf = p; for (i = 0; i < USED_LOCAL_BUF_MAX; i++) { - if (p->di_buf_dup_p[i] == NULL) + if (IS_ERR_OR_NULL(p->di_buf_dup_p[i])) continue; - used_local_buf_index[ii] = - p->di_buf_dup_p[i]->index; /* prepare for recycle * the keep buffer */ @@ -2263,41 +2087,35 @@ static void di_uninit_buf(void) } ii++; if (p->di_buf_dup_p[i]->di_wr_linked_buf) - used_local_buf_index[ii] = - p->di_buf_dup_p[i]->di_wr_linked_buf->index; + p->di_buf_dup_p[i+1] = + p->di_buf_dup_p[i]->di_wr_linked_buf; } queue_out(p); break; } } - if (used_post_buf_index != -1) { - pr_info("%s keep cur di_buf %d (%d %d %d)\n", - __func__, used_post_buf_index, used_local_buf_index[0], - used_local_buf_index[1], used_local_buf_index[2]); + if (!IS_ERR_OR_NULL(di_post_stru.keep_buf)) { + keep_buf = di_post_stru.keep_buf; + pr_info("%s keep cur di_buf %d (", + __func__, keep_buf->index); + for (i = 0; i < USED_LOCAL_BUF_MAX; i++) { + if (!IS_ERR_OR_NULL(keep_buf->di_buf_dup_p[i])) + pr_info("%d\t", + keep_buf->di_buf_dup_p[i]->index); + } + pr_info(")\n"); } queue_init(0); - for (i = 0; i < MAX_IN_BUF_NUM; i++) { - if (vframe_in[i]) { - vf_put(vframe_in[i], VFM_NAME); - vf_notify_provider( - VFM_NAME, VFRAME_EVENT_RECEIVER_PUT, NULL); - vframe_in[i] = NULL; - } - } -#ifdef CONFIG_CMA - if (de_devp->flag_cma == 1) { - pr_dbg("%s:cma release req time: %d ms\n", - __func__, jiffies_to_msecs(jiffies)); - di_pre_stru.cma_release_req = 1; - up(&di_sema); - } -#endif + /* decoder'buffer had been releae no need put */ + for (i = 0; i < MAX_IN_BUF_NUM; i++) + vframe_in[i] = NULL; di_pre_stru.pre_de_process_done = 0; di_pre_stru.pre_de_busy = 0; - if (post_wr_en && post_wr_surpport) { + if (post_wr_en && post_wr_support) { di_post_stru.cur_post_buf = NULL; di_post_stru.post_de_busy = 0; di_post_stru.de_post_process_done = 0; + di_post_stru.post_wr_cnt = 0; } } @@ -2317,9 +2135,9 @@ static void log_buffer_state(unsigned char *tag) int recycle = 0; int di_inp = 0; int di_wr = 0; - ulong flags = 0, fiq_flag = 0, irq_flag2 = 0; + ulong irq_flag2 = 0; - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); in_free = list_count(QUEUE_IN_FREE); local_free = list_count(QUEUE_LOCAL_FREE); pre_ready = list_count(QUEUE_PRE_READY); @@ -2354,11 +2172,10 @@ static void log_buffer_state(unsigned char *tag) if (buf_state_log_start) { di_print( - "[%s]i %d, i_f %d/%d, l_f %d/%d, pre_r %d, post_f %d/%d,", + "[%s]i i_f %d/%d, l_f %d/%d, pre_r %d, post_f %d/%d,", tag, - provider_vframe_level, in_free, MAX_IN_BUF_NUM, - local_free, local_buf_num, + local_free, de_devp->buf_num_avail, pre_ready, post_free, MAX_POST_BUF_NUM); di_print( @@ -2369,45 +2186,44 @@ static void log_buffer_state(unsigned char *tag) di_inp, di_wr ); } - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); } } static void dump_state(void) { - struct di_buf_s *p = NULL;/* , *ptmp; */ - int itmp; - int i; + struct di_buf_s *p = NULL, *keep_buf; + int itmp, i; dump_state_flag = 1; - pr_info("version %s, provider vframe level %d,", - version_s, provider_vframe_level); - pr_info("init_flag %d, is_bypass %d, receiver_is_amvideo %d\n", - init_flag, is_bypass(NULL), receiver_is_amvideo); + pr_info("version %s, init_flag %d, is_bypass %d\n", + version_s, init_flag, is_bypass(NULL)); pr_info("recovery_flag = %d, recovery_log_reason=%d, di_blocking=%d", recovery_flag, recovery_log_reason, di_blocking); pr_info("recovery_log_queue_idx=%d, recovery_log_di_buf=0x%p\n", recovery_log_queue_idx, recovery_log_di_buf); - pr_info("buffer_size=%d,mem_flag=%d\n", de_devp->buffer_size, mem_flag); - pr_info("new_keep_last_frame_enable %d,", new_keep_last_frame_enable); - pr_info("used_post_buf_index %d(0x%p),", used_post_buf_index, - (used_post_buf_index == - -1) ? NULL : &(di_buf_post[used_post_buf_index])); - pr_info("used_local_buf_index:\n"); - for (i = 0; i < USED_LOCAL_BUF_MAX; i++) { - int tmp = used_local_buf_index[i]; - - pr_info("%d(0x%p) ", tmp, - (tmp == -1) ? NULL : &(di_buf_local[tmp])); + pr_info("buffer_size=%d, mem_flag=%d, cma_flag=%d\n", + de_devp->buffer_size, atomic_read(&de_devp->mem_flag), + de_devp->flag_cma); + keep_buf = di_post_stru.keep_buf; + pr_info("used_post_buf_index %d(0x%p),", + IS_ERR_OR_NULL(keep_buf) ? + -1 : keep_buf->index, keep_buf); + if (!IS_ERR_OR_NULL(keep_buf)) { + pr_info("used_local_buf_index:\n"); + for (i = 0; i < USED_LOCAL_BUF_MAX; i++) { + p = keep_buf->di_buf_dup_p[i]; + pr_info("%d(0x%p) ", + IS_ERR_OR_NULL(p) ? -1 : p->index, p); + } } - pr_info("\nin_free_list (max %d):\n", MAX_IN_BUF_NUM); queue_for_each_entry(p, ptmp, QUEUE_IN_FREE, list) { pr_info("index %2d, 0x%p, type %d\n", p->index, p, p->type); } - pr_info("local_free_list (max %d):\n", local_buf_num); + pr_info("local_free_list (max %d):\n", de_devp->buf_num_avail); queue_for_each_entry(p, ptmp, QUEUE_LOCAL_FREE, list) { pr_info("index %2d, 0x%p, type %d\n", p->index, p, p->type); } @@ -2479,10 +2295,9 @@ static void dump_state(void) pr_info("0x%p ", vframe_in[i]); pr_info("\n"); - pr_info("vf_peek()=>0x%p,di_process_cnt = %d\n", - vf_peek(VFM_NAME), di_process_cnt); - pr_info("video_peek_cnt = %d,force_trig_cnt = %d\n", - video_peek_cnt, force_trig_cnt); + pr_info("vf_peek()=>0x%p, video_peek_cnt = %d\n", + vf_peek(VFM_NAME), video_peek_cnt); + pr_info("reg_unreg_timerout = %lu\n", reg_unreg_timeout_cnt); dump_state_flag = 0; } @@ -2550,7 +2365,7 @@ config_di_pre_mc_mif(struct DI_MC_MIF_s *di_mcinfo_mif, di_mcvec_mif->canvas_num = di_buf->mcvec_canvas_idx; } } -#ifdef NEW_DI_V1 + static void config_di_cnt_mif(struct DI_SIM_MIF_s *di_cnt_mif, struct di_buf_s *di_buf) { @@ -2562,7 +2377,6 @@ static void config_di_cnt_mif(struct DI_SIM_MIF_s *di_cnt_mif, di_cnt_mif->canvas_num = di_buf->cnt_canvas_idx; } } -#endif static void config_di_wr_mif(struct DI_SIM_MIF_s *di_nrwr_mif, @@ -2591,7 +2405,8 @@ config_di_wr_mif(struct DI_SIM_MIF_s *di_nrwr_mif, di_mtnwr_mif->canvas_num = di_buf->mtn_canvas_idx; } } - +static bool force_prog; +module_param_named(force_prog, force_prog, bool, 0664); static void config_di_mif(struct DI_MIF_s *di_mif, struct di_buf_s *di_buf) { if (di_buf == NULL) @@ -2671,7 +2486,7 @@ static void config_di_mif(struct DI_MIF_s *di_mif, struct di_buf_s *di_buf) di_mif->chroma_y_end0 = di_buf->vframe->height / 2 - 1; } else { - di_mif->src_prog = di_pre_stru.cur_prog_flag; + di_mif->src_prog = force_prog?1:0; di_mif->src_field_mode = 1; if ( (di_buf->vframe->type & VIDTYPE_TYPEMASK) == @@ -2711,20 +2526,28 @@ static void config_di_mif(struct DI_MIF_s *di_mif, struct di_buf_s *di_buf) } } +static void di_pre_size_change(unsigned short width, + unsigned short height, unsigned short vf_type); + +#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC +static void pre_inp_canvas_config(struct vframe_s *vf); +#endif static void pre_de_process(void) { + unsigned short pre_width = 0, pre_height = 0; int chan2_field_num = 1; int canvases_idex = di_pre_stru.field_count_for_cont % 2; - -#ifdef NEW_DI_V1 + unsigned short cur_inp_field_type = VIDTYPE_TYPEMASK; + bool me_auto_en = true; int cont_rd = 1; -#endif - unsigned int blkhsize = 0; - unsigned int di_mtn_1_ctrl1 = RDMA_RD(DI_MTN_1_CTRL1); - di_print("%s: start\n", __func__); + if (is_meson_gxlx_cpu() || is_meson_txhd_cpu()) + me_auto_en = false; di_pre_stru.pre_de_busy = 1; di_pre_stru.pre_de_busy_timer_count = 0; + #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC + pre_inp_canvas_config(di_pre_stru.di_inp_buf->vframe); + #endif config_di_mif(&di_pre_stru.di_inp_mif, di_pre_stru.di_inp_buf); /* pr_dbg("set_separate_en=%d vframe->type %d\n", @@ -2732,33 +2555,40 @@ static void pre_de_process(void) * di_pre_stru.di_inp_buf->vframe->type); */ #ifdef DI_USE_FIXED_CANVAS_IDX - if ((di_pre_stru.di_mem_buf_dup_p != NULL && - di_pre_stru.di_mem_buf_dup_p != di_pre_stru.di_inp_buf)) { + if (di_pre_stru.di_mem_buf_dup_p != NULL && + di_pre_stru.di_mem_buf_dup_p != di_pre_stru.di_inp_buf) { config_canvas_idx(di_pre_stru.di_mem_buf_dup_p, di_pre_idx[canvases_idex][0], -1); -#ifdef NEW_DI_V1 config_cnt_canvas_idx(di_pre_stru.di_mem_buf_dup_p, di_pre_idx[canvases_idex][1]); -#endif + } else { + config_cnt_canvas_idx(di_pre_stru.di_wr_buf, + di_pre_idx[canvases_idex][1]); + config_di_cnt_mif(&di_pre_stru.di_contp2rd_mif, + di_pre_stru.di_wr_buf); + } if (di_pre_stru.di_chan2_buf_dup_p != NULL) { config_canvas_idx(di_pre_stru.di_chan2_buf_dup_p, di_pre_idx[canvases_idex][2], -1); -#ifdef NEW_DI_V1 config_cnt_canvas_idx(di_pre_stru.di_chan2_buf_dup_p, di_pre_idx[canvases_idex][3]); -#endif + } else { + config_cnt_canvas_idx(di_pre_stru.di_wr_buf, + di_pre_idx[canvases_idex][3]); } config_canvas_idx(di_pre_stru.di_wr_buf, di_pre_idx[canvases_idex][4], di_pre_idx[canvases_idex][5]); -#ifdef NEW_DI_V1 config_cnt_canvas_idx(di_pre_stru.di_wr_buf, di_pre_idx[canvases_idex][6]); -#endif if (mcpre_en) { if (di_pre_stru.di_chan2_buf_dup_p != NULL) config_mcinfo_canvas_idx(di_pre_stru.di_chan2_buf_dup_p, di_pre_idx[canvases_idex][7]); + else + config_mcinfo_canvas_idx(di_pre_stru.di_wr_buf, + di_pre_idx[canvases_idex][7]); + config_mcinfo_canvas_idx(di_pre_stru.di_wr_buf, di_pre_idx[canvases_idex][8]); config_mcvec_canvas_idx(di_pre_stru.di_wr_buf, @@ -2766,21 +2596,31 @@ static void pre_de_process(void) } #endif config_di_mif(&di_pre_stru.di_mem_mif, di_pre_stru.di_mem_buf_dup_p); - config_di_mif(&di_pre_stru.di_chan2_mif, - di_pre_stru.di_chan2_buf_dup_p); + if (di_pre_stru.di_chan2_buf_dup_p == NULL) { + config_di_mif(&di_pre_stru.di_chan2_mif, + di_pre_stru.di_inp_buf); + } else + config_di_mif(&di_pre_stru.di_chan2_mif, + di_pre_stru.di_chan2_buf_dup_p); config_di_wr_mif(&di_pre_stru.di_nrwr_mif, &di_pre_stru.di_mtnwr_mif, di_pre_stru.di_wr_buf, di_pre_stru.di_inp_buf->vframe); -#ifdef NEW_DI_V1 - config_di_cnt_mif(&di_pre_stru.di_contp2rd_mif, - di_pre_stru.di_mem_buf_dup_p); - config_di_cnt_mif(&di_pre_stru.di_contprd_mif, - di_pre_stru.di_chan2_buf_dup_p); - config_di_cnt_mif(&di_pre_stru.di_contwr_mif, di_pre_stru.di_wr_buf); -#endif - if (mcpre_en) { - config_di_mcinford_mif(&di_pre_stru.di_mcinford_mif, + if (di_pre_stru.di_chan2_buf_dup_p) + config_di_cnt_mif(&di_pre_stru.di_contprd_mif, di_pre_stru.di_chan2_buf_dup_p); + else + config_di_cnt_mif(&di_pre_stru.di_contprd_mif, + di_pre_stru.di_wr_buf); + + config_di_cnt_mif(&di_pre_stru.di_contwr_mif, di_pre_stru.di_wr_buf); + if (mcpre_en) { + if (di_pre_stru.di_chan2_buf_dup_p) + config_di_mcinford_mif(&di_pre_stru.di_mcinford_mif, + di_pre_stru.di_chan2_buf_dup_p); + else + config_di_mcinford_mif(&di_pre_stru.di_mcinford_mif, + di_pre_stru.di_wr_buf); + config_di_pre_mc_mif(&di_pre_stru.di_mcinfowr_mif, &di_pre_stru.di_mcvecwr_mif, di_pre_stru.di_wr_buf); } @@ -2789,64 +2629,37 @@ static void pre_de_process(void) ((di_pre_stru.di_chan2_buf_dup_p->vframe->type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP)) chan2_field_num = 0; - - RDMA_WR(DI_PRE_SIZE, di_pre_stru.di_nrwr_mif.end_x | - (di_pre_stru.di_nrwr_mif.end_y << 16)); - if (mcpre_en) { - blkhsize = (di_pre_stru.di_nrwr_mif.end_x + 4) / 5; - RDMA_WR(MCDI_HV_SIZEIN, (di_pre_stru.di_nrwr_mif.end_y + 1) - | ((di_pre_stru.di_nrwr_mif.end_x + 1) << 16)); - RDMA_WR(MCDI_HV_BLKSIZEIN, (overturn ? 3 : 0) << 30 - | blkhsize << 16 - | (di_pre_stru.di_nrwr_mif.end_y + 1)); - RDMA_WR(MCDI_BLKTOTAL, - blkhsize * (di_pre_stru.di_nrwr_mif.end_y + 1)); + pre_width = di_pre_stru.di_nrwr_mif.end_x + 1; + pre_height = di_pre_stru.di_nrwr_mif.end_y + 1; + if (di_pre_stru.input_size_change_flag) { + cur_inp_field_type = + (di_pre_stru.di_inp_buf->vframe->type & VIDTYPE_TYPEMASK); + cur_inp_field_type = + di_pre_stru.cur_prog_flag ? VIDTYPE_PROGRESSIVE : cur_inp_field_type; + di_pre_size_change(pre_width, pre_height, + cur_inp_field_type); + di_pre_stru.input_size_change_flag = false; } /* set interrupt mask for pre module. * we need to only leave one mask open * to prevent multiple entry for de_irq - */ - RDMA_WR(DI_INTR_CTRL, - /* mask nrwr interrupt. */ - ((di_pre_stru.enable_mtnwr ? 1 : 0) << 16) | - /* mtnwr interrupt. */ - ((di_pre_stru.enable_mtnwr ? 0 : 1) << 17) | - /* mask diwr intrpt. */ - (((post_wr_en && post_wr_surpport)?0:1) << 18) | - (1 << 19) | /* mask hist check interrupt. */ - (1 << 20) | /* mask cont interrupt. */ - (1 << 21) | /* mask medi interrupt. */ - (1 << 22) | /* mask vecwr interrupt. */ - (1 << 23) | /* mask infwr interrupt. */ - #ifdef DET3D - ((det3d_en ? 0 : 1) << 24) | /* mask det3d interrupt. */ - #else - (1 << 24) | /* mask det3d interrupt. */ - #endif - ((post_wr_en && post_wr_surpport)?0xb:0xf)); - /* clean all pending interrupt bits. */ - - enable_di_pre_aml(&di_pre_stru.di_inp_mif, /* di_inp */ - &di_pre_stru.di_mem_mif, /* di_mem */ - &di_pre_stru.di_chan2_mif, /* chan2 */ - &di_pre_stru.di_nrwr_mif, /* nrwrite */ - &di_pre_stru.di_mtnwr_mif, /* mtn write */ -#ifdef NEW_DI_V1 + */ + enable_di_pre_aml(&di_pre_stru.di_inp_mif, + &di_pre_stru.di_mem_mif, + &di_pre_stru.di_chan2_mif, + &di_pre_stru.di_nrwr_mif, + &di_pre_stru.di_mtnwr_mif, &di_pre_stru.di_contp2rd_mif, &di_pre_stru.di_contprd_mif, &di_pre_stru.di_contwr_mif, -#endif - 1, /* nr enable */ - di_pre_stru.enable_mtnwr, /* mtn enable */ + 1, + di_pre_stru.enable_mtnwr, di_pre_stru.enable_pulldown_check, -/* pd32 check_en */ di_pre_stru.enable_pulldown_check, -/* pd22 check_en */ - 0, /* hist check_en */ + 0, chan2_field_num, -/* field num for chan2. 1 bottom, 0 top. */ - di_pre_stru.vdin2nr, /* pre vdin link. */ - pre_hold_line, /* hold line. */ + di_pre_stru.vdin2nr, + pre_hold_line, pre_urgent ); if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) @@ -2859,88 +2672,60 @@ static void pre_de_process(void) &di_pre_stru.di_mcvecwr_mif, pre_urgent); } if (di_pre_stru.cur_prog_flag == 1 || di_pre_stru.enable_mtnwr == 0) { - di_mtn_1_ctrl1 &= (~(1 << 31)); /* disable contwr */ - di_mtn_1_ctrl1 &= (~(1 << 29)); /* disable txt */ + RDMA_WR_BITS(DI_MTN_1_CTRL1, 0, 31, 1); /* disable contwr */ + RDMA_WR_BITS(DI_MTN_1_CTRL1, 0, 29, 1); /* disable txt */ cont_rd = 0; - if (mcpre_en) - RDMA_WR(DI_ARB_CTRL, - (RDMA_RD(DI_ARB_CTRL) & (~0x303)) | 0xF0F); - else - RDMA_WR(DI_ARB_CTRL, - RDMA_RD(DI_ARB_CTRL) | 1 << 9 | 1 << 8 - | 1 << 1 | 1 << 0); - } else { - if (mcpre_en) - RDMA_WR(DI_ARB_CTRL, - RDMA_RD(DI_ARB_CTRL) | 1 << 9 | 1 << 8 - | 1 << 1 | 1 << 0 | 0xF0F); - else - RDMA_WR(DI_ARB_CTRL, - RDMA_RD(DI_ARB_CTRL) | 1 << 9 | 1 << 8 - | 1 << 1 | 1 << 0); - di_mtn_1_ctrl1 |= (1 << 31); /* enable contwr */ - RDMA_WR(DI_PRE_CTRL, RDMA_RD(DI_PRE_CTRL) | (1 << 1)); - /* mtn must enable for mtn1 enable */ - di_mtn_1_ctrl1 &= (~(1 << 29));/* disable txt */ - cont_rd = 1; - } - if (di_pre_stru.field_count_for_cont >= 3) { - di_mtn_1_ctrl1 |= 1 << 29;/* enable txt */ - RDMA_WR(DI_PRE_CTRL, - RDMA_RD(DI_PRE_CTRL) | (cont_rd << 25)); -#ifdef NEW_DI_V4 - if ((!dnr_en) && (Rd(DNR_CTRL) != 0) && dnr_reg_update) - RDMA_WR(DNR_CTRL, 0); -#endif - if (mcpre_en) { - if ((di_pre_stru.cur_prog_flag == 0) && - (di_pre_stru.enable_mtnwr == 1) - ) - RDMA_WR(DI_MTN_CTRL1, - (mcpre_en ? 0x3000 : 0) | - RDMA_RD(DI_MTN_CTRL1)); - else - RDMA_WR(DI_MTN_CTRL1, - (0xffffcfff & RDMA_RD(DI_MTN_CTRL1))); - /* enable me(mc di) */ - if (di_pre_stru.field_count_for_cont == 4) { - di_mtn_1_ctrl1 &= (~(1 << 30)); - /* enable contp2rd and contprd */ - RDMA_WR(MCDI_MOTINEN, 1 << 1 | 1); - } - if (di_pre_stru.field_count_for_cont == 5) - RDMA_WR(MCDI_CTRL_MODE, 0x1bfff7ff); - /* disalbe reflinfo */ - } else { - di_mtn_1_ctrl1 &= (~(1 << 30)); - } - /* enable contp2rd and contprd */ + RDMA_WR_BITS(MCDI_MOTINEN, 0, 0, 2); + RDMA_WR(MCDI_CTRL_MODE, 0); + RDMA_WR_BITS(DI_MTN_CTRL1, 0, 12, 2); + RDMA_WR(DI_INTR_CTRL, + /* mask nrwr interrupt. */ + (2 << 16) | + /* mask diwr intrpt. */ + (((post_wr_en && post_wr_support)?0:1) << 18) | + (0x1f << 19) | /* mask hist check interrupt. */ + #ifdef DET3D + ((det3d_en ? 0 : 1) << 24) | /* mask det3d interrupt. */ + #else + (1 << 24) | /* mask det3d interrupt. */ + #endif + ((post_wr_en && post_wr_support)?0xb:0xf)); + /* clean all pending interrupt bits. */ } else { - di_mtn_1_ctrl1 |= (1 << 30); - enable_film_mode_check( - di_pre_stru.di_inp_buf->vframe->width, - di_pre_stru.di_inp_buf->vframe->height / 2, - di_pre_stru.di_inp_buf->vframe->source_type); + RDMA_WR_BITS(DI_MTN_1_CTRL1, 5, 29, 3); + RDMA_WR(DI_PRE_CTRL, RDMA_RD(DI_PRE_CTRL) | (1 << 1)); + cont_rd = 1; + RDMA_WR(DI_INTR_CTRL, + (((post_wr_en && post_wr_support)?0:1) << 18) | + (1 << 19) | /* mask hist check interrupt. */ + (7 << 21) | /* mask mcdi interrupt. */ + #ifdef DET3D + ((det3d_en ? 0 : 1) << 24) | + #else + (1 << 24) | /* mask det3d interrupt. */ + #endif + ((post_wr_en && post_wr_support)?0xb:0xf)); if (mcpre_en) { - /* txtdet_en mode */ - RDMA_WR_BITS(MCDI_CTRL_MODE, 0, 1, 1); - RDMA_WR_BITS(MCDI_CTRL_MODE, 1, 9, 1); - RDMA_WR_BITS(MCDI_CTRL_MODE, 1, 16, 1); - RDMA_WR_BITS(MCDI_CTRL_MODE, 0, 28, 1); - RDMA_WR(MCDI_MOTINEN, 0); - RDMA_WR(DI_MTN_CTRL1, - (0xffffcfff & RDMA_RD(DI_MTN_CTRL1))); - /* disable me(mc di) */ + /* enable me(mc di) */ + RDMA_WR_BITS(MCDI_MOTINEN, 3, 0, 2); + RDMA_WR(MCDI_CTRL_MODE, + me_auto_en ? 0x1bfff7ff:0x1bfe37ff); + /* + * bit12=0 disable autoen for + * hw issue in mcdi + */ + RDMA_WR_BITS(DI_MTN_CTRL1, + (me_auto_en ? 3 : 2), 12, 2); + } else { + RDMA_WR_BITS(MCDI_MOTINEN, 0, 0, 2); + RDMA_WR(MCDI_CTRL_MODE, 0); + RDMA_WR_BITS(DI_MTN_CTRL1, 0, 12, 2); } -#ifdef NEW_DI_V4 - RDMA_WR(DNR_CTRL, 0); -#endif } + di_pre_stru.field_count_for_cont++; - RDMA_WR(DI_MTN_1_CTRL1, di_mtn_1_ctrl1); - di_apply_reg_cfg(0); #ifdef SUPPORT_MPEG_TO_VDIN if (mpeg2vdin_flag) { struct vdin_arg_s vdin_arg; @@ -2951,10 +2736,18 @@ static void pre_de_process(void) vdin_ops->tvin_vdin_func(0, &vdin_arg); } #endif + /* frame + soft reset for the pre modules. */ + RDMA_WR(DI_PRE_CTRL, Rd(DI_PRE_CTRL) | 3 << 30); + RDMA_WR(DI_PRE_CTRL, + RDMA_RD(DI_PRE_CTRL) | (cont_rd << 25)); + #ifdef SUPPORT_MPEG_TO_VDIN + if (mpeg2vdin_flag) + RDMA_WR_BITS(DI_PRE_CTRL, 1, 13, 1); + #endif /* enable pre mif*/ - enable_di_pre_mif(1); - di_print("DI:buf[%d] irq start.\n", di_pre_stru.di_inp_buf->seq); + enable_di_pre_mif(true, mcpre_en); + di_pre_stru.irq_time = sched_clock()/NSEC_PER_MSEC; #ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (di_pre_rdma_enable & 0x2) rdma_config(de_devp->rdma_handle, RDMA_TRIGGER_MANUAL); @@ -3010,107 +2803,7 @@ static void top_bot_config(struct di_buf_s *di_buf) } } -static void pulldown_buf_init(struct di_buf_s *di_buf) -{ - di_buf->pulldown_mode = - PULL_DOWN_NORMAL; - di_buf->reg0_s = 0; - di_buf->reg0_e = 0; - di_buf->reg0_bmode = 0; - - di_buf->reg1_s = 0; - di_buf->reg1_e = 0; - di_buf->reg1_bmode = 0; - - di_buf->reg2_s = 0; - di_buf->reg2_e = 0; - di_buf->reg2_bmode = 0; - - di_buf->reg3_s = 0; - di_buf->reg3_e = 0; - di_buf->reg3_bmode = 0; -} - -static void pulldown_wnd_config(struct di_buf_s *di_buf) -{ - di_buf->reg0_s = dectres.rPstCYWnd0[0]; - di_buf->reg0_e = dectres.rPstCYWnd0[1]; - di_buf->reg1_s = dectres.rPstCYWnd1[0]; - di_buf->reg1_e = dectres.rPstCYWnd1[1]; - di_buf->reg2_s = dectres.rPstCYWnd2[0]; - di_buf->reg2_e = dectres.rPstCYWnd2[1]; - di_buf->reg3_s = dectres.rPstCYWnd3[0]; - di_buf->reg3_e = dectres.rPstCYWnd3[1]; - di_buf->reg0_bmode = dectres.rPstCYWnd0[2]; - di_buf->reg1_bmode = dectres.rPstCYWnd1[2]; - di_buf->reg2_bmode = dectres.rPstCYWnd2[2]; - di_buf->reg3_bmode = dectres.rPstCYWnd3[2]; - -} -struct FlmModReg_t flmreg; -unsigned int pulldown_enable = 1; -module_param(pulldown_enable, uint, 0644); -MODULE_PARM_DESC(pulldown_enable, "/n pulldonw mode result./n"); - -static unsigned int pldn_mod; -module_param(pldn_mod, uint, 0644); -MODULE_PARM_DESC(pldn_mod, "/n pulldonw mode result./n"); - -static unsigned int pldn_cmb0 = 1; -module_param(pldn_cmb0, uint, 0644); -MODULE_PARM_DESC(pldn_cmb0, "/n pulldonw combing result./n"); - -static unsigned int pldn_cmb1; -module_param(pldn_cmb1, uint, 0644); -MODULE_PARM_DESC(pldn_cmb1, "/n pulldonw combing result./n"); - -unsigned int field_count; - -int cmb_adpset_cnt; -module_param(cmb_adpset_cnt, int, 0664); - -unsigned int field_diff_rate; - -static unsigned int flm22_sure_num = 100; - -/* - * static unsigned int flmxx_sure_num = 50; - * module_param(flmxx_sure_num, uint, 0644); - * MODULE_PARM_DESC(flmxx_sure_num, "true film-xx/n"); - */ - -static unsigned int flm22_sure_smnum = 70; -static unsigned int flm22_ratio = 100; -/* 79 for iptv test pd22 ts */ -module_param_named(flm22_ratio, flm22_ratio, uint, 0644); -/* static unsigned int flmxx_sure_num[7] - * = {50, 50, 50, 50, 50, 50, 50}; - */ -static unsigned int flmxx_sure_num[7] = {20, 20, 20, 20, 20, 20, 20}; -static unsigned int flmxx_snum_adr = 7; -module_param_array(flmxx_sure_num, uint, &flmxx_snum_adr, 0664); - -static unsigned int flm22_glbpxlnum_rat = 4; /* 4/256 = 64 */ - -static unsigned int flm22_glbpxl_maxrow = 16; /* 16/256 = 16 */ -module_param(flm22_glbpxl_maxrow, uint, 0644); -MODULE_PARM_DESC(flm22_glbpxl_maxrow, "flm22_glbpxl_maxrow/n"); - -static unsigned int flm22_glbpxl_minrow = 3; /* 4/256 = 64 */ -module_param(flm22_glbpxl_minrow, uint, 0644); -MODULE_PARM_DESC(flm22_glbpxl_minrow, "flm22_glbpxl_minrow/n"); - -static unsigned int cmb_3point_rnum; -module_param(cmb_3point_rnum, uint, 0644); -MODULE_PARM_DESC(cmb_3point_rnum, "cmb_3point_rnum/n"); - -static unsigned int cmb_3point_rrat = 32; -module_param(cmb_3point_rrat, uint, 0644); -MODULE_PARM_DESC(cmb_3point_rrat, "cmb_3point_rrat/n"); - -static unsigned int pldn_calc_en = 1; -module_param(pldn_calc_en, uint, 0644); -MODULE_PARM_DESC(pldn_calc_en, "/n pulldonw calculation enable./n"); +static bool pulldown_enable = true; static bool combing_fix_en = true; module_param_named(combing_fix_en, combing_fix_en, bool, 0664); @@ -3120,22 +2813,10 @@ module_param_named(combing_cur_lev, cur_lev, int, 0444); static void pre_de_done_buf_config(void) { - ulong flags = 0, fiq_flag = 0, irq_flag2 = 0; - bool dynamic_flag = false; - int hHeight = di_pre_stru.di_nrwr_mif.end_y; - int wWidth = di_pre_stru.di_nrwr_mif.end_x; - int tTCNm; - bool flm32 = false; - bool flm22 = false; - bool flmxx = false; - int tb_chk_ret = 0, like_pulldown22_flag = 0; - static unsigned int frame_diff_avg; + ulong irq_flag2 = 0; + struct di_buf_s *post_wr_buf = NULL; unsigned int glb_frame_mot_num = 0; unsigned int glb_field_mot_num = 0; - unsigned int mot_row = 0; - unsigned int mot_max = 0; - unsigned int flm22_surenum = flm22_sure_num; - unsigned int ntmp = 0; if (di_pre_stru.di_wr_buf) { if (di_pre_stru.pre_throw_flag > 0) { @@ -3153,301 +2834,28 @@ static void pre_de_done_buf_config(void) di_pre_stru.di_wr_buf->vframe); } #endif + } if (!di_pre_rdma_enable) di_pre_stru.di_post_wr_buf = di_pre_stru.di_wr_buf; + post_wr_buf = di_pre_stru.di_post_wr_buf; - if (di_pre_stru.cur_source_type == VFRAME_SOURCE_TYPE_OTHERS && - tff_bff_enable) { - tb_chk_ret = tff_bff_check((di_pre_stru.cur_height>>1), - di_pre_stru.cur_width); - di_pre_stru.di_post_wr_buf->privated &= (~0x3); - di_pre_stru.di_post_wr_buf->privated |= tb_chk_ret; - } - if (di_pre_stru.di_post_wr_buf) { - dynamic_flag = read_pulldown_info( - &(di_pre_stru.di_post_wr_buf->field_pd_info), - &(di_pre_stru.di_post_wr_buf->win_pd_info[0])); - glb_frame_mot_num = di_pre_stru.di_post_wr_buf-> - field_pd_info.frame_diff_num; - glb_field_mot_num = di_pre_stru.di_post_wr_buf-> - field_pd_info.field_diff_num; - di_pre_stru.static_frame_count = - dynamic_flag ? 0 : (di_pre_stru. - static_frame_count + 1); - if (di_pre_stru.static_frame_count > - static_pic_threshold) { - di_pre_stru.static_frame_count = - static_pic_threshold; - di_pre_stru.di_post_wr_buf->pulldown_mode = - PULL_DOWN_BLEND_0; - } else { - di_pre_stru.di_post_wr_buf->pulldown_mode = - PULL_DOWN_NORMAL; - } + if (post_wr_buf && !di_pre_stru.cur_prog_flag) { + read_pulldown_info(&glb_frame_mot_num, + &glb_field_mot_num); + if (pulldown_enable) + pulldown_detection(&post_wr_buf->pd_config, + di_pre_stru.mtn_status, overturn); if (combing_fix_en) cur_lev = adaptive_combing_fixing( + di_pre_stru.mtn_status, glb_field_mot_num, glb_frame_mot_num, - cur_lev, - di_force_bit_mode, - tTCNm, - like_pulldown22_flag, - &frame_diff_avg); + di_force_bit_mode); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) + adaptive_cue_adjust(glb_frame_mot_num, + glb_field_mot_num); } - tTCNm = 0; - if (!di_pre_stru.cur_prog_flag) { - /* always read and print data */ - read_new_pulldown_info(&flmreg); - /* read_new_pulldown_info(&flmreg); */ - if ((pldn_calc_en == 1) && pulldown_enable) { - dectres.rF22Flag = FlmVOFSftTop( - &(dectres.rCmb32Spcl), - dectres.rPstCYWnd0, - dectres.rPstCYWnd1, - dectres.rPstCYWnd2, - dectres.rPstCYWnd3, - dectres.rPstCYWnd4, - &(dectres.rFlmPstGCm), - &(dectres.rFlmSltPre), - &(dectres.rFlmPstMod), - flmreg.rROFldDif01, - flmreg.rROFrmDif02, - flmreg.rROCmbInf, - glb_frame_mot_num, - glb_field_mot_num, - &tTCNm, - &pd_param, - hHeight + 1, - wWidth + 1, - &frame_diff_avg); - - if (hHeight >= 289) /*full hd */ - tTCNm = tTCNm << 1; - if (tTCNm > hHeight) - tTCNm = hHeight; - - prt_flg = ((pr_pd >> 1) & 0x1); - if (prt_flg) { - sprintf(debug_str, "#Pst-Dbg:\n"); - sprintf(debug_str + strlen(debug_str), - "Mod=%d, Pre=%d, GCmb=%d, Lvl2=%d\n", - dectres.rFlmPstMod, - dectres.rFlmSltPre, - dectres.rFlmPstGCm, - dectres.rF22Flag); - - sprintf(debug_str + strlen(debug_str), - "N%03d: nd[%d~%d], [%d~%d], [%d~%d], [%d~%d]\n", - tTCNm, - dectres.rPstCYWnd0[0], - dectres.rPstCYWnd0[1], - dectres.rPstCYWnd1[0], - dectres.rPstCYWnd1[1], - dectres.rPstCYWnd2[0], - dectres.rPstCYWnd2[1], - dectres.rPstCYWnd3[0], - dectres.rPstCYWnd3[1]); - - pr_info("%s", debug_str); - } - } - - if (pulldown_enable && di_pre_stru.di_post_wr_buf) { - /* refresh, default setting */ - pulldown_buf_init(di_pre_stru.di_post_wr_buf); - } - if (dectres.rFlmPstMod == 1) - like_pulldown22_flag = dectres.rF22Flag; - else - like_pulldown22_flag = 0; - - if ((pr_pd >> 1) & 0x1) - pr_info("fld_dif_rat=%d\n", - field_diff_rate); - if ((dectres.rF22Flag >= - (cmb_3point_rnum + field_diff_rate)) && - (tTCNm > - (hHeight * cmb_3point_rrat >> 8))) { - if ((pr_pd >> 1) & 0x1) - pr_info("coeff-3-point enabled\n"); - } - if (pulldown_enable == 1 && dectres.rFlmPstMod != 0 - && di_pre_stru.di_post_wr_buf) { - flm32 = (dectres.rFlmPstMod == 2 && - dectres.rFlmPstGCm == 0); - - ntmp = (glb_frame_mot_num + glb_field_mot_num) / - (wWidth + 1); - if (flm22_sure_num > ntmp + flm22_sure_smnum) - flm22_surenum = flm22_sure_num - ntmp; - else - flm22_surenum = flm22_sure_smnum; - - if (cmb_adpset_cnt > 0) - pr_info("flm22_surenum = %2d\n", - flm22_surenum); - if (dectres.rFlmPstMod == 1) { - mot_row = glb_frame_mot_num * - flm22_glbpxlnum_rat / (wWidth + 1); - mot_max = (flm22_glbpxl_maxrow * - hHeight + 128) >> 8; - if ((pr_pd >> 1) & 0x1) - pr_info("dejaggies level=%3d - (%02d - %02d)\n", - dectres.rF22Flag, - mot_max, mot_row); - - if (mot_row < mot_max) { - if (dectres.rF22Flag > - (mot_max - mot_row)) - dectres.rF22Flag -= - (mot_max - mot_row); - else - dectres.rF22Flag = 0; - - if (mot_row <= flm22_glbpxl_minrow) - dectres.rFlmPstMod = 0; - } - } - - flm22 = (dectres.rFlmPstMod == 1 && - dectres.rF22Flag >= flm22_surenum); - if (dectres.rFlmPstMod >= 4) - flmxx = (dectres.rF22Flag >= - flmxx_sure_num[dectres.rFlmPstMod - 4]); - else - flmxx = 0; - - /* 2-2 force */ - if ((pldn_mod == 0) && - (flm32 || flm22 || flmxx)) { - if (dectres.rFlmSltPre == 1) - di_pre_stru.di_post_wr_buf - ->pulldown_mode = - PULL_DOWN_BLEND_0; - else { - di_pre_stru.di_post_wr_buf - ->pulldown_mode = - PULL_DOWN_BLEND_2; - } - } else if (pldn_mod == 1) { - if (dectres.rFlmSltPre == 1) - di_pre_stru.di_post_wr_buf - ->pulldown_mode = - PULL_DOWN_BLEND_0; - else - di_pre_stru.di_post_wr_buf - ->pulldown_mode = - PULL_DOWN_BLEND_2; - } else { - di_pre_stru.di_post_wr_buf-> - pulldown_mode = - PULL_DOWN_NORMAL; - } - - if (flm32 && (pldn_cmb0 == 1)) { - pulldown_wnd_config( - di_pre_stru.di_post_wr_buf); - } else if (dectres.rF22Flag > 1 && - dectres.rFlmPstMod == 1 && - pldn_cmb0 == 1) { - /* SRSHARP0_SHARP_SR2_CTRL */ - /* SRSHARP0_SHARP_DEJ2_MISC */ - /* SRSHARP0_SHARP_DEJ1_MISC */ - - if ((pr_pd >> 1) & 0x1) - pr_info("dejaggies level= %3d\n", - dectres.rF22Flag); - } else if (dectres.rFlmPstGCm == 0 && - pldn_cmb0 > 1 && pldn_cmb0 <= 5) { - pulldown_wnd_config( - di_pre_stru.di_post_wr_buf); - /* 1-->only film-mode - * 2-->windows-->mtn - * 3-->windows-->detected - * 4-->windows-->di - */ - /* pldn_cmb0 == 2 - * setting in pulldown wnd config - */ - if (pldn_cmb0 == 3) { - di_pre_stru.di_post_wr_buf-> - reg0_bmode = 3; - di_pre_stru.di_post_wr_buf-> - reg1_bmode = 3; - di_pre_stru.di_post_wr_buf-> - reg2_bmode = 3; - di_pre_stru.di_post_wr_buf-> - reg3_bmode = 3; - } else if (pldn_cmb0 == 4) { - di_pre_stru.di_post_wr_buf-> - reg0_bmode = 2; - di_pre_stru.di_post_wr_buf-> - reg1_bmode = 2; - di_pre_stru.di_post_wr_buf-> - reg2_bmode = 2; - di_pre_stru.di_post_wr_buf-> - reg3_bmode = 2; - } else if (pldn_cmb0 == 5) { - di_pre_stru. - di_post_wr_buf->reg3_s = 0; - di_pre_stru. - di_post_wr_buf->reg3_e = 60; - di_pre_stru. - di_post_wr_buf->reg3_bmode = 0; - } - } - /* else pldn_cmb0==0 (Nothing) */ - if ((dectres.rFlmPstGCm == 1) && (pldn_cmb1 > 0) - && (pldn_cmb1 <= 5)) { - pulldown_wnd_config( - di_pre_stru.di_post_wr_buf); - /* - * 1-->normal set in pulldown - * wnd config func - */ - if (pldn_cmb1 == 2) { - di_pre_stru. - di_post_wr_buf->reg0_bmode = 3; - di_pre_stru. - di_post_wr_buf->reg1_bmode = 3; - di_pre_stru. - di_post_wr_buf->reg2_bmode = 3; - di_pre_stru. - di_post_wr_buf->reg3_bmode = 3; - } else if (pldn_cmb1 == 3) { - di_pre_stru. - di_post_wr_buf->reg0_bmode = 2; - di_pre_stru. - di_post_wr_buf->reg1_bmode = 2; - di_pre_stru. - di_post_wr_buf->reg2_bmode = 2; - di_pre_stru. - di_post_wr_buf->reg3_bmode = 2; - } else if (pldn_cmb1 == 4) { - di_pre_stru. - di_post_wr_buf->reg2_s = 202; - di_pre_stru. - di_post_wr_buf->reg2_e = 222; - di_pre_stru. - di_post_wr_buf->reg2_bmode = 0; - } - } - } else if ((pldn_cmb0 == 6) && (pldn_cmb1 == 6)) { - if (!IS_ERR_OR_NULL( - di_pre_stru.di_post_wr_buf)) { - di_pre_stru.di_post_wr_buf->reg1_s = 60; - di_pre_stru.di_post_wr_buf->reg1_e - = 180; - di_pre_stru.di_post_wr_buf->reg1_bmode - = 0; - } - } - } - field_count++; - if (field_count == 0x7fffffff) - field_count = 3; - if (di_pre_stru.cur_prog_flag) { if (di_pre_stru.prog_proc_type == 0) { /* di_mem_buf_dup->vfrme @@ -3612,7 +3020,6 @@ static void pre_de_done_buf_config(void) di_pre_stru.di_wr_buf = NULL; } } - } if (di_pre_stru.di_post_inp_buf && di_pre_rdma_enable) { #ifdef DI_BUFFER_DEBUG @@ -3620,10 +3027,10 @@ static void pre_de_done_buf_config(void) vframe_type_name[di_pre_stru.di_post_inp_buf->type], di_pre_stru.di_post_inp_buf->index); #endif - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); queue_in(di_pre_stru.di_post_inp_buf, QUEUE_RECYCLE); di_pre_stru.di_post_inp_buf = NULL; - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); } if (di_pre_stru.di_inp_buf) { if (!di_pre_rdma_enable) { @@ -3632,10 +3039,10 @@ static void pre_de_done_buf_config(void) vframe_type_name[di_pre_stru.di_inp_buf->type], di_pre_stru.di_inp_buf->index); #endif - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); queue_in(di_pre_stru.di_inp_buf, QUEUE_RECYCLE); di_pre_stru.di_inp_buf = NULL; - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); } else { di_pre_stru.di_post_inp_buf = di_pre_stru.di_inp_buf; di_pre_stru.di_inp_buf = NULL; @@ -3645,13 +3052,13 @@ static void pre_de_done_buf_config(void) static void recycle_vframe_type_pre(struct di_buf_s *di_buf) { - ulong flags = 0, fiq_flag = 0, irq_flag2 = 0; + ulong irq_flag2 = 0; - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); queue_in(di_buf, QUEUE_RECYCLE); - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); } /* * it depend on local buffer queue type is 2 @@ -3729,19 +3136,26 @@ static void pre_inp_canvas_config(struct vframe_s *vf) } } #endif - -static bool pre_de_proc(void) +static unsigned char pre_de_buf_config(void) { - int in_buf_num = 0, i = 0; - struct vframe_s *vframe = vf_peek(VFM_NAME); + struct di_buf_s *di_buf = NULL; + vframe_t *vframe; + int i, di_linked_buf_idx = -1; + unsigned char change_type = 0; + bool bit10_pack_patch = false; + unsigned int width_roundup = 2; - if (!vframe || di_blocking) - return false; + if (di_blocking || !atomic_read(&de_devp->mem_flag)) + return 0; + if ((list_count(QUEUE_IN_FREE) < 2 && (!di_pre_stru.di_inp_buf_next)) || + (queue_empty(QUEUE_LOCAL_FREE))) + return 0; - if (is_bypass(vframe)) { + if (is_bypass(NULL)) { /* some provider has problem if receiver * get all buffers of provider */ + int in_buf_num = 0; cur_lev = 0; for (i = 0; i < MAX_IN_BUF_NUM; i++) if (vframe_in[i] != NULL) @@ -3750,59 +3164,18 @@ static bool pre_de_proc(void) #ifdef DET3D && (di_pre_stru.vframe_interleave_flag == 0) #endif - ) - return false; - } -#ifdef CHECK_VDIN_BUF_ERROR - if (is_from_vdin(vframe)) { - if (vframe->canvas0Addr == - Rd_reg_bits((VDIN_WR_CTRL + 0), WR_CANVAS_BIT, - WR_CANVAS_WID)) - same_w_r_canvas_count++; -#ifdef RUN_DI_PROCESS_IN_IRQ - di_pre_stru.vdin2nr = is_input2pre(); -#endif - } -#endif - if ( - (vframe->source_type == VFRAME_SOURCE_TYPE_OTHERS) && - (vframe->width % 2 == 1)) { - force_width = vframe->width - 1; - if (force_width != (vframe->width - 1)) - pr_info("DI: force source width %u to even num %d.\n", - vframe->width, force_width); - } else { - force_width = 0; - } - - return true; - -} - -static unsigned char pre_de_buf_config(void) -{ - struct di_buf_s *di_buf = NULL; - vframe_t *vframe; - int di_linked_buf_idx = -1; - unsigned char change_type = 0; - - if ((list_count(QUEUE_IN_FREE) < 2 && (!di_pre_stru.di_inp_buf_next)) || - (queue_empty(QUEUE_LOCAL_FREE))) - return 0; - - if (di_pre_stru.prog_proc_type == 2) { + ) + return 0; + } else if (di_pre_stru.prog_proc_type == 2) { di_linked_buf_idx = peek_free_linked_buf(); - if (di_linked_buf_idx == -1 && used_post_buf_index != -1) { + if (di_linked_buf_idx == -1 && + !IS_ERR_OR_NULL(di_post_stru.keep_buf)) { recycle_keep_buffer(); pr_info("%s: recycle keep buffer for peek null linked buf\n", __func__); return 0; } } - - if (!pre_de_proc()) - return 0; - if (di_pre_stru.di_inp_buf_next) { di_pre_stru.di_inp_buf = di_pre_stru.di_inp_buf_next; di_pre_stru.di_inp_buf_next = NULL; @@ -3822,27 +3195,48 @@ static unsigned char pre_de_buf_config(void) } } else { /* check if source change */ + vframe = vf_peek(VFM_NAME); + + if (vframe && is_from_vdin(vframe)) { +#ifdef RUN_DI_PROCESS_IN_IRQ + di_pre_stru.vdin2nr = is_input2pre(); +#endif + } vframe = vf_get(VFM_NAME); if (vframe == NULL) return 0; - else { - #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC - pre_inp_canvas_config(vframe); - #endif - di_print("DI: get vframe[0x%p] from frontend %u ms.\n", - vframe, - jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); - } + di_print("DI: get %dth vf[0x%p] from frontend %u ms.\n", + di_pre_stru.in_seq, vframe, +jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64)); vframe->prog_proc_config = (prog_proc_config&0x20) >> 5; + + if (vframe->width > 10000 || vframe->height > 10000 || + hold_video || di_pre_stru.bad_frame_throw_count > 0) { + if (vframe->width > 10000 || vframe->height > 10000) + di_pre_stru.bad_frame_throw_count = 10; + di_pre_stru.bad_frame_throw_count--; + vf_put(vframe, VFM_NAME); + vf_notify_provider( + VFM_NAME, VFRAME_EVENT_RECEIVER_PUT, NULL); + return 0; + } + bit10_pack_patch = (is_meson_gxtvbb_cpu() || + is_meson_gxl_cpu() || + is_meson_gxm_cpu()); + width_roundup = bit10_pack_patch ? 16 : width_roundup; + if (di_force_bit_mode == 10) + force_width = roundup(vframe->width, width_roundup); + else + force_width = 0; di_pre_stru.source_trans_fmt = vframe->trans_fmt; di_pre_stru.left_right = di_pre_stru.left_right ? 0 : 1; di_pre_stru.invert_flag = (vframe->type & TB_DETECT_MASK) ? true : false; vframe->type &= ~TB_DETECT_MASK; - if (((invert_top_bot & 0x2) != 0 || + if ((((invert_top_bot & 0x2) != 0) || di_pre_stru.invert_flag) && (!is_progressive(vframe))) { if ( @@ -3855,16 +3249,14 @@ static unsigned char pre_de_buf_config(void) vframe->type |= VIDTYPE_INTERLACE_TOP; } } - + di_pre_stru.width_bk = vframe->width; if (force_width) vframe->width = force_width; - /* backup frame motion info */ vframe->combing_cur_lev = cur_lev; di_print("%s: vf_get => 0x%p\n", __func__, vframe); - provider_vframe_level--; di_buf = get_di_buf_head(QUEUE_IN_FREE); if (check_di_buf(di_buf, 10)) @@ -3920,18 +3312,20 @@ static unsigned char pre_de_buf_config(void) di_pre_stru.di_chan2_buf_dup_p = NULL; } /* force recycle keep buffer when switch source */ - if (used_post_buf_index != -1) { - if (di_buf_post[used_post_buf_index].vframe + if (!IS_ERR_OR_NULL(di_post_stru.keep_buf)) { + if (di_post_stru.keep_buf->vframe ->source_type != di_buf->vframe->source_type) { recycle_keep_buffer(); - pr_info("%s: source type changed!!!\n", + pr_info("%s: source type changed recycle buffer!!!\n", __func__); } } pr_info( - "%s: source change: 0x%x/%d/%d/%d=>0x%x/%d/%d/%d\n", + "%s:%ums %dth source change: 0x%x/%d/%d/%d=>0x%x/%d/%d/%d\n", __func__, + jiffies_to_msecs(jiffies_64), + di_pre_stru.in_seq, di_pre_stru.cur_inp_type, di_pre_stru.cur_width, di_pre_stru.cur_height, @@ -3959,10 +3353,7 @@ static unsigned char pre_de_buf_config(void) di_pre_stru.cur_sig_fmt = di_buf->vframe->sig_fmt; di_pre_stru.orientation = di_buf->vframe->video_angle; di_pre_stru.source_change_flag = 1; - di_pre_stru.same_field_source_flag = 0; -#if defined(NEW_DI_TV) - di_set_para_by_tvinfo(vframe); -#endif + di_pre_stru.input_size_change_flag = true; #ifdef SUPPORT_MPEG_TO_VDIN if ((!is_from_vdin(vframe)) && (vframe->sig_fmt == TVIN_SIG_FMT_NULL) && @@ -3978,9 +3369,7 @@ static unsigned char pre_de_buf_config(void) mpeg2vdin_flag = 1; } #endif -#ifdef NEW_DI_V1 di_pre_stru.field_count_for_cont = 0; -#endif } else if (di_pre_stru.cur_prog_flag == 0) { /* check if top/bot interleaved */ if (change_type == 2) @@ -3989,34 +3378,15 @@ static unsigned char pre_de_buf_config(void) if ((di_pre_stru.cur_inp_type & VIDTYPE_TYPEMASK) == (di_buf->vframe->type & VIDTYPE_TYPEMASK)) { -#ifdef CHECK_VDIN_BUF_ERROR if ((di_buf->vframe->type & VIDTYPE_TYPEMASK) == VIDTYPE_INTERLACE_TOP) same_field_top_count++; else same_field_bot_count++; -#endif - if (di_pre_stru.same_field_source_flag < - same_field_source_flag_th) { - /* some source's filed - * is top or bot always - */ - di_pre_stru.same_field_source_flag++; - - if (skip_wrong_field && - is_from_vdin(di_buf->vframe)) { - recycle_vframe_type_pre( - di_buf); - return 0; - } - } - - } else - di_pre_stru.same_field_source_flag = 0; + } di_pre_stru.cur_inp_type = di_buf->vframe->type; } else { - di_pre_stru.same_field_source_flag = 0; di_pre_stru.cur_inp_type = di_buf->vframe->type; } @@ -4075,6 +3445,7 @@ static unsigned char pre_de_buf_config(void) } top_bot_config(di_buf); + queue_in(di_buf, QUEUE_PRE_READY); /*if previous isn't bypass post_wr_buf not recycled */ if (di_pre_stru.di_post_wr_buf && di_pre_rdma_enable) { queue_in( @@ -4089,8 +3460,6 @@ static unsigned char pre_de_buf_config(void) di_buf->post_proc_flag = -2; else di_buf->post_proc_flag = 0; - - queue_in(di_buf, QUEUE_PRE_READY); #ifdef DI_BUFFER_DEBUG di_print( "%s: %s[%d] => pre_ready_list\n", __func__, @@ -4178,13 +3547,11 @@ static unsigned char pre_de_buf_config(void) } } } else { -#ifdef NEW_DI_V1 if ( di_pre_stru.di_chan2_buf_dup_p == NULL) { di_pre_stru.field_count_for_cont = 0; /* ignore contp2rd and contprd */ } -#endif di_buf->post_proc_flag = 1; di_pre_stru.di_inp_buf = di_buf; di_print("%s: %s[%d] => di_inp_buf\n", __func__, @@ -4285,9 +3652,11 @@ static unsigned char pre_de_buf_config(void) VIDTYPE_VIU_422 | VIDTYPE_VIU_SINGLE_PLANE | VIDTYPE_VIU_FIELD; + /*add for vpp skip line ref*/ + if (bypass_state == 0) + di_buf->vframe->type |= VIDTYPE_PRE_INTERLACE; } -/* */ if (is_bypass_post()) { if (bypass_post_state == 0) di_pre_stru.source_change_flag = 1; @@ -4300,7 +3669,6 @@ static unsigned char pre_de_buf_config(void) bypass_post_state = 0; } -/* if(is_progressive(di_pre_stru.di_inp_buf->vframe)){ */ if (di_pre_stru.di_inp_buf->post_proc_flag == 0) { di_pre_stru.enable_mtnwr = 0; di_pre_stru.enable_pulldown_check = 0; @@ -4310,19 +3678,12 @@ static unsigned char pre_de_buf_config(void) di_pre_stru.enable_pulldown_check = 0; di_buf->post_proc_flag = 0; } else { - if (di_pre_stru.di_chan2_buf_dup_p == NULL) { - di_pre_stru.enable_mtnwr = 0; - di_pre_stru.enable_pulldown_check = 0; - di_buf->post_proc_flag = 2; - } else { - di_pre_stru.enable_mtnwr = 1; - di_buf->post_proc_flag = 1; - di_pre_stru.enable_pulldown_check = - di_pre_stru.cur_prog_flag ? 0 : 1; - } + di_pre_stru.enable_mtnwr = 1; + di_buf->post_proc_flag = 1; + di_pre_stru.enable_pulldown_check = + di_pre_stru.cur_prog_flag ? 0 : 1; } -#ifndef USE_LIST if ((di_pre_stru.di_mem_buf_dup_p == di_pre_stru.di_wr_buf) || (di_pre_stru.di_chan2_buf_dup_p == di_pre_stru.di_wr_buf)) { pr_dbg("+++++++++++++++++++++++\n"); @@ -4332,7 +3693,6 @@ static unsigned char pre_de_buf_config(void) recovery_flag++; return 0; } -#endif return 1; } @@ -4356,12 +3716,13 @@ static int check_recycle_buf(void) vf_notify_provider(VFM_NAME, VFRAME_EVENT_RECEIVER_PUT, NULL); -#ifdef DI_BUFFER_DEBUG di_print( - "%s: vf_put(%d) %x\n", __func__, + "%s: vf_put(%d) %x, %u ms\n", + __func__, di_pre_stru.recycle_seq, - vframe_in[di_buf->index]); -#endif + vframe_in[di_buf->index], + jiffies_to_msecs(jiffies_64 - + vframe_in[di_buf->index]->ready_jiffies64)); vframe_in[di_buf->index] = NULL; } di_buf->invert_top_bot_flag = 0; @@ -4569,18 +3930,34 @@ static void get_mcinfo_from_reg_in_irq(void) } } } + +static unsigned int bit_reverse(unsigned int val) +{ + unsigned int i = 0, res = 0; + + for (i = 0; i < 16; i++) { + res |= (((val&(1<>i)<<(31-i)); + res |= (((val&(1<<(31-i)))<>(31-i)); + } + return res; +} + static void set_post_mcinfo(struct mcinfo_pre_s *curr_field_mcinfo) { - unsigned int i = 0; + unsigned int i = 0, value = 0; DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_REL_GAIN_OFFST_0, curr_field_mcinfo->highvertfrqflg, 24, 1); DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_REL_GAIN_OFFST_0, curr_field_mcinfo->motionparadoxflg, 25, 1); - for (i = 0; i < 26; i++) - DI_VSYNC_WR_MPEG_REG(0x2f78 + i, curr_field_mcinfo->regs[i]); + for (i = 0; i < 26; i++) { + if (overturn) + value = bit_reverse(curr_field_mcinfo->regs[i]); + else + value = curr_field_mcinfo->regs[i]; + DI_VSYNC_WR_MPEG_REG(0x2f78 + i, value); + } } - static irqreturn_t de_irq(int irq, void *dev_instance) { #ifndef CHECK_DI_DONE @@ -4618,9 +3995,14 @@ static irqreturn_t de_irq(int irq, void *dev_instance) #else DI_Wr(DI_INTR_CTRL, data32); #endif - if ((post_wr_en && post_wr_surpport) && (data32&0x4)) { + if ((post_wr_en && post_wr_support) && (data32&0x4)) { di_post_stru.de_post_process_done = 1; di_post_stru.post_de_busy = 0; + di_post_stru.irq_time = + (sched_clock()/NSEC_PER_MSEC - di_post_stru.irq_time); + trace_di_post("POST-IRQ-1", + di_post_stru.post_wr_cnt, + di_post_stru.irq_time); if (!(data32 & 0x2)) { DI_Wr(DI_INTR_CTRL, data32); goto end; @@ -4635,29 +4017,31 @@ static irqreturn_t de_irq(int irq, void *dev_instance) } if (flag) { - if (mcpre_en) + di_pre_stru.irq_time = + (sched_clock()/NSEC_PER_MSEC - di_pre_stru.irq_time); + trace_di_pre("PRE-IRQ-0", + di_pre_stru.field_count_for_cont, + di_pre_stru.irq_time); + if (mcpre_en) { get_mcinfo_from_reg_in_irq(); -#ifdef NEW_DI_V4 - if (dnr_en) - run_dnr_in_irq( - di_pre_stru.di_nrwr_mif.end_x + 1, - di_pre_stru.di_nrwr_mif.end_y + 1); - else - if ((Rd(DNR_CTRL) != 0) && dnr_reg_update) - DI_Wr(DNR_CTRL, 0); -#endif + if (is_meson_gxlx_cpu() || + is_meson_txhd_cpu()) + mc_pre_mv_irq(); + calc_lmv_base_mcinfo((di_pre_stru.cur_height>>1), + di_pre_stru.di_wr_buf->mcinfo_adr); + } + nr_process_in_irq(); /* disable mif */ - enable_di_pre_mif(0); + enable_di_pre_mif(false, mcpre_en); di_pre_stru.pre_de_process_done = 1; di_pre_stru.pre_de_busy = 0; end: - if (init_flag && mem_flag) + if (init_flag) /* pr_dbg("%s:up di sema\n", __func__); */ trigger_pre_di_process(TRIGGER_PRE_BY_DE_IRQ); } - di_print("DI:buf[%d] irq end.\n", di_pre_stru.di_inp_buf->seq); return IRQ_HANDLED; } @@ -4698,7 +4082,7 @@ static void dec_post_ref_count(struct di_buf_s *di_buf) recovery_flag++; return; } - if (di_buf->pulldown_mode == PULL_DOWN_BUF1) + if (di_buf->pd_config.global_mode == PULL_DOWN_BUF1) return; if (di_buf->di_buf_dup_p[1]) di_buf->di_buf_dup_p[1]->post_ref_count--; @@ -4764,12 +4148,14 @@ static void process_vscale_skip(struct di_buf_s *di_buf, vframe_t *disp_vf) (di_vscale_skip_enable & 0x5)) || (di_vscale_skip_enable >> 16) ) { - if ((di_vscale_skip_enable & 0x4) && !vpp_3d_mode) { - if (di_buf->di_buf_dup_p[1] && - di_buf->pulldown_mode != PULL_DOWN_BUF1) - di_buf->pulldown_mode = PULL_DOWN_EI; - } else { + if ((di_vscale_skip_enable & 0x8) || vpp_3d_mode) { vscale_skip_disable_post(di_buf, disp_vf); + } else { + if (di_buf->di_buf_dup_p[1] && + di_buf->pd_config.global_mode != + PULL_DOWN_BUF1) + di_buf->pd_config.global_mode = + PULL_DOWN_EI; } } } @@ -4836,13 +4222,14 @@ static int do_pre_only_fun(void *arg, vframe_t *disp_vf) canvas_height = di_buf->di_buf[0]->canvas_height; #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA - if ((is_vsync_rdma_enable() && - ((force_update_post_reg & 0x40) == 0)) || - (force_update_post_reg & 0x20)) { + if (is_vsync_rdma_enable()) { di_post_stru.canvas_id = di_post_stru.next_canvas_id; } else { di_post_stru.canvas_id = 0; di_post_stru.next_canvas_id = 1; + if (post_wr_en && post_wr_support) + di_post_stru.canvas_id = + di_post_stru.next_canvas_id; } #endif @@ -4881,65 +4268,6 @@ static int do_pre_only_fun(void *arg, vframe_t *disp_vf) return 0; } -static void config_fftffb_mode(struct di_buf_s *di_buf, - unsigned int *post_field_type, char fftffb_mode) -{ - unsigned char tmp_canvas_idx = 0; - - switch (fftffb_mode) { - case 1: - *post_field_type = - (di_buf->di_buf_dup_p[0]->vframe->type & - VIDTYPE_TYPEMASK) - == VIDTYPE_INTERLACE_TOP ? 0 : 1; - di_post_stru.di_buf0_mif.canvas0_addr0 = - di_buf->di_buf_dup_p[0]->nr_canvas_idx; - di_post_stru.di_buf1_mif.canvas0_addr0 = - di_buf->di_buf_dup_p[1]->nr_canvas_idx; - di_post_stru.di_buf2_mif.canvas0_addr0 = - di_buf->di_buf_dup_p[2]->nr_canvas_idx; - di_post_stru.di_mtnprd_mif.canvas_num = - di_buf->di_buf_dup_p[1]->mtn_canvas_idx; - break; - case 2: - *post_field_type = - (di_buf->di_buf_dup_p[2]->vframe->type & - VIDTYPE_TYPEMASK) - == VIDTYPE_INTERLACE_TOP ? 0 : 1; - di_post_stru.di_buf0_mif.canvas0_addr0 = - di_buf->di_buf_dup_p[2]->nr_canvas_idx; - di_post_stru.di_buf1_mif.canvas0_addr0 = - di_buf->di_buf_dup_p[0]->nr_canvas_idx; - di_post_stru.di_buf2_mif.canvas0_addr0 = - di_buf->di_buf_dup_p[1]->nr_canvas_idx; - di_post_stru.di_mtnprd_mif.canvas_num = - di_buf->di_buf_dup_p[1]->mtn_canvas_idx; - break; - default: - *post_field_type = - (di_buf->di_buf_dup_p[1]->vframe->type & - VIDTYPE_TYPEMASK) - == VIDTYPE_INTERLACE_TOP ? 0 : 1; - di_post_stru.di_buf0_mif.canvas0_addr0 = - di_buf->di_buf_dup_p[1]->nr_canvas_idx; - di_post_stru.di_buf1_mif.canvas0_addr0 = - di_buf->di_buf_dup_p[0]->nr_canvas_idx; - di_post_stru.di_buf2_mif.canvas0_addr0 = - di_buf->di_buf_dup_p[2]->nr_canvas_idx; - di_post_stru.di_mtnprd_mif.canvas_num = - di_buf->di_buf_dup_p[2]->mtn_canvas_idx; - break; - } - if (is_meson_txl_cpu() && overturn) { - /* swap if1&if2 mean negation of mv */ - tmp_canvas_idx = di_post_stru.di_buf1_mif.canvas0_addr0; - di_post_stru.di_buf1_mif.canvas0_addr0 = - di_post_stru.di_buf2_mif.canvas0_addr0; - di_post_stru.di_buf2_mif.canvas0_addr0 = tmp_canvas_idx; - } - -} - static void get_vscale_skip_count(unsigned int par) { di_vscale_skip_count_real = (par >> 24) & 0xff; @@ -4948,15 +4276,6 @@ static void get_vscale_skip_count(unsigned int par) #define get_vpp_reg_update_flag(par) ((par >> 16) & 0x1) static unsigned int pldn_dly = 1; -static unsigned int tbbtff_dly; - -static unsigned int pldn_wnd_flsh = 1; -module_param(pldn_wnd_flsh, uint, 0644); -MODULE_PARM_DESC(pldn_wnd_flsh, "/n reflesh the window./n"); - -static unsigned int pldn_pst_set; -module_param(pldn_pst_set, uint, 0644); -MODULE_PARM_DESC(pldn_pst_set, "/n pulldown post setting./n"); static unsigned int post_blend; module_param(post_blend, uint, 0664); @@ -4971,23 +4290,21 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, { struct di_buf_s *di_buf = (struct di_buf_s *)arg; struct di_buf_s *di_pldn_buf = NULL; - unsigned int di_width, di_height, di_start_x, di_end_x; + unsigned int di_width, di_height, di_start_x, di_end_x, mv_offset; unsigned int di_start_y, di_end_y, hold_line = post_hold_line; unsigned int post_blend_en = 0, post_blend_mode = 0, blend_mtn_en = 0, ei_en = 0, post_field_num = 0; int di_vpp_en, di_ddr_en; + unsigned char mc_pre_flag = 0; + bool invert_mv = false; + static int post_index = -1; - if ((di_get_power_control(1) == 0) || di_post_stru.vscale_skip_flag) + if (di_post_stru.vscale_skip_flag) return 0; - if (is_in_queue(di_buf, QUEUE_POST_FREE)) { - pr_info("%s post_buf[%d] is in post free list.\n", - __func__, di_buf->index); - return 0; - } + get_vscale_skip_count(zoom_start_x_lines); - if ((!di_post_stru.toggle_flag) && - ((force_update_post_reg & 0x10) == 0)) + if (!di_post_stru.toggle_flag) return 0; if (IS_ERR_OR_NULL(di_buf)) @@ -4996,6 +4313,14 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, return 0; di_pldn_buf = di_buf->di_buf_dup_p[pldn_dly]; + if (is_in_queue(di_buf, QUEUE_POST_FREE) && + post_index != di_buf->index) { + post_index = di_buf->index; + pr_info("%s post_buf[%d] is in post free list.\n", + __func__, di_buf->index); + return 0; + } + if (di_post_stru.toggle_flag && di_buf->di_buf_dup_p[1]) top_bot_config(di_buf->di_buf_dup_p[1]); @@ -5003,15 +4328,8 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, di_post_stru.cur_disp_index = di_buf->index; - if ((di_post_stru.post_process_fun_index != 1) || - ((force_update_post_reg & 0xf) != 0)) { - force_update_post_reg &= ~0x1; - di_post_stru.post_process_fun_index = 1; - di_post_stru.update_post_reg_flag = update_post_reg_count; - } - if (get_vpp_reg_update_flag(zoom_start_x_lines)) - di_post_stru.update_post_reg_flag = update_post_reg_count; + di_post_stru.update_post_reg_flag = 1; /* pr_dbg("%s set update_post_reg_flag to %d\n", __func__, * di_post_stru.update_post_reg_flag); */ @@ -5021,8 +4339,7 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, zoom_start_y_lines = zoom_start_y_lines & 0xffff; zoom_end_y_lines = zoom_end_y_lines & 0xffff; - if (((init_flag == 0) || (mem_flag == 0)) && - (new_keep_last_frame_enable == 0)) + if (init_flag == 0 && IS_ERR_OR_NULL(di_post_stru.keep_buf)) return 0; di_start_x = zoom_start_x_lines; @@ -5046,7 +4363,9 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, (di_post_stru.di_buf0_mif.luma_y_start0 != di_start_y / 2)) { di_post_stru.buf_type = di_buf->di_buf_dup_p[0]->type; - initial_di_post_2(di_width, di_height, hold_line); + initial_di_post_2(di_width, di_height, + hold_line, + (post_wr_en && post_wr_support)); if ((di_buf->di_buf_dup_p[0]->vframe == NULL) || (di_buf->vframe == NULL)) @@ -5060,18 +4379,24 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, (di_buf->vframe->bitdepth & FULL_PACK_422_MODE)?3:2; di_post_stru.di_buf2_mif.bit_mode = (di_buf->vframe->bitdepth & FULL_PACK_422_MODE)?3:2; + di_post_stru.di_diwr_mif.bit_mode = + (di_buf->vframe->bitdepth & FULL_PACK_422_MODE)?3:2; + } else { di_post_stru.di_buf0_mif.bit_mode = (di_buf->vframe->bitdepth & FULL_PACK_422_MODE)?3:1; di_post_stru.di_buf1_mif.bit_mode = (di_buf->vframe->bitdepth & FULL_PACK_422_MODE)?3:1; di_post_stru.di_buf2_mif.bit_mode = + (di_buf->vframe->bitdepth & FULL_PACK_422_MODE)?3:1; + di_post_stru.di_diwr_mif.bit_mode = (di_buf->vframe->bitdepth & FULL_PACK_422_MODE)?3:1; } } else { di_post_stru.di_buf0_mif.bit_mode = 0; di_post_stru.di_buf1_mif.bit_mode = 0; di_post_stru.di_buf2_mif.bit_mode = 0; + di_post_stru.di_diwr_mif.bit_mode = 0; } if (di_buf->vframe->type & VIDTYPE_VIU_444) { di_post_stru.di_buf0_mif.video_mode = 1; @@ -5117,7 +4442,7 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, di_post_stru.di_buf2_mif.luma_x_start0 = di_start_x; di_post_stru.di_buf2_mif.luma_x_end0 = di_end_x; - if ((post_wr_en && post_wr_surpport)) { + if (post_wr_en && post_wr_support) { di_post_stru.di_diwr_mif.start_x = di_start_x; di_post_stru.di_diwr_mif.end_x = di_end_x; di_post_stru.di_diwr_mif.start_y = di_start_y; @@ -5130,34 +4455,36 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, di_post_stru.di_mtnprd_mif.end_y = di_end_y >> 1; if (mcpre_en) { di_post_stru.di_mcvecrd_mif.start_x = di_start_x / 5; + mv_offset = (di_start_x % 5) ? (5 - di_start_x % 5) : 0; di_post_stru.di_mcvecrd_mif.vecrd_offset = - ((di_start_x % 5) ? (5 - di_start_x % 5) : 0); + overturn ? (di_end_x + 1) % 5 : mv_offset; di_post_stru.di_mcvecrd_mif.start_y = (di_start_y >> 1); di_post_stru.di_mcvecrd_mif.size_x = (di_end_x + 1 + 4) / 5 - 1 - di_start_x / 5; - di_post_stru.di_mcvecrd_mif.size_y = - (di_height >> 1) - 1; + di_post_stru.di_mcvecrd_mif.end_y = + (di_end_y >> 1); } - di_post_stru.update_post_reg_flag = update_post_reg_count; + di_post_stru.update_post_reg_flag = 1; /* if height decrease, mtn will not enough */ - if (di_buf->pulldown_mode != PULL_DOWN_BUF1) - di_buf->pulldown_mode = PULL_DOWN_EI; + if (di_buf->pd_config.global_mode != PULL_DOWN_BUF1) + di_buf->pd_config.global_mode = PULL_DOWN_EI; } #ifdef DI_USE_FIXED_CANVAS_IDX #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA - if ((is_vsync_rdma_enable() && - ((force_update_post_reg & 0x40) == 0)) || - (force_update_post_reg & 0x20)) { + if (is_vsync_rdma_enable()) { di_post_stru.canvas_id = di_post_stru.next_canvas_id; } else { di_post_stru.canvas_id = 0; di_post_stru.next_canvas_id = 1; + if (post_wr_en && post_wr_support) + di_post_stru.canvas_id = + di_post_stru.next_canvas_id; } #endif - post_blend = di_buf->pulldown_mode; - switch (di_buf->pulldown_mode) { + post_blend = di_buf->pd_config.global_mode; + switch (post_blend) { case PULL_DOWN_BLEND_0: case PULL_DOWN_NORMAL: config_canvas_idx( @@ -5176,13 +4503,9 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, config_mcvec_canvas_idx( di_buf->di_buf_dup_p[2], di_post_idx[di_post_stru.canvas_id][4]); - - /* for post_wr_en */ - if ((post_wr_en && post_wr_surpport) && !mcpre_en) - config_canvas_idx( - di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); break; case PULL_DOWN_BLEND_2: + case PULL_DOWN_NORMAL_2: config_canvas_idx( di_buf->di_buf_dup_p[0], di_post_idx[di_post_stru.canvas_id][3], -1); @@ -5199,9 +4522,6 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, config_mcvec_canvas_idx( di_buf->di_buf_dup_p[2], di_post_idx[di_post_stru.canvas_id][4]); - if ((post_wr_en && post_wr_surpport) && !mcpre_en) - config_canvas_idx( - di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); break; case PULL_DOWN_MTN: config_canvas_idx( @@ -5213,9 +4533,6 @@ de_post_process(void *arg, unsigned int zoom_start_x_lines, config_canvas_idx( di_buf->di_buf_dup_p[0], di_post_idx[di_post_stru.canvas_id][1], -1); - if ((post_wr_en && post_wr_surpport)) - config_canvas_idx( -di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); break; case PULL_DOWN_BUF1:/* wave with buf1 */ config_canvas_idx( @@ -5227,18 +4544,12 @@ di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); config_canvas_idx( di_buf->di_buf_dup_p[0], di_post_idx[di_post_stru.canvas_id][1], -1); - if ((post_wr_en && post_wr_surpport)) - config_canvas_idx( -di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); break; case PULL_DOWN_EI: if (di_buf->di_buf_dup_p[1]) config_canvas_idx( di_buf->di_buf_dup_p[1], di_post_idx[di_post_stru.canvas_id][0], -1); - if ((post_wr_en && post_wr_surpport)) - config_canvas_idx( -di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); break; default: break; @@ -5250,23 +4561,36 @@ di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); if ((di_buf->di_buf_dup_p[1]->vframe == NULL) || di_buf->di_buf_dup_p[0]->vframe == NULL) return 0; - switch (di_buf->pulldown_mode) { + switch (post_blend) { case PULL_DOWN_BLEND_0: case PULL_DOWN_NORMAL: - config_fftffb_mode(di_buf, &post_field_num, - (di_buf->di_buf_dup_p[tbbtff_dly]->privated&0x3)); - if (mcpre_en) - di_post_stru.di_mcvecrd_mif.canvas_num = - di_buf->di_buf_dup_p[2]->mcvec_canvas_idx; - if (di_buf->pulldown_mode == PULL_DOWN_NORMAL) + post_field_num = + (di_buf->di_buf_dup_p[1]->vframe->type & + VIDTYPE_TYPEMASK) + == VIDTYPE_INTERLACE_TOP ? 0 : 1; + di_post_stru.di_buf0_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[1]->nr_canvas_idx; + di_post_stru.di_buf1_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[0]->nr_canvas_idx; + di_post_stru.di_buf2_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[2]->nr_canvas_idx; + di_post_stru.di_mtnprd_mif.canvas_num = + di_buf->di_buf_dup_p[2]->mtn_canvas_idx; + mc_pre_flag = (overturn?0:1); + if (di_buf->pd_config.global_mode == PULL_DOWN_NORMAL) post_blend_mode = 3; else post_blend_mode = 1; + if (mcpre_en) { + di_post_stru.di_mcvecrd_mif.canvas_num = + di_buf->di_buf_dup_p[2]->mcvec_canvas_idx; + } blend_mtn_en = 1; post_ei = ei_en = 1; post_blend_en = 1; break; case PULL_DOWN_BLEND_2: + case PULL_DOWN_NORMAL_2: post_field_num = (di_buf->di_buf_dup_p[1]->vframe->type & VIDTYPE_TYPEMASK) @@ -5279,15 +4603,21 @@ di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); di_buf->di_buf_dup_p[0]->nr_canvas_idx; di_post_stru.di_mtnprd_mif.canvas_num = di_buf->di_buf_dup_p[2]->mtn_canvas_idx; - if (mcpre_en) + if (mcpre_en) { di_post_stru.di_mcvecrd_mif.canvas_num = di_buf->di_buf_dup_p[2]->mcvec_canvas_idx; - - if ((post_wr_en && post_wr_surpport)) - di_post_stru.di_diwr_mif.canvas_num = - di_post_idx[di_post_stru.canvas_id][4]; - - post_blend_mode = 1; + mc_pre_flag = (overturn?1:0); + if (is_meson_txlx_cpu() || is_meson_gxlx_cpu() || + is_meson_txhd_cpu()) + invert_mv = true; + else if (!overturn) + di_post_stru.di_buf2_mif.canvas0_addr0 = + di_buf->di_buf_dup_p[2]->nr_canvas_idx; + } + if (di_buf->pd_config.global_mode == PULL_DOWN_NORMAL_2) + post_blend_mode = 3; + else + post_blend_mode = 1; blend_mtn_en = 1; post_ei = ei_en = 1; post_blend_en = 1; @@ -5303,9 +4633,6 @@ di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); di_buf->di_buf_dup_p[0]->nr_canvas_idx; di_post_stru.di_mtnprd_mif.canvas_num = di_buf->di_buf_dup_p[2]->mtn_canvas_idx; - if ((post_wr_en && post_wr_surpport)) - di_post_stru.di_diwr_mif.canvas_num = - di_post_idx[di_post_stru.canvas_id][4]; post_blend_mode = 0; blend_mtn_en = 1; post_ei = ei_en = 1; @@ -5322,9 +4649,6 @@ di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); di_buf->di_buf_dup_p[1]->mtn_canvas_idx; di_post_stru.di_buf1_mif.canvas0_addr0 = di_buf->di_buf_dup_p[0]->nr_canvas_idx; - if ((post_wr_en && post_wr_surpport)) - di_post_stru.di_diwr_mif.canvas_num = - di_post_idx[di_post_stru.canvas_id][4]; post_blend_mode = 1; blend_mtn_en = 0; post_ei = ei_en = 0; @@ -5346,9 +4670,6 @@ di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); di_post_stru.di_buf0_mif.src_field_mode = post_field_num; } - if ((post_wr_en && post_wr_surpport)) - di_post_stru.di_diwr_mif.canvas_num = - di_post_idx[di_post_stru.canvas_id][4]; post_blend_mode = 2; blend_mtn_en = 0; post_ei = ei_en = 1; @@ -5358,7 +4679,10 @@ di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); break; } - if ((post_wr_en && post_wr_surpport)) { + if (post_wr_en && post_wr_support) { + config_canvas_idx(di_buf, + di_post_idx[di_post_stru.canvas_id][5], -1); + di_post_stru.di_diwr_mif.canvas_num = di_buf->nr_canvas_idx; di_vpp_en = 0; di_ddr_en = 1; } else { @@ -5368,9 +4692,9 @@ di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); /* if post size < MIN_POST_WIDTH, force ei */ if ((di_width < MIN_BLEND_WIDTH) && - (di_buf->pulldown_mode == PULL_DOWN_BLEND_0 || - di_buf->pulldown_mode == PULL_DOWN_BLEND_2 || - di_buf->pulldown_mode == PULL_DOWN_NORMAL + (di_buf->pd_config.global_mode == PULL_DOWN_BLEND_0 || + di_buf->pd_config.global_mode == PULL_DOWN_BLEND_2 || + di_buf->pd_config.global_mode == PULL_DOWN_NORMAL )) { post_blend_mode = 1; blend_mtn_en = 0; @@ -5379,16 +4703,14 @@ di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); } if (mcpre_en) - di_post_stru.di_mcvecrd_mif.blend_mode = post_blend_mode; - - if ((di_post_stru.update_post_reg_flag) && - ((force_update_post_reg & 0x80) == 0)) { + di_post_stru.di_mcvecrd_mif.blend_en = post_blend_en; + invert_mv = overturn ? (!invert_mv) : invert_mv; + if (di_post_stru.update_post_reg_flag) { enable_di_post_2( &di_post_stru.di_buf0_mif, &di_post_stru.di_buf1_mif, &di_post_stru.di_buf2_mif, - (di_ddr_en ? - (&di_post_stru.di_diwr_mif):NULL), + &di_post_stru.di_diwr_mif, &di_post_stru.di_mtnprd_mif, ei_en, /* ei enable */ post_blend_en, /* blend enable */ @@ -5398,20 +4720,22 @@ di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); di_ddr_en, /* di_ddr_en. */ post_field_num, /* 1 bottom generate top */ hold_line, - post_urgent + post_urgent, + (invert_mv?1:0), + di_vscale_skip_count_real ); if (mcpre_en) enable_mc_di_post( &di_post_stru.di_mcvecrd_mif, post_urgent, - overturn); - else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu()) + overturn, (invert_mv?1:0)); + else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 0, 2); } else { di_post_switch_buffer( &di_post_stru.di_buf0_mif, &di_post_stru.di_buf1_mif, &di_post_stru.di_buf2_mif, -(di_ddr_en ? (&di_post_stru.di_diwr_mif):NULL), + &di_post_stru.di_diwr_mif, &di_post_stru.di_mtnprd_mif, &di_post_stru.di_mcvecrd_mif, ei_en, /* ei enable */ @@ -5422,24 +4746,26 @@ di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); di_ddr_en, /* di_ddr_en. */ post_field_num, /* 1 bottom generate top */ hold_line, - post_urgent + post_urgent, + (invert_mv?1:0), + pulldown_enable, + mcpre_en, + di_vscale_skip_count_real ); } -#ifdef NEW_DI_V1 - if (di_post_stru.update_post_reg_flag && (!combing_fix_en)) { - di_apply_reg_cfg(1); - last_lev = -1; + if (is_meson_txlx_cpu() || + is_meson_gxlx_cpu()) { + di_post_read_reverse_irq(overturn, mc_pre_flag, mcpre_en); + /* disable mc for first 2 fieldes mv unreliable */ + if (di_buf->seq < 2) + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 0, 2); } - -#endif - if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu()) - di_post_read_reverse_irq(overturn); if (mcpre_en) { if (di_buf->di_buf_dup_p[2]) set_post_mcinfo(&di_buf->di_buf_dup_p[2] ->curr_field_mcinfo); - } else if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu()) + } else if (is_meson_gxlx_cpu() || is_meson_txlx_cpu()) DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 0, 2); @@ -5447,77 +4773,14 @@ di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); if (di_pldn_buf && pulldown_enable && !di_pre_stru.cur_prog_flag) { - if (pldn_wnd_flsh == 1) { - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG0_Y, - di_pldn_buf->reg0_s, 17, 12); - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG0_Y, - di_pldn_buf->reg0_e, 1, 12); + unsigned short offset = (di_start_y>>1); - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG1_Y, - di_pldn_buf->reg1_s, 17, 12); - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG1_Y, - di_pldn_buf->reg1_e, 1, 12); - - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG2_Y, - di_pldn_buf->reg2_s, 17, 12); - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG2_Y, - di_pldn_buf->reg2_e, 1, 12); - - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG3_Y, - di_pldn_buf->reg3_s, 17, 12); - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG3_Y, - di_pldn_buf->reg3_e, 1, 12); - -/* region0 */ - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, - (di_pldn_buf->reg0_e > di_pldn_buf->reg0_s) - ? 1 : 0, 16, 1); - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, - di_pldn_buf->reg0_bmode, 8, 2); - - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, - (di_pldn_buf->reg1_e > di_pldn_buf->reg1_s) - ? 1 : 0, 17, 1); - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, - di_pldn_buf->reg1_bmode, 10, 2); - - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, - (di_pldn_buf->reg2_e > di_pldn_buf->reg2_s) - ? 1 : 0, 18, 1); - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, - di_pldn_buf->reg2_bmode, 12, 2); - - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, - (di_pldn_buf->reg3_e > di_pldn_buf->reg3_s) - ? 1 : 0, 19, 1); - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, - di_pldn_buf->reg3_bmode, 14, 2); - } else if (pldn_wnd_flsh == 2) { - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG0_Y, 479); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG1_Y, 160); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG2_Y, 320 << 16 | 160); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG3_Y, 479 << 16 | 320); - RDMA_WR(DI_BLEND_CTRL, 0x81f00019); /* normal */ - } - - if (pldn_pst_set == 1) { - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, 1, 17, 1); -/* weaver */ - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, 1, 10, 2); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG1_Y, 120); - } else if (pldn_pst_set == 2) { - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, 1, 18, 1); -/* bob */ - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, 2, 12, 2); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG2_Y, 120); - } else if (pldn_pst_set == 3) { - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, 1, 19, 1); -/* bob mtn */ - DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, 0, 14, 2); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG3_Y, 120); - } else if (pldn_pst_set == 5) { - RDMA_WR(DI_BLEND_CTRL, 0x81f00019); /* normal */ - } + if (overturn) + offset = ((di_buf->vframe->height - di_end_y)>>1); + else + offset = 0; + pulldown_vof_win_vshift(&di_pldn_buf->pd_config, offset); + pulldown_vof_win_config(&di_pldn_buf->pd_config); } if (di_post_stru.update_post_reg_flag > 0) @@ -5528,17 +4791,17 @@ di_buf, di_post_idx[di_post_stru.canvas_id][4], -1); static void post_de_done_buf_config(void) { - ulong flags = 0, fiq_flag = 0, irq_flag2 = 0; + ulong irq_flag2 = 0; struct di_buf_s *di_buf = NULL; if (di_post_stru.cur_post_buf == NULL) return; - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); queue_out(di_post_stru.cur_post_buf); di_buf = di_post_stru.cur_post_buf; queue_in(di_post_stru.cur_post_buf, QUEUE_POST_READY); - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); vf_notify_receiver(VFM_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); di_post_stru.cur_post_buf = NULL; @@ -5560,11 +4823,18 @@ static void di_post_process(void) vf_p->early_process_fun( vf_p->private_data, vf_p); } - if (di_buf->process_fun_index) + if (di_buf->process_fun_index) { + RDMA_WR_BITS(DI_INTR_CTRL, 0, 18, 1); + RDMA_WR_BITS(DI_INTR_CTRL, 0, 2, 1); + di_post_stru.post_wr_cnt++; de_post_process( di_buf, 0, vf_p->width-1, 0, vf_p->height-1, vf_p); di_post_stru.post_de_busy = 1; + di_post_stru.irq_time = sched_clock()/NSEC_PER_MSEC; + } else { + di_post_stru.de_post_process_done = 1; + } di_post_stru.cur_post_buf = di_buf; } } @@ -5616,7 +4886,6 @@ recycle_vframe_type_post_print(struct di_buf_s *di_buf, #endif static int debug_blend_mode = -1; static unsigned int pldn_dly1 = 1; -static unsigned int pldn_pst_wver = 5; static void set_pulldown_mode(struct di_buf_s *di_buf) { struct di_buf_s *pre_buf_p = di_buf->di_buf_dup_p[pldn_dly1]; @@ -5624,29 +4893,25 @@ static void set_pulldown_mode(struct di_buf_s *di_buf) if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXBB)) { if (pulldown_enable && !di_pre_stru.cur_prog_flag) { if (pre_buf_p) { - di_buf->pulldown_mode = - pre_buf_p->pulldown_mode; + di_buf->pd_config.global_mode = + pre_buf_p->pd_config.global_mode; } else { pr_err("DI[%s]: index out of range.\n", __func__); } } else { - di_buf->pulldown_mode = PULL_DOWN_NORMAL; - } - if (pldn_pst_wver != 5) { - if (pldn_pst_wver > 5) - pldn_pst_wver = 5; - di_buf->pulldown_mode = pldn_pst_wver; + di_buf->pd_config.global_mode + = PULL_DOWN_NORMAL; } } } void drop_frame(int check_drop, int throw_flag, struct di_buf_s *di_buf) { - ulong flags = 0, fiq_flag = 0, irq_flag2 = 0; + ulong irq_flag2 = 0; int i = 0, drop_flag = 0; - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); if ((frame_count == 0) && check_drop) di_post_stru.start_pts = di_buf->vframe->pts; if ((check_drop && (frame_count < start_frame_drop_count)) @@ -5680,17 +4945,17 @@ void drop_frame(int check_drop, int throw_flag, struct di_buf_s *di_buf) __LINE__); #endif } else { - if ((post_wr_en && post_wr_surpport)) + if (post_wr_en && post_wr_support) queue_in(di_buf, QUEUE_POST_DOING); else queue_in(di_buf, QUEUE_POST_READY); - di_print("DI:%s[%d] => post ready %u ms.\n", - vframe_type_name[di_buf->type], di_buf->index, + di_print("DI:%dth %s[%d] => post ready %u ms.\n", + frame_count, vframe_type_name[di_buf->type], di_buf->index, jiffies_to_msecs(jiffies_64 - di_buf->vframe->ready_jiffies64)); } - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); } static int process_post_vframe(void) @@ -5702,7 +4967,7 @@ static int process_post_vframe(void) * 2) get buf from pre_ready_list, attach it to buf from post_free_list * (it will be send to recycle_list in di_vf_put() ) */ - ulong flags = 0, fiq_flag = 0, irq_flag2 = 0; + ulong irq_flag2 = 0; int i = 0; int ret = 0; int buffer_keep_count = 3; @@ -5747,13 +5012,13 @@ static int process_post_vframe(void) } if (ready_di_buf->post_proc_flag > 0) { if (ready_count >= buffer_keep_count) { - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); di_buf = get_di_buf_head(QUEUE_POST_FREE); if (check_di_buf(di_buf, 17)) return 0; queue_out(di_buf); - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); i = 0; queue_for_each_entry( @@ -5782,18 +5047,18 @@ static int process_post_vframe(void) di_buf->di_buf[0] = di_buf->di_buf_dup_p[0]; di_buf->di_buf[1] = NULL; queue_out(di_buf->di_buf[0]); - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); queue_in(di_buf, QUEUE_TMP); recycle_vframe_type_post(di_buf); - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); #ifdef DI_BUFFER_DEBUG di_print("%s : ", __func__); #endif } else { if (di_buf->di_buf_dup_p[1]-> post_proc_flag == 2){ - di_buf->pulldown_mode + di_buf->pd_config.global_mode = PULL_DOWN_BLEND_2; /* blend with di_buf->di_buf_dup_p[2] */ } else { @@ -5803,7 +5068,9 @@ static int process_post_vframe(void) VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_422 | VIDTYPE_VIU_SINGLE_PLANE | - VIDTYPE_VIU_FIELD; + VIDTYPE_VIU_FIELD | + VIDTYPE_PRE_INTERLACE; + di_buf->vframe->width = di_pre_stru.width_bk; if ( di_buf->di_buf_dup_p[1]-> new_format_flag) { @@ -5825,8 +5092,9 @@ static int process_post_vframe(void) di_buf->vframe->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_422 | - VIDTYPE_VIU_SINGLE_PLANE - | VIDTYPE_VIU_FIELD; + VIDTYPE_VIU_SINGLE_PLANE | + VIDTYPE_VIU_FIELD | + VIDTYPE_PRE_INTERLACE; di_buf->vframe->height >>= 1; di_buf->vframe->canvas0Addr = di_buf->di_buf_dup_p[0] @@ -5841,11 +5109,11 @@ static int process_post_vframe(void) } else { /*for debug*/ if (debug_blend_mode != -1) - di_buf->pulldown_mode = - debug_blend_mode; + di_buf->pd_config.global_mode + = debug_blend_mode; di_buf->vframe->process_fun = -((post_wr_en && post_wr_surpport) ? NULL : de_post_process); +((post_wr_en && post_wr_support) ? NULL : de_post_process); di_buf->process_fun_index = PROCESS_FUN_DI; inc_post_ref_count(di_buf); @@ -5865,7 +5133,7 @@ static int process_post_vframe(void) #ifdef DI_BUFFER_DEBUG di_print("%s : ", __func__); #endif - if (!(post_wr_en && post_wr_surpport)) + if (!(post_wr_en && post_wr_support)) vf_notify_receiver(VFM_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } @@ -5895,13 +5163,13 @@ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); if (ready_count >= vframe_process_count) { struct di_buf_s *di_buf_i; - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); di_buf = get_di_buf_head(QUEUE_POST_FREE); if (check_di_buf(di_buf, 19)) return 0; queue_out(di_buf); - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); i = 0; queue_for_each_entry( @@ -5946,6 +5214,7 @@ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); memcpy(di_buf->vframe, di_buf_i->vframe, sizeof(vframe_t)); + di_buf->vframe->width = di_pre_stru.width_bk; di_buf->vframe->private_data = di_buf; if (ready_di_buf->new_format_flag && @@ -5972,17 +5241,17 @@ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); di_buf->vframe->type &= ~(VIDTYPE_TYPEMASK); di_buf->vframe->process_fun -= (post_wr_en && post_wr_surpport)?NULL:de_post_process; += (post_wr_en && post_wr_support)?NULL:de_post_process; di_buf->process_fun_index = PROCESS_FUN_DI; - di_buf->pulldown_mode + di_buf->pd_config.global_mode = PULL_DOWN_EI; } else { di_buf->vframe->process_fun = NULL; di_buf->process_fun_index = PROCESS_FUN_NULL; - di_buf->pulldown_mode = + di_buf->pd_config.global_mode = PULL_DOWN_NORMAL; } di_buf->di_buf[0] = ready_di_buf; @@ -5996,10 +5265,6 @@ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); queue_out(di_buf->di_buf[1]); } #endif - if ((check_start_drop_prog && - is_progressive(ready_di_buf->vframe)) - || !is_progressive(ready_di_buf->vframe)) - check_drop = true; drop_frame(check_drop, di_buf->di_buf[0]->throw_flag, di_buf); @@ -6021,14 +5286,14 @@ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); */ unsigned char prog_tb_field_proc_type = (prog_proc_config >> 1) & 0x3; - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); di_buf = get_di_buf_head(QUEUE_POST_FREE); if (check_di_buf(di_buf, 20)) return 0; queue_out(di_buf); - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); i = 0; queue_for_each_entry( @@ -6063,7 +5328,8 @@ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_422 | VIDTYPE_VIU_SINGLE_PLANE | - VIDTYPE_VIU_FIELD; + VIDTYPE_VIU_FIELD | + VIDTYPE_PRE_INTERLACE; if ( di_buf->di_buf_dup_p[0]-> new_format_flag) @@ -6075,9 +5341,10 @@ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); early_process_fun = do_nothing_fun; - di_buf->pulldown_mode = PULL_DOWN_BUF1; + di_buf->pd_config.global_mode = + PULL_DOWN_BUF1; di_buf->vframe->process_fun = -(post_wr_en && post_wr_surpport)?NULL:de_post_process; +(post_wr_en && post_wr_support)?NULL:de_post_process; di_buf->process_fun_index = PROCESS_FUN_DI; } else if (prog_tb_field_proc_type == 0) { @@ -6117,8 +5384,10 @@ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_422 | VIDTYPE_VIU_SINGLE_PLANE | - VIDTYPE_VIU_FIELD; + VIDTYPE_VIU_FIELD | + VIDTYPE_PRE_INTERLACE; di_buf->vframe->height >>= 1; + di_buf->vframe->width = di_pre_stru.width_bk; if ( (di_buf->di_buf_dup_p[0]-> new_format_flag) || @@ -6157,8 +5426,7 @@ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); VIDTYPE_INTERLACE_BOTTOM) { di_buf->di_buf[1] = di_buf->di_buf_dup_p[1] = NULL; - di_lock_irqfiq_save(irq_flag2, - fiq_flag); + di_lock_irqfiq_save(irq_flag2); queue_in(di_buf, QUEUE_TMP); recycle_vframe_type_post(di_buf); pr_dbg("%s drop field %d.\n", __func__, @@ -6211,32 +5479,39 @@ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); */ static void di_unreg_process(void) { + unsigned long start_jiffes = 0; if (reg_flag) { - field_count = 0; + pr_dbg("%s unreg start %d.\n", __func__, reg_flag); + start_jiffes = jiffies_64; vf_unreg_provider(&di_vf_prov); - reg_flag = 0; + pr_dbg("%s vf unreg cost %u ms.\n", __func__, + jiffies_to_msecs(jiffies_64 - start_jiffes)); unreg_cnt++; if (unreg_cnt > 0x3fffffff) unreg_cnt = 0; - di_print("########%s\n", __func__); + pr_dbg("%s unreg stop %d.\n", __func__, reg_flag); + di_pre_stru.pre_de_busy = 0; di_pre_stru.unreg_req_flag_irq = 1; + reg_flag = 0; trigger_pre_di_process(TRIGGER_PRE_BY_UNREG); } else { di_pre_stru.force_unreg_req_flag = 0; di_pre_stru.disable_req_flag = 0; recovery_flag = 0; di_pre_stru.unreg_req_flag = 0; + trigger_pre_di_process(TRIGGER_PRE_BY_UNREG); } } static void di_unreg_process_irq(void) { - ulong flags = 0, fiq_flag = 0, irq_flag2 = 0; + ulong irq_flag2 = 0; #if (defined ENABLE_SPIN_LOCK_ALWAYS) + ulong flags = 0; spin_lock_irqsave(&plist_lock, flags); #endif - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); di_print("%s: di_uninit_buf\n", __func__); di_uninit_buf(); init_flag = 0; @@ -6245,29 +5520,38 @@ static void di_unreg_process_irq(void) rdma_clear(de_devp->rdma_handle); #endif adpative_combing_exit(); - di_set_power_control(0, 0); -#ifndef NEW_DI_V3 - DI_Wr(DI_CLKG_CTRL, 0xff0000); -/* di enable nr clock gate */ -#else - if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) + enable_di_pre_mif(false, mcpre_en); + di_hw_uninit(); + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) + di_pre_gate_control(false, mcpre_en); + else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { DI_Wr(DI_CLKG_CTRL, 0x80f60000); - else + DI_Wr(DI_PRE_CTRL, 0); + } else DI_Wr(DI_CLKG_CTRL, 0xf60000); /* nr/blend0/ei0/mtn0 clock gate */ -#endif if (get_blackout_policy()) { - di_set_power_control(1, 0); - DI_Wr(DI_CLKG_CTRL, 0x80000000); - switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, VPU_CLK_GATE_OFF); + di_hw_disable(mcpre_en); + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) { + enable_di_post_mif(GATE_OFF); + di_post_gate_control(false); + di_top_gate_control(false, false); + } else { + DI_Wr(DI_CLKG_CTRL, 0x80000000); + } + if (!is_meson_gxl_cpu() && !is_meson_gxm_cpu() && + !is_meson_gxbb_cpu() && !is_meson_txlx_cpu()) + switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, + VPU_CLK_GATE_OFF); + pr_info("%s disable di mirror image.\n", __func__); } - if ((post_wr_en && post_wr_surpport)) { + if (post_wr_en && post_wr_support) { diwr_set_power_control(0); #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA enable_rdma(1); #endif } - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); #if (defined ENABLE_SPIN_LOCK_ALWAYS) spin_unlock_irqrestore(&plist_lock, flags); @@ -6276,11 +5560,17 @@ static void di_unreg_process_irq(void) di_pre_stru.force_unreg_req_flag = 0; di_pre_stru.disable_req_flag = 0; recovery_flag = 0; -#ifdef NEW_DI_V3 di_pre_stru.cur_prog_flag = 0; -#endif di_pre_stru.unreg_req_flag = 0; di_pre_stru.unreg_req_flag_irq = 0; +#ifdef CONFIG_CMA + if (de_devp->flag_cma == 1) { + pr_dbg("%s:cma release req time: %d ms\n", + __func__, jiffies_to_msecs(jiffies)); + di_pre_stru.cma_release_req = 1; + up(&di_sema); + } +#endif } static void di_reg_process(void) @@ -6288,7 +5578,6 @@ static void di_reg_process(void) /*get vout information first time*/ if (reg_flag == 1) return; - vf_provider_init(&di_vf_prov, VFM_NAME, &deinterlace_vf_provider, NULL); vf_reg_provider(&di_vf_prov); vf_notify_receiver(VFM_NAME, VFRAME_EVENT_PROVIDER_START, NULL); reg_flag = 1; @@ -6321,6 +5610,36 @@ static struct rdma_op_s di_rdma_op = { NULL }; #endif +static void di_pre_size_change(unsigned short width, + unsigned short height, unsigned short vf_type) +{ + unsigned int blkhsize = 0; + + nr_all_config(width, height, vf_type); + #ifdef DET3D + det3d_config(det3d_en ? 1 : 0); + #endif + if (pulldown_enable) { + pulldown_init(width, height); + init_field_mode(height); + if (is_meson_txlx_cpu() || + is_meson_gxlx_cpu() || + is_meson_txhd_cpu()) + film_mode_win_config(width, height); + } + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) + combing_pd22_window_config(width, height); + RDMA_WR(DI_PRE_SIZE, (width - 1) | + ((height - 1) << 16)); + if (mcpre_en) { + blkhsize = (width + 3) / 5; + RDMA_WR(MCDI_HV_SIZEIN, height + | (width << 16)); + RDMA_WR(MCDI_HV_BLKSIZEIN, (overturn ? 3 : 0) << 30 + | blkhsize << 16 | height); + RDMA_WR(MCDI_BLKTOTAL, blkhsize * height); + } +} static bool need_bypass(struct vframe_s *vf) { if (vf->type & VIDTYPE_MVC) @@ -6346,8 +5665,12 @@ static bool need_bypass(struct vframe_s *vf) } static void di_reg_process_irq(void) { - ulong flags = 0, fiq_flag = 0, irq_flag2 = 0; + ulong irq_flag2 = 0; + #ifndef RUN_DI_PROCESS_IN_IRQ + ulong flags = 0; + #endif vframe_t *vframe; + unsigned short nr_height = 0, first_field_type; if ((pre_run_flag != DI_RUN_FLAG_RUN) && (pre_run_flag != DI_RUN_FLAG_STEP)) @@ -6355,8 +5678,6 @@ static void di_reg_process_irq(void) if (pre_run_flag == DI_RUN_FLAG_STEP) pre_run_flag = DI_RUN_FLAG_STEP_DONE; - /*di_pre_stru.reg_req_flag = 1;*/ - /*trigger_pre_di_process(TRIGGER_PRE_BY_TIMERC);*/ vframe = vf_peek(VFM_NAME); @@ -6368,40 +5689,51 @@ static void di_reg_process_irq(void) } di_pre_stru.bypass_flag = true; return; + } else { + di_pre_stru.bypass_flag = false; } - di_pre_stru.bypass_flag = false; /* patch for vdin progressive input */ - if (((vframe->type & VIDTYPE_VIU_422) && - ((vframe->type & VIDTYPE_PROGRESSIVE) == 0)) + if ((is_from_vdin(vframe) && + is_progressive(vframe)) #ifdef DET3D || det3d_en #endif || (use_2_interlace_buff & 0x2) - ) + ) { use_2_interlace_buff = 1; - else + nr_height = vframe->height; + } else { use_2_interlace_buff = 0; + nr_height = (vframe->height>>1); + } switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, VPU_CLK_GATE_ON); - di_set_power_control(0, 1); - di_set_power_control(1, 1); - if ((post_wr_en && post_wr_surpport)) { + if (post_wr_en && post_wr_support) { diwr_set_power_control(1); #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA enable_rdma(0); #endif } -#ifndef NEW_DI_V3 - DI_Wr(DI_CLKG_CTRL, 0xfeff0000); - /* di enable nr clock gate */ -#else - /* if mcdi enable DI_CLKG_CTRL should be 0xfef60000 */ - DI_Wr(DI_CLKG_CTRL, 0xfef60001); - /* nr/blend0/ei0/mtn0 clock gate */ -#endif - /* add for di Reg re-init */ -#ifdef NEW_DI_TV - di_set_para_by_tvinfo(vframe); -#endif + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) { + if (!use_2_interlace_buff) { + /* nr only clkb upto 500M*/ + clk_set_rate(de_devp->vpu_clkb, + de_devp->clkb_min_rate); + di_top_gate_control(true, true); + di_post_gate_control(true); + /* freerun for reg configuration */ + enable_di_post_mif(GATE_AUTO); + } else { + clk_set_rate(de_devp->vpu_clkb, + de_devp->clkb_max_rate); + di_top_gate_control(true, false); + } + enable_di_pre_mif(true, mcpre_en); + di_pre_gate_control(true, mcpre_en); + } else { + /* if mcdi enable DI_CLKG_CTRL should be 0xfef60000 */ + DI_Wr(DI_CLKG_CTRL, 0xfef60001); + /* nr/blend0/ei0/mtn0 clock gate */ + } if (di_printk_flag & 2) di_printk_flag = 1; @@ -6411,7 +5743,7 @@ static void di_reg_process_irq(void) #if (!(defined RUN_DI_PROCESS_IN_IRQ)) || (defined ENABLE_SPIN_LOCK_ALWAYS) spin_lock_irqsave(&plist_lock, flags); #endif - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); /* * 10 bit mode need 1.5 times buffer size of * 8 bit mode, init the buffer size as 10 bit @@ -6420,16 +5752,17 @@ static void di_reg_process_irq(void) */ di_init_buf(default_width, default_height, 1); - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); #if (!(defined RUN_DI_PROCESS_IN_IRQ)) || (defined ENABLE_SPIN_LOCK_ALWAYS) spin_unlock_irqrestore(&plist_lock, flags); + nr_height = vframe->height; #endif } else { #if (!(defined RUN_DI_PROCESS_IN_IRQ)) || (defined ENABLE_SPIN_LOCK_ALWAYS) spin_lock_irqsave(&plist_lock, flags); #endif - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); /* * 10 bit mode need 1.5 times buffer size of * 8 bit mode, init the buffer size as 10 bit @@ -6438,29 +5771,39 @@ static void di_reg_process_irq(void) */ di_init_buf(default_width, default_height, 0); - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); #if (!(defined RUN_DI_PROCESS_IN_IRQ)) || (defined ENABLE_SPIN_LOCK_ALWAYS) spin_unlock_irqrestore(&plist_lock, flags); #endif } - if (pulldown_enable) { - FlmVOFSftInt(&pd_param); - flm22_sure_num = (vframe->height * 100)/480; - flm22_sure_smnum = (flm22_sure_num * flm22_ratio)/100; + calc_lmv_init(); + first_field_type = (vframe->type & VIDTYPE_TYPEMASK); + di_pre_size_change(vframe->width, nr_height, + first_field_type); + + if (de_devp->flags & DI_LOAD_REG_FLAG) { + struct di_pq_parm_s *pos = NULL, *tmp = NULL; + + mutex_lock(&de_devp->pq_lock); + list_for_each_entry_safe(pos, tmp, + &de_devp->pq_table_list, list) { + di_load_regs(pos); + list_del(&pos->list); + di_pq_parm_destroy(pos); + } + de_devp->flags &= ~DI_LOAD_REG_FLAG; + mutex_unlock(&de_devp->pq_lock); } - adpative_combing_config(vframe->width, - (vframe->height>>1), - (vframe->source_type), - is_progressive(vframe), - vframe->sig_fmt); - if (is_meson_txl_cpu()) { - combing_pd22_window_config(vframe->width, - (vframe->height>>1)); - tbff_init(); - } + + di_pre_stru.mtn_status = + adpative_combing_config(vframe->width, + (vframe->height>>1), + (vframe->source_type), + is_progressive(vframe), + vframe->sig_fmt); init_flag = 1; di_pre_stru.reg_req_flag_irq = 1; } @@ -6468,11 +5811,12 @@ static void di_reg_process_irq(void) static void di_process(void) { - ulong flags = 0, fiq_flag = 0, irq_flag2 = 0; + ulong irq_flag2 = 0; + #ifndef RUN_DI_PROCESS_IN_IRQ + ulong flags = 0; + #endif - di_process_cnt++; - - if (init_flag && mem_flag && (recovery_flag == 0) && + if (init_flag && (recovery_flag == 0) && (dump_state_flag == 0)) { #if (!(defined RUN_DI_PROCESS_IN_IRQ)) || (defined ENABLE_SPIN_LOCK_ALWAYS) spin_lock_irqsave(&plist_lock, flags); @@ -6513,19 +5857,26 @@ static void di_process(void) #endif } else if (di_pre_stru.pre_de_clear_flag == 1) { di_lock_irqfiq_save( - irq_flag2, fiq_flag); + irq_flag2); pre_de_done_buf_clear(); di_unlock_irqfiq_restore( - irq_flag2, fiq_flag); + irq_flag2); di_pre_stru.pre_de_process_done = 0; di_pre_stru.pre_de_clear_flag = 0; } } - di_lock_irqfiq_save(irq_flag2, fiq_flag); - while (check_recycle_buf() & 1) - ; - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); + di_post_stru.check_recycle_buf_cnt = 0; + while (check_recycle_buf() & 1) { + if (di_post_stru.check_recycle_buf_cnt++ > + MAX_IN_BUF_NUM) { + di_pr_info("%s: check_recycle_buf time out!!\n", + __func__); + break; + } + } + di_unlock_irqfiq_restore(irq_flag2); if ((di_pre_stru.pre_de_busy == 0) && (di_pre_stru.pre_de_process_done == 0)) { @@ -6538,10 +5889,16 @@ static void di_process(void) pre_de_process(); } } - while (process_post_vframe()) - ; - - if ((post_wr_en && post_wr_surpport)) { + di_post_stru.di_post_process_cnt = 0; + while (process_post_vframe()) { + if (di_post_stru.di_post_process_cnt++ > + MAX_POST_BUF_NUM) { + di_pr_info("%s: process_post_vframe time out!!\n", + __func__); + break; + } + } + if (post_wr_en && post_wr_support) { if (di_post_stru.post_de_busy == 0 && di_post_stru.de_post_process_done) { post_de_done_buf_config(); @@ -6556,44 +5913,42 @@ static void di_process(void) } } static unsigned int nr_done_check_cnt = 5; -module_param_named(nr_done_check_cnt, nr_done_check_cnt, uint, 0644); -void di_timer_handle(struct work_struct *work) +static void di_pre_trigger_work(struct di_pre_stru_s *pre_stru_p) { - if (di_pre_stru.bypass_flag) - return; - if (di_pre_stru.pre_de_busy) { - di_pre_stru.pre_de_busy_timer_count++; - if (di_pre_stru.pre_de_busy_timer_count >= nr_done_check_cnt) { - enable_di_pre_mif(0); - di_pre_stru.pre_de_busy_timer_count = 0; - di_pre_stru.pre_de_irq_timeout_count++; + + if (pre_stru_p->pre_de_busy && init_flag) { + pre_stru_p->pre_de_busy_timer_count++; + if (pre_stru_p->pre_de_busy_timer_count >= nr_done_check_cnt) { + enable_di_pre_mif(false, mcpre_en); + pre_stru_p->pre_de_busy_timer_count = 0; + pre_stru_p->pre_de_irq_timeout_count++; if (timeout_miss_policy == 0) { - di_pre_stru.pre_de_process_done = 1; - di_pre_stru.pre_de_busy = 0; - di_pre_stru.pre_de_clear_flag = 2; + pre_stru_p->pre_de_process_done = 1; + pre_stru_p->pre_de_busy = 0; + pre_stru_p->pre_de_clear_flag = 2; } else if (timeout_miss_policy == 1) { - di_pre_stru.pre_de_clear_flag = 1; - di_pre_stru.pre_de_busy = 0; - } /* else if (timeout_miss_policy == 2) { - * } - */ - pr_info("***** DI ****** wait %d pre_de_irq timeout\n", - di_pre_stru.field_count_for_cont); + pre_stru_p->pre_de_clear_flag = 1; + pre_stru_p->pre_de_busy = 0; + } + if ((pre_stru_p->field_count_for_cont < 10) || + (di_dbg_mask&0x2)) { + pr_info("DI*****wait %d timeout*****\n", + pre_stru_p->field_count_for_cont); + } } } else { - di_pre_stru.pre_de_busy_timer_count = 0; + pre_stru_p->pre_de_busy_timer_count = 0; } /* if(force_trig){ */ - force_trig_cnt++; trigger_pre_di_process(TRIGGER_PRE_BY_TIMER); /* } */ if (force_recovery) { if (recovery_flag || (force_recovery & 0x2)) { force_recovery_count++; - if (init_flag && mem_flag) { - pr_dbg("====== DI force recovery =========\n"); + if (init_flag) { + pr_err("====== DI force recovery =========\n"); force_recovery &= (~0x2); dis2_di(); recovery_flag = 0; @@ -6604,16 +5959,20 @@ void di_timer_handle(struct work_struct *work) static int di_task_handle(void *data) { + struct di_dev_s *devp; int ret = 0; - + devp = (struct di_dev_s *)data; + if (!devp) + return -1; while (1) { ret = down_interruptible(&di_sema); if (active_flag) { if ((di_pre_stru.unreg_req_flag || di_pre_stru.force_unreg_req_flag || di_pre_stru.disable_req_flag) && - (di_pre_stru.pre_de_busy == 0)) + (di_pre_stru.pre_de_busy == 0)) { di_unreg_process(); + } if (di_pre_stru.reg_req_flag_irq || di_pre_stru.reg_req_flag) { di_reg_process(); @@ -6621,18 +5980,22 @@ static int di_task_handle(void *data) di_pre_stru.reg_req_flag_irq = 0; } #ifdef CONFIG_CMA - if (di_pre_stru.cma_alloc_req) { - di_cma_alloc(); - di_pre_stru.cma_alloc_req = 0; - di_pre_stru.cma_alloc_done = 1; - mem_flag = 1; - } + mutex_lock(&de_devp->cma_mutex); if (di_pre_stru.cma_release_req) { - di_cma_release(); + atomic_set(&devp->mem_flag, 0); + di_cma_release(devp); di_pre_stru.cma_release_req = 0; di_pre_stru.cma_alloc_done = 0; - mem_flag = 0; } + if (di_pre_stru.cma_alloc_req) { + if (di_cma_alloc(devp)) + atomic_set(&devp->mem_flag, 1); + else + atomic_set(&devp->mem_flag, 0); + di_pre_stru.cma_alloc_req = 0; + di_pre_stru.cma_alloc_done = 1; + } + mutex_unlock(&de_devp->cma_mutex); #endif } } @@ -6640,29 +6003,46 @@ static int di_task_handle(void *data) return 0; } -static irqreturn_t timer_irq(int irq, void *dev_instance) +static void di_pre_process_irq(struct di_pre_stru_s *pre_stru_p) { -/* unsigned int data32; */ int i; if (active_flag) { - if (di_pre_stru.unreg_req_flag_irq) + if (pre_stru_p->unreg_req_flag_irq) di_unreg_process_irq(); - if (init_flag == 0 && di_pre_stru.reg_req_flag_irq == 0) + if (init_flag == 0 && pre_stru_p->reg_req_flag_irq == 0) di_reg_process_irq(); } - for (i = 0; i < 2; i++) + for (i = 0; i < 2; i++) { if (active_flag) di_process(); + } log_buffer_state("pro"); - return IRQ_HANDLED; +} +static struct hrtimer di_pre_hrtimer; + +static void pre_tasklet(unsigned long arg) +{ + unsigned int hrtimer_time = 0; + + hrtimer_time = jiffies_to_msecs(jiffies_64 - de_devp->jiffy); + if (hrtimer_time > 10) + pr_dbg("DI: tasklet schedule cost %ums.\n", hrtimer_time); + di_pre_process_irq((struct di_pre_stru_s *)arg); +} + +static enum hrtimer_restart di_pre_hrtimer_func(struct hrtimer *timer) +{ + if (!di_pre_stru.bypass_flag) + di_pre_trigger_work(&di_pre_stru); + hrtimer_forward_now(&di_pre_hrtimer, ms_to_ktime(10)); + return HRTIMER_RESTART; } /* * provider/receiver interface */ - -/* unsigned int vf_keep_current(void);*/ +char *vf_get_receiver_name(const char *provider_name); static int di_receiver_event_fun(int type, void *data, void *arg) { int i; @@ -6673,21 +6053,22 @@ static int di_receiver_event_fun(int type, void *data, void *arg) } else if (type == VFRAME_EVENT_PROVIDER_UNREG) { pr_dbg("%s , is_bypass() %d trick_mode %d bypass_all %d\n", __func__, is_bypass(NULL), trick_mode, bypass_all); - - if ((Rd(DI_IF1_GEN_REG) & 0x1) && get_blackout_policy()) - /* disable post di, so can call vf_keep_current() - * to keep displayed vframe - */ - pr_info("DI: disabled, not keep buffer.\n"); - - pr_dbg("%s: vf_notify_receiver unreg\n", __func__); + pr_info("%s: vf_notify_receiver unreg\n", __func__); di_pre_stru.unreg_req_flag = 1; - provider_vframe_level = 0; - vdin_source_flag = 0; + di_pre_stru.vdin_source = false; trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_UNREG); - while (di_pre_stru.unreg_req_flag) + di_pre_stru.unreg_req_flag_cnt = 0; + while (di_pre_stru.unreg_req_flag) { usleep_range(10000, 10001); + if (di_pre_stru.unreg_req_flag_cnt++ > + di_reg_unreg_cnt) { + reg_unreg_timeout_cnt++; + pr_err("%s:unreg_reg_flag timeout!!!\n", + __func__); + break; + } + } #ifdef SUPPORT_MPEG_TO_VDIN if (mpeg2vdin_flag) { struct vdin_arg_s vdin_arg; @@ -6702,9 +6083,8 @@ static int di_receiver_event_fun(int type, void *data, void *arg) #endif bypass_state = 1; #ifdef RUN_DI_PROCESS_IN_IRQ - if (vdin_source_flag) + if (di_pre_stru.vdin_source) DI_Wr_reg_bits(VDIN_WR_CTRL, 0x3, 24, 3); - #endif } else if (type == VFRAME_EVENT_PROVIDER_RESET) { di_blocking = 1; @@ -6718,8 +6098,6 @@ static int di_receiver_event_fun(int type, void *data, void *arg) pr_dbg("%s: vf_notify_receiver ligth unreg\n", __func__); light_unreg: - provider_vframe_level = 0; - spin_lock_irqsave(&plist_lock, flags); for (i = 0; i < MAX_IN_BUF_NUM; i++) { @@ -6736,9 +6114,6 @@ light_unreg: pr_dbg( "%s:VFRAME_EVENT_PROVIDER_LIGHT_UNREG_RETURN_VFRAME\n", __func__); - - provider_vframe_level = 0; - /* * do not display garbage when 2d->3d or 3d->2d */ @@ -6757,7 +6132,6 @@ light_unreg: spin_unlock_irqrestore(&plist_lock, flags); } else if (type == VFRAME_EVENT_PROVIDER_VFRAME_READY) { - provider_vframe_level++; if (di_pre_stru.bypass_flag) vf_notify_receiver(VFM_NAME, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); @@ -6765,7 +6139,7 @@ light_unreg: #ifdef RUN_DI_PROCESS_IN_IRQ #define INPUT2PRE_2_BYPASS_SKIP_COUNT 4 - if (active_flag && vdin_source_flag) { + if (active_flag && di_pre_stru.vdin_source) { if (is_bypass(NULL)) { if (di_pre_stru.pre_de_busy == 0) { DI_Wr_reg_bits(VDIN_WR_CTRL, @@ -6867,35 +6241,39 @@ light_unreg: } else if (type == VFRAME_EVENT_PROVIDER_REG) { char *provider_name = (char *)data; char *receiver_name = NULL; - + if (de_devp->flags & DI_SUSPEND_FLAG) { + pr_err("[DI] reg event device hasn't resumed\n"); + return -1; + } bypass_state = 0; di_pre_stru.reg_req_flag = 1; pr_dbg("%s: vframe provider reg\n", __func__); trigger_pre_di_process(TRIGGER_PRE_BY_PROVERDER_REG); - while (di_pre_stru.reg_req_flag) + di_pre_stru.reg_req_flag_cnt = 0; + while (di_pre_stru.reg_req_flag) { usleep_range(10000, 10001); + if (di_pre_stru.reg_req_flag_cnt++ > di_reg_unreg_cnt) { + reg_unreg_timeout_cnt++; + pr_dbg("%s:reg_req_flag timeout!!!\n", + __func__); + break; + } + } - aml_cbus_update_bits(ISA_TIMER_MUX, 1 << 14, 0 << 14); - aml_cbus_update_bits(ISA_TIMER_MUX, 3 << 4, 0 << 4); - aml_cbus_update_bits(ISA_TIMER_MUX, 1 << 18, 1 << 18); - aml_write_cbus(ISA_TIMERC, 1); - - if (strncmp(provider_name, "vdin", 4) == 0) { - vdin_source_flag = 1; + if (strncmp(provider_name, "vdin0", 4) == 0) { + di_pre_stru.vdin_source = true; } else { - vdin_source_flag = 0; + di_pre_stru.vdin_source = false; pre_urgent = 0; } receiver_name = vf_get_receiver_name(VFM_NAME); if (receiver_name) { if (!strcmp(receiver_name, "amvideo")) { di_post_stru.run_early_proc_fun_flag = 0; - receiver_is_amvideo = 1; /* pr_info("set run_early_proc_fun_flag to 1\n"); */ } else { di_post_stru.run_early_proc_fun_flag = 1; - receiver_is_amvideo = 0; - pr_info("set run_early_proc_fun_flag to 1\n"); + pr_info("set run_early_proc_fun_flag to 1\n"); } } else { pr_info("%s error receiver is null.\n", __func__); @@ -6922,10 +6300,10 @@ light_unreg: static void fast_process(void) { int i; - ulong flags = 0, fiq_flag = 0, irq_flag2 = 0; + ulong flags = 0, irq_flag2 = 0; if (active_flag && is_bypass(NULL) && (BYPASS_GET_MAX_BUF_NUM <= 1) && - init_flag && mem_flag && (recovery_flag == 0) && + init_flag && (recovery_flag == 0) && (dump_state_flag == 0)) { if (vf_peek(VFM_NAME) == NULL) return; @@ -6937,10 +6315,17 @@ static void fast_process(void) di_pre_stru.pre_de_process_done = 0; } - di_lock_irqfiq_save(irq_flag2, fiq_flag); - while (check_recycle_buf() & 1) - ; - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); + di_post_stru.check_recycle_buf_cnt = 0; + while (check_recycle_buf() & 1) { + if (di_post_stru.check_recycle_buf_cnt++ > + MAX_IN_BUF_NUM) { + di_pr_info("%s: check_recycle_buf time out!!\n", + __func__); + break; + } + } + di_unlock_irqfiq_restore(irq_flag2); if ((di_pre_stru.pre_de_busy == 0) && (di_pre_stru.pre_de_process_done == 0)) { @@ -6953,8 +6338,15 @@ static void fast_process(void) pre_de_process(); } } - while (process_post_vframe()) - ; + di_post_stru.di_post_process_cnt = 0; + while (process_post_vframe()) { + if (di_post_stru.di_post_process_cnt++ > + MAX_POST_BUF_NUM) { + di_pr_info("%s: process_post_vframe time out!!\n", + __func__); + break; + } + } spin_unlock_irqrestore(&plist_lock, flags); } @@ -7003,49 +6395,43 @@ static vframe_t *di_vf_peek(void *arg) vframe_type_name[di_buf->type], di_buf->index, vframe_ret); #endif - if (force_duration_0) { - if (vframe_ret) - vframe_ret->duration = 0; - } return vframe_ret; } /*recycle the buffer for keeping buffer*/ -void recycle_keep_buffer(void) +static void recycle_keep_buffer(void) { - ulong flags = 0, fiq_flag = 0, irq_flag2 = 0; + ulong irq_flag2 = 0; int i = 0; + struct di_buf_s *keep_buf; - if ((used_post_buf_index != -1) && (new_keep_last_frame_enable)) { - if (di_buf_post[used_post_buf_index].type == VFRAME_TYPE_POST) { + keep_buf = di_post_stru.keep_buf; + if (!IS_ERR_OR_NULL(keep_buf)) { + if (keep_buf->type == VFRAME_TYPE_POST) { pr_dbg("%s recycle keep cur di_buf %d (", - __func__, used_post_buf_index); - di_lock_irqfiq_save(irq_flag2, fiq_flag); + __func__, keep_buf->index); + di_lock_irqfiq_save(irq_flag2); for (i = 0; i < USED_LOCAL_BUF_MAX; i++) { - if ( - di_buf_post[used_post_buf_index]. - di_buf_dup_p[i]) { + if (keep_buf->di_buf_dup_p[i]) { queue_in( - di_buf_post[used_post_buf_index]. - di_buf_dup_p[i], - QUEUE_RECYCLE); + keep_buf->di_buf_dup_p[i], + QUEUE_RECYCLE); pr_dbg(" %d ", - di_buf_post[used_post_buf_index] - .di_buf_dup_p[i]->index); + keep_buf->di_buf_dup_p[i]->index); } } - queue_in(&di_buf_post[used_post_buf_index], - QUEUE_POST_FREE); - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + queue_in(keep_buf, QUEUE_POST_FREE); + di_unlock_irqfiq_restore(irq_flag2); pr_dbg(")\n"); } - used_post_buf_index = -1; + di_post_stru.keep_buf = NULL; } } +static bool show_nrwr; static vframe_t *di_vf_get(void *arg) { vframe_t *vframe_ret = NULL; struct di_buf_s *di_buf = NULL; - ulong flags = 0, fiq_flag = 0, irq_flag2 = 0; + ulong irq_flag2 = 0; if (di_pre_stru.bypass_flag) return vf_get(VFM_NAME); @@ -7071,26 +6457,47 @@ static vframe_t *di_vf_get(void *arg) get_vframe: #endif log_buffer_state("ge_"); - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); di_buf = get_di_buf_head(QUEUE_POST_READY); queue_out(di_buf); queue_in(di_buf, QUEUE_DISPLAY); /* add it into display_list */ - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); if (di_buf) { vframe_ret = di_buf->vframe; - if ((post_wr_en && post_wr_surpport) && + if ((post_wr_en && post_wr_support) && (di_buf->process_fun_index != PROCESS_FUN_NULL)) { - config_canvas_idx(di_buf, - di_post_idx[di_post_stru.canvas_id][5], -1); + #if 0 + CONFIG_MULTI_DEC + vframe_ret->canvas0_config[0].phy_addr = + di_buf->nr_adr; + vframe_ret->canvas0_config[0].width = + di_buf->canvas_width[NR_CANVAS], + vframe_ret->canvas0_config[0].height = + di_buf->canvas_height; + vframe_ret->canvas0_config[0].block_mode = 0; + vframe_ret->plane_num = 1; + vframe_ret->canvas0Addr = -1; + vframe_ret->canvas1Addr = -1; + #else + config_canvas_idx(di_buf, di_wr_idx, -1); vframe_ret->canvas0Addr = di_buf->nr_canvas_idx; vframe_ret->canvas1Addr = di_buf->nr_canvas_idx; + if (show_nrwr) { + config_canvas_idx( + di_buf->di_buf_dup_p[1], + di_wr_idx, -1); + vframe_ret->canvas0Addr = di_wr_idx; + vframe_ret->canvas1Addr = di_wr_idx; + } + #endif vframe_ret->early_process_fun = NULL; vframe_ret->process_fun = NULL; } + di_buf->seq = disp_frame_count; atomic_set(&di_buf->di_cnt, 1); } disp_frame_count++; @@ -7105,11 +6512,6 @@ get_vframe: jiffies_to_msecs(jiffies_64 - vframe_ret->ready_jiffies64)); } - if (force_duration_0) { - if (vframe_ret) - vframe_ret->duration = 0; - } - if (!post_wr_en && di_post_stru.run_early_proc_fun_flag && vframe_ret) { if (vframe_ret->early_process_fun == do_pre_only_fun) vframe_ret->early_process_fun( @@ -7120,34 +6522,41 @@ get_vframe: static void di_vf_put(vframe_t *vf, void *arg) { - struct di_buf_s *di_buf = (struct di_buf_s *)vf->private_data; - ulong flags = 0, fiq_flag = 0, irq_flag2 = 0; + struct di_buf_s *di_buf = NULL; + ulong irq_flag2 = 0; if (di_pre_stru.bypass_flag) { vf_put(vf, VFM_NAME); vf_notify_provider(VFM_NAME, VFRAME_EVENT_RECEIVER_PUT, NULL); - if (used_post_buf_index != -1) + if (!IS_ERR_OR_NULL(di_post_stru.keep_buf)) recycle_keep_buffer(); return; } /* struct di_buf_s *p = NULL; */ /* int itmp = 0; */ - if ((init_flag == 0) || (mem_flag == 0) || recovery_flag || !vf) { + if ((init_flag == 0) || recovery_flag || + IS_ERR_OR_NULL(vf)) { di_print("%s: 0x%p\n", __func__, vf); return; } if (di_blocking) return; log_buffer_state("pu_"); - if (used_post_buf_index != -1) + di_buf = (struct di_buf_s *)vf->private_data; + if (IS_ERR_OR_NULL(di_buf)) { + pr_info("%s: get vframe %p without di buf\n", + __func__, vf); + return; + } + if (di_post_stru.keep_buf == di_buf) { + pr_info("[DI]recycle buffer %d, get cnt %d.\n", + di_buf->index, disp_frame_count); recycle_keep_buffer(); - - if (!di_buf) - return vf_put(vf, VFM_NAME); + } if (di_buf->type == VFRAME_TYPE_POST) { - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); if (is_in_queue(di_buf, QUEUE_DISPLAY)) { if (!atomic_dec_and_test(&di_buf->di_cnt)) @@ -7157,14 +6566,14 @@ static void di_vf_put(vframe_t *vf, void *arg) di_print("%s: %s[%d] not in display list\n", __func__, vframe_type_name[di_buf->type], di_buf->index); } - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); #ifdef DI_BUFFER_DEBUG recycle_vframe_type_post_print(di_buf, __func__, __LINE__); #endif } else { - di_lock_irqfiq_save(irq_flag2, fiq_flag); + di_lock_irqfiq_save(irq_flag2); queue_in(di_buf, QUEUE_RECYCLE); - di_unlock_irqfiq_restore(irq_flag2, fiq_flag); + di_unlock_irqfiq_restore(irq_flag2); di_print("%s: %s[%d] =>recycle_list\n", __func__, vframe_type_name[di_buf->type], di_buf->index); @@ -7176,13 +6585,25 @@ static void di_vf_put(vframe_t *vf, void *arg) static int di_event_cb(int type, void *data, void *private_data) { if (type == VFRAME_EVENT_RECEIVER_FORCE_UNREG) { - pr_dbg("%s: VFRAME_EVENT_RECEIVER_FORCE_UNREG\n", __func__); + pr_info("%s: RECEIVER_FORCE_UNREG return\n", + __func__); + return 0; di_pre_stru.force_unreg_req_flag = 1; - provider_vframe_level = 0; trigger_pre_di_process(TRIGGER_PRE_BY_FORCE_UNREG); - while (di_pre_stru.force_unreg_req_flag) + di_pre_stru.unreg_req_flag_cnt = 0; + while (di_pre_stru.force_unreg_req_flag) { usleep_range(1000, 1001); + di_pr_info("%s:unreg_req_flag_cnt:%d!!!\n", + __func__, di_pre_stru.unreg_req_flag_cnt); + if (di_pre_stru.unreg_req_flag_cnt++ > + di_reg_unreg_cnt) { + di_pre_stru.unreg_req_flag_cnt = 0; + di_pr_info("%s:unreg_reg_flag timeout!!!\n", + __func__); + break; + } + } } return 0; } @@ -7191,10 +6612,15 @@ static int di_vf_states(struct vframe_states *states, void *arg) { if (!states) return -1; - states->vf_pool_size = local_buf_num; + states->vf_pool_size = de_devp->buf_num_avail; states->buf_free_num = list_count(QUEUE_LOCAL_FREE); states->buf_avail_num = list_count(QUEUE_POST_READY); states->buf_recycle_num = list_count(QUEUE_RECYCLE); + if (di_dbg_mask&0x1) { + di_pr_info("di-pre-ready-num:%d\n", + list_count(QUEUE_PRE_READY)); + di_pr_info("di-display-num:%d\n", list_count(QUEUE_DISPLAY)); + } return 0; } @@ -7221,15 +6647,134 @@ static int di_release(struct inode *node, struct file *file) /* Reset file pointer */ /* Release some other fields */ -/* ... */ + file->private_data = NULL; return 0; } +static struct di_pq_parm_s *di_pq_parm_create(struct am_pq_parm_s *pq_parm_p) +{ + struct di_pq_parm_s *pq_ptr = NULL; + struct am_reg_s *am_reg_p = NULL; + size_t mem_size = 0; + + pq_ptr = vzalloc(sizeof(struct di_pq_parm_s)); + if (!pq_ptr) + return NULL; + mem_size = sizeof(struct am_pq_parm_s); + memcpy(&pq_ptr->pq_parm, pq_parm_p, mem_size); + mem_size = sizeof(struct am_reg_s)*pq_parm_p->table_len; + am_reg_p = vzalloc(mem_size); + if (!am_reg_p) { + vfree(pq_ptr); + pr_err("[DI] alloc pq table memory errors\n"); + return NULL; + } + pq_ptr->regs = am_reg_p; + + return pq_ptr; +} + +static void di_pq_parm_destroy(struct di_pq_parm_s *pq_ptr) +{ + if (!pq_ptr) { + pr_err("[DI] %s pq parm pointer null.\n", __func__); + return; + } + vfree(pq_ptr->regs); + vfree(pq_ptr); +} +static long di_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret = 0, tab_flag = 0; + di_dev_t *di_devp; + void __user *argp = (void __user *)arg; + size_t mm_size = 0; + struct am_pq_parm_s tmp_pq_s = {0}; + struct di_pq_parm_s *di_pq_ptr = NULL; + + if (_IOC_TYPE(cmd) != _DI_) { + pr_err("%s invalid command: %u\n", __func__, cmd); + return -EFAULT; + } + di_devp = file->private_data; + switch (cmd) { + case AMDI_IOC_SET_PQ_PARM: + mm_size = sizeof(struct am_pq_parm_s); + if (copy_from_user(&tmp_pq_s, argp, mm_size)) { + pr_err("[DI] set pq parm errors\n"); + return -EFAULT; + } + tab_flag = TABLE_NAME_DI | TABLE_NAME_NR | TABLE_NAME_MCDI | + TABLE_NAME_DEBLOCK | TABLE_NAME_DEMOSQUITO; + if (tmp_pq_s.table_name & tab_flag) { + pr_info("[DI] load 0x%x pq table len %u.\n", + tmp_pq_s.table_name, tmp_pq_s.table_len); + } else { + pr_err("[DI] load 0x%x wrong pq table.\n", + tmp_pq_s.table_name); + return -EFAULT; + } + di_pq_ptr = di_pq_parm_create(&tmp_pq_s); + if (!di_pq_ptr) { + pr_err("[DI] allocat pq parm struct error.\n"); + return -EFAULT; + } + argp = (void __user *)tmp_pq_s.table_ptr; + mm_size = tmp_pq_s.table_len * sizeof(struct am_reg_s); + if (copy_from_user(di_pq_ptr->regs, argp, mm_size)) { + pr_err("[DI] user copy pq table errors\n"); + return -EFAULT; + } + if (init_flag) { + di_load_regs(di_pq_ptr); + di_pq_parm_destroy(di_pq_ptr); + } else { + if (di_devp->flags & DI_LOAD_REG_FLAG) { + struct di_pq_parm_s *pos = NULL, *tmp = NULL; + + mutex_lock(&de_devp->pq_lock); + list_for_each_entry_safe(pos, tmp, + &di_devp->pq_table_list, list) { + if (di_pq_ptr->pq_parm.table_name & + pos->pq_parm.table_name) { + list_del(&pos->list); + di_pq_parm_destroy(pos); + } + } + mutex_unlock(&de_devp->pq_lock); + } + mutex_lock(&de_devp->pq_lock); + list_add_tail(&di_pq_ptr->list, + &di_devp->pq_table_list); + di_devp->flags |= DI_LOAD_REG_FLAG; + mutex_unlock(&di_devp->pq_lock); + } + break; + default: + break; + } + return ret; +} + +#ifdef CONFIG_COMPAT +static long di_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned long ret; + + arg = (unsigned long)compat_ptr(arg); + ret = di_ioctl(file, cmd, arg); + return ret; +} +#endif static const struct file_operations di_fops = { .owner = THIS_MODULE, .open = di_open, .release = di_release, -/* .ioctl = di_ioctl, */ + .unlocked_ioctl = di_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = di_compat_ioctl, +#endif }; static ssize_t @@ -7238,7 +6783,7 @@ show_frame_format(struct device *dev, { int ret = 0; - if (init_flag && mem_flag) + if (init_flag) ret += sprintf(buf + ret, "%s\n", di_pre_stru.cur_prog_flag ? "progressive" : "interlace"); @@ -7284,7 +6829,7 @@ static void rmem_di_device_release(struct reserved_mem *rmem, unsigned int RDMA_RD_BITS(unsigned int adr, unsigned int start, unsigned int len) { - if (de_devp->rdma_handle) + if (de_devp->rdma_handle && di_pre_rdma_enable) return rdma_read_reg(de_devp->rdma_handle, adr) & (((1 << len) - 1) << start); else @@ -7360,25 +6905,33 @@ unsigned int RDMA_WR_BITS(unsigned int adr, unsigned int val, static void set_di_flag(void) { - if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu()) { + if (is_meson_txlx_cpu() || + is_meson_gxlx_cpu() || + is_meson_txhd_cpu()) { mcpre_en = true; - pulldown_enable = 1; + mc_mem_alloc = true; + pulldown_enable = true; di_pre_rdma_enable = false; - di_vscale_skip_enable = 4; - use_2_interlace_buff = 1; + /* + * txlx atsc 1080i ei only will cause flicker + * when full to small win in home screen + */ + di_vscale_skip_enable = (is_meson_txlx_cpu() + || is_meson_txhd_cpu())?12:4; + use_2_interlace_buff = is_meson_gxlx_cpu()?0:1; pre_hold_line = 12; - if (nr10bit_surpport) + if (nr10bit_support) di_force_bit_mode = 10; else di_force_bit_mode = 8; - if (is_meson_txl_cpu()) { + if (is_meson_txlx_cpu() || + is_meson_gxlx_cpu() || + is_meson_txhd_cpu()) { full_422_pack = true; - tff_bff_enable = false; - dejaggy_enable = 0; } } else { mcpre_en = false; - pulldown_enable = 0; + pulldown_enable = false; di_pre_rdma_enable = false; di_vscale_skip_enable = 4; use_2_interlace_buff = 0; @@ -7388,15 +6941,11 @@ static void set_di_flag(void) if (di_pre_rdma_enable) { pldn_dly = 1; pldn_dly1 = 1; - tbbtff_dly = 1; } else { pldn_dly = 2; pldn_dly1 = 2; - tbbtff_dly = 0; } - if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXBB)) - dnr_dm_en = true; } static const struct reserved_mem_ops rmem_di_ops = { @@ -7416,11 +6965,49 @@ static int __init rmem_di_setup(struct reserved_mem *rmem) return 0; } RESERVEDMEM_OF_DECLARE(di, "amlogic, di-mem", rmem_di_setup); + +static void di_get_vpu_clkb(struct device *dev, struct di_dev_s *pdev) +{ + + struct clk *clk_div4, *clk_div3, *vpu_clkb_tmp, *vpu_clk; + unsigned long clkb_tmp_rate; + + vpu_clk = clk_get(dev, "vpu_mux"); + if (IS_ERR(vpu_clk)) + pr_err("%s: get clk vpu error.\n", __func__); + vpu_clkb_tmp = clk_get(dev, "vpu_clkb_tmp_composite"); + if (IS_ERR(vpu_clkb_tmp)) + pr_err("%s: get vpu clkb tmp error.\n", __func__); + pdev->vpu_clkb = clk_get(dev, "vpu_clkb_composite"); + if (IS_ERR(pdev->vpu_clkb)) + pr_err("%s: get vpu clkb gate error.\n", __func__); + if (is_meson_txlx_cpu()) { + clk_div4 = clk_get(dev, "fclk_div4"); + if (IS_ERR(clk_div4)) + pr_err("%s: get clk div4 error.\n", __func__); + clk_set_parent(vpu_clkb_tmp, clk_div4); + pdev->clkb_max_rate = 500000000; + pdev->clkb_min_rate = 250000000; + clkb_tmp_rate = 500000000; + } else { + clk_div3 = clk_get(dev, "fclk_div3"); + if (IS_ERR(clk_div3)) + pr_err("%s: get clk div3 error.\n", __func__); + clk_set_parent(vpu_clkb_tmp, clk_div3); + pdev->clkb_max_rate = 333000000; + pdev->clkb_min_rate = 333000000; + clkb_tmp_rate = 666000000; + } + clk_set_rate(vpu_clkb_tmp, clkb_tmp_rate); + clk_set_rate(pdev->vpu_clkb, pdev->clkb_min_rate); + clk_prepare_enable(vpu_clkb_tmp); + +} + static int di_probe(struct platform_device *pdev) { - int ret = 0, i = 0;/* , offset = 0, size = 0; */ + int ret = 0; /* struct resource *res_irq = NULL; */ - int buf_num_avail = 0; struct di_dev_s *di_devp = NULL; /* const void *name = NULL; */ @@ -7455,56 +7042,63 @@ static int di_probe(struct platform_device *pdev) pr_err("DI-%s: get flag_cma error.\n", __func__); else pr_info("DI-%s: flag_cma: %d\n", __func__, di_devp->flag_cma); - if (di_devp->flag_cma == 1) { + if (di_devp->flag_cma >= 1) { #ifdef CONFIG_CMA di_devp->pdev = pdev; + di_devp->flags |= DI_MAP_FLAG; di_devp->mem_size = dma_get_cma_size_int_byte(&pdev->dev); pr_info("DI: CMA size 0x%x.\n", di_devp->mem_size); + if (di_devp->flag_cma == 2) { + if (di_cma_alloc_total(di_devp)) + atomic_set(&di_devp->mem_flag, 1); + } else #endif - mem_flag = 0; + atomic_set(&di_devp->mem_flag, 0); } else { - mem_flag = 1; + atomic_set(&di_devp->mem_flag, 1); } + mutex_init(&di_devp->cma_mutex); + INIT_LIST_HEAD(&di_devp->pq_table_list); + mutex_init(&di_devp->pq_lock); di_devp->di_irq = irq_of_parse_and_map(pdev->dev.of_node, 0); - di_devp->timerc_irq = irq_of_parse_and_map(pdev->dev.of_node, 1); - pr_info("di_irq:%d,timerc_irq:%d\n", - di_devp->di_irq, di_devp->timerc_irq); + pr_info("di_irq:%d\n", + di_devp->di_irq); #ifdef CONFIG_AMLOGIC_MEDIA_RDMA /* rdma handle */ - di_rdma_op.arg = di_devp; - di_devp->rdma_handle = rdma_register(&di_rdma_op, - di_devp, RDMA_TABLE_SIZE); + if (di_pre_rdma_enable) { + di_rdma_op.arg = di_devp; + di_devp->rdma_handle = rdma_register(&di_rdma_op, + di_devp, RDMA_TABLE_SIZE); + } #endif di_pr_info("%s allocate rdma channel %d.\n", __func__, di_devp->rdma_handle); - + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) { + di_get_vpu_clkb(&pdev->dev, di_devp); + clk_prepare_enable(di_devp->vpu_clkb); + } ret = of_property_read_u32(pdev->dev.of_node, "buffer-size", &(di_devp->buffer_size)); if (ret) pr_err("DI-%s: get buffer size error.\n", __func__); - ret = of_property_read_u32(pdev->dev.of_node, - "hw-version", &(di_devp->hw_version)); - if (ret) - pr_err("DI-%s: get hw version error.\n", __func__); - di_pr_info("DI hw version %u.\n", di_devp->hw_version); - /* set flag to indicate that post_wr is surpportted */ + /* set flag to indicate that post_wr is supportted */ ret = of_property_read_u32(pdev->dev.of_node, - "post-wr-surpport", - &(di_devp->post_wr_surpport)); + "post-wr-support", + &(di_devp->post_wr_support)); if (ret) - post_wr_surpport = 0; + post_wr_support = 0; else - post_wr_surpport = di_devp->post_wr_surpport; + post_wr_support = di_devp->post_wr_support; ret = of_property_read_u32(pdev->dev.of_node, - "nr10bit-surpport", - &(di_devp->nr10bit_surpport)); + "nr10bit-support", + &(di_devp->nr10bit_support)); if (ret) - nr10bit_surpport = 0; + nr10bit_support = 0; else - nr10bit_surpport = di_devp->nr10bit_surpport; + nr10bit_support = di_devp->nr10bit_support; memset(&di_post_stru, 0, sizeof(di_post_stru)); di_post_stru.next_canvas_id = 1; @@ -7517,79 +7111,52 @@ static int di_probe(struct platform_device *pdev) #endif /* call di_add_reg_cfg() */ - di_add_reg_cfg_init(); device_create_file(di_devp->dev, &dev_attr_config); device_create_file(di_devp->dev, &dev_attr_debug); device_create_file(di_devp->dev, &dev_attr_dump_pic); device_create_file(di_devp->dev, &dev_attr_log); - device_create_file(di_devp->dev, &dev_attr_status); device_create_file(di_devp->dev, &dev_attr_provider_vframe_status); device_create_file(di_devp->dev, &dev_attr_frame_format); - device_create_file(di_devp->dev, &dev_attr_pd_param); device_create_file(di_devp->dev, &dev_attr_tvp_region); + pd_device_files_add(di_devp->dev); + nr_drv_init(di_devp->dev); -#ifdef NEW_DI_V4 - nr_init(di_devp->dev); -#endif -/* get resource as memory,irq...*/ -/* mem = &memobj; */ - for (i = 0; i < USED_LOCAL_BUF_MAX; i++) - used_local_buf_index[i] = -1; - - used_post_buf_index = -1; init_flag = 0; reg_flag = 0; - field_count = 0; -/* set start_frame_hold_count base on buffer size */ di_devp->buf_num_avail = di_devp->mem_size / di_devp->buffer_size; if (di_devp->buf_num_avail > MAX_LOCAL_BUF_NUM) di_devp->buf_num_avail = MAX_LOCAL_BUF_NUM; - buf_num_avail = di_devp->buf_num_avail; -/**/ - vf_receiver_init(&di_vf_recv, VFM_NAME, &di_vf_receiver, NULL); vf_reg_receiver(&di_vf_recv); + vf_provider_init(&di_vf_prov, VFM_NAME, &deinterlace_vf_provider, NULL); active_flag = 1; -/* data32 = (*P_A9_0_IRQ_IN1_INTR_STAT_CLR); */ ret = request_irq(di_devp->di_irq, &de_irq, IRQF_SHARED, "deinterlace", (void *)"deinterlace"); sema_init(&di_sema, 1); di_sema_init_flag = 1; - di_hw_init(); - - if (pulldown_enable) - FlmVOFSftInt(&pd_param); + di_hw_init(pulldown_enable, mcpre_en); set_di_flag(); /* Disable MCDI when code does not surpport MCDI */ if (!mcpre_en) DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 0, 1); -/* timer */ - INIT_WORK(&di_pre_work, di_timer_handle); - init_timer(&di_pre_timer); - di_pre_timer.data = (ulong) &di_pre_timer; - di_pre_timer.function = di_pre_timer_cb; - di_pre_timer.expires = jiffies + DI_PRE_INTERVAL; - add_timer(&di_pre_timer); -/**/ + tasklet_init(&di_pre_tasklet, pre_tasklet, + (unsigned long)(&di_pre_stru)); + tasklet_disable(&di_pre_tasklet); + hrtimer_init(&di_pre_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + di_pre_hrtimer.function = di_pre_hrtimer_func; + hrtimer_start(&di_pre_hrtimer, ms_to_ktime(10), HRTIMER_MODE_REL); + tasklet_enable(&di_pre_tasklet); + di_pr_info("%s:Di use HRTIMER\n", __func__); di_devp->task = kthread_run(di_task_handle, di_devp, "kthread_di"); - di_pr_info("%s here.\n", __func__); - - aml_cbus_update_bits(ISA_TIMER_MUX, 1 << 14, 0 << 14); - aml_cbus_update_bits(ISA_TIMER_MUX, 3 << 4, 0 << 4); - aml_cbus_update_bits(ISA_TIMER_MUX, 1 << 18, 1 << 18); - - ret = request_irq(di_devp->timerc_irq, &timer_irq, - IRQF_SHARED, "timerC", - (void *)"timerC"); - di_set_power_control(0, 0); - di_set_power_control(1, 0); + if (IS_ERR(di_devp->task)) + pr_err("%s create kthread error.\n", __func__); fail_kmalloc_dev: return ret; } @@ -7600,9 +7167,15 @@ static int di_remove(struct platform_device *pdev) di_devp = platform_get_drvdata(pdev); + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) + clk_disable_unprepare(di_devp->vpu_clkb); di_hw_uninit(); di_devp->di_event = 0xff; + mutex_destroy(&di_devp->pq_lock); kthread_stop(di_devp->task); + hrtimer_cancel(&di_pre_hrtimer); + tasklet_disable(&di_pre_tasklet); + tasklet_kill(&di_pre_tasklet); #ifdef CONFIG_AMLOGIC_MEDIA_RDMA /* rdma handle */ if (di_devp->rdma_handle > 0) @@ -7613,17 +7186,29 @@ static int di_remove(struct platform_device *pdev) vf_unreg_receiver(&di_vf_recv); di_uninit_buf(); - di_set_power_control(0, 0); - di_set_power_control(1, 0); /* Remove the cdev */ device_remove_file(di_devp->dev, &dev_attr_config); device_remove_file(di_devp->dev, &dev_attr_debug); device_remove_file(di_devp->dev, &dev_attr_log); device_remove_file(di_devp->dev, &dev_attr_dump_pic); - device_remove_file(di_devp->dev, &dev_attr_status); - + device_remove_file(di_devp->dev, &dev_attr_provider_vframe_status); + device_remove_file(di_devp->dev, &dev_attr_frame_format); + device_remove_file(di_devp->dev, &dev_attr_tvp_region); + pd_device_files_del(di_devp->dev); + nr_drv_uninit(di_devp->dev); cdev_del(&di_devp->cdev); + if (di_devp->flag_cma == 2) { + if (dma_release_from_contiguous(&(pdev->dev), + di_devp->total_pages, + di_devp->mem_size >> PAGE_SHIFT)) { + di_devp->total_pages = NULL; + di_devp->mem_start = 0; + pr_dbg("DI CMA total release ok.\n"); + } else { + pr_dbg("DI CMA total release fail.\n"); + } + } device_destroy(di_clsp, di_devno); kfree(di_devp); /* free drvdata */ @@ -7633,20 +7218,43 @@ static int di_remove(struct platform_device *pdev) return 0; } +static void di_shutdown(struct platform_device *pdev) +{ + struct di_dev_s *di_devp = NULL; + int ret = 0; + + di_devp = platform_get_drvdata(pdev); + ret = hrtimer_cancel(&di_pre_hrtimer); + pr_info("di pre hrtimer canel %d.\n", ret); + tasklet_disable(&di_pre_tasklet); + tasklet_kill(&di_pre_tasklet); + init_flag = 0; + if (is_meson_txlx_cpu()) + di_top_gate_control(true, true); + else + DI_Wr(DI_CLKG_CTRL, 0x2); + + if (!is_meson_txlx_cpu()) + switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, + VPU_CLK_GATE_OFF); + kfree(di_devp); + pr_info("[DI] shutdown done.\n"); + +} + #ifdef CONFIG_PM static int save_init_flag; -static int save_mem_flag; -static int di_suspend(struct platform_device *pdev, pm_message_t state) +/* must called after lcd */ +static int di_suspend(struct device *dev) { - aml_cbus_update_bits(ISA_TIMER_MUX, 1 << 18, 0 << 18); + struct di_dev_s *di_devp = NULL; -/* fix suspend/resume crash problem */ + di_devp = dev_get_drvdata(dev); + di_devp->flags |= DI_SUSPEND_FLAG; + /* fix suspend/resume crash problem */ save_init_flag = init_flag; - save_mem_flag = mem_flag; init_flag = 0; - mem_flag = 0; - field_count = 0; if (di_pre_stru.di_inp_buf) { if (vframe_in[di_pre_stru.di_inp_buf->index]) { vf_put(vframe_in[di_pre_stru.di_inp_buf->index], @@ -7658,28 +7266,32 @@ static int di_suspend(struct platform_device *pdev, pm_message_t state) } - di_set_power_control(0, 0); - di_set_power_control(1, 0); - di_pr_info("di: di_suspend\n"); + if (!is_meson_txlx_cpu()) + switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, + VPU_CLK_GATE_OFF); + if (is_meson_txhd_cpu()) + clk_disable_unprepare(di_devp->vpu_clkb); + pr_info("di: di_suspend\n"); return 0; } - -static int di_resume(struct platform_device *pdev) +/* must called before lcd */ +static int di_resume(struct device *dev) { - init_flag = save_init_flag; - mem_flag = save_mem_flag; - if (init_flag && mem_flag) { - di_set_power_control(0, 1); - di_set_power_control(1, 1); - } + struct di_dev_s *di_devp = NULL; - aml_cbus_update_bits(ISA_TIMER_MUX, 1 << 14, 0 << 14); - aml_cbus_update_bits(ISA_TIMER_MUX, 3 << 4, 0 << 4); - aml_cbus_update_bits(ISA_TIMER_MUX, 1 << 18, 1 << 18); - aml_write_cbus(ISA_TIMERC, 1); - di_pr_info("di_hdmirx: resume module\n"); + di_devp = dev_get_drvdata(dev); + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) + clk_prepare_enable(di_devp->vpu_clkb); + init_flag = save_init_flag; + di_devp->flags &= ~DI_SUSPEND_FLAG; + pr_info("di: resume module\n"); return 0; } + +static const struct dev_pm_ops di_pm_ops = { + .suspend_late = di_suspend, + .resume_early = di_resume, +}; #endif /* #ifdef CONFIG_USE_OF */ @@ -7694,14 +7306,14 @@ static const struct of_device_id amlogic_deinterlace_dt_match[] = { static struct platform_driver di_driver = { .probe = di_probe, .remove = di_remove, -#ifdef CONFIG_PM - .suspend = di_suspend, - .resume = di_resume, -#endif + .shutdown = di_shutdown, .driver = { .name = DEVICE_NAME, .owner = THIS_MODULE, .of_match_table = amlogic_deinterlace_dt_match, +#ifdef CONFIG_PM + .pm = &di_pm_ops, +#endif } }; @@ -7710,8 +7322,6 @@ static int __init di_module_init(void) int ret = 0; di_pr_info("%s ok.\n", __func__); - if (boot_init_flag & INIT_FLAG_NOT_LOAD) - return 0; ret = alloc_chrdev_region(&di_devno, 0, DI_COUNT, DEVICE_NAME); if (ret < 0) { @@ -7740,7 +7350,6 @@ fail_alloc_cdev_region: return ret; } - static void __exit di_module_exit(void) { class_destroy(di_clsp); @@ -7751,84 +7360,6 @@ static void __exit di_module_exit(void) module_init(di_module_init); module_exit(di_module_exit); -static char *next_token_ex(char *separator, char *buf, unsigned int size, - unsigned int offset, unsigned int *token_len, - unsigned int *token_offset) -{ - /* besides characters defined in separator, '\"' are used as - * separator; and any characters in '\"' will not act as separator - */ - char *pToken = NULL; - char last_separator = 0; - char trans_char_flag = 0; - - if (buf) { - for (; offset < size; offset++) { - int ii = 0; - char ch; - - if (buf[offset] == '\\') { - trans_char_flag = 1; - continue; - } - while (((ch = separator[ii]) != buf[offset]) && (ch)) - ii++; - if (ch) { - if (!pToken) { - continue; - } else { - if (last_separator != '"') { - *token_len = (unsigned int) - (buf + offset - pToken); - *token_offset = offset; - return pToken; - } - } - } else if (!pToken) { - if (trans_char_flag && (buf[offset] == '"')) - last_separator = buf[offset]; - pToken = &buf[offset]; - } else if ( - (trans_char_flag && (buf[offset] == '"')) && - (last_separator == '"')) { - *token_len = - (unsigned int)(buf + offset - pToken - 2); - *token_offset = offset + 1; - return pToken + 1; - } - trans_char_flag = 0; - } - if (pToken) { - *token_len = (unsigned int)(buf + offset - pToken); - *token_offset = offset; - } - } - return pToken; -} - -static int __init di_boot_para_setup(char *s) -{ - char separator[] = { ' ', ',', ';', 0x0 }; - char *token; - unsigned int token_len, token_offset, offset = 0; - int size = strlen(s); - - do { - token = next_token_ex(separator, s, size, - offset, &token_len, &token_offset); - if (token) { - if ((token_len == 3) && - (strncmp(token, "off", token_len) == 0)) { - boot_init_flag |= INIT_FLAG_NOT_LOAD; - pr_info("DI: NOT LOAD\n"); - } - } - offset = token_offset; - } while (token); - return 0; -} - -__setup("di=", di_boot_para_setup); module_param_named(bypass_all, bypass_all, int, 0664); module_param_named(bypass_3d, bypass_3d, int, 0664); @@ -7837,7 +7368,6 @@ module_param_named(invert_top_bot, invert_top_bot, int, 0664); module_param_named(skip_top_bot, skip_top_bot, int, 0664); module_param_named(force_width, force_width, int, 0664); module_param_named(prog_proc_config, prog_proc_config, int, 0664); -module_param_named(skip_wrong_field, skip_wrong_field, int, 0664); module_param_named(start_frame_drop_count, start_frame_drop_count, int, 0664); #ifdef SUPPORT_START_FRAME_HOLD module_param_named(start_frame_hold_count, start_frame_hold_count, int, 0664); @@ -7846,8 +7376,6 @@ module_param_named(same_field_top_count, same_field_top_count, long, 0664); module_param_named(same_field_bot_count, same_field_bot_count, long, 0664); -module_param_named(same_field_source_flag_th, same_field_source_flag_th, - int, 0664); MODULE_PARM_DESC(di_log_flag, "\n di log flag\n"); module_param(di_log_flag, int, 0664); @@ -7860,9 +7388,6 @@ module_param(buf_state_log_threshold, int, 0664); MODULE_PARM_DESC(bypass_state, "\n bypass_state\n"); module_param(bypass_state, uint, 0664); -MODULE_PARM_DESC(force_bob_flag, "\n force_bob_flag\n"); -module_param(force_bob_flag, uint, 0664); - MODULE_PARM_DESC(di_vscale_skip_enable, "\n di_vscale_skip_enable\n"); module_param(di_vscale_skip_enable, uint, 0664); @@ -7892,9 +7417,6 @@ module_param(post_hold_line, uint, 0664); MODULE_PARM_DESC(post_urgent, "\n post_urgent\n"); module_param(post_urgent, uint, 0664); -MODULE_PARM_DESC(force_duration_0, "\n force_duration_0\n"); -module_param(force_duration_0, uint, 0664); - MODULE_PARM_DESC(di_printk_flag, "\n di_printk_flag\n"); module_param(di_printk_flag, uint, 0664); @@ -7906,29 +7428,25 @@ module_param_named(pre_process_time_force, pre_process_time_force, uint, 0664); module_param_named(pre_process_time, pre_process_time, uint, 0664); module_param_named(bypass_post, bypass_post, uint, 0664); module_param_named(post_wr_en, post_wr_en, bool, 0664); -module_param_named(post_wr_surpport, post_wr_surpport, uint, 0664); +module_param_named(post_wr_support, post_wr_support, uint, 0664); module_param_named(bypass_post_state, bypass_post_state, uint, 0664); -module_param_named(force_update_post_reg, force_update_post_reg, uint, 0664); -module_param_named(update_post_reg_count, update_post_reg_count, uint, 0664); /* n debug for progress interlace mixed source */ module_param_named(use_2_interlace_buff, use_2_interlace_buff, int, 0664); module_param_named(debug_blend_mode, debug_blend_mode, int, 0664); MODULE_PARM_DESC(debug_blend_mode, "\n force post blend mode\n"); -module_param_named(nr10bit_surpport, nr10bit_surpport, uint, 0664); +module_param_named(nr10bit_support, nr10bit_support, uint, 0664); module_param_named(di_stop_reg_flag, di_stop_reg_flag, uint, 0664); +module_param(di_dbg_mask, uint, 0664); +MODULE_PARM_DESC(di_dbg_mask, "\n di_dbg_mask\n"); module_param_array(di_stop_reg_addr, uint, &num_di_stop_reg_addr, 0664); -module_param_named(static_pic_threshold, static_pic_threshold, int, 0664); module_param_named(mcpre_en, mcpre_en, bool, 0664); -#ifdef NEW_DI_V4 -module_param_named(dnr_en, dnr_en, bool, 0664); -#endif module_param_named(check_start_drop_prog, check_start_drop_prog, bool, 0664); module_param_named(overturn, overturn, bool, 0664); module_param_named(queue_print_flag, queue_print_flag, int, 0664); module_param_named(full_422_pack, full_422_pack, bool, 0644); #ifdef DEBUG_SUPPORT - +module_param_named(pulldown_enable, pulldown_enable, bool, 0644); #ifdef RUN_DI_PROCESS_IN_IRQ module_param_named(input2pre, input2pre, uint, 0664); module_param_named(input2pre_buf_miss_count, input2pre_buf_miss_count, @@ -7940,19 +7458,17 @@ module_param_named(input2pre_throw_count, input2pre_throw_count, uint, 0664); #endif module_param_named(timeout_miss_policy, timeout_miss_policy, uint, 0664); -module_param_named(pldn_pst_wver, pldn_pst_wver, uint, 0644); +#ifdef SUPPORT_MPEG_TO_VDIN module_param_named(mpeg2vdin_en, mpeg2vdin_en, int, 0664); module_param_named(mpeg2vdin_flag, mpeg2vdin_flag, int, 0664); +#endif module_param_named(di_pre_rdma_enable, di_pre_rdma_enable, uint, 0664); module_param_named(pldn_dly, pldn_dly, uint, 0644); -module_param_named(tbbtff_dly, tbbtff_dly, uint, 0644); module_param_named(pldn_dly1, pldn_dly1, uint, 0644); -module_param_named(flm22_sure_num, flm22_sure_num, uint, 0644); -module_param_named(flm22_glbpxlnum_rat, flm22_glbpxlnum_rat, uint, 0644); +module_param_named(di_reg_unreg_cnt, di_reg_unreg_cnt, int, 0664); module_param_named(bypass_pre, bypass_pre, int, 0664); module_param_named(frame_count, frame_count, int, 0664); -module_param_named(same_w_r_canvas_count, same_w_r_canvas_count, long, 0664); #endif MODULE_DESCRIPTION("AMLOGIC DEINTERLACE driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION("1.0.0"); +MODULE_VERSION("4.0.0"); diff --git a/drivers/amlogic/media/deinterlace/deinterlace.h b/drivers/amlogic/media/deinterlace/deinterlace.h index 7efa759b38ad..7e167725a6bb 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace.h +++ b/drivers/amlogic/media/deinterlace/deinterlace.h @@ -20,86 +20,61 @@ #include #include #include + +#include #include -#include "film_vof_soft.h" -/* di hardware version m8m2*/ -#define NEW_DI_V1 0x00000002 /* from m6tvc */ -#define NEW_DI_V2 0x00000004 /* from m6tvd */ -#define NEW_DI_V3 0x00000008 /* from gx */ -#define NEW_DI_V4 0x00000010 /* dnr added */ +#include "deinterlace_hw.h" +#include "pulldown_drv.h" +#include "nr_drv.h" /*trigger_pre_di_process param*/ -#define TRIGGER_PRE_BY_PUT 'p' +#define TRIGGER_PRE_BY_PUT 'p' #define TRIGGER_PRE_BY_DE_IRQ 'i' #define TRIGGER_PRE_BY_UNREG 'u' /*di_timer_handle*/ -#define TRIGGER_PRE_BY_TIMER 't' -#define TRIGGER_PRE_BY_FORCE_UNREG 'f' -#define TRIGGER_PRE_BY_VFRAME_READY 'r' +#define TRIGGER_PRE_BY_TIMER 't' +#define TRIGGER_PRE_BY_FORCE_UNREG 'f' +#define TRIGGER_PRE_BY_VFRAME_READY 'r' #define TRIGGER_PRE_BY_PROVERDER_UNREG 'n' #define TRIGGER_PRE_BY_DEBUG_DISABLE 'd' -#define TRIGGER_PRE_BY_TIMERC 'T' +#define TRIGGER_PRE_BY_TIMERC 'T' #define TRIGGER_PRE_BY_PROVERDER_REG 'R' +#define DI_RUN_FLAG_RUN 0 +#define DI_RUN_FLAG_PAUSE 1 +#define DI_RUN_FLAG_STEP 2 +#define DI_RUN_FLAG_STEP_DONE 3 + +#define USED_LOCAL_BUF_MAX 3 #define BYPASS_GET_MAX_BUF_NUM 4 + +/* buffer management related */ +#define MAX_IN_BUF_NUM 20 +#define MAX_LOCAL_BUF_NUM 12 +#define MAX_POST_BUF_NUM 16 + +#define VFRAME_TYPE_IN 1 +#define VFRAME_TYPE_LOCAL 2 +#define VFRAME_TYPE_POST 3 +#define VFRAME_TYPE_NUM 3 + /*vframe define*/ #define vframe_t struct vframe_s /* canvas defination */ #define DI_USE_FIXED_CANVAS_IDX - -#undef USE_LIST -/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ -#define NEW_KEEP_LAST_FRAME -/* #endif */ #define DET3D -#undef SUPPORT_MPEG_TO_VDIN /* for all ic after m6c@20140731 */ +#undef SUPPORT_MPEG_TO_VDIN -/************************************ - * di hardware level interface - *************************************/ -#define MAX_WIN_NUM 5 -/* if post size < 80, filter of ei can't work */ -#define MIN_POST_WIDTH 80 -#define MIN_BLEND_WIDTH 27 -struct pulldown_detect_info_s { - unsigned int field_diff; -/* total pixels difference between current field and previous field */ - unsigned int field_diff_num; -/* the number of pixels with big difference between - * current field and previous field - */ - unsigned int frame_diff; -/*total pixels difference between current field and previouse-previouse field*/ - unsigned int frame_diff_num; -/* the number of pixels with big difference between current - * field and previouse-previous field - */ - unsigned int frame_diff_skew; -/* the difference between current frame_diff and previous frame_diff */ - unsigned int frame_diff_num_skew; -/* the difference between current frame_diff_num and previous frame_diff_num*/ -/* parameters for detection */ - unsigned int field_diff_by_pre; - unsigned int field_diff_by_next; - unsigned int field_diff_num_by_pre; - unsigned int field_diff_num_by_next; - unsigned int frame_diff_by_pre; - unsigned int frame_diff_num_by_pre; - unsigned int frame_diff_skew_ratio; - unsigned int frame_diff_num_skew_ratio; - /* matching pattern */ - unsigned int field_diff_pattern; - unsigned int field_diff_num_pattern; - unsigned int frame_diff_pattern; - unsigned int frame_diff_num_pattern; -}; -#define pulldown_detect_info_t struct pulldown_detect_info_s +#ifndef CONFIG_AMLOGIC_MEDIA_RDMA +#ifndef VSYNC_WR_MPEG_REG +#define VSYNC_WR_MPEG_REG(adr, val) aml_write_vcbus(adr, val) +#define VSYNC_WR_MPEG_REG_BITS(adr, val, start, len) \ + aml_vcbus_update_bits(adr, ((1<nr2_cnt * 3 (f3,nr2_cnt,nr1_cnt)->nr3_cnt */ -#endif struct DI_MC_MIF_s di_mcinford_mif; struct DI_MC_MIF_s di_mcvecwr_mif; struct DI_MC_MIF_s di_mcinfowr_mif; @@ -498,8 +262,10 @@ struct di_pre_stru_s { /* flag is set when VFRAME_EVENT_PROVIDER_UNREG*/ int unreg_req_flag; int unreg_req_flag_irq; + int unreg_req_flag_cnt; int reg_req_flag; int reg_req_flag_irq; + int reg_req_flag_cnt; int force_unreg_req_flag; int disable_req_flag; /* current source info */ @@ -512,23 +278,23 @@ struct di_pre_stru_s { int cur_prog_flag; /* 1 for progressive source */ /* valid only when prog_proc_type is 0, for * progressive source: top field 1, bot field 0 - */ +*/ int source_change_flag; +/* input size change flag, 1: need reconfig pre/nr/dnr size */ +/* 0: not need config pre/nr/dnr size*/ + bool input_size_change_flag; /* true: bypass di all logic, false: not bypass */ bool bypass_flag; - unsigned char prog_proc_type; /* set by prog_proc_config when source is vdin,0:use 2 i * serial buffer,1:use 1 p buffer,3:use 2 i paralleling buffer - */ +*/ unsigned char buf_alloc_mode; /* alloc di buf as p or i;0: alloc buf as i; * 1: alloc buf as p; - */ +*/ unsigned char enable_mtnwr; unsigned char enable_pulldown_check; - - int same_field_source_flag; int left_right;/*1,left eye; 0,right eye in field alternative*/ /*input2pre*/ int bypass_start_count; @@ -540,16 +306,20 @@ struct di_pre_stru_s { unsigned int det_tp; unsigned int det_la; unsigned int det_null; + unsigned int width_bk; #ifdef DET3D int vframe_interleave_flag; #endif +/**/ int pre_de_irq_timeout_count; int pre_throw_flag; + int bad_frame_throw_count; /*for static pic*/ int static_frame_count; bool force_interlace; bool bypass_pre; bool invert_flag; + bool vdin_source; int nr_size; int count_size; int mcinfo_size; @@ -558,6 +328,10 @@ struct di_pre_stru_s { int cma_alloc_req; int cma_alloc_done; int cma_release_req; + /* for performance debug */ + unsigned long irq_time; + /* combing adaptive */ + struct combing_status_s *mtn_status; }; struct di_post_stru_s { @@ -568,8 +342,8 @@ struct di_post_stru_s { struct DI_SIM_MIF_s di_mtnprd_mif; struct DI_MC_MIF_s di_mcvecrd_mif; struct di_buf_s *cur_post_buf; + struct di_buf_s *keep_buf; int update_post_reg_flag; - int post_process_fun_index; int run_early_proc_fun_flag; int cur_disp_index; int canvas_id; @@ -581,17 +355,27 @@ struct di_post_stru_s { int de_post_process_done; int post_de_busy; int di_post_num; + unsigned int di_post_process_cnt; + unsigned int check_recycle_buf_cnt; + /* performance debug */ + unsigned int post_wr_cnt; + unsigned long irq_time; }; #define MAX_QUEUE_POOL_SIZE 256 struct queue_s { - int num; - int in_idx; - int out_idx; - int type; /* 0, first in first out; + unsigned int num; + unsigned int in_idx; + unsigned int out_idx; + unsigned int type; /* 0, first in first out; * 1, general;2, fix position for di buf */ - unsigned int pool[MAX_QUEUE_POOL_SIZE]; + unsigned int pool[MAX_QUEUE_POOL_SIZE]; +}; + +struct di_buf_pool_s { + struct di_buf_s *di_buf_ptr; + unsigned int size; }; #define di_dev_t struct di_dev_s diff --git a/drivers/amlogic/media/deinterlace/deinterlace_dbg.c b/drivers/amlogic/media/deinterlace/deinterlace_dbg.c index 0159a1d60e1d..64ea2bdce9af 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_dbg.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_dbg.c @@ -56,55 +56,119 @@ void parse_cmd_params(char *buf_orig, char **parm) void dump_di_reg(void) { - unsigned int i = 0; + unsigned int i = 0, base_addr = 0; + unsigned int size_reg_addr[57] = { + 0x1702, 0x1703, 0x2d01, + 0x2d01, 0x2d8f, 0x2d08, + 0x2d09, 0x2f00, 0x2f01, + 0x17d0, 0x17d1, 0x17d2, + 0x17d3, 0x17dd, 0x17de, + 0x17df, 0x17e0, 0x17f7, + 0x17f8, 0x17f9, 0x17fa, + 0x17c0, 0x17c1, 0x17a0, + 0x17a1, 0x17c3, 0x17c4, + 0x17cb, 0x17cc, 0x17a3, + 0x17a4, 0x17a5, 0x17a6, + 0x2f92, 0x2f93, 0x2f95, + 0x2f96, 0x2f98, 0x2f99, + 0x2f9b, 0x2f9c, 0x2f65, + 0x2f66, 0x2f67, 0x2f68, + 0x1a53, 0x1a54, 0x1a55, + 0x1a56, 0x17ea, 0x17eb, + 0x17ec, 0x17ed, 0x2012, + 0x2013, 0x2014, 0x2015 + }; + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) + base_addr = 0xff900000; + else + base_addr = 0xd0100000; - pr_info("----dump di reg----\n"); - for (i = 0; i < 255; i++) { - if (i == 0x45) - pr_info("----nr reg----"); - if (i == 0x80) - pr_info("----3d reg----"); - if (i == 0x9e) - pr_info("---nr reg done---"); - if (i == 0x9c) - pr_info("---3d reg done---"); - pr_info("[0x%x][0x%x]=0x%x\n", - 0xd0100000 + ((0x1700 + i) << 2), - 0x1700 + i, RDMA_RD(0x1700 + i)); - } - pr_info("----dump mcdi reg----\n"); - for (i = 0; i < 201; i++) - pr_info("[0x%x][0x%x]=0x%x\n", - 0xd0100000 + ((0x2f00 + i) << 2), - 0x2f00 + i, RDMA_RD(0x2f00 + i)); - pr_info("----dump pulldown reg----\n"); - for (i = 0; i < 26; i++) - pr_info("[0x%x][0x%x]=0x%x\n", - 0xd0100000 + ((0x2fd0 + i) << 2), - 0x2fd0 + i, RDMA_RD(0x2fd0 + i)); - pr_info("----dump bit mode reg----\n"); - for (i = 0; i < 4; i++) - pr_info("[0x%x][0x%x]=0x%x\n", - 0xd0100000 + ((0x20a7 + i) << 2), - 0x20a7 + i, RDMA_RD(0x20a7 + i)); + pr_info("----dump di reg----\n"); + pr_info("----dump size reg---"); + for (i = 0; i < 57; i++) pr_info("[0x%x][0x%x]=0x%x\n", - 0xd0100000 + (0x2022 << 2), - 0x2022, RDMA_RD(0x2022)); + base_addr + ((size_reg_addr[i]) << 2), + size_reg_addr[i], RDMA_RD(size_reg_addr[i])); + for (i = 0; i < 255; i++) { + if (i == 0x45) + pr_info("----nr reg----"); + if (i == 0x80) + pr_info("----3d reg----"); + if (i == 0x9e) + pr_info("---nr reg done---"); + if (i == 0x9c) + pr_info("---3d reg done---"); pr_info("[0x%x][0x%x]=0x%x\n", - 0xd0100000 + (0x17c1 << 2), - 0x17c1, RDMA_RD(0x17c1)); + base_addr + ((0x1700 + i) << 2), + 0x1700 + i, RDMA_RD(0x1700 + i)); + } + pr_info("----dump mcdi reg----\n"); + for (i = 0; i < 201; i++) pr_info("[0x%x][0x%x]=0x%x\n", - 0xd0100000 + (0x17c2 << 2), - 0x17c2, RDMA_RD(0x17c2)); + base_addr + ((0x2f00 + i) << 2), + 0x2f00 + i, RDMA_RD(0x2f00 + i)); + pr_info("----dump pulldown reg----\n"); + for (i = 0; i < 26; i++) pr_info("[0x%x][0x%x]=0x%x\n", - 0xd0100000 + (0x1aa7 << 2), - 0x1aa7, RDMA_RD(0x1aa7)); - pr_info("----dump dnr reg----\n"); - for (i = 0; i < 29; i++) - pr_info("[0x%x][0x%x]=0x%x\n", - 0xd0100000 + ((0x2d00 + i) << 2), - 0x2d00 + i, RDMA_RD(0x2d00 + i)); - pr_info("----dump reg done----\n"); + base_addr + ((0x2fd0 + i) << 2), + 0x2fd0 + i, RDMA_RD(0x2fd0 + i)); + pr_info("----dump bit mode reg----\n"); + for (i = 0; i < 4; i++) + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + ((0x20a7 + i) << 2), + 0x20a7 + i, RDMA_RD(0x20a7 + i)); + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + (0x2022 << 2), + 0x2022, RDMA_RD(0x2022)); + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + (0x17c1 << 2), + 0x17c1, RDMA_RD(0x17c1)); + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + (0x17c2 << 2), + 0x17c2, RDMA_RD(0x17c2)); + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + (0x1aa7 << 2), + 0x1aa7, RDMA_RD(0x1aa7)); + pr_info("----dump dnr reg----\n"); + for (i = 0; i < 29; i++) + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + ((0x2d00 + i) << 2), + 0x2d00 + i, RDMA_RD(0x2d00 + i)); + pr_info("----dump if0 reg----\n"); + for (i = 0; i < 26; i++) + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + ((0x1a60 + i) << 2), + 0x1a50 + i, RDMA_RD(0x1a50 + i)); + pr_info("----dump gate reg----\n"); + pr_info("[0x%x][0x1718]=0x%x\n", + base_addr + ((0x1718) << 2), + RDMA_RD(0x1718)); + for (i = 0; i < 5; i++) + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + ((0x2006 + i) << 2), + 0x2006 + i, RDMA_RD(0x2006 + i)); + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + ((0x2dff) << 2), + 0x2dff, RDMA_RD(0x2dff)); + pr_info("----dump if2 reg----\n"); + for (i = 0; i < 29; i++) + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + ((0x2010 + i) << 2), + 0x2010 + i, RDMA_RD(0x2010 + i)); + pr_info("----dump nr4 reg----\n"); + for (i = 0x2da4; i < 0x2df6; i++) + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + (i << 2), + i, RDMA_RD(i)); + for (i = 0x3700; i < 0x373f; i++) + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + (i << 2), + i, RDMA_RD(i)); + for (i = 0; i < 57; i++) + pr_info("[0x%x][0x%x]=0x%x\n", + base_addr + ((size_reg_addr[i]) << 2), + size_reg_addr[i], RDMA_RD(size_reg_addr[i])); + pr_info("----dump reg done----\n"); } void dump_di_pre_stru(struct di_pre_stru_s *di_pre_stru_p) @@ -154,8 +218,6 @@ void dump_di_pre_stru(struct di_pre_stru_s *di_pre_stru_p) di_pre_stru_p->enable_mtnwr); pr_info("enable_pulldown_check = %d\n", di_pre_stru_p->enable_pulldown_check); - pr_info("same_field_source_flag = %d\n", - di_pre_stru_p->same_field_source_flag); #ifdef DET3D pr_info("vframe_interleave_flag = %d\n", di_pre_stru_p->vframe_interleave_flag); @@ -197,7 +259,7 @@ void dump_di_buf(struct di_buf_s *di_buf) di_buf->seq, di_buf->pre_ref_count, di_buf->post_ref_count, di_buf->queue_index); pr_info("pulldown_mode %d process_fun_index %d\n", - di_buf->pulldown_mode, di_buf->process_fun_index); + di_buf->pd_config.global_mode, di_buf->process_fun_index); pr_info("di_buf: %p, %p, di_buf_dup_p: %p, %p, %p, %p, %p\n", di_buf->di_buf[0], di_buf->di_buf[1], di_buf->di_buf_dup_p[0], di_buf->di_buf_dup_p[1], di_buf->di_buf_dup_p[2], @@ -292,4 +354,91 @@ void print_di_buf(struct di_buf_s *di_buf, int format) } } } +void dump_pre_mif_state(void) +{ + unsigned int i = 0; + + Wr_reg_bits(DI_INP_GEN_REG3, 3, 10, 2); + Wr_reg_bits(DI_MEM_GEN_REG3, 3, 10, 2); + Wr_reg_bits(DI_CHAN2_GEN_REG3, 3, 10, 2); + pr_info("DI_INP_GEN_REG2=0x%x.\n", Rd(DI_INP_GEN_REG2)); + pr_info("DI_INP_GEN_REG3=0x%x.\n", Rd(DI_INP_GEN_REG3)); + pr_info("DI_INP_LUMA_FIFO_SIZE=0x%x.\n", Rd(DI_INP_LUMA_FIFO_SIZE)); + pr_info("DI_INP_RANGE_MAP_Y=0x%x.\n", Rd(DI_INP_RANGE_MAP_Y)); + pr_info("DI_INP_RANGE_MAP_CB=0x%x.\n", Rd(DI_INP_RANGE_MAP_CB)); + pr_info("DI_INP_RANGE_MAP_CR=0x%x.\n", Rd(DI_INP_RANGE_MAP_CR)); + pr_info("DI_INP_URGENT_CTRL=0x%x.\n", Rd(DI_INP_URGENT_CTRL)); + for (i = 0; i < 10; i++) + pr_info("0x%x=0x%x.\n", 0x17ce + i, Rd(0x17ce + i)); + pr_info("DI_MEM_GEN_REG2=0x%x.\n", Rd(DI_MEM_GEN_REG2)); + pr_info("DI_MEM_GEN_REG3=0x%x.\n", Rd(DI_MEM_GEN_REG3)); + pr_info("DI_MEM_LUMA_FIFO_SIZE=0x%x.\n", Rd(DI_MEM_LUMA_FIFO_SIZE)); + pr_info("DI_MEM_RANGE_MAP_CB=0x%x.\n", Rd(DI_MEM_RANGE_MAP_CB)); + pr_info("DI_MEM_RANGE_MAP_CR=0x%x.\n", Rd(DI_MEM_RANGE_MAP_CR)); + pr_info("DI_MEM_URGENT_CTRL=0x%x.\n", Rd(DI_MEM_URGENT_CTRL)); + for (i = 0; i < 10; i++) + pr_info("0x%x=0x%x.\n", 0x17db + i, Rd(0x17db + i)); + pr_info("DI_CHAN2_GEN_REG2=0x%x.\n", Rd(DI_CHAN2_GEN_REG2)); + pr_info("DI_CHAN2_GEN_REG3=0x%x.\n", Rd(DI_CHAN2_GEN_REG3)); + pr_info("DI_CHAN2_LUMA_FIFO_SIZE=0x%x.\n", Rd(DI_CHAN2_LUMA_FIFO_SIZE)); + pr_info("DI_CHAN2_RANGE_MAP_CB=0x%x.\n", Rd(DI_CHAN2_RANGE_MAP_CB)); + pr_info("DI_CHAN2_RANGE_MAP_CR=0x%x.\n", Rd(DI_CHAN2_RANGE_MAP_CR)); + pr_info("DI_CHAN2_URGENT_CTRL=0x%x.\n", Rd(DI_CHAN2_URGENT_CTRL)); + for (i = 0; i < 10; i++) + pr_info("0x%x=0x%x.\n", 0x17f5 + i, Rd(0x17f5 + i)); +} + +void dump_post_mif_reg(void) +{ + pr_info("VIU_MISC_CTRL0=0x%x\n", Rd(VIU_MISC_CTRL0)); + + pr_info("VD1_IF0_GEN_REG=0x%x\n", Rd(VD1_IF0_GEN_REG)); + pr_info("VD1_IF0_GEN_REG2=0x%x\n", Rd(VD1_IF0_GEN_REG2)); + pr_info("VD1_IF0_GEN_REG3=0x%x\n", Rd(VD1_IF0_GEN_REG3)); + pr_info("VD1_IF0_LUMA_X0=0x%x\n", Rd(VD1_IF0_LUMA_X0)); + pr_info("VD1_IF0_LUMA_Y0=0x%x\n", Rd(VD1_IF0_LUMA_Y0)); + pr_info("VD1_IF0_CHROMA_X0=0x%x\n", Rd(VD1_IF0_CHROMA_X0)); + pr_info("VD1_IF0_CHROMA_Y0=0x%x\n", Rd(VD1_IF0_CHROMA_Y0)); + pr_info("VD1_IF0_LUMA_X1=0x%x\n", Rd(VD1_IF0_LUMA_X1)); + pr_info("VD1_IF0_LUMA_Y1=0x%x\n", Rd(VD1_IF0_LUMA_Y1)); + pr_info("VD1_IF0_CHROMA_X1=0x%x\n", Rd(VD1_IF0_CHROMA_X1)); + pr_info("VD1_IF0_CHROMA_Y1=0x%x\n", Rd(VD1_IF0_CHROMA_Y1)); + pr_info("VD1_IF0_REPEAT_LOOP=0x%x\n", Rd(VD1_IF0_RPT_LOOP)); + pr_info("VD1_IF0_LUMA0_RPT_PAT=0x%x\n", Rd(VD1_IF0_LUMA0_RPT_PAT)); + pr_info("VD1_IF0_CHROMA0_RPT_PAT=0x%x\n", Rd(VD1_IF0_CHROMA0_RPT_PAT)); + pr_info("VD1_IF0_LUMA_PSEL=0x%x\n", Rd(VD1_IF0_LUMA_PSEL)); + pr_info("VD1_IF0_CHROMA_PSEL=0x%x\n", Rd(VD1_IF0_CHROMA_PSEL)); + pr_info("VIU_VD1_FMT_CTRL=0x%x\n", Rd(VIU_VD1_FMT_CTRL)); + pr_info("VIU_VD1_FMT_W=0x%x\n", Rd(VIU_VD1_FMT_W)); + + pr_info("DI_IF1_GEN_REG=0x%x\n", Rd(DI_IF1_GEN_REG)); + pr_info("DI_IF1_GEN_REG2=0x%x\n", Rd(DI_IF1_GEN_REG2)); + pr_info("DI_IF1_GEN_REG3=0x%x\n", Rd(DI_IF1_GEN_REG3)); + pr_info("DI_IF1_CANVAS0=0x%x\n", Rd(DI_IF1_CANVAS0)); + pr_info("DI_IF1_LUMA_X0=0x%x\n", Rd(DI_IF1_LUMA_X0)); + pr_info("DI_IF1_LUMA_Y0=0x%x\n", Rd(DI_IF1_LUMA_Y0)); + pr_info("DI_IF1_CHROMA_X0=0x%x\n", Rd(DI_IF1_CHROMA_X0)); + pr_info("DI_IF1_CHROMA_Y0=0x%x\n", Rd(DI_IF1_CHROMA_Y0)); + pr_info("DI_IF1_LUMA0_RPT_PAT=0x%x\n", Rd(DI_IF1_LUMA0_RPT_PAT)); + pr_info("DI_IF1_CHROMA0_RPT_PAT=0x%x\n", Rd(DI_IF1_LUMA0_RPT_PAT)); + pr_info("DI_IF1_FMT_CTRL=0x%x\n", Rd(DI_IF1_FMT_CTRL)); + pr_info("DI_IF1_FMT_W=0x%x\n", Rd(DI_IF1_FMT_W)); + + pr_info("DI_IF2_GEN_REG=0x%x\n", Rd(DI_IF2_GEN_REG)); + pr_info("DI_IF2_GEN_REG2=0x%x\n", Rd(DI_IF2_GEN_REG2)); + pr_info("DI_IF2_GEN_REG3=0x%x\n", Rd(DI_IF2_GEN_REG3)); + pr_info("DI_IF2_CANVAS0=0x%x\n", Rd(DI_IF2_CANVAS0)); + pr_info("DI_IF2_LUMA_X0=0x%x\n", Rd(DI_IF2_LUMA_X0)); + pr_info("DI_IF2_LUMA_Y0=0x%x\n", Rd(DI_IF2_LUMA_Y0)); + pr_info("DI_IF2_CHROMA_X0=0x%x\n", Rd(DI_IF2_CHROMA_X0)); + pr_info("DI_IF2_CHROMA_Y0=0x%x\n", Rd(DI_IF2_CHROMA_Y0)); + pr_info("DI_IF2_LUMA0_RPT_PAT=0x%x\n", Rd(DI_IF2_LUMA0_RPT_PAT)); + pr_info("DI_IF2_CHROMA0_RPT_PAT=0x%x\n", Rd(DI_IF2_LUMA0_RPT_PAT)); + pr_info("DI_IF2_FMT_CTRL=0x%x\n", Rd(DI_IF2_FMT_CTRL)); + pr_info("DI_IF2_FMT_W=0x%x\n", Rd(DI_IF2_FMT_W)); + + pr_info("DI_DIWR_Y=0x%x\n", Rd(DI_DIWR_Y)); + pr_info("DI_DIWR_CTRL=0x%x", Rd(DI_DIWR_CTRL)); + pr_info("DI_DIWR_X=0x%x.\n", Rd(DI_DIWR_X)); +} diff --git a/drivers/amlogic/media/deinterlace/deinterlace_dbg.h b/drivers/amlogic/media/deinterlace/deinterlace_dbg.h index ded85378e31e..d4072de81231 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_dbg.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_dbg.h @@ -14,8 +14,8 @@ * more details. * */ - -#include +#ifndef _DI_DBG_H +#define _DI_DBG_H #include "deinterlace.h" void parse_cmd_params(char *buf_orig, char **parm); @@ -26,4 +26,8 @@ void dump_pool(struct queue_s *q); void dump_vframe(vframe_t *vf); void dump_di_reg(void); void print_di_buf(struct di_buf_s *di_buf, int format); - +void dump_pre_mif_state(void); +void dump_post_mif_reg(void); +void debug_device_files_add(struct device *dev); +void debug_device_files_del(struct device *dev); +#endif diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.c b/drivers/amlogic/media/deinterlace/deinterlace_hw.c index bccfae3bc20e..100d31542052 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_hw.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.c @@ -26,48 +26,11 @@ #include #include #include -/* #include */ -#include "deinterlace.h" +#include "deinterlace_hw.h" #include "register.h" #ifdef DET3D #include "detect3d.h" #endif -#include "nr.h" - -#ifndef DI_CHAN2_CANVAS -#define DI_CHAN2_CANVAS DI_CHAN2_CANVAS0 -#endif -#ifndef DI_CHAN2_LUMA_X -#define DI_CHAN2_LUMA_X DI_CHAN2_LUMA_X0 -#endif -#ifndef DI_CHAN2_LUMA_Y -#define DI_CHAN2_LUMA_Y DI_CHAN2_LUMA_Y0 -#endif -#ifndef DI_CHAN2_LUMA_RPT_PAT -#define DI_CHAN2_LUMA_RPT_PAT DI_CHAN2_LUMA0_RPT_PAT -#endif - -uint di_mtn_1_ctrl1 = 0xa0202015; -uint mtn_ctrl1; - -static bool cue_enable; - -pd_win_prop_t pd_win_prop[MAX_WIN_NUM]; - -static bool frame_dynamic; -MODULE_PARM_DESC(frame_dynamic, "\n frame_dynamic\n"); -module_param(frame_dynamic, bool, 0664); - -static bool frame_dynamic_dbg; -MODULE_PARM_DESC(frame_dynamic_dbg, "\n frame_dynamic_dbg\n"); -module_param(frame_dynamic_dbg, bool, 0664); - -static int frame_dynamic_level; -MODULE_PARM_DESC(frame_dynamic_level, "\n frame_dynamic_level\n"); -module_param(frame_dynamic_level, int, 0664); - -MODULE_PARM_DESC(cue_enable, "\n cue_enable\n"); -module_param(cue_enable, bool, 0664); static unsigned short mcen_mode = 1; MODULE_PARM_DESC(mcen_mode, "\n mcen mode\n"); @@ -87,22 +50,13 @@ module_param(debug_blend_mode_ctrl, ushort, 0664); * 8: froce to 8 bit mode. * 10: froce to 10 bit mode and enable nr 10 bit. */ -unsigned int di_force_bit_mode = 10; -module_param(di_force_bit_mode, uint, 0664); -MODULE_PARM_DESC(di_force_bit_mode, "force DI bit mode to 8 or 10 bit"); -static unsigned short mc_pre_flag = 2; -MODULE_PARM_DESC(mc_pre_flag, "\n mc per/forward flag\n"); -module_param(mc_pre_flag, ushort, 0664); +static unsigned int pq_load_dbg; +module_param_named(pq_load_dbg, pq_load_dbg, uint, 0644); -#ifdef DET3D -static unsigned int det3d_cfg; -module_param(det3d_cfg, uint, 0664); -MODULE_PARM_DESC(det3d_cfg, "det3d_cfg"); +#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA +extern u32 VSYNC_RD_MPEG_REG(u32 adr); #endif - -static int vdin_en; - static void set_di_inp_fmt_more( unsigned int repeat_l0_en, int hz_yc_ratio, /* 2bit */ @@ -155,33 +109,45 @@ static void set_di_if1_fmt_more( int hz_rpt /* 1bit */ ); -static void set_di_if1_mif(struct DI_MIF_s *mif, int urgent, int hold_line); +static void set_di_if1_mif(struct DI_MIF_s *mif, int urgent, + int hold_line, int vskip_cnt); static void set_di_chan2_mif(struct DI_MIF_s *mif, int urgent, int hold_line); -static void set_di_if0_mif(struct DI_MIF_s *mif, int urgent, int hold_line); +static void set_di_if0_mif(struct DI_MIF_s *mif, int urgent, + int hold_line, int vskip_cnt, int wr_en); -#if (defined NEW_DI_V2 && !defined NEW_DI_TV) static void ma_di_init(void) { /* 420->422 chrome difference is large motion is large,flick */ DI_Wr(DI_MTN_1_CTRL4, 0x01800880); DI_Wr(DI_MTN_1_CTRL7, 0x0a800480); + /* mtn setting */ + DI_Wr(DI_MTN_1_CTRL1, 0xa0202015); + /* invert chan2 field num */ + DI_Wr(DI_MTN_CTRL1, (1 << 17) | 2); + /* no invert chan2 field num from gxlx*/ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) + DI_Wr(DI_MTN_CTRL1, 2); + +} + +static void ei_hw_init(void) +{ /* ei setting */ DI_Wr(DI_EI_CTRL0, 0x00ff0100); DI_Wr(DI_EI_CTRL1, 0x5a0a0f2d); DI_Wr(DI_EI_CTRL2, 0x050a0a5d); DI_Wr(DI_EI_CTRL3, 0x80000013); - /* mtn setting */ - DI_Wr(DI_MTN_1_CTRL1, 0xa0202015); - #if 0 - /* no use from g9tv */ - DI_Wr(DI_MTN_CTRL, 0xe228c440); - DI_Wr(DI_BLEND_CTRL1, 0xc4402840); - DI_Wr(DI_BLEND_CTRL2, 0x430); - #endif + if (is_meson_txlx_cpu()) { + DI_Wr_reg_bits(DI_EI_DRT_CTRL, 1, 30, 1); + DI_Wr_reg_bits(DI_EI_DRT_CTRL, 1, 31, 1); + } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) { + DI_Wr_reg_bits(DI_EI_DRT_CTRL_GXLX, 1, 30, 1); + DI_Wr_reg_bits(DI_EI_DRT_CTRL_GXLX, 1, 31, 1); + } + } -#endif static void mc_di_param_init(void) { @@ -190,38 +156,212 @@ static void mc_di_param_init(void) DI_Wr(MCDI_LMV_GAINTHD, 0x6014d409); DI_Wr(MCDI_REL_DET_LPF_MSK_22_30, 0x0a010001); DI_Wr(MCDI_REL_DET_LPF_MSK_31_34, 0x01010101); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) + DI_Wr_reg_bits(MCDI_REF_MV_NUM, 2, 0, 2); } -static void init_field_mode(void) +void init_field_mode(unsigned short height) { DI_Wr(DIPD_COMB_CTRL0, 0x02400210); DI_Wr(DIPD_COMB_CTRL1, 0x88080808); DI_Wr(DIPD_COMB_CTRL2, 0x41041008); DI_Wr(DIPD_COMB_CTRL3, 0x00008053); DI_Wr(DIPD_COMB_CTRL4, 0x20070002); - DI_Wr(DIPD_COMB_CTRL5, 0x04040804); + if (height > 288) + DI_Wr(DIPD_COMB_CTRL5, 0x04041020); + else + DI_Wr(DIPD_COMB_CTRL5, 0x04040804); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) + DI_Wr(DIPD_COMB_CTRL6, 0x00107064); +} +void mc_pre_mv_irq(void) +{ + unsigned int val1; + + val1 = RDMA_RD(MCDI_RO_PD_22_FLG); + RDMA_WR(MCDI_PD_22_CHK_FLG_CNT, val1); + + val1 = RDMA_RD_BITS(MCDI_RO_HIGH_VERT_FRQ_FLG, 0, 1); + RDMA_WR_BITS(MCDI_FIELD_HVF_PRDX_CNT, val1, 0, 1); + val1 = RDMA_RD_BITS(MCDI_RO_HIGH_VERT_FRQ_FLG, 1, 2); + RDMA_WR_BITS(MCDI_FIELD_HVF_PRDX_CNT, val1, 2, 2); + val1 = RDMA_RD_BITS(MCDI_RO_HIGH_VERT_FRQ_FLG, 8, 8); + RDMA_WR_BITS(MCDI_FIELD_HVF_PRDX_CNT, val1, 8, 8); + val1 = RDMA_RD_BITS(MCDI_RO_MOTION_PARADOX_FLG, 0, 16); + RDMA_WR_BITS(MCDI_FIELD_HVF_PRDX_CNT, val1, 16, 16); + + val1 = RDMA_RD_BITS(MCDI_RO_RPT_MV, 0, 6); + if (val1 == 32) { + val1 = 0; + RDMA_WR_BITS(MCDI_CTRL_MODE, 0, 15, 1); + } else { + RDMA_WR_BITS(MCDI_CTRL_MODE, 1, 15, 1); + } + + RDMA_WR_BITS(MCDI_FIELD_MV, val1, 8, 6); + + val1 = RDMA_RD_BITS(MCDI_RO_GMV_LOCK_FLG, 0, 1); + RDMA_WR_BITS(MCDI_FIELD_MV, val1, 14, 1); + + val1 = RDMA_RD_BITS(MCDI_RO_GMV_LOCK_FLG, 8, 8); + RDMA_WR_BITS(MCDI_FIELD_MV, val1, 16, 8); + + val1 = RDMA_RD_BITS(MCDI_RO_GMV_LOCK_FLG, 2, 6); + if (val1 == 32) { + val1 = 0; + RDMA_WR_BITS(MCDI_CTRL_MODE, 0, 14, 1); + } else { + RDMA_WR_BITS(MCDI_CTRL_MODE, 1, 14, 1); + } + RDMA_WR_BITS(MCDI_FIELD_MV, val1, 0, 6); + + val1 = RDMA_RD(MCDI_FIELD_LUMA_AVG_SUM_1); + RDMA_WR(MCDI_FIELD_LUMA_AVG_SUM_0, val1); + + val1 = RDMA_RD(MCDI_RO_FLD_LUMA_AVG_SUM); + RDMA_WR(MCDI_FIELD_LUMA_AVG_SUM_1, val1); + } -void di_hw_init(void) +static void lmvs_init(struct mcinfo_lmv_s *lmvs, unsigned short lmv) +{ + lmvs->lock_flag = (lmv>>14) & 3; + lmvs->lmv = (lmv>>8)&63; + lmvs->lmv = lmvs->lmv > 32 ? (32 - lmvs->lmv) : lmvs->lmv; + lmvs->lock_cnt = (lmv & 255); +} + +static bool lmv_lock_win_en; +module_param_named(lmv_lock_win_en, lmv_lock_win_en, bool, 0644); + +void calc_lmv_init(void) +{ + if (lmv_lock_win_en) { + RDMA_WR_BITS(MCDI_REL_DET_LMV_DIF_CHK, 3, 12, 2); + RDMA_WR_BITS(MCDI_LMVLCKSTEXT_1, 3, 30, 2); + } else { + RDMA_WR_BITS(MCDI_REL_DET_LMV_DIF_CHK, 0, 12, 2); + RDMA_WR_BITS(MCDI_LMVLCKSTEXT_1, 0, 30, 2); + } +} + +static short lmv_dist = 5; +module_param_named(lmv_dist, lmv_dist, short, 0644); + +static unsigned short pr_mcinfo_cnt; +module_param_named(pr_mcinfo_cnt, pr_mcinfo_cnt, ushort, 0644); +static struct mcinfo_lmv_s lines_mv[540]; +static short offset_lmv = 100; +module_param_named(offset_lmv, offset_lmv, short, 0644); + +void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr) +{ + unsigned short i, top_str, bot_str, top_end, bot_end, j = 0; + unsigned short *mcinfo_vadr = NULL, lck_num; + unsigned short flg_m1 = 0, flg_i = 0, nLmvLckSt = 0; + unsigned short lmv_lckstext[3] = {0, 0, 0}, nLmvLckEd; + unsigned short lmv_lckedext[3] = {0, 0, 0}, nLmvLckNum; + + mcinfo_vadr = (unsigned short *)phys_to_virt(mcinfo_adr); + if (!lmv_lock_win_en) + return; + for (i = 0; i < (vf_height>>1); i++) { + lmvs_init(&lines_mv[i], *(mcinfo_vadr+i)); + j = i + (vf_height>>1); + lmvs_init(&lines_mv[j], *(mcinfo_vadr+i+272)); + if (pr_mcinfo_cnt && j < (vf_height - 10) && + j > (vf_height - offset_lmv)) { + pr_info("MCINFO[%u]=0x%x\t", j, + *(mcinfo_vadr + i + 272)); + if (i%16 == 0) + pr_info("\n"); + } + } + pr_mcinfo_cnt ? pr_mcinfo_cnt-- : (pr_mcinfo_cnt = 0); + top_str = 0; + top_end = offset_lmv; + i = top_str; + j = 0; + lck_num = Rd_reg_bits(MCDI_LMVLCKSTEXT_1, 16, 12); + + while (i < top_end) { + flg_m1 = (i == top_str) ? 0 : + (lines_mv[i-1].lock_flag > 0); + flg_i = (i == top_end - 1) ? 0 : + lines_mv[i].lock_flag > 0; + if (!flg_m1 && flg_i) { + nLmvLckSt = (j == 0) ? i : ((i < (lmv_lckedext[j-1] + + lmv_dist)) ? lmv_lckstext[j-1] : i); + j = (nLmvLckSt != i) ? (j - 1) : j; + } else if (flg_m1 && !flg_i) { + nLmvLckEd = i; + nLmvLckNum = (nLmvLckEd - nLmvLckSt + 1); + if (nLmvLckNum >= lck_num) { + lmv_lckstext[j] = nLmvLckSt; + lmv_lckedext[j] = nLmvLckEd; + j++; + } + } + i++; + if (j > 2) + break; + } + + bot_str = vf_height - offset_lmv - 1; + bot_end = vf_height; + i = bot_str; + while (i < bot_end && j < 3) { + flg_m1 = (i == bot_str) ? 0 : + (lines_mv[i-1].lock_flag > 0); + flg_i = (i == bot_end - 1) ? 0 : + lines_mv[i].lock_flag > 0; + if (!flg_m1 && flg_i) { + nLmvLckSt = (j == 0) ? i : ((i < (lmv_lckedext[j-1] + + lmv_dist)) ? lmv_lckstext[j-1] : i); + j = (nLmvLckSt != i) ? (j - 1) : j; + } else if (flg_m1 && !flg_i) { + nLmvLckEd = i; + nLmvLckNum = (nLmvLckEd - nLmvLckSt + 1); + if (nLmvLckNum >= lck_num) { + lmv_lckstext[j] = nLmvLckSt; + lmv_lckedext[j] = nLmvLckEd; + j++; + } + } + i++; + if (j > 2) + break; + } + + Wr(MCDI_LMVLCKSTEXT_0, lmv_lckstext[1]<<16 | lmv_lckstext[0]); + Wr_reg_bits(MCDI_LMVLCKSTEXT_1, lmv_lckstext[2], 0, 12); + Wr(MCDI_LMVLCKEDEXT_0, lmv_lckedext[1]<<16 | lmv_lckedext[0]); + Wr(MCDI_LMVLCKEDEXT_1, lmv_lckedext[2]); +} + +void di_hw_init(bool pd_enable, bool mc_enable) { -#ifdef NEW_DI_V1 unsigned short fifo_size_vpp = 0xc0; unsigned short fifo_size_di = 0xc0; -#endif -#ifdef NEW_DI_V1 switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, VPU_CLK_GATE_ON); - /* enable old DI mode for m6tv */ - if (is_meson_gxtvbb_cpu() || is_meson_gxl_cpu() || is_meson_gxm_cpu()) + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) + di_top_gate_control(true, true); + else if (is_meson_gxl_cpu() || is_meson_gxm_cpu() + || is_meson_gxlx_cpu()) DI_Wr(DI_CLKG_CTRL, 0xffff0001); else DI_Wr(DI_CLKG_CTRL, 0x1); /* di no clock gate */ - if (is_meson_txl_cpu()) { + if (is_meson_txlx_cpu() || + is_meson_gxlx_cpu() || + is_meson_txhd_cpu()) { /* vpp fifo max size on txl :128*3=384[0x180] */ /* di fifo max size on txl :96*3=288[0x120] */ fifo_size_vpp = 0x180; fifo_size_di = 0x120; } + /* enable di all arb */ + DI_Wr_reg_bits(DI_ARB_CTRL, 0xf0f, 0, 16); DI_Wr(VD1_IF0_LUMA_FIFO_SIZE, fifo_size_vpp); DI_Wr(VD2_IF0_LUMA_FIFO_SIZE, fifo_size_vpp); /* 1a83 is vd2_if0_luma_fifo_size */ @@ -231,29 +371,45 @@ void di_hw_init(void) /* 17e5 is DI_MEM_luma_fifo_size */ DI_Wr(DI_IF1_LUMA_FIFO_SIZE, fifo_size_di); /* 17f2 is DI_IF1_luma_fifo_size */ + DI_Wr(DI_IF2_LUMA_FIFO_SIZE, fifo_size_di); + /* 201a is if2 fifo size */ DI_Wr(DI_CHAN2_LUMA_FIFO_SIZE, fifo_size_di); /* 17b3 is DI_chan2_luma_fifo_size */ -#endif + if (is_meson_txlx_cpu() || + is_meson_txhd_cpu()) { + di_pre_gate_control(true, true); + di_post_gate_control(true); + } DI_Wr(DI_PRE_HOLD, (1 << 31) | (31 << 16) | 31); - /* nr default setting */ - di_nr_init(); -#if (defined NEW_DI_V2 && !defined NEW_DI_TV) ma_di_init(); -#endif + ei_hw_init(); + nr_hw_init(); + if (pd_enable) + init_field_mode(288); - if (pulldown_enable) - init_field_mode(); - - if (mcpre_en) + if (mc_enable) mc_di_param_init(); + if (is_meson_txlx_cpu() || + is_meson_txhd_cpu()) { + di_pre_gate_control(false, true); + di_post_gate_control(false); + di_top_gate_control(false, false); + } else if (is_meson_gxlx_cpu()) { + /* di clock div enable for pq load */ + DI_Wr(DI_CLKG_CTRL, 0x80000000); + } else { + DI_Wr(DI_CLKG_CTRL, 0x2); /* di clock gate all */ + } + switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, + VPU_CLK_GATE_OFF); - DI_Wr(DI_CLKG_CTRL, 0x2); /* di clock gate all */ - switch_vpu_clk_gate_vmod(VPU_VPU_CLKB, VPU_CLK_GATE_OFF); } void di_hw_uninit(void) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) + nr_gate_control(false); } /* config di pre bit mode */ @@ -271,29 +427,21 @@ static void pre_bit_mode_config(unsigned char inp, RDMA_WR_BITS(DI_NRWR_CTRL, 0x3, 22, 2); } -unsigned int nr2_en = 0x1; -module_param(nr2_en, uint, 0644); -MODULE_PARM_DESC(nr2_en, "\n nr2_en\n"); - void enable_di_pre_aml( struct DI_MIF_s *di_inp_mif, struct DI_MIF_s *di_mem_mif, struct DI_MIF_s *di_chan2_mif, struct DI_SIM_MIF_s *di_nrwr_mif, struct DI_SIM_MIF_s *di_mtnwr_mif, -#ifdef NEW_DI_V1 struct DI_SIM_MIF_s *di_contp2rd_mif, struct DI_SIM_MIF_s *di_contprd_mif, struct DI_SIM_MIF_s *di_contwr_mif, -#endif int nr_en, int mtn_en, int pd32_check_en, int pd22_check_en, int hist_check_en, int pre_field_num, int pre_vdin_link, int hold_line, int urgent) { int hist_check_only = 0; -#ifdef NEW_DI_V1 - int nr_w = 0, nr_h = 0; -#endif + pd32_check_en = 1; /* for progressive luma detection */ hist_check_only = hist_check_en && !nr_en && !mtn_en && @@ -301,23 +449,15 @@ void enable_di_pre_aml( if (nr_en | mtn_en | pd22_check_en || pd32_check_en) { set_di_mem_mif(di_mem_mif, urgent, hold_line); - if (!vdin_en) - set_di_inp_mif(di_inp_mif, urgent, hold_line); + set_di_inp_mif(di_inp_mif, urgent, hold_line); } - if (pd22_check_en || hist_check_only) { + if (pd22_check_en || hist_check_only) set_di_chan2_mif(di_chan2_mif, urgent, hold_line); - #ifdef NEW_DI_V1 - RDMA_WR_BITS(DI_NR_CTRL0, cue_enable, 26, 1); - #endif - } else { - RDMA_WR_BITS(DI_NR_CTRL0, 0, 26, 1); - } - /* set nr wr mif interface. */ if (nr_en) { - RDMA_WR(DI_NRWR_X, (di_nrwr_mif->start_x << 16)| - (di_nrwr_mif->end_x)); + RDMA_WR_BITS(DI_NRWR_X, di_nrwr_mif->end_x, 0, 14); + RDMA_WR_BITS(DI_NRWR_X, di_nrwr_mif->start_x, 16, 14); RDMA_WR_BITS(DI_NRWR_Y, di_nrwr_mif->start_y, 16, 13); RDMA_WR_BITS(DI_NRWR_Y, di_nrwr_mif->end_y, 0, 13); RDMA_WR_BITS(DI_NRWR_Y, 3, 30, 2); @@ -333,7 +473,6 @@ void enable_di_pre_aml( di_nrwr_mif->bit_mode); /* motion wr mif. */ if (mtn_en) { -#ifdef NEW_DI_V1 RDMA_WR(DI_CONTWR_X, (di_contwr_mif->start_x << 16)| (di_contwr_mif->end_x)); RDMA_WR(DI_CONTWR_Y, (di_contwr_mif->start_y << 16)| @@ -352,37 +491,14 @@ void enable_di_pre_aml( (urgent << 16)|/* urgent */ di_contp2rd_mif->canvas_num); /* current field mtn canvas index. */ -#endif RDMA_WR(DI_MTNWR_X, (di_mtnwr_mif->start_x << 16)| (di_mtnwr_mif->end_x)); RDMA_WR(DI_MTNWR_Y, (di_mtnwr_mif->start_y << 16)| (di_mtnwr_mif->end_y)); RDMA_WR(DI_MTNWR_CTRL, di_mtnwr_mif->canvas_num| (urgent << 8)); /* urgent. */ - RDMA_WR(DI_MTN_CTRL1, (0 << 8) | 2); } -#ifdef NEW_DI_V1 - nr_w = (di_nrwr_mif->end_x - di_nrwr_mif->start_x + 1); - nr_h = (di_nrwr_mif->end_y - di_nrwr_mif->start_y + 1); - RDMA_WR(NR2_FRM_SIZE, (nr_h<<16)|nr_w); - /*gate for nr*/ - if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) - RDMA_WR_BITS(NR2_SW_EN, nr2_en, 4, 1); - else { - /*only process sd,avoid affecting sharp*/ - if ((nr_h<<1) >= 720 || nr_w >= 1280) - RDMA_WR_BITS(NR2_SW_EN, 0, 4, 1); - else - RDMA_WR_BITS(NR2_SW_EN, nr2_en, 4, 1); - } - /*enable noise meter*/ - RDMA_WR_BITS(NR2_SW_EN, 1, 17, 1); -#endif - - /* frame + soft reset for the pre modules. */ - RDMA_WR(DI_PRE_CTRL, Rd(DI_PRE_CTRL) | 3 << 30); - RDMA_WR(DI_PRE_CTRL, nr_en | /* NR enable */ (mtn_en << 1) | /* MTN_EN */ (pd32_check_en << 2)|/* check 3:2 pulldown */ @@ -403,23 +519,9 @@ void enable_di_pre_aml( (pre_vdin_link << 14) |/* pre go line link */ (hold_line << 16)|/* pre hold line number */ (1 << 22)|/* MTN after NR. */ - (pre_field_num << 29)|/* pre field number.*/ - (0x1 << 30) /* pre soft rst, pre frame rst */ + (pre_field_num << 29)/* pre field number.*/ ); -#ifdef SUPPORT_MPEG_TO_VDIN - if (mpeg2vdin_flag) - RDMA_WR_BITS(DI_PRE_CTRL, 1, 13, 1); -#endif -#ifdef DET3D - if (det3d_en && (!det3d_cfg)) { - det3d_enable(1); - det3d_cfg = 1; - } else if ((!det3d_en) && det3d_cfg) { - det3d_enable(0); - det3d_cfg = 0; - } -#endif } void enable_afbc_input(struct vframe_s *vf) { @@ -527,16 +629,19 @@ void enable_mc_di_pre(struct DI_MC_MIF_s *di_mcinford_mif, } void enable_mc_di_post(struct DI_MC_MIF_s *di_mcvecrd_mif, - int urgent, bool reverse) + int urgent, bool reverse, int invert_mv) { + di_mcvecrd_mif->size_y = + (di_mcvecrd_mif->end_y - di_mcvecrd_mif->start_y + 1); DI_VSYNC_WR_MPEG_REG(MCDI_MCVECRD_X, (reverse?1:0)<<30 | - di_mcvecrd_mif->start_x<<16 | + di_mcvecrd_mif->start_x << 16 | (di_mcvecrd_mif->size_x+di_mcvecrd_mif->start_x)); DI_VSYNC_WR_MPEG_REG(MCDI_MCVECRD_Y, (reverse?1:0)<<30 | - di_mcvecrd_mif->start_y<<16 | - (di_mcvecrd_mif->size_y+di_mcvecrd_mif->start_y)); + di_mcvecrd_mif->start_y << 16 | + di_mcvecrd_mif->end_y); DI_VSYNC_WR_MPEG_REG(MCDI_MCVECRD_CANVAS_SIZE, - (di_mcvecrd_mif->size_x<<16)+di_mcvecrd_mif->size_y); + (di_mcvecrd_mif->size_x << 16) | + di_mcvecrd_mif->size_y); DI_VSYNC_WR_MPEG_REG(MCDI_MCVECRD_CTRL, di_mcvecrd_mif->canvas_num | (urgent<<8)|/* urgent */ (1<<9)|/* canvas enable */ @@ -544,14 +649,19 @@ void enable_mc_di_post(struct DI_MC_MIF_s *di_mcvecrd_mif, (0x31<<16)); DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, di_mcvecrd_mif->vecrd_offset, 12, 3); - - if (di_mcvecrd_mif->blend_mode == 3) + if (di_mcvecrd_mif->blend_en) DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, mcen_mode, 0, 2); else DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 0, 2); - if (is_meson_txl_cpu()) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) { DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, mcuv_en, 10, 1); - DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 1, 11, 3); + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 1, 11, 1); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) { + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + invert_mv, 17, 1); + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + 3, 18, 2); + } } else DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, mcuv_en, 9, 1); DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, mcdebug_mode, 2, 3); @@ -789,7 +899,6 @@ static void set_di_mem_fmt_more(int hfmt_en, ); } -#ifdef NEW_DI_V1 static void set_di_chan2_fmt_more(int hfmt_en, int hz_yc_ratio,/* 2bit */ int hz_ini_phase,/* 4bit */ @@ -820,7 +929,6 @@ static void set_di_chan2_fmt_more(int hfmt_en, (c_length << 0) /* vt format width */ ); } -#endif static void set_di_mem_mif(struct DI_MIF_s *mif, int urgent, int hold_line) { @@ -1062,13 +1170,14 @@ static void set_di_if2_fmt_more(int hfmt_en, static const u32 vpat[] = {0, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; -static void set_di_if2_mif(struct DI_MIF_s *mif, int urgent, int hold_line) +static void set_di_if2_mif(struct DI_MIF_s *mif, int urgent, + int hold_line, int vskip_cnt) { unsigned int bytes_per_pixel, demux_mode; unsigned int pat, loop = 0, chro_rpt_lastl_ctrl = 0; if (mif->set_separate_en == 1) { - pat = vpat[(di_vscale_skip_count_real<<1)+1]; + pat = vpat[(vskip_cnt<<1)+1]; /*top*/ if (mif->src_field_mode == 0) { chro_rpt_lastl_ctrl = 1; @@ -1077,7 +1186,7 @@ static void set_di_if2_mif(struct DI_MIF_s *mif, int urgent, int hold_line) } } else { loop = 0; - pat = vpat[di_vscale_skip_count_real]; + pat = vpat[vskip_cnt]; } bytes_per_pixel = mif->set_separate_en ? 0 : (mif->video_mode ? 2 : 1); @@ -1161,13 +1270,14 @@ static void set_di_if2_mif(struct DI_MIF_s *mif, int urgent, int hold_line) } } -static void set_di_if1_mif(struct DI_MIF_s *mif, int urgent, int hold_line) +static void set_di_if1_mif(struct DI_MIF_s *mif, int urgent, + int hold_line, int vskip_cnt) { unsigned int bytes_per_pixel, demux_mode; unsigned int pat, loop = 0, chro_rpt_lastl_ctrl = 0; if (mif->set_separate_en == 1) { - pat = vpat[(di_vscale_skip_count_real<<1)+1]; + pat = vpat[(vskip_cnt<<1)+1]; /*top*/ if (mif->src_field_mode == 0) { chro_rpt_lastl_ctrl = 1; @@ -1176,7 +1286,7 @@ static void set_di_if1_mif(struct DI_MIF_s *mif, int urgent, int hold_line) } } else { loop = 0; - pat = vpat[di_vscale_skip_count_real]; + pat = vpat[vskip_cnt]; } bytes_per_pixel = mif->set_separate_en ? 0 : (mif->video_mode ? 2 : 1); @@ -1202,11 +1312,6 @@ static void set_di_if1_mif(struct DI_MIF_s *mif, int urgent, int hold_line) ((mif->set_separate_en != 0) << 1)| (1 << 0)/* cntl_enable */ ); - #if 0 - /* post bit mode config, if0 config in video.c */ - if (is_meson_gxtvbb_cpu() || is_meson_gxl_cpu() || is_meson_gxm_cpu()) - DI_VSYNC_WR_MPEG_REG_BITS(DI_IF1_GEN_REG3, mif->bit_mode, 8, 2); - #endif /* ---------------------- */ /* Canvas */ /* ---------------------- */ @@ -1266,24 +1371,52 @@ static void set_di_chan2_mif(struct DI_MIF_s *mif, int urgent, int hold_line) { unsigned int bytes_per_pixel; unsigned int demux_mode; + unsigned int chro_rpt_lastl_ctrl; unsigned int luma0_rpt_loop_start; unsigned int luma0_rpt_loop_end; unsigned int luma0_rpt_loop_pat; + unsigned int chroma0_rpt_loop_start; + unsigned int chroma0_rpt_loop_end; + unsigned int chroma0_rpt_loop_pat; unsigned int reset_on_gofield; - - bytes_per_pixel = mif->set_separate_en ? 0 : -((mif->video_mode == 1) ? 2 : 1); - demux_mode = mif->video_mode & 1; - - if (mif->src_field_mode == 1) { + if (mif->set_separate_en != 0 && mif->src_field_mode == 1) { + chro_rpt_lastl_ctrl = 1; luma0_rpt_loop_start = 1; luma0_rpt_loop_end = 1; + chroma0_rpt_loop_start = 1; + chroma0_rpt_loop_end = 1; luma0_rpt_loop_pat = 0x80; - } else { + chroma0_rpt_loop_pat = 0x80; + } else if (mif->set_separate_en != 0 && mif->src_field_mode == 0) { + chro_rpt_lastl_ctrl = 1; luma0_rpt_loop_start = 0; luma0_rpt_loop_end = 0; - luma0_rpt_loop_pat = 0; + chroma0_rpt_loop_start = 0; + chroma0_rpt_loop_end = 0; + luma0_rpt_loop_pat = 0x0; + chroma0_rpt_loop_pat = 0x0; + } else if (mif->set_separate_en == 0 && mif->src_field_mode == 1) { + chro_rpt_lastl_ctrl = 1; + luma0_rpt_loop_start = 1; + luma0_rpt_loop_end = 1; + chroma0_rpt_loop_start = 0; + chroma0_rpt_loop_end = 0; + luma0_rpt_loop_pat = 0x80; + chroma0_rpt_loop_pat = 0x00; + } else { + chro_rpt_lastl_ctrl = 0; + luma0_rpt_loop_start = 0; + luma0_rpt_loop_end = 0; + chroma0_rpt_loop_start = 0; + chroma0_rpt_loop_end = 0; + luma0_rpt_loop_pat = 0x00; + chroma0_rpt_loop_pat = 0x00; } + + bytes_per_pixel = mif->set_separate_en ? 0 : (mif->video_mode ? 2 : 1); + demux_mode = mif->video_mode; + + /* ---------------------- */ /* General register */ /* ---------------------- */ @@ -1298,9 +1431,11 @@ static void set_di_chan2_mif(struct DI_MIF_s *mif, int urgent, int hold_line) (bytes_per_pixel << 14) | (1 << 12) |/*burst_size_cr*/ (1 << 10) |/*burst_size_cb*/ - (3 << 8) |/*burst_size_y*/ -((hold_line == 0 ? 1 : 0) << 7) | -(0 << 6)|(0 << 1)|(0 << 0)); + (3 << 8) |/*burst_size_y*/ + (chro_rpt_lastl_ctrl << 6) | + ((mif->set_separate_en != 0) << 1)| + (0 << 0) /* cntl_enable */ + ); /* ---------------------- */ /* Canvas */ /* ---------------------- */ @@ -1310,18 +1445,21 @@ static void set_di_chan2_mif(struct DI_MIF_s *mif, int urgent, int hold_line) } else { RDMA_WR_BITS(DI_CHAN2_GEN_REG2, 0, 0, 1); } - RDMA_WR(DI_CHAN2_CANVAS, (0 << 16) | /* cntl_canvas0_addr2 */ -(0 << 8)|(mif->canvas0_addr0 << 0)); - + RDMA_WR(DI_CHAN2_CANVAS0, (mif->canvas0_addr2 << 16) | + (mif->canvas0_addr1 << 8) | + (mif->canvas0_addr0 << 0)); /* ---------------------- */ /* Picture 0 X/Y start,end */ /* ---------------------- */ - RDMA_WR(DI_CHAN2_LUMA_X, (mif->luma_x_end0 << 16) | + RDMA_WR(DI_CHAN2_LUMA_X0, (mif->luma_x_end0 << 16) | /* cntl_luma_x_end0 */ (mif->luma_x_start0 << 0)); - RDMA_WR(DI_CHAN2_LUMA_Y, (mif->luma_y_end0 << 16) | - /* cntl_luma_y_end0 */ -(mif->luma_y_start0 << 0)); + RDMA_WR(DI_CHAN2_LUMA_Y0, (mif->luma_y_end0 << 16) | + (mif->luma_y_start0 << 0)); + RDMA_WR(DI_CHAN2_CHROMA_X0, (mif->chroma_x_end0 << 16) | + (mif->chroma_x_start0 << 0)); + RDMA_WR(DI_CHAN2_CHROMA_Y0, (mif->chroma_y_end0 << 16) | + (mif->chroma_y_start0 << 0)); /* ---------------------- */ /* Repeat or skip */ @@ -1336,12 +1474,11 @@ static void set_di_chan2_mif(struct DI_MIF_s *mif, int urgent, int hold_line) (luma0_rpt_loop_end << 0) ); - RDMA_WR(DI_CHAN2_LUMA_RPT_PAT, luma0_rpt_loop_pat); + RDMA_WR(DI_CHAN2_LUMA0_RPT_PAT, luma0_rpt_loop_pat); /* Dummy pixel value */ RDMA_WR(DI_CHAN2_DUMMY_PIXEL, 0x00808000); -#ifdef NEW_DI_V1 if ((mif->set_separate_en != 0)) { /* 4:2:0 block mode. */ set_di_chan2_fmt_more( 1, /* hfmt_en */ @@ -1365,26 +1502,26 @@ static void set_di_chan2_mif(struct DI_MIF_s *mif, int urgent, int hold_line) ((mif->luma_x_end0 >> 1) - (mif->luma_x_start0>>1) + 1), 0); /* hz repeat. */ } -#endif } -static void set_di_if0_mif(struct DI_MIF_s *mif, int urgent, int hold_line) +static void set_di_if0_mif(struct DI_MIF_s *mif, int urgent, int hold_line, + int vskip_cnt, int post_write_en) { unsigned int pat, loop = 0; unsigned int bytes_per_pixel, demux_mode; if (mif->set_separate_en == 1) { - pat = vpat[(di_vscale_skip_count_real<<1)+1]; + pat = vpat[(vskip_cnt<<1)+1]; if (mif->src_field_mode == 0) {/* top */ loop = 0x11; pat <<= 4; } } else { loop = 0; - pat = vpat[di_vscale_skip_count_real]; + pat = vpat[vskip_cnt]; - if ((post_wr_en && post_wr_surpport)) { + if (post_write_en) { bytes_per_pixel = mif->set_separate_en ? 0 : (mif->video_mode ? 2 : 1); demux_mode = mif->video_mode; @@ -1435,7 +1572,7 @@ static void set_di_if0_mif(struct DI_MIF_s *mif, int urgent, int hold_line) DI_VSYNC_WR_MPEG_REG(VD1_IF0_LUMA0_RPT_PAT, pat); DI_VSYNC_WR_MPEG_REG(VD1_IF0_CHROMA0_RPT_PAT, pat); - if ((post_wr_en && post_wr_surpport)) { + if (post_write_en) { /* 4:2:0 block mode. */ if (mif->set_separate_en != 0) { set_di_if0_fmt_more( @@ -1463,67 +1600,30 @@ mif->chroma_x_end0 - mif->chroma_x_start0 + 1, /* c length */ } } -void initial_di_pre_aml(int hsize_pre, int vsize_pre, int hold_line) -{ - DI_Wr(DI_PRE_SIZE, (hsize_pre - 1) | ((vsize_pre - 1) << 16)); - DI_Wr(DI_PRE_CTRL, 0 | /* NR enable */ -(0 << 1) | /* MTN_EN */ -(1 << 2) | /* check 3:2 pulldown */ -(0 << 3) | /* check 2:2 pulldown */ -(0 << 4) | /* 2:2 check mid pixel come from next field after MTN. */ -(0 << 5) | /* hist check enable */ -(0 << 6) | /* hist check not use chan2. */ -(0 << 7) | /* hist check use data before noise reduction. */ -(0 << 8) | /* chan 2 enable for 2:2 pull down check. */ -(0 << 9) | /* line buffer 2 enable */ -(0 << 10) | /* pre drop first. */ -(0 << 11) | /* pre repeat. */ -(0 << 12) | /* pre viu link */ -(hold_line << 16) | /* pre hold line number */ -(0 << 29) | /* pre field number. */ -(0x3 << 30) /* pre soft rst, pre frame rst. */ - ); -#ifdef SUPPORT_MPEG_TO_VDIN - if (mpeg2vdin_flag) - DI_Wr_reg_bits(DI_PRE_CTRL, 1, 13, 1); -#endif - DI_Wr(DI_MC_22LVL0, (Rd(DI_MC_22LVL0) & 0xffff0000) | 256); - DI_Wr(DI_MC_32LVL0, (Rd(DI_MC_32LVL0) & 0xffffff00) | 16); -} - -void initial_di_post_2(int hsize_post, int vsize_post, int hold_line) +void initial_di_post_2(int hsize_post, int vsize_post, + int hold_line, bool post_write_en) { DI_VSYNC_WR_MPEG_REG(DI_POST_SIZE, (hsize_post - 1) | ((vsize_post - 1) << 16)); -#if 0 - /* di demo */ - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG0_X, ((hsize_post-1)>>1)); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG0_Y, (vsize_post-1)); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_CTRL, Rd(DI_BLEND_CTRL)| -(0x2 << 20) | /* top mode. EI only */ -25); /* KDEINT */ -#endif /* if post size < MIN_POST_WIDTH, force old ei */ if (hsize_post < MIN_POST_WIDTH) DI_VSYNC_WR_MPEG_REG_BITS(DI_EI_CTRL3, 0, 31, 1); else DI_VSYNC_WR_MPEG_REG_BITS(DI_EI_CTRL3, 1, 31, 1); - if (pulldown_enable) { - /* DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG0_Y, (vsize_post>>2)-1 ); */ - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG0_Y, (vsize_post-1)); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG1_Y, - ((vsize_post>>2)<<16) | (2*(vsize_post>>2)-1)); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG2_Y, - ((2*(vsize_post>>2))<<16) | (3*(vsize_post>>2)-1)); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG3_Y, - ((3*(vsize_post>>2))<<16) | (vsize_post-1)); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG0_X, (hsize_post-1)); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG1_X, (hsize_post-1)); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG2_X, (hsize_post-1)); - DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG3_X, (hsize_post-1)); - } + /* DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG0_Y, (vsize_post>>2)-1 ); */ + DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG0_Y, (vsize_post-1)); + DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG1_Y, + ((vsize_post>>2)<<16) | (2*(vsize_post>>2)-1)); + DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG2_Y, + ((2*(vsize_post>>2))<<16) | (3*(vsize_post>>2)-1)); + DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG3_Y, + ((3*(vsize_post>>2))<<16) | (vsize_post-1)); + DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG0_X, (hsize_post-1)); + DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG1_X, (hsize_post-1)); + DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG2_X, (hsize_post-1)); + DI_VSYNC_WR_MPEG_REG(DI_BLEND_REG3_X, (hsize_post-1)); DI_VSYNC_WR_MPEG_REG(DI_POST_CTRL, (0 << 0) | (0 << 1) | @@ -1544,15 +1644,29 @@ void initial_di_post_2(int hsize_post, int vsize_post, int hold_line) ); if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { /* enable ma,disable if0 to vpp */ - if (Rd_reg_bits(VIU_MISC_CTRL0, 16, 3) != 5) { + if ((VSYNC_RD_MPEG_REG(VIU_MISC_CTRL0) & 0x50000) != 0x50000) { DI_VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0, 5, 16, 3); - if (post_wr_en) + if (post_write_en) DI_VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0, 1, 28, 1); } } } +static void post_bit_mode_config(unsigned char if0, + unsigned char if1, unsigned char if2, unsigned char post_wr) +{ + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) + return; + + DI_Wr_reg_bits(VD1_IF0_GEN_REG3, if0&0x3, 8, 2); + DI_Wr_reg_bits(DI_IF1_GEN_REG3, if1&0x3, 8, 2); + DI_Wr_reg_bits(DI_IF2_GEN_REG3, if2&0x3, 8, 2); + DI_Wr_reg_bits(DI_DIWR_Y, post_wr&0x1, 14, 1); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL) && ((post_wr&0x3) == 0x3)) + DI_Wr_reg_bits(DI_DIWR_CTRL, 0x3, 22, 2); +} + static unsigned int pldn_ctrl_rflsh = 1; module_param(pldn_ctrl_rflsh, uint, 0644); MODULE_PARM_DESC(pldn_ctrl_rflsh, "/n post blend reflesh./n"); @@ -1566,7 +1680,9 @@ void di_post_switch_buffer( struct DI_MC_MIF_s *di_mcvecrd_mif, int ei_en, int blend_en, int blend_mtn_en, int blend_mode, int di_vpp_en, int di_ddr_en, - int post_field_num, int hold_line, int urgent + int post_field_num, int hold_line, int urgent, + int invert_mv, bool pd_enable, bool mc_enable, + int vskip_cnt ) { int ei_only, buf1_en; @@ -1574,34 +1690,26 @@ void di_post_switch_buffer( ei_only = ei_en && !blend_en && (di_vpp_en || di_ddr_en); buf1_en = (!ei_only && (di_ddr_en || di_vpp_en)); - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { - if (Rd_reg_bits(VIU_MISC_CTRL0, 16, 3) != 5) - DI_VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0, 5, 16, 3); - } + if ((VSYNC_RD_MPEG_REG(VIU_MISC_CTRL0) & 0x50000) != 0x50000) + DI_VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0, 5, 16, 3); + if (di_ddr_en) + DI_VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0, + 1, 28, 1); if (ei_en || di_vpp_en || di_ddr_en) - set_di_if0_mif(di_buf0_mif, urgent, hold_line); + set_di_if0_mif(di_buf0_mif, urgent, + hold_line, vskip_cnt, di_ddr_en); if (!ei_only && (di_ddr_en || di_vpp_en)) { DI_VSYNC_WR_MPEG_REG(DI_IF1_CANVAS0, (di_buf1_mif->canvas0_addr2 << 16) | (di_buf1_mif->canvas0_addr1 << 8) | (di_buf1_mif->canvas0_addr0 << 0)); - if (is_meson_txl_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) DI_VSYNC_WR_MPEG_REG(DI_IF2_CANVAS0, (di_buf2_mif->canvas0_addr2 << 16) | (di_buf2_mif->canvas0_addr1 << 8) | (di_buf2_mif->canvas0_addr0 << 0)); - #if 0 - /* post bit mode config, if0 config in video.c */ - if (is_meson_gxtvbb_cpu() || is_meson_gxl_cpu() || - is_meson_gxm_cpu()) - DI_VSYNC_WR_MPEG_REG_BITS(DI_IF1_GEN_REG3, - di_buf1_mif->bit_mode, 8, 2); - if (is_meson_txl_cpu()) - DI_VSYNC_WR_MPEG_REG_BITS(DI_IF2_GEN_REG3, - di_buf2_mif->bit_mode, 8, 2); - #endif } /* motion for current display field. */ @@ -1614,12 +1722,16 @@ void di_post_switch_buffer( if (di_ddr_en) { DI_VSYNC_WR_MPEG_REG(DI_DIWR_CTRL, - di_diwr_mif->canvas_num | - (urgent << 16) | - (2 << 26) | - (di_ddr_en << 30)); + di_diwr_mif->canvas_num | + (urgent << 16) | + (2 << 26) | + (di_ddr_en << 30)); + post_bit_mode_config(di_buf0_mif->bit_mode, + di_buf1_mif->bit_mode, + di_buf2_mif->bit_mode, + di_diwr_mif->bit_mode); } - if ((pldn_ctrl_rflsh == 1) && pulldown_enable) { + if ((pldn_ctrl_rflsh == 1) && pd_enable) { DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, blend_en, 31, 1); DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, 7, 22, 3); DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, blend_mode, 20, 2); @@ -1630,21 +1742,27 @@ void di_post_switch_buffer( DI_VSYNC_WR_MPEG_REG(DI_BLEND_CTRL, Rd(DI_BLEND_CTRL)| (blend_en<<31) | (blend_mode<<20) | 0x1c0001f); - if (mcpre_en) { + if (mc_enable) { DI_VSYNC_WR_MPEG_REG(MCDI_MCVECRD_CTRL, (Rd(MCDI_MCVECRD_CTRL) & 0xffffff00) | (1<<9) | /* canvas enable */ di_mcvecrd_mif->canvas_num | /* canvas index. */ (urgent << 8)); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + invert_mv, 17, 1);/* invert mv */ + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + di_mcvecrd_mif->vecrd_offset, 12, 3); + if (di_mcvecrd_mif->blend_en) + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + mcen_mode, 0, 2); + else DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, - di_mcvecrd_mif->vecrd_offset, 12, 3); - if (di_mcvecrd_mif->blend_mode == 3) - DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, - mcen_mode, 0, 2); - else - DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, 0, 0, 2); } + if (!is_meson_txlx_cpu()) + invert_mv = 0; + DI_VSYNC_WR_MPEG_REG(DI_POST_CTRL, ((ei_en|blend_en) << 0) | /* line buf 0 enable */ ((blend_mode == 1?1:0) << 1) | @@ -1659,10 +1777,13 @@ void di_post_switch_buffer( (0 << 10) | /* post drop first. */ (0 << 11) | (di_vpp_en << 12) | /* post viu link */ + (invert_mv << 14) | (hold_line << 16) | /* post hold line number */ (post_field_num << 29) | /* post field number. */ (0x3 << 30) /* post soft rst post frame rst. */ ); + if (di_ddr_en && mc_enable) + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_CTRL, 1, 9, 1); } void enable_di_post_2( @@ -1673,7 +1794,8 @@ void enable_di_post_2( struct DI_SIM_MIF_s *di_mtnprd_mif, int ei_en, int blend_en, int blend_mtn_en, int blend_mode, int di_vpp_en, int di_ddr_en, int post_field_num, - int hold_line, int urgent + int hold_line, int urgent, int invert_mv, + int vskip_cnt ) { int ei_only; @@ -1683,12 +1805,16 @@ void enable_di_post_2( buf1_en = (!ei_only && (di_ddr_en || di_vpp_en)); if (ei_en || di_vpp_en || di_ddr_en) - set_di_if0_mif(di_buf0_mif, di_vpp_en, hold_line); + set_di_if0_mif(di_buf0_mif, di_vpp_en, + hold_line, vskip_cnt, di_ddr_en); /* if (!ei_only && (di_ddr_en || di_vpp_en)) */ - set_di_if1_mif(di_buf1_mif, di_vpp_en, hold_line); - if (is_meson_txl_cpu()) - set_di_if2_mif(di_buf2_mif, di_vpp_en, hold_line); + set_di_if1_mif(di_buf1_mif, di_vpp_en, hold_line, vskip_cnt); + if (is_meson_txlx_cpu() || + is_meson_gxlx_cpu() || + is_meson_txhd_cpu()) + set_di_if2_mif(di_buf2_mif, + di_vpp_en, hold_line, vskip_cnt); /* printk("%s: ei_only %d,buf1_en %d,ei_en %d,di_vpp_en %d, * di_ddr_en %d,blend_mtn_en %d,blend_mode %d.\n", @@ -1716,6 +1842,10 @@ void enable_di_post_2( (urgent << 16) | (2 << 26) | (di_ddr_en << 30)); + post_bit_mode_config(di_buf0_mif->bit_mode, + di_buf1_mif->bit_mode, + di_buf2_mif->bit_mode, + di_diwr_mif->bit_mode); } DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, 7, 22, 3); @@ -1726,6 +1856,8 @@ void enable_di_post_2( if (debug_blend_mode_ctrl != 0xff) DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, debug_blend_mode_ctrl&0x3, 20, 2); + if (!is_meson_txlx_cpu()) + invert_mv = 0; DI_VSYNC_WR_MPEG_REG(DI_POST_CTRL, ((ei_en | blend_en) << 0) | /* line buffer 0 enable */ @@ -1741,6 +1873,7 @@ void enable_di_post_2( (0 << 10) | /* post drop first. */ (0 << 11) | (di_vpp_en << 12) | /* post viu link */ +(invert_mv << 14) | /* invert mv */ (hold_line << 16) | /* post hold line number */ (post_field_num << 29) | /* post field number. */ (0x3 << 30) @@ -1753,11 +1886,11 @@ void disable_post_deinterlace_2(void) DI_VSYNC_WR_MPEG_REG(DI_POST_CTRL, 0x3 << 30); DI_VSYNC_WR_MPEG_REG(DI_POST_SIZE, (32-1) | ((128-1) << 16)); DI_VSYNC_WR_MPEG_REG(DI_IF1_GEN_REG, 0x3 << 30); - if (is_meson_txl_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) DI_VSYNC_WR_MPEG_REG(DI_IF2_GEN_REG, 0x3 << 30); if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { /* disable ma,enable if0 to vpp,enable afbc to vpp */ - if (Rd_reg_bits(VIU_MISC_CTRL0, 16, 4) != 0) + if ((VSYNC_RD_MPEG_REG(VIU_MISC_CTRL0) & 0x50000) != 0) DI_VSYNC_WR_MPEG_REG_BITS(VIU_MISC_CTRL0, 0, 16, 4); /* DI inp(current data) switch to memory */ DI_VSYNC_WR_MPEG_REG_BITS(VIUB_MISC_CTRL0, 0, 16, 1); @@ -1767,8 +1900,60 @@ void disable_post_deinterlace_2(void) */ } -void enable_film_mode_check(unsigned int width, unsigned int height, - enum vframe_source_type_e source_type) +void enable_di_post_mif(enum gate_mode_e mode) +{ + unsigned char gate = 0; + + switch (mode) { + case GATE_OFF: + gate = 1; + break; + case GATE_ON: + gate = 2; + break; + case GATE_AUTO: + gate = 0; + break; + default: + gate = 0; + } + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) { + /* enable if1 external gate freerun hw issue */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, ((gate == 0)?2:gate), 2, 2); + /* enable if2 external gate freerun hw issue */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, ((gate == 0)?2:gate), 4, 2); + /* enable di wr external gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, gate, 6, 2); + /* enable mtn rd external gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, gate, 8, 2); + /* enable mv rd external gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, gate, 10, 2); + } +} + +void di_hw_disable(bool mc_enable) +{ + DI_Wr(DI_PRE_CTRL, 0x3 << 30); + enable_di_pre_mif(false, mc_enable); + DI_Wr(DI_POST_CTRL, 0x3 << 30); + DI_Wr(DI_POST_SIZE, (32-1) | ((128-1) << 16)); + DI_Wr(DI_IF1_GEN_REG, 0x3 << 30); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) + DI_Wr(DI_IF2_GEN_REG, 0x3 << 30); + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) { + /* disable ma,enable if0 to vpp,enable afbc to vpp */ + if (Rd_reg_bits(VIU_MISC_CTRL0, 16, 4) != 0) + DI_Wr_reg_bits(VIU_MISC_CTRL0, 0, 16, 4); + /* DI inp(current data) switch to memory */ + DI_Wr_reg_bits(VIUB_MISC_CTRL0, 0, 16, 1); + } +} +/* + * old pulldown windows share below ctrl + * registers + * with new pulldown windows + */ +void film_mode_win_config(unsigned int width, unsigned int height) { unsigned int win0_start_x, win0_end_x, win0_start_y, win0_end_y; unsigned int win1_start_x, win1_end_x, win1_start_y, win1_end_y; @@ -1791,17 +1976,6 @@ void enable_film_mode_check(unsigned int width, unsigned int height, win3_end_y = win4_start_y - 1; win4_end_y = win4_start_y + (height>>3) - 1; /* 1/8 */ - pd_win_prop[0].pixels_num = -(win0_end_x-win0_start_x)*(win0_end_y-win0_start_y); - pd_win_prop[1].pixels_num = -(win1_end_x-win1_start_x)*(win1_end_y-win1_start_y); - pd_win_prop[2].pixels_num = -(win2_end_x-win2_start_x)*(win2_end_y-win2_start_y); - pd_win_prop[3].pixels_num = -(win3_end_x-win3_start_x)*(win3_end_y-win3_start_y); - pd_win_prop[4].pixels_num = -(win4_end_x-win4_start_x)*(win4_end_y-win4_start_y); - RDMA_WR(DI_MC_REG0_X, (win0_start_x << 16) | win0_end_x); RDMA_WR(DI_MC_REG0_Y, (win0_start_y << 16) | win0_end_y); RDMA_WR(DI_MC_REG1_X, (win1_start_x << 16) | win1_end_x); @@ -1812,72 +1986,22 @@ void enable_film_mode_check(unsigned int width, unsigned int height, RDMA_WR(DI_MC_REG3_Y, (win3_start_y << 16) | win3_end_y); RDMA_WR(DI_MC_REG4_X, (win4_start_x << 16) | win4_end_x); RDMA_WR(DI_MC_REG4_Y, (win4_start_y << 16) | win4_end_y); - } -static int fdn[5] = {0}; -bool read_pulldown_info(pulldown_detect_info_t *field_pd_info, - pulldown_detect_info_t *win_pd_info) +/* + * old pulldown detction module, global field diff/num & frame + * diff/numm and 5 window included + */ +void read_pulldown_info(unsigned int *glb_frm_mot_num, + unsigned int *glb_fid_mot_num) { - int i; - unsigned long pd_info[6]; - unsigned long tmp; - - DI_Wr(DI_INFO_ADDR, 0); - for (i = 0; i < 6; i++) - pd_info[i] = Rd(DI_INFO_DATA); - - memset(field_pd_info, 0, sizeof(pulldown_detect_info_t)); - field_pd_info->field_diff = pd_info[2]; - field_pd_info->field_diff_num = pd_info[4]&0xffffff; - field_pd_info->frame_diff = pd_info[0]; - field_pd_info->frame_diff_num = pd_info[1]&0xffffff; - - fdn[0] = fdn[1]; - fdn[1] = fdn[2]; - fdn[2] = fdn[3]; - fdn[3] = fdn[4]; - fdn[4] = field_pd_info->frame_diff_num; - /* if (fdn[0] || fdn[1] || fdn[2] || fdn[3] || fdn[4]) */ - if (frame_dynamic_dbg) - pr_dbg("\n fdn[4]= %x", fdn[4]); - if (frame_dynamic_level == 0) - fdn[4] = fdn[4]&0xffff00; - else if (frame_dynamic_level == 1) - fdn[4] = fdn[4]&0xfffe00; - else if (frame_dynamic_level == 2) - fdn[4] = fdn[4]&0xfffc00; - else if (frame_dynamic_level == 3) - fdn[4] = fdn[4]&0xfff800; - else if (frame_dynamic_level == 4) - fdn[4] = fdn[4]&0xfff000; - else - fdn[4] = fdn[4]&0xffff00; - if ((fdn[0]&0xffff00) || fdn[1] || fdn[2] || fdn[3] || fdn[4]) - frame_dynamic = true; - else - frame_dynamic = false; - - for (i = 0; i < MAX_WIN_NUM; i++) - memset(&(win_pd_info[i]), 0, sizeof(pulldown_detect_info_t)); - - for (i = 0; i < MAX_WIN_NUM; i++) - win_pd_info[i].frame_diff = Rd(DI_INFO_DATA); - - for (i = 0; i < MAX_WIN_NUM; i++) - win_pd_info[i].field_diff = Rd(DI_INFO_DATA); - - for (i = 0; i < MAX_WIN_NUM; i++) - tmp = Rd(DI_INFO_DATA); /* luma */ - - for (i = 0; i < MAX_WIN_NUM; i++) - win_pd_info[i].frame_diff_num = Rd(DI_INFO_DATA)&0xffffff; - - for (i = 0; i < MAX_WIN_NUM; i++) - win_pd_info[i].field_diff_num = -(Rd(DI_INFO_DATA)&0xfffff)<<4; - - return frame_dynamic; + /* + * addr will increase by 1 automatically + */ + DI_Wr(DI_INFO_ADDR, 1); + *glb_frm_mot_num = Rd(DI_INFO_DATA); + DI_Wr(DI_INFO_ADDR, 4); + *glb_fid_mot_num = Rd(DI_INFO_DATA); } void read_new_pulldown_info(struct FlmModReg_t *pFMReg) @@ -1896,14 +2020,13 @@ void read_new_pulldown_info(struct FlmModReg_t *pFMReg) pFMReg->rROCmbInf[i] = Rd(DIPD_RO_COMB_12+i); } -void di_post_read_reverse(bool reverse) +void di_post_read_reverse(bool reverse, bool mc_enable) { -#ifdef NEW_DI_TV if (reverse) { DI_Wr_reg_bits(DI_IF1_GEN_REG2, 3, 2, 2); DI_Wr_reg_bits(VD1_IF0_GEN_REG2, 0xf, 2, 4); DI_Wr_reg_bits(VD2_IF0_GEN_REG2, 0xf, 2, 4); - if (mcpre_en) { + if (mc_enable) { /* motion vector read reverse*/ DI_Wr_reg_bits(MCDI_MCVECRD_X, 1, 30, 1); DI_Wr_reg_bits(MCDI_MCVECRD_Y, 1, 30, 1); @@ -1913,16 +2036,25 @@ void di_post_read_reverse(bool reverse) DI_Wr_reg_bits(DI_IF1_GEN_REG2, 0, 2, 2); DI_Wr_reg_bits(VD1_IF0_GEN_REG2, 0, 2, 4); DI_Wr_reg_bits(VD2_IF0_GEN_REG2, 0, 2, 4); - if (mcpre_en) { + if (mc_enable) { DI_Wr_reg_bits(MCDI_MCVECRD_X, 0, 30, 1); DI_Wr_reg_bits(MCDI_MCVECRD_Y, 0, 30, 1); DI_Wr_reg_bits(MCDI_MC_CRTL, 1, 8, 1); } } -#endif } -void di_post_read_reverse_irq(bool reverse) + +static bool if2_disable; +module_param_named(if2_disable, if2_disable, bool, 0644); + +static unsigned short pre_flag = 2; +module_param_named(pre_flag, pre_flag, ushort, 0644); +void di_post_read_reverse_irq(bool reverse, unsigned char mc_pre_flag, + bool mc_enable) { + unsigned short flag_val = 1; + + mc_pre_flag = if2_disable?1:mc_pre_flag; if (reverse) { DI_VSYNC_WR_MPEG_REG_BITS(DI_IF1_GEN_REG2, 3, 2, 2); DI_VSYNC_WR_MPEG_REG_BITS(VD1_IF0_GEN_REG2, 0xf, 2, 4); @@ -1930,16 +2062,38 @@ void di_post_read_reverse_irq(bool reverse) DI_VSYNC_WR_MPEG_REG_BITS(DI_MTNRD_CTRL, 0xf, 17, 4); if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) DI_VSYNC_WR_MPEG_REG_BITS(DI_IF2_GEN_REG2, 3, 2, 2); - if (mcpre_en) { + if (mc_enable) { /* motion vector read reverse*/ DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_X, 1, 30, 1); DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_Y, 1, 30, 1); - if (is_meson_txl_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) { + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + pre_flag, 8, 2); + flag_val = (pre_flag != 2) ? 0 : 1; + } else { + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + mc_pre_flag, 8, 2); + flag_val = (mc_pre_flag != 2) ? 0 : 1; + } + DI_VSYNC_WR_MPEG_REG_BITS( + MCDI_MC_CRTL, flag_val, 11, 1); + /* disable if2 for wave if1 case, + *disable mc for pq issue + */ + if (if2_disable) { + DI_VSYNC_WR_MPEG_REG_BITS( + MCDI_MC_CRTL, 0, 11, 1); + DI_VSYNC_WR_MPEG_REG_BITS( + DI_IF2_GEN_REG, 0, 0, 1); + if (cpu_after_eq( + MESON_CPU_MAJOR_ID_GXLX)) + DI_VSYNC_WR_MPEG_REG_BITS( + MCDI_MC_CRTL, 0, 18, 1); + } + } else DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, - mc_pre_flag, 8, 2); - else - DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, - 0, 8, 1); + mc_pre_flag, 8, 1); } } else { DI_VSYNC_WR_MPEG_REG_BITS(DI_IF1_GEN_REG2, 0, 2, 2); @@ -1948,15 +2102,35 @@ void di_post_read_reverse_irq(bool reverse) DI_VSYNC_WR_MPEG_REG_BITS(DI_MTNRD_CTRL, 0, 17, 4); if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) DI_VSYNC_WR_MPEG_REG_BITS(DI_IF2_GEN_REG2, 0, 2, 2); - if (mcpre_en) { + if (mc_enable) { DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_X, 0, 30, 1); DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MCVECRD_Y, 0, 30, 1); - if (is_meson_txl_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) { + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + pre_flag, 8, 2); + flag_val = (pre_flag != 2) ? 0 : 1; + } else { + DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, + mc_pre_flag, 8, 2); + flag_val = (mc_pre_flag != 2) ? 0 : 1; + } + DI_VSYNC_WR_MPEG_REG_BITS( + MCDI_MC_CRTL, flag_val, 11, 1); + /* disable if2 for wave if1 case */ + if (if2_disable) { + DI_VSYNC_WR_MPEG_REG_BITS( + MCDI_MC_CRTL, 0, 11, 1); + DI_VSYNC_WR_MPEG_REG_BITS( + DI_IF2_GEN_REG, 0, 0, 1); + if (cpu_after_eq( + MESON_CPU_MAJOR_ID_GXLX)) + DI_VSYNC_WR_MPEG_REG_BITS( + MCDI_MC_CRTL, 0, 18, 1); + } + } else DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, - mc_pre_flag, 8, 2); - else - DI_VSYNC_WR_MPEG_REG_BITS(MCDI_MC_CRTL, - 1, 8, 1); + mc_pre_flag, 8, 1); } } } @@ -1969,41 +2143,127 @@ void diwr_set_power_control(unsigned char enable) enable?VPU_MEM_POWER_ON:VPU_MEM_POWER_DOWN); } - -static unsigned char pre_power_on; -static unsigned char post_power_on; -void di_set_power_control(unsigned char type, unsigned char enable) +void di_top_gate_control(bool top_en, bool mc_en) { - if (di_debug_flag&0x20) - return; - if (type == 0) { - /* WRITE_MPEG_REG_BITS(HHI_VPU_MEM_PD_REG0, - * enable?0:3, 26, 2); //di pre - */ - switch_vpu_mem_pd_vmod(VPU_DI_PRE, -enable?VPU_MEM_POWER_ON:VPU_MEM_POWER_DOWN); - pre_power_on = enable; + if (top_en) { + /* enable clkb input */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 1, 0, 1); + DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 1, 15, 1); + /* enable slow clk */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL0, mc_en?1:0, 10, 1); + /* enable di arb */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 0, 0, 2); + } else { + /* disable clkb input */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 0, 0, 1); + DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 0, 15, 1); + /* disable slow clk */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 0, 10, 1); + /* disable di arb */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 1, 0, 2); } - if (type == 1) - post_power_on = enable; } -unsigned char di_get_power_control(unsigned char type) +void di_pre_gate_control(bool gate, bool mc_enable) { - if (type == 0) - return pre_power_on; - -#if 0 -/* let video.c handle it */ - return 1; -#else - return post_power_on; -#endif - + if (gate) { + /* enable ma pre clk */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 1, 8, 1); + /* enable mc clk */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 1, 11, 1); + /* enable pd clk gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 0, 2, 2); + /* enable motion clk gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 0, 4, 2); + /* enable deband clk gate freerun for hw issue */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 2, 6, 2); + /* enable input mif external gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 0, 16, 2); + /* enable mem mif external gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 0, 18, 2); + /* enable chan2 mif external gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 0, 20, 2); + /* enable nr wr mif external gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 0, 22, 2); + /* enable mtn wr mif external gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 0, 24, 2); + if (mc_enable) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXHD)) + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 0, 12, 2); + else + /* enable me clk always run vlsi issue */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 3, 12, 2); + /* + * enable mc pre mv(wr) mcinfo w/r + * mif external gate + */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, + 0, 26, 2); + } + /* cowork with auto gate to config reg */ + DI_Wr_reg_bits(DI_PRE_CTRL, 3, 2, 2); + } else { + /* disable ma pre clk */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 0, 8, 1); + /* disable mc clk */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 0, 11, 1); + /* disable pd clk gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 1, 2, 2); + /* disable motion clk gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 1, 4, 2); + /* disable deband clk gate freerun for hw issue */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 1, 6, 2); + /* disable input mif external gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 1, 16, 2); + /* disable mem mif external gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 1, 18, 2); + /* disable chan2 mif external gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 1, 20, 2); + /* disable nr wr mif external gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 1, 22, 2); + /* disable mtn wr mif external gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, 1, 24, 2); + if (mc_enable) { + /* disable mc pre mv(wr) mcinfo + * w/r mif external gate + */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL1, + 1, 26, 2); + /* disable me clk gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 1, 12, 2); + } + } } +void di_post_gate_control(bool gate) +{ + if (gate) { + /* enable clk post div */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 1, 12, 1); + /* enable post line buf/fifo/mux clk */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 1, 9, 1); + /* enable blend1 clk gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL3, 0, 0, 2); + /* enable ei clk gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL3, 0, 2, 2); + /* enable ei_0 clk gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL3, 0, 4, 2); + } else { + /* disable clk post div */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 0, 12, 1); + /* disable post line buf/fifo/mux clk */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL0, 0, 9, 1); + /* disable blend1 clk gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL3, 1, 0, 2); + /* disable ei clk gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL3, 1, 2, 2); + /* disable ei_0 clk gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL3, 1, 4, 2); + } -void enable_di_pre_mif(int en) +} +static bool pre_mif_gate; +void enable_di_pre_mif(bool en, bool mc_enable) { if (en) { /* enable input mif*/ @@ -2012,15 +2272,23 @@ void enable_di_pre_mif(int en) DI_Wr(DI_INP_GEN_REG, Rd(DI_INP_GEN_REG) | 0x1); /* nrwr no clk gate en=0 */ RDMA_WR_BITS(DI_NRWR_CTRL, 0, 24, 1); - if (mcpre_en) { + if (mc_enable) { /* gate clk */ RDMA_WR_BITS(MCDI_MCVECWR_CTRL, 0, 9, 1); /* gate clk */ RDMA_WR_BITS(MCDI_MCINFOWR_CTRL, 0, 9, 1); + /* mcinfo rd req en =1 */ + RDMA_WR_BITS(MCDI_MCINFORD_CTRL, 1, 9, 1); + /* mv wr req en =1 */ + RDMA_WR_BITS(MCDI_MCVECWR_CTRL, 1, 12, 1); + /* mcinfo wr req en =1 */ + RDMA_WR_BITS(MCDI_MCINFOWR_CTRL, 1, 12, 1); } /* enable di nr/mtn/mv mif */ - RDMA_WR(VPU_WRARB_REQEN_SLV_L1C1, 0x3f); + /* RDMA_WR(VPU_WRARB_REQEN_SLV_L1C1, 0x3f); */ } else { + if (pre_mif_gate) + return; /* nrwr no clk gate en=1 */ RDMA_WR_BITS(DI_NRWR_CTRL, 1, 24, 1); /* nr wr req en =0 */ @@ -2029,7 +2297,7 @@ void enable_di_pre_mif(int en) RDMA_WR_BITS(DI_PRE_CTRL, 0, 1, 1); /* cont wr req en =0 */ RDMA_WR_BITS(DI_MTN_1_CTRL1, 0, 31, 1); - if (mcpre_en) { + if (mc_enable) { /* no gate clk */ RDMA_WR_BITS(MCDI_MCVECWR_CTRL, 1, 9, 1); /* no gate clk */ @@ -2042,7 +2310,7 @@ void enable_di_pre_mif(int en) RDMA_WR_BITS(MCDI_MCINFORD_CTRL, 0, 9, 1); } /* disable nr cont mtn mv minfo mif */ - RDMA_WR(VPU_WRARB_REQEN_SLV_L1C1, 0x2b); + /* RDMA_WR(VPU_WRARB_REQEN_SLV_L1C1, 0x2b); */ /* disable cont rd */ DI_Wr(DI_PRE_CTRL, Rd(DI_PRE_CTRL) & ~(1 << 25)); /* disable input mif*/ @@ -2056,27 +2324,114 @@ void combing_pd22_window_config(unsigned int width, unsigned int height) { unsigned short y1 = 39, y2 = height - 41; - if (width == 1080) { + if (height >= 540) { y1 = 79; y2 = height - 81; } - - DI_Wr_reg_bits(DECOMB_WIND00, 0, 16, 13);/* dcomb x0 */ - DI_Wr_reg_bits(DECOMB_WIND00, (width-1), 0, 13);/* dcomb x1 */ - DI_Wr_reg_bits(DECOMB_WIND01, 0, 16, 13);/* dcomb y0 */ - DI_Wr_reg_bits(DECOMB_WIND01, y1, 0, 13);/* dcomb y1 */ + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) { + DI_Wr_reg_bits(DECOMB_WIND00, 0, 16, 13);/* dcomb x0 */ + DI_Wr_reg_bits(DECOMB_WIND00, (width-1), 0, 13);/* dcomb x1 */ + DI_Wr_reg_bits(DECOMB_WIND01, 0, 16, 13);/* dcomb y0 */ + DI_Wr_reg_bits(DECOMB_WIND01, y1, 0, 13);/* dcomb y1 */ + DI_Wr_reg_bits(DECOMB_WIND10, 0, 16, 13);/* dcomb x0 */ + DI_Wr_reg_bits(DECOMB_WIND10, (width-1), 0, 13);/* dcomb x1 */ + DI_Wr_reg_bits(DECOMB_WIND11, (y1+1), 16, 13);/* dcomb y0 */ + DI_Wr_reg_bits(DECOMB_WIND11, y2, 0, 13);/* dcomb y1 */ + } DI_Wr_reg_bits(MCDI_PD_22_CHK_WND0_X, 0, 0, 13);/* pd22 x0 */ DI_Wr_reg_bits(MCDI_PD_22_CHK_WND0_X, (width-1), 16, 13);/* pd22 x1 */ DI_Wr_reg_bits(MCDI_PD_22_CHK_WND0_Y, 0, 0, 13);/* pd22 y0 */ DI_Wr_reg_bits(MCDI_PD_22_CHK_WND0_Y, y1, 16, 13);/* pd y1 */ - DI_Wr_reg_bits(DECOMB_WIND10, 0, 16, 13);/* dcomb x0 */ - DI_Wr_reg_bits(DECOMB_WIND10, (width-1), 0, 13);/* dcomb x1 */ - DI_Wr_reg_bits(DECOMB_WIND11, (y1+1), 16, 13);/* dcomb y0 */ - DI_Wr_reg_bits(DECOMB_WIND11, y2, 0, 13);/* dcomb y1 */ DI_Wr_reg_bits(MCDI_PD_22_CHK_WND1_X, 0, 0, 13);/* pd x0 */ DI_Wr_reg_bits(MCDI_PD_22_CHK_WND1_X, (width-1), 16, 13);/* pd x1 */ DI_Wr_reg_bits(MCDI_PD_22_CHK_WND1_Y, (y1+1), 0, 13);/* pd y0 */ - DI_Wr_reg_bits(DECOMB_WIND11, y2, 16, 13);/* pd y1 */ - + DI_Wr_reg_bits(MCDI_PD_22_CHK_WND1_Y, y2, 16, 13);/* pd y2 */ } + +void pulldown_vof_win_config(struct pulldown_detected_s *wins) +{ + + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG0_Y, + wins->regs[0].win_vs, 17, 12); + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG0_Y, + wins->regs[0].win_ve, 1, 12); + + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG1_Y, + wins->regs[1].win_vs, 17, 12); + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG1_Y, + wins->regs[1].win_ve, 1, 12); + + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG2_Y, + wins->regs[2].win_vs, 17, 12); + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG2_Y, + wins->regs[2].win_ve, 1, 12); + + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG3_Y, + wins->regs[3].win_vs, 17, 12); + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_REG3_Y, + wins->regs[3].win_ve, 1, 12); + + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + (wins->regs[0].win_ve > wins->regs[0].win_vs) + ? 1 : 0, 16, 1); + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + wins->regs[0].blend_mode, 8, 2); + + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + (wins->regs[1].win_ve > wins->regs[1].win_vs) + ? 1 : 0, 17, 1); + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + wins->regs[1].blend_mode, 10, 2); + + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + (wins->regs[2].win_ve > wins->regs[2].win_vs) + ? 1 : 0, 18, 1); + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + wins->regs[2].blend_mode, 12, 2); + + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + (wins->regs[3].win_ve > wins->regs[3].win_vs) + ? 1 : 0, 19, 1); + DI_VSYNC_WR_MPEG_REG_BITS(DI_BLEND_CTRL, + wins->regs[3].blend_mode, 14, 2); +} + +void di_load_regs(struct di_pq_parm_s *di_pq_ptr) +{ + unsigned int i = 0, addr = 0, value = 0, mask = 0, len; + struct am_reg_s *regs_p; + + if (pq_load_dbg == 1) + return; + if (pq_load_dbg == 2) + pr_info("[DI]%s hw load 0x%x pq table len %u.\n", + __func__, di_pq_ptr->pq_parm.table_name, + di_pq_ptr->pq_parm.table_len); + if (PTR_RET(di_pq_ptr->regs)) { + pr_err("[DI] table ptr error.\n"); + return; + } + regs_p = (struct am_reg_s *)di_pq_ptr->regs; + len = di_pq_ptr->pq_parm.table_len; + for (i = 0; i < len; i++) { + addr = regs_p->addr; + value = regs_p->val; + mask = regs_p->mask; + if (pq_load_dbg == 2) + pr_info("[%u][0x%x] = [0x%x]&[0x%x]\n", + i, addr, value, mask); + if (regs_p->mask != 0xffffffff) { + value = ((Rd(addr) & (~(mask))) | + (value & mask)); + } + regs_p++; + DI_Wr(addr, value); + if (pq_load_dbg == 2) + pr_info("[%u][0x%x] = [0x%x]\n", i, addr, value); + } +} + +#ifdef DEBUG_SUPPORT +module_param_named(pre_mif_gate, pre_mif_gate, bool, 0644); +#endif diff --git a/drivers/amlogic/media/deinterlace/deinterlace_hw.h b/drivers/amlogic/media/deinterlace/deinterlace_hw.h new file mode 100644 index 000000000000..19656a101261 --- /dev/null +++ b/drivers/amlogic/media/deinterlace/deinterlace_hw.h @@ -0,0 +1,165 @@ +/* + * drivers/amlogic/media/deinterlace/deinterlace_hw.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef _DI_HW_H +#define _DI_HW_H +#include +#include "pulldown_drv.h" +#include "nr_drv.h" +#include "deinterlace_hw.h" + +/* if post size < 80, filter of ei can't work */ +#define MIN_POST_WIDTH 80 +#define MIN_BLEND_WIDTH 27 + +struct DI_MIF_s { + unsigned short luma_x_start0; + unsigned short luma_x_end0; + unsigned short luma_y_start0; + unsigned short luma_y_end0; + unsigned short chroma_x_start0; + unsigned short chroma_x_end0; + unsigned short chroma_y_start0; + unsigned short chroma_y_end0; + unsigned set_separate_en:2; + unsigned src_field_mode:1; + unsigned src_prog:1; + unsigned video_mode:1; + unsigned output_field_num:1; + unsigned bit_mode:2; + /* + * unsigned burst_size_y:2; set 3 as default + * unsigned burst_size_cb:2;set 1 as default + * unsigned burst_size_cr:2;set 1 as default + */ + unsigned canvas0_addr0:8; + unsigned canvas0_addr1:8; + unsigned canvas0_addr2:8; +}; + +struct DI_SIM_MIF_s { + unsigned short start_x; + unsigned short end_x; + unsigned short start_y; + unsigned short end_y; + unsigned short canvas_num; + unsigned short bit_mode; +}; + +struct DI_MC_MIF_s { + unsigned short start_x; + unsigned short start_y; + unsigned short end_y; + unsigned short size_x; + unsigned short size_y; + unsigned short canvas_num; + unsigned short blend_en; + unsigned short vecrd_offset; +}; + +enum gate_mode_e { + GATE_AUTO, + GATE_ON, + GATE_OFF, +}; + +struct mcinfo_lmv_s { + unsigned char lock_flag; + char lmv; + unsigned short lock_cnt; +}; + +struct di_pq_parm_s { + struct am_pq_parm_s pq_parm; + struct am_reg_s *regs; + struct list_head list; +}; + +void read_pulldown_info(unsigned int *glb_frm_mot_num, + unsigned int *glb_fid_mot_num); +void read_new_pulldown_info(struct FlmModReg_t *pFMRegp); + +void combing_pd22_window_config(unsigned int width, unsigned int height); +void di_hw_init(bool pulldown_en, bool mc_enable); +void di_hw_uninit(void); +void enable_di_pre_aml( + struct DI_MIF_s *di_inp_mif, + struct DI_MIF_s *di_mem_mif, + struct DI_MIF_s *di_chan2_mif, + struct DI_SIM_MIF_s *di_nrwr_mif, + struct DI_SIM_MIF_s *di_mtnwr_mif, + struct DI_SIM_MIF_s *di_contp2rd_mif, + struct DI_SIM_MIF_s *di_contprd_mif, + struct DI_SIM_MIF_s *di_contwr_mif, + int nr_en, int mtn_en, int pd32_check_en, int pd22_check_en, + int hist_check_en, int pre_field_num, int pre_vdin_link, + int hold_line, int urgent); +void enable_afbc_input(struct vframe_s *vf); + +void mc_pre_mv_irq(void); +void enable_mc_di_pre(struct DI_MC_MIF_s *di_mcinford_mif, + struct DI_MC_MIF_s *di_mcinfowr_mif, + struct DI_MC_MIF_s *di_mcvecwr_mif, int urgent); +void enable_mc_di_post(struct DI_MC_MIF_s *di_mcvecrd_mif, + int urgent, bool reverse, int invert_mv); +void disable_post_deinterlace_2(void); +void initial_di_post_2(int hsize_post, int vsize_post, + int hold_line, bool write_en); +void enable_di_post_2( + struct DI_MIF_s *di_buf0_mif, + struct DI_MIF_s *di_buf1_mif, + struct DI_MIF_s *di_buf2_mif, + struct DI_SIM_MIF_s *di_diwr_mif, + struct DI_SIM_MIF_s *di_mtnprd_mif, + int ei_en, int blend_en, int blend_mtn_en, int blend_mode, + int di_vpp_en, int di_ddr_en, + int post_field_num, int hold_line, int urgent, + int invert_mv, int vskip_cnt +); +void di_post_switch_buffer( + struct DI_MIF_s *di_buf0_mif, + struct DI_MIF_s *di_buf1_mif, + struct DI_MIF_s *di_buf2_mif, + struct DI_SIM_MIF_s *di_diwr_mif, + struct DI_SIM_MIF_s *di_mtnprd_mif, + struct DI_MC_MIF_s *di_mcvecrd_mif, + int ei_en, int blend_en, int blend_mtn_en, int blend_mode, + int di_vpp_en, int di_ddr_en, + int post_field_num, int hold_line, int urgent, + int invert_mv, bool pd_en, bool mc_enable, + int vskip_cnt +); +void di_post_read_reverse(bool reverse, bool mc_enable); +void di_post_read_reverse_irq(bool reverse, + unsigned char mc_pre_flag, bool mc_enable); +void di_top_gate_control(bool top_en, bool mc_en); +void di_pre_gate_control(bool enable, bool mc_enable); +void di_post_gate_control(bool gate); +void diwr_set_power_control(unsigned char enable); +void di_hw_disable(bool mc_enable); +void enable_di_pre_mif(bool enable, bool mc_enable); +void enable_di_post_mif(enum gate_mode_e mode); +void di_hw_uninit(void); +void di_load_regs(struct di_pq_parm_s *di_pq_ptr); +void combing_pd22_window_config(unsigned int width, unsigned int height); +void calc_lmv_init(void); +void calc_lmv_base_mcinfo(unsigned int vf_height, unsigned long mcinfo_adr); +void init_field_mode(unsigned short height); +void film_mode_win_config(unsigned int width, unsigned int height); +void pulldown_vof_win_config(struct pulldown_detected_s *wins); +void di_load_regs(struct di_pq_parm_s *di_pq_ptr); +#endif diff --git a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c index be4e871cc787..04cdda5cdccb 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_mtn.c +++ b/drivers/amlogic/media/deinterlace/deinterlace_mtn.c @@ -39,7 +39,6 @@ #include #include #include "register.h" -#include "deinterlace.h" #include "deinterlace_mtn.h" #define MAX_NUM_DI_REG 32 @@ -88,7 +87,7 @@ module_param_array(combing_glb_mot_thr_LH, uint, &num_glb_mot_thr_LH, 0664); static unsigned int num_glb_mot_thr_HL = 4; module_param_array(combing_glb_mot_thr_HL, uint, &num_glb_mot_thr_HL, 0664); -int last_lev = -1; +static int last_lev = -1; static int force_lev = 0xff; module_param_named(combing_force_lev, force_lev, int, 0664); static int dejaggy_flag = -1; @@ -101,15 +100,6 @@ static uint num_dejaggy_setting = 5; static int combing_dejaggy_setting[6] = {1, 1, 1, 2, 3, 3}; module_param_array(combing_dejaggy_setting, uint, &num_dejaggy_setting, 0664); -#ifdef CONFIG_AM_ATVDEMOD -static int atv_snr_val = 30; -module_param_named(atv_snr_val, atv_snr_val, int, 0664); -static int atv_snr_cnt; -module_param_named(atv_snr_cnt, atv_snr_cnt, int, 0664); -static int atv_snr_cnt_limit = 30; -module_param_named(atv_snr_cnt_limit, atv_snr_cnt_limit, int, 0664); -#endif - static struct combing_param_s cmb_param; static unsigned int combing_setting_masks[MAX_NUM_DI_REG] = { @@ -123,7 +113,7 @@ static unsigned int combing_setting_masks[MAX_NUM_DI_REG] = { 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, + 0xffffff9f, 0xffffffff, 0x0003ff1f, 0x01ff3fff, @@ -143,7 +133,7 @@ static unsigned int combing_pure_still_setting[MAX_NUM_DI_REG] = { 0x1A1A2662, 0x0D200302, 0x02020202, - 0x06090708, + 0x06090748, 0x40020A04, 0x0001FF0C, 0x00400204, @@ -162,7 +152,7 @@ static unsigned int combing_bias_static_setting[MAX_NUM_DI_REG] = { 0x1A1A2662, 0x0D200302, 0x02020202, - 0x06090708, + 0x06090748, 0x40020A04, 0x0001FF0C, 0x00400204, @@ -182,7 +172,7 @@ static unsigned int combing_normal_setting[MAX_NUM_DI_REG] = { 0x1A1A2662, 0x0D200302, 0x02020606, - 0x05080304, + 0x05080344, 0x40020a04, 0x0001FF0C, 0x00400204, @@ -201,7 +191,7 @@ static unsigned int combing_bias_motion_setting[MAX_NUM_DI_REG] = { 0x1A1A2662, 0x0D200302, 0x02020606, - 0x05080304, + 0x05080344, 0x40020a04, 0x0001ff0c, /* 0x0001FF12 */ 0x00400204, /* 0x00200204 */ @@ -220,7 +210,7 @@ static unsigned int combing_very_motion_setting[MAX_NUM_DI_REG] = { 0x1A1A2662, 0x0D200302, 0x02020606, - 0x05080304, + 0x05080344, 0x40020a04, /* 0x60000404,*/ 0x0001ff0c, /* 0x0001FF12 */ 0x00400204, /* 0x00200204 */ @@ -239,7 +229,7 @@ static unsigned int combing_resolution_setting[MAX_NUM_DI_REG] = { 0x1a1a2662, 0x0d200302, 0x01010101, - 0x06090708, + 0x06090748, 0x40020a04, 0x0001ff0c, 0x00400204, @@ -278,10 +268,11 @@ static unsigned int (*combing_setting_values[6])[MAX_NUM_DI_REG] = { &combing_very_motion_setting, &combing_resolution_setting }; - -void adpative_combing_config(unsigned int width, unsigned int height, - enum vframe_source_type_e src_type, - bool prog, enum tvin_sig_fmt_e fmt) +static struct combing_status_s cmb_status; +struct combing_status_s *adpative_combing_config(unsigned int width, + unsigned int height, + enum vframe_source_type_e src_type, + bool prog, enum tvin_sig_fmt_e fmt) { int i = 0; @@ -294,10 +285,11 @@ void adpative_combing_config(unsigned int width, unsigned int height, last_lev = -1; cmb_param.width = width; cmb_param.height = height; + cmb_param.field_idx = 0; cmb_param.src_type = src_type; cmb_param.fmt = fmt; cmb_param.prog_flag = prog; - di_apply_reg_cfg(0); + return &cmb_status; } void adpative_combing_exit(void) @@ -307,6 +299,7 @@ void adpative_combing_exit(void) DI_Wr_reg_bits(SRSHARP0_SHARP_DEJ1_MISC, 0, 3, 1); } } +static int cmb_adpset_cnt; unsigned int adp_set_level(unsigned int diff, unsigned int field_diff_num) { unsigned int rst = 0; @@ -318,7 +311,7 @@ unsigned int adp_set_level(unsigned int diff, unsigned int field_diff_num) rst = 1; else rst = 2; - pr_info("%s rst=%u.", __func__, rst); + if (cmb_adpset_cnt > 0) { pr_info("\field-num=%04d frame-num=%04d lvl=%c\n", field_diff_num, diff, tlog[rst]); @@ -497,16 +490,19 @@ module_param(small_local_mtn, uint, 0644); MODULE_PARM_DESC(small_local_mtn, "small_local_mtn"); unsigned int adp_set_mtn_ctrl10(unsigned int diff, unsigned int dlvel, - unsigned int *frame_diff_avg) + unsigned int frame_diff_avg) { int istp = 0, idats = 0, idatm = 0, idatr = 0; unsigned int rst = 0; - if (*frame_diff_avg < small_local_mtn) + if (frame_diff_avg < small_local_mtn) rst = combing_very_motion_setting[9]; - else if (dlvel == 0) - rst = combing_pure_still_setting[9]; - else if (dlvel == 1) + else if (dlvel == 0) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) + rst = 0x01010101; + else + rst = combing_pure_still_setting[9]; + } else if (dlvel == 1) rst = combing_very_motion_setting[9]; else { istp = 64 * (diff - combing_glb_mot_thr_LH[0]) / @@ -540,7 +536,7 @@ unsigned int adp_set_mtn_ctrl10(unsigned int diff, unsigned int dlvel, if (cmb_adpset_cnt > 0) { pr_info("mtn_ctr10=0x%08x (frame_dif_avg=%03d)\n", - rst, *frame_diff_avg); + rst, frame_diff_avg); } return rst; } @@ -600,6 +596,10 @@ static void set_combing_regs(int lvl, int bit_mode) if ((combing_setting_registers[i] == 0) || (combing_setting_masks[i] == 0)) break; + if (combing_setting_registers[i] == DI_MTN_1_CTRL1) + DI_Wr_reg_bits(DI_MTN_1_CTRL1, + ((*combing_setting_values[lvl])[0] & + combing_setting_masks[i]), 0, 24); if (bit_mode != 10 && combing_setting_registers[i] == NR2_MATNR_DEGHOST) break; @@ -622,15 +622,12 @@ static void set_combing_regs(int lvl, int bit_mode) static int di_debug_readreg; module_param(di_debug_readreg, int, 0644); MODULE_PARM_DESC(di_debug_readreg, "di_debug_readreg"); -static int dejaggy_4p = true; -module_param_named(dejaggy_4p, dejaggy_4p, int, 0664); int adaptive_combing_fixing( + struct combing_status_s *cmb_status, unsigned int field_diff, unsigned int frame_diff, - int cur_lev, int bit_mode, - int cmb_cnt, int like_pulldown22_flag, - unsigned int *frame_diff_avg) + int bit_mode) { unsigned int glb_mot_avg2; unsigned int glb_mot_avg3; @@ -645,6 +642,7 @@ int adaptive_combing_fixing( static unsigned int pre_num; unsigned int crt_num = field_diff; unsigned int drat = 0; + int tmp = 0; static int still_field_count; static int glb_mot[5] = {0, 0, 0, 0, 0}; @@ -654,13 +652,13 @@ int adaptive_combing_fixing( diff = crt_num - pre_num; if (diff >= cmb_param.width) - field_diff_rate = 0; + cmb_status->field_diff_rate = 0; else { drat = (diff << 8) / (cmb_param.width + 1); if (drat > 255) - field_diff_rate = 0; + cmb_status->field_diff_rate = 0; else - field_diff_rate = 256 - drat; + cmb_status->field_diff_rate = 256 - drat; } pre_num = crt_num; @@ -690,26 +688,29 @@ int adaptive_combing_fixing( else if (still_field_count < 16) still_field_count++; - if (glb_mot_avg3 > combing_glb_mot_thr_LH[min(cur_lev, 3)]) { - if (cur_lev < 4) - cur_lev++; + tmp = cmb_status->cur_level; + if (glb_mot_avg3 > combing_glb_mot_thr_LH[min(tmp, 3)]) { + if (cmb_status->cur_level < 4) + cmb_status->cur_level++; } else { + tmp = cmb_status->cur_level; if (glb_mot_avg5 < - combing_glb_mot_thr_HL[max(cur_lev - 1, 0)]) { - if (cur_lev <= 1 && still_field_count > 5) - cur_lev = 0; + combing_glb_mot_thr_HL[max((tmp - 1), 0)]) { + if (cmb_status->cur_level <= 1 && still_field_count > 5) + cmb_status->cur_level = 0; else - cur_lev = max(cur_lev - 1, 1); + cmb_status->cur_level = max((tmp - 1), 1); } } if ((force_lev >= 0) & (force_lev < 6)) - cur_lev = force_lev; - if (cur_lev != last_lev) { - set_combing_regs(cur_lev, bit_mode); - if (pr_pd & 0x400) - pr_dbg("\t%5d: from %d to %d: di_mtn_1_ctrl1 = %08x\n", - field_count, last_lev, cur_lev, Rd(DI_MTN_1_CTRL1)); - last_lev = cur_lev; + cmb_status->cur_level = force_lev; + if (cmb_status->cur_level != last_lev) { + set_combing_regs(cmb_status->cur_level, bit_mode); + if (prt_flg) + pr_info("\t%5d: from %d to %d: mtn_1_ctrl1 = %08x\n", + cmb_param.field_idx, last_lev, + cmb_status->cur_level, Rd(DI_MTN_1_CTRL1)); + last_lev = cmb_status->cur_level; } if ((force_lev > 5) && (glb_mot[1] != glb_mot[0])) { @@ -728,7 +729,7 @@ int adaptive_combing_fixing( pre_dat[1] = Rd(DI_MTN_1_CTRL4); wt_dat = adp_set_mtn_ctrl4(diff, dlvl, cmb_param.height, - cmb_cnt); + cmb_status->cmb_row_num); if (pre_dat[1] != wt_dat) { DI_Wr(DI_MTN_1_CTRL4, wt_dat); if (prt_flg) @@ -747,7 +748,8 @@ int adaptive_combing_fixing( } pre_dat[3] = Rd(DI_MTN_1_CTRL10); - wt_dat = adp_set_mtn_ctrl10(diff, dlvl, frame_diff_avg); + wt_dat = adp_set_mtn_ctrl10(diff, dlvl, + cmb_status->frame_diff_avg); if (pre_dat[3] != wt_dat) { DI_Wr(DI_MTN_1_CTRL10, wt_dat); pre_dat[3] = wt_dat; @@ -764,229 +766,10 @@ int adaptive_combing_fixing( pr_info("set mtn11 0x%08x.\n\n", wt_dat); } } - - if (is_meson_gxtvbb_cpu() && dejaggy_enable) { - /* only enable dejaggy for interlace */ - if (cmb_param.prog_flag && - !dejaggy_4p) { - if (dejaggy_flag != -1) { - dejaggy_flag = -1; - DI_Wr_reg_bits(SRSHARP0_SHARP_DEJ1_MISC, - 0, 3, 1); - } - } else { - if ((dejaggy_flag == -1) - || ((Rd(SRSHARP0_SHARP_SR2_CTRL) & (1 << 24)) == 0)) { - /* enable dejaggy module */ - DI_Wr_reg_bits(SRSHARP0_SHARP_SR2_CTRL, - 1, 24, 1); - /* first time set default */ - DI_Wr_reg_bits(SRSHARP0_SHARP_DEJ2_PRC, - 0xff, 24, 8); - DI_Wr(SRSHARP0_SHARP_DEJ1_PRC, - (0xff<<24)|(0xd1<<16)|(0xe<<8)|0x31); - DI_Wr( - SRSHARP0_SHARP_DEJ2_MISC, 0x30); - DI_Wr( - SRSHARP0_SHARP_DEJ1_MISC, 0x02f4); - dejaggy_flag = 0; - } - if (dejaggy_enable) { - /* dejaggy alpha according to motion level */ - dejaggy_flag = - combing_dejaggy_setting[cur_lev]; - /* TODO: check like_pulldown22_flag and ATV - * noise_level - */ - #ifdef CONFIG_AM_ATVDEMOD - if ((aml_atvdemod_get_snr_ex() < atv_snr_val) - && cmb_param.src_type == VFRAME_SOURCE_TYPE_TUNER) { - if (atv_snr_cnt++ > atv_snr_cnt_limit) - dejaggy_flag += 3; - } else if (atv_snr_cnt) - atv_snr_cnt = 0; - #endif - if (like_pulldown22_flag && (cur_lev > 2)) - dejaggy_flag += 1; - /* overwrite dejaggy alpha */ - if (dejaggy_enable >= 2) - dejaggy_flag = dejaggy_enable; - if (dejaggy_flag > 4) - dejaggy_flag = 4; - if (dejaggy_flag) - DI_Wr_reg_bits( - SRSHARP0_SHARP_DEJ1_MISC, - (1<<3)|dejaggy_flag, 0, 4); - else - DI_Wr_reg_bits( - SRSHARP0_SHARP_DEJ1_MISC, - 0, 3, 1); - } else - dejaggy_flag = 0; - } - } else if (is_meson_gxtvbb_cpu()) { - dejaggy_flag = -1; - DI_Wr_reg_bits(SRSHARP0_SHARP_DEJ1_MISC, 0, 3, 1); - } - return cur_lev; + cmb_param.field_idx++; + return 0; } -static reg_cfg_t *reg_cfg_head; - -/* new pre and post di setting */ -reg_cfg_t di_default_pre = { - NULL, - ((1 << VFRAME_SOURCE_TYPE_OTHERS) | - (1 << VFRAME_SOURCE_TYPE_TUNER) | - (1 << VFRAME_SOURCE_TYPE_CVBS) | - (1 << VFRAME_SOURCE_TYPE_COMP) | - (1 << VFRAME_SOURCE_TYPE_HDMI) - ), - 0, - 0, - { - ( - (TVIN_SIG_FMT_COMP_480P_60HZ_D000 << 16) | - TVIN_SIG_FMT_CVBS_SECAM), - 0 - }, - { - {DI_EI_CTRL3, 0x0000013, 0, 27}, - {DI_EI_CTRL4, 0x151b3084, 0, 31}, - {DI_EI_CTRL5, 0x5273204f, 0, 31}, - {DI_EI_CTRL6, 0x50232815, 0, 31}, - {DI_EI_CTRL7, 0x2fb56650, 0, 31}, - {DI_EI_CTRL8, 0x230019a4, 0, 31}, - {DI_EI_CTRL9, 0x7cb9bb33, 0, 31}, -/* #define DI_EI_CTRL10 */ - {0x1793, 0x0842c6a9, 0, 31}, -/* #define DI_EI_CTRL11 */ - {0x179e, 0x486ab07a, 0, 31}, -/* #define DI_EI_CTRL12 */ - {0x179f, 0xdb0c2503, 0, 32}, -/* #define DI_EI_CTRL13 */ - {0x17a8, 0x0f021414, 0, 31}, - { 0 }, - } -}; -reg_cfg_t di_default_post = { - NULL, - ((1 << VFRAME_SOURCE_TYPE_OTHERS) | - (1 << VFRAME_SOURCE_TYPE_TUNER) | - (1 << VFRAME_SOURCE_TYPE_CVBS) | - (1 << VFRAME_SOURCE_TYPE_COMP) | - (1 << VFRAME_SOURCE_TYPE_HDMI) - ), - 1, - 2, - { - ( - (TVIN_SIG_FMT_COMP_480P_60HZ_D000 << 16) | - TVIN_SIG_FMT_CVBS_SECAM), - 0 - }, - { - {DI_MTN_1_CTRL1, 0, 30, 1}, - {DI_MTN_1_CTRL1, 0x0202015, 0, 27}, - {DI_MTN_1_CTRL2, 0x141a2062, 0, 31}, - {DI_MTN_1_CTRL3, 0x1520050a, 0, 31}, - {DI_MTN_1_CTRL4, 0x08800840, 0, 31}, - {DI_MTN_1_CTRL5, 0x74200d0d, 0, 31}, -/* #define DI_MTN_1_CTRL6 */ - {DI_MTN_1_CTRL6, 0x0d5a1520, 0, 31}, -/* #define DI_MTN_1_CTRL7 */ - {DI_MTN_1_CTRL7, 0x0a0a0201, 0, 31}, -/* #define DI_MTN_1_CTRL8 */ - {DI_MTN_1_CTRL8, 0x1a1a2662, 0, 31}, -/* #define DI_MTN_1_CTRL9 */ - {DI_MTN_1_CTRL9, 0x0d200302, 0, 31}, -/* #define DI_MTN_1_CTRL10 */ - {DI_MTN_1_CTRL10, 0x02020606, 0, 31}, -/* #define DI_MTN_1_CTRL11 */ - {DI_MTN_1_CTRL11, 0x05080304, 0, 31}, -/* #define DI_MTN_1_CTRL12 */ - {DI_MTN_1_CTRL12, 0x40020a04, 0, 31}, - { 0 }, - } -}; - -void di_add_reg_cfg(reg_cfg_t *reg_cfg) -{ - reg_cfg->next = reg_cfg_head; - reg_cfg_head = reg_cfg; -} - -void di_add_reg_cfg_init(void) -{ - di_add_reg_cfg(&di_default_pre); - di_add_reg_cfg(&di_default_post); -} -static int use_reg_cfg = 1; -MODULE_PARM_DESC(use_reg_cfg, "\n use_reg_cfg\n"); -module_param(use_reg_cfg, uint, 0664); - -void di_apply_reg_cfg(unsigned char pre_post_type) -{ - reg_cfg_t *reg_cfg = reg_cfg_head; - int ii; - unsigned char set_flag = 0; - - if (!use_reg_cfg) - return; - while (reg_cfg) { - if ((pre_post_type == reg_cfg->pre_post_type) && - ((1 << cmb_param.src_type) & - reg_cfg->source_types_enable)) { - if (cmb_param.src_type == - VFRAME_SOURCE_TYPE_OTHERS && - (reg_cfg->dtv_definition_type != 2)) { - /* if:dtv stand definition - * else if:high definition - */ - if ((cmb_param.height<<1) < 720 && - reg_cfg->dtv_definition_type) - set_flag = 1; - else if ((cmb_param.height<<1) >= 720 - && (!reg_cfg->dtv_definition_type)) - set_flag = 1; - } else { - for (ii = 0; ii < FMT_MAX_NUM; ii++) { - if (reg_cfg-> - sig_fmt_range[ii] == 0) - break; - else if ( - (cmb_param.fmt >= - ((reg_cfg->sig_fmt_range[ii] - >> 16) & 0xffff)) - && (cmb_param.fmt <= - (reg_cfg->sig_fmt_range[ii] & - 0xffff))) { - set_flag = 1; - break; - } - } - } - } - if (set_flag) { - for (ii = 0; ii < REG_SET_MAX_NUM; ii++) { - if (reg_cfg->reg_set[ii].adr == 0) - break; - if (pre_post_type) { - DI_VSYNC_WR_MPEG_REG_BITS( - reg_cfg->reg_set[ii].adr, - reg_cfg->reg_set[ii].val, - reg_cfg->reg_set[ii].start, - reg_cfg->reg_set[ii].len); - } else { - RDMA_WR_BITS( - reg_cfg->reg_set[ii].adr, - reg_cfg->reg_set[ii].val, - reg_cfg->reg_set[ii].start, - reg_cfg->reg_set[ii].len); - } - } - break; - } - reg_cfg = reg_cfg->next; - } -} +#ifdef DEBUG_SUPPORT +module_param_named(cmb_adpset_cnt, cmb_adpset_cnt, int, 0644); +#endif diff --git a/drivers/amlogic/media/deinterlace/deinterlace_mtn.h b/drivers/amlogic/media/deinterlace/deinterlace_mtn.h index 49d7b1d9d53a..019e01273ebe 100644 --- a/drivers/amlogic/media/deinterlace/deinterlace_mtn.h +++ b/drivers/amlogic/media/deinterlace/deinterlace_mtn.h @@ -14,50 +14,34 @@ * more details. * */ - +#ifndef _DI_MTN_H +#define _DI_MTN_H +#include +#include struct combing_param_s { unsigned int width; unsigned int height; + unsigned int field_idx; enum vframe_source_type_e src_type; enum tvin_sig_fmt_e fmt; bool prog_flag; }; -struct reg_set_s { - unsigned int adr; - unsigned int val; - unsigned short start; - unsigned short len; +struct combing_status_s { + unsigned int frame_diff_avg; + unsigned int cmb_row_num; + unsigned int field_diff_rate; + int like_pulldown22_flag; + unsigned int cur_level; }; -#define reg_set_t struct reg_set_s -#define REG_SET_MAX_NUM 128 -#define FMT_MAX_NUM 32 -struct reg_cfg_ { - struct reg_cfg_ *next; - unsigned int source_types_enable; - /* each bit corresponds to one source type */ - unsigned int pre_post_type; /* pre, 0; post, 1 */ - unsigned int dtv_definition_type; - /*high definition,0; stand definition ,1;common,2*/ - unsigned int sig_fmt_range[FMT_MAX_NUM]; - /* {bit[31:16]~bit[15:0]}, include bit[31:16] and bit[15:0] */ - reg_set_t reg_set[REG_SET_MAX_NUM]; -}; -#define reg_cfg_t struct reg_cfg_ -extern int last_lev; -extern int dejaggy_enable; -void adpative_combing_config(unsigned int width, unsigned int height, - enum vframe_source_type_e src_type, bool prog, - enum tvin_sig_fmt_e fmt); +struct combing_status_s *adpative_combing_config(unsigned int width, + unsigned int height, + enum vframe_source_type_e src_type, bool prog, + enum tvin_sig_fmt_e fmt); int adaptive_combing_fixing( + struct combing_status_s *cmb_status, unsigned int field_diff, unsigned int frame_diff, - int cur_lev, int bit_mode, int cmb_cnt, - int like_pulldown22_flag, unsigned int *frame_diff_avg); + int bit_mode); void adpative_combing_exit(void); -#ifdef CONFIG_AM_ATVDEMOD -extern int aml_atvdemod_get_snr_ex(void); #endif -void di_apply_reg_cfg(unsigned char pre_post_type); -void di_add_reg_cfg_init(void); - diff --git a/drivers/amlogic/media/deinterlace/deinterlace_trace.h b/drivers/amlogic/media/deinterlace/deinterlace_trace.h new file mode 100644 index 000000000000..bee3411fad68 --- /dev/null +++ b/drivers/amlogic/media/deinterlace/deinterlace_trace.h @@ -0,0 +1,57 @@ +/* + * drivers/amlogic/media/deinterlace/deinterlace_trace.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM di + +#if !defined(_DI_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _DI_TRACE_H + +#include + +/* single lifecycle events */ +DECLARE_EVENT_CLASS(di_event_class, + TP_PROTO(const char *name, int field_cnt, unsigned long time), + TP_ARGS(name, field_cnt, time), + TP_STRUCT__entry( + __string(name, name) + __field(int, field_cnt) + __field(unsigned long, time) + ), + TP_fast_assign( + __assign_str(name, name); + __entry->field_cnt = field_cnt; + __entry->time = time; + ), + TP_printk("[%s-%dth-%lums]", __get_str(name), + __entry->field_cnt, __entry->time) +); + +#define DEFINE_DI_EVENT(name) \ +DEFINE_EVENT(di_event_class, name, \ + TP_PROTO(const char *name, int field_cnt, unsigned long time), \ + TP_ARGS(name, field_cnt, time)) + +DEFINE_DI_EVENT(di_pre); +DEFINE_DI_EVENT(di_post); +#endif /* _VDEC_TRACE_H */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE deinterlace_trace +#include diff --git a/drivers/amlogic/media/deinterlace/detect3d.c b/drivers/amlogic/media/deinterlace/detect3d.c index b9c856b9770c..320edf292ad4 100644 --- a/drivers/amlogic/media/deinterlace/detect3d.c +++ b/drivers/amlogic/media/deinterlace/detect3d.c @@ -19,13 +19,10 @@ #include /* Amlogic Headers */ -#include #include #include - #include "register.h" #include "detect3d.h" -#include "deinterlace.h" /*******************Local defines**********************/ #define DET3D_REG_NUM 9 @@ -98,7 +95,7 @@ static struct det3d_info_s det3d_info = { * Enable and Disable det3d * flag == true, enable det3d; flag == false, disable det3d; */ -void det3d_enable(bool flag) +void det3d_config(bool flag) { int i; @@ -225,7 +222,7 @@ det3d_info.tscore_3d_tb_accum + (tb_score <= 0) - det3d_info.score_3d_chs = det3d_info.score_3d_chs + tmp1; det3d_info.score_3d_int = det3d_info.score_3d_int + tmp2; if (det3d_debug) - pr_dbg("%s input(%d,%d),output (%d,%d).\n", + pr_info("%s input(%d,%d),output (%d,%d).\n", __func__, chessbd_score, int_score, det3d_info.score_3d_chs, det3d_info.score_3d_int); /* cliping to s7 */ @@ -422,9 +419,9 @@ chessbd_ver_thrd); } if (det3d_debug) { - pr_dbg("det3d:frame = %d, 3D_fmt = %d, score_3d_lr = %d,", + pr_info("det3d:frame = %d, 3D_fmt = %d, score_3d_lr = %d,", det3d_info.nfrm, det3d_info.tfw_det3d_fmt, det3d_info.score_3d_lr); - pr_dbg("score_3d_tb = %d, score_3d_int = %d, score_3d_chs = %d", + pr_info("score_3d_tb = %d, score_3d_int = %d, score_3d_chs = %d", det3d_info.score_3d_tb, det3d_info.score_3d_int, det3d_info.score_3d_chs); } return det3d_info.tfw_det3d_fmt; diff --git a/drivers/amlogic/media/deinterlace/detect3d.h b/drivers/amlogic/media/deinterlace/detect3d.h index efead1b27cec..ab9f91479ae6 100644 --- a/drivers/amlogic/media/deinterlace/detect3d.h +++ b/drivers/amlogic/media/deinterlace/detect3d.h @@ -313,7 +313,7 @@ enum det3d_fmt_e { /* *************************************** */ /* ******** GLOBAL FUNCTION CLAIM ******** */ /* *************************************** */ -extern void det3d_enable(bool flag); +extern void det3d_config(bool flag); extern enum tvin_trans_fmt det3d_fmt_detect(void); #define WRITE_DET3D_REG(x, val) aml_write_vcbus(x, val) #define WRITE_DET3D_REG_BITS(x, val, start, length) \ diff --git a/drivers/amlogic/media/deinterlace/film_mode_fmw/Makefile b/drivers/amlogic/media/deinterlace/film_mode_fmw/Makefile new file mode 100644 index 000000000000..5448575d5ecb --- /dev/null +++ b/drivers/amlogic/media/deinterlace/film_mode_fmw/Makefile @@ -0,0 +1,7 @@ +ifeq ($(TARGET_BUILD_VARIANT),userdebug) +ccflags-y := -D DEBUG_SUPPORT +endif +obj-y += film_mode.o +film_mode-objs += vof_soft_top.o +film_mode-objs += flm_mod_xx.o +film_mode-objs += film_fw1.o diff --git a/drivers/amlogic/media/deinterlace/film_fw1.c b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c similarity index 85% rename from drivers/amlogic/media/deinterlace/film_fw1.c rename to drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c index a52d80d7866b..6c111681c391 100644 --- a/drivers/amlogic/media/deinterlace/film_fw1.c +++ b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/media/deinterlace/film_fw1.c + * drivers/amlogic/media/deinterlace/film_mode_fmw/film_fw1.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -19,6 +19,8 @@ #include #include "film_vof_soft.h" + +static int DIweavedetec(struct sFlmSftPar *pPar, int nDif01); /* Software parameters (registers) */ UINT8 FlmVOFSftInt(struct sFlmSftPar *pPar) { @@ -38,7 +40,7 @@ UINT8 FlmVOFSftInt(struct sFlmSftPar *pPar) pPar->sF32Dif01A1 = 65; pPar->sF32Dif01T1 = 128; - pPar->sF32Dif01A2 = 65; + pPar->sF32Dif01A2 = 60; pPar->sF32Dif01T2 = 128; pPar->rCmbRwMinCt0 = 8; /* for film 3-2 */ @@ -52,11 +54,23 @@ UINT8 FlmVOFSftInt(struct sFlmSftPar *pPar) */ pPar->mNxtDlySft = 1; - pPar->sF32Dif02M0 = 4096; /* mpeg-4096, cvbs-8192 */ + pPar->cmb22_nocmb_num = 30; + pPar->flm22_en = 1; + pPar->flm32_en = 1; + pPar->flm22_flag = 1; + pPar->flm2224_flag = 1; + pPar->flm22_comlev = 22; + pPar->flm22_comlev1 = 8; + pPar->flm22_comlev2 = 22; + pPar->flm22_comnum = 115; + pPar->flm22_comth = 15; + pPar->flm22_dif01_avgth = 55; + pPar->dif01rate = 20; + pPar->flag_di01th = 0; + pPar->numthd = 60; + pPar->sF32Dif02M0 = 4096;/* mpeg-4096, cvbs-8192 */ pPar->sF32Dif02M1 = 4096; - field_count = 0; - return 0; } @@ -103,6 +117,10 @@ int flm32_mim_frms = 6; module_param(flm32_mim_frms, int, 0644); MODULE_PARM_DESC(flm32_mim_frms, "flm32_mim_frms"); +int flm22_dif01a_flag = 1; +module_param(flm22_dif01a_flag, int, 0644); +MODULE_PARM_DESC(flm22_dif01a_flag, "flm22_dif01a_flag"); + int flm22_mim_frms = 60; module_param(flm22_mim_frms, int, 0644); MODULE_PARM_DESC(flm22_mim_frms, "flm22_mim_frms"); @@ -135,6 +153,10 @@ int flm32_chk3_rtn = 16; module_param(flm32_chk3_rtn, int, 0644); MODULE_PARM_DESC(flm32_chk3_rtn, "flm32_chk3_rtn"); +int flm32_dif02_ratio = 8; +module_param(flm32_dif02_ratio, int, 0644); +MODULE_PARM_DESC(flm32_dif02_ratio, "flm32_dif02_ratio"); + int flm22_chk20_sml = 6; module_param(flm22_chk20_sml, int, 0644); MODULE_PARM_DESC(flm22_chk20_sml, "flm22_chk20_sml"); @@ -200,15 +222,24 @@ int flm22_minus_cntmax = 2; module_param(flm22_minus_cntmax, int, 0644); MODULE_PARM_DESC(flm22_minus_cntmax, "flm22_minus_cntmax"); +static int flagdif01chk = 1; +module_param(flagdif01chk, int, 0644); +MODULE_PARM_DESC(flagdif01chk, "flagdif01chk"); + +static int dif01_ratio = 10; +module_param(dif01_ratio, int, 0644); +MODULE_PARM_DESC(dif01_ratio, "dif01_ratio"); + +int comsum; int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, - unsigned short *rPstCYWnd1, unsigned short *rPstCYWnd2, - unsigned short *rPstCYWnd3, unsigned short *rPstCYWnd4, - UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, - UINT32 *rROFldDif01, UINT32 *rROFrmDif02, UINT32 *rROCmbInf, - UINT32 glb_frame_mot_num, UINT32 glb_field_mot_num, int *tTCNm, - struct sFlmSftPar *pPar, int nROW, int nCOL, - unsigned int *frame_diff_avg) + unsigned short *rPstCYWnd1, unsigned short *rPstCYWnd2, + unsigned short *rPstCYWnd3, unsigned short *rPstCYWnd4, + UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, + UINT8 *dif01flag, UINT32 *rROFldDif01, UINT32 *rROFrmDif02, + UINT32 *rROCmbInf, UINT32 glb_frame_mot_num, + UINT32 glb_field_mot_num, unsigned int *combing_row_num, + unsigned int *frame_diff_avg, struct sFlmSftPar *pPar, bool reverse) { static UINT32 DIF01[HISDIFNUM]; /* Last one is global */ static UINT32 DIF02[HISDIFNUM]; /* Last one is global */ @@ -218,34 +249,48 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, static struct sFlmDatSt pRDat; static int pre22lvl; static UINT32 pre_fld_motnum; + static int modpre; + static int num; + static int num32; + static int flag_pre; + static int comsumpre; + static int nS1pre; + int dif01th = 0; int nDIF01[HISDIFNUM]; int nDIF02[HISDIFNUM]; /* UINT32 nCb32=0; */ unsigned int ntmp = 0; unsigned int flm22_mim_numb = 0; - /* int nRCMB[ROWCMBNUM]; */ int mDly = pPar->mPstDlyPre; int mNDly = pPar->mNxtDlySft; + int flm22 = pPar->flm22_en; + int flm32 = pPar->flm32_en; + int flm22_flag = pPar->flm22_flag; + int flm2224_flag = pPar->flm2224_flag; + int flm22_comth = pPar->flm22_comth; + int comdif = 0; + int dif01avg = 0; int nT0 = 0; int nT1 = 0; int nS0 = 0; int nS1 = 0; int nMod = 0; + int difflag = 0; /* difference */ pRDat.rROFrmDif02 = rROFrmDif02; /* size of the image */ - pRDat.iHeight = nROW; /* field height */ - pRDat.iWidth = nCOL; + pRDat.iHeight = pPar->height; /* field height */ + pRDat.iWidth = pPar->width; prt_flg = 0; debug_str[0] = '\0'; /* Initialization */ - if (field_count < 3) { + if (pPar->field_count < 3) { for (nT1 = 0; nT1 < HISDIFNUM; nT1++) { DIF01[nT1] = 0xffffffff; DIF02[nT1] = 0xffffffff; @@ -296,7 +341,7 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, if (pr_pd) { sprintf(debug_str, "\nField#%5d: [%4dx%4d]\n", - field_count, nROW, nCOL); + pPar->field_count, pPar->height, pPar->width); sprintf(debug_str + strlen(debug_str), "diff counter: %4d %4d\n", glb_field_mot_num, glb_frame_mot_num); @@ -389,7 +434,8 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, */ *rFlmPstMod = 2; /* param: at least 5 field+5 */ - if (pRDat.mNum32[HISDETNUM - 1] < flm32_mim_frms) { + if (pRDat.mNum32[HISDETNUM - 1] < flm32_mim_frms || + flm32 == 0) { *rFlmSltPre = 0; *rFlmPstMod = 0; } @@ -403,7 +449,7 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, *rFlmPstMod = 1; ntmp = (glb_frame_mot_num + glb_field_mot_num) / - (nCOL + 1); + (pPar->width + 1); if (flm22_mim_frms > ntmp + flm22_mim_smfrms) flm22_mim_numb = flm22_mim_frms - ntmp; else @@ -426,6 +472,7 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, /*ntmp = DIF01[HISDIFNUM-1] / (glb_field_mot_num + 1);*/ /* min / max */ ntmp = DIF01[HISDIFNUM-1] / (pre_fld_motnum + 1); + dif01avg = ntmp; if (pr_pd) pr_info("diff01-avg=%4d\n", ntmp); @@ -441,10 +488,38 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, else pRDat.mNum22[HISDETNUM - 1] = 0; } + comdif = (comsumpre < comsum) ? (comsum - comsumpre) + : (comsumpre - comsum); + if (pr_pd) + pr_info("comsum=%d, comsumpre=%d, flev=%d\n", + comsum, comsumpre, nS1); + if ((comsum < 200) && (comsum > pPar->flm22_comnum) + && (comdif < flm22_comth) && + flm22_dif01a_flag) { + if (nS1 < pPar->flm22_comlev) + nS1 = 0; + else + nS1 = nS1 - pPar->flm22_comlev; + } else if (dif01avg > pPar->flm22_dif01_avgth) { + if (nS1 < pPar->flm22_comlev) + nS1 = 0; + else + nS1 = nS1 - pPar->flm22_comlev; + } + if (pr_pd) + pr_info("flev=%d\n", nS1); + comsumpre = comsum; + } else if (nS1pre < 100) { + if (nS1 < pPar->flm22_comlev2) + nS1 = 0; + else + nS1 = nS1 - pPar->flm22_comlev2; } + nS1pre = nS1; /* param: at least 60 field+4 */ - if (pRDat.mNum22[HISDETNUM - 1] < flm22_mim_numb) { + if (pRDat.mNum22[HISDETNUM - 1] < flm22_mim_numb || + flm22 == 0) { *rFlmSltPre = 0; *rFlmPstMod = 0; if (pr_pd) @@ -461,19 +536,63 @@ int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, } pre_fld_motnum = glb_field_mot_num; - VOFSftTop(rFlmPstGCm, rFlmSltPre, rFlmPstMod, + comsum = VOFSftTop(rFlmPstGCm, rFlmSltPre, rFlmPstMod, rPstCYWnd0, rPstCYWnd1, rPstCYWnd2, rPstCYWnd3, - nMod, rROCmbInf, &pRDat, pPar, nROW, nCOL); + nMod, rROCmbInf, &pRDat, pPar, pPar->height, + pPar->width, reverse); + if (*rFlmPstMod == 1 && *rFlmPstGCm && flm22_flag) + *rFlmPstMod = 0; nT1 = pRDat.pLvlXx[HISDETNUM - 1 - mDly]; if ((*rFlmPstMod == 0) && (nT1 > flmxx_maybe_num) - && (nS0 != 6) && (pRDat.pMod22[HISDETNUM - 1 - mDly] != 2)) { + && (nS0 != 6) && + (pRDat.pMod22[HISDETNUM - 1 - mDly] != 2 || flm2224_flag)) { *rFlmSltPre = pRDat.pFlgXx[HISDETNUM - 1 - mDly]; *rFlmPstMod = 4 + pRDat.pModXx[HISDETNUM - 1 - mDly]; nS1 = pRDat.pLvlXx[HISDETNUM - 1 - mDly]; } + *dif01flag = 2; + if (*rFlmPstMod == 0) + *dif01flag = DIweavedetec(pPar, rROFldDif01[0]); + if (num32 > 0 && *rFlmPstMod != 2) + num32 = num32-1; + if (pRDat.pFlg32[HISDETNUM - 1 - mDly] == 3) { + if (DIF01[HISDIFNUM - 2] > DIF01[HISDIFNUM - 1]) + num32 = num32 + 1; + else if (num32 > 0) + num32 = num32 - 1; + } + if (modpre != *rFlmPstMod && modpre != 0 && *rFlmPstMod != 0 && + num32 == 0) { + flag_pre = 1; + num = 0; + } else { + if (modpre == 0 || *rFlmPstMod == 0) + num = 0; + else if (num <= 255) + num = num + 1; + } + + if (num > 5 || num32 > 0) + flag_pre = 0; + + if (DIF01[HISDIFNUM - 2] < DIF01[HISDIFNUM - 1]) + difflag = 1; + else + difflag = 0; + + dif01th = (DIF01[HISDIFNUM - 2] + DIF01[HISDIFNUM - 1]) / dif01_ratio; + + if (abs(DIF01[HISDIFNUM - 2] - DIF01[HISDIFNUM - 1]) > dif01th && + flag_pre && flagdif01chk) + *rFlmSltPre = difflag; + modpre = *rFlmPstMod; + + *combing_row_num = pRDat.TCNm[HISCMBNUM - 1]; + pPar->field_count++; + if (pPar->field_count == 0x7fffffff) + pPar->field_count = 3; - *tTCNm = pRDat.TCNm[HISCMBNUM - 1]; return nS1; } @@ -647,9 +766,8 @@ int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, if (nMn <= (1 << flm32_f2fdif_min0)) { nSTP = nT2; } else { - nSTP = - 16 * (nDif02[HISDIFNUM - 1] - nMn) + (nAV1 - nMn + - sFrmDifLgTDif) / 2; + nSTP = flm32_dif02_ratio * (nDif02[HISDIFNUM - 1] - nMn) + + (nAV1 - nMn + sFrmDifLgTDif) / 2; nSTP = nSTP / (nAV1 - nMn + sFrmDifLgTDif); /* ======================== */ @@ -1036,6 +1154,10 @@ int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02, int sFlm20ftAlpha = pPar->sFlm20ftAlpha; /* 16; // [0~63] */ int sFlm2LgDifThd = pPar->sFlm2LgDifThd; /* 4096; */ int sFlm2LgFlgThd = pPar->sFlm2LgFlgThd; /* 8; */ + int flm22_flag = pPar->flm22_flag; + int flm22_comlev = pPar->flm22_comlev; + int flm22_comlev1 = pPar->flm22_comlev1; + int flm22_comnum = pPar->flm22_comnum; int cFlg = pFlg[HISDETNUM - 1]; int rFlg[4] = { 2, 3, 4, 1 }; @@ -1062,6 +1184,7 @@ int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02, int nOfst = 0; int tMgn = 0; int BtMn = 0; + static int num22; int FdTg[6]; @@ -1435,6 +1558,33 @@ int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02, nFlm22Lvl -= nT1; } + if (flm22_flag) { + if (pFlg[HISDETNUM-1] == 3 + || pFlg[HISDETNUM-1] == 1) { + if (comsum > flm22_comnum) { + if (num22 < 30) + num22 = num22 + 1; + else + nFlm22Lvl = nFlm22Lvl + flm22_comlev; + } else { + num22 = 0; + nFlm22Lvl = nFlm22Lvl - flm22_comlev; + } + /* if(prt_flg) + * pr_info("nFlm22Lvl = %d, comsum=%d,num22=%d," + * "flm22_comnum=%d,flm22_flag=%d\n", + * nFlm22Lvl,comsum,num22,flm22_comnum,flm22_flag); + */ + } + if (nFlgCk20 < flm22_chk20_sml) + nFlm22Lvl = nFlm22Lvl + flm22_comlev1 - nFlgCk20; + if (nFlgCk21 < flm22_chk21_sml) + nFlm22Lvl = nFlm22Lvl + flm22_comlev1 - nFlgCk20; + if (prt_flg) { + pr_info("nFlm22Lvl=%d, nFlgCk20=%d, nFlgCk21=%d\n", + nFlm22Lvl, nFlgCk20, nFlgCk21); + } + } /* for sony-mp3 */ nFlm22Lvl -= nFlgChk5; @@ -1454,3 +1604,39 @@ int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02, return nFlm22Lvl; } +static int DIweavedetec(struct sFlmSftPar *pPar, int nDif01) +{ + int dif01th = 0; + int dif01rate = pPar->dif01rate; + int flag_di01th = pPar->flag_di01th; + int numthd = pPar->numthd; + static int numdif; + static int predifflag; + static int predif01; + static int difflag; + + dif01th = (predif01+nDif01)/dif01rate; + if (abs(predif01 - nDif01) < dif01th && flag_di01th) + difflag = 2; + else { + if (predif01 < nDif01) + difflag = 1; + else + difflag = 0; + if (difflag^predifflag) { + if (numdif > 255) + numdif = numdif; + else + numdif = numdif + 1; + predifflag = difflag; + } else if (numdif > numthd) { + numdif = 0; + difflag = difflag^1; + predifflag = difflag; + } else + difflag = 2; + } + predif01 = nDif01; + return difflag; +} + diff --git a/drivers/amlogic/media/deinterlace/film_mode_fmw/film_vof_soft.h b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_vof_soft.h new file mode 100644 index 000000000000..b659881aed0e --- /dev/null +++ b/drivers/amlogic/media/deinterlace/film_mode_fmw/film_vof_soft.h @@ -0,0 +1,208 @@ +/* + * drivers/amlogic/media/deinterlace/film_mode_fmw/film_vof_soft.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef _FLMVOFSFT_H_ +#define _FLMVOFSFT_H_ +#include +/* Film Detection and VOF detection Software implementation */ +/* Designer: Xin.Hu@amlogic.com */ +/* Date: 12/06/13 */ + +/* Difference Windows Number (Last one is the global/total dif) */ +/* 5wind+global */ +/* #define DIFWNDNUM 6 */ +#define HISDIFNUM 10 +#define HISCMBNUM 10 +/* detection history information */ +#define HISDETNUM 6 +/* The number of VOF window */ +#define VOFWNDNUM 4 + +#define PDXX_PT_NUM 7 + +/* 288Row, 1bit/row -> (288/32)=9 */ +#define ROWCMBNUM 288 +#define ROWCMBLEN 9 + +#ifndef UINT32 +#define UINT32 unsigned int +#endif + +#ifndef UINT8 +#define UINT8 unsigned char +#endif + +#ifndef UShort +#define UShort unsigned short +#endif + +extern uint pr_pd; +extern bool prt_flg; +extern char debug_str[]; + +/* Software: Film Detection and VOF parameters */ +struct sFlmDatSt { + UINT8 pFlg32[HISDETNUM]; /* history information */ + UINT8 pMod32[HISDETNUM]; + UINT8 mNum32[HISDETNUM]; + + UINT8 pFld32[HISDETNUM]; + UINT8 pFrm32[HISDETNUM]; + UINT8 pFrm32t[HISDETNUM]; /* history information: spacial processing */ + + UINT8 pFlg22[HISDETNUM]; + UINT8 pMod22[HISDETNUM]; + UINT8 mNum22[HISDETNUM]; + + UINT8 pStp22[HISDETNUM]; + UINT8 pSmp22[HISDETNUM]; + + UINT8 pModXx[HISDETNUM]; /* mode */ + UINT8 pFlgXx[HISDETNUM]; /* pre-1, nxt-0 */ + UINT8 pLvlXx[HISDETNUM]; /* mode level */ + + int TCNm[HISCMBNUM];/* history: the number of combing-rows */ + + UINT32 *rROFrmDif02; + + /* size of the image */ + int iHeight; + int iWidth; +}; + +/* Software parameters */ +struct sFlmSftPar { + /* software */ + int sFrmDifAvgRat; /* 16; //0~32 */ + /* 4096; //The Large Decision should be: (large>average+LgDifThrd) */ + int sFrmDifLgTDif; + int sF32StpWgt01; /* 15; */ + int sF32StpWgt02; /* 15; */ + int sF32DifLgRat; /* 16; //Dif>Rat*Min --> Larger */ + + int sFlm2MinAlpha; /* = 32; // [0~63] */ + int sFlm2MinBelta; /* = 32; // [0~63] */ + int sFlm20ftAlpha; /* = 16; // [0~63] */ + int sFlm2LgDifThd; /* = 4096; // [0~63] %LgDifThrd */ + int sFlm2LgFlgThd; /* = 8; */ + + int sF32Dif01A1; /* 65; */ + int sF32Dif01T1; /* 128; */ + int sF32Dif01A2; /* 65; */ + int sF32Dif01T2; /* 128; */ + + int rCmbRwMinCt0; /* 8; //for film 3-2 */ + int rCmbRwMinCt1; /* =7; //for film 2-2 */ + + UINT8 sFlm32NCmb; /* absolute no combing for film 32 */ + + /* pre-processing (t-0), post-processing f(t-mPstDlyPre); // No RTL */ + int mPstDlyPre; + /* pre-processing (t-0), pre-processing f(t+mNxtDlySft); default=1 */ + int mNxtDlySft; + int cmb22_nocmb_num; + int flm22_en; + int flm32_en; + int flm22_flag; + int flm2224_flag; + int flm22_comlev; + int flm22_comlev1; + int flm22_comlev2; + int flm22_comnum; + int flm22_comth; + int flm22_dif01_avgth; + int dif01rate; + int flag_di01th; + int numthd; + + UINT32 sF32Dif02M0; /* mpeg-4096, cvbs-8192 */ + UINT32 sF32Dif02M1; /* mpeg-4096, cvbs-8192 */ + unsigned int field_count; + unsigned short width; + unsigned short height; +}; + +struct FlmModReg_t { + UINT32 rROFrmDif02[6]; /* Read only */ + UINT32 rROFldDif01[6]; /* Read only */ + UINT32 rROCmbInf[9];/* Inf[0]-[31:0], First-[31], Lst-[0] (Only 0/1) */ +}; + +struct FlmDectRes { + UINT8 rCmb32Spcl; + UINT8 rFlmPstGCm; + UINT8 rFlmSltPre; + UINT8 rFlmPstMod; + UINT8 dif01flag; + UShort rPstCYWnds[5][3]; + UShort rF22Flag; +}; + +UINT8 FlmVOFSftInt(struct sFlmSftPar *pPar); +/* Get 1-Row combing information, 1bit */ +/* iHSCMB[9]; 9x32=288 */ +UINT8 Get1RCmb(UINT32 *iHSCMB, UINT32 iRow); + +int FlmModsDet(struct sFlmDatSt *pRDat, int nDif01, int nDif02); + +/* */ +int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, + unsigned short *rPstCYWnd1, unsigned short *rPstCYWnd2, + unsigned short *rPstCYWnd3, unsigned short *rPstCYWnd4, + UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, + UINT8 *dif01flag, UINT32 *rROFldDif01, UINT32 *rROFrmDif02, + UINT32 *rROCmbInf, UINT32 glb_frame_mot_num, + UINT32 glb_field_mot_num, unsigned int *cmb_row_num, + unsigned int *frame_diff_avg, struct sFlmSftPar *pPar, bool reverse); + +/* length of pFlm01/nDif01: [0:5]; */ +/* iDx: index of minimum dif02 ([0:5] */ +int Cal32Flm01(UINT8 *pFlm01, int *nDif01, int iDx, struct sFlmSftPar *pPar); + +/* Film Detection Software implementation */ +/* nDif01: Fild Difference */ +/* nDif02: Frame Difference */ +/* WND: The index of Window */ +int FlmDetSft(struct sFlmDatSt *pRDat, int *nDif01, int *nDif02, int WND, + struct sFlmSftPar *pPar); + +int VOFDetSub1(int *PREWV, int *nCNum, int nMod, UINT32 *nRCmb, int nROW, + struct sFlmSftPar *pPar); + +/* Video on Film Detection Software implementaion */ +int VOFDetSft(int *VOFWnd, int *nCNum, int *nGCmb, + UINT32 HSCMB[HISCMBNUM][ROWCMBLEN], int nMod, UINT8 *PREWV, + int nROW, struct sFlmSftPar *pPar); + +/* */ +int Flm32DetSft(struct sFlmDatSt *pRDat, int *nDif02, int *nDif01, + struct sFlmSftPar *pPar); + +/* Film2-2 Detection */ +int Flm22DetSft(struct sFlmDatSt *pRDat, int *nDif02, + int *nDif01, struct sFlmSftPar *pPar); + +/* length: [0:5] */ +/* MIX: [1~5] */ +int Flm32DetSub1(struct sFlmDatSt *pRDat, UINT8 *nFlg12, UINT8 *pFlm02t, + UINT8 *nFlg01, UINT8 *nFlg02, UINT8 MIX); +int VOFSftTop(UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, + UShort *rPstCYWnd0, UShort *rPstCYWnd1, UShort *rPstCYWnd2, + UShort *rPstCYWnd3, int nMod, UINT32 *rROCmbInf, + struct sFlmDatSt *pRDat, struct sFlmSftPar *pPar, + int nROW, int nCOL, bool reverse); +#endif diff --git a/drivers/amlogic/media/deinterlace/flm_mod_xx.c b/drivers/amlogic/media/deinterlace/film_mode_fmw/flm_mod_xx.c similarity index 99% rename from drivers/amlogic/media/deinterlace/flm_mod_xx.c rename to drivers/amlogic/media/deinterlace/film_mode_fmw/flm_mod_xx.c index db09e1b259bd..49d97a4ee1eb 100644 --- a/drivers/amlogic/media/deinterlace/flm_mod_xx.c +++ b/drivers/amlogic/media/deinterlace/film_mode_fmw/flm_mod_xx.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/media/deinterlace/flm_mod_xx.c + * drivers/amlogic/media/deinterlace/film_mode_fmw/flm_mod_xx.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * diff --git a/drivers/amlogic/media/deinterlace/vof_soft_top.c b/drivers/amlogic/media/deinterlace/film_mode_fmw/vof_soft_top.c similarity index 90% rename from drivers/amlogic/media/deinterlace/vof_soft_top.c rename to drivers/amlogic/media/deinterlace/film_mode_fmw/vof_soft_top.c index a448bd6189e0..e464165b48f1 100644 --- a/drivers/amlogic/media/deinterlace/vof_soft_top.c +++ b/drivers/amlogic/media/deinterlace/film_mode_fmw/vof_soft_top.c @@ -1,5 +1,5 @@ /* - * drivers/amlogic/media/deinterlace/vof_soft_top.c + * drivers/amlogic/media/deinterlace/film_mode_fmw/vof_soft_top.c * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -80,7 +80,7 @@ int VOFSftTop(UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, UShort *rPstCYWnd0, UShort *rPstCYWnd1, UShort *rPstCYWnd2, UShort *rPstCYWnd3, int nMod, UINT32 *rROCmbInf, struct sFlmDatSt *pRDat, - struct sFlmSftPar *pPar, int nROW, int nCOL) + struct sFlmSftPar *pPar, int nROW, int nCOL, bool reverse) { /* HSCMB[hist10][9(32bit)] */ static UINT32 HSCMB[HISCMBNUM][ROWCMBLEN]; @@ -92,7 +92,9 @@ int VOFSftTop(UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, static UINT8 NumSmFd; /* counter for same field */ int mDly = pPar->mPstDlyPre; - + int flm22_flag = pPar->flm22_flag; + int cmb22_nocmb_num = pPar->cmb22_nocmb_num; + int cmb32_blw_wnd_rel = cmb32_blw_wnd; /* UINT8 *PREWV = pRDat.pFlg32; or pRDat.pFlg22 */ /* static int TCNm[HISCMBNUM]; history: the number of combing-rows */ int *TCNm = pRDat->TCNm; @@ -125,7 +127,9 @@ int VOFSftTop(UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, pFlgXx = (((pFlgXx >> 1) << 2) | (pRDat->pFlgXx[HISDETNUM - 2] << 1) | (pRDat->pFlgXx[HISDETNUM - 1])); - + /* for 1080i */ + if (nROW > 288) + cmb32_blw_wnd_rel = 70; /* Initialization */ if (BGN == 0) { for (nT0 = 0; nT0 < HISCMBNUM; nT0++) { @@ -225,11 +229,21 @@ int VOFSftTop(UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, nWCmb = 0; nBCmb = 0; for (nT0 = 0; nT0 < nT1; nT0++) { - if (VOFWnd[2 * nT0] > (cmb32_blw_wnd * nROW >> 8)) { - CWND[HISDETNUM - 1][2 * nT0] = - VOFWnd[2 * nT0] - cmb32_wnd_ext; - CWND[HISDETNUM - 1][2 * nT0 + 1] = - VOFWnd[2 * nT0 + 1] + cmb32_wnd_ext; + if (VOFWnd[2*nT0] > (cmb32_blw_wnd_rel * nROW >> 8)) { + CWND[HISDETNUM-1][2*nT0] = + VOFWnd[2*nT0] - cmb32_wnd_ext; + CWND[HISDETNUM-1][2*nT0+1] = + VOFWnd[2*nT0+1] + cmb32_wnd_ext; + if (reverse) { + if (CWND[HISDETNUM-1][2*nT0+1] >= + nROW - 1) + CWND[HISDETNUM-1][2*nT0+1] + = nROW - 1; + CWND[HISDETNUM-1][2*nT0] = nROW - 1 + - CWND[HISDETNUM-1][2*nT0+1]; + CWND[HISDETNUM-1][2*nT0+1] = nROW + - 1 - (VOFWnd[2*nT0] - cmb32_wnd_ext); + } nBCmb = VOFWnd[2*nT0+1]-VOFWnd[2*nT0]+1; @@ -350,13 +364,17 @@ int VOFSftTop(UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, } /* here for vertical moving VOF */ } else if ((pMod22[HISDETNUM-1] == 2) && (pFlg22[HISDETNUM-1] & 0x1)) { - nT2 = ((nROW * cmb22_gcmb_rnum + 8) >> 4); + if (flm22_flag) + nT2 = 288 - cmb22_nocmb_num; + else + nT2 = ((nROW * cmb22_gcmb_rnum + 8) >> 4); if (nCSum > nT2) WGlb[HISDETNUM-1] = 1; /*global combing*/ - + else + WGlb[HISDETNUM-1] = 0; /*global combing*/ if (prt_flg) sprintf(debug_str + strlen(debug_str), - "WGlb22=%d\n", WGlb[HISDETNUM-1]); + "WGlb22=%d\n", WGlb[HISDETNUM-1]); for (nT0 = 0; nT0 < ROWCMBLEN; nT0++) nRCmbAd[nT0] = HSCMB[HISCMBNUM-1][nT0]; @@ -377,7 +395,12 @@ int VOFSftTop(UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, for (nT0 = 0; nT0 < nT1; nT0++) { CWND[HISDETNUM-1][2*nT0] = VOFWnd[2*nT0]; CWND[HISDETNUM-1][2*nT0+1] = VOFWnd[2*nT0+1]; - + if (reverse) { + CWND[HISDETNUM-1][2*nT0] = + nROW - 1 - VOFWnd[2*nT0+1]; + CWND[HISDETNUM-1][2*nT0+1] = + nROW - 1 - VOFWnd[2*nT0]; + } if (prt_flg) sprintf(debug_str + strlen(debug_str), "Wnd22[%d]=[%3d~%3d]\n", @@ -428,7 +451,12 @@ int VOFSftTop(UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, for (nT0 = 0; nT0 < nT1; nT0++) { CWND[HISDETNUM-1][2*nT0] = VOFWnd[2*nT0]; CWND[HISDETNUM-1][2*nT0+1] = VOFWnd[2*nT0+1]; - + if (reverse) { + CWND[HISDETNUM-1][2*nT0] = + nROW - 1 - VOFWnd[2*nT0+1]; + CWND[HISDETNUM-1][2*nT0+1] = + nROW - 1 - VOFWnd[2*nT0]; + } if (prt_flg) sprintf(debug_str + strlen(debug_str), "WndXx[%d]=[%3d~%3d]\n", @@ -553,7 +581,7 @@ int VOFSftTop(UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, pr_info("%s", debug_str); } - return nWCmb; + return nCSum; } /* int *PREWV:5*2 */ @@ -561,10 +589,10 @@ int VOFSftTop(UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, int VOFDetSub1(int *VOFWnd, int *nCNum, int nMod, UINT32 *nRCmb, int nROW, struct sFlmSftPar *pPar) { - int rCmbRwMinCt0 = pPar->rCmbRwMinCt0; /* 8; //for film 3-2 */ - int rCmbRwMinCt1 = pPar->rCmbRwMinCt1; /* =7; //for film 2-2 */ + int rCmbRwMinCt0 = 0; /* 8; //for film 3-2 */ + int rCmbRwMinCt1 = 0; /* =7; //for film 2-2 */ /* int rCmbRwMaxStp=1; //fill in the hole */ - int rCmbRwMinCt = rCmbRwMinCt1; + int rCmbRwMinCt = 0; int nCSUM = 0; /* Combing sum (nCSUM>rCmbRwMinCt0) */ int nMIN = 0; int nT0 = 0; @@ -577,8 +605,16 @@ int VOFDetSub1(int *VOFWnd, int *nCNum, int nMod, UINT32 *nRCmb, int nROW, int pIDx[VOFWNDNUM + 1][2]; /* Maximum-5windows */ int nIDx = 0; + rCmbRwMinCt = rCmbRwMinCt1; if (nMod == 3) rCmbRwMinCt = rCmbRwMinCt0; + if (IS_ERR(pPar)) { + pr_err("%s:%d pPar = 0x%p.\n", + __func__, __LINE__, pPar); + return -1; + } + rCmbRwMinCt0 = pPar->rCmbRwMinCt0; /* 8; //for film 3-2 */ + rCmbRwMinCt1 = pPar->rCmbRwMinCt1; /* =7; //for film 2-2 */ for (nT0 = 0; (nT0 < nROW) && (nIDx <= VOFWNDNUM); nT0++) { fEND = 0; @@ -650,6 +686,7 @@ UINT8 Get1RCmb(UINT32 *iHSCMB, UINT32 iRow) UINT8 nBt = 0; nR1 = ((iRow >> 5) & 0xf);/* iRow/32; 0--8 */ + iHSCMB[nR1] = nR1 > 8 ? 0 : iHSCMB[nR1]; nBt = (iRow & 0x1f);/* iRow%32 */ return (iHSCMB[nR1] >> nBt) & 0x1; } diff --git a/drivers/amlogic/media/deinterlace/film_vof_soft.h b/drivers/amlogic/media/deinterlace/film_vof_soft.h index 9f58ad325c9c..867e86fc3832 100644 --- a/drivers/amlogic/media/deinterlace/film_vof_soft.h +++ b/drivers/amlogic/media/deinterlace/film_vof_soft.h @@ -114,6 +114,20 @@ struct sFlmSftPar { int mPstDlyPre; /* pre-processing (t-0), pre-processing f(t+mNxtDlySft); default=1 */ int mNxtDlySft; + int cmb22_nocmb_num; + int flm22_en; + int flm32_en; + int flm22_flag; + int flm2224_flag; + int flm22_comlev; + int flm22_comlev1; + int flm22_comlev2; + int flm22_comnum; + int flm22_comth; + int flm22_dif01_avgth; + int dif01rate; + int flag_di01th; + int numthd; UINT32 sF32Dif02M0; /* mpeg-4096, cvbs-8192 */ UINT32 sF32Dif02M1; /* mpeg-4096, cvbs-8192 */ @@ -130,6 +144,7 @@ struct FlmDectRes { UINT8 rFlmPstGCm; UINT8 rFlmSltPre; UINT8 rFlmPstMod; + UINT8 dif01flag; UShort rPstCYWnd0[3]; UShort rPstCYWnd1[3]; UShort rPstCYWnd2[3]; @@ -147,13 +162,15 @@ int FlmModsDet(struct sFlmDatSt *pRDat, int nDif01, int nDif02); /* */ -int FlmVOFSftTop(UINT8 *rCmb32Spcl, UShort *rPstCYWnd0, UShort *rPstCYWnd1, - UShort *rPstCYWnd2, UShort *rPstCYWnd3, UShort *rPstCYWnd4, +int FlmVOFSftTop(UINT8 *rCmb32Spcl, unsigned short *rPstCYWnd0, + unsigned short *rPstCYWnd1, unsigned short *rPstCYWnd2, + unsigned short *rPstCYWnd3, unsigned short *rPstCYWnd4, UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, - UINT32 *rROFldDif01, UINT32 *rROFrmDif02, UINT32 *rROCmbInf, - UINT32 glb_frame_mot_num, UINT32 glb_field_mot_num, int *tTCNm, + UINT8 *dif01flag, UINT32 *rROFldDif01, UINT32 *rROFrmDif02, + UINT32 *rROCmbInf, UINT32 glb_frame_mot_num, + UINT32 glb_field_mot_num, int *tTCNm, struct sFlmSftPar *pPar, int nROW, int nCOL, - unsigned int *frame_diff_avg); + unsigned int *frame_diff_avg, bool reverse); /* length of pFlm01/nDif01: [0:5]; */ /* iDx: index of minimum dif02 ([0:5] */ @@ -191,7 +208,7 @@ int VOFSftTop(UINT8 *rFlmPstGCm, UINT8 *rFlmSltPre, UINT8 *rFlmPstMod, UShort *rPstCYWnd0, UShort *rPstCYWnd1, UShort *rPstCYWnd2, UShort *rPstCYWnd3, int nMod, UINT32 *rROCmbInf, struct sFlmDatSt *pRDat, struct sFlmSftPar *pPar, - int nROW, int nCOL); + int nROW, int nCOL, bool reverse); extern UINT32 field_count; diff --git a/drivers/amlogic/media/deinterlace/nr.c b/drivers/amlogic/media/deinterlace/nr.c deleted file mode 100644 index b434283c9be4..000000000000 --- a/drivers/amlogic/media/deinterlace/nr.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - * drivers/amlogic/media/deinterlace/nr.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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 -#include -#include -#include -#include -#include "register.h" -#include "nr.h" -#include "deinterlace.h" - -static DNR_PRM_t dnr_param; -static DNR_PRM_t *pDnrPrm = &dnr_param; -static bool dnr_pr; -module_param(dnr_pr, bool, 0644); -MODULE_PARM_DESC(dnr_pr, "/n print dnr debug information /n"); - -bool dnr_dm_en;/*gxtvbb can't work normal,must set to 0*/ -module_param(dnr_dm_en, bool, 0644); -MODULE_PARM_DESC(dnr_dm_en, "/n dnr dm enable debug /n"); - -bool dnr_reg_update = 1;/*gxtvbb can't work normal,must set to 0*/ -module_param(dnr_reg_update, bool, 0644); -MODULE_PARM_DESC(dnr_reg_update, "/n dnr dm enable debug /n"); - -static unsigned int dnr_stat_coef = 3;/*gxtvbb default is 3*/ -module_param(dnr_stat_coef, uint, 0644); -MODULE_PARM_DESC(dnr_stat_coef, "/n dnr stat coef /n"); - -static int dnr_prm_init(DNR_PRM_t *pPrm) -{ - pPrm->prm_sw_gbs_ctrl = 0; - /* 0: update gbs, 1: update hoffst & gbs, - * 2: update voffst & gbs, 3: update all (hoffst & voffst & gbs). - */ - - pPrm->prm_gbs_vldcntthd = 4; - pPrm->prm_gbs_cnt_min = 32; - pPrm->prm_gbs_ratcalcmod = 1;/* 0: use LR, 1: use Dif */ - pPrm->prm_gbs_ratthd[0] = 40; - pPrm->prm_gbs_ratthd[1] = 80; - pPrm->prm_gbs_ratthd[2] = 120; - pPrm->prm_gbs_difthd[0] = 25; - pPrm->prm_gbs_difthd[1] = 75; - pPrm->prm_gbs_difthd[2] = 125; - pPrm->prm_gbs_bsdifthd = 1; - pPrm->prm_gbs_calcmod = 1; /* 0:dif0, 1:dif1, 2: dif2 */ - - pPrm->sw_gbs = 0; - pPrm->sw_gbs_vld_flg = 0; - pPrm->sw_gbs_vld_cnt = 0; - - pPrm->prm_hbof_minthd = 32; - pPrm->prm_hbof_ratthd0 = 150; - pPrm->prm_hbof_ratthd1 = 150; - pPrm->prm_hbof_vldcntthd = 4; - pPrm->sw_hbof = 0; - pPrm->sw_hbof_vld_flg = 0; - pPrm->sw_hbof_vld_cnt = 0; - - pPrm->prm_vbof_minthd = 32; - pPrm->prm_vbof_ratthd0 = 150; - pPrm->prm_vbof_ratthd1 = 120; - pPrm->prm_vbof_vldcntthd = 4; - pPrm->sw_vbof = 0; - pPrm->sw_vbof_vld_flg = 0; - pPrm->sw_vbof_vld_cnt = 0; - - return 0; -} -int global_bs_calc_sw(int *pGbsVldCnt, - int *pGbsVldFlg, - int *pGbs, - int nGbsStatLR, - int nGbsStatLL, - int nGbsStatRR, - int nGbsStatDif, - int nGbsStatCnt, - int prm_gbs_vldcntthd, /* prm below */ - int prm_gbs_cnt_min, - int prm_gbs_ratcalcmod, - int prm_gbs_ratthd[3], - int prm_gbs_difthd[3], - int prm_gbs_bsdifthd, - int prm_gbs_calcmod) -{ - int nMax, nMin; - int nDif0, nDif1, nDif2; - int nDif, nRat; - int nCurGbs; - - nMax = max(max(nGbsStatLR, nGbsStatLL), nGbsStatRR); - nMin = min(min(nGbsStatLR, nGbsStatLL), nGbsStatRR); - - nDif0 = nMax == 0 ? 0 : ((nMax - nMin) << 9)/nMax; - nDif0 = min(511, nDif0); - - nDif1 = nGbsStatLR == 0 ? 0 : - (abs(nGbsStatLR - (nGbsStatLL + nGbsStatRR)/2) << 9)/nGbsStatLR; - nDif1 = min(511, nDif1); - - nDif2 = nGbsStatLR == 0 ? 0 : - (abs(nGbsStatLR - max(nGbsStatLL, nGbsStatRR)) << 9)/nGbsStatLR; - nDif2 = min(511, nDif2); - - if (prm_gbs_ratcalcmod == 0) - nRat = (nGbsStatLR << 4) / max(prm_gbs_cnt_min, nGbsStatCnt); - else - nRat = (nGbsStatDif << 4) / max(prm_gbs_cnt_min, nGbsStatCnt); - - nDif = (prm_gbs_calcmod == 0) ? nDif0 : -(prm_gbs_calcmod == 1 ? nDif1 : nDif2); - - if (nGbsStatLR < max(nGbsStatLL, nGbsStatRR)) { - if (nGbsStatCnt <= prm_gbs_cnt_min || nRat <= prm_gbs_ratthd[0]) - nCurGbs = 0; - else if (nRat <= prm_gbs_ratthd[1]) - nCurGbs = 1; - else if (nRat <= prm_gbs_ratthd[2]) - nCurGbs = 2; - else - nCurGbs = 3; - } else { - if (nGbsStatCnt <= prm_gbs_cnt_min || nDif <= prm_gbs_difthd[0]) - nCurGbs = 0; - else if (nDif <= prm_gbs_difthd[1]) - nCurGbs = 1; - else if (nDif <= prm_gbs_difthd[2]) - nCurGbs = 2; - else - nCurGbs = 3; - } - - /* */ - if ((nCurGbs != 0 && 0 == *pGbs) || -(nCurGbs != 0 && abs(nCurGbs - *pGbs) <= prm_gbs_bsdifthd)) - (*pGbsVldCnt)++; - else - *pGbsVldCnt = 0; - - if (*pGbsVldCnt >= prm_gbs_vldcntthd) - *pGbsVldFlg = 1; - else - *pGbsVldFlg = 0; - - *pGbs = nCurGbs; - - /* print debug info. */ - /* printk("GBS info at Field: LR = %6d, LL = %6d, RR = %6d.\n", - * nGbsStatLR, nGbsStatLL, nGbsStatRR; - */ - - return 0; -} - -#ifdef DNR_HV_SHIFT -int hor_blk_ofst_calc_sw(int *pHbOfVldCnt, - int *pHbOfVldFlg, - int *pHbOfst, - int nHbOfStatCnt[32], - int nXst, - int nXed, - int prm_hbof_minthd, - int prm_hbof_ratthd0, - int prm_hbof_ratthd1, - int prm_hbof_vldcntthd, - int nRow, - int nCol) -{ - int i = 0; - - int nCurHbOfst = 0; - int nRat0 = 0, nRat1 = 0; - - int nMax1 = 0; - int nMax2 = 0; - int nMaxIdx = 0; - - /* get 2 maximum, move to RTL part */ - nMax1 = nMax2 = 0; - for (i = 0; i < 8; i++) { - if (nHbOfStatCnt[i] > nMax1) { - nMax2 = nMax1; - nMax1 = nHbOfStatCnt[i]; - nMaxIdx = i; - } else if (nHbOfStatCnt[i] > nMax2) { - nMax2 = nHbOfStatCnt[i]; - } - } /* i */ - - /* decide if offset valid */ - nCurHbOfst = -1; - nRat0 = 256*nMax1/((nXed - nXst)/8)/nRow; - nRat1 = 128*nMax1/max(nMax2, prm_hbof_minthd); - if (nRat0 >= prm_hbof_ratthd0 && nRat1 >= prm_hbof_ratthd1) - nCurHbOfst = (nMaxIdx+1)%8; - - if (nCurHbOfst == *pHbOfst) - (*pHbOfVldCnt)++; - else - *pHbOfVldCnt = 0; - - if (*pHbOfVldCnt >= prm_hbof_vldcntthd) - *pHbOfVldFlg = 1; - else - *pHbOfVldFlg = 0; - - *pHbOfst = (nCurHbOfst == -1) ? 0 : nCurHbOfst; - - /* print for debug - * printk("Hoff info at Field: "); - * for ( i = 0; i < 32; i++ ) { - * printk("%5d, ", nHbOfStatCnt[i]); - * } - */ - if (dnr_pr) { - pr_dbg("Max1 = %5d, Max2 = %5d, MaxIdx = %5d, Rat0 = %5d,Rat1 = %5d.\n", - nMax1, nMax2, nMaxIdx, nRat0, nRat1); - pr_dbg("CurHbOfst = %5d, HbOfVldFlg = %d, HbOfVldCnt = %d.\n", - nCurHbOfst, *pHbOfVldFlg, *pHbOfVldCnt); - } - - return 0; -} -int ver_blk_ofst_calc_sw(int *pVbOfVldCnt, - int *pVbOfVldFlg, - int *pVbOfst, - int nVbOfStatCnt[32], - int nYst, - int nYed, - int prm_vbof_minthd, - int prm_vbof_ratthd0, - int prm_vbof_ratthd1, - int prm_vbof_vldcntthd, - int nRow, - int nCol) -{ - int i = 0; - - int nCurVbOfst = 0; - int nRat0 = 0, nRat1 = 0; - - int nMax1 = 0; - int nMax2 = 0; - int nMaxIdx = 0; - - /* get 2 maximum, move to RTL part */ - nMax1 = nMax2 = 0; - for (i = 0; i < 8; i++) { - if (nVbOfStatCnt[i] > nMax1) { - nMax2 = nMax1; - nMax1 = nVbOfStatCnt[i]; - nMaxIdx = i; - } - else if (nVbOfStatCnt[i] > nMax2) { - nMax2 = nVbOfStatCnt[i]; - } - } - - /* decide if offset valid */ - nCurVbOfst = -1; - nRat0 = 256*nMax1/((nYed - nYst)/8)/nCol; - nRat1 = 128*nMax1/max(nMax2, prm_vbof_minthd); - if (nRat0 >= prm_vbof_ratthd0 && nRat1 >= prm_vbof_ratthd1) - nCurVbOfst = (nMaxIdx+1)%8; - - if (nCurVbOfst == *pVbOfst) - (*pVbOfVldCnt)++; - else - *pVbOfVldCnt = 0; - - if (*pVbOfVldCnt >= prm_vbof_vldcntthd) - *pVbOfVldFlg = 1; - else - *pVbOfVldFlg = 0; - - *pVbOfst = (nCurVbOfst == -1) ? 0 : nCurVbOfst; - - /* print for debug - * printk("Voff info at Field: "); - * for ( i = 0; i < 32; i++ ) { - * printk("%5d, ", nVbOfStatCnt[i]); - * }//i - * //printk("Max1 = %5d, Max2 = %5d, MaxIdx = %5d, Rat0 = %5d, - * Rat1 = %5d, CurVbOfst = %5d, VbOfVldFlg = %d, VbOfVldCnt = %d.\n" - * nMax1, nMax2, nMaxIdx, nRat0, nRat1, nCurVbOfst, *pVbOfVldFlg, - * *pVbOfVldCnt); - */ - return 0; -} -#endif - -void run_dnr_in_irq(unsigned short nCol, unsigned short nRow) -{ - static int ro_gbs_stat_lr = 0, ro_gbs_stat_ll = 0, ro_gbs_stat_rr = 0, - ro_gbs_stat_dif = 0, ro_gbs_stat_cnt = 0; - /* int reg_dnr_stat_xst=0,reg_dnr_stat_xed=0, - * reg_dnr_stat_yst=0,reg_dnr_stat_yed=0; - */ -#ifdef DNR_HV_SHIFT - int ro_hbof_stat_cnt[32], ro_vbof_stat_cnt[32], i = 0; -#endif - if (dnr_reg_update == 0) - return; - - DI_Wr(DNR_CTRL, 0x1df00); - DI_Wr(DNR_DM_CTRL, Rd(DNR_DM_CTRL)|(1 << 11)); - /* dm for sd, hd will slower */ - if (nCol >= 1920) - DI_Wr_reg_bits(DNR_DM_CTRL, 0, 9, 1); - else - DI_Wr_reg_bits(DNR_DM_CTRL, dnr_dm_en, 9, 1); - DI_Wr(DNR_HVSIZE, nCol<<16|nRow); - DI_Wr(DNR_STAT_X_START_END, (((dnr_stat_coef<<3)&0x3fff) << 16) - |((nCol-((dnr_stat_coef<<3)+1))&0x3fff)); - DI_Wr(DNR_STAT_Y_START_END, (((dnr_stat_coef<<3)&0x3fff) << 16) - |((nRow-((dnr_stat_coef<<3)+1))&0x3fff)); - if (ro_gbs_stat_lr != Rd(DNR_RO_GBS_STAT_LR) || - ro_gbs_stat_ll != Rd(DNR_RO_GBS_STAT_LL) || - ro_gbs_stat_rr != Rd(DNR_RO_GBS_STAT_RR) || - ro_gbs_stat_dif != Rd(DNR_RO_GBS_STAT_DIF) || - ro_gbs_stat_cnt != Rd(DNR_RO_GBS_STAT_CNT)) { - - ro_gbs_stat_lr = Rd(DNR_RO_GBS_STAT_LR); - ro_gbs_stat_ll = Rd(DNR_RO_GBS_STAT_LL); - ro_gbs_stat_rr = Rd(DNR_RO_GBS_STAT_RR); - ro_gbs_stat_dif = Rd(DNR_RO_GBS_STAT_DIF); - ro_gbs_stat_cnt = Rd(DNR_RO_GBS_STAT_CNT); - } else { - return; - } - - global_bs_calc_sw(&pDnrPrm->sw_gbs_vld_cnt, - &pDnrPrm->sw_gbs_vld_flg, - &pDnrPrm->sw_gbs, - ro_gbs_stat_lr, - ro_gbs_stat_ll, - ro_gbs_stat_rr, - ro_gbs_stat_dif, - ro_gbs_stat_cnt, - pDnrPrm->prm_gbs_vldcntthd, /* prm below */ - pDnrPrm->prm_gbs_cnt_min, - pDnrPrm->prm_gbs_ratcalcmod, - pDnrPrm->prm_gbs_ratthd, - pDnrPrm->prm_gbs_difthd, - pDnrPrm->prm_gbs_bsdifthd, - pDnrPrm->prm_gbs_calcmod); -#ifdef DNR_HV_SHIFT - for (i = 0; i < 32; i++) - ro_hbof_stat_cnt[i] = Rd(DNR_RO_HBOF_STAT_CNT_0+i); - for (i = 0; i < 32; i++) - ro_vbof_stat_cnt[i] = Rd(DNR_RO_VBOF_STAT_CNT_0+i); - hor_blk_ofst_calc_sw(&pDnrPrm->sw_hbof_vld_cnt, - &pDnrPrm->sw_hbof_vld_flg, - &pDnrPrm->sw_hbof, - ro_hbof_stat_cnt, - 0, - nCol-1, - pDnrPrm->prm_hbof_minthd, - pDnrPrm->prm_hbof_ratthd0, - pDnrPrm->prm_hbof_ratthd1, - pDnrPrm->prm_hbof_vldcntthd, - nRow, - nCol); - - ver_blk_ofst_calc_sw(&pDnrPrm->sw_vbof_vld_cnt, - &pDnrPrm->sw_vbof_vld_flg, - &pDnrPrm->sw_vbof, - ro_vbof_stat_cnt, - 0, - nRow-1, - pDnrPrm->prm_vbof_minthd, - pDnrPrm->prm_vbof_ratthd0, - pDnrPrm->prm_vbof_ratthd1, - pDnrPrm->prm_vbof_vldcntthd, - nRow, - nCol); -#endif - /* update hardware registers */ - if (pDnrPrm->prm_sw_gbs_ctrl == 0) { - DI_Wr(DNR_GBS, - (pDnrPrm->sw_gbs_vld_flg == 1)?pDnrPrm->sw_gbs : 0); - } else if (pDnrPrm->prm_sw_gbs_ctrl == 1) { - DI_Wr_reg_bits(DNR_BLK_OFFST, - (pDnrPrm->sw_hbof_vld_flg == 1)?pDnrPrm->sw_hbof:0, 4, 3); - DI_Wr(DNR_GBS, (pDnrPrm->sw_hbof_vld_flg == 1 && - pDnrPrm->sw_gbs_vld_flg == 1)?pDnrPrm->sw_gbs:0); - } else if (pDnrPrm->prm_sw_gbs_ctrl == 2) { - DI_Wr_reg_bits(DNR_BLK_OFFST, - (pDnrPrm->sw_vbof_vld_flg == 1)?pDnrPrm->sw_vbof:0, 0, 3); - DI_Wr(DNR_GBS, (pDnrPrm->sw_vbof_vld_flg == 1 && - pDnrPrm->sw_gbs_vld_flg == 1)?pDnrPrm->sw_gbs:0); - } else if (pDnrPrm->prm_sw_gbs_ctrl == 1) { - DI_Wr_reg_bits(DNR_BLK_OFFST, - pDnrPrm->sw_hbof_vld_flg == 1 ? pDnrPrm->sw_hbof : 0, 4, 3); - DI_Wr_reg_bits(DNR_BLK_OFFST, - pDnrPrm->sw_vbof_vld_flg == 1 ? pDnrPrm->sw_vbof : 0, 0, 3); - DI_Wr(DNR_GBS, (pDnrPrm->sw_hbof_vld_flg == 1 && - pDnrPrm->sw_vbof_vld_flg == 1 && - pDnrPrm->sw_gbs_vld_flg == 1)?pDnrPrm->sw_gbs:0); - } -} - -static void parse_cmd_params(char *buf_orig, char **parm) -{ - char *ps, *token; - char delim1[2] = " "; - char delim2[2] = "\n"; - unsigned int n = 0; - - ps = buf_orig; - strcat(delim1, delim2); - while (1) { - token = strsep(&ps, delim1); - if (token == NULL) - break; - if (*token == '\0') - continue; - parm[n++] = token; - } -} - -static dnr_param_t dnr_params[] = { - {"prm_sw_gbs_ctrl", &(dnr_param.prm_sw_gbs_ctrl)}, - {"prm_gbs_vldcntthd", &(dnr_param.prm_gbs_vldcntthd)}, - {"prm_gbs_cnt_min", &(dnr_param.prm_gbs_cnt_min)}, - {"prm_gbs_ratcalcmod", &(dnr_param.prm_gbs_ratcalcmod)}, - {"prm_gbs_ratthd[0]", &(dnr_param.prm_gbs_ratthd[0])}, - {"prm_gbs_ratthd[1]", &(dnr_param.prm_gbs_ratthd[1])}, - {"prm_gbs_ratthd[2]", &(dnr_param.prm_gbs_ratthd[2])}, - {"prm_gbs_difthd[0]", &(dnr_param.prm_gbs_difthd[0])}, - {"prm_gbs_difthd[1]", &(dnr_param.prm_gbs_difthd[1])}, - {"prm_gbs_difthd[2]", &(dnr_param.prm_gbs_difthd[2])}, - {"prm_gbs_bsdifthd", &(dnr_param.prm_gbs_bsdifthd)}, - {"prm_gbs_calcmod", &(dnr_param.prm_gbs_calcmod)}, - {"sw_gbs", &(dnr_param.sw_gbs)}, - {"sw_gbs_vld_flg", &(dnr_param.sw_gbs_vld_flg)}, - {"sw_gbs_vld_cnt", &(dnr_param.sw_gbs_vld_cnt)}, - {"prm_hbof_minthd", &(dnr_param.prm_hbof_minthd)}, - {"prm_hbof_ratthd0", &(dnr_param.prm_hbof_ratthd0)}, - {"prm_hbof_ratthd1", &(dnr_param.prm_hbof_ratthd1)}, - {"prm_hbof_vldcntthd", &(dnr_param.prm_hbof_vldcntthd)}, - {"sw_hbof", &(dnr_param.sw_hbof)}, - {"sw_hbof_vld_flg", &(dnr_param.sw_hbof_vld_flg)}, - {"sw_hbof_vld_cnt", &(dnr_param.sw_hbof_vld_cnt)}, - {"prm_vbof_minthd", &(dnr_param.prm_vbof_minthd)}, - {"prm_vbof_ratthd0", &(dnr_param.prm_vbof_ratthd0)}, - {"prm_vbof_ratthd1", &(dnr_param.prm_vbof_ratthd1)}, - {"prm_vbof_vldcntthd", &(dnr_param.prm_vbof_vldcntthd)}, - {"sw_vbof", &(dnr_param.sw_vbof)}, - {"sw_vbof_vld_flg", &(dnr_param.sw_vbof_vld_flg)}, - {"sw_vbof_vld_cnt", &(dnr_param.sw_vbof_vld_cnt)}, - {"", NULL} -}; -static ssize_t dnr_param_store(struct device *dev, - struct device_attribute *attr, - const char *buff, size_t count) -{ - int i = 0, value = 0; - char *parm[2] = {NULL}, *buf_orig; - - buf_orig = kstrdup(buff, GFP_KERNEL); - parse_cmd_params(buf_orig, (char **)(&parm)); - for (i = 0; dnr_params[i].addr; i++) { - if (!strcmp(parm[0], dnr_params[i].name)) { - value = kstrtol(parm[1], 10, NULL); - *(dnr_params[i].addr) = value; - pr_dbg("%s=%d.\n", dnr_params[i].name, - *(dnr_params[i].addr)); - } - } - - return count; -} - -static ssize_t dnr_param_show(struct device *dev, - struct device_attribute *attr, - char *buff) -{ - ssize_t len = 0; - int i = 0; - - for (i = 0; dnr_params[i].addr; i++) - len += sprintf(buff+len, "%s=%d.\n", - dnr_params[i].name, - *(dnr_params[i].addr)); - return len; -} -static DEVICE_ATTR(dnr_param, 0664, dnr_param_show, dnr_param_store); -void di_nr_init(void) -{ -#if 0 - DI_Wr(DI_NR_CTRL0, 0xc60c0804); - DI_Wr(DI_NR_CTRL1, 0x403e3c3a); - DI_Wr(DI_NR_CTRL2, 0x08010a01); - DI_Wr(NR2_MET_NM_CCTRL, 0x45056410); - DI_Wr(NR2_MATNR_SNR_NRM_GAIN, 0x4); - DI_Wr(NR2_MATNR_SNR_LPF_CFG, 0xc2b64); - DI_Wr(NR2_MATNR_SNR_EDGE2B, 0xcff08); - DI_Wr(NR2_MATNR_YBETA_SCL, 0x00ff2000); - DI_Wr(NR2_MATNR_MTN_CRTL2, 0x32020); - DI_Wr(NR2_MATNR_MTN_COR, 0x3333); - DI_Wr(NR2_MATNR_DEGHOST, 0x133); - DI_Wr(NR2_MATNR_ALPHALP_LUT0, 0x99999a9a); - DI_Wr(NR2_MATNR_ALPHALP_LUT1, 0x9aa0a6e3); - DI_Wr(NR2_MATNR_ALPHALP_LUT2, 0x90808080); - DI_Wr(NR2_MATNR_ALPHALP_LUT3, 0xffe0c0a4); - DI_Wr(NR2_MATNR_ALPHAHP_LUT1, 0x80805040); - DI_Wr(NR2_MATNR_ALPHAHP_LUT2, 0x90808080); - DI_Wr(NR2_MATNR_ALPHAHP_LUT3, 0xffe0c0a4); -#endif - DI_Wr(NR3_MODE, 0x3); - DI_Wr(NR3_COOP_PARA, 0x28ff00); - DI_Wr(NR3_CNOOP_GAIN, 0x881900); - DI_Wr(NR3_YMOT_PARA, 0x0c0a1e); - DI_Wr(NR3_CMOT_PARA, 0x08140f); - DI_Wr(NR3_SUREMOT_YGAIN, 0x100c4014); - DI_Wr(NR3_SUREMOT_CGAIN, 0x22264014); - - DI_Wr(0x1745, 0x5056410); - DI_Wr(0x1746, 0x45056410); - DI_Wr(0x1747, 0x45056410); - DI_Wr(0x1748, 0x1); - DI_Wr(0x1749, 0x7c3a); - DI_Wr(0x174a, 0x29e77); - DI_Wr(0x174b, 0x9f1a); - DI_Wr(0x174c, 0x2822c); - DI_Wr(0x174d, 0x77); - DI_Wr(0x174e, 0x3030); - DI_Wr(0x174f, 0x20030); - DI_Wr(0x1750, 0xf002d0); - DI_Wr(0x1751, 0x132f); - DI_Wr(0x1752, 0x8d); - DI_Wr(0x1753, 0x40ff00); - DI_Wr(0x1754, 0x4); - DI_Wr(0x1755, 0xc2b64); - DI_Wr(0x1756, 0x0); - DI_Wr(0x1757, 0x3608); - DI_Wr(0x1758, 0x420); - DI_Wr(0x1759, 0xa06664); - DI_Wr(0x175a, 0xe0000); - DI_Wr(0x175b, 0x991c00); - DI_Wr(0x175c, 0x991000); - DI_Wr(0x175d, 0xf9f3e); - DI_Wr(0x175e, 0x7292abcd); - DI_Wr(0x175f, 0x1c23314f); - DI_Wr(0x1760, 0xf111317); - DI_Wr(0x1761, 0x8090a0c); - DI_Wr(0x1762, 0x80a0e0ff); - DI_Wr(0x1763, 0x4102050); - DI_Wr(0x1764, 0x2); - DI_Wr(0x1765, 0x0); - DI_Wr(0x1766, 0x20100400); - DI_Wr(0x1767, 0xc4804030); - DI_Wr(0x1768, 0xfffff0e0); - DI_Wr(0x1769, 0xffffffff); - DI_Wr(0x176a, 0x1132); - DI_Wr(0x176b, 0x32020); - DI_Wr(0x176c, 0x3333); - DI_Wr(0x176d, 0x4b4e4b4d); - DI_Wr(0x176e, 0x111); - DI_Wr(0x176f, 0x32181818); - DI_Wr(0x1770, 0x80644032); - DI_Wr(0x1771, 0x9e808080); - DI_Wr(0x1772, 0xffffffff); - DI_Wr(0x1773, 0x32181818); - DI_Wr(0x1774, 0x80644032); - DI_Wr(0x1775, 0xa5808080); - DI_Wr(0x1776, 0xffffffff); - DI_Wr(0x1777, 0xa06663); - DI_Wr(0x1778, 0x372); - DI_Wr(0x1779, 0x14141414); - DI_Wr(0x177a, 0x1400); - DI_Wr(0x177b, 0x80064); - DI_Wr(0x177c, 0x80064); - DI_Wr(0x177d, 0x80a0a); - DI_Wr(0x177e, 0x4281e); - DI_Wr(0x177f, 0x0); - DI_Wr(0x179c, 0x11b); - DI_Wr(0x179d, 0x202220); -} -void nr_init(struct device *dev) -{ - dnr_prm_init(&dnr_param); - device_create_file(dev, &dev_attr_dnr_param); -} - diff --git a/drivers/amlogic/media/deinterlace/nr_drv.c b/drivers/amlogic/media/deinterlace/nr_drv.c new file mode 100644 index 000000000000..70a85b57e992 --- /dev/null +++ b/drivers/amlogic/media/deinterlace/nr_drv.c @@ -0,0 +1,1157 @@ +/* + * drivers/amlogic/media/deinterlace/nr_drv.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "register.h" +#include "register_nr4.h" +#include "nr_drv.h" +#include "deinterlace.h" + +static DNR_PRM_t dnr_param; +static struct NR_PARM_s nr_param; +static bool dnr_pr; +module_param(dnr_pr, bool, 0644); +MODULE_PARM_DESC(dnr_pr, "/n print dnr debug information /n"); + +static bool dnr_dm_en; +module_param(dnr_dm_en, bool, 0644); +MODULE_PARM_DESC(dnr_dm_en, "/n dnr dm enable debug /n"); + +static bool dnr_en = true; +module_param_named(dnr_en, dnr_en, bool, 0644); + +static unsigned int nr2_en = 0x1; +module_param_named(nr2_en, nr2_en, uint, 0644); + +int global_bs_calc_sw(int *pGbsVldCnt, + int *pGbsVldFlg, + int *pGbs, + int nGbsStatLR, + int nGbsStatLL, + int nGbsStatRR, + int nGbsStatDif, + int nGbsStatCnt, + int prm_gbs_vldcntthd, /* prm below */ + int prm_gbs_cnt_min, + int prm_gbs_ratcalcmod, + int prm_gbs_ratthd[3], + int prm_gbs_difthd[3], + int prm_gbs_bsdifthd, + int prm_gbs_calcmod) +{ + int nMax, nMin; + int nDif0, nDif1, nDif2; + int nDif, nRat; + int nCurGbs; + + nMax = max(max(nGbsStatLR, nGbsStatLL), nGbsStatRR); + nMin = min(min(nGbsStatLR, nGbsStatLL), nGbsStatRR); + + nDif0 = nMax == 0 ? 0 : ((nMax - nMin) << 9)/nMax; + nDif0 = min(511, nDif0); + + nDif1 = nGbsStatLR == 0 ? 0 : + (abs(nGbsStatLR - (nGbsStatLL + nGbsStatRR)/2) << 9)/nGbsStatLR; + nDif1 = min(511, nDif1); + + nDif2 = nGbsStatLR == 0 ? 0 : + (abs(nGbsStatLR - max(nGbsStatLL, nGbsStatRR)) << 9)/nGbsStatLR; + nDif2 = min(511, nDif2); + + if (prm_gbs_ratcalcmod == 0) + nRat = (nGbsStatLR << 4) / max(prm_gbs_cnt_min, nGbsStatCnt); + else + nRat = (nGbsStatDif << 4) / max(prm_gbs_cnt_min, nGbsStatCnt); + + nDif = (prm_gbs_calcmod == 0) ? nDif0 : +(prm_gbs_calcmod == 1 ? nDif1 : nDif2); + + if (nGbsStatLR < max(nGbsStatLL, nGbsStatRR)) { + if (nGbsStatCnt <= prm_gbs_cnt_min || nRat <= prm_gbs_ratthd[0]) + nCurGbs = 0; + else if (nRat <= prm_gbs_ratthd[1]) + nCurGbs = 1; + else if (nRat <= prm_gbs_ratthd[2]) + nCurGbs = 2; + else + nCurGbs = 3; + } else { + if (nGbsStatCnt <= prm_gbs_cnt_min || nDif <= prm_gbs_difthd[0]) + nCurGbs = 0; + else if (nDif <= prm_gbs_difthd[1]) + nCurGbs = 1; + else if (nDif <= prm_gbs_difthd[2]) + nCurGbs = 2; + else + nCurGbs = 3; + } + + /* */ + if ((nCurGbs != 0 && 0 == *pGbs) || +(nCurGbs != 0 && abs(nCurGbs - *pGbs) <= prm_gbs_bsdifthd)) + (*pGbsVldCnt)++; + else + *pGbsVldCnt = 0; + + if (*pGbsVldCnt >= prm_gbs_vldcntthd) + *pGbsVldFlg = 1; + else + *pGbsVldFlg = 0; + + *pGbs = nCurGbs; + + /* print debug info. */ + /* printk("GBS info at Field: LR = %6d, LL = %6d, RR = %6d.\n", + * nGbsStatLR, nGbsStatLL, nGbsStatRR; + */ + + return 0; +} + +#ifdef DNR_HV_SHIFT +int hor_blk_ofst_calc_sw(int *pHbOfVldCnt, + int *pHbOfVldFlg, + int *pHbOfst, + int nHbOfStatCnt[32], + int nXst, + int nXed, + int prm_hbof_minthd, + int prm_hbof_ratthd0, + int prm_hbof_ratthd1, + int prm_hbof_vldcntthd, + int nRow, + int nCol) +{ + int i = 0; + + int nCurHbOfst = 0; + int nRat0 = 0, nRat1 = 0; + + int nMax1 = 0; + int nMax2 = 0; + int nMaxIdx = 0; + + /* get 2 maximum, move to RTL part */ + nMax1 = nMax2 = 0; + for (i = 0; i < 8; i++) { + if (nHbOfStatCnt[i] > nMax1) { + nMax2 = nMax1; + nMax1 = nHbOfStatCnt[i]; + nMaxIdx = i; + } else if (nHbOfStatCnt[i] > nMax2) { + nMax2 = nHbOfStatCnt[i]; + } + } /* i */ + + /* decide if offset valid */ + nCurHbOfst = -1; + nRat0 = 256*nMax1/((nXed - nXst)/8)/nRow; + nRat1 = 128*nMax1/max(nMax2, prm_hbof_minthd); + if (nRat0 >= prm_hbof_ratthd0 && nRat1 >= prm_hbof_ratthd1) + nCurHbOfst = (nMaxIdx+1)%8; + + if (nCurHbOfst == *pHbOfst) + (*pHbOfVldCnt)++; + else + *pHbOfVldCnt = 0; + + if (*pHbOfVldCnt >= prm_hbof_vldcntthd) + *pHbOfVldFlg = 1; + else + *pHbOfVldFlg = 0; + + *pHbOfst = (nCurHbOfst == -1) ? 0 : nCurHbOfst; + + /* print for debug + * printk("Hoff info at Field: "); + * for ( i = 0; i < 32; i++ ) { + * printk("%5d, ", nHbOfStatCnt[i]); + * } + */ + if (dnr_pr) { + pr_dbg("Max1 = %5d, Max2 = %5d, MaxIdx = %5d, Rat0 = %5d,Rat1 = %5d.\n", + nMax1, nMax2, nMaxIdx, nRat0, nRat1); + pr_dbg("CurHbOfst = %5d, HbOfVldFlg = %d, HbOfVldCnt = %d.\n", + nCurHbOfst, *pHbOfVldFlg, *pHbOfVldCnt); + } + + return 0; +} +int ver_blk_ofst_calc_sw(int *pVbOfVldCnt, + int *pVbOfVldFlg, + int *pVbOfst, + int nVbOfStatCnt[32], + int nYst, + int nYed, + int prm_vbof_minthd, + int prm_vbof_ratthd0, + int prm_vbof_ratthd1, + int prm_vbof_vldcntthd, + int nRow, + int nCol) +{ + int i = 0; + + int nCurVbOfst = 0; + int nRat0 = 0, nRat1 = 0; + + int nMax1 = 0; + int nMax2 = 0; + int nMaxIdx = 0; + + /* get 2 maximum, move to RTL part */ + nMax1 = nMax2 = 0; + for (i = 0; i < 8; i++) { + if (nVbOfStatCnt[i] > nMax1) { + nMax2 = nMax1; + nMax1 = nVbOfStatCnt[i]; + nMaxIdx = i; + } + else if (nVbOfStatCnt[i] > nMax2) { + nMax2 = nVbOfStatCnt[i]; + } + } + + /* decide if offset valid */ + nCurVbOfst = -1; + nRat0 = 256*nMax1/((nYed - nYst)/8)/nCol; + nRat1 = 128*nMax1/max(nMax2, prm_vbof_minthd); + if (nRat0 >= prm_vbof_ratthd0 && nRat1 >= prm_vbof_ratthd1) + nCurVbOfst = (nMaxIdx+1)%8; + + if (nCurVbOfst == *pVbOfst) + (*pVbOfVldCnt)++; + else + *pVbOfVldCnt = 0; + + if (*pVbOfVldCnt >= prm_vbof_vldcntthd) + *pVbOfVldFlg = 1; + else + *pVbOfVldFlg = 0; + + *pVbOfst = (nCurVbOfst == -1) ? 0 : nCurVbOfst; + + /* print for debug + * printk("Voff info at Field: "); + * for ( i = 0; i < 32; i++ ) { + * printk("%5d, ", nVbOfStatCnt[i]); + * }//i + * //printk("Max1 = %5d, Max2 = %5d, MaxIdx = %5d, Rat0 = %5d, + * Rat1 = %5d, CurVbOfst = %5d, VbOfVldFlg = %d, VbOfVldCnt = %d.\n" + * nMax1, nMax2, nMaxIdx, nRat0, nRat1, nCurVbOfst, *pVbOfVldFlg, + * *pVbOfVldCnt); + */ + return 0; +} +#endif +static void dnr_config(struct DNR_PARM_s *dnr_parm_p, + unsigned short width, unsigned short height) +{ + unsigned short border_offset = dnr_parm_p->dnr_stat_coef; + + DI_Wr(DNR_HVSIZE, width<<16|height); + DI_Wr(DNR_STAT_X_START_END, (((border_offset<<3)&0x3fff) << 16) + |((width-((border_offset<<3)+1))&0x3fff)); + DI_Wr(DNR_STAT_Y_START_END, (((border_offset<<3)&0x3fff) << 16) + |((height-((border_offset<<3)+1))&0x3fff)); + DI_Wr(DNR_DM_CTRL, Rd(DNR_DM_CTRL)|(1 << 11)); + DI_Wr_reg_bits(DNR_CTRL, dnr_en?1:0, 16, 1); + /* dm for sd, hd will slower */ + DI_Wr(DNR_CTRL, 0x1df00); + if (is_meson_gxlx_cpu()) { + /* disable chroma dm according to baozheng */ + DI_Wr_reg_bits(DNR_DM_CTRL, 0, 8, 1); + DI_Wr(DNR_CTRL, 0x1dd00); + } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) { + /*disable */ + if (width > 1280) { + DI_Wr_reg_bits(DNR_DM_CTRL, 0, 8, 1); + /* disable dm for 1080 which will cause pre timeout*/ + DI_Wr_reg_bits(DNR_DM_CTRL, 0, 9, 1); + } else { + DI_Wr_reg_bits(DNR_DM_CTRL, 1, 8, 1); + DI_Wr_reg_bits(DNR_DM_CTRL, dnr_dm_en, 9, 1); + } + } else { + if (width >= 1920) + DI_Wr_reg_bits(DNR_DM_CTRL, 0, 9, 1); + else + DI_Wr_reg_bits(DNR_DM_CTRL, dnr_dm_en, 9, 1); + } +} +static void nr4_config(struct NR4_PARM_s *nr4_parm_p, + unsigned short width, unsigned short height) +{ + unsigned short val = 0; + + val = nr4_parm_p->border_offset; + /* luma enhancement*/ + DI_Wr(NR4_MCNR_LUMA_STAT_LIMTX, (val<<16) | (width-val-1)); + DI_Wr(NR4_MCNR_LUMA_STAT_LIMTY, (val<<16) | (height-val-1)); + /* noise meter */ + DI_Wr(NR4_NM_X_CFG, (val<<16) | (width-val-1)); + DI_Wr(NR4_NM_Y_CFG, (val<<16) | (height-val-1)); + /* enable nr4 */ + DI_Wr_reg_bits(NR4_TOP_CTRL, 1, 16, 1); + DI_Wr_reg_bits(NR4_TOP_CTRL, 1, 18, 1); + DI_Wr_reg_bits(NR4_TOP_CTRL, 1, 3, 1); + DI_Wr_reg_bits(NR4_TOP_CTRL, (val&0x1), 5, 1); + nr4_parm_p->width = width - val - val - 1; + nr4_parm_p->height = height - val - val - 1; +} +/* + * line buffer ctrl such as 5 lines or 3 lines + * yuv444 or yuv422 + */ +static void linebuffer_config(unsigned short width) +{ + unsigned short val = 0; + unsigned short line5_444 = 1368, line5_422 = 2052; + unsigned short line3_444 = 2736; + + if (is_meson_txhd_cpu()) { + line5_444 = 640; + line5_422 = 960; + line3_444 = 1280; + } + if (width <= line5_444) + val = 3; + else if (width <= line5_422) + val = 1; + else if (width <= line3_444) + val = 2; + else + val = 0; + /* line buffer no gate clock */ + DI_Wr_reg_bits(LBUF_TOP_CTRL, 0, 20, 6); + DI_Wr_reg_bits(LBUF_TOP_CTRL, val, 16, 2); +} + +static void nr2_config(unsigned short width, unsigned short height) +{ + if (is_meson_txlx_cpu()) + DI_Wr_reg_bits(NR4_TOP_CTRL, nr2_en, 2, 1); + else { + /*set max height to disable nfram cnt in cue*/ + if (is_meson_gxlx_cpu()) + DI_Wr(NR2_FRM_SIZE, (0xfff<<16)|width); + else + DI_Wr(NR2_FRM_SIZE, (height<<16)|width); + DI_Wr_reg_bits(NR2_SW_EN, nr2_en, 4, 1); + } +} + +static bool cue_en = true; +module_param_named(cue_en, cue_en, bool, 0664); +/* + * workaround for nframe count + * indicating error field type in cue + */ +static void cue_config(struct CUE_PARM_s *pcue_parm, unsigned short field_type) +{ + pcue_parm->field_count = 8; + pcue_parm->frame_count = 8; + if (field_type != VIDTYPE_PROGRESSIVE) { + DI_Wr_reg_bits(NR2_CUE_PRG_DIF, 0, 20, 1); + DI_Wr_reg_bits(DI_NR_CTRL0, 0, 26, 1); + /* cur row mode avoid seek error */ + Wr_reg_bits(NR2_CUE_MODE, 5, 0, 4); + } else { + DI_Wr_reg_bits(NR2_CUE_PRG_DIF, 1, 20, 1); + /* disable cue for progressive issue */ + DI_Wr_reg_bits(DI_NR_CTRL0, 0, 26, 1); + } +} + +void nr_all_config(unsigned short width, unsigned short height, + unsigned short field_type) +{ + nr_param.width = width; + nr_param.height = height; + nr_param.frame_count = 0; + nr_param.prog_flag = field_type?false:true; + nr_gate_control(true); + nr2_config(width, height); + dnr_config(nr_param.pdnr_parm, width, height); + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) + cue_config(nr_param.pcue_parm, field_type); + if (is_meson_txlx_cpu()) { + linebuffer_config(width); + nr4_config(nr_param.pnr4_parm, width, height); + } + if (is_meson_txhd_cpu()) + linebuffer_config(width); +} + +static int find_lut16(unsigned int val, int *pLut) +{ + int idx_L, shft, dist; + int left, right, norm; + int res; + + if (val < 2) { + idx_L = 0; + dist = val - 0; + shft = 1; + } else if (val < 4) { + idx_L = 1; + dist = val - 2; + shft = 1; + } else if (val < 8) { + idx_L = 2; + dist = val - 4; + shft = 2; + } else if (val < 16) { + idx_L = 3; + dist = val - 8; + shft = 3; + } else if (val < 32) { + idx_L = 4; + dist = val - 16; + shft = 4; + } else if (val < 48) { + idx_L = 5; + dist = val - 32; + shft = 4; + } else if (val < 64) { + idx_L = 6; + dist = val - 48; + shft = 4; + } else if (val < 80) { + idx_L = 7; + dist = val - 64; + shft = 4; + } else if (val < 96) { + idx_L = 8; + dist = val - 80; + shft = 4; + } else if (val < 112) { + idx_L = 9; + dist = val - 96; + shft = 4; + } else if (val < 128) { + idx_L = 10; + dist = val - 112; + shft = 4; + } else if (val < 160) { + idx_L = 11; + dist = val - 128; + shft = 5; + } else if (val < 192) { + idx_L = 12; + dist = val - 160; + shft = 5; + } else if (val < 224) { + idx_L = 13; + dist = val - 192; + shft = 5; + } else { + idx_L = 14; + dist = val - 224; + shft = 5; + } + left = pLut[idx_L]; + right = pLut[idx_L+1]; + norm = (1<>1))>>shft); + return res; +} +static void noise_meter_process(struct NR4_PARM_s *nr4_param_p, + unsigned int field_cnt) +{ + unsigned int val1 = 0, val2 = 0, field_sad = 0, field_var = 0; + int val = 0; + + val1 = Rd(NR4_RO_NM_SAD_CNT); + val2 = Rd(NR4_RO_NM_SAD_SUM); + + field_sad = (val1 == 0 ? 0 : (val2 + (val1>>1)) / val1); + + val1 = Rd(NR4_RO_NM_VAR_SCNT); + val2 = Rd(NR4_RO_NM_VAR_SUM); + field_var = (val1 == 0 ? 0 : (val2 + (val1>>1)) / val1); + /* + * field sad based global noise level to gain, + * maybe improved further + */ + if (nr4_param_p->sw_nr4_sad2gain_en == 1) { + val2 = (field_sad<<2) < 255 ? (field_sad<<2) : 255; + val1 = find_lut16(val2, &nr4_param_p->sw_nr4_sad2gain_lut[0]); + } else + val1 = 64; + DI_Wr_reg_bits(NR4_MCNR_MV_CTRL_REG, val1, 4, 8); + /* scene change processing */ + nr4_param_p->sw_nr4_scene_change_flg[0] = + nr4_param_p->sw_nr4_scene_change_flg[1]; + nr4_param_p->sw_nr4_scene_change_flg[1] = + nr4_param_p->sw_nr4_scene_change_flg[2]; + val = field_sad - nr4_param_p->sw_nr4_field_sad[1]; + if (field_cnt > 2 + && (val > nr4_param_p->sw_nr4_scene_change_thd)) { + nr4_param_p->sw_nr4_scene_change_flg[2] = 1; + if (nr4_param_p->nr4_debug) { + pr_info("NR4 current field_sad=%d, sad[1]=%d, val=%d", + field_sad, nr4_param_p->sw_nr4_field_sad[1], val); + } + } else + nr4_param_p->sw_nr4_scene_change_flg[2] = 0; + if (nr4_param_p->sw_nr4_scene_change_flg[1] || + nr4_param_p->sw_nr4_scene_change_flg[2]) + DI_Wr_reg_bits(NR4_TOP_CTRL, 1, 0, 1); + else + DI_Wr_reg_bits(NR4_TOP_CTRL, 0, 0, 1); + nr4_param_p->sw_nr4_field_sad[0] = nr4_param_p->sw_nr4_field_sad[1]; + nr4_param_p->sw_nr4_field_sad[1] = field_sad; +} +static void luma_enhancement_process(struct NR4_PARM_s *nr4_param_p, + unsigned int field_cnt) +{ + unsigned int reg_val = 0, tmp1 = 0; + + tmp1 = nr4_param_p->width * nr4_param_p->height; + if (field_cnt <= 2) { + reg_val = (Rd(NR4_MCNR_RO_U_SUM) + (tmp1>>1))/tmp1; + DI_Wr_reg_bits(NR4_MCNR_LUMAPRE_CAL_PRAM, reg_val, 8, 8); + reg_val = (Rd(NR4_MCNR_RO_V_SUM) + (tmp1>>1))/tmp1; + DI_Wr_reg_bits(NR4_MCNR_LUMAPRE_CAL_PRAM, reg_val, 0, 8); + } else { + reg_val = Rd_reg_bits(NR4_MCNR_LUMACUR_CAL_PRAM, 8, 8); + DI_Wr_reg_bits(NR4_MCNR_LUMAPRE_CAL_PRAM, reg_val, 8, 8); + reg_val = Rd_reg_bits(NR4_MCNR_LUMACUR_CAL_PRAM, 0, 8); + DI_Wr_reg_bits(NR4_MCNR_LUMACUR_CAL_PRAM, reg_val, 0, 8); + } + reg_val = Rd_reg_bits(NR4_MCNR_LUMACUR_CAL_PRAM, 24, 2); + DI_Wr_reg_bits(NR4_MCNR_LUMAPRE_CAL_PRAM, reg_val, 24, 2); + reg_val = Rd_reg_bits(NR4_MCNR_LUMACUR_CAL_PRAM, 16, 2); + DI_Wr_reg_bits(NR4_MCNR_LUMAPRE_CAL_PRAM, reg_val, 16, 2); + reg_val = (Rd(NR4_MCNR_RO_U_SUM) + (tmp1>>1))/tmp1; + DI_Wr_reg_bits(NR4_MCNR_LUMACUR_CAL_PRAM, reg_val, 8, 8); + reg_val = (Rd(NR4_MCNR_RO_V_SUM) + (tmp1>>1))/tmp1; + DI_Wr_reg_bits(NR4_MCNR_LUMACUR_CAL_PRAM, reg_val, 0, 8); + reg_val = SGN2(Rd(NR4_MCNR_RO_GRDU_SUM)); + DI_Wr_reg_bits(NR4_MCNR_LUMACUR_CAL_PRAM, reg_val, 24, 2); + reg_val = SGN2(Rd(NR4_MCNR_RO_GRDV_SUM)); + DI_Wr_reg_bits(NR4_MCNR_LUMACUR_CAL_PRAM, reg_val, 16, 2); +} +static void dnr_process(struct DNR_PARM_s *pDnrPrm) +{ + static int ro_gbs_stat_lr = 0, ro_gbs_stat_ll = 0, ro_gbs_stat_rr = 0, + ro_gbs_stat_dif = 0, ro_gbs_stat_cnt = 0; + /* int reg_dnr_stat_xst=0,reg_dnr_stat_xed=0, + * reg_dnr_stat_yst=0,reg_dnr_stat_yed=0; + */ +#ifdef DNR_HV_SHIFT + int ro_hbof_stat_cnt[32], ro_vbof_stat_cnt[32], i = 0; +#endif + + if (ro_gbs_stat_lr != Rd(DNR_RO_GBS_STAT_LR) || + ro_gbs_stat_ll != Rd(DNR_RO_GBS_STAT_LL) || + ro_gbs_stat_rr != Rd(DNR_RO_GBS_STAT_RR) || + ro_gbs_stat_dif != Rd(DNR_RO_GBS_STAT_DIF) || + ro_gbs_stat_cnt != Rd(DNR_RO_GBS_STAT_CNT)) { + + ro_gbs_stat_lr = Rd(DNR_RO_GBS_STAT_LR); + ro_gbs_stat_ll = Rd(DNR_RO_GBS_STAT_LL); + ro_gbs_stat_rr = Rd(DNR_RO_GBS_STAT_RR); + ro_gbs_stat_dif = Rd(DNR_RO_GBS_STAT_DIF); + ro_gbs_stat_cnt = Rd(DNR_RO_GBS_STAT_CNT); + } else { + return; + } + + global_bs_calc_sw(&pDnrPrm->sw_gbs_vld_cnt, + &pDnrPrm->sw_gbs_vld_flg, + &pDnrPrm->sw_gbs, + ro_gbs_stat_lr, + ro_gbs_stat_ll, + ro_gbs_stat_rr, + ro_gbs_stat_dif, + ro_gbs_stat_cnt, + pDnrPrm->prm_gbs_vldcntthd, /* prm below */ + pDnrPrm->prm_gbs_cnt_min, + pDnrPrm->prm_gbs_ratcalcmod, + pDnrPrm->prm_gbs_ratthd, + pDnrPrm->prm_gbs_difthd, + pDnrPrm->prm_gbs_bsdifthd, + pDnrPrm->prm_gbs_calcmod); +#ifdef DNR_HV_SHIFT + for (i = 0; i < 32; i++) + ro_hbof_stat_cnt[i] = Rd(DNR_RO_HBOF_STAT_CNT_0+i); + for (i = 0; i < 32; i++) + ro_vbof_stat_cnt[i] = Rd(DNR_RO_VBOF_STAT_CNT_0+i); + hor_blk_ofst_calc_sw(&pDnrPrm->sw_hbof_vld_cnt, + &pDnrPrm->sw_hbof_vld_flg, + &pDnrPrm->sw_hbof, + ro_hbof_stat_cnt, + 0, + nCol-1, + pDnrPrm->prm_hbof_minthd, + pDnrPrm->prm_hbof_ratthd0, + pDnrPrm->prm_hbof_ratthd1, + pDnrPrm->prm_hbof_vldcntthd, + nRow, + nCol); + + ver_blk_ofst_calc_sw(&pDnrPrm->sw_vbof_vld_cnt, + &pDnrPrm->sw_vbof_vld_flg, + &pDnrPrm->sw_vbof, + ro_vbof_stat_cnt, + 0, + nRow-1, + pDnrPrm->prm_vbof_minthd, + pDnrPrm->prm_vbof_ratthd0, + pDnrPrm->prm_vbof_ratthd1, + pDnrPrm->prm_vbof_vldcntthd, + nRow, + nCol); +#endif + /* update hardware registers */ + if (pDnrPrm->prm_sw_gbs_ctrl == 0) { + DI_Wr(DNR_GBS, + (pDnrPrm->sw_gbs_vld_flg == 1)?pDnrPrm->sw_gbs : 0); + } else if (pDnrPrm->prm_sw_gbs_ctrl == 1) { + DI_Wr_reg_bits(DNR_BLK_OFFST, + (pDnrPrm->sw_hbof_vld_flg == 1)?pDnrPrm->sw_hbof:0, 4, 3); + DI_Wr(DNR_GBS, (pDnrPrm->sw_hbof_vld_flg == 1 && + pDnrPrm->sw_gbs_vld_flg == 1)?pDnrPrm->sw_gbs:0); + } else if (pDnrPrm->prm_sw_gbs_ctrl == 2) { + DI_Wr_reg_bits(DNR_BLK_OFFST, + (pDnrPrm->sw_vbof_vld_flg == 1)?pDnrPrm->sw_vbof:0, 0, 3); + DI_Wr(DNR_GBS, (pDnrPrm->sw_vbof_vld_flg == 1 && + pDnrPrm->sw_gbs_vld_flg == 1)?pDnrPrm->sw_gbs:0); + } else if (pDnrPrm->prm_sw_gbs_ctrl == 1) { + DI_Wr_reg_bits(DNR_BLK_OFFST, + pDnrPrm->sw_hbof_vld_flg == 1 ? pDnrPrm->sw_hbof : 0, 4, 3); + DI_Wr_reg_bits(DNR_BLK_OFFST, + pDnrPrm->sw_vbof_vld_flg == 1 ? pDnrPrm->sw_vbof : 0, 0, 3); + DI_Wr(DNR_GBS, (pDnrPrm->sw_hbof_vld_flg == 1 && + pDnrPrm->sw_vbof_vld_flg == 1 && + pDnrPrm->sw_gbs_vld_flg == 1)?pDnrPrm->sw_gbs:0); + } +} + +static bool invert_cue_phase; +module_param_named(invert_cue_phase, invert_cue_phase, bool, 0644); + +static unsigned int cue_pr_cnt; +module_param_named(cue_pr_cnt, cue_pr_cnt, uint, 0644); + +static bool cue_glb_mot_check_en = true; +module_param_named(cue_glb_mot_check_en, cue_glb_mot_check_en, bool, 0644); + +static void cue_process_irq(void) +{ + + int pre_field_num = 0, cue_invert = 0; + + if (is_meson_gxlx_cpu()) { + pre_field_num = Rd_reg_bits(DI_PRE_CTRL, 29, 1); + if (invert_cue_phase) + cue_invert = (pre_field_num?3:0); + else + cue_invert = (pre_field_num?0:3); + if (cue_pr_cnt > 0) { + pr_info("[DI]: chan2 field num %d, cue_invert %d.\n", + pre_field_num, cue_invert); + cue_pr_cnt--; + } + Wr_reg_bits(NR2_CUE_MODE, cue_invert, 10, 2); + } + if (!nr_param.prog_flag) { + if (nr_param.frame_count > 1 && cue_glb_mot_check_en) + DI_Wr_reg_bits(DI_NR_CTRL0, cue_en?1:0, 26, 1); + } + if (nr_param.frame_count == 5) + Wr_reg_bits(NR2_CUE_MODE, 7, 0, 4); +} + +static bool glb_fieldck_en = true; +module_param_named(glb_fieldck_en, glb_fieldck_en, bool, 0644); + +void adaptive_cue_adjust(unsigned int frame_diff, unsigned int field_diff) +{ + struct CUE_PARM_s *pcue_parm = nr_param.pcue_parm; + + if (frame_diff > pcue_parm->glb_mot_framethr) { + pcue_parm->frame_count = pcue_parm->frame_count > 0 ? + (pcue_parm->frame_count - 1) : 0; + } else if (pcue_parm->frame_count < pcue_parm->glb_mot_fieldnum) { + pcue_parm->frame_count = pcue_parm->frame_count + 1; + } + if (glb_fieldck_en) { + if (field_diff < pcue_parm->glb_mot_fieldthr) + pcue_parm->field_count = pcue_parm->field_count + 1; + else if (pcue_parm->field_count < pcue_parm->glb_mot_fieldnum) { + pcue_parm->field_count = pcue_parm->field_count > 0 ? + (pcue_parm->field_count - 1) : 0; + } + } + + if (cue_glb_mot_check_en) { + if (pcue_parm->frame_count > (pcue_parm->glb_mot_fieldnum - 6)) + cue_en = true; + else + cue_en = false; + /* for clockfuliness clip */ + if (pcue_parm->field_count > + (pcue_parm->glb_mot_fieldnum - 6)) { + Wr(NR2_CUE_MODE, 0x50322|(Rd(NR2_CUE_MODE)&0xc00)); + Wr(NR2_CUE_CON_MOT_TH, 0x03010e01); + } else { + Wr(NR2_CUE_MODE, 0x00054377|(Rd(NR2_CUE_MODE)&0xc00)); + Wr(NR2_CUE_CON_MOT_TH, 0xa03c8c3c); + } + } +} + +void nr_process_in_irq(void) +{ + nr_param.frame_count++; + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) + cue_process_irq(); + if (dnr_en) + dnr_process(&dnr_param); + if (is_meson_txlx_cpu()) { + noise_meter_process(nr_param.pnr4_parm, nr_param.frame_count); + luma_enhancement_process(nr_param.pnr4_parm, + nr_param.frame_count); + } +} +static void parse_cmd_params(char *buf_orig, char **parm) +{ + char *ps, *token; + char delim1[2] = " "; + char delim2[2] = "\n"; + unsigned int n = 0; + + ps = buf_orig; + strcat(delim1, delim2); + while (1) { + token = strsep(&ps, delim1); + if (token == NULL) + break; + if (*token == '\0') + continue; + parm[n++] = token; + } +} + +static dnr_param_t dnr_params[] = { + {"prm_sw_gbs_ctrl", &(dnr_param.prm_sw_gbs_ctrl)}, + {"prm_gbs_vldcntthd", &(dnr_param.prm_gbs_vldcntthd)}, + {"prm_gbs_cnt_min", &(dnr_param.prm_gbs_cnt_min)}, + {"prm_gbs_ratcalcmod", &(dnr_param.prm_gbs_ratcalcmod)}, + {"prm_gbs_ratthd[0]", &(dnr_param.prm_gbs_ratthd[0])}, + {"prm_gbs_ratthd[1]", &(dnr_param.prm_gbs_ratthd[1])}, + {"prm_gbs_ratthd[2]", &(dnr_param.prm_gbs_ratthd[2])}, + {"prm_gbs_difthd[0]", &(dnr_param.prm_gbs_difthd[0])}, + {"prm_gbs_difthd[1]", &(dnr_param.prm_gbs_difthd[1])}, + {"prm_gbs_difthd[2]", &(dnr_param.prm_gbs_difthd[2])}, + {"prm_gbs_bsdifthd", &(dnr_param.prm_gbs_bsdifthd)}, + {"prm_gbs_calcmod", &(dnr_param.prm_gbs_calcmod)}, + {"sw_gbs", &(dnr_param.sw_gbs)}, + {"sw_gbs_vld_flg", &(dnr_param.sw_gbs_vld_flg)}, + {"sw_gbs_vld_cnt", &(dnr_param.sw_gbs_vld_cnt)}, + {"prm_hbof_minthd", &(dnr_param.prm_hbof_minthd)}, + {"prm_hbof_ratthd0", &(dnr_param.prm_hbof_ratthd0)}, + {"prm_hbof_ratthd1", &(dnr_param.prm_hbof_ratthd1)}, + {"prm_hbof_vldcntthd", &(dnr_param.prm_hbof_vldcntthd)}, + {"sw_hbof", &(dnr_param.sw_hbof)}, + {"sw_hbof_vld_flg", &(dnr_param.sw_hbof_vld_flg)}, + {"sw_hbof_vld_cnt", &(dnr_param.sw_hbof_vld_cnt)}, + {"prm_vbof_minthd", &(dnr_param.prm_vbof_minthd)}, + {"prm_vbof_ratthd0", &(dnr_param.prm_vbof_ratthd0)}, + {"prm_vbof_ratthd1", &(dnr_param.prm_vbof_ratthd1)}, + {"prm_vbof_vldcntthd", &(dnr_param.prm_vbof_vldcntthd)}, + {"sw_vbof", &(dnr_param.sw_vbof)}, + {"sw_vbof_vld_flg", &(dnr_param.sw_vbof_vld_flg)}, + {"sw_vbof_vld_cnt", &(dnr_param.sw_vbof_vld_cnt)}, + {"dnr_stat_coef", &(dnr_param.dnr_stat_coef)}, + {"", NULL} +}; +static ssize_t dnr_param_store(struct device *dev, + struct device_attribute *attr, + const char *buff, size_t count) +{ + int i = 0, value = 0; + char *parm[2] = {NULL}, *buf_orig; + + buf_orig = kstrdup(buff, GFP_KERNEL); + parse_cmd_params(buf_orig, (char **)(&parm)); + for (i = 0; dnr_params[i].addr; i++) { + if (!strcmp(parm[0], dnr_params[i].name)) { + value = kstrtol(parm[1], 10, NULL); + *(dnr_params[i].addr) = value; + pr_dbg("%s=%d.\n", dnr_params[i].name, + *(dnr_params[i].addr)); + } + } + + kfree(buf_orig); + return count; +} + +static ssize_t dnr_param_show(struct device *dev, + struct device_attribute *attr, + char *buff) +{ + ssize_t len = 0; + int i = 0; + + for (i = 0; dnr_params[i].addr; i++) + len += sprintf(buff+len, "%s=%d.\n", + dnr_params[i].name, *(dnr_params[i].addr)); + return len; +} + +static nr4_param_t nr4_params[30]; +static void nr4_params_init(struct NR4_PARM_s *nr4_parm_p) +{ + nr4_params[0].name = "prm_nr4_srch_stp"; + nr4_params[0].addr = &(nr4_parm_p->prm_nr4_srch_stp); + nr4_params[1].name = "sw_nr4_field_sad[0]"; + nr4_params[1].addr = &(nr4_parm_p->sw_nr4_field_sad[0]); + nr4_params[2].name = "sw_nr4_field_sad[1]"; + nr4_params[2].addr = &(nr4_parm_p->sw_nr4_field_sad[1]); + nr4_params[3].name = "sw_nr4_scene_change_thd"; + nr4_params[3].addr = &(nr4_parm_p->sw_nr4_scene_change_thd); + nr4_params[4].name = "sw_nr4_scene_change_flg[0]"; + nr4_params[4].addr = &(nr4_parm_p->sw_nr4_scene_change_flg[0]); + nr4_params[5].name = "sw_nr4_scene_change_flg[1]"; + nr4_params[5].addr = &(nr4_parm_p->sw_nr4_scene_change_flg[1]); + nr4_params[6].name = "sw_nr4_scene_change_flg[2]"; + nr4_params[6].addr = &(nr4_parm_p->sw_nr4_scene_change_flg[2]); + nr4_params[7].name = "sw_nr4_scene_change_flg[3]"; + nr4_params[7].addr = &(nr4_parm_p->sw_nr4_scene_change_flg[3]); + nr4_params[8].name = "sw_nr4_sad2gain_en"; + nr4_params[8].addr = &(nr4_parm_p->sw_nr4_sad2gain_en); + nr4_params[9].name = "sw_nr4_sad2gain_lut[0]"; + nr4_params[9].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[0]); + nr4_params[10].name = "sw_nr4_sad2gain_lut[1]"; + nr4_params[10].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[1]); + nr4_params[11].name = "sw_nr4_sad2gain_lut[2]"; + nr4_params[11].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[2]); + nr4_params[12].name = "sw_nr4_sad2gain_lut[3]"; + nr4_params[12].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[3]); + nr4_params[13].name = "sw_nr4_sad2gain_lut[4]"; + nr4_params[13].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[4]); + nr4_params[14].name = "sw_nr4_sad2gain_lut[5]"; + nr4_params[14].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[5]); + nr4_params[15].name = "sw_nr4_sad2gain_lut[6]"; + nr4_params[15].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[6]); + nr4_params[16].name = "sw_nr4_sad2gain_lut[7]"; + nr4_params[16].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[7]); + nr4_params[17].name = "sw_nr4_sad2gain_lut[8]"; + nr4_params[17].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[8]); + nr4_params[18].name = "sw_nr4_sad2gain_lut[9]"; + nr4_params[18].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[9]); + nr4_params[19].name = "sw_nr4_sad2gain_lut[10]"; + nr4_params[19].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[10]); + nr4_params[20].name = "sw_nr4_sad2gain_lut11]"; + nr4_params[20].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[11]); + nr4_params[21].name = "sw_nr4_sad2gain_lut[12]"; + nr4_params[21].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[12]); + nr4_params[22].name = "sw_nr4_sad2gain_lut13]"; + nr4_params[22].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[13]); + nr4_params[23].name = "sw_nr4_sad2gain_lut[14]"; + nr4_params[23].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[14]); + nr4_params[24].name = "sw_nr4_sad2gain_lut[15]"; + nr4_params[24].addr = &(nr4_parm_p->sw_nr4_sad2gain_lut[15]); + nr4_params[25].name = "nr4_debug"; + nr4_params[25].addr = &(nr4_parm_p->nr4_debug); + +}; + +static ssize_t nr4_param_store(struct device *dev, + struct device_attribute *attr, + const char *buff, size_t count) +{ + long i = 0, value = 0; + char *parm[2] = {NULL}, *buf_orig; + + buf_orig = kstrdup(buff, GFP_KERNEL); + parse_cmd_params(buf_orig, (char **)(&parm)); + for (i = 0; i < 30; i++) { + if (!strcmp(parm[0], nr4_params[i].name)) { + if (parm[1]) { + if (kstrtol(parm[1], 10, &value) < 0) + pr_err("DI: input value error.\n"); + *(nr4_params[i].addr) = value; + } + } + } + + kfree(buf_orig); + return count; +} + +static ssize_t nr4_param_show(struct device *dev, + struct device_attribute *attr, + char *buff) +{ + ssize_t len = 0; + int i = 0; + + for (i = 0; i < 30; i++) + len += sprintf(buff+len, "%s=%d.\n", + nr4_params[i].name, *(nr4_params[i].addr)); + return len; +} + +static DEVICE_ATTR(nr4_param, 0664, nr4_param_show, nr4_param_store); + +static void nr4_param_init(struct NR4_PARM_s *nr4_parm_p) +{ + int k = 0; + + nr4_parm_p->border_offset = 8; + nr4_parm_p->nr4_debug = 0; + nr4_parm_p->prm_nr4_srch_stp = 1; + nr4_parm_p->sw_nr4_field_sad[0] = 0; + nr4_parm_p->sw_nr4_field_sad[1] = 0; + nr4_parm_p->sw_nr4_scene_change_thd = 20; + for (k = 0; k < 3; k++) + nr4_parm_p->sw_nr4_scene_change_flg[k] = 0; + nr4_parm_p->sw_nr4_sad2gain_en = 1; + nr4_parm_p->sw_nr4_sad2gain_lut[0] = 1; + nr4_parm_p->sw_nr4_sad2gain_lut[1] = 2; + nr4_parm_p->sw_nr4_sad2gain_lut[2] = 2; + nr4_parm_p->sw_nr4_sad2gain_lut[3] = 4; + nr4_parm_p->sw_nr4_sad2gain_lut[4] = 8; + nr4_parm_p->sw_nr4_sad2gain_lut[5] = 16; + nr4_parm_p->sw_nr4_sad2gain_lut[6] = 32; + nr4_parm_p->sw_nr4_sad2gain_lut[7] = 63; + nr4_parm_p->sw_nr4_sad2gain_lut[8] = 67; + nr4_parm_p->sw_nr4_sad2gain_lut[9] = 104; + nr4_parm_p->sw_nr4_sad2gain_lut[10] = 48; + nr4_parm_p->sw_nr4_sad2gain_lut[11] = 32; + nr4_parm_p->sw_nr4_sad2gain_lut[12] = 20; + nr4_parm_p->sw_nr4_sad2gain_lut[13] = 16; + nr4_parm_p->sw_nr4_sad2gain_lut[14] = 14; + nr4_parm_p->sw_nr4_sad2gain_lut[15] = 9; +} + +static void cue_param_init(struct CUE_PARM_s *cue_parm_p) +{ + cue_parm_p->glb_mot_framethr = 1000; + cue_parm_p->glb_mot_fieldnum = 20; + cue_parm_p->glb_mot_fieldthr = 10; + cue_parm_p->field_count = 8; + cue_parm_p->frame_count = 8; +} +static int dnr_prm_init(DNR_PRM_t *pPrm) +{ + pPrm->prm_sw_gbs_ctrl = 0; + /* + * 0: update gbs, 1: update hoffst & gbs, + * 2: update voffst & gbs, 3: update all (hoffst & voffst & gbs). + */ + + pPrm->prm_gbs_vldcntthd = 4; + pPrm->prm_gbs_cnt_min = 32; + pPrm->prm_gbs_ratcalcmod = 1;/* 0: use LR, 1: use Dif */ + pPrm->prm_gbs_ratthd[0] = 40; + pPrm->prm_gbs_ratthd[1] = 80; + pPrm->prm_gbs_ratthd[2] = 120; + pPrm->prm_gbs_difthd[0] = 25; + pPrm->prm_gbs_difthd[1] = 75; + pPrm->prm_gbs_difthd[2] = 125; + pPrm->prm_gbs_bsdifthd = 1; + pPrm->prm_gbs_calcmod = 1; /* 0:dif0, 1:dif1, 2: dif2 */ + + pPrm->sw_gbs = 0; + pPrm->sw_gbs_vld_flg = 0; + pPrm->sw_gbs_vld_cnt = 0; + + pPrm->prm_hbof_minthd = 32; + pPrm->prm_hbof_ratthd0 = 150; + pPrm->prm_hbof_ratthd1 = 150; + pPrm->prm_hbof_vldcntthd = 4; + pPrm->sw_hbof = 0; + pPrm->sw_hbof_vld_flg = 0; + pPrm->sw_hbof_vld_cnt = 0; + + pPrm->prm_vbof_minthd = 32; + pPrm->prm_vbof_ratthd0 = 150; + pPrm->prm_vbof_ratthd1 = 120; + pPrm->prm_vbof_vldcntthd = 4; + pPrm->sw_vbof = 0; + pPrm->sw_vbof_vld_flg = 0; + pPrm->sw_vbof_vld_cnt = 0; + pPrm->dnr_stat_coef = 3; + return 0; +} + +static DEVICE_ATTR(dnr_param, 0664, dnr_param_show, dnr_param_store); + +static void nr_all_ctrl(bool enable) +{ + unsigned char value = 0; + + value = enable ? 1 : 0; + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) { + /* nr4 nr2*/ + DI_Wr_reg_bits(NR4_TOP_CTRL, value, 18, 1); + DI_Wr_reg_bits(NR4_TOP_CTRL, value, 2, 1); + } else { + DI_Wr_reg_bits(NR2_SW_EN, value, 4, 1); + } + DI_Wr_reg_bits(DNR_CTRL, value, 16, 1); + +} +static ssize_t nr_dbg_store(struct device *dev, + struct device_attribute *attr, + const char *buff, size_t count) +{ + char *parm[2] = {NULL}, *buf_orig; + + buf_orig = kstrdup(buff, GFP_KERNEL); + parse_cmd_params(buf_orig, (char **)(&parm)); + if (!strcmp(parm[0], "disable")) + nr_all_ctrl(false); + else if (!strcmp(parm[0], "enable")) + nr_all_ctrl(true); + + kfree(buf_orig); + return count; +} + +static ssize_t nr_dbg_show(struct device *dev, + struct device_attribute *attr, + char *buff) +{ + ssize_t len = 0; + + len += sprintf(buff+len, + "echo disable/enable to disable/enable nr(nr2/nr4/dnr).\n"); + return len; +} + + +static DEVICE_ATTR(nr_debug, 0664, nr_dbg_show, nr_dbg_store); + +void nr_hw_init(void) +{ + + nr_gate_control(true); + DI_Wr(DNR_CTRL, 0x1df00); + DI_Wr(NR3_MODE, 0x3); + DI_Wr(NR3_COOP_PARA, 0x28ff00); + DI_Wr(NR3_CNOOP_GAIN, 0x881900); + DI_Wr(NR3_YMOT_PARA, 0x0c0a1e); + DI_Wr(NR3_CMOT_PARA, 0x08140f); + DI_Wr(NR3_SUREMOT_YGAIN, 0x100c4014); + DI_Wr(NR3_SUREMOT_CGAIN, 0x22264014); + nr_gate_control(false); +} +void nr_gate_control(bool gate) +{ + if (!is_meson_txlx_cpu()) + return; + if (gate) { + /* enable nr auto gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 0, 0, 2); + /* enable dnr auto gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 0, 8, 2); + /* enable nr/dm blend auto gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 0, 10, 2); + /* enable nr internal snr gate */ + DI_Wr_reg_bits(NR4_TOP_CTRL, 0, 30, 2); + /* enable nr internal tnr gate */ + DI_Wr_reg_bits(NR4_TOP_CTRL, 0, 28, 2); + /* enable nr internal mcnr gate */ + DI_Wr_reg_bits(NR4_TOP_CTRL, 0, 26, 2); + /* enable nr internal cfr gate */ + DI_Wr_reg_bits(NR4_TOP_CTRL, 0, 24, 2); + /* enable nr internal det_polar gate */ + DI_Wr_reg_bits(NR4_TOP_CTRL, 0, 22, 2); + /* enable nr internal 3ddet gate */ + DI_Wr_reg_bits(NR4_TOP_CTRL, 0, 20, 2); + } else { + /* enable nr auto gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 1, 0, 2); + /* enable dnr auto gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 1, 8, 2); + /* disable nr/dm blend auto gate */ + DI_Wr_reg_bits(VIUB_GCLK_CTRL2, 1, 10, 2); + /* disable nr internal snr gate */ + DI_Wr_reg_bits(NR4_TOP_CTRL, 1, 30, 2); + /* disable nr internal tnr gate */ + DI_Wr_reg_bits(NR4_TOP_CTRL, 1, 28, 2); + /* disable nr internal mcnr gate */ + DI_Wr_reg_bits(NR4_TOP_CTRL, 1, 26, 2); + /* disable nr internal cfr gate */ + DI_Wr_reg_bits(NR4_TOP_CTRL, 1, 24, 2); + /* disable nr internal det_polar gate */ + DI_Wr_reg_bits(NR4_TOP_CTRL, 1, 22, 2); + /* disable nr internal 3ddet gate */ + DI_Wr_reg_bits(NR4_TOP_CTRL, 1, 20, 2); + } +} +void nr_drv_uninit(struct device *dev) +{ + if (nr_param.pnr4_parm) { + vfree(nr_param.pnr4_parm); + nr_param.pnr4_parm = NULL; + } + + if (nr_param.pcue_parm) { + vfree(nr_param.pcue_parm); + nr_param.pcue_parm = NULL; + } + + device_remove_file(dev, &dev_attr_nr4_param); + device_remove_file(dev, &dev_attr_dnr_param); + device_remove_file(dev, &dev_attr_nr_debug); +} +void nr_drv_init(struct device *dev) +{ + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX)) { + nr_param.pnr4_parm = vmalloc(sizeof(struct NR4_PARM_s)); + if (IS_ERR(nr_param.pnr4_parm)) + pr_err("%s allocate nr4 parm error.\n", __func__); + else { + nr4_params_init(nr_param.pnr4_parm); + nr4_param_init(nr_param.pnr4_parm); + device_create_file(dev, &dev_attr_nr4_param); + } + } + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXLX)) { + nr_param.pcue_parm = vmalloc(sizeof(struct CUE_PARM_s)); + if (IS_ERR(nr_param.pcue_parm)) + pr_err("%s allocate cue parm error.\n", __func__); + else + cue_param_init(nr_param.pcue_parm); + } + dnr_prm_init(&dnr_param); + nr_param.pdnr_parm = &dnr_param; + device_create_file(dev, &dev_attr_dnr_param); + device_create_file(dev, &dev_attr_nr_debug); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXBB)) + dnr_dm_en = true; + else + dnr_dm_en = false; +} diff --git a/drivers/amlogic/media/deinterlace/nr.h b/drivers/amlogic/media/deinterlace/nr_drv.h similarity index 65% rename from drivers/amlogic/media/deinterlace/nr.h rename to drivers/amlogic/media/deinterlace/nr_drv.h index 1a6f256a12a4..715b3fef4d15 100644 --- a/drivers/amlogic/media/deinterlace/nr.h +++ b/drivers/amlogic/media/deinterlace/nr_drv.h @@ -1,5 +1,5 @@ /* - * drivers/amlogic/media/deinterlace/nr.h + * drivers/amlogic/media/deinterlace/nr_drv.h * * Copyright (C) 2017 Amlogic, Inc. All rights reserved. * @@ -18,14 +18,15 @@ #ifndef _DNR_H #define _DNR_H -struct dnr_param_s { +struct nr_param_s { char *name; int *addr; }; -#define dnr_param_t struct dnr_param_s +#define dnr_param_t struct nr_param_s +#define nr4_param_t struct nr_param_s -struct DNR_PRM_s { +struct DNR_PARM_s { int prm_sw_gbs_ctrl; int prm_gbs_vldcntthd; int prm_gbs_cnt_min; @@ -51,11 +52,44 @@ struct DNR_PRM_s { int sw_vbof; int sw_vbof_vld_flg; int sw_vbof_vld_cnt; + int dnr_stat_coef; };/* used for software */ -#define DNR_PRM_t struct DNR_PRM_s -/* software parameters initialization£¬ initializing before used */ -void nr_init(struct device *dev); -void di_nr_init(void); +#define DNR_PRM_t struct DNR_PARM_s +struct NR4_PARM_s { + int prm_nr4_srch_stp; + int sw_nr4_field_sad[2]; + int sw_nr4_scene_change_thd; + int sw_nr4_scene_change_flg[3]; + int sw_nr4_sad2gain_en; + int sw_nr4_sad2gain_lut[16]; + int nr4_debug; + unsigned short width; + unsigned short height; + unsigned short border_offset; +}; + +struct CUE_PARM_s { + int glb_mot_framethr; + int glb_mot_fieldnum; + int glb_mot_fieldthr; + int field_count; + int frame_count; +}; + +struct NR_PARM_s { + unsigned short width; + unsigned short height; + unsigned short frame_count; + bool prog_flag; + struct DNR_PARM_s *pdnr_parm; + struct NR4_PARM_s *pnr4_parm; + struct CUE_PARM_s *pcue_parm; +}; +#ifndef SGN2 +#define SGN2(x) ((x) > 0 ? 1 : ((x) < 0 ? -1 : 0)) +#endif + + int global_bs_calc_sw(int *pGbsVldCnt, int *pGbsVldFlg, int *pGbs, @@ -110,6 +144,14 @@ int ver_blk_ofst_calc_sw(int *pVbOfVldCnt, int prm_vbof_vldcntthd, int nRow, int nCol); -void run_dnr_in_irq(unsigned short nCol, unsigned short nRow); +/* software parameters initialization before used */ +void adaptive_cue_adjust(unsigned int frame_diff, unsigned int field_diff); +void nr_hw_init(void); +void nr_gate_control(bool gate); +void nr_drv_init(struct device *dev); +void nr_drv_uninit(struct device *dev); +void nr_process_in_irq(void); +void nr_all_config(unsigned short nCol, unsigned short nRow, + unsigned short type); #endif diff --git a/drivers/amlogic/media/deinterlace/pulldown_drv.c b/drivers/amlogic/media/deinterlace/pulldown_drv.c new file mode 100644 index 000000000000..f53448897630 --- /dev/null +++ b/drivers/amlogic/media/deinterlace/pulldown_drv.c @@ -0,0 +1,519 @@ +/* + * drivers/amlogic/media/deinterlace/pulldown_drv.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 +#include +#include +#include +#include "deinterlace_hw.h" +#include "deinterlace_dbg.h" + +static unsigned int field_diff_rate; + +static unsigned int flm22_sure_num = 100; +static unsigned int flm22_sure_smnum = 70; +static unsigned int flm22_ratio = 200; +/* 79 for iptv test pd22 ts */ +module_param_named(flm22_ratio, flm22_ratio, uint, 0644); + +static struct sFlmSftPar pd_param; +static struct FlmDectRes dectres; +static struct FlmModReg_t flmreg; + +static void pulldown_mode_init(struct pulldown_detected_s *pd_config) +{ + unsigned int i = 0; + + pd_config->global_mode = + PULL_DOWN_NORMAL; + for (i = 0; i < MAX_VOF_WIN_NUM; i++) { + pd_config->regs[i].win_vs = 0; + pd_config->regs[i].win_ve = 0; + pd_config->regs[i].blend_mode = + PULL_DOWN_NORMAL; + } +} + +static void pulldown_wnd_config(struct pulldown_detected_s *pd_config, + unsigned short **wins) +{ + unsigned int i = 0; + + for (i = 0; i < MAX_VOF_WIN_NUM; i++) { + pd_config->regs[i].win_vs = wins[i][0]; + pd_config->regs[i].win_ve = wins[i][1]; + pd_config->regs[i].blend_mode = wins[i][2]; + } +} + +void pulldown_vof_win_vshift(struct pulldown_detected_s *wins, + unsigned short v_offset) +{ + unsigned int i = 0; + + for (i = 0; i < MAX_VOF_WIN_NUM; i++) { + if (wins->regs[0].win_vs > v_offset) + wins->regs[0].win_vs -= v_offset; + else + wins->regs[0].win_vs = 0; + if (wins->regs[0].win_ve > v_offset) + wins->regs[0].win_ve -= v_offset; + else + wins->regs[0].win_ve = 0; + } +} +static int flag_di_weave = 1; +static unsigned int pldn_mod; + +static unsigned int pldn_cmb0 = 1; +module_param_named(pldn_cmb0, pldn_cmb0, uint, 0644); + +static unsigned int pldn_cmb1; +module_param_named(pldn_cmb1, pldn_cmb1, uint, 0644); + + +/* static unsigned int flmxx_sure_num[7] + * = {50, 50, 50, 50, 50, 50, 50}; + */ +static unsigned int flmxx_sure_num[7] = {20, 20, 20, 20, 20, 20, 20}; +static unsigned int flmxx_snum_adr = 7; +module_param_array(flmxx_sure_num, uint, &flmxx_snum_adr, 0664); + +static unsigned int flm22_glbpxlnum_rat = 4; /* 4/256 = 64 */ + +static unsigned int flm22_glbpxl_maxrow = 16; /* 16/256 = 16 */ +module_param(flm22_glbpxl_maxrow, uint, 0644); +MODULE_PARM_DESC(flm22_glbpxl_maxrow, "flm22_glbpxl_maxrow/n"); + +static unsigned int flm22_glbpxl_minrow = 3; /* 4/256 = 64 */ +module_param(flm22_glbpxl_minrow, uint, 0644); +MODULE_PARM_DESC(flm22_glbpxl_minrow, "flm22_glbpxl_minrow/n"); + +static unsigned int cmb_3point_rnum; +module_param(cmb_3point_rnum, uint, 0644); +MODULE_PARM_DESC(cmb_3point_rnum, "cmb_3point_rnum/n"); + +static unsigned int cmb_3point_rrat = 32; +module_param(cmb_3point_rrat, uint, 0644); +MODULE_PARM_DESC(cmb_3point_rrat, "cmb_3point_rrat/n"); + +unsigned int pulldown_detection(struct pulldown_detected_s *res, + struct combing_status_s *cmb_sts, bool reverse) +{ + unsigned int glb_frame_mot_num, glb_field_mot_num, i; + unsigned int mot_row = 0, mot_max = 0, ntmp = 0; + unsigned int flm22_surenum = flm22_sure_num; + int difflag = 2; + bool flm32 = false, flm22 = false, flmxx = false; + + read_pulldown_info(&glb_frame_mot_num, + &glb_field_mot_num); + + read_new_pulldown_info(&flmreg); + dectres.rF22Flag = FlmVOFSftTop(&(dectres.rCmb32Spcl), + dectres.rPstCYWnds[0], + dectres.rPstCYWnds[1], + dectres.rPstCYWnds[2], + dectres.rPstCYWnds[3], + dectres.rPstCYWnds[4], + &(dectres.rFlmPstGCm), + &(dectres.rFlmSltPre), + &(dectres.rFlmPstMod), + &(dectres.dif01flag), + flmreg.rROFldDif01, + flmreg.rROFrmDif02, + flmreg.rROCmbInf, + glb_frame_mot_num, + glb_field_mot_num, + &cmb_sts->cmb_row_num, + &cmb_sts->frame_diff_avg, + &pd_param, + reverse); + + difflag = dectres.dif01flag; + if (dectres.rFlmPstMod == 1) + difflag = dectres.rFlmSltPre; + if (pd_param.height >= 289) /*full hd */ + cmb_sts->cmb_row_num = cmb_sts->cmb_row_num << 1; + if (cmb_sts->cmb_row_num > pd_param.height) + cmb_sts->cmb_row_num = pd_param.height; + + prt_flg = ((pr_pd >> 1) & 0x1); + if (prt_flg) { + sprintf(debug_str, "#Pst-Dbg:\n"); + sprintf(debug_str + strlen(debug_str), + "Mod=%d, Pre=%d, GCmb=%d, Lvl2=%d\n", + dectres.rFlmPstMod, + dectres.rFlmSltPre, + dectres.rFlmPstGCm, + dectres.rF22Flag); + + sprintf(debug_str + strlen(debug_str), + "N%03d: nd[%d~%d], [%d~%d], [%d~%d], [%d~%d]\n", + cmb_sts->cmb_row_num, + dectres.rPstCYWnds[0][0], + dectres.rPstCYWnds[0][1], + dectres.rPstCYWnds[1][0], + dectres.rPstCYWnds[1][1], + dectres.rPstCYWnds[2][0], + dectres.rPstCYWnds[2][1], + dectres.rPstCYWnds[3][0], + dectres.rPstCYWnds[3][1]); + + pr_info("%s", debug_str); + } + + pulldown_mode_init(res); + if (difflag == 1 && flag_di_weave) + res->global_mode = PULL_DOWN_NORMAL; + else if (difflag == 0 && flag_di_weave == 1) + res->global_mode = PULL_DOWN_NORMAL_2; + + if (dectres.rFlmPstMod == 1) + cmb_sts->like_pulldown22_flag = dectres.rF22Flag; + else + cmb_sts->like_pulldown22_flag = 0; + + if ((pr_pd >> 1) & 0x1) + pr_info("fld_dif_rat=%d\n", + field_diff_rate); + if ((dectres.rF22Flag >= + (cmb_3point_rnum + field_diff_rate)) && + (cmb_sts->cmb_row_num > + (pd_param.height * cmb_3point_rrat >> 8))) { + if ((pr_pd >> 1) & 0x1) + pr_info("coeff-3-point enabled\n"); + } + if (dectres.rFlmPstMod != 0) { + flm32 = (dectres.rFlmPstMod == 2 && + dectres.rFlmPstGCm == 0); + + ntmp = (glb_frame_mot_num + glb_field_mot_num) / + (pd_param.width + 1); + if (flm22_sure_num > ntmp + flm22_sure_smnum) + flm22_surenum = flm22_sure_num - ntmp; + else + flm22_surenum = flm22_sure_smnum; + + if (dectres.rFlmPstMod == 1) { + mot_row = glb_frame_mot_num * + flm22_glbpxlnum_rat / (pd_param.width + 1); + mot_max = (flm22_glbpxl_maxrow * + pd_param.height + 128) >> 8; + if ((pr_pd >> 1) & 0x1) + pr_info("dejaggies level=%3d - (%02d - %02d)\n", + dectres.rF22Flag, + mot_max, mot_row); + + if (mot_row < mot_max) { + if (dectres.rF22Flag > + (mot_max - mot_row)) + dectres.rF22Flag -= + (mot_max - mot_row); + else + dectres.rF22Flag = 0; + + if (mot_row <= flm22_glbpxl_minrow) + dectres.rFlmPstMod = 0; + } + } + + flm22 = (dectres.rFlmPstMod == 1 && + dectres.rF22Flag >= flm22_surenum); + if (dectres.rFlmPstMod >= 4) + flmxx = (dectres.rF22Flag >= + flmxx_sure_num[dectres.rFlmPstMod - 4]); + else + flmxx = 0; + + /* 2-2 force */ + if ((pldn_mod == 0) && + (flm32 || flm22 || flmxx)) { + if (dectres.rFlmSltPre == 1) + res->global_mode = + PULL_DOWN_BLEND_0; + else { + res->global_mode = + PULL_DOWN_BLEND_2; + } + } else if (pldn_mod == 1) { + if (dectres.rFlmSltPre == 1) + res->global_mode = + PULL_DOWN_BLEND_0; + else + res->global_mode = + PULL_DOWN_BLEND_2; + } else { + if (difflag == 1 && flag_di_weave) { + res->global_mode + = PULL_DOWN_NORMAL; + } else if (difflag == 0 && + flag_di_weave) { + res->global_mode + = PULL_DOWN_NORMAL_2; + } else { + res->global_mode + = PULL_DOWN_NORMAL; + } + } + + if (flm32 && (pldn_cmb0 == 1)) { + pulldown_wnd_config(res, + (unsigned short **)dectres.rPstCYWnds); + } else if (dectres.rF22Flag > 1 && + dectres.rFlmPstMod == 1 && + pldn_cmb0 == 1) { + if ((pr_pd >> 1) & 0x1) + pr_info("dejaggies level= %3d\n", + dectres.rF22Flag); + } else if (dectres.rFlmPstGCm == 0 && + pldn_cmb0 > 1 && pldn_cmb0 <= 5) { + pulldown_wnd_config(res, + (unsigned short **)dectres.rPstCYWnds); + /* 1-->only film-mode + * 2-->windows-->mtn + * 3-->windows-->detected + * 4-->windows-->di + */ + /* pldn_cmb0 == 2 + * setting in pulldown wnd config + */ + if (pldn_cmb0 == 3) { + for (i = 0; i < MAX_VOF_WIN_NUM; i++) + res->regs[i].blend_mode = 3; + } else if (pldn_cmb0 == 4) { + for (i = 0; i < MAX_VOF_WIN_NUM; i++) + res->regs[i].blend_mode = 2; + } else if (pldn_cmb0 == 5) { + res->regs[3].win_vs = 0; + res->regs[3].win_ve = 60; + res->regs[3].blend_mode = 0; + } + } + /* else pldn_cmb0==0 (Nothing) */ + if ((dectres.rFlmPstGCm == 1) && (pldn_cmb1 > 0) + && (pldn_cmb1 <= 5)) { + pulldown_wnd_config(res, + (unsigned short **)dectres.rPstCYWnds); + /* + * 1-->normal set in pulldown + * wnd config func + */ + if (pldn_cmb1 == 2) { + for (i = 0; i < MAX_VOF_WIN_NUM; i++) + res->regs[i].blend_mode = 3; + } else if (pldn_cmb1 == 3) { + for (i = 0; i < MAX_VOF_WIN_NUM; i++) + res->regs[i].blend_mode = 2; + } else if (pldn_cmb1 == 4) { + res->regs[2].win_vs = 202; + res->regs[2].win_ve = 222; + res->regs[2].blend_mode = 0; + } + } else if ((pldn_cmb0 == 6) && (pldn_cmb1 == 6)) { + res->regs[1].win_vs = 60; + res->regs[1].win_ve = 180; + res->regs[1].blend_mode = 0; + } + } + return 0; +} + +unsigned char pulldown_init(unsigned short width, unsigned short height) +{ + flm22_sure_num = (height * 100)/480; + flm22_sure_smnum = (flm22_sure_num * flm22_ratio)/100; + pd_param.width = width; + pd_param.height = height; + pd_param.field_count = 0; + return FlmVOFSftInt(&pd_param); +} + +struct pd_param_s { + char *name; + int *addr; +}; + +static struct pd_param_s pd_params[] = { + { "sFrmDifAvgRat", + &(pd_param.sFrmDifAvgRat)}, + { "sFrmDifLgTDif", + &(pd_param.sFrmDifLgTDif) }, + { "sF32StpWgt01", + &(pd_param.sF32StpWgt01) }, + { "sF32StpWgt02", + &(pd_param.sF32StpWgt02) }, + { "sF32DifLgRat", + &(pd_param.sF32DifLgRat) }, + { "sFlm2MinAlpha", + &(pd_param.sFlm2MinAlpha) }, + { "sFlm2MinBelta", + &(pd_param.sFlm2MinBelta) }, + { "sFlm20ftAlpha", + &(pd_param.sFlm20ftAlpha) }, + { "sFlm2LgDifThd", + &(pd_param.sFlm2LgDifThd) }, + { "sFlm2LgFlgThd", + &(pd_param.sFlm2LgFlgThd) }, + { "sF32Dif01A1", + &(pd_param.sF32Dif01A1) }, + { "sF32Dif01T1", + &(pd_param.sF32Dif01T1) }, + { "sF32Dif01A2", + &(pd_param.sF32Dif01A2) }, + { "sF32Dif01T2", + &(pd_param.sF32Dif01T2) }, + { "rCmbRwMinCt0", + &(pd_param.rCmbRwMinCt0) }, + { "rCmbRwMinCt1", + &(pd_param.rCmbRwMinCt1) }, + { "mPstDlyPre", + &(pd_param.mPstDlyPre) }, + { "mNxtDlySft", + &(pd_param.mNxtDlySft) }, + { "cmb22_nocmb_num", + &(pd_param.cmb22_nocmb_num)}, + { "flm22_en", + &(pd_param.flm22_en) }, + { "flm32_en", + &(pd_param.flm32_en) }, + { "flm22_flag", + &(pd_param.flm22_flag) }, + { "flm2224_flag", + &(pd_param.flm2224_flag) }, + { "flm22_comlev", + &(pd_param.flm22_comlev) }, + { "flm22_comlev1", + &(pd_param.flm22_comlev1) }, + { "flm22_comnum", + &(pd_param.flm22_comnum) }, + { "flm22_comth", + &(pd_param.flm22_comth) }, + { "flm22_dif01_avgth", + &(pd_param.flm22_dif01_avgth) }, + { "dif01rate", + &(pd_param.dif01rate) }, + { "flag_di01th", + &(pd_param.flag_di01th) }, + { "numthd", + &(pd_param.numthd) }, + { "sF32Dif02M0", + &(pd_param.sF32Dif02M0) }, /* mpeg-4096, cvbs-8192 */ + { "sF32Dif02M1", + &(pd_param.sF32Dif02M1) }, /* mpeg-4096, cvbs-8192 */ + { "", NULL } +}; + +static ssize_t pd_parm_store(struct device *dev, + struct device_attribute *attr, const char *buff, + size_t count) +{ + int i = 0; + int value = 0; + int rc = 0; + char *parm[2] = { NULL }, *buf_orig; + + buf_orig = kstrdup(buff, GFP_KERNEL); + parse_cmd_params(buf_orig, (char **)(&parm)); + for (i = 0; pd_params[i].addr; i++) { + if (!strcmp(parm[0], pd_params[i].name)) { + rc = kstrtoint(parm[1], 10, &value); + *(pd_params[i].addr) = value; + pr_dbg("%s=%d.\n", pd_params[i].name, value); + } + } + + return count; +} + +static ssize_t pd_parm_show(struct device *dev, + struct device_attribute *attr, char *buff) +{ + ssize_t len = 0; + int i = 0; + + for (i = 0; pd_params[i].addr; i++) { + len += sprintf(buff + len, "%s=%d.\n", + pd_params[i].name, *pd_params[i].addr); + } + + len += sprintf(buff + len, "\npulldown detection result:\n"); + len += sprintf(buff + len, "rPstCYWnd0 s=%u.\n", + dectres.rPstCYWnds[0][0]); + len += sprintf(buff + len, "rPstCYWnd0 e=%u.\n", + dectres.rPstCYWnds[0][1]); + len += sprintf(buff + len, "rPstCYWnd0 b=%u.\n", + dectres.rPstCYWnds[0][2]); + + len += sprintf(buff + len, "rPstCYWnd1 s=%u.\n", + dectres.rPstCYWnds[1][0]); + len += sprintf(buff + len, "rPstCYWnd1 e=%u.\n", + dectres.rPstCYWnds[1][1]); + len += sprintf(buff + len, "rPstCYWnd1 b=%u.\n", + dectres.rPstCYWnds[1][2]); + + len += sprintf(buff + len, "rPstCYWnd2 s=%u.\n", + dectres.rPstCYWnds[2][0]); + len += sprintf(buff + len, "rPstCYWnd2 e=%u.\n", + dectres.rPstCYWnds[2][1]); + len += sprintf(buff + len, "rPstCYWnd2 b=%u.\n", + dectres.rPstCYWnds[2][2]); + + len += sprintf(buff + len, "rPstCYWnd3 s=%u.\n", + dectres.rPstCYWnds[3][0]); + len += sprintf(buff + len, "rPstCYWnd3 e=%u.\n", + dectres.rPstCYWnds[3][1]); + len += sprintf(buff + len, "rPstCYWnd3 b=%u.\n", + dectres.rPstCYWnds[3][2]); + + len += sprintf(buff + len, "rPstCYWnd4 s=%u.\n", + dectres.rPstCYWnds[4][0]); + len += sprintf(buff + len, "rPstCYWnd4 e=%u.\n", + dectres.rPstCYWnds[4][1]); + len += sprintf(buff + len, "rPstCYWnd4 b=%u.\n", + dectres.rPstCYWnds[4][2]); + + len += sprintf(buff + len, "rFlmPstGCm=%u.\n", + dectres.rFlmPstGCm); + len += sprintf(buff + len, "rFlmSltPre=%u.\n", + dectres.rFlmSltPre); + len += sprintf(buff + len, "rFlmPstMod=%d.\n", + dectres.rFlmPstMod); + len += sprintf(buff + len, "rFlmPstMod=%d.\n", + dectres.dif01flag); + len += sprintf(buff + len, "rF22Flag=%d.\n", + dectres.rF22Flag); + return len; +} + +static DEVICE_ATTR(pd_param, 0664, pd_parm_show, pd_parm_store); + +void pd_device_files_add(struct device *dev) +{ + device_create_file(dev, &dev_attr_pd_param); + +} + +void pd_device_files_del(struct device *dev) +{ + device_create_file(dev, &dev_attr_pd_param); +} +#ifdef DEBUG_SUPPORT +module_param_named(flm22_sure_num, flm22_sure_num, uint, 0644); +module_param_named(flm22_glbpxlnum_rat, flm22_glbpxlnum_rat, uint, 0644); +module_param_named(flag_di_weave, flag_di_weave, int, 0644); +#endif diff --git a/drivers/amlogic/media/deinterlace/pulldown_drv.h b/drivers/amlogic/media/deinterlace/pulldown_drv.h new file mode 100644 index 000000000000..912119bc78f8 --- /dev/null +++ b/drivers/amlogic/media/deinterlace/pulldown_drv.h @@ -0,0 +1,57 @@ +/* + * drivers/amlogic/media/deinterlace/pulldown_drv.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#ifndef _DI_PULLDOWN_H +#define _DI_PULLDOWN_H +#include "film_mode_fmw/film_vof_soft.h" +#include "deinterlace_mtn.h" + +#define MAX_VOF_WIN_NUM 4 + +enum pulldown_mode_e { + PULL_DOWN_BLEND_0 = 0,/* buf1=dup[0] */ + PULL_DOWN_BLEND_2 = 1,/* buf1=dup[2] */ + PULL_DOWN_MTN = 2,/* mtn only */ + PULL_DOWN_BUF1 = 3,/* do wave with dup[0] */ + PULL_DOWN_EI = 4,/* ei only */ + PULL_DOWN_NORMAL = 5,/* normal di */ + PULL_DOWN_NORMAL_2 = 6,/* di */ +}; + +struct pulldown_vof_win_s { + unsigned short win_vs; + unsigned short win_ve; + enum pulldown_mode_e blend_mode; +}; + +struct pulldown_detected_s { + enum pulldown_mode_e global_mode; + struct pulldown_vof_win_s regs[4]; +}; + +unsigned char pulldown_init(unsigned short width, unsigned short height); + +unsigned int pulldown_detection(struct pulldown_detected_s *res, + struct combing_status_s *cmb_sts, bool reverse); + +void pulldown_vof_win_vshift(struct pulldown_detected_s *wins, + unsigned short v_offset); + +void pd_device_files_add(struct device *dev); + +void pd_device_files_del(struct device *dev); +#endif diff --git a/drivers/amlogic/media/deinterlace/register.h b/drivers/amlogic/media/deinterlace/register.h index 08c4193e2c9a..ebb6b4888cd2 100644 --- a/drivers/amlogic/media/deinterlace/register.h +++ b/drivers/amlogic/media/deinterlace/register.h @@ -17,6 +17,7 @@ #ifndef __MACH_DEINTERLACE_REG_ADDR_H_ #define __MACH_DEINTERLACE_REG_ADDR_H_ +#include #define Wr(adr, val) aml_write_vcbus(adr, val) #define Rd(adr) aml_read_vcbus(adr) @@ -31,6 +32,13 @@ unsigned int RDMA_WR_BITS(unsigned int adr, unsigned int val, unsigned int start, unsigned int len); unsigned int RDMA_RD_BITS(unsigned int adr, unsigned int start, unsigned int len); +void DI_Wr(unsigned int addr, unsigned int val); +void DI_Wr_reg_bits(unsigned int adr, unsigned int val, + unsigned int start, unsigned int len); +void DI_VSYNC_WR_MPEG_REG(unsigned int addr, unsigned int val); +void DI_VSYNC_WR_MPEG_REG_BITS(unsigned int addr, + unsigned int val, unsigned int start, unsigned int len); + #define VPU_WRARB_REQEN_SLV_L1C1 ((0x2795)) /* << 2) + 0xd0100000) */ #define VPU_ARB_DBG_STAT_L1C1 ((0x27b4)) /* << 2) + 0xd0100000) */ #define SRSHARP0_SHARP_SR2_CTRL ((0x3257)) /* << 2) + 0xd0100000) */ @@ -152,17 +160,9 @@ unsigned int RDMA_RD_BITS(unsigned int adr, unsigned int start, * Bit 7:0 Write luma canvas address */ /* timerc */ -#define ISA_TIMER_MUX 0x2650 - /* 0xc1109940 */ -#define ISA_TIMERC 0x2653 - /* 0xc110994c */ -#define ISA_TIMERE 0x2655 - /* 0xc1109954 */ /* vd1 */ -#define VD1_IF0_LUMA_FIFO_SIZE 0x1a63 - /* 0xd010698c */ -#define VD2_IF0_LUMA_FIFO_SIZE 0x1a83 - /* 0xd0106a0c */ +#define VD1_IF0_GEN_REG 0x1a50 + #define VD1_IF0_CANVAS0 0x1a51 /* 0xd0106944 */ #define VD1_IF0_CANVAS1 0x1a52 @@ -175,11 +175,50 @@ unsigned int RDMA_RD_BITS(unsigned int adr, unsigned int start, /* 0xd0106954 */ #define VD1_IF0_CHROMA_Y0 0x1a56 /* 0xd0106958 */ +#define VD1_IF0_LUMA_X1 0x1a57 + +#define VD1_IF0_LUMA_Y1 0x1a58 + +#define VD1_IF0_CHROMA_X1 0x1a59 + +#define VD1_IF0_CHROMA_Y1 0x1a5a + #define VD1_IF0_RPT_LOOP 0x1a5b - /* 0xd010696c */ -#define VD1_IF0_LUMA0_RPT_PAT 0x1a5c - /* 0xd0106970 */ -#define VD1_IF0_CHROMA0_RPT_PAT 0x1a5d + +#define VD1_IF0_LUMA0_RPT_PAT 0x1a5c + +#define VD1_IF0_CHROMA0_RPT_PAT 0x1a5d + +#define VD1_IF0_LUMA1_RPT_PAT 0x1a5e + +#define VD1_IF0_CHROMA1_RPT_PAT 0x1a5f + +#define VD1_IF0_LUMA_PSEL 0x1a60 + +#define VD1_IF0_CHROMA_PSEL 0x1a61 + +#define VD1_IF0_DUMMY_PIXEL 0x1a62 + +#define VD1_IF0_LUMA_FIFO_SIZE 0x1a63 + +#define VD1_IF0_RANGE_MAP_Y 0x1a6a + +#define VD1_IF0_RANGE_MAP_CB 0x1a6b + +#define VD1_IF0_RANGE_MAP_CR 0x1a6c + +#define VD1_IF0_GEN_REG2 0x1a6d + +#define VD1_IF0_PROT_CNTL 0x1a6e + +#define VIU_VD1_FMT_CTRL 0x1a68 + +#define VIU_VD1_FMT_W 0x1a69 + +#define VD1_IF0_LUMA_FIFO_SIZE 0x1a63 + /* 0xd010698c */ +#define VD2_IF0_LUMA_FIFO_SIZE 0x1a83 + /* 0xd0106a0c */ /* 0xd0106974 */ #define VIU_OSD1_CTRL_STAT 0x1a10 /* 0xd0106840 */ @@ -322,7 +361,10 @@ unsigned int RDMA_RD_BITS(unsigned int adr, unsigned int start, /* 0xd0106818 */ #define VIUB_MISC_CTRL0 0x2006 /* 0xd0108018 */ -/* txl new add begin */ +#define VIUB_GCLK_CTRL0 0x2007 +#define VIUB_GCLK_CTRL1 0x2008 +#define VIUB_GCLK_CTRL2 0x2009 +#define VIUB_GCLK_CTRL3 0x200a #define DI_IF2_GEN_REG 0x2010 #define DI_IF2_CANVAS0 0x2011 #define DI_IF2_LUMA_X0 0x2012 @@ -1384,6 +1426,19 @@ unsigned int RDMA_RD_BITS(unsigned int adr, unsigned int start, /* Bit 7: 0, reg_CUE_CON_difP1_thrd2 U8, P1 field Intra-Field top/below line * chroma difference threshold (tighter), */ +/* change from txlx */ +#define DI_EI_DRT_CTRL ((0x1778)) + +#define DI_EI_DRT_PIXTH ((0x1779)) + +#define DI_EI_DRT_CORRPIXTH ((0x177a)) + +#define DI_EI_DRT_RECTG_WAVE ((0x177b)) + +#define DI_EI_DRT_PIX_DIFFTH ((0x177c)) + +#define DI_EI_DRT_UNBITREND_TH ((0x177d)) + #define NR2_CUE_PRG_DIF ((0x177e)) /* << 2) + 0xd0100000) */ /* Bit 20, reg_CUE_PRG_Enable Enable bit for progressive video CUE * detection.If interlace input video, @@ -1408,6 +1463,17 @@ unsigned int RDMA_RD_BITS(unsigned int adr, unsigned int start, /* // NR2 REG DEFINE END //// */ /* // DET 3D REG DEFINE BEGIN //// */ /* // 8'h80~8'h8f */ +#define DI_EI_DRT_CTRL_GXLX ((0x2028)) + +#define DI_EI_DRT_PIXTH_GXLX ((0x2029)) + +#define DI_EI_DRT_CORRPIXTH_GXLX ((0x202a)) + +#define DI_EI_DRT_RECTG_WAVE_GXLX ((0x202b)) + +#define DI_EI_DRT_PIX_DIFFTH_GXLX ((0x202c)) + +#define DI_EI_DRT_UNBITREND_TH_GXLX ((0x202d)) #define DET3D_RO_SPLT_HB ((0x1780)) /* << 2) + 0xd0100000) */ /* Bit 24, RO_Det3D_Split_HB_valid * U1 horizontal LR split border detected valid signal for top half picture @@ -2667,6 +2733,7 @@ unsigned int RDMA_RD_BITS(unsigned int adr, unsigned int start, #define MCDI_PD_22_CHK_WND0_Y (0x2f5a) #define MCDI_PD_22_CHK_WND1_X (0x2f5b) #define MCDI_PD_22_CHK_WND1_Y (0x2f5c) +#define MCDI_PD_22_CHK_FLG_CNT (0x2f5e) /* mc di */ /* //=================================================================//// */ /* // memc di core 0 */ @@ -4013,6 +4080,10 @@ unsigned int RDMA_RD_BITS(unsigned int adr, unsigned int start, #define MCDI_MCVECRD_CANVAS_SIZE ((0x2f66)) #define MCDI_MCINFOWR_CANVAS_SIZE ((0x2f67)) #define MCDI_MCINFORD_CANVAS_SIZE ((0x2f68)) +#define MCDI_LMVLCKSTEXT_0 ((0x2f69)) +#define MCDI_LMVLCKSTEXT_1 ((0x2f6a)) +#define MCDI_LMVLCKEDEXT_0 ((0x2f6b)) +#define MCDI_LMVLCKEDEXT_1 ((0x2f6c)) #define MCDI_MCVECWR_X ((0x2f92)) #define MCDI_MCVECWR_Y ((0x2f93)) #define MCDI_MCVECWR_CTRL ((0x2f94)) @@ -4491,6 +4562,7 @@ unsigned int RDMA_RD_BITS(unsigned int adr, unsigned int start, #define DIPD_RO_COMB_18 0x2fe8 #define DIPD_RO_COMB_19 0x2fe9 #define DIPD_RO_COMB_20 0x2fea +#define DIPD_COMB_CTRL6 0x2feb /* nr3 */ #define NR3_MODE 0x2ff0 /* d010bfc0 */ diff --git a/drivers/amlogic/media/deinterlace/register_nr4.h b/drivers/amlogic/media/deinterlace/register_nr4.h new file mode 100644 index 000000000000..23e03f3bf2cf --- /dev/null +++ b/drivers/amlogic/media/deinterlace/register_nr4.h @@ -0,0 +1,149 @@ +/* + * drivers/amlogic/media/deinterlace/register_nr4.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +#define NR4_DRT_CTRL ((0x2da4)) +#define NR4_DRT_YSAD_GAIN ((0x2da5)) +#define NR4_DRT_CSAD_GAIN ((0x2da6)) +#define NR4_DRT_SAD_ALP_CORE ((0x2da7)) +#define NR4_DRT_ALP_MINMAX ((0x2da8)) +#define NR4_SNR_CTRL_REG ((0x2da9)) +#define NR4_SNR_ALPHA0_MAX_MIN ((0x2daa)) +#define NR4_ALP0C_ERR2CURV_LIMIT0 ((0x2dab)) +#define NR4_ALP0C_ERR2CURV_LIMIT1 ((0x2dac)) +#define NR4_ALP0Y_ERR2CURV_LIMIT0 ((0x2dad)) +#define NR4_ALP0Y_ERR2CURV_LIMIT1 ((0x2dae)) +#define NR4_SNR_ALPA1_RATE_AND_OFST ((0x2daf)) +#define NR4_SNR_ALPHA1_MAX_MIN ((0x2db0)) +#define NR4_ALP1C_ERR2CURV_LIMIT0 ((0x2db1)) +#define NR4_ALP1C_ERR2CURV_LIMIT1 ((0x2db2)) +#define NR4_ALP1Y_ERR2CURV_LIMIT0 ((0x2db3)) +#define NR4_ALP1Y_ERR2CURV_LIMIT1 ((0x2db4)) +#define NR4_MTN_CTRL ((0x2db5)) +#define NR4_MTN_REF_PAR0 ((0x2db6)) +#define NR4_MTN_REF_PAR1 ((0x2db7)) +#define NR4_MCNR_LUMA_ENH_CTRL ((0x2db8)) +#define NR4_MCNR_LUMA_STAT_LIMTX ((0x2db9)) +#define NR4_MCNR_LUMA_STAT_LIMTY ((0x2dba)) +#define NR4_MCNR_LUMA_DIF_CALC ((0x2dbb)) +#define NR4_MCNR_LUMAPRE_CAL_PRAM ((0x2dbc)) +#define NR4_MCNR_LUMACUR_CAL_PRAM ((0x2dbd)) +#define NR4_MCNR_MV_CTRL_REG ((0x2dbe)) +#define NR4_MCNR_MV_GAIN0 ((0x2dbf)) +#define NR4_MCNR_LMV_PARM ((0x2dc0)) +#define NR4_MCNR_ALP0_REG (0x2dc1) +#define NR4_MCNR_ALP1_AND_BET0_REG (0x2dc2) +#define NR4_MCNR_BET1_AND_BET2_REG (0x2dc3) +#define NR4_MCNR_AC_DC_CRTL (0x2dc4) +#define NR4_MCNR_CM_CTRL0 (0x2dc5) +#define NR4_MCNR_CM_PRAM (0x2dc6) +#define NR4_MCNR_CM_RSHFT_ALP0 (0x2dc7) +#define NR4_MCNR_BLUE_CENT (0x2dc8) +#define NR4_MCNR_BLUE_GAIN_PAR0 (0x2dc9) +#define NR4_MCNR_BLUE_GAIN_PAR1 (0x2dca) +#define NR4_MCNR_CM_BLUE_CLIP0 (0x2dcb) +#define NR4_MCNR_CM_BLUE_CLIP1 (0x2dcc) +#define NR4_MCNR_GREEN_CENT (0x2dcd) +#define NR4_MCNR_GREEN_GAIN_PAR0 (0x2dce) +#define NR4_MCNR_GREEN_GAIN_PAR1 (0x2dcf) +#define NR4_MCNR_GREEN_CLIP0 (0x2dd0) +#define NR4_MCNR_GREEN_CLIP2 (0x2dd1) +#define NR4_MCNR_SKIN_CENT (0x2dd2) +#define NR4_MCNR_SKIN_GAIN_PAR0 (0x2dd3) +#define NR4_MCNR_SKIN_GAIN_PAR1 (0x2dd4) +#define NR4_MCNR_SKIN_CLIP0 (0x2dd5) +#define NR4_MCNR_SKIN_CLIP1 (0x2dd6) +#define NR4_MCNR_ALP1_GLB_CTRL (0x2dd7) +#define NR4_MCNR_DC2NORM_LUT0 (0x2dd8) +#define NR4_MCNR_DC2NORM_LUT1 (0x2dd9) +#define NR4_MCNR_DC2NORM_LUT2 (0x2dda) +#define NR4_MCNR_AC2NORM_LUT0 (0x2ddb) +#define NR4_MCNR_AC2NORM_LUT1 (0x2ddc) +#define NR4_MCNR_AC2NORM_LUT2 (0x2ddd) +#define NR4_MCNR_SAD2ALP0_LUT0 (0x2dde) +#define NR4_MCNR_SAD2ALP0_LUT1 (0x2ddf) +#define NR4_MCNR_SAD2ALP0_LUT2 (0x2de0) +#define NR4_MCNR_SAD2ALP0_LUT3 (0x2de1) +#define NR4_MCNR_SAD2ALP1_LUT0 (0x2de2) +#define NR4_MCNR_SAD2ALP1_LUT1 (0x2de3) +#define NR4_MCNR_SAD2ALP1_LUT2 (0x2de4) +#define NR4_MCNR_SAD2ALP1_LUT3 (0x2de5) +#define NR4_MCNR_SAD2BET0_LUT0 (0x2de6) +#define NR4_MCNR_SAD2BET0_LUT1 (0x2de7) +#define NR4_MCNR_SAD2BET0_LUT2 (0x2de8) +#define NR4_MCNR_SAD2BET0_LUT3 (0x2de9) +#define NR4_MCNR_SAD2BET1_LUT0 (0x2dea) +#define NR4_MCNR_SAD2BET1_LUT1 (0x2deb) +#define NR4_MCNR_SAD2BET1_LUT2 (0x2dec) +#define NR4_MCNR_SAD2BET1_LUT3 (0x2ded) +#define NR4_MCNR_SAD2BET2_LUT0 (0x2dee) +#define NR4_MCNR_SAD2BET2_LUT1 (0x2def) +#define NR4_MCNR_SAD2BET2_LUT2 (0x2df0) +#define NR4_MCNR_SAD2BET2_LUT3 (0x2df1) +#define NR4_MCNR_RO_U_SUM (0x2df2) +#define NR4_MCNR_RO_V_SUM (0x2df3) +#define NR4_MCNR_RO_GRDU_SUM (0x2df4) +#define NR4_MCNR_RO_GRDV_SUM (0x2df5) +#define NR4_TOP_CTRL (0x2dff) +#define NR4_MCNR_SAD_GAIN (0x3700) +#define NR4_MCNR_LPF_CTRL (0x3701) +#define NR4_MCNR_BLD_VS3LUT0 (0x3702) +#define NR4_MCNR_BLD_VS3LUT1 (0x3703) +#define NR4_MCNR_BLD_VS3LUT2 (0x3704) +#define NR4_MCNR_BLD_VS2LUT0 (0x3705) +#define NR4_MCNR_BLD_VS2LUT1 (0x3706) +#define NR4_COEFBLT_LUT10 (0x3707) +#define NR4_COEFBLT_LUT11 (0x3708) +#define NR4_COEFBLT_LUT12 (0x3709) +#define NR4_COEFBLT_LUT20 (0x370a) +#define NR4_COEFBLT_LUT21 (0x370b) +#define NR4_COEFBLT_LUT22 (0x370c) +#define NR4_COEFBLT_LUT30 (0x370d) +#define NR4_COEFBLT_LUT31 (0x370e) +#define NR4_COEFBLT_LUT32 (0x370f) +#define NR4_COEFBLT_CONV (0x3710) +#define NR4_DBGWIN_YX0 (0x3711) +#define NR4_DBGWIN_YX1 (0x3712) +#define NR4_NM_X_CFG (0x3713) +#define NR4_NM_Y_CFG (0x3714) +#define NR4_NM_SAD_THD (0x3715) +#define NR4_MCNR_BANDSPLIT_PRAM (0x3716) +#define NR4_MCNR_ALP1_SGN_COR (0x3717) +#define NR4_MCNR_ALP1_SGN_PRAM (0x3718) +#define NR4_MCNR_ALP1_MVX_LUT1 (0x3719) +#define NR4_MCNR_ALP1_MVX_LUT2 (0x371a) +#define NR4_MCNR_ALP1_MVX_LUT3 (0x371b) +#define NR4_MCNR_ALP1_LP_PRAM (0x371c) +#define NR4_MCNR_ALP1_SGN_LUT1 (0x371d) +#define NR4_MCNR_ALP1_SGN_LUT2 (0x371e) +#define NR4_RO_NM_SAD_SUM (0x371f) +#define NR4_RO_NM_SAD_CNT (0x3720) +#define NR4_RO_NM_VAR_SUM (0x3721) +#define NR4_RO_NM_VAR_SCNT (0x3722) +#define NR4_RO_NM_VAR_MIN_MAX (0x3723) +#define NR4_RO_NR4_DBGPIX_NUM (0x3724) +#define NR4_RO_NR4_BLDVS2_SUM (0x3725) +#define NR4_BLDVS3_SUM (0x3726) +#define NR4_COEF12_SUM (0x3727) +#define NR4_COEF123_SUM (0x3728) +#define NR_DB_FLT_CTRL (0x3738) +#define NR_DB_FLT_YC_THRD (0x3739) +#define NR_DB_FLT_RANDLUT (0x373a) +#define NR_DB_FLT_PXI_THRD (0x373b) +#define NR_DB_FLT_SEED_Y (0x373c) +#define NR_DB_FLT_SEED_V (0x373e) +#define NR_DB_FLT_SEED3 (0x373f) +#define LBUF_TOP_CTRL (0x2fff) diff --git a/drivers/amlogic/media/deinterlace/tffbff_check.c b/drivers/amlogic/media/deinterlace/tffbff_check.c deleted file mode 100644 index 135c7ded9876..000000000000 --- a/drivers/amlogic/media/deinterlace/tffbff_check.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * drivers/amlogic/media/deinterlace/tffbff_check.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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 -#include -#include "deinterlace.h" -#include "register.h" - -/* define the length of history */ -#define TBFF_DLEN 20 - -/* parameters */ -/* valid data: only pixel_num > size*rat >> 8 */ -/* u8: [0,255] */ -static int tbff_pixel_minnum = 16; - -/* x3 / row > rat */ -/* => x3 > (row * rat >> 5) */ -/* u10: [0 ~ 1023] => [0, 16] */ -static int tbff_x3_minrow = 64; - -/* m1/p1/m2/p2 changing 0/1/0/1... as 2-2 mode */ -/* (max)/ min > (rat): define it max, else min */ -/* u8: [0,31] */ -static int tbff_mp_lgrat[4] = {16, 16, 16, 16}; - -/* tbff check length */ -/* [0, 31] */ -static int tbff_chk_len[4] = {4, 4, 4, 4}; - -static int calc_tbff_pixel_minnum = 16; -static int calc_tbff_x3_minrow = 64; -static int calc_tbff_mp_lgrat[4] = {16, 16, 16, 16}; - -static int nTmp0; -static bool tbff_pr, tffbff_en = true; -static int mode_count; - -void tbff_init(void) -{ - int i = 0; - - mode_count = 0; - calc_tbff_pixel_minnum = tbff_pixel_minnum; - calc_tbff_x3_minrow = tbff_x3_minrow; - for (i = 0; i < 4; i++) - calc_tbff_mp_lgrat[i] = tbff_mp_lgrat[i]; -} -static int tbff_get_rate(int t0, int t1) -{ - int nmax = t1; - int nmin = t0; - int nrst = 0; - - if (t0 > t1) { - nmax = t0; - nmin = t1; - } - - nrst = (8 * nmax) + (nmin >> 1); - nrst /= (nmin+1); - if (nrst > 31) - nrst = 31; - - if (nmax == t1) /* current is small */ - nrst = 0; - - return nrst; -} - -static int tbff_get_minrate(int *pLen) -{ - int iT0 = 0; - int aTLn[4] = {0, 0, 0, 0}; - int nrst = 255; - - int nP0 = pLen[TBFF_DLEN - 1]; - int nP1 = pLen[TBFF_DLEN - 2]; - - if (nP0 < nP1) { - for (iT0 = 0; iT0 < 4; (iT0 += 2)) { - aTLn[iT0] = 31 - pLen[TBFF_DLEN - iT0 - 1]; - aTLn[iT0 + 1] = pLen[TBFF_DLEN - iT0 - 2]; - } - } else { - for (iT0 = 0; iT0 < 4; (iT0 += 2)) { - aTLn[iT0] = pLen[TBFF_DLEN - iT0 - 1]; - aTLn[iT0 + 1] = 31 - pLen[TBFF_DLEN - iT0 - 2]; - } - } - - for (iT0 = 0; iT0 < 4; iT0++) { - if (aTLn[iT0] < nrst) - nrst = aTLn[iT0]; - } - - return nrst; -} - -/* update param according to detection count */ -static void calc_tbff_param(int mode_cnt, int step_max) -{ - int delt_num, delt_row, delt_lgrat, i; - - delt_num = tbff_pixel_minnum - 4; - delt_row = tbff_x3_minrow; - delt_lgrat = tbff_mp_lgrat[0] - 6; - - calc_tbff_pixel_minnum = - tbff_pixel_minnum - (delt_num * mode_cnt)/step_max; - calc_tbff_x3_minrow = tbff_x3_minrow - (delt_row * mode_cnt)/step_max; - calc_tbff_mp_lgrat[0] = - tbff_mp_lgrat[0] - (delt_lgrat * mode_cnt)/step_max; - - for (i = 1; i < 4; i++) - calc_tbff_mp_lgrat[i] = calc_tbff_mp_lgrat[0]; -} -/* TFF / BFF error check */ -/* polar3[0]: num of pixels */ -/* polar3[1]: smooth motion vector */ -/* polar3[2]: m1 */ -/* polar3[3]: p1 */ -/* polar3[4]: m2 */ -/* polar3[5]: p2 */ -/* polar3[6]: x3 */ - -int tff_bff_check(int nROW, int nCOL) -{ - int iT0 = 0, iT1 = 0, nTmp1 = 0; - int nTmp2 = 0, tbfalse = 0, nSIZE = nROW * nCOL; - /* int nMin0 = 0; */ - unsigned int uTp0 = 0; - - int polar3[7]; - /* top/bot field first error */ - static int pPolar3[7]; /* previous polar3 */ - static int sDat[4][TBFF_DLEN]; /* history infor */ - static unsigned int stc_pp3[4]; - - for (iT0 = 0; iT0 < 7; iT0++) - polar3[iT0] = Rd_reg_bits(NR2_RO_POLAR3_NUMOFPIX+iT0, 0, 24); - - if (tbff_pr) - pr_info("polar3=%8d %8d %8d %8d %8d %8d %8d.\n", - polar3[0], polar3[1], polar3[2], polar3[3], - polar3[4], polar3[5], polar3[6]); - /* history */ - for (iT0 = 0; iT0 < 4; iT0++) { - for (iT1 = 0; iT1 < (TBFF_DLEN - 1); iT1++) - sDat[iT0][iT1] = sDat[iT0][iT1 + 1]; - - stc_pp3[iT0] = (stc_pp3[iT0] << 1); - sDat[iT0][TBFF_DLEN - 1] = 0; - } - - /* only valid pixel is enough */ - nTmp0 = ((nSIZE * calc_tbff_pixel_minnum + 128) >> 8); - if (polar3[0] > nTmp0) { - /* only x3 pixel is enough */ - nTmp1 = ((nROW * calc_tbff_x3_minrow + 16) >> 5); - if (polar3[6] > nTmp1) { - /* nMin0 = 255; */ - for (iT1 = 0; iT1 < 4; iT1++) { - nTmp2 = - tbff_get_rate(polar3[iT1 + 2], pPolar3[iT1 + 2]); - sDat[iT1][TBFF_DLEN - 1] = nTmp2; - } - } - } - - for (iT1 = 0; iT1 < 4; iT1++) { - nTmp2 = tbff_get_minrate(sDat[iT1]); - if (nTmp2 >= calc_tbff_mp_lgrat[iT1]) - stc_pp3[iT1] |= 0x1; - } - - for (iT1 = 0; iT1 < 4; iT1++) { - uTp0 = stc_pp3[iT1]; - nTmp0 = 0; - for (iT0 = 0; iT0 < 31; iT0++) { - if (uTp0 & 0x1) - nTmp0++; - else - break; - uTp0 = (uTp0 >> 1); - } - - if (nTmp0 >= tbff_chk_len[iT1]) - tbfalse += 1; - } - - /* m1/p1/m2/p2 all 2-2 mode */ - /* return (tbfalse==4); */ - nTmp0 = (tbfalse == 4); - - if (nTmp0 == 1) - nTmp0 += (polar3[2] < pPolar3[2]); - if (nTmp0 != 0) - mode_count = mode_count > 32 ? 32 : (mode_count+1); - else - mode_count = mode_count > 0 ? (mode_count-1) : 0; - calc_tbff_param(mode_count, 32); - for (iT0 = 0; iT0 < 7; iT0++) - pPolar3[iT0] = polar3[iT0]; - if (tbff_pr) - pr_info("num %d, x3 %d, lgrat %d, result is %d.\n", - calc_tbff_pixel_minnum, calc_tbff_x3_minrow, - calc_tbff_mp_lgrat[0], nTmp0); - - return tffbff_en?nTmp0:0; -} -module_param_named(tffbff_en, tffbff_en, bool, 0664); -module_param_named(tbff_pixel_minnum, tbff_pixel_minnum, int, 0664); -module_param_named(tbff_x3_minrow, tbff_x3_minrow, int, 0664); -module_param_named(tbff_pr, tbff_pr, bool, 0664); diff --git a/include/linux/amlogic/media/amvecm/amvecm.h b/include/linux/amlogic/media/amvecm/amvecm.h index 2e7b5c7ebb42..8396f40d760d 100644 --- a/include/linux/amlogic/media/amvecm/amvecm.h +++ b/include/linux/amlogic/media/amvecm/amvecm.h @@ -20,6 +20,7 @@ #include "linux/amlogic/media/amvecm/ve.h" #include "linux/amlogic/media/amvecm/cm.h" +#include #include #include @@ -94,6 +95,34 @@ #define MTX_BYPASS_RGB_OGO (1 << 0) #define MTX_RGB2YUVL_RGB_OGO (1 << 1) +enum pq_table_name_e { + TABLE_NAME_SHARPNESS0 = 0x1,/*in vpp*/ + TABLE_NAME_SHARPNESS1 = 0x2,/*in vpp*/ + TABLE_NAME_DNLP = 0x4, /*in vpp*/ + TABLE_NAME_CM = 0x8, /*in vpp*/ + TABLE_NAME_BLK_BLUE_EXT = 0x10,/*in vpp*/ + TABLE_NAME_BRIGHTNESS = 0x20,/*in vpp*/ + TABLE_NAME_CONTRAST = 0x40, /*in vpp*/ + TABLE_NAME_SATURATION_HUE = 0x80,/*in vpp*/ + TABLE_NAME_CVD2 = 0x100, /*in tvafe*/ + TABLE_NAME_DI = 0x200, /*in di*/ + TABLE_NAME_NR = 0x400, /*in di*/ + TABLE_NAME_MCDI = 0x800, /*in di*/ + TABLE_NAME_DEBLOCK = 0x1000, /*in di*/ + TABLE_NAME_DEMOSQUITO = 0x2000,/*in di*/ + TABLE_NAME_WB = 0X4000, /*in vpp*/ + TABLE_NAME_GAMMA = 0X8000, /*in vpp*/ + TABLE_NAME_XVYCC = 0x10000, /*in vpp*/ + TABLE_NAME_HDR = 0x20000, /*in vpp*/ + TABLE_NAME_DOLBY_VISION = 0x40000,/*in vpp*/ + TABLE_NAME_RESERVED1 = 0x80000, + TABLE_NAME_RESERVED2 = 0x100000, + TABLE_NAME_RESERVED3 = 0x200000, + TABLE_NAME_RESERVED4 = 0x400000, + TABLE_NAME_RESERVED5 = 0x800000, + TABLE_NAME_MAX, +}; + #define _VE_CM 'C' #define AMVECM_IOC_VE_DNLP _IOW(_VE_CM, 0x21, struct ve_dnlp_s) @@ -126,6 +155,17 @@ #define AMVECM_IOC_3D_SYNC_EN _IO(_VE_CM, 0x49) #define AMVECM_IOC_3D_SYNC_DIS _IO(_VE_CM, 0x50) +#define _DI_ 'D' + +struct am_pq_parm_s { + unsigned int table_name; + unsigned int table_len; + void *table_ptr; + void *reserved; +}; + +#define AMDI_IOC_SET_PQ_PARM _IOW(_DI_, 0x51, struct am_pq_parm_s) + /* #if (MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8) */ /* #define WRITE_VPP_REG(x,val)*/ /* WRITE_VCBUS_REG(x,val) */