From f0a348f68bc79ddf94455620f15e227464980d80 Mon Sep 17 00:00:00 2001 From: Xihai Zhu Date: Fri, 23 Aug 2019 08:22:48 -0400 Subject: [PATCH] amvecm: add pattern detection function [1/1] PD#SWPL-13075 Problem: some pattern need special handling Solution: per VLSI'e suggestion, add pattern detection to try to detect special pattern Verify: tl1 Change-Id: I545b6e8c1b4a11fca927be46f16caeeb2cbe5327 Signed-off-by: Xihai Zhu --- MAINTAINERS | 8 + drivers/amlogic/media/enhancement/amvecm/Makefile | 1 + drivers/amlogic/media/enhancement/amvecm/amcm.c | 33 + drivers/amlogic/media/enhancement/amvecm/amvecm.c | 83 +- .../media/enhancement/amvecm/pattern_detection.c | 1120 ++++++++++++++++++++ .../media/enhancement/amvecm/pattern_detection.h | 81 ++ .../amvecm/pattern_detection_bar_settings.h | 285 +++++ .../amvecm/pattern_detection_corn_settings.h | 53 + .../amvecm/pattern_detection_face_settings.h | 65 ++ .../media/video_processor/ppmgr/ppmgr_vpp.c | 2 +- .../amlogic/media/vin/tvin/tvafe/tvafe_general.c | 5 + include/linux/amlogic/media/vfm/vframe.h | 2 + 12 files changed, 1735 insertions(+), 3 deletions(-) create mode 100644 drivers/amlogic/media/enhancement/amvecm/pattern_detection.c create mode 100644 drivers/amlogic/media/enhancement/amvecm/pattern_detection.h create mode 100644 drivers/amlogic/media/enhancement/amvecm/pattern_detection_bar_settings.h create mode 100644 drivers/amlogic/media/enhancement/amvecm/pattern_detection_corn_settings.h create mode 100644 drivers/amlogic/media/enhancement/amvecm/pattern_detection_face_settings.h diff --git a/MAINTAINERS b/MAINTAINERS index ceeffc1..1708ee9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15055,6 +15055,14 @@ M: Cheng Wang F: drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.c F: drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus_ootf.h +AMLOGIC PATTERN DETECTION FUNCTION +M: Xihai ZHu +F: drivers/amlogic/media/enhancement/amvecm/pattern_detection.c +F: drivers/amlogic/media/enhancement/amvecm/pattern_detection.h +F: drivers/amlogic/media/enhancement/amvecm/pattern_detection_bar_settings.h +F: drivers/amlogic/media/enhancement/amvecm/pattern_detection_corn_settings.h +F: drivers/amlogic/media/enhancement/amvecm/pattern_detection_face_settings.h + AMLOGIC DRM M: Ao Xu M: Dezhi Kong diff --git a/drivers/amlogic/media/enhancement/amvecm/Makefile b/drivers/amlogic/media/enhancement/amvecm/Makefile index 07733fb..4f01fcc 100644 --- a/drivers/amlogic/media/enhancement/amvecm/Makefile +++ b/drivers/amlogic/media/enhancement/amvecm/Makefile @@ -13,6 +13,7 @@ am_vecm-objs += bitdepth.o am_vecm-objs += set_hdr2_v0.o am_vecm-objs += dnlp_cal.o am_vecm-objs += cm2_adj.o +am_vecm-objs += pattern_detection.o am_vecm-objs += vlock.o am_vecm-objs += hdr/am_hdr10_plus.o am_vecm-objs += local_contrast.o diff --git a/drivers/amlogic/media/enhancement/amvecm/amcm.c b/drivers/amlogic/media/enhancement/amvecm/amcm.c index af01e6f..c84a10e 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amcm.c @@ -305,6 +305,12 @@ void amcm_disable(void) { int temp; + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, STA_CFG_REG); + temp = READ_VPP_REG(VPP_CHROMA_DATA_PORT); + temp = (temp & (~0xc0000000)) | (0 << 30); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, STA_CFG_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, temp); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, 0x208); temp = READ_VPP_REG(VPP_CHROMA_DATA_PORT); if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { @@ -322,6 +328,7 @@ void amcm_disable(void) temp & 0xfffffffd); } } + cm_en_flag = false; } @@ -348,6 +355,27 @@ void amcm_enable(void) temp | 0x2); } } + + /* enable CM histogram by default, mode 0 */ + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, STA_CFG_REG); + temp = READ_VPP_REG(VPP_CHROMA_DATA_PORT); + temp = (temp & (~0xc0000000)) | (1 << 30); + temp = (temp & (~0xff0000)) | (24 << 16); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, STA_CFG_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, temp); + + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, LUMA_ADJ1_REG); + temp = READ_VPP_REG(VPP_CHROMA_DATA_PORT); + temp = (temp & (~(0x1fff0000))) | (0 << 16); + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, LUMA_ADJ1_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, temp); + + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, STA_SAT_HIST0_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0 | (1 << 24)); + + WRITE_VPP_REG(VPP_CHROMA_ADDR_PORT, STA_SAT_HIST1_REG); + WRITE_VPP_REG(VPP_CHROMA_DATA_PORT, 0); + cm_en_flag = true; } @@ -414,6 +442,11 @@ void cm2_frame_size_patch(unsigned int width, unsigned int height) VSYNC_WR_MPEG_REG(VPP_CHROMA_DATA_PORT, width << 16); VSYNC_WR_MPEG_REG(VPP_CHROMA_ADDR_PORT, 0x20a); VSYNC_WR_MPEG_REG(VPP_CHROMA_DATA_PORT, height << 16); + /* default set full size for CM histogram */ + VSYNC_WR_MPEG_REG(VPP_CHROMA_ADDR_PORT, STA_WIN_XYXY0_REG); + VSYNC_WR_MPEG_REG(VPP_CHROMA_DATA_PORT, 0 | (width << 16)); + VSYNC_WR_MPEG_REG(VPP_CHROMA_ADDR_PORT, STA_WIN_XYXY1_REG); + VSYNC_WR_MPEG_REG(VPP_CHROMA_DATA_PORT, 0 | (height << 16)); cm_size = vpp_size; pr_amcm_dbg("\n[amcm..]cm size from scaler: set cm2 framesize %x, ", vpp_size); diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 860c7e5..0361b71 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -61,6 +61,7 @@ #include "keystone_correction.h" #include "bitdepth.h" #include "cm2_adj.h" +#include "pattern_detection.h" #include #include "dnlp_cal.h" #include "vlock.h" @@ -823,7 +824,7 @@ void vpp_get_hist_en(void) static unsigned int vpp_luma_max; void vpp_get_vframe_hist_info(struct vframe_s *vf) { - unsigned int hist_height, hist_width; + unsigned int hist_height, hist_width, i; u64 divid; if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) { @@ -989,6 +990,23 @@ void vpp_get_vframe_hist_info(struct vframe_s *vf) VI_HIST_ON_BIN_62_BIT, VI_HIST_ON_BIN_62_WID); vf->prop.hist.vpp_gamma[63] = READ_VPP_REG_BITS(VI_DNLP_HIST31, VI_HIST_ON_BIN_63_BIT, VI_HIST_ON_BIN_63_WID); + + if (enable_pattern_detect == 1) { + for (i = 0; i < 32; i++) { + WRITE_VPP_REG( + VPP_CHROMA_ADDR_PORT, + RO_CM_HUE_HIST_BIN0 + i); + vf->prop.hist.vpp_hue_gamma[i] = + READ_VPP_REG(VPP_CHROMA_DATA_PORT); + } + for (i = 0; i < 32; i++) { + WRITE_VPP_REG( + VPP_CHROMA_ADDR_PORT, + RO_CM_SAT_HIST_BIN0 + i); + vf->prop.hist.vpp_sat_gamma[i] = + READ_VPP_REG(VPP_CHROMA_DATA_PORT); + } + } if (debug_game_mode_1 && (vpp_luma_max != vf->prop.hist.vpp_luma_max)) { divid = vf->ready_clock_hist[1] = sched_clock(); @@ -1216,6 +1234,7 @@ void refresh_on_vs(struct vframe_s *vf) #endif ve_on_vs(vf); vpp_backup_histgram(vf); + pattern_detect(vf); } } EXPORT_SYMBOL(refresh_on_vs); @@ -5326,7 +5345,27 @@ static ssize_t amvecm_debug_store(struct class *cla, dump_vpp_size_info(); else if (!strncmp(parm[0], "vpp_state", 9)) pr_info("amvecm driver version : %s\n", AMVECM_VER); - else if (!strncmp(parm[0], "wb", 2)) { + else if (!strncmp(parm[0], "checkpattern", 12)) { + if (!strncmp(parm[1], "enable", 6)) { + pattern_detect_debug = 1; + enable_pattern_detect = 1; + pr_info("enable pattern detection\n"); + } else if (!strncmp(parm[1], "debug", 5)) { + pattern_detect_debug = 2; + pr_info("enable pattern detection debug info\n"); + } else if (!strncmp(parm[1], "disable", 7)) { + pattern_detect_debug = 0; + enable_pattern_detect = 0; + pr_info("disable pattern detection\n"); + } else if (!strncmp(parm[1], "setmask", 7)) { + if (kstrtoul(parm[2], 16, &val) < 0) + goto free_buf; + pattern_mask = val; + pr_info("pattern_mask is 0x%x\n", pattern_mask); + } else if (!strncmp(parm[1], "getmask", 7)) { + pr_info("pattern_mask is 0x%x\n", pattern_mask); + } + } else if (!strncmp(parm[0], "wb", 2)) { if (!strncmp(parm[1], "enable", 6)) { amvecm_wb_enable(1); pr_info("enable wb\n"); @@ -6860,6 +6899,45 @@ static void aml_vecm_dt_parse(struct platform_device *pdev) pr_info("Can't find cm_en.\n"); else cm_en = val; + ret = of_property_read_u32(node, "detect_colorbar", &val); + if (ret) { + pr_info("Can't find detect_colorbar.\n"); + } else { + if (val == 0) + pattern_mask = + pattern_mask & + (!PATTERN_MASK(PATTERN_75COLORBAR)); + else + pattern_mask = + pattern_mask | + PATTERN_MASK(PATTERN_75COLORBAR); + } + ret = of_property_read_u32(node, "detect_face", &val); + if (ret) { + pr_info("Can't find detect_face.\n"); + } else { + if (val == 0) + pattern_mask = + pattern_mask & + (!PATTERN_MASK(PATTERN_SKIN_TONE_FACE)); + else + pattern_mask = + pattern_mask | + PATTERN_MASK(PATTERN_SKIN_TONE_FACE); + } + ret = of_property_read_u32(node, "detect_corn", &val); + if (ret) { + pr_info("Can't find detect_corn.\n"); + } else { + if (val == 0) + pattern_mask = + pattern_mask & + (!PATTERN_MASK(PATTERN_GREEN_CORN)); + else + pattern_mask = + pattern_mask | + PATTERN_MASK(PATTERN_GREEN_CORN); + } ret = of_property_read_u32(node, "wb_sel", &val); if (ret) pr_info("Can't find wb_sel.\n"); @@ -6993,6 +7071,7 @@ static int aml_vecm_probe(struct platform_device *pdev) vout_register_client(&vlock_notifier_nb); init_pq_setting(); + init_pattern_detect(); /* #endif */ vpp_get_hist_en(); diff --git a/drivers/amlogic/media/enhancement/amvecm/pattern_detection.c b/drivers/amlogic/media/enhancement/amvecm/pattern_detection.c new file mode 100644 index 0000000..ed0fb30 --- /dev/null +++ b/drivers/amlogic/media/enhancement/amvecm/pattern_detection.c @@ -0,0 +1,1120 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/pattern_detection.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. + * + */ + +/* Standard Linux headers */ +#include +#include +#include +#include + +/* moudle headers */ +#include +#include +#include "../../vin/tvin/tvafe/tvafe.h" +#include "../../vin/tvin/tvafe/tvafe_vbi.h" +#include "arch/vpp_regs.h" +#include "amve.h" +#include "pattern_detection.h" +#ifdef CONFIG_TVIN_AFE +#include "pattern_detection_bar_settings.h" +#include "pattern_detection_face_settings.h" +#include "pattern_detection_corn_settings.h" +#endif + +#define PATTERN_INDEX_MAX PATTERN_GREEN_CORN + +int pattern_detect_debug; +#define pr_pattern_detect_dbg(fmt, args...)\ + do {\ + if (pattern_detect_debug > 0)\ + pr_info("Detect debug: [%s]: " fmt, __func__, ## args);\ + } while (0) + +int enable_pattern_detect = 1; +int detected_pattern = PATTERN_UNKNOWN; +int last_detected_pattern = PATTERN_UNKNOWN; +uint pattern_mask = PATTERN_MASK(PATTERN_75COLORBAR) | + PATTERN_MASK(PATTERN_SKIN_TONE_FACE) | + PATTERN_MASK(PATTERN_GREEN_CORN); + +static uint pattern_param = PATTERN_PARAM_COUNT; + +static uint pattern0_param_info[PATTERN_PARAM_COUNT] = { + 5, 100, 850, 30, 110, 0x70000, 0xd0000, 0x158000, + 400, 40, 650, 50, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static uint pattern1_param_info[PATTERN_PARAM_COUNT] = { + 850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static uint pattern2_param_info[PATTERN_PARAM_COUNT] = { + 80, 730, 180, 6, /* pal hue hist 14 ~ 17 */ + 80, 510, 340, 70, /* ntsc hue hist 14 ~ 17 */ + 59, 112, 133, 223, /* pal sat hist 0 ~ 3 */ + 290, 165, 16, 1, /* pal sat hist 4 ~ 7 */ + 83, 143, 204, 316, /* ntsc sat hist 0 ~ 3 */ + 221, 28, 3, 0, /* ntsc sat hist 4 ~ 7 */ + 50, 55, 900, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +module_param_array( + pattern0_param_info, uint, + &pattern_param, 0664); +MODULE_PARM_DESC(pattern0_param_info, "\n pattern0_param_info\n"); + +module_param_array( + pattern1_param_info, uint, + &pattern_param, 0664); +MODULE_PARM_DESC(pattern1_param_info, "\n pattern1_param_info\n"); + +module_param_array( + pattern2_param_info, uint, + &pattern_param, 0664); +MODULE_PARM_DESC(pattern2_param_info, "\n pattern2_param_info\n"); + +static int default_pattern0_checker(struct vframe_s *vf) +{ + pr_pattern_detect_dbg("check for pattern0\n"); + return 0; +} + +static int default_pattern1_checker(struct vframe_s *vf) +{ + pr_pattern_detect_dbg("check for pattern1\n"); + return 0; +} + +static int default_pattern2_checker(struct vframe_s *vf) +{ + pr_pattern_detect_dbg("check for pattern2\n"); + return 0; +} + +static int default_pattern0_handler(struct vframe_s *vf, int flag) +{ + pr_pattern_detect_dbg("pattern0 detected and handled\n"); + return 0; +} + +static int default_pattern1_handler(struct vframe_s *vf, int flag) +{ + pr_pattern_detect_dbg("pattern1 detected and handled\n"); + return 0; +} + +static int default_pattern2_handler(struct vframe_s *vf, int flag) +{ + pr_pattern_detect_dbg("pattern2 detected and handled\n"); + return 0; +} + +static int default_pattern0_defaultloader(struct vframe_s *vf) +{ + pr_pattern_detect_dbg("pattern0 load default setting\n"); + return 0; +} + +static int default_pattern1_defaultloader(struct vframe_s *vf) +{ + pr_pattern_detect_dbg("pattern1 load default setting\n"); + return 0; +} + +static int default_pattern2_defaultloader(struct vframe_s *vf) +{ + pr_pattern_detect_dbg("pattern2 load default setting\n"); + return 0; +} + +static int pattern_index; +static struct pattern pattern_list[] = { + { + PATTERN_75COLORBAR, + pattern0_param_info, + NULL, + NULL, + default_pattern0_checker, + default_pattern0_defaultloader, + default_pattern0_handler, + }, + { + PATTERN_SKIN_TONE_FACE, + pattern1_param_info, + NULL, + NULL, + default_pattern1_checker, + default_pattern1_defaultloader, + default_pattern1_handler, + }, + { + PATTERN_GREEN_CORN, + pattern2_param_info, + NULL, + NULL, + default_pattern2_checker, + default_pattern2_defaultloader, + default_pattern2_handler, + }, +}; + +#ifdef CONFIG_TVIN_AFE +static void tvafe_get_default_regmap(struct am_regs_s *p) +{ + unsigned short i; + + for (i = 0; i < p->length; i++) { + switch (p->am_reg[i].type) { + case REG_TYPE_APB: + tvafe_reg_read( + p->am_reg[i].addr << 2, + &p->am_reg[i].val); + p->am_reg[i].val = p->am_reg[i].val & + p->am_reg[i].mask; + break; + default: + break; + } + pr_info( + "Detect debug: [%s]: tvafe read default 0x%x = 0x%x\n", + __func__, p->am_reg[i].addr, + p->am_reg[i].val); + } +} + +static void am_get_default_regmap(struct am_regs_s *p) +{ + unsigned short i; + + for (i = 0; i < p->length; i++) { + switch (p->am_reg[i].type) { + case REG_TYPE_CBUS: + p->am_reg[i].val = + aml_read_cbus(p->am_reg[i].addr) & + p->am_reg[i].mask; + break; + case REG_TYPE_INDEX_VPP_COEF: + WRITE_VPP_REG( + VPP_CHROMA_ADDR_PORT, + p->am_reg[i].addr); + p->am_reg[i].val = + READ_VPP_REG(VPP_CHROMA_DATA_PORT) & + p->am_reg[i].mask; + break; + case REG_TYPE_VCBUS: + p->am_reg[i].val = + aml_read_vcbus(p->am_reg[i].addr) & + p->am_reg[i].mask; + break; + default: + break; + } + pr_info( + "Detect debug: [%s]: vpp read default 0x%x = 0x%x\n", + __func__, p->am_reg[i].addr, + p->am_reg[i].val); + } +} + +static void defaultsetting_get_regmap(int index) +{ + struct setting_regs_s *cvd2_set = + pattern_list[pattern_index].cvd2_settings; + struct setting_regs_s *vpp_set = + pattern_list[pattern_index].vpp_settings; + + pr_pattern_detect_dbg("enter\n"); + + if (cvd2_set && cvd2_set[index].length > 0) { + /* default setting is not ready, need to update it */ + if (cvd2_set[index].am_reg[0].val == 0xffffffff) + tvafe_get_default_regmap( + (struct am_regs_s *)(&cvd2_set[index])); + } + + if (vpp_set && vpp_set[index].length > 0) { + /* default setting is not ready, need to update it */ + if (vpp_set[index].am_reg[0].val == 0xffffffff) + am_get_default_regmap( + (struct am_regs_s *)(&vpp_set[index])); + } + pr_pattern_detect_dbg("leave\n"); +} + +static void setting_set_regmap(int index) +{ + struct setting_regs_s *cvd2_set = + pattern_list[pattern_index].cvd2_settings; + struct setting_regs_s *vpp_set = + pattern_list[pattern_index].vpp_settings; + + pr_pattern_detect_dbg("enter\n"); + + /* check if default setting is ready*/ + + if (cvd2_set) + tvafe_set_regmap((struct am_regs_s *)(&cvd2_set[index])); + + if (vpp_set) + am_set_regmap((struct am_regs_s *)(&vpp_set[index])); + + pr_pattern_detect_dbg("leave\n"); +} + +static int colorbar_hist_checker(struct vframe_s *vf) +{ + /* check cm2 hist and dnlp apl value */ + int flag = -1; + int hue_hist[32], y_hist_total; + int i, apl, hist_total = 0; + int peak_hue_bin_sum = 0, bin2021, bin2526, bin32; + int apl_diff, bin1, bin2, bin5, bin910, bin16; + int bin8, bin24, bin26, bin3132, bin17; + int tolerence_zero, tolerence_hue; + int tolerence_hue2; + int tolerence_hue3a, tolerence_hue3b; + int tolerence_hue5; + int tolerence_hue_all, tolerence_luma, target_apl; + unsigned int tvafe_val, tolerance_tvafe; + int bin56, bin1718, bin2122; + int peak_hue_bin_sum4 = 0; + int peak_hue_bin_sum5 = 0; + + tolerence_zero = pattern_list[pattern_index].pattern_param[0]; + tolerence_hue = pattern_list[pattern_index].pattern_param[1]; + tolerence_hue_all = pattern_list[pattern_index].pattern_param[2]; + tolerence_luma = pattern_list[pattern_index].pattern_param[3]; + target_apl = pattern_list[pattern_index].pattern_param[4]; + tolerance_tvafe = pattern_list[pattern_index].pattern_param[5]; + tolerence_hue2 = pattern_list[pattern_index].pattern_param[8]; + tolerence_hue3a = pattern_list[pattern_index].pattern_param[9]; + tolerence_hue3b = pattern_list[pattern_index].pattern_param[10]; + tolerence_hue5 = pattern_list[pattern_index].pattern_param[11]; + + if ( + vf->source_type == VFRAME_SOURCE_TYPE_TUNER && + vf->source_mode == VFRAME_SOURCE_MODE_PAL) { + tolerance_tvafe = pattern_list[pattern_index].pattern_param[7]; + } else if (vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_NTSC) { + tolerance_tvafe = pattern_list[pattern_index].pattern_param[5]; + } else if (vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_PAL) { + tolerance_tvafe = pattern_list[pattern_index].pattern_param[6]; + } + + if ( + (vf->source_type != VFRAME_SOURCE_TYPE_TUNER) && + (vf->source_type != VFRAME_SOURCE_TYPE_CVBS)) + return flag; + + if (tvafe_clk_status == 0) + return flag; + + flag = 0; + + /* check cm2 hue/sat hist */ + for (i = 0; i <= 31; i++) { + hue_hist[i] = vf->prop.hist.vpp_hue_gamma[i]; + hist_total += hue_hist[i]; + } + hist_total = hist_total / 1000; + for (i = 0; i <= 31; i++) { + hue_hist[i] = hue_hist[i] / hist_total; + pr_pattern_detect_dbg( + "read hue_hist[%d]=%d, origin=%d\n", i, + (int)hue_hist[i], + vf->prop.hist.vpp_hue_gamma[i]); + } + + /* + * check hue hist bin 5, bin 9+10, bin 16 + * bin 20+21, bin 25+26, bin 32 and sum + */ + bin1 = hue_hist[0]; + bin2 = hue_hist[1]; + bin5 = hue_hist[3] + hue_hist[4]; + bin56 = hue_hist[4] + hue_hist[5]; + bin8 = hue_hist[7]; + bin910 = hue_hist[8] + hue_hist[9] + hue_hist[10]; + bin16 = hue_hist[15]; + bin17 = hue_hist[16]; + bin1718 = hue_hist[16] + hue_hist[17]; + bin2021 = hue_hist[19] + hue_hist[20]; + bin2122 = hue_hist[20] + hue_hist[21]; + bin24 = hue_hist[23]; + bin2526 = hue_hist[24] + hue_hist[25] + hue_hist[26]; + bin26 = hue_hist[25]; + bin32 = hue_hist[31]; + bin3132 = hue_hist[29] + hue_hist[30] + hue_hist[31]; + peak_hue_bin_sum = hue_hist[1] + hue_hist[4] + hue_hist[8] + + hue_hist[9] + hue_hist[15] + hue_hist[19] + + hue_hist[20] + hue_hist[24] + hue_hist[25] + + hue_hist[31] + hue_hist[3] + hue_hist[10] + + hue_hist[26]; + peak_hue_bin_sum4 = bin2 + bin56 + bin910 + + bin1718 + bin2122 + bin2526; + peak_hue_bin_sum5 = bin1 + bin5 + bin8 + + bin910 + bin16 + bin2021 + bin24 + + bin26 + bin3132 + bin17; + pr_pattern_detect_dbg( + "bin2=%d, bin5=%d, bin910=%d, bin16=%d\n", + bin2, bin5, bin910, bin16); + pr_pattern_detect_dbg( + "bin2021=%d, bin2526=%d, bin32=%d\n", + bin2021, bin2526, bin32); + pr_pattern_detect_dbg( + "peak_hue_bin_sum=%d\n", + peak_hue_bin_sum); + + /* check apl */ + apl = vf->prop.hist.luma_sum / + (vf->prop.hist.height * vf->prop.hist.width); + apl_diff = (apl - target_apl) * 1000 / target_apl; + pr_pattern_detect_dbg( + "apl=%d, target_apl=%d\n", + apl, target_apl); + + /* check high 4 bin sum of dnlp histogram */ + y_hist_total = 0; + for (i = 60; i <= 63; i++) + y_hist_total += vf->prop.hist.vpp_gamma[i]; + pr_pattern_detect_dbg( + "high 4 luma bin sum=%d\n", + y_hist_total); + + /* read tvafe status register to check mixed pattern*/ + tvafe_reg_read(0x18d << 2, &tvafe_val); + pr_pattern_detect_dbg( + "tvafe status reg val=0x%x, check value= 0x%x\n", + tvafe_val, tolerance_tvafe); + + /* judge type 1, normal / mixed colorbar 7 color */ + if ( + (peak_hue_bin_sum >= tolerence_hue_all) && + (bin5 >= tolerence_hue) && + (bin910 >= tolerence_hue) && + (bin16 >= tolerence_hue) && + (bin2021 >= tolerence_hue) && + (bin2526 >= tolerence_hue) && + (bin32 >= tolerence_hue)) { + if (tvafe_val <= tolerance_tvafe) { + pr_pattern_detect_dbg( + "judge1 colorbar detected\n"); + flag = 2; + } else { + pr_pattern_detect_dbg( + "judge1 colorbar mixed detected\n"); + flag = 1; + } + } + if (flag > 0) + goto judge_finish; + + /* judge type 2, 4 grid, pink and blue*/ + pr_pattern_detect_dbg( + "judge2......\n"); + if ( + (peak_hue_bin_sum >= tolerence_hue_all) && + (bin5 >= tolerence_hue2) && + (bin2526 >= tolerence_hue2)) { + pr_pattern_detect_dbg( + "judge2 4 grid pattern detected\n"); + flag = 2; + } + if (flag > 0) + goto judge_finish; + + /* judge type 3, ega-64blue color */ + pr_pattern_detect_dbg( + "judge3......\n"); + if ( + (peak_hue_bin_sum >= tolerence_hue_all) && + (bin5 >= tolerence_hue3a) && + (bin910 >= tolerence_hue3a) && + (bin16 >= tolerence_hue3a) && + (bin2021 >= tolerence_hue3a) && + (bin2526 >= tolerence_hue3a) && + (bin32 >= tolerence_hue3b)) { + pr_pattern_detect_dbg( + "judge3 ega-64blue pattern detected\n"); + flag = 2; + } + if (flag > 0) + goto judge_finish; + + /* judge type 4, BDGH pattern */ + pr_pattern_detect_dbg( + "judge4......\n"); + pr_pattern_detect_dbg( + "bin2=%d, bin56=%d, bin910=%d, bin1718=%d\n", + bin2, bin56, bin910, bin1718); + pr_pattern_detect_dbg( + "bin2122=%d, bin2526=%d\n", + bin2122, bin2526); + pr_pattern_detect_dbg( + "peak_hue_bin_sum4=%d\n", + peak_hue_bin_sum4); + if ( + (peak_hue_bin_sum4 >= tolerence_hue_all) && + (bin56 >= tolerence_hue) && + (bin910 >= tolerence_hue) && + (bin1718 >= tolerence_hue) && + (bin2122 >= tolerence_hue) && + (bin2526 >= tolerence_hue) && + (bin2 >= tolerence_hue)) { + pr_pattern_detect_dbg( + "judge4 BDGH pattern detected\n"); + flag = 2; + } + if (flag > 0) + goto judge_finish; + + /* judge type 5, color BDGH pattern */ + pr_pattern_detect_dbg( + "judge5......\n"); + pr_pattern_detect_dbg( + "bin1=%d, bin5=%d, bin8=%d, bin910=%d\n", + bin1, bin5, bin8, bin910); + pr_pattern_detect_dbg( + "bin16=%d, bin2021=%d, bin24=%d\n", + bin16, bin2021, bin24); + pr_pattern_detect_dbg( + "bin26=%d, bin3132=%d\n", + bin26, bin3132); + pr_pattern_detect_dbg( + "peak_hue_bin_sum5=%d\n", + peak_hue_bin_sum5); + if ( + (peak_hue_bin_sum5 >= tolerence_hue_all) && + (bin5 >= tolerence_hue5) && + (bin8 >= tolerence_hue5) && + (bin910 >= tolerence_hue5) && + (bin16 >= tolerence_hue5) && + (bin2021 >= tolerence_hue5) && + (bin24 >= tolerence_hue5) && + (bin26 >= tolerence_hue5) && + (bin3132 >= tolerence_hue5) && + (bin1 >= tolerence_hue5)) { + pr_pattern_detect_dbg( + "judge5 color BDGH pattern detected\n"); + flag = 2; + } + if (flag > 0) + goto judge_finish; + +judge_finish: + if (flag <= 0) + pr_pattern_detect_dbg("colorbar is not detected\n"); + + return flag; +} + +static int colorbar_default_loader(struct vframe_s *vf) +{ + pr_pattern_detect_dbg("enter\n"); + + if (tvafe_clk_status == 0) + return 0; + + if ( + vf->source_type == VFRAME_SOURCE_TYPE_TUNER && + vf->source_mode == VFRAME_SOURCE_MODE_NTSC) + defaultsetting_get_regmap(12); + else if ( + vf->source_type == VFRAME_SOURCE_TYPE_TUNER && + vf->source_mode == VFRAME_SOURCE_MODE_PAL) + defaultsetting_get_regmap(13); + else if ( + vf->source_type == VFRAME_SOURCE_TYPE_TUNER && + vf->source_mode == VFRAME_SOURCE_MODE_SECAM) + defaultsetting_get_regmap(14); + else if ( + vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_NTSC) + defaultsetting_get_regmap(15); + else if ( + vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_PAL) + defaultsetting_get_regmap(16); + else if ( + vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_SECAM) + defaultsetting_get_regmap(17); + + pr_pattern_detect_dbg("leave\n"); + return 0; +} + +static int colorbar_handler(struct vframe_s *vf, int flag) +{ + static int last_flag = -1, last_type, last_mode; + + pr_pattern_detect_dbg("enter\n"); + + /* + * flag == 0, color bar is not detected, restore + * the dedault setting + * flag == 1, mixed color bar is detected, apply + * the specific setting + * flag == 2, color bar is detected, apply + * the specific setting + */ + + /* + * do not keep programming register + * return if detection result is not chaneged + */ + if ( + (last_type == vf->source_type) && + (last_mode == vf->source_mode) && + (flag == last_flag)) + return 0; + + if ( + vf->source_type == VFRAME_SOURCE_TYPE_TUNER && + vf->source_mode == VFRAME_SOURCE_MODE_NTSC) { + if (flag <= 0) + setting_set_regmap(12); + else if (flag == 1) + setting_set_regmap(6); + else if (flag == 2) + setting_set_regmap(0); + } else if ( + vf->source_type == VFRAME_SOURCE_TYPE_TUNER && + vf->source_mode == VFRAME_SOURCE_MODE_PAL) { + if (flag <= 0) + setting_set_regmap(13); + else if (flag == 1) + setting_set_regmap(7); + else if (flag == 2) + setting_set_regmap(1); + } else if ( + vf->source_type == VFRAME_SOURCE_TYPE_TUNER && + vf->source_mode == VFRAME_SOURCE_MODE_SECAM) { + if (flag <= 0) + setting_set_regmap(14); + else if (flag == 1) + setting_set_regmap(8); + else if (flag == 2) + setting_set_regmap(2); + } else if ( + vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_NTSC) { + if (flag <= 0) + setting_set_regmap(15); + else if (flag == 1) + setting_set_regmap(9); + else if (flag == 2) + setting_set_regmap(3); + } else if ( + vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_PAL) { + if (flag <= 0) + setting_set_regmap(16); + else if (flag == 1) + setting_set_regmap(10); + else if (flag == 2) + setting_set_regmap(4); + } else if ( + vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_SECAM) { + if (flag <= 0) + setting_set_regmap(17); + else if (flag == 1) + setting_set_regmap(11); + else if (flag == 2) + setting_set_regmap(5); + } + + last_flag = flag; + last_type = vf->source_type; + last_mode = vf->source_mode; + pr_pattern_detect_dbg("leave\n"); + return 0; +} + +static int face_hist_checker(struct vframe_s *vf) +{ + /* check cm2 hue hist */ + int flag = -1; + int hue_hist[32]; + int i, hist_total = 0; + int skin_tone_hue_bin_sum = 0; + int tolerence_face; + + tolerence_face = pattern_list[pattern_index].pattern_param[0]; + + if ( + (vf->source_type != VFRAME_SOURCE_TYPE_TUNER) && + (vf->source_type != VFRAME_SOURCE_TYPE_CVBS)) + return flag; + + if (tvafe_clk_status == 0) + return flag; + + flag = 0; + + /* check cm2 hue hist */ + for (i = 0; i <= 31; i++) { + hue_hist[i] = vf->prop.hist.vpp_hue_gamma[i]; + hist_total += hue_hist[i]; + } + hist_total = hist_total / 1000; + for (i = 0; i <= 31; i++) { + hue_hist[i] = hue_hist[i] / hist_total; + pr_pattern_detect_dbg( + "read hue_hist[%d]=%d, origin=%d\n", i, + (int)hue_hist[i], vf->prop.hist.vpp_hue_gamma[i]); + } + + /* + * check skin tone hue hist + */ + skin_tone_hue_bin_sum = hue_hist[9] + hue_hist[10] + + hue_hist[11] + hue_hist[12]; + pr_pattern_detect_dbg( + "skin_tone_hue_bin_sum=%d\n", + skin_tone_hue_bin_sum); + + /* judge */ + if (skin_tone_hue_bin_sum >= tolerence_face) { + pr_pattern_detect_dbg( + "skin tone pattern detected\n"); + flag = 1; + } + + if (flag <= 0) + pr_pattern_detect_dbg( + "skin tone pattern is not detected\n"); + + return flag; +} + +static int face_default_loader(struct vframe_s *vf) +{ + pr_pattern_detect_dbg("enter\n"); + + if (tvafe_clk_status == 0) + return 0; + + if ( + vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_NTSC) + defaultsetting_get_regmap(2); + else if ( + vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_PAL) + defaultsetting_get_regmap(3); + + pr_pattern_detect_dbg("leave\n"); + return 0; +} + +static int face_handler(struct vframe_s *vf, int flag) +{ + static int last_flag = -1, last_type, last_mode; + + pr_pattern_detect_dbg("enter\n"); + + /* + * flag == 0, face is not detected, restore + * the dedault setting + * flag == 1, face is detected, apply + * the specific setting + */ + + /* + * do not keep programming register + * return if detection result is not chaneged + */ + if ( + (last_type == vf->source_type) && + (last_mode == vf->source_mode) && + (flag == last_flag)) + return 0; + + if ( + vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_NTSC) { + if (flag <= 0) + setting_set_regmap(2); + else if (flag == 1) + setting_set_regmap(0); + } else if ( + vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_PAL) { + if (flag <= 0) + setting_set_regmap(3); + else if (flag == 1) + setting_set_regmap(1); + } + + last_flag = flag; + last_type = vf->source_type; + last_mode = vf->source_mode; + pr_pattern_detect_dbg("leave\n"); + + return 0; +} + +static int corn_hist_checker(struct vframe_s *vf) +{ + /* check cm2 hue hist */ + int flag = -1; + int hue_hist[32], sat_hist[32]; + int i, hist_total = 0, hist_sat_total = 0; + int hue_bin_sum = 0, diff_hue_bin14, diff_hue_bin15; + int diff_hue_bin16, diff_hue_bin17, diff_sat[8]; + int tolerence_hue, tolerence_sat, tolerence_sum; + int hue_offset = 0; /* for pal default */ + int sat_offset = 0; /* for pal default */ + + tolerence_hue = pattern_list[pattern_index].pattern_param[24]; + tolerence_sat = pattern_list[pattern_index].pattern_param[25]; + tolerence_sum = pattern_list[pattern_index].pattern_param[26]; + + if (vf->source_mode == VFRAME_SOURCE_MODE_NTSC) { + hue_offset = 4; + sat_offset = 8; + } + + if ( + (vf->source_type != VFRAME_SOURCE_TYPE_TUNER) && + (vf->source_type != VFRAME_SOURCE_TYPE_CVBS)) + return flag; + + if (tvafe_clk_status == 0) + return flag; + + flag = 0; + + /* check cm2 hue hist */ + for (i = 0; i <= 31; i++) { + hue_hist[i] = vf->prop.hist.vpp_hue_gamma[i]; + sat_hist[i] = vf->prop.hist.vpp_sat_gamma[i]; + hist_total += hue_hist[i]; + hist_sat_total += sat_hist[i]; + } + hist_total = hist_total / 1000; + hist_sat_total = hist_sat_total / 1000; + + for (i = 0; i <= 31; i++) { + hue_hist[i] = hue_hist[i] / hist_total; + pr_pattern_detect_dbg( + "read hue_hist[%d]=%d, origin=%d\n", i, + (int)hue_hist[i], vf->prop.hist.vpp_hue_gamma[i]); + } + + for (i = 0; i <= 31; i++) { + sat_hist[i] = sat_hist[i] / hist_sat_total; + pr_pattern_detect_dbg( + "read sat_hist[%d]=%d, origin=%d\n", i, + (int)sat_hist[i], vf->prop.hist.vpp_sat_gamma[i]); + } + + /* + * check hue hist + */ + diff_hue_bin14 = hue_hist[14] - + pattern_list[pattern_index].pattern_param[0 + hue_offset]; + diff_hue_bin15 = hue_hist[15] - + pattern_list[pattern_index].pattern_param[1 + hue_offset]; + diff_hue_bin16 = hue_hist[16] - + pattern_list[pattern_index].pattern_param[2 + hue_offset]; + diff_hue_bin17 = hue_hist[17] - + pattern_list[pattern_index].pattern_param[3 + hue_offset]; + hue_bin_sum = hue_hist[14] + hue_hist[15] + + hue_hist[16]; + pr_pattern_detect_dbg( + "diff_hue_bin14=%d, diff_hue_bin15=%d\n", + diff_hue_bin14, diff_hue_bin15); + pr_pattern_detect_dbg( + "diff_hue_bin16=%d, diff_hue_bin17=%d\n", + diff_hue_bin16, diff_hue_bin17); + pr_pattern_detect_dbg( + "hue_bin_sum=%d\n", + hue_bin_sum); + + /* + * check sat hist + */ + for (i = 0; i <= 7; i++) { + diff_sat[i] = sat_hist[i] - + pattern_list[pattern_index].pattern_param[8 + i + sat_offset]; + pr_pattern_detect_dbg( + "diff_sat[%d]=%d\n", + i, diff_sat[i]); + } + + /* judge */ + if (hue_bin_sum >= tolerence_sum) { + pr_pattern_detect_dbg( + "green corn pattern detected\n"); + flag = 1; + } + + if (flag <= 0) + pr_pattern_detect_dbg( + "green corn pattern is not detected\n"); + + return flag; +} + +static int corn_default_loader(struct vframe_s *vf) +{ + pr_pattern_detect_dbg("enter\n"); + + if (tvafe_clk_status == 0) + return 0; + + if ( + vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_NTSC) + defaultsetting_get_regmap(2); + else if ( + vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_PAL) + defaultsetting_get_regmap(3); + + pr_pattern_detect_dbg("leave\n"); + return 0; +} + +static int corn_handler(struct vframe_s *vf, int flag) +{ + static int last_flag = -1, last_type, last_mode; + + pr_pattern_detect_dbg("enter\n"); + + /* + * flag == 0, green corn is not detected, restore + * the dedault setting + * flag == 1, green corn is detected, apply + * the specific setting + */ + + /* + * do not keep programming register + * return if detection result is not chaneged + */ + if ( + (last_type == vf->source_type) && + (last_mode == vf->source_mode) && + (flag == last_flag)) + return 0; + + if ( + vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_NTSC) { + if (flag <= 0) + setting_set_regmap(2); + else if (flag == 1) + setting_set_regmap(0); + } else if ( + vf->source_type == VFRAME_SOURCE_TYPE_CVBS && + vf->source_mode == VFRAME_SOURCE_MODE_PAL) { + if (flag <= 0) + setting_set_regmap(3); + else if (flag == 1) + setting_set_regmap(1); + } + + last_flag = flag; + last_type = vf->source_type; + last_mode = vf->source_mode; + pr_pattern_detect_dbg("leave\n"); + + return 0; +} +#endif + +/* public api */ +int pattern_detect_add_checker( + int id, + int (*newchecker)(struct vframe_s *vf)) +{ + pattern_list[id].checker = newchecker; + + return 0; +} + +int pattern_detect_add_defaultloader( + int id, + int (*newloader)(struct vframe_s *vf)) +{ + pattern_list[id].default_loader = newloader; + + return 0; +} + +int pattern_detect_add_handler( + int id, + int (*newhandler)(struct vframe_s *vf, int flag)) +{ + pattern_list[id].handler = newhandler; + + return 0; +} + +int pattern_detect_add_cvd2_setting_table( + int id, + struct setting_regs_s *new_settings) +{ + pattern_list[id].cvd2_settings = new_settings; + + return 0; +} + +int pattern_detect_add_vpp_setting_table( + int id, + struct setting_regs_s *new_settings) +{ + pattern_list[id].vpp_settings = new_settings; + + return 0; +} + +int init_pattern_detect(void) +{ + /* install callback for color bar */ +#ifdef CONFIG_TVIN_AFE + pattern_detect_add_checker( + PATTERN_75COLORBAR, + colorbar_hist_checker); + pattern_detect_add_defaultloader( + PATTERN_75COLORBAR, + colorbar_default_loader); + pattern_detect_add_handler( + PATTERN_75COLORBAR, + colorbar_handler); + pattern_detect_add_cvd2_setting_table( + PATTERN_75COLORBAR, + colorbar_cvd2_settings); + pattern_detect_add_vpp_setting_table( + PATTERN_75COLORBAR, + colorbar_vpp_settings); + + /* install callback for face pattern */ + pattern_detect_add_checker( + PATTERN_SKIN_TONE_FACE, + face_hist_checker); + pattern_detect_add_handler( + PATTERN_SKIN_TONE_FACE, + face_handler); + pattern_detect_add_defaultloader( + PATTERN_SKIN_TONE_FACE, + face_default_loader); + pattern_detect_add_cvd2_setting_table( + PATTERN_SKIN_TONE_FACE, + face_cvd2_settings); + + /* install callback for corn */ + pattern_detect_add_checker( + PATTERN_GREEN_CORN, + corn_hist_checker); + pattern_detect_add_handler( + PATTERN_GREEN_CORN, + corn_handler); + pattern_detect_add_defaultloader( + PATTERN_GREEN_CORN, + corn_default_loader); + pattern_detect_add_cvd2_setting_table( + PATTERN_GREEN_CORN, + corn_cvd2_settings); +#endif + + return 0; +} + +int pattern_detect(struct vframe_s *vf) +{ + int flag = 0, rc = PATTERN_UNKNOWN; + + if (!vf) + return 0; + + if (enable_pattern_detect <= 0) + return 0; + + for (pattern_index = PATTERN_START; + pattern_index <= PATTERN_INDEX_MAX; + pattern_index++) { + if (!(pattern_mask & (1 << pattern_index))) + continue; + + /* load the default setting */ + if (pattern_list[pattern_index].default_loader) { + pr_pattern_detect_dbg( + "loading the default setting for pattern %d:\n", + pattern_index); + pattern_list[pattern_index].default_loader(vf); + } + + /* check the pattern */ + if (pattern_list[pattern_index].checker) { + pr_pattern_detect_dbg( + "checking the pattern %d:\n", + pattern_index); + flag = + pattern_list[pattern_index].checker(vf); + } + + detected_pattern = + (flag > 0) ? pattern_index : + PATTERN_UNKNOWN; + + /* handle the detected pattern */ + if (flag >= 0) { + /* call the handler if present */ + if (pattern_list[pattern_index].handler) { + pr_pattern_detect_dbg( + "handling the pattern %d:\n", + pattern_index); + pattern_list[pattern_index].handler(vf, flag); + } else { + /* handler is not present, send a notify */ + if (detected_pattern != + last_detected_pattern) { + pr_pattern_detect_dbg( + "trigger the polling client\n"); + } + } + + if (flag > 0) { + rc = pattern_index; + goto finish_detect; + } + } + } + +finish_detect: + last_detected_pattern = detected_pattern; + if (pattern_detect_debug > 0) + pattern_detect_debug--; + + return rc; +} diff --git a/drivers/amlogic/media/enhancement/amvecm/pattern_detection.h b/drivers/amlogic/media/enhancement/amvecm/pattern_detection.h new file mode 100644 index 0000000..0eef9a4 --- /dev/null +++ b/drivers/amlogic/media/enhancement/amvecm/pattern_detection.h @@ -0,0 +1,81 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/pattern_detection.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 __PATTERN_DETECTION__ +#define __PATTERN_DETECTION__ +#include + +#define PATTERN_PARAM_COUNT 64 +#define HIST_BIN_COUNT 32 +#define PATTERN_START 0 +#define PATTERN_MAX 8 +#define PATTERN_MASK(i) (1 << (i)) + +#define setting_reg_count 32 +struct setting_regs_s { + unsigned int length; /* Length of total am_reg */ + struct am_reg_s am_reg[setting_reg_count]; +}; + +enum ePattern { + PATTERN_UNKNOWN = -1, + PATTERN_75COLORBAR = PATTERN_START, + PATTERN_SKIN_TONE_FACE, + PATTERN_GREEN_CORN, + PATTERN3, + PATTERN4, + PATTERN5, + PATTERN6, + PATTERN7, + PATTERNMAX = PATTERN_MAX, +}; + +struct pattern { + int pattern_id; + unsigned int *pattern_param; + struct setting_regs_s *cvd2_settings; + struct setting_regs_s *vpp_settings; + int (*checker)(struct vframe_s *vf); + int (*default_loader)(struct vframe_s *vf); + int (*handler)(struct vframe_s *vf, int flag); +}; + +extern int enable_pattern_detect; +extern int pattern_detect_debug; +extern int detected_pattern; +extern int last_detected_pattern; +extern uint pattern_mask; +int pattern_detect_add_checker( + int id, + int (*newchecker)(struct vframe_s *vf)); +int pattern_detect_add_handler( + int id, + int (*newhandler)(struct vframe_s *vf, int flag)); +int pattern_detect_add_defaultloader( + int id, + int (*newloader)(struct vframe_s *vf)); +int pattern_detect_add_cvd2_setting_table( + int id, + struct setting_regs_s *new_settings); +int pattern_detect_add_vpp_setting_table( + int id, + struct setting_regs_s *new_settings); +int init_pattern_detect(void); +int pattern_detect(struct vframe_s *vf); + +#endif + diff --git a/drivers/amlogic/media/enhancement/amvecm/pattern_detection_bar_settings.h b/drivers/amlogic/media/enhancement/amvecm/pattern_detection_bar_settings.h new file mode 100644 index 0000000..22804b4 --- /dev/null +++ b/drivers/amlogic/media/enhancement/amvecm/pattern_detection_bar_settings.h @@ -0,0 +1,285 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/pattern_detection_bar_settings.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 __PATTERN_DETECTION_COLORBAR_SETTINGS__ +#define __PATTERN_DETECTION_COLORBAR_SETTINGS__ + +static struct setting_regs_s colorbar_cvd2_settings[] = { + /* color bar ATV NTSC */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xcc }, + } + }, + /* color bar ATV PAL */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xcc }, + } + }, + /* color bar ATV SECAM */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xcc }, + } + }, + /* color bar AV NTSC */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xc4 }, + } + }, + /* color bar AV PAL */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xc4 }, + } + }, + /* color bar AV SECAM */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xc4 }, + } + }, + /* mixed color bar ATV NTSC */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xcc }, + } + }, + /* mixed color bar ATV PAL */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xcc }, + } + }, + /* mixed color bar ATV SECAM */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xcc }, + } + }, + /* mixed color bar AV NTSC */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xc4 }, + } + }, + /* mixed color bar AV PAL */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xc4 }, + } + }, + /* mixed color bar AV SECAM */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xc4 }, + } + }, + /* default ATV NTSC */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xffffffff }, + } + }, + /* default ATV PAL */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xffffffff }, + } + }, + /* default ATV SECAM */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xffffffff }, + } + }, + /* default AV NTSC */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xffffffff }, + } + }, + /* default AV PAL */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xffffffff }, + } + }, + /* default AV SECAM */ + { + 1, + { + {REG_TYPE_APB, 0xb5, 0xff, 0xffffffff }, + } + } +}; + +static struct setting_regs_s colorbar_vpp_settings[] = { + /* colorbar ATV */ + {0}, {0}, {0}, + /* + *{ + * 2, + * { + * {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xc, 0x4}, + * {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xff000000, 0x4000000}, + * } + *}, + */ + /* colorbar AV NTSC */ + {0}, + /* + *{ + * 2, + * { + * {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xc, 0x4}, + * {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xff000000, 0x4000000}, + * } + *}, + */ + /* colorbar AV PAL */ + {0}, + /* + *{ + * 2, + * { + * {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xc, 0x4}, + * {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xff000000, 0x4000000}, + * } + *}, + */ + /* colorbar AV SECAM */ + {0}, + /* + *{ + * 2, + * { + * {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xc, 0x4}, + * {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xff000000, 0x4000000}, + * } + *}, + */ + /* mixed color bar ATV */ + {0}, {0}, {0}, + /* + *{ + * 2, + * { + * {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xc, 0x4}, + * {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xff000000, 0x4000000}, + * } + *}, + */ + /* mixed color bar AV NTSC */ + {0}, + /* + *{ + * 2, + * { + * {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xc, 0x4}, + * {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xff000000, 0x4000000}, + * } + *}, + */ + /* mixed color bar AV PAL */ + {0}, + /* + *{ + * 2, + * { + * {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xc, 0x4}, + * {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xff000000, 0x4000000}, + * } + *}, + */ + /* mixed color bar AV SECAM */ + {0}, + /* + *{ + * 2, + * { + * {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xc, 0x4}, + * {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xff000000, 0x4000000}, + * } + *}, + */ + /* default ATV */ + {0}, {0}, {0}, + /* + *{ + * 2, + * { + * {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xc, 0x4}, + * {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xff000000, 0x4000000}, + * } + *}, + */ + /* default AV NTSC */ + {0}, + /* + *{ + * 2, + * { + * {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xc, 0x4}, + * {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xff000000, 0x4000000}, + * } + *}, + */ + /* default AV PAL */ + {0}, + /* + *{ + * 2, + * { + * {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xc, 0x4}, + * {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xff000000, 0x4000000}, + * } + *}, + */ + /* default AV SECAM */ + {0}, + /* + *{ + * 2, + * { + * {REG_TYPE_VCBUS, SHARP0_NR_TI_DNLP_BLEND, 0xc, 0x4}, + * {REG_TYPE_VCBUS, SHARP0_HCTI_BST_CORE, 0xff000000, 0x4000000}, + * } + *}, + */ +}; +#endif + diff --git a/drivers/amlogic/media/enhancement/amvecm/pattern_detection_corn_settings.h b/drivers/amlogic/media/enhancement/amvecm/pattern_detection_corn_settings.h new file mode 100644 index 0000000..e19ca48 --- /dev/null +++ b/drivers/amlogic/media/enhancement/amvecm/pattern_detection_corn_settings.h @@ -0,0 +1,53 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/pattern_detection_corn_settings.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 __PATTERN_DETECTION_CORN_SETTINGS__ +#define __PATTERN_DETECTION_CORN_SETTINGS__ + +static struct setting_regs_s corn_cvd2_settings[] = { + /* corn AV NTSC */ + { + 1, + { + {REG_TYPE_APB, 0x153, 0xffffffff, 0x50502020 }, + } + }, + /* corn AV PAL */ + { + 1, + { + {REG_TYPE_APB, 0x153, 0xffffffff, 0x18182020 }, + } + }, + /* default AV NTSC */ + { + 1, + { + {REG_TYPE_APB, 0x153, 0xffffffff, 0xffffffff }, + } + }, + /* default AV PAL */ + { + 1, + { + {REG_TYPE_APB, 0x153, 0xffffffff, 0xffffffff }, + } + }, +}; + +#endif + diff --git a/drivers/amlogic/media/enhancement/amvecm/pattern_detection_face_settings.h b/drivers/amlogic/media/enhancement/amvecm/pattern_detection_face_settings.h new file mode 100644 index 0000000..85154ca --- /dev/null +++ b/drivers/amlogic/media/enhancement/amvecm/pattern_detection_face_settings.h @@ -0,0 +1,65 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/pattern_detection_face_settings.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 __PATTERN_DETECTION_FACE_SETTINGS__ +#define __PATTERN_DETECTION_FACE_SETTINGS__ + +static struct setting_regs_s face_cvd2_settings[] = { + /* face AV NTSC */ + { + 4, + { + {REG_TYPE_APB, 0x16f, 0xffffffff, 0xa00833da }, + {REG_TYPE_APB, 0x194, 0xffffffff, 0x40100160 }, + {REG_TYPE_APB, 0x195, 0xffffffff, 0x00000050 }, + {REG_TYPE_APB, 0x196, 0xffffffff, 0x00000000 }, + } + }, + /* face AV PAL */ + { + 4, + { + {REG_TYPE_APB, 0x16f, 0xffffffff, 0x800833da }, + {REG_TYPE_APB, 0x194, 0xffffffff, 0x4011a293 }, + {REG_TYPE_APB, 0x195, 0xffffffff, 0x34f2038a }, + {REG_TYPE_APB, 0x196, 0xffffffff, 0xfe0df9e8 }, + } + }, + /* default AV NTSC */ + { + 4, + { + {REG_TYPE_APB, 0x16f, 0xffffffff, 0xffffffff }, + {REG_TYPE_APB, 0x194, 0xffffffff, 0xffffffff }, + {REG_TYPE_APB, 0x195, 0xffffffff, 0xffffffff }, + {REG_TYPE_APB, 0x196, 0xffffffff, 0xffffffff }, + } + }, + /* default AV PAL */ + { + 4, + { + {REG_TYPE_APB, 0x16f, 0xffffffff, 0xffffffff }, + {REG_TYPE_APB, 0x194, 0xffffffff, 0xffffffff }, + {REG_TYPE_APB, 0x195, 0xffffffff, 0xffffffff }, + {REG_TYPE_APB, 0x196, 0xffffffff, 0xffffffff }, + } + } +}; + +#endif + diff --git a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c index 47d0d80..7e64cc6 100644 --- a/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c +++ b/drivers/amlogic/media/video_processor/ppmgr/ppmgr_vpp.c @@ -1140,7 +1140,7 @@ static void process_vf_rotate(struct vframe_s *vf, struct vframe_s *new_vf; struct ppframe_s *pp_vf; struct canvas_s cs0, cs1, cs2, cd; - struct vframe_s src_vf; + static struct vframe_s src_vf; int ret = 0; unsigned int cur_angle = 0; int interlace_mode; diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c index 40058c4..bd0956e 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c @@ -247,6 +247,7 @@ static const unsigned int tvafe_pq_reg_trust_table[][2] = { {CVD2_CHROMA_BW_MOTION, 0xff}, /* 0xe8 */ {CVD2_REG_FA, 0xa0}, /* 0xfa */ + {ACD_REG_1B, 0xffffffff}, {ACD_REG_25, 0xffffffff}, {ACD_REG_53, 0xffffffff}, {ACD_REG_54, 0xffffffff}, @@ -257,11 +258,15 @@ static const unsigned int tvafe_pq_reg_trust_table[][2] = { {ACD_REG_64, 0xffffffff}, {ACD_REG_65, 0xffffffff}, {ACD_REG_66, 0x80000ff0}, + {ACD_REG_6F, 0xffffffff}, {ACD_REG_86, 0xc0000000}, {ACD_REG_89, 0x803ff3ff}, {ACD_REG_8A, 0x03ff1fff}, {ACD_REG_8B, 0x0fffffff}, {ACD_REG_8C, 0x0fffffff}, + {ACD_REG_94, 0xffffffff}, + {ACD_REG_95, 0xffffffff}, + {ACD_REG_96, 0xffffffff}, {0xffffffff, 0x00000000}, /* ending */ }; diff --git a/include/linux/amlogic/media/vfm/vframe.h b/include/linux/amlogic/media/vfm/vframe.h index 1335fe3..0272f73 100644 --- a/include/linux/amlogic/media/vfm/vframe.h +++ b/include/linux/amlogic/media/vfm/vframe.h @@ -112,6 +112,8 @@ struct vframe_hist_s { unsigned char vpp_luma_max; unsigned char vpp_luma_min; unsigned short vpp_gamma[64]; + unsigned int vpp_hue_gamma[32]; + unsigned int vpp_sat_gamma[32]; #ifdef AML_LOCAL_DIMMING unsigned int ldim_max[100]; #endif -- 2.7.4