// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
 * drivers/amlogic/media/enhancement/amvecm/amcsc.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.
 *
 */

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
/* Standard Linux headers */
#include <linux/types.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/debugfs.h>
#include <linux/uaccess.h>

#include <linux/amlogic/media/vfm/vframe.h>
#include <linux/amlogic/media/video_common.h>
#include <linux/amlogic/media/amvecm/amvecm.h>
#include <linux/amlogic/media/vout/vout_notify.h>
#include "arch/vpp_regs.h"
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN
#include "../../vin/tvin/tvin_global.h"
#endif
#include "arch/vpp_hdr_regs.h"
#include "arch/hdr_curve.h"
#include <linux/amlogic/media/amvecm/cuva_alg.h>

/* use osd rdma reg w/r */
#include "../../osd/osd_rdma.h"
#endif

#include "amcsc.h"
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
#include "amcsc_pip.h"
#include "set_hdr2_v0.h"
#include "s5_set_hdr2_v0.h"

#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
#include <linux/amlogic/media/amdolbyvision/dolby_vision.h>
#endif
#include <linux/amlogic/media/video_sink/video_signal_notify.h>
#include <linux/amlogic/media/video_sink/video.h>
#include "hdr/am_hdr10_plus.h"
#include "hdr/am_hdr10_plus_ootf.h"
#include "hdr/gamut_convert.h"
#include "hdr/am_hdr10_tm.h"
#include "reg_helper.h"
#include <linux/amlogic/gki_module.h>
#include "color/ai_color.h"
#include "hdr/am_cuva_hdr_tm.h"

uint debug_csc;
static int cur_mvc_type[VD_PATH_MAX];
static int cur_rgb_type[VD_PATH_MAX];
static int rgb_type_proc[VD_PATH_MAX];
static int cur_primesl_type[VD_PATH_MAX];
#define FORCE_RGB_PROCESS 1

module_param(debug_csc, uint, 0664);
MODULE_PARM_DESC(debug_csc, "\n debug_csc\n");

/*used for TV color gamut to panel*/
uint gamut_conv_enable;
module_param(gamut_conv_enable, uint, 0664);
MODULE_PARM_DESC(gamut_conv_enable, "\n gamut_conv_enable\n");

static uint pre_gamut_conv_en;
#endif
signed int vd1_contrast_offset;

signed int saturation_offset;

/*hdr------------------------------------*/

void hdr_osd_off(enum vpp_index_e vpp_index)
{
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	enum hdr_process_sel cur_hdr_process[3];

	cur_hdr_process[0] =
		hdr_func(OSD1_HDR, HDR_BYPASS,
			 NULL, NULL, vpp_index);
	cur_hdr_process[1] =
		hdr_func(OSD2_HDR, HDR_BYPASS,
			 NULL, NULL, vpp_index);
	cur_hdr_process[2] =
		hdr_func(OSD3_HDR, HDR_BYPASS,
			 NULL, NULL, vpp_index);
	pr_csc(8, "am_vecm: module=OSDn_HDR, process=HDR_BYPASS(%d, %d, %d, %d)\n",
	       HDR_BYPASS, cur_hdr_process[0], cur_hdr_process[1], cur_hdr_process[2]);
#endif
}

void hdr_osd2_off(enum vpp_index_e vpp_index)
{
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	enum hdr_process_sel cur_hdr_process;

	cur_hdr_process =
		hdr_func(OSD2_HDR, HDR_BYPASS,
			 NULL, NULL, vpp_index);
	pr_csc(8, "am_vecm: module=OSD2_HDR, process=HDR_BYPASS(%d, %d)\n",
	       HDR_BYPASS, cur_hdr_process);
#endif
}

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
void hdr_osd3_off(enum vpp_index_e vpp_index)
{
	enum hdr_process_sel cur_hdr_process;

	cur_hdr_process =
		hdr_func(OSD3_HDR, HDR_BYPASS,
			 NULL, NULL, vpp_index);
	pr_csc(8, "am_vecm: module=OSD3_HDR, process=HDR_BYPASS(%d, %d)\n",
	       HDR_BYPASS, cur_hdr_process);
}
#endif

void hdr_vd1_off(enum vpp_index_e vpp_index)
{
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	enum hdr_process_sel cur_hdr_process;
	int silce_mode = 1;

	if (is_meson_s5_cpu())
		silce_mode = 4;/*bypass 4 vd1 slice no matter vd1 slice num*/
	else if (is_meson_t3x_cpu())
		silce_mode = 2;

	if (silce_mode == VD1_1SLICE) {
		cur_hdr_process =
			hdr_func(VD1_HDR, HDR_BYPASS,
				NULL, NULL, vpp_index);
	} else if (silce_mode == VD1_2SLICE) {
		cur_hdr_process =
			hdr_func(VD1_HDR, HDR_BYPASS,
				NULL, NULL, vpp_index);
		cur_hdr_process =
			hdr_func(S5_VD1_SLICE1, HDR_BYPASS,
				NULL, NULL, vpp_index);
	} else if (silce_mode == VD1_4SLICE) {
		cur_hdr_process =
			hdr_func(VD1_HDR, HDR_BYPASS,
				NULL, NULL, vpp_index);
		cur_hdr_process =
			hdr_func(S5_VD1_SLICE1, HDR_BYPASS,
				NULL, NULL, vpp_index);
		cur_hdr_process =
			hdr_func(S5_VD1_SLICE2, HDR_BYPASS,
				NULL, NULL, vpp_index);
		cur_hdr_process =
			hdr_func(S5_VD1_SLICE3, HDR_BYPASS,
				NULL, NULL, vpp_index);
	}
	pr_csc(8, "am_vecm: module=VD1_HDR, process=HDR_BYPASS(%d, %d)\n",
		HDR_BYPASS, cur_hdr_process);
#endif
}

void hdr_vd2_off(enum vpp_index_e vpp_index)
{
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	enum hdr_process_sel cur_hdr_process;

	cur_hdr_process =
		hdr_func(VD2_HDR, HDR_BYPASS,
			 NULL, NULL, vpp_index);
	pr_csc(8, "am_vecm: module=VD2_HDR, process=HDR_BYPASS(%d, %d)\n",
	       HDR_BYPASS, cur_hdr_process);
#endif
}

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
void hdr_vd3_off(enum vpp_index_e vpp_index)
{
	enum hdr_process_sel cur_hdr_process;

	cur_hdr_process =
		hdr_func(VD3_HDR, HDR_BYPASS,
			 NULL, NULL, vpp_index);
	pr_csc(8, "am_vecm: module=VD3_HDR, process=HDR_BYPASS(%d, %d)\n",
	       HDR_BYPASS, cur_hdr_process);
}
#endif

void hdr_vd1_iptmap(enum vpp_index_e vpp_index)
{
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	enum hdr_process_sel cur_hdr_process;
	int s5_silce_mode = get_s5_slice_mode();

	if (s5_silce_mode == VD1_1SLICE) {
		cur_hdr_process =
			hdr_func(VD1_HDR, IPT_MAP,
				 NULL, NULL, vpp_index);
	} else if (s5_silce_mode == VD1_2SLICE) {
		cur_hdr_process =
			hdr_func(VD1_HDR, IPT_MAP,
				 NULL, NULL, vpp_index);
		cur_hdr_process =
			hdr_func(S5_VD1_SLICE1, IPT_MAP,
				 NULL, NULL, vpp_index);
	} else if (s5_silce_mode == VD1_4SLICE) {
		cur_hdr_process =
			hdr_func(VD1_HDR, IPT_MAP,
				 NULL, NULL, vpp_index);
		cur_hdr_process =
			hdr_func(S5_VD1_SLICE1, IPT_MAP,
				 NULL, NULL, vpp_index);
		cur_hdr_process =
			hdr_func(S5_VD1_SLICE2, IPT_MAP,
				 NULL, NULL, vpp_index);
		cur_hdr_process =
			hdr_func(S5_VD1_SLICE3, IPT_MAP,
				 NULL, NULL, vpp_index);
	}
	pr_csc(8, "module=VD1_HDR, process=IPT_MAP(%d, %d)\n",
	       IPT_MAP, cur_hdr_process);
#endif
}

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static struct hdr_data_t *phdr;

struct hdr_data_t *hdr_get_data(void)
{
	return phdr;
}

int is_hdr_cfg_osd_100(void)
{
	int ret = 0;

	if (phdr) {
		if (phdr->hdr_cfg.en_osd_lut_100)
			ret = phdr->hdr_cfg.en_osd_lut_100;
	}

	return ret;
}

void hdr_set_cfg_osd_100(int val)
{
	if (val > 0)
		phdr->hdr_cfg.en_osd_lut_100 = val;
	else
		phdr->hdr_cfg.en_osd_lut_100 = 0;
}

static ssize_t read_file_hdr_cfgosd(struct file *file, char __user *userbuf,
				    size_t count, loff_t *ppos)
{
	char buf[20];
	ssize_t len;

	len = snprintf(buf, 20, "%d\n", phdr->hdr_cfg.en_osd_lut_100);
	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
}

static ssize_t write_file_hdr_cfgosd(struct file *file,
				     const char __user *userbuf,
				     size_t count, loff_t *ppos)
{
	int val;
	char buf[20];
	int ret = 0;
	int cont2;

	cont2 = min_t(size_t, count, (sizeof(buf) - 1));
	if (copy_from_user(buf, userbuf, cont2))
		return -EFAULT;
	buf[cont2] = 0;
	ret = kstrtoint(buf, 0, &val);
	if (ret != 0) {
		pr_info("cfg_en_osd_100 do nothing!\n");
		return -EINVAL;
	}

	hdr_set_cfg_osd_100(val);

	pr_info("HDR: en_osd_lut_100: %d\n", phdr->hdr_cfg.en_osd_lut_100);

	return count;
}

static const struct file_operations file_ops_hdr_cfgosd = {
	.open		= simple_open,
	.read		= read_file_hdr_cfgosd,
	.write		= write_file_hdr_cfgosd,
};

struct hdr_debugfs_files_t {
	const char *name;
	const umode_t mode;
	const struct file_operations *fops;
};

static struct hdr_debugfs_files_t hdr_debugfs_files[] = {
	{"cfg_en_osd_100", S_IFREG | 0644, &file_ops_hdr_cfgosd},

};

static void hdr_debugfs_init(void)
{
	int i;
	struct dentry *ent;

	if (!phdr)
		return;

	if (phdr->dbg_root)
		return;

	phdr->dbg_root = debugfs_create_dir("hdr", NULL);
	if (!phdr->dbg_root) {
		pr_err("can't create debugfs dir hdr\n");
		return;
	}

	for (i = 0; i < ARRAY_SIZE(hdr_debugfs_files); i++) {
		ent =
		debugfs_create_file(hdr_debugfs_files[i].name,
				    hdr_debugfs_files[i].mode,
				    phdr->dbg_root, NULL,
				    hdr_debugfs_files[i].fops);
		if (!ent)
			pr_err("debugfs create failed\n");
	}
}

static void hdr_debugfs_exit(void)
{
	if (phdr && phdr->dbg_root)
		debugfs_remove(phdr->dbg_root);
}

void hdr_init(struct hdr_data_t *phdr_data)
{
	if (phdr_data) {
		phdr = phdr_data;
	} else {
		phdr = NULL;
		pr_err("%s failed\n", __func__);
		return;
	}

	hdr_debugfs_init();
}

void hdr_exit(void)
{
	hdr_debugfs_exit();
}

/*-----------------------------------------*/
static void vpp_set_mtx_en_read(void);
static void vpp_set_mtx_en_write(void);
#endif

struct hdr_osd_reg_s hdr_osd_reg = {
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	0x00000001, /* VIU_OSD1_MATRIX_CTRL 0x1a90 */
	0x00ba0273, /* VIU_OSD1_MATRIX_COEF00_01 0x1a91 */
	0x003f1f9a, /* VIU_OSD1_MATRIX_COEF02_10 0x1a92 */
	0x1ea801c0, /* VIU_OSD1_MATRIX_COEF11_12 0x1a93 */
	0x01c01e6a, /* VIU_OSD1_MATRIX_COEF20_21 0x1a94 */
	0x00000000, /* VIU_OSD1_MATRIX_COLMOD_COEF42 0x1a95 */
	0x00400200, /* VIU_OSD1_MATRIX_OFFSET0_1 0x1a96 */
	0x00000200, /* VIU_OSD1_MATRIX_PRE_OFFSET2 0x1a97 */
	0x00000000, /* VIU_OSD1_MATRIX_PRE_OFFSET0_1 0x1a98 */
	0x00000000, /* VIU_OSD1_MATRIX_PRE_OFFSET2 0x1a99 */
	0x1fd80000, /* VIU_OSD1_MATRIX_COEF22_30 0x1a9d */
	0x00000000, /* VIU_OSD1_MATRIX_COEF31_32 0x1a9e */
	0x00000000, /* VIU_OSD1_MATRIX_COEF40_41 0x1a9f */
	0x00000000, /* VIU_OSD1_EOTF_CTL 0x1ad4 */
	0x08000000, /* VIU_OSD1_EOTF_COEF00_01 0x1ad5 */
	0x00000000, /* VIU_OSD1_EOTF_COEF02_10 0x1ad6 */
	0x08000000, /* VIU_OSD1_EOTF_COEF11_12 0x1ad7 */
	0x00000000, /* VIU_OSD1_EOTF_COEF20_21 0x1ad8 */
	0x08000001, /* VIU_OSD1_EOTF_COEF22_RS 0x1ad9 */
	0x0,        /* VIU_OSD1_EOTF_3X3_OFST_0 0x1aa0 */
	0x0,        /* VIU_OSD1_EOTF_3X3_OFST_1 0x1aa1 */
	0x01c00000, /* VIU_OSD1_OETF_CTL 0x1adc */
	{
		/* eotf table */
		{ /* r map */
			0x0000, 0x0200, 0x0400, 0x0600, 0x0800, 0x0a00,
			0x0c00, 0x0e00, 0x1000, 0x1200, 0x1400, 0x1600,
			0x1800, 0x1a00, 0x1c00, 0x1e00, 0x2000, 0x2200,
			0x2400, 0x2600, 0x2800, 0x2a00, 0x2c00, 0x2e00,
			0x3000, 0x3200, 0x3400, 0x3600, 0x3800, 0x3a00,
			0x3c00, 0x3e00, 0x4000
		},
		{ /* g map */
			0x0000, 0x0200, 0x0400, 0x0600, 0x0800, 0x0a00,
			0x0c00, 0x0e00, 0x1000, 0x1200, 0x1400, 0x1600,
			0x1800, 0x1a00, 0x1c00, 0x1e00, 0x2000, 0x2200,
			0x2400, 0x2600, 0x2800, 0x2a00, 0x2c00, 0x2e00,
			0x3000, 0x3200, 0x3400, 0x3600, 0x3800, 0x3a00,
			0x3c00, 0x3e00, 0x4000
		},
		{ /* b map */
			0x0000, 0x0200, 0x0400, 0x0600, 0x0800, 0x0a00,
			0x0c00, 0x0e00, 0x1000, 0x1200, 0x1400, 0x1600,
			0x1800, 0x1a00, 0x1c00, 0x1e00, 0x2000, 0x2200,
			0x2400, 0x2600, 0x2800, 0x2a00, 0x2c00, 0x2e00,
			0x3000, 0x3200, 0x3400, 0x3600, 0x3800, 0x3a00,
			0x3c00, 0x3e00, 0x4000
		},
		/* oetf table */
		{ /* or map */
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000
		},
		{ /* og map */
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000
		},
		{ /* ob map */
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
			0x0000, 0x0000, 0x0000, 0x0000, 0x0000
		}
	},
	-1 /* shadow mode */
#endif
};

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
#define HDR_VERSION   "----gxl_20180830---hdrv2_20200106-----\n"

static struct vframe_s *dbg_vf[VD_PATH_MAX] = {NULL, NULL};
struct master_display_info_s dbg_hdr_send;
static struct hdr_info receiver_hdr_info;

/* extra hdr process code, updated per signal change */
static u32 hdr_ex;

static bool print_lut_mtx;
module_param(print_lut_mtx, bool, 0664);
MODULE_PARM_DESC(print_lut_mtx, "\n print_lut_mtx\n");

/* bit 0: enable csc */
/* bit 1: enable osd csc */
/* bit 2: enable video csc */
/* bit 4: csc delay one frame */
static uint csc_en = 0x7;
module_param(csc_en, uint, 0664);
MODULE_PARM_DESC(csc_en, "\n csc_en\n");

/* white balance adjust */
static bool cur_eye_protect_mode;

static int num_wb_val = 10;
static int wb_val[10] = {
	0, /* wb enable */
	0, /* -1024~1023, r_pre_offset */
	0, /* -1024~1023, g_pre_offset */
	0, /* -1024~1023, b_pre_offset */
	1024, /* 0~2047, r_gain */
	1024, /* 0~2047, g_gain */
	1024, /* 0~2047, b_gain */
	0, /* -1024~1023, r_post_offset */
	0, /* -1024~1023, g_post_offset */
	0  /* -1024~1023, b_post_offset */
};
module_param_array(wb_val, int, &num_wb_val, 0664);
MODULE_PARM_DESC(wb_val, "\n white balance setting\n");

static enum vframe_source_type_e pre_src_type[VD_PATH_MAX] = {
	VFRAME_SOURCE_TYPE_COMP,
	VFRAME_SOURCE_TYPE_COMP,
	VFRAME_SOURCE_TYPE_COMP
};

static unsigned int vpp_top_max = VPP_TOP_MAX_S;
#endif
static unsigned int vd_path_max = VD_PATH_MAX;

uint cur_csc_type[VD_PATH_MAX] = {0xffff, 0xffff, 0xffff};
module_param_array(cur_csc_type, uint, &vd_path_max, 0444);
MODULE_PARM_DESC(cur_csc_type, "\n current color space convert type\n");

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static uint hdmi_csc_type = 0xffff;
module_param(hdmi_csc_type, uint, 0444);
MODULE_PARM_DESC(hdmi_csc_type, "\n current color space convert type\n");
#endif

/* Android U force mode: hdr_policy = 4 */
/* 0: follow sink, 1: follow source, 2: debug, 0xff: bootup default value */
/* by default follow source to match default sdr_mode*/
static uint hdr_policy;
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static uint cur_hdr_policy = 0xff;
#endif
module_param(hdr_policy, uint, 0664);
MODULE_PARM_DESC(hdr_policy, "\n current hdr_policy\n");

/* 0: source: use src meta */
/* 1: Auto: 601/709=709 P3/2020=P3 */
/* 2: Native: 601/709=off P3/2020=2020 */
static uint primary_policy;
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static uint cur_primary_policy;
#endif
module_param(primary_policy, uint, 0664);
MODULE_PARM_DESC(primary_policy, "\n current primary_policy\n");
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
int boot_hdr_policy(char *str)
{
	if (strncmp("1", str, 1) == 0) {
		hdr_policy = 1; /*follow source*/
		pr_debug("boot hdr_policy: 1\n");
	} else if (strncmp("0", str, 1) == 0) {
		hdr_policy = 0; /*follow sink*/
		pr_debug("boot hdr_policy: 0\n");
	} else if (strncmp("2", str, 1) == 0) {
		hdr_policy = 2; /*force policy for vivid*/
		pr_debug("boot hdr_policy: 2\n");
	} else if (strncmp("4", str, 1) == 0) {
		hdr_policy = 4; /*force policy for u*/
		pr_debug("boot hdr_policy: 4\n");
	}
	return 0;
}
__setup("hdr_policy=", boot_hdr_policy);

int boot_hdr_debug(char *str)
{
	u32 cur_debug_csc = 0;

	if (strncmp("4", str, 1) == 0) {
		/* print more csc/dv log and disable flush hdr */
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
		debug_dolby = 0x103;
#endif
		debug_csc = 0xf;
		disable_flush_flag = 0xffffffff;
		cur_debug_csc = 4;
	} else if (strncmp("3", str, 1) == 0) {
		/* print more csc/dv log */
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
		debug_dolby = 0x103;
#endif
		debug_csc = 0xf;
		cur_debug_csc = 3;
	} else if (strncmp("2", str, 1) == 0) {
		/* only print csc/dv trigger status */
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
		debug_dolby = 0x100;
#endif
		debug_csc = 0xc;
		cur_debug_csc = 2;
	} else if (strncmp("1", str, 1) == 0) {
		/* only disable flush hdr core */
		disable_flush_flag = 0xffffffff;
		cur_debug_csc = 1;
	}
	if (cur_debug_csc)
		pr_info("enable hdr_debug: %d\n", cur_debug_csc);
	return 0;
}
__setup("hdr_debug=", boot_hdr_debug);
#endif

/* when get_hdr_policy() == 0 */
/* enum output_format_e */
/*	BT709 = 1,				*/
/*	BT2020 = 2,				*/
/*	BT2020_PQ = 3,			*/
/*	BT2020_PQ_DYNAMIC = 4,	*/
/*	BT2020_HLG = 5,			*/
/*	BT2100_IPT = 6			*/
/*	BT_BYPASS = 7			*/
/* BT2020 = 2: 2020 + gamma not support in hdmi now */
static uint force_output; /* 0: no force */
module_param(force_output, uint, 0664);
MODULE_PARM_DESC(force_output, "\n current force_output\n");

int boot_hdr_force_mode(char *str)
{
	if (strncmp("3", str, 1) == 0) {
		force_output = 3; /*force hdr10*/
		pr_debug("boot output format: hdr10\n");
	} else if (strncmp("5", str, 1) == 0) {
		force_output = 5; /*force hlg*/
		pr_debug("boot output format: hlg\n");
	}
	return 0;
}
__setup("hdr_force_mode=", boot_hdr_force_mode);

int get_primary_policy(void)
{
	return primary_policy;
}
EXPORT_SYMBOL(get_primary_policy);

int get_hdr_policy(void)
{
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	int dv_policy = 0;
	int dv_mode = 0;

	if (is_amdv_enable()) {
		/* sync hdr_policy with dolby_vision_policy */
		/* get current dolby_vision_mode */
		dv_policy = get_amdv_policy();
		dv_mode = get_amdv_target_mode();
		if (dv_policy != AMDV_FORCE_OUTPUT_MODE ||
		    dv_mode != AMDV_OUTPUT_MODE_BYPASS) {
			/* use dv policy when not force bypass */
			return dv_policy;
		}
	}
#endif
#endif
	return hdr_policy;
}
EXPORT_SYMBOL(get_hdr_policy);

void set_hdr_policy(int policy)
{
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
	if (is_amdv_enable())
		set_amdv_policy(policy);
	#endif
	hdr_policy = policy;
#endif
}
EXPORT_SYMBOL(set_hdr_policy);

void set_cur_hdr_policy(uint policy)
{
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	cur_hdr_policy = policy;
#endif
}
EXPORT_SYMBOL(set_cur_hdr_policy);

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
enum output_format_e get_force_output(void)
{
	return force_output;
}
EXPORT_SYMBOL(get_force_output);
#endif

void set_force_output(enum output_format_e output)
{
	force_output = output;
}
EXPORT_SYMBOL(set_force_output);

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static uint hdr_mode = 2; /* 0: hdr->hdr, 1:hdr->sdr, 2:auto */
module_param(hdr_mode, uint, 0664);
MODULE_PARM_DESC(hdr_mode, "\n set hdr_mode\n");

/* 0:hdr->hdr, 1:hdr->sdr, 2:hdr->hlg, 3:hdr->cuva */
/* 4:hdr->cuva_hlg*/
uint hdr_process_mode[VD_PATH_MAX];
uint cur_hdr_process_mode[VD_PATH_MAX] = {PROC_OFF, PROC_OFF, PROC_OFF};
module_param_array(hdr_process_mode, uint, &vd_path_max, 0444);
MODULE_PARM_DESC(hdr_process_mode, "\n current hdr_process_mode\n");

/* 0:bypass, 1:hdr10p->hdr, 2:hdr10p->sdr, 3:hdr10p->hlg */
/* 4:hdr10p->cuva, 5:hdr10p->cuva_hlg*/
uint hdr10_plus_process_mode[VD_PATH_MAX];
uint cur_hdr10_plus_process_mode[VD_PATH_MAX] = {PROC_OFF, PROC_OFF, PROC_OFF};
module_param_array(hdr10_plus_process_mode, uint, &vd_path_max, 0444);
MODULE_PARM_DESC(hdr10_plus_process_mode, "\n current hdr10_plus_process_mode\n");

/* 0:hlg->hlg, 1:hlg->sdr 2:hlg->hdr, 3:hlg->cuva*/
/* 4:hdr->cuva_hlg*/
uint hlg_process_mode[VD_PATH_MAX];
uint cur_hlg_process_mode[VD_PATH_MAX] = {PROC_OFF, PROC_OFF, PROC_OFF};
module_param_array(hlg_process_mode, uint, &vd_path_max, 0444);
MODULE_PARM_DESC(hlg_process_mode, "\n current hlg_process_mode\n");

/* 0:bypass, 1:cuva->sdr, 2:cuva->hdr, 3:cuva->hlg */
/* 4:cuva->hdr10p, 5:cuva->cuva_hlg*/
uint cuva_hdr_process_mode[VD_PATH_MAX];
uint cur_cuva_hdr_process_mode[VD_PATH_MAX] = {PROC_OFF, PROC_OFF, PROC_OFF};
module_param_array(cuva_hdr_process_mode, uint, &vd_path_max, 0444);
MODULE_PARM_DESC(cuva_hdr_process_mode, "\n current cuva_hdr_process_mode\n");

/* 0:bypass, 1:cuva_hlg->sdr, 2:cuva_hlg->hdr, 3:cuva_hlg->hlg */
/* 4:cuva_hlg->hdr, 5:cuva_hlg->cuva*/
uint cuva_hlg_process_mode[VD_PATH_MAX];
uint cur_cuva_hlg_process_mode[VD_PATH_MAX] = {PROC_OFF, PROC_OFF, PROC_OFF};
module_param_array(cuva_hlg_process_mode, uint, &vd_path_max, 0444);
MODULE_PARM_DESC(cuva_hlg_process_mode, "\n current cuva_hlg_process_mode\n");

/* 0: tx don't support hdr10+, 1: tx support hdr10+*/
uint tx_hdr10_plus_support;

static uint force_pure_hlg[VD_PATH_MAX];
module_param_array(force_pure_hlg, uint, &vd_path_max, 0664);
MODULE_PARM_DESC(force_pure_hlg, "\n current force_pure_hlg\n");

uint sdr_mode; /* 0: sdr->sdr, 1:sdr->hdr, 2:auto */
module_param(sdr_mode, uint, 0664);
MODULE_PARM_DESC(sdr_mode, "\n set sdr_mode\n");

static uint cur_sdr_mode;

/* 0: sdr->sdr, 1:sdr->hdr, 2:sdr->hlg, 3:sdr->cuva, 4:sdr->cuva_hlg*/
uint sdr_process_mode[VD_PATH_MAX];
uint cur_sdr_process_mode[VD_PATH_MAX] = {PROC_OFF, PROC_OFF, PROC_OFF};
module_param_array(sdr_process_mode, uint, &vd_path_max, 0444);
MODULE_PARM_DESC(sdr_process_mode, "\n current hdr_process_mode\n");

static int sdr_saturation_offset = 20; /* 0: sdr->sdr, 1:sdr->hdr */
module_param(sdr_saturation_offset, int, 0664);
MODULE_PARM_DESC(sdr_saturation_offset, "\n add saturation\n");

static uint force_csc_type = 0xff;
module_param(force_csc_type, uint, 0664);
MODULE_PARM_DESC(force_csc_type, "\n force colour space convert type\n");

static uint cur_hdr_support[VPP_TOP_MAX_S];
module_param_array(cur_hdr_support, uint, &vpp_top_max, 0444);
MODULE_PARM_DESC(cur_hdr_support, "\n current cur_hdr_support\n");


static uint cur_colorimetry_support[VPP_TOP_MAX_S];
module_param_array(cur_colorimetry_support, uint, &vpp_top_max, 0444);
MODULE_PARM_DESC(cur_colorimetry_support, "\n current cur_colorimetry_support\n");

static uint cur_hlg_support[VPP_TOP_MAX_S];
module_param_array(cur_hlg_support, uint, &vpp_top_max, 0444);
MODULE_PARM_DESC(cur_hlg_support, "\n current cur_hlg_support\n");


static uint cur_color_fmt[VPP_TOP_MAX_S];
module_param_array(cur_color_fmt, uint, &vpp_top_max, 0664);
MODULE_PARM_DESC(cur_color_fmt, "\n current cur_color_fmt\n");

static uint range_control;
module_param(range_control, uint, 0664);
MODULE_PARM_DESC(range_control, "\n range_control 0:limit 1:full\n");

/* bit 0: use source primary,*/
/* bit 1: use display primary,*/
/* bit 2: adjust contrast according to source lumin,*/
/* bit 3: adjust saturation according to source lumin */
/* bit 4: convert HLG to HDR if sink not supprot HLG but HDR */
uint hdr_flag = (1 << 0) | (1 << 1) | (0 << 2) | (0 << 3) | (1 << 4);
module_param(hdr_flag, uint, 0664);
MODULE_PARM_DESC(hdr_flag, "\n set hdr_flag\n");
#endif

/* 0: off, 1: normal, 2: bypass */
static int video_process_status[VD_PATH_MAX] = {2, 2, 2};
module_param_array(video_process_status, uint, &vd_path_max, 0664);
MODULE_PARM_DESC(video_process_status, "\n video_process_status\n");

void set_hdr_module_status(enum vd_path_e vd_path, int status)
{
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	video_process_status[vd_path] = status;

#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
	pr_csc(4, "%d: set video_process_status[VD%d] = %d, dv %s %s %d\n",
	       __LINE__,

	       vd_path + 1, status,
	       is_amdv_enable() ? "en" : "",
	       is_amdv_on() ? "on" : "",
	       get_dv_support_info());
#else
	pr_csc(4, "%d: set video_process_status[VD%d] = %d\n",
	       __LINE__,
	       vd_path + 1, status);
#endif
#endif
}
EXPORT_SYMBOL(set_hdr_module_status);

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
#define PROC_FLAG_FORCE_PROCESS 1
static uint video_process_flags[VD_PATH_MAX];
module_param_array(video_process_flags, uint, &vd_path_max, 0664);
MODULE_PARM_DESC(video_process_flags, "\n video_process_flags\n");

static uint rdma_flag =
	(1 << VPP_MATRIX_OSD) |
	(1 << VPP_MATRIX_VD1) |
	(1 << VPP_MATRIX_VD2) |
	(1 << VPP_MATRIX_POST) |
	(1 << VPP_MATRIX_XVYCC);
module_param(rdma_flag, uint, 0664);
MODULE_PARM_DESC(rdma_flag, "\n set rdma_flag\n");

#define MAX_KNEE_SETTING	35
/* recommended setting for 100 nits panel: */
/* 0,16,96,224,320,544,720,864,1000,1016,1023 */
/* knee factor = 256 */
static int num_knee_setting = MAX_KNEE_SETTING;
static int knee_setting[MAX_KNEE_SETTING] = {
	/* 0, 16, 96, 224, 320, 544, 720, 864, 1000, 1016, 1023 */
	0, 16, 36, 59, 71, 96,
	120, 145, 170, 204, 230, 258,
	288, 320, 355, 390, 428, 470,
	512, 554, 598, 650, 720, 758,
	790, 832, 864, 894, 920, 945,
	968, 980, 1000, 1016, 1023
};

static int num_knee_linear_setting = MAX_KNEE_SETTING;
static int knee_linear_setting[MAX_KNEE_SETTING] = {
	0x000,
	0x010,
	0x02f,
	0x04e,
	0x06d,
	0x08c,
	0x0ab,
	0x0ca,
	0x0e9,
	0x108,
	0x127,
	0x146,
	0x165,
	0x184,
	0x1a3,
	0x1c2,
	0x1e1,
	0x200,
	0x21f,
	0x23e,
	0x25d,
	0x27c,
	0x29b,
	0x2ba,
	0x2d9,
	0x2f8,
	0x317,
	0x336,
	0x355,
	0x374,
	0x393,
	0x3b2,
	0x3d1,
	0x3f0,
	0x3ff
};

static bool lut_289_en = 1;
module_param(lut_289_en, bool, 0664);
MODULE_PARM_DESC(lut_289_en, "\n if enable 289 lut\n");

/*for gxtvbb(968), only 289 point lut for hdr curve set */
/*default for 350nit panel*/
unsigned int lut_289_mapping[LUT_289_SIZE] = {
	   0,    0,    0,    0,    0,    0,    0,    0,
	   0,    0,    0,    0,    0,    0,    0,    0,
	   0x9, 0xa, 0xb, 0xd, 0xe, 0x10, 0x11, 0x12,
	  0x14, 0x15, 0x17, 0x18, 0x1a, 0x1c, 0x1d, 0x1f,
	  0x20, 0x22, 0x24, 0x26, 0x27, 0x29, 0x2b, 0x2d,
	 0x2f,  0x31,  0x33,  0x35,  0x37,  0x39,  0x3b,  0x3d,
	 0x40,  0x42,  0x44,  0x46,  0x49,  0x4b,  0x4e,  0x50,
	 0x53,  0x55,  0x58,  0x5a,  0x5d,  0x60,  0x62,  0x65,
	 0x68,  0x6b,  0x6e,  0x71,  0x74,  0x77,  0x7a,  0x7e,
	 0x81,  0x84,  0x87,  0x8b,  0x8e,  0x92,  0x95,  0x99,
	 0x9d,  0xa1,  0xa4,  0xa8,  0xac,  0xb0,  0xb4,  0xb8,
	 0xbc,  0xc1,  0xc5,  0xc9,  0xce,  0xd2,  0xd7,  0xdc,
	 0xe0,  0xe5,  0xea,  0xef,  0xf4,  0xf9,  0xfe,  0x104,
	 0x109,  0x10e,  0x114,  0x11a,  0x11f,  0x125,  0x12b,  0x131,
	 0x137,  0x13d,  0x143,  0x14a,  0x150,  0x156,  0x15d,  0x164,
	 0x16b,  0x172,  0x179,  0x180,  0x187,  0x18e,  0x196,  0x19d,
	 0x1a5,  0x1ad,  0x1b5,  0x1bd,  0x1c5,  0x1cd,  0x1d6,  0x1de,
	 0x1e7,  0x1f0,  0x1f9,  0x202,  0x20b,  0x214,  0x21e,  0x227,
	 0x231,  0x23b,  0x245,  0x24f,  0x25a,  0x264,  0x26f,  0x27a,
	 0x285,  0x290,  0x29c,  0x2a7,  0x2b3,  0x2bf,  0x2cb,  0x2d7,
	 0x2e3,  0x2f0,  0x2fd,  0x30a,  0x317,  0x325,  0x332,  0x33e,
	 0x34a,  0x356,  0x362,  0x36d,  0x377,  0x381,  0x38b,  0x394,
	 0x39c,  0x3a4,  0x3ac,  0x3b3,  0x3ba,  0x3c1,  0x3c7,  0x3cd,
	 0x3d2,  0x3d7,  0x3db,  0x3df,  0x3e3,  0x3e6,  0x3e9,  0x3ec,
	 0x3ef,  0x3f1,  0x3f3,  0x3f5,  0x3f6,  0x3f7,  0x3f8,  0x3f9,
	 0x3fa,  0x3fa,  0x3fb,  0x3fb,  0x3fb,  0x3fc,  0x3fc,  0x3fc,
	 0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,
	 0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,
	 0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,
	 0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,
	 0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,
	 0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,
	 0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,  0x3fc,
	 0x3fc, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff,
	0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff,
	0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0x3ff,
	0x3ff
};

static int knee_factor; /* 0 ~ 256, 128 = 0.5 */
static int knee_interpolation_mode = 1; /* 0: linear, 1: cubic */

module_param_array(knee_setting, int, &num_knee_setting, 0664);
MODULE_PARM_DESC(knee_setting, "\n knee_setting, 256=1.0\n");

module_param_array(knee_linear_setting, int, &num_knee_linear_setting, 0444);
MODULE_PARM_DESC(knee_linear_setting, "\n reference linear knee_setting\n");

module_param(knee_factor, int, 0664);
MODULE_PARM_DESC(knee_factor, "\n knee_factor, 255=1.0\n");

module_param(knee_interpolation_mode, int, 0664);
MODULE_PARM_DESC(knee_interpolation_mode, "\n 0: linear, 1: cubic\n");

#define NUM_MATRIX_PARAM 16
static uint num_customer_matrix_param = NUM_MATRIX_PARAM;
static uint customer_matrix_param[NUM_MATRIX_PARAM] = {
	0, 0, 0,
	0x0d49, 0x1b4d, 0x1f6b,
	0x1f01, 0x0910, 0x1fef,
	0x1fdb, 0x1f32, 0x08f3,
	0, 0, 0,
	1
};

static bool customer_matrix_en = true;

#define INORM	50000
#define BL		16

static u32 bt709_primaries[3][2] = {
	{0.30 * INORM + 0.5, 0.60 * INORM + 0.5},	/* G */
	{0.15 * INORM + 0.5, 0.06 * INORM + 0.5},	/* B */
	{0.64 * INORM + 0.5, 0.33 * INORM + 0.5},	/* R */
};

static u32 bt709_white_point[2] = {
	0.3127 * INORM + 0.5, 0.3290 * INORM + 0.5
};

static u32 bt2020_primaries[3][2] = {
	{0.17 * INORM + 0.5, 0.797 * INORM + 0.5},	/* G */
	{0.131 * INORM + 0.5, 0.046 * INORM + 0.5},	/* B */
	{0.708 * INORM + 0.5, 0.292 * INORM + 0.5},	/* R */
};

static u32 bt2020_white_point[2] = {
	0.3127 * INORM + 0.5, 0.3290 * INORM + 0.5
};

/* 0: off, 1: on */
static int customer_master_display_en;
static uint num_customer_master_display_param = 12;
static uint customer_master_display_param[12] = {
	0.17 * INORM + 0.5, 0.797 * INORM + 0.5,      /* G */
	0.131 * INORM + 0.5, 0.046 * INORM + 0.5,     /* B */
	0.708 * INORM + 0.5, 0.292 * INORM + 0.5,     /* R */
	0.3127 * INORM + 0.5, 0.3290 * INORM + 0.5,   /* W */
	5000 * 10000, 50,
	/* man/min lumin */
	5000, 50
	/* content lumin and frame average */
};

static int customer_panel_lumin = 380;
module_param(customer_panel_lumin, int, 0664);
MODULE_PARM_DESC(customer_panel_lumin, "\n customer_panel_lumin\n");

int customer_hdr_clipping;
module_param(customer_hdr_clipping, int, 0664);
MODULE_PARM_DESC(customer_hdr_clipping, "\n customer_hdr_clipping\n");

module_param(customer_matrix_en, bool, 0664);
MODULE_PARM_DESC(customer_matrix_en, "\n if enable customer matrix\n");

module_param_array(customer_matrix_param, uint,
		   &num_customer_matrix_param, 0664);
MODULE_PARM_DESC(customer_matrix_param,
		 "\n matrix from source primary to panel primary\n");

module_param(customer_master_display_en, int, 0664);
MODULE_PARM_DESC(customer_master_display_en,
		 "\n if enable customer primaries and white point\n");

module_param_array(customer_master_display_param, uint,
		   &num_customer_master_display_param, 0664);
MODULE_PARM_DESC(customer_master_display_param,
		 "\n matrix from source primary and white point\n");

/* 0: off, 1: on */
static int customer_hdmi_display_en;
static uint num_customer_hdmi_display_param = 14;
static uint customer_hdmi_display_param[14] = {
	9, /* color primary = bt2020 */
	16, /* characteristic = st2084 */
	0.17 * INORM + 0.5, 0.797 * INORM + 0.5,      /* G */
	0.131 * INORM + 0.5, 0.046 * INORM + 0.5,     /* B */
	0.708 * INORM + 0.5, 0.292 * INORM + 0.5,     /* R */
	0.3127 * INORM + 0.5, 0.3290 * INORM + 0.5,   /* W */
	9997 * 10000, 0,
	/* man/min lumin */
	5000, 50
	/* content lumin and frame average */
};

module_param(customer_hdmi_display_en, int, 0664);
MODULE_PARM_DESC(customer_hdmi_display_en,
		 "\n if enable customer primaries and white point\n");

module_param_array(customer_hdmi_display_param, uint,
		   &num_customer_hdmi_display_param, 0664);
MODULE_PARM_DESC(customer_hdmi_display_param,
		 "\n matrix from source primary and white point\n");

/* sat offset when > 1200 and <= 1200 */
static uint num_extra_sat_lut = 2;
static uint extra_sat_lut[] = {16, 32};
module_param_array(extra_sat_lut, uint,
		   &num_extra_sat_lut, 0664);
MODULE_PARM_DESC(extra_sat_lut,
		 "\n lookup table for saturation match source luminance.\n");

/* norm to 128 as 1, LUT can be changed */
static uint num_extra_con_lut = 5;
static uint extra_con_lut[] = {144, 136, 132, 130, 128};
module_param_array(extra_con_lut, uint,
		   &num_extra_con_lut, 0664);
MODULE_PARM_DESC(extra_con_lut,
		 "\n lookup table for contrast match source luminance.\n");

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT

static uint clip(uint y, uint ymin, uint ymax)
{
	return (y > ymax) ? ymax : ((y < ymin) ? ymin : y);
}
#endif
static const int coef[] = {
	  0,   256,     0,     0, /* phase 0  */
	 -2,   256,     2,     0, /* phase 1  */
	 -4,   256,     4,     0, /* phase 2  */
	 -5,   254,     7,     0, /* phase 3  */
	 -7,   254,    10,    -1, /* phase 4  */
	 -8,   252,    13,    -1, /* phase 5  */
	-10,   251,    16,    -1, /* phase 6  */
	-11,   249,    19,    -1, /* phase 7  */
	-12,   247,    23,    -2, /* phase 8  */
	-13,   244,    27,    -2, /* phase 9  */
	-14,   242,    31,    -3, /* phase 10 */
	-15,   239,    35,    -3, /* phase 11 */
	-16,   236,    40,    -4, /* phase 12 */
	-17,   233,    44,    -4, /* phase 13 */
	-17,   229,    49,    -5, /* phase 14 */
	-18,   226,    53,    -5, /* phase 15 */
	-18,   222,    58,    -6, /* phase 16 */
	-18,   218,    63,    -7, /* phase 17 */
	-19,   214,    68,    -7, /* phase 18 */
	-19,   210,    73,    -8, /* phase 19 */
	-19,   205,    79,    -9, /* phase 20 */
	-19,   201,    83,    -9, /* phase 21 */
	-19,   196,    89,   -10, /* phase 22 */
	-19,   191,    94,   -10, /* phase 23 */
	-19,   186,   100,   -11, /* phase 24 */
	-18,   181,   105,   -12, /* phase 25 */
	-18,   176,   111,   -13, /* phase 26 */
	-18,   171,   116,   -13, /* phase 27 */
	-18,   166,   122,   -14, /* phase 28 */
	-17,   160,   127,   -14, /* phase 28 */
	-17,   155,   133,   -15, /* phase 30 */
	-16,   149,   138,   -15, /* phase 31 */
	-16,   144,   144,   -16  /* phase 32 */
};

int cubic_interpolation(int y0, int y1, int y2, int y3, int mu)
{
	int c0, c1, c2, c3;
	int d0, d1, d2, d3;

	if (mu <= 32) {
		c0 = coef[(mu << 2) + 0];
		c1 = coef[(mu << 2) + 1];
		c2 = coef[(mu << 2) + 2];
		c3 = coef[(mu << 2) + 3];
		d0 = y0; d1 = y1; d2 = y2; d3 = y3;
	} else {
		c0 = coef[((64 - mu) << 2) + 0];
		c1 = coef[((64 - mu) << 2) + 1];
		c2 = coef[((64 - mu) << 2) + 2];
		c3 = coef[((64 - mu) << 2) + 3];
		d0 = y3; d1 = y2; d2 = y1; d3 = y0;
	}
	return (d0 * c0 + d1 * c1 + d2 * c2 + d3 * c3 + 128) >> 8;
}

static int knee_lut_on;
static int cur_knee_factor = -1;

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static void load_knee_lut(int on)
{
	int i, j, k, mu;
	int value, addr_tmp, data_temp;
	int final_knee_setting[MAX_KNEE_SETTING] = {0};
	int *plist;

	plist = final_knee_setting;

	if (cur_knee_factor != knee_factor && !lut_289_en && (on)) {
		pr_csc(1, "Knee_factor changed from %d to %d\n",
		       cur_knee_factor, knee_factor);
		for (i = 0; i < MAX_KNEE_SETTING; i++) {
			plist[i] =
				plist[i] + (((plist[i]
				- plist[i]) * knee_factor) >> 8);
			if (plist[i] > 0x3ff)
				plist[i] = 0x3ff;
			else if (plist[i] < 0)
				plist[i] = 0;
		}
		VSYNC_WRITE_VPP_REG(XVYCC_LUT_CTL, 0x0);
		for (j = 0; j < 3; j++) {
			addr_tmp = XVYCC_LUT_R_ADDR_PORT + 2 * j;
			data_temp = XVYCC_LUT_R_DATA_PORT + 2 * j;
			for (i = 0; i < 16; i++) {
				VSYNC_WRITE_VPP_REG(addr_tmp, i);
				value = plist[0]
					+ (((plist[1]
					- plist[0]) * i) >> 4);
				value = clip(value, 0, 0x3ff);
				VSYNC_WRITE_VPP_REG(data_temp, value);
				if (j == 0)
					pr_csc(1,
					       "xvycc_lut[%1d][%3d] = 0x%03x\n",
					       j, i, value);
			}
			for (i = 16; i < 272; i++) {
				mu = ((i - 16) & 0x7) << 3;
				k = 1 + ((i - 16) >> 3);
				VSYNC_WRITE_VPP_REG(addr_tmp, i);
				if (knee_interpolation_mode == 0)
					value = plist[k]
						+ (((plist[k + 1]
						- plist[k])
						* ((i - 16) & 0x7)) >> 3);
				else
					value =
					cubic_interpolation(plist[k - 1],
							    plist[k],
							    plist[k + 1],
							    plist[k + 2],
							    mu);
				value = clip(value, 0, 0x3ff);
				VSYNC_WRITE_VPP_REG(data_temp, value);
				if (j == 0)
					pr_csc(1,
					       "xvycc_lut[%1d][%3d] = 0x%03x\n",
					       j, i, value);
			}
			for (i = 272; i < 289; i++) {
				k = MAX_KNEE_SETTING - 2;
				VSYNC_WRITE_VPP_REG(addr_tmp, i);
				value = plist[k]
					+ (((plist[k + 1]
					- plist[k])
					* (i - 272)) >> 4);
				value = clip(value, 0, 0x3ff);
				VSYNC_WRITE_VPP_REG(data_temp, value);
				if (j == 0)
					pr_csc(1,
					       "xvycc_lut[%1d][%3d] = 0x%03x\n",
					       j, i, value);
			}
		}
		cur_knee_factor = knee_factor;
	}

	if (cur_knee_factor != knee_factor && lut_289_en && on) {
		VSYNC_WRITE_VPP_REG(XVYCC_LUT_CTL, 0x0);
		VSYNC_WRITE_VPP_REG(XVYCC_LUT_R_ADDR_PORT, 0);
		for (i = 0; i < LUT_289_SIZE; i++)
			VSYNC_WRITE_VPP_REG(XVYCC_LUT_R_DATA_PORT,
					    lut_289_mapping[i]);
		VSYNC_WRITE_VPP_REG(XVYCC_LUT_R_ADDR_PORT + 2, 0);
		for (i = 0; i < LUT_289_SIZE; i++)
			VSYNC_WRITE_VPP_REG(XVYCC_LUT_R_DATA_PORT + 2,
					    lut_289_mapping[i]);
		VSYNC_WRITE_VPP_REG(XVYCC_LUT_R_ADDR_PORT + 4, 0);
		for (i = 0; i < LUT_289_SIZE; i++)
			VSYNC_WRITE_VPP_REG(XVYCC_LUT_R_DATA_PORT + 4,
					    lut_289_mapping[i]);
		cur_knee_factor = knee_factor;
	}

	if (on) {
		VSYNC_WRITE_VPP_REG(XVYCC_LUT_CTL, 0x7f);
		knee_lut_on = 1;
	} else {
		VSYNC_WRITE_VPP_REG(XVYCC_LUT_CTL, 0x0f);
		knee_lut_on = 0;
	}
}
#endif

/***************************** gxl hdr ****************************/
/* 16 for [-2048, 0), 32 for [0, 1024), 17 for [1024, 2048) */
#define EOTF_INV_LUT_NEG2048_SIZE 16
#define EOTF_INV_LUT_SIZE 32
#define EOTF_INV_LUT_1024_SIZE 17

#define INVLUT_SDR2HDR 0x1
#define INVLUT_HLG 0x2
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static unsigned int int_lut_sel[] = {0};
#endif

static unsigned int num_invlut_neg_mapping = EOTF_INV_LUT_NEG2048_SIZE;
static int invlut_y_neg[EOTF_INV_LUT_NEG2048_SIZE] = {
	-2048, -1920, -1792, -1664,
	-1536, -1408, -1280, -1152,
	-1024, -896, -768, -640,
	-512, -384, -256, -128
};

static unsigned int num_invlut_mapping = EOTF_INV_LUT_SIZE;
static unsigned int invlut_y[EOTF_INV_LUT_SIZE] = {
	0, 32, 64, 96, 128, 160, 192, 224,
	256, 288, 320, 352, 384, 416, 448, 480,
	512, 544, 576, 608, 640, 672, 704, 736,
	768, 800, 832, 864, 896, 928, 960, 992
};

static unsigned int num_invlut_1024_mapping = EOTF_INV_LUT_1024_SIZE;
static unsigned int invlut_y_1024[EOTF_INV_LUT_1024_SIZE] = {
	1024, 1088, 1152, 1216,
	1280, 1344, 1408, 1472,
	1536, 1600, 1664, 1728,
	1792, 1856, 1920, 1984,
	2047
};

static unsigned int num_invlut_hlg_mapping = EOTF_INV_LUT_SIZE;
static unsigned int invlut_hlg_y[EOTF_INV_LUT_SIZE] = {
	    0, 14, 28, 48, 69, 91, 114, 138,
	  163, 188, 215, 241, 269, 297, 325, 354,
	  383, 415, 450, 490, 535, 579, 622, 663,
	  705, 745, 786, 826, 866, 905, 945, 985
};

#define EOTF_LUT_SIZE 33
static unsigned int num_osd_eotf_r_mapping = EOTF_LUT_SIZE;
static unsigned int osd_eotf_r_mapping[EOTF_LUT_SIZE] = {
	0x0000,	0x0200,	0x0400, 0x0600,
	0x0800, 0x0a00, 0x0c00, 0x0e00,
	0x1000, 0x1200, 0x1400, 0x1600,
	0x1800, 0x1a00, 0x1c00, 0x1e00,
	0x2000, 0x2200, 0x2400, 0x2600,
	0x2800, 0x2a00, 0x2c00, 0x2e00,
	0x3000, 0x3200, 0x3400, 0x3600,
	0x3800, 0x3a00, 0x3c00, 0x3e00,
	0x4000
};

static unsigned int num_osd_eotf_g_mapping = EOTF_LUT_SIZE;
static unsigned int osd_eotf_g_mapping[EOTF_LUT_SIZE] = {
	0x0000,	0x0200,	0x0400, 0x0600,
	0x0800, 0x0a00, 0x0c00, 0x0e00,
	0x1000, 0x1200, 0x1400, 0x1600,
	0x1800, 0x1a00, 0x1c00, 0x1e00,
	0x2000, 0x2200, 0x2400, 0x2600,
	0x2800, 0x2a00, 0x2c00, 0x2e00,
	0x3000, 0x3200, 0x3400, 0x3600,
	0x3800, 0x3a00, 0x3c00, 0x3e00,
	0x4000
};

static unsigned int num_osd_eotf_b_mapping = EOTF_LUT_SIZE;
static unsigned int osd_eotf_b_mapping[EOTF_LUT_SIZE] = {
	0x0000,	0x0200,	0x0400, 0x0600,
	0x0800, 0x0a00, 0x0c00, 0x0e00,
	0x1000, 0x1200, 0x1400, 0x1600,
	0x1800, 0x1a00, 0x1c00, 0x1e00,
	0x2000, 0x2200, 0x2400, 0x2600,
	0x2800, 0x2a00, 0x2c00, 0x2e00,
	0x3000, 0x3200, 0x3400, 0x3600,
	0x3800, 0x3a00, 0x3c00, 0x3e00,
	0x4000
};

static unsigned int num_video_eotf_r_mapping = EOTF_LUT_SIZE;
static unsigned int video_eotf_r_mapping[EOTF_LUT_SIZE] = {
	0x0000,	0x0200,	0x0400, 0x0600,
	0x0800, 0x0a00, 0x0c00, 0x0e00,
	0x1000, 0x1200, 0x1400, 0x1600,
	0x1800, 0x1a00, 0x1c00, 0x1e00,
	0x2000, 0x2200, 0x2400, 0x2600,
	0x2800, 0x2a00, 0x2c00, 0x2e00,
	0x3000, 0x3200, 0x3400, 0x3600,
	0x3800, 0x3a00, 0x3c00, 0x3e00,
	0x4000
};

static unsigned int num_video_eotf_g_mapping = EOTF_LUT_SIZE;
static unsigned int video_eotf_g_mapping[EOTF_LUT_SIZE] = {
	0x0000,	0x0200,	0x0400, 0x0600,
	0x0800, 0x0a00, 0x0c00, 0x0e00,
	0x1000, 0x1200, 0x1400, 0x1600,
	0x1800, 0x1a00, 0x1c00, 0x1e00,
	0x2000, 0x2200, 0x2400, 0x2600,
	0x2800, 0x2a00, 0x2c00, 0x2e00,
	0x3000, 0x3200, 0x3400, 0x3600,
	0x3800, 0x3a00, 0x3c00, 0x3e00,
	0x4000
};

static unsigned int num_video_eotf_b_mapping = EOTF_LUT_SIZE;
static unsigned int video_eotf_b_mapping[EOTF_LUT_SIZE] = {
	0x0000,	0x0200,	0x0400, 0x0600,
	0x0800, 0x0a00, 0x0c00, 0x0e00,
	0x1000, 0x1200, 0x1400, 0x1600,
	0x1800, 0x1a00, 0x1c00, 0x1e00,
	0x2000, 0x2200, 0x2400, 0x2600,
	0x2800, 0x2a00, 0x2c00, 0x2e00,
	0x3000, 0x3200, 0x3400, 0x3600,
	0x3800, 0x3a00, 0x3c00, 0x3e00,
	0x4000
};

#define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2))
#define EOTF_COEFF_SIZE 10
#define EOTF_COEFF_RIGHTSHIFT 1
static unsigned int num_osd_eotf_coeff = EOTF_COEFF_SIZE;
static int osd_eotf_coeff[EOTF_COEFF_SIZE] = {
	EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0),
	EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0),
	EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0),
	EOTF_COEFF_RIGHTSHIFT /* right shift */
};

static unsigned int num_video_eotf_coeff = EOTF_COEFF_SIZE;
static int video_eotf_coeff[EOTF_COEFF_SIZE] = {
	EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0),
	EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0),
	EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0),
	EOTF_COEFF_RIGHTSHIFT /* right shift */
};

static unsigned int reload_mtx;
static unsigned int reload_lut;

/******************** osd oetf **************/

static unsigned int num_osd_oetf_r_mapping = OSD_OETF_LUT_SIZE;
static unsigned int osd_oetf_r_mapping[OSD_OETF_LUT_SIZE] = {
		0, 4, 8, 12,
		16, 20, 24, 28,
		31, 62, 93, 124,
		155, 186, 217, 248,
		279, 310, 341, 372,
		403, 434, 465, 496,
		527, 558, 589, 620,
		651, 682, 713, 744,
		775, 806, 837, 868,
		899, 930, 961, 992,
		1023
};

static unsigned int num_osd_oetf_g_mapping = OSD_OETF_LUT_SIZE;
static unsigned int osd_oetf_g_mapping[OSD_OETF_LUT_SIZE] = {
		0, 4, 8, 12,
		16, 20, 24, 28,
		31, 62, 93, 124,
		155, 186, 217, 248,
		279, 310, 341, 372,
		403, 434, 465, 496,
		527, 558, 589, 620,
		651, 682, 713, 744,
		775, 806, 837, 868,
		899, 930, 961, 992,
		1023
};

static unsigned int num_osd_oetf_b_mapping = OSD_OETF_LUT_SIZE;
static unsigned int osd_oetf_b_mapping[OSD_OETF_LUT_SIZE] = {
		0, 4, 8, 12,
		16, 20, 24, 28,
		31, 62, 93, 124,
		155, 186, 217, 248,
		279, 310, 341, 372,
		403, 434, 465, 496,
		527, 558, 589, 620,
		651, 682, 713, 744,
		775, 806, 837, 868,
		899, 930, 961, 992,
		1023
};

/************ video oetf ***************/

#define VIDEO_OETF_LUT_SIZE 289
static unsigned int num_video_oetf_r_mapping = VIDEO_OETF_LUT_SIZE;
static unsigned int video_oetf_r_mapping[VIDEO_OETF_LUT_SIZE] = {
	   0,    0,    0,    0,    0,    0,    0,    0,
	   0,    0,    0,    0,    0,    0,    0,    0,
	   4,    8,   12,   16,   20,   24,   28,   32,
	  36,   40,   44,   48,   52,   56,   60,   64,
	  68,   72,   76,   80,   84,   88,   92,   96,
	 100,  104,  108,  112,  116,  120,  124,  128,
	 132,  136,  140,  144,  148,  152,  156,  160,
	 164,  168,  172,  176,  180,  184,  188,  192,
	 196,  200,  204,  208,  212,  216,  220,  224,
	 228,  232,  236,  240,  244,  248,  252,  256,
	 260,  264,  268,  272,  276,  280,  284,  288,
	 292,  296,  300,  304,  308,  312,  316,  320,
	 324,  328,  332,  336,  340,  344,  348,  352,
	 356,  360,  364,  368,  372,  376,  380,  384,
	 388,  392,  396,  400,  404,  408,  412,  416,
	 420,  424,  428,  432,  436,  440,  444,  448,
	 452,  456,  460,  464,  468,  472,  476,  480,
	 484,  488,  492,  496,  500,  504,  508,  512,
	 516,  520,  524,  528,  532,  536,  540,  544,
	 548,  552,  556,  560,  564,  568,  572,  576,
	 580,  584,  588,  592,  596,  600,  604,  608,
	 612,  616,  620,  624,  628,  632,  636,  640,
	 644,  648,  652,  656,  660,  664,  668,  672,
	 676,  680,  684,  688,  692,  696,  700,  704,
	 708,  712,  716,  720,  724,  728,  732,  736,
	 740,  744,  748,  752,  756,  760,  764,  768,
	 772,  776,  780,  784,  788,  792,  796,  800,
	 804,  808,  812,  816,  820,  824,  828,  832,
	 836,  840,  844,  848,  852,  856,  860,  864,
	 868,  872,  876,  880,  884,  888,  892,  896,
	 900,  904,  908,  912,  916,  920,  924,  928,
	 932,  936,  940,  944,  948,  952,  956,  960,
	 964,  968,  972,  976,  980,  984,  988,  992,
	 996, 1000, 1004, 1008, 1012, 1016, 1020, 1023,
	1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
	1023
};

static unsigned int num_video_oetf_g_mapping = VIDEO_OETF_LUT_SIZE;
static unsigned int video_oetf_g_mapping[VIDEO_OETF_LUT_SIZE] = {
	   0,    0,    0,    0,    0,    0,    0,    0,
	   0,    0,    0,    0,    0,    0,    0,    0,
	   4,    8,   12,   16,   20,   24,   28,   32,
	  36,   40,   44,   48,   52,   56,   60,   64,
	  68,   72,   76,   80,   84,   88,   92,   96,
	 100,  104,  108,  112,  116,  120,  124,  128,
	 132,  136,  140,  144,  148,  152,  156,  160,
	 164,  168,  172,  176,  180,  184,  188,  192,
	 196,  200,  204,  208,  212,  216,  220,  224,
	 228,  232,  236,  240,  244,  248,  252,  256,
	 260,  264,  268,  272,  276,  280,  284,  288,
	 292,  296,  300,  304,  308,  312,  316,  320,
	 324,  328,  332,  336,  340,  344,  348,  352,
	 356,  360,  364,  368,  372,  376,  380,  384,
	 388,  392,  396,  400,  404,  408,  412,  416,
	 420,  424,  428,  432,  436,  440,  444,  448,
	 452,  456,  460,  464,  468,  472,  476,  480,
	 484,  488,  492,  496,  500,  504,  508,  512,
	 516,  520,  524,  528,  532,  536,  540,  544,
	 548,  552,  556,  560,  564,  568,  572,  576,
	 580,  584,  588,  592,  596,  600,  604,  608,
	 612,  616,  620,  624,  628,  632,  636,  640,
	 644,  648,  652,  656,  660,  664,  668,  672,
	 676,  680,  684,  688,  692,  696,  700,  704,
	 708,  712,  716,  720,  724,  728,  732,  736,
	 740,  744,  748,  752,  756,  760,  764,  768,
	 772,  776,  780,  784,  788,  792,  796,  800,
	 804,  808,  812,  816,  820,  824,  828,  832,
	 836,  840,  844,  848,  852,  856,  860,  864,
	 868,  872,  876,  880,  884,  888,  892,  896,
	 900,  904,  908,  912,  916,  920,  924,  928,
	 932,  936,  940,  944,  948,  952,  956,  960,
	 964,  968,  972,  976,  980,  984,  988,  992,
	 996, 1000, 1004, 1008, 1012, 1016, 1020, 1023,
	1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
	1023
};

static unsigned int num_video_oetf_b_mapping = VIDEO_OETF_LUT_SIZE;
static unsigned int video_oetf_b_mapping[VIDEO_OETF_LUT_SIZE] = {
	   0,    0,    0,    0,    0,    0,    0,    0,
	   0,    0,    0,    0,    0,    0,    0,    0,
	   4,    8,   12,   16,   20,   24,   28,   32,
	  36,   40,   44,   48,   52,   56,   60,   64,
	  68,   72,   76,   80,   84,   88,   92,   96,
	 100,  104,  108,  112,  116,  120,  124,  128,
	 132,  136,  140,  144,  148,  152,  156,  160,
	 164,  168,  172,  176,  180,  184,  188,  192,
	 196,  200,  204,  208,  212,  216,  220,  224,
	 228,  232,  236,  240,  244,  248,  252,  256,
	 260,  264,  268,  272,  276,  280,  284,  288,
	 292,  296,  300,  304,  308,  312,  316,  320,
	 324,  328,  332,  336,  340,  344,  348,  352,
	 356,  360,  364,  368,  372,  376,  380,  384,
	 388,  392,  396,  400,  404,  408,  412,  416,
	 420,  424,  428,  432,  436,  440,  444,  448,
	 452,  456,  460,  464,  468,  472,  476,  480,
	 484,  488,  492,  496,  500,  504,  508,  512,
	 516,  520,  524,  528,  532,  536,  540,  544,
	 548,  552,  556,  560,  564,  568,  572,  576,
	 580,  584,  588,  592,  596,  600,  604,  608,
	 612,  616,  620,  624,  628,  632,  636,  640,
	 644,  648,  652,  656,  660,  664,  668,  672,
	 676,  680,  684,  688,  692,  696,  700,  704,
	 708,  712,  716,  720,  724,  728,  732,  736,
	 740,  744,  748,  752,  756,  760,  764,  768,
	 772,  776,  780,  784,  788,  792,  796,  800,
	 804,  808,  812,  816,  820,  824,  828,  832,
	 836,  840,  844,  848,  852,  856,  860,  864,
	 868,  872,  876,  880,  884,  888,  892,  896,
	 900,  904,  908,  912,  916,  920,  924,  928,
	 932,  936,  940,  944,  948,  952,  956,  960,
	 964,  968,  972,  976,  980,  984,  988,  992,
	 996, 1000, 1004, 1008, 1012, 1016, 1020, 1023,
	1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
	1023
};

#define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2))
#define MATRIX_5x3_COEF_SIZE 24
/******* osd1 matrix0 *******/
/* default rgb to yuv_limit */
static unsigned int num_osd_matrix_coeff = MATRIX_5x3_COEF_SIZE;
static int osd_matrix_coeff[MATRIX_5x3_COEF_SIZE] = {
	0, 0, 0, /* pre offset */
	COEFF_NORM(0.2126),	COEFF_NORM(0.7152),	COEFF_NORM(0.0722),
	COEFF_NORM(-0.11457),	COEFF_NORM(-0.38543),	COEFF_NORM(0.5),
	COEFF_NORM(0.5),	COEFF_NORM(-0.45415),	COEFF_NORM(-0.045847),
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	0, 512, 512, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

static unsigned int num_vd1_matrix_coeff = MATRIX_5x3_COEF_SIZE;
static int vd1_matrix_coeff[MATRIX_5x3_COEF_SIZE] = {
	0, 0, 0, /* pre offset */
	COEFF_NORM(1.0),	COEFF_NORM(0.0),	COEFF_NORM(0.0),
	COEFF_NORM(0.0),	COEFF_NORM(1.0),	COEFF_NORM(0.0),
	COEFF_NORM(0.0),	COEFF_NORM(0.0),	COEFF_NORM(1.0),
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	0, 0, 0, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

static unsigned int num_vd2_matrix_coeff = MATRIX_5x3_COEF_SIZE;
static int vd2_matrix_coeff[MATRIX_5x3_COEF_SIZE] = {
	0, 0, 0, /* pre offset */
	COEFF_NORM(1.0),	COEFF_NORM(0.0),	COEFF_NORM(0.0),
	COEFF_NORM(0.0),	COEFF_NORM(1.0),	COEFF_NORM(0.0),
	COEFF_NORM(0.0),	COEFF_NORM(0.0),	COEFF_NORM(1.0),
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	0, 0, 0, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

static unsigned int num_post_matrix_coeff = MATRIX_5x3_COEF_SIZE;
static int post_matrix_coeff[MATRIX_5x3_COEF_SIZE] = {
	0, 0, 0, /* pre offset */
	COEFF_NORM(1.0),	COEFF_NORM(0.0),	COEFF_NORM(0.0),
	COEFF_NORM(0.0),	COEFF_NORM(1.0),	COEFF_NORM(0.0),
	COEFF_NORM(0.0),	COEFF_NORM(0.0),	COEFF_NORM(1.0),
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	0, 0, 0, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

static unsigned int num_xvycc_matrix_coeff = MATRIX_5x3_COEF_SIZE;
static int xvycc_matrix_coeff[MATRIX_5x3_COEF_SIZE] = {
	0, 0, 0, /* pre offset */
	COEFF_NORM(1.0),	COEFF_NORM(0.0),	COEFF_NORM(0.0),
	COEFF_NORM(0.0),	COEFF_NORM(1.0),	COEFF_NORM(0.0),
	COEFF_NORM(0.0),	COEFF_NORM(0.0),	COEFF_NORM(1.0),
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	0, 0, 0, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

/****************** osd eotf ********************/
module_param_array(osd_eotf_coeff, int,
		   &num_osd_eotf_coeff, 0664);
MODULE_PARM_DESC(osd_eotf_coeff, "\n matrix for osd eotf\n");

module_param_array(osd_eotf_r_mapping, uint,
		   &num_osd_eotf_r_mapping, 0664);
MODULE_PARM_DESC(osd_eotf_r_mapping, "\n lut for osd r eotf\n");

module_param_array(osd_eotf_g_mapping, uint,
		   &num_osd_eotf_g_mapping, 0664);
MODULE_PARM_DESC(osd_eotf_g_mapping, "\n lut for osd g eotf\n");

module_param_array(osd_eotf_b_mapping, uint,
		   &num_osd_eotf_b_mapping, 0664);
MODULE_PARM_DESC(osd_eotf_b_mapping, "\n lut for osd b eotf\n");

module_param_array(osd_matrix_coeff, int,
		   &num_osd_matrix_coeff, 0664);
MODULE_PARM_DESC(osd_matrix_coeff, "\n coef for osd matrix\n");

/****************** video eotf ********************/
module_param_array(invlut_y_neg, int,
		   &num_invlut_neg_mapping, 0664);
MODULE_PARM_DESC(invlut_y_neg, "\n lut for inv y -2048..0 eotf\n");

module_param_array(invlut_y, uint,
		   &num_invlut_mapping, 0664);
MODULE_PARM_DESC(invlut_y, "\n lut for inv y 0..1024 eotf\n");

module_param_array(invlut_y_1024, uint,
		   &num_invlut_1024_mapping, 0664);
MODULE_PARM_DESC(invlut_y_1024, "\n lut for inv y 1024..2048 eotf\n");

module_param_array(invlut_hlg_y, int,
		   &num_invlut_hlg_mapping, 0664);
MODULE_PARM_DESC(invlut_hlg_y, "\n lut for hlg 0..1024 eotf\n");

module_param_array(video_eotf_coeff, int,
		   &num_video_eotf_coeff, 0664);
MODULE_PARM_DESC(video_eotf_coeff, "\n matrix for video eotf\n");

module_param_array(video_eotf_r_mapping, uint,
		   &num_video_eotf_r_mapping, 0664);
MODULE_PARM_DESC(video_eotf_r_mapping, "\n lut for video r eotf\n");

module_param_array(video_eotf_g_mapping, uint,
		   &num_video_eotf_g_mapping, 0664);
MODULE_PARM_DESC(video_eotf_g_mapping, "\n lut for video g eotf\n");

module_param_array(video_eotf_b_mapping, uint,
		   &num_video_eotf_b_mapping, 0664);
MODULE_PARM_DESC(video_eotf_b_mapping, "\n lut for video b eotf\n");

/****************** osd oetf ********************/
module_param_array(osd_oetf_r_mapping, uint,
		   &num_osd_oetf_r_mapping, 0664);
MODULE_PARM_DESC(osd_oetf_r_mapping, "\n lut for osd r oetf\n");

module_param_array(osd_oetf_g_mapping, uint,
		   &num_osd_oetf_g_mapping, 0664);
MODULE_PARM_DESC(osd_oetf_g_mapping, "\n lut for osd g oetf\n");

module_param_array(osd_oetf_b_mapping, uint,
		   &num_osd_oetf_b_mapping, 0664);
MODULE_PARM_DESC(osd_oetf_b_mapping, "\n lut for osd b oetf\n");

/****************** video oetf ********************/
module_param_array(video_oetf_r_mapping, uint,
		   &num_video_oetf_r_mapping, 0664);
MODULE_PARM_DESC(video_oetf_r_mapping, "\n lut for video r oetf\n");

module_param_array(video_oetf_g_mapping, uint,
		   &num_video_oetf_g_mapping, 0664);
MODULE_PARM_DESC(video_oetf_g_mapping, "\n lut for video g oetf\n");

module_param_array(video_oetf_b_mapping, uint,
		   &num_video_oetf_b_mapping, 0664);
MODULE_PARM_DESC(video_oetf_b_mapping, "\n lut for video b oetf\n");

/****************** vpp matrix ********************/

module_param_array(vd1_matrix_coeff, int,
		   &num_vd1_matrix_coeff, 0664);
MODULE_PARM_DESC(vd1_matrix_coeff, "\n vd1 matrix\n");

module_param_array(vd2_matrix_coeff, int,
		   &num_vd2_matrix_coeff, 0664);
MODULE_PARM_DESC(vd2_matrix_coeff, "\n vd2 matrix\n");

module_param_array(post_matrix_coeff, int,
		   &num_post_matrix_coeff, 0664);
MODULE_PARM_DESC(post_matrix_coeff, "\n post matrix\n");

module_param_array(xvycc_matrix_coeff, int,
		   &num_xvycc_matrix_coeff, 0664);
MODULE_PARM_DESC(xvycc_matrix_coeff, "\n xvycc matrix\n");

static unsigned int mtx_en_mux;
module_param(mtx_en_mux, uint, 0664);
MODULE_PARM_DESC(mtx_en_mux, "\n mtx enable mux\n");

/****************** matrix/lut reload********************/

module_param(reload_mtx, uint, 0664);
MODULE_PARM_DESC(reload_mtx, "\n reload matrix coeff\n");

module_param(reload_lut, uint, 0664);
MODULE_PARM_DESC(reload_lut, "\n reload lut settings\n");

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static int RGB709_to_YUV709_coeff[MATRIX_5x3_COEF_SIZE] = {
	0, 0, 0, /* pre offset */
	COEFF_NORM(0.2126),	COEFF_NORM(0.7152),	COEFF_NORM(0.0722),
	COEFF_NORM(-0.114572),	COEFF_NORM(-0.385428),	COEFF_NORM(0.5),
	COEFF_NORM(0.5),	COEFF_NORM(-0.454153),	COEFF_NORM(-0.045847),
	0, 0, 0, /* 10'/11'/12' */
	0, 0, 0, /* 20'/21'/22' */
	0, 512, 512, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};
#endif


static int RGB709_to_YUV709l_coeff[MATRIX_5x3_COEF_SIZE] = {
	0, 0, 0, /* pre offset */
	COEFF_NORM(0.181873),	COEFF_NORM(0.611831),	COEFF_NORM(0.061765),
	COEFF_NORM(-0.100251),	COEFF_NORM(-0.337249),	COEFF_NORM(0.437500),
	COEFF_NORM(0.437500),	COEFF_NORM(-0.397384),	COEFF_NORM(-0.040116),
	0, 0, 0, /* 10'/11'/12' */
	0, 0, 0, /* 20'/21'/22' */
	64, 512, 512, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static int RGB2020_to_YUV2020l_coeff[MATRIX_5x3_COEF_SIZE] = {
	0, 0, 0, /* pre offset */
	COEFF_NORM(0.224732),	COEFF_NORM(0.580008),	COEFF_NORM(0.050729),
	COEFF_NORM(-0.122176),	COEFF_NORM(-0.315324),	COEFF_NORM(0.437500),
	COEFF_NORM(0.437500),	COEFF_NORM(-0.402312),	COEFF_NORM(-0.035188),
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	64, 512, 512, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

static int YUV709f_to_YUV709l_coeff[MATRIX_5x3_COEF_SIZE] = {
	0, -512, -512, /* pre offset */
	COEFF_NORM(0.859),	COEFF_NORM(0),	COEFF_NORM(0),
	COEFF_NORM(0),	COEFF_NORM(0.878),	COEFF_NORM(0),
	COEFF_NORM(0),	COEFF_NORM(0),	COEFF_NORM(0.878),
	0, 0, 0, /* 10'/11'/12' */
	0, 0, 0, /* 20'/21'/22' */
	64, 512, 512, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

static int YUV709l_to_YUV709f_coeff[MATRIX_5x3_COEF_SIZE] = {
	64, -512, -512, /* pre offset */
	COEFF_NORM(1.16895),	COEFF_NORM(0),	COEFF_NORM(0),
	COEFF_NORM(0),	COEFF_NORM(1.14286),	COEFF_NORM(0),
	COEFF_NORM(0),	COEFF_NORM(0),	COEFF_NORM(1.14286),
	0, 0, 0, /* 10'/11'/12' */
	0, 0, 0, /* 20'/21'/22' */
	0, 512, 512, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};
#endif

static int YUV709l_to_RGB709_coeff[MATRIX_5x3_COEF_SIZE] = {
	-64, -512, -512, /* pre offset */
	COEFF_NORM(1.16895),	COEFF_NORM(0.00000),	COEFF_NORM(1.79977),
	COEFF_NORM(1.16895),	COEFF_NORM(-0.21408),	COEFF_NORM(-0.53500),
	COEFF_NORM(1.16895),	COEFF_NORM(2.12069),	COEFF_NORM(0.00000),
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	0, 0, 0, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static int YUV709l_to_YUV2020_coeff[MATRIX_5x3_COEF_SIZE] = {
	-64, -512, -512, /* pre offset */
	0x400,	0x1fe4,	0x2b,
	0,	0x39f,	0x1fe5,
	0x0,	0xc,	0x321,
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	64, 512, 512, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

static int YUV709f_to_RGB709_coeff[MATRIX_5x3_COEF_SIZE] = {
	0, -512, -512, /* pre offset */
	COEFF_NORM(1.0),	COEFF_NORM(0.00000),	COEFF_NORM(1.575),
	COEFF_NORM(1.0),	COEFF_NORM(-0.187),	COEFF_NORM(-0.468),
	COEFF_NORM(1.0),	COEFF_NORM(1.856),	COEFF_NORM(0.00000),
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	0, 0, 0, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

static int YUV601l_to_YUV709l_coeff[MATRIX_5x3_COEF_SIZE] = {
	-64, -512, -512, /* pre offset */
	COEFF_NORM(1.0),	COEFF_NORM(-0.115),	COEFF_NORM(-0.207),
	COEFF_NORM(0),	COEFF_NORM(1.018),	COEFF_NORM(0.114),
	COEFF_NORM(0),	COEFF_NORM(0.075),	COEFF_NORM(1.025),
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	64, 512, 512, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

static int YUV601f_to_YUV709f_coeff[MATRIX_5x3_COEF_SIZE] = {
	0, -512, -512, /* pre offset */
	COEFF_NORM(1.00000),	COEFF_NORM(-0.118),	COEFF_NORM(-0.212),
	COEFF_NORM(0.00000),	COEFF_NORM(1.018),	COEFF_NORM(0.114),
	COEFF_NORM(0.00000),	COEFF_NORM(0.075),	COEFF_NORM(1.025),
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	0, 512, 512, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

static int YUV709l_to_YUV601l_coeff[MATRIX_5x3_COEF_SIZE] = {
	-64, -512, -512, /* pre offset */
	COEFF_NORM(1.0),	COEFF_NORM(0.1),	COEFF_NORM(0.192),
	COEFF_NORM(0),	COEFF_NORM(0.990),	COEFF_NORM(-0.110),
	COEFF_NORM(0),	COEFF_NORM(-0.072),	COEFF_NORM(0.984),
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	64, 512, 512, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

static int YUV601l_to_YUV709f_coeff[MATRIX_5x3_COEF_SIZE] = {
	-64, -512, -512, /* pre offset */
	COEFF_NORM(1.164),	COEFF_NORM(-0.134),	COEFF_NORM(-0.241),
	COEFF_NORM(0),	COEFF_NORM(1.160),	COEFF_NORM(-0.129),
	COEFF_NORM(0),	COEFF_NORM(-0.085),	COEFF_NORM(1.167),
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	0, 512, 512, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

static int YUV601f_to_YUV709l_coeff[MATRIX_5x3_COEF_SIZE] = {
	0, -512, -512, /* pre offset */
	COEFF_NORM(0.859),	COEFF_NORM(-0.101),	COEFF_NORM(-0.182),
	COEFF_NORM(0),	COEFF_NORM(0.894),	COEFF_NORM(-0.100),
	COEFF_NORM(0),	COEFF_NORM(-0.066),	COEFF_NORM(0.900),
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	64, 512, 512, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};
#endif

static int bypass_coeff[MATRIX_5x3_COEF_SIZE] = {
	0, 0, 0, /* pre offset */
	COEFF_NORM(1.0),	COEFF_NORM(0.0),	COEFF_NORM(0.0),
	COEFF_NORM(0.0),	COEFF_NORM(1.0),	COEFF_NORM(0.0),
	COEFF_NORM(0.0),	COEFF_NORM(0.0),	COEFF_NORM(1.0),
	0, 0, 0, /* 10'/11'/12' */
	0, 0, 0, /* 20'/21'/22' */
	0, 0, 0, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
/*  eotf matrix: bypass */
static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
	EOTF_COEFF_NORM(1.0),	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(0.0),
	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(1.0),	EOTF_COEFF_NORM(0.0),
	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(1.0),
	EOTF_COEFF_RIGHTSHIFT /* right shift */
};

static int eotf_RGB709_to_RGB2020_coeff[EOTF_COEFF_SIZE] = {
	EOTF_COEFF_NORM(0.627441),	EOTF_COEFF_NORM(0.329285),
	EOTF_COEFF_NORM(0.043274),
	EOTF_COEFF_NORM(0.069092),	EOTF_COEFF_NORM(0.919556),
	EOTF_COEFF_NORM(0.011322),
	EOTF_COEFF_NORM(0.016418),	EOTF_COEFF_NORM(0.088058),
	EOTF_COEFF_NORM(0.895554),
	EOTF_COEFF_RIGHTSHIFT /* right shift */
};

/* post matrix: YUV2020 limit to RGB2020 */
static int YUV2020l_to_RGB2020_coeff[MATRIX_5x3_COEF_SIZE] = {
	-64, -512, -512, /* pre offset */
	COEFF_NORM(1.16895),	COEFF_NORM(0.00000),	COEFF_NORM(1.68526),
	COEFF_NORM(1.16895),	COEFF_NORM(-0.18806),	COEFF_NORM(-0.65298),
	COEFF_NORM(1.16895),	COEFF_NORM(2.15017),	COEFF_NORM(0.00000),
	0, 0, 0, /* 30/31/32 */
	0, 0, 0, /* 40/41/42 */
	0, 0, 0, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

/* eotf lut: linear */
static unsigned int eotf_33_linear_mapping[EOTF_LUT_SIZE] = {
	0x0000,	0x0200,	0x0400, 0x0600,
	0x0800, 0x0a00, 0x0c00, 0x0e00,
	0x1000, 0x1200, 0x1400, 0x1600,
	0x1800, 0x1a00, 0x1c00, 0x1e00,
	0x2000, 0x2200, 0x2400, 0x2600,
	0x2800, 0x2a00, 0x2c00, 0x2e00,
	0x3000, 0x3200, 0x3400, 0x3600,
	0x3800, 0x3a00, 0x3c00, 0x3e00,
	0x4000
};

/* osd oetf lut: linear */
static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = {
		0, 4, 8, 12,
		16, 20, 24, 28,
		31, 62, 93, 124,
		155, 186, 217, 248,
		279, 310, 341, 372,
		403, 434, 465, 496,
		527, 558, 589, 620,
		651, 682, 713, 744,
		775, 806, 837, 868,
		899, 930, 961, 992,
		1023
};
#endif

/* following array generated from model, do not edit */
static int video_lut_switch;
module_param(video_lut_switch, int, 0664);
MODULE_PARM_DESC(video_lut_switch, "\n video_lut_switch\n");

/* gamma=2.200000 lumin=500 boost=0.075000 */
static unsigned int display_scale_factor =
	(unsigned int)((((1.000000) * 4096.0) + 1) / 2);

static unsigned int eotf_33_2084_mapping[EOTF_LUT_SIZE] = {
	    0,     3,     6,    11,    18,    27,    40,    58,
	   84,   119,   169,   237,   329,   455,   636,   881,
	 1209,  1648,  2234,  3014,  4050,  5425,  7251,  9673,
	12889, 13773, 14513, 15117, 15594, 15951, 16196, 16338,
	16383
};

static unsigned int oetf_289_gamma22_mapping[VIDEO_OETF_LUT_SIZE] = {
	   0,    0,    0,    0,    0,    0,    0,    0,
	   0,    0,    0,    0,    0,    0,    0,    0,
	   0,  125,  171,  206,  235,  259,  281,  302,
	 321,  339,  356,  371,  386,  401,  414,  427,
	 440,  453,  465,  476,  488,  498,  509,  519,
	 529,  539,  549,  558,  568,  577,  586,  595,
	 603,  612,  620,  628,  637,  645,  652,  660,
	 668,  675,  683,  690,  697,  705,  712,  719,
	 726,  733,  740,  748,  755,  763,  771,  778,
	 786,  793,  801,  808,  814,  821,  827,  832,
	 837,  842,  846,  849,  852,  854,  856,  858,
	 860,  862,  864,  866,  867,  869,  871,  873,
	 875,  877,  879,  880,  882,  884,  886,  887,
	 889,  891,  893,  894,  896,  898,  899,  901,
	 902,  904,  906,  907,  909,  910,  912,  914,
	 915,  917,  918,  920,  921,  923,  924,  925,
	 927,  928,  930,  931,  933,  934,  935,  937,
	 938,  939,  941,  942,  943,  945,  946,  947,
	 948,  950,  951,  952,  953,  954,  956,  957,
	 958,  959,  960,  961,  962,  963,  965,  966,
	 967,  968,  969,  970,  971,  972,  973,  974,
	 975,  976,  977,  978,  979,  980,  981,  981,
	 982,  983,  984,  985,  986,  987,  987,  988,
	 989,  990,  991,  991,  992,  993,  994,  995,
	 995,  996,  997,  997,  998,  999,  999, 1000,
	1001, 1001, 1002, 1003, 1003, 1004, 1004, 1005,
	1006, 1006, 1007, 1007, 1008, 1008, 1009, 1009,
	1010, 1010, 1011, 1011, 1012, 1012, 1012, 1013,
	1013, 1014, 1014, 1015, 1015, 1015, 1016, 1016,
	1016, 1017, 1017, 1017, 1018, 1018, 1018, 1019,
	1019, 1019, 1019, 1020, 1020, 1020, 1020, 1020,
	1021, 1021, 1021, 1021, 1021, 1022, 1022, 1022,
	1022, 1022, 1022, 1022, 1022, 1023, 1023, 1023,
	1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
	1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
	1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
	1023
};

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
/* osd eotf lut: 709 */
static unsigned int osd_eotf_33_709_mapping[EOTF_LUT_SIZE] = {
	    0,   512,  1024,  1536,  2048,  2560,  3072,  3584,
	 4096,  4608,  5120,  5632,  6144,  6656,  7168,  7680,
	 8192,  8704,  9216,  9728, 10240, 10752, 11264, 11776,
	12288, 12800, 13312, 13824, 14336, 14848, 15360, 15872,
	16383
};

/* osd oetf lut: 2084 */
static unsigned int osd_oetf_41_2084_mapping[OSD_OETF_LUT_SIZE] = {
	   0,   21,   43,   64,   79,   90,  101,  111,
	 120,  174,  208,  233,  277,  313,  344,  372,
	 398,  420,  440,  459,  476,  492,  507,  522,
	 536,  549,  561,  574,  585,  596,  606,  616,
	 624,  632,  642,  661,  684,  706,  727,  749,
	1023
};

/* osd eotf lut: 709 from  */
static unsigned int osd_eotf_33_709_mapping_100[EOTF_LUT_SIZE] = {
	    0,     8,    37,    90,   169,   276,   412,   579,
	  776,  1006,  1268,  1564,  1894,  2258,  2658,  3094,
	 3566,  4075,  4621,  5204,  5826,  6486,  7185,  7923,
	 8701,  9518, 10376, 11274, 12213, 13194, 14215, 15279,
	16384
};

/* osd oetf lut: 2084 from  */
static unsigned int osd_oetf_41_2084_mapping_100[OSD_OETF_LUT_SIZE] = {
	   0,  110,  141,  162,  178,  191,  203,  212,
	 221,  270,  302,  325,  344,  360,  374,  386,
	 396,  406,  415,  423,  431,  438,  445,  451,
	 457,  462,  468,  473,  478,  482,  487,  491,
	 495,  499,  503,  507,  510,  514,  517,  520,
	 523
};

static unsigned int osd_eotf_33_709_mapping_290[EOTF_LUT_SIZE] = {
	    0,     8,    37,    90,   169,   276,   412,   579,
	  776,  1006,  1268,  1564,  1894,  2258,  2658,  3094,
	 3566,  4075,  4621,  5204,  5826,  6486,  7185,  7923,
	 8701,  9518, 10376, 11274, 12213, 13194, 14215, 15279,
	16384
};

/* osd oetf lut: 2084 from  */
static unsigned int osd_oetf_41_2084_mapping_290[OSD_OETF_LUT_SIZE] = {
	   0,  141,  178,  203,  221,  236,  249,  260,
	 270,  325,  360,  386,  406,  423,  438,  451,
	 462,  473,  482,  491,  499,  507,  514,  520,
	 527,  532,  538,  543,  548,  553,  558,  562,
	 567,  571,  575,  579,  583,  586,  590,  593,
	 596
};

static unsigned int osd_eotf_33_709_mapping_330[EOTF_LUT_SIZE] = {
	    0,     8,    37,    90,   169,   276,   412,   579,
	  776,  1006,  1268,  1564,  1894,  2258,  2658,  3094,
	 3566,  4075,  4621,  5204,  5826,  6486,  7185,  7923,
	 8701,  9518, 10376, 11274, 12213, 13194, 14215, 15279,
	16384
};

/* osd oetf lut: 2084 from  */
static unsigned int osd_oetf_41_2084_mapping_330[OSD_OETF_LUT_SIZE] = {
	   0,  166,  207,  233,  254,  270,  284,  296,
	 307,  366,  402,  429,  451,  469,  484,  498,
	 509,  520,  530,  539,  547,  555,  562,  569,
	 576,  582,  588,  593,  598,  603,  608,  613,
	 617,  621,  625,  629,  633,  637,  640,  644,
	 647
};

/* osd eotf lut: sdr->hlg */
static unsigned int osd_eotf_33_sdr2hlg_mapping[EOTF_LUT_SIZE] = {
	    0,   512,  1024,  1536,  2048,  2560,  3072,  3584,
	 4096,  4608,  5120,  5632,  6144,  6656,  7168,  7680,
	 8192,  8704,  9216,  9728, 10240, 10752, 11264, 11776,
	12288, 12800, 13312, 13824, 14336, 14848, 15360, 15872,
	16383
};

/* osd oetf lut:  sdr->hlg */
static unsigned int osd_oetf_41_sdr2hlg_mapping[OSD_OETF_LUT_SIZE] = {
	   0,   23,   36,   43,   49,   54,   59,   64,
	  69,   96,  127,  172,  218,  267,  316,  365,
	 415,  468,  519,  567,  607,  643,  676,  706,
	 733,  758,  782,  805,  826,  847,  866,  885,
	 903,  920,  936,  951,  965,  980,  994, 1009,
	1023
};

/* sdr eotf lut: 709 */
static unsigned int eotf_33_sdr_709_mapping[EOTF_LUT_SIZE] = {
	    0,   512,  1024,  1536,  2048,  2560,  3072,  3584,
	 4096,  4608,  5120,  5632,  6144,  6656,  7168,  7680,
	 8192,  8704,  9216,  9728, 10240, 10752, 11264, 11776,
	12288, 12800, 13312, 13824, 14336, 14848, 15360, 15872,
	16383
};

/* sdr oetf lut: 2084 */
static unsigned int oetf_sdr_2084_mapping[VIDEO_OETF_LUT_SIZE] = {
	   0,    0,    0,    0,    0,    0,    0,    0,
	   0,    0,    0,    0,    0,    0,    0,    0,
	   0,   32,   55,   72,   85,   96,  106,  115,
	 124,  132,  140,  147,  154,  160,  166,  171,
	 176,  181,  186,  190,  194,  198,  204,  208,
	 211,  215,  218,  221,  224,  227,  230,  233,
	 239,  245,  252,  257,  263,  268,  274,  279,
	 283,  288,  292,  296,  302,  306,  310,  315,
	 319,  323,  326,  331,  334,  339,  342,  346,
	 350,  354,  357,  361,  365,  368,  372,  376,
	 379,  382,  386,  389,  392,  396,  399,  402,
	 405,  408,  411,  413,  416,  419,  422,  424,
	 427,  429,  432,  434,  437,  439,  442,  444,
	 446,  449,  451,  454,  456,  459,  461,  463,
	 465,  468,  470,  472,  474,  476,  478,  481,
	 483,  485,  487,  489,  491,  493,  495,  497,
	 499,  501,  503,  505,  507,  509,  511,  513,
	 515,  516,  518,  520,  522,  524,  526,  527,
	 529,  531,  533,  535,  536,  538,  540,  541,
	 543,  545,  546,  548,  550,  551,  553,  555,
	 556,  558,  559,  561,  562,  564,  566,  567,
	 569,  570,  572,  573,  575,  576,  578,  579,
	 580,  582,  584,  585,  586,  588,  589,  591,
	 592,  594,  595,  596,  598,  599,  600,  602,
	 603,  604,  606,  607,  608,  609,  611,  612,
	 613,  615,  616,  617,  618,  619,  620,  621,
	 622,  623,  624,  625,  626,  627,  628,  629,
	 630,  631,  632,  634,  635,  636,  637,  638,
	 640,  641,  642,  644,  646,  648,  651,  654,
	 657,  661,  664,  666,  670,  672,  676,  678,
	 681,  684,  687,  690,  692,  695,  698,  701,
	 704,  706,  709,  712,  715,  718,  720,  723,
	 726,  729,  731,  734,  737,  740,  743,  746,
	 748,  751,  754,  758,  763,  772,  797,  833,
	1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
	1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
	1023
};

/* end of array generated from model */

module_param(display_scale_factor, uint, 0664);
MODULE_PARM_DESC(display_scale_factor, "\n display scale factor\n");

/*HLG eotf and oetf curve*/
static unsigned int eotf_33_hlg_mapping[EOTF_LUT_SIZE] = {
	    0,     5,    21,    48,    85,   133,   192,   261,
	  341,   432,   533,   645,   768,   901,  1045,  1200,
	 1365,  1552,  1774,  2038,  2353,  2729,  3175,  3707,
	 4341,  5096,  5995,  7065,  8340,  9858, 11666, 13819,
	16383
};

static unsigned int oetf_289_2084_mapping[VIDEO_OETF_LUT_SIZE] = {
	   0,    0,    0,    0,    0,    0,    0,    0,
	   0,    0,    0,    0,    0,    0,    0,    0,
	0, 249, 301, 335, 360, 379, 396, 410,
	423, 434, 444, 453, 462, 470, 477, 484,
	491, 497, 502, 508, 513, 518, 523, 528,
	532, 536, 540, 544, 548, 552, 555, 559,
	562, 565, 568, 571, 574, 577, 580, 583,
	586, 588, 591, 593, 596, 598, 601, 603,
	605, 607, 609, 612, 614, 616, 618, 620,
	622, 624, 625, 627, 629, 631, 633, 634,
	636, 638, 640, 641, 643, 644, 646, 647,
	649, 651, 652, 653, 655, 656, 658, 659,
	661, 662, 663, 665, 666, 667, 668, 670,
	671, 672, 673, 675, 676, 677, 678, 679,
	681, 682, 683, 684, 685, 686, 687, 688,
	689, 690, 691, 692, 694, 695, 696, 697,
	698, 699, 699, 700, 701, 702, 703, 704,
	705, 706, 707, 708, 709, 710, 711, 711,
	712, 713, 714, 715, 716, 717, 717, 718,
	719, 720, 721, 721, 722, 723, 724, 725,
	725, 726, 727, 728, 728, 729, 730, 731,
	731, 732, 733, 734, 734, 735, 736, 736,
	737, 738, 738, 739, 740, 741, 741, 742,
	743, 743, 744, 744, 745, 746, 746, 747,
	748, 748, 749, 750, 750, 751, 751, 752,
	753, 753, 754, 754, 755, 756, 756, 757,
	757, 758, 759, 759, 760, 760, 761, 761,
	762, 762, 763, 764, 764, 765, 765, 766,
	766, 767, 767, 768, 768, 769, 769, 770,
	771, 771, 772, 772, 773, 773, 774, 774,
	775, 775, 776, 776, 777, 777, 778, 778,
	778, 779, 779, 780, 780, 781, 781, 782,
	782, 783, 783, 784, 784, 785, 785, 785,
	786, 786, 787, 787, 788, 788, 789, 789,
	1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
	1023, 1023, 1023, 1023, 1023, 1023, 1023, 1023,
	1023
};
#endif

static int dvll_RGB_to_YUV709l_coeff[MATRIX_5x3_COEF_SIZE] = {
	0, 0, 0, /* pre offset */
	COEFF_NORM(0.181873), COEFF_NORM(0.611831), COEFF_NORM(0.061765),
	COEFF_NORM(-0.100251), COEFF_NORM(-0.337249), COEFF_NORM(0.437500),
	COEFF_NORM(0.437500), COEFF_NORM(-0.397384), COEFF_NORM(-0.040116),
	0, 0, 0, /* 10'/11'/12' */
	0, 0, 0, /* 20'/21'/22' */
	64, 512, 512, /* offset */
	0, 0, 0 /* mode, right_shift, clip_en */
};

/*static unsigned int oetf_289_709_mapping[VIDEO_OETF_LUT_SIZE] = {*/
/*	   0,    0,    0,    0,    0,    0,    0,    0,*/
/*	   0,    0,    0,    0,    0,    0,    0,    0,*/
/*	   0,   17,   35,   52,   70,   84,  100,  114,*/
/*	 127,  140,  151,  163,  173,  183,  193,  202,*/
/*	 211,  220,  228,  236,  244,  252,  259,  266,*/
/*	 274,  280,  287,  294,  300,  307,  313,  319,*/
/*	 325,  331,  337,  343,  349,  354,  360,  365,*/
/*	 371,  376,  381,  386,  391,  396,  401,  406,*/
/*	 411,  416,  421,  425,  430,  435,  439,  444,*/
/*	 448,  453,  457,  461,  466,  470,  474,  478,*/
/*	 482,  486,  491,  495,  499,  503,  506,  510,*/
/*	 514,  518,  522,  526,  530,  533,  537,  541,*/
/*	 544,  548,  552,  555,  559,  562,  566,  569,*/
/*	 573,  576,  580,  583,  586,  590,  593,  597,*/
/*	 600,  603,  606,  610,  613,  616,  619,  623,*/
/*	 626,  629,  632,  635,  638,  641,  644,  647,*/
/*	 651,  654,  657,  660,  663,  666,  668,  671,*/
/*	 674,  677,  680,  683,  686,  689,  692,  695,*/
/*	 697,  700,  703,  706,  709,  711,  714,  717,*/
/*	 720,  722,  725,  728,  730,  733,  736,  738,*/
/*	 741,  744,  746,  749,  752,  754,  757,  759,*/
/*	 762,  765,  767,  770,  772,  775,  777,  780,*/
/*	 782,  785,  787,  790,  792,  795,  797,  800,*/
/*	 802,  804,  807,  809,  812,  814,  817,  819,*/
/*	 821,  824,  826,  828,  831,  833,  835,  838,*/
/*	 840,  842,  845,  847,  849,  852,  854,  856,*/
/*	 858,  861,  863,  865,  867,  870,  872,  874,*/
/*	 876,  878,  881,  883,  885,  887,  889,  892,*/
/*	 894,  896,  898,  900,  902,  905,  907,  909,*/
/*	 911,  913,  915,  917,  919,  922,  924,  926,*/
/*	 928,  930,  932,  934,  936,  938,  940,  942,*/
/*	 944,  946,  948,  950,  952,  954,  956,  958,*/
/*	 960,  962,  964,  966,  968,  970,  972,  974,*/
/*	 976,  978,  980,  982,  984,  986,  988,  990,*/
/*	 992,  994,  996,  998, 1000, 1002, 1004, 1006,*/
/*	1008, 1010, 1012, 1014, 1016, 1018, 1020, 1022,*/
/*	1023*/
/*};*/
/*end HLG eotf and oetf curve*/

#define SIGN(a) (((a) < 0) ? "-" : "+")
#define DECI(a) ((a) / 1024)
#define FRAC(a) ({ \
	typeof(a) _a = a; \
	((((_a) >= 0) ? \
	((_a) & 0x3ff) : ((~(_a) + 1) & 0x3ff)) * 10000 / 1024); })

const char matrix_name[7][16] = {
	"OSD",
	"VD1",
	"POST",
	"XVYCC",
	"EOTF",
	"OSD_EOTF",
	"VD2"
};

static void print_vpp_matrix(int m_select, int *s, int on)
{
	unsigned int size;

	if (!s)
		return;
	if (m_select == VPP_MATRIX_OSD)
		size = MATRIX_5x3_COEF_SIZE;
	else if (m_select == VPP_MATRIX_POST)
		size = MATRIX_5x3_COEF_SIZE;
	else if (m_select == VPP_MATRIX_VD1)
		size = MATRIX_5x3_COEF_SIZE;
	else if (m_select == VPP_MATRIX_VD2)
		size = MATRIX_5x3_COEF_SIZE;
	else if (m_select == VPP_MATRIX_XVYCC)
		size = MATRIX_5x3_COEF_SIZE;
	else if (m_select == VPP_MATRIX_EOTF)
		size = EOTF_COEFF_SIZE;
	else if (m_select == VPP_MATRIX_OSD_EOTF)
		size = EOTF_COEFF_SIZE;
	else
		return;

	pr_csc(1, "%s matrix %s:\n", matrix_name[m_select],
	       on ? "on" : "off");

	if (size == MATRIX_5x3_COEF_SIZE) {
		pr_csc(1,
		       "\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\n",
		       SIGN(s[0]), DECI(s[0]), FRAC(s[0]),
		       SIGN(s[3]), DECI(s[3]), FRAC(s[3]),
		       SIGN(s[4]), DECI(s[4]), FRAC(s[4]),
		       SIGN(s[5]), DECI(s[5]), FRAC(s[5]),
		       SIGN(s[18]), DECI(s[18]), FRAC(s[18]));
		pr_csc(1,
		       "\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\n",
		       SIGN(s[1]), DECI(s[1]), FRAC(s[1]),
		       SIGN(s[6]), DECI(s[6]), FRAC(s[6]),
		       SIGN(s[7]), DECI(s[7]), FRAC(s[7]),
		       SIGN(s[8]), DECI(s[8]), FRAC(s[8]),
		       SIGN(s[19]), DECI(s[19]), FRAC(s[19]));
		pr_csc(1,
		       "\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\n",
		       SIGN(s[2]), DECI(s[2]), FRAC(s[2]),
		       SIGN(s[9]), DECI(s[9]), FRAC(s[9]),
		       SIGN(s[10]), DECI(s[10]), FRAC(s[10]),
		       SIGN(s[11]), DECI(s[11]), FRAC(s[11]),
		       SIGN(s[20]), DECI(s[20]), FRAC(s[20]));
		if (s[21]) {
			pr_csc(1, "\t\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\n",
			       SIGN(s[12]), DECI(s[12]), FRAC(s[12]),
			       SIGN(s[13]), DECI(s[13]), FRAC(s[13]),
			       SIGN(s[14]), DECI(s[14]), FRAC(s[14]));
			pr_csc(1, "\t\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\n",
			       SIGN(s[15]), DECI(s[15]), FRAC(s[15]),
			       SIGN(s[16]), DECI(s[16]), FRAC(s[16]),
			       SIGN(s[17]), DECI(s[17]), FRAC(s[17]));
		}
		if (s[22])
			pr_csc(1, "\tright shift=%d\n", s[22]);
	} else {
		pr_csc(1, "\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\n",
		       SIGN(s[0]), DECI(s[0]), FRAC(s[0]),
		       SIGN(s[1]), DECI(s[1]), FRAC(s[1]),
		       SIGN(s[2]), DECI(s[2]), FRAC(s[2]));
		pr_csc(1, "\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\n",
		       SIGN(s[3]), DECI(s[3]), FRAC(s[3]),
		       SIGN(s[4]), DECI(s[4]), FRAC(s[4]),
		       SIGN(s[5]), DECI(s[5]), FRAC(s[5]));
		pr_csc(1, "\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\n",
		       SIGN(s[6]), DECI(s[6]), FRAC(s[6]),
		       SIGN(s[7]), DECI(s[7]), FRAC(s[7]),
		       SIGN(s[8]), DECI(s[8]), FRAC(s[8]));
		if (s[9])
			pr_csc(1, "\tright shift=%d\n", s[9]);
	}
	pr_csc(1, "\n");
}

static int *cur_osd_mtx = RGB709_to_YUV709l_coeff;
static int *cur_post_mtx = bypass_coeff;
static int *cur_vd1_mtx = bypass_coeff;
static int cur_vd1_on = CSC_OFF;
static int cur_post_on = CSC_OFF;
void set_vpp_matrix(int m_select, int *s, int on)
{
	int *m = NULL;
	int size = 0;
	int i, reg_value, addr, val;

	if (debug_csc && print_lut_mtx)
		print_vpp_matrix(m_select, s, on);
	if (m_select == VPP_MATRIX_OSD) {
		m = osd_matrix_coeff;
		size = MATRIX_5x3_COEF_SIZE;
		cur_osd_mtx = s;
	} else if (m_select == VPP_MATRIX_POST)	{
		m = post_matrix_coeff;
		size = MATRIX_5x3_COEF_SIZE;
		cur_post_mtx = s;
		cur_post_on = on;
	} else if (m_select == VPP_MATRIX_VD1) {
		m = vd1_matrix_coeff;
		size = MATRIX_5x3_COEF_SIZE;
		cur_vd1_mtx = s;
		cur_vd1_on = on;
	} else if (m_select == VPP_MATRIX_VD2) {
		m = vd2_matrix_coeff;
		size = MATRIX_5x3_COEF_SIZE;
	} else if (m_select == VPP_MATRIX_XVYCC) {
		m = xvycc_matrix_coeff;
		size = MATRIX_5x3_COEF_SIZE;
	} else if (m_select == VPP_MATRIX_EOTF) {
		m = video_eotf_coeff;
		size = EOTF_COEFF_SIZE;
	} else if (m_select == VPP_MATRIX_OSD_EOTF) {
		m = osd_eotf_coeff;
		size = EOTF_COEFF_SIZE;
	} else {
		return;
	}

	if (s)
		for (i = 0; i < size; i++)
			m[i] = s[i];
	else
		reload_mtx &= ~(1 << m_select);

	reg_value = READ_VPP_REG(VPP_MATRIX_CTRL);

	if (m_select == VPP_MATRIX_OSD) {
		/* osd matrix, VPP_MATRIX_0 */
		if (!is_meson_txlx_cpu() &&
		    !is_meson_gxlx_cpu() &&
		    !is_meson_txhd_cpu()) {
			/* not enable latched */
			hdr_osd_reg.viu_osd1_matrix_pre_offset0_1 =
				((m[0] & 0xfff) << 16) | (m[1] & 0xfff);
			hdr_osd_reg.viu_osd1_matrix_pre_offset2 =
				m[2] & 0xfff;
			hdr_osd_reg.viu_osd1_matrix_coef00_01 =
				((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff);
			hdr_osd_reg.viu_osd1_matrix_coef02_10 =
				((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff);
			hdr_osd_reg.viu_osd1_matrix_coef11_12 =
				((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff);
			hdr_osd_reg.viu_osd1_matrix_coef20_21 =
				((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff);
			if (m[21]) {
				hdr_osd_reg.viu_osd1_matrix_coef22_30 =
					((m[11] & 0x1fff) << 16) |
					(m[12] & 0x1fff);
				hdr_osd_reg.viu_osd1_matrix_coef31_32 =
					((m[13] & 0x1fff) << 16) |
					(m[14] & 0x1fff);
				hdr_osd_reg.viu_osd1_matrix_coef40_41 =
					((m[15] & 0x1fff) << 16) |
					(m[16] & 0x1fff);
				hdr_osd_reg.viu_osd1_matrix_colmod_coef42 =
					m[17] & 0x1fff;
			} else {
				hdr_osd_reg.viu_osd1_matrix_coef22_30 =
					(m[11] & 0x1fff) << 16;
			}
			hdr_osd_reg.viu_osd1_matrix_offset0_1 =
				((m[18] & 0xfff) << 16) | (m[19] & 0xfff);
			hdr_osd_reg.viu_osd1_matrix_offset2 =
				m[20] & 0xfff;

			hdr_osd_reg.viu_osd1_matrix_colmod_coef42 &= 0x3ff8ffff;
			hdr_osd_reg.viu_osd1_matrix_colmod_coef42 |=
				(m[21] << 30) | (m[22] << 16);

			/* 23 reserved for clipping control */
			hdr_osd_reg.viu_osd1_matrix_ctrl &= 0xfffffffc;
			hdr_osd_reg.viu_osd1_matrix_ctrl |= on;
		} else {
			/* move the matrix from osd to vpp in txlx */
			m = osd_matrix_coeff;
			if (is_meson_gxlx_cpu()) {
				if (on) {
					/*VSYNC_WRITE_VPP_REG_BITS(*/
					/*VPP_MATRIX_CTRL,*/
					/*4, 8, 3);*/
					addr = VIU_OSD1_MATRIX_PRE_OFFSET0_1;
					val = ((m[0] & 0xfff) << 16) |
						(m[1] & 0xfff);
					VSYNC_WRITE_VPP_REG(addr, val);
					addr = VIU_OSD1_MATRIX_PRE_OFFSET2;
					val = m[2] & 0xfff;
					VSYNC_WRITE_VPP_REG(addr, val);
					addr = VIU_OSD1_MATRIX_COEF00_01;
					val = ((m[3] & 0x1fff) << 16)
						| (m[4] & 0x1fff);
					VSYNC_WRITE_VPP_REG(addr, val);
					addr = VIU_OSD1_MATRIX_COEF02_10;
					val = ((m[5] & 0x1fff) << 16)
						| (m[6] & 0x1fff);
					VSYNC_WRITE_VPP_REG(addr, val);
					addr = VIU_OSD1_MATRIX_COEF11_12;
					val = ((m[7] & 0x1fff) << 16)
						| (m[8] & 0x1fff);
					VSYNC_WRITE_VPP_REG(addr, val);
					addr = VIU_OSD1_MATRIX_COEF20_21;
					val = ((m[9] & 0x1fff) << 16)
						| (m[10] & 0x1fff);
					VSYNC_WRITE_VPP_REG(addr, val);
					addr = VIU_OSD1_MATRIX_COLMOD_COEF42;
					val = m[11] & 0x1fff;
					VSYNC_WRITE_VPP_REG(addr, val);
					addr = VIU_OSD1_MATRIX_OFFSET0_1;
					val = ((m[18] & 0xfff) << 16)
						| (m[19] & 0xfff);
					VSYNC_WRITE_VPP_REG(addr, val);
					addr = VIU_OSD1_MATRIX_OFFSET2;
					val = m[20] & 0xfff;
					VSYNC_WRITE_VPP_REG(addr, val);
				}
				/*VSYNC_WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL,*/
				/*on, 7, 1);*/
				addr = VIU_OSD1_MATRIX_CTRL;
				VSYNC_WRITE_VPP_REG_BITS(addr, on, 0, 1);
			} else {
				if (on) {
					/*VSYNC_WRITE_VPP_REG_BITS(*/
					/*VPP_MATRIX_CTRL,*/
					/*4, 8, 3);*/
					reg_value = (reg_value &
						    (~(7 << 8))) |
						    (4 << 8);
					addr = VPP_MATRIX_CTRL;
					VSYNC_WRITE_VPP_REG(addr, reg_value);
					addr = VPP_MATRIX_PRE_OFFSET0_1;
					val = ((m[0] & 0xfff) << 16) |
						(m[1] & 0xfff);
					VSYNC_WRITE_VPP_REG(addr, val);
					addr = VPP_MATRIX_PRE_OFFSET2;
					val = m[2] & 0xfff;
					VSYNC_WRITE_VPP_REG(addr, val);
					addr = VPP_MATRIX_COEF00_01;
					val = ((m[3] & 0x1fff) << 16)
						| (m[4] & 0x1fff);
					VSYNC_WRITE_VPP_REG(addr, val);
					addr = VPP_MATRIX_COEF02_10;
					val = ((m[5] & 0x1fff) << 16)
						| (m[6] & 0x1fff);
					VSYNC_WRITE_VPP_REG(addr, val);
					addr = VPP_MATRIX_COEF11_12;
					val = ((m[7] & 0x1fff) << 16)
						| (m[8] & 0x1fff);
					VSYNC_WRITE_VPP_REG(addr, val);
					addr = VPP_MATRIX_COEF20_21;
					val = ((m[9] & 0x1fff) << 16)
						| (m[10] & 0x1fff);
					VSYNC_WRITE_VPP_REG(addr, val);
					addr = VPP_MATRIX_COEF22;
					val = m[11] & 0x1fff;
					VSYNC_WRITE_VPP_REG(addr, val);
					if (m[21]) {
						addr = VPP_MATRIX_COEF13_14;
						val = ((m[12] & 0x1fff) << 16)
							| (m[13] & 0x1fff);
						VSYNC_WRITE_VPP_REG(addr, val);
						addr = VPP_MATRIX_COEF15_25;
						val = ((m[14] & 0x1fff) << 16)
							| (m[17] & 0x1fff);
						VSYNC_WRITE_VPP_REG(addr, val);
						addr = VPP_MATRIX_COEF23_24;
						val = ((m[15] & 0x1fff) << 16)
							| (m[16] & 0x1fff);
						VSYNC_WRITE_VPP_REG(addr, val);
					}
					if (is_meson_txhd_cpu()) {
						addr = VPP_MATRIX_OFFSET0_1;
						val = (m[18] >> 2) & 0xfff;
						val = val << 16;
						val |= (m[19] >> 2) & 0xfff;
						VSYNC_WRITE_VPP_REG(addr, val);
						addr = VPP_MATRIX_OFFSET2;
						val = (m[20] >> 2) & 0xfff;
						VSYNC_WRITE_VPP_REG(addr, val);
					} else {
						addr = VPP_MATRIX_OFFSET0_1;
						val = ((m[18] & 0xfff) << 16)
							| (m[19] & 0xfff);
						VSYNC_WRITE_VPP_REG(addr, val);
						addr = VPP_MATRIX_OFFSET2;
						val = m[20] & 0xfff;
						VSYNC_WRITE_VPP_REG(addr, val);
					}

					addr = VPP_MATRIX_CLIP;
					VSYNC_WRITE_VPP_REG_BITS(addr,
								 m[21], 3, 2);
					addr = VPP_MATRIX_CLIP;
					VSYNC_WRITE_VPP_REG_BITS(addr,
								 m[22], 5, 3);
				}
				/*VSYNC_WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL,*/
				/*on, 7, 1);*/
				if (on)
					mtx_en_mux |= OSD1_MTX_EN_MASK;
				else
					mtx_en_mux &= ~OSD1_MTX_EN_MASK;
			}
		}
	} else if (m_select == VPP_MATRIX_EOTF) {
		/* eotf matrix, VPP_MATRIX_EOTF */
		/* enable latched */
		for (i = 0; i < 5; i++)
			VSYNC_WRITE_VPP_REG(VIU_EOTF_CTL + i + 1,
					    ((m[i * 2] & 0x1fff) << 16) |
					  (m[i * 2 + 1] & 0x1fff));
		if (is_meson_txlx_cpu() ||
		    is_meson_gxlx_cpu() ||
		    is_meson_txhd_cpu()) {
			VSYNC_WRITE_VPP_REG(VIU_EOTF_CTL + 8, 0);
			VSYNC_WRITE_VPP_REG(VIU_EOTF_CTL + 9, 0);
		}
		WRITE_VPP_REG_BITS(VIU_EOTF_CTL, on, 30, 1);
		WRITE_VPP_REG_BITS(VIU_EOTF_CTL, on, 31, 1);
	} else if (m_select == VPP_MATRIX_OSD_EOTF) {
		/* osd eotf matrix, VPP_MATRIX_OSD_EOTF */
		if (!is_meson_txlx_cpu() &&
		    !is_meson_gxlx_cpu() &&
		    !is_meson_txhd_cpu()) {
			/* enable latched */
			hdr_osd_reg.viu_osd1_eotf_coef00_01 =
				((m[0 * 2] & 0x1fff) << 16)
				| (m[0 * 2 + 1] & 0x1fff);

			hdr_osd_reg.viu_osd1_eotf_coef02_10 =
				((m[1 * 2] & 0x1fff) << 16)
				| (m[1 * 2 + 1] & 0x1fff);

			hdr_osd_reg.viu_osd1_eotf_coef11_12 =
				((m[2 * 2] & 0x1fff) << 16)
				| (m[2 * 2 + 1] & 0x1fff);

			hdr_osd_reg.viu_osd1_eotf_coef20_21 =
				((m[3 * 2] & 0x1fff) << 16)
				| (m[3 * 2 + 1] & 0x1fff);
			hdr_osd_reg.viu_osd1_eotf_coef22_rs =
				((m[4 * 2] & 0x1fff) << 16)
				| (m[4 * 2 + 1] & 0x1fff);

			hdr_osd_reg.viu_osd1_eotf_ctl &= 0x3fffffff;
			hdr_osd_reg.viu_osd1_eotf_ctl |=
				(on << 30) | (on << 31);
		} else {
			/* latch enable */
			WRITE_VPP_REG_BITS(VIU_OSD1_EOTF_CTL, 1, 26, 1);
			if (on) {
				VSYNC_WRITE_VPP_REG(VIU_OSD1_EOTF_COEF00_01,
						    ((m[0 * 2] & 0x1fff) << 16) |
						  (m[0 * 2 + 1] & 0x1fff));
				VSYNC_WRITE_VPP_REG(VIU_OSD1_EOTF_COEF02_10,
						    ((m[1 * 2] & 0x1fff) << 16) |
						  (m[1 * 2 + 1] & 0x1fff));
				VSYNC_WRITE_VPP_REG(VIU_OSD1_EOTF_COEF11_12,
						    ((m[2 * 2] & 0x1fff) << 16) |
						  (m[2 * 2 + 1] & 0x1fff));
				VSYNC_WRITE_VPP_REG(VIU_OSD1_EOTF_COEF20_21,
						    ((m[3 * 2] & 0x1fff) << 16) |
						  (m[3 * 2 + 1] & 0x1fff));
				VSYNC_WRITE_VPP_REG(VIU_OSD1_EOTF_COEF22_RS,
						    ((m[4 * 2] & 0x1fff) << 16) |
						  (m[4 * 2 + 1] & 0x1fff));
			}
			WRITE_VPP_REG_BITS(VIU_OSD1_EOTF_CTL,
					   (on | (on << 1)), 30, 2);
		}
	} else {
		/* vd1 matrix, VPP_MATRIX_1 */
		/* post matrix, VPP_MATRIX_2 */
		/* xvycc matrix, VPP_MATRIX_3 */
		/* vd2 matrix, VPP_MATRIX_6 */
		if (m_select == VPP_MATRIX_POST) {
			/* post matrix */
			m = post_matrix_coeff;
			if (rdma_flag & (1 << m_select)) {
				/* set bit for disable latched */
				WRITE_VPP_REG_BITS(VPP_XVYCC_MISC, 0, 14, 1);
				if (on)
					mtx_en_mux |= POST_MTX_EN_MASK;
				else
					mtx_en_mux &= ~POST_MTX_EN_MASK;
			} else {
				WRITE_VPP_REG_BITS(VPP_XVYCC_MISC, 1, 14, 1);
				WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL, on, 0, 1);
			}

			if (on) {
				if (rdma_flag & (1 << m_select)) {
					/*VSYNC_WRITE_VPP_REG_BITS(*/
					/*VPP_MATRIX_CTRL, 0, 8, 3);*/
					val = (reg_value & (~(7 << 8)))
						| (0 << 8);
					VSYNC_WRITE_VPP_REG(VPP_MATRIX_CTRL,
							    val);
				} else {
					WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL,
							   0, 8, 3);
				}
			}
		} else if (m_select == VPP_MATRIX_VD1) {
			/* vd1 matrix, latched */
			m = vd1_matrix_coeff;
			if (rdma_flag & (1 << m_select)) {
				/* set bit for disable latched */
				WRITE_VPP_REG_BITS(VPP_XVYCC_MISC, 0, 9, 1);
				/*WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL,*/
				/*on, 5, 1);*/
				if (on)
					mtx_en_mux |= VD1_MTX_EN_MASK;
				else
					mtx_en_mux &= ~VD1_MTX_EN_MASK;
			} else {
				/* set bit for enable latched */
				WRITE_VPP_REG_BITS(VPP_XVYCC_MISC, 1, 9, 1);
				WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL, on, 5, 1);
			}
			if (on) {
				if (rdma_flag & (1 << m_select)) {
					/*VSYNC_WRITE_VPP_REG_BITS(*/
					/*VPP_MATRIX_CTRL, 1, 8, 3);*/
					val = (reg_value & (~(7 << 8)))
						| (1 << 8);
					VSYNC_WRITE_VPP_REG(VPP_MATRIX_CTRL,
							    val);
				} else {
					WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL,
							   1, 8, 3);
				}
			}
		} else if (m_select == VPP_MATRIX_VD2) {
			/* vd2 matrix, not latched */
			m = vd2_matrix_coeff;
			if (rdma_flag & (1 << m_select)) {
				if (on)
					mtx_en_mux |= VD2_MTX_EN_MASK;
				else
					mtx_en_mux &= ~VD2_MTX_EN_MASK;
			} else {
				WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL, on, 4, 1);
			}
			if (on) {
				if (rdma_flag & (1 << m_select)) {
					/*VSYNC_WRITE_VPP_REG_BITS(*/
					/*VPP_MATRIX_CTRL, 2, 8, 3);*/
					val = (reg_value & (~(7 << 8)))
						| (2 << 8);
					VSYNC_WRITE_VPP_REG(VPP_MATRIX_CTRL,
							    val);
				} else {
					WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL,
							   2, 8, 3);
				}
			}
		} else if (m_select == VPP_MATRIX_XVYCC) {
			/* xvycc matrix, not latched */
			m = xvycc_matrix_coeff;

			if (on) {
				if (rdma_flag & (1 << m_select)) {
					mtx_en_mux |= XVY_MTX_EN_MASK;
					val = (reg_value & (~(7 << 8)))
							| (3 << 8);
					VSYNC_WRITE_VPP_REG(VPP_MATRIX_CTRL,
							    val);
				} else {
					WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL,
							   on, 6, 1);
					WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL,
							   3, 8, 3);
				}
			} else {
				if (rdma_flag & (1 << m_select)) {
					mtx_en_mux &= ~XVY_MTX_EN_MASK;
				} else {
					WRITE_VPP_REG_BITS(VPP_MATRIX_CTRL,
							   on, 6, 1);
				}
			}
		}
		if (on) {
			if (rdma_flag & (1 << m_select)) {
				val = ((m[0] & 0xfff) << 16)
					| (m[1] & 0xfff);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET0_1,
						    val);
				val = m[2] & 0xfff;
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET2,
						    val);
				val = ((m[3] & 0x1fff) << 16)
					| (m[4] & 0x1fff);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF00_01,
						    val);
				val = ((m[5] & 0x1fff) << 16)
					| (m[6] & 0x1fff);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF02_10,
						    val);
				val = ((m[7] & 0x1fff) << 16)
					| (m[8] & 0x1fff);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF11_12,
						    val);
				val = ((m[9] & 0x1fff) << 16)
					| (m[10] & 0x1fff);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF20_21,
						    val);
				val = m[11] & 0x1fff;
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF22,
						    val);
				if (m[21]) {
					val = ((m[12] & 0x1fff) << 16)
						| (m[13] & 0x1fff);
					VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF13_14,
							    val);
					val = ((m[14] & 0x1fff) << 16)
						| (m[17] & 0x1fff);
					VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF15_25,
							    val);
					val = ((m[15] & 0x1fff) << 16)
						| (m[16] & 0x1fff);
					VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF23_24,
							    val);
				}
				if (is_meson_txhd_cpu() &&
				    m_select == VPP_MATRIX_XVYCC) {
					val = (((m[18] >> 2) & 0xfff) << 16)
						| ((m[19] >> 2) & 0xfff);
					VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1,
							    val);
					val = (m[20] >> 2) & 0xfff;
					VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET2,
							    val);
				} else {
					val = ((m[18] & 0xfff) << 16)
						| (m[19] & 0xfff);
					VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1,
							    val);
					val = m[20] & 0xfff;
					VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET2,
							    val);
				}
				VSYNC_WRITE_VPP_REG_BITS(VPP_MATRIX_CLIP,
							 m[21], 3, 2);
				VSYNC_WRITE_VPP_REG_BITS(VPP_MATRIX_CLIP,
							 m[22], 5, 3);
			} else {
				val = ((m[0] & 0xfff) << 16)
					| (m[1] & 0xfff);
				WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET0_1,
					      val);
				val = m[2] & 0xfff;
				WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET2,
					      val);
				val = ((m[3] & 0x1fff) << 16)
					| (m[4] & 0x1fff);
				WRITE_VPP_REG(VPP_MATRIX_COEF00_01,
					      val);
				val = ((m[5]  & 0x1fff) << 16)
					| (m[6] & 0x1fff);
				WRITE_VPP_REG(VPP_MATRIX_COEF02_10,
					      val);
				val = ((m[7] & 0x1fff) << 16)
					| (m[8] & 0x1fff);
				WRITE_VPP_REG(VPP_MATRIX_COEF11_12,
					      val);
				val = ((m[9] & 0x1fff) << 16)
					| (m[10] & 0x1fff);
				WRITE_VPP_REG(VPP_MATRIX_COEF20_21,
					      val);
				val = m[11] & 0x1fff;
				WRITE_VPP_REG(VPP_MATRIX_COEF22,
					      val);
				if (m[21]) {
					val = ((m[12] & 0x1fff) << 16)
						| (m[13] & 0x1fff);
					WRITE_VPP_REG(VPP_MATRIX_COEF13_14,
						      val);
					val = ((m[14] & 0x1fff) << 16)
						| (m[17] & 0x1fff);
					WRITE_VPP_REG(VPP_MATRIX_COEF15_25,
						      val);
					val = ((m[15] & 0x1fff) << 16)
						| (m[16] & 0x1fff);
					WRITE_VPP_REG(VPP_MATRIX_COEF23_24,
						      val);
				}
				if (is_meson_txhd_cpu()	&&
				    m_select == VPP_MATRIX_XVYCC) {
					val = (((m[18] >> 2) & 0xfff) << 16)
						| ((m[19] >> 2) & 0xfff);
					WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1,
						      val);
					val = (m[20] >> 2) & 0xfff;
					WRITE_VPP_REG(VPP_MATRIX_OFFSET2,
						      val);
				} else {
					val = ((m[18] & 0xfff) << 16)
						| (m[19] & 0xfff);
					WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1,
						      val);
					val = m[20] & 0xfff;
					WRITE_VPP_REG(VPP_MATRIX_OFFSET2,
						      val);
				}
				WRITE_VPP_REG_BITS(VPP_MATRIX_CLIP,
						   m[21], 3, 2);
				WRITE_VPP_REG_BITS(VPP_MATRIX_CLIP,
						   m[22], 5, 3);
			}
		}
	}
}
#endif

void enable_osd_path(int on, int shadow_mode)
{
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	static int *osd1_mtx_backup;
	static u32 osd1_eotf_ctl_backup;
	static u32 osd1_oetf_ctl_backup;

	if (!on) {
		osd1_mtx_backup = cur_osd_mtx;
		osd1_eotf_ctl_backup = hdr_osd_reg.viu_osd1_eotf_ctl;
		osd1_oetf_ctl_backup = hdr_osd_reg.viu_osd1_oetf_ctl;

		set_vpp_matrix(VPP_MATRIX_OSD, bypass_coeff, CSC_ON);
		hdr_osd_reg.viu_osd1_eotf_ctl &= 0x07ffffff;
		hdr_osd_reg.viu_osd1_oetf_ctl &= 0x1fffffff;
		hdr_osd_reg.shadow_mode = shadow_mode;
	} else {
		set_vpp_matrix(VPP_MATRIX_OSD, osd1_mtx_backup, CSC_ON);
		hdr_osd_reg.viu_osd1_eotf_ctl = osd1_eotf_ctl_backup;
		hdr_osd_reg.viu_osd1_oetf_ctl = osd1_oetf_ctl_backup;
		hdr_osd_reg.shadow_mode = shadow_mode;
	}
#endif
}
EXPORT_SYMBOL(enable_osd_path);

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
/* coeff: pointer to target coeff array */
/* bits: how many bits for target coeff, could be 10 ~ 12, default 10 */
static s32 *post_mtx_backup;
static s32 post_on_backup;
static bool restore_post_table;
static s32 *vd1_mtx_backup;
static s32 vd1_on_backup;
#endif

int enable_rgb_to_yuv_matrix_for_dvll(s32 on, u32 *coeff_orig, u32 bits)
{
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	s32 i;
	u32 coeff01, coeff23, coeff45, coeff67, coeff89;
	u32 scale, shift, offset[3];
	s32 *coeff = dvll_RGB_to_YUV709l_coeff;

	if (bits < 10 || bits > 12)
		return -1;
	if (on && !coeff_orig)
		return -2;
	if (on) {
		/* only store the start one */
		if (cur_post_mtx !=
		    dvll_RGB_to_YUV709l_coeff) {
			post_mtx_backup = cur_post_mtx;
			post_on_backup = cur_post_on;
			vd1_mtx_backup = cur_vd1_mtx;
			vd1_on_backup = cur_vd1_on;
		}
		coeff01 = coeff_orig[0];
		coeff23 = coeff_orig[1];
		coeff45 = coeff_orig[2];
		coeff67 = coeff_orig[3];
		coeff89 = coeff_orig[4] & 0xffff;
		scale = (coeff_orig[4] >> 16) & 0x0f;
		offset[0] = coeff_orig[5];
		offset[1] = 0; /* coeff_orig[6]; */
		offset[2] = 0; /* coeff_orig[7]; */

		coeff[0] = 0;
		coeff[1] = 0;
		coeff[2] = 0; /* pre offset */

		coeff[5] = (int32_t)((coeff01 & 0xffff) << 16) >> 16;
		coeff[3] = (int32_t)coeff01 >> 16;
		coeff[4] = (int32_t)((coeff23 & 0xffff) << 16) >> 16;
		coeff[8] = (int32_t)coeff23 >> 16;
		coeff[6] = (int32_t)((coeff45 & 0xffff) << 16) >> 16;
		coeff[7] = (int32_t)coeff45 >> 16;
		coeff[11] = (int32_t)((coeff67 & 0xffff) << 16) >> 16;
		coeff[9] = (int32_t)coeff67 >> 16;
		coeff[10] = (int32_t)((coeff89 & 0xffff) << 16) >> 16;

		if (scale > 12) {
			shift = scale - 12;
			for (i = 3; i < 12; i++)
				coeff[i] =
					(coeff[i] + (1 << (shift - 1)))
					>> shift;
		} else if (scale < 12) {
			shift = 12 - scale;
			for (i = 3; i < 12; i++)
				coeff[i] <<= shift;
		}

		/* post offset */
		coeff[18] = offset[0];
		coeff[19] = offset[1];
		coeff[20] = offset[2];

		coeff[5] =
			((coeff[3] + coeff[4] + coeff[5]) & 0xfffe)
			- coeff[3] - coeff[4];
		coeff[8] = 0 - coeff[6] - coeff[7];
		coeff[11] = 0 - coeff[9] - coeff[10];
		coeff[18] -= (0x1000 - coeff[3] - coeff[4] - coeff[5]) >> 1;

		coeff[22] = 2;
		vpp_set_mtx_en_read();
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_CTRL, 0);
		set_vpp_matrix(VPP_MATRIX_OSD,
			       cur_osd_mtx, CSC_OFF);
		set_vpp_matrix(VPP_MATRIX_VD1,
			       cur_vd1_mtx, CSC_OFF);
		set_vpp_matrix(VPP_MATRIX_POST,
			       coeff, CSC_ON);
		vpp_set_mtx_en_write();
		restore_post_table = true;
	} else if (restore_post_table) {
		vpp_set_mtx_en_read();
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_CTRL, 0);
		set_vpp_matrix(VPP_MATRIX_OSD,
			       cur_osd_mtx, CSC_OFF);
		set_vpp_matrix(VPP_MATRIX_VD1,
			       vd1_mtx_backup, cur_vd1_on);
		set_vpp_matrix(VPP_MATRIX_POST,
			       post_mtx_backup, post_on_backup);
		vpp_set_mtx_en_write();
		restore_post_table = false;
	}
#endif
	return 0;
}
EXPORT_SYMBOL(enable_rgb_to_yuv_matrix_for_dvll);

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
const char lut_name[NUM_LUT][16] = {
	"OSD_EOTF",
	"OSD_OETF",
	"EOTF",
	"OETF",
	"INV_EOTF"
};

/* VIDEO_OETF_LUT_SIZE 289 >*/
/*	OSD_OETF_LUT_SIZE 41 >*/
/*	OSD_OETF_LUT_SIZE 33 */
static void print_vpp_lut(enum vpp_lut_sel_e lut_sel, int on)
{
	unsigned short *r_map;
	unsigned short *g_map;
	unsigned short *b_map;
	unsigned int addr_port;
	unsigned int data_port;
	unsigned int ctrl_port;
	unsigned int data;
	int i;

	r_map = kmalloc(sizeof(unsigned short) * VIDEO_OETF_LUT_SIZE * 3,
			GFP_ATOMIC);
	if (!r_map)
		return;
	g_map = &r_map[VIDEO_OETF_LUT_SIZE];
	b_map = &r_map[VIDEO_OETF_LUT_SIZE * 2];

	if (lut_sel == VPP_LUT_OSD_EOTF) {
		addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
		data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
		ctrl_port = VIU_OSD1_EOTF_CTL;
	} else if (lut_sel == VPP_LUT_EOTF) {
		addr_port = VIU_EOTF_LUT_ADDR_PORT;
		data_port = VIU_EOTF_LUT_DATA_PORT;
		ctrl_port = VIU_EOTF_CTL;
	} else if (lut_sel == VPP_LUT_OSD_OETF) {
		addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
		data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
		ctrl_port = VIU_OSD1_OETF_CTL;
	} else if (lut_sel == VPP_LUT_OETF) {
		addr_port = XVYCC_LUT_R_ADDR_PORT;
		data_port = XVYCC_LUT_R_DATA_PORT;
		ctrl_port = XVYCC_LUT_CTL;
	} else if (lut_sel == VPP_LUT_INV_EOTF) {
		addr_port = XVYCC_INV_LUT_Y_ADDR_PORT;
		data_port = XVYCC_INV_LUT_Y_DATA_PORT;
		ctrl_port = XVYCC_INV_LUT_CTL;
	} else {
		kfree(r_map);
		return;
	}
	if (lut_sel == VPP_LUT_OSD_OETF) {
		for (i = 0; i < 20; i++) {
			WRITE_VPP_REG(addr_port, i);
			data = READ_VPP_REG(data_port);
			r_map[i * 2] = data & 0xffff;
			r_map[i * 2 + 1] = (data >> 16) & 0xffff;
		}
		WRITE_VPP_REG(addr_port, 20);
		data = READ_VPP_REG(data_port);
		r_map[OSD_OETF_LUT_SIZE - 1] = data & 0xffff;
		g_map[0] = (data >> 16) & 0xffff;
		for (i = 0; i < 20; i++) {
			WRITE_VPP_REG(addr_port, 21 + i);
			data = READ_VPP_REG(data_port);
			g_map[i * 2 + 1] = data & 0xffff;
			g_map[i * 2 + 2] = (data >> 16) & 0xffff;
		}
		for (i = 0; i < 20; i++) {
			WRITE_VPP_REG(addr_port, 41 + i);
			data = READ_VPP_REG(data_port);
			b_map[i * 2] = data & 0xffff;
			b_map[i * 2 + 1] = (data >> 16) & 0xffff;
		}
		WRITE_VPP_REG(addr_port, 61);
		data = READ_VPP_REG(data_port);
		b_map[OSD_OETF_LUT_SIZE - 1] = data & 0xffff;
		pr_csc(1, "%s lut %s:\n", lut_name[lut_sel], on ? "on" : "off");
		for (i = 0; i < OSD_OETF_LUT_SIZE; i++) {
			pr_csc(1, "\t[%d] = 0x%04x 0x%04x 0x%04x\n",
			       i, r_map[i], g_map[i], b_map[i]);
		}
		pr_csc(1, "\n");
	} else if (lut_sel == VPP_LUT_OSD_EOTF) {
		WRITE_VPP_REG(addr_port, 0);
		for (i = 0; i < 16; i++) {
			data = READ_VPP_REG(data_port);
			r_map[i * 2] = data & 0xffff;
			r_map[i * 2 + 1] = (data >> 16) & 0xffff;
		}
		data = READ_VPP_REG(data_port);
		r_map[EOTF_LUT_SIZE - 1] = data & 0xffff;
		g_map[0] = (data >> 16) & 0xffff;
		for (i = 0; i < 16; i++) {
			data = READ_VPP_REG(data_port);
			g_map[i * 2 + 1] = data & 0xffff;
			g_map[i * 2 + 2] = (data >> 16) & 0xffff;
		}
		for (i = 0; i < 16; i++) {
			data = READ_VPP_REG(data_port);
			b_map[i * 2] = data & 0xffff;
			b_map[i * 2 + 1] = (data >> 16) & 0xffff;
		}
		data = READ_VPP_REG(data_port);
		b_map[EOTF_LUT_SIZE - 1] = data & 0xffff;
		pr_csc(1, "%s lut %s:\n", lut_name[lut_sel], on ? "on" : "off");
		for (i = 0; i < EOTF_LUT_SIZE; i++) {
			pr_csc(1, "\t[%d] = 0x%04x 0x%04x 0x%04x\n",
			       i, r_map[i], g_map[i], b_map[i]);
		}
		pr_csc(1, "\n");
	} else if (lut_sel == VPP_LUT_EOTF) {
		WRITE_VPP_REG(addr_port, 0);
		for (i = 0; i < 16; i++) {
			data = READ_VPP_REG(data_port);
			r_map[i * 2] = data & 0xffff;
			r_map[i * 2 + 1] = (data >> 16) & 0xffff;
		}
		data = READ_VPP_REG(data_port);
		r_map[EOTF_LUT_SIZE - 1] = data & 0xffff;
		g_map[0] = (data >> 16) & 0xffff;
		for (i = 0; i < 16; i++) {
			data = READ_VPP_REG(data_port);
			g_map[i * 2 + 1] = data & 0xffff;
			g_map[i * 2 + 2] = (data >> 16) & 0xffff;
		}
		for (i = 0; i < 16; i++) {
			data = READ_VPP_REG(data_port);
			b_map[i * 2] = data & 0xffff;
			b_map[i * 2 + 1] = (data >> 16) & 0xffff;
		}
		data = READ_VPP_REG(data_port);
		b_map[EOTF_LUT_SIZE - 1] = data & 0xffff;
		pr_csc(1, "%s lut %s:\n", lut_name[lut_sel], on ? "on" : "off");
		for (i = 0; i < EOTF_LUT_SIZE; i++) {
			pr_csc(1, "\t[%d] = 0x%04x 0x%04x 0x%04x\n",
			       i, r_map[i], g_map[i], b_map[i]);
		}
		pr_csc(1, "\n");
	} else if (lut_sel == VPP_LUT_OETF) {
		WRITE_VPP_REG(ctrl_port, 0x0);
		WRITE_VPP_REG(addr_port, 0);
		for (i = 0; i < VIDEO_OETF_LUT_SIZE; i++)
			r_map[i] = READ_VPP_REG(data_port) & 0x3ff;
		WRITE_VPP_REG(addr_port + 2, 0);
		for (i = 0; i < VIDEO_OETF_LUT_SIZE; i++)
			g_map[i] = READ_VPP_REG(data_port + 2) & 0x3ff;
		WRITE_VPP_REG(addr_port + 4, 0);
		for (i = 0; i < VIDEO_OETF_LUT_SIZE; i++)
			b_map[i] = READ_VPP_REG(data_port + 4) & 0x3ff;
		pr_csc(1, "%s lut %s:\n", lut_name[lut_sel], on ? "on" : "off");
		for (i = 0; i < VIDEO_OETF_LUT_SIZE; i++) {
			pr_csc(1, "\t[%d] = 0x%04x 0x%04x 0x%04x\n",
			       i, r_map[i], g_map[i], b_map[i]);
		}
		pr_csc(1, "\n");
		if (on)
			WRITE_VPP_REG(ctrl_port, 0x7f);
	} else if (lut_sel == VPP_LUT_INV_EOTF) {
		WRITE_VPP_REG_BITS(ctrl_port, 0, 12, 3);
		pr_csc(1, "%s lut %s:\n", lut_name[lut_sel], on ? "on" : "off");
		for (i = 0;
			i < EOTF_INV_LUT_NEG2048_SIZE +
			EOTF_INV_LUT_SIZE + EOTF_INV_LUT_1024_SIZE;
			i++) {
			WRITE_VPP_REG(addr_port, i);
			data = READ_VPP_REG(data_port) & 0xfff;
			if (data & 0x800)
				pr_csc(1, "\t[%d] = %d\n",
				       i, -(~(data | 0xfffff000) + 1));
			else
				pr_csc(1, "\t[%d] = %d\n", i, data);
		}
		pr_csc(1, "\n");
		if (on)
			WRITE_VPP_REG_BITS(ctrl_port, 1 << 2, 12, 3);
	}
	kfree(r_map);
}

void set_vpp_lut(enum vpp_lut_sel_e lut_sel,
		 unsigned int *r,
		 unsigned int *g,
		 unsigned int *b,
		 int on)
{
	unsigned int *r_map = NULL;
	unsigned int *g_map = NULL;
	unsigned int *b_map = NULL;
	unsigned int addr_port;
	unsigned int data_port;
	unsigned int ctrl_port;
	int i, val;

	if (reload_lut & (1 << lut_sel))
		reload_lut &= ~(1 << lut_sel);
	if (lut_sel == VPP_LUT_OSD_EOTF) {
		r_map = osd_eotf_r_mapping;
		g_map = osd_eotf_g_mapping;
		b_map = osd_eotf_b_mapping;
		addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
		data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
		ctrl_port = VIU_OSD1_EOTF_CTL;
	} else if (lut_sel == VPP_LUT_EOTF) {
		r_map = video_eotf_r_mapping;
		g_map = video_eotf_g_mapping;
		b_map = video_eotf_b_mapping;
		addr_port = VIU_EOTF_LUT_ADDR_PORT;
		data_port = VIU_EOTF_LUT_DATA_PORT;
		ctrl_port = VIU_EOTF_CTL;
	} else if (lut_sel == VPP_LUT_OSD_OETF) {
		r_map = osd_oetf_r_mapping;
		g_map = osd_oetf_g_mapping;
		b_map = osd_oetf_b_mapping;
		addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
		data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
		ctrl_port = VIU_OSD1_OETF_CTL;
	} else if (lut_sel == VPP_LUT_OETF) {
		r_map = video_oetf_r_mapping;
		g_map = video_oetf_g_mapping;
		b_map = video_oetf_b_mapping;
		addr_port = XVYCC_LUT_R_ADDR_PORT;
		data_port = XVYCC_LUT_R_DATA_PORT;
		ctrl_port = XVYCC_LUT_CTL;
	} else if (lut_sel == VPP_LUT_INV_EOTF) {
		addr_port = XVYCC_INV_LUT_Y_ADDR_PORT;
		data_port = XVYCC_INV_LUT_Y_DATA_PORT;
		ctrl_port = XVYCC_INV_LUT_CTL;
	} else {
		return;
	}

	if (lut_sel == VPP_LUT_OSD_OETF) {
		/* enable latched */
		if (r && r_map)
			for (i = 0; i < OSD_OETF_LUT_SIZE; i++)
				r_map[i] = r[i];
		if (g && g_map)
			for (i = 0; i < OSD_OETF_LUT_SIZE; i++)
				g_map[i] = g[i];
		if (r && r_map)
			for (i = 0; i < OSD_OETF_LUT_SIZE; i++)
				b_map[i] = b[i];

		if (!is_meson_txlx_cpu()) {
			for (i = 0; i < OSD_OETF_LUT_SIZE; i++) {
				hdr_osd_reg.lut_val.or_map[i] = r_map[i];
				hdr_osd_reg.lut_val.og_map[i] = g_map[i];
				hdr_osd_reg.lut_val.ob_map[i] = b_map[i];
			}
			hdr_osd_reg.viu_osd1_oetf_ctl &= 0x1fffffff;
			hdr_osd_reg.viu_osd1_oetf_ctl |= 7 << 22;
			if (on)
				hdr_osd_reg.viu_osd1_oetf_ctl |= 7 << 29;
		} else {
			/* latch enable */
			WRITE_VPP_REG_BITS(VIU_OSD1_OETF_CTL, 1, 28, 1);
			if (on) {
				/* change to 12bit from txlx */
				if (is_meson_txlx_cpu())
					for (i = 0;
					     i < OSD_OETF_LUT_SIZE;
					     i++) {
						r_map[i] = 4 * r_map[i];
						g_map[i] = 4 * g_map[i];
						b_map[i] = 4 * b_map[i];
					}
				for (i = 0; i < 20; i++) {
					VSYNC_WRITE_VPP_REG(addr_port, i);
					val = r_map[i * 2] |
					      (r_map[i * 2 + 1] << 16);
					VSYNC_WRITE_VPP_REG(data_port,
							    val);
				}
				VSYNC_WRITE_VPP_REG(addr_port, 20);
				val = r_map[41 - 1]
					| (g_map[0] << 16);
				VSYNC_WRITE_VPP_REG(data_port,
						    val);
				for (i = 0; i < 20; i++) {
					VSYNC_WRITE_VPP_REG(addr_port, 21 + i);
					val = g_map[i * 2 + 1]
						| (g_map[i * 2 + 2] << 16);
					VSYNC_WRITE_VPP_REG(data_port,
							    val);
				}
				for (i = 0; i < 20; i++) {
					VSYNC_WRITE_VPP_REG(addr_port, 41 + i);
					val = b_map[i * 2]
						| (b_map[i * 2 + 1] << 16);
					VSYNC_WRITE_VPP_REG(data_port,
							    val);
				}
				VSYNC_WRITE_VPP_REG(addr_port, 61);
				val = b_map[41 - 1];
				VSYNC_WRITE_VPP_REG(data_port,
						    val);
			}

			WRITE_VPP_REG_BITS(VIU_OSD1_OETF_CTL, 7, 22, 3);
			WRITE_VPP_REG_BITS(VIU_OSD1_OETF_CTL,
					   (on | (on << 1) | (on << 2)),
					   29, 3);
		}
	} else if (lut_sel == VPP_LUT_OSD_EOTF) {
		/* enable latched */
		if (r && r_map)
			for (i = 0; i < EOTF_LUT_SIZE; i++)
				r_map[i] = r[i];
		if (g && g_map)
			for (i = 0; i < EOTF_LUT_SIZE; i++)
				g_map[i] = g[i];
		if (r && r_map)
			for (i = 0; i < EOTF_LUT_SIZE; i++)
				b_map[i] = b[i];

		if (!is_meson_txlx_cpu() &&
		    !is_meson_gxlx_cpu() &&
		    !is_meson_txhd_cpu()) {
			for (i = 0; i < EOTF_LUT_SIZE; i++) {
				hdr_osd_reg.lut_val.r_map[i] = r_map[i];
				hdr_osd_reg.lut_val.g_map[i] = g_map[i];
				hdr_osd_reg.lut_val.b_map[i] = b_map[i];
			}
			hdr_osd_reg.viu_osd1_eotf_ctl &= 0xc7ffffff;
			if (on)
				hdr_osd_reg.viu_osd1_eotf_ctl |= 7 << 27;
			hdr_osd_reg.viu_osd1_eotf_ctl |= 1 << 31;
		} else {
			/* latch enable */
			WRITE_VPP_REG_BITS(VIU_OSD1_EOTF_CTL, 1, 26, 1);
			if (on) {
				VSYNC_WRITE_VPP_REG(addr_port, 0);
				for (i = 0; i < 16; i++) {
					val = r_map[i * 2] |
						(r_map[i * 2 + 1] << 16);
					VSYNC_WRITE_VPP_REG(data_port,
							    val);
				}
				val = r_map[EOTF_LUT_SIZE - 1]
					| (g_map[0] << 16);
				VSYNC_WRITE_VPP_REG(data_port,
						    val);
				for (i = 0; i < 16; i++) {
					val = g_map[i * 2 + 1]
					| (b_map[i * 2 + 2] << 16);
					VSYNC_WRITE_VPP_REG(data_port,
							    val);
				}
				for (i = 0; i < 16; i++) {
					val = b_map[i * 2]
					| (b_map[i * 2 + 1] << 16);
					VSYNC_WRITE_VPP_REG(data_port,
							    val);
				}
				val = b_map[EOTF_LUT_SIZE - 1];
				VSYNC_WRITE_VPP_REG(data_port, val);
			}

			WRITE_VPP_REG_BITS(VIU_OSD1_EOTF_CTL,
					   1, 31, 1);
			WRITE_VPP_REG_BITS(VIU_OSD1_EOTF_CTL,
					   (on | (on << 1) | (on << 2)),
					   27, 3);
		}
	} else if (lut_sel == VPP_LUT_EOTF) {
		/* enable latched */
		if (r && r_map)
			for (i = 0; i < EOTF_LUT_SIZE; i++)
				r_map[i] = r[i];
		if (g && g_map)
			for (i = 0; i < EOTF_LUT_SIZE; i++)
				g_map[i] = g[i];
		if (r && r_map)
			for (i = 0; i < EOTF_LUT_SIZE; i++)
				b_map[i] = b[i];
		/*txlx add eotf latch ctl bit 26*/
		if (is_meson_txlx_cpu() ||
		    is_meson_gxlx_cpu() ||
		    is_meson_txhd_cpu())
			WRITE_VPP_REG_BITS(ctrl_port, 1, 26, 1);

		if (on) {
			for (i = 0; i < 16; i++) {
				VSYNC_WRITE_VPP_REG(addr_port, i);
				val = r_map[i * 2]
					| (r_map[i * 2 + 1] << 16);
				VSYNC_WRITE_VPP_REG(data_port,
						    val);
			}
			VSYNC_WRITE_VPP_REG(addr_port, 16);
			val = r_map[EOTF_LUT_SIZE - 1]
				| (g_map[0] << 16);
			VSYNC_WRITE_VPP_REG(data_port,
					    val);
			for (i = 0; i < 16; i++) {
				VSYNC_WRITE_VPP_REG(addr_port, i + 17);
				val = g_map[i * 2 + 1]
					| (g_map[i * 2 + 2] << 16);
				VSYNC_WRITE_VPP_REG(data_port,
						    val);
			}
			for (i = 0; i < 16; i++) {
				VSYNC_WRITE_VPP_REG(addr_port, i + 33);
				val = b_map[i * 2]
					| (b_map[i * 2 + 1] << 16);
				VSYNC_WRITE_VPP_REG(data_port,
						    val);
			}
			VSYNC_WRITE_VPP_REG(addr_port, 49);
			VSYNC_WRITE_VPP_REG(data_port, b_map[EOTF_LUT_SIZE - 1]);
			WRITE_VPP_REG_BITS(ctrl_port, 7, 27, 3);
		} else {
			WRITE_VPP_REG_BITS(ctrl_port, 0, 27, 3);
		}
		WRITE_VPP_REG_BITS(ctrl_port, 1, 31, 1);
	} else if (lut_sel == VPP_LUT_OETF) {
		/* set bit to disable latched */
		WRITE_VPP_REG_BITS(VPP_XVYCC_MISC, 0, 18, 3);
		if (r && r_map)
			for (i = 0; i < VIDEO_OETF_LUT_SIZE; i++)
				r_map[i] = r[i];
		if (g && g_map)
			for (i = 0; i < VIDEO_OETF_LUT_SIZE; i++)
				g_map[i] = g[i];
		if (r && r_map)
			for (i = 0; i < VIDEO_OETF_LUT_SIZE; i++)
				b_map[i] = b[i];
		if (on) {
			VSYNC_WRITE_VPP_REG(ctrl_port, 0x0f);
			for (i = 0; i < VIDEO_OETF_LUT_SIZE; i++) {
				VSYNC_WRITE_VPP_REG(addr_port, i);
				VSYNC_WRITE_VPP_REG(data_port, r_map[i]);
			}
			for (i = 0; i < VIDEO_OETF_LUT_SIZE; i++) {
				VSYNC_WRITE_VPP_REG(addr_port + 2, i);
				VSYNC_WRITE_VPP_REG(data_port + 2, g_map[i]);
			}
			for (i = 0; i < VIDEO_OETF_LUT_SIZE; i++) {
				VSYNC_WRITE_VPP_REG(addr_port + 4, i);
				VSYNC_WRITE_VPP_REG(data_port + 4, b_map[i]);
			}
			VSYNC_WRITE_VPP_REG(ctrl_port, 0x7f);
			knee_lut_on = 1;
		} else {
			VSYNC_WRITE_VPP_REG(ctrl_port, 0x0f);
			knee_lut_on = 0;
		}
		cur_knee_factor = knee_factor;
	} else if (lut_sel == VPP_LUT_INV_EOTF) {
		/* set bit to enable latched */
		WRITE_VPP_REG_BITS(VPP_XVYCC_MISC, 0x7, 4, 3);
		if (on) {
			if (r[0] & INVLUT_HLG) {
				for (i = 0; i < EOTF_INV_LUT_SIZE; i++)
					invlut_y[i] = invlut_hlg_y[i];
				r[0] = 0;
			}
			VSYNC_WRITE_VPP_REG(addr_port, 0);
			for (i = 0; i < EOTF_INV_LUT_NEG2048_SIZE; i++) {
				VSYNC_WRITE_VPP_REG(addr_port, i);
				VSYNC_WRITE_VPP_REG(data_port, invlut_y_neg[i]);
			}
			for (i = 0; i < EOTF_INV_LUT_SIZE; i++) {
				VSYNC_WRITE_VPP_REG(addr_port,
						    EOTF_INV_LUT_NEG2048_SIZE + i);
				VSYNC_WRITE_VPP_REG(data_port, invlut_y[i]);
			}
			for (i = 0; i < EOTF_INV_LUT_1024_SIZE; i++) {
				VSYNC_WRITE_VPP_REG(addr_port,
						    EOTF_INV_LUT_NEG2048_SIZE +
						    EOTF_INV_LUT_SIZE + i);
				VSYNC_WRITE_VPP_REG(data_port, invlut_y_1024[i]);
			}
			WRITE_VPP_REG_BITS(ctrl_port, 1 << 2, 12, 3);
		} else {
			WRITE_VPP_REG_BITS(ctrl_port, 0, 12, 3);
		}
	}
	if (debug_csc && print_lut_mtx)
		print_vpp_lut(lut_sel, on);
}

/***************************** end of gxl hdr **************************/

/* extern unsigned int cm_size; */
/* extern unsigned int ve_size; */
/* extern unsigned int cm2_patch_flag; */
/* extern struct ve_dnlp_s am_ve_dnlp; */
/* extern struct ve_dnlp_table_s am_ve_new_dnlp; */
/* extern int cm_en; //0:disable;1:enable */
/* extern struct tcon_gamma_table_s video_gamma_table_r; */
/* extern struct tcon_gamma_table_s video_gamma_table_g; */
/* extern struct tcon_gamma_table_s video_gamma_table_b; */
/* extern struct tcon_gamma_table_s video_gamma_table_r_adj; */
/* extern struct tcon_gamma_table_s video_gamma_table_g_adj; */
/* extern struct tcon_gamma_table_s video_gamma_table_b_adj; */
/* extern struct tcon_rgb_ogo_s     video_rgb_ogo; */

/* csc mode:*/
/*	0: 601 limit to RGB*/
/*		vd1 for ycbcr to rgb*/
/*	1: 601 full to RGB*/
/*		vd1 for ycbcr to rgb*/
/*	2: 709 limit to RGB*/
/*		vd1 for ycbcr to rgb*/
/*	3: 709 full to RGB*/
/*		vd1 for ycbcr to rgb*/
/*	4: 2020 limit to RGB*/
/*		vd1 for ycbcr to rgb*/
/*		post for rgb to r'g'b'*/
/*	5: 2020(G:33c2,86c4 B:1d4c,0bb8 R:84d0,3e80) limit to RGB*/
/*		vd1 for ycbcr to rgb*/
/*		post for rgb to r'g'b'*/
/*	6: customer matrix calculation according to src and dest primary*/
/*		vd1 for ycbcr to rgb*/
/*		post for rgb to r'g'b' */
static void vpp_set_mtx_en_write(void)
{
	int reg_val;

	reg_val = READ_VPP_REG(VPP_MATRIX_CTRL);
	VSYNC_WRITE_VPP_REG(VPP_MATRIX_CTRL, (reg_val &
			  (~(POST_MTX_EN_MASK |
			  VD2_MTX_EN_MASK |
			  VD1_MTX_EN_MASK |
			  XVY_MTX_EN_MASK |
			  OSD1_MTX_EN_MASK))) |
			  mtx_en_mux);
}

static void vpp_set_mtx_en_read(void)
{
	int reg_value;

	reg_value = READ_VPP_REG(VPP_MATRIX_CTRL);
	mtx_en_mux = reg_value &
			(POST_MTX_EN_MASK |
			VD2_MTX_EN_MASK |
			VD1_MTX_EN_MASK |
			XVY_MTX_EN_MASK |
			OSD1_MTX_EN_MASK);
}

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static void vpp_set_matrix(enum vpp_matrix_sel_e vd1_or_vd2_or_post,
			   unsigned int on,
			   enum vpp_matrix_csc_e csc_mode,
			   struct matrix_s *m)
{
	int reg_value, val;

	if (force_csc_type != 0xff)
		csc_mode = force_csc_type;

	reg_value = READ_VPP_REG(VPP_MATRIX_CTRL);

	if (vd1_or_vd2_or_post == VPP_MATRIX_VD1) {
		/* vd1 matrix */
		reg_value = (reg_value & (~(7 << 8))) |
			(1 << 8);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_CTRL, reg_value);

		if (on)
			mtx_en_mux |= VD1_MTX_EN_MASK;
		else
			mtx_en_mux &= ~VD1_MTX_EN_MASK;
	} else if (vd1_or_vd2_or_post == VPP_MATRIX_VD2) {
		/* vd2 matrix */
		reg_value = (reg_value & (~(7 << 8))) |
			(2 << 8);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_CTRL, reg_value);

		if (on)
			mtx_en_mux |= VD2_MTX_EN_MASK;
		else
			mtx_en_mux &= ~VD2_MTX_EN_MASK;
	} else {
		/* post matrix */
		reg_value = (reg_value & (~(7 << 8))) |
			(0 << 8);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_CTRL, reg_value);

		if (on)
			mtx_en_mux |= POST_MTX_EN_MASK;
		else
			mtx_en_mux &= ~POST_MTX_EN_MASK;
	}
	if (!on)
		return;

	if (csc_mode == VPP_MATRIX_YUV601_RGB) {
		/* ycbcr limit, 601 to RGB */
		/*  -16  1.164   0       1.596   0*/
		/*    -128 1.164   -0.392  -0.813  0*/
		/*    -128 1.164   2.017   0       0 */
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF00_01, 0x04A80000);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF02_10, 0x066204A8);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF11_12, 0x1e701cbf);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF20_21, 0x04A80812);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF22, 0x00000000);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1, 0x00000000);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET2, 0x00000000);
		VSYNC_WRITE_VPP_REG_BITS(VPP_MATRIX_CLIP, 0, 5, 3);
	} else if (csc_mode == VPP_MATRIX_YUV601F_RGB) {
		/* ycbcr full range, 601F to RGB */
		/*  0    1    0           1.402    0*/
		/*   -128  1   -0.34414    -0.71414  0*/
		/*   -128  1    1.772       0        0 */
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF00_01, (0x400 << 16) | 0);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF02_10, (0x59c << 16) | 0x400);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF11_12,
				    (0x1ea0 << 16) | 0x1d24);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF20_21, (0x400 << 16) | 0x718);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF22, 0x0);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1, 0x0);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET2, 0x0);
		VSYNC_WRITE_VPP_REG_BITS(VPP_MATRIX_CLIP, 0, 5, 3);
	} else if (csc_mode == VPP_MATRIX_YUV709_RGB) {
		/* ycbcr limit range, 709 to RGB */
		/* -16      1.164  0      1.793  0 */
		/* -128     1.164 -0.213 -0.534  0 */
		/* -128     1.164  2.115  0      0 */
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF00_01, 0x04A80000);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF02_10, 0x072C04A8);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF11_12, 0x1F261DDD);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF20_21, 0x04A80876);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF22, 0x0);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1, 0x0);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET2, 0x0);

		VSYNC_WRITE_VPP_REG_BITS(VPP_MATRIX_CLIP, 0, 5, 3);
	} else if (csc_mode == VPP_MATRIX_YUV709F_RGB) {
		/* ycbcr full range, 709F to RGB */
		/*  0    1      0       1.575   0*/
		/*  -128  1     -0.187  -0.468   0*/
		/*  -128  1      1.856   0       0 */
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF00_01, 0x04000000);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF02_10, 0x064D0400);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF11_12, 0x1F411E21);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF20_21, 0x0400076D);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF22, 0x0);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1, 0x0);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET2, 0x0);
		VSYNC_WRITE_VPP_REG_BITS(VPP_MATRIX_CLIP, 0, 5, 3);
	} else if (csc_mode == VPP_MATRIX_NULL) {
		/* bypass matrix */
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF00_01, 0x04000000);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF02_10, 0);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF11_12, 0x04000000);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF20_21, 0x00000000);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF22, 0x00000400);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1, 0x0);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET2, 0x0);
		VSYNC_WRITE_VPP_REG_BITS(VPP_MATRIX_CLIP, 0, 5, 3);
	} else if (csc_mode >= VPP_MATRIX_BT2020YUV_BT2020RGB) {
		if (vd1_or_vd2_or_post == VPP_MATRIX_VD1) {
			/* bt2020 limit to bt2020 RGB  */
			VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF00_01, 0x4ad0000);
			VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF02_10, 0x6e50492);
			VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF11_12, 0x1f3f1d63);
			VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF20_21, 0x492089a);
			VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF22, 0x0);
			VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1, 0x0);
			VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET2, 0x0);
			VSYNC_WRITE_VPP_REG_BITS(VPP_MATRIX_CLIP, 0, 5, 3);
		}
		if (vd1_or_vd2_or_post == VPP_MATRIX_POST) {
			if (csc_mode == VPP_MATRIX_BT2020YUV_BT2020RGB) {
				/* 2020 RGB to R'G'B */
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET0_1,
						    0x0);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET2, 0x0);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF00_01,
						    0xd491b4d);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF02_10,
						    0x1f6b1f01);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF11_12,
						    0x9101fef);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF20_21,
						    0x1fdb1f32);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF22, 0x108f3);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1, 0x0);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET2, 0x0);
				VSYNC_WRITE_VPP_REG_BITS(VPP_MATRIX_CLIP,
							 1, 5, 3);
			} else if (csc_mode == VPP_MATRIX_BT2020RGB_CUSRGB) {
				/* customer matrix 2020 RGB to R'G'B' */
				val =  (m->pre_offset[0] << 16)
					| (m->pre_offset[1] & 0xffff);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET0_1,
						    val);
				val = m->pre_offset[2] & 0xffff;
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET2,
						    val);
				val = (m->matrix[0][0] << 16)
					| (m->matrix[0][1] & 0xffff);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF00_01,
						    val);
				val = (m->matrix[0][2] << 16)
					| (m->matrix[1][0] & 0xffff);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF02_10,
						    val);
				val = (m->matrix[1][1] << 16)
					| (m->matrix[1][2] & 0xffff);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF11_12,
						    val);
				val = (m->matrix[2][0] << 16)
					| (m->matrix[2][1] & 0xffff);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF20_21,
						    val);
				val = (m->right_shift << 16)
					| (m->matrix[2][2] & 0xffff);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF22,
						    val);
				val = (m->offset[0] << 16)
					| (m->offset[1] & 0xffff);
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1,
						    val);
				val = m->offset[2] & 0xffff;
				VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET2,
						    val);
				VSYNC_WRITE_VPP_REG_BITS(VPP_MATRIX_CLIP,
							 m->right_shift,
							 5, 3);
			}
		}
	}
}
#endif

/* matrix between xvycclut and linebuffer*/
static uint cur_csc_mode = 0xff;

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static void vpp_set_matrix3(unsigned int on,
			    enum vpp_matrix_csc_e csc_mode)
{
	int reg_value;

	reg_value = READ_VPP_REG(VPP_MATRIX_CTRL);

	if (on)
		mtx_en_mux |= XVY_MTX_EN_MASK;
	else
		mtx_en_mux &= ~XVY_MTX_EN_MASK;

	if (!on)
		return;

	if (cur_csc_mode == csc_mode)
		return;

	reg_value = READ_VPP_REG(VPP_MATRIX_CTRL);

	VSYNC_WRITE_VPP_REG(VPP_MATRIX_CTRL,
			    (reg_value & (~(7 << 8))) | (3 << 8));

	if (csc_mode == VPP_MATRIX_RGB_YUV709F) {
		/* RGB -> 709F*/
		/*WRITE_VPP_REG(VPP_MATRIX_CTRL, 0x7360);*/

		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF00_01, 0xda02dc);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF02_10, 0x4a1f8a);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF11_12, 0x1e760200);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF20_21, 0x2001e2f);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF22, 0x1fd1);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1, 0x200);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET2, 0x200);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET0_1, 0x0);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET2, 0x0);
	} else if (csc_mode == VPP_MATRIX_RGB_YUV709) {
		/* RGB -> 709 limit */
		/*WRITE_VPP_REG(VPP_MATRIX_CTRL, 0x7360);*/

		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF00_01, 0x00bb0275);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF02_10, 0x003f1f99);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF11_12, 0x1ea601c2);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF20_21, 0x01c21e67);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_COEF22, 0x00001fd7);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET0_1, 0x00400200);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_OFFSET2, 0x00000200);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET0_1, 0x0);
		VSYNC_WRITE_VPP_REG(VPP_MATRIX_PRE_OFFSET2, 0x0);
	}
	cur_csc_mode = csc_mode;
}
#endif

static uint cur_signal_type[VD_PATH_MAX] = {
	0xffffffff,
	0xffffffff
};
module_param_array(cur_signal_type, uint, &vd_path_max, 0664);
MODULE_PARM_DESC(cur_signal_type, "\n cur_signal_type\n");

static struct vframe_master_display_colour_s
cur_master_display_colour[VD_PATH_MAX] = {
	{
		0,
		{
			{0, 0},
			{0, 0},
			{0, 0},
		},
		{0, 0},
		{0, 0}
	},
	{
		0,
		{
			{0, 0},
			{0, 0},
			{0, 0},
		},
		{0, 0},
		{0, 0}
	}
};

unsigned int pre_vd1_mtx_sel[VD_PATH_MAX] = {
	VPP_MATRIX_NULL,
	VPP_MATRIX_NULL,
};
module_param_array(pre_vd1_mtx_sel, uint, &vd_path_max, 0664);
MODULE_PARM_DESC(pre_vd1_mtx_sel, "\n pre_vd1_mtx_sel\n");
unsigned int vd1_mtx_sel = VPP_MATRIX_NULL;
static int src_timing_outputmode_changed(struct vframe_s *vf,
					 struct vinfo_s *vinfo,
					 enum vd_path_e vd_path)
{
	unsigned int width, height;

	if (vinfo_lcd_support())
		return 0;

	width = (vf->type & VIDTYPE_COMPRESS) ?
		vf->compWidth : vf->width;
	height = (vf->type & VIDTYPE_COMPRESS) ?
		vf->compHeight : vf->height;

	if (height < 720 && vinfo->height < 720)
		vd1_mtx_sel = VPP_MATRIX_NULL;
	else if ((height < 720) && (vinfo->height >= 720))
		vd1_mtx_sel = VPP_MATRIX_YUV601L_YUV709L;
	else if ((height >= 720) && (vinfo->height < 720))
		vd1_mtx_sel = VPP_MATRIX_YUV709L_YUV601L;
	else if ((height >= 720) && (vinfo->height >= 720))
		vd1_mtx_sel = VPP_MATRIX_NULL;
	else
		vd1_mtx_sel = VPP_MATRIX_NULL;

	if (pre_vd1_mtx_sel[vd_path] != vd1_mtx_sel) {
		pre_vd1_mtx_sel[vd_path] = vd1_mtx_sel;
		return 1;
	}

	return 0;
}

static void print_primaries_info(struct vframe_master_display_colour_s *p)
{
	int i, j;

	if (!(p->present_flag & 1)) {
		pr_csc(1, "\tmaster display color not available");
		return;
	}
	if (p->present_flag & 0x20)
		pr_csc(1, "\tcolor primaries in GBR\n");
	else if (p->present_flag & 0x10)
		pr_csc(1, "\tcolor primaries in RGB\n");
	else
		pr_csc(1, "\tcolor primaries not available use 2020\n");
	for (i = 0; i < 3; i++)
		for (j = 0; j < 2; j++)
			pr_csc(1, "\t\tprimaries[%1d][%1d] = %04x\n",
			       i, j,
			       p->primaries[i][j]);
	pr_csc(1, "\t\twhite_point = (%04x, %04x)\n",
	       p->white_point[0], p->white_point[1]);
	pr_csc(1, "\t\tmax, min luminance = %08x, %08x\n",
	       p->luminance[0], p->luminance[1]);
}

static uint cur_vd_signal_type = 0xffffffff;
void get_cur_vd_signal_type(enum vd_path_e vd_path)
{
	cur_vd_signal_type = cur_signal_type[vd_path];
}
#endif

int get_primaries_type(struct vframe_master_display_colour_s *p_mdc)
{
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	if (!p_mdc->present_flag)
		return 0;

	if (p_mdc->primaries[0][1] > p_mdc->primaries[1][1] &&
	    p_mdc->primaries[0][1] > p_mdc->primaries[2][1] &&
	    p_mdc->primaries[2][0] > p_mdc->primaries[0][0] &&
	    p_mdc->primaries[2][0] > p_mdc->primaries[1][0]) {
		/* reasonable g,b,r */
		return 2;
	} else if (p_mdc->primaries[0][0] > p_mdc->primaries[1][0] &&
		   p_mdc->primaries[0][0] > p_mdc->primaries[2][0] &&
		   p_mdc->primaries[1][1] > p_mdc->primaries[0][1] &&
		   p_mdc->primaries[1][1] > p_mdc->primaries[2][1]) {
		/* reasonable r,g,b */
		return 1;
	}
	/* source not usable, use standard bt2020 */
#endif
	return 0;
}
EXPORT_SYMBOL(get_primaries_type);

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
int hdr10_primaries_changed(struct vframe_master_display_colour_s *p_mdc,
			    struct vframe_master_display_colour_s *p_hdr10_param)
{
	struct vframe_content_light_level_s *p_cll =
		&p_mdc->content_light_level;
	struct vframe_master_display_colour_s *p = p_hdr10_param;
	u32 (*prim_mdc)[2] = p_mdc->primaries;
	u32 (*prim_p)[2] = p->primaries;
	u8 flag = 0;
	u32 max_lum = 1000 * 10000;
	u32 min_lum = 50;
	int primaries_type = 0;
	int i, j;

	primaries_type = get_primaries_type(p_mdc);
	if (primaries_type == 0) {
		if ((p->luminance[0] != max_lum && (p->luminance[0] != max_lum / 10000)) ||
		    p->luminance[1] != min_lum) {
			flag |= 1;
			p->luminance[0] = max_lum;
			p->luminance[1] = min_lum;
		}
		for (i = 0; i < 2; i++) {
			if (p->white_point[i] != bt2020_white_point[i]) {
				p->white_point[i] = bt2020_white_point[i];
				flag |= 4;
			}
		}
		for (i = 0; i < 3; i++) {
			/* GBR -> GBR */
			for (j = 0; j < 2; j++) {
				if (prim_p[i][j] != bt2020_primaries[i][j]) {
					prim_p[i][j] = bt2020_primaries[i][j];
					flag |= 2;
				}
			}
		}
		p_hdr10_param->present_flag = 1;
	} else {
		for (i = 0; i < 2; i++) {
			if (p->luminance[i] != p_mdc->luminance[i]) {
				if (i != 0 ||
				    (p->luminance[0] != p_mdc->luminance[0] / 10000))
					flag |= 1;
				p->luminance[i] = p_mdc->luminance[i];
			}
			if (p->white_point[i]
			    != p_mdc->white_point[i]) {
				flag |= 4;
				p->white_point[i] = p_mdc->white_point[i];
			}
		}
		if (primaries_type == 1) {
			/* RGB -> GBR */
			for (i = 0; i < 3; i++) {
				for (j = 0; j < 2; j++) {
					if (prim_p[i][j] != prim_mdc[(i + 2) % 3][j]) {
						prim_p[i][j] = prim_mdc[(i + 2) % 3][j];
						flag |= 2;
					}
				}
			}
			p->present_flag = 0x21;
		} else if (primaries_type == 2) {
			/* GBR -> GBR */
			for (i = 0; i < 3; i++) {
				for (j = 0; j < 2; j++) {
					if (prim_p[i][j] != prim_mdc[i][j]) {
						prim_p[i][j] = prim_mdc[i][j];
						flag |= 2;
					}
				}
			}
			p->present_flag = 0x11;
		}
	}

	if (p_cll->present_flag) {
		if (p->content_light_level.max_content != p_cll->max_content ||
		    p->content_light_level.max_pic_average != p_cll->max_pic_average)
			flag |= 8;
		if (flag & 8) {
			p->content_light_level.max_content =
				p_cll->max_content;
			p->content_light_level.max_pic_average =
				p_cll->max_pic_average;
		}
		p->content_light_level.present_flag = 1;
	} else {
		if (p->content_light_level.max_content != 0 ||
		    p->content_light_level.max_pic_average != 0) {
			p->content_light_level.max_content = 0;
			p->content_light_level.max_pic_average = 0;
		}
		if (p->content_light_level.present_flag)
			flag |= 8;
		p->content_light_level.present_flag = 0;
	}
	return flag;
}

uint32_t sink_dv_support(const struct vinfo_s *vinfo)
{
	if (!vinfo || !vinfo->name || !vinfo->vout_device ||
	    !vinfo->vout_device->dv_info)
		return 0;
	if (vinfo->vout_device->dv_info->ieeeoui != 0x00d046)
		return 0;
	if (vinfo->vout_device->dv_info->block_flag != CORRECT)
		return 0;
	/* for sink not support 60 dovi */
	if (strstr(vinfo->name, "2160p60hz") ||
	    strstr(vinfo->name, "2160p50hz")) {
		if (!vinfo->vout_device->dv_info->sup_2160p60hz)
			return 0;
	}
	/* for sink not support 120hz*/
	if (strstr(vinfo->name, "120hz") ||
	    strstr(vinfo->name, "100hz")) {
		if (!vinfo->vout_device->dv_info->sup_1080p120hz)
			return 0;
	}
	/* currently all sink not support 4k100/120 and 8k dv */
	if (strstr(vinfo->name, "2160p100hz") ||
		strstr(vinfo->name, "2160p120hz") ||
		strstr(vinfo->name, "3840x2160p100hz") ||
		strstr(vinfo->name, "3840x2160p120hz") ||
		strstr(vinfo->name, "7680x4320p")) {
		/*in the future, some new flag in vsvdb will be used to judge dv cap*/
		return 0;
	}
	/* for interlace output */
	if (vinfo->height != vinfo->field_height)
		return 0;
	if (vinfo->vout_device->dv_info->ver == 2) {
		if (vinfo->vout_device->dv_info->Interface <= 1)
			return 2; /* LL only */
		else
			return 3; /* STD & LL */
	} else if (vinfo->vout_device->dv_info->low_latency) {
		return 3; /* STD & LL */
	}
	return 1; /* STD only */
}
EXPORT_SYMBOL(sink_dv_support);
#endif

uint32_t sink_hdr_support(const struct vinfo_s *vinfo)
{
	u32 hdr_cap = 0;
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	u32 dv_cap = 0;
	bool u_force = false;

	/* hdr_cap from vinfo for Android U force mode*/
	if (get_amdv_policy() == AMDV_FORCE_OUTPUT_MODE ||
		hdr_policy == 4)
		u_force = true;

	/* when policy == follow sink(0) or force output (2) */
	/* use force_output */
	if (get_force_output() != 0 &&
	    get_hdr_policy() != 1 && !u_force) {
		switch (get_force_output()) {
		case BT709:
		case BT_BYPASS:
			break;
		case BT2020:
			hdr_cap |= BT2020_SUPPORT;
			break;
		case BT2020_PQ:
			hdr_cap |= HDR_SUPPORT;
			break;
		case BT2020_PQ_DYNAMIC:
			hdr_cap |= HDRP_SUPPORT;
			break;
		case BT2020_HLG:
			hdr_cap |= HLG_SUPPORT;
			break;
		case BT2100_IPT:
			hdr_cap |= DV_SUPPORT;
		default:
			break;
		}
	} else if (vinfo) {
		if (vinfo->hdr_info.hdr_support & HDR_SUPPORT)
			hdr_cap |= HDR_SUPPORT;
		if (vinfo->hdr_info.hdr_support & HLG_SUPPORT)
			hdr_cap |= HLG_SUPPORT;
		if (vinfo->hdr_info.hdr10plus_info.ieeeoui == HDR_PLUS_IEEE_OUI &&
		    vinfo->hdr_info.hdr10plus_info.application_version == 1)
			hdr_cap |= HDRP_SUPPORT;
		if (vinfo->hdr_info.cuva_info.ieeeoui ==
			CUVA_IEEEOUI)
			hdr_cap |= CUVA_SUPPORT;
		if (vinfo->hdr_info.colorimetry_support & 0xe0)
			hdr_cap |= BT2020_SUPPORT;
		dv_cap = sink_dv_support(vinfo);
		if (dv_cap)
			hdr_cap |= (dv_cap << DV_SUPPORT_SHF) & DV_SUPPORT;
	}
	if (vinfo)
		pr_csc(256, "%s: support %d %d %d,mode=%d, hdr_cap 0x%x\n",
			__func__,
			vinfo->hdr_info.hdr_support,
			vinfo->hdr_info.hdr10plus_info.ieeeoui,
			vinfo->hdr_info.hdr10plus_info.application_version,
			vinfo->mode,
			hdr_cap);
#endif
	return hdr_cap;
}
EXPORT_SYMBOL(sink_hdr_support);

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
int signal_type_changed(struct vframe_s *vf,
			struct vinfo_s *vinfo, enum vd_path_e vd_path,
			enum vpp_index_e vpp_index)
{
	u32 signal_type = 0;
	u32 default_signal_type;
	int change_flag = 0;
	int i, j;
	struct vframe_master_display_colour_s *p_cur = NULL;
	struct vframe_master_display_colour_s *p_new = NULL;
	struct vframe_master_display_colour_s cus;
	int ret;
	u32 limit_full = 0;

	if (!vf)
		return 0;
	if (vf->type & VIDTYPE_MVC) {
		if (cur_mvc_type[vd_path] != (vf->type & VIDTYPE_MVC)) {
			change_flag |= SIG_SRC_CHG;
			cur_mvc_type[vd_path] = vf->type & VIDTYPE_MVC;
			pr_csc(1, "VIDTYPE MVC changed.\n");
			/*return change_flag;*/
		}
	} else {
		cur_mvc_type[vd_path] = 0;
	}
	limit_full = (vf->signal_type >> 25) & 0x01;
	if (vf->source_type == VFRAME_SOURCE_TYPE_TUNER ||
	    vf->source_type == VFRAME_SOURCE_TYPE_CVBS ||
	    vf->source_type == VFRAME_SOURCE_TYPE_COMP ||
	    vf->source_type == VFRAME_SOURCE_TYPE_HDMI) {
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
		if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) {
			default_signal_type =
				/* default 709 full */
				  (1 << 29)	/* video available */
				| (5 << 26)	/* unspecified */
				| (1 << 25)	/* limit */
				| (1 << 24)	/* color available */
				| (1 << 16)	/* bt709 */
				| (1 << 8)	/* bt709 */
				| (1 << 0);	/* bt709 */
		} else {
#else
		{
#endif
			default_signal_type =
				/* default 709 limit */
				  (1 << 29)	/* video available */
				| (5 << 26)	/* unspecified */
				| (limit_full << 25)	/* limit */
				| (1 << 24)	/* color available */
				| (1 << 16)	/* bt709 */
				| (1 << 8)	/* bt709 */
				| (1 << 0);	/* bt709 */
		}
	} else { /* for local play */
		if (vf->height >= 720)
			default_signal_type =
				/* HD default 709 limit */
				  (1 << 29)	/* video available */
				| (5 << 26)	/* unspecified */
				| (0 << 25)	/* limit */
				| (1 << 24)	/* color available */
				| (1 << 16)	/* bt709 */
				| (1 << 8)	/* bt709 */
				| (1 << 0);	/* bt709 */
		else
			default_signal_type =
				/* SD default 601 limited */
				  (1 << 29)	/* video available */
				| (5 << 26)	/* unspecified */
				| (0 << 25)	/* limited */
				| (1 << 24)	/* color available */
				| (3 << 16)	/* bt601 */
				| (3 << 8)	/* bt601 */
				| (3 << 0);	/* bt601 */
	}
	if (vf->signal_type & (1 << 29))
		signal_type = vf->signal_type;
	else
		signal_type = default_signal_type;

	/* RGB / YUV vdin input handling  prepare extra op code or info */
	hdr_ex = 0;
	if (vf->type & VIDTYPE_RGB_444)
		hdr_ex |= RGB_VDIN;

	if (limit_full)
		hdr_ex |= FULL_VDIN;
	/* RGB / YUV input handling */

	p_new = &vf->prop.master_display_colour;
	p_cur = &cur_master_display_colour[vd_path];
	/* customer overwrite */
	if (customer_master_display_en &&
	    (p_new->present_flag & 0x80000000) == 0) {
		signal_type = (1 << 29)	/* video available */
				| (5 << 26)	/* unspecified */
				| (0 << 25)	/* limit */
				| (1 << 24)	/* color available */
				| (9 << 16)	/* 2020 */
				| (16 << 8)	/* 2084 */
				| (9 << 0);	/* 2020 */
		for (i = 0; i < 3; i++)
			for (j = 0; j < 2; j++)
				cus.primaries[i][j] =
				customer_master_display_param[i * 2 + j];
		for (i = 0; i < 2; i++)
			cus.white_point[i] =
				customer_master_display_param[6 + i];
		for (i = 0; i < 2; i++)
			cus.luminance[i] =
				customer_master_display_param[8 + i];
		cus.present_flag = 1;
		p_new = &cus;
	}

	/* For txhd, must skip HDR process */
	if (is_meson_txhd_cpu()) {
		if (((signal_type & 0xff) != 1)	&&
		    ((signal_type & 0xff) != 3)) {
			signal_type &= 0xffffff00;
			signal_type |= 0x00000001;
		}
		if (((signal_type & 0xff00) >> 8 != 1) &&
		    ((signal_type & 0xff00) >> 8 != 3)) {
			signal_type &= 0xffff00ff;
			signal_type |= 0x00000100;
		}
		if (((signal_type & 0xff0000) >> 16 != 1) &&
		    ((signal_type & 0xff0000) >> 16 != 3)) {
			signal_type &= 0xff00ffff;
			signal_type |= 0x00010000;
		}
		/*pr_err("Signal type changed from 0x%x to 0x%x.\n",*/
		/*vf->signal_type, signal_type);*/
	}

	/* only check primary for new = bt2020 or  cur = bt2020 */
	if (p_new && p_cur &&
	    (((signal_type >> 16) & 0xff) == 9 || p_cur->present_flag)) {
		ret = hdr10_primaries_changed(p_new, p_cur);
		if (ret)
			change_flag |= SIG_PRI_INFO;
	}
	if (change_flag & SIG_PRI_INFO) {
		pr_csc(1, "vd%d Master_display_colour changed %x flag %x.\n",
		       vd_path + 1, ret,
		       p_cur->present_flag);
		print_primaries_info(p_cur);
	}
	if (signal_type != cur_signal_type[vd_path]) {
		pr_csc(1, "vd%d Signal type changed from 0x%x to 0x%x.\n",
		       vd_path + 1,
		       cur_signal_type[vd_path],
		       signal_type);
		change_flag |= SIG_CS_CHG;
		cur_signal_type[vd_path] = signal_type;
	}
	if (pre_src_type[vd_path] != vf->source_type) {
		pr_csc(1, "vd%d Signal source changed from 0x%x to 0x%x.\n",
		       vd_path + 1, pre_src_type[vd_path], vf->source_type);
		change_flag |= SIG_SRC_CHG;
		pre_src_type[vd_path] = vf->source_type;
	}
	if (cur_knee_factor != knee_factor) {
		pr_csc(1, "vd%d Knee factor changed.\n", vd_path + 1);
		change_flag |= SIG_KNEE_FACTOR;
		cur_knee_factor = knee_factor;
	}
	if (!is_amdv_on() || vd_path != VD1_PATH) {
		if (cur_hdr_process_mode[vd_path]
		    != hdr_process_mode[vd_path]) {
			pr_csc(1, "vd%d HDR mode changed %d %d.\n", vd_path + 1,
			       cur_hdr_process_mode[vd_path],
			       hdr_process_mode[vd_path]);
			change_flag |= SIG_HDR_MODE;
		}
		if (cur_hlg_process_mode[vd_path]
		    != hlg_process_mode[vd_path]) {
			pr_csc(1, "vd%d HLG mode changed %d %d.\n", vd_path + 1,
			       cur_hlg_process_mode[vd_path],
			       hlg_process_mode[vd_path]);
			change_flag |= SIG_HLG_MODE;
		}
		if (cur_sdr_process_mode[vd_path]
		    != sdr_process_mode[vd_path]) {
			pr_csc(1, "vd%d SDR mode changed %d %d.\n", vd_path + 1,
			       cur_sdr_process_mode[vd_path],
			       sdr_process_mode[vd_path]);
			change_flag |= SIG_HDR_MODE;
		}
		if (cur_hdr10_plus_process_mode[vd_path]
		    != hdr10_plus_process_mode[vd_path]) {
			pr_csc(1, "vd%d HDR10+ mode changed %d %d.\n",
			       vd_path + 1,
			       cur_hdr10_plus_process_mode[vd_path],
			       hdr10_plus_process_mode[vd_path]);
			change_flag |= SIG_HDR10_PLUS_MODE;
		}
		if (cur_cuva_hdr_process_mode[vd_path]
		    != cuva_hdr_process_mode[vd_path]) {
			pr_csc(1, "vd%d cuva hdr mode changed %d %d.\n",
				vd_path + 1,
				cur_cuva_hdr_process_mode[vd_path],
				cuva_hdr_process_mode[vd_path]);
			change_flag |= SIG_CUVA_HDR_MODE;
		}
		if (cur_cuva_hlg_process_mode[vd_path]
		    != cuva_hlg_process_mode[vd_path]) {
			pr_csc(1, "vd%d cuva hlg mode changed %d %d.\n",
				vd_path + 1,
				cur_cuva_hlg_process_mode[vd_path],
				cuva_hlg_process_mode[vd_path]);
			change_flag |= SIG_CUVA_HLG_MODE;
		}
	}

	if (cur_hdr_support[vpp_index]
		!= (vinfo->hdr_info.hdr_support & 0x4)) {
		pr_csc(1, "Tx HDR support changed.\n");
		change_flag |= SIG_HDR_SUPPORT;
		cur_hdr_support[vpp_index] =
			vinfo->hdr_info.hdr_support & 0x4;
	}
	if (cur_colorimetry_support[vpp_index] != vinfo->hdr_info.colorimetry_support) {
		pr_csc(1, "Tx colorimetry support changed.\n");
		change_flag |= SIG_COLORIMETRY_SUPPORT;
		cur_colorimetry_support[vpp_index] = vinfo->hdr_info.colorimetry_support;
	}
	if (cur_color_fmt[vpp_index] != vinfo->viu_color_fmt) {
		pr_csc(1, "color format changed.\n");
		change_flag |= SIG_OP_CHG;
		cur_color_fmt[vpp_index] = vinfo->viu_color_fmt;
	}
	if (cur_hlg_support[vpp_index] != (vinfo->hdr_info.hdr_support & 0x8)) {
		pr_csc(1, "Tx HLG support changed.\n");
		change_flag |= SIG_HLG_SUPPORT;
		cur_hlg_support[vpp_index] = vinfo->hdr_info.hdr_support & 0x8;
	}

	if (cur_eye_protect_mode != wb_val[0] ||
	    cur_eye_protect_mode == 1) {
		pr_csc(1, "eye protect mode changed.\n");
		change_flag |= SIG_WB_CHG;
	}

	if (src_timing_outputmode_changed(vf, vinfo, vd_path)) {
		pr_csc(1, "vd%d source timing output mode changed.\n",
		       vd_path + 1);
		change_flag |= SIG_SRC_OUTPUT_CHG;
	}

	if (vecm_latch_flag & FLAG_HDR_OOTF_LATCH) {
		change_flag |= SIG_HDR_OOTF_CHG;
		vecm_latch_flag &= ~FLAG_HDR_OOTF_LATCH;
		pr_csc(1, "ootf curve changed.\n");
	}

	if (vecm_latch_flag & FLAG_COLORPRI_LATCH) {
		change_flag |= SIG_PRI_INFO;
		vecm_latch_flag &= ~FLAG_COLORPRI_LATCH;
	}

	if (vf->type & VIDTYPE_RGB_444) {
		if (cur_rgb_type[vd_path] !=
		   (vf->type & VIDTYPE_RGB_444)) {
			change_flag |= SIG_SRC_CHG;
			rgb_type_proc[vd_path] = FORCE_RGB_PROCESS;
			cur_rgb_type[vd_path] = vf->type & VIDTYPE_RGB_444;
			pr_csc(1, "VIDTYPE RGB changed. vf->type = 0x%x\n",
			       vf->type);
		}
	} else {
		if (cur_rgb_type[vd_path] != 0) {
			change_flag |= SIG_SRC_CHG;
			rgb_type_proc[vd_path] = FORCE_RGB_PROCESS;
			cur_rgb_type[vd_path] = 0;
			pr_csc(1, "VIDTYPE YUV changed. vf->type = 0x%x\n",
			       vf->type);
		}
	}

	if (rgb_type_proc[vd_path] == FORCE_RGB_PROCESS)
		change_flag |= SIG_SRC_CHG;
	if (gamut_conv_enable != pre_gamut_conv_en) {
		change_flag |= SIG_CS_CHG;
		pre_gamut_conv_en = gamut_conv_enable;
		pr_csc(
			1, "gamut convert changed = 0x%x\n",
			gamut_conv_enable);
	}

	return change_flag;
}

#define signal_cuva ((cur_vd_signal_type >> 31) & 1)
#define signal_format ((cur_vd_signal_type >> 26) & 7)
#define signal_range ((cur_vd_signal_type >> 25) & 1)
#define signal_color_primaries ((cur_vd_signal_type >> 16) & 0xff)
#define signal_transfer_characteristic ((cur_vd_signal_type >> 8) & 0xff)
enum vpp_matrix_csc_e get_csc_type(void)
{
	enum vpp_matrix_csc_e csc_type = VPP_MATRIX_NULL;

	if (signal_color_primaries == 1 &&
	    signal_transfer_characteristic < 14) {
		if (signal_range == 0)
			csc_type = VPP_MATRIX_YUV709_RGB;
		else
			csc_type = VPP_MATRIX_YUV709F_RGB;
	} else if ((signal_color_primaries == 3) &&
		   (signal_transfer_characteristic < 14)) {
		if (signal_range == 0)
			csc_type = VPP_MATRIX_YUV601_RGB;
		else
			csc_type = VPP_MATRIX_YUV601F_RGB;
	} else if ((signal_color_primaries == 9) ||
		   (signal_transfer_characteristic >= 14)) {
		if (signal_transfer_characteristic == 16) {
			if (signal_cuva) {
				csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB_CUVA;
			/* smpte st-2084 */
			} else {
				if (signal_color_primaries != 9)
					pr_csc(1, "\tWARNING: non-standard HDR!!!\n");
				csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB;
			}
		} else if (signal_transfer_characteristic == 14 ||
				signal_transfer_characteristic == 18) {
			/* bt2020-10 */
			if (signal_cuva)
				csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB_CUVA;
			else
				csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB;
		} else if (signal_transfer_characteristic == 15) {
			/* bt2020-12 */
			pr_csc(1, "\tWARNING: bt2020-12 HDR!!!\n");
			if (signal_range == 0)
				csc_type = VPP_MATRIX_YUV709_RGB;
			else
				csc_type = VPP_MATRIX_YUV709F_RGB;
		} else if (signal_transfer_characteristic == 0x30) {
			if (signal_color_primaries == 9) {
				/* pr_csc(1, "\tHDR10+!!!\n"); */
				csc_type =
					VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC;
			} else {
				pr_csc(1,
				       "\tWARNING: non-standard HDR10+!!!\n");
				csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB;
			}
		} else {
			/* unknown transfer characteristic */
			pr_csc(1, "\tWARNING: unknown HDR!!!\n");
			if (signal_range == 0)
				csc_type = VPP_MATRIX_YUV709_RGB;
			else
				csc_type = VPP_MATRIX_YUV709F_RGB;
		}
	} else {
		if (signal_format == 0)
			pr_csc(1, "\tWARNING: unknown colour space!!!\n");
		if (signal_range == 0)
			csc_type = VPP_MATRIX_YUV601_RGB;
		else
			csc_type = VPP_MATRIX_YUV601F_RGB;
	}
	return csc_type;
}

/*hdr10: return 0;  hlg: return 1*/
#define HLG_FLAG 0x1
static int get_hdr_type(void)
{
	int change_flag = 0;

	if (signal_transfer_characteristic == 18 ||
	    signal_transfer_characteristic == 14)
		change_flag |= HLG_FLAG;

	return change_flag;
}

enum hdr_type_e get_hdr_source_type(void)
{
	enum hdr_type_e hdr_type;

	if ((signal_transfer_characteristic == 14 ||
	     signal_transfer_characteristic == 18) &&
	    signal_color_primaries == 9)
		hdr_source_type =
			signal_cuva ? CUVA_HLG_SOURCE : HLG_SOURCE;
	else if (signal_transfer_characteristic == 0x30 &&
		 signal_color_primaries == 9)
		hdr_source_type = HDR10PLUS_SOURCE;
	else if (signal_transfer_characteristic == 16)
		hdr_source_type =
			signal_cuva ? CUVA_HDR_SOURCE : HDR10_SOURCE;
	else
		hdr_source_type = SDR_SOURCE;

	hdr_type = hdr_source_type;

	return hdr_type;
}

enum color_primary_e get_color_primary(void)
{
	enum color_primary_e color_pri;

	if (signal_color_primaries == 1)
		color_pri = VPP_COLOR_PRI_BT709;
	else if (signal_color_primaries == 3)
		color_pri = VPP_COLOR_PRI_BT601;
	else if (signal_color_primaries == 9)
		color_pri = VPP_COLOR_PRI_BT2020;
	else
		color_pri = VPP_COLOR_PRI_NULL;
	return color_pri;
}

static void cal_out_curve(uint panel_luma)
{
	int index;

	if (panel_luma == 0)
		return;

	if (panel_luma <= 500) {
		if (panel_luma < 250)
			panel_luma = 250;
		index = (panel_luma - 250) / 20;
	} else {
		if (panel_luma > 1000)
			panel_luma = 1000;
		index = ((500 - 260) / 20) + (panel_luma - 500) / 100;
	}
	memcpy(eotf_33_2084_mapping,
	       eotf_33_2084_table[index], sizeof(int) * EOTF_LUT_SIZE);
	memcpy(oetf_289_gamma22_mapping,
	       oetf_289_gamma22_table[index],
	       sizeof(int) * VIDEO_OETF_LUT_SIZE);
}

static void mtx_dot_mul(s64 (*a)[3], s64 (*b)[3],
			s64 (*out)[3], s32 norm)
{
	int i, j;
	s64 tmp;

	for (i = 0; i < 3; i++)
		for (j = 0; j < 3; j++) {
			tmp = a[i][j] * b[i][j] + (norm >> 1);
			out[i][j] = div64_s64(tmp, norm);
		}
}

static void mtx_mul(s64 (*a)[3], s64 *b, s64 *out, s32 norm)
{
	int j, k;
	s64 tmp;

	for (j = 0; j < 3; j++) {
		out[j] = 0;
		for (k = 0; k < 3; k++)
			out[j] += a[k][j] * b[k];
		tmp = out[j] + (norm >> 1);
		out[j] = div64_s64(tmp, norm);
	}
}

static void mtx_mul_mtx(s64 (*a)[3], s64 (*b)[3],
			s64 (*out)[3], s32 norm)
{
	int i, j, k;
	s64 tmp;

	for (i = 0; i < 3; i++)
		for (j = 0; j < 3; j++) {
			out[i][j] = 0;
			for (k = 0; k < 3; k++)
				out[i][j] += a[k][j] * b[i][k];
			tmp = out[i][j] + (norm >> 1);
			out[i][j] = div64_s64(tmp, norm);
		}
}

static void inverse_3x3(s64 (*in)[3], s64 (*out)[3],
			s32 norm, s32 obl)
{
	int i, j;
	s64 determinant = 0;
	s64 tmp;

	for (i = 0; i < 3; i++)
		determinant +=
			in[0][i] * (in[1][(i + 1) % 3] * in[2][(i + 2) % 3]
			- in[1][(i + 2) % 3] * in[2][(i + 1) % 3]);
	determinant = (determinant + 1) >> 1;

	for (i = 0; i < 3; i++) {
		for (j = 0; j < 3; j++) {
			out[j][i] = (in[(i + 1) % 3][(j + 1) % 3]
				* in[(i + 2) % 3][(j + 2) % 3]);
			out[j][i] -= (in[(i + 1) % 3][(j + 2) % 3]
				* in[(i + 2) % 3][(j + 1) % 3]);
			out[j][i] = (out[j][i] * norm) << (obl - 1);
			tmp = out[j][i] + (determinant >> 1);
			out[j][i] = div64_s64(tmp, determinant);
		}
	}
}

static void calc_T(s64 (*prmy)[2], s64 (*tout)[3],
		   s32 norm, s32 obl)
{
	int i, j;
	s64 z[4];
	s64 A[3][3];
	s64 B[3];
	s64 C[3];
	s64 D[3][3];
	s64 E[3][3];
	s64 tmp;

	for (i = 0; i < 4; i++)
		z[i] = norm - prmy[i][0] - prmy[i][1];

	for (i = 0; i < 3; i++) {
		for (j = 0; j < 2; j++)
			A[i][j] = prmy[i][j];
		A[i][2] = z[i];
	}
	tmp = norm * prmy[3][0] * 2;
	tmp = div64_s64(tmp, prmy[3][1]);
	B[0] = (tmp + 1) >> 1;
	B[1] = norm;
	tmp = norm * z[3] * 2;
	tmp = div64_s64(tmp, prmy[3][1]);
	B[2] = (tmp + 1) >> 1;
	inverse_3x3(A, D, norm, obl);
	mtx_mul(D, B, C, norm);
	for (i = 0; i < 3; i++)
		for (j = 0; j < 3; j++)
			E[i][j] = C[i];
	mtx_dot_mul(A, E, tout, norm);
}

static void gamut_mtx(s64 (*src_prmy)[2], s64 (*dst_prmy)[2],
		      s64 (*tout)[3], s32 norm, s32 obl)
{
	s64 tsrc[3][3];
	s64 tdst[3][3];
	s64 out[3][3];

	calc_T(src_prmy, tsrc, norm, obl);
	calc_T(dst_prmy, tdst, norm, obl);
	inverse_3x3(tdst, out, 1 << obl, obl);
	mtx_mul_mtx(out, tsrc, tout, 1 << obl);
}

static void apply_scale_factor(s64 (*in)[3], s32 *rs)
{
	int i, j;
	s32 right_shift;

	if (display_scale_factor > 2 * 2048)
		right_shift = -2;
	else if (display_scale_factor > 2048)
		right_shift = -1;
	else
		right_shift = 0;
	for (i = 0; i < 3; i++)
		for (j = 0; j < 3; j++) {
			in[i][j] *= display_scale_factor;
			in[i][j] >>= 11 - right_shift;
		}
	right_shift += 1;
	if (right_shift < 0)
		*rs = 8 + right_shift;
	else
		*rs = right_shift;
}

static void N2C(s64 (*in)[3], s32 ibl, s32 obl)
{
	int i, j;

	for (i = 0; i < 3; i++)
		for (j = 0; j < 3; j++) {
			in[i][j] =
				(in[i][j] + (1 << (ibl - 12))) >> (ibl - 11);
			if (in[i][j] < 0)
				in[i][j] += 1 << obl;
		}
}

static void cal_mtx_seting(s64 (*in)[3],
			   s32 ibl, s32 obl,
			   struct matrix_s *m)
{
	int i, j;
	s32 right_shift;

	if (get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB) {
		apply_scale_factor(in, &right_shift);
		m->right_shift = right_shift;
	}
	N2C(in, ibl, obl);
	pr_csc(1, "\tHDR color convert matrix:\n");
	for (i = 0; i < 3; i++) {
		m->pre_offset[i] = 0;
		for (j = 0; j < 3; j++)
			m->matrix[i][j] = in[j][i];
		m->offset[i] = 0;
		pr_csc(1, "\t\t%04x %04x %04x\n",
		       (int)(m->matrix[i][0] & 0xffff),
		       (int)(m->matrix[i][1] & 0xffff),
		       (int)(m->matrix[i][2] & 0xffff));
	}
}

static int check_primaries(uint (*p)[3][2],/* src primaries and white point */
			   uint (*w)[2],
			   /* dst display info from vinfo */
			   const struct vinfo_s *v,
			   /* prepare src and dst color info array */
			   s64 (*si)[4][2], s64 (*di)[4][2])
{
	int i, j;
	/* always calculate to apply scale factor */
	int need_calculate_mtx = 1;
	const struct master_display_info_s *d;

	/* check and copy primaries */
	if (hdr_flag & 1) {
		if (((*p)[0][1] > (*p)[1][1]) &&
		    ((*p)[0][1] > (*p)[2][1]) &&
		    ((*p)[2][0] > (*p)[0][0]) &&
		    ((*p)[2][0] > (*p)[1][0])) {
			/* reasonable g,b,r */
			for (i = 0; i < 3; i++)
				for (j = 0; j < 2; j++) {
					(*si)[i][j] = (*p)[(i + 2) % 3][j];
				if ((*si)[i][j] !=
				    bt2020_primaries[(i + 2) % 3][j])
					need_calculate_mtx = 1;
				}
		} else if (((*p)[0][0] > (*p)[1][0]) &&
			   ((*p)[0][0] > (*p)[2][0]) &&
			   ((*p)[1][1] > (*p)[0][1]) &&
			   ((*p)[1][1] > (*p)[2][1])) {
			/* reasonable r,g,b */
			for (i = 0; i < 3; i++)
				for (j = 0; j < 2; j++) {
					(*si)[i][j] = (*p)[i][j];
					if ((*si)[i][j] !=
					    bt2020_primaries[(i + 2) % 3][j])
						need_calculate_mtx = 1;
				}
		} else {
			/* source not usable, use standard bt2020 */
			for (i = 0; i < 3; i++)
				for (j = 0; j < 2; j++)
					(*si)[i][j] =
						bt2020_primaries
						[(i + 2) % 3][j];
		}
		/* check white point */
		if (need_calculate_mtx == 1) {
			if (((*w)[0] > (*si)[2][0]) &&
			    ((*w)[0] < (*si)[0][0]) &&
			    ((*w)[1] > (*si)[2][1]) &&
			    ((*w)[1] < (*si)[1][1])) {
				for (i = 0; i < 2; i++)
					(*si)[3][i] = (*w)[i];
			} else {
				for (i = 0; i < 3; i++)
					for (j = 0; j < 2; j++)
						(*si)[i][j] =
					bt2020_primaries[(i + 2) % 3][j];

				for (i = 0; i < 2; i++)
					(*si)[3][i] = bt2020_white_point[i];
				/* need_calculate_mtx = 0; */
			}
		} else {
			if (((*w)[0] > (*si)[2][0]) &&
			    ((*w)[0] < (*si)[0][0]) &&
			    ((*w)[1] > (*si)[2][1]) &&
			    ((*w)[1] < (*si)[1][1])) {
				for (i = 0; i < 2; i++) {
					(*si)[3][i] = (*w)[i];
					if ((*si)[3][i] !=
					bt2020_white_point[i])
						need_calculate_mtx = 1;
				}
			} else {
				for (i = 0; i < 2; i++)
					(*si)[3][i] = bt2020_white_point[i];
			}
		}
	} else {
		/* use standard bt2020 */
		for (i = 0; i < 3; i++)
			for (j = 0; j < 2; j++)
				(*si)[i][j] = bt2020_primaries[(i + 2) % 3][j];
		for (i = 0; i < 2; i++)
			(*si)[3][i] = bt2020_white_point[i];
	}

	/* check display */
	if (v->master_display_info.present_flag && (hdr_flag & 2)) {
		d = &v->master_display_info;
		for (i = 0; i < 3; i++) {
			for (j = 0; j < 2; j++) {
				(*di)[i][j] = d->primaries[(i + 2) % 3][j];
				if ((*di)[i][j] !=
				    bt709_primaries[(i + 2) % 3][j])
					need_calculate_mtx = 1;
			}
		}
		for (i = 0; i < 2; i++) {
			(*di)[3][i] = d->white_point[i];
			if ((*di)[3][i] != bt709_white_point[i])
				need_calculate_mtx = 1;
		}
		if (vinfo_lcd_support())
			cal_out_curve(v->hdr_info.lumi_max);
	} else {
		for (i = 0; i < 3; i++) {
			for (j = 0; j < 2; j++)
				(*di)[i][j] = bt709_primaries[(i + 2) % 3][j];
		}
		for (i = 0; i < 2; i++)
			(*di)[3][i] = bt709_white_point[i];
	}
	return need_calculate_mtx;
}

enum vpp_matrix_csc_e prepare_customer_matrix(u32 (*s)[3][2],/* src prim */
					      /* source white point */
					      u32 (*w)[2],
					      /* vinfo carry display prim */
					      const struct vinfo_s *v,
					      struct matrix_s *m,
					      bool inverse_flag)
{
	s64 prmy_src[4][2];
	s64 prmy_dst[4][2];
	s64 out[3][3];
	int ret;
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
	int i, j;
#endif

	ret = VPP_MATRIX_BT2020YUV_BT2020RGB;

#ifndef CONFIG_AMLOGIC_REMOVE_OLD
	if (customer_matrix_en &&
	    get_cpu_type() <= MESON_CPU_MAJOR_ID_GXTVBB) {
		for (i = 0; i < 3; i++) {
			m->pre_offset[i] = customer_matrix_param[i];
			for (j = 0; j < 3; j++)
				m->matrix[i][j] = customer_matrix_param[3 + i * 3 + j];
			m->offset[i] =
				customer_matrix_param[12 + i];
		}
		m->right_shift = customer_matrix_param[15];
		ret = VPP_MATRIX_BT2020RGB_CUSRGB;
	} else {
#else
	{
#endif
		if (inverse_flag) {
			if (check_primaries(s, w, v, &prmy_src, &prmy_dst)) {
				gamut_mtx(prmy_dst, prmy_src, out, INORM, BL);
				cal_mtx_seting(out, BL, 13, m);
			}
		} else {
			if (check_primaries(s, w, v, &prmy_src, &prmy_dst)) {
				gamut_mtx(prmy_src, prmy_dst, out, INORM, BL);
				cal_mtx_seting(out, BL, 13, m);
			}
		}
		ret = VPP_MATRIX_BT2020RGB_CUSRGB;
	}
	return ret;
}

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
/* Max luminance lookup table for contrast */
static const int maxluma_thrd[5] = {512, 1024, 2048, 4096, 8192};
static int calculate_contrast_adj(int max_lumin)
{
	int k;
	int left, right, norm, alph;
	int ratio, target_contrast;

	if (max_lumin < maxluma_thrd[0])
		k = 0;
	else if (max_lumin < maxluma_thrd[1])
		k = 1;
	else if (max_lumin < maxluma_thrd[2])
		k = 2;
	else if (max_lumin < maxluma_thrd[3])
		k = 3;
	else if (max_lumin < maxluma_thrd[4])
		k = 4;
	else
		k = 5;

	if (k == 0) {
		ratio = extra_con_lut[0];
	} else if (k == 5) {
		ratio = extra_con_lut[4];
	} else {
		left = extra_con_lut[k - 1];
		right = extra_con_lut[k];
		norm = maxluma_thrd[k] - maxluma_thrd[k - 1];
		alph = max_lumin - maxluma_thrd[k - 1];
		ratio = left + (alph * (right - left) + (norm >> 1)) / norm;
	}
	target_contrast = ((vd1_contrast + 1024) * ratio + 64) >> 7;
	target_contrast = clip(target_contrast, 0, 2047);
	target_contrast -= 1024;
	return target_contrast - vd1_contrast;
}

static void amvecm_cp_hdr_info(struct master_display_info_s *hdr_data,
			       struct vframe_master_display_colour_s *p)
{
	int i, j;

	if (customer_hdmi_display_en) {
		hdr_data->features =
			  (1 << 29)	/* video available */
			| (5 << 26)	/* unspecified */
			| (0 << 25)	/* limit */
			| (1 << 24)	/* color available */
			| (customer_hdmi_display_param[0] << 16) /* bt2020 */
			| (customer_hdmi_display_param[1] << 8)	/* 2084 */
			| (10 << 0);	/* bt2020c */
		memcpy(hdr_data->primaries,
		       &customer_hdmi_display_param[2],
		       sizeof(u32) * 6);
		memcpy(hdr_data->white_point,
		       &customer_hdmi_display_param[8],
		       sizeof(u32) * 2);
		hdr_data->luminance[0] =
				customer_hdmi_display_param[10];
		hdr_data->luminance[1] =
				customer_hdmi_display_param[11];
		hdr_data->max_content =
				customer_hdmi_display_param[12];
		hdr_data->max_frame_average =
				customer_hdmi_display_param[13];
	} else if ((((hdr_data->features >> 16) & 0xff) == 9) ||
		   ((((hdr_data->features >> 8) & 0xff) >= 14) &&
		   (((hdr_data->features >> 8) & 0xff) <= 18))) {
		if (p->present_flag & 1) {
			memcpy(hdr_data->primaries,
			       p->primaries,
			       sizeof(u32) * 6);
			memcpy(hdr_data->white_point,
			       p->white_point,
			       sizeof(u32) * 2);
			hdr_data->luminance[0] = p->luminance[0];
			hdr_data->luminance[1] = p->luminance[1];
			if (p->content_light_level.present_flag == 1) {
				hdr_data->max_content =
					p->content_light_level.max_content;
				hdr_data->max_frame_average =
					p->content_light_level.max_pic_average;
			} else {
				hdr_data->max_content = 0;
				hdr_data->max_frame_average = 0;
			}
		} else {
			for (i = 0; i < 3; i++)
				for (j = 0; j < 2; j++)
					hdr_data->primaries[i][j] =
							bt2020_primaries[i][j];
			hdr_data->white_point[0] = bt709_white_point[0];
			hdr_data->white_point[1] = bt709_white_point[1];
			/* default luminance */
			hdr_data->luminance[0] = 1000 * 10000;
			hdr_data->luminance[1] = 50;

			/* content_light_level */
			hdr_data->max_content = 0;
			hdr_data->max_frame_average = 0;
		}
		hdr_data->luminance[0] = hdr_data->luminance[0] / 10000;
		hdr_data->present_flag = 1;
	} else {
		memset(hdr_data->primaries, 0, sizeof(hdr_data->primaries));
	}
	/* hdr send information debug */
	memcpy(&dbg_hdr_send, hdr_data,
	       sizeof(struct master_display_info_s));
}

static void hdr_process_pq_enable(int enable)
{
	dnlp_en = enable;
	/*cm_en = enable;*/
}
static void vpp_lut_curve_set(enum vpp_lut_sel_e lut_sel,
			      struct vinfo_s *vinfo)
{
	unsigned int *ptable = NULL;

	if (lut_sel == VPP_LUT_EOTF) {
		/* eotf lut 2048 */
		if (!vinfo_lcd_support()) {
			if (video_lut_switch == 1)
				/*350nit alpha_low = 0.12; */
				ptable = eotf_33_2084_mapping_level1_box;
			else if (video_lut_switch == 2)
				/*800nit alpha_low = 0.12; */
				ptable = eotf_33_2084_mapping_level2_box;
			else if (video_lut_switch == 3)
				/*400nit alpha_low = 0.20; */
				ptable = eotf_33_2084_mapping_level3_box;
			else if (video_lut_switch == 4)
				/*450nit alpha_low = 0.12; */
				ptable = eotf_33_2084_mapping_level4_box;
			else
				/* eotf lut 2048 */
				/*600nit  alpha_low = 0.12;*/
				ptable = eotf_33_2084_mapping_box;
		} else {
			ptable = eotf_33_2084_mapping_box;
		}
	} else if (lut_sel == VPP_LUT_OETF) {
		/* oetf lut bypass */
		if (!vinfo_lcd_support()) {
			if (video_lut_switch == 1)
				ptable = oetf_289_gamma22_mapping_level1_box;
			else if (video_lut_switch == 2)
				ptable = oetf_289_gamma22_mapping_level2_box;
			else if (video_lut_switch == 3)
				ptable = oetf_289_gamma22_mapping_level3_box;
			else if (video_lut_switch == 4)
				ptable = oetf_289_gamma22_mapping_level4_box;
			else
				ptable = oetf_289_gamma22_mapping_box;
				/* oetf lut bypass */
		} else {
			ptable = oetf_289_gamma22_mapping;
		}
	}

	if (lut_sel == VPP_LUT_EOTF ||
	    lut_sel == VPP_LUT_OETF)
		set_vpp_lut(lut_sel,
			    ptable,
			    ptable,
			    ptable,
			    CSC_ON);
}

static int hdr_process(enum vpp_matrix_csc_e csc_type,
		       struct vinfo_s *vinfo,
		       struct vframe_master_display_colour_s *master_info,
		       enum vd_path_e vd_path,
		       enum hdr_type_e *source_type,
		       enum vpp_index_e vpp_index)
{
	int need_adjust_contrast_saturation = 0;
	int max_lumin = 10000;
	int s5_silce_mode = get_s5_slice_mode();
	struct matrix_s m = {
		{0, 0, 0},
		{
			{0x0d49, 0x1b4d, 0x1f6b},
			{0x1f01, 0x0910, 0x1fef},
			{0x1fdb, 0x1f32, 0x08f3},
		},
		{0, 0, 0},
		1
	};
	struct matrix_s osd_m = {
		{0, 0, 0},
		{
			{0x505, 0x2A2, 0x059},
			{0x08E, 0x75B, 0x017},
			{0x022, 0x0B4, 0x72A},
		},
		{0, 0, 0},
		1
	};
	int mtx[EOTF_COEFF_SIZE] = {
		EOTF_COEFF_NORM(1.6607056 / 2),
		EOTF_COEFF_NORM(-0.5877533 / 2),
		EOTF_COEFF_NORM(-0.0729065 / 2),
		EOTF_COEFF_NORM(-0.1245575 / 2),
		EOTF_COEFF_NORM(1.1329346 / 2),
		EOTF_COEFF_NORM(-0.0083771 / 2),
		EOTF_COEFF_NORM(-0.0181122 / 2),
		EOTF_COEFF_NORM(-0.1005249 / 2),
		EOTF_COEFF_NORM(1.1186371 / 2),
		EOTF_COEFF_RIGHTSHIFT,
	};
	int osd_mtx[EOTF_COEFF_SIZE] = {
		EOTF_COEFF_NORM(0.627441),
		EOTF_COEFF_NORM(0.329285),
		EOTF_COEFF_NORM(0.043274),
		EOTF_COEFF_NORM(0.069092),
		EOTF_COEFF_NORM(0.919556),
		EOTF_COEFF_NORM(0.011322),
		EOTF_COEFF_NORM(0.016418),
		EOTF_COEFF_NORM(0.088058),
		EOTF_COEFF_NORM(0.895554),
		EOTF_COEFF_RIGHTSHIFT
	};
	int i, j;

	if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
		gamut_convert_process(vinfo, source_type, vd_path, &m, 8);
		eo_clip_proc(master_info, 0);
		hdr_func(OSD1_HDR, HDR_BYPASS | hdr_ex, vinfo, NULL, vpp_index);
		hdr_func(OSD2_HDR, HDR_BYPASS | hdr_ex, vinfo, NULL, vpp_index);
		hdr_func(OSD3_HDR, HDR_BYPASS | hdr_ex, vinfo, NULL, vpp_index);
		if (vd_path == VD1_PATH) {
			if (s5_silce_mode == VD1_1SLICE) {
				hdr_func(VD1_HDR, HDR_SDR | hdr_ex, vinfo, &m, vpp_index);
			} else if (s5_silce_mode == VD1_2SLICE) {
				hdr_func(VD1_HDR, HDR_SDR | hdr_ex, vinfo, &m, vpp_index);
				hdr_func(S5_VD1_SLICE1, HDR_SDR | hdr_ex, vinfo, &m, vpp_index);
			} else if (s5_silce_mode == VD1_4SLICE) {
				hdr_func(VD1_HDR, HDR_SDR | hdr_ex, vinfo, &m, vpp_index);
				hdr_func(S5_VD1_SLICE1, HDR_SDR | hdr_ex, vinfo, &m, vpp_index);
				hdr_func(S5_VD1_SLICE2, HDR_SDR | hdr_ex, vinfo, &m, vpp_index);
				hdr_func(S5_VD1_SLICE3, HDR_SDR | hdr_ex, vinfo, &m, vpp_index);
			}
		} else if (vd_path == VD2_PATH) {
			hdr_func(VD2_HDR, HDR_SDR | hdr_ex, vinfo, &m, vpp_index);
		} else if (vd_path == VD3_PATH) {
			hdr_func(VD3_HDR, HDR_SDR | hdr_ex, vinfo, &m, vpp_index);
		}
		return need_adjust_contrast_saturation;
	}

	if (master_info->present_flag & 1) {
		pr_csc(1, "\tMaster_display_colour available.\n");
		print_primaries_info(master_info);
		/* for VIDEO */
		csc_type =
			prepare_customer_matrix(&master_info->primaries,
						&master_info->white_point,
						vinfo, &m, 0);
		/* for OSD */
		if (get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB)
			prepare_customer_matrix(&bt2020_primaries,
						&bt2020_white_point,
						vinfo, &osd_m, 1);
		need_adjust_contrast_saturation |= 1;
	} else {
		/* use bt2020 primaries */
		pr_csc(1, "\tNo master_display_colour.\n");
		/* for VIDEO */
		csc_type =
			prepare_customer_matrix(&bt2020_primaries,
						&bt2020_white_point,
						vinfo, &m, 0);
		/* for OSD */
		if (get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB)
			prepare_customer_matrix(&bt2020_primaries,
						&bt2020_white_point,
						vinfo, &osd_m, 1);
	}

	/************** OSD ***************/
	/*vpp matrix mux read*/
	vpp_set_mtx_en_read();
	if (get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB &&
	    (csc_en & 0x2)) {
		/* RGB to YUV */
		/* not using old RGB2YUV convert HW */
		/* use new 10bit OSD convert matrix */
		/* WRITE_VPP_REG_BITS */
		/*(VIU_OSD1_BLK0_CFG_W0,0, 7, 1); */

		/* eotf lut 709 */
		if (is_hdr_cfg_osd_100() == 1) {
			set_vpp_lut(VPP_LUT_OSD_EOTF,
				    osd_eotf_33_709_mapping_100, /* R */
				    osd_eotf_33_709_mapping_100, /* G */
				    osd_eotf_33_709_mapping_100, /* B */
				    CSC_ON);
		} else if (is_hdr_cfg_osd_100() == 2) {
			set_vpp_lut(VPP_LUT_OSD_EOTF,
				    osd_eotf_33_709_mapping_290, /* R */
				    osd_eotf_33_709_mapping_290, /* G */
				    osd_eotf_33_709_mapping_290, /* B */
				    CSC_ON);
		} else if (is_hdr_cfg_osd_100() == 3) {
			set_vpp_lut(VPP_LUT_OSD_EOTF,
				    osd_eotf_33_709_mapping_330, /* R */
				    osd_eotf_33_709_mapping_330, /* G */
				    osd_eotf_33_709_mapping_330, /* B */
				    CSC_ON);
		} else {
			set_vpp_lut(VPP_LUT_OSD_EOTF,
				    osd_eotf_33_709_mapping, /* R */
				    osd_eotf_33_709_mapping, /* G */
				    osd_eotf_33_709_mapping, /* B */
				    CSC_ON);
		}
		/* eotf matrix 709->2020 */
		osd_mtx[EOTF_COEFF_SIZE - 1] = osd_m.right_shift;
		for (i = 0; i < 3; i++)
			for (j = 0; j < 3; j++) {
				if (osd_m.matrix[i][j] & 0x1000)
					osd_mtx[i * 3 + j] =
					-(((~osd_m.matrix[i][j]) & 0xfff) + 1);
				else
					osd_mtx[i * 3 + j] = osd_m.matrix[i][j];
			}
		set_vpp_matrix(VPP_MATRIX_OSD_EOTF,
			       osd_mtx,
			       CSC_ON);

		/* oetf lut 2084 */
		if (is_hdr_cfg_osd_100() == 1) {
			set_vpp_lut(VPP_LUT_OSD_OETF,
				    osd_oetf_41_2084_mapping_100, /* R */
				    osd_oetf_41_2084_mapping_100, /* G */
				    osd_oetf_41_2084_mapping_100, /* B */
				    CSC_ON);
		} else if (is_hdr_cfg_osd_100() == 2) {
			set_vpp_lut(VPP_LUT_OSD_OETF,
				    osd_oetf_41_2084_mapping_290, /* R */
				    osd_oetf_41_2084_mapping_290, /* G */
				    osd_oetf_41_2084_mapping_290, /* B */
				    CSC_ON);
		} else if (is_hdr_cfg_osd_100() == 3) {
			set_vpp_lut(VPP_LUT_OSD_OETF,
				    osd_oetf_41_2084_mapping_330, /* R */
				    osd_oetf_41_2084_mapping_330, /* G */
				    osd_oetf_41_2084_mapping_330, /* B */
				    CSC_ON);
		} else {
			set_vpp_lut(VPP_LUT_OSD_OETF,
				    osd_oetf_41_2084_mapping, /* R */
				    osd_oetf_41_2084_mapping, /* G */
				    osd_oetf_41_2084_mapping, /* B */
				    CSC_ON);
		}
		/* osd matrix RGB2020 to YUV2020 limit */
		set_vpp_matrix(VPP_MATRIX_OSD,
			       RGB2020_to_YUV2020l_coeff,
			       CSC_ON);
	}
	/************** VIDEO **************/
	if (get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB &&
	    (csc_en & 0x4)) {
		/* vd1 matrix bypass */
		set_vpp_matrix(VPP_MATRIX_VD1,
			       bypass_coeff,
			       CSC_OFF);

		/*INV LUT*/
		set_vpp_lut(VPP_LUT_INV_EOTF,
			    NULL,
			    NULL,
			    NULL,
			    CSC_OFF);

		/* post matrix YUV2020 to RGB2020 */
		set_vpp_matrix(VPP_MATRIX_POST,
			       YUV2020l_to_RGB2020_coeff,
			       CSC_ON);

		/* eotf lut 2048 */
		vpp_lut_curve_set(VPP_LUT_EOTF, vinfo);

		need_adjust_contrast_saturation = 0;
		saturation_offset =	0;
		if (hdr_flag & 8) {
			need_adjust_contrast_saturation |= 2;
			saturation_offset =	extra_sat_lut[0];
		}
		if (master_info->present_flag & 1) {
			max_lumin = master_info->luminance[0]
				/ 10000;
			if (max_lumin <= 1200 && max_lumin > 0) {
				if (hdr_flag & 4)
					need_adjust_contrast_saturation |= 1;
				if (hdr_flag & 8)
					saturation_offset =
						extra_sat_lut[1];
			}
		}
		/* eotf matrix RGB2020 to RGB709 */
		mtx[EOTF_COEFF_SIZE - 1] = m.right_shift;
		for (i = 0; i < 3; i++)
			for (j = 0; j < 3; j++) {
				if (m.matrix[i][j] & 0x1000)
					mtx[i * 3 + j] =
					-(((~m.matrix[i][j]) & 0xfff) + 1);
				else
					mtx[i * 3 + j] = m.matrix[i][j];
			}

		set_vpp_matrix(VPP_MATRIX_EOTF,
			       mtx,
			       CSC_ON);

		vpp_lut_curve_set(VPP_LUT_OETF, vinfo);

		/* xvyccc matrix3: bypass */
		if (!(vinfo->mode == VMODE_LCD ||
			vinfo->mode == VMODE_DUMMY_ENCP))
			set_vpp_matrix(VPP_MATRIX_XVYCC,
				       RGB709_to_YUV709l_coeff,
				       CSC_ON);
	}
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
	if (get_cpu_type() <= MESON_CPU_MAJOR_ID_GXTVBB) {
		/* turn vd1 matrix on */
		vpp_set_matrix(VPP_MATRIX_VD1, CSC_ON,
			       csc_type, NULL);
		/* turn post matrix on */
		vpp_set_matrix(VPP_MATRIX_POST, CSC_ON,
			       csc_type, &m);
		/* xvycc lut on */
		load_knee_lut(CSC_ON);

		vecm_latch_flag |= FLAG_VADJ1_BRI;
		hdr_process_pq_enable(0);
		/* if GXTVBB HDMI output(YUV) case */
		/* xvyccc matrix3: RGB to YUV */
		/* other cases */
		/* xvyccc matrix3: bypass */
		if (!vinfo_lcd_support() &&
		    get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB)
			vpp_set_matrix3(CSC_ON, VPP_MATRIX_RGB_YUV709);
		else
			vpp_set_matrix3(CSC_OFF, VPP_MATRIX_NULL);
	}
#endif
	/*vpp matrix mux write*/
	vpp_set_mtx_en_write();
	return need_adjust_contrast_saturation;
}

static int hdr10p_process(enum vpp_matrix_csc_e csc_type,
			  struct vinfo_s *vinfo,
			  struct vframe_master_display_colour_s *master_info,
			  enum vd_path_e vd_path,
			  enum hdr_type_e *source_type,
			  enum vpp_index_e vpp_index)
{
	struct matrix_s m = {
		{0, 0, 0},
		{
			{0x0d49, 0x1b4d, 0x1f6b},
			{0x1f01, 0x0910, 0x1fef},
			{0x1fdb, 0x1f32, 0x08f3},
		},
		{0, 0, 0},
		1
	};
	int s5_silce_mode = get_s5_slice_mode();

	if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
		gamut_convert_process(vinfo, source_type, vd_path, &m, 8);
		hdr_func(OSD1_HDR, HDR_BYPASS | hdr_ex, vinfo, NULL, vpp_index);
		hdr_func(OSD2_HDR, HDR_BYPASS | hdr_ex, vinfo, NULL, vpp_index);
		hdr_func(OSD3_HDR, HDR_BYPASS | hdr_ex, vinfo, NULL, vpp_index);
		if (vd_path == VD1_PATH) {
			if (s5_silce_mode == VD1_1SLICE) {
				hdr10p_func(VD1_HDR, HDR10P_SDR | hdr_ex, vinfo,
					&m, vpp_index);
			} else if (s5_silce_mode == VD1_2SLICE) {
				hdr10p_func(VD1_HDR, HDR10P_SDR | hdr_ex, vinfo,
					&m, vpp_index);
				hdr10p_func(S5_VD1_SLICE1, HDR10P_SDR | hdr_ex, vinfo,
					&m, vpp_index);
			} else if (s5_silce_mode == VD1_4SLICE) {
				hdr10p_func(VD1_HDR, HDR10P_SDR | hdr_ex, vinfo,
					&m, vpp_index);
				hdr10p_func(S5_VD1_SLICE1, HDR10P_SDR | hdr_ex, vinfo,
					&m, vpp_index);
				hdr10p_func(S5_VD1_SLICE2, HDR10P_SDR | hdr_ex, vinfo,
					&m, vpp_index);
				hdr10p_func(S5_VD1_SLICE3, HDR10P_SDR | hdr_ex, vinfo,
					&m, vpp_index);
			}
		} else if (vd_path == VD2_PATH) {
			hdr10p_func(VD2_HDR, HDR10P_SDR | hdr_ex, vinfo, &m, vpp_index);
		} else if (vd_path == VD3_PATH) {
			hdr10p_func(VD3_HDR, HDR10P_SDR | hdr_ex, vinfo, &m, vpp_index);
		}
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	} else {
		hdr_process(csc_type, vinfo, master_info, vd_path,
			    source_type, vpp_index);
#endif
	}

	return 0;
}

static int hlg_process(enum vpp_matrix_csc_e csc_type,
		       struct vinfo_s *vinfo,
		       struct vframe_master_display_colour_s *master_info,
		       enum vd_path_e vd_path,
		       enum hdr_type_e *source_type,
		       enum vpp_index_e vpp_index)
{
	int need_adjust_contrast_saturation = 0;
	int max_lumin = 10000;
	struct matrix_s m = {
		{0, 0, 0},
		{
			{0x0d49, 0x1b4d, 0x1f6b},
			{0x1f01, 0x0910, 0x1fef},
			{0x1fdb, 0x1f32, 0x08f3},
		},
		{0, 0, 0},
		1
	};
	struct matrix_s osd_m = {
		{0, 0, 0},
		{
			{0x505, 0x2A2, 0x059},
			{0x08E, 0x75B, 0x017},
			{0x022, 0x0B4, 0x72A},
		},
		{0, 0, 0},
		1
	};
	int mtx[EOTF_COEFF_SIZE] = {
		EOTF_COEFF_NORM(1.6607056 / 2),
		EOTF_COEFF_NORM(-0.5877533 / 2),
		EOTF_COEFF_NORM(-0.0729065 / 2),
		EOTF_COEFF_NORM(-0.1245575 / 2),
		EOTF_COEFF_NORM(1.1329346 / 2),
		EOTF_COEFF_NORM(-0.0083771 / 2),
		EOTF_COEFF_NORM(-0.0181122 / 2),
		EOTF_COEFF_NORM(-0.1005249 / 2),
		EOTF_COEFF_NORM(1.1186371 / 2),
		EOTF_COEFF_RIGHTSHIFT,
	};
	int osd_mtx[EOTF_COEFF_SIZE] = {
		EOTF_COEFF_NORM(0.627441),
		EOTF_COEFF_NORM(0.329285),
		EOTF_COEFF_NORM(0.043274),
		EOTF_COEFF_NORM(0.069092),
		EOTF_COEFF_NORM(0.919556),
		EOTF_COEFF_NORM(0.011322),
		EOTF_COEFF_NORM(0.016418),
		EOTF_COEFF_NORM(0.088058),
		EOTF_COEFF_NORM(0.895554),
		EOTF_COEFF_RIGHTSHIFT
	};
	int i, j;
	int s5_silce_mode = get_s5_slice_mode();

	if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
		gamut_convert_process(vinfo, source_type, vd_path, &m, 8);
		if (vd_path == VD1_PATH) {
			if (s5_silce_mode == VD1_1SLICE) {
				hdr_func(VD1_HDR, HLG_SDR | hdr_ex, vinfo, &m, vpp_index);
			} else if (s5_silce_mode == VD1_2SLICE) {
				hdr_func(VD1_HDR, HLG_SDR | hdr_ex, vinfo, &m, vpp_index);
				hdr_func(S5_VD1_SLICE1, HLG_SDR | hdr_ex, vinfo, &m, vpp_index);
			} else if (s5_silce_mode == VD1_4SLICE) {
				hdr_func(VD1_HDR, HLG_SDR | hdr_ex, vinfo, &m, vpp_index);
				hdr_func(S5_VD1_SLICE1, HLG_SDR | hdr_ex, vinfo, &m, vpp_index);
				hdr_func(S5_VD1_SLICE2, HLG_SDR | hdr_ex, vinfo, &m, vpp_index);
				hdr_func(S5_VD1_SLICE3, HLG_SDR | hdr_ex, vinfo, &m, vpp_index);
			}
		} else if (vd_path == VD2_PATH) {
			hdr_func(VD2_HDR, HLG_SDR | hdr_ex, vinfo, &m, vpp_index);
		} else if (vd_path == VD3_PATH) {
			hdr_func(VD3_HDR, HLG_SDR | hdr_ex, vinfo, &m, vpp_index);
		}
		hdr_func(OSD1_HDR, HDR_BYPASS | hdr_ex, vinfo, NULL, vpp_index);
		hdr_func(OSD2_HDR, HDR_BYPASS | hdr_ex, vinfo, NULL, vpp_index);
		hdr_func(OSD3_HDR, HDR_BYPASS | hdr_ex, vinfo, NULL, vpp_index);
		return need_adjust_contrast_saturation;
	}

	if (master_info->present_flag & 1) {
		pr_csc(1, "\tMaster_display_colour available.\n");
		print_primaries_info(master_info);
		/* for VIDEO */
		csc_type =
			prepare_customer_matrix(&master_info->primaries,
						&master_info->white_point,
						vinfo, &m, 0);
		/* for OSD */
		if (get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB)
			prepare_customer_matrix(&master_info->primaries,
						&master_info->white_point,
						vinfo, &osd_m, 1);
		need_adjust_contrast_saturation |= 1;
	} else {
		/* use bt2020 primaries */
		pr_csc(1, "\tNo master_display_colour.\n");
		/* for VIDEO */
		csc_type =
			prepare_customer_matrix(&bt2020_primaries,
						&bt2020_white_point,
						vinfo, &m, 0);
		/* for OSD */
		if (get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB)
			prepare_customer_matrix(&bt2020_primaries,
						&bt2020_white_point,
						vinfo, &osd_m, 1);
	}
	/*vpp matrix mux read*/
	vpp_set_mtx_en_read();
	if (get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB &&
	    (csc_en & 0x2)) {
		/************** OSD ***************/
		/* RGB to YUV */
		/* not using old RGB2YUV convert HW */
		/* use new 10bit OSD convert matrix */
		/* WRITE_VPP_REG_BITS(VIU_OSD1_BLK0_CFG_W0, */
		/* 0, 7, 1); */
		/* eotf lut 709 */
		if (get_hdr_type() & HLG_FLAG)
			set_vpp_lut(VPP_LUT_OSD_EOTF,
				    osd_eotf_33_sdr2hlg_mapping, /* R */
				    osd_eotf_33_sdr2hlg_mapping, /* G */
				    osd_eotf_33_sdr2hlg_mapping, /* B */
				    CSC_ON);
		else
			set_vpp_lut(VPP_LUT_OSD_EOTF,
				    osd_eotf_33_709_mapping, /* R */
				    osd_eotf_33_709_mapping, /* G */
				    osd_eotf_33_709_mapping, /* B */
				    CSC_ON);

		/* eotf matrix 709->2020 */
		osd_mtx[EOTF_COEFF_SIZE - 1] = osd_m.right_shift;
		for (i = 0; i < 3; i++)
			for (j = 0; j < 3; j++) {
				if (osd_m.matrix[i][j] & 0x1000)
					osd_mtx[i * 3 + j] =
					-(((~osd_m.matrix[i][j]) & 0xfff) + 1);
				else
					osd_mtx[i * 3 + j] = osd_m.matrix[i][j];
			}
		set_vpp_matrix(VPP_MATRIX_OSD_EOTF,
			       osd_mtx,
			       CSC_ON);

		/* oetf lut 2084 */
		if (get_hdr_type() & HLG_FLAG)
			set_vpp_lut(VPP_LUT_OSD_OETF,
				    osd_oetf_41_sdr2hlg_mapping, /* R */
				    osd_oetf_41_sdr2hlg_mapping, /* G */
				    osd_oetf_41_sdr2hlg_mapping, /* B */
				    CSC_ON);
		else
			set_vpp_lut(VPP_LUT_OSD_OETF,
				    osd_oetf_41_2084_mapping, /* R */
				    osd_oetf_41_2084_mapping, /* G */
				    osd_oetf_41_2084_mapping, /* B */
				    CSC_ON);

		/* osd matrix RGB2020 to YUV2020 limit */
		set_vpp_matrix(VPP_MATRIX_OSD,
			       RGB2020_to_YUV2020l_coeff,
			       CSC_ON);
	}
	/************** VIDEO **************/
	if (get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB &&
	    (csc_en & 0x4)) {
		/* vd1 matrix bypass */
		set_vpp_matrix(VPP_MATRIX_VD1,
			       bypass_coeff,
			       CSC_OFF);

		/*eo oo oe*/
		set_vpp_lut(VPP_LUT_INV_EOTF,
			    NULL,
			    NULL,
			    NULL,
			    CSC_OFF);

		/* post matrix YUV2020 to RGB2020 */
		set_vpp_matrix(VPP_MATRIX_POST,
			       YUV2020l_to_RGB2020_coeff,
			       CSC_ON);

		/* eotf lut 2048 */
		set_vpp_lut(VPP_LUT_EOTF,
			    eotf_33_hlg_mapping, /* R */
			    eotf_33_hlg_mapping, /* G */
			    eotf_33_hlg_mapping, /* B */
			    CSC_ON);

		need_adjust_contrast_saturation = 0;
		saturation_offset = 0;
		if (hdr_flag & 8) {
			need_adjust_contrast_saturation |= 2;
			saturation_offset = extra_sat_lut[0];
		}
		if (master_info->present_flag & 1) {
			max_lumin = master_info->luminance[0] / 10000;
			if (max_lumin <= 1200 && max_lumin > 0) {
				if (hdr_flag & 4)
					need_adjust_contrast_saturation |= 1;
				if (hdr_flag & 8)
					saturation_offset =
						extra_sat_lut[1];
			}
		}
		/* eotf matrix RGB2020 to RGB709 */
		mtx[EOTF_COEFF_SIZE - 1] = m.right_shift;
		for (i = 0; i < 3; i++)
			for (j = 0; j < 3; j++) {
				if (m.matrix[i][j] & 0x1000)
					mtx[i * 3 + j] =
					-(((~m.matrix[i][j]) & 0xfff) + 1);
				else
					mtx[i * 3 + j] = m.matrix[i][j];
			}

		set_vpp_matrix(VPP_MATRIX_EOTF,
			       mtx,
			       CSC_ON);

		set_vpp_lut(VPP_LUT_OETF,
			    oetf_289_gamma22_mapping,
			    oetf_289_gamma22_mapping,
			    oetf_289_gamma22_mapping,
			    CSC_ON);

		/* xvyccc matrix3: bypass */
		if (!vinfo_lcd_support())
			set_vpp_matrix(VPP_MATRIX_XVYCC,
				       RGB709_to_YUV709l_coeff,
				       CSC_ON);
	}
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
	if (get_cpu_type() <= MESON_CPU_MAJOR_ID_GXTVBB) {
		/* turn vd1 matrix on */
		vpp_set_matrix(VPP_MATRIX_VD1, CSC_ON,
			       csc_type, NULL);
		/* turn post matrix on */
		vpp_set_matrix(VPP_MATRIX_POST, CSC_ON,
			       csc_type, &m);
		/* xvycc lut on */
		load_knee_lut(CSC_ON);

		vecm_latch_flag |= FLAG_VADJ1_BRI;
		hdr_process_pq_enable(0);
		/* if GXTVBB HDMI output(YUV) case */
		/* xvyccc matrix3: RGB to YUV */
		/* other cases */
		/* xvyccc matrix3: bypass */
		if (!vinfo_lcd_support() &&
		    get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB)
			vpp_set_matrix3(CSC_ON, VPP_MATRIX_RGB_YUV709);
		else
			vpp_set_matrix3(CSC_OFF, VPP_MATRIX_NULL);
	}
#endif
	/*vpp matrix mux write*/
	vpp_set_mtx_en_write();
	return need_adjust_contrast_saturation;
}

static void bypass_hdr_process(enum vpp_matrix_csc_e csc_type,
			       struct vinfo_s *vinfo,
			       struct vframe_master_display_colour_s
			       *master_info,
			       enum vd_path_e vd_path,
			       enum hdr_type_e *source_type,
			       enum vpp_index_e vpp_index)
{
	struct matrix_s m = {
		{0, 0, 0},
		{
			{0x0400, 0x0, 0x0},
			{0x0, 0x0400, 0x0},
			{0x0, 0x0, 0x0400},
		},
		{0, 0, 0},
		1
	};
	struct matrix_s osd_m = {
		{0, 0, 0},
		{
			{0x505, 0x2A2, 0x059},
			{0x08E, 0x75B, 0x017},
			{0x022, 0x0B4, 0x72A},
		},
		{0, 0, 0},
		1
	};
	int osd_mtx[EOTF_COEFF_SIZE] = {
		EOTF_COEFF_NORM(0.627441),	EOTF_COEFF_NORM(0.329285),
		EOTF_COEFF_NORM(0.043274),
		EOTF_COEFF_NORM(0.069092),	EOTF_COEFF_NORM(0.919556),
		EOTF_COEFF_NORM(0.011322),
		EOTF_COEFF_NORM(0.016418),	EOTF_COEFF_NORM(0.088058),
		EOTF_COEFF_NORM(0.895554),
		EOTF_COEFF_RIGHTSHIFT
	};
	int i, j, p_sel;
	unsigned int *ptable;
	int *pmatrix;
	int s5_silce_mode = get_s5_slice_mode();

	if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
		if (gamut_conv_enable)
			gamut_convert_process(vinfo, source_type,
					      vd_path, &m, 10);

		p_sel = gamut_conv_enable ? SDR_GMT_CONVERT : HDR_BYPASS;
		p_sel |= hdr_ex;

		if (vd_path == VD1_PATH) {
			if (s5_silce_mode == VD1_1SLICE) {
				hdr_func(VD1_HDR,
					 p_sel,
					 vinfo,
					 gamut_conv_enable ? &m : NULL,
					 vpp_index);
			} else if (s5_silce_mode == VD1_2SLICE) {
				hdr_func(VD1_HDR,
					 p_sel,
					 vinfo,
					 gamut_conv_enable ? &m : NULL,
					 vpp_index);
				hdr_func(S5_VD1_SLICE1,
					 p_sel,
					 vinfo,
					 gamut_conv_enable ? &m : NULL,
					 vpp_index);
			} else if (s5_silce_mode == VD1_4SLICE) {
				hdr_func(VD1_HDR,
					 p_sel,
					 vinfo,
					 gamut_conv_enable ? &m : NULL,
					 vpp_index);
				hdr_func(S5_VD1_SLICE1,
					 p_sel,
					 vinfo,
					 gamut_conv_enable ? &m : NULL,
					 vpp_index);
				hdr_func(S5_VD1_SLICE2,
					 p_sel,
					 vinfo,
					 gamut_conv_enable ? &m : NULL,
					 vpp_index);
				hdr_func(S5_VD1_SLICE3,
					 p_sel,
					 vinfo,
					 gamut_conv_enable ? &m : NULL,
					 vpp_index);
			}
		}
		else if (vd_path == VD2_PATH)
			hdr_func(VD2_HDR,
				 p_sel,
				 vinfo,
				 gamut_conv_enable ? &m : NULL,
				 vpp_index);
		else if (vd_path == VD3_PATH)
			hdr_func(VD3_HDR,
				 p_sel,
				 vinfo,
				 gamut_conv_enable ? &m : NULL,
				 vpp_index);
		if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB &&
		    ((sink_hdr_support(vinfo) & (HDR_SUPPORT | HLG_SUPPORT)) &&
		     !vinfo_lcd_support())) {
			if (get_hdr_type() & HLG_FLAG) {
				hdr_func(OSD1_HDR,
					 SDR_HLG | hdr_ex, vinfo, NULL, vpp_index);
				hdr_func(OSD2_HDR,
					 SDR_HLG | hdr_ex, vinfo, NULL, vpp_index);
				hdr_func(OSD3_HDR,
					 SDR_HLG | hdr_ex, vinfo, NULL, vpp_index);
			} else {
				hdr_func(OSD1_HDR,
					 SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
				hdr_func(OSD2_HDR,
					 SDR_HLG | hdr_ex, vinfo, NULL, vpp_index);
				hdr_func(OSD3_HDR,
					 SDR_HLG | hdr_ex, vinfo, NULL, vpp_index);
			}
			pr_csc(1, "\t osd sdr->hdr/hlg\n");
		} else {
			hdr_func(OSD1_HDR, HDR_BYPASS | hdr_ex, vinfo, NULL, vpp_index);
			hdr_func(OSD2_HDR, HDR_BYPASS | hdr_ex, vinfo, NULL, vpp_index);
			hdr_func(OSD3_HDR, HDR_BYPASS | hdr_ex, vinfo, NULL, vpp_index);
		}
		return;
	}
	/*vpp matrix mux read*/
	vpp_set_mtx_en_read();
	if (get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB) {
		/************** OSD ***************/
		/* RGB to YUV */
		/* not using old RGB2YUV convert HW */
		/* use new 10bit OSD convert matrix */
		/* WRITE_VPP_REG_BITS*/
		/*(VIU_OSD1_BLK0_CFG_W0,0, 7, 1);*/
		if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB &&
		    ((sink_hdr_support(vinfo) & HDR_SUPPORT) &&
		     !vinfo_lcd_support())) {
			/* OSD convert to HDR to match HDR video */
			/* osd eotf lut 709 */
			if (get_hdr_type() & HLG_FLAG) {
				set_vpp_lut(VPP_LUT_OSD_EOTF,
					    osd_eotf_33_sdr2hlg_mapping, /* R */
					    osd_eotf_33_sdr2hlg_mapping, /* G */
					    osd_eotf_33_sdr2hlg_mapping, /* B */
					    CSC_ON);
			} else {
				if (is_hdr_cfg_osd_100() == 1) {
					ptable =
					osd_eotf_33_709_mapping_100;
					set_vpp_lut(VPP_LUT_OSD_EOTF,
						    ptable,
						    ptable,
						    ptable,
						    CSC_ON);
				} else if (is_hdr_cfg_osd_100() == 2) {
					ptable =
					osd_eotf_33_709_mapping_290;
					set_vpp_lut(VPP_LUT_OSD_EOTF,
						    ptable,
						    ptable,
						    ptable,
						    CSC_ON);
				} else if (is_hdr_cfg_osd_100() == 3) {
					ptable =
					osd_eotf_33_709_mapping_330;
					set_vpp_lut(VPP_LUT_OSD_EOTF,
						    ptable,
						    ptable,
						    ptable,
						    CSC_ON);
				} else {
					set_vpp_lut(VPP_LUT_OSD_EOTF,
						    osd_eotf_33_709_mapping,
						    osd_eotf_33_709_mapping,
						    osd_eotf_33_709_mapping,
						    CSC_ON);
				}
			}
			/* osd eotf matrix 709->2020 */
			if (master_info->present_flag & 1) {
				pr_csc(1,
				       "\tMaster_display_colour available.\n");
				print_primaries_info(master_info);
				prepare_customer_matrix(&bt2020_primaries,
							&bt2020_white_point,
							vinfo, &osd_m, 1);
			} else {
				pr_csc(1, "\tNo master_display_colour.\n");
				prepare_customer_matrix(&bt2020_primaries,
							&bt2020_white_point,
							vinfo, &osd_m, 1);
			}
			osd_mtx[EOTF_COEFF_SIZE - 1] = osd_m.right_shift;
			for (i = 0; i < 3; i++)
				for (j = 0; j < 3; j++) {
					if (osd_m.matrix[i][j] & 0x1000) {
						osd_mtx[i * 3 + j] =
						(~osd_m.matrix[i][j]) & 0xfff;
						osd_mtx[i * 3 + j] =
						-(1 + osd_mtx[i * 3 + j]);
					} else {
						osd_mtx[i * 3 + j] =
							osd_m.matrix[i][j];
					}
				}
			set_vpp_matrix(VPP_MATRIX_OSD_EOTF,
				       osd_mtx,
				       CSC_ON);

			/* osd oetf lut 2084 */
			if (get_hdr_type() & HLG_FLAG) {
				set_vpp_lut(VPP_LUT_OSD_OETF,
					    osd_oetf_41_sdr2hlg_mapping,
					    osd_oetf_41_sdr2hlg_mapping,
					    osd_oetf_41_sdr2hlg_mapping,
					    CSC_ON);
			} else {
				if (is_hdr_cfg_osd_100() == 1) {
					ptable =
					osd_oetf_41_2084_mapping_100;
					set_vpp_lut(VPP_LUT_OSD_OETF,
						    ptable,
						    ptable,
						    ptable,
						    CSC_ON);
				} else if (is_hdr_cfg_osd_100() == 2) {
					ptable =
					osd_oetf_41_2084_mapping_290;
					set_vpp_lut(VPP_LUT_OSD_OETF,
						    ptable,
						    ptable,
						    ptable,
						    CSC_ON);
				} else if (is_hdr_cfg_osd_100() == 3) {
					ptable =
					osd_oetf_41_2084_mapping_330;
					set_vpp_lut(VPP_LUT_OSD_OETF,
						    ptable,
						    ptable,
						    ptable,
						    CSC_ON);
				} else {
					set_vpp_lut(VPP_LUT_OSD_OETF,
						    osd_oetf_41_2084_mapping,
						    osd_oetf_41_2084_mapping,
						    osd_oetf_41_2084_mapping,
						    CSC_ON);
				}
			}
			/* osd matrix RGB2020 to YUV2020 limit */
			set_vpp_matrix(VPP_MATRIX_OSD,
				       RGB2020_to_YUV2020l_coeff,
				       CSC_ON);
		} else {
			/* OSD convert to 709 limited to match SDR video */
			/* eotf lut bypass */
			set_vpp_lut(VPP_LUT_OSD_EOTF,
				    eotf_33_linear_mapping, /* R */
				    eotf_33_linear_mapping, /* G */
				    eotf_33_linear_mapping, /* B */
				    CSC_OFF);

			/* eotf matrix bypass */
			set_vpp_matrix(VPP_MATRIX_OSD_EOTF,
				       eotf_bypass_coeff,
				       CSC_OFF);

			/* oetf lut bypass */
			set_vpp_lut(VPP_LUT_OSD_OETF,
				    oetf_41_linear_mapping, /* R */
				    oetf_41_linear_mapping, /* G */
				    oetf_41_linear_mapping, /* B */
				    CSC_OFF);

			/* osd matrix RGB709 to YUV709 limit/full */
			if (range_control)
				set_vpp_matrix(VPP_MATRIX_OSD,
					       RGB709_to_YUV709_coeff,
					       CSC_ON);	/* use full range */
			else
				set_vpp_matrix(VPP_MATRIX_OSD,
					       RGB709_to_YUV709l_coeff,
					       CSC_ON);	/* use limit range */
		}

		/************** VIDEO **************/
		/* vd1 matrix: bypass */
		if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) {
			set_vpp_matrix(VPP_MATRIX_VD1,
				       bypass_coeff,
				       CSC_OFF);/* limit->limit range */
		} else {
			if (vinfo_lcd_support()) {
				if (signal_range == 0) {/* limit range */
					if (csc_type == VPP_MATRIX_YUV601_RGB) {
						pmatrix =
						range_control ?
						YUV601l_to_YUV709f_coeff :
						YUV601l_to_YUV709l_coeff;
						set_vpp_matrix(VPP_MATRIX_VD1,
							       pmatrix,
							       CSC_ON);
					} else {
						pmatrix =
						range_control ?
						YUV709l_to_YUV709f_coeff :
						bypass_coeff;
						set_vpp_matrix(VPP_MATRIX_VD1,
							       pmatrix,
							       CSC_ON);
					}
				} else {
					if (csc_type == VPP_MATRIX_YUV601_RGB) {
						pmatrix =
						range_control ?
						YUV601f_to_YUV709f_coeff :
						YUV601f_to_YUV709l_coeff;
						set_vpp_matrix(VPP_MATRIX_VD1,
							       pmatrix,
							       CSC_ON);
					} else {
						pmatrix =
						range_control ?
						bypass_coeff :
						YUV709f_to_YUV709l_coeff;
						set_vpp_matrix(VPP_MATRIX_VD1,
							       pmatrix,
							       CSC_ON);
					}
				}
			} else {
				/*default limit range */
				if (vd1_mtx_sel == VPP_MATRIX_NULL)
					set_vpp_matrix(VPP_MATRIX_VD1,
						       bypass_coeff,
						       CSC_OFF);
				else if (vd1_mtx_sel ==
					VPP_MATRIX_YUV601L_YUV709L)
					set_vpp_matrix(VPP_MATRIX_VD1,
						       YUV601l_to_YUV709l_coeff,
						       CSC_ON);
				else if (vd1_mtx_sel ==
					VPP_MATRIX_YUV709L_YUV601L)
					set_vpp_matrix(VPP_MATRIX_VD1,
						       YUV709l_to_YUV601l_coeff,
						       CSC_ON);
			}
		}

		/* post matrix bypass */
		if (!vinfo_lcd_support()) {
			/* yuv2rgb for eye protect mode */
			set_vpp_matrix(VPP_MATRIX_POST,
				       bypass_coeff,
				       CSC_OFF);
		} else {/* matrix yuv2rgb for LCD */
			if (range_control) {
				pmatrix = YUV709f_to_RGB709_coeff;
				set_vpp_matrix(VPP_MATRIX_POST,
					       pmatrix,
					       CSC_ON);
			} else {
				pmatrix = YUV709l_to_RGB709_coeff;
				set_vpp_matrix(VPP_MATRIX_POST,
					       pmatrix,
					       CSC_ON);
			}
		}
		/* xvycc inv lut */
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
		if (sdr_process_mode[vd_path] &&
		    csc_type < VPP_MATRIX_BT2020YUV_BT2020RGB &&
		    ((get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) ||
		    (get_cpu_type() == MESON_CPU_MAJOR_ID_TXL))) {
			set_vpp_lut(VPP_LUT_INV_EOTF,
				    NULL,
				    NULL,
				    NULL,
				    CSC_ON);
		} else {
#else
		{
#endif
			set_vpp_lut(VPP_LUT_INV_EOTF,
				    NULL,
				    NULL,
				    NULL,
				    CSC_OFF);
		}
		/* eotf lut bypass */
		set_vpp_lut(VPP_LUT_EOTF,
			    NULL, /* R */
			    NULL, /* G */
			    NULL, /* B */
			    CSC_OFF);

		/* eotf matrix bypass */
		set_vpp_matrix(VPP_MATRIX_EOTF,
			       eotf_bypass_coeff,
			       CSC_OFF);

		/* oetf lut bypass */
		set_vpp_lut(VPP_LUT_OETF,
			    NULL,
			    NULL,
			    NULL,
			    CSC_OFF);

		/* xvycc matrix full2limit or bypass */
		if (!vinfo_lcd_support()) {
			if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) {
				set_vpp_matrix(VPP_MATRIX_XVYCC,
					       bypass_coeff,
					       CSC_OFF);
			} else {
				if (range_control) {
					pmatrix = YUV709f_to_YUV709l_coeff;
					set_vpp_matrix(VPP_MATRIX_XVYCC,
						       pmatrix,
						       CSC_ON);
				} else {
					pmatrix = bypass_coeff;
					set_vpp_matrix(VPP_MATRIX_XVYCC,
						       pmatrix,
						       CSC_OFF);
				}
			}
		}
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
	} else {
		/* OSD */
		/* keep RGB */

		/* VIDEO */
		if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) {
			/* vd1 matrix: convert YUV to RGB */
			csc_type = VPP_MATRIX_YUV709_RGB;
		}
		/* vd1 matrix on to convert YUV to RGB */
		vpp_set_matrix(VPP_MATRIX_VD1, CSC_ON,
			       csc_type, NULL);
		/* post matrix off */
		vpp_set_matrix(VPP_MATRIX_POST, CSC_OFF,
			       csc_type, NULL);
		/* xvycc lut off */
		load_knee_lut(CSC_OFF);
		/* xvycc inv lut */

		if (sdr_process_mode[vd_path])
			set_vpp_lut(VPP_LUT_INV_EOTF,
				    NULL,
				    NULL,
				    NULL,
				    CSC_ON);
		else
			set_vpp_lut(VPP_LUT_INV_EOTF,
				    NULL,
				    NULL,
				    NULL,
				    CSC_OFF);

		vecm_latch_flag |= FLAG_VADJ1_BRI;
		hdr_process_pq_enable(1);
		/* if GXTVBB HDMI output(YUV) case */
		/* xvyccc matrix3: RGB to YUV */
		/* other cases */
		/* xvyccc matrix3: bypass */
		if (!vinfo_lcd_support() &&
		    get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) {
			vpp_set_matrix3(CSC_ON, VPP_MATRIX_RGB_YUV709);
		} else {
			vpp_set_matrix3(CSC_OFF, VPP_MATRIX_NULL);
		}
#endif
	}
	/*vpp matrix mux write*/
	vpp_set_mtx_en_write();
}

static void set_bt2020csc_process(enum vpp_matrix_csc_e csc_type,
				  struct vinfo_s *vinfo,
				  struct vframe_master_display_colour_s *master_info,
				  enum vd_path_e vd_path)
{
	struct matrix_s osd_m = {
		{0, 0, 0},
		{
			{0x505, 0x2A2, 0x059},
			{0x08E, 0x75B, 0x017},
			{0x022, 0x0B4, 0x72A},
		},
		{0, 0, 0},
		1
	};
	int osd_mtx[EOTF_COEFF_SIZE] = {
		EOTF_COEFF_NORM(0.627441),	EOTF_COEFF_NORM(0.329285),
		EOTF_COEFF_NORM(0.043274),
		EOTF_COEFF_NORM(0.069092),	EOTF_COEFF_NORM(0.919556),
		EOTF_COEFF_NORM(0.011322),
		EOTF_COEFF_NORM(0.016418),	EOTF_COEFF_NORM(0.088058),
		EOTF_COEFF_NORM(0.895554),
		EOTF_COEFF_RIGHTSHIFT
	};
	int i, j;
	int *pmatrix;
	u32 (*p_prim)[3][2];
	u32 (*p_wp)[2];

	/*vpp matrix mux read*/
	vpp_set_mtx_en_read();
	if (get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB) {
		/************** OSD ***************/
		/* RGB to YUV */
		/* not using old RGB2YUV convert HW */
		/* use new 10bit OSD convert matrix */
		/* WRITE_VPP_REG_BITS*/
		/*(VIU_OSD1_BLK0_CFG_W0,0, 7, 1);*/
		if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB &&
		    ((sink_hdr_support(vinfo) & HDR_SUPPORT) &&
		     !vinfo_lcd_support())) {
			/* OSD convert to HDR to match HDR video */
			/* osd eotf lut 709 */
			if (get_hdr_type() & HLG_FLAG)
				set_vpp_lut(VPP_LUT_OSD_EOTF,
					    osd_eotf_33_sdr2hlg_mapping,
					    osd_eotf_33_sdr2hlg_mapping,
					    osd_eotf_33_sdr2hlg_mapping,
					    CSC_ON);
			else
				set_vpp_lut(VPP_LUT_OSD_EOTF,
					    osd_eotf_33_709_mapping,
					    osd_eotf_33_709_mapping,
					    osd_eotf_33_709_mapping,
					    CSC_ON);

			/* osd eotf matrix 709->2020 */
			if (master_info->present_flag & 1) {
				pr_csc(1,
				       "\tMaster_display_colour present.\n");
				print_primaries_info(master_info);
				p_prim = &master_info->primaries;
				p_wp = &master_info->white_point;
				prepare_customer_matrix(p_prim,
							p_wp,
							vinfo, &osd_m, 1);
			} else {
				pr_csc(1, "\tNo master_display_colour.\n");
				p_prim = &bt2020_primaries;
				p_wp = &bt2020_white_point;
				prepare_customer_matrix(p_prim,
							p_wp,
							vinfo, &osd_m, 1);
			}
			osd_mtx[EOTF_COEFF_SIZE - 1] = osd_m.right_shift;
			for (i = 0; i < 3; i++)
				for (j = 0; j < 3; j++) {
					if (osd_m.matrix[i][j] & 0x1000) {
						osd_mtx[i * 3 + j] =
						(~osd_m.matrix[i][j]) & 0xfff;
						osd_mtx[i * 3 + j] =
						-(1 + osd_mtx[i * 3 + j]);
					} else {
						osd_mtx[i * 3 + j] =
							osd_m.matrix[i][j];
					}
				}
			set_vpp_matrix(VPP_MATRIX_OSD_EOTF,
				       osd_mtx,
				       CSC_ON);

			/* osd oetf lut 2084 */
			if (get_hdr_type() & HLG_FLAG)
				set_vpp_lut(VPP_LUT_OSD_OETF,
					    osd_oetf_41_sdr2hlg_mapping,
					    osd_oetf_41_sdr2hlg_mapping,
					    osd_oetf_41_sdr2hlg_mapping,
					    CSC_ON);
			else
				set_vpp_lut(VPP_LUT_OSD_OETF,
					    osd_oetf_41_2084_mapping,
					    osd_oetf_41_2084_mapping,
					    osd_oetf_41_2084_mapping,
					    CSC_ON);

			/* osd matrix RGB2020 to YUV2020 limit */
			set_vpp_matrix(VPP_MATRIX_OSD,
				       RGB2020_to_YUV2020l_coeff,
				       CSC_ON);
		} else {
			/* OSD convert to 709 limited to match SDR video */
			/* eotf lut bypass */
			set_vpp_lut(VPP_LUT_OSD_EOTF,
				    eotf_33_linear_mapping, /* R */
				    eotf_33_linear_mapping, /* G */
				    eotf_33_linear_mapping, /* B */
				    CSC_OFF);

			/* eotf matrix bypass */
			set_vpp_matrix(VPP_MATRIX_OSD_EOTF,
				       eotf_bypass_coeff,
				       CSC_OFF);

			/* oetf lut bypass */
			set_vpp_lut(VPP_LUT_OSD_OETF,
				    oetf_41_linear_mapping, /* R */
				    oetf_41_linear_mapping, /* G */
				    oetf_41_linear_mapping, /* B */
				    CSC_OFF);

			/* osd matrix RGB709 to YUV709 limit/full */
			if (range_control)
				set_vpp_matrix(VPP_MATRIX_OSD,
					       RGB709_to_YUV709_coeff,
					       CSC_ON);	/* use full range */
			else
				set_vpp_matrix(VPP_MATRIX_OSD,
					       RGB709_to_YUV709l_coeff,
					       CSC_ON);	/* use limit range */
		}

		/************** VIDEO **************/
		/* vd1 matrix: bypass */
		if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) {
			set_vpp_matrix(VPP_MATRIX_VD1,
				       bypass_coeff,
				       CSC_OFF);/* limit->limit range */
		} else {
			if (vinfo_lcd_support()) {
				if (signal_range == 0) {/* limit range */
					if (csc_type == VPP_MATRIX_YUV601_RGB) {
						pmatrix =
						range_control ?
						YUV601l_to_YUV709f_coeff :
						YUV601l_to_YUV709l_coeff;
						set_vpp_matrix(VPP_MATRIX_VD1,
							       pmatrix,
							       CSC_ON);
					} else {
						pmatrix =
						range_control ?
						YUV709l_to_YUV709f_coeff :
						bypass_coeff;
						set_vpp_matrix(VPP_MATRIX_VD1,
							       pmatrix,
							       CSC_ON);
					}
				} else {
					if (csc_type == VPP_MATRIX_YUV601_RGB) {
						pmatrix =
						range_control ?
						YUV601f_to_YUV709f_coeff :
						YUV601f_to_YUV709l_coeff;
						set_vpp_matrix(VPP_MATRIX_VD1,
							       pmatrix,
							       CSC_ON);
					} else {
						pmatrix =
						range_control ?
						bypass_coeff :
						YUV709f_to_YUV709l_coeff;
						set_vpp_matrix(VPP_MATRIX_VD1,
							       pmatrix,
							       CSC_ON);
					}
				}
			} else {
				/*default limit range */
				if (vd1_mtx_sel == VPP_MATRIX_NULL)
					set_vpp_matrix(VPP_MATRIX_VD1,
						       bypass_coeff,
						       CSC_OFF);
				else if (vd1_mtx_sel ==
					VPP_MATRIX_YUV601L_YUV709L)
					set_vpp_matrix(VPP_MATRIX_VD1,
						       YUV601l_to_YUV709l_coeff,
						       CSC_ON);
				else if (vd1_mtx_sel ==
					VPP_MATRIX_YUV709L_YUV601L)
					set_vpp_matrix(VPP_MATRIX_VD1,
						       YUV709l_to_YUV601l_coeff,
						       CSC_ON);
			}
		}

		/* post matrix bypass */
		if (!vinfo_lcd_support()) {
			/* yuv2rgb for eye protect mode */
			set_vpp_matrix(VPP_MATRIX_POST,
				       YUV709l_to_YUV2020_coeff,
				       CSC_ON);
		} else {/* matrix yuv2rgb for LCD */
			if (range_control)
				set_vpp_matrix(VPP_MATRIX_POST,
					       YUV709f_to_RGB709_coeff,
					       CSC_ON);
			else
				set_vpp_matrix(VPP_MATRIX_POST,
					       YUV709l_to_RGB709_coeff,
					       CSC_ON);
		}
		/* xvycc inv lut */
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
		if (sdr_process_mode[vd_path] &&
		    csc_type < VPP_MATRIX_BT2020YUV_BT2020RGB &&
		    (get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB ||
		     get_cpu_type() == MESON_CPU_MAJOR_ID_TXL)) {
			set_vpp_lut(VPP_LUT_INV_EOTF,
				    NULL,
				    NULL,
				    NULL,
				    CSC_ON);
		} else {
#else
		{
#endif
			set_vpp_lut(VPP_LUT_INV_EOTF,
				    NULL,
				    NULL,
				    NULL,
				    CSC_OFF);
		}
		/* eotf lut bypass */
		set_vpp_lut(VPP_LUT_EOTF,
			    NULL, /* R */
			    NULL, /* G */
			    NULL, /* B */
			    CSC_OFF);

		/* eotf matrix bypass */
		set_vpp_matrix(VPP_MATRIX_EOTF,
			       bypass_coeff,
			       CSC_OFF);

		/* oetf lut bypass */
		set_vpp_lut(VPP_LUT_OETF,
			    NULL,
			    NULL,
			    NULL,
			    CSC_OFF);

		/* xvycc matrix full2limit or bypass */
		if (!vinfo_lcd_support()) {
			if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB)
				set_vpp_matrix(VPP_MATRIX_XVYCC,
					       bypass_coeff,
					       CSC_ON);
			else
				set_vpp_matrix(VPP_MATRIX_XVYCC,
					       bypass_coeff,
					       CSC_OFF);
		}
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
	} else {
		/* OSD */
		/* keep RGB */

		/* VIDEO */
		if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) {
			/* vd1 matrix: convert YUV to RGB */
			csc_type = VPP_MATRIX_YUV709_RGB;
		}
		/* vd1 matrix on to convert YUV to RGB */
		vpp_set_matrix(VPP_MATRIX_VD1, CSC_ON,
			       csc_type, NULL);
		/* post matrix off */
		vpp_set_matrix(VPP_MATRIX_POST, CSC_OFF,
			       csc_type, NULL);
		/* xvycc lut off */
		load_knee_lut(CSC_OFF);
		/* xvycc inv lut */

		if (sdr_process_mode[vd_path])
			set_vpp_lut(VPP_LUT_INV_EOTF,
				    NULL,
				    NULL,
				    NULL,
				    CSC_ON);
		else
			set_vpp_lut(VPP_LUT_INV_EOTF,
				    NULL,
				    NULL,
				    NULL,
				    CSC_OFF);

		vecm_latch_flag |= FLAG_VADJ1_BRI;
		hdr_process_pq_enable(1);
		/* if GXTVBB HDMI output(YUV) case */
		/* xvyccc matrix3: RGB to YUV */
		/* other cases */
		/* xvyccc matrix3: bypass */
		if (!vinfo_lcd_support() &&
		    get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) {
			vpp_set_matrix3(CSC_ON, VPP_MATRIX_RGB_YUV709);
		} else {
			vpp_set_matrix3(CSC_OFF, VPP_MATRIX_NULL);
		}
#endif
	}
	/*vpp matrix mux write*/
	vpp_set_mtx_en_write();
}

static void hlg_hdr_process(enum vpp_matrix_csc_e csc_type,
			    struct vinfo_s *vinfo,
			    struct vframe_master_display_colour_s
			    *master_info,
			    enum vd_path_e vd_path,
			    enum vpp_index_e vpp_index)
{
	struct matrix_s osd_m = {
		{0, 0, 0},
		{
			{0x505, 0x2A2, 0x059},
			{0x08E, 0x75B, 0x017},
			{0x022, 0x0B4, 0x72A},
		},
		{0, 0, 0},
		1
	};
	int osd_mtx[EOTF_COEFF_SIZE] = {
		EOTF_COEFF_NORM(0.627441),	EOTF_COEFF_NORM(0.329285),
		EOTF_COEFF_NORM(0.043274),
		EOTF_COEFF_NORM(0.069092),	EOTF_COEFF_NORM(0.919556),
		EOTF_COEFF_NORM(0.011322),
		EOTF_COEFF_NORM(0.016418),	EOTF_COEFF_NORM(0.088058),
		EOTF_COEFF_NORM(0.895554),
		EOTF_COEFF_RIGHTSHIFT
	};
	int i, j;
	int *pmatrix;
	u32 (*p_prim)[3][2];
	u32 (*p_wp)[2];
	int s5_silce_mode = get_s5_slice_mode();

	if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
		if (vd_path == VD1_PATH) {
			if (s5_silce_mode == VD1_1SLICE) {
				hdr_func(VD1_HDR, HLG_HDR | hdr_ex, vinfo, NULL, vpp_index);
			} else if (s5_silce_mode == VD1_2SLICE) {
				hdr_func(VD1_HDR, HLG_HDR | hdr_ex, vinfo, NULL, vpp_index);
				hdr_func(S5_VD1_SLICE1, HLG_HDR | hdr_ex, vinfo, NULL, vpp_index);
			} else if (s5_silce_mode == VD1_4SLICE) {
				hdr_func(VD1_HDR, HLG_HDR | hdr_ex, vinfo, NULL, vpp_index);
				hdr_func(S5_VD1_SLICE1, HLG_HDR | hdr_ex, vinfo, NULL, vpp_index);
				hdr_func(S5_VD1_SLICE2, HLG_HDR | hdr_ex, vinfo, NULL, vpp_index);
				hdr_func(S5_VD1_SLICE3, HLG_HDR | hdr_ex, vinfo, NULL, vpp_index);
			}
		} else if (vd_path == VD2_PATH) {
			hdr_func(VD2_HDR, HLG_HDR | hdr_ex, vinfo, NULL, vpp_index);
		} else if (vd_path == VD3_PATH) {
			hdr_func(VD3_HDR, HLG_HDR | hdr_ex, vinfo, NULL, vpp_index);
		}
		hdr_func(OSD1_HDR, SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
		hdr_func(OSD2_HDR, SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
		hdr_func(OSD3_HDR, SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
		return;
	}
	/*vpp matrix mux read*/
	vpp_set_mtx_en_read();
	if ((get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB) &&
	    (csc_en & 0x2)) {
		/************** OSD ***************/
		/* RGB to YUV */
		/* not using old RGB2YUV convert HW */
		/* use new 10bit OSD convert matrix */
		/* WRITE_VPP_REG_BITS(VIU_OSD1_BLK0_CFG_W0, */
		/* 0, 7, 1); */
		if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB &&
		    ((sink_hdr_support(vinfo) & HDR_SUPPORT) &&
		     !vinfo_lcd_support())) {
			/* OSD convert to HDR to match HDR video */
			/* osd eotf lut 709 */
			if (get_hdr_type() & HLG_FLAG)
				set_vpp_lut(VPP_LUT_OSD_EOTF,
					    osd_eotf_33_sdr2hlg_mapping,
					    osd_eotf_33_sdr2hlg_mapping,
					    osd_eotf_33_sdr2hlg_mapping,
					    CSC_ON);
			else
				set_vpp_lut(VPP_LUT_OSD_EOTF,
					    osd_eotf_33_709_mapping,
					    osd_eotf_33_709_mapping,
					    osd_eotf_33_709_mapping,
					    CSC_ON);

			/* osd eotf matrix 709->2020 */
			if (master_info->present_flag & 1) {
				pr_csc(1,
				       "\tMaster_display_colour available.\n");
				print_primaries_info(master_info);
				p_prim = &master_info->primaries;
				p_wp = &master_info->white_point;
				prepare_customer_matrix(p_prim,
							p_wp,
							vinfo, &osd_m, 1);
			} else {
				pr_csc(1, "\tNo master_display_colour.\n");
				p_prim = &bt2020_primaries;
				p_wp = &bt2020_white_point;
				prepare_customer_matrix(p_prim,
							p_wp,
							vinfo, &osd_m, 1);
			}
			osd_mtx[EOTF_COEFF_SIZE - 1] = osd_m.right_shift;
			for (i = 0; i < 3; i++)
				for (j = 0; j < 3; j++) {
					if (osd_m.matrix[i][j] & 0x1000) {
						osd_mtx[i * 3 + j] =
						(~osd_m.matrix[i][j]) & 0xfff;
						osd_mtx[i * 3 + j] =
						-(1 + osd_mtx[i * 3 + j]);
					} else {
						osd_mtx[i * 3 + j] =
							osd_m.matrix[i][j];
					}
				}
			set_vpp_matrix(VPP_MATRIX_OSD_EOTF,
				       osd_mtx,
				       CSC_ON);

			/* osd oetf lut 2084 */
			if (get_hdr_type() & HLG_FLAG)
				set_vpp_lut(VPP_LUT_OSD_OETF,
					    osd_oetf_41_sdr2hlg_mapping,
					    osd_oetf_41_sdr2hlg_mapping,
					    osd_oetf_41_sdr2hlg_mapping,
					    CSC_ON);
			else
				set_vpp_lut(VPP_LUT_OSD_OETF,
					    osd_oetf_41_2084_mapping,
					    osd_oetf_41_2084_mapping,
					    osd_oetf_41_2084_mapping,
					    CSC_ON);

			/* osd matrix RGB2020 to YUV2020 limit */
			set_vpp_matrix(VPP_MATRIX_OSD,
				       RGB2020_to_YUV2020l_coeff,
				       CSC_ON);
		} else {
			/* OSD convert to 709 limited to match SDR video */
			/* eotf lut bypass */
			set_vpp_lut(VPP_LUT_OSD_EOTF,
				    eotf_33_linear_mapping, /* R */
				    eotf_33_linear_mapping, /* G */
				    eotf_33_linear_mapping, /* B */
				    CSC_OFF);

			/* eotf matrix bypass */
			set_vpp_matrix(VPP_MATRIX_OSD_EOTF,
				       eotf_bypass_coeff,
				       CSC_OFF);

			/* oetf lut bypass */
			set_vpp_lut(VPP_LUT_OSD_OETF,
				    oetf_41_linear_mapping, /* R */
				    oetf_41_linear_mapping, /* G */
				    oetf_41_linear_mapping, /* B */
				    CSC_OFF);

			/* osd matrix RGB709 to YUV709 limit/full */
			if (range_control)
				set_vpp_matrix(VPP_MATRIX_OSD,
					       RGB709_to_YUV709_coeff,
					       CSC_ON);/* use full range */
			else
				set_vpp_matrix(VPP_MATRIX_OSD,
					       RGB709_to_YUV709l_coeff,
					       CSC_ON);/* use limit range */
		}
	}
	/************** VIDEO **************/
	if ((get_cpu_type() > MESON_CPU_MAJOR_ID_GXTVBB) &&
	    (csc_en & 0x4)) {
		/* vd1 matrix: bypass */
		if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) {
			set_vpp_matrix(VPP_MATRIX_VD1,
				       bypass_coeff,
				       CSC_OFF);/* limit->limit range */
		} else {
			if (signal_range == 0) {
				set_vpp_matrix(VPP_MATRIX_VD1,
					       bypass_coeff,
					       CSC_OFF);
				/* limit->limit range */
			} else {
				pmatrix = YUV709f_to_YUV709l_coeff;
				set_vpp_matrix(VPP_MATRIX_VD1,
					       pmatrix,
					       CSC_ON);
			}
		}
		/*eo oo oe*/
		int_lut_sel[0] |= INVLUT_HLG;
		set_vpp_lut(VPP_LUT_INV_EOTF,
			    int_lut_sel,
			    int_lut_sel,
			    int_lut_sel,
			    CSC_ON);

		/* post matrix bypass */
		if (!vinfo_lcd_support())
			/* yuv2rgb for eye protect mode */
			set_vpp_matrix(VPP_MATRIX_POST,
				       YUV2020l_to_RGB2020_coeff,
				       CSC_ON);
		else /* matrix yuv2rgb for LCD */
			set_vpp_matrix(VPP_MATRIX_POST,
				       YUV709l_to_RGB709_coeff,
				       CSC_ON);

		/* eotf lut bypass */
		set_vpp_lut(VPP_LUT_EOTF,
			    eotf_33_hlg_mapping, /* R */
			    eotf_33_hlg_mapping, /* G */
			    eotf_33_hlg_mapping, /* B */
			    CSC_ON);

		/* eotf matrix bypass */
		set_vpp_matrix(VPP_MATRIX_EOTF,
			       eotf_bypass_coeff,
			       CSC_ON);

		/* oetf lut bypass */
		set_vpp_lut(VPP_LUT_OETF,
			    oetf_289_2084_mapping,
			    oetf_289_2084_mapping,
			    oetf_289_2084_mapping,
			    CSC_ON);

		/* xvycc matrix full2limit or bypass */
		if (!vinfo_lcd_support()) {
			if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) {
				set_vpp_matrix(VPP_MATRIX_XVYCC,
					       RGB2020_to_YUV2020l_coeff,
					       CSC_ON);
			} else {
				if (range_control) {
					pmatrix = YUV709f_to_YUV709l_coeff;
					set_vpp_matrix(VPP_MATRIX_XVYCC,
						       pmatrix,
						       CSC_ON);
				} else {
					set_vpp_matrix(VPP_MATRIX_XVYCC,
						       bypass_coeff,
						       CSC_OFF);
				}
			}
		}
	} else {
		/* OSD */
		/* keep RGB */

		/* VIDEO */
		if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) {
			/* vd1 matrix: convert YUV to RGB */
			csc_type = VPP_MATRIX_YUV709_RGB;
		}
		/* vd1 matrix on to convert YUV to RGB */
		vpp_set_matrix(VPP_MATRIX_VD1, CSC_ON,
			       csc_type, NULL);
		/* post matrix off */
		vpp_set_matrix(VPP_MATRIX_POST, CSC_OFF,
			       csc_type, NULL);
		/* xvycc lut off */
		load_knee_lut(CSC_OFF);
		/* xvycc inv lut */

		if (sdr_process_mode[vd_path])
			set_vpp_lut(VPP_LUT_INV_EOTF,
				    NULL,
				    NULL,
				    NULL,
				    CSC_ON);
		else
			set_vpp_lut(VPP_LUT_INV_EOTF,
				    NULL,
				    NULL,
				    NULL,
				    CSC_OFF);

		vecm_latch_flag |= FLAG_VADJ1_BRI;
		hdr_process_pq_enable(1);
		/* if GXTVBB HDMI output(YUV) case */
		/* xvyccc matrix3: RGB to YUV */
		/* other cases */
		/* xvyccc matrix3: bypass */
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
		if (!vinfo_lcd_support() &&
		    get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) {
			vpp_set_matrix3(CSC_ON, VPP_MATRIX_RGB_YUV709);
		} else {
#else
		{
#endif
			vpp_set_matrix3(CSC_OFF, VPP_MATRIX_NULL);
		}
	}
	/*vpp matrix mux write*/
	vpp_set_mtx_en_write();
}

static void sdr_hdr_process(enum vpp_matrix_csc_e csc_type,
			    struct vinfo_s *vinfo,
			    struct vframe_master_display_colour_s
			    *master_info,
			    enum vd_path_e vd_path,
			    enum hdr_type_e *source_type,
			    enum vpp_index_e vpp_index)
{
	int s5_silce_mode = get_s5_slice_mode();

	if (!vinfo_lcd_support()) {
		if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
			if (vd_path == VD1_PATH) {
				if (s5_silce_mode == VD1_1SLICE) {
					hdr_func(VD1_HDR,
						 SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
				} else if (s5_silce_mode == VD1_2SLICE) {
					hdr_func(VD1_HDR,
						SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
					hdr_func(S5_VD1_SLICE1,
						SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
				} else if (s5_silce_mode == VD1_4SLICE) {
					hdr_func(VD1_HDR,
						SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
					hdr_func(S5_VD1_SLICE1,
						SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
					hdr_func(S5_VD1_SLICE2,
						SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
					hdr_func(S5_VD1_SLICE3,
						SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
				}
			}
			else if (vd_path == VD2_PATH)
				hdr_func(VD2_HDR,
					 SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
			else if (vd_path == VD3_PATH)
				hdr_func(VD3_HDR,
					 SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
			hdr_func(OSD1_HDR, SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
			hdr_func(OSD2_HDR, SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
			hdr_func(OSD3_HDR, SDR_HDR | hdr_ex, vinfo, NULL, vpp_index);
			return;
		}
		/*vpp matrix mux read*/
		vpp_set_mtx_en_read();
		/* OSD convert to 709 limited to match SDR video */
		/* eotf lut bypass */
		set_vpp_lut(VPP_LUT_OSD_EOTF,
			    eotf_33_linear_mapping, /* R */
			    eotf_33_linear_mapping, /* G */
			    eotf_33_linear_mapping, /* B */
			    CSC_OFF);

		/* eotf matrix bypass */
		set_vpp_matrix(VPP_MATRIX_OSD_EOTF,
			       eotf_bypass_coeff,
			       CSC_OFF);

		/* oetf lut bypass */
		set_vpp_lut(VPP_LUT_OSD_OETF,
			    oetf_41_linear_mapping, /* R */
			    oetf_41_linear_mapping, /* G */
			    oetf_41_linear_mapping, /* B */
			    CSC_OFF);

		/* osd matrix RGB709 to YUV709 limit/full */
		if (range_control)
			set_vpp_matrix(VPP_MATRIX_OSD,
				       RGB709_to_YUV709_coeff,
				       CSC_ON);/* use full range */
		else
			set_vpp_matrix(VPP_MATRIX_OSD,
				       RGB709_to_YUV709l_coeff,
				       CSC_ON);/* use limit range */

		/************** VIDEO **************/
		/* convert SDR Video to HDR */
		if (range_control) {
			if (signal_range == 0) /* limit range */
				set_vpp_matrix(VPP_MATRIX_VD1,
					       YUV709l_to_YUV709f_coeff,
					       CSC_ON);/* limit->full range */
			else
				set_vpp_matrix(VPP_MATRIX_VD1,
					       bypass_coeff,
					       CSC_OFF);/* full->full range */
		} else {
			if (signal_range == 0) /* limit range */
				set_vpp_matrix(VPP_MATRIX_VD1,
					       bypass_coeff,
					       CSC_OFF);/* limit->limit range */
			else
				set_vpp_matrix(VPP_MATRIX_VD1,
					       YUV709f_to_YUV709l_coeff,
					       CSC_ON);	/* full->limit range */
		}

		set_vpp_matrix(VPP_MATRIX_POST,
			       YUV709l_to_RGB709_coeff,
			       CSC_ON);

		/* eotf lut bypass */
		set_vpp_lut(VPP_LUT_EOTF,
			    eotf_33_sdr_709_mapping, /* R */
			    eotf_33_sdr_709_mapping, /* G */
			    eotf_33_sdr_709_mapping, /* B */
			    CSC_ON);

		/* eotf matrix bypass */
		set_vpp_matrix(VPP_MATRIX_EOTF,
			       eotf_RGB709_to_RGB2020_coeff,
			       CSC_ON);

		/* oetf lut bypass */
		set_vpp_lut(VPP_LUT_OETF,
			    oetf_sdr_2084_mapping,
			    oetf_sdr_2084_mapping,
			    oetf_sdr_2084_mapping,
			    CSC_ON);

		/* xvycc matrix bypass */
		set_vpp_matrix(VPP_MATRIX_XVYCC,
			       RGB2020_to_YUV2020l_coeff,
			       CSC_ON);
		/*vpp matrix mux write*/
		vpp_set_mtx_en_write();
	} else {
		bypass_hdr_process(csc_type, vinfo,
				   master_info, vd_path, source_type, vpp_index);
	}
}
#endif

static int vpp_eye_protection_process(enum vpp_matrix_csc_e csc_type,
				      struct vinfo_s *vinfo,
				      enum vd_path_e vd_path)
{
	cur_eye_protect_mode = wb_val[0];
	memcpy(&video_rgb_ogo, wb_val,
	       sizeof(struct tcon_rgb_ogo_s));
	ve_ogo_param_update();
	vpp_set_mtx_en_read();
	/* only SDR need switch csc */
	if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB &&
	    hdr_process_mode[vd_path])
		return 0;
	if (csc_type < VPP_MATRIX_BT2020YUV_BT2020RGB &&
	    sdr_process_mode[vd_path])
		return 0;

	if (vinfo_lcd_support())
		return 0;
	/* post matrix bypass */

	if (cur_eye_protect_mode == 0) {
	/* yuv2rgb for eye protect mode */
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
		if (get_cpu_type() == MESON_CPU_MAJOR_ID_G12A)
			mtx_setting(POST2_MTX, MATRIX_YUV709_RGB,
				MTX_OFF);
		else
#endif
			set_vpp_matrix(VPP_MATRIX_POST,
				bypass_coeff,
				CSC_ON);
	} else {/* matrix yuv2rgb for LCD */
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
		if (get_cpu_type() == MESON_CPU_MAJOR_ID_G12A)
			mtx_setting(POST2_MTX, MATRIX_YUV709_RGB,
				MTX_ON);
		else
#endif
			set_vpp_matrix(VPP_MATRIX_POST,
				YUV709l_to_RGB709_coeff,
				CSC_ON);
	}

	/* xvycc matrix bypass */
	if (cur_eye_protect_mode == 1) {
		/*  for eye protect mode */
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
		if (get_cpu_type() == MESON_CPU_MAJOR_ID_G12A) {
			if (video_rgb_ogo_xvy_mtx)
				video_rgb_ogo_xvy_mtx_latch |=
					MTX_RGB2YUVL_RGB_OGO;
		} else {
#else
		{
#endif
			if (video_rgb_ogo_xvy_mtx) {
				video_rgb_ogo_xvy_mtx_latch |=
					MTX_RGB2YUVL_RGB_OGO;
				mtx_en_mux |= XVY_MTX_EN_MASK;
			} else {
				set_vpp_matrix(VPP_MATRIX_XVYCC,
					       RGB709_to_YUV709l_coeff,
					       CSC_ON);
			}
		}
	} else {/* matrix yuv2rgb for LCD */
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
		if (get_cpu_type() == MESON_CPU_MAJOR_ID_G12A)
			mtx_setting(POST_MTX, MATRIX_RGB_YUV709,
				MTX_OFF);
		else
#endif
			set_vpp_matrix(VPP_MATRIX_XVYCC,
				bypass_coeff,
				CSC_ON);
	}

	vpp_set_mtx_en_write();
	return 0;
}

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static void hdr_support_process(struct vinfo_s *vinfo,
	enum vd_path_e vd_path,
	enum vpp_index_e vpp_index)
{
	/*check if hdmitx support hdr10+*/
	tx_hdr10_plus_support = sink_hdr_support(vinfo) & HDRP_SUPPORT;

	/* check hdr support info from Tx or Panel */
	if (hdr_mode == 2) { /* auto */
		/*hdr_support & bit2 is hdr10*/
		/*hdr_support & bit3 is hlg*/
		if ((sink_hdr_support(vinfo) & HDR_SUPPORT) &&
		    (sink_hdr_support(vinfo) & HLG_SUPPORT)) {
			hdr_process_mode[vd_path] = PROC_BYPASS; /* hdr->hdr*/
			hlg_process_mode[vd_path] = PROC_BYPASS; /* hlg->hlg*/
		} else if ((sink_hdr_support(vinfo) & HDR_SUPPORT) &&
			!(sink_hdr_support(vinfo) & HLG_SUPPORT)) {
			hdr_process_mode[vd_path] = PROC_BYPASS; /* hdr->hdr*/
			if (force_pure_hlg[vd_path])
				hlg_process_mode[vd_path] = PROC_BYPASS;
			else  /* hlg->hdr10*/
				hlg_process_mode[vd_path] = PROC_MATCH;
		} else if (!(sink_hdr_support(vinfo) & HDR_SUPPORT) &&
			(sink_hdr_support(vinfo) & HLG_SUPPORT)) {
			hdr_process_mode[vd_path] = PROC_MATCH;
			hlg_process_mode[vd_path] = PROC_BYPASS;
		} else {
			hdr_process_mode[vd_path] = PROC_MATCH;
			hlg_process_mode[vd_path] = PROC_MATCH;
		}

		if (tx_hdr10_plus_support)
			hdr10_plus_process_mode[vd_path] = PROC_BYPASS;
		else
			hdr10_plus_process_mode[vd_path] = PROC_MATCH;
	} else if (hdr_mode == 1) {
		hdr_process_mode[vd_path] = PROC_MATCH;
		hlg_process_mode[vd_path] = PROC_MATCH;
		hdr10_plus_process_mode[vd_path] = PROC_MATCH;
	} else {
		hdr_process_mode[vd_path] = PROC_BYPASS;
		if (sink_hdr_support(vinfo) & HDR_SUPPORT) {
			if (force_pure_hlg[vd_path] ||
			    (sink_hdr_support(vinfo) & HLG_SUPPORT))
				hlg_process_mode[vd_path] = PROC_BYPASS;
			else  /* hlg->hdr10*/
				hlg_process_mode[vd_path] = PROC_MATCH;
		} else {
			hlg_process_mode[vd_path] = PROC_BYPASS;
		}
		hdr10_plus_process_mode[vd_path] = PROC_BYPASS;
	}

	if (sdr_mode == 2) { /* auto */
		if ((sink_hdr_support(vinfo) & HDR_SUPPORT) &&
		    ((cpu_after_eq(MESON_CPU_MAJOR_ID_GXL)) &&
		     !vinfo_lcd_support()))
			/*box sdr->hdr*/
			sdr_process_mode[vd_path] = PROC_SDR_TO_HDR;
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
		else if (vinfo_lcd_support() &&
			 ((get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) ||
			 (get_cpu_type() == MESON_CPU_MAJOR_ID_TXL))) {
			/*tv sdr->hdr*/
			sdr_process_mode[vd_path] = PROC_SDR_TO_HDR;
#endif
		} else {
			/* sdr->sdr*/
			sdr_process_mode[vd_path] = PROC_BYPASS;
		}
	} else {
		/* force sdr->hdr */
		sdr_process_mode[vd_path] = sdr_mode;
	}
}
#endif
static int sink_support_dv(const struct vinfo_s *vinfo)
{
	if (sink_hdr_support(vinfo) & DV_SUPPORT)
		return 1;
	return 0;
}

static int sink_support_hdr(const struct vinfo_s *vinfo)
{
	if (sink_hdr_support(vinfo) & HDR_SUPPORT)
		return 1;
	return 0;
}

static int sink_support_hlg(const struct vinfo_s *vinfo)
{
	if (sink_hdr_support(vinfo) & HLG_SUPPORT)
		return 1;
	return 0;
}

static int sink_support_hdr10_plus(const struct vinfo_s *vinfo)
{
	/* panel output and TL1 and TM2 */
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	if (vinfo_lcd_support() &&
	    ((get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) ||
	    (get_cpu_type() == MESON_CPU_MAJOR_ID_TM2)))
		return 1;
#endif

	/* hdmi */
	if (sink_hdr_support(vinfo) & HDRP_SUPPORT)
		return 1;

	return 0;
}
#endif

bool is_vinfo_available(const struct vinfo_s *vinfo)
{
	if (!vinfo || !vinfo->name)
		return false;
	else
		return strcmp(vinfo->name, "invalid") &&
			strcmp(vinfo->name, "null") &&
			strcmp(vinfo->name, "576cvbs") &&
			strcmp(vinfo->name, "470cvbs");
}
EXPORT_SYMBOL(is_vinfo_available);

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static enum hdr_type_e get_source_type(enum vd_path_e vd_path,
	enum vpp_index_e vpp_index)
{
	struct vinfo_s *vinfo;

	if (vpp_index == VPP_TOP1)
		vinfo = get_current_vinfo2();
	#ifdef CONFIG_AMLOGIC_VOUT3_SERVE
	else if (vpp_index == VPP_TOP2)
		vinfo = get_current_vinfo3();
	#endif
	else
		vinfo = get_current_vinfo();

	get_cur_vd_signal_type(vd_path);
	if (cur_mvc_type[vd_path] == VIDTYPE_MVC)
		return HDRTYPE_MVC;
	if (cur_primesl_type[vd_path])
		return HDRTYPE_PRIMESL;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
	if (vd_path == VD1_PATH &&
	    is_amdv_enable() &&
	    get_amdv_src_format(vd_path)
	    == HDRTYPE_DOVI)
		return HDRTYPE_DOVI;
#endif
	if ((signal_transfer_characteristic == 14 ||
	     signal_transfer_characteristic == 18) &&
	     signal_color_primaries == 9) {
		if (signal_cuva)
			return HDRTYPE_CUVA_HLG;
		else
			return HDRTYPE_HLG;
	} else if (signal_transfer_characteristic == 0x30 &&
		   signal_color_primaries == 9) {
		if (sink_support_hdr10_plus(vinfo) &&
		    vd_path == VD1_PATH)
			return HDRTYPE_HDR10PLUS;
		/* tv chip need not regard hdr10p as hdr10. */
		else if (vinfo_lcd_support() ||
			(!sink_support_hdr10_plus(vinfo) &&
			 !sink_support_hdr(vinfo) &&
			 !is_amdv_enable()))
			return HDRTYPE_HDR10PLUS;
		else
			return HDRTYPE_HDR10;
	} else if (signal_transfer_characteristic == 16) {
		if (signal_cuva)
			return HDRTYPE_CUVA_HDR;
		else
			return HDRTYPE_HDR10;
	} else {
		return HDRTYPE_SDR;
	}
}
#endif

enum hdr_type_e get_cur_source_type(enum vd_path_e vd_path,
	enum vpp_index_e vpp_index)
{
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	if (vd_path >= VD_PATH_MAX)
		return UNKNOWN_SOURCE;
	return get_source_type(vd_path, vpp_index);
#else
	return HDRTYPE_SDR;
#endif
}
EXPORT_SYMBOL(get_cur_source_type);

int get_hdr_module_status(enum vd_path_e vd_path,
	enum vpp_index_e vpp_index)
{
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
	if (vd_path == VD1_PATH &&
	    is_amdv_enable() &&
	    get_amdv_policy()
	    == AMDV_FOLLOW_SOURCE &&
	    get_source_type(VD1_PATH, vpp_index)
	    == HDRTYPE_SDR &&
	    sdr_process_mode[VD1_PATH]
	    == PROC_BYPASS) {
		pr_csc(16, "get video_process_status[VD%d] = MODULE BYPASS\n",
		       vd_path + 1);
		return HDR_MODULE_BYPASS;
	}
	if (support_multi_core1() &&
	    vd_path == VD2_PATH &&
	    is_amdv_enable() &&
	    get_amdv_policy()
	    == AMDV_FOLLOW_SOURCE &&
	    get_source_type(VD2_PATH, vpp_index)
	    == HDRTYPE_SDR &&
	    sdr_process_mode[VD2_PATH]
	    == PROC_BYPASS)
		return HDR_MODULE_BYPASS;
#endif
	pr_csc(16, "get video_process_status[VD%d] = %d\n",
	       vd_path + 1, video_process_status[vd_path]);

#endif
	return video_process_status[vd_path];
}
EXPORT_SYMBOL(get_hdr_module_status);

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static bool video_layer_wait_on[VD_PATH_MAX];
bool is_video_layer_on(enum vd_path_e vd_path)
{
	bool video_on;

	if (vd_path <= VD3_PATH)
		video_on = get_video_enabled(vd_path);
	else
		return false;

	if (video_on)
		video_layer_wait_on[vd_path] = false;

	return video_on ||
		video_layer_wait_on[vd_path];
}

static bool hdr10_plus_metadata_update(struct vframe_s *vf,
				       enum vpp_matrix_csc_e csc_type,
				       struct hdr10plus_para *p)
{
	if (!vf)
		return false;
	if (csc_type != VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC)
		return false;

	parser_dynamic_metadata(vf);

	if (tx_hdr10_plus_support) {
		hdr10_plus_hdmitx_vsif_parser(p, vf);
		pr_csc(0x10,
		       "hdr10+ vsif: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
		       ((p->application_version & 0x3) << 6) |
		       ((p->targeted_max_lum & 0x1f) << 1),
		       p->average_maxrgb,
		       p->distribution_values[0],
		       p->distribution_values[1],
		       p->distribution_values[2],
		       p->distribution_values[3],
		       p->distribution_values[4],
		       p->distribution_values[5],
		       p->distribution_values[6],
		       p->distribution_values[7],
		       p->distribution_values[8],
		       ((p->num_bezier_curve_anchors & 0xf) << 4) |
		       ((p->knee_point_x >> 6) & 0xf),
		       ((p->knee_point_x & 0x3f) << 2) |
		       ((p->knee_point_y >> 8) & 0x3),
		       p->knee_point_y & 0xff,
		       p->bezier_curve_anchors[0],
		       p->bezier_curve_anchors[1],
		       p->bezier_curve_anchors[2],
		       p->bezier_curve_anchors[3],
		       p->bezier_curve_anchors[4],
		       p->bezier_curve_anchors[5],
		       p->bezier_curve_anchors[6],
		       p->bezier_curve_anchors[7],
		       p->bezier_curve_anchors[8],
		       ((p->graphics_overlay_flag & 0x1) << 7) |
		       ((p->no_delay_flag & 0x1) << 6));
	}
	//TODO: return false if meta not changed
	return true;
}

static bool cuva_metadata_update(struct vframe_s *vf,
	enum vpp_matrix_csc_e csc_type,
	struct cuva_hdr_vsif_para *vsif_paras,
	struct cuva_hdr_vs_emds_para *emds_paras)
{
	//struct cuva_hdr_vsif_para vsif_para;
	//struct cuva_hdr_vs_emds_para emds_para;

	if (!vf)
		return false;
	if (csc_type != VPP_MATRIX_BT2020YUV_BT2020RGB_CUVA)
		return false;

	/* TODO: add meta update */
	parser_dynamic_metadata(vf);

	cuva_hdr_vsif_pkt_update(vsif_paras);
	cuva_hdr_emds_pkt_update(emds_paras);

	//TODO: return false if meta not changed
	return true;
}
static struct hdr10pgen_param_s hdr10pgen_param;
void hdr10_plus_process_update(int force_source_lumin,
	enum vd_path_e vd_path,
	enum vpp_index_e vpp_index)
{
	int panel_lumin;
	struct vinfo_s *vinfo;
	int silce_mode = get_s5_slice_mode();

	if (vpp_index == VPP_TOP1)
		vinfo = get_current_vinfo2();
	#ifdef CONFIG_AMLOGIC_VOUT3_SERVE
	else if (vpp_index == VPP_TOP2)
		vinfo = get_current_vinfo3();
	#endif
	else
		vinfo = get_current_vinfo();

	if (vinfo) {
		if (vinfo->hdr_info.lumi_max > 0 &&
		    vinfo->hdr_info.lumi_max <= 1000)
			panel_lumin = vinfo->hdr_info.lumi_max;
		else
			panel_lumin = customer_panel_lumin;
	} else {
		panel_lumin = customer_panel_lumin;
	}

	hdr10_plus_ootf_gen(panel_lumin,
			    force_source_lumin,
			    &hdr10pgen_param);
	if (vd_path == VD1_PATH) {
		if (silce_mode == VD1_1SLICE) {
			hdr10p_ebzcurve_update(VD1_HDR,
					       HDR10P_SDR,
					       &hdr10pgen_param,
					       vpp_index);
		} else if (silce_mode == VD1_2SLICE) {
			hdr10p_ebzcurve_update(VD1_HDR,
						   HDR10P_SDR,
						   &hdr10pgen_param,
						   vpp_index);
			hdr10p_ebzcurve_update(S5_VD1_SLICE1,
						   HDR10P_SDR,
						   &hdr10pgen_param,
						   vpp_index);
		} else if (silce_mode == VD1_4SLICE) {
			hdr10p_ebzcurve_update(VD1_HDR,
						   HDR10P_SDR,
						   &hdr10pgen_param,
						   vpp_index);
			hdr10p_ebzcurve_update(S5_VD1_SLICE1,
						   HDR10P_SDR,
						   &hdr10pgen_param,
						   vpp_index);
			hdr10p_ebzcurve_update(S5_VD1_SLICE2,
						   HDR10P_SDR,
						   &hdr10pgen_param,
						   vpp_index);
			hdr10p_ebzcurve_update(S5_VD1_SLICE3,
						   HDR10P_SDR,
						   &hdr10pgen_param,
						   vpp_index);
		}
	} else if (vd_path == VD2_PATH) {
		hdr10p_ebzcurve_update(VD2_HDR,
				       HDR10P_SDR,
				       &hdr10pgen_param,
				       vpp_index);
	} else if (vd_path == VD3_PATH) {
		hdr10p_ebzcurve_update(VD3_HDR,
				       HDR10P_SDR,
				       &hdr10pgen_param,
				       vpp_index);
	}
}
EXPORT_SYMBOL(hdr10_plus_process_update);

static void hdr10_tm_process_update(struct vframe_master_display_colour_s *p,
				    enum vd_path_e vd_path, enum vpp_index_e vpp_index)
{
	int silce_mode = get_s5_slice_mode();

	hdr10_tm_dynamic_proc(p);
	if (vd_path == VD1_PATH) {
		if (silce_mode == VD1_1SLICE) {
			hdr10_tm_update(VD1_HDR, HDR_SDR, vpp_index);
		} else if (silce_mode == VD1_2SLICE) {
			hdr10_tm_update(VD1_HDR, HDR_SDR, vpp_index);
			hdr10_tm_update(S5_VD1_SLICE1, HDR_SDR, vpp_index);
		} else if (silce_mode == VD1_4SLICE) {
			hdr10_tm_update(VD1_HDR, HDR_SDR, vpp_index);
			hdr10_tm_update(S5_VD1_SLICE1, HDR_SDR, vpp_index);
			hdr10_tm_update(S5_VD1_SLICE2, HDR_SDR, vpp_index);
			hdr10_tm_update(S5_VD1_SLICE3, HDR_SDR, vpp_index);
		}
	} else if (vd_path == VD2_PATH) {
		hdr10_tm_update(VD2_HDR, HDR_SDR, vpp_index);
	} else if (vd_path == VD3_PATH) {
		hdr10_tm_update(VD3_HDR, HDR_SDR, vpp_index);
	}
}

static void cuva_hdr_process_update(enum hdr_type_e src_type,
	int proc_mode, enum vd_path_e vd_path,
	struct vframe_master_display_colour_s *p,
	enum vpp_index_e vpp_index)
{
	int proc_flag = 0;
	struct aml_cuva_data_s *cuva_data = get_cuva_data();
	int silce_mode = get_s5_slice_mode();

	if (src_type == CUVA_HDR_SOURCE) {
		if (proc_mode == PROC_CUVA_TO_SDR) {
			cuva_tm_func(CUVA_HDR2SDR, p);
			proc_flag = 1;
		} else if (proc_mode == PROC_CUVA_TO_HDR) {
			cuva_tm_func(CUVA_HDR2HDR10, p);
			proc_flag = 1;
		}
	} else if (src_type == CUVA_HLG_SOURCE) {
		if (proc_mode == PROC_CUVAHLG_TO_SDR) {
			cuva_tm_func(CUVA_HLG2SDR, p);
			proc_flag = 1;
		} else if (proc_mode == PROC_CUVAHLG_TO_HLG) {
			cuva_tm_func(CUVA_HLG2HLG, p);
			proc_flag = 1;
		} else if (proc_mode == PROC_CUVAHLG_TO_HDR) {
			cuva_tm_func(CUVA_HLG2HDR10, p);
			proc_flag = 1;
		}
	}
	if (!proc_flag || !cuva_data->cuva_hdr_alg)
		return;

	if (is_meson_g12a_cpu() || is_meson_g12b_cpu())
		cuva_data->ic_type = IC_G12A;

	cuva_data->cuva_hdr_alg(cuva_data);

	if (src_type == CUVA_HDR_SOURCE) {
		if (proc_mode == PROC_CUVA_TO_SDR) {
			if (vd_path == VD1_PATH) {
				if (silce_mode == VD1_1SLICE) {
					cuva_hdr_update(VD1_HDR, CUVA_SDR, vpp_index);
				} else if (silce_mode == VD1_2SLICE) {
					cuva_hdr_update(VD1_HDR, CUVA_SDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE1, CUVA_SDR, vpp_index);
				} else if (silce_mode == VD1_4SLICE) {
					cuva_hdr_update(VD1_HDR, CUVA_SDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE1, CUVA_SDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE2, CUVA_SDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE3, CUVA_SDR, vpp_index);
				}
			} else if (vd_path == VD2_PATH) {
				cuva_hdr_update(VD2_HDR, CUVA_SDR, vpp_index);
			} else if (vd_path == VD3_PATH) {
				cuva_hdr_update(VD3_HDR, CUVA_SDR, vpp_index);
			}
		} else if (proc_mode == PROC_CUVA_TO_HDR) {
			if (vd_path == VD1_PATH) {
				if (silce_mode == VD1_1SLICE) {
					cuva_hdr_update(VD1_HDR, CUVA_HDR, vpp_index);
				} else if (silce_mode == VD1_2SLICE) {
					cuva_hdr_update(VD1_HDR, CUVA_HDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE1, CUVA_HDR, vpp_index);
				} else if (silce_mode == VD1_4SLICE) {
					cuva_hdr_update(VD1_HDR, CUVA_HDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE1, CUVA_HDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE2, CUVA_HDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE3, CUVA_HDR, vpp_index);
				}
			} else if (vd_path == VD2_PATH) {
				cuva_hdr_update(VD2_HDR, CUVA_HDR, vpp_index);
			} else if (vd_path == VD3_PATH) {
				cuva_hdr_update(VD3_HDR, CUVA_HDR, vpp_index);
			}
		}
	} else if (src_type == CUVA_HLG_SOURCE) {
		if (proc_mode == PROC_CUVAHLG_TO_SDR) {
			if (vd_path == VD1_PATH) {
				if (silce_mode == VD1_1SLICE) {
					cuva_hdr_update(VD1_HDR, CUVAHLG_SDR, vpp_index);
				} else if (silce_mode == VD1_2SLICE) {
					cuva_hdr_update(VD1_HDR, CUVAHLG_SDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE1, CUVAHLG_SDR, vpp_index);
				} else if (silce_mode == VD1_4SLICE) {
					cuva_hdr_update(VD1_HDR, CUVAHLG_SDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE1, CUVAHLG_SDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE2, CUVAHLG_SDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE3, CUVAHLG_SDR, vpp_index);
				}
			} else if (vd_path == VD2_PATH) {
				cuva_hdr_update(VD2_HDR, CUVAHLG_SDR, vpp_index);
			} else if (vd_path == VD3_PATH) {
				cuva_hdr_update(VD3_HDR, CUVAHLG_SDR, vpp_index);
			}
		} else if (proc_mode == PROC_CUVAHLG_TO_HLG) {
			if (vd_path == VD1_PATH) {
				if (silce_mode == VD1_1SLICE) {
					cuva_hdr_update(VD1_HDR, CUVAHLG_HLG, vpp_index);
				} else if (silce_mode == VD1_2SLICE) {
					cuva_hdr_update(VD1_HDR, CUVAHLG_HLG, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE1, CUVAHLG_HLG, vpp_index);
				}  else if (silce_mode == VD1_4SLICE) {
					cuva_hdr_update(VD1_HDR, CUVAHLG_HLG, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE1, CUVAHLG_HLG, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE2, CUVAHLG_HLG, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE3, CUVAHLG_HLG, vpp_index);
				}
			} else if (vd_path == VD2_PATH) {
				cuva_hdr_update(VD2_HDR, CUVAHLG_HLG, vpp_index);
			} else if (vd_path == VD3_PATH) {
				cuva_hdr_update(VD3_HDR, CUVAHLG_HLG, vpp_index);
			}
		} else if (proc_mode == PROC_CUVAHLG_TO_HDR) {
			if (vd_path == VD1_PATH) {
				if (silce_mode == VD1_1SLICE) {
					cuva_hdr_update(VD1_HDR, CUVAHLG_HDR, vpp_index);
				} else if (silce_mode == VD1_2SLICE) {
					cuva_hdr_update(VD1_HDR, CUVAHLG_HDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE1, CUVAHLG_HDR, vpp_index);
				} else if (silce_mode == VD1_4SLICE) {
					cuva_hdr_update(VD1_HDR, CUVAHLG_HDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE1, CUVAHLG_HDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE2, CUVAHLG_HDR, vpp_index);
					cuva_hdr_update(S5_VD1_SLICE3, CUVAHLG_HDR, vpp_index);
				}
			} else if (vd_path == VD2_PATH) {
				cuva_hdr_update(VD2_HDR, CUVAHLG_HDR, vpp_index);
			} else if (vd_path == VD3_PATH) {
				cuva_hdr_update(VD3_HDR, CUVAHLG_HDR, vpp_index);
			}
		}
	}
}

static struct hdr10plus_para hdmitx_hdr10plus_params[VD_PATH_MAX];
static int hdr10_plus_pkt_update;
static bool hdr10_plus_pkt_on;
/* 0: no delay, 1:delay one frame, >1:delay one frame and repeat */
static uint hdr10_plus_pkt_delay = 1;
static struct hdr10plus_para cur_hdr10plus_params;
static struct master_display_info_s cur_send_info;
module_param(hdr10_plus_pkt_delay, uint, 0664);

uint get_hdr10_plus_pkt_delay(void)
{
	return hdr10_plus_pkt_delay;
}
EXPORT_SYMBOL(get_hdr10_plus_pkt_delay);

static int cuva_pkt_update;
static bool cuva_pkt_on;
static struct cuva_hdr_vsif_para hdmitx_vsif_params[VD_PATH_MAX];
static struct cuva_hdr_vs_emds_para hdmitx_edms_params[VD_PATH_MAX];
static struct cuva_hdr_vsif_para cur_cuva_params;
static struct cuva_hdr_vs_emds_para cur_edms_params;
static uint cuva_pkt_delay = 1; // should set 1, 0 is ok
module_param(cuva_pkt_delay, uint, 0664);

uint get_cuva_pkt_delay(void)
{
	return cuva_pkt_delay;
}
EXPORT_SYMBOL(get_cuva_pkt_delay);

void pkt_delay_flag_init(void)
{
	if (pkt_adv_chip()) {
		hdr10_plus_pkt_delay = 0;
		cuva_pkt_delay = 0;
	}
}

void update_hdr10_plus_pkt(bool enable,
			   void *hdr10plus_params,
			   void *send_info,
			   enum vpp_index_e vpp_index)
{
	struct vinfo_s *vinfo;
	struct vout_device_s *vdev = NULL;

	if (vpp_index == VPP_TOP1)
		vinfo = get_current_vinfo2();
	#ifdef CONFIG_AMLOGIC_VOUT3_SERVE
	else if (vpp_index == VPP_TOP2)
		vinfo = get_current_vinfo3();
	#endif
	else
		vinfo = get_current_vinfo();

	if (vinfo && vinfo->mode != VMODE_HDMI)
		return;

	if (vinfo->vout_device) {
		vdev = vinfo->vout_device;
		if (!vdev)
			return;
		if (!vdev->fresh_tx_hdr_pkt)
			return;
		if (!vdev->fresh_tx_hdr10plus_pkt)
			return;
	}

	hdr10_plus_pkt_on = enable;
	if (hdr10_plus_pkt_on) {
		memcpy((void *)&cur_hdr10plus_params, hdr10plus_params,
		       sizeof(struct hdr10plus_para));
		memcpy((void *)&cur_send_info, send_info,
		       sizeof(struct master_display_info_s));
		hdr10_plus_pkt_update = HDRPLUS_PKT_UPDATE;
		pr_csc(2, "update hdr10_plus_pkt on\n");
	} else {
		if (!vdev)
			return;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
		if ((get_amdv_policy() == AMDV_FOLLOW_SINK) &&
		    sink_support_hdr(vinfo) &&
		    (!sink_support_dv(vinfo))) {
			pr_csc(2, "update hdr10_plus_pkt: DISABLE_VSIF\n");
			vdev->fresh_tx_hdr10plus_pkt(HDR10_PLUS_DISABLE_VSIF,
						     &cur_hdr10plus_params);
		} else {
#endif
			pr_csc(2, "update hdr10_plus_pkt: ZERO_VSIF\n");
			vdev->fresh_tx_hdr_pkt(send_info);
			vdev->fresh_tx_hdr10plus_pkt(HDR10_PLUS_ZERO_VSIF,
						     &cur_hdr10plus_params);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
		}
#endif
		hdr10_plus_pkt_update = HDRPLUS_PKT_IDLE;
		pr_csc(2, "update hdr10_plus_pkt off\n");
	}
}
EXPORT_SYMBOL(update_hdr10_plus_pkt);

void update_cuva_pkt(bool enable,
	void *cuva_params,
	void *edms_params,
	void *send_info,
	enum vpp_index_e vpp_index)
{
	struct vinfo_s *vinfo;
	struct vout_device_s *vdev = NULL;
	bool follow_sink;

	if (vpp_index == VPP_TOP1)
		vinfo = get_current_vinfo2();
#ifdef CONFIG_AMLOGIC_VOUT3_SERVE
	else if (vpp_index == VPP_TOP2)
		vinfo = get_current_vinfo3();
#endif
	else
		vinfo = get_current_vinfo();

	if (vinfo && vinfo->mode != VMODE_HDMI)
		return;

	if (vinfo->vout_device) {
		vdev = vinfo->vout_device;
		if (!vdev)
			return;
		if (!vdev->fresh_tx_cuva_hdr_vsif)
			return;
		if (!vdev->fresh_tx_cuva_hdr_vs_emds)
			return;
	}

	cuva_pkt_on = enable;
	if (cuva_pkt_on) {
		memcpy((void *)&cur_cuva_params, cuva_params,
			sizeof(struct cuva_hdr_vsif_para));
		memcpy((void *)&cur_edms_params, edms_params,
			sizeof(struct cuva_hdr_vs_emds_para));
		memcpy((void *)&cur_send_info, send_info,
					sizeof(struct master_display_info_s));
		cuva_pkt_update = CUVA_PKT_UPDATE;
		pr_csc(2, "%s on\n", __func__);
	} else {
		if (!vdev)
			return;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
		follow_sink = (get_amdv_policy() ==
			AMDV_FOLLOW_SINK);
#else
		follow_sink = (get_hdr_policy() == 0);
#endif
		if (follow_sink &&
		    (sink_hdr_support(vinfo) & CUVA_SUPPORT) &&
		    (!sink_support_dv(vinfo))) {
			pr_csc(2, "%s: DISABLE_VSIF\n", __func__);
			if (vinfo->hdr_info.cuva_info.monitor_mode_sup == 1)
				vdev->fresh_tx_cuva_hdr_vsif(NULL);
			else
				vdev->fresh_tx_cuva_hdr_vs_emds(NULL);
		} else {
			pr_csc(2, "%s: ZERO_VSIF\n", __func__);
			vdev->fresh_tx_hdr_pkt(send_info);
			vdev->fresh_tx_cuva_hdr_vsif(NULL);
			vdev->fresh_tx_cuva_hdr_vs_emds(NULL);
		}
		cuva_pkt_update = CUVA_PKT_IDLE;
		pr_csc(2, "%s off\n", __func__);
	}
}
EXPORT_SYMBOL(update_cuva_pkt);

void send_hdr10_plus_pkt(enum vd_path_e vd_path,
	enum vpp_index_e vpp_index)
{
	struct vinfo_s *vinfo;
	struct vout_device_s *vdev = NULL;

	if (vpp_index == VPP_TOP1)
		vinfo = get_current_vinfo2();
	#ifdef CONFIG_AMLOGIC_VOUT3_SERVE
	else if (vpp_index == VPP_TOP2)
		vinfo = get_current_vinfo3();
	#endif
	else
		vinfo = get_current_vinfo();

	if (vinfo && vinfo->mode != VMODE_HDMI)
		return;

	if (vinfo->vout_device) {
		vdev = vinfo->vout_device;
		if (!vdev)
			return;
		if (!vdev->fresh_tx_hdr_pkt)
			return;
		if (!vdev->fresh_tx_hdr10plus_pkt)
			return;
	}
	if (hdr10_plus_pkt_update == HDRPLUS_PKT_UPDATE) {
		if (!vdev)
			return;
		vdev->fresh_tx_hdr_pkt(&cur_send_info);
		vdev->fresh_tx_hdr10plus_pkt(hdr10_plus_pkt_on,
					     &cur_hdr10plus_params);
		if (get_hdr10_plus_pkt_delay() > 1)
			hdr10_plus_pkt_update = HDRPLUS_PKT_REPEAT;
		else
			hdr10_plus_pkt_update = HDRPLUS_PKT_IDLE;
		pr_csc(2, "send hdr10_plus_pkt update\n");
	} else if ((hdr10_plus_pkt_update == HDRPLUS_PKT_REPEAT) &&
		(get_hdr10_plus_pkt_delay() > 1)) {
		if (!vdev)
			return;
		vdev->fresh_tx_hdr_pkt(&cur_send_info);
		vdev->fresh_tx_hdr10plus_pkt(hdr10_plus_pkt_on,
					     &cur_hdr10plus_params);
		pr_csc(2, "send hdr10_plus_pkt repeat\n");
	}
}
EXPORT_SYMBOL(send_hdr10_plus_pkt);

void send_cuva_pkt(enum vd_path_e vd_path,
	enum vpp_index_e vpp_index)
{
	struct vinfo_s *vinfo;
	struct vout_device_s *vdev = NULL;

	if (vpp_index == VPP_TOP1)
		vinfo = get_current_vinfo2();
#ifdef CONFIG_AMLOGIC_VOUT3_SERVE
	else if (vpp_index == VPP_TOP2)
		vinfo = get_current_vinfo3();
#endif
	else
		vinfo = get_current_vinfo();

	if (vinfo && vinfo->mode != VMODE_HDMI)
		return;

	if (vinfo->vout_device) {
		vdev = vinfo->vout_device;
		if (!vdev)
			return;
		if (!vdev->fresh_tx_hdr_pkt)
			return;
		if (!vdev->fresh_tx_cuva_hdr_vsif)
			return;
		if (!vdev->fresh_tx_cuva_hdr_vs_emds)
			return;
	}
	if (cuva_pkt_update == CUVA_PKT_UPDATE) {
		if (!vdev)
			return;
		vdev->fresh_tx_hdr_pkt(&cur_send_info);
		if (vinfo->hdr_info.cuva_info.monitor_mode_sup == 1)
			vdev->fresh_tx_cuva_hdr_vsif(&cur_cuva_params);
		else
			vdev->fresh_tx_cuva_hdr_vs_emds(&cur_edms_params);
		if (get_cuva_pkt_delay() > 1)
			cuva_pkt_update = CUVA_PKT_REPEAT;
		else
			cuva_pkt_update = CUVA_PKT_IDLE;
		pr_csc(2, "%s update cuva_pkt_update = %d\n",
			__func__,
			cuva_pkt_update);
	} else if ((cuva_pkt_update == CUVA_PKT_REPEAT) &&
		(get_cuva_pkt_delay() > 1)) {
		if (!vdev)
			return;
		if (vinfo->hdr_info.cuva_info.monitor_mode_sup == 1)
			vdev->fresh_tx_cuva_hdr_vsif(&cur_cuva_params);
		else
			vdev->fresh_tx_cuva_hdr_vs_emds(&cur_edms_params);
		pr_csc(2, "%s repeat cuva_pkt_update = %d\n",
			__func__,
			cuva_pkt_update);
	}
}
EXPORT_SYMBOL(send_cuva_pkt);

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static int notify_vd_signal_to_amvideo(struct vd_signal_info_s *vd_signal,
	enum vpp_index_e vpp_index)
{
	static int pre_signal = -1;

	if (vpp_index != VPP_TOP0)
		return -1;

#ifdef CONFIG_AMLOGIC_MEDIA_VIDEO
	if (pre_signal != vd_signal->signal_type) {
		vd_signal->vd1_signal_type =
			vd_signal->signal_type;
		vd_signal->vd2_signal_type =
			vd_signal->signal_type;
		pr_csc(8,
			"%s:line=%d, signal_type=%x, vd1_signal_type=%x, vd2_signal_type=%x\n",
			__func__, __LINE__,
			vd_signal->signal_type,
			vd_signal->vd1_signal_type,
			vd_signal->vd2_signal_type);
		amvideo_notifier_call_chain
			(AMVIDEO_UPDATE_SIGNAL_MODE,
			(void *)vd_signal);
	}
#endif
	pre_signal = vd_signal->signal_type;
	return 0;
}

static void hdr_tx_pkt_cb(struct vinfo_s *vinfo,
	int signal_change_flag,
	enum vpp_matrix_csc_e csc_type,
	struct vframe_master_display_colour_s *p,
	int *hdmi_scs_type_changed,
	struct hdr10plus_para *hdmitx_hdr10plus_param,
	struct cuva_hdr_vsif_para *hdmitx_vsif_param,
	struct cuva_hdr_vs_emds_para *hdmitx_edms_param,
	enum vd_path_e vd_path, enum vpp_index_e vpp_index)
{
	struct vout_device_s *vdev = NULL;
	void (*f_h10)(unsigned int flag,
		      struct hdr10plus_para *data);
	void (*f_h)(struct master_display_info_s *data);
	struct hdr10plus_para *h10_para;
	struct master_display_info_s send_info;
	struct vd_signal_info_s vd_signal;

	f_h = NULL;
	f_h10 = NULL;
	h10_para = NULL;

	if (vinfo->vout_device)
		vdev = vinfo->vout_device;

	if (vdev) {
		f_h = vdev->fresh_tx_hdr_pkt;
		f_h10 = vdev->fresh_tx_hdr10plus_pkt;
		h10_para = hdmitx_hdr10plus_param;
	}

	if (!vinfo_lcd_support() &&
	    ((sink_hdr_support(vinfo) &
	    (HDR_SUPPORT | HLG_SUPPORT)) ||
	     (signal_change_flag & SIG_HDR_SUPPORT) ||
	     (signal_change_flag & SIG_HLG_SUPPORT) ||
	     /*hdr10 plus*/
	     tx_hdr10_plus_support ||
	     (signal_change_flag & SIG_HDR10_PLUS_MODE))) {
		if (sdr_process_mode[vd_path] &&
		    csc_type < VPP_MATRIX_BT2020YUV_BT2020RGB) {
			/* sdr source convert to hdr */
			/* send hdr info */
			/* use the features to describe source info */
			send_info.features =
					(0 << 30) /*sdr output 709*/
					| (1 << 29)	/*video available*/
					| (5 << 26)	/* unspecified */
					| (0 << 25)	/* limit */
					| (1 << 24)	/* color available */
					| (9 << 16)	/* bt2020 */
					| (16 << 8)	/* bt2020-10 */
					| (10 << 0);	/* bt2020c */
			amvecm_cp_hdr_info(&send_info, p);
			if (vdev) {
				if (f_h)
					f_h(&send_info);
			}

			if (cur_csc_type[vd_path] ==
				VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC) {
				if (vdev) {
					if (f_h10)
						f_h10(0,
						      h10_para);
				}
			}

			vd_signal.signal_type = SIGNAL_HDR10PLUS;
			notify_vd_signal_to_amvideo(&vd_signal, vpp_index);

			if (hdmi_csc_type != VPP_MATRIX_BT2020YUV_BT2020RGB) {
				hdmi_csc_type =
				VPP_MATRIX_BT2020YUV_BT2020RGB;
				*hdmi_scs_type_changed = 1;
			}
		} else if (hdr_process_mode[vd_path] == PROC_BYPASS &&
			   hlg_process_mode[vd_path] == PROC_BYPASS &&
			   csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) {
			/* source is hdr, send hdr info */
			/* use the features to describe source info */
			send_info.features =
					(0 << 30) /*sdr output 709*/
					| (1 << 29)	/*video available*/
					| (5 << 26)	/* unspecified */
					| (0 << 25)	/* limit */
					| (1 << 24)	/*color available*/
					/* bt2020 */
					| (signal_color_primaries << 16)
					/* bt2020-10 */
					| (signal_transfer_characteristic << 8)
					| (10 << 0);	/* bt2020c */
			amvecm_cp_hdr_info(&send_info, p);
			if (vdev) {
				if (f_h)
					f_h(&send_info);
			}
			vd_signal.signal_type = SIGNAL_HDR10;
			notify_vd_signal_to_amvideo(&vd_signal, vpp_index);

			if (hdmi_csc_type != VPP_MATRIX_BT2020YUV_BT2020RGB) {
				hdmi_csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB;
				*hdmi_scs_type_changed = 1;
			}
		} else if (hdr_process_mode[vd_path] == PROC_BYPASS &&
			   hlg_process_mode[vd_path] == PROC_MATCH &&
			   csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) {
			/* source is hdr, send hdr info */
			/* use the features to describe source info */
			if (get_hdr_type() & HLG_FLAG) {
				send_info.features =
					(0 << 30) /*sdr output 709*/
					| (1 << 29)	/*video available*/
					| (5 << 26)	/* unspecified */
					| (0 << 25)	/* limit */
					| (1 << 24)	/*color available*/
					/* bt2020 */
					| (9 << 16)
					/* bt2020-10 */
					| (16 << 8)
					| (10 << 0);	/* bt2020c */
				vd_signal.signal_type = SIGNAL_HLG;
			} else {
				send_info.features =
					(0 << 30) /*sdr output 709*/
					| (1 << 29)	/*video available*/
					| (5 << 26)	/* unspecified */
					| (0 << 25)	/* limit */
					| (1 << 24)	/*color available*/
					/* bt2020 */
					| (signal_color_primaries << 16)
					/* bt2020-10 */
					| (signal_transfer_characteristic << 8)
					| (10 << 0);	/* bt2020c */
				vd_signal.signal_type = SIGNAL_HDR10;
			}
			amvecm_cp_hdr_info(&send_info, p);
			if (vdev) {
				if (f_h)
					f_h(&send_info);
			}
			notify_vd_signal_to_amvideo(&vd_signal, vpp_index);

			if (hdmi_csc_type != VPP_MATRIX_BT2020YUV_BT2020RGB) {
				hdmi_csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB;
				*hdmi_scs_type_changed = 1;
			}
		} else if (hdr_process_mode[vd_path] == PROC_MATCH &&
			   hlg_process_mode[vd_path] == PROC_BYPASS &&
			   csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) {
			/* source is hdr, send hdr info */
			/* use the features to describe source info */
			if (get_hdr_type() & HLG_FLAG) {
				send_info.features =
					(0 << 30) /*sdr output 709*/
					| (1 << 29)	/*video available*/
					| (5 << 26)	/* unspecified */
					| (0 << 25)	/* limit */
					| (1 << 24)	/*color available*/
					/* bt2020 */
					| (signal_color_primaries << 16)
					/* bt2020-10 */
					| (signal_transfer_characteristic << 8)
					| (10 << 0);	/* bt2020c */
				vd_signal.signal_type = SIGNAL_HLG;
			} else {
				send_info.features =
					/* default 709 full */
					(0 << 30) /*sdr output 709*/
					| (1 << 29) /*video available*/
					| (5 << 26) /* unspecified */
					| (0 << 25) /* limit */
					| (1 << 24) /*color available*/
					| (1 << 16) /* bt709 */
					| (1 << 8)	/* bt709 */
					| (1 << 0); /* bt709 */
				vd_signal.signal_type = SIGNAL_HDR10;
			}
			amvecm_cp_hdr_info(&send_info, p);
			if (vdev) {
				if (f_h)
					f_h(&send_info);
			}
			notify_vd_signal_to_amvideo(&vd_signal, vpp_index);
			if (hdmi_csc_type != VPP_MATRIX_BT2020YUV_BT2020RGB) {
				hdmi_csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB;
				*hdmi_scs_type_changed = 1;
			}
		} else if (hdr10_plus_process_mode[vd_path] == 0 &&
			   csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC) {
			/* source is hdr10+, send hdr10 drm packet as well*/
			/* use the features to describe source info */
			send_info.features =
					(0 << 30) /*sdr output 709*/
					| (1 << 29)	/*video available*/
					| (5 << 26)	/* unspecified */
					| (0 << 25)	/* limit */
					| (1 << 24)	/*color available*/
					/* bt2020 */
					| (signal_color_primaries << 16)
					| (16 << 8)     /* Always HDR10 */
					| (10 << 0);	/* bt2020c */
			amvecm_cp_hdr_info(&send_info, p);
			if (vdev) {
				/* source is hdr10 plus, send hdr10 plus info */
				if (get_hdr10_plus_pkt_delay()) {
					update_hdr10_plus_pkt(true,
							      h10_para,
							      &send_info,
							      vpp_index);
				} else {
					/* send HDR10 DRM packet */
					if (f_h)
						f_h(&send_info);
					/* send hdr10 plus info */
					if (f_h10)
						f_h10(1, h10_para);
				}
				vd_signal.signal_type = SIGNAL_HDR10PLUS;
				notify_vd_signal_to_amvideo(&vd_signal, vpp_index);
			}
			if (hdmi_csc_type != VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC) {
				hdmi_csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC;
				*hdmi_scs_type_changed = 1;
			}
		} else if ((cuva_hdr_process_mode[vd_path] == 0) &&
			(csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB_CUVA)) {
			/* source is cuva, send cuva packet as well*/
			/* source is cuva, send cuva info */
			if (get_cuva_pkt_delay() && vdev) {
				update_cuva_pkt(true,
					hdmitx_vsif_param,
					hdmitx_edms_param,
					&send_info,
					vpp_index);
			} else {
					/* send cuva packet */
				if (vinfo->hdr_info.cuva_info.monitor_mode_sup == 1) {
					if (vdev && vdev->fresh_tx_cuva_hdr_vsif)
						vdev->fresh_tx_cuva_hdr_vsif
						(hdmitx_vsif_param);
				} else {
					if (vdev && vdev->fresh_tx_cuva_hdr_vs_emds)
						vdev->fresh_tx_cuva_hdr_vs_emds
						(hdmitx_edms_param);
				}
			}
			vd_signal.signal_type = SIGNAL_CUVA;
			notify_vd_signal_to_amvideo(&vd_signal, vpp_index);
			if (hdmi_csc_type !=
				VPP_MATRIX_BT2020YUV_BT2020RGB_CUVA) {
				hdmi_csc_type =
					VPP_MATRIX_BT2020YUV_BT2020RGB_CUVA;
				*hdmi_scs_type_changed = 1;
			}
		} else {
			/* sdr source send normal info*/
			/* use the features to describe source info */
			if (((sink_hdr_support(vinfo) & HDR_SUPPORT) ||
			     (sink_hdr_support(vinfo) & HLG_SUPPORT)) &&
			     csc_type < VPP_MATRIX_BT2020YUV_BT2020RGB &&
			     tx_op_color_primary)
				send_info.features =
					/* default 709 limit */
					(1 << 30) /*sdr output 2020*/
					| (1 << 29)	/*video available*/
					| (5 << 26)	/* unspecified */
					| (0 << 25)	/* limit */
					| (1 << 24)	/*color available*/
					| (1 << 16)	/* bt709 */
					| (1 << 8)	/* bt709 */
					| (1 << 0);	/* bt709 */
			else
				send_info.features =
					/* default 709 limit */
					(0 << 30) /*sdr output 709*/
					| (1 << 29)	/*video available*/
					| (5 << 26)	/* unspecified */
					| (0 << 25)	/* limit */
					| (1 << 24)	/*color available*/
					| (1 << 16)	/* bt709 */
					| (1 << 8)	/* bt709 */
					| (1 << 0);	/* bt709 */
			amvecm_cp_hdr_info(&send_info, p);
			if (cur_csc_type[vd_path] <= VPP_MATRIX_BT2020YUV_BT2020RGB) {
				if (vdev) {
					if (f_h)
						f_h(&send_info);
				}
			} else if (cur_csc_type[vd_path] ==
				   VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC) {
				if (vdev) {
					if (f_h)
						f_h(&send_info);
					if (f_h10)
						f_h10(0, h10_para);
				}
			} else if (cur_csc_type[vd_path] == VPP_MATRIX_BT2020YUV_BT2020RGB_CUVA) {
				if (vinfo->hdr_info.cuva_info.monitor_mode_sup == 1) {
					if (vdev && vdev->fresh_tx_cuva_hdr_vsif)
						vdev->fresh_tx_cuva_hdr_vsif(NULL);
				} else {
					if (vdev && vdev->fresh_tx_cuva_hdr_vs_emds)
						vdev->fresh_tx_cuva_hdr_vs_emds(NULL);
				}
			}
			vd_signal.signal_type = SIGNAL_SDR;
			notify_vd_signal_to_amvideo(&vd_signal, vpp_index);
			if (hdmi_csc_type != VPP_MATRIX_YUV709_RGB) {
				hdmi_csc_type = VPP_MATRIX_YUV709_RGB;
				*hdmi_scs_type_changed = 1;
			}
		}
	}
}

static void video_process(struct vframe_s *vf,
			  enum vpp_matrix_csc_e csc_type,
			  int signal_change_flag,
			  struct vinfo_s *vinfo,
			  struct vframe_master_display_colour_s *p,
			  enum vd_path_e vd_path,
			  enum hdr_type_e *source_type,
			  enum vpp_index_e vpp_index)
{
	int need_adjust_contrast_saturation = 0;

	/* decided by edid or panel info or user setting */
	if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB &&
	    hdr_process_mode[vd_path] == PROC_MATCH &&
	    hlg_process_mode[vd_path] == PROC_MATCH) {
		/* hdr->sdr hlg->sdr */
		if ((signal_change_flag &
		     (SIG_CS_CHG |
		      SIG_PRI_INFO |
		      SIG_KNEE_FACTOR |
		      SIG_HDR_MODE |
		      SIG_HDR_SUPPORT |
		      SIG_HLG_MODE |
		      SIG_HDR_OOTF_CHG |
		      SIG_CUVA_HDR_MODE)) ||
		    cur_csc_type[vd_path] < VPP_MATRIX_BT2020YUV_BT2020RGB) {
			if (get_hdr_type() & HLG_FLAG)
				need_adjust_contrast_saturation =
					hlg_process(csc_type, vinfo, p,
						    vd_path, source_type, vpp_index);
			else
				need_adjust_contrast_saturation =
				hdr_process(csc_type, vinfo, p, vd_path,
					    source_type,
					    vpp_index);
			pr_csc(1, "vd_path = %d\n"
				"hdr_process_mode = 0x%x\n"
				"hlg_process_mode = 0x%x.\n",
				vd_path + 1,
				hdr_process_mode[vd_path],
				hlg_process_mode[vd_path]);
		}
	} else if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB &&
		   hdr_process_mode[vd_path] == PROC_BYPASS &&
		   hlg_process_mode[vd_path] == PROC_MATCH) {
		/* hdr->hdr hlg->hdr*/
		if ((signal_change_flag &
		     (SIG_CS_CHG |
		      SIG_PRI_INFO |
		      SIG_KNEE_FACTOR |
		      SIG_HDR_MODE |
		      SIG_HDR_SUPPORT |
		      SIG_HLG_MODE |
		      SIG_HDR_OOTF_CHG)) ||
		    cur_csc_type[vd_path] < VPP_MATRIX_BT2020YUV_BT2020RGB) {
			if (get_hdr_type() & HLG_FLAG)
				hlg_hdr_process(csc_type, vinfo, p, vd_path, vpp_index);
			else
				bypass_hdr_process(csc_type, vinfo, p,
						   vd_path, source_type, vpp_index);
			pr_csc(1, "vd_path = %d\n"
			       "\thdr_process_mode = 0x%x\n"
			       "\thlg_process_mode = 0x%x.\n",
			       vd_path + 1,
			       hdr_process_mode[vd_path],
			       hlg_process_mode[vd_path]);
		}
	} else if ((csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) &&
		(hdr_process_mode[vd_path] == PROC_MATCH) &&
		(hlg_process_mode[vd_path] == PROC_BYPASS)) {
		/* hdr->sdr hlg->hlg*/
		if ((signal_change_flag &
		     (SIG_CS_CHG |
		      SIG_PRI_INFO |
		      SIG_KNEE_FACTOR |
		      SIG_HDR_MODE |
		      SIG_HDR_SUPPORT |
		      SIG_HLG_MODE |
		      SIG_HDR_OOTF_CHG)) ||
		    cur_csc_type[vd_path] < VPP_MATRIX_BT2020YUV_BT2020RGB) {
			if (get_hdr_type() & HLG_FLAG)
				bypass_hdr_process(csc_type, vinfo, p,
						   vd_path, source_type, vpp_index);
			else
				need_adjust_contrast_saturation =
					hdr_process(csc_type, vinfo, p,
						    vd_path, source_type, vpp_index);
			pr_csc(1, "vd_path = %d\n"
				"\thdr_process_mode = 0x%x\n"
				"\thlg_process_mode = 0x%x.\n",
				vd_path + 1,
				hdr_process_mode[vd_path],
				hlg_process_mode[vd_path]);
		}
	} else if ((csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) &&
		(hdr_process_mode[vd_path] == PROC_BYPASS) &&
		(hlg_process_mode[vd_path] == PROC_BYPASS)) {
		/* hdr->hdr hlg->hlg*/
		if ((signal_change_flag &
		     (SIG_CS_CHG |
		      SIG_PRI_INFO |
		      SIG_KNEE_FACTOR |
		      SIG_HDR_MODE |
		      SIG_HDR_SUPPORT |
		      SIG_HLG_MODE |
		      SIG_HDR_OOTF_CHG)) ||
		    cur_csc_type[vd_path] < VPP_MATRIX_BT2020YUV_BT2020RGB) {
			bypass_hdr_process(csc_type, vinfo, p,
					   vd_path, source_type, vpp_index);
			pr_csc(1, "vd_path = %d\n"
				"bypass_hdr_process: 0x%x, 0x%x.\n",
				vd_path + 1,
				hdr_process_mode[vd_path],
				hlg_process_mode[vd_path]);
		}
	} else if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC) {
		if ((signal_change_flag & SIG_HDR10_PLUS_MODE) ||
		    cur_csc_type[vd_path] !=
		    VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC) {
			// TODO: hdr10_plus_process(vf, mode, vd_path);
			if (hdr10_plus_process_mode[vd_path] == PROC_MATCH) {
				hdr10p_process(csc_type, vinfo, p, vd_path, source_type, vpp_index);
				/* hdr10_plus_process(vf); */
			} else {
				bypass_hdr_process(csc_type, vinfo, p,
						   vd_path, source_type, vpp_index);
			}
		}
		pr_csc(1, "vd_path = %d\nhdr10_plus_process.\n",
		       vd_path + 1);
	} else {
		if (csc_type < VPP_MATRIX_BT2020YUV_BT2020RGB &&
		    sdr_process_mode[vd_path]) {
			/* for gxl and gxm SDR to HDR process */
			sdr_hdr_process(csc_type,
					vinfo, p, vd_path, source_type, vpp_index);
		} else {
			/* for gxtvbb and gxl HDR bypass process */
			if (((vinfo->hdr_info.hdr_support & HDR_SUPPORT) ||
			     (vinfo->hdr_info.hdr_support & HLG_SUPPORT)) &&
			    csc_type < VPP_MATRIX_BT2020YUV_BT2020RGB &&
			    tx_op_color_primary) {
				set_bt2020csc_process(csc_type,
						      vinfo, p, vd_path);
			} else {
				bypass_hdr_process(csc_type,
						   vinfo, p,
						   vd_path, source_type,
						   vpp_index);
			}
			pr_csc(1, "vd_path = %d\n"
			       "\tcsc_type = 0x%x\n"
			       "\thdr_process_mode = %d.\n"
			       "\thlg_process_mode = %d.\n"
			       "\thdr10_plus_process_mode = %d.\n",
			       vd_path + 1,
			       csc_type,
			       hdr_process_mode[vd_path],
			       hlg_process_mode[vd_path],
			       hdr10_plus_process_mode[vd_path]);
		}
	}

	if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
		if (!(vinfo->mode == VMODE_LCD ||
			vinfo->mode == VMODE_DUMMY_ENCP)) {
			if (vpp_index == VPP_TOP1)
				mtx_setting(VPP1_POST2_MTX, MATRIX_NULL, MTX_OFF);
			else if (vpp_index == VPP_TOP2)
				mtx_setting(VPP2_POST2_MTX, MATRIX_NULL, MTX_OFF);
			else
				mtx_setting(POST2_MTX, MATRIX_NULL, MTX_OFF);
		} else {
			if (vf && vf->type & VIDTYPE_RGB_444 &&
			    source_type[vd_path] == HDRTYPE_SDR) {
				WRITE_VPP_REG_BITS(VPP_VADJ1_MISC, 0, 1, 1);
				WRITE_VPP_REG_BITS(VPP_VADJ2_MISC, 0, 1, 1);
				if (vpp_index == VPP_TOP1)
					mtx_setting(VPP1_POST2_MTX,
						MATRIX_YUV709F_RGB, MTX_ON);
				else if (vpp_index == VPP_TOP2)
					mtx_setting(VPP2_POST2_MTX,
						MATRIX_YUV709F_RGB, MTX_ON);
				else
					mtx_setting(POST2_MTX,
						MATRIX_YUV709F_RGB, MTX_ON);
			} else {
				WRITE_VPP_REG_BITS(VPP_VADJ1_MISC, 1, 1, 1);
				WRITE_VPP_REG_BITS(VPP_VADJ2_MISC, 1, 1, 1);
				if (vpp_index == VPP_TOP1)
					mtx_setting(VPP1_POST2_MTX,
					    (enum mtx_csc_e)csc_type, MTX_ON);
				else if (vpp_index == VPP_TOP2)
					mtx_setting(VPP2_POST2_MTX,
					    (enum mtx_csc_e)csc_type, MTX_ON);
				else
					mtx_setting(POST2_MTX,
						(enum mtx_csc_e)csc_type, MTX_ON);
			}
		}
	}

	if (cur_hdr_process_mode[vd_path] != hdr_process_mode[vd_path]) {
		cur_hdr_process_mode[vd_path] =
			hdr_process_mode[vd_path];
		pr_csc(1, "vd_path = %d\n"
		       "hdr_process_mode changed to %d\n",
		       vd_path + 1, hdr_process_mode[vd_path]);
	}
	if (cur_sdr_process_mode[vd_path] != sdr_process_mode[vd_path]) {
		cur_sdr_process_mode[vd_path] =
			sdr_process_mode[vd_path];
		pr_csc(1, "vd_path = %d\nsdr_process_mode changed to %d\n",
		       vd_path + 1, sdr_process_mode[vd_path]);
	}
	if (cur_hlg_process_mode[vd_path] != hlg_process_mode[vd_path]) {
		cur_hlg_process_mode[vd_path] =
			hlg_process_mode[vd_path];
		pr_csc(1, "vd_path = %d\nhlg_process_mode changed to %d\n",
		       vd_path + 1, hlg_process_mode[vd_path]);
	}
	if (cur_hdr10_plus_process_mode[vd_path] !=
	    hdr10_plus_process_mode[vd_path]) {
		cur_hdr10_plus_process_mode[vd_path] =
			hdr10_plus_process_mode[vd_path];
		pr_csc(1, "vd_path = %d\n"
		       "hdr10_plus_process_mode changed to %d\n",
		       vd_path + 1, hdr10_plus_process_mode[vd_path]);
	}
	if (cuva_hdr_process_mode[vd_path] !=
		cur_cuva_hdr_process_mode[vd_path]) {
		cuva_hdr_process_mode[vd_path] =
			cur_cuva_hdr_process_mode[vd_path];
		pr_csc(1, "vd_path = %d\n"
			"cuva_hdr_process_mode changed to %d\n",
			vd_path + 1, cuva_hdr_process_mode[vd_path]);
	}
	if (cuva_hlg_process_mode[vd_path] !=
		cur_cuva_hlg_process_mode[vd_path]) {
		cuva_hlg_process_mode[vd_path] =
			cur_cuva_hlg_process_mode[vd_path];
		pr_csc(1, "vd_path = %d\n"
			"cur_cuva_hlg_process_mode changed to %d\n",
			vd_path + 1, cuva_hlg_process_mode[vd_path]);
	}
	if (need_adjust_contrast_saturation & 1) {
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
		if (lut_289_en &&
		    get_cpu_type() <= MESON_CPU_MAJOR_ID_GXTVBB) {
			vd1_contrast_offset = 0;
		} else {
#else
		{
#endif
			vd1_contrast_offset =
			calculate_contrast_adj(p->luminance[0] / 10000);
		}
		vecm_latch_flag |= FLAG_VADJ1_CON;
	} else {
		vd1_contrast_offset = 0;
		vecm_latch_flag |= FLAG_VADJ1_CON;
	}
	if (need_adjust_contrast_saturation & 2) {
		vecm_latch_flag |= FLAG_VADJ1_COLOR;
	} else {
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
		if ((get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB ||
		     get_cpu_type() == MESON_CPU_MAJOR_ID_TXL) &&
		    sdr_process_mode[vd_path] == PROC_SDR_TO_HDR) {
			saturation_offset = sdr_saturation_offset;
		} else {
#else
		{
#endif
			saturation_offset = 0;
		}
		vecm_latch_flag |= FLAG_VADJ1_COLOR;
	}
	if (cur_csc_type[vd_path] != csc_type) {
		pr_csc(1, "vd_path = %d\n"
		       "\tcsc from 0x%x to 0x%x.\n"
		       "contrast offset = %d.\n"
		       "saturation offset = %d.\n",
		       vd_path + 1, cur_csc_type[vd_path], csc_type,
		       vd1_contrast_offset, saturation_offset);
		cur_csc_type[vd_path] = csc_type;
	}
}
#endif

static int current_hdr_cap[VD_PATH_MAX] = {-1, -1, -1}; /* should set when probe */
static int current_sink_available[VD_PATH_MAX] = {-1, -1, -1};
#endif

int is_sink_cap_changed(const struct vinfo_s *vinfo,
			int *p_current_hdr_cap,
			int *p_current_sink_available,
			enum vpp_index_e vpp_index)
{
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	int hdr_cap;
	int sink_available;
#endif
	int ret = 0;
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	if (vinfo && is_vinfo_available(vinfo)) {
		hdr_cap = (1 << 0) |
			(sink_support_dv(vinfo) << 1) |
			(sink_support_hdr10_plus(vinfo) << 2) |
			(sink_support_hdr(vinfo) << 3) |
			(sink_support_hlg(vinfo) << 4);
		sink_available = 1;
	} else {
		hdr_cap = 0;
		*p_current_hdr_cap = 0;
		sink_available = 0;
	}

	if (*p_current_hdr_cap == -1) {
		*p_current_hdr_cap = hdr_cap;
		ret |= 4;
	} else if (*p_current_hdr_cap != hdr_cap) {
		*p_current_hdr_cap = hdr_cap;
		ret |= 2;
	}
	if (*p_current_sink_available != sink_available) {
		*p_current_sink_available = sink_available;
		ret |= 1;
	}
#endif
	return ret;
}
EXPORT_SYMBOL(is_sink_cap_changed);

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static bool video_on[VD_PATH_MAX];
#endif

int is_video_turn_on(bool *vd_on, enum vd_path_e vd_path)
{
	int ret = 0;

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	if (vd_on[vd_path] != is_video_layer_on(vd_path)) {
		vd_on[vd_path] = is_video_layer_on(vd_path);
		ret = vd_on[vd_path] ? 1 : -1;
	}
#endif
	return ret;
}
EXPORT_SYMBOL(is_video_turn_on);

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static int vpp_matrix_update(struct vframe_s *vf,
			     struct vinfo_s *vinfo, int flags,
			     enum vd_path_e vd_path, enum vpp_index_e vpp_index)
{
	enum vpp_matrix_csc_e csc_type = VPP_MATRIX_NULL;
	int signal_change_flag = 0;
	struct vframe_master_display_colour_s *p =
		&cur_master_display_colour[vd_path];
	int hdmi_scs_type_changed = 0;
	bool hdr10p_meta_updated = false;
	bool cuva_meta_updated = false;
	enum hdr_type_e source_format[VD_PATH_MAX];
	static struct hdr10plus_para *para;
	static int signal_change_latch;
	int i, k;

	if (!vinfo || vinfo->mode == VMODE_NULL ||
	    vinfo->mode == VMODE_INVALID)
		return 0;

	/* Tx hdr information */
	memcpy(&receiver_hdr_info, &vinfo->hdr_info,
	       sizeof(struct hdr_info));

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A) ||
	    get_cpu_type() == MESON_CPU_MAJOR_ID_TL1)
		hdr_support_process(vinfo, vd_path, vpp_index);
#endif

	if (vf && vinfo)
		signal_change_flag =
			signal_type_changed(vf, vinfo, vd_path, vpp_index);

	if ((flags & CSC_FLAG_CHECK_OUTPUT) &&
	    (signal_change_flag & (SIG_PRI_INFO | SIG_CS_CHG))) {
		if (signal_change_flag & SIG_PRI_INFO)
			signal_change_latch |= SIG_PRI_INFO;
		if (signal_change_flag & SIG_CS_CHG)
			signal_change_latch |= SIG_CS_CHG;
	} else if (flags & CSC_FLAG_TOGGLE_FRAME) {
		signal_change_flag |= signal_change_latch;
		signal_change_latch = 0;
	}

	if (flags & CSC_FLAG_FORCE_SIGNAL)
		signal_change_flag |= SIG_FORCE_CHG;

	get_cur_vd_signal_type(vd_path);
	if (force_csc_type != 0xff) {
		csc_type = force_csc_type;
		cur_primesl_type[vd_path] = 0;
	} else {
		csc_type = get_csc_type();
		/* force prime sl output as HDR */
		/* TODO: check if need VD1_PATH */
		if (get_vframe_src_fmt(vf) == VFRAME_SIGNAL_FMT_HDR10PRIME) {
			csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB;
			cur_primesl_type[vd_path] = 1;
		} else {
			cur_primesl_type[vd_path] = 0;
		}
	}

	if (video_process_status[vd_path] == HDR_MODULE_BYPASS &&
	    !(video_process_flags[vd_path] & PROC_FLAG_FORCE_PROCESS)) {
		if ((is_video_layer_on(vd_path) ||
		     video_layer_wait_on[vd_path]) && // TODO  should we add vd3 here
		    (!is_amdv_on() || vd_path == VD2_PATH || vd_path == VD3_PATH)) {
			video_process_status[vd_path] = HDR_MODULE_ON;
			pr_csc(4,
			       "%d:set video_process_status[%s] = HDR_MODULE_ON\n",
			       __LINE__, vd_path == VD1_PATH ? "VD1" : "VD2");
		} else {
			return 2;
		}
	}

	/*used for force process when repeat frame, run the full flow*/
	if (video_process_status[vd_path] == HDR_MODULE_ON &&
	    (video_process_flags[vd_path] & PROC_FLAG_FORCE_PROCESS))
		signal_change_flag |= SIG_FORCE_CHG;

	if (is_amdv_on() &&
	    (vd_path == VD1_PATH ||
	    !cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)))
		return 0;

	if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A) &&
	    get_cpu_type() != MESON_CPU_MAJOR_ID_TL1) {
		enum vd_path_e oth_path[VD_PATH_MAX - 1];

		k = 0;
		for (i = 0; i < VD_PATH_MAX; i++) {
			if (i != vd_path) {
				oth_path[k] = i;
				k++;
			}
		}

		if (get_hdr_policy() != cur_hdr_policy) {
			pr_csc(4, "policy changed from %d to %d.\n",
			       cur_hdr_policy,
			       get_hdr_policy());
			signal_change_flag |= SIG_HDR_MODE;
		}

		if (get_primary_policy() != cur_primary_policy) {
			pr_csc(4, "primary policy changed from %d to %d.\n",
			       cur_primary_policy,
			       get_primary_policy());
			signal_change_flag |= SIG_HDR_MODE;
		}

		source_format[VD1_PATH] = get_source_type(VD1_PATH, vpp_index);
		source_format[VD2_PATH] = get_source_type(VD2_PATH, vpp_index);
		source_format[VD3_PATH] = get_source_type(VD3_PATH, vpp_index);
		get_cur_vd_signal_type(vd_path);
#ifdef T7_BRINGUP_MULTI_VPP
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
		if (get_cpu_type() == MESON_CPU_MAJOR_ID_T7)
			signal_change_flag |=
			hdr_policy_process_t7(vinfo, source_format, vd_path);
		else
#endif
			signal_change_flag |=
			hdr_policy_process(vinfo, source_format, vd_path, vpp_index);
#else
		signal_change_flag |=
			hdr_policy_process(vinfo, source_format, vd_path, vpp_index);
#endif

		if (signal_change_flag & SIG_OUTPUT_MODE_CHG) {
			if (!is_video_layer_on(vd_path))
				video_layer_wait_on[vd_path] = true;
			for (i = 0; i < VD_PATH_MAX - 1; i++)
				video_process_flags[oth_path[i]] |=
				PROC_FLAG_FORCE_PROCESS;
			return 1;
		}
	} else {
		source_format[vd_path] = get_hdr_source_type();
	}

	if (vf && ((flags & (CSC_FLAG_TOGGLE_FRAME | CSC_FLAG_FORCE_SIGNAL)) ||
		(signal_change_flag & SIG_FORCE_CHG))) {
		hdr10p_meta_updated =
		hdr10_plus_metadata_update(vf, csc_type,
					   &hdmitx_hdr10plus_params[vd_path]);
		cuva_meta_updated =
			cuva_metadata_update(vf, csc_type,
			&hdmitx_vsif_params[vd_path],
			&hdmitx_edms_params[vd_path]);

		if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC ||
			csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB ||
			csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB_CUVA) {
			if (chip_type_id == chip_s5 || chip_type_id == chip_t3x)
				s5_get_hist(vd_path, HIST_E_RGBMAX);
			else if (cpu_after_eq(MESON_CPU_MAJOR_ID_TM2))
				get_hist(vd_path, HIST_E_RGBMAX);
			else if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A))
				get_hist(vd_path, HIST_E_RGBMAX);
		}
	}

#ifdef T7_BRINGUP_MULTI_VPP
	if (get_cpu_type() == MESON_CPU_MAJOR_ID_T7) {
		// TODO
		// support vd3
		//
	} else if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) {
		if (vd_path == VD1_PATH ||
		    (vd_path == VD2_PATH &&
		     !is_video_layer_on(VD1_PATH) &&
		     is_video_layer_on(VD2_PATH) &&
		     !is_amdv_on())) {
			para =
			hdr10p_meta_updated ?
			&hdmitx_hdr10plus_params[vd_path] : NULL;
			hdmi_packet_process(signal_change_flag, vinfo, p,
					    para,
					    vd_path, source_format, vpp_index);
		}
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	} else {
		if (vd_path == VD1_PATH ||
		    (vd_path == VD2_PATH &&
		     !is_video_layer_on(VD1_PATH)))
			hdr_tx_pkt_cb(vinfo,
				      signal_change_flag,
				      csc_type,
				      p,
				      &hdmi_scs_type_changed,
				      &hdmitx_hdr10plus_params[vd_path],
				      vd_path, vpp_index);
#endif
	}
#else
	if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) {
		if (vd_path == VD1_PATH ||
		    (vd_path == VD2_PATH &&
		     !is_video_layer_on(VD1_PATH) &&
		     is_video_layer_on(VD2_PATH)) ||
		     (!is_video_layer_on(VD1_PATH) &&
		     !is_video_layer_on(VD2_PATH) &&
		     !is_amdv_on()) ||
		     vpp_index == VPP_TOP1) {
			para =
			hdr10p_meta_updated ?
			&hdmitx_hdr10plus_params[vd_path] : NULL;
			hdmi_packet_process(signal_change_flag, vinfo, p,
					    para, cuva_meta_updated ?
					    &hdmitx_vsif_params[vd_path] : NULL,
					    cuva_meta_updated ?
					    &hdmitx_edms_params[vd_path] : NULL,
					    vd_path, source_format, vpp_index);
		}
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	} else {
		if (vd_path == VD1_PATH ||
		    (vd_path == VD2_PATH &&
		     !is_video_layer_on(VD1_PATH)))
			hdr_tx_pkt_cb(vinfo,
				      signal_change_flag,
				      csc_type,
				      p,
				      &hdmi_scs_type_changed,
				      &hdmitx_hdr10plus_params[vd_path],
				      &hdmitx_vsif_params[vd_path],
				      &hdmitx_edms_params[vd_path],
				      vd_path, vpp_index);
#endif
	}

#endif

	if (hdmi_scs_type_changed &&
	    (flags & CSC_FLAG_CHECK_OUTPUT) &&
	    (csc_en & 0x10))
		return 1;

	if ((!signal_change_flag && force_csc_type == 0xff) &&
	    ((flags & CSC_FLAG_TOGGLE_FRAME) == 0))
		return 0;

	if (cur_csc_type[vd_path] != csc_type ||
	    (signal_change_flag &
	     (SIG_CS_CHG | SIG_PRI_INFO | SIG_KNEE_FACTOR | SIG_HDR_MODE |
	      SIG_HDR_SUPPORT | SIG_HLG_MODE | SIG_OP_CHG |
	      SIG_SRC_OUTPUT_CHG | SIG_HDR10_PLUS_MODE |
	      SIG_SRC_CHG | SIG_HDR_OOTF_CHG | SIG_FORCE_CHG |
	      SIG_CUVA_HDR_MODE | SIG_CUVA_HLG_MODE))) {
#ifdef T7_BRINGUP_MULTI_VPP
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
		if (get_cpu_type() == MESON_CPU_MAJOR_ID_T7)
			video_post_process_t7(vf, csc_type, vinfo,
					      vd_path, p, source_format);
		else
#endif
		if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A) &&
			 (get_cpu_type() != MESON_CPU_MAJOR_ID_TL1))
			video_post_process(vf, csc_type, vinfo,
					   vd_path, p, source_format, vpp_index);
		else
			video_process(vf, csc_type, signal_change_flag,
				      vinfo, p, vd_path, source_format, vpp_index);
#else
		if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A) &&
			 (get_cpu_type() != MESON_CPU_MAJOR_ID_TL1))
			video_post_process(vf, csc_type, vinfo,
					   vd_path, p, source_format, vpp_index);
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
		else
			video_process(vf, csc_type, signal_change_flag,
				      vinfo, p, vd_path, source_format, vpp_index);
#endif

#endif
		cur_hdr_policy = get_hdr_policy();
		cur_primary_policy = get_primary_policy();
	}

	if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A) &&
	    (get_cpu_type() != MESON_CPU_MAJOR_ID_TL1)) {
		if (hdr_process_mode[vd_path] == PROC_HDR_TO_SDR &&
		    csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB &&
			!(get_hdr_type() & HLG_FLAG))
			hdr10_tm_process_update(p, vd_path, vpp_index);
		if (hdr10p_meta_updated &&
		    hdr10_plus_process_mode[vd_path] == PROC_HDRP_TO_SDR)
			hdr10_plus_process_update(0, vd_path, vpp_index);
	}
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	else if (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1) {
		if (hdr_process_mode[vd_path] == PROC_MATCH &&
		    csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB &&
			!(get_hdr_type() & HLG_FLAG))
			hdr10_tm_process_update(p, vd_path, vpp_index);
		if (hdr10p_meta_updated &&
		    hdr10_plus_process_mode[vd_path] == PROC_MATCH)
			hdr10_plus_process_update(0, vd_path, vpp_index);
	}
#endif
	if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A) &&
	    csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB_CUVA) {
		if (get_hdr_type() & HLG_FLAG)
			cuva_hdr_process_update(source_format[vd_path],
				cuva_hlg_process_mode[vd_path],
				vd_path, p, vpp_index);
		else
			cuva_hdr_process_update(source_format[vd_path],
				cuva_hdr_process_mode[vd_path],
				vd_path, p, vpp_index);
	}

	if (ai_color_enable)
		ai_color_proc(vf);

	/* eye protection mode */
	if (signal_change_flag & SIG_WB_CHG)
		vpp_eye_protection_process(csc_type, vinfo, vd_path);

	if (rgb_type_proc[vd_path] == FORCE_RGB_PROCESS)
		rgb_type_proc[vd_path] &= ~FORCE_RGB_PROCESS;

	return 0;
}

static struct vframe_s last_vf_backup[VD_PATH_MAX];
static struct vframe_s *last_vf[VD_PATH_MAX];
static int last_vf_signal_type[VD_PATH_MAX];
static int null_vf_cnt[VD_PATH_MAX] = {2, 2, 2};
static int prev_color_fmt[3];
static int prev_vmode[3] = {0xff, 0xff, 0xff};
static bool dovi_on;

static unsigned int fg_vf_sw_dbg;
unsigned int null_vf_max = 2;
module_param(null_vf_max, uint, 0664);
MODULE_PARM_DESC(null_vf_max, "\n null_vf_max\n");

int amvecm_matrix_process(struct vframe_s *vf,
			  struct vframe_s *vf_rpt, int flags,
			  enum vd_path_e vd_path, enum vpp_index_e vpp_index)
{
	static struct vframe_s fake_vframe;
	struct vinfo_s *vinfo;
	int toggle_frame = 0;
	int i, size;
	int ret;
	int sink_changed = 0;
	bool cap_changed = false;
	bool send_fake_frame = false;
	struct vframe_master_display_colour_s *pa;
	static bool amdv_enable;
	int s5_silce_mode = get_s5_slice_mode();

	if (vpp_index == VPP_TOP1)
		vinfo = get_current_vinfo2();
	#ifdef CONFIG_AMLOGIC_VOUT3_SERVE
	else if (vpp_index == VPP_TOP2)
		vinfo = get_current_vinfo3();
	#endif
	else
		vinfo = get_current_vinfo();

	if (is_vpp1(VD2_PATH) &&
		((vd_path == VD2_PATH &&
		vpp_index != VPP_TOP1)))
		return 0;

	pr_csc(1, "%s: vd_path = %d vpp_index = %d\n",
		__func__, vd_path, vpp_index);
	if (get_cpu_type() < MESON_CPU_MAJOR_ID_GXTVBB ||
	    is_meson_gxl_package_905M2() || csc_en == 0 || !vinfo)
		return 0;

	if (vinfo->mode == VMODE_NULL ||
	    vinfo->mode == VMODE_INVALID) {
		current_hdr_cap[vpp_index] = 0;
		current_sink_available[vpp_index] = 0;
		return 0;
	}

	if (reload_mtx) {
		for (i = 0; i < NUM_MATRIX; i++)
			if (reload_mtx & (1 << i))
				set_vpp_matrix(i, NULL, CSC_ON);
	}

	if (reload_lut) {
		for (i = 0; i < NUM_LUT; i++)
			if (reload_lut & (1 << i))
				set_vpp_lut(i,
					    NULL, /* R */
					    NULL, /* G */
					    NULL, /* B */
					    CSC_ON);
	}

	pr_csc(16, "amvecm process vd%d %s %p %p, %d, %d\n",
		vd_path + 1,
		is_video_layer_on(vd_path) ? "on" : "off",
		vf, vf_rpt, is_amdv_on(), dovi_on);
	if (vd_path == VD1_PATH) {
		if (is_amdv_on()) {
			if (!dovi_on) {
				if (s5_silce_mode == VD1_1SLICE) {
					hdr_func(VD1_HDR, HDR_BYPASS,
						 get_current_vinfo(),
						 NULL, vpp_index);
				} else if (s5_silce_mode == VD1_2SLICE) {
					hdr_func(VD1_HDR, HDR_BYPASS,
						 get_current_vinfo(),
						 NULL, vpp_index);
					hdr_func(S5_VD1_SLICE1, HDR_BYPASS,
						 get_current_vinfo(),
						 NULL, vpp_index);
				} else if (s5_silce_mode == VD1_4SLICE) {
					hdr_func(VD1_HDR, HDR_BYPASS,
						 get_current_vinfo(),
						 NULL, vpp_index);
					hdr_func(S5_VD1_SLICE1, HDR_BYPASS,
						 get_current_vinfo(),
						 NULL, vpp_index);
					hdr_func(S5_VD1_SLICE2, HDR_BYPASS,
						 get_current_vinfo(),
						 NULL, vpp_index);
					hdr_func(S5_VD1_SLICE3, HDR_BYPASS,
						 get_current_vinfo(),
						 NULL, vpp_index);
				}
			}
			dovi_on = true;
			if (video_process_status[vd_path]
				== HDR_MODULE_BYPASS &&
				(vf || vf_rpt))
				return vpp_matrix_update(vf ? vf : vf_rpt,
					vinfo,
					flags,
					vd_path,
					vpp_index);
			else
				return 0;
		} else {
			/* dv from on to off */
			if (dovi_on) {
				cap_changed = true;
				if (flags &
				    (CSC_FLAG_TOGGLE_FRAME |
				    CSC_FLAG_CHECK_OUTPUT))
					flags |= CSC_FLAG_FORCE_SIGNAL;
				dovi_on = false;
			}
		}
	}
	sink_changed = is_sink_cap_changed(vinfo,
					   &current_hdr_cap[vpp_index],
					   &current_sink_available[vpp_index],
					   vpp_index);
	if (sink_changed) {
		cap_changed = sink_changed & 0x02;
		pr_csc(4, "sink %s, cap%s 0x%x, vd%d %s %p %p vpp%d hdr_cap = 0x%x\n",
		       current_sink_available[vpp_index] ? "on" : "off",
		       cap_changed ? " changed" : "",
		       current_hdr_cap[vpp_index],
		       vd_path + 1,
		       is_video_layer_on(vd_path) ? "on" : "off",
		       vf, vf_rpt, vpp_index,
		       sink_hdr_support(vinfo));
	}

	if (is_video_turn_on(video_on, vd_path) == 1)
		cap_changed = true;

	if (vf && (flags & CSC_FLAG_CHECK_OUTPUT)) {
		ret = vpp_matrix_update(vf, vinfo, flags, vd_path, vpp_index);
		if (ret == 1) {
			pr_csc(2, "vd%d: hold frame when output changing\n",
			       vd_path + 1);
			return 1;
		} else if (ret == 2) {
			pr_csc(2, "vd%d: hold frame when video off\n",
			       vd_path + 1);
			return 2;
		}
	} else if (vf && (flags & CSC_FLAG_TOGGLE_FRAME)) {
		if (is_video_layer_on(vd_path) ||
		    video_layer_wait_on[vd_path] ||
		    video_process_flags[vd_path] & PROC_FLAG_FORCE_PROCESS) {
			if (video_process_status[vd_path] != HDR_MODULE_ON) {
				video_process_status[vd_path] = HDR_MODULE_ON;
				pr_csc(4,
				       "%d:set video_process_status[VD%d] = MODULE_ON new vf\n",
				       __LINE__, vd_path + 1);
			}
			vpp_matrix_update(vf, vinfo, flags, vd_path, vpp_index);
			video_process_flags[vd_path] &= ~PROC_FLAG_FORCE_PROCESS;
			memcpy(&last_vf_backup[vd_path], vf,
			       sizeof(struct vframe_s));
			last_vf[vd_path] = &last_vf_backup[vd_path];
			last_vf_signal_type[vd_path] = vf->signal_type;
			null_vf_cnt[vd_path] = 0;
			pr_csc(2, "vd%d: process toggle frame(%p) %x\n",
			       vd_path + 1,
			       vf, vf->signal_type);
		} else {
			pr_csc(2, "vd%d: skip process frame(%p) %x\n",
			       vd_path + 1,
			       vf, vf->signal_type);
		}
		fg_vf_sw_dbg = 1;
		/* debug vframe info backup */
		dbg_vf[vd_path] = vf;
	} else if (vf_rpt &&
		(is_video_layer_on(vd_path) ||
		video_layer_wait_on[vd_path])) {
		if ((video_process_flags[vd_path] & PROC_FLAG_FORCE_PROCESS) ||
		    cap_changed) {
			if (video_process_status[vd_path] != HDR_MODULE_ON) {
				video_process_status[vd_path] = HDR_MODULE_ON;
				pr_csc(4,
				       "%d:set video_process_status[VD%d] = MODULE_ON rpt vf\n",
				       __LINE__, vd_path + 1);
			}
			vpp_matrix_update(vf_rpt, vinfo, flags, vd_path, vpp_index);
			video_process_flags[vd_path] &= ~PROC_FLAG_FORCE_PROCESS;
			pr_csc(4, "vd%d: rpt and process frame(%p)\n",
			       vd_path + 1, vf_rpt);
		} else {
			pr_csc(2, "vd%d: rpt frame(%p)\n", vd_path + 1, vf_rpt);
		}
		null_vf_cnt[vd_path] = 0;
		fg_vf_sw_dbg = 2;
	} else if (last_vf[vd_path] &&
		(is_video_layer_on(vd_path) ||
		video_layer_wait_on[vd_path])) {
		if (video_process_flags[vd_path] & PROC_FLAG_FORCE_PROCESS ||
		    cap_changed) {
			vpp_matrix_update(last_vf[vd_path],
					  vinfo, flags, vd_path, vpp_index);
			video_process_flags[vd_path] &= ~PROC_FLAG_FORCE_PROCESS;
			pr_csc(4, "vd%d: rpt and process frame local(%p)\n",
			       vd_path + 1, last_vf[vd_path]);
		} else {
			pr_csc(2, "vd%d: rpt frame local\n",
			       vd_path + 1);
		}
		null_vf_cnt[vd_path] = 0;
		fg_vf_sw_dbg = 3;
	} else {
		bool force_fake = false;

		last_vf[vd_path] = NULL;

		if (null_vf_cnt[vd_path] <= null_vf_max)
			null_vf_cnt[vd_path]++;

		/* handle change between TV support/not support HDR */
		if (cap_changed) {
			if (is_video_layer_on(vd_path))
				null_vf_cnt[vd_path] = 0;
			else
				force_fake = true;
			pr_csc(4, "vd%d: sink cap changed when idle\n",
			       vd_path + 1);
		}

		/* handle change between output mode*/
		if (prev_vmode[vpp_index] != vinfo->mode) {
			if (is_video_layer_on(vd_path))
				null_vf_cnt[vd_path] = 0;
			else
				force_fake = true;
			prev_vmode[vpp_index] = vinfo->mode;
			pr_csc(4, "vd%d: output display mode changed\n",
			       vd_path + 1);
		}

		/* handle change between output mode*/
		if (prev_color_fmt[vpp_index] != vinfo->viu_color_fmt) {
			if (is_video_layer_on(vd_path))
				null_vf_cnt[vd_path] = 0;
			else
				force_fake = true;
			prev_color_fmt[vpp_index] = vinfo->viu_color_fmt;
			pr_csc(4, "vd%d: output color format changed\n",
			       vd_path + 1);
			pr_csc(4, "p_c_fmt[top%d] = %d v_c_fmt = %d",
				   vpp_index,
				   prev_color_fmt[vpp_index],
				   vinfo->viu_color_fmt);
		}

		/* handle eye protect mode */
		if (cur_eye_protect_mode != wb_val[0] &&
		    vd_path == VD1_PATH) {
			if (is_video_layer_on(vd_path))
				null_vf_cnt[vd_path] = 0;
			else
				force_fake = true;
			pr_csc(4, "vd%d: eye_protect_mode changed\n",
			       vd_path + 1);
		}

		/* gxl handle sdr_mode change bug fix. */
		if ((sink_hdr_support(vinfo) & HDR_SUPPORT) &&
		    !cpu_after_eq(MESON_CPU_MAJOR_ID_G12A) &&
		    (!(vinfo->mode == VMODE_LCD ||
		    vinfo->mode == VMODE_DUMMY_ENCP))) {
			if (sdr_mode != cur_sdr_mode) {
				force_fake = true;
				cur_sdr_mode = sdr_mode;
				pr_csc(4, "vd%d: sdr_mode changed\n",
				       vd_path + 1);
			}
		}

		/* handle sdr_mode change */
		if (is_video_layer_on(vd_path) &&
		    (sink_hdr_support(vinfo) & HDR_SUPPORT) &&
		    ((cpu_after_eq(MESON_CPU_MAJOR_ID_GXL)) &&
		     (!(vinfo->mode == VMODE_LCD ||
		     vinfo->mode == VMODE_DUMMY_ENCP)))) {
			if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) {
				if (sdr_mode != cur_sdr_mode) {
					null_vf_cnt[vd_path] = 0;
					cur_sdr_mode = sdr_mode;
					pr_csc(4, "vd%d: sdr_mode changed\n",
					       vd_path + 1);
				}
			} else {
				if ((sdr_process_mode[vd_path] != PROC_SDR_TO_HDR &&
				     sdr_mode > 0) ||
				    (sdr_process_mode[vd_path] > PROC_BYPASS &&
				     sdr_process_mode[vd_path] != PROC_OFF &&
				     sdr_mode == 0)) {
					null_vf_cnt[vd_path] = 0;
					pr_csc(4, "vd%d: sdr_mode changed\n",
					       vd_path + 1);
				}
			}
		}
		if (!is_amdv_enable() &&
		    get_hdr_policy() != cur_hdr_policy) {
			null_vf_cnt[vd_path] = 1;
			toggle_frame = 1;
		} else if (!is_video_layer_on(vd_path) &&
			   (video_process_status[vd_path]
			    == HDR_MODULE_ON)) {
			null_vf_cnt[vd_path] = 1;
			toggle_frame = 1;
		} else if (force_fake) {
			null_vf_cnt[vd_path] = 1;
			toggle_frame = 1;
		} else if (csc_en & 0x10) {
			toggle_frame = null_vf_max;
		} else if (vd_path == VD1_PATH &&
			   amdv_enable && !is_amdv_enable()) {
			/*dv enable->disable*/
			null_vf_cnt[vd_path] = 1;
			toggle_frame = 1;
			pr_csc(8, "vd%d: dv enable->disable\n", vd_path + 1);
		} else {
			toggle_frame = 0;
		}
		if (vd_path == VD1_PATH)
			amdv_enable = is_amdv_enable();

		if (null_vf_cnt[vd_path] == toggle_frame) {
			if (null_vf_cnt[vd_path] == 0) {
				/* video on */
				video_process_flags[vd_path] |=
					PROC_FLAG_FORCE_PROCESS;
				return 0;
			}
			/* video off */
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
			int dv_hdr_policy = 0;

			if (is_amdv_enable()) {
				/* dolby enable */
				dv_hdr_policy = get_amdv_hdr_policy();
				pr_csc(8,
				       "vd%d: %d %d Fake SDR frame%s, dv on=%d, policy=%d, hdr policy=0x%x\n",
				       vd_path + 1,
				       null_vf_cnt[vd_path],
				       toggle_frame,
				       is_video_layer_on(vd_path) ?
				       " " : ", video off",
				       is_amdv_on(),
				       get_amdv_policy(),
				       dv_hdr_policy);
				if (vd_path == VD2_PATH || // TODO, add vd3??
				    (vd_path == VD1_PATH &&
				     (get_source_type(VD1_PATH, vpp_index) == HDRTYPE_HDR10PLUS ||
				      get_source_type(VD1_PATH, vpp_index) == HDRTYPE_MVC ||
				      get_source_type(VD1_PATH, vpp_index) == HDRTYPE_CUVA_HDR ||
				      get_source_type(VD1_PATH, vpp_index) == HDRTYPE_CUVA_HLG ||
				      ((get_dv_support_info() & 7) != 7) ||
				      (get_source_type(VD1_PATH, vpp_index) == HDRTYPE_HDR10 &&
				       !(dv_hdr_policy & 1)) ||
				      (get_source_type(VD1_PATH, vpp_index) == HDRTYPE_HLG &&
				       !(dv_hdr_policy & 2)) ||
				      (get_source_type(VD1_PATH, vpp_index) == HDRTYPE_SDR &&
				       !(dv_hdr_policy & 0x20))))) {
					/* and VD1 adaptive or VD2*/
					/* or always hdr hdr+/hlg bypass */
					/* faked vframe to switch matrix */
					/* 2020 to 601 when video disabled */
					/* and bypass hdr module for dv core*/
					send_fake_frame = true;
					video_process_status[vd_path] = HDR_MODULE_OFF;
					pr_csc(4,
					       "%d:set video_process_status[VD%d] = MODULE_OFF\n",
					       __LINE__, vd_path + 1);
				}
			} else {
#endif
				/* dolby disable */
				pr_csc(8,
				       "vd%d: %d %d Fake SDR frame%s, policy =%d, cur_policy =%d\n",
				       vd_path + 1,
				       null_vf_cnt[vd_path],
				       toggle_frame,
				       is_video_layer_on(vd_path) ?
				       " " : ", video off",
				       get_hdr_policy(),
				       cur_hdr_policy);
				send_fake_frame = true;
				if (get_hdr_policy() == 1) {
				/* adaptive hdr */
				/* faked vframe to switch matrix */
				/* turn off hdr module */
					video_process_status[vd_path] =
						HDR_MODULE_OFF;
					pr_csc(4,
					       "%d:set video_process_status[VD%d] = MODULE_OFF\n",
					       __LINE__, vd_path + 1);
				} else {
				/* always hdr */
				/* faked vframe to switch matrix */
				/* hdr module to handle osd */
					video_process_status[vd_path] =
						HDR_MODULE_ON;
					pr_csc(4,
					       "%d:set video_process_status[VD%d] = MODULE_ON\n",
					       __LINE__, vd_path + 1);
				}
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
			}
#endif

			if (send_fake_frame) {
				memset(&fake_vframe, 0x0,
				       sizeof(struct vframe_s));
				fake_vframe.source_type =
					VFRAME_SOURCE_TYPE_OTHERS;
				fake_vframe.signal_type = 0;
				fake_vframe.width = 1920;
				fake_vframe.height = 1080;
				pa = &fake_vframe.prop.master_display_colour;
				pa->present_flag = 0x80000000;
				fake_vframe.type = 0;
				size =
				sizeof(struct vframe_master_display_colour_s);
				memset(&fake_vframe.prop.master_display_colour,
				       0,
				       size);
				vpp_matrix_update(&fake_vframe, vinfo,
						  CSC_FLAG_TOGGLE_FRAME | CSC_FLAG_FORCE_SIGNAL,
						  vd_path, vpp_index);
				last_vf[vd_path] = NULL;
				null_vf_cnt[vd_path] = null_vf_max + 1;
				fg_vf_sw_dbg = 4;
				dbg_vf[vd_path] = NULL;
				video_process_status[vd_path] =
					HDR_MODULE_BYPASS;
				pr_csc(4,
				       "%d: set video_process_status[VD%d] = HDR_MODULE_BYPASS\n",
				       __LINE__, vd_path + 1);
				if (vd_path == VD2_PATH && // should we add vd3 here?? TODO
				    (is_video_layer_on(VD1_PATH) ||
				     video_layer_wait_on[VD1_PATH]))
					video_process_flags[VD1_PATH] |=
						PROC_FLAG_FORCE_PROCESS;
			}
		}
	}
	return 0;
}

void force_toggle(void)
{
	enum vd_path_e vd_path;

	for (vd_path = VD1_PATH; vd_path < VD_PATH_MAX; vd_path++) {
		if (null_vf_cnt[vd_path] == 0) {
			video_process_flags[vd_path] |=
				PROC_FLAG_FORCE_PROCESS;
			pr_csc(2, "vd%d: force toggle for API set\n",
				vd_path + 1);
		}
	}
}

int amvecm_hdr_dbg(u32 sel)
{
	int i, j, k;
	struct vframe_content_light_level_s *content_light_level;
	/* select debug information */
	if (sel == 1) /* dump reg */
		goto reg_dump;

	if (!dbg_vf[VD1_PATH] && !dbg_vf[VD2_PATH] && !dbg_vf[VD3_PATH])
		goto hdr_dump;

	for (k = 0; k < VD_PATH_MAX; k++) {
		if (!dbg_vf[k])
			continue;
		pr_info("----HDR VD%d frame info----\n", k + 1);
		pr_info("bitdepth:0x%x, signal_type:0x%x, present_flag:0x%x\n",
			dbg_vf[k]->bitdepth,
			dbg_vf[k]->signal_type,
			dbg_vf[k]->prop.master_display_colour.present_flag);

		if (((dbg_vf[k]->signal_type >> 16) & 0xff) == 9) {
			pr_info("HDR color primaries:0x%x\n",
				((dbg_vf[k]->signal_type >> 16) & 0xff));
			pr_info("HDR transfer_characteristic:0x%x\n",
				((dbg_vf[k]->signal_type >> 8) & 0xff));
		} else {
			pr_info("SDR color primaries:0x%x\n",
				signal_color_primaries);
		}

		if (dbg_vf[k]->prop.master_display_colour.present_flag == 1) {
			pr_info("----SEI info----\n");
			for (i = 0; i < 3; i++)
				for (j = 0; j < 2; j++)
					pr_info("\tprimaries[%1d][%1d] = %04x\n",
						i, j,
			dbg_vf[k]->prop.master_display_colour.primaries[i][j]);
			pr_info("\twhite_point = (%04x, %04x)\n",
				dbg_vf[k]->prop.master_display_colour.white_point[0],
				dbg_vf[k]->prop.master_display_colour.white_point[1]);
			pr_info("\tmax,min luminance = %08x, %08x\n",
				dbg_vf[k]->prop.master_display_colour.luminance[0],
				dbg_vf[k]->prop.master_display_colour.luminance[1]);
			content_light_level =
			&dbg_vf[k]->prop.master_display_colour.content_light_level;
			pr_info("\tcontent_light_level.present_flag = %08x\n",
				content_light_level->present_flag);
			pr_info("\tmax_content,min max_pic_average = %08x, %08x\n",
				content_light_level->max_content,
				content_light_level->max_pic_average);
		}
	}

	pr_info(HDR_VERSION);
hdr_dump:
	for (i = 0; i < VD_PATH_MAX; i++) {
		pr_info("----VD%d : HDR process info----\n", i + 1);
		pr_info("hdr_mode:0x%x, hdr_process_mode:0x%x, cur_hdr_process_mode:0x%x\n",
			hdr_mode, hdr_process_mode[i], cur_hdr_process_mode[i]);
		pr_info("hlg_process_mode: 0x%x\n",
			hlg_process_mode[i]);
		pr_info("sdr_mode:0x%x, sdr_process_mode:0x%x, cur_sdr_process_mode:0x%x\n",
			sdr_mode, sdr_process_mode[i], cur_sdr_process_mode[i]);
		pr_info("cur_signal_type:0x%x, cur_csc_mode:0x%x, cur_csc_type:0x%x, cur_primesl_type:%d\n",
			cur_signal_type[i], cur_csc_mode, cur_csc_type[i], cur_primesl_type[i]);
		pr_info("hdr10_plus_process_mode = 0x%x\n",
			hdr10_plus_process_mode[i]);
	}

	pr_info("----HDR other info----\n");
	pr_info("customer_master_display_en:0x%x\n", customer_master_display_en);
	pr_info("hdr_flag:0x%x, fg_vf_sw_dbg:0x%x\n",
		hdr_flag, fg_vf_sw_dbg);

	pr_info("knee_lut_on:0x%x,knee_interpolation_mode:0x%x,cur_knee_factor:0x%x\n",
		knee_lut_on, knee_interpolation_mode, cur_knee_factor);

	pr_info("tx_hdr10_plus_support = 0x%x\n", tx_hdr10_plus_support);

	//if (signal_transfer_characteristic == 0x30)
	if (cur_csc_type[0] >= VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC)
		hdr10_plus_debug(cur_csc_type[0]);

	if ((receiver_hdr_info.hdr_support & 0xc) == 0)
		goto dbg_end;
	pr_info("----TV EDID info----\n");
	pr_info("hdr_support:0x%x, lumi_max:%d, lumi_avg:%d, lumi_min:%d\n",
		receiver_hdr_info.hdr_support,
		receiver_hdr_info.lumi_max,
		receiver_hdr_info.lumi_avg,
		receiver_hdr_info.lumi_min);

	pr_info("----Tx HDR package info----\n");
	pr_info("\tfeatures = 0x%08x\n", dbg_hdr_send.features);
	for (i = 0; i < 3; i++)
		for (j = 0; j < 2; j++)
			pr_info("\tprimaries[%1d][%1d] = %04x\n",
				i, j,
				dbg_hdr_send.primaries[i][j]);
	pr_info("\twhite_point = (%04x, %04x)\n",
		dbg_hdr_send.white_point[0],
		dbg_hdr_send.white_point[1]);
	pr_info("\tmax,min luminance = %08x, %08x\n",
		dbg_hdr_send.luminance[0], dbg_hdr_send.luminance[1]);

	goto dbg_end;

	/************************dump reg start***************************/
reg_dump:

	/* osd matrix, VPP_MATRIX_0 */
	pr_info("----dump regs VPP_MATRIX_OSD----\n");
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_PRE_OFFSET0_1,
		READ_VPP_REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1));
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_PRE_OFFSET2,
		READ_VPP_REG(VIU_OSD1_MATRIX_PRE_OFFSET2));
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_COEF00_01,
		READ_VPP_REG(VIU_OSD1_MATRIX_COEF00_01));
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_COEF02_10,
		READ_VPP_REG(VIU_OSD1_MATRIX_COEF02_10));
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_COEF11_12,
		READ_VPP_REG(VIU_OSD1_MATRIX_COEF11_12));
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_COEF20_21,
		READ_VPP_REG(VIU_OSD1_MATRIX_COEF20_21));

	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_COEF22_30,
		READ_VPP_REG(VIU_OSD1_MATRIX_COEF22_30));
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_COEF31_32,
		READ_VPP_REG(VIU_OSD1_MATRIX_COEF31_32));
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_COEF40_41,
		READ_VPP_REG(VIU_OSD1_MATRIX_COEF40_41));
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_COLMOD_COEF42,
		READ_VPP_REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_COEF22_30,
		READ_VPP_REG(VIU_OSD1_MATRIX_COEF22_30));

	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_OFFSET0_1,
		READ_VPP_REG(VIU_OSD1_MATRIX_OFFSET0_1));
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_OFFSET2,
		READ_VPP_REG(VIU_OSD1_MATRIX_OFFSET2));
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_COLMOD_COEF42,
		READ_VPP_REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_COLMOD_COEF42,
		READ_VPP_REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_PRE_OFFSET0_1,
		READ_VPP_REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1));
	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_MATRIX_CTRL,
		READ_VPP_REG(VIU_OSD1_MATRIX_CTRL));

	/* osd eotf matrix, VPP_MATRIX_OSD_EOTF */
	pr_info("----dump regs VPP_MATRIX_OSD_EOTF----\n");

	for (i = 0; i < 5; i++)
		pr_info("\taddr = %08x, val = %08x\n",
			(VIU_OSD1_EOTF_CTL + i + 1),
			READ_VPP_REG(VIU_OSD1_EOTF_CTL + i + 1));

	pr_info("\taddr = %08x, val = %08x\n",
		VIU_OSD1_EOTF_CTL,
		READ_VPP_REG(VIU_OSD1_EOTF_CTL));

	{
		unsigned short *r_map;
		unsigned short *g_map;
		unsigned short *b_map;
		unsigned int addr_port;
		unsigned int data_port;
		unsigned int ctrl_port;
		unsigned int data;
		int i;

		r_map = kmalloc(sizeof(unsigned short) *
			VIDEO_OETF_LUT_SIZE * 3, GFP_ATOMIC);
		if (!r_map)
			return 0;
		g_map = &r_map[VIDEO_OETF_LUT_SIZE];
		b_map = &r_map[VIDEO_OETF_LUT_SIZE * 2];

		pr_info("----dump regs VPP_LUT_OSD_OETF----\n");

		addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
		data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
		ctrl_port = VIU_OSD1_OETF_CTL;

		pr_info("\taddr = %08x, val = %08x\n",
			ctrl_port, READ_VPP_REG(ctrl_port));

		for (i = 0; i < 20; i++) {
			WRITE_VPP_REG(addr_port, i);
			data = READ_VPP_REG(data_port);
			r_map[i * 2] = data & 0xffff;
			r_map[i * 2 + 1] = (data >> 16) & 0xffff;
		}
		WRITE_VPP_REG(addr_port, 20);
		data = READ_VPP_REG(data_port);
		r_map[OSD_OETF_LUT_SIZE - 1] = data & 0xffff;
		g_map[0] = (data >> 16) & 0xffff;
		for (i = 0; i < 20; i++) {
			WRITE_VPP_REG(addr_port, 21 + i);
			data = READ_VPP_REG(data_port);
			g_map[i * 2 + 1] = data & 0xffff;
			g_map[i * 2 + 2] = (data >> 16) & 0xffff;
		}
		for (i = 0; i < 20; i++) {
			WRITE_VPP_REG(addr_port, 41 + i);
			data = READ_VPP_REG(data_port);
			b_map[i * 2] = data & 0xffff;
			b_map[i * 2 + 1] = (data >> 16) & 0xffff;
		}
		WRITE_VPP_REG(addr_port, 61);
		data = READ_VPP_REG(data_port);
		b_map[OSD_OETF_LUT_SIZE - 1] = data & 0xffff;

		for (i = 0; i < OSD_OETF_LUT_SIZE; i++) {
			pr_info("\t[%d] = 0x%04x 0x%04x 0x%04x\n",
				i, r_map[i], g_map[i], b_map[i]);
		}

		addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
		data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
		ctrl_port = VIU_OSD1_EOTF_CTL;
		pr_info("----dump regs VPP_LUT_OSD_EOTF----\n");
		WRITE_VPP_REG(addr_port, 0);
		for (i = 0; i < 16; i++) {
			data = READ_VPP_REG(data_port);
			r_map[i * 2] = data & 0xffff;
			r_map[i * 2 + 1] = (data >> 16) & 0xffff;
		}
		data = READ_VPP_REG(data_port);
		r_map[EOTF_LUT_SIZE - 1] = data & 0xffff;
		g_map[0] = (data >> 16) & 0xffff;
		for (i = 0; i < 16; i++) {
			data = READ_VPP_REG(data_port);
			g_map[i * 2 + 1] = data & 0xffff;
			g_map[i * 2 + 2] = (data >> 16) & 0xffff;
		}
		for (i = 0; i < 16; i++) {
			data = READ_VPP_REG(data_port);
			b_map[i * 2] = data & 0xffff;
			b_map[i * 2 + 1] = (data >> 16) & 0xffff;
		}
		data = READ_VPP_REG(data_port);
		b_map[EOTF_LUT_SIZE - 1] = data & 0xffff;

		for (i = 0; i < EOTF_LUT_SIZE; i++) {
			pr_info("\t[%d] = 0x%04x 0x%04x 0x%04x\n",
				i, r_map[i], g_map[i], b_map[i]);
		}

		pr_info("----dump hdr_osd_reg structure ----\n");

		pr_info("\tviu_osd1_matrix_ctrl = 0x%04x\n",
			hdr_osd_reg.viu_osd1_matrix_ctrl);
		pr_info("\tviu_osd1_matrix_coef00_01 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_matrix_coef00_01);
		pr_info("\tviu_osd1_matrix_coef02_10 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_matrix_coef02_10);
		pr_info("\tviu_osd1_matrix_coef11_12 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_matrix_coef11_12);
		pr_info("\tviu_osd1_matrix_coef20_21 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_matrix_coef20_21);
		pr_info("\tviu_osd1_matrix_colmod_coef42 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_matrix_colmod_coef42);
		pr_info("\tviu_osd1_matrix_offset0_1 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_matrix_offset0_1);
		pr_info("\tviu_osd1_matrix_offset2 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_matrix_offset2);
		pr_info("\tviu_osd1_matrix_pre_offset0_1 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_matrix_pre_offset0_1);
		pr_info("\tviu_osd1_matrix_pre_offset2 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_matrix_pre_offset2);
		pr_info("\tviu_osd1_matrix_coef22_30 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_matrix_coef22_30);
		pr_info("\tviu_osd1_matrix_coef31_32 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_matrix_coef31_32);
		pr_info("\tviu_osd1_matrix_coef40_41 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_matrix_coef40_41);
		pr_info("\tviu_osd1_eotf_ctl = 0x%04x\n",
			hdr_osd_reg.viu_osd1_eotf_ctl);
		pr_info("\tviu_osd1_eotf_coef00_01 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_eotf_coef00_01);
		pr_info("\tviu_osd1_eotf_coef02_10 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_eotf_coef02_10);
		pr_info("\tviu_osd1_eotf_coef11_12 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_eotf_coef11_12);
		pr_info("\tviu_osd1_eotf_coef20_21 = 0x%04x\n",
			hdr_osd_reg.viu_osd1_eotf_coef20_21);
		pr_info("\tviu_osd1_eotf_coef22_rs = 0x%04x\n",
			hdr_osd_reg.viu_osd1_eotf_coef22_rs);
		pr_info("\tviu_osd1_oetf_ctl = 0x%04x\n",
			hdr_osd_reg.viu_osd1_oetf_ctl);

		for (i = 0; i < EOTF_LUT_SIZE; i++) {
			pr_info("\t[%d] = 0x%04x 0x%04x 0x%04x\n",
				i,
				hdr_osd_reg.lut_val.r_map[i],
				hdr_osd_reg.lut_val.g_map[i],
				hdr_osd_reg.lut_val.b_map[i]);
		}
		for (i = 0; i < OSD_OETF_LUT_SIZE; i++) {
			pr_info("\t[%d] = 0x%04x 0x%04x 0x%04x\n",
				i,
				hdr_osd_reg.lut_val.or_map[i],
				hdr_osd_reg.lut_val.og_map[i],
				hdr_osd_reg.lut_val.ob_map[i]);
		}
		pr_info("\n");
		kfree(r_map);
	}
	pr_info("----dump regs VPP_LUT_EOTF----\n");
	print_vpp_lut(VPP_LUT_EOTF, READ_VPP_REG(VIU_EOTF_CTL) & (7 << 27));
	pr_info("----dump regs VPP_LUT_OETF----\n");
	print_vpp_lut(VPP_LUT_OETF, READ_VPP_REG(XVYCC_LUT_CTL) & 0x70);
	/*********************dump reg end*********************/
dbg_end:

	return 0;
}
#endif
