From 7e32eee3088ff3a7a8e3f7e7d0dcc90d48fc180a Mon Sep 17 00:00:00 2001 From: "wenfeng.guo" Date: Wed, 21 Mar 2018 10:44:00 +0800 Subject: [PATCH] amvecm: add overscan iocontrol PD#162552: amvecm: add overscan iocontrol Change-Id: I1aa4b2469e7360029a0c647a0a1e46c73c71e7cd Signed-off-by: wenfeng.guo --- drivers/amlogic/media/enhancement/amvecm/amve.c | 63 +++++++++++++++++ drivers/amlogic/media/enhancement/amvecm/amve.h | 2 + drivers/amlogic/media/enhancement/amvecm/amvecm.c | 69 ++++++++++++++++++- include/linux/amlogic/media/amvecm/amvecm.h | 82 +++++++++++++++++++++-- 4 files changed, 210 insertions(+), 6 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.c b/drivers/amlogic/media/enhancement/amvecm/amve.c index 7ad9811..43c733b 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.c +++ b/drivers/amlogic/media/enhancement/amvecm/amve.c @@ -2013,3 +2013,66 @@ void amve_sharpness_init(void) { am_set_regmap(&sr1reg_sd_scale); } + +static int overscan_timing = TIMING_MAX; +module_param(overscan_timing, uint, 0664); +MODULE_PARM_DESC(overscan_timing, "\n overscan_control\n"); + +static int overscan_screen_mode = 0xff; +module_param(overscan_screen_mode, uint, 0664); +MODULE_PARM_DESC(overscan_screen_mode, "\n overscan_screen_mode\n"); + +static int overscan_disable; +module_param(overscan_disable, uint, 0664); +MODULE_PARM_DESC(overscan_disable, "\n overscan_disable\n"); + +void amvecm_fresh_overscan(struct vframe_s *vf) +{ + unsigned int height = 0; + unsigned int cur_overscan_timing = 0; + + if (overscan_disable) + return; + if (overscan_table[0].load_flag) { + height = (vf->type & VIDTYPE_COMPRESS) ? + vf->compHeight : vf->height; + if (height <= 576) + cur_overscan_timing = TIMING_SD; + else if (height <= 720) + cur_overscan_timing = TIMING_HD; + else if (height <= 1088) + cur_overscan_timing = TIMING_FHD; + else + cur_overscan_timing = TIMING_UHD; + + + overscan_timing = cur_overscan_timing; + overscan_screen_mode = + overscan_table[overscan_timing].screen_mode; + + vf->pic_mode.AFD_enable = + overscan_table[overscan_timing].afd_enable; + vf->pic_mode.screen_mode = + overscan_table[overscan_timing].screen_mode; + vf->pic_mode.hs = overscan_table[overscan_timing].hs; + vf->pic_mode.he = overscan_table[overscan_timing].he; + vf->pic_mode.vs = overscan_table[overscan_timing].vs; + vf->pic_mode.ve = overscan_table[overscan_timing].ve; + vf->ratio_control |= DISP_RATIO_ADAPTED_PICMODE; + } +} + +void amvecm_reset_overscan(void) +{ + if (overscan_disable) + return; + if (overscan_timing != TIMING_MAX) { + overscan_timing = TIMING_MAX; + if ((overscan_table[0].source != SOURCE_DTV) && + (overscan_table[0].source != SOURCE_MPEG)) { + overscan_table[0].load_flag = 0; + overscan_screen_mode = 0xff; + } + } +} + diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.h b/drivers/amlogic/media/enhancement/amvecm/amve.h index 060d74b..2719cdf 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.h +++ b/drivers/amlogic/media/enhancement/amvecm/amve.h @@ -190,5 +190,7 @@ extern struct am_regs_s sr1reg_sd_scale; extern struct am_regs_s sr1reg_hd_scale; extern struct am_regs_s sr1reg_cvbs; extern struct am_regs_s sr1reg_hv_noscale; +extern void amvecm_fresh_overscan(struct vframe_s *vf); +extern void amvecm_reset_overscan(void); #endif diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 7b4a802..1ac764b 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -911,6 +911,10 @@ int amvecm_on_vs( return 0; #endif if (flags & CSC_FLAG_CHECK_OUTPUT) { + if (toggle_vf) + amvecm_fresh_overscan(toggle_vf); + else if (vf) + amvecm_fresh_overscan(vf); /* to test if output will change */ return amvecm_matrix_process( toggle_vf, vf, flags); @@ -920,8 +924,10 @@ int amvecm_on_vs( result = amvecm_matrix_process(toggle_vf, vf, flags); if (toggle_vf) ioctrl_get_hdr_metadata(toggle_vf); - } else + } else { + amvecm_reset_overscan(); result = amvecm_matrix_process(NULL, NULL, flags); + } /* add some flag to trigger */ if (vf) { @@ -940,6 +946,10 @@ int amvecm_on_vs( vpp_demo_config(vf); } + if (vf) + amvecm_fresh_overscan(vf); + else + amvecm_reset_overscan(); /* todo:vlock processs only for tv chip */ if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || is_meson_txlx_cpu() @@ -989,12 +999,20 @@ static int amvecm_release(struct inode *inode, struct file *file) return 0; } static struct am_regs_s amregs_ext; +struct ve_pq_overscan_s overscan_table[TIMING_MAX]; static long amvecm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; void __user *argp; + int mem_size; + struct ve_pq_load_s vpp_pq_load; + struct ve_pq_table_s *vpp_pq_load_table = NULL; + int i = 0; + + i = sizeof(struct ve_pq_load_s); + pr_info("sizeof(struct ve_pq_load_s) = %d", i); pr_amvecm_dbg("[amvecm..] %s: cmd_nr = 0x%x\n", __func__, _IOC_NR(cmd)); @@ -1149,10 +1167,59 @@ static long amvecm_ioctl(struct file *file, case AMVECM_IOC_3D_SYNC_DIS: vecm_latch_flag |= FLAG_3D_SYNC_DIS; break; + case AMVECM_IOC_GET_OVERSCAN: + if (copy_from_user(&vpp_pq_load, + (void __user *)arg, + sizeof(struct ve_pq_load_s))) { + ret = -EFAULT; + pr_amvecm_dbg("[amvecm..] pq ioctl copy fail!!\n"); + break; + } + if (!(vpp_pq_load.param_id & TABLE_NAME_OVERSCAN)) { + ret = -EFAULT; + pr_amvecm_dbg("[amvecm..] overscan ioctl param_id fail!!\n"); + break; + } + mem_size = vpp_pq_load.length * sizeof(struct ve_pq_table_s); + vpp_pq_load_table = kmalloc(mem_size, GFP_KERNEL); + if (vpp_pq_load_table == NULL) { + pr_info("vpp_pq_load_table kmalloc fail!!!\n"); + return -EFAULT; + } + argp = (void __user *)vpp_pq_load.param_ptr; + if (copy_from_user(vpp_pq_load_table, argp, mem_size)) { + pr_amvecm_dbg("[amvecm..] ovescan copy fail!!\n"); + break; + } + for (i = 0; i < vpp_pq_load.length; i++) { + if (i >= TIMING_MAX) + break; + overscan_table[i].load_flag = + (vpp_pq_load_table[i].src_timing >> 31) & 0x1; + overscan_table[i].afd_enable = + (vpp_pq_load_table[i].src_timing >> 30) & 0x1; + overscan_table[i].screen_mode = + (vpp_pq_load_table[i].src_timing >> 24) & 0x3f; + overscan_table[i].source = + (vpp_pq_load_table[i].src_timing >> 16) & 0xff; + overscan_table[i].timing = + vpp_pq_load_table[i].src_timing & 0xffff; + overscan_table[i].hs = + vpp_pq_load_table[i].value1 & 0xffff; + overscan_table[i].he = + (vpp_pq_load_table[i].value1 >> 16) & 0xffff; + overscan_table[i].vs = + vpp_pq_load_table[i].value2 & 0xffff; + overscan_table[i].ve = + (vpp_pq_load_table[i].value2 >> 16) & 0xffff; + } + break; default: ret = -EINVAL; break; } + if (vpp_pq_load_table != NULL) + kfree(vpp_pq_load_table); return ret; } #ifdef CONFIG_COMPAT diff --git a/include/linux/amlogic/media/amvecm/amvecm.h b/include/linux/amlogic/media/amvecm/amvecm.h index f7adfb6..d9ea64e 100644 --- a/include/linux/amlogic/media/amvecm/amvecm.h +++ b/include/linux/amlogic/media/amvecm/amvecm.h @@ -115,11 +115,11 @@ enum pq_table_name_e { 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_OVERSCAN = 0x80000, + TABLE_NAME_RESERVED1 = 0x100000, + TABLE_NAME_RESERVED2 = 0x200000, + TABLE_NAME_RESERVED3 = 0x400000, + TABLE_NAME_RESERVED4 = 0x800000, TABLE_NAME_MAX, }; @@ -154,6 +154,78 @@ enum pq_table_name_e { #define AMVECM_IOC_3D_SYNC_EN _IO(_VE_CM, 0x49) #define AMVECM_IOC_3D_SYNC_DIS _IO(_VE_CM, 0x50) +struct ve_pq_load_s { + enum pq_table_name_e param_id; + unsigned int length; + void *param_ptr; + void *reserved; +}; + +struct ve_pq_table_s { + unsigned int src_timing; + unsigned int value1; + unsigned int value2; + unsigned int reserved1; + unsigned int reserved2; +}; + +#define AMVECM_IOC_GET_OVERSCAN _IOR(_VE_CM, 0x52, struct ve_pq_load_s) + +enum ve_source_input_e { + SOURCE_INVALID = -1, + SOURCE_TV = 0, + SOURCE_AV1, + SOURCE_AV2, + SOURCE_YPBPR1, + SOURCE_YPBPR2, + SOURCE_HDMI1, + SOURCE_HDMI2, + SOURCE_HDMI3, + SOURCE_HDMI4, + SOURCE_VGA, + SOURCE_MPEG, + SOURCE_DTV, + SOURCE_SVIDEO, + SOURCE_IPTV, + SOURCE_DUMMY, + SOURCE_SPDIF, + SOURCE_ADTV, + SOURCE_MAX, +}; + +enum ve_pq_timing_e { + TIMING_SD = 0, + TIMING_HD, + TIMING_FHD, + TIMING_UHD, + TIMING_MAX, +}; + +/*overscan: + *length 0~31bit :number of crop; + *src_timing: bit31: on: load/save all crop + bit31: off: load one according to timing* + bit30: AFD_enable: 1 -> on; 0 -> off* + screen mode: bit24~bit29* + source: bit16~bit23 -> source* + timing: bit0~bit15 -> sd/hd/fhd/uhd* + *value1: 0~15bit hs 16~31bit he* + *value2: 0~15bit vs 16~31bit ve* + */ +struct ve_pq_overscan_s { + unsigned int load_flag; + unsigned int afd_enable; + unsigned int screen_mode; + enum ve_source_input_e source; + enum ve_pq_timing_e timing; + unsigned int hs; + unsigned int he; + unsigned int vs; + unsigned int ve; +}; + +extern struct ve_pq_overscan_s overscan_table[TIMING_MAX]; + #define _DI_ 'D' struct am_pq_parm_s { -- 2.7.4